From 7042680a0a93f1dfad4dda3d1e8b944615c826c6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Dec 2017 14:42:30 -0800 Subject: [PATCH 0001/1504] Fixed usage of a partition pointing to a file instead of a folder --- CHANGES.md | 3 ++- src/vfs.rs | 7 ++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 34493b28..5749f081 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,8 @@ # Rojo Change Log ## Current Master -* *No changes* +* Fixed server when using a file as a partition + * Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory! ## 0.2.3 * Plugin only release diff --git a/src/vfs.rs b/src/vfs.rs index 7a709b14..44b9165f 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -62,7 +62,12 @@ impl Vfs { None => return None, }; - let full_path = { + // It's possible that the partition points to a file if `rest` is empty. + // Joining "" onto a path will put a trailing slash on, which causes + // file reads to fail. + let full_path = if rest.is_empty() { + partition.clone() + } else { let joined = rest.join("/"); let relative = Path::new(&joined); From 37bb0d1aa9c2e7fa0d4b0be920ec685e038b7d66 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Dec 2017 14:48:02 -0800 Subject: [PATCH 0002/1504] Add Travis-CI configuration to start running tests --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..3a5c36c8 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: rust +rust: + - stable + - beta + - nightly +matrix: + allow_failures: + - rust: nightly +cache: cargo \ No newline at end of file From 4ff9033916f03f4a4b8c62f993f04890a2c6a862 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Dec 2017 15:47:18 -0800 Subject: [PATCH 0003/1504] Update dependencies --- Cargo.lock | 104 ++++++++++++++++++++++++++--------------------------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88997cd6..c448488c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,16 +1,3 @@ -[root] -name = "rojo" -version = "0.2.0" -dependencies = [ - "clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", - "rouille 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "aho-corasick" version = "0.5.3" @@ -35,7 +22,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -61,7 +48,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -70,7 +57,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "brotli-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -98,7 +85,7 @@ name = "chrono" version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -109,7 +96,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clap" -version = "2.28.0" +version = "2.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -198,7 +185,7 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -207,7 +194,7 @@ name = "flate2" version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -218,7 +205,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -226,7 +213,7 @@ name = "fsevent-sys" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -265,7 +252,7 @@ name = "inotify" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -284,7 +271,7 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.33" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -302,7 +289,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -330,7 +317,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -339,7 +326,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", @@ -382,7 +369,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -393,7 +380,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -407,7 +394,7 @@ dependencies = [ "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -415,12 +402,12 @@ dependencies = [ [[package]] name = "num" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -428,7 +415,7 @@ name = "num-integer" version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -437,12 +424,12 @@ version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -495,7 +482,7 @@ version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -528,6 +515,19 @@ name = "regex-syntax" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rojo" +version = "0.2.0" +dependencies = [ + "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rouille 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rouille" version = "1.0.3" @@ -566,17 +566,17 @@ name = "serde" version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -595,13 +595,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -664,7 +664,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -683,7 +683,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -700,7 +700,7 @@ version = "0.1.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -824,7 +824,7 @@ dependencies = [ "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" -"checksum clap 2.28.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dc34bf7d5d66268b466b9852bca925ec1d2650654dab4da081e63fd230145c2e" +"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" @@ -845,7 +845,7 @@ dependencies = [ "checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2" +"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" @@ -858,10 +858,10 @@ dependencies = [ "checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" "checksum nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfb3ddedaa14746434a02041940495bf11325c22f6d36125d3bdd56090d50a79" "checksum notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5c3812da3098f210a0bb440f9c008471a031aa4c1de07a264fdd75456c95a4eb" -"checksum num 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "a311b77ebdc5dd4cf6449d81e4135d9f0e3b153839ac90e648a8ef538f923525" +"checksum num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4083e14b542ea3eb9b5f33ff48bd373a92d78687e74f4cc0a30caeb754f0ca" "checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba" "checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01" -"checksum num-traits 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "99843c856d68d8b4313b03a17e33c4bb42ae8f6610ea81b28abe076ac721b9b0" +"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" "checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" @@ -877,10 +877,10 @@ dependencies = [ "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum same-file 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70a18720d745fb9ca6a041b37cb36d0b21066006b6cff8b5b360142d4b81fb60" "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" -"checksum serde 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6eda663e865517ee783b0891a3f6eb3a253e0b0dabb46418969ee9635beadd9e" -"checksum serde_derive 1.0.21 (registry+https://github.com/rust-lang/crates.io-index)" = "652bc323d694dc925829725ec6c890156d8e70ae5202919869cb00fe2eff3788" +"checksum serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7c37d7f192f00041e8a613e936717923a71bc0c9051fc4425a49b104140f05" +"checksum serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "0672de7300b02bac3f3689f8faea813c4a1ea9fe0cb49e80f714231d267518a2" "checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab" -"checksum serde_json 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e4586746d1974a030c48919731ecffd0ed28d0c40749d0d18d43b3a7d6c9b20e" +"checksum serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ea28ea0cca944668919bec6af209864a8dfe769fd2b0b723f36b22e20c1bf69f" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" From 1ad20421e9b5f0a5ff0ec70e4753126003a0f5b9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Dec 2017 15:50:55 -0800 Subject: [PATCH 0004/1504] Move Windows-specific path test into its own file --- src/pathext.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/pathext.rs b/src/pathext.rs index b6a6f30b..1fd49a80 100644 --- a/src/pathext.rs +++ b/src/pathext.rs @@ -33,6 +33,15 @@ fn test_path_to_route() { t(Path::new("/a/b/c"), Path::new("/a/b/c/d"), Some(vec!["d".to_string()])); t(Path::new("/a/b"), Path::new("a"), None); +} + +#[test] +#[cfg(target_os = "windows")] +fn test_path_to_route_windows() { + fn t(root: &Path, value: &Path, result: Option>) { + assert_eq!(path_to_route(root, value), result); + } + t(Path::new("C:\\foo"), Path::new("C:\\foo\\bar\\baz"), Some(vec!["bar".to_string(), "baz".to_string()])); } From 5898780e8eeb1bb30f9a7bd5ee4ab4d566ecdcb4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Dec 2017 15:52:24 -0800 Subject: [PATCH 0005/1504] Add note about testing to CHANGES --- CHANGES.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 5749f081..2e433a77 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,9 @@ ## Current Master * Fixed server when using a file as a partition * Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory! +* Started running automatic tests on Travis CI + * This is only for the server right now + * Soon, I'll upgrade [Lemur](http://github.com/LPGhatguy/Lemur) to have APIs necessary for testing plugins and start testing the plugion portion of Rojo as well. ## 0.2.3 * Plugin only release From 9fd6799f935b3d7f65f6f8962d783d98b62328de Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Dec 2017 15:53:45 -0800 Subject: [PATCH 0006/1504] Fix Travis-CI README link --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index dd0ac9ab..7c596afc 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

Rojo

From 23d4f45ac948726bdd807fdc78c09b980729ced4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Dec 2017 16:56:20 -0800 Subject: [PATCH 0007/1504] Fix use of services as partition targets --- CHANGES.md | 5 ++++- plugin/src/Reconciler.lua | 9 +++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 2e433a77..29565cd6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,9 +1,12 @@ # Rojo Change Log ## Current Master +* Fixed using a service as the target of a partition (part of #11) + * There are still cases that will trigger errors, like putting an `init.lua` file inside of a service. + * **Note that the contents of the service will be synced with the filesystem, so any existing items will be deleted!** * Fixed server when using a file as a partition * Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory! -* Started running automatic tests on Travis CI +* Started running automatic tests on Travis CI (#9) * This is only for the server right now * Soon, I'll upgrade [Lemur](http://github.com/LPGhatguy/Lemur) to have APIs necessary for testing plugins and start testing the plugion portion of Rojo as well. diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 38176aa9..062f0dee 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -171,8 +171,13 @@ function Reconciler.reconcile(rbx, item, fileName, parent) end else if rbx.ClassName ~= "Folder" then - rbx:Destroy() - return Reconciler._reify(item, fileName, parent) + -- Certain objects (services) can't be destroyed. + -- If we target one of these, leave it alone! + local ok = pcall(rbx.Destroy, rbx) + + if ok then + return Reconciler._reify(item, fileName, parent) + end end end From 97682108aa52fe36238f09548909426ea5563677 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Dec 2017 17:29:00 -0800 Subject: [PATCH 0008/1504] Update git module paths, still fighting git submodules a bit --- .gitmodules | 27 +++++++++++++++------------ modules/Roact | 1 - modules/RoactRodux | 1 - modules/Rodux | 1 - modules/TestEZ | 1 - 5 files changed, 15 insertions(+), 16 deletions(-) delete mode 160000 modules/Roact delete mode 160000 modules/RoactRodux delete mode 160000 modules/Rodux delete mode 160000 modules/TestEZ diff --git a/.gitmodules b/.gitmodules index b801911f..f181740d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,15 @@ -[submodule "modules/Roact"] - path = modules/Roact - url = https://github.com/Roblox/Roact.git -[submodule "modules/Rodux"] - path = modules/Rodux - url = https://github.com/Roblox/Rodux.git -[submodule "modules/RoactRodux"] - path = modules/RoactRodux - url = https://github.com/Roblox/RoactRodux.git -[submodule "modules/TestEZ"] - path = modules/TestEZ - url = https://github.com/Roblox/TestEZ.git +[submodule "modules/roact"] + path = modules/roact + url = https://github.com/Roblox/roact.git +[submodule "modules/rodux"] + path = modules/rodux + url = https://github.com/Roblox/rodux.git +[submodule "modules/roact-rodux"] + path = modules/roact-rodux + url = https://github.com/Roblox/roact-rodux.git +[submodule "modules/testez"] + path = modules/testez + url = https://github.com/Roblox/testez.git +[submodule "modules/lemur"] + path = modules/lemur + url = https://github.com/LPGhatguy/lemur.git diff --git a/modules/Roact b/modules/Roact deleted file mode 160000 index 7cce62b1..00000000 --- a/modules/Roact +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7cce62b13051dd11bfab8a1fb7231f10156c5f20 diff --git a/modules/RoactRodux b/modules/RoactRodux deleted file mode 160000 index 43c4f347..00000000 --- a/modules/RoactRodux +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 43c4f347fe26cfc6cccbef99ed35d9ccef221c97 diff --git a/modules/Rodux b/modules/Rodux deleted file mode 160000 index 6c573259..00000000 --- a/modules/Rodux +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6c573259abbcfec78413d9486d5fb373ebc5261b diff --git a/modules/TestEZ b/modules/TestEZ deleted file mode 160000 index 9945f562..00000000 --- a/modules/TestEZ +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9945f562e529952057da801e19a024c7362d68f0 From fe4678fdc569f374eb7610e40dd124da70c08a71 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Dec 2017 17:36:06 -0800 Subject: [PATCH 0009/1504] Re-add dependencies with their new path --- modules/lemur | 1 + modules/roact | 1 + modules/roact-rodux | 1 + modules/rodux | 1 + modules/testez | 1 + 5 files changed, 5 insertions(+) create mode 160000 modules/lemur create mode 160000 modules/roact create mode 160000 modules/roact-rodux create mode 160000 modules/rodux create mode 160000 modules/testez diff --git a/modules/lemur b/modules/lemur new file mode 160000 index 00000000..67558cbd --- /dev/null +++ b/modules/lemur @@ -0,0 +1 @@ +Subproject commit 67558cbd7b06c9b2a1448f160d4b4520b2c0253d diff --git a/modules/roact b/modules/roact new file mode 160000 index 00000000..8eaabac5 --- /dev/null +++ b/modules/roact @@ -0,0 +1 @@ +Subproject commit 8eaabac5c1e03c9f6a389c4c0b8b808b8e9ee90e diff --git a/modules/roact-rodux b/modules/roact-rodux new file mode 160000 index 00000000..57f3fc62 --- /dev/null +++ b/modules/roact-rodux @@ -0,0 +1 @@ +Subproject commit 57f3fc62207827baf11af40359c04492a35c8fed diff --git a/modules/rodux b/modules/rodux new file mode 160000 index 00000000..6e1dcc9c --- /dev/null +++ b/modules/rodux @@ -0,0 +1 @@ +Subproject commit 6e1dcc9c4d56c9d13e20a568fe632ee965d730e7 diff --git a/modules/testez b/modules/testez new file mode 160000 index 00000000..3c421758 --- /dev/null +++ b/modules/testez @@ -0,0 +1 @@ +Subproject commit 3c42175897f7133d10fdc269c040df98a55906d6 From 4dc705ee45d7ba70854e224ef1323edfbd83761d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Dec 2017 17:36:47 -0800 Subject: [PATCH 0010/1504] Update Rojo project paths to point to new dependencies --- rojo.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/rojo.json b/rojo.json index 0ecdbc24..821517a3 100644 --- a/rojo.json +++ b/rojo.json @@ -6,20 +6,20 @@ "path": "plugin/src", "target": "ReplicatedStorage.Rojo" }, - "modules/Roact": { - "path": "modules/Roact/lib", + "modules/roact": { + "path": "modules/roact/lib", "target": "ReplicatedStorage.Rojo.modules.Roact" }, - "modules/Rodux": { - "path": "modules/Rodux/lib", + "modules/rodux": { + "path": "modules/rodux/lib", "target": "ReplicatedStorage.Rojo.modules.Rodux" }, - "modules/RoactRodux": { - "path": "modules/RoactRodux/lib", + "modules/roact-rodux": { + "path": "modules/roact-rodux/lib", "target": "ReplicatedStorage.Rojo.modules.RoactRodux" }, - "modules/TestEZ": { - "path": "modules/TestEZ/lib", + "modules/testez": { + "path": "modules/testez/lib", "target": "ReplicatedStorage.TestEZ" } } From 713a1994193e18bc83fd2232a4b6a1936f6c7941 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Dec 2017 18:08:03 -0800 Subject: [PATCH 0011/1504] Add spec.lua for testing -- Promise tests are currently broken --- spec.lua | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 spec.lua diff --git a/spec.lua b/spec.lua new file mode 100644 index 00000000..dd0edde0 --- /dev/null +++ b/spec.lua @@ -0,0 +1,69 @@ +--[[ + Loads our library and all of its dependencies, then runs tests using TestEZ. +]] + +-- If you add any dependencies, add them to this table so they'll be loaded! +local LOAD_MODULES = { + {"plugin/src", "Plugin"}, + {"modules/testez/lib", "TestEZ"}, +} + +-- This makes sure we can load Lemur and other libraries that depend on init.lua +package.path = package.path .. ";?/init.lua" + +-- If this fails, make sure you've run `lua bin/install-dependencies.lua` first! +local lemur = require("modules.lemur") + +--[[ + Collapses ModuleScripts named 'init' into their parent folders. + + This is the same result as the collapsing mechanism from Rojo. +]] +local function collapse(root) + local init = root:FindFirstChild("init") + if init then + init.Name = root.Name + init.Parent = root.Parent + + for _, child in ipairs(root:GetChildren()) do + child.Parent = init + end + + root:Destroy() + root = init + end + + for _, child in ipairs(root:GetChildren()) do + if child:IsA("Folder") then + collapse(child) + end + end + + return root +end + +-- Create a virtual Roblox tree +local habitat = lemur.Habitat.new() + +-- We'll put all of our library code and dependencies here +local Root = lemur.Instance.new("Folder") +Root.Name = "Root" + +-- Load all of the modules specified above +for _, module in ipairs(LOAD_MODULES) do + local container = lemur.Instance.new("Folder", Root) + container.Name = module[2] + habitat:loadFromFs(module[1], container) +end + +collapse(Root) + +-- Load TestEZ and run our tests +local TestEZ = habitat:require(Root.TestEZ) + +local results = TestEZ.TestBootstrap:run(Root.Plugin, TestEZ.Reporters.TextReporter) + +-- Did something go wrong? +if results.failureCount > 0 then + os.exit(1) +end From 23ae0bc18629443ef86545a08e7393bea37f064d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Dec 2017 11:34:22 -0800 Subject: [PATCH 0012/1504] Wrap warning earlier in Promise --- plugin/src/Promise.lua | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugin/src/Promise.lua b/plugin/src/Promise.lua index 12c82344..cdcea791 100644 --- a/plugin/src/Promise.lua +++ b/plugin/src/Promise.lua @@ -242,7 +242,10 @@ function Promise:_resolve(...) if Promise.is((...)) then -- Without this warning, arguments sometimes mysteriously disappear if select("#", ...) > 1 then - local message = ("When returning a Promise from andThen, extra arguments are discarded! See:\n\n%s"):format( + local message = ( + "When returning a Promise from andThen, extra arguments are " .. + "discarded! See:\n\n%s" + ):format( self._source ) warn(message) From 551f75f39cf8d8651436ff15c690a0daadc1c56b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Dec 2017 13:59:36 -0800 Subject: [PATCH 0013/1504] Implement Lua unit tests, this may fail --- .travis.yml | 43 +++++++++++++++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3a5c36c8..e4917928 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,9 +1,36 @@ -language: rust -rust: - - stable - - beta - - nightly matrix: - allow_failures: - - rust: nightly -cache: cargo \ No newline at end of file + include: + - language: rust + rust: + - stable + - beta + - nightly + matrix: + allow_failures: + - rust: nightly + cache: cargo + + # http://kiki.to/blog/2016/02/04/talk-continuous-integration-with-lua/ + - language: python + env: + - LUA="lua=5.1" + + before_install: + - pip install hererocks + - hererocks lua_install -r^ --$LUA + - export PATH=$PATH:$PWD/lua_install/bin + + install: + - luarocks install luafilesystem + - luarocks install busted + - luarocks install luacov + - luarocks install luacov-coveralls + - luarocks install luacheck + - git submodule update --init --recursive + + script: + - cd plugin && luacheck . + - lua -lluacov spec.lua + + after_success: + - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install \ No newline at end of file From dd16cadb4c61b059d8ef7266ca25d54455dd18dd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Dec 2017 14:01:09 -0800 Subject: [PATCH 0014/1504] Fix indentation, yaml is mean --- .travis.yml | 58 ++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/.travis.yml b/.travis.yml index e4917928..e932c52d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,36 +1,36 @@ matrix: include: - - language: rust - rust: - - stable - - beta - - nightly - matrix: - allow_failures: - - rust: nightly - cache: cargo + - language: rust + rust: + - stable + - beta + - nightly + matrix: + allow_failures: + - rust: nightly + cache: cargo - # http://kiki.to/blog/2016/02/04/talk-continuous-integration-with-lua/ - - language: python - env: - - LUA="lua=5.1" + # http://kiki.to/blog/2016/02/04/talk-continuous-integration-with-lua/ + - language: python + env: + - LUA="lua=5.1" - before_install: - - pip install hererocks - - hererocks lua_install -r^ --$LUA - - export PATH=$PATH:$PWD/lua_install/bin + before_install: + - pip install hererocks + - hererocks lua_install -r^ --$LUA + - export PATH=$PATH:$PWD/lua_install/bin - install: - - luarocks install luafilesystem - - luarocks install busted - - luarocks install luacov - - luarocks install luacov-coveralls - - luarocks install luacheck - - git submodule update --init --recursive + install: + - luarocks install luafilesystem + - luarocks install busted + - luarocks install luacov + - luarocks install luacov-coveralls + - luarocks install luacheck + - git submodule update --init --recursive - script: - - cd plugin && luacheck . - - lua -lluacov spec.lua + script: + - cd plugin && luacheck . + - lua -lluacov spec.lua - after_success: - - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install \ No newline at end of file + after_success: + - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install \ No newline at end of file From 059ff1777bd985e8647ac3196b68cae2d83d5392 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Dec 2017 14:23:37 -0800 Subject: [PATCH 0015/1504] Try some random fixes I saw on StackOverflow to work around Travis-CI bug --- .travis.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index e932c52d..e3de44cf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,15 @@ +language: python +env: + - LUA="lua=5.1" + +matrix: + allow_failures: + + matrix: include: - language: rust - rust: - - stable - - beta - - nightly + rust:\n- stable\n- beta\n -nightly matrix: allow_failures: - rust: nightly @@ -26,10 +31,9 @@ matrix: - luarocks install luacov - luarocks install luacov-coveralls - luarocks install luacheck - - git submodule update --init --recursive script: - - cd plugin && luacheck . + - cd plugin && luacheck . && cd .. - lua -lluacov spec.lua after_success: From 68b3d566196781f2f321f84e3c2ab2b1988a4c44 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Dec 2017 14:23:58 -0800 Subject: [PATCH 0016/1504] Remove extra stuff I accidentally added :D --- .travis.yml | 8 -------- 1 file changed, 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index e3de44cf..c9787ea5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,11 +1,3 @@ -language: python -env: - - LUA="lua=5.1" - -matrix: - allow_failures: - - matrix: include: - language: rust From fd7e737c202a6c4935ea9c0f27997d040e04a5de Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Dec 2017 14:26:29 -0800 Subject: [PATCH 0017/1504] Put back the original Rust config, maybe this will work --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c9787ea5..764b79c4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,10 @@ matrix: include: - language: rust - rust:\n- stable\n- beta\n -nightly + rust: + - stable + - beta + - nightly matrix: allow_failures: - rust: nightly From 7995b6eca4f6462377462f80ad6505d4130aaf18 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Dec 2017 15:39:17 -0800 Subject: [PATCH 0018/1504] Try radically changing the Travis script --- .travis.yml | 51 +++++++++++++++++++++------------------------------ 1 file changed, 21 insertions(+), 30 deletions(-) diff --git a/.travis.yml b/.travis.yml index 764b79c4..2eaef4d2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,35 +1,26 @@ -matrix: - include: - - language: rust - rust: - - stable - - beta - - nightly - matrix: - allow_failures: - - rust: nightly - cache: cargo +language: python - # http://kiki.to/blog/2016/02/04/talk-continuous-integration-with-lua/ - - language: python - env: - - LUA="lua=5.1" +env: + - RUST="stable" LUA="lua=5.1" + - RUST="beta" LUA="lua=5.1" - before_install: - - pip install hererocks - - hererocks lua_install -r^ --$LUA - - export PATH=$PATH:$PWD/lua_install/bin +before_install: + - pip install hererocks + - hererocks lua_install -r^ --$LUA + - export PATH=$PATH:$PWD/lua_install/bin + - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $RUST - install: - - luarocks install luafilesystem - - luarocks install busted - - luarocks install luacov - - luarocks install luacov-coveralls - - luarocks install luacheck +install: + - luarocks install luafilesystem + - luarocks install busted + - luarocks install luacov + - luarocks install luacov-coveralls + - luarocks install luacheck - script: - - cd plugin && luacheck . && cd .. - - lua -lluacov spec.lua +script: + - cd plugin && luacheck . && cd .. + - lua -lluacov spec.lua + - cargo test --verbose - after_success: - - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install \ No newline at end of file +after_success: + - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install \ No newline at end of file From 302c6cf6631a9119dced4befbcfbeb2bfd25f9b9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Dec 2017 15:42:56 -0800 Subject: [PATCH 0019/1504] Hybrid build script between Travis and custom installation... --- .travis.yml | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2eaef4d2..431c6c61 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,14 +1,16 @@ -language: python +language: rust + +rust: + - stable + - beta env: - - RUST="stable" LUA="lua=5.1" - - RUST="beta" LUA="lua=5.1" + - LUA="lua=5.1" before_install: - pip install hererocks - hererocks lua_install -r^ --$LUA - export PATH=$PATH:$PWD/lua_install/bin - - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $RUST install: - luarocks install luafilesystem From f88cb67210613dfd7dbc5fc32a6a7a92dc7dff7b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Dec 2017 15:46:50 -0800 Subject: [PATCH 0020/1504] Back to being custom, since the 'Rust' image has a really old Python version --- .travis.yml | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 431c6c61..c24c36df 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,14 @@ -language: rust - -rust: - - stable - - beta +language: python env: - - LUA="lua=5.1" + - RUST="stable" LUA="lua=5.1" + - RUST="beta" LUA="lua=5.1" before_install: - pip install hererocks - hererocks lua_install -r^ --$LUA - - export PATH=$PATH:$PWD/lua_install/bin + - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $RUST + - export PATH=$PATH:$PWD/lua_install/bin:$HOME/.cargo/bin install: - luarocks install luafilesystem From edd45ca02e38a11097a22b196d0c135e9122a0d6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Dec 2017 15:53:25 -0800 Subject: [PATCH 0021/1504] Update to Lemur master, 'fixes' Promise tests --- modules/lemur | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/lemur b/modules/lemur index 67558cbd..c7b1cc33 160000 --- a/modules/lemur +++ b/modules/lemur @@ -1 +1 @@ -Subproject commit 67558cbd7b06c9b2a1448f160d4b4520b2c0253d +Subproject commit c7b1cc335d3a77be1e45e8c0208c1a384b6e57d6 From c9a53debc393f4a22a08a0bb85689008f7e891e1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Dec 2017 16:32:32 -0800 Subject: [PATCH 0022/1504] Add small config test --- plugin/src/Config.spec.lua | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 plugin/src/Config.spec.lua diff --git a/plugin/src/Config.spec.lua b/plugin/src/Config.spec.lua new file mode 100644 index 00000000..ce9b43fd --- /dev/null +++ b/plugin/src/Config.spec.lua @@ -0,0 +1,7 @@ +return function() + local Config = require(script.Parent.Config) + + it("should have 'dev' disabled", function() + expect(Config.dev).to.equal(false) + end) +end From d5b41e2bd4dd2d2d0822f5bf7c9a953874d9459c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Dec 2017 16:50:30 -0800 Subject: [PATCH 0023/1504] Remove plugin source, moved to rojo-plugin --- .editorconfig | 5 - .gitmodules | 15 -- .travis.yml | 29 +--- modules/lemur | 1 - modules/roact | 1 - modules/roact-rodux | 1 - modules/rodux | 1 - modules/testez | 1 - plugin/.luacheckrc | 56 ------- plugin/src/Config.lua | 5 - plugin/src/Config.spec.lua | 7 - plugin/src/Http.lua | 67 -------- plugin/src/HttpError.lua | 57 ------- plugin/src/HttpResponse.lua | 20 --- plugin/src/Main.server.lua | 42 ----- plugin/src/Plugin.lua | 178 --------------------- plugin/src/Promise.lua | 311 ------------------------------------ plugin/src/Promise.spec.lua | 70 -------- plugin/src/Reconciler.lua | 269 ------------------------------- plugin/src/Server.lua | 69 -------- plugin/src/runTests.lua | 4 - rojo.json | 26 --- spec.lua | 69 -------- 23 files changed, 4 insertions(+), 1300 deletions(-) delete mode 100644 .gitmodules delete mode 160000 modules/lemur delete mode 160000 modules/roact delete mode 160000 modules/roact-rodux delete mode 160000 modules/rodux delete mode 160000 modules/testez delete mode 100644 plugin/.luacheckrc delete mode 100644 plugin/src/Config.lua delete mode 100644 plugin/src/Config.spec.lua delete mode 100644 plugin/src/Http.lua delete mode 100644 plugin/src/HttpError.lua delete mode 100644 plugin/src/HttpResponse.lua delete mode 100644 plugin/src/Main.server.lua delete mode 100644 plugin/src/Plugin.lua delete mode 100644 plugin/src/Promise.lua delete mode 100644 plugin/src/Promise.spec.lua delete mode 100644 plugin/src/Reconciler.lua delete mode 100644 plugin/src/Server.lua delete mode 100644 plugin/src/runTests.lua delete mode 100644 rojo.json delete mode 100644 spec.lua diff --git a/.editorconfig b/.editorconfig index 50456de4..c2c2496b 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,11 +4,6 @@ root = true end_of_line = lf charset = utf-8 -[*.lua] -indent_style = tab -trim_trailing_whitespace = true -insert_final_newline = true - [*.rs] indent_style = space indent_size = 4 diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index f181740d..00000000 --- a/.gitmodules +++ /dev/null @@ -1,15 +0,0 @@ -[submodule "modules/roact"] - path = modules/roact - url = https://github.com/Roblox/roact.git -[submodule "modules/rodux"] - path = modules/rodux - url = https://github.com/Roblox/rodux.git -[submodule "modules/roact-rodux"] - path = modules/roact-rodux - url = https://github.com/Roblox/roact-rodux.git -[submodule "modules/testez"] - path = modules/testez - url = https://github.com/Roblox/testez.git -[submodule "modules/lemur"] - path = modules/lemur - url = https://github.com/LPGhatguy/lemur.git diff --git a/.travis.yml b/.travis.yml index c24c36df..2657bd4d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,26 +1,5 @@ -language: python +language: rust -env: - - RUST="stable" LUA="lua=5.1" - - RUST="beta" LUA="lua=5.1" - -before_install: - - pip install hererocks - - hererocks lua_install -r^ --$LUA - - curl https://sh.rustup.rs -sSf | sh -s -- -y --default-toolchain $RUST - - export PATH=$PATH:$PWD/lua_install/bin:$HOME/.cargo/bin - -install: - - luarocks install luafilesystem - - luarocks install busted - - luarocks install luacov - - luarocks install luacov-coveralls - - luarocks install luacheck - -script: - - cd plugin && luacheck . && cd .. - - lua -lluacov spec.lua - - cargo test --verbose - -after_success: - - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install \ No newline at end of file +rust: + - stable + - beta \ No newline at end of file diff --git a/modules/lemur b/modules/lemur deleted file mode 160000 index c7b1cc33..00000000 --- a/modules/lemur +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c7b1cc335d3a77be1e45e8c0208c1a384b6e57d6 diff --git a/modules/roact b/modules/roact deleted file mode 160000 index 8eaabac5..00000000 --- a/modules/roact +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 8eaabac5c1e03c9f6a389c4c0b8b808b8e9ee90e diff --git a/modules/roact-rodux b/modules/roact-rodux deleted file mode 160000 index 57f3fc62..00000000 --- a/modules/roact-rodux +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 57f3fc62207827baf11af40359c04492a35c8fed diff --git a/modules/rodux b/modules/rodux deleted file mode 160000 index 6e1dcc9c..00000000 --- a/modules/rodux +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 6e1dcc9c4d56c9d13e20a568fe632ee965d730e7 diff --git a/modules/testez b/modules/testez deleted file mode 160000 index 3c421758..00000000 --- a/modules/testez +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 3c42175897f7133d10fdc269c040df98a55906d6 diff --git a/plugin/.luacheckrc b/plugin/.luacheckrc deleted file mode 100644 index bce1d4dd..00000000 --- a/plugin/.luacheckrc +++ /dev/null @@ -1,56 +0,0 @@ -stds.roblox = { - read_globals = { - game = { - other_fields = true, - }, - - -- Roblox globals - "script", - - -- Extra functions - "tick", "warn", "spawn", - "wait", "settings", - - -- Types - "Vector2", "Vector3", - "Color3", - "UDim", "UDim2", - "Rect", - "CFrame", - "Enum", - "Instance", - } -} - -stds.plugin = { - read_globals = { - "plugin", - } -} - -stds.testez = { - read_globals = { - "describe", - "it", "itFOCUS", "itSKIP", - "FOCUS", "SKIP", "HACK_NO_XPCALL", - "expect", - } -} - -ignore = { - "212", -- unused arguments - "421", -- shadowing local variable - "422", -- shadowing argument - "431", -- shadowing upvalue - "432", -- shadowing upvalue argument -} - -std = "lua51+roblox" - -files["**/*.server.lua"] = { - std = "+plugin", -} - -files["**/*.spec.lua"] = { - std = "+testez", -} \ No newline at end of file diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua deleted file mode 100644 index 9e90fd85..00000000 --- a/plugin/src/Config.lua +++ /dev/null @@ -1,5 +0,0 @@ -return { - pollingRate = 0.3, - version = "v0.2.3", - dev = false, -} diff --git a/plugin/src/Config.spec.lua b/plugin/src/Config.spec.lua deleted file mode 100644 index ce9b43fd..00000000 --- a/plugin/src/Config.spec.lua +++ /dev/null @@ -1,7 +0,0 @@ -return function() - local Config = require(script.Parent.Config) - - it("should have 'dev' disabled", function() - expect(Config.dev).to.equal(false) - end) -end diff --git a/plugin/src/Http.lua b/plugin/src/Http.lua deleted file mode 100644 index 98997b9f..00000000 --- a/plugin/src/Http.lua +++ /dev/null @@ -1,67 +0,0 @@ -local HttpService = game:GetService("HttpService") - -local HTTP_DEBUG = false - -local Promise = require(script.Parent.Promise) -local HttpError = require(script.Parent.HttpError) -local HttpResponse = require(script.Parent.HttpResponse) - -local function dprint(...) - if HTTP_DEBUG then - print(...) - end -end - -local Http = {} -Http.__index = Http - -function Http.new(baseUrl) - assert(type(baseUrl) == "string", "Http.new needs a baseUrl!") - - local http = { - baseUrl = baseUrl - } - - setmetatable(http, Http) - - return http -end - -function Http:get(endpoint) - dprint("\nGET", endpoint) - return Promise.new(function(resolve, reject) - spawn(function() - local ok, result = pcall(function() - return HttpService:GetAsync(self.baseUrl .. endpoint, true) - end) - - if ok then - dprint("\t", result, "\n") - resolve(HttpResponse.new(result)) - else - reject(HttpError.fromErrorString(result)) - end - end) - end) -end - -function Http:post(endpoint, body) - dprint("\nPOST", endpoint) - dprint(body) - return Promise.new(function(resolve, reject) - spawn(function() - local ok, result = pcall(function() - return HttpService:PostAsync(self.baseUrl .. endpoint, body) - end) - - if ok then - dprint("\t", result, "\n") - resolve(HttpResponse.new(result)) - else - reject(HttpError.fromErrorString(result)) - end - end) - end) -end - -return Http diff --git a/plugin/src/HttpError.lua b/plugin/src/HttpError.lua deleted file mode 100644 index 9da4b946..00000000 --- a/plugin/src/HttpError.lua +++ /dev/null @@ -1,57 +0,0 @@ -local HttpError = {} -HttpError.__index = HttpError - -HttpError.Error = { - HttpNotEnabled = { - message = "Rojo requires HTTP access, which is not enabled.\n" .. - "Check your game settings, located in the 'Home' tab of Studio.", - }, - ConnectFailed = { - message = "Rojo plugin couldn't connect to the Rojo server.\n" .. - "Make sure the server is running -- use 'Rojo serve' to run it!", - }, - Unknown = { - message = "Rojo encountered an unknown error: {{message}}", - }, -} - -function HttpError.new(type, extraMessage) - extraMessage = extraMessage or "" - local message = type.message:gsub("{{message}}", extraMessage) - - local err = { - type = type, - message = message, - } - - setmetatable(err, HttpError) - - return err -end - -function HttpError:__tostring() - return self.message -end - ---[[ - This method shouldn't have to exist. Ugh. -]] -function HttpError.fromErrorString(err) - err = err:lower() - - if err:find("^http requests are not enabled") then - return HttpError.new(HttpError.Error.HttpNotEnabled) - end - - if err:find("^curl error") then - return HttpError.new(HttpError.Error.ConnectFailed) - end - - return HttpError.new(HttpError.Error.Unknown, err) -end - -function HttpError:report() - warn(self.message) -end - -return HttpError diff --git a/plugin/src/HttpResponse.lua b/plugin/src/HttpResponse.lua deleted file mode 100644 index 0b85db94..00000000 --- a/plugin/src/HttpResponse.lua +++ /dev/null @@ -1,20 +0,0 @@ -local HttpService = game:GetService("HttpService") - -local HttpResponse = {} -HttpResponse.__index = HttpResponse - -function HttpResponse.new(body) - local response = { - body = body, - } - - setmetatable(response, HttpResponse) - - return response -end - -function HttpResponse:json() - return HttpService:JSONDecode(self.body) -end - -return HttpResponse diff --git a/plugin/src/Main.server.lua b/plugin/src/Main.server.lua deleted file mode 100644 index 2d393e8d..00000000 --- a/plugin/src/Main.server.lua +++ /dev/null @@ -1,42 +0,0 @@ -if not plugin then - return -end - -local Plugin = require(script.Parent.Plugin) -local Config = require(script.Parent.Config) - -local function main() - local pluginInstance = Plugin.new() - - local displayedVersion = Config.dev and "DEV" or Config.version - - local toolbar = plugin:CreateToolbar("Rojo Plugin " .. displayedVersion) - - toolbar:CreateButton("Test Connection", "Connect to Rojo Server", "") - .Click:Connect(function() - pluginInstance:connect() - :catch(function(err) - warn(err) - end) - end) - - toolbar:CreateButton("Sync In", "Sync into Roblox Studio", "") - .Click:Connect(function() - pluginInstance:syncIn() - :catch(function(err) - warn(err) - end) - end) - - toolbar:CreateButton("Toggle Polling", "Poll server for changes", "") - .Click:Connect(function() - spawn(function() - pluginInstance:togglePolling() - :catch(function(err) - warn(err) - end) - end) - end) -end - -main() diff --git a/plugin/src/Plugin.lua b/plugin/src/Plugin.lua deleted file mode 100644 index 79d7418d..00000000 --- a/plugin/src/Plugin.lua +++ /dev/null @@ -1,178 +0,0 @@ -local Config = require(script.Parent.Config) -local Http = require(script.Parent.Http) -local Server = require(script.Parent.Server) -local Promise = require(script.Parent.Promise) -local Reconciler = require(script.Parent.Reconciler) - -local function collectMatch(source, pattern) - local result = {} - - for match in source:gmatch(pattern) do - table.insert(result, match) - end - - return result -end - -local Plugin = {} -Plugin.__index = Plugin - -function Plugin.new() - local address = "localhost" - local port = Config.dev and 8001 or 8000 - - local remote = ("http://%s:%d"):format(address, port) - - local foop = { - _http = Http.new(remote), - _server = nil, - _polling = false, - } - - setmetatable(foop, Plugin) - - do - local screenGui = Instance.new("ScreenGui") - screenGui.Name = "Rojo UI" - screenGui.Parent = game.CoreGui - screenGui.DisplayOrder = -1 - screenGui.Enabled = false - - local label = Instance.new("TextLabel") - label.Font = Enum.Font.SourceSans - label.TextSize = 20 - label.Text = "Rojo polling..." - label.BackgroundColor3 = Color3.fromRGB(31, 31, 31) - label.BackgroundTransparency = 0.5 - label.BorderSizePixel = 0 - label.TextColor3 = Color3.new(1, 1, 1) - label.Size = UDim2.new(0, 120, 0, 28) - label.Position = UDim2.new(0, 0, 0, 0) - label.Parent = screenGui - - foop._label = screenGui - end - - return foop -end - -function Plugin:server() - if not self._server then - self._server = Server.connect(self._http) - :catch(function(err) - self._server = nil - return Promise.reject(err) - end) - end - - return self._server -end - -function Plugin:connect() - print("Testing connection...") - - return self:server() - :andThen(function(server) - return server:getInfo() - end) - :andThen(function(result) - print("Server found!") - print("Protocol version:", result.protocolVersion) - print("Server version:", result.serverVersion) - end) -end - -function Plugin:togglePolling() - if self._polling then - self:stopPolling() - - return Promise.resolve(nil) - else - return self:startPolling() - end -end - -function Plugin:stopPolling() - if not self._polling then - return - end - - print("Stopped polling.") - - self._polling = false - self._label.Enabled = false -end - -function Plugin:_pull(server, project, routes) - local items = server:read(routes):await() - - for index = 1, #routes do - local route = routes[index] - local partitionName = route[1] - local partition = project.partitions[partitionName] - local item = items[index] - - local fullRoute = collectMatch(partition.target, "[^.]+") - for i = 2, #route do - table.insert(fullRoute, routes[index][i]) - end - - Reconciler.reconcileRoute(fullRoute, item) - end -end - -function Plugin:startPolling() - if self._polling then - return - end - - print("Starting to poll...") - - self._polling = true - self._label.Enabled = true - - return self:server() - :andThen(function(server) - self:syncIn():await() - - local project = server:getInfo():await().project - - while self._polling do - local changes = server:getChanges():await() - - local routes = {} - - for _, change in ipairs(changes) do - table.insert(routes, change.route) - end - - self:_pull(server, project, routes) - - wait(Config.pollingRate) - end - end) - :catch(function() - self:stopPolling() - end) -end - -function Plugin:syncIn() - print("Syncing from server...") - - return self:server() - :andThen(function(server) - local project = server:getInfo():await().project - - local routes = {} - - for name in pairs(project.partitions) do - table.insert(routes, {name}) - end - - self:_pull(server, project, routes) - - print("Sync successful!") - end) -end - -return Plugin diff --git a/plugin/src/Promise.lua b/plugin/src/Promise.lua deleted file mode 100644 index cdcea791..00000000 --- a/plugin/src/Promise.lua +++ /dev/null @@ -1,311 +0,0 @@ ---[[ - An implementation of Promises similar to Promise/A+. -]] - -local PROMISE_DEBUG = false - --- If promise debugging is on, use a version of pcall that warns on failure. --- This is useful for finding errors that happen within Promise itself. -local wpcall -if PROMISE_DEBUG then - wpcall = function(f, ...) - local result = { pcall(f, ...) } - - if not result[1] then - warn(result[2]) - end - - return unpack(result) - end -else - wpcall = pcall -end - ---[[ - Creates a function that invokes a callback with correct error handling and - resolution mechanisms. -]] -local function createAdvancer(callback, resolve, reject) - return function(...) - local result = { wpcall(callback, ...) } - local ok = table.remove(result, 1) - - if ok then - resolve(unpack(result)) - else - reject(unpack(result)) - end - end -end - -local function isEmpty(t) - return next(t) == nil -end - -local Promise = {} -Promise.__index = Promise - -Promise.Status = { - Started = "Started", - Resolved = "Resolved", - Rejected = "Rejected", -} - ---[[ - Constructs a new Promise with the given initializing callback. - - This is generally only called when directly wrapping a non-promise API into - a promise-based version. - - The callback will receive 'resolve' and 'reject' methods, used to start - invoking the promise chain. - - For example: - - local function get(url) - return Promise.new(function(resolve, reject) - spawn(function() - resolve(HttpService:GetAsync(url)) - end) - end) - end - - get("https://google.com") - :andThen(function(stuff) - print("Got some stuff!", stuff) - end) -]] -function Promise.new(callback) - local promise = { - -- Used to locate where a promise was created - _source = debug.traceback(), - - -- A tag to identify us as a promise - _type = "Promise", - - _status = Promise.Status.Started, - - -- A table containing a list of all results, whether success or failure. - -- Only valid if _status is set to something besides Started - _value = nil, - - -- If an error occurs with no observers, this will be set. - _unhandledRejection = false, - - -- Queues representing functions we should invoke when we update! - _queuedResolve = {}, - _queuedReject = {}, - } - - setmetatable(promise, Promise) - - local function resolve(...) - promise:_resolve(...) - end - - local function reject(...) - promise:_reject(...) - end - - local ok, err = wpcall(callback, resolve, reject) - - if not ok and promise._status == Promise.Status.Started then - reject(err) - end - - return promise -end - ---[[ - Create a promise that represents the immediately resolved value. -]] -function Promise.resolve(value) - return Promise.new(function(resolve) - resolve(value) - end) -end - ---[[ - Create a promise that represents the immediately rejected value. -]] -function Promise.reject(value) - return Promise.new(function(_, reject) - reject(value) - end) -end - ---[[ - Returns a new promise that: - * is resolved when all input promises resolve - * is rejected if ANY input promises reject -]] -function Promise.all(...) - error("unimplemented", 2) -end - ---[[ - Is the given object a Promise instance? -]] -function Promise.is(object) - if type(object) ~= "table" then - return false - end - - return object._type == "Promise" -end - ---[[ - Creates a new promise that receives the result of this promise. - - The given callbacks are invoked depending on that result. -]] -function Promise:andThen(successHandler, failureHandler) - self._unhandledRejection = false - - -- Create a new promise to follow this part of the chain - return Promise.new(function(resolve, reject) - -- Our default callbacks just pass values onto the next promise. - -- This lets success and failure cascade correctly! - - local successCallback = resolve - if successHandler then - successCallback = createAdvancer(successHandler, resolve, reject) - end - - local failureCallback = reject - if failureHandler then - failureCallback = createAdvancer(failureHandler, resolve, reject) - end - - if self._status == Promise.Status.Started then - -- If we haven't resolved yet, put ourselves into the queue - table.insert(self._queuedResolve, successCallback) - table.insert(self._queuedReject, failureCallback) - elseif self._status == Promise.Status.Resolved then - -- This promise has already resolved! Trigger success immediately. - successCallback(unpack(self._value)) - elseif self._status == Promise.Status.Rejected then - -- This promise died a terrible death! Trigger failure immediately. - failureCallback(unpack(self._value)) - end - end) -end - ---[[ - Used to catch any errors that may have occurred in the promise. -]] -function Promise:catch(failureCallback) - return self:andThen(nil, failureCallback) -end - ---[[ - Yield until the promise is completed. - - This matches the execution model of normal Roblox functions. -]] -function Promise:await() - self._unhandledRejection = false - - if self._status == Promise.Status.Started then - local result - local bindable = Instance.new("BindableEvent") - - self:andThen(function(...) - result = {...} - bindable:Fire(true) - end, function(...) - result = {...} - bindable:Fire(false) - end) - - local ok = bindable.Event:Wait() - bindable:Destroy() - - if not ok then - error(tostring(result[1]), 2) - end - - return unpack(result) - elseif self._status == Promise.Status.Resolved then - return unpack(self._value) - elseif self._status == Promise.Status.Rejected then - error(tostring(self._value[1]), 2) - end -end - -function Promise:_resolve(...) - if self._status ~= Promise.Status.Started then - return - end - - -- If the resolved value was a Promise, we chain onto it! - if Promise.is((...)) then - -- Without this warning, arguments sometimes mysteriously disappear - if select("#", ...) > 1 then - local message = ( - "When returning a Promise from andThen, extra arguments are " .. - "discarded! See:\n\n%s" - ):format( - self._source - ) - warn(message) - end - - (...):andThen(function(...) - self:_resolve(...) - end, function(...) - self:_reject(...) - end) - - return - end - - self._status = Promise.Status.Resolved - self._value = {...} - - -- We assume that these callbacks will not throw errors. - for _, callback in ipairs(self._queuedResolve) do - callback(...) - end -end - -function Promise:_reject(...) - if self._status ~= Promise.Status.Started then - return - end - - self._status = Promise.Status.Rejected - self._value = {...} - - -- If there are any rejection handlers, call those! - if not isEmpty(self._queuedReject) then - -- We assume that these callbacks will not throw errors. - for _, callback in ipairs(self._queuedReject) do - callback(...) - end - else - -- At this point, no one was able to observe the error. - -- An error handler might still be attached if the error occurred - -- synchronously. We'll wait one tick, and if there are still no - -- observers, then we should put a message in the console. - - self._unhandledRejection = true - local err = tostring((...)) - - spawn(function() - -- Someone observed the error, hooray! - if not self._unhandledRejection then - return - end - - -- Build a reasonable message - local message = ("Unhandled promise rejection:\n\n%s\n\n%s"):format( - err, - self._source - ) - warn(message) - end) - end -end - -return Promise diff --git a/plugin/src/Promise.spec.lua b/plugin/src/Promise.spec.lua deleted file mode 100644 index 60cc9cbe..00000000 --- a/plugin/src/Promise.spec.lua +++ /dev/null @@ -1,70 +0,0 @@ -return function() - local Promise = require(script.Parent.Promise) - - describe("Promise.new", function() - it("should instantiate with a callback", function() - local promise = Promise.new(function() end) - - expect(promise).to.be.ok() - end) - - it("should invoke the given callback with resolve and reject", function() - local callCount = 0 - local resolveArg - local rejectArg - - local promise = Promise.new(function(resolve, reject) - callCount = callCount + 1 - resolveArg = resolve - rejectArg = reject - end) - - expect(promise).to.be.ok() - - expect(callCount).to.equal(1) - expect(resolveArg).to.be.a("function") - expect(rejectArg).to.be.a("function") - expect(promise._status).to.equal(Promise.Status.Started) - end) - - it("should resolve promises on resolve()", function() - local callCount = 0 - - local promise = Promise.new(function(resolve) - callCount = callCount + 1 - resolve() - end) - - expect(promise).to.be.ok() - expect(callCount).to.equal(1) - expect(promise._status).to.equal(Promise.Status.Resolved) - end) - - it("should reject promises on reject()", function() - local callCount = 0 - - local promise = Promise.new(function(resolve, reject) - callCount = callCount + 1 - reject() - end) - - expect(promise).to.be.ok() - expect(callCount).to.equal(1) - expect(promise._status).to.equal(Promise.Status.Rejected) - end) - - it("should reject on error in callback", function() - local callCount = 0 - - local promise = Promise.new(function() - callCount = callCount + 1 - error("hahah") - end) - - expect(promise).to.be.ok() - expect(callCount).to.equal(1) - expect(promise._status).to.equal(Promise.Status.Rejected) - expect(promise._value[1]:find("hahah")).to.be.ok() - end) - end) -end diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua deleted file mode 100644 index 062f0dee..00000000 --- a/plugin/src/Reconciler.lua +++ /dev/null @@ -1,269 +0,0 @@ -local Reconciler = {} - ---[[ - The set of file names that should pass as init files - These files usurp their parents. -]] -local initNames = { - ["init.lua"] = true, - ["init.server.lua"] = true, - ["init.client.lua"] = true, -} - -local function isInit(item, itemFileName) - if item and item.type == "dir" then - return - end - - return initNames[itemFileName] or false -end - ---[[ - Determines if the given VFS item has an init file. Yields information about - the file. -]] -local function findInit(item) - if item.type ~= "dir" then - return nil, nil - end - - for childFileName, childItem in pairs(item.children) do - if isInit(childItem, childFileName) then - return childItem, childFileName - end - end - - return nil, nil -end - ---[[ - Given a VFS item, returns a Name and ClassName for a corresponding Roblox - instance. - - Doesn't take into account init files. -]] -local function itemToName(item, fileName) - if item and item.type == "dir" then - return fileName, "Folder" - elseif item and item.type == "file" or not item then - if fileName:find("%.server%.lua$") then - return fileName:match("^(.-)%.server%.lua$"), "Script" - elseif fileName:find("%.client%.lua$") then - return fileName:match("^(.-)%.client%.lua$"), "LocalScript" - elseif fileName:find("%.lua") then - return fileName:match("^(.-)%.lua$"), "ModuleScript" - else - return fileName, "StringValue" - end - else - error("unknown item type " .. tostring(item.type)) - end -end - ---[[ - Given a VFS item, assigns all relevant values (except Name!) to a Roblox - instance. -]] -local function setValues(rbx, item, fileName) - local _, className = itemToName(item, fileName) - - if className:find("Script") then - rbx.Source = item.contents - else - rbx.Value = item.contents - end -end - -function Reconciler._reifyShallow(item, fileName) - if item.type == "dir" then - local initItem, initFileName = findInit(item) - - if initItem then - local rbx = Reconciler._reify(initItem, initFileName) - rbx.Name = fileName - - return rbx - else - local rbx = Instance.new("Folder") - rbx.Name = fileName - - return rbx - end - elseif item.type == "file" then - local objectName, className = itemToName(item, fileName) - - local rbx = Instance.new(className) - rbx.Name = objectName - - setValues(rbx, item, fileName) - - return rbx - else - error("unknown item type " .. tostring(item.type)) - end -end - ---[[ - Construct a new Roblox instance tree that corresponds to the given VFS item. -]] -function Reconciler._reify(item, fileName, parent) - local rbx = Reconciler._reifyShallow(item, fileName) - - if item.type == "dir" then - for childFileName, childItem in pairs(item.children) do - if not isInit(childItem, childFileName) then - local childRbx = Reconciler._reify(childItem, childFileName) - childRbx.Parent = rbx - end - end - end - - rbx.Parent = parent - - return rbx -end - -function Reconciler.reconcile(rbx, item, fileName, parent) - -- Item was deleted! - if not item then - if isInit(item, fileName) then - if not parent then - return - end - - -- Un-usurp parent! - local newParent = Instance.new("Folder") - newParent.Name = parent.Name - - for _, child in ipairs(parent:GetChildren()) do - child.Parent = newParent - end - - newParent.Parent = parent.Parent - parent:Destroy() - - return - else - if rbx then - rbx:Destroy() - end - - return - end - end - - if item.type == "dir" then - -- Folder was created! - if not rbx then - return Reconciler._reify(item, fileName, parent) - end - - local initItem, initFileName = findInit(item) - - if initItem then - local _, initClassName = itemToName(initItem, initFileName) - - if rbx.ClassName == initClassName then - setValues(rbx, initItem, initFileName) - else - rbx:Destroy() - return Reconciler._reify(item, fileName, parent) - end - else - if rbx.ClassName ~= "Folder" then - -- Certain objects (services) can't be destroyed. - -- If we target one of these, leave it alone! - local ok = pcall(rbx.Destroy, rbx) - - if ok then - return Reconciler._reify(item, fileName, parent) - end - end - end - - local visitedChildren = {} - - for childFileName, childItem in pairs(item.children) do - if not isInit(childItem, childFileName) then - local childName = itemToName(childItem, childFileName) - - visitedChildren[childName] = true - - Reconciler.reconcile(rbx:FindFirstChild(childName), childItem, childFileName, rbx) - end - end - - for _, childRbx in ipairs(rbx:GetChildren()) do - -- Child was deleted! - if not visitedChildren[childRbx.Name] then - childRbx:Destroy() - end - end - - return rbx - elseif item.type == "file" then - if isInit(item, fileName) then - -- Usurp our container! - local _, className = itemToName(item, fileName) - - if parent.ClassName == className then - rbx = parent - else - rbx = Reconciler._reify(item, fileName, parent.Parent) - rbx.Name = parent.Name - - for _, child in ipairs(parent:GetChildren()) do - child.Parent = rbx - end - - parent:Destroy() - end - - setValues(rbx, item, fileName) - - return rbx - else - if not rbx then - return Reconciler._reify(item, fileName, parent) - end - - local _, className = itemToName(item, fileName) - - if rbx.ClassName ~= className then - rbx:Destroy() - return Reconciler._reify(item, fileName, parent) - end - - setValues(rbx, item, fileName) - - return rbx - end - else - error("unknown item type " .. tostring(item.type)) - end -end - -function Reconciler.reconcileRoute(route, item) - local location = game - - for i = 1, #route - 1 do - local piece = route[i] - local newLocation = location:FindFirstChild(piece) - - if not newLocation then - newLocation = Instance.new("Folder") - newLocation.Name = piece - newLocation.Parent = location - end - - location = newLocation - end - - local fileName = route[#route] - - local name = itemToName(item, fileName) - local rbx = location:FindFirstChild(name) - Reconciler.reconcile(rbx, item, fileName, location) -end - -return Reconciler diff --git a/plugin/src/Server.lua b/plugin/src/Server.lua deleted file mode 100644 index 02268220..00000000 --- a/plugin/src/Server.lua +++ /dev/null @@ -1,69 +0,0 @@ -local HttpService = game:GetService("HttpService") - -local Server = {} -Server.__index = Server - ---[[ - Create a new Server using the given HTTP implementation and replacer. - - If the context becomes invalid, `replacer` will be invoked with a new - context that should be suitable to replace this one. - - Attempting to invoke methods on an invalid conext will throw errors! -]] -function Server.connect(http) - local context = { - http = http, - serverId = nil, - currentTime = 0, - } - - setmetatable(context, Server) - - return context:_start() -end - -function Server:_start() - return self:getInfo() - :andThen(function(response) - self.serverId = response.serverId - self.currentTime = response.currentTime - - return self - end) -end - -function Server:getInfo() - return self.http:get("/") - :andThen(function(response) - response = response:json() - - return response - end) -end - -function Server:read(paths) - local body = HttpService:JSONEncode(paths) - - return self.http:post("/read", body) - :andThen(function(response) - response = response:json() - - return response.items - end) -end - -function Server:getChanges() - local url = ("/changes/%f"):format(self.currentTime) - - return self.http:get(url) - :andThen(function(response) - response = response:json() - - self.currentTime = response.currentTime - - return response.changes - end) -end - -return Server diff --git a/plugin/src/runTests.lua b/plugin/src/runTests.lua deleted file mode 100644 index 9b1da76e..00000000 --- a/plugin/src/runTests.lua +++ /dev/null @@ -1,4 +0,0 @@ -return function() - local TestEZ = require(script.Parent.Parent.TestEZ) - TestEZ.TestBootstrap:run(script.Parent) -end diff --git a/rojo.json b/rojo.json deleted file mode 100644 index 821517a3..00000000 --- a/rojo.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "rojo", - "servePort": 8000, - "partitions": { - "plugin": { - "path": "plugin/src", - "target": "ReplicatedStorage.Rojo" - }, - "modules/roact": { - "path": "modules/roact/lib", - "target": "ReplicatedStorage.Rojo.modules.Roact" - }, - "modules/rodux": { - "path": "modules/rodux/lib", - "target": "ReplicatedStorage.Rojo.modules.Rodux" - }, - "modules/roact-rodux": { - "path": "modules/roact-rodux/lib", - "target": "ReplicatedStorage.Rojo.modules.RoactRodux" - }, - "modules/testez": { - "path": "modules/testez/lib", - "target": "ReplicatedStorage.TestEZ" - } - } -} \ No newline at end of file diff --git a/spec.lua b/spec.lua deleted file mode 100644 index dd0edde0..00000000 --- a/spec.lua +++ /dev/null @@ -1,69 +0,0 @@ ---[[ - Loads our library and all of its dependencies, then runs tests using TestEZ. -]] - --- If you add any dependencies, add them to this table so they'll be loaded! -local LOAD_MODULES = { - {"plugin/src", "Plugin"}, - {"modules/testez/lib", "TestEZ"}, -} - --- This makes sure we can load Lemur and other libraries that depend on init.lua -package.path = package.path .. ";?/init.lua" - --- If this fails, make sure you've run `lua bin/install-dependencies.lua` first! -local lemur = require("modules.lemur") - ---[[ - Collapses ModuleScripts named 'init' into their parent folders. - - This is the same result as the collapsing mechanism from Rojo. -]] -local function collapse(root) - local init = root:FindFirstChild("init") - if init then - init.Name = root.Name - init.Parent = root.Parent - - for _, child in ipairs(root:GetChildren()) do - child.Parent = init - end - - root:Destroy() - root = init - end - - for _, child in ipairs(root:GetChildren()) do - if child:IsA("Folder") then - collapse(child) - end - end - - return root -end - --- Create a virtual Roblox tree -local habitat = lemur.Habitat.new() - --- We'll put all of our library code and dependencies here -local Root = lemur.Instance.new("Folder") -Root.Name = "Root" - --- Load all of the modules specified above -for _, module in ipairs(LOAD_MODULES) do - local container = lemur.Instance.new("Folder", Root) - container.Name = module[2] - habitat:loadFromFs(module[1], container) -end - -collapse(Root) - --- Load TestEZ and run our tests -local TestEZ = habitat:require(Root.TestEZ) - -local results = TestEZ.TestBootstrap:run(Root.Plugin, TestEZ.Reporters.TextReporter) - --- Did something go wrong? -if results.failureCount > 0 then - os.exit(1) -end From f00bcc6d7ed8ccc8b70b677cca90f0717dca4d99 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Dec 2017 16:52:13 -0800 Subject: [PATCH 0024/1504] Point to the rojo-plugin repository --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7c596afc..4cfb5dac 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ Rojo is a flexible multi-tool designed for creating robust Roblox projects. It's It's designed for power users who want to use the **best tools available** for building games, libraries, and plugins. +This is the main Rojo repository, containing the binary server component. For the source for the Roblox plugin, [see the rojo-plugin repository](https://github.com/LPGhatguy/rojo-plugin). + ## Features Rojo has a number of desirable features *right now*: @@ -28,7 +30,7 @@ Soon, Rojo will be able to: ## Installation Rojo has two components: * The command line tool, written in Rust -* The [Roblox Studio plugin](https://www.roblox.com/library/1211549683/Rojo-v0-0-0), written in Lua +* The [Roblox Studio plugin](https://www.roblox.com/library/1211549683/Rojo), written in Lua To install the command line tool, there are two options: * Cargo, if you have Rust installed From b60f06aa88ae146eddcd1fda0aa6c47acc763102 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Dec 2017 15:50:22 -0800 Subject: [PATCH 0025/1504] Update changelog to represent refactoring of server/client --- CHANGES.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 29565cd6..1c94895c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,14 +1,10 @@ # Rojo Change Log ## Current Master -* Fixed using a service as the target of a partition (part of #11) - * There are still cases that will trigger errors, like putting an `init.lua` file inside of a service. - * **Note that the contents of the service will be synced with the filesystem, so any existing items will be deleted!** +* Factored out the plugin into a separate repository * Fixed server when using a file as a partition * Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory! * Started running automatic tests on Travis CI (#9) - * This is only for the server right now - * Soon, I'll upgrade [Lemur](http://github.com/LPGhatguy/Lemur) to have APIs necessary for testing plugins and start testing the plugion portion of Rojo as well. ## 0.2.3 * Plugin only release From b74ba141d16ae9851fd023409d1cbc7c5397109b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 12 Dec 2017 15:01:36 -0800 Subject: [PATCH 0026/1504] Update dependencies, server v0.3.0 --- CHANGES.md | 3 +++ Cargo.lock | 28 ++++++++++++++-------------- Cargo.toml | 2 +- 3 files changed, 18 insertions(+), 15 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 1c94895c..f2231f48 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,9 @@ # Rojo Change Log ## Current Master +* *No changes* + +## 0.3.0 * Factored out the plugin into a separate repository * Fixed server when using a file as a partition * Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory! diff --git a/Cargo.lock b/Cargo.lock index c448488c..5f2566c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -517,15 +517,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rojo" -version = "0.2.0" +version = "0.3.0" dependencies = [ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -571,22 +571,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.17.0" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -595,13 +595,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -877,10 +877,10 @@ dependencies = [ "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum same-file 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70a18720d745fb9ca6a041b37cb36d0b21066006b6cff8b5b360142d4b81fb60" "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" -"checksum serde 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "6a7c37d7f192f00041e8a613e936717923a71bc0c9051fc4425a49b104140f05" -"checksum serde_derive 1.0.23 (registry+https://github.com/rust-lang/crates.io-index)" = "0672de7300b02bac3f3689f8faea813c4a1ea9fe0cb49e80f714231d267518a2" -"checksum serde_derive_internals 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "32f1926285523b2db55df263d2aa4eb69ddcfa7a7eade6430323637866b513ab" -"checksum serde_json 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ea28ea0cca944668919bec6af209864a8dfe769fd2b0b723f36b22e20c1bf69f" +"checksum serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "1c57ab4ec5fa85d08aaf8ed9245899d9bbdd66768945b21113b84d5f595cb6a1" +"checksum serde_derive 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "02c92ea07b6e49b959c1481804ebc9bfd92d3c459f1274c9a9546829e42a66ce" +"checksum serde_derive_internals 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75c6aac7b99801a16db5b40b7bf0d7e4ba16e76fbf231e32a4677f271cac0603" +"checksum serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7cf5b0b5b4bd22eeecb7e01ac2e1225c7ef5e4272b79ee28a8392a8c8489c839" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" diff --git a/Cargo.toml b/Cargo.toml index 5bdf9454..0c8a279e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.2.0" +version = "0.3.0" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 59b2401c2cced334d59b0338b70c93cd014489db Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 13 Dec 2017 11:55:30 -0800 Subject: [PATCH 0027/1504] Add more detailed error reporting around invalid projects --- CHANGES.md | 3 ++- src/bin.rs | 30 +++++++++++++++++++++++++++--- src/project.rs | 4 ++-- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index f2231f48..d795a015 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,8 @@ # Rojo Change Log ## Current Master -* *No changes* +* Improved error reporting when invalid JSON is found in a `rojo.json` project + * These messages are passed on from Serde ## 0.3.0 * Factored out the plugin into a separate repository diff --git a/src/bin.rs b/src/bin.rs index 7b24940b..7242af14 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -25,7 +25,7 @@ use std::thread; use core::Config; use pathext::canonicalish; -use project::Project; +use project::{Project, ProjectLoadError}; use vfs::Vfs; use vfs_watch::VfsWatcher; @@ -98,8 +98,32 @@ fn main() { println!("Using project from {}", project_path.display()); v }, - Err(_) => { - println!("Using default project..."); + Err(err) => { + match err { + ProjectLoadError::InvalidJson(serde_err) => { + eprintln!( + "Found invalid JSON!\nProject in: {}\nError: {}", + project_path.display(), + serde_err, + ); + + std::process::exit(1); + }, + ProjectLoadError::FailedToOpen | ProjectLoadError::FailedToRead => { + eprintln!("Found project file, but failed to read it!"); + eprintln!( + "Check the permissions of the project file at\n{}", + project_path.display(), + ); + + std::process::exit(1); + }, + _ => { + // Any other error is fine; use the default project. + }, + } + + println!("Found no project file, using default project..."); Project::default() }, }; diff --git a/src/project.rs b/src/project.rs index 6b705fb7..10392c53 100644 --- a/src/project.rs +++ b/src/project.rs @@ -13,7 +13,7 @@ pub enum ProjectLoadError { DidNotExist, FailedToOpen, FailedToRead, - Invalid, + InvalidJson(serde_json::Error), } #[derive(Debug)] @@ -116,7 +116,7 @@ impl Project { match serde_json::from_str(&contents) { Ok(v) => Ok(v), - Err(_) => return Err(ProjectLoadError::Invalid), + Err(e) => return Err(ProjectLoadError::InvalidJson(e)), } } From f89d491f296fbeb634ad81a527930184e0920ba1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 13 Dec 2017 12:05:11 -0800 Subject: [PATCH 0028/1504] Run rustfmt I ignored some odd formatting it introduced relating to putting braces on newlines in if-let blocks. This might be a bug, but I didn't find any way to turn that off. --- src/pathext.rs | 12 ++++++++++-- src/vfs_watch.rs | 4 ++-- src/web.rs | 2 +- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/pathext.rs b/src/pathext.rs index 1fd49a80..10f654d5 100644 --- a/src/pathext.rs +++ b/src/pathext.rs @@ -31,7 +31,11 @@ fn test_path_to_route() { assert_eq!(path_to_route(root, value), result); } - t(Path::new("/a/b/c"), Path::new("/a/b/c/d"), Some(vec!["d".to_string()])); + t( + Path::new("/a/b/c"), + Path::new("/a/b/c/d"), + Some(vec!["d".to_string()]), + ); t(Path::new("/a/b"), Path::new("a"), None); } @@ -42,7 +46,11 @@ fn test_path_to_route_windows() { assert_eq!(path_to_route(root, value), result); } - t(Path::new("C:\\foo"), Path::new("C:\\foo\\bar\\baz"), Some(vec!["bar".to_string(), "baz".to_string()])); + t( + Path::new("C:\\foo"), + Path::new("C:\\foo\\bar\\baz"), + Some(vec!["bar".to_string(), "baz".to_string()]), + ); } /// Turns the path into an absolute one, using the current working directory if diff --git a/src/vfs_watch.rs b/src/vfs_watch.rs index 84808805..697b9ff6 100644 --- a/src/vfs_watch.rs +++ b/src/vfs_watch.rs @@ -4,9 +4,9 @@ use std::time::Duration; use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; -use vfs::Vfs; -use pathext::path_to_route; use core::Config; +use pathext::path_to_route; +use vfs::Vfs; pub struct VfsWatcher { vfs: Arc>, diff --git a/src/web.rs b/src/web.rs index e8ba8bc0..12c936ae 100644 --- a/src/web.rs +++ b/src/web.rs @@ -8,7 +8,7 @@ use serde_json; use core::Config; use project::Project; -use vfs::{Vfs, VfsItem, VfsChange}; +use vfs::{Vfs, VfsChange, VfsItem}; static MAX_BODY_SIZE: usize = 25 * 1024 * 1025; // 25 MiB From 7c6fe38346a03e426db2b735438db59b9d01ccd0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Dec 2017 00:24:01 -0800 Subject: [PATCH 0029/1504] CLI version 0.3.1 --- CHANGES.md | 3 +++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d795a015..1a6b333b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,9 @@ # Rojo Change Log ## Current Master +* *No changes* + +## 0.3.1 * Improved error reporting when invalid JSON is found in a `rojo.json` project * These messages are passed on from Serde diff --git a/Cargo.lock b/Cargo.lock index 5f2566c4..fe831498 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -517,7 +517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rojo" -version = "0.3.0" +version = "0.3.1" dependencies = [ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 0c8a279e..a1e34642 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.3.0" +version = "0.3.1" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From b4e31ea35d3aed8ece19c3aaa5d3896075237a44 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Dec 2017 01:08:05 -0800 Subject: [PATCH 0030/1504] Fix serve path failing to be absolute when given as a relative path --- CHANGES.md | 2 +- src/bin.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 1a6b333b..dfc0d178 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,7 @@ # Rojo Change Log ## Current Master -* *No changes* +* Fixed `rojo serve` failing to correctly construct an absolute root path when passed as an argument ## 0.3.1 * Improved error reporting when invalid JSON is found in a `rojo.json` project diff --git a/src/bin.rs b/src/bin.rs index 7242af14..4c42a4cf 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -85,7 +85,7 @@ fn main() { let sub_matches = sub_matches.unwrap(); let project_path = match sub_matches.value_of("PROJECT") { - Some(v) => PathBuf::from(v), + Some(v) => canonicalish(PathBuf::from(v)), None => std::env::current_dir().unwrap(), }; From 5bf1f1119076750afb0d4a0f38ec6f2a854e11c4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 13 Dec 2017 15:41:25 -0800 Subject: [PATCH 0031/1504] Hacky first go at it -- keeping the existing VfsItem infrastructure I think this is actually a pretty reasonable flow. --- Cargo.lock | 76 +++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 ++ src/bin.rs | 4 +++ src/web.rs | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 4 files changed, 182 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fe831498..50e19653 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6,6 +6,14 @@ dependencies = [ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "aho-corasick" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ansi_term" version = "0.10.2" @@ -269,6 +277,11 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lazy_static" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "libc" version = "0.2.34" @@ -292,6 +305,14 @@ dependencies = [ "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memchr" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mime" version = "0.1.3" @@ -510,18 +531,37 @@ dependencies = [ "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "regex" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex-syntax" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "regex-syntax" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rojo" version = "0.3.1" dependencies = [ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -694,6 +734,15 @@ dependencies = [ "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "thread_local" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "time" version = "0.1.38" @@ -742,6 +791,14 @@ name = "unicode-xid" version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unreachable" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "url" version = "0.2.38" @@ -767,6 +824,11 @@ name = "utf8-ranges" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "utf8-ranges" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "uuid" version = "0.1.18" @@ -781,6 +843,11 @@ name = "vec_map" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "void" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "walkdir" version = "2.0.1" @@ -810,6 +877,7 @@ dependencies = [ [metadata] "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" +"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" "checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860" @@ -845,10 +913,12 @@ dependencies = [ "checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" "checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0" "checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" +"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" "checksum mime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ec0c2f4d901bf1d4a2192a40b4b570ae3b19c51243e549defc1de741940aa787" "checksum mime_guess 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "422acd80644209a8c8c66a20514840d8c092eb1eab2898ca7c548cc1d64c8998" "checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" @@ -872,7 +942,9 @@ dependencies = [ "checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" +"checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" +"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" "checksum rouille 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d6415f261a8775bef50e9fcfb14ed73209ce637f753f9d1c8c6122559e559001" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum same-file 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70a18720d745fb9ca6a041b37cb36d0b21066006b6cff8b5b360142d4b81fb60" @@ -893,17 +965,21 @@ dependencies = [ "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" +"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" "checksum tiny_http 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "016f040cfc9b5be610de3619eaaa57017fa0b0b678187327bde75fc146e2a41f" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)" = "cbaa8377a162d88e7d15db0cf110c8523453edcbc5bc66d2b6fffccffa34a068" "checksum url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa35e768d4daf1d85733418a49fb42e10d7f633e394fccab4ab7aba897053fe2" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" +"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b6d201f4f8998a837196b6de9c73e35af14c992cbb92c4ab641d2c2dce52de" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/Cargo.toml b/Cargo.toml index a1e34642..9cab5bfb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,3 +18,5 @@ serde_derive = "1.0" serde_json = "1.0" notify = "4.0.0" rand = "0.3" +regex = "0.2" +lazy_static = "1.0" diff --git a/src/bin.rs b/src/bin.rs index 4c42a4cf..aecb946a 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -7,10 +7,14 @@ extern crate rouille; #[macro_use] extern crate clap; +#[macro_use] +extern crate lazy_static; + extern crate notify; extern crate rand; extern crate serde; extern crate serde_json; +extern crate regex; pub mod web; pub mod core; diff --git a/src/web.rs b/src/web.rs index 12c936ae..4a8aaebe 100644 --- a/src/web.rs +++ b/src/web.rs @@ -1,3 +1,4 @@ +use std::collections::HashMap; use std::io::Read; use std::sync::{Arc, Mutex}; use std::thread; @@ -5,6 +6,7 @@ use std::thread; use rouille; use serde; use serde_json; +use regex::Regex; use core::Config; use project::Project; @@ -12,6 +14,91 @@ use vfs::{Vfs, VfsChange, VfsItem}; static MAX_BODY_SIZE: usize = 25 * 1024 * 1025; // 25 MiB +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +struct RbxItem { + name: String, + class_name: String, + children: Vec, + properties: HashMap, +} + +impl RbxItem { + pub fn from_vfs_item(file_name: &String, item: &VfsItem) -> RbxItem { + lazy_static! { + static ref PT_MODULE: Regex = Regex::new(r"^(.*?)\.lua$").unwrap(); + } + + match item { + &VfsItem::File { ref contents } => { + let mut properties = HashMap::new(); + + properties.insert("Source".to_string(), RbxValue::String { + value: contents.clone() + }); + + let rbx_name = { + if let Some(captures) = PT_MODULE.captures(file_name) { + captures.get(1).unwrap().as_str().to_string() + } else { + file_name.clone() + } + }; + + RbxItem { + name: rbx_name, + class_name: "ModuleScript".to_string(), + children: Vec::new(), + properties, + } + }, + &VfsItem::Dir { ref children } => { + let init = children.get(&"init.lua".to_string()); + + if let Some(init) = init { + let mut rbx_children = Vec::new(); + + for (name, child_item) in children { + if name != "init.lua" { + rbx_children.push(RbxItem::from_vfs_item(&name, &child_item)); + } + } + + let init_rbx = RbxItem::from_vfs_item(&"init.lua".to_string(), &init); + + RbxItem { + name: file_name.clone(), + class_name: init_rbx.class_name, + children: rbx_children, + properties: init_rbx.properties, + } + } else { + let mut rbx_children = Vec::new(); + + for (name, child_item) in children { + rbx_children.push(RbxItem::from_vfs_item(&name, &child_item)); + } + + RbxItem { + name: file_name.clone(), + class_name: "Folder".to_string(), + children: rbx_children, + properties: HashMap::new(), + } + } + }, + } + } +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase", tag = "type")] +enum RbxValue { + String { + value: String, + }, +} + #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct ServerInfo<'a> { @@ -25,7 +112,7 @@ struct ServerInfo<'a> { #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct ReadResult<'a> { - items: Vec>, + items: Vec>, server_id: &'a str, current_time: f64, } @@ -110,7 +197,7 @@ pub fn start(config: Config, project: Project, vfs: Arc>) { json(ServerInfo { server_version: env!("CARGO_PKG_VERSION"), - protocol_version: 0, + protocol_version: 1, server_id: &server_id, project: &project, current_time, @@ -152,9 +239,19 @@ pub fn start(config: Config, project: Project, vfs: Arc>) { (items, current_time) }; + let rbx_items = items + .iter() + .map(|item| { + match *item { + Some(ref item) => Some(RbxItem::from_vfs_item(&"src".to_string(), item)), + None => None, + } + }) + .collect::>(); + json(ReadResult { server_id: &server_id, - items, + items: rbx_items, current_time, }) }, From 21e9625c36544303f55b8ea61e038b0cdbe4e83b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 13 Dec 2017 17:50:34 -0800 Subject: [PATCH 0032/1504] Prototype plugin architecture, switch instance-based stuff to that --- src/bin.rs | 3 ++ src/plugin.rs | 11 ++++ src/plugins/default_plugin.rs | 49 ++++++++++++++++++ src/plugins/mod.rs | 3 ++ src/rbx.rs | 18 +++++++ src/vfs.rs | 8 ++- src/web.rs | 95 ++++------------------------------- 7 files changed, 99 insertions(+), 88 deletions(-) create mode 100644 src/plugin.rs create mode 100644 src/plugins/default_plugin.rs create mode 100644 src/plugins/mod.rs create mode 100644 src/rbx.rs diff --git a/src/bin.rs b/src/bin.rs index aecb946a..41090e1b 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -22,6 +22,9 @@ pub mod project; pub mod pathext; pub mod vfs; pub mod vfs_watch; +pub mod rbx; +pub mod plugin; +pub mod plugins; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; diff --git a/src/plugin.rs b/src/plugin.rs new file mode 100644 index 00000000..1d03d326 --- /dev/null +++ b/src/plugin.rs @@ -0,0 +1,11 @@ +use rbx::RbxItem; +use vfs::VfsItem; + +pub enum PluginResult { + Value(Option), + Pass, +} + +pub trait Plugin { + fn transform(item: &VfsItem) -> PluginResult; +} diff --git a/src/plugins/default_plugin.rs b/src/plugins/default_plugin.rs new file mode 100644 index 00000000..b5beeca6 --- /dev/null +++ b/src/plugins/default_plugin.rs @@ -0,0 +1,49 @@ +use std::collections::HashMap; + +use plugin::{Plugin, PluginResult}; +use rbx::{RbxItem, RbxValue}; +use vfs::VfsItem; + +pub struct DefaultPlugin; + +impl Plugin for DefaultPlugin { + fn transform(item: &VfsItem) -> PluginResult { + match item { + &VfsItem::File { ref contents, ref name } => { + let mut properties = HashMap::new(); + + properties.insert("Value".to_string(), RbxValue::String { + value: contents.clone(), + }); + + PluginResult::Value(Some(RbxItem { + name: name.clone(), + class_name: "StringValue".to_string(), + children: Vec::new(), + properties, + })) + }, + &VfsItem::Dir { ref children, ref name } => { + // TODO: call back into plugin list and transform there instead + + let mut rbx_children = Vec::new(); + + for (_, child_item) in children { + match Self::transform(child_item) { + PluginResult::Value(Some(rbx_item)) => { + rbx_children.push(rbx_item); + }, + _ => {}, + } + } + + PluginResult::Value(Some(RbxItem { + name: name.clone(), + class_name: "Folder".to_string(), + children: rbx_children, + properties: HashMap::new(), + })) + }, + } + } +} diff --git a/src/plugins/mod.rs b/src/plugins/mod.rs new file mode 100644 index 00000000..c3b68bad --- /dev/null +++ b/src/plugins/mod.rs @@ -0,0 +1,3 @@ +mod default_plugin; + +pub use self::default_plugin::*; diff --git a/src/rbx.rs b/src/rbx.rs new file mode 100644 index 00000000..043dc3b6 --- /dev/null +++ b/src/rbx.rs @@ -0,0 +1,18 @@ +use std::collections::HashMap; + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct RbxItem { + pub name: String, + pub class_name: String, + pub children: Vec, + pub properties: HashMap, +} + +#[derive(Debug, Serialize)] +#[serde(rename_all = "camelCase", tag = "type")] +pub enum RbxValue { + String { + value: String, + }, +} diff --git a/src/vfs.rs b/src/vfs.rs index 44b9165f..81fb9c04 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -37,8 +37,8 @@ pub struct VfsChange { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase", tag = "type")] pub enum VfsItem { - File { contents: String }, - Dir { children: HashMap }, + File { name: String, contents: String }, + Dir { name: String, children: HashMap }, } impl Vfs { @@ -78,6 +78,7 @@ impl Vfs { } fn read_dir>(&self, path: P) -> Result { + let path = path.as_ref(); let reader = match fs::read_dir(path) { Ok(v) => v, Err(_) => return Err(()), @@ -104,11 +105,13 @@ impl Vfs { } Ok(VfsItem::Dir { + name: path.file_name().unwrap().to_string_lossy().into_owned(), children, }) } fn read_file>(&self, path: P) -> Result { + let path = path.as_ref(); let mut file = match File::open(path) { Ok(v) => v, Err(_) => return Err(()), @@ -122,6 +125,7 @@ impl Vfs { } Ok(VfsItem::File { + name: path.file_name().unwrap().to_string_lossy().into_owned(), contents, }) } diff --git a/src/web.rs b/src/web.rs index 4a8aaebe..670b0f0c 100644 --- a/src/web.rs +++ b/src/web.rs @@ -11,94 +11,12 @@ use regex::Regex; use core::Config; use project::Project; use vfs::{Vfs, VfsChange, VfsItem}; +use rbx::{RbxItem, RbxValue}; +use plugin::{Plugin, PluginResult}; +use plugins::DefaultPlugin; static MAX_BODY_SIZE: usize = 25 * 1024 * 1025; // 25 MiB -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -struct RbxItem { - name: String, - class_name: String, - children: Vec, - properties: HashMap, -} - -impl RbxItem { - pub fn from_vfs_item(file_name: &String, item: &VfsItem) -> RbxItem { - lazy_static! { - static ref PT_MODULE: Regex = Regex::new(r"^(.*?)\.lua$").unwrap(); - } - - match item { - &VfsItem::File { ref contents } => { - let mut properties = HashMap::new(); - - properties.insert("Source".to_string(), RbxValue::String { - value: contents.clone() - }); - - let rbx_name = { - if let Some(captures) = PT_MODULE.captures(file_name) { - captures.get(1).unwrap().as_str().to_string() - } else { - file_name.clone() - } - }; - - RbxItem { - name: rbx_name, - class_name: "ModuleScript".to_string(), - children: Vec::new(), - properties, - } - }, - &VfsItem::Dir { ref children } => { - let init = children.get(&"init.lua".to_string()); - - if let Some(init) = init { - let mut rbx_children = Vec::new(); - - for (name, child_item) in children { - if name != "init.lua" { - rbx_children.push(RbxItem::from_vfs_item(&name, &child_item)); - } - } - - let init_rbx = RbxItem::from_vfs_item(&"init.lua".to_string(), &init); - - RbxItem { - name: file_name.clone(), - class_name: init_rbx.class_name, - children: rbx_children, - properties: init_rbx.properties, - } - } else { - let mut rbx_children = Vec::new(); - - for (name, child_item) in children { - rbx_children.push(RbxItem::from_vfs_item(&name, &child_item)); - } - - RbxItem { - name: file_name.clone(), - class_name: "Folder".to_string(), - children: rbx_children, - properties: HashMap::new(), - } - } - }, - } - } -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase", tag = "type")] -enum RbxValue { - String { - value: String, - }, -} - #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct ServerInfo<'a> { @@ -243,7 +161,12 @@ pub fn start(config: Config, project: Project, vfs: Arc>) { .iter() .map(|item| { match *item { - Some(ref item) => Some(RbxItem::from_vfs_item(&"src".to_string(), item)), + Some(ref item) => { + match DefaultPlugin::transform(item) { + PluginResult::Value(rbx_item) => rbx_item, + _ => None, + } + }, None => None, } }) From 01325c8c7ec4a6dbe49ef0190a58954101490497 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 13 Dec 2017 23:40:32 -0800 Subject: [PATCH 0033/1504] Implement PluginChain --- src/plugin.rs | 25 ++++++++++++++++++++++++- src/plugins/default_plugin.rs | 18 +++++++++++------- src/web.rs | 24 +++++++++++++----------- 3 files changed, 48 insertions(+), 19 deletions(-) diff --git a/src/plugin.rs b/src/plugin.rs index 1d03d326..6c2f6246 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -7,5 +7,28 @@ pub enum PluginResult { } pub trait Plugin { - fn transform(item: &VfsItem) -> PluginResult; + fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> PluginResult; +} + +pub struct PluginChain { + plugins: Vec>, +} + +impl PluginChain { + pub fn new(plugins: Vec>) -> PluginChain { + PluginChain { + plugins, + } + } + + pub fn transform_file(&self, vfs_item: &VfsItem) -> Option { + for plugin in &self.plugins { + match plugin.transform_file(self, vfs_item) { + PluginResult::Value(rbx_item) => return rbx_item, + PluginResult::Pass => {}, + } + } + + None + } } diff --git a/src/plugins/default_plugin.rs b/src/plugins/default_plugin.rs index b5beeca6..9026f063 100644 --- a/src/plugins/default_plugin.rs +++ b/src/plugins/default_plugin.rs @@ -1,14 +1,20 @@ use std::collections::HashMap; -use plugin::{Plugin, PluginResult}; +use plugin::{Plugin, PluginChain, PluginResult}; use rbx::{RbxItem, RbxValue}; use vfs::VfsItem; pub struct DefaultPlugin; +impl DefaultPlugin { + pub fn new() -> DefaultPlugin { + DefaultPlugin + } +} + impl Plugin for DefaultPlugin { - fn transform(item: &VfsItem) -> PluginResult { - match item { + fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> PluginResult { + match vfs_item { &VfsItem::File { ref contents, ref name } => { let mut properties = HashMap::new(); @@ -24,13 +30,11 @@ impl Plugin for DefaultPlugin { })) }, &VfsItem::Dir { ref children, ref name } => { - // TODO: call back into plugin list and transform there instead - let mut rbx_children = Vec::new(); for (_, child_item) in children { - match Self::transform(child_item) { - PluginResult::Value(Some(rbx_item)) => { + match plugins.transform_file(child_item) { + Some(rbx_item) => { rbx_children.push(rbx_item); }, _ => {}, diff --git a/src/web.rs b/src/web.rs index 670b0f0c..aa069f6d 100644 --- a/src/web.rs +++ b/src/web.rs @@ -1,4 +1,3 @@ -use std::collections::HashMap; use std::io::Read; use std::sync::{Arc, Mutex}; use std::thread; @@ -6,13 +5,12 @@ use std::thread; use rouille; use serde; use serde_json; -use regex::Regex; use core::Config; use project::Project; -use vfs::{Vfs, VfsChange, VfsItem}; -use rbx::{RbxItem, RbxValue}; -use plugin::{Plugin, PluginResult}; +use vfs::{Vfs, VfsChange}; +use rbx::RbxItem; +use plugin::PluginChain; use plugins::DefaultPlugin; static MAX_BODY_SIZE: usize = 25 * 1024 * 1025; // 25 MiB @@ -103,6 +101,13 @@ pub fn start(config: Config, project: Project, vfs: Arc>) { let server_id = config.server_id.to_string(); + // Fine, rouille, I'll put things in a 'static Arc... + lazy_static! { + static ref PLUGIN_CHAIN: Arc> = Arc::new(Mutex::new(PluginChain::new(vec![ + Box::new(DefaultPlugin::new()), + ]))); + } + thread::spawn(move || { rouille::start_server(address, move |request| { router!(request, @@ -135,6 +140,8 @@ pub fn start(config: Config, project: Project, vfs: Arc>) { }, (POST) (/read) => { + let plugin_chain = PLUGIN_CHAIN.lock().unwrap(); + let read_request: Vec> = match read_json(&request) { Some(v) => v, None => return rouille::Response::empty_400(), @@ -161,12 +168,7 @@ pub fn start(config: Config, project: Project, vfs: Arc>) { .iter() .map(|item| { match *item { - Some(ref item) => { - match DefaultPlugin::transform(item) { - PluginResult::Value(rbx_item) => rbx_item, - _ => None, - } - }, + Some(ref item) => plugin_chain.transform_file(item), None => None, } }) From 67ac6b7cec4afdd8c27bc072ce5b86800a16a71f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 13 Dec 2017 23:58:53 -0800 Subject: [PATCH 0034/1504] First implementation of 'ScriptPlugin', which serves script files as scripts --- src/plugins/default_plugin.rs | 3 ++ src/plugins/mod.rs | 2 ++ src/plugins/script_plugin.rs | 57 +++++++++++++++++++++++++++++++++++ src/web.rs | 3 +- 4 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 src/plugins/script_plugin.rs diff --git a/src/plugins/default_plugin.rs b/src/plugins/default_plugin.rs index 9026f063..92ce1104 100644 --- a/src/plugins/default_plugin.rs +++ b/src/plugins/default_plugin.rs @@ -4,6 +4,9 @@ use plugin::{Plugin, PluginChain, PluginResult}; use rbx::{RbxItem, RbxValue}; use vfs::VfsItem; +/// A plugin with simple transforms: +/// * Directories become Folder instances +/// * Files become StringValue objects with 'Value' as their contents pub struct DefaultPlugin; impl DefaultPlugin { diff --git a/src/plugins/mod.rs b/src/plugins/mod.rs index c3b68bad..dd39b2db 100644 --- a/src/plugins/mod.rs +++ b/src/plugins/mod.rs @@ -1,3 +1,5 @@ mod default_plugin; +mod script_plugin; pub use self::default_plugin::*; +pub use self::script_plugin::*; diff --git a/src/plugins/script_plugin.rs b/src/plugins/script_plugin.rs new file mode 100644 index 00000000..2be88e25 --- /dev/null +++ b/src/plugins/script_plugin.rs @@ -0,0 +1,57 @@ +use std::collections::HashMap; + +use regex::Regex; + +use plugin::{Plugin, PluginChain, PluginResult}; +use rbx::{RbxItem, RbxValue}; +use vfs::VfsItem; + +lazy_static! { + static ref SERVER_PATTERN: Regex = Regex::new(r"^(.*?)\.server\.lua$").unwrap(); + static ref CLIENT_PATTERN: Regex = Regex::new(r"^(.*?)\.client\.lua$").unwrap(); + static ref MODULE_PATTERN: Regex = Regex::new(r"^(.*?)\.lua$").unwrap(); +} + +pub struct ScriptPlugin; + +impl ScriptPlugin { + pub fn new() -> ScriptPlugin { + ScriptPlugin + } +} + +impl Plugin for ScriptPlugin { + fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> PluginResult { + match vfs_item { + &VfsItem::File { ref contents, ref name } => { + let (class_name, rbx_name) = { + if let Some(captures) = SERVER_PATTERN.captures(name) { + ("Script".to_string(), captures.get(1).unwrap().as_str().to_string()) + } else if let Some(captures) = CLIENT_PATTERN.captures(name) { + ("LocalScript".to_string(), captures.get(1).unwrap().as_str().to_string()) + } else if let Some(captures) = MODULE_PATTERN.captures(name) { + ("ModuleScript".to_string(), captures.get(1).unwrap().as_str().to_string()) + } else { + return PluginResult::Pass; + } + }; + + let mut properties = HashMap::new(); + + properties.insert("Source".to_string(), RbxValue::String { + value: contents.clone(), + }); + + PluginResult::Value(Some(RbxItem { + name: rbx_name, + class_name: class_name, + children: Vec::new(), + properties, + })) + }, + &VfsItem::Dir { ref children, ref name } => { + PluginResult::Pass + }, + } + } +} diff --git a/src/web.rs b/src/web.rs index aa069f6d..e6955c78 100644 --- a/src/web.rs +++ b/src/web.rs @@ -11,7 +11,7 @@ use project::Project; use vfs::{Vfs, VfsChange}; use rbx::RbxItem; use plugin::PluginChain; -use plugins::DefaultPlugin; +use plugins::{ScriptPlugin, DefaultPlugin}; static MAX_BODY_SIZE: usize = 25 * 1024 * 1025; // 25 MiB @@ -104,6 +104,7 @@ pub fn start(config: Config, project: Project, vfs: Arc>) { // Fine, rouille, I'll put things in a 'static Arc... lazy_static! { static ref PLUGIN_CHAIN: Arc> = Arc::new(Mutex::new(PluginChain::new(vec![ + Box::new(ScriptPlugin::new()), Box::new(DefaultPlugin::new()), ]))); } From d365bc076e05f37e83b0af6e9044c001be080e00 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Dec 2017 00:18:55 -0800 Subject: [PATCH 0035/1504] Add VfsItem::name to make comparisons easier --- src/vfs.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/vfs.rs b/src/vfs.rs index 81fb9c04..8b39ced4 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -41,6 +41,15 @@ pub enum VfsItem { Dir { name: String, children: HashMap }, } +impl VfsItem { + pub fn name(&self) -> &String { + match self { + &VfsItem::File { ref name, .. } => name, + &VfsItem::Dir { ref name, .. } => name, + } + } +} + impl Vfs { pub fn new(config: Config) -> Vfs { Vfs { From 12bfcd7b663c35b2fe21f217e0e4eed1d7c526e7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Dec 2017 00:19:07 -0800 Subject: [PATCH 0036/1504] Implement init.lua support in ScriptPlugin --- src/plugins/script_plugin.rs | 41 +++++++++++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/src/plugins/script_plugin.rs b/src/plugins/script_plugin.rs index 2be88e25..bda36bcf 100644 --- a/src/plugins/script_plugin.rs +++ b/src/plugins/script_plugin.rs @@ -12,6 +12,10 @@ lazy_static! { static ref MODULE_PATTERN: Regex = Regex::new(r"^(.*?)\.lua$").unwrap(); } +static SERVER_INIT: &'static str = "init.server.lua"; +static CLIENT_INIT: &'static str = "init.client.lua"; +static MODULE_INIT: &'static str = "init.lua"; + pub struct ScriptPlugin; impl ScriptPlugin { @@ -50,7 +54,42 @@ impl Plugin for ScriptPlugin { })) }, &VfsItem::Dir { ref children, ref name } => { - PluginResult::Pass + let init_item = { + let maybe_item = children.get(SERVER_INIT) + .or(children.get(CLIENT_INIT)) + .or(children.get(MODULE_INIT)); + + match maybe_item { + Some(v) => v, + None => return PluginResult::Pass, + } + }; + + let mut rbx_item = match self.transform_file(plugins, init_item) { + PluginResult::Value(Some(item)) => item, + _ => { + eprintln!("Inconsistency detected in ScriptPlugin!"); + return PluginResult::Pass; + }, + }; + + rbx_item.name.clear(); + rbx_item.name.push_str(name); + + for (child_name, child_item) in children { + if child_name == init_item.name() { + continue; + } + + match plugins.transform_file(child_item) { + Some(child_rbx_item) => { + rbx_item.children.push(child_rbx_item); + }, + _ => {}, + } + } + + PluginResult::Value(Some(rbx_item)) }, } } From ae6ca6fb231321770a4bd47769d23d120dc33acc Mon Sep 17 00:00:00 2001 From: James Onnen Date: Sun, 17 Dec 2017 14:20:24 -0600 Subject: [PATCH 0037/1504] Fix #21: High CPU usage in a small project --- src/bin.rs | 5 ++++- src/vfs_watch.rs | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index 4c42a4cf..b0ff3a68 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -22,6 +22,7 @@ pub mod vfs_watch; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; use std::thread; +use std::time::Duration; use core::Config; use pathext::canonicalish; @@ -193,7 +194,9 @@ fn main() { println!("Server listening on port {}", port); - loop {} + loop { + thread::sleep(Duration::from_secs(1)); + } }, ("pack", _) => { eprintln!("'rojo pack' is not yet implemented!"); diff --git a/src/vfs_watch.rs b/src/vfs_watch.rs index 697b9ff6..f28e200f 100644 --- a/src/vfs_watch.rs +++ b/src/vfs_watch.rs @@ -92,6 +92,8 @@ impl VfsWatcher { } } - loop {} + loop { + thread::sleep(Duration::from_secs(1)); + } } } From 199ebda68904f55d684eaea6aaaee6130ca16196 Mon Sep 17 00:00:00 2001 From: James Onnen Date: Sun, 17 Dec 2017 14:34:31 -0600 Subject: [PATCH 0038/1504] Use ::park() instead of ::sleep() --- src/bin.rs | 2 +- src/vfs_watch.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index b0ff3a68..9422c62c 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -195,7 +195,7 @@ fn main() { println!("Server listening on port {}", port); loop { - thread::sleep(Duration::from_secs(1)); + thread::park(); } }, ("pack", _) => { diff --git a/src/vfs_watch.rs b/src/vfs_watch.rs index f28e200f..872ba683 100644 --- a/src/vfs_watch.rs +++ b/src/vfs_watch.rs @@ -93,7 +93,7 @@ impl VfsWatcher { } loop { - thread::sleep(Duration::from_secs(1)); + thread::park(); } } } From 5a20646c570be931f114789330ae28bc813b9d2e Mon Sep 17 00:00:00 2001 From: James Onnen Date: Sun, 17 Dec 2017 23:40:32 -0600 Subject: [PATCH 0039/1504] Address code review, remove unnecessary import --- src/bin.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bin.rs b/src/bin.rs index 9422c62c..b04500a9 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -22,7 +22,6 @@ pub mod vfs_watch; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; use std::thread; -use std::time::Duration; use core::Config; use pathext::canonicalish; From 6472a2cbcea47d6a08cc0db922b9dc8c11c0172a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 17 Dec 2017 22:46:56 -0800 Subject: [PATCH 0040/1504] Add handle_file_change to plugin API This solves the problem I was running into with the ScriptPlugin implementation -- if foo/init.lua changes, foo needs to be requested, not 'foo/init.lua' (which would then erroneously create a ModuleScript before this commit) --- src/core.rs | 2 ++ src/plugin.rs | 15 ++++++++++---- src/plugins/default_plugin.rs | 13 ++++++++---- src/plugins/script_plugin.rs | 37 +++++++++++++++++++++++++++-------- 4 files changed, 51 insertions(+), 16 deletions(-) diff --git a/src/core.rs b/src/core.rs index 6d83d3cd..8300fe0b 100644 --- a/src/core.rs +++ b/src/core.rs @@ -4,3 +4,5 @@ pub struct Config { pub verbose: bool, pub server_id: u64, } + +pub type Route = Vec; diff --git a/src/plugin.rs b/src/plugin.rs index 6c2f6246..fa56a701 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -1,13 +1,20 @@ use rbx::RbxItem; use vfs::VfsItem; +use core::Route; -pub enum PluginResult { +pub enum TransformResult { Value(Option), Pass, } +pub enum FileChangeResult { + MarkChanged(Option>), + Pass, +} + pub trait Plugin { - fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> PluginResult; + fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformResult; + fn handle_file_change(&self, route: &Route) -> FileChangeResult; } pub struct PluginChain { @@ -24,8 +31,8 @@ impl PluginChain { pub fn transform_file(&self, vfs_item: &VfsItem) -> Option { for plugin in &self.plugins { match plugin.transform_file(self, vfs_item) { - PluginResult::Value(rbx_item) => return rbx_item, - PluginResult::Pass => {}, + TransformResult::Value(rbx_item) => return rbx_item, + TransformResult::Pass => {}, } } diff --git a/src/plugins/default_plugin.rs b/src/plugins/default_plugin.rs index 92ce1104..b3ac5289 100644 --- a/src/plugins/default_plugin.rs +++ b/src/plugins/default_plugin.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; -use plugin::{Plugin, PluginChain, PluginResult}; +use core::Route; +use plugin::{Plugin, PluginChain, TransformResult, FileChangeResult}; use rbx::{RbxItem, RbxValue}; use vfs::VfsItem; @@ -16,7 +17,7 @@ impl DefaultPlugin { } impl Plugin for DefaultPlugin { - fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> PluginResult { + fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformResult { match vfs_item { &VfsItem::File { ref contents, ref name } => { let mut properties = HashMap::new(); @@ -25,7 +26,7 @@ impl Plugin for DefaultPlugin { value: contents.clone(), }); - PluginResult::Value(Some(RbxItem { + TransformResult::Value(Some(RbxItem { name: name.clone(), class_name: "StringValue".to_string(), children: Vec::new(), @@ -44,7 +45,7 @@ impl Plugin for DefaultPlugin { } } - PluginResult::Value(Some(RbxItem { + TransformResult::Value(Some(RbxItem { name: name.clone(), class_name: "Folder".to_string(), children: rbx_children, @@ -53,4 +54,8 @@ impl Plugin for DefaultPlugin { }, } } + + fn handle_file_change(&self, route: &Route) -> FileChangeResult { + FileChangeResult::MarkChanged(Some(vec![route.clone()])) + } } diff --git a/src/plugins/script_plugin.rs b/src/plugins/script_plugin.rs index bda36bcf..75d78e42 100644 --- a/src/plugins/script_plugin.rs +++ b/src/plugins/script_plugin.rs @@ -2,7 +2,8 @@ use std::collections::HashMap; use regex::Regex; -use plugin::{Plugin, PluginChain, PluginResult}; +use core::Route; +use plugin::{Plugin, PluginChain, TransformResult, FileChangeResult}; use rbx::{RbxItem, RbxValue}; use vfs::VfsItem; @@ -25,7 +26,7 @@ impl ScriptPlugin { } impl Plugin for ScriptPlugin { - fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> PluginResult { + fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformResult { match vfs_item { &VfsItem::File { ref contents, ref name } => { let (class_name, rbx_name) = { @@ -36,7 +37,7 @@ impl Plugin for ScriptPlugin { } else if let Some(captures) = MODULE_PATTERN.captures(name) { ("ModuleScript".to_string(), captures.get(1).unwrap().as_str().to_string()) } else { - return PluginResult::Pass; + return TransformResult::Pass; } }; @@ -46,7 +47,7 @@ impl Plugin for ScriptPlugin { value: contents.clone(), }); - PluginResult::Value(Some(RbxItem { + TransformResult::Value(Some(RbxItem { name: rbx_name, class_name: class_name, children: Vec::new(), @@ -61,15 +62,15 @@ impl Plugin for ScriptPlugin { match maybe_item { Some(v) => v, - None => return PluginResult::Pass, + None => return TransformResult::Pass, } }; let mut rbx_item = match self.transform_file(plugins, init_item) { - PluginResult::Value(Some(item)) => item, + TransformResult::Value(Some(item)) => item, _ => { eprintln!("Inconsistency detected in ScriptPlugin!"); - return PluginResult::Pass; + return TransformResult::Pass; }, }; @@ -89,8 +90,28 @@ impl Plugin for ScriptPlugin { } } - PluginResult::Value(Some(rbx_item)) + TransformResult::Value(Some(rbx_item)) }, } } + + fn handle_file_change(&self, route: &Route) -> FileChangeResult { + let leaf = match route.last() { + Some(v) => v, + None => return FileChangeResult::Pass, + }; + + let is_init = leaf == SERVER_INIT + || leaf == CLIENT_INIT + || leaf == MODULE_INIT; + + if is_init { + let mut changed = route.clone(); + changed.pop(); + + FileChangeResult::MarkChanged(Some(vec![changed])) + } else { + FileChangeResult::Pass + } + } } From f90c51e9237c2a20ec9f34534def2046a5f1be1b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 18 Dec 2017 01:20:04 -0800 Subject: [PATCH 0041/1504] Move web server onto main thread --- src/bin.rs | 6 +-- src/web.rs | 138 ++++++++++++++++++++++++++--------------------------- 2 files changed, 69 insertions(+), 75 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index e759a753..18378c7f 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -196,13 +196,9 @@ fn main() { }); } - web::start(config.clone(), project.clone(), vfs.clone()); - println!("Server listening on port {}", port); - loop { - thread::park(); - } + web::start(config.clone(), project.clone(), vfs.clone()); }, ("pack", _) => { eprintln!("'rojo pack' is not yet implemented!"); diff --git a/src/web.rs b/src/web.rs index e6955c78..f15dc7e1 100644 --- a/src/web.rs +++ b/src/web.rs @@ -109,85 +109,83 @@ pub fn start(config: Config, project: Project, vfs: Arc>) { ]))); } - thread::spawn(move || { - rouille::start_server(address, move |request| { - router!(request, - (GET) (/) => { - let current_time = { - let vfs = vfs.lock().unwrap(); - - vfs.current_time() - }; - - json(ServerInfo { - server_version: env!("CARGO_PKG_VERSION"), - protocol_version: 1, - server_id: &server_id, - project: &project, - current_time, - }) - }, - - (GET) (/changes/{ last_time: f64 }) => { + rouille::start_server(address, move |request| { + router!(request, + (GET) (/) => { + let current_time = { let vfs = vfs.lock().unwrap(); + + vfs.current_time() + }; + + json(ServerInfo { + server_version: env!("CARGO_PKG_VERSION"), + protocol_version: 1, + server_id: &server_id, + project: &project, + current_time, + }) + }, + + (GET) (/changes/{ last_time: f64 }) => { + let vfs = vfs.lock().unwrap(); + let current_time = vfs.current_time(); + let changes = vfs.changes_since(last_time); + + json(ChangesResult { + changes, + server_id: &server_id, + current_time, + }) + }, + + (POST) (/read) => { + let plugin_chain = PLUGIN_CHAIN.lock().unwrap(); + + let read_request: Vec> = match read_json(&request) { + Some(v) => v, + None => return rouille::Response::empty_400(), + }; + + let (items, current_time) = { + let vfs = vfs.lock().unwrap(); + let current_time = vfs.current_time(); - let changes = vfs.changes_since(last_time); - json(ChangesResult { - changes, - server_id: &server_id, - current_time, - }) - }, + let mut items = Vec::new(); - (POST) (/read) => { - let plugin_chain = PLUGIN_CHAIN.lock().unwrap(); - - let read_request: Vec> = match read_json(&request) { - Some(v) => v, - None => return rouille::Response::empty_400(), - }; - - let (items, current_time) = { - let vfs = vfs.lock().unwrap(); - - let current_time = vfs.current_time(); - - let mut items = Vec::new(); - - for route in &read_request { - match vfs.read(&route) { - Ok(v) => items.push(Some(v)), - Err(_) => items.push(None), - } + for route in &read_request { + match vfs.read(&route) { + Ok(v) => items.push(Some(v)), + Err(_) => items.push(None), } + } - (items, current_time) - }; + (items, current_time) + }; - let rbx_items = items - .iter() - .map(|item| { - match *item { - Some(ref item) => plugin_chain.transform_file(item), - None => None, - } - }) - .collect::>(); - - json(ReadResult { - server_id: &server_id, - items: rbx_items, - current_time, + let rbx_items = items + .iter() + .map(|item| { + match *item { + Some(ref item) => plugin_chain.transform_file(item), + None => None, + } }) - }, + .collect::>(); - (POST) (/write) => { - rouille::Response::empty_404() - }, + json(ReadResult { + server_id: &server_id, + items: rbx_items, + current_time, + }) + }, - _ => rouille::Response::empty_404() - ) - }); + (POST) (/write) => { + rouille::Response::empty_404() + }, + + _ => rouille::Response::empty_404() + ) }); } From 6ee9a48e20b990ec785a00f377d3f66f1c42bb4a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 18 Dec 2017 01:52:08 -0800 Subject: [PATCH 0042/1504] Use plugin chain code in Vfs --- src/bin.rs | 11 ++++++++++- src/plugin.rs | 15 +++++++++++++-- src/vfs.rs | 23 +++++++++++++++++------ src/web.rs | 1 - 4 files changed, 40 insertions(+), 10 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index 18378c7f..57520201 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -33,6 +33,8 @@ use std::thread; use core::Config; use pathext::canonicalish; use project::{Project, ProjectLoadError}; +use plugin::{PluginChain}; +use plugins::{DefaultPlugin, ScriptPlugin}; use vfs::Vfs; use vfs_watch::VfsWatcher; @@ -148,6 +150,13 @@ fn main() { } }; + lazy_static! { + static ref PLUGIN_CHAIN: PluginChain = PluginChain::new(vec![ + Box::new(ScriptPlugin::new()), + Box::new(DefaultPlugin::new()), + ]); + } + let config = Config { port, verbose, @@ -159,7 +168,7 @@ fn main() { } let vfs = { - let mut vfs = Vfs::new(config.clone()); + let mut vfs = Vfs::new(config.clone(), &PLUGIN_CHAIN); for (name, project_partition) in &project.partitions { let path = { diff --git a/src/plugin.rs b/src/plugin.rs index fa56a701..cd0c90a8 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -18,11 +18,11 @@ pub trait Plugin { } pub struct PluginChain { - plugins: Vec>, + plugins: Vec>, } impl PluginChain { - pub fn new(plugins: Vec>) -> PluginChain { + pub fn new(plugins: Vec>) -> PluginChain { PluginChain { plugins, } @@ -38,4 +38,15 @@ impl PluginChain { None } + + pub fn handle_file_change(&self, route: &Route) -> Option> { + for plugin in &self.plugins { + match plugin.handle_file_change(route) { + FileChangeResult::MarkChanged(changes) => return changes, + FileChangeResult::Pass => {}, + } + } + + None + } } diff --git a/src/vfs.rs b/src/vfs.rs index 8b39ced4..483a93b2 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -6,6 +6,7 @@ use std::path::{Path, PathBuf}; use std::time::Instant; use core::Config; +use plugin::PluginChain; /// Represents a virtual layer over multiple parts of the filesystem. /// @@ -24,6 +25,8 @@ pub struct Vfs { /// created, along with a timestamp denoting when. pub change_history: Vec, + plugin_chain: &'static PluginChain, + config: Config, } @@ -51,11 +54,12 @@ impl VfsItem { } impl Vfs { - pub fn new(config: Config) -> Vfs { + pub fn new(config: Config, plugin_chain: &'static PluginChain) -> Vfs { Vfs { partitions: HashMap::new(), start_time: Instant::now(), change_history: Vec::new(), + plugin_chain, config, } } @@ -164,13 +168,20 @@ impl Vfs { pub fn add_change(&mut self, timestamp: f64, route: Vec) { if self.config.verbose { - println!("Added change {:?}", route); + println!("Received change {:?}, running through plugins...", route); } - self.change_history.push(VfsChange { - timestamp, - route, - }); + match self.plugin_chain.handle_file_change(&route) { + Some(routes) => { + for route in routes { + self.change_history.push(VfsChange { + timestamp, + route, + }); + } + }, + None => {} + } } pub fn changes_since(&self, timestamp: f64) -> &[VfsChange] { diff --git a/src/web.rs b/src/web.rs index f15dc7e1..2a0e1118 100644 --- a/src/web.rs +++ b/src/web.rs @@ -1,6 +1,5 @@ use std::io::Read; use std::sync::{Arc, Mutex}; -use std::thread; use rouille; use serde; From 0f78eb933a3a5202ae41b80281e899ee876325b6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 20 Dec 2017 22:00:01 -0800 Subject: [PATCH 0043/1504] DESIGN doc, stub out /write endpoint --- DESIGN.md | 20 ++++++++++++++++++++ src/rbx.rs | 4 ++-- src/web.rs | 14 ++++++++++++++ 3 files changed, 36 insertions(+), 2 deletions(-) create mode 100644 DESIGN.md diff --git a/DESIGN.md b/DESIGN.md new file mode 100644 index 00000000..a3366429 --- /dev/null +++ b/DESIGN.md @@ -0,0 +1,20 @@ +# Rojo Design +This is a super rough draft that I'm trying to use to lay out of my thoughts. + +## API + +### POST `/read` +Accepts a `Vec` of items to read. + +Returns `Vec>`, in the same order as the request. + +### POST `/write` +Accepts a `Vec<{ Route, RbxItem }>` of items to write. + +I imagine that the `Name` attribute of the top-level `RbxItem` would be ignored in favor of the route name? + +## CLI + +### Transform Plugins + +## Roblox Studio Plugin \ No newline at end of file diff --git a/src/rbx.rs b/src/rbx.rs index 043dc3b6..234529ca 100644 --- a/src/rbx.rs +++ b/src/rbx.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -#[derive(Debug, Serialize)] +#[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RbxItem { pub name: String, @@ -9,7 +9,7 @@ pub struct RbxItem { pub properties: HashMap, } -#[derive(Debug, Serialize)] +#[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase", tag = "type")] pub enum RbxValue { String { diff --git a/src/web.rs b/src/web.rs index 2a0e1118..f4237a1e 100644 --- a/src/web.rs +++ b/src/web.rs @@ -40,6 +40,13 @@ struct ChangesResult<'a> { current_time: f64, } +#[derive(Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +struct WriteSpecifier { + route: String, + item: RbxItem, +} + fn json(value: T) -> rouille::Response { let data = serde_json::to_string(&value).unwrap(); rouille::Response::from_data("application/json", data) @@ -181,6 +188,13 @@ pub fn start(config: Config, project: Project, vfs: Arc>) { }, (POST) (/write) => { + let _plugin_chain = PLUGIN_CHAIN.lock().unwrap(); + + let _write_request: Vec = match read_json(&request) { + Some(v) => v, + None => return rouille::Response::empty_400(), + }; + rouille::Response::empty_404() }, From b885cae0864c662d604dd482efa4d9a705596418 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 20 Dec 2017 22:01:38 -0800 Subject: [PATCH 0044/1504] Rename TransformResult -> TransformFileResult in preparation for two-way syncing --- src/plugin.rs | 8 ++++---- src/plugins/default_plugin.rs | 8 ++++---- src/plugins/script_plugin.rs | 16 ++++++++-------- 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/plugin.rs b/src/plugin.rs index cd0c90a8..3686ffb8 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -2,7 +2,7 @@ use rbx::RbxItem; use vfs::VfsItem; use core::Route; -pub enum TransformResult { +pub enum TransformFileResult { Value(Option), Pass, } @@ -13,7 +13,7 @@ pub enum FileChangeResult { } pub trait Plugin { - fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformResult; + fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult; fn handle_file_change(&self, route: &Route) -> FileChangeResult; } @@ -31,8 +31,8 @@ impl PluginChain { pub fn transform_file(&self, vfs_item: &VfsItem) -> Option { for plugin in &self.plugins { match plugin.transform_file(self, vfs_item) { - TransformResult::Value(rbx_item) => return rbx_item, - TransformResult::Pass => {}, + TransformFileResult::Value(rbx_item) => return rbx_item, + TransformFileResult::Pass => {}, } } diff --git a/src/plugins/default_plugin.rs b/src/plugins/default_plugin.rs index b3ac5289..11bab5a9 100644 --- a/src/plugins/default_plugin.rs +++ b/src/plugins/default_plugin.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use core::Route; -use plugin::{Plugin, PluginChain, TransformResult, FileChangeResult}; +use plugin::{Plugin, PluginChain, TransformFileResult, FileChangeResult}; use rbx::{RbxItem, RbxValue}; use vfs::VfsItem; @@ -17,7 +17,7 @@ impl DefaultPlugin { } impl Plugin for DefaultPlugin { - fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformResult { + fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult { match vfs_item { &VfsItem::File { ref contents, ref name } => { let mut properties = HashMap::new(); @@ -26,7 +26,7 @@ impl Plugin for DefaultPlugin { value: contents.clone(), }); - TransformResult::Value(Some(RbxItem { + TransformFileResult::Value(Some(RbxItem { name: name.clone(), class_name: "StringValue".to_string(), children: Vec::new(), @@ -45,7 +45,7 @@ impl Plugin for DefaultPlugin { } } - TransformResult::Value(Some(RbxItem { + TransformFileResult::Value(Some(RbxItem { name: name.clone(), class_name: "Folder".to_string(), children: rbx_children, diff --git a/src/plugins/script_plugin.rs b/src/plugins/script_plugin.rs index 75d78e42..a6932392 100644 --- a/src/plugins/script_plugin.rs +++ b/src/plugins/script_plugin.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use regex::Regex; use core::Route; -use plugin::{Plugin, PluginChain, TransformResult, FileChangeResult}; +use plugin::{Plugin, PluginChain, TransformFileResult, FileChangeResult}; use rbx::{RbxItem, RbxValue}; use vfs::VfsItem; @@ -26,7 +26,7 @@ impl ScriptPlugin { } impl Plugin for ScriptPlugin { - fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformResult { + fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult { match vfs_item { &VfsItem::File { ref contents, ref name } => { let (class_name, rbx_name) = { @@ -37,7 +37,7 @@ impl Plugin for ScriptPlugin { } else if let Some(captures) = MODULE_PATTERN.captures(name) { ("ModuleScript".to_string(), captures.get(1).unwrap().as_str().to_string()) } else { - return TransformResult::Pass; + return TransformFileResult::Pass; } }; @@ -47,7 +47,7 @@ impl Plugin for ScriptPlugin { value: contents.clone(), }); - TransformResult::Value(Some(RbxItem { + TransformFileResult::Value(Some(RbxItem { name: rbx_name, class_name: class_name, children: Vec::new(), @@ -62,15 +62,15 @@ impl Plugin for ScriptPlugin { match maybe_item { Some(v) => v, - None => return TransformResult::Pass, + None => return TransformFileResult::Pass, } }; let mut rbx_item = match self.transform_file(plugins, init_item) { - TransformResult::Value(Some(item)) => item, + TransformFileResult::Value(Some(item)) => item, _ => { eprintln!("Inconsistency detected in ScriptPlugin!"); - return TransformResult::Pass; + return TransformFileResult::Pass; }, }; @@ -90,7 +90,7 @@ impl Plugin for ScriptPlugin { } } - TransformResult::Value(Some(rbx_item)) + TransformFileResult::Value(Some(rbx_item)) }, } } From aaaf3ba0b9253278aa103debdb37e2395b21003f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 20 Dec 2017 22:11:46 -0800 Subject: [PATCH 0045/1504] Implement handle_rbx_change API for plugins as a pass --- src/plugin.rs | 17 +++++++++++++++++ src/plugins/default_plugin.rs | 6 +++++- src/plugins/script_plugin.rs | 6 +++++- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/src/plugin.rs b/src/plugin.rs index 3686ffb8..2a6e34a6 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -7,6 +7,11 @@ pub enum TransformFileResult { Pass, } +pub enum RbxChangeResult { + Write(Option), + Pass, +} + pub enum FileChangeResult { MarkChanged(Option>), Pass, @@ -14,6 +19,7 @@ pub enum FileChangeResult { pub trait Plugin { fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult; + fn handle_rbx_change(&self, route: &Route, rbx_item: &RbxItem) -> RbxChangeResult; fn handle_file_change(&self, route: &Route) -> FileChangeResult; } @@ -39,6 +45,17 @@ impl PluginChain { None } + pub fn handle_rbx_change(&self, route: &Route, rbx_item: &RbxItem) -> Option { + for plugin in &self.plugins { + match plugin.handle_rbx_change(route, rbx_item) { + RbxChangeResult::Write(vfs_item) => return vfs_item, + RbxChangeResult::Pass => {}, + } + } + + None + } + pub fn handle_file_change(&self, route: &Route) -> Option> { for plugin in &self.plugins { match plugin.handle_file_change(route) { diff --git a/src/plugins/default_plugin.rs b/src/plugins/default_plugin.rs index 11bab5a9..b9503877 100644 --- a/src/plugins/default_plugin.rs +++ b/src/plugins/default_plugin.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use core::Route; -use plugin::{Plugin, PluginChain, TransformFileResult, FileChangeResult}; +use plugin::{Plugin, PluginChain, TransformFileResult, RbxChangeResult, FileChangeResult}; use rbx::{RbxItem, RbxValue}; use vfs::VfsItem; @@ -58,4 +58,8 @@ impl Plugin for DefaultPlugin { fn handle_file_change(&self, route: &Route) -> FileChangeResult { FileChangeResult::MarkChanged(Some(vec![route.clone()])) } + + fn handle_rbx_change(&self, route: &Route, rbx_item: &RbxItem) -> RbxChangeResult { + RbxChangeResult::Pass + } } diff --git a/src/plugins/script_plugin.rs b/src/plugins/script_plugin.rs index a6932392..70cdc059 100644 --- a/src/plugins/script_plugin.rs +++ b/src/plugins/script_plugin.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use regex::Regex; use core::Route; -use plugin::{Plugin, PluginChain, TransformFileResult, FileChangeResult}; +use plugin::{Plugin, PluginChain, TransformFileResult, RbxChangeResult, FileChangeResult}; use rbx::{RbxItem, RbxValue}; use vfs::VfsItem; @@ -114,4 +114,8 @@ impl Plugin for ScriptPlugin { FileChangeResult::Pass } } + + fn handle_rbx_change(&self, route: &Route, rbx_item: &RbxItem) -> RbxChangeResult { + RbxChangeResult::Pass + } } From 95581dbaa6a3b60ab61643105b247ae21e0687c8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 20 Dec 2017 22:35:26 -0800 Subject: [PATCH 0046/1504] Pass common plugin chain into web handler --- src/bin.rs | 2 +- src/web.rs | 15 +-------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index 57520201..4cc0aa1c 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -207,7 +207,7 @@ fn main() { println!("Server listening on port {}", port); - web::start(config.clone(), project.clone(), vfs.clone()); + web::start(config.clone(), project.clone(), &PLUGIN_CHAIN, vfs.clone()); }, ("pack", _) => { eprintln!("'rojo pack' is not yet implemented!"); diff --git a/src/web.rs b/src/web.rs index f4237a1e..c9aef861 100644 --- a/src/web.rs +++ b/src/web.rs @@ -10,7 +10,6 @@ use project::Project; use vfs::{Vfs, VfsChange}; use rbx::RbxItem; use plugin::PluginChain; -use plugins::{ScriptPlugin, DefaultPlugin}; static MAX_BODY_SIZE: usize = 25 * 1024 * 1025; // 25 MiB @@ -102,19 +101,11 @@ where Some(parsed) } -pub fn start(config: Config, project: Project, vfs: Arc>) { +pub fn start(config: Config, project: Project, plugin_chain: &'static PluginChain, vfs: Arc>) { let address = format!("localhost:{}", config.port); let server_id = config.server_id.to_string(); - // Fine, rouille, I'll put things in a 'static Arc... - lazy_static! { - static ref PLUGIN_CHAIN: Arc> = Arc::new(Mutex::new(PluginChain::new(vec![ - Box::new(ScriptPlugin::new()), - Box::new(DefaultPlugin::new()), - ]))); - } - rouille::start_server(address, move |request| { router!(request, (GET) (/) => { @@ -146,8 +137,6 @@ pub fn start(config: Config, project: Project, vfs: Arc>) { }, (POST) (/read) => { - let plugin_chain = PLUGIN_CHAIN.lock().unwrap(); - let read_request: Vec> = match read_json(&request) { Some(v) => v, None => return rouille::Response::empty_400(), @@ -188,8 +177,6 @@ pub fn start(config: Config, project: Project, vfs: Arc>) { }, (POST) (/write) => { - let _plugin_chain = PLUGIN_CHAIN.lock().unwrap(); - let _write_request: Vec = match read_json(&request) { Some(v) => v, None => return rouille::Response::empty_400(), From 68ba3fee6c6857192367991640ae7025fea74ba1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 20 Dec 2017 22:36:12 -0800 Subject: [PATCH 0047/1504] Fix max body size typo --- src/web.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web.rs b/src/web.rs index c9aef861..65024b18 100644 --- a/src/web.rs +++ b/src/web.rs @@ -11,7 +11,7 @@ use vfs::{Vfs, VfsChange}; use rbx::RbxItem; use plugin::PluginChain; -static MAX_BODY_SIZE: usize = 25 * 1024 * 1025; // 25 MiB +static MAX_BODY_SIZE: usize = 25 * 1024 * 1024; // 25 MiB #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] From 13925f5879665f9eb8eb4f7f86ea0bf6b6a36720 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 20 Dec 2017 22:41:23 -0800 Subject: [PATCH 0048/1504] Publish 0.3.2 --- CHANGES.md | 3 +++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index dfc0d178..aa8f2a57 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,9 @@ # Rojo Change Log ## Current Master +* No changes + +## 0.3.2 * Fixed `rojo serve` failing to correctly construct an absolute root path when passed as an argument ## 0.3.1 diff --git a/Cargo.lock b/Cargo.lock index fe831498..54425c46 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -517,7 +517,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rojo" -version = "0.3.1" +version = "0.3.2" dependencies = [ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index a1e34642..bc492d2b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.3.1" +version = "0.3.2" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From e731811911ebaf877bda26c91b6b31e32b5b68cd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 20 Dec 2017 22:54:10 -0800 Subject: [PATCH 0049/1504] Add changes from serve-instances merge --- CHANGES.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index aa8f2a57..bccf1aa1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,9 @@ # Rojo Change Log ## Current Master -* No changes +* Began protocol version 1, which shifts more responsibility onto the server + * The server now has a content of 'filter plugins', which transform data at various stages in the pipeline + * The server now exposes Roblox instance objects instead of file contents, which lines up with how `rojo pack` will work, and paves the way for more robust syncing. ## 0.3.2 * Fixed `rojo serve` failing to correctly construct an absolute root path when passed as an argument From 958b6660be22d57242defc9f74fbdfcaa5292086 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 20 Dec 2017 23:00:48 -0800 Subject: [PATCH 0050/1504] Update README and DESIGN --- DESIGN.md | 21 ++++++++++++++++++--- README.md | 2 ++ 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index a3366429..f14e86e2 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -1,5 +1,5 @@ -# Rojo Design -This is a super rough draft that I'm trying to use to lay out of my thoughts. +# Rojo Design - Protocol Version 1 +This is a super rough draft that I'm trying to use to lay out some of my thoughts. ## API @@ -16,5 +16,20 @@ I imagine that the `Name` attribute of the top-level `RbxItem` would be ignored ## CLI ### Transform Plugins +Transform plugins (or filter plugins?) can interject in three places: +* Transform a `VfsItem` that's being read into an `RbxItem` +* Transform an `Rbxitem` that's being written into a `VfsItem` +* Transform a file change into paths that need to be updated -## Roblox Studio Plugin \ No newline at end of file +The plan is to have several built-in plugins that can be rearranged/configured in project settings: + +* Base plugin + * Transforms all unhandled files to/from StringValue objects +* Script plugin + * Transforms `*.lua` files to their appropriate file types +* JSON/rbxmx/rbxlx model plugin +* External binary plugin + * User passes a binary name (like `moonc`) that modifies file contents + +## Roblox Studio Plugin +With the protocol version 1 change, the Roblox Studio plugin got a lot simpler. Notably, the plugin doesn't need to be aware of anything about the filesystem's semantics, which is super handy. \ No newline at end of file diff --git a/README.md b/README.md index 4cfb5dac..e1454d67 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,8 @@ It's designed for power users who want to use the **best tools available** for b This is the main Rojo repository, containing the binary server component. For the source for the Roblox plugin, [see the rojo-plugin repository](https://github.com/LPGhatguy/rojo-plugin). +The master branches of both respositories should always pass all tests and be functional, but are not suitable for production use! + ## Features Rojo has a number of desirable features *right now*: From 7a372dc50cbbbbf916f1afdf697d6f6ec6102f8c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 21 Dec 2017 14:21:03 -0800 Subject: [PATCH 0051/1504] Add forgotten change about CPU usage --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index bccf1aa1..132b42c0 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -7,6 +7,7 @@ ## 0.3.2 * Fixed `rojo serve` failing to correctly construct an absolute root path when passed as an argument +* Fixed intense CPU usage when running `rojo serve` ## 0.3.1 * Improved error reporting when invalid JSON is found in a `rojo.json` project From 5e98cbe68fc374a9f94f82b1581aeb4f3047c225 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 21 Dec 2017 16:10:47 -0800 Subject: [PATCH 0052/1504] More detail in DESIGN.md --- DESIGN.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index f14e86e2..46ad11a0 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -14,12 +14,16 @@ Accepts a `Vec<{ Route, RbxItem }>` of items to write. I imagine that the `Name` attribute of the top-level `RbxItem` would be ignored in favor of the route name? ## CLI +The `rojo serve` command uses three major components: +* A Virtual Filesystem (VFS), which exposes the filesystem as `VfsItem` objects +* A VFS watcher, which tracks changes to the filesystem and logs them +* An HTTP API, which exposes an interface to the Roblox Studio plugin ### Transform Plugins Transform plugins (or filter plugins?) can interject in three places: -* Transform a `VfsItem` that's being read into an `RbxItem` -* Transform an `Rbxitem` that's being written into a `VfsItem` -* Transform a file change into paths that need to be updated +* Transform a `VfsItem` that's being read into an `RbxItem` in the VFS +* Transform an `Rbxitem` that's being written into a `VfsItem` in the VFS +* Transform a file change into paths that need to be updated in the VFS watcher The plan is to have several built-in plugins that can be rearranged/configured in project settings: From fe240ed57791a9a521b834177ffe382928daf3aa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 21 Dec 2017 17:09:32 -0800 Subject: [PATCH 0053/1504] Prototype JsonModelPlugin, untested Also cleaned up all of the warnings in the other plugin code --- src/plugin.rs | 1 + src/plugins/default_plugin.rs | 2 +- src/plugins/json_model_plugin.rs | 52 ++++++++++++++++++++++++++++++++ src/plugins/mod.rs | 2 ++ src/plugins/script_plugin.rs | 2 +- 5 files changed, 57 insertions(+), 2 deletions(-) create mode 100644 src/plugins/json_model_plugin.rs diff --git a/src/plugin.rs b/src/plugin.rs index 2a6e34a6..5b80f084 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -2,6 +2,7 @@ use rbx::RbxItem; use vfs::VfsItem; use core::Route; +// TODO: Add error case? pub enum TransformFileResult { Value(Option), Pass, diff --git a/src/plugins/default_plugin.rs b/src/plugins/default_plugin.rs index b9503877..a503fbe8 100644 --- a/src/plugins/default_plugin.rs +++ b/src/plugins/default_plugin.rs @@ -59,7 +59,7 @@ impl Plugin for DefaultPlugin { FileChangeResult::MarkChanged(Some(vec![route.clone()])) } - fn handle_rbx_change(&self, route: &Route, rbx_item: &RbxItem) -> RbxChangeResult { + fn handle_rbx_change(&self, _route: &Route, _rbx_item: &RbxItem) -> RbxChangeResult { RbxChangeResult::Pass } } diff --git a/src/plugins/json_model_plugin.rs b/src/plugins/json_model_plugin.rs new file mode 100644 index 00000000..137560c8 --- /dev/null +++ b/src/plugins/json_model_plugin.rs @@ -0,0 +1,52 @@ +use regex::Regex; +use serde_json; + +use core::Route; +use plugin::{Plugin, PluginChain, TransformFileResult, RbxChangeResult, FileChangeResult}; +use rbx::{RbxItem, RbxValue}; +use vfs::VfsItem; + +lazy_static! { + static ref JSON_MODEL_PATTERN: Regex = Regex::new(r"^(.*?)\.model\.json$").unwrap(); +} + +pub struct JsonModelPlugin; + +impl JsonModelPlugin { + pub fn new() -> JsonModelPlugin { + JsonModelPlugin + } +} + +impl Plugin for JsonModelPlugin { + fn transform_file(&self, _plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult { + match vfs_item { + &VfsItem::File { ref contents, ref name } => { + let rbx_name = match JSON_MODEL_PATTERN.captures(name) { + Some(captures) => captures.get(1).unwrap().as_str().to_string(), + None => return TransformFileResult::Pass, + }; + + let mut rbx_item: RbxItem = match serde_json::from_str(contents) { + Ok(v) => v, + Err(_) => return TransformFileResult::Pass, // This should be an error in the future + }; + + rbx_item.properties.insert("Name".to_string(), RbxValue::String { + value: rbx_name, + }); + + TransformFileResult::Value(Some(rbx_item)) + }, + &VfsItem::Dir { .. } => TransformFileResult::Pass, + } + } + + fn handle_file_change(&self, _route: &Route) -> FileChangeResult { + FileChangeResult::Pass + } + + fn handle_rbx_change(&self, _route: &Route, _rbx_item: &RbxItem) -> RbxChangeResult { + RbxChangeResult::Pass + } +} diff --git a/src/plugins/mod.rs b/src/plugins/mod.rs index dd39b2db..73482635 100644 --- a/src/plugins/mod.rs +++ b/src/plugins/mod.rs @@ -1,5 +1,7 @@ mod default_plugin; mod script_plugin; +mod json_model_plugin; pub use self::default_plugin::*; pub use self::script_plugin::*; +pub use self::json_model_plugin::*; diff --git a/src/plugins/script_plugin.rs b/src/plugins/script_plugin.rs index 70cdc059..38bd746a 100644 --- a/src/plugins/script_plugin.rs +++ b/src/plugins/script_plugin.rs @@ -115,7 +115,7 @@ impl Plugin for ScriptPlugin { } } - fn handle_rbx_change(&self, route: &Route, rbx_item: &RbxItem) -> RbxChangeResult { + fn handle_rbx_change(&self, _route: &Route, _rbx_item: &RbxItem) -> RbxChangeResult { RbxChangeResult::Pass } } From d7e2a3542c042aa1b32335e8a465e21ec81ac8bc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 2 Jan 2018 14:52:51 -0800 Subject: [PATCH 0054/1504] Make notes about compatibility breakage and version 0.4.0 --- CHANGES.md | 3 ++- Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 132b42c0..a989a369 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,8 @@ # Rojo Change Log -## Current Master +## Current Master (0.4.0) * Began protocol version 1, which shifts more responsibility onto the server + * This is a **major breaking** change! * The server now has a content of 'filter plugins', which transform data at various stages in the pipeline * The server now exposes Roblox instance objects instead of file contents, which lines up with how `rojo pack` will work, and paves the way for more robust syncing. diff --git a/Cargo.lock b/Cargo.lock index fa8723f8..d88291a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -555,7 +555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rojo" -version = "0.3.2" +version = "0.4.0" dependencies = [ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index cab5b988..90071e05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.3.2" +version = "0.4.0" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 73117edbe7944652e8626132848fb05e54205e31 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 2 Jan 2018 15:41:10 -0800 Subject: [PATCH 0055/1504] Enable JsonModelPlugin by default as a test --- src/bin.rs | 3 ++- src/plugins/json_model_plugin.rs | 6 +++++- test-project/src/hello.model.json | 24 ++++++++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) create mode 100644 test-project/src/hello.model.json diff --git a/src/bin.rs b/src/bin.rs index 4cc0aa1c..a0c87fb8 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -34,7 +34,7 @@ use core::Config; use pathext::canonicalish; use project::{Project, ProjectLoadError}; use plugin::{PluginChain}; -use plugins::{DefaultPlugin, ScriptPlugin}; +use plugins::{DefaultPlugin, JsonModelPlugin, ScriptPlugin}; use vfs::Vfs; use vfs_watch::VfsWatcher; @@ -153,6 +153,7 @@ fn main() { lazy_static! { static ref PLUGIN_CHAIN: PluginChain = PluginChain::new(vec![ Box::new(ScriptPlugin::new()), + Box::new(JsonModelPlugin::new()), Box::new(DefaultPlugin::new()), ]); } diff --git a/src/plugins/json_model_plugin.rs b/src/plugins/json_model_plugin.rs index 137560c8..c4d6eb74 100644 --- a/src/plugins/json_model_plugin.rs +++ b/src/plugins/json_model_plugin.rs @@ -29,7 +29,11 @@ impl Plugin for JsonModelPlugin { let mut rbx_item: RbxItem = match serde_json::from_str(contents) { Ok(v) => v, - Err(_) => return TransformFileResult::Pass, // This should be an error in the future + Err(_) => { + eprintln!("Unable to parse JSON Model File named {}", name); + + return TransformFileResult::Pass; // This should be an error in the future! + }, }; rbx_item.properties.insert("Name".to_string(), RbxValue::String { diff --git a/test-project/src/hello.model.json b/test-project/src/hello.model.json new file mode 100644 index 00000000..3f3b8077 --- /dev/null +++ b/test-project/src/hello.model.json @@ -0,0 +1,24 @@ +{ + "name": "hello", + "className": "Model", + "children": [ + { + "name": "Some Part", + "className": "Part", + "children": [], + "properties": {} + }, + { + "name": "Some StringValue", + "className": "StringValue", + "children": [], + "properties": { + "Value": { + "type": "string", + "value": "Hello, world!" + } + } + } + ], + "properties": {} +} \ No newline at end of file From ab22b55b84edbbb7744999df41c26758037599c0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 2 Jan 2018 18:17:44 -0800 Subject: [PATCH 0056/1504] Add further logging in verbose mode --- src/vfs.rs | 4 ++++ src/web.rs | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/src/vfs.rs b/src/vfs.rs index 483a93b2..b6fd57cc 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -173,6 +173,10 @@ impl Vfs { match self.plugin_chain.handle_file_change(&route) { Some(routes) => { + if self.config.verbose { + println!("Adding changes from plugin: {:?}", routes); + } + for route in routes { self.change_history.push(VfsChange { timestamp, diff --git a/src/web.rs b/src/web.rs index 65024b18..a91bcd38 100644 --- a/src/web.rs +++ b/src/web.rs @@ -169,6 +169,11 @@ pub fn start(config: Config, project: Project, plugin_chain: &'static PluginChai }) .collect::>(); + if config.verbose { + println!("Got read request: {:?}", read_request); + println!("Responding with:\n\t{:?}", rbx_items); + } + json(ReadResult { server_id: &server_id, items: rbx_items, From 13ce04abb2d56d144ebc2213f5cf17e19c85ae3b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 3 Jan 2018 11:44:45 -0800 Subject: [PATCH 0057/1504] Add 'Contributing' section to README --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index e1454d67..bd42ab5b 100644 --- a/README.md +++ b/README.md @@ -141,5 +141,12 @@ I also have a couple tools that Rojo intends to replace: * [rbxfs](https://github.com/LPGhatguy/rbxfs), which has been deprecated by Rojo * [rbxpacker](https://github.com/LPGhatguy/rbxpacker), which is still useful +## Contributing +Pull requests are welcome! + +The `master` branch of both repositories have tests running on Travis for every commit and pull request. The test suite on `master` should always pass! + +The Rojo and Rojo Plugin repositories should stay in sync with eachother, so that the current `master` of each repository can be used together. + ## License Rojo is available under the terms of the MIT license. See [LICENSE.md](LICENSE.md) for details. \ No newline at end of file From 9720c5676503e584ecc70df36bf651a547306d88 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 3 Jan 2018 15:56:19 -0800 Subject: [PATCH 0058/1504] Change each VfsItem to keep a full route instead of just its name --- src/plugins/default_plugin.rs | 8 ++--- src/plugins/json_model_plugin.rs | 6 ++-- src/plugins/script_plugin.rs | 8 +++-- src/vfs.rs | 53 +++++++++++++++++++------------- 4 files changed, 44 insertions(+), 31 deletions(-) diff --git a/src/plugins/default_plugin.rs b/src/plugins/default_plugin.rs index a503fbe8..a870aa18 100644 --- a/src/plugins/default_plugin.rs +++ b/src/plugins/default_plugin.rs @@ -19,7 +19,7 @@ impl DefaultPlugin { impl Plugin for DefaultPlugin { fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult { match vfs_item { - &VfsItem::File { ref contents, ref name } => { + &VfsItem::File { ref contents, .. } => { let mut properties = HashMap::new(); properties.insert("Value".to_string(), RbxValue::String { @@ -27,13 +27,13 @@ impl Plugin for DefaultPlugin { }); TransformFileResult::Value(Some(RbxItem { - name: name.clone(), + name: vfs_item.name().clone(), class_name: "StringValue".to_string(), children: Vec::new(), properties, })) }, - &VfsItem::Dir { ref children, ref name } => { + &VfsItem::Dir { ref children, .. } => { let mut rbx_children = Vec::new(); for (_, child_item) in children { @@ -46,7 +46,7 @@ impl Plugin for DefaultPlugin { } TransformFileResult::Value(Some(RbxItem { - name: name.clone(), + name: vfs_item.name().clone(), class_name: "Folder".to_string(), children: rbx_children, properties: HashMap::new(), diff --git a/src/plugins/json_model_plugin.rs b/src/plugins/json_model_plugin.rs index c4d6eb74..29be5b29 100644 --- a/src/plugins/json_model_plugin.rs +++ b/src/plugins/json_model_plugin.rs @@ -21,8 +21,8 @@ impl JsonModelPlugin { impl Plugin for JsonModelPlugin { fn transform_file(&self, _plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult { match vfs_item { - &VfsItem::File { ref contents, ref name } => { - let rbx_name = match JSON_MODEL_PATTERN.captures(name) { + &VfsItem::File { ref contents, .. } => { + let rbx_name = match JSON_MODEL_PATTERN.captures(vfs_item.name()) { Some(captures) => captures.get(1).unwrap().as_str().to_string(), None => return TransformFileResult::Pass, }; @@ -30,7 +30,7 @@ impl Plugin for JsonModelPlugin { let mut rbx_item: RbxItem = match serde_json::from_str(contents) { Ok(v) => v, Err(_) => { - eprintln!("Unable to parse JSON Model File named {}", name); + eprintln!("Unable to parse JSON Model File named {}", vfs_item.name()); return TransformFileResult::Pass; // This should be an error in the future! }, diff --git a/src/plugins/script_plugin.rs b/src/plugins/script_plugin.rs index 38bd746a..183d5df8 100644 --- a/src/plugins/script_plugin.rs +++ b/src/plugins/script_plugin.rs @@ -28,7 +28,9 @@ impl ScriptPlugin { impl Plugin for ScriptPlugin { fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult { match vfs_item { - &VfsItem::File { ref contents, ref name } => { + &VfsItem::File { ref contents, .. } => { + let name = vfs_item.name(); + let (class_name, rbx_name) = { if let Some(captures) = SERVER_PATTERN.captures(name) { ("Script".to_string(), captures.get(1).unwrap().as_str().to_string()) @@ -54,7 +56,7 @@ impl Plugin for ScriptPlugin { properties, })) }, - &VfsItem::Dir { ref children, ref name } => { + &VfsItem::Dir { ref children, .. } => { let init_item = { let maybe_item = children.get(SERVER_INIT) .or(children.get(CLIENT_INIT)) @@ -75,7 +77,7 @@ impl Plugin for ScriptPlugin { }; rbx_item.name.clear(); - rbx_item.name.push_str(name); + rbx_item.name.push_str(vfs_item.name()); for (child_name, child_item) in children { if child_name == init_item.name() { diff --git a/src/vfs.rs b/src/vfs.rs index b6fd57cc..22753533 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -1,4 +1,3 @@ -use std::borrow::Borrow; use std::collections::HashMap; use std::fs::{self, File}; use std::io::Read; @@ -40,15 +39,25 @@ pub struct VfsChange { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase", tag = "type")] pub enum VfsItem { - File { name: String, contents: String }, - Dir { name: String, children: HashMap }, + File { + route: Vec, + contents: String, + }, + Dir { + route: Vec, + children: HashMap, + }, } impl VfsItem { pub fn name(&self) -> &String { + self.route().last().unwrap() + } + + pub fn route(&self) -> &[String] { match self { - &VfsItem::File { ref name, .. } => name, - &VfsItem::Dir { ref name, .. } => name, + &VfsItem::File { ref route, .. } => route, + &VfsItem::Dir { ref route, .. } => route, } } } @@ -64,9 +73,9 @@ impl Vfs { } } - fn route_to_path>(&self, route: &[R]) -> Option { + fn route_to_path(&self, route: &[String]) -> Option { let (partition_name, rest) = match route.split_first() { - Some((first, rest)) => (first.borrow(), rest), + Some((first, rest)) => (first, rest), None => return None, }; @@ -90,7 +99,7 @@ impl Vfs { Some(full_path) } - fn read_dir>(&self, path: P) -> Result { + fn read_dir>(&self, route: &[String], path: P) -> Result { let path = path.as_ref(); let reader = match fs::read_dir(path) { Ok(v) => v, @@ -106,11 +115,13 @@ impl Vfs { }; let path = entry.path(); + let name = path.file_name().unwrap().to_string_lossy().into_owned(); - match self.read_path(&path) { + let mut child_route = route.iter().cloned().collect::>(); + child_route.push(name.clone()); + + match self.read_path(&child_route, &path) { Ok(child_item) => { - let name = path.file_name().unwrap().to_string_lossy().into_owned(); - children.insert(name, child_item); }, Err(_) => {}, @@ -118,12 +129,12 @@ impl Vfs { } Ok(VfsItem::Dir { - name: path.file_name().unwrap().to_string_lossy().into_owned(), + route: route.iter().cloned().collect::>(), children, }) } - fn read_file>(&self, path: P) -> Result { + fn read_file>(&self, route: &[String], path: P) -> Result { let path = path.as_ref(); let mut file = match File::open(path) { Ok(v) => v, @@ -138,12 +149,12 @@ impl Vfs { } Ok(VfsItem::File { - name: path.file_name().unwrap().to_string_lossy().into_owned(), + route: route.iter().cloned().collect::>(), contents, }) } - fn read_path>(&self, path: P) -> Result { + fn read_path>(&self, route: &[String], path: P) -> Result { let path = path.as_ref(); let metadata = match fs::metadata(path) { @@ -152,9 +163,9 @@ impl Vfs { }; if metadata.is_dir() { - self.read_dir(path) + self.read_dir(route, path) } else if metadata.is_file() { - self.read_file(path) + self.read_file(route, path) } else { Err(()) } @@ -206,18 +217,18 @@ impl Vfs { } } - pub fn read>(&self, route: &[R]) -> Result { + pub fn read(&self, route: &[String]) -> Result { match self.route_to_path(route) { - Some(path) => self.read_path(&path), + Some(path) => self.read_path(route, &path), None => Err(()), } } - pub fn write>(&self, _route: &[R], _item: VfsItem) -> Result<(), ()> { + pub fn write(&self, _route: &[String], _item: VfsItem) -> Result<(), ()> { unimplemented!() } - pub fn delete>(&self, _route: &[R]) -> Result<(), ()> { + pub fn delete(&self, _route: &[String]) -> Result<(), ()> { unimplemented!() } } From f00152a9ac3446e7931f09aa6c30d6f5af6a3fb5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 3 Jan 2018 16:00:27 -0800 Subject: [PATCH 0059/1504] Add a bit of documentation, this code is lacking it --- src/vfs.rs | 9 +++++++++ src/vfs_watch.rs | 2 ++ 2 files changed, 11 insertions(+) diff --git a/src/vfs.rs b/src/vfs.rs index 22753533..00b7617d 100644 --- a/src/vfs.rs +++ b/src/vfs.rs @@ -36,6 +36,10 @@ pub struct VfsChange { route: Vec, } +/// A VfsItem represents either a file or directory as it came from the filesystem. +/// +/// The interface here is intentionally simplified to make it easier to traverse +/// files that have been read into memory. #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase", tag = "type")] pub enum VfsItem { @@ -171,12 +175,15 @@ impl Vfs { } } + /// Get the current time, used for logging timestamps for file changes. pub fn current_time(&self) -> f64 { let elapsed = self.start_time.elapsed(); elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 * 1e-9 } + /// Register a new change to the filesystem at the given timestamp and VFS + /// route. pub fn add_change(&mut self, timestamp: f64, route: Vec) { if self.config.verbose { println!("Received change {:?}, running through plugins...", route); @@ -199,6 +206,7 @@ impl Vfs { } } + /// Collect a list of changes that occured since the given timestamp. pub fn changes_since(&self, timestamp: f64) -> &[VfsChange] { let mut marker: Option = None; @@ -217,6 +225,7 @@ impl Vfs { } } + /// Read an item from the filesystem using the given VFS route. pub fn read(&self, route: &[String]) -> Result { match self.route_to_path(route) { Some(path) => self.read_path(route, &path), diff --git a/src/vfs_watch.rs b/src/vfs_watch.rs index 872ba683..cb0d15be 100644 --- a/src/vfs_watch.rs +++ b/src/vfs_watch.rs @@ -8,6 +8,8 @@ use core::Config; use pathext::path_to_route; use vfs::Vfs; +/// An object that registers watchers on the real filesystem and relays those +/// changes to the virtual filesystem layer. pub struct VfsWatcher { vfs: Arc>, watchers: Vec, From d8bcbee46300f0f4f70fb167ef8e5b47bdc2db16 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 3 Jan 2018 16:01:48 -0800 Subject: [PATCH 0060/1504] Rename RbxItem -> RbxInstance --- DESIGN.md | 8 ++++---- src/plugin.rs | 10 +++++----- src/plugins/default_plugin.rs | 8 ++++---- src/plugins/json_model_plugin.rs | 6 +++--- src/plugins/script_plugin.rs | 6 +++--- src/rbx.rs | 4 ++-- src/web.rs | 6 +++--- 7 files changed, 24 insertions(+), 24 deletions(-) diff --git a/DESIGN.md b/DESIGN.md index 46ad11a0..f1877c39 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -6,12 +6,12 @@ This is a super rough draft that I'm trying to use to lay out some of my thought ### POST `/read` Accepts a `Vec` of items to read. -Returns `Vec>`, in the same order as the request. +Returns `Vec>`, in the same order as the request. ### POST `/write` -Accepts a `Vec<{ Route, RbxItem }>` of items to write. +Accepts a `Vec<{ Route, RbxInstance }>` of items to write. -I imagine that the `Name` attribute of the top-level `RbxItem` would be ignored in favor of the route name? +I imagine that the `Name` attribute of the top-level `RbxInstance` would be ignored in favor of the route name? ## CLI The `rojo serve` command uses three major components: @@ -21,7 +21,7 @@ The `rojo serve` command uses three major components: ### Transform Plugins Transform plugins (or filter plugins?) can interject in three places: -* Transform a `VfsItem` that's being read into an `RbxItem` in the VFS +* Transform a `VfsItem` that's being read into an `RbxInstance` in the VFS * Transform an `Rbxitem` that's being written into a `VfsItem` in the VFS * Transform a file change into paths that need to be updated in the VFS watcher diff --git a/src/plugin.rs b/src/plugin.rs index 5b80f084..3f18bcbe 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -1,10 +1,10 @@ -use rbx::RbxItem; +use rbx::RbxInstance; use vfs::VfsItem; use core::Route; // TODO: Add error case? pub enum TransformFileResult { - Value(Option), + Value(Option), Pass, } @@ -20,7 +20,7 @@ pub enum FileChangeResult { pub trait Plugin { fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult; - fn handle_rbx_change(&self, route: &Route, rbx_item: &RbxItem) -> RbxChangeResult; + fn handle_rbx_change(&self, route: &Route, rbx_item: &RbxInstance) -> RbxChangeResult; fn handle_file_change(&self, route: &Route) -> FileChangeResult; } @@ -35,7 +35,7 @@ impl PluginChain { } } - pub fn transform_file(&self, vfs_item: &VfsItem) -> Option { + pub fn transform_file(&self, vfs_item: &VfsItem) -> Option { for plugin in &self.plugins { match plugin.transform_file(self, vfs_item) { TransformFileResult::Value(rbx_item) => return rbx_item, @@ -46,7 +46,7 @@ impl PluginChain { None } - pub fn handle_rbx_change(&self, route: &Route, rbx_item: &RbxItem) -> Option { + pub fn handle_rbx_change(&self, route: &Route, rbx_item: &RbxInstance) -> Option { for plugin in &self.plugins { match plugin.handle_rbx_change(route, rbx_item) { RbxChangeResult::Write(vfs_item) => return vfs_item, diff --git a/src/plugins/default_plugin.rs b/src/plugins/default_plugin.rs index a870aa18..276aa50f 100644 --- a/src/plugins/default_plugin.rs +++ b/src/plugins/default_plugin.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use core::Route; use plugin::{Plugin, PluginChain, TransformFileResult, RbxChangeResult, FileChangeResult}; -use rbx::{RbxItem, RbxValue}; +use rbx::{RbxInstance, RbxValue}; use vfs::VfsItem; /// A plugin with simple transforms: @@ -26,7 +26,7 @@ impl Plugin for DefaultPlugin { value: contents.clone(), }); - TransformFileResult::Value(Some(RbxItem { + TransformFileResult::Value(Some(RbxInstance { name: vfs_item.name().clone(), class_name: "StringValue".to_string(), children: Vec::new(), @@ -45,7 +45,7 @@ impl Plugin for DefaultPlugin { } } - TransformFileResult::Value(Some(RbxItem { + TransformFileResult::Value(Some(RbxInstance { name: vfs_item.name().clone(), class_name: "Folder".to_string(), children: rbx_children, @@ -59,7 +59,7 @@ impl Plugin for DefaultPlugin { FileChangeResult::MarkChanged(Some(vec![route.clone()])) } - fn handle_rbx_change(&self, _route: &Route, _rbx_item: &RbxItem) -> RbxChangeResult { + fn handle_rbx_change(&self, _route: &Route, _rbx_item: &RbxInstance) -> RbxChangeResult { RbxChangeResult::Pass } } diff --git a/src/plugins/json_model_plugin.rs b/src/plugins/json_model_plugin.rs index 29be5b29..ed8178ca 100644 --- a/src/plugins/json_model_plugin.rs +++ b/src/plugins/json_model_plugin.rs @@ -3,7 +3,7 @@ use serde_json; use core::Route; use plugin::{Plugin, PluginChain, TransformFileResult, RbxChangeResult, FileChangeResult}; -use rbx::{RbxItem, RbxValue}; +use rbx::{RbxInstance, RbxValue}; use vfs::VfsItem; lazy_static! { @@ -27,7 +27,7 @@ impl Plugin for JsonModelPlugin { None => return TransformFileResult::Pass, }; - let mut rbx_item: RbxItem = match serde_json::from_str(contents) { + let mut rbx_item: RbxInstance = match serde_json::from_str(contents) { Ok(v) => v, Err(_) => { eprintln!("Unable to parse JSON Model File named {}", vfs_item.name()); @@ -50,7 +50,7 @@ impl Plugin for JsonModelPlugin { FileChangeResult::Pass } - fn handle_rbx_change(&self, _route: &Route, _rbx_item: &RbxItem) -> RbxChangeResult { + fn handle_rbx_change(&self, _route: &Route, _rbx_item: &RbxInstance) -> RbxChangeResult { RbxChangeResult::Pass } } diff --git a/src/plugins/script_plugin.rs b/src/plugins/script_plugin.rs index 183d5df8..86810be3 100644 --- a/src/plugins/script_plugin.rs +++ b/src/plugins/script_plugin.rs @@ -4,7 +4,7 @@ use regex::Regex; use core::Route; use plugin::{Plugin, PluginChain, TransformFileResult, RbxChangeResult, FileChangeResult}; -use rbx::{RbxItem, RbxValue}; +use rbx::{RbxInstance, RbxValue}; use vfs::VfsItem; lazy_static! { @@ -49,7 +49,7 @@ impl Plugin for ScriptPlugin { value: contents.clone(), }); - TransformFileResult::Value(Some(RbxItem { + TransformFileResult::Value(Some(RbxInstance { name: rbx_name, class_name: class_name, children: Vec::new(), @@ -117,7 +117,7 @@ impl Plugin for ScriptPlugin { } } - fn handle_rbx_change(&self, _route: &Route, _rbx_item: &RbxItem) -> RbxChangeResult { + fn handle_rbx_change(&self, _route: &Route, _rbx_item: &RbxInstance) -> RbxChangeResult { RbxChangeResult::Pass } } diff --git a/src/rbx.rs b/src/rbx.rs index 234529ca..151414e0 100644 --- a/src/rbx.rs +++ b/src/rbx.rs @@ -2,10 +2,10 @@ use std::collections::HashMap; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct RbxItem { +pub struct RbxInstance { pub name: String, pub class_name: String, - pub children: Vec, + pub children: Vec, pub properties: HashMap, } diff --git a/src/web.rs b/src/web.rs index a91bcd38..c475bc6e 100644 --- a/src/web.rs +++ b/src/web.rs @@ -8,7 +8,7 @@ use serde_json; use core::Config; use project::Project; use vfs::{Vfs, VfsChange}; -use rbx::RbxItem; +use rbx::RbxInstance; use plugin::PluginChain; static MAX_BODY_SIZE: usize = 25 * 1024 * 1024; // 25 MiB @@ -26,7 +26,7 @@ struct ServerInfo<'a> { #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct ReadResult<'a> { - items: Vec>, + items: Vec>, server_id: &'a str, current_time: f64, } @@ -43,7 +43,7 @@ struct ChangesResult<'a> { #[serde(rename_all = "camelCase")] struct WriteSpecifier { route: String, - item: RbxItem, + item: RbxInstance, } fn json(value: T) -> rouille::Response { From 58b244b7e9cf7618790a40e995dbb4bc014e43ae Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 3 Jan 2018 16:45:46 -0800 Subject: [PATCH 0061/1504] Reorganize some of the unwieldly parts of the codebase * Moved commands into their own folder to reduce `bin.rs`'s size * Moved all of the VFS-related functionality into its own folder * Documented a lot of functions, including a few very obscure ones --- DESIGN.md | 2 +- src/bin.rs | 152 ++--------------------- src/commands/init.rs | 16 +++ src/commands/mod.rs | 5 + src/commands/serve.rs | 114 +++++++++++++++++ src/core.rs | 7 -- src/plugin.rs | 14 ++- src/project.rs | 20 ++- src/rbx.rs | 5 + src/vfs/mod.rs | 7 ++ src/vfs/vfs_item.rs | 31 +++++ src/{vfs.rs => vfs/vfs_session.rs} | 51 +------- src/{vfs_watch.rs => vfs/vfs_watcher.rs} | 14 +-- src/web.rs | 41 +++++- 14 files changed, 267 insertions(+), 212 deletions(-) create mode 100644 src/commands/init.rs create mode 100644 src/commands/mod.rs create mode 100644 src/commands/serve.rs create mode 100644 src/vfs/mod.rs create mode 100644 src/vfs/vfs_item.rs rename src/{vfs.rs => vfs/vfs_session.rs} (82%) rename src/{vfs_watch.rs => vfs/vfs_watcher.rs} (90%) diff --git a/DESIGN.md b/DESIGN.md index f1877c39..dba5d405 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -22,7 +22,7 @@ The `rojo serve` command uses three major components: ### Transform Plugins Transform plugins (or filter plugins?) can interject in three places: * Transform a `VfsItem` that's being read into an `RbxInstance` in the VFS -* Transform an `Rbxitem` that's being written into a `VfsItem` in the VFS +* Transform an `RbxInstance` that's being written into a `VfsItem` in the VFS * Transform a file change into paths that need to be updated in the VFS watcher The plan is to have several built-in plugins that can be rearranged/configured in project settings: diff --git a/src/bin.rs b/src/bin.rs index a0c87fb8..2546c9aa 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -1,15 +1,7 @@ -#[macro_use] -extern crate serde_derive; - -#[macro_use] -extern crate rouille; - -#[macro_use] -extern crate clap; - -#[macro_use] -extern crate lazy_static; - +#[macro_use] extern crate serde_derive; +#[macro_use] extern crate rouille; +#[macro_use] extern crate clap; +#[macro_use] extern crate lazy_static; extern crate notify; extern crate rand; extern crate serde; @@ -21,22 +13,15 @@ pub mod core; pub mod project; pub mod pathext; pub mod vfs; -pub mod vfs_watch; pub mod rbx; pub mod plugin; pub mod plugins; +pub mod commands; use std::path::{Path, PathBuf}; -use std::sync::{Arc, Mutex}; -use std::thread; +use std::process; -use core::Config; use pathext::canonicalish; -use project::{Project, ProjectLoadError}; -use plugin::{PluginChain}; -use plugins::{DefaultPlugin, JsonModelPlugin, ScriptPlugin}; -use vfs::Vfs; -use vfs_watch::VfsWatcher; fn main() { let matches = clap_app!(rojo => @@ -68,27 +53,13 @@ fn main() { _ => true, }; - let server_id = rand::random::(); - - if verbose { - println!("Server ID: {}", server_id); - } - match matches.subcommand() { ("init", sub_matches) => { let sub_matches = sub_matches.unwrap(); let project_path = Path::new(sub_matches.value_of("PATH").unwrap_or(".")); let full_path = canonicalish(project_path); - match Project::init(&full_path) { - Ok(_) => { - println!("Created new empty project at {}", full_path.display()); - }, - Err(e) => { - eprintln!("Failed to create new project.\n{}", e); - std::process::exit(1); - }, - } + commands::init(&full_path); }, ("serve", sub_matches) => { let sub_matches = sub_matches.unwrap(); @@ -98,126 +69,29 @@ fn main() { None => std::env::current_dir().unwrap(), }; - if verbose { - println!("Attempting to locate project at {}", project_path.display()); - } - - let project = match Project::load(&project_path) { - Ok(v) => { - println!("Using project from {}", project_path.display()); - v - }, - Err(err) => { - match err { - ProjectLoadError::InvalidJson(serde_err) => { - eprintln!( - "Found invalid JSON!\nProject in: {}\nError: {}", - project_path.display(), - serde_err, - ); - - std::process::exit(1); - }, - ProjectLoadError::FailedToOpen | ProjectLoadError::FailedToRead => { - eprintln!("Found project file, but failed to read it!"); - eprintln!( - "Check the permissions of the project file at\n{}", - project_path.display(), - ); - - std::process::exit(1); - }, - _ => { - // Any other error is fine; use the default project. - }, - } - - println!("Found no project file, using default project..."); - Project::default() - }, - }; - let port = { match sub_matches.value_of("port") { Some(source) => match source.parse::() { - Ok(value) => value, + Ok(value) => Some(value), Err(_) => { eprintln!("Invalid port '{}'", source); - std::process::exit(1); + process::exit(1); }, }, - None => project.serve_port, + None => None, } }; - lazy_static! { - static ref PLUGIN_CHAIN: PluginChain = PluginChain::new(vec![ - Box::new(ScriptPlugin::new()), - Box::new(JsonModelPlugin::new()), - Box::new(DefaultPlugin::new()), - ]); - } - - let config = Config { - port, - verbose, - server_id, - }; - - if verbose { - println!("Loading VFS..."); - } - - let vfs = { - let mut vfs = Vfs::new(config.clone(), &PLUGIN_CHAIN); - - for (name, project_partition) in &project.partitions { - let path = { - let given_path = Path::new(&project_partition.path); - - if given_path.is_absolute() { - given_path.to_path_buf() - } else { - project_path.join(given_path) - } - }; - - if verbose { - println!( - "Partition '{}': {} @ {}", - name, - project_partition.target, - project_partition.path - ); - } - - vfs.partitions.insert(name.clone(), path); - } - - Arc::new(Mutex::new(vfs)) - }; - - { - let vfs = vfs.clone(); - let config = config.clone(); - - thread::spawn(move || { - VfsWatcher::new(config, vfs).start(); - }); - } - - println!("Server listening on port {}", port); - - web::start(config.clone(), project.clone(), &PLUGIN_CHAIN, vfs.clone()); + commands::serve(&project_path, verbose, port); }, ("pack", _) => { eprintln!("'rojo pack' is not yet implemented!"); - std::process::exit(1); + process::exit(1); }, _ => { eprintln!("Please specify a subcommand!"); eprintln!("Try 'rojo help' for information."); - std::process::exit(1); + process::exit(1); }, } } diff --git a/src/commands/init.rs b/src/commands/init.rs new file mode 100644 index 00000000..96cbbcb3 --- /dev/null +++ b/src/commands/init.rs @@ -0,0 +1,16 @@ +use std::path::PathBuf; +use std::process; + +use project::Project; + +pub fn init(project_path: &PathBuf) { + match Project::init(project_path) { + Ok(_) => { + println!("Created new empty project at {}", project_path.display()); + }, + Err(e) => { + eprintln!("Failed to create new project.\n{}", e); + process::exit(1); + }, + } +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs new file mode 100644 index 00000000..58023fa3 --- /dev/null +++ b/src/commands/mod.rs @@ -0,0 +1,5 @@ +mod serve; +mod init; + +pub use self::serve::*; +pub use self::init::*; diff --git a/src/commands/serve.rs b/src/commands/serve.rs new file mode 100644 index 00000000..8ffc3790 --- /dev/null +++ b/src/commands/serve.rs @@ -0,0 +1,114 @@ +use std::path::{Path, PathBuf}; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::process; + +use rand; + +use project::{Project, ProjectLoadError}; +use plugin::{PluginChain}; +use plugins::{DefaultPlugin, JsonModelPlugin, ScriptPlugin}; +use vfs::{VfsSession, VfsWatcher}; +use web; + +pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { + let server_id = rand::random::(); + + if verbose { + println!("Attempting to locate project at {}", project_path.display()); + } + + let project = match Project::load(project_path) { + Ok(v) => { + println!("Using project from {}", project_path.display()); + v + }, + Err(err) => { + match err { + ProjectLoadError::InvalidJson(serde_err) => { + eprintln!( + "Found invalid JSON!\nProject in: {}\nError: {}", + project_path.display(), + serde_err, + ); + + process::exit(1); + }, + ProjectLoadError::FailedToOpen | ProjectLoadError::FailedToRead => { + eprintln!("Found project file, but failed to read it!"); + eprintln!( + "Check the permissions of the project file at\n{}", + project_path.display(), + ); + + process::exit(1); + }, + _ => { + // Any other error is fine; use the default project. + }, + } + + println!("Found no project file, using default project..."); + Project::default() + }, + }; + + let web_config = web::WebConfig { + verbose, + port: port.unwrap_or(project.serve_port), + server_id, + }; + + lazy_static! { + static ref PLUGIN_CHAIN: PluginChain = PluginChain::new(vec![ + Box::new(ScriptPlugin::new()), + Box::new(JsonModelPlugin::new()), + Box::new(DefaultPlugin::new()), + ]); + } + + if verbose { + println!("Loading VFS..."); + } + + let vfs = { + let mut vfs = VfsSession::new(&PLUGIN_CHAIN); + + for (name, project_partition) in &project.partitions { + let path = { + let given_path = Path::new(&project_partition.path); + + if given_path.is_absolute() { + given_path.to_path_buf() + } else { + project_path.join(given_path) + } + }; + + if verbose { + println!( + "Partition '{}': {} @ {}", + name, + project_partition.target, + project_partition.path + ); + } + + vfs.partitions.insert(name.clone(), path); + } + + Arc::new(Mutex::new(vfs)) + }; + + { + let vfs = vfs.clone(); + + thread::spawn(move || { + VfsWatcher::new(vfs).start(); + }); + } + + println!("Server listening on port {}", web_config.port); + + web::start(web_config, project.clone(), &PLUGIN_CHAIN, vfs.clone()); +} diff --git a/src/core.rs b/src/core.rs index 8300fe0b..9259cca0 100644 --- a/src/core.rs +++ b/src/core.rs @@ -1,8 +1 @@ -#[derive(Debug, Clone)] -pub struct Config { - pub port: u64, - pub verbose: bool, - pub server_id: u64, -} - pub type Route = Vec; diff --git a/src/plugin.rs b/src/plugin.rs index 3f18bcbe..2f25bf55 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -2,15 +2,18 @@ use rbx::RbxInstance; use vfs::VfsItem; use core::Route; -// TODO: Add error case? pub enum TransformFileResult { Value(Option), Pass, + + // TODO: Error case } pub enum RbxChangeResult { Write(Option), Pass, + + // TODO: Error case } pub enum FileChangeResult { @@ -19,11 +22,20 @@ pub enum FileChangeResult { } pub trait Plugin { + /// Invoked when a file is read from the filesystem and needs to be turned + /// into a Roblox instance. fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult; + + /// Invoked when a Roblox Instance change is reported by the Roblox Studio + /// plugin and needs to be turned into a file to save. fn handle_rbx_change(&self, route: &Route, rbx_item: &RbxInstance) -> RbxChangeResult; + + /// Invoked when a file changes on the filesystem. The result defines what + /// routes are marked as needing to be refreshed. fn handle_file_change(&self, route: &Route) -> FileChangeResult; } +/// A set of plugins that are composed in order. pub struct PluginChain { plugins: Vec>, } diff --git a/src/project.rs b/src/project.rs index 10392c53..eb45ce21 100644 --- a/src/project.rs +++ b/src/project.rs @@ -44,10 +44,19 @@ impl fmt::Display for ProjectInitError { #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ProjectPartition { + /// A slash-separated path to a file or folder, relative to the project's + /// directory. pub path: String, + + /// A dot-separated route to a Roblox instance, relative to game. pub target: String, } +/// Represents a project configured by a user for use with Rojo. Holds anything +/// that can be configured with `rojo.json`. +/// +/// In the future, this object will hold dependency information and other handy +/// configurables #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(default, rename_all = "camelCase")] pub struct Project { @@ -57,6 +66,7 @@ pub struct Project { } impl Project { + /// Creates a new empty Project object with the given name. pub fn new>(name: T) -> Project { Project { name: name.into(), @@ -64,10 +74,12 @@ impl Project { } } + /// Initializes a new project inside the given folder path. pub fn init>(location: T) -> Result { let location = location.as_ref(); let package_path = location.join(PROJECT_FILENAME); + // We abort if the project file already exists. match fs::metadata(&package_path) { Ok(_) => return Err(ProjectInitError::AlreadyExists), Err(_) => {}, @@ -78,11 +90,14 @@ impl Project { Err(_) => return Err(ProjectInitError::FailedToCreate), }; + // Try to give the project a meaningful name. + // If we can't, we'll just fall back to a default. let name = match location.file_name() { Some(v) => v.to_string_lossy().into_owned(), None => "new-project".to_string(), }; + // Configure the project with all of the values we know so far. let project = Project::new(name); let serialized = serde_json::to_string_pretty(&project).unwrap(); @@ -94,6 +109,8 @@ impl Project { Ok(project) } + /// Attempts to load a project from the file named PROJECT_FILENAME from the + /// given folder. pub fn load>(location: T) -> Result { let package_path = location.as_ref().join(Path::new(PROJECT_FILENAME)); @@ -120,6 +137,7 @@ impl Project { } } + /// Saves the given project file to the given folder with the appropriate name. pub fn save>(&self, location: T) -> Result<(), ProjectSaveError> { let package_path = location.as_ref().join(Path::new(PROJECT_FILENAME)); @@ -139,7 +157,7 @@ impl Project { impl Default for Project { fn default() -> Project { Project { - name: "some-project".to_string(), + name: "new-project".to_string(), serve_port: 8000, partitions: HashMap::new(), } diff --git a/src/rbx.rs b/src/rbx.rs index 151414e0..03019fc8 100644 --- a/src/rbx.rs +++ b/src/rbx.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; +/// Represents data about a Roblox instance #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct RbxInstance { @@ -9,10 +10,14 @@ pub struct RbxInstance { pub properties: HashMap, } +/// Any kind value that can be used by Roblox #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase", tag = "type")] pub enum RbxValue { String { value: String, }, + + // TODO: Other primitives + // TODO: Compound types like Vector3 } diff --git a/src/vfs/mod.rs b/src/vfs/mod.rs new file mode 100644 index 00000000..a19dc4d0 --- /dev/null +++ b/src/vfs/mod.rs @@ -0,0 +1,7 @@ +mod vfs_session; +mod vfs_item; +mod vfs_watcher; + +pub use self::vfs_session::*; +pub use self::vfs_item::*; +pub use self::vfs_watcher::*; diff --git a/src/vfs/vfs_item.rs b/src/vfs/vfs_item.rs new file mode 100644 index 00000000..ae00c6dc --- /dev/null +++ b/src/vfs/vfs_item.rs @@ -0,0 +1,31 @@ +use std::collections::HashMap; + +/// A VfsItem represents either a file or directory as it came from the filesystem. +/// +/// The interface here is intentionally simplified to make it easier to traverse +/// files that have been read into memory. +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase", tag = "type")] +pub enum VfsItem { + File { + route: Vec, + contents: String, + }, + Dir { + route: Vec, + children: HashMap, + }, +} + +impl VfsItem { + pub fn name(&self) -> &String { + self.route().last().unwrap() + } + + pub fn route(&self) -> &[String] { + match self { + &VfsItem::File { ref route, .. } => route, + &VfsItem::Dir { ref route, .. } => route, + } + } +} diff --git a/src/vfs.rs b/src/vfs/vfs_session.rs similarity index 82% rename from src/vfs.rs rename to src/vfs/vfs_session.rs index 00b7617d..504f16b6 100644 --- a/src/vfs.rs +++ b/src/vfs/vfs_session.rs @@ -4,14 +4,14 @@ use std::io::Read; use std::path::{Path, PathBuf}; use std::time::Instant; -use core::Config; use plugin::PluginChain; +use vfs::VfsItem; /// Represents a virtual layer over multiple parts of the filesystem. /// /// Paths in this system are represented as slices of strings, and are always /// relative to a partition, which is an absolute path into the real filesystem. -pub struct Vfs { +pub struct VfsSession { /// Contains all of the partitions mounted by the Vfs. /// /// These must be absolute paths! @@ -25,8 +25,6 @@ pub struct Vfs { pub change_history: Vec, plugin_chain: &'static PluginChain, - - config: Config, } #[derive(Debug, Serialize, Deserialize)] @@ -36,44 +34,13 @@ pub struct VfsChange { route: Vec, } -/// A VfsItem represents either a file or directory as it came from the filesystem. -/// -/// The interface here is intentionally simplified to make it easier to traverse -/// files that have been read into memory. -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", tag = "type")] -pub enum VfsItem { - File { - route: Vec, - contents: String, - }, - Dir { - route: Vec, - children: HashMap, - }, -} - -impl VfsItem { - pub fn name(&self) -> &String { - self.route().last().unwrap() - } - - pub fn route(&self) -> &[String] { - match self { - &VfsItem::File { ref route, .. } => route, - &VfsItem::Dir { ref route, .. } => route, - } - } -} - -impl Vfs { - pub fn new(config: Config, plugin_chain: &'static PluginChain) -> Vfs { - Vfs { +impl VfsSession { + pub fn new(plugin_chain: &'static PluginChain) -> VfsSession { + VfsSession { partitions: HashMap::new(), start_time: Instant::now(), change_history: Vec::new(), plugin_chain, - config, } } @@ -185,16 +152,8 @@ impl Vfs { /// Register a new change to the filesystem at the given timestamp and VFS /// route. pub fn add_change(&mut self, timestamp: f64, route: Vec) { - if self.config.verbose { - println!("Received change {:?}, running through plugins...", route); - } - match self.plugin_chain.handle_file_change(&route) { Some(routes) => { - if self.config.verbose { - println!("Adding changes from plugin: {:?}", routes); - } - for route in routes { self.change_history.push(VfsChange { timestamp, diff --git a/src/vfs_watch.rs b/src/vfs/vfs_watcher.rs similarity index 90% rename from src/vfs_watch.rs rename to src/vfs/vfs_watcher.rs index cb0d15be..5a5cd91b 100644 --- a/src/vfs_watch.rs +++ b/src/vfs/vfs_watcher.rs @@ -4,24 +4,21 @@ use std::time::Duration; use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; -use core::Config; use pathext::path_to_route; -use vfs::Vfs; +use vfs::VfsSession; /// An object that registers watchers on the real filesystem and relays those /// changes to the virtual filesystem layer. pub struct VfsWatcher { - vfs: Arc>, + vfs: Arc>, watchers: Vec, - config: Config, } impl VfsWatcher { - pub fn new(config: Config, vfs: Arc>) -> VfsWatcher { + pub fn new(vfs: Arc>) -> VfsWatcher { VfsWatcher { vfs, watchers: Vec::new(), - config, } } @@ -45,7 +42,6 @@ impl VfsWatcher { { let vfs = self.vfs.clone(); - let config = self.config.clone(); thread::spawn(move || { loop { @@ -53,10 +49,6 @@ impl VfsWatcher { let mut vfs = vfs.lock().unwrap(); let current_time = vfs.current_time(); - if config.verbose { - println!("FS event {:?}", event); - } - match event { DebouncedEvent::Write(ref change_path) | DebouncedEvent::Create(ref change_path) | diff --git a/src/web.rs b/src/web.rs index c475bc6e..dd05b2a4 100644 --- a/src/web.rs +++ b/src/web.rs @@ -5,14 +5,20 @@ use rouille; use serde; use serde_json; -use core::Config; use project::Project; -use vfs::{Vfs, VfsChange}; +use vfs::{VfsSession, VfsChange}; use rbx::RbxInstance; use plugin::PluginChain; static MAX_BODY_SIZE: usize = 25 * 1024 * 1024; // 25 MiB +/// The set of configuration the web server needs to start. +pub struct WebConfig { + pub port: u64, + pub verbose: bool, + pub server_id: u64, +} + #[derive(Debug, Serialize)] #[serde(rename_all = "camelCase")] struct ServerInfo<'a> { @@ -51,7 +57,12 @@ fn json(value: T) -> rouille::Response { rouille::Response::from_data("application/json", data) } +/// Pulls text that may be JSON out of a Rouille Request object. +/// +/// Doesn't do any actual parsing -- all this method does is verify the content +/// type of the request and read the request's body. fn read_json_text(request: &rouille::Request) -> Option { + // Bail out if the request body isn't marked as JSON match request.header("Content-Type") { Some(header) => if !header.starts_with("application/json") { return None; @@ -64,14 +75,15 @@ fn read_json_text(request: &rouille::Request) -> Option { None => return None, }; + // Allocate a buffer and read up to MAX_BODY_SIZE+1 bytes into it. let mut out = Vec::new(); - match body.take(MAX_BODY_SIZE.saturating_add(1) as u64) - .read_to_end(&mut out) - { + match body.take(MAX_BODY_SIZE.saturating_add(1) as u64).read_to_end(&mut out) { Ok(_) => {}, Err(_) => return None, } + // If the body was too big (MAX_BODY_SIZE+1), we abort instead of trying to + // process it. if out.len() > MAX_BODY_SIZE { return None; } @@ -84,6 +96,7 @@ fn read_json_text(request: &rouille::Request) -> Option { Some(parsed) } +/// Reads the body out of a Rouille Request and attempts to turn it into JSON. fn read_json(request: &rouille::Request) -> Option where T: serde::de::DeserializeOwned, @@ -98,10 +111,13 @@ where Err(_) => return None, }; + // TODO: Change return type to some sort of Result + Some(parsed) } -pub fn start(config: Config, project: Project, plugin_chain: &'static PluginChain, vfs: Arc>) { +/// Start the Rojo web server and park our current thread. +pub fn start(config: WebConfig, project: Project, plugin_chain: &'static PluginChain, vfs: Arc>) { let address = format!("localhost:{}", config.port); let server_id = config.server_id.to_string(); @@ -109,6 +125,8 @@ pub fn start(config: Config, project: Project, plugin_chain: &'static PluginChai rouille::start_server(address, move |request| { router!(request, (GET) (/) => { + // Get a summary of information about the server. + let current_time = { let vfs = vfs.lock().unwrap(); @@ -125,6 +143,8 @@ pub fn start(config: Config, project: Project, plugin_chain: &'static PluginChai }, (GET) (/changes/{ last_time: f64 }) => { + // Get the list of changes since the given time. + let vfs = vfs.lock().unwrap(); let current_time = vfs.current_time(); let changes = vfs.changes_since(last_time); @@ -137,11 +157,16 @@ pub fn start(config: Config, project: Project, plugin_chain: &'static PluginChai }, (POST) (/read) => { + // Read some instances from the server according to a JSON + // format body. + let read_request: Vec> = match read_json(&request) { Some(v) => v, None => return rouille::Response::empty_400(), }; + // Read the files off of the filesystem that the client + // requested. let (items, current_time) = { let vfs = vfs.lock().unwrap(); @@ -159,6 +184,8 @@ pub fn start(config: Config, project: Project, plugin_chain: &'static PluginChai (items, current_time) }; + // Transform all of our VfsItem objects into Roblox instances + // the client can use. let rbx_items = items .iter() .map(|item| { @@ -182,6 +209,8 @@ pub fn start(config: Config, project: Project, plugin_chain: &'static PluginChai }, (POST) (/write) => { + // Not yet implemented. + let _write_request: Vec = match read_json(&request) { Some(v) => v, None => return rouille::Response::empty_400(), From f52f43fe90d49791f9aebcef19b6dc9f00e7e01c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 3 Jan 2018 18:02:56 -0800 Subject: [PATCH 0062/1504] Eliminate extra thread for VfsWatcher --- src/commands/serve.rs | 10 +---- src/vfs/vfs_watcher.rs | 98 ++++++++++++++++++++---------------------- 2 files changed, 47 insertions(+), 61 deletions(-) diff --git a/src/commands/serve.rs b/src/commands/serve.rs index 8ffc3790..c68881a0 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -1,6 +1,5 @@ use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; -use std::thread; use std::process; use rand; @@ -100,15 +99,8 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { Arc::new(Mutex::new(vfs)) }; - { - let vfs = vfs.clone(); - - thread::spawn(move || { - VfsWatcher::new(vfs).start(); - }); - } - println!("Server listening on port {}", web_config.port); + VfsWatcher::new(vfs.clone()).start(); web::start(web_config, project.clone(), &PLUGIN_CHAIN, vfs.clone()); } diff --git a/src/vfs/vfs_watcher.rs b/src/vfs/vfs_watcher.rs index 5a5cd91b..4598e72b 100644 --- a/src/vfs/vfs_watcher.rs +++ b/src/vfs/vfs_watcher.rs @@ -23,71 +23,65 @@ impl VfsWatcher { } pub fn start(mut self) { - { - let outer_vfs = self.vfs.lock().unwrap(); + let outer_vfs = self.vfs.lock().unwrap(); - for (partition_name, root_path) in &outer_vfs.partitions { - let (tx, rx) = mpsc::channel(); - let partition_name = partition_name.clone(); - let root_path = root_path.clone(); + for (partition_name, root_path) in &outer_vfs.partitions { + let (tx, rx) = mpsc::channel(); + let partition_name = partition_name.clone(); + let root_path = root_path.clone(); - let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(1)) - .expect("Unable to create watcher!"); + let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(1)) + .expect("Unable to create watcher!"); - watcher - .watch(&root_path, RecursiveMode::Recursive) - .expect("Unable to watch path!"); + watcher + .watch(&root_path, RecursiveMode::Recursive) + .expect("Unable to watch path!"); - self.watchers.push(watcher); + self.watchers.push(watcher); - { - let vfs = self.vfs.clone(); + { + let vfs = self.vfs.clone(); - thread::spawn(move || { - loop { - let event = rx.recv().unwrap(); - let mut vfs = vfs.lock().unwrap(); - let current_time = vfs.current_time(); + thread::spawn(move || { + loop { + let event = rx.recv().unwrap(); + let mut vfs = vfs.lock().unwrap(); + let current_time = vfs.current_time(); - match event { - DebouncedEvent::Write(ref change_path) | - DebouncedEvent::Create(ref change_path) | - DebouncedEvent::Remove(ref change_path) => { - if let Some(mut route) = path_to_route(&root_path, change_path) { - route.insert(0, partition_name.clone()); + match event { + DebouncedEvent::Write(ref change_path) | + DebouncedEvent::Create(ref change_path) | + DebouncedEvent::Remove(ref change_path) => { + if let Some(mut route) = path_to_route(&root_path, change_path) { + route.insert(0, partition_name.clone()); - vfs.add_change(current_time, route); - } else { - println!("Failed to get route from {}", change_path.display()); - } - }, - DebouncedEvent::Rename(ref from_change, ref to_change) => { - if let Some(mut route) = path_to_route(&root_path, from_change) { - route.insert(0, partition_name.clone()); + vfs.add_change(current_time, route); + } else { + println!("Failed to get route from {}", change_path.display()); + } + }, + DebouncedEvent::Rename(ref from_change, ref to_change) => { + if let Some(mut route) = path_to_route(&root_path, from_change) { + route.insert(0, partition_name.clone()); - vfs.add_change(current_time, route); - } else { - println!("Failed to get route from {}", from_change.display()); - } + vfs.add_change(current_time, route); + } else { + println!("Failed to get route from {}", from_change.display()); + } - if let Some(mut route) = path_to_route(&root_path, to_change) { - route.insert(0, partition_name.clone()); + if let Some(mut route) = path_to_route(&root_path, to_change) { + route.insert(0, partition_name.clone()); - vfs.add_change(current_time, route); - } else { - println!("Failed to get route from {}", to_change.display()); - } - }, - _ => {}, - } + vfs.add_change(current_time, route); + } else { + println!("Failed to get route from {}", to_change.display()); + } + }, + _ => {}, } - }); - } + } + }); } } - - loop { - thread::park(); - } } } From 78a1c658d81468b50ca944b1be71f6f2c243169b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 3 Jan 2018 18:05:00 -0800 Subject: [PATCH 0063/1504] Simplify and collapse some code from 'rojo serve' --- src/commands/serve.rs | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/src/commands/serve.rs b/src/commands/serve.rs index c68881a0..b456f9c9 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -14,7 +14,7 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { let server_id = rand::random::(); if verbose { - println!("Attempting to locate project at {}", project_path.display()); + println!("Attempting to locate project at {}...", project_path.display()); } let project = match Project::load(project_path) { @@ -44,11 +44,10 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { }, _ => { // Any other error is fine; use the default project. + println!("Found no project file, using default project..."); + Project::default() }, } - - println!("Found no project file, using default project..."); - Project::default() }, }; @@ -66,10 +65,6 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { ]); } - if verbose { - println!("Loading VFS..."); - } - let vfs = { let mut vfs = VfsSession::new(&PLUGIN_CHAIN); @@ -84,15 +79,6 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { } }; - if verbose { - println!( - "Partition '{}': {} @ {}", - name, - project_partition.target, - project_partition.path - ); - } - vfs.partitions.insert(name.clone(), path); } From 2df1dfa1cbd4e44626a0e815d5e1f1b435a423f3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 3 Jan 2018 18:13:49 -0800 Subject: [PATCH 0064/1504] Insulate VFS internals a little bit --- src/commands/serve.rs | 2 +- src/vfs/vfs_session.rs | 22 +++++++++++++++++----- src/vfs/vfs_watcher.rs | 2 +- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/src/commands/serve.rs b/src/commands/serve.rs index b456f9c9..e8cb2b82 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -79,7 +79,7 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { } }; - vfs.partitions.insert(name.clone(), path); + vfs.insert_partition(name, path); } Arc::new(Mutex::new(vfs)) diff --git a/src/vfs/vfs_session.rs b/src/vfs/vfs_session.rs index 504f16b6..efe86ea7 100644 --- a/src/vfs/vfs_session.rs +++ b/src/vfs/vfs_session.rs @@ -15,14 +15,14 @@ pub struct VfsSession { /// Contains all of the partitions mounted by the Vfs. /// /// These must be absolute paths! - pub partitions: HashMap, - - /// When the Vfs was initialized; used for change tracking. - pub start_time: Instant, + partitions: HashMap, /// A chronologically-sorted list of routes that changed since the Vfs was /// created, along with a timestamp denoting when. - pub change_history: Vec, + change_history: Vec, + + /// When the Vfs was initialized; used for change tracking. + start_time: Instant, plugin_chain: &'static PluginChain, } @@ -44,6 +44,18 @@ impl VfsSession { } } + pub fn get_partitions(&self) -> &HashMap { + &self.partitions + } + + pub fn insert_partition>(&mut self, name: &str, path: P) { + let path = path.into(); + + assert!(path.is_absolute()); + + self.partitions.insert(name.to_string(), path.into()); + } + fn route_to_path(&self, route: &[String]) -> Option { let (partition_name, rest) = match route.split_first() { Some((first, rest)) => (first, rest), diff --git a/src/vfs/vfs_watcher.rs b/src/vfs/vfs_watcher.rs index 4598e72b..b1db63b7 100644 --- a/src/vfs/vfs_watcher.rs +++ b/src/vfs/vfs_watcher.rs @@ -25,7 +25,7 @@ impl VfsWatcher { pub fn start(mut self) { let outer_vfs = self.vfs.lock().unwrap(); - for (partition_name, root_path) in &outer_vfs.partitions { + for (partition_name, root_path) in outer_vfs.get_partitions() { let (tx, rx) = mpsc::channel(); let partition_name = partition_name.clone(); let root_path = root_path.clone(); From 86d7d033d74ecd43d1a011bf4fcb5eef5db75afa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 5 Jan 2018 13:07:09 -0800 Subject: [PATCH 0065/1504] Add 'route' to each RbxInstance, which tags how the instance was generated --- src/plugins/default_plugin.rs | 2 ++ src/plugins/json_model_plugin.rs | 2 ++ src/plugins/script_plugin.rs | 1 + src/rbx.rs | 3 +++ 4 files changed, 8 insertions(+) diff --git a/src/plugins/default_plugin.rs b/src/plugins/default_plugin.rs index 276aa50f..3ea7addd 100644 --- a/src/plugins/default_plugin.rs +++ b/src/plugins/default_plugin.rs @@ -31,6 +31,7 @@ impl Plugin for DefaultPlugin { class_name: "StringValue".to_string(), children: Vec::new(), properties, + route: Some(vfs_item.route().to_vec()), })) }, &VfsItem::Dir { ref children, .. } => { @@ -50,6 +51,7 @@ impl Plugin for DefaultPlugin { class_name: "Folder".to_string(), children: rbx_children, properties: HashMap::new(), + route: Some(vfs_item.route().to_vec()), })) }, } diff --git a/src/plugins/json_model_plugin.rs b/src/plugins/json_model_plugin.rs index ed8178ca..e9025b2a 100644 --- a/src/plugins/json_model_plugin.rs +++ b/src/plugins/json_model_plugin.rs @@ -36,6 +36,8 @@ impl Plugin for JsonModelPlugin { }, }; + rbx_item.route = Some(vfs_item.route().to_vec()); + rbx_item.properties.insert("Name".to_string(), RbxValue::String { value: rbx_name, }); diff --git a/src/plugins/script_plugin.rs b/src/plugins/script_plugin.rs index 86810be3..dabe8d5c 100644 --- a/src/plugins/script_plugin.rs +++ b/src/plugins/script_plugin.rs @@ -54,6 +54,7 @@ impl Plugin for ScriptPlugin { class_name: class_name, children: Vec::new(), properties, + route: Some(vfs_item.route().to_vec()), })) }, &VfsItem::Dir { ref children, .. } => { diff --git a/src/rbx.rs b/src/rbx.rs index 03019fc8..99f24d40 100644 --- a/src/rbx.rs +++ b/src/rbx.rs @@ -8,6 +8,9 @@ pub struct RbxInstance { pub class_name: String, pub children: Vec, pub properties: HashMap, + + /// The route that this instance was generated from, if there was one. + pub route: Option>, } /// Any kind value that can be used by Roblox From 1318842c361a54c116112a44fa07b2f96b71266a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 8 Jan 2018 12:33:33 -0800 Subject: [PATCH 0066/1504] Update dependencies --- Cargo.lock | 203 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 116 insertions(+), 87 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d88291a7..e185036a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,13 +26,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "atty" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -56,7 +55,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -65,7 +64,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "brotli-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -94,7 +93,7 @@ version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -108,7 +107,7 @@ version = "2.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -183,7 +182,7 @@ name = "env_logger" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -193,8 +192,8 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -202,7 +201,7 @@ name = "flate2" version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -213,7 +212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -221,24 +220,22 @@ name = "fsevent-sys" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fuchsia-zircon" -version = "0.2.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fuchsia-zircon-sys" -version = "0.2.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "gcc" @@ -260,7 +257,7 @@ name = "inotify" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -284,13 +281,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.34" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "log" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "matches" @@ -302,7 +310,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -310,7 +318,7 @@ name = "memchr" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -318,7 +326,7 @@ name = "mime" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -338,7 +346,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -347,13 +355,13 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -375,11 +383,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "buf_redux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -390,7 +398,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -401,7 +409,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -415,7 +423,7 @@ dependencies = [ "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -481,7 +489,7 @@ version = "0.7.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -499,16 +507,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rand" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.32" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -516,7 +524,7 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -533,12 +541,12 @@ dependencies = [ [[package]] name = "regex" -version = "0.2.3" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -550,7 +558,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex-syntax" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -560,12 +568,12 @@ dependencies = [ "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -578,11 +586,11 @@ dependencies = [ "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "multipart 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "tiny_http 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -594,11 +602,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "same-file" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -611,22 +618,22 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.24" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.24" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -635,13 +642,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -687,7 +694,7 @@ name = "tempdir" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -704,8 +711,8 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -723,7 +730,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -745,13 +752,12 @@ dependencies = [ [[package]] name = "time" -version = "0.1.38" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -763,7 +769,7 @@ dependencies = [ "chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", "chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -834,7 +840,7 @@ name = "uuid" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -853,7 +859,7 @@ name = "walkdir" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "same-file 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -861,11 +867,30 @@ name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -880,7 +905,7 @@ dependencies = [ "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" "checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" -"checksum atty 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "21e50800ec991574876040fff8ee46b136a53e985286fbe6a3bdfe6421b78860" +"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" @@ -906,16 +931,17 @@ dependencies = [ "checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423" "checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05" "checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874" -"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159" -"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" "checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" -"checksum libc 0.2.34 (registry+https://github.com/rust-lang/crates.io-index)" = "36fbc8a8929c632868295d0178dd8f63fc423fd7537ad0738372bd010b3ac9b0" -"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b" +"checksum libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)" = "96264e9b293e95d25bfcbbf8a88ffd1aedc85b754eba8b7d78012f638ba220eb" +"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" +"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" @@ -938,21 +964,21 @@ dependencies = [ "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" "checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd" -"checksum redox_syscall 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ab105df655884ede59d45b7070c8a65002d921461ee813a024558ca16030eea0" +"checksum rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9e7944d95d25ace8f377da3ac7068ce517e4c646754c43a1b1849177bbf72e59" +"checksum redox_syscall 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "df1a5c588807af3b0cbbfa2f1358f2d5ec6ad546858c1ccd30dfbb127021706b" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" -"checksum regex 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ac6ab4e9218ade5b423358bbd2567d1617418403c7a512603630181813316322" +"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" -"checksum regex-syntax 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad890a5eef7953f55427c50575c680c42841653abd2b028b68cd223d157f62db" +"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" "checksum rouille 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d6415f261a8775bef50e9fcfb14ed73209ce637f753f9d1c8c6122559e559001" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum same-file 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "70a18720d745fb9ca6a041b37cb36d0b21066006b6cff8b5b360142d4b81fb60" +"checksum same-file 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3257af0472da4b8b8902102a57bafffd9991f0f43772a8af6153d597e6e4ae2" "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" -"checksum serde 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "1c57ab4ec5fa85d08aaf8ed9245899d9bbdd66768945b21113b84d5f595cb6a1" -"checksum serde_derive 1.0.24 (registry+https://github.com/rust-lang/crates.io-index)" = "02c92ea07b6e49b959c1481804ebc9bfd92d3c459f1274c9a9546829e42a66ce" -"checksum serde_derive_internals 0.18.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75c6aac7b99801a16db5b40b7bf0d7e4ba16e76fbf231e32a4677f271cac0603" -"checksum serde_json 1.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7cf5b0b5b4bd22eeecb7e01ac2e1225c7ef5e4272b79ee28a8392a8c8489c839" +"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526" +"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0" +"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5" +"checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" @@ -966,7 +992,7 @@ dependencies = [ "checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" -"checksum time 0.1.38 (registry+https://github.com/rust-lang/crates.io-index)" = "d5d788d3aa77bc0ef3e9621256885555368b47bd495c13dd2e7413c89f845520" +"checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" "checksum tiny_http 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "016f040cfc9b5be610de3619eaaa57017fa0b0b678187327bde75fc146e2a41f" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" @@ -982,5 +1008,8 @@ dependencies = [ "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b6d201f4f8998a837196b6de9c73e35af14c992cbb92c4ab641d2c2dce52de" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b09fb3b6f248ea4cd42c9a65113a847d612e17505d6ebd1f7357ad68a8bf8693" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ec6667f60c23eca65c561e63a13d81b44234c2e38a6b6c959025ee907ec614cc" +"checksum winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98f12c52b2630cd05d2c3ffd8e008f7f48252c042b4871c72aed9dc733b96668" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" From c08a598d3fc9e45de1f3020f6c50e153ef0073e3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 8 Jan 2018 12:33:36 -0800 Subject: [PATCH 0067/1504] Fix broken file watcher implementation This one took a little bit of tracking down; the VfsWatcher used to spawn a new thread and then stall/park forever. With one of the recent changes to get rid of the extra thread, VfsWatcher started getting dropped, which in turn dropped the watchers created by the notify crate. Because the threads only tie back to the VfsWatcher was a cloned Arc>, everything was fine, except that their mpsc::Receiver objects were no longer receiving events. This manifested itself as the file watcher magically not watching any files. Oops. --- src/commands/serve.rs | 11 +++- src/vfs/vfs_watcher.rs | 132 +++++++++++++++++++++++------------------ 2 files changed, 84 insertions(+), 59 deletions(-) diff --git a/src/commands/serve.rs b/src/commands/serve.rs index e8cb2b82..998001ba 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -1,6 +1,7 @@ use std::path::{Path, PathBuf}; -use std::sync::{Arc, Mutex}; use std::process; +use std::sync::{Arc, Mutex}; +use std::thread; use rand; @@ -87,6 +88,12 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { println!("Server listening on port {}", web_config.port); - VfsWatcher::new(vfs.clone()).start(); + { + let vfs = vfs.clone(); + thread::spawn(move || { + VfsWatcher::new(vfs).start(); + }); + } + web::start(web_config, project.clone(), &PLUGIN_CHAIN, vfs.clone()); } diff --git a/src/vfs/vfs_watcher.rs b/src/vfs/vfs_watcher.rs index b1db63b7..f5d50174 100644 --- a/src/vfs/vfs_watcher.rs +++ b/src/vfs/vfs_watcher.rs @@ -1,3 +1,4 @@ +use std::path::PathBuf; use std::sync::{mpsc, Arc, Mutex}; use std::thread; use std::time::Duration; @@ -11,77 +12,94 @@ use vfs::VfsSession; /// changes to the virtual filesystem layer. pub struct VfsWatcher { vfs: Arc>, - watchers: Vec, } impl VfsWatcher { pub fn new(vfs: Arc>) -> VfsWatcher { VfsWatcher { vfs, - watchers: Vec::new(), } } - pub fn start(mut self) { - let outer_vfs = self.vfs.lock().unwrap(); + fn start_watcher( + vfs: Arc>, + rx: mpsc::Receiver, + partition_name: String, + root_path: PathBuf, + ) { + loop { + let event = rx.recv().unwrap(); - for (partition_name, root_path) in outer_vfs.get_partitions() { - let (tx, rx) = mpsc::channel(); - let partition_name = partition_name.clone(); - let root_path = root_path.clone(); + let mut vfs = vfs.lock().unwrap(); + let current_time = vfs.current_time(); - let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(1)) - .expect("Unable to create watcher!"); + match event { + DebouncedEvent::Write(ref change_path) | + DebouncedEvent::Create(ref change_path) | + DebouncedEvent::Remove(ref change_path) => { + if let Some(mut route) = path_to_route(&root_path, change_path) { + route.insert(0, partition_name.clone()); - watcher - .watch(&root_path, RecursiveMode::Recursive) - .expect("Unable to watch path!"); - - self.watchers.push(watcher); - - { - let vfs = self.vfs.clone(); - - thread::spawn(move || { - loop { - let event = rx.recv().unwrap(); - let mut vfs = vfs.lock().unwrap(); - let current_time = vfs.current_time(); - - match event { - DebouncedEvent::Write(ref change_path) | - DebouncedEvent::Create(ref change_path) | - DebouncedEvent::Remove(ref change_path) => { - if let Some(mut route) = path_to_route(&root_path, change_path) { - route.insert(0, partition_name.clone()); - - vfs.add_change(current_time, route); - } else { - println!("Failed to get route from {}", change_path.display()); - } - }, - DebouncedEvent::Rename(ref from_change, ref to_change) => { - if let Some(mut route) = path_to_route(&root_path, from_change) { - route.insert(0, partition_name.clone()); - - vfs.add_change(current_time, route); - } else { - println!("Failed to get route from {}", from_change.display()); - } - - if let Some(mut route) = path_to_route(&root_path, to_change) { - route.insert(0, partition_name.clone()); - - vfs.add_change(current_time, route); - } else { - println!("Failed to get route from {}", to_change.display()); - } - }, - _ => {}, - } + vfs.add_change(current_time, route); + } else { + eprintln!("Failed to get route from {}", change_path.display()); } - }); + }, + DebouncedEvent::Rename(ref from_change, ref to_change) => { + if let Some(mut route) = path_to_route(&root_path, from_change) { + route.insert(0, partition_name.clone()); + + vfs.add_change(current_time, route); + } else { + eprintln!("Failed to get route from {}", from_change.display()); + } + + if let Some(mut route) = path_to_route(&root_path, to_change) { + route.insert(0, partition_name.clone()); + + vfs.add_change(current_time, route); + } else { + eprintln!("Failed to get route from {}", to_change.display()); + } + }, + _ => {}, } } } + + pub fn start(self) { + let mut watchers = Vec::new(); + + // Create an extra scope so that `vfs` gets dropped and unlocked + { + let vfs = self.vfs.lock().unwrap(); + + for (ref partition_name, ref root_path) in vfs.get_partitions() { + let (tx, rx) = mpsc::channel(); + + let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(1)) + .expect("Unable to create watcher!"); + + watcher + .watch(&root_path, RecursiveMode::Recursive) + .expect("Unable to watch path!"); + + watchers.push(watcher); + + { + let partition_name = partition_name.to_string(); + let root_path = root_path.to_path_buf(); + let vfs = self.vfs.clone(); + + thread::spawn(move || { + Self::start_watcher(vfs, rx, partition_name, root_path); + }); + } + } + } + + loop { + thread::park(); + } + } } From 27cf2c8740a4e6dcd04b6195961989948d3ab205 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 9 Jan 2018 11:31:48 -0800 Subject: [PATCH 0068/1504] Add error context to output for JsonModelPlugin --- src/plugins/json_model_plugin.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugins/json_model_plugin.rs b/src/plugins/json_model_plugin.rs index e9025b2a..e7b2470a 100644 --- a/src/plugins/json_model_plugin.rs +++ b/src/plugins/json_model_plugin.rs @@ -29,8 +29,8 @@ impl Plugin for JsonModelPlugin { let mut rbx_item: RbxInstance = match serde_json::from_str(contents) { Ok(v) => v, - Err(_) => { - eprintln!("Unable to parse JSON Model File named {}", vfs_item.name()); + Err(e) => { + eprintln!("Unable to parse JSON Model File named {}: {}", vfs_item.name(), e); return TransformFileResult::Pass; // This should be an error in the future! }, From 1a1b6d923feb01e3918b41d70e0aeaa6f2a238f5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 9 Jan 2018 16:40:39 -0800 Subject: [PATCH 0069/1504] Fix JsonModelPlugin setting the name of the resulting RbxInstance --- src/plugins/json_model_plugin.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/plugins/json_model_plugin.rs b/src/plugins/json_model_plugin.rs index e7b2470a..0a5a8da9 100644 --- a/src/plugins/json_model_plugin.rs +++ b/src/plugins/json_model_plugin.rs @@ -3,7 +3,7 @@ use serde_json; use core::Route; use plugin::{Plugin, PluginChain, TransformFileResult, RbxChangeResult, FileChangeResult}; -use rbx::{RbxInstance, RbxValue}; +use rbx::RbxInstance; use vfs::VfsItem; lazy_static! { @@ -37,10 +37,7 @@ impl Plugin for JsonModelPlugin { }; rbx_item.route = Some(vfs_item.route().to_vec()); - - rbx_item.properties.insert("Name".to_string(), RbxValue::String { - value: rbx_name, - }); + rbx_item.name = rbx_name; TransformFileResult::Value(Some(rbx_item)) }, From 72557c9d2348a44b1f17a58254dbbf391ec6dc27 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 29 Jan 2018 15:57:10 -0800 Subject: [PATCH 0070/1504] Hip logo, totally not riffing on Babel --- README.md | 13 +++++++++---- assets/rojo-logo.png | Bin 0 -> 42784 bytes 2 files changed, 9 insertions(+), 4 deletions(-) create mode 100644 assets/rojo-logo.png diff --git a/README.md b/README.md index bd42ab5b..6e232794 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,22 @@ -

Rojo

+
+ Rojo +
+ +
 
+ -
 
+
-Rojo is a flexible multi-tool designed for creating robust Roblox projects. It's in early development, but is still useful for many projects. +**Rojo** is a flexible multi-tool designed for creating robust Roblox projects. It's in early development, but is still useful for many projects. It's designed for power users who want to use the **best tools available** for building games, libraries, and plugins. -This is the main Rojo repository, containing the binary server component. For the source for the Roblox plugin, [see the rojo-plugin repository](https://github.com/LPGhatguy/rojo-plugin). +This is the main Rojo repository, containing the binary and project server component. For the source for the Roblox plugin, [see the rojo-plugin repository](https://github.com/LPGhatguy/rojo-plugin). The master branches of both respositories should always pass all tests and be functional, but are not suitable for production use! diff --git a/assets/rojo-logo.png b/assets/rojo-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..49b2a572af012006d9a74c6389092eb717feb25e GIT binary patch literal 42784 zcma&NV{|1?v_2f$wrv{|+fHWUOl&(Rwrx)`F(u@mt?z}In5&s_GuIe)4V6`(uXa6Qp zmSRd`U|&dRle49{aiagGG#u-E+h@D=z9wt$ph8%0gxnLnp&L}Re!D+6_DX!;# zwZ3vmTJTXhOY;AkEjJW&RCScUhrK)aJa56`vV3oI+8YQ%{Qo&X!Wl`@`JZ=_2I2a+ zeo+`_v88m*?Gd#L(>Os#{P&qdJOmSbY@j#I;6)w`BNy?uDn7^prfX3j(8z4%P>!Zo zkWf5fWcFt(wABAlrD|RBj&zUn9{No2q?e2fl#1IW&c}>k0+Ic_#%4jZ!aV}F7 zjmec_y+OJ{g2Rn5tLT^`5T@y$cU zWB(Y{n|uW@Q^4LCOEd1;7sNLLLn^Y+rR_L+>tc5ZP5GxzHeaYQ?f6Ej;Cf%+^iio2 z;Bo+kzEb~#9+5ZP$no8Jh`c}Sh>DW61rPqGU1>1R zy%b+7gh^+OUE#PoOK)SM(S!*-2&Vns!RZi6&;%_Vwu4gtdN)dvLBbi0LJ3YnpqJL+jVqdHjolNVl@m(AyR4#xHx}Y zW%{CpQZ3p_ep??_4v8G8^MNm2+z^q&0HyKHhr=XhynY6kchsl46=)Q5Xsc4#;!J2d zUQ7EP!N~Vd)y|58kb^nsNR4DP#NLksbbF)Ldrp$F6?B@df;&^tBpZEqWYD9tB~CWT zLv{#!g8+^1AuH_{d%^(woCzN6MFEE6rY1V;3B6nOo{TxU+Yi(O+3kD#CHv^Xd6>a~ zB*Zw6|7<}`jAV)eA)Frr3E!m1HXs!pX)7!=qD(MhN-KcAsyLlv*FhgG3ztnIvQhFN9p# ziyi|T81*1*37|u8s!mkG9R+q~_qr?nx_$*EcFLX3ppH^HPPLV3J_D9|*Co%d38);} z39krIDMS2G$8E=IIBvM;f$2nB&P&G{ zBxScs@bD-_Px`SvKFe5)S=uT+)-%|oLi1!kn~A7Sj8!SdxH&cklaCV3Kz$Pi9{&Gs zd49kvP`?QsZdyujUyf_Y22C4k4iuX>SL_bm)%0Q|@Sqij#6>|$y!X`d&vr(LEP#ssun5Z8F?~pw+e#)>caUtN-(boP1H=5L ztEEo0PG>s5i=@va$M8I*;k0UPSUE12C${-Bt1}K*MGK{u5i$_A5nulU2^}22HzHl! z80IdSTXv|mM0mOl!Pxs`P&6TZNDl<^>X||8*W_8Fno%lB5cjAKwnHVR98llv0<;~%Q)Q6Q@8yx?B*}ng=bUZW~4`PH= zQRp6_ZtXtIortl1>ARK~HJ@bg`P%%&8!cuoN4 z>v#Gr)y%p^J}S1<9*KFClDt~8YVx9uA(uq|Cyw_^y{E}mG}E6DQQv4W#^Gfp>F8c! zw+v?jNlpf3?qUj^p~55`|JQNEN6TU1ILeIMA;g%H#vt`sVUo*^Ns<1L@swX%F-+4;Aj-$(%>RujvXo$p0?_^Yl|Ww!AonK< zcb%mcb9mYpx8fVt>&m)0A;Kg-;Knn{=~}se!+{L{wvR6#!mJ3~HfgcNRjue3;f;?ZTF)=!dwNA=&I6UdFGm5REf&{8q#cO9`X;nubX`cM7&GfrCw4m^2b>poA}V2= z=~X1XN3FaiK;JHye5SqcY>84%Qj~8}0)P{P(zD)urm=88Br3-}bNVnblV0x4BJJ$N zWFDOP9DNW=Xuq2}@0rHlqF}M|As4lq%eto2Z+cSPZp56fwZk^(qE}NOL?Phxy!oZ< zwa6Q<`*|dTA9%S`V-oQ#((`rY&M?dLsB4FZhE_)@PB;~H);lE;Q}qezdE8Ay2E2R< zpf3~tBG2wByl67RU;%G;Vpq(BstY6lJsEPO(NHZamf;yTK}U&jFO4){P`m zA+o$T?jP~On^N);w+Z{74d@u3*6T$lYTNTk&&O7a9+E~X0Uw_fy~oG;Yjr$DHU8KF zmsdZ;Uo#^Vf>^#Iq2VCiw9xTc;NN8k*5jmjGqZQzG16;=7kZb4S%q0&Q%iK#;EY@H zkT+c5H<#XXD~0_zg@RJ)MT0ilJK_gH)=0R?jM(t4po>xv(NQfBp0%EKkW|J~`ch)h zlBsfFeavANt*jc8O{(rqR9RX4#TC12r&a5IE~{;Df|llO3+0D9>}SeHx_KA} zrrmMtq09o(PAjUUi-T96s7eW}XGVCE*TmW403^x#6rO0I_`8|PIScMAL+U;G6RY?9 zh4PPi&ZriK@4+*!0d&y!D-1(Va{>+OY%{LLJt2xf^?-c-v|3&w1qjJAUXIS{*XU`K zTzhztgLqq|?wE&~*I|iYKd-LB}=7xa?>4MxHM(wsqE;pnjzz;}RFAZABy27<$ zwp@@dhw%_Npe};v;LVn3TAXdrjWSNta3lnh2xDfLaZGF=6m%a}ygQi3h>LQ~-*RX~ z+8JPc4^Sj|l_a(izd{DtvsY#UBzJc2J=k06Lb><6UQ{}8!Yotp^Q3@k2_((Npp4ZoKuGU3 zGGH_5L#+nCcoqEe)k`JFbsdmx{J65aYlYjtutD2-JGO`_l5;4{@mJCty(llgQn!v76fp8IXR2-VanRMcoiT)d(Ek;WNaWczP6KKz>*Z& zQ9-1LG`B>G+VCjVZ}Cu_ZHzw}+p&b!C(I8VO;yPXT8W_g4ttQl;ODmz(MLR6@|dMF zXQ&gi7D?|SmPw*7qcQGS?qh7)d7HB!qrcn25@m5TYg7uR6lv&f(|Eu$w0l z=Y&AWYOjtXg)gHTF=7sUE1L6%if;rH>#-#tXPJgs`~CyxsXv~9D!whNwBz&CT?y_{IKrxoUEFXW6;Od3T~ zyT;Mv-2JjD@bHKdrF!Q}5QTeaq!KvhksM2?+UPqg_E}sB?6Jh?8qO`Op&<%6t_Tf9 z$xzD$TQ53%D- zj)x0;Qpc%LK_2;CO?B_h610R#(p>F>9R>M^5`XWb*9;1CFH8K$f+h{e{?I`3;-?x( zHQ$*_4)Q_4%b-A)6PO7V5Apr66UtyrbcRj@Xi~b+lLD_w zEXI&CPU6^SU)axru3+7(kO~5B&s$vfvql%)ubDsChcZSzs7fmKGR@uoL@=|l*n>nI ze6OG~*%1p=()P3wQz(U9+Xs+W{;Mfz;`FGr!9lTjm01@ zUuNc59odLx9A^ENBc>E;x{5Z%lM81qYEzhM7{VtWmyXGCuI-W0mU!}gZdkR1y`bZ1 z;{YAEw-c%V+VU3 z;^XS=NnVtyYD#+Tt&)yLG34Ie0@{+Nqy#rTUCQ_-w5dSG=c@op4Dn$VF zM;M1^#PLiK)}_iP)T7EuY`yyuZciwPaYF5ZwR#F_=0&U z0ZkU#xLo<0TNijA?A8PP&u zqmf1DQ)WG>+3OFC8C2nVl08cdV@%z~BS`bsnGZSL=MRkAj&L>I7>)C1)Z$B1?OP)+ z{sIf?oG(|8pzpICGdxf_wDq6uNcPV?p}ILUHdh_O9Tj1F2Ju}AdVvfy%GPKrX5gXO z&&95a=bX9^GC};X9KpLfsWy#%S4zHbo{DMIkEJ(FONwpZ3bwq@RB& zLZ!bF+d!ICgY6hnE3t{HC1v0^H=U+@?DMVqy0yE}z_)Z6Pei&roV+l_oqGDAm-elF zu|j%;gT#N{6Ekz^$J`MC&%Xhx`|26W^}SWX zJ`uIPGG0PLw?0@1dqf=1Rf$PD{ta5e4U8!b9m^zx?gSf7_`qzn zLY-|BbHrqzRTC=*dSDf>5sKN6#Cu#bMBk8c(`Qu)I7vH%Ia`WZAh!OA3wh+C|1^j& zacsw5zTOx`@4|cq(8C#W!EXmrH0jM4$g{HOpT<-{ACtJi{i<^(322lE399tF@ycDA5_ED70cE33qfnDYOdugzO|DG^T&|V!!@s zz`%V$S9yDBe~NlZs;HK3qzPW%+u{>~|swGom zq9A`bDP9^{lJ0yT7c?ZpocM!Y1MJV973~b&X#UQt4>?XYa^oiX-ETSm`iI}o7T6ir zFra8Ju7@cp%7*%@=lx)hxFa;__@gOQ2q&ODCF!*A8(-?s?OL!$HZJ-v6yj~$B)4Rc zayDDMViGY^8k6SL4zSy^|DZs*%7psHmRM=a9Q);otTAZbuan>+NSj5@3%*aHZDrqdX55riaY1jdOg%Bh0MuX`eTNwmQH!S(RSPkF_5)n zktVjpSnOqe_?-EJ zjSBk`3GG>FwVL6M#Jl33vDE9@ow!uzU9Kx6E^|bsOInj+E9cNyr1qv_)PNS+ zhZ0>(yB9o|PfAtu-m6A)jL7B*>MR1@Bq|sEKCu9LYvDTk?7eMU=-{!k1%C7J4jf^toxmjqb>hNjvGa# zF&y1JDTyc(WoEom9Sx0>(2_0=u^5JKx{%6TXQXf0$z?4EjGP$mX87@o0<(~Adh1ao zQMWwbQK5vxYQC!r>|LSCt$pQ7ULw*Ke~4-qo?YMU1M|NqDBoxVLEPyrW>Z1o2xaYK z5g89=R>ZUhlJ;wi&y?GVK`B4IC;{+5tZqc90xsh(O2MqyB`-SY*?aTmg2TsA-NXEI z$F7zS1H@Su##(mctv51#4=GpUkS(Manr_sx0)yB@ugv)8>8VYO)q zaODk1{R50@ZfEdtAWyXNyLmeObKNGc_&)L?{+p8=PCX9&hRB--yyA?sf$IRS(;N&e zf+Ce7kh)E=QK5(QH0Hf-xP-(a{(@}<=%XILrr`S9H11Q$laB9PvkSC7sz|hxhgT!_5rUqKr>V~1a5`zFwvN}11glIF`OlFgPDQ_hg`EqiXQ(7)1z1@>emmNK$; z#7L|6$ANK#Rg@=CqgilDfvC|t?jm=hMo1U(+XUyb0An>=L~e|pm^FL{f0(N7(Z7=ngns2k zjNgbx`h7ij(mdv%lmQi|L&~6?E8Etms<5)0A!~w`SK!L}^-y{}!NqkHgP%Vx-KIUm zWOpXifA)DZ1{!4rzZ1IF7<{CaMFrMTrOmEV+`ibjE&chG!VxQMlcf35DwLKzst&gN zeD--FdSo~h{cCW7Kj1H}OL1|^F1u)0a-*Z!xy4DzODD?I*Rj<_5FxYIPl>;dKJ}PB zPa*1Biud5Sc@bSv*#Dp?79{vNV4D}$B^87AHX!L0FzqoxTIZyz!ur96Cj0J}baY`Z zkE_wyos=g{z*%?S?;8wl>y9v^08`C-grcB#e^lRG^}{x7{kly#alOW}mkU(MXl$&j zhLUi@bXY)qDd76Ut)Vp&EDsLX3_^C>xhY)ov&9fEIzLjZ9EIO z!a&u6R@)S^EbXn*vFMxxU%-wj#ZP|N*q_OfLl5*)mbMzq&w9atKI` z8uWC=N?fRor|8lYv`hF)u&O$7S(OyHz)c4#CCyK`TXB+}S978>vG=h*+~mpa)U7R) z_9cV6UkR(|ydu!F4nf^j)bGVAjzhhrWjVURyIQx(e;#13Hg zV;n1*2DrummhM4%#D&!T4YDVus&g5hw8i(I)j&M_ex>eMauBjCs@1b!M-9CRKJXltkz!G^f$Cigx#IY zM`$g9IEP9N#^!#P>))DtM`J+Q^mGK;jMZ@ICm)(b^jvNtVO+O9kWY@k3QdfVCq!o0 zF_0f*7IV#>bQJk=_^ljiN!JxI&yx)1*EZNk)HJ=>cKUP@a_uVYpi|Zj;gQ3z7&9`x z;;e+!;F{V({Rf^8AW9}GPWo+`#hu305B-Hmk2}2-0xr~QBv9!X%b+BQVO!F$qXg

!O~rsrEHu5}BeX_8v=$$z%KSsq|^R(dcJn24X4EFC?w=pdHyF zXZYEvCQO$W#tJ1tw25OU^M|a3G->1{N`~k!s++8U=0@VE=MUU-s<{#DV^u3A@zcMq zs^4Jt>A(vY;u64=_ea1Z(AD)N71>|MO?2la%0h=${^T7xapTm+|J4@l9m;>M^VIB4ETO-d?gQ2La z@n;lKw%-tcg6lbI)!gfvu+@t6Fnd3&8izfBpAkd&iRBmIyxU~0ZgDk3?KU1B2%_Dw zDe8@c`efSVOS!Soa%?pYjPnQm#TgnIe%q*EzoG{o{)h!>sC)y$5C~-4ugp_WhZ7PE z`7_lej#&w>J@Vw1gY8$6VJL}E5fCI+*h@7k6E<(qFFtgj=1ri6-j5&1jfeN_velf+ zGnh^4mI{nj^G!7txQXD>6QBHy47mv%%?0ChV!;@vf*ym1o3;&g^@9}`u)p^6=%K0S zx+tnWxpYhPxp`LYZLkP+g+rz-HStHbuv`N&nB)bMQ<+D^(3BlTt=sS8iX@7I0K`@` zwUR>ZfCGj_%8w=XU`}+nF67}{-xXdj`eEvvfZ9eAzjl}>|F4MOVvatSQTK^P9_R=? z1VOK;U8%qJD*ZxxrH-we$#0CTgw3src)1$)1NZMm@5%HwLI-9wA}{%3*XpiiHurwB zYr=fuWBybMyXmE$yY7O1RJjtnd~`2*E_v`*Km$?i*fba!Mn&ijL8dj?2zxICiUOW! z3#2dVAMa&NHE{|v`fgsKh#&IkBQPdg8LUUQJ}O1p zZN;zkSSD3_LwSr+rqWI1w?UhnfGH4Szr_wE6+~l<7M;lvE{=e2Z;mzQNzp3}9!ep= z&liap=-E^{UrI3a1k-%o%Z_YE$xb6iI(CCc#Tm?fwxNtCE8n=8>x~MalfN& z8YE~cGb21juo~aFhzfm8hfgxI&$*JnLAEHHr9oe`LJT?b=cTm45I^q7FqGX+M)iHF zNrSBn9gUTEILHpp^6(cna(sdQSXG?kmDjJV1K(LB`>CaXfBSCIN4j@nhGs(|H6&2K zX9Pd;Y+o=UBeXc5gb@q{ejpWdFRHpB<6pISu zVHkLj-FEEKMR=Znf3Z-r&6Bu1lxhtFt2W)lOaDAe#Duvk=;*DFj;{<1AXChsFZYdHrZQsPp)g!eZKe)+?c?l}gMaJhu4{S0)hZ{o3Dvny ziThtKL}^W@?;!)xo+XC`LQW1pVd?#w0-LE}$jd>RNVmSLMGc?)l2^q11CpPlNS3_G z`m&_IjZ$1Ut23d#Ds&Siz`19FQ&fQ~a=^17>O5O^q5%3!K^n_FW4ScYzAdpYbJwT zO_0D&FMhCX^5|qUeRF zBC&0O4fIdWh%O~Wv3Nr3yas3O+EFPyTNM?be)<~Pd-+X7c+oJVHFlpdu*6S|L9{+I z$iUG$fu&BoXA-HN+~Q1(VCg)T#vyIXB+v=sA;p08hf}a3y7G&A-%NZNWTC=PK<^p} zE|M1xB(%xa7c;X#Qp-aTX_B3NqKDakr+2D^+wi7lGx~LtP@;Kl#r(IbR&dP&8pZ;` zoZ;2)70WAPvW?I=7LK!*;5DUAX8!TDKJ`xDJ8Yy{0x7#eWG%;W7?8^jY1wDyPf~`- zD%D?By))dEcEz&YL-uU+uE?W<*?ghxV8YV1ty1#vHw6u3IfHGTCt=?N8fD$A7nNXs za7`$AycR?kU0SmB_`@_cdnL^F`Q8^B%fW8fUOqE0jG&fNRrxhSc9(%CeJH1m+n z^zr7C&tw|6TL+R7=P;~bPlVF+Bz#vS2i2W6yk>ckwUuYKw%IO&5Bv@@re(GtxmKG2 z3f^Xo@b855OB!#YceYC>n)$x!3S!U@Msoe1?90e`2_lEiWW&Q zf`E+m>qog8K{jKezde{p9@jC}tiipH(jo+|x*D~6xmnZ}M zp&K&j?5o3oligWx6nE!B%}240zX;%mzn9v*@PRAY-x=%z_^l_WwU_cmc>?ob;k!8_Gl(FPJY74%;|JF$jY~l%8Gt((4`9S!W0X4XU!&}-TTy09fy=>U2 z!6|%DPgaMzFY?1`YUV-X2x*j)=#l+0W~T?cm#e65>bIPx`ud51_!S`)Q)>N=CliJY zHAul1%=V9kXXL^k?EoBj!N3n);R@e(!WDZkhnZ-oW6E5|h*AG}vlXvh&fMpC_Lz zElDUK^P*bB3rUa|E!83JRCfDQfpj6(^F|_CJ7UEJHlY%jJ}t2;-jh~FA9F%BX?uv? z7{uYQu^k}stUne>3Rh&mxSCX7Ic+2XIEW*E`TG&c2qjF*h8Q4f{o^r9*2Ic-aWk|z zX_-C;qM)pziV>|8&F!ZX3Ra`Z1m7M|>mp~re;Vg9ec4K&l_~xJjfo%e^`-#6Kpk3> zD5)3{Ky~HtbTs>qrO`MOcI`lIXY%VSzM$sh-7YLB-bQ5iB*^W!5U~U%YAK+3I0c~` zuVa@i_5};dRoW~I#ql<4tg{i$5L!mIifBq8!^)U&Qbiru^^16gn4W93Csy`%R!B~O zX(-y*d`mH4-|bL|ns*@}3Sd`TZF`fn8<5^&^00Pi_KuZy?CcN z`$JosRx(Uxv(RUfxoqdhtff&G;`mq#onW5O?)SbPOUi+`+5T~S8iQqb>8Q`F8Pm-A zmSes=rOZN3p6rUg`y;1r=;m@#Fpsk(JK!;MX2W4@5JKq z^@rT_L2`%Dc&F#hPy?j{Q|L`A`LVS?NZA7-`P2u2xrB&@v%rG z;y?r%s+EX1{n^UJa~tBV!6DlDi|AseH!%{5N}o7~(C*|r0 zy+0U?v{)ZqQ8(PRn^0^uWIa^DnD5I_-8pzJrMvEobr$+^#ar&MJm5Q}G-0TzmX6g| zdJ7>)5aQdak>O+ML{|e)epGQSCd=DPXjF6L!8-dH&jlY)y>#=c3kre*5`Zpjh*sF12iBXy8;3AD_< zeapD>-i#Ql!kjDjPSThoxJh!I4#5i5sb9pRujENfarb5w_ulSe;ax)4NlV)2^f44t zp0{nlS4~`g=`W;_g6_({S9KFd+n&9lQT_AuG+-Wto zaa9#)R(ghkM;5;Vr!o-eu&9`l(xgDAK)2rO{iRiuS3cXo1$1TK{T%t7gvmVOjL*5B zLeYTbogr^#Nu7GDvGIH2+j*&oS3lsf3U{vIQ*CHazvBGO>QGE7!Y5`p3qId86A!}AlP<4zVhlZ4U-eAu% z!6^aeldWH#bUFVGoWG|GBlHBL60muAZ}F+L=>@tf+eCXu2sk!@K8msMDgI(^Z{-;N zL}$Hcl>Rj2QEJ+W{y14S>w$n#{AgDY+Md6+#^*jF>#;l?6 zX*fr3XnV6p!+YB$B9X`!*HT*!*6+j;UVG+Vux9*m{I%bbM#Pb9$jqEF@0*T9h+;`d zN-sh;+|Q)w_!6|81g2G2w;mjB%eq!g2fdl1LOsfj#uhk{qXRVF$?}b&R$jcvdXp7b zjZ^fA>;X3}3v6;CmAxH`Xhg4;~g5yD&M5Z(yYC0`L1n zF6NS4um60q8TYf}epdb>djQWizx(ks*~216-(&kK2d(|_r=*A7b<(&yI|MYs4rS4U zn-($_L1;H88o|Q;wpAgH-0Om*o$zMWbc#OO((ByE>#wr1QM$P*Pci|TAy4ps6ywm{ zU;Oyy{@2H)Um}wSOdwHP+$gAF0#=N`AK^6Cj%L9Uk!4oU4ByoQvX2hUELELiJ6llb zz3gSJ)bx9v08{rcXXMy$Nb*gr#(%moz0Gsapq-}8i2rqPapEe)iXQApidB;5XQ)_J z*_38G@Vk1KL(D&ERReNiN8pJfGA8D=d3`fE9#D9HC&f1WK&V+Jnpsl2iau&ksFf5G zD^~bs!?ILnoGS^=5N4o%Z%dOq1Ym!_L4twAAfk$%v!Lr*LA;0TB0BXZpdx$sbdLmm zYPnsmuPMAaVoC>)R|kO}WgL)k!l-EA};* zW21|yBj({RepXxv!N7?w$KEB6QQG-oN%r^+&AErbqSR7%d>Tx3mqwE4ETY7Ni-})-2>L}_8Ot_MvYuPV#d;$>!@&)J8I!va}sQDv|mzyZ1N=*GG?@U;;0g|ou zpHrj;@=T;Fe>*00xPS{BKGtY!CFZ)xj9?i%Ev;#*iEzRqk_r|%f) z6x6py8(~f8;KbHk+dF;s9}Xt_A{jr$tW+k zPKNcQiXs_?2a!#2%z|jO8$q(ljP1fnExUa9MF$y_6{TSt3Tg@vFZdQC&ua?NFXP{a zR)+cm!s=A&>2Qo_&VS_9e?9wJ)%cZ@1`A=6r;y5PoH-`jh+n+7d=;VUq)JSWaHNrn zX56x1DHVo`lyVVK4Rv280_9(%p&>_3`#%xyXA z@_xY}3;bx==`VoZah3srf3Tz4p9JO`JrEfAE{pTwu@mOQi28Nw^Rx$Xq5)^ZZ{#t< z|H6lOgd~dnp-B|V#T!ofikC57iGmAAb#%X^HrW{v*|GXp*WK)l6J}Fw(W)Au@p>h3 zUe9EpZA+C4AM5KRr`s?uj3&sFPt47hlI>G3R>l&w&saB;r6Euz@u&0UIFA(q9yIT< zvMJp|jF+&1I4Z#^7YqWWm7RSHZQ2oN2EypX!zfI8R4%Izm$PhvUv=146%Tzq+1RYg z{f6D`o9NZ;kqkp0)ql1QU5Ek*5y z>~$kSpQxw2ps|(-3uTCp&T51IWdzM@_n|fI=yJHT`l)_!^b9jvm3ycaTk;1vNhKK6@+hM%YQTfixma!^@_J7oO}u{~H}dOt$c_1Bb-D|YiMs2u%k;KQ26R8>xh z0?AS5%csvyKmI~v=i{9;tk8G*%5(iXIFxDxE#Y*Rhe2-!q8L%@=8VbYIEY!y-2KB& zGu$0P9Pxyr5bI3e*Q*R-ob)BhPM+dc+t60#x7Uj_swr=c#6@?3WVJVB*tvq0-zhiO zC(yasu?KapL|#*Qf=tQoRf@XoJ-d*A>?7YVd{Wm38JcE(S#ehFz78&34T3Qc0~B2+ z8e&0rK`4!|^1(S*?6i$OIt=&P69lg_8+0Swwe*Uj;w(fWKhQB3ew)yhZd)o^&@ts5 zcII%hLtNhSc#l^t^BLN~u7cPE^*K?Bi-@TR{KpAA$-MisE$KO$=ARfS)PCW zXa6QYJRsM>$njLiNipmX2Uj2}V)*=Dj!XP{?e1F-aECp{Wc zHMasBNQy1HkcE3r!3(^5hFV}mFg|Ae_AR(Vbf=A|?w)?w-Bj1H$WJ_ImZ)6c7Uwup zC0o2++8ScZ+g4X^(d5xp(ipVma^RNxM^;E-?WW0VjpF9|#i_A88TFVkS7 zmr`fQhw!O@Z^|6v3AuW5{%NPw>PLOgnNl3499F^*n%`+g1wM9>CzobFOPN#Rj$TZ< z__HFkMt5^pf&wkiwEa}@YBp-!-vW$%NOB~4{Wx-lA1xtc0#ofjTj$RYUp$O-H3R91 zXC`^37!doL){C}QMLQ%a$HuMlAbQTTU=SKoXD;nn6k6AVV#k?aqFkxXQLWf3N=-Ue3deiA!T@dqWqJTdY2%nQ{ zKIq2|uuosrQYR9BC^mjSw4RBQKp~jOUQCtJo+AEsgl3M;7g@TV3-5S(pU1GD1hhG# zBHjBPlFBfDq<}x2IcMUvVMwhLrFnCWRR_M+Syk7P>z~dFOQjG8mKAzuDjwP;kK+*Tb>@pJ{opo*{Haa}V4!kK9A`?ZUvH`3 z=@#Z3pPRy`TP&TmuIId;*vnDaNQC)&0=kASl`KeeRO-yv_h`ll`J{V9TF+#%u5(r^~gTU=TgG`N~s(`q7TEH;PJ*A&Lv0Rh-czE74ws za}1eK_ydZA>U+Fj_DbNNm}cI{-|v){5;T{m%|zoLjcA`;)Nnm1_7~=52Kw_r?Vg^z zGG5aO9AeNrHhHK~UepZv^T)gs4+4!+#7)zs>J=1C5}~JWqF=OqvAPM75}15N%^|7q zn5D}8dm-+)DDk(G<7ul|{PNw1`Sc*As`2^XKq8!FLC&HS8sxPClM~}n+ogIek(`b0 zzvS!EEf#aK3IXpik)!&s=qp>nr98hUw5S0F)2xXK>i%nzF!~A_ZU}-Z%?k$I4@A}* zf29cMY3+6D5B?B^{<%dBBn-)w!cGSNP3W@ap~FK(giS}5;Zt{Q@Hu@95$baMJqb{_ z8pRg%^Mrfs{#Jqm>K=es?VJD2Qdp_c1$GAOW{WbUW7OY95c{_pT}#zWx;9 z#9`|AAJ)jVx3W{Bd)ZhF-R*ldCkL?Ou;%10`b@`z(ibk#1t`Kx@hY0f0FIpq>*MP# zNXi^;4-rsG2IT{I)1(d~?%=`Yq3>%+N+r4BwC$_oI|1ji(uwuoQ4idDCR$e?A;1ha zA^Hu~9#WwZ%)HR`Urq5k%pMr} zcO$jl9*n4jYRQv?f^QcA#I|ejv+sPB%9h^bQBONtAsZ6JgS#kq3sW%zYFt_ZBmDlZ zPP;?AJS${wzzF`r%G?BywZ>kWdr{k?g4YEjlRh3{bd0=ZTD48Y*K35#3s$pGCIC^@ z$(nrX!mIKFDW_t3`zNK`)!(jU;_B9iKYG&qRi8txjz?ABH6#2YKLTI{2({yj=Fo7+ z>R-$c{f%j8^4(z&#IJtnn_!+<;>6$u(R80z6jL_^SHdBM@yI}H)vFkPShS-y*V<1z z{np<_(nYV7T2Lsjb61@3AT*=A`EvBYRu4OIv&Lgh}>H zv1T%rV&voLeJHX1x*1WeFkq{;24Z`6C>ID0174qO)!09fQYRr&pJ-t!rmce;abia3 zC3Cyz18+uW=oN$h9{`O&a=#}OgeA>i`)CGY(Q3X_wjk2H4lM&7n~$KRgySpsm;?od zgmL(Y@RAVOz}NJ_O}b|34J{l8ox`($g&MlCikHEn zie5nN$@^ZK-a~Oq^@RHT);h#@uSDap2<^Tw7yii?qTpIi2u08F#dwbD-(MWWCwSp` zKMB9T1#$KN14$%*>Fe4xdogeQWfGcR`*fH4YD_SXZTdE*eC(f4e*Gc@52Ro|Pr5tX zM)X5bM1o{^#jLoF|CFGVn?w;{>T?NvXA<(ql&+43a(GJF#<{Gd>f4t|5q4sTm8^@D3t6W9<;*%nfga^tk@Bd`bge~Q{hsqU1NnKA;8ReK zEb?sUIs4gYrG?jYU=R^(xqzbzjxu=iPD9?AC9v2z#^W0hfAnXFwCeb-BaaLj|AZoG z7K%RTixFi5MKNq;{hFGP8dDSZTI2_O@PERAEr!|a!q_13k^%GC6^Jy{ji9EI57Yl1 zl$=e@qg~)~KkTN}aCZ=%dOrf6=KFKm*L}51QEd;zVf-`++ljz?J?Um=2|Av-4GC#w zV+JzD4$f?8!RM!7M;=GpLmVF;8Px}ANloCZ&P-6!$O5)uB?XE0GiU){XUH}dqrjYk zAm8R5IFUIZrrd_hS;79?hrMAR`{TeQw!H-+JqY*$|qI}+HN*yOt@$M@4R zxtdn$lmKE+Z$x=QSkqlNeWN@7WQVCy8yOx98fi^XiW zLXWlHA;rdg5S4aSjvntxj_$1+75= zU^G+cDrlmDUpS9NmPB8?Ml_M6b-L5;I-??GT0?=-s!VNsFDsK5?p$5Rvt_V>}zQ#*x}-AvUIiu>`>d zdGP2Q4f)B3%S9zdw!@3~lgrRJqT#p85iFXIz=tdtaxZu(BwjFKuHgIQY}jw-wM_Ef z=tgu=O_F(N8{#j$fXGw}o>O^qb2aRh&kdt%b1*m`1^J)B#3BmyO=N1-DVU4ij!6X} z1fJo?%CV;NWitDS>dASv4?#+j7($rWMV_(qvKUuI!4ZdJ*CG;4q2u?Dpm8fr{b6^HEJC3CbmXh!2kMvY z4%Lg3+ulJfa?JJyOn|5OG~``MO+@Pg1I-iE7sQa;$?P6%MbY-JceQmyPyvtsbmX0v z59=CUN=sB0? znH+)h9@=61sNE`k$WTI5bz0l%JOrZ6W2C82Sa?rF@Z|aMYtv*Vhu3gG#I@Ey^7(sF zIbw0`)L0D)y%{s$QxuibBvAWwp5uV8;G0t@I4)s>WEJ)X)p0*H&)c^kx^osh3&^N1 zA>+O05W-uZN9&lo9cb0&lld=Xo%o-%p0}1H5dT~X$uF{vaxF?j7DVHm7xrc{!Ax`> znWD~g&&%0~UWe3Fj!$oU3B;)Ss<+yjqyTvN6f_TbVO#_<1-|3RJT<;5`}k84Uh7=( z?)zZ+gIrszh#^am(+v0>J)MRUh4 zZ4Vl!II7@yk)5F}!bdKL6*>UrDrHXYiqIK~-6qHL&Po_z?-=YD*CwE^qjdILP^e^( zS}5x|d53}qGQ3AuA$)l62!2NUm3&+ zbPM3~c;Lvrm)^g@FF54DR6Rr|+4hs%fd!;7MISm;B==P!p7Xx{^N}}wGQ6_DyRY9! z_-yUDLZj!6&$o06yQ3c0HBE`8&D$|ZqX(t0F+zj}K2UD;bD8(a{W3YJn zF%$(I_&!5|ke_^@5iLi~j=FaHY%WsQT> zhbXwx>mBKbdjbFE!34~wpGQ;pR0PlV!KAP;U-}aoYnpN(PMt(4YiE zP5TTUXNNZNwMQKt3JT-h)P5I;vmU_(w7TB)DJlpH;U7x$->{$c~u?B zz#OfKNr?1HJG{BpkHX0GL3mbm^l>RX%KWH5R#!!7b;j6t0}0+x;!+892|ZdX=AI3R zjhKQo95@Mn?`a4uW}W4x>fUh;Y>TW}@qpgui`rEaLvr{1Xc*A|myyPp3JxtU1-g=+ zb;4Q0w=VX)C#%t(!Z4<&dkuri( zfogG3Rs-n-Q^=gOt67`-_@dPCjx3Pw%!-rV`4m4?QohXETQM2p2TI_7$1DVkigV~t zr|XgLXB)Ig`v$9>m6jVw!bJCb8^2cGtbYb|om&PGid%(Lh!zH|xHOZL)fuJ$t7X3_ z$|_seGyBoe8q*|}-KFq5Md^s>+y&ds`H)`6>>dE4{u8}xp6V3S-UNpl_7Y2+^pn$V zJQ~K7_=~Bn6v88+p|I7#)po_7rmR(`Oj5+$oB( zQlDIVE`sM=je^XYNDe^fcc;&=euE{%&evgE{RK2s@tMOG>_G|mY9!=#$wX9J*vr2Y6J}pKdr17Tz#E&9bNCc0W>bmKx>$Gbf_!~@ST12Z#M63%=Jxh` z(bCy64i^9W!K7zb^Myn ziSAhkT~|^_JUSPxRn)>bSxl|()Hfio{*e*1kOqS)B%}cXg54mI>N%~4}?4jZsD z=i~P^nVZ=szu|{l_G2J7o}HjXpmOW>71_2s38%6Io}6~YWrHyj9E#$Z1s@6BSi&AwDBobwMk+hJ1MR6m zpYwiru>ii{M^Jp>LIiZ`opKw!!9_4gP(61Z=j6GQ{h{#2S2?p+-j3E0bN47Rr!e6xGOzPYq#k+^;pUxv zGvP4-1&6qi7ICM0;3V0YQVQw0CahQp#ZR)jIxD2Fo$dO&=SZvU3rA}uCsXQt=z5e) zFCOE?atmgl1inI!ml$}aE@@vni!7zSln#y0o+1j)%Ji|=1IOven?WT?w4uMRChgiR z(zazGXFL8gSa(^qO2g4P1>Ql`Wi%ky`T~S5qT-Cu9)<08_Xx*b1#$}Khn5Xe?UZHSY#~aenKk9|&nyXMaX(qg5COoQ(jSw0tq~DtLfX(AIQZMj3M**KxzeI1bQTV;CA6|#Z|j^ zelY?UEP#K^);pFVRGNabjN{gQ9?5cQ;2?;J_azjl5IBuHk&HJCl95$+DK%1@#7BJW zk7xpM8k=~TUnoYI4dh;v#a=?ez4IZo=A_^#fEAn!|HQVI(OC((UYv(Q3cPb$q6UuTQbaWkuz|c-NUIoc%#m^z5Ti!94g+^mIkN zb%%Ch>zv!Z+$O?)KT_4fK`xAI50)QBJHK2mGHt*OQ4!q#9Gcn3MlG+ip7+L+bTvTEUdGKW-{li>tT`h~3Q2CCsr zPmFNA2a6gc)Xo&^t>~)E_{9v^c^4w+TL!O~pHkoOB|SDh+d<7beG1~G{ODPJsLgf! z9^?EVjE_x&InaDXL&ijSw4r1s-%0_?FkC566zEDenAVJYqgA!9F^trX2E+!X;VWY9 z8WifgWi4nPhJ7%dS70PtkdVOAoIIK`r%bw9Q)@Ng9PlBUoB?mn(GRT+?^P(ef`rli zm}J#6+q%ly*tQd~rj9Yr+&x?v6TvYpt-*%^>~%#W4aMCPGhuIjUox zp3c%+m@$XW**Tfx$nQCqA9u!Jy?7hivUN|4I%pk!*uwHXTm2-N&+JDyQ+65 z>mp% zqP^ysM&i}N*ia_gP6rm5t~u<)HW}W~S1|d?D^Pel>HeR1E4`yS{o&Bj$qN5$2V#F& zi%9d{Axz%Epa$_N)U>5NiQ$Nma`HMd!KoQJ&*YZ{xAhG&1!G4FJ}qjV z%I|u74r+(x?D>&GF$^&+Sq0q%2dyll)eB#n4deBL#Mq`k@I^U?deW6vk&A7ZU-rP> z#P=`rUbF5|pnNKV_*o~SAa6qY_>Pf>2M&MeZ}mO`oA*|89L41NT6#xBJ+tAT5-!ydD!8>>{qm;3m9G;w9+sNP& z$kjf7i zQm#^wK0d) z&a4d{4GKE>>jA_!uN0}hNiZgY<6S77T@Ej`-d@8zvjrKL)82+;{hmR_q4z`{%)t9m zblT-8{L~2u=wKhYa)z^y8mSHbF@?_Gzl6HV{fLjM&=9Ugo*9I3HM>2tpeij|`v81= z`)7*v=0@b7ObuKSZ(^)Hv6aGQO%kR;TKSAowI1Qa8wTksA1zeD(OQi*GIpQ5oeu2$ z6jF023^dLfk5;xz0Rp=2i#Fx1yp{}D!d8q#ZW!IWG=|9gj)Q07c_<(8xzz~cB37}d z>+~hg3#C`r{a)+OwjN9&(Hw#?B>Jo7+~W`EH`LZ?m1ys{o5H9X3GI;9+|F2cV!At6 zfwAWwJ?`%~5%=Pn*${rw#Gz9J3(4xI06IF}xH z7%cP z%;u!v7&-?HBpSjw?z^RSEaufy!-06 zTBviwB$yXoisGJ;PQ!}#q99ZXOTw_nDU<1aH~MV_JM>1s5}y0FB6?`U(6cSevdGNi z04;P&`-3LI*PMVOMIzJR9$G=$*iUg*R2FM5wBp24@RUzZZwek;kSUrcBXs;+_!VWS z2s~EUd7gB#mgQm!UIim$1JalMPz4&RCympy#rwjj3yvA^`7S|`h+Pp?Lm`p?2XWK- zA!@pd5G;N_$}XObyq`NTe?*GT`2L5pZ^T?4YlCsichSE2ZLo*rA{ZqqsGE2THVr}WVqNe8_x{tpP(qeQ4iCc3cSAaP*CcH zq0>S$bF-4nmUVO_wA7cq2o8hvn3yn?!sp11F##LUUUwM2^YZh zEP#LRX$XCI34;F?fT;tRN=V%!(I?Lyhwyh-p<~rH#K+8~!%0z529JE=65QRPsICnr zlGPSc3rOKw6z}P#65*5S7%!!eO49t+MyP5sTi3HTK{V_^d$_lMh#*LA=6rr`Zk$@RW=2Fs|s-mt_GG2 zT{MyTD%@GZM0My{FCpZ>3RECC>O84C-h+aokE8T`oGVK3Nz206&Mv#vgi*#e$VJtg zLZx^X+oF6HS`XF6H1&JbA`JFV;)WL&EjXjJikkfVz^VH3)E1U$uECS1!atOKT|>eJ2>RwDcqOa*US7&|*+3=Y zLAHf$Oe;!qTlG`~(*4e|m5ox0d0BzlFSM;4&SQ_FO`pB#FzSNC5AQTe@61H&jexR& z2sP1wWMlmRv|Ua(&j&GK@jFrW{~UN9OcMc;c8(fuEjLN3$hH<{_WLhY4Z(3U zY&i2L!tz%mE(=zDm03g4nwqZbS=qkkfrR)1N{zCDF-ROa8@|w)D7=zZkIvSSRj&1z zS6QbO6nIK6qzuxsLeJwRp zLLAN1jOCASCwIom^(rCM{2Z(Sc9GUFBS(_Y3r==O~)qlZ(_D9gNg7*|bmF;?tPU=}^ z!Twq?oQi4i4;wSQ5``1W1&-YS1dh1iUq;|8Bq$5YJP!5RkL}-0aV6dHNHkGgIe?^8~L~KJsNuomL9Za0!q3{GxP@sIJR2YN)I&QMMF?IxVsN72})Ca>K2A3@1UU&o{$l*788zxmI+ zt;NLQ+|1VXTS)>X{5i2aBbL2)I8lux8B#h;$Ux{_Nt4#h!Q^xs`5hfA(ez*n zju?sJTjtrR!M$FD;7nhQ*BXCE9D}@6@JXYki}83X%-; zOj8ubwuguDkSz*SFAq z^24pLUVI!@=b_%)_@=<93Xb{k(6miQunchlOflh!*u*~g|3r9$ry~D?1qgnVTK2~{ zdK%b)GLC^_7n$n+YeeFCZjjSP~`g-(@2Vl7G+Oz*JsLNLK9#iOuQ?^x`IS0aw#M}=57W-eH{133ps*$>t400te z2jYg9Xv6-%*~q_mDT1QIL4!mUoCM!2Rz+4{hMu)Z-H?Q}h2x@7>fYv;Cd-TY$PZTz z$=H7**tZg_5~QL9Sy-oB3}4X-;ea!>E11sNw*=!@FBY5>}ZG@kwwd zUxmpd%Ac-B=>;Y5ewA-8U=i)>_o*N`ukwvtwpX(#)lhHss3aX|C%lv~J)?F~ka%v{ ziumD;O2Y6a#;6L8WeCmYfDAQ1m9+S94WiVZ;=MAixiCFf00o>(GBFGIV}1Re7@Z8o*)Y+d0~5~+_YMsV>}C>^vmeFA(5Dkzx)#4_-3TsBy+6=fxBqc^m1toN=#IMxJZ z3K<@Bt!JbIB{UDz&f`q@3oLkLg=qhheoM4<8t>;@2uf=8Hx7mTlXnJTUwkq0OA69U zMZ=4w2$g;w6(2nTft&c{+N+_y%=}Ib1)TQrT*vnk!o7`E2ZhEa(ts2%1(T>vIsomK zCipfzfT}mGizTg+}_aqQ} z`gb@mto@s-7&XCB2+QMzq1gZ44h9+sEKY#!Mab)Qfbw8k9-8tmA@53FDiR{&Qx*|# zVfhsY{st01r^gL!8hRbj!M`{NU5;U?tiva;&7PK$mKGAM%b6*pl>e-WMM6UN7nv|P4(2Y_Mk!j3(r;-C z`IA?n=+d*0m#@gUuKR<7ABK4x0&}lM;fLnHry~+%f%f*Dx+gm6i&iQ*hSePtMH0HeEm=ynR=ACh4XB+5!1sda#ll)?MfZ(#n!lTnRMshA3?He(;zb~^oJ@WXlNTcpCUac$yASvBRPu` zLQz#|!ND=mK8+<5Dypv{tB&T*Q5f7M74UrZauk2~gD9Us9x`A-o58nGHsLyye2%~W zDPCqmZU+kXqandJk>8UETiG@wp#Sf;zuZ?{o4#iZj<3s<&=TEWG`3dram0jmhIA7prN{ijw zhMxW)MzVpO_U+lgk1j^#-e*Vf5UJq+D_m~Dli9-%BV*|_VQWGwEk!n~q#Cz~h2#eI zo5rs_2=n0c7@K@s0|6OVKAFvltiLv(4TRP^$dz}kM@PS7dkAQ6Gix8CX7Hwz#M$Aguz80c2KE1hi6x;ej8&bm(hT9WWi0gdw zeSDiy=9aL1C-Pn`i(J8^Ax8r9RKBG^aTJM^jdd=i?o=P}l?CvA{U1;^e>w8Bu8=jZ zL2=O+QSm+pez_KPu0~&*J+pzfjd9L6S`gQKs^wg|vlE?9u0eBK%P_7TS*~C2dy;_oSaTWJ)-Rv5_SQslCzO_-lZt`>|zAJRSM5XIC9biwi+;R&4c~zWvKtf zHE7xGLEhpRNgZHXAan~&SrNhm)8q^6eh|>Db9YdV5N;k2#6N6sZnjspqYcFkXj`K z?3H=3VXH#4HYgPO9p7J~s&g$m|48jqhx-hKDQga#eSb%#v( z4N+6l%-8T$!bAeHw{h9ThU|R;?IWV(R3jm)VlRIqqj49J&K9z=5~y{&e?+LJ>#hZS z_Pvpcp~s&sfae?ULh0MDNAYoA#JoU7+IZ_7li&@V!@fNMfzMHS&~9+;(dfQm za-dKfWzEUOCE+70@3t_aw;e=h<47O%oNE|0!BLggR+RyB&;uv5)8vg8A~gM7nDmKn zVDhh)A^+D7%+GVw7PD;UjJ&ZBi4Sc>_<@g2c?bR=bz?xD8gevS_=`j z;jBm@_WhM;|I23)Z#p+LL3VednH)gdJQz^~Hb zNds};i3U$jBJt&kNX)ttrAJ-&dk2ceuzE(n(b{khag5}1@5}AFF$TLie*{j-6sVlg zs<2k^hcm*nlD^9U^uq|8kAm~BLhs(eJH-d<+d-J$A`!lW-$`xFd7AhCEd=i;=ArWYZ$)#< z7KG1;!TFakeBVsM)Ixb?QT}xT%M#iN`u%n!{&6eXR@{q@j>mI6H&b`y!&=D6D~2X* zvw=cZ8E#A2fNY6f;h$bUtTtLUb;m}86ZfF$RsO_1{1IuT1A%Dw3O}3=zXkcTCLG0w--Lv;=AP+9w9!Oa z02Bz)o8VByRplyl)@(;~AnvrRQHglu8MME^FPA_TZK!^8Nq5s&9a$ZjeIB}h0_!SM zE`4$$%Rr#Nm*BZ7h2*E%Z-00z3cmkgl)dlmDEa97Q2LoKq2eq5fyp;5L+~d4{s;KH zESzjyvPT6wRx9+f)}N*#ddsgVH2D6gH1cM|s0fb52o#)-kQT;!jrbS<#iT@^r&i{-f_GdD*$PP?>_Z_JC)^#ZPo&iIIBlnnG0X-+w(ID;VIUDvj;%NQp z%cwte*DxMYJ6fnlA|tHT{{8F|=~KU7drX8{8DK*NE=eSb|RY7ffDgz1Ab_$NwespHtM)q;TnP|Jqf}i(HyNt{3X84q!}R$ zg+Z%N(>u#`haIzkv?T9?c3o$)NZu2oW3^ZPFo#Obhmx>=Iu+J`E=BN56XE$XAJL{? zg_#f4!_gDk!2GNa;a{&n{l;1(#vMNxE{uxcs6*1?4=EaCpe~}`p!n%$_+6h1B6%VC z+U+)yigM6`_wBs@8lS#z?Z$FwJ{1G~vo*Ni5$O+7#2FnSh zi6h}5h7>c9qM4mOoh@4}On<+Z|D4PY@C0B~@67T28;cQ~u?(SeS@oVNRFn&;oJFp? z-rBErZA`(azh!{#hx5^1*@DEcNG5%yU+)j)6dv!LiQv_95bAaJekJT;2bP#+_q_$$ zU{_D($=@@2I~YxEh{j>A{uNqBWMRBJC_t6ceGf~k#h9wT-@`iO~`qEu`#a z?B#)kMD_*|na)R8$?uvMhUaT0O8&)*q8mN%eS!n4O*;}6>Eqr80Zp_9n)dg^5c#(! z(ecpJh_6&cPah4To?n@Mrj!v?>id>7kma& z<#Kuh$dqMeENA_@TNOG;X)7%qxv;uNT4kVd+USS3qZFPIAG0bXbl{bQM<#=?_6W_U zFx5S+DG93c$)v*~7Dei1p4HrbktGwfFwi-twr9$4Ln(TmPr~@tT120H1o2K*a-j8l zQ(;sXzzrx{>Vq+qh=vSe94%>G7qPsXMPaue8!zlEbFh9$N^_m8oZRyVn-D1FQ_$jPGSyV5gz2R}RJkH-1101M^PeJZ1Ghu(D z7|x_AJx&h%Bq}OcX}Nj23w)i&TFqBQEA{5$QY7H!!)S~IMsdel*+->K$w>dqTf6z1`JSU{nN0dsoIznXF<~LxKGAO8tEXix#_8fB96OB}INGN{y`&byr!i|AqHN zkl8@mqRi`yMns^{t_$io#J_3=>YB7eT)TO9#(LE6#>N zTAV%VYazZ5$#8RyMwDHKkiQiE_wlXPHnO#-GGJdAyYdm)cRZpQSIdCVh=jcp(M?`> zZsMhw>-Hf2p85-~|>jea&}T9O+XhUuIpk)*)Jy)p0r%HCZIDr&;H{GexFxG=17Y#3 zzvpea{>Fk?tG~2A zkw*74HRvCa0RN3l@qYeD@f1w>pA^j7_?cq(^<005P++`}Li~s8(e~5ZQN4aP!r30w zlk+$p{(N?T7^wQ47KdSyi6jpoDT_>g=WKlOVn`}2)Z}TE1>%&{BhG{dgFJXo^uoG| zZ__!o(l@h5s{!Z078nhG=wfbzLM7s{FXO;#N!YiNQTDl4q#sx&j2k#HZ@3Dj$DKk8 z>O2(WPliwP=M7O)9E6w+Lzb1=+spcfQyE5lR|L^Px!wkY{fNe@k<|QC7TgSdeVBD^ z=RB1ak+~-i#D`cU^rXOure?9-SDPrDmxttY(-8UAOvL`3O}?3*N!iJUUNg|fLn%iC z`J3*LrEzZ(oxgY(t!tXoi9%guFyexPy`7&AuZVj%EDlXV5l}kcQ~>_>l%eep9yn8Y z{V58MZx}F@piDxeKaEqG!#Y;yU#Ly|<3_aoc{Mt!cD~6Dm7flONeMg|g4aoA_FlBa zSD{Ut;4(hv{-FLi#FE|_&CWkO6@@uDfu_J)S^=M2YTC~*(6ux%ttjc|)dgsiraWY9 zLFBeDoM-q}3{2mjHTbZsymv(re&4C^%~=NjbV`MuCm2%DrFXz-p})7e#c?v~$&vSM z9_8qtYS=HuVCclebc7WvCaXhfUwYO6%4q13(grRY=2&_nzZ@&??<@?$>w8ijW@R&`J40H^;tgxG&QkIv1nD!#zQ8!%9< zY`}=XcFsrP2RM-0tvyipK~G3yp(bZM%vVxG>aFbve3lIDqr4Uo>LjlIBDX}i2PtG8 zaNxUX4(ta#sHyvJq*9vQZ#INr7A`?>Df{G9UPk%)l7ZB!HHhLgh zx6WonBgODo)8SKKftdb4XwPBjOZ_c$f1iOO-{zCyzqJ+Syn1-G@P8HO{JU7@ z^Rw5VXZv2@%dNbzf@LF%(w->ll7iQ{h)*o%Gd=gc^at$*f5->VjcsVZ_fa%8zY2Sx z7UMC25w|!lM1B#uwFthaDLqisQ}dv}ke}3fC(E}<96E&MEu2BwZtmL=NAl)fXuauo zsCn+)INbh^T@&z4iK?zcc63y%7^%)BshxxTL^b$799?%G6ImcikKKJiQh#@n`j>^1 z%J4s?^J{Vp)8U;+!SQZZOafAETEY5icXGCxqSB~8TYz?LhtITqsBo$fc|L{6-TcCA z*OR(K{XBzx{*NZif8>SEM(;je`dq@iFGWeZ(3V#a8+9vMVX9T>qjqC=^D+~jE8!u2 zqk8uTeXe#Eu?w%^99J5lt9ko4e$f4IIkpa!z%<<|UPEg=m$B&iFHy)SsxHG9jt0@m zb_e#&afE;LDk@+7HdNJtCq z&djt|LmSw-ZQx2{8Skf$#Uyi`IJHN#&sc+XGpdi=u@33#rUN;kfHbZ@-|>_*fMA z-#iUXtN)C)==OmV@wi1b;>rmmw@no_D)VVnI*Skt_+iQ~+?}aZvQwlT_6%drOjw7L zt8nrl&X5>MdeG-%7ibtKw0PH!Y8>Q>jbae6<0|*PcUi*f+^Nh(uKio|{>p z?i=FA7O)7B`<(V#?pFFAEjbkIHz#%sQBS8Hk_Z?u(iMA|5$V&+fdphYhoL%px=05 zd}$i$|L2#eI&>!vC!ZbTz8X&$QNdxt@Ge9^dpLScqcBVmAu8-~4T+NkYJSiU@0s=J z{Krjb{^K9fzWWYD!{Kp~&2~6JArY7kpVCr@fy&iaFd2TUD!r#qzTwxqL_1?WWV%WL zp)kqbtV5mb);R^CVRPjS787BaZ%4tbGm-Z}60lrU^7C(C8^|XOZIWBS>ufAsY2zC` za2`*hW5iN&>_j+u7|B0dFdyWl7H>zg504D0vD!pIPPklNMEmyV(f%`5?dQByl-|)S zFKq_Yn$G7qme;dfMB4i(|NcVW8%p1CjExmR#D2US?f>^08lL|=k}WN+z!)$_RB%j% z6-jm_nj5N{DgzC$G&XJSQ)u2=Y7Y09i2u|^_`8K@xhaUcN56*s4L?SEQu&5%K8A^+ zs>{OC+Jq)s0X4V6DKL#HB%`Tx(!2C&Y=X>)N(y>0HKDi3>0@6Pco8j{2JeW{O@Hvw z=v;jZe-#ami`siRQT`SFyH&LtdjSsT4U{UK(WX&*btyv2w5%Ksf%W{$_u z+Hf}-DL9-bS&3l@`RxPB5U?SIME&j9mlL#KgG8zhZM)us#$VV-eV4bkvtmcHyrkS{ zY%iwJxQ69)jsW`P%xql;4Fm7 zC^4iB4rHMFgEW<$CcMAML(%8_@V!5Zs`po;{<~YyeE;v!vHf$1b;ey{NTV9@P6`WY zS<3>6Wt@b^O@V))dlH5X??uVU4m`?)tc`CcV| zL^mtRthA>>>9(cJ>}PWye;(1j+eRr}J}tob_fhvM$K~g&w-)k8;&&VP-7OE`U}Q%+ zd2Vh&b9EgWZ#U8U?;a%ojTL;Aw?&J?wZ5e95e+}e@4vAX;jhx#`_0eMzWx^2`W=@? z3htOF;oe0 zt!r$lLt=jf&cxa9pT?fkUVtRaW)`gzXp@za=JghlM4o5tO~G0B8p5OQKYt&}=FURk zUs*q$$D&B1?KaGxkgzED99bY~VZzcK(z4UT9ktFse?$~em`2O5~EB% zA$WEc!88KtbRkC1^EHNwz3h`ew!_%91)amijE5ELIbLl@RC|!v!G3tjg160pNo6Fx z%Uk0*(EiW>D%s;Jr1ATx+}xB8^M7qry|N0?`o|E9*QNC)7sG`S6C6|F^IwY+EpRD| zZEuI>3<{k5`d?vq3k%^XKMVP_ZAf)=P>{GTs=r4GJQEfmpgk{h*>Pg9d%{R<+Ksqp zDMH$9Kb!ZpTE2x^JGEg$`!=*&w>QC|UA?g&tS45WUC}M0f<^Fo-ie}<=OUmzJXf(O z*rI_<;!mW7m8`dDOlOPtJjh7&p!6!Q@VP?%odl>{b-O4ye{nxrSB=GCJUbCh79)9Z zDol?Fk9JdQO=dV0D_K@sTaocs^g1C{Sl^+);s! zJN}4{&QX^dN3avg_B(-0C9R9cwfICene^B4Bh(;VNCIVX0Qu@;W~6GWWn(cEGq zx~U4OHD@6FLMQSbu#noHg0Gc|!6tT0C51@^EfYRxz3NBs0hZejqvmD<&3AgxxpEz% z)l`T&9z!ZQ+E(PTh7l7Sa#bxw-n)V@6=N^KG1N)X6Z$?)wwY8%PMQR7!E|^dRFmru zATi>Lo#O@6tfLp8P+^Qq*kMXD(iVc}(I?Sbbvp8|qF_Wx159mc_8c=vb0>1Y~37eEC(z7r5U`3&TLnwQ!=ok`}`#(!?%YX|G{MOI)QuY1$j zYk2=@zMjn2%u%9Sf{5R=5v}`P9iv^;D5ChuhKq!W!h=>qU6=WOTd~MbR%hkoV0)u?p|C&km6RXxLb?6dvGb%;#S}WT3m`d6pCA+xO+3o_DR~DQ>tAgqP9sz;x>L{K&PkXizYo0Fw7p~0&1BeRHaqT) z0=wRj7R&la6|&1&+sRwxBR!&PH%WTRQ0lSV`qfNhjNG%Q|2`=3i^e>lS=6Pr6_mq@ z>~o@?lwTEXdB5X_?j<#@$p*=&u$5XlBZGWsr8l}36{n(;Gj-xNKK(uKibsFi)R8rm zV=)LA0r>4tDap25?>OT^RKw^P-duQw%G_{>Q%j5-xsPOO#vA1N>PYOek2F+y1bVzmZ3$ z^vuXEIQ?d6DQ!J~zHz_WQDFb_)Ln!4?&8dK@LoVVgVt8Gwhq>X=Ty=A``Q@P3i=;U z93&fjxCO6vrjuI1{<*xND7+*zpgRrM6Xe+@Z{^IVZ6Yom6R(T%H`_Ab<*p|;_EM)u z>FL%7hWLn^a7e>NbA(R0@$&4y5{6#gi_BQs@OTh2GKgMTK1fH#d4No&#w`;ne~~?z z;)}@>nrk+1=E@*Rze)m55;i}|Ko1QiT9jx*atdrQ*!$J7w}{XbK{W?g7W09d!Ms13 z>uRi3S6wLZ{ZpN`PRcv8m}kicm+f+F3=J&%!#M`6X_fy(nr1Nl_9FxFJ$mhSg$f7J z30mIx>SM?Rba};wm{31w>?n_9+Vy+h1#UhuMGcdhm!keU$s0g|d?sXaBGc*P|5+n{ z_VxVZ+BaSZO^%FtWOD7}Uq~>IA_bxr+ip7c^sn3@6!EPW=efYQF!bg*Jv9%OxAo;U zXRo*&nV)%83Z-+VuLX8+RMxO$f@~6(s+AhC(EEr3e;m#R=O6FeIeCF z3&jqi<-Uh0{ztA^-%`K&2w<&%>sHt$OKKxWu@%Gl?`WHZ;;u|}8`>mt} z@|YxIC_>yiaqnOLz+5qeC5Pcsx(c~_vSb&4ZFM2tb zDpT06yHorY$#Kh@hOXVyCfWgH0&d9(ZVLZlwPGxk-Sg}qRB~zRGGN9>D;+2h&M%j0lix!jEQ?g=l8R73g&gO7>!M}4u|8^qh$7bF}+<8z* zSjJAtTE&uw57E%khW}j(Q2NIGWeRu>xr$zc3csa|#FR2kp?<*oI}0{BGC(#yzgGNBw%`Z>{2!n}Op zxEm05o^TJe7>k11mEKpoR?IehFnQA$g!Y6gxFyww?QYKz+tZw#y7u{h>A@#T1RLpI z94sio+Jnrs8t>UiR4EdQEo%^n7B1zwZI6&N@V8 zU6?7f2w8cD;5f3<`fl2pZ0b}OvBa{D_){wgKSKl~-QvU$Mpvfmo(F;8FJ`vD%Ag0< ztbs-$Kt&KpGAShI(r0;0L{~_~SFiV^l(bU8HD81XR6kK+y|>`1V7@%R*4FaCi{HstE}tAITUKoPMoD#|^8zHvm%{H$$?Cn< zSl4+I9n!(-NyBDis|>Hi<)qD#2?A~{IM0ZEZ$f4!=s>GSQ_*>~gxl5W1^}ZJ8N3VJ z30^I+>LbyDRG4L$@x!Tz3rtUjjRH**WpFw+weSi!(+rFO7bAXE7-_`gG5Ze z#li=9yW#HVE`S<#Sb2Kg2dCjQpRe3k77E!#VT+N$guKn?5bnjeRX*TeAonmwbxjTS z{gTM%Bk7O5Ge+dbWwaO&UGa0hM^+vckpFNHz+N-r_;S1=T^)@D<}xw)KcaVA6i;zl!E5q>*LDEQU4Hz6g0GNM>QSJQ}1W|!8#V$#M`Rx5Yc##A5eVtc?Q zsxHg;xuL3a{958OIn}QBPHMX{th!-&8R*wc*u!F-KQdT6qL1!wPTl0dR=6Xl2KkkN z+m8;EOO{m&%8;HUhc)S4U-MX^<<=P5sDEli;RC+K?n@qkTq(XE#YP@}!dG}*@rw=< zrcA#4U<#i;5EpoTFS;&6*0l%}ZH>y$YrCE=ce0b=;Wvc^I+8+pSqUghKjYewiZY;# zI!SdXZ3&HUbuNq{BI8(4e%tJ6WT+y>V~{djJrUI&6QS_6Ht2NLrz545LZ=1Ce5%SO zD&2%fDe6}p_*30)cG1^6iWRzGvYD3K?*YlqPgFjSVr(^*75U?;?S>1!EY#na!ivXW z7v@QmKQSHFQe$O*MZ8^-E3w75YR09wvpHc<;zvj<0N|3W^lt3Up!^iRbfsZDiP15V z{%Uc~s5>?60>P}*jlDjPtP&=d-uR`NZ&Xt`DYEa_C0D$;Ipud;8-5!*kjiJnromia zK5L+O`CJKN5_4CMCpG8V3ML4d^Yg7ye?sCjJoQd}n$(8?g9-Dw|COeOxi@XbwsvFe z=h3TubjggaVMN7;LVBsIji$AzPueZ2CY4*Q4dtd~(oE@9cc z3Wq^g#O;hRRNADCmbHSL4(Se>;W;Y~vJ+Y>a2F@<1GQ+^7a_Px#XurpOK6FHk7?ME z>hl zL*U0BESja_S`2ZC(2vt(G-cn#aW?Q7 z50}Zp{ClI=H-h#jEHl$$Lgd-i_Lu84v3d=qQC?>6VGCZ!RXf@lqEJ|yl@4ey*B(TA z%~<(6%($lrrpzjAqOi}|s>c$cbY3NizCUmZsP#THKCgWsk!(e9O~#i#r=k`v653Ra zk}@X_w_zOnp8fIr8*{&t36=JgFlJ2mI?~**$-%7H%71_b= zuOy(w6#>2zEU`wtW%%L|9g~nYSciqjnXe+HB}(3>`8m+x(sNoZD%3BOW;kA^xW$oI z9M2?dH*2hJv89)I&wgc)<-}Ugg!u`n-LnbZCI)k-2JFXUu1JQ!%ELB(xr?RNe<79& z>GkJfb0K6`EaH4#cu`z&L|C}B_G~x?6}w|Zgdf>HRI68&1Zg$^7dA$W>NwT??nb8D zzM;+FO2Z54E%vW3nCF>gnV=7m8u*ff45~WkB+u(JFW)4XXqp(G!gU5+%@T(*&6OT2 z3zbE`E+^<+;W71dT8tFfKYCM)UDpx!D3&~Hl>LQ$ATN!#B>K`$F+@mVTo3vQ}s* zoG>QjH{X1~N%KA1gu%R}*|i-M@->NyMjq0M*cX=CphK;RIetId={-}x3wo2&$I-FM^U&c;b_ z@q3&USDq_IW{g4n@|37i^<73CT|lV&8(_45y!-f7PT+2Hpv>)JMZmrd%KBaiT!WP` zI4ovB1YV@`mCdN6$bI$qU8`>SG*y(w<$U`z5mN~D@Vlo|q3$W0h_f@_0ES<9YjWea z*XV@z3mQ%O(nl;eo?BM){51&a%Pf0PguOl2!KgXH=fTA>;m zY-bDKEXJSB7*)7r5xi-|G$VB5Z9ig6>2HymHMI?GgFKO&H(N6XjKxu2#OAixzXGmd zmP~nLLORACr*%Q@?pVp+j$jAWZeHijEBpjYBp;)ylfitYash{;2XP)q(r+59K22!VNV&=cXsy6f~YlZ~1 zpqEvE(J?#my6nKMJRPKq`_q)k&)U0j^fMtCae498DgBPcx9fbQ1z?{&Nnuc9Z$7S* zo`btKjH0U@t9hv?qtNj+oNRmVYIeJ0u|kN)Ba&9#0s~XJWhVS?afk4EfJf-#Bbk-! z&-`bErK~vBn?>=IlGy%B9wmkSU!A#R`8G-=><`FTa|DrQ7uVd=TWv`$E27IN zzs^v|Rqas|IE$l>MY3=!=$o9-8r70t{*k!9qS~mn63igc27|N03>Vk)R(stPr@kVyR{lYx4Aiak z{6z{=k-HY^%JcVx8)g9e+PE-{h`ET`<8+_$xGR!m&{HeLFi|_iK4BG4LTdhvZyIeW1j(AoW8r#A)pknwcO@?!Urg-x z_sLp!7s`aTq8GR-SiWAl>s^GRZ7rW$-vE@zc|33tNamrl+Dd;Q0*7b?$EvuC?J6qvLS=K;vqDPxa4&ySP|Z&G5N645^mY#JNB8 zRw(M%w*i9|lIYrz(k4&xmANW8Me1L}5AVJ7sbDTnvG3JDtiv0wP%i4S5Iz0HdoCi; zB{4Ui&A@UYI+uVOyp|UQ;(gkV>6;3P>6Rn8rormrWdYBv{vm3FV_8#mj#uhx9U4n~xj3*-V-#l#KNV(YUz16!|K)uSRPeyRvh8{yY- z8KY~h>b1JO3ZqEz#&CiJ;u3F#jOi<~dc~V*H2UI3tE-ie6SUJs`F>GjUxZn=f;{{f z@_vDH)|qP9Yffj#CKiASHdUJJZd!vX&LhvV(J_+g)wIj6?R538f0A}RIcM~J->@%n z@AWI-Ss9{^Fu^sxqQ6SO^}jaf{E`K|!p#KcH>ARZ`Hw97>;(K#>QU?&>dSG46KY{X zS0WMfHA91qf9hBq8dth(67T9Quf71_|Gmul;(V)ppw3Uyz+DrY4DI7l z2^IN(PY+B=vf7=N&LU&tNJw2KR4F7locq@8vKV(`^x*k2x8b=~j6k__6=HZjw*$Vq ztjC32#AhF?2{arplCcq8PdtF2{}?cUn`IQpe|Jaa-TRLMha~R041E&YneYgT$2j+Q zz(Yo7MhdzFgghqbrW$|2*W`SAB6`Ag7jGg6Hc!+HR`|V);9Y)U=Pl&79A*#OJsOKD z{jd9vz@$*JWDR*fJ~-UDlQ|Baj^(EziiEV$!QTi%T6Iul5Tl~TZl(<+J+(uxSGQ;E z{zeQkLh-m9d!VR!tY<9=doIDhlt`ApNycr$2#s7kjwMue{2co~tEmxI56<&|w_@S? zBSUz?l*Q`nkJEM#g9}KFynP^!h|}gWdYH{yqGoKu4~;a#F=+7COU8fEL5~ge0gbXY zUna_ZItRn=$pqjAoiJ%4R?od1&e8j7HV6yM^URzea={lz4|?eToZs}c6UjHFP9JjQ z;ul1`$zRc5n1d5~^TvviNA|WcrG>#LkWkzV+WX2;tyulr!IqjdBv1&nN}P`VXmmsl z52y&AZn)Vxbc7DbBWm5VY|xi52W>vOHPn-($k=;Y~GaY zLfTqbRTNE%G67BXYjA;^ZZ(xZeNAYoPzSV9^X)YntTp39p69w~19)Y+XKgyAqHR#i zA$i_r=E+&Cqgod#y{o@sZ)oL>pi38ruB2N+N#qCGZh4Z_()ncu0w}=zgZ!_^J#$}^ zjcF+>Q-I&zjLEnChdZeX8WbVv3u4Ah!69ar($mXCruf@4~l+V0G1j?y$dl0da(nU#3h zS!;>6UKbhjX@YNEUQ{|e2@ZMGmc+v03epcis8zgFG?bpjANu54ie5!-1v{Sa^ufNp zf7<-~q^8}9@<(rp)sWTc$uTA<^}_d3BxFy)?M|w4t(9mC=1}HuK6q=6pYke+wQ#V- zi^0$|fp4wI3PvT{7Nn&ZUw)s3>s*RC6@v^AUWU3>4NRh`P#h?Ppi9ga#|dwHdm}6# zwOj^_D6qA`bV$~e3yPYEBE8?gN2;2lfjpXrCQtIKn%ps8wW7e(zeGN@mt*A1-@8$E zs5}zeINmG@-zSSNe`yc~ZeF90O4>K_X2337LcaeC--=*@L~N+a*>&#rhPX&rIiv6` z%0%DB$U|2zwT-o2?QeB+VrGzb@28a7=3{17qK@jRAo<2V?}$%4C@h6K9(hgL{B$i1 z0V6_wHTXsFCo6d9m@4zH@iuNWto&R5EtJZ27*-xX{!kFF+QrhFDY`9gPQ^=Rvt8bJ zMuFJ1Te1)?gRF-i9UYoDItpOTKjy43LIrhPA$+}-Y1gB}=-{Bnx0sLX1~ctjdvQLc=x&Gg44~*1w^^A*+GGtEkRYd=Mz4vkNK`aN>wNX< z_bDif@+7EoiFsDRxx|fjYoUN~Ecmf-sDj#+PS9=R3?gKua>X0-S_RQNrT5#$pRN zDdN>?ZC}Tz4li6Ah6%??$uT|7Jj|U2q&*oV$FalqR5#yUnn~gVHIXDQ>(!bL`=b*s zqb&((qG1!FNPV26P%pE87I!=ZD|+^|et2gd&xzD*pZrAf{3zmXc}s&=OQF&d*uyUr zPaUI4_VwmX2Xcw+kI3!oCvPhCQ55%2&kW!>WE;$qF@gN~GMPS%lWrDtu6=&1G;m%~ zOn+O!O-`e*rXe-tNV;Z43{XFFL92LEf?oC*1xKzEz;Hxh(7rnDZ|Aq zVbRZqrs0Q5R$+ZjG%+XGYpEmEWFw;YGbY7bn??WKHDkzBTN$9sX`rlO+^Gjz)6&NR zogjNqk0x=JvZH!@;$k)~WA;!HOZ;=d_~X`V5KIWLeh=*s7(_s>&{&WlTW-WoB-_y2}9 z6oifEo<20%!G*tXWFs!`UQZ){V5Cgk%`z1uiUHL3VOc1^2GbJgps3p}TT}lt#F&sGo*J(%r``A4Rze?kG z->MRvRYp1f!g4oQG;Qf{RW-T30o}h8~`MIp(V%8V$c=lEIzne*2pR`JM03pJSaSz0?N3qg?ML z0sGh9`;HhxEPboMJ_eLrk(J?djdyv_F!~q;d8a zU@w!8FVyUk!wsZ9O=OoV2nl|Ln#WM|jD|0@Tj9PoiNbmM?*10j<6=hye;)70r1&ZH(zl)u6{1>u5)a!p_@${TZT(ZT{uHu#^1y@ zchLL=S`*jT6Hcc(PQLWs?F!vJUVBCo(JDLBpmSDai5TlPpn;r7kP3g za?ad3vP>8;B~WG2!^A&)aXKe-Q@OBCn&|e}2c+SvdQ=e*8M#PF+EQU!`I=q3h zk#M>y^x#?tyO|P->5%qeyZ>mR zOaITX0S|Up^7JE3&;XrV00k}wx*o7G+lAr>ETAiTUJYeY>|IWIkW6l2{xAbbKo3-2 zHh^`%*0*tF@w~)B*mL%&sa(bKJeYKA5yR#E7-D`eO$4?7XV(`xs|U|;vSCs6&4&J^ z{2*FwZ6hSUT-mx&s z$cU=RNSCInns97&MO7L?8plY-@iu-kvrv9Z@Hh7LTe?JhYd#?V^re$Di*$yp-VQHz zQ>0MpNYBZXDa*e3?@+UC-c!NN&cTakJFIu*mW~IH9xu;9(k*|Z?(3N`3M9#2`~|n} zOya7NEJfXUxw&N2Dg@VX5I`$Y2+^kTmcONd;hb>&s$RjB@+-C4JxEV%V%P+#uK(J# zuZ^kX4B+XIZ2p(+g;f;&(KPt?6RGG}55r0bDMQDHw7+gdCDnM0mz9_spNz5IRh+;- z7=e@|G!?EGM?<|@o-l3T7YAWe0;xAE%8JMsUE-wZKv#t=T@b`aTlS2}@z7P}-$>ND zZ!1KcjV9zX_*6u}Av6G49N0xw`=eHVgz=x-VkW&S?FqayXBiqb%>*Q2={tEv&oD(CfXL39wql5A8d2$f;$*#( zHhaoi@-z&1nS3Cr`SF7PU!k*XzbOG7N@tRF198kfP*ej)-x7#5#YboiP7e8odq9+2 zSOYL({L_{zbk5Dy;XtZ46K3Q*@Mwbhb#*0egHl1M8|gxg_@(+ChW(Y85toN0M;`o~ zj6!BP{M#8fl*!r8^TX1eCFn#n2~8DgV$&ZZ5Po+V5QW7fJ4+r*`~l@v0Kd~C^Qt3J z=0bjZ*t|IF;eT;lktni7wDQ3yyJ!>HBeNAI(8$-l5%XM25B42NYm1*aKwj6)`Q+QD zEq``vkW%t5Zf!oy^q_y)0zCmw)~N3aInUwEj1;v+j}Mi&nFa&Ag2{#7#|VXLwRCTM z7S0jjj1`@{C^lIPYh%IMAfn!PL9r{&&PpO*M8V4=Qi-+=QrzI(+fM%I5O@iUDt+{q zxBqEhbQhTB)&eT$+{FWMu0TqVT*DOSa}X;7fo4r9M`guo5PS4% znVQ9X*^7s9BsAmqFUKT#cQ9|D%v_A@^K&@8jtsZrhu@7T$}ab835#x2sVaFf7TOr= zpIaC`mOeXFvzppHOCg{l1q~Xv=%jqeA28rYiv`#I9uIy{&z~@O@Lf^u0~5&}@4E`) z5lXHv&$J%zq}GuiE2c__H?4=o z8LC0E5Xz6AvO3(~oNaF;WOMyWXXrB*b5jQ=uXitsXSAzFNIfP_l}*;|Ko>=w3L+ZU9SW zO-LV}#!}!S!_Tb{A;{NRMFpy1M_4u`pRK#H;768hxFbbDpsQSSKbL8uAe;52rjc-e zG6_S2r&QkigQA^GHgM>>UY;V@bO7{kx^c%SMr^6v%|YorVUiku_(xQzi$r4b=+^gt z?uZ#`m%br?GZbA$trQ2?NacRk|IlIdBG$__vg;aP!BedNU_}rvvj&Y^s8#++v!x!< zURG#6AXFIpF-qG_2NPV83!9$xnmkZiS^Z3g!zFd3wjX{a!T~V+UQI^4-_`8)DUhi7 zgD}IEaT%g4KEw!U=p$w00+D|Sc}w(G1oX#`m*~^rcrMA6Q5NH7K5pqY6MTF%&DRdA zN>$xZu!>#nfN{#v(B^xpju7s4s>va^?Sb?bY}lR@?SM>i7_9( zc-@C|WeC@xPbmIB+Q(*_ZNwk*Mxe$tJSK=xd)Ny&p=r{%Dk+;lG5H+f{}ZJ&aj>H9 zFDZXn_q9yr#_Bc;pVyX^NiQi4k0S0pU+q-C&wi;xI;OoGV}zhp-G7XAi|a8D-=3jA zBL)y5jmP9Bc}mw&47b|?wKGy`Wa$5WLo8qW|G!_>2j9HNBnRGOT`+yte}j15DQG~x IgDoQd4}J~y9RL6T literal 0 HcmV?d00001 From c5f82475430bbe469b07730349a97629f1991429 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 3 Feb 2018 23:16:29 -0800 Subject: [PATCH 0071/1504] Add support for Bool and Number primitive types. --- src/rbx.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/rbx.rs b/src/rbx.rs index 99f24d40..30cd2194 100644 --- a/src/rbx.rs +++ b/src/rbx.rs @@ -20,7 +20,12 @@ pub enum RbxValue { String { value: String, }, + Bool { + value: bool, + }, + Number { + value: f64, + }, - // TODO: Other primitives // TODO: Compound types like Vector3 } From d99df59d9bce2de843f8bbee68596eff7e35f3e7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 4 Feb 2018 07:10:59 -0800 Subject: [PATCH 0072/1504] 'Wildcard' type in DefaultPlugin, change to PascalCase in API --- src/plugins/default_plugin.rs | 2 +- src/rbx.rs | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/plugins/default_plugin.rs b/src/plugins/default_plugin.rs index 3ea7addd..56d2a2eb 100644 --- a/src/plugins/default_plugin.rs +++ b/src/plugins/default_plugin.rs @@ -48,7 +48,7 @@ impl Plugin for DefaultPlugin { TransformFileResult::Value(Some(RbxInstance { name: vfs_item.name().clone(), - class_name: "Folder".to_string(), + class_name: "*".to_string(), children: rbx_children, properties: HashMap::new(), route: Some(vfs_item.route().to_vec()), diff --git a/src/rbx.rs b/src/rbx.rs index 30cd2194..f411242f 100644 --- a/src/rbx.rs +++ b/src/rbx.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; /// Represents data about a Roblox instance #[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] +#[serde(rename_all = "PascalCase")] pub struct RbxInstance { pub name: String, pub class_name: String, @@ -15,14 +15,17 @@ pub struct RbxInstance { /// Any kind value that can be used by Roblox #[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", tag = "type")] +#[serde(rename_all = "PascalCase", tag = "Type")] pub enum RbxValue { + #[serde(rename_all = "PascalCase")] String { value: String, }, + #[serde(rename_all = "PascalCase")] Bool { value: bool, }, + #[serde(rename_all = "PascalCase")] Number { value: f64, }, From c6cdd8a8157654a30500652848df8ec2c9604017 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 4 Feb 2018 07:26:30 -0800 Subject: [PATCH 0073/1504] Change test project to test another edge case --- test-project/rojo.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-project/rojo.json b/test-project/rojo.json index 1876c81f..5f2e5c4c 100644 --- a/test-project/rojo.json +++ b/test-project/rojo.json @@ -4,7 +4,7 @@ "partitions": { "src": { "path": "src", - "target": "ReplicatedStorage.TestProject" + "target": "ReplicatedFirst" } } } \ No newline at end of file From ab644c3dfabbe4edcbea2c1b3068bc7ef721419c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 4 Feb 2018 07:31:33 -0800 Subject: [PATCH 0074/1504] Update model.json example --- test-project/src/hello.model.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/test-project/src/hello.model.json b/test-project/src/hello.model.json index 3f3b8077..bc707e8d 100644 --- a/test-project/src/hello.model.json +++ b/test-project/src/hello.model.json @@ -1,24 +1,24 @@ { - "name": "hello", - "className": "Model", - "children": [ + "Name": "hello", + "ClassName": "Model", + "Children": [ { - "name": "Some Part", - "className": "Part", - "children": [], - "properties": {} + "Name": "Some Part", + "ClassName": "Part", + "Children": [], + "Properties": {} }, { - "name": "Some StringValue", - "className": "StringValue", - "children": [], - "properties": { + "Name": "Some StringValue", + "ClassName": "StringValue", + "Children": [], + "Properties": { "Value": { - "type": "string", - "value": "Hello, world!" + "Type": "String", + "Value": "Hello, world!" } } } ], - "properties": {} + "Properties": {} } \ No newline at end of file From ebffba9589903aa94ec960c8075f8c6adb0f9f13 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 4 Feb 2018 08:55:19 -0800 Subject: [PATCH 0075/1504] Add bi-directional syncing note from Quenty --- DESIGN.md | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/DESIGN.md b/DESIGN.md index dba5d405..bd2094e7 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -36,4 +36,14 @@ The plan is to have several built-in plugins that can be rearranged/configured i * User passes a binary name (like `moonc`) that modifies file contents ## Roblox Studio Plugin -With the protocol version 1 change, the Roblox Studio plugin got a lot simpler. Notably, the plugin doesn't need to be aware of anything about the filesystem's semantics, which is super handy. \ No newline at end of file +With the protocol version 1 change, the Roblox Studio plugin got a lot simpler. Notably, the plugin doesn't need to be aware of anything about the filesystem's semantics, which is super handy. + +## Bi-directional syncing +Quenty laid out a good way to handle bi-directional syncing. + +When receiving a change from the plugin: +1. Hash the new contents of the file, store it in a map from routes to hashes +2. Write the new file contents to the filesystem +3. Later down the line, receive a change event from the filesystem watcher +4. When receiving a change, if the item is in the hash map, read it and hash those contents +5. If the hash matches the last noted hash, discard the change, else continue as normal \ No newline at end of file From 2c188738e6fea526beb83141064345bff81ba57d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 21 Feb 2018 23:48:37 -0800 Subject: [PATCH 0076/1504] Document JSON syncing and fix README typos --- CHANGES.md | 2 +- README.md | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a989a369..d99df9e3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,7 @@ # Rojo Change Log ## Current Master (0.4.0) -* Began protocol version 1, which shifts more responsibility onto the server +* Protocol version 1, which shifts more responsibility onto the server * This is a **major breaking** change! * The server now has a content of 'filter plugins', which transform data at various stages in the pipeline * The server now exposes Roblox instance objects instead of file contents, which lines up with how `rojo pack` will work, and paves the way for more robust syncing. diff --git a/README.md b/README.md index 6e232794..d9e78b34 100644 --- a/README.md +++ b/README.md @@ -26,10 +26,11 @@ Rojo has a number of desirable features *right now*: * Work on scripts from the filesystem, in your favorite editor * Version your place, library, or plugin using Git or another VCS +* Sync JSON-format models from the filesystem into your game -Soon, Rojo will be able to: +Later this year, Rojo will be able to: -* Sync Roblox objects (including models) bi-directionally between the filesystem and Roblox Studio +* Sync rbxmx-format Roblox models bi-directionally between the filesystem and Roblox Studio * Create installation scripts for libraries to be used in standalone places * Similar to [rbxpacker](https://github.com/LPGhatguy/rbxpacker), another one of my projects * Add strongly-versioned dependencies to your project @@ -103,7 +104,7 @@ For example, if you want to map your `src` directory to an object named `My Cool The `path` parameter is relative to the project file. -The `target` starts at `game` and crawls down the tree. If any objects don't exist along the way, they'll be created as `Folder` instances. +The `target` parameter is a path to a Roblox object to link the partition to. It starts at `game` and crawls down the tree. If any objects don't exist along the way, they'll be created as `Folder` instances. Run `rojo serve` in the directory containing this project, then press the "Sync In" or "Toggle Polling" buttons in the Roblox Studio plugin to move code into your game. @@ -117,6 +118,7 @@ Creation of Roblox instances follows a simple set of rules. The first rule that | `*.server.lua` | `Script` | `Source` will contain the file's contents | | `*.client.lua` | `LocalScript` | `Source` will contain the file's contents | | `*.lua` | `ModuleScript` | `Source` will contain the file's contents | +| `*.model.json` | *Varies* | See [this file](test-project/src/hello.model.json) for an example model | | `*` | `StringValue` | `Value` will contain the file's contents | Any folders on the filesystem will turn into `Folder` objects unless they contain a file named `init.lua`, `init.server.lua`, or `init.client.lua`. Following the convention of Lua, those objects will instead be whatever the `init` file would turn into. From 116be16392fb048b0f7614e04c581624c39e0f90 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Mar 2018 00:50:44 -0700 Subject: [PATCH 0077/1504] Improve error message when a partition target doesn't exist. Closes #46 --- src/vfs/vfs_watcher.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/vfs/vfs_watcher.rs b/src/vfs/vfs_watcher.rs index f5d50174..9ace5262 100644 --- a/src/vfs/vfs_watcher.rs +++ b/src/vfs/vfs_watcher.rs @@ -78,11 +78,14 @@ impl VfsWatcher { let (tx, rx) = mpsc::channel(); let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(1)) - .expect("Unable to create watcher!"); + .expect("Unable to create watcher! This is a bug in Rojo."); - watcher - .watch(&root_path, RecursiveMode::Recursive) - .expect("Unable to watch path!"); + match watcher.watch(&root_path, RecursiveMode::Recursive) { + Ok(_) => (), + Err(_) => { + panic!("Unable to watch partition {}, with path {}! Make sure that it's a file or directory.", partition_name, root_path.display()); + }, + } watchers.push(watcher); From ed183e0805ab5cbebc9a5f3847c447c03becb060 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Mar 2018 00:55:52 -0700 Subject: [PATCH 0078/1504] Update CHANGES, 0.4.0 --- CHANGES.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index d99df9e3..e926ddc6 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,10 +1,14 @@ # Rojo Change Log -## Current Master (0.4.0) +## Current Master +*No changes* + +## 0.4.0 * Protocol version 1, which shifts more responsibility onto the server * This is a **major breaking** change! * The server now has a content of 'filter plugins', which transform data at various stages in the pipeline * The server now exposes Roblox instance objects instead of file contents, which lines up with how `rojo pack` will work, and paves the way for more robust syncing. +* Improved error messages in some cases ([#46](https://github.com/LPGhatguy/rojo/issues/46)) ## 0.3.2 * Fixed `rojo serve` failing to correctly construct an absolute root path when passed as an argument From 42107e0715d2916655eb986d59267d894d269731 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Mar 2018 00:57:20 -0700 Subject: [PATCH 0079/1504] Update changes again, one day we'll release 0.4.0 --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index e926ddc6..5c64592a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -8,6 +8,7 @@ * This is a **major breaking** change! * The server now has a content of 'filter plugins', which transform data at various stages in the pipeline * The server now exposes Roblox instance objects instead of file contents, which lines up with how `rojo pack` will work, and paves the way for more robust syncing. +* Added `*.model.json` files, which let you embed small Roblox objects into your Rojo tree. * Improved error messages in some cases ([#46](https://github.com/LPGhatguy/rojo/issues/46)) ## 0.3.2 From d3d67d47e1ebd6d4d46ef78a6a1264277ed92fdd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Mar 2018 01:11:18 -0700 Subject: [PATCH 0080/1504] Add new plugin logo --- assets/rojo-plugin-logo.png | Bin 0 -> 44173 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/rojo-plugin-logo.png diff --git a/assets/rojo-plugin-logo.png b/assets/rojo-plugin-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..b86e4197e2c039ec9178714452a44ed89603b6e3 GIT binary patch literal 44173 zcmc$_bx<79w>3%<2=4Cg1a}R=ZE*Jh!QDN$dvFVG0fIXOcemi~u7l6({O`vX;4tO z_KAl5l2A~;FlEF=)jXC@U)??Q4?If{H>@kyp4a~#b_9_@-BZY7&3o5TkE*8-3t*Ov zrH-YikMVIhPqa^!ArbJQ6BI5+i=W zSHJU6F8_Onrl;t>X$r?G%|3 zmBK{�n_>FD4UDF@TQ?<-O>RVCj{5F59@puvbcI+}ks6^xawltfE)b3@ymCo}wa zE++3hObX^bE{Uhm6a^Hew?n0&hEsKCFADJAF-y7A0kVB4EvZ)KuWuJpBLLlPe(6l z&4%gfIW&ZSZTDBw&hv=+eZha0bPt1oLhuLC7fe-;*5}J?yTOg=sHTdzsluqVQ89*` z&!7_Ann*<6#rdxc3}o0b7(|&=yzHUN7Jt;z;%dlnon^=uYQJ7La&BoE#?`QrW>5b< zL`(gzRi&9;Gkbvde2Hcf2HNId4DfgOVaj`L+2dU{dSwnmPSlZ@c={OWZd+ur_zi)l zvR6Yppmh2>8Pm}ZM{-#wJz#3L5YS@89pV&N=jTWJ5>y|A`2xBsau4e>)tLM&A1wLC zUWk$nr1prtEuPj3{#rAzrr_jr;G>H>E`81Wue-yh!a?C^1Y>?&UzzNSaDMQD4R01K zOrj5FeDGGC#uFnY?o<0A)x9qwYR>(MkErOs&!WIWU|U@oRJ(xc%y~zV{VE=pL(M8E z$&MvD;ghk8Q`K`2@%%peROHL1E+rnq4c32FWOItVq5|9UN?e6X^b2W3I|cpt0ia&0fZY zl{R1CobE}aMIoTiAItTTVIj?IEcN#dJ5vesNw8xSJzhx-ugpY~4+>XL>0L7>movb? zgs^Z7nO=nWp*Ofhs82{3?eh<+Mo0yzGWc?hH*=9( zCedm8->&6V{BvPmSe;w8{_dqCsLv}b{#nvo5&b}d0v{nsrbshedQ4($r{H3|!(vQw zI{>Y-lU$HkNL-nK-n)UWwp#LQ8p-Qpnn;+BG83jfdWIKNTXoJ3JxX+$qmf9Ch&RFNBFCePvb2Y zuuih*ea8#;?S5f)_ARQal?~Y%NX<5p=I<})r&TbZDHLNLk!k*mgj*RL!u%t*Wg0VL zJGFSj{>L!w`o4Yd^Oj~7#VyW#f-kAN{1P>S7QRZFa1}J@OzFr2i{O|4X~mCq z7a@WUPz{l?l9JYIp$a`l4IV=>L4yWIn*(){jHK7o;oB};K&(NckeJ2H(g>-uCAt%T z?`3E2ZRgutNe+nPeO|o6w*y-naTE50*g$`A^z~c+p~l%qZ^(qeU~sZF?9R|4&+O6dQ~E z!kxy)U~Gp!>i>DpjFOxft?ggpU}}v0#gL3Dh9J8)wCGpbw*CrT zmnSaYi4_{VWnv9pDOJ4}u}&Cq%u+O2q+at*ml9Q#+7V(C1x#5_5Y; zQ1BqFOmGjdC{`eQBE6d~n`b0{L|CKACnLx=B1#Hy6*Wn7V(nJXgqoMzWI`$GO0Z;- zDi3AGIg5Sq%X6b2TYxp%KdlrsVJv3NMlMa^L=#if8hxE|XAy-EU$4`bj@hU8-tm+2 zfA0TtV>$iq4JEB=n)9i&)!k{=s3|*AM@{PV2Psjsbi1=YW!>&psf)pBB{_B?09+RdP7?qbu-|vdzaJ{?No&(?(XoS5JjoUKOBj_ zkI@NPuzGa?J(%~%S6sEy{b#$JQsl_8J={yl=bjYqJsS?jr;4$sQzc8sgQ%|DZ}Yhc zF2Tr-mt8NP;NDvm$Mf#0_RWmWl6rs!!^ z8_!yq^Iu|k2#lAeI=ndk*3Ouz8t!tJbWYG`(O|?hHfW$KI&(s6%bl2F_BDa7%!5ez zBYBc&?0{pF`;O)4K1J-yo}yzDI6hjOMOeaTSmLW&cPdr%BPi0%CjUM_ptRWp^+^vl zkV-$HTc+atnK6$6CZu85!JXw`-2)e#Fgw&iiHCT@hP`LPFqZjfD10OyXv)ioVHHFo ziZxWoE?%q$9V&T+8oPOR+`G2)T!hN?Ns=?`sb8>l)!tVHjbflFf zPA5OML&?5J!G6|qc>6QFuSe;q{;w57X{!mUf?*r3oE#-V_I)Jh-^wTJJV6u$gvFHU z3A?Wyy${~7O6f7YjhsoEnlX|U)SKX)^el>VR0^8J(iwIuWhz0on396jqXnA_F`D$x z=5=Nv)CpwASLk>|=?zFCETDt_FUEPg*6(7bzjstcF2i2@++SZAwk?xVEBpL#O_2Q$ z%>MpDwe2XbEZ+Jjhd*gpk9%K;n{_C?3&N$ZC@8f`+Lx9pc9e56wWygGF@Q$txcvs@ zSe;usDCOW1ICa?f3(a(t2LJ>FUooJ!-lX(w*M^R6Pv4g|q)7);6i(2VBxCkU@E$V^+gha^#gz8yXiud3 zKYcozY?mB6F`U`Fq)GuiWg+p;O0p@=OIc(pwFnoStnNnxtD&0hvp2 z!r6n?G~tziXFY*o2N$;hO~Tu7E9}N{_62`1x~yFbiMcH`L(IqTKQ|N?w{~10{UWT_ zSLib}57gus5@fX+L@f$;OCMYBv=bb-xqhQW5U?n)Uo>&-Z$>fkBX|SF0aE z7J2A=ieP?=E@BHkpM=yaIpgJ8CE62IOk1K9MX^9M zXcOpM$^AfQ8qxn%J~ou~kA_Kf=rDPVqpo=h8+OR3! z#aYQ256cXA7x4jBGG))vY{+@$VH~#9_tGs(mnV-0KiORqJ+_FAUr>Idg_}l4;40^Y zVxB8p7(>dIn_QN{i5~z%wD=K;i!hoZ9^{Ls|cX4o-EK;g_8YEK8 zwiDpqBIsX)f;>Qt?7qdw_7K**1jl>>kunF%L}*PXorNuq4Hq_+ja9zGisUs<<)Dhe zdj@z%Nh+T5L0RThjxQUfPDF%xzb$YqDkL-*qFS}VErI|%i! zA1c8n5lFZ9Y|Hb#YPz_cb=g!aUNSL?0N@;^QZ-ef-*pL<=g)3n?lg6#8zZT9bz?j- zMd;|2+`3ob)gfTzUaYYLyM}Yr!3z`KXf!uA>oa>PW>b4^LYqi|wye%*c-cEQ_jyFI zlnHMSvr(c$TC_%GS+VzwKaEflE0E*4l-}x?{t*!j>~fDknk9xy6z^WZK?1>U(c>o2 z^K1=Ueks5d7wY8l-~O$hY|OwcZr(&zu4Xaz&1peBsjUoMSD!0%m57snEq@)hdQ@Rj zmBr!ZB8QBXwU)|Qo$!`7^SBJM{5t2mXLp)R{Sz*fg6Jkeo+cd+->lXj&0Ul9t&X^F z!X@DvRz@n7>rc zGDvM(e`ZMU6A&I2w}#D8wMFW>7tX2j0|JHW=*7kI?)XPd2dmvR`-qC{Mi2UeI+};yw~)46k&A^o%P=TX7{) z(Nj2KrxB43-VHkrtV4op3Q8{TkkRj+aP3ZnR5$D^>GB?0KdG&GGg9-M16YqDJeN8A z;Gzi1;tu1`6$<*pJBnKQRZ=o^xI_@uqDJZPR~ma0O3!g*UUNM|;=B2u8sw#FxOe#0W~sOkroznbF1Ejgm1U7ShkjuCR2u2?jSU1!7z~Hv3XaI z_v9x|p*OBuP}sJ5Lk0-5*ET!rVJ!-%SZp*H1DP=K@CN}fXJql?vJg=;W!UGNrhC7A z9#fLcx1HZx5thrjp2=_EdlT=P=$A7>EpW2;bSk#-r%!6vu}ef=p%QOGr!ecVftWuIf#4+f;@^Zf2Yo{fixHrJ|7HilU!{gUeT$d}D^O zf}^YIn!Q{I2@n&u)e&&z5`!%`lA;HAuXbo_G?G=FR*><=X!?o4R*B(*%GR8zdbiT7 zeM8Rn>{oq=RAT6f2aFoRm?Z|t@1XdS$d9klZl2QlXF-GZ2F2I0LO)jBgkahl6Ae{E z3N+gN2k*j>h4~T zTnHxX5hov@JG;>-dUyKTK2BM29cF{FPRij?6xn}+(SR)-uW)UUv?U?;YXM`PVdVa_ za4X@Nb=M%9xQ=P`VUI5Q0_|%jW2r@hpc}U-FLT@dOsMbp&;sHgW!!nB|4D(+1*mD7rA@i z`y7XslSVsE)Xfqq^=DZ|}$1lFV7JyJ~F%Ow7D26+yoc zn~cY@f{RV01%$PGT84rn|EK$3x;8(;7FTr(8x2VmBD3pVzI?k$8+NeOs>_vjjX1$z7<)-Ny z_EM?SrCIp|zf96f;d{OM`dkoG?cW*tF_n@1Nb@!gk=iyA0j3JX*LY8EAT?#Q!tBB`d_XKOW%TRn3!AazXNp<7kLzoLeODZ6>wc6cU9akq zcFPeH7D`xOQP|UwRHYQBUwblzo--9?7eWsBrwOQ_++s)Al(PKHd%>zDSJq`aFuFz>BBL?Ew5CbD{^rs_^nfP zAT~?qHxy#N^jk5_g6|!uzGcFife6N|h|GMbP(_|dBH-+~m&9$#Ec7y_hhoCAFu|qwIPR1Kr5%WoNGXnMdZ>)V&#)dITs!Dnqo1Pc zFqQen`sh*D3x4MtxvbsaiBM8MOw;uB#dS*lGXn?ws+RijlnY_`^M#nwDn~8pALNt~ zb=eoM7rxQXzCw-5k$j9(SX){ew~{owSM2xaev-m`k{(|()_LwJBDW8gg?yByp#zcH z+eqa+=>;HhA_Hj$FEfatlRJ4Q5A^T7QQ2SirR1Aj$qm1Onab6$Y;5!H^V;avI^pNh_VxFOR|mWjhuGmkKD93lsGB26B%Ub2n054RWNSI;a> zaQy|!eF^mMgD97#7Qf&ibi}Uif3&&dg42AcPY55x7jy`I1HvNMh8Bi!p>9vHGmK3n zb%8e5U66}9#Qai?1h`OUgeAEA@WN>$=1&y-Cewiq(xp^KA*|mcD$mq#o3FB$N|{i8Dh)% zx=DzqDKja~gfoipcg&kGBaMcYQ+A7hao7N}hpqJj4i<8vm?peflW*{Bz5VgXRZBKX zx*rpumm=ib`0h}xf7yI#==k^)>eJfP&X+06Z~I4isS*a$=0$6kd+7{$B1Y&EsN?re?n7uQ!!lfu3%%AleDms~LgY&Z~Fp>)l1U zydrg@DfI+Qd(>Dqz%qXRh|pyFM_VO))8*&%iMgVyA+#qBbilMpiA*pKGXX<(N)K`7 z6z`cPCq2pKvnAw6HS29DiA;8G)gQKq$6#omS z;|f;2ZdP@6oSiwA+^sPHd@`i`e0p24^tcrc1(OyZ+<~P-DO0hL0YQTcbzQ>rD?-DP zcyBK_vCa1be~_QLp1UjSm!JN4+4J&!dlMtUWbv`I(h??pzVGI~?PRbC>$~=_2?_S} zwUN$(UkK%WoT5F*ZudwmC`ZNhNhs_tBv@j*{L^+IH@T&)2ROGHH|lku<_w??(#sYi zdT4^g4DXmnc)k|S9$_EVYaG@8lfeLXVL7`ScIzE#Y|^hwG%jY z`N}%M+_xx%z0WAhUOOnV=k4gub`$03kl{DcG3pTQsC3g~iVx#}EEPN%rA;jF zPa`&WVzT{LTPN2i79b%g_V4^H6E_eM*nIY>Q#tUzQ0^dI2z_T83=kGMKun@jESW`e zcjI{3*1hexMNutT{^qPZs{L{9qtIh!W?AO}jx6|891S{Dn7{9kRtlXeVcRy7zSED< zs&XIk5ox$q-oh&5$T=JFyg6l#;hLNK8}eh-pPOW9D!i9nI$K4-sJ0GRRmXRqL|$kB z0%1bvkqDp9zO0l-*$GU{<-`ci7j4=qRSr5SsUG~&0WcJ#qK)8 zYI=89PX*;!f;?S55kIr1D=kkd@blv*o}UXR8ZS3PwPR}bB5Pe<0ST{CfCy3lvPt-3 zy*X$LD7{vn*?^?K-tZZaIyP3tUwgre8PqiMx~+@U4rZ%bsEXQ0r(xZ;dqJ^q2wWv8z#=$H<#{KtlKuF^U3DnZPCKx5>%gTb{HKR<;C6^E}cL0 zCk$2wx)<@y{+fp?uP%K!oPx3AS4fcP!1_ac=OQ>UvY&pnB|S9kB0xHP;=pilc1gg0 zP81CwM(U1GJA(#HO)W0o5s>(P2SO^jrADd+6(+o_3(ZH#ftp2ibOMs+dP8ZnaQPM` z%ej$=otv~%!rierf0;#lLmKwvGbsHC(}T!%JpwL7#5nZd71 z=Nt66{B78(%I~ZS0$iA4n@V!!8Dhv;VEMAo9)wv!^L3Id3$=`m<)M2$_`O-I^mMI( zL^+@%aOAnA;N|y7v_%h&45Nop?u*Y1s;fyUZ?h{tEk3FFf$O`~zy0OK1QYrxRGJod zL6Ejw?Qi)g8#dOjW-~8_S1LwZ zu0$Yw6RxgA&$*D`y0U;{Z#zj_F2frbUVyB{;>Mwd2h?8&pUBNi-hezdpjra>mLqWt zUS|ORM`I&)$c4|@a z?->PUIayB6{BlTBNt`L`7YCoj%}cGuFIEu?3%DKMYw$Wdjd!`Y;SRq{TWt8pcjvyw zPAkTmoefm~;V=g1kgJ-o(#`{oUv~|M=BHC#Ou*uvqOg?&E)F1HIa?aByEFo7;O`;1 z{-Q<>&<&!Kt@eV_M^&F(gunzJ?0p}Oc!OKc&CIkH#B3J1`Ez_@hU&ux?1jUN_LrC4 zJR}ErA2dbG7D*u_3+1)iSMgNvU4uajriFmEN=2y*hzLC*yn)sJaLFJ!(~*!*`X3@4 z^yI0CzFi*5Jmvc2bTa@7|pgc(Sc=l*xd*6!zh zw?LWaB|sW_E`^w-EBII^ma6 zB@yHf%&*6E@{+E>TlG&;`KD_y**oI{36(Ej|p;OI?jYM(_N@5K%10UW8<@rZeT25G!Z%R#pRT zd%em(h!T)KBbY-`OC~Tg&p&C^pnyY(S`Yq(D`NQ3VZY z|H{PiwI(IMSrmXYiXYo&0oXTY9}<>-Y(S<>r#SDN6_B~nG#%2k*b|H#HpnIK{k~A( z4d`f(JlU_tEm#%bl^x&skY|q=F#3#@y!*g(<&jn6E5&;W zc_o$466Bes_H<=S#j4#?^p6X*7Y=qTZhX!-<%J=)j@bNd;{3N|OXQU=Cr9{ceYxqE zxB~;uKmLs&A((5*FJ6}F&5?20fUvjRCs#4zqQ#pNE zba&IrDsQGzmd@+PEzoQkfMwVOGmpSMHC!9*?T|LjBm8G^EpGW|$sD zO^ldf>3-X`vghM9JZDYq>L9ZCDrT`6D>5vDr=Uz(^c7B27x=+U-K`J}2+ z-HU=`(Df7v;HZg^xu|-TDU$4%%&6;-ePOW8I6AG^2`XR?p7<$dnc0V_B8>3n2?)`B zC4_Bhl8miPe@v7Z7;ToN!o?^UB$d;PVgU-{>_c`K8!q;*){s6f{@8B932u{5l=74% zGaUKttzv9>pT94-3l~C4y3Aewz_;4hl=EhRBImyg8T$ z;kg$HI#9*=K4bkbjNkI4QN@JrUkC>_{0gV^e^dl%4`T(A88I-E0dYu0KekkxaJ)ow7x^Ymk^Oee`u1giFCAmv+8m_SZ2Q4e z;jXSKy&?dxUd)}DZD+qCb#(b}IVT;ElfdP(WulqkYo}AJiKPu=Xad2Y-aPMO~JK1dts?X~zGBnA>PwRyA9asGPx!yq&xa(v0DPuQF*E~G4*B#Zy70l-O1(|MCb5`+G5vJ@BWzA5A5VZY#A3$nj=s*$0n%0po z#5BC#_4sp^caXlw``lOOfy0(^Eo(G1o_Cz1i#A@tcu9)zk?#suWNS|3CBu}rkv-H` z2ib|Cj)AlmNUaaun5WNR|A>kPli|r=vPcUi8UW@@Uk>@s2|K`s_MFZMNwDsB-AB;l z&Q`7!ZX=G`!*Te+F4S&gFF8=}IO^nj<#aZQP@LbG(0|H5p2&1)a(6!0oJ4Py$4;&x zOFj0sr@nZqG@Y@0p`9QvoBwgT`hD6;Td0IT=wmWf0-O}OIJ}}ciznei-l!{?491o; zbb~<{IS*`usEB}wFy$y*V(_w&o@(Aa_G_U*Q)Z)~@ZfaUllLld2O|SPARTjSilDt1 z<-$m&W?p(iHe=ub-1vh&@wYyRGq5-Icezo;o1IRytYd{6x z>cn(2+ZQ@aQu(M}ZM7W{p#E|eH%y+!UM7QOONxw~Ik?=6u(r|1#5d5jG; z+pO~807^YsLvHMZ_8jpiN9Lu=J)o+70h#kSN62S*&;|ZfA-8M@XTaWypoi9$1eHwl z{?hcR-7Xh!1XTOK2M4=JlQZ|4kk1xAR@x}V`LYr;zK*F4Y#R|wK&iD36Vj>1|7oF| z-KGDrf_?u?&k!KDgVz_q7(^t1sLA|jUZyZ$)3D5-`#DHhWR0bxza{qt!Ej?LF$oM< zD(cE|&itP~FkH04>)XXTjcAb(RHg(34c1LAz9$5!dlBDfAV7DxEiL{%apSn{rj7P< zidGX81&JX86fnTYu|K>GE=hK^2&a<$Y|t+CzC_6yM>Z8t$kE)OO_EosHOFNraGclM zF%<-LPRl?4KorHA+T*Y7P`6`o;#Z(aB9|(m<>masj@G9Yj~E!wk>boUvu3rQ6HLkEDTpK{Oj)t_%>@P; z2!N~|pDM?n(%e_Ri};D?U03b|?ndF=0T3LI3|(;Rmw(dw%OT#y34h)@4#AL~sy!vo8rdWT6U>A1lYCDDrDfYuIJ({os1Mk!c$Rl)BW0k~UwM25{ z4554Nk)r?S>8ekM@{+4HtXH2MxVhn2eT#|hH8;!{S(sbW-53|Pd(_uHF?~qM@9{Kg zuqq(eUB-pezwgJTf^S%omQ86{P@d7^9Jy>Gbv}fEO=u?T$ywM+lxxjtKZ!hX0~C?_ zJdOjnkBS)bz?mR}3;4Q7m0Wro)jO`VhB_`$6lBolFSz2Ji$_LBlv+tJ7EEjU_# zFh(WhwZtQZ7gMijRs}qzZ}U(`nz*4CC+UCZ_O(%vmJgW=$^QX9403F~s-YcO(CRau zK`!})eCF&`9LJa=QKtB}+7EJ>afENz0M;-#>o$& zNgg4PrI`f)6BB-bDQ{rb@EDHE&=IFq!MkLQsQLj=qnsC|N*PvCWp>ufiXl*39OmP? zisdAwY&`R~0fk&dWxgplGqXLB4CWRch(a0 zMc!^-9r)vu%0^R8j{)bM&KcKQO<|(U)5c@`y1x&BJp?ULC;5(7r_UTiok7;^!l;*2 zP;zTPvi@VQ`YQ;fBx%6jAG>mVWOMyPw2w=8+Mpr;-fSsMegEL3i#T&HP%z)rvw1Ye z40X=}s#XFAzE4NcKbG*aFsi5W6PBGN1uuJSwfSYDY8g;6JhWCGGJT_g4a0xk#gka! z`ARotn0(>PkY4!roNWJ!tro&swZJ?RL6ty{8>j);T%|6<(7pqF0{Noo+!KWcV5xn)9dQ3@#L2GO=zdkTFgq^=R5hFY zi=Im_p``#g;L<|4sn$MqzntUK@qfXhgpD<>C^H(&g^;Vep9iFa?nB5dx&FyJ`|G-_ z%ax0#e$t7-N}J*nrfK|+Dbr%K(oA)AkPI7XcKnZ^-0|gmmhHYmcm64zO1Y}@1T%aJ zwkJTIE**^$9-IJZitq_L!0a?)-QMorw^i^;v~+Kk*IIM!QUa}r_^r$ zWFw4_m)HNDJ|SVoS=DmfAptM-3`@#!dut8-6eg??I(ZYK&VP1#C6{Yr{%V3+w}sjj z)$z-8J-Y@d4)E|Ht6348N%A?UQu^xLOU%{hf9qu{zdhLu=9^66=5rr9a#xFS9#$Rq zrh-Zw!6;5I_Ws?Q&!i?53?)ZbQuHl$i~tPm{kx@#$lN=xBmWDsAB1(f6fognduD9< zC-G!#LPokMP0$m?UU#v!qoIo1E)~)6Vk*#9asn|709JC!-HFcd@0!B$P*E|!W)kH4 z_v{bdw1pJPR;2A8ylt`1tNdstT@tfQnBxGWMPST{%){~2#VKMsdIFe%in7M0tZF5!aQbJH_7v`3C7;Ozj0o`uV*TiseeB|i zdXuq9vsqG+i3$H3DZK31C=$W!Udd@!-G7E!f~0rZYqC2{Bwt5!U(w_ox6DYT*(i68 zPdiTK7^E>I02a(Zm+wN!OUwYp>DwJ)sDvKLzjDCiCmNE(? ztgHB@WpR4h#^!0-I#kj8QT!~& zJtXk6g$;(LHSVy{LwW9D3gvOJ$47T>aDF*4M;VqUVdiJF)E9l&$@*>Evk~t45%vhB zwC2IEGP+zqgsP>kI9mg{Tv+JQ0X<}wdtSBKgabVlS5ucKw$)00B1^r4GA@L2_e6dP z{1AAO5({K|PAV~S3RPzDWX{=7IpoK8JpIyZZ_G^pvYL5uek}GL z+VQQ+e8^SFYiGj7#vw;Pyl_6>oxjSX_pcMse0AG#CA>8qA$Ls}C2G!P!a(0#?x$Dq zAt>v)qy+!%5DkjZ@6y#tcVQZGFXbW(;ZGED1k(!`jg ze?>?7u^q|JBki(pj+&e^SyXYnqvvNV%Vy=f7k0{~fwUmWWR5yZ^FkmU z#+?WHycJ-{@B6Scn@krWUc3r;Du8Yk0GliVwqWh)#K~twpsnWZHSFkV&l!MIR;0~A z3jVjmiQRM^K+!;fCplv^WNT#vfac7nwtF&un}?ux3qtp3+Tf&rO!UNPd)D&Ec?Aubar-+(%b-589`El2U&PWabU`Ye|FCq zVYMf@7+~Qzn^JaR;0i9lO)dzfrHOcYNt-!RU-EGq79fmbbG^kHRx))gS-i$TYC)Nk zqeD(MOP~6I2$7Pi(;&n}NS9O?zFT3%!ePCgCI{%53}=iyfZhi@A`c%W|LK!6YXYpi zzlMIdKG)O}ynLXx@mBZ&5Occ<4hkseUpbi$IOo9|cQ zg~9OnHW!5l5eIZ#lt%ZbKGDvuK5Y znlEBuGN=3Vl~p=FbEoqtQmD*W#hby!D6)Chx~{XOg$A~(d%q+BfrNK#Ga(7kWIKPo zgfflJ3A*s`M?D^AC1Su!8hGa>Y;;JPE-TEh@u&jAI+Bk=e3HmBSNB%Us77zLyMP21 zfFyrE#&t>oHk_aOFl$Q*pW`2<>!{`ls5)X@n1mS*x2`M`6aHqTr?RdBLg`FLDLyJd zZP)3tsV9G;&m|jWk9bq20cDNrSn7Es4v**E7N4L|B>>z2Epgl2UnMjNz)llbsLb*3 z_73o+0=*L!8fA;CA$STjg3OE5i_3aCeVeekXatZsYWLgCE1Mfb8nNz_Z=3@Sme$VN zTMmkfvp1*K@}xovKwCr=U{ByVRk)KU749B-E9h(Y%ZhQedBGJayw1^`(iX1t(K@vg z!9XBKQHV#H?27-ENZ-EZ3&6z7JJiV*RmJ{oEm?#*Y?+F_Qf4e9cBeyVnxuqwOK<5sM%@G3KWb)J@eXqHoQN&mf8EsN{ z&+!Erpqlnc(E^MS3qu}DnL6Mv*Fv~XaZ#BxWq0wtWIIBXOEvdm2U-lf)zto62ADMK z3Yg!J;^wmvvZdkx&J4!}w|w_yHtc=o6^kpY_;AS@yqIX;duIgJwPlI1vsaf&ei0i5 zEC9IvWEs*wgdjHWWC|orxVza2(lq#?*_Y@t55_w3GP(+scUjT1*uyAg?I`f2w-6M)bx4Ndg3VpmVVH`~)?AV`d0=fc>-U zzDt)s3YArzFDlj6+z|n6x2`XC+ygDHE%EH7V1Fa%c$tu1Txz>lz((^jK)~xL z-fK(&be|cNN(6tNji3TL5|ypz9pt{ zYc9lqyQXTW0kXRG(1%q5xM=YNoDf8@0LOwKgI!wypu~TDaE4Zjr$TVIDSirA0W6S` z3w=UfN!FNYjMm{;$DtshrP!}&= z12)jGwqY3eU=58=4@C{$)=|^}v{@oOkdfFtuUFe+*C&cU)=Pe{MtAJguO(0T0-`GQ zyaZX1cEXz2p-fxyR4R5z&+QexZFyV13R$Q|fYT!_T5x@f~bk?$HwHudre1k5Q$ z4?#hIEXZ)t9sy)|1q+|V9Kd8ID9lw2g^(ERtdHz!*b-&RIyM(kr?%#aNzHTi#W^N3 zrzZdk-QTDYi=UN008~wj9fO|kmLx-E?!FGBm!bMh7ppr&DI<>`L%VbNic+40izW{I zDZ9$p@F7YuAWS?03AHk%6W7uPg5Y#(^Xf9ACl|ubx4f2IZ0!N9_5W#sSY^LrI`l(~Nkac1FEM^(s1=?PW&5 zW4Z0h6+8a2*23i-tONIgebBNBhF06B_1F>u#DCSX(-Y$22vGGqq38I< z6I)ku5iXjh9oObDKxOww_opkYy8s;rmn)>k^o(D70TWVXu~WYnY@o16sHK17ic5Nr zvgh-;dV+&OiOK^g%j{vNfa;63NV!ef)in;Osj?ggU{v)1{N0ypkfNaS)4(>xBK*#{m?8y5>?EMGIn|nq}TbyVZPr$w) zBUwAIw!Gait8kW+@x_|^(?bi6I681M3>BW^2!ny=V||x!Ym@DvS<*At1%pE?HTZW3 zp@F8RKnwCs$|CcRz;OjUM5pRUJMN@mG$N9M*QV-!?KCOIJLVxZkKS=#E6bXq&b!5oqe-PLFzg z)0T}=I&oQYFcJ({u#zk>B>YgHzXcc2Nb*lk$FXjh{=Q%(dhok?Nt-42xr}m)RSY%` z-SQ;wdLpy5{rTH1qYZDdW?9`@aoOBV7eGta)u0R;x9v-<0y+H%=%4#=aiRM|bLv3Z z>6IHG0fY&oIs;Mlfad3?KWzND{@H1Zah1h^Pf{1XX_>vlq>#wG*RbKf15mge0apX+ z`tUyB8xAC!dK$ClJuWZnJo8ffcEi=d;+2HXm;LRbAP68#fNslV7Yfmp>Kw}LYg0J~ zReFqWv=9MqKnIZ~KrZv3$Q&IVs#tIn2YRli=>U@7jQ04`dtEd9lK z8uN{3M9I)~%Kh^F;qOY_tG+Wi{cIUNPGm5XP-gHroj#T@%C;u9BumvMeT#{JX*ITs4Upc6^#;}^FG4I z!bXa@%TjMCHpuLd?nK0Ak4uKq*d&Y(?yg?FWtLg}w58o-5COTi`vww|yo7cUlYws9 zSk@k)tC9E9du8V9_`PVXw+S1lg%>rMK92nCv*)tje7I(ar$qY%!IdGdwiUpJaXXbe z2}Oz!NgCOZi5k@TGebsvXM|^u5j*!4W|W#&o4zEX3Xd#>3g(qz?iWsf+$L||Q_5^o zQt!0W;t!YfN>4?5kM%WIzl12&6E~~hfyE>?DN*4~x#>o2w6re9{O_n4X&zx`k>!Oi z%=-(0K_U1Dr_mp@3o0~=M^)J-A2??ct!}0r{B_)AwYFP#t#Oiaz) z)pxy5oE4lx8zHAu>4N@&f2#@ftZ`XOT#AH57hD_^xD7$HQs`{l@`JuzpkF$|ns2no z$rxZ1-mhbGL|(Wb2+Db%!CB*n-aIl>ijFW~bt~FQTBG(i=;(b?l}k}D`cg3Yh4}#f z3A%d4mIT~-c9w{t%b%to0lp}R-fb2d;l=da#Ft_Q8Tfa_gGk_K+XyDvi^no15k5!Y zR*b65t!+|saL7SL4X2g&Jwu#y)-Jh#wO?!33X~5hR5V#lo4@HLuPm45QTcy=Gkkd3 zJh5(C_{yn;d#h>T9v(JIOsx>1IBtcgqJrBf?-thXh3jE`8TQF_dH{uueYHVtn_1ej zr%*BPh|XZFF%?C&2U65W$1SC!oYbH`qEyQgUVdwC%c_vQPN+hNfmrU`?2t!MdnZb? z{j~erUCal=mtIBbTBzB-=WVx6vB}!iv^}ACKJWHzU=_>Q+{mu-2j$S&isDMKlEVQT z)i4D#n|)2}9kN=Obb2l$-sHSd^!}wRizFoPm!eLzcL>wRG z7F6!TnMf^4)uK~}Hhkq2A~e1$Mvv*Ep(qaukd)!V_-1moP8cjsCEDNq?QU?OE>A)S zREWMS`5Ul&Gpw5aNKw?O`Odj1roI`mgxq5Zx8?|rOK zAwu3?`=!CsYF0Z^rpVxc(k&)UTT7Y_?+`*!$A4tHEbHEnzSW-!xDUm(j74jxM`C>W zoTJ9+u=H^7KB`hQTyNh)dR=&pE}{+chm6D&w05OI9jIrd(Ah4_r9c?W)CNVGcqLCS`|$3O$Iz0g`!IxIt^|8?O{)*69~8e zY3{V7bFZq>>NuvK!}_v^HaMG5`QkTuDm>wi}>1uvGe7*xFl zs~w_}xb~X*_5VdVZo^wq8}C{cve?2`Ov!!8lc$#h-%f1Ng(#&3<= zoG_}^NSV=w#8fE(b5g1HKv)QpyfKL${wQL;o*a9xi42LO6aq3v+43%gljQV)NHO*7 zvu07Vl6J}Z1wT~l8*P(d+7ny2z2RIpEPCB`l##~CWs8ZxS7i!Btp?gn=-AwDmV|d+ z;UN}Wf$>k+i#Qc5tMrTV#WSnV`Kj?RY?d0XVuQ1FpDf@1k%OCDoe`QRbn<$ncH3V~ znKqqM;d)8kNwCy5?S5tX>t6_Z^9HxLM(pREefF^{E|aFrxxgRE+ShNgz@A-10Ke!x zvXmmo!ak7?3~6%A^ol8rVEONSs~k&0xG0|fQx3x^()dI~Nv!DoG;b0wJ0ry1+_|{v z=YO*QuFlqZkvTrR3js$wI)HBV1xZiUOYfi3x7ugl@oJ)egbF_vW z{luvz*^UhFMd^GqS^njdZNxG|NVQH(T+sW{O5gvIwb%DcvB|rF6>7lrl-_hmpmMCZ zc!*b!C?a+eNekqdBtU}-H43B|hi57No)is^`0=;Wh^}Y`GRSk-THhM;56`cEbNBqx zuKtwHt*ABv%aP>`PoHDtqn$rphj9*ePaXb+8F~ql)d!FEo}isj09io4$5GjSr{F8S zHW>5|!XRkzF{|q@H&W5G>|b>Gp2Z)}jBqRRXYx)%@>gPxbKsDvvP<$jYL4BZA@C2y zkbry6DY_KH#GjXjT@r>(5>$t4-4w}*^~RnRk&keRNYW3y`HRO@)2ffU)PJ%@rg9gw zOxMeve-}*t6g7fsEAc!aH|IZF>A`SR9n%50Iwd7tK#H_=&d!jq4|SQvT=hfXX1{+j zWb@$NY?XFJeb`X8lQ#SCX+)!@cHi%si_&N02WBX?Bqn2W`yQh{dAB|PgYw!3Z$}6m z{=5FO4nA!+gpI!xJ`G%09L4?2cudpMuN5#`gVuJE5460B83C5{GzV77zM@ zM-+h3t9tnGjKG1IqT9=1aa*((jQ)J@&{5rtNYP%jk@;` zRE*|x82!ep0nK5NW!z5J!n}$T|B5D7aJ;bv9Ub~ZAWgxE825a9Brt z@SOX8=wrVnOA{)~4YW|2>6Ao0;1&SL04vGuNZuUZo&>-E|59&J;?s-G<3gaED}TC> zADMO}B{`U;_l+Hw0zL)&EO(wq)bP3*I_^f?eGsC3VE9S+k=TQ;e!3h_4_sNaO?mqp z)^JcZM+qim{G-Wi4zPpLhK)<<|2A#@m-AD^x9fX~`d9Wz;RkSgkCg;zg^wgu%^K2A zaTy*v?Sb1u;aib6fdVwtgPYQ(4+dYa*~iM><5Z9Sadz3pOYlGx2gCk2Z1*Cjq5~|D zfhm?(@%h|88RO)*&gY*zxT#73AKZBC(jtzY9J0oX<%s+~yhs5WiCCz3qWlrCOG?{!of4y=@+PL!mpC@SloSkkFbS>%3^@hc?aq}P zmsN$sR@D5V(UG_WSu3YN@yFs5f2m<=o#GC~nv7g}b5n7_vAoh(J&=XZ*cOtQ23P1M z^DZ^Uq_b?~;Klj{3SCxVu9Kl*95i_+QI1gGNB9)YgcRhF?Qta=ooU5~p+>tZpE%cc zaQBC&KE{?Vkjxy`W9g94)Dux1*`kH?GI6k8M}OS{g;{qauV5P_JP>Yw9%($y9on!e zENWjZE;{2F7m~ul8L0_t(7n21! z%1SoP4*%|kHl!P&W=87`&h#Iuv^^xg@!b9LxuJsDGziZh3^2w&C4Pm3voy=cLx(d( zO14PzKnh{L6+aFSTm0oADjFrj(`Lm1BCI7|e!b$NKH@=5CBSk(X47V~$X!MlM?7;B z2c#M~I=?W{6a%T)#ie+E$$vF66f~)vx*fHBz5;sU;DNm!=0G>6&=#)cHujj}_V$TR z+sS%AVjd%E=WJ@BetilhP#X*ziX`inE~3=@XqqRj-U^1nXbLBp65K?GZg&@hZI$cv z<>z=vdZEeac3b)&gI9Y$$LTEa5$3{Y51=18))E+odUu}JWv=e|(#QVN$TI3kYGLaMuoAVEZ`!FiU`AM zVNx9>7n4aAh5ejw@cP|+AiOvv0=yAp?L@-_GNRE6Kw7FO-o(UKn7sx~GXrKLaeS7!09mQ@JsE)DE7 z>m$K8GE@#DTJ~2i=f=Mg-#bXrt`H6RV@QLG88$rff(nN!Nk%(Leont3-_$N}O?|d~ zO6X?>hS*@R{Ho37{Ri`m^ueEEDJUAp`D=~o`vWYD>AY;+$OSi|Y_;XHhvn=~1`k?n z?JkGQoN6xA#d*NzS~+*ttiNHPb*W6R*Q2+gOAPS(mGI zuV}7nb@{_6l2#F45=BUz+oF1QNfRO6HhbwCcE6n_rAkF(wWhxCQ53Zhjv{XG2bQ*9 zZ}BYqf0zFHp{mIWoEmkz%Y~)iIOHNXM_HB&aFHIwn9zvP{fAe&1 zj2Yw(&G-TR2mPx|{_XD|dkn+|LKhn_ErM};cF zPmvB7kMx$(#ai4v^G*5)_s_!UW(YN$K{)4;yptv=Cd}a&SMx6%`sPigrUmhRdxnQi z0ueDBOUpPX=$#qEEws0SCVj20N1k9z5|cjAQj27N2;Ec_8c8M!sZ8!4GB;U!+~%0I z`)q(vvE#cBF?YQJ25qazW@WXn6~D;5de6N(EZ=d@<4Az8Ykdj)Hkn5Qs$R?w@!2v&U!hEtB6LNyzL~;qCjSbMa35EaJTF8{&5Pu0rz86W}9$~NJkGIIO%(CGd3DN{MsvHl*3^aMZ3R2GzYO- zdd$M?$CunP`sdSNuC@VJ`0(3r9#)34oTyKO>~ngJ-WuI?(JXiw`*bUtN@>Jr6Vv>S zJ6n(4XR*q(4iFP6YM1oi$9`lY5Dzn?@h|TR+?aVYY!+|P7ckPJ_z26t6yb%gCYaT1qnjQzY0bCN7&yiAVy3-!> zRUx1VDLL}D@0Wak3=uoC=DzD*K#KrBx*;)meGs418={uMtESZ`Yd*-Xfw*9LJ&6)t zXU|^Tk{n$EBEca-llHk@iE(6@So_-9O#WB;?7@|Ze{E0YJ(P5GMHZ(X`}r}f5n(6# zc-r8gG*e<&6TdzKB9q&L!k6W|HCHqR@-)z{Jf z4My;#N}e=M5{zI4E11fN&gSN_n_M#$g2Na}uHWM|?n>N7baX$#^#{fb+Zqizd`qBY zaz;O5b3xzi=}*AA$<()Qu_MulE}7iwFc~#_@Hj#yqO1^2DZSIjblFLbrogA89HDBr zh~OfY6#TV%Ga3Lih+7QM^MFe=vFpu$gCEDgxCet`2K8i)ejX|Ju%GLQY(px~Cq&KT z`~oXpb#n$bEDA6OG;ulp5=}`-UCdtlv@U_B^NHV7ke#{ZgKdOV?21yzBEse8GT1Ny=^iMBjB9(rHv`9;J( z3?RJUM&DIbuw7_Z)XQZ^)ib@%1VB9B^}|&ns8&k!#{{Bc{C%EcN*ud13$F32tPM#^>*sF50}n_;NxeO^fIl`@=3{={^Vt7 zx!}gQG&*dm?`y=7k*8mD5)xetY^18X9~}K7BcUOuLaJ(ZN>g9GH*!vW?ElbW>ILKn zXd?FRM?7pWY6_Fd-gB_SKRAyeKzSB?Si<05w6A*9D-a|0jKh}5O< zg?`!Qvi9_$$0euFdAupf(4L$EuEo|9Tuf~ij7Rt|Mu2n9xjXCL7Sj7ZoeBfQe9&Bc za>7?Vb_}2dDzK5S{vrERB0yPCK3LPGlbaCxE0k*i7y8`qMP)8C*B0IKad@90&gWi_ zeK%(vH*`lW$FVnCUsl8*ttepqs6y03slyoPI=^(B@7Fa47Zfh|PanLd39Ko&pc2I& zWlG#wj};t#UX||o*bv>z-0WSc$f!iZZd_)4Y|B_2<%yj&>; z=^UcyD-W?c{@7>e`w<|^S)<{)GH0n{v>N5;r{DtFz0@_A5FA?GLTra`P8&FiYAUf`GeuD?A1_#J(EyGpPo?bY9!O+e zAO}aP*fpF!3j27HIsP)*8aSJwD;YOn5uVs8V)5pV458}W9*<~?3 zs6sP6fyRJ+=$I-`?)A8Qw$I1Ym&6kDA$-0=g1~Xj=?io)GEaKzTGULw?s^B9arp@d zczVozvC4b=-BFNXq8?Xw=lAr7#Zozlm7qj9OW1IfGW;_zMt$b?7E^Vb~Mz*&LDhiCwNL_Gpa~78)mIMZ+tAFweXTPPZijO zf5_U?9BQC@?iXzFOV|Bdu*WHDY6-E_AhT6haU=m~@#$ul^Hm(tOS%VKV$$IlwK4ky?D@5#SNeN>23g#1_d{(n=`2L!P?g}Qz7}2HrJU*kAxCP3& zu@t0G>nltB8YeM4XE$)xlt3tNU4x?~kE&S~S4!%*K%PPa*bQjjh|+)XK;me#*LtSc z$M0)76d2p66sQfC?L5vk+#jxFophO6kYv^#?r{;1$Jq$+#wo(2$1T%)c1l9$l5Lr6XeLA$88}XLMvA$aV$&Z$O$3W+S zQp~sC0}O3|HKg@6O>21_{ox&cLN(h>;_@mGm zHVnubc2czST4bC8xBWiZx9bgLSXuoe(@&lLtW@>6AMw)POwOG3tc=A5!ccbiLD2tT zKl_O%1JF}<_SWAfNqQ92`t|X>mReB|2E>Egilbt_JN_x7=MjBO;0F{anr2)(KG{ly zK`_E>U4@hVefv-v5g%%{5HVE^SMxA z;d5vAb5ft{DJ1vd>@_nT$%>e9Z-`rzJ@V>aU*5iI*&=A)l15Duf?=_7Sme}6a-jTk z5Dg&SIHfgRD3!{ zGF5FcZVT2#O}A;n55O-2eyWNV@SJnh(g#scJ}QAm}ogg2-yrWfa5_d zXdhj5edIA0_09daU&94zVdXY~`Et!_-9rh$T$x>{i=>@}P|{~tI*($SNw+PE3%UUP z){wP0=|LhEuLkpmFg*}x2EE$vVg~h|eSzknOn#%L(wF@77+{06n)9de#*MXzQ3Oer zWe4>%?YIcWW$2l9Z$^rwcZ&Dkaa3}j!h*>X73y|&@xwQ}r028OzH{X+lM7)A*|=h1 zX3Yyd%gjQNonN7Nm+h$6M}-X)%%^4(Y%Bi12Av+_rmN@YS#3W+lFM&6=snIKLZ86M0|8?$rV^IN(M|uc+f53DAk~(j@CMb=x5+StSpckbwE+=3oNDhEbw(bcI7X#DK z^7T&_at4D8Gn5o_ryi%If;W2~r)REWl6)%h;A@&ZKwgvolYwmuZB;esPwSq$)`^K{ zKLZ3LQ~@zHn9YLX<(OJKuEl7UrI)(ac$ULo+VL^NgTP6+40?6k@E2F!G|tt%W6Yk( z0Rc+Qd}8ocKh8JF*Zlsq^Gs$hxR+1^;c5|U)zw;^os77=Qj9ilqzI7o!wNK#RYxQv z{(WZTOFxPb>m$|GNOp~^C7&&0H31Zwc+AO0?Qn6XM~H<9;-TyRg2`NtQv#?UQ!367 zkHyJ9iZ}?jHJ>$%^GnZudUSwf5r`=#6BH5t?RRti#^-s@11_=XuyPWAM++(*LD3!4 z9b7WvlmlCM6%|Lv;1Q8^@`?E0h7WUc*UM6$k@2+Y$lNtL{}=7?F*fT|ii}Ebsieh& zsan51IVNvjqNbTqDTw*TuAD&rWN5FYRN)CYhA>lUUQap#+ns-1HI^ls#{^CvD&k%? zP3S|-FL5B=MJ>6-D6(_b}f%1^5#3yhY2mjpO8 z#;N#UVg&*BY9)yvwIsG!Ey~N`1A6ir86Rf#)5+pMvS#jsKH>wLGJFD5PpB3Gc|h5H ztG&O=9+8Uk!Kk>>~nz$y2h<9VxOIz4B6Lx7DswN5mA^w$we)k_~=xoAcYRtO) ziISnN^Q*xInw{ExTXI|USB{g&@7r(Bo;s=;WJZ{=ky{Om$O;}I(M3zym5>- zIvrjj49g#JSNbcbZJQ;xj}Q0nUQmYz8f3bHbJCI9XqvJnj86hXHSHkVfkq%q+1 znVoTz-sxH~M+1(J@xCpa1`17-e;28vvRgm&ot9C*{eZc7@tdN}F?|ETFxa$FfQ{vr z74yQhOs{~cd1g>vpCUp+OI5<*XN1Ft?rd_@GpOPi(PRCZs)3{{WZeei%hF93uOAmy zvcZcxTrEOAM|XJ=9D&4(zue&O$qQH7{H=yjW$#)v`1zht-}PT4v2l)FCm&Sy8B@+Puk$$Scr`iZ^N2zARM8v zXq=Pe*zQpO#bkXe#3+xylnPKkF#G%ymzgXZaG}2N?Rp_Q<}DwK5uq*w7UHi@Ya%x% z0xbyIc`o`ZddDubm}TxN)|8RX%b_Vc-fR{+J@5HTJ1Jn#5T1n4e*0OnhL1@SZey_O z1m5i|PR$_7m8lvWOz5o;5YD?UvHd&!AbqcgOalsdds)#!PEp!k4cyQHwpuS%Im);G>s6P7r?%n4S4t8df>&I!D5JKOPP=sqDnuX zNh}t@w`ZtDm~?Z<^9+bkRy?FBDr@!tvBl@Dg0Qc;n4W7q_01wB(Il*MphEcE5B~~r zcYEadJyMTT`JVjRQiix!dcG~CcM`z5`*#3P5hYgBN-z{INZN5VLomU3<=$@=7V(e>w$>r0XOEppA`zwUyMRyNs_B@t!H zH=`~CE3CDIj1(b@l;re0f_rOobV>k520A_zV#4F7L((~kOVlFaQ*WTszW%e|`hy@7 z%rWV9{GT=FyI7d%j(-Lxl`5lceTrodmr0J`Bi?+6^S|+r9wz1l*A>4Caft=#3sa4~yei^b7~fu=DmvoCCF+d4Oywl*%q_T_ZY{X1 zoQa&a#_uFV((rKB>Fw=e2ZD%!D2txLM%K;U5((48_-H6N#m;dsEkk1O@G5-9Kfl7X zZ&(rbsTiIFKmGQm07WpH-1Gx6@Npx8>4Bu)2SOrjSui$xgrf8qQq$IlJfOLL=URRA zkVesm8jM2;E5k%s5yR@SOAZ+H9Kw0?QN6uxNV4z&3Fi< z8JPEA_hH-yaPN>G3JCNpT~g*;c-U-aV>OALdW`Jvmwt2V&;AE2k>HFm!=P!ky_1*^ z#K={FD@(T*R7CZwE%6X38=nmRB-9pAX(?VX?7Dq5N`j^0y7+vEf^w#)zGhC?A6x?ANAB5S%*pfUEQGqzmk$5fAbi*cG_i*)*`*5v5a1rWIa$3AH^9by=tkDZ3yG zR%PxKiALK~7F zqp*6bjvSyzwziKB$xW*)>9(-uwzd!pDpO5)Ka3t-g0C%b86)yHtKrlU<~9-jrMSdn z2(8u#a9Z#hu(2BMPpthwjJ<0bEPb#g_i;1ow_%xbxf?!-SMtwxsh&lHxulSZLv&=L zvZk+00Udb|e5$Qeqf#@?CqOcOM8Fl!P5j6G01pr=5pUF`XMKzyd`4~{!6}%2D@cL= zLZMBcQ&8mmYY75r2uKAKskUhCKcv_we!XUx<#f~)*wc+!BJN~wlp13ccnb5Z1@n+~E zkX*pO$dN-!tqNt3i;!?&{{oq{cA?w+PNjHRW-IGY4R95FneKuN1Pm78=cxDJiG$T; z$K@?-;FDuJp;X}6@-yEO2Pm$vXKa4U}#HS@C zV2HS~*VoVg5M8=0-Ma8EfjfOvVRm|DX;8>gXNKu9w?vGWQi2c1ZFpb{q+>!cbp?s! zVOC&bd!Zic(waAC=lo2frplm@p;z-~3qDl3APZ&y;V;uFqx`y|kFca>#Qlf@m^_da zc{Dmqi{Ntlbq7DW>|MY;LC>+d{xw=@t0 z(91DW`r#wlY}Dt7ON#XQ4l*xyRq3!CszlNin)8 zI$R94Rh^t5H03Y`U=~1FD!1V6k>8#Qlf?MEfs^1bcK*qHsqYF!R`q>R&* z@0HvhK{q`J=^T1JK5M{31T|>jR0tddAO`*vjJRL9n`PP(YSAoOFYSHQr$9=~>p(o) zhR(~w%C1szB~4<+s8vbpQ)~Vl4**Lx_;EKW<9km)48Rsk#s@KBeoq>>-rIdT?+TIt z-PvegxTyaP>D~Gm;svqoQqzRLr})LEEOjMK%N~EM$Ve~QMB|N!tMV}I49HZFo$MVi zIZJW#N{nWgYJg-zu!>+(0g8s9&ilS%>EI-QH0QzwtaTvC<{FYYN)c}LH}tL6r^_Xo z(Gmnig#D!z5zx#BmBpdtx<)s1b9rNM@`tH15B!Uq|Mpnn(}o6!hX53$;cK6Vxi#*__1wRY z2BHG2dH$e-W^Glmr}L3~blS`(G9Qz@R`|U_zrLqCqV=6KVPIwXu?f%Vg%2B}EyPUW zm~X5MGA?|rfBAC1%96%z_aTVVDv(NOT>K{wLJCkg$qlkIuwwzUzA6RsToGmU$pfb& z;q>Oo4OIY87|Ga3LmbQ07PJag6<=dhrt6(N0NOyzak=&A*JhJ4PUn5HT#2{Od%VG% zfY&)x3il2VZFd{4+2LI>jQF#Aj0px|XNEF>YMSsA_*Sl5foz*p;BkD146EW5(`dZg z3(ydpH6ACuqI!h~0iurH_nULpT%F#2PSceCRJ5LrY^QOxCBtwzx-t`6GN@RJ_v27g zy4y&5D>>Q3d!8IeBxjdOM$&Xy{PC8lD#urCHFxnn48cwATBdqb_88{!j~BhNv9bX< zKiy7f`8GT4{5$axWl^8GL9U0~kX(weRL@4kl2B)y9ACqGE}bYBwUOyph8J08?e>62 ztf7PmIkbR{R=pH`(Mxw$TK3BRY30{G_Mq6lV*V56W()fKFlRGDU7_&Eo zI?7G&k6-C}NCHSicKclYt3eoM%13XB==#31_Z6A|WC8>?SY`1+^eL31Ib~Y^a4E4%$ECx{K0I_C@Uq6_3xhk1Uj^Hc2WAj@ep=1kT+=U^YkIUY4L_WZ z^(vXYrgb#dEx*7*0kr+`ut5%sL5FSll#1fu(G}g{|-@W$R3()}Q z&i!eNZLeDw)0Cx&Qg?md+O|TI6~CFf%r-RW(^JERyEf}40NRY$^mE@X6o7DRybXNn zG(l+A1lSfbZHwjC%MyS)xsTo2>yt~fSrIkCEUUy`Qlt4$f+>NthvWyqJZqY-=ld<apnHF@`qnNh%S1jD#1Mx zsA6y2kml3Zi#I(Jjp>-RXHUe?gW=w&qq1t5DgHkVeYED|`F67a9}h#CHLo{ylFWO# z3|M~HT}l#Hm%_~+^vC$S@rsej_JsUAmQbjjCS>qjciFEgC81I*{P%o1$zP@@{nW=C zfVjB#PTqZ^Whb1!&qFDIcP~sjD-^*byA&uVnc4K~)4#Lhwpe-!GuaCMs$lk=3Y`#{ zbd8E8POEdWtD>D=!FV<Zq`s}B;TpZkAi(xh)bK|@ zHi&@fVWr0s2#m#JYCTi8JZJ}uD@NQ;-d|od zgFi1O7`C*D-~Za>W^2MU&)4P7WTH4v+obOEgo>?DnxQYB!EFO%dNV|zCX+W9XDj`D zyxNUjPX2=nPO}I{?c6mp;GO`2w7$>s3vnN|NxeQ9b(uK*hHNV-v`~`&=5O`mzxmg` z6BBlo{vYD#ft*${uJRgE^GrJvVrxM{o#M@b6wl?6Q;yiW8Jr^&)d~)ZR07fS_wcm=@lodU5+q zn8N4z^QM-P;Q(aPy_c1Zwkt;E+z0&8vWqaD9@>#M7uAU%uIKl&YkA1~>wR+6-rSrv zW0cC-=`(F?@f_F!*L3YInWO1=;!bpi60{x~bu=7C^F5dfk$n^LHM`is;Bm~Sl(?O3 z2D`x#JLI?YqZsna=d%;CR76I=V0jQ+`qFG;-I$R%bF*#B^>F7}2+-KF_4%;%6KJuZ z%Jy()v!HlFQES!1@+M8Bp{_DK2re`xly%sqN{#VW(x**#zo`|qk4`4YzhcAJvVYo( zbcqa~5dvo@@qF?Prkh=8?yz}EG^5Tk>a!hZP4@#flKSh%nKgXrT*Twz=%>mZ7~lDb zMISEI|#*i z?(9xGs_Np1Z!Ca&Xw^}#&`0)1E`Fc8*7C)Ms`+Y58e#y&r`;G5Zyg=~-hhRb0nNN? z;^E>9f!XPZK5~1(xHRJnI!v{0RV2>GAhg7j=~ve3>`+vF1t}*dWa{SH$(IvbHkU}) z2nJ#y=V9Y58F)@O`RTRpj!$}JJMN~*bV8hZUje2*U$SG7PLj~^XZ6jCc%g>D9_U+b@sjL=!eCS5$bQ@O7^mTE*YjY z*c(UnW_$8$2Hd?qg#9Q;xjpW>qZ7J?aAdGfq4E^iT#>x4>AEYHj zJmzs!nV`e&+ILQKY`5JE60h5lI0vVM z7k^4{j%M+_mHJ;L*?&Au%CaWuQ9L!1(zF_phXKYfp@NB)m=a`+5j<1hTTT0oNZ> zHz)q=ITeNOu@U=RA%B~Sd#ORW2#_qiRrhX8+9hH zjK2p!7_VhYchfN&oxAb{x95G^^>Hxp<7`+x8a4C;WHN{KS=chn`W^BtXC&4t<#YV+ zD{UO<3JwBXf+$b<|4 zH9=5sbwbd^9XJ7K_Wn>VLixEc759(Fk?@t}CT-HI*8pRH*5n5)4j~u9$Ttwe1l9_y zN|9F|2^Uk&H9q@u#j(A7Se~$(VLEA15HlrzN28%YHN2VGBuCj{n z$4gNle+drDjaOorYJSiL!h)rv`KBJtuJpV#XJO(r@!$JzWITT zBRTuSAMf71!wDT>8j%zm%Whx$t@cL2-IhGKO>=*2^gR=^=n?HnSlqLWyOS{z4^iqAH0b!T#{nm!;2XX>)X)#Y>eHte4PhZDjj`!F=|Fh}2NOMtb z_imXb%%!j@`3(>TCf{__T)gTTFJU#z@9vBF3oN7qFt_Z5h$28DLKO9wibNVghJyX|83-Xy~P1(u*to^^3qTbw9h={rK zLy5PBOAD86T&8c&?Yk_iDSCT^DL(|g&1}MTaCs8;mb3dm=>lj|N&uGSO|3b8rO!Px z-oGiyO!Y0<0Z*GzB&nIa*o2t)mP8?wCrvXr#nPfI4KbfDQvo2t6|upb0+Pb-aS8k-ZXAYp_cP54x8$3>C%7ov50EE2HP2JLc&=9oMa-1y&+#%!4m%F-qFVX?4rQk?sIV2apa0D!HZ?)4j#PhQJU{b9 z;(8_5+B0*05Fk`}#u=n`|LG*l#bq`piGAY5Wd7-_(D7im!p_bu_oUSKM@IA7b%8@Q zRm!#YtiiMdtG!0V)Q_C4Fi*~3i7y`Tv5v1Ey{(&E`jJO{(`Qda#&?F}+M-9mzgleQ z5=%i$Juuk2^qWJnD&lLaFC#bgOpLbbuq-+^?K@Z?NZ@5qoEnxE{eY`0U~ndl^cWU| zSRK}Qw69hhDf^+&I>H*9vXFtA8`vB|TI9t4B7Hop%KgKyu-96Ioo^F+{PAQQ&D+(~ zT!;BWk6^b8san~-;k52K6us20wTHtzDO&?7V)`rX|E!Ys&rB!u?rM>M@&w+m44eiSaaV)X3EszBv6C zyUoddL*#FC3gw|uG?@~oGGf6`(Ql2JW(KXVm|$uBZ?meILyjVMeSXm!0oXJ_Y(Ti| zST-I0x2+=McJuA}^bBL3r5`$e>1lzrLSuvb2ji=gj>gLrZF5Hr6#idW`4fI*%68}| zNexzFEm>-MHNKBf^=*Abw)YlOmZQh;W}ud0UPUEp@SuR~VjGFGx|+2e*KVZ}tylVX z$!|eMvAPd4kl5j2kWa4XliOP}OP1Op&-l^Px$j8iOPCHs_|p$)^)Qh9&1+@IM*FrV zWcTG4g2IdWFz}~RxF1TrPg&yW!HvR7zKgWnw_(DUjyo+Hnl06oSAmVN5=CH+;a*k` zW@+>&&K`Q~>Z+)Grd9MK<>Os8F4_B*o!|925^_G-@XHv+w>8|H9r1JjS`UOPQ+H5V z-ovE#@5kT0d59V??DsJ@DDi`RpySDK$%#2#Uj^5QRq%B>mNCzt?(K)#u8O>xtb%2C zBZfU`r^Nc!ookO&o%jnHlM=kvyTsY6>Io56#`c1jy<4{1jn+|XnE2XtJlDI3z$DAe z?KP>+Y6I3j;T=}3ml`>n8Wwg&_zd^nh^51m_dDD;@WFd7WXR*2mKzd)3Jt zNw6bmY^OPGuNwP|?T^P9T}kdokm5d^Y<)MoXw%Yk?2d|&os7U1mFeEQId&8;OusoE z&47Eh+NgnpQHG@^`xnoH1=QA_q1$S%+tPIHcQVkvVFaTP3A-j<`xupL`l8XTK64`T zYW;#ZQ@*EO^w{MSYvmuRQl{>~^`n?SPh|C27Uo_*^qy}_m6g(8smr?VDfqKp_wP%| z+MmB*aMeRUGmSQY--)E8`OYK#;%o$2$p8&L`3w!-SG3F;}qn6{e}?& zzTdA#>oCd8e=dYKI=S#ayLh1A(@R%2*EU-k)UIEiEG*xSeeKydj+Bmh`NS>q=O(_; ztG30&tC|#!dD5Q?S9qqC=sS7NXu(NF&NObeliF{j|K1TA(6qejtogA(HJ#%ApNB1} zIeT65cF1#dqmY2jzZH6K6Q$%T1j>C{#j75mcgs$3bhAKkM8wZr|dVvWh0ij7i~X zc#cUeYE6nN_1yzU{;}Pth3Nq;bfqmf7Dlk$Tju<@F*he#{Mny-k1mE|KU||8%%i`P zJ|m+q*fZhHC)r=2*V+FhF3E4q@aq6gYQ1Qdwm74b`?JgxnD5&yPC4$#rLuk|I}3O1cq8$eEg)kz$&{? zU-6P>r$Wips}w{7SXeDIbpokci}0|!}A#e6V0gxX632yBuvkDHFc;F3C5S- zR)~e&eJ1SH-0IZ4R_HChuw|5`wfk{i|n> zs21^w%+&Ir9^Qq%-4t6=?A(#S#r^j9h&{aF1G!|4xf;O(9zpVBSN5#SL@iCDB}r7j z9+u~H+`+H7q`#+M_{6B6_WsS^%}EJr|T{+!F;#94Ir>_ImgaY1yCzj7iiDkg=9Sn zGl<(i+|if52LnBFH&UbtaqHxd zYl=CvIoP7~ot+|6eIx_ph$E3z>ynFNjCqQ!L@DCl{UDqvg zvWtt9f$OUkjCVh6jNjc0U{)1XeJH1Z-q)pk9+Iq|QR1gUhis4qEaB67%J?`jfnfV?7w^LE5-88@*zM$Z<}XVUCiT$a$clAL{!-9R%i z$eq8Kt63M^)1|DBFM8Wt8_v2PPc>9T97I|j%_YlzyRaA;8&*p&Z|Cd1lq3R7#_Al&n)ZO z4+j_|6A0>r@ayc;%}^g2D(x!PH_Hni$TGe(B3am0I?Folp&Yxh+^>D1AYVhYnc ze8)X3MxE1%jeT`G!jm4<8^~LgI&Q+b?DP-uTKf(!NPM@>F|e)S`U&B6f56vsG=$qu zdwhiVWK`!{TcHw|4|Jqv5R_T455_;R=~ANP*s@g9nw8N2esYAHn7a15DqHk_DRK6y zo3ql5WA?E#aiuD>j}TU;7wCIi&pHM=+ctJ?T<_eW;d|OT;KzOXfQ*{+seDgPb9|WR znAL@P2N@;#hXph4h^sZvNxh0W9c58rGNVH?{Jk{}6Dq&n1PMv&TThVx!JBS;MC7G> zCdLsK*U*HVQ;VVik6#@FrD}w`d=XD*s{yB^i)$^cBmLd!aiF^@$@@@>D3SWZd$mzXKf z+dDcX<8Ssp=r7{021)*3abFn~)%&%rl1d6l3qKkpBt#lyNTs`^VL(8-TS6KHqy+?| zhHhz)66r>fp<}2496IK?{eO9$^;^$c?^^GN_nmL|Ix}a^xzBy}z4vwPy)O$xtb)NX zD74hU!72=N(0_AlDphbs;g?QJnUl6Lye%7f?oKIJz~I#LWH#W26LGxyzE7}Dn+&UU zAe@sN`q?Jjf__t_gfY&*fO;ByYR4+`oo(OSN6TMtcCk2vG0RF94&52m-z;^ zNs&@rT@!!x@Om@TM)b8fL1pI)8=@5rDHgFN*IRm%uazK4V#$Qi9rfAv8NSdn*A;Y! z;%(~5yu{D*9%m~9-k>l~L&Pv`lAaHF|`nWv-eTyZ7| zC&_1Zx-+%N1$4^GrK(+LgtGj!?7bMFtfWZ@ikt>{yDL?EQaCrb(1sn_=Rf0X3E}$w z*DvUu7oK?Gypn77iuHa%94S?<*_WD(PdX>s5*K&+&frnSUy0@XuBP{dj4G@g4c`@f z;ayA;pziVd`fjF%GQ(O9)$a8XY>vJ3pEvp>$dGLqbz*Lwa$DLblahUkmUv)(rcz=B zsY#~Hla6G4i9cn3*lv2xk8I53ezv~hbd)TH}$jEz+^mITs zCxMBDvBRi3e0tHSOht<$Uv&?|dLVF4L@cLKZ7sYl5tym&Cluuz2C9p=$6{v9{+XXr z;1Z6?eD#nD??bDnh-gfP`jS~o=-SoNz-|Dyc8V3V=#(+9kBlT~w0x)yfZ526lx!=Dp z*L_fLc>*1BP0<%u(&^@t`ZbPfa~GPTCh$(>mMhbsdgIXHBmK+`qy4JFi^@@03En^R z@pp6h^<$c&X>H&mQtWqWS3^a*Jvedey^>>9czyFy%B__SD-HU)Cf+M;NL&)q^_bNy zmsVIEo@by+Iduwm64lI3pcA)4LX_e^6+gG{rXE>Na3iHLe4%zNT0?Pd+Q@5v~ zKpSZ7EZImiR=&6|CoMEnnb-j-n`_R-Pu{g%ZONNaGG8OINUjH^vEUmK?w40U_#j3y zj9Tl07*8rq`q!$iKb$O`^T+>k{nU4%OcY0QU->olZ>RTQ;eIZN$eW78&vjtlBQiUM zCQiPY;Ql6m)~L)z*?>>)#4Ns<%K^FHysO9iQ%KR>oW zX^9QB@#WSHU+rPv4RzE!HF!3;C`8>_YEtD3UYfS0w5VFtU`D`TvN8;#{%8?M`;8m* z?=s+V0hXAr`P0{Eyg?H~l|fjc*>h4nRiKIYv_Y(WMU!JSSqsze5+UUsa$vfz5D_9j zW9Dql1+)7CR_{)ABIS{QerDiC9&M0S0!3^M(;LDXUjQ@JcNX_&} zZP^LYm55|1_!9ZMfzz4W6mn#26se|4`Z)I=s;Gc<4vy@>$aY?O1#=$iiubb2z5#4y zWLWl%5kDdh%ugsJRp9Sawv~$(e5Tv7uqD8*_Y|WJrR{taBP>iNXMR46 zC2HcEjnF`s<9OJsl0PCkVD|cBh%eB|E?P&W)sZ&IZ9n+hFfP9YfXMlzc|QBR=Nd}- zgZi#o+NBhQ>(Z(*?IS7Rx2zyl zh!8_#1i1~Ar@?B|=75}6hw5PE+wCAr^{?mqs`0VBhnr&0+G}&;_27)upV}_izCv^S zM-G(5Pn1f21rQbOkktNAs^&VhYlFd#4}xy(4R3F^Vw;M0MUB;ZxGN@J$Q$rIcOsv7 z@!_bEXLZUPG`@Ktpkp@_Q+m1Ho?iEwodQEgLs2##KgR*QWp9eG-z&;m&Y_Sy%JKl4 zX-K-m{gTH=`D5&!>m}6UoRYE+iCYgdskuLuB1xLD(Wfo`HF-xt@}1Yd>(A>)tDg7cOU-bH ztgIXbBeYY1E9u}kr*K;ZRCI=;T|b3mkvT1Zf`$vejwT`j*OsW#?!+w5*QnKCnrz&O zKcf$^<8!`gqz{B|1@<4?Millb*rP)%_|17U^wAAf>b3SX7*1_6e>ktGgeRSE zXsX--lJs-{;c`2xde6Asy{#nyV8iTRExF(Sas}jbnBYKYK6{ftdHxiFUB3l$C{1!? zxzsK8lVs3{97h@5ukeWtS(PH(%S%MS6>$^-7j*Uua2HC+oJw?vQ;iTDkQtO%&_8Y- z_-?F|Fld)p$iYA!?6XKaXV*Y`6Vu5uy?^!H^|zj-r;R4S9)Azn^QBihO=)S6Is7!R z;wtTGg%RrMh%lH++3}}z*gGemy_mLYDesqUN_fXafJr?n;9C0-3+p2&nFeMKPeSnNCq{K~UH%O3Zl0^V(Olgk=-2#^+vP*0emk)F^O2>3 z>*OF~gR?w@Be;F5n(wuAt7hG!3OL!(_Q-R86ry zsnHZRskZkS)v<3Y;Gpl&m?ep)f$|lnnXA>r@JtKEd%AB8tXdDo3!VF?r=$SYysU$< z&(*I4{EQfPV6@rLObuF@B0KmUEwK=~`MiXPwRhjnBn@V$mRpDpp9?aM-S@@u%OQWF35=|IllfF+h6&Hs8=IhVWuGW^G@Q`I5iND zH+jN$r4(5zn^Y~;1yYkc&f>=}ztOozLo6()ADPD8|B9l*Zw7wgr^szUF#5{7l*hx5WmgQY(9KMDn?IOc2LTdM^m>8MGBcwMoUH~%D|gm97k zX&eB6!2H?O((3PoAiiCTuxR<7O{bf?9;Vk^R3ZjK?!+28DZQv?E2*9>@j{cA=)iE~ zvWrDtX&K#`&NJ%0aG&`c~3*IPnvwKeA*o7%aMp2b(|2Xpo_x zq);!`_#{ZG`0X7k`_xqq&i)mbrFvK~43-ovPbC_VQwQMVce6b2M?bOgi{?lg`o&4* zc0>D8(?VMtA0T&pqZ^%iTcK3c?YF51ySNOF9?r@UJ~wzvpHI@90;_|11Z#ck=Fgv^ zIRwWfqx#G{MXG{fBnbmivGJ4bXT)29D7<_7#vtCUYBMchXa9@3M!_Py5<7jkv1s%x zhg=gQ`-Ra{X>S5th-8XKjem`$_pC_)mjiCmuVwV|_Pvf(mC?(K8?kXCZd<2G(iRvj zj4cE~!f7no0+&!7gJUq~YpfZePcD2!X zd{EJe??p|-B(xYKZ)tBgb0>~|br=w(j~;`1%KeyW@f%9{tdpV+Vv1ZKWC>#GAflxj z0ryUi4@a}A(;qWC?xSg*&h$|!p4PIEE!M2h4 z(p3Z92rr+<%|rGsGbxtGR{87?c7`?6hk3(3EZ{(bGuX1dPY01 zwSF9Q;w^IfGwNt@T;E_Q*L(4y;4ei38xqu!T{;UTc5&FK=bT0OVkt!Xj0M8EN2>Ie zDitVt;hdazBMV|hKwn)w8R*_s6{6s8=XGZ^+Vbhj20XN4xJ<;giDUXBFK#FWXl>(I z)uHz+Hm%Yz!@=Cqe^6#c_+I_v6mXFR_!XM~tp&5DBSZjNarW4-9`AFxED-d3$&4F! zf$&)~?jQ5wo1IWS%R(C4Ik^9HnTgq`jKdc9&4v~nHw~2{nXld#%5Jz@LsjE z+V?fE&x5i_QKLMJxBt9-+9rRs>qKh1+i`3jd?sbRv`w=skc9xr*2BjnKRn+KXqc+3 z6bTCdX|KJ@9hR>5=UCB>mvURmkHHvf@tk4}Dm)Z3kwF2Kp_40+wi#cB!Tw2k1vn=V zBK}qyDD$Hd_k7=-9EXsEQ>f7_4j;3^G9~XxJcb_jQpt~+bfs<;R#Z|We?8&~ICWtZ zCE!V*X@7R}5W*F<4Cr)a0>b3zv5GTyAR1?5Fdx20CMPZCM*H09#;#V6%euNW{OG;B zVNOtX_gZmOc+sRWO47pTl~aS+(2%*WH)`%ic9Xb`g2mDW?C`)_-wr_H4&1H=XSLfdD6aB*j4igIQ)HaLZz5NVLrV@t&6``4z;E*rOoz!Z>j_Rq~m zN0WZkLn3J?XfYI2k0)&c6QU~N22vbZ5iYhE7=&!Wqi>B~L;JXl(tg zpMviSxNhE?D!3hr!5Qs=_m?lp$VnHlQwr>X*Fpby9)rwbF<5i2(0|6Y+`utdt}cu{ z>}$3o3?k8oW?p-g1+7Z{H9ALbh*d{@cZtDfAkGgE25R z+#T6l)aoGG-Klpz_i<5Wx)RD8JU(n2-6x(TP-jeKM2o=2k5x;Al8w!qCe|6tB(>+_4}N zUqMQKhZ6c^3<(M$G~oPvcIQ4AYpIMBobh{a-rLIY%X#5P1W-@&ATw1Q!c8sUrQ11& zmF8*G55zvZSw{on`{OsUrVly>(x+ADYYs*NUkTlAh7<_6UTOf0C7We5Uf^Wc!D+G1(-6 zM<1>da-hrS2DBhW)mZhlPNB9`2aQT1g`Noym4Rbv21^*`z(&%V^fx9;HyYsv!`F`r z=WC7WcjNS|i{>H(#qf4V_pK_8rTcEY1SVz_rqoO=)|E+^*Ny|y*q{kVE99_MWOCah&|1-|;zd1c?f&;k_< z=Ab6X`Sq$1T^uBLG+JR>h`SUKJ7m|Q_dOgMk}a8;v(&R3HKj~+6%~sEUBuadhAsEq z()!TotyNY8=f8d~c_IuOiT!EOZT9SkvTS66j5842$OP^(@_HhdPhx1}Nt}toelfkp zLeM2sIh>11ypr#QW)0;RP5f-9BJ_SiY_@$da@(cfP&BZe!nI7zIzTZJ;Ojtz5=gff zSuL<8`8Xb@X|D{QnTTeyW0%KvT3qTL<{9afNh3w>g`nU^Y*$aF$tS zvxBe%KXx=^Eg?{K;ptMBfuXE|#@$MthUq!r+B;7rPyF25 zs<$S6(7O$rWw|y#ky0_OUlg$;MP9KavnS$C$cBv0o$|YvBrYG`dF*#eN`Sf5MsG1R z0&)aG0FebKkB%O;^c{MLN>QYW%GmyVbv}UN#tnvTPkbLVRTi5~iSBLmSyhyDXXN5h zH#@NR<`WSHB_s%S97doz0=AFY7Bb@9fgcInd{O<4a+pm|(=AounM02)|6nU$0?&R# zy%)a(F9dljF@)#3`yub^$F4PyG<(GM6!G}F?(M05Yx`Y;N zN78n12`lrk9qhP%1Bw9d?xrqNvzf_#Kb9_NIRnuK<)ipMY>sBZUo<(Uy+4&m1*4}8 z-j6j+E;-)?OEyfQA7rp0&bAFD9|#1DW~UUcmzNhGXc1XF{Vs>BCOy80j8mOB{z2z^ zO3x@Ms4_0}Vy7o{hz!ff@wvf}og$0YyjxvKAS&?J=^o4YtXy?j0!Z>u*8vEN2u!twLHIE{|D@v$dbFP!NWHjoPdqc&N%62_7uBrH!q-sJO?BwuJvv6)C@ru1DBR z*@KFpL&>z{ANExIh&DW-y=&H%P( z#o^a`S09)e`6au@j|5_$KX+@-mq#DXn+2dLk?$D7}H(NQM{m%$dhFCEJaShcV=@n^l=uetl(H=H%53|LOQrI;~ zn_te~m0AnJ!oR}?`k;x6zt1%9G3s1zgq3skz7<-Flq+z*wv%!SyvR}}z&G~wtp{C> zFOj!cRE2VFmka1mFBHaba;)m~rfY7*f|PF?Pbk;V_qns9Y{|lHc@@zsq=0YELyzAV zUGl~eOw0*?J>@zz%*9++OQvALBT@#EBpUC>^u+etF^N(!g2i*Q5rCo>1vv#203!li zdJ>yw-6oAGgZ)d9%#5L23L8R-tEPc(4;6bSsPScGw6-ny$O`V7$}stXwG5g)!{~#8 zRnVvQ`o^k0ZsA|Mp^JBUGhR(}qIo5pI+Xl3IRp#pBUP3zG3;{vKQ!vWznty&Afl^~ zc!Xs_F^^1rGp~)k%o-M~eOAavWuH+KMCX4N$Z$?gOKNY)Syd@3@i}I&m|(|lO#z)b zRM<*@2uJdb3}%b(UrMmiv}4rSQh?N05=3nvT7XG5$JqXpo)aKzDLfQi;5f`q$}v2Q0!$R3^^WJNz?n>tLNWK!xyXwML|=oFl?tPGx>adHnvvnOw16Xc<(#R_ z_^!Az`cW>LE1U=(F2a`OY@39yqr`u?%cfHytu{DXF@1Yl{Jru?8uSI8@Qd{3;IyW; zoKG#(tP1i57Z+>@5$BLpy(Kf4U+~fFC`x&~r(;&x;Pl*GcyZ-0;BII>uf&cGAgJ9% zNpwjM_PE^Vn%y%DbcX|^E_sHBbHa%6goTSj8HPQ@u#9H4&icmGYXg{A{VqvN&Fmhu z&&0YOVOQ(Mv=${<=c38rDM}MV9sT+DA7+~*2t1{j$qMy*Ly)5Od#vl7CF15o4;$iV z&DEj&MUdOE>LWP2JQH39;i=gzn~DV{AFjWW`m0q z8_>lUps(BTCS|i)gTZpH?!8fF@=v`VGo){}=!$Kx`gcuJiSd|Zq1d)r3o3mF#$-!% z*^yNVr8WO3ppTvIdtM$2H2~{gb#dF@7ZSN36)Z5vVZoX4k=lSLjj&DeIk&Mq@x$!%}zuC`JLMB!VU6^!hEj|z3V1g zj3*6I&xsNN`ekdIzW$xEJ%W1MJ3uP$AduDf>S0S`IX2|2B$MiFvS7u*f) z<5E(C`2P-Fo7CdaM4;A~0VbnC24P~tfBeP_X7lm(J$7bp5P={_IgPV$wW&pwDge3n zcllyM7S)5tA3>l985S1?y1igij*P|HKHs1@kAFr?hsP@@3;{_$4(FT5RW8odd+#BN z&bThk>%+>-;=;<+&5we{?ri?1{hK!BD#9WR0&e2f9vj9QMNCk6#DvGt%@9Vs>d9)4 z0l@`sUl{S^Tn3{jz`oG8jJr)07PaIixfyTHqDRmFCfR+sF4*0y3Q Date: Tue, 27 Mar 2018 01:51:15 -0700 Subject: [PATCH 0081/1504] Improve README in slight ways Closes #14. --- README.md | 77 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 59 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index d9e78b34..9e750c25 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,8 @@ Travis-CI Build Status + Current server version + Current plugin version


@@ -16,9 +18,7 @@ It's designed for power users who want to use the **best tools available** for building games, libraries, and plugins. -This is the main Rojo repository, containing the binary and project server component. For the source for the Roblox plugin, [see the rojo-plugin repository](https://github.com/LPGhatguy/rojo-plugin). - -The master branches of both respositories should always pass all tests and be functional, but are not suitable for production use! +This is the main Rojo repository, containing the Rojo CLI. The Roblox Studio plugin is contained in [the rojo-plugin repository](https://github.com/LPGhatguy/rojo-plugin). ## Features @@ -31,13 +31,11 @@ Rojo has a number of desirable features *right now*: Later this year, Rojo will be able to: * Sync rbxmx-format Roblox models bi-directionally between the filesystem and Roblox Studio -* Create installation scripts for libraries to be used in standalone places - * Similar to [rbxpacker](https://github.com/LPGhatguy/rbxpacker), another one of my projects -* Add strongly-versioned dependencies to your project +* Package libraries and plugins into `rbxmx` files from the command line ## Installation Rojo has two components: -* The command line tool, written in Rust +* The command line interface (CLI), written in Rust * The [Roblox Studio plugin](https://www.roblox.com/library/1211549683/Rojo), written in Lua To install the command line tool, there are two options: @@ -71,7 +69,7 @@ The default project looks like this: ``` ### Start Dev Server -To create a server that allows the Rojo Dev Plugin to access your project, use: +To create a server that allows the Rojo Studio plugin to access your project, use: ```sh rojo serve @@ -80,12 +78,14 @@ rojo serve The tool will tell you whether it found an existing project. You should then be able to connect and use the project from within Roblox Studio! ### Migrating an Existing Roblox Project -**Coming soon!** +[Bi-directional script syncing](https://github.com/LPGhatguy/rojo/issues/5) is on the roadmap for Rojo this year, but isn't implemented. + +In the mean-time, manually migrating scripts is probably the best route forward. ### Syncing into Roblox -In order to sync code into Roblox, you'll need to add one or more "partitions" to your configuration. A partition tells Rojo how to map directories to Roblox objects. +In order to sync code into Roblox, you'll need toadd one or more *partitions* to your configuration. A partition tells Rojo how to map directories on your filesystem to Roblox objects. -Each entry in the partitions table has a unique name, a filesystem path, and the full name of the Roblox object to sync into. +Each entry in the `partitions` map has a unique name, a filesystem path, and the full name of the Roblox object to sync into. For example, if you want to map your `src` directory to an object named `My Cool Game` in `ReplicatedStorage`, you could use this configuration: @@ -104,12 +104,14 @@ For example, if you want to map your `src` directory to an object named `My Cool The `path` parameter is relative to the project file. -The `target` parameter is a path to a Roblox object to link the partition to. It starts at `game` and crawls down the tree. If any objects don't exist along the way, they'll be created as `Folder` instances. +The `target` parameter is a path to a Roblox object to link the partition to, starting at `game`. If any objects don't exist along the way, Rojo will try to create them. -Run `rojo serve` in the directory containing this project, then press the "Sync In" or "Toggle Polling" buttons in the Roblox Studio plugin to move code into your game. +**Any objects in a partition may be wiped away by Rojo after syncing! If this is not desired, use multiple, smaller partitions.** + +Run `rojo serve` in the directory containing this project, then press the "Sync In" or "Toggle Polling" buttons in the Roblox Studio plugin to sync into your game. ### Sync Details -The structure of files and folders on the filesystem are preserved when syncing into game. +The structure of files and diectories on the filesystem are preserved when syncing into game. Creation of Roblox instances follows a simple set of rules. The first rule that matches the file name is chosen: @@ -118,10 +120,16 @@ Creation of Roblox instances follows a simple set of rules. The first rule that | `*.server.lua` | `Script` | `Source` will contain the file's contents | | `*.client.lua` | `LocalScript` | `Source` will contain the file's contents | | `*.lua` | `ModuleScript` | `Source` will contain the file's contents | -| `*.model.json` | *Varies* | See [this file](test-project/src/hello.model.json) for an example model | +| `*.model.json` | *Varies* | See the example below | | `*` | `StringValue` | `Value` will contain the file's contents | -Any folders on the filesystem will turn into `Folder` objects unless they contain a file named `init.lua`, `init.server.lua`, or `init.client.lua`. Following the convention of Lua, those objects will instead be whatever the `init` file would turn into. +Any directories on the filesystem will turn into `Folder` objects. + +Any directory containing one of these files will instead be a `ModuleScript`, `Script`, `LocalScript` containing the directory's contents: + +* `init.lua` +* `init.server.lua` +* `init.client.lua` For example, this file tree: @@ -129,15 +137,47 @@ For example, this file tree: * init.client.lua * foo.lua -Will turn into this tree in Roblox: +Will turn into these instances in Roblox: * `my-game` (`LocalScript` with source from `my-game/init.client.lua`) * `foo` (`ModuleScript` with source from `my-game/foo.lua`) +`*.model.json` files are intended as a simple way to represent non-script Roblox instances on the filesystem until `rbxmx` and `rbxlx` support is implemented in Rojo. + +JSON Model files are fairly strict, with every property being required. They generally look like this: + +```json +{ + "Name": "hello", + "ClassName": "Model", + "Children": [ + { + "Name": "Some Part", + "ClassName": "Part", + "Children": [], + "Properties": {} + }, + { + "Name": "Some StringValue", + "ClassName": "StringValue", + "Children": [], + "Properties": { + "Value": { + "Type": "String", + "Value": "Hello, world!" + } + } + } + ], + "Properties": {} +} +``` + ## Inspiration -There are lots of other tools that sync scripts into Roblox, or otherwise work to improve the development flow outside of Roblox Studio. +There are lots of other tools that sync scripts into Roblox or provide other tools for working with Roblox places. Here are a few, if you're looking for alternatives or supplements to Rojo: + * [Studio Bridge by Vocksel](https://github.com/vocksel/studio-bridge) * [RbxRefresh by Osyris](https://github.com/osyrisrblx/RbxRefresh) * [RbxSync by evaera](https://github.com/evaera/RbxSync) @@ -145,6 +185,7 @@ Here are a few, if you're looking for alternatives or supplements to Rojo: * [rbxmk by Anaminus](https://github.com/anaminus/rbxmk) I also have a couple tools that Rojo intends to replace: + * [rbxfs](https://github.com/LPGhatguy/rbxfs), which has been deprecated by Rojo * [rbxpacker](https://github.com/LPGhatguy/rbxpacker), which is still useful From c8f837d7263f01a027cd4c7d597d3a7a02d96fc0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 1 Apr 2018 21:23:22 -0700 Subject: [PATCH 0082/1504] Add dates to each release in CHANGELOG --- CHANGES.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5c64592a..9a1113d8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,7 +3,7 @@ ## Current Master *No changes* -## 0.4.0 +## 0.4.0 (March 27, 2018) * Protocol version 1, which shifts more responsibility onto the server * This is a **major breaking** change! * The server now has a content of 'filter plugins', which transform data at various stages in the pipeline @@ -11,36 +11,36 @@ * Added `*.model.json` files, which let you embed small Roblox objects into your Rojo tree. * Improved error messages in some cases ([#46](https://github.com/LPGhatguy/rojo/issues/46)) -## 0.3.2 +## 0.3.2 (December 20, 2017) * Fixed `rojo serve` failing to correctly construct an absolute root path when passed as an argument * Fixed intense CPU usage when running `rojo serve` -## 0.3.1 +## 0.3.1 (December 14, 2017) * Improved error reporting when invalid JSON is found in a `rojo.json` project * These messages are passed on from Serde -## 0.3.0 +## 0.3.0 (December 12, 2017) * Factored out the plugin into a separate repository * Fixed server when using a file as a partition * Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory! * Started running automatic tests on Travis CI (#9) -## 0.2.3 +## 0.2.3 (December 4, 2017) * Plugin only release * Tightened `init` file rules to only match script files * Previously, Rojo would sometimes pick up the wrong file when syncing -## 0.2.2 +## 0.2.2 (December 1, 2017) * Plugin only release * Fixed broken reconciliation behavior with `init` files -## 0.2.1 +## 0.2.1 (December 1, 2017) * Plugin only release * Changes default port to 8000 -## 0.2.0 +## 0.2.0 (December 1, 2017) * Support for `init.lua` like rbxfs and rbxpacker * More robust syncing with a new reconciler -## 0.1.0 +## 0.1.0 (November 29, 2017) * Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) \ No newline at end of file From 6fa925a402d7bebf74aaa0dca63394264b0d62db Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 1 Apr 2018 23:22:04 -0700 Subject: [PATCH 0083/1504] Merge plugin back into main repository (#49) --- .editorconfig | 6 - .gitmodules | 15 + .travis.yml | 42 ++- CHANGES.md | 3 +- README.md | 57 ++-- plugin/.editorconfig | 4 + plugin/.gitignore | 1 + plugin/.luacheckrc | 56 ++++ plugin/.luacov | 8 + plugin/modules/lemur | 1 + plugin/modules/roact | 1 + plugin/modules/roact-rodux | 1 + plugin/modules/rodux | 1 + plugin/modules/testez | 1 + plugin/rojo.json | 30 ++ plugin/spec.lua | 69 ++++ plugin/src/Config.lua | 7 + plugin/src/Config.spec.lua | 7 + plugin/src/Http.lua | 67 ++++ plugin/src/HttpError.lua | 57 ++++ plugin/src/HttpResponse.lua | 20 ++ plugin/src/Main.server.lua | 79 +++++ plugin/src/Plugin.lua | 198 +++++++++++ plugin/src/Promise.lua | 311 ++++++++++++++++++ plugin/src/Promise.spec.lua | 262 +++++++++++++++ plugin/src/Reconciler.lua | 203 ++++++++++++ plugin/src/RouteMap.lua | 103 ++++++ plugin/src/Server.lua | 89 +++++ plugin/src/Version.lua | 40 +++ plugin/src/Version.spec.lua | 28 ++ plugin/src/runTests.lua | 4 + plugin/tests/runTests.server.lua | 2 + server/.editorconfig | 5 + .gitignore => server/.gitignore | 0 Cargo.lock => server/Cargo.lock | 0 Cargo.toml => server/Cargo.toml | 0 rustfmt.toml => server/rustfmt.toml | 0 {src => server/src}/bin.rs | 0 {src => server/src}/commands/init.rs | 0 {src => server/src}/commands/mod.rs | 0 {src => server/src}/commands/serve.rs | 0 {src => server/src}/core.rs | 0 {src => server/src}/pathext.rs | 0 {src => server/src}/plugin.rs | 0 {src => server/src}/plugins/default_plugin.rs | 0 .../src}/plugins/json_model_plugin.rs | 0 {src => server/src}/plugins/mod.rs | 0 {src => server/src}/plugins/script_plugin.rs | 0 {src => server/src}/project.rs | 0 {src => server/src}/rbx.rs | 0 {src => server/src}/vfs/mod.rs | 0 {src => server/src}/vfs/vfs_item.rs | 0 {src => server/src}/vfs/vfs_session.rs | 0 {src => server/src}/vfs/vfs_watcher.rs | 0 {src => server/src}/web.rs | 0 55 files changed, 1742 insertions(+), 36 deletions(-) create mode 100644 .gitmodules create mode 100644 plugin/.editorconfig create mode 100644 plugin/.gitignore create mode 100644 plugin/.luacheckrc create mode 100644 plugin/.luacov create mode 160000 plugin/modules/lemur create mode 160000 plugin/modules/roact create mode 160000 plugin/modules/roact-rodux create mode 160000 plugin/modules/rodux create mode 160000 plugin/modules/testez create mode 100644 plugin/rojo.json create mode 100644 plugin/spec.lua create mode 100644 plugin/src/Config.lua create mode 100644 plugin/src/Config.spec.lua create mode 100644 plugin/src/Http.lua create mode 100644 plugin/src/HttpError.lua create mode 100644 plugin/src/HttpResponse.lua create mode 100644 plugin/src/Main.server.lua create mode 100644 plugin/src/Plugin.lua create mode 100644 plugin/src/Promise.lua create mode 100644 plugin/src/Promise.spec.lua create mode 100644 plugin/src/Reconciler.lua create mode 100644 plugin/src/RouteMap.lua create mode 100644 plugin/src/Server.lua create mode 100644 plugin/src/Version.lua create mode 100644 plugin/src/Version.spec.lua create mode 100644 plugin/src/runTests.lua create mode 100644 plugin/tests/runTests.server.lua create mode 100644 server/.editorconfig rename .gitignore => server/.gitignore (100%) rename Cargo.lock => server/Cargo.lock (100%) rename Cargo.toml => server/Cargo.toml (100%) rename rustfmt.toml => server/rustfmt.toml (100%) rename {src => server/src}/bin.rs (100%) rename {src => server/src}/commands/init.rs (100%) rename {src => server/src}/commands/mod.rs (100%) rename {src => server/src}/commands/serve.rs (100%) rename {src => server/src}/core.rs (100%) rename {src => server/src}/pathext.rs (100%) rename {src => server/src}/plugin.rs (100%) rename {src => server/src}/plugins/default_plugin.rs (100%) rename {src => server/src}/plugins/json_model_plugin.rs (100%) rename {src => server/src}/plugins/mod.rs (100%) rename {src => server/src}/plugins/script_plugin.rs (100%) rename {src => server/src}/project.rs (100%) rename {src => server/src}/rbx.rs (100%) rename {src => server/src}/vfs/mod.rs (100%) rename {src => server/src}/vfs/vfs_item.rs (100%) rename {src => server/src}/vfs/vfs_session.rs (100%) rename {src => server/src}/vfs/vfs_watcher.rs (100%) rename {src => server/src}/web.rs (100%) diff --git a/.editorconfig b/.editorconfig index c2c2496b..263d65f2 100644 --- a/.editorconfig +++ b/.editorconfig @@ -4,12 +4,6 @@ root = true end_of_line = lf charset = utf-8 -[*.rs] -indent_style = space -indent_size = 4 -trim_trailing_whitespace = true -insert_final_newline = true - [*.json] indent_style = space indent_size = 2 diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..4d521fd8 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,15 @@ +[submodule "plugin/modules/roact"] + path = plugin/modules/roact + url = https://github.com/Roblox/roact.git +[submodule "plugin/modules/rodux"] + path = plugin/modules/rodux + url = https://github.com/Roblox/rodux.git +[submodule "plugin/modules/roact-rodux"] + path = plugin/modules/roact-rodux + url = https://github.com/Roblox/roact-rodux.git +[submodule "plugin/modules/testez"] + path = plugin/modules/testez + url = https://github.com/Roblox/testez.git +[submodule "plugin/modules/lemur"] + path = plugin/modules/lemur + url = https://github.com/LPGhatguy/lemur.git diff --git a/.travis.yml b/.travis.yml index 2657bd4d..b83c1564 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,39 @@ -language: rust +matrix: + include: + - language: python + env: + - LUA="lua=5.1" -rust: - - stable - - beta \ No newline at end of file + before_install: + - pip install hererocks + - hererocks lua_install -r^ --$LUA + - export PATH=$PATH:$PWD/lua_install/bin + + install: + - luarocks install luafilesystem + - luarocks install busted + - luarocks install luacov + - luarocks install luacov-coveralls + - luarocks install luacheck + + script: + - cd plugin + - luacheck src + - lua -lluacov spec.lua + + after_success: + - cd plugin + - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install + + - language: rust + rust: stable + + script: + - cd server + - cargo test --verbose + - language: rust + rust: beta + + script: + - cd server + - cargo test --verbose diff --git a/CHANGES.md b/CHANGES.md index 9a1113d8..19a6cf7b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,8 @@ # Rojo Change Log ## Current Master -*No changes* +* Merged plugin repository into main Rojo repository for easier tracking +* Improved `RouteMap` object tracking; this should fix some cases of duplicated instances being synced into the tree. ## 0.4.0 (March 27, 2018) * Protocol version 1, which shifts more responsibility onto the server diff --git a/README.md b/README.md index 9e750c25..6137b612 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@
- Rojo + Rojo
 
@@ -14,15 +14,12 @@
-**Rojo** is a flexible multi-tool designed for creating robust Roblox projects. It's in early development, but is still useful for many projects. +**Rojo** is a flexible multi-tool designed for creating robust Roblox projects. It's designed for power users who want to use the **best tools available** for building games, libraries, and plugins. -This is the main Rojo repository, containing the Rojo CLI. The Roblox Studio plugin is contained in [the rojo-plugin repository](https://github.com/LPGhatguy/rojo-plugin). - ## Features - -Rojo has a number of desirable features *right now*: +Rojo lets you: * Work on scripts from the filesystem, in your favorite editor * Version your place, library, or plugin using Git or another VCS @@ -30,24 +27,34 @@ Rojo has a number of desirable features *right now*: Later this year, Rojo will be able to: -* Sync rbxmx-format Roblox models bi-directionally between the filesystem and Roblox Studio -* Package libraries and plugins into `rbxmx` files from the command line +* Sync `rbxmx` models between the filesystem and Roblox Studio +* Package projects into `rbxmx` files from the command line ## Installation Rojo has two components: -* The command line interface (CLI), written in Rust -* The [Roblox Studio plugin](https://www.roblox.com/library/1211549683/Rojo), written in Lua -To install the command line tool, there are two options: -* Cargo, if you have Rust installed - * Use `cargo install rojo` -- Rojo will be available with the `rojo` command -* Download a pre-built Windows binary from [the GitHub releases page](https://github.com/LPGhatguy/rojo/releases) +* The server, a binary written in Rust +* The plugin, a Roblox Studio plugin written in Lua -## Usage +It's important that the plugin and server are compatible. The plugin will show errors in the Roblox Studio Output window if there is a version mismatch. + +To install the server, either: + +* If you have Rust installed, use `cargo install rojo` +* Or, download a pre-built Windows binary from [the GitHub releases page](https://github.com/LPGhatguy/rojo/releases) + +To install the plugin, either: + +* Install the plugin from the [Roblox plugin page](https://www.roblox.com/library/1211549683/Rojo). + * This gives you less control over what version you install -- you will always have the latest version. +* Or, download the latest release from [the GitHub releases section](https://github.com/LPGhatguy/rojo/releases) and install it into your Roblox plugins folder + * You can open this folder by clicking the "Plugins Folder" button from the Plugins toolbar in Roblox Studio + +## Server Usage For more help, use `rojo help`. ### New Project -Just create a new folder and tell Rojo to initialize it! +Create a new folder, then use `rojo init` inside that folder to initialize an empty project: ```sh mkdir my-new-project @@ -56,9 +63,9 @@ cd my-new-project rojo init ``` -Rojo will create an empty project in the directory. +Rojo will create an empty project file named `rojo.json` in the directory. -The default project looks like this: +The default project file is: ```json { @@ -69,7 +76,7 @@ The default project looks like this: ``` ### Start Dev Server -To create a server that allows the Rojo Studio plugin to access your project, use: +To start the Rojo dev server, use: ```sh rojo serve @@ -83,7 +90,7 @@ The tool will tell you whether it found an existing project. You should then be In the mean-time, manually migrating scripts is probably the best route forward. ### Syncing into Roblox -In order to sync code into Roblox, you'll need toadd one or more *partitions* to your configuration. A partition tells Rojo how to map directories on your filesystem to Roblox objects. +In order to sync code into Roblox, you'll need to add one or more *partitions* to your configuration. A partition tells Rojo how to map directories on your filesystem to Roblox objects. Each entry in the `partitions` map has a unique name, a filesystem path, and the full name of the Roblox object to sync into. @@ -142,9 +149,11 @@ Will turn into these instances in Roblox: * `my-game` (`LocalScript` with source from `my-game/init.client.lua`) * `foo` (`ModuleScript` with source from `my-game/foo.lua`) -`*.model.json` files are intended as a simple way to represent non-script Roblox instances on the filesystem until `rbxmx` and `rbxlx` support is implemented in Rojo. +`*.model.json` files are a way to represent simple Roblox instances on the filesystem until `rbxmx` and `rbxlx` support is implemented in Rojo. -JSON Model files are fairly strict, with every property being required. They generally look like this: +This feature is intended for small instances, like `RemoteEvent` or `*Value` objects. + +JSON Model files are strict, with every property being required. They look like this: ```json { @@ -192,9 +201,7 @@ I also have a couple tools that Rojo intends to replace: ## Contributing Pull requests are welcome! -The `master` branch of both repositories have tests running on Travis for every commit and pull request. The test suite on `master` should always pass! - -The Rojo and Rojo Plugin repositories should stay in sync with eachother, so that the current `master` of each repository can be used together. +All pull requests are run against a test suite on Travis CI. That test suite should always pass! ## License Rojo is available under the terms of the MIT license. See [LICENSE.md](LICENSE.md) for details. \ No newline at end of file diff --git a/plugin/.editorconfig b/plugin/.editorconfig new file mode 100644 index 00000000..da77c5d6 --- /dev/null +++ b/plugin/.editorconfig @@ -0,0 +1,4 @@ +[*.lua] +indent_style = tab +trim_trailing_whitespace = true +insert_final_newline = true \ No newline at end of file diff --git a/plugin/.gitignore b/plugin/.gitignore new file mode 100644 index 00000000..92b37c63 --- /dev/null +++ b/plugin/.gitignore @@ -0,0 +1 @@ +/luacov.* \ No newline at end of file diff --git a/plugin/.luacheckrc b/plugin/.luacheckrc new file mode 100644 index 00000000..5e011987 --- /dev/null +++ b/plugin/.luacheckrc @@ -0,0 +1,56 @@ +stds.roblox = { + read_globals = { + game = { + other_fields = true, + }, + + -- Roblox globals + "script", + + -- Extra functions + "tick", "warn", "spawn", + "wait", "settings", "typeof", + + -- Types + "Vector2", "Vector3", + "Color3", + "UDim", "UDim2", + "Rect", + "CFrame", + "Enum", + "Instance", + } +} + +stds.plugin = { + read_globals = { + "plugin", + } +} + +stds.testez = { + read_globals = { + "describe", + "it", "itFOCUS", "itSKIP", + "FOCUS", "SKIP", "HACK_NO_XPCALL", + "expect", + } +} + +ignore = { + "212", -- unused arguments + "421", -- shadowing local variable + "422", -- shadowing argument + "431", -- shadowing upvalue + "432", -- shadowing upvalue argument +} + +std = "lua51+roblox" + +files["**/*.server.lua"] = { + std = "+plugin", +} + +files["**/*.spec.lua"] = { + std = "+testez", +} \ No newline at end of file diff --git a/plugin/.luacov b/plugin/.luacov new file mode 100644 index 00000000..996d3cc0 --- /dev/null +++ b/plugin/.luacov @@ -0,0 +1,8 @@ +return { + include = { + "^src", + }, + exclude = { + "%.spec$", + }, +} \ No newline at end of file diff --git a/plugin/modules/lemur b/plugin/modules/lemur new file mode 160000 index 00000000..852c71b8 --- /dev/null +++ b/plugin/modules/lemur @@ -0,0 +1 @@ +Subproject commit 852c71b897ff346f6a76796a418b9da4255d04b1 diff --git a/plugin/modules/roact b/plugin/modules/roact new file mode 160000 index 00000000..bbb06631 --- /dev/null +++ b/plugin/modules/roact @@ -0,0 +1 @@ +Subproject commit bbb066316149f9b56fdf7718d48bcded7288d86f diff --git a/plugin/modules/roact-rodux b/plugin/modules/roact-rodux new file mode 160000 index 00000000..97fbfee9 --- /dev/null +++ b/plugin/modules/roact-rodux @@ -0,0 +1 @@ +Subproject commit 97fbfee90af6abaa2118c9abd4532210793c26dc diff --git a/plugin/modules/rodux b/plugin/modules/rodux new file mode 160000 index 00000000..b8ba4863 --- /dev/null +++ b/plugin/modules/rodux @@ -0,0 +1 @@ +Subproject commit b8ba4863359f3a05ac5a8f1993d02b5410e5e718 diff --git a/plugin/modules/testez b/plugin/modules/testez new file mode 160000 index 00000000..442b7192 --- /dev/null +++ b/plugin/modules/testez @@ -0,0 +1 @@ +Subproject commit 442b71926d4e9bd9933bbdd87d95679062723dad diff --git a/plugin/rojo.json b/plugin/rojo.json new file mode 100644 index 00000000..c1cbdb8c --- /dev/null +++ b/plugin/rojo.json @@ -0,0 +1,30 @@ +{ + "name": "rojo", + "servePort": 8000, + "partitions": { + "plugin": { + "path": "src", + "target": "ReplicatedStorage.Rojo.plugin" + }, + "modules/roact": { + "path": "modules/roact/lib", + "target": "ReplicatedStorage.Rojo.modules.Roact" + }, + "modules/rodux": { + "path": "modules/rodux/lib", + "target": "ReplicatedStorage.Rojo.modules.Rodux" + }, + "modules/roact-rodux": { + "path": "modules/roact-rodux/lib", + "target": "ReplicatedStorage.Rojo.modules.RoactRodux" + }, + "modules/testez": { + "path": "modules/testez/lib", + "target": "ReplicatedStorage.TestEZ" + }, + "tests": { + "path": "tests", + "target": "TestService" + } + } +} \ No newline at end of file diff --git a/plugin/spec.lua b/plugin/spec.lua new file mode 100644 index 00000000..02325bdd --- /dev/null +++ b/plugin/spec.lua @@ -0,0 +1,69 @@ +--[[ + Loads our library and all of its dependencies, then runs tests using TestEZ. +]] + +-- If you add any dependencies, add them to this table so they'll be loaded! +local LOAD_MODULES = { + {"src", "Plugin"}, + {"modules/testez/lib", "TestEZ"}, +} + +-- This makes sure we can load Lemur and other libraries that depend on init.lua +package.path = package.path .. ";?/init.lua" + +-- If this fails, make sure you've run `lua bin/install-dependencies.lua` first! +local lemur = require("modules.lemur") + +--[[ + Collapses ModuleScripts named 'init' into their parent folders. + + This is the same result as the collapsing mechanism from Rojo. +]] +local function collapse(root) + local init = root:FindFirstChild("init") + if init then + init.Name = root.Name + init.Parent = root.Parent + + for _, child in ipairs(root:GetChildren()) do + child.Parent = init + end + + root:Destroy() + root = init + end + + for _, child in ipairs(root:GetChildren()) do + if child:IsA("Folder") then + collapse(child) + end + end + + return root +end + +-- Create a virtual Roblox tree +local habitat = lemur.Habitat.new() + +-- We'll put all of our library code and dependencies here +local Root = lemur.Instance.new("Folder") +Root.Name = "Root" + +-- Load all of the modules specified above +for _, module in ipairs(LOAD_MODULES) do + local container = lemur.Instance.new("Folder", Root) + container.Name = module[2] + habitat:loadFromFs(module[1], container) +end + +collapse(Root) + +-- Load TestEZ and run our tests +local TestEZ = habitat:require(Root.TestEZ) + +local results = TestEZ.TestBootstrap:run(Root.Plugin, TestEZ.Reporters.TextReporter) + +-- Did something go wrong? +if results.failureCount > 0 then + os.exit(1) +end diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua new file mode 100644 index 00000000..b4bfa3be --- /dev/null +++ b/plugin/src/Config.lua @@ -0,0 +1,7 @@ +return { + pollingRate = 0.2, + version = {0, 4, 1}, + expectedServerVersionString = "0.4.x", + protocolVersion = 1, + dev = false, +} diff --git a/plugin/src/Config.spec.lua b/plugin/src/Config.spec.lua new file mode 100644 index 00000000..ce9b43fd --- /dev/null +++ b/plugin/src/Config.spec.lua @@ -0,0 +1,7 @@ +return function() + local Config = require(script.Parent.Config) + + it("should have 'dev' disabled", function() + expect(Config.dev).to.equal(false) + end) +end diff --git a/plugin/src/Http.lua b/plugin/src/Http.lua new file mode 100644 index 00000000..98997b9f --- /dev/null +++ b/plugin/src/Http.lua @@ -0,0 +1,67 @@ +local HttpService = game:GetService("HttpService") + +local HTTP_DEBUG = false + +local Promise = require(script.Parent.Promise) +local HttpError = require(script.Parent.HttpError) +local HttpResponse = require(script.Parent.HttpResponse) + +local function dprint(...) + if HTTP_DEBUG then + print(...) + end +end + +local Http = {} +Http.__index = Http + +function Http.new(baseUrl) + assert(type(baseUrl) == "string", "Http.new needs a baseUrl!") + + local http = { + baseUrl = baseUrl + } + + setmetatable(http, Http) + + return http +end + +function Http:get(endpoint) + dprint("\nGET", endpoint) + return Promise.new(function(resolve, reject) + spawn(function() + local ok, result = pcall(function() + return HttpService:GetAsync(self.baseUrl .. endpoint, true) + end) + + if ok then + dprint("\t", result, "\n") + resolve(HttpResponse.new(result)) + else + reject(HttpError.fromErrorString(result)) + end + end) + end) +end + +function Http:post(endpoint, body) + dprint("\nPOST", endpoint) + dprint(body) + return Promise.new(function(resolve, reject) + spawn(function() + local ok, result = pcall(function() + return HttpService:PostAsync(self.baseUrl .. endpoint, body) + end) + + if ok then + dprint("\t", result, "\n") + resolve(HttpResponse.new(result)) + else + reject(HttpError.fromErrorString(result)) + end + end) + end) +end + +return Http diff --git a/plugin/src/HttpError.lua b/plugin/src/HttpError.lua new file mode 100644 index 00000000..9da4b946 --- /dev/null +++ b/plugin/src/HttpError.lua @@ -0,0 +1,57 @@ +local HttpError = {} +HttpError.__index = HttpError + +HttpError.Error = { + HttpNotEnabled = { + message = "Rojo requires HTTP access, which is not enabled.\n" .. + "Check your game settings, located in the 'Home' tab of Studio.", + }, + ConnectFailed = { + message = "Rojo plugin couldn't connect to the Rojo server.\n" .. + "Make sure the server is running -- use 'Rojo serve' to run it!", + }, + Unknown = { + message = "Rojo encountered an unknown error: {{message}}", + }, +} + +function HttpError.new(type, extraMessage) + extraMessage = extraMessage or "" + local message = type.message:gsub("{{message}}", extraMessage) + + local err = { + type = type, + message = message, + } + + setmetatable(err, HttpError) + + return err +end + +function HttpError:__tostring() + return self.message +end + +--[[ + This method shouldn't have to exist. Ugh. +]] +function HttpError.fromErrorString(err) + err = err:lower() + + if err:find("^http requests are not enabled") then + return HttpError.new(HttpError.Error.HttpNotEnabled) + end + + if err:find("^curl error") then + return HttpError.new(HttpError.Error.ConnectFailed) + end + + return HttpError.new(HttpError.Error.Unknown, err) +end + +function HttpError:report() + warn(self.message) +end + +return HttpError diff --git a/plugin/src/HttpResponse.lua b/plugin/src/HttpResponse.lua new file mode 100644 index 00000000..0b85db94 --- /dev/null +++ b/plugin/src/HttpResponse.lua @@ -0,0 +1,20 @@ +local HttpService = game:GetService("HttpService") + +local HttpResponse = {} +HttpResponse.__index = HttpResponse + +function HttpResponse.new(body) + local response = { + body = body, + } + + setmetatable(response, HttpResponse) + + return response +end + +function HttpResponse:json() + return HttpService:JSONDecode(self.body) +end + +return HttpResponse diff --git a/plugin/src/Main.server.lua b/plugin/src/Main.server.lua new file mode 100644 index 00000000..062dc414 --- /dev/null +++ b/plugin/src/Main.server.lua @@ -0,0 +1,79 @@ +if not plugin then + return +end + +local Plugin = require(script.Parent.Plugin) +local Config = require(script.Parent.Config) +local Version = require(script.Parent.Version) + +--[[ + Check if the user is using a newer version of Rojo than last time. If they + are, show them a reminder to make sure they check their server version. +]] +local function checkUpgrade() + local lastVersion = plugin:GetSetting("LastRojoVersion") + + if lastVersion then + local wasUpgraded = Version.compare(Config.version, lastVersion) == 1 + + if wasUpgraded then + local message = ( + "\nRojo detected an upgrade from version %s to version %s." .. + "\nMake sure you have also upgraded your server!" .. + "\n\nRojo version %s is intended for use with server version %s.\n" + ):format( + Version.display(lastVersion), Version.display(Config.version), + Version.display(Config.version), Config.expectedServerVersionString + ) + + print(message) + end + end + + -- When developing Rojo, there's no use in storing that version number. + if not Config.dev then + plugin:SetSetting("LastRojoVersion", Config.version) + end +end + +local function main() + local pluginInstance = Plugin.new() + + local displayedVersion = Config.dev and "DEV" or Version.display(Config.version) + + local toolbar = plugin:CreateToolbar("Rojo Plugin " .. displayedVersion) + + toolbar:CreateButton("Test Connection", "Connect to Rojo Server", "") + .Click:Connect(function() + checkUpgrade() + + pluginInstance:connect() + :catch(function(err) + warn(err) + end) + end) + + toolbar:CreateButton("Sync In", "Sync into Roblox Studio", "") + .Click:Connect(function() + checkUpgrade() + + pluginInstance:syncIn() + :catch(function(err) + warn(err) + end) + end) + + toolbar:CreateButton("Toggle Polling", "Poll server for changes", "") + .Click:Connect(function() + checkUpgrade() + + spawn(function() + pluginInstance:togglePolling() + :catch(function(err) + warn(err) + end) + end) + end) +end + +main() diff --git a/plugin/src/Plugin.lua b/plugin/src/Plugin.lua new file mode 100644 index 00000000..92cdbd4b --- /dev/null +++ b/plugin/src/Plugin.lua @@ -0,0 +1,198 @@ +local Config = require(script.Parent.Config) +local Http = require(script.Parent.Http) +local Server = require(script.Parent.Server) +local Promise = require(script.Parent.Promise) +local Reconciler = require(script.Parent.Reconciler) + +local function collectMatch(source, pattern) + local result = {} + + for match in source:gmatch(pattern) do + table.insert(result, match) + end + + return result +end + +local Plugin = {} +Plugin.__index = Plugin + +function Plugin.new() + local address = "localhost" + local port = Config.dev and 8001 or 8000 + + local remote = ("http://%s:%d"):format(address, port) + + local self = { + _http = Http.new(remote), + _reconciler = Reconciler.new(), + _server = nil, + _polling = false, + } + + setmetatable(self, Plugin) + + do + local screenGui = Instance.new("ScreenGui") + screenGui.Name = "Rojo UI" + screenGui.Parent = game.CoreGui + screenGui.DisplayOrder = -1 + screenGui.Enabled = false + + local label = Instance.new("TextLabel") + label.Font = Enum.Font.SourceSans + label.TextSize = 20 + label.Text = "Rojo polling..." + label.BackgroundColor3 = Color3.fromRGB(31, 31, 31) + label.BackgroundTransparency = 0.5 + label.BorderSizePixel = 0 + label.TextColor3 = Color3.new(1, 1, 1) + label.Size = UDim2.new(0, 120, 0, 28) + label.Position = UDim2.new(0, 0, 0, 0) + label.Parent = screenGui + + self._label = screenGui + end + + return self +end + +function Plugin:server() + if not self._server then + self._server = Server.connect(self._http) + :catch(function(err) + self._server = nil + return Promise.reject(err) + end) + end + + return self._server +end + +function Plugin:connect() + print("Testing connection...") + + return self:server() + :andThen(function(server) + return server:getInfo() + end) + :andThen(function(result) + print("Server found!") + print("Protocol version:", result.protocolVersion) + print("Server version:", result.serverVersion) + end) +end + +function Plugin:togglePolling() + if self._polling then + self:stopPolling() + + return Promise.resolve(nil) + else + return self:startPolling() + end +end + +function Plugin:stopPolling() + if not self._polling then + return + end + + print("Stopped polling.") + + self._polling = false + self._label.Enabled = false +end + +function Plugin:_pull(server, project, routes) + local items = server:read(routes):await() + + for index = 1, #routes do + local itemRoute = routes[index] + local partitionName = itemRoute[1] + local partition = project.partitions[partitionName] + local item = items[index] + + local partitionRoute = collectMatch(partition.target, "[^.]+") + + -- If the item route's length was 1, we need to rename the instance to + -- line up with the partition's root object name. + -- + -- This is a HACK! + if #itemRoute == 1 then + if item then + local objectName = partition.target:match("[^.]+$") + item.Name = objectName + end + end + + local fullRoute = {} + for _, piece in ipairs(partitionRoute) do + table.insert(fullRoute, piece) + end + + for i = 2, #itemRoute do + table.insert(fullRoute, itemRoute[i]) + end + + self._reconciler:reconcileRoute(fullRoute, item, itemRoute) + end +end + +function Plugin:startPolling() + if self._polling then + return + end + + print("Starting to poll...") + + self._polling = true + self._label.Enabled = true + + return self:server() + :andThen(function(server) + self:syncIn():await() + + local project = server:getInfo():await().project + + while self._polling do + local changes = server:getChanges():await() + + if #changes > 0 then + local routes = {} + + for _, change in ipairs(changes) do + table.insert(routes, change.route) + end + + self:_pull(server, project, routes) + end + + wait(Config.pollingRate) + end + end) + :catch(function() + self:stopPolling() + end) +end + +function Plugin:syncIn() + print("Syncing from server...") + + return self:server() + :andThen(function(server) + local project = server:getInfo():await().project + + local routes = {} + + for name in pairs(project.partitions) do + table.insert(routes, {name}) + end + + self:_pull(server, project, routes) + + print("Sync successful!") + end) +end + +return Plugin diff --git a/plugin/src/Promise.lua b/plugin/src/Promise.lua new file mode 100644 index 00000000..cdcea791 --- /dev/null +++ b/plugin/src/Promise.lua @@ -0,0 +1,311 @@ +--[[ + An implementation of Promises similar to Promise/A+. +]] + +local PROMISE_DEBUG = false + +-- If promise debugging is on, use a version of pcall that warns on failure. +-- This is useful for finding errors that happen within Promise itself. +local wpcall +if PROMISE_DEBUG then + wpcall = function(f, ...) + local result = { pcall(f, ...) } + + if not result[1] then + warn(result[2]) + end + + return unpack(result) + end +else + wpcall = pcall +end + +--[[ + Creates a function that invokes a callback with correct error handling and + resolution mechanisms. +]] +local function createAdvancer(callback, resolve, reject) + return function(...) + local result = { wpcall(callback, ...) } + local ok = table.remove(result, 1) + + if ok then + resolve(unpack(result)) + else + reject(unpack(result)) + end + end +end + +local function isEmpty(t) + return next(t) == nil +end + +local Promise = {} +Promise.__index = Promise + +Promise.Status = { + Started = "Started", + Resolved = "Resolved", + Rejected = "Rejected", +} + +--[[ + Constructs a new Promise with the given initializing callback. + + This is generally only called when directly wrapping a non-promise API into + a promise-based version. + + The callback will receive 'resolve' and 'reject' methods, used to start + invoking the promise chain. + + For example: + + local function get(url) + return Promise.new(function(resolve, reject) + spawn(function() + resolve(HttpService:GetAsync(url)) + end) + end) + end + + get("https://google.com") + :andThen(function(stuff) + print("Got some stuff!", stuff) + end) +]] +function Promise.new(callback) + local promise = { + -- Used to locate where a promise was created + _source = debug.traceback(), + + -- A tag to identify us as a promise + _type = "Promise", + + _status = Promise.Status.Started, + + -- A table containing a list of all results, whether success or failure. + -- Only valid if _status is set to something besides Started + _value = nil, + + -- If an error occurs with no observers, this will be set. + _unhandledRejection = false, + + -- Queues representing functions we should invoke when we update! + _queuedResolve = {}, + _queuedReject = {}, + } + + setmetatable(promise, Promise) + + local function resolve(...) + promise:_resolve(...) + end + + local function reject(...) + promise:_reject(...) + end + + local ok, err = wpcall(callback, resolve, reject) + + if not ok and promise._status == Promise.Status.Started then + reject(err) + end + + return promise +end + +--[[ + Create a promise that represents the immediately resolved value. +]] +function Promise.resolve(value) + return Promise.new(function(resolve) + resolve(value) + end) +end + +--[[ + Create a promise that represents the immediately rejected value. +]] +function Promise.reject(value) + return Promise.new(function(_, reject) + reject(value) + end) +end + +--[[ + Returns a new promise that: + * is resolved when all input promises resolve + * is rejected if ANY input promises reject +]] +function Promise.all(...) + error("unimplemented", 2) +end + +--[[ + Is the given object a Promise instance? +]] +function Promise.is(object) + if type(object) ~= "table" then + return false + end + + return object._type == "Promise" +end + +--[[ + Creates a new promise that receives the result of this promise. + + The given callbacks are invoked depending on that result. +]] +function Promise:andThen(successHandler, failureHandler) + self._unhandledRejection = false + + -- Create a new promise to follow this part of the chain + return Promise.new(function(resolve, reject) + -- Our default callbacks just pass values onto the next promise. + -- This lets success and failure cascade correctly! + + local successCallback = resolve + if successHandler then + successCallback = createAdvancer(successHandler, resolve, reject) + end + + local failureCallback = reject + if failureHandler then + failureCallback = createAdvancer(failureHandler, resolve, reject) + end + + if self._status == Promise.Status.Started then + -- If we haven't resolved yet, put ourselves into the queue + table.insert(self._queuedResolve, successCallback) + table.insert(self._queuedReject, failureCallback) + elseif self._status == Promise.Status.Resolved then + -- This promise has already resolved! Trigger success immediately. + successCallback(unpack(self._value)) + elseif self._status == Promise.Status.Rejected then + -- This promise died a terrible death! Trigger failure immediately. + failureCallback(unpack(self._value)) + end + end) +end + +--[[ + Used to catch any errors that may have occurred in the promise. +]] +function Promise:catch(failureCallback) + return self:andThen(nil, failureCallback) +end + +--[[ + Yield until the promise is completed. + + This matches the execution model of normal Roblox functions. +]] +function Promise:await() + self._unhandledRejection = false + + if self._status == Promise.Status.Started then + local result + local bindable = Instance.new("BindableEvent") + + self:andThen(function(...) + result = {...} + bindable:Fire(true) + end, function(...) + result = {...} + bindable:Fire(false) + end) + + local ok = bindable.Event:Wait() + bindable:Destroy() + + if not ok then + error(tostring(result[1]), 2) + end + + return unpack(result) + elseif self._status == Promise.Status.Resolved then + return unpack(self._value) + elseif self._status == Promise.Status.Rejected then + error(tostring(self._value[1]), 2) + end +end + +function Promise:_resolve(...) + if self._status ~= Promise.Status.Started then + return + end + + -- If the resolved value was a Promise, we chain onto it! + if Promise.is((...)) then + -- Without this warning, arguments sometimes mysteriously disappear + if select("#", ...) > 1 then + local message = ( + "When returning a Promise from andThen, extra arguments are " .. + "discarded! See:\n\n%s" + ):format( + self._source + ) + warn(message) + end + + (...):andThen(function(...) + self:_resolve(...) + end, function(...) + self:_reject(...) + end) + + return + end + + self._status = Promise.Status.Resolved + self._value = {...} + + -- We assume that these callbacks will not throw errors. + for _, callback in ipairs(self._queuedResolve) do + callback(...) + end +end + +function Promise:_reject(...) + if self._status ~= Promise.Status.Started then + return + end + + self._status = Promise.Status.Rejected + self._value = {...} + + -- If there are any rejection handlers, call those! + if not isEmpty(self._queuedReject) then + -- We assume that these callbacks will not throw errors. + for _, callback in ipairs(self._queuedReject) do + callback(...) + end + else + -- At this point, no one was able to observe the error. + -- An error handler might still be attached if the error occurred + -- synchronously. We'll wait one tick, and if there are still no + -- observers, then we should put a message in the console. + + self._unhandledRejection = true + local err = tostring((...)) + + spawn(function() + -- Someone observed the error, hooray! + if not self._unhandledRejection then + return + end + + -- Build a reasonable message + local message = ("Unhandled promise rejection:\n\n%s\n\n%s"):format( + err, + self._source + ) + warn(message) + end) + end +end + +return Promise diff --git a/plugin/src/Promise.spec.lua b/plugin/src/Promise.spec.lua new file mode 100644 index 00000000..2193fcb6 --- /dev/null +++ b/plugin/src/Promise.spec.lua @@ -0,0 +1,262 @@ +return function() + local Promise = require(script.Parent.Promise) + + describe("Promise.new", function() + it("should instantiate with a callback", function() + local promise = Promise.new(function() end) + + expect(promise).to.be.ok() + end) + + it("should invoke the given callback with resolve and reject", function() + local callCount = 0 + local resolveArg + local rejectArg + + local promise = Promise.new(function(resolve, reject) + callCount = callCount + 1 + resolveArg = resolve + rejectArg = reject + end) + + expect(promise).to.be.ok() + + expect(callCount).to.equal(1) + expect(resolveArg).to.be.a("function") + expect(rejectArg).to.be.a("function") + expect(promise._status).to.equal(Promise.Status.Started) + end) + + it("should resolve promises on resolve()", function() + local callCount = 0 + + local promise = Promise.new(function(resolve) + callCount = callCount + 1 + resolve() + end) + + expect(promise).to.be.ok() + expect(callCount).to.equal(1) + expect(promise._status).to.equal(Promise.Status.Resolved) + end) + + it("should reject promises on reject()", function() + local callCount = 0 + + local promise = Promise.new(function(resolve, reject) + callCount = callCount + 1 + reject() + end) + + expect(promise).to.be.ok() + expect(callCount).to.equal(1) + expect(promise._status).to.equal(Promise.Status.Rejected) + end) + + it("should reject on error in callback", function() + local callCount = 0 + + local promise = Promise.new(function() + callCount = callCount + 1 + error("hahah") + end) + + expect(promise).to.be.ok() + expect(callCount).to.equal(1) + expect(promise._status).to.equal(Promise.Status.Rejected) + expect(promise._value[1]:find("hahah")).to.be.ok() + end) + end) + + describe("Promise.resolve", function() + it("should immediately resolve with a value", function() + local promise = Promise.resolve(5) + + expect(promise).to.be.ok() + expect(promise._status).to.equal(Promise.Status.Resolved) + expect(promise._value[1]).to.equal(5) + end) + + it("should chain onto passed promises", function() + local promise = Promise.resolve(Promise.new(function(_, reject) + reject(7) + end)) + + expect(promise).to.be.ok() + expect(promise._status).to.equal(Promise.Status.Rejected) + expect(promise._value[1]).to.equal(7) + end) + end) + + describe("Promise.reject", function() + it("should immediately reject with a value", function() + local promise = Promise.reject(6) + + expect(promise).to.be.ok() + expect(promise._status).to.equal(Promise.Status.Rejected) + expect(promise._value[1]).to.equal(6) + end) + + it("should pass a promise as-is as an error", function() + local innerPromise = Promise.new(function(resolve) + resolve(6) + end) + + local promise = Promise.reject(innerPromise) + + expect(promise).to.be.ok() + expect(promise._status).to.equal(Promise.Status.Rejected) + expect(promise._value[1]).to.equal(innerPromise) + end) + end) + + describe("Promise:andThen", function() + it("should chain onto resolved promises", function() + local args + local argsLength + local callCount = 0 + local badCallCount = 0 + + local promise = Promise.resolve(5) + + local chained = promise + :andThen(function(...) + args = {...} + argsLength = select("#", ...) + callCount = callCount + 1 + end, function() + badCallCount = badCallCount + 1 + end) + + expect(badCallCount).to.equal(0) + + expect(callCount).to.equal(1) + expect(argsLength).to.equal(1) + expect(args[1]).to.equal(5) + + expect(promise).to.be.ok() + expect(promise._status).to.equal(Promise.Status.Resolved) + expect(promise._value[1]).to.equal(5) + + expect(chained).to.be.ok() + expect(chained).never.to.equal(promise) + expect(chained._status).to.equal(Promise.Status.Resolved) + expect(#chained._value).to.equal(0) + end) + + it("should chain onto rejected promises", function() + local args + local argsLength + local callCount = 0 + local badCallCount = 0 + + local promise = Promise.reject(5) + + local chained = promise + :andThen(function(...) + badCallCount = badCallCount + 1 + end, function(...) + args = {...} + argsLength = select("#", ...) + callCount = callCount + 1 + end) + + expect(badCallCount).to.equal(0) + + expect(callCount).to.equal(1) + expect(argsLength).to.equal(1) + expect(args[1]).to.equal(5) + + expect(promise).to.be.ok() + expect(promise._status).to.equal(Promise.Status.Rejected) + expect(promise._value[1]).to.equal(5) + + expect(chained).to.be.ok() + expect(chained).never.to.equal(promise) + expect(chained._status).to.equal(Promise.Status.Resolved) + expect(#chained._value).to.equal(0) + end) + + it("should chain onto asynchronously resolved promises", function() + local args + local argsLength + local callCount = 0 + local badCallCount = 0 + + local startResolution + local promise = Promise.new(function(resolve) + startResolution = resolve + end) + + local chained = promise + :andThen(function(...) + args = {...} + argsLength = select("#", ...) + callCount = callCount + 1 + end, function() + badCallCount = badCallCount + 1 + end) + + expect(callCount).to.equal(0) + expect(badCallCount).to.equal(0) + + startResolution(6) + + expect(badCallCount).to.equal(0) + + expect(callCount).to.equal(1) + expect(argsLength).to.equal(1) + expect(args[1]).to.equal(6) + + expect(promise).to.be.ok() + expect(promise._status).to.equal(Promise.Status.Resolved) + expect(promise._value[1]).to.equal(6) + + expect(chained).to.be.ok() + expect(chained).never.to.equal(promise) + expect(chained._status).to.equal(Promise.Status.Resolved) + expect(#chained._value).to.equal(0) + end) + + it("should chain onto asynchronously rejected promises", function() + local args + local argsLength + local callCount = 0 + local badCallCount = 0 + + local startResolution + local promise = Promise.new(function(_, reject) + startResolution = reject + end) + + local chained = promise + :andThen(function() + badCallCount = badCallCount + 1 + end, function(...) + args = {...} + argsLength = select("#", ...) + callCount = callCount + 1 + end) + + expect(callCount).to.equal(0) + expect(badCallCount).to.equal(0) + + startResolution(6) + + expect(badCallCount).to.equal(0) + + expect(callCount).to.equal(1) + expect(argsLength).to.equal(1) + expect(args[1]).to.equal(6) + + expect(promise).to.be.ok() + expect(promise._status).to.equal(Promise.Status.Rejected) + expect(promise._value[1]).to.equal(6) + + expect(chained).to.be.ok() + expect(chained).never.to.equal(promise) + expect(chained._status).to.equal(Promise.Status.Resolved) + expect(#chained._value).to.equal(0) + end) + end) +end diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua new file mode 100644 index 00000000..22d7968d --- /dev/null +++ b/plugin/src/Reconciler.lua @@ -0,0 +1,203 @@ +local RouteMap = require(script.Parent.RouteMap) + +local function classEqual(rbx, className) + if className == "*" then + return true + end + + return rbx.ClassName == className +end + +local function reparent(rbx, parent) + if rbx then + -- It's possible that 'rbx' is a service or some other object that we + -- can't change the parent of. That's the only reason why Parent would + -- fail except for rbx being previously destroyed! + pcall(function() + rbx.Parent = parent + end) + end +end + +--[[ + Attempts to match up Roblox instances and object specifiers for + reconciliation. + + An object is considered a match if they have the same Name and ClassName. + + primaryChildren and secondaryChildren can each be either a list of Roblox + instances or object specifiers. Since they share a common shape, switching + the two around isn't problematic! + + visited is expected to be an empty table initially. It will be filled with + the set of children that have been visited so far. +]] +local function findNextChildPair(primaryChildren, secondaryChildren, visited) + for _, primaryChild in ipairs(primaryChildren) do + if not visited[primaryChild] then + visited[primaryChild] = true + + for _, secondaryChild in ipairs(secondaryChildren) do + if primaryChild.ClassName == secondaryChild.ClassName and primaryChild.Name == secondaryChild.Name then + visited[secondaryChild] = true + + return primaryChild, secondaryChild + end + end + + return primaryChild, nil + end + end + + return nil, nil +end + +local Reconciler = {} +Reconciler.__index = Reconciler + +function Reconciler.new() + local reconciler = { + _routeMap = RouteMap.new(), + } + + setmetatable(reconciler, Reconciler) + + return reconciler +end + +--[[ + A semi-smart algorithm that attempts to apply the given item's children to + an existing Roblox object. +]] +function Reconciler:_reconcileChildren(rbx, item) + local visited = {} + local rbxChildren = rbx:GetChildren() + + -- Reconcile any children that were added or updated + while true do + local itemChild, rbxChild = findNextChildPair(item.Children, rbxChildren, visited) + + if not itemChild then + break + end + + reparent(self:reconcile(rbxChild, itemChild), rbx) + end + + -- Reconcile any children that were deleted + while true do + local rbxChild, itemChild = findNextChildPair(rbxChildren, item.Children, visited) + + if not rbxChild then + break + end + + reparent(self:reconcile(rbxChild, itemChild), rbx) + end +end + +--[[ + Construct a new Roblox object from the given item. +]] +function Reconciler:_reify(item) + local className = item.ClassName + + -- "*" represents a match of any class. It reifies as a folder! + if className == "*" then + className = "Folder" + end + + local rbx = Instance.new(className) + rbx.Name = item.Name + + for key, property in pairs(item.Properties) do + -- TODO: Check for compound types, like Vector3! + rbx[key] = property.Value + end + + self:_reconcileChildren(rbx, item) + + if item.Route then + self._routeMap:insert(item.Route, rbx) + end + + return rbx +end + +--[[ + Apply the changes represented by the given item to a Roblox object that's a + child of the given instance. +]] +function Reconciler:reconcile(rbx, item) + -- Item was deleted + if not item then + if rbx then + rbx:Destroy() + end + + return nil + end + + -- Item was created! + if not rbx then + return self:_reify(item) + end + + -- Item changed type! + if not classEqual(rbx, item.ClassName) then + rbx:Destroy() + + rbx = self:_reify(item) + end + + -- Apply all properties, Roblox will de-duplicate changes + for key, property in pairs(item.Properties) do + -- TODO: Transform property value based on property.Type + -- Right now, we assume that 'value' is primitive! + + rbx[key] = property.Value + end + + -- Use a dumb algorithm for reconciling children + self:_reconcileChildren(rbx, item) + + return rbx +end + +function Reconciler:reconcileRoute(route, item, itemRoute) + local parent + local rbx = game + + for i = 1, #route do + local piece = route[i] + + local child = rbx:FindFirstChild(piece) + + -- We should get services instead of making folders here. + if rbx == game and not child then + local _ + _, child = pcall(game.GetService, game, piece) + end + + -- We don't want to create a folder if we're reaching our target item! + if not child and i ~= #route then + child = Instance.new("Folder") + child.Parent = rbx + child.Name = piece + end + + parent = rbx + rbx = child + end + + -- Let's check the route map! + if not rbx then + rbx = self._routeMap:get(itemRoute) + end + + rbx = self:reconcile(rbx, item) + + reparent(rbx, parent) +end + +return Reconciler diff --git a/plugin/src/RouteMap.lua b/plugin/src/RouteMap.lua new file mode 100644 index 00000000..d76e5a0b --- /dev/null +++ b/plugin/src/RouteMap.lua @@ -0,0 +1,103 @@ +--[[ + A map from Route objects (given by the server) to Roblox instances (created + by the plugin). +]] + +local function hashRoute(route) + return table.concat(route, "/") +end + +local RouteMap = {} +RouteMap.__index = RouteMap + +function RouteMap.new() + local self = { + _map = {}, + _reverseMap = {}, + _connectionsByRbx = {}, + } + + setmetatable(self, RouteMap) + + return self +end + +function RouteMap:insert(route, rbx) + local hashed = hashRoute(route) + + self._map[hashed] = rbx + self._reverseMap[rbx] = hashed + self._connectionsByRbx[rbx] = rbx.AncestryChanged:Connect(function(_, parent) + if parent == nil then + self:removeByRbx(rbx) + end + end) +end + +function RouteMap:get(route) + return self._map[hashRoute(route)] +end + +function RouteMap:removeByRoute(route) + local hashedRoute = hashRoute(route) + local rbx = self._map[hashedRoute] + + if rbx then + self._map[hashedRoute] = nil + self._reverseMap[rbx] = nil + self._connectionsByRbx[rbx] = nil + end +end + +function RouteMap:removeByRbx(rbx) + local hashedRoute = self._reverseMap[rbx] + + if hashedRoute then + self._map[hashedRoute] = nil + self._reverseMap[rbx] = nil + self._connectionsByRbx[rbx] = nil + end +end + +function RouteMap:removeRbxDescendants(parentRbx) + for rbx in pairs(self._reverseMap) do + if rbx:IsDescendantOf(parentRbx) then + self:removeByRbx(rbx) + end + end +end + +function RouteMap:clear() + self._map = {} + self._reverseMap = {} + + for object in pairs(self._connectionsByRbx) do + object:Disconnect() + end + + self._connectionsByRbx = {} +end + +function RouteMap:visualize() + -- Log all of our keys so that the visualization has a stable order. + local keys = {} + + for key in pairs(self._map) do + table.insert(keys, key) + end + + table.sort(keys) + + local buffer = {} + for _, key in ipairs(keys) do + local visualized = ("- %s: %s"):format( + key, + self._map[key]:GetFullName() + ) + table.insert(buffer, visualized) + end + + return table.concat(buffer, "\n") +end + +return RouteMap diff --git a/plugin/src/Server.lua b/plugin/src/Server.lua new file mode 100644 index 00000000..5619426f --- /dev/null +++ b/plugin/src/Server.lua @@ -0,0 +1,89 @@ +local HttpService = game:GetService("HttpService") + +local Config = require(script.Parent.Config) +local Promise = require(script.Parent.Promise) +local Version = require(script.Parent.Version) + +local Server = {} +Server.__index = Server + +--[[ + Create a new Server using the given HTTP implementation and replacer. + + If the context becomes invalid, `replacer` will be invoked with a new + context that should be suitable to replace this one. + + Attempting to invoke methods on an invalid conext will throw errors! +]] +function Server.connect(http) + local context = { + http = http, + serverId = nil, + currentTime = 0, + } + + setmetatable(context, Server) + + return context:_start() +end + +function Server:_start() + return self:getInfo() + :andThen(function(response) + if response.protocolVersion ~= Config.protocolVersion then + local message = ( + "Found a Rojo dev server, but it's using a different protocol version, and is incompatible." .. + "\nMake sure you have matching versions of both the Rojo plugin and server!" .. + "\n\nYour client is version %s, with protocol version %s. It expects server version %s." .. + "\nYour server is version %s, with protocol version %s." .. + "\n\nGo to https://github.com/LPGhatguy/rojo for more details." + ):format( + Version.display(Config.version), Config.protocolVersion, + Config.expectedServerVersionString, + response.serverVersion, response.protocolVersion + ) + + return Promise.reject(message) + end + + self.serverId = response.serverId + self.currentTime = response.currentTime + + return self + end) +end + +function Server:getInfo() + return self.http:get("/") + :andThen(function(response) + response = response:json() + + return response + end) +end + +function Server:read(paths) + local body = HttpService:JSONEncode(paths) + + return self.http:post("/read", body) + :andThen(function(response) + response = response:json() + + return response.items + end) +end + +function Server:getChanges() + local url = ("/changes/%f"):format(self.currentTime) + + return self.http:get(url) + :andThen(function(response) + response = response:json() + + self.currentTime = response.currentTime + + return response.changes + end) +end + +return Server diff --git a/plugin/src/Version.lua b/plugin/src/Version.lua new file mode 100644 index 00000000..24483fa0 --- /dev/null +++ b/plugin/src/Version.lua @@ -0,0 +1,40 @@ +local function compare(a, b) + if a > b then + return 1 + elseif a < b then + return -1 + end + + return 0 +end + +local Version = {} + +--[[ + Compares two versions of the form {major, minor, revision}. + + If a is newer than b, 1. + If a is older than b, -1. + If a and b are the same, 0. +]] +function Version.compare(a, b) + local major = compare(a[1], b[1]) + local minor = compare(a[2] or 0, b[2] or 0) + local revision = compare(a[3] or 0, b[3] or 0) + + if major ~= 0 then + return major + end + + if minor ~= 0 then + return minor + end + + return revision +end + +function Version.display(version) + return table.concat(version, ".") +end + +return Version diff --git a/plugin/src/Version.spec.lua b/plugin/src/Version.spec.lua new file mode 100644 index 00000000..7be002e9 --- /dev/null +++ b/plugin/src/Version.spec.lua @@ -0,0 +1,28 @@ +return function() + local Version = require(script.Parent.Version) + + it("should compare equal versions", function() + expect(Version.compare({1, 2, 3}, {1, 2, 3})).to.equal(0) + expect(Version.compare({0, 4, 0}, {0, 4})).to.equal(0) + expect(Version.compare({0, 0, 123}, {0, 0, 123})).to.equal(0) + expect(Version.compare({26}, {26})).to.equal(0) + expect(Version.compare({26, 42}, {26, 42})).to.equal(0) + expect(Version.compare({1, 0, 0}, {1})).to.equal(0) + end) + + it("should compare newer, older versions", function() + expect(Version.compare({1}, {0})).to.equal(1) + expect(Version.compare({1, 1}, {1, 0})).to.equal(1) + end) + + it("should compare different major versions", function() + expect(Version.compare({1, 3, 2}, {2, 2, 1})).to.equal(-1) + expect(Version.compare({1, 2}, {2, 1})).to.equal(-1) + expect(Version.compare({1}, {2})).to.equal(-1) + end) + + it("should compare different minor versions", function() + expect(Version.compare({1, 2, 3}, {1, 3, 2})).to.equal(-1) + expect(Version.compare({50, 1}, {50, 2})).to.equal(-1) + end) +end diff --git a/plugin/src/runTests.lua b/plugin/src/runTests.lua new file mode 100644 index 00000000..9b1da76e --- /dev/null +++ b/plugin/src/runTests.lua @@ -0,0 +1,4 @@ +return function() + local TestEZ = require(script.Parent.Parent.TestEZ) + TestEZ.TestBootstrap:run(script.Parent) +end diff --git a/plugin/tests/runTests.server.lua b/plugin/tests/runTests.server.lua new file mode 100644 index 00000000..be1a94d5 --- /dev/null +++ b/plugin/tests/runTests.server.lua @@ -0,0 +1,2 @@ +local TestEZ = require(game.ReplicatedStorage.TestEZ) +TestEZ.TestBootstrap:run(game.ReplicatedStorage.Rojo.plugin) diff --git a/server/.editorconfig b/server/.editorconfig new file mode 100644 index 00000000..1be11156 --- /dev/null +++ b/server/.editorconfig @@ -0,0 +1,5 @@ +[*.rs] +indent_style = space +indent_size = 4 +trim_trailing_whitespace = true +insert_final_newline = true \ No newline at end of file diff --git a/.gitignore b/server/.gitignore similarity index 100% rename from .gitignore rename to server/.gitignore diff --git a/Cargo.lock b/server/Cargo.lock similarity index 100% rename from Cargo.lock rename to server/Cargo.lock diff --git a/Cargo.toml b/server/Cargo.toml similarity index 100% rename from Cargo.toml rename to server/Cargo.toml diff --git a/rustfmt.toml b/server/rustfmt.toml similarity index 100% rename from rustfmt.toml rename to server/rustfmt.toml diff --git a/src/bin.rs b/server/src/bin.rs similarity index 100% rename from src/bin.rs rename to server/src/bin.rs diff --git a/src/commands/init.rs b/server/src/commands/init.rs similarity index 100% rename from src/commands/init.rs rename to server/src/commands/init.rs diff --git a/src/commands/mod.rs b/server/src/commands/mod.rs similarity index 100% rename from src/commands/mod.rs rename to server/src/commands/mod.rs diff --git a/src/commands/serve.rs b/server/src/commands/serve.rs similarity index 100% rename from src/commands/serve.rs rename to server/src/commands/serve.rs diff --git a/src/core.rs b/server/src/core.rs similarity index 100% rename from src/core.rs rename to server/src/core.rs diff --git a/src/pathext.rs b/server/src/pathext.rs similarity index 100% rename from src/pathext.rs rename to server/src/pathext.rs diff --git a/src/plugin.rs b/server/src/plugin.rs similarity index 100% rename from src/plugin.rs rename to server/src/plugin.rs diff --git a/src/plugins/default_plugin.rs b/server/src/plugins/default_plugin.rs similarity index 100% rename from src/plugins/default_plugin.rs rename to server/src/plugins/default_plugin.rs diff --git a/src/plugins/json_model_plugin.rs b/server/src/plugins/json_model_plugin.rs similarity index 100% rename from src/plugins/json_model_plugin.rs rename to server/src/plugins/json_model_plugin.rs diff --git a/src/plugins/mod.rs b/server/src/plugins/mod.rs similarity index 100% rename from src/plugins/mod.rs rename to server/src/plugins/mod.rs diff --git a/src/plugins/script_plugin.rs b/server/src/plugins/script_plugin.rs similarity index 100% rename from src/plugins/script_plugin.rs rename to server/src/plugins/script_plugin.rs diff --git a/src/project.rs b/server/src/project.rs similarity index 100% rename from src/project.rs rename to server/src/project.rs diff --git a/src/rbx.rs b/server/src/rbx.rs similarity index 100% rename from src/rbx.rs rename to server/src/rbx.rs diff --git a/src/vfs/mod.rs b/server/src/vfs/mod.rs similarity index 100% rename from src/vfs/mod.rs rename to server/src/vfs/mod.rs diff --git a/src/vfs/vfs_item.rs b/server/src/vfs/vfs_item.rs similarity index 100% rename from src/vfs/vfs_item.rs rename to server/src/vfs/vfs_item.rs diff --git a/src/vfs/vfs_session.rs b/server/src/vfs/vfs_session.rs similarity index 100% rename from src/vfs/vfs_session.rs rename to server/src/vfs/vfs_session.rs diff --git a/src/vfs/vfs_watcher.rs b/server/src/vfs/vfs_watcher.rs similarity index 100% rename from src/vfs/vfs_watcher.rs rename to server/src/vfs/vfs_watcher.rs diff --git a/src/web.rs b/server/src/web.rs similarity index 100% rename from src/web.rs rename to server/src/web.rs From 3b1d647acb9ad91de4b7e93148b2538c2fd70844 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 1 Apr 2018 23:30:25 -0700 Subject: [PATCH 0084/1504] Bump license year --- LICENSE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE.md b/LICENSE.md index 7d0bc1cb..d9aeb8a3 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2017 Lucien Greathouse +Copyright (c) 2018 Lucien Greathouse Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: From 9723622b66d498d35421f1bdc1b2e1193f741783 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 1 Apr 2018 23:30:33 -0700 Subject: [PATCH 0085/1504] Bump server to version 0.4.1, update dependencies --- server/Cargo.lock | 338 +++++++++++++++++++++++++--------------------- server/Cargo.toml | 2 +- 2 files changed, 188 insertions(+), 152 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index e185036a..686447ec 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -16,8 +16,11 @@ dependencies = [ [[package]] name = "ansi_term" -version = "0.10.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "ascii" @@ -26,12 +29,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "atty" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -55,7 +58,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -64,7 +67,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "brotli-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -79,7 +82,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cc" -version = "1.0.3" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -92,7 +95,7 @@ name = "chrono" version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -103,13 +106,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clap" -version = "2.29.0" +version = "2.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -188,12 +191,12 @@ dependencies = [ [[package]] name = "filetime" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -201,7 +204,7 @@ name = "flate2" version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -212,7 +215,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -220,7 +223,7 @@ name = "fsevent-sys" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -257,12 +260,12 @@ name = "inotify" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -281,7 +284,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.35" +version = "0.2.40" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -310,7 +313,7 @@ name = "memchr" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -318,7 +321,7 @@ name = "memchr" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -345,8 +348,8 @@ name = "miniz-sys" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -355,10 +358,10 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -371,7 +374,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -387,20 +390,18 @@ dependencies = [ "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "net2" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -409,7 +410,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -418,47 +419,47 @@ version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num" -version = "0.1.41" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-integer" -version = "0.1.35" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-iter" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.1.41" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -489,7 +490,7 @@ version = "0.7.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -501,22 +502,44 @@ dependencies = [ ] [[package]] -name = "quote" -version = "0.3.15" +name = "proc-macro2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "rand" -version = "0.3.19" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.34" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -524,7 +547,7 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -541,12 +564,12 @@ dependencies = [ [[package]] name = "regex" -version = "0.2.5" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -558,22 +581,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex-syntax" -version = "0.4.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "remove_dir_all" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "rojo" -version = "0.4.0" +version = "0.4.1" dependencies = [ - "clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -583,16 +617,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "brotli2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", "multipart 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny_http 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny_http 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -602,10 +636,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "same-file" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -613,42 +647,43 @@ name = "serde" version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde" -version = "1.0.27" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.27" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.19.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.9" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -668,33 +703,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strsim" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.11.11" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "synom" -version = "0.11.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tempdir" -version = "0.3.5" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -711,8 +739,8 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -730,7 +758,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -755,14 +783,14 @@ name = "time" version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tiny_http" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -770,10 +798,14 @@ dependencies = [ "chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ucd-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -794,7 +826,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-xid" -version = "0.0.4" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -817,7 +849,7 @@ dependencies = [ [[package]] name = "url" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -840,7 +872,7 @@ name = "uuid" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -856,10 +888,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" -version = "2.0.1" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "same-file 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -869,11 +902,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -883,12 +916,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi-i686-pc-windows-gnu" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi-x86_64-pc-windows-gnu" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -903,9 +936,9 @@ dependencies = [ [metadata] "checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" -"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" -"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859" +"checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" @@ -913,11 +946,11 @@ dependencies = [ "checksum brotli2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea9d0bbab1235017a09226b079ed733bca4bf9ecb6b6102bd01aac79ea082dca" "checksum buf_redux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b115bd9935c68b58f80ff867e1c46942c4aed79e78bcc8c2bc22d50f52bb9099" "checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27" -"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719" +"checksum cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" -"checksum clap 2.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "110d43e343eb29f4f51c1db31beb879d546db27998577e5715270a54bcf41d3f" +"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" @@ -927,7 +960,7 @@ dependencies = [ "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" -"checksum filetime 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "aa75ec8f7927063335a9583e7fa87b0110bb888cf766dc01b54c0ff70d760c8e" +"checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f" "checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423" "checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05" "checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874" @@ -936,10 +969,10 @@ dependencies = [ "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" -"checksum itoa 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8324a32baf01e2ae060e9de58ed0bc2320c9a2833491ee36cd3b4c414de4db8c" +"checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" -"checksum libc 0.2.35 (registry+https://github.com/rust-lang/crates.io-index)" = "96264e9b293e95d25bfcbbf8a88ffd1aedc85b754eba8b7d78012f638ba220eb" +"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" @@ -951,41 +984,43 @@ dependencies = [ "checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e" "checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" "checksum multipart 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b68c9a0c757bd65893af529f7af6e7a71442e57ca6d9db1fa69b79e2f05f6b49" -"checksum net2 0.2.31 (registry+https://github.com/rust-lang/crates.io-index)" = "3a80f842784ef6c9a958b68b7516bc7e35883c614004dd94959a4dca1b716c09" +"checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0" "checksum nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfb3ddedaa14746434a02041940495bf11325c22f6d36125d3bdd56090d50a79" "checksum notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5c3812da3098f210a0bb440f9c008471a031aa4c1de07a264fdd75456c95a4eb" -"checksum num 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cc4083e14b542ea3eb9b5f33ff48bd373a92d78687e74f4cc0a30caeb754f0ca" -"checksum num-integer 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "d1452e8b06e448a07f0e6ebb0bb1d92b8890eea63288c0b627331d53514d0fba" -"checksum num-iter 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "7485fcc84f85b4ecd0ea527b14189281cf27d60e583ae65ebc9c088b13dffe01" -"checksum num-traits 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "cacfcab5eb48250ee7d0c7896b51a2c5eec99c1feea5f32025635f5ae4b00070" +"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" +"checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe" +"checksum num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "4b226df12c5a59b63569dd57fafb926d91b385dfce33d8074a412411b689d593" +"checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" "checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" -"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a" -"checksum rand 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)" = "9e7944d95d25ace8f377da3ac7068ce517e4c646754c43a1b1849177bbf72e59" -"checksum redox_syscall 0.1.34 (registry+https://github.com/rust-lang/crates.io-index)" = "df1a5c588807af3b0cbbfa2f1358f2d5ec6ad546858c1ccd30dfbb127021706b" +"checksum proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "388d7ea47318c5ccdeb9ba6312cee7d3f65dd2804be8580a170fce410d50b786" +"checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a" +"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" +"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" +"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" -"checksum regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "744554e01ccbd98fff8c457c3b092cd67af62a555a43bfe97ae8a0451f7799fa" +"checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" "checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" -"checksum regex-syntax 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8e931c58b93d86f080c734bfd2bce7dd0079ae2331235818133c8be7f422e20e" +"checksum regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2550876c31dc914696a6c2e01cbce8afba79a93c8ae979d2fe051c0230b3756" +"checksum remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfc5b3ce5d5ea144bb04ebd093a9e14e9765bcfec866aecda9b6dec43b3d1e24" "checksum rouille 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d6415f261a8775bef50e9fcfb14ed73209ce637f753f9d1c8c6122559e559001" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum same-file 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3257af0472da4b8b8902102a57bafffd9991f0f43772a8af6153d597e6e4ae2" +"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" -"checksum serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "db99f3919e20faa51bb2996057f5031d8685019b5a06139b1ce761da671b8526" -"checksum serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "f4ba7591cfe93755e89eeecdbcc668885624829b020050e6aec99c2a03bd3fd0" -"checksum serde_derive_internals 0.19.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6e03f1c9530c3fb0a0a5c9b826bdd9246a5921ae995d75f512ac917fc4dd55b5" -"checksum serde_json 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c9db7266c7d63a4c4b7fe8719656ccdd51acf1bed6124b174f933b009fb10bcb" +"checksum serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "d3bcee660dcde8f52c3765dd9ca5ee36b4bf35470a738eb0bd5a8752b0389645" +"checksum serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "f1711ab8b208541fa8de00425f6a577d90f27bb60724d2bb5fd911314af9668f" +"checksum serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89b340a48245bc03ddba31d0ff1709c118df90edc6adabaca4aac77aea181cce" +"checksum serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5c508584d9913df116b91505eec55610a2f5b16e9ed793c46e4d0152872b3e74" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" -"checksum strsim 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d15c810519a91cf877e7e36e63fe068815c678181439f2f29e2562147c3694" -"checksum syn 0.11.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d3b891b9015c88c576343b9b3e41c2c11a51c219ef067b264bd9c8aa9b441dad" -"checksum synom 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a393066ed9010ebaed60b9eafa373d4b1baac186dd7e008555b0f702b51945b6" -"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" +"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" +"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" @@ -993,23 +1028,24 @@ dependencies = [ "checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" "checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" -"checksum tiny_http 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "016f040cfc9b5be610de3619eaaa57017fa0b0b678187327bde75fc146e2a41f" +"checksum tiny_http 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2f4d55c9a213880d1f0c89ded183f209c6e45b912ca6c7df6f93c163773572e1" +"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" -"checksum unicode-xid 0.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f860d7d29cf02cb2f3f359fd35991af3d30bac52c57d265a3c461074cb4dc" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)" = "cbaa8377a162d88e7d15db0cf110c8523453edcbc5bc66d2b6fffccffa34a068" -"checksum url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa35e768d4daf1d85733418a49fb42e10d7f633e394fccab4ab7aba897053fe2" +"checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" "checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b6d201f4f8998a837196b6de9c73e35af14c992cbb92c4ab641d2c2dce52de" +"checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b09fb3b6f248ea4cd42c9a65113a847d612e17505d6ebd1f7357ad68a8bf8693" +"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum winapi-i686-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ec6667f60c23eca65c561e63a13d81b44234c2e38a6b6c959025ee907ec614cc" -"checksum winapi-x86_64-pc-windows-gnu 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98f12c52b2630cd05d2c3ffd8e008f7f48252c042b4871c72aed9dc733b96668" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" diff --git a/server/Cargo.toml b/server/Cargo.toml index 90071e05..d6000225 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.4.0" +version = "0.4.1" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 3a3af6ab10c029a991e41eda1f6e2aa1e97e0c3d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 1 Apr 2018 23:35:18 -0700 Subject: [PATCH 0086/1504] Introduce mkdocs documentation --- docs/index.md | 6 ++++++ docs/requirements.txt | 3 +++ mkdocs.yml | 20 ++++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 docs/index.md create mode 100644 docs/requirements.txt create mode 100644 mkdocs.yml diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 00000000..a3319d83 --- /dev/null +++ b/docs/index.md @@ -0,0 +1,6 @@ +# Home +This is the documentation home for Rojo. + +**Rojo** is a flexible multi-tool designed for creating robust Roblox projects. + +This documentation is a work in progress, and is incomplete. \ No newline at end of file diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 00000000..51b61b75 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,3 @@ +mkdocs +mkdocs-material +pymdown-extensions \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 00000000..10529937 --- /dev/null +++ b/mkdocs.yml @@ -0,0 +1,20 @@ +site_name: Rojo Documentation +site_url: https://lpghatguy.github.io/rojo/ +repo_name: LPGhatguy/rojo +repo_url: https://github.com/LPGhatguy/rojo + +theme: + name: material + palette: + primary: 'Red' + accent: 'Red' + +pages: + - Home: index.md + +markdown_extensions: + - admonition + - codehilite: + guess_lang: false + - toc: + permalink: true \ No newline at end of file From eabcc0bd1d24bcdf812f0ebb36ac559a714da642 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 1 Apr 2018 23:36:04 -0700 Subject: [PATCH 0087/1504] Add root gitignore to ignore mkdocs generated site --- .gitignore | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitignore diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c9490a53 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/site From 477235096858045e8fb17b48916bce35b2376b29 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 1 Apr 2018 23:39:19 -0700 Subject: [PATCH 0088/1504] Version 0.4.1 --- CHANGES.md | 5 ++++- README.md | 3 +-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 19a6cf7b..71b6728f 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,10 @@ # Rojo Change Log ## Current Master -* Merged plugin repository into main Rojo repository for easier tracking +*No changes* + +## 0.4.1 (April 1, 2018) +* Merged plugin repository into main Rojo repository for easier tracking. * Improved `RouteMap` object tracking; this should fix some cases of duplicated instances being synced into the tree. ## 0.4.0 (March 27, 2018) diff --git a/README.md b/README.md index 6137b612..14d4c1b3 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,7 @@ Travis-CI Build Status - Current server version - Current plugin version + Current server version
From 3dee3dd627d7aed3d194f76ca089e8a972ae4034 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 4 Apr 2018 00:14:23 -0700 Subject: [PATCH 0089/1504] Fix README whitespace inconsistency --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 14d4c1b3..db3bc360 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,9 @@
 
From bad0e672669fcca226bd8e0ba9f511c14e3270ce Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 4 Apr 2018 23:02:46 -0700 Subject: [PATCH 0090/1504] Remove extra spawn in server code --- plugin/src/Main.server.lua | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/plugin/src/Main.server.lua b/plugin/src/Main.server.lua index 062dc414..ca771f5b 100644 --- a/plugin/src/Main.server.lua +++ b/plugin/src/Main.server.lua @@ -67,12 +67,10 @@ local function main() .Click:Connect(function() checkUpgrade() - spawn(function() - pluginInstance:togglePolling() - :catch(function(err) - warn(err) - end) - end) + pluginInstance:togglePolling() + :catch(function(err) + warn(err) + end) end) end From b448e8007eedba785379729547bce858cb6c9c28 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 4 Apr 2018 23:05:01 -0700 Subject: [PATCH 0091/1504] Fix duplication 0.4.x duplication bug for good --- CHANGES.md | 3 ++- plugin/src/Reconciler.lua | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 71b6728f..ab681518 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,8 @@ # Rojo Change Log ## Current Master -*No changes* +* Fixed instances that were reconciled not being inserted into the RouteMap. + * The reconciler is still not a perfect solution, especially if script instances get moved around without being destroyed. I don't think this can be fixed before a big refactor. ## 0.4.1 (April 1, 2018) * Merged plugin repository into main Rojo repository for easier tracking. diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 22d7968d..33f1119f 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -161,6 +161,10 @@ function Reconciler:reconcile(rbx, item) -- Use a dumb algorithm for reconciling children self:_reconcileChildren(rbx, item) + if item.Route then + self._routeMap:insert(item.Route, rbx) + end + return rbx end From 4d0fdf0dfd58e5b06d234bbd7741788f85d94d16 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 4 Apr 2018 23:06:57 -0700 Subject: [PATCH 0092/1504] 0.4.2 --- CHANGES.md | 5 ++++- README.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index ab681518..1557d9a7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,10 @@ # Rojo Change Log ## Current Master -* Fixed instances that were reconciled not being inserted into the RouteMap. +*No changes* + +## 0.4.2 (April 4, 2018) +* Fixed final case of duplicated instance insertion, caused by reconciled instances not being inserted into `RouteMap`. * The reconciler is still not a perfect solution, especially if script instances get moved around without being destroyed. I don't think this can be fixed before a big refactor. ## 0.4.1 (April 1, 2018) diff --git a/README.md b/README.md index db3bc360..e22e1cbc 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Travis-CI Build Status - Current server version + Current server version
diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index b4bfa3be..d7c9466d 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { pollingRate = 0.2, - version = {0, 4, 1}, + version = {0, 4, 2}, expectedServerVersionString = "0.4.x", protocolVersion = 1, dev = false, diff --git a/server/Cargo.toml b/server/Cargo.toml index d6000225..4fa2ba90 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.4.1" +version = "0.4.2" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 7a7ac9550d211495885fbb132e2459d0dbd25ed8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 4 Apr 2018 23:09:02 -0700 Subject: [PATCH 0093/1504] Update server dependencies --- server/Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 686447ec..f84aa23f 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -597,7 +597,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.4.1" +version = "0.4.2" dependencies = [ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", From 31e5c558ab02d62b51b791e2679cb4f0dbabbd00 Mon Sep 17 00:00:00 2001 From: Validark Date: Sat, 7 Apr 2018 21:10:55 -0600 Subject: [PATCH 0094/1504] Open Http Properties upon HttpEnabled prompt (#58) --- plugin/src/HttpError.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugin/src/HttpError.lua b/plugin/src/HttpError.lua index 9da4b946..674721cf 100644 --- a/plugin/src/HttpError.lua +++ b/plugin/src/HttpError.lua @@ -52,6 +52,9 @@ end function HttpError:report() warn(self.message) + if self.type == HttpError.Error.HttpNotEnabled then + game:GetService("Selection"):Set{game:GetService("HttpService")} + end end return HttpError From c2f7e268ff7330a940d0c1283def5da6a784d2e3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 7 Apr 2018 20:13:07 -0700 Subject: [PATCH 0095/1504] Update changelog --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 1557d9a7..a4b8ed62 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,7 @@ # Rojo Change Log ## Current Master -*No changes* +* Plugin now automatically selects `HttpService` if it determines that HTTP isn't enabled ([#58](https://github.com/LPGhatguy/rojo/pull/58)) ## 0.4.2 (April 4, 2018) * Fixed final case of duplicated instance insertion, caused by reconciled instances not being inserted into `RouteMap`. From 52eea667a714f2d6d6fd257a1b6244a8a9377330 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 7 Apr 2018 22:24:21 -0700 Subject: [PATCH 0096/1504] Make plugin connection much more robust, with better errors --- CHANGES.md | 1 + plugin/src/{Server.lua => Api.lua} | 51 ++++++--- plugin/src/Main.server.lua | 10 +- plugin/src/Plugin.lua | 173 +++++++++++++++++++---------- plugin/src/Promise.lua | 10 +- plugin/src/Reconciler.lua | 7 ++ plugin/src/RouteMap.lua | 4 +- 7 files changed, 170 insertions(+), 86 deletions(-) rename plugin/src/{Server.lua => Api.lua} (66%) diff --git a/CHANGES.md b/CHANGES.md index a4b8ed62..0e6a1c95 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## Current Master * Plugin now automatically selects `HttpService` if it determines that HTTP isn't enabled ([#58](https://github.com/LPGhatguy/rojo/pull/58)) +* Plugin now has much more robust handling and will wipe all state when the server changes. ## 0.4.2 (April 4, 2018) * Fixed final case of duplicated instance insertion, caused by reconciled instances not being inserted into `RouteMap`. diff --git a/plugin/src/Server.lua b/plugin/src/Api.lua similarity index 66% rename from plugin/src/Server.lua rename to plugin/src/Api.lua index 5619426f..131acf6f 100644 --- a/plugin/src/Server.lua +++ b/plugin/src/Api.lua @@ -4,32 +4,43 @@ local Config = require(script.Parent.Config) local Promise = require(script.Parent.Promise) local Version = require(script.Parent.Version) -local Server = {} -Server.__index = Server +local Api = {} +Api.__index = Api + +Api.Error = { + ServerIdMismatch = "ServerIdMismatch", +} + +setmetatable(Api.Error, { + __index = function(_, key) + error("Invalid API.Error name " .. key, 2) + end +}) --[[ - Create a new Server using the given HTTP implementation and replacer. + Api.connect(Http) -> Promise - If the context becomes invalid, `replacer` will be invoked with a new - context that should be suitable to replace this one. + Create a new Api using the given HTTP implementation. Attempting to invoke methods on an invalid conext will throw errors! ]] -function Server.connect(http) +function Api.connect(http) local context = { http = http, serverId = nil, currentTime = 0, } - setmetatable(context, Server) + setmetatable(context, Api) return context:_start() end -function Server:_start() - return self:getInfo() +function Api:_start() + return self.http:get("/") :andThen(function(response) + response = response:json() + if response.protocolVersion ~= Config.protocolVersion then local message = ( "Found a Rojo dev server, but it's using a different protocol version, and is incompatible." .. @@ -39,7 +50,7 @@ function Server:_start() "\n\nGo to https://github.com/LPGhatguy/rojo for more details." ):format( Version.display(Config.version), Config.protocolVersion, - Config.expectedServerVersionString, + Config.expectedApiVersionString, response.serverVersion, response.protocolVersion ) @@ -53,37 +64,49 @@ function Server:_start() end) end -function Server:getInfo() +function Api:getInfo() return self.http:get("/") :andThen(function(response) response = response:json() + if response.serverId ~= self.serverId then + return Promise.reject(Api.Error.ServerIdMismatch) + end + return response end) end -function Server:read(paths) +function Api:read(paths) local body = HttpService:JSONEncode(paths) return self.http:post("/read", body) :andThen(function(response) response = response:json() + if response.serverId ~= self.serverId then + return Promise.reject(Api.Error.ServerIdMismatch) + end + return response.items end) end -function Server:getChanges() +function Api:getChanges() local url = ("/changes/%f"):format(self.currentTime) return self.http:get(url) :andThen(function(response) response = response:json() + if response.serverId ~= self.serverId then + return Promise.reject(Api.Error.ServerIdMismatch) + end + self.currentTime = response.currentTime return response.changes end) end -return Server +return Api diff --git a/plugin/src/Main.server.lua b/plugin/src/Main.server.lua index ca771f5b..c6570229 100644 --- a/plugin/src/Main.server.lua +++ b/plugin/src/Main.server.lua @@ -11,6 +11,11 @@ local Version = require(script.Parent.Version) are, show them a reminder to make sure they check their server version. ]] local function checkUpgrade() + -- When developing Rojo, there's no use in doing version checks + if Config.dev then + return + end + local lastVersion = plugin:GetSetting("LastRojoVersion") if lastVersion then @@ -30,10 +35,7 @@ local function checkUpgrade() end end - -- When developing Rojo, there's no use in storing that version number. - if not Config.dev then - plugin:SetSetting("LastRojoVersion", Config.version) - end + plugin:SetSetting("LastRojoVersion", Config.version) end local function main() diff --git a/plugin/src/Plugin.lua b/plugin/src/Plugin.lua index 92cdbd4b..1227c43d 100644 --- a/plugin/src/Plugin.lua +++ b/plugin/src/Plugin.lua @@ -1,6 +1,6 @@ local Config = require(script.Parent.Config) local Http = require(script.Parent.Http) -local Server = require(script.Parent.Server) +local Api = require(script.Parent.Api) local Promise = require(script.Parent.Promise) local Reconciler = require(script.Parent.Reconciler) @@ -26,7 +26,7 @@ function Plugin.new() local self = { _http = Http.new(remote), _reconciler = Reconciler.new(), - _server = nil, + _api = nil, _polling = false, } @@ -57,37 +57,58 @@ function Plugin.new() return self end -function Plugin:server() - if not self._server then - self._server = Server.connect(self._http) +--[[ + Clears all state and issues a notice to the user that the plugin has + restarted. +]] +function Plugin:restart() + warn("The server has changed since the last request, reloading plugin...") + + self._reconciler:clear() + self._api = nil + self._polling = false +end + +function Plugin:api() + if not self._api then + self._api = Api.connect(self._http) :catch(function(err) - self._server = nil + self._api = nil return Promise.reject(err) end) end - return self._server + return self._api end function Plugin:connect() print("Testing connection...") - return self:server() - :andThen(function(server) - return server:getInfo() - end) - :andThen(function(result) + return self:api() + :andThen(function(api) + local ok, info = api:getInfo():await() + + if not ok then + return Promise.reject(info) + end + print("Server found!") - print("Protocol version:", result.protocolVersion) - print("Server version:", result.serverVersion) + print("Protocol version:", info.protocolVersion) + print("Server version:", info.serverVersion) + end) + :catch(function(err) + if err == Api.Error.ServerIdMismatch then + self:restart() + return self:connect() + else + return Promise.reject(err) + end end) end function Plugin:togglePolling() if self._polling then - self:stopPolling() - - return Promise.resolve(nil) + return self:stopPolling() else return self:startPolling() end @@ -95,48 +116,51 @@ end function Plugin:stopPolling() if not self._polling then - return + return Promise.resolve(false) end print("Stopped polling.") self._polling = false self._label.Enabled = false + + return Promise.resolve(true) end -function Plugin:_pull(server, project, routes) - local items = server:read(routes):await() +function Plugin:_pull(api, project, routes) + return api:read(routes) + :andThen(function(items) + for index = 1, #routes do + local itemRoute = routes[index] + local partitionName = itemRoute[1] + local partition = project.partitions[partitionName] + local item = items[index] - for index = 1, #routes do - local itemRoute = routes[index] - local partitionName = itemRoute[1] - local partition = project.partitions[partitionName] - local item = items[index] + local partitionRoute = collectMatch(partition.target, "[^.]+") - local partitionRoute = collectMatch(partition.target, "[^.]+") + -- If the item route's length was 1, we need to rename the instance to + -- line up with the partition's root object name. + -- + -- This is a HACK! + if #itemRoute == 1 then + if item then + local objectName = partition.target:match("[^.]+$") + item.Name = objectName + end + end - -- If the item route's length was 1, we need to rename the instance to - -- line up with the partition's root object name. - -- - -- This is a HACK! - if #itemRoute == 1 then - if item then - local objectName = partition.target:match("[^.]+$") - item.Name = objectName + local fullRoute = {} + for _, piece in ipairs(partitionRoute) do + table.insert(fullRoute, piece) + end + + for i = 2, #itemRoute do + table.insert(fullRoute, itemRoute[i]) + end + + self._reconciler:reconcileRoute(fullRoute, item, itemRoute) end - end - - local fullRoute = {} - for _, piece in ipairs(partitionRoute) do - table.insert(fullRoute, piece) - end - - for i = 2, #itemRoute do - table.insert(fullRoute, itemRoute[i]) - end - - self._reconciler:reconcileRoute(fullRoute, item, itemRoute) - end + end) end function Plugin:startPolling() @@ -149,14 +173,22 @@ function Plugin:startPolling() self._polling = true self._label.Enabled = true - return self:server() - :andThen(function(server) - self:syncIn():await() + return self:api() + :andThen(function(api) + local syncOk, result = self:syncIn():await() - local project = server:getInfo():await().project + if not syncOk then + return Promise.reject(result) + end + + local infoOk, info = api:getInfo():await() + + if not infoOk then + return Promise.reject(info) + end while self._polling do - local changes = server:getChanges():await() + local changes = api:getChanges():await() if #changes > 0 then local routes = {} @@ -165,34 +197,57 @@ function Plugin:startPolling() table.insert(routes, change.route) end - self:_pull(server, project, routes) + local pullOk, pullResult = self:_pull(api, info.project, routes):await() + + if not pullOk then + return Promise.reject(pullResult) + end end wait(Config.pollingRate) end end) - :catch(function() + :catch(function(err) self:stopPolling() + + if err == Api.Error.ServerIdMismatch then + self:restart() + return self:startPolling() + else + return Promise.reject(err) + end end) end function Plugin:syncIn() print("Syncing from server...") - return self:server() - :andThen(function(server) - local project = server:getInfo():await().project + return self:api() + :andThen(function(api) + local ok, info = api:getInfo():await() + + if not ok then + return Promise.reject(info) + end local routes = {} - for name in pairs(project.partitions) do + for name in pairs(info.project.partitions) do table.insert(routes, {name}) end - self:_pull(server, project, routes) + self:_pull(api, info.project, routes) print("Sync successful!") end) + :catch(function(err) + if err == Api.Error.ServerIdMismatch then + self:restart() + return self:syncIn() + else + return Promise.reject(err) + end + end) end return Plugin diff --git a/plugin/src/Promise.lua b/plugin/src/Promise.lua index cdcea791..144469e6 100644 --- a/plugin/src/Promise.lua +++ b/plugin/src/Promise.lua @@ -221,15 +221,11 @@ function Promise:await() local ok = bindable.Event:Wait() bindable:Destroy() - if not ok then - error(tostring(result[1]), 2) - end - - return unpack(result) + return ok, unpack(result) elseif self._status == Promise.Status.Resolved then - return unpack(self._value) + return true, unpack(self._value) elseif self._status == Promise.Status.Rejected then - error(tostring(self._value[1]), 2) + return false, unpack(self._value) end end diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 33f1119f..b69929fa 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -124,6 +124,13 @@ function Reconciler:_reify(item) return rbx end +--[[ + Clears any state that the Reconciler has, effectively restarting it. +]] +function Reconciler:clear() + self._routeMap:clear() +end + --[[ Apply the changes represented by the given item to a Roblox object that's a child of the given instance. diff --git a/plugin/src/RouteMap.lua b/plugin/src/RouteMap.lua index d76e5a0b..a707f7cd 100644 --- a/plugin/src/RouteMap.lua +++ b/plugin/src/RouteMap.lua @@ -71,8 +71,8 @@ function RouteMap:clear() self._map = {} self._reverseMap = {} - for object in pairs(self._connectionsByRbx) do - object:Disconnect() + for _, connection in pairs(self._connectionsByRbx) do + connection:Disconnect() end self._connectionsByRbx = {} From 6fc497f95ec5bbeeb3117191ec4287ddf1af242e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 7 Apr 2018 22:53:56 -0700 Subject: [PATCH 0097/1504] 0.4.3 --- CHANGES.md | 4 ++++ README.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.lock | 2 +- server/Cargo.toml | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 0e6a1c95..38fb155b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,8 +1,12 @@ # Rojo Change Log ## Current Master +*No changes* + +## 0.4.3 (April 7, 2018) * Plugin now automatically selects `HttpService` if it determines that HTTP isn't enabled ([#58](https://github.com/LPGhatguy/rojo/pull/58)) * Plugin now has much more robust handling and will wipe all state when the server changes. + * This should fix issues that would otherwise be solved by restarting Roblox Studio. ## 0.4.2 (April 4, 2018) * Fixed final case of duplicated instance insertion, caused by reconciled instances not being inserted into `RouteMap`. diff --git a/README.md b/README.md index e22e1cbc..131f632c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Travis-CI Build Status - Current server version + Current server version
diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index d7c9466d..9aec7d95 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { pollingRate = 0.2, - version = {0, 4, 2}, + version = {0, 4, 3}, expectedServerVersionString = "0.4.x", protocolVersion = 1, dev = false, diff --git a/server/Cargo.lock b/server/Cargo.lock index f84aa23f..f1f7a30d 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -597,7 +597,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.4.2" +version = "0.4.3" dependencies = [ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/server/Cargo.toml b/server/Cargo.toml index 4fa2ba90..e06d2da5 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.4.2" +version = "0.4.3" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 1f5a686570f4089688bc272e082836a8ddd7fb89 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 7 Apr 2018 22:57:48 -0700 Subject: [PATCH 0098/1504] Fix small regression that I missed for 0.4.3 --- plugin/src/Plugin.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugin/src/Plugin.lua b/plugin/src/Plugin.lua index 1227c43d..2a734f70 100644 --- a/plugin/src/Plugin.lua +++ b/plugin/src/Plugin.lua @@ -188,7 +188,11 @@ function Plugin:startPolling() end while self._polling do - local changes = api:getChanges():await() + local changesOk, changes = api:getChanges():await() + + if not changesOk then + return Promise.reject(changes) + end if #changes > 0 then local routes = {} From 73c6b5a08cee2a68e7386f6437d2fff0cf1d33fa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 7 Apr 2018 22:58:39 -0700 Subject: [PATCH 0099/1504] 0.4.4 --- CHANGES.md | 3 +++ README.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.lock | 2 +- server/Cargo.toml | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 38fb155b..86606407 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,9 @@ ## Current Master *No changes* +## 0.4.4 (April 7, 2018) +* Fix small regression introduced in 0.4.3 + ## 0.4.3 (April 7, 2018) * Plugin now automatically selects `HttpService` if it determines that HTTP isn't enabled ([#58](https://github.com/LPGhatguy/rojo/pull/58)) * Plugin now has much more robust handling and will wipe all state when the server changes. diff --git a/README.md b/README.md index 131f632c..de72a54c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Travis-CI Build Status - Current server version + Current server version
diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 9aec7d95..8c8aaa5c 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { pollingRate = 0.2, - version = {0, 4, 3}, + version = {0, 4, 4}, expectedServerVersionString = "0.4.x", protocolVersion = 1, dev = false, diff --git a/server/Cargo.lock b/server/Cargo.lock index f1f7a30d..bed68bc1 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -597,7 +597,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.4.3" +version = "0.4.4" dependencies = [ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/server/Cargo.toml b/server/Cargo.toml index e06d2da5..1d0a0255 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.4.3" +version = "0.4.4" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From b5cc2434669ee813bfd8dede93a24f6d1bded0cb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 8 Apr 2018 00:09:28 -0700 Subject: [PATCH 0100/1504] Flesh out documentation, normalize markdown indentation --- .editorconfig | 5 ++ README.md | 82 ++++++++++----------- docs/getting-started/creating-a-project.md | 77 +++++++++++++++++++ docs/getting-started/installation.md | 23 ++++++ docs/images/connection-error.png | Bin 0 -> 5928 bytes docs/images/plugin-buttons.png | Bin 0 -> 17614 bytes docs/images/sync-example.png | Bin 0 -> 1931 bytes docs/sync-details.md | 61 +++++++++++++++ docs/why-rojo.md | 21 ++++++ mkdocs.yml | 6 ++ 10 files changed, 234 insertions(+), 41 deletions(-) create mode 100644 docs/getting-started/creating-a-project.md create mode 100644 docs/getting-started/installation.md create mode 100644 docs/images/connection-error.png create mode 100644 docs/images/plugin-buttons.png create mode 100644 docs/images/sync-example.png create mode 100644 docs/sync-details.md create mode 100644 docs/why-rojo.md diff --git a/.editorconfig b/.editorconfig index 263d65f2..702598e1 100644 --- a/.editorconfig +++ b/.editorconfig @@ -7,4 +7,9 @@ charset = utf-8 [*.json] indent_style = space indent_size = 2 +trim_trailing_whitespace = true + +[*.md] +indent_style = space +indent_size = 4 trim_trailing_whitespace = true \ No newline at end of file diff --git a/README.md b/README.md index de72a54c..79ee70c4 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@
- Rojo + Rojo
 
- - Travis-CI Build Status - - Current server version + + Travis-CI Build Status + + Current server version

@@ -45,9 +45,9 @@ To install the server, either: To install the plugin, either: * Install the plugin from the [Roblox plugin page](https://www.roblox.com/library/1211549683/Rojo). - * This gives you less control over what version you install -- you will always have the latest version. + * This gives you less control over what version you install -- you will always have the latest version. * Or, download the latest release from [the GitHub releases section](https://github.com/LPGhatguy/rojo/releases) and install it into your Roblox plugins folder - * You can open this folder by clicking the "Plugins Folder" button from the Plugins toolbar in Roblox Studio + * You can open this folder by clicking the "Plugins Folder" button from the Plugins toolbar in Roblox Studio ## Server Usage For more help, use `rojo help`. @@ -68,9 +68,9 @@ The default project file is: ```json { - "name": "my-new-project", - "servePort": 8000, - "partitions": {} + "name": "my-new-project", + "servePort": 8000, + "partitions": {} } ``` @@ -97,14 +97,14 @@ For example, if you want to map your `src` directory to an object named `My Cool ```json { - "name": "rojo", - "servePort": 8000, - "partitions": { - "game": { - "path": "src", - "target": "ReplicatedStorage.My Cool Game" + "name": "rojo", + "servePort": 8000, + "partitions": { + "game": { + "path": "src", + "target": "ReplicatedStorage.My Cool Game" + } } - } } ``` @@ -140,13 +140,13 @@ Any directory containing one of these files will instead be a `ModuleScript`, `S For example, this file tree: * my-game - * init.client.lua - * foo.lua + * init.client.lua + * foo.lua Will turn into these instances in Roblox: * `my-game` (`LocalScript` with source from `my-game/init.client.lua`) - * `foo` (`ModuleScript` with source from `my-game/foo.lua`) + * `foo` (`ModuleScript` with source from `my-game/foo.lua`) `*.model.json` files are a way to represent simple Roblox instances on the filesystem until `rbxmx` and `rbxlx` support is implemented in Rojo. @@ -156,28 +156,28 @@ JSON Model files are strict, with every property being required. They look like ```json { - "Name": "hello", - "ClassName": "Model", - "Children": [ - { - "Name": "Some Part", - "ClassName": "Part", - "Children": [], - "Properties": {} - }, - { - "Name": "Some StringValue", - "ClassName": "StringValue", - "Children": [], - "Properties": { - "Value": { - "Type": "String", - "Value": "Hello, world!" + "Name": "hello", + "ClassName": "Model", + "Children": [ + { + "Name": "Some Part", + "ClassName": "Part", + "Children": [], + "Properties": {} + }, + { + "Name": "Some StringValue", + "ClassName": "StringValue", + "Children": [], + "Properties": { + "Value": { + "Type": "String", + "Value": "Hello, world!" + } + } } - } - } - ], - "Properties": {} + ], + "Properties": {} } ``` diff --git a/docs/getting-started/creating-a-project.md b/docs/getting-started/creating-a-project.md new file mode 100644 index 00000000..49dad7fc --- /dev/null +++ b/docs/getting-started/creating-a-project.md @@ -0,0 +1,77 @@ +# Creating a Project +To use Rojo, you'll need to create a new project file, which tells Rojo what your project is, and how to load it into Roblox Studio. + +## New Project +Create a new folder, then run `rojo init` inside that folder to initialize an empty project. + +```sh +mkdir my-new-project +cd my-new-project + +rojo init +``` + +Rojo will create an empty project file named `rojo.json` in the directory. + +The default configuration doesn't do anything. We need to tell Rojo where our code is on the filesystem, and where we want to put it in the Roblox tree. + +To do that, open up `rojo.json` and add an entry to the `partitions` table: + +```json +{ + "name": "your-project-name-here", + "servePort": 8000, + "partitions": { + "src": { + "path": "src", + "target": "ReplicatedStorage.Project" + } + } +} +``` + +!!! warning + Make sure that the `src` directory exists in your project, or Rojo will throw an error! + +!!! warning + Any objects contained in the `target` of a partition will be destroyed by Rojo if not found on the filesystem! + +A Rojo project has one or more *partitions*. Partitions define how code should be transferred between the filesystem and Roblox by mapping directories and files to Roblox objects. + +Each partition has: + +* A name (the key in the `partitions` object), which is used for debugging +* `path`, the location on the filesystem relative to `rojo.json` +* `target`, the location in Roblox relative to `game` + +## Syncing into Studio + +Once you've added your partition to the project file, you can start the Rojo dev server by running a command in your project's directory: + +```sh +rojo serve +``` + +If your project is in the right place, Rojo will let you know that it was found and start an HTTP server that the plugin can connect to. + +In Roblox Studio, open the plugins tab and find Rojo's buttons. + +![Location of Rojo's plugin buttons in Roblox Studio](/images/plugin-buttons.png) +{: align="center" } + +Press **Test Connection** to verify that the plugin can communicate with the dev server. Watch the Output panel for the results. + +!!! info + If you see an error message, return to the previous steps and make sure that the Rojo dev server is running. + + ![Rojo error in Roblox Studio Output](/images/connection-error.png) + {: align="center" } + +After your connection was successful, press **Sync In** to move code from the filesystem into Studio, or use **Toggle Polling** to have Rojo automatically sync in changes as they happen. + +## Importing an Existing Project +Rojo will eventually support importing an existing Roblox project onto the filesystem for use with Rojo. + +Rojo doesn't currently support converting an existing project or syncing files from Roblox Studio onto the filesystem. In the mean time, you can manually copy your files into the structure that Rojo expects. + +Up-to-date information will be available on [issue #5](https://github.com/LPGhatguy/rojo/issues/5) as this is worked on. \ No newline at end of file diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md new file mode 100644 index 00000000..2c3c986d --- /dev/null +++ b/docs/getting-started/installation.md @@ -0,0 +1,23 @@ +# Installation +Rojo has two components: + +* The server, a binary written in Rust +* The plugin, a Roblox Studio plugin written in Lua + +It's important that the plugin and server are compatible. The plugin will show errors in the Roblox Studio Output window if there is a version mismatch. + +## Installing the Server +To install the server, either: + +* If you have Rust installed, use `cargo install rojo` +* Or, download a pre-built Windows binary from [the GitHub releases page](https://github.com/LPGhatguy/rojo/releases) + +**The Rojo binary must be run from the command line, like Terminal on MacOS or `cmd.exe` on Windows. It's recommended that you put the Rojo binary on your `PATH` to make this easier.** + +## Installing the Plugin +To install the plugin, either: + +* Install the plugin from the [Roblox plugin page](https://www.roblox.com/library/1211549683/Rojo). + * This gives you less control over what version you install -- you will always have the latest version. +* Or, download the latest release from [the GitHub releases section](https://github.com/LPGhatguy/rojo/releases) and install it into your Roblox plugins folder + * You can open this folder by clicking the "Plugins Folder" button from the Plugins toolbar in Roblox Studio \ No newline at end of file diff --git a/docs/images/connection-error.png b/docs/images/connection-error.png new file mode 100644 index 0000000000000000000000000000000000000000..af3c16faa69226f1e3a2e58a4c6fff74be10cab2 GIT binary patch literal 5928 zcmdT|XH-*7yN!b4D=0`+stSs9rHIlZ(xeNBbPz>~5ds7Pp(GZhNR!Zs5NSf_Aib(c zCq!x}0xvZXN`%lu!VSLPx9+;@e(V0fKTesmX3soj&pc;O#6u&Ub7y(a0sw$>x(_r> z0f3Vq>F)t&PSWq`g`Ar7#|en3&V4{hAOAAF!RVrHs15*>$1)!}o}#z^@_b+g0RYao z9$zOq!1+$}kL*5LmOf@+XCFUD@8%BhnS z1``<>$M)9a_I%{lJJSv+7Ag zFVy*Q8lRVN_ElkFSvfs(adRTYh(C^t3pO{!r#PD@p7=A)29G#9vBp_3;J zvQ13{5!5KNt-HXzSRieAjx`nm+xfWls|iM!Xn6=s$dV*hOrQ@8Gimp->>>_33&)8d*l>qfPyO>$%iN z*R7k$PxjZ}hWRC9@qs-9@(cm)f-i8YgTl{5qLFN=ppDi!q;~2GD$*g6L4s8Jk6HK4-49<53p$>K!1^C-!*mL3sp=KvIZ57vr4dljZz`RZ<>Re zm5T5FtfHUClzrgVUfT%S!q~w>4eq_RX};Xzzy3WMgl}s$n2+wPiej0luS`_HYo~)Y z&F{x=%X)R$l2YrOv_$M|K*mm2tz@m#{@NKx<}oA+stg3Cze}u&PW08S!c~J&->Sgg zl*G~&)xZNeMSMqINzit&ljX>RBpV{Rw`&mT)K$P4@ujZbQF?U^>4Is`S4}L1Myzco zf!Qakz@_kwWrC=h^-yhz9nEO*V1vji8~H<`M-;|A*WPD6+&C6p>|&guhS*%Kql)7P zeiTJ{8M~($?TZ@*#V;hCRE8afjAZuG{lw?RpcA4m?AH7zX%3qrsnJLxQ!wsXK_ zHzW>AFx>&dci%qR9ysm;(fXdCCns#keAEftF|x;{vWyQ&^R z2)pL))XQ8F)G6nR)EgO1mNqa+P%vr7PVD9~3-&sy_Zp>tRc{O_0YVPAzN)^F72UA{ zv}=LQ?nMlW8aq^1r8Rr?DA=jHeO6mo3EeNivV^Z!7>WiQy815v+6M{-?v9dTn|4X0 zuKW5v6%guLiTgOW?a<<+yp}RAhkWV-@tI+AGAl_2txRcaIUEEE9sSPsgYTA-Xft+W zq>7Dea?Z+33Sfh=z{#o_HmUR zjdLObCQJZ8ir>ea!u%sqdZ%6~qk#*)0Kh9)hptlAc{+;pf1!klbPT08?(}+umlrZ7 zpP@I+Avs21*e-Z$lvr9Khb`6D7Z5g$^5X#*uug7XS&ul4bwR1ViTBYIc=GwM-e;@R zB(JWeL{Qm#ezaiC`0CqOX|5i!zu$?koNmO*20cfuU+2!0YJAM0&-6uv+cwTOSdu5P z(IQ!UlZ))RJ=*`QJgX4^E_&=_M&prlc>l-ssy0!H>WR6I;vc4S*-@qXO2g zs^yA*JSInkA3W$e@%M*6iAphM^95X-`R|2Q>gqOQfOfU^j>ap zmFJDt&c?bykn37@G&&Vt)iE3s;NqD-e7JY-m>#E3{>eKVeKNqS*Piz@gI!=Vo!>WO z0)70iu+kZ!CXm(Kv_$g`?A$95Ui={WT7}Lf&LxUou&iuIir74TjL%=~k6~WlnxGCW zXgSgqWp3`8?TAmtm#jDjO=7?ODywZ;b7oU6amZgxv`P-d%yst1Y206GAz`r-twJj% zs-f+TZ7{a?hm3$%tv!2L9`gC7;@MJ(MV3{V(Dj$35XIbPg|ZYB5oft=V_D5Hl%YT- zGAO&Z|9u9O&)%B8wx-9eal}BWgF&dpum@PsjZO^=8UXP0zi{Db`YgGuG+#&Qsi2Yq z$SmdLt-@`_Mf17U=M>wRzejj|Ewp33$<7C$$qfz+OzITu#x@7N(#r&1*gjJ#t~}8b z$-J|?w6?^4t8n?z@5`dzcbzo#NLhdBWFMoj<{@fvsTN)J?!Chq5lZ#cKOWd?HkoPj zvJX4-R%DrT^enocdjUO3EQu0aSj27-dI{*8ob#DO#sI*b#wZD5wN6M5aeS-<9-vnL zLN9>}U4JRe8p6tA)h{bNymS$0mK-QfIC-Q2gpd~x$gmH$vPFqP(q+55J#;7aq~&s{ z^fVbq$q=>kqd0FcGxr!h(tM)bBwPjAv*8^%lq)cj$}$h;4SJ7;gVkKgqNz+*1)GNeNyDNaw(nRBPI zH#46B0JwKnQ-IFF%a@6eK2+Oep$-&*+A_W}R8*~40uK5-KYwxSJ!nFup?Os>x?^H( zvS!^|T5KC(y3r1WLh;YbxhJ!!gufG{?*Wyxf&=}6GnJTlpa`;%LNbl$nef>2b7e-`=)bUeH$NUPwGxZ!>%LS_m!VV>63W#&eGt<1vvKxw9YvwxSVw1?yv?y z5fyeNqJH3l1;V7p{FXTKz3zhhQ3PBgO?w%(Uq3f-mgQAWJofyopr&84^Y#^4f~ z0kKTY)#t~%e4c*|E>2`}KOWr3gf;vJE}qSoa<#V3J<33O)Nb5t$PD_ZxM@piRsGkN zl>QyHt#3k0viknDr0o2aM%v{-6ii1Q+|S*N?2IF)Z4@^+zn|^i zkKdKEVa34oso+ZvkHV~!Z%dCYpYqC08KV`%Cf^GhURZVYdT}AmnL2dnulRkiwDUaw zNj=R;bKN=5giYQisnSuU$XJGkGKoP3?MW&a=K+H9E-^tfB(Ni;vI7i9R`}jcL z);+AuG^W#!wY?_v&ho1+c0na+?&$hW_3wXm_-9Q{-Br_Oy;JDvt<=uvpO6z}GKvz6tEO#UEd{{+ub) z7;J(+J2J_Y={sHLW*9d%8>2bd5?yLO>ZYUnzJB6xd$x}q9%f@mR4icRiU`1<+gm>k zixj^mx4fA0_xY@8!rcF=Z{yast=62v!1xtD!K>dgAEWRwUa&8k_Lsi@+OaAPHN3_L zZa2=oWHE>!7-P^$np55h?R1+5r!&xtje4(-l462(FdF(#rv_?edtV|jN3%P#>!?pB zZB|{`56uLD*Bkv?>*j!;Y z_b~Ev1?jJ5Y;)n(?64jaUW-1oK}&!sDEd%d?DzBlzk_X9(vQYmujj|i@YpcS25kV7 zgQ|q7&i8^ni+#slXAbHNt=YdQoIFs|WjC*`uKl|x{g*n&1#sTMmEpQEpLqOj7az|~ zv%0sXKX4iIj1^?Ih|@kXv2IwKS=%%1E?Sc@f2~~E?EY}K=!^VI@iBinxHz^pji!vy zqgHZ$%**v!IPBUIl`VBzG}qhyB#aIw{zRtK$d|ClO*n9EcB=!qKa9%wR&>?Ov{biH z<{~}$m2Y|~Y1t{7XM5&q>!9H^@3;ihOc9O?S|Q3;Dzk+qFkG%AG={l3Z+|E7i>S)w zESIKq&sLwkI+qvUIRu@Ct0D@o7~O9yY-sNo9nI}p#H)lb1wVbxF#Q5|diMpwwFAb! z2#hMvIO2Dsl=9!Hwn))ItrOrpM3hH6BSlEz-a4K9946`s6hjeE+$`?pwTE z<|g*wb=qu+bz}BHWPocPj%nS;>>XCWfwQvsnOi^80#b|L$c|5FbVIqi6{l)8@q0LQ zs92(pflBHX#b>JtDRCa4=!@2mk!N58C3DqsL85`GhB1-4~w-j;+v6j)K{?@3y@!uWlx}Ur+s*PZ8Q%8@~1`RSxqH zkY0KiPW>M zT;r*$QE)+>w%#KT%L&f6Y%M?XKCo>wuw<>5ne)Oqhe%fLSch}iThn6h^O@b{%*<7 zl3Lo2PpbZfyE?S*Y0nWED66$_WE(#!@;03LbWHKU=X_ACy-40UkPu$q<6IUpF5Dw@#0r9@&t7()M`F?hnRKI~_>fS^ zxcrs-2WU;jn3 zk4Lb2{Iy;eXs05OMy*e zMjH=2%+ip^WB&%}-Ty|;VBffu7qw|utzEukO4PK&X-zUFtU;vg=wL5V$V=*7~Q9lSPT&z`H*+0?MOf$+%-3`ISfWP){`njcyP7 zR3%d<#^Yt_Y+Lqaq5$bLJbRYfzf!QTG+0qswWIQgYZWEOwV2l(fh=0RwaCT(`TIo% zq3c{0k?BshZycEAKB?7?)UQ^4P|+M%L5iw^Jp|;AU0{bhx8t=#pKZ?X==ZC2x1+jT zdX%_tr47hy*kKD@xkhX_ z)SQc^kV#FQYmaZNA)k3h^&RCABXkb)#wMPp=*u0S8BiOiRHI6w#2a>CAiIaiH*lFX zZ25jZT8-f7(#)?MM|!!{VdNplSgsTHtfHa=rRXUB4YV`#{u8aJhC|vt3?0~> zpwAX#BsH9Us-W2|PvYk%OVEDlQ?KR8<%3n-bz_aiRX_KFX0r8n7G-agr>WP%TIH&x z8GCiKtw4{_d4l6blfEOBWf){7r3X?njokY3yy-h^GQ}-Ewx&|>ef}5=#MCa5I2j+&k?4SfgI8lagA?an$>adK?L+7bHL23{B@g6sK%s_tC z?l?bgjRCZ*TC1i#Q)(8G%8F9R2>1vP5D>^R(&DNR5YSrS*GWJq@NYt1CT#E@NM}_k zQHZK>!Xxk-fVqf*2n0lJ9OAPv4EQ~~gS56Y1O!U&pC8Bp`w~;|hZrsrS}tn#pIqFH zoy;JloXpJZoGt8K4Ag<(DdG|`;vyeB3{JA(ld*5I&d?3UJ%>hlJk43{_eV`r?$%A~ z#@?|Vn38j|r2jPiwqttr8Q%=!!=xu$x;$0_jV`8JNQwlOh*`MZ?Vek31Up~D@HgRl zTK4Ek8(H_@YtAA>*mF+Lr$tlVhKQhm3SQ>^wGRxcx%z1BcW zQ(_P@v9q(mw((?7C{h~mb1o}q|0dx`zxbow_8Me3P&9u9I(f9L`u3X&_D0|9U)B`J z!}pNfy)e<N_aO3ouGgtDUn?u?Wzztiw2nZ@M7|P6=E53+lvi`##o!6p}O)j{Og7VIZ zSnsF(4UN}}f?lqU>AZvB7rBj%VT~WxBcA7lYg*~*$h#oiOA9gudxAoed>9uz$BJ`1 z0=X-EBCKNFyMtLJgWzv@e@CCOEbz5@O4qgVE=}gF_L)iD^!iyz@jHEnMUmmS*|L!H zuS>S;{GV)eu=nimY7*x*NgVNYYgbf|T-9V}wHez~ITd`vc+&P;BonCCaz(>6QKnW; zl+I1{iA1{sZqBmwah%&2Zqj~9DY8YIWK)?Ib)@S)pf}G&wV3DKSpG89Eee>L`bSC_ zER+C|t)rkbx!(DjXQA}x>}*so70xMn{l3Pyu+L-=7!EJR*n>Cglu+WLNrvBAEnp3SvATL3Hv>0eDnQgWFgJ-^{NBlubt>}%nuOQ#VKCRsYKZs9j6uGECoflF zUXgKH-RIb_zXPY)5p@5#_|q>drDf_*4X@`yVQ&6~`uoqjc^iZM=|>CRCPfEcN~}X! z6vZwM*JAd#57vmqA4xxH;OWp-qwe5KB@{JdD}J&)y%|`H>+xU8)7Y5Q)leJjp{r8P zdPxm23NZQk13?4_q4}AkFwg%#22RV&2zc}QjY4~)ciWmk(8X_qE$9EMFS@R9=K8pk zy_7jMEPlb;5m!O~Qot(Ujuhr|cD1J4+5|a|jdiSiP0iPT=K*{9LIRO`%~y_v&6~||6Lr# z#o5Wj6J}f;R%^G14!6iZ-q@^?Y>wDpmaE^j-m3jNZX9_&;yNDEXAdwuBO(i+G8Jo< zbS#QgMyo+pk`SBeB@<7ctb62IBI3TInKlAO{-zLjZWj8f{x;;rTfo%~v|(IdGGh^t z{a`|yHxysk6YH5FolxvLf~*4{k`$|rcMG}03KR3MR8k@$!zE7J?{Y|p&*wJA9)91i z<)nJ5;|3YM)nB5$9Xl&^km`O5We#T*`*+BFfd`c=`QEMF^}ccKg7NRoWjm0VshNer zV+K=Ai0x=miNt4A{T;)kGVovHEL=bmRc`k7e!B!?>vMY^-P_0K40nG1N%g3dvH$I= zI^cf*n!Q2wzacaY;9uLC9G?BJ33*>iU9Bb203zF)Yl#6$up;r75TT?&q|*EWQQOs` zOghRyGU?VpQ8W=W3S#hUpsGtQnm8ID5)LZ}7=%Sc13(AQh5R!`Lh1s(2mT9POn-EA z_(k~&^{3@^LANjVZ1#V5I0Z&=HlB2kV>=uL*Jkn&}+^h0L^9ZCqzl-V^WiyJTR!U z^Qp5!r{?KE(%)6`iQ2o9)nWCR9u6b^A-s9?DXHrw=T+S|j-=xE>)ermpwRvX+*}QU zr0{LvD*=bq>}VR>!9&fdM=E1EaF!*z>a7Qe8{GZ z0WH81BWN7k-R9)oOfmJ_m)r@}3qHtMhu>t&oHDW>9~sDuxVsm`6ek3KAXeMQ=erX^ z$Fcw?zdPzhUQeXTEV98;(Yz!JCOr;&rxCqdLydAo81qiy-L|vBMo(?-f~$Qu?AfND z2t#i~R%!NxDGKDA$aHBSY3@&JuZkY6Z?}xvUgh^{GPGq=T3K*k;H=xnZu}}p%2UUB z^qKqZ_h~f!1TI*rs&-g~Xsf>cZcCevYy~jZJp`|xK2-PJlB}}Y zA3D3%JdEXZF7J$BzCCh1y?rvBq5iJ9wqrfh?r)~kd{%krrdu@dl`6*5k z>6!4`7??-gX1^C}o%cuI3HkBw3f-+bD;GC4-5wR^e7Zx_ro)wgM%FsNi0C7UF>tc_ zxm`c!ikz{|)9N=7X{L+s_FJfRXKlxx*oNQ#NNl}3{3BY>ZqTwblA7kODBYz96vQ^Z zLe+wR_wcuS_w0bJXMtpAQm;^s+sBlUW-O_Jz#WWgfzwj?Iu=+{(DRO29X?_-H6J4( zk(W0$&uFiJ+&~O`2_9tKEE&Q#bDjWi3iY(#SY$r2j6U$xfY8DAMSf>LlQ5e48c_## zhQsfl%HD+6^_`k1JJkbb$t^pvONFhcsZ?nn1Hd*p{F#OXxm_{;^s2Pf2`OOQ`!4gO zZm51<-ph5*xw@jn$J3J gP^_yV_)_OyGr@cJsnFjNpBA%_(f zg)n-RPNUUkcc6ACX-RiV+{!X9uRAgSjiYXOgFc*6qq~bJx`hasfn;bwr_nT6HMXkx zN+h18p$)&gm(=<1QE?CRT*PKC|K*!@KQ@7&ZMU~{scjk=JX!=lMC`od=HcWFpNAPC zlL1%54K~pTq&#C}Vzx>D`3q&HP%FI1``?EG9S)-B+l5gNzZr95sQ@D9Csq|k?(c3i zV#n+M;gQ|*TaAZO`0K$;{J}UOWS0A3$4MQw>zOnnIY7wuN>AFS?qHO_(BdioiPQCM zwZxpNqsN+^>(0+d;_iFS>PhTPF3>XtbJA_(D-#K;>0pQFl?ToXJ>F$FG6C#1Dg|jl zFR*7yPEo&e-E&U|4k&U@TiLb6z8gHI=YCn4-=&0O*y==y1ELWu-|lyIhSgY&oTvh^ z9=^#vP4bC~r;6yz&bCKcGhLD>ejY)8HxAVW^Csi7JP?|{)9o1f?a~70i%cRrrJO#z zvVe=4H4$noim})a=Ow92=6m8_)YPB2Ox@FmcX$lGdZ14QdVBaT(Whpf0TqY$VsqWB zmBlnZMee8lF3Qz-2-e@tH+G_9SvmLtfgl2)<%&`T61Q8xX=#A&E8jnr+l@qf0mFDB(%0o4OsdteD8UGZk#Q#)M$-6*d-DSTl*9Q3f&CX zT*;_vu;p_=@RNns2R;}nLzXG%FN|k+Mo0kdTz)t^_qT4pwucQGy@>!c)O?28;ik$}>FkPGRL46sJRL zCg>2NJlus?PtdCHP`@Qvv-EI;*b2#g{#@?3Kc&}2UeZ8x7P9`F^hIL(PY%?AK?MggQ+IP_pM%S0^VOz~~|ojU#eYW85nlgNLpP%(l0)?zq0# zcUStMWXXq;=)(*Gtaz}YZiQ}sq0{upC~&B1S^bEskuDVo)ih>}rrv)#Q;L$Q-xvJm zu*7c~p(jPvmw}0Sdg0sedT&1*!u~Z3OO??(34Yngvc=nQ%hBUx(IKCYP>Y46WOPpQ zT+vXZJ|)o*`%v;ech^lyd22XC!L2x+j56yu-x$qD5@caGF={_b*eSl7i+B}2g7Vjm zqgSJSh&V2kEWxyN6F$gl{RpE4hKFAnS0~@S+AjQ`&BgBgJ+{IKa?W1A;F3;(aThLT zZvy?za$<;Um0jqbFX+pcFFONqB)l#(BifBtb81QgFwxpA0OB!bg!3<~$#0HD!b=T^?1)D3n2%D-Bq=hnO)Ov8U-oS^R~8V}zk$p|t4%DnQG4U*34=b56xnv}BD9 zhqfE9fh9SH10kExpRvKl8?;2xXn<6lm|Q6If>n4BU8Av^b7Z#7F8lowm7CeqkPh)LcF_|> z6UL4pRS^b7kV;RfB#YKmt|8Pshipb8uK&IWt>s#6+YQSo2h}=0u^4PBiHSi=cN=3# z+pJmnJvERpf?BRNOW8;agw|($ZdDN}e%+dR`sPwd{<$00f1=-A`3z0e$LgnrPu&ym zqSv=umlm6B38cHhSlBbcpxbo5>L3lzU0bwsVzSUg!hN$IYArQk@URKKpTUN6(87qM zx;l15M};uQI)q5PDR`-Pwe7BAVsaT5o%Pb8MjAWn&LOK<&)eMhL(RQC#DqgPZluh1 zu1_KI89rn!c4rr^?MgPQ-g;D8fC<38+ag!0wTSth$|pgX0*zpxl_x)YX-v0F^{= z6&b}F01o(ZTC(5k+_T4P8857rm6gFD;?V0h*-!?#(AtD&^1A+tdBY|MBqz253<~2iTK>0MA}fA#HxyZueM_TNfCfS6p?DcA7Ac&gd&oVN#pjo z4I&e8R_Hd{EmY~#0CpgIwIG-W`w*-2#fNzU3Yp#G&_bdwZjKjL&kA9_c88L{b*FF?B3|Fe>$!4GhLP>Qi=aPqU@(JjZf>I4 zjgoMa$wGM)&Nlo>lS)gg43JS6`&K$-H3 z9qMi>yn;Na>gBmr=Lsfo8kVnuzwo1o?iTZkuXmAcE-Uz}mbuU_@=hN|N)EElDvwQ? zYhGIOaE8-7ORe%CMAg%gPPQ!E#Wvs;ZjP@$xW?-S92Qp^&Bic1`irVD@lvZ{ilt$|PLNQF{JY(q74NaRykSXc-K z0G7-<-kSa20;8g~lp!(r%jF!8ge*I_@e4szsc4zCQ#$q3gDKz5L>h~6+%)Lx85_@= zSfH|$bdHH+| zU>X_@<@ZuOb<$A7_)F!@BjWrxeE2?pt#NPI%hMefC#PsuY9r|%p8jM6Yy|{%3I7t& ztTE3K^lhuEswyjsIuarp3?VCln9BtNd2dT>vvcKquyxgj%1!OUYwP2VxjU8jAf%5YO+Y>=#~snXkdaD)^H z9^WB&l_u%0YU(cRp#6suVSS+D)2U5Lyac_9^mZ0sNq0Td+v)5mweI}w+2XTdmiqTo zA6uP+^&t|5U*3BUa2Zm!51V)20StKcvSOf!f+&yB+z)}Cm|t-+uk708-dcapegT{b zx;?m}jN9clw>|3yx82Wt#+4%XijT`|G_0y`BB|wTKUH*56g_Wso$r1hZPD{(KD^fN zmBauTt7mp&Xmn#}@ws~Ft;^^u32C1q2pVW*e>k?I_3_-jzk6b8BaJMYYL%79Z~Xoh z>R#L1{A75=T1&<0C*K{I{d#47mzTOs`u1sdu3Z*H8S}NiR!>v3l}}Vn6?hx`{;N-7 zr?8dtU}=dmG(82;01`f+=c6^y(|toQ6{emNBKK?Q_u*4s4tgQ#u!8#Om;PxYbar8Z zi-Y5$!bbQ-isXf3#T;*&sIf%25a~Cjm|TC%SGC@(3M1Q>s@7r$5CAhh$K8hts7s; z9H|Fh_>+cyuQa3jRm1WOW=H`3SjR`Kps}$ryM7Blwyj@ zJ`)@hdu--GLc=O%+=@!{IVh{te;Px1;0DgZ@eFdcLH(ms=mLXkhV|K1r-bcgCPvsQ zArs#}WjXoSHll$em^l5qyPW!*N)U=rYmM`pu|Qr80n6twZ*AZ|!KoPv!0Z7bzr z>48vcBAX}*i?*B90R!ybFVHpo1kY?jrUF*E!S?Z&x4GH_mU5GLGlklXvz6N8z_^sR zU!!uJ6H0Ao%S|kmy2Pic?!^LEIaP}73{4YSU~gDTCJ6#|3yu})0dg_d^`|fvN~21J zUxwm}im2k(x5?f8$lRZ0b0kp z9n<0`hSgK%!FTO#&gY5a&YB*L9grlV2qO6c`dJwz2(50DR}DAwZSLD#hd8_ky}P2a zdQqB4djK`>X{vSJU`kW;@)SZa;rVfbRu&do;0S%Mnb_v-Ui<0icUR6;ci$U<1;f|x zCy4&*tp`2h*4SBD!3@^taMi0ZqG+@V+t@+HN;&&h<3nK24%W;-f7c%){KC{7?LLl2 zO<*?fDA5;}$rpWkzK8ee9jef-7uiz(fMgEKp-+Mn-2D+1SB&_bk?oOiU2v<586aPn6&FI=~L6C?6E*`ycaM2az*w|9Jm11s7~5+d!X3@KD=oDsv&6fH)U<9~=uwLV#URKV6TWE6ZsAd6%Us#Q@e!-d>~c>J>U_8*8bF$Y z)(nb-gE4XEuou_Rf%G?E&u6$3hVV86pq*6>^=y38XIyPbH_<90k5JJ`>5h*yWNr7s z*Y(XEgItNA_12_t2^678FXPn#h8`o?fEkXYwic`d!MuMI9Njh&uAYlitVop z;Be(Hn0B}vCBAlb50Ln0(siK)sP2v(KEddprH^BOwPRb(Z(Nw*Y*#w0;`QsdegdoR zFdYEw>_yH4J%RuwG}&^-8&tFESOs|~C6dfLQlqsH#IowR(Sap<`sQFC0v$qHUt7-W zCzV4Um`*KLp2@6dyEE?*X%Wp3uC5r+>T!g8sn~;h`JzkiHL=-y*~}m?FcG7b(&^QF zV?$LT3RYuU6@A{n!o?z&aF;^!I&QhPC$crMd9qs}HeT^P8Rt8>C0TN_Um-Si6`Z;K zEp)n6UtCyNSXqf|ND`b(RSWESe0+30o@X%VNR{Im7PwpORW|^-fPli9lg9I0)K6Q} zwvyg&bz3&4Wjp2_O+vMqWvprVU*AK)4+_$Ma);C|07gGZi3f5Q5 z(A)&Aab^kG4(DRSr}l{^sioVq(zVv8k6eBWP5$O9&=qDIydLL9*Y;I>;9$QXN-Ko) ztG!~&&#UkS#1PbYa>g|(+m%Q{#g|+x{jtIe{MVmOWmez-54qWppLO&Uij#u_Tx21= z)Dnb9%SF#){a_@tH$y>Ml%y6Ytb*7>3jzyd$a*E5={VP3u2$o$Y57}cFh)O7+pNxW zN>-8xrgBvWA_A}{FnTZ;pOn<5+{#`LPi zvuv^)Db16HF#1}nJKlcZrxt;aFrM?puL6k{XQcRu__2DH9GP3L+ZaKbRZBA)HQ7~7 z220|%Q7^^6w?-o6j_m2o)!XA5I5fmSc!?edD8&QwYVOTG=k+P|LS0^a zvHK(LguE^#;LXQ}?lH~vuA}XFe;Yk7x>qywf}gZ>pvCNwwC^LKq}_t&W@k_U2_RXd zuN0aoNjXHoY%n;%G;h$Z|5UG(ln08CC_ybtP?w8fMGqRyF1ID=Xo0Spk9OlumZ}O! z@oEa|_>5|E_U=-(ySTh!`Q`Qz_UVqUf~CCDmt>J#LnnNEC46EfUsGF(DKT9c89xXw zXn6FIDIh0HZN3RrU$i5=l_i`yEC0T`z2>Ac-1afv^&mw4DYuV^w8>!Y=jVlU(C+e4 zne_q-!S#G3;_dIT`PIt#)189rn-|WCKDB82m&tX8u?YOmZ_a+JL+lka~TrMrrd!wt0t1Bo*7 zsyh&RlHobz8XJKEg_s{0h4wbjtooSz1#P$QwdL2-yXq5gbn$-DpY*6(_$^QoYHXl@ z7qA76Hr@?vyNvbsijqZNR$`nG|?6b1}+R<}BE z6Y&{EVkugib9~e?X3S{S=a}z>IUIH-;hGE-65oTgz(MIYN#!;HE%{L^E)-UfbeS-y zWT))xFBs&M37?y>a^%81G(iB!+6@PdbfWAd!sUL*m1{v*9;$jn7I|mTO$8Gg02K!t zPz~g(X2>Q{_RUqsJK zLqFvVR8yV(geB?^ho^`_J;*q@u$E>IV>(NfRnHx%>(XG}UG70sb+xss5rN8XGc~jV zaorZ6CBv7PYwsSss!^D4$atS>Y*PSx$jwjUs+P$$b>!SG*1<+sZC588V9@%BEfPMx z`T@Vy93BdtGg4@la?um#q^8Q?pcz7c4zCm=$k{H7ogR+uLllD(f{P8 z)(cgYRaN_!pPkM+@0|K@q0V~ACXIiiMxTH5*SmR%S-7Q+RKxZrk9k#L`U&SkypbEA z>H>rOAy-q7N;W-|RL`O}waPNPoRXyD)=;?1wCN(3=*8Xxq77KCXU*UlO(E<-WK)Nl z)jVKEuWWLb-8fLu)L&7HlIa{#0|5eZ+R#44q@rRmYxo2olFMm)0b`8TU1v zSeCcb{W0l^+yS-IZRtITp?b1}6W%Su z?j}gJY|m_(5hr@*H5@Oa$>S5_IBq>kZr)#D7Q_dUDF^m@mynW(WL|vUr9}pDTTyzN zAr+Y0H!=Ra#?X#r{Lvk2Kz6sKg^y7~8|{)Liq?^M+x~vr){Mb|iA;-&n?wVdGzxWc z^@*rQFhKO#T_9F5nnBNHlz~^ z4h(>Q(*^_3;T`q9f#1Vkm+zAkB+Z}IK4Ch`q3-4a)Mx;Z%7MQ<6TnHtJ^cLgGJ+6j z=Bzy+j`!_QdOEpVs`q<2)z@9xP=2-jPzN_OQ>MzhZj^0kj)SfH~ zoZcV1V2}xz;s?l61u{TN$Z@)2UHJF%9GZX|PvRsSHn3_&U+1iZ6EC_DQgb+1{YPPTV7u^!Kpdn5R~Y z!`9D8%%{7vjcUX1>z&>k&JzM1-D208?rkm^Q?dH&nPd8{&wos63T#r=q?oF?Z<_~T zX*{1k1j>gX_~ero=mFa>400`Y5v;2x=+cjmkH24hwqJEyvGw6&Lh(0Z@*nxwWCYjx z{Jka69+rT8*7FD%%{lAkC?j*?z+*-A4id?yq~c`O`FV6tZ2Am6vuPbF6sujN8S+UO z0vu;qvH;5Lwkz38b+|N94kgn3UQQRR{4?(t5R(2ka@Y^77@?-(od1M~>}6KMRcJ$PS6$iM(580!NQ=y&<5+Z*|6mLLw! z;1H{bKXM7mb7BbeLgfCUT7OKGXEVuwSkd$KX4r6(?TxZe!W<7Xtnfdna+Tq?OT1o1 zg#25_p#kXX=(Hq9Bf0ePjUj%uyQ(MA^yhbzdn&r)i!*Gh@{wPcIWF5Y_rdc|*d zEHA+mw4S$_REnGa&W+@R<_CMof7>VWJtGue#YI$EGq9!<*VVvYdFE}YX-I$o*Y*Ad zYv-@q^mKoXI#i={`@-8VB8!ABKjqSx-3 zUnv~RtgNh@N=v}?fgs+H98$Q>I~b987#~Mwp2e@YBK5zjg2LlV4{E4$^CM>YgKV&Z zCit&LbJ7CHxcP)G2g%*nTs6VX4d9Y&yZhO?(A$;J*-G=--S;=&_^=93ac~-PHFmp> zxm#VLAM=bGpAQtV7~Ed+NH8-k#;V%Wmkoq2LF7~Ru3l?obcUM>t>Jlsdv@oM*0jo@ zss~3BL3=-?{}&AaUOql@D-jFgm$-)(7v10e;TK>Z@}&b8C|lmuMLbOkDI#6V7n=K! z3uO}&cuyeYC;GKSI8yGGrKk8nycKtFkbF=Qgy$gTu-sr7j~WTKq+m2c9;e-2RG|*% zgK==~_OfUAYIa?m9zY|C77#W`$QucC!O#bW{j=Jy0Oc}XX=wuY5%#pB7oDy5Z^bcJ zMObdcSV4PoMTX6O@3Lbfe!q9hxj+yRwh}o+xV34~nxC6HI>SvCros||DS`b0qQ=1n zUT;k9C)%;#yNv%O0eePi=FspR?8QN%T5dxw5DQcYf4hkAL9=J)IKz!S!7V0R70vjf$^& zZ7xGM?oviGH}e)27#EmZ*YQ8WUTzDOV)joK|4ZZ}IHlJwzlD;nL_;#^;M{w>IgWfS z8V@lNkCp&RvahRf%Wmnc7ZxxFHOn0DKR!8?l4Xf9hw63O*)NjJeS9vb4$WhquR@gZgh<0N z?XTa?2Xl!(B)5f<>hvTbL&)a|SUQ++^FjgcFia8E_%55k;Pg4ofQyhvk&FGT7v&dp zS~+3dCK8fdxSLkvcpqGtv(ZGsZke*h*K9%)tpfW1!LTM{JjIL%F5~p{1p&pL5F=k- zfrS99osDjqcNhrdfX}`(dLnOH(pL6xP+;SQa5y1T9fzb3Z9RAo;82H?Ni2@K7Z7Sb zO~Q7GKr@;1=o%%Spi!kpSY#2rGq%9~r zSB^6`t{3GF??)}6FX>=WnYpcMeCee{3YU}{DB2?Ni^?uu12#b)ccuy1I-tM;S^(e9 z901;IFoOw04<*Hb_|LA%9bqVGYl`(`Igj3mch8*OAc1EBuCz>U9($mPSb14un0z%s zEDC%ZL5DVDFsw60?=I;(VI+X@=FS7R&7t=E=o*~Kgp(Mz1Wcw<>|qf5G+I4GZcs=C zvuRqmnj#!ULqX3wNQ54WZe|<^B&UlYYup4U6eHSE0aVaohXY$|ye{AG_1KOfG zsp=ky+8UPPx?tgdevTAKy81=*qGp17hz)c1jr>am%4~dMgvd$_fov|s`=dg`8!?LH zNjS+Vqv7keygkC9Zml+gZ`vrqj}T+`;w33tk0+g9D&{p z^7cue8KGv*_K$>$b4bz_GQn)%+(9Pb|JY0Nt`dzeT9S(Fd{lvvzJb^%T5!8%;H71t z;g6fgU>#hG{p2YT%ri5Uc~in8`l4#b?FHm2A$b-vo)5)xQ8YF=o!ldqz&Y53mZ<)e ziZx}8fj7kz-hKj4)i;2hvt^;liq6kb{Xaih8WaJ5z?h&(Z9|#VmQDRM*l(RpSUUyd zv8Fbj9EkQiXbq;?`R~RUMXQ^3+}*6c5P*kUW1P>Qc9ba8i2bmV;e^;w2hIHi;xvn^ z81cfL$`AxRpdXMK>0IMLV**^lTE!mtdM0r|fqJFy_JuddxRWLc*2Ro;LIFMz9s-k{ z1*RJ^@@Jd z!Yn%bsLpFZibZZJbIIE)HPDLScq}B-V4X)A-bvmcPt~9lcE>ywOx8}oV>seWYTe84 zMWwJ9vwhzS>$kh9)sSUKK(mdW9z0S@B*=5dubnwdM6RA>XaNqHha()MY7B)gc5f48 zrOSgAUR5dCQEV~{oKC7FW2MtYjIjk=p&SV>K8k&^D%6=~E7924Y$`!PiH!7s$Cf;V z?^nsj3uogI3)^>8vEzY;8RIrp%cv})()lG&{`xH!xtQ}qk@1%+vgJnQT)yL&y!YSe zU~~z!h5WBoXvb?y=yvbF?O3v~G8t0pcNx5#=9vk*q3(Gs|01|8FIXLX&{3S!o6EfT zt++hvA^HJ?x%)7x*_lHs4F_x9kpS=hE4ruFg73Ra04ZmK{1^5Cy}Y~K>~<43$6`pfD-RPfuVFUE zB8NjUe@|Iza9xj7nN7XV3K^j&?aQHS3tX?CH^eHKc#KF#9S)TamT1R8D5%%zCZ+Wa z9ZVI)N5^mu#5W*7d|$&s<%kiz-|q9H@|<|sGHL(y37d!ylIw^52&J9omtZHFMm`Y^ zbJ0)dCiAmOoQw7GrlI#8xtL0((&@;cHP%>4LX5YAtv_-`8I??|ijw~_x}R7QbGN>OPaK`pP#ButNHBSXY$`=e-&F@ER+z@{s2qc>r{!sBfiU9g5BE5!+48>e3A1jebnH8qepWt)B}! z#p`XI+!gYx52iF53`$wq3r74aek#DxMUNfg@LD#Z#%?nigAyM_P+5XAPv}OIX1JAB zLm(Eb8lAe#UGCB^%!a$xj3Hu4Rxae}ua4ZoY!pt6nhHI$<97TL=t_-wUh_%l%&oa? zx3K(5-}Dh-((A)oXAo1gEC+nP86z~9(04*9nHzQy@+Vh*aIUP)`%q-!NPb|=BQl~g zarzX20ag0 zcuP4~V;wy>pP0n#+=Qh_4a{s4FAeR!qB8!?Ex)0CfJ<0CkqO$5-&u9`0DMrBN`-Km zJ;8J8FcTw?&O;sYB7eE$Kg(6b^|XHrH7NY>(9yd z&e`|lH~e=IQo{2y-e4+~JB5c&%1$-e|ByMYjZG+BpM@L*Fq_`F*IN*!aQIwER{T7z zy1zHlBeo>Vv4DSE7}=6=)tH&PH&|dyqfLcz`bUqMT^tu_n9X^;UrB}%E=W74LJ(pc z=@X*<;MK-fR78$^BE02ZAmflcHjMO4?|=ZGZRwA!e`x0}J!@+-Sr4V^+qQ#~D;qA_ z+b^`DA^)33r~_p`!14eVs}Hv!F)E#uITFOSzQ0cti?OX!lVT>W2L6iwAXbJM@2y@=ma^v!X4baruiBe^}Ubii0G+%~*hn>Rd zJalZG|LXCK_B+DGr4N}BvWS-AMjw#xY+tfy|Ik; z9^T;UJ;Y7I?qq@lA3*0c4y`OmJi70g!Wx5`TPUKaM$B9X>h0(YrnG?*k+1`hpe|s3F$pJ$u zKmBoM{0QVS#bFr^W?VQwB6`Tcy$dyxZrd#YJF4HTs{HO?+i^^!0%`I7e`^&1_pki1 zHepaI0Iwe^K!nlYzrw|Qu;+vMA3`XiKQ+2-oFLkVL~lI#s{UQS?cy>r1UBkdi~LlY zzw-wn>b}y3Z%N;mq0@wB!Tp&)1{7(Dk=xZxbLwbH;$rE09fn(DdHD2!=|T=uhOqek z0R1XUqMsEc|BsDn9SD~VsGPYEr+p+R4k9Vl^yIOZ9S&H`*=AC-dL!-0KVZZ0dg+e$~nqK0;Ay!pP4n;tKiTGqGgM_61Ytceurz^nL5I64(3 zgmD=M{gdQ`StJZSL|GtlNMQk+^*^@`f&qtpIlb8Luhsl*#j10#z&XQT5at(EwjGqO z{2=$kGU!bdKAtU1F9n6*@32+_w~Wwe2`Y{jtu(B8xs^o;PH ztx+{C8TXUZzJq!&I0Vnr)FB)?GC({~_!~h@j1WccLm`Vud<&#Q75HQ+yMOGiuYuANW>T=JGO zroN}G{<`aRT=uC9wbYuy) ze#)>%I@BL>Y?Kf7Cd=c(K6?JcFhAc(A)4W^>l>Nq;`|`lvg9FuiU`$~6nENCgj_k` zaBm11q6%;y;cpejSxOlM=FUkJyo_7rHNW1+3Z-2CJpN+m=z4*6#Sx^&o^l>p2{kFI zfi+u*KQc4VLoh=aepp&mQM29M^yehhj|}|te17B1Q1Ybwn|-lcQp5?uczLHcr7JBG zxuTnX9hfg4Xp`Qg(Fz?H&QuYwyCFc*w_b1+Xmyx^II_kEB7b(*C_+j3LMN|6`K4Nz zM!kHeGKP01Y{Ps>1M^+`NEsc>H-AzgNN}hQ3nh;a(zRJZS-MG0&r}M5mlRWfeqUN< z*@K*Ik7S`wYe<@eiolaCBJqP8agVv6SCUUW-tznNCyrKR=`d2F_K)NO3q*kh4l?Sb zdq0@Q#Df3V!h{#=_lytyrFr+h$x@5`r%2L__Tj6z*BD@sjr7~M!Td?KnBU^Z3RFjh z>FQ&9s~??4CzDR!(-p=c4HoHOzNd`2;=mjzMF^Y8CC_;NU~r+zN!jb;eEvs;tN=4n zBO*I-ZY`wIQ_>T9=(1c-7c52<2Av^lPRat=fol0JFH%7?q1K*XRcj!AWHZIuzlmYE z`JGUZCd#NF@S*;ZnK)Vy4>UM}NF4MyLrFpL$fAR|fZ=IB6yJtHjgP=$3}~h0Q^25- z{CE8-(jaLi%E4sMmS(5CjGCr!F{o*ES2c+26z!IE9x!Wu8xq+$X4GvK=|w-+Z|wII1Kp0pmc|hWqIP{ zFhel$V~j;*6mpb}wcwpx&LUD>#6Bew5^W>SyX1n*^>T*0inVJl;Fj$z}{!LAUT(m^sKK{#-gw%TZm5eoQ~&ZS z>I>#XUx#`eN}yDq9y$g(x^~5v#MJY}AuqCEtm$PJXwr;jSv(Uvyk_AGCHleTWXiDC zcHvOKa8`=y^mp2(GrrL9Ui9SYlYc$O!lY9>4=6ImCgho5=ELfQH>Togb{ zI+{AuGa1c!3n!T@aLnHa<1yk$!cs>IS&rCz0tA6_e4<+x7MZj$7K`StXEzMyepsNA z%&mMe5Zo`1ZHU5E1=Tp*1mQ{k9XseB0ehas2e}QQxm{b4t@%ZH$;Q7GK7l(~WF`WO z=D3Ka0M1HKP5GkMXHKwK*yNVDL8i9aB}b09V6sb^^b4Ueaf58AXNwTvrKciF>eKR) z3mzxqL>s)QIqQWZ4b-8~vf>~6Q?Ihs{hby=c5<}h_W*$Y)^d4*@tuZIY{{j#aeQdXJR_WTs50^%+36MXk$~BGR0J_0thwM=wgqMc z>XmWmo2;7oVJ_dC1w9Iaaqfr&km2g1%6O_9ftwvAbOiIg^0qrbqGXIk)0pE6>-D-R zyIGOO`y?kKY4a+p_y8=15EcnFVNR#Qca!Ktn{PZon)kA*i~yn$D$ba+GGy&c!CywF z2pA~&t0sH9d#g7EIA{r!y1eO`i%8VMx5pS`(^ipI??(fcCwWzdp!$SrNv)H<;T@a~ znzr=PJUO}mr&I`7qzuGN@iWYi*)FhS8r&Xd*)2Bpvc<69DTUE$bs-j0nkntp{j8Ip zgV40k4x?&z?k5!9k~B!j^P3so-?s__AHVQio;9ruNaMvHCi4Y~9VFWD#kG=z+gm}a zb~%!M9`YB5v%`^by@vhGNu09=*7)Re(ubd!a0A83TfaV6#>bT57^H;|FUsP_Dy#WM z+3d<0%LuC^s78s#I|M!J1}j(x9T#ADKH^ z;in%c_ql$%1w?8+e>0)z5Mj=XII20dIhvp4~1zYp@!zQ3T()NjJe+OS#BK ztm{B-WS{qIM*s!BuOB63-!R(hSlJ_SJc-iM`aIQghN_JU8rkHLr*{*7U+BeA_hQl~ZbgM?NRf=p zVbbof0E9d^?CsaX44Rz>2!+>H&J!S&`WSG}(;L`4XxfY7shk@#K;J%COQRrcq)kKd zlpIDPjk7A*gdu$7KbU+#5E%n2dAQzI9v4bO3zV{q`clKnxhh982_-#XEO63<(JEc; zT^Sd08m$zm{yD#Nn@QCIZf7fB(aK~DJrBb2 zQav*msv+jKTX$CL%hu4Cud>6*!_)X9^3%|WnxVtrKosgk0^ZxdXs|ycV!izgLSj=n zcSzeWP{10eSZ7WoT+R&dpRr#}SeRn_jQDX73x)c7P{RDUxz)4H>9t-oH8eh*MUy*r zOfB{tP0h9r4$^+<{wgv>Mc&HEDj4l12G3E&v}x}KPV&|{gnyI-m3`qwMX(pb&{iS% z5RHwB)x+V^1+G~ZvQ2-bcO)ggh_sUF>a((HSI7~pfFAQ^qhtVR(|8mhu`F1nYlM8e zqf(*E{dOjBP2&P%N*#;7M&wNLGo9ya8U*&Do3Ki4k}61R_unjtwyiN(E`WE({&wB_ zoboKJC;4hTXTFu7F&dSU2GE-%mn)hy8K}YdzxCcrw76}r!;sqJhLW9yiTrbYJ{l4v z06sQY++aF&@V{UFU#S}-ocgU2BT|GNPx#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D01|XXSaefwW^{L9 za%BKVa%E+1b7*gLUR4MM000L9Nkln!;j3Q&>b;lYGkgxkPum$@(K^K2$e% zpvIUeHY8N(KCRa8tI{5*(SKcMkPh2daW5JWBSctJmSXN#nH4oymOZ5PKB2O?hv(d# z+Lf|COMIE8pxc7FV}uB6O2>5hoi+&SB~|&!aoKxB`CrC0*NazilG{M51SOkX-c>xo zG-8JcYf6z!UhlOH^>$tP?9Hrr5%&YJLeXJdVmuu#)OiT{>>VvvA1erGq9_VQJP&8q z;=uKxI^{yyiBI#B-<6#DY^>}!Tp=zxx=(HOk~ID8wIR7`@q^$0K?7oh2Q?KI7N(}A z5(I(TGz~Fiii(O*J0$Uc^vP9AlJf`Et>uo6D}=HLt`Jvb9#qcaBt?JnTi<&*z16)& zG$2L@(&Y7e!H7sC@|ofsaT)04%0jT?V%vmirLdx5^!gF!pqLz&z!l=Wl7?23^7pMbKR>PiSMdm(O}-rz z7Z>+PjvOoQZ5a)}*J?gaRm#kCW@Yt>Kg(0H3$OOBrsNoRrrn!&dbXayND|H{LHxTU z;4}M@e2%xoERcoi_6-0{{3H;=-rez zIQi2U{Y5XGAfrF5r#~vEvpeYc6Jy{1T>r*V391$#v?e4-XfFYb9&Uk2TsJcXvtgjY zPZ4T)QI3dy)UI_@%A z{MXItE8DlGRiSDDLM;QuuykQd{s9PP9GhX!Aa;t7^E00KoSKmv$eNlS6|Kp>{g`+x zXS+D#+g<71`y1(f7@bf<@2R7A!-hIHoqpu(T){ir(kjsa0oK(dV1tKQr4ROK;WJy3 zlF$_E&CmGcMzF_L01?x4p`vqh@}DWcl;q|9@zz(jUOL<-N*@xX4~vcuzIwF(xt+B) z#Wh%+c;~SYn${!m+zBQ~AGW5;$0lN$63&P-O7Ectio+C_tP#lB3qa1x#>wKihT zPMo?X|1PT@4TvcscQzU46VuDz{^sgy`>(vRH~YoiSxjP4*c$*<8rG3)jcJmMN_9{QT(^X z#DtlcU0l6buQ^$(LUkeFp2H*m1kMmGni_^oO=Alqb9l?7N3QX-Pvc!$PoDwT+g#~Y zqZ;!vs#}wwZ*>tTS~T70m{RKOpr%>vk*Ph3DO@q-xu?aaEz2c}X*jb`-J1LlG?5fl z)G{$?a>~^1R<#?hGL1(*<>}Sq&CSgU76?$a5EyzV$G<=bcqQUjCzuS6sL+HH4o+LBQ?Xx4{m8VOW2Ezg#XaD=S08g7_b3 z%9He5zdJInThv?c&pX^smsci}!Odkf8oRo>R4UcvsaXid$P-mzI_+7K>i5pO~0{BOEet1x@AUl3xIBIKaYiVgIC@4Th{~=MT3I4Rf!2~xN+;KXc4vuXw z1^cL{r)Q17bWfHj)#RhJv=kl!;AtSt|Mhr6M7t&cPAC91o)R&j>FGn${{qtuuUA#Q RSAqZl002ovPDHLkV1nI2o$3Gp literal 0 HcmV?d00001 diff --git a/docs/sync-details.md b/docs/sync-details.md new file mode 100644 index 00000000..40dfb285 --- /dev/null +++ b/docs/sync-details.md @@ -0,0 +1,61 @@ +# Sync Details +This page aims to describe how Rojo turns files on the filesystem into Roblox objects. + +## Folders +Any directory on the filesystem will turn into a `Folder` instance in Roblox, unless that folder matches the name of a service or other existing instance. In those cases, that instance will be preserved. + +## Scripts +Rojo can represent `ModuleScript`, `Script`, and `LocalScript` objects. The default script type is `ModuleScript`, since most scripts in well-structued Roblox projects will be modules. + +| File Name | Instance Type | +| -------------- | -------------- | +| `*.server.lua` | `Script` | +| `*.client.lua` | `LocalScript` | +| `*.lua` | `ModuleScript` | + +If a directory contains a file named `init.server.lua`, `init.client.lua`, or `init.lua`, that folder will be transformed into a `*Script` instance with the conents of the `init` file. This can be used to create scripts inside of scripts. + +For example, this file tree: + +* my-game + * init.client.lua + * foo.lua + +Will turn into these instances in Roblox: + +![Example of Roblox instances](/images/sync-example.png) + +## Models +Rojo supports a JSON model format for representing simple models. It's designed for instance types like `BindableEvent` or `*Value` objects, and is not suitable for larger models. + +!!! info + In the future, Rojo will support `.rbxmx` models. See [issue #7](https://github.com/LPGhatguy/rojo/issues/7) for more details and updates on this feature. + +JSON model files are strict, with every property being required. They look like this: + +```json +{ + "Name": "hello", + "ClassName": "Model", + "Children": [ + { + "Name": "Some Part", + "ClassName": "Part", + "Children": [], + "Properties": {} + }, + { + "Name": "Some StringValue", + "ClassName": "StringValue", + "Children": [], + "Properties": { + "Value": { + "Type": "String", + "Value": "Hello, world!" + } + } + } + ], + "Properties": {} +} +``` \ No newline at end of file diff --git a/docs/why-rojo.md b/docs/why-rojo.md new file mode 100644 index 00000000..b6872309 --- /dev/null +++ b/docs/why-rojo.md @@ -0,0 +1,21 @@ +# Why Rojo? +There are a number of existing plugins for Roblox that move code from the filesystem into Roblox. + +Besides Rojo, there is: + +* [Studio Bridge](https://github.com/vocksel/studio-bridge) by [Vocksel](https://github.com/vocksel) +* [RbxRefresh](https://github.com/osyrisrblx/RbxRefresh) by [Osyris](https://github.com/osyrisrblx) +* [RbxSync](https://github.com/evaera/RbxSync) by [evaera](https://github.com/evaera) +* [CodeSync](https://github.com/MemoryPenguin/CodeSync) and [rbx-exteditor](https://github.com/MemoryPenguin/rbx-exteditor) by [MemoryPenguin](https://github.com/MemoryPenguin) +* [rbxmk](https://github.com/anaminus/rbxmk) by [Anaminus](https://github.com/anaminus) + +So why did I build Rojo? + +Each of these tools solves what is essentially the same problem from a few different angles. The goal of Rojo is to take all of the lessons and ideas learned from these projects and build a tool that can solve the problem for good. + +Additionally: + +* I think that this tool needs to be built in a compiled language without a runtime, for easy distribution and good performance. +* I think that the conventions promoted by other sync plugins (`.module.lua` for modules, as well a single sync point) are sub-optimal. +* I think that I have a good enough understanding of the problem to build something robust. +* I think that Rojo should be able to do more than just sync code. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 10529937..703712bf 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -11,8 +11,14 @@ theme: pages: - Home: index.md + - Why Rojo?: why-rojo.md + - Getting Started: + - Installation: getting-started/installation.md + - Creating a Project: getting-started/creating-a-project.md + - Sync Details: sync-details.md markdown_extensions: + - attr_list - admonition - codehilite: guess_lang: false From 9cee587f22fab738122d63cfedff4b31c4daa353 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 8 Apr 2018 00:16:21 -0700 Subject: [PATCH 0101/1504] Remove documentation from README and point to snazzy new documentation website --- README.md | 156 ++---------------------------------------------------- 1 file changed, 5 insertions(+), 151 deletions(-) diff --git a/README.md b/README.md index 79ee70c4..767399d6 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,9 @@ Travis-CI Build Status Current server version + + Rojo Documentation +
@@ -29,157 +32,8 @@ Later this year, Rojo will be able to: * Sync `rbxmx` models between the filesystem and Roblox Studio * Package projects into `rbxmx` files from the command line -## Installation -Rojo has two components: - -* The server, a binary written in Rust -* The plugin, a Roblox Studio plugin written in Lua - -It's important that the plugin and server are compatible. The plugin will show errors in the Roblox Studio Output window if there is a version mismatch. - -To install the server, either: - -* If you have Rust installed, use `cargo install rojo` -* Or, download a pre-built Windows binary from [the GitHub releases page](https://github.com/LPGhatguy/rojo/releases) - -To install the plugin, either: - -* Install the plugin from the [Roblox plugin page](https://www.roblox.com/library/1211549683/Rojo). - * This gives you less control over what version you install -- you will always have the latest version. -* Or, download the latest release from [the GitHub releases section](https://github.com/LPGhatguy/rojo/releases) and install it into your Roblox plugins folder - * You can open this folder by clicking the "Plugins Folder" button from the Plugins toolbar in Roblox Studio - -## Server Usage -For more help, use `rojo help`. - -### New Project -Create a new folder, then use `rojo init` inside that folder to initialize an empty project: - -```sh -mkdir my-new-project -cd my-new-project - -rojo init -``` - -Rojo will create an empty project file named `rojo.json` in the directory. - -The default project file is: - -```json -{ - "name": "my-new-project", - "servePort": 8000, - "partitions": {} -} -``` - -### Start Dev Server -To start the Rojo dev server, use: - -```sh -rojo serve -``` - -The tool will tell you whether it found an existing project. You should then be able to connect and use the project from within Roblox Studio! - -### Migrating an Existing Roblox Project -[Bi-directional script syncing](https://github.com/LPGhatguy/rojo/issues/5) is on the roadmap for Rojo this year, but isn't implemented. - -In the mean-time, manually migrating scripts is probably the best route forward. - -### Syncing into Roblox -In order to sync code into Roblox, you'll need to add one or more *partitions* to your configuration. A partition tells Rojo how to map directories on your filesystem to Roblox objects. - -Each entry in the `partitions` map has a unique name, a filesystem path, and the full name of the Roblox object to sync into. - -For example, if you want to map your `src` directory to an object named `My Cool Game` in `ReplicatedStorage`, you could use this configuration: - -```json -{ - "name": "rojo", - "servePort": 8000, - "partitions": { - "game": { - "path": "src", - "target": "ReplicatedStorage.My Cool Game" - } - } -} -``` - -The `path` parameter is relative to the project file. - -The `target` parameter is a path to a Roblox object to link the partition to, starting at `game`. If any objects don't exist along the way, Rojo will try to create them. - -**Any objects in a partition may be wiped away by Rojo after syncing! If this is not desired, use multiple, smaller partitions.** - -Run `rojo serve` in the directory containing this project, then press the "Sync In" or "Toggle Polling" buttons in the Roblox Studio plugin to sync into your game. - -### Sync Details -The structure of files and diectories on the filesystem are preserved when syncing into game. - -Creation of Roblox instances follows a simple set of rules. The first rule that matches the file name is chosen: - -| File Name | Instance Type | Notes | -| -------------- | -------------- | ----------------------------------------- | -| `*.server.lua` | `Script` | `Source` will contain the file's contents | -| `*.client.lua` | `LocalScript` | `Source` will contain the file's contents | -| `*.lua` | `ModuleScript` | `Source` will contain the file's contents | -| `*.model.json` | *Varies* | See the example below | -| `*` | `StringValue` | `Value` will contain the file's contents | - -Any directories on the filesystem will turn into `Folder` objects. - -Any directory containing one of these files will instead be a `ModuleScript`, `Script`, `LocalScript` containing the directory's contents: - -* `init.lua` -* `init.server.lua` -* `init.client.lua` - -For example, this file tree: - -* my-game - * init.client.lua - * foo.lua - -Will turn into these instances in Roblox: - -* `my-game` (`LocalScript` with source from `my-game/init.client.lua`) - * `foo` (`ModuleScript` with source from `my-game/foo.lua`) - -`*.model.json` files are a way to represent simple Roblox instances on the filesystem until `rbxmx` and `rbxlx` support is implemented in Rojo. - -This feature is intended for small instances, like `RemoteEvent` or `*Value` objects. - -JSON Model files are strict, with every property being required. They look like this: - -```json -{ - "Name": "hello", - "ClassName": "Model", - "Children": [ - { - "Name": "Some Part", - "ClassName": "Part", - "Children": [], - "Properties": {} - }, - { - "Name": "Some StringValue", - "ClassName": "StringValue", - "Children": [], - "Properties": { - "Value": { - "Type": "String", - "Value": "Hello, world!" - } - } - } - ], - "Properties": {} -} -``` +## [Documentation Website](https://lpghatguy.github.io/rojo) +You can also view the documentation by browsing the [docs folder of the repository](https://github.com/LPGhatguy/rojo/tree/master/docs), but because it uses a number of Markdown extensions, it may not be very readable. ## Inspiration There are lots of other tools that sync scripts into Roblox or provide other tools for working with Roblox places. From a563e4c381fd0d85b69ac960b2834124c61c7150 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 12 Apr 2018 00:13:09 -0700 Subject: [PATCH 0102/1504] Update LICENSE --- LICENSE | 353 +++++++++++++++++++++++++++++++++++++++++++++++++++++ LICENSE.md | 9 -- README.md | 2 +- 3 files changed, 354 insertions(+), 10 deletions(-) create mode 100644 LICENSE delete mode 100644 LICENSE.md diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..7cdb712f --- /dev/null +++ b/LICENSE @@ -0,0 +1,353 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. \ No newline at end of file diff --git a/LICENSE.md b/LICENSE.md deleted file mode 100644 index d9aeb8a3..00000000 --- a/LICENSE.md +++ /dev/null @@ -1,9 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2018 Lucien Greathouse - -Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/README.md b/README.md index 767399d6..4d5a4c65 100644 --- a/README.md +++ b/README.md @@ -57,4 +57,4 @@ Pull requests are welcome! All pull requests are run against a test suite on Travis CI. That test suite should always pass! ## License -Rojo is available under the terms of the MIT license. See [LICENSE.md](LICENSE.md) for details. \ No newline at end of file +Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE](LICENSE) for details. \ No newline at end of file From 29a83cb6263ad45f70403ca883a22f41bc0da447 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 12 Apr 2018 00:18:45 -0700 Subject: [PATCH 0103/1504] Update LICENSE --- LICENSE | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 7cdb712f..dbdb0fa8 100644 --- a/LICENSE +++ b/LICENSE @@ -350,4 +350,24 @@ Licenses If You choose to distribute Source Code Form that is Incompatible With Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. \ No newline at end of file +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. \ No newline at end of file From 8c482f75dd7f7ad13a6de6614f02bfca801d5c13 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 20 Apr 2018 21:45:48 -0700 Subject: [PATCH 0104/1504] Improve error messages for 'serve' command. Rojo now throws an error if no project file could be found. Fixes #63. --- CHANGES.md | 2 +- server/src/commands/serve.rs | 26 +++++++++----------------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 86606407..3e005aa8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,7 @@ # Rojo Change Log ## Current Master -*No changes* +* Rojo now throws an error if no project file is found. ([#63](https://github.com/LPGhatguy/rojo/issues/63)) ## 0.4.4 (April 7, 2018) * Fix small regression introduced in 0.4.3 diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 998001ba..7d5a117a 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -14,10 +14,6 @@ use web; pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { let server_id = rand::random::(); - if verbose { - println!("Attempting to locate project at {}...", project_path.display()); - } - let project = match Project::load(project_path) { Ok(v) => { println!("Using project from {}", project_path.display()); @@ -26,27 +22,23 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { Err(err) => { match err { ProjectLoadError::InvalidJson(serde_err) => { - eprintln!( - "Found invalid JSON!\nProject in: {}\nError: {}", - project_path.display(), - serde_err, - ); + eprintln!("Project contained invalid JSON!"); + eprintln!("{}", project_path.display()); + eprintln!("Error: {}", serde_err); process::exit(1); }, ProjectLoadError::FailedToOpen | ProjectLoadError::FailedToRead => { eprintln!("Found project file, but failed to read it!"); - eprintln!( - "Check the permissions of the project file at\n{}", - project_path.display(), - ); + eprintln!("Check the permissions of the project file at {}", project_path.display()); process::exit(1); }, - _ => { - // Any other error is fine; use the default project. - println!("Found no project file, using default project..."); - Project::default() + ProjectLoadError::DidNotExist => { + eprintln!("Found no project file! Create one using 'rojo init'"); + eprintln!("Checked for a project at {}", project_path.display()); + + process::exit(1); }, } }, From c2cfcc7a2c471c414195944f8264affc91baf468 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 20 Apr 2018 22:27:12 -0700 Subject: [PATCH 0105/1504] Prevent syncing while a sync is already in progress. I'm fairly confident that there will be zero cases where the plugin gets into a bad state where you can't sync. This change also prefixes most of Rojo's messages with `Rojo:` to make them easier to identify. Fixes #61. --- CHANGES.md | 1 + plugin/src/Plugin.lua | 30 +++++++++++++++++++++--------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 3e005aa8..5d447311 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## Current Master * Rojo now throws an error if no project file is found. ([#63](https://github.com/LPGhatguy/rojo/issues/63)) +* Fixed multiple sync operations occuring at the same time. ([#61](https://github.com/LPGhatguy/rojo/issues/61)) ## 0.4.4 (April 7, 2018) * Fix small regression introduced in 0.4.3 diff --git a/plugin/src/Plugin.lua b/plugin/src/Plugin.lua index 2a734f70..67882b37 100644 --- a/plugin/src/Plugin.lua +++ b/plugin/src/Plugin.lua @@ -28,6 +28,7 @@ function Plugin.new() _reconciler = Reconciler.new(), _api = nil, _polling = false, + _syncInProgress = false, } setmetatable(self, Plugin) @@ -62,11 +63,12 @@ end restarted. ]] function Plugin:restart() - warn("The server has changed since the last request, reloading plugin...") + warn("Rojo: The server has changed since the last request, reloading plugin...") self._reconciler:clear() self._api = nil self._polling = false + self._syncInProgress = false end function Plugin:api() @@ -82,7 +84,7 @@ function Plugin:api() end function Plugin:connect() - print("Testing connection...") + print("Rojo: Testing connection...") return self:api() :andThen(function(api) @@ -92,9 +94,9 @@ function Plugin:connect() return Promise.reject(info) end - print("Server found!") - print("Protocol version:", info.protocolVersion) - print("Server version:", info.serverVersion) + print("Rojo: Server found!") + print("Rojo: Protocol version:", info.protocolVersion) + print("Rojo: Server version:", info.serverVersion) end) :catch(function(err) if err == Api.Error.ServerIdMismatch then @@ -119,7 +121,7 @@ function Plugin:stopPolling() return Promise.resolve(false) end - print("Stopped polling.") + print("Rojo Stopped polling server for changes.") self._polling = false self._label.Enabled = false @@ -168,7 +170,7 @@ function Plugin:startPolling() return end - print("Starting to poll...") + print("Rojo: Polling server for changes...") self._polling = true self._label.Enabled = true @@ -224,7 +226,14 @@ function Plugin:startPolling() end function Plugin:syncIn() - print("Syncing from server...") + if self._syncInProgress then + warn("Rojo: Can't sync right now, because a sync is already in progress.") + + return Promise.resolve() + end + + self._syncInProgress = true + print("Rojo: Syncing from server...") return self:api() :andThen(function(api) @@ -242,9 +251,12 @@ function Plugin:syncIn() self:_pull(api, info.project, routes) - print("Sync successful!") + self._syncInProgress = false + print("Rojo: Sync successful!") end) :catch(function(err) + self._syncInProgress = false + if err == Api.Error.ServerIdMismatch then self:restart() return self:syncIn() From 9e956e593dbbf83c1b403ca5053ec6db0f39b7db Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 20 Apr 2018 23:13:01 -0700 Subject: [PATCH 0106/1504] Expand test project to have a partition targeting a script directly --- test-project/extra-script.lua | 0 test-project/rojo.json | 4 ++++ 2 files changed, 4 insertions(+) create mode 100644 test-project/extra-script.lua diff --git a/test-project/extra-script.lua b/test-project/extra-script.lua new file mode 100644 index 00000000..e69de29b diff --git a/test-project/rojo.json b/test-project/rojo.json index 5f2e5c4c..c7e2f3e8 100644 --- a/test-project/rojo.json +++ b/test-project/rojo.json @@ -5,6 +5,10 @@ "src": { "path": "src", "target": "ReplicatedFirst" + }, + "extra": { + "path": "extra-script.lua", + "target": "ReplicatedStorage.ExtraScript" } } } \ No newline at end of file From 187194a615ceeee4721dad27ffa2c19e3b3b7ac8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 20 Apr 2018 23:13:43 -0700 Subject: [PATCH 0107/1504] Keep track of actual file name in VfsItem. This should fix the case of a partition pointed directly at a file turning the object into a `StringValue`. Fixes #57. --- CHANGES.md | 1 + server/src/vfs/vfs_item.rs | 7 ++++++- server/src/vfs/vfs_session.rs | 6 ++++++ 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 5d447311..a00a25c1 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,6 +3,7 @@ ## Current Master * Rojo now throws an error if no project file is found. ([#63](https://github.com/LPGhatguy/rojo/issues/63)) * Fixed multiple sync operations occuring at the same time. ([#61](https://github.com/LPGhatguy/rojo/issues/61)) +* Partitions targeting files directly now work as expected. ([#57](https://github.com/LPGhatguy/rojo/issues/57)) ## 0.4.4 (April 7, 2018) * Fix small regression introduced in 0.4.3 diff --git a/server/src/vfs/vfs_item.rs b/server/src/vfs/vfs_item.rs index ae00c6dc..89fd2608 100644 --- a/server/src/vfs/vfs_item.rs +++ b/server/src/vfs/vfs_item.rs @@ -9,17 +9,22 @@ use std::collections::HashMap; pub enum VfsItem { File { route: Vec, + file_name: String, contents: String, }, Dir { route: Vec, + file_name: String, children: HashMap, }, } impl VfsItem { pub fn name(&self) -> &String { - self.route().last().unwrap() + match self { + &VfsItem::File { ref file_name , .. } => file_name, + &VfsItem::Dir { ref file_name , .. } => file_name, + } } pub fn route(&self) -> &[String] { diff --git a/server/src/vfs/vfs_session.rs b/server/src/vfs/vfs_session.rs index efe86ea7..52945d0d 100644 --- a/server/src/vfs/vfs_session.rs +++ b/server/src/vfs/vfs_session.rs @@ -111,8 +111,11 @@ impl VfsSession { } } + let file_name = path.file_name().unwrap().to_string_lossy().into_owned(); + Ok(VfsItem::Dir { route: route.iter().cloned().collect::>(), + file_name, children, }) } @@ -131,8 +134,11 @@ impl VfsSession { Err(_) => return Err(()), } + let file_name = path.file_name().unwrap().to_string_lossy().into_owned(); + Ok(VfsItem::File { route: route.iter().cloned().collect::>(), + file_name, contents, }) } From 2d71e3ebead48ff4f98f72c1a60b066185d932bb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 20 Apr 2018 23:26:50 -0700 Subject: [PATCH 0108/1504] Switch to library version of Promise --- .gitmodules | 3 + plugin/modules/promise | 1 + plugin/rojo.json | 4 + plugin/src/Api.lua | 3 +- plugin/src/Http.lua | 3 +- plugin/src/Plugin.lua | 3 +- plugin/src/Promise.lua | 307 ----------------------------------------- 7 files changed, 14 insertions(+), 310 deletions(-) create mode 160000 plugin/modules/promise delete mode 100644 plugin/src/Promise.lua diff --git a/.gitmodules b/.gitmodules index 4d521fd8..a43f0aff 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "plugin/modules/lemur"] path = plugin/modules/lemur url = https://github.com/LPGhatguy/lemur.git +[submodule "plugin/modules/promise"] + path = plugin/modules/promise + url = https://github.com/LPGhatguy/roblox-lua-promise.git diff --git a/plugin/modules/promise b/plugin/modules/promise new file mode 160000 index 00000000..7fb09d10 --- /dev/null +++ b/plugin/modules/promise @@ -0,0 +1 @@ +Subproject commit 7fb09d103f4a680cbd61d5348ec9c5d50244a8e0 diff --git a/plugin/rojo.json b/plugin/rojo.json index c1cbdb8c..6ba55d43 100644 --- a/plugin/rojo.json +++ b/plugin/rojo.json @@ -18,6 +18,10 @@ "path": "modules/roact-rodux/lib", "target": "ReplicatedStorage.Rojo.modules.RoactRodux" }, + "modules/promise": { + "path": "modules/promise/lib", + "target": "ReplicatedStorage.Rojo.modules.Promise" + }, "modules/testez": { "path": "modules/testez/lib", "target": "ReplicatedStorage.TestEZ" diff --git a/plugin/src/Api.lua b/plugin/src/Api.lua index 131acf6f..163c4d1e 100644 --- a/plugin/src/Api.lua +++ b/plugin/src/Api.lua @@ -1,7 +1,8 @@ local HttpService = game:GetService("HttpService") +local Promise = require(script.Parent.Parent.modules.Promise) + local Config = require(script.Parent.Config) -local Promise = require(script.Parent.Promise) local Version = require(script.Parent.Version) local Api = {} diff --git a/plugin/src/Http.lua b/plugin/src/Http.lua index 98997b9f..56a538b4 100644 --- a/plugin/src/Http.lua +++ b/plugin/src/Http.lua @@ -2,7 +2,8 @@ local HttpService = game:GetService("HttpService") local HTTP_DEBUG = false -local Promise = require(script.Parent.Promise) +local Promise = require(script.Parent.Parent.modules.Promise) + local HttpError = require(script.Parent.HttpError) local HttpResponse = require(script.Parent.HttpResponse) diff --git a/plugin/src/Plugin.lua b/plugin/src/Plugin.lua index 67882b37..a54adb93 100644 --- a/plugin/src/Plugin.lua +++ b/plugin/src/Plugin.lua @@ -1,7 +1,8 @@ +local Promise = require(script.Parent.Parent.modules.Promise) + local Config = require(script.Parent.Config) local Http = require(script.Parent.Http) local Api = require(script.Parent.Api) -local Promise = require(script.Parent.Promise) local Reconciler = require(script.Parent.Reconciler) local function collectMatch(source, pattern) diff --git a/plugin/src/Promise.lua b/plugin/src/Promise.lua deleted file mode 100644 index 144469e6..00000000 --- a/plugin/src/Promise.lua +++ /dev/null @@ -1,307 +0,0 @@ ---[[ - An implementation of Promises similar to Promise/A+. -]] - -local PROMISE_DEBUG = false - --- If promise debugging is on, use a version of pcall that warns on failure. --- This is useful for finding errors that happen within Promise itself. -local wpcall -if PROMISE_DEBUG then - wpcall = function(f, ...) - local result = { pcall(f, ...) } - - if not result[1] then - warn(result[2]) - end - - return unpack(result) - end -else - wpcall = pcall -end - ---[[ - Creates a function that invokes a callback with correct error handling and - resolution mechanisms. -]] -local function createAdvancer(callback, resolve, reject) - return function(...) - local result = { wpcall(callback, ...) } - local ok = table.remove(result, 1) - - if ok then - resolve(unpack(result)) - else - reject(unpack(result)) - end - end -end - -local function isEmpty(t) - return next(t) == nil -end - -local Promise = {} -Promise.__index = Promise - -Promise.Status = { - Started = "Started", - Resolved = "Resolved", - Rejected = "Rejected", -} - ---[[ - Constructs a new Promise with the given initializing callback. - - This is generally only called when directly wrapping a non-promise API into - a promise-based version. - - The callback will receive 'resolve' and 'reject' methods, used to start - invoking the promise chain. - - For example: - - local function get(url) - return Promise.new(function(resolve, reject) - spawn(function() - resolve(HttpService:GetAsync(url)) - end) - end) - end - - get("https://google.com") - :andThen(function(stuff) - print("Got some stuff!", stuff) - end) -]] -function Promise.new(callback) - local promise = { - -- Used to locate where a promise was created - _source = debug.traceback(), - - -- A tag to identify us as a promise - _type = "Promise", - - _status = Promise.Status.Started, - - -- A table containing a list of all results, whether success or failure. - -- Only valid if _status is set to something besides Started - _value = nil, - - -- If an error occurs with no observers, this will be set. - _unhandledRejection = false, - - -- Queues representing functions we should invoke when we update! - _queuedResolve = {}, - _queuedReject = {}, - } - - setmetatable(promise, Promise) - - local function resolve(...) - promise:_resolve(...) - end - - local function reject(...) - promise:_reject(...) - end - - local ok, err = wpcall(callback, resolve, reject) - - if not ok and promise._status == Promise.Status.Started then - reject(err) - end - - return promise -end - ---[[ - Create a promise that represents the immediately resolved value. -]] -function Promise.resolve(value) - return Promise.new(function(resolve) - resolve(value) - end) -end - ---[[ - Create a promise that represents the immediately rejected value. -]] -function Promise.reject(value) - return Promise.new(function(_, reject) - reject(value) - end) -end - ---[[ - Returns a new promise that: - * is resolved when all input promises resolve - * is rejected if ANY input promises reject -]] -function Promise.all(...) - error("unimplemented", 2) -end - ---[[ - Is the given object a Promise instance? -]] -function Promise.is(object) - if type(object) ~= "table" then - return false - end - - return object._type == "Promise" -end - ---[[ - Creates a new promise that receives the result of this promise. - - The given callbacks are invoked depending on that result. -]] -function Promise:andThen(successHandler, failureHandler) - self._unhandledRejection = false - - -- Create a new promise to follow this part of the chain - return Promise.new(function(resolve, reject) - -- Our default callbacks just pass values onto the next promise. - -- This lets success and failure cascade correctly! - - local successCallback = resolve - if successHandler then - successCallback = createAdvancer(successHandler, resolve, reject) - end - - local failureCallback = reject - if failureHandler then - failureCallback = createAdvancer(failureHandler, resolve, reject) - end - - if self._status == Promise.Status.Started then - -- If we haven't resolved yet, put ourselves into the queue - table.insert(self._queuedResolve, successCallback) - table.insert(self._queuedReject, failureCallback) - elseif self._status == Promise.Status.Resolved then - -- This promise has already resolved! Trigger success immediately. - successCallback(unpack(self._value)) - elseif self._status == Promise.Status.Rejected then - -- This promise died a terrible death! Trigger failure immediately. - failureCallback(unpack(self._value)) - end - end) -end - ---[[ - Used to catch any errors that may have occurred in the promise. -]] -function Promise:catch(failureCallback) - return self:andThen(nil, failureCallback) -end - ---[[ - Yield until the promise is completed. - - This matches the execution model of normal Roblox functions. -]] -function Promise:await() - self._unhandledRejection = false - - if self._status == Promise.Status.Started then - local result - local bindable = Instance.new("BindableEvent") - - self:andThen(function(...) - result = {...} - bindable:Fire(true) - end, function(...) - result = {...} - bindable:Fire(false) - end) - - local ok = bindable.Event:Wait() - bindable:Destroy() - - return ok, unpack(result) - elseif self._status == Promise.Status.Resolved then - return true, unpack(self._value) - elseif self._status == Promise.Status.Rejected then - return false, unpack(self._value) - end -end - -function Promise:_resolve(...) - if self._status ~= Promise.Status.Started then - return - end - - -- If the resolved value was a Promise, we chain onto it! - if Promise.is((...)) then - -- Without this warning, arguments sometimes mysteriously disappear - if select("#", ...) > 1 then - local message = ( - "When returning a Promise from andThen, extra arguments are " .. - "discarded! See:\n\n%s" - ):format( - self._source - ) - warn(message) - end - - (...):andThen(function(...) - self:_resolve(...) - end, function(...) - self:_reject(...) - end) - - return - end - - self._status = Promise.Status.Resolved - self._value = {...} - - -- We assume that these callbacks will not throw errors. - for _, callback in ipairs(self._queuedResolve) do - callback(...) - end -end - -function Promise:_reject(...) - if self._status ~= Promise.Status.Started then - return - end - - self._status = Promise.Status.Rejected - self._value = {...} - - -- If there are any rejection handlers, call those! - if not isEmpty(self._queuedReject) then - -- We assume that these callbacks will not throw errors. - for _, callback in ipairs(self._queuedReject) do - callback(...) - end - else - -- At this point, no one was able to observe the error. - -- An error handler might still be attached if the error occurred - -- synchronously. We'll wait one tick, and if there are still no - -- observers, then we should put a message in the console. - - self._unhandledRejection = true - local err = tostring((...)) - - spawn(function() - -- Someone observed the error, hooray! - if not self._unhandledRejection then - return - end - - -- Build a reasonable message - local message = ("Unhandled promise rejection:\n\n%s\n\n%s"):format( - err, - self._source - ) - warn(message) - end) - end -end - -return Promise From ce5fe00a66d0eb8ed7b3551c3cfd94f0b4b0da8d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 21 Apr 2018 01:16:19 -0700 Subject: [PATCH 0109/1504] Delete Promise.spec.lua --- plugin/src/Promise.spec.lua | 262 ------------------------------------ 1 file changed, 262 deletions(-) delete mode 100644 plugin/src/Promise.spec.lua diff --git a/plugin/src/Promise.spec.lua b/plugin/src/Promise.spec.lua deleted file mode 100644 index 2193fcb6..00000000 --- a/plugin/src/Promise.spec.lua +++ /dev/null @@ -1,262 +0,0 @@ -return function() - local Promise = require(script.Parent.Promise) - - describe("Promise.new", function() - it("should instantiate with a callback", function() - local promise = Promise.new(function() end) - - expect(promise).to.be.ok() - end) - - it("should invoke the given callback with resolve and reject", function() - local callCount = 0 - local resolveArg - local rejectArg - - local promise = Promise.new(function(resolve, reject) - callCount = callCount + 1 - resolveArg = resolve - rejectArg = reject - end) - - expect(promise).to.be.ok() - - expect(callCount).to.equal(1) - expect(resolveArg).to.be.a("function") - expect(rejectArg).to.be.a("function") - expect(promise._status).to.equal(Promise.Status.Started) - end) - - it("should resolve promises on resolve()", function() - local callCount = 0 - - local promise = Promise.new(function(resolve) - callCount = callCount + 1 - resolve() - end) - - expect(promise).to.be.ok() - expect(callCount).to.equal(1) - expect(promise._status).to.equal(Promise.Status.Resolved) - end) - - it("should reject promises on reject()", function() - local callCount = 0 - - local promise = Promise.new(function(resolve, reject) - callCount = callCount + 1 - reject() - end) - - expect(promise).to.be.ok() - expect(callCount).to.equal(1) - expect(promise._status).to.equal(Promise.Status.Rejected) - end) - - it("should reject on error in callback", function() - local callCount = 0 - - local promise = Promise.new(function() - callCount = callCount + 1 - error("hahah") - end) - - expect(promise).to.be.ok() - expect(callCount).to.equal(1) - expect(promise._status).to.equal(Promise.Status.Rejected) - expect(promise._value[1]:find("hahah")).to.be.ok() - end) - end) - - describe("Promise.resolve", function() - it("should immediately resolve with a value", function() - local promise = Promise.resolve(5) - - expect(promise).to.be.ok() - expect(promise._status).to.equal(Promise.Status.Resolved) - expect(promise._value[1]).to.equal(5) - end) - - it("should chain onto passed promises", function() - local promise = Promise.resolve(Promise.new(function(_, reject) - reject(7) - end)) - - expect(promise).to.be.ok() - expect(promise._status).to.equal(Promise.Status.Rejected) - expect(promise._value[1]).to.equal(7) - end) - end) - - describe("Promise.reject", function() - it("should immediately reject with a value", function() - local promise = Promise.reject(6) - - expect(promise).to.be.ok() - expect(promise._status).to.equal(Promise.Status.Rejected) - expect(promise._value[1]).to.equal(6) - end) - - it("should pass a promise as-is as an error", function() - local innerPromise = Promise.new(function(resolve) - resolve(6) - end) - - local promise = Promise.reject(innerPromise) - - expect(promise).to.be.ok() - expect(promise._status).to.equal(Promise.Status.Rejected) - expect(promise._value[1]).to.equal(innerPromise) - end) - end) - - describe("Promise:andThen", function() - it("should chain onto resolved promises", function() - local args - local argsLength - local callCount = 0 - local badCallCount = 0 - - local promise = Promise.resolve(5) - - local chained = promise - :andThen(function(...) - args = {...} - argsLength = select("#", ...) - callCount = callCount + 1 - end, function() - badCallCount = badCallCount + 1 - end) - - expect(badCallCount).to.equal(0) - - expect(callCount).to.equal(1) - expect(argsLength).to.equal(1) - expect(args[1]).to.equal(5) - - expect(promise).to.be.ok() - expect(promise._status).to.equal(Promise.Status.Resolved) - expect(promise._value[1]).to.equal(5) - - expect(chained).to.be.ok() - expect(chained).never.to.equal(promise) - expect(chained._status).to.equal(Promise.Status.Resolved) - expect(#chained._value).to.equal(0) - end) - - it("should chain onto rejected promises", function() - local args - local argsLength - local callCount = 0 - local badCallCount = 0 - - local promise = Promise.reject(5) - - local chained = promise - :andThen(function(...) - badCallCount = badCallCount + 1 - end, function(...) - args = {...} - argsLength = select("#", ...) - callCount = callCount + 1 - end) - - expect(badCallCount).to.equal(0) - - expect(callCount).to.equal(1) - expect(argsLength).to.equal(1) - expect(args[1]).to.equal(5) - - expect(promise).to.be.ok() - expect(promise._status).to.equal(Promise.Status.Rejected) - expect(promise._value[1]).to.equal(5) - - expect(chained).to.be.ok() - expect(chained).never.to.equal(promise) - expect(chained._status).to.equal(Promise.Status.Resolved) - expect(#chained._value).to.equal(0) - end) - - it("should chain onto asynchronously resolved promises", function() - local args - local argsLength - local callCount = 0 - local badCallCount = 0 - - local startResolution - local promise = Promise.new(function(resolve) - startResolution = resolve - end) - - local chained = promise - :andThen(function(...) - args = {...} - argsLength = select("#", ...) - callCount = callCount + 1 - end, function() - badCallCount = badCallCount + 1 - end) - - expect(callCount).to.equal(0) - expect(badCallCount).to.equal(0) - - startResolution(6) - - expect(badCallCount).to.equal(0) - - expect(callCount).to.equal(1) - expect(argsLength).to.equal(1) - expect(args[1]).to.equal(6) - - expect(promise).to.be.ok() - expect(promise._status).to.equal(Promise.Status.Resolved) - expect(promise._value[1]).to.equal(6) - - expect(chained).to.be.ok() - expect(chained).never.to.equal(promise) - expect(chained._status).to.equal(Promise.Status.Resolved) - expect(#chained._value).to.equal(0) - end) - - it("should chain onto asynchronously rejected promises", function() - local args - local argsLength - local callCount = 0 - local badCallCount = 0 - - local startResolution - local promise = Promise.new(function(_, reject) - startResolution = reject - end) - - local chained = promise - :andThen(function() - badCallCount = badCallCount + 1 - end, function(...) - args = {...} - argsLength = select("#", ...) - callCount = callCount + 1 - end) - - expect(callCount).to.equal(0) - expect(badCallCount).to.equal(0) - - startResolution(6) - - expect(badCallCount).to.equal(0) - - expect(callCount).to.equal(1) - expect(argsLength).to.equal(1) - expect(args[1]).to.equal(6) - - expect(promise).to.be.ok() - expect(promise._status).to.equal(Promise.Status.Rejected) - expect(promise._value[1]).to.equal(6) - - expect(chained).to.be.ok() - expect(chained).never.to.equal(promise) - expect(chained._status).to.equal(Promise.Status.Resolved) - expect(#chained._value).to.equal(0) - end) - end) -end From f215df891c2541abf625d53f7d69fac7b97bfc56 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 22 Apr 2018 16:41:45 -0700 Subject: [PATCH 0110/1504] Decrease debounce timeout, which will make polling much snappier --- CHANGES.md | 1 + server/src/vfs/vfs_watcher.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index a00a25c1..4ecf2505 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,7 @@ # Rojo Change Log ## Current Master +* Fixed server to notice file changes *much* more quickly. (200ms vs 1000ms) * Rojo now throws an error if no project file is found. ([#63](https://github.com/LPGhatguy/rojo/issues/63)) * Fixed multiple sync operations occuring at the same time. ([#61](https://github.com/LPGhatguy/rojo/issues/61)) * Partitions targeting files directly now work as expected. ([#57](https://github.com/LPGhatguy/rojo/issues/57)) diff --git a/server/src/vfs/vfs_watcher.rs b/server/src/vfs/vfs_watcher.rs index 9ace5262..0e7ac27d 100644 --- a/server/src/vfs/vfs_watcher.rs +++ b/server/src/vfs/vfs_watcher.rs @@ -77,7 +77,7 @@ impl VfsWatcher { for (ref partition_name, ref root_path) in vfs.get_partitions() { let (tx, rx) = mpsc::channel(); - let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_secs(1)) + let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_millis(200)) .expect("Unable to create watcher! This is a bug in Rojo."); match watcher.watch(&root_path, RecursiveMode::Recursive) { From 3661d0daec81875905d37c95d3b721ba3c1c4e7a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 22 Apr 2018 17:19:21 -0700 Subject: [PATCH 0111/1504] Show name of project when starting server --- CHANGES.md | 1 + server/src/commands/serve.rs | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 4ecf2505..e257a9c2 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## Current Master * Fixed server to notice file changes *much* more quickly. (200ms vs 1000ms) +* Server now lists name of project when starting up. * Rojo now throws an error if no project file is found. ([#63](https://github.com/LPGhatguy/rojo/issues/63)) * Fixed multiple sync operations occuring at the same time. ([#61](https://github.com/LPGhatguy/rojo/issues/61)) * Partitions targeting files directly now work as expected. ([#57](https://github.com/LPGhatguy/rojo/issues/57)) diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 7d5a117a..d0c41b5d 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -15,9 +15,9 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { let server_id = rand::random::(); let project = match Project::load(project_path) { - Ok(v) => { - println!("Using project from {}", project_path.display()); - v + Ok(project) => { + println!("Using project \"{}\" from {}", project.name, project_path.display()); + project }, Err(err) => { match err { @@ -44,12 +44,6 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { }, }; - let web_config = web::WebConfig { - verbose, - port: port.unwrap_or(project.serve_port), - server_id, - }; - lazy_static! { static ref PLUGIN_CHAIN: PluginChain = PluginChain::new(vec![ Box::new(ScriptPlugin::new()), @@ -78,8 +72,6 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { Arc::new(Mutex::new(vfs)) }; - println!("Server listening on port {}", web_config.port); - { let vfs = vfs.clone(); thread::spawn(move || { @@ -87,5 +79,13 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { }); } + let web_config = web::WebConfig { + verbose, + port: port.unwrap_or(project.serve_port), + server_id, + }; + + println!("Server listening on port {}", web_config.port); + web::start(web_config, project.clone(), &PLUGIN_CHAIN, vfs.clone()); } From 274ba5810b67f014024cde11dc75dc7588d82db2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 22 Apr 2018 17:35:21 -0700 Subject: [PATCH 0112/1504] Update to Rouille 2.1 and latest dependencies --- server/Cargo.lock | 347 ++++++++++++++++++++++++++-------------------- server/Cargo.toml | 2 +- 2 files changed, 201 insertions(+), 148 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index bed68bc1..637d3291 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -1,10 +1,7 @@ [[package]] -name = "aho-corasick" -version = "0.5.3" +name = "adler32" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "aho-corasick" @@ -29,7 +26,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "atty" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -37,6 +34,15 @@ dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base64" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "0.4.0" @@ -72,7 +78,21 @@ dependencies = [ [[package]] name = "buf_redux" -version = "0.1.3" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "build_const" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "byteorder" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -80,11 +100,6 @@ name = "bytes" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "cc" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "cfg-if" version = "0.1.2" @@ -99,6 +114,16 @@ dependencies = [ "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "chrono" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "chunked_transfer" version = "0.3.1" @@ -110,7 +135,7 @@ version = "2.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -118,6 +143,24 @@ dependencies = [ "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crc" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "deflate" +version = "0.7.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "gzip-header 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "dtoa" version = "0.4.2" @@ -181,12 +224,11 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "env_logger" -version = "0.3.5" +name = "enum_primitive" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -199,15 +241,6 @@ dependencies = [ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "flate2" -version = "0.2.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "fsevent" version = "0.2.17" @@ -245,6 +278,20 @@ name = "gcc" version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "gzip-header" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "httparse" +version = "1.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "idna" version = "0.1.4" @@ -310,7 +357,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "0.1.11" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -326,30 +373,21 @@ dependencies = [ [[package]] name = "mime" -version = "0.1.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mime_guess" -version = "1.5.0" +version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "mime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miniz-sys" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -381,17 +419,18 @@ dependencies = [ [[package]] name = "multipart" -version = "0.5.1" +version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "buf_redux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 1.8.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -457,11 +496,27 @@ dependencies = [ "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-traits" +version = "0.1.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-traits" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num_cpus" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "percent-encoding" version = "1.0.1" @@ -499,11 +554,12 @@ version = "0.7.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro2" -version = "0.3.1" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -511,10 +567,10 @@ dependencies = [ [[package]] name = "quote" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -550,18 +606,6 @@ dependencies = [ "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "regex" -version = "0.1.80" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex" version = "0.2.10" @@ -569,19 +613,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "regex-syntax" -version = "0.5.3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -589,7 +628,7 @@ dependencies = [ [[package]] name = "remove_dir_all" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -604,26 +643,31 @@ dependencies = [ "notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rouille 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rouille" -version = "1.0.3" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "brotli2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)", - "multipart 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "tiny_http 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -634,6 +678,11 @@ name = "rustc-serialize" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "safemem" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "same-file" version = "1.0.2" @@ -644,46 +693,37 @@ dependencies = [ [[package]] name = "serde" -version = "0.6.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde" -version = "1.0.37" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.37" +version = "1.0.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive_internals" -version = "0.23.0" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.13" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -711,8 +751,8 @@ name = "syn" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -722,7 +762,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -752,23 +792,6 @@ dependencies = [ "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "thread-id" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "thread_local" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "thread_local" version = "0.3.5" @@ -778,6 +801,14 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "threadpool" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "time" version = "0.1.39" @@ -801,11 +832,27 @@ dependencies = [ "url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "twoway" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ucd-util" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicase" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -857,11 +904,6 @@ dependencies = [ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "utf8-ranges" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "utf8-ranges" version = "1.0.0" @@ -881,6 +923,11 @@ name = "vec_map" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "void" version = "1.0.2" @@ -934,23 +981,28 @@ dependencies = [ ] [metadata] -"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66" +"checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45" "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" -"checksum atty 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "af80143d6f7608d746df1520709e5d141c96f240b0e62b0aa41bdfb53374d9d4" +"checksum atty 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6609a866dd1a1b2d0ee1362195bf3e4f6438abb2d80120b83b1e1f4fb6476dd0" +"checksum base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5032d51da2741729bfdaeb2664d9b8c6d9fd1e2b90715c660b6def36628499c2" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum brotli-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cb50f54b2e0c671b7ef1637a76237ebacbb293be179440d5d65ca288e42116bb" "checksum brotli2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea9d0bbab1235017a09226b079ed733bca4bf9ecb6b6102bd01aac79ea082dca" -"checksum buf_redux 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b115bd9935c68b58f80ff867e1c46942c4aed79e78bcc8c2bc22d50f52bb9099" +"checksum buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9279646319ff816b05fb5897883ece50d7d854d12b59992683d4f8a71b0f949" +"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" +"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" "checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27" -"checksum cc 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2b4911e4bdcb4100c7680e7e854ff38e23f1b34d4d9e079efae3da2801341ffc" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" +"checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6" "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" +"checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7" +"checksum deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "32c8120d981901a9970a3a1c97cf8b630e0fa8c3ca31e75b6fd6fd5f9f427b31" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" @@ -959,14 +1011,15 @@ dependencies = [ "checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" -"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" +"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" "checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f" -"checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423" "checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05" "checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" +"checksum gzip-header 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0a9fcfe1c9ee125342355b2467bc29b9dfcb2124fcae27edb9cee6f4cc5ecd40" +"checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37" "checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" "checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" "checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" @@ -976,45 +1029,44 @@ dependencies = [ "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" "checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" -"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" +"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" -"checksum mime 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ec0c2f4d901bf1d4a2192a40b4b570ae3b19c51243e549defc1de741940aa787" -"checksum mime_guess 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "422acd80644209a8c8c66a20514840d8c092eb1eab2898ca7c548cc1d64c8998" -"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4" +"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" +"checksum mime_guess 1.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b7e2b09d08313f84e0fb82d13a4d859109a17543fe9af3b6d941dc1431f7de79" "checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e" "checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" -"checksum multipart 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b68c9a0c757bd65893af529f7af6e7a71442e57ca6d9db1fa69b79e2f05f6b49" +"checksum multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92f54eb45230c3aa20864ccf0c277eeaeadcf5e437e91731db498dbf7fbe0ec6" "checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0" "checksum nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfb3ddedaa14746434a02041940495bf11325c22f6d36125d3bdd56090d50a79" "checksum notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5c3812da3098f210a0bb440f9c008471a031aa4c1de07a264fdd75456c95a4eb" "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" "checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe" "checksum num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "4b226df12c5a59b63569dd57fafb926d91b385dfce33d8074a412411b689d593" +"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" "checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" +"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" "checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" "checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" "checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" -"checksum proc-macro2 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "388d7ea47318c5ccdeb9ba6312cee7d3f65dd2804be8580a170fce410d50b786" -"checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a" +"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" +"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f" "checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" -"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957" -"checksum regex-syntax 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b2550876c31dc914696a6c2e01cbce8afba79a93c8ae979d2fe051c0230b3756" -"checksum remove_dir_all 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfc5b3ce5d5ea144bb04ebd093a9e14e9765bcfec866aecda9b6dec43b3d1e24" -"checksum rouille 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d6415f261a8775bef50e9fcfb14ed73209ce637f753f9d1c8c6122559e559001" +"checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb" +"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" +"checksum rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc1f8407af80b0630983b2c1f1860dda1960fdec8d3ee75ba8db14937756d3a0" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" -"checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" -"checksum serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "d3bcee660dcde8f52c3765dd9ca5ee36b4bf35470a738eb0bd5a8752b0389645" -"checksum serde_derive 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "f1711ab8b208541fa8de00425f6a577d90f27bb60724d2bb5fd911314af9668f" -"checksum serde_derive_internals 0.23.0 (registry+https://github.com/rust-lang/crates.io-index)" = "89b340a48245bc03ddba31d0ff1709c118df90edc6adabaca4aac77aea181cce" -"checksum serde_json 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "5c508584d9913df116b91505eec55610a2f5b16e9ed793c46e4d0152872b3e74" +"checksum serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "a73973861352c932ed1365ce22b32467ce260ac4c8db11cf750ce56334ff2dcf" +"checksum serde_derive 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b392c5a0cebb98121454531c50e60e2ffe0fbeb1a44da277da2d681d08d7dc0b" +"checksum serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d30c4596450fd7bbda79ef15559683f9a79ac0193ea819db90000d7e1cae794" +"checksum serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6c4e049dc657a99e394bd85c22acbf97356feeec6dbf44150f2dcf79fb3118" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" @@ -1024,12 +1076,13 @@ dependencies = [ "checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" -"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03" -"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5" "checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" "checksum tiny_http 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2f4d55c9a213880d1f0c89ded183f209c6e45b912ca6c7df6f93c163773572e1" +"checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" +"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" @@ -1037,10 +1090,10 @@ dependencies = [ "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)" = "cbaa8377a162d88e7d15db0cf110c8523453edcbc5bc66d2b6fffccffa34a068" "checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" -"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f" "checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" "checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f" "checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" +"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" diff --git a/server/Cargo.toml b/server/Cargo.toml index 1d0a0255..5a7cbc6b 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -12,7 +12,7 @@ path = "src/bin.rs" [dependencies] clap = "2.27.1" -rouille = "1.0" +rouille = "2.1.0" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" From 23c59dcae7a437c9b2866f1b98af296e7bb9d576 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 May 2018 12:29:48 -0700 Subject: [PATCH 0113/1504] 0.4.5 --- CHANGES.md | 4 ++++ README.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.lock | 2 +- server/Cargo.toml | 2 +- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index e257a9c2..988ad367 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,10 @@ # Rojo Change Log ## Current Master +*No changes* + +## 0.4.5 (May 1, 2018) +* Rojo messages are now prefixed with `Rojo: ` to make them stand out in the output more. * Fixed server to notice file changes *much* more quickly. (200ms vs 1000ms) * Server now lists name of project when starting up. * Rojo now throws an error if no project file is found. ([#63](https://github.com/LPGhatguy/rojo/issues/63)) diff --git a/README.md b/README.md index 4d5a4c65..7b4365a1 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Travis-CI Build Status - Current server version + Current server version Rojo Documentation diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 8c8aaa5c..55906858 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { pollingRate = 0.2, - version = {0, 4, 4}, + version = {0, 4, 5}, expectedServerVersionString = "0.4.x", protocolVersion = 1, dev = false, diff --git a/server/Cargo.lock b/server/Cargo.lock index 637d3291..32f5b742 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -636,7 +636,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.4.4" +version = "0.4.5" dependencies = [ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/server/Cargo.toml b/server/Cargo.toml index 5a7cbc6b..feb5c639 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.4.4" +version = "0.4.5" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 78de30dcf22d75cc62b7836e006e43d1f765cbf3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 May 2018 14:36:25 -0700 Subject: [PATCH 0114/1504] Fix missing colon in plugin stopped polling message --- plugin/src/Plugin.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/Plugin.lua b/plugin/src/Plugin.lua index a54adb93..fa0f4c72 100644 --- a/plugin/src/Plugin.lua +++ b/plugin/src/Plugin.lua @@ -122,7 +122,7 @@ function Plugin:stopPolling() return Promise.resolve(false) end - print("Rojo Stopped polling server for changes.") + print("Rojo: Stopped polling server for changes.") self._polling = false self._label.Enabled = false From c0f4b31ab35ea9402d68089a0e1d08fe2bc6fa0f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 May 2018 10:40:06 -0700 Subject: [PATCH 0115/1504] Make sure all descendants get removed from the RouteMap --- plugin/src/RouteMap.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/src/RouteMap.lua b/plugin/src/RouteMap.lua index a707f7cd..7b385ce1 100644 --- a/plugin/src/RouteMap.lua +++ b/plugin/src/RouteMap.lua @@ -57,6 +57,8 @@ function RouteMap:removeByRbx(rbx) self._reverseMap[rbx] = nil self._connectionsByRbx[rbx] = nil end + + self:removeRbxDescendants(rbx) end function RouteMap:removeRbxDescendants(parentRbx) From e9d33bdc02a3c36997904d6f21499e9a4d7b38a2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 May 2018 11:16:56 -0700 Subject: [PATCH 0116/1504] Skip reparenting if parent is the same --- plugin/src/Reconciler.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index b69929fa..49b7bfba 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -10,6 +10,10 @@ end local function reparent(rbx, parent) if rbx then + if rbx.Parent == parent then + return + end + -- It's possible that 'rbx' is a service or some other object that we -- can't change the parent of. That's the only reason why Parent would -- fail except for rbx being previously destroyed! From fd2cb3495ba02a63406de3e6e9d9cc365099407b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 May 2018 11:21:31 -0700 Subject: [PATCH 0117/1504] Make reconciler more robust with regards to RouteMap --- plugin/src/Reconciler.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 49b7bfba..a0ea06a8 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -143,6 +143,7 @@ function Reconciler:reconcile(rbx, item) -- Item was deleted if not item then if rbx then + self._routeMap:removeByRbx(rbx) rbx:Destroy() end @@ -156,9 +157,10 @@ function Reconciler:reconcile(rbx, item) -- Item changed type! if not classEqual(rbx, item.ClassName) then + self._routeMap:removeByRbx(rbx) rbx:Destroy() - rbx = self:_reify(item) + return self:_reify(item) end -- Apply all properties, Roblox will de-duplicate changes From 3bd191414bdb93b009d6e44aca11f5f3d2ed6138 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 May 2018 11:45:55 -0700 Subject: [PATCH 0118/1504] Update CHANGES --- CHANGES.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 988ad367..1e1aeb61 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,9 @@ # Rojo Change Log ## Current Master -*No changes* +* Folders should no longer get collapsed when syncing occurs. +* Improved robustness of route caching, which should catch the remaining script duplication bugs. +* Fixed message in plugin not being prefixed with `Rojo: `. ## 0.4.5 (May 1, 2018) * Rojo messages are now prefixed with `Rojo: ` to make them stand out in the output more. From 6fbe1daf8e5990e886b44f9cdf64cb8d70161655 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 May 2018 12:47:51 -0700 Subject: [PATCH 0119/1504] Add folder for testing script duplication bug --- test-project/src/a/b.lua | 1 + 1 file changed, 1 insertion(+) create mode 100644 test-project/src/a/b.lua diff --git a/test-project/src/a/b.lua b/test-project/src/a/b.lua new file mode 100644 index 00000000..de385843 --- /dev/null +++ b/test-project/src/a/b.lua @@ -0,0 +1 @@ +print("HEY!") \ No newline at end of file From 8b17d3b7d9c251af3f281b92f0d8b7e7bafda6b2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 May 2018 12:48:25 -0700 Subject: [PATCH 0120/1504] Intense robustness pass --- plugin/src/Plugin.lua | 4 ++- plugin/src/Reconciler.lua | 52 +++++++++++++++++++-------------------- plugin/src/RouteMap.lua | 38 ++++++++++++++++++++-------- 3 files changed, 57 insertions(+), 37 deletions(-) diff --git a/plugin/src/Plugin.lua b/plugin/src/Plugin.lua index fa0f4c72..498f6be3 100644 --- a/plugin/src/Plugin.lua +++ b/plugin/src/Plugin.lua @@ -66,7 +66,9 @@ end function Plugin:restart() warn("Rojo: The server has changed since the last request, reloading plugin...") - self._reconciler:clear() + self._reconciler:destruct() + self._reconciler = Reconciler.new() + self._api = nil self._polling = false self._syncInProgress = false diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index a0ea06a8..327aa839 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -1,13 +1,26 @@ local RouteMap = require(script.Parent.RouteMap) -local function classEqual(rbx, className) - if className == "*" then +local function classEqual(a, b) + if a == "*" or b == "*" then return true end - return rbx.ClassName == className + return a == b end +local function applyProperties(target, properties) + for key, property in pairs(properties) do + -- TODO: Transform property value based on property.Type + -- Right now, we assume that 'value' is primitive! + target[key] = property.Value + end +end + +--[[ + Attempt to parent `rbx` to `parent`, doing nothing if: + * parent is already `parent` + * Changing parent threw an error +]] local function reparent(rbx, parent) if rbx then if rbx.Parent == parent then @@ -42,7 +55,7 @@ local function findNextChildPair(primaryChildren, secondaryChildren, visited) visited[primaryChild] = true for _, secondaryChild in ipairs(secondaryChildren) do - if primaryChild.ClassName == secondaryChild.ClassName and primaryChild.Name == secondaryChild.Name then + if classEqual(primaryChild.ClassName, secondaryChild.ClassName) and primaryChild.Name == secondaryChild.Name then visited[secondaryChild] = true return primaryChild, secondaryChild @@ -114,12 +127,11 @@ function Reconciler:_reify(item) local rbx = Instance.new(className) rbx.Name = item.Name - for key, property in pairs(item.Properties) do - -- TODO: Check for compound types, like Vector3! - rbx[key] = property.Value - end + applyProperties(rbx, item.Properties) - self:_reconcileChildren(rbx, item) + for _, child in ipairs(item.Children) do + reparent(self:_reify(child), rbx) + end if item.Route then self._routeMap:insert(item.Route, rbx) @@ -129,10 +141,10 @@ function Reconciler:_reify(item) end --[[ - Clears any state that the Reconciler has, effectively restarting it. + Clears any state that the Reconciler has, stopping it completely. ]] -function Reconciler:clear() - self._routeMap:clear() +function Reconciler:destruct() + self._routeMap:destruct() end --[[ @@ -156,28 +168,16 @@ function Reconciler:reconcile(rbx, item) end -- Item changed type! - if not classEqual(rbx, item.ClassName) then + if not classEqual(rbx.ClassName, item.ClassName) then self._routeMap:removeByRbx(rbx) rbx:Destroy() return self:_reify(item) end - -- Apply all properties, Roblox will de-duplicate changes - for key, property in pairs(item.Properties) do - -- TODO: Transform property value based on property.Type - -- Right now, we assume that 'value' is primitive! - - rbx[key] = property.Value - end - - -- Use a dumb algorithm for reconciling children + applyProperties(rbx, item.Properties) self:_reconcileChildren(rbx, item) - if item.Route then - self._routeMap:insert(item.Route, rbx) - end - return rbx end diff --git a/plugin/src/RouteMap.lua b/plugin/src/RouteMap.lua index 7b385ce1..35d67ff6 100644 --- a/plugin/src/RouteMap.lua +++ b/plugin/src/RouteMap.lua @@ -25,6 +25,10 @@ end function RouteMap:insert(route, rbx) local hashed = hashRoute(route) + -- Make sure that each route and instance are only present in RouteMap once. + self:removeByRoute(route) + self:removeByRbx(rbx) + self._map[hashed] = rbx self._reverseMap[rbx] = hashed self._connectionsByRbx[rbx] = rbx.AncestryChanged:Connect(function(_, parent) @@ -42,26 +46,36 @@ function RouteMap:removeByRoute(route) local hashedRoute = hashRoute(route) local rbx = self._map[hashedRoute] - if rbx then - self._map[hashedRoute] = nil - self._reverseMap[rbx] = nil - self._connectionsByRbx[rbx] = nil + if rbx ~= nil then + self:_removeInternal(hashedRoute, rbx) end end function RouteMap:removeByRbx(rbx) local hashedRoute = self._reverseMap[rbx] - if hashedRoute then - self._map[hashedRoute] = nil - self._reverseMap[rbx] = nil - self._connectionsByRbx[rbx] = nil + if hashedRoute ~= nil then + self:_removeInternal(hashedRoute, rbx) end +end + +--[[ + Correcly removes the given Roblox Instance/Route pair from the RouteMap. +]] +function RouteMap:_removeInternal(rbx, hashedRoute) + self._map[hashedRoute] = nil + self._reverseMap[rbx] = nil + self._connectionsByRbx[rbx]:Disconnect() + self._connectionsByRbx[rbx] = nil self:removeRbxDescendants(rbx) end -function RouteMap:removeRbxDescendants(parentRbx) +--[[ + Ensure that there are no descendants of the given Roblox Instance still + present in the map, guaranteeing that it has been cleaned out. +]] +function RouteMap:_removeRbxDescendants(parentRbx) for rbx in pairs(self._reverseMap) do if rbx:IsDescendantOf(parentRbx) then self:removeByRbx(rbx) @@ -69,7 +83,11 @@ function RouteMap:removeRbxDescendants(parentRbx) end end -function RouteMap:clear() +--[[ + Remove all items from the map and disconnect all connections, cleaning up + the RouteMap. +]] +function RouteMap:destruct() self._map = {} self._reverseMap = {} From f777d1b6c68750b4ca40ee82656e846c4538ae74 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 May 2018 12:52:46 -0700 Subject: [PATCH 0121/1504] Update CHANGES --- CHANGES.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 1e1aeb61..e9208308 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,7 +2,8 @@ ## Current Master * Folders should no longer get collapsed when syncing occurs. -* Improved robustness of route caching, which should catch the remaining script duplication bugs. +* **Significant** robustness improvements with regards to caching. + * If there are any bugs with script duplication or caching in the future, restarting the Rojo server process should fix them for that session. * Fixed message in plugin not being prefixed with `Rojo: `. ## 0.4.5 (May 1, 2018) From 533c8ddaf75a37e7903810457392482b4b3fdbd6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 May 2018 12:55:41 -0700 Subject: [PATCH 0122/1504] Update CHANGES --- CHANGES.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index e9208308..096c33f3 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,9 +1,10 @@ # Rojo Change Log -## Current Master +## Current master * Folders should no longer get collapsed when syncing occurs. * **Significant** robustness improvements with regards to caching. - * If there are any bugs with script duplication or caching in the future, restarting the Rojo server process should fix them for that session. + * **This should catch all existing script duplication bugs.** + * If there are any bugs with script duplication or caching in the future, restarting the Rojo server process will fix them for that session. * Fixed message in plugin not being prefixed with `Rojo: `. ## 0.4.5 (May 1, 2018) From 000ff351a561d7551672f80a4104840cfc0a96f3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 May 2018 13:05:52 -0700 Subject: [PATCH 0123/1504] Improve plugin handling with regards to restarts and UI Closes #67. --- plugin/src/Plugin.lua | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/plugin/src/Plugin.lua b/plugin/src/Plugin.lua index 498f6be3..eae50920 100644 --- a/plugin/src/Plugin.lua +++ b/plugin/src/Plugin.lua @@ -1,9 +1,12 @@ +local CoreGui = game:GetService("CoreGui") + local Promise = require(script.Parent.Parent.modules.Promise) local Config = require(script.Parent.Config) local Http = require(script.Parent.Http) local Api = require(script.Parent.Api) local Reconciler = require(script.Parent.Reconciler) +local Version = require(script.Parent.Version) local function collectMatch(source, pattern) local result = {} @@ -35,9 +38,23 @@ function Plugin.new() setmetatable(self, Plugin) do + local uiName = ("Rojo %s UI"):format(Version.display(Config.version)) + + if Config.dev then + uiName = "Rojo Dev UI" + end + + -- If there's an existing Rojo UI, like from a Roblox plugin upgrade + -- that wasn't Rojo, make sure we clean it up. + local existingUi = CoreGui:FindFirstChild(uiName) + + if existingUi ~= nil then + existingUi:Destroy() + end + local screenGui = Instance.new("ScreenGui") - screenGui.Name = "Rojo UI" - screenGui.Parent = game.CoreGui + screenGui.Name = uiName + screenGui.Parent = CoreGui screenGui.DisplayOrder = -1 screenGui.Enabled = false @@ -54,6 +71,18 @@ function Plugin.new() label.Parent = screenGui self._label = screenGui + + -- If our UI was destroyed, we assume it was from another instance of + -- the Rojo plugin coming online. + -- + -- Roblox doesn't notify plugins when they get unloaded, so this is the + -- best trigger we have right now unless we create a dedicated event + -- object. + screenGui.AncestryChanged:Connect(function(_, parent) + if parent == nil then + self:restart() + end + end) end return self @@ -66,6 +95,8 @@ end function Plugin:restart() warn("Rojo: The server has changed since the last request, reloading plugin...") + self:stopPolling() + self._reconciler:destruct() self._reconciler = Reconciler.new() From 3137753afa8c0adf044fd6222eb8f4c995fffa62 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 May 2018 13:09:00 -0700 Subject: [PATCH 0124/1504] Update CHANGES --- CHANGES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGES.md b/CHANGES.md index 096c33f3..3dd10975 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,7 @@ # Rojo Change Log ## Current master +* Rojo handles being restarted by Roblox Studio more gracefully ([#67](https://github.com/LPGhatguy/rojo/issues/67)) * Folders should no longer get collapsed when syncing occurs. * **Significant** robustness improvements with regards to caching. * **This should catch all existing script duplication bugs.** From 910be640e95094fceb42a58f742ad50dd2fdc2b5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 May 2018 13:26:25 -0700 Subject: [PATCH 0125/1504] Release 0.4.6 --- CHANGES.md | 3 +++ README.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.lock | 2 +- server/Cargo.toml | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 3dd10975..61d7e81b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,9 @@ # Rojo Change Log ## Current master +* *No changes* + +## 0.4.6 (May 21, 2018) * Rojo handles being restarted by Roblox Studio more gracefully ([#67](https://github.com/LPGhatguy/rojo/issues/67)) * Folders should no longer get collapsed when syncing occurs. * **Significant** robustness improvements with regards to caching. diff --git a/README.md b/README.md index 7b4365a1..fdb2dbbe 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Travis-CI Build Status - Current server version + Current server version Rojo Documentation diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 55906858..d945ad67 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { pollingRate = 0.2, - version = {0, 4, 5}, + version = {0, 4, 6}, expectedServerVersionString = "0.4.x", protocolVersion = 1, dev = false, diff --git a/server/Cargo.lock b/server/Cargo.lock index 32f5b742..e4b98085 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -636,7 +636,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.4.5" +version = "0.4.6" dependencies = [ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/server/Cargo.toml b/server/Cargo.toml index feb5c639..884b72fb 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.4.5" +version = "0.4.6" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 7d24a14004b4f303ff15aa2aed865eb0f300a391 Mon Sep 17 00:00:00 2001 From: Jonathan Holmes Date: Wed, 23 May 2018 05:52:55 +1200 Subject: [PATCH 0126/1504] Added plugin icons to Rojo (#70) --- assets/rojo-polling-icon.png | Bin 0 -> 375 bytes assets/rojo-sync-in.png | Bin 0 -> 382 bytes assets/rojo-test-icon.png | Bin 0 -> 430 bytes plugin/src/Config.lua | 5 +++++ plugin/src/Main.server.lua | 6 +++--- 5 files changed, 8 insertions(+), 3 deletions(-) create mode 100644 assets/rojo-polling-icon.png create mode 100644 assets/rojo-sync-in.png create mode 100644 assets/rojo-test-icon.png diff --git a/assets/rojo-polling-icon.png b/assets/rojo-polling-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..c0bcfaac87d5b077bbaed07bf482d9ed55497e27 GIT binary patch literal 375 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmUKs7M+SzC{oH>NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!CBxDS21sKVp<&7Yj08)YrcEAssUev|Hhs#+s| zOk(;4rqssgZ}-*yG4FmNa3;cw$!JsRB}2!}r!pIFI<8{q({x{K()ePB5N|NcrpI08 zbx{kdVh%EkFtV@Ir^4oD-3v@W^j}@!KgTn{+sip_eCOHKFun7`E)hn> z$sJWDjEa*iUInnW+_Z^xxZtN6E#zSEIPmOJru)yzS=J@S-cy#gIjB1M$OWJW7(8A5 KT-G@yGywn_n}03< literal 0 HcmV?d00001 diff --git a/assets/rojo-sync-in.png b/assets/rojo-sync-in.png new file mode 100644 index 0000000000000000000000000000000000000000..90e7fd0d4876054e4a6eadf7fa9d748a80e80f60 GIT binary patch literal 382 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=fdzmUKs7M+SzC{oH>NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!CBxDSa_frA*_i`{BuiW)N`mv#O3D+9QW**oGxJLH@={9_O!N%&j0`_2 zWKIPt+T-cs7!u+B_Cg|GlL3!IVjlBzgLxgsRqIb0Uz>7qW1hyv8}joNBO~ScG?xaS zeY_=!uTn=}UDsYeab+4`<%Tb1JMBKqnLqu-Q-gM!h+mT#m6((inBo}!L@=8Q3NQ+O zh-cK<@Pfg+u7BH{-^>SEH*Hw9P3A1)2bYRzi?tc51@Aq5!Pg*qag$6t(*otF>B+(e zRA!TNSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!CBxDSa_frA*_i`{BuiW)N`mv#O3D+9QW**oGxJLH@={9_O!N%&j0`_2 zWKIPtdgJNh7!u+B_F^F4Aq4@J3-{d4C)!L*{}Oki<^s=S5iSj>x5v9vr^l)law^tL z(LI;aZG1DS$a-$`CF{jGh6kI!pDrzB`EiP2#nuZy-z+fLpw4h#^XFfNA7x&jZ#sVb zaINVU^VYhu0GpVqhMoVSnXmZpH&|y?G0aQ+FV1k^>wP+VYvV! Date: Tue, 22 May 2018 10:55:23 -0700 Subject: [PATCH 0127/1504] Update CHANGES --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 61d7e81b..8e3a8b20 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,7 @@ # Rojo Change Log ## Current master -* *No changes* +* Added icons to the Rojo plugin, made by [@Vorlias](https://github.com/Vorlias)! ([#70](https://github.com/LPGhatguy/rojo/pull/70)) ## 0.4.6 (May 21, 2018) * Rojo handles being restarted by Roblox Studio more gracefully ([#67](https://github.com/LPGhatguy/rojo/issues/67)) From aa5f0cc3354076a23f7522e23482c40a393c4b42 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 22 May 2018 11:04:53 -0700 Subject: [PATCH 0128/1504] Issue a warning if no partitions are specified during serve. Closes #40 --- CHANGES.md | 1 + server/src/commands/serve.rs | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index 8e3a8b20..5ddab829 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## Current master * Added icons to the Rojo plugin, made by [@Vorlias](https://github.com/Vorlias)! ([#70](https://github.com/LPGhatguy/rojo/pull/70)) +* Server will now issue a warning if no partitions are specified in `rojo serve` ([#40](https://github.com/LPGhatguy/rojo/issues/40)) ## 0.4.6 (May 21, 2018) * Rojo handles being restarted by Roblox Studio more gracefully ([#67](https://github.com/LPGhatguy/rojo/issues/67)) diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index d0c41b5d..eb841807 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -44,6 +44,13 @@ pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { }, }; + if project.partitions.len() == 0 { + println!(""); + println!("This project has no partitions and will not do anything when served!"); + println!("This is usually a mistake -- edit rojo.json!"); + println!(""); + } + lazy_static! { static ref PLUGIN_CHAIN: PluginChain = PluginChain::new(vec![ Box::new(ScriptPlugin::new()), From c856a3e36139e96e0ebda8010c007668661e7b9b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 25 May 2018 23:31:01 -0700 Subject: [PATCH 0129/1504] Release 0.4.7 --- CHANGES.md | 3 +++ README.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.lock | 2 +- server/Cargo.toml | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5ddab829..dc836788 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,9 @@ # Rojo Change Log ## Current master +* *No changes* + +## 0.4.7 (May 25, 2018) * Added icons to the Rojo plugin, made by [@Vorlias](https://github.com/Vorlias)! ([#70](https://github.com/LPGhatguy/rojo/pull/70)) * Server will now issue a warning if no partitions are specified in `rojo serve` ([#40](https://github.com/LPGhatguy/rojo/issues/40)) diff --git a/README.md b/README.md index fdb2dbbe..f7538146 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Travis-CI Build Status - Current server version + Current server version Rojo Documentation diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index d0c3c940..1b526126 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { pollingRate = 0.2, - version = {0, 4, 6}, + version = {0, 4, 7}, expectedServerVersionString = "0.4.x", protocolVersion = 1, icons = { diff --git a/server/Cargo.lock b/server/Cargo.lock index e4b98085..b73360a5 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -636,7 +636,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.4.6" +version = "0.4.7" dependencies = [ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/server/Cargo.toml b/server/Cargo.toml index 884b72fb..5842ee1b 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.4.6" +version = "0.4.7" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 6ad763fc01e14cbd2b4aed3db4263cc224882892 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 25 May 2018 23:40:34 -0700 Subject: [PATCH 0130/1504] Fix flip-flopped arguments in RouteMap:_removeInternal --- CHANGES.md | 2 +- plugin/src/RouteMap.lua | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index dc836788..d7517dbc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,7 @@ # Rojo Change Log ## Current master -* *No changes* +* Hotfix to prevent errors from being thrown when objects managed by Rojo are deleted ## 0.4.7 (May 25, 2018) * Added icons to the Rojo plugin, made by [@Vorlias](https://github.com/Vorlias)! ([#70](https://github.com/LPGhatguy/rojo/pull/70)) diff --git a/plugin/src/RouteMap.lua b/plugin/src/RouteMap.lua index 35d67ff6..0e0ceb65 100644 --- a/plugin/src/RouteMap.lua +++ b/plugin/src/RouteMap.lua @@ -47,7 +47,7 @@ function RouteMap:removeByRoute(route) local rbx = self._map[hashedRoute] if rbx ~= nil then - self:_removeInternal(hashedRoute, rbx) + self:_removeInternal(rbx, hashedRoute) end end @@ -55,7 +55,7 @@ function RouteMap:removeByRbx(rbx) local hashedRoute = self._reverseMap[rbx] if hashedRoute ~= nil then - self:_removeInternal(hashedRoute, rbx) + self:_removeInternal(rbx, hashedRoute) end end From c2495ed57f212367e94ffaaf37e5e960b0e7967b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 25 May 2018 23:42:31 -0700 Subject: [PATCH 0131/1504] Release 0.4.8 (oops) --- CHANGES.md | 3 +++ README.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.lock | 2 +- server/Cargo.toml | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d7517dbc..1af9bfb7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,9 @@ # Rojo Change Log ## Current master +* *No changes* + +## 0.4.8 (May 26, 2018) * Hotfix to prevent errors from being thrown when objects managed by Rojo are deleted ## 0.4.7 (May 25, 2018) diff --git a/README.md b/README.md index f7538146..2af08ccf 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Travis-CI Build Status - Current server version + Current server version Rojo Documentation diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 1b526126..2d676c9e 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { pollingRate = 0.2, - version = {0, 4, 7}, + version = {0, 4, 8}, expectedServerVersionString = "0.4.x", protocolVersion = 1, icons = { diff --git a/server/Cargo.lock b/server/Cargo.lock index b73360a5..2e752b5f 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -636,7 +636,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.4.7" +version = "0.4.8" dependencies = [ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/server/Cargo.toml b/server/Cargo.toml index 5842ee1b..e031883f 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.4.7" +version = "0.4.8" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From fcfd55ff76eb0561ca6879e43c82d9b2863daa93 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 26 May 2018 16:19:58 -0700 Subject: [PATCH 0132/1504] Fix error in RouteMap Closes #72. --- plugin/src/RouteMap.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/RouteMap.lua b/plugin/src/RouteMap.lua index 0e0ceb65..8dc92fc7 100644 --- a/plugin/src/RouteMap.lua +++ b/plugin/src/RouteMap.lua @@ -68,7 +68,7 @@ function RouteMap:_removeInternal(rbx, hashedRoute) self._connectionsByRbx[rbx]:Disconnect() self._connectionsByRbx[rbx] = nil - self:removeRbxDescendants(rbx) + self:_removeRbxDescendants(rbx) end --[[ From 9ac537d38fdc2f09c4c13f888c2b7d9dc69036cc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 26 May 2018 16:23:09 -0700 Subject: [PATCH 0133/1504] Add entry to CHANGES --- CHANGES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 1af9bfb7..9f5beab8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,7 @@ # Rojo Change Log ## Current master -* *No changes* +* Fixed warning when renaming or removing files that would sometimes corrupt the instance cache (#72) ## 0.4.8 (May 26, 2018) * Hotfix to prevent errors from being thrown when objects managed by Rojo are deleted From 0936c7c97d51ef621664514d43bce86f2d67a9de Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 26 May 2018 16:23:13 -0700 Subject: [PATCH 0134/1504] Fix indentation in CHANGES --- CHANGES.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 9f5beab8..82cb68dc 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -32,11 +32,11 @@ ## 0.4.3 (April 7, 2018) * Plugin now automatically selects `HttpService` if it determines that HTTP isn't enabled ([#58](https://github.com/LPGhatguy/rojo/pull/58)) * Plugin now has much more robust handling and will wipe all state when the server changes. - * This should fix issues that would otherwise be solved by restarting Roblox Studio. + * This should fix issues that would otherwise be solved by restarting Roblox Studio. ## 0.4.2 (April 4, 2018) * Fixed final case of duplicated instance insertion, caused by reconciled instances not being inserted into `RouteMap`. - * The reconciler is still not a perfect solution, especially if script instances get moved around without being destroyed. I don't think this can be fixed before a big refactor. + * The reconciler is still not a perfect solution, especially if script instances get moved around without being destroyed. I don't think this can be fixed before a big refactor. ## 0.4.1 (April 1, 2018) * Merged plugin repository into main Rojo repository for easier tracking. @@ -44,9 +44,9 @@ ## 0.4.0 (March 27, 2018) * Protocol version 1, which shifts more responsibility onto the server - * This is a **major breaking** change! - * The server now has a content of 'filter plugins', which transform data at various stages in the pipeline - * The server now exposes Roblox instance objects instead of file contents, which lines up with how `rojo pack` will work, and paves the way for more robust syncing. + * This is a **major breaking** change! + * The server now has a content of 'filter plugins', which transform data at various stages in the pipeline + * The server now exposes Roblox instance objects instead of file contents, which lines up with how `rojo pack` will work, and paves the way for more robust syncing. * Added `*.model.json` files, which let you embed small Roblox objects into your Rojo tree. * Improved error messages in some cases ([#46](https://github.com/LPGhatguy/rojo/issues/46)) @@ -56,18 +56,18 @@ ## 0.3.1 (December 14, 2017) * Improved error reporting when invalid JSON is found in a `rojo.json` project - * These messages are passed on from Serde + * These messages are passed on from Serde ## 0.3.0 (December 12, 2017) * Factored out the plugin into a separate repository * Fixed server when using a file as a partition - * Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory! + * Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory! * Started running automatic tests on Travis CI (#9) ## 0.2.3 (December 4, 2017) * Plugin only release * Tightened `init` file rules to only match script files - * Previously, Rojo would sometimes pick up the wrong file when syncing + * Previously, Rojo would sometimes pick up the wrong file when syncing ## 0.2.2 (December 1, 2017) * Plugin only release From 40c41b440009ede7bc022ca60badc18e408e8809 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 26 May 2018 16:41:38 -0700 Subject: [PATCH 0135/1504] Update Sync Details docs to mention how JSON models work. Closes #71. --- docs/sync-details.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/sync-details.md b/docs/sync-details.md index 40dfb285..21448fc0 100644 --- a/docs/sync-details.md +++ b/docs/sync-details.md @@ -26,13 +26,16 @@ Will turn into these instances in Roblox: ![Example of Roblox instances](/images/sync-example.png) ## Models -Rojo supports a JSON model format for representing simple models. It's designed for instance types like `BindableEvent` or `*Value` objects, and is not suitable for larger models. +Rojo supports a JSON model format for representing simple models. It's designed for instance types like `BindableEvent` or `Value` objects, and is not suitable for larger models. + +Rojo JSON models are stored in `.model.json` files. !!! info In the future, Rojo will support `.rbxmx` models. See [issue #7](https://github.com/LPGhatguy/rojo/issues/7) for more details and updates on this feature. JSON model files are strict, with every property being required. They look like this: +`hello.model.json` ```json { "Name": "hello", From e7fe4ac3ecbb368ad9ae35700cca7bdc4a07d7be Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 26 May 2018 16:44:25 -0700 Subject: [PATCH 0136/1504] Remove vestigial backwards syncing functionality. This functionality won't be present until the refactor in 0.5.0 --- server/src/plugin.rs | 22 ---------------------- server/src/plugins/default_plugin.rs | 6 +----- server/src/plugins/json_model_plugin.rs | 6 +----- server/src/plugins/script_plugin.rs | 6 +----- 4 files changed, 3 insertions(+), 37 deletions(-) diff --git a/server/src/plugin.rs b/server/src/plugin.rs index 2f25bf55..82999535 100644 --- a/server/src/plugin.rs +++ b/server/src/plugin.rs @@ -9,13 +9,6 @@ pub enum TransformFileResult { // TODO: Error case } -pub enum RbxChangeResult { - Write(Option), - Pass, - - // TODO: Error case -} - pub enum FileChangeResult { MarkChanged(Option>), Pass, @@ -26,10 +19,6 @@ pub trait Plugin { /// into a Roblox instance. fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult; - /// Invoked when a Roblox Instance change is reported by the Roblox Studio - /// plugin and needs to be turned into a file to save. - fn handle_rbx_change(&self, route: &Route, rbx_item: &RbxInstance) -> RbxChangeResult; - /// Invoked when a file changes on the filesystem. The result defines what /// routes are marked as needing to be refreshed. fn handle_file_change(&self, route: &Route) -> FileChangeResult; @@ -58,17 +47,6 @@ impl PluginChain { None } - pub fn handle_rbx_change(&self, route: &Route, rbx_item: &RbxInstance) -> Option { - for plugin in &self.plugins { - match plugin.handle_rbx_change(route, rbx_item) { - RbxChangeResult::Write(vfs_item) => return vfs_item, - RbxChangeResult::Pass => {}, - } - } - - None - } - pub fn handle_file_change(&self, route: &Route) -> Option> { for plugin in &self.plugins { match plugin.handle_file_change(route) { diff --git a/server/src/plugins/default_plugin.rs b/server/src/plugins/default_plugin.rs index 56d2a2eb..6d2866d3 100644 --- a/server/src/plugins/default_plugin.rs +++ b/server/src/plugins/default_plugin.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use core::Route; -use plugin::{Plugin, PluginChain, TransformFileResult, RbxChangeResult, FileChangeResult}; +use plugin::{Plugin, PluginChain, TransformFileResult, FileChangeResult}; use rbx::{RbxInstance, RbxValue}; use vfs::VfsItem; @@ -60,8 +60,4 @@ impl Plugin for DefaultPlugin { fn handle_file_change(&self, route: &Route) -> FileChangeResult { FileChangeResult::MarkChanged(Some(vec![route.clone()])) } - - fn handle_rbx_change(&self, _route: &Route, _rbx_item: &RbxInstance) -> RbxChangeResult { - RbxChangeResult::Pass - } } diff --git a/server/src/plugins/json_model_plugin.rs b/server/src/plugins/json_model_plugin.rs index 0a5a8da9..2deee6ea 100644 --- a/server/src/plugins/json_model_plugin.rs +++ b/server/src/plugins/json_model_plugin.rs @@ -2,7 +2,7 @@ use regex::Regex; use serde_json; use core::Route; -use plugin::{Plugin, PluginChain, TransformFileResult, RbxChangeResult, FileChangeResult}; +use plugin::{Plugin, PluginChain, TransformFileResult, FileChangeResult}; use rbx::RbxInstance; use vfs::VfsItem; @@ -48,8 +48,4 @@ impl Plugin for JsonModelPlugin { fn handle_file_change(&self, _route: &Route) -> FileChangeResult { FileChangeResult::Pass } - - fn handle_rbx_change(&self, _route: &Route, _rbx_item: &RbxInstance) -> RbxChangeResult { - RbxChangeResult::Pass - } } diff --git a/server/src/plugins/script_plugin.rs b/server/src/plugins/script_plugin.rs index dabe8d5c..feb5198d 100644 --- a/server/src/plugins/script_plugin.rs +++ b/server/src/plugins/script_plugin.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use regex::Regex; use core::Route; -use plugin::{Plugin, PluginChain, TransformFileResult, RbxChangeResult, FileChangeResult}; +use plugin::{Plugin, PluginChain, TransformFileResult, FileChangeResult}; use rbx::{RbxInstance, RbxValue}; use vfs::VfsItem; @@ -117,8 +117,4 @@ impl Plugin for ScriptPlugin { FileChangeResult::Pass } } - - fn handle_rbx_change(&self, _route: &Route, _rbx_item: &RbxInstance) -> RbxChangeResult { - RbxChangeResult::Pass - } } From 804bbc93b7d061b46588eeb9a7d776b007c4c5b9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 26 May 2018 16:59:09 -0700 Subject: [PATCH 0137/1504] Make JSON models less strict --- CHANGES.md | 1 + server/src/rbx.rs | 4 ++++ test-project/src/hello.model.json | 8 ++------ 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 82cb68dc..5e18cae7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## Current master * Fixed warning when renaming or removing files that would sometimes corrupt the instance cache (#72) +* JSON models are no longer as strict -- `Children` and `Properties` are now optional. ## 0.4.8 (May 26, 2018) * Hotfix to prevent errors from being thrown when objects managed by Rojo are deleted diff --git a/server/src/rbx.rs b/server/src/rbx.rs index f411242f..14d3b8cd 100644 --- a/server/src/rbx.rs +++ b/server/src/rbx.rs @@ -6,7 +6,11 @@ use std::collections::HashMap; pub struct RbxInstance { pub name: String, pub class_name: String, + + #[serde(default = "Vec::new")] pub children: Vec, + + #[serde(default = "HashMap::new")] pub properties: HashMap, /// The route that this instance was generated from, if there was one. diff --git a/test-project/src/hello.model.json b/test-project/src/hello.model.json index bc707e8d..c0afd96f 100644 --- a/test-project/src/hello.model.json +++ b/test-project/src/hello.model.json @@ -4,14 +4,11 @@ "Children": [ { "Name": "Some Part", - "ClassName": "Part", - "Children": [], - "Properties": {} + "ClassName": "Part" }, { "Name": "Some StringValue", "ClassName": "StringValue", - "Children": [], "Properties": { "Value": { "Type": "String", @@ -19,6 +16,5 @@ } } } - ], - "Properties": {} + ] } \ No newline at end of file From 7e4d451765ef8c82e2b864d8968362d432f1bd36 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 26 May 2018 17:00:23 -0700 Subject: [PATCH 0138/1504] Update Sync Details docs --- docs/sync-details.md | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/docs/sync-details.md b/docs/sync-details.md index 21448fc0..3642fc7c 100644 --- a/docs/sync-details.md +++ b/docs/sync-details.md @@ -33,7 +33,7 @@ Rojo JSON models are stored in `.model.json` files. !!! info In the future, Rojo will support `.rbxmx` models. See [issue #7](https://github.com/LPGhatguy/rojo/issues/7) for more details and updates on this feature. -JSON model files are strict, with every property being required. They look like this: +JSON model files are fairly strict; any syntax errors will cause the model to fail to sync! They look like this: `hello.model.json` ```json @@ -43,14 +43,11 @@ JSON model files are strict, with every property being required. They look like "Children": [ { "Name": "Some Part", - "ClassName": "Part", - "Children": [], - "Properties": {} + "ClassName": "Part" }, { "Name": "Some StringValue", "ClassName": "StringValue", - "Children": [], "Properties": { "Value": { "Type": "String", @@ -58,7 +55,6 @@ JSON model files are strict, with every property being required. They look like } } } - ], - "Properties": {} + ] } ``` \ No newline at end of file From 0d6e3e66cec60ad4fd7c6628ca0fff8a443fd764 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 26 May 2018 17:02:04 -0700 Subject: [PATCH 0139/1504] Release 0.4.9 --- CHANGES.md | 5 ++++- README.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.lock | 2 +- server/Cargo.toml | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5e18cae7..b0a100e9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,10 @@ # Rojo Change Log ## Current master -* Fixed warning when renaming or removing files that would sometimes corrupt the instance cache (#72) +* *No changes* + +## 0.4.9 (May 26, 2018) +* Fixed warning when renaming or removing files that would sometimes corrupt the instance cache ([#72](https://github.com/LPGhatguy/rojo/pull/72)) * JSON models are no longer as strict -- `Children` and `Properties` are now optional. ## 0.4.8 (May 26, 2018) diff --git a/README.md b/README.md index 2af08ccf..9aeb947e 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Travis-CI Build Status - Current server version + Current server version Rojo Documentation diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 2d676c9e..ea77b75a 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { pollingRate = 0.2, - version = {0, 4, 8}, + version = {0, 4, 9}, expectedServerVersionString = "0.4.x", protocolVersion = 1, icons = { diff --git a/server/Cargo.lock b/server/Cargo.lock index 2e752b5f..d3592280 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -636,7 +636,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.4.8" +version = "0.4.9" dependencies = [ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/server/Cargo.toml b/server/Cargo.toml index e031883f..f5df7b74 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.4.8" +version = "0.4.9" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From f4d7dda8e3da4a409aa3d5d549b527f1966e9d96 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 26 May 2018 17:19:37 -0700 Subject: [PATCH 0140/1504] Make docs on JSON model versioning more explicit --- docs/sync-details.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/sync-details.md b/docs/sync-details.md index 3642fc7c..21bf340b 100644 --- a/docs/sync-details.md +++ b/docs/sync-details.md @@ -33,6 +33,9 @@ Rojo JSON models are stored in `.model.json` files. !!! info In the future, Rojo will support `.rbxmx` models. See [issue #7](https://github.com/LPGhatguy/rojo/issues/7) for more details and updates on this feature. +!!! warning + Prior to version 0.4.9, the `Properties` and `Children` properties are required on all instances in JSON models! + JSON model files are fairly strict; any syntax errors will cause the model to fail to sync! They look like this: `hello.model.json` From 4b2f27b26df64a06423bc848f205d9ad5417c861 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Jun 2018 22:17:54 -0700 Subject: [PATCH 0141/1504] Fix error when targeting invalid services --- CHANGES.md | 2 +- plugin/src/Reconciler.lua | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b0a100e9..b7076d2d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,7 @@ # Rojo Change Log ## Current master -* *No changes* +* Fixed obscure error when syncing into an invalid service ## 0.4.9 (May 26, 2018) * Fixed warning when renaming or removing files that would sometimes corrupt the instance cache ([#72](https://github.com/LPGhatguy/rojo/pull/72)) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 327aa839..fd3ab6cf 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -192,12 +192,17 @@ function Reconciler:reconcileRoute(route, item, itemRoute) -- We should get services instead of making folders here. if rbx == game and not child then - local _ - _, child = pcall(game.GetService, game, piece) + local success + success, child = pcall(game.GetService, game, piece) + + -- That isn't a valid service! + if not success then + child = nil + end end -- We don't want to create a folder if we're reaching our target item! - if not child and i ~= #route then + if child == nil and i ~= #route then child = Instance.new("Folder") child.Parent = rbx child.Name = piece @@ -208,7 +213,7 @@ function Reconciler:reconcileRoute(route, item, itemRoute) end -- Let's check the route map! - if not rbx then + if rbx == nil then rbx = self._routeMap:get(itemRoute) end From b60bfc7495506ead44ca77fd1c8fea942d5f04e7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Jun 2018 22:21:59 -0700 Subject: [PATCH 0142/1504] Make nil checks more robust. This represents an evolution in how I've been thinking about Lua -- using boolean coercion is generally a bad idea I think because it obscures the underlying types. It also makes it so that if a boolean is eronneously passed into a function, and it happens to be a 'false' value, it will be coerced into the nil case instead of being reported as an error, no matter how unintuitive the resulting error might be. --- plugin/src/Reconciler.lua | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index fd3ab6cf..8158ddd6 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -94,7 +94,7 @@ function Reconciler:_reconcileChildren(rbx, item) while true do local itemChild, rbxChild = findNextChildPair(item.Children, rbxChildren, visited) - if not itemChild then + if itemChild == nil then break end @@ -105,7 +105,7 @@ function Reconciler:_reconcileChildren(rbx, item) while true do local rbxChild, itemChild = findNextChildPair(rbxChildren, item.Children, visited) - if not rbxChild then + if rbxChild == nil then break end @@ -133,7 +133,7 @@ function Reconciler:_reify(item) reparent(self:_reify(child), rbx) end - if item.Route then + if item.Route ~= nil then self._routeMap:insert(item.Route, rbx) end @@ -153,8 +153,8 @@ end ]] function Reconciler:reconcile(rbx, item) -- Item was deleted - if not item then - if rbx then + if item == nil then + if rbx ~= nil then self._routeMap:removeByRbx(rbx) rbx:Destroy() end @@ -163,7 +163,7 @@ function Reconciler:reconcile(rbx, item) end -- Item was created! - if not rbx then + if rbx == nil then return self:_reify(item) end @@ -191,7 +191,7 @@ function Reconciler:reconcileRoute(route, item, itemRoute) local child = rbx:FindFirstChild(piece) -- We should get services instead of making folders here. - if rbx == game and not child then + if rbx == game and child == nil then local success success, child = pcall(game.GetService, game, piece) From a86347ea323a8e71705eb40f94897cc00861e823 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Jun 2018 22:34:11 -0700 Subject: [PATCH 0143/1504] Add typechecks to reconciler and improve robustness a touch --- plugin/src/Reconciler.lua | 39 +++++++++++++++++++++++++++------------ 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 8158ddd6..19e2d3d1 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -1,6 +1,9 @@ local RouteMap = require(script.Parent.RouteMap) local function classEqual(a, b) + assert(typeof(a) == "string") + assert(typeof(b) == "string") + if a == "*" or b == "*" then return true end @@ -9,6 +12,9 @@ local function classEqual(a, b) end local function applyProperties(target, properties) + assert(typeof(target) == "Instance") + assert(typeof(properties) == "table") + for key, property in pairs(properties) do -- TODO: Transform property value based on property.Type -- Right now, we assume that 'value' is primitive! @@ -22,18 +28,19 @@ end * Changing parent threw an error ]] local function reparent(rbx, parent) - if rbx then - if rbx.Parent == parent then - return - end + assert(typeof(rbx) == "Instance") + assert(typeof(parent) == "Instance") - -- It's possible that 'rbx' is a service or some other object that we - -- can't change the parent of. That's the only reason why Parent would - -- fail except for rbx being previously destroyed! - pcall(function() - rbx.Parent = parent - end) + if rbx.Parent == parent then + return end + + -- Setting `Parent` can fail if: + -- * The object has been destroyed + -- * The object is a service and cannot be reparented + pcall(function() + rbx.Parent = parent + end) end --[[ @@ -98,7 +105,11 @@ function Reconciler:_reconcileChildren(rbx, item) break end - reparent(self:reconcile(rbxChild, itemChild), rbx) + local newRbxChild = self:reconcile(rbxChild, itemChild) + + if newRbxChild ~= nil then + newRbxChild.Parent = rbx + end end -- Reconcile any children that were deleted @@ -109,7 +120,11 @@ function Reconciler:_reconcileChildren(rbx, item) break end - reparent(self:reconcile(rbxChild, itemChild), rbx) + local newRbxChild = self:reconcile(rbxChild, itemChild) + + if newRbxChild ~= nil then + newRbxChild.Parent = rbx + end end end From c894b38f06300aca83273a3b10ddc7ef9c046ce8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Jun 2018 23:11:50 -0700 Subject: [PATCH 0144/1504] Improve plugin API robustness --- CHANGES.md | 1 + plugin/src/Api.lua | 5 +++-- plugin/src/Plugin.lua | 47 +++++++++++++++++++++++++------------------ 3 files changed, 31 insertions(+), 22 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index b7076d2d..1788e524 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## Current master * Fixed obscure error when syncing into an invalid service +* Fixed multiple sync processes occurring when a server ID mismatch is detected ## 0.4.9 (May 26, 2018) * Fixed warning when renaming or removing files that would sometimes corrupt the instance cache ([#72](https://github.com/LPGhatguy/rojo/pull/72)) diff --git a/plugin/src/Api.lua b/plugin/src/Api.lua index 163c4d1e..317f6282 100644 --- a/plugin/src/Api.lua +++ b/plugin/src/Api.lua @@ -35,6 +35,9 @@ function Api.connect(http) setmetatable(context, Api) return context:_start() + :andThen(function() + return context + end) end function Api:_start() @@ -60,8 +63,6 @@ function Api:_start() self.serverId = response.serverId self.currentTime = response.currentTime - - return self end) end diff --git a/plugin/src/Plugin.lua b/plugin/src/Plugin.lua index eae50920..89c88117 100644 --- a/plugin/src/Plugin.lua +++ b/plugin/src/Plugin.lua @@ -8,6 +8,9 @@ local Api = require(script.Parent.Api) local Reconciler = require(script.Parent.Reconciler) local Version = require(script.Parent.Version) +local MESSAGE_SERVER_CHANGED = "Rojo: The server has changed since the last request, reloading plugin..." +local MESSAGE_PLUGIN_CHANGED = "Rojo: Another instance of Rojo came online, unloading..." + local function collectMatch(source, pattern) local result = {} @@ -80,6 +83,7 @@ function Plugin.new() -- object. screenGui.AncestryChanged:Connect(function(_, parent) if parent == nil then + warn(MESSAGE_PLUGIN_CHANGED) self:restart() end end) @@ -93,8 +97,6 @@ end restarted. ]] function Plugin:restart() - warn("Rojo: The server has changed since the last request, reloading plugin...") - self:stopPolling() self._reconciler:destruct() @@ -105,22 +107,25 @@ function Plugin:restart() self._syncInProgress = false end -function Plugin:api() - if not self._api then - self._api = Api.connect(self._http) - :catch(function(err) - self._api = nil +function Plugin:getApi() + if self._api == nil then + return Api.connect(self._http) + :andThen(function(api) + self._api = api + + return api + end, function(err) return Promise.reject(err) end) end - return self._api + return Promise.resolve(self._api) end function Plugin:connect() print("Rojo: Testing connection...") - return self:api() + return self:getApi() :andThen(function(api) local ok, info = api:getInfo():await() @@ -134,6 +139,7 @@ function Plugin:connect() end) :catch(function(err) if err == Api.Error.ServerIdMismatch then + warn(MESSAGE_SERVER_CHANGED) self:restart() return self:connect() else @@ -204,25 +210,25 @@ function Plugin:startPolling() return end - print("Rojo: Polling server for changes...") + print("Rojo: Starting to poll server for changes...") self._polling = true self._label.Enabled = true - return self:api() + return self:getApi() :andThen(function(api) - local syncOk, result = self:syncIn():await() - - if not syncOk then - return Promise.reject(result) - end - local infoOk, info = api:getInfo():await() if not infoOk then return Promise.reject(info) end + local syncOk, result = self:syncIn():await() + + if not syncOk then + return Promise.reject(result) + end + while self._polling do local changesOk, changes = api:getChanges():await() @@ -248,12 +254,12 @@ function Plugin:startPolling() end end) :catch(function(err) - self:stopPolling() - if err == Api.Error.ServerIdMismatch then + warn(MESSAGE_SERVER_CHANGED) self:restart() return self:startPolling() else + self:stopPolling() return Promise.reject(err) end end) @@ -269,7 +275,7 @@ function Plugin:syncIn() self._syncInProgress = true print("Rojo: Syncing from server...") - return self:api() + return self:getApi() :andThen(function(api) local ok, info = api:getInfo():await() @@ -292,6 +298,7 @@ function Plugin:syncIn() self._syncInProgress = false if err == Api.Error.ServerIdMismatch then + warn(MESSAGE_SERVER_CHANGED) self:restart() return self:syncIn() else From d5a21a051327dd414f7aed6ba031e06c31da299f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Jun 2018 23:11:58 -0700 Subject: [PATCH 0145/1504] Update plugin .luacheckrc to be more strict --- plugin/.luacheckrc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/plugin/.luacheckrc b/plugin/.luacheckrc index 5e011987..df243b3b 100644 --- a/plugin/.luacheckrc +++ b/plugin/.luacheckrc @@ -39,10 +39,6 @@ stds.testez = { ignore = { "212", -- unused arguments - "421", -- shadowing local variable - "422", -- shadowing argument - "431", -- shadowing upvalue - "432", -- shadowing upvalue argument } std = "lua51+roblox" From bfd33f4b8d9505a3a6de6243bdc7e6e14524bcb6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Jun 2018 23:29:39 -0700 Subject: [PATCH 0146/1504] Support init.model.json Closes #66. --- server/src/plugins/json_model_plugin.rs | 37 ++++++++++++++++++- test-project/src/SomeTool/SomeTool.client.lua | 1 + test-project/src/SomeTool/init.model.json | 4 ++ 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 test-project/src/SomeTool/SomeTool.client.lua create mode 100644 test-project/src/SomeTool/init.model.json diff --git a/server/src/plugins/json_model_plugin.rs b/server/src/plugins/json_model_plugin.rs index 2deee6ea..9a40b0c3 100644 --- a/server/src/plugins/json_model_plugin.rs +++ b/server/src/plugins/json_model_plugin.rs @@ -10,6 +10,8 @@ lazy_static! { static ref JSON_MODEL_PATTERN: Regex = Regex::new(r"^(.*?)\.model\.json$").unwrap(); } +static JSON_MODEL_INIT: &'static str = "init.model.json"; + pub struct JsonModelPlugin; impl JsonModelPlugin { @@ -19,7 +21,7 @@ impl JsonModelPlugin { } impl Plugin for JsonModelPlugin { - fn transform_file(&self, _plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult { + fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult { match vfs_item { &VfsItem::File { ref contents, .. } => { let rbx_name = match JSON_MODEL_PATTERN.captures(vfs_item.name()) { @@ -41,7 +43,38 @@ impl Plugin for JsonModelPlugin { TransformFileResult::Value(Some(rbx_item)) }, - &VfsItem::Dir { .. } => TransformFileResult::Pass, + &VfsItem::Dir { ref children, .. } => { + let init_item = match children.get(JSON_MODEL_INIT) { + Some(v) => v, + None => return TransformFileResult::Pass, + }; + + let mut rbx_item = match self.transform_file(plugins, init_item) { + TransformFileResult::Value(Some(item)) => item, + TransformFileResult::Value(None) | TransformFileResult::Pass => { + eprintln!("Inconsistency detected in JsonModelPlugin!"); + return TransformFileResult::Pass; + }, + }; + + rbx_item.name.clear(); + rbx_item.name.push_str(vfs_item.name()); + + for (child_name, child_item) in children { + if child_name == init_item.name() { + continue; + } + + match plugins.transform_file(child_item) { + Some(child_rbx_item) => { + rbx_item.children.push(child_rbx_item); + }, + _ => {}, + } + } + + TransformFileResult::Value(Some(rbx_item)) + }, } } diff --git a/test-project/src/SomeTool/SomeTool.client.lua b/test-project/src/SomeTool/SomeTool.client.lua new file mode 100644 index 00000000..9c537fc8 --- /dev/null +++ b/test-project/src/SomeTool/SomeTool.client.lua @@ -0,0 +1 @@ +print("Hello, world, from my tool!") \ No newline at end of file diff --git a/test-project/src/SomeTool/init.model.json b/test-project/src/SomeTool/init.model.json new file mode 100644 index 00000000..500c7bca --- /dev/null +++ b/test-project/src/SomeTool/init.model.json @@ -0,0 +1,4 @@ +{ + "Name": "SomeTool", + "ClassName": "Tool" +} \ No newline at end of file From 7b824abe52c26be5e27f150362e30a884b39b96b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Jun 2018 23:30:59 -0700 Subject: [PATCH 0147/1504] Update CHANGES --- CHANGES.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 1788e524..fb2914ea 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,8 +1,9 @@ # Rojo Change Log ## Current master -* Fixed obscure error when syncing into an invalid service -* Fixed multiple sync processes occurring when a server ID mismatch is detected +* Added support for `init.model.json` files, which enable versioning `Tool` instances (among other things) with Rojo. ([#66](https://github.com/LPGhatguy/rojo/issues/66)) +* Fixed obscure error when syncing into an invalid service. +* Fixed multiple sync processes occurring when a server ID mismatch is detected. ## 0.4.9 (May 26, 2018) * Fixed warning when renaming or removing files that would sometimes corrupt the instance cache ([#72](https://github.com/LPGhatguy/rojo/pull/72)) From 320974074c032bf8973238e49f85fcd75ef87ffd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Jun 2018 23:33:36 -0700 Subject: [PATCH 0148/1504] Update docs --- docs/sync-details.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/sync-details.md b/docs/sync-details.md index 21bf340b..a9f2b7be 100644 --- a/docs/sync-details.md +++ b/docs/sync-details.md @@ -30,11 +30,13 @@ Rojo supports a JSON model format for representing simple models. It's designed Rojo JSON models are stored in `.model.json` files. +Starting in Rojo version **0.4.10**, model files named `init.model.json` that are located in folders will replace that folder, much like Rojo's `init.lua` support. This can be useful to version instances like `Tool` that tend to contain several instances as well as one or more scripts. + !!! info In the future, Rojo will support `.rbxmx` models. See [issue #7](https://github.com/LPGhatguy/rojo/issues/7) for more details and updates on this feature. !!! warning - Prior to version 0.4.9, the `Properties` and `Children` properties are required on all instances in JSON models! + Prior to Rojo version **0.4.9**, the `Properties` and `Children` properties are required on all instances in JSON models! JSON model files are fairly strict; any syntax errors will cause the model to fail to sync! They look like this: From d6dd46c46704a00a7c869d0d5f24ee6c701e4ae1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Jun 2018 23:38:49 -0700 Subject: [PATCH 0149/1504] Fix JsonModelPlugin marking paths as changed correctly --- server/src/plugins/json_model_plugin.rs | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/server/src/plugins/json_model_plugin.rs b/server/src/plugins/json_model_plugin.rs index 9a40b0c3..addd3bbd 100644 --- a/server/src/plugins/json_model_plugin.rs +++ b/server/src/plugins/json_model_plugin.rs @@ -78,7 +78,21 @@ impl Plugin for JsonModelPlugin { } } - fn handle_file_change(&self, _route: &Route) -> FileChangeResult { - FileChangeResult::Pass + fn handle_file_change(&self, route: &Route) -> FileChangeResult { + let leaf = match route.last() { + Some(v) => v, + None => return FileChangeResult::Pass, + }; + + let is_init = leaf == JSON_MODEL_INIT; + + if is_init { + let mut changed = route.clone(); + changed.pop(); + + FileChangeResult::MarkChanged(Some(vec![changed])) + } else { + FileChangeResult::Pass + } } } From a86001b85ccf2aa77975dd2144c65090dc28ac05 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Jun 2018 23:51:35 -0700 Subject: [PATCH 0150/1504] Release 0.4.10 --- server/Cargo.lock | 2 +- server/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index d3592280..0c58d363 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -636,7 +636,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.4.9" +version = "0.4.10" dependencies = [ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/server/Cargo.toml b/server/Cargo.toml index f5df7b74..f44881d5 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.4.9" +version = "0.4.10" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 1343d3a2a930815a9693d9a2ba640c167d34fe60 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 2 Jun 2018 00:50:35 -0700 Subject: [PATCH 0151/1504] Pick up rest of changes for 0.4.10, oops --- CHANGES.md | 3 +++ README.md | 2 +- plugin/src/Config.lua | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index fb2914ea..c01db101 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,9 @@ # Rojo Change Log ## Current master +* *No changes* + +## 0.4.10 (June 2, 2018) * Added support for `init.model.json` files, which enable versioning `Tool` instances (among other things) with Rojo. ([#66](https://github.com/LPGhatguy/rojo/issues/66)) * Fixed obscure error when syncing into an invalid service. * Fixed multiple sync processes occurring when a server ID mismatch is detected. diff --git a/README.md b/README.md index 9aeb947e..9853f3fc 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Travis-CI Build Status - Current server version + Current server version Rojo Documentation diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index ea77b75a..459c5dd1 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { pollingRate = 0.2, - version = {0, 4, 9}, + version = {0, 4, 10}, expectedServerVersionString = "0.4.x", protocolVersion = 1, icons = { From 0d49a2e0afbe942106ad3083eeb8bb56473789d7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 2 Jun 2018 01:04:31 -0700 Subject: [PATCH 0152/1504] Mention VS Code extension in getting started guide --- docs/getting-started/installation.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index 2c3c986d..2b843a32 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -20,4 +20,7 @@ To install the plugin, either: * Install the plugin from the [Roblox plugin page](https://www.roblox.com/library/1211549683/Rojo). * This gives you less control over what version you install -- you will always have the latest version. * Or, download the latest release from [the GitHub releases section](https://github.com/LPGhatguy/rojo/releases) and install it into your Roblox plugins folder - * You can open this folder by clicking the "Plugins Folder" button from the Plugins toolbar in Roblox Studio \ No newline at end of file + * You can open this folder by clicking the "Plugins Folder" button from the Plugins toolbar in Roblox Studio + +## Visual Studio Code Extension +If you use Visual Studio Code on Windows, you can install [Evaera's unofficial Rojo extension](https://marketplace.visualstudio.com/items?itemName=evaera.vscode-rojo), which will install both halves of Rojo for you. It even has a nifty UI to add partitions and start/stop the Rojo server! \ No newline at end of file From 1b82044d7d81c2105b177f64ec31f21320390728 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 15:03:36 -0700 Subject: [PATCH 0153/1504] Defensively insert existing instances into RouteMap --- plugin/src/Reconciler.lua | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 19e2d3d1..4b503a3a 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -190,6 +190,12 @@ function Reconciler:reconcile(rbx, item) return self:_reify(item) end + -- It's possible that the instance we're associating with this item hasn't + -- been inserted into the RouteMap yet. + if item.Route ~= nil then + self._routeMap:insert(item.Route, rbx) + end + applyProperties(rbx, item.Properties) self:_reconcileChildren(rbx, item) @@ -235,6 +241,9 @@ function Reconciler:reconcileRoute(route, item, itemRoute) rbx = self:reconcile(rbx, item) reparent(rbx, parent) + + print("Post reconcileRoute RouteMap:") + print(self._routeMap:visualize()) end return Reconciler From 82ba583fa0ece1099cf15d14111c745841862e6c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 15:13:49 -0700 Subject: [PATCH 0154/1504] Fix incorrect synchronization for Plugin:_pull that would make polling flaky --- plugin/src/Plugin.lua | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugin/src/Plugin.lua b/plugin/src/Plugin.lua index 89c88117..11a65eac 100644 --- a/plugin/src/Plugin.lua +++ b/plugin/src/Plugin.lua @@ -289,9 +289,14 @@ function Plugin:syncIn() table.insert(routes, {name}) end - self:_pull(api, info.project, routes) + local pullSuccess, pullResult = self:_pull(api, info.project, routes):await() self._syncInProgress = false + + if not pullSuccess then + return Promise.reject(pullResult) + end + print("Rojo: Sync successful!") end) :catch(function(err) From a089d8202312e016509cf278f14e5d6650f43f6b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 15:44:56 -0700 Subject: [PATCH 0155/1504] Fix incorrect route being assigned to init.lua and init.model.json files --- server/src/plugins/json_model_plugin.rs | 1 + server/src/plugins/script_plugin.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/server/src/plugins/json_model_plugin.rs b/server/src/plugins/json_model_plugin.rs index addd3bbd..575feacb 100644 --- a/server/src/plugins/json_model_plugin.rs +++ b/server/src/plugins/json_model_plugin.rs @@ -59,6 +59,7 @@ impl Plugin for JsonModelPlugin { rbx_item.name.clear(); rbx_item.name.push_str(vfs_item.name()); + rbx_item.route = Some(vfs_item.route().to_vec()); for (child_name, child_item) in children { if child_name == init_item.name() { diff --git a/server/src/plugins/script_plugin.rs b/server/src/plugins/script_plugin.rs index feb5198d..185f1758 100644 --- a/server/src/plugins/script_plugin.rs +++ b/server/src/plugins/script_plugin.rs @@ -79,6 +79,7 @@ impl Plugin for ScriptPlugin { rbx_item.name.clear(); rbx_item.name.push_str(vfs_item.name()); + rbx_item.route = Some(vfs_item.route().to_vec()); for (child_name, child_item) in children { if child_name == init_item.name() { From ccec93aee863ae1d628dec930c2adcf06e28e842 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 15:50:03 -0700 Subject: [PATCH 0156/1504] Untangle route terminology a bit --- plugin/src/Plugin.lua | 40 ++++++++++++++++++--------------------- plugin/src/Reconciler.lua | 10 +++++----- 2 files changed, 23 insertions(+), 27 deletions(-) diff --git a/plugin/src/Plugin.lua b/plugin/src/Plugin.lua index 11a65eac..04391133 100644 --- a/plugin/src/Plugin.lua +++ b/plugin/src/Plugin.lua @@ -169,38 +169,34 @@ function Plugin:stopPolling() return Promise.resolve(true) end -function Plugin:_pull(api, project, routes) - return api:read(routes) +function Plugin:_pull(api, project, fileRoutes) + return api:read(fileRoutes) :andThen(function(items) - for index = 1, #routes do - local itemRoute = routes[index] - local partitionName = itemRoute[1] + for index = 1, #fileRoutes do + local fileRoute = fileRoutes[index] + local partitionName = fileRoute[1] local partition = project.partitions[partitionName] local item = items[index] - local partitionRoute = collectMatch(partition.target, "[^.]+") + local partitionTargetRbxRoute = collectMatch(partition.target, "[^.]+") -- If the item route's length was 1, we need to rename the instance to -- line up with the partition's root object name. - -- - -- This is a HACK! - if #itemRoute == 1 then - if item then - local objectName = partition.target:match("[^.]+$") - item.Name = objectName - end + if item ~= nil and #fileRoute == 1 then + local objectName = partition.target:match("[^.]+$") + item.Name = objectName end - local fullRoute = {} - for _, piece in ipairs(partitionRoute) do - table.insert(fullRoute, piece) + local itemRbxRoute = {} + for _, piece in ipairs(partitionTargetRbxRoute) do + table.insert(itemRbxRoute, piece) end - for i = 2, #itemRoute do - table.insert(fullRoute, itemRoute[i]) + for i = 2, #fileRoute do + table.insert(itemRbxRoute, fileRoute[i]) end - self._reconciler:reconcileRoute(fullRoute, item, itemRoute) + self._reconciler:reconcileRoute(itemRbxRoute, item, fileRoute) end end) end @@ -283,13 +279,13 @@ function Plugin:syncIn() return Promise.reject(info) end - local routes = {} + local fileRoutes = {} for name in pairs(info.project.partitions) do - table.insert(routes, {name}) + table.insert(fileRoutes, {name}) end - local pullSuccess, pullResult = self:_pull(api, info.project, routes):await() + local pullSuccess, pullResult = self:_pull(api, info.project, fileRoutes):await() self._syncInProgress = false diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 4b503a3a..86833406 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -202,12 +202,12 @@ function Reconciler:reconcile(rbx, item) return rbx end -function Reconciler:reconcileRoute(route, item, itemRoute) +function Reconciler:reconcileRoute(rbxRoute, item, fileRoute) local parent local rbx = game - for i = 1, #route do - local piece = route[i] + for i = 1, #rbxRoute do + local piece = rbxRoute[i] local child = rbx:FindFirstChild(piece) @@ -223,7 +223,7 @@ function Reconciler:reconcileRoute(route, item, itemRoute) end -- We don't want to create a folder if we're reaching our target item! - if child == nil and i ~= #route then + if child == nil and i ~= #rbxRoute then child = Instance.new("Folder") child.Parent = rbx child.Name = piece @@ -235,7 +235,7 @@ function Reconciler:reconcileRoute(route, item, itemRoute) -- Let's check the route map! if rbx == nil then - rbx = self._routeMap:get(itemRoute) + rbx = self._routeMap:get(fileRoute) end rbx = self:reconcile(rbx, item) From 5e0165884633e8d08dc8ea96b9120d05fc3554a1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 15:50:30 -0700 Subject: [PATCH 0157/1504] Remove straggling debug message --- plugin/src/Reconciler.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 86833406..b0ba0b0f 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -241,9 +241,6 @@ function Reconciler:reconcileRoute(rbxRoute, item, fileRoute) rbx = self:reconcile(rbx, item) reparent(rbx, parent) - - print("Post reconcileRoute RouteMap:") - print(self._routeMap:visualize()) end return Reconciler From 100d69262cf81c07d51b7222c8d018d57585661f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 15:52:42 -0700 Subject: [PATCH 0158/1504] Update CHANGES --- CHANGES.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index c01db101..a2067c4b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,10 @@ # Rojo Change Log ## Current master -* *No changes* +* Defensively insert existing instances into RouteMap; should fix most duplication cases when syncing into existing trees. +* Fixed incorrect synchronization from `Plugin:_pull` that would cause polling to create issues +* Fixed incorrect file routes being assigned to `init.lua` and `init.model.json` files +* Untangled route handling-internals slightly ## 0.4.10 (June 2, 2018) * Added support for `init.model.json` files, which enable versioning `Tool` instances (among other things) with Rojo. ([#66](https://github.com/LPGhatguy/rojo/issues/66)) From fb7bfa928a234238fe695ee9f6225b02e3b14547 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 15:54:57 -0700 Subject: [PATCH 0159/1504] Release 0.4.11 --- CHANGES.md | 3 +++ README.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.lock | 2 +- server/Cargo.toml | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a2067c4b..d573cd2e 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,9 @@ # Rojo Change Log ## Current master +* *No changes* + +## 0.4.11 (June 10, 2018) * Defensively insert existing instances into RouteMap; should fix most duplication cases when syncing into existing trees. * Fixed incorrect synchronization from `Plugin:_pull` that would cause polling to create issues * Fixed incorrect file routes being assigned to `init.lua` and `init.model.json` files diff --git a/README.md b/README.md index 9853f3fc..78d94c87 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Travis-CI Build Status - Current server version + Current server version Rojo Documentation diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 459c5dd1..c8f2ed91 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { pollingRate = 0.2, - version = {0, 4, 10}, + version = {0, 4, 11}, expectedServerVersionString = "0.4.x", protocolVersion = 1, icons = { diff --git a/server/Cargo.lock b/server/Cargo.lock index 0c58d363..a3b0fe3e 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -636,7 +636,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.4.10" +version = "0.4.11" dependencies = [ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/server/Cargo.toml b/server/Cargo.toml index f44881d5..f44419ea 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.4.10" +version = "0.4.11" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 7d7f671920a5fb6417b0b68f0c76a8309e5f7066 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 22:50:37 -0700 Subject: [PATCH 0160/1504] merge impl-v2: .editorconfig --- .editorconfig | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.editorconfig b/.editorconfig index 702598e1..198a492d 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,13 +3,16 @@ root = true [*] end_of_line = lf charset = utf-8 - -[*.json] -indent_style = space -indent_size = 2 +insert_final_newline = false trim_trailing_whitespace = true -[*.md] +[*.{json,js,css}] +indent_style = space +indent_size = 2 + +[*.{md,rs}] indent_style = space indent_size = 4 -trim_trailing_whitespace = true \ No newline at end of file + +[*.lua] +indent_style = tab \ No newline at end of file From e30545c132404d68c56b1f04289277fba23c3c6f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 22:53:22 -0700 Subject: [PATCH 0161/1504] merge impl-v2: plugin --- plugin/.editorconfig | 4 - plugin/.luacheckrc | 4 + plugin/rojo.json | 8 +- plugin/src/Api.lua | 114 -------------- plugin/src/ApiContext.lua | 119 ++++++++++++++ plugin/src/Config.lua | 13 +- plugin/src/Http.lua | 34 ++-- plugin/src/HttpError.lua | 9 +- plugin/src/Main.server.lua | 41 ++--- plugin/src/Plugin.lua | 311 ------------------------------------- plugin/src/Reconciler.lua | 246 ----------------------------- plugin/src/RouteMap.lua | 123 --------------- plugin/src/Session.lua | 76 +++++++++ 13 files changed, 243 insertions(+), 859 deletions(-) delete mode 100644 plugin/.editorconfig delete mode 100644 plugin/src/Api.lua create mode 100644 plugin/src/ApiContext.lua delete mode 100644 plugin/src/Plugin.lua delete mode 100644 plugin/src/Reconciler.lua delete mode 100644 plugin/src/RouteMap.lua create mode 100644 plugin/src/Session.lua diff --git a/plugin/.editorconfig b/plugin/.editorconfig deleted file mode 100644 index da77c5d6..00000000 --- a/plugin/.editorconfig +++ /dev/null @@ -1,4 +0,0 @@ -[*.lua] -indent_style = tab -trim_trailing_whitespace = true -insert_final_newline = true \ No newline at end of file diff --git a/plugin/.luacheckrc b/plugin/.luacheckrc index df243b3b..5e011987 100644 --- a/plugin/.luacheckrc +++ b/plugin/.luacheckrc @@ -39,6 +39,10 @@ stds.testez = { ignore = { "212", -- unused arguments + "421", -- shadowing local variable + "422", -- shadowing argument + "431", -- shadowing upvalue + "432", -- shadowing upvalue argument } std = "lua51+roblox" diff --git a/plugin/rojo.json b/plugin/rojo.json index 6ba55d43..e184e52f 100644 --- a/plugin/rojo.json +++ b/plugin/rojo.json @@ -18,14 +18,14 @@ "path": "modules/roact-rodux/lib", "target": "ReplicatedStorage.Rojo.modules.RoactRodux" }, - "modules/promise": { - "path": "modules/promise/lib", - "target": "ReplicatedStorage.Rojo.modules.Promise" - }, "modules/testez": { "path": "modules/testez/lib", "target": "ReplicatedStorage.TestEZ" }, + "modules/promise": { + "path": "modules/promise/lib", + "target": "ReplicatedStorage.Rojo.modules.Promise" + }, "tests": { "path": "tests", "target": "TestService" diff --git a/plugin/src/Api.lua b/plugin/src/Api.lua deleted file mode 100644 index 317f6282..00000000 --- a/plugin/src/Api.lua +++ /dev/null @@ -1,114 +0,0 @@ -local HttpService = game:GetService("HttpService") - -local Promise = require(script.Parent.Parent.modules.Promise) - -local Config = require(script.Parent.Config) -local Version = require(script.Parent.Version) - -local Api = {} -Api.__index = Api - -Api.Error = { - ServerIdMismatch = "ServerIdMismatch", -} - -setmetatable(Api.Error, { - __index = function(_, key) - error("Invalid API.Error name " .. key, 2) - end -}) - ---[[ - Api.connect(Http) -> Promise - - Create a new Api using the given HTTP implementation. - - Attempting to invoke methods on an invalid conext will throw errors! -]] -function Api.connect(http) - local context = { - http = http, - serverId = nil, - currentTime = 0, - } - - setmetatable(context, Api) - - return context:_start() - :andThen(function() - return context - end) -end - -function Api:_start() - return self.http:get("/") - :andThen(function(response) - response = response:json() - - if response.protocolVersion ~= Config.protocolVersion then - local message = ( - "Found a Rojo dev server, but it's using a different protocol version, and is incompatible." .. - "\nMake sure you have matching versions of both the Rojo plugin and server!" .. - "\n\nYour client is version %s, with protocol version %s. It expects server version %s." .. - "\nYour server is version %s, with protocol version %s." .. - "\n\nGo to https://github.com/LPGhatguy/rojo for more details." - ):format( - Version.display(Config.version), Config.protocolVersion, - Config.expectedApiVersionString, - response.serverVersion, response.protocolVersion - ) - - return Promise.reject(message) - end - - self.serverId = response.serverId - self.currentTime = response.currentTime - end) -end - -function Api:getInfo() - return self.http:get("/") - :andThen(function(response) - response = response:json() - - if response.serverId ~= self.serverId then - return Promise.reject(Api.Error.ServerIdMismatch) - end - - return response - end) -end - -function Api:read(paths) - local body = HttpService:JSONEncode(paths) - - return self.http:post("/read", body) - :andThen(function(response) - response = response:json() - - if response.serverId ~= self.serverId then - return Promise.reject(Api.Error.ServerIdMismatch) - end - - return response.items - end) -end - -function Api:getChanges() - local url = ("/changes/%f"):format(self.currentTime) - - return self.http:get(url) - :andThen(function(response) - response = response:json() - - if response.serverId ~= self.serverId then - return Promise.reject(Api.Error.ServerIdMismatch) - end - - self.currentTime = response.currentTime - - return response.changes - end) -end - -return Api diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua new file mode 100644 index 00000000..999f8cb7 --- /dev/null +++ b/plugin/src/ApiContext.lua @@ -0,0 +1,119 @@ +local Promise = require(script.Parent.Parent.modules.Promise) + +local Config = require(script.Parent.Config) +local Version = require(script.Parent.Version) +local Http = require(script.Parent.Http) +local HttpError = require(script.Parent.HttpError) + +local ApiContext = {} +ApiContext.__index = ApiContext + +-- TODO: Audit cases of errors and create enum values for each of them. +ApiContext.Error = { + ServerIdMismatch = "ServerIdMismatch", +} + +setmetatable(ApiContext.Error, { + __index = function(_, key) + error("Invalid API.Error name " .. key, 2) + end +}) + +function ApiContext.new(url, onMessage) + assert(type(url) == "string") + assert(type(onMessage) == "function") + + local context = { + url = url, + onMessage = onMessage, + serverId = nil, + connected = false, + messageCursor = -1, + } + + setmetatable(context, ApiContext) + + return context +end + +function ApiContext:connect() + return Http.get(self.url) + :andThen(function(response) + local body = response:json() + + if body.protocolVersion ~= Config.protocolVersion then + local message = ( + "Found a Rojo dev server, but it's using a different protocol version, and is incompatible." .. + "\nMake sure you have matching versions of both the Rojo plugin and server!" .. + "\n\nYour client is version %s, with protocol version %s. It expects server version %s." .. + "\nYour server is version %s, with protocol version %s." .. + "\n\nGo to https://github.com/LPGhatguy/rojo for more details." + ):format( + Version.display(Config.version), Config.protocolVersion, + Config.expectedApiContextVersionString, + body.serverVersion, body.protocolVersion + ) + + return Promise.reject(message) + end + + self.serverId = body.serverId + self.connected = true + end) +end + +function ApiContext:readAll() + if not self.connected then + return Promise.reject() + end + + return Http.get(self.url .. "/read_all") + :andThen(function(response) + local body = response:json() + + if body.serverId ~= self.serverId then + return Promise.reject("server changed ID") + end + + self.messageCursor = body.messageCursor + + return body.instances + end, function(err) + self.connected = false + + return Promise.reject(err) + end) +end + +function ApiContext:retrieveMessages() + if not self.connected then + return Promise.reject() + end + + return Http.get(self.url .. "/subscribe/" .. self.messageCursor) + :andThen(function(response) + local body = response:json() + + if body.serverId ~= self.serverId then + return Promise.reject("server changed ID") + end + + for _, message in ipairs(body.messages) do + self.onMessage(message) + end + + self.messageCursor = body.messageCursor + + return self:retrieveMessages() + end, function(err) + if err.type == HttpError.Error.Timeout then + return self:retrieveMessages() + end + + self.connected = false + + return Promise.reject(err) + end) +end + +return ApiContext diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index c8f2ed91..a3bb163a 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,12 +1,7 @@ return { - pollingRate = 0.2, - version = {0, 4, 11}, - expectedServerVersionString = "0.4.x", - protocolVersion = 1, - icons = { - syncIn = "rbxassetid://1820320573", - togglePolling = "rbxassetid://1820320064", - testConnection = "rbxassetid://1820320989", - }, + version = {0, 5, 0}, + expectedServerVersionString = "0.5.x", + protocolVersion = 2, + port = 34872, dev = false, } diff --git a/plugin/src/Http.lua b/plugin/src/Http.lua index 56a538b4..19383b7e 100644 --- a/plugin/src/Http.lua +++ b/plugin/src/Http.lua @@ -13,27 +13,15 @@ local function dprint(...) end end +-- TODO: Factor out into separate library, especially error handling local Http = {} -Http.__index = Http -function Http.new(baseUrl) - assert(type(baseUrl) == "string", "Http.new needs a baseUrl!") - - local http = { - baseUrl = baseUrl - } - - setmetatable(http, Http) - - return http -end - -function Http:get(endpoint) - dprint("\nGET", endpoint) +function Http.get(url) + dprint("\nGET", url) return Promise.new(function(resolve, reject) spawn(function() local ok, result = pcall(function() - return HttpService:GetAsync(self.baseUrl .. endpoint, true) + return HttpService:GetAsync(url, true) end) if ok then @@ -46,13 +34,13 @@ function Http:get(endpoint) end) end -function Http:post(endpoint, body) - dprint("\nPOST", endpoint) +function Http.post(url, body) + dprint("\nPOST", url) dprint(body) return Promise.new(function(resolve, reject) spawn(function() local ok, result = pcall(function() - return HttpService:PostAsync(self.baseUrl .. endpoint, body) + return HttpService:PostAsync(url, body) end) if ok then @@ -65,4 +53,12 @@ function Http:post(endpoint, body) end) end +function Http.jsonEncode(object) + return HttpService:JSONEncode(object) +end + +function Http.jsonDecode(source) + return HttpService:JSONDecode(source) +end + return Http diff --git a/plugin/src/HttpError.lua b/plugin/src/HttpError.lua index 674721cf..ca624037 100644 --- a/plugin/src/HttpError.lua +++ b/plugin/src/HttpError.lua @@ -10,6 +10,9 @@ HttpError.Error = { message = "Rojo plugin couldn't connect to the Rojo server.\n" .. "Make sure the server is running -- use 'Rojo serve' to run it!", }, + Timeout = { + message = "Rojo timed out during a request.", + }, Unknown = { message = "Rojo encountered an unknown error: {{message}}", }, @@ -44,7 +47,11 @@ function HttpError.fromErrorString(err) end if err:find("^curl error") then - return HttpError.new(HttpError.Error.ConnectFailed) + if err:find("couldn't connect to server") then + return HttpError.new(HttpError.Error.ConnectFailed) + elseif err:find("timeout was reached") then + return HttpError.new(HttpError.Error.Timeout) + end end return HttpError.new(HttpError.Error.Unknown, err) diff --git a/plugin/src/Main.server.lua b/plugin/src/Main.server.lua index 0b21c11d..e2c50be3 100644 --- a/plugin/src/Main.server.lua +++ b/plugin/src/Main.server.lua @@ -2,7 +2,7 @@ if not plugin then return end -local Plugin = require(script.Parent.Plugin) +local Session = require(script.Parent.Session) local Config = require(script.Parent.Config) local Version = require(script.Parent.Version) @@ -39,40 +39,25 @@ local function checkUpgrade() end local function main() - local pluginInstance = Plugin.new() - local displayedVersion = Config.dev and "DEV" or Version.display(Config.version) - local toolbar = plugin:CreateToolbar("Rojo Plugin " .. displayedVersion) + local toolbar = plugin:CreateToolbar("Rojo " .. displayedVersion) - toolbar:CreateButton("Test Connection", "Connect to Rojo Server", Config.icons.testConnection) + local currentSession + + -- TODO: More robust session tracking to handle errors + -- TODO: Icon! + toolbar:CreateButton("Connect", "Connect to Rojo Session", "") .Click:Connect(function() checkUpgrade() - pluginInstance:connect() - :catch(function(err) - warn(err) - end) - end) + if currentSession ~= nil then + warn("Rojo: A session is already running!") + return + end - toolbar:CreateButton("Sync In", "Sync into Roblox Studio", Config.icons.syncIn) - .Click:Connect(function() - checkUpgrade() - - pluginInstance:syncIn() - :catch(function(err) - warn(err) - end) - end) - - toolbar:CreateButton("Toggle Polling", "Poll server for changes", Config.icons.togglePolling) - .Click:Connect(function() - checkUpgrade() - - pluginInstance:togglePolling() - :catch(function(err) - warn(err) - end) + print("Rojo: Started session.") + currentSession = Session.new() end) end diff --git a/plugin/src/Plugin.lua b/plugin/src/Plugin.lua deleted file mode 100644 index 04391133..00000000 --- a/plugin/src/Plugin.lua +++ /dev/null @@ -1,311 +0,0 @@ -local CoreGui = game:GetService("CoreGui") - -local Promise = require(script.Parent.Parent.modules.Promise) - -local Config = require(script.Parent.Config) -local Http = require(script.Parent.Http) -local Api = require(script.Parent.Api) -local Reconciler = require(script.Parent.Reconciler) -local Version = require(script.Parent.Version) - -local MESSAGE_SERVER_CHANGED = "Rojo: The server has changed since the last request, reloading plugin..." -local MESSAGE_PLUGIN_CHANGED = "Rojo: Another instance of Rojo came online, unloading..." - -local function collectMatch(source, pattern) - local result = {} - - for match in source:gmatch(pattern) do - table.insert(result, match) - end - - return result -end - -local Plugin = {} -Plugin.__index = Plugin - -function Plugin.new() - local address = "localhost" - local port = Config.dev and 8001 or 8000 - - local remote = ("http://%s:%d"):format(address, port) - - local self = { - _http = Http.new(remote), - _reconciler = Reconciler.new(), - _api = nil, - _polling = false, - _syncInProgress = false, - } - - setmetatable(self, Plugin) - - do - local uiName = ("Rojo %s UI"):format(Version.display(Config.version)) - - if Config.dev then - uiName = "Rojo Dev UI" - end - - -- If there's an existing Rojo UI, like from a Roblox plugin upgrade - -- that wasn't Rojo, make sure we clean it up. - local existingUi = CoreGui:FindFirstChild(uiName) - - if existingUi ~= nil then - existingUi:Destroy() - end - - local screenGui = Instance.new("ScreenGui") - screenGui.Name = uiName - screenGui.Parent = CoreGui - screenGui.DisplayOrder = -1 - screenGui.Enabled = false - - local label = Instance.new("TextLabel") - label.Font = Enum.Font.SourceSans - label.TextSize = 20 - label.Text = "Rojo polling..." - label.BackgroundColor3 = Color3.fromRGB(31, 31, 31) - label.BackgroundTransparency = 0.5 - label.BorderSizePixel = 0 - label.TextColor3 = Color3.new(1, 1, 1) - label.Size = UDim2.new(0, 120, 0, 28) - label.Position = UDim2.new(0, 0, 0, 0) - label.Parent = screenGui - - self._label = screenGui - - -- If our UI was destroyed, we assume it was from another instance of - -- the Rojo plugin coming online. - -- - -- Roblox doesn't notify plugins when they get unloaded, so this is the - -- best trigger we have right now unless we create a dedicated event - -- object. - screenGui.AncestryChanged:Connect(function(_, parent) - if parent == nil then - warn(MESSAGE_PLUGIN_CHANGED) - self:restart() - end - end) - end - - return self -end - ---[[ - Clears all state and issues a notice to the user that the plugin has - restarted. -]] -function Plugin:restart() - self:stopPolling() - - self._reconciler:destruct() - self._reconciler = Reconciler.new() - - self._api = nil - self._polling = false - self._syncInProgress = false -end - -function Plugin:getApi() - if self._api == nil then - return Api.connect(self._http) - :andThen(function(api) - self._api = api - - return api - end, function(err) - return Promise.reject(err) - end) - end - - return Promise.resolve(self._api) -end - -function Plugin:connect() - print("Rojo: Testing connection...") - - return self:getApi() - :andThen(function(api) - local ok, info = api:getInfo():await() - - if not ok then - return Promise.reject(info) - end - - print("Rojo: Server found!") - print("Rojo: Protocol version:", info.protocolVersion) - print("Rojo: Server version:", info.serverVersion) - end) - :catch(function(err) - if err == Api.Error.ServerIdMismatch then - warn(MESSAGE_SERVER_CHANGED) - self:restart() - return self:connect() - else - return Promise.reject(err) - end - end) -end - -function Plugin:togglePolling() - if self._polling then - return self:stopPolling() - else - return self:startPolling() - end -end - -function Plugin:stopPolling() - if not self._polling then - return Promise.resolve(false) - end - - print("Rojo: Stopped polling server for changes.") - - self._polling = false - self._label.Enabled = false - - return Promise.resolve(true) -end - -function Plugin:_pull(api, project, fileRoutes) - return api:read(fileRoutes) - :andThen(function(items) - for index = 1, #fileRoutes do - local fileRoute = fileRoutes[index] - local partitionName = fileRoute[1] - local partition = project.partitions[partitionName] - local item = items[index] - - local partitionTargetRbxRoute = collectMatch(partition.target, "[^.]+") - - -- If the item route's length was 1, we need to rename the instance to - -- line up with the partition's root object name. - if item ~= nil and #fileRoute == 1 then - local objectName = partition.target:match("[^.]+$") - item.Name = objectName - end - - local itemRbxRoute = {} - for _, piece in ipairs(partitionTargetRbxRoute) do - table.insert(itemRbxRoute, piece) - end - - for i = 2, #fileRoute do - table.insert(itemRbxRoute, fileRoute[i]) - end - - self._reconciler:reconcileRoute(itemRbxRoute, item, fileRoute) - end - end) -end - -function Plugin:startPolling() - if self._polling then - return - end - - print("Rojo: Starting to poll server for changes...") - - self._polling = true - self._label.Enabled = true - - return self:getApi() - :andThen(function(api) - local infoOk, info = api:getInfo():await() - - if not infoOk then - return Promise.reject(info) - end - - local syncOk, result = self:syncIn():await() - - if not syncOk then - return Promise.reject(result) - end - - while self._polling do - local changesOk, changes = api:getChanges():await() - - if not changesOk then - return Promise.reject(changes) - end - - if #changes > 0 then - local routes = {} - - for _, change in ipairs(changes) do - table.insert(routes, change.route) - end - - local pullOk, pullResult = self:_pull(api, info.project, routes):await() - - if not pullOk then - return Promise.reject(pullResult) - end - end - - wait(Config.pollingRate) - end - end) - :catch(function(err) - if err == Api.Error.ServerIdMismatch then - warn(MESSAGE_SERVER_CHANGED) - self:restart() - return self:startPolling() - else - self:stopPolling() - return Promise.reject(err) - end - end) -end - -function Plugin:syncIn() - if self._syncInProgress then - warn("Rojo: Can't sync right now, because a sync is already in progress.") - - return Promise.resolve() - end - - self._syncInProgress = true - print("Rojo: Syncing from server...") - - return self:getApi() - :andThen(function(api) - local ok, info = api:getInfo():await() - - if not ok then - return Promise.reject(info) - end - - local fileRoutes = {} - - for name in pairs(info.project.partitions) do - table.insert(fileRoutes, {name}) - end - - local pullSuccess, pullResult = self:_pull(api, info.project, fileRoutes):await() - - self._syncInProgress = false - - if not pullSuccess then - return Promise.reject(pullResult) - end - - print("Rojo: Sync successful!") - end) - :catch(function(err) - self._syncInProgress = false - - if err == Api.Error.ServerIdMismatch then - warn(MESSAGE_SERVER_CHANGED) - self:restart() - return self:syncIn() - else - return Promise.reject(err) - end - end) -end - -return Plugin diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua deleted file mode 100644 index b0ba0b0f..00000000 --- a/plugin/src/Reconciler.lua +++ /dev/null @@ -1,246 +0,0 @@ -local RouteMap = require(script.Parent.RouteMap) - -local function classEqual(a, b) - assert(typeof(a) == "string") - assert(typeof(b) == "string") - - if a == "*" or b == "*" then - return true - end - - return a == b -end - -local function applyProperties(target, properties) - assert(typeof(target) == "Instance") - assert(typeof(properties) == "table") - - for key, property in pairs(properties) do - -- TODO: Transform property value based on property.Type - -- Right now, we assume that 'value' is primitive! - target[key] = property.Value - end -end - ---[[ - Attempt to parent `rbx` to `parent`, doing nothing if: - * parent is already `parent` - * Changing parent threw an error -]] -local function reparent(rbx, parent) - assert(typeof(rbx) == "Instance") - assert(typeof(parent) == "Instance") - - if rbx.Parent == parent then - return - end - - -- Setting `Parent` can fail if: - -- * The object has been destroyed - -- * The object is a service and cannot be reparented - pcall(function() - rbx.Parent = parent - end) -end - ---[[ - Attempts to match up Roblox instances and object specifiers for - reconciliation. - - An object is considered a match if they have the same Name and ClassName. - - primaryChildren and secondaryChildren can each be either a list of Roblox - instances or object specifiers. Since they share a common shape, switching - the two around isn't problematic! - - visited is expected to be an empty table initially. It will be filled with - the set of children that have been visited so far. -]] -local function findNextChildPair(primaryChildren, secondaryChildren, visited) - for _, primaryChild in ipairs(primaryChildren) do - if not visited[primaryChild] then - visited[primaryChild] = true - - for _, secondaryChild in ipairs(secondaryChildren) do - if classEqual(primaryChild.ClassName, secondaryChild.ClassName) and primaryChild.Name == secondaryChild.Name then - visited[secondaryChild] = true - - return primaryChild, secondaryChild - end - end - - return primaryChild, nil - end - end - - return nil, nil -end - -local Reconciler = {} -Reconciler.__index = Reconciler - -function Reconciler.new() - local reconciler = { - _routeMap = RouteMap.new(), - } - - setmetatable(reconciler, Reconciler) - - return reconciler -end - ---[[ - A semi-smart algorithm that attempts to apply the given item's children to - an existing Roblox object. -]] -function Reconciler:_reconcileChildren(rbx, item) - local visited = {} - local rbxChildren = rbx:GetChildren() - - -- Reconcile any children that were added or updated - while true do - local itemChild, rbxChild = findNextChildPair(item.Children, rbxChildren, visited) - - if itemChild == nil then - break - end - - local newRbxChild = self:reconcile(rbxChild, itemChild) - - if newRbxChild ~= nil then - newRbxChild.Parent = rbx - end - end - - -- Reconcile any children that were deleted - while true do - local rbxChild, itemChild = findNextChildPair(rbxChildren, item.Children, visited) - - if rbxChild == nil then - break - end - - local newRbxChild = self:reconcile(rbxChild, itemChild) - - if newRbxChild ~= nil then - newRbxChild.Parent = rbx - end - end -end - ---[[ - Construct a new Roblox object from the given item. -]] -function Reconciler:_reify(item) - local className = item.ClassName - - -- "*" represents a match of any class. It reifies as a folder! - if className == "*" then - className = "Folder" - end - - local rbx = Instance.new(className) - rbx.Name = item.Name - - applyProperties(rbx, item.Properties) - - for _, child in ipairs(item.Children) do - reparent(self:_reify(child), rbx) - end - - if item.Route ~= nil then - self._routeMap:insert(item.Route, rbx) - end - - return rbx -end - ---[[ - Clears any state that the Reconciler has, stopping it completely. -]] -function Reconciler:destruct() - self._routeMap:destruct() -end - ---[[ - Apply the changes represented by the given item to a Roblox object that's a - child of the given instance. -]] -function Reconciler:reconcile(rbx, item) - -- Item was deleted - if item == nil then - if rbx ~= nil then - self._routeMap:removeByRbx(rbx) - rbx:Destroy() - end - - return nil - end - - -- Item was created! - if rbx == nil then - return self:_reify(item) - end - - -- Item changed type! - if not classEqual(rbx.ClassName, item.ClassName) then - self._routeMap:removeByRbx(rbx) - rbx:Destroy() - - return self:_reify(item) - end - - -- It's possible that the instance we're associating with this item hasn't - -- been inserted into the RouteMap yet. - if item.Route ~= nil then - self._routeMap:insert(item.Route, rbx) - end - - applyProperties(rbx, item.Properties) - self:_reconcileChildren(rbx, item) - - return rbx -end - -function Reconciler:reconcileRoute(rbxRoute, item, fileRoute) - local parent - local rbx = game - - for i = 1, #rbxRoute do - local piece = rbxRoute[i] - - local child = rbx:FindFirstChild(piece) - - -- We should get services instead of making folders here. - if rbx == game and child == nil then - local success - success, child = pcall(game.GetService, game, piece) - - -- That isn't a valid service! - if not success then - child = nil - end - end - - -- We don't want to create a folder if we're reaching our target item! - if child == nil and i ~= #rbxRoute then - child = Instance.new("Folder") - child.Parent = rbx - child.Name = piece - end - - parent = rbx - rbx = child - end - - -- Let's check the route map! - if rbx == nil then - rbx = self._routeMap:get(fileRoute) - end - - rbx = self:reconcile(rbx, item) - - reparent(rbx, parent) -end - -return Reconciler diff --git a/plugin/src/RouteMap.lua b/plugin/src/RouteMap.lua deleted file mode 100644 index 8dc92fc7..00000000 --- a/plugin/src/RouteMap.lua +++ /dev/null @@ -1,123 +0,0 @@ ---[[ - A map from Route objects (given by the server) to Roblox instances (created - by the plugin). -]] - -local function hashRoute(route) - return table.concat(route, "/") -end - -local RouteMap = {} -RouteMap.__index = RouteMap - -function RouteMap.new() - local self = { - _map = {}, - _reverseMap = {}, - _connectionsByRbx = {}, - } - - setmetatable(self, RouteMap) - - return self -end - -function RouteMap:insert(route, rbx) - local hashed = hashRoute(route) - - -- Make sure that each route and instance are only present in RouteMap once. - self:removeByRoute(route) - self:removeByRbx(rbx) - - self._map[hashed] = rbx - self._reverseMap[rbx] = hashed - self._connectionsByRbx[rbx] = rbx.AncestryChanged:Connect(function(_, parent) - if parent == nil then - self:removeByRbx(rbx) - end - end) -end - -function RouteMap:get(route) - return self._map[hashRoute(route)] -end - -function RouteMap:removeByRoute(route) - local hashedRoute = hashRoute(route) - local rbx = self._map[hashedRoute] - - if rbx ~= nil then - self:_removeInternal(rbx, hashedRoute) - end -end - -function RouteMap:removeByRbx(rbx) - local hashedRoute = self._reverseMap[rbx] - - if hashedRoute ~= nil then - self:_removeInternal(rbx, hashedRoute) - end -end - ---[[ - Correcly removes the given Roblox Instance/Route pair from the RouteMap. -]] -function RouteMap:_removeInternal(rbx, hashedRoute) - self._map[hashedRoute] = nil - self._reverseMap[rbx] = nil - self._connectionsByRbx[rbx]:Disconnect() - self._connectionsByRbx[rbx] = nil - - self:_removeRbxDescendants(rbx) -end - ---[[ - Ensure that there are no descendants of the given Roblox Instance still - present in the map, guaranteeing that it has been cleaned out. -]] -function RouteMap:_removeRbxDescendants(parentRbx) - for rbx in pairs(self._reverseMap) do - if rbx:IsDescendantOf(parentRbx) then - self:removeByRbx(rbx) - end - end -end - ---[[ - Remove all items from the map and disconnect all connections, cleaning up - the RouteMap. -]] -function RouteMap:destruct() - self._map = {} - self._reverseMap = {} - - for _, connection in pairs(self._connectionsByRbx) do - connection:Disconnect() - end - - self._connectionsByRbx = {} -end - -function RouteMap:visualize() - -- Log all of our keys so that the visualization has a stable order. - local keys = {} - - for key in pairs(self._map) do - table.insert(keys, key) - end - - table.sort(keys) - - local buffer = {} - for _, key in ipairs(keys) do - local visualized = ("- %s: %s"):format( - key, - self._map[key]:GetFullName() - ) - table.insert(buffer, visualized) - end - - return table.concat(buffer, "\n") -end - -return RouteMap diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua new file mode 100644 index 00000000..1d0e6d30 --- /dev/null +++ b/plugin/src/Session.lua @@ -0,0 +1,76 @@ +local Config = require(script.Parent.Config) +local ApiContext = require(script.Parent.ApiContext) + +local REMOTE_URL = ("http://localhost:%d"):format(Config.port) + +local Session = {} +Session.__index = Session + +function Session.new() + local self = {} + + setmetatable(self, Session) + + -- TODO: Rewrite all instance tracking logic and implement a real reconciler + local created = {} + created["0"] = game:GetService("ReplicatedFirst") + + local api + local function readAll() + print("Reading all...") + + return api:readAll() + :andThen(function(instances) + local visited = {} + for id, instance in pairs(instances) do + visited[id] = true + if id ~= "0" then + local existing = created[id] + if existing ~= nil then + pcall(existing.Destroy, existing) + end + + local real = Instance.new(instance.className) + real.Name = instance.name + + for key, value in pairs(instance.properties) do + real[key] = value + end + + created[id] = real + end + end + + for id, instance in pairs(instances) do + if id ~= "0" then + created[id].Parent = created[tostring(instance.parent)] + end + end + + for id, object in pairs(created) do + if not visited[id] then + object:Destroy() + end + end + end) + end + + api = ApiContext.new(REMOTE_URL, function(message) + if message.type == "InstanceChanged" then + print("Instance", message.id, "changed!") + readAll() + else + warn("Unknown message type " .. message.type) + end + end) + + api:connect() + :andThen(readAll) + :andThen(function() + return api:retrieveMessages() + end) + + return self +end + +return Session From ec1f9bd706130487f73e277882020112a4a87015 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 22:59:04 -0700 Subject: [PATCH 0162/1504] merge impl-v2: server --- server/.editorconfig | 5 - server/Cargo.lock | 149 +++---- server/Cargo.toml | 15 +- server/src/bin.rs | 39 +- server/src/commands/serve.rs | 99 +---- server/src/core.rs | 1 - server/src/file_route.rs | 89 +++++ server/src/id.rs | 21 + server/src/lib.rs | 26 ++ server/src/message_session.rs | 64 +++ server/src/partition.rs | 13 + server/src/partition_watcher.rs | 65 +++ server/src/plugin.rs | 60 --- server/src/plugins/default_plugin.rs | 63 --- server/src/plugins/json_model_plugin.rs | 99 ----- server/src/plugins/mod.rs | 7 - server/src/plugins/script_plugin.rs | 121 ------ server/src/project.rs | 219 +++++++---- server/src/rbx.rs | 132 +++++-- server/src/rbx_session.rs | 231 +++++++++++ server/src/session.rs | 95 +++++ server/src/vfs/mod.rs | 7 - server/src/vfs/vfs_item.rs | 36 -- server/src/vfs/vfs_session.rs | 220 ----------- server/src/vfs/vfs_watcher.rs | 108 ----- server/src/vfs_session.rs | 242 ++++++++++++ server/src/web.rs | 371 +++++++++--------- server/src/web_util.rs | 43 ++ server/test-projects/empty/rojo.json | 5 + server/test-projects/one-partition/lib/a.lua | 1 + .../one-partition/lib/a.server.lua | 1 + .../one-partition/lib/b.client.lua | 1 + server/test-projects/one-partition/rojo.json | 10 + server/tests/test_util/mod.rs | 22 ++ server/tests/web.rs | 170 ++++++++ 35 files changed, 1643 insertions(+), 1207 deletions(-) delete mode 100644 server/.editorconfig delete mode 100644 server/src/core.rs create mode 100644 server/src/file_route.rs create mode 100644 server/src/id.rs create mode 100644 server/src/lib.rs create mode 100644 server/src/message_session.rs create mode 100644 server/src/partition.rs create mode 100644 server/src/partition_watcher.rs delete mode 100644 server/src/plugin.rs delete mode 100644 server/src/plugins/default_plugin.rs delete mode 100644 server/src/plugins/json_model_plugin.rs delete mode 100644 server/src/plugins/mod.rs delete mode 100644 server/src/plugins/script_plugin.rs create mode 100644 server/src/rbx_session.rs create mode 100644 server/src/session.rs delete mode 100644 server/src/vfs/mod.rs delete mode 100644 server/src/vfs/vfs_item.rs delete mode 100644 server/src/vfs/vfs_session.rs delete mode 100644 server/src/vfs/vfs_watcher.rs create mode 100644 server/src/vfs_session.rs create mode 100644 server/src/web_util.rs create mode 100644 server/test-projects/empty/rojo.json create mode 100644 server/test-projects/one-partition/lib/a.lua create mode 100644 server/test-projects/one-partition/lib/a.server.lua create mode 100644 server/test-projects/one-partition/lib/b.client.lua create mode 100644 server/test-projects/one-partition/rojo.json create mode 100644 server/tests/test_util/mod.rs create mode 100644 server/tests/web.rs diff --git a/server/.editorconfig b/server/.editorconfig deleted file mode 100644 index 1be11156..00000000 --- a/server/.editorconfig +++ /dev/null @@ -1,5 +0,0 @@ -[*.rs] -indent_style = space -indent_size = 4 -trim_trailing_whitespace = true -insert_final_newline = true \ No newline at end of file diff --git a/server/Cargo.lock b/server/Cargo.lock index a3b0fe3e..f777c0ab 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -26,7 +26,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "atty" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -55,7 +55,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -102,7 +102,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -135,8 +135,8 @@ version = "2.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -145,7 +145,7 @@ dependencies = [ [[package]] name = "crc" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -236,7 +236,7 @@ name = "filetime" version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -264,7 +264,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -283,7 +283,7 @@ name = "gzip-header" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -299,7 +299,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -347,7 +347,7 @@ name = "log" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -385,8 +385,8 @@ version = "1.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -438,7 +438,7 @@ name = "net2" version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -524,33 +524,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "phf" -version = "0.7.21" +version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_codegen" -version = "0.7.21" +version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_generator" -version = "0.7.21" +version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_shared" -version = "0.7.21" +version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -559,7 +559,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -570,7 +570,7 @@ name = "quote" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -608,19 +608,19 @@ dependencies = [ [[package]] name = "regex" -version = "0.2.10" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.5.5" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -636,17 +636,18 @@ dependencies = [ [[package]] name = "rojo" -version = "0.4.11" +version = "0.5.0" dependencies = [ "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -662,9 +663,9 @@ dependencies = [ "multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -693,37 +694,27 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.42" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.42" +version = "1.0.51" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "serde_derive_internals" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -748,10 +739,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.13.1" +version = "0.13.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -765,6 +756,18 @@ dependencies = [ "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tempfile" +version = "3.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "term" version = "0.2.14" @@ -863,7 +866,7 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -985,23 +988,23 @@ dependencies = [ "checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" -"checksum atty 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6609a866dd1a1b2d0ee1362195bf3e4f6438abb2d80120b83b1e1f4fb6476dd0" +"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1" "checksum base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5032d51da2741729bfdaeb2664d9b8c6d9fd1e2b90715c660b6def36628499c2" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" -"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" +"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" "checksum brotli-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cb50f54b2e0c671b7ef1637a76237ebacbb293be179440d5d65ca288e42116bb" "checksum brotli2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea9d0bbab1235017a09226b079ed733bca4bf9ecb6b6102bd01aac79ea082dca" "checksum buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9279646319ff816b05fb5897883ece50d7d854d12b59992683d4f8a71b0f949" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" "checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27" -"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" "checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6" "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" "checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" -"checksum crc 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bd5d02c0aac6bd68393ed69e00bbc2457f3e89075c6349db7189618dc4ddc1d7" +"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "32c8120d981901a9970a3a1c97cf8b630e0fa8c3ca31e75b6fd6fd5f9f427b31" "checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" @@ -1046,33 +1049,33 @@ dependencies = [ "checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum phf 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "cb325642290f28ee14d8c6201159949a872f220c62af6e110a56ea914fbe42fc" -"checksum phf_codegen 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d62594c0bb54c464f633175d502038177e90309daf2e0158be42ed5f023ce88f" -"checksum phf_generator 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "6b07ffcc532ccc85e3afc45865469bf5d9e4ef5bfcf9622e3cfe80c2d275ec03" -"checksum phf_shared 0.7.21 (registry+https://github.com/rust-lang/crates.io-index)" = "07e24b0ca9643bdecd0632f2b3da6b1b89bbb0030e0b992afc1113b23a7bc2f2" -"checksum proc-macro2 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "49b6a521dc81b643e9a51e0d1cf05df46d5a2f3c0280ea72bcb68276ba64a118" +"checksum phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "7d37a244c75a9748e049225155f56dbcb98fe71b192fd25fd23cb914b5ad62f2" +"checksum phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4048fe7dd7a06b8127ecd6d3803149126e9b33c7558879846da3a63f734f2b" +"checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998" +"checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930" +"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" "checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" "checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "aec3f58d903a7d2a9dc2bf0e41a746f4530e0cab6b615494e058f67a3ef947fb" -"checksum regex-syntax 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "bd90079345f4a4c3409214734ae220fd773c6f2e8a543d07370c6c1c369cfbfb" +"checksum regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75ecf88252dce580404a22444fc7d626c01815debba56a7f4f536772a5ff19d3" +"checksum regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1ac0f60d675cc6cf13a20ec076568254472551051ad5dd050364d70671bf6b" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc1f8407af80b0630983b2c1f1860dda1960fdec8d3ee75ba8db14937756d3a0" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" -"checksum serde 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "a73973861352c932ed1365ce22b32467ce260ac4c8db11cf750ce56334ff2dcf" -"checksum serde_derive 1.0.42 (registry+https://github.com/rust-lang/crates.io-index)" = "b392c5a0cebb98121454531c50e60e2ffe0fbeb1a44da277da2d681d08d7dc0b" -"checksum serde_derive_internals 0.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9d30c4596450fd7bbda79ef15559683f9a79ac0193ea819db90000d7e1cae794" -"checksum serde_json 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "8c6c4e049dc657a99e394bd85c22acbf97356feeec6dbf44150f2dcf79fb3118" +"checksum serde 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)" = "21924cc18e5281f232a17c040355fac97732b42cf019c24996a1642bcb169cdb" +"checksum serde_derive 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)" = "9c624a90bec6fe9bc60d275d7af71c72c26b24cd6c6776d8e344dc4044caa3e2" +"checksum serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f3ad6d546e765177cf3dded3c2e424a8040f870083a0e64064746b958ece9cb1" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" "checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "91b52877572087400e83d24b9178488541e3d535259e04ff17a63df1e5ceff59" +"checksum syn 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "61b8f1b737f929c6516ba46a3133fd6d5215ad8a62f66760f851f7048aebedfb" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" +"checksum tempfile 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8cddbd26c5686ece823b507f304c8f188daef548b4cb753512d929ce478a093c" "checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" @@ -1084,7 +1087,7 @@ dependencies = [ "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" +"checksum unicode-normalization 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90d662d111b0dbb08a180f2761026cba648c258023c355954a7c00e00e354636" "checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" diff --git a/server/Cargo.toml b/server/Cargo.toml index f44419ea..05bc6d60 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,22 +1,29 @@ [package] name = "rojo" -version = "0.4.11" +version = "0.5.0" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" repository = "https://github.com/LPGhatguy/rojo" +[lib] +name = "librojo" +path = "src/lib.rs" + [[bin]] name = "rojo" path = "src/bin.rs" [dependencies] clap = "2.27.1" -rouille = "2.1.0" +rouille = "2.1" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" notify = "4.0.0" -rand = "0.3" -regex = "0.2" +rand = "0.4" +regex = "1.0" lazy_static = "1.0" + +[dev-dependencies] +tempfile = "3" diff --git a/server/src/bin.rs b/server/src/bin.rs index 2546c9aa..bf20429e 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -1,27 +1,11 @@ -#[macro_use] extern crate serde_derive; -#[macro_use] extern crate rouille; #[macro_use] extern crate clap; -#[macro_use] extern crate lazy_static; -extern crate notify; -extern crate rand; -extern crate serde; -extern crate serde_json; -extern crate regex; -pub mod web; -pub mod core; -pub mod project; -pub mod pathext; -pub mod vfs; -pub mod rbx; -pub mod plugin; -pub mod plugins; -pub mod commands; +extern crate librojo; use std::path::{Path, PathBuf}; use std::process; -use pathext::canonicalish; +use librojo::pathext::canonicalish; fn main() { let matches = clap_app!(rojo => @@ -40,26 +24,15 @@ fn main() { (@arg port: --port +takes_value "The port to listen on. Defaults to 8000.") ) - (@subcommand pack => - (about: "Packs the project into a GUI installer bundle. NOT YET IMPLEMENTED!") - (@arg PROJECT: "Path to the project to pack. Defaults to the current directory.") - ) - - (@arg verbose: --verbose "Enable extended logging.") ).get_matches(); - let verbose = match matches.occurrences_of("verbose") { - 0 => false, - _ => true, - }; - match matches.subcommand() { ("init", sub_matches) => { let sub_matches = sub_matches.unwrap(); let project_path = Path::new(sub_matches.value_of("PATH").unwrap_or(".")); let full_path = canonicalish(project_path); - commands::init(&full_path); + librojo::commands::init(&full_path); }, ("serve", sub_matches) => { let sub_matches = sub_matches.unwrap(); @@ -82,11 +55,7 @@ fn main() { } }; - commands::serve(&project_path, verbose, port); - }, - ("pack", _) => { - eprintln!("'rojo pack' is not yet implemented!"); - process::exit(1); + librojo::commands::serve(&project_path, port); }, _ => { eprintln!("Please specify a subcommand!"); diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index eb841807..497c4ccb 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -1,98 +1,37 @@ -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::process; -use std::sync::{Arc, Mutex}; -use std::thread; +use std::fs; use rand; -use project::{Project, ProjectLoadError}; -use plugin::{PluginChain}; -use plugins::{DefaultPlugin, JsonModelPlugin, ScriptPlugin}; -use vfs::{VfsSession, VfsWatcher}; -use web; +use project::Project; +use web::{self, WebConfig}; +use session::Session; -pub fn serve(project_path: &PathBuf, verbose: bool, port: Option) { +pub fn serve(project_dir: &PathBuf, override_port: Option) { let server_id = rand::random::(); - let project = match Project::load(project_path) { - Ok(project) => { - println!("Using project \"{}\" from {}", project.name, project_path.display()); - project + let project = match Project::load(project_dir) { + Ok(v) => { + println!("Using project from {}", fs::canonicalize(project_dir).unwrap().display()); + v }, Err(err) => { - match err { - ProjectLoadError::InvalidJson(serde_err) => { - eprintln!("Project contained invalid JSON!"); - eprintln!("{}", project_path.display()); - eprintln!("Error: {}", serde_err); - - process::exit(1); - }, - ProjectLoadError::FailedToOpen | ProjectLoadError::FailedToRead => { - eprintln!("Found project file, but failed to read it!"); - eprintln!("Check the permissions of the project file at {}", project_path.display()); - - process::exit(1); - }, - ProjectLoadError::DidNotExist => { - eprintln!("Found no project file! Create one using 'rojo init'"); - eprintln!("Checked for a project at {}", project_path.display()); - - process::exit(1); - }, - } + eprintln!("{}", err); + process::exit(1); }, }; - if project.partitions.len() == 0 { - println!(""); - println!("This project has no partitions and will not do anything when served!"); - println!("This is usually a mistake -- edit rojo.json!"); - println!(""); - } + let port = override_port.unwrap_or(project.serve_port); - lazy_static! { - static ref PLUGIN_CHAIN: PluginChain = PluginChain::new(vec![ - Box::new(ScriptPlugin::new()), - Box::new(JsonModelPlugin::new()), - Box::new(DefaultPlugin::new()), - ]); - } + println!("Using project {:#?}", project); - let vfs = { - let mut vfs = VfsSession::new(&PLUGIN_CHAIN); + let mut session = Session::new(project.clone()); + session.start(); - for (name, project_partition) in &project.partitions { - let path = { - let given_path = Path::new(&project_partition.path); + let web_config = WebConfig::from_session(server_id, port, &session); - if given_path.is_absolute() { - given_path.to_path_buf() - } else { - project_path.join(given_path) - } - }; + println!("Server listening on port {}", port); - vfs.insert_partition(name, path); - } - - Arc::new(Mutex::new(vfs)) - }; - - { - let vfs = vfs.clone(); - thread::spawn(move || { - VfsWatcher::new(vfs).start(); - }); - } - - let web_config = web::WebConfig { - verbose, - port: port.unwrap_or(project.serve_port), - server_id, - }; - - println!("Server listening on port {}", web_config.port); - - web::start(web_config, project.clone(), &PLUGIN_CHAIN, vfs.clone()); + web::start(web_config); } diff --git a/server/src/core.rs b/server/src/core.rs deleted file mode 100644 index 9259cca0..00000000 --- a/server/src/core.rs +++ /dev/null @@ -1 +0,0 @@ -pub type Route = Vec; diff --git a/server/src/file_route.rs b/server/src/file_route.rs new file mode 100644 index 00000000..ba972bb7 --- /dev/null +++ b/server/src/file_route.rs @@ -0,0 +1,89 @@ +use std::path::{Path, PathBuf, Component}; + +use partition::Partition; + +// TODO: Change backing data structure to use a single allocation with slices +// taken out of it for each portion +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +pub struct FileRoute { + pub partition: String, + pub route: Vec, +} + +impl FileRoute { + pub fn from_path(path: &Path, partition: &Partition) -> Option { + assert!(path.is_absolute()); + + let relative_path = path.strip_prefix(&partition.path).ok()?; + let mut route = Vec::new(); + + for component in relative_path.components() { + match component { + Component::Normal(piece) => { + route.push(piece.to_string_lossy().into_owned()); + }, + _ => panic!("Unexpected path component: {:?}", component), + } + } + + Some(FileRoute { + partition: partition.name.clone(), + route, + }) + } + + pub fn parent(&self) -> Option { + if self.route.len() == 0 { + return None; + } + + let mut new_route = self.route.clone(); + new_route.pop(); + + Some(FileRoute { + partition: self.partition.clone(), + route: new_route, + }) + } + + /// Creates a PathBuf out of the `FileRoute` based on the given partition + /// `Path`. + pub fn to_path_buf(&self, partition_path: &Path) -> PathBuf { + let mut result = partition_path.to_path_buf(); + + for route_piece in &self.route { + result.push(route_piece); + } + + result + } + + /// Creates a version of the FileRoute with the given extra pieces appended + /// to the end. + pub fn extended_with(&self, pieces: &[&str]) -> FileRoute { + let mut result = self.clone(); + + for piece in pieces { + result.route.push(piece.to_string()); + } + + result + } + + /// This function is totally wrong and should be handled by middleware, heh. + pub fn name(&self, partition: &Partition) -> String { // I guess?? + if self.route.len() == 0 { + // This FileRoute refers to the partition itself + + if partition.target.len() == 0 { + // We're targeting the game! + "game".to_string() + } else { + partition.target.last().unwrap().clone() + } + } else { + // This FileRoute refers to an item in a partition + self.route.last().unwrap().clone() + } + } +} diff --git a/server/src/id.rs b/server/src/id.rs new file mode 100644 index 00000000..a27a9d8c --- /dev/null +++ b/server/src/id.rs @@ -0,0 +1,21 @@ +use std::sync::atomic::{AtomicUsize, Ordering}; + +/// A unique identifier, not guaranteed to be generated in any order. +pub type Id = usize; + +lazy_static! { + static ref LAST_ID: AtomicUsize = AtomicUsize::new(0); +} + +/// Generate a new ID, which has no defined ordering. +pub fn get_id() -> Id { + LAST_ID.fetch_add(1, Ordering::SeqCst) +} + +#[test] +fn it_gives_unique_numbers() { + let a = get_id(); + let b = get_id(); + + assert!(a != b); +} diff --git a/server/src/lib.rs b/server/src/lib.rs new file mode 100644 index 00000000..5ea4b8f0 --- /dev/null +++ b/server/src/lib.rs @@ -0,0 +1,26 @@ +#[macro_use] extern crate serde_derive; +#[macro_use] extern crate rouille; +#[macro_use] extern crate lazy_static; +extern crate notify; +extern crate rand; +extern crate serde; +extern crate serde_json; +extern crate regex; + +#[cfg(test)] +extern crate tempfile; + +pub mod commands; +pub mod file_route; +pub mod id; +pub mod message_session; +pub mod partition; +pub mod partition_watcher; +pub mod pathext; +pub mod project; +pub mod rbx; +pub mod rbx_session; +pub mod session; +pub mod vfs_session; +pub mod web; +pub mod web_util; diff --git a/server/src/message_session.rs b/server/src/message_session.rs new file mode 100644 index 00000000..85b2aa32 --- /dev/null +++ b/server/src/message_session.rs @@ -0,0 +1,64 @@ +use std::collections::HashMap; +use std::sync::{mpsc, Arc, RwLock, Mutex}; + +use id::{Id, get_id}; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum Message { + InstanceChanged { + id: Id, + }, +} + +#[derive(Clone)] +pub struct MessageSession { + pub messages: Arc>>, + pub message_listeners: Arc>>>, +} + +impl MessageSession { + pub fn new() -> MessageSession { + MessageSession { + messages: Arc::new(RwLock::new(Vec::new())), + message_listeners: Arc::new(Mutex::new(HashMap::new())), + } + } + + pub fn push_messages(&self, new_messages: &[Message]) { + let message_listeners = self.message_listeners.lock().unwrap(); + + { + let mut messages = self.messages.write().unwrap(); + messages.extend_from_slice(new_messages); + } + + { + for listener in message_listeners.values() { + listener.send(()).unwrap(); + } + } + } + + pub fn subscribe(&self, sender: mpsc::Sender<()>) -> Id { + let id = get_id(); + + { + let mut message_listeners = self.message_listeners.lock().unwrap(); + message_listeners.insert(id, sender); + } + + id + } + + pub fn unsubscribe(&self, id: Id) { + { + let mut message_listeners = self.message_listeners.lock().unwrap(); + message_listeners.remove(&id); + } + } + + pub fn get_message_cursor(&self) -> i32 { + self.messages.read().unwrap().len() as i32 - 1 + } +} diff --git a/server/src/partition.rs b/server/src/partition.rs new file mode 100644 index 00000000..9ef66664 --- /dev/null +++ b/server/src/partition.rs @@ -0,0 +1,13 @@ +use std::path::PathBuf; + +#[derive(Debug, Clone, PartialEq)] +pub struct Partition { + /// The unique name of this partition, used for debugging. + pub name: String, + + /// The path on the filesystem that this partition maps to. + pub path: PathBuf, + + /// The route to the Roblox instance that this partition maps to. + pub target: Vec, +} diff --git a/server/src/partition_watcher.rs b/server/src/partition_watcher.rs new file mode 100644 index 00000000..2f9785e7 --- /dev/null +++ b/server/src/partition_watcher.rs @@ -0,0 +1,65 @@ +use std::sync::mpsc::{channel, Sender}; +use std::time::Duration; +use std::thread; + +use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher, watcher}; + +use partition::Partition; +use vfs_session::FileChange; +use file_route::FileRoute; + +pub struct PartitionWatcher { + pub watcher: RecommendedWatcher, +} + +impl PartitionWatcher { + pub fn start_new(partition: Partition, tx: Sender) -> PartitionWatcher { + let (watch_tx, watch_rx) = channel(); + + let mut watcher = watcher(watch_tx, Duration::from_millis(100)).unwrap(); + + watcher.watch(&partition.path, RecursiveMode::Recursive).unwrap(); + + thread::spawn(move || { + loop { + match watch_rx.recv() { + Ok(event) => { + let file_change = match event { + DebouncedEvent::Create(path) => { + let route = FileRoute::from_path(&path, &partition).unwrap(); + FileChange::Created(route) + }, + DebouncedEvent::Write(path) => { + let route = FileRoute::from_path(&path, &partition).unwrap(); + FileChange::Updated(route) + }, + DebouncedEvent::Remove(path) => { + let route = FileRoute::from_path(&path, &partition).unwrap(); + FileChange::Deleted(route) + }, + DebouncedEvent::Rename(from_path, to_path) => { + let from_route = FileRoute::from_path(&from_path, &partition).unwrap(); + let to_route = FileRoute::from_path(&to_path, &partition).unwrap(); + FileChange::Moved(from_route, to_route) + }, + _ => continue, + }; + + match tx.send(file_change) { + Ok(_) => {}, + Err(_) => break, + } + }, + Err(_) => break, + }; + } + }); + + PartitionWatcher { + watcher, + } + } + + pub fn stop(self) { + } +} diff --git a/server/src/plugin.rs b/server/src/plugin.rs deleted file mode 100644 index 82999535..00000000 --- a/server/src/plugin.rs +++ /dev/null @@ -1,60 +0,0 @@ -use rbx::RbxInstance; -use vfs::VfsItem; -use core::Route; - -pub enum TransformFileResult { - Value(Option), - Pass, - - // TODO: Error case -} - -pub enum FileChangeResult { - MarkChanged(Option>), - Pass, -} - -pub trait Plugin { - /// Invoked when a file is read from the filesystem and needs to be turned - /// into a Roblox instance. - fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult; - - /// Invoked when a file changes on the filesystem. The result defines what - /// routes are marked as needing to be refreshed. - fn handle_file_change(&self, route: &Route) -> FileChangeResult; -} - -/// A set of plugins that are composed in order. -pub struct PluginChain { - plugins: Vec>, -} - -impl PluginChain { - pub fn new(plugins: Vec>) -> PluginChain { - PluginChain { - plugins, - } - } - - pub fn transform_file(&self, vfs_item: &VfsItem) -> Option { - for plugin in &self.plugins { - match plugin.transform_file(self, vfs_item) { - TransformFileResult::Value(rbx_item) => return rbx_item, - TransformFileResult::Pass => {}, - } - } - - None - } - - pub fn handle_file_change(&self, route: &Route) -> Option> { - for plugin in &self.plugins { - match plugin.handle_file_change(route) { - FileChangeResult::MarkChanged(changes) => return changes, - FileChangeResult::Pass => {}, - } - } - - None - } -} diff --git a/server/src/plugins/default_plugin.rs b/server/src/plugins/default_plugin.rs deleted file mode 100644 index 6d2866d3..00000000 --- a/server/src/plugins/default_plugin.rs +++ /dev/null @@ -1,63 +0,0 @@ -use std::collections::HashMap; - -use core::Route; -use plugin::{Plugin, PluginChain, TransformFileResult, FileChangeResult}; -use rbx::{RbxInstance, RbxValue}; -use vfs::VfsItem; - -/// A plugin with simple transforms: -/// * Directories become Folder instances -/// * Files become StringValue objects with 'Value' as their contents -pub struct DefaultPlugin; - -impl DefaultPlugin { - pub fn new() -> DefaultPlugin { - DefaultPlugin - } -} - -impl Plugin for DefaultPlugin { - fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult { - match vfs_item { - &VfsItem::File { ref contents, .. } => { - let mut properties = HashMap::new(); - - properties.insert("Value".to_string(), RbxValue::String { - value: contents.clone(), - }); - - TransformFileResult::Value(Some(RbxInstance { - name: vfs_item.name().clone(), - class_name: "StringValue".to_string(), - children: Vec::new(), - properties, - route: Some(vfs_item.route().to_vec()), - })) - }, - &VfsItem::Dir { ref children, .. } => { - let mut rbx_children = Vec::new(); - - for (_, child_item) in children { - match plugins.transform_file(child_item) { - Some(rbx_item) => { - rbx_children.push(rbx_item); - }, - _ => {}, - } - } - - TransformFileResult::Value(Some(RbxInstance { - name: vfs_item.name().clone(), - class_name: "*".to_string(), - children: rbx_children, - properties: HashMap::new(), - route: Some(vfs_item.route().to_vec()), - })) - }, - } - } - - fn handle_file_change(&self, route: &Route) -> FileChangeResult { - FileChangeResult::MarkChanged(Some(vec![route.clone()])) - } -} diff --git a/server/src/plugins/json_model_plugin.rs b/server/src/plugins/json_model_plugin.rs deleted file mode 100644 index 575feacb..00000000 --- a/server/src/plugins/json_model_plugin.rs +++ /dev/null @@ -1,99 +0,0 @@ -use regex::Regex; -use serde_json; - -use core::Route; -use plugin::{Plugin, PluginChain, TransformFileResult, FileChangeResult}; -use rbx::RbxInstance; -use vfs::VfsItem; - -lazy_static! { - static ref JSON_MODEL_PATTERN: Regex = Regex::new(r"^(.*?)\.model\.json$").unwrap(); -} - -static JSON_MODEL_INIT: &'static str = "init.model.json"; - -pub struct JsonModelPlugin; - -impl JsonModelPlugin { - pub fn new() -> JsonModelPlugin { - JsonModelPlugin - } -} - -impl Plugin for JsonModelPlugin { - fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult { - match vfs_item { - &VfsItem::File { ref contents, .. } => { - let rbx_name = match JSON_MODEL_PATTERN.captures(vfs_item.name()) { - Some(captures) => captures.get(1).unwrap().as_str().to_string(), - None => return TransformFileResult::Pass, - }; - - let mut rbx_item: RbxInstance = match serde_json::from_str(contents) { - Ok(v) => v, - Err(e) => { - eprintln!("Unable to parse JSON Model File named {}: {}", vfs_item.name(), e); - - return TransformFileResult::Pass; // This should be an error in the future! - }, - }; - - rbx_item.route = Some(vfs_item.route().to_vec()); - rbx_item.name = rbx_name; - - TransformFileResult::Value(Some(rbx_item)) - }, - &VfsItem::Dir { ref children, .. } => { - let init_item = match children.get(JSON_MODEL_INIT) { - Some(v) => v, - None => return TransformFileResult::Pass, - }; - - let mut rbx_item = match self.transform_file(plugins, init_item) { - TransformFileResult::Value(Some(item)) => item, - TransformFileResult::Value(None) | TransformFileResult::Pass => { - eprintln!("Inconsistency detected in JsonModelPlugin!"); - return TransformFileResult::Pass; - }, - }; - - rbx_item.name.clear(); - rbx_item.name.push_str(vfs_item.name()); - rbx_item.route = Some(vfs_item.route().to_vec()); - - for (child_name, child_item) in children { - if child_name == init_item.name() { - continue; - } - - match plugins.transform_file(child_item) { - Some(child_rbx_item) => { - rbx_item.children.push(child_rbx_item); - }, - _ => {}, - } - } - - TransformFileResult::Value(Some(rbx_item)) - }, - } - } - - fn handle_file_change(&self, route: &Route) -> FileChangeResult { - let leaf = match route.last() { - Some(v) => v, - None => return FileChangeResult::Pass, - }; - - let is_init = leaf == JSON_MODEL_INIT; - - if is_init { - let mut changed = route.clone(); - changed.pop(); - - FileChangeResult::MarkChanged(Some(vec![changed])) - } else { - FileChangeResult::Pass - } - } -} diff --git a/server/src/plugins/mod.rs b/server/src/plugins/mod.rs deleted file mode 100644 index 73482635..00000000 --- a/server/src/plugins/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod default_plugin; -mod script_plugin; -mod json_model_plugin; - -pub use self::default_plugin::*; -pub use self::script_plugin::*; -pub use self::json_model_plugin::*; diff --git a/server/src/plugins/script_plugin.rs b/server/src/plugins/script_plugin.rs deleted file mode 100644 index 185f1758..00000000 --- a/server/src/plugins/script_plugin.rs +++ /dev/null @@ -1,121 +0,0 @@ -use std::collections::HashMap; - -use regex::Regex; - -use core::Route; -use plugin::{Plugin, PluginChain, TransformFileResult, FileChangeResult}; -use rbx::{RbxInstance, RbxValue}; -use vfs::VfsItem; - -lazy_static! { - static ref SERVER_PATTERN: Regex = Regex::new(r"^(.*?)\.server\.lua$").unwrap(); - static ref CLIENT_PATTERN: Regex = Regex::new(r"^(.*?)\.client\.lua$").unwrap(); - static ref MODULE_PATTERN: Regex = Regex::new(r"^(.*?)\.lua$").unwrap(); -} - -static SERVER_INIT: &'static str = "init.server.lua"; -static CLIENT_INIT: &'static str = "init.client.lua"; -static MODULE_INIT: &'static str = "init.lua"; - -pub struct ScriptPlugin; - -impl ScriptPlugin { - pub fn new() -> ScriptPlugin { - ScriptPlugin - } -} - -impl Plugin for ScriptPlugin { - fn transform_file(&self, plugins: &PluginChain, vfs_item: &VfsItem) -> TransformFileResult { - match vfs_item { - &VfsItem::File { ref contents, .. } => { - let name = vfs_item.name(); - - let (class_name, rbx_name) = { - if let Some(captures) = SERVER_PATTERN.captures(name) { - ("Script".to_string(), captures.get(1).unwrap().as_str().to_string()) - } else if let Some(captures) = CLIENT_PATTERN.captures(name) { - ("LocalScript".to_string(), captures.get(1).unwrap().as_str().to_string()) - } else if let Some(captures) = MODULE_PATTERN.captures(name) { - ("ModuleScript".to_string(), captures.get(1).unwrap().as_str().to_string()) - } else { - return TransformFileResult::Pass; - } - }; - - let mut properties = HashMap::new(); - - properties.insert("Source".to_string(), RbxValue::String { - value: contents.clone(), - }); - - TransformFileResult::Value(Some(RbxInstance { - name: rbx_name, - class_name: class_name, - children: Vec::new(), - properties, - route: Some(vfs_item.route().to_vec()), - })) - }, - &VfsItem::Dir { ref children, .. } => { - let init_item = { - let maybe_item = children.get(SERVER_INIT) - .or(children.get(CLIENT_INIT)) - .or(children.get(MODULE_INIT)); - - match maybe_item { - Some(v) => v, - None => return TransformFileResult::Pass, - } - }; - - let mut rbx_item = match self.transform_file(plugins, init_item) { - TransformFileResult::Value(Some(item)) => item, - _ => { - eprintln!("Inconsistency detected in ScriptPlugin!"); - return TransformFileResult::Pass; - }, - }; - - rbx_item.name.clear(); - rbx_item.name.push_str(vfs_item.name()); - rbx_item.route = Some(vfs_item.route().to_vec()); - - for (child_name, child_item) in children { - if child_name == init_item.name() { - continue; - } - - match plugins.transform_file(child_item) { - Some(child_rbx_item) => { - rbx_item.children.push(child_rbx_item); - }, - _ => {}, - } - } - - TransformFileResult::Value(Some(rbx_item)) - }, - } - } - - fn handle_file_change(&self, route: &Route) -> FileChangeResult { - let leaf = match route.last() { - Some(v) => v, - None => return FileChangeResult::Pass, - }; - - let is_init = leaf == SERVER_INIT - || leaf == CLIENT_INIT - || leaf == MODULE_INIT; - - if is_init { - let mut changed = route.clone(); - changed.pop(); - - FileChangeResult::MarkChanged(Some(vec![changed])) - } else { - FileChangeResult::Pass - } - } -} diff --git a/server/src/project.rs b/server/src/project.rs index eb45ce21..b0b95de7 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -2,18 +2,39 @@ use std::collections::HashMap; use std::fmt; use std::fs::{self, File}; use std::io::{Read, Write}; -use std::path::Path; +use std::path::{Path, PathBuf}; + +use rand::{self, Rng}; use serde_json; +use partition::Partition; + pub static PROJECT_FILENAME: &'static str = "rojo.json"; #[derive(Debug)] pub enum ProjectLoadError { - DidNotExist, - FailedToOpen, - FailedToRead, - InvalidJson(serde_json::Error), + DidNotExist(PathBuf), + FailedToOpen(PathBuf), + FailedToRead(PathBuf), + InvalidJson(PathBuf, serde_json::Error), +} + +impl fmt::Display for ProjectLoadError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + &ProjectLoadError::InvalidJson(ref project_path, ref serde_err) => { + write!(f, "Found invalid JSON reading project: {}\nError: {}", project_path.display(), serde_err) + }, + &ProjectLoadError::FailedToOpen(ref project_path) | + &ProjectLoadError::FailedToRead(ref project_path) => { + write!(f, "Found project file, but failed to read it: {}", project_path.display()) + }, + &ProjectLoadError::DidNotExist(ref project_path) => { + write!(f, "Could not locate a project file at {}.\nUse 'rojo init' to create one.", project_path.display()) + }, + } + } } #[derive(Debug)] @@ -34,16 +55,17 @@ impl fmt::Display for ProjectInitError { &ProjectInitError::AlreadyExists => { write!(f, "A project already exists at that location.") }, - &ProjectInitError::FailedToCreate | &ProjectInitError::FailedToWrite => { + &ProjectInitError::FailedToCreate | + &ProjectInitError::FailedToWrite => { write!(f, "Failed to write to the given location.") }, } } } -#[derive(Clone, Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ProjectPartition { +pub struct SourceProjectPartition { /// A slash-separated path to a file or folder, relative to the project's /// directory. pub path: String, @@ -52,43 +74,114 @@ pub struct ProjectPartition { pub target: String, } -/// Represents a project configured by a user for use with Rojo. Holds anything -/// that can be configured with `rojo.json`. -/// -/// In the future, this object will hold dependency information and other handy -/// configurables -#[derive(Clone, Debug, Serialize, Deserialize)] +/// Represents a Rojo project in the format that's most convenient for users to +/// edit. This should generally line up with `Project`, but can diverge when +/// there's either compatibility shims or when the data structures that Rojo +/// want are too verbose to write in JSON but easy to convert from something +/// else. +// +/// Holds anything that can be configured with `rojo.json`. +#[derive(Debug, Clone, Serialize, Deserialize)] #[serde(default, rename_all = "camelCase")] -pub struct Project { +pub struct SourceProject { pub name: String, pub serve_port: u64, - pub partitions: HashMap, + pub partitions: HashMap, +} + +impl Default for SourceProject { + fn default() -> SourceProject { + SourceProject { + name: "new-project".to_string(), + serve_port: 8000, + partitions: HashMap::new(), + } + } +} + +/// Represents a Rojo project in the format that's convenient for Rojo to work +/// with. +#[derive(Debug, Clone)] +pub struct Project { + /// The path to the project file that this project is associated with. + pub project_path: PathBuf, + + /// The name of this project, used for user-facing labels. + pub name: String, + + /// The port that this project will run a web server on. + pub serve_port: u64, + + /// All of the project's partitions, laid out in an expanded way. + pub partitions: HashMap, } impl Project { - /// Creates a new empty Project object with the given name. - pub fn new>(name: T) -> Project { + fn from_source_project(source_project: SourceProject, project_path: PathBuf) -> Project { + let mut partitions = HashMap::new(); + + { + let project_directory = project_path.parent().unwrap(); + + for (partition_name, partition) in source_project.partitions.into_iter() { + let path = project_directory.join(&partition.path); + let target = partition.target + .split(".") + .map(String::from) + .collect::>(); + + partitions.insert(partition_name.clone(), Partition { + path, + target, + name: partition_name, + }); + } + } + Project { - name: name.into(), - ..Default::default() + project_path, + name: source_project.name, + serve_port: source_project.serve_port, + partitions, + } + } + + fn as_source_project(&self) -> SourceProject { + let mut partitions = HashMap::new(); + + for partition in self.partitions.values() { + let path = partition.path.strip_prefix(&self.project_path) + .unwrap_or_else(|_| &partition.path) + .to_str() + .unwrap() + .to_string(); + + let target = partition.target.join("."); + + partitions.insert(partition.name.clone(), SourceProjectPartition { + path, + target, + }); + } + + SourceProject { + partitions, + name: self.name.clone(), + serve_port: self.serve_port, } } /// Initializes a new project inside the given folder path. pub fn init>(location: T) -> Result { let location = location.as_ref(); - let package_path = location.join(PROJECT_FILENAME); + let project_path = location.join(PROJECT_FILENAME); // We abort if the project file already exists. - match fs::metadata(&package_path) { - Ok(_) => return Err(ProjectInitError::AlreadyExists), - Err(_) => {}, - } + fs::metadata(&project_path) + .map_err(|_| ProjectInitError::AlreadyExists)?; - let mut file = match File::create(&package_path) { - Ok(f) => f, - Err(_) => return Err(ProjectInitError::FailedToCreate), - }; + let mut file = File::create(&project_path) + .map_err(|_| ProjectInitError::FailedToCreate)?; // Try to give the project a meaningful name. // If we can't, we'll just fall back to a default. @@ -97,69 +190,57 @@ impl Project { None => "new-project".to_string(), }; + // Generate a random port to run the server on. + let serve_port = rand::thread_rng().gen_range(2000, 49151); + // Configure the project with all of the values we know so far. - let project = Project::new(name); - let serialized = serde_json::to_string_pretty(&project).unwrap(); + let source_project = SourceProject { + name, + serve_port, + partitions: HashMap::new(), + }; + let serialized = serde_json::to_string_pretty(&source_project).unwrap(); - match file.write(serialized.as_bytes()) { - Ok(_) => {}, - Err(_) => return Err(ProjectInitError::FailedToWrite), - } + file.write(serialized.as_bytes()) + .map_err(|_| ProjectInitError::FailedToWrite)?; - Ok(project) + Ok(Project::from_source_project(source_project, project_path)) } /// Attempts to load a project from the file named PROJECT_FILENAME from the /// given folder. pub fn load>(location: T) -> Result { - let package_path = location.as_ref().join(Path::new(PROJECT_FILENAME)); + let project_path = location.as_ref().join(Path::new(PROJECT_FILENAME)); - match fs::metadata(&package_path) { - Ok(_) => {}, - Err(_) => return Err(ProjectLoadError::DidNotExist), - } + fs::metadata(&project_path) + .map_err(|_| ProjectLoadError::DidNotExist(project_path.clone()))?; - let mut file = match File::open(&package_path) { - Ok(f) => f, - Err(_) => return Err(ProjectLoadError::FailedToOpen), - }; + let mut file = File::open(&project_path) + .map_err(|_| ProjectLoadError::FailedToOpen(project_path.clone()))?; let mut contents = String::new(); - match file.read_to_string(&mut contents) { - Ok(_) => {}, - Err(_) => return Err(ProjectLoadError::FailedToRead), - } + file.read_to_string(&mut contents) + .map_err(|_| ProjectLoadError::FailedToRead(project_path.clone()))?; - match serde_json::from_str(&contents) { - Ok(v) => Ok(v), - Err(e) => return Err(ProjectLoadError::InvalidJson(e)), - } + let source_project = serde_json::from_str(&contents) + .map_err(|e| ProjectLoadError::InvalidJson(project_path.clone(), e))?; + + Ok(Project::from_source_project(source_project, project_path)) } /// Saves the given project file to the given folder with the appropriate name. pub fn save>(&self, location: T) -> Result<(), ProjectSaveError> { - let package_path = location.as_ref().join(Path::new(PROJECT_FILENAME)); + let project_path = location.as_ref().join(Path::new(PROJECT_FILENAME)); - let mut file = match File::create(&package_path) { - Ok(f) => f, - Err(_) => return Err(ProjectSaveError::FailedToCreate), - }; + let mut file = File::create(&project_path) + .map_err(|_| ProjectSaveError::FailedToCreate)?; - let serialized = serde_json::to_string_pretty(self).unwrap(); + let source_project = self.as_source_project(); + let serialized = serde_json::to_string_pretty(&source_project).unwrap(); file.write(serialized.as_bytes()).unwrap(); Ok(()) } } - -impl Default for Project { - fn default() -> Project { - Project { - name: "new-project".to_string(), - serve_port: 8000, - partitions: HashMap::new(), - } - } -} diff --git a/server/src/rbx.rs b/server/src/rbx.rs index 14d3b8cd..75c03a1a 100644 --- a/server/src/rbx.rs +++ b/server/src/rbx.rs @@ -1,38 +1,116 @@ +use std::borrow::Cow; use std::collections::HashMap; -/// Represents data about a Roblox instance -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "PascalCase")] +use id::Id; + +// TODO: Switch to enum to represent more value types +pub type RbxValue = String; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct RbxInstance { + /// Maps to the `Name` property on Instance. pub name: String, + + /// Maps to the `ClassName` property on Instance. pub class_name: String, - #[serde(default = "Vec::new")] - pub children: Vec, - - #[serde(default = "HashMap::new")] + /// Contains all other properties of an Instance. pub properties: HashMap, - /// The route that this instance was generated from, if there was one. - pub route: Option>, + /// All of the children of this instance. Order is relevant to preserve! + pub children: Vec, + + pub parent: Option, } -/// Any kind value that can be used by Roblox -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "PascalCase", tag = "Type")] -pub enum RbxValue { - #[serde(rename_all = "PascalCase")] - String { - value: String, - }, - #[serde(rename_all = "PascalCase")] - Bool { - value: bool, - }, - #[serde(rename_all = "PascalCase")] - Number { - value: f64, - }, - - // TODO: Compound types like Vector3 +// This seems like a really bad idea? +// Why isn't there a blanket impl for this for all T? +impl<'a> From<&'a RbxInstance> for Cow<'a, RbxInstance> { + fn from(instance: &'a RbxInstance) -> Cow<'a, RbxInstance> { + Cow::Borrowed(instance) + } +} + +pub struct RbxTree { + instances: HashMap, +} + +impl RbxTree { + pub fn new() -> RbxTree { + RbxTree { + instances: HashMap::new(), + } + } + + pub fn get_all_instances(&self) -> &HashMap { + &self.instances + } + + pub fn insert_instance(&mut self, id: Id, instance: RbxInstance) { + if let Some(parent_id) = instance.parent { + if let Some(mut parent) = self.instances.get_mut(&parent_id) { + if !parent.children.contains(&id) { + parent.children.push(id); + } + } + } + + self.instances.insert(id, instance); + } + + pub fn delete_instance(&mut self, id: Id) -> Vec { + let mut ids_to_visit = vec![id]; + let mut ids_deleted = Vec::new(); + + for instance in self.instances.values_mut() { + match instance.children.iter().position(|&v| v == id) { + Some(index) => { + instance.children.remove(index); + }, + None => {}, + } + } + + loop { + let id = match ids_to_visit.pop() { + Some(id) => id, + None => break, + }; + + match self.instances.get(&id) { + Some(instance) => ids_to_visit.extend_from_slice(&instance.children), + None => continue, + } + + self.instances.remove(&id); + ids_deleted.push(id); + } + + ids_deleted + } + + pub fn get_instance<'a, 'b, T>(&'a self, id: Id, output: &'b mut HashMap) + where T: From<&'a RbxInstance> + { + let mut ids_to_visit = vec![id]; + + loop { + let id = match ids_to_visit.pop() { + Some(id) => id, + None => break, + }; + + match self.instances.get(&id) { + Some(instance) => { + output.insert(id, instance.into()); + + for child_id in &instance.children { + ids_to_visit.push(*child_id); + } + }, + None => continue, + } + } + } } diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs new file mode 100644 index 00000000..7db35bff --- /dev/null +++ b/server/src/rbx_session.rs @@ -0,0 +1,231 @@ +use std::collections::HashMap; +use std::sync::{Arc, RwLock}; + +use file_route::FileRoute; +use id::{Id, get_id}; +use message_session::{Message, MessageSession}; +use partition::Partition; +use project::Project; +use rbx::{RbxInstance, RbxTree}; +use vfs_session::{VfsSession, FileItem, FileChange}; + +// TODO: Rethink data structure and insertion/update behavior. Maybe break some +// pieces off into a new object? +fn file_to_instances( + file_item: &FileItem, + partition: &Partition, + tree: &mut RbxTree, + instances_by_route: &mut HashMap, + parent_id: Option, +) -> (Id, Vec) { + match file_item { + FileItem::File { contents, route } => { + let primary_id = match instances_by_route.get(&file_item.get_route()) { + Some(&id) => id, + None => { + let id = get_id(); + instances_by_route.insert(route.clone(), id); + + id + }, + }; + + // This is placeholder logic; this whole function is! + let (class_name, property_key, name) = { + // TODO: Root instances have an empty route + let file_name = route.route.last().unwrap(); + + fn strip_suffix<'a>(source: &'a str, suffix: &'static str) -> &'a str { + &source[..source.len() - suffix.len()] + } + + if file_name.ends_with(".client.lua") { + ("LocalScript", "Source", strip_suffix(&file_name, ".client.lua")) + } else if file_name.ends_with(".server.lua") { + ("Script", "Source", strip_suffix(&file_name, ".server.lua")) + } else if file_name.ends_with(".lua") { + ("ModuleScript", "Source", strip_suffix(&file_name, ".lua")) + } else { + // TODO: Error/warn/skip instead of falling back + ("StringValue", "Value", file_name.as_str()) + } + }; + + let mut properties = HashMap::new(); + properties.insert(property_key.to_string(), contents.clone()); + + tree.insert_instance(primary_id, RbxInstance { + name: name.to_string(), + class_name: class_name.to_string(), + properties, + children: Vec::new(), + parent: parent_id, + }); + + (primary_id, vec![primary_id]) + }, + FileItem::Directory { children, route } => { + let primary_id = match instances_by_route.get(&file_item.get_route()) { + Some(&id) => id, + None => { + let id = get_id(); + instances_by_route.insert(route.clone(), id); + + id + }, + }; + + let mut child_ids = Vec::new(); + + let mut changed_ids = vec![primary_id]; + + for child_file_item in children.values() { + let (child_id, mut child_changed_ids) = file_to_instances(child_file_item, partition, tree, instances_by_route, Some(primary_id)); + + child_ids.push(child_id); + changed_ids.push(child_id); + + // TODO: Should I stop using drain on Vecs of Copyable types? + for id in child_changed_ids.drain(..) { + changed_ids.push(id); + } + } + + tree.insert_instance(primary_id, RbxInstance { + name: route.name(partition).to_string(), + class_name: "Folder".to_string(), + properties: HashMap::new(), + children: child_ids, + parent: parent_id, + }); + + (primary_id, changed_ids) + }, + } +} + +pub struct RbxSession { + project: Project, + + vfs_session: Arc>, + + message_session: MessageSession, + + /// The RbxInstance that represents each partition. + // TODO: Can this be removed in favor of instances_by_route? + pub partition_instances: HashMap, + + /// Keeps track of all of the instances in the tree + pub tree: RbxTree, + + /// A map from files in the VFS to instances loaded in the session. + instances_by_route: HashMap, +} + +impl RbxSession { + pub fn new(project: Project, vfs_session: Arc>, message_session: MessageSession) -> RbxSession { + RbxSession { + project, + vfs_session, + message_session, + partition_instances: HashMap::new(), + tree: RbxTree::new(), + instances_by_route: HashMap::new(), + } + } + + pub fn read_partitions(&mut self) { + let vfs_session_arc = self.vfs_session.clone(); + let vfs_session = vfs_session_arc.read().unwrap(); + + for partition in self.project.partitions.values() { + let route = FileRoute { + partition: partition.name.clone(), + route: Vec::new(), + }; + let file_item = vfs_session.get_by_route(&route).unwrap(); + + let parent_id = match route.parent() { + Some(parent_route) => match self.instances_by_route.get(&parent_route) { + Some(&parent_id) => Some(parent_id), + None => None, + }, + None => None, + }; + + let (root_id, _) = file_to_instances(file_item, partition, &mut self.tree, &mut self.instances_by_route, parent_id); + + self.partition_instances.insert(partition.name.clone(), root_id); + } + } + + pub fn handle_change(&mut self, change: &FileChange) { + let vfs_session_arc = self.vfs_session.clone(); + let vfs_session = vfs_session_arc.read().unwrap(); + + match change { + FileChange::Created(route) | FileChange::Updated(route) => { + let file_item = vfs_session.get_by_route(route).unwrap(); + let partition = self.project.partitions.get(&route.partition).unwrap(); + + let parent_id = match route.parent() { + Some(parent_route) => match self.instances_by_route.get(&parent_route) { + Some(&parent_id) => Some(parent_id), + None => None, + }, + None => None, + }; + + let (_, changed_ids) = file_to_instances(file_item, partition, &mut self.tree, &mut self.instances_by_route, parent_id); + + let messages = changed_ids + .iter() + .map(|&id| Message::InstanceChanged { id }) + .collect::>(); + + self.message_session.push_messages(&messages); + }, + FileChange::Deleted(route) => { + match self.instances_by_route.get(route) { + Some(&id) => { + self.tree.delete_instance(id); + self.instances_by_route.remove(route); + self.message_session.push_messages(&[Message::InstanceChanged { id }]); + }, + None => (), + } + }, + FileChange::Moved(from_route, to_route) => { + let mut messages = Vec::new(); + + match self.instances_by_route.get(from_route) { + Some(&id) => { + self.tree.delete_instance(id); + self.instances_by_route.remove(from_route); + messages.push(Message::InstanceChanged { id }); + }, + None => (), + } + + let file_item = vfs_session.get_by_route(to_route).unwrap(); + let partition = self.project.partitions.get(&to_route.partition).unwrap(); + + let parent_id = match to_route.parent() { + Some(parent_route) => match self.instances_by_route.get(&parent_route) { + Some(&parent_id) => Some(parent_id), + None => None, + }, + None => None, + }; + + let (_, changed_ids) = file_to_instances(file_item, partition, &mut self.tree, &mut self.instances_by_route, parent_id); + + for id in changed_ids { + messages.push(Message::InstanceChanged { id }); + } + + self.message_session.push_messages(&messages); + }, + } + } +} diff --git a/server/src/session.rs b/server/src/session.rs new file mode 100644 index 00000000..55341bb3 --- /dev/null +++ b/server/src/session.rs @@ -0,0 +1,95 @@ +use std::sync::{mpsc, Arc, RwLock}; +use std::thread; + +use message_session::MessageSession; +use partition_watcher::PartitionWatcher; +use project::Project; +use rbx_session::RbxSession; +use vfs_session::VfsSession; + +/// Stub trait for middleware +trait Middleware { +} + +pub struct Session { + pub project: Project, + vfs_session: Arc>, + rbx_session: Arc>, + message_session: MessageSession, + watchers: Vec, +} + +impl Session { + pub fn new(project: Project) -> Session { + let message_session = MessageSession::new(); + let vfs_session = Arc::new(RwLock::new(VfsSession::new(project.clone()))); + let rbx_session = Arc::new(RwLock::new(RbxSession::new(project.clone(), vfs_session.clone(), message_session.clone()))); + + Session { + vfs_session, + rbx_session, + watchers: Vec::new(), + message_session, + project, + } + } + + pub fn start(&mut self) { + { + let mut vfs_session = self.vfs_session.write().unwrap(); + vfs_session.read_partitions(); + } + + { + let mut rbx_session = self.rbx_session.write().unwrap(); + rbx_session.read_partitions(); + } + + let (tx, rx) = mpsc::channel(); + + for partition in self.project.partitions.values() { + let watcher = PartitionWatcher::start_new(partition.clone(), tx.clone()); + + self.watchers.push(watcher); + } + + { + let vfs_session = self.vfs_session.clone(); + let rbx_session = self.rbx_session.clone(); + + thread::spawn(move || { + loop { + match rx.recv() { + Ok(change) => { + { + let mut vfs_session = vfs_session.write().unwrap(); + vfs_session.handle_change(&change); + } + + { + let mut rbx_session = rbx_session.write().unwrap(); + rbx_session.handle_change(&change); + } + }, + Err(_) => break, + } + } + }); + } + } + + pub fn stop(self) { + } + + pub fn get_vfs_session(&self) -> Arc> { + self.vfs_session.clone() + } + + pub fn get_rbx_session(&self) -> Arc> { + self.rbx_session.clone() + } + + pub fn get_message_session(&self) -> MessageSession { + self.message_session.clone() + } +} diff --git a/server/src/vfs/mod.rs b/server/src/vfs/mod.rs deleted file mode 100644 index a19dc4d0..00000000 --- a/server/src/vfs/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -mod vfs_session; -mod vfs_item; -mod vfs_watcher; - -pub use self::vfs_session::*; -pub use self::vfs_item::*; -pub use self::vfs_watcher::*; diff --git a/server/src/vfs/vfs_item.rs b/server/src/vfs/vfs_item.rs deleted file mode 100644 index 89fd2608..00000000 --- a/server/src/vfs/vfs_item.rs +++ /dev/null @@ -1,36 +0,0 @@ -use std::collections::HashMap; - -/// A VfsItem represents either a file or directory as it came from the filesystem. -/// -/// The interface here is intentionally simplified to make it easier to traverse -/// files that have been read into memory. -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase", tag = "type")] -pub enum VfsItem { - File { - route: Vec, - file_name: String, - contents: String, - }, - Dir { - route: Vec, - file_name: String, - children: HashMap, - }, -} - -impl VfsItem { - pub fn name(&self) -> &String { - match self { - &VfsItem::File { ref file_name , .. } => file_name, - &VfsItem::Dir { ref file_name , .. } => file_name, - } - } - - pub fn route(&self) -> &[String] { - match self { - &VfsItem::File { ref route, .. } => route, - &VfsItem::Dir { ref route, .. } => route, - } - } -} diff --git a/server/src/vfs/vfs_session.rs b/server/src/vfs/vfs_session.rs deleted file mode 100644 index 52945d0d..00000000 --- a/server/src/vfs/vfs_session.rs +++ /dev/null @@ -1,220 +0,0 @@ -use std::collections::HashMap; -use std::fs::{self, File}; -use std::io::Read; -use std::path::{Path, PathBuf}; -use std::time::Instant; - -use plugin::PluginChain; -use vfs::VfsItem; - -/// Represents a virtual layer over multiple parts of the filesystem. -/// -/// Paths in this system are represented as slices of strings, and are always -/// relative to a partition, which is an absolute path into the real filesystem. -pub struct VfsSession { - /// Contains all of the partitions mounted by the Vfs. - /// - /// These must be absolute paths! - partitions: HashMap, - - /// A chronologically-sorted list of routes that changed since the Vfs was - /// created, along with a timestamp denoting when. - change_history: Vec, - - /// When the Vfs was initialized; used for change tracking. - start_time: Instant, - - plugin_chain: &'static PluginChain, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct VfsChange { - timestamp: f64, - route: Vec, -} - -impl VfsSession { - pub fn new(plugin_chain: &'static PluginChain) -> VfsSession { - VfsSession { - partitions: HashMap::new(), - start_time: Instant::now(), - change_history: Vec::new(), - plugin_chain, - } - } - - pub fn get_partitions(&self) -> &HashMap { - &self.partitions - } - - pub fn insert_partition>(&mut self, name: &str, path: P) { - let path = path.into(); - - assert!(path.is_absolute()); - - self.partitions.insert(name.to_string(), path.into()); - } - - fn route_to_path(&self, route: &[String]) -> Option { - let (partition_name, rest) = match route.split_first() { - Some((first, rest)) => (first, rest), - None => return None, - }; - - let partition = match self.partitions.get(partition_name) { - Some(v) => v, - None => return None, - }; - - // It's possible that the partition points to a file if `rest` is empty. - // Joining "" onto a path will put a trailing slash on, which causes - // file reads to fail. - let full_path = if rest.is_empty() { - partition.clone() - } else { - let joined = rest.join("/"); - let relative = Path::new(&joined); - - partition.join(relative) - }; - - Some(full_path) - } - - fn read_dir>(&self, route: &[String], path: P) -> Result { - let path = path.as_ref(); - let reader = match fs::read_dir(path) { - Ok(v) => v, - Err(_) => return Err(()), - }; - - let mut children = HashMap::new(); - - for entry in reader { - let entry = match entry { - Ok(v) => v, - Err(_) => return Err(()), - }; - - let path = entry.path(); - let name = path.file_name().unwrap().to_string_lossy().into_owned(); - - let mut child_route = route.iter().cloned().collect::>(); - child_route.push(name.clone()); - - match self.read_path(&child_route, &path) { - Ok(child_item) => { - children.insert(name, child_item); - }, - Err(_) => {}, - } - } - - let file_name = path.file_name().unwrap().to_string_lossy().into_owned(); - - Ok(VfsItem::Dir { - route: route.iter().cloned().collect::>(), - file_name, - children, - }) - } - - fn read_file>(&self, route: &[String], path: P) -> Result { - let path = path.as_ref(); - let mut file = match File::open(path) { - Ok(v) => v, - Err(_) => return Err(()), - }; - - let mut contents = String::new(); - - match file.read_to_string(&mut contents) { - Ok(_) => {}, - Err(_) => return Err(()), - } - - let file_name = path.file_name().unwrap().to_string_lossy().into_owned(); - - Ok(VfsItem::File { - route: route.iter().cloned().collect::>(), - file_name, - contents, - }) - } - - fn read_path>(&self, route: &[String], path: P) -> Result { - let path = path.as_ref(); - - let metadata = match fs::metadata(path) { - Ok(v) => v, - Err(_) => return Err(()), - }; - - if metadata.is_dir() { - self.read_dir(route, path) - } else if metadata.is_file() { - self.read_file(route, path) - } else { - Err(()) - } - } - - /// Get the current time, used for logging timestamps for file changes. - pub fn current_time(&self) -> f64 { - let elapsed = self.start_time.elapsed(); - - elapsed.as_secs() as f64 + elapsed.subsec_nanos() as f64 * 1e-9 - } - - /// Register a new change to the filesystem at the given timestamp and VFS - /// route. - pub fn add_change(&mut self, timestamp: f64, route: Vec) { - match self.plugin_chain.handle_file_change(&route) { - Some(routes) => { - for route in routes { - self.change_history.push(VfsChange { - timestamp, - route, - }); - } - }, - None => {} - } - } - - /// Collect a list of changes that occured since the given timestamp. - pub fn changes_since(&self, timestamp: f64) -> &[VfsChange] { - let mut marker: Option = None; - - for (index, value) in self.change_history.iter().enumerate().rev() { - if value.timestamp >= timestamp { - marker = Some(index); - } else { - break; - } - } - - if let Some(index) = marker { - &self.change_history[index..] - } else { - &self.change_history[..0] - } - } - - /// Read an item from the filesystem using the given VFS route. - pub fn read(&self, route: &[String]) -> Result { - match self.route_to_path(route) { - Some(path) => self.read_path(route, &path), - None => Err(()), - } - } - - pub fn write(&self, _route: &[String], _item: VfsItem) -> Result<(), ()> { - unimplemented!() - } - - pub fn delete(&self, _route: &[String]) -> Result<(), ()> { - unimplemented!() - } -} diff --git a/server/src/vfs/vfs_watcher.rs b/server/src/vfs/vfs_watcher.rs deleted file mode 100644 index 0e7ac27d..00000000 --- a/server/src/vfs/vfs_watcher.rs +++ /dev/null @@ -1,108 +0,0 @@ -use std::path::PathBuf; -use std::sync::{mpsc, Arc, Mutex}; -use std::thread; -use std::time::Duration; - -use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; - -use pathext::path_to_route; -use vfs::VfsSession; - -/// An object that registers watchers on the real filesystem and relays those -/// changes to the virtual filesystem layer. -pub struct VfsWatcher { - vfs: Arc>, -} - -impl VfsWatcher { - pub fn new(vfs: Arc>) -> VfsWatcher { - VfsWatcher { - vfs, - } - } - - fn start_watcher( - vfs: Arc>, - rx: mpsc::Receiver, - partition_name: String, - root_path: PathBuf, - ) { - loop { - let event = rx.recv().unwrap(); - - let mut vfs = vfs.lock().unwrap(); - let current_time = vfs.current_time(); - - match event { - DebouncedEvent::Write(ref change_path) | - DebouncedEvent::Create(ref change_path) | - DebouncedEvent::Remove(ref change_path) => { - if let Some(mut route) = path_to_route(&root_path, change_path) { - route.insert(0, partition_name.clone()); - - vfs.add_change(current_time, route); - } else { - eprintln!("Failed to get route from {}", change_path.display()); - } - }, - DebouncedEvent::Rename(ref from_change, ref to_change) => { - if let Some(mut route) = path_to_route(&root_path, from_change) { - route.insert(0, partition_name.clone()); - - vfs.add_change(current_time, route); - } else { - eprintln!("Failed to get route from {}", from_change.display()); - } - - if let Some(mut route) = path_to_route(&root_path, to_change) { - route.insert(0, partition_name.clone()); - - vfs.add_change(current_time, route); - } else { - eprintln!("Failed to get route from {}", to_change.display()); - } - }, - _ => {}, - } - } - } - - pub fn start(self) { - let mut watchers = Vec::new(); - - // Create an extra scope so that `vfs` gets dropped and unlocked - { - let vfs = self.vfs.lock().unwrap(); - - for (ref partition_name, ref root_path) in vfs.get_partitions() { - let (tx, rx) = mpsc::channel(); - - let mut watcher: RecommendedWatcher = Watcher::new(tx, Duration::from_millis(200)) - .expect("Unable to create watcher! This is a bug in Rojo."); - - match watcher.watch(&root_path, RecursiveMode::Recursive) { - Ok(_) => (), - Err(_) => { - panic!("Unable to watch partition {}, with path {}! Make sure that it's a file or directory.", partition_name, root_path.display()); - }, - } - - watchers.push(watcher); - - { - let partition_name = partition_name.to_string(); - let root_path = root_path.to_path_buf(); - let vfs = self.vfs.clone(); - - thread::spawn(move || { - Self::start_watcher(vfs, rx, partition_name, root_path); - }); - } - } - } - - loop { - thread::park(); - } - } -} diff --git a/server/src/vfs_session.rs b/server/src/vfs_session.rs new file mode 100644 index 00000000..c4dc3e0b --- /dev/null +++ b/server/src/vfs_session.rs @@ -0,0 +1,242 @@ +use std::collections::HashMap; +use std::io::Read; +use std::fs::{self, File}; +use std::mem; + +use file_route::FileRoute; +use project::Project; + +/// Represents a file or directory that has been read from the filesystem. +#[derive(Debug, Clone)] +pub enum FileItem { + File { + contents: String, + route: FileRoute, + }, + Directory { + children: HashMap, + route: FileRoute, + }, +} + +impl FileItem { + pub fn get_route(&self) -> &FileRoute { + match self { + FileItem::File { route, .. } => route, + FileItem::Directory { route, .. } => route, + } + } +} + +#[derive(Debug, Clone)] +pub enum FileChange { + Created(FileRoute), + Deleted(FileRoute), + Updated(FileRoute), + Moved(FileRoute, FileRoute), +} + +pub struct VfsSession { + pub project: Project, + + /// The in-memory files associated with each partition. + pub partition_files: HashMap, +} + +impl VfsSession { + pub fn new(project: Project) -> VfsSession { + VfsSession { + project, + partition_files: HashMap::new(), + } + } + + pub fn read_partitions(&mut self) { + for partition_name in self.project.partitions.keys() { + let route = FileRoute { + partition: partition_name.clone(), + route: Vec::new(), + }; + + let file_item = self.read(&route).expect("Couldn't load partitions"); + + self.partition_files.insert(partition_name.clone(), file_item); + } + } + + pub fn handle_change(&mut self, change: &FileChange) -> Option<()> { + match change { + FileChange::Created(route) | FileChange::Updated(route) => { + let new_item = self.read(&route).ok()?; + self.set_file_item(new_item); + }, + FileChange::Deleted(route) => { + self.delete_route(&route); + }, + FileChange::Moved(from_route, to_route) => { + let new_item = self.read(&to_route).ok()?; + self.delete_route(&from_route); + self.set_file_item(new_item); + }, + } + + None + } + + pub fn get_by_route(&self, route: &FileRoute) -> Option<&FileItem> { + let partition = self.partition_files.get(&route.partition)?; + let mut current = partition; + + for piece in &route.route { + match current { + FileItem::File { .. } => return None, + FileItem::Directory { children, .. } => { + current = children.get(piece)?; + }, + } + } + + Some(current) + } + + pub fn get_by_route_mut(&mut self, route: &FileRoute) -> Option<&mut FileItem> { + let mut current = self.partition_files.get_mut(&route.partition)?; + + for piece in &route.route { + let mut next = match { current } { + FileItem::File { .. } => return None, + FileItem::Directory { children, .. } => { + children.get_mut(piece)? + }, + }; + + current = next; + } + + Some(current) + } + + pub fn set_file_item(&mut self, item: FileItem) { + match self.get_by_route_mut(item.get_route()) { + Some(existing) => { + mem::replace(existing, item); + return; + }, + None => {}, + } + + if item.get_route().route.len() > 0 { + let mut parent_route = item.get_route().clone(); + let child_name = parent_route.route.pop().unwrap(); + + let mut parent_children = HashMap::new(); + parent_children.insert(child_name, item); + + let parent_item = FileItem::Directory { + route: parent_route, + children: parent_children, + }; + + self.set_file_item(parent_item); + } else { + self.partition_files.insert(item.get_route().partition.clone(), item); + } + } + + pub fn delete_route(&mut self, route: &FileRoute) -> Option<()> { + if route.route.len() == 0 { + self.partition_files.remove(&route.partition); + return Some(()); + } + + let mut current = self.partition_files.get_mut(&route.partition)?; + + for i in 0..(route.route.len() - 1) { + let piece = &route.route[i]; + + let mut next = match { current } { + FileItem::File { .. } => return None, + FileItem::Directory { children, .. } => { + children.get_mut(piece)? + }, + }; + + current = next; + } + + match current { + FileItem::Directory { children, .. } => { + children.remove(route.route.last().unwrap().as_str()); + }, + _ => {}, + } + + Some(()) + } + + fn read(&self, route: &FileRoute) -> Result { + let partition_path = &self.project.partitions.get(&route.partition) + .ok_or(())?.path; + let path = route.to_path_buf(partition_path); + + let metadata = fs::metadata(path) + .map_err(|_| ())?; + + if metadata.is_dir() { + self.read_directory(route) + } else if metadata.is_file() { + self.read_file(route) + } else { + Err(()) + } + } + + fn read_file(&self, route: &FileRoute) -> Result { + let partition_path = &self.project.partitions.get(&route.partition) + .ok_or(())?.path; + let path = route.to_path_buf(partition_path); + + let mut file = File::open(path) + .map_err(|_| ())?; + + let mut contents = String::new(); + + file.read_to_string(&mut contents) + .map_err(|_| ())?; + + Ok(FileItem::File { + contents, + route: route.clone(), + }) + } + + fn read_directory(&self, route: &FileRoute) -> Result { + let partition_path = &self.project.partitions.get(&route.partition) + .ok_or(())?.path; + let path = route.to_path_buf(partition_path); + + let reader = fs::read_dir(path) + .map_err(|_| ())?; + + let mut children = HashMap::new(); + + for entry in reader { + let entry = entry + .map_err(|_| ())?; + + let path = entry.path(); + let name = path.file_name().unwrap().to_string_lossy().into_owned(); + + let child_route = route.extended_with(&[&name]); + + let child_item = self.read(&child_route)?; + + children.insert(name, child_item); + } + + Ok(FileItem::Directory { + children, + route: route.clone(), + }) + } +} diff --git a/server/src/web.rs b/server/src/web.rs index dd05b2a4..7c81641a 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -1,225 +1,212 @@ -use std::io::Read; -use std::sync::{Arc, Mutex}; +use std::borrow::Cow; +use std::collections::HashMap; +use std::sync::{mpsc, RwLock, Arc}; -use rouille; -use serde; -use serde_json; +use rouille::{self, Request, Response}; +use id::Id; +use message_session::{MessageSession, Message}; use project::Project; -use vfs::{VfsSession, VfsChange}; use rbx::RbxInstance; -use plugin::PluginChain; - -static MAX_BODY_SIZE: usize = 25 * 1024 * 1024; // 25 MiB +use rbx_session::RbxSession; +use session::Session; /// The set of configuration the web server needs to start. pub struct WebConfig { pub port: u64, - pub verbose: bool, + pub project: Project, pub server_id: u64, + pub rbx_session: Arc>, + pub message_session: MessageSession, } -#[derive(Debug, Serialize)] +impl WebConfig { + pub fn from_session(server_id: u64, port: u64, session: &Session) -> WebConfig { + WebConfig { + port, + server_id, + project: session.project.clone(), + rbx_session: session.get_rbx_session(), + message_session: session.get_message_session(), + } + } +} + +#[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -struct ServerInfo<'a> { +pub struct ServerInfoResponse<'a> { + pub server_id: &'a str, + pub server_version: &'a str, + pub protocol_version: u64, + pub partitions: HashMap>, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ReadAllResponse<'a> { + pub server_id: &'a str, + pub message_cursor: i32, + pub instances: Cow<'a, HashMap>, + pub partition_instances: Cow<'a, HashMap>, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ReadResponse<'a> { + pub server_id: &'a str, + pub message_cursor: i32, + pub instances: HashMap>, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SubscribeResponse<'a> { + pub server_id: &'a str, + pub message_cursor: i32, + pub messages: Cow<'a, [Message]>, +} + +pub struct Server { + config: WebConfig, server_version: &'static str, - protocol_version: u64, - server_id: &'a str, - project: &'a Project, - current_time: f64, + server_id: String, } -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -struct ReadResult<'a> { - items: Vec>, - server_id: &'a str, - current_time: f64, -} - -#[derive(Debug, Serialize)] -#[serde(rename_all = "camelCase")] -struct ChangesResult<'a> { - changes: &'a [VfsChange], - server_id: &'a str, - current_time: f64, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -struct WriteSpecifier { - route: String, - item: RbxInstance, -} - -fn json(value: T) -> rouille::Response { - let data = serde_json::to_string(&value).unwrap(); - rouille::Response::from_data("application/json", data) -} - -/// Pulls text that may be JSON out of a Rouille Request object. -/// -/// Doesn't do any actual parsing -- all this method does is verify the content -/// type of the request and read the request's body. -fn read_json_text(request: &rouille::Request) -> Option { - // Bail out if the request body isn't marked as JSON - match request.header("Content-Type") { - Some(header) => if !header.starts_with("application/json") { - return None; - }, - None => return None, +impl Server { + pub fn new(config: WebConfig) -> Server { + Server { + server_version: env!("CARGO_PKG_VERSION"), + server_id: config.server_id.to_string(), + config, + } } - let body = match request.data() { - Some(v) => v, - None => return None, - }; - - // Allocate a buffer and read up to MAX_BODY_SIZE+1 bytes into it. - let mut out = Vec::new(); - match body.take(MAX_BODY_SIZE.saturating_add(1) as u64).read_to_end(&mut out) { - Ok(_) => {}, - Err(_) => return None, - } - - // If the body was too big (MAX_BODY_SIZE+1), we abort instead of trying to - // process it. - if out.len() > MAX_BODY_SIZE { - return None; - } - - let parsed = match String::from_utf8(out) { - Ok(v) => v, - Err(_) => return None, - }; - - Some(parsed) -} - -/// Reads the body out of a Rouille Request and attempts to turn it into JSON. -fn read_json(request: &rouille::Request) -> Option -where - T: serde::de::DeserializeOwned, -{ - let body = match read_json_text(&request) { - Some(v) => v, - None => return None, - }; - - let parsed = match serde_json::from_str(&body) { - Ok(v) => v, - Err(_) => return None, - }; - - // TODO: Change return type to some sort of Result - - Some(parsed) -} - -/// Start the Rojo web server and park our current thread. -pub fn start(config: WebConfig, project: Project, plugin_chain: &'static PluginChain, vfs: Arc>) { - let address = format!("localhost:{}", config.port); - - let server_id = config.server_id.to_string(); - - rouille::start_server(address, move |request| { + pub fn handle_request(&self, request: &Request) -> Response { router!(request, (GET) (/) => { + Response::text("Rojo up and running!") + }, + + (GET) (/api/rojo) => { // Get a summary of information about the server. - let current_time = { - let vfs = vfs.lock().unwrap(); + let mut partitions = HashMap::new(); - vfs.current_time() - }; - - json(ServerInfo { - server_version: env!("CARGO_PKG_VERSION"), - protocol_version: 1, - server_id: &server_id, - project: &project, - current_time, - }) - }, - - (GET) (/changes/{ last_time: f64 }) => { - // Get the list of changes since the given time. - - let vfs = vfs.lock().unwrap(); - let current_time = vfs.current_time(); - let changes = vfs.changes_since(last_time); - - json(ChangesResult { - changes, - server_id: &server_id, - current_time, - }) - }, - - (POST) (/read) => { - // Read some instances from the server according to a JSON - // format body. - - let read_request: Vec> = match read_json(&request) { - Some(v) => v, - None => return rouille::Response::empty_400(), - }; - - // Read the files off of the filesystem that the client - // requested. - let (items, current_time) = { - let vfs = vfs.lock().unwrap(); - - let current_time = vfs.current_time(); - - let mut items = Vec::new(); - - for route in &read_request { - match vfs.read(&route) { - Ok(v) => items.push(Some(v)), - Err(_) => items.push(None), - } - } - - (items, current_time) - }; - - // Transform all of our VfsItem objects into Roblox instances - // the client can use. - let rbx_items = items - .iter() - .map(|item| { - match *item { - Some(ref item) => plugin_chain.transform_file(item), - None => None, - } - }) - .collect::>(); - - if config.verbose { - println!("Got read request: {:?}", read_request); - println!("Responding with:\n\t{:?}", rbx_items); + for partition in self.config.project.partitions.values() { + partitions.insert(partition.name.clone(), partition.target.clone()); } - json(ReadResult { - server_id: &server_id, - items: rbx_items, - current_time, + Response::json(&ServerInfoResponse { + server_version: self.server_version, + protocol_version: 2, + server_id: &self.server_id, + partitions: partitions, }) }, - (POST) (/write) => { - // Not yet implemented. + (GET) (/api/subscribe/{ cursor: i32 }) => { + // Retrieve any messages past the given cursor index, and if + // there weren't any, subscribe to receive any new messages. - let _write_request: Vec = match read_json(&request) { - Some(v) => v, - None => return rouille::Response::empty_400(), - }; + // Did the client miss any messages since the last subscribe? + { + let messages = self.config.message_session.messages.read().unwrap(); - rouille::Response::empty_404() + if cursor > messages.len() as i32 { + return Response::json(&SubscribeResponse { + server_id: &self.server_id, + messages: Cow::Borrowed(&[]), + message_cursor: messages.len() as i32 - 1, + }); + } + + if cursor < messages.len() as i32 - 1 { + let new_messages = &messages[(cursor + 1) as usize..]; + let new_cursor = cursor + new_messages.len() as i32; + + return Response::json(&SubscribeResponse { + server_id: &self.server_id, + messages: Cow::Borrowed(new_messages), + message_cursor: new_cursor, + }); + } + } + + let (tx, rx) = mpsc::channel(); + + let sender_id = self.config.message_session.subscribe(tx); + + match rx.recv() { + Ok(_) => (), + Err(_) => return Response::text("error!").with_status_code(500), + } + + self.config.message_session.unsubscribe(sender_id); + + { + let messages = self.config.message_session.messages.read().unwrap(); + let new_messages = &messages[(cursor + 1) as usize..]; + let new_cursor = cursor + new_messages.len() as i32; + + Response::json(&SubscribeResponse { + server_id: &self.server_id, + messages: Cow::Borrowed(new_messages), + message_cursor: new_cursor, + }) + } }, - _ => rouille::Response::empty_404() + (GET) (/api/read_all) => { + let rbx_session = self.config.rbx_session.read().unwrap(); + + let message_cursor = self.config.message_session.get_message_cursor(); + + Response::json(&ReadAllResponse { + server_id: &self.server_id, + message_cursor, + instances: Cow::Borrowed(rbx_session.tree.get_all_instances()), + partition_instances: Cow::Borrowed(&rbx_session.partition_instances), + }) + }, + + (GET) (/api/read/{ id_list: String }) => { + let requested_ids = id_list + .split(",") + .map(str::parse::) + .collect::, _>>(); + + let requested_ids = match requested_ids { + Ok(v) => v, + Err(_) => return rouille::Response::text("Malformed ID list").with_status_code(400), + }; + + let rbx_session = self.config.rbx_session.read().unwrap(); + + let message_cursor = self.config.message_session.get_message_cursor(); + + let mut instances = HashMap::new(); + + for requested_id in &requested_ids { + rbx_session.tree.get_instance(*requested_id, &mut instances); + } + + Response::json(&ReadResponse { + server_id: &self.server_id, + message_cursor, + instances, + }) + }, + + _ => Response::empty_404() ) - }); + } +} + +/// Start the Rojo web server, taking over the current thread. +#[allow(unreachable_code)] +pub fn start(config: WebConfig) { + let address = format!("localhost:{}", config.port); + let server = Server::new(config); + + rouille::start_server(address, move |request| server.handle_request(request)); } diff --git a/server/src/web_util.rs b/server/src/web_util.rs new file mode 100644 index 00000000..0c344e6c --- /dev/null +++ b/server/src/web_util.rs @@ -0,0 +1,43 @@ +use std::io::Read; + +use rouille; +use serde; +use serde_json; + +static MAX_BODY_SIZE: usize = 100 * 1024 * 1024; // 100 MiB + +/// Pulls text that may be JSON out of a Rouille Request object. +/// +/// Doesn't do any actual parsing -- all this method does is verify the content +/// type of the request and read the request's body. +fn read_json_text(request: &rouille::Request) -> Option { + // Bail out if the request body isn't marked as JSON + let content_type = request.header("Content-Type")?; + + if !content_type.starts_with("application/json") { + return None; + } + + let body = request.data()?; + + // Allocate a buffer and read up to MAX_BODY_SIZE+1 bytes into it. + let mut out = Vec::new(); + body.take(MAX_BODY_SIZE.saturating_add(1) as u64).read_to_end(&mut out).ok()?; + + // If the body was too big (MAX_BODY_SIZE+1), we abort instead of trying to + // process it. + if out.len() > MAX_BODY_SIZE { + return None; + } + + String::from_utf8(out).ok() +} + +/// Reads the body out of a Rouille Request and attempts to turn it into JSON. +pub fn read_json(request: &rouille::Request) -> Option +where + T: serde::de::DeserializeOwned, +{ + let body = read_json_text(&request)?; + serde_json::from_str(&body).ok()? +} diff --git a/server/test-projects/empty/rojo.json b/server/test-projects/empty/rojo.json new file mode 100644 index 00000000..51c7917c --- /dev/null +++ b/server/test-projects/empty/rojo.json @@ -0,0 +1,5 @@ +{ + "name": "empty", + "servePort": 23456, + "partitions": {} +} \ No newline at end of file diff --git a/server/test-projects/one-partition/lib/a.lua b/server/test-projects/one-partition/lib/a.lua new file mode 100644 index 00000000..f23fd06a --- /dev/null +++ b/server/test-projects/one-partition/lib/a.lua @@ -0,0 +1 @@ +-- a.lua \ No newline at end of file diff --git a/server/test-projects/one-partition/lib/a.server.lua b/server/test-projects/one-partition/lib/a.server.lua new file mode 100644 index 00000000..08491e94 --- /dev/null +++ b/server/test-projects/one-partition/lib/a.server.lua @@ -0,0 +1 @@ +-- a.server.lua \ No newline at end of file diff --git a/server/test-projects/one-partition/lib/b.client.lua b/server/test-projects/one-partition/lib/b.client.lua new file mode 100644 index 00000000..12d034fa --- /dev/null +++ b/server/test-projects/one-partition/lib/b.client.lua @@ -0,0 +1 @@ +-- b.client.lua \ No newline at end of file diff --git a/server/test-projects/one-partition/rojo.json b/server/test-projects/one-partition/rojo.json new file mode 100644 index 00000000..d774a8f8 --- /dev/null +++ b/server/test-projects/one-partition/rojo.json @@ -0,0 +1,10 @@ +{ + "name": "one-partition", + "servePort": 23456, + "partitions": { + "lib": { + "path": "lib", + "target": "ReplicatedStorage.OnePartition" + } + } +} \ No newline at end of file diff --git a/server/tests/test_util/mod.rs b/server/tests/test_util/mod.rs new file mode 100644 index 00000000..cca6744b --- /dev/null +++ b/server/tests/test_util/mod.rs @@ -0,0 +1,22 @@ +use rouille::Request; + +use librojo::web::Server; + +pub trait HttpTestUtil { + fn get_string(&self, url: &str) -> String; +} + +impl HttpTestUtil for Server { + fn get_string(&self, url: &str) -> String { + let info_request = Request::fake_http("GET", url, vec![], vec![]); + let response = self.handle_request(&info_request); + + assert_eq!(response.status_code, 200); + + let (mut reader, _) = response.data.into_reader_and_size(); + let mut body = String::new(); + reader.read_to_string(&mut body).unwrap(); + + body + } +} diff --git a/server/tests/web.rs b/server/tests/web.rs new file mode 100644 index 00000000..d59e822e --- /dev/null +++ b/server/tests/web.rs @@ -0,0 +1,170 @@ +extern crate rouille; +extern crate serde_json; +extern crate serde; + +extern crate librojo; + +mod test_util; +use test_util::*; + +use std::collections::HashMap; +use std::path::PathBuf; + +use librojo::{ + session::Session, + project::Project, + web::{Server, WebConfig, ServerInfoResponse, ReadResponse, ReadAllResponse}, +}; + +#[test] +fn empty() { + let project_path = { + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("test-projects/empty"); + path + }; + + let project = Project::load(&project_path).unwrap(); + let mut session = Session::new(project.clone()); + session.start(); + + let web_config = WebConfig::from_session(0, project.serve_port, &session); + let server = Server::new(web_config); + + { + let body = server.get_string("/api/rojo"); + let response = serde_json::from_str::(&body).unwrap(); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.protocol_version, 2); + assert_eq!(response.partitions.len(), 0); + } + + { + let body = server.get_string("/api/read_all"); + let response = serde_json::from_str::(&body).unwrap(); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.message_cursor, -1); + assert_eq!(response.instances.len(), 0); + } + + { + let body = server.get_string("/api/read/0"); + let response = serde_json::from_str::(&body).unwrap(); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.message_cursor, -1); + assert_eq!(response.instances.len(), 0); + } +} + +#[test] +fn one_partition() { + let project_path = { + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("test-projects/one-partition"); + path + }; + + let project = Project::load(&project_path).unwrap(); + let mut session = Session::new(project.clone()); + session.start(); + + let web_config = WebConfig::from_session(0, project.serve_port, &session); + let server = Server::new(web_config); + + { + let body = server.get_string("/api/rojo"); + let response = serde_json::from_str::(&body).unwrap(); + + let mut partitions = HashMap::new(); + partitions.insert("lib".to_string(), vec!["ReplicatedStorage".to_string(), "OnePartition".to_string()]); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.protocol_version, 2); + assert_eq!(response.partitions, partitions); + } + + { + let body = server.get_string("/api/read_all"); + let response = serde_json::from_str::(&body).unwrap(); + + let partition_id = *response.partition_instances.get("lib").unwrap(); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.message_cursor, -1); + assert_eq!(response.instances.len(), 4); // root and three children + + let mut found_root = false; + let mut found_module = false; + let mut found_client = false; + let mut found_server = false; + + for (id, instance) in response.instances.iter() { + match instance.class_name.as_str() { + // TOOD: Should partition roots (and other directories) be some + // magical object instead of Folder? + "Folder" => { + assert!(!found_root); + found_root = true; + + assert_eq!(*id, partition_id); + + // TODO: Should this actually equal the last part of the + // partition's target? + assert_eq!(instance.name, "OnePartition"); + + assert_eq!(instance.properties.len(), 0); + assert_eq!(instance.parent, None); + assert_eq!(instance.children.len(), 3); + }, + "ModuleScript" => { + assert!(!found_module); + found_module = true; + + let mut properties = HashMap::new(); + properties.insert("Source".to_string(), "-- a.lua".to_string()); + + assert_eq!(instance.name, "a"); + assert_eq!(instance.properties, properties); + assert_eq!(instance.parent, Some(partition_id)); + assert_eq!(instance.children.len(), 0); + }, + "LocalScript" => { + assert!(!found_client); + found_client = true; + + let mut properties = HashMap::new(); + properties.insert("Source".to_string(), "-- b.client.lua".to_string()); + + assert_eq!(instance.name, "b"); + assert_eq!(instance.properties, properties); + assert_eq!(instance.parent, Some(partition_id)); + assert_eq!(instance.children.len(), 0); + }, + "Script" => { + assert!(!found_server); + found_server = true; + + let mut properties = HashMap::new(); + properties.insert("Source".to_string(), "-- a.server.lua".to_string()); + + assert_eq!(instance.name, "a"); + assert_eq!(instance.properties, properties); + assert_eq!(instance.parent, Some(partition_id)); + assert_eq!(instance.children.len(), 0); + }, + _ => panic!("Unexpected instance!"), + } + } + + assert!(found_root); + assert!(found_module); + assert!(found_client); + assert!(found_server); + } + + // TODO: Test /read + // TODO: Test /subscribe +} \ No newline at end of file From 0b46860cddf06819fa80705be11fbb0277e10452 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 23:00:51 -0700 Subject: [PATCH 0163/1504] merge impl-v2: DESIGN.md and design.gv --- DESIGN.md | 151 +++++++++++++++++++++++++++++++++++++++++------------- design.gv | 30 +++++++++++ 2 files changed, 144 insertions(+), 37 deletions(-) create mode 100644 design.gv diff --git a/DESIGN.md b/DESIGN.md index bd2094e7..1847c57d 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -1,49 +1,126 @@ -# Rojo Design - Protocol Version 1 -This is a super rough draft that I'm trying to use to lay out some of my thoughts. +# Rojo - Protocol v2 Design +This spec is a work in progress. -## API +The aim is to rewrite most of Rojo to drop the notion of routes almost entirely in favor of generated IDs and make the server much more stateful. This should make change description completely robust in all cases, including models with many duplicated instance names. -### POST `/read` -Accepts a `Vec` of items to read. +## Base Terms -Returns `Vec>`, in the same order as the request. +* **Server**: The binary portion of Rojo, in Rust. +* **Client**: The Roblox Studio plugin portion of Rojo, in Lua. +* **Middleware**: Part of the server, transforms files to Roblox representations and back. +* **VFS**: The Virtual File System specifically that middleware deal with; it is in-memory. +* **Roblox Instance**: An actual Roblox object derived from `Instance` on the client. -### POST `/write` -Accepts a `Vec<{ Route, RbxInstance }>` of items to write. +## Initialization +On server initialization, Rojo reads all files in each partition and runs each through our middleware stack (renamed from plugins). Middleware transform a `VfsItem` into a set of `RbxInstance` objects with these properties: -I imagine that the `Name` attribute of the top-level `RbxInstance` would be ignored in favor of the route name? +* name: `String` +* class_name: `String` +* parent: `Option` +* properties: `HashMap` +* file_route: `FileRoute` +* id: `Id` +* rbx_referent: `Option` -## CLI -The `rojo serve` command uses three major components: -* A Virtual Filesystem (VFS), which exposes the filesystem as `VfsItem` objects -* A VFS watcher, which tracks changes to the filesystem and logs them -* An HTTP API, which exposes an interface to the Roblox Studio plugin +The server should keep these book-keeping maps: -### Transform Plugins -Transform plugins (or filter plugins?) can interject in three places: -* Transform a `VfsItem` that's being read into an `RbxInstance` in the VFS -* Transform an `RbxInstance` that's being written into a `VfsItem` in the VFS -* Transform a file change into paths that need to be updated in the VFS watcher +* partitions: `HashMap`, to read partitions from disk +* partition_instances: `HashMap`, to track partition instances +* partition_files: `HashMap`, to serve as an in-memory filesystem +* instances: `HashMap`, to serve as an index +* instances_by_route: `HashMap`, to handle filesystem changes -The plan is to have several built-in plugins that can be rearranged/configured in project settings: +As a future extension, the server should also track: -* Base plugin - * Transforms all unhandled files to/from StringValue objects -* Script plugin - * Transforms `*.lua` files to their appropriate file types -* JSON/rbxmx/rbxlx model plugin -* External binary plugin - * User passes a binary name (like `moonc`) that modifies file contents +* `referent_to_id`: `HashMap`, when loading `rbxmx` format models from disk. -## Roblox Studio Plugin -With the protocol version 1 change, the Roblox Studio plugin got a lot simpler. Notably, the plugin doesn't need to be aware of anything about the filesystem's semantics, which is super handy. +`Partition` is defined as: -## Bi-directional syncing -Quenty laid out a good way to handle bi-directional syncing. +* path: `PathBuf` +* target: `Vec` -When receiving a change from the plugin: -1. Hash the new contents of the file, store it in a map from routes to hashes -2. Write the new file contents to the filesystem -3. Later down the line, receive a change event from the filesystem watcher -4. When receiving a change, if the item is in the hash map, read it and hash those contents -5. If the hash matches the last noted hash, discard the change, else continue as normal \ No newline at end of file +On initial sync, the client should receive: + +* A list of every `RbxInstance` the server knows of. +* A map from `Id` to a Roblox route, containing an entry for every partition and where they should be mounted. + +## File Changes +Whenever a file is changed, the server should: + +* Convert its path to a `FileRoute`. +* Read the file into a `VfsItem` object. +* Compare the contents of the file with the last-seen contents from the map from `FileRoute` to `String`. + * If they're the same, that means this change was caused by the server itself, and should be discarded. + * Else, clear the value from the map. +* Pass the `VfsItem` through the middleware chain to create a tree of `RbxInstance` objects. +* Check the existing map from `FileRoute` to `Id`. + * If an existing instance exists with the root's `Id`, reuse it and replace the root's `Id`. + * Else, generate a new ID. +* For each child instance: + * If an `RbxReferent` value is present on the instance, attempt to map it to an existing `Id`, falling back to creating a new `Id`. +* Log a change event `(Timestamp, Id)` for the root instance into a sorted list that's client queryable. + +The client will then: + +* Receive notice of changes by receiving a list of `Id`s that have changed. +* Ask the server for the contents of each `Id` that has changed. +* Apply the properties the server returns to each instance. + +If an `Id` was not previously tracked by the client, the associated `RbxInstance`'s `parent` field will point to another `Id`. The client will either have knowledge of that `Id`, or request it from the server if it isn't known. This can potentially continue up the tree until the client reaches a partition mount point, which should be known by the client due to the initialization process. + +## Client Changes +The client should keep list of mutations to track any uncommitted changes to Roblox Instances tracked by Rojo. + +Those changes should come in three flavors: + +* Changed a property (need `id`, `key`, and `value`) +* Deleted a known instance (need `id`) +* Created a new instance (need `clientId`) + +Every sync period, which could be around 50ms, the plugin should send a request with every Roblox Instance mutation all at once. + +In order to correctly serialize changes received from the client, some care needs to be taken. + +For every *Changed* or *Deleted* mutation received from the client, the server should: + +* Attempt to locate the `RbxInstance` associated with the `id`. + * If it doesn't exist, abort the change and output a warning to the console. +* Modify the `RbxInstance` in-place. +* Traverse up the tree by following the `parent` property until an `RbxInstance` is found that has a `route` property. +* Use the middleware chain to serialize these nodes to a single `VfsItem` object. +* Insert the contents of the `VfsItem` into the server's map from `Route` to `String`, which is used by the "File Changes" process. +* Write the file or directory to the disk atomically using *write-and-rename*. + +For every *Created* mutation received from the client, the server should: + +* Attempt to locate the `RbxInstance` associated with the instance's `parent` `Id` + * If it doesn't exist, abort the change and output a warning to the console. +* Generate a new `Id` for the instance being created. +* Use the middleware chain to process the added instance, its parent, and generate a list of `VfsItem` objects to commit to disk. +* Insert the `RbxInstance` into all of the server's relevant maps. +* Yield the generated `Id` to the client, indexed by the request's `clientId`, which can be used for later updates in both directions. + +## State and Session Restart +Previously, only the client had meaningful state with regards to what instances were loaded; the server in 0.3.x only tracks a list of changes by route. + +Both the Rojo server and client in the Stateful IDs redesign have a significant amount of state, which requires using a field already present, but unused, in the sync protocol. + +During initialization and initial sync, the server should send the client two values: +* A server ID value generated randomly on each startup +* A project name, specified in `rojo.json` + +The client should store the server ID as connection metadata, and the project name as place metadata that it may persist. + +Every request from the client should attach both the server ID and the project name. As a first validation check, the server must compare both values to its own. + +If a mismatch is detected, the server should immediately abort the request and return an error containing its server ID and loaded project name. + +If the client detects an error in this way, it should delete any connection metadata, including `Id` mappings -- this data is no longer relevant to any new connections. + +If the returned project name matches the value that the client was using before, the client should begin a *session restart* by reinitializing the connection to the server and creating new metadata. + +## Other Changes +These changes aren't directly related to this refactor, but are changes that need to be made to Rojo. + +* Unknown instances will no longer sync as `StringValue` instances +* `rojo init` generates project files with random port numbers \ No newline at end of file diff --git a/design.gv b/design.gv new file mode 100644 index 00000000..910efaf4 --- /dev/null +++ b/design.gv @@ -0,0 +1,30 @@ +digraph G { + ranksep=0.7; + node [ + fontname="Hack", + shape="box", + ]; + + roblox_studio -> plugin [dir="both"]; + plugin -> web_server [style="dashed", dir="both"]; + + web_server -> rbx_session; + + session -> rbx_session [dir="both"]; + session -> vfs_session; + session -> watchers [dir="both"]; + + vfs_session -> fs; + + rbx_session -> vfs_session [constraint=false]; + rbx_session -> middlewares; + + roblox_studio [label="Roblox Studio"]; + fs [label="Filesystem"]; + middlewares [label="Vec"]; + watchers [label="Vec"]; + session [label="Session"]; + web_server [label="Rouille Server"]; + vfs_session [label="Arc>"]; + rbx_session [label="Arc>"]; +} \ No newline at end of file From 8893d0ddde5bdabe32dd8b1d5252d1477dc442c6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 23:07:33 -0700 Subject: [PATCH 0164/1504] Update README --- README.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 78d94c87..12f2099c 100644 --- a/README.md +++ b/README.md @@ -40,16 +40,13 @@ There are lots of other tools that sync scripts into Roblox or provide other too Here are a few, if you're looking for alternatives or supplements to Rojo: -* [Studio Bridge by Vocksel](https://github.com/vocksel/studio-bridge) +* [rbxmk by Anaminus](https://github.com/anaminus/rbxmk) * [RbxRefresh by Osyris](https://github.com/osyrisrblx/RbxRefresh) +* [Studio Bridge by Vocksel](https://github.com/vocksel/studio-bridge) * [RbxSync by evaera](https://github.com/evaera/RbxSync) * [CodeSync](https://github.com/MemoryPenguin/CodeSync) and [rbx-exteditor](https://github.com/MemoryPenguin/rbx-exteditor) by [MemoryPenguin](https://github.com/MemoryPenguin) -* [rbxmk by Anaminus](https://github.com/anaminus/rbxmk) -I also have a couple tools that Rojo intends to replace: - -* [rbxfs](https://github.com/LPGhatguy/rbxfs), which has been deprecated by Rojo -* [rbxpacker](https://github.com/LPGhatguy/rbxpacker), which is still useful +If you use a plugin that _isn't_ Rojo for syncing code, open an issue and let me know why! I'd like Rojo to be the end-all tool so that people stop reinventing solutions to this problem. ## Contributing Pull requests are welcome! From 9aa27f4c11d6042c7abbe5d3759b028e7a4afc61 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 23:10:41 -0700 Subject: [PATCH 0165/1504] Finish merging impl-v2 --- test-project/rojo.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test-project/rojo.json b/test-project/rojo.json index c7e2f3e8..3d7187b6 100644 --- a/test-project/rojo.json +++ b/test-project/rojo.json @@ -1,6 +1,6 @@ { "name": "test-project", - "servePort": 8001, + "servePort": 34872, "partitions": { "src": { "path": "src", From db71bdfde7b8e7ea2f7289835dff28e2d356f4af Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 23:11:10 -0700 Subject: [PATCH 0166/1504] Protocol v2 (0.5.0) (#56) From 9733f059c2ffb92ee04b08c5195cbafde4e1d07f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 23:22:07 -0700 Subject: [PATCH 0167/1504] Do something wrong instead of crashing for partitions pointing at files --- server/src/rbx_session.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 7db35bff..d5eb56d5 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -32,8 +32,7 @@ fn file_to_instances( // This is placeholder logic; this whole function is! let (class_name, property_key, name) = { - // TODO: Root instances have an empty route - let file_name = route.route.last().unwrap(); + let file_name = route.route.last().unwrap_or(&route.partition); fn strip_suffix<'a>(source: &'a str, suffix: &'static str) -> &'a str { &source[..source.len() - suffix.len()] From 284f5cfb716d20e9caf948b003af095712cf32d3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 23:36:38 -0700 Subject: [PATCH 0168/1504] Test /read endpoint for single partition case --- server/tests/web.rs | 69 ++++++++++++++++++++++++++++++++------------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/server/tests/web.rs b/server/tests/web.rs index d59e822e..d7a64382 100644 --- a/server/tests/web.rs +++ b/server/tests/web.rs @@ -9,6 +9,7 @@ use test_util::*; use std::collections::HashMap; use std::path::PathBuf; +use std::borrow::Cow; use librojo::{ session::Session, @@ -86,7 +87,7 @@ fn one_partition() { assert_eq!(response.partitions, partitions); } - { + let check_base_read_all = || { let body = server.get_string("/api/read_all"); let response = serde_json::from_str::(&body).unwrap(); @@ -96,18 +97,18 @@ fn one_partition() { assert_eq!(response.message_cursor, -1); assert_eq!(response.instances.len(), 4); // root and three children - let mut found_root = false; - let mut found_module = false; - let mut found_client = false; - let mut found_server = false; + let mut root_id = None; + let mut module_id = None; + let mut client_id = None; + let mut server_id = None; for (id, instance) in response.instances.iter() { match instance.class_name.as_str() { // TOOD: Should partition roots (and other directories) be some // magical object instead of Folder? "Folder" => { - assert!(!found_root); - found_root = true; + assert!(root_id.is_none()); + root_id = Some(*id); assert_eq!(*id, partition_id); @@ -118,10 +119,17 @@ fn one_partition() { assert_eq!(instance.properties.len(), 0); assert_eq!(instance.parent, None); assert_eq!(instance.children.len(), 3); + + let single_body = server.get_string(&format!("/api/read/{}", id)); + let single_response = serde_json::from_str::(&single_body).unwrap(); + + let single_instance = single_response.instances.get(id).unwrap(); + + assert_eq!(single_instance, &Cow::Borrowed(instance)); }, "ModuleScript" => { - assert!(!found_module); - found_module = true; + assert!(module_id.is_none()); + module_id = Some(*id); let mut properties = HashMap::new(); properties.insert("Source".to_string(), "-- a.lua".to_string()); @@ -130,10 +138,17 @@ fn one_partition() { assert_eq!(instance.properties, properties); assert_eq!(instance.parent, Some(partition_id)); assert_eq!(instance.children.len(), 0); + + let single_body = server.get_string(&format!("/api/read/{}", id)); + let single_response = serde_json::from_str::(&single_body).unwrap(); + + let single_instance = single_response.instances.get(id).unwrap(); + + assert_eq!(single_instance, &Cow::Borrowed(instance)); }, "LocalScript" => { - assert!(!found_client); - found_client = true; + assert!(client_id.is_none()); + client_id = Some(*id); let mut properties = HashMap::new(); properties.insert("Source".to_string(), "-- b.client.lua".to_string()); @@ -142,10 +157,17 @@ fn one_partition() { assert_eq!(instance.properties, properties); assert_eq!(instance.parent, Some(partition_id)); assert_eq!(instance.children.len(), 0); + + let single_body = server.get_string(&format!("/api/read/{}", id)); + let single_response = serde_json::from_str::(&single_body).unwrap(); + + let single_instance = single_response.instances.get(id).unwrap(); + + assert_eq!(single_instance, &Cow::Borrowed(instance)); }, "Script" => { - assert!(!found_server); - found_server = true; + assert!(server_id.is_none()); + server_id = Some(*id); let mut properties = HashMap::new(); properties.insert("Source".to_string(), "-- a.server.lua".to_string()); @@ -154,17 +176,26 @@ fn one_partition() { assert_eq!(instance.properties, properties); assert_eq!(instance.parent, Some(partition_id)); assert_eq!(instance.children.len(), 0); + + let single_body = server.get_string(&format!("/api/read/{}", id)); + let single_response = serde_json::from_str::(&single_body).unwrap(); + + let single_instance = single_response.instances.get(id).unwrap(); + + assert_eq!(single_instance, &Cow::Borrowed(instance)); }, _ => panic!("Unexpected instance!"), } } - assert!(found_root); - assert!(found_module); - assert!(found_client); - assert!(found_server); - } + module_id.unwrap(); + client_id.unwrap(); + server_id.unwrap(); + + root_id.unwrap() + }; + + check_base_read_all(); - // TODO: Test /read // TODO: Test /subscribe } \ No newline at end of file From ff0f5cd49c923dc26f6ee157eb1e6561134c783a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 10 Jun 2018 23:44:03 -0700 Subject: [PATCH 0169/1504] Test for children, make child matching more robust --- server/tests/web.rs | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/server/tests/web.rs b/server/tests/web.rs index d7a64382..00303011 100644 --- a/server/tests/web.rs +++ b/server/tests/web.rs @@ -95,7 +95,7 @@ fn one_partition() { assert_eq!(response.server_id, "0"); assert_eq!(response.message_cursor, -1); - assert_eq!(response.instances.len(), 4); // root and three children + assert_eq!(response.instances.len(), 4); let mut root_id = None; let mut module_id = None; @@ -103,19 +103,17 @@ fn one_partition() { let mut server_id = None; for (id, instance) in response.instances.iter() { - match instance.class_name.as_str() { + match (instance.name.as_str(), instance.class_name.as_str()) { // TOOD: Should partition roots (and other directories) be some // magical object instead of Folder? - "Folder" => { + // TODO: Should this name actually equal the last part of the + // partition's target? + ("OnePartition", "Folder") => { assert!(root_id.is_none()); root_id = Some(*id); assert_eq!(*id, partition_id); - // TODO: Should this actually equal the last part of the - // partition's target? - assert_eq!(instance.name, "OnePartition"); - assert_eq!(instance.properties.len(), 0); assert_eq!(instance.parent, None); assert_eq!(instance.children.len(), 3); @@ -127,14 +125,13 @@ fn one_partition() { assert_eq!(single_instance, &Cow::Borrowed(instance)); }, - "ModuleScript" => { + ("a", "ModuleScript") => { assert!(module_id.is_none()); module_id = Some(*id); let mut properties = HashMap::new(); properties.insert("Source".to_string(), "-- a.lua".to_string()); - assert_eq!(instance.name, "a"); assert_eq!(instance.properties, properties); assert_eq!(instance.parent, Some(partition_id)); assert_eq!(instance.children.len(), 0); @@ -146,7 +143,7 @@ fn one_partition() { assert_eq!(single_instance, &Cow::Borrowed(instance)); }, - "LocalScript" => { + ("b", "LocalScript") => { assert!(client_id.is_none()); client_id = Some(*id); @@ -165,7 +162,7 @@ fn one_partition() { assert_eq!(single_instance, &Cow::Borrowed(instance)); }, - "Script" => { + ("a", "Script") => { assert!(server_id.is_none()); server_id = Some(*id); @@ -184,15 +181,20 @@ fn one_partition() { assert_eq!(single_instance, &Cow::Borrowed(instance)); }, - _ => panic!("Unexpected instance!"), + _ => {}, } } - module_id.unwrap(); - client_id.unwrap(); - server_id.unwrap(); + let root_id = root_id.unwrap(); + let module_id = module_id.unwrap(); + let client_id = client_id.unwrap(); + let server_id = server_id.unwrap(); - root_id.unwrap() + let root_instance = response.instances.get(&root_id).unwrap(); + + assert!(root_instance.children.contains(&module_id)); + assert!(root_instance.children.contains(&client_id)); + assert!(root_instance.children.contains(&server_id)); }; check_base_read_all(); From ba3fa24f9ac74f30f5314d58607f4cbbfef729a5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Jun 2018 00:15:15 -0700 Subject: [PATCH 0170/1504] Tests for modifying projects and using /subscribe --- server/src/partition_watcher.rs | 4 +- server/tests/web.rs | 200 +++++++++++++++++++++++++++++--- 2 files changed, 190 insertions(+), 14 deletions(-) diff --git a/server/src/partition_watcher.rs b/server/src/partition_watcher.rs index 2f9785e7..5885bb74 100644 --- a/server/src/partition_watcher.rs +++ b/server/src/partition_watcher.rs @@ -8,6 +8,8 @@ use partition::Partition; use vfs_session::FileChange; use file_route::FileRoute; +const WATCH_TIMEOUT_MS: u64 = 100; + pub struct PartitionWatcher { pub watcher: RecommendedWatcher, } @@ -16,7 +18,7 @@ impl PartitionWatcher { pub fn start_new(partition: Partition, tx: Sender) -> PartitionWatcher { let (watch_tx, watch_rx) = channel(); - let mut watcher = watcher(watch_tx, Duration::from_millis(100)).unwrap(); + let mut watcher = watcher(watch_tx, Duration::from_millis(WATCH_TIMEOUT_MS)).unwrap(); watcher.watch(&partition.path, RecursiveMode::Recursive).unwrap(); diff --git a/server/tests/web.rs b/server/tests/web.rs index 00303011..b21f4220 100644 --- a/server/tests/web.rs +++ b/server/tests/web.rs @@ -7,14 +7,16 @@ extern crate librojo; mod test_util; use test_util::*; -use std::collections::HashMap; -use std::path::PathBuf; use std::borrow::Cow; +use std::collections::HashMap; +use std::fs::{File, remove_file}; +use std::io::Write; +use std::path::PathBuf; use librojo::{ session::Session, project::Project, - web::{Server, WebConfig, ServerInfoResponse, ReadResponse, ReadAllResponse}, + web::{Server, WebConfig, ServerInfoResponse, ReadResponse, ReadAllResponse, SubscribeResponse}, }; #[test] @@ -87,16 +89,16 @@ fn one_partition() { assert_eq!(response.partitions, partitions); } - let check_base_read_all = || { - let body = server.get_string("/api/read_all"); - let response = serde_json::from_str::(&body).unwrap(); - - let partition_id = *response.partition_instances.get("lib").unwrap(); + let initial_body = server.get_string("/api/read_all"); + let initial_response = { + let response = serde_json::from_str::(&initial_body).unwrap(); assert_eq!(response.server_id, "0"); assert_eq!(response.message_cursor, -1); assert_eq!(response.instances.len(), 4); + let partition_id = *response.partition_instances.get("lib").unwrap(); + let mut root_id = None; let mut module_id = None; let mut client_id = None; @@ -150,7 +152,6 @@ fn one_partition() { let mut properties = HashMap::new(); properties.insert("Source".to_string(), "-- b.client.lua".to_string()); - assert_eq!(instance.name, "b"); assert_eq!(instance.properties, properties); assert_eq!(instance.parent, Some(partition_id)); assert_eq!(instance.children.len(), 0); @@ -169,7 +170,6 @@ fn one_partition() { let mut properties = HashMap::new(); properties.insert("Source".to_string(), "-- a.server.lua".to_string()); - assert_eq!(instance.name, "a"); assert_eq!(instance.properties, properties); assert_eq!(instance.parent, Some(partition_id)); assert_eq!(instance.children.len(), 0); @@ -190,14 +190,188 @@ fn one_partition() { let client_id = client_id.unwrap(); let server_id = server_id.unwrap(); + { + let root_instance = response.instances.get(&root_id).unwrap(); + + assert!(root_instance.children.contains(&module_id)); + assert!(root_instance.children.contains(&client_id)); + assert!(root_instance.children.contains(&server_id)); + } + + response + }; + + { + let temp_name = { + let mut path = project_path.clone(); + path.push("lib/c.client.lua"); + path + }; + + { + let mut file = File::create(&temp_name).unwrap(); + file.write_all(b"-- c.client.lua").unwrap(); + } + + { + // Block until Rojo detects the addition of our temp file + let body = server.get_string("/api/subscribe/-1"); + let response = serde_json::from_str::(&body).unwrap(); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.message_cursor, 0); + assert_eq!(response.messages.len(), 1); + } + + let body = server.get_string("/api/read_all"); + let response = serde_json::from_str::(&body).unwrap(); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.message_cursor, 0); + assert_eq!(response.instances.len(), 5); + + let partition_id = *response.partition_instances.get("lib").unwrap(); + + let mut root_id = None; + let mut module_id = None; + let mut client_id = None; + let mut server_id = None; + let mut new_id = None; + + for (id, instance) in response.instances.iter() { + match (instance.name.as_str(), instance.class_name.as_str()) { + // TOOD: Should partition roots (and other directories) be some + // magical object instead of Folder? + // TODO: Should this name actually equal the last part of the + // partition's target? + ("OnePartition", "Folder") => { + assert!(root_id.is_none()); + root_id = Some(*id); + + assert_eq!(*id, partition_id); + + assert_eq!(instance.properties.len(), 0); + assert_eq!(instance.parent, None); + assert_eq!(instance.children.len(), 4); + + let single_body = server.get_string(&format!("/api/read/{}", id)); + let single_response = serde_json::from_str::(&single_body).unwrap(); + + let single_instance = single_response.instances.get(id).unwrap(); + + assert_eq!(single_instance, &Cow::Borrowed(instance)); + }, + ("a", "ModuleScript") => { + assert!(module_id.is_none()); + module_id = Some(*id); + + let mut properties = HashMap::new(); + properties.insert("Source".to_string(), "-- a.lua".to_string()); + + assert_eq!(instance.properties, properties); + assert_eq!(instance.parent, Some(partition_id)); + assert_eq!(instance.children.len(), 0); + + let single_body = server.get_string(&format!("/api/read/{}", id)); + let single_response = serde_json::from_str::(&single_body).unwrap(); + + let single_instance = single_response.instances.get(id).unwrap(); + + assert_eq!(single_instance, &Cow::Borrowed(instance)); + }, + ("b", "LocalScript") => { + assert!(client_id.is_none()); + client_id = Some(*id); + + let mut properties = HashMap::new(); + properties.insert("Source".to_string(), "-- b.client.lua".to_string()); + + assert_eq!(instance.properties, properties); + assert_eq!(instance.parent, Some(partition_id)); + assert_eq!(instance.children.len(), 0); + + let single_body = server.get_string(&format!("/api/read/{}", id)); + let single_response = serde_json::from_str::(&single_body).unwrap(); + + let single_instance = single_response.instances.get(id).unwrap(); + + assert_eq!(single_instance, &Cow::Borrowed(instance)); + }, + ("a", "Script") => { + assert!(server_id.is_none()); + server_id = Some(*id); + + let mut properties = HashMap::new(); + properties.insert("Source".to_string(), "-- a.server.lua".to_string()); + + assert_eq!(instance.properties, properties); + assert_eq!(instance.parent, Some(partition_id)); + assert_eq!(instance.children.len(), 0); + + let single_body = server.get_string(&format!("/api/read/{}", id)); + let single_response = serde_json::from_str::(&single_body).unwrap(); + + let single_instance = single_response.instances.get(id).unwrap(); + + assert_eq!(single_instance, &Cow::Borrowed(instance)); + }, + ("c", "LocalScript") => { + assert!(new_id.is_none()); + new_id = Some(*id); + + let mut properties = HashMap::new(); + properties.insert("Source".to_string(), "-- c.client.lua".to_string()); + + assert_eq!(instance.properties, properties); + assert_eq!(instance.parent, Some(partition_id)); + assert_eq!(instance.children.len(), 0); + + let single_body = server.get_string(&format!("/api/read/{}", id)); + let single_response = serde_json::from_str::(&single_body).unwrap(); + + let single_instance = single_response.instances.get(id).unwrap(); + + assert_eq!(single_instance, &Cow::Borrowed(instance)); + }, + _ => {}, + } + } + + let root_id = root_id.unwrap(); + let module_id = module_id.unwrap(); + let client_id = client_id.unwrap(); + let server_id = server_id.unwrap(); + let new_id = new_id.unwrap(); + let root_instance = response.instances.get(&root_id).unwrap(); assert!(root_instance.children.contains(&module_id)); assert!(root_instance.children.contains(&client_id)); assert!(root_instance.children.contains(&server_id)); - }; + assert!(root_instance.children.contains(&new_id)); - check_base_read_all(); + remove_file(&temp_name).unwrap(); + } - // TODO: Test /subscribe + { + // Block until Rojo detects the removal of our temp file + let body = server.get_string("/api/subscribe/0"); + let response = serde_json::from_str::(&body).unwrap(); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.message_cursor, 1); + assert_eq!(response.messages.len(), 1); + } + + { + // Everything should be back to the initial state! + let body = server.get_string("/api/read_all"); + let response = serde_json::from_str::(&body).unwrap(); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.message_cursor, 1); + assert_eq!(response.instances.len(), 4); + + assert_eq!(response.instances, initial_response.instances); + } } \ No newline at end of file From ba930ea584cf6e00e6fb0cdb9a907fb368de081c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Jun 2018 00:15:49 -0700 Subject: [PATCH 0171/1504] Add TODO --- server/tests/web.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/tests/web.rs b/server/tests/web.rs index b21f4220..9f420118 100644 --- a/server/tests/web.rs +++ b/server/tests/web.rs @@ -221,6 +221,9 @@ fn one_partition() { assert_eq!(response.server_id, "0"); assert_eq!(response.message_cursor, 0); assert_eq!(response.messages.len(), 1); + + // TODO: Read which instance was changed and try to access it with + // /read } let body = server.get_string("/api/read_all"); From f5599b95b352a9229386858c020c186ede4d2fb7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Jun 2018 15:37:59 -0700 Subject: [PATCH 0172/1504] Add TODOs to web tests --- server/tests/web.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/tests/web.rs b/server/tests/web.rs index 9f420118..1e4863c9 100644 --- a/server/tests/web.rs +++ b/server/tests/web.rs @@ -377,4 +377,7 @@ fn one_partition() { assert_eq!(response.instances, initial_response.instances); } + + // TODO: Test to change existing instance + // TODO: Copy each project into temp dir before using them } \ No newline at end of file From 5e08093609038cd3e632e8156d07d935ea1492a8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 24 Jun 2018 14:09:57 -0700 Subject: [PATCH 0173/1504] Update README and CHANGES from 0.4.12 release --- CHANGES.md | 6 +++++- README.md | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d573cd2e..253e734a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,11 @@ # Rojo Change Log ## Current master -* *No changes* +The `master` branch is currently undergoing a major rewrite to lay the groundwork for bidirectional syncing and other robustness improvements. Check out the `v0.4.x` branch for the current release. + +## 0.4.12 (June 21, 2018) +* Fixed obscure assertion failure when renaming or deleting files ([#78](https://github.com/LPGhatguy/rojo/issues/78)) +* Added a `PluginAction` for the sync in command, which should help with some automation scripts ([#80](https://github.com/LPGhatguy/rojo/pull/80)) ## 0.4.11 (June 10, 2018) * Defensively insert existing instances into RouteMap; should fix most duplication cases when syncing into existing trees. diff --git a/README.md b/README.md index 12f2099c..50fc6c0a 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ Travis-CI Build Status - Current server version + Current server version Rojo Documentation From be58598a3e8c9bdd57dadf85ab8bb86624f09f1d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 24 Jun 2018 19:37:30 -0700 Subject: [PATCH 0174/1504] Make web tests no longer mutate original files --- server/Cargo.lock | 7 ++++--- server/Cargo.toml | 7 ++++--- server/tests/test_util/mod.rs | 32 ++++++++++++++++++++++++++++++++ server/tests/web.rs | 22 +++++++++++++++------- 4 files changed, 55 insertions(+), 13 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index f777c0ab..bf03e25e 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -647,7 +647,8 @@ dependencies = [ "serde 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -758,7 +759,7 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.0.1" +version = "3.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1075,7 +1076,7 @@ dependencies = [ "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum syn 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "61b8f1b737f929c6516ba46a3133fd6d5215ad8a62f66760f851f7048aebedfb" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum tempfile 3.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8cddbd26c5686ece823b507f304c8f188daef548b4cb753512d929ce478a093c" +"checksum tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "47776f63b85777d984a50ce49d6b9e58826b6a3766a449fc95bc66cd5663c15b" "checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" diff --git a/server/Cargo.toml b/server/Cargo.toml index 05bc6d60..e38cedd9 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -15,15 +15,16 @@ name = "rojo" path = "src/bin.rs" [dependencies] -clap = "2.27.1" +clap = "2.27" rouille = "2.1" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -notify = "4.0.0" +notify = "4.0" rand = "0.4" regex = "1.0" lazy_static = "1.0" [dev-dependencies] -tempfile = "3" +tempfile = "3.0" +walkdir = "2.1" diff --git a/server/tests/test_util/mod.rs b/server/tests/test_util/mod.rs index cca6744b..ec3c51fd 100644 --- a/server/tests/test_util/mod.rs +++ b/server/tests/test_util/mod.rs @@ -1,5 +1,11 @@ +use std::fs::{create_dir, copy}; +use std::path::Path; +use std::io; + use rouille::Request; +use walkdir::WalkDir; + use librojo::web::Server; pub trait HttpTestUtil { @@ -20,3 +26,29 @@ impl HttpTestUtil for Server { body } } + +pub fn copy_recursive(from: &Path, to: &Path) -> io::Result<()> { + for entry in WalkDir::new(from) { + let entry = entry?; + let path = entry.path(); + let new_path = to.join(path.strip_prefix(from).unwrap()); + + let file_type = entry.file_type(); + + if file_type.is_dir() { + match create_dir(new_path) { + Ok(_) => {}, + Err(err) => match err.kind() { + io::ErrorKind::AlreadyExists => {}, + _ => panic!(err), + } + } + } else if file_type.is_file() { + copy(path, new_path)?; + } else { + unimplemented!("no symlinks please"); + } + } + + Ok(()) +} diff --git a/server/tests/web.rs b/server/tests/web.rs index 1e4863c9..fcd10fd4 100644 --- a/server/tests/web.rs +++ b/server/tests/web.rs @@ -1,6 +1,8 @@ extern crate rouille; extern crate serde_json; extern crate serde; +extern crate tempfile; +extern crate walkdir; extern crate librojo; @@ -21,12 +23,17 @@ use librojo::{ #[test] fn empty() { - let project_path = { + let original_project_path = { let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); path.push("test-projects/empty"); path }; + let project_tempdir = tempfile::tempdir().unwrap(); + let project_path = project_tempdir.path(); + + copy_recursive(&original_project_path, &project_path).unwrap(); + let project = Project::load(&project_path).unwrap(); let mut session = Session::new(project.clone()); session.start(); @@ -64,12 +71,17 @@ fn empty() { #[test] fn one_partition() { - let project_path = { + let original_project_path = { let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); path.push("test-projects/one-partition"); path }; + let project_tempdir = tempfile::tempdir().unwrap(); + let project_path = project_tempdir.path(); + + copy_recursive(&original_project_path, &project_path).unwrap(); + let project = Project::load(&project_path).unwrap(); let mut session = Session::new(project.clone()); session.start(); @@ -202,11 +214,7 @@ fn one_partition() { }; { - let temp_name = { - let mut path = project_path.clone(); - path.push("lib/c.client.lua"); - path - }; + let temp_name = project_path.join("lib/c.client.lua"); { let mut file = File::create(&temp_name).unwrap(); From e1c420d37df92e3d4842474fba44c3f1d5df4fb2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 24 Jun 2018 19:40:50 -0700 Subject: [PATCH 0175/1504] Switch RbxValue to an enum --- server/src/rbx.rs | 9 +++++++-- server/src/rbx_session.rs | 4 ++-- server/tests/web.rs | 15 ++++++++------- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/server/src/rbx.rs b/server/src/rbx.rs index 75c03a1a..d2aa7b50 100644 --- a/server/src/rbx.rs +++ b/server/src/rbx.rs @@ -3,8 +3,13 @@ use std::collections::HashMap; use id::Id; -// TODO: Switch to enum to represent more value types -pub type RbxValue = String; +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(tag = "type")] +pub enum RbxValue { + String { + value: String, + } +} #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index d5eb56d5..198fd52d 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -6,7 +6,7 @@ use id::{Id, get_id}; use message_session::{Message, MessageSession}; use partition::Partition; use project::Project; -use rbx::{RbxInstance, RbxTree}; +use rbx::{RbxInstance, RbxTree, RbxValue}; use vfs_session::{VfsSession, FileItem, FileChange}; // TODO: Rethink data structure and insertion/update behavior. Maybe break some @@ -51,7 +51,7 @@ fn file_to_instances( }; let mut properties = HashMap::new(); - properties.insert(property_key.to_string(), contents.clone()); + properties.insert(property_key.to_string(), RbxValue::String { value: contents.clone() }); tree.insert_instance(primary_id, RbxInstance { name: name.to_string(), diff --git a/server/tests/web.rs b/server/tests/web.rs index fcd10fd4..f37295a4 100644 --- a/server/tests/web.rs +++ b/server/tests/web.rs @@ -19,6 +19,7 @@ use librojo::{ session::Session, project::Project, web::{Server, WebConfig, ServerInfoResponse, ReadResponse, ReadAllResponse, SubscribeResponse}, + rbx::RbxValue, }; #[test] @@ -144,7 +145,7 @@ fn one_partition() { module_id = Some(*id); let mut properties = HashMap::new(); - properties.insert("Source".to_string(), "-- a.lua".to_string()); + properties.insert("Source".to_string(), RbxValue::String { value: "-- a.lua".to_string() }); assert_eq!(instance.properties, properties); assert_eq!(instance.parent, Some(partition_id)); @@ -162,7 +163,7 @@ fn one_partition() { client_id = Some(*id); let mut properties = HashMap::new(); - properties.insert("Source".to_string(), "-- b.client.lua".to_string()); + properties.insert("Source".to_string(), RbxValue::String { value: "-- b.client.lua".to_string() }); assert_eq!(instance.properties, properties); assert_eq!(instance.parent, Some(partition_id)); @@ -180,7 +181,7 @@ fn one_partition() { server_id = Some(*id); let mut properties = HashMap::new(); - properties.insert("Source".to_string(), "-- a.server.lua".to_string()); + properties.insert("Source".to_string(), RbxValue::String { value: "-- a.server.lua".to_string() }); assert_eq!(instance.properties, properties); assert_eq!(instance.parent, Some(partition_id)); @@ -277,7 +278,7 @@ fn one_partition() { module_id = Some(*id); let mut properties = HashMap::new(); - properties.insert("Source".to_string(), "-- a.lua".to_string()); + properties.insert("Source".to_string(), RbxValue::String { value: "-- a.lua".to_string() }); assert_eq!(instance.properties, properties); assert_eq!(instance.parent, Some(partition_id)); @@ -295,7 +296,7 @@ fn one_partition() { client_id = Some(*id); let mut properties = HashMap::new(); - properties.insert("Source".to_string(), "-- b.client.lua".to_string()); + properties.insert("Source".to_string(), RbxValue::String { value: "-- b.client.lua".to_string() }); assert_eq!(instance.properties, properties); assert_eq!(instance.parent, Some(partition_id)); @@ -313,7 +314,7 @@ fn one_partition() { server_id = Some(*id); let mut properties = HashMap::new(); - properties.insert("Source".to_string(), "-- a.server.lua".to_string()); + properties.insert("Source".to_string(), RbxValue::String { value: "-- a.server.lua".to_string() }); assert_eq!(instance.properties, properties); assert_eq!(instance.parent, Some(partition_id)); @@ -331,7 +332,7 @@ fn one_partition() { new_id = Some(*id); let mut properties = HashMap::new(); - properties.insert("Source".to_string(), "-- c.client.lua".to_string()); + properties.insert("Source".to_string(), RbxValue::String { value: "-- c.client.lua".to_string() }); assert_eq!(instance.properties, properties); assert_eq!(instance.parent, Some(partition_id)); From 20c9c89b27d86e7338aa54afc05428cd49b0db46 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 24 Jun 2018 20:26:58 -0700 Subject: [PATCH 0176/1504] RbxTree robustness * delete_instance is no longer O(n) * renamed get_instance to get_instance_and_descendants, which is more accurate --- server/src/rbx.rs | 21 +++++++++++++-------- server/src/web.rs | 2 +- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/server/src/rbx.rs b/server/src/rbx.rs index d2aa7b50..f4c2a9a4 100644 --- a/server/src/rbx.rs +++ b/server/src/rbx.rs @@ -68,13 +68,18 @@ impl RbxTree { let mut ids_to_visit = vec![id]; let mut ids_deleted = Vec::new(); - for instance in self.instances.values_mut() { - match instance.children.iter().position(|&v| v == id) { - Some(index) => { - instance.children.remove(index); - }, - None => {}, - } + // We only need to explicitly remove a child from the first instance we + // delete, since all others will descend from this instance. + let parent_id = match self.instances.get(&id) { + Some(instance) => instance.parent, + None => None, + }; + + if let Some(parent_id) = parent_id { + let mut parent = self.instances.get_mut(&parent_id).unwrap(); + let index = parent.children.iter().position(|&v| v == id).unwrap(); + + parent.children.remove(index); } loop { @@ -95,7 +100,7 @@ impl RbxTree { ids_deleted } - pub fn get_instance<'a, 'b, T>(&'a self, id: Id, output: &'b mut HashMap) + pub fn get_instance_and_descendants<'a, 'b, T>(&'a self, id: Id, output: &'b mut HashMap) where T: From<&'a RbxInstance> { let mut ids_to_visit = vec![id]; diff --git a/server/src/web.rs b/server/src/web.rs index 7c81641a..2a5fefd4 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -187,7 +187,7 @@ impl Server { let mut instances = HashMap::new(); for requested_id in &requested_ids { - rbx_session.tree.get_instance(*requested_id, &mut instances); + rbx_session.tree.get_instance_and_descendants(*requested_id, &mut instances); } Response::json(&ReadResponse { From 43b27831eb1f87660d3eb5668281bb111b7c4249 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 24 Jun 2018 20:29:51 -0700 Subject: [PATCH 0177/1504] Update Lemur and TestEZ --- plugin/modules/lemur | 2 +- plugin/modules/testez | 2 +- plugin/spec.lua | 36 +++--------------------------------- 3 files changed, 5 insertions(+), 35 deletions(-) diff --git a/plugin/modules/lemur b/plugin/modules/lemur index 852c71b8..bdbdc3bf 160000 --- a/plugin/modules/lemur +++ b/plugin/modules/lemur @@ -1 +1 @@ -Subproject commit 852c71b897ff346f6a76796a418b9da4255d04b1 +Subproject commit bdbdc3bf43515daba2578eb0bb49c4e300588a4c diff --git a/plugin/modules/testez b/plugin/modules/testez index 442b7192..5acef965 160000 --- a/plugin/modules/testez +++ b/plugin/modules/testez @@ -1 +1 @@ -Subproject commit 442b71926d4e9bd9933bbdd87d95679062723dad +Subproject commit 5acef9659a177d446800e986b60e4613a35eb418 diff --git a/plugin/spec.lua b/plugin/spec.lua index 02325bdd..57750e93 100644 --- a/plugin/spec.lua +++ b/plugin/spec.lua @@ -14,34 +14,6 @@ package.path = package.path .. ";?/init.lua" -- If this fails, make sure you've run `lua bin/install-dependencies.lua` first! local lemur = require("modules.lemur") ---[[ - Collapses ModuleScripts named 'init' into their parent folders. - - This is the same result as the collapsing mechanism from Rojo. -]] -local function collapse(root) - local init = root:FindFirstChild("init") - if init then - init.Name = root.Name - init.Parent = root.Parent - - for _, child in ipairs(root:GetChildren()) do - child.Parent = init - end - - root:Destroy() - root = init - end - - for _, child in ipairs(root:GetChildren()) do - if child:IsA("Folder") then - collapse(child) - end - end - - return root -end - -- Create a virtual Roblox tree local habitat = lemur.Habitat.new() @@ -51,13 +23,11 @@ Root.Name = "Root" -- Load all of the modules specified above for _, module in ipairs(LOAD_MODULES) do - local container = lemur.Instance.new("Folder", Root) + local container = habitat:loadFromFs(module[1]) container.Name = module[2] - habitat:loadFromFs(module[1], container) + container.Parent = Root end -collapse(Root) - -- Load TestEZ and run our tests local TestEZ = habitat:require(Root.TestEZ) @@ -66,4 +36,4 @@ local results = TestEZ.TestBootstrap:run(Root.Plugin, TestEZ.Reporters.TextRepor -- Did something go wrong? if results.failureCount > 0 then os.exit(1) -end +end \ No newline at end of file From d10b6d324eca2c0b6aec425e7f5f493fbaeae59b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 24 Jun 2018 21:06:00 -0700 Subject: [PATCH 0178/1504] Add roblox_studio module for locating and interacting with install --- server/src/lib.rs | 1 + server/src/roblox_studio.rs | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 server/src/roblox_studio.rs diff --git a/server/src/lib.rs b/server/src/lib.rs index 5ea4b8f0..2f806548 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -24,3 +24,4 @@ pub mod session; pub mod vfs_session; pub mod web; pub mod web_util; +pub mod roblox_studio; diff --git a/server/src/roblox_studio.rs b/server/src/roblox_studio.rs new file mode 100644 index 00000000..c55311b3 --- /dev/null +++ b/server/src/roblox_studio.rs @@ -0,0 +1,27 @@ +//! Interactions with Roblox Studio's installation, including its location and +//! mechanisms like PluginSettings. + +use std::path::PathBuf; +use std::env; + +static ROJO_PLUGIN_ID: &'static str = "1211549683"; + +#[cfg(target_os = "windows")] +pub fn install_location() -> Option { + let local_app_data = env::var("LocalAppData").ok()?; + let mut location = PathBuf::from(local_app_data); + + location.push("Roblox"); + + Some(location) +} + +#[cfg(target_os = "macos")] +pub fn install_location() -> Option { + unimplemented!(); +} + +#[cfg(not(any(target_os = "windows", target_os = "macos")))] +pub fn install_location() -> Option { + None +} \ No newline at end of file From 4088bb47f0f4dd3fdbe5a60b602ee5f24ed89955 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 24 Jun 2018 23:54:40 -0700 Subject: [PATCH 0179/1504] Add comment about roblox_studio::install_location --- server/src/roblox_studio.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/roblox_studio.rs b/server/src/roblox_studio.rs index c55311b3..8da69b95 100644 --- a/server/src/roblox_studio.rs +++ b/server/src/roblox_studio.rs @@ -23,5 +23,6 @@ pub fn install_location() -> Option { #[cfg(not(any(target_os = "windows", target_os = "macos")))] pub fn install_location() -> Option { + // Roblox Studio doesn't install on any other platforms! None } \ No newline at end of file From 4138bb7ee1bd14637a95c49f9189b1eb09e29e9b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 24 Jun 2018 23:55:13 -0700 Subject: [PATCH 0180/1504] install_location -> get_install_location --- server/src/roblox_studio.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/roblox_studio.rs b/server/src/roblox_studio.rs index 8da69b95..6f461285 100644 --- a/server/src/roblox_studio.rs +++ b/server/src/roblox_studio.rs @@ -7,7 +7,7 @@ use std::env; static ROJO_PLUGIN_ID: &'static str = "1211549683"; #[cfg(target_os = "windows")] -pub fn install_location() -> Option { +pub fn get_install_location() -> Option { let local_app_data = env::var("LocalAppData").ok()?; let mut location = PathBuf::from(local_app_data); @@ -17,12 +17,12 @@ pub fn install_location() -> Option { } #[cfg(target_os = "macos")] -pub fn install_location() -> Option { +pub fn get_install_location() -> Option { unimplemented!(); } #[cfg(not(any(target_os = "windows", target_os = "macos")))] -pub fn install_location() -> Option { +pub fn get_install_location() -> Option { // Roblox Studio doesn't install on any other platforms! None } \ No newline at end of file From 5a5da3240fbf4afc5f44aad8080616eea4598282 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 25 Jun 2018 00:53:21 -0700 Subject: [PATCH 0181/1504] Add plugin bundling, sourced from target/plugin.rbxm --- server/Cargo.toml | 4 +++ server/src/commands/serve.rs | 3 +++ server/src/roblox_studio.rs | 52 +++++++++++++++++++++++++++++++++++- 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/server/Cargo.toml b/server/Cargo.toml index e38cedd9..69c9bfe1 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -14,6 +14,10 @@ path = "src/lib.rs" name = "rojo" path = "src/bin.rs" +[features] +default = [] +bundle-plugin = [] + [dependencies] clap = "2.27" rouille = "2.1" diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 497c4ccb..b70261fd 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -7,6 +7,7 @@ use rand; use project::Project; use web::{self, WebConfig}; use session::Session; +use roblox_studio; pub fn serve(project_dir: &PathBuf, override_port: Option) { let server_id = rand::random::(); @@ -26,6 +27,8 @@ pub fn serve(project_dir: &PathBuf, override_port: Option) { println!("Using project {:#?}", project); + roblox_studio::install_bundled_plugin(); + let mut session = Session::new(project.clone()); session.start(); diff --git a/server/src/roblox_studio.rs b/server/src/roblox_studio.rs index 6f461285..a79cb059 100644 --- a/server/src/roblox_studio.rs +++ b/server/src/roblox_studio.rs @@ -1,10 +1,19 @@ //! Interactions with Roblox Studio's installation, including its location and //! mechanisms like PluginSettings. +#![allow(dead_code)] + use std::path::PathBuf; use std::env; -static ROJO_PLUGIN_ID: &'static str = "1211549683"; +#[cfg(all(not(debug_assertions), not(feature = "bundle-plugin")))] +compile_error!("`bundle-plugin` feature must be set for release builds."); + +#[cfg(feature = "bundle-plugin")] +static PLUGIN_RBXM: &'static [u8] = include_bytes!("../target/plugin.rbxm"); + +const ROJO_HOTSWAP_PLUGIN_ID: &'static str = "0"; +const ROJO_RELEASE_PLUGIN_ID: &'static str = "1997686364"; #[cfg(target_os = "windows")] pub fn get_install_location() -> Option { @@ -25,4 +34,45 @@ pub fn get_install_location() -> Option { pub fn get_install_location() -> Option { // Roblox Studio doesn't install on any other platforms! None +} + +#[cfg(feature = "bundle-plugin")] +pub fn get_plugin_location() -> Option { + let mut location = get_install_location()?; + + location.push("InstalledPlugins"); + location.push(ROJO_RELEASE_PLUGIN_ID); + + Some(location) +} + +#[cfg(not(feature = "bundle-plugin"))] +pub fn get_plugin_location() -> Option { + let mut location = get_install_location()?; + + location.push("InstalledPlugins"); + location.push(ROJO_HOTSWAP_PLUGIN_ID); + + Some(location) +} + +#[cfg(feature = "bundle-plugin")] +pub fn install_bundled_plugin() -> Option<()> { + use std::fs::create_dir_all; + + println!("Installing plugin..."); + + // TODO: Check error of this value; the only one we actually want to ignore + // is ErrorKind::AlreadyExists probably. + let _ = create_dir_all(get_plugin_location()?); + + // TODO: Copy PLUGIN_RBXM to plugin_location/Plugin.rbxm + // TODO: Update PluginMetadata.json + + Some(()) +} + +#[cfg(not(feature = "bundle-plugin"))] +pub fn install_bundled_plugin() { + println!("Skipping plugin installation, bundle-plugin not set."); } \ No newline at end of file From bece337d797e16542a8645394c3560bf14886966 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 25 Jun 2018 17:58:30 -0700 Subject: [PATCH 0182/1504] Implement rudimentary reifer against new APIs --- plugin/src/ApiContext.lua | 14 ++++---- plugin/src/HttpError.lua | 2 +- plugin/src/Session.lua | 73 ++++++++++++++++++++++----------------- 3 files changed, 51 insertions(+), 38 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 999f8cb7..5bfcc6b8 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -29,6 +29,7 @@ function ApiContext.new(url, onMessage) serverId = nil, connected = false, messageCursor = -1, + partitionRoutes = nil, } setmetatable(context, ApiContext) @@ -37,7 +38,7 @@ function ApiContext.new(url, onMessage) end function ApiContext:connect() - return Http.get(self.url) + return Http.get(self.url .. "/api/rojo") :andThen(function(response) local body = response:json() @@ -59,6 +60,7 @@ function ApiContext:connect() self.serverId = body.serverId self.connected = true + self.partitionRoutes = body.partitions end) end @@ -67,17 +69,17 @@ function ApiContext:readAll() return Promise.reject() end - return Http.get(self.url .. "/read_all") + return Http.get(self.url .. "/api/read_all") :andThen(function(response) local body = response:json() if body.serverId ~= self.serverId then - return Promise.reject("server changed ID") + return Promise.reject("Server changed ID") end self.messageCursor = body.messageCursor - return body.instances + return body end, function(err) self.connected = false @@ -90,12 +92,12 @@ function ApiContext:retrieveMessages() return Promise.reject() end - return Http.get(self.url .. "/subscribe/" .. self.messageCursor) + return Http.get(self.url .. "/api/subscribe/" .. self.messageCursor) :andThen(function(response) local body = response:json() if body.serverId ~= self.serverId then - return Promise.reject("server changed ID") + return Promise.reject("Server changed ID") end for _, message in ipairs(body.messages) do diff --git a/plugin/src/HttpError.lua b/plugin/src/HttpError.lua index ca624037..ed611356 100644 --- a/plugin/src/HttpError.lua +++ b/plugin/src/HttpError.lua @@ -8,7 +8,7 @@ HttpError.Error = { }, ConnectFailed = { message = "Rojo plugin couldn't connect to the Rojo server.\n" .. - "Make sure the server is running -- use 'Rojo serve' to run it!", + "Make sure the server is running -- use 'rojo serve' to run it!", }, Timeout = { message = "Rojo timed out during a request.", diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 1d0e6d30..e209f3f9 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -12,45 +12,56 @@ function Session.new() setmetatable(self, Session) -- TODO: Rewrite all instance tracking logic and implement a real reconciler - local created = {} - created["0"] = game:GetService("ReplicatedFirst") + local instancesById = {} + + local function createFoldersUntil(location, route) + for i = 1, #route - 1 do + local piece = route[i] + + local child = location:FindFirstChild(piece) + + if child == nil then + child = Instance.new("Folder") + child.Name = piece + child.Parent = location + end + + location = child + end + + return location + end + + local function reify(instancesById, id) + local object = instancesById[tostring(id)] + local instance = Instance.new(object.className) + instance.Name = object.name + + for key, property in pairs(object.properties) do + instance[key] = property.value + end + + for _, childId in ipairs(object.children) do + reify(instancesById, childId).Parent = instance + end + + return instance + end local api local function readAll() print("Reading all...") return api:readAll() - :andThen(function(instances) - local visited = {} - for id, instance in pairs(instances) do - visited[id] = true - if id ~= "0" then - local existing = created[id] - if existing ~= nil then - pcall(existing.Destroy, existing) - end + :andThen(function(response) + for partitionName, partitionRoute in pairs(api.partitionRoutes) do + local parent = createFoldersUntil(game, partitionRoute) - local real = Instance.new(instance.className) - real.Name = instance.name + local rootInstanceId = response.partitionInstances[partitionName] - for key, value in pairs(instance.properties) do - real[key] = value - end + print("Root for", partitionName, "is", rootInstanceId) - created[id] = real - end - end - - for id, instance in pairs(instances) do - if id ~= "0" then - created[id].Parent = created[tostring(instance.parent)] - end - end - - for id, object in pairs(created) do - if not visited[id] then - object:Destroy() - end + reify(response.instances, rootInstanceId).Parent = parent end end) end @@ -58,7 +69,7 @@ function Session.new() api = ApiContext.new(REMOTE_URL, function(message) if message.type == "InstanceChanged" then print("Instance", message.id, "changed!") - readAll() + -- readAll() else warn("Unknown message type " .. message.type) end From 77d0865d58613aa655f5b76929b6c7f338fe1e7f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 25 Jun 2018 18:22:36 -0700 Subject: [PATCH 0183/1504] Remove redundnant comment and unused variable --- plugin/src/Session.lua | 3 --- 1 file changed, 3 deletions(-) diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index e209f3f9..47d8d5d0 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -11,9 +11,6 @@ function Session.new() setmetatable(self, Session) - -- TODO: Rewrite all instance tracking logic and implement a real reconciler - local instancesById = {} - local function createFoldersUntil(location, route) for i = 1, #route - 1 do local piece = route[i] From 8a2699408426e49d791347520b4b01ec81ef7694 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 25 Jun 2018 22:10:03 -0700 Subject: [PATCH 0184/1504] Simplify plugin installation by using Plugins instead of InstalledPlugins --- server/src/commands/serve.rs | 2 +- server/src/roblox_studio.rs | 34 +++++++++------------------------- 2 files changed, 10 insertions(+), 26 deletions(-) diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index b70261fd..243ee335 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -27,7 +27,7 @@ pub fn serve(project_dir: &PathBuf, override_port: Option) { println!("Using project {:#?}", project); - roblox_studio::install_bundled_plugin(); + roblox_studio::install_bundled_plugin().unwrap(); let mut session = Session::new(project.clone()); session.start(); diff --git a/server/src/roblox_studio.rs b/server/src/roblox_studio.rs index a79cb059..ee90a0b5 100644 --- a/server/src/roblox_studio.rs +++ b/server/src/roblox_studio.rs @@ -10,10 +10,7 @@ use std::env; compile_error!("`bundle-plugin` feature must be set for release builds."); #[cfg(feature = "bundle-plugin")] -static PLUGIN_RBXM: &'static [u8] = include_bytes!("../target/plugin.rbxm"); - -const ROJO_HOTSWAP_PLUGIN_ID: &'static str = "0"; -const ROJO_RELEASE_PLUGIN_ID: &'static str = "1997686364"; +static PLUGIN_RBXM: &'static [u8] = include_bytes!("../target/plugin.rbxmx"); #[cfg(target_os = "windows")] pub fn get_install_location() -> Option { @@ -36,43 +33,30 @@ pub fn get_install_location() -> Option { None } -#[cfg(feature = "bundle-plugin")] pub fn get_plugin_location() -> Option { let mut location = get_install_location()?; - location.push("InstalledPlugins"); - location.push(ROJO_RELEASE_PLUGIN_ID); - - Some(location) -} - -#[cfg(not(feature = "bundle-plugin"))] -pub fn get_plugin_location() -> Option { - let mut location = get_install_location()?; - - location.push("InstalledPlugins"); - location.push(ROJO_HOTSWAP_PLUGIN_ID); + location.push("Plugins/Rojo.rbxmx"); Some(location) } #[cfg(feature = "bundle-plugin")] pub fn install_bundled_plugin() -> Option<()> { - use std::fs::create_dir_all; + use std::fs::File; + use std::io::Write; println!("Installing plugin..."); - // TODO: Check error of this value; the only one we actually want to ignore - // is ErrorKind::AlreadyExists probably. - let _ = create_dir_all(get_plugin_location()?); - - // TODO: Copy PLUGIN_RBXM to plugin_location/Plugin.rbxm - // TODO: Update PluginMetadata.json + let mut file = File::create(get_plugin_location()?).ok()?; + file.write_all(PLUGIN_RBXM).ok()?; Some(()) } #[cfg(not(feature = "bundle-plugin"))] -pub fn install_bundled_plugin() { +pub fn install_bundled_plugin() -> Option<()> { println!("Skipping plugin installation, bundle-plugin not set."); + + Some(()) } \ No newline at end of file From bfe8dcd2246bf8b0cca9c1f215bcf5cc05eb14ff Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 2 Jul 2018 18:34:12 -0700 Subject: [PATCH 0185/1504] Try out some nonsense with services being special-ish cased --- server/src/rbx_session.rs | 58 ++++++++++++++++--- .../test-projects/partition-to-file/foo.lua | 0 .../test-projects/partition-to-file/rojo.json | 10 ++++ server/tests/web.rs | 5 +- 4 files changed, 64 insertions(+), 9 deletions(-) create mode 100644 server/test-projects/partition-to-file/foo.lua create mode 100644 server/test-projects/partition-to-file/rojo.json diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 198fd52d..74514678 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -9,6 +9,43 @@ use project::Project; use rbx::{RbxInstance, RbxTree, RbxValue}; use vfs_session::{VfsSession, FileItem, FileChange}; +static SERVICES: &'static [&'static str] = &[ + "Chat", + "Lighting", + "LocalizationService", + "Players", + "ReplicatedFirst", + "ReplicatedStorage", + "ServerScriptService", + "ServerStorage", + "SoundService", + "StarterGui", + "StarterPack", + "StarterPlayer", + "TestService", + "Workspace", +]; + +fn get_partition_target_class_name(target: &[String]) -> &'static str { + match target.len() { + 1 => { + let target_name = &target[0]; + + for &service in SERVICES { + if service == target_name { + return service; + } + } + + "Folder" + }, + 2 => { + "Folder" + }, + _ => "Folder", + } +} + // TODO: Rethink data structure and insertion/update behavior. Maybe break some // pieces off into a new object? fn file_to_instances( @@ -32,10 +69,13 @@ fn file_to_instances( // This is placeholder logic; this whole function is! let (class_name, property_key, name) = { - let file_name = route.route.last().unwrap_or(&route.partition); + let file_name = match route.route.last() { + Some(v) => v.to_string(), + None => partition.path.file_name().unwrap().to_str().unwrap().to_string() + }; - fn strip_suffix<'a>(source: &'a str, suffix: &'static str) -> &'a str { - &source[..source.len() - suffix.len()] + fn strip_suffix<'a>(source: &'a str, suffix: &'static str) -> String { + source[..source.len() - suffix.len()].to_string() } if file_name.ends_with(".client.lua") { @@ -46,7 +86,7 @@ fn file_to_instances( ("ModuleScript", "Source", strip_suffix(&file_name, ".lua")) } else { // TODO: Error/warn/skip instead of falling back - ("StringValue", "Value", file_name.as_str()) + ("StringValue", "Value", file_name) } }; @@ -54,7 +94,7 @@ fn file_to_instances( properties.insert(property_key.to_string(), RbxValue::String { value: contents.clone() }); tree.insert_instance(primary_id, RbxInstance { - name: name.to_string(), + name, class_name: class_name.to_string(), properties, children: Vec::new(), @@ -90,9 +130,13 @@ fn file_to_instances( } } + let class_name = get_partition_target_class_name(&route.route).to_string(); + + let name = route.name(partition); + tree.insert_instance(primary_id, RbxInstance { - name: route.name(partition).to_string(), - class_name: "Folder".to_string(), + name, + class_name, properties: HashMap::new(), children: child_ids, parent: parent_id, diff --git a/server/test-projects/partition-to-file/foo.lua b/server/test-projects/partition-to-file/foo.lua new file mode 100644 index 00000000..e69de29b diff --git a/server/test-projects/partition-to-file/rojo.json b/server/test-projects/partition-to-file/rojo.json new file mode 100644 index 00000000..5592e29f --- /dev/null +++ b/server/test-projects/partition-to-file/rojo.json @@ -0,0 +1,10 @@ +{ + "name": "partition-to-file", + "servePort": 23456, + "partitions": { + "lib": { + "path": "foo.lua", + "target": "ReplicatedStorage.foo" + } + } +} \ No newline at end of file diff --git a/server/tests/web.rs b/server/tests/web.rs index f37295a4..733382be 100644 --- a/server/tests/web.rs +++ b/server/tests/web.rs @@ -194,7 +194,9 @@ fn one_partition() { assert_eq!(single_instance, &Cow::Borrowed(instance)); }, - _ => {}, + _ => { + panic!("Unexpected instance named {} of class {}", instance.name, instance.class_name); + }, } } @@ -388,5 +390,4 @@ fn one_partition() { } // TODO: Test to change existing instance - // TODO: Copy each project into temp dir before using them } \ No newline at end of file From ae8098b80a7fa4ccd0f078e227274d81681a8559 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Jul 2018 16:01:34 -0700 Subject: [PATCH 0186/1504] Do a bit of tinkering with instance names relative to files and partitions --- server/src/file_route.rs | 99 ++++++++++++++++--- server/src/rbx_session.rs | 42 +++++++- .../test-projects/partition-to-file/foo.lua | 1 + .../test-projects/partition-to-file/rojo.json | 2 +- server/tests/web.rs | 60 ++++++++++- 5 files changed, 186 insertions(+), 18 deletions(-) diff --git a/server/src/file_route.rs b/server/src/file_route.rs index ba972bb7..a691034e 100644 --- a/server/src/file_route.rs +++ b/server/src/file_route.rs @@ -13,6 +13,7 @@ pub struct FileRoute { impl FileRoute { pub fn from_path(path: &Path, partition: &Partition) -> Option { assert!(path.is_absolute()); + assert!(path.starts_with(&partition.path)); let relative_path = path.strip_prefix(&partition.path).ok()?; let mut route = Vec::new(); @@ -70,20 +71,96 @@ impl FileRoute { result } - /// This function is totally wrong and should be handled by middleware, heh. - pub fn name(&self, partition: &Partition) -> String { // I guess?? + pub fn file_name(&self, partition: &Partition) -> String { if self.route.len() == 0 { - // This FileRoute refers to the partition itself - - if partition.target.len() == 0 { - // We're targeting the game! - "game".to_string() - } else { - partition.target.last().unwrap().clone() - } + partition.path.file_name().unwrap().to_str().unwrap().to_string() } else { - // This FileRoute refers to an item in a partition self.route.last().unwrap().clone() } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[cfg(windows)] + const ROOT_PATH: &'static str = "C:\\"; + + #[cfg(not(windows))] + const ROOT_PATH: &'static str = "/"; + + #[test] + fn from_path_empty() { + let path = Path::new(ROOT_PATH).join("a/b/c"); + + let partition = Partition { + name: "foo".to_string(), + path: path.clone(), + target: vec![], + }; + + let route = FileRoute::from_path(&path, &partition); + + assert_eq!(route, Some(FileRoute { + partition: "foo".to_string(), + route: vec![], + })); + } + + #[test] + fn from_path_non_empty() { + let partition_path = Path::new(ROOT_PATH).join("a/b/c"); + + let inside_path = partition_path.join("d"); + + let partition = Partition { + name: "bar".to_string(), + path: partition_path, + target: vec![], + }; + + let route = FileRoute::from_path(&inside_path, &partition); + + assert_eq!(route, Some(FileRoute { + partition: "bar".to_string(), + route: vec!["d".to_string()], + })); + } + + #[test] + fn file_name_empty_route() { + let partition_path = Path::new(ROOT_PATH).join("a/b/c"); + + let partition = Partition { + name: "bar".to_string(), + path: partition_path, + target: vec![], + }; + + let route = FileRoute { + partition: "bar".to_string(), + route: vec![], + }; + + assert_eq!(route.file_name(&partition), "c"); + } + + #[test] + fn file_name_non_empty_route() { + let partition_path = Path::new(ROOT_PATH).join("a/b/c"); + + let partition = Partition { + name: "bar".to_string(), + path: partition_path, + target: vec![], + }; + + let route = FileRoute { + partition: "bar".to_string(), + route: vec!["foo".to_string(), "hello.lua".to_string()], + }; + + assert_eq!(route.file_name(&partition), "hello.lua"); + } +} \ No newline at end of file diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 74514678..0abd25e8 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -74,19 +74,47 @@ fn file_to_instances( None => partition.path.file_name().unwrap().to_str().unwrap().to_string() }; + let use_partition_name = route.route.len() == 0; + + let partition_name = partition.target.last().unwrap(); + fn strip_suffix<'a>(source: &'a str, suffix: &'static str) -> String { source[..source.len() - suffix.len()].to_string() } if file_name.ends_with(".client.lua") { - ("LocalScript", "Source", strip_suffix(&file_name, ".client.lua")) + let name = if use_partition_name { + partition_name.clone() + } else { + strip_suffix(&file_name, ".client.lua") + }; + + ("LocalScript", "Source", name) } else if file_name.ends_with(".server.lua") { - ("Script", "Source", strip_suffix(&file_name, ".server.lua")) + let name = if use_partition_name { + partition_name.clone() + } else { + strip_suffix(&file_name, ".server.lua") + }; + + ("Script", "Source", name) } else if file_name.ends_with(".lua") { - ("ModuleScript", "Source", strip_suffix(&file_name, ".lua")) + let name = if use_partition_name { + partition_name.clone() + } else { + strip_suffix(&file_name, ".lua") + }; + + ("ModuleScript", "Source", name) } else { + let name = if use_partition_name { + partition_name.clone() + } else { + file_name + }; + // TODO: Error/warn/skip instead of falling back - ("StringValue", "Value", file_name) + ("StringValue", "Value", name) } }; @@ -132,7 +160,11 @@ fn file_to_instances( let class_name = get_partition_target_class_name(&route.route).to_string(); - let name = route.name(partition); + let name = if route.route.len() == 0 { + partition.target.last().unwrap().clone() + } else { + route.file_name(partition) + }; tree.insert_instance(primary_id, RbxInstance { name, diff --git a/server/test-projects/partition-to-file/foo.lua b/server/test-projects/partition-to-file/foo.lua index e69de29b..4c3ac65c 100644 --- a/server/test-projects/partition-to-file/foo.lua +++ b/server/test-projects/partition-to-file/foo.lua @@ -0,0 +1 @@ +-- foo.lua \ No newline at end of file diff --git a/server/test-projects/partition-to-file/rojo.json b/server/test-projects/partition-to-file/rojo.json index 5592e29f..0e7367f1 100644 --- a/server/test-projects/partition-to-file/rojo.json +++ b/server/test-projects/partition-to-file/rojo.json @@ -4,7 +4,7 @@ "partitions": { "lib": { "path": "foo.lua", - "target": "ReplicatedStorage.foo" + "target": "ReplicatedStorage.bar" } } } \ No newline at end of file diff --git a/server/tests/web.rs b/server/tests/web.rs index 733382be..187f2cff 100644 --- a/server/tests/web.rs +++ b/server/tests/web.rs @@ -390,4 +390,62 @@ fn one_partition() { } // TODO: Test to change existing instance -} \ No newline at end of file +} + +#[test] +fn partition_to_file() { + let original_project_path = { + let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + path.push("test-projects/partition-to-file"); + path + }; + + let project_tempdir = tempfile::tempdir().unwrap(); + let project_path = project_tempdir.path(); + + copy_recursive(&original_project_path, &project_path).unwrap(); + + let project = Project::load(&project_path).unwrap(); + let mut session = Session::new(project.clone()); + session.start(); + + let web_config = WebConfig::from_session(0, project.serve_port, &session); + let server = Server::new(web_config); + + { + let body = server.get_string("/api/rojo"); + let response = serde_json::from_str::(&body).unwrap(); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.protocol_version, 2); + assert_eq!(response.partitions.len(), 1); + } + + { + let body = server.get_string("/api/read_all"); + let response = serde_json::from_str::(&body).unwrap(); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.message_cursor, -1); + assert_eq!(response.instances.len(), 1); + + let instance = response.instances.values().next().unwrap(); + + assert_eq!(instance.name, "bar"); + assert_eq!(instance.class_name, "ModuleScript"); + assert_eq!(instance.properties.get("Source"), Some(&RbxValue::String { value: "-- foo.lua".to_string() })); + assert_eq!(instance.children.len(), 0); + assert_eq!(instance.parent, None); + + let body = server.get_string("/api/read/0"); + let response = serde_json::from_str::(&body).unwrap(); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.message_cursor, -1); + assert_eq!(response.instances.len(), 1); + + let single_instance = response.instances.values().next().unwrap(); + + assert_eq!(&Cow::Borrowed(instance), single_instance); + } +} From 2bd64db8d95cc09582d39ecf4d74cdbf911bcf4b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Jul 2018 16:32:45 -0700 Subject: [PATCH 0187/1504] Add test for modifying file a partition is pointing at directly --- server/tests/web.rs | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/server/tests/web.rs b/server/tests/web.rs index 187f2cff..516a0bd8 100644 --- a/server/tests/web.rs +++ b/server/tests/web.rs @@ -448,4 +448,38 @@ fn partition_to_file() { assert_eq!(&Cow::Borrowed(instance), single_instance); } + + let file_path = project_path.join("foo.lua"); + + { + let mut file = File::create(file_path).unwrap(); + file.write_all(b"-- modified").unwrap(); + } + + { + // Block until Rojo detects our file being modified + let body = server.get_string("/api/subscribe/-1"); + let response = serde_json::from_str::(&body).unwrap(); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.message_cursor, 0); + assert_eq!(response.messages.len(), 1); + } + + { + let body = server.get_string("/api/read/0"); + let response = serde_json::from_str::(&body).unwrap(); + + assert_eq!(response.server_id, "0"); + assert_eq!(response.message_cursor, 0); + assert_eq!(response.instances.len(), 1); + + let instance = response.instances.values().next().unwrap(); + + assert_eq!(instance.name, "bar"); + assert_eq!(instance.class_name, "ModuleScript"); + assert_eq!(instance.properties.get("Source"), Some(&RbxValue::String { value: "-- modified".to_string() })); + assert_eq!(instance.children.len(), 0); + assert_eq!(instance.parent, None); + } } From f3e7e5467579798195073d3de234203e1641d3de Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Jul 2018 20:24:57 -0700 Subject: [PATCH 0188/1504] Add useless comment --- server/src/rbx.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/rbx.rs b/server/src/rbx.rs index f4c2a9a4..e3437f3c 100644 --- a/server/src/rbx.rs +++ b/server/src/rbx.rs @@ -26,6 +26,7 @@ pub struct RbxInstance { /// All of the children of this instance. Order is relevant to preserve! pub children: Vec, + /// The parent of the instance, if there is one. pub parent: Option, } From 1db06194c7db191f521d17f82199e4ab67f6a471 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 13 Aug 2018 15:24:35 -0700 Subject: [PATCH 0189/1504] Fix module layout to make more sense --- plugin/rojo.json | 2 +- plugin/spec.lua | 5 +++-- plugin/src/ApiContext.lua | 2 +- plugin/src/Http.lua | 2 +- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/plugin/rojo.json b/plugin/rojo.json index e184e52f..17f5548f 100644 --- a/plugin/rojo.json +++ b/plugin/rojo.json @@ -4,7 +4,7 @@ "partitions": { "plugin": { "path": "src", - "target": "ReplicatedStorage.Rojo.plugin" + "target": "ReplicatedStorage.Rojo.modules.Plugin" }, "modules/roact": { "path": "modules/roact/lib", diff --git a/plugin/spec.lua b/plugin/spec.lua index 57750e93..102093f1 100644 --- a/plugin/spec.lua +++ b/plugin/spec.lua @@ -4,7 +4,8 @@ -- If you add any dependencies, add them to this table so they'll be loaded! local LOAD_MODULES = { - {"src", "Plugin"}, + {"src", "plugin"}, + {"modules/promise/lib", "Promise"}, {"modules/testez/lib", "TestEZ"}, } @@ -31,7 +32,7 @@ end -- Load TestEZ and run our tests local TestEZ = habitat:require(Root.TestEZ) -local results = TestEZ.TestBootstrap:run(Root.Plugin, TestEZ.Reporters.TextReporter) +local results = TestEZ.TestBootstrap:run(Root.plugin, TestEZ.Reporters.TextReporter) -- Did something go wrong? if results.failureCount > 0 then diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 5bfcc6b8..d8d301e1 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -1,4 +1,4 @@ -local Promise = require(script.Parent.Parent.modules.Promise) +local Promise = require(script.Parent.Parent.Promise) local Config = require(script.Parent.Config) local Version = require(script.Parent.Version) diff --git a/plugin/src/Http.lua b/plugin/src/Http.lua index 19383b7e..d6dd9cdb 100644 --- a/plugin/src/Http.lua +++ b/plugin/src/Http.lua @@ -2,7 +2,7 @@ local HttpService = game:GetService("HttpService") local HTTP_DEBUG = false -local Promise = require(script.Parent.Parent.modules.Promise) +local Promise = require(script.Parent.Parent.Promise) local HttpError = require(script.Parent.HttpError) local HttpResponse = require(script.Parent.HttpResponse) From ef0d1e7cecdf769a3fe1b36610305ba59eeea907 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 13 Aug 2018 15:31:36 -0700 Subject: [PATCH 0190/1504] Update to latest Lemur --- plugin/modules/lemur | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/modules/lemur b/plugin/modules/lemur index bdbdc3bf..7145587f 160000 --- a/plugin/modules/lemur +++ b/plugin/modules/lemur @@ -1 +1 @@ -Subproject commit bdbdc3bf43515daba2578eb0bb49c4e300588a4c +Subproject commit 7145587fa5c1382e4e67db137c3931e6823fa2b6 From c6982f70b4d5dbb81350b5586537e00cd93fb463 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 13 Aug 2018 15:35:04 -0700 Subject: [PATCH 0191/1504] Move test projects out of server folder --- server/tests/web.rs | 26 +++++++++---------- test-project/extra-script.lua | 0 test-project/rojo.json | 14 ---------- test-project/src/SomeTool/SomeTool.client.lua | 1 - test-project/src/SomeTool/init.model.json | 4 --- test-project/src/a/b.lua | 1 - test-project/src/bar.client.lua | 1 - test-project/src/foo.server.lua | 1 - test-project/src/hello.model.json | 20 -------------- test-project/src/meh/init.lua | 0 test-project/src/meh/x.lua | 1 - test-project/src/test.lua | 1 - .../empty/rojo.json | 0 .../one-partition/lib/a.lua | 0 .../one-partition/lib/a.server.lua | 0 .../one-partition/lib/b.client.lua | 0 .../one-partition/rojo.json | 0 .../partition-to-file/foo.lua | 0 .../partition-to-file/rojo.json | 0 19 files changed, 12 insertions(+), 58 deletions(-) delete mode 100644 test-project/extra-script.lua delete mode 100644 test-project/rojo.json delete mode 100644 test-project/src/SomeTool/SomeTool.client.lua delete mode 100644 test-project/src/SomeTool/init.model.json delete mode 100644 test-project/src/a/b.lua delete mode 100644 test-project/src/bar.client.lua delete mode 100644 test-project/src/foo.server.lua delete mode 100644 test-project/src/hello.model.json delete mode 100644 test-project/src/meh/init.lua delete mode 100644 test-project/src/meh/x.lua delete mode 100644 test-project/src/test.lua rename {server/test-projects => test-projects}/empty/rojo.json (100%) rename {server/test-projects => test-projects}/one-partition/lib/a.lua (100%) rename {server/test-projects => test-projects}/one-partition/lib/a.server.lua (100%) rename {server/test-projects => test-projects}/one-partition/lib/b.client.lua (100%) rename {server/test-projects => test-projects}/one-partition/rojo.json (100%) rename {server/test-projects => test-projects}/partition-to-file/foo.lua (100%) rename {server/test-projects => test-projects}/partition-to-file/rojo.json (100%) diff --git a/server/tests/web.rs b/server/tests/web.rs index 516a0bd8..103345b0 100644 --- a/server/tests/web.rs +++ b/server/tests/web.rs @@ -1,3 +1,5 @@ +#[macro_use] extern crate lazy_static; + extern crate rouille; extern crate serde_json; extern crate serde; @@ -22,13 +24,17 @@ use librojo::{ rbx::RbxValue, }; -#[test] -fn empty() { - let original_project_path = { +lazy_static! { + static ref TEST_PROJECTS_ROOT: PathBuf = { let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - path.push("test-projects/empty"); + path.push("../test-projects"); path }; +} + +#[test] +fn empty() { + let original_project_path = TEST_PROJECTS_ROOT.join("empty"); let project_tempdir = tempfile::tempdir().unwrap(); let project_path = project_tempdir.path(); @@ -72,11 +78,7 @@ fn empty() { #[test] fn one_partition() { - let original_project_path = { - let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - path.push("test-projects/one-partition"); - path - }; + let original_project_path = TEST_PROJECTS_ROOT.join("one-partition"); let project_tempdir = tempfile::tempdir().unwrap(); let project_path = project_tempdir.path(); @@ -394,11 +396,7 @@ fn one_partition() { #[test] fn partition_to_file() { - let original_project_path = { - let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - path.push("test-projects/partition-to-file"); - path - }; + let original_project_path = TEST_PROJECTS_ROOT.join("partition-to-file"); let project_tempdir = tempfile::tempdir().unwrap(); let project_path = project_tempdir.path(); diff --git a/test-project/extra-script.lua b/test-project/extra-script.lua deleted file mode 100644 index e69de29b..00000000 diff --git a/test-project/rojo.json b/test-project/rojo.json deleted file mode 100644 index 3d7187b6..00000000 --- a/test-project/rojo.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "test-project", - "servePort": 34872, - "partitions": { - "src": { - "path": "src", - "target": "ReplicatedFirst" - }, - "extra": { - "path": "extra-script.lua", - "target": "ReplicatedStorage.ExtraScript" - } - } -} \ No newline at end of file diff --git a/test-project/src/SomeTool/SomeTool.client.lua b/test-project/src/SomeTool/SomeTool.client.lua deleted file mode 100644 index 9c537fc8..00000000 --- a/test-project/src/SomeTool/SomeTool.client.lua +++ /dev/null @@ -1 +0,0 @@ -print("Hello, world, from my tool!") \ No newline at end of file diff --git a/test-project/src/SomeTool/init.model.json b/test-project/src/SomeTool/init.model.json deleted file mode 100644 index 500c7bca..00000000 --- a/test-project/src/SomeTool/init.model.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "Name": "SomeTool", - "ClassName": "Tool" -} \ No newline at end of file diff --git a/test-project/src/a/b.lua b/test-project/src/a/b.lua deleted file mode 100644 index de385843..00000000 --- a/test-project/src/a/b.lua +++ /dev/null @@ -1 +0,0 @@ -print("HEY!") \ No newline at end of file diff --git a/test-project/src/bar.client.lua b/test-project/src/bar.client.lua deleted file mode 100644 index 7999f9b4..00000000 --- a/test-project/src/bar.client.lua +++ /dev/null @@ -1 +0,0 @@ --- bar.client.lua \ No newline at end of file diff --git a/test-project/src/foo.server.lua b/test-project/src/foo.server.lua deleted file mode 100644 index 66d1b30d..00000000 --- a/test-project/src/foo.server.lua +++ /dev/null @@ -1 +0,0 @@ --- foo.server.lua \ No newline at end of file diff --git a/test-project/src/hello.model.json b/test-project/src/hello.model.json deleted file mode 100644 index c0afd96f..00000000 --- a/test-project/src/hello.model.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "Name": "hello", - "ClassName": "Model", - "Children": [ - { - "Name": "Some Part", - "ClassName": "Part" - }, - { - "Name": "Some StringValue", - "ClassName": "StringValue", - "Properties": { - "Value": { - "Type": "String", - "Value": "Hello, world!" - } - } - } - ] -} \ No newline at end of file diff --git a/test-project/src/meh/init.lua b/test-project/src/meh/init.lua deleted file mode 100644 index e69de29b..00000000 diff --git a/test-project/src/meh/x.lua b/test-project/src/meh/x.lua deleted file mode 100644 index 79743485..00000000 --- a/test-project/src/meh/x.lua +++ /dev/null @@ -1 +0,0 @@ --- meh/x.lua \ No newline at end of file diff --git a/test-project/src/test.lua b/test-project/src/test.lua deleted file mode 100644 index 42f8349e..00000000 --- a/test-project/src/test.lua +++ /dev/null @@ -1 +0,0 @@ --- test.lua \ No newline at end of file diff --git a/server/test-projects/empty/rojo.json b/test-projects/empty/rojo.json similarity index 100% rename from server/test-projects/empty/rojo.json rename to test-projects/empty/rojo.json diff --git a/server/test-projects/one-partition/lib/a.lua b/test-projects/one-partition/lib/a.lua similarity index 100% rename from server/test-projects/one-partition/lib/a.lua rename to test-projects/one-partition/lib/a.lua diff --git a/server/test-projects/one-partition/lib/a.server.lua b/test-projects/one-partition/lib/a.server.lua similarity index 100% rename from server/test-projects/one-partition/lib/a.server.lua rename to test-projects/one-partition/lib/a.server.lua diff --git a/server/test-projects/one-partition/lib/b.client.lua b/test-projects/one-partition/lib/b.client.lua similarity index 100% rename from server/test-projects/one-partition/lib/b.client.lua rename to test-projects/one-partition/lib/b.client.lua diff --git a/server/test-projects/one-partition/rojo.json b/test-projects/one-partition/rojo.json similarity index 100% rename from server/test-projects/one-partition/rojo.json rename to test-projects/one-partition/rojo.json diff --git a/server/test-projects/partition-to-file/foo.lua b/test-projects/partition-to-file/foo.lua similarity index 100% rename from server/test-projects/partition-to-file/foo.lua rename to test-projects/partition-to-file/foo.lua diff --git a/server/test-projects/partition-to-file/rojo.json b/test-projects/partition-to-file/rojo.json similarity index 100% rename from server/test-projects/partition-to-file/rojo.json rename to test-projects/partition-to-file/rojo.json From 5d608cb498b7676775fa2317dbb0e85437e98b1f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 14 Aug 2018 00:41:09 -0700 Subject: [PATCH 0192/1504] Remove old garbage code --- server/src/pathext.rs | 97 +------------------------------------------ 1 file changed, 2 insertions(+), 95 deletions(-) diff --git a/server/src/pathext.rs b/server/src/pathext.rs index 10f654d5..0b4c0f79 100644 --- a/server/src/pathext.rs +++ b/server/src/pathext.rs @@ -1,57 +1,5 @@ use std::env::current_dir; -use std::path::{Component, Path, PathBuf}; - -/// Converts a path to a 'route', used as the paths in Rojo. -pub fn path_to_route(root: A, value: B) -> Option> -where - A: AsRef, - B: AsRef, -{ - let root = root.as_ref(); - let value = value.as_ref(); - - let relative = match value.strip_prefix(root) { - Ok(v) => v, - Err(_) => return None, - }; - - let result = relative - .components() - .map(|component| { - component.as_os_str().to_string_lossy().into_owned() - }) - .collect::>(); - - Some(result) -} - -#[test] -fn test_path_to_route() { - fn t(root: &Path, value: &Path, result: Option>) { - assert_eq!(path_to_route(root, value), result); - } - - t( - Path::new("/a/b/c"), - Path::new("/a/b/c/d"), - Some(vec!["d".to_string()]), - ); - t(Path::new("/a/b"), Path::new("a"), None); -} - -#[test] -#[cfg(target_os = "windows")] -fn test_path_to_route_windows() { - fn t(root: &Path, value: &Path, result: Option>) { - assert_eq!(path_to_route(root, value), result); - } - - t( - Path::new("C:\\foo"), - Path::new("C:\\foo\\bar\\baz"), - Some(vec!["bar".to_string(), "baz".to_string()]), - ); -} +use std::path::{Path, PathBuf}; /// Turns the path into an absolute one, using the current working directory if /// necessary. @@ -63,7 +11,7 @@ pub fn canonicalish>(value: T) -> PathBuf { /// Converts the given path to be absolute if it isn't already using a given /// root. -pub fn absoluteify(root: A, value: B) -> PathBuf +fn absoluteify(root: A, value: B) -> PathBuf where A: AsRef, B: AsRef, @@ -77,44 +25,3 @@ where root.join(value) } } - -/// Collapses any `.` values along with any `..` values not at the start of the -/// path. -pub fn collapse>(value: T) -> PathBuf { - let value = value.as_ref(); - - let mut buffer = Vec::new(); - - for component in value.components() { - match component { - Component::ParentDir => match buffer.pop() { - Some(_) => {}, - None => buffer.push(component.as_os_str()), - }, - Component::CurDir => {}, - _ => { - buffer.push(component.as_os_str()); - }, - } - } - - buffer.iter().fold(PathBuf::new(), |mut acc, &x| { - acc.push(x); - acc - }) -} - -#[test] -fn test_collapse() { - fn identity(buf: PathBuf) { - assert_eq!(buf, collapse(&buf)); - } - - identity(PathBuf::from("C:\\foo\\bar")); - identity(PathBuf::from("/a/b/c")); - identity(PathBuf::from("a/b")); - - assert_eq!(collapse(PathBuf::from("a/b/..")), PathBuf::from("a")); - assert_eq!(collapse(PathBuf::from("./a/b/c/..")), PathBuf::from("a/b")); - assert_eq!(collapse(PathBuf::from("../a")), PathBuf::from("../a")); -} From 7e671ee76a4d3c6c69167ef22582413f8b3e134b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 14 Aug 2018 00:41:37 -0700 Subject: [PATCH 0193/1504] Update to latest Lemur --- plugin/modules/lemur | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/modules/lemur b/plugin/modules/lemur index 7145587f..86b33cdf 160000 --- a/plugin/modules/lemur +++ b/plugin/modules/lemur @@ -1 +1 @@ -Subproject commit 7145587fa5c1382e4e67db137c3931e6823fa2b6 +Subproject commit 86b33cdfb46fd1e736f8ee1d8861d1b58ffa987f From 80b9b7594b435eb7f5b6f44669f6ccf4404b609b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 14 Aug 2018 00:48:53 -0700 Subject: [PATCH 0194/1504] Fix test failure due to bad test --- server/tests/web.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/tests/web.rs b/server/tests/web.rs index 103345b0..c9ae6259 100644 --- a/server/tests/web.rs +++ b/server/tests/web.rs @@ -427,7 +427,7 @@ fn partition_to_file() { assert_eq!(response.message_cursor, -1); assert_eq!(response.instances.len(), 1); - let instance = response.instances.values().next().unwrap(); + let (id, instance) = response.instances.iter().next().unwrap(); assert_eq!(instance.name, "bar"); assert_eq!(instance.class_name, "ModuleScript"); @@ -435,7 +435,7 @@ fn partition_to_file() { assert_eq!(instance.children.len(), 0); assert_eq!(instance.parent, None); - let body = server.get_string("/api/read/0"); + let body = server.get_string(&format!("/api/read/{}", id)); let response = serde_json::from_str::(&body).unwrap(); assert_eq!(response.server_id, "0"); From 72bc77f1d5a5130230498863590d599df0e241ca Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 26 Aug 2018 01:03:53 -0700 Subject: [PATCH 0195/1504] WIP: Epiphany Refactor (#85) --- README.md | 6 +- integration/.gitignore | 2 + integration/Cargo.lock | 4 + integration/Cargo.toml | 6 + integration/README.md | 2 + integration/src/main.rs | 32 ++ plugin/README.md | 5 + plugin/loadEnvironment.lua | 37 ++ plugin/modules/lemur | 2 +- plugin/rojo.json | 20 +- plugin/runTest.lua | 15 + plugin/spec.lua | 31 +- plugin/src/ApiContext.lua | 22 +- plugin/src/Http.lua | 2 +- plugin/src/Session.lua | 54 +- plugin/testBootstrap.server.lua | 2 + plugin/tests/empty.lua | 5 + plugin/tests/runTests.server.lua | 2 - server/Cargo.lock | 473 +++++++++-------- server/README.md | 4 + server/src/bin.rs | 17 +- server/src/commands/init.rs | 2 +- server/src/commands/mod.rs | 2 +- server/src/commands/serve.rs | 53 +- server/src/file_route.rs | 166 ------ server/src/id.rs | 2 +- server/src/lib.rs | 14 +- .../{message_session.rs => message_queue.rs} | 38 +- server/src/partition.rs | 13 - server/src/partition_watcher.rs | 67 --- server/src/pathext.rs | 2 +- server/src/project.rs | 437 ++++++++-------- server/src/rbx.rs | 131 +++-- server/src/rbx_session.rs | 306 ----------- server/src/session.rs | 178 ++++--- server/src/vfs.rs | 139 +++++ server/src/vfs_session.rs | 242 --------- server/src/web.rs | 176 +++---- server/src/web_util.rs | 2 +- server/tests/read_projects.rs | 36 ++ server/tests/web.rs | 483 ------------------ test-projects/empty/roblox-project.json | 4 + test-projects/empty/rojo.json | 5 - test-projects/foo.json | 26 + test-projects/one-partition/lib/a.lua | 1 - test-projects/one-partition/lib/a.server.lua | 1 - test-projects/one-partition/lib/b.client.lua | 1 - test-projects/one-partition/rojo.json | 10 - test-projects/partition-to-file/foo.lua | 1 - test-projects/partition-to-file/rojo.json | 10 - test-projects/single-sync-point/lib/main.lua | 0 .../single-sync-point/roblox-project.json | 11 + 52 files changed, 1145 insertions(+), 2157 deletions(-) create mode 100644 integration/.gitignore create mode 100644 integration/Cargo.lock create mode 100644 integration/Cargo.toml create mode 100644 integration/README.md create mode 100644 integration/src/main.rs create mode 100644 plugin/README.md create mode 100644 plugin/loadEnvironment.lua create mode 100644 plugin/runTest.lua create mode 100644 plugin/testBootstrap.server.lua create mode 100644 plugin/tests/empty.lua delete mode 100644 plugin/tests/runTests.server.lua create mode 100644 server/README.md delete mode 100644 server/src/file_route.rs rename server/src/{message_session.rs => message_queue.rs} (55%) delete mode 100644 server/src/partition.rs delete mode 100644 server/src/partition_watcher.rs delete mode 100644 server/src/rbx_session.rs create mode 100644 server/src/vfs.rs delete mode 100644 server/src/vfs_session.rs create mode 100644 server/tests/read_projects.rs delete mode 100644 server/tests/web.rs create mode 100644 test-projects/empty/roblox-project.json delete mode 100644 test-projects/empty/rojo.json create mode 100644 test-projects/foo.json delete mode 100644 test-projects/one-partition/lib/a.lua delete mode 100644 test-projects/one-partition/lib/a.server.lua delete mode 100644 test-projects/one-partition/lib/b.client.lua delete mode 100644 test-projects/one-partition/rojo.json delete mode 100644 test-projects/partition-to-file/foo.lua delete mode 100644 test-projects/partition-to-file/rojo.json create mode 100644 test-projects/single-sync-point/lib/main.lua create mode 100644 test-projects/single-sync-point/roblox-project.json diff --git a/README.md b/README.md index 50fc6c0a..d7a50670 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,9 @@ Travis-CI Build Status - Current server version + + Latest server version + Rojo Documentation @@ -41,7 +43,7 @@ There are lots of other tools that sync scripts into Roblox or provide other too Here are a few, if you're looking for alternatives or supplements to Rojo: * [rbxmk by Anaminus](https://github.com/anaminus/rbxmk) -* [RbxRefresh by Osyris](https://github.com/osyrisrblx/RbxRefresh) +* [Rofresh](https://github.com/osyrisrblx/rofresh) and [RbxRefresh](https://github.com/osyrisrblx/RbxRefresh) by [Osyris](https://github.com/osyrisrblx) * [Studio Bridge by Vocksel](https://github.com/vocksel/studio-bridge) * [RbxSync by evaera](https://github.com/evaera/RbxSync) * [CodeSync](https://github.com/MemoryPenguin/CodeSync) and [rbx-exteditor](https://github.com/MemoryPenguin/rbx-exteditor) by [MemoryPenguin](https://github.com/MemoryPenguin) diff --git a/integration/.gitignore b/integration/.gitignore new file mode 100644 index 00000000..a79a8002 --- /dev/null +++ b/integration/.gitignore @@ -0,0 +1,2 @@ +/target/ +**/*.rs.bk \ No newline at end of file diff --git a/integration/Cargo.lock b/integration/Cargo.lock new file mode 100644 index 00000000..02b1e530 --- /dev/null +++ b/integration/Cargo.lock @@ -0,0 +1,4 @@ +[[package]] +name = "integration" +version = "0.1.0" + diff --git a/integration/Cargo.toml b/integration/Cargo.toml new file mode 100644 index 00000000..769e48aa --- /dev/null +++ b/integration/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "integration" +version = "0.1.0" +authors = ["Lucien Greathouse "] + +[dependencies] diff --git a/integration/README.md b/integration/README.md new file mode 100644 index 00000000..e211270b --- /dev/null +++ b/integration/README.md @@ -0,0 +1,2 @@ +# Rojo Integration Runner +This is a WIP test runner designed for Rojo. It will eventually start up the Rojo server and plugin and test functionality end-to-end. \ No newline at end of file diff --git a/integration/src/main.rs b/integration/src/main.rs new file mode 100644 index 00000000..4e4883b1 --- /dev/null +++ b/integration/src/main.rs @@ -0,0 +1,32 @@ +use std::{ + path::Path, + process::Command, + thread, + time::Duration, +}; + +fn main() { + let plugin_path = Path::new("../plugin"); + let server_path = Path::new("../server"); + let tests_path = Path::new("../tests"); + + let server = Command::new("cargo") + .args(&["run", "--", "serve", "../test-projects/empty"]) + .current_dir(server_path) + .spawn(); + + thread::sleep(Duration::from_millis(1000)); + + // TODO: Wait for server to start responding on the right port + + let test_client = Command::new("lua") + .args(&["runTest.lua", "tests/empty.lua"]) + .current_dir(plugin_path) + .spawn(); + + thread::sleep(Duration::from_millis(300)); + + // TODO: Collect output from the client for success/failure? + + println!("Dying!"); +} diff --git a/plugin/README.md b/plugin/README.md new file mode 100644 index 00000000..f3f68394 --- /dev/null +++ b/plugin/README.md @@ -0,0 +1,5 @@ +# Rojo Plugin + +This is the source to the Rojo Roblox Studio plugin. + +Documentation is WIP. \ No newline at end of file diff --git a/plugin/loadEnvironment.lua b/plugin/loadEnvironment.lua new file mode 100644 index 00000000..e7065daa --- /dev/null +++ b/plugin/loadEnvironment.lua @@ -0,0 +1,37 @@ +--[[ + Loads the Rojo plugin and all of its dependencies. +]] + +local function loadEnvironment() + -- If you add any dependencies, add them to this table so they'll be loaded! + local LOAD_MODULES = { + {"src", "Rojo"}, + {"modules/promise/lib", "Promise"}, + {"modules/testez/lib", "TestEZ"}, + } + + -- This makes sure we can load Lemur and other libraries that depend on init.lua + package.path = package.path .. ";?/init.lua" + + -- If this fails, make sure you've run `lua bin/install-dependencies.lua` first! + local lemur = require("modules.lemur") + + -- Create a virtual Roblox tree + local habitat = lemur.Habitat.new() + + -- We'll put all of our library code and dependencies here + local modules = lemur.Instance.new("Folder") + modules.Name = "Modules" + modules.Parent = habitat.game:GetService("ReplicatedStorage") + + -- Load all of the modules specified above + for _, module in ipairs(LOAD_MODULES) do + local container = habitat:loadFromFs(module[1]) + container.Name = module[2] + container.Parent = modules + end + + return habitat, modules +end + +return loadEnvironment \ No newline at end of file diff --git a/plugin/modules/lemur b/plugin/modules/lemur index 86b33cdf..96d4166a 160000 --- a/plugin/modules/lemur +++ b/plugin/modules/lemur @@ -1 +1 @@ -Subproject commit 86b33cdfb46fd1e736f8ee1d8861d1b58ffa987f +Subproject commit 96d4166a2d9e146e6955eeacccc0c79a86a177f5 diff --git a/plugin/rojo.json b/plugin/rojo.json index 17f5548f..2276882c 100644 --- a/plugin/rojo.json +++ b/plugin/rojo.json @@ -4,31 +4,31 @@ "partitions": { "plugin": { "path": "src", - "target": "ReplicatedStorage.Rojo.modules.Plugin" + "target": "ReplicatedStorage.Rojo.Modules.Plugin" }, "modules/roact": { "path": "modules/roact/lib", - "target": "ReplicatedStorage.Rojo.modules.Roact" + "target": "ReplicatedStorage.Rojo.Modules.Roact" }, "modules/rodux": { "path": "modules/rodux/lib", - "target": "ReplicatedStorage.Rojo.modules.Rodux" + "target": "ReplicatedStorage.Rojo.Modules.Rodux" }, "modules/roact-rodux": { "path": "modules/roact-rodux/lib", - "target": "ReplicatedStorage.Rojo.modules.RoactRodux" + "target": "ReplicatedStorage.Rojo.Modules.RoactRodux" + }, + "modules/promise": { + "path": "modules/promise/lib", + "target": "ReplicatedStorage.Rojo.Modules.Promise" }, "modules/testez": { "path": "modules/testez/lib", "target": "ReplicatedStorage.TestEZ" }, - "modules/promise": { - "path": "modules/promise/lib", - "target": "ReplicatedStorage.Rojo.modules.Promise" - }, "tests": { - "path": "tests", - "target": "TestService" + "path": "testBootstrap.server.lua", + "target": "TestService.testBootstrap" } } } \ No newline at end of file diff --git a/plugin/runTest.lua b/plugin/runTest.lua new file mode 100644 index 00000000..a3a682d0 --- /dev/null +++ b/plugin/runTest.lua @@ -0,0 +1,15 @@ +local loadEnvironment = require("loadEnvironment") + +local testPath = assert((...), "Please specify a path to a test file.") + +local habitat = loadEnvironment() + +local testModule = habitat:loadFromFs(testPath) + +if testModule == nil then + error("Couldn't find test file at " .. testPath) +end + +print("Starting test module.") + +habitat:require(testModule) \ No newline at end of file diff --git a/plugin/spec.lua b/plugin/spec.lua index 102093f1..25e23181 100644 --- a/plugin/spec.lua +++ b/plugin/spec.lua @@ -2,37 +2,14 @@ Loads our library and all of its dependencies, then runs tests using TestEZ. ]] --- If you add any dependencies, add them to this table so they'll be loaded! -local LOAD_MODULES = { - {"src", "plugin"}, - {"modules/promise/lib", "Promise"}, - {"modules/testez/lib", "TestEZ"}, -} +local loadEnvironment = require("loadEnvironment") --- This makes sure we can load Lemur and other libraries that depend on init.lua -package.path = package.path .. ";?/init.lua" - --- If this fails, make sure you've run `lua bin/install-dependencies.lua` first! -local lemur = require("modules.lemur") - --- Create a virtual Roblox tree -local habitat = lemur.Habitat.new() - --- We'll put all of our library code and dependencies here -local Root = lemur.Instance.new("Folder") -Root.Name = "Root" - --- Load all of the modules specified above -for _, module in ipairs(LOAD_MODULES) do - local container = habitat:loadFromFs(module[1]) - container.Name = module[2] - container.Parent = Root -end +local habitat, modules = loadEnvironment() -- Load TestEZ and run our tests -local TestEZ = habitat:require(Root.TestEZ) +local TestEZ = habitat:require(modules.TestEZ) -local results = TestEZ.TestBootstrap:run(Root.plugin, TestEZ.Reporters.TextReporter) +local results = TestEZ.TestBootstrap:run(modules.Rojo, TestEZ.Reporters.TextReporter) -- Did something go wrong? if results.failureCount > 0 then diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index d8d301e1..19dd19eb 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -19,14 +19,15 @@ setmetatable(ApiContext.Error, { end }) -function ApiContext.new(url, onMessage) - assert(type(url) == "string") +function ApiContext.new(baseUrl, onMessage) + assert(type(baseUrl) == "string") assert(type(onMessage) == "function") local context = { - url = url, + baseUrl = baseUrl, onMessage = onMessage, serverId = nil, + rootInstanceId = nil, connected = false, messageCursor = -1, partitionRoutes = nil, @@ -38,7 +39,9 @@ function ApiContext.new(url, onMessage) end function ApiContext:connect() - return Http.get(self.url .. "/api/rojo") + local url = ("%s/api/rojo"):format(self.baseUrl) + + return Http.get(url) :andThen(function(response) local body = response:json() @@ -61,15 +64,18 @@ function ApiContext:connect() self.serverId = body.serverId self.connected = true self.partitionRoutes = body.partitions + self.rootInstanceId = body.rootInstanceId end) end -function ApiContext:readAll() +function ApiContext:read(ids) if not self.connected then return Promise.reject() end - return Http.get(self.url .. "/api/read_all") + local url = ("%s/api/read/%s"):format(self.baseUrl, table.concat(ids, ",")) + + return Http.get(url) :andThen(function(response) local body = response:json() @@ -92,7 +98,9 @@ function ApiContext:retrieveMessages() return Promise.reject() end - return Http.get(self.url .. "/api/subscribe/" .. self.messageCursor) + local url = ("%s/api/subscribe/%s"):format(self.baseUrl, self.messageCursor) + + return Http.get(url) :andThen(function(response) local body = response:json() diff --git a/plugin/src/Http.lua b/plugin/src/Http.lua index d6dd9cdb..57cedc15 100644 --- a/plugin/src/Http.lua +++ b/plugin/src/Http.lua @@ -1,6 +1,6 @@ local HttpService = game:GetService("HttpService") -local HTTP_DEBUG = false +local HTTP_DEBUG = true local Promise = require(script.Parent.Parent.Promise) diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 47d8d5d0..4eb1d012 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -11,57 +11,7 @@ function Session.new() setmetatable(self, Session) - local function createFoldersUntil(location, route) - for i = 1, #route - 1 do - local piece = route[i] - - local child = location:FindFirstChild(piece) - - if child == nil then - child = Instance.new("Folder") - child.Name = piece - child.Parent = location - end - - location = child - end - - return location - end - - local function reify(instancesById, id) - local object = instancesById[tostring(id)] - local instance = Instance.new(object.className) - instance.Name = object.name - - for key, property in pairs(object.properties) do - instance[key] = property.value - end - - for _, childId in ipairs(object.children) do - reify(instancesById, childId).Parent = instance - end - - return instance - end - local api - local function readAll() - print("Reading all...") - - return api:readAll() - :andThen(function(response) - for partitionName, partitionRoute in pairs(api.partitionRoutes) do - local parent = createFoldersUntil(game, partitionRoute) - - local rootInstanceId = response.partitionInstances[partitionName] - - print("Root for", partitionName, "is", rootInstanceId) - - reify(response.instances, rootInstanceId).Parent = parent - end - end) - end api = ApiContext.new(REMOTE_URL, function(message) if message.type == "InstanceChanged" then @@ -73,7 +23,9 @@ function Session.new() end) api:connect() - :andThen(readAll) + :andThen(function() + return api:read({api.rootInstanceId}) + end) :andThen(function() return api:retrieveMessages() end) diff --git a/plugin/testBootstrap.server.lua b/plugin/testBootstrap.server.lua new file mode 100644 index 00000000..ae53be9f --- /dev/null +++ b/plugin/testBootstrap.server.lua @@ -0,0 +1,2 @@ +local TestEZ = require(game.ReplicatedStorage.TestEZ) +TestEZ.TestBootstrap:run(game.ReplicatedStorage.Rojo.plugin) \ No newline at end of file diff --git a/plugin/tests/empty.lua b/plugin/tests/empty.lua new file mode 100644 index 00000000..bfda7fad --- /dev/null +++ b/plugin/tests/empty.lua @@ -0,0 +1,5 @@ +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local Session = require(ReplicatedStorage.Modules.Rojo.Session) + +Session.new() \ No newline at end of file diff --git a/plugin/tests/runTests.server.lua b/plugin/tests/runTests.server.lua deleted file mode 100644 index be1a94d5..00000000 --- a/plugin/tests/runTests.server.lua +++ /dev/null @@ -1,2 +0,0 @@ -local TestEZ = require(game.ReplicatedStorage.TestEZ) -TestEZ.TestBootstrap:run(game.ReplicatedStorage.Rojo.plugin) diff --git a/server/Cargo.lock b/server/Cargo.lock index bf03e25e..3e0dfd05 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -1,14 +1,14 @@ [[package]] name = "adler32" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "aho-corasick" -version = "0.6.4" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -16,7 +16,7 @@ name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -26,12 +26,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "atty" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -39,7 +39,7 @@ name = "base64" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -55,7 +55,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -64,7 +64,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -73,7 +73,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "brotli-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -92,7 +92,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.2" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -102,7 +102,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -111,17 +111,17 @@ version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "chrono" -version = "0.4.2" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -131,16 +131,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clap" -version = "2.31.2" +version = "2.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -156,16 +164,11 @@ name = "deflate" version = "0.7.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "gzip-header 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "dtoa" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "encoding" version = "0.2.33" @@ -236,9 +239,9 @@ name = "filetime" version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -248,7 +251,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -256,7 +259,7 @@ name = "fsevent-sys" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -264,7 +267,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -289,17 +292,17 @@ dependencies = [ [[package]] name = "httparse" -version = "1.2.4" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "idna" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -307,12 +310,12 @@ name = "inotify" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -326,12 +329,15 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "libc" -version = "0.2.40" +version = "0.2.43" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -339,20 +345,20 @@ name = "log" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "log" -version = "0.4.1" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "matches" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -360,15 +366,15 @@ name = "memchr" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memchr" -version = "2.0.1" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -381,7 +387,7 @@ dependencies = [ [[package]] name = "mime_guess" -version = "1.8.4" +version = "1.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -396,13 +402,13 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -412,7 +418,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -423,10 +429,10 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.8.4 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -435,12 +441,12 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.32" +version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -449,12 +455,12 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "notify" -version = "4.0.3" +version = "4.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -463,9 +469,9 @@ dependencies = [ "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -474,26 +480,26 @@ name = "num" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-integer" -version = "0.1.36" +version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-iter" -version = "0.1.35" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -501,12 +507,12 @@ name = "num-traits" version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.2" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -514,7 +520,7 @@ name = "num_cpus" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -545,7 +551,7 @@ version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -553,13 +559,13 @@ name = "phf_shared" version = "0.7.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro2" -version = "0.3.8" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -567,10 +573,10 @@ dependencies = [ [[package]] name = "quote" -version = "0.5.2" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -579,23 +585,40 @@ version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "redox_syscall" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -603,24 +626,24 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.0.0" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -631,24 +654,24 @@ name = "remove_dir_all" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rojo" version = "0.5.0" dependencies = [ - "clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -658,21 +681,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "brotli2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "tiny_http 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -680,6 +703,11 @@ name = "rustc-serialize" version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ryu" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "safemem" version = "0.2.0" @@ -687,35 +715,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "same-file" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde" -version = "1.0.51" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.51" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.17" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -725,7 +753,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "siphasher" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -740,11 +768,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.13.7" +version = "0.14.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -753,20 +781,20 @@ name = "tempdir" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tempfile" -version = "3.0.2" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -783,26 +811,25 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "textwrap" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "thread_local" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -815,12 +842,12 @@ dependencies = [ [[package]] name = "time" -version = "0.1.39" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -841,7 +868,7 @@ name = "twoway" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -854,7 +881,7 @@ name = "unicase" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -862,17 +889,17 @@ name = "unicode-bidi" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-normalization" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-width" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -880,37 +907,29 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "url" version = "0.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "url" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "utf8-ranges" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -924,26 +943,22 @@ dependencies = [ [[package]] name = "vec_map" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "version_check" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "void" -version = "1.0.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" -version = "2.1.4" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -953,7 +968,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -970,6 +985,14 @@ name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "winapi-util" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -985,29 +1008,29 @@ dependencies = [ ] [metadata] -"checksum adler32 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6cbd0b9af8587c72beadc9f72d35b9fbb070982c9e6203e46e93f10df25f8f45" -"checksum aho-corasick 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6531d44de723825aa81398a6415283229725a00fa30713812ab9323faa82fc4" +"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" +"checksum aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee94e9463ccb9d681e7b708082687b2c56d2bd420ca8a3d3157d27d59508ec0" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" -"checksum atty 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2fc4a1aa4c24c0718a250f0681885c1af91419d242f29eb8f2ab28502d80dbd1" +"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5032d51da2741729bfdaeb2664d9b8c6d9fd1e2b90715c660b6def36628499c2" "checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" -"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" +"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum brotli-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cb50f54b2e0c671b7ef1637a76237ebacbb293be179440d5d65ca288e42116bb" "checksum brotli2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea9d0bbab1235017a09226b079ed733bca4bf9ecb6b6102bd01aac79ea082dca" "checksum buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9279646319ff816b05fb5897883ece50d7d854d12b59992683d4f8a71b0f949" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" -"checksum byteorder 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "73b5bdfe7ee3ad0b99c9801d58807a9dbc9e09196365b0203853b99889ab3c87" +"checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" "checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27" -"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" +"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" "checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" -"checksum chrono 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1cce36c92cb605414e9b824f866f5babe0a0368e39ea07393b9b63cf3844c0e6" +"checksum chrono 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e48d85528df61dc964aa43c5f6ca681a19cfa74939b2348d204bd08a981f2fb0" "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" -"checksum clap 2.31.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0f16b89cbb9ee36d87483dc939fe9f1e13c05898d56d7b230a0d4dff033a536" +"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "32c8120d981901a9970a3a1c97cf8b630e0fa8c3ca31e75b6fd6fd5f9f427b31" -"checksum dtoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "09c3753c3db574d215cba4ea76018483895d7bff25a31b49ba45db21c48e50ab" "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" "checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" @@ -1023,86 +1046,88 @@ dependencies = [ "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum gzip-header 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0a9fcfe1c9ee125342355b2467bc29b9dfcb2124fcae27edb9cee6f4cc5ecd40" -"checksum httparse 1.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c2f407128745b78abc95c0ffbe4e5d37427fdc0d45470710cfef8c44522a2e37" -"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" +"checksum httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7b6288d7db100340ca12873fd4d08ad1b8f206a9457798dfb17c018a33fee540" +"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" -"checksum itoa 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c069bbec61e1ca5a596166e55dfe4773ff745c3d16b700013bcaff9a6df2c682" +"checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c8f31047daa365f19be14b47c29df4f7c3b581832407daabe6ae77397619237d" -"checksum libc 0.2.40 (registry+https://github.com/rust-lang/crates.io-index)" = "6fd41f331ac7c5b8ac259b8bf82c75c0fb2e469bbf37d2becbba9a6a2221965b" +"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" +"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" -"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" +"checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2" +"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" -"checksum memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "796fba70e76612589ed2ce7f45282f5af869e0fdd7cc6199fa1aa1f1d591ba9d" +"checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -"checksum mime_guess 1.8.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b7e2b09d08313f84e0fb82d13a4d859109a17543fe9af3b6d941dc1431f7de79" +"checksum mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2d4c0961143b8efdcfa29c3ae63281601b446a4a668165454b6c90f8024954c5" "checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e" "checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" "checksum multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92f54eb45230c3aa20864ccf0c277eeaeadcf5e437e91731db498dbf7fbe0ec6" -"checksum net2 0.2.32 (registry+https://github.com/rust-lang/crates.io-index)" = "9044faf1413a1057267be51b5afba8eb1090bd2231c693664aa1db716fe1eae0" +"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfb3ddedaa14746434a02041940495bf11325c22f6d36125d3bdd56090d50a79" -"checksum notify 4.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5c3812da3098f210a0bb440f9c008471a031aa4c1de07a264fdd75456c95a4eb" +"checksum notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d023ef40ca7680784b07be3f49913e1ea176da1b63949f2eb2fed96438bd7f42" "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" -"checksum num-integer 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "f8d26da319fb45674985c78f1d1caf99aa4941f785d384a2ae36d0740bc3e2fe" -"checksum num-iter 0.1.35 (registry+https://github.com/rust-lang/crates.io-index)" = "4b226df12c5a59b63569dd57fafb926d91b385dfce33d8074a412411b689d593" +"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" +"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" "checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -"checksum num-traits 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dee092fcdf725aee04dd7da1d21debff559237d49ef1cb3e69bcb8ece44c7364" +"checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "7d37a244c75a9748e049225155f56dbcb98fe71b192fd25fd23cb914b5ad62f2" "checksum phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4048fe7dd7a06b8127ecd6d3803149126e9b33c7558879846da3a63f734f2b" "checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998" "checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930" -"checksum proc-macro2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1b06e2f335f48d24442b35a19df506a835fb3547bc3c06ef27340da9acf5cae7" -"checksum quote 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9949cfe66888ffe1d53e6ec9d9f3b70714083854be20fd5e271b232a017401e8" +"checksum proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5697238f0d893c7f0ecc59c0999f18d2af85e424de441178bcacc9f9e6cf67" +"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" -"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" -"checksum redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" +"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" +"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" +"checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" +"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75ecf88252dce580404a22444fc7d626c01815debba56a7f4f536772a5ff19d3" -"checksum regex-syntax 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8f1ac0f60d675cc6cf13a20ec076568254472551051ad5dd050364d70671bf6b" +"checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025" +"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc1f8407af80b0630983b2c1f1860dda1960fdec8d3ee75ba8db14937756d3a0" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" +"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" -"checksum same-file 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cfb6eded0b06a0b512c8ddbcf04089138c9b4362c2f696f3c3d76039d68f3637" -"checksum serde 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)" = "21924cc18e5281f232a17c040355fac97732b42cf019c24996a1642bcb169cdb" -"checksum serde_derive 1.0.51 (registry+https://github.com/rust-lang/crates.io-index)" = "9c624a90bec6fe9bc60d275d7af71c72c26b24cd6c6776d8e344dc4044caa3e2" -"checksum serde_json 1.0.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f3ad6d546e765177cf3dded3c2e424a8040f870083a0e64064746b958ece9cb1" +"checksum same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f7794e2fda7f594866840e95f5c5962e886e228e68b6505885811a94dd728c" +"checksum serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "22d340507cea0b7e6632900a176101fea959c7065d93ba555072da90aaaafc87" +"checksum serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "234fc8b737737b148ccd625175fc6390f5e4dacfdaa543cb93a3430d984a9119" +"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae" "checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" -"checksum siphasher 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0df90a788073e8d0235a67e50441d47db7c8ad9debd91cbf43736a2a92d36537" +"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.13.7 (registry+https://github.com/rust-lang/crates.io-index)" = "61b8f1b737f929c6516ba46a3133fd6d5215ad8a62f66760f851f7048aebedfb" +"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum tempfile 3.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "47776f63b85777d984a50ce49d6b9e58826b6a3766a449fc95bc66cd5663c15b" +"checksum tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4b103c6d08d323b92ff42c8ce62abcd83ca8efa7fd5bf7927efefec75f58c76" "checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" -"checksum thread_local 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "279ef31c19ededf577bfd12dfae728040a21f635b06a24cd670ff510edd38963" +"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" -"checksum time 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "a15375f1df02096fb3317256ce2cee6a1f42fc84ea5ad5fc8c421cfe40c73098" +"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" "checksum tiny_http 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2f4d55c9a213880d1f0c89ded183f209c6e45b912ca6c7df6f93c163773572e1" "checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" "checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90d662d111b0dbb08a180f2761026cba648c258023c355954a7c00e00e354636" -"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" +"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)" = "cbaa8377a162d88e7d15db0cf110c8523453edcbc5bc66d2b6fffccffa34a068" -"checksum url 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f808aadd8cfec6ef90e4a14eb46f24511824d1ac596b9682703c87056c8678b7" -"checksum utf8-ranges 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "662fab6525a98beff2921d7f61a39e7d59e0b425ebc7d0d9e66d316e55124122" +"checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" +"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" "checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f" -"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" -"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" -"checksum walkdir 2.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "63636bd0eb3d00ccb8b9036381b526efac53caf112b7783b730ab3f8e44da369" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" +"checksum walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "af464bc7be7b785c7ac72e266a6b67c4c9070155606f51655a650a6686204e35" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" +"checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" diff --git a/server/README.md b/server/README.md new file mode 100644 index 00000000..b3801934 --- /dev/null +++ b/server/README.md @@ -0,0 +1,4 @@ +# Rojo Server +This is the source to the Rojo server. + +Documentation is WIP. \ No newline at end of file diff --git a/server/src/bin.rs b/server/src/bin.rs index bf20429e..86232c92 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -42,20 +42,7 @@ fn main() { None => std::env::current_dir().unwrap(), }; - let port = { - match sub_matches.value_of("port") { - Some(source) => match source.parse::() { - Ok(value) => Some(value), - Err(_) => { - eprintln!("Invalid port '{}'", source); - process::exit(1); - }, - }, - None => None, - } - }; - - librojo::commands::serve(&project_path, port); + librojo::commands::serve(&project_path); }, _ => { eprintln!("Please specify a subcommand!"); @@ -63,4 +50,4 @@ fn main() { process::exit(1); }, } -} +} \ No newline at end of file diff --git a/server/src/commands/init.rs b/server/src/commands/init.rs index 96cbbcb3..9050e072 100644 --- a/server/src/commands/init.rs +++ b/server/src/commands/init.rs @@ -13,4 +13,4 @@ pub fn init(project_path: &PathBuf) { process::exit(1); }, } -} +} \ No newline at end of file diff --git a/server/src/commands/mod.rs b/server/src/commands/mod.rs index 58023fa3..db228aa1 100644 --- a/server/src/commands/mod.rs +++ b/server/src/commands/mod.rs @@ -2,4 +2,4 @@ mod serve; mod init; pub use self::serve::*; -pub use self::init::*; +pub use self::init::*; \ No newline at end of file diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 243ee335..7233c872 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -1,40 +1,39 @@ -use std::path::PathBuf; -use std::process; -use std::fs; +use std::{ + path::Path, + process, + sync::Arc, +}; -use rand; +use ::{ + project::Project, + web::Server, + session::Session, + roblox_studio, +}; -use project::Project; -use web::{self, WebConfig}; -use session::Session; -use roblox_studio; - -pub fn serve(project_dir: &PathBuf, override_port: Option) { - let server_id = rand::random::(); - - let project = match Project::load(project_dir) { - Ok(v) => { - println!("Using project from {}", fs::canonicalize(project_dir).unwrap().display()); - v - }, - Err(err) => { - eprintln!("{}", err); +pub fn serve(fuzzy_project_location: &Path) { + let project = match Project::load_fuzzy(fuzzy_project_location) { + Ok(project) => project, + Err(error) => { + eprintln!("Fatal: {}", error); process::exit(1); }, }; - let port = override_port.unwrap_or(project.serve_port); - + println!("Found project at {}", project.file_location.display()); println!("Using project {:#?}", project); roblox_studio::install_bundled_plugin().unwrap(); - let mut session = Session::new(project.clone()); - session.start(); + let session = Arc::new({ + let mut session = Session::new(project); + session.start().unwrap(); + session + }); - let web_config = WebConfig::from_session(server_id, port, &session); + let server = Server::new(Arc::clone(&session)); - println!("Server listening on port {}", port); + println!("Server listening on port 34872"); - web::start(web_config); -} + server.listen(34872); +} \ No newline at end of file diff --git a/server/src/file_route.rs b/server/src/file_route.rs deleted file mode 100644 index a691034e..00000000 --- a/server/src/file_route.rs +++ /dev/null @@ -1,166 +0,0 @@ -use std::path::{Path, PathBuf, Component}; - -use partition::Partition; - -// TODO: Change backing data structure to use a single allocation with slices -// taken out of it for each portion -#[derive(Debug, Clone, PartialEq, Eq, Hash)] -pub struct FileRoute { - pub partition: String, - pub route: Vec, -} - -impl FileRoute { - pub fn from_path(path: &Path, partition: &Partition) -> Option { - assert!(path.is_absolute()); - assert!(path.starts_with(&partition.path)); - - let relative_path = path.strip_prefix(&partition.path).ok()?; - let mut route = Vec::new(); - - for component in relative_path.components() { - match component { - Component::Normal(piece) => { - route.push(piece.to_string_lossy().into_owned()); - }, - _ => panic!("Unexpected path component: {:?}", component), - } - } - - Some(FileRoute { - partition: partition.name.clone(), - route, - }) - } - - pub fn parent(&self) -> Option { - if self.route.len() == 0 { - return None; - } - - let mut new_route = self.route.clone(); - new_route.pop(); - - Some(FileRoute { - partition: self.partition.clone(), - route: new_route, - }) - } - - /// Creates a PathBuf out of the `FileRoute` based on the given partition - /// `Path`. - pub fn to_path_buf(&self, partition_path: &Path) -> PathBuf { - let mut result = partition_path.to_path_buf(); - - for route_piece in &self.route { - result.push(route_piece); - } - - result - } - - /// Creates a version of the FileRoute with the given extra pieces appended - /// to the end. - pub fn extended_with(&self, pieces: &[&str]) -> FileRoute { - let mut result = self.clone(); - - for piece in pieces { - result.route.push(piece.to_string()); - } - - result - } - - pub fn file_name(&self, partition: &Partition) -> String { - if self.route.len() == 0 { - partition.path.file_name().unwrap().to_str().unwrap().to_string() - } else { - self.route.last().unwrap().clone() - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[cfg(windows)] - const ROOT_PATH: &'static str = "C:\\"; - - #[cfg(not(windows))] - const ROOT_PATH: &'static str = "/"; - - #[test] - fn from_path_empty() { - let path = Path::new(ROOT_PATH).join("a/b/c"); - - let partition = Partition { - name: "foo".to_string(), - path: path.clone(), - target: vec![], - }; - - let route = FileRoute::from_path(&path, &partition); - - assert_eq!(route, Some(FileRoute { - partition: "foo".to_string(), - route: vec![], - })); - } - - #[test] - fn from_path_non_empty() { - let partition_path = Path::new(ROOT_PATH).join("a/b/c"); - - let inside_path = partition_path.join("d"); - - let partition = Partition { - name: "bar".to_string(), - path: partition_path, - target: vec![], - }; - - let route = FileRoute::from_path(&inside_path, &partition); - - assert_eq!(route, Some(FileRoute { - partition: "bar".to_string(), - route: vec!["d".to_string()], - })); - } - - #[test] - fn file_name_empty_route() { - let partition_path = Path::new(ROOT_PATH).join("a/b/c"); - - let partition = Partition { - name: "bar".to_string(), - path: partition_path, - target: vec![], - }; - - let route = FileRoute { - partition: "bar".to_string(), - route: vec![], - }; - - assert_eq!(route.file_name(&partition), "c"); - } - - #[test] - fn file_name_non_empty_route() { - let partition_path = Path::new(ROOT_PATH).join("a/b/c"); - - let partition = Partition { - name: "bar".to_string(), - path: partition_path, - target: vec![], - }; - - let route = FileRoute { - partition: "bar".to_string(), - route: vec!["foo".to_string(), "hello.lua".to_string()], - }; - - assert_eq!(route.file_name(&partition), "hello.lua"); - } -} \ No newline at end of file diff --git a/server/src/id.rs b/server/src/id.rs index a27a9d8c..98144cfa 100644 --- a/server/src/id.rs +++ b/server/src/id.rs @@ -18,4 +18,4 @@ fn it_gives_unique_numbers() { let b = get_id(); assert!(a != b); -} +} \ No newline at end of file diff --git a/server/src/lib.rs b/server/src/lib.rs index 2f806548..315d266c 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -11,17 +11,13 @@ extern crate regex; extern crate tempfile; pub mod commands; -pub mod file_route; pub mod id; -pub mod message_session; -pub mod partition; -pub mod partition_watcher; +pub mod message_queue; pub mod pathext; pub mod project; pub mod rbx; -pub mod rbx_session; -pub mod session; -pub mod vfs_session; -pub mod web; -pub mod web_util; pub mod roblox_studio; +pub mod session; +pub mod vfs; +pub mod web; +pub mod web_util; \ No newline at end of file diff --git a/server/src/message_session.rs b/server/src/message_queue.rs similarity index 55% rename from server/src/message_session.rs rename to server/src/message_queue.rs index 85b2aa32..1029c7e1 100644 --- a/server/src/message_session.rs +++ b/server/src/message_queue.rs @@ -1,5 +1,5 @@ use std::collections::HashMap; -use std::sync::{mpsc, Arc, RwLock, Mutex}; +use std::sync::{mpsc, RwLock, Mutex}; use id::{Id, get_id}; @@ -11,17 +11,16 @@ pub enum Message { }, } -#[derive(Clone)] -pub struct MessageSession { - pub messages: Arc>>, - pub message_listeners: Arc>>>, +pub struct MessageQueue { + messages: RwLock>, + message_listeners: Mutex>>, } -impl MessageSession { - pub fn new() -> MessageSession { - MessageSession { - messages: Arc::new(RwLock::new(Vec::new())), - message_listeners: Arc::new(Mutex::new(HashMap::new())), +impl MessageQueue { + pub fn new() -> MessageQueue { + MessageQueue { + messages: RwLock::new(Vec::new()), + message_listeners: Mutex::new(HashMap::new()), } } @@ -58,7 +57,20 @@ impl MessageSession { } } - pub fn get_message_cursor(&self) -> i32 { - self.messages.read().unwrap().len() as i32 - 1 + pub fn get_message_cursor(&self) -> u32 { + self.messages.read().unwrap().len() as u32 } -} + + pub fn get_messages_since(&self, cursor: u32) -> (u32, Vec) { + let messages = self.messages.read().unwrap(); + + let current_cursor = messages.len() as u32; + + // Cursor is out of bounds or there are no new messages + if cursor >= current_cursor { + return (current_cursor, Vec::new()); + } + + (current_cursor, messages[(cursor as usize)..].to_vec()) + } +} \ No newline at end of file diff --git a/server/src/partition.rs b/server/src/partition.rs deleted file mode 100644 index 9ef66664..00000000 --- a/server/src/partition.rs +++ /dev/null @@ -1,13 +0,0 @@ -use std::path::PathBuf; - -#[derive(Debug, Clone, PartialEq)] -pub struct Partition { - /// The unique name of this partition, used for debugging. - pub name: String, - - /// The path on the filesystem that this partition maps to. - pub path: PathBuf, - - /// The route to the Roblox instance that this partition maps to. - pub target: Vec, -} diff --git a/server/src/partition_watcher.rs b/server/src/partition_watcher.rs deleted file mode 100644 index 5885bb74..00000000 --- a/server/src/partition_watcher.rs +++ /dev/null @@ -1,67 +0,0 @@ -use std::sync::mpsc::{channel, Sender}; -use std::time::Duration; -use std::thread; - -use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher, watcher}; - -use partition::Partition; -use vfs_session::FileChange; -use file_route::FileRoute; - -const WATCH_TIMEOUT_MS: u64 = 100; - -pub struct PartitionWatcher { - pub watcher: RecommendedWatcher, -} - -impl PartitionWatcher { - pub fn start_new(partition: Partition, tx: Sender) -> PartitionWatcher { - let (watch_tx, watch_rx) = channel(); - - let mut watcher = watcher(watch_tx, Duration::from_millis(WATCH_TIMEOUT_MS)).unwrap(); - - watcher.watch(&partition.path, RecursiveMode::Recursive).unwrap(); - - thread::spawn(move || { - loop { - match watch_rx.recv() { - Ok(event) => { - let file_change = match event { - DebouncedEvent::Create(path) => { - let route = FileRoute::from_path(&path, &partition).unwrap(); - FileChange::Created(route) - }, - DebouncedEvent::Write(path) => { - let route = FileRoute::from_path(&path, &partition).unwrap(); - FileChange::Updated(route) - }, - DebouncedEvent::Remove(path) => { - let route = FileRoute::from_path(&path, &partition).unwrap(); - FileChange::Deleted(route) - }, - DebouncedEvent::Rename(from_path, to_path) => { - let from_route = FileRoute::from_path(&from_path, &partition).unwrap(); - let to_route = FileRoute::from_path(&to_path, &partition).unwrap(); - FileChange::Moved(from_route, to_route) - }, - _ => continue, - }; - - match tx.send(file_change) { - Ok(_) => {}, - Err(_) => break, - } - }, - Err(_) => break, - }; - } - }); - - PartitionWatcher { - watcher, - } - } - - pub fn stop(self) { - } -} diff --git a/server/src/pathext.rs b/server/src/pathext.rs index 0b4c0f79..0b257cc8 100644 --- a/server/src/pathext.rs +++ b/server/src/pathext.rs @@ -24,4 +24,4 @@ where } else { root.join(value) } -} +} \ No newline at end of file diff --git a/server/src/project.rs b/server/src/project.rs index b0b95de7..b0a39e5a 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -1,246 +1,223 @@ -use std::collections::HashMap; -use std::fmt; -use std::fs::{self, File}; -use std::io::{Read, Write}; -use std::path::{Path, PathBuf}; - -use rand::{self, Rng}; - +use std::{ + collections::HashMap, + fmt, + fs, + io, + path::{Path, PathBuf}, +}; use serde_json; -use partition::Partition; +pub static PROJECT_FILENAME: &'static str = "roblox-project.json"; -pub static PROJECT_FILENAME: &'static str = "rojo.json"; +#[derive(Debug, Serialize, Deserialize)] +#[serde(untagged)] +enum SourceProjectNode { + Regular { + #[serde(rename = "$className")] + class_name: String, -#[derive(Debug)] -pub enum ProjectLoadError { - DidNotExist(PathBuf), - FailedToOpen(PathBuf), - FailedToRead(PathBuf), - InvalidJson(PathBuf, serde_json::Error), + // #[serde(rename = "$ignoreUnknown", default = "false")] + // ignore_unknown: bool, + + #[serde(flatten)] + children: HashMap, + }, + SyncPoint { + #[serde(rename = "$path")] + path: String, + } } -impl fmt::Display for ProjectLoadError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { +impl SourceProjectNode { + pub fn into_project_node(self, project_file_location: &Path) -> ProjectNode { match self { - &ProjectLoadError::InvalidJson(ref project_path, ref serde_err) => { - write!(f, "Found invalid JSON reading project: {}\nError: {}", project_path.display(), serde_err) + SourceProjectNode::Regular { class_name, mut children } => { + let mut new_children = HashMap::new(); + + for (node_name, node) in children.drain() { + new_children.insert(node_name, node.into_project_node(project_file_location)); + } + + ProjectNode::Regular { + class_name, + children: new_children, + } }, - &ProjectLoadError::FailedToOpen(ref project_path) | - &ProjectLoadError::FailedToRead(ref project_path) => { - write!(f, "Found project file, but failed to read it: {}", project_path.display()) - }, - &ProjectLoadError::DidNotExist(ref project_path) => { - write!(f, "Could not locate a project file at {}.\nUse 'rojo init' to create one.", project_path.display()) - }, - } - } -} + SourceProjectNode::SyncPoint { path: source_path } => { + let path = if Path::new(&source_path).is_absolute() { + PathBuf::from(source_path) + } else { + let project_folder_location = project_file_location.parent().unwrap(); + project_folder_location.join(source_path) + }; -#[derive(Debug)] -pub enum ProjectSaveError { - FailedToCreate, -} - -#[derive(Debug)] -pub enum ProjectInitError { - AlreadyExists, - FailedToCreate, - FailedToWrite, -} - -impl fmt::Display for ProjectInitError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - &ProjectInitError::AlreadyExists => { - write!(f, "A project already exists at that location.") - }, - &ProjectInitError::FailedToCreate | - &ProjectInitError::FailedToWrite => { - write!(f, "Failed to write to the given location.") - }, - } - } -} - -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SourceProjectPartition { - /// A slash-separated path to a file or folder, relative to the project's - /// directory. - pub path: String, - - /// A dot-separated route to a Roblox instance, relative to game. - pub target: String, -} - -/// Represents a Rojo project in the format that's most convenient for users to -/// edit. This should generally line up with `Project`, but can diverge when -/// there's either compatibility shims or when the data structures that Rojo -/// want are too verbose to write in JSON but easy to convert from something -/// else. -// -/// Holds anything that can be configured with `rojo.json`. -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(default, rename_all = "camelCase")] -pub struct SourceProject { - pub name: String, - pub serve_port: u64, - pub partitions: HashMap, -} - -impl Default for SourceProject { - fn default() -> SourceProject { - SourceProject { - name: "new-project".to_string(), - serve_port: 8000, - partitions: HashMap::new(), - } - } -} - -/// Represents a Rojo project in the format that's convenient for Rojo to work -/// with. -#[derive(Debug, Clone)] -pub struct Project { - /// The path to the project file that this project is associated with. - pub project_path: PathBuf, - - /// The name of this project, used for user-facing labels. - pub name: String, - - /// The port that this project will run a web server on. - pub serve_port: u64, - - /// All of the project's partitions, laid out in an expanded way. - pub partitions: HashMap, -} - -impl Project { - fn from_source_project(source_project: SourceProject, project_path: PathBuf) -> Project { - let mut partitions = HashMap::new(); - - { - let project_directory = project_path.parent().unwrap(); - - for (partition_name, partition) in source_project.partitions.into_iter() { - let path = project_directory.join(&partition.path); - let target = partition.target - .split(".") - .map(String::from) - .collect::>(); - - partitions.insert(partition_name.clone(), Partition { + ProjectNode::SyncPoint { path, - target, - name: partition_name, - }); - } + } + }, + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct SourceProject { + name: String, + tree: HashMap, +} + +impl SourceProject { + pub fn into_project(mut self, project_file_location: &Path) -> Project { + let mut tree = HashMap::new(); + + for (node_name, node) in self.tree.drain() { + tree.insert(node_name, node.into_project_node(project_file_location)); } Project { - project_path, - name: source_project.name, - serve_port: source_project.serve_port, - partitions, + name: self.name, + tree: tree, + file_location: PathBuf::from(project_file_location), } } - - fn as_source_project(&self) -> SourceProject { - let mut partitions = HashMap::new(); - - for partition in self.partitions.values() { - let path = partition.path.strip_prefix(&self.project_path) - .unwrap_or_else(|_| &partition.path) - .to_str() - .unwrap() - .to_string(); - - let target = partition.target.join("."); - - partitions.insert(partition.name.clone(), SourceProjectPartition { - path, - target, - }); - } - - SourceProject { - partitions, - name: self.name.clone(), - serve_port: self.serve_port, - } - } - - /// Initializes a new project inside the given folder path. - pub fn init>(location: T) -> Result { - let location = location.as_ref(); - let project_path = location.join(PROJECT_FILENAME); - - // We abort if the project file already exists. - fs::metadata(&project_path) - .map_err(|_| ProjectInitError::AlreadyExists)?; - - let mut file = File::create(&project_path) - .map_err(|_| ProjectInitError::FailedToCreate)?; - - // Try to give the project a meaningful name. - // If we can't, we'll just fall back to a default. - let name = match location.file_name() { - Some(v) => v.to_string_lossy().into_owned(), - None => "new-project".to_string(), - }; - - // Generate a random port to run the server on. - let serve_port = rand::thread_rng().gen_range(2000, 49151); - - // Configure the project with all of the values we know so far. - let source_project = SourceProject { - name, - serve_port, - partitions: HashMap::new(), - }; - let serialized = serde_json::to_string_pretty(&source_project).unwrap(); - - file.write(serialized.as_bytes()) - .map_err(|_| ProjectInitError::FailedToWrite)?; - - Ok(Project::from_source_project(source_project, project_path)) - } - - /// Attempts to load a project from the file named PROJECT_FILENAME from the - /// given folder. - pub fn load>(location: T) -> Result { - let project_path = location.as_ref().join(Path::new(PROJECT_FILENAME)); - - fs::metadata(&project_path) - .map_err(|_| ProjectLoadError::DidNotExist(project_path.clone()))?; - - let mut file = File::open(&project_path) - .map_err(|_| ProjectLoadError::FailedToOpen(project_path.clone()))?; - - let mut contents = String::new(); - - file.read_to_string(&mut contents) - .map_err(|_| ProjectLoadError::FailedToRead(project_path.clone()))?; - - let source_project = serde_json::from_str(&contents) - .map_err(|e| ProjectLoadError::InvalidJson(project_path.clone(), e))?; - - Ok(Project::from_source_project(source_project, project_path)) - } - - /// Saves the given project file to the given folder with the appropriate name. - pub fn save>(&self, location: T) -> Result<(), ProjectSaveError> { - let project_path = location.as_ref().join(Path::new(PROJECT_FILENAME)); - - let mut file = File::create(&project_path) - .map_err(|_| ProjectSaveError::FailedToCreate)?; - - let source_project = self.as_source_project(); - let serialized = serde_json::to_string_pretty(&source_project).unwrap(); - - file.write(serialized.as_bytes()).unwrap(); - - Ok(()) - } } + +#[derive(Debug)] +pub enum ProjectLoadExactError { + IoError(io::Error), + JsonError(serde_json::Error), +} + +impl fmt::Display for ProjectLoadExactError { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + match self { + ProjectLoadExactError::IoError(inner) => write!(output, "{}", inner), + ProjectLoadExactError::JsonError(inner) => write!(output, "{}", inner), + } + } +} + +#[derive(Debug)] +pub enum ProjectInitError {} + +impl fmt::Display for ProjectInitError { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + write!(output, "ProjectInitError") + } +} + +#[derive(Debug)] +pub enum ProjectLoadFuzzyError { + NotFound, + IoError(io::Error), + JsonError(serde_json::Error), +} + +impl From for ProjectLoadFuzzyError { + fn from(error: ProjectLoadExactError) -> ProjectLoadFuzzyError { + match error { + ProjectLoadExactError::IoError(inner) => ProjectLoadFuzzyError::IoError(inner), + ProjectLoadExactError::JsonError(inner) => ProjectLoadFuzzyError::JsonError(inner), + } + } +} + +impl fmt::Display for ProjectLoadFuzzyError { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + match self { + ProjectLoadFuzzyError::NotFound => write!(output, "Project not found."), + ProjectLoadFuzzyError::IoError(inner) => write!(output, "{}", inner), + ProjectLoadFuzzyError::JsonError(inner) => write!(output, "{}", inner), + } + } +} + +#[derive(Debug)] +pub enum ProjectSaveError {} + +impl fmt::Display for ProjectSaveError { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + write!(output, "ProjectSaveError") + } +} + +#[derive(Debug)] +pub enum ProjectNode { + Regular { + class_name: String, + children: HashMap, + + // ignore_unknown: bool, + }, + SyncPoint { + path: PathBuf, + }, +} + +#[derive(Debug)] +pub struct Project { + pub name: String, + pub tree: HashMap, + pub file_location: PathBuf, +} + +impl Project { + pub fn init(_project_folder_location: &Path) -> Result<(), ProjectInitError> { + unimplemented!(); + } + + pub fn locate(start_location: &Path) -> Option { + // TODO: Check for specific error kinds, convert 'not found' to Result. + let location_metadata = fs::metadata(start_location).ok()?; + + // If this is a file, we should assume it's the config we want + if location_metadata.is_file() { + return Some(start_location.to_path_buf()); + } else if location_metadata.is_dir() { + let with_file = start_location.join(PROJECT_FILENAME); + + match fs::metadata(&with_file) { + Ok(with_file_metadata) => { + if with_file_metadata.is_file() { + return Some(with_file); + } else { + return None; + } + }, + Err(_) => {}, + } + } + + match start_location.parent() { + Some(parent_location) => Self::locate(parent_location), + None => None, + } + } + + pub fn load_fuzzy(fuzzy_project_location: &Path) -> Result { + let project_path = Self::locate(fuzzy_project_location) + .ok_or(ProjectLoadFuzzyError::NotFound)?; + + Self::load_exact(&project_path).map_err(From::from) + } + + pub fn load_exact(project_file_location: &Path) -> Result { + let contents = fs::read_to_string(project_file_location) + .map_err(ProjectLoadExactError::IoError)?; + + let parsed: SourceProject = serde_json::from_str(&contents) + .map_err(ProjectLoadExactError::JsonError)?; + + Ok(parsed.into_project(project_file_location)) + } + + pub fn save(&self) -> Result<(), ProjectSaveError> { + let _source_project = self.to_source_project(); + + unimplemented!(); + } + + fn to_source_project(&self) -> SourceProject { + unimplemented!(); + } +} \ No newline at end of file diff --git a/server/src/rbx.rs b/server/src/rbx.rs index e3437f3c..d3873cb7 100644 --- a/server/src/rbx.rs +++ b/server/src/rbx.rs @@ -1,7 +1,6 @@ -use std::borrow::Cow; use std::collections::HashMap; -use id::Id; +use id::{Id, get_id}; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] @@ -23,46 +22,107 @@ pub struct RbxInstance { /// Contains all other properties of an Instance. pub properties: HashMap, + /// The unique ID of the instance + id: Id, + /// All of the children of this instance. Order is relevant to preserve! - pub children: Vec, + children: Vec, /// The parent of the instance, if there is one. - pub parent: Option, + parent: Option, } -// This seems like a really bad idea? -// Why isn't there a blanket impl for this for all T? -impl<'a> From<&'a RbxInstance> for Cow<'a, RbxInstance> { - fn from(instance: &'a RbxInstance) -> Cow<'a, RbxInstance> { - Cow::Borrowed(instance) +impl RbxInstance { + pub fn get_id(&self) -> Id { + self.id + } +} + +pub struct Descendants<'a> { + tree: &'a RbxTree, + ids_to_visit: Vec, +} + +impl<'a> Iterator for Descendants<'a> { + type Item = &'a RbxInstance; + + fn next(&mut self) -> Option { + loop { + let id = match self.ids_to_visit.pop() { + Some(id) => id, + None => break, + }; + + match self.tree.get_instance(id) { + Some(instance) => { + for child_id in &instance.children { + self.ids_to_visit.push(*child_id); + } + + return Some(instance); + }, + None => continue, + } + } + + None } } pub struct RbxTree { instances: HashMap, + pub root_instance_id: Id, } impl RbxTree { pub fn new() -> RbxTree { + let root_instance_id = get_id(); + let root_instance = RbxInstance { + name: "game".to_string(), + class_name: "DataModel".to_string(), + properties: HashMap::new(), + id: root_instance_id, + children: Vec::new(), + parent: None, + }; + + let mut instances = HashMap::new(); + instances.insert(root_instance_id, root_instance); + RbxTree { - instances: HashMap::new(), + instances, + root_instance_id, } } + pub fn get_instance(&self, id: Id) -> Option<&RbxInstance> { + self.instances.get(&id) + } + pub fn get_all_instances(&self) -> &HashMap { &self.instances } - pub fn insert_instance(&mut self, id: Id, instance: RbxInstance) { - if let Some(parent_id) = instance.parent { - if let Some(mut parent) = self.instances.get_mut(&parent_id) { - if !parent.children.contains(&id) { - parent.children.push(id); + pub fn insert_instance(&mut self, mut instance: RbxInstance) { + match instance.parent { + Some(parent_id) => { + match self.instances.get_mut(&parent_id) { + Some(mut parent) => { + if !parent.children.contains(&instance.id) { + parent.children.push(instance.id); + } + }, + None => { + panic!("Tree consistency error, parent {} was not present in tree.", parent_id); + } } - } + }, + None => { + instance.parent = Some(self.root_instance_id); + }, } - self.instances.insert(id, instance); + self.instances.insert(instance.id, instance); } pub fn delete_instance(&mut self, id: Id) -> Vec { @@ -101,27 +161,20 @@ impl RbxTree { ids_deleted } - pub fn get_instance_and_descendants<'a, 'b, T>(&'a self, id: Id, output: &'b mut HashMap) - where T: From<&'a RbxInstance> - { - let mut ids_to_visit = vec![id]; - - loop { - let id = match ids_to_visit.pop() { - Some(id) => id, - None => break, - }; - - match self.instances.get(&id) { - Some(instance) => { - output.insert(id, instance.into()); - - for child_id in &instance.children { - ids_to_visit.push(*child_id); - } - }, - None => continue, - } + pub fn iter_descendants<'a>(&'a self, id: Id) -> Descendants<'a> { + match self.get_instance(id) { + Some(instance) => { + Descendants { + tree: self, + ids_to_visit: instance.children.clone(), + } + }, + None => { + Descendants { + tree: self, + ids_to_visit: vec![], + } + }, } } -} +} \ No newline at end of file diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs deleted file mode 100644 index 0abd25e8..00000000 --- a/server/src/rbx_session.rs +++ /dev/null @@ -1,306 +0,0 @@ -use std::collections::HashMap; -use std::sync::{Arc, RwLock}; - -use file_route::FileRoute; -use id::{Id, get_id}; -use message_session::{Message, MessageSession}; -use partition::Partition; -use project::Project; -use rbx::{RbxInstance, RbxTree, RbxValue}; -use vfs_session::{VfsSession, FileItem, FileChange}; - -static SERVICES: &'static [&'static str] = &[ - "Chat", - "Lighting", - "LocalizationService", - "Players", - "ReplicatedFirst", - "ReplicatedStorage", - "ServerScriptService", - "ServerStorage", - "SoundService", - "StarterGui", - "StarterPack", - "StarterPlayer", - "TestService", - "Workspace", -]; - -fn get_partition_target_class_name(target: &[String]) -> &'static str { - match target.len() { - 1 => { - let target_name = &target[0]; - - for &service in SERVICES { - if service == target_name { - return service; - } - } - - "Folder" - }, - 2 => { - "Folder" - }, - _ => "Folder", - } -} - -// TODO: Rethink data structure and insertion/update behavior. Maybe break some -// pieces off into a new object? -fn file_to_instances( - file_item: &FileItem, - partition: &Partition, - tree: &mut RbxTree, - instances_by_route: &mut HashMap, - parent_id: Option, -) -> (Id, Vec) { - match file_item { - FileItem::File { contents, route } => { - let primary_id = match instances_by_route.get(&file_item.get_route()) { - Some(&id) => id, - None => { - let id = get_id(); - instances_by_route.insert(route.clone(), id); - - id - }, - }; - - // This is placeholder logic; this whole function is! - let (class_name, property_key, name) = { - let file_name = match route.route.last() { - Some(v) => v.to_string(), - None => partition.path.file_name().unwrap().to_str().unwrap().to_string() - }; - - let use_partition_name = route.route.len() == 0; - - let partition_name = partition.target.last().unwrap(); - - fn strip_suffix<'a>(source: &'a str, suffix: &'static str) -> String { - source[..source.len() - suffix.len()].to_string() - } - - if file_name.ends_with(".client.lua") { - let name = if use_partition_name { - partition_name.clone() - } else { - strip_suffix(&file_name, ".client.lua") - }; - - ("LocalScript", "Source", name) - } else if file_name.ends_with(".server.lua") { - let name = if use_partition_name { - partition_name.clone() - } else { - strip_suffix(&file_name, ".server.lua") - }; - - ("Script", "Source", name) - } else if file_name.ends_with(".lua") { - let name = if use_partition_name { - partition_name.clone() - } else { - strip_suffix(&file_name, ".lua") - }; - - ("ModuleScript", "Source", name) - } else { - let name = if use_partition_name { - partition_name.clone() - } else { - file_name - }; - - // TODO: Error/warn/skip instead of falling back - ("StringValue", "Value", name) - } - }; - - let mut properties = HashMap::new(); - properties.insert(property_key.to_string(), RbxValue::String { value: contents.clone() }); - - tree.insert_instance(primary_id, RbxInstance { - name, - class_name: class_name.to_string(), - properties, - children: Vec::new(), - parent: parent_id, - }); - - (primary_id, vec![primary_id]) - }, - FileItem::Directory { children, route } => { - let primary_id = match instances_by_route.get(&file_item.get_route()) { - Some(&id) => id, - None => { - let id = get_id(); - instances_by_route.insert(route.clone(), id); - - id - }, - }; - - let mut child_ids = Vec::new(); - - let mut changed_ids = vec![primary_id]; - - for child_file_item in children.values() { - let (child_id, mut child_changed_ids) = file_to_instances(child_file_item, partition, tree, instances_by_route, Some(primary_id)); - - child_ids.push(child_id); - changed_ids.push(child_id); - - // TODO: Should I stop using drain on Vecs of Copyable types? - for id in child_changed_ids.drain(..) { - changed_ids.push(id); - } - } - - let class_name = get_partition_target_class_name(&route.route).to_string(); - - let name = if route.route.len() == 0 { - partition.target.last().unwrap().clone() - } else { - route.file_name(partition) - }; - - tree.insert_instance(primary_id, RbxInstance { - name, - class_name, - properties: HashMap::new(), - children: child_ids, - parent: parent_id, - }); - - (primary_id, changed_ids) - }, - } -} - -pub struct RbxSession { - project: Project, - - vfs_session: Arc>, - - message_session: MessageSession, - - /// The RbxInstance that represents each partition. - // TODO: Can this be removed in favor of instances_by_route? - pub partition_instances: HashMap, - - /// Keeps track of all of the instances in the tree - pub tree: RbxTree, - - /// A map from files in the VFS to instances loaded in the session. - instances_by_route: HashMap, -} - -impl RbxSession { - pub fn new(project: Project, vfs_session: Arc>, message_session: MessageSession) -> RbxSession { - RbxSession { - project, - vfs_session, - message_session, - partition_instances: HashMap::new(), - tree: RbxTree::new(), - instances_by_route: HashMap::new(), - } - } - - pub fn read_partitions(&mut self) { - let vfs_session_arc = self.vfs_session.clone(); - let vfs_session = vfs_session_arc.read().unwrap(); - - for partition in self.project.partitions.values() { - let route = FileRoute { - partition: partition.name.clone(), - route: Vec::new(), - }; - let file_item = vfs_session.get_by_route(&route).unwrap(); - - let parent_id = match route.parent() { - Some(parent_route) => match self.instances_by_route.get(&parent_route) { - Some(&parent_id) => Some(parent_id), - None => None, - }, - None => None, - }; - - let (root_id, _) = file_to_instances(file_item, partition, &mut self.tree, &mut self.instances_by_route, parent_id); - - self.partition_instances.insert(partition.name.clone(), root_id); - } - } - - pub fn handle_change(&mut self, change: &FileChange) { - let vfs_session_arc = self.vfs_session.clone(); - let vfs_session = vfs_session_arc.read().unwrap(); - - match change { - FileChange::Created(route) | FileChange::Updated(route) => { - let file_item = vfs_session.get_by_route(route).unwrap(); - let partition = self.project.partitions.get(&route.partition).unwrap(); - - let parent_id = match route.parent() { - Some(parent_route) => match self.instances_by_route.get(&parent_route) { - Some(&parent_id) => Some(parent_id), - None => None, - }, - None => None, - }; - - let (_, changed_ids) = file_to_instances(file_item, partition, &mut self.tree, &mut self.instances_by_route, parent_id); - - let messages = changed_ids - .iter() - .map(|&id| Message::InstanceChanged { id }) - .collect::>(); - - self.message_session.push_messages(&messages); - }, - FileChange::Deleted(route) => { - match self.instances_by_route.get(route) { - Some(&id) => { - self.tree.delete_instance(id); - self.instances_by_route.remove(route); - self.message_session.push_messages(&[Message::InstanceChanged { id }]); - }, - None => (), - } - }, - FileChange::Moved(from_route, to_route) => { - let mut messages = Vec::new(); - - match self.instances_by_route.get(from_route) { - Some(&id) => { - self.tree.delete_instance(id); - self.instances_by_route.remove(from_route); - messages.push(Message::InstanceChanged { id }); - }, - None => (), - } - - let file_item = vfs_session.get_by_route(to_route).unwrap(); - let partition = self.project.partitions.get(&to_route.partition).unwrap(); - - let parent_id = match to_route.parent() { - Some(parent_route) => match self.instances_by_route.get(&parent_route) { - Some(&parent_id) => Some(parent_id), - None => None, - }, - None => None, - }; - - let (_, changed_ids) = file_to_instances(file_item, partition, &mut self.tree, &mut self.instances_by_route, parent_id); - - for id in changed_ids { - messages.push(Message::InstanceChanged { id }); - } - - self.message_session.push_messages(&messages); - }, - } - } -} diff --git a/server/src/session.rs b/server/src/session.rs index 55341bb3..b1e9c7c8 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -1,95 +1,121 @@ -use std::sync::{mpsc, Arc, RwLock}; -use std::thread; +use std::{ + sync::{Arc, RwLock, Mutex, mpsc}, + thread, + io, + time::Duration, +}; -use message_session::MessageSession; -use partition_watcher::PartitionWatcher; -use project::Project; -use rbx_session::RbxSession; -use vfs_session::VfsSession; +use rand; -/// Stub trait for middleware -trait Middleware { -} +use notify::{ + self, + DebouncedEvent, + RecommendedWatcher, + RecursiveMode, + Watcher, +}; + +use ::{ + message_queue::MessageQueue, + rbx::RbxTree, + project::{Project, ProjectNode}, + vfs::Vfs, +}; + +const WATCH_TIMEOUT_MS: u64 = 100; pub struct Session { - pub project: Project, - vfs_session: Arc>, - rbx_session: Arc>, - message_session: MessageSession, - watchers: Vec, + project: Project, + pub session_id: String, + pub message_queue: Arc, + pub tree: Arc>, + vfs: Arc>, + watchers: Vec, } impl Session { pub fn new(project: Project) -> Session { - let message_session = MessageSession::new(); - let vfs_session = Arc::new(RwLock::new(VfsSession::new(project.clone()))); - let rbx_session = Arc::new(RwLock::new(RbxSession::new(project.clone(), vfs_session.clone(), message_session.clone()))); + let session_id = rand::random::().to_string(); Session { - vfs_session, - rbx_session, - watchers: Vec::new(), - message_session, + session_id, project, + message_queue: Arc::new(MessageQueue::new()), + tree: Arc::new(RwLock::new(RbxTree::new())), + vfs: Arc::new(Mutex::new(Vfs::new())), + watchers: Vec::new(), } } - pub fn start(&mut self) { - { - let mut vfs_session = self.vfs_session.write().unwrap(); - vfs_session.read_partitions(); - } - - { - let mut rbx_session = self.rbx_session.write().unwrap(); - rbx_session.read_partitions(); - } - - let (tx, rx) = mpsc::channel(); - - for partition in self.project.partitions.values() { - let watcher = PartitionWatcher::start_new(partition.clone(), tx.clone()); - - self.watchers.push(watcher); - } - - { - let vfs_session = self.vfs_session.clone(); - let rbx_session = self.rbx_session.clone(); - - thread::spawn(move || { - loop { - match rx.recv() { - Ok(change) => { - { - let mut vfs_session = vfs_session.write().unwrap(); - vfs_session.handle_change(&change); - } - - { - let mut rbx_session = rbx_session.write().unwrap(); - rbx_session.handle_change(&change); - } - }, - Err(_) => break, + pub fn start(&mut self) -> io::Result<()> { + fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> { + match project_node { + ProjectNode::Regular { children, .. } => { + for child in children.values() { + add_sync_points(vfs, child)?; } - } - }); + }, + ProjectNode::SyncPoint { path } => { + vfs.add_root(path)?; + }, + } + + Ok(()) } + + { + let mut vfs = self.vfs.lock().unwrap(); + + for child in self.project.tree.values() { + add_sync_points(&mut vfs, child)?; + } + + for root in vfs.get_roots() { + println!("Watching {}", root.display()); + + let (watch_tx, watch_rx) = mpsc::channel(); + + let mut watcher = notify::watcher(watch_tx, Duration::from_millis(WATCH_TIMEOUT_MS)).unwrap(); + + watcher.watch(root, RecursiveMode::Recursive).unwrap(); + self.watchers.push(watcher); + + let vfs = Arc::clone(&self.vfs); + + thread::spawn(move || { + println!("Thread started"); + loop { + match watch_rx.recv() { + Ok(event) => { + match event { + DebouncedEvent::Create(path) | DebouncedEvent::Write(path) => { + let mut vfs = vfs.lock().unwrap(); + vfs.add_or_update(&path).unwrap(); + }, + DebouncedEvent::Remove(path) => { + let mut vfs = vfs.lock().unwrap(); + vfs.remove(&path); + }, + DebouncedEvent::Rename(from_path, to_path) => { + let mut vfs = vfs.lock().unwrap(); + vfs.remove(&from_path); + vfs.add_or_update(&to_path).unwrap(); + }, + _ => continue, + }; + }, + Err(_) => break, + }; + } + println!("Thread stopped"); + }); + } + } + + Ok(()) } - pub fn stop(self) { + pub fn get_project(&self) -> &Project { + &self.project } - - pub fn get_vfs_session(&self) -> Arc> { - self.vfs_session.clone() - } - - pub fn get_rbx_session(&self) -> Arc> { - self.rbx_session.clone() - } - - pub fn get_message_session(&self) -> MessageSession { - self.message_session.clone() - } -} +} \ No newline at end of file diff --git a/server/src/vfs.rs b/server/src/vfs.rs new file mode 100644 index 00000000..7ac6e0f4 --- /dev/null +++ b/server/src/vfs.rs @@ -0,0 +1,139 @@ +use std::{ + collections::{HashMap, HashSet}, + path::{Path, PathBuf}, + fs, + io, +}; + +#[derive(Debug)] +pub struct Vfs { + contents: HashMap>, + items: HashMap, + roots: HashSet, +} + +impl Vfs { + pub fn new() -> Vfs { + Vfs { + contents: HashMap::new(), + items: HashMap::new(), + roots: HashSet::new(), + } + } + + pub fn add_root<'a, 'b>(&'a mut self, root_path: &'b Path) -> io::Result<&'a VfsItem> { + debug_assert!(root_path.is_absolute()); + + self.roots.insert(root_path.to_path_buf()); + + VfsItem::get(self, root_path) + } + + pub fn get_roots(&self) -> &HashSet { + &self.roots + } + + pub fn get(&mut self, path: &Path) -> Option<&VfsItem> { + debug_assert!(path.is_absolute()); + debug_assert!(self.is_valid_path(path)); + + self.items.get(path) + } + + pub fn remove(&mut self, path: &Path) { + debug_assert!(path.is_absolute()); + debug_assert!(self.is_valid_path(path)); + + match self.items.remove(path) { + Some(item) => match item { + VfsItem::File(_) => { + self.contents.remove(path); + }, + VfsItem::Directory(VfsDirectory { children, .. }) => { + for child_path in &children { + self.remove(child_path); + } + }, + }, + None => {}, + } + } + + pub fn add_or_update<'a, 'b>(&'a mut self, path: &'b Path) -> io::Result<&'a VfsItem> { + debug_assert!(path.is_absolute()); + debug_assert!(self.is_valid_path(path)); + + VfsItem::get(self, path) + } + + fn is_valid_path(&self, path: &Path) -> bool { + let mut is_valid_path = false; + + for root_path in &self.roots { + if path.starts_with(root_path) { + is_valid_path = true; + break; + } + } + + is_valid_path + } +} + +#[derive(Debug)] +pub struct VfsFile { + path: PathBuf, +} + +#[derive(Debug)] +pub struct VfsDirectory { + path: PathBuf, + children: HashSet, +} + +#[derive(Debug)] +pub enum VfsItem { + File(VfsFile), + Directory(VfsDirectory), +} + +impl VfsItem { + fn get<'a, 'b>(vfs: &'a mut Vfs, root_path: &'b Path) -> io::Result<&'a VfsItem> { + let metadata = fs::metadata(root_path)?; + + if metadata.is_file() { + let item = VfsItem::File(VfsFile { + path: root_path.to_path_buf(), + }); + + vfs.items.insert(root_path.to_path_buf(), item); + + let contents = fs::read(root_path)?; + vfs.contents.insert(root_path.to_path_buf(), contents); + + Ok(vfs.items.get(root_path).unwrap()) + } else if metadata.is_dir() { + let mut children = HashSet::new(); + + for entry in fs::read_dir(root_path)? { + let entry = entry?; + let path = entry.path(); + + VfsItem::get(vfs, &path)?; + + children.insert(path); + } + + let item = VfsItem::Directory(VfsDirectory { + path: root_path.to_path_buf(), + children, + }); + + vfs.items.insert(root_path.to_path_buf(), item); + + Ok(vfs.items.get(root_path).unwrap()) + } else { + unimplemented!(); + } + } +} \ No newline at end of file diff --git a/server/src/vfs_session.rs b/server/src/vfs_session.rs deleted file mode 100644 index c4dc3e0b..00000000 --- a/server/src/vfs_session.rs +++ /dev/null @@ -1,242 +0,0 @@ -use std::collections::HashMap; -use std::io::Read; -use std::fs::{self, File}; -use std::mem; - -use file_route::FileRoute; -use project::Project; - -/// Represents a file or directory that has been read from the filesystem. -#[derive(Debug, Clone)] -pub enum FileItem { - File { - contents: String, - route: FileRoute, - }, - Directory { - children: HashMap, - route: FileRoute, - }, -} - -impl FileItem { - pub fn get_route(&self) -> &FileRoute { - match self { - FileItem::File { route, .. } => route, - FileItem::Directory { route, .. } => route, - } - } -} - -#[derive(Debug, Clone)] -pub enum FileChange { - Created(FileRoute), - Deleted(FileRoute), - Updated(FileRoute), - Moved(FileRoute, FileRoute), -} - -pub struct VfsSession { - pub project: Project, - - /// The in-memory files associated with each partition. - pub partition_files: HashMap, -} - -impl VfsSession { - pub fn new(project: Project) -> VfsSession { - VfsSession { - project, - partition_files: HashMap::new(), - } - } - - pub fn read_partitions(&mut self) { - for partition_name in self.project.partitions.keys() { - let route = FileRoute { - partition: partition_name.clone(), - route: Vec::new(), - }; - - let file_item = self.read(&route).expect("Couldn't load partitions"); - - self.partition_files.insert(partition_name.clone(), file_item); - } - } - - pub fn handle_change(&mut self, change: &FileChange) -> Option<()> { - match change { - FileChange::Created(route) | FileChange::Updated(route) => { - let new_item = self.read(&route).ok()?; - self.set_file_item(new_item); - }, - FileChange::Deleted(route) => { - self.delete_route(&route); - }, - FileChange::Moved(from_route, to_route) => { - let new_item = self.read(&to_route).ok()?; - self.delete_route(&from_route); - self.set_file_item(new_item); - }, - } - - None - } - - pub fn get_by_route(&self, route: &FileRoute) -> Option<&FileItem> { - let partition = self.partition_files.get(&route.partition)?; - let mut current = partition; - - for piece in &route.route { - match current { - FileItem::File { .. } => return None, - FileItem::Directory { children, .. } => { - current = children.get(piece)?; - }, - } - } - - Some(current) - } - - pub fn get_by_route_mut(&mut self, route: &FileRoute) -> Option<&mut FileItem> { - let mut current = self.partition_files.get_mut(&route.partition)?; - - for piece in &route.route { - let mut next = match { current } { - FileItem::File { .. } => return None, - FileItem::Directory { children, .. } => { - children.get_mut(piece)? - }, - }; - - current = next; - } - - Some(current) - } - - pub fn set_file_item(&mut self, item: FileItem) { - match self.get_by_route_mut(item.get_route()) { - Some(existing) => { - mem::replace(existing, item); - return; - }, - None => {}, - } - - if item.get_route().route.len() > 0 { - let mut parent_route = item.get_route().clone(); - let child_name = parent_route.route.pop().unwrap(); - - let mut parent_children = HashMap::new(); - parent_children.insert(child_name, item); - - let parent_item = FileItem::Directory { - route: parent_route, - children: parent_children, - }; - - self.set_file_item(parent_item); - } else { - self.partition_files.insert(item.get_route().partition.clone(), item); - } - } - - pub fn delete_route(&mut self, route: &FileRoute) -> Option<()> { - if route.route.len() == 0 { - self.partition_files.remove(&route.partition); - return Some(()); - } - - let mut current = self.partition_files.get_mut(&route.partition)?; - - for i in 0..(route.route.len() - 1) { - let piece = &route.route[i]; - - let mut next = match { current } { - FileItem::File { .. } => return None, - FileItem::Directory { children, .. } => { - children.get_mut(piece)? - }, - }; - - current = next; - } - - match current { - FileItem::Directory { children, .. } => { - children.remove(route.route.last().unwrap().as_str()); - }, - _ => {}, - } - - Some(()) - } - - fn read(&self, route: &FileRoute) -> Result { - let partition_path = &self.project.partitions.get(&route.partition) - .ok_or(())?.path; - let path = route.to_path_buf(partition_path); - - let metadata = fs::metadata(path) - .map_err(|_| ())?; - - if metadata.is_dir() { - self.read_directory(route) - } else if metadata.is_file() { - self.read_file(route) - } else { - Err(()) - } - } - - fn read_file(&self, route: &FileRoute) -> Result { - let partition_path = &self.project.partitions.get(&route.partition) - .ok_or(())?.path; - let path = route.to_path_buf(partition_path); - - let mut file = File::open(path) - .map_err(|_| ())?; - - let mut contents = String::new(); - - file.read_to_string(&mut contents) - .map_err(|_| ())?; - - Ok(FileItem::File { - contents, - route: route.clone(), - }) - } - - fn read_directory(&self, route: &FileRoute) -> Result { - let partition_path = &self.project.partitions.get(&route.partition) - .ok_or(())?.path; - let path = route.to_path_buf(partition_path); - - let reader = fs::read_dir(path) - .map_err(|_| ())?; - - let mut children = HashMap::new(); - - for entry in reader { - let entry = entry - .map_err(|_| ())?; - - let path = entry.path(); - let name = path.file_name().unwrap().to_string_lossy().into_owned(); - - let child_route = route.extended_with(&[&name]); - - let child_item = self.read(&child_route)?; - - children.insert(name, child_item); - } - - Ok(FileItem::Directory { - children, - route: route.clone(), - }) - } -} diff --git a/server/src/web.rs b/server/src/web.rs index 2a5fefd4..5d312aa4 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -1,197 +1,152 @@ -use std::borrow::Cow; -use std::collections::HashMap; -use std::sync::{mpsc, RwLock, Arc}; +use std::{ + borrow::Cow, + collections::HashMap, + sync::{mpsc, Arc}, +}; use rouille::{self, Request, Response}; -use id::Id; -use message_session::{MessageSession, Message}; -use project::Project; -use rbx::RbxInstance; -use rbx_session::RbxSession; -use session::Session; - -/// The set of configuration the web server needs to start. -pub struct WebConfig { - pub port: u64, - pub project: Project, - pub server_id: u64, - pub rbx_session: Arc>, - pub message_session: MessageSession, -} - -impl WebConfig { - pub fn from_session(server_id: u64, port: u64, session: &Session) -> WebConfig { - WebConfig { - port, - server_id, - project: session.project.clone(), - rbx_session: session.get_rbx_session(), - message_session: session.get_message_session(), - } - } -} +use ::{ + id::Id, + message_queue::Message, + project::Project, + rbx::RbxInstance, + session::Session, +}; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ServerInfoResponse<'a> { - pub server_id: &'a str, + pub session_id: &'a str, pub server_version: &'a str, pub protocol_version: u64, - pub partitions: HashMap>, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ReadAllResponse<'a> { - pub server_id: &'a str, - pub message_cursor: i32, - pub instances: Cow<'a, HashMap>, - pub partition_instances: Cow<'a, HashMap>, + pub root_instance_id: Id, } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ReadResponse<'a> { - pub server_id: &'a str, - pub message_cursor: i32, + pub session_id: &'a str, + pub message_cursor: u32, pub instances: HashMap>, } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SubscribeResponse<'a> { - pub server_id: &'a str, - pub message_cursor: i32, + pub session_id: &'a str, + pub message_cursor: u32, pub messages: Cow<'a, [Message]>, } pub struct Server { - config: WebConfig, + session: Arc, server_version: &'static str, - server_id: String, } impl Server { - pub fn new(config: WebConfig) -> Server { + pub fn new(session: Arc) -> Server { Server { + session: session, server_version: env!("CARGO_PKG_VERSION"), - server_id: config.server_id.to_string(), - config, } } + #[allow(unreachable_code)] pub fn handle_request(&self, request: &Request) -> Response { router!(request, (GET) (/) => { - Response::text("Rojo up and running!") + Response::text("Rojo is up and running!") }, (GET) (/api/rojo) => { // Get a summary of information about the server. - let mut partitions = HashMap::new(); - - for partition in self.config.project.partitions.values() { - partitions.insert(partition.name.clone(), partition.target.clone()); - } + let tree = self.session.tree.read().unwrap(); Response::json(&ServerInfoResponse { server_version: self.server_version, protocol_version: 2, - server_id: &self.server_id, - partitions: partitions, + session_id: &self.session.session_id, + root_instance_id: tree.root_instance_id, }) }, - (GET) (/api/subscribe/{ cursor: i32 }) => { + (GET) (/api/subscribe/{ cursor: u32 }) => { // Retrieve any messages past the given cursor index, and if // there weren't any, subscribe to receive any new messages. + let message_queue = Arc::clone(&self.session.message_queue); + // Did the client miss any messages since the last subscribe? { - let messages = self.config.message_session.messages.read().unwrap(); + let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); - if cursor > messages.len() as i32 { + if new_messages.len() > 0 { return Response::json(&SubscribeResponse { - server_id: &self.server_id, + session_id: &self.session.session_id, messages: Cow::Borrowed(&[]), - message_cursor: messages.len() as i32 - 1, - }); - } - - if cursor < messages.len() as i32 - 1 { - let new_messages = &messages[(cursor + 1) as usize..]; - let new_cursor = cursor + new_messages.len() as i32; - - return Response::json(&SubscribeResponse { - server_id: &self.server_id, - messages: Cow::Borrowed(new_messages), message_cursor: new_cursor, - }); + }) } } let (tx, rx) = mpsc::channel(); - let sender_id = self.config.message_session.subscribe(tx); + let sender_id = message_queue.subscribe(tx); match rx.recv() { Ok(_) => (), Err(_) => return Response::text("error!").with_status_code(500), } - self.config.message_session.unsubscribe(sender_id); + message_queue.unsubscribe(sender_id); { - let messages = self.config.message_session.messages.read().unwrap(); - let new_messages = &messages[(cursor + 1) as usize..]; - let new_cursor = cursor + new_messages.len() as i32; + let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); - Response::json(&SubscribeResponse { - server_id: &self.server_id, - messages: Cow::Borrowed(new_messages), + return Response::json(&SubscribeResponse { + session_id: &self.session.session_id, + messages: Cow::Owned(new_messages), message_cursor: new_cursor, }) } }, - (GET) (/api/read_all) => { - let rbx_session = self.config.rbx_session.read().unwrap(); - - let message_cursor = self.config.message_session.get_message_cursor(); - - Response::json(&ReadAllResponse { - server_id: &self.server_id, - message_cursor, - instances: Cow::Borrowed(rbx_session.tree.get_all_instances()), - partition_instances: Cow::Borrowed(&rbx_session.partition_instances), - }) - }, - (GET) (/api/read/{ id_list: String }) => { - let requested_ids = id_list + let message_queue = Arc::clone(&self.session.message_queue); + + let requested_ids: Result, _> = id_list .split(",") - .map(str::parse::) - .collect::, _>>(); + .map(str::parse) + .collect(); let requested_ids = match requested_ids { - Ok(v) => v, + Ok(id) => id, Err(_) => return rouille::Response::text("Malformed ID list").with_status_code(400), }; - let rbx_session = self.config.rbx_session.read().unwrap(); + let tree = self.session.tree.read().unwrap(); - let message_cursor = self.config.message_session.get_message_cursor(); + let message_cursor = message_queue.get_message_cursor(); let mut instances = HashMap::new(); - for requested_id in &requested_ids { - rbx_session.tree.get_instance_and_descendants(*requested_id, &mut instances); + for &requested_id in &requested_ids { + match tree.get_instance(requested_id) { + Some(instance) => { + instances.insert(instance.get_id(), Cow::Borrowed(instance)); + + for descendant in tree.iter_descendants(requested_id) { + instances.insert(descendant.get_id(), Cow::Borrowed(descendant)); + } + }, + None => {}, + } } Response::json(&ReadResponse { - server_id: &self.server_id, + session_id: &self.session.session_id, message_cursor, instances, }) @@ -200,13 +155,10 @@ impl Server { _ => Response::empty_404() ) } -} -/// Start the Rojo web server, taking over the current thread. -#[allow(unreachable_code)] -pub fn start(config: WebConfig) { - let address = format!("localhost:{}", config.port); - let server = Server::new(config); + pub fn listen(self, port: u64) { + let address = format!("localhost:{}", port); - rouille::start_server(address, move |request| server.handle_request(request)); -} + rouille::start_server(address, move |request| self.handle_request(request)); + } +} \ No newline at end of file diff --git a/server/src/web_util.rs b/server/src/web_util.rs index 0c344e6c..a6aea450 100644 --- a/server/src/web_util.rs +++ b/server/src/web_util.rs @@ -40,4 +40,4 @@ where { let body = read_json_text(&request)?; serde_json::from_str(&body).ok()? -} +} \ No newline at end of file diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs new file mode 100644 index 00000000..05a85759 --- /dev/null +++ b/server/tests/read_projects.rs @@ -0,0 +1,36 @@ +#[macro_use] extern crate lazy_static; + +extern crate librojo; + +use std::{ + collections::HashMap, + path::{Path, PathBuf}, +}; + +use librojo::{ + project::Project, +}; + +lazy_static! { + static ref TEST_PROJECTS_ROOT: PathBuf = { + Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects") + }; +} + +#[test] +fn foo() { + let project_file_location = TEST_PROJECTS_ROOT.join("foo.json"); + let project = Project::load_exact(&project_file_location).unwrap(); + + assert_eq!(project.name, "foo"); + assert_eq!(project.tree.len(), 1); +} + +#[test] +fn empty() { + let project_file_location = TEST_PROJECTS_ROOT.join("empty/roblox-project.json"); + let project = Project::load_exact(&project_file_location).unwrap(); + + assert_eq!(project.name, "empty"); + assert_eq!(project.tree.len(), 0); +} \ No newline at end of file diff --git a/server/tests/web.rs b/server/tests/web.rs deleted file mode 100644 index c9ae6259..00000000 --- a/server/tests/web.rs +++ /dev/null @@ -1,483 +0,0 @@ -#[macro_use] extern crate lazy_static; - -extern crate rouille; -extern crate serde_json; -extern crate serde; -extern crate tempfile; -extern crate walkdir; - -extern crate librojo; - -mod test_util; -use test_util::*; - -use std::borrow::Cow; -use std::collections::HashMap; -use std::fs::{File, remove_file}; -use std::io::Write; -use std::path::PathBuf; - -use librojo::{ - session::Session, - project::Project, - web::{Server, WebConfig, ServerInfoResponse, ReadResponse, ReadAllResponse, SubscribeResponse}, - rbx::RbxValue, -}; - -lazy_static! { - static ref TEST_PROJECTS_ROOT: PathBuf = { - let mut path = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - path.push("../test-projects"); - path - }; -} - -#[test] -fn empty() { - let original_project_path = TEST_PROJECTS_ROOT.join("empty"); - - let project_tempdir = tempfile::tempdir().unwrap(); - let project_path = project_tempdir.path(); - - copy_recursive(&original_project_path, &project_path).unwrap(); - - let project = Project::load(&project_path).unwrap(); - let mut session = Session::new(project.clone()); - session.start(); - - let web_config = WebConfig::from_session(0, project.serve_port, &session); - let server = Server::new(web_config); - - { - let body = server.get_string("/api/rojo"); - let response = serde_json::from_str::(&body).unwrap(); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.protocol_version, 2); - assert_eq!(response.partitions.len(), 0); - } - - { - let body = server.get_string("/api/read_all"); - let response = serde_json::from_str::(&body).unwrap(); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.message_cursor, -1); - assert_eq!(response.instances.len(), 0); - } - - { - let body = server.get_string("/api/read/0"); - let response = serde_json::from_str::(&body).unwrap(); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.message_cursor, -1); - assert_eq!(response.instances.len(), 0); - } -} - -#[test] -fn one_partition() { - let original_project_path = TEST_PROJECTS_ROOT.join("one-partition"); - - let project_tempdir = tempfile::tempdir().unwrap(); - let project_path = project_tempdir.path(); - - copy_recursive(&original_project_path, &project_path).unwrap(); - - let project = Project::load(&project_path).unwrap(); - let mut session = Session::new(project.clone()); - session.start(); - - let web_config = WebConfig::from_session(0, project.serve_port, &session); - let server = Server::new(web_config); - - { - let body = server.get_string("/api/rojo"); - let response = serde_json::from_str::(&body).unwrap(); - - let mut partitions = HashMap::new(); - partitions.insert("lib".to_string(), vec!["ReplicatedStorage".to_string(), "OnePartition".to_string()]); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.protocol_version, 2); - assert_eq!(response.partitions, partitions); - } - - let initial_body = server.get_string("/api/read_all"); - let initial_response = { - let response = serde_json::from_str::(&initial_body).unwrap(); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.message_cursor, -1); - assert_eq!(response.instances.len(), 4); - - let partition_id = *response.partition_instances.get("lib").unwrap(); - - let mut root_id = None; - let mut module_id = None; - let mut client_id = None; - let mut server_id = None; - - for (id, instance) in response.instances.iter() { - match (instance.name.as_str(), instance.class_name.as_str()) { - // TOOD: Should partition roots (and other directories) be some - // magical object instead of Folder? - // TODO: Should this name actually equal the last part of the - // partition's target? - ("OnePartition", "Folder") => { - assert!(root_id.is_none()); - root_id = Some(*id); - - assert_eq!(*id, partition_id); - - assert_eq!(instance.properties.len(), 0); - assert_eq!(instance.parent, None); - assert_eq!(instance.children.len(), 3); - - let single_body = server.get_string(&format!("/api/read/{}", id)); - let single_response = serde_json::from_str::(&single_body).unwrap(); - - let single_instance = single_response.instances.get(id).unwrap(); - - assert_eq!(single_instance, &Cow::Borrowed(instance)); - }, - ("a", "ModuleScript") => { - assert!(module_id.is_none()); - module_id = Some(*id); - - let mut properties = HashMap::new(); - properties.insert("Source".to_string(), RbxValue::String { value: "-- a.lua".to_string() }); - - assert_eq!(instance.properties, properties); - assert_eq!(instance.parent, Some(partition_id)); - assert_eq!(instance.children.len(), 0); - - let single_body = server.get_string(&format!("/api/read/{}", id)); - let single_response = serde_json::from_str::(&single_body).unwrap(); - - let single_instance = single_response.instances.get(id).unwrap(); - - assert_eq!(single_instance, &Cow::Borrowed(instance)); - }, - ("b", "LocalScript") => { - assert!(client_id.is_none()); - client_id = Some(*id); - - let mut properties = HashMap::new(); - properties.insert("Source".to_string(), RbxValue::String { value: "-- b.client.lua".to_string() }); - - assert_eq!(instance.properties, properties); - assert_eq!(instance.parent, Some(partition_id)); - assert_eq!(instance.children.len(), 0); - - let single_body = server.get_string(&format!("/api/read/{}", id)); - let single_response = serde_json::from_str::(&single_body).unwrap(); - - let single_instance = single_response.instances.get(id).unwrap(); - - assert_eq!(single_instance, &Cow::Borrowed(instance)); - }, - ("a", "Script") => { - assert!(server_id.is_none()); - server_id = Some(*id); - - let mut properties = HashMap::new(); - properties.insert("Source".to_string(), RbxValue::String { value: "-- a.server.lua".to_string() }); - - assert_eq!(instance.properties, properties); - assert_eq!(instance.parent, Some(partition_id)); - assert_eq!(instance.children.len(), 0); - - let single_body = server.get_string(&format!("/api/read/{}", id)); - let single_response = serde_json::from_str::(&single_body).unwrap(); - - let single_instance = single_response.instances.get(id).unwrap(); - - assert_eq!(single_instance, &Cow::Borrowed(instance)); - }, - _ => { - panic!("Unexpected instance named {} of class {}", instance.name, instance.class_name); - }, - } - } - - let root_id = root_id.unwrap(); - let module_id = module_id.unwrap(); - let client_id = client_id.unwrap(); - let server_id = server_id.unwrap(); - - { - let root_instance = response.instances.get(&root_id).unwrap(); - - assert!(root_instance.children.contains(&module_id)); - assert!(root_instance.children.contains(&client_id)); - assert!(root_instance.children.contains(&server_id)); - } - - response - }; - - { - let temp_name = project_path.join("lib/c.client.lua"); - - { - let mut file = File::create(&temp_name).unwrap(); - file.write_all(b"-- c.client.lua").unwrap(); - } - - { - // Block until Rojo detects the addition of our temp file - let body = server.get_string("/api/subscribe/-1"); - let response = serde_json::from_str::(&body).unwrap(); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.message_cursor, 0); - assert_eq!(response.messages.len(), 1); - - // TODO: Read which instance was changed and try to access it with - // /read - } - - let body = server.get_string("/api/read_all"); - let response = serde_json::from_str::(&body).unwrap(); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.message_cursor, 0); - assert_eq!(response.instances.len(), 5); - - let partition_id = *response.partition_instances.get("lib").unwrap(); - - let mut root_id = None; - let mut module_id = None; - let mut client_id = None; - let mut server_id = None; - let mut new_id = None; - - for (id, instance) in response.instances.iter() { - match (instance.name.as_str(), instance.class_name.as_str()) { - // TOOD: Should partition roots (and other directories) be some - // magical object instead of Folder? - // TODO: Should this name actually equal the last part of the - // partition's target? - ("OnePartition", "Folder") => { - assert!(root_id.is_none()); - root_id = Some(*id); - - assert_eq!(*id, partition_id); - - assert_eq!(instance.properties.len(), 0); - assert_eq!(instance.parent, None); - assert_eq!(instance.children.len(), 4); - - let single_body = server.get_string(&format!("/api/read/{}", id)); - let single_response = serde_json::from_str::(&single_body).unwrap(); - - let single_instance = single_response.instances.get(id).unwrap(); - - assert_eq!(single_instance, &Cow::Borrowed(instance)); - }, - ("a", "ModuleScript") => { - assert!(module_id.is_none()); - module_id = Some(*id); - - let mut properties = HashMap::new(); - properties.insert("Source".to_string(), RbxValue::String { value: "-- a.lua".to_string() }); - - assert_eq!(instance.properties, properties); - assert_eq!(instance.parent, Some(partition_id)); - assert_eq!(instance.children.len(), 0); - - let single_body = server.get_string(&format!("/api/read/{}", id)); - let single_response = serde_json::from_str::(&single_body).unwrap(); - - let single_instance = single_response.instances.get(id).unwrap(); - - assert_eq!(single_instance, &Cow::Borrowed(instance)); - }, - ("b", "LocalScript") => { - assert!(client_id.is_none()); - client_id = Some(*id); - - let mut properties = HashMap::new(); - properties.insert("Source".to_string(), RbxValue::String { value: "-- b.client.lua".to_string() }); - - assert_eq!(instance.properties, properties); - assert_eq!(instance.parent, Some(partition_id)); - assert_eq!(instance.children.len(), 0); - - let single_body = server.get_string(&format!("/api/read/{}", id)); - let single_response = serde_json::from_str::(&single_body).unwrap(); - - let single_instance = single_response.instances.get(id).unwrap(); - - assert_eq!(single_instance, &Cow::Borrowed(instance)); - }, - ("a", "Script") => { - assert!(server_id.is_none()); - server_id = Some(*id); - - let mut properties = HashMap::new(); - properties.insert("Source".to_string(), RbxValue::String { value: "-- a.server.lua".to_string() }); - - assert_eq!(instance.properties, properties); - assert_eq!(instance.parent, Some(partition_id)); - assert_eq!(instance.children.len(), 0); - - let single_body = server.get_string(&format!("/api/read/{}", id)); - let single_response = serde_json::from_str::(&single_body).unwrap(); - - let single_instance = single_response.instances.get(id).unwrap(); - - assert_eq!(single_instance, &Cow::Borrowed(instance)); - }, - ("c", "LocalScript") => { - assert!(new_id.is_none()); - new_id = Some(*id); - - let mut properties = HashMap::new(); - properties.insert("Source".to_string(), RbxValue::String { value: "-- c.client.lua".to_string() }); - - assert_eq!(instance.properties, properties); - assert_eq!(instance.parent, Some(partition_id)); - assert_eq!(instance.children.len(), 0); - - let single_body = server.get_string(&format!("/api/read/{}", id)); - let single_response = serde_json::from_str::(&single_body).unwrap(); - - let single_instance = single_response.instances.get(id).unwrap(); - - assert_eq!(single_instance, &Cow::Borrowed(instance)); - }, - _ => {}, - } - } - - let root_id = root_id.unwrap(); - let module_id = module_id.unwrap(); - let client_id = client_id.unwrap(); - let server_id = server_id.unwrap(); - let new_id = new_id.unwrap(); - - let root_instance = response.instances.get(&root_id).unwrap(); - - assert!(root_instance.children.contains(&module_id)); - assert!(root_instance.children.contains(&client_id)); - assert!(root_instance.children.contains(&server_id)); - assert!(root_instance.children.contains(&new_id)); - - remove_file(&temp_name).unwrap(); - } - - { - // Block until Rojo detects the removal of our temp file - let body = server.get_string("/api/subscribe/0"); - let response = serde_json::from_str::(&body).unwrap(); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.message_cursor, 1); - assert_eq!(response.messages.len(), 1); - } - - { - // Everything should be back to the initial state! - let body = server.get_string("/api/read_all"); - let response = serde_json::from_str::(&body).unwrap(); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.message_cursor, 1); - assert_eq!(response.instances.len(), 4); - - assert_eq!(response.instances, initial_response.instances); - } - - // TODO: Test to change existing instance -} - -#[test] -fn partition_to_file() { - let original_project_path = TEST_PROJECTS_ROOT.join("partition-to-file"); - - let project_tempdir = tempfile::tempdir().unwrap(); - let project_path = project_tempdir.path(); - - copy_recursive(&original_project_path, &project_path).unwrap(); - - let project = Project::load(&project_path).unwrap(); - let mut session = Session::new(project.clone()); - session.start(); - - let web_config = WebConfig::from_session(0, project.serve_port, &session); - let server = Server::new(web_config); - - { - let body = server.get_string("/api/rojo"); - let response = serde_json::from_str::(&body).unwrap(); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.protocol_version, 2); - assert_eq!(response.partitions.len(), 1); - } - - { - let body = server.get_string("/api/read_all"); - let response = serde_json::from_str::(&body).unwrap(); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.message_cursor, -1); - assert_eq!(response.instances.len(), 1); - - let (id, instance) = response.instances.iter().next().unwrap(); - - assert_eq!(instance.name, "bar"); - assert_eq!(instance.class_name, "ModuleScript"); - assert_eq!(instance.properties.get("Source"), Some(&RbxValue::String { value: "-- foo.lua".to_string() })); - assert_eq!(instance.children.len(), 0); - assert_eq!(instance.parent, None); - - let body = server.get_string(&format!("/api/read/{}", id)); - let response = serde_json::from_str::(&body).unwrap(); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.message_cursor, -1); - assert_eq!(response.instances.len(), 1); - - let single_instance = response.instances.values().next().unwrap(); - - assert_eq!(&Cow::Borrowed(instance), single_instance); - } - - let file_path = project_path.join("foo.lua"); - - { - let mut file = File::create(file_path).unwrap(); - file.write_all(b"-- modified").unwrap(); - } - - { - // Block until Rojo detects our file being modified - let body = server.get_string("/api/subscribe/-1"); - let response = serde_json::from_str::(&body).unwrap(); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.message_cursor, 0); - assert_eq!(response.messages.len(), 1); - } - - { - let body = server.get_string("/api/read/0"); - let response = serde_json::from_str::(&body).unwrap(); - - assert_eq!(response.server_id, "0"); - assert_eq!(response.message_cursor, 0); - assert_eq!(response.instances.len(), 1); - - let instance = response.instances.values().next().unwrap(); - - assert_eq!(instance.name, "bar"); - assert_eq!(instance.class_name, "ModuleScript"); - assert_eq!(instance.properties.get("Source"), Some(&RbxValue::String { value: "-- modified".to_string() })); - assert_eq!(instance.children.len(), 0); - assert_eq!(instance.parent, None); - } -} diff --git a/test-projects/empty/roblox-project.json b/test-projects/empty/roblox-project.json new file mode 100644 index 00000000..5844e00e --- /dev/null +++ b/test-projects/empty/roblox-project.json @@ -0,0 +1,4 @@ +{ + "name": "empty", + "tree": {} +} \ No newline at end of file diff --git a/test-projects/empty/rojo.json b/test-projects/empty/rojo.json deleted file mode 100644 index 51c7917c..00000000 --- a/test-projects/empty/rojo.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "name": "empty", - "servePort": 23456, - "partitions": {} -} \ No newline at end of file diff --git a/test-projects/foo.json b/test-projects/foo.json new file mode 100644 index 00000000..f12be6a8 --- /dev/null +++ b/test-projects/foo.json @@ -0,0 +1,26 @@ +{ + "name": "foo", + "tree": { + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + "Rojo": { + "$className": "Folder", + "Plugin": { + "$path": "lib" + }, + "Roact": { + "$path": "modules/roact/lib" + }, + "Rodux": { + "$path": "modules/rodux/lib" + }, + "RoactRodux": { + "$path": "modules/roact-rodux/lib" + }, + "Promise": { + "$path": "modules/promise/lib" + } + } + } + } +} \ No newline at end of file diff --git a/test-projects/one-partition/lib/a.lua b/test-projects/one-partition/lib/a.lua deleted file mode 100644 index f23fd06a..00000000 --- a/test-projects/one-partition/lib/a.lua +++ /dev/null @@ -1 +0,0 @@ --- a.lua \ No newline at end of file diff --git a/test-projects/one-partition/lib/a.server.lua b/test-projects/one-partition/lib/a.server.lua deleted file mode 100644 index 08491e94..00000000 --- a/test-projects/one-partition/lib/a.server.lua +++ /dev/null @@ -1 +0,0 @@ --- a.server.lua \ No newline at end of file diff --git a/test-projects/one-partition/lib/b.client.lua b/test-projects/one-partition/lib/b.client.lua deleted file mode 100644 index 12d034fa..00000000 --- a/test-projects/one-partition/lib/b.client.lua +++ /dev/null @@ -1 +0,0 @@ --- b.client.lua \ No newline at end of file diff --git a/test-projects/one-partition/rojo.json b/test-projects/one-partition/rojo.json deleted file mode 100644 index d774a8f8..00000000 --- a/test-projects/one-partition/rojo.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "one-partition", - "servePort": 23456, - "partitions": { - "lib": { - "path": "lib", - "target": "ReplicatedStorage.OnePartition" - } - } -} \ No newline at end of file diff --git a/test-projects/partition-to-file/foo.lua b/test-projects/partition-to-file/foo.lua deleted file mode 100644 index 4c3ac65c..00000000 --- a/test-projects/partition-to-file/foo.lua +++ /dev/null @@ -1 +0,0 @@ --- foo.lua \ No newline at end of file diff --git a/test-projects/partition-to-file/rojo.json b/test-projects/partition-to-file/rojo.json deleted file mode 100644 index 0e7367f1..00000000 --- a/test-projects/partition-to-file/rojo.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "partition-to-file", - "servePort": 23456, - "partitions": { - "lib": { - "path": "foo.lua", - "target": "ReplicatedStorage.bar" - } - } -} \ No newline at end of file diff --git a/test-projects/single-sync-point/lib/main.lua b/test-projects/single-sync-point/lib/main.lua new file mode 100644 index 00000000..e69de29b diff --git a/test-projects/single-sync-point/roblox-project.json b/test-projects/single-sync-point/roblox-project.json new file mode 100644 index 00000000..3681fb2b --- /dev/null +++ b/test-projects/single-sync-point/roblox-project.json @@ -0,0 +1,11 @@ +{ + "name": "empty", + "tree": { + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + "Foo": { + "$path": "lib" + } + } + } +} \ No newline at end of file From 81a18e88ad50b56fb781b3a5a1fb6948156e8aa9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 26 Aug 2018 01:13:20 -0700 Subject: [PATCH 0196/1504] Cooler sounding README --- README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index d7a50670..99a54a58 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,9 @@ **Rojo** is a flexible multi-tool designed for creating robust Roblox projects. -It's designed for power users who want to use the **best tools available** for building games, libraries, and plugins. +It lets Roblox developers use industry-leading tools like Git and VS Code, and crucial utilities like Luacheck. + +Rojo is designed for **power users** who want to use the **best tools available** for building games, libraries, and plugins. ## Features Rojo lets you: @@ -29,15 +31,17 @@ Rojo lets you: * Version your place, library, or plugin using Git or another VCS * Sync JSON-format models from the filesystem into your game -Later this year, Rojo will be able to: +Later in 2018, Rojo will be able to: +* Sync scripts from Roblox Studio to the filesystem +* Compile MoonScript and sync it into Roblox Studio * Sync `rbxmx` models between the filesystem and Roblox Studio * Package projects into `rbxmx` files from the command line -## [Documentation Website](https://lpghatguy.github.io/rojo) -You can also view the documentation by browsing the [docs folder of the repository](https://github.com/LPGhatguy/rojo/tree/master/docs), but because it uses a number of Markdown extensions, it may not be very readable. +## [Documentation](https://lpghatguy.github.io/rojo) +You can also view the documentation by browsing the [docs](https://github.com/LPGhatguy/rojo/tree/master/docs) folder of the repository, but because it uses a number of Markdown extensions, it may not be very readable. -## Inspiration +## Inspiration and Alternatives There are lots of other tools that sync scripts into Roblox or provide other tools for working with Roblox places. Here are a few, if you're looking for alternatives or supplements to Rojo: @@ -51,6 +55,8 @@ Here are a few, if you're looking for alternatives or supplements to Rojo: If you use a plugin that _isn't_ Rojo for syncing code, open an issue and let me know why! I'd like Rojo to be the end-all tool so that people stop reinventing solutions to this problem. ## Contributing +The `master` branch is undergoing a rewrite right now known as 'Epiphany'. It includes a breaking change to the project configuration format and an infrastructure overhaul. + Pull requests are welcome! All pull requests are run against a test suite on Travis CI. That test suite should always pass! From 284f423220dec530667c11756942384286229fdd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 26 Aug 2018 01:13:57 -0700 Subject: [PATCH 0197/1504] Rename 'integration' to 'rojo-e2e' --- {integration => rojo-e2e}/.gitignore | 0 {integration => rojo-e2e}/Cargo.lock | 2 +- {integration => rojo-e2e}/Cargo.toml | 2 +- {integration => rojo-e2e}/README.md | 2 +- {integration => rojo-e2e}/src/main.rs | 0 5 files changed, 3 insertions(+), 3 deletions(-) rename {integration => rojo-e2e}/.gitignore (100%) rename {integration => rojo-e2e}/Cargo.lock (59%) rename {integration => rojo-e2e}/Cargo.toml (81%) rename {integration => rojo-e2e}/README.md (83%) rename {integration => rojo-e2e}/src/main.rs (100%) diff --git a/integration/.gitignore b/rojo-e2e/.gitignore similarity index 100% rename from integration/.gitignore rename to rojo-e2e/.gitignore diff --git a/integration/Cargo.lock b/rojo-e2e/Cargo.lock similarity index 59% rename from integration/Cargo.lock rename to rojo-e2e/Cargo.lock index 02b1e530..0b6ac389 100644 --- a/integration/Cargo.lock +++ b/rojo-e2e/Cargo.lock @@ -1,4 +1,4 @@ [[package]] -name = "integration" +name = "rojo-e2e" version = "0.1.0" diff --git a/integration/Cargo.toml b/rojo-e2e/Cargo.toml similarity index 81% rename from integration/Cargo.toml rename to rojo-e2e/Cargo.toml index 769e48aa..8afc532d 100644 --- a/integration/Cargo.toml +++ b/rojo-e2e/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "integration" +name = "rojo-e2e" version = "0.1.0" authors = ["Lucien Greathouse "] diff --git a/integration/README.md b/rojo-e2e/README.md similarity index 83% rename from integration/README.md rename to rojo-e2e/README.md index e211270b..6dbb1cca 100644 --- a/integration/README.md +++ b/rojo-e2e/README.md @@ -1,2 +1,2 @@ -# Rojo Integration Runner +# Rojo End-to-End This is a WIP test runner designed for Rojo. It will eventually start up the Rojo server and plugin and test functionality end-to-end. \ No newline at end of file diff --git a/integration/src/main.rs b/rojo-e2e/src/main.rs similarity index 100% rename from integration/src/main.rs rename to rojo-e2e/src/main.rs From a69cbf45df77581b5c7ee5b5fd16bcf7898716b7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 26 Aug 2018 22:17:30 -0700 Subject: [PATCH 0198/1504] Remove line break in HTTP debug output that studio messes up anyways --- plugin/src/Http.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/Http.lua b/plugin/src/Http.lua index 57cedc15..2087cee7 100644 --- a/plugin/src/Http.lua +++ b/plugin/src/Http.lua @@ -25,7 +25,7 @@ function Http.get(url) end) if ok then - dprint("\t", result, "\n") + dprint("\t", result) resolve(HttpResponse.new(result)) else reject(HttpError.fromErrorString(result)) @@ -44,7 +44,7 @@ function Http.post(url, body) end) if ok then - dprint("\t", result, "\n") + dprint("\t", result) resolve(HttpResponse.new(result)) else reject(HttpError.fromErrorString(result)) From dbad0a16c4eb305c4192f4954b1dea09dc00af4e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 21 Sep 2018 18:00:41 -0700 Subject: [PATCH 0199/1504] Comment out roblox_studio mechanisms for now, start using env_logger --- server/Cargo.lock | 49 ++++++++++++++++++++++++++++++++++++ server/Cargo.toml | 2 ++ server/src/bin.rs | 10 ++++++-- server/src/commands/init.rs | 2 +- server/src/commands/serve.rs | 12 +++++---- server/src/lib.rs | 3 ++- server/src/roblox_studio.rs | 7 +++--- server/src/session.rs | 5 ++-- server/src/web.rs | 3 ++- 9 files changed, 77 insertions(+), 16 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 3e0dfd05..caedd382 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -234,6 +234,18 @@ dependencies = [ "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "env_logger" +version = "0.5.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "filetime" version = "0.1.15" @@ -295,6 +307,14 @@ name = "httparse" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "humantime" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "idna" version = "0.1.5" @@ -571,6 +591,11 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quick-error" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "quote" version = "0.6.8" @@ -662,7 +687,9 @@ name = "rojo" version = "0.5.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -806,6 +833,14 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "termcolor" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "termion" version = "1.5.1" @@ -998,6 +1033,15 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "wincolor" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -1039,6 +1083,7 @@ dependencies = [ "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" +"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f" "checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05" "checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874" @@ -1047,6 +1092,7 @@ dependencies = [ "checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" "checksum gzip-header 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0a9fcfe1c9ee125342355b2467bc29b9dfcb2124fcae27edb9cee6f4cc5ecd40" "checksum httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7b6288d7db100340ca12873fd4d08ad1b8f206a9457798dfb17c018a33fee540" +"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" "checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606" @@ -1078,6 +1124,7 @@ dependencies = [ "checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998" "checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930" "checksum proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5697238f0d893c7f0ecc59c0999f18d2af85e424de441178bcacc9f9e6cf67" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" @@ -1104,6 +1151,7 @@ dependencies = [ "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4b103c6d08d323b92ff42c8ce62abcd83ca8efa7fd5bf7927efefec75f58c76" "checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" +"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" @@ -1130,4 +1178,5 @@ dependencies = [ "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" diff --git a/server/Cargo.toml b/server/Cargo.toml index 69c9bfe1..c773efd1 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -28,6 +28,8 @@ notify = "4.0" rand = "0.4" regex = "1.0" lazy_static = "1.0" +log = "0.4" +env_logger = "0.5" [dev-dependencies] tempfile = "3.0" diff --git a/server/src/bin.rs b/server/src/bin.rs index 86232c92..da27fcbc 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -1,4 +1,6 @@ #[macro_use] extern crate clap; +#[macro_use] extern crate log; +extern crate env_logger; extern crate librojo; @@ -8,6 +10,10 @@ use std::process; use librojo::pathext::canonicalish; fn main() { + env_logger::Builder::from_default_env() + .default_format_timestamp(false) + .init(); + let matches = clap_app!(rojo => (version: env!("CARGO_PKG_VERSION")) (author: env!("CARGO_PKG_AUTHORS")) @@ -45,8 +51,8 @@ fn main() { librojo::commands::serve(&project_path); }, _ => { - eprintln!("Please specify a subcommand!"); - eprintln!("Try 'rojo help' for information."); + error!("Please specify a subcommand!"); + error!("Try 'rojo help' for information."); process::exit(1); }, } diff --git a/server/src/commands/init.rs b/server/src/commands/init.rs index 9050e072..05407f14 100644 --- a/server/src/commands/init.rs +++ b/server/src/commands/init.rs @@ -9,7 +9,7 @@ pub fn init(project_path: &PathBuf) { println!("Created new empty project at {}", project_path.display()); }, Err(e) => { - eprintln!("Failed to create new project.\n{}", e); + error!("Failed to create new project.\n{}", e); process::exit(1); }, } diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 7233c872..4164026d 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -8,22 +8,24 @@ use ::{ project::Project, web::Server, session::Session, - roblox_studio, + // roblox_studio, }; pub fn serve(fuzzy_project_location: &Path) { + info!("Looking for project at {}", fuzzy_project_location.display()); + let project = match Project::load_fuzzy(fuzzy_project_location) { Ok(project) => project, Err(error) => { - eprintln!("Fatal: {}", error); + error!("{}", error); process::exit(1); }, }; - println!("Found project at {}", project.file_location.display()); - println!("Using project {:#?}", project); + info!("Found project at {}", project.file_location.display()); + info!("Using project {:#?}", project); - roblox_studio::install_bundled_plugin().unwrap(); + // roblox_studio::install_bundled_plugin().unwrap(); let session = Arc::new({ let mut session = Session::new(project); diff --git a/server/src/lib.rs b/server/src/lib.rs index 315d266c..41d3fd7e 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,6 +1,7 @@ #[macro_use] extern crate serde_derive; #[macro_use] extern crate rouille; #[macro_use] extern crate lazy_static; +#[macro_use] extern crate log; extern crate notify; extern crate rand; extern crate serde; @@ -16,7 +17,7 @@ pub mod message_queue; pub mod pathext; pub mod project; pub mod rbx; -pub mod roblox_studio; +// pub mod roblox_studio; pub mod session; pub mod vfs; pub mod web; diff --git a/server/src/roblox_studio.rs b/server/src/roblox_studio.rs index ee90a0b5..195e86be 100644 --- a/server/src/roblox_studio.rs +++ b/server/src/roblox_studio.rs @@ -4,7 +4,6 @@ #![allow(dead_code)] use std::path::PathBuf; -use std::env; #[cfg(all(not(debug_assertions), not(feature = "bundle-plugin")))] compile_error!("`bundle-plugin` feature must be set for release builds."); @@ -14,6 +13,8 @@ static PLUGIN_RBXM: &'static [u8] = include_bytes!("../target/plugin.rbxmx"); #[cfg(target_os = "windows")] pub fn get_install_location() -> Option { + use std::env; + let local_app_data = env::var("LocalAppData").ok()?; let mut location = PathBuf::from(local_app_data); @@ -46,7 +47,7 @@ pub fn install_bundled_plugin() -> Option<()> { use std::fs::File; use std::io::Write; - println!("Installing plugin..."); + info!("Installing plugin..."); let mut file = File::create(get_plugin_location()?).ok()?; file.write_all(PLUGIN_RBXM).ok()?; @@ -56,7 +57,7 @@ pub fn install_bundled_plugin() -> Option<()> { #[cfg(not(feature = "bundle-plugin"))] pub fn install_bundled_plugin() -> Option<()> { - println!("Skipping plugin installation, bundle-plugin not set."); + info!("Skipping plugin installation, bundle-plugin not set."); Some(()) } \ No newline at end of file diff --git a/server/src/session.rs b/server/src/session.rs index b1e9c7c8..7a69bed9 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -71,7 +71,7 @@ impl Session { } for root in vfs.get_roots() { - println!("Watching {}", root.display()); + info!("Watching {}", root.display()); let (watch_tx, watch_rx) = mpsc::channel(); @@ -83,7 +83,6 @@ impl Session { let vfs = Arc::clone(&self.vfs); thread::spawn(move || { - println!("Thread started"); loop { match watch_rx.recv() { Ok(event) => { @@ -107,7 +106,7 @@ impl Session { Err(_) => break, }; } - println!("Thread stopped"); + info!("Watcher thread stopped"); }); } } diff --git a/server/src/web.rs b/server/src/web.rs index 5d312aa4..8ec85213 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -9,7 +9,6 @@ use rouille::{self, Request, Response}; use ::{ id::Id, message_queue::Message, - project::Project, rbx::RbxInstance, session::Session, }; @@ -54,6 +53,8 @@ impl Server { #[allow(unreachable_code)] pub fn handle_request(&self, request: &Request) -> Response { + trace!("Request {} {}", request.method(), request.url()); + router!(request, (GET) (/) => { Response::text("Rojo is up and running!") From 31e1f6154846234a59868a20baa3cbfbde68aa82 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 31 Oct 2018 18:07:02 -0700 Subject: [PATCH 0200/1504] Start refining RbxTree operations, going to be a new crate --- server/src/rbx.rs | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/server/src/rbx.rs b/server/src/rbx.rs index d3873cb7..29f55072 100644 --- a/server/src/rbx.rs +++ b/server/src/rbx.rs @@ -7,7 +7,19 @@ use id::{Id, get_id}; pub enum RbxValue { String { value: String, - } + }, + Number { + value: f64, + }, + Bool { + value: bool, + }, + Vector3 { + value: [f64; 3], + }, + Color3 { + value: [u8; 3], + }, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -71,6 +83,7 @@ impl<'a> Iterator for Descendants<'a> { pub struct RbxTree { instances: HashMap, + // TODO: Make private pub root_instance_id: Id, } @@ -103,6 +116,30 @@ impl RbxTree { &self.instances } + // TODO: Test this function! + pub fn insert_tree(&mut self, parent_id: Id, tree: &RbxTree) { + let mut to_visit = vec![tree.root_instance_id]; + + loop { + let id = match to_visit.pop() { + Some(id) => id, + None => break, + }; + + let mut new_child = tree.get_instance(id).unwrap().clone(); + + for child in &new_child.children { + to_visit.push(*child); + } + + if id == tree.root_instance_id { + new_child.parent = Some(parent_id); + } + + self.insert_instance(new_child); + } + } + pub fn insert_instance(&mut self, mut instance: RbxInstance) { match instance.parent { Some(parent_id) => { From 5a99281e232663cd149b7ad39bf6425d51223915 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 8 Nov 2018 13:22:09 -0800 Subject: [PATCH 0201/1504] Make Rojo build with rbx_tree --- server/Cargo.lock | 20 ++++ server/Cargo.toml | 1 + server/src/lib.rs | 2 +- server/src/rbx.rs | 217 ------------------------------------------ server/src/session.rs | 3 +- server/src/web.rs | 19 ++-- 6 files changed, 33 insertions(+), 229 deletions(-) delete mode 100644 server/src/rbx.rs diff --git a/server/Cargo.lock b/server/Cargo.lock index caedd382..083fe9ff 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -641,6 +641,15 @@ name = "rand_core" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rbx-tree" +version = "0.1.0" +dependencies = [ + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" version = "0.1.40" @@ -692,6 +701,7 @@ dependencies = [ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx-tree 0.1.0", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", @@ -976,6 +986,15 @@ dependencies = [ "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "uuid" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "vec_map" version = "0.8.1" @@ -1169,6 +1188,7 @@ dependencies = [ "checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" "checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" "checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f" +"checksum uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dab5c5526c5caa3d106653401a267fed923e7046f35895ffcb5ca42db64942e6" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" "checksum walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "af464bc7be7b785c7ac72e266a6b67c4c9070155606f51655a650a6686204e35" diff --git a/server/Cargo.toml b/server/Cargo.toml index c773efd1..3381e44b 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -30,6 +30,7 @@ regex = "1.0" lazy_static = "1.0" log = "0.4" env_logger = "0.5" +rbx-tree = { path = "../../rbx-tree" } [dev-dependencies] tempfile = "3.0" diff --git a/server/src/lib.rs b/server/src/lib.rs index 41d3fd7e..e0e28ba8 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -7,6 +7,7 @@ extern crate rand; extern crate serde; extern crate serde_json; extern crate regex; +extern crate rbx_tree; #[cfg(test)] extern crate tempfile; @@ -16,7 +17,6 @@ pub mod id; pub mod message_queue; pub mod pathext; pub mod project; -pub mod rbx; // pub mod roblox_studio; pub mod session; pub mod vfs; diff --git a/server/src/rbx.rs b/server/src/rbx.rs deleted file mode 100644 index 29f55072..00000000 --- a/server/src/rbx.rs +++ /dev/null @@ -1,217 +0,0 @@ -use std::collections::HashMap; - -use id::{Id, get_id}; - -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum RbxValue { - String { - value: String, - }, - Number { - value: f64, - }, - Bool { - value: bool, - }, - Vector3 { - value: [f64; 3], - }, - Color3 { - value: [u8; 3], - }, -} - -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct RbxInstance { - /// Maps to the `Name` property on Instance. - pub name: String, - - /// Maps to the `ClassName` property on Instance. - pub class_name: String, - - /// Contains all other properties of an Instance. - pub properties: HashMap, - - /// The unique ID of the instance - id: Id, - - /// All of the children of this instance. Order is relevant to preserve! - children: Vec, - - /// The parent of the instance, if there is one. - parent: Option, -} - -impl RbxInstance { - pub fn get_id(&self) -> Id { - self.id - } -} - -pub struct Descendants<'a> { - tree: &'a RbxTree, - ids_to_visit: Vec, -} - -impl<'a> Iterator for Descendants<'a> { - type Item = &'a RbxInstance; - - fn next(&mut self) -> Option { - loop { - let id = match self.ids_to_visit.pop() { - Some(id) => id, - None => break, - }; - - match self.tree.get_instance(id) { - Some(instance) => { - for child_id in &instance.children { - self.ids_to_visit.push(*child_id); - } - - return Some(instance); - }, - None => continue, - } - } - - None - } -} - -pub struct RbxTree { - instances: HashMap, - // TODO: Make private - pub root_instance_id: Id, -} - -impl RbxTree { - pub fn new() -> RbxTree { - let root_instance_id = get_id(); - let root_instance = RbxInstance { - name: "game".to_string(), - class_name: "DataModel".to_string(), - properties: HashMap::new(), - id: root_instance_id, - children: Vec::new(), - parent: None, - }; - - let mut instances = HashMap::new(); - instances.insert(root_instance_id, root_instance); - - RbxTree { - instances, - root_instance_id, - } - } - - pub fn get_instance(&self, id: Id) -> Option<&RbxInstance> { - self.instances.get(&id) - } - - pub fn get_all_instances(&self) -> &HashMap { - &self.instances - } - - // TODO: Test this function! - pub fn insert_tree(&mut self, parent_id: Id, tree: &RbxTree) { - let mut to_visit = vec![tree.root_instance_id]; - - loop { - let id = match to_visit.pop() { - Some(id) => id, - None => break, - }; - - let mut new_child = tree.get_instance(id).unwrap().clone(); - - for child in &new_child.children { - to_visit.push(*child); - } - - if id == tree.root_instance_id { - new_child.parent = Some(parent_id); - } - - self.insert_instance(new_child); - } - } - - pub fn insert_instance(&mut self, mut instance: RbxInstance) { - match instance.parent { - Some(parent_id) => { - match self.instances.get_mut(&parent_id) { - Some(mut parent) => { - if !parent.children.contains(&instance.id) { - parent.children.push(instance.id); - } - }, - None => { - panic!("Tree consistency error, parent {} was not present in tree.", parent_id); - } - } - }, - None => { - instance.parent = Some(self.root_instance_id); - }, - } - - self.instances.insert(instance.id, instance); - } - - pub fn delete_instance(&mut self, id: Id) -> Vec { - let mut ids_to_visit = vec![id]; - let mut ids_deleted = Vec::new(); - - // We only need to explicitly remove a child from the first instance we - // delete, since all others will descend from this instance. - let parent_id = match self.instances.get(&id) { - Some(instance) => instance.parent, - None => None, - }; - - if let Some(parent_id) = parent_id { - let mut parent = self.instances.get_mut(&parent_id).unwrap(); - let index = parent.children.iter().position(|&v| v == id).unwrap(); - - parent.children.remove(index); - } - - loop { - let id = match ids_to_visit.pop() { - Some(id) => id, - None => break, - }; - - match self.instances.get(&id) { - Some(instance) => ids_to_visit.extend_from_slice(&instance.children), - None => continue, - } - - self.instances.remove(&id); - ids_deleted.push(id); - } - - ids_deleted - } - - pub fn iter_descendants<'a>(&'a self, id: Id) -> Descendants<'a> { - match self.get_instance(id) { - Some(instance) => { - Descendants { - tree: self, - ids_to_visit: instance.children.clone(), - } - }, - None => { - Descendants { - tree: self, - ids_to_visit: vec![], - } - }, - } - } -} \ No newline at end of file diff --git a/server/src/session.rs b/server/src/session.rs index 7a69bed9..b08810fe 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -15,9 +15,10 @@ use notify::{ Watcher, }; +use rbx_tree::RbxTree; + use ::{ message_queue::MessageQueue, - rbx::RbxTree, project::{Project, ProjectNode}, vfs::Vfs, }; diff --git a/server/src/web.rs b/server/src/web.rs index 8ec85213..919fcba9 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -5,11 +5,10 @@ use std::{ }; use rouille::{self, Request, Response}; +use rbx_tree::{RbxId, RootedRbxInstance}; use ::{ - id::Id, message_queue::Message, - rbx::RbxInstance, session::Session, }; @@ -19,7 +18,7 @@ pub struct ServerInfoResponse<'a> { pub session_id: &'a str, pub server_version: &'a str, pub protocol_version: u64, - pub root_instance_id: Id, + pub root_instance_id: RbxId, } #[derive(Debug, Serialize, Deserialize)] @@ -27,7 +26,7 @@ pub struct ServerInfoResponse<'a> { pub struct ReadResponse<'a> { pub session_id: &'a str, pub message_cursor: u32, - pub instances: HashMap>, + pub instances: HashMap>, } #[derive(Debug, Serialize, Deserialize)] @@ -69,7 +68,7 @@ impl Server { server_version: self.server_version, protocol_version: 2, session_id: &self.session.session_id, - root_instance_id: tree.root_instance_id, + root_instance_id: *tree.get_root_ids().iter().nth(0).unwrap(), // TODO }) }, @@ -117,14 +116,14 @@ impl Server { (GET) (/api/read/{ id_list: String }) => { let message_queue = Arc::clone(&self.session.message_queue); - let requested_ids: Result, _> = id_list + let requested_ids: Option> = id_list .split(",") - .map(str::parse) + .map(RbxId::parse_str) .collect(); let requested_ids = match requested_ids { - Ok(id) => id, - Err(_) => return rouille::Response::text("Malformed ID list").with_status_code(400), + Some(id) => id, + None => return rouille::Response::text("Malformed ID list").with_status_code(400), }; let tree = self.session.tree.read().unwrap(); @@ -138,7 +137,7 @@ impl Server { Some(instance) => { instances.insert(instance.get_id(), Cow::Borrowed(instance)); - for descendant in tree.iter_descendants(requested_id) { + for descendant in tree.descendants(requested_id) { instances.insert(descendant.get_id(), Cow::Borrowed(descendant)); } }, From a29c4f2b652cbfa813b57107ed52daedc04a1897 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 8 Nov 2018 13:25:50 -0800 Subject: [PATCH 0202/1504] Fix test warning --- server/tests/read_projects.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index 05a85759..ac9fbd4a 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -3,7 +3,6 @@ extern crate librojo; use std::{ - collections::HashMap, path::{Path, PathBuf}, }; From 60c5c2d344b8abb45e38b11f0bf57cece4e7c5c9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 16 Nov 2018 14:51:14 -0800 Subject: [PATCH 0203/1504] Iterating on project format to make it friendlier --- server/Cargo.lock | 1 + server/Cargo.toml | 1 + server/src/commands/serve.rs | 7 +-- server/src/lib.rs | 18 +++++--- server/src/project.rs | 14 ++---- server/src/session.rs | 88 +++++++++++++++++++----------------- server/src/session_id.rs | 11 +++++ server/src/web.rs | 19 ++++---- 8 files changed, 86 insertions(+), 73 deletions(-) create mode 100644 server/src/session_id.rs diff --git a/server/Cargo.lock b/server/Cargo.lock index 083fe9ff..26c6120d 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -708,6 +708,7 @@ dependencies = [ "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/server/Cargo.toml b/server/Cargo.toml index 3381e44b..9afa0d53 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -31,6 +31,7 @@ lazy_static = "1.0" log = "0.4" env_logger = "0.5" rbx-tree = { path = "../../rbx-tree" } +uuid = { version = "0.7", features = ["v4", "serde"] } [dev-dependencies] tempfile = "3.0" diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 4164026d..c00eec8d 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -27,12 +27,7 @@ pub fn serve(fuzzy_project_location: &Path) { // roblox_studio::install_bundled_plugin().unwrap(); - let session = Arc::new({ - let mut session = Session::new(project); - session.start().unwrap(); - session - }); - + let session = Arc::new(Session::new(project).unwrap()); let server = Server::new(Arc::clone(&session)); println!("Server listening on port 34872"); diff --git a/server/src/lib.rs b/server/src/lib.rs index e0e28ba8..065245bd 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,24 +1,28 @@ -#[macro_use] extern crate serde_derive; -#[macro_use] extern crate rouille; #[macro_use] extern crate lazy_static; #[macro_use] extern crate log; +#[macro_use] extern crate rouille; +#[macro_use] extern crate serde_derive; extern crate notify; extern crate rand; +extern crate rbx_tree; +extern crate regex; extern crate serde; extern crate serde_json; -extern crate regex; -extern crate rbx_tree; +extern crate uuid; #[cfg(test)] extern crate tempfile; +// pub mod roblox_studio; pub mod commands; -pub mod id; pub mod message_queue; pub mod pathext; pub mod project; -// pub mod roblox_studio; pub mod session; +pub mod session_id; pub mod vfs; pub mod web; -pub mod web_util; \ No newline at end of file +pub mod web_util; + +// TODO: Remove +pub mod id; \ No newline at end of file diff --git a/server/src/project.rs b/server/src/project.rs index b0a39e5a..5bec5112 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -63,20 +63,16 @@ impl SourceProjectNode { #[serde(rename_all = "camelCase")] struct SourceProject { name: String, - tree: HashMap, + tree: SourceProjectNode, } impl SourceProject { - pub fn into_project(mut self, project_file_location: &Path) -> Project { - let mut tree = HashMap::new(); - - for (node_name, node) in self.tree.drain() { - tree.insert(node_name, node.into_project_node(project_file_location)); - } + pub fn into_project(self, project_file_location: &Path) -> Project { + let tree = self.tree.into_project_node(project_file_location); Project { name: self.name, - tree: tree, + tree, file_location: PathBuf::from(project_file_location), } } @@ -157,7 +153,7 @@ pub enum ProjectNode { #[derive(Debug)] pub struct Project { pub name: String, - pub tree: HashMap, + pub tree: ProjectNode, pub file_location: PathBuf, } diff --git a/server/src/session.rs b/server/src/session.rs index b08810fe..3aef342f 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -1,12 +1,11 @@ use std::{ + collections::HashMap, sync::{Arc, RwLock, Mutex, mpsc}, thread, io, time::Duration, }; -use rand; - use notify::{ self, DebouncedEvent, @@ -15,73 +14,65 @@ use notify::{ Watcher, }; -use rbx_tree::RbxTree; +use rbx_tree::{RbxTree, RbxInstance}; -use ::{ +use crate::{ message_queue::MessageQueue, project::{Project, ProjectNode}, vfs::Vfs, + session_id::SessionId, }; const WATCH_TIMEOUT_MS: u64 = 100; pub struct Session { project: Project, - pub session_id: String, + pub session_id: SessionId, pub message_queue: Arc, pub tree: Arc>, vfs: Arc>, watchers: Vec, } -impl Session { - pub fn new(project: Project) -> Session { - let session_id = rand::random::().to_string(); - - Session { - session_id, - project, - message_queue: Arc::new(MessageQueue::new()), - tree: Arc::new(RwLock::new(RbxTree::new())), - vfs: Arc::new(Mutex::new(Vfs::new())), - watchers: Vec::new(), - } +fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> { + match project_node { + ProjectNode::Regular { children, .. } => { + for child in children.values() { + add_sync_points(vfs, child)?; + } + }, + ProjectNode::SyncPoint { path } => { + vfs.add_root(path)?; + }, } - pub fn start(&mut self) -> io::Result<()> { - fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> { - match project_node { - ProjectNode::Regular { children, .. } => { - for child in children.values() { - add_sync_points(vfs, child)?; - } - }, - ProjectNode::SyncPoint { path } => { - vfs.add_root(path)?; - }, - } + Ok(()) +} - Ok(()) - } +impl Session { + pub fn new(project: Project) -> io::Result { + let session_id = SessionId::new(); + let vfs = Arc::new(Mutex::new(Vfs::new())); + let message_queue = Arc::new(MessageQueue::new()); + let mut watchers = Vec::new(); { - let mut vfs = self.vfs.lock().unwrap(); + let mut vfs_temp = vfs.lock().unwrap(); - for child in self.project.tree.values() { - add_sync_points(&mut vfs, child)?; - } - - for root in vfs.get_roots() { - info!("Watching {}", root.display()); + add_sync_points(&mut vfs_temp, &project.tree) + .expect("Could not add sync points when starting new Rojo session"); + for root in vfs_temp.get_roots() { let (watch_tx, watch_rx) = mpsc::channel(); let mut watcher = notify::watcher(watch_tx, Duration::from_millis(WATCH_TIMEOUT_MS)).unwrap(); - watcher.watch(root, RecursiveMode::Recursive).unwrap(); - self.watchers.push(watcher); + watcher.watch(root, RecursiveMode::Recursive) + .expect("Could not watch directory"); - let vfs = Arc::clone(&self.vfs); + watchers.push(watcher); + + let vfs = Arc::clone(&vfs); thread::spawn(move || { loop { @@ -112,7 +103,20 @@ impl Session { } } - Ok(()) + let tree = RbxTree::new(RbxInstance { + name: "ahhhh".to_string(), + class_name: "ahhh help me".to_string(), + properties: HashMap::new(), + }); + + Ok(Session { + session_id, + project, + message_queue, + tree: Arc::new(RwLock::new(tree)), + vfs, + watchers: Vec::new(), + }) } pub fn get_project(&self) -> &Project { diff --git a/server/src/session_id.rs b/server/src/session_id.rs new file mode 100644 index 00000000..67783a7f --- /dev/null +++ b/server/src/session_id.rs @@ -0,0 +1,11 @@ +use serde_derive::{Serialize, Deserialize}; +use uuid::Uuid; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] +pub struct SessionId(Uuid); + +impl SessionId { + pub fn new() -> SessionId { + SessionId(Uuid::new_v4()) + } +} \ No newline at end of file diff --git a/server/src/web.rs b/server/src/web.rs index 919fcba9..4f19e39c 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -7,15 +7,16 @@ use std::{ use rouille::{self, Request, Response}; use rbx_tree::{RbxId, RootedRbxInstance}; -use ::{ +use crate::{ message_queue::Message, session::Session, + session_id::SessionId, }; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ServerInfoResponse<'a> { - pub session_id: &'a str, + pub session_id: SessionId, pub server_version: &'a str, pub protocol_version: u64, pub root_instance_id: RbxId, @@ -24,7 +25,7 @@ pub struct ServerInfoResponse<'a> { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ReadResponse<'a> { - pub session_id: &'a str, + pub session_id: SessionId, pub message_cursor: u32, pub instances: HashMap>, } @@ -32,7 +33,7 @@ pub struct ReadResponse<'a> { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SubscribeResponse<'a> { - pub session_id: &'a str, + pub session_id: SessionId, pub message_cursor: u32, pub messages: Cow<'a, [Message]>, } @@ -67,8 +68,8 @@ impl Server { Response::json(&ServerInfoResponse { server_version: self.server_version, protocol_version: 2, - session_id: &self.session.session_id, - root_instance_id: *tree.get_root_ids().iter().nth(0).unwrap(), // TODO + session_id: self.session.session_id, + root_instance_id: tree.get_root_id(), }) }, @@ -84,7 +85,7 @@ impl Server { if new_messages.len() > 0 { return Response::json(&SubscribeResponse { - session_id: &self.session.session_id, + session_id: self.session.session_id, messages: Cow::Borrowed(&[]), message_cursor: new_cursor, }) @@ -106,7 +107,7 @@ impl Server { let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); return Response::json(&SubscribeResponse { - session_id: &self.session.session_id, + session_id: self.session.session_id, messages: Cow::Owned(new_messages), message_cursor: new_cursor, }) @@ -146,7 +147,7 @@ impl Server { } Response::json(&ReadResponse { - session_id: &self.session.session_id, + session_id: self.session.session_id, message_cursor, instances, }) From fb950cb007fd7d9d0b3c59e58473d4f68ff61df8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 16 Nov 2018 15:11:24 -0800 Subject: [PATCH 0204/1504] Update test projects --- test-projects/empty/roblox-project.json | 4 +++- test-projects/single-sync-point/roblox-project.json | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/test-projects/empty/roblox-project.json b/test-projects/empty/roblox-project.json index 5844e00e..3d5be5e6 100644 --- a/test-projects/empty/roblox-project.json +++ b/test-projects/empty/roblox-project.json @@ -1,4 +1,6 @@ { "name": "empty", - "tree": {} + "tree": { + "$className": "DataModel" + } } \ No newline at end of file diff --git a/test-projects/single-sync-point/roblox-project.json b/test-projects/single-sync-point/roblox-project.json index 3681fb2b..2ec428cc 100644 --- a/test-projects/single-sync-point/roblox-project.json +++ b/test-projects/single-sync-point/roblox-project.json @@ -1,6 +1,7 @@ { "name": "empty", "tree": { + "$className": "DataModel", "ReplicatedStorage": { "$className": "ReplicatedStorage", "Foo": { From 9ad0eabb859bf69d9faedf101c55f68fceb02332 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 16 Nov 2018 20:32:39 -0800 Subject: [PATCH 0205/1504] Syncing sort of works --- server/Cargo.lock | 4 +- server/Cargo.toml | 2 +- server/src/project.rs | 2 +- server/src/session.rs | 122 ++++++++++++++++--- server/src/vfs.rs | 15 ++- test-projects/single-sync-point/lib/main.lua | 1 + 6 files changed, 125 insertions(+), 21 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 26c6120d..9211b849 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -644,6 +644,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rbx-tree" version = "0.1.0" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#124175066fa31e114fe55cca627dad4cae571a63" dependencies = [ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", @@ -701,7 +702,7 @@ dependencies = [ "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx-tree 0.1.0", + "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1150,6 +1151,7 @@ dependencies = [ "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" +"checksum rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025" diff --git a/server/Cargo.toml b/server/Cargo.toml index 9afa0d53..52036fef 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -30,7 +30,7 @@ regex = "1.0" lazy_static = "1.0" log = "0.4" env_logger = "0.5" -rbx-tree = { path = "../../rbx-tree" } +rbx-tree = { git = "https://github.com/LPGhatguy/rbx-tree.git" } uuid = { version = "0.7", features = ["v4", "serde"] } [dev-dependencies] diff --git a/server/src/project.rs b/server/src/project.rs index 5bec5112..78244856 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -142,7 +142,7 @@ pub enum ProjectNode { Regular { class_name: String, children: HashMap, - + // properties: HashMap, // ignore_unknown: bool, }, SyncPoint { diff --git a/server/src/session.rs b/server/src/session.rs index 3aef342f..ff1c3724 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -1,11 +1,15 @@ use std::{ collections::HashMap, sync::{Arc, RwLock, Mutex, mpsc}, + path::{Path, PathBuf}, thread, io, time::Duration, + str, }; +use serde_json; + use notify::{ self, DebouncedEvent, @@ -14,12 +18,12 @@ use notify::{ Watcher, }; -use rbx_tree::{RbxTree, RbxInstance}; +use rbx_tree::{RbxId, RbxTree, RbxInstance, RbxValue}; use crate::{ message_queue::MessageQueue, project::{Project, ProjectNode}, - vfs::Vfs, + vfs::{Vfs, VfsItem}, session_id::SessionId, }; @@ -30,6 +34,7 @@ pub struct Session { pub session_id: SessionId, pub message_queue: Arc, pub tree: Arc>, + paths_to_ids: HashMap, vfs: Arc>, watchers: Vec, } @@ -49,18 +54,104 @@ fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> Ok(()) } +fn read_sync_to_rbx( + tree: &mut RbxTree, + vfs: &Vfs, + paths_to_ids: &mut HashMap, + parent_node_id: RbxId, + project_node_name: &str, + path: &Path +) { + match vfs.get(path) { + Some(VfsItem::File(file)) => { + let contents = str::from_utf8(vfs.get_contents(&file.path).unwrap()).unwrap(); + + let mut properties = HashMap::new(); + properties.insert("Source".to_string(), RbxValue::String { value: contents.to_string() }); + + let instance = RbxInstance { + class_name: "ModuleScript".to_string(), + name: project_node_name.to_string(), + properties, + }; + + let id = tree.insert_instance(instance, parent_node_id); + paths_to_ids.insert(path.to_path_buf(), id); + }, + Some(VfsItem::Directory(directory)) => { + let instance = RbxInstance { + class_name: "Folder".to_string(), + name: project_node_name.to_string(), + properties: HashMap::new(), + }; + + let id = tree.insert_instance(instance, parent_node_id); + paths_to_ids.insert(path.to_path_buf(), id); + + for child_path in &directory.children { + let child_name = child_path.file_name().unwrap().to_str().unwrap(); + read_sync_to_rbx(tree, vfs, paths_to_ids, id, child_name, child_path); + } + }, + None => panic!("Couldn't read {} from disk", path.display()), + } +} + +fn read_to_rbx( + tree: &mut RbxTree, + vfs: &Vfs, + paths_to_ids: &mut HashMap, + parent_node_id: RbxId, + project_node_name: &str, + project_node: &ProjectNode +) { + match project_node { + ProjectNode::Regular { children, class_name, .. } => { + let instance = RbxInstance { + class_name: class_name.clone(), + name: project_node_name.to_string(), + properties: HashMap::new(), + }; + + let id = tree.insert_instance(instance, parent_node_id); + + for (child_name, child_project_node) in children { + read_to_rbx(tree, vfs, paths_to_ids, id, child_name, child_project_node); + } + }, + ProjectNode::SyncPoint { path } => { + read_sync_to_rbx(tree, vfs, paths_to_ids, parent_node_id, project_node_name, path); + }, + } +} + impl Session { pub fn new(project: Project) -> io::Result { - let session_id = SessionId::new(); - let vfs = Arc::new(Mutex::new(Vfs::new())); - let message_queue = Arc::new(MessageQueue::new()); + let mut vfs = Vfs::new(); + + let (change_tx, change_rx) = mpsc::channel(); + + add_sync_points(&mut vfs, &project.tree) + .expect("Could not add sync points when starting new Rojo session"); + + let mut tree = RbxTree::new(RbxInstance { + name: "ahhhh".to_string(), + class_name: "ahhh help me".to_string(), + properties: HashMap::new(), + }); + + let mut paths_to_ids = HashMap::new(); + + let root_id = tree.get_root_id(); + read_to_rbx(&mut tree, &vfs, &mut paths_to_ids, root_id, "root", &project.tree); + + println!("tree:\n{}", serde_json::to_string(&tree).unwrap()); + + let vfs = Arc::new(Mutex::new(vfs)); let mut watchers = Vec::new(); { - let mut vfs_temp = vfs.lock().unwrap(); - - add_sync_points(&mut vfs_temp, &project.tree) - .expect("Could not add sync points when starting new Rojo session"); + let vfs_temp = vfs.lock().unwrap(); for root in vfs_temp.get_roots() { let (watch_tx, watch_rx) = mpsc::channel(); @@ -72,6 +163,7 @@ impl Session { watchers.push(watcher); + let change_tx = change_tx.clone(); let vfs = Arc::clone(&vfs); thread::spawn(move || { @@ -82,15 +174,19 @@ impl Session { DebouncedEvent::Create(path) | DebouncedEvent::Write(path) => { let mut vfs = vfs.lock().unwrap(); vfs.add_or_update(&path).unwrap(); + change_tx.send(path.clone()).unwrap(); }, DebouncedEvent::Remove(path) => { let mut vfs = vfs.lock().unwrap(); vfs.remove(&path); + change_tx.send(path.clone()).unwrap(); }, DebouncedEvent::Rename(from_path, to_path) => { let mut vfs = vfs.lock().unwrap(); vfs.remove(&from_path); vfs.add_or_update(&to_path).unwrap(); + change_tx.send(from_path.clone()).unwrap(); + change_tx.send(to_path.clone()).unwrap(); }, _ => continue, }; @@ -103,14 +199,12 @@ impl Session { } } - let tree = RbxTree::new(RbxInstance { - name: "ahhhh".to_string(), - class_name: "ahhh help me".to_string(), - properties: HashMap::new(), - }); + let message_queue = Arc::new(MessageQueue::new()); + let session_id = SessionId::new(); Ok(Session { session_id, + paths_to_ids, project, message_queue, tree: Arc::new(RwLock::new(tree)), diff --git a/server/src/vfs.rs b/server/src/vfs.rs index 7ac6e0f4..d02e8290 100644 --- a/server/src/vfs.rs +++ b/server/src/vfs.rs @@ -33,13 +33,20 @@ impl Vfs { &self.roots } - pub fn get(&mut self, path: &Path) -> Option<&VfsItem> { + pub fn get(&self, path: &Path) -> Option<&VfsItem> { debug_assert!(path.is_absolute()); debug_assert!(self.is_valid_path(path)); self.items.get(path) } + pub fn get_contents(&self, path: &Path) -> Option<&[u8]> { + debug_assert!(path.is_absolute()); + debug_assert!(self.is_valid_path(path)); + + self.contents.get(path).map(Vec::as_slice) + } + pub fn remove(&mut self, path: &Path) { debug_assert!(path.is_absolute()); debug_assert!(self.is_valid_path(path)); @@ -82,13 +89,13 @@ impl Vfs { #[derive(Debug)] pub struct VfsFile { - path: PathBuf, + pub path: PathBuf, } #[derive(Debug)] pub struct VfsDirectory { - path: PathBuf, - children: HashSet, + pub path: PathBuf, + pub children: HashSet, } #[derive(Debug)] diff --git a/test-projects/single-sync-point/lib/main.lua b/test-projects/single-sync-point/lib/main.lua index e69de29b..36c9d9bc 100644 --- a/test-projects/single-sync-point/lib/main.lua +++ b/test-projects/single-sync-point/lib/main.lua @@ -0,0 +1 @@ +-- hello, from main \ No newline at end of file From e09d23d6c2bf297ecc2fb9cf1bf00ee2d81036ce Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 16 Nov 2018 23:14:32 -0800 Subject: [PATCH 0206/1504] RbxSession refactoring stuff --- server/src/lib.rs | 1 + server/src/project.rs | 36 ++++---- server/src/rbx_session.rs | 160 ++++++++++++++++++++++++++++++++++ server/src/session.rs | 178 ++++++++++++-------------------------- server/src/web.rs | 6 +- 5 files changed, 242 insertions(+), 139 deletions(-) create mode 100644 server/src/rbx_session.rs diff --git a/server/src/lib.rs b/server/src/lib.rs index 065245bd..4f1e9375 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -18,6 +18,7 @@ pub mod commands; pub mod message_queue; pub mod pathext; pub mod project; +pub mod rbx_session; pub mod session; pub mod session_id; pub mod vfs; diff --git a/server/src/project.rs b/server/src/project.rs index 78244856..853c8547 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -12,7 +12,7 @@ pub static PROJECT_FILENAME: &'static str = "roblox-project.json"; #[derive(Debug, Serialize, Deserialize)] #[serde(untagged)] enum SourceProjectNode { - Regular { + Instance { #[serde(rename = "$className")] class_name: String, @@ -31,17 +31,17 @@ enum SourceProjectNode { impl SourceProjectNode { pub fn into_project_node(self, project_file_location: &Path) -> ProjectNode { match self { - SourceProjectNode::Regular { class_name, mut children } => { + SourceProjectNode::Instance { class_name, mut children } => { let mut new_children = HashMap::new(); for (node_name, node) in children.drain() { new_children.insert(node_name, node.into_project_node(project_file_location)); } - ProjectNode::Regular { + ProjectNode::Instance(InstanceProjectNode { class_name, children: new_children, - } + }) }, SourceProjectNode::SyncPoint { path: source_path } => { let path = if Path::new(&source_path).is_absolute() { @@ -51,9 +51,9 @@ impl SourceProjectNode { project_folder_location.join(source_path) }; - ProjectNode::SyncPoint { + ProjectNode::SyncPoint(SyncPointProjectNode { path, - } + }) }, } } @@ -139,15 +139,21 @@ impl fmt::Display for ProjectSaveError { #[derive(Debug)] pub enum ProjectNode { - Regular { - class_name: String, - children: HashMap, - // properties: HashMap, - // ignore_unknown: bool, - }, - SyncPoint { - path: PathBuf, - }, + Instance(InstanceProjectNode), + SyncPoint(SyncPointProjectNode), +} + +#[derive(Debug)] +pub struct InstanceProjectNode { + pub class_name: String, + pub children: HashMap, + // properties: HashMap, + // ignore_unknown: bool, +} + +#[derive(Debug)] +pub struct SyncPointProjectNode { + pub path: PathBuf, } #[derive(Debug)] diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs new file mode 100644 index 00000000..427f490e --- /dev/null +++ b/server/src/rbx_session.rs @@ -0,0 +1,160 @@ +use std::{ + collections::HashMap, + path::{Path, PathBuf}, + sync::{Arc, Mutex}, + str, +}; + +use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; + +use crate::{ + project::{Project, ProjectNode, InstanceProjectNode}, + message_queue::MessageQueue, + vfs::{Vfs, VfsItem}, +}; + +pub struct RbxSession { + tree: RbxTree, + paths_to_ids: HashMap, + message_queue: Arc, + vfs: Arc>, + project: Arc, +} + +impl RbxSession { + pub fn new(project: Arc, vfs: Arc>, message_queue: Arc) -> RbxSession { + let (tree, paths_to_ids) = { + let temp_vfs = vfs.lock().unwrap(); + construct_initial_tree(&project, &temp_vfs) + }; + + { + use serde_json; + println!("{}", serde_json::to_string(&tree).unwrap()); + } + + RbxSession { + tree, + paths_to_ids, + message_queue, + vfs, + project, + } + } + + pub fn path_created_or_updated(&mut self, path: &Path) { + println!("Path changed: {}", path.display()); + } + + pub fn path_removed(&mut self, path: &Path) { + println!("Path removed: {}", path.display()); + } + + pub fn path_renamed(&mut self, from_path: &Path, to_path: &Path) { + println!("Path renamed from {} to {}", from_path.display(), to_path.display()); + } + + pub fn get_tree(&self) -> &RbxTree { + &self.tree + } +} + +fn construct_initial_tree( + project: &Project, + vfs: &Vfs, +) -> (RbxTree, HashMap) { + let mut paths_to_ids = HashMap::new(); + let mut tree = RbxTree::new(RbxInstance { + name: "this isn't supposed to be here".to_string(), + class_name: "ahhh, help me".to_string(), + properties: HashMap::new(), + }); + + let root_id = tree.get_root_id(); + + construct_initial_tree_node(&mut tree, vfs, &mut paths_to_ids, root_id, "<<>>", &project.tree); + + (tree, paths_to_ids) +} + +fn construct_initial_tree_node( + tree: &mut RbxTree, + vfs: &Vfs, + paths_to_ids: &mut HashMap, + parent_instance_id: RbxId, + instance_name: &str, + project_node: &ProjectNode, +) { + match project_node { + ProjectNode::Instance(node) => { + construct_instance_node(tree, vfs, paths_to_ids, parent_instance_id, instance_name, node); + }, + ProjectNode::SyncPoint(node) => { + construct_sync_point_node(tree, vfs, paths_to_ids, parent_instance_id, instance_name, &node.path); + }, + } +} + +fn construct_instance_node( + tree: &mut RbxTree, + vfs: &Vfs, + paths_to_ids: &mut HashMap, + parent_instance_id: RbxId, + instance_name: &str, + project_node: &InstanceProjectNode, +) { + let instance = RbxInstance { + class_name: project_node.class_name.clone(), + name: instance_name.to_string(), + properties: HashMap::new(), + }; + + let id = tree.insert_instance(instance, parent_instance_id); + + for (child_name, child_project_node) in &project_node.children { + construct_initial_tree_node(tree, vfs, paths_to_ids, id, child_name, child_project_node); + } +} + +fn construct_sync_point_node( + tree: &mut RbxTree, + vfs: &Vfs, + paths_to_ids: &mut HashMap, + parent_instance_id: RbxId, + instance_name: &str, + file_path: &Path, +) { + match vfs.get(&file_path) { + Some(VfsItem::File(file)) => { + let contents = str::from_utf8(vfs.get_contents(&file.path).unwrap()).unwrap(); + + let mut properties = HashMap::new(); + properties.insert("Source".to_string(), RbxValue::String { value: contents.to_string() }); + + let instance = RbxInstance { + class_name: "ModuleScript".to_string(), + name: instance_name.to_string(), + properties, + }; + + let id = tree.insert_instance(instance, parent_instance_id); + paths_to_ids.insert(file.path.clone(), id); + }, + Some(VfsItem::Directory(directory)) => { + let instance = RbxInstance { + class_name: "Folder".to_string(), + name: instance_name.to_string(), + properties: HashMap::new(), + }; + + let id = tree.insert_instance(instance, parent_instance_id); + paths_to_ids.insert(directory.path.clone(), id); + + for child_path in &directory.children { + let child_instance_name = child_path.file_name().unwrap().to_str().unwrap(); + construct_sync_point_node(tree, vfs, paths_to_ids, id, child_instance_name, child_path); + } + }, + None => panic!("Couldn't read {} from disk", file_path.display()), + } +} \ No newline at end of file diff --git a/server/src/session.rs b/server/src/session.rs index ff1c3724..53533dba 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -1,15 +1,10 @@ use std::{ - collections::HashMap, - sync::{Arc, RwLock, Mutex, mpsc}, - path::{Path, PathBuf}, + sync::{Arc, Mutex, mpsc}, thread, io, time::Duration, - str, }; -use serde_json; - use notify::{ self, DebouncedEvent, @@ -18,142 +13,66 @@ use notify::{ Watcher, }; -use rbx_tree::{RbxId, RbxTree, RbxInstance, RbxValue}; - use crate::{ message_queue::MessageQueue, project::{Project, ProjectNode}, - vfs::{Vfs, VfsItem}, + vfs::Vfs, session_id::SessionId, + rbx_session::RbxSession, }; const WATCH_TIMEOUT_MS: u64 = 100; pub struct Session { - project: Project, + project: Arc, pub session_id: SessionId, pub message_queue: Arc, - pub tree: Arc>, - paths_to_ids: HashMap, + pub rbx_session: Arc>, vfs: Arc>, watchers: Vec, } fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> { match project_node { - ProjectNode::Regular { children, .. } => { - for child in children.values() { + ProjectNode::Instance(node) => { + for child in node.children.values() { add_sync_points(vfs, child)?; } }, - ProjectNode::SyncPoint { path } => { - vfs.add_root(path)?; + ProjectNode::SyncPoint(node) => { + vfs.add_root(&node.path)?; }, } Ok(()) } -fn read_sync_to_rbx( - tree: &mut RbxTree, - vfs: &Vfs, - paths_to_ids: &mut HashMap, - parent_node_id: RbxId, - project_node_name: &str, - path: &Path -) { - match vfs.get(path) { - Some(VfsItem::File(file)) => { - let contents = str::from_utf8(vfs.get_contents(&file.path).unwrap()).unwrap(); - - let mut properties = HashMap::new(); - properties.insert("Source".to_string(), RbxValue::String { value: contents.to_string() }); - - let instance = RbxInstance { - class_name: "ModuleScript".to_string(), - name: project_node_name.to_string(), - properties, - }; - - let id = tree.insert_instance(instance, parent_node_id); - paths_to_ids.insert(path.to_path_buf(), id); - }, - Some(VfsItem::Directory(directory)) => { - let instance = RbxInstance { - class_name: "Folder".to_string(), - name: project_node_name.to_string(), - properties: HashMap::new(), - }; - - let id = tree.insert_instance(instance, parent_node_id); - paths_to_ids.insert(path.to_path_buf(), id); - - for child_path in &directory.children { - let child_name = child_path.file_name().unwrap().to_str().unwrap(); - read_sync_to_rbx(tree, vfs, paths_to_ids, id, child_name, child_path); - } - }, - None => panic!("Couldn't read {} from disk", path.display()), - } -} - -fn read_to_rbx( - tree: &mut RbxTree, - vfs: &Vfs, - paths_to_ids: &mut HashMap, - parent_node_id: RbxId, - project_node_name: &str, - project_node: &ProjectNode -) { - match project_node { - ProjectNode::Regular { children, class_name, .. } => { - let instance = RbxInstance { - class_name: class_name.clone(), - name: project_node_name.to_string(), - properties: HashMap::new(), - }; - - let id = tree.insert_instance(instance, parent_node_id); - - for (child_name, child_project_node) in children { - read_to_rbx(tree, vfs, paths_to_ids, id, child_name, child_project_node); - } - }, - ProjectNode::SyncPoint { path } => { - read_sync_to_rbx(tree, vfs, paths_to_ids, parent_node_id, project_node_name, path); - }, - } -} - impl Session { pub fn new(project: Project) -> io::Result { - let mut vfs = Vfs::new(); + let project = Arc::new(project); + let message_queue = Arc::new(MessageQueue::new()); + let vfs = Arc::new(Mutex::new(Vfs::new())); - let (change_tx, change_rx) = mpsc::channel(); + { + let mut vfs = vfs.lock().unwrap(); + add_sync_points(&mut vfs, &project.tree) + .expect("Could not add sync points when starting new Rojo session"); + } - add_sync_points(&mut vfs, &project.tree) - .expect("Could not add sync points when starting new Rojo session"); + let rbx_session = Arc::new(Mutex::new(RbxSession::new( + Arc::clone(&project), + Arc::clone(&vfs), + Arc::clone(&message_queue), + ))); - let mut tree = RbxTree::new(RbxInstance { - name: "ahhhh".to_string(), - class_name: "ahhh help me".to_string(), - properties: HashMap::new(), - }); - - let mut paths_to_ids = HashMap::new(); - - let root_id = tree.get_root_id(); - read_to_rbx(&mut tree, &vfs, &mut paths_to_ids, root_id, "root", &project.tree); - - println!("tree:\n{}", serde_json::to_string(&tree).unwrap()); - - let vfs = Arc::new(Mutex::new(vfs)); let mut watchers = Vec::new(); { let vfs_temp = vfs.lock().unwrap(); for root in vfs_temp.get_roots() { + println!("Watching {}", root.display()); + let (watch_tx, watch_rx) = mpsc::channel(); let mut watcher = notify::watcher(watch_tx, Duration::from_millis(WATCH_TIMEOUT_MS)).unwrap(); @@ -163,8 +82,8 @@ impl Session { watchers.push(watcher); - let change_tx = change_tx.clone(); let vfs = Arc::clone(&vfs); + let rbx_session = Arc::clone(&rbx_session); thread::spawn(move || { loop { @@ -172,23 +91,40 @@ impl Session { Ok(event) => { match event { DebouncedEvent::Create(path) | DebouncedEvent::Write(path) => { - let mut vfs = vfs.lock().unwrap(); - vfs.add_or_update(&path).unwrap(); - change_tx.send(path.clone()).unwrap(); + { + let mut vfs = vfs.lock().unwrap(); + vfs.add_or_update(&path).unwrap(); + } + + { + let mut rbx_session = rbx_session.lock().unwrap(); + rbx_session.path_created_or_updated(&path); + } }, DebouncedEvent::Remove(path) => { - let mut vfs = vfs.lock().unwrap(); - vfs.remove(&path); - change_tx.send(path.clone()).unwrap(); + { + let mut vfs = vfs.lock().unwrap(); + vfs.remove(&path); + } + + { + let mut rbx_session = rbx_session.lock().unwrap(); + rbx_session.path_removed(&path); + } }, DebouncedEvent::Rename(from_path, to_path) => { - let mut vfs = vfs.lock().unwrap(); - vfs.remove(&from_path); - vfs.add_or_update(&to_path).unwrap(); - change_tx.send(from_path.clone()).unwrap(); - change_tx.send(to_path.clone()).unwrap(); + { + let mut vfs = vfs.lock().unwrap(); + vfs.remove(&from_path); + vfs.add_or_update(&to_path).unwrap(); + } + + { + let mut rbx_session = rbx_session.lock().unwrap(); + rbx_session.path_renamed(&from_path, &to_path); + } }, - _ => continue, + _ => {}, }; }, Err(_) => break, @@ -199,17 +135,15 @@ impl Session { } } - let message_queue = Arc::new(MessageQueue::new()); let session_id = SessionId::new(); Ok(Session { session_id, - paths_to_ids, + rbx_session, project, message_queue, - tree: Arc::new(RwLock::new(tree)), vfs, - watchers: Vec::new(), + watchers, }) } diff --git a/server/src/web.rs b/server/src/web.rs index 4f19e39c..150c019f 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -63,7 +63,8 @@ impl Server { (GET) (/api/rojo) => { // Get a summary of information about the server. - let tree = self.session.tree.read().unwrap(); + let rbx_session = self.session.rbx_session.lock().unwrap(); + let tree = rbx_session.get_tree(); Response::json(&ServerInfoResponse { server_version: self.server_version, @@ -127,7 +128,8 @@ impl Server { None => return rouille::Response::text("Malformed ID list").with_status_code(400), }; - let tree = self.session.tree.read().unwrap(); + let rbx_session = self.session.rbx_session.lock().unwrap(); + let tree = rbx_session.get_tree(); let message_cursor = message_queue.get_message_cursor(); From b4fd2e31b3970a5efcc66f7ca160b9a1837f3474 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 16 Nov 2018 23:27:19 -0800 Subject: [PATCH 0207/1504] Cleanup old modules and create more focused code --- server/Cargo.lock | 1 - server/Cargo.toml | 1 - server/src/bin.rs | 20 +++++++++++++++----- server/src/id.rs | 21 --------------------- server/src/lib.rs | 7 +------ server/src/message_queue.rs | 34 ++++++++++++++++++++++++++-------- server/src/pathext.rs | 27 --------------------------- server/src/rbx_session.rs | 11 +++-------- server/src/session.rs | 2 +- 9 files changed, 46 insertions(+), 78 deletions(-) delete mode 100644 server/src/id.rs delete mode 100644 server/src/pathext.rs diff --git a/server/Cargo.lock b/server/Cargo.lock index 9211b849..3242e81a 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -698,7 +698,6 @@ version = "0.5.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/server/Cargo.toml b/server/Cargo.toml index 52036fef..21cf0ba5 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -27,7 +27,6 @@ serde_json = "1.0" notify = "4.0" rand = "0.4" regex = "1.0" -lazy_static = "1.0" log = "0.4" env_logger = "0.5" rbx-tree = { git = "https://github.com/LPGhatguy/rbx-tree.git" } diff --git a/server/src/bin.rs b/server/src/bin.rs index da27fcbc..d8783082 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -4,10 +4,20 @@ extern crate env_logger; extern crate librojo; -use std::path::{Path, PathBuf}; -use std::process; +use std::{ + path::{Path, PathBuf}, + process, + env, +}; -use librojo::pathext::canonicalish; +fn make_path_absolute(value: &Path) -> PathBuf { + if value.is_absolute() { + PathBuf::from(value) + } else { + let current_dir = env::current_dir().unwrap(); + current_dir.join(value) + } +} fn main() { env_logger::Builder::from_default_env() @@ -36,7 +46,7 @@ fn main() { ("init", sub_matches) => { let sub_matches = sub_matches.unwrap(); let project_path = Path::new(sub_matches.value_of("PATH").unwrap_or(".")); - let full_path = canonicalish(project_path); + let full_path = make_path_absolute(project_path); librojo::commands::init(&full_path); }, @@ -44,7 +54,7 @@ fn main() { let sub_matches = sub_matches.unwrap(); let project_path = match sub_matches.value_of("PROJECT") { - Some(v) => canonicalish(PathBuf::from(v)), + Some(v) => make_path_absolute(Path::new(v)), None => std::env::current_dir().unwrap(), }; diff --git a/server/src/id.rs b/server/src/id.rs deleted file mode 100644 index 98144cfa..00000000 --- a/server/src/id.rs +++ /dev/null @@ -1,21 +0,0 @@ -use std::sync::atomic::{AtomicUsize, Ordering}; - -/// A unique identifier, not guaranteed to be generated in any order. -pub type Id = usize; - -lazy_static! { - static ref LAST_ID: AtomicUsize = AtomicUsize::new(0); -} - -/// Generate a new ID, which has no defined ordering. -pub fn get_id() -> Id { - LAST_ID.fetch_add(1, Ordering::SeqCst) -} - -#[test] -fn it_gives_unique_numbers() { - let a = get_id(); - let b = get_id(); - - assert!(a != b); -} \ No newline at end of file diff --git a/server/src/lib.rs b/server/src/lib.rs index 4f1e9375..ca15e9a3 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,4 +1,3 @@ -#[macro_use] extern crate lazy_static; #[macro_use] extern crate log; #[macro_use] extern crate rouille; #[macro_use] extern crate serde_derive; @@ -16,14 +15,10 @@ extern crate tempfile; // pub mod roblox_studio; pub mod commands; pub mod message_queue; -pub mod pathext; pub mod project; pub mod rbx_session; pub mod session; pub mod session_id; pub mod vfs; pub mod web; -pub mod web_util; - -// TODO: Remove -pub mod id; \ No newline at end of file +pub mod web_util; \ No newline at end of file diff --git a/server/src/message_queue.rs b/server/src/message_queue.rs index 1029c7e1..75c4ab2f 100644 --- a/server/src/message_queue.rs +++ b/server/src/message_queue.rs @@ -1,19 +1,37 @@ -use std::collections::HashMap; -use std::sync::{mpsc, RwLock, Mutex}; +use std::{ + collections::HashMap, + sync::{ + mpsc, + atomic::{AtomicUsize, Ordering}, + RwLock, + Mutex, + }, +}; -use id::{Id, get_id}; +use rbx_tree::RbxId; + +/// A unique identifier, not guaranteed to be generated in any order. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub struct ListenerId(usize); + +/// Generate a new ID, which has no defined ordering. +pub fn get_listener_id() -> ListenerId { + static LAST_ID: AtomicUsize = AtomicUsize::new(0); + + ListenerId(LAST_ID.fetch_add(1, Ordering::SeqCst)) +} #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "type")] pub enum Message { InstanceChanged { - id: Id, + id: RbxId, }, } pub struct MessageQueue { messages: RwLock>, - message_listeners: Mutex>>, + message_listeners: Mutex>>, } impl MessageQueue { @@ -39,8 +57,8 @@ impl MessageQueue { } } - pub fn subscribe(&self, sender: mpsc::Sender<()>) -> Id { - let id = get_id(); + pub fn subscribe(&self, sender: mpsc::Sender<()>) -> ListenerId { + let id = get_listener_id(); { let mut message_listeners = self.message_listeners.lock().unwrap(); @@ -50,7 +68,7 @@ impl MessageQueue { id } - pub fn unsubscribe(&self, id: Id) { + pub fn unsubscribe(&self, id: ListenerId) { { let mut message_listeners = self.message_listeners.lock().unwrap(); message_listeners.remove(&id); diff --git a/server/src/pathext.rs b/server/src/pathext.rs deleted file mode 100644 index 0b257cc8..00000000 --- a/server/src/pathext.rs +++ /dev/null @@ -1,27 +0,0 @@ -use std::env::current_dir; -use std::path::{Path, PathBuf}; - -/// Turns the path into an absolute one, using the current working directory if -/// necessary. -pub fn canonicalish>(value: T) -> PathBuf { - let cwd = current_dir().unwrap(); - - absoluteify(&cwd, value) -} - -/// Converts the given path to be absolute if it isn't already using a given -/// root. -fn absoluteify(root: A, value: B) -> PathBuf -where - A: AsRef, - B: AsRef, -{ - let root = root.as_ref(); - let value = value.as_ref(); - - if value.is_absolute() { - PathBuf::from(value) - } else { - root.join(value) - } -} \ No newline at end of file diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 427f490e..db4608bf 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -28,11 +28,6 @@ impl RbxSession { construct_initial_tree(&project, &temp_vfs) }; - { - use serde_json; - println!("{}", serde_json::to_string(&tree).unwrap()); - } - RbxSession { tree, paths_to_ids, @@ -43,15 +38,15 @@ impl RbxSession { } pub fn path_created_or_updated(&mut self, path: &Path) { - println!("Path changed: {}", path.display()); + info!("Path changed: {}", path.display()); } pub fn path_removed(&mut self, path: &Path) { - println!("Path removed: {}", path.display()); + info!("Path removed: {}", path.display()); } pub fn path_renamed(&mut self, from_path: &Path, to_path: &Path) { - println!("Path renamed from {} to {}", from_path.display(), to_path.display()); + info!("Path renamed from {} to {}", from_path.display(), to_path.display()); } pub fn get_tree(&self) -> &RbxTree { diff --git a/server/src/session.rs b/server/src/session.rs index 53533dba..2cf03fed 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -71,7 +71,7 @@ impl Session { let vfs_temp = vfs.lock().unwrap(); for root in vfs_temp.get_roots() { - println!("Watching {}", root.display()); + info!("Watching path {}", root.display()); let (watch_tx, watch_rx) = mpsc::channel(); From 38e0f82812db460aeae55130ddbe360171554c31 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 17 Nov 2018 00:04:44 -0800 Subject: [PATCH 0208/1504] Clean up VFS code to make it much more robust --- server/src/rbx_session.rs | 10 ++- server/src/session.rs | 22 ++++-- server/src/vfs.rs | 151 ++++++++++++++++++++++---------------- 3 files changed, 112 insertions(+), 71 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index db4608bf..de3e16c1 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -37,8 +37,12 @@ impl RbxSession { } } - pub fn path_created_or_updated(&mut self, path: &Path) { - info!("Path changed: {}", path.display()); + pub fn path_created(&mut self, path: &Path) { + info!("Path created: {}", path.display()); + } + + pub fn path_updated(&mut self, path: &Path) { + info!("Path updated: {}", path.display()); } pub fn path_removed(&mut self, path: &Path) { @@ -121,7 +125,7 @@ fn construct_sync_point_node( ) { match vfs.get(&file_path) { Some(VfsItem::File(file)) => { - let contents = str::from_utf8(vfs.get_contents(&file.path).unwrap()).unwrap(); + let contents = str::from_utf8(&file.contents).unwrap(); let mut properties = HashMap::new(); properties.insert("Source".to_string(), RbxValue::String { value: contents.to_string() }); diff --git a/server/src/session.rs b/server/src/session.rs index 2cf03fed..a546c18b 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -90,21 +90,32 @@ impl Session { match watch_rx.recv() { Ok(event) => { match event { - DebouncedEvent::Create(path) | DebouncedEvent::Write(path) => { + DebouncedEvent::Create(path) => { { let mut vfs = vfs.lock().unwrap(); - vfs.add_or_update(&path).unwrap(); + vfs.path_created(&path).unwrap(); } { let mut rbx_session = rbx_session.lock().unwrap(); - rbx_session.path_created_or_updated(&path); + rbx_session.path_created(&path); + } + }, + DebouncedEvent::Write(path) => { + { + let mut vfs = vfs.lock().unwrap(); + vfs.path_updated(&path).unwrap(); + } + + { + let mut rbx_session = rbx_session.lock().unwrap(); + rbx_session.path_updated(&path); } }, DebouncedEvent::Remove(path) => { { let mut vfs = vfs.lock().unwrap(); - vfs.remove(&path); + vfs.path_removed(&path).unwrap(); } { @@ -115,8 +126,7 @@ impl Session { DebouncedEvent::Rename(from_path, to_path) => { { let mut vfs = vfs.lock().unwrap(); - vfs.remove(&from_path); - vfs.add_or_update(&to_path).unwrap(); + vfs.path_moved(&from_path, &to_path).unwrap(); } { diff --git a/server/src/vfs.rs b/server/src/vfs.rs index d02e8290..b744d567 100644 --- a/server/src/vfs.rs +++ b/server/src/vfs.rs @@ -7,7 +7,6 @@ use std::{ #[derive(Debug)] pub struct Vfs { - contents: HashMap>, items: HashMap, roots: HashSet, } @@ -15,81 +14,110 @@ pub struct Vfs { impl Vfs { pub fn new() -> Vfs { Vfs { - contents: HashMap::new(), items: HashMap::new(), roots: HashSet::new(), } } - pub fn add_root<'a, 'b>(&'a mut self, root_path: &'b Path) -> io::Result<&'a VfsItem> { - debug_assert!(root_path.is_absolute()); - - self.roots.insert(root_path.to_path_buf()); - - VfsItem::get(self, root_path) - } - pub fn get_roots(&self) -> &HashSet { &self.roots } pub fn get(&self, path: &Path) -> Option<&VfsItem> { debug_assert!(path.is_absolute()); - debug_assert!(self.is_valid_path(path)); + debug_assert!(self.is_within_roots(path)); self.items.get(path) } - pub fn get_contents(&self, path: &Path) -> Option<&[u8]> { + pub fn add_root(&mut self, path: &Path) -> io::Result<()> { debug_assert!(path.is_absolute()); - debug_assert!(self.is_valid_path(path)); + debug_assert!(!self.is_within_roots(path)); - self.contents.get(path).map(Vec::as_slice) + self.roots.insert(path.to_path_buf()); + + VfsItem::read_from_disk(self, path)?; + Ok(()) } - pub fn remove(&mut self, path: &Path) { + pub fn path_created(&mut self, path: &Path) -> io::Result<()> { debug_assert!(path.is_absolute()); - debug_assert!(self.is_valid_path(path)); + debug_assert!(self.is_within_roots(path)); - match self.items.remove(path) { - Some(item) => match item { - VfsItem::File(_) => { - self.contents.remove(path); - }, - VfsItem::Directory(VfsDirectory { children, .. }) => { - for child_path in &children { - self.remove(child_path); - } - }, - }, - None => {}, - } - } - - pub fn add_or_update<'a, 'b>(&'a mut self, path: &'b Path) -> io::Result<&'a VfsItem> { - debug_assert!(path.is_absolute()); - debug_assert!(self.is_valid_path(path)); - - VfsItem::get(self, path) - } - - fn is_valid_path(&self, path: &Path) -> bool { - let mut is_valid_path = false; - - for root_path in &self.roots { - if path.starts_with(root_path) { - is_valid_path = true; - break; + if let Some(parent_path) = path.parent() { + if self.is_within_roots(parent_path) && self.get(parent_path).is_none() { + self.path_created(parent_path)?; } } - is_valid_path + VfsItem::read_from_disk(self, path)?; + Ok(()) + } + + pub fn path_updated(&mut self, path: &Path) -> io::Result<()> { + debug_assert!(path.is_absolute()); + debug_assert!(self.is_within_roots(path)); + + if let Some(parent_path) = path.parent() { + if self.is_within_roots(parent_path) && self.get(parent_path).is_none() { + self.path_created(parent_path)?; + } + } + + VfsItem::read_from_disk(self, path)?; + Ok(()) + } + + pub fn path_removed(&mut self, path: &Path) -> io::Result<()> { + debug_assert!(path.is_absolute()); + debug_assert!(self.is_within_roots(path)); + + if let Some(parent_path) = path.parent() { + if self.is_within_roots(parent_path) { + if let Some(VfsItem::Directory(parent)) = self.items.get_mut(parent_path) { + parent.children.remove(path); + } + } + } + + match self.items.remove(path) { + Some(VfsItem::Directory(directory)) => { + for child_path in &directory.children { + self.path_removed(child_path)?; + } + }, + _ => {}, + } + + Ok(()) + } + + pub fn path_moved(&mut self, from_path: &Path, to_path: &Path) -> io::Result<()> { + debug_assert!(from_path.is_absolute()); + debug_assert!(self.is_within_roots(from_path)); + debug_assert!(to_path.is_absolute()); + debug_assert!(self.is_within_roots(to_path)); + + self.path_removed(from_path)?; + self.path_created(to_path)?; + Ok(()) + } + + fn is_within_roots(&self, path: &Path) -> bool { + for root_path in &self.roots { + if path.starts_with(root_path) { + return true; + } + } + + false } } #[derive(Debug)] pub struct VfsFile { pub path: PathBuf, + pub contents: Vec, } #[derive(Debug)] @@ -105,42 +133,41 @@ pub enum VfsItem { } impl VfsItem { - fn get<'a, 'b>(vfs: &'a mut Vfs, root_path: &'b Path) -> io::Result<&'a VfsItem> { - let metadata = fs::metadata(root_path)?; + fn read_from_disk<'a, 'b>(vfs: &'a mut Vfs, path: &'b Path) -> io::Result<&'a VfsItem> { + let metadata = fs::metadata(path)?; if metadata.is_file() { + let contents = fs::read(path)?; let item = VfsItem::File(VfsFile { - path: root_path.to_path_buf(), + path: path.to_path_buf(), + contents, }); - vfs.items.insert(root_path.to_path_buf(), item); + vfs.items.insert(path.to_path_buf(), item); - let contents = fs::read(root_path)?; - vfs.contents.insert(root_path.to_path_buf(), contents); - - Ok(vfs.items.get(root_path).unwrap()) + Ok(vfs.items.get(path).unwrap()) } else if metadata.is_dir() { let mut children = HashSet::new(); - for entry in fs::read_dir(root_path)? { + for entry in fs::read_dir(path)? { let entry = entry?; - let path = entry.path(); + let child_path = entry.path(); - VfsItem::get(vfs, &path)?; + VfsItem::read_from_disk(vfs, &child_path)?; - children.insert(path); + children.insert(child_path); } let item = VfsItem::Directory(VfsDirectory { - path: root_path.to_path_buf(), + path: path.to_path_buf(), children, }); - vfs.items.insert(root_path.to_path_buf(), item); + vfs.items.insert(path.to_path_buf(), item); - Ok(vfs.items.get(root_path).unwrap()) + Ok(vfs.items.get(path).unwrap()) } else { - unimplemented!(); + panic!("Unexpected non-file, non-directory item"); } } } \ No newline at end of file From 729ab25581992bd9bc29a7c49dfea9a06418c975 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 17 Nov 2018 01:14:07 -0800 Subject: [PATCH 0209/1504] Expose more project stuff via the API --- server/src/project.rs | 11 +++-- server/src/rbx_session.rs | 88 ++++++++++++++++++++++++++------------- server/src/session.rs | 2 +- server/src/web.rs | 5 +++ 4 files changed, 73 insertions(+), 33 deletions(-) diff --git a/server/src/project.rs b/server/src/project.rs index 853c8547..4d761d12 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -137,13 +137,15 @@ impl fmt::Display for ProjectSaveError { } } -#[derive(Debug)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(tag = "type")] pub enum ProjectNode { Instance(InstanceProjectNode), SyncPoint(SyncPointProjectNode), } -#[derive(Debug)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct InstanceProjectNode { pub class_name: String, pub children: HashMap, @@ -151,12 +153,13 @@ pub struct InstanceProjectNode { // ignore_unknown: bool, } -#[derive(Debug)] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct SyncPointProjectNode { pub path: PathBuf, } -#[derive(Debug)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct Project { pub name: String, pub tree: ProjectNode, diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index de3e16c1..13d0f7d2 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -16,6 +16,7 @@ use crate::{ pub struct RbxSession { tree: RbxTree, paths_to_ids: HashMap, + ids_to_project_paths: HashMap, message_queue: Arc, vfs: Arc>, project: Arc, @@ -23,7 +24,7 @@ pub struct RbxSession { impl RbxSession { pub fn new(project: Arc, vfs: Arc>, message_queue: Arc) -> RbxSession { - let (tree, paths_to_ids) = { + let (tree, paths_to_ids, ids_to_project_paths) = { let temp_vfs = vfs.lock().unwrap(); construct_initial_tree(&project, &temp_vfs) }; @@ -31,6 +32,7 @@ impl RbxSession { RbxSession { tree, paths_to_ids, + ids_to_project_paths, message_queue, vfs, project, @@ -56,14 +58,19 @@ impl RbxSession { pub fn get_tree(&self) -> &RbxTree { &self.tree } + + pub fn get_project_path_map(&self) -> &HashMap { + &self.ids_to_project_paths + } } fn construct_initial_tree( project: &Project, vfs: &Vfs, -) -> (RbxTree, HashMap) { - let mut paths_to_ids = HashMap::new(); - let mut tree = RbxTree::new(RbxInstance { +) -> (RbxTree, HashMap, HashMap) { + let paths_to_ids = HashMap::new(); + let ids_to_project_paths = HashMap::new(); + let tree = RbxTree::new(RbxInstance { name: "this isn't supposed to be here".to_string(), class_name: "ahhh, help me".to_string(), properties: HashMap::new(), @@ -71,59 +78,80 @@ fn construct_initial_tree( let root_id = tree.get_root_id(); - construct_initial_tree_node(&mut tree, vfs, &mut paths_to_ids, root_id, "<<>>", &project.tree); + let mut context = ConstructContext { + tree, + vfs, + paths_to_ids, + ids_to_project_paths, + }; - (tree, paths_to_ids) + construct_project_node( + &mut context, + root_id, + "<<>>".to_string(), + "<<>>", + &project.tree, + ); + + (context.tree, context.paths_to_ids, context.ids_to_project_paths) } -fn construct_initial_tree_node( - tree: &mut RbxTree, - vfs: &Vfs, - paths_to_ids: &mut HashMap, +struct ConstructContext<'a> { + tree: RbxTree, + vfs: &'a Vfs, + paths_to_ids: HashMap, + ids_to_project_paths: HashMap, +} + +fn construct_project_node( + context: &mut ConstructContext, parent_instance_id: RbxId, + instance_path: String, instance_name: &str, project_node: &ProjectNode, ) { match project_node { ProjectNode::Instance(node) => { - construct_instance_node(tree, vfs, paths_to_ids, parent_instance_id, instance_name, node); + let id = construct_instance_node(context, parent_instance_id, &instance_path, instance_name, node); + context.ids_to_project_paths.insert(id, instance_path.to_string()); }, ProjectNode::SyncPoint(node) => { - construct_sync_point_node(tree, vfs, paths_to_ids, parent_instance_id, instance_name, &node.path); + let id = construct_sync_point_node(context, parent_instance_id, instance_name, &node.path); + context.ids_to_project_paths.insert(id, instance_path.to_string()); }, } } fn construct_instance_node( - tree: &mut RbxTree, - vfs: &Vfs, - paths_to_ids: &mut HashMap, + context: &mut ConstructContext, parent_instance_id: RbxId, + instance_path: &str, instance_name: &str, project_node: &InstanceProjectNode, -) { +) -> RbxId { let instance = RbxInstance { class_name: project_node.class_name.clone(), name: instance_name.to_string(), properties: HashMap::new(), }; - let id = tree.insert_instance(instance, parent_instance_id); + let id = context.tree.insert_instance(instance, parent_instance_id); for (child_name, child_project_node) in &project_node.children { - construct_initial_tree_node(tree, vfs, paths_to_ids, id, child_name, child_project_node); + let child_path = format!("{}/{}", instance_path, child_name); + construct_project_node(context, id, child_path, child_name, child_project_node); } + + id } fn construct_sync_point_node( - tree: &mut RbxTree, - vfs: &Vfs, - paths_to_ids: &mut HashMap, + context: &mut ConstructContext, parent_instance_id: RbxId, instance_name: &str, file_path: &Path, -) { - match vfs.get(&file_path) { +) -> RbxId { + match context.vfs.get(&file_path) { Some(VfsItem::File(file)) => { let contents = str::from_utf8(&file.contents).unwrap(); @@ -136,8 +164,10 @@ fn construct_sync_point_node( properties, }; - let id = tree.insert_instance(instance, parent_instance_id); - paths_to_ids.insert(file.path.clone(), id); + let id = context.tree.insert_instance(instance, parent_instance_id); + context.paths_to_ids.insert(file.path.clone(), id); + + id }, Some(VfsItem::Directory(directory)) => { let instance = RbxInstance { @@ -146,13 +176,15 @@ fn construct_sync_point_node( properties: HashMap::new(), }; - let id = tree.insert_instance(instance, parent_instance_id); - paths_to_ids.insert(directory.path.clone(), id); + let id = context.tree.insert_instance(instance, parent_instance_id); + context.paths_to_ids.insert(directory.path.clone(), id); for child_path in &directory.children { let child_instance_name = child_path.file_name().unwrap().to_str().unwrap(); - construct_sync_point_node(tree, vfs, paths_to_ids, id, child_instance_name, child_path); + construct_sync_point_node(context, id, child_instance_name, child_path); } + + id }, None => panic!("Couldn't read {} from disk", file_path.display()), } diff --git a/server/src/session.rs b/server/src/session.rs index a546c18b..f072fdd9 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -24,7 +24,7 @@ use crate::{ const WATCH_TIMEOUT_MS: u64 = 100; pub struct Session { - project: Arc, + pub project: Arc, pub session_id: SessionId, pub message_queue: Arc, pub rbx_session: Arc>, diff --git a/server/src/web.rs b/server/src/web.rs index 150c019f..c76ebe2e 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -11,6 +11,7 @@ use crate::{ message_queue::Message, session::Session, session_id::SessionId, + project::Project, }; #[derive(Debug, Serialize, Deserialize)] @@ -20,6 +21,8 @@ pub struct ServerInfoResponse<'a> { pub server_version: &'a str, pub protocol_version: u64, pub root_instance_id: RbxId, + pub project: Cow<'a, Project>, + pub project_paths_to_ids: Cow<'a, HashMap>, } #[derive(Debug, Serialize, Deserialize)] @@ -71,6 +74,8 @@ impl Server { protocol_version: 2, session_id: self.session.session_id, root_instance_id: tree.get_root_id(), + project: Cow::Borrowed(&self.session.project), + project_paths_to_ids: Cow::Borrowed(rbx_session.get_project_path_map()), }) }, From c8bb9bf2e9df080172607881f9b72e8fb9a97316 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 17 Nov 2018 13:46:56 -0800 Subject: [PATCH 0210/1504] Break out file watching into FsWatcher object --- server/src/fs_watcher.rs | 118 ++++++++++++++++++++++++++++++++++++++ server/src/lib.rs | 1 + server/src/session.rs | 121 ++++++--------------------------------- 3 files changed, 135 insertions(+), 105 deletions(-) create mode 100644 server/src/fs_watcher.rs diff --git a/server/src/fs_watcher.rs b/server/src/fs_watcher.rs new file mode 100644 index 00000000..13a79027 --- /dev/null +++ b/server/src/fs_watcher.rs @@ -0,0 +1,118 @@ +use std::{ + sync::{mpsc, Arc, Mutex}, + time::Duration, + thread, +}; + +use notify::{ + self, + DebouncedEvent, + RecommendedWatcher, + RecursiveMode, + Watcher, +}; + +use crate::{ + vfs::Vfs, + rbx_session::RbxSession, +}; + +const WATCH_TIMEOUT: Duration = Duration::from_millis(100); + +fn handle_event(vfs: &Mutex, rbx_session: &Mutex, event: DebouncedEvent) { + match event { + DebouncedEvent::Create(path) => { + { + let mut vfs = vfs.lock().unwrap(); + vfs.path_created(&path).unwrap(); + } + + { + let mut rbx_session = rbx_session.lock().unwrap(); + rbx_session.path_created(&path); + } + }, + DebouncedEvent::Write(path) => { + { + let mut vfs = vfs.lock().unwrap(); + vfs.path_updated(&path).unwrap(); + } + + { + let mut rbx_session = rbx_session.lock().unwrap(); + rbx_session.path_updated(&path); + } + }, + DebouncedEvent::Remove(path) => { + { + let mut vfs = vfs.lock().unwrap(); + vfs.path_removed(&path).unwrap(); + } + + { + let mut rbx_session = rbx_session.lock().unwrap(); + rbx_session.path_removed(&path); + } + }, + DebouncedEvent::Rename(from_path, to_path) => { + { + let mut vfs = vfs.lock().unwrap(); + vfs.path_moved(&from_path, &to_path).unwrap(); + } + + { + let mut rbx_session = rbx_session.lock().unwrap(); + rbx_session.path_renamed(&from_path, &to_path); + } + }, + _ => {}, + } +} + +/// Watches for changes on the filesystem and links together the in-memory +/// filesystem and in-memory Roblox tree. +pub struct FsWatcher { + #[allow(unused)] + watchers: Vec, +} + +impl FsWatcher { + pub fn start(vfs: Arc>, rbx_session: Arc>) -> FsWatcher { + let mut watchers = Vec::new(); + + { + let vfs_temp = vfs.lock().unwrap(); + + for root_path in vfs_temp.get_roots() { + let (watch_tx, watch_rx) = mpsc::channel(); + + let mut watcher = notify::watcher(watch_tx, WATCH_TIMEOUT) + .expect("Could not create `notify` watcher"); + + watcher.watch(root_path, RecursiveMode::Recursive) + .expect("Could not watch directory"); + + watchers.push(watcher); + + let vfs = Arc::clone(&vfs); + let rbx_session = Arc::clone(&rbx_session); + let root_path = root_path.clone(); + + thread::spawn(move || { + info!("Watcher thread ({}) started", root_path.display()); + loop { + match watch_rx.recv() { + Ok(event) => handle_event(&vfs, &rbx_session, event), + Err(_) => break, + }; + } + info!("Watcher thread ({}) stopped", root_path.display()); + }); + } + } + + FsWatcher { + watchers, + } + } +} \ No newline at end of file diff --git a/server/src/lib.rs b/server/src/lib.rs index ca15e9a3..117aa841 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -14,6 +14,7 @@ extern crate tempfile; // pub mod roblox_studio; pub mod commands; +pub mod fs_watcher; pub mod message_queue; pub mod project; pub mod rbx_session; diff --git a/server/src/session.rs b/server/src/session.rs index f072fdd9..fd51dd4f 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -1,16 +1,6 @@ use std::{ - sync::{Arc, Mutex, mpsc}, - thread, + sync::{Arc, Mutex}, io, - time::Duration, -}; - -use notify::{ - self, - DebouncedEvent, - RecommendedWatcher, - RecursiveMode, - Watcher, }; use crate::{ @@ -19,17 +9,15 @@ use crate::{ vfs::Vfs, session_id::SessionId, rbx_session::RbxSession, + fs_watcher::FsWatcher, }; -const WATCH_TIMEOUT_MS: u64 = 100; - pub struct Session { pub project: Arc, pub session_id: SessionId, pub message_queue: Arc, pub rbx_session: Arc>, - vfs: Arc>, - watchers: Vec, + fs_watcher: FsWatcher, } fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> { @@ -49,15 +37,14 @@ fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> impl Session { pub fn new(project: Project) -> io::Result { + let mut vfs = Vfs::new(); + + add_sync_points(&mut vfs, &project.tree) + .expect("Could not add sync points when starting new Rojo session"); + + let vfs = Arc::new(Mutex::new(vfs)); let project = Arc::new(project); let message_queue = Arc::new(MessageQueue::new()); - let vfs = Arc::new(Mutex::new(Vfs::new())); - - { - let mut vfs = vfs.lock().unwrap(); - add_sync_points(&mut vfs, &project.tree) - .expect("Could not add sync points when starting new Rojo session"); - } let rbx_session = Arc::new(Mutex::new(RbxSession::new( Arc::clone(&project), @@ -65,95 +52,19 @@ impl Session { Arc::clone(&message_queue), ))); - let mut watchers = Vec::new(); - - { - let vfs_temp = vfs.lock().unwrap(); - - for root in vfs_temp.get_roots() { - info!("Watching path {}", root.display()); - - let (watch_tx, watch_rx) = mpsc::channel(); - - let mut watcher = notify::watcher(watch_tx, Duration::from_millis(WATCH_TIMEOUT_MS)).unwrap(); - - watcher.watch(root, RecursiveMode::Recursive) - .expect("Could not watch directory"); - - watchers.push(watcher); - - let vfs = Arc::clone(&vfs); - let rbx_session = Arc::clone(&rbx_session); - - thread::spawn(move || { - loop { - match watch_rx.recv() { - Ok(event) => { - match event { - DebouncedEvent::Create(path) => { - { - let mut vfs = vfs.lock().unwrap(); - vfs.path_created(&path).unwrap(); - } - - { - let mut rbx_session = rbx_session.lock().unwrap(); - rbx_session.path_created(&path); - } - }, - DebouncedEvent::Write(path) => { - { - let mut vfs = vfs.lock().unwrap(); - vfs.path_updated(&path).unwrap(); - } - - { - let mut rbx_session = rbx_session.lock().unwrap(); - rbx_session.path_updated(&path); - } - }, - DebouncedEvent::Remove(path) => { - { - let mut vfs = vfs.lock().unwrap(); - vfs.path_removed(&path).unwrap(); - } - - { - let mut rbx_session = rbx_session.lock().unwrap(); - rbx_session.path_removed(&path); - } - }, - DebouncedEvent::Rename(from_path, to_path) => { - { - let mut vfs = vfs.lock().unwrap(); - vfs.path_moved(&from_path, &to_path).unwrap(); - } - - { - let mut rbx_session = rbx_session.lock().unwrap(); - rbx_session.path_renamed(&from_path, &to_path); - } - }, - _ => {}, - }; - }, - Err(_) => break, - }; - } - info!("Watcher thread stopped"); - }); - } - } + let fs_watcher = FsWatcher::start( + Arc::clone(&vfs), + Arc::clone(&rbx_session), + ); let session_id = SessionId::new(); Ok(Session { - session_id, - rbx_session, project, + session_id, message_queue, - vfs, - watchers, + rbx_session, + fs_watcher, }) } From 16c3c1f49897d8bcbc1c4d37211c3ad91b407437 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 17 Nov 2018 13:51:22 -0800 Subject: [PATCH 0211/1504] Vfs -> Imfs, clean up and document a bit --- server/Cargo.lock | 10 +++----- server/Cargo.toml | 1 + server/src/fs_watcher.rs | 30 +++++++++++------------ server/src/{vfs.rs => imfs.rs} | 45 ++++++++++++++++++---------------- server/src/lib.rs | 2 +- server/src/rbx_session.rs | 24 +++++++++--------- server/src/session.rs | 18 +++++++------- server/tests/read_projects.rs | 2 -- test-projects/foo.json | 1 + 9 files changed, 67 insertions(+), 66 deletions(-) rename server/src/{vfs.rs => imfs.rs} (78%) diff --git a/server/Cargo.lock b/server/Cargo.lock index 3242e81a..9c2c0a85 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -349,11 +349,8 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "libc" @@ -698,6 +695,7 @@ version = "0.5.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -875,7 +873,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1117,7 +1115,7 @@ dependencies = [ "checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" "checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca488b89a5657b0a2ecd45b95609b3e848cf1755da332a0da46e2b2b1cb371a7" +"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2" diff --git a/server/Cargo.toml b/server/Cargo.toml index 21cf0ba5..95369e2c 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -35,3 +35,4 @@ uuid = { version = "0.7", features = ["v4", "serde"] } [dev-dependencies] tempfile = "3.0" walkdir = "2.1" +lazy_static = "1.2" diff --git a/server/src/fs_watcher.rs b/server/src/fs_watcher.rs index 13a79027..a48319ef 100644 --- a/server/src/fs_watcher.rs +++ b/server/src/fs_watcher.rs @@ -13,18 +13,18 @@ use notify::{ }; use crate::{ - vfs::Vfs, + imfs::Imfs, rbx_session::RbxSession, }; const WATCH_TIMEOUT: Duration = Duration::from_millis(100); -fn handle_event(vfs: &Mutex, rbx_session: &Mutex, event: DebouncedEvent) { +fn handle_event(imfs: &Mutex, rbx_session: &Mutex, event: DebouncedEvent) { match event { DebouncedEvent::Create(path) => { { - let mut vfs = vfs.lock().unwrap(); - vfs.path_created(&path).unwrap(); + let mut imfs = imfs.lock().unwrap(); + imfs.path_created(&path).unwrap(); } { @@ -34,8 +34,8 @@ fn handle_event(vfs: &Mutex, rbx_session: &Mutex, event: Deboun }, DebouncedEvent::Write(path) => { { - let mut vfs = vfs.lock().unwrap(); - vfs.path_updated(&path).unwrap(); + let mut imfs = imfs.lock().unwrap(); + imfs.path_updated(&path).unwrap(); } { @@ -45,8 +45,8 @@ fn handle_event(vfs: &Mutex, rbx_session: &Mutex, event: Deboun }, DebouncedEvent::Remove(path) => { { - let mut vfs = vfs.lock().unwrap(); - vfs.path_removed(&path).unwrap(); + let mut imfs = imfs.lock().unwrap(); + imfs.path_removed(&path).unwrap(); } { @@ -56,8 +56,8 @@ fn handle_event(vfs: &Mutex, rbx_session: &Mutex, event: Deboun }, DebouncedEvent::Rename(from_path, to_path) => { { - let mut vfs = vfs.lock().unwrap(); - vfs.path_moved(&from_path, &to_path).unwrap(); + let mut imfs = imfs.lock().unwrap(); + imfs.path_moved(&from_path, &to_path).unwrap(); } { @@ -77,13 +77,13 @@ pub struct FsWatcher { } impl FsWatcher { - pub fn start(vfs: Arc>, rbx_session: Arc>) -> FsWatcher { + pub fn start(imfs: Arc>, rbx_session: Arc>) -> FsWatcher { let mut watchers = Vec::new(); { - let vfs_temp = vfs.lock().unwrap(); + let imfs_temp = imfs.lock().unwrap(); - for root_path in vfs_temp.get_roots() { + for root_path in imfs_temp.get_roots() { let (watch_tx, watch_rx) = mpsc::channel(); let mut watcher = notify::watcher(watch_tx, WATCH_TIMEOUT) @@ -94,7 +94,7 @@ impl FsWatcher { watchers.push(watcher); - let vfs = Arc::clone(&vfs); + let imfs = Arc::clone(&imfs); let rbx_session = Arc::clone(&rbx_session); let root_path = root_path.clone(); @@ -102,7 +102,7 @@ impl FsWatcher { info!("Watcher thread ({}) started", root_path.display()); loop { match watch_rx.recv() { - Ok(event) => handle_event(&vfs, &rbx_session, event), + Ok(event) => handle_event(&imfs, &rbx_session, event), Err(_) => break, }; } diff --git a/server/src/vfs.rs b/server/src/imfs.rs similarity index 78% rename from server/src/vfs.rs rename to server/src/imfs.rs index b744d567..519faaaf 100644 --- a/server/src/vfs.rs +++ b/server/src/imfs.rs @@ -5,15 +5,18 @@ use std::{ io, }; +/// The in-memory filesystem keeps a mirror of all files being watcher by Rojo +/// in order to deduplicate file changes in the case of bidirectional syncing +/// from Roblox Studio. #[derive(Debug)] -pub struct Vfs { - items: HashMap, +pub struct Imfs { + items: HashMap, roots: HashSet, } -impl Vfs { - pub fn new() -> Vfs { - Vfs { +impl Imfs { + pub fn new() -> Imfs { + Imfs { items: HashMap::new(), roots: HashSet::new(), } @@ -23,7 +26,7 @@ impl Vfs { &self.roots } - pub fn get(&self, path: &Path) -> Option<&VfsItem> { + pub fn get(&self, path: &Path) -> Option<&ImfsItem> { debug_assert!(path.is_absolute()); debug_assert!(self.is_within_roots(path)); @@ -36,7 +39,7 @@ impl Vfs { self.roots.insert(path.to_path_buf()); - VfsItem::read_from_disk(self, path)?; + ImfsItem::read_from_disk(self, path)?; Ok(()) } @@ -50,7 +53,7 @@ impl Vfs { } } - VfsItem::read_from_disk(self, path)?; + ImfsItem::read_from_disk(self, path)?; Ok(()) } @@ -64,7 +67,7 @@ impl Vfs { } } - VfsItem::read_from_disk(self, path)?; + ImfsItem::read_from_disk(self, path)?; Ok(()) } @@ -74,14 +77,14 @@ impl Vfs { if let Some(parent_path) = path.parent() { if self.is_within_roots(parent_path) { - if let Some(VfsItem::Directory(parent)) = self.items.get_mut(parent_path) { + if let Some(ImfsItem::Directory(parent)) = self.items.get_mut(parent_path) { parent.children.remove(path); } } } match self.items.remove(path) { - Some(VfsItem::Directory(directory)) => { + Some(ImfsItem::Directory(directory)) => { for child_path in &directory.children { self.path_removed(child_path)?; } @@ -115,30 +118,30 @@ impl Vfs { } #[derive(Debug)] -pub struct VfsFile { +pub struct ImfsFile { pub path: PathBuf, pub contents: Vec, } #[derive(Debug)] -pub struct VfsDirectory { +pub struct ImfsDirectory { pub path: PathBuf, pub children: HashSet, } #[derive(Debug)] -pub enum VfsItem { - File(VfsFile), - Directory(VfsDirectory), +pub enum ImfsItem { + File(ImfsFile), + Directory(ImfsDirectory), } -impl VfsItem { - fn read_from_disk<'a, 'b>(vfs: &'a mut Vfs, path: &'b Path) -> io::Result<&'a VfsItem> { +impl ImfsItem { + fn read_from_disk<'a, 'b>(vfs: &'a mut Imfs, path: &'b Path) -> io::Result<&'a ImfsItem> { let metadata = fs::metadata(path)?; if metadata.is_file() { let contents = fs::read(path)?; - let item = VfsItem::File(VfsFile { + let item = ImfsItem::File(ImfsFile { path: path.to_path_buf(), contents, }); @@ -153,12 +156,12 @@ impl VfsItem { let entry = entry?; let child_path = entry.path(); - VfsItem::read_from_disk(vfs, &child_path)?; + ImfsItem::read_from_disk(vfs, &child_path)?; children.insert(child_path); } - let item = VfsItem::Directory(VfsDirectory { + let item = ImfsItem::Directory(ImfsDirectory { path: path.to_path_buf(), children, }); diff --git a/server/src/lib.rs b/server/src/lib.rs index 117aa841..cde3cdb4 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -20,6 +20,6 @@ pub mod project; pub mod rbx_session; pub mod session; pub mod session_id; -pub mod vfs; +pub mod imfs; pub mod web; pub mod web_util; \ No newline at end of file diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 13d0f7d2..397f949c 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -10,7 +10,7 @@ use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; use crate::{ project::{Project, ProjectNode, InstanceProjectNode}, message_queue::MessageQueue, - vfs::{Vfs, VfsItem}, + imfs::{Imfs, ImfsItem}, }; pub struct RbxSession { @@ -18,15 +18,15 @@ pub struct RbxSession { paths_to_ids: HashMap, ids_to_project_paths: HashMap, message_queue: Arc, - vfs: Arc>, + imfs: Arc>, project: Arc, } impl RbxSession { - pub fn new(project: Arc, vfs: Arc>, message_queue: Arc) -> RbxSession { + pub fn new(project: Arc, imfs: Arc>, message_queue: Arc) -> RbxSession { let (tree, paths_to_ids, ids_to_project_paths) = { - let temp_vfs = vfs.lock().unwrap(); - construct_initial_tree(&project, &temp_vfs) + let temp_imfs = imfs.lock().unwrap(); + construct_initial_tree(&project, &temp_imfs) }; RbxSession { @@ -34,7 +34,7 @@ impl RbxSession { paths_to_ids, ids_to_project_paths, message_queue, - vfs, + imfs, project, } } @@ -66,7 +66,7 @@ impl RbxSession { fn construct_initial_tree( project: &Project, - vfs: &Vfs, + imfs: &Imfs, ) -> (RbxTree, HashMap, HashMap) { let paths_to_ids = HashMap::new(); let ids_to_project_paths = HashMap::new(); @@ -80,7 +80,7 @@ fn construct_initial_tree( let mut context = ConstructContext { tree, - vfs, + imfs, paths_to_ids, ids_to_project_paths, }; @@ -98,7 +98,7 @@ fn construct_initial_tree( struct ConstructContext<'a> { tree: RbxTree, - vfs: &'a Vfs, + imfs: &'a Imfs, paths_to_ids: HashMap, ids_to_project_paths: HashMap, } @@ -151,8 +151,8 @@ fn construct_sync_point_node( instance_name: &str, file_path: &Path, ) -> RbxId { - match context.vfs.get(&file_path) { - Some(VfsItem::File(file)) => { + match context.imfs.get(&file_path) { + Some(ImfsItem::File(file)) => { let contents = str::from_utf8(&file.contents).unwrap(); let mut properties = HashMap::new(); @@ -169,7 +169,7 @@ fn construct_sync_point_node( id }, - Some(VfsItem::Directory(directory)) => { + Some(ImfsItem::Directory(directory)) => { let instance = RbxInstance { class_name: "Folder".to_string(), name: instance_name.to_string(), diff --git a/server/src/session.rs b/server/src/session.rs index fd51dd4f..ca237dee 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -6,7 +6,7 @@ use std::{ use crate::{ message_queue::MessageQueue, project::{Project, ProjectNode}, - vfs::Vfs, + imfs::Imfs, session_id::SessionId, rbx_session::RbxSession, fs_watcher::FsWatcher, @@ -20,15 +20,15 @@ pub struct Session { fs_watcher: FsWatcher, } -fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> { +fn add_sync_points(imfs: &mut Imfs, project_node: &ProjectNode) -> io::Result<()> { match project_node { ProjectNode::Instance(node) => { for child in node.children.values() { - add_sync_points(vfs, child)?; + add_sync_points(imfs, child)?; } }, ProjectNode::SyncPoint(node) => { - vfs.add_root(&node.path)?; + imfs.add_root(&node.path)?; }, } @@ -37,23 +37,23 @@ fn add_sync_points(vfs: &mut Vfs, project_node: &ProjectNode) -> io::Result<()> impl Session { pub fn new(project: Project) -> io::Result { - let mut vfs = Vfs::new(); + let mut imfs = Imfs::new(); - add_sync_points(&mut vfs, &project.tree) + add_sync_points(&mut imfs, &project.tree) .expect("Could not add sync points when starting new Rojo session"); - let vfs = Arc::new(Mutex::new(vfs)); + let imfs = Arc::new(Mutex::new(imfs)); let project = Arc::new(project); let message_queue = Arc::new(MessageQueue::new()); let rbx_session = Arc::new(Mutex::new(RbxSession::new( Arc::clone(&project), - Arc::clone(&vfs), + Arc::clone(&imfs), Arc::clone(&message_queue), ))); let fs_watcher = FsWatcher::start( - Arc::clone(&vfs), + Arc::clone(&imfs), Arc::clone(&rbx_session), ); diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index ac9fbd4a..d547e7d0 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -22,7 +22,6 @@ fn foo() { let project = Project::load_exact(&project_file_location).unwrap(); assert_eq!(project.name, "foo"); - assert_eq!(project.tree.len(), 1); } #[test] @@ -31,5 +30,4 @@ fn empty() { let project = Project::load_exact(&project_file_location).unwrap(); assert_eq!(project.name, "empty"); - assert_eq!(project.tree.len(), 0); } \ No newline at end of file diff --git a/test-projects/foo.json b/test-projects/foo.json index f12be6a8..e93d066d 100644 --- a/test-projects/foo.json +++ b/test-projects/foo.json @@ -1,6 +1,7 @@ { "name": "foo", "tree": { + "$className": "DataModel", "ReplicatedStorage": { "$className": "ReplicatedStorage", "Rojo": { From f632444a0e60db0dbb4320f0cee79e8cc1cf5d02 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 17 Nov 2018 14:58:07 -0800 Subject: [PATCH 0212/1504] Update design graph --- design.gv | 49 +++++++++++++++++++++++++++++-------------------- 1 file changed, 29 insertions(+), 20 deletions(-) diff --git a/design.gv b/design.gv index 910efaf4..479ab71c 100644 --- a/design.gv +++ b/design.gv @@ -1,30 +1,39 @@ digraph G { - ranksep=0.7; + graph [ + ranksep = "0.7", + nodesep = "1.0", + ]; node [ - fontname="Hack", - shape="box", + fontname = "Hack", + shape = "record", ]; - roblox_studio -> plugin [dir="both"]; - plugin -> web_server [style="dashed", dir="both"]; + roblox_studio -> plugin [dir = "both"]; + plugin -> web_server [style = "dashed", dir = "both"]; - web_server -> rbx_session; + web_server -> session; - session -> rbx_session [dir="both"]; - session -> vfs_session; - session -> watchers [dir="both"]; + session -> rbx_session; + session -> fs_watcher; + session -> message_queue; - vfs_session -> fs; + fs_watcher -> imfs [weight = "10"]; + fs_watcher -> rbx_session [constraint = "false"]; - rbx_session -> vfs_session [constraint=false]; - rbx_session -> middlewares; + imfs -> fs; - roblox_studio [label="Roblox Studio"]; - fs [label="Filesystem"]; - middlewares [label="Vec"]; - watchers [label="Vec"]; - session [label="Session"]; - web_server [label="Rouille Server"]; - vfs_session [label="Arc>"]; - rbx_session [label="Arc>"]; + rbx_session -> imfs; + rbx_session -> middlewares [weight = "10"]; + rbx_session -> message_queue [constraint = "false"]; + + plugin [label = "Studio Plugin"]; + roblox_studio [label = "Roblox Studio"]; + fs [label = "Filesystem"]; + fs_watcher [label = "Filesystem Watcher"]; + session [label = "Session"]; + web_server [label = "Web API"]; + imfs [label = "In-Memory Filesystem"]; + rbx_session [label = "RbxSession"]; + message_queue [label = "MessageQueue"]; + middlewares [label = "Middlewares"]; } \ No newline at end of file From 767a59a481a1d3c78469411c0f6ef86ed95ebd56 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 17 Nov 2018 20:17:24 -0800 Subject: [PATCH 0213/1504] Handle removing folders and their path-to-ID associations better --- server/Cargo.lock | 2 +- server/src/message_queue.rs | 22 +++--- server/src/rbx_session.rs | 129 +++++++++++++++++++++++++++++++----- 3 files changed, 120 insertions(+), 33 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 9c2c0a85..b0d15526 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -641,7 +641,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rbx-tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#124175066fa31e114fe55cca627dad4cae571a63" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#258b458cffbcbd01e3f1cf5bbd701cc75260f01a" dependencies = [ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/server/src/message_queue.rs b/server/src/message_queue.rs index 75c4ab2f..c7f75133 100644 --- a/server/src/message_queue.rs +++ b/server/src/message_queue.rs @@ -24,8 +24,8 @@ pub fn get_listener_id() -> ListenerId { #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "type")] pub enum Message { - InstanceChanged { - id: RbxId, + InstancesRemoved { + ids: Vec, }, } @@ -50,29 +50,23 @@ impl MessageQueue { messages.extend_from_slice(new_messages); } - { - for listener in message_listeners.values() { - listener.send(()).unwrap(); - } + for listener in message_listeners.values() { + listener.send(()).unwrap(); } } pub fn subscribe(&self, sender: mpsc::Sender<()>) -> ListenerId { let id = get_listener_id(); - { - let mut message_listeners = self.message_listeners.lock().unwrap(); - message_listeners.insert(id, sender); - } + let mut message_listeners = self.message_listeners.lock().unwrap(); + message_listeners.insert(id, sender); id } pub fn unsubscribe(&self, id: ListenerId) { - { - let mut message_listeners = self.message_listeners.lock().unwrap(); - message_listeners.remove(&id); - } + let mut message_listeners = self.message_listeners.lock().unwrap(); + message_listeners.remove(&id); } pub fn get_message_cursor(&self) -> u32 { diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 397f949c..0a721d17 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -1,5 +1,5 @@ use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, path::{Path, PathBuf}, sync::{Arc, Mutex}, str, @@ -9,13 +9,83 @@ use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; use crate::{ project::{Project, ProjectNode, InstanceProjectNode}, - message_queue::MessageQueue, + message_queue::{Message, MessageQueue}, imfs::{Imfs, ImfsItem}, }; +#[derive(Debug)] +struct PathIdNode { + id: RbxId, + children: HashSet, +} + +/// A map from paths to instance IDs, with a bit of additional data that enables +/// removing a path and all of its child paths from the tree in constant time. +#[derive(Debug)] +struct PathIdTree { + nodes: HashMap, +} + +impl PathIdTree { + pub fn new() -> PathIdTree { + PathIdTree { + nodes: HashMap::new(), + } + } + + pub fn insert(&mut self, path: &Path, id: RbxId) { + if let Some(parent_path) = path.parent() { + if let Some(mut parent) = self.nodes.get_mut(parent_path) { + parent.children.insert(path.to_path_buf()); + } + } + + self.nodes.insert(path.to_path_buf(), PathIdNode { + id, + children: HashSet::new(), + }); + } + + pub fn remove(&mut self, root_path: &Path) -> Option { + if let Some(parent_path) = root_path.parent() { + if let Some(mut parent) = self.nodes.get_mut(parent_path) { + parent.children.remove(root_path); + } + } + + let mut root_node = match self.nodes.remove(root_path) { + Some(node) => node, + None => return None, + }; + + let root_id = root_node.id; + let mut to_visit: Vec = root_node.children.drain().collect(); + + loop { + let next_path = match to_visit.pop() { + Some(path) => path, + None => break, + }; + + match self.nodes.remove(&next_path) { + Some(mut node) => { + for child in node.children.drain() { + to_visit.push(child); + } + }, + None => { + warn!("Consistency issue; tried to remove {} but it was already removed", next_path.display()); + }, + } + } + + Some(root_id) + } +} + pub struct RbxSession { tree: RbxTree, - paths_to_ids: HashMap, + path_id_tree: PathIdTree, ids_to_project_paths: HashMap, message_queue: Arc, imfs: Arc>, @@ -24,14 +94,14 @@ pub struct RbxSession { impl RbxSession { pub fn new(project: Arc, imfs: Arc>, message_queue: Arc) -> RbxSession { - let (tree, paths_to_ids, ids_to_project_paths) = { + let (tree, path_id_tree, ids_to_project_paths) = { let temp_imfs = imfs.lock().unwrap(); construct_initial_tree(&project, &temp_imfs) }; RbxSession { tree, - paths_to_ids, + path_id_tree, ids_to_project_paths, message_queue, imfs, @@ -49,10 +119,33 @@ impl RbxSession { pub fn path_removed(&mut self, path: &Path) { info!("Path removed: {}", path.display()); + + let instance_id = match self.path_id_tree.remove(path) { + Some(id) => id, + None => return, + }; + + let removed_subtree = match self.tree.remove_instance(instance_id) { + Some(tree) => tree, + None => { + warn!("Rojo tried to remove an instance that was half cleaned-up. This is probably a bug in Rojo."); + return; + }, + }; + + let removed_ids: Vec = removed_subtree.iter_all_ids().collect(); + + self.message_queue.push_messages(&[ + Message::InstancesRemoved { + ids: removed_ids, + }, + ]); } pub fn path_renamed(&mut self, from_path: &Path, to_path: &Path) { info!("Path renamed from {} to {}", from_path.display(), to_path.display()); + self.path_removed(from_path); + self.path_created(to_path); } pub fn get_tree(&self) -> &RbxTree { @@ -64,11 +157,18 @@ impl RbxSession { } } +struct ConstructContext<'a> { + tree: RbxTree, + imfs: &'a Imfs, + path_id_tree: PathIdTree, + ids_to_project_paths: HashMap, +} + fn construct_initial_tree( project: &Project, imfs: &Imfs, -) -> (RbxTree, HashMap, HashMap) { - let paths_to_ids = HashMap::new(); +) -> (RbxTree, PathIdTree, HashMap) { + let path_id_tree = PathIdTree::new(); let ids_to_project_paths = HashMap::new(); let tree = RbxTree::new(RbxInstance { name: "this isn't supposed to be here".to_string(), @@ -81,7 +181,7 @@ fn construct_initial_tree( let mut context = ConstructContext { tree, imfs, - paths_to_ids, + path_id_tree, ids_to_project_paths, }; @@ -93,14 +193,7 @@ fn construct_initial_tree( &project.tree, ); - (context.tree, context.paths_to_ids, context.ids_to_project_paths) -} - -struct ConstructContext<'a> { - tree: RbxTree, - imfs: &'a Imfs, - paths_to_ids: HashMap, - ids_to_project_paths: HashMap, + (context.tree, context.path_id_tree, context.ids_to_project_paths) } fn construct_project_node( @@ -165,7 +258,7 @@ fn construct_sync_point_node( }; let id = context.tree.insert_instance(instance, parent_instance_id); - context.paths_to_ids.insert(file.path.clone(), id); + context.path_id_tree.insert(&file.path, id); id }, @@ -177,7 +270,7 @@ fn construct_sync_point_node( }; let id = context.tree.insert_instance(instance, parent_instance_id); - context.paths_to_ids.insert(directory.path.clone(), id); + context.path_id_tree.insert(&directory.path, id); for child_path in &directory.children { let child_instance_name = child_path.file_name().unwrap().to_str().unwrap(); From 9db31c9191834faecf9f575cf5af87ac3b848245 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 10:38:44 -0800 Subject: [PATCH 0214/1504] Stub out build command for generating rbxmx files --- server/src/bin.rs | 24 ++++++++++++++++++++++++ server/src/commands/build.rs | 13 +++++++++++++ server/src/commands/mod.rs | 4 +++- 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 server/src/commands/build.rs diff --git a/server/src/bin.rs b/server/src/bin.rs index d8783082..acef7ece 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -10,6 +10,8 @@ use std::{ env, }; +use librojo::commands; + fn make_path_absolute(value: &Path) -> PathBuf { if value.is_absolute() { PathBuf::from(value) @@ -40,6 +42,11 @@ fn main() { (@arg port: --port +takes_value "The port to listen on. Defaults to 8000.") ) + (@subcommand build => + (about: "Generates a .model.json, rbxm, or rbxmx model from the project.") + (@arg PROJECT: "Path to the project to serve. Defaults to the current directory.") + (@arg output: --output +takes_value +required "Where to output the result.") + ) ).get_matches(); match matches.subcommand() { @@ -60,6 +67,23 @@ fn main() { librojo::commands::serve(&project_path); }, + ("build", sub_matches) => { + let sub_matches = sub_matches.unwrap(); + + let fuzzy_project_path = match sub_matches.value_of("PROJECT") { + Some(v) => make_path_absolute(Path::new(v)), + None => std::env::current_dir().unwrap(), + }; + + let output_file = make_path_absolute(Path::new(sub_matches.value_of("output").unwrap())); + + let options = commands::BuildOptions { + fuzzy_project_path, + output_file, + }; + + commands::build(&options); + }, _ => { error!("Please specify a subcommand!"); error!("Try 'rojo help' for information."); diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs new file mode 100644 index 00000000..0c7d51eb --- /dev/null +++ b/server/src/commands/build.rs @@ -0,0 +1,13 @@ +use std::{ + path::PathBuf, +}; + +#[derive(Debug)] +pub struct BuildOptions { + pub fuzzy_project_path: PathBuf, + pub output_file: PathBuf, +} + +pub fn build(options: &BuildOptions) { + println!("build {:#?}", options); +} \ No newline at end of file diff --git a/server/src/commands/mod.rs b/server/src/commands/mod.rs index db228aa1..6f2bb133 100644 --- a/server/src/commands/mod.rs +++ b/server/src/commands/mod.rs @@ -1,5 +1,7 @@ mod serve; mod init; +mod build; pub use self::serve::*; -pub use self::init::*; \ No newline at end of file +pub use self::init::*; +pub use self::build::*; \ No newline at end of file From 6617b8b6c459d7d2a61fcf417bcf5155205cca0e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 10:45:02 -0800 Subject: [PATCH 0215/1504] Move server to (temporarily) require Rust Beta or stable 1.31+ --- .travis.yml | 13 ++++++++----- README.md | 4 +++- server/Cargo.toml | 1 + server/src/commands/init.rs | 2 +- server/src/commands/serve.rs | 2 +- server/src/project.rs | 1 + 6 files changed, 15 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index b83c1564..ba811ce8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,12 +25,15 @@ matrix: - cd plugin - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install - - language: rust - rust: stable + # Stable builds can be re-enabled after 2018-12-06, when Rust 1.31 is stable + + # - language: rust + # rust: stable + + # script: + # - cd server + # - cargo test --verbose - script: - - cd server - - cargo test --verbose - language: rust rust: beta diff --git a/README.md b/README.md index 99a54a58..df944095 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,9 @@ Here are a few, if you're looking for alternatives or supplements to Rojo: If you use a plugin that _isn't_ Rojo for syncing code, open an issue and let me know why! I'd like Rojo to be the end-all tool so that people stop reinventing solutions to this problem. ## Contributing -The `master` branch is undergoing a rewrite right now known as 'Epiphany'. It includes a breaking change to the project configuration format and an infrastructure overhaul. +The `master` branch is a rewrite known as **Epiphany**. It includes a breaking change to the project configuration format and an infrastructure overhaul. + +Building Rojo requires the latest Rust beta in order to use **2018 Edition** features. Once Rust 1.31 is stable on **December 6, 2018**, Rojo `master` will compile on Rust stable again. Pull requests are welcome! diff --git a/server/Cargo.toml b/server/Cargo.toml index 95369e2c..022ef5a2 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" repository = "https://github.com/LPGhatguy/rojo" +edition = "2018" [lib] name = "librojo" diff --git a/server/src/commands/init.rs b/server/src/commands/init.rs index 05407f14..186d531c 100644 --- a/server/src/commands/init.rs +++ b/server/src/commands/init.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; use std::process; -use project::Project; +use crate::project::Project; pub fn init(project_path: &PathBuf) { match Project::init(project_path) { diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index c00eec8d..d7c8e9a4 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -4,7 +4,7 @@ use std::{ sync::Arc, }; -use ::{ +use crate::{ project::Project, web::Server, session::Session, diff --git a/server/src/project.rs b/server/src/project.rs index 4d761d12..54ffa601 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -5,6 +5,7 @@ use std::{ io, path::{Path, PathBuf}, }; + use serde_json; pub static PROJECT_FILENAME: &'static str = "roblox-project.json"; From f7689f3154755a816bd3b35b58076c85478321c7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 10:50:52 -0800 Subject: [PATCH 0216/1504] Take advantage of 2018 edition. - Remove explicit 'extern crate' fields where useful - Fix mutability of variable (unrelated?) - Add rbxmx dependency, which needs 2018 edition --- server/Cargo.lock | 19 ++++++++++++++++++- server/Cargo.toml | 1 + server/src/bin.rs | 3 --- server/src/lib.rs | 15 +++++---------- server/src/rbx_session.rs | 4 ++-- server/src/web.rs | 7 ++++++- 6 files changed, 32 insertions(+), 17 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index b0d15526..d96eab56 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -641,13 +641,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rbx-tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#258b458cffbcbd01e3f1cf5bbd701cc75260f01a" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#0fe8dacd013668e194afb1d074161477ebc759b6" dependencies = [ "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rbxmx" +version = "0.1.0" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#0fe8dacd013668e194afb1d074161477ebc759b6" +dependencies = [ + "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", + "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" version = "0.1.40" @@ -700,6 +709,7 @@ dependencies = [ "notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", + "rbxmx 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1069,6 +1079,11 @@ dependencies = [ "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "xml-rs" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [metadata] "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee94e9463ccb9d681e7b708082687b2c56d2bd420ca8a3d3157d27d59508ec0" @@ -1149,6 +1164,7 @@ dependencies = [ "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" "checksum rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" +"checksum rbxmx 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025" @@ -1200,3 +1216,4 @@ dependencies = [ "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +"checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" diff --git a/server/Cargo.toml b/server/Cargo.toml index 022ef5a2..4ac23ec1 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -31,6 +31,7 @@ regex = "1.0" log = "0.4" env_logger = "0.5" rbx-tree = { git = "https://github.com/LPGhatguy/rbx-tree.git" } +rbxmx = { git = "https://github.com/LPGhatguy/rbx-tree.git" } uuid = { version = "0.7", features = ["v4", "serde"] } [dev-dependencies] diff --git a/server/src/bin.rs b/server/src/bin.rs index acef7ece..922cabc6 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -1,8 +1,5 @@ #[macro_use] extern crate clap; #[macro_use] extern crate log; -extern crate env_logger; - -extern crate librojo; use std::{ path::{Path, PathBuf}, diff --git a/server/src/lib.rs b/server/src/lib.rs index cde3cdb4..536f781b 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,13 +1,8 @@ -#[macro_use] extern crate log; -#[macro_use] extern crate rouille; -#[macro_use] extern crate serde_derive; -extern crate notify; -extern crate rand; -extern crate rbx_tree; -extern crate regex; -extern crate serde; -extern crate serde_json; -extern crate uuid; +#[macro_use] +extern crate log; + +#[macro_use] +extern crate serde_derive; #[cfg(test)] extern crate tempfile; diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 0a721d17..52f73c08 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -35,7 +35,7 @@ impl PathIdTree { pub fn insert(&mut self, path: &Path, id: RbxId) { if let Some(parent_path) = path.parent() { - if let Some(mut parent) = self.nodes.get_mut(parent_path) { + if let Some(parent) = self.nodes.get_mut(parent_path) { parent.children.insert(path.to_path_buf()); } } @@ -48,7 +48,7 @@ impl PathIdTree { pub fn remove(&mut self, root_path: &Path) -> Option { if let Some(parent_path) = root_path.parent() { - if let Some(mut parent) = self.nodes.get_mut(parent_path) { + if let Some(parent) = self.nodes.get_mut(parent_path) { parent.children.remove(root_path); } } diff --git a/server/src/web.rs b/server/src/web.rs index c76ebe2e..168db49b 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -4,7 +4,12 @@ use std::{ sync::{mpsc, Arc}, }; -use rouille::{self, Request, Response}; +use rouille::{ + self, + router, + Request, + Response, +}; use rbx_tree::{RbxId, RootedRbxInstance}; use crate::{ From 7c585fcbce889f9b4dfa286d49f8f94fe772e500 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 13:28:43 -0800 Subject: [PATCH 0217/1504] Clean up bin, print better help text --- server/src/bin.rs | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/server/src/bin.rs b/server/src/bin.rs index 922cabc6..625b9d05 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -1,9 +1,7 @@ #[macro_use] extern crate clap; -#[macro_use] extern crate log; use std::{ path::{Path, PathBuf}, - process, env, }; @@ -23,7 +21,7 @@ fn main() { .default_format_timestamp(false) .init(); - let matches = clap_app!(rojo => + let mut app = clap_app!(Rojo => (version: env!("CARGO_PKG_VERSION")) (author: env!("CARGO_PKG_AUTHORS")) (about: env!("CARGO_PKG_DESCRIPTION")) @@ -40,23 +38,23 @@ fn main() { ) (@subcommand build => - (about: "Generates a .model.json, rbxm, or rbxmx model from the project.") + (about: "Generates an rbxmx model file from the project.") (@arg PROJECT: "Path to the project to serve. Defaults to the current directory.") (@arg output: --output +takes_value +required "Where to output the result.") ) - ).get_matches(); + ); + + // `get_matches` consumes self for some reason. + let matches = app.clone().get_matches(); match matches.subcommand() { - ("init", sub_matches) => { - let sub_matches = sub_matches.unwrap(); + ("init", Some(sub_matches)) => { let project_path = Path::new(sub_matches.value_of("PATH").unwrap_or(".")); let full_path = make_path_absolute(project_path); librojo::commands::init(&full_path); }, - ("serve", sub_matches) => { - let sub_matches = sub_matches.unwrap(); - + ("serve", Some(sub_matches)) => { let project_path = match sub_matches.value_of("PROJECT") { Some(v) => make_path_absolute(Path::new(v)), None => std::env::current_dir().unwrap(), @@ -64,9 +62,7 @@ fn main() { librojo::commands::serve(&project_path); }, - ("build", sub_matches) => { - let sub_matches = sub_matches.unwrap(); - + ("build", Some(sub_matches)) => { let fuzzy_project_path = match sub_matches.value_of("PROJECT") { Some(v) => make_path_absolute(Path::new(v)), None => std::env::current_dir().unwrap(), @@ -82,9 +78,7 @@ fn main() { commands::build(&options); }, _ => { - error!("Please specify a subcommand!"); - error!("Try 'rojo help' for information."); - process::exit(1); + app.print_help().expect("Could not print help text to stdout!"); }, } } \ No newline at end of file From 8aee5c769f466d5a2789149e7c79696531b47cd6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 14:07:00 -0800 Subject: [PATCH 0218/1504] Implement build command, shuffle around some internals to make it easier --- server/src/bin.rs | 4 ++-- server/src/commands/build.rs | 34 +++++++++++++++++++++++++++++++++- server/src/imfs.rs | 27 ++++++++++++++++++++++++++- server/src/rbx_session.rs | 4 ++++ server/src/session.rs | 24 ++---------------------- 5 files changed, 67 insertions(+), 26 deletions(-) diff --git a/server/src/bin.rs b/server/src/bin.rs index 625b9d05..6db5da5e 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -1,10 +1,10 @@ -#[macro_use] extern crate clap; - use std::{ path::{Path, PathBuf}, env, }; +use clap::clap_app; + use librojo::commands; fn make_path_absolute(value: &Path) -> PathBuf { diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index 0c7d51eb..d3e81fa2 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -1,5 +1,15 @@ use std::{ path::PathBuf, + fs::File, + process, +}; + +use rbxmx; + +use crate::{ + rbx_session::construct_oneoff_tree, + project::Project, + imfs::Imfs, }; #[derive(Debug)] @@ -9,5 +19,27 @@ pub struct BuildOptions { } pub fn build(options: &BuildOptions) { - println!("build {:#?}", options); + info!("Looking for project at {}", options.fuzzy_project_path.display()); + + let project = match Project::load_fuzzy(&options.fuzzy_project_path) { + Ok(project) => project, + Err(error) => { + error!("{}", error); + process::exit(1); + }, + }; + + info!("Found project at {}", project.file_location.display()); + info!("Using project {:#?}", project); + + let imfs = Imfs::new(&project) + .expect("Could not create in-memory filesystem"); + + let tree = construct_oneoff_tree(&project, &imfs); + let root_id = tree.get_root_id(); + + let mut file = File::create(&options.output_file) + .expect("Could not open output file for write"); + + rbxmx::encode(&tree, &[root_id], &mut file); } \ No newline at end of file diff --git a/server/src/imfs.rs b/server/src/imfs.rs index 519faaaf..47ca782a 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -5,6 +5,23 @@ use std::{ io, }; +use crate::project::{Project, ProjectNode}; + +fn add_sync_points(imfs: &mut Imfs, project_node: &ProjectNode) -> io::Result<()> { + match project_node { + ProjectNode::Instance(node) => { + for child in node.children.values() { + add_sync_points(imfs, child)?; + } + }, + ProjectNode::SyncPoint(node) => { + imfs.add_root(&node.path)?; + }, + } + + Ok(()) +} + /// The in-memory filesystem keeps a mirror of all files being watcher by Rojo /// in order to deduplicate file changes in the case of bidirectional syncing /// from Roblox Studio. @@ -15,7 +32,15 @@ pub struct Imfs { } impl Imfs { - pub fn new() -> Imfs { + pub fn new(project: &Project) -> io::Result { + let mut imfs = Imfs::empty(); + + add_sync_points(&mut imfs, &project.tree)?; + + Ok(imfs) + } + + pub fn empty() -> Imfs { Imfs { items: HashMap::new(), roots: HashSet::new(), diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 52f73c08..302f3926 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -157,6 +157,10 @@ impl RbxSession { } } +pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { + construct_initial_tree(project, imfs).0 +} + struct ConstructContext<'a> { tree: RbxTree, imfs: &'a Imfs, diff --git a/server/src/session.rs b/server/src/session.rs index ca237dee..90488124 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -5,7 +5,7 @@ use std::{ use crate::{ message_queue::MessageQueue, - project::{Project, ProjectNode}, + project::Project, imfs::Imfs, session_id::SessionId, rbx_session::RbxSession, @@ -20,29 +20,9 @@ pub struct Session { fs_watcher: FsWatcher, } -fn add_sync_points(imfs: &mut Imfs, project_node: &ProjectNode) -> io::Result<()> { - match project_node { - ProjectNode::Instance(node) => { - for child in node.children.values() { - add_sync_points(imfs, child)?; - } - }, - ProjectNode::SyncPoint(node) => { - imfs.add_root(&node.path)?; - }, - } - - Ok(()) -} - impl Session { pub fn new(project: Project) -> io::Result { - let mut imfs = Imfs::new(); - - add_sync_points(&mut imfs, &project.tree) - .expect("Could not add sync points when starting new Rojo session"); - - let imfs = Arc::new(Mutex::new(imfs)); + let imfs = Arc::new(Mutex::new(Imfs::new(&project)?)); let project = Arc::new(project); let message_queue = Arc::new(MessageQueue::new()); From c61d6a580439323a7a65705da828d5876be3eb94 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 14:22:06 -0800 Subject: [PATCH 0219/1504] Build out 'build' command --- server/src/bin.rs | 12 +++++- server/src/commands/build.rs | 78 ++++++++++++++++++++++++++++++------ 2 files changed, 77 insertions(+), 13 deletions(-) diff --git a/server/src/bin.rs b/server/src/bin.rs index 6db5da5e..9dc1e529 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -1,6 +1,9 @@ +#[macro_use] extern crate log; + use std::{ path::{Path, PathBuf}, env, + process, }; use clap::clap_app; @@ -73,9 +76,16 @@ fn main() { let options = commands::BuildOptions { fuzzy_project_path, output_file, + output_kind: None, // TODO: Accept from argument }; - commands::build(&options); + match commands::build(&options) { + Ok(_) => {}, + Err(e) => { + error!("{}", e); + process::exit(1); + }, + } }, _ => { app.print_help().expect("Could not print help text to stdout!"); diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index d3e81fa2..9ac990f0 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -1,33 +1,76 @@ use std::{ path::PathBuf, fs::File, - process, + fmt, }; use rbxmx; use crate::{ rbx_session::construct_oneoff_tree, - project::Project, + project::{Project, ProjectLoadFuzzyError}, imfs::Imfs, }; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum OutputKind { + Rbxmx, + Rbxlx, +} + +fn detect_output_kind(options: &BuildOptions) -> Option { + match options.output_kind { + Some(output_kind) => Some(output_kind), + None => { + let extension = options.output_file.extension()?.to_str()?; + + match extension { + "rbxlx" => Some(OutputKind::Rbxlx), + "rbxmx" => Some(OutputKind::Rbxmx), + _ => None, + } + }, + } +} + #[derive(Debug)] pub struct BuildOptions { pub fuzzy_project_path: PathBuf, pub output_file: PathBuf, + pub output_kind: Option, } -pub fn build(options: &BuildOptions) { +pub enum BuildError { + UnknownOutputKind, + ProjectLoadError(ProjectLoadFuzzyError), +} + +impl fmt::Display for BuildError { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + match self { + BuildError::UnknownOutputKind => { + write!(output, "Could not detect what kind of output file to create") + }, + BuildError::ProjectLoadError(inner) => write!(output, "{}", inner), + } + } +} + +impl From for BuildError { + fn from(error: ProjectLoadFuzzyError) -> BuildError { + BuildError::ProjectLoadError(error) + } +} + +pub fn build(options: &BuildOptions) -> Result<(), BuildError> { + let output_kind = detect_output_kind(options) + .ok_or(BuildError::UnknownOutputKind)?; + + info!("Hoping to generate file of type {:?}", output_kind); + info!("Looking for project at {}", options.fuzzy_project_path.display()); - let project = match Project::load_fuzzy(&options.fuzzy_project_path) { - Ok(project) => project, - Err(error) => { - error!("{}", error); - process::exit(1); - }, - }; + let project = Project::load_fuzzy(&options.fuzzy_project_path)?; info!("Found project at {}", project.file_location.display()); info!("Using project {:#?}", project); @@ -36,10 +79,21 @@ pub fn build(options: &BuildOptions) { .expect("Could not create in-memory filesystem"); let tree = construct_oneoff_tree(&project, &imfs); - let root_id = tree.get_root_id(); let mut file = File::create(&options.output_file) .expect("Could not open output file for write"); - rbxmx::encode(&tree, &[root_id], &mut file); + match output_kind { + OutputKind::Rbxmx => { + let root_id = tree.get_root_id(); + rbxmx::encode(&tree, &[root_id], &mut file); + }, + OutputKind::Rbxlx => { + let root_id = tree.get_root_id(); + let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); + rbxmx::encode(&tree, top_level_ids, &mut file); + }, + } + + Ok(()) } \ No newline at end of file From 1e0a7dea734f61e9f916d86cbf21086893bebd45 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 14:40:19 -0800 Subject: [PATCH 0220/1504] Add test model, shore up 'build' command more --- server/src/commands/build.rs | 41 +++++++++++-------- test-projects/{foo.json => example.json} | 0 .../single-sync-point/roblox-project.json | 2 +- test-projects/test-model/roblox-project.json | 9 ++++ test-projects/test-model/src/main.lua | 3 ++ test-projects/test-model/src/other.lua | 1 + 6 files changed, 38 insertions(+), 18 deletions(-) rename test-projects/{foo.json => example.json} (100%) create mode 100644 test-projects/test-model/roblox-project.json create mode 100644 test-projects/test-model/src/main.lua create mode 100644 test-projects/test-model/src/other.lua diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index 9ac990f0..ab57fb6b 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -1,6 +1,7 @@ use std::{ path::PathBuf, fs::File, + io, fmt, }; @@ -19,17 +20,12 @@ pub enum OutputKind { } fn detect_output_kind(options: &BuildOptions) -> Option { - match options.output_kind { - Some(output_kind) => Some(output_kind), - None => { - let extension = options.output_file.extension()?.to_str()?; + let extension = options.output_file.extension()?.to_str()?; - match extension { - "rbxlx" => Some(OutputKind::Rbxlx), - "rbxmx" => Some(OutputKind::Rbxmx), - _ => None, - } - }, + match extension { + "rbxlx" => Some(OutputKind::Rbxlx), + "rbxmx" => Some(OutputKind::Rbxmx), + _ => None, } } @@ -43,6 +39,7 @@ pub struct BuildOptions { pub enum BuildError { UnknownOutputKind, ProjectLoadError(ProjectLoadFuzzyError), + IoError(io::Error), } impl fmt::Display for BuildError { @@ -52,6 +49,7 @@ impl fmt::Display for BuildError { write!(output, "Could not detect what kind of output file to create") }, BuildError::ProjectLoadError(inner) => write!(output, "{}", inner), + BuildError::IoError(inner) => write!(output, "{}", inner), } } } @@ -62,8 +60,15 @@ impl From for BuildError { } } +impl From for BuildError { + fn from(error: io::Error) -> BuildError { + BuildError::IoError(error) + } +} + pub fn build(options: &BuildOptions) -> Result<(), BuildError> { - let output_kind = detect_output_kind(options) + let output_kind = options.output_kind + .or_else(|| detect_output_kind(options)) .ok_or(BuildError::UnknownOutputKind)?; info!("Hoping to generate file of type {:?}", output_kind); @@ -75,20 +80,22 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { info!("Found project at {}", project.file_location.display()); info!("Using project {:#?}", project); - let imfs = Imfs::new(&project) - .expect("Could not create in-memory filesystem"); - + let imfs = Imfs::new(&project)?; let tree = construct_oneoff_tree(&project, &imfs); - - let mut file = File::create(&options.output_file) - .expect("Could not open output file for write"); + let mut file = File::create(&options.output_file)?; match output_kind { OutputKind::Rbxmx => { + // Model files include the root instance of the tree and all its + // descendants. + let root_id = tree.get_root_id(); rbxmx::encode(&tree, &[root_id], &mut file); }, OutputKind::Rbxlx => { + // Place files don't contain an entry for the DataModel, but our + // RbxTree representation does. + let root_id = tree.get_root_id(); let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); rbxmx::encode(&tree, top_level_ids, &mut file); diff --git a/test-projects/foo.json b/test-projects/example.json similarity index 100% rename from test-projects/foo.json rename to test-projects/example.json diff --git a/test-projects/single-sync-point/roblox-project.json b/test-projects/single-sync-point/roblox-project.json index 2ec428cc..d3970b9c 100644 --- a/test-projects/single-sync-point/roblox-project.json +++ b/test-projects/single-sync-point/roblox-project.json @@ -1,5 +1,5 @@ { - "name": "empty", + "name": "single-sync-point", "tree": { "$className": "DataModel", "ReplicatedStorage": { diff --git a/test-projects/test-model/roblox-project.json b/test-projects/test-model/roblox-project.json new file mode 100644 index 00000000..503a7d25 --- /dev/null +++ b/test-projects/test-model/roblox-project.json @@ -0,0 +1,9 @@ +{ + "name": "empty", + "tree": { + "$className": "Folder", + "Library": { + "$path": "src" + } + } +} \ No newline at end of file diff --git a/test-projects/test-model/src/main.lua b/test-projects/test-model/src/main.lua new file mode 100644 index 00000000..506c4701 --- /dev/null +++ b/test-projects/test-model/src/main.lua @@ -0,0 +1,3 @@ +local other = require(script.Parent.other) + +print(other) \ No newline at end of file diff --git a/test-projects/test-model/src/other.lua b/test-projects/test-model/src/other.lua new file mode 100644 index 00000000..4c06176d --- /dev/null +++ b/test-projects/test-model/src/other.lua @@ -0,0 +1 @@ +return "Hello, world!" \ No newline at end of file From 5a9d3959e21afc82459c80702c069cfe7dcf4701 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 15:11:10 -0800 Subject: [PATCH 0221/1504] Rework RbxSession to drop top-level garbage node, upgrade test-model --- server/src/rbx_session.rs | 50 ++++++++++++-------- test-projects/test-model/roblox-project.json | 5 +- 2 files changed, 32 insertions(+), 23 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 302f3926..a51ae48f 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -162,7 +162,7 @@ pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { } struct ConstructContext<'a> { - tree: RbxTree, + tree: Option, imfs: &'a Imfs, path_id_tree: PathIdTree, ids_to_project_paths: HashMap, @@ -174,16 +174,9 @@ fn construct_initial_tree( ) -> (RbxTree, PathIdTree, HashMap) { let path_id_tree = PathIdTree::new(); let ids_to_project_paths = HashMap::new(); - let tree = RbxTree::new(RbxInstance { - name: "this isn't supposed to be here".to_string(), - class_name: "ahhh, help me".to_string(), - properties: HashMap::new(), - }); - - let root_id = tree.get_root_id(); let mut context = ConstructContext { - tree, + tree: None, imfs, path_id_tree, ids_to_project_paths, @@ -191,18 +184,35 @@ fn construct_initial_tree( construct_project_node( &mut context, - root_id, + None, "<<>>".to_string(), "<<>>", &project.tree, ); - (context.tree, context.path_id_tree, context.ids_to_project_paths) + let tree = context.tree.unwrap(); + + (tree, context.path_id_tree, context.ids_to_project_paths) +} + +fn insert_or_create_tree(context: &mut ConstructContext, parent_instance_id: Option, instance: RbxInstance) -> RbxId { + match (&mut context.tree, parent_instance_id) { + (Some(tree), Some(parent_instance_id)) => { + tree.insert_instance(instance, parent_instance_id) + }, + _ => { + let new_tree = RbxTree::new(instance); + let root_id = new_tree.get_root_id(); + + context.tree = Some(new_tree); + root_id + }, + } } fn construct_project_node( context: &mut ConstructContext, - parent_instance_id: RbxId, + parent_instance_id: Option, instance_path: String, instance_name: &str, project_node: &ProjectNode, @@ -221,7 +231,7 @@ fn construct_project_node( fn construct_instance_node( context: &mut ConstructContext, - parent_instance_id: RbxId, + parent_instance_id: Option, instance_path: &str, instance_name: &str, project_node: &InstanceProjectNode, @@ -232,11 +242,11 @@ fn construct_instance_node( properties: HashMap::new(), }; - let id = context.tree.insert_instance(instance, parent_instance_id); + let id = insert_or_create_tree(context, parent_instance_id, instance); for (child_name, child_project_node) in &project_node.children { let child_path = format!("{}/{}", instance_path, child_name); - construct_project_node(context, id, child_path, child_name, child_project_node); + construct_project_node(context, Some(id), child_path, child_name, child_project_node); } id @@ -244,7 +254,7 @@ fn construct_instance_node( fn construct_sync_point_node( context: &mut ConstructContext, - parent_instance_id: RbxId, + parent_instance_id: Option, instance_name: &str, file_path: &Path, ) -> RbxId { @@ -261,7 +271,8 @@ fn construct_sync_point_node( properties, }; - let id = context.tree.insert_instance(instance, parent_instance_id); + let id = insert_or_create_tree(context, parent_instance_id, instance); + context.path_id_tree.insert(&file.path, id); id @@ -273,12 +284,13 @@ fn construct_sync_point_node( properties: HashMap::new(), }; - let id = context.tree.insert_instance(instance, parent_instance_id); + let id = insert_or_create_tree(context, parent_instance_id, instance); + context.path_id_tree.insert(&directory.path, id); for child_path in &directory.children { let child_instance_name = child_path.file_name().unwrap().to_str().unwrap(); - construct_sync_point_node(context, id, child_instance_name, child_path); + construct_sync_point_node(context, Some(id), child_instance_name, child_path); } id diff --git a/test-projects/test-model/roblox-project.json b/test-projects/test-model/roblox-project.json index 503a7d25..57e85571 100644 --- a/test-projects/test-model/roblox-project.json +++ b/test-projects/test-model/roblox-project.json @@ -1,9 +1,6 @@ { "name": "empty", "tree": { - "$className": "Folder", - "Library": { - "$path": "src" - } + "$path": "src" } } \ No newline at end of file From 797c39347f6aaf3bd0b59d11cbb2a6bfa3360a83 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 15:15:02 -0800 Subject: [PATCH 0222/1504] Upgrade dependencies --- server/Cargo.lock | 824 ++++++++++++++++++++++++++++------------------ 1 file changed, 510 insertions(+), 314 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index d96eab56..78381752 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -5,10 +5,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "aho-corasick" -version = "0.6.7" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -16,12 +16,12 @@ name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ascii" -version = "0.7.1" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -29,25 +29,20 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "base64" -version = "0.7.0" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bitflags" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "0.7.0" @@ -60,20 +55,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "brotli-sys" -version = "0.2.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "brotli2" -version = "0.2.2" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "brotli-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -92,35 +87,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.6" +version = "1.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.3.0" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cc" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chrono" -version = "0.2.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "chrono" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -159,14 +154,22 @@ dependencies = [ "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-utils" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "deflate" -version = "0.7.18" +version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "gzip-header 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -226,34 +229,26 @@ name = "encoding_index_tests" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "enum_primitive" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "env_logger" version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "filetime" -version = "0.1.15" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -263,7 +258,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -271,7 +266,7 @@ name = "fsevent-sys" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -289,27 +284,26 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "gcc" -version = "0.3.54" +name = "futures" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "gzip-header" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "httparse" -version = "1.3.2" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "humantime" -version = "1.1.1" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -327,15 +321,38 @@ dependencies = [ [[package]] name = "inotify" -version = "0.3.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "inotify-sys" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "iovec" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -353,24 +370,38 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "libc" -version = "0.2.43" +name = "lazycell" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "libc" +version = "0.2.44" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "lock_api" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "log" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "log" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -383,15 +414,17 @@ name = "memchr" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memchr" -version = "2.0.2" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -408,30 +441,43 @@ version = "1.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mio" -version = "0.5.1" +version = "0.6.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mio-extras" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "miow" -version = "0.1.5" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -446,7 +492,7 @@ version = "0.13.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -461,45 +507,27 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "nix" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "notify" -version = "4.0.4" +version = "4.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num" -version = "0.1.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -507,29 +535,12 @@ name = "num-integer" version = "0.1.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-iter" -version = "0.1.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.1.43" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-traits" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -537,7 +548,36 @@ name = "num_cpus" version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "owning_ref" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "parking_lot_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -547,33 +587,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "phf" -version = "0.7.22" +version = "0.7.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_codegen" -version = "0.7.22" +version = "0.7.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_generator 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_generator" -version = "0.7.22" +version = "0.7.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_shared" -version = "0.7.22" +version = "0.7.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -582,7 +622,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "0.4.13" +version = "0.4.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -595,10 +635,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.8" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -607,7 +647,7 @@ version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -617,8 +657,8 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -628,30 +668,98 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_chacha" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand_hc" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_isaac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_pcg" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_xorshift" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "rbx-tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#0fe8dacd013668e194afb1d074161477ebc759b6" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#328c503732cf82a7200a3c971ab8ff761308adbe" dependencies = [ - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbxmx" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#0fe8dacd013668e194afb1d074161477ebc759b6" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#328c503732cf82a7200a3c971ab8ff761308adbe" dependencies = [ "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -659,7 +767,7 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.40" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -667,27 +775,27 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -695,7 +803,7 @@ name = "remove_dir_all" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -705,53 +813,56 @@ dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "rbxmx 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", - "regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rouille" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "brotli2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny_http 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rustc-serialize" -version = "0.3.24" +name = "rustc_version" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "ryu" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -759,42 +870,65 @@ name = "safemem" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "safemem" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "same-file" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "semver" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "semver-parser" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "serde" -version = "1.0.75" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.75" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "sha1" -version = "0.2.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -804,7 +938,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "slab" -version = "0.1.3" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "smallvec" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "stable_deref_trait" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -814,11 +961,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.14.9" +version = "0.15.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -833,23 +980,24 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.0.3" +version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "term" -version = "0.2.14" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -865,8 +1013,8 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -899,22 +1047,57 @@ name = "time" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tiny_http" -version = "0.5.9" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)", + "ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-executor" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-io" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-reactor" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -922,12 +1105,12 @@ name = "twoway" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ucd-util" -version = "0.1.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -935,7 +1118,7 @@ name = "unicase" version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -962,18 +1145,16 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "url" -version = "0.2.38" +name = "unreachable" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "url" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -983,25 +1164,16 @@ dependencies = [ [[package]] name = "utf8-ranges" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "uuid" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "uuid" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1011,16 +1183,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "version_check" -version = "0.1.4" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "void" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" -version = "2.2.5" +version = "2.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1031,7 +1208,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1053,7 +1230,7 @@ name = "winapi-util" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1066,7 +1243,7 @@ name = "wincolor" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1086,28 +1263,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" -"checksum aho-corasick 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "7ee94e9463ccb9d681e7b708082687b2c56d2bd420ca8a3d3157d27d59508ec0" +"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum ascii 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae7d751998c189c1d4468cf0a39bb2eae052a9c58d50ebb3b9591ee3813ad50" +"checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum base64 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5032d51da2741729bfdaeb2664d9b8c6d9fd1e2b90715c660b6def36628499c2" -"checksum bitflags 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dead7461c1127cf637931a1e50934eb6eee8bff2f74433ac7909e9afcee04a3" +"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum brotli-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cb50f54b2e0c671b7ef1637a76237ebacbb293be179440d5d65ca288e42116bb" -"checksum brotli2 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ea9d0bbab1235017a09226b079ed733bca4bf9ecb6b6102bd01aac79ea082dca" +"checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" +"checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" "checksum buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9279646319ff816b05fb5897883ece50d7d854d12b59992683d4f8a71b0f949" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" -"checksum byteorder 1.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "90492c5858dd7d2e78691cfb89f90d273a2800fc11d98f60786e5d87e2f83781" -"checksum bytes 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c129aff112dcc562970abb69e2508b40850dd24c274761bb50fb8a0067ba6c27" -"checksum cfg-if 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0c4e7bb64a8ebb0d856483e1e682ea3422f883c5f5615a90d51a2c82fe87fdd3" -"checksum chrono 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "9213f7cd7c27e95c2b57c49f0e69b1ea65b27138da84a170133fd21b07659c00" -"checksum chrono 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e48d85528df61dc964aa43c5f6ca681a19cfa74939b2348d204bd08a981f2fb0" +"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" +"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" +"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" +"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -"checksum deflate 0.7.18 (registry+https://github.com/rust-lang/crates.io-index)" = "32c8120d981901a9970a3a1c97cf8b630e0fa8c3ca31e75b6fd6fd5f9f427b31" +"checksum crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c55913cc2799171a550e307918c0a360e8c16004820291bf3b638969b4a01816" +"checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86" "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" "checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" @@ -1115,101 +1292,120 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" -"checksum enum_primitive 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be4551092f4d519593039259a9ed8daedf0da12e5109c5280338073eaeb81180" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" -"checksum filetime 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "714653f3e34871534de23771ac7b26e999651a0a228f47beb324dfdf1dd4b10f" +"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" "checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05" "checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" -"checksum gzip-header 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0a9fcfe1c9ee125342355b2467bc29b9dfcb2124fcae27edb9cee6f4cc5ecd40" -"checksum httparse 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7b6288d7db100340ca12873fd4d08ad1b8f206a9457798dfb17c018a33fee540" -"checksum humantime 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0484fda3e7007f2a4a0d9c3a703ca38c71c54c55602ce4660c419fd32e188c9e" +"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" +"checksum gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9e59524a909fe98bb6c6f2cf1f27f2f6772887a496bf4c68cae0d94f884586" +"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" +"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum inotify 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887fcc180136e77a85e6a6128579a719027b1bab9b1c38ea4444244fe262c20c" -"checksum itoa 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5adb58558dcd1d786b5f0bd15f3226ee23486e24b7b58304b60f64dc68e62606" +"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" +"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" +"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" -"checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" +"checksum lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddba4c30a78328befecec92fc94970e53b3ae385827d28620f0f5bb2493081e0" +"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" +"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -"checksum log 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cba860f648db8e6f269df990180c2217f333472b4a6e901e97446858487971e2" +"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" -"checksum memchr 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a3b4142ab8738a78c51896f704f83c11df047ff1bda9a92a661aa6361552d93d" +"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2d4c0961143b8efdcfa29c3ae63281601b446a4a668165454b6c90f8024954c5" -"checksum mio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a637d1ca14eacae06296a008fa7ad955347e34efcb5891cfd8ba05491a37907e" -"checksum miow 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3e690c5df6b2f60acd45d56378981e827ff8295562fc8d34f573deb267a59cd1" +"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" +"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" +"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92f54eb45230c3aa20864ccf0c277eeaeadcf5e437e91731db498dbf7fbe0ec6" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum nix 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bfb3ddedaa14746434a02041940495bf11325c22f6d36125d3bdd56090d50a79" -"checksum notify 4.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d023ef40ca7680784b07be3f49913e1ea176da1b63949f2eb2fed96438bd7f42" -"checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" +"checksum notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "873ecfd8c174964ae30f401329d140142312c8e5590719cf1199d5f1717d8078" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-iter 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "af3fdbbc3291a5464dc57b03860ec37ca6bf915ed6ee385e7c6c052c422b2124" -"checksum num-traits 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" -"checksum num-traits 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "630de1ef5cc79d0cdd78b7e33b81f083cbfe90de0f4b2b2f07f905867c70e9fe" +"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" +"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" +"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum phf 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "7d37a244c75a9748e049225155f56dbcb98fe71b192fd25fd23cb914b5ad62f2" -"checksum phf_codegen 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "4e4048fe7dd7a06b8127ecd6d3803149126e9b33c7558879846da3a63f734f2b" -"checksum phf_generator 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "05a079dd052e7b674d21cb31cbb6c05efd56a2cd2827db7692e2f1a507ebd998" -"checksum phf_shared 0.7.22 (registry+https://github.com/rust-lang/crates.io-index)" = "c2261d544c2bb6aa3b10022b0be371b9c7c64f762ef28c6f5d4f1ef6d97b5930" -"checksum proc-macro2 0.4.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ee5697238f0d893c7f0ecc59c0999f18d2af85e424de441178bcacc9f9e6cf67" +"checksum phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "cec29da322b242f4c3098852c77a0ca261c9c01b806cae85a5572a1eb94db9a6" +"checksum phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "7d187f00cd98d5afbcd8898f6cf181743a449162aeb329dcd2f3849009e605ad" +"checksum phf_generator 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "03dc191feb9b08b0dc1330d6549b795b9d81aec19efe6b4a45aec8d4caee0c4b" +"checksum phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "b539898d22d4273ded07f64a05737649dc69095d92cb87c7097ec68e3f150b93" +"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "dd636425967c33af890042c483632d33fa7a18f19ad1d7ea72e8998c6ef8dea5" +"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand_core 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "edecf0f94da5551fc9b492093e30b041a891657db7940ee221f9d2f66e82eef2" +"checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" +"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" +"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" +"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" "checksum rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum rbxmx 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" -"checksum redox_syscall 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "c214e91d3ecf43e9a4e41e578973adeb14b474f2bee858742d127af75a0112b1" +"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "67d0301b0c6804eca7e3c275119d0b01ff3b7ab9258a65709e608a66312a1025" -"checksum regex-syntax 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "747ba3b235651f6e2f67dfa8bcdcd073ddb7c243cb21c442fc12395dfcac212d" +"checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467" +"checksum regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fbc557aac2b708fe84121caf261346cc2eed71978024337e42eb46b8a252ac6e" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum rouille 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc1f8407af80b0630983b2c1f1860dda1960fdec8d3ee75ba8db14937756d3a0" -"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" -"checksum ryu 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7153dd96dade874ab973e098cb62fcdbb89a03682e46b144fd09550998d4a4a7" +"checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841" +"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" +"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" -"checksum same-file 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f7794e2fda7f594866840e95f5c5962e886e228e68b6505885811a94dd728c" -"checksum serde 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "22d340507cea0b7e6632900a176101fea959c7065d93ba555072da90aaaafc87" -"checksum serde_derive 1.0.75 (registry+https://github.com/rust-lang/crates.io-index)" = "234fc8b737737b148ccd625175fc6390f5e4dacfdaa543cb93a3430d984a9119" -"checksum serde_json 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "44dd2cfde475037451fa99b7e5df77aa3cfd1536575fa8e7a538ab36dcde49ae" -"checksum sha1 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cc30b1e1e8c40c121ca33b86c23308a090d19974ef001b4bf6e61fd1a0fb095c" +"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" +"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" +"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" +"checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" +"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c" +"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" +"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" -"checksum slab 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d807fd58c4181bbabed77cb3b891ba9748241a552bcc5be698faaebefc54f46e" +"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" +"checksum smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "622df2d454c29a4d89b30dc3b27b42d7d90d6b9e587dbf8f67652eb7514da484" +"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.14.9 (registry+https://github.com/rust-lang/crates.io-index)" = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741" +"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum tempfile 3.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4b103c6d08d323b92ff42c8ce62abcd83ca8efa7fd5bf7927efefec75f58c76" -"checksum term 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "f2077e54d38055cf1ca0fd7933a2e00cd3ec8f6fed352b2a377f06dcdaaf3281" +"checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" +"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" -"checksum tiny_http 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "2f4d55c9a213880d1f0c89ded183f209c6e45b912ca6c7df6f93c163773572e1" +"checksum tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a442681f9f72e440be192700eeb2861e4174b9983f16f4877c93a134cb5e5f63" +"checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde" +"checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21" +"checksum tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "502b625acb4ee13cbb3b90b8ca80e0addd263ddacf6931666ef751e610b07fb5" "checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" -"checksum ucd-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd2be2d6639d0f8fe6cdda291ad456e23629558d466e2789d2c3e9892bda285d" +"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum url 0.2.38 (registry+https://github.com/rust-lang/crates.io-index)" = "cbaa8377a162d88e7d15db0cf110c8523453edcbc5bc66d2b6fffccffa34a068" -"checksum url 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a321979c09843d272956e73700d12c4e7d3d92b2ee112b31548aef0d4efc5a6" -"checksum utf8-ranges 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fd70f467df6810094968e2fce0ee1bd0e87157aceb026a8c083bcf5e25b9efe4" -"checksum uuid 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "78c590b5bd79ed10aad8fb75f078a59d8db445af6c743e55c4a53227fc01c13f" +"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" +"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dab5c5526c5caa3d106653401a267fed923e7046f35895ffcb5ca42db64942e6" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "7716c242968ee87e5542f8021178248f267f295a5c4803beae8b8b7fd9bc6051" -"checksum walkdir 2.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "af464bc7be7b785c7ac72e266a6b67c4c9070155606f51655a650a6686204e35" +"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" +"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "773ef9dcc5f24b7d850d0ff101e542ff24c3b090a9768e03ff889fdef41f00fd" +"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" From 2340a07408e9c15ad6cb9b0b151310259dc774b6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 15:16:48 -0800 Subject: [PATCH 0223/1504] Use project name for root object name --- server/src/rbx_session.rs | 4 ++-- test-projects/test-model/roblox-project.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index a51ae48f..a58c6c89 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -185,8 +185,8 @@ fn construct_initial_tree( construct_project_node( &mut context, None, - "<<>>".to_string(), - "<<>>", + project.name.clone(), + &project.name, &project.tree, ); diff --git a/test-projects/test-model/roblox-project.json b/test-projects/test-model/roblox-project.json index 57e85571..0eb0c8ea 100644 --- a/test-projects/test-model/roblox-project.json +++ b/test-projects/test-model/roblox-project.json @@ -1,5 +1,5 @@ { - "name": "empty", + "name": "test-model", "tree": { "$path": "src" } From 29fe7492cc78a8f35901aaeb6f2689f3882c2896 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 15:51:25 -0800 Subject: [PATCH 0224/1504] Generate correct names for Lua scripts --- server/src/rbx_session.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index a58c6c89..43a562f4 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -289,7 +289,7 @@ fn construct_sync_point_node( context.path_id_tree.insert(&directory.path, id); for child_path in &directory.children { - let child_instance_name = child_path.file_name().unwrap().to_str().unwrap(); + let child_instance_name = child_path.file_stem().unwrap().to_str().unwrap(); construct_sync_point_node(context, Some(id), child_instance_name, child_path); } From f1c526867038d314150a9cda640608699685c276 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 17:44:17 -0800 Subject: [PATCH 0225/1504] Support init.lua and client/server scripts --- server/src/rbx_session.rs | 65 +++++++++++++++---- .../src/{main.lua => main.server.lua} | 0 2 files changed, 53 insertions(+), 12 deletions(-) rename test-projects/test-model/src/{main.lua => main.server.lua} (100%) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 43a562f4..b853a5ea 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -10,7 +10,7 @@ use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; use crate::{ project::{Project, ProjectNode, InstanceProjectNode}, message_queue::{Message, MessageQueue}, - imfs::{Imfs, ImfsItem}, + imfs::{Imfs, ImfsItem, ImfsFile}, }; #[derive(Debug)] @@ -252,6 +252,27 @@ fn construct_instance_node( id } +#[derive(Debug, Clone, Copy)] +enum FileType { + ModuleScript, + ServerScript, + ClientScript, +} + +fn classify_file(file: &ImfsFile) -> Option { + let file_name = file.path.file_name()?.to_str()?; + + if file_name.ends_with(".server.lua") { + Some(FileType::ServerScript) + } else if file_name.ends_with(".client.lua") { + Some(FileType::ClientScript) + } else if file_name.ends_with(".lua") { + Some(FileType::ModuleScript) + } else { + None + } +} + fn construct_sync_point_node( context: &mut ConstructContext, parent_instance_id: Option, @@ -260,13 +281,21 @@ fn construct_sync_point_node( ) -> RbxId { match context.imfs.get(&file_path) { Some(ImfsItem::File(file)) => { + let file_type = classify_file(file).unwrap(); // TODO: Don't die here! + + let class_name = match file_type { + FileType::ModuleScript => "ModuleScript", + FileType::ServerScript => "Script", + FileType::ClientScript => "LocalScript", + }; + let contents = str::from_utf8(&file.contents).unwrap(); let mut properties = HashMap::new(); properties.insert("Source".to_string(), RbxValue::String { value: contents.to_string() }); let instance = RbxInstance { - class_name: "ModuleScript".to_string(), + class_name: class_name.to_string(), name: instance_name.to_string(), properties, }; @@ -278,19 +307,31 @@ fn construct_sync_point_node( id }, Some(ImfsItem::Directory(directory)) => { - let instance = RbxInstance { - class_name: "Folder".to_string(), - name: instance_name.to_string(), - properties: HashMap::new(), + let init_path = directory.path.join("init.lua"); + + let id = if directory.children.contains(&init_path) { + construct_sync_point_node(context, parent_instance_id, instance_name, &init_path) + } else { + let instance = RbxInstance { + class_name: "Folder".to_string(), + name: instance_name.to_string(), + properties: HashMap::new(), + }; + + let id = insert_or_create_tree(context, parent_instance_id, instance); + context.path_id_tree.insert(&directory.path, id); + id }; - let id = insert_or_create_tree(context, parent_instance_id, instance); - - context.path_id_tree.insert(&directory.path, id); - for child_path in &directory.children { - let child_instance_name = child_path.file_stem().unwrap().to_str().unwrap(); - construct_sync_point_node(context, Some(id), child_instance_name, child_path); + if child_path != &init_path { + let child_instance_name = match context.imfs.get(child_path).unwrap() { + ImfsItem::File(_) => child_path.file_stem().unwrap().to_str().unwrap(), + ImfsItem::Directory(_) => child_path.file_name().unwrap().to_str().unwrap(), + }; + + construct_sync_point_node(context, Some(id), child_instance_name, child_path); + } } id diff --git a/test-projects/test-model/src/main.lua b/test-projects/test-model/src/main.server.lua similarity index 100% rename from test-projects/test-model/src/main.lua rename to test-projects/test-model/src/main.server.lua From 49a2bc8acef19500affe426346bee29e1b308be9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 21:17:38 -0800 Subject: [PATCH 0226/1504] Fix example test --- server/tests/read_projects.rs | 6 +++--- test-projects/example.json | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index d547e7d0..b8a1315d 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -17,11 +17,11 @@ lazy_static! { } #[test] -fn foo() { - let project_file_location = TEST_PROJECTS_ROOT.join("foo.json"); +fn fullexample() { + let project_file_location = TEST_PROJECTS_ROOT.join("example.json"); let project = Project::load_exact(&project_file_location).unwrap(); - assert_eq!(project.name, "foo"); + assert_eq!(project.name, "example"); } #[test] diff --git a/test-projects/example.json b/test-projects/example.json index e93d066d..d86db968 100644 --- a/test-projects/example.json +++ b/test-projects/example.json @@ -1,5 +1,5 @@ { - "name": "foo", + "name": "example", "tree": { "$className": "DataModel", "ReplicatedStorage": { From bcd5fab33c119407eb54aee0ad65f6416589da59 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 23:08:37 -0800 Subject: [PATCH 0227/1504] Add $properties to project nodes, unsure the full ramifications yet --- server/src/project.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/server/src/project.rs b/server/src/project.rs index 54ffa601..25b9e560 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -7,6 +7,7 @@ use std::{ }; use serde_json; +use rbx_tree::RbxValue; pub static PROJECT_FILENAME: &'static str = "roblox-project.json"; @@ -17,6 +18,9 @@ enum SourceProjectNode { #[serde(rename = "$className")] class_name: String, + #[serde(rename = "$properties", default="HashMap::new")] + properties: HashMap, + // #[serde(rename = "$ignoreUnknown", default = "false")] // ignore_unknown: bool, @@ -32,7 +36,7 @@ enum SourceProjectNode { impl SourceProjectNode { pub fn into_project_node(self, project_file_location: &Path) -> ProjectNode { match self { - SourceProjectNode::Instance { class_name, mut children } => { + SourceProjectNode::Instance { class_name, mut children, properties } => { let mut new_children = HashMap::new(); for (node_name, node) in children.drain() { @@ -42,6 +46,7 @@ impl SourceProjectNode { ProjectNode::Instance(InstanceProjectNode { class_name, children: new_children, + properties, }) }, SourceProjectNode::SyncPoint { path: source_path } => { @@ -150,7 +155,7 @@ pub enum ProjectNode { pub struct InstanceProjectNode { pub class_name: String, pub children: HashMap, - // properties: HashMap, + pub properties: HashMap, // ignore_unknown: bool, } From c50922e90c2781774fe1ca3eaed495bc3914ceb5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Nov 2018 23:21:16 -0800 Subject: [PATCH 0228/1504] Add ignoreUnknown to project nodes --- server/src/project.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/server/src/project.rs b/server/src/project.rs index 25b9e560..0221f7fc 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -11,6 +11,11 @@ use rbx_tree::RbxValue; pub static PROJECT_FILENAME: &'static str = "roblox-project.json"; +// Serde is silly, +const fn yeah() -> bool { + true +} + #[derive(Debug, Serialize, Deserialize)] #[serde(untagged)] enum SourceProjectNode { @@ -18,11 +23,11 @@ enum SourceProjectNode { #[serde(rename = "$className")] class_name: String, - #[serde(rename = "$properties", default="HashMap::new")] + #[serde(rename = "$properties", default = "HashMap::new")] properties: HashMap, - // #[serde(rename = "$ignoreUnknown", default = "false")] - // ignore_unknown: bool, + #[serde(rename = "$ignoreUnknown", default = "yeah")] + ignore_unknown: bool, #[serde(flatten)] children: HashMap, @@ -36,7 +41,7 @@ enum SourceProjectNode { impl SourceProjectNode { pub fn into_project_node(self, project_file_location: &Path) -> ProjectNode { match self { - SourceProjectNode::Instance { class_name, mut children, properties } => { + SourceProjectNode::Instance { class_name, mut children, properties, .. } => { let mut new_children = HashMap::new(); for (node_name, node) in children.drain() { From ce6a9dc4486e006ae563b5e970f26f152cfa3f97 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 30 Nov 2018 18:01:44 -0800 Subject: [PATCH 0229/1504] Update dependencies --- server/Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 78381752..88040c0f 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -576,7 +576,7 @@ dependencies = [ "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -749,7 +749,7 @@ dependencies = [ [[package]] name = "rbx-tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#328c503732cf82a7200a3c971ab8ff761308adbe" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#9d42aa5da5132cc08bd04e30d235207e774d9909" dependencies = [ "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", @@ -759,7 +759,7 @@ dependencies = [ [[package]] name = "rbxmx" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#328c503732cf82a7200a3c971ab8ff761308adbe" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#9d42aa5da5132cc08bd04e30d235207e774d9909" dependencies = [ "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -943,7 +943,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1372,7 +1372,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" -"checksum smallvec 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "622df2d454c29a4d89b30dc3b27b42d7d90d6b9e587dbf8f67652eb7514da484" +"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" From 25c73ed91783f5f3db7c675ec61129674f7fbebb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 30 Nov 2018 18:08:03 -0800 Subject: [PATCH 0230/1504] Add support for binary (rbxl and rbxm) build output --- server/Cargo.lock | 128 +++++++++++++++++++++++++++++++++++ server/Cargo.toml | 1 + server/src/commands/build.rs | 15 +++- 3 files changed, 142 insertions(+), 2 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 88040c0f..ecdd0192 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -34,6 +34,27 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "backtrace" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "base64" version = "0.9.3" @@ -48,6 +69,11 @@ name = "bitflags" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bitflags" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bitflags" version = "1.0.4" @@ -85,6 +111,11 @@ name = "build_const" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "bytecount" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byteorder" version = "1.2.7" @@ -99,6 +130,18 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cargo_metadata" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cc" version = "1.0.25" @@ -241,6 +284,14 @@ dependencies = [ "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "error-chain" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "filetime" version = "0.2.4" @@ -288,6 +339,11 @@ name = "futures" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "gzip-header" version = "0.2.0" @@ -404,6 +460,25 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lz4" +version = "1.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "skeptic 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "lz4-sys" +version = "1.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "matches" version = "0.1.8" @@ -628,6 +703,14 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pulldown-cmark" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "quick-error" version = "1.2.2" @@ -756,6 +839,16 @@ dependencies = [ "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rbxm" +version = "0.1.0" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#9d42aa5da5132cc08bd04e30d235207e774d9909" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", +] + [[package]] name = "rbxmx" version = "0.1.0" @@ -817,6 +910,7 @@ dependencies = [ "notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", + "rbxm 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "rbxmx 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -852,6 +946,11 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rustc-demangle" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "rustc_version" version = "0.2.3" @@ -894,6 +993,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -936,6 +1036,21 @@ name = "siphasher" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "skeptic" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "slab" version = "0.4.1" @@ -1267,15 +1382,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" +"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" +"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" +"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" "checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" "checksum buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9279646319ff816b05fb5897883ece50d7d854d12b59992683d4f8a71b0f949" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" +"checksum bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f861d9ce359f56dbcb6e0c2a1cb84e52ad732cadb57b806adeb3c7668caccbd8" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" +"checksum cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1efca0b863ca03ed4c109fb1c55e0bc4bbeb221d3e103d86251046b06a526bd0" "checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" @@ -1293,12 +1413,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" +"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" "checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" "checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05" "checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" +"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9e59524a909fe98bb6c6f2cf1f27f2f6772887a496bf4c68cae0d94f884586" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" @@ -1314,6 +1436,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" +"checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" @@ -1337,6 +1461,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_generator 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "03dc191feb9b08b0dc1330d6549b795b9d81aec19efe6b4a45aec8d4caee0c4b" "checksum phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "b539898d22d4273ded07f64a05737649dc69095d92cb87c7097ec68e3f150b93" "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" +"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" @@ -1351,6 +1476,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" "checksum rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" +"checksum rbxm 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum rbxmx 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" @@ -1358,6 +1484,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fbc557aac2b708fe84121caf261346cc2eed71978024337e42eb46b8a252ac6e" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841" +"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" @@ -1371,6 +1498,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" +"checksum skeptic 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4474d6da9593171bcb086890fc344a3a12783cb24e5b141f8a5d0e43561f4b6" "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" "checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" diff --git a/server/Cargo.toml b/server/Cargo.toml index 4ac23ec1..72fe84d8 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -32,6 +32,7 @@ log = "0.4" env_logger = "0.5" rbx-tree = { git = "https://github.com/LPGhatguy/rbx-tree.git" } rbxmx = { git = "https://github.com/LPGhatguy/rbx-tree.git" } +rbxm = { git = "https://github.com/LPGhatguy/rbx-tree.git" } uuid = { version = "0.7", features = ["v4", "serde"] } [dev-dependencies] diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index ab57fb6b..70164709 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -5,8 +5,6 @@ use std::{ fmt, }; -use rbxmx; - use crate::{ rbx_session::construct_oneoff_tree, project::{Project, ProjectLoadFuzzyError}, @@ -17,6 +15,8 @@ use crate::{ pub enum OutputKind { Rbxmx, Rbxlx, + Rbxm, + Rbxl, } fn detect_output_kind(options: &BuildOptions) -> Option { @@ -25,6 +25,8 @@ fn detect_output_kind(options: &BuildOptions) -> Option { match extension { "rbxlx" => Some(OutputKind::Rbxlx), "rbxmx" => Some(OutputKind::Rbxmx), + "rbxl" => Some(OutputKind::Rbxl), + "rbxm" => Some(OutputKind::Rbxm), _ => None, } } @@ -100,6 +102,15 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); rbxmx::encode(&tree, top_level_ids, &mut file); }, + OutputKind::Rbxm => { + let root_id = tree.get_root_id(); + rbxm::encode(&tree, &[root_id], &mut file)?; + }, + OutputKind::Rbxl => { + let root_id = tree.get_root_id(); + let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); + rbxm::encode(&tree, top_level_ids, &mut file)?; + }, } Ok(()) From d427f0122472e1debe838d51fab570b19f14a03b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 30 Nov 2018 20:33:41 -0800 Subject: [PATCH 0231/1504] Add Rojo 0.5.0+ config to plugin --- plugin/roblox-project.json | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 plugin/roblox-project.json diff --git a/plugin/roblox-project.json b/plugin/roblox-project.json new file mode 100644 index 00000000..ab8cf8d0 --- /dev/null +++ b/plugin/roblox-project.json @@ -0,0 +1,38 @@ +{ + "name": "rojo", + "tree": { + "$className": "DataModel", + + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + "Rojo": { + "$className": "Folder", + "Plugin": { + "$path": "src" + }, + "Roact": { + "$path": "modules/roact/lib" + }, + "Rodux": { + "$path": "modules/rodux/lib" + }, + "RoactRodux": { + "$path": "modules/roact-rodux/lib" + }, + "Promise": { + "$path": "modules/promise/lib" + } + }, + "TestEZ": { + "$path": "modules/testez/lib" + } + }, + + "TestService": { + "$className": "TestService", + "TestBootstrap": { + "$path": "testBootstrap.server.lua" + } + } + } +} \ No newline at end of file From 26a7bb9746e9175855d3ea2977fdd4622d63a7cd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 1 Dec 2018 00:01:31 -0800 Subject: [PATCH 0232/1504] Stub out RbxSession::path_updated a bit --- server/src/rbx_session.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index b853a5ea..ca722fd0 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -33,6 +33,10 @@ impl PathIdTree { } } + pub fn get_id(&self, path: &Path) -> Option { + self.nodes.get(path).map(|v| v.id) + } + pub fn insert(&mut self, path: &Path, id: RbxId) { if let Some(parent_path) = path.parent() { if let Some(parent) = self.nodes.get_mut(parent_path) { @@ -111,10 +115,24 @@ impl RbxSession { pub fn path_created(&mut self, path: &Path) { info!("Path created: {}", path.display()); + self.path_updated(path); } pub fn path_updated(&mut self, path: &Path) { info!("Path updated: {}", path.display()); + + let imfs = self.imfs.lock().unwrap(); + + // If the path doesn't exist or it's a directory, we don't care if it + // updated + let file = match imfs.get(path) { + Some(ImfsItem::Directory(_)) | None => return, + Some(ImfsItem::File(file)) => file, + }; + + // TODO: Crawl up path to find first node represented in the tree or a + // sync point root. That path immediately before we find an existing + // node should be read into the tree. } pub fn path_removed(&mut self, path: &Path) { From 13a7c1ba81aa98cbd212422d2aa78991c9781920 Mon Sep 17 00:00:00 2001 From: boyned//Kampfkarren Date: Mon, 3 Dec 2018 10:35:40 -0800 Subject: [PATCH 0233/1504] Fixed clippy warnings (#90) * Fixed clippy warnings * Fix as per review --- server/src/fs_watcher.rs | 7 ++----- server/src/imfs.rs | 15 ++++++--------- server/src/message_queue.rs | 1 + server/src/project.rs | 15 ++++++--------- server/src/rbx_session.rs | 17 ++++++----------- server/src/session.rs | 4 ++-- server/src/web.rs | 19 ++++++++----------- 7 files changed, 31 insertions(+), 47 deletions(-) diff --git a/server/src/fs_watcher.rs b/server/src/fs_watcher.rs index a48319ef..9737aa4e 100644 --- a/server/src/fs_watcher.rs +++ b/server/src/fs_watcher.rs @@ -100,11 +100,8 @@ impl FsWatcher { thread::spawn(move || { info!("Watcher thread ({}) started", root_path.display()); - loop { - match watch_rx.recv() { - Ok(event) => handle_event(&imfs, &rbx_session, event), - Err(_) => break, - }; + while let Ok(event) = watch_rx.recv() { + handle_event(&imfs, &rbx_session, event); } info!("Watcher thread ({}) stopped", root_path.display()); }); diff --git a/server/src/imfs.rs b/server/src/imfs.rs index 47ca782a..40d81d6f 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -108,13 +108,10 @@ impl Imfs { } } - match self.items.remove(path) { - Some(ImfsItem::Directory(directory)) => { - for child_path in &directory.children { - self.path_removed(child_path)?; - } - }, - _ => {}, + if let Some(ImfsItem::Directory(directory)) = self.items.remove(path) { + for child_path in &directory.children { + self.path_removed(child_path)?; + } } Ok(()) @@ -173,7 +170,7 @@ impl ImfsItem { vfs.items.insert(path.to_path_buf(), item); - Ok(vfs.items.get(path).unwrap()) + Ok(&vfs.items[path]) } else if metadata.is_dir() { let mut children = HashSet::new(); @@ -193,7 +190,7 @@ impl ImfsItem { vfs.items.insert(path.to_path_buf(), item); - Ok(vfs.items.get(path).unwrap()) + Ok(&vfs.items[path]) } else { panic!("Unexpected non-file, non-directory item"); } diff --git a/server/src/message_queue.rs b/server/src/message_queue.rs index c7f75133..7c8280f6 100644 --- a/server/src/message_queue.rs +++ b/server/src/message_queue.rs @@ -29,6 +29,7 @@ pub enum Message { }, } +#[derive(Default)] pub struct MessageQueue { messages: RwLock>, message_listeners: Mutex>>, diff --git a/server/src/project.rs b/server/src/project.rs index 0221f7fc..e67834de 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -192,15 +192,12 @@ impl Project { } else if location_metadata.is_dir() { let with_file = start_location.join(PROJECT_FILENAME); - match fs::metadata(&with_file) { - Ok(with_file_metadata) => { - if with_file_metadata.is_file() { - return Some(with_file); - } else { - return None; - } - }, - Err(_) => {}, + if let Ok(with_file_metadata) = fs::metadata(&with_file) { + if with_file_metadata.is_file() { + return Some(with_file); + } else { + return None; + } } } diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index ca722fd0..705a6ecd 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -65,20 +65,15 @@ impl PathIdTree { let root_id = root_node.id; let mut to_visit: Vec = root_node.children.drain().collect(); - loop { - let next_path = match to_visit.pop() { - Some(path) => path, - None => break, - }; - - match self.nodes.remove(&next_path) { + while let Some(path) = to_visit.pop() { + match self.nodes.remove(&path) { Some(mut node) => { for child in node.children.drain() { to_visit.push(child); } }, None => { - warn!("Consistency issue; tried to remove {} but it was already removed", next_path.display()); + warn!("Consistency issue; tried to remove {} but it was already removed", path.display()); }, } } @@ -203,7 +198,7 @@ fn construct_initial_tree( construct_project_node( &mut context, None, - project.name.clone(), + &project.name, &project.name, &project.tree, ); @@ -231,7 +226,7 @@ fn insert_or_create_tree(context: &mut ConstructContext, parent_instance_id: Opt fn construct_project_node( context: &mut ConstructContext, parent_instance_id: Option, - instance_path: String, + instance_path: &str, instance_name: &str, project_node: &ProjectNode, ) { @@ -264,7 +259,7 @@ fn construct_instance_node( for (child_name, child_project_node) in &project_node.children { let child_path = format!("{}/{}", instance_path, child_name); - construct_project_node(context, Some(id), child_path, child_name, child_project_node); + construct_project_node(context, Some(id), &child_path, child_name, child_project_node); } id diff --git a/server/src/session.rs b/server/src/session.rs index 90488124..5fb589f6 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -17,7 +17,7 @@ pub struct Session { pub session_id: SessionId, pub message_queue: Arc, pub rbx_session: Arc>, - fs_watcher: FsWatcher, + _fs_watcher: FsWatcher, } impl Session { @@ -44,7 +44,7 @@ impl Session { session_id, message_queue, rbx_session, - fs_watcher, + _fs_watcher: fs_watcher, }) } diff --git a/server/src/web.rs b/server/src/web.rs index 168db49b..bae32228 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -54,7 +54,7 @@ pub struct Server { impl Server { pub fn new(session: Arc) -> Server { Server { - session: session, + session, server_version: env!("CARGO_PKG_VERSION"), } } @@ -94,7 +94,7 @@ impl Server { { let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); - if new_messages.len() > 0 { + if !new_messages.is_empty() { return Response::json(&SubscribeResponse { session_id: self.session.session_id, messages: Cow::Borrowed(&[]), @@ -129,7 +129,7 @@ impl Server { let message_queue = Arc::clone(&self.session.message_queue); let requested_ids: Option> = id_list - .split(",") + .split(',') .map(RbxId::parse_str) .collect(); @@ -146,15 +146,12 @@ impl Server { let mut instances = HashMap::new(); for &requested_id in &requested_ids { - match tree.get_instance(requested_id) { - Some(instance) => { - instances.insert(instance.get_id(), Cow::Borrowed(instance)); + if let Some(instance) = tree.get_instance(requested_id) { + instances.insert(instance.get_id(), Cow::Borrowed(instance)); - for descendant in tree.descendants(requested_id) { - instances.insert(descendant.get_id(), Cow::Borrowed(descendant)); - } - }, - None => {}, + for descendant in tree.descendants(requested_id) { + instances.insert(descendant.get_id(), Cow::Borrowed(descendant)); + } } } From 5114d12daf2d78bdcb67aa5c45fbc388634954a8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 10:38:26 -0800 Subject: [PATCH 0234/1504] Start using failure for error management --- server/Cargo.lock | 35 +++++++++++++++++++ server/Cargo.toml | 3 +- server/src/commands/build.rs | 23 +++++-------- server/src/project.rs | 66 ++++++++++++------------------------ 4 files changed, 68 insertions(+), 59 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index ecdd0192..2464935c 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -292,6 +292,26 @@ dependencies = [ "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "failure" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "failure_derive" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "filetime" version = "0.2.4" @@ -905,6 +925,7 @@ version = "0.5.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1084,6 +1105,17 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "synstructure" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tempdir" version = "0.3.7" @@ -1414,6 +1446,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" +"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" "checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" "checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05" "checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874" @@ -1504,6 +1538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" +"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" "checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" diff --git a/server/Cargo.toml b/server/Cargo.toml index 72fe84d8..5b6bfca8 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -30,10 +30,11 @@ rand = "0.4" regex = "1.0" log = "0.4" env_logger = "0.5" +uuid = { version = "0.7", features = ["v4", "serde"] } +failure = "0.1.3" rbx-tree = { git = "https://github.com/LPGhatguy/rbx-tree.git" } rbxmx = { git = "https://github.com/LPGhatguy/rbx-tree.git" } rbxm = { git = "https://github.com/LPGhatguy/rbx-tree.git" } -uuid = { version = "0.7", features = ["v4", "serde"] } [dev-dependencies] tempfile = "3.0" diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index 70164709..34cb73d7 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -2,9 +2,10 @@ use std::{ path::PathBuf, fs::File, io, - fmt, }; +use failure::Fail; + use crate::{ rbx_session::construct_oneoff_tree, project::{Project, ProjectLoadFuzzyError}, @@ -38,22 +39,16 @@ pub struct BuildOptions { pub output_kind: Option, } +#[derive(Debug, Fail)] pub enum BuildError { + #[fail(display = "Could not detect what kind of file to create")] UnknownOutputKind, - ProjectLoadError(ProjectLoadFuzzyError), - IoError(io::Error), -} -impl fmt::Display for BuildError { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - match self { - BuildError::UnknownOutputKind => { - write!(output, "Could not detect what kind of output file to create") - }, - BuildError::ProjectLoadError(inner) => write!(output, "{}", inner), - BuildError::IoError(inner) => write!(output, "{}", inner), - } - } + #[fail(display = "Project load error: {}", _0)] + ProjectLoadError(#[fail(cause)] ProjectLoadFuzzyError), + + #[fail(display = "IO error: {}", _0)] + IoError(#[fail(cause)] io::Error), } impl From for BuildError { diff --git a/server/src/project.rs b/server/src/project.rs index e67834de..539401d9 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -1,17 +1,16 @@ use std::{ collections::HashMap, - fmt, fs, io, path::{Path, PathBuf}, }; -use serde_json; +use failure::Fail; use rbx_tree::RbxValue; pub static PROJECT_FILENAME: &'static str = "roblox-project.json"; -// Serde is silly, +// Serde is silly. const fn yeah() -> bool { true } @@ -89,35 +88,25 @@ impl SourceProject { } } -#[derive(Debug)] +#[derive(Debug, Fail)] pub enum ProjectLoadExactError { - IoError(io::Error), - JsonError(serde_json::Error), + #[fail(display = "IO error: {}", _0)] + IoError(#[fail(cause)] io::Error), + + #[fail(display = "JSON error: {}", _0)] + JsonError(#[fail(cause)] serde_json::Error), } -impl fmt::Display for ProjectLoadExactError { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - match self { - ProjectLoadExactError::IoError(inner) => write!(output, "{}", inner), - ProjectLoadExactError::JsonError(inner) => write!(output, "{}", inner), - } - } -} - -#[derive(Debug)] -pub enum ProjectInitError {} - -impl fmt::Display for ProjectInitError { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - write!(output, "ProjectInitError") - } -} - -#[derive(Debug)] +#[derive(Debug, Fail)] pub enum ProjectLoadFuzzyError { + #[fail(display = "Project not found")] NotFound, - IoError(io::Error), - JsonError(serde_json::Error), + + #[fail(display = "IO error: {}", _0)] + IoError(#[fail(cause)] io::Error), + + #[fail(display = "JSON error: {}", _0)] + JsonError(#[fail(cause)] serde_json::Error), } impl From for ProjectLoadFuzzyError { @@ -129,24 +118,13 @@ impl From for ProjectLoadFuzzyError { } } -impl fmt::Display for ProjectLoadFuzzyError { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - match self { - ProjectLoadFuzzyError::NotFound => write!(output, "Project not found."), - ProjectLoadFuzzyError::IoError(inner) => write!(output, "{}", inner), - ProjectLoadFuzzyError::JsonError(inner) => write!(output, "{}", inner), - } - } -} +#[derive(Debug, Fail)] +#[fail(display = "Project init error")] +pub struct ProjectInitError; -#[derive(Debug)] -pub enum ProjectSaveError {} - -impl fmt::Display for ProjectSaveError { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - write!(output, "ProjectSaveError") - } -} +#[derive(Debug, Fail)] +#[fail(display = "Project save error")] +pub struct ProjectSaveError; #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(tag = "type")] From f59a9040fca719292235566ae590ae07cd5b51a8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 11:48:30 -0800 Subject: [PATCH 0235/1504] Update plugin project files, remove outdated DESIGN doc --- DESIGN.md | 126 ------------------------------------- plugin/roblox-package.json | 21 +++++++ plugin/roblox-project.json | 17 +---- 3 files changed, 22 insertions(+), 142 deletions(-) delete mode 100644 DESIGN.md create mode 100644 plugin/roblox-package.json diff --git a/DESIGN.md b/DESIGN.md deleted file mode 100644 index 1847c57d..00000000 --- a/DESIGN.md +++ /dev/null @@ -1,126 +0,0 @@ -# Rojo - Protocol v2 Design -This spec is a work in progress. - -The aim is to rewrite most of Rojo to drop the notion of routes almost entirely in favor of generated IDs and make the server much more stateful. This should make change description completely robust in all cases, including models with many duplicated instance names. - -## Base Terms - -* **Server**: The binary portion of Rojo, in Rust. -* **Client**: The Roblox Studio plugin portion of Rojo, in Lua. -* **Middleware**: Part of the server, transforms files to Roblox representations and back. -* **VFS**: The Virtual File System specifically that middleware deal with; it is in-memory. -* **Roblox Instance**: An actual Roblox object derived from `Instance` on the client. - -## Initialization -On server initialization, Rojo reads all files in each partition and runs each through our middleware stack (renamed from plugins). Middleware transform a `VfsItem` into a set of `RbxInstance` objects with these properties: - -* name: `String` -* class_name: `String` -* parent: `Option` -* properties: `HashMap` -* file_route: `FileRoute` -* id: `Id` -* rbx_referent: `Option` - -The server should keep these book-keeping maps: - -* partitions: `HashMap`, to read partitions from disk -* partition_instances: `HashMap`, to track partition instances -* partition_files: `HashMap`, to serve as an in-memory filesystem -* instances: `HashMap`, to serve as an index -* instances_by_route: `HashMap`, to handle filesystem changes - -As a future extension, the server should also track: - -* `referent_to_id`: `HashMap`, when loading `rbxmx` format models from disk. - -`Partition` is defined as: - -* path: `PathBuf` -* target: `Vec` - -On initial sync, the client should receive: - -* A list of every `RbxInstance` the server knows of. -* A map from `Id` to a Roblox route, containing an entry for every partition and where they should be mounted. - -## File Changes -Whenever a file is changed, the server should: - -* Convert its path to a `FileRoute`. -* Read the file into a `VfsItem` object. -* Compare the contents of the file with the last-seen contents from the map from `FileRoute` to `String`. - * If they're the same, that means this change was caused by the server itself, and should be discarded. - * Else, clear the value from the map. -* Pass the `VfsItem` through the middleware chain to create a tree of `RbxInstance` objects. -* Check the existing map from `FileRoute` to `Id`. - * If an existing instance exists with the root's `Id`, reuse it and replace the root's `Id`. - * Else, generate a new ID. -* For each child instance: - * If an `RbxReferent` value is present on the instance, attempt to map it to an existing `Id`, falling back to creating a new `Id`. -* Log a change event `(Timestamp, Id)` for the root instance into a sorted list that's client queryable. - -The client will then: - -* Receive notice of changes by receiving a list of `Id`s that have changed. -* Ask the server for the contents of each `Id` that has changed. -* Apply the properties the server returns to each instance. - -If an `Id` was not previously tracked by the client, the associated `RbxInstance`'s `parent` field will point to another `Id`. The client will either have knowledge of that `Id`, or request it from the server if it isn't known. This can potentially continue up the tree until the client reaches a partition mount point, which should be known by the client due to the initialization process. - -## Client Changes -The client should keep list of mutations to track any uncommitted changes to Roblox Instances tracked by Rojo. - -Those changes should come in three flavors: - -* Changed a property (need `id`, `key`, and `value`) -* Deleted a known instance (need `id`) -* Created a new instance (need `clientId`) - -Every sync period, which could be around 50ms, the plugin should send a request with every Roblox Instance mutation all at once. - -In order to correctly serialize changes received from the client, some care needs to be taken. - -For every *Changed* or *Deleted* mutation received from the client, the server should: - -* Attempt to locate the `RbxInstance` associated with the `id`. - * If it doesn't exist, abort the change and output a warning to the console. -* Modify the `RbxInstance` in-place. -* Traverse up the tree by following the `parent` property until an `RbxInstance` is found that has a `route` property. -* Use the middleware chain to serialize these nodes to a single `VfsItem` object. -* Insert the contents of the `VfsItem` into the server's map from `Route` to `String`, which is used by the "File Changes" process. -* Write the file or directory to the disk atomically using *write-and-rename*. - -For every *Created* mutation received from the client, the server should: - -* Attempt to locate the `RbxInstance` associated with the instance's `parent` `Id` - * If it doesn't exist, abort the change and output a warning to the console. -* Generate a new `Id` for the instance being created. -* Use the middleware chain to process the added instance, its parent, and generate a list of `VfsItem` objects to commit to disk. -* Insert the `RbxInstance` into all of the server's relevant maps. -* Yield the generated `Id` to the client, indexed by the request's `clientId`, which can be used for later updates in both directions. - -## State and Session Restart -Previously, only the client had meaningful state with regards to what instances were loaded; the server in 0.3.x only tracks a list of changes by route. - -Both the Rojo server and client in the Stateful IDs redesign have a significant amount of state, which requires using a field already present, but unused, in the sync protocol. - -During initialization and initial sync, the server should send the client two values: -* A server ID value generated randomly on each startup -* A project name, specified in `rojo.json` - -The client should store the server ID as connection metadata, and the project name as place metadata that it may persist. - -Every request from the client should attach both the server ID and the project name. As a first validation check, the server must compare both values to its own. - -If a mismatch is detected, the server should immediately abort the request and return an error containing its server ID and loaded project name. - -If the client detects an error in this way, it should delete any connection metadata, including `Id` mappings -- this data is no longer relevant to any new connections. - -If the returned project name matches the value that the client was using before, the client should begin a *session restart* by reinitializing the connection to the server and creating new metadata. - -## Other Changes -These changes aren't directly related to this refactor, but are changes that need to be made to Rojo. - -* Unknown instances will no longer sync as `StringValue` instances -* `rojo init` generates project files with random port numbers \ No newline at end of file diff --git a/plugin/roblox-package.json b/plugin/roblox-package.json new file mode 100644 index 00000000..1d1ace9f --- /dev/null +++ b/plugin/roblox-package.json @@ -0,0 +1,21 @@ +{ + "name": "Rojo", + "tree": { + "$className": "Folder", + "Plugin": { + "$path": "src" + }, + "Roact": { + "$path": "modules/roact/lib" + }, + "Rodux": { + "$path": "modules/rodux/lib" + }, + "RoactRodux": { + "$path": "modules/roact-rodux/lib" + }, + "Promise": { + "$path": "modules/promise/lib" + } + } +} \ No newline at end of file diff --git a/plugin/roblox-project.json b/plugin/roblox-project.json index ab8cf8d0..0c399c87 100644 --- a/plugin/roblox-project.json +++ b/plugin/roblox-project.json @@ -6,22 +6,7 @@ "ReplicatedStorage": { "$className": "ReplicatedStorage", "Rojo": { - "$className": "Folder", - "Plugin": { - "$path": "src" - }, - "Roact": { - "$path": "modules/roact/lib" - }, - "Rodux": { - "$path": "modules/rodux/lib" - }, - "RoactRodux": { - "$path": "modules/roact-rodux/lib" - }, - "Promise": { - "$path": "modules/promise/lib" - } + "$path": "." }, "TestEZ": { "$path": "modules/testez/lib" From db7f8ffb1b8eb7ffc2276d9c351cbd7e5e5dd155 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 11:52:06 -0800 Subject: [PATCH 0236/1504] Update to latest rbx-tree --- server/Cargo.lock | 36 ++++++++++++++++++------------------ server/Cargo.toml | 4 ++-- server/src/commands/build.rs | 8 ++++---- 3 files changed, 24 insertions(+), 24 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 2464935c..abb87827 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -850,19 +850,9 @@ dependencies = [ ] [[package]] -name = "rbx-tree" +name = "rbx-binary" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#9d42aa5da5132cc08bd04e30d235207e774d9909" -dependencies = [ - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rbxm" -version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#9d42aa5da5132cc08bd04e30d235207e774d9909" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#c0393de710c32a1766b4ae829e24bab8a9e48cc2" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -870,9 +860,19 @@ dependencies = [ ] [[package]] -name = "rbxmx" +name = "rbx-tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#9d42aa5da5132cc08bd04e30d235207e774d9909" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#c0393de710c32a1766b4ae829e24bab8a9e48cc2" +dependencies = [ + "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rbx-xml" +version = "0.1.0" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#c0393de710c32a1766b4ae829e24bab8a9e48cc2" dependencies = [ "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -930,9 +930,9 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx-binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", - "rbxm 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", - "rbxmx 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", + "rbx-xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1509,9 +1509,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" +"checksum rbx-binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" -"checksum rbxm 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" -"checksum rbxmx 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" +"checksum rbx-xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467" diff --git a/server/Cargo.toml b/server/Cargo.toml index 5b6bfca8..d8777d76 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -33,8 +33,8 @@ env_logger = "0.5" uuid = { version = "0.7", features = ["v4", "serde"] } failure = "0.1.3" rbx-tree = { git = "https://github.com/LPGhatguy/rbx-tree.git" } -rbxmx = { git = "https://github.com/LPGhatguy/rbx-tree.git" } -rbxm = { git = "https://github.com/LPGhatguy/rbx-tree.git" } +rbx-xml = { git = "https://github.com/LPGhatguy/rbx-tree.git" } +rbx-binary = { git = "https://github.com/LPGhatguy/rbx-tree.git" } [dev-dependencies] tempfile = "3.0" diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index 34cb73d7..6d2ce204 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -87,7 +87,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { // descendants. let root_id = tree.get_root_id(); - rbxmx::encode(&tree, &[root_id], &mut file); + rbx_xml::encode(&tree, &[root_id], &mut file); }, OutputKind::Rbxlx => { // Place files don't contain an entry for the DataModel, but our @@ -95,16 +95,16 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let root_id = tree.get_root_id(); let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); - rbxmx::encode(&tree, top_level_ids, &mut file); + rbx_xml::encode(&tree, top_level_ids, &mut file); }, OutputKind::Rbxm => { let root_id = tree.get_root_id(); - rbxm::encode(&tree, &[root_id], &mut file)?; + rbx_binary::encode(&tree, &[root_id], &mut file)?; }, OutputKind::Rbxl => { let root_id = tree.get_root_id(); let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); - rbxm::encode(&tree, top_level_ids, &mut file)?; + rbx_binary::encode(&tree, top_level_ids, &mut file)?; }, } From 75359e2b8308f80a223b11e98a27f27db6b3b1c0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 11:58:09 -0800 Subject: [PATCH 0237/1504] Upgrade to latest rbx_tree (underscores! ) --- server/Cargo.lock | 28 ++++++++++++++-------------- server/Cargo.toml | 6 +++--- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index abb87827..a7f3223d 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -850,19 +850,19 @@ dependencies = [ ] [[package]] -name = "rbx-binary" +name = "rbx_binary" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#c0393de710c32a1766b4ae829e24bab8a9e48cc2" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#b5972918fae985f9570811ab05993d268aba03cc" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", + "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", ] [[package]] -name = "rbx-tree" +name = "rbx_tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#c0393de710c32a1766b4ae829e24bab8a9e48cc2" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#b5972918fae985f9570811ab05993d268aba03cc" dependencies = [ "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", @@ -870,11 +870,11 @@ dependencies = [ ] [[package]] -name = "rbx-xml" +name = "rbx_xml" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#c0393de710c32a1766b4ae829e24bab8a9e48cc2" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#b5972918fae985f9570811ab05993d268aba03cc" dependencies = [ - "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", + "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -930,9 +930,9 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx-binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", - "rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", - "rbx-xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", + "rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", + "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", + "rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1509,9 +1509,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" -"checksum rbx-binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" -"checksum rbx-tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" -"checksum rbx-xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" +"checksum rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" +"checksum rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" +"checksum rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467" diff --git a/server/Cargo.toml b/server/Cargo.toml index d8777d76..a28f5bab 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -32,9 +32,9 @@ log = "0.4" env_logger = "0.5" uuid = { version = "0.7", features = ["v4", "serde"] } failure = "0.1.3" -rbx-tree = { git = "https://github.com/LPGhatguy/rbx-tree.git" } -rbx-xml = { git = "https://github.com/LPGhatguy/rbx-tree.git" } -rbx-binary = { git = "https://github.com/LPGhatguy/rbx-tree.git" } +rbx_tree = { git = "https://github.com/LPGhatguy/rbx-tree.git" } +rbx_xml = { git = "https://github.com/LPGhatguy/rbx-tree.git" } +rbx_binary = { git = "https://github.com/LPGhatguy/rbx-tree.git" } [dev-dependencies] tempfile = "3.0" From dd4d542d7e1348f578d1c2184336252ab8cbefbf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 13:54:54 -0800 Subject: [PATCH 0238/1504] Clean up and start work on Epiphany plugin --- plugin/src/Http.lua | 43 ++++++++++++++++++++++--------------- plugin/src/HttpResponse.lua | 24 +++++++++++++++++++++ plugin/src/Logging.lua | 21 ++++++++++++++++++ 3 files changed, 71 insertions(+), 17 deletions(-) create mode 100644 plugin/src/Logging.lua diff --git a/plugin/src/Http.lua b/plugin/src/Http.lua index 2087cee7..e8753c0e 100644 --- a/plugin/src/Http.lua +++ b/plugin/src/Http.lua @@ -18,38 +18,47 @@ local Http = {} function Http.get(url) dprint("\nGET", url) + return Promise.new(function(resolve, reject) - spawn(function() - local ok, result = pcall(function() - return HttpService:GetAsync(url, true) + coroutine.wrap(function() + local success, response = pcall(function() + return HttpService:RequestAsync({ + Url = url, + Method = "GET", + }) end) - if ok then - dprint("\t", result) - resolve(HttpResponse.new(result)) + if success then + dprint("\t", response) + resolve(HttpResponse.fromRobloxResponse(response)) else - reject(HttpError.fromErrorString(result)) + reject(HttpError.fromErrorString(response)) end - end) + end)() end) end function Http.post(url, body) dprint("\nPOST", url) - dprint(body) + dprint(body); + return Promise.new(function(resolve, reject) - spawn(function() - local ok, result = pcall(function() - return HttpService:PostAsync(url, body) + coroutine.wrap(function() + local success, response = pcall(function() + return HttpService:RequestAsync({ + Url = url, + Method = "POST", + Body = body, + }) end) - if ok then - dprint("\t", result) - resolve(HttpResponse.new(result)) + if success then + dprint("\t", response) + resolve(HttpResponse.fromRobloxResponse(response)) else - reject(HttpError.fromErrorString(result)) + reject(HttpError.fromErrorString(response)) end - end) + end)() end) end diff --git a/plugin/src/HttpResponse.lua b/plugin/src/HttpResponse.lua index 0b85db94..c9a210ca 100644 --- a/plugin/src/HttpResponse.lua +++ b/plugin/src/HttpResponse.lua @@ -1,8 +1,18 @@ local HttpService = game:GetService("HttpService") +local stringTemplate = [[ +HttpResponse { + code: %d + body: %s +}]] + local HttpResponse = {} HttpResponse.__index = HttpResponse +function HttpResponse:__tostring() + return stringTemplate:format(self.code, self.body) +end + function HttpResponse.new(body) local response = { body = body, @@ -13,6 +23,20 @@ function HttpResponse.new(body) return response end +function HttpResponse.fromRobloxResponse(response) + local self = { + body = response.Body, + code = response.StatusCode, + headers = response.Headers, + } + + return setmetatable(self, HttpResponse) +end + +function HttpResponse:isSuccess() + return self.code >= 200 and self.code < 300 +end + function HttpResponse:json() return HttpService:JSONDecode(self.body) end diff --git a/plugin/src/Logging.lua b/plugin/src/Logging.lua new file mode 100644 index 00000000..0cedb620 --- /dev/null +++ b/plugin/src/Logging.lua @@ -0,0 +1,21 @@ +local enabledByTest = false + +local function isEnabled() + return _G.ROJO_LOG or enabledByTest +end + +local Logging = {} + +function Logging.info(template, ...) + if isEnabled() then + print("[Rojo] " .. template:format(...)) + end +end + +function Logging.warn(template, ...) + if isEnabled() then + warn("[Rojo] " .. template:format(...)) + end +end + +return Logging \ No newline at end of file From 061ea0e7a30d3d690645b6429d93318db53a5cf1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 16:24:28 -0800 Subject: [PATCH 0239/1504] Unify logging --- plugin/src/Http.lua | 26 ++++++++++--------- plugin/src/HttpError.lua | 10 ++++++-- plugin/src/HttpResponse.lua | 10 -------- plugin/src/Logging.lua | 50 +++++++++++++++++++++++++++++-------- plugin/src/Main.server.lua | 7 ++++-- plugin/src/Session.lua | 9 +++---- 6 files changed, 70 insertions(+), 42 deletions(-) diff --git a/plugin/src/Http.lua b/plugin/src/Http.lua index e8753c0e..eda12b05 100644 --- a/plugin/src/Http.lua +++ b/plugin/src/Http.lua @@ -1,23 +1,21 @@ local HttpService = game:GetService("HttpService") -local HTTP_DEBUG = true - local Promise = require(script.Parent.Parent.Promise) +local Logging = require(script.Parent.Logging) local HttpError = require(script.Parent.HttpError) local HttpResponse = require(script.Parent.HttpResponse) -local function dprint(...) - if HTTP_DEBUG then - print(...) - end -end +local lastRequestId = 0 -- TODO: Factor out into separate library, especially error handling local Http = {} function Http.get(url) - dprint("\nGET", url) + local requestId = lastRequestId + 1 + lastRequestId = requestId + + Logging.trace("GET(%d) %s", requestId, url) return Promise.new(function(resolve, reject) coroutine.wrap(function() @@ -29,9 +27,10 @@ function Http.get(url) end) if success then - dprint("\t", response) + Logging.trace("Request %d success: status code %s", requestId, response.StatusCode) resolve(HttpResponse.fromRobloxResponse(response)) else + Logging.trace("Request %d failure: %s", requestId, response) reject(HttpError.fromErrorString(response)) end end)() @@ -39,8 +38,10 @@ function Http.get(url) end function Http.post(url, body) - dprint("\nPOST", url) - dprint(body); + local requestId = lastRequestId + 1 + lastRequestId = requestId + + Logging.trace("POST(%d) %s\n%s", requestId, url, body) return Promise.new(function(resolve, reject) coroutine.wrap(function() @@ -53,9 +54,10 @@ function Http.post(url, body) end) if success then - dprint("\t", response) + Logging.trace("Request %d success: status code %s", requestId, response.StatusCode) resolve(HttpResponse.fromRobloxResponse(response)) else + Logging.trace("Request %d failure: %s", requestId, response) reject(HttpError.fromErrorString(response)) end end)() diff --git a/plugin/src/HttpError.lua b/plugin/src/HttpError.lua index ed611356..462ed5f1 100644 --- a/plugin/src/HttpError.lua +++ b/plugin/src/HttpError.lua @@ -1,3 +1,8 @@ +local Selection = game:GetService("Selection") +local HttpService = game:GetService("HttpService") + +local Logging = require(script.Parent.Logging) + local HttpError = {} HttpError.__index = HttpError @@ -58,9 +63,10 @@ function HttpError.fromErrorString(err) end function HttpError:report() - warn(self.message) + Logging.warn(self.message) + if self.type == HttpError.Error.HttpNotEnabled then - game:GetService("Selection"):Set{game:GetService("HttpService")} + Selection:Set(HttpService) end end diff --git a/plugin/src/HttpResponse.lua b/plugin/src/HttpResponse.lua index c9a210ca..637f57de 100644 --- a/plugin/src/HttpResponse.lua +++ b/plugin/src/HttpResponse.lua @@ -13,16 +13,6 @@ function HttpResponse:__tostring() return stringTemplate:format(self.code, self.body) end -function HttpResponse.new(body) - local response = { - body = body, - } - - setmetatable(response, HttpResponse) - - return response -end - function HttpResponse.fromRobloxResponse(response) local self = { body = response.Body, diff --git a/plugin/src/Logging.lua b/plugin/src/Logging.lua index 0cedb620..a7f15c55 100644 --- a/plugin/src/Logging.lua +++ b/plugin/src/Logging.lua @@ -1,21 +1,49 @@ -local enabledByTest = false +local testLogLevel = nil +local configValue = game:FindFirstChild("ROJO_LOG") -local function isEnabled() - return _G.ROJO_LOG or enabledByTest +local Level = { + Error = 0, + Warning = 1, + Info = 2, + Trace = 3, +} + +local function getLogLevel() + if testLogLevel ~= nil then + return testLogLevel + end + + if _G.ROJO_LOG ~= nil then + return _G.ROJO_LOG + end + + if configValue ~= nil then + return configValue.Value + end + + return Level.Info end -local Logging = {} +local Log = {} -function Logging.info(template, ...) - if isEnabled() then - print("[Rojo] " .. template:format(...)) +Log.Level = Level + +function Log.trace(template, ...) + if getLogLevel() >= Level.Trace then + print("[Rojo-Trace] " .. string.format(template, ...)) end end -function Logging.warn(template, ...) - if isEnabled() then - warn("[Rojo] " .. template:format(...)) +function Log.info(template, ...) + if getLogLevel() >= Level.Info then + print("[Rojo-Info] " .. string.format(template, ...)) end end -return Logging \ No newline at end of file +function Log.warn(template, ...) + if getLogLevel() >= Level.Warning then + warn("[Rojo-Warn] " .. string.format(template, ...)) + end +end + +return Log \ No newline at end of file diff --git a/plugin/src/Main.server.lua b/plugin/src/Main.server.lua index e2c50be3..844c5e87 100644 --- a/plugin/src/Main.server.lua +++ b/plugin/src/Main.server.lua @@ -5,6 +5,7 @@ end local Session = require(script.Parent.Session) local Config = require(script.Parent.Config) local Version = require(script.Parent.Version) +local Logging = require(script.Parent.Logging) --[[ Check if the user is using a newer version of Rojo than last time. If they @@ -41,6 +42,8 @@ end local function main() local displayedVersion = Config.dev and "DEV" or Version.display(Config.version) + Logging.trace("Rojo %s initialized", displayedVersion) + local toolbar = plugin:CreateToolbar("Rojo " .. displayedVersion) local currentSession @@ -52,11 +55,11 @@ local function main() checkUpgrade() if currentSession ~= nil then - warn("Rojo: A session is already running!") + Logging.warn("A session is already running!") return end - print("Rojo: Started session.") + Logging.info("Started new session.") currentSession = Session.new() end) end diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 4eb1d012..ab47170a 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -1,5 +1,6 @@ local Config = require(script.Parent.Config) local ApiContext = require(script.Parent.ApiContext) +local Logging = require(script.Parent.Logging) local REMOTE_URL = ("http://localhost:%d"):format(Config.port) @@ -9,16 +10,14 @@ Session.__index = Session function Session.new() local self = {} - setmetatable(self, Session) - local api api = ApiContext.new(REMOTE_URL, function(message) if message.type == "InstanceChanged" then - print("Instance", message.id, "changed!") + Logging.trace("Instance %s changed!", message.id) -- readAll() else - warn("Unknown message type " .. message.type) + Logging.warn("Unknown message type %s", message.type) end end) @@ -30,7 +29,7 @@ function Session.new() return api:retrieveMessages() end) - return self + return setmetatable(self, Session) end return Session From 503d7400f3819ec78cfca3d5df8b43bb699058c0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 16:54:21 -0800 Subject: [PATCH 0240/1504] Add a dev settings feature, keyed off codename right now --- plugin/src/Config.lua | 4 +- plugin/src/Config.spec.lua | 7 --- plugin/src/DevSettings.lua | 53 +++++++++++++++++++ plugin/src/HttpError.lua | 23 +++----- plugin/src/Logging.lua | 18 ++++--- plugin/src/Session.lua | 3 ++ .../src/{Main.server.lua => init.server.lua} | 15 +++--- 7 files changed, 86 insertions(+), 37 deletions(-) delete mode 100644 plugin/src/Config.spec.lua create mode 100644 plugin/src/DevSettings.lua rename plugin/src/{Main.server.lua => init.server.lua} (77%) diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index a3bb163a..1525c2f8 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,7 +1,7 @@ return { + codename = "Epiphany", version = {0, 5, 0}, - expectedServerVersionString = "0.5.x", + expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, port = 34872, - dev = false, } diff --git a/plugin/src/Config.spec.lua b/plugin/src/Config.spec.lua deleted file mode 100644 index ce9b43fd..00000000 --- a/plugin/src/Config.spec.lua +++ /dev/null @@ -1,7 +0,0 @@ -return function() - local Config = require(script.Parent.Config) - - it("should have 'dev' disabled", function() - expect(Config.dev).to.equal(false) - end) -end diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua new file mode 100644 index 00000000..efca1e3f --- /dev/null +++ b/plugin/src/DevSettings.lua @@ -0,0 +1,53 @@ +local Config = require(script.Parent.Config) + +local function getValueContainer() + return game:FindFirstChild("RojoDev-" .. Config.codename) +end + +local valueContainer = getValueContainer() + +local function create() + valueContainer = getValueContainer() + + if valueContainer == nil then + valueContainer = Instance.new("Folder") + valueContainer.Name = "RojoDev-" .. Config.codename + valueContainer.Parent = game + end + + local valueLogLevel = valueContainer:FindFirstChild("LogLevel") + if valueLogLevel == nil then + valueLogLevel = Instance.new("IntValue") + valueLogLevel.Name = "LogLevel" + valueLogLevel.Value = 2 + valueLogLevel.Parent = valueContainer + end +end + +_G[("ROJO_%s_DEV_CREATE"):format(Config.codename:upper())] = create + +local function getValue(name) + if valueContainer == nil then + return nil + end + + local valueObject = valueContainer:FindFirstChild(name) + + if valueObject == nil then + return nil + end + + return valueObject.Value +end + +local DevSettings = {} + +function DevSettings:isEnabled() + return valueContainer ~= nil +end + +function DevSettings:getLogLevel() + return getValue("LogLevel") +end + +return DevSettings \ No newline at end of file diff --git a/plugin/src/HttpError.lua b/plugin/src/HttpError.lua index 462ed5f1..e28bc392 100644 --- a/plugin/src/HttpError.lua +++ b/plugin/src/HttpError.lua @@ -12,14 +12,11 @@ HttpError.Error = { "Check your game settings, located in the 'Home' tab of Studio.", }, ConnectFailed = { - message = "Rojo plugin couldn't connect to the Rojo server.\n" .. + message = "Couldn't connect to the Rojo server.\n" .. "Make sure the server is running -- use 'rojo serve' to run it!", }, - Timeout = { - message = "Rojo timed out during a request.", - }, Unknown = { - message = "Rojo encountered an unknown error: {{message}}", + message = "Unknown error: {{message}}", }, } @@ -44,22 +41,18 @@ end --[[ This method shouldn't have to exist. Ugh. ]] -function HttpError.fromErrorString(err) - err = err:lower() +function HttpError.fromErrorString(message) + local lower = message:lower() - if err:find("^http requests are not enabled") then + if lower:find("^http requests are not enabled") then return HttpError.new(HttpError.Error.HttpNotEnabled) end - if err:find("^curl error") then - if err:find("couldn't connect to server") then - return HttpError.new(HttpError.Error.ConnectFailed) - elseif err:find("timeout was reached") then - return HttpError.new(HttpError.Error.Timeout) - end + if lower:find("^httperror: connectfail") then + return HttpError.new(HttpError.Error.ConnectFailed) end - return HttpError.new(HttpError.Error.Unknown, err) + return HttpError.new(HttpError.Error.Unknown, message) end function HttpError:report() diff --git a/plugin/src/Logging.lua b/plugin/src/Logging.lua index a7f15c55..b6f24c3b 100644 --- a/plugin/src/Logging.lua +++ b/plugin/src/Logging.lua @@ -1,5 +1,6 @@ +local DevSettings = require(script.Parent.DevSettings) + local testLogLevel = nil -local configValue = game:FindFirstChild("ROJO_LOG") local Level = { Error = 0, @@ -17,32 +18,37 @@ local function getLogLevel() return _G.ROJO_LOG end - if configValue ~= nil then - return configValue.Value + local hyperValue = DevSettings:getLogLevel() + if hyperValue ~= nil then + return hyperValue end return Level.Info end +local function addTags(tag, message) + return tag .. message:gsub("\n", "\n" .. tag) +end + local Log = {} Log.Level = Level function Log.trace(template, ...) if getLogLevel() >= Level.Trace then - print("[Rojo-Trace] " .. string.format(template, ...)) + print(addTags("[Rojo-Trace] ", string.format(template, ...))) end end function Log.info(template, ...) if getLogLevel() >= Level.Info then - print("[Rojo-Info] " .. string.format(template, ...)) + print(addTags("[Rojo-Info] ", string.format(template, ...))) end end function Log.warn(template, ...) if getLogLevel() >= Level.Warning then - warn("[Rojo-Warn] " .. string.format(template, ...)) + warn(addTags("[Rojo-Warn] ", string.format(template, ...))) end end diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index ab47170a..b01c30d7 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -28,6 +28,9 @@ function Session.new() :andThen(function() return api:retrieveMessages() end) + :catch(function(message) + Logging.warn("Couldn't start a new Rojo session: %s", tostring(message)) + end) return setmetatable(self, Session) end diff --git a/plugin/src/Main.server.lua b/plugin/src/init.server.lua similarity index 77% rename from plugin/src/Main.server.lua rename to plugin/src/init.server.lua index 844c5e87..e4edfcb2 100644 --- a/plugin/src/Main.server.lua +++ b/plugin/src/init.server.lua @@ -2,10 +2,11 @@ if not plugin then return end -local Session = require(script.Parent.Session) -local Config = require(script.Parent.Config) -local Version = require(script.Parent.Version) -local Logging = require(script.Parent.Logging) +local Session = require(script.Session) +local Config = require(script.Config) +local Version = require(script.Version) +local Logging = require(script.Logging) +local DevSettings = require(script.DevSettings) --[[ Check if the user is using a newer version of Rojo than last time. If they @@ -13,7 +14,7 @@ local Logging = require(script.Parent.Logging) ]] local function checkUpgrade() -- When developing Rojo, there's no use in doing version checks - if Config.dev then + if DevSettings:isEnabled() then return end @@ -26,7 +27,7 @@ local function checkUpgrade() local message = ( "\nRojo detected an upgrade from version %s to version %s." .. "\nMake sure you have also upgraded your server!" .. - "\n\nRojo version %s is intended for use with server version %s.\n" + "\n\nRojo plugin version %s is intended for use with server version %s.\n" ):format( Version.display(lastVersion), Version.display(Config.version), Version.display(Config.version), Config.expectedServerVersionString @@ -40,7 +41,7 @@ local function checkUpgrade() end local function main() - local displayedVersion = Config.dev and "DEV" or Version.display(Config.version) + local displayedVersion = DevSettings:isEnabled() and "DEV" or Version.display(Config.version) Logging.trace("Rojo %s initialized", displayedVersion) From f691d8a6a556e865e238ba61ca613585ded44c83 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 16:57:28 -0800 Subject: [PATCH 0241/1504] Clean up DevSettings --- plugin/src/DevSettings.lua | 46 +++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua index efca1e3f..9dcc4fca 100644 --- a/plugin/src/DevSettings.lua +++ b/plugin/src/DevSettings.lua @@ -6,26 +6,6 @@ end local valueContainer = getValueContainer() -local function create() - valueContainer = getValueContainer() - - if valueContainer == nil then - valueContainer = Instance.new("Folder") - valueContainer.Name = "RojoDev-" .. Config.codename - valueContainer.Parent = game - end - - local valueLogLevel = valueContainer:FindFirstChild("LogLevel") - if valueLogLevel == nil then - valueLogLevel = Instance.new("IntValue") - valueLogLevel.Name = "LogLevel" - valueLogLevel.Value = 2 - valueLogLevel.Parent = valueContainer - end -end - -_G[("ROJO_%s_DEV_CREATE"):format(Config.codename:upper())] = create - local function getValue(name) if valueContainer == nil then return nil @@ -40,6 +20,32 @@ local function getValue(name) return valueObject.Value end +local function setValue(name, kind, value) + local object = valueContainer:FindFirstChild(name) + + if object == nil then + object = Instance.new(kind) + object.Name = name + object.Parent = valueContainer + end + + object.Value = value +end + +local function createAllValues() + valueContainer = getValueContainer() + + if valueContainer == nil then + valueContainer = Instance.new("Folder") + valueContainer.Name = "RojoDev-" .. Config.codename + valueContainer.Parent = game + end + + setValue("LogLevel", "IntValue", getValue("LogLevel") or 2) +end + +_G[("ROJO_%s_DEV_CREATE"):format(Config.codename:upper())] = createAllValues + local DevSettings = {} function DevSettings:isEnabled() From 4542febaaf4ffdb5c95b84bb4c6be43f11cb87e2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 16:59:04 -0800 Subject: [PATCH 0242/1504] Remove global logging variable --- plugin/src/Logging.lua | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/plugin/src/Logging.lua b/plugin/src/Logging.lua index b6f24c3b..30c54c78 100644 --- a/plugin/src/Logging.lua +++ b/plugin/src/Logging.lua @@ -14,13 +14,9 @@ local function getLogLevel() return testLogLevel end - if _G.ROJO_LOG ~= nil then - return _G.ROJO_LOG - end - - local hyperValue = DevSettings:getLogLevel() - if hyperValue ~= nil then - return hyperValue + local devValue = DevSettings:getLogLevel() + if devValue ~= nil then + return devValue end return Level.Info From e4379e29af7025c583269be3111bd662f92f7467 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 17:04:08 -0800 Subject: [PATCH 0243/1504] Refactor upgrade messaging and version display --- plugin/src/init.server.lua | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index e4edfcb2..de1d2873 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -8,6 +8,19 @@ local Version = require(script.Version) local Logging = require(script.Logging) local DevSettings = require(script.DevSettings) +local function showUpgradeMessage(lastVersion) + local message = ( + "Rojo detected an upgrade from version %s to version %s." .. + "\nMake sure you have also upgraded your server!" .. + "\n\nRojo plugin version %s is intended for use with server version %s." + ):format( + Version.display(lastVersion), Version.display(Config.version), + Version.display(Config.version), Config.expectedServerVersionString + ) + + Logging.info(message) +end + --[[ Check if the user is using a newer version of Rojo than last time. If they are, show them a reminder to make sure they check their server version. @@ -24,16 +37,7 @@ local function checkUpgrade() local wasUpgraded = Version.compare(Config.version, lastVersion) == 1 if wasUpgraded then - local message = ( - "\nRojo detected an upgrade from version %s to version %s." .. - "\nMake sure you have also upgraded your server!" .. - "\n\nRojo plugin version %s is intended for use with server version %s.\n" - ):format( - Version.display(lastVersion), Version.display(Config.version), - Version.display(Config.version), Config.expectedServerVersionString - ) - - print(message) + showUpgradeMessage(lastVersion) end end @@ -41,7 +45,9 @@ local function checkUpgrade() end local function main() - local displayedVersion = DevSettings:isEnabled() and "DEV" or Version.display(Config.version) + local displayedVersion = DevSettings:isEnabled() + and Config.codename + or Version.display(Config.version) Logging.trace("Rojo %s initialized", displayedVersion) From e4d3c3b0458b141df5d3cfadcd980ec6f0240ac4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 17:19:44 -0800 Subject: [PATCH 0244/1504] Field name fix, clean up project paths --- server/src/rbx_session.rs | 9 +++++++-- server/src/web.rs | 4 ++-- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 705a6ecd..3fc2fd4b 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -198,7 +198,7 @@ fn construct_initial_tree( construct_project_node( &mut context, None, - &project.name, + "", &project.name, &project.tree, ); @@ -258,7 +258,12 @@ fn construct_instance_node( let id = insert_or_create_tree(context, parent_instance_id, instance); for (child_name, child_project_node) in &project_node.children { - let child_path = format!("{}/{}", instance_path, child_name); + let child_path = if instance_path.is_empty() { + child_name.clone() + } else { + format!("{}/{}", instance_path, child_name) + }; + construct_project_node(context, Some(id), &child_path, child_name, child_project_node); } diff --git a/server/src/web.rs b/server/src/web.rs index bae32228..c367dabd 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -27,7 +27,7 @@ pub struct ServerInfoResponse<'a> { pub protocol_version: u64, pub root_instance_id: RbxId, pub project: Cow<'a, Project>, - pub project_paths_to_ids: Cow<'a, HashMap>, + pub ids_to_project_paths: Cow<'a, HashMap>, } #[derive(Debug, Serialize, Deserialize)] @@ -80,7 +80,7 @@ impl Server { session_id: self.session.session_id, root_instance_id: tree.get_root_id(), project: Cow::Borrowed(&self.session.project), - project_paths_to_ids: Cow::Borrowed(rbx_session.get_project_path_map()), + ids_to_project_paths: Cow::Borrowed(rbx_session.get_project_path_map()), }) }, From 457f3c8f54d98db7e1e5aacf12a77a8ef6a8ce08 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 17:39:55 -0800 Subject: [PATCH 0245/1504] Break out PathMap from RbxSession --- server/src/lib.rs | 3 +- server/src/path_map.rs | 73 +++++++++++++++++++++++++++++++++ server/src/rbx_session.rs | 86 ++++----------------------------------- 3 files changed, 84 insertions(+), 78 deletions(-) create mode 100644 server/src/path_map.rs diff --git a/server/src/lib.rs b/server/src/lib.rs index 536f781b..4945f343 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -10,11 +10,12 @@ extern crate tempfile; // pub mod roblox_studio; pub mod commands; pub mod fs_watcher; +pub mod imfs; pub mod message_queue; +pub mod path_map; pub mod project; pub mod rbx_session; pub mod session; pub mod session_id; -pub mod imfs; pub mod web; pub mod web_util; \ No newline at end of file diff --git a/server/src/path_map.rs b/server/src/path_map.rs new file mode 100644 index 00000000..ef60c6c7 --- /dev/null +++ b/server/src/path_map.rs @@ -0,0 +1,73 @@ +use std::{ + path::{Path, PathBuf}, + collections::{HashMap, HashSet}, +}; + +#[derive(Debug)] +struct PathMapNode { + value: T, + children: HashSet, +} + +/// A map from paths to instance IDs, with a bit of additional data that enables +/// removing a path and all of its child paths from the tree in constant time. +#[derive(Debug)] +pub struct PathMap { + nodes: HashMap>, +} + +impl PathMap { + pub fn new() -> PathMap { + PathMap { + nodes: HashMap::new(), + } + } + + pub fn get(&self, path: &Path) -> Option<&T> { + self.nodes.get(path).map(|v| &v.value) + } + + pub fn insert(&mut self, path: PathBuf, value: T) { + if let Some(parent_path) = path.parent() { + if let Some(parent) = self.nodes.get_mut(parent_path) { + parent.children.insert(path.to_path_buf()); + } + } + + self.nodes.insert(path, PathMapNode { + value, + children: HashSet::new(), + }); + } + + pub fn remove(&mut self, root_path: &Path) -> Option { + if let Some(parent_path) = root_path.parent() { + if let Some(parent) = self.nodes.get_mut(parent_path) { + parent.children.remove(root_path); + } + } + + let mut root_node = match self.nodes.remove(root_path) { + Some(node) => node, + None => return None, + }; + + let root_value = root_node.value; + let mut to_visit: Vec = root_node.children.drain().collect(); + + while let Some(path) = to_visit.pop() { + match self.nodes.remove(&path) { + Some(mut node) => { + for child in node.children.drain() { + to_visit.push(child); + } + }, + None => { + warn!("Consistency issue; tried to remove {} but it was already removed", path.display()); + }, + } + } + + Some(root_value) + } +} \ No newline at end of file diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 3fc2fd4b..13925d48 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -1,6 +1,6 @@ use std::{ - collections::{HashMap, HashSet}, - path::{Path, PathBuf}, + collections::HashMap, + path::Path, sync::{Arc, Mutex}, str, }; @@ -11,80 +11,12 @@ use crate::{ project::{Project, ProjectNode, InstanceProjectNode}, message_queue::{Message, MessageQueue}, imfs::{Imfs, ImfsItem, ImfsFile}, + path_map::PathMap, }; -#[derive(Debug)] -struct PathIdNode { - id: RbxId, - children: HashSet, -} - -/// A map from paths to instance IDs, with a bit of additional data that enables -/// removing a path and all of its child paths from the tree in constant time. -#[derive(Debug)] -struct PathIdTree { - nodes: HashMap, -} - -impl PathIdTree { - pub fn new() -> PathIdTree { - PathIdTree { - nodes: HashMap::new(), - } - } - - pub fn get_id(&self, path: &Path) -> Option { - self.nodes.get(path).map(|v| v.id) - } - - pub fn insert(&mut self, path: &Path, id: RbxId) { - if let Some(parent_path) = path.parent() { - if let Some(parent) = self.nodes.get_mut(parent_path) { - parent.children.insert(path.to_path_buf()); - } - } - - self.nodes.insert(path.to_path_buf(), PathIdNode { - id, - children: HashSet::new(), - }); - } - - pub fn remove(&mut self, root_path: &Path) -> Option { - if let Some(parent_path) = root_path.parent() { - if let Some(parent) = self.nodes.get_mut(parent_path) { - parent.children.remove(root_path); - } - } - - let mut root_node = match self.nodes.remove(root_path) { - Some(node) => node, - None => return None, - }; - - let root_id = root_node.id; - let mut to_visit: Vec = root_node.children.drain().collect(); - - while let Some(path) = to_visit.pop() { - match self.nodes.remove(&path) { - Some(mut node) => { - for child in node.children.drain() { - to_visit.push(child); - } - }, - None => { - warn!("Consistency issue; tried to remove {} but it was already removed", path.display()); - }, - } - } - - Some(root_id) - } -} - pub struct RbxSession { tree: RbxTree, - path_id_tree: PathIdTree, + path_id_tree: PathMap, ids_to_project_paths: HashMap, message_queue: Arc, imfs: Arc>, @@ -177,15 +109,15 @@ pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { struct ConstructContext<'a> { tree: Option, imfs: &'a Imfs, - path_id_tree: PathIdTree, + path_id_tree: PathMap, ids_to_project_paths: HashMap, } fn construct_initial_tree( project: &Project, imfs: &Imfs, -) -> (RbxTree, PathIdTree, HashMap) { - let path_id_tree = PathIdTree::new(); +) -> (RbxTree, PathMap, HashMap) { + let path_id_tree = PathMap::new(); let ids_to_project_paths = HashMap::new(); let mut context = ConstructContext { @@ -320,7 +252,7 @@ fn construct_sync_point_node( let id = insert_or_create_tree(context, parent_instance_id, instance); - context.path_id_tree.insert(&file.path, id); + context.path_id_tree.insert(file.path.clone(), id); id }, @@ -337,7 +269,7 @@ fn construct_sync_point_node( }; let id = insert_or_create_tree(context, parent_instance_id, instance); - context.path_id_tree.insert(&directory.path, id); + context.path_id_tree.insert(directory.path.clone(), id); id }; From fc3f750efbe5b34ece7c079784f503591e7d8f99 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 3 Dec 2018 18:09:01 -0800 Subject: [PATCH 0246/1504] Tweak logic in RbxSession to distinguish create and update --- server/src/message_queue.rs | 3 +++ server/src/rbx_session.rs | 32 +++++++++++++++++++++----------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/server/src/message_queue.rs b/server/src/message_queue.rs index 7c8280f6..94203b90 100644 --- a/server/src/message_queue.rs +++ b/server/src/message_queue.rs @@ -27,6 +27,9 @@ pub enum Message { InstancesRemoved { ids: Vec, }, + InstancesUpdated { + ids: Vec, + }, } #[derive(Default)] diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 13925d48..00f32ac6 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -40,26 +40,36 @@ impl RbxSession { } } + fn path_created_or_updated(&mut self, path: &Path) { + if let Some(instance_id) = self.path_id_tree.get(path) { + // TODO: Replace instance with ID `instance_id` with new instance + } + + // TODO: Crawl up path to find first node represented in the tree or a + // sync point root. That path immediately before we find an existing + // node should be read into the tree. + } + pub fn path_created(&mut self, path: &Path) { info!("Path created: {}", path.display()); - self.path_updated(path); + self.path_created_or_updated(path); } pub fn path_updated(&mut self, path: &Path) { info!("Path updated: {}", path.display()); - let imfs = self.imfs.lock().unwrap(); + { + let imfs = self.imfs.lock().unwrap(); - // If the path doesn't exist or it's a directory, we don't care if it - // updated - let file = match imfs.get(path) { - Some(ImfsItem::Directory(_)) | None => return, - Some(ImfsItem::File(file)) => file, - }; + // If the path doesn't exist or it's a directory, we don't care if it + // updated + match imfs.get(path) { + Some(ImfsItem::Directory(_)) | None => return, + Some(ImfsItem::File(_)) => {}, + } + } - // TODO: Crawl up path to find first node represented in the tree or a - // sync point root. That path immediately before we find an existing - // node should be read into the tree. + self.path_created_or_updated(path); } pub fn path_removed(&mut self, path: &Path) { From dbd499701f4450d5a2e7d42ce9272ddd5d3e8092 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 11 Dec 2018 18:23:20 -0800 Subject: [PATCH 0247/1504] Snapshot tinkering, this is an idea --- server/src/lib.rs | 1 + server/src/rbx_snapshot.rs | 60 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 server/src/rbx_snapshot.rs diff --git a/server/src/lib.rs b/server/src/lib.rs index 4945f343..fd3d600b 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -15,6 +15,7 @@ pub mod message_queue; pub mod path_map; pub mod project; pub mod rbx_session; +pub mod rbx_snapshot; pub mod session; pub mod session_id; pub mod web; diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs new file mode 100644 index 00000000..0f11f1ca --- /dev/null +++ b/server/src/rbx_snapshot.rs @@ -0,0 +1,60 @@ +use std::{ + str, + borrow::Cow, + collections::HashMap, +}; + +use rbx_tree::{RbxTree, RbxId}; + +use crate::{ + imfs::{Imfs, ImfsItem, ImfsFile, ImfsDirectory}, +}; + +pub struct RbxSnapshotInstance<'a> { + name: String, + class_name: String, + properties: HashMap>, + children: Vec>, +} + +pub enum RbxSnapshotValue<'a> { + String(Cow<'a, str>), +} + +pub fn reify(snapshot: RbxSnapshotInstance, tree: &mut RbxTree, parent_id: RbxId) { + unimplemented!() +} + +pub fn render<'a>(imfs: &'a Imfs, imfs_item: &'a ImfsItem) -> RbxSnapshotInstance<'a> { + match imfs_item { + ImfsItem::File(file) => { + let name = file.path.file_stem().unwrap().to_str().unwrap(); + let source = str::from_utf8(&file.contents).unwrap(); + let mut properties = HashMap::new(); + properties.insert("Source".to_string(), RbxSnapshotValue::String(Cow::Borrowed(source))); + + RbxSnapshotInstance { + name: name.to_string(), + class_name: "ModuleScript".to_string(), + properties, + children: Vec::new(), + } + }, + ImfsItem::Directory(directory) => { + let name = directory.path.file_name().unwrap().to_str().unwrap(); + let mut children = Vec::new(); + + for child_path in &directory.children { + let child_item = imfs.get(child_path).unwrap(); + children.push(render(imfs, child_item)); + } + + RbxSnapshotInstance { + name: name.to_string(), + class_name: "Folder".to_string(), + properties: HashMap::new(), + children, + } + }, + } +} \ No newline at end of file From ee0a5cada3e8c0b8b8d41988a94e8cc1e5849602 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 11 Dec 2018 23:30:53 -0800 Subject: [PATCH 0248/1504] Snapshot madness --- server/src/rbx_session.rs | 128 +++++++++++++++---------------------- server/src/rbx_snapshot.rs | 83 +++++++++++++----------- 2 files changed, 95 insertions(+), 116 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 00f32ac6..e0dd90e8 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -1,17 +1,19 @@ use std::{ + borrow::Cow, collections::HashMap, path::Path, sync::{Arc, Mutex}, str, }; -use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; +use rbx_tree::{RbxTree, RbxId}; use crate::{ project::{Project, ProjectNode, InstanceProjectNode}, message_queue::{Message, MessageQueue}, imfs::{Imfs, ImfsItem, ImfsFile}, path_map::PathMap, + rbx_snapshot::{RbxSnapshotInstance, RbxSnapshotValue, reify_root}, }; pub struct RbxSession { @@ -25,11 +27,15 @@ pub struct RbxSession { impl RbxSession { pub fn new(project: Arc, imfs: Arc>, message_queue: Arc) -> RbxSession { - let (tree, path_id_tree, ids_to_project_paths) = { + let tree = { let temp_imfs = imfs.lock().unwrap(); construct_initial_tree(&project, &temp_imfs) }; + // TODO: Restore these? + let path_id_tree = PathMap::new(); + let ids_to_project_paths = HashMap::new(); + RbxSession { tree, path_id_tree, @@ -113,11 +119,10 @@ impl RbxSession { } pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { - construct_initial_tree(project, imfs).0 + construct_initial_tree(project, imfs) } struct ConstructContext<'a> { - tree: Option, imfs: &'a Imfs, path_id_tree: PathMap, ids_to_project_paths: HashMap, @@ -126,78 +131,49 @@ struct ConstructContext<'a> { fn construct_initial_tree( project: &Project, imfs: &Imfs, -) -> (RbxTree, PathMap, HashMap) { +) -> RbxTree { let path_id_tree = PathMap::new(); let ids_to_project_paths = HashMap::new(); let mut context = ConstructContext { - tree: None, imfs, path_id_tree, ids_to_project_paths, }; - construct_project_node( + let snapshot = construct_project_node( &mut context, - None, "", &project.name, &project.tree, ); - let tree = context.tree.unwrap(); - - (tree, context.path_id_tree, context.ids_to_project_paths) + reify_root(&snapshot) } -fn insert_or_create_tree(context: &mut ConstructContext, parent_instance_id: Option, instance: RbxInstance) -> RbxId { - match (&mut context.tree, parent_instance_id) { - (Some(tree), Some(parent_instance_id)) => { - tree.insert_instance(instance, parent_instance_id) - }, - _ => { - let new_tree = RbxTree::new(instance); - let root_id = new_tree.get_root_id(); - - context.tree = Some(new_tree); - root_id - }, - } -} - -fn construct_project_node( - context: &mut ConstructContext, - parent_instance_id: Option, +fn construct_project_node<'a>( + context: &mut ConstructContext<'a>, instance_path: &str, - instance_name: &str, - project_node: &ProjectNode, -) { + instance_name: &'a str, + project_node: &'a ProjectNode, +) -> RbxSnapshotInstance<'a> { match project_node { ProjectNode::Instance(node) => { - let id = construct_instance_node(context, parent_instance_id, &instance_path, instance_name, node); - context.ids_to_project_paths.insert(id, instance_path.to_string()); + construct_instance_node(context, &instance_path, instance_name, node) }, ProjectNode::SyncPoint(node) => { - let id = construct_sync_point_node(context, parent_instance_id, instance_name, &node.path); - context.ids_to_project_paths.insert(id, instance_path.to_string()); + construct_sync_point_node(context, instance_name, &node.path) }, } } -fn construct_instance_node( - context: &mut ConstructContext, - parent_instance_id: Option, +fn construct_instance_node<'a>( + context: &mut ConstructContext<'a>, instance_path: &str, - instance_name: &str, - project_node: &InstanceProjectNode, -) -> RbxId { - let instance = RbxInstance { - class_name: project_node.class_name.clone(), - name: instance_name.to_string(), - properties: HashMap::new(), - }; - - let id = insert_or_create_tree(context, parent_instance_id, instance); + instance_name: &'a str, + project_node: &'a InstanceProjectNode, +) -> RbxSnapshotInstance<'a> { + let mut children = Vec::new(); for (child_name, child_project_node) in &project_node.children { let child_path = if instance_path.is_empty() { @@ -206,10 +182,15 @@ fn construct_instance_node( format!("{}/{}", instance_path, child_name) }; - construct_project_node(context, Some(id), &child_path, child_name, child_project_node); + children.push(construct_project_node(context, &child_path, child_name, child_project_node)); } - id + RbxSnapshotInstance { + class_name: Cow::Borrowed(&project_node.class_name), + name: Cow::Borrowed(instance_name), + properties: HashMap::new(), + children, + } } #[derive(Debug, Clone, Copy)] @@ -233,12 +214,11 @@ fn classify_file(file: &ImfsFile) -> Option { } } -fn construct_sync_point_node( - context: &mut ConstructContext, - parent_instance_id: Option, - instance_name: &str, +fn construct_sync_point_node<'a>( + context: &mut ConstructContext<'a>, + instance_name: &'a str, file_path: &Path, -) -> RbxId { +) -> RbxSnapshotInstance<'a> { match context.imfs.get(&file_path) { Some(ImfsItem::File(file)) => { let file_type = classify_file(file).unwrap(); // TODO: Don't die here! @@ -252,35 +232,29 @@ fn construct_sync_point_node( let contents = str::from_utf8(&file.contents).unwrap(); let mut properties = HashMap::new(); - properties.insert("Source".to_string(), RbxValue::String { value: contents.to_string() }); + properties.insert("Source".to_string(), RbxSnapshotValue::String(Cow::Borrowed(contents))); - let instance = RbxInstance { - class_name: class_name.to_string(), - name: instance_name.to_string(), + let instance = RbxSnapshotInstance { + class_name: Cow::Borrowed(class_name), + name: Cow::Borrowed(instance_name), properties, + children: Vec::new(), }; - let id = insert_or_create_tree(context, parent_instance_id, instance); - - context.path_id_tree.insert(file.path.clone(), id); - - id + instance }, Some(ImfsItem::Directory(directory)) => { let init_path = directory.path.join("init.lua"); - let id = if directory.children.contains(&init_path) { - construct_sync_point_node(context, parent_instance_id, instance_name, &init_path) + let mut instance = if directory.children.contains(&init_path) { + construct_sync_point_node(context, instance_name, &init_path) } else { - let instance = RbxInstance { - class_name: "Folder".to_string(), - name: instance_name.to_string(), + RbxSnapshotInstance { + class_name: Cow::Borrowed("Folder"), + name: Cow::Borrowed(instance_name), properties: HashMap::new(), - }; - - let id = insert_or_create_tree(context, parent_instance_id, instance); - context.path_id_tree.insert(directory.path.clone(), id); - id + children: Vec::new(), + } }; for child_path in &directory.children { @@ -290,11 +264,11 @@ fn construct_sync_point_node( ImfsItem::Directory(_) => child_path.file_name().unwrap().to_str().unwrap(), }; - construct_sync_point_node(context, Some(id), child_instance_name, child_path); + instance.children.push(construct_sync_point_node(context, child_instance_name, child_path)); } } - id + instance }, None => panic!("Couldn't read {} from disk", file_path.display()), } diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 0f11f1ca..376a6daf 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -4,57 +4,62 @@ use std::{ collections::HashMap, }; -use rbx_tree::{RbxTree, RbxId}; - -use crate::{ - imfs::{Imfs, ImfsItem, ImfsFile, ImfsDirectory}, -}; +use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; pub struct RbxSnapshotInstance<'a> { - name: String, - class_name: String, - properties: HashMap>, - children: Vec>, + pub name: Cow<'a, str>, + pub class_name: Cow<'a, str>, + pub properties: HashMap>, + pub children: Vec>, } pub enum RbxSnapshotValue<'a> { String(Cow<'a, str>), } -pub fn reify(snapshot: RbxSnapshotInstance, tree: &mut RbxTree, parent_id: RbxId) { - unimplemented!() +impl<'a> RbxSnapshotValue<'a> { + pub fn to_rbx_value(&self) -> RbxValue { + match self { + RbxSnapshotValue::String(value) => RbxValue::String { + value: value.to_string(), + }, + } + } } -pub fn render<'a>(imfs: &'a Imfs, imfs_item: &'a ImfsItem) -> RbxSnapshotInstance<'a> { - match imfs_item { - ImfsItem::File(file) => { - let name = file.path.file_stem().unwrap().to_str().unwrap(); - let source = str::from_utf8(&file.contents).unwrap(); - let mut properties = HashMap::new(); - properties.insert("Source".to_string(), RbxSnapshotValue::String(Cow::Borrowed(source))); +fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstance { + let mut properties = HashMap::new(); - RbxSnapshotInstance { - name: name.to_string(), - class_name: "ModuleScript".to_string(), - properties, - children: Vec::new(), - } - }, - ImfsItem::Directory(directory) => { - let name = directory.path.file_name().unwrap().to_str().unwrap(); - let mut children = Vec::new(); + for (key, value) in &snapshot.properties { + properties.insert(key.clone(), value.to_rbx_value()); + } - for child_path in &directory.children { - let child_item = imfs.get(child_path).unwrap(); - children.push(render(imfs, child_item)); - } + let instance = RbxInstance { + name: snapshot.name.to_string(), + class_name: snapshot.class_name.to_string(), + properties, + }; - RbxSnapshotInstance { - name: name.to_string(), - class_name: "Folder".to_string(), - properties: HashMap::new(), - children, - } - }, + instance +} + +pub fn reify_root(snapshot: &RbxSnapshotInstance) -> RbxTree { + let instance = reify_core(snapshot); + let mut tree = RbxTree::new(instance); + let root_id = tree.get_root_id(); + + for child in &snapshot.children { + reify_child(child, &mut tree, root_id); + } + + tree +} + +fn reify_child(snapshot: &RbxSnapshotInstance, tree: &mut RbxTree, parent_id: RbxId) { + let instance = reify_core(snapshot); + let id = tree.insert_instance(instance, parent_id); + + for child in &snapshot.children { + reify_child(child, tree, id); } } \ No newline at end of file From b732c432748b9166f6b5aa9ee1f883941bc60a3d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 12 Dec 2018 13:56:11 -0800 Subject: [PATCH 0249/1504] Trimming of stuff to get into the snapshotting mood --- server/src/imfs.rs | 6 +- server/src/path_map.rs | 2 +- server/src/rbx_session.rs | 110 +++++++++++++++---------------------- server/src/rbx_snapshot.rs | 2 + 4 files changed, 52 insertions(+), 68 deletions(-) diff --git a/server/src/imfs.rs b/server/src/imfs.rs index 40d81d6f..be9d544c 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -76,9 +76,10 @@ impl Imfs { if self.is_within_roots(parent_path) && self.get(parent_path).is_none() { self.path_created(parent_path)?; } + } else { + ImfsItem::read_from_disk(self, path)?; } - ImfsItem::read_from_disk(self, path)?; Ok(()) } @@ -90,9 +91,10 @@ impl Imfs { if self.is_within_roots(parent_path) && self.get(parent_path).is_none() { self.path_created(parent_path)?; } + } else { + ImfsItem::read_from_disk(self, path)?; } - ImfsItem::read_from_disk(self, path)?; Ok(()) } diff --git a/server/src/path_map.rs b/server/src/path_map.rs index ef60c6c7..f1907b30 100644 --- a/server/src/path_map.rs +++ b/server/src/path_map.rs @@ -10,7 +10,7 @@ struct PathMapNode { } /// A map from paths to instance IDs, with a bit of additional data that enables -/// removing a path and all of its child paths from the tree in constant time. +/// removing a path and all of its child paths from the tree more quickly. #[derive(Debug)] pub struct PathMap { nodes: HashMap>, diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index e0dd90e8..a6028cb6 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -122,28 +122,12 @@ pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { construct_initial_tree(project, imfs) } -struct ConstructContext<'a> { - imfs: &'a Imfs, - path_id_tree: PathMap, - ids_to_project_paths: HashMap, -} - fn construct_initial_tree( project: &Project, imfs: &Imfs, ) -> RbxTree { - let path_id_tree = PathMap::new(); - let ids_to_project_paths = HashMap::new(); - - let mut context = ConstructContext { - imfs, - path_id_tree, - ids_to_project_paths, - }; - let snapshot = construct_project_node( - &mut context, - "", + imfs, &project.name, &project.tree, ); @@ -152,37 +136,30 @@ fn construct_initial_tree( } fn construct_project_node<'a>( - context: &mut ConstructContext<'a>, - instance_path: &str, + imfs: &'a Imfs, instance_name: &'a str, project_node: &'a ProjectNode, ) -> RbxSnapshotInstance<'a> { match project_node { ProjectNode::Instance(node) => { - construct_instance_node(context, &instance_path, instance_name, node) + construct_instance_node(imfs, instance_name, node) }, ProjectNode::SyncPoint(node) => { - construct_sync_point_node(context, instance_name, &node.path) + snapshot_instances_from_imfs(imfs, &node.path) + .expect("Could not reify nodes from Imfs") }, } } fn construct_instance_node<'a>( - context: &mut ConstructContext<'a>, - instance_path: &str, + imfs: &'a Imfs, instance_name: &'a str, project_node: &'a InstanceProjectNode, ) -> RbxSnapshotInstance<'a> { let mut children = Vec::new(); for (child_name, child_project_node) in &project_node.children { - let child_path = if instance_path.is_empty() { - child_name.clone() - } else { - format!("{}/{}", instance_path, child_name) - }; - - children.push(construct_project_node(context, &child_path, child_name, child_project_node)); + children.push(construct_project_node(imfs, child_name, child_project_node)); } RbxSnapshotInstance { @@ -190,6 +167,7 @@ fn construct_instance_node<'a>( name: Cow::Borrowed(instance_name), properties: HashMap::new(), children, + update_trigger_paths: Vec::new(), } } @@ -200,28 +178,33 @@ enum FileType { ClientScript, } -fn classify_file(file: &ImfsFile) -> Option { - let file_name = file.path.file_name()?.to_str()?; - - if file_name.ends_with(".server.lua") { - Some(FileType::ServerScript) - } else if file_name.ends_with(".client.lua") { - Some(FileType::ClientScript) - } else if file_name.ends_with(".lua") { - Some(FileType::ModuleScript) +fn get_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { + if input.ends_with(trailer) { + let end = input.len().saturating_sub(trailer.len()); + Some(&input[..end]) } else { None } } -fn construct_sync_point_node<'a>( - context: &mut ConstructContext<'a>, - instance_name: &'a str, - file_path: &Path, -) -> RbxSnapshotInstance<'a> { - match context.imfs.get(&file_path) { - Some(ImfsItem::File(file)) => { - let file_type = classify_file(file).unwrap(); // TODO: Don't die here! +fn classify_file(file: &ImfsFile) -> Option<(&str, FileType)> { + let file_name = file.path.file_name()?.to_str()?; + + if let Some(instance_name) = get_trailing(file_name, ".server.lua") { + Some((instance_name, FileType::ServerScript)) + } else if let Some(instance_name) = get_trailing(file_name, ".client.lua") { + Some((instance_name, FileType::ClientScript)) + } else if let Some(instance_name) = get_trailing(file_name, ".lua") { + Some((instance_name, FileType::ModuleScript)) + } else { + None + } +} + +fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option> { + match imfs.get(imfs_path)? { + ImfsItem::File(file) => { + let (instance_name, file_type) = classify_file(file)?; let class_name = match file_type { FileType::ModuleScript => "ModuleScript", @@ -229,47 +212,44 @@ fn construct_sync_point_node<'a>( FileType::ClientScript => "LocalScript", }; - let contents = str::from_utf8(&file.contents).unwrap(); + let contents = str::from_utf8(&file.contents) + .expect("File did not contain UTF-8 data, which is required for scripts."); let mut properties = HashMap::new(); - properties.insert("Source".to_string(), RbxSnapshotValue::String(Cow::Borrowed(contents))); + properties.insert(String::from("Source"), RbxSnapshotValue::String(Cow::Borrowed(contents))); - let instance = RbxSnapshotInstance { - class_name: Cow::Borrowed(class_name), + Some(RbxSnapshotInstance { name: Cow::Borrowed(instance_name), + class_name: Cow::Borrowed(class_name), properties, children: Vec::new(), - }; - - instance + update_trigger_paths: vec![file.path.clone()], + }) }, - Some(ImfsItem::Directory(directory)) => { + ImfsItem::Directory(directory) => { let init_path = directory.path.join("init.lua"); let mut instance = if directory.children.contains(&init_path) { - construct_sync_point_node(context, instance_name, &init_path) + snapshot_instances_from_imfs(imfs, &init_path)? } else { RbxSnapshotInstance { class_name: Cow::Borrowed("Folder"), - name: Cow::Borrowed(instance_name), + name: Cow::Borrowed(""), // Assigned later in the method properties: HashMap::new(), children: Vec::new(), + update_trigger_paths: vec![directory.path.clone()], } }; + instance.name = Cow::Borrowed(directory.path.file_name()?.to_str()?); + for child_path in &directory.children { if child_path != &init_path { - let child_instance_name = match context.imfs.get(child_path).unwrap() { - ImfsItem::File(_) => child_path.file_stem().unwrap().to_str().unwrap(), - ImfsItem::Directory(_) => child_path.file_name().unwrap().to_str().unwrap(), - }; - - instance.children.push(construct_sync_point_node(context, child_instance_name, child_path)); + instance.children.push(snapshot_instances_from_imfs(imfs, child_path)?); } } - instance + Some(instance) }, - None => panic!("Couldn't read {} from disk", file_path.display()), } } \ No newline at end of file diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 376a6daf..05654cad 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -2,6 +2,7 @@ use std::{ str, borrow::Cow, collections::HashMap, + path::PathBuf, }; use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; @@ -11,6 +12,7 @@ pub struct RbxSnapshotInstance<'a> { pub class_name: Cow<'a, str>, pub properties: HashMap>, pub children: Vec>, + pub update_trigger_paths: Vec, } pub enum RbxSnapshotValue<'a> { From 52f01da40069c05fab92cebf8ad58a1ca762c319 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 12 Dec 2018 23:11:59 -0800 Subject: [PATCH 0250/1504] Flesh out reconciler routine --- server/src/rbx_session.rs | 10 +++--- server/src/rbx_snapshot.rs | 69 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index a6028cb6..c697ee7f 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -18,7 +18,7 @@ use crate::{ pub struct RbxSession { tree: RbxTree, - path_id_tree: PathMap, + paths_to_node_ids: PathMap, ids_to_project_paths: HashMap, message_queue: Arc, imfs: Arc>, @@ -33,12 +33,12 @@ impl RbxSession { }; // TODO: Restore these? - let path_id_tree = PathMap::new(); + let paths_to_node_ids = PathMap::new(); let ids_to_project_paths = HashMap::new(); RbxSession { tree, - path_id_tree, + paths_to_node_ids, ids_to_project_paths, message_queue, imfs, @@ -47,7 +47,7 @@ impl RbxSession { } fn path_created_or_updated(&mut self, path: &Path) { - if let Some(instance_id) = self.path_id_tree.get(path) { + if let Some(instance_id) = self.paths_to_node_ids.get(path) { // TODO: Replace instance with ID `instance_id` with new instance } @@ -81,7 +81,7 @@ impl RbxSession { pub fn path_removed(&mut self, path: &Path) { info!("Path removed: {}", path.display()); - let instance_id = match self.path_id_tree.remove(path) { + let instance_id = match self.paths_to_node_ids.remove(path) { Some(id) => id, None => return, }; diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 05654cad..28fb0137 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -64,4 +64,73 @@ fn reify_child(snapshot: &RbxSnapshotInstance, tree: &mut RbxTree, parent_id: Rb for child in &snapshot.children { reify_child(child, tree, id); } +} + +fn reconcile_instance_properties(instance: &mut RbxInstance, snapshot: &RbxSnapshotInstance) -> bool { + let mut has_diffs = false; + + if instance.name != snapshot.name { + instance.name = snapshot.name.to_string(); + has_diffs = true; + } + + if instance.class_name != snapshot.class_name { + instance.class_name = snapshot.class_name.to_string(); + has_diffs = true; + } + + let mut property_updates = HashMap::new(); + + for (key, instance_value) in &instance.properties { + match snapshot.properties.get(key) { + Some(snapshot_value) => { + if &snapshot_value.to_rbx_value() != instance_value { + property_updates.insert(key.clone(), Some(snapshot_value.clone())); + } + }, + None => { + property_updates.insert(key.clone(), None); + }, + } + } + + for (key, snapshot_value) in &snapshot.properties { + if property_updates.contains_key(key) { + continue; + } + + match instance.properties.get(key) { + Some(instance_value) => { + if &snapshot_value.to_rbx_value() != instance_value { + property_updates.insert(key.clone(), Some(snapshot_value.clone())); + } + }, + None => { + property_updates.insert(key.clone(), Some(snapshot_value.clone())); + }, + } + } + + has_diffs = has_diffs || !property_updates.is_empty(); + + for (key, change) in property_updates.drain() { + match change { + Some(value) => instance.properties.insert(key, value.to_rbx_value()), + None => instance.properties.remove(&key), + }; + } + + has_diffs +} + +fn reconcile_instance_children(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance, changed_ids: &mut Vec) { + // TODO: enumerate and match up children, update props, construct and delete IDs +} + +pub fn reconcile_subtree(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance, changed_ids: &mut Vec) { + if reconcile_instance_properties(tree.get_instance_mut().unwrap(), snapshot) { + changed_ids.push(id); + } + + reconcile_instance_children(tree, id, snapshot, changed_ids); } \ No newline at end of file From a89fff1a22bfa93653fae89de2f2f3ad671bde5b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 12 Dec 2018 23:37:06 -0800 Subject: [PATCH 0251/1504] Add missing pieces of commit --- server/Cargo.lock | 214 ++++++++++++++++++------------------- server/src/rbx_snapshot.rs | 45 ++++++-- 2 files changed, 143 insertions(+), 116 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index a7f3223d..a42d6486 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -8,7 +8,7 @@ name = "aho-corasick" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -29,19 +29,19 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace" -version = "0.3.9" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -51,8 +51,8 @@ name = "backtrace-sys" version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -69,11 +69,6 @@ name = "bitflags" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "bitflags" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "1.0.4" @@ -84,8 +79,8 @@ name = "brotli-sys" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -94,7 +89,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -113,7 +108,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytecount" -version = "0.3.2" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -132,19 +127,19 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.5.8" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.25" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -199,7 +194,7 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -280,16 +275,16 @@ dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "error-chain" -version = "0.11.0" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -297,7 +292,7 @@ name = "failure" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -318,8 +313,8 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -329,7 +324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -337,7 +332,7 @@ name = "fsevent-sys" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -403,7 +398,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -414,7 +409,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -422,7 +417,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -447,12 +442,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lazycell" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.44" +version = "0.2.45" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -485,9 +480,9 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", - "skeptic 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)", + "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -495,8 +490,8 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -509,16 +504,16 @@ name = "memchr" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memchr" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -550,8 +545,8 @@ dependencies = [ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -564,7 +559,7 @@ name = "mio-extras" version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -603,7 +598,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -618,7 +613,7 @@ dependencies = [ "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -640,10 +635,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "num_cpus" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -668,7 +663,7 @@ name = "parking_lot_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -725,10 +720,10 @@ dependencies = [ [[package]] name = "pulldown-cmark" -version = "0.1.2" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -750,7 +745,7 @@ version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -760,7 +755,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -771,7 +766,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -783,7 +778,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -852,7 +847,7 @@ dependencies = [ [[package]] name = "rbx_binary" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#b5972918fae985f9570811ab05993d268aba03cc" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#1719d35df9b08637c2938d4418e834e48f39f624" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -862,17 +857,17 @@ dependencies = [ [[package]] name = "rbx_tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#b5972918fae985f9570811ab05993d268aba03cc" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#1719d35df9b08637c2938d4418e834e48f39f624" dependencies = [ - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_xml" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#b5972918fae985f9570811ab05993d268aba03cc" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#1719d35df9b08637c2938d4418e834e48f39f624" dependencies = [ "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -880,7 +875,7 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -888,24 +883,24 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.0.6" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -933,10 +928,10 @@ dependencies = [ "rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", - "regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -954,10 +949,10 @@ dependencies = [ "deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1014,7 +1009,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1024,12 +1019,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.80" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.80" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1044,7 +1039,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1059,14 +1054,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "skeptic" -version = "0.13.3" +version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1131,9 +1126,9 @@ version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1160,8 +1155,8 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1186,7 +1181,7 @@ name = "threadpool" version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1194,8 +1189,8 @@ name = "time" version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1235,12 +1230,12 @@ name = "tokio-reactor" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1252,7 +1247,7 @@ name = "twoway" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1320,7 +1315,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1414,28 +1409,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum backtrace 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "89a47830402e9981c5c41223151efcced65a0510c13097c769cede7efb34782a" +"checksum backtrace 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eff3830839471718ef8522b9025b399bfb713e25bc220da721364efb660d7d" "checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" -"checksum bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4efd02e230a02e18f92fc2735f44597385ed02ad8f831e7c1c1156ee5e1ab3a5" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" "checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" "checksum buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9279646319ff816b05fb5897883ece50d7d854d12b59992683d4f8a71b0f949" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" -"checksum bytecount 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f861d9ce359f56dbcb6e0c2a1cb84e52ad732cadb57b806adeb3c7668caccbd8" +"checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum cargo_metadata 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1efca0b863ca03ed4c109fb1c55e0bc4bbeb221d3e103d86251046b06a526bd0" -"checksum cc 1.0.25 (registry+https://github.com/rust-lang/crates.io-index)" = "f159dfd43363c4d08055a07703eb7a3406b0dac4d0584d96965a3262db3c9d16" +"checksum cargo_metadata 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "48e8d5fd5b81d86d3ec3c820ecf5a3027fa22d6aede2be981cf07a8ce16451bb" +"checksum cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "389803e36973d242e7fecb092b2de44a3d35ac62524b3b9339e51d577d668e02" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -"checksum crossbeam-utils 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c55913cc2799171a550e307918c0a360e8c16004820291bf3b638969b4a01816" +"checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a" "checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86" "checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" "checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" @@ -1445,7 +1439,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" -"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" "checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" "checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" @@ -1465,8 +1459,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" -"checksum lazycell 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ddba4c30a78328befecec92fc94970e53b3ae385827d28620f0f5bb2493081e0" -"checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" +"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" +"checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" @@ -1474,7 +1468,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" -"checksum memchr 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0a3eb002f0535929f1199681417029ebea04aadc0c7a4224b46be99c7f5d6a16" +"checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2d4c0961143b8efdcfa29c3ae63281601b446a4a668165454b6c90f8024954c5" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" @@ -1485,7 +1479,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "873ecfd8c174964ae30f401329d140142312c8e5590719cf1199d5f1717d8078" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" -"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" "checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" @@ -1495,7 +1489,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_generator 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "03dc191feb9b08b0dc1330d6549b795b9d81aec19efe6b4a45aec8d4caee0c4b" "checksum phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "b539898d22d4273ded07f64a05737649dc69095d92cb87c7097ec68e3f150b93" "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" -"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32" +"checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" @@ -1512,10 +1506,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" -"checksum redox_syscall 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "679da7508e9a6390aeaf7fbd02a800fdc64b73fe2204dd2c8ae66d22d9d5ad5d" +"checksum redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "a84bcd297b87a545980a2d25a0beb72a1f490c31f0a9fde52fca35bfbb1ceb70" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ee84f70c8c08744ea9641a731c7fadb475bf2ecc52d7f627feb833e0b3990467" -"checksum regex-syntax 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "fbc557aac2b708fe84121caf261346cc2eed71978024337e42eb46b8a252ac6e" +"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841" "checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" @@ -1527,12 +1521,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "15c141fc7027dd265a47c090bf864cf62b42c4d228bbcf4e51a0c9e2b0d3f7ef" -"checksum serde_derive 1.0.80 (registry+https://github.com/rust-lang/crates.io-index)" = "225de307c6302bec3898c51ca302fc94a7a1697ef0845fcee6448f33c032249c" +"checksum serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "6fa52f19aee12441d5ad11c9a00459122bd8f98707cadf9778c540674f1935b6" +"checksum serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "96a7f9496ac65a2db5929afa087b54f8fc5008dcfbe48a8874ed20049b0d6154" "checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" -"checksum skeptic 0.13.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c4474d6da9593171bcb086890fc344a3a12783cb24e5b141f8a5d0e43561f4b6" +"checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" "checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 28fb0137..f296442e 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -123,14 +123,47 @@ fn reconcile_instance_properties(instance: &mut RbxInstance, snapshot: &RbxSnaps has_diffs } -fn reconcile_instance_children(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance, changed_ids: &mut Vec) { +fn reconcile_instance_children(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance) { // TODO: enumerate and match up children, update props, construct and delete IDs -} + let children_ids = tree.get_instance(id).unwrap().get_children_ids().to_vec(); + let child_count = children_ids.len().max(snapshot.children.len()); -pub fn reconcile_subtree(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance, changed_ids: &mut Vec) { - if reconcile_instance_properties(tree.get_instance_mut().unwrap(), snapshot) { - changed_ids.push(id); + let mut children_to_add = Vec::new(); + let mut children_to_update = Vec::new(); + let mut children_to_remove = Vec::new(); + + for i in 0..child_count { + let instance_child_foo = children_ids.get(i).map(|&id| tree.get_instance_mut(id).unwrap()); + let snapshot_child_foo = snapshot.children.get(i); + + match (instance_child_foo, snapshot_child_foo) { + (Some(instance_child), Some(snapshot_child)) => { + children_to_update.push((instance_child.get_id(), snapshot_child)); + }, + (Some(instance_child), None) => { + children_to_remove.push(instance_child.get_id()); + }, + (None, Some(snapshot_child)) => { + children_to_add.push(snapshot_child); + }, + (None, None) => unreachable!(), + } } - reconcile_instance_children(tree, id, snapshot, changed_ids); + for child_snapshot in &children_to_add { + reify_child(child_snapshot, tree, id); + } + + for child_id in &children_to_remove { + tree.remove_instance(*child_id); + } + + for (child_id, child_snapshot) in &children_to_update { + reconcile_subtree(tree, *child_id, child_snapshot); + } +} + +pub fn reconcile_subtree(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance) { + reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot); + reconcile_instance_children(tree, id, snapshot); } \ No newline at end of file From 4d0a2b806cd1e306d7a0aa3c3eb7d71d56e8f2f5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 13 Dec 2018 10:53:32 -0800 Subject: [PATCH 0252/1504] Remove RbxSnapshotValue for RbxValue We can always change RbxValue to use Cow<'a, str> instead of String later if perf needs it --- server/src/rbx_session.rs | 8 +++++--- server/src/rbx_snapshot.rs | 24 +++++------------------- 2 files changed, 10 insertions(+), 22 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index c697ee7f..ce93d6d7 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -6,14 +6,14 @@ use std::{ str, }; -use rbx_tree::{RbxTree, RbxId}; +use rbx_tree::{RbxTree, RbxValue, RbxId}; use crate::{ project::{Project, ProjectNode, InstanceProjectNode}, message_queue::{Message, MessageQueue}, imfs::{Imfs, ImfsItem, ImfsFile}, path_map::PathMap, - rbx_snapshot::{RbxSnapshotInstance, RbxSnapshotValue, reify_root}, + rbx_snapshot::{RbxSnapshotInstance, reify_root}, }; pub struct RbxSession { @@ -216,7 +216,9 @@ fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option< .expect("File did not contain UTF-8 data, which is required for scripts."); let mut properties = HashMap::new(); - properties.insert(String::from("Source"), RbxSnapshotValue::String(Cow::Borrowed(contents))); + properties.insert(String::from("Source"), RbxValue::String { + value: contents.to_string(), + }); Some(RbxSnapshotInstance { name: Cow::Borrowed(instance_name), diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index f296442e..37e790a0 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -10,30 +10,16 @@ use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; pub struct RbxSnapshotInstance<'a> { pub name: Cow<'a, str>, pub class_name: Cow<'a, str>, - pub properties: HashMap>, + pub properties: HashMap, pub children: Vec>, pub update_trigger_paths: Vec, } -pub enum RbxSnapshotValue<'a> { - String(Cow<'a, str>), -} - -impl<'a> RbxSnapshotValue<'a> { - pub fn to_rbx_value(&self) -> RbxValue { - match self { - RbxSnapshotValue::String(value) => RbxValue::String { - value: value.to_string(), - }, - } - } -} - fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstance { let mut properties = HashMap::new(); for (key, value) in &snapshot.properties { - properties.insert(key.clone(), value.to_rbx_value()); + properties.insert(key.clone(), value.clone()); } let instance = RbxInstance { @@ -84,7 +70,7 @@ fn reconcile_instance_properties(instance: &mut RbxInstance, snapshot: &RbxSnaps for (key, instance_value) in &instance.properties { match snapshot.properties.get(key) { Some(snapshot_value) => { - if &snapshot_value.to_rbx_value() != instance_value { + if snapshot_value != instance_value { property_updates.insert(key.clone(), Some(snapshot_value.clone())); } }, @@ -101,7 +87,7 @@ fn reconcile_instance_properties(instance: &mut RbxInstance, snapshot: &RbxSnaps match instance.properties.get(key) { Some(instance_value) => { - if &snapshot_value.to_rbx_value() != instance_value { + if snapshot_value != instance_value { property_updates.insert(key.clone(), Some(snapshot_value.clone())); } }, @@ -115,7 +101,7 @@ fn reconcile_instance_properties(instance: &mut RbxInstance, snapshot: &RbxSnaps for (key, change) in property_updates.drain() { match change { - Some(value) => instance.properties.insert(key, value.to_rbx_value()), + Some(value) => instance.properties.insert(key, value), None => instance.properties.remove(&key), }; } From 3feb8c33448f3a74a818aeac8e3dc91b40f9ae61 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 13 Dec 2018 15:39:39 -0800 Subject: [PATCH 0253/1504] Fix midnight naming --- server/src/rbx_snapshot.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 37e790a0..b8b3f32f 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -119,10 +119,12 @@ fn reconcile_instance_children(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnap let mut children_to_remove = Vec::new(); for i in 0..child_count { - let instance_child_foo = children_ids.get(i).map(|&id| tree.get_instance_mut(id).unwrap()); - let snapshot_child_foo = snapshot.children.get(i); + let instance_child = children_ids + .get(i) + .map(|&id| tree.get_instance_mut(id).unwrap()); + let snapshot_child = snapshot.children.get(i); - match (instance_child_foo, snapshot_child_foo) { + match (instance_child, snapshot_child) { (Some(instance_child), Some(snapshot_child)) => { children_to_update.push((instance_child.get_id(), snapshot_child)); }, From f43dc99f7a919bd12152e93703c8561e0123fe89 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 14 Dec 2018 14:33:45 -0800 Subject: [PATCH 0254/1504] Imfs test --- server/src/commands/build.rs | 3 +- server/src/imfs.rs | 24 +++++----- server/src/session.rs | 7 ++- server/tests/imfs.rs | 93 ++++++++++++++++++++++++++++++++++++ 4 files changed, 113 insertions(+), 14 deletions(-) create mode 100644 server/tests/imfs.rs diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index 6d2ce204..83ba2346 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -77,7 +77,8 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { info!("Found project at {}", project.file_location.display()); info!("Using project {:#?}", project); - let imfs = Imfs::new(&project)?; + let mut imfs = Imfs::new(); + imfs.add_roots_from_project(&project)?; let tree = construct_oneoff_tree(&project, &imfs); let mut file = File::create(&options.output_file)?; diff --git a/server/src/imfs.rs b/server/src/imfs.rs index be9d544c..5891ff4a 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -32,25 +32,25 @@ pub struct Imfs { } impl Imfs { - pub fn new(project: &Project) -> io::Result { - let mut imfs = Imfs::empty(); - - add_sync_points(&mut imfs, &project.tree)?; - - Ok(imfs) - } - - pub fn empty() -> Imfs { + pub fn new() -> Imfs { Imfs { items: HashMap::new(), roots: HashSet::new(), } } + pub fn add_roots_from_project(&mut self, project: &Project) -> io::Result<()> { + add_sync_points(self, &project.tree) + } + pub fn get_roots(&self) -> &HashSet { &self.roots } + pub fn get_items(&self) -> &HashMap { + &self.items + } + pub fn get(&self, path: &Path) -> Option<&ImfsItem> { debug_assert!(path.is_absolute()); debug_assert!(self.is_within_roots(path)); @@ -141,19 +141,19 @@ impl Imfs { } } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub struct ImfsFile { pub path: PathBuf, pub contents: Vec, } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub struct ImfsDirectory { pub path: PathBuf, pub children: HashSet, } -#[derive(Debug)] +#[derive(Debug, PartialEq)] pub enum ImfsItem { File(ImfsFile), Directory(ImfsDirectory), diff --git a/server/src/session.rs b/server/src/session.rs index 5fb589f6..380fec2c 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -22,7 +22,12 @@ pub struct Session { impl Session { pub fn new(project: Project) -> io::Result { - let imfs = Arc::new(Mutex::new(Imfs::new(&project)?)); + let imfs = { + let mut imfs = Imfs::new(); + imfs.add_roots_from_project(&project)?; + + Arc::new(Mutex::new(imfs)) + }; let project = Arc::new(project); let message_queue = Arc::new(MessageQueue::new()); diff --git a/server/tests/imfs.rs b/server/tests/imfs.rs new file mode 100644 index 00000000..a6fd40ff --- /dev/null +++ b/server/tests/imfs.rs @@ -0,0 +1,93 @@ +use std::{ + collections::{HashMap, HashSet}, + io, + fs, + path::PathBuf, +}; + +use tempfile::tempdir; + +use librojo::{ + imfs::{Imfs, ImfsItem, ImfsFile, ImfsDirectory}, +}; + +struct ExpectedImfs { + roots: HashSet, + items: HashMap, +} + +fn check_expected(real: &Imfs, expected: &ExpectedImfs) { + assert_eq!(real.get_roots(), &expected.roots); + assert_eq!(real.get_items(), &expected.items); +} + +fn base_tree() -> io::Result<(Imfs, ExpectedImfs)> { + let root = tempdir()?; + + let foo_path = root.path().join("foo"); + let bar_path = root.path().join("bar.txt"); + let baz_path = foo_path.join("baz.txt"); + + fs::create_dir(&foo_path)?; + fs::write(&bar_path, b"bar")?; + fs::write(&baz_path, b"baz")?; + + let mut imfs = Imfs::new(); + imfs.add_root(root.path())?; + + let mut expected_roots = HashSet::new(); + expected_roots.insert(root.path().to_path_buf()); + + let root_item = { + let mut children = HashSet::new(); + children.insert(foo_path.clone()); + children.insert(bar_path.clone()); + + ImfsItem::Directory(ImfsDirectory { + path: root.path().to_path_buf(), + children, + }) + }; + + let foo_item = { + let mut children = HashSet::new(); + children.insert(baz_path.clone()); + + ImfsItem::Directory(ImfsDirectory { + path: foo_path.clone(), + children, + }) + }; + + let bar_item = ImfsItem::File(ImfsFile { + path: bar_path.clone(), + contents: b"bar".to_vec(), + }); + + let baz_item = ImfsItem::File(ImfsFile { + path: baz_path.clone(), + contents: b"baz".to_vec(), + }); + + let mut expected_items = HashMap::new(); + expected_items.insert(root.path().to_path_buf(), root_item); + expected_items.insert(foo_path.clone(), foo_item); + expected_items.insert(bar_path.clone(), bar_item); + expected_items.insert(baz_path.clone(), baz_item); + + let expected_imfs = ExpectedImfs { + roots: expected_roots, + items: expected_items, + }; + + Ok((imfs, expected_imfs)) +} + +#[test] +fn initial_read() -> io::Result<()> { + let (imfs, expected_imfs) = base_tree()?; + + check_expected(&imfs, &expected_imfs); + + Ok(()) +} \ No newline at end of file From 9516a1aeeafe6479abc241b235905705130110aa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 14 Dec 2018 18:03:56 -0800 Subject: [PATCH 0255/1504] Rework Imfs and expand tests a bit --- server/src/imfs.rs | 148 ++++++++++++++++++++++++++----------------- server/tests/imfs.rs | 68 ++++++++++++++++++-- 2 files changed, 155 insertions(+), 61 deletions(-) diff --git a/server/src/imfs.rs b/server/src/imfs.rs index 5891ff4a..655a2b43 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -64,23 +64,14 @@ impl Imfs { self.roots.insert(path.to_path_buf()); - ImfsItem::read_from_disk(self, path)?; - Ok(()) + self.read_from_disk(path) } pub fn path_created(&mut self, path: &Path) -> io::Result<()> { debug_assert!(path.is_absolute()); debug_assert!(self.is_within_roots(path)); - if let Some(parent_path) = path.parent() { - if self.is_within_roots(parent_path) && self.get(parent_path).is_none() { - self.path_created(parent_path)?; - } - } else { - ImfsItem::read_from_disk(self, path)?; - } - - Ok(()) + self.read_from_disk(path) } pub fn path_updated(&mut self, path: &Path) -> io::Result<()> { @@ -92,7 +83,7 @@ impl Imfs { self.path_created(parent_path)?; } } else { - ImfsItem::read_from_disk(self, path)?; + self.read_from_disk(path)?; } Ok(()) @@ -103,11 +94,7 @@ impl Imfs { debug_assert!(self.is_within_roots(path)); if let Some(parent_path) = path.parent() { - if self.is_within_roots(parent_path) { - if let Some(ImfsItem::Directory(parent)) = self.items.get_mut(parent_path) { - parent.children.remove(path); - } - } + self.unlink_child(parent_path, path); } if let Some(ImfsItem::Directory(directory)) = self.items.remove(path) { @@ -130,37 +117,35 @@ impl Imfs { Ok(()) } - fn is_within_roots(&self, path: &Path) -> bool { - for root_path in &self.roots { - if path.starts_with(root_path) { - return true; + fn unlink_child(&mut self, parent: &Path, child: &Path) { + let parent_item = self.items.get_mut(parent); + + match parent_item { + Some(ImfsItem::Directory(directory)) => { + directory.children.remove(child); + }, + _ => { + panic!("Tried to unlink child of path that wasn't a directory!"); + }, + } + } + + fn link_child(&mut self, parent: &Path, child: &Path) { + if self.is_within_roots(parent) { + let parent_item = self.items.get_mut(parent); + + match parent_item { + Some(ImfsItem::Directory(directory)) => { + directory.children.insert(child.to_path_buf()); + }, + _ => { + panic!("Tried to link child of path that wasn't a directory!"); + }, } } - - false } -} -#[derive(Debug, PartialEq)] -pub struct ImfsFile { - pub path: PathBuf, - pub contents: Vec, -} - -#[derive(Debug, PartialEq)] -pub struct ImfsDirectory { - pub path: PathBuf, - pub children: HashSet, -} - -#[derive(Debug, PartialEq)] -pub enum ImfsItem { - File(ImfsFile), - Directory(ImfsDirectory), -} - -impl ImfsItem { - fn read_from_disk<'a, 'b>(vfs: &'a mut Imfs, path: &'b Path) -> io::Result<&'a ImfsItem> { + fn read_from_disk(&mut self, path: &Path) -> io::Result<()> { let metadata = fs::metadata(path)?; if metadata.is_file() { @@ -170,31 +155,80 @@ impl ImfsItem { contents, }); - vfs.items.insert(path.to_path_buf(), item); + self.items.insert(path.to_path_buf(), item); - Ok(&vfs.items[path]) + if let Some(parent_path) = path.parent() { + self.link_child(parent_path, path); + } + + Ok(()) } else if metadata.is_dir() { - let mut children = HashSet::new(); + let item = ImfsItem::Directory(ImfsDirectory { + path: path.to_path_buf(), + children: HashSet::new(), + }); + + self.items.insert(path.to_path_buf(), item); for entry in fs::read_dir(path)? { let entry = entry?; let child_path = entry.path(); - ImfsItem::read_from_disk(vfs, &child_path)?; - - children.insert(child_path); + self.read_from_disk(&child_path)?; } - let item = ImfsItem::Directory(ImfsDirectory { - path: path.to_path_buf(), - children, - }); + if let Some(parent_path) = path.parent() { + self.link_child(parent_path, path); + } - vfs.items.insert(path.to_path_buf(), item); - - Ok(&vfs.items[path]) + Ok(()) } else { panic!("Unexpected non-file, non-directory item"); } } + + fn is_within_roots(&self, path: &Path) -> bool { + let kind = self.classify_path(path); + + kind == PathKind::Root || kind == PathKind::InRoot + } + + fn classify_path(&self, path: &Path) -> PathKind { + for root_path in &self.roots { + if root_path == path { + return PathKind::Root; + } + + if path.starts_with(root_path) { + return PathKind::InRoot; + } + } + + PathKind::NotInRoot + } +} + +#[derive(Debug, Clone, Copy, PartialEq)] +enum PathKind { + Root, + InRoot, + NotInRoot, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct ImfsFile { + pub path: PathBuf, + pub contents: Vec, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub struct ImfsDirectory { + pub path: PathBuf, + pub children: HashSet, +} + +#[derive(Debug, PartialEq, Serialize, Deserialize)] +pub enum ImfsItem { + File(ImfsFile), + Directory(ImfsDirectory), } \ No newline at end of file diff --git a/server/tests/imfs.rs b/server/tests/imfs.rs index a6fd40ff..4e32df8a 100644 --- a/server/tests/imfs.rs +++ b/server/tests/imfs.rs @@ -5,7 +5,7 @@ use std::{ path::PathBuf, }; -use tempfile::tempdir; +use tempfile::{TempDir, tempdir}; use librojo::{ imfs::{Imfs, ImfsItem, ImfsFile, ImfsDirectory}, @@ -16,18 +16,30 @@ struct ExpectedImfs { items: HashMap, } +struct TestResources { + foo_path: PathBuf, + bar_path: PathBuf, + baz_path: PathBuf, +} + fn check_expected(real: &Imfs, expected: &ExpectedImfs) { assert_eq!(real.get_roots(), &expected.roots); assert_eq!(real.get_items(), &expected.items); } -fn base_tree() -> io::Result<(Imfs, ExpectedImfs)> { +fn base_tree() -> io::Result<(TempDir, Imfs, ExpectedImfs, TestResources)> { let root = tempdir()?; let foo_path = root.path().join("foo"); let bar_path = root.path().join("bar.txt"); let baz_path = foo_path.join("baz.txt"); + let resources = TestResources { + foo_path: foo_path.clone(), + bar_path: bar_path.clone(), + baz_path: baz_path.clone(), + }; + fs::create_dir(&foo_path)?; fs::write(&bar_path, b"bar")?; fs::write(&baz_path, b"baz")?; @@ -80,12 +92,60 @@ fn base_tree() -> io::Result<(Imfs, ExpectedImfs)> { items: expected_items, }; - Ok((imfs, expected_imfs)) + Ok((root, imfs, expected_imfs, resources)) } #[test] fn initial_read() -> io::Result<()> { - let (imfs, expected_imfs) = base_tree()?; + let (root, imfs, expected_imfs, _) = base_tree()?; + + check_expected(&imfs, &expected_imfs); + + Ok(()) +} + +#[test] +fn adding_files() -> io::Result<()> { + let (root, mut imfs, mut expected_imfs, resources) = base_tree()?; + + check_expected(&imfs, &expected_imfs); + + let add_one_path = root.path().join("add_one.txt"); + let add_two_path = resources.foo_path.join("add_two.txt"); + + fs::write(&add_one_path, b"add_one")?; + fs::write(&add_two_path, b"add_two")?; + + imfs.path_created(&add_one_path)?; + imfs.path_created(&add_two_path)?; + + match expected_imfs.items.get_mut(root.path()) { + Some(ImfsItem::Directory(directory)) => { + directory.children.insert(add_one_path.clone()); + }, + _ => unreachable!(), + } + + match expected_imfs.items.get_mut(&resources.foo_path) { + Some(ImfsItem::Directory(directory)) => { + directory.children.insert(add_two_path.clone()); + }, + _ => unreachable!(), + } + + expected_imfs.items.insert(add_one_path.clone(), ImfsItem::File(ImfsFile { + path: add_one_path.clone(), + contents: b"add_one".to_vec(), + })); + + expected_imfs.items.insert(add_two_path.clone(), ImfsItem::File(ImfsFile { + path: add_two_path.clone(), + contents: b"add_two".to_vec(), + })); + + println!("{}", serde_json::to_string(imfs.get_items()).unwrap()); + println!("---------------------------------------------------------------"); + println!("{}", serde_json::to_string(&expected_imfs.items).unwrap()); check_expected(&imfs, &expected_imfs); From 308369b14fb18a26d298bc1c6f5969236a1a1ef1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 14 Dec 2018 18:37:11 -0800 Subject: [PATCH 0256/1504] Implement more tests, fix up removal --- server/src/imfs.rs | 16 +++--- server/tests/imfs.rs | 119 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 124 insertions(+), 11 deletions(-) diff --git a/server/src/imfs.rs b/server/src/imfs.rs index 655a2b43..b48343b9 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -93,16 +93,12 @@ impl Imfs { debug_assert!(path.is_absolute()); debug_assert!(self.is_within_roots(path)); + self.remove_item(path); + if let Some(parent_path) = path.parent() { self.unlink_child(parent_path, path); } - if let Some(ImfsItem::Directory(directory)) = self.items.remove(path) { - for child_path in &directory.children { - self.path_removed(child_path)?; - } - } - Ok(()) } @@ -117,6 +113,14 @@ impl Imfs { Ok(()) } + fn remove_item(&mut self, path: &Path) { + if let Some(ImfsItem::Directory(directory)) = self.items.remove(path) { + for child_path in &directory.children { + self.remove_item(child_path); + } + } + } + fn unlink_child(&mut self, parent: &Path, child: &Path) { let parent_item = self.items.get_mut(parent); diff --git a/server/tests/imfs.rs b/server/tests/imfs.rs index 4e32df8a..b46d4f65 100644 --- a/server/tests/imfs.rs +++ b/server/tests/imfs.rs @@ -24,7 +24,14 @@ struct TestResources { fn check_expected(real: &Imfs, expected: &ExpectedImfs) { assert_eq!(real.get_roots(), &expected.roots); - assert_eq!(real.get_items(), &expected.items); + + let real_items = real.get_items(); + if real_items != &expected.items { + let real_str = serde_json::to_string(real_items).unwrap(); + let expected_str = serde_json::to_string(&expected.items).unwrap(); + + panic!("Items differed!\nReal:\n{}\nExpected:\n{}\n", real_str, expected_str); + } } fn base_tree() -> io::Result<(TempDir, Imfs, ExpectedImfs, TestResources)> { @@ -97,7 +104,7 @@ fn base_tree() -> io::Result<(TempDir, Imfs, ExpectedImfs, TestResources)> { #[test] fn initial_read() -> io::Result<()> { - let (root, imfs, expected_imfs, _) = base_tree()?; + let (_, imfs, expected_imfs, _) = base_tree()?; check_expected(&imfs, &expected_imfs); @@ -143,9 +150,111 @@ fn adding_files() -> io::Result<()> { contents: b"add_two".to_vec(), })); - println!("{}", serde_json::to_string(imfs.get_items()).unwrap()); - println!("---------------------------------------------------------------"); - println!("{}", serde_json::to_string(&expected_imfs.items).unwrap()); + check_expected(&imfs, &expected_imfs); + + Ok(()) +} + +#[test] +fn adding_folder() -> io::Result<()> { + let (root, mut imfs, mut expected_imfs, resources) = base_tree()?; + + check_expected(&imfs, &expected_imfs); + + let folder_path = root.path().join("folder"); + let file1_path = folder_path.join("file1.txt"); + let file2_path = folder_path.join("file2.txt"); + + fs::create_dir(&folder_path)?; + fs::write(&file1_path, b"file1")?; + fs::write(&file2_path, b"file2")?; + + // TODO: Enumerate all possible combinations of file changed events this + // could trigger. + imfs.path_created(&folder_path)?; + + match expected_imfs.items.get_mut(root.path()) { + Some(ImfsItem::Directory(directory)) => { + directory.children.insert(folder_path.clone()); + }, + _ => unreachable!(), + } + + let folder_item = { + let mut children = HashSet::new(); + children.insert(file1_path.clone()); + children.insert(file2_path.clone()); + + ImfsItem::Directory(ImfsDirectory { + path: folder_path.clone(), + children, + }) + }; + + expected_imfs.items.insert(folder_path.clone(), folder_item); + + let file1_item = ImfsItem::File(ImfsFile { + path: file1_path.clone(), + contents: b"file1".to_vec(), + }); + expected_imfs.items.insert(file1_path.clone(), file1_item); + + let file2_item = ImfsItem::File(ImfsFile { + path: file2_path.clone(), + contents: b"file2".to_vec(), + }); + expected_imfs.items.insert(file2_path.clone(), file2_item); + + check_expected(&imfs, &expected_imfs); + + Ok(()) +} + +#[test] +fn removing_file() -> io::Result<()> { + let (root, mut imfs, mut expected_imfs, resources) = base_tree()?; + + check_expected(&imfs, &expected_imfs); + + fs::remove_file(&resources.bar_path)?; + + imfs.path_removed(&resources.bar_path)?; + + match expected_imfs.items.get_mut(root.path()) { + Some(ImfsItem::Directory(directory)) => { + directory.children.remove(&resources.bar_path); + }, + _ => unreachable!(), + } + + expected_imfs.items.remove(&resources.bar_path); + + check_expected(&imfs, &expected_imfs); + + Ok(()) +} + +#[test] +fn removing_folder() -> io::Result<()> { + let (root, mut imfs, mut expected_imfs, resources) = base_tree()?; + + check_expected(&imfs, &expected_imfs); + + fs::remove_dir_all(&resources.foo_path)?; + + // TODO: Enumerate all possible combinations of file changed events this + // could trigger. + imfs.path_removed(&resources.foo_path)?; + + match expected_imfs.items.get_mut(root.path()) { + Some(ImfsItem::Directory(directory)) => { + directory.children.remove(&resources.foo_path); + }, + _ => unreachable!(), + } + + expected_imfs.items.remove(&resources.foo_path); + expected_imfs.items.remove(&resources.baz_path); check_expected(&imfs, &expected_imfs); From 893587040d25fe2bd1b4c48d33f50605afec7bd1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 14 Dec 2018 21:31:48 -0800 Subject: [PATCH 0257/1504] Permute order of FS change events semi-exhaustively --- server/src/imfs.rs | 8 ++--- server/tests/imfs.rs | 70 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 61 insertions(+), 17 deletions(-) diff --git a/server/src/imfs.rs b/server/src/imfs.rs index b48343b9..3b163f6f 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -25,7 +25,7 @@ fn add_sync_points(imfs: &mut Imfs, project_node: &ProjectNode) -> io::Result<() /// The in-memory filesystem keeps a mirror of all files being watcher by Rojo /// in order to deduplicate file changes in the case of bidirectional syncing /// from Roblox Studio. -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct Imfs { items: HashMap, roots: HashSet, @@ -219,19 +219,19 @@ enum PathKind { NotInRoot, } -#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct ImfsFile { pub path: PathBuf, pub contents: Vec, } -#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct ImfsDirectory { pub path: PathBuf, pub children: HashSet, } -#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub enum ImfsItem { File(ImfsFile), Directory(ImfsDirectory), diff --git a/server/tests/imfs.rs b/server/tests/imfs.rs index b46d4f65..4cf034d6 100644 --- a/server/tests/imfs.rs +++ b/server/tests/imfs.rs @@ -11,6 +11,27 @@ use librojo::{ imfs::{Imfs, ImfsItem, ImfsFile, ImfsDirectory}, }; +enum FsEvent { + Created(PathBuf), + Updated(PathBuf), + Removed(PathBuf), + Moved(PathBuf, PathBuf), +} + +fn send_events(imfs: &mut Imfs, events: &[FsEvent]) -> io::Result<()> { + for event in events { + match event { + FsEvent::Created(path) => imfs.path_created(path)?, + FsEvent::Updated(path) => imfs.path_updated(path)?, + FsEvent::Removed(path) => imfs.path_removed(path)?, + FsEvent::Moved(from, to) => imfs.path_moved(from, to)?, + } + } + + Ok(()) +} + +#[derive(Debug, Clone, PartialEq)] struct ExpectedImfs { roots: HashSet, items: HashMap, @@ -123,9 +144,6 @@ fn adding_files() -> io::Result<()> { fs::write(&add_one_path, b"add_one")?; fs::write(&add_two_path, b"add_two")?; - imfs.path_created(&add_one_path)?; - imfs.path_created(&add_two_path)?; - match expected_imfs.items.get_mut(root.path()) { Some(ImfsItem::Directory(directory)) => { directory.children.insert(add_one_path.clone()); @@ -150,6 +168,9 @@ fn adding_files() -> io::Result<()> { contents: b"add_two".to_vec(), })); + imfs.path_created(&add_one_path)?; + imfs.path_created(&add_two_path)?; + check_expected(&imfs, &expected_imfs); Ok(()) @@ -169,10 +190,6 @@ fn adding_folder() -> io::Result<()> { fs::write(&file1_path, b"file1")?; fs::write(&file2_path, b"file2")?; - // TODO: Enumerate all possible combinations of file changed events this - // could trigger. - imfs.path_created(&folder_path)?; - match expected_imfs.items.get_mut(root.path()) { Some(ImfsItem::Directory(directory)) => { directory.children.insert(folder_path.clone()); @@ -205,7 +222,23 @@ fn adding_folder() -> io::Result<()> { }); expected_imfs.items.insert(file2_path.clone(), file2_item); - check_expected(&imfs, &expected_imfs); + let possible_event_sequences = vec![ + vec![ + FsEvent::Created(folder_path.clone()) + ], + vec![ + FsEvent::Created(folder_path.clone()), + FsEvent::Created(file1_path.clone()), + FsEvent::Created(file2_path.clone()), + ], + ]; + + for events in &possible_event_sequences { + let mut imfs = imfs.clone(); + + send_events(&mut imfs, events); + check_expected(&imfs, &expected_imfs); + } Ok(()) } @@ -242,10 +275,6 @@ fn removing_folder() -> io::Result<()> { fs::remove_dir_all(&resources.foo_path)?; - // TODO: Enumerate all possible combinations of file changed events this - // could trigger. - imfs.path_removed(&resources.foo_path)?; - match expected_imfs.items.get_mut(root.path()) { Some(ImfsItem::Directory(directory)) => { directory.children.remove(&resources.foo_path); @@ -256,7 +285,22 @@ fn removing_folder() -> io::Result<()> { expected_imfs.items.remove(&resources.foo_path); expected_imfs.items.remove(&resources.baz_path); - check_expected(&imfs, &expected_imfs); + let possible_event_sequences = vec![ + vec![ + FsEvent::Removed(resources.foo_path.clone()), + ], + vec![ + FsEvent::Removed(resources.baz_path.clone()), + FsEvent::Removed(resources.foo_path.clone()), + ], + ]; + + for events in &possible_event_sequences { + let mut imfs = imfs.clone(); + + send_events(&mut imfs, events); + check_expected(&imfs, &expected_imfs); + } Ok(()) } \ No newline at end of file From f1258148479111111aa3abcd2995ebfabe43179c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 14 Dec 2018 21:42:38 -0800 Subject: [PATCH 0258/1504] Trim up dead/dying code --- server/src/imfs.rs | 31 +++---------------------------- server/tests/imfs.rs | 11 ++++++----- 2 files changed, 9 insertions(+), 33 deletions(-) diff --git a/server/src/imfs.rs b/server/src/imfs.rs index 3b163f6f..a1190a15 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -78,15 +78,7 @@ impl Imfs { debug_assert!(path.is_absolute()); debug_assert!(self.is_within_roots(path)); - if let Some(parent_path) = path.parent() { - if self.is_within_roots(parent_path) && self.get(parent_path).is_none() { - self.path_created(parent_path)?; - } - } else { - self.read_from_disk(path)?; - } - - Ok(()) + self.read_from_disk(path) } pub fn path_removed(&mut self, path: &Path) -> io::Result<()> { @@ -192,33 +184,16 @@ impl Imfs { } fn is_within_roots(&self, path: &Path) -> bool { - let kind = self.classify_path(path); - - kind == PathKind::Root || kind == PathKind::InRoot - } - - fn classify_path(&self, path: &Path) -> PathKind { for root_path in &self.roots { - if root_path == path { - return PathKind::Root; - } - if path.starts_with(root_path) { - return PathKind::InRoot; + return true; } } - PathKind::NotInRoot + false } } -#[derive(Debug, Clone, Copy, PartialEq)] -enum PathKind { - Root, - InRoot, - NotInRoot, -} - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct ImfsFile { pub path: PathBuf, diff --git a/server/tests/imfs.rs b/server/tests/imfs.rs index 4cf034d6..39ffafc9 100644 --- a/server/tests/imfs.rs +++ b/server/tests/imfs.rs @@ -11,6 +11,7 @@ use librojo::{ imfs::{Imfs, ImfsItem, ImfsFile, ImfsDirectory}, }; +#[allow(unused)] enum FsEvent { Created(PathBuf), Updated(PathBuf), @@ -125,7 +126,7 @@ fn base_tree() -> io::Result<(TempDir, Imfs, ExpectedImfs, TestResources)> { #[test] fn initial_read() -> io::Result<()> { - let (_, imfs, expected_imfs, _) = base_tree()?; + let (_root, imfs, expected_imfs, _resources) = base_tree()?; check_expected(&imfs, &expected_imfs); @@ -178,7 +179,7 @@ fn adding_files() -> io::Result<()> { #[test] fn adding_folder() -> io::Result<()> { - let (root, mut imfs, mut expected_imfs, resources) = base_tree()?; + let (root, imfs, mut expected_imfs, _resources) = base_tree()?; check_expected(&imfs, &expected_imfs); @@ -236,7 +237,7 @@ fn adding_folder() -> io::Result<()> { for events in &possible_event_sequences { let mut imfs = imfs.clone(); - send_events(&mut imfs, events); + send_events(&mut imfs, events)?; check_expected(&imfs, &expected_imfs); } @@ -269,7 +270,7 @@ fn removing_file() -> io::Result<()> { #[test] fn removing_folder() -> io::Result<()> { - let (root, mut imfs, mut expected_imfs, resources) = base_tree()?; + let (root, imfs, mut expected_imfs, resources) = base_tree()?; check_expected(&imfs, &expected_imfs); @@ -298,7 +299,7 @@ fn removing_folder() -> io::Result<()> { for events in &possible_event_sequences { let mut imfs = imfs.clone(); - send_events(&mut imfs, events); + send_events(&mut imfs, events)?; check_expected(&imfs, &expected_imfs); } From 5707b8c7e80a187888d7ad9167c672fecd526c24 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 14 Dec 2018 23:34:31 -0800 Subject: [PATCH 0259/1504] Descent-based create/update mechanism --- server/src/imfs.rs | 10 ++++++++++ server/src/path_map.rs | 25 ++++++++++++++++++++++++- server/src/rbx_session.rs | 23 +++++++++++++---------- server/src/rbx_snapshot.rs | 2 +- 4 files changed, 48 insertions(+), 12 deletions(-) diff --git a/server/src/imfs.rs b/server/src/imfs.rs index a1190a15..21f6be1e 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -105,6 +105,16 @@ impl Imfs { Ok(()) } + pub fn get_root_for_path<'a>(&'a self, path: &Path) -> Option<&'a Path> { + for root_path in &self.roots { + if path.starts_with(root_path) { + return Some(root_path); + } + } + + None + } + fn remove_item(&mut self, path: &Path) { if let Some(ImfsItem::Directory(directory)) = self.items.remove(path) { for child_path in &directory.children { diff --git a/server/src/path_map.rs b/server/src/path_map.rs index f1907b30..ebb23364 100644 --- a/server/src/path_map.rs +++ b/server/src/path_map.rs @@ -1,5 +1,5 @@ use std::{ - path::{Path, PathBuf}, + path::{self, Path, PathBuf}, collections::{HashMap, HashSet}, }; @@ -70,4 +70,27 @@ impl PathMap { Some(root_value) } + + pub fn descend(&self, start_path: &Path, target_path: &Path) -> PathBuf { + let relative_path = target_path.strip_prefix(start_path) + .expect("target_path did not begin with start_path"); + let mut current_path = start_path.to_path_buf(); + + for component in relative_path.components() { + match component { + path::Component::Normal(name) => { + let next_path = current_path.join(name); + + if self.nodes.contains_key(&next_path) { + current_path = next_path; + } else { + return current_path; + } + }, + _ => unreachable!(), + } + } + + current_path + } } \ No newline at end of file diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index ce93d6d7..0181267a 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -13,7 +13,7 @@ use crate::{ message_queue::{Message, MessageQueue}, imfs::{Imfs, ImfsItem, ImfsFile}, path_map::PathMap, - rbx_snapshot::{RbxSnapshotInstance, reify_root}, + rbx_snapshot::{RbxSnapshotInstance, reify_root, reconcile_subtree}, }; pub struct RbxSession { @@ -47,13 +47,16 @@ impl RbxSession { } fn path_created_or_updated(&mut self, path: &Path) { - if let Some(instance_id) = self.paths_to_node_ids.get(path) { - // TODO: Replace instance with ID `instance_id` with new instance - } + let imfs = self.imfs.lock().unwrap(); + let root_path = imfs.get_root_for_path(path) + .expect("Path was outside in-memory filesystem roots"); - // TODO: Crawl up path to find first node represented in the tree or a - // sync point root. That path immediately before we find an existing - // node should be read into the tree. + let closest_path = self.paths_to_node_ids.descend(root_path, path); + let &instance_id = self.paths_to_node_ids.get(&closest_path).unwrap(); + + let snapshot = snapshot_instances_from_imfs(&imfs, &closest_path) + .expect("Could not generate instance snapshot"); + reconcile_subtree(&mut self.tree, instance_id, &snapshot); } pub fn path_created(&mut self, path: &Path) { @@ -167,7 +170,7 @@ fn construct_instance_node<'a>( name: Cow::Borrowed(instance_name), properties: HashMap::new(), children, - update_trigger_paths: Vec::new(), + source_path: None, } } @@ -225,7 +228,7 @@ fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option< class_name: Cow::Borrowed(class_name), properties, children: Vec::new(), - update_trigger_paths: vec![file.path.clone()], + source_path: Some(file.path.clone()), }) }, ImfsItem::Directory(directory) => { @@ -239,7 +242,7 @@ fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option< name: Cow::Borrowed(""), // Assigned later in the method properties: HashMap::new(), children: Vec::new(), - update_trigger_paths: vec![directory.path.clone()], + source_path: Some(directory.path.clone()), } }; diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index b8b3f32f..c7dd7b23 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -12,7 +12,7 @@ pub struct RbxSnapshotInstance<'a> { pub class_name: Cow<'a, str>, pub properties: HashMap, pub children: Vec>, - pub update_trigger_paths: Vec, + pub source_path: Option, } fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstance { From e3e480944679977b78d5d58e1e4574a220fb2397 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Dec 2018 12:50:40 -0800 Subject: [PATCH 0260/1504] Flesh out project loading tests --- server/src/project.rs | 8 ++--- server/tests/read_projects.rs | 67 +++++++++++++++++++++++++++++++++-- 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/server/src/project.rs b/server/src/project.rs index 539401d9..d99d3f15 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -126,14 +126,14 @@ pub struct ProjectInitError; #[fail(display = "Project save error")] pub struct ProjectSaveError; -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] pub enum ProjectNode { Instance(InstanceProjectNode), SyncPoint(SyncPointProjectNode), } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct InstanceProjectNode { pub class_name: String, @@ -142,13 +142,13 @@ pub struct InstanceProjectNode { // ignore_unknown: bool, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SyncPointProjectNode { pub path: PathBuf, } -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Project { pub name: String, pub tree: ProjectNode, diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index b8a1315d..6de207ea 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -3,11 +3,12 @@ extern crate librojo; use std::{ + collections::HashMap, path::{Path, PathBuf}, }; use librojo::{ - project::Project, + project::{Project, ProjectNode, InstanceProjectNode, SyncPointProjectNode}, }; lazy_static! { @@ -17,7 +18,7 @@ lazy_static! { } #[test] -fn fullexample() { +fn tour_de_force() { let project_file_location = TEST_PROJECTS_ROOT.join("example.json"); let project = Project::load_exact(&project_file_location).unwrap(); @@ -30,4 +31,66 @@ fn empty() { let project = Project::load_exact(&project_file_location).unwrap(); assert_eq!(project.name, "empty"); +} + +#[test] +fn empty_fuzzy_file() { + let project_file_location = TEST_PROJECTS_ROOT.join("empty/roblox-project.json"); + let project = Project::load_fuzzy(&project_file_location).unwrap(); + + assert_eq!(project.name, "empty"); +} + +#[test] +fn empty_fuzzy_folder() { + let project_location = TEST_PROJECTS_ROOT.join("empty"); + let project = Project::load_fuzzy(&project_location).unwrap(); + + assert_eq!(project.name, "empty"); +} + +#[test] +fn single_sync_point() { + let project_file_location = TEST_PROJECTS_ROOT.join("single-sync-point/roblox-project.json"); + let project = Project::load_exact(&project_file_location).unwrap(); + + let expected_project = { + let foo = ProjectNode::SyncPoint(SyncPointProjectNode { + path: project_file_location.parent().unwrap().join("lib"), + }); + + let mut replicated_storage_children = HashMap::new(); + replicated_storage_children.insert("Foo".to_string(), foo); + + let replicated_storage = ProjectNode::Instance(InstanceProjectNode { + class_name: "ReplicatedStorage".to_string(), + children: replicated_storage_children, + properties: HashMap::new(), + }); + + let mut root_children = HashMap::new(); + root_children.insert("ReplicatedStorage".to_string(), replicated_storage); + + let root_node = ProjectNode::Instance(InstanceProjectNode { + class_name: "DataModel".to_string(), + children: root_children, + properties: HashMap::new(), + }); + + Project { + name: "single-sync-point".to_string(), + tree: root_node, + file_location: project_file_location.clone(), + } + }; + + assert_eq!(project, expected_project); +} + +#[test] +fn test_model() { + let project_file_location = TEST_PROJECTS_ROOT.join("test-model/roblox-project.json"); + let project = Project::load_exact(&project_file_location).unwrap(); + + assert_eq!(project.name, "test-model"); } \ No newline at end of file From 7154f2c32897a6a4d4e2c3635bb4907b1e8434de Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Dec 2018 13:02:40 -0800 Subject: [PATCH 0261/1504] Reorganize and clean up rbx_snapshot a bit --- server/src/rbx_snapshot.rs | 54 +++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index c7dd7b23..5d226fda 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -15,6 +15,32 @@ pub struct RbxSnapshotInstance<'a> { pub source_path: Option, } +pub fn reify_root(snapshot: &RbxSnapshotInstance) -> RbxTree { + let instance = reify_core(snapshot); + let mut tree = RbxTree::new(instance); + let root_id = tree.get_root_id(); + + for child in &snapshot.children { + reify_subtree(child, &mut tree, root_id); + } + + tree +} + +pub fn reify_subtree(snapshot: &RbxSnapshotInstance, tree: &mut RbxTree, parent_id: RbxId) { + let instance = reify_core(snapshot); + let id = tree.insert_instance(instance, parent_id); + + for child in &snapshot.children { + reify_subtree(child, tree, id); + } +} + +pub fn reconcile_subtree(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance) { + reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot); + reconcile_instance_children(tree, id, snapshot); +} + fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstance { let mut properties = HashMap::new(); @@ -31,27 +57,6 @@ fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstance { instance } -pub fn reify_root(snapshot: &RbxSnapshotInstance) -> RbxTree { - let instance = reify_core(snapshot); - let mut tree = RbxTree::new(instance); - let root_id = tree.get_root_id(); - - for child in &snapshot.children { - reify_child(child, &mut tree, root_id); - } - - tree -} - -fn reify_child(snapshot: &RbxSnapshotInstance, tree: &mut RbxTree, parent_id: RbxId) { - let instance = reify_core(snapshot); - let id = tree.insert_instance(instance, parent_id); - - for child in &snapshot.children { - reify_child(child, tree, id); - } -} - fn reconcile_instance_properties(instance: &mut RbxInstance, snapshot: &RbxSnapshotInstance) -> bool { let mut has_diffs = false; @@ -139,7 +144,7 @@ fn reconcile_instance_children(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnap } for child_snapshot in &children_to_add { - reify_child(child_snapshot, tree, id); + reify_subtree(child_snapshot, tree, id); } for child_id in &children_to_remove { @@ -149,9 +154,4 @@ fn reconcile_instance_children(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnap for (child_id, child_snapshot) in &children_to_update { reconcile_subtree(tree, *child_id, child_snapshot); } -} - -pub fn reconcile_subtree(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance) { - reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot); - reconcile_instance_children(tree, id, snapshot); } \ No newline at end of file From 57442a4848c107d86458d6f0760addd6fa59995f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Dec 2018 13:22:29 -0800 Subject: [PATCH 0262/1504] Make MessageQueue generic, collapse Message into a single struct --- server/src/message_queue.rs | 25 ++++++------------------- server/src/rbx_session.rs | 29 +++++++++++++++++++++-------- server/src/session.rs | 4 ++-- server/src/web.rs | 4 ++-- 4 files changed, 31 insertions(+), 31 deletions(-) diff --git a/server/src/message_queue.rs b/server/src/message_queue.rs index 94203b90..dd86bc04 100644 --- a/server/src/message_queue.rs +++ b/server/src/message_queue.rs @@ -8,8 +8,6 @@ use std::{ }, }; -use rbx_tree::RbxId; - /// A unique identifier, not guaranteed to be generated in any order. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ListenerId(usize); @@ -21,32 +19,21 @@ pub fn get_listener_id() -> ListenerId { ListenerId(LAST_ID.fetch_add(1, Ordering::SeqCst)) } -#[derive(Debug, Clone, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum Message { - InstancesRemoved { - ids: Vec, - }, - InstancesUpdated { - ids: Vec, - }, -} - #[derive(Default)] -pub struct MessageQueue { - messages: RwLock>, +pub struct MessageQueue { + messages: RwLock>, message_listeners: Mutex>>, } -impl MessageQueue { - pub fn new() -> MessageQueue { +impl MessageQueue { + pub fn new() -> MessageQueue { MessageQueue { messages: RwLock::new(Vec::new()), message_listeners: Mutex::new(HashMap::new()), } } - pub fn push_messages(&self, new_messages: &[Message]) { + pub fn push_messages(&self, new_messages: &[T]) { let message_listeners = self.message_listeners.lock().unwrap(); { @@ -77,7 +64,7 @@ impl MessageQueue { self.messages.read().unwrap().len() as u32 } - pub fn get_messages_since(&self, cursor: u32) -> (u32, Vec) { + pub fn get_messages_since(&self, cursor: u32) -> (u32, Vec) { let messages = self.messages.read().unwrap(); let current_cursor = messages.len() as u32; diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 0181267a..1d4b7855 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -1,6 +1,6 @@ use std::{ borrow::Cow, - collections::HashMap, + collections::{HashMap, HashSet}, path::Path, sync::{Arc, Mutex}, str, @@ -10,23 +10,34 @@ use rbx_tree::{RbxTree, RbxValue, RbxId}; use crate::{ project::{Project, ProjectNode, InstanceProjectNode}, - message_queue::{Message, MessageQueue}, + message_queue::MessageQueue, imfs::{Imfs, ImfsItem, ImfsFile}, path_map::PathMap, rbx_snapshot::{RbxSnapshotInstance, reify_root, reconcile_subtree}, }; +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct InstanceChanges { + pub added: HashSet, + pub removed: HashSet, + pub updated: HashSet, +} + pub struct RbxSession { tree: RbxTree, paths_to_node_ids: PathMap, ids_to_project_paths: HashMap, - message_queue: Arc, + message_queue: Arc>, imfs: Arc>, project: Arc, } impl RbxSession { - pub fn new(project: Arc, imfs: Arc>, message_queue: Arc) -> RbxSession { + pub fn new( + project: Arc, + imfs: Arc>, + message_queue: Arc>, + ) -> RbxSession { let tree = { let temp_imfs = imfs.lock().unwrap(); construct_initial_tree(&project, &temp_imfs) @@ -97,12 +108,14 @@ impl RbxSession { }, }; - let removed_ids: Vec = removed_subtree.iter_all_ids().collect(); + let removed_ids: HashSet = removed_subtree.iter_all_ids().collect(); self.message_queue.push_messages(&[ - Message::InstancesRemoved { - ids: removed_ids, - }, + InstanceChanges { + added: HashSet::new(), + removed: removed_ids, + updated: HashSet::new(), + } ]); } diff --git a/server/src/session.rs b/server/src/session.rs index 380fec2c..86fbf5a0 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -8,14 +8,14 @@ use crate::{ project::Project, imfs::Imfs, session_id::SessionId, - rbx_session::RbxSession, + rbx_session::{RbxSession, InstanceChanges}, fs_watcher::FsWatcher, }; pub struct Session { pub project: Arc, pub session_id: SessionId, - pub message_queue: Arc, + pub message_queue: Arc>, pub rbx_session: Arc>, _fs_watcher: FsWatcher, } diff --git a/server/src/web.rs b/server/src/web.rs index c367dabd..ee7c473a 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -13,10 +13,10 @@ use rouille::{ use rbx_tree::{RbxId, RootedRbxInstance}; use crate::{ - message_queue::Message, session::Session, session_id::SessionId, project::Project, + rbx_session::{InstanceChanges}, }; #[derive(Debug, Serialize, Deserialize)] @@ -43,7 +43,7 @@ pub struct ReadResponse<'a> { pub struct SubscribeResponse<'a> { pub session_id: SessionId, pub message_cursor: u32, - pub messages: Cow<'a, [Message]>, + pub messages: Cow<'a, [InstanceChanges]>, } pub struct Server { From 8fadafcd24720102870115287cff4e655df0ef5a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Dec 2018 14:18:32 -0800 Subject: [PATCH 0263/1504] Track instance changes inside rbx_snapshot --- server/src/rbx_session.rs | 30 ++++++++++++++++++---------- server/src/rbx_snapshot.rs | 41 +++++++++++++++++++++++++++----------- 2 files changed, 48 insertions(+), 23 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 1d4b7855..08ffb590 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -16,13 +16,19 @@ use crate::{ rbx_snapshot::{RbxSnapshotInstance, reify_root, reconcile_subtree}, }; -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct InstanceChanges { pub added: HashSet, pub removed: HashSet, pub updated: HashSet, } +impl InstanceChanges { + pub fn is_empty(&self) -> bool { + self.added.is_empty() && self.removed.is_empty() && self.updated.is_empty() + } +} + pub struct RbxSession { tree: RbxTree, paths_to_node_ids: PathMap, @@ -67,7 +73,9 @@ impl RbxSession { let snapshot = snapshot_instances_from_imfs(&imfs, &closest_path) .expect("Could not generate instance snapshot"); - reconcile_subtree(&mut self.tree, instance_id, &snapshot); + + let mut changes = InstanceChanges::default(); + reconcile_subtree(&mut self.tree, instance_id, &snapshot, &mut changes); } pub fn path_created(&mut self, path: &Path) { @@ -108,15 +116,13 @@ impl RbxSession { }, }; - let removed_ids: HashSet = removed_subtree.iter_all_ids().collect(); + let changes = InstanceChanges { + added: HashSet::new(), + removed: removed_subtree.iter_all_ids().collect(), + updated: HashSet::new(), + }; - self.message_queue.push_messages(&[ - InstanceChanges { - added: HashSet::new(), - removed: removed_ids, - updated: HashSet::new(), - } - ]); + self.message_queue.push_messages(&[changes]); } pub fn path_renamed(&mut self, from_path: &Path, to_path: &Path) { @@ -148,7 +154,9 @@ fn construct_initial_tree( &project.tree, ); - reify_root(&snapshot) + let mut changes = InstanceChanges::default(); + + reify_root(&snapshot, &mut changes) } fn construct_project_node<'a>( diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 5d226fda..4a45afd0 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -7,6 +7,8 @@ use std::{ use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; +use crate::rbx_session::InstanceChanges; + pub struct RbxSnapshotInstance<'a> { pub name: Cow<'a, str>, pub class_name: Cow<'a, str>, @@ -15,30 +17,37 @@ pub struct RbxSnapshotInstance<'a> { pub source_path: Option, } -pub fn reify_root(snapshot: &RbxSnapshotInstance) -> RbxTree { +pub fn reify_root(snapshot: &RbxSnapshotInstance, changes: &mut InstanceChanges) -> RbxTree { let instance = reify_core(snapshot); let mut tree = RbxTree::new(instance); let root_id = tree.get_root_id(); + changes.added.insert(root_id); + for child in &snapshot.children { - reify_subtree(child, &mut tree, root_id); + reify_subtree(child, &mut tree, root_id, changes); } tree } -pub fn reify_subtree(snapshot: &RbxSnapshotInstance, tree: &mut RbxTree, parent_id: RbxId) { +pub fn reify_subtree(snapshot: &RbxSnapshotInstance, tree: &mut RbxTree, parent_id: RbxId, changes: &mut InstanceChanges) { let instance = reify_core(snapshot); let id = tree.insert_instance(instance, parent_id); + changes.added.insert(id); + for child in &snapshot.children { - reify_subtree(child, tree, id); + reify_subtree(child, tree, id, changes); } } -pub fn reconcile_subtree(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance) { - reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot); - reconcile_instance_children(tree, id, snapshot); +pub fn reconcile_subtree(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance, changes: &mut InstanceChanges) { + if reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot) { + changes.updated.insert(id); + } + + reconcile_instance_children(tree, id, snapshot, changes); } fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstance { @@ -114,8 +123,12 @@ fn reconcile_instance_properties(instance: &mut RbxInstance, snapshot: &RbxSnaps has_diffs } -fn reconcile_instance_children(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance) { - // TODO: enumerate and match up children, update props, construct and delete IDs +fn reconcile_instance_children( + tree: &mut RbxTree, + id: RbxId, + snapshot: &RbxSnapshotInstance, + changes: &mut InstanceChanges +) { let children_ids = tree.get_instance(id).unwrap().get_children_ids().to_vec(); let child_count = children_ids.len().max(snapshot.children.len()); @@ -144,14 +157,18 @@ fn reconcile_instance_children(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnap } for child_snapshot in &children_to_add { - reify_subtree(child_snapshot, tree, id); + reify_subtree(child_snapshot, tree, id, changes); } for child_id in &children_to_remove { - tree.remove_instance(*child_id); + if let Some(subtree) = tree.remove_instance(*child_id) { + for id in subtree.iter_all_ids() { + changes.removed.insert(id); + } + } } for (child_id, child_snapshot) in &children_to_update { - reconcile_subtree(tree, *child_id, child_snapshot); + reconcile_subtree(tree, *child_id, child_snapshot, changes); } } \ No newline at end of file From 65e551c5cfdd76084add376324eb66c10c5fdc6e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Dec 2018 14:20:19 -0800 Subject: [PATCH 0264/1504] Move InstanceChanges into rbx_snapshot --- server/src/rbx_session.rs | 15 +-------------- server/src/rbx_snapshot.rs | 15 +++++++++++++-- server/src/session.rs | 3 ++- server/src/web.rs | 2 +- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 08ffb590..3c306064 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -13,22 +13,9 @@ use crate::{ message_queue::MessageQueue, imfs::{Imfs, ImfsItem, ImfsFile}, path_map::PathMap, - rbx_snapshot::{RbxSnapshotInstance, reify_root, reconcile_subtree}, + rbx_snapshot::{RbxSnapshotInstance, InstanceChanges, reify_root, reconcile_subtree}, }; -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -pub struct InstanceChanges { - pub added: HashSet, - pub removed: HashSet, - pub updated: HashSet, -} - -impl InstanceChanges { - pub fn is_empty(&self) -> bool { - self.added.is_empty() && self.removed.is_empty() && self.updated.is_empty() - } -} - pub struct RbxSession { tree: RbxTree, paths_to_node_ids: PathMap, diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 4a45afd0..45320990 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -1,13 +1,24 @@ use std::{ str, borrow::Cow, - collections::HashMap, + collections::{HashMap, HashSet}, path::PathBuf, }; use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; -use crate::rbx_session::InstanceChanges; +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct InstanceChanges { + pub added: HashSet, + pub removed: HashSet, + pub updated: HashSet, +} + +impl InstanceChanges { + pub fn is_empty(&self) -> bool { + self.added.is_empty() && self.removed.is_empty() && self.updated.is_empty() + } +} pub struct RbxSnapshotInstance<'a> { pub name: Cow<'a, str>, diff --git a/server/src/session.rs b/server/src/session.rs index 86fbf5a0..bf7686e5 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -8,7 +8,8 @@ use crate::{ project::Project, imfs::Imfs, session_id::SessionId, - rbx_session::{RbxSession, InstanceChanges}, + rbx_session::RbxSession, + rbx_snapshot::InstanceChanges, fs_watcher::FsWatcher, }; diff --git a/server/src/web.rs b/server/src/web.rs index ee7c473a..6a7e02d6 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -16,7 +16,7 @@ use crate::{ session::Session, session_id::SessionId, project::Project, - rbx_session::{InstanceChanges}, + rbx_snapshot::InstanceChanges, }; #[derive(Debug, Serialize, Deserialize)] From 1176c9bbf16700b3d294b0dc0576a244771a2dd1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Dec 2018 17:05:58 -0800 Subject: [PATCH 0265/1504] Add little harness to test against a new project without accidentally committing junk --- server/.gitignore | 1 + server/test-scratch-project | 12 ++++++++++++ 2 files changed, 13 insertions(+) create mode 100644 server/test-scratch-project diff --git a/server/.gitignore b/server/.gitignore index eccd7b4a..9b55d532 100644 --- a/server/.gitignore +++ b/server/.gitignore @@ -1,2 +1,3 @@ /target/ +/scratch/ **/*.rs.bk diff --git a/server/test-scratch-project b/server/test-scratch-project new file mode 100644 index 00000000..a9d498ee --- /dev/null +++ b/server/test-scratch-project @@ -0,0 +1,12 @@ +#!/bin/sh + +set -e + +if [ -d "scratch" ] +then + rm -rf scratch +fi + +mkdir -p scratch +cp -r ../test-projects/test-model scratch +cargo run -- serve scratch/test-model \ No newline at end of file From 1b9ab43b6d8a08f0db89768f9a947187e0988200 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Dec 2018 17:06:14 -0800 Subject: [PATCH 0266/1504] Path and change tracking working --- server/src/rbx_session.rs | 56 ++++++++++++++++++++------------------ server/src/rbx_snapshot.rs | 45 ++++++++++++++++++++++++------ server/src/web.rs | 4 +-- 3 files changed, 66 insertions(+), 39 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 3c306064..e1a0df67 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -18,8 +18,7 @@ use crate::{ pub struct RbxSession { tree: RbxTree, - paths_to_node_ids: PathMap, - ids_to_project_paths: HashMap, + path_map: PathMap, message_queue: Arc>, imfs: Arc>, project: Arc, @@ -31,19 +30,16 @@ impl RbxSession { imfs: Arc>, message_queue: Arc>, ) -> RbxSession { + let mut path_map = PathMap::new(); + let tree = { let temp_imfs = imfs.lock().unwrap(); - construct_initial_tree(&project, &temp_imfs) + construct_initial_tree(&project, &temp_imfs, &mut path_map) }; - // TODO: Restore these? - let paths_to_node_ids = PathMap::new(); - let ids_to_project_paths = HashMap::new(); - RbxSession { tree, - paths_to_node_ids, - ids_to_project_paths, + path_map, message_queue, imfs, project, @@ -51,18 +47,25 @@ impl RbxSession { } fn path_created_or_updated(&mut self, path: &Path) { - let imfs = self.imfs.lock().unwrap(); - let root_path = imfs.get_root_for_path(path) - .expect("Path was outside in-memory filesystem roots"); - - let closest_path = self.paths_to_node_ids.descend(root_path, path); - let &instance_id = self.paths_to_node_ids.get(&closest_path).unwrap(); - - let snapshot = snapshot_instances_from_imfs(&imfs, &closest_path) - .expect("Could not generate instance snapshot"); - let mut changes = InstanceChanges::default(); - reconcile_subtree(&mut self.tree, instance_id, &snapshot, &mut changes); + + { + let imfs = self.imfs.lock().unwrap(); + let root_path = imfs.get_root_for_path(path) + .expect("Path was outside in-memory filesystem roots"); + + let closest_path = self.path_map.descend(root_path, path); + let &instance_id = self.path_map.get(&closest_path).unwrap(); + + let snapshot = snapshot_instances_from_imfs(&imfs, &closest_path) + .expect("Could not generate instance snapshot"); + + reconcile_subtree(&mut self.tree, instance_id, &snapshot, &mut self.path_map, &mut changes); + } + + if !changes.is_empty() { + self.message_queue.push_messages(&[changes]); + } } pub fn path_created(&mut self, path: &Path) { @@ -90,7 +93,7 @@ impl RbxSession { pub fn path_removed(&mut self, path: &Path) { info!("Path removed: {}", path.display()); - let instance_id = match self.paths_to_node_ids.remove(path) { + let instance_id = match self.path_map.remove(path) { Some(id) => id, None => return, }; @@ -121,19 +124,17 @@ impl RbxSession { pub fn get_tree(&self) -> &RbxTree { &self.tree } - - pub fn get_project_path_map(&self) -> &HashMap { - &self.ids_to_project_paths - } } pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { - construct_initial_tree(project, imfs) + let mut path_map = PathMap::new(); + construct_initial_tree(project, imfs, &mut path_map) } fn construct_initial_tree( project: &Project, imfs: &Imfs, + path_map: &mut PathMap, ) -> RbxTree { let snapshot = construct_project_node( imfs, @@ -142,8 +143,9 @@ fn construct_initial_tree( ); let mut changes = InstanceChanges::default(); + let tree = reify_root(&snapshot, path_map, &mut changes); - reify_root(&snapshot, &mut changes) + tree } fn construct_project_node<'a>( diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 45320990..f81161d7 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -7,6 +7,8 @@ use std::{ use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; +use crate::path_map::PathMap; + #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct InstanceChanges { pub added: HashSet, @@ -28,37 +30,61 @@ pub struct RbxSnapshotInstance<'a> { pub source_path: Option, } -pub fn reify_root(snapshot: &RbxSnapshotInstance, changes: &mut InstanceChanges) -> RbxTree { +pub fn reify_root( + snapshot: &RbxSnapshotInstance, + path_map: &mut PathMap, + changes: &mut InstanceChanges, +) -> RbxTree { let instance = reify_core(snapshot); let mut tree = RbxTree::new(instance); let root_id = tree.get_root_id(); + if let Some(source_path) = &snapshot.source_path { + path_map.insert(source_path.clone(), root_id); + } + changes.added.insert(root_id); for child in &snapshot.children { - reify_subtree(child, &mut tree, root_id, changes); + reify_subtree(child, &mut tree, root_id, path_map, changes); } tree } -pub fn reify_subtree(snapshot: &RbxSnapshotInstance, tree: &mut RbxTree, parent_id: RbxId, changes: &mut InstanceChanges) { +pub fn reify_subtree( + snapshot: &RbxSnapshotInstance, + tree: &mut RbxTree, + parent_id: RbxId, + path_map: &mut PathMap, + changes: &mut InstanceChanges, +) { let instance = reify_core(snapshot); let id = tree.insert_instance(instance, parent_id); + if let Some(source_path) = &snapshot.source_path { + path_map.insert(source_path.clone(), id); + } + changes.added.insert(id); for child in &snapshot.children { - reify_subtree(child, tree, id, changes); + reify_subtree(child, tree, id, path_map, changes); } } -pub fn reconcile_subtree(tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance, changes: &mut InstanceChanges) { +pub fn reconcile_subtree( + tree: &mut RbxTree, + id: RbxId, + snapshot: &RbxSnapshotInstance, + path_map: &mut PathMap, + changes: &mut InstanceChanges, +) { if reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot) { changes.updated.insert(id); } - reconcile_instance_children(tree, id, snapshot, changes); + reconcile_instance_children(tree, id, snapshot, path_map, changes); } fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstance { @@ -138,7 +164,8 @@ fn reconcile_instance_children( tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance, - changes: &mut InstanceChanges + path_map: &mut PathMap, + changes: &mut InstanceChanges, ) { let children_ids = tree.get_instance(id).unwrap().get_children_ids().to_vec(); let child_count = children_ids.len().max(snapshot.children.len()); @@ -168,7 +195,7 @@ fn reconcile_instance_children( } for child_snapshot in &children_to_add { - reify_subtree(child_snapshot, tree, id, changes); + reify_subtree(child_snapshot, tree, id, path_map, changes); } for child_id in &children_to_remove { @@ -180,6 +207,6 @@ fn reconcile_instance_children( } for (child_id, child_snapshot) in &children_to_update { - reconcile_subtree(tree, *child_id, child_snapshot, changes); + reconcile_subtree(tree, *child_id, child_snapshot, path_map, changes); } } \ No newline at end of file diff --git a/server/src/web.rs b/server/src/web.rs index 6a7e02d6..d1974bed 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -27,7 +27,6 @@ pub struct ServerInfoResponse<'a> { pub protocol_version: u64, pub root_instance_id: RbxId, pub project: Cow<'a, Project>, - pub ids_to_project_paths: Cow<'a, HashMap>, } #[derive(Debug, Serialize, Deserialize)] @@ -80,7 +79,6 @@ impl Server { session_id: self.session.session_id, root_instance_id: tree.get_root_id(), project: Cow::Borrowed(&self.session.project), - ids_to_project_paths: Cow::Borrowed(rbx_session.get_project_path_map()), }) }, @@ -97,7 +95,7 @@ impl Server { if !new_messages.is_empty() { return Response::json(&SubscribeResponse { session_id: self.session.session_id, - messages: Cow::Borrowed(&[]), + messages: Cow::Borrowed(&new_messages), message_cursor: new_cursor, }) } From 9125f9630283c9fb79db411f5571793092750afc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Dec 2018 17:23:07 -0800 Subject: [PATCH 0267/1504] Get rid of intermediate 'modules' folder in plugin --- plugin/rojo.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugin/rojo.json b/plugin/rojo.json index 2276882c..3882435a 100644 --- a/plugin/rojo.json +++ b/plugin/rojo.json @@ -4,23 +4,23 @@ "partitions": { "plugin": { "path": "src", - "target": "ReplicatedStorage.Rojo.Modules.Plugin" + "target": "ReplicatedStorage.Rojo.Plugin" }, "modules/roact": { "path": "modules/roact/lib", - "target": "ReplicatedStorage.Rojo.Modules.Roact" + "target": "ReplicatedStorage.Rojo.Roact" }, "modules/rodux": { "path": "modules/rodux/lib", - "target": "ReplicatedStorage.Rojo.Modules.Rodux" + "target": "ReplicatedStorage.Rojo.Rodux" }, "modules/roact-rodux": { "path": "modules/roact-rodux/lib", - "target": "ReplicatedStorage.Rojo.Modules.RoactRodux" + "target": "ReplicatedStorage.Rojo.RoactRodux" }, "modules/promise": { "path": "modules/promise/lib", - "target": "ReplicatedStorage.Rojo.Modules.Promise" + "target": "ReplicatedStorage.Rojo.Promise" }, "modules/testez": { "path": "modules/testez/lib", From a511a5b259cda4f320e086dec3464e0b6220a7fa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Dec 2018 17:36:03 -0800 Subject: [PATCH 0268/1504] Upgrade dependencies --- server/Cargo.lock | 57 ++++++++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 25 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index a42d6486..2d8060fc 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -34,21 +34,27 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "autocfg" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "backtrace" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.24" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", @@ -127,7 +133,7 @@ dependencies = [ [[package]] name = "cargo_metadata" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -154,7 +160,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -284,7 +290,7 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -292,7 +298,7 @@ name = "failure" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -303,7 +309,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -847,7 +853,7 @@ dependencies = [ [[package]] name = "rbx_binary" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#1719d35df9b08637c2938d4418e834e48f39f624" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#ff15a6d54bd136921ad3fdd901a31b6cc003d630" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -857,7 +863,7 @@ dependencies = [ [[package]] name = "rbx_tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#1719d35df9b08637c2938d4418e834e48f39f624" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#ff15a6d54bd136921ad3fdd901a31b6cc003d630" dependencies = [ "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", @@ -867,7 +873,7 @@ dependencies = [ [[package]] name = "rbx_xml" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#1719d35df9b08637c2938d4418e834e48f39f624" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#ff15a6d54bd136921ad3fdd901a31b6cc003d630" dependencies = [ "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -957,14 +963,14 @@ dependencies = [ "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.9" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1029,7 +1035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1058,7 +1064,7 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1092,7 +1098,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.22" +version = "0.15.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1107,7 +1113,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1186,7 +1192,7 @@ dependencies = [ [[package]] name = "time" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1409,8 +1415,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum backtrace 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "a2eff3830839471718ef8522b9025b399bfb713e25bc220da721364efb660d7d" -"checksum backtrace-sys 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "c66d56ac8dabd07f6aacdaf633f4b8262f5b3601a810a0dcddffd5c22c69daa0" +"checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727" +"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace-sys 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3fcce89e5ad5c8949caa9434501f7b55415b3e7ad5270cb88c75a8d35e8f1279" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" @@ -1421,7 +1428,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" -"checksum cargo_metadata 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "48e8d5fd5b81d86d3ec3c820ecf5a3027fa22d6aede2be981cf07a8ce16451bb" +"checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" "checksum cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "389803e36973d242e7fecb092b2de44a3d35ac62524b3b9339e51d577d668e02" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" @@ -1512,7 +1519,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841" -"checksum rustc-demangle 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "bcfe5b13211b4d78e5c2cadfebd7769197d95c639c35a50057eb4c05de811395" +"checksum rustc-demangle 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "01b90379b8664dd83460d59bdc5dd1fd3172b8913788db483ed1325171eab2f7" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" @@ -1531,7 +1538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)" = "ae8b29eb5210bc5cf63ed6149cbf9adfc82ac0be023d8735c176ee74a2db4da7" +"checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" @@ -1541,7 +1548,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" -"checksum time 0.1.40 (registry+https://github.com/rust-lang/crates.io-index)" = "d825be0eb33fda1a7e68012d51e9c7f451dc1a69391e7fdc197060bb8c56667b" +"checksum time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c" "checksum tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a442681f9f72e440be192700eeb2861e4174b9983f16f4877c93a134cb5e5f63" "checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde" "checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21" From 05594ecca0818009b9071022d0baaa43ca281934 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Dec 2018 17:51:25 -0800 Subject: [PATCH 0269/1504] Update timeout detection --- plugin/src/HttpError.lua | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/plugin/src/HttpError.lua b/plugin/src/HttpError.lua index e28bc392..f1b06fc2 100644 --- a/plugin/src/HttpError.lua +++ b/plugin/src/HttpError.lua @@ -15,11 +15,20 @@ HttpError.Error = { message = "Couldn't connect to the Rojo server.\n" .. "Make sure the server is running -- use 'rojo serve' to run it!", }, + Timeout = { + message = "Request timed out.", + }, Unknown = { message = "Unknown error: {{message}}", }, } +setmetatable(HttpError.Error, { + __index = function(_, key) + error(("%q is not a valid member of HttpError.Error"):format(tostring(key)), 2) + end, +}) + function HttpError.new(type, extraMessage) extraMessage = extraMessage or "" local message = type.message:gsub("{{message}}", extraMessage) @@ -48,6 +57,10 @@ function HttpError.fromErrorString(message) return HttpError.new(HttpError.Error.HttpNotEnabled) end + if lower:find("^httperror: timedout") then + return HttpError.new(HttpError.Error.Timeout) + end + if lower:find("^httperror: connectfail") then return HttpError.new(HttpError.Error.ConnectFailed) end From d807d2235065023be011e03c152d95297f3658d5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Dec 2018 17:52:00 -0800 Subject: [PATCH 0270/1504] Basic reification, works for model-like projects but not place-like ones --- plugin/src/Session.lua | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index b01c30d7..3414bc24 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -4,6 +4,27 @@ local Logging = require(script.Parent.Logging) local REMOTE_URL = ("http://localhost:%d"):format(Config.port) +local function reify(instanceData, id, parent) + local data = instanceData[id] + + local instance = Instance.new(data.ClassName) + + for key, value in pairs(data.Properties) do + -- TODO: Branch on value.Type + instance[key] = value.Value + end + + instance.Name = data.Name + + for _, childId in ipairs(data.Children) do + reify(instanceData, childId, instance) + end + + instance.Parent = parent + + return instance +end + local Session = {} Session.__index = Session @@ -25,7 +46,8 @@ function Session.new() :andThen(function() return api:read({api.rootInstanceId}) end) - :andThen(function() + :andThen(function(response) + reify(response.instances, api.rootInstanceId, game.ReplicatedStorage) return api:retrieveMessages() end) :catch(function(message) From 9ac7ebc3353250b2da4a1f8739475de0a55a2051 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Dec 2018 18:37:38 -0800 Subject: [PATCH 0271/1504] Hacky reify/reconcile stuff, mostly works --- plugin/src/ApiContext.lua | 3 + plugin/src/Session.lua | 155 +++++++++++++++++++++++++++++++++++--- 2 files changed, 147 insertions(+), 11 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 19dd19eb..54362a39 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -19,6 +19,7 @@ setmetatable(ApiContext.Error, { end }) +-- TODO: Switch to onMessages and batch processing function ApiContext.new(baseUrl, onMessage) assert(type(baseUrl) == "string") assert(type(onMessage) == "function") @@ -108,6 +109,8 @@ function ApiContext:retrieveMessages() return Promise.reject("Server changed ID") end + -- TODO: Wait for all messages to be processed before resuming. + -- This callback will return a promise! for _, message in ipairs(body.messages) do self.onMessage(message) end diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 3414bc24..17af009e 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -4,42 +4,174 @@ local Logging = require(script.Parent.Logging) local REMOTE_URL = ("http://localhost:%d"):format(Config.port) -local function reify(instanceData, id, parent) +local function makeInstanceMap() + local self = { + fromIds = {}, + fromInstances = {}, + } + + function self:insert(id, instance) + self.fromIds[id] = instance + self.fromInstances[instance] = id + end + + function self:removeId(id) + local instance = self.fromIds[id] + + if instance then + self.fromIds[id] = nil + self.fromInstances[instance] = nil + end + end + + function self:removeInstance(instance) + local id = self.fromInstances[instance] + + if id then + self.fromInstances[instance] = nil + self.fromIds[id] = nil + end + end + + return self +end + +local function setProperty(instance, key, value) + local ok, err = pcall(function() + instance[key] = value + end) + + if not ok then + error(("Cannot set property %s on class %s: %s"):format(tostring(key), instance.ClassName, err), 2) + end +end + +-- TODO: Pull this from project configuration instead +local function shouldClearUnknown(instance) + return instance.ClassName ~= "DataModel" and instance.ClassName ~= "ReplicatedStorage" +end + +local function reify(instanceData, instanceMap, id, parent) local data = instanceData[id] local instance = Instance.new(data.ClassName) for key, value in pairs(data.Properties) do -- TODO: Branch on value.Type - instance[key] = value.Value + setProperty(instance, key, value.Value) end instance.Name = data.Name for _, childId in ipairs(data.Children) do - reify(instanceData, childId, instance) + reify(instanceData, instanceMap, childId, instance) end - instance.Parent = parent + setProperty(instance, "Parent", parent) + instanceMap:insert(id, instance) return instance end +local function reconcile(instanceData, instanceMap, id, existingInstance) + local data = instanceData[id] + + assert(data.ClassName == existingInstance.ClassName) + + for key, value in pairs(data.Properties) do + setProperty(existingInstance, key, value.Value) + end + + local existingChildren = existingInstance:GetChildren() + + local unvisitedExistingChildren = {} + for _, child in ipairs(existingChildren) do + unvisitedExistingChildren[child] = true + end + + for _, childId in ipairs(data.Children) do + local childData = instanceData[childId] + + local existingChildInstance + for instance in pairs(unvisitedExistingChildren) do + local ok, name, className = pcall(function() + return instance.Name, instance.ClassName + end) + + if ok then + if name == childData.Name and className == childData.ClassName then + existingChildInstance = instance + break + end + end + end + + if existingChildInstance ~= nil then + unvisitedExistingChildren[existingChildInstance] = nil + reconcile(instanceData, instanceMap, childId, existingChildInstance) + else + reify(instanceData, instanceMap, childId, existingInstance) + end + end + + if shouldClearUnknown(existingInstance) then + for existingChildInstance in pairs(unvisitedExistingChildren) do + instanceMap:removeInstance(existingChildInstance) + existingChildInstance:Destroy() + end + end + + return existingInstance +end + local Session = {} Session.__index = Session function Session.new() local self = {} + local instanceMap = makeInstanceMap() + local api api = ApiContext.new(REMOTE_URL, function(message) - if message.type == "InstanceChanged" then - Logging.trace("Instance %s changed!", message.id) - -- readAll() - else - Logging.warn("Unknown message type %s", message.type) + local idsToGet = {} + + for _, id in ipairs(message.added) do + table.insert(idsToGet, id) end + + for _, id in ipairs(message.updated) do + table.insert(idsToGet, id) + end + + for _, id in ipairs(message.removed) do + table.insert(idsToGet, id) + end + + coroutine.wrap(function() + -- TODO: This section is a mess + local _, response = assert(api:read(idsToGet):await()) + + for _, id in ipairs(idsToGet) do + local data = response.instances[id] + local instance = instanceMap.fromIds[id] + + if data == nil then + -- TOO: Destroy descendants too + if instance ~= nil then + instanceMap:removeInstance(instance) + instance:Destroy() + end + else + if instance ~= nil then + reconcile(response.instances, instanceMap, id, instance) + else + error("TODO: Crawl up to nearest parent, use that?") + end + end + end + end)() end) api:connect() @@ -47,7 +179,8 @@ function Session.new() return api:read({api.rootInstanceId}) end) :andThen(function(response) - reify(response.instances, api.rootInstanceId, game.ReplicatedStorage) + reconcile(response.instances, instanceMap, api.rootInstanceId, game) + -- reify(response.instances, instanceMap, api.rootInstanceId, game.ReplicatedStorage) return api:retrieveMessages() end) :catch(function(message) @@ -57,4 +190,4 @@ function Session.new() return setmetatable(self, Session) end -return Session +return Session \ No newline at end of file From 645ab0ae983b9159364ea03cfc63a3f6a4d34ee1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Dec 2018 18:38:29 -0800 Subject: [PATCH 0272/1504] Fix up test scratch project snippet to accept a project as an arg --- server/test-scratch-project | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/server/test-scratch-project b/server/test-scratch-project index a9d498ee..f227ef13 100644 --- a/server/test-scratch-project +++ b/server/test-scratch-project @@ -2,11 +2,17 @@ set -e +if [ ! -d "../test-projects/$1" ] +then + echo "Pick a project that exists!" + exit 1 +fi + if [ -d "scratch" ] then rm -rf scratch fi mkdir -p scratch -cp -r ../test-projects/test-model scratch -cargo run -- serve scratch/test-model \ No newline at end of file +cp -r "../test-projects/$1" scratch +cargo run -- serve "scratch/$1" \ No newline at end of file From 2f1aadd497863328c139eedb76d4cce87f4bb264 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 29 Dec 2018 22:59:41 -0800 Subject: [PATCH 0273/1504] Tinkering with zero testing --- plugin/src/ApiContext.lua | 68 ++++++++++++++++++++++----------------- plugin/src/Session.lua | 4 +-- 2 files changed, 41 insertions(+), 31 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 54362a39..0c7b5d92 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -15,18 +15,17 @@ ApiContext.Error = { setmetatable(ApiContext.Error, { __index = function(_, key) - error("Invalid API.Error name " .. key, 2) + error("Invalid ApiContext.Error name " .. key, 2) end }) -- TODO: Switch to onMessages and batch processing -function ApiContext.new(baseUrl, onMessage) +function ApiContext.new(baseUrl) assert(type(baseUrl) == "string") - assert(type(onMessage) == "function") - local context = { + local self = { baseUrl = baseUrl, - onMessage = onMessage, + onMessageCallback = nil, serverId = nil, rootInstanceId = nil, connected = false, @@ -34,9 +33,13 @@ function ApiContext.new(baseUrl, onMessage) partitionRoutes = nil, } - setmetatable(context, ApiContext) + setmetatable(self, ApiContext) - return context + return self +end + +function ApiContext:onMessage(callback) + self.onMessageCallback = callback end function ApiContext:connect() @@ -77,6 +80,11 @@ function ApiContext:read(ids) local url = ("%s/api/read/%s"):format(self.baseUrl, table.concat(ids, ",")) return Http.get(url) + :catch(function(err) + self.connected = false + + return Promise.reject(err) + end) :andThen(function(response) local body = response:json() @@ -87,10 +95,6 @@ function ApiContext:read(ids) self.messageCursor = body.messageCursor return body - end, function(err) - self.connected = false - - return Promise.reject(err) end) end @@ -102,23 +106,7 @@ function ApiContext:retrieveMessages() local url = ("%s/api/subscribe/%s"):format(self.baseUrl, self.messageCursor) return Http.get(url) - :andThen(function(response) - local body = response:json() - - if body.serverId ~= self.serverId then - return Promise.reject("Server changed ID") - end - - -- TODO: Wait for all messages to be processed before resuming. - -- This callback will return a promise! - for _, message in ipairs(body.messages) do - self.onMessage(message) - end - - self.messageCursor = body.messageCursor - - return self:retrieveMessages() - end, function(err) + :catch(function(err) if err.type == HttpError.Error.Timeout then return self:retrieveMessages() end @@ -127,6 +115,28 @@ function ApiContext:retrieveMessages() return Promise.reject(err) end) + :andThen(function(response) + local body = response:json() + + if body.serverId ~= self.serverId then + return Promise.reject("Server changed ID") + end + + local promise = Promise.resolve(nil) + + for _, message in ipairs(body.messages) do + promise = promise:andThen(function() + return self.onMessageCalllback(message) + end) + end + + self.messageCursor = body.messageCursor + + return promise + end) + :andThen(function() + return self:retrieveMessages() + end) end -return ApiContext +return ApiContext \ No newline at end of file diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 17af009e..893bd76b 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -132,9 +132,9 @@ function Session.new() local instanceMap = makeInstanceMap() - local api + local api = ApiContext.new(REMOTE_URL) - api = ApiContext.new(REMOTE_URL, function(message) + ApiContext:onMessage(function(message) local idsToGet = {} for _, id in ipairs(message.added) do From c0ffbd360eed8b47355053b66de6f666e5a7e43d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 30 Dec 2018 20:21:46 -0800 Subject: [PATCH 0274/1504] Fix name assignment for sync points --- server/src/rbx_session.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index e1a0df67..119965ea 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -158,8 +158,12 @@ fn construct_project_node<'a>( construct_instance_node(imfs, instance_name, node) }, ProjectNode::SyncPoint(node) => { - snapshot_instances_from_imfs(imfs, &node.path) - .expect("Could not reify nodes from Imfs") + let mut snapshot = snapshot_instances_from_imfs(imfs, &node.path) + .expect("Could not reify nodes from Imfs"); + + snapshot.name = Cow::Borrowed(instance_name); + + snapshot }, } } From fff71e1de07e14d72257f707318548d036f06e73 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 30 Dec 2018 21:25:22 -0800 Subject: [PATCH 0275/1504] Accept connections from all addresses --- server/src/web.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/web.rs b/server/src/web.rs index d1974bed..1273ffff 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -165,7 +165,7 @@ impl Server { } pub fn listen(self, port: u64) { - let address = format!("localhost:{}", port); + let address = format!("0.0.0.0:{}", port); rouille::start_server(address, move |request| self.handle_request(request)); } From 01dd603bd5f77230edc39d2ce8b17bb322a18106 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 30 Dec 2018 21:25:40 -0800 Subject: [PATCH 0276/1504] Vertically align output for monospace consoles --- plugin/src/Logging.lua | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/plugin/src/Logging.lua b/plugin/src/Logging.lua index 30c54c78..c57130b5 100644 --- a/plugin/src/Logging.lua +++ b/plugin/src/Logging.lua @@ -26,25 +26,29 @@ local function addTags(tag, message) return tag .. message:gsub("\n", "\n" .. tag) end +local INFO_TAG = (" "):rep(15) .. "[Rojo-Info] " +local TRACE_TAG = (" "):rep(15) .. "[Rojo-Trace] " +local WARN_TAG = "[Rojo-Warn] " + local Log = {} Log.Level = Level function Log.trace(template, ...) if getLogLevel() >= Level.Trace then - print(addTags("[Rojo-Trace] ", string.format(template, ...))) + print(addTags(TRACE_TAG, string.format(template, ...))) end end function Log.info(template, ...) if getLogLevel() >= Level.Info then - print(addTags("[Rojo-Info] ", string.format(template, ...))) + print(addTags(INFO_TAG, string.format(template, ...))) end end function Log.warn(template, ...) if getLogLevel() >= Level.Warning then - warn(addTags("[Rojo-Warn] ", string.format(template, ...))) + warn(addTags(WARN_TAG, string.format(template, ...))) end end From 4453211c0dc4f359c94abba321a819ed19a15f0f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 30 Dec 2018 22:43:23 -0800 Subject: [PATCH 0277/1504] Server component of config maps --- server/src/project.rs | 12 ++++++++++-- server/src/rbx_session.rs | 22 +++++++++++++++++----- server/src/rbx_snapshot.rs | 29 +++++++++++++++++++++++------ server/src/web.rs | 6 +++--- 4 files changed, 53 insertions(+), 16 deletions(-) diff --git a/server/src/project.rs b/server/src/project.rs index d99d3f15..b5477d77 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -40,7 +40,7 @@ enum SourceProjectNode { impl SourceProjectNode { pub fn into_project_node(self, project_file_location: &Path) -> ProjectNode { match self { - SourceProjectNode::Instance { class_name, mut children, properties, .. } => { + SourceProjectNode::Instance { class_name, mut children, properties, ignore_unknown } => { let mut new_children = HashMap::new(); for (node_name, node) in children.drain() { @@ -51,6 +51,9 @@ impl SourceProjectNode { class_name, children: new_children, properties, + config: InstanceProjectNodeConfig { + ignore_unknown, + }, }) }, SourceProjectNode::SyncPoint { path: source_path } => { @@ -126,6 +129,11 @@ pub struct ProjectInitError; #[fail(display = "Project save error")] pub struct ProjectSaveError; +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct InstanceProjectNodeConfig { + pub ignore_unknown: bool, +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] pub enum ProjectNode { @@ -139,7 +147,7 @@ pub struct InstanceProjectNode { pub class_name: String, pub children: HashMap, pub properties: HashMap, - // ignore_unknown: bool, + pub config: InstanceProjectNodeConfig, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 119965ea..97bb6b50 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -9,7 +9,7 @@ use std::{ use rbx_tree::{RbxTree, RbxValue, RbxId}; use crate::{ - project::{Project, ProjectNode, InstanceProjectNode}, + project::{Project, ProjectNode, InstanceProjectNode, InstanceProjectNodeConfig}, message_queue::MessageQueue, imfs::{Imfs, ImfsItem, ImfsFile}, path_map::PathMap, @@ -19,6 +19,7 @@ use crate::{ pub struct RbxSession { tree: RbxTree, path_map: PathMap, + config_map: HashMap, message_queue: Arc>, imfs: Arc>, project: Arc, @@ -31,15 +32,17 @@ impl RbxSession { message_queue: Arc>, ) -> RbxSession { let mut path_map = PathMap::new(); + let mut config_map = HashMap::new(); let tree = { let temp_imfs = imfs.lock().unwrap(); - construct_initial_tree(&project, &temp_imfs, &mut path_map) + construct_initial_tree(&project, &temp_imfs, &mut path_map, &mut config_map) }; RbxSession { tree, path_map, + config_map, message_queue, imfs, project, @@ -60,7 +63,7 @@ impl RbxSession { let snapshot = snapshot_instances_from_imfs(&imfs, &closest_path) .expect("Could not generate instance snapshot"); - reconcile_subtree(&mut self.tree, instance_id, &snapshot, &mut self.path_map, &mut changes); + reconcile_subtree(&mut self.tree, instance_id, &snapshot, &mut self.path_map, &mut self.config_map, &mut changes); } if !changes.is_empty() { @@ -124,17 +127,23 @@ impl RbxSession { pub fn get_tree(&self) -> &RbxTree { &self.tree } + + pub fn get_config_map(&self) -> &HashMap { + &self.config_map + } } pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { let mut path_map = PathMap::new(); - construct_initial_tree(project, imfs, &mut path_map) + let mut config_map = HashMap::new(); + construct_initial_tree(project, imfs, &mut path_map, &mut config_map) } fn construct_initial_tree( project: &Project, imfs: &Imfs, path_map: &mut PathMap, + config_map: &mut HashMap, ) -> RbxTree { let snapshot = construct_project_node( imfs, @@ -143,7 +152,7 @@ fn construct_initial_tree( ); let mut changes = InstanceChanges::default(); - let tree = reify_root(&snapshot, path_map, &mut changes); + let tree = reify_root(&snapshot, path_map, config_map, &mut changes); tree } @@ -185,6 +194,7 @@ fn construct_instance_node<'a>( properties: HashMap::new(), children, source_path: None, + config: Some(project_node.config.clone()), } } @@ -243,6 +253,7 @@ fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option< properties, children: Vec::new(), source_path: Some(file.path.clone()), + config: None, }) }, ImfsItem::Directory(directory) => { @@ -257,6 +268,7 @@ fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option< properties: HashMap::new(), children: Vec::new(), source_path: Some(directory.path.clone()), + config: None, } }; diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index f81161d7..842c3f6c 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -7,7 +7,10 @@ use std::{ use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; -use crate::path_map::PathMap; +use crate::{ + path_map::PathMap, + project::InstanceProjectNodeConfig, +}; #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct InstanceChanges { @@ -28,11 +31,13 @@ pub struct RbxSnapshotInstance<'a> { pub properties: HashMap, pub children: Vec>, pub source_path: Option, + pub config: Option, } pub fn reify_root( snapshot: &RbxSnapshotInstance, path_map: &mut PathMap, + config_map: &mut HashMap, changes: &mut InstanceChanges, ) -> RbxTree { let instance = reify_core(snapshot); @@ -43,10 +48,14 @@ pub fn reify_root( path_map.insert(source_path.clone(), root_id); } + if let Some(config) = &snapshot.config { + config_map.insert(root_id, config.clone()); + } + changes.added.insert(root_id); for child in &snapshot.children { - reify_subtree(child, &mut tree, root_id, path_map, changes); + reify_subtree(child, &mut tree, root_id, path_map, config_map, changes); } tree @@ -57,6 +66,7 @@ pub fn reify_subtree( tree: &mut RbxTree, parent_id: RbxId, path_map: &mut PathMap, + config_map: &mut HashMap, changes: &mut InstanceChanges, ) { let instance = reify_core(snapshot); @@ -66,10 +76,14 @@ pub fn reify_subtree( path_map.insert(source_path.clone(), id); } + if let Some(config) = &snapshot.config { + config_map.insert(id, config.clone()); + } + changes.added.insert(id); for child in &snapshot.children { - reify_subtree(child, tree, id, path_map, changes); + reify_subtree(child, tree, id, path_map, config_map, changes); } } @@ -78,13 +92,14 @@ pub fn reconcile_subtree( id: RbxId, snapshot: &RbxSnapshotInstance, path_map: &mut PathMap, + config_map: &mut HashMap, changes: &mut InstanceChanges, ) { if reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot) { changes.updated.insert(id); } - reconcile_instance_children(tree, id, snapshot, path_map, changes); + reconcile_instance_children(tree, id, snapshot, path_map, config_map, changes); } fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstance { @@ -165,6 +180,7 @@ fn reconcile_instance_children( id: RbxId, snapshot: &RbxSnapshotInstance, path_map: &mut PathMap, + config_map: &mut HashMap, changes: &mut InstanceChanges, ) { let children_ids = tree.get_instance(id).unwrap().get_children_ids().to_vec(); @@ -195,18 +211,19 @@ fn reconcile_instance_children( } for child_snapshot in &children_to_add { - reify_subtree(child_snapshot, tree, id, path_map, changes); + reify_subtree(child_snapshot, tree, id, path_map, config_map, changes); } for child_id in &children_to_remove { if let Some(subtree) = tree.remove_instance(*child_id) { for id in subtree.iter_all_ids() { + config_map.remove(&id); changes.removed.insert(id); } } } for (child_id, child_snapshot) in &children_to_update { - reconcile_subtree(tree, *child_id, child_snapshot, path_map, changes); + reconcile_subtree(tree, *child_id, child_snapshot, path_map, config_map, changes); } } \ No newline at end of file diff --git a/server/src/web.rs b/server/src/web.rs index 1273ffff..0985a975 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -15,7 +15,7 @@ use rbx_tree::{RbxId, RootedRbxInstance}; use crate::{ session::Session, session_id::SessionId, - project::Project, + project::InstanceProjectNodeConfig, rbx_snapshot::InstanceChanges, }; @@ -26,7 +26,7 @@ pub struct ServerInfoResponse<'a> { pub server_version: &'a str, pub protocol_version: u64, pub root_instance_id: RbxId, - pub project: Cow<'a, Project>, + pub config_map: Cow<'a, HashMap>, } #[derive(Debug, Serialize, Deserialize)] @@ -78,7 +78,7 @@ impl Server { protocol_version: 2, session_id: self.session.session_id, root_instance_id: tree.get_root_id(), - project: Cow::Borrowed(&self.session.project), + config_map: Cow::Borrowed(rbx_session.get_config_map()), }) }, From 2e42c28485669ed0443ef6b7795a5b4330c6b68b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 30 Dec 2018 22:57:08 -0800 Subject: [PATCH 0278/1504] Add execute permission to test-scratch-project --- server/test-scratch-project | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 server/test-scratch-project diff --git a/server/test-scratch-project b/server/test-scratch-project old mode 100644 new mode 100755 From b6a2b7dded7a02ab0eb7bc8527be1eaf9dcc0493 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 30 Dec 2018 22:57:22 -0800 Subject: [PATCH 0279/1504] Fix naming for InstanceProjectNodeConfig --- server/src/project.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/project.rs b/server/src/project.rs index b5477d77..87f0b3ba 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -130,6 +130,7 @@ pub struct ProjectInitError; pub struct ProjectSaveError; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct InstanceProjectNodeConfig { pub ignore_unknown: bool, } From 474d877290f48dbc482008b6a206b5d51ecbaeb1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 30 Dec 2018 22:58:12 -0800 Subject: [PATCH 0280/1504] Plugin half of configMap --- plugin/src/ApiContext.lua | 4 +++- plugin/src/Session.lua | 27 +++++++++++++++------------ 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 0c7b5d92..c8aab107 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -28,6 +28,7 @@ function ApiContext.new(baseUrl) onMessageCallback = nil, serverId = nil, rootInstanceId = nil, + configMap = nil, connected = false, messageCursor = -1, partitionRoutes = nil, @@ -69,6 +70,7 @@ function ApiContext:connect() self.connected = true self.partitionRoutes = body.partitions self.rootInstanceId = body.rootInstanceId + self.configMap = body.configMap end) end @@ -126,7 +128,7 @@ function ApiContext:retrieveMessages() for _, message in ipairs(body.messages) do promise = promise:andThen(function() - return self.onMessageCalllback(message) + return self.onMessageCallback(message) end) end diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 893bd76b..b32fbdeb 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -46,12 +46,15 @@ local function setProperty(instance, key, value) end end --- TODO: Pull this from project configuration instead -local function shouldClearUnknown(instance) - return instance.ClassName ~= "DataModel" and instance.ClassName ~= "ReplicatedStorage" +local function shouldClearUnknown(id, configMap) + if configMap[id] then + return not configMap[id].ignoreUnknown + else + return true + end end -local function reify(instanceData, instanceMap, id, parent) +local function reify(instanceData, instanceMap, configMap, id, parent) local data = instanceData[id] local instance = Instance.new(data.ClassName) @@ -64,7 +67,7 @@ local function reify(instanceData, instanceMap, id, parent) instance.Name = data.Name for _, childId in ipairs(data.Children) do - reify(instanceData, instanceMap, childId, instance) + reify(instanceData, instanceMap, configMap, childId, instance) end setProperty(instance, "Parent", parent) @@ -73,7 +76,7 @@ local function reify(instanceData, instanceMap, id, parent) return instance end -local function reconcile(instanceData, instanceMap, id, existingInstance) +local function reconcile(instanceData, instanceMap, configMap, id, existingInstance) local data = instanceData[id] assert(data.ClassName == existingInstance.ClassName) @@ -108,13 +111,13 @@ local function reconcile(instanceData, instanceMap, id, existingInstance) if existingChildInstance ~= nil then unvisitedExistingChildren[existingChildInstance] = nil - reconcile(instanceData, instanceMap, childId, existingChildInstance) + reconcile(instanceData, instanceMap, configMap, childId, existingChildInstance) else - reify(instanceData, instanceMap, childId, existingInstance) + reify(instanceData, instanceMap, configMap, childId, existingInstance) end end - if shouldClearUnknown(existingInstance) then + if shouldClearUnknown(id, configMap) then for existingChildInstance in pairs(unvisitedExistingChildren) do instanceMap:removeInstance(existingChildInstance) existingChildInstance:Destroy() @@ -165,7 +168,7 @@ function Session.new() end else if instance ~= nil then - reconcile(response.instances, instanceMap, id, instance) + reconcile(response.instances, instanceMap, api.configMap, id, instance) else error("TODO: Crawl up to nearest parent, use that?") end @@ -179,8 +182,8 @@ function Session.new() return api:read({api.rootInstanceId}) end) :andThen(function(response) - reconcile(response.instances, instanceMap, api.rootInstanceId, game) - -- reify(response.instances, instanceMap, api.rootInstanceId, game.ReplicatedStorage) + reconcile(response.instances, instanceMap, api.configMap, api.rootInstanceId, game) + -- reify(response.instances, instanceMap, configMap, api.rootInstanceId, game.ReplicatedStorage) return api:retrieveMessages() end) :catch(function(message) From 3be598808330a5498f27823acb118a37a1ab6d98 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Jan 2019 14:13:21 -0800 Subject: [PATCH 0281/1504] config_map -> instance_metadata_map --- plugin/src/ApiContext.lua | 4 ++-- plugin/src/Session.lua | 24 ++++++++++++------------ server/src/rbx_session.rs | 22 +++++++++++----------- server/src/web.rs | 4 ++-- 4 files changed, 27 insertions(+), 27 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index c8aab107..d7a5b6d6 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -28,7 +28,7 @@ function ApiContext.new(baseUrl) onMessageCallback = nil, serverId = nil, rootInstanceId = nil, - configMap = nil, + instanceMetadataMap = nil, connected = false, messageCursor = -1, partitionRoutes = nil, @@ -70,7 +70,7 @@ function ApiContext:connect() self.connected = true self.partitionRoutes = body.partitions self.rootInstanceId = body.rootInstanceId - self.configMap = body.configMap + self.instanceMetadataMap = body.instanceMetadataMap end) end diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index b32fbdeb..89691817 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -46,15 +46,15 @@ local function setProperty(instance, key, value) end end -local function shouldClearUnknown(id, configMap) - if configMap[id] then - return not configMap[id].ignoreUnknown +local function shouldClearUnknown(id, instanceMetadataMap) + if instanceMetadataMap[id] then + return not instanceMetadataMap[id].ignoreUnknown else return true end end -local function reify(instanceData, instanceMap, configMap, id, parent) +local function reify(instanceData, instanceMap, instanceMetadataMap, id, parent) local data = instanceData[id] local instance = Instance.new(data.ClassName) @@ -67,7 +67,7 @@ local function reify(instanceData, instanceMap, configMap, id, parent) instance.Name = data.Name for _, childId in ipairs(data.Children) do - reify(instanceData, instanceMap, configMap, childId, instance) + reify(instanceData, instanceMap, instanceMetadataMap, childId, instance) end setProperty(instance, "Parent", parent) @@ -76,7 +76,7 @@ local function reify(instanceData, instanceMap, configMap, id, parent) return instance end -local function reconcile(instanceData, instanceMap, configMap, id, existingInstance) +local function reconcile(instanceData, instanceMap, instanceMetadataMap, id, existingInstance) local data = instanceData[id] assert(data.ClassName == existingInstance.ClassName) @@ -111,13 +111,13 @@ local function reconcile(instanceData, instanceMap, configMap, id, existingInsta if existingChildInstance ~= nil then unvisitedExistingChildren[existingChildInstance] = nil - reconcile(instanceData, instanceMap, configMap, childId, existingChildInstance) + reconcile(instanceData, instanceMap, instanceMetadataMap, childId, existingChildInstance) else - reify(instanceData, instanceMap, configMap, childId, existingInstance) + reify(instanceData, instanceMap, instanceMetadataMap, childId, existingInstance) end end - if shouldClearUnknown(id, configMap) then + if shouldClearUnknown(id, instanceMetadataMap) then for existingChildInstance in pairs(unvisitedExistingChildren) do instanceMap:removeInstance(existingChildInstance) existingChildInstance:Destroy() @@ -168,7 +168,7 @@ function Session.new() end else if instance ~= nil then - reconcile(response.instances, instanceMap, api.configMap, id, instance) + reconcile(response.instances, instanceMap, api.instanceMetadataMap, id, instance) else error("TODO: Crawl up to nearest parent, use that?") end @@ -182,8 +182,8 @@ function Session.new() return api:read({api.rootInstanceId}) end) :andThen(function(response) - reconcile(response.instances, instanceMap, api.configMap, api.rootInstanceId, game) - -- reify(response.instances, instanceMap, configMap, api.rootInstanceId, game.ReplicatedStorage) + reconcile(response.instances, instanceMap, api.instanceMetadataMap, api.rootInstanceId, game) + -- reify(response.instances, instanceMap, instanceMetadataMap, api.rootInstanceId, game.ReplicatedStorage) return api:retrieveMessages() end) :catch(function(message) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 97bb6b50..0251fe64 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -19,7 +19,7 @@ use crate::{ pub struct RbxSession { tree: RbxTree, path_map: PathMap, - config_map: HashMap, + instance_metadata_map: HashMap, message_queue: Arc>, imfs: Arc>, project: Arc, @@ -32,17 +32,17 @@ impl RbxSession { message_queue: Arc>, ) -> RbxSession { let mut path_map = PathMap::new(); - let mut config_map = HashMap::new(); + let mut instance_metadata_map = HashMap::new(); let tree = { let temp_imfs = imfs.lock().unwrap(); - construct_initial_tree(&project, &temp_imfs, &mut path_map, &mut config_map) + construct_initial_tree(&project, &temp_imfs, &mut path_map, &mut instance_metadata_map) }; RbxSession { tree, path_map, - config_map, + instance_metadata_map, message_queue, imfs, project, @@ -63,7 +63,7 @@ impl RbxSession { let snapshot = snapshot_instances_from_imfs(&imfs, &closest_path) .expect("Could not generate instance snapshot"); - reconcile_subtree(&mut self.tree, instance_id, &snapshot, &mut self.path_map, &mut self.config_map, &mut changes); + reconcile_subtree(&mut self.tree, instance_id, &snapshot, &mut self.path_map, &mut self.instance_metadata_map, &mut changes); } if !changes.is_empty() { @@ -128,22 +128,22 @@ impl RbxSession { &self.tree } - pub fn get_config_map(&self) -> &HashMap { - &self.config_map + pub fn get_instance_metadata_map(&self) -> &HashMap { + &self.instance_metadata_map } } pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { let mut path_map = PathMap::new(); - let mut config_map = HashMap::new(); - construct_initial_tree(project, imfs, &mut path_map, &mut config_map) + let mut instance_metadata_map = HashMap::new(); + construct_initial_tree(project, imfs, &mut path_map, &mut instance_metadata_map) } fn construct_initial_tree( project: &Project, imfs: &Imfs, path_map: &mut PathMap, - config_map: &mut HashMap, + instance_metadata_map: &mut HashMap, ) -> RbxTree { let snapshot = construct_project_node( imfs, @@ -152,7 +152,7 @@ fn construct_initial_tree( ); let mut changes = InstanceChanges::default(); - let tree = reify_root(&snapshot, path_map, config_map, &mut changes); + let tree = reify_root(&snapshot, path_map, instance_metadata_map, &mut changes); tree } diff --git a/server/src/web.rs b/server/src/web.rs index 0985a975..2ab8620c 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -26,7 +26,7 @@ pub struct ServerInfoResponse<'a> { pub server_version: &'a str, pub protocol_version: u64, pub root_instance_id: RbxId, - pub config_map: Cow<'a, HashMap>, + pub instance_metadata_map: Cow<'a, HashMap>, } #[derive(Debug, Serialize, Deserialize)] @@ -78,7 +78,7 @@ impl Server { protocol_version: 2, session_id: self.session.session_id, root_instance_id: tree.get_root_id(), - config_map: Cow::Borrowed(rbx_session.get_config_map()), + instance_metadata_map: Cow::Borrowed(rbx_session.get_instance_metadata_map()), }) }, From 20e9688268278b481c7337f8e00df9fd83379e91 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Jan 2019 15:59:26 -0800 Subject: [PATCH 0282/1504] Fininsh config -> metadata migration --- server/src/project.rs | 14 +++++++++++--- server/src/rbx_session.rs | 14 +++++++------- server/src/rbx_snapshot.rs | 32 ++++++++++++++++---------------- server/src/web.rs | 4 ++-- server/tests/read_projects.rs | 2 ++ 5 files changed, 38 insertions(+), 28 deletions(-) diff --git a/server/src/project.rs b/server/src/project.rs index 87f0b3ba..ce643427 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -51,7 +51,7 @@ impl SourceProjectNode { class_name, children: new_children, properties, - config: InstanceProjectNodeConfig { + metadata: InstanceProjectNodeMetadata { ignore_unknown, }, }) @@ -131,10 +131,18 @@ pub struct ProjectSaveError; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct InstanceProjectNodeConfig { +pub struct InstanceProjectNodeMetadata { pub ignore_unknown: bool, } +impl Default for InstanceProjectNodeMetadata { + fn default() -> InstanceProjectNodeMetadata { + InstanceProjectNodeMetadata { + ignore_unknown: true, + } + } +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(tag = "type")] pub enum ProjectNode { @@ -148,7 +156,7 @@ pub struct InstanceProjectNode { pub class_name: String, pub children: HashMap, pub properties: HashMap, - pub config: InstanceProjectNodeConfig, + pub metadata: InstanceProjectNodeMetadata, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 0251fe64..3a7fd31a 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -9,7 +9,7 @@ use std::{ use rbx_tree::{RbxTree, RbxValue, RbxId}; use crate::{ - project::{Project, ProjectNode, InstanceProjectNode, InstanceProjectNodeConfig}, + project::{Project, ProjectNode, InstanceProjectNode, InstanceProjectNodeMetadata}, message_queue::MessageQueue, imfs::{Imfs, ImfsItem, ImfsFile}, path_map::PathMap, @@ -19,7 +19,7 @@ use crate::{ pub struct RbxSession { tree: RbxTree, path_map: PathMap, - instance_metadata_map: HashMap, + instance_metadata_map: HashMap, message_queue: Arc>, imfs: Arc>, project: Arc, @@ -128,7 +128,7 @@ impl RbxSession { &self.tree } - pub fn get_instance_metadata_map(&self) -> &HashMap { + pub fn get_instance_metadata_map(&self) -> &HashMap { &self.instance_metadata_map } } @@ -143,7 +143,7 @@ fn construct_initial_tree( project: &Project, imfs: &Imfs, path_map: &mut PathMap, - instance_metadata_map: &mut HashMap, + instance_metadata_map: &mut HashMap, ) -> RbxTree { let snapshot = construct_project_node( imfs, @@ -194,7 +194,7 @@ fn construct_instance_node<'a>( properties: HashMap::new(), children, source_path: None, - config: Some(project_node.config.clone()), + metadata: Some(project_node.metadata.clone()), } } @@ -253,7 +253,7 @@ fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option< properties, children: Vec::new(), source_path: Some(file.path.clone()), - config: None, + metadata: None, }) }, ImfsItem::Directory(directory) => { @@ -268,7 +268,7 @@ fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option< properties: HashMap::new(), children: Vec::new(), source_path: Some(directory.path.clone()), - config: None, + metadata: None, } }; diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 842c3f6c..55de7bbf 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -9,7 +9,7 @@ use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; use crate::{ path_map::PathMap, - project::InstanceProjectNodeConfig, + project::InstanceProjectNodeMetadata, }; #[derive(Debug, Clone, Default, Serialize, Deserialize)] @@ -31,13 +31,13 @@ pub struct RbxSnapshotInstance<'a> { pub properties: HashMap, pub children: Vec>, pub source_path: Option, - pub config: Option, + pub metadata: Option, } pub fn reify_root( snapshot: &RbxSnapshotInstance, path_map: &mut PathMap, - config_map: &mut HashMap, + instance_metadata_map: &mut HashMap, changes: &mut InstanceChanges, ) -> RbxTree { let instance = reify_core(snapshot); @@ -48,14 +48,14 @@ pub fn reify_root( path_map.insert(source_path.clone(), root_id); } - if let Some(config) = &snapshot.config { - config_map.insert(root_id, config.clone()); + if let Some(metadata) = &snapshot.metadata { + instance_metadata_map.insert(root_id, metadata.clone()); } changes.added.insert(root_id); for child in &snapshot.children { - reify_subtree(child, &mut tree, root_id, path_map, config_map, changes); + reify_subtree(child, &mut tree, root_id, path_map, instance_metadata_map, changes); } tree @@ -66,7 +66,7 @@ pub fn reify_subtree( tree: &mut RbxTree, parent_id: RbxId, path_map: &mut PathMap, - config_map: &mut HashMap, + instance_metadata_map: &mut HashMap, changes: &mut InstanceChanges, ) { let instance = reify_core(snapshot); @@ -76,14 +76,14 @@ pub fn reify_subtree( path_map.insert(source_path.clone(), id); } - if let Some(config) = &snapshot.config { - config_map.insert(id, config.clone()); + if let Some(metadata) = &snapshot.metadata { + instance_metadata_map.insert(id, metadata.clone()); } changes.added.insert(id); for child in &snapshot.children { - reify_subtree(child, tree, id, path_map, config_map, changes); + reify_subtree(child, tree, id, path_map, instance_metadata_map, changes); } } @@ -92,14 +92,14 @@ pub fn reconcile_subtree( id: RbxId, snapshot: &RbxSnapshotInstance, path_map: &mut PathMap, - config_map: &mut HashMap, + instance_metadata_map: &mut HashMap, changes: &mut InstanceChanges, ) { if reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot) { changes.updated.insert(id); } - reconcile_instance_children(tree, id, snapshot, path_map, config_map, changes); + reconcile_instance_children(tree, id, snapshot, path_map, instance_metadata_map, changes); } fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstance { @@ -180,7 +180,7 @@ fn reconcile_instance_children( id: RbxId, snapshot: &RbxSnapshotInstance, path_map: &mut PathMap, - config_map: &mut HashMap, + instance_metadata_map: &mut HashMap, changes: &mut InstanceChanges, ) { let children_ids = tree.get_instance(id).unwrap().get_children_ids().to_vec(); @@ -211,19 +211,19 @@ fn reconcile_instance_children( } for child_snapshot in &children_to_add { - reify_subtree(child_snapshot, tree, id, path_map, config_map, changes); + reify_subtree(child_snapshot, tree, id, path_map, instance_metadata_map, changes); } for child_id in &children_to_remove { if let Some(subtree) = tree.remove_instance(*child_id) { for id in subtree.iter_all_ids() { - config_map.remove(&id); + instance_metadata_map.remove(&id); changes.removed.insert(id); } } } for (child_id, child_snapshot) in &children_to_update { - reconcile_subtree(tree, *child_id, child_snapshot, path_map, config_map, changes); + reconcile_subtree(tree, *child_id, child_snapshot, path_map, instance_metadata_map, changes); } } \ No newline at end of file diff --git a/server/src/web.rs b/server/src/web.rs index 2ab8620c..7347f837 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -15,7 +15,7 @@ use rbx_tree::{RbxId, RootedRbxInstance}; use crate::{ session::Session, session_id::SessionId, - project::InstanceProjectNodeConfig, + project::InstanceProjectNodeMetadata, rbx_snapshot::InstanceChanges, }; @@ -26,7 +26,7 @@ pub struct ServerInfoResponse<'a> { pub server_version: &'a str, pub protocol_version: u64, pub root_instance_id: RbxId, - pub instance_metadata_map: Cow<'a, HashMap>, + pub instance_metadata_map: Cow<'a, HashMap>, } #[derive(Debug, Serialize, Deserialize)] diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index 6de207ea..3a180b75 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -66,6 +66,7 @@ fn single_sync_point() { class_name: "ReplicatedStorage".to_string(), children: replicated_storage_children, properties: HashMap::new(), + metadata: Default::default(), }); let mut root_children = HashMap::new(); @@ -75,6 +76,7 @@ fn single_sync_point() { class_name: "DataModel".to_string(), children: root_children, properties: HashMap::new(), + metadata: Default::default(), }); Project { From 45af35cccd2714dd8d19467fdb46e814740cc1fc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Jan 2019 17:02:46 -0800 Subject: [PATCH 0283/1504] Enable stable Rust again --- .travis.yml | 14 ++++++-------- README.md | 2 -- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/.travis.yml b/.travis.yml index ba811ce8..3a12362f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,18 +25,16 @@ matrix: - cd plugin - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install - # Stable builds can be re-enabled after 2018-12-06, when Rust 1.31 is stable + - language: rust + rust: stable - # - language: rust - # rust: stable - - # script: - # - cd server - # - cargo test --verbose + script: + - cd server + - cargo test --verbose - language: rust rust: beta script: - cd server - - cargo test --verbose + - cargo test --verbose \ No newline at end of file diff --git a/README.md b/README.md index df944095..05b09ba0 100644 --- a/README.md +++ b/README.md @@ -57,8 +57,6 @@ If you use a plugin that _isn't_ Rojo for syncing code, open an issue and let me ## Contributing The `master` branch is a rewrite known as **Epiphany**. It includes a breaking change to the project configuration format and an infrastructure overhaul. -Building Rojo requires the latest Rust beta in order to use **2018 Edition** features. Once Rust 1.31 is stable on **December 6, 2018**, Rojo `master` will compile on Rust stable again. - Pull requests are welcome! All pull requests are run against a test suite on Travis CI. That test suite should always pass! From a3cc39cd924e7891e4cb62b137c80a3b4cfc93c2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Jan 2019 23:46:15 -0800 Subject: [PATCH 0284/1504] Attempt to preserve sync point names --- server/src/rbx_session.rs | 47 +++++++++++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 12 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 3a7fd31a..e695db04 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -1,7 +1,7 @@ use std::{ borrow::Cow, collections::{HashMap, HashSet}, - path::Path, + path::{Path, PathBuf}, sync::{Arc, Mutex}, str, }; @@ -20,6 +20,7 @@ pub struct RbxSession { tree: RbxTree, path_map: PathMap, instance_metadata_map: HashMap, + sync_point_names: HashMap, message_queue: Arc>, imfs: Arc>, project: Arc, @@ -31,18 +32,20 @@ impl RbxSession { imfs: Arc>, message_queue: Arc>, ) -> RbxSession { + let mut sync_point_names = HashMap::new(); let mut path_map = PathMap::new(); let mut instance_metadata_map = HashMap::new(); let tree = { let temp_imfs = imfs.lock().unwrap(); - construct_initial_tree(&project, &temp_imfs, &mut path_map, &mut instance_metadata_map) + construct_initial_tree(&project, &temp_imfs, &mut path_map, &mut instance_metadata_map, &mut sync_point_names) }; RbxSession { tree, path_map, instance_metadata_map, + sync_point_names, message_queue, imfs, project, @@ -60,7 +63,7 @@ impl RbxSession { let closest_path = self.path_map.descend(root_path, path); let &instance_id = self.path_map.get(&closest_path).unwrap(); - let snapshot = snapshot_instances_from_imfs(&imfs, &closest_path) + let snapshot = snapshot_instances_from_imfs(&imfs, &closest_path, &mut self.sync_point_names) .expect("Could not generate instance snapshot"); reconcile_subtree(&mut self.tree, instance_id, &snapshot, &mut self.path_map, &mut self.instance_metadata_map, &mut changes); @@ -136,7 +139,8 @@ impl RbxSession { pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { let mut path_map = PathMap::new(); let mut instance_metadata_map = HashMap::new(); - construct_initial_tree(project, imfs, &mut path_map, &mut instance_metadata_map) + let mut sync_point_names = HashMap::new(); + construct_initial_tree(project, imfs, &mut path_map, &mut instance_metadata_map, &mut sync_point_names) } fn construct_initial_tree( @@ -144,11 +148,13 @@ fn construct_initial_tree( imfs: &Imfs, path_map: &mut PathMap, instance_metadata_map: &mut HashMap, + sync_point_names: &mut HashMap, ) -> RbxTree { let snapshot = construct_project_node( imfs, &project.name, &project.tree, + sync_point_names, ); let mut changes = InstanceChanges::default(); @@ -161,16 +167,18 @@ fn construct_project_node<'a>( imfs: &'a Imfs, instance_name: &'a str, project_node: &'a ProjectNode, + sync_point_names: &mut HashMap, ) -> RbxSnapshotInstance<'a> { match project_node { ProjectNode::Instance(node) => { - construct_instance_node(imfs, instance_name, node) + construct_instance_node(imfs, instance_name, node, sync_point_names) }, ProjectNode::SyncPoint(node) => { - let mut snapshot = snapshot_instances_from_imfs(imfs, &node.path) + let mut snapshot = snapshot_instances_from_imfs(imfs, &node.path, sync_point_names) .expect("Could not reify nodes from Imfs"); snapshot.name = Cow::Borrowed(instance_name); + sync_point_names.insert(node.path.clone(), instance_name.to_string()); snapshot }, @@ -181,11 +189,12 @@ fn construct_instance_node<'a>( imfs: &'a Imfs, instance_name: &'a str, project_node: &'a InstanceProjectNode, + sync_point_names: &mut HashMap, ) -> RbxSnapshotInstance<'a> { let mut children = Vec::new(); for (child_name, child_project_node) in &project_node.children { - children.push(construct_project_node(imfs, child_name, child_project_node)); + children.push(construct_project_node(imfs, child_name, child_project_node, sync_point_names)); } RbxSnapshotInstance { @@ -228,11 +237,21 @@ fn classify_file(file: &ImfsFile) -> Option<(&str, FileType)> { } } -fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option> { +fn snapshot_instances_from_imfs<'a>( + imfs: &'a Imfs, + imfs_path: &Path, + sync_point_names: &HashMap, +) -> Option> { match imfs.get(imfs_path)? { ImfsItem::File(file) => { let (instance_name, file_type) = classify_file(file)?; + let instance_name = if let Some(actual_name) = sync_point_names.get(imfs_path) { + Cow::Owned(actual_name.clone()) + } else { + Cow::Borrowed(instance_name) + }; + let class_name = match file_type { FileType::ModuleScript => "ModuleScript", FileType::ServerScript => "Script", @@ -248,7 +267,7 @@ fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option< }); Some(RbxSnapshotInstance { - name: Cow::Borrowed(instance_name), + name: instance_name, class_name: Cow::Borrowed(class_name), properties, children: Vec::new(), @@ -260,7 +279,7 @@ fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option< let init_path = directory.path.join("init.lua"); let mut instance = if directory.children.contains(&init_path) { - snapshot_instances_from_imfs(imfs, &init_path)? + snapshot_instances_from_imfs(imfs, &init_path, sync_point_names)? } else { RbxSnapshotInstance { class_name: Cow::Borrowed("Folder"), @@ -272,11 +291,15 @@ fn snapshot_instances_from_imfs<'a>(imfs: &'a Imfs, imfs_path: &Path) -> Option< } }; - instance.name = Cow::Borrowed(directory.path.file_name()?.to_str()?); + instance.name = if let Some(actual_name) = sync_point_names.get(imfs_path) { + Cow::Owned(actual_name.clone()) + } else { + Cow::Borrowed(directory.path.file_name()?.to_str()?) + }; for child_path in &directory.children { if child_path != &init_path { - instance.children.push(snapshot_instances_from_imfs(imfs, child_path)?); + instance.children.push(snapshot_instances_from_imfs(imfs, child_path, sync_point_names)?); } } From 9bf5bd11e2ddc7dce625e76d3ca6412a6005ca0e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 2 Jan 2019 00:18:28 -0800 Subject: [PATCH 0285/1504] Add visualization stuff using GraphViz at /api/visualize --- server/src/lib.rs | 1 + server/src/visualize_tree.rs | 42 ++++++++++++++++++++++++++++++++++++ server/src/web.rs | 26 ++++++++++++++++++++++ 3 files changed, 69 insertions(+) create mode 100644 server/src/visualize_tree.rs diff --git a/server/src/lib.rs b/server/src/lib.rs index fd3d600b..80b7235c 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -18,5 +18,6 @@ pub mod rbx_session; pub mod rbx_snapshot; pub mod session; pub mod session_id; +pub mod visualize_tree; pub mod web; pub mod web_util; \ No newline at end of file diff --git a/server/src/visualize_tree.rs b/server/src/visualize_tree.rs new file mode 100644 index 00000000..9faee18f --- /dev/null +++ b/server/src/visualize_tree.rs @@ -0,0 +1,42 @@ +use std::fmt; +use rbx_tree::{RbxTree, RbxId}; + +static GRAPHVIZ_HEADER: &str = r#" +digraph RojoTree { + rankdir = "LR"; + graph [ + ranksep = "0.7", + nodesep = "0.5", + ]; + node [ + fontname = "Hack", + shape = "record", + ]; +"#; + +pub struct VisualizeTree<'a>(pub &'a RbxTree); + +impl<'a> fmt::Display for VisualizeTree<'a> { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + writeln!(output, "{}", GRAPHVIZ_HEADER)?; + + visualize_node(self.0, self.0.get_root_id(), output)?; + + writeln!(output, "}}")?; + + Ok(()) + } +} + +fn visualize_node(tree: &RbxTree, id: RbxId, output: &mut fmt::Formatter) -> fmt::Result { + let node = tree.get_instance(id).unwrap(); + + writeln!(output, " \"{}\" [label=\"{}\"]", id, node.name)?; + + for &child_id in node.get_children_ids() { + writeln!(output, " \"{}\" -> \"{}\"", id, child_id)?; + visualize_node(tree, child_id, output)?; + } + + Ok(()) +} \ No newline at end of file diff --git a/server/src/web.rs b/server/src/web.rs index 7347f837..f73ecef2 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -1,6 +1,8 @@ use std::{ borrow::Cow, collections::HashMap, + io::Write, + process::{Command, Stdio}, sync::{mpsc, Arc}, }; @@ -17,6 +19,7 @@ use crate::{ session_id::SessionId, project::InstanceProjectNodeMetadata, rbx_snapshot::InstanceChanges, + visualize_tree::VisualizeTree, }; #[derive(Debug, Serialize, Deserialize)] @@ -160,6 +163,29 @@ impl Server { }) }, + (GET) (/api/visualize) => { + let rbx_session = self.session.rbx_session.lock().unwrap(); + let tree = rbx_session.get_tree(); + + let dot_source = format!("{}", VisualizeTree(tree)); + + let mut child = Command::new("dot") + .arg("-Tsvg") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .expect("Failed to spawn GraphViz process -- make sure it's installed in order to use /api/visualize"); + + { + let stdin = child.stdin.as_mut().expect("Failed to open stdin"); + stdin.write_all(dot_source.as_bytes()).expect("Failed to write to stdin"); + } + + let output = child.wait_with_output().expect("Failed to read stdout"); + + Response::svg(String::from_utf8_lossy(&output.stdout)) + }, + _ => Response::empty_404() ) } From 9949a6c9eea4fa318beadd451267b86277b23cbb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 2 Jan 2019 00:21:19 -0800 Subject: [PATCH 0286/1504] Implement more reconciliation --- plugin/src/Session.lua | 115 ++++++++++++++++++++++++++++++----------- 1 file changed, 85 insertions(+), 30 deletions(-) diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 89691817..ca74e19c 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -1,6 +1,7 @@ -local Config = require(script.Parent.Config) local ApiContext = require(script.Parent.ApiContext) +local Config = require(script.Parent.Config) local Logging = require(script.Parent.Logging) +local Promise = require(script.Parent.Parent.Promise) local REMOTE_URL = ("http://localhost:%d"):format(Config.port) @@ -18,7 +19,7 @@ local function makeInstanceMap() function self:removeId(id) local instance = self.fromIds[id] - if instance then + if instance ~= nil then self.fromIds[id] = nil self.fromInstances[instance] = nil end @@ -27,12 +28,33 @@ local function makeInstanceMap() function self:removeInstance(instance) local id = self.fromInstances[instance] - if id then + if id ~= nil then self.fromInstances[instance] = nil self.fromIds[id] = nil end end + function self:destroyId(id) + self:removeId(id) + local instance = self.fromIds[id] + + if instance ~= nil then + local descendantsToDestroy = {} + + for otherInstance in pairs(self.fromInstances) do + if otherInstance:IsDescendantOf(instance) then + table.insert(descendantsToDestroy, otherInstance) + end + end + + for _, otherInstance in ipairs(descendantsToDestroy) do + self:removeInstance(otherInstance) + end + + instance:Destroy() + end + end + return self end @@ -127,6 +149,58 @@ local function reconcile(instanceData, instanceMap, instanceMetadataMap, id, exi return existingInstance end +local function applyUpdatePiece(id, visitedIds, responseData, instanceMap, instanceMetadataMap) + if visitedIds[id] then + return + end + + visitedIds[id] = true + + local data = responseData[id] + local instance = instanceMap.fromIds[id] + + -- The instance was deleted in this update + if data == nil then + instanceMap:destroyId(id) + return + end + + -- An instance we know about was updated + if instance ~= nil then + reconcile(responseData, instanceMap, instanceMetadataMap, id, instance) + return instance + end + + -- If the instance's parent already exists, we can stick it there + local parentInstance = instanceMap.fromIds[data.Parent] + if parentInstance ~= nil then + reify(responseData, instanceMap, instanceMetadataMap, id, parentInstance) + return + end + + -- Otherwise, we can check if this response payload contained the parent and + -- work from there instead. + local parentData = responseData[data.Parent] + if parentData ~= nil then + assert(not visitedIds[data.Parent], "Rojo bug: An instance was present and marked as visited but its instance was missing") + + applyUpdatePiece(data.Parent, visitedIds, responseData, instanceMap, instanceMetadataMap) + return + end + + error("Rojo NYI: Instances with parents that weren't mentioned in an update payload") +end + +local function applyUpdate(requestedIds, responseData, instanceMap, instanceMetadataMap) + -- This function may eventually be asynchronous; it will require calls to + -- the server to resolve instances that don't exist yet. + local visitedIds = {} + + for _, id in ipairs(requestedIds) do + applyUpdatePiece(id, visitedIds, responseData, instanceMap, instanceMetadataMap) + end +end + local Session = {} Session.__index = Session @@ -138,43 +212,24 @@ function Session.new() local api = ApiContext.new(REMOTE_URL) ApiContext:onMessage(function(message) - local idsToGet = {} + local requestedIds = {} for _, id in ipairs(message.added) do - table.insert(idsToGet, id) + table.insert(requestedIds, id) end for _, id in ipairs(message.updated) do - table.insert(idsToGet, id) + table.insert(requestedIds, id) end for _, id in ipairs(message.removed) do - table.insert(idsToGet, id) + table.insert(requestedIds, id) end - coroutine.wrap(function() - -- TODO: This section is a mess - local _, response = assert(api:read(idsToGet):await()) - - for _, id in ipairs(idsToGet) do - local data = response.instances[id] - local instance = instanceMap.fromIds[id] - - if data == nil then - -- TOO: Destroy descendants too - if instance ~= nil then - instanceMap:removeInstance(instance) - instance:Destroy() - end - else - if instance ~= nil then - reconcile(response.instances, instanceMap, api.instanceMetadataMap, id, instance) - else - error("TODO: Crawl up to nearest parent, use that?") - end - end - end - end)() + return api:read(requestedIds) + :andThen(function(response) + return applyUpdate(requestedIds, response.instances, instanceMap, api.instanceMetadataMap) + end) end) api:connect() From 14db86e4b749f7e623ce94563448d2c517997074 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 2 Jan 2019 13:11:29 -0800 Subject: [PATCH 0287/1504] Fix luacheck errors --- plugin/src/Session.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index ca74e19c..3e4f6b5b 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -1,7 +1,6 @@ local ApiContext = require(script.Parent.ApiContext) local Config = require(script.Parent.Config) local Logging = require(script.Parent.Logging) -local Promise = require(script.Parent.Parent.Promise) local REMOTE_URL = ("http://localhost:%d"):format(Config.port) @@ -182,7 +181,9 @@ local function applyUpdatePiece(id, visitedIds, responseData, instanceMap, insta -- work from there instead. local parentData = responseData[data.Parent] if parentData ~= nil then - assert(not visitedIds[data.Parent], "Rojo bug: An instance was present and marked as visited but its instance was missing") + if visitedIds[data.Parent] then + error("Rojo bug: An instance was present and marked as visited but its instance was missing") + end applyUpdatePiece(data.Parent, visitedIds, responseData, instanceMap, instanceMetadataMap) return From 0aaefe9a66553556af4216f0a3baf7f5f1bebc2d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 2 Jan 2019 14:00:35 -0800 Subject: [PATCH 0288/1504] C:/Program Files/Git/api/visualize -> /visualize/rbx, added /visualize/imfs --- server/src/lib.rs | 2 +- server/src/session.rs | 2 + server/src/visualize.rs | 128 +++++++++++++++++++++++++++++++++++ server/src/visualize_tree.rs | 42 ------------ server/src/web.rs | 26 +++---- 5 files changed, 140 insertions(+), 60 deletions(-) create mode 100644 server/src/visualize.rs delete mode 100644 server/src/visualize_tree.rs diff --git a/server/src/lib.rs b/server/src/lib.rs index 80b7235c..d15c4d68 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -18,6 +18,6 @@ pub mod rbx_session; pub mod rbx_snapshot; pub mod session; pub mod session_id; -pub mod visualize_tree; +pub mod visualize; pub mod web; pub mod web_util; \ No newline at end of file diff --git a/server/src/session.rs b/server/src/session.rs index bf7686e5..91a286ee 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -18,6 +18,7 @@ pub struct Session { pub session_id: SessionId, pub message_queue: Arc>, pub rbx_session: Arc>, + pub imfs: Arc>, _fs_watcher: FsWatcher, } @@ -50,6 +51,7 @@ impl Session { session_id, message_queue, rbx_session, + imfs, _fs_watcher: fs_watcher, }) } diff --git a/server/src/visualize.rs b/server/src/visualize.rs new file mode 100644 index 00000000..b7cda558 --- /dev/null +++ b/server/src/visualize.rs @@ -0,0 +1,128 @@ +use std::{ + fmt, + io::Write, + path::Path, + process::{Command, Stdio}, +}; + +use rbx_tree::{RbxTree, RbxId}; + +use crate::{ + imfs::{Imfs, ImfsItem}, +}; + +static GRAPHVIZ_HEADER: &str = r#" +digraph RojoTree { + rankdir = "LR"; + graph [ + ranksep = "0.7", + nodesep = "0.5", + ]; + node [ + fontname = "Hack", + shape = "record", + ]; +"#; + +pub fn graphviz_to_svg(source: &str) -> String { + let mut child = Command::new("dot") + .arg("-Tsvg") + .stdin(Stdio::piped()) + .stdout(Stdio::piped()) + .spawn() + .expect("Failed to spawn GraphViz process -- make sure it's installed in order to use /api/visualize"); + + { + let stdin = child.stdin.as_mut().expect("Failed to open stdin"); + stdin.write_all(source.as_bytes()).expect("Failed to write to stdin"); + } + + let output = child.wait_with_output().expect("Failed to read stdout"); + String::from_utf8(output.stdout).expect("Failed to parse stdout as UTF-8") +} + +pub struct VisualizeRbxTree<'a>(pub &'a RbxTree); + +impl<'a> fmt::Display for VisualizeRbxTree<'a> { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + writeln!(output, "{}", GRAPHVIZ_HEADER)?; + + visualize_rbx_node(self.0, self.0.get_root_id(), output)?; + + writeln!(output, "}}")?; + + Ok(()) + } +} + +fn visualize_rbx_node(tree: &RbxTree, id: RbxId, output: &mut fmt::Formatter) -> fmt::Result { + let node = tree.get_instance(id).unwrap(); + + writeln!(output, " \"{}\" [label=\"{}\"]", id, node.name)?; + + for &child_id in node.get_children_ids() { + writeln!(output, " \"{}\" -> \"{}\"", id, child_id)?; + visualize_rbx_node(tree, child_id, output)?; + } + + Ok(()) +} + +pub struct VisualizeImfs<'a>(pub &'a Imfs); + +impl<'a> fmt::Display for VisualizeImfs<'a> { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + writeln!(output, "{}", GRAPHVIZ_HEADER)?; + + for root_path in self.0.get_roots() { + visualize_root_path(self.0, root_path, output)?; + } + + writeln!(output, "}}")?; + + Ok(()) + } +} + +fn normalize_name(path: &Path) -> String { + path.to_str().unwrap().replace("\\", "/") +} + +fn visualize_root_path(imfs: &Imfs, path: &Path, output: &mut fmt::Formatter) -> fmt::Result { + let normalized_name = normalize_name(path); + let item = imfs.get(path).unwrap(); + + writeln!(output, " \"{}\"", normalized_name)?; + + match item { + ImfsItem::File(_) => {}, + ImfsItem::Directory(directory) => { + for child_path in &directory.children { + writeln!(output, " \"{}\" -> \"{}\"", normalized_name, normalize_name(child_path))?; + visualize_path(imfs, child_path, output)?; + } + }, + } + + Ok(()) +} + +fn visualize_path(imfs: &Imfs, path: &Path, output: &mut fmt::Formatter) -> fmt::Result { + let normalized_name = normalize_name(path); + let short_name = path.file_name().unwrap().to_string_lossy(); + let item = imfs.get(path).unwrap(); + + writeln!(output, " \"{}\" [label = \"{}\"]", normalized_name, short_name)?; + + match item { + ImfsItem::File(_) => {}, + ImfsItem::Directory(directory) => { + for child_path in &directory.children { + writeln!(output, " \"{}\" -> \"{}\"", normalized_name, normalize_name(child_path))?; + visualize_path(imfs, child_path, output)?; + } + }, + } + + Ok(()) +} \ No newline at end of file diff --git a/server/src/visualize_tree.rs b/server/src/visualize_tree.rs deleted file mode 100644 index 9faee18f..00000000 --- a/server/src/visualize_tree.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::fmt; -use rbx_tree::{RbxTree, RbxId}; - -static GRAPHVIZ_HEADER: &str = r#" -digraph RojoTree { - rankdir = "LR"; - graph [ - ranksep = "0.7", - nodesep = "0.5", - ]; - node [ - fontname = "Hack", - shape = "record", - ]; -"#; - -pub struct VisualizeTree<'a>(pub &'a RbxTree); - -impl<'a> fmt::Display for VisualizeTree<'a> { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - writeln!(output, "{}", GRAPHVIZ_HEADER)?; - - visualize_node(self.0, self.0.get_root_id(), output)?; - - writeln!(output, "}}")?; - - Ok(()) - } -} - -fn visualize_node(tree: &RbxTree, id: RbxId, output: &mut fmt::Formatter) -> fmt::Result { - let node = tree.get_instance(id).unwrap(); - - writeln!(output, " \"{}\" [label=\"{}\"]", id, node.name)?; - - for &child_id in node.get_children_ids() { - writeln!(output, " \"{}\" -> \"{}\"", id, child_id)?; - visualize_node(tree, child_id, output)?; - } - - Ok(()) -} \ No newline at end of file diff --git a/server/src/web.rs b/server/src/web.rs index f73ecef2..5467b3cc 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -1,8 +1,6 @@ use std::{ borrow::Cow, collections::HashMap, - io::Write, - process::{Command, Stdio}, sync::{mpsc, Arc}, }; @@ -19,7 +17,7 @@ use crate::{ session_id::SessionId, project::InstanceProjectNodeMetadata, rbx_snapshot::InstanceChanges, - visualize_tree::VisualizeTree, + visualize::{VisualizeRbxTree, VisualizeImfs, graphviz_to_svg}, }; #[derive(Debug, Serialize, Deserialize)] @@ -163,27 +161,21 @@ impl Server { }) }, - (GET) (/api/visualize) => { + (GET) (/visualize/rbx) => { let rbx_session = self.session.rbx_session.lock().unwrap(); let tree = rbx_session.get_tree(); - let dot_source = format!("{}", VisualizeTree(tree)); + let dot_source = format!("{}", VisualizeRbxTree(tree)); - let mut child = Command::new("dot") - .arg("-Tsvg") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn() - .expect("Failed to spawn GraphViz process -- make sure it's installed in order to use /api/visualize"); + Response::svg(graphviz_to_svg(&dot_source)) + }, - { - let stdin = child.stdin.as_mut().expect("Failed to open stdin"); - stdin.write_all(dot_source.as_bytes()).expect("Failed to write to stdin"); - } + (GET) (/visualize/imfs) => { + let imfs = self.session.imfs.lock().unwrap(); - let output = child.wait_with_output().expect("Failed to read stdout"); + let dot_source = format!("{}", VisualizeImfs(&imfs)); - Response::svg(String::from_utf8_lossy(&output.stdout)) + Response::svg(graphviz_to_svg(&dot_source)) }, _ => Response::empty_404() From 8c2e430a568853e463c1cd29a05548c08461d564 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 2 Jan 2019 14:19:26 -0800 Subject: [PATCH 0289/1504] Add more diagnostics --- server/src/rbx_session.rs | 21 ++++++++++++++++++--- server/src/rbx_snapshot.rs | 30 ++++++++++++++++++++++++++++++ server/src/visualize.rs | 2 +- 3 files changed, 49 insertions(+), 4 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index e695db04..218aa8fb 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -63,13 +63,18 @@ impl RbxSession { let closest_path = self.path_map.descend(root_path, path); let &instance_id = self.path_map.get(&closest_path).unwrap(); + trace!("Snapshotting path {}", closest_path.display()); + let snapshot = snapshot_instances_from_imfs(&imfs, &closest_path, &mut self.sync_point_names) .expect("Could not generate instance snapshot"); reconcile_subtree(&mut self.tree, instance_id, &snapshot, &mut self.path_map, &mut self.instance_metadata_map, &mut changes); } - if !changes.is_empty() { + if changes.is_empty() { + trace!("No instance changes triggered from file update."); + } else { + trace!("Pushing changes: {}", changes); self.message_queue.push_messages(&[changes]); } } @@ -88,7 +93,10 @@ impl RbxSession { // If the path doesn't exist or it's a directory, we don't care if it // updated match imfs.get(path) { - Some(ImfsItem::Directory(_)) | None => return, + Some(ImfsItem::Directory(_)) | None => { + trace!("Updated path was a directory, ignoring."); + return; + }, Some(ImfsItem::File(_)) => {}, } } @@ -101,7 +109,12 @@ impl RbxSession { let instance_id = match self.path_map.remove(path) { Some(id) => id, - None => return, + None => { + // TODO: init.lua files won't be in the path map, that should be + // patched up! + trace!("Path was not in path map, ignoring removal."); + return; + }, }; let removed_subtree = match self.tree.remove_instance(instance_id) { @@ -118,6 +131,8 @@ impl RbxSession { updated: HashSet::new(), }; + trace!("Pushing changes: {}", changes); + self.message_queue.push_messages(&[changes]); } diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 55de7bbf..9cd43bb7 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -2,6 +2,7 @@ use std::{ str, borrow::Cow, collections::{HashMap, HashSet}, + fmt, path::PathBuf, }; @@ -19,6 +20,35 @@ pub struct InstanceChanges { pub updated: HashSet, } +impl fmt::Display for InstanceChanges { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + writeln!(output, "InstanceChanges {{")?; + + if !self.added.is_empty() { + writeln!(output, " Added:")?; + for id in &self.added { + writeln!(output, " {}", id)?; + } + } + + if !self.removed.is_empty() { + writeln!(output, " Removed:")?; + for id in &self.removed { + writeln!(output, " {}", id)?; + } + } + + if !self.updated.is_empty() { + writeln!(output, " Updated:")?; + for id in &self.updated { + writeln!(output, " {}", id)?; + } + } + + writeln!(output, "}}") + } +} + impl InstanceChanges { pub fn is_empty(&self) -> bool { self.added.is_empty() && self.removed.is_empty() && self.updated.is_empty() diff --git a/server/src/visualize.rs b/server/src/visualize.rs index b7cda558..97b1f294 100644 --- a/server/src/visualize.rs +++ b/server/src/visualize.rs @@ -58,7 +58,7 @@ impl<'a> fmt::Display for VisualizeRbxTree<'a> { fn visualize_rbx_node(tree: &RbxTree, id: RbxId, output: &mut fmt::Formatter) -> fmt::Result { let node = tree.get_instance(id).unwrap(); - writeln!(output, " \"{}\" [label=\"{}\"]", id, node.name)?; + writeln!(output, " \"{}\" [label=\"{} ({})\"]", id, node.name, node.class_name)?; for &child_id in node.get_children_ids() { writeln!(output, " \"{}\" -> \"{}\"", id, child_id)?; From 77c10d14c9733819762d057407899efd6794af17 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 2 Jan 2019 14:19:41 -0800 Subject: [PATCH 0290/1504] Support changing instance ClassName --- plugin/src/Session.lua | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 3e4f6b5b..7d82c659 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -100,7 +100,13 @@ end local function reconcile(instanceData, instanceMap, instanceMetadataMap, id, existingInstance) local data = instanceData[id] - assert(data.ClassName == existingInstance.ClassName) + if data.ClassName ~= existingInstance.ClassName then + -- TODO: Preserve existing children instead? + local parent = existingInstance.Parent + instanceMap:destroyId(id) + reify(instanceData, instanceMap, instanceMetadataMap, id, parent) + return + end for key, value in pairs(data.Properties) do setProperty(existingInstance, key, value.Value) From ad3999066d80fe09ae36450d193d64bf69588d33 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 2 Jan 2019 15:16:23 -0800 Subject: [PATCH 0291/1504] Expand diagnostics and exploratively fix some edge cases --- plugin/src/Session.lua | 8 ++++++- server/src/path_map.rs | 4 ++-- server/src/rbx_session.rs | 45 +++++++++++--------------------------- server/src/rbx_snapshot.rs | 9 ++++++++ server/src/web.rs | 6 +++++ 5 files changed, 37 insertions(+), 35 deletions(-) diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 7d82c659..79b70b30 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -21,6 +21,8 @@ local function makeInstanceMap() if instance ~= nil then self.fromIds[id] = nil self.fromInstances[instance] = nil + else + Logging.warn("Attempted to remove nonexistant ID %s", tostring(id)) end end @@ -30,12 +32,14 @@ local function makeInstanceMap() if id ~= nil then self.fromInstances[instance] = nil self.fromIds[id] = nil + else + Logging.warn("Attempted to remove nonexistant instance %s", tostring(instance)) end end function self:destroyId(id) - self:removeId(id) local instance = self.fromIds[id] + self:removeId(id) if instance ~= nil then local descendantsToDestroy = {} @@ -51,6 +55,8 @@ local function makeInstanceMap() end instance:Destroy() + else + Logging.warn("Attempted to destroy nonexistant ID %s", tostring(id)) end end diff --git a/server/src/path_map.rs b/server/src/path_map.rs index ebb23364..b32302e2 100644 --- a/server/src/path_map.rs +++ b/server/src/path_map.rs @@ -3,7 +3,7 @@ use std::{ collections::{HashMap, HashSet}, }; -#[derive(Debug)] +#[derive(Debug, Serialize)] struct PathMapNode { value: T, children: HashSet, @@ -11,7 +11,7 @@ struct PathMapNode { /// A map from paths to instance IDs, with a bit of additional data that enables /// removing a path and all of its child paths from the tree more quickly. -#[derive(Debug)] +#[derive(Debug, Serialize)] pub struct PathMap { nodes: HashMap>, } diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 218aa8fb..dd5d1345 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -66,7 +66,9 @@ impl RbxSession { trace!("Snapshotting path {}", closest_path.display()); let snapshot = snapshot_instances_from_imfs(&imfs, &closest_path, &mut self.sync_point_names) - .expect("Could not generate instance snapshot"); + .unwrap_or_else(|| panic!("Could not generate instance snapshot for path {}", closest_path.display())); + + trace!("Snapshot: {:#?}", snapshot); reconcile_subtree(&mut self.tree, instance_id, &snapshot, &mut self.path_map, &mut self.instance_metadata_map, &mut changes); } @@ -106,40 +108,14 @@ impl RbxSession { pub fn path_removed(&mut self, path: &Path) { info!("Path removed: {}", path.display()); - - let instance_id = match self.path_map.remove(path) { - Some(id) => id, - None => { - // TODO: init.lua files won't be in the path map, that should be - // patched up! - trace!("Path was not in path map, ignoring removal."); - return; - }, - }; - - let removed_subtree = match self.tree.remove_instance(instance_id) { - Some(tree) => tree, - None => { - warn!("Rojo tried to remove an instance that was half cleaned-up. This is probably a bug in Rojo."); - return; - }, - }; - - let changes = InstanceChanges { - added: HashSet::new(), - removed: removed_subtree.iter_all_ids().collect(), - updated: HashSet::new(), - }; - - trace!("Pushing changes: {}", changes); - - self.message_queue.push_messages(&[changes]); + self.path_map.remove(path); + self.path_created_or_updated(path); } pub fn path_renamed(&mut self, from_path: &Path, to_path: &Path) { info!("Path renamed from {} to {}", from_path.display(), to_path.display()); - self.path_removed(from_path); - self.path_created(to_path); + self.path_created_or_updated(from_path); + self.path_created_or_updated(to_path); } pub fn get_tree(&self) -> &RbxTree { @@ -149,6 +125,10 @@ impl RbxSession { pub fn get_instance_metadata_map(&self) -> &HashMap { &self.instance_metadata_map } + + pub fn debug_get_path_map(&self) -> &PathMap { + &self.path_map + } } pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { @@ -291,6 +271,7 @@ fn snapshot_instances_from_imfs<'a>( }) }, ImfsItem::Directory(directory) => { + // TODO: Expand init support to handle server and client scripts let init_path = directory.path.join("init.lua"); let mut instance = if directory.children.contains(&init_path) { @@ -306,7 +287,7 @@ fn snapshot_instances_from_imfs<'a>( } }; - instance.name = if let Some(actual_name) = sync_point_names.get(imfs_path) { + instance.name = if let Some(actual_name) = sync_point_names.get(&directory.path) { Cow::Owned(actual_name.clone()) } else { Cow::Borrowed(directory.path.file_name()?.to_str()?) diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 9cd43bb7..768c4c5b 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -55,6 +55,7 @@ impl InstanceChanges { } } +#[derive(Debug)] pub struct RbxSnapshotInstance<'a> { pub name: Cow<'a, str>, pub class_name: Cow<'a, str>, @@ -125,6 +126,14 @@ pub fn reconcile_subtree( instance_metadata_map: &mut HashMap, changes: &mut InstanceChanges, ) { + if let Some(source_path) = &snapshot.source_path { + path_map.insert(source_path.clone(), id); + } + + if let Some(metadata) = &snapshot.metadata { + instance_metadata_map.insert(id, metadata.clone()); + } + if reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot) { changes.updated.insert(id); } diff --git a/server/src/web.rs b/server/src/web.rs index 5467b3cc..679c1881 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -178,6 +178,12 @@ impl Server { Response::svg(graphviz_to_svg(&dot_source)) }, + (GET) (/visualize/path_map) => { + let rbx_session = self.session.rbx_session.lock().unwrap(); + + Response::json(&rbx_session.debug_get_path_map()) + }, + _ => Response::empty_404() ) } From a74c11aef525e0abffa060216b5e322a5909b195 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Jan 2019 15:22:38 -0800 Subject: [PATCH 0292/1504] Expand visualization to show IDs --- server/src/visualize.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/visualize.rs b/server/src/visualize.rs index 97b1f294..74696eda 100644 --- a/server/src/visualize.rs +++ b/server/src/visualize.rs @@ -58,7 +58,7 @@ impl<'a> fmt::Display for VisualizeRbxTree<'a> { fn visualize_rbx_node(tree: &RbxTree, id: RbxId, output: &mut fmt::Formatter) -> fmt::Result { let node = tree.get_instance(id).unwrap(); - writeln!(output, " \"{}\" [label=\"{} ({})\"]", id, node.name, node.class_name)?; + writeln!(output, " \"{}\" [label=\"{} ({})|{}\"]", id, node.name, node.class_name, id)?; for &child_id in node.get_children_ids() { writeln!(output, " \"{}\" -> \"{}\"", id, child_id)?; From e6c2f1c15d9090c4523432ceba0e23fb5a7f601c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Jan 2019 15:23:23 -0800 Subject: [PATCH 0293/1504] Cleaned up and polished session flow - Sessions can now be restarted if they error - Terminology is much easier to follow in the plugin - More change cases are handled correctly --- plugin/src/Session.lua | 97 ++++++++++++++++++++++++++------------ plugin/src/init.server.lua | 7 ++- 2 files changed, 72 insertions(+), 32 deletions(-) diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 79b70b30..32be9573 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -65,7 +65,9 @@ end local function setProperty(instance, key, value) local ok, err = pcall(function() - instance[key] = value + if instance[key] ~= value then + instance[key] = value + end end) if not ok then @@ -81,20 +83,20 @@ local function shouldClearUnknown(id, instanceMetadataMap) end end -local function reify(instanceData, instanceMap, instanceMetadataMap, id, parent) - local data = instanceData[id] +local function reify(virtualInstancesById, instanceMap, instanceMetadataMap, id, parent) + local virtualInstance = virtualInstancesById[id] - local instance = Instance.new(data.ClassName) + local instance = Instance.new(virtualInstance.ClassName) - for key, value in pairs(data.Properties) do + for key, value in pairs(virtualInstance.Properties) do -- TODO: Branch on value.Type setProperty(instance, key, value.Value) end - instance.Name = data.Name + instance.Name = virtualInstance.Name - for _, childId in ipairs(data.Children) do - reify(instanceData, instanceMap, instanceMetadataMap, childId, instance) + for _, childId in ipairs(virtualInstance.Children) do + reify(virtualInstancesById, instanceMap, instanceMetadataMap, childId, instance) end setProperty(instance, "Parent", parent) @@ -103,18 +105,29 @@ local function reify(instanceData, instanceMap, instanceMetadataMap, id, parent) return instance end -local function reconcile(instanceData, instanceMap, instanceMetadataMap, id, existingInstance) - local data = instanceData[id] +--[[ + Update an existing instance, including its properties and children, to match + the given information. +]] +local function reconcile(virtualInstancesById, instanceMap, instanceMetadataMap, id, existingInstance) + local virtualInstance = virtualInstancesById[id] - if data.ClassName ~= existingInstance.ClassName then + -- If an instance changes ClassName, we assume it's very different. That's + -- not always the case! + if virtualInstance.ClassName ~= existingInstance.ClassName then -- TODO: Preserve existing children instead? local parent = existingInstance.Parent instanceMap:destroyId(id) - reify(instanceData, instanceMap, instanceMetadataMap, id, parent) + reify(virtualInstancesById, instanceMap, instanceMetadataMap, id, parent) return end - for key, value in pairs(data.Properties) do + instanceMap:insert(id, existingInstance) + + -- Some instances don't like being named, even if their name already matches + setProperty(existingInstance, "Name", virtualInstance.Name) + + for key, value in pairs(virtualInstance.Properties) do setProperty(existingInstance, key, value.Value) end @@ -125,8 +138,8 @@ local function reconcile(instanceData, instanceMap, instanceMetadataMap, id, exi unvisitedExistingChildren[child] = true end - for _, childId in ipairs(data.Children) do - local childData = instanceData[childId] + for _, childId in ipairs(virtualInstance.Children) do + local childData = virtualInstancesById[childId] local existingChildInstance for instance in pairs(unvisitedExistingChildren) do @@ -144,9 +157,9 @@ local function reconcile(instanceData, instanceMap, instanceMetadataMap, id, exi if existingChildInstance ~= nil then unvisitedExistingChildren[existingChildInstance] = nil - reconcile(instanceData, instanceMap, instanceMetadataMap, childId, existingChildInstance) + reconcile(virtualInstancesById, instanceMap, instanceMetadataMap, childId, existingChildInstance) else - reify(instanceData, instanceMap, instanceMetadataMap, childId, existingInstance) + reify(virtualInstancesById, instanceMap, instanceMetadataMap, childId, existingInstance) end end @@ -157,67 +170,86 @@ local function reconcile(instanceData, instanceMap, instanceMetadataMap, id, exi end end + -- The root instance of a project won't have a parent, like the DataModel, + -- so we need to be careful here. + if virtualInstance.Parent ~= nil then + local parent = instanceMap.fromIds[virtualInstance.Parent] + + if parent == nil then + Logging.info("Instance %s wanted parent of %s", tostring(id), tostring(virtualInstance.Parent)) + error("Rojo bug: During reconciliation, an instance referred to an instance ID as parent that does not exist.") + end + + -- Some instances, like services, don't like having their Parent + -- property poked, even if we're setting it to the same value. + setProperty(existingInstance, "Parent", parent) + if existingInstance.Parent ~= parent then + existingInstance.Parent = parent + end + end + return existingInstance end -local function applyUpdatePiece(id, visitedIds, responseData, instanceMap, instanceMetadataMap) +local function applyUpdatePiece(id, visitedIds, virtualInstancesById, instanceMap, instanceMetadataMap) if visitedIds[id] then return end visitedIds[id] = true - local data = responseData[id] + local virtualInstance = virtualInstancesById[id] local instance = instanceMap.fromIds[id] -- The instance was deleted in this update - if data == nil then + if virtualInstance == nil then instanceMap:destroyId(id) return end -- An instance we know about was updated if instance ~= nil then - reconcile(responseData, instanceMap, instanceMetadataMap, id, instance) + reconcile(virtualInstancesById, instanceMap, instanceMetadataMap, id, instance) return instance end -- If the instance's parent already exists, we can stick it there - local parentInstance = instanceMap.fromIds[data.Parent] + local parentInstance = instanceMap.fromIds[virtualInstance.Parent] if parentInstance ~= nil then - reify(responseData, instanceMap, instanceMetadataMap, id, parentInstance) + reify(virtualInstancesById, instanceMap, instanceMetadataMap, id, parentInstance) return end -- Otherwise, we can check if this response payload contained the parent and -- work from there instead. - local parentData = responseData[data.Parent] + local parentData = virtualInstancesById[virtualInstance.Parent] if parentData ~= nil then - if visitedIds[data.Parent] then + if visitedIds[virtualInstance.Parent] then error("Rojo bug: An instance was present and marked as visited but its instance was missing") end - applyUpdatePiece(data.Parent, visitedIds, responseData, instanceMap, instanceMetadataMap) + applyUpdatePiece(virtualInstance.Parent, visitedIds, virtualInstancesById, instanceMap, instanceMetadataMap) return end + Logging.trace("Instance ID %s, parent ID %s", tostring(id), tostring(virtualInstance.Parent)) error("Rojo NYI: Instances with parents that weren't mentioned in an update payload") end -local function applyUpdate(requestedIds, responseData, instanceMap, instanceMetadataMap) +local function applyUpdate(requestedIds, virtualInstancesById, instanceMap, instanceMetadataMap) -- This function may eventually be asynchronous; it will require calls to -- the server to resolve instances that don't exist yet. local visitedIds = {} for _, id in ipairs(requestedIds) do - applyUpdatePiece(id, visitedIds, responseData, instanceMap, instanceMetadataMap) + applyUpdatePiece(id, visitedIds, virtualInstancesById, instanceMap, instanceMetadataMap) end end local Session = {} Session.__index = Session -function Session.new() +function Session.new(onError) local self = {} local instanceMap = makeInstanceMap() @@ -243,6 +275,10 @@ function Session.new() :andThen(function(response) return applyUpdate(requestedIds, response.instances, instanceMap, api.instanceMetadataMap) end) + :catch(function(message) + Logging.warn("%s", tostring(message)) + onError() + end) end) api:connect() @@ -255,7 +291,8 @@ function Session.new() return api:retrieveMessages() end) :catch(function(message) - Logging.warn("Couldn't start a new Rojo session: %s", tostring(message)) + Logging.warn("%s", tostring(message)) + onError() end) return setmetatable(self, Session) diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index de1d2873..8f18ea53 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -67,8 +67,11 @@ local function main() end Logging.info("Started new session.") - currentSession = Session.new() + currentSession = Session.new(function() + Logging.info("Session terminated.") + currentSession = nil + end) end) end -main() +main() \ No newline at end of file From 37ed80055b74bcf929cb8405de2ec675633dca46 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Jan 2019 16:28:25 -0800 Subject: [PATCH 0294/1504] Remove unused import --- server/src/rbx_session.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index dd5d1345..57b83f37 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -1,6 +1,6 @@ use std::{ borrow::Cow, - collections::{HashMap, HashSet}, + collections::HashMap, path::{Path, PathBuf}, sync::{Arc, Mutex}, str, From b7a28aa511814c0c3c422e3b06a0fd72d7d3a9d0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Jan 2019 18:06:11 -0800 Subject: [PATCH 0295/1504] Upgrade all plugin dependencies --- plugin/modules/roact | 2 +- plugin/modules/roact-rodux | 2 +- plugin/modules/rodux | 2 +- plugin/modules/testez | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin/modules/roact b/plugin/modules/roact index bbb06631..8da5b298 160000 --- a/plugin/modules/roact +++ b/plugin/modules/roact @@ -1 +1 @@ -Subproject commit bbb066316149f9b56fdf7718d48bcded7288d86f +Subproject commit 8da5b298059382499df05102d62ba01a20bd4e1e diff --git a/plugin/modules/roact-rodux b/plugin/modules/roact-rodux index 97fbfee9..5d2e6885 160000 --- a/plugin/modules/roact-rodux +++ b/plugin/modules/roact-rodux @@ -1 +1 @@ -Subproject commit 97fbfee90af6abaa2118c9abd4532210793c26dc +Subproject commit 5d2e6885fc7a340e4d4e455a928419ec3cbd2e65 diff --git a/plugin/modules/rodux b/plugin/modules/rodux index b8ba4863..862f1c76 160000 --- a/plugin/modules/rodux +++ b/plugin/modules/rodux @@ -1 +1 @@ -Subproject commit b8ba4863359f3a05ac5a8f1993d02b5410e5e718 +Subproject commit 862f1c769ac31f9041f89433458336397988538c diff --git a/plugin/modules/testez b/plugin/modules/testez index 5acef965..6e9157db 160000 --- a/plugin/modules/testez +++ b/plugin/modules/testez @@ -1 +1 @@ -Subproject commit 5acef9659a177d446800e986b60e4613a35eb418 +Subproject commit 6e9157db3c1a8b1558c54c50065e3562cab362e1 From 5816bb64dc4d7443703e4a79de1c68960c83a1b9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Jan 2019 18:06:24 -0800 Subject: [PATCH 0296/1504] Start work on plugin UI, this is pretty painful --- plugin/src/Components/App.lua | 15 +++ plugin/src/Components/ConnectPanel.lua | 177 +++++++++++++++++++++++++ plugin/src/Components/FitList.lua | 63 +++++++++ plugin/src/Components/FitText.lua | 69 ++++++++++ plugin/src/init.server.lua | 37 ++++-- 5 files changed, 348 insertions(+), 13 deletions(-) create mode 100644 plugin/src/Components/App.lua create mode 100644 plugin/src/Components/ConnectPanel.lua create mode 100644 plugin/src/Components/FitList.lua create mode 100644 plugin/src/Components/FitText.lua diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua new file mode 100644 index 00000000..12aac48d --- /dev/null +++ b/plugin/src/Components/App.lua @@ -0,0 +1,15 @@ +local Roact = require(script:FindFirstAncestor("Rojo").Roact) + +local ConnectPanel = require(script.Parent.ConnectPanel) + +local e = Roact.createElement + +local App = Roact.Component:extend("App") + +function App:render() + return e("ScreenGui", nil, { + ConnectPanel = e(ConnectPanel), + }) +end + +return App \ No newline at end of file diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua new file mode 100644 index 00000000..59c8b500 --- /dev/null +++ b/plugin/src/Components/ConnectPanel.lua @@ -0,0 +1,177 @@ +local Roact = require(script:FindFirstAncestor("Rojo").Roact) + +local FitList = require(script.Parent.FitList) +local FitText = require(script.Parent.FitText) + +local e = Roact.createElement + +local ConnectPanel = Roact.Component:extend("ConnectPanel") + +function ConnectPanel:init() + self.labelSizes = {} + self.labelSize, self.setLabelSize = Roact.createBinding(Vector2.new()) + + self:setState({ + address = "localhost", + port = "34872", + }) +end + +function ConnectPanel:updateLabelSize(name, size) + self.labelSizes[name] = size + + local x = 0 + local y = 0 + + for _, size in pairs(self.labelSizes) do + x = math.max(x, size.X) + y = math.max(y, size.Y) + end + + self.setLabelSize(Vector2.new(x, y)) +end + +function ConnectPanel:render() + return e(FitList, { + containerProps = { + BackgroundColor3 = Color3.fromRGB(8, 8, 8), + BorderColor3 = Color3.fromRGB(64, 64, 64), + Position = UDim2.new(0.5, 0, 0, 0), + AnchorPoint = Vector2.new(0.5, 0), + }, + layoutProps = { + Padding = UDim.new(0, 8), + }, + paddingProps = { + PaddingTop = UDim.new(0, 8), + PaddingBottom = UDim.new(0, 8), + PaddingLeft = UDim.new(0, 8), + PaddingRight = UDim.new(0, 8), + }, + }, { + Address = e(FitList, { + containerProps = { + LayoutOrder = 1, + BackgroundTransparency = 1, + }, + layoutProps = { + FillDirection = Enum.FillDirection.Horizontal, + Padding = UDim.new(0, 8), + }, + }, { + Label = e(FitText, { + Kind = "TextLabel", + LayoutOrder = 1, + BackgroundTransparency = 1, + TextXAlignment = Enum.TextXAlignment.Left, + Font = Enum.Font.SourceSans, + TextSize = 16, + Text = "Address", + TextColor3 = Color3.fromRGB(245, 245, 245), + [Roact.Change.AbsoluteSize] = function(rbx) + self:updateLabelSize("address", rbx.AbsoluteSize) + end, + }, { + Sizing = e("UISizeConstraint", { + MinSize = self.labelSize, + }), + }), + + Input = e("TextBox", { + LayoutOrder = 2, + Size = UDim2.new(0, 300, 0, 20), + Font = Enum.Font.SourceSans, + ClearTextOnFocus = false, + TextXAlignment = Enum.TextXAlignment.Left, + TextSize = 16, + Text = self.state.address, + [Roact.Change.Text] = function(rbx) + self:setState({ + address = rbx.Text, + }) + end, + TextColor3 = Color3.fromRGB(245, 245, 245), + BackgroundColor3 = Color3.fromRGB(8, 8, 8), + BorderColor3 = Color3.fromRGB(64, 64, 64), + }), + }), + + Port = e(FitList, { + containerProps = { + LayoutOrder = 2, + BackgroundTransparency = 1, + }, + layoutProps = { + FillDirection = Enum.FillDirection.Horizontal, + Padding = UDim.new(0, 8), + }, + }, { + Label = e(FitText, { + Kind = "TextLabel", + LayoutOrder = 1, + BackgroundTransparency = 1, + TextXAlignment = Enum.TextXAlignment.Left, + Font = Enum.Font.SourceSans, + TextSize = 16, + Text = "Port", + TextColor3 = Color3.fromRGB(245, 245, 245), + [Roact.Change.AbsoluteSize] = function(rbx) + self:updateLabelSize("port", rbx.AbsoluteSize) + end, + }, { + Sizing = e("UISizeConstraint", { + MinSize = self.labelSize, + }), + }), + + Input = e("TextBox", { + LayoutOrder = 2, + Size = UDim2.new(0, 300, 0, 20), + Font = Enum.Font.SourceSans, + ClearTextOnFocus = false, + TextXAlignment = Enum.TextXAlignment.Left, + TextSize = 16, + Text = self.state.port, + [Roact.Change.Text] = function(rbx) + self:setState({ + port = rbx.Text, + }) + end, + TextColor3 = Color3.fromRGB(245, 245, 245), + BackgroundColor3 = Color3.fromRGB(8, 8, 8), + BorderColor3 = Color3.fromRGB(64, 64, 64), + }), + }), + + Buttons = e(FitList, { + containerProps = { + LayoutOrder = 3, + BackgroundTransparency = 1, + }, + layoutProps = { + FillDirection = Enum.FillDirection.Horizontal, + Padding = UDim.new(0, 8), + }, + }, { + e(FitText, { + Kind = "TextButton", + LayoutOrder = 1, + BackgroundColor3 = Color3.fromRGB(16, 16, 16), + BorderColor3 = Color3.fromRGB(64, 64, 64), + TextColor3 = Color3.fromRGB(245, 245, 245), + Text = "Start", + }), + + e(FitText, { + Kind = "TextButton", + LayoutOrder = 2, + BackgroundColor3 = Color3.fromRGB(16, 16, 16), + BorderColor3 = Color3.fromRGB(64, 64, 64), + TextColor3 = Color3.fromRGB(245, 245, 245), + Text = "Cancel", + }), + }) + }) +end + +return ConnectPanel \ No newline at end of file diff --git a/plugin/src/Components/FitList.lua b/plugin/src/Components/FitList.lua new file mode 100644 index 00000000..d7a1c8c0 --- /dev/null +++ b/plugin/src/Components/FitList.lua @@ -0,0 +1,63 @@ +local Roact = require(script:FindFirstAncestor("Rojo").Roact) + +local e = Roact.createElement + +local function merge(...) + local output = {} + + for i = 1, select("#", ...) do + local source = select(i, ...) + + if source ~= nil then + for key, value in pairs(source) do + output[key] = value + end + end + end + + return output +end + +local FitList = Roact.Component:extend("FitList") + +function FitList:init() + self.sizeBinding, self.setSize = Roact.createBinding(UDim2.new()) +end + +function FitList:render() + local containerProps = self.props.containerProps + local layoutProps = self.props.layoutProps + local paddingProps = self.props.paddingProps + + local padding + if paddingProps ~= nil then + padding = e("UIPadding", paddingProps) + end + + local children = merge(self.props[Roact.Children], { + ["$Layout"] = e("UIListLayout", merge({ + SortOrder = Enum.SortOrder.LayoutOrder, + [Roact.Change.AbsoluteContentSize] = function(instance) + local size = instance.AbsoluteContentSize + + if paddingProps ~= nil then + size = size + Vector2.new( + paddingProps.PaddingLeft.Offset + paddingProps.PaddingRight.Offset, + paddingProps.PaddingTop.Offset + paddingProps.PaddingBottom.Offset) + end + + self.setSize(UDim2.new(0, size.X, 0, size.Y)) + end, + }, layoutProps)), + + ["$Padding"] = padding, + }) + + local fullContainerProps = merge(containerProps, { + Size = self.sizeBinding, + }) + + return e("Frame", fullContainerProps, children) +end + +return FitList \ No newline at end of file diff --git a/plugin/src/Components/FitText.lua b/plugin/src/Components/FitText.lua new file mode 100644 index 00000000..76524e03 --- /dev/null +++ b/plugin/src/Components/FitText.lua @@ -0,0 +1,69 @@ +local TextService = game:GetService("TextService") + +local Roact = require(script:FindFirstAncestor("Rojo").Roact) + +local e = Roact.createElement + +local None = newproxy(false) +local function merge(...) + local output = {} + + for i = 1, select("#", ...) do + local source = select(i, ...) + + if source ~= nil then + for key, value in pairs(source) do + if value == None then + output[key] = nil + else + output[key] = value + end + end + end + end + + return output +end + +local FitText = Roact.Component:extend("FitText") + +function FitText:init() + self.sizeBinding, self.setSize = Roact.createBinding(UDim2.new()) +end + +function FitText:render() + local kind = self.props.Kind + + local containerProps = merge(self.props, { + Kind = None, + Padding = None, + Size = self.sizeBinding + }) + + return e(kind, containerProps) +end + +function FitText:didMount() + self:updateTextMeasurements() +end + +function FitText:didUpdate() + self:updateTextMeasurements() +end + +function FitText:updateTextMeasurements() + local padding = self.props.Padding or Vector2.new(0, 0) + + local text = self.props.Text or "" + local font = self.props.Font or Enum.Font.Legacy + local textSize = self.props.TextSize or 12 + + local measuredText = TextService:GetTextSize(text, textSize, font, Vector2.new(9e6, 9e6)) + local totalSize = UDim2.new( + 0, padding.X * 2 + measuredText.X, + 0, padding.Y * 2 + measuredText.Y) + + self.setSize(totalSize) +end + +return FitText \ No newline at end of file diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index 8f18ea53..b956cbf2 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -2,11 +2,18 @@ if not plugin then return end +local Roact = require(script.Parent.Roact) + +Roact.setGlobalConfig({ + elementTracing = true, +}) + local Session = require(script.Session) local Config = require(script.Config) local Version = require(script.Version) local Logging = require(script.Logging) local DevSettings = require(script.DevSettings) +local App = require(script.Components.App) local function showUpgradeMessage(lastVersion) local message = ( @@ -53,25 +60,29 @@ local function main() local toolbar = plugin:CreateToolbar("Rojo " .. displayedVersion) + Roact.mount(Roact.createElement(App), game:GetService("CoreGui"), "Rojo UI") + local currentSession - -- TODO: More robust session tracking to handle errors -- TODO: Icon! - toolbar:CreateButton("Connect", "Connect to Rojo Session", "") - .Click:Connect(function() - checkUpgrade() + local connectButton = toolbar:CreateButton("Connect", "Connect to Rojo Session", "") + connectButton.ClickableWhenViewportHidden = true - if currentSession ~= nil then - Logging.warn("A session is already running!") - return - end + connectButton.Click:Connect(function() + connectButton:SetActive(false) + checkUpgrade() - Logging.info("Started new session.") - currentSession = Session.new(function() - Logging.info("Session terminated.") - currentSession = nil - end) + if currentSession ~= nil then + Logging.warn("A session is already running!") + return + end + + Logging.info("Started new session.") + currentSession = Session.new(function() + Logging.info("Session terminated.") + currentSession = nil end) + end) end main() \ No newline at end of file From 1582d8f504808f07bd47ca6d765d3d96d88522f7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 10:59:47 -0800 Subject: [PATCH 0297/1504] plugin: Migrate 'merge' utility into Dictionary module --- plugin/src/Components/FitList.lua | 24 +++++----------------- plugin/src/Components/FitText.lua | 29 +++++---------------------- plugin/src/Dictionary.lua | 33 +++++++++++++++++++++++++++++++ 3 files changed, 43 insertions(+), 43 deletions(-) create mode 100644 plugin/src/Dictionary.lua diff --git a/plugin/src/Components/FitList.lua b/plugin/src/Components/FitList.lua index d7a1c8c0..4aa49cb9 100644 --- a/plugin/src/Components/FitList.lua +++ b/plugin/src/Components/FitList.lua @@ -1,23 +1,9 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) +local Dictionary = require(script.Parent.Parent.Dictionary) + local e = Roact.createElement -local function merge(...) - local output = {} - - for i = 1, select("#", ...) do - local source = select(i, ...) - - if source ~= nil then - for key, value in pairs(source) do - output[key] = value - end - end - end - - return output -end - local FitList = Roact.Component:extend("FitList") function FitList:init() @@ -34,8 +20,8 @@ function FitList:render() padding = e("UIPadding", paddingProps) end - local children = merge(self.props[Roact.Children], { - ["$Layout"] = e("UIListLayout", merge({ + local children = Dictionary.merge(self.props[Roact.Children], { + ["$Layout"] = e("UIListLayout", Dictionary.merge({ SortOrder = Enum.SortOrder.LayoutOrder, [Roact.Change.AbsoluteContentSize] = function(instance) local size = instance.AbsoluteContentSize @@ -53,7 +39,7 @@ function FitList:render() ["$Padding"] = padding, }) - local fullContainerProps = merge(containerProps, { + local fullContainerProps = Dictionary.merge(containerProps, { Size = self.sizeBinding, }) diff --git a/plugin/src/Components/FitText.lua b/plugin/src/Components/FitText.lua index 76524e03..2ec0b51b 100644 --- a/plugin/src/Components/FitText.lua +++ b/plugin/src/Components/FitText.lua @@ -2,29 +2,10 @@ local TextService = game:GetService("TextService") local Roact = require(script:FindFirstAncestor("Rojo").Roact) +local Dictionary = require(script.Parent.Parent.Dictionary) + local e = Roact.createElement -local None = newproxy(false) -local function merge(...) - local output = {} - - for i = 1, select("#", ...) do - local source = select(i, ...) - - if source ~= nil then - for key, value in pairs(source) do - if value == None then - output[key] = nil - else - output[key] = value - end - end - end - end - - return output -end - local FitText = Roact.Component:extend("FitText") function FitText:init() @@ -34,9 +15,9 @@ end function FitText:render() local kind = self.props.Kind - local containerProps = merge(self.props, { - Kind = None, - Padding = None, + local containerProps = Dictionary.merge(self.props, { + Kind = Dictionary.None, + Padding = Dictionary.None, Size = self.sizeBinding }) diff --git a/plugin/src/Dictionary.lua b/plugin/src/Dictionary.lua new file mode 100644 index 00000000..c4b1e532 --- /dev/null +++ b/plugin/src/Dictionary.lua @@ -0,0 +1,33 @@ +--[[ + This is a placeholder module waiting for Cryo to become available. +]] + +local None = newproxy(true) +getmetatable(None).__tostring = function() + return "None" +end + +local function merge(...) + local output = {} + + for i = 1, select("#", ...) do + local source = select(i, ...) + + if source ~= nil then + for key, value in pairs(source) do + if value == None then + output[key] = nil + else + output[key] = value + end + end + end + end + + return output +end + +return { + None = None, + merge = merge, +} \ No newline at end of file From edcb3d86388565ea0e24602b0617526c512507ea Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 11:02:54 -0800 Subject: [PATCH 0298/1504] plugin: ConnectPanel now accepts button callbacks --- plugin/src/Components/ConnectPanel.lua | 31 +++++++++++++++++++++----- 1 file changed, 25 insertions(+), 6 deletions(-) diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index 59c8b500..ce54da7f 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -32,6 +32,9 @@ function ConnectPanel:updateLabelSize(name, size) end function ConnectPanel:render() + local startSession = self.props.startSession + local cancel = self.props.cancel + return e(FitList, { containerProps = { BackgroundColor3 = Color3.fromRGB(8, 8, 8), @@ -68,6 +71,7 @@ function ConnectPanel:render() TextSize = 16, Text = "Address", TextColor3 = Color3.fromRGB(245, 245, 245), + [Roact.Change.AbsoluteSize] = function(rbx) self:updateLabelSize("address", rbx.AbsoluteSize) end, @@ -85,14 +89,15 @@ function ConnectPanel:render() TextXAlignment = Enum.TextXAlignment.Left, TextSize = 16, Text = self.state.address, + TextColor3 = Color3.fromRGB(245, 245, 245), + BackgroundColor3 = Color3.fromRGB(8, 8, 8), + BorderColor3 = Color3.fromRGB(64, 64, 64), + [Roact.Change.Text] = function(rbx) self:setState({ address = rbx.Text, }) end, - TextColor3 = Color3.fromRGB(245, 245, 245), - BackgroundColor3 = Color3.fromRGB(8, 8, 8), - BorderColor3 = Color3.fromRGB(64, 64, 64), }), }), @@ -115,6 +120,7 @@ function ConnectPanel:render() TextSize = 16, Text = "Port", TextColor3 = Color3.fromRGB(245, 245, 245), + [Roact.Change.AbsoluteSize] = function(rbx) self:updateLabelSize("port", rbx.AbsoluteSize) end, @@ -132,14 +138,15 @@ function ConnectPanel:render() TextXAlignment = Enum.TextXAlignment.Left, TextSize = 16, Text = self.state.port, + TextColor3 = Color3.fromRGB(245, 245, 245), + BackgroundColor3 = Color3.fromRGB(8, 8, 8), + BorderColor3 = Color3.fromRGB(64, 64, 64), + [Roact.Change.Text] = function(rbx) self:setState({ port = rbx.Text, }) end, - TextColor3 = Color3.fromRGB(245, 245, 245), - BackgroundColor3 = Color3.fromRGB(8, 8, 8), - BorderColor3 = Color3.fromRGB(64, 64, 64), }), }), @@ -160,6 +167,12 @@ function ConnectPanel:render() BorderColor3 = Color3.fromRGB(64, 64, 64), TextColor3 = Color3.fromRGB(245, 245, 245), Text = "Start", + + [Roact.Event.Activated] = function() + if startSession ~= nil then + startSession(self.state.address, self.state.port) + end + end, }), e(FitText, { @@ -169,6 +182,12 @@ function ConnectPanel:render() BorderColor3 = Color3.fromRGB(64, 64, 64), TextColor3 = Color3.fromRGB(245, 245, 245), Text = "Cancel", + + [Roact.Event.Activated] = function() + if cancel ~= nil then + cancel() + end + end, }), }) }) From 86e0f3fabe8cb631478ebad7c005ed3b18c0db43 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 11:54:12 -0800 Subject: [PATCH 0299/1504] plugin: UI pretty much done --- plugin/src/Components/App.lua | 145 +++++++++++++++++- plugin/src/Components/ConnectPanel.lua | 90 +++++++---- .../src/Components/ConnectionActivePanel.lua | 25 +++ plugin/src/Components/FitText.lua | 6 +- plugin/src/Session.lua | 14 +- plugin/src/init.server.lua | 79 +--------- 6 files changed, 241 insertions(+), 118 deletions(-) create mode 100644 plugin/src/Components/ConnectionActivePanel.lua diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 12aac48d..5d097ef2 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -1,15 +1,154 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) +local Session = require(script.Parent.Parent.Session) +local Config = require(script.Parent.Parent.Config) +local Version = require(script.Parent.Parent.Version) +local Logging = require(script.Parent.Parent.Logging) +local DevSettings = require(script.Parent.Parent.DevSettings) + local ConnectPanel = require(script.Parent.ConnectPanel) +local ConnectionActivePanel = require(script.Parent.ConnectionActivePanel) local e = Roact.createElement +local function showUpgradeMessage(lastVersion) + local message = ( + "Rojo detected an upgrade from version %s to version %s." .. + "\nMake sure you have also upgraded your server!" .. + "\n\nRojo plugin version %s is intended for use with server version %s." + ):format( + Version.display(lastVersion), Version.display(Config.version), + Version.display(Config.version), Config.expectedServerVersionString + ) + + Logging.info(message) +end + +--[[ + Check if the user is using a newer version of Rojo than last time. If they + are, show them a reminder to make sure they check their server version. +]] +local function checkUpgrade(plugin) + -- When developing Rojo, there's no use in doing version checks + if DevSettings:isEnabled() then + return + end + + local lastVersion = plugin:GetSetting("LastRojoVersion") + + if lastVersion then + local wasUpgraded = Version.compare(Config.version, lastVersion) == 1 + + if wasUpgraded then + showUpgradeMessage(lastVersion) + end + end + + plugin:SetSetting("LastRojoVersion", Config.version) +end + +local SessionStatus = { + Disconnected = "Disconnected", + Connected = "Connected", + Configuring = "Configuring", + -- TODO: Error? +} + +setmetatable(SessionStatus, { + __index = function(_, key) + error(("%q is not a valid member of SessionStatus"):format(tostring(key)), 2) + end, +}) + local App = Roact.Component:extend("App") -function App:render() - return e("ScreenGui", nil, { - ConnectPanel = e(ConnectPanel), +function App:init() + self:setState({ + sessionStatus = SessionStatus.Disconnected, }) + + self.currentSession = nil + + self.displayedVersion = DevSettings:isEnabled() + and Config.codename + or Version.display(Config.version) +end + +function App:render() + local children + + if self.state.sessionStatus == SessionStatus.Connected then + children = { + ConnectionActivePanel = e(ConnectionActivePanel), + } + elseif self.state.sessionStatus == SessionStatus.Configuring then + children = { + ConnectPanel = e(ConnectPanel, { + startSession = function(address, port) + Logging.info("Starting new session") + + self.currentSession = Session.new({ + address = address, + port = port, + onError = function() + Logging.info("Session terminated") + self.currentSession = nil + + self:setState({ + sessionStatus = SessionStatus.Disconnected, + }) + end + }) + + self:setState({ + sessionStatus = SessionStatus.Connected, + }) + end, + cancel = function() + Logging.info("Canceling session configuration") + + self:setState({ + sessionStatus = SessionStatus.Disconnected, + }) + end, + }), + } + end + + return e("ScreenGui", nil, children) +end + +function App:didMount() + Logging.trace("Rojo %s initializing", self.displayedVersion) + + local toolbar = self.props.plugin:CreateToolbar("Rojo " .. self.displayedVersion) + + -- TODO: Icon! + local connectButton = toolbar:CreateButton("Connect", "Connect to Rojo Session", "") + connectButton.ClickableWhenViewportHidden = true + + connectButton.Click:Connect(function() + connectButton:SetActive(false) + checkUpgrade(self.props.plugin) + + if self.state.sessionStatus == SessionStatus.Connected then + Logging.info("Disconnecting session") + + error("NYI") + elseif self.state.sessionStatus == SessionStatus.Disconnected then + Logging.info("Starting session configuration") + + self:setState({ + sessionStatus = SessionStatus.Configuring, + }) + elseif self.state.sessionStatus == SessionStatus.Configuring then + Logging.info("Canceling session configuration") + + self:setState({ + sessionStatus = SessionStatus.Disconnected, + }) + end + end) end return App \ No newline at end of file diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index ce54da7f..1457fe9c 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -5,6 +5,8 @@ local FitText = require(script.Parent.FitText) local e = Roact.createElement +local FORM_TEXT_SIZE = 20 + local ConnectPanel = Roact.Component:extend("ConnectPanel") function ConnectPanel:init() @@ -37,7 +39,7 @@ function ConnectPanel:render() return e(FitList, { containerProps = { - BackgroundColor3 = Color3.fromRGB(8, 8, 8), + BackgroundColor3 = Color3.fromRGB(32, 32, 32), BorderColor3 = Color3.fromRGB(64, 64, 64), Position = UDim2.new(0.5, 0, 0, 0), AnchorPoint = Vector2.new(0.5, 0), @@ -63,12 +65,13 @@ function ConnectPanel:render() }, }, { Label = e(FitText, { + MinSize = Vector2.new(0, 24), Kind = "TextLabel", LayoutOrder = 1, BackgroundTransparency = 1, TextXAlignment = Enum.TextXAlignment.Left, Font = Enum.Font.SourceSans, - TextSize = 16, + TextSize = FORM_TEXT_SIZE, Text = "Address", TextColor3 = Color3.fromRGB(245, 245, 245), @@ -81,23 +84,30 @@ function ConnectPanel:render() }), }), - Input = e("TextBox", { + InputOuter = e("Frame", { LayoutOrder = 2, - Size = UDim2.new(0, 300, 0, 20), - Font = Enum.Font.SourceSans, - ClearTextOnFocus = false, - TextXAlignment = Enum.TextXAlignment.Left, - TextSize = 16, - Text = self.state.address, - TextColor3 = Color3.fromRGB(245, 245, 245), - BackgroundColor3 = Color3.fromRGB(8, 8, 8), + Size = UDim2.new(0, 300, 0, 24), + BackgroundColor3 = Color3.fromRGB(32, 32, 32), BorderColor3 = Color3.fromRGB(64, 64, 64), + }, { + InputInner = e("TextBox", { + BackgroundTransparency = 1, + Size = UDim2.new(1, -8, 1, -8), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + Font = Enum.Font.SourceSans, + ClearTextOnFocus = false, + TextXAlignment = Enum.TextXAlignment.Left, + TextSize = FORM_TEXT_SIZE, + Text = self.state.address, + TextColor3 = Color3.fromRGB(245, 245, 245), - [Roact.Change.Text] = function(rbx) - self:setState({ - address = rbx.Text, - }) - end, + [Roact.Change.Text] = function(rbx) + self:setState({ + address = rbx.Text, + }) + end, + }), }), }), @@ -112,12 +122,13 @@ function ConnectPanel:render() }, }, { Label = e(FitText, { + MinSize = Vector2.new(0, 24), Kind = "TextLabel", LayoutOrder = 1, BackgroundTransparency = 1, TextXAlignment = Enum.TextXAlignment.Left, Font = Enum.Font.SourceSans, - TextSize = 16, + TextSize = FORM_TEXT_SIZE, Text = "Port", TextColor3 = Color3.fromRGB(245, 245, 245), @@ -130,23 +141,30 @@ function ConnectPanel:render() }), }), - Input = e("TextBox", { + InputOuter = e("Frame", { LayoutOrder = 2, - Size = UDim2.new(0, 300, 0, 20), - Font = Enum.Font.SourceSans, - ClearTextOnFocus = false, - TextXAlignment = Enum.TextXAlignment.Left, - TextSize = 16, - Text = self.state.port, - TextColor3 = Color3.fromRGB(245, 245, 245), - BackgroundColor3 = Color3.fromRGB(8, 8, 8), + Size = UDim2.new(0, 300, 0, 24), + BackgroundColor3 = Color3.fromRGB(32, 32, 32), BorderColor3 = Color3.fromRGB(64, 64, 64), + }, { + InputInner = e("TextBox", { + BackgroundTransparency = 1, + Size = UDim2.new(1, -8, 1, -8), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + Font = Enum.Font.SourceSans, + ClearTextOnFocus = false, + TextXAlignment = Enum.TextXAlignment.Left, + TextSize = FORM_TEXT_SIZE, + Text = self.state.port, + TextColor3 = Color3.fromRGB(245, 245, 245), - [Roact.Change.Text] = function(rbx) - self:setState({ - port = rbx.Text, - }) - end, + [Roact.Change.Text] = function(rbx) + self:setState({ + port = rbx.Text, + }) + end, + }), }), }), @@ -163,10 +181,13 @@ function ConnectPanel:render() e(FitText, { Kind = "TextButton", LayoutOrder = 1, - BackgroundColor3 = Color3.fromRGB(16, 16, 16), + BackgroundColor3 = Color3.fromRGB(32, 32, 32), BorderColor3 = Color3.fromRGB(64, 64, 64), TextColor3 = Color3.fromRGB(245, 245, 245), Text = "Start", + Font = Enum.Font.SourceSans, + TextSize = FORM_TEXT_SIZE, + Padding = Vector2.new(12, 3), [Roact.Event.Activated] = function() if startSession ~= nil then @@ -178,10 +199,13 @@ function ConnectPanel:render() e(FitText, { Kind = "TextButton", LayoutOrder = 2, - BackgroundColor3 = Color3.fromRGB(16, 16, 16), + BackgroundColor3 = Color3.fromRGB(32, 32, 32), BorderColor3 = Color3.fromRGB(64, 64, 64), TextColor3 = Color3.fromRGB(245, 245, 245), Text = "Cancel", + Font = Enum.Font.SourceSans, + TextSize = FORM_TEXT_SIZE, + Padding = Vector2.new(12, 3), [Roact.Event.Activated] = function() if cancel ~= nil then diff --git a/plugin/src/Components/ConnectionActivePanel.lua b/plugin/src/Components/ConnectionActivePanel.lua new file mode 100644 index 00000000..a63ea6aa --- /dev/null +++ b/plugin/src/Components/ConnectionActivePanel.lua @@ -0,0 +1,25 @@ +local Roact = require(script:FindFirstAncestor("Rojo").Roact) + +local FitText = require(script.Parent.FitText) + +local e = Roact.createElement + +local ConnectionActivePanel = Roact.Component:extend("ConnectionActivePanel") + +function ConnectionActivePanel:render() + return e(FitText, { + Kind = "TextLabel", + Padding = Vector2.new(4, 4), + Font = Enum.Font.SourceSans, + TextSize = 16, + Text = "Rojo Connected", + TextColor3 = Color3.new(1, 1, 1), + BackgroundColor3 = Color3.new(0, 0, 0), + BorderSizePixel = 0, + BackgroundTransparency = 0.6, + Position = UDim2.new(0.5, 0, 0, 0), + AnchorPoint = Vector2.new(0.5, 0), + }) +end + +return ConnectionActivePanel \ No newline at end of file diff --git a/plugin/src/Components/FitText.lua b/plugin/src/Components/FitText.lua index 2ec0b51b..673bcf03 100644 --- a/plugin/src/Components/FitText.lua +++ b/plugin/src/Components/FitText.lua @@ -18,6 +18,7 @@ function FitText:render() local containerProps = Dictionary.merge(self.props, { Kind = Dictionary.None, Padding = Dictionary.None, + MinSize = Dictionary.None, Size = self.sizeBinding }) @@ -33,6 +34,7 @@ function FitText:didUpdate() end function FitText:updateTextMeasurements() + local minSize = self.props.MinSize or Vector2.new(0, 0) local padding = self.props.Padding or Vector2.new(0, 0) local text = self.props.Text or "" @@ -41,8 +43,8 @@ function FitText:updateTextMeasurements() local measuredText = TextService:GetTextSize(text, textSize, font, Vector2.new(9e6, 9e6)) local totalSize = UDim2.new( - 0, padding.X * 2 + measuredText.X, - 0, padding.Y * 2 + measuredText.Y) + 0, math.max(minSize.X, padding.X * 2 + measuredText.X), + 0, math.max(minSize.Y, padding.Y * 2 + measuredText.Y)) self.setSize(totalSize) end diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 32be9573..6117e46c 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -2,8 +2,6 @@ local ApiContext = require(script.Parent.ApiContext) local Config = require(script.Parent.Config) local Logging = require(script.Parent.Logging) -local REMOTE_URL = ("http://localhost:%d"):format(Config.port) - local function makeInstanceMap() local self = { fromIds = {}, @@ -249,12 +247,16 @@ end local Session = {} Session.__index = Session -function Session.new(onError) +function Session.new(config) local self = {} + self.onError = config.onError + local instanceMap = makeInstanceMap() - local api = ApiContext.new(REMOTE_URL) + local remoteUrl = ("http://%s:%s"):format(config.address, config.port) + + local api = ApiContext.new(remoteUrl) ApiContext:onMessage(function(message) local requestedIds = {} @@ -277,7 +279,7 @@ function Session.new(onError) end) :catch(function(message) Logging.warn("%s", tostring(message)) - onError() + self.onError() end) end) @@ -292,7 +294,7 @@ function Session.new(onError) end) :catch(function(message) Logging.warn("%s", tostring(message)) - onError() + self.onError() end) return setmetatable(self, Session) diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index b956cbf2..dc547c85 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -8,81 +8,12 @@ Roact.setGlobalConfig({ elementTracing = true, }) -local Session = require(script.Session) -local Config = require(script.Config) -local Version = require(script.Version) -local Logging = require(script.Logging) -local DevSettings = require(script.DevSettings) local App = require(script.Components.App) -local function showUpgradeMessage(lastVersion) - local message = ( - "Rojo detected an upgrade from version %s to version %s." .. - "\nMake sure you have also upgraded your server!" .. - "\n\nRojo plugin version %s is intended for use with server version %s." - ):format( - Version.display(lastVersion), Version.display(Config.version), - Version.display(Config.version), Config.expectedServerVersionString - ) +local app = Roact.createElement(App, { + plugin = plugin, +}) - Logging.info(message) -end +Roact.mount(app, game:GetService("CoreGui"), "Rojo UI") ---[[ - Check if the user is using a newer version of Rojo than last time. If they - are, show them a reminder to make sure they check their server version. -]] -local function checkUpgrade() - -- When developing Rojo, there's no use in doing version checks - if DevSettings:isEnabled() then - return - end - - local lastVersion = plugin:GetSetting("LastRojoVersion") - - if lastVersion then - local wasUpgraded = Version.compare(Config.version, lastVersion) == 1 - - if wasUpgraded then - showUpgradeMessage(lastVersion) - end - end - - plugin:SetSetting("LastRojoVersion", Config.version) -end - -local function main() - local displayedVersion = DevSettings:isEnabled() - and Config.codename - or Version.display(Config.version) - - Logging.trace("Rojo %s initialized", displayedVersion) - - local toolbar = plugin:CreateToolbar("Rojo " .. displayedVersion) - - Roact.mount(Roact.createElement(App), game:GetService("CoreGui"), "Rojo UI") - - local currentSession - - -- TODO: Icon! - local connectButton = toolbar:CreateButton("Connect", "Connect to Rojo Session", "") - connectButton.ClickableWhenViewportHidden = true - - connectButton.Click:Connect(function() - connectButton:SetActive(false) - checkUpgrade() - - if currentSession ~= nil then - Logging.warn("A session is already running!") - return - end - - Logging.info("Started new session.") - currentSession = Session.new(function() - Logging.info("Session terminated.") - currentSession = nil - end) - end) -end - -main() \ No newline at end of file +-- TODO: Detect another instance of Rojo coming online and shut down this one. \ No newline at end of file From 9cfeee0577d5eb07cb3d07194065154821e9dbc6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 13:26:09 -0800 Subject: [PATCH 0300/1504] server: Make 'rojo serve' respect --port option --- server/src/bin.rs | 28 ++++++++++++++++--- server/src/commands/serve.rs | 52 ++++++++++++++++++++++++------------ server/src/web.rs | 2 +- 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/server/src/bin.rs b/server/src/bin.rs index 9dc1e529..8baec4b8 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -55,15 +55,37 @@ fn main() { let project_path = Path::new(sub_matches.value_of("PATH").unwrap_or(".")); let full_path = make_path_absolute(project_path); - librojo::commands::init(&full_path); + commands::init(&full_path); }, ("serve", Some(sub_matches)) => { - let project_path = match sub_matches.value_of("PROJECT") { + let fuzzy_project_path = match sub_matches.value_of("PROJECT") { Some(v) => make_path_absolute(Path::new(v)), None => std::env::current_dir().unwrap(), }; - librojo::commands::serve(&project_path); + let port = match sub_matches.value_of("port") { + Some(v) => match v.parse::() { + Ok(port) => port, + Err(_) => { + error!("Invalid port {}", v); + process::exit(1); + }, + }, + None => None, + }; + + let options = commands::ServeOptions { + fuzzy_project_path, + port, + }; + + match commands::serve(&options) { + Ok(_) => {}, + Err(e) => { + error!("{}", e); + process::exit(1); + }, + } }, ("build", Some(sub_matches)) => { let fuzzy_project_path = match sub_matches.value_of("PROJECT") { diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index d7c8e9a4..777df444 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -1,36 +1,54 @@ use std::{ - path::Path, - process, + path::PathBuf, sync::Arc, }; +use failure::Fail; + use crate::{ - project::Project, + project::{Project, ProjectLoadFuzzyError}, web::Server, session::Session, - // roblox_studio, }; -pub fn serve(fuzzy_project_location: &Path) { - info!("Looking for project at {}", fuzzy_project_location.display()); +const DEFAULT_PORT: u16 = 34872; - let project = match Project::load_fuzzy(fuzzy_project_location) { - Ok(project) => project, - Err(error) => { - error!("{}", error); - process::exit(1); - }, - }; +#[derive(Debug)] +pub struct ServeOptions { + pub fuzzy_project_path: PathBuf, + pub port: Option, +} + +#[derive(Debug, Fail)] +pub enum ServeError { + #[fail(display = "Project load error: {}", _0)] + ProjectLoadError(#[fail(cause)] ProjectLoadFuzzyError), +} + +impl From for ServeError { + fn from(error: ProjectLoadFuzzyError) -> ServeError { + ServeError::ProjectLoadError(error) + } +} + +pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { + info!("Looking for project at {}", options.fuzzy_project_path.display()); + + let project = Project::load_fuzzy(&options.fuzzy_project_path)?; info!("Found project at {}", project.file_location.display()); info!("Using project {:#?}", project); - // roblox_studio::install_bundled_plugin().unwrap(); - let session = Arc::new(Session::new(project).unwrap()); let server = Server::new(Arc::clone(&session)); - println!("Server listening on port 34872"); + let port = options.port + // .or(project.serve_port) + .unwrap_or(DEFAULT_PORT); - server.listen(34872); + println!("Rojo server listening on port {}", port); + + server.listen(port); + + Ok(()) } \ No newline at end of file diff --git a/server/src/web.rs b/server/src/web.rs index 679c1881..afb7a5cd 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -188,7 +188,7 @@ impl Server { ) } - pub fn listen(self, port: u64) { + pub fn listen(self, port: u16) { let address = format!("0.0.0.0:{}", port); rouille::start_server(address, move |request| self.handle_request(request)); From 64e2ef3d3b29715e7aec0bfebb3af5b72a833779 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 13:40:10 -0800 Subject: [PATCH 0301/1504] Fix build issue, add servePort project option --- server/src/bin.rs | 2 +- server/src/commands/serve.rs | 6 +++--- server/src/project.rs | 3 +++ server/src/session.rs | 3 +-- 4 files changed, 8 insertions(+), 6 deletions(-) diff --git a/server/src/bin.rs b/server/src/bin.rs index 8baec4b8..8145dce2 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -65,7 +65,7 @@ fn main() { let port = match sub_matches.value_of("port") { Some(v) => match v.parse::() { - Ok(port) => port, + Ok(port) => Some(port), Err(_) => { error!("Invalid port {}", v); process::exit(1); diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 777df444..3ed97e85 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -34,16 +34,16 @@ impl From for ServeError { pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { info!("Looking for project at {}", options.fuzzy_project_path.display()); - let project = Project::load_fuzzy(&options.fuzzy_project_path)?; + let project = Arc::new(Project::load_fuzzy(&options.fuzzy_project_path)?); info!("Found project at {}", project.file_location.display()); info!("Using project {:#?}", project); - let session = Arc::new(Session::new(project).unwrap()); + let session = Arc::new(Session::new(Arc::clone(&project)).unwrap()); let server = Server::new(Arc::clone(&session)); let port = options.port - // .or(project.serve_port) + .or(project.serve_port) .unwrap_or(DEFAULT_PORT); println!("Rojo server listening on port {}", port); diff --git a/server/src/project.rs b/server/src/project.rs index ce643427..01b8d552 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -77,6 +77,7 @@ impl SourceProjectNode { struct SourceProject { name: String, tree: SourceProjectNode, + serve_port: Option, } impl SourceProject { @@ -86,6 +87,7 @@ impl SourceProject { Project { name: self.name, tree, + serve_port: self.serve_port, file_location: PathBuf::from(project_file_location), } } @@ -169,6 +171,7 @@ pub struct SyncPointProjectNode { pub struct Project { pub name: String, pub tree: ProjectNode, + pub serve_port: Option, pub file_location: PathBuf, } diff --git a/server/src/session.rs b/server/src/session.rs index 91a286ee..76953e9f 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -23,14 +23,13 @@ pub struct Session { } impl Session { - pub fn new(project: Project) -> io::Result { + pub fn new(project: Arc) -> io::Result { let imfs = { let mut imfs = Imfs::new(); imfs.add_roots_from_project(&project)?; Arc::new(Mutex::new(imfs)) }; - let project = Arc::new(project); let message_queue = Arc::new(MessageQueue::new()); let rbx_session = Arc::new(Mutex::new(RbxSession::new( From ae36688bf2efcb05227db63794cb75d4b5e5aa9d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 13:48:50 -0800 Subject: [PATCH 0302/1504] server: Add servePlaceId for verifying correct place IDs --- server/src/project.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/project.rs b/server/src/project.rs index 01b8d552..4a30df4c 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -78,6 +78,7 @@ struct SourceProject { name: String, tree: SourceProjectNode, serve_port: Option, + serve_place_id: Option, } impl SourceProject { @@ -88,6 +89,7 @@ impl SourceProject { name: self.name, tree, serve_port: self.serve_port, + serve_place_id: self.serve_place_id, file_location: PathBuf::from(project_file_location), } } @@ -172,6 +174,7 @@ pub struct Project { pub name: String, pub tree: ProjectNode, pub serve_port: Option, + pub serve_place_id: Option, pub file_location: PathBuf, } From 1138c05dff9b9c8db295a86cf2ad528f6814370e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 13:49:08 -0800 Subject: [PATCH 0303/1504] plugin: Remove unused import --- plugin/src/Session.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 6117e46c..5d789533 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -1,5 +1,4 @@ local ApiContext = require(script.Parent.ApiContext) -local Config = require(script.Parent.Config) local Logging = require(script.Parent.Logging) local function makeInstanceMap() From b8025452bffff8cc51d5d38b2ee20dcb11e97f1b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 14:11:06 -0800 Subject: [PATCH 0304/1504] server: Make servePlaceId into a list of IDs, servePlaceIds --- server/src/project.rs | 7 ++++--- server/src/web.rs | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/server/src/project.rs b/server/src/project.rs index 4a30df4c..ab79e3d5 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -1,5 +1,5 @@ use std::{ - collections::HashMap, + collections::{HashMap, HashSet}, fs, io, path::{Path, PathBuf}, @@ -78,6 +78,7 @@ struct SourceProject { name: String, tree: SourceProjectNode, serve_port: Option, + serve_place_ids: Option>, serve_place_id: Option, } @@ -89,7 +90,7 @@ impl SourceProject { name: self.name, tree, serve_port: self.serve_port, - serve_place_id: self.serve_place_id, + serve_place_ids: self.serve_place_ids, file_location: PathBuf::from(project_file_location), } } @@ -174,7 +175,7 @@ pub struct Project { pub name: String, pub tree: ProjectNode, pub serve_port: Option, - pub serve_place_id: Option, + pub serve_place_ids: Option>, pub file_location: PathBuf, } diff --git a/server/src/web.rs b/server/src/web.rs index afb7a5cd..5be2cef5 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -1,6 +1,6 @@ use std::{ borrow::Cow, - collections::HashMap, + collections::{HashMap, HashSet}, sync::{mpsc, Arc}, }; @@ -26,6 +26,7 @@ pub struct ServerInfoResponse<'a> { pub session_id: SessionId, pub server_version: &'a str, pub protocol_version: u64, + pub expected_place_ids: Option>, pub root_instance_id: RbxId, pub instance_metadata_map: Cow<'a, HashMap>, } @@ -78,6 +79,7 @@ impl Server { server_version: self.server_version, protocol_version: 2, session_id: self.session.session_id, + expected_place_ids: self.session.project.serve_place_ids.clone(), root_instance_id: tree.get_root_id(), instance_metadata_map: Cow::Borrowed(rbx_session.get_instance_metadata_map()), }) From 699e07a0f751771da988ff973ce9914ef7d4ae45 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 14:11:33 -0800 Subject: [PATCH 0305/1504] plugin: Add support for expectedPlaceIds in the protocol --- plugin/src/ApiContext.lua | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index d7a5b6d6..aba7f53d 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -66,6 +66,36 @@ function ApiContext:connect() return Promise.reject(message) end + if body.expectedPlaceIds ~= nil then + local foundId = false + + for _, id in ipairs(body.expectedPlaceIds) do + if id == game.PlaceId then + foundId = true + break + end + end + + if not foundId then + local idList = {} + for _, id in ipairs(body.expectedPlaceIds) do + table.insert(idList, "- " .. tostring(id)) + end + + local message = ( + "Found a Rojo server, but its project is set to only be used with a specific list of places." .. + "\nYour place ID is %s, but needs to be one of these:" .. + "\n%s" .. + "\n\nTo change this list, edit 'servePlaceIds' in roblox-project.json" + ):format( + tostring(game.PlaceId), + table.concat(idList, "\n") + ) + + return Promise.reject(message) + end + end + self.serverId = body.serverId self.connected = true self.partitionRoutes = body.partitions From b5ae6a5785143e72cfa2bff58d6753459ab6d50e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 14:21:16 -0800 Subject: [PATCH 0306/1504] server: Fix broken test from adding more Project fields --- server/tests/read_projects.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index 3a180b75..239016c2 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -82,6 +82,8 @@ fn single_sync_point() { Project { name: "single-sync-point".to_string(), tree: root_node, + serve_port: None, + serve_place_ids: None, file_location: project_file_location.clone(), } }; From 5c2bf65eaa6a1de2f3dbc1d6c118ad6f246a1a53 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 14:30:00 -0800 Subject: [PATCH 0307/1504] protocol/config: ignoreUnknown -> ignoreUnknownInstances --- plugin/src/Session.lua | 2 +- server/src/project.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 5d789533..ce8de667 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -74,7 +74,7 @@ end local function shouldClearUnknown(id, instanceMetadataMap) if instanceMetadataMap[id] then - return not instanceMetadataMap[id].ignoreUnknown + return not instanceMetadataMap[id].ignoreUnknownInstances else return true end diff --git a/server/src/project.rs b/server/src/project.rs index ab79e3d5..61cce205 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -25,8 +25,8 @@ enum SourceProjectNode { #[serde(rename = "$properties", default = "HashMap::new")] properties: HashMap, - #[serde(rename = "$ignoreUnknown", default = "yeah")] - ignore_unknown: bool, + #[serde(rename = "$ignoreUnknownInstances", default = "yeah")] + ignore_unknown_instances: bool, #[serde(flatten)] children: HashMap, @@ -40,7 +40,7 @@ enum SourceProjectNode { impl SourceProjectNode { pub fn into_project_node(self, project_file_location: &Path) -> ProjectNode { match self { - SourceProjectNode::Instance { class_name, mut children, properties, ignore_unknown } => { + SourceProjectNode::Instance { class_name, mut children, properties, ignore_unknown_instances } => { let mut new_children = HashMap::new(); for (node_name, node) in children.drain() { @@ -52,7 +52,7 @@ impl SourceProjectNode { children: new_children, properties, metadata: InstanceProjectNodeMetadata { - ignore_unknown, + ignore_unknown_instances, }, }) }, @@ -137,13 +137,13 @@ pub struct ProjectSaveError; #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct InstanceProjectNodeMetadata { - pub ignore_unknown: bool, + pub ignore_unknown_instances: bool, } impl Default for InstanceProjectNodeMetadata { fn default() -> InstanceProjectNodeMetadata { InstanceProjectNodeMetadata { - ignore_unknown: true, + ignore_unknown_instances: true, } } } From 02a3da111a37aa15bf9bad902bb8efa6c15dc79b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 14:55:53 -0800 Subject: [PATCH 0308/1504] plugin: Fix test runner for new TestEZ --- plugin/spec.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/spec.lua b/plugin/spec.lua index 25e23181..22ed2543 100644 --- a/plugin/spec.lua +++ b/plugin/spec.lua @@ -9,7 +9,7 @@ local habitat, modules = loadEnvironment() -- Load TestEZ and run our tests local TestEZ = habitat:require(modules.TestEZ) -local results = TestEZ.TestBootstrap:run(modules.Rojo, TestEZ.Reporters.TextReporter) +local results = TestEZ.TestBootstrap:run({modules.Rojo}, TestEZ.Reporters.TextReporter) -- Did something go wrong? if results.failureCount > 0 then From 837fd222545839d88fa510b216ac5e4f2ce987fa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 15:44:59 -0800 Subject: [PATCH 0309/1504] Update README to indicate that the new year happened --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 05b09ba0..e5bcb490 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ Rojo lets you: * Version your place, library, or plugin using Git or another VCS * Sync JSON-format models from the filesystem into your game -Later in 2018, Rojo will be able to: +Soon, Rojo will be able to: * Sync scripts from Roblox Studio to the filesystem * Compile MoonScript and sync it into Roblox Studio From 1888c83b6e8e5e30debfb2919539a80cba55382f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 18:22:53 -0800 Subject: [PATCH 0310/1504] server: Update dependencies --- server/Cargo.lock | 198 ++++++++++++++++++++++++---------------------- 1 file changed, 105 insertions(+), 93 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 2d8060fc..3856f1de 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -29,7 +29,7 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -45,20 +45,20 @@ version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace-sys 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.26" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -85,8 +85,8 @@ name = "brotli-sys" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -95,7 +95,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -138,14 +138,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.26" +version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -295,16 +295,16 @@ dependencies = [ [[package]] name = "failure" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -319,8 +319,8 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -330,7 +330,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -338,7 +338,7 @@ name = "fsevent-sys" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -404,7 +404,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -415,7 +415,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -423,7 +423,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -453,7 +453,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.45" +version = "0.2.46" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -486,7 +486,7 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -496,8 +496,8 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -510,7 +510,7 @@ name = "memchr" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -519,7 +519,7 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -552,7 +552,7 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -604,7 +604,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -619,7 +619,7 @@ dependencies = [ "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -644,7 +644,7 @@ name = "num_cpus" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -669,7 +669,7 @@ name = "parking_lot_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -751,7 +751,7 @@ version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -761,7 +761,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -772,36 +772,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.6.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_chacha" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -833,6 +832,18 @@ dependencies = [ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_os" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_pcg" version = "0.1.1" @@ -844,7 +855,7 @@ dependencies = [ [[package]] name = "rand_xorshift" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -853,7 +864,7 @@ dependencies = [ [[package]] name = "rbx_binary" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#ff15a6d54bd136921ad3fdd901a31b6cc003d630" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#ef0f7310931e9f10bdc37a0e8a823c1309a7c198" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -863,17 +874,17 @@ dependencies = [ [[package]] name = "rbx_tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#ff15a6d54bd136921ad3fdd901a31b6cc003d630" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#ef0f7310931e9f10bdc37a0e8a823c1309a7c198" dependencies = [ - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_xml" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#ff15a6d54bd136921ad3fdd901a31b6cc003d630" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#ef0f7310931e9f10bdc37a0e8a823c1309a7c198" dependencies = [ "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -881,7 +892,7 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.44" +version = "0.1.50" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -889,7 +900,7 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -926,7 +937,7 @@ version = "0.5.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -936,9 +947,9 @@ dependencies = [ "rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -957,20 +968,20 @@ dependencies = [ "multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny_http 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1015,7 +1026,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1025,12 +1036,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.82" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.82" +version = "1.0.84" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1040,12 +1051,12 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1068,7 +1079,7 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1132,9 +1143,9 @@ version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1161,8 +1172,8 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1195,14 +1206,14 @@ name = "time" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tiny_http" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1321,7 +1332,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1417,7 +1428,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727" "checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" -"checksum backtrace-sys 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3fcce89e5ad5c8949caa9434501f7b55415b3e7ad5270cb88c75a8d35e8f1279" +"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" @@ -1429,7 +1440,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cc 1.0.26 (registry+https://github.com/rust-lang/crates.io-index)" = "389803e36973d242e7fecb092b2de44a3d35ac62524b3b9339e51d577d668e02" +"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" @@ -1447,8 +1458,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" -"checksum failure 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6dd377bcc1b1b7ce911967e3ec24fa19c3224394ec05b54aa7b083d498341ac7" -"checksum failure_derive 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "64c2d913fe8ed3b6c6518eedf4538255b989945c14c2a7d5cbff62a5e2120596" +"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" +"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" "checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05" "checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874" @@ -1467,7 +1478,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)" = "2d2857ec59fadc0773853c664d2d18e7198e83883e7060b63c924cb077bd5c74" +"checksum libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)" = "023a4cd09b2ff695f9734c1934145a315594b7986398496841c7031a5a1bbdbd" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" @@ -1502,24 +1513,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae9d223d52ae411a33cf7e54ec6034ec165df296ccd23533d671a28252b6f66a" -"checksum rand_chacha 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "771b009e3a508cb67e8823dda454aaa5368c7bc1c16829fb77d3e980440dd34a" +"checksum rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b65e163105a6284f841bd23100a015895f54340e88a5ffc9ca7b8b33827cfce0" +"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" +"checksum rand_os 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de5ac4de1c2973e1391dc305cb0fbf8788cb58068e98255439b7485a77022273" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" -"checksum rand_xorshift 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effa3fcaa47e18db002bdde6060944b6d2f9cfd8db471c30e873448ad9187be3" +"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" -"checksum redox_syscall 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "a84bcd297b87a545980a2d25a0beb72a1f490c31f0a9fde52fca35bfbb1ceb70" +"checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841" -"checksum rustc-demangle 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "01b90379b8664dd83460d59bdc5dd1fd3172b8913788db483ed1325171eab2f7" +"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" @@ -1528,9 +1540,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "6fa52f19aee12441d5ad11c9a00459122bd8f98707cadf9778c540674f1935b6" -"checksum serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "96a7f9496ac65a2db5929afa087b54f8fc5008dcfbe48a8874ed20049b0d6154" -"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811" +"checksum serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "0e732ed5a5592c17d961555e3b552985baf98d50ce418b7b655f31f6ba7eb1b7" +"checksum serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d6115a3ca25c224e409185325afc16a0d5aaaabc15c42b09587d6f1ba39a5b" +"checksum serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "bdf540260cfee6da923831f4776ddc495ada940c30117977c70f1313a6130545" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" @@ -1549,7 +1561,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c" -"checksum tiny_http 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a442681f9f72e440be192700eeb2861e4174b9983f16f4877c93a134cb5e5f63" +"checksum tiny_http 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "29909009df3f0541d1851992c5cab50209eceaf2eb4b3d1ef395a39f555173c3" "checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde" "checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21" "checksum tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "502b625acb4ee13cbb3b90b8ca80e0addd263ddacf6931666ef751e610b07fb5" From c57989a7906120a2098f4f0d140e5d75c0a9325e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 18:23:07 -0800 Subject: [PATCH 0311/1504] plugin: Title bar in session window, clean up Config --- plugin/src/Components/ConnectPanel.lua | 318 +++++++++++++------------ plugin/src/Config.lua | 5 +- 2 files changed, 175 insertions(+), 148 deletions(-) diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index 1457fe9c..5de9b10e 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -1,5 +1,7 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) +local Config = require(script.Parent.Parent.Config) + local FitList = require(script.Parent.FitList) local FitText = require(script.Parent.FitText) @@ -14,8 +16,8 @@ function ConnectPanel:init() self.labelSize, self.setLabelSize = Roact.createBinding(Vector2.new()) self:setState({ - address = "localhost", - port = "34872", + address = Config.defaultHost, + port = Config.defaultPort, }) end @@ -44,175 +46,199 @@ function ConnectPanel:render() Position = UDim2.new(0.5, 0, 0, 0), AnchorPoint = Vector2.new(0.5, 0), }, - layoutProps = { - Padding = UDim.new(0, 8), - }, - paddingProps = { - PaddingTop = UDim.new(0, 8), - PaddingBottom = UDim.new(0, 8), - PaddingLeft = UDim.new(0, 8), - PaddingRight = UDim.new(0, 8), - }, }, { - Address = e(FitList, { - containerProps = { - LayoutOrder = 1, - BackgroundTransparency = 1, - }, - layoutProps = { - FillDirection = Enum.FillDirection.Horizontal, - Padding = UDim.new(0, 8), - }, + Title = e("TextLabel", { + LayoutOrder = 1, + Font = Enum.Font.SourceSans, + TextSize = 22, + Text = "Start Rojo Session", + Size = UDim2.new(1, 0, 0, 28), + BackgroundTransparency = 1, + TextColor3 = Color3.new(1, 1, 1), }, { - Label = e(FitText, { - MinSize = Vector2.new(0, 24), - Kind = "TextLabel", - LayoutOrder = 1, - BackgroundTransparency = 1, - TextXAlignment = Enum.TextXAlignment.Left, - Font = Enum.Font.SourceSans, - TextSize = FORM_TEXT_SIZE, - Text = "Address", - TextColor3 = Color3.fromRGB(245, 245, 245), - - [Roact.Change.AbsoluteSize] = function(rbx) - self:updateLabelSize("address", rbx.AbsoluteSize) - end, - }, { - Sizing = e("UISizeConstraint", { - MinSize = self.labelSize, - }), - }), - - InputOuter = e("Frame", { - LayoutOrder = 2, - Size = UDim2.new(0, 300, 0, 24), - BackgroundColor3 = Color3.fromRGB(32, 32, 32), - BorderColor3 = Color3.fromRGB(64, 64, 64), - }, { - InputInner = e("TextBox", { - BackgroundTransparency = 1, - Size = UDim2.new(1, -8, 1, -8), - Position = UDim2.new(0.5, 0, 0.5, 0), - AnchorPoint = Vector2.new(0.5, 0.5), - Font = Enum.Font.SourceSans, - ClearTextOnFocus = false, - TextXAlignment = Enum.TextXAlignment.Left, - TextSize = FORM_TEXT_SIZE, - Text = self.state.address, - TextColor3 = Color3.fromRGB(245, 245, 245), - - [Roact.Change.Text] = function(rbx) - self:setState({ - address = rbx.Text, - }) - end, - }), + BottomBorder = e("Frame", { + BorderSizePixel = 0, + BackgroundColor3 = Color3.fromRGB(48, 48, 48), + Size = UDim2.new(1, 0, 0, 1), + Position = UDim2.new(0, 0, 1, -1), }), }), - Port = e(FitList, { + Body = e(FitList, { containerProps = { - LayoutOrder = 2, BackgroundTransparency = 1, + LayoutOrder = 2, }, layoutProps = { - FillDirection = Enum.FillDirection.Horizontal, Padding = UDim.new(0, 8), }, + paddingProps = { + PaddingTop = UDim.new(0, 8), + PaddingBottom = UDim.new(0, 8), + PaddingLeft = UDim.new(0, 8), + PaddingRight = UDim.new(0, 8), + }, }, { - Label = e(FitText, { - MinSize = Vector2.new(0, 24), - Kind = "TextLabel", - LayoutOrder = 1, - BackgroundTransparency = 1, - TextXAlignment = Enum.TextXAlignment.Left, - Font = Enum.Font.SourceSans, - TextSize = FORM_TEXT_SIZE, - Text = "Port", - TextColor3 = Color3.fromRGB(245, 245, 245), - - [Roact.Change.AbsoluteSize] = function(rbx) - self:updateLabelSize("port", rbx.AbsoluteSize) - end, - }, { - Sizing = e("UISizeConstraint", { - MinSize = self.labelSize, - }), - }), - - InputOuter = e("Frame", { - LayoutOrder = 2, - Size = UDim2.new(0, 300, 0, 24), - BackgroundColor3 = Color3.fromRGB(32, 32, 32), - BorderColor3 = Color3.fromRGB(64, 64, 64), - }, { - InputInner = e("TextBox", { + Address = e(FitList, { + containerProps = { + LayoutOrder = 1, + BackgroundTransparency = 1, + }, + layoutProps = { + FillDirection = Enum.FillDirection.Horizontal, + Padding = UDim.new(0, 8), + }, + }, { + Label = e(FitText, { + MinSize = Vector2.new(0, 24), + Kind = "TextLabel", + LayoutOrder = 1, BackgroundTransparency = 1, - Size = UDim2.new(1, -8, 1, -8), - Position = UDim2.new(0.5, 0, 0.5, 0), - AnchorPoint = Vector2.new(0.5, 0.5), - Font = Enum.Font.SourceSans, - ClearTextOnFocus = false, TextXAlignment = Enum.TextXAlignment.Left, + Font = Enum.Font.SourceSans, TextSize = FORM_TEXT_SIZE, - Text = self.state.port, + Text = "Address", TextColor3 = Color3.fromRGB(245, 245, 245), - [Roact.Change.Text] = function(rbx) - self:setState({ - port = rbx.Text, - }) + [Roact.Change.AbsoluteSize] = function(rbx) + self:updateLabelSize("address", rbx.AbsoluteSize) end, + }, { + Sizing = e("UISizeConstraint", { + MinSize = self.labelSize, + }), + }), + + InputOuter = e("Frame", { + LayoutOrder = 2, + Size = UDim2.new(0, 300, 0, 24), + BackgroundColor3 = Color3.fromRGB(32, 32, 32), + BorderColor3 = Color3.fromRGB(64, 64, 64), + }, { + InputInner = e("TextBox", { + BackgroundTransparency = 1, + Size = UDim2.new(1, -8, 1, -8), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + Font = Enum.Font.SourceSans, + ClearTextOnFocus = false, + TextXAlignment = Enum.TextXAlignment.Left, + TextSize = FORM_TEXT_SIZE, + Text = self.state.address, + TextColor3 = Color3.fromRGB(245, 245, 245), + + [Roact.Change.Text] = function(rbx) + self:setState({ + address = rbx.Text, + }) + end, + }), }), }), - }), - Buttons = e(FitList, { - containerProps = { - LayoutOrder = 3, - BackgroundTransparency = 1, - }, - layoutProps = { - FillDirection = Enum.FillDirection.Horizontal, - Padding = UDim.new(0, 8), - }, - }, { - e(FitText, { - Kind = "TextButton", - LayoutOrder = 1, - BackgroundColor3 = Color3.fromRGB(32, 32, 32), - BorderColor3 = Color3.fromRGB(64, 64, 64), - TextColor3 = Color3.fromRGB(245, 245, 245), - Text = "Start", - Font = Enum.Font.SourceSans, - TextSize = FORM_TEXT_SIZE, - Padding = Vector2.new(12, 3), + Port = e(FitList, { + containerProps = { + LayoutOrder = 2, + BackgroundTransparency = 1, + }, + layoutProps = { + FillDirection = Enum.FillDirection.Horizontal, + Padding = UDim.new(0, 8), + }, + }, { + Label = e(FitText, { + MinSize = Vector2.new(0, 24), + Kind = "TextLabel", + LayoutOrder = 1, + BackgroundTransparency = 1, + TextXAlignment = Enum.TextXAlignment.Left, + Font = Enum.Font.SourceSans, + TextSize = FORM_TEXT_SIZE, + Text = "Port", + TextColor3 = Color3.fromRGB(245, 245, 245), - [Roact.Event.Activated] = function() - if startSession ~= nil then - startSession(self.state.address, self.state.port) - end - end, + [Roact.Change.AbsoluteSize] = function(rbx) + self:updateLabelSize("port", rbx.AbsoluteSize) + end, + }, { + Sizing = e("UISizeConstraint", { + MinSize = self.labelSize, + }), + }), + + InputOuter = e("Frame", { + LayoutOrder = 2, + Size = UDim2.new(0, 300, 0, 24), + BackgroundColor3 = Color3.fromRGB(32, 32, 32), + BorderColor3 = Color3.fromRGB(64, 64, 64), + }, { + InputInner = e("TextBox", { + BackgroundTransparency = 1, + Size = UDim2.new(1, -8, 1, -8), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + Font = Enum.Font.SourceSans, + ClearTextOnFocus = false, + TextXAlignment = Enum.TextXAlignment.Left, + TextSize = FORM_TEXT_SIZE, + Text = self.state.port, + TextColor3 = Color3.fromRGB(245, 245, 245), + + [Roact.Change.Text] = function(rbx) + self:setState({ + port = rbx.Text, + }) + end, + }), + }), }), - e(FitText, { - Kind = "TextButton", - LayoutOrder = 2, - BackgroundColor3 = Color3.fromRGB(32, 32, 32), - BorderColor3 = Color3.fromRGB(64, 64, 64), - TextColor3 = Color3.fromRGB(245, 245, 245), - Text = "Cancel", - Font = Enum.Font.SourceSans, - TextSize = FORM_TEXT_SIZE, - Padding = Vector2.new(12, 3), + Buttons = e(FitList, { + containerProps = { + LayoutOrder = 3, + BackgroundTransparency = 1, + }, + layoutProps = { + FillDirection = Enum.FillDirection.Horizontal, + Padding = UDim.new(0, 8), + }, + }, { + e(FitText, { + Kind = "TextButton", + LayoutOrder = 1, + BackgroundColor3 = Color3.fromRGB(32, 32, 32), + BorderColor3 = Color3.fromRGB(64, 64, 64), + TextColor3 = Color3.fromRGB(245, 245, 245), + Text = "Start", + Font = Enum.Font.SourceSans, + TextSize = FORM_TEXT_SIZE, + Padding = Vector2.new(12, 3), - [Roact.Event.Activated] = function() - if cancel ~= nil then - cancel() - end - end, - }), + [Roact.Event.Activated] = function() + if startSession ~= nil then + startSession(self.state.address, self.state.port) + end + end, + }), + + e(FitText, { + Kind = "TextButton", + LayoutOrder = 2, + BackgroundColor3 = Color3.fromRGB(32, 32, 32), + BorderColor3 = Color3.fromRGB(64, 64, 64), + TextColor3 = Color3.fromRGB(245, 245, 245), + Text = "Cancel", + Font = Enum.Font.SourceSans, + TextSize = FORM_TEXT_SIZE, + Padding = Vector2.new(12, 3), + + [Roact.Event.Activated] = function() + if cancel ~= nil then + cancel() + end + end, + }), + }) }) }) end diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 1525c2f8..09cb5eb8 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -3,5 +3,6 @@ return { version = {0, 5, 0}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, - port = 34872, -} + defaultHost = "localhost", + defaultPort = 34872, +} \ No newline at end of file From 27245341562ba495b9b285a050f0d801f0ac48e2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Jan 2019 18:34:48 -0800 Subject: [PATCH 0312/1504] Factor out reconciliation into separate module --- plugin/src/Reconciler.lua | 256 ++++++++++++++++++++++++++++++++++++++ plugin/src/Session.lua | 252 +------------------------------------ 2 files changed, 262 insertions(+), 246 deletions(-) create mode 100644 plugin/src/Reconciler.lua diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua new file mode 100644 index 00000000..60e637a7 --- /dev/null +++ b/plugin/src/Reconciler.lua @@ -0,0 +1,256 @@ +local Logging = require(script.Parent.Logging) + +local function makeInstanceMap() + local self = { + fromIds = {}, + fromInstances = {}, + } + + function self:insert(id, instance) + self.fromIds[id] = instance + self.fromInstances[instance] = id + end + + function self:removeId(id) + local instance = self.fromIds[id] + + if instance ~= nil then + self.fromIds[id] = nil + self.fromInstances[instance] = nil + else + Logging.warn("Attempted to remove nonexistant ID %s", tostring(id)) + end + end + + function self:removeInstance(instance) + local id = self.fromInstances[instance] + + if id ~= nil then + self.fromInstances[instance] = nil + self.fromIds[id] = nil + else + Logging.warn("Attempted to remove nonexistant instance %s", tostring(instance)) + end + end + + function self:destroyId(id) + local instance = self.fromIds[id] + self:removeId(id) + + if instance ~= nil then + local descendantsToDestroy = {} + + for otherInstance in pairs(self.fromInstances) do + if otherInstance:IsDescendantOf(instance) then + table.insert(descendantsToDestroy, otherInstance) + end + end + + for _, otherInstance in ipairs(descendantsToDestroy) do + self:removeInstance(otherInstance) + end + + instance:Destroy() + else + Logging.warn("Attempted to destroy nonexistant ID %s", tostring(id)) + end + end + + return self +end + +local function setProperty(instance, key, value) + local ok, err = pcall(function() + if instance[key] ~= value then + instance[key] = value + end + end) + + if not ok then + error(("Cannot set property %s on class %s: %s"):format(tostring(key), instance.ClassName, err), 2) + end +end + +local Reconciler = {} +Reconciler.__index = Reconciler + +function Reconciler.new(instanceMetadataMap) + local self = { + instanceMap = makeInstanceMap(), + instanceMetadataMap = instanceMetadataMap, + } + + return setmetatable(self, Reconciler) +end + +function Reconciler:applyUpdate(requestedIds, virtualInstancesById) + -- This function may eventually be asynchronous; it will require calls to + -- the server to resolve instances that don't exist yet. + local visitedIds = {} + + for _, id in ipairs(requestedIds) do + self:__applyUpdatePiece(id, visitedIds, virtualInstancesById) + end +end + +--[[ + Update an existing instance, including its properties and children, to match + the given information. +]] +function Reconciler:reconcile(virtualInstancesById, id, instance) + local virtualInstance = virtualInstancesById[id] + + -- If an instance changes ClassName, we assume it's very different. That's + -- not always the case! + if virtualInstance.ClassName ~= instance.ClassName then + -- TODO: Preserve existing children instead? + local parent = instance.Parent + self.instanceMap:destroyId(id) + return self:__reify(virtualInstancesById, id, parent) + end + + self.instanceMap:insert(id, instance) + + -- Some instances don't like being named, even if their name already matches + setProperty(instance, "Name", virtualInstance.Name) + + for key, value in pairs(virtualInstance.Properties) do + setProperty(instance, key, value.Value) + end + + local existingChildren = instance:GetChildren() + + local unvisitedExistingChildren = {} + for _, child in ipairs(existingChildren) do + unvisitedExistingChildren[child] = true + end + + for _, childId in ipairs(virtualInstance.Children) do + local childData = virtualInstancesById[childId] + + local existingChildInstance + for instance in pairs(unvisitedExistingChildren) do + local ok, name, className = pcall(function() + return instance.Name, instance.ClassName + end) + + if ok then + if name == childData.Name and className == childData.ClassName then + existingChildInstance = instance + break + end + end + end + + if existingChildInstance ~= nil then + unvisitedExistingChildren[existingChildInstance] = nil + self:reconcile(virtualInstancesById, childId, existingChildInstance) + else + self:__reify(virtualInstancesById, childId, instance) + end + end + + if self:__shouldClearUnknownInstances(id) then + for existingChildInstance in pairs(unvisitedExistingChildren) do + self.instanceMap:removeInstance(existingChildInstance) + existingChildInstance:Destroy() + end + end + + -- The root instance of a project won't have a parent, like the DataModel, + -- so we need to be careful here. + if virtualInstance.Parent ~= nil then + local parent = self.instanceMap.fromIds[virtualInstance.Parent] + + if parent == nil then + Logging.info("Instance %s wanted parent of %s", tostring(id), tostring(virtualInstance.Parent)) + error("Rojo bug: During reconciliation, an instance referred to an instance ID as parent that does not exist.") + end + + -- Some instances, like services, don't like having their Parent + -- property poked, even if we're setting it to the same value. + setProperty(instance, "Parent", parent) + if instance.Parent ~= parent then + instance.Parent = parent + end + end + + return instance +end + +function Reconciler:__shouldClearUnknownInstances(id) + if self.instanceMetadataMap[id] then + return not self.instanceMetadataMap[id].ignoreUnknownInstances + else + return true + end +end + +function Reconciler:__reify(virtualInstancesById, id, parent) + local virtualInstance = virtualInstancesById[id] + + local instance = Instance.new(virtualInstance.ClassName) + + for key, value in pairs(virtualInstance.Properties) do + -- TODO: Branch on value.Type + setProperty(instance, key, value.Value) + end + + instance.Name = virtualInstance.Name + + for _, childId in ipairs(virtualInstance.Children) do + self:__reify(virtualInstancesById, childId, instance) + end + + setProperty(instance, "Parent", parent) + self.instanceMap:insert(id, instance) + + return instance +end + +function Reconciler:__applyUpdatePiece(id, visitedIds, virtualInstancesById) + if visitedIds[id] then + return + end + + visitedIds[id] = true + + local virtualInstance = virtualInstancesById[id] + local instance = self.instanceMap.fromIds[id] + + -- The instance was deleted in this update + if virtualInstance == nil then + self.instanceMap:destroyId(id) + return + end + + -- An instance we know about was updated + if instance ~= nil then + self:reconcile(virtualInstancesById, id, instance) + return instance + end + + -- If the instance's parent already exists, we can stick it there + local parentInstance = self.instanceMap.fromIds[virtualInstance.Parent] + if parentInstance ~= nil then + self:__reify(virtualInstancesById, id, parentInstance) + return + end + + -- Otherwise, we can check if this response payload contained the parent and + -- work from there instead. + local parentData = virtualInstancesById[virtualInstance.Parent] + if parentData ~= nil then + if visitedIds[virtualInstance.Parent] then + error("Rojo bug: An instance was present and marked as visited but its instance was missing") + end + + self:__applyUpdatePiece(virtualInstance.Parent, visitedIds, virtualInstancesById) + return + end + + Logging.trace("Instance ID %s, parent ID %s", tostring(id), tostring(virtualInstance.Parent)) + error("Rojo NYI: Instances with parents that weren't mentioned in an update payload") +end + +return Reconciler \ No newline at end of file diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index ce8de667..fd086ff7 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -1,247 +1,6 @@ local ApiContext = require(script.Parent.ApiContext) local Logging = require(script.Parent.Logging) - -local function makeInstanceMap() - local self = { - fromIds = {}, - fromInstances = {}, - } - - function self:insert(id, instance) - self.fromIds[id] = instance - self.fromInstances[instance] = id - end - - function self:removeId(id) - local instance = self.fromIds[id] - - if instance ~= nil then - self.fromIds[id] = nil - self.fromInstances[instance] = nil - else - Logging.warn("Attempted to remove nonexistant ID %s", tostring(id)) - end - end - - function self:removeInstance(instance) - local id = self.fromInstances[instance] - - if id ~= nil then - self.fromInstances[instance] = nil - self.fromIds[id] = nil - else - Logging.warn("Attempted to remove nonexistant instance %s", tostring(instance)) - end - end - - function self:destroyId(id) - local instance = self.fromIds[id] - self:removeId(id) - - if instance ~= nil then - local descendantsToDestroy = {} - - for otherInstance in pairs(self.fromInstances) do - if otherInstance:IsDescendantOf(instance) then - table.insert(descendantsToDestroy, otherInstance) - end - end - - for _, otherInstance in ipairs(descendantsToDestroy) do - self:removeInstance(otherInstance) - end - - instance:Destroy() - else - Logging.warn("Attempted to destroy nonexistant ID %s", tostring(id)) - end - end - - return self -end - -local function setProperty(instance, key, value) - local ok, err = pcall(function() - if instance[key] ~= value then - instance[key] = value - end - end) - - if not ok then - error(("Cannot set property %s on class %s: %s"):format(tostring(key), instance.ClassName, err), 2) - end -end - -local function shouldClearUnknown(id, instanceMetadataMap) - if instanceMetadataMap[id] then - return not instanceMetadataMap[id].ignoreUnknownInstances - else - return true - end -end - -local function reify(virtualInstancesById, instanceMap, instanceMetadataMap, id, parent) - local virtualInstance = virtualInstancesById[id] - - local instance = Instance.new(virtualInstance.ClassName) - - for key, value in pairs(virtualInstance.Properties) do - -- TODO: Branch on value.Type - setProperty(instance, key, value.Value) - end - - instance.Name = virtualInstance.Name - - for _, childId in ipairs(virtualInstance.Children) do - reify(virtualInstancesById, instanceMap, instanceMetadataMap, childId, instance) - end - - setProperty(instance, "Parent", parent) - instanceMap:insert(id, instance) - - return instance -end - ---[[ - Update an existing instance, including its properties and children, to match - the given information. -]] -local function reconcile(virtualInstancesById, instanceMap, instanceMetadataMap, id, existingInstance) - local virtualInstance = virtualInstancesById[id] - - -- If an instance changes ClassName, we assume it's very different. That's - -- not always the case! - if virtualInstance.ClassName ~= existingInstance.ClassName then - -- TODO: Preserve existing children instead? - local parent = existingInstance.Parent - instanceMap:destroyId(id) - reify(virtualInstancesById, instanceMap, instanceMetadataMap, id, parent) - return - end - - instanceMap:insert(id, existingInstance) - - -- Some instances don't like being named, even if their name already matches - setProperty(existingInstance, "Name", virtualInstance.Name) - - for key, value in pairs(virtualInstance.Properties) do - setProperty(existingInstance, key, value.Value) - end - - local existingChildren = existingInstance:GetChildren() - - local unvisitedExistingChildren = {} - for _, child in ipairs(existingChildren) do - unvisitedExistingChildren[child] = true - end - - for _, childId in ipairs(virtualInstance.Children) do - local childData = virtualInstancesById[childId] - - local existingChildInstance - for instance in pairs(unvisitedExistingChildren) do - local ok, name, className = pcall(function() - return instance.Name, instance.ClassName - end) - - if ok then - if name == childData.Name and className == childData.ClassName then - existingChildInstance = instance - break - end - end - end - - if existingChildInstance ~= nil then - unvisitedExistingChildren[existingChildInstance] = nil - reconcile(virtualInstancesById, instanceMap, instanceMetadataMap, childId, existingChildInstance) - else - reify(virtualInstancesById, instanceMap, instanceMetadataMap, childId, existingInstance) - end - end - - if shouldClearUnknown(id, instanceMetadataMap) then - for existingChildInstance in pairs(unvisitedExistingChildren) do - instanceMap:removeInstance(existingChildInstance) - existingChildInstance:Destroy() - end - end - - -- The root instance of a project won't have a parent, like the DataModel, - -- so we need to be careful here. - if virtualInstance.Parent ~= nil then - local parent = instanceMap.fromIds[virtualInstance.Parent] - - if parent == nil then - Logging.info("Instance %s wanted parent of %s", tostring(id), tostring(virtualInstance.Parent)) - error("Rojo bug: During reconciliation, an instance referred to an instance ID as parent that does not exist.") - end - - -- Some instances, like services, don't like having their Parent - -- property poked, even if we're setting it to the same value. - setProperty(existingInstance, "Parent", parent) - if existingInstance.Parent ~= parent then - existingInstance.Parent = parent - end - end - - return existingInstance -end - -local function applyUpdatePiece(id, visitedIds, virtualInstancesById, instanceMap, instanceMetadataMap) - if visitedIds[id] then - return - end - - visitedIds[id] = true - - local virtualInstance = virtualInstancesById[id] - local instance = instanceMap.fromIds[id] - - -- The instance was deleted in this update - if virtualInstance == nil then - instanceMap:destroyId(id) - return - end - - -- An instance we know about was updated - if instance ~= nil then - reconcile(virtualInstancesById, instanceMap, instanceMetadataMap, id, instance) - return instance - end - - -- If the instance's parent already exists, we can stick it there - local parentInstance = instanceMap.fromIds[virtualInstance.Parent] - if parentInstance ~= nil then - reify(virtualInstancesById, instanceMap, instanceMetadataMap, id, parentInstance) - return - end - - -- Otherwise, we can check if this response payload contained the parent and - -- work from there instead. - local parentData = virtualInstancesById[virtualInstance.Parent] - if parentData ~= nil then - if visitedIds[virtualInstance.Parent] then - error("Rojo bug: An instance was present and marked as visited but its instance was missing") - end - - applyUpdatePiece(virtualInstance.Parent, visitedIds, virtualInstancesById, instanceMap, instanceMetadataMap) - return - end - - Logging.trace("Instance ID %s, parent ID %s", tostring(id), tostring(virtualInstance.Parent)) - error("Rojo NYI: Instances with parents that weren't mentioned in an update payload") -end - -local function applyUpdate(requestedIds, virtualInstancesById, instanceMap, instanceMetadataMap) - -- This function may eventually be asynchronous; it will require calls to - -- the server to resolve instances that don't exist yet. - local visitedIds = {} - - for _, id in ipairs(requestedIds) do - applyUpdatePiece(id, visitedIds, virtualInstancesById, instanceMap, instanceMetadataMap) - end -end +local Reconciler = require(script.Parent.Reconciler) local Session = {} Session.__index = Session @@ -251,7 +10,7 @@ function Session.new(config) self.onError = config.onError - local instanceMap = makeInstanceMap() + local reconciler local remoteUrl = ("http://%s:%s"):format(config.address, config.port) @@ -274,7 +33,7 @@ function Session.new(config) return api:read(requestedIds) :andThen(function(response) - return applyUpdate(requestedIds, response.instances, instanceMap, api.instanceMetadataMap) + return reconciler:applyUpdate(requestedIds, response.instances) end) :catch(function(message) Logging.warn("%s", tostring(message)) @@ -284,11 +43,12 @@ function Session.new(config) api:connect() :andThen(function() + reconciler = Reconciler.new(api.instanceMetadataMap) + return api:read({api.rootInstanceId}) end) :andThen(function(response) - reconcile(response.instances, instanceMap, api.instanceMetadataMap, api.rootInstanceId, game) - -- reify(response.instances, instanceMap, instanceMetadataMap, api.rootInstanceId, game.ReplicatedStorage) + reconciler:reconcile(response.instances, api.rootInstanceId, game) return api:retrieveMessages() end) :catch(function(message) From 1992ce1cfb48e3a846a50cae4fc223e6b6a3cf38 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 7 Jan 2019 14:01:29 -0800 Subject: [PATCH 0313/1504] server: Update dependencies --- server/Cargo.lock | 693 +++++++++++++++++++++++++++++++++++++++------- server/Cargo.toml | 15 +- 2 files changed, 600 insertions(+), 108 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 3856f1de..0ce3fc03 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -1,3 +1,11 @@ +[[package]] +name = "MacTypes-sys" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "adler32" version = "1.0.3" @@ -19,6 +27,14 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "arrayvec" +version = "0.4.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ascii" version = "0.8.7" @@ -190,6 +206,23 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "core-foundation" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation-sys" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crc" version = "1.8.1" @@ -198,6 +231,47 @@ dependencies = [ "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crc32fast" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-channel" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-deque" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-utils" version = "0.6.3" @@ -217,62 +291,18 @@ dependencies = [ ] [[package]] -name = "encoding" -version = "0.2.33" +name = "dtoa" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] -name = "encoding-index-japanese" -version = "1.20141219.5" +name = "encoding_rs" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "encoding-index-korean" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-simpchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-singlebyte" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding-index-tradchinese" -version = "1.20141219.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "encoding_index_tests" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "env_logger" version = "0.5.13" @@ -309,7 +339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -323,6 +353,24 @@ dependencies = [ "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fnv" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fsevent" version = "0.2.17" @@ -360,6 +408,15 @@ name = "futures" version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "futures-cpupool" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "glob" version = "0.2.11" @@ -373,6 +430,33 @@ dependencies = [ "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "h2" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "http" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "httparse" version = "1.3.3" @@ -386,6 +470,44 @@ dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hyper" +version = "0.12.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "hyper-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "idna" version = "0.1.5" @@ -396,6 +518,11 @@ dependencies = [ "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "indexmap" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "inotify" version = "0.6.1" @@ -406,8 +533,8 @@ dependencies = [ "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -456,6 +583,16 @@ name = "libc" version = "0.2.46" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "libflate" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lock_api" version = "0.1.5" @@ -523,6 +660,11 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memoffset" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "mime" version = "0.2.6" @@ -531,14 +673,33 @@ dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mime" +version = "0.3.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mime_guess" version = "1.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mime_guess" +version = "2.0.0-alpha.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -571,6 +732,16 @@ dependencies = [ "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mio-uds" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "miow" version = "0.2.1" @@ -598,6 +769,23 @@ dependencies = [ "twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "native-tls" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "net2" version = "0.2.33" @@ -608,6 +796,11 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "nodrop" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "notify" version = "4.0.6" @@ -647,6 +840,35 @@ dependencies = [ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "openssl" +version = "0.10.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "openssl-sys" +version = "0.9.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "owning_ref" version = "0.4.0" @@ -657,20 +879,20 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.6.4" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot_core" -version = "0.3.1" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -683,39 +905,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "phf" -version = "0.7.23" +version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_codegen" -version = "0.7.23" +version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_generator 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_generator" -version = "0.7.23" +version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "phf_shared" -version = "0.7.23" +version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pkg-config" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro2" version = "0.4.24" @@ -864,7 +1091,7 @@ dependencies = [ [[package]] name = "rbx_binary" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#ef0f7310931e9f10bdc37a0e8a823c1309a7c198" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#b134ef96958dce745ccb775f9b32c97759c75414" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -874,7 +1101,7 @@ dependencies = [ [[package]] name = "rbx_tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#ef0f7310931e9f10bdc37a0e8a823c1309a7c198" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#b134ef96958dce745ccb775f9b32c97759c75414" dependencies = [ "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", @@ -884,7 +1111,7 @@ dependencies = [ [[package]] name = "rbx_xml" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#ef0f7310931e9f10bdc37a0e8a823c1309a7c198" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#b134ef96958dce745ccb775f9b32c97759c75414" dependencies = [ "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -931,6 +1158,32 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "reqwest" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rojo" version = "0.5.0" @@ -946,6 +1199,7 @@ dependencies = [ "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", @@ -975,7 +1229,7 @@ dependencies = [ "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny_http 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1015,11 +1269,41 @@ dependencies = [ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "schannel" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "security-framework" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "security-framework-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "MacTypes-sys 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver" version = "0.9.0" @@ -1046,7 +1330,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1059,6 +1343,17 @@ dependencies = [ "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_urlencoded" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "sha1" version = "0.6.0" @@ -1102,6 +1397,11 @@ name = "stable_deref_trait" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "string" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "strsim" version = "0.7.0" @@ -1109,7 +1409,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.23" +version = "0.15.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1124,7 +1424,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1213,28 +1513,79 @@ dependencies = [ [[package]] name = "tiny_http" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "tokio-executor" -version = "0.1.5" +name = "tokio" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-codec" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-current-thread" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-executor" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-fs" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-io" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1244,7 +1595,7 @@ dependencies = [ [[package]] name = "tokio-reactor" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1253,12 +1604,87 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-tcp" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-threadpool" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-timer" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-udp" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-uds" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "try-lock" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "twoway" version = "0.1.8" @@ -1280,6 +1706,14 @@ dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicase" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-bidi" version = "0.3.4" @@ -1335,6 +1769,11 @@ dependencies = [ "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "vcpkg" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vec_map" version = "0.8.1" @@ -1360,6 +1799,16 @@ dependencies = [ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "want" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi" version = "0.2.8" @@ -1421,9 +1870,11 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] +"checksum MacTypes-sys 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7dbbe033994ae2198a18517c7132d952a29fb1db44249a1234779da7c50f4698" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727" @@ -1446,31 +1897,41 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" +"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" +"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" +"checksum crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "137bc235f622ffaa0428e3854e24acb53291fc0b3ff6fb2cb75a8be6fb02f06b" +"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" +"checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c" "checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a" "checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86" -"checksum encoding 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "6b0d943856b990d12d3b55b359144ff341533e516d94098b1d3fc1ac666d36ec" -"checksum encoding-index-japanese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "04e8b2ff42e9a05335dbf8b5c6f7567e5591d0d916ccef4e0b1710d32a0d0c91" -"checksum encoding-index-korean 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4dc33fb8e6bcba213fe2f14275f0963fd16f0a02c878e3095ecfdf5bee529d81" -"checksum encoding-index-simpchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "d87a7194909b9118fc707194baa434a4e3b0fb6a5a757c73c3adb07aa25031f7" -"checksum encoding-index-singlebyte 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3351d5acffb224af9ca265f435b859c7c01537c0849754d3db3fdf2bfe2ae84a" -"checksum encoding-index-tradchinese 1.20141219.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fd0e20d5688ce3cab59eb3ef3a2083a5c77bf496cb798dc6fcdb75f323890c18" -"checksum encoding_index_tests 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a246d82be1c9d791c5dfde9a2bd045fc3cbba3fa2b11ad558f27d01712f00569" +"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" +"checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" +"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05" "checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" +"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9e59524a909fe98bb6c6f2cf1f27f2f6772887a496bf4c68cae0d94f884586" +"checksum h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac030ae20dee464c5d0f36544d8b914a6bc606da44a57e052d2b0f5dae129e0" +"checksum http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "02096a6d2c55e63f7fcb800690e4f889a25f6ec342e3adb4594e293b625215ab" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f1ebec079129e43af5e234ef36ee3d7e6085687d145b7ea653b262d16c6b65f1" +"checksum hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd73f14ad370d3b4d4b7dce08f69b81536c82e39fcc89731930fe5788cd661" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" @@ -1479,6 +1940,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)" = "023a4cd09b2ff695f9734c1934145a315594b7986398496841c7031a5a1bbdbd" +"checksum libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "bff3ac7d6f23730d3b533c35ed75eef638167634476a499feef16c428d74b57b" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" @@ -1487,25 +1949,35 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9" +"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" +"checksum mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "0a907b83e7b9e987032439a387e187119cddafc92d5c2aaeb1d92580a793f630" "checksum mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2d4c0961143b8efdcfa29c3ae63281601b446a4a668165454b6c90f8024954c5" +"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" +"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92f54eb45230c3aa20864ccf0c277eeaeadcf5e437e91731db498dbf7fbe0ec6" +"checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "873ecfd8c174964ae30f401329d140142312c8e5590719cf1199d5f1717d8078" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" +"checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" +"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" +"checksum openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1bb974e77de925ef426b6bc82fce15fd45bdcbeb5728bffcfc7cdeeb7ce1c2d6" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" -"checksum parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f0802bff09003b291ba756dc7e79313e51cc31667e94afbe847def490424cde5" -"checksum parking_lot_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ad7f7e6ebdc79edff6fdcb87a55b620174f7a989e3eb31b65231f4af57f00b8c" +"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum phf 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "cec29da322b242f4c3098852c77a0ca261c9c01b806cae85a5572a1eb94db9a6" -"checksum phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "7d187f00cd98d5afbcd8898f6cf181743a449162aeb329dcd2f3849009e605ad" -"checksum phf_generator 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "03dc191feb9b08b0dc1330d6549b795b9d81aec19efe6b4a45aec8d4caee0c4b" -"checksum phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "b539898d22d4273ded07f64a05737649dc69095d92cb87c7097ec68e3f150b93" +"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" +"checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" +"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" +"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" +"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" @@ -1530,6 +2002,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" +"checksum reqwest 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ab52e462d1e15891441aeefadff68bdea005174328ce3da0a314f2ad313ec837" "checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" @@ -1537,20 +2010,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" "checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" +"checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "697d3f3c23a618272ead9e1fb259c1411102b31c6af8b93f1d64cca9c3b0e8e0" +"checksum security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "40d95f3d7da09612affe897f320d78264f0d2320f3e8eea27d12bd1bd94445e2" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "0e732ed5a5592c17d961555e3b552985baf98d50ce418b7b655f31f6ba7eb1b7" "checksum serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d6115a3ca25c224e409185325afc16a0d5aaaabc15c42b09587d6f1ba39a5b" "checksum serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "bdf540260cfee6da923831f4776ddc495ada940c30117977c70f1313a6130545" +"checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" "checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" +"checksum string 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98998cced76115b1da46f63388b909d118a37ae0be0f82ad35773d4a4bc9d18d" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.15.23 (registry+https://github.com/rust-lang/crates.io-index)" = "9545a6a093a3f0bd59adb472700acc08cad3776f860f16a897dfce8c88721cbc" +"checksum syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)" = "734ecc29cd36e8123850d9bf21dfd62ef8300aaa8f879aabaa899721808be37c" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" @@ -1561,13 +2039,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c" -"checksum tiny_http 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "29909009df3f0541d1851992c5cab50209eceaf2eb4b3d1ef395a39f555173c3" -"checksum tokio-executor 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c117b6cf86bb730aab4834f10df96e4dd586eff2c3c27d3781348da49e255bde" -"checksum tokio-io 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "7392fe0a70d5ce0c882c4778116c519bd5dbaa8a7c3ae3d04578b3afafdcda21" -"checksum tokio-reactor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "502b625acb4ee13cbb3b90b8ca80e0addd263ddacf6931666ef751e610b07fb5" +"checksum tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1661fa0a44c95d01604bd05c66732a446c657efb62b5164a7a083a3b552b4951" +"checksum tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4790d0be6f4ba6ae4f48190efa2ed7780c9e3567796abdb285003cf39840d9c5" +"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" +"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" +"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" +"checksum tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d" +"checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" +"checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" +"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" +"checksum tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "17465013014410310f9f61fa10bf4724803c149ea1d51efece131c38efca93aa" +"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" +"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" +"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" +"checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" @@ -1576,10 +2065,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" "checksum uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dab5c5526c5caa3d106653401a267fed923e7046f35895ffcb5ca42db64942e6" +"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" +"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/server/Cargo.toml b/server/Cargo.toml index a28f5bab..97c5c5d9 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -21,17 +21,18 @@ bundle-plugin = [] [dependencies] clap = "2.27" +env_logger = "0.5" +failure = "0.1.3" +log = "0.4" +notify = "4.0" +rand = "0.4" +regex = "1.0" +reqwest = "0.9.5" rouille = "2.1" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" -notify = "4.0" -rand = "0.4" -regex = "1.0" -log = "0.4" -env_logger = "0.5" uuid = { version = "0.7", features = ["v4", "serde"] } -failure = "0.1.3" rbx_tree = { git = "https://github.com/LPGhatguy/rbx-tree.git" } rbx_xml = { git = "https://github.com/LPGhatguy/rbx-tree.git" } rbx_binary = { git = "https://github.com/LPGhatguy/rbx-tree.git" } @@ -39,4 +40,4 @@ rbx_binary = { git = "https://github.com/LPGhatguy/rbx-tree.git" } [dev-dependencies] tempfile = "3.0" walkdir = "2.1" -lazy_static = "1.2" +lazy_static = "1.2" \ No newline at end of file From 99ea374fc5da596ab55145654e4fe97c1da6a7c8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 7 Jan 2019 14:01:53 -0800 Subject: [PATCH 0314/1504] Add 'upload' command to publish places to Roblox for you --- server/src/bin.rs | 41 ++++++++++++++++ server/src/commands/mod.rs | 4 +- server/src/commands/upload.rs | 89 +++++++++++++++++++++++++++++++++++ 3 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 server/src/commands/upload.rs diff --git a/server/src/bin.rs b/server/src/bin.rs index 8145dce2..db0900b5 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -45,6 +45,13 @@ fn main() { (@arg PROJECT: "Path to the project to serve. Defaults to the current directory.") (@arg output: --output +takes_value +required "Where to output the result.") ) + + (@subcommand upload => + (about: "Generates a place file out of the project and uploads it to Roblox.") + (@arg PROJECT: "Path to the project to upload. Defaults to the current directory.") + (@arg cookie: --cookie +takes_value +required "Security cookie to authenticate with.") + (@arg place_id: --place_id +takes_value +required "Place ID to upload to.") + ) ); // `get_matches` consumes self for some reason. @@ -109,6 +116,40 @@ fn main() { }, } }, + ("upload", Some(sub_matches)) => { + let fuzzy_project_path = match sub_matches.value_of("PROJECT") { + Some(v) => make_path_absolute(Path::new(v)), + None => std::env::current_dir().unwrap(), + }; + + let security_cookie = sub_matches.value_of("cookie").unwrap(); + + let place_id: u64 = { + let arg = sub_matches.value_of("place_id").unwrap(); + + match arg.parse() { + Ok(v) => v, + Err(_) => { + error!("Invalid place ID {}", arg); + process::exit(1); + }, + } + }; + + let options = commands::UploadOptions { + fuzzy_project_path, + security_cookie: security_cookie.to_string(), + place_id, + }; + + match commands::upload(&options) { + Ok(_) => {}, + Err(e) => { + error!("{}", e); + process::exit(1); + }, + } + }, _ => { app.print_help().expect("Could not print help text to stdout!"); }, diff --git a/server/src/commands/mod.rs b/server/src/commands/mod.rs index 6f2bb133..966d67db 100644 --- a/server/src/commands/mod.rs +++ b/server/src/commands/mod.rs @@ -1,7 +1,9 @@ mod serve; mod init; mod build; +mod upload; pub use self::serve::*; pub use self::init::*; -pub use self::build::*; \ No newline at end of file +pub use self::build::*; +pub use self::upload::*; \ No newline at end of file diff --git a/server/src/commands/upload.rs b/server/src/commands/upload.rs new file mode 100644 index 00000000..78cf4bd9 --- /dev/null +++ b/server/src/commands/upload.rs @@ -0,0 +1,89 @@ +use std::{ + path::PathBuf, + io, +}; + +use failure::Fail; + +use reqwest::header::{USER_AGENT, CONTENT_TYPE, COOKIE}; + +use crate::{ + rbx_session::construct_oneoff_tree, + project::{Project, ProjectLoadFuzzyError}, + imfs::Imfs, +}; + +#[derive(Debug, Fail)] +pub enum UploadError { + #[fail(display = "Roblox API Error: {}", _0)] + RobloxApiError(String), + + #[fail(display = "Project load error: {}", _0)] + ProjectLoadError(#[fail(cause)] ProjectLoadFuzzyError), + + #[fail(display = "IO error: {}", _0)] + IoError(#[fail(cause)] io::Error), + + #[fail(display = "HTTP error: {}", _0)] + HttpError(#[fail(cause)] reqwest::Error), +} + +impl From for UploadError { + fn from(error: ProjectLoadFuzzyError) -> UploadError { + UploadError::ProjectLoadError(error) + } +} + +impl From for UploadError { + fn from(error: io::Error) -> UploadError { + UploadError::IoError(error) + } +} + +impl From for UploadError { + fn from(error: reqwest::Error) -> UploadError { + UploadError::HttpError(error) + } +} + +#[derive(Debug)] +pub struct UploadOptions { + pub fuzzy_project_path: PathBuf, + pub security_cookie: String, + pub place_id: u64, +} + +pub fn upload(options: &UploadOptions) -> Result<(), UploadError> { + info!("Looking for project at {}", options.fuzzy_project_path.display()); + + let project = Project::load_fuzzy(&options.fuzzy_project_path)?; + + info!("Found project at {}", project.file_location.display()); + info!("Using project {:#?}", project); + + let mut imfs = Imfs::new(); + imfs.add_roots_from_project(&project)?; + let tree = construct_oneoff_tree(&project, &imfs); + + let root_id = tree.get_root_id(); + let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); + let mut contents = Vec::new(); + rbx_xml::encode(&tree, top_level_ids, &mut contents); + + let url = format!("https://data.roblox.com/Data/Upload.ashx?json=1&type=Place&assetid={}", options.place_id); + + let client = reqwest::Client::new(); + let mut response = client.post(&url) + .header(COOKIE, format!(".ROBLOSECURITY={}", &options.security_cookie)) + .header(USER_AGENT, "Roblox/WinInet") + .header("Requester", "Client") + .header(CONTENT_TYPE, "application/xml") + .body(contents) + .send()?; + + if !response.status().is_success() { + return Err(UploadError::RobloxApiError(response.text()?)); + } + + Ok(()) +} \ No newline at end of file From 24a4099d8233b28a380582b4ea1a9529381fc119 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 7 Jan 2019 14:13:02 -0800 Subject: [PATCH 0315/1504] Add TODOs to upload --- server/src/commands/upload.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/server/src/commands/upload.rs b/server/src/commands/upload.rs index 78cf4bd9..7ed1e649 100644 --- a/server/src/commands/upload.rs +++ b/server/src/commands/upload.rs @@ -54,6 +54,9 @@ pub struct UploadOptions { } pub fn upload(options: &UploadOptions) -> Result<(), UploadError> { + // TODO: Support uploading models too + // TODO: Switch to uploading binary format? + info!("Looking for project at {}", options.fuzzy_project_path.display()); let project = Project::load_fuzzy(&options.fuzzy_project_path)?; From 11f398b55341484302bb74034c36980f83d34e77 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Jan 2019 10:53:36 -0800 Subject: [PATCH 0316/1504] Improve init script support - init.server.lua and init.client.lua are now supported again - Updating an init script no longer nukes its parent --- server/src/rbx_session.rs | 54 +++++++++++++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 11 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 57b83f37..bb29a730 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -16,6 +16,10 @@ use crate::{ rbx_snapshot::{RbxSnapshotInstance, InstanceChanges, reify_root, reconcile_subtree}, }; +const INIT_SCRIPT: &str = "init.lua"; +const INIT_SERVER_SCRIPT: &str = "init.server.lua"; +const INIT_CLIENT_SCRIPT: &str = "init.client.lua"; + pub struct RbxSession { tree: RbxTree, path_map: PathMap, @@ -23,7 +27,6 @@ pub struct RbxSession { sync_point_names: HashMap, message_queue: Arc>, imfs: Arc>, - project: Arc, } impl RbxSession { @@ -48,11 +51,12 @@ impl RbxSession { sync_point_names, message_queue, imfs, - project, } } fn path_created_or_updated(&mut self, path: &Path) { + // TODO: Track paths actually updated in each step so we can ignore + // redundant changes. let mut changes = InstanceChanges::default(); { @@ -60,17 +64,34 @@ impl RbxSession { let root_path = imfs.get_root_for_path(path) .expect("Path was outside in-memory filesystem roots"); - let closest_path = self.path_map.descend(root_path, path); - let &instance_id = self.path_map.get(&closest_path).unwrap(); + // Find the closest instance in the tree that still exists + let mut path_to_snapshot = self.path_map.descend(root_path, path); + let &instance_id = self.path_map.get(&path_to_snapshot).unwrap(); - trace!("Snapshotting path {}", closest_path.display()); + // If this is a file that might affect its parent if modified, we + // should snapshot the parent instead. + match path_to_snapshot.file_name().unwrap().to_str() { + Some(INIT_SCRIPT) | Some(INIT_SERVER_SCRIPT) | Some(INIT_CLIENT_SCRIPT) => { + path_to_snapshot.pop(); + }, + _ => {}, + } - let snapshot = snapshot_instances_from_imfs(&imfs, &closest_path, &mut self.sync_point_names) - .unwrap_or_else(|| panic!("Could not generate instance snapshot for path {}", closest_path.display())); + trace!("Snapshotting path {}", path_to_snapshot.display()); + + let snapshot = snapshot_instances_from_imfs(&imfs, &path_to_snapshot, &mut self.sync_point_names) + .unwrap_or_else(|| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())); trace!("Snapshot: {:#?}", snapshot); - reconcile_subtree(&mut self.tree, instance_id, &snapshot, &mut self.path_map, &mut self.instance_metadata_map, &mut changes); + reconcile_subtree( + &mut self.tree, + instance_id, + &snapshot, + &mut self.path_map, + &mut self.instance_metadata_map, + &mut changes, + ); } if changes.is_empty() { @@ -272,10 +293,16 @@ fn snapshot_instances_from_imfs<'a>( }, ImfsItem::Directory(directory) => { // TODO: Expand init support to handle server and client scripts - let init_path = directory.path.join("init.lua"); + let init_path = directory.path.join(INIT_SCRIPT); + let init_server_path = directory.path.join(INIT_SERVER_SCRIPT); + let init_client_path = directory.path.join(INIT_CLIENT_SCRIPT); let mut instance = if directory.children.contains(&init_path) { snapshot_instances_from_imfs(imfs, &init_path, sync_point_names)? + } else if directory.children.contains(&init_server_path) { + snapshot_instances_from_imfs(imfs, &init_server_path, sync_point_names)? + } else if directory.children.contains(&init_client_path) { + snapshot_instances_from_imfs(imfs, &init_client_path, sync_point_names)? } else { RbxSnapshotInstance { class_name: Cow::Borrowed("Folder"), @@ -294,8 +321,13 @@ fn snapshot_instances_from_imfs<'a>( }; for child_path in &directory.children { - if child_path != &init_path { - instance.children.push(snapshot_instances_from_imfs(imfs, child_path, sync_point_names)?); + match child_path.file_name().unwrap().to_str() { + Some(INIT_SCRIPT) | Some(INIT_SERVER_SCRIPT) | Some(INIT_CLIENT_SCRIPT) => { + // These modify the parent, we can skip them + }, + _ => { + instance.children.push(snapshot_instances_from_imfs(imfs, child_path, sync_point_names)?); + }, } } From b2753cb268ce681f9c9a27878503b8918c7e258f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Jan 2019 11:18:35 -0800 Subject: [PATCH 0317/1504] Tidy and document RbxSession more --- server/src/rbx_session.rs | 60 +++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index bb29a730..cda99442 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -9,7 +9,7 @@ use std::{ use rbx_tree::{RbxTree, RbxValue, RbxId}; use crate::{ - project::{Project, ProjectNode, InstanceProjectNode, InstanceProjectNodeMetadata}, + project::{Project, ProjectNode, InstanceProjectNodeMetadata}, message_queue::MessageQueue, imfs::{Imfs, ImfsItem, ImfsFile}, path_map::PathMap, @@ -64,12 +64,12 @@ impl RbxSession { let root_path = imfs.get_root_for_path(path) .expect("Path was outside in-memory filesystem roots"); - // Find the closest instance in the tree that still exists + // Find the closest instance in the tree that currently exists let mut path_to_snapshot = self.path_map.descend(root_path, path); let &instance_id = self.path_map.get(&path_to_snapshot).unwrap(); // If this is a file that might affect its parent if modified, we - // should snapshot the parent instead. + // should snapshot its parent instead. match path_to_snapshot.file_name().unwrap().to_str() { Some(INIT_SCRIPT) | Some(INIT_SERVER_SCRIPT) | Some(INIT_CLIENT_SCRIPT) => { path_to_snapshot.pop(); @@ -113,7 +113,7 @@ impl RbxSession { { let imfs = self.imfs.lock().unwrap(); - // If the path doesn't exist or it's a directory, we don't care if it + // If the path doesn't exist or is a directory, we don't care if it // updated match imfs.get(path) { Some(ImfsItem::Directory(_)) | None => { @@ -187,7 +187,20 @@ fn construct_project_node<'a>( ) -> RbxSnapshotInstance<'a> { match project_node { ProjectNode::Instance(node) => { - construct_instance_node(imfs, instance_name, node, sync_point_names) + let mut children = Vec::new(); + + for (child_name, child_project_node) in &node.children { + children.push(construct_project_node(imfs, child_name, child_project_node, sync_point_names)); + } + + RbxSnapshotInstance { + class_name: Cow::Borrowed(&node.class_name), + name: Cow::Borrowed(instance_name), + properties: HashMap::new(), + children, + source_path: None, + metadata: Some(node.metadata.clone()), + } }, ProjectNode::SyncPoint(node) => { let mut snapshot = snapshot_instances_from_imfs(imfs, &node.path, sync_point_names) @@ -201,28 +214,6 @@ fn construct_project_node<'a>( } } -fn construct_instance_node<'a>( - imfs: &'a Imfs, - instance_name: &'a str, - project_node: &'a InstanceProjectNode, - sync_point_names: &mut HashMap, -) -> RbxSnapshotInstance<'a> { - let mut children = Vec::new(); - - for (child_name, child_project_node) in &project_node.children { - children.push(construct_project_node(imfs, child_name, child_project_node, sync_point_names)); - } - - RbxSnapshotInstance { - class_name: Cow::Borrowed(&project_node.class_name), - name: Cow::Borrowed(instance_name), - properties: HashMap::new(), - children, - source_path: None, - metadata: Some(project_node.metadata.clone()), - } -} - #[derive(Debug, Clone, Copy)] enum FileType { ModuleScript, @@ -253,6 +244,8 @@ fn classify_file(file: &ImfsFile) -> Option<(&str, FileType)> { } } +// TODO: Return a Result wrapping an Option so that failure can be represented +// separately from "this thing is unknown" fn snapshot_instances_from_imfs<'a>( imfs: &'a Imfs, imfs_path: &Path, @@ -306,7 +299,7 @@ fn snapshot_instances_from_imfs<'a>( } else { RbxSnapshotInstance { class_name: Cow::Borrowed("Folder"), - name: Cow::Borrowed(""), // Assigned later in the method + name: Cow::Borrowed(""), properties: HashMap::new(), children: Vec::new(), source_path: Some(directory.path.clone()), @@ -314,6 +307,9 @@ fn snapshot_instances_from_imfs<'a>( } }; + // We have to be careful not to lose instance names that are + // specified in the project manifest. We store them in + // sync_point_names when the original tree is constructed. instance.name = if let Some(actual_name) = sync_point_names.get(&directory.path) { Cow::Owned(actual_name.clone()) } else { @@ -323,10 +319,14 @@ fn snapshot_instances_from_imfs<'a>( for child_path in &directory.children { match child_path.file_name().unwrap().to_str() { Some(INIT_SCRIPT) | Some(INIT_SERVER_SCRIPT) | Some(INIT_CLIENT_SCRIPT) => { - // These modify the parent, we can skip them + // The existence of files with these names modifies the + // parent instance and is handled above, so we can skip + // them here. }, _ => { - instance.children.push(snapshot_instances_from_imfs(imfs, child_path, sync_point_names)?); + // TODO: Ignore this child instead? + let child = snapshot_instances_from_imfs(imfs, child_path, sync_point_names)?; + instance.children.push(child); }, } } From 70ba101fe1ab8d1c657f094437584e333b362092 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Jan 2019 11:28:57 -0800 Subject: [PATCH 0318/1504] Add more types in rbx_snapshot --- server/src/rbx_snapshot.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 768c4c5b..a9896abe 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -225,9 +225,9 @@ fn reconcile_instance_children( let children_ids = tree.get_instance(id).unwrap().get_children_ids().to_vec(); let child_count = children_ids.len().max(snapshot.children.len()); - let mut children_to_add = Vec::new(); - let mut children_to_update = Vec::new(); - let mut children_to_remove = Vec::new(); + let mut children_to_update: Vec<(RbxId, &RbxSnapshotInstance)> = Vec::new(); + let mut children_to_add: Vec<&RbxSnapshotInstance> = Vec::new(); + let mut children_to_remove: Vec = Vec::new(); for i in 0..child_count { let instance_child = children_ids From b9f7d3d88998c63339e0107875159a937f74b6b2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Jan 2019 14:23:48 -0800 Subject: [PATCH 0319/1504] Smarter reconciliation algorithm --- server/src/rbx_session.rs | 1 + server/src/rbx_snapshot.rs | 53 ++++++++++++++++++++++++++------------ 2 files changed, 38 insertions(+), 16 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index cda99442..a09672eb 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -135,6 +135,7 @@ impl RbxSession { pub fn path_renamed(&mut self, from_path: &Path, to_path: &Path) { info!("Path renamed from {} to {}", from_path.display(), to_path.display()); + self.path_map.remove(from_path); self.path_created_or_updated(from_path); self.path_created_or_updated(to_path); } diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index a9896abe..554a20f6 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -222,30 +222,51 @@ fn reconcile_instance_children( instance_metadata_map: &mut HashMap, changes: &mut InstanceChanges, ) { - let children_ids = tree.get_instance(id).unwrap().get_children_ids().to_vec(); - let child_count = children_ids.len().max(snapshot.children.len()); + let mut visited_snapshot_indices = HashSet::new(); let mut children_to_update: Vec<(RbxId, &RbxSnapshotInstance)> = Vec::new(); let mut children_to_add: Vec<&RbxSnapshotInstance> = Vec::new(); let mut children_to_remove: Vec = Vec::new(); - for i in 0..child_count { - let instance_child = children_ids - .get(i) - .map(|&id| tree.get_instance_mut(id).unwrap()); - let snapshot_child = snapshot.children.get(i); + let children_ids = tree.get_instance(id).unwrap().get_children_ids(); - match (instance_child, snapshot_child) { - (Some(instance_child), Some(snapshot_child)) => { - children_to_update.push((instance_child.get_id(), snapshot_child)); + // Find all instances that were removed or updated, which we derive by + // trying to pair up existing instances to snapshots. + for &child_id in children_ids { + let child_instance = tree.get_instance(child_id).unwrap(); + + // Locate a matching snapshot for this instance + let mut matching_snapshot = None; + for (snapshot_index, child_snapshot) in snapshot.children.iter().enumerate() { + if visited_snapshot_indices.contains(&snapshot_index) { + continue; + } + + // We assume that instances with the same name are probably pretty + // similar. This heuristic is similar to React's reconciliation + // strategy. + if child_snapshot.name == child_instance.name { + visited_snapshot_indices.insert(snapshot_index); + matching_snapshot = Some(child_snapshot); + break; + } + } + + match matching_snapshot { + Some(child_snapshot) => { + children_to_update.push((child_instance.get_id(), child_snapshot)); }, - (Some(instance_child), None) => { - children_to_remove.push(instance_child.get_id()); + None => { + children_to_remove.push(child_instance.get_id()); }, - (None, Some(snapshot_child)) => { - children_to_add.push(snapshot_child); - }, - (None, None) => unreachable!(), + } + } + + // Find all instancs that were added, which is just the snapshots we didn't + // match up to existing instances above. + for (snapshot_index, child_snapshot) in snapshot.children.iter().enumerate() { + if !visited_snapshot_indices.contains(&snapshot_index) { + children_to_add.push(child_snapshot); } } From 049875e8fcce057659aa08fd347cecf845714be8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Jan 2019 17:19:26 -0800 Subject: [PATCH 0320/1504] Update plugin config to work with Git master Rojo --- plugin/roblox-project.json | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/plugin/roblox-project.json b/plugin/roblox-project.json index 0c399c87..ab8cf8d0 100644 --- a/plugin/roblox-project.json +++ b/plugin/roblox-project.json @@ -6,7 +6,22 @@ "ReplicatedStorage": { "$className": "ReplicatedStorage", "Rojo": { - "$path": "." + "$className": "Folder", + "Plugin": { + "$path": "src" + }, + "Roact": { + "$path": "modules/roact/lib" + }, + "Rodux": { + "$path": "modules/rodux/lib" + }, + "RoactRodux": { + "$path": "modules/roact-rodux/lib" + }, + "Promise": { + "$path": "modules/promise/lib" + } }, "TestEZ": { "$path": "modules/testez/lib" From 0be4e6921dfa9baf384f124865fa10c5ec1d218e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Jan 2019 18:16:04 -0800 Subject: [PATCH 0321/1504] Implement CSV-format LocalizationTable serialization --- server/Cargo.lock | 20 +++++++++++ server/Cargo.toml | 1 + server/single-sync-point.rbxl | Bin 0 -> 881 bytes server/src/rbx_session.rs | 62 ++++++++++++++++++++++++++++++++-- 4 files changed, 80 insertions(+), 3 deletions(-) create mode 100644 server/single-sync-point.rbxl diff --git a/server/Cargo.lock b/server/Cargo.lock index 0ce3fc03..8f184fa4 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -280,6 +280,23 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "csv" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "csv-core" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "deflate" version = "0.7.19" @@ -1189,6 +1206,7 @@ name = "rojo" version = "0.5.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1905,6 +1923,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" "checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c" "checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a" +"checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" +"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" "checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7" diff --git a/server/Cargo.toml b/server/Cargo.toml index 97c5c5d9..88bdf38e 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -21,6 +21,7 @@ bundle-plugin = [] [dependencies] clap = "2.27" +csv = "1.0" env_logger = "0.5" failure = "0.1.3" log = "0.4" diff --git a/server/single-sync-point.rbxl b/server/single-sync-point.rbxl new file mode 100644 index 0000000000000000000000000000000000000000..6890b3f60450f39fb6eff9ef8af4efd897821457 GIT binary patch literal 881 zcmZuwO>fgc5FI;7DJ?W=3$2Qv-B<-xBH<$(DuoIm0*#7Fh!S5af~u{(v{u$$W3M3) zFq6-;>9h z3DPVfV-bUpPSQAmv8kjhqNB-yh%5N{64epujEUnJj7Q2%q-Z&j7wRK=w$Xgt7~em2 zS?9hm{@cj7hW39#6LUY5!j5r4tdhuChV|af{t66UaG8kMs`MmRKa6i5YCPafNG6^qUZ`#WY(e%dLjD@e z<_{qUHOM)}zhgui>}gnDk9PeI+tS> zB|i58qOD(input: &'a str, trailer: &str) -> Option<&'a str> { @@ -240,11 +241,46 @@ fn classify_file(file: &ImfsFile) -> Option<(&str, FileType)> { Some((instance_name, FileType::ClientScript)) } else if let Some(instance_name) = get_trailing(file_name, ".lua") { Some((instance_name, FileType::ModuleScript)) + } else if let Some(instance_name) = get_trailing(file_name, ".csv") { + Some((instance_name, FileType::LocalizationTable)) } else { None } } +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +struct LocalizationEntryCsv { + key: String, + context: String, + example: String, + source: String, + #[serde(flatten)] + values: HashMap, +} + +impl LocalizationEntryCsv { + fn to_json(self) -> LocalizationEntryJson { + LocalizationEntryJson { + key: self.key, + context: self.context, + example: self.example, + source: self.source, + values: self.values, + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct LocalizationEntryJson { + key: String, + context: String, + example: String, + source: String, + values: HashMap, +} + // TODO: Return a Result wrapping an Option so that failure can be represented // separately from "this thing is unknown" fn snapshot_instances_from_imfs<'a>( @@ -266,15 +302,35 @@ fn snapshot_instances_from_imfs<'a>( FileType::ModuleScript => "ModuleScript", FileType::ServerScript => "Script", FileType::ClientScript => "LocalScript", + FileType::LocalizationTable => "LocalizationTable", }; let contents = str::from_utf8(&file.contents) .expect("File did not contain UTF-8 data, which is required for scripts."); let mut properties = HashMap::new(); - properties.insert(String::from("Source"), RbxValue::String { - value: contents.to_string(), - }); + + match file_type { + FileType::ModuleScript | FileType::ServerScript | FileType::ClientScript => { + properties.insert(String::from("Source"), RbxValue::String { + value: contents.to_string(), + }); + }, + FileType::LocalizationTable => { + let entries: Vec = csv::Reader::from_reader(contents.as_bytes()) + .deserialize() + .map(|result| result.expect("Malformed localization table found!")) + .map(LocalizationEntryCsv::to_json) + .collect(); + + let table_contents = serde_json::to_string(&entries) + .expect("Could not encode JSON for localization table"); + + properties.insert(String::from("Contents"), RbxValue::String { + value: table_contents, + }); + }, + } Some(RbxSnapshotInstance { name: instance_name, From eff4301027780994a332ea6aa0c7c1a771ddc912 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Jan 2019 18:30:09 -0800 Subject: [PATCH 0322/1504] Add case in reconciler to handle LocalizationTable Contents --- plugin/src/Reconciler.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 60e637a7..db0728e2 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -60,6 +60,13 @@ local function makeInstanceMap() end local function setProperty(instance, key, value) + -- The 'Contents' property of LocalizationTable isn't directly exposed, but + -- has corresponding (deprecated) getters and setters. + if key == "Contents" and instance.ClassName == "LocalizationTable" then + instance:SetContents(value) + return + end + local ok, err = pcall(function() if instance[key] ~= value then instance[key] = value From 8d640ab467c300bf96ee73d3af29718ee8db72c3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 10:18:21 -0800 Subject: [PATCH 0323/1504] Add more alternative projects to README --- README.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index e5bcb490..26df1316 100644 --- a/README.md +++ b/README.md @@ -47,10 +47,13 @@ There are lots of other tools that sync scripts into Roblox or provide other too Here are a few, if you're looking for alternatives or supplements to Rojo: * [rbxmk by Anaminus](https://github.com/anaminus/rbxmk) -* [Rofresh](https://github.com/osyrisrblx/rofresh) and [RbxRefresh](https://github.com/osyrisrblx/RbxRefresh) by [Osyris](https://github.com/osyrisrblx) +* [Rofresh by Osyris](https://github.com/osyrisrblx/rofresh) +* [RbxRefresh by Osyris](https://github.com/osyrisrblx/RbxRefresh) * [Studio Bridge by Vocksel](https://github.com/vocksel/studio-bridge) +* [Elixir by Vocksel](https://github.com/vocksel/elixir) * [RbxSync by evaera](https://github.com/evaera/RbxSync) -* [CodeSync](https://github.com/MemoryPenguin/CodeSync) and [rbx-exteditor](https://github.com/MemoryPenguin/rbx-exteditor) by [MemoryPenguin](https://github.com/MemoryPenguin) +* [CodeSync by MemoryPenguin](https://github.com/MemoryPenguin/CodeSync) +* [rbx-exteditor by MemoryPenguin](https://github.com/MemoryPenguin/rbx-exteditor) If you use a plugin that _isn't_ Rojo for syncing code, open an issue and let me know why! I'd like Rojo to be the end-all tool so that people stop reinventing solutions to this problem. From b26b36da5dbd0bbbe8562f8cee6b4fcb25d84cf3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 10:52:18 -0800 Subject: [PATCH 0324/1504] Update CHANGES --- CHANGES.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 253e734a..e43da968 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,25 @@ # Rojo Change Log ## Current master -The `master` branch is currently undergoing a major rewrite to lay the groundwork for bidirectional syncing and other robustness improvements. Check out the `v0.4.x` branch for the current release. +* "Epiphany" rewrite, in progress since the beginning of time +* New live sync protocol + * Uses HTTP long polling to reduce request count and improve responsiveness +* New project format + * Hierarchical, preventing overlapping partitions +* Added `rojo build` command + * Generates `rbxm`, `rbxmx`, `rbxl`, or `rbxlx` files out of your project + * Usage: `rojo build --output .rbxm` +* Added `rojo upload` command + * Generates and uploads a place file to roblox.com out of your project + * Usage: `rojo upload --cookie "" --place_id ` +* New plugin + * Only one button now, "Connect" + * New UI to pick server address and port + * Better error reporting +* Added support for `.csv` files turning into `LocalizationTable` instances + +## 0.4.13 (November 12, 2018) +* When `rojo.json` points to a file or directory that does not exist, Rojo now issues a warning instead of throwing an error and exiting ## 0.4.12 (June 21, 2018) * Fixed obscure assertion failure when renaming or deleting files ([#78](https://github.com/LPGhatguy/rojo/issues/78)) From b62d946f8324edc1294638b05ba5290226a2a91e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 11:23:00 -0800 Subject: [PATCH 0325/1504] Stub out new 'init' command --- server/src/bin.rs | 18 ++++++++++--- server/src/commands/init.rs | 54 ++++++++++++++++++++++++++++--------- server/src/project.rs | 6 ++++- 3 files changed, 62 insertions(+), 16 deletions(-) diff --git a/server/src/bin.rs b/server/src/bin.rs index db0900b5..e6f43df3 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -32,6 +32,7 @@ fn main() { (@subcommand init => (about: "Creates a new Rojo project") (@arg PATH: "Path to the place to create the project. Defaults to the current directory.") + (@arg kind: --kind +takes_value "The kind of project to create, 'place' or 'model'. Defaults to place.") ) (@subcommand serve => @@ -59,10 +60,21 @@ fn main() { match matches.subcommand() { ("init", Some(sub_matches)) => { - let project_path = Path::new(sub_matches.value_of("PATH").unwrap_or(".")); - let full_path = make_path_absolute(project_path); + let fuzzy_project_path = make_path_absolute(Path::new(sub_matches.value_of("PATH").unwrap_or("."))); + let kind = sub_matches.value_of("kind"); - commands::init(&full_path); + let options = commands::InitOptions { + fuzzy_project_path, + kind, + }; + + match commands::init(&options) { + Ok(_) => {}, + Err(e) => { + error!("{}", e); + process::exit(1); + }, + } }, ("serve", Some(sub_matches)) => { let fuzzy_project_path = match sub_matches.value_of("PROJECT") { diff --git a/server/src/commands/init.rs b/server/src/commands/init.rs index 186d531c..a764ccb0 100644 --- a/server/src/commands/init.rs +++ b/server/src/commands/init.rs @@ -1,16 +1,46 @@ -use std::path::PathBuf; -use std::process; +use std::{ + path::PathBuf, +}; -use crate::project::Project; +use failure::Fail; -pub fn init(project_path: &PathBuf) { - match Project::init(project_path) { - Ok(_) => { - println!("Created new empty project at {}", project_path.display()); - }, - Err(e) => { - error!("Failed to create new project.\n{}", e); - process::exit(1); - }, +use crate::project::{Project, ProjectInitError}; + +#[derive(Debug, Fail)] +pub enum InitError { + #[fail(display = "Invalid project kind '{}', valid kinds are 'place' and 'model'", _0)] + InvalidKind(String), + + #[fail(display = "Project init error: {}", _0)] + ProjectInitError(#[fail(cause)] ProjectInitError) +} + +impl From for InitError { + fn from(error: ProjectInitError) -> InitError { + InitError::ProjectInitError(error) } +} + +#[derive(Debug)] +pub struct InitOptions<'a> { + pub fuzzy_project_path: PathBuf, + pub kind: Option<&'a str>, +} + +pub fn init(options: &InitOptions) -> Result<(), InitError> { + let (project_path, project_kind) = match options.kind { + Some("place") | None => { + let path = Project::init_place(&options.fuzzy_project_path)?; + (path, "place") + }, + Some("model") => { + let path = Project::init_model(&options.fuzzy_project_path)?; + (path, "model") + }, + Some(invalid) => return Err(InitError::InvalidKind(invalid.to_string())), + }; + + println!("Created new {} project at {}", project_kind, project_path.display()); + + Ok(()) } \ No newline at end of file diff --git a/server/src/project.rs b/server/src/project.rs index 61cce205..46c4d7be 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -180,7 +180,11 @@ pub struct Project { } impl Project { - pub fn init(_project_folder_location: &Path) -> Result<(), ProjectInitError> { + pub fn init_place(_project_fuzzy_location: &Path) -> Result { + unimplemented!(); + } + + pub fn init_model(_project_fuzzy_location: &Path) -> Result { unimplemented!(); } From 9574f8ebd7a36c3ddbecefc8e84efd3bb4dbcedb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 13:40:46 -0800 Subject: [PATCH 0326/1504] Improve snapshot error robustness * Unknown files are now ignored * Errors bubble up a level higher --- server/src/rbx_session.rs | 88 +++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 21 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index a9a15c11..ad72dd4e 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -1,11 +1,14 @@ use std::{ borrow::Cow, collections::HashMap, + fmt, path::{Path, PathBuf}, - sync::{Arc, Mutex}, str, + sync::{Arc, Mutex}, }; +use failure::Fail; + use rbx_tree::{RbxTree, RbxValue, RbxId}; use crate::{ @@ -79,8 +82,13 @@ impl RbxSession { trace!("Snapshotting path {}", path_to_snapshot.display()); - let snapshot = snapshot_instances_from_imfs(&imfs, &path_to_snapshot, &mut self.sync_point_names) - .unwrap_or_else(|| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())); + let maybe_snapshot = snapshot_instances_from_imfs(&imfs, &path_to_snapshot, &mut self.sync_point_names) + .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())); + + let snapshot = match maybe_snapshot { + Some(snapshot) => snapshot, + None => return, + }; trace!("Snapshot: {:#?}", snapshot); @@ -204,8 +212,10 @@ fn construct_project_node<'a>( } }, ProjectNode::SyncPoint(node) => { + // TODO: Propagate errors upward instead of dying let mut snapshot = snapshot_instances_from_imfs(imfs, &node.path, sync_point_names) - .expect("Could not reify nodes from Imfs"); + .expect("Could not reify nodes from Imfs") + .expect("Sync point node did not result in an instance"); snapshot.name = Cow::Borrowed(instance_name); sync_point_names.insert(node.path.clone(), instance_name.to_string()); @@ -281,16 +291,40 @@ struct LocalizationEntryJson { values: HashMap, } -// TODO: Return a Result wrapping an Option so that failure can be represented -// separately from "this thing is unknown" +#[derive(Debug, Fail)] +enum SnapshotError { + DidNotExist(PathBuf), + + // TODO: Add file path to the error message? + Utf8Error { + #[fail(cause)] + inner: str::Utf8Error, + path: PathBuf, + }, +} + +impl fmt::Display for SnapshotError { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + match self { + SnapshotError::DidNotExist(path) => write!(output, "Path did not exist: {}", path.display()), + SnapshotError::Utf8Error { inner, path } => { + write!(output, "Invalid UTF-8: {} in path {}", inner, path.display()) + }, + } + } +} + fn snapshot_instances_from_imfs<'a>( imfs: &'a Imfs, imfs_path: &Path, sync_point_names: &HashMap, -) -> Option> { - match imfs.get(imfs_path)? { - ImfsItem::File(file) => { - let (instance_name, file_type) = classify_file(file)?; +) -> Result>, SnapshotError> { + match imfs.get(imfs_path) { + Some(ImfsItem::File(file)) => { + let (instance_name, file_type) = match classify_file(file) { + Some(info) => info, + None => return Ok(None), + }; let instance_name = if let Some(actual_name) = sync_point_names.get(imfs_path) { Cow::Owned(actual_name.clone()) @@ -306,7 +340,10 @@ fn snapshot_instances_from_imfs<'a>( }; let contents = str::from_utf8(&file.contents) - .expect("File did not contain UTF-8 data, which is required for scripts."); + .map_err(|inner| SnapshotError::Utf8Error { + inner, + path: imfs_path.to_path_buf(), + })?; let mut properties = HashMap::new(); @@ -332,16 +369,16 @@ fn snapshot_instances_from_imfs<'a>( }, } - Some(RbxSnapshotInstance { + Ok(Some(RbxSnapshotInstance { name: instance_name, class_name: Cow::Borrowed(class_name), properties, children: Vec::new(), source_path: Some(file.path.clone()), metadata: None, - }) + })) }, - ImfsItem::Directory(directory) => { + Some(ImfsItem::Directory(directory)) => { // TODO: Expand init support to handle server and client scripts let init_path = directory.path.join(INIT_SCRIPT); let init_server_path = directory.path.join(INIT_SERVER_SCRIPT); @@ -349,10 +386,13 @@ fn snapshot_instances_from_imfs<'a>( let mut instance = if directory.children.contains(&init_path) { snapshot_instances_from_imfs(imfs, &init_path, sync_point_names)? + .expect("Could not snapshot instance from file that existed!") } else if directory.children.contains(&init_server_path) { snapshot_instances_from_imfs(imfs, &init_server_path, sync_point_names)? + .expect("Could not snapshot instance from file that existed!") } else if directory.children.contains(&init_client_path) { snapshot_instances_from_imfs(imfs, &init_client_path, sync_point_names)? + .expect("Could not snapshot instance from file that existed!") } else { RbxSnapshotInstance { class_name: Cow::Borrowed("Folder"), @@ -370,25 +410,31 @@ fn snapshot_instances_from_imfs<'a>( instance.name = if let Some(actual_name) = sync_point_names.get(&directory.path) { Cow::Owned(actual_name.clone()) } else { - Cow::Borrowed(directory.path.file_name()?.to_str()?) + Cow::Borrowed(directory.path + .file_name().expect("Could not extract file name") + .to_str().expect("Could not convert path to UTF-8")) }; for child_path in &directory.children { - match child_path.file_name().unwrap().to_str() { - Some(INIT_SCRIPT) | Some(INIT_SERVER_SCRIPT) | Some(INIT_CLIENT_SCRIPT) => { + match child_path.file_name().unwrap().to_str().unwrap() { + INIT_SCRIPT | INIT_SERVER_SCRIPT | INIT_CLIENT_SCRIPT => { // The existence of files with these names modifies the // parent instance and is handled above, so we can skip // them here. }, _ => { - // TODO: Ignore this child instead? - let child = snapshot_instances_from_imfs(imfs, child_path, sync_point_names)?; - instance.children.push(child); + match snapshot_instances_from_imfs(imfs, child_path, sync_point_names)? { + Some(child) => { + instance.children.push(child); + }, + None => {}, + } }, } } - Some(instance) + Ok(Some(instance)) }, + None => Err(SnapshotError::DidNotExist(imfs_path.to_path_buf())), } } \ No newline at end of file From a306fa26e0613d5040f568ed1b079bd24068f9ae Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 13:47:58 -0800 Subject: [PATCH 0327/1504] Add extra diagnostic trace for path_created_or_updated --- server/src/rbx_session.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index ad72dd4e..4562f784 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -87,7 +87,10 @@ impl RbxSession { let snapshot = match maybe_snapshot { Some(snapshot) => snapshot, - None => return, + None => { + trace!("Path resulted in no snapshot being generated."); + return; + }, }; trace!("Snapshot: {:#?}", snapshot); From 665809e11a9e2d0434bfaed99d9aa194528ecc7d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 16:18:56 -0800 Subject: [PATCH 0328/1504] Remove accidental place file --- server/single-sync-point.rbxl | Bin 881 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 server/single-sync-point.rbxl diff --git a/server/single-sync-point.rbxl b/server/single-sync-point.rbxl deleted file mode 100644 index 6890b3f60450f39fb6eff9ef8af4efd897821457..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 881 zcmZuwO>fgc5FI;7DJ?W=3$2Qv-B<-xBH<$(DuoIm0*#7Fh!S5af~u{(v{u$$W3M3) zFq6-;>9h z3DPVfV-bUpPSQAmv8kjhqNB-yh%5N{64epujEUnJj7Q2%q-Z&j7wRK=w$Xgt7~em2 zS?9hm{@cj7hW39#6LUY5!j5r4tdhuChV|af{t66UaG8kMs`MmRKa6i5YCPafNG6^qUZ`#WY(e%dLjD@e z<_{qUHOM)}zhgui>}gnDk9PeI+tS> zB|i58qOD Date: Wed, 9 Jan 2019 16:28:17 -0800 Subject: [PATCH 0329/1504] Update dependencies --- server/Cargo.lock | 225 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 193 insertions(+), 32 deletions(-) diff --git a/server/Cargo.lock b/server/Cargo.lock index 8f184fa4..b47008b8 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -86,6 +86,14 @@ dependencies = [ "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base64" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "0.7.0" @@ -176,7 +184,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -246,7 +254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -332,6 +340,14 @@ dependencies = [ "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "error-chain" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "error-chain" version = "0.12.0" @@ -464,6 +480,15 @@ dependencies = [ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hostname" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "http" version = "0.1.14" @@ -489,7 +514,7 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.19" +version = "0.12.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -502,7 +527,7 @@ dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -520,7 +545,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.20 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -571,6 +596,18 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ipconfig" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.4.3" @@ -610,6 +647,11 @@ dependencies = [ "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "linked-hash-map" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "lock_api" version = "0.1.5" @@ -635,6 +677,14 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lru-cache" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "lz4" version = "1.23.1" @@ -909,7 +959,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -943,7 +993,7 @@ version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -996,16 +1046,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.3" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1023,7 +1075,7 @@ dependencies = [ [[package]] name = "rand" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1032,7 +1084,7 @@ dependencies = [ "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1078,13 +1130,14 @@ dependencies = [ [[package]] name = "rand_os" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1108,7 +1161,7 @@ dependencies = [ [[package]] name = "rbx_binary" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#b134ef96958dce745ccb775f9b32c97759c75414" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#cb68b560bc2c5e922b4b19368ead78f775109065" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1118,7 +1171,7 @@ dependencies = [ [[package]] name = "rbx_tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#b134ef96958dce745ccb775f9b32c97759c75414" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#cb68b560bc2c5e922b4b19368ead78f775109065" dependencies = [ "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1128,12 +1181,20 @@ dependencies = [ [[package]] name = "rbx_xml" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#b134ef96958dce745ccb775f9b32c97759c75414" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#cb68b560bc2c5e922b4b19368ead78f775109065" dependencies = [ "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "redox_syscall" version = "0.1.50" @@ -1177,15 +1238,15 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.5" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.20 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1196,11 +1257,24 @@ dependencies = [ "serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-resolver 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "resolv-conf" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rojo" version = "0.5.0" @@ -1212,12 +1286,12 @@ dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1239,14 +1313,14 @@ dependencies = [ "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1410,6 +1484,17 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "socket2" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "stable_deref_trait" version = "1.1.1" @@ -1451,7 +1536,7 @@ name = "tempdir" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1462,7 +1547,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1521,7 +1606,7 @@ dependencies = [ [[package]] name = "time" -version = "0.1.41" +version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1652,7 +1737,7 @@ dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1698,6 +1783,47 @@ dependencies = [ "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "trust-dns-proto" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "trust-dns-resolver" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "trust-dns-proto 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "try-lock" version = "0.2.2" @@ -1827,6 +1953,11 @@ dependencies = [ "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "widestring" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" @@ -1873,6 +2004,22 @@ dependencies = [ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winreg" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "winutil" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -1898,6 +2045,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727" "checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" @@ -1930,6 +2078,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" +"checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" @@ -1945,25 +2094,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9e59524a909fe98bb6c6f2cf1f27f2f6772887a496bf4c68cae0d94f884586" "checksum h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac030ae20dee464c5d0f36544d8b914a6bc606da44a57e052d2b0f5dae129e0" +"checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" "checksum http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "02096a6d2c55e63f7fcb800690e4f889a25f6ec342e3adb4594e293b625215ab" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.12.19 (registry+https://github.com/rust-lang/crates.io-index)" = "f1ebec079129e43af5e234ef36ee3d7e6085687d145b7ea653b262d16c6b65f1" +"checksum hyper 0.12.20 (registry+https://github.com/rust-lang/crates.io-index)" = "80eeda66c9ef8e18f5122fff2c54604c053420b11dae951cfb74cf1dcba2e93f" "checksum hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd73f14ad370d3b4d4b7dce08f69b81536c82e39fcc89731930fe5788cd661" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)" = "023a4cd09b2ff695f9734c1934145a315594b7986398496841c7031a5a1bbdbd" "checksum libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "bff3ac7d6f23730d3b533c35ed75eef638167634476a499feef16c428d74b57b" +"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" @@ -2003,26 +2156,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" -"checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" +"checksum rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dee497e66d8d76bf08ce20c8d36e16f93749ab0bf89975b4f8ae5cee660c2da2" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b65e163105a6284f841bd23100a015895f54340e88a5ffc9ca7b8b33827cfce0" +"checksum rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3906503e80ac6cbcacb2c2973fa8e473f24d7e2747c8c92bb230c2441cad96b5" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_os 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de5ac4de1c2973e1391dc305cb0fbf8788cb58068e98255439b7485a77022273" +"checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" "checksum rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" +"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ab52e462d1e15891441aeefadff68bdea005174328ce3da0a314f2ad313ec837" +"checksum reqwest 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4286c88f8769db1f4280b494efe7a8c64df6c1f8faa29faf9f0862075cb69a58" +"checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" "checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" @@ -2045,6 +2200,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" "checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" +"checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98998cced76115b1da46f63388b909d118a37ae0be0f82ad35773d4a4bc9d18d" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" @@ -2058,7 +2214,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" -"checksum time 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "847da467bf0db05882a9e2375934a8a55cffdc9db0d128af1518200260ba1f6c" +"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1661fa0a44c95d01604bd05c66732a446c657efb62b5164a7a083a3b552b4951" "checksum tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4790d0be6f4ba6ae4f48190efa2ed7780c9e3567796abdb285003cf39840d9c5" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" @@ -2072,6 +2228,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" "checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum trust-dns-proto 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e33f29df428f112ffeda24b328b814b61d6916be29aa89f19bc3f684ba5437b8" +"checksum trust-dns-resolver 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "de630f95a192f793436ffae5137e88253cc4142a97d9a8e73c8d804fa85ddf0a" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" @@ -2091,6 +2249,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" +"checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" @@ -2098,5 +2257,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" +"checksum winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a" +"checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" From 998fca721a046491ef1c9c05f50c79d3efd4cd1a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 16:28:31 -0800 Subject: [PATCH 0330/1504] Add support for properties metadata in project files --- server/src/rbx_session.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 4562f784..51ef4b15 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -208,7 +208,7 @@ fn construct_project_node<'a>( RbxSnapshotInstance { class_name: Cow::Borrowed(&node.class_name), name: Cow::Borrowed(instance_name), - properties: HashMap::new(), + properties: node.properties.clone(), children, source_path: None, metadata: Some(node.metadata.clone()), From f2849357f874d6150d0c5df99bd04ab5756e23fc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 16:28:44 -0800 Subject: [PATCH 0331/1504] Remove crusty example, add property to single-sync-point --- test-projects/example.json | 27 ------------------- .../lib/sampleTranslation.csv | 6 +++++ .../single-sync-point/roblox-project.json | 9 +++++++ 3 files changed, 15 insertions(+), 27 deletions(-) delete mode 100644 test-projects/example.json create mode 100644 test-projects/single-sync-point/lib/sampleTranslation.csv diff --git a/test-projects/example.json b/test-projects/example.json deleted file mode 100644 index d86db968..00000000 --- a/test-projects/example.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "name": "example", - "tree": { - "$className": "DataModel", - "ReplicatedStorage": { - "$className": "ReplicatedStorage", - "Rojo": { - "$className": "Folder", - "Plugin": { - "$path": "lib" - }, - "Roact": { - "$path": "modules/roact/lib" - }, - "Rodux": { - "$path": "modules/rodux/lib" - }, - "RoactRodux": { - "$path": "modules/roact-rodux/lib" - }, - "Promise": { - "$path": "modules/promise/lib" - } - } - } - } -} \ No newline at end of file diff --git a/test-projects/single-sync-point/lib/sampleTranslation.csv b/test-projects/single-sync-point/lib/sampleTranslation.csv new file mode 100644 index 00000000..525fbdb2 --- /dev/null +++ b/test-projects/single-sync-point/lib/sampleTranslation.csv @@ -0,0 +1,6 @@ +Key,Context,Example,Source,es-es,de +,ClickableGroup:BuilderGui:TextLabel,You got 22 hearts!,You got {1} hearts!,, +,,"Team ""Red"" wins!","Team ""{1}"" wins!","¡Gana el equipo ""{1}""!","¡Gana el equipo ""{1}""!" +,Frame:TextLabel,,"{1} killed {2}, with a {3}","{1} mató a {2} con +una escopeta","{1} mató a {2} con +una escopeta" \ No newline at end of file diff --git a/test-projects/single-sync-point/roblox-project.json b/test-projects/single-sync-point/roblox-project.json index d3970b9c..3fbff1ac 100644 --- a/test-projects/single-sync-point/roblox-project.json +++ b/test-projects/single-sync-point/roblox-project.json @@ -7,6 +7,15 @@ "Foo": { "$path": "lib" } + }, + "HttpService": { + "$className": "HttpService", + "$properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + } } } } \ No newline at end of file From 779bcaeccb557cc77ce01f0ba838c5fb31a80619 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 16:49:23 -0800 Subject: [PATCH 0332/1504] Fix CI build (hopefully), migrate to using Cargo workspace --- .gitignore | 3 +++ .travis.yml | 2 -- server/Cargo.lock => Cargo.lock | 12 +++++++++--- Cargo.toml | 5 +++++ rojo-e2e/.gitignore | 2 -- rojo-e2e/Cargo.lock | 4 ---- server/.gitignore | 3 --- server/tests/read_projects.rs | 23 +++++++++++++++-------- 8 files changed, 32 insertions(+), 22 deletions(-) rename server/Cargo.lock => Cargo.lock (99%) create mode 100644 Cargo.toml delete mode 100644 rojo-e2e/.gitignore delete mode 100644 rojo-e2e/Cargo.lock delete mode 100644 server/.gitignore diff --git a/.gitignore b/.gitignore index c9490a53..9f64df56 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,4 @@ /site +/target +/server/scratch +**/*.rs.bk \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index 3a12362f..b8ea5d69 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,12 +29,10 @@ matrix: rust: stable script: - - cd server - cargo test --verbose - language: rust rust: beta script: - - cd server - cargo test --verbose \ No newline at end of file diff --git a/server/Cargo.lock b/Cargo.lock similarity index 99% rename from server/Cargo.lock rename to Cargo.lock index b47008b8..56d24a69 100644 --- a/server/Cargo.lock +++ b/Cargo.lock @@ -1161,9 +1161,10 @@ dependencies = [ [[package]] name = "rbx_binary" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#cb68b560bc2c5e922b4b19368ead78f775109065" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#34794a857f8654167b219e229937853388aef822" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", ] @@ -1171,7 +1172,7 @@ dependencies = [ [[package]] name = "rbx_tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#cb68b560bc2c5e922b4b19368ead78f775109065" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#34794a857f8654167b219e229937853388aef822" dependencies = [ "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1181,8 +1182,9 @@ dependencies = [ [[package]] name = "rbx_xml" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#cb68b560bc2c5e922b4b19368ead78f775109065" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#34794a857f8654167b219e229937853388aef822" dependencies = [ + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1301,6 +1303,10 @@ dependencies = [ "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rojo-e2e" +version = "0.1.0" + [[package]] name = "rouille" version = "2.2.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000..27dc248a --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,5 @@ +[workspace] +members = [ + "server", + "rojo-e2e", +] \ No newline at end of file diff --git a/rojo-e2e/.gitignore b/rojo-e2e/.gitignore deleted file mode 100644 index a79a8002..00000000 --- a/rojo-e2e/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -/target/ -**/*.rs.bk \ No newline at end of file diff --git a/rojo-e2e/Cargo.lock b/rojo-e2e/Cargo.lock deleted file mode 100644 index 0b6ac389..00000000 --- a/rojo-e2e/Cargo.lock +++ /dev/null @@ -1,4 +0,0 @@ -[[package]] -name = "rojo-e2e" -version = "0.1.0" - diff --git a/server/.gitignore b/server/.gitignore deleted file mode 100644 index 9b55d532..00000000 --- a/server/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/target/ -/scratch/ -**/*.rs.bk diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index 239016c2..af30ed99 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -7,6 +7,8 @@ use std::{ path::{Path, PathBuf}, }; +use rbx_tree::RbxValue; + use librojo::{ project::{Project, ProjectNode, InstanceProjectNode, SyncPointProjectNode}, }; @@ -17,14 +19,6 @@ lazy_static! { }; } -#[test] -fn tour_de_force() { - let project_file_location = TEST_PROJECTS_ROOT.join("example.json"); - let project = Project::load_exact(&project_file_location).unwrap(); - - assert_eq!(project.name, "example"); -} - #[test] fn empty() { let project_file_location = TEST_PROJECTS_ROOT.join("empty/roblox-project.json"); @@ -69,8 +63,21 @@ fn single_sync_point() { metadata: Default::default(), }); + let mut http_service_properties = HashMap::new(); + http_service_properties.insert("HttpEnabled".to_string(), RbxValue::Bool { + value: true, + }); + + let http_service = ProjectNode::Instance(InstanceProjectNode { + class_name: "HttpService".to_string(), + children: HashMap::new(), + properties: http_service_properties, + metadata: Default::default(), + }); + let mut root_children = HashMap::new(); root_children.insert("ReplicatedStorage".to_string(), replicated_storage); + root_children.insert("HttpService".to_string(), http_service); let root_node = ProjectNode::Instance(InstanceProjectNode { class_name: "DataModel".to_string(), From 4e7aa5d0a9757d0086c3ef532b2c58f8ec93acf8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 16:56:39 -0800 Subject: [PATCH 0333/1504] Expand changelog --- CHANGES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index e43da968..c7187d4c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -17,6 +17,12 @@ * New UI to pick server address and port * Better error reporting * Added support for `.csv` files turning into `LocalizationTable` instances +* Added debug visualization code to diagnose problems + * `/visualize/rbx` and `/visualize/imfs` show instance and file state respectively; they require GraphViz to be installed on your machine. +* Added optional place ID restrictions to project files + * This helps prevent syncing in content to the wrong place + * Multiple places can be specified, like when building a multi-place game +* Added support for specifying properties on services in project files ## 0.4.13 (November 12, 2018) * When `rojo.json` points to a file or directory that does not exist, Rojo now issues a warning instead of throwing an error and exiting From f870107c66e3296be2a323be8d187ab06f9927c7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 18:16:58 -0800 Subject: [PATCH 0334/1504] Foundations for actual 'rojo init' implementation --- server/src/project.rs | 105 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 95 insertions(+), 10 deletions(-) diff --git a/server/src/project.rs b/server/src/project.rs index 46c4d7be..c4c6d45c 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -1,6 +1,7 @@ use std::{ collections::{HashMap, HashSet}, - fs, + fmt, + fs::{self, File}, io, path::{Path, PathBuf}, }; @@ -127,12 +128,30 @@ impl From for ProjectLoadFuzzyError { } #[derive(Debug, Fail)] -#[fail(display = "Project init error")] -pub struct ProjectInitError; +pub enum ProjectInitError { + AlreadyExists(PathBuf), + IoError(#[fail(cause)] io::Error), + SaveError(#[fail(cause)] ProjectSaveError), +} + +impl fmt::Display for ProjectInitError { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + match self { + ProjectInitError::AlreadyExists(path) => write!(output, "Path {} already exists", path.display()), + ProjectInitError::IoError(inner) => write!(output, "IO error: {}", inner), + ProjectInitError::SaveError(inner) => write!(output, "{}", inner), + } + } +} #[derive(Debug, Fail)] -#[fail(display = "Project save error")] -pub struct ProjectSaveError; +pub enum ProjectSaveError { + #[fail(display = "JSON error: {}", _0)] + JsonError(#[fail(cause)] serde_json::Error), + + #[fail(display = "IO error: {}", _0)] + IoError(#[fail(cause)] io::Error), +} #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -180,14 +199,75 @@ pub struct Project { } impl Project { - pub fn init_place(_project_fuzzy_location: &Path) -> Result { - unimplemented!(); + pub fn init_place(project_fuzzy_location: &Path) -> Result { + let is_exact = project_fuzzy_location.extension().is_some(); + + let project_name = if is_exact { + project_fuzzy_location.parent().unwrap().file_name().unwrap().to_str().unwrap() + } else { + project_fuzzy_location.file_name().unwrap().to_str().unwrap() + }; + + // TODO: Add children for src folder, potentially client, server, and + // common? + + let replicated_storage_children = HashMap::new(); + + let replicated_storage = ProjectNode::Instance(InstanceProjectNode { + class_name: "ReplicatedStorage".to_string(), + children: replicated_storage_children, + properties: HashMap::new(), + metadata: Default::default(), + }); + + let mut root_children = HashMap::new(); + root_children.insert("ReplicatedStorage".to_string(), replicated_storage); + + let tree = ProjectNode::Instance(InstanceProjectNode { + class_name: "DataModel".to_string(), + children: root_children, + properties: HashMap::new(), + metadata: Default::default(), + }); + + let project = Project { + name: project_name.to_string(), + tree, + serve_port: None, + serve_place_ids: None, + file_location: project_fuzzy_location.to_path_buf(), + }; + + Project::init_internal(project_fuzzy_location, &project) } pub fn init_model(_project_fuzzy_location: &Path) -> Result { unimplemented!(); } + fn init_internal(project_fuzzy_location: &Path, project: &Project) -> Result { + let is_exact = project_fuzzy_location.extension().is_some(); + + let project_location = if is_exact { + project_fuzzy_location.to_path_buf() + } else { + project_fuzzy_location.join(PROJECT_FILENAME) + }; + + match fs::metadata(&project_location) { + Err(error) => match error.kind() { + io::ErrorKind::NotFound => {}, + _ => return Err(ProjectInitError::IoError(error)), + }, + Ok(_) => return Err(ProjectInitError::AlreadyExists(project_location)), + } + + project.save(&project_location) + .map_err(ProjectInitError::SaveError)?; + + Ok(project_location) + } + pub fn locate(start_location: &Path) -> Option { // TODO: Check for specific error kinds, convert 'not found' to Result. let location_metadata = fs::metadata(start_location).ok()?; @@ -230,10 +310,15 @@ impl Project { Ok(parsed.into_project(project_file_location)) } - pub fn save(&self) -> Result<(), ProjectSaveError> { - let _source_project = self.to_source_project(); + pub fn save(&self, path: &Path) -> Result<(), ProjectSaveError> { + let source_project = self.to_source_project(); + let mut file = File::create(path) + .map_err(ProjectSaveError::IoError)?; - unimplemented!(); + serde_json::to_writer_pretty(&mut file, &source_project) + .map_err(ProjectSaveError::JsonError)?; + + Ok(()) } fn to_source_project(&self) -> SourceProject { From 6ced8f32b146e1d827ce7f293bb4e5aa29c1b56e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 20:52:00 -0800 Subject: [PATCH 0335/1504] Make rojo-e2e a lib so 'cargo run' works again --- rojo-e2e/src/{main.rs => lib.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename rojo-e2e/src/{main.rs => lib.rs} (100%) diff --git a/rojo-e2e/src/main.rs b/rojo-e2e/src/lib.rs similarity index 100% rename from rojo-e2e/src/main.rs rename to rojo-e2e/src/lib.rs From 98f8c5c0f2f8a30b34fb6f468ff66a5e8be79d44 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 21:16:08 -0800 Subject: [PATCH 0336/1504] Working 'init' command for places --- server/src/bin.rs | 2 +- server/src/commands/init.rs | 2 +- server/src/project.rs | 106 ++++++++++++++++++++++++++++-------- 3 files changed, 84 insertions(+), 26 deletions(-) diff --git a/server/src/bin.rs b/server/src/bin.rs index e6f43df3..7607abff 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -60,7 +60,7 @@ fn main() { match matches.subcommand() { ("init", Some(sub_matches)) => { - let fuzzy_project_path = make_path_absolute(Path::new(sub_matches.value_of("PATH").unwrap_or("."))); + let fuzzy_project_path = make_path_absolute(Path::new(sub_matches.value_of("PATH").unwrap_or(""))); let kind = sub_matches.value_of("kind"); let options = commands::InitOptions { diff --git a/server/src/commands/init.rs b/server/src/commands/init.rs index a764ccb0..9bc5bd71 100644 --- a/server/src/commands/init.rs +++ b/server/src/commands/init.rs @@ -40,7 +40,7 @@ pub fn init(options: &InitOptions) -> Result<(), InitError> { Some(invalid) => return Err(InitError::InvalidKind(invalid.to_string())), }; - println!("Created new {} project at {}", project_kind, project_path.display()); + println!("Created new {} project file at {}", project_kind, project_path.display()); Ok(()) } \ No newline at end of file diff --git a/server/src/project.rs b/server/src/project.rs index c4c6d45c..10f91118 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -16,6 +16,10 @@ const fn yeah() -> bool { true } +const fn is_true(value: &bool) -> bool { + *value +} + #[derive(Debug, Serialize, Deserialize)] #[serde(untagged)] enum SourceProjectNode { @@ -23,10 +27,10 @@ enum SourceProjectNode { #[serde(rename = "$className")] class_name: String, - #[serde(rename = "$properties", default = "HashMap::new")] + #[serde(rename = "$properties", default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")] properties: HashMap, - #[serde(rename = "$ignoreUnknownInstances", default = "yeah")] + #[serde(rename = "$ignoreUnknownInstances", default = "yeah", skip_serializing_if = "is_true")] ignore_unknown_instances: bool, #[serde(flatten)] @@ -78,9 +82,10 @@ impl SourceProjectNode { struct SourceProject { name: String, tree: SourceProjectNode, + #[serde(skip_serializing_if = "Option::is_none")] serve_port: Option, + #[serde(skip_serializing_if = "Option::is_none")] serve_place_ids: Option>, - serve_place_id: Option, } impl SourceProject { @@ -174,6 +179,39 @@ pub enum ProjectNode { SyncPoint(SyncPointProjectNode), } +impl ProjectNode { + fn to_source_node(&self, project_file_location: &Path) -> SourceProjectNode { + match self { + ProjectNode::Instance(node) => { + let mut children = HashMap::new(); + + for (key, child) in &node.children { + children.insert(key.clone(), child.to_source_node(project_file_location)); + } + + SourceProjectNode::Instance { + class_name: node.class_name.clone(), + children, + properties: node.properties.clone(), + ignore_unknown_instances: node.metadata.ignore_unknown_instances, + } + }, + ProjectNode::SyncPoint(sync_node) => { + let project_folder_location = project_file_location.parent().unwrap(); + + let friendly_path = match sync_node.path.strip_prefix(project_folder_location) { + Ok(stripped) => stripped.to_str().unwrap().replace("\\", "/"), + Err(_) => format!("{}", sync_node.path.display()), + }; + + SourceProjectNode::SyncPoint { + path: friendly_path, + } + }, + } + } +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct InstanceProjectNode { @@ -199,18 +237,30 @@ pub struct Project { } impl Project { - pub fn init_place(project_fuzzy_location: &Path) -> Result { - let is_exact = project_fuzzy_location.extension().is_some(); + pub fn init_place(project_fuzzy_path: &Path) -> Result { + let is_exact = project_fuzzy_path.extension().is_some(); let project_name = if is_exact { - project_fuzzy_location.parent().unwrap().file_name().unwrap().to_str().unwrap() + project_fuzzy_path.parent().unwrap().file_name().unwrap().to_str().unwrap() } else { - project_fuzzy_location.file_name().unwrap().to_str().unwrap() + project_fuzzy_path.file_name().unwrap().to_str().unwrap() }; // TODO: Add children for src folder, potentially client, server, and // common? + let mut http_service_properties = HashMap::new(); + http_service_properties.insert("HttpEnabled".to_string(), RbxValue::Bool { + value: true, + }); + + let http_service = ProjectNode::Instance(InstanceProjectNode { + class_name: "HttpService".to_string(), + children: HashMap::new(), + properties: http_service_properties, + metadata: Default::default(), + }); + let replicated_storage_children = HashMap::new(); let replicated_storage = ProjectNode::Instance(InstanceProjectNode { @@ -222,6 +272,7 @@ impl Project { let mut root_children = HashMap::new(); root_children.insert("ReplicatedStorage".to_string(), replicated_storage); + root_children.insert("HttpService".to_string(), http_service); let tree = ProjectNode::Instance(InstanceProjectNode { class_name: "DataModel".to_string(), @@ -230,42 +281,44 @@ impl Project { metadata: Default::default(), }); + let project_path = Project::init_pick_path(project_fuzzy_path)?; + let project = Project { name: project_name.to_string(), tree, serve_port: None, serve_place_ids: None, - file_location: project_fuzzy_location.to_path_buf(), + file_location: project_path.clone(), }; - Project::init_internal(project_fuzzy_location, &project) + project.save() + .map_err(ProjectInitError::SaveError)?; + + Ok(project_path) } - pub fn init_model(_project_fuzzy_location: &Path) -> Result { + pub fn init_model(_project_fuzzy_path: &Path) -> Result { unimplemented!(); } - fn init_internal(project_fuzzy_location: &Path, project: &Project) -> Result { - let is_exact = project_fuzzy_location.extension().is_some(); + fn init_pick_path(project_fuzzy_path: &Path) -> Result { + let is_exact = project_fuzzy_path.extension().is_some(); - let project_location = if is_exact { - project_fuzzy_location.to_path_buf() + let project_path = if is_exact { + project_fuzzy_path.to_path_buf() } else { - project_fuzzy_location.join(PROJECT_FILENAME) + project_fuzzy_path.join(PROJECT_FILENAME) }; - match fs::metadata(&project_location) { + match fs::metadata(&project_path) { Err(error) => match error.kind() { io::ErrorKind::NotFound => {}, _ => return Err(ProjectInitError::IoError(error)), }, - Ok(_) => return Err(ProjectInitError::AlreadyExists(project_location)), + Ok(_) => return Err(ProjectInitError::AlreadyExists(project_path)), } - project.save(&project_location) - .map_err(ProjectInitError::SaveError)?; - - Ok(project_location) + Ok(project_path) } pub fn locate(start_location: &Path) -> Option { @@ -310,9 +363,9 @@ impl Project { Ok(parsed.into_project(project_file_location)) } - pub fn save(&self, path: &Path) -> Result<(), ProjectSaveError> { + pub fn save(&self) -> Result<(), ProjectSaveError> { let source_project = self.to_source_project(); - let mut file = File::create(path) + let mut file = File::create(&self.file_location) .map_err(ProjectSaveError::IoError)?; serde_json::to_writer_pretty(&mut file, &source_project) @@ -322,6 +375,11 @@ impl Project { } fn to_source_project(&self) -> SourceProject { - unimplemented!(); + SourceProject { + name: self.name.clone(), + tree: self.tree.to_source_node(&self.file_location), + serve_port: self.serve_port, + serve_place_ids: self.serve_place_ids.clone(), + } } } \ No newline at end of file From ce5ea9207637facf23e9428cf98033b9b5739e8f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 21:27:10 -0800 Subject: [PATCH 0337/1504] Add maplit, flesh out 'init' place command --- Cargo.lock | 7 +++++ server/Cargo.toml | 1 + server/src/project.rs | 60 +++++++++++++++++++------------------------ 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 56d24a69..1a37b901 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -704,6 +704,11 @@ dependencies = [ "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "maplit" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "matches" version = "0.1.8" @@ -1287,6 +1292,7 @@ dependencies = [ "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", @@ -2125,6 +2131,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" +"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9" diff --git a/server/Cargo.toml b/server/Cargo.toml index 88bdf38e..ba818366 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -25,6 +25,7 @@ csv = "1.0" env_logger = "0.5" failure = "0.1.3" log = "0.4" +maplit = "1.0.1" notify = "4.0" rand = "0.4" regex = "1.0" diff --git a/server/src/project.rs b/server/src/project.rs index 10f91118..5647625c 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -6,6 +6,7 @@ use std::{ path::{Path, PathBuf}, }; +use maplit::hashmap; use failure::Fail; use rbx_tree::RbxValue; @@ -238,51 +239,42 @@ pub struct Project { impl Project { pub fn init_place(project_fuzzy_path: &Path) -> Result { - let is_exact = project_fuzzy_path.extension().is_some(); - - let project_name = if is_exact { + let project_path = Project::init_pick_path(project_fuzzy_path)?; + let project_folder_path = project_path.parent().unwrap(); + let project_name = if project_fuzzy_path == project_path { project_fuzzy_path.parent().unwrap().file_name().unwrap().to_str().unwrap() } else { project_fuzzy_path.file_name().unwrap().to_str().unwrap() }; - // TODO: Add children for src folder, potentially client, server, and - // common? - - let mut http_service_properties = HashMap::new(); - http_service_properties.insert("HttpEnabled".to_string(), RbxValue::Bool { - value: true, - }); - - let http_service = ProjectNode::Instance(InstanceProjectNode { - class_name: "HttpService".to_string(), - children: HashMap::new(), - properties: http_service_properties, - metadata: Default::default(), - }); - - let replicated_storage_children = HashMap::new(); - - let replicated_storage = ProjectNode::Instance(InstanceProjectNode { - class_name: "ReplicatedStorage".to_string(), - children: replicated_storage_children, - properties: HashMap::new(), - metadata: Default::default(), - }); - - let mut root_children = HashMap::new(); - root_children.insert("ReplicatedStorage".to_string(), replicated_storage); - root_children.insert("HttpService".to_string(), http_service); - let tree = ProjectNode::Instance(InstanceProjectNode { class_name: "DataModel".to_string(), - children: root_children, + children: hashmap! { + String::from("ReplicatedStorage") => ProjectNode::Instance(InstanceProjectNode { + class_name: String::from("ReplicatedStorage"), + children: hashmap! { + String::from("Source") => ProjectNode::SyncPoint(SyncPointProjectNode { + path: project_folder_path.join("src"), + }), + }, + properties: HashMap::new(), + metadata: Default::default(), + }), + String::from("HttpService") => ProjectNode::Instance(InstanceProjectNode { + class_name: String::from("HttpService"), + children: HashMap::new(), + properties: hashmap! { + String::from("HttpEnabled") => RbxValue::Bool { + value: true, + }, + }, + metadata: Default::default(), + }), + }, properties: HashMap::new(), metadata: Default::default(), }); - let project_path = Project::init_pick_path(project_fuzzy_path)?; - let project = Project { name: project_name.to_string(), tree, From 54da8264471af0c6247837a4ae8771b3afa98a5e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 21:30:00 -0800 Subject: [PATCH 0338/1504] Implement rojo init for models --- server/src/project.rs | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/server/src/project.rs b/server/src/project.rs index 5647625c..6cfd147f 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -289,8 +289,31 @@ impl Project { Ok(project_path) } - pub fn init_model(_project_fuzzy_path: &Path) -> Result { - unimplemented!(); + pub fn init_model(project_fuzzy_path: &Path) -> Result { + let project_path = Project::init_pick_path(project_fuzzy_path)?; + let project_folder_path = project_path.parent().unwrap(); + let project_name = if project_fuzzy_path == project_path { + project_fuzzy_path.parent().unwrap().file_name().unwrap().to_str().unwrap() + } else { + project_fuzzy_path.file_name().unwrap().to_str().unwrap() + }; + + let tree = ProjectNode::SyncPoint(SyncPointProjectNode { + path: project_folder_path.join("src"), + }); + + let project = Project { + name: project_name.to_string(), + tree, + serve_port: None, + serve_place_ids: None, + file_location: project_path.clone(), + }; + + project.save() + .map_err(ProjectInitError::SaveError)?; + + Ok(project_path) } fn init_pick_path(project_fuzzy_path: &Path) -> Result { From c883850142629ec920f9eb86ea85a3b135317057 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 22:04:24 -0800 Subject: [PATCH 0339/1504] Support -o for build as an --output alias --- server/src/bin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/bin.rs b/server/src/bin.rs index 7607abff..87520d5a 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -44,7 +44,7 @@ fn main() { (@subcommand build => (about: "Generates an rbxmx model file from the project.") (@arg PROJECT: "Path to the project to serve. Defaults to the current directory.") - (@arg output: --output +takes_value +required "Where to output the result.") + (@arg output: --output -o +takes_value +required "Where to output the result.") ) (@subcommand upload => From 0822aa9240770de3655af0c46777497b301dc57b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 22:25:04 -0800 Subject: [PATCH 0340/1504] Update docs for Epiphany --- docs/getting-started/creating-a-place.md | 64 ++++++++++++++++++ docs/getting-started/creating-a-project.md | 77 ---------------------- docs/getting-started/installation.md | 1 - docs/index.md | 3 +- docs/migrating-to-epiphany.md | 59 +++++++++++++++++ docs/sync-details.md | 66 +++++-------------- docs/why-rojo.md | 1 - mkdocs.yml | 3 +- 8 files changed, 144 insertions(+), 130 deletions(-) create mode 100644 docs/getting-started/creating-a-place.md delete mode 100644 docs/getting-started/creating-a-project.md create mode 100644 docs/migrating-to-epiphany.md diff --git a/docs/getting-started/creating-a-place.md b/docs/getting-started/creating-a-place.md new file mode 100644 index 00000000..1ff300ed --- /dev/null +++ b/docs/getting-started/creating-a-place.md @@ -0,0 +1,64 @@ +To use Rojo to build a place, you'll need to create a new project file, which tells Rojo how your project is structured on-disk and in Roblox. + +Create a new folder, then run `rojo init` inside that folder to initialize an empty project. + +```sh +mkdir my-new-project +cd my-new-project + +rojo init +``` + +Rojo will make a small project file in your directory, named `roblox-project.json`. It'll make sure that any code in the directory `src` will get put into `ReplicatedStorage.Source`. + +Speaking of, let's make sure we create a directory named `src`, and maybe a Lua file inside of it: + +```sh +mkdir src +echo 'print("Hello, world!")' > src/hello.lua +``` + +## Building Your Place +Now that we have a project, one thing we can do is build a Roblox place file for our project. This is a great way to get started with a project quickly with no fuss. + +All we have to do is call `rojo build`: + +```sh +rojo build -o MyNewProject.rbxl +``` + +If you open `MyNewProject.rbxl` in Roblox Studio now, you should see a `Folder` containing a `ModuleScript` under `ReplicatedStorage`! + +!!! info + To generate an XML place file instead, like if you're checking the place file into version control, just use `rbxlx` as the extension on the output file instead. + +## Live-Syncing into Studio +Building a place file is great for the initial build, but for actively working on your place, you'll want something quicker. + +In Roblox Studio, make sure the Rojo plugin is installed. If you need it, check out [the installation guide](installation) to learn how to install it. + +To expose your project to the plugin, you'll need to _serve_ it from the command line: + +```sh +rojo serve +``` + +This will start up a web server that tells Roblox Studio what instances are in your project and sends notifications if any of them change. + +Note the port number, then switch into Roblox Studio and press the Rojo **Connect** button in the plugins tab. Type in the port number, if necessary, and press **Start**. + +If everything went well, you should now be able to change files in the `src` directory and watch them sync into Roblox Studio in real time! + +## Uploading Your Place +Aimed at teams that want serious levels of automation, Rojo can upload places to Roblox.com automatically. + +You'll need an existing place on Roblox.com as well as the `.ROBLOSECURITY` cookie of an account that has write access to that place. + +!!! warning + It's recommended that you set up a Roblox account dedicated to deploying your place instead of your personal account in case your security cookie is compromised. + +Generating and uploading your place file is as simple as: + +```sh +rojo upload --place_id [PLACE ID] --cookie "[SECURITY COOKIE]" +``` \ No newline at end of file diff --git a/docs/getting-started/creating-a-project.md b/docs/getting-started/creating-a-project.md deleted file mode 100644 index 49dad7fc..00000000 --- a/docs/getting-started/creating-a-project.md +++ /dev/null @@ -1,77 +0,0 @@ -# Creating a Project -To use Rojo, you'll need to create a new project file, which tells Rojo what your project is, and how to load it into Roblox Studio. - -## New Project -Create a new folder, then run `rojo init` inside that folder to initialize an empty project. - -```sh -mkdir my-new-project -cd my-new-project - -rojo init -``` - -Rojo will create an empty project file named `rojo.json` in the directory. - -The default configuration doesn't do anything. We need to tell Rojo where our code is on the filesystem, and where we want to put it in the Roblox tree. - -To do that, open up `rojo.json` and add an entry to the `partitions` table: - -```json -{ - "name": "your-project-name-here", - "servePort": 8000, - "partitions": { - "src": { - "path": "src", - "target": "ReplicatedStorage.Project" - } - } -} -``` - -!!! warning - Make sure that the `src` directory exists in your project, or Rojo will throw an error! - -!!! warning - Any objects contained in the `target` of a partition will be destroyed by Rojo if not found on the filesystem! - -A Rojo project has one or more *partitions*. Partitions define how code should be transferred between the filesystem and Roblox by mapping directories and files to Roblox objects. - -Each partition has: - -* A name (the key in the `partitions` object), which is used for debugging -* `path`, the location on the filesystem relative to `rojo.json` -* `target`, the location in Roblox relative to `game` - -## Syncing into Studio - -Once you've added your partition to the project file, you can start the Rojo dev server by running a command in your project's directory: - -```sh -rojo serve -``` - -If your project is in the right place, Rojo will let you know that it was found and start an HTTP server that the plugin can connect to. - -In Roblox Studio, open the plugins tab and find Rojo's buttons. - -![Location of Rojo's plugin buttons in Roblox Studio](/images/plugin-buttons.png) -{: align="center" } - -Press **Test Connection** to verify that the plugin can communicate with the dev server. Watch the Output panel for the results. - -!!! info - If you see an error message, return to the previous steps and make sure that the Rojo dev server is running. - - ![Rojo error in Roblox Studio Output](/images/connection-error.png) - {: align="center" } - -After your connection was successful, press **Sync In** to move code from the filesystem into Studio, or use **Toggle Polling** to have Rojo automatically sync in changes as they happen. - -## Importing an Existing Project -Rojo will eventually support importing an existing Roblox project onto the filesystem for use with Rojo. - -Rojo doesn't currently support converting an existing project or syncing files from Roblox Studio onto the filesystem. In the mean time, you can manually copy your files into the structure that Rojo expects. - -Up-to-date information will be available on [issue #5](https://github.com/LPGhatguy/rojo/issues/5) as this is worked on. \ No newline at end of file diff --git a/docs/getting-started/installation.md b/docs/getting-started/installation.md index 2b843a32..77a5728c 100644 --- a/docs/getting-started/installation.md +++ b/docs/getting-started/installation.md @@ -1,4 +1,3 @@ -# Installation Rojo has two components: * The server, a binary written in Rust diff --git a/docs/index.md b/docs/index.md index a3319d83..03f92af1 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,5 @@ -# Home This is the documentation home for Rojo. **Rojo** is a flexible multi-tool designed for creating robust Roblox projects. -This documentation is a work in progress, and is incomplete. \ No newline at end of file +This documentation is a continual work in progress. If you find any issues, please file an issue on [Rojo's issue tracker](https://github.com/LPGhatguy/rojo/issues)! \ No newline at end of file diff --git a/docs/migrating-to-epiphany.md b/docs/migrating-to-epiphany.md new file mode 100644 index 00000000..98fca7b8 --- /dev/null +++ b/docs/migrating-to-epiphany.md @@ -0,0 +1,59 @@ +Rojo underwent a large refactor during most of 2018 to enable a bunch of new features and lay groundwork for lots more in 2019. As such, Rojo **0.5.x** projects are not compatible with Rojo **0.4.x** projects. + +## Supporting Both 0.4.x and 0.5.x +Rojo 0.5.x uses a different name for its project format. While 0.4.x used `rojo.json`, 0.5.x uses `roblox-project.json`, which allows them to coexist. + +If you aren't sure about upgrading or want to upgrade gradually, it's possible to keep both files in the same project without causing problems. + +## Upgrading Your Project File +Project files in 0.5.x are more explicit and flexible than they were in 0.4.x. Project files can now describe models and plugins in addition to places. + +This new project file format also guards against two of the biggest pitfalls when writing a config file: + +* Using a service as a partition target directly, which often wiped away extra instances +* Defining two partitions that overlapped, which made Rojo act unpredictably + +The biggest change is that the `partitions` field has been replaced with a new field, `tree`, that describes the entire hierarchy of your project from the top-down. + +A project for 0.4.x that syncs from the `src` directory into `ReplicatedStorage.Source` would look like this: + +```json +{ + "name": "Rojo 0.4.x Example", + "partitions": { + "path": "src", + "target": "ReplicatedStorage.Source" + } +} +``` + +In 0.5.x, the project format is more explicit: + +```json +{ + "name": "Rojo 0.5.x Example", + "tree": { + "$className": "DataModel", + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + "Source": { + "$path": "src" + } + } + } +} +``` + +For each object in the tree, we define *metadata* and *children*. + +Metadata begins with a dollar sign (`$`), like `$className`. This is so that children and metadata can coexist without creating too many nested layers. + +All other values are considered children, where the key is the instance's name, and the value is an object, repeating the process. + +## Migrating `.model.json` Files +No upgrade path yet, stay tuned. + +## Migrating Unknown Files +If you used Rojo to sync in files as `StringValue` objects, you'll need to make sure those files end with the `txt` extension to preserve this in Rojo 0.5.x. + +Unknown files are now ignored in Rojo instead of being converted to `StringValue` objects. \ No newline at end of file diff --git a/docs/sync-details.md b/docs/sync-details.md index a9f2b7be..55a1e543 100644 --- a/docs/sync-details.md +++ b/docs/sync-details.md @@ -1,21 +1,24 @@ -# Sync Details This page aims to describe how Rojo turns files on the filesystem into Roblox objects. +## Overview +| File Name | Instance Type | +| -------------- | ------------------- | +| any directory | `Folder` | +| `*.server.lua` | `Script` | +| `*.client.lua` | `LocalScript` | +| `*.lua` | `ModuleScript` | +| `*.csv` | `LocalizationTable` | +| `*.txt` | `StringValue` | + ## Folders -Any directory on the filesystem will turn into a `Folder` instance in Roblox, unless that folder matches the name of a service or other existing instance. In those cases, that instance will be preserved. +Any directory on the filesystem will turn into a `Folder` instance unless it contains an 'init' script, described below. ## Scripts -Rojo can represent `ModuleScript`, `Script`, and `LocalScript` objects. The default script type is `ModuleScript`, since most scripts in well-structued Roblox projects will be modules. +The default script type in Rojo projects is `ModuleScript`, since most scripts in well-structued Roblox projects will be modules. -| File Name | Instance Type | -| -------------- | -------------- | -| `*.server.lua` | `Script` | -| `*.client.lua` | `LocalScript` | -| `*.lua` | `ModuleScript` | +If a directory contains a file named `init.server.lua`, `init.client.lua`, or `init.lua`, that folder will be transformed into a `*Script` instance with the contents of the 'init' file. This can be used to create scripts inside of scripts. -If a directory contains a file named `init.server.lua`, `init.client.lua`, or `init.lua`, that folder will be transformed into a `*Script` instance with the conents of the `init` file. This can be used to create scripts inside of scripts. - -For example, this file tree: +For example, these files: * my-game * init.client.lua @@ -25,41 +28,8 @@ Will turn into these instances in Roblox: ![Example of Roblox instances](/images/sync-example.png) -## Models -Rojo supports a JSON model format for representing simple models. It's designed for instance types like `BindableEvent` or `Value` objects, and is not suitable for larger models. +## Localization Tables +Any CSV files are transformed into `LocalizationTable` instances. Rojo expects these files to follow the same format that Roblox does when importing and exporting localization information. -Rojo JSON models are stored in `.model.json` files. - -Starting in Rojo version **0.4.10**, model files named `init.model.json` that are located in folders will replace that folder, much like Rojo's `init.lua` support. This can be useful to version instances like `Tool` that tend to contain several instances as well as one or more scripts. - -!!! info - In the future, Rojo will support `.rbxmx` models. See [issue #7](https://github.com/LPGhatguy/rojo/issues/7) for more details and updates on this feature. - -!!! warning - Prior to Rojo version **0.4.9**, the `Properties` and `Children` properties are required on all instances in JSON models! - -JSON model files are fairly strict; any syntax errors will cause the model to fail to sync! They look like this: - -`hello.model.json` -```json -{ - "Name": "hello", - "ClassName": "Model", - "Children": [ - { - "Name": "Some Part", - "ClassName": "Part" - }, - { - "Name": "Some StringValue", - "ClassName": "StringValue", - "Properties": { - "Value": { - "Type": "String", - "Value": "Hello, world!" - } - } - } - ] -} -``` \ No newline at end of file +## Plain Text Files +Plain text files (`.txt`) files are transformed into `StringValue` instances. This is useful for bringing in text data that can be read by scripts at runtime. \ No newline at end of file diff --git a/docs/why-rojo.md b/docs/why-rojo.md index b6872309..f4ecae06 100644 --- a/docs/why-rojo.md +++ b/docs/why-rojo.md @@ -1,4 +1,3 @@ -# Why Rojo? There are a number of existing plugins for Roblox that move code from the filesystem into Roblox. Besides Rojo, there is: diff --git a/mkdocs.yml b/mkdocs.yml index 703712bf..a6cbf9fc 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -14,8 +14,9 @@ pages: - Why Rojo?: why-rojo.md - Getting Started: - Installation: getting-started/installation.md - - Creating a Project: getting-started/creating-a-project.md + - Creating a Place with Rojo: getting-started/creating-a-place.md - Sync Details: sync-details.md + - Migrating from 0.4.x to 0.5.x: migrating-to-epiphany.md markdown_extensions: - attr_list From 54b8a1aea5bab0077ad2bdfa9210a72a913e926c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 23:10:15 -0800 Subject: [PATCH 0341/1504] Upgrade to latest MkDocs --- mkdocs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index a6cbf9fc..711d3fd5 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -9,7 +9,7 @@ theme: primary: 'Red' accent: 'Red' -pages: +nav: - Home: index.md - Why Rojo?: why-rojo.md - Getting Started: From 95866d0f2eafe388ad1013df2fe01fc47847e54e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 23:14:59 -0800 Subject: [PATCH 0342/1504] Multiple versions of the docs --- docs/index.md | 6 ++++++ generate-docs | 25 +++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 generate-docs diff --git a/docs/index.md b/docs/index.md index 03f92af1..886c9fd0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,11 @@ This is the documentation home for Rojo. +Other versions of these docs: + +* [0.5.x](https://lpghatguy.github.io/rojo/0.5.x) +* [0.4.x](https://lpghatguy.github.io/rojo/0.4.x) +* [`master` branch](https://lpghatguy.github.io/rojo/master) + **Rojo** is a flexible multi-tool designed for creating robust Roblox projects. This documentation is a continual work in progress. If you find any issues, please file an issue on [Rojo's issue tracker](https://github.com/LPGhatguy/rojo/issues)! \ No newline at end of file diff --git a/generate-docs b/generate-docs new file mode 100644 index 00000000..d74e096d --- /dev/null +++ b/generate-docs @@ -0,0 +1,25 @@ +#!/bin/sh + +# Kludged documentation generator to support multiple versions. +# Make sure the `site` folder is a checkout of this repository's `gh-pages` +# branch. +# To use, run `generate-docs` in the root of the repository. + +set -e + +CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) + +echo "Building 0.4.x" +git checkout v0.4.x +mkdocs build --site-dir site +mkdocs build --site-dir site/0.4.x + +git checkout master + +echo "Building master" +mkdocs build --site-dir site/master + +echo "Building 0.5.x" +mkdocs build --site-dir site/0.5.x + +git checkout "$CURRENT_BRANCH" \ No newline at end of file From 4b811667824843a7562f86641c2173aae91f436b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 23:19:52 -0800 Subject: [PATCH 0343/1504] Pull after switching branches in generate-docs --- generate-docs | 1 + 1 file changed, 1 insertion(+) diff --git a/generate-docs b/generate-docs index d74e096d..159d379a 100644 --- a/generate-docs +++ b/generate-docs @@ -11,6 +11,7 @@ CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) echo "Building 0.4.x" git checkout v0.4.x +git pull mkdocs build --site-dir site mkdocs build --site-dir site/0.4.x From 9ac001bd3e848994528b869fa9fcade86c6739ba Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Jan 2019 23:22:42 -0800 Subject: [PATCH 0344/1504] Stupid workaround for Git statting files on branch switch --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 9f64df56..f6839452 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /site /target /server/scratch -**/*.rs.bk \ No newline at end of file +**/*.rs.bk +/generate-docs.run \ No newline at end of file From d52ecaa050a63e9f9dd2c738adc291fbc80a375a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 10 Jan 2019 11:15:11 -0800 Subject: [PATCH 0345/1504] Stop building documentation root, only version-specific docs --- README.md | 6 +++--- docs/index.md | 2 +- generate-docs | 7 +++---- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 26df1316..f0804bfc 100644 --- a/README.md +++ b/README.md @@ -11,8 +11,8 @@ Latest server version - - Rojo Documentation + + Rojo Documentation @@ -38,7 +38,7 @@ Soon, Rojo will be able to: * Sync `rbxmx` models between the filesystem and Roblox Studio * Package projects into `rbxmx` files from the command line -## [Documentation](https://lpghatguy.github.io/rojo) +## [Documentation](https://lpghatguy.github.io/rojo/0.4.x) You can also view the documentation by browsing the [docs](https://github.com/LPGhatguy/rojo/tree/master/docs) folder of the repository, but because it uses a number of Markdown extensions, it may not be very readable. ## Inspiration and Alternatives diff --git a/docs/index.md b/docs/index.md index 886c9fd0..712f95a3 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,6 +1,6 @@ This is the documentation home for Rojo. -Other versions of these docs: +Available versions of these docs: * [0.5.x](https://lpghatguy.github.io/rojo/0.5.x) * [0.4.x](https://lpghatguy.github.io/rojo/0.4.x) diff --git a/generate-docs b/generate-docs index 159d379a..6366a096 100644 --- a/generate-docs +++ b/generate-docs @@ -3,7 +3,8 @@ # Kludged documentation generator to support multiple versions. # Make sure the `site` folder is a checkout of this repository's `gh-pages` # branch. -# To use, run `generate-docs` in the root of the repository. +# To use, copy this file to `generate-docs.run` so that Git will leave it alone, +# then run `generate-docs.run` in the root of the repository. set -e @@ -12,12 +13,10 @@ CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) echo "Building 0.4.x" git checkout v0.4.x git pull -mkdocs build --site-dir site mkdocs build --site-dir site/0.4.x -git checkout master - echo "Building master" +git checkout master mkdocs build --site-dir site/master echo "Building 0.5.x" From d53ffd8da288767cf3a7cdc22e4e425018f9a3d0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 10 Jan 2019 14:31:41 -0800 Subject: [PATCH 0346/1504] Add support for uploading models, rename place_id to asset_id --- docs/getting-started/creating-a-place.md | 2 +- server/src/bin.rs | 13 +++++++----- server/src/commands/upload.rs | 27 ++++++++++++++++++------ 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/docs/getting-started/creating-a-place.md b/docs/getting-started/creating-a-place.md index 1ff300ed..fb2b493f 100644 --- a/docs/getting-started/creating-a-place.md +++ b/docs/getting-started/creating-a-place.md @@ -60,5 +60,5 @@ You'll need an existing place on Roblox.com as well as the `.ROBLOSECURITY` cook Generating and uploading your place file is as simple as: ```sh -rojo upload --place_id [PLACE ID] --cookie "[SECURITY COOKIE]" +rojo upload --asset_id [PLACE ID] --cookie "[SECURITY COOKIE]" ``` \ No newline at end of file diff --git a/server/src/bin.rs b/server/src/bin.rs index 87520d5a..d57230d2 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -48,10 +48,11 @@ fn main() { ) (@subcommand upload => - (about: "Generates a place file out of the project and uploads it to Roblox.") + (about: "Generates a place or model file out of the project and uploads it to Roblox.") (@arg PROJECT: "Path to the project to upload. Defaults to the current directory.") + (@arg kind: --kind +takes_value "The kind of asset to generate, 'place', or 'model'. Defaults to place.") (@arg cookie: --cookie +takes_value +required "Security cookie to authenticate with.") - (@arg place_id: --place_id +takes_value +required "Place ID to upload to.") + (@arg asset_id: --asset_id +takes_value +required "Asset ID to upload to.") ) ); @@ -134,10 +135,11 @@ fn main() { None => std::env::current_dir().unwrap(), }; + let kind = sub_matches.value_of("kind"); let security_cookie = sub_matches.value_of("cookie").unwrap(); - let place_id: u64 = { - let arg = sub_matches.value_of("place_id").unwrap(); + let asset_id: u64 = { + let arg = sub_matches.value_of("asset_id").unwrap(); match arg.parse() { Ok(v) => v, @@ -151,7 +153,8 @@ fn main() { let options = commands::UploadOptions { fuzzy_project_path, security_cookie: security_cookie.to_string(), - place_id, + asset_id, + kind, }; match commands::upload(&options) { diff --git a/server/src/commands/upload.rs b/server/src/commands/upload.rs index 7ed1e649..1685275e 100644 --- a/server/src/commands/upload.rs +++ b/server/src/commands/upload.rs @@ -5,7 +5,7 @@ use std::{ use failure::Fail; -use reqwest::header::{USER_AGENT, CONTENT_TYPE, COOKIE}; +use reqwest::header::{ACCEPT, USER_AGENT, CONTENT_TYPE, COOKIE}; use crate::{ rbx_session::construct_oneoff_tree, @@ -18,6 +18,9 @@ pub enum UploadError { #[fail(display = "Roblox API Error: {}", _0)] RobloxApiError(String), + #[fail(display = "Invalid asset kind: {}", _0)] + InvalidKind(String), + #[fail(display = "Project load error: {}", _0)] ProjectLoadError(#[fail(cause)] ProjectLoadFuzzyError), @@ -47,14 +50,14 @@ impl From for UploadError { } #[derive(Debug)] -pub struct UploadOptions { +pub struct UploadOptions<'a> { pub fuzzy_project_path: PathBuf, pub security_cookie: String, - pub place_id: u64, + pub asset_id: u64, + pub kind: Option<&'a str>, } pub fn upload(options: &UploadOptions) -> Result<(), UploadError> { - // TODO: Support uploading models too // TODO: Switch to uploading binary format? info!("Looking for project at {}", options.fuzzy_project_path.display()); @@ -69,11 +72,20 @@ pub fn upload(options: &UploadOptions) -> Result<(), UploadError> { let tree = construct_oneoff_tree(&project, &imfs); let root_id = tree.get_root_id(); - let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); let mut contents = Vec::new(); - rbx_xml::encode(&tree, top_level_ids, &mut contents); - let url = format!("https://data.roblox.com/Data/Upload.ashx?json=1&type=Place&assetid={}", options.place_id); + match options.kind { + Some("place") | None => { + let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); + rbx_xml::encode(&tree, top_level_ids, &mut contents); + }, + Some("model") => { + rbx_xml::encode(&tree, &[root_id], &mut contents); + }, + Some(invalid) => return Err(UploadError::InvalidKind(invalid.to_owned())), + } + + let url = format!("https://data.roblox.com/Data/Upload.ashx?assetid={}", options.asset_id); let client = reqwest::Client::new(); let mut response = client.post(&url) @@ -81,6 +93,7 @@ pub fn upload(options: &UploadOptions) -> Result<(), UploadError> { .header(USER_AGENT, "Roblox/WinInet") .header("Requester", "Client") .header(CONTENT_TYPE, "application/xml") + .header(ACCEPT, "application/json") .body(contents) .send()?; From ed6d8415bd24c82ce06152f7fac3f6c48e89d5a3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 10 Jan 2019 15:29:38 -0800 Subject: [PATCH 0347/1504] Make plugin output less verbose --- plugin/src/Components/App.lua | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 5d097ef2..eebcfa29 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -85,13 +85,13 @@ function App:render() children = { ConnectPanel = e(ConnectPanel, { startSession = function(address, port) - Logging.info("Starting new session") + Logging.trace("Starting new session") self.currentSession = Session.new({ address = address, port = port, onError = function() - Logging.info("Session terminated") + Logging.trace("Session terminated") self.currentSession = nil self:setState({ @@ -105,7 +105,7 @@ function App:render() }) end, cancel = function() - Logging.info("Canceling session configuration") + Logging.trace("Canceling session configuration") self:setState({ sessionStatus = SessionStatus.Disconnected, @@ -132,17 +132,17 @@ function App:didMount() checkUpgrade(self.props.plugin) if self.state.sessionStatus == SessionStatus.Connected then - Logging.info("Disconnecting session") + Logging.trace("Disconnecting session") error("NYI") elseif self.state.sessionStatus == SessionStatus.Disconnected then - Logging.info("Starting session configuration") + Logging.trace("Starting session configuration") self:setState({ sessionStatus = SessionStatus.Configuring, }) elseif self.state.sessionStatus == SessionStatus.Configuring then - Logging.info("Canceling session configuration") + Logging.trace("Canceling session configuration") self:setState({ sessionStatus = SessionStatus.Disconnected, From 5bb70c2675ad34d7496c7531610d6bcd4fa162a1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 10 Jan 2019 15:32:50 -0800 Subject: [PATCH 0348/1504] Fix up plugin project naming --- plugin/roblox-package.json | 21 --------------- plugin/roblox-project.json | 47 +++++++++++---------------------- plugin/test-plugin-project.json | 38 ++++++++++++++++++++++++++ 3 files changed, 53 insertions(+), 53 deletions(-) delete mode 100644 plugin/roblox-package.json create mode 100644 plugin/test-plugin-project.json diff --git a/plugin/roblox-package.json b/plugin/roblox-package.json deleted file mode 100644 index 1d1ace9f..00000000 --- a/plugin/roblox-package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "Rojo", - "tree": { - "$className": "Folder", - "Plugin": { - "$path": "src" - }, - "Roact": { - "$path": "modules/roact/lib" - }, - "Rodux": { - "$path": "modules/rodux/lib" - }, - "RoactRodux": { - "$path": "modules/roact-rodux/lib" - }, - "Promise": { - "$path": "modules/promise/lib" - } - } -} \ No newline at end of file diff --git a/plugin/roblox-project.json b/plugin/roblox-project.json index ab8cf8d0..1d1ace9f 100644 --- a/plugin/roblox-project.json +++ b/plugin/roblox-project.json @@ -1,38 +1,21 @@ { - "name": "rojo", + "name": "Rojo", "tree": { - "$className": "DataModel", - - "ReplicatedStorage": { - "$className": "ReplicatedStorage", - "Rojo": { - "$className": "Folder", - "Plugin": { - "$path": "src" - }, - "Roact": { - "$path": "modules/roact/lib" - }, - "Rodux": { - "$path": "modules/rodux/lib" - }, - "RoactRodux": { - "$path": "modules/roact-rodux/lib" - }, - "Promise": { - "$path": "modules/promise/lib" - } - }, - "TestEZ": { - "$path": "modules/testez/lib" - } + "$className": "Folder", + "Plugin": { + "$path": "src" }, - - "TestService": { - "$className": "TestService", - "TestBootstrap": { - "$path": "testBootstrap.server.lua" - } + "Roact": { + "$path": "modules/roact/lib" + }, + "Rodux": { + "$path": "modules/rodux/lib" + }, + "RoactRodux": { + "$path": "modules/roact-rodux/lib" + }, + "Promise": { + "$path": "modules/promise/lib" } } } \ No newline at end of file diff --git a/plugin/test-plugin-project.json b/plugin/test-plugin-project.json new file mode 100644 index 00000000..ab8cf8d0 --- /dev/null +++ b/plugin/test-plugin-project.json @@ -0,0 +1,38 @@ +{ + "name": "rojo", + "tree": { + "$className": "DataModel", + + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + "Rojo": { + "$className": "Folder", + "Plugin": { + "$path": "src" + }, + "Roact": { + "$path": "modules/roact/lib" + }, + "Rodux": { + "$path": "modules/rodux/lib" + }, + "RoactRodux": { + "$path": "modules/roact-rodux/lib" + }, + "Promise": { + "$path": "modules/promise/lib" + } + }, + "TestEZ": { + "$path": "modules/testez/lib" + } + }, + + "TestService": { + "$className": "TestService", + "TestBootstrap": { + "$path": "testBootstrap.server.lua" + } + } + } +} \ No newline at end of file From 5f91a8fdfe4204db34e40a47cf68087e3efac951 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 10 Jan 2019 16:12:52 -0800 Subject: [PATCH 0349/1504] Fix bug where HTTP being disabled would cause stickiness --- plugin/src/ApiContext.lua | 2 +- plugin/src/Components/App.lua | 11 +++++++---- plugin/src/Http.lua | 2 +- plugin/src/HttpError.lua | 9 +-------- plugin/src/Session.lua | 6 +++++- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index aba7f53d..c16535d0 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -97,10 +97,10 @@ function ApiContext:connect() end self.serverId = body.serverId - self.connected = true self.partitionRoutes = body.partitions self.rootInstanceId = body.rootInstanceId self.instanceMetadataMap = body.instanceMetadataMap + self.connected = true end) end diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index eebcfa29..bf90b1cc 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -87,7 +87,7 @@ function App:render() startSession = function(address, port) Logging.trace("Starting new session") - self.currentSession = Session.new({ + local success, session = Session.new({ address = address, port = port, onError = function() @@ -100,9 +100,12 @@ function App:render() end }) - self:setState({ - sessionStatus = SessionStatus.Connected, - }) + if success then + self.currentSession = session + self:setState({ + sessionStatus = SessionStatus.Connected, + }) + end end, cancel = function() Logging.trace("Canceling session configuration") diff --git a/plugin/src/Http.lua b/plugin/src/Http.lua index eda12b05..03b26658 100644 --- a/plugin/src/Http.lua +++ b/plugin/src/Http.lua @@ -72,4 +72,4 @@ function Http.jsonDecode(source) return HttpService:JSONDecode(source) end -return Http +return Http \ No newline at end of file diff --git a/plugin/src/HttpError.lua b/plugin/src/HttpError.lua index f1b06fc2..e1ef9b7a 100644 --- a/plugin/src/HttpError.lua +++ b/plugin/src/HttpError.lua @@ -1,6 +1,3 @@ -local Selection = game:GetService("Selection") -local HttpService = game:GetService("HttpService") - local Logging = require(script.Parent.Logging) local HttpError = {} @@ -70,10 +67,6 @@ end function HttpError:report() Logging.warn(self.message) - - if self.type == HttpError.Error.HttpNotEnabled then - Selection:Set(HttpService) - end end -return HttpError +return HttpError \ No newline at end of file diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index fd086ff7..5e1d15df 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -10,6 +10,8 @@ function Session.new(config) self.onError = config.onError + local hasErrors = false + local reconciler local remoteUrl = ("http://%s:%s"):format(config.address, config.port) @@ -36,6 +38,7 @@ function Session.new(config) return reconciler:applyUpdate(requestedIds, response.instances) end) :catch(function(message) + hasErrors = true Logging.warn("%s", tostring(message)) self.onError() end) @@ -52,11 +55,12 @@ function Session.new(config) return api:retrieveMessages() end) :catch(function(message) + hasErrors = true Logging.warn("%s", tostring(message)) self.onError() end) - return setmetatable(self, Session) + return not hasErrors, setmetatable(self, Session) end return Session \ No newline at end of file From 1e1b409f8b519e0e3a91e753c7591bda8560543a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 10 Jan 2019 16:56:43 -0800 Subject: [PATCH 0350/1504] Add support for StringValue instances Closes #93. --- server/src/rbx_session.rs | 9 +++++++++ test-projects/single-sync-point/lib/foo.txt | 1 + 2 files changed, 10 insertions(+) create mode 100644 test-projects/single-sync-point/lib/foo.txt diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 51ef4b15..470515cc 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -233,6 +233,7 @@ enum FileType { ModuleScript, ServerScript, ClientScript, + StringValue, LocalizationTable, } @@ -256,6 +257,8 @@ fn classify_file(file: &ImfsFile) -> Option<(&str, FileType)> { Some((instance_name, FileType::ModuleScript)) } else if let Some(instance_name) = get_trailing(file_name, ".csv") { Some((instance_name, FileType::LocalizationTable)) + } else if let Some(instance_name) = get_trailing(file_name, ".txt") { + Some((instance_name, FileType::StringValue)) } else { None } @@ -339,6 +342,7 @@ fn snapshot_instances_from_imfs<'a>( FileType::ModuleScript => "ModuleScript", FileType::ServerScript => "Script", FileType::ClientScript => "LocalScript", + FileType::StringValue => "StringValue", FileType::LocalizationTable => "LocalizationTable", }; @@ -356,6 +360,11 @@ fn snapshot_instances_from_imfs<'a>( value: contents.to_string(), }); }, + FileType::StringValue => { + properties.insert(String::from("Value"), RbxValue::String { + value: contents.to_string(), + }); + }, FileType::LocalizationTable => { let entries: Vec = csv::Reader::from_reader(contents.as_bytes()) .deserialize() diff --git a/test-projects/single-sync-point/lib/foo.txt b/test-projects/single-sync-point/lib/foo.txt new file mode 100644 index 00000000..18d0c8b1 --- /dev/null +++ b/test-projects/single-sync-point/lib/foo.txt @@ -0,0 +1 @@ +Hello world, from foo.txt \ No newline at end of file From 7b84fce737b559034962a676074b3993d53ee114 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 10 Jan 2019 16:57:44 -0800 Subject: [PATCH 0351/1504] Fix syncing projects that mention properties with elevated permissions. Permission errors aren't reported since I'm not sure what the user could do about them. Some properties can be set in the model format but not in live-sync mode, like HttpEnabled. --- plugin/src/Reconciler.lua | 25 ++++++++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index db0728e2..df925325 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -67,15 +67,34 @@ local function setProperty(instance, key, value) return end - local ok, err = pcall(function() - if instance[key] ~= value then + -- If we don't have permissions to access this value at all, we can skip it. + local readSuccess, existingValue = pcall(function() + return instance[key] + end) + + if not readSuccess then + -- An error will be thrown if there was a permission issue or if the + -- property doesn't exist. In the latter case, we should tell the user + -- because it's probably their fault. + if existingValue:find("lacking permission") then + Logging.trace("Permission error reading property %s on class %s", tostring(key), instance.ClassName) + return + else + error(("Invalid property %s on class %s: %s"):format(tostring(key), instance.ClassName, existingValue), 2) + end + end + + local writeSuccess, err = pcall(function() + if existingValue ~= value then instance[key] = value end end) - if not ok then + if not writeSuccess then error(("Cannot set property %s on class %s: %s"):format(tostring(key), instance.ClassName, err), 2) end + + return true end local Reconciler = {} From 0a2810a98b156146f570e8a35026853856c15d00 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 10 Jan 2019 17:48:19 -0800 Subject: [PATCH 0352/1504] Scaffold out model file support, still needs working decoders --- server/src/rbx_session.rs | 115 +++++++++++++++--- server/src/rbx_snapshot.rs | 18 +++ .../composing-models/roblox-project.json | 6 + .../composing-models/src/Binary.rbxm | Bin 0 -> 576 bytes test-projects/composing-models/src/XML.rbxmx | 16 +++ 5 files changed, 141 insertions(+), 14 deletions(-) create mode 100644 test-projects/composing-models/roblox-project.json create mode 100644 test-projects/composing-models/src/Binary.rbxm create mode 100644 test-projects/composing-models/src/XML.rbxmx diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 470515cc..13342379 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -9,14 +9,14 @@ use std::{ use failure::Fail; -use rbx_tree::{RbxTree, RbxValue, RbxId}; +use rbx_tree::{RbxTree, RbxInstance, RbxValue, RbxId}; use crate::{ project::{Project, ProjectNode, InstanceProjectNodeMetadata}, message_queue::MessageQueue, imfs::{Imfs, ImfsItem, ImfsFile}, path_map::PathMap, - rbx_snapshot::{RbxSnapshotInstance, InstanceChanges, reify_root, reconcile_subtree}, + rbx_snapshot::{RbxSnapshotInstance, InstanceChanges, snapshot_from_tree, reify_root, reconcile_subtree}, }; const INIT_SCRIPT: &str = "init.lua"; @@ -235,6 +235,8 @@ enum FileType { ClientScript, StringValue, LocalizationTable, + XmlModel, + BinaryModel, } fn get_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { @@ -247,21 +249,25 @@ fn get_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { } fn classify_file(file: &ImfsFile) -> Option<(&str, FileType)> { + static EXTENSIONS_TO_TYPES: &[(&str, FileType)] = &[ + (".server.lua", FileType::ServerScript), + (".client.lua", FileType::ClientScript), + (".lua", FileType::ModuleScript), + (".csv", FileType::LocalizationTable), + (".txt", FileType::StringValue), + (".rbxmx", FileType::XmlModel), + (".rbxm", FileType::BinaryModel), + ]; + let file_name = file.path.file_name()?.to_str()?; - if let Some(instance_name) = get_trailing(file_name, ".server.lua") { - Some((instance_name, FileType::ServerScript)) - } else if let Some(instance_name) = get_trailing(file_name, ".client.lua") { - Some((instance_name, FileType::ClientScript)) - } else if let Some(instance_name) = get_trailing(file_name, ".lua") { - Some((instance_name, FileType::ModuleScript)) - } else if let Some(instance_name) = get_trailing(file_name, ".csv") { - Some((instance_name, FileType::LocalizationTable)) - } else if let Some(instance_name) = get_trailing(file_name, ".txt") { - Some((instance_name, FileType::StringValue)) - } else { - None + for (extension, file_type) in EXTENSIONS_TO_TYPES { + if let Some(instance_name) = get_trailing(file_name, extension) { + return Some((instance_name, *file_type)) + } } + + None } #[derive(Debug, Serialize, Deserialize)] @@ -307,6 +313,16 @@ enum SnapshotError { inner: str::Utf8Error, path: PathBuf, }, + + XmlModelDecodeError { + inner: rbx_xml::DecodeError, + path: PathBuf, + }, + + BinaryModelDecodeError { + inner: rbx_binary::DecodeError, + path: PathBuf, + }, } impl fmt::Display for SnapshotError { @@ -316,10 +332,78 @@ impl fmt::Display for SnapshotError { SnapshotError::Utf8Error { inner, path } => { write!(output, "Invalid UTF-8: {} in path {}", inner, path.display()) }, + SnapshotError::XmlModelDecodeError { inner, path } => { + write!(output, "Malformed rbxmx model: {:?} in path {}", inner, path.display()) + }, + SnapshotError::BinaryModelDecodeError { inner, path } => { + write!(output, "Malformed rbxm model: {:?} in path {}", inner, path.display()) + }, } } } +fn snapshot_xml_model<'a>( + instance_name: Cow<'a, str>, + file: &ImfsFile, +) -> Result>, SnapshotError> { + let mut temp_tree = RbxTree::new(RbxInstance { + name: "Temp".to_owned(), + class_name: "Folder".to_owned(), + properties: HashMap::new(), + }); + + let root_id = temp_tree.get_root_id(); + rbx_xml::decode(&mut temp_tree, root_id, file.contents.as_slice()) + .map_err(|inner| SnapshotError::XmlModelDecodeError { + inner, + path: file.path.clone(), + })?; + + let root_instance = temp_tree.get_instance(root_id).unwrap(); + let children = root_instance.get_children_ids(); + + match children.len() { + 0 => Ok(None), + 1 => { + let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); + snapshot.name = instance_name; + Ok(Some(snapshot)) + }, + _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), + } +} + +fn snapshot_binary_model<'a>( + instance_name: Cow<'a, str>, + file: &ImfsFile, +) -> Result>, SnapshotError> { + let mut temp_tree = RbxTree::new(RbxInstance { + name: "Temp".to_owned(), + class_name: "Folder".to_owned(), + properties: HashMap::new(), + }); + + let root_id = temp_tree.get_root_id(); + rbx_binary::decode(&mut temp_tree, root_id, file.contents.as_slice()) + .map_err(|inner| SnapshotError::BinaryModelDecodeError { + inner, + path: file.path.clone(), + })?; + + let root_instance = temp_tree.get_instance(root_id).unwrap(); + let children = root_instance.get_children_ids(); + + match children.len() { + 0 => Ok(None), + 1 => { + let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); + snapshot.name = instance_name; + Ok(Some(snapshot)) + }, + _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), + } +} + fn snapshot_instances_from_imfs<'a>( imfs: &'a Imfs, imfs_path: &Path, @@ -344,6 +428,8 @@ fn snapshot_instances_from_imfs<'a>( FileType::ClientScript => "LocalScript", FileType::StringValue => "StringValue", FileType::LocalizationTable => "LocalizationTable", + FileType::XmlModel => return snapshot_xml_model(instance_name, file), + FileType::BinaryModel => return snapshot_binary_model(instance_name, file), }; let contents = str::from_utf8(&file.contents) @@ -379,6 +465,7 @@ fn snapshot_instances_from_imfs<'a>( value: table_contents, }); }, + FileType::XmlModel | FileType::BinaryModel => unreachable!(), } Ok(Some(RbxSnapshotInstance { diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 554a20f6..4ffac64a 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -65,6 +65,24 @@ pub struct RbxSnapshotInstance<'a> { pub metadata: Option, } +pub fn snapshot_from_tree(tree: &RbxTree, id: RbxId) -> Option> { + let instance = tree.get_instance(id)?; + + let mut children = Vec::new(); + for &child_id in instance.get_children_ids() { + children.push(snapshot_from_tree(tree, child_id)?); + } + + Some(RbxSnapshotInstance { + name: Cow::Owned(instance.name.to_owned()), + class_name: Cow::Owned(instance.class_name.to_owned()), + properties: instance.properties.clone(), + children, + source_path: None, + metadata: None, + }) +} + pub fn reify_root( snapshot: &RbxSnapshotInstance, path_map: &mut PathMap, diff --git a/test-projects/composing-models/roblox-project.json b/test-projects/composing-models/roblox-project.json new file mode 100644 index 00000000..440d72bd --- /dev/null +++ b/test-projects/composing-models/roblox-project.json @@ -0,0 +1,6 @@ +{ + "name": "composing-models", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/test-projects/composing-models/src/Binary.rbxm b/test-projects/composing-models/src/Binary.rbxm new file mode 100644 index 0000000000000000000000000000000000000000..d163ae7d4afe54b609e4b9a68b8113d3e111fc53 GIT binary patch literal 576 zcmZXSdrHGV5XO_@Gd@6zud3LJ`d<`lOdDvGXj329SWGSulSLM{*|JTbPVUqQOkAb`ZBKuIptD-V3 zKmCQqpCs~lDnc?tcLCX!AfSs_o}D}o$s=KmW6N7enmKol9E??&Jmn#!k$MK{$g=Ee zt$Nqe&3e718};h7ZW(Puui1{>wl7WFGOxzi&IH;3qq0+Mhl8BntpXwAVZh2gIk0lG xJQ{17AW16XX-)e-iv03_M&bH6sVy+dfd4>Mz6%JVRL5<}0B4M9TulC(n_ob}U~B*Y literal 0 HcmV?d00001 diff --git a/test-projects/composing-models/src/XML.rbxmx b/test-projects/composing-models/src/XML.rbxmx new file mode 100644 index 00000000..67e8b820 --- /dev/null +++ b/test-projects/composing-models/src/XML.rbxmx @@ -0,0 +1,16 @@ + + true + null + nil + + + false + + Lone Script + {C62CD9FB-FF28-4FD9-9712-AD28A1E92C84} + + + + + \ No newline at end of file From 14e1829164361affcb1d39e8d59bc28c4e43ebbd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 10 Jan 2019 18:31:43 -0800 Subject: [PATCH 0353/1504] Upgrade dependencies, which makes some rbxm models now work --- Cargo.lock | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1a37b901..4f5f8835 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -476,7 +476,7 @@ dependencies = [ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1166,7 +1166,7 @@ dependencies = [ [[package]] name = "rbx_binary" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#34794a857f8654167b219e229937853388aef822" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#f20378979f555e7e090bc62eb82afe7274a32ed4" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1177,7 +1177,7 @@ dependencies = [ [[package]] name = "rbx_tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#34794a857f8654167b219e229937853388aef822" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#f20378979f555e7e090bc62eb82afe7274a32ed4" dependencies = [ "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1187,7 +1187,7 @@ dependencies = [ [[package]] name = "rbx_xml" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#34794a857f8654167b219e229937853388aef822" +source = "git+https://github.com/LPGhatguy/rbx-tree.git#f20378979f555e7e090bc62eb82afe7274a32ed4" dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", @@ -1245,7 +1245,7 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.6" +version = "0.9.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1299,7 +1299,7 @@ dependencies = [ "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1514,7 +1514,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "string" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2189,7 +2189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4286c88f8769db1f4280b494efe7a8c64df6c1f8faa29faf9f0862075cb69a58" +"checksum reqwest 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "519ae6326d2e2863bd9e03cf5bd57758a330076a4b2be42eb00cea9a35f4084a" "checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" "checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" @@ -2215,7 +2215,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum string 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "98998cced76115b1da46f63388b909d118a37ae0be0f82ad35773d4a4bc9d18d" +"checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" "checksum syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)" = "734ecc29cd36e8123850d9bf21dfd62ef8300aaa8f879aabaa899721808be37c" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" From 5ad830a6d7a3b9469b6cd3f2e7c01ea1631b22ab Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 11 Jan 2019 11:57:15 -0800 Subject: [PATCH 0354/1504] Set up icons, make UI a little more resiliant --- plugin/src/Components/App.lua | 68 +++++++++++++++++++------- plugin/src/Components/ConnectPanel.lua | 2 +- plugin/src/Icons.lua | 13 +++++ 3 files changed, 64 insertions(+), 19 deletions(-) create mode 100644 plugin/src/Icons.lua diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index bf90b1cc..53b4ee51 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -1,13 +1,16 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) -local Session = require(script.Parent.Parent.Session) -local Config = require(script.Parent.Parent.Config) -local Version = require(script.Parent.Parent.Version) -local Logging = require(script.Parent.Parent.Logging) -local DevSettings = require(script.Parent.Parent.DevSettings) +local Plugin = script:FindFirstAncestor("Plugin") -local ConnectPanel = require(script.Parent.ConnectPanel) -local ConnectionActivePanel = require(script.Parent.ConnectionActivePanel) +local Icons = require(Plugin.Icons) +local Session = require(Plugin.Session) +local Config = require(Plugin.Config) +local Version = require(Plugin.Version) +local Logging = require(Plugin.Logging) +local DevSettings = require(Plugin.DevSettings) + +local ConnectPanel = require(Plugin.Components.ConnectPanel) +local ConnectionActivePanel = require(Plugin.Components.ConnectionActivePanel) local e = Roact.createElement @@ -50,7 +53,7 @@ end local SessionStatus = { Disconnected = "Disconnected", Connected = "Connected", - Configuring = "Configuring", + ConfiguringSession = "ConfiguringSession", -- TODO: Error? } @@ -67,6 +70,8 @@ function App:init() sessionStatus = SessionStatus.Disconnected, }) + self.connectButton = nil + self.configButton = nil self.currentSession = nil self.displayedVersion = DevSettings:isEnabled() @@ -81,7 +86,7 @@ function App:render() children = { ConnectionActivePanel = e(ConnectionActivePanel), } - elseif self.state.sessionStatus == SessionStatus.Configuring then + elseif self.state.sessionStatus == SessionStatus.ConfiguringSession then children = { ConnectPanel = e(ConnectPanel, { startSession = function(address, port) @@ -126,25 +131,30 @@ function App:didMount() local toolbar = self.props.plugin:CreateToolbar("Rojo " .. self.displayedVersion) - -- TODO: Icon! - local connectButton = toolbar:CreateButton("Connect", "Connect to Rojo Session", "") - connectButton.ClickableWhenViewportHidden = true - - connectButton.Click:Connect(function() - connectButton:SetActive(false) + self.connectButton = toolbar:CreateButton( + "Connect", + "Connect to a running Rojo session", + Icons.StartSession) + self.connectButton.ClickableWhenViewportHidden = false + self.connectButton.Click:Connect(function() checkUpgrade(self.props.plugin) if self.state.sessionStatus == SessionStatus.Connected then Logging.trace("Disconnecting session") - error("NYI") + self.currentSession = nil + self:setState({ + sessionStatus = SessionStatus.Disconnected, + }) + + error("TODO: Actually disconnect old session") elseif self.state.sessionStatus == SessionStatus.Disconnected then Logging.trace("Starting session configuration") self:setState({ - sessionStatus = SessionStatus.Configuring, + sessionStatus = SessionStatus.ConfiguringSession, }) - elseif self.state.sessionStatus == SessionStatus.Configuring then + elseif self.state.sessionStatus == SessionStatus.ConfiguringSession then Logging.trace("Canceling session configuration") self:setState({ @@ -152,6 +162,28 @@ function App:didMount() }) end end) + + self.configButton = toolbar:CreateButton( + "Configure", + "Configure the Rojo plugin", + Icons.Configure) + self.configButton.ClickableWhenViewportHidden = false + self.configButton.Click:Connect(function() + self.configButton:SetActive(false) + end) +end + +function App:didUpdate() + local connectActive = self.state.sessionStatus == SessionStatus.ConfiguringSession + or self.state.sessionStatus == SessionStatus.Connected + + self.connectButton:SetActive(connectActive) + + if self.state.sessionStatus == SessionStatus.Connected then + self.connectButton.Icon = Icons.SessionActive + else + self.connectButton.Icon = Icons.StartSession + end end return App \ No newline at end of file diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index 5de9b10e..d4d6e2eb 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -51,7 +51,7 @@ function ConnectPanel:render() LayoutOrder = 1, Font = Enum.Font.SourceSans, TextSize = 22, - Text = "Start Rojo Session", + Text = "Start New Rojo Session", Size = UDim2.new(1, 0, 0, 28), BackgroundTransparency = 1, TextColor3 = Color3.new(1, 1, 1), diff --git a/plugin/src/Icons.lua b/plugin/src/Icons.lua new file mode 100644 index 00000000..ef631416 --- /dev/null +++ b/plugin/src/Icons.lua @@ -0,0 +1,13 @@ +local Icons = { + StartSession = "", + SessionActive = "", + Configure = "", +} + +setmetatable(Icons, { + __index = function(_, key) + error(("%q is not a valid member of Icons"):format(tostring(key)), 2) + end +}) + +return Icons \ No newline at end of file From d81eaa6c1372d9bd67d115c95aed013c5631ef25 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 11 Jan 2019 14:10:02 -0800 Subject: [PATCH 0355/1504] Revamp UI using Kenney UI assets --- assets/kenney-ui-gray-sheet.png | Bin 0 -> 12953 bytes assets/kenney-ui-gray-sheet.xml | 41 +++++ plugin/src/Assets.lua | 52 +++++++ plugin/src/Components/App.lua | 15 +- plugin/src/Components/ConnectPanel.lua | 146 +++++++++++------- .../src/Components/ConnectionActivePanel.lua | 38 +++-- plugin/src/Components/FitList.lua | 3 +- plugin/src/Components/FitText.lua | 2 +- plugin/src/Components/FormButton.lua | 49 ++++++ plugin/src/Icons.lua | 13 -- 10 files changed, 270 insertions(+), 89 deletions(-) create mode 100644 assets/kenney-ui-gray-sheet.png create mode 100644 assets/kenney-ui-gray-sheet.xml create mode 100644 plugin/src/Assets.lua create mode 100644 plugin/src/Components/FormButton.lua delete mode 100644 plugin/src/Icons.lua diff --git a/assets/kenney-ui-gray-sheet.png b/assets/kenney-ui-gray-sheet.png new file mode 100644 index 0000000000000000000000000000000000000000..1ebbd975d33283c59cdbe7257a74d02855334d77 GIT binary patch literal 12953 zcmbVz2Ut_f*7hU>m7*Xbpnw#q3P@8riAo1)Dkw-15k#a3Qbb5NSSV5~2ueK^(W8P& zuR*1F1OiBtj-V6?M5L3D{IfyNckj9Pe*gV{pND5Bd(W(yJ+s!k-t|t5G&j}X%DS5s z0I=22K*tgQH2jDLTQrrkt6c%qCpOYBMbckKDnBXZ|^NL&}zb`|H1D|H7HHSu&>>brOEIO5{s68W*# zqE|97*^B)b`-Jpt8M+)+*4E=)U0poL6UJ&c@mr9wdU2NzDPi^?NaEDj*XK=OY2s=d z(;#lPxc%dl%x3Y}3X^XzSXVpjf%7N>RS7fKj)MrjKJ8ZUM0l__Zr*R0`2cqB==b z*X&|TTk&y?xI;s`nJ;Y9(nr}iI2`!$^)}i3>f%8fZLX!vY}~zdKhutp@84hUcBm#Y z)+p0Tdzp`ZNKyW{)1&&};g^pv!gtTRy5`bpD|7wgu~T2ZWIqGh-JEp?LnSGOTsS~r zxu+gK!AV>miFVn%tNZKjR3{~zp%qGbhlfUQ;BIDvc`kw`597Z5UeMERjzP(z!5175 z4Gs?egW2d<;jAetaCLst_B=OXbab@;7659TgabsH<&_!}`TctV2Gq3f1pp-sKMBLD z)Jq^BDEL)-8sH}VLv0=CqgW*%Oc z>MrB>)pX-Z+6Smq>fi5fLHrdlB&7VW z(Jw11lBxgN<;T~?zjtxnNk~mi{rg?aFGJr)>Z1St5O$fKp8osY^)8QvL6MDYVjVWt zoevc;)EJDc4B;s&F2~Z1CnG#O{7BUU)j`!6RXVBrWl2fm)QC_+_sZ`14{&uP_JKGd ztS8U!&CSh!HQVsEv#8}CjR%qiN9gqGZv@L79-6(YL-fUxF-CeyO2k;GS>5`#C8g&#R!~O>DY2=|j9$LNEIETWP<@(EfbLrnd zzhjiA*%n=voEtQ?iig#aC~v0wN_eABsg9O5&hG{$No#9sWzdb!=b+9@^ad6#*bjv#t9X%A zqAZGpbqjVk*w%Lg$G3ARrz0o);uVzCUvPpby^F*b#k8~Kq@kG3&d#!;qN2L`mIQ-6 zk{@!;xeJb;+2z1Q5NKioM(SViuL=hA750tXEmNIQtl9+BO6fwzSxz_S*HOkq;GU>N z(a?p)9)6OJt=V+7<&qa?m$)qPE5W~cDymH2CS4Pvv*F?WH zqR%E9>5s8Nk%hkY0{C6_;r4t-8sezz70p_=kiuoWQziGz?f=Kn6`>;U}V%656_M^G>aCNm7RXl&DFr)AlTq=vpa)#(_8}y^F@UckiA};ac$0Owq01ONxtGXKhAQ+Z8qf_ePks zPhemvm%|4y;#zT!VJKs5Y2PLz-NMNWeQovO7v|a)Dg9-~@yp*on7X#oU_h<26{RHYBCj`5SlhMFB4)cBNmHm#f3&DgLxv#w9)S-02Q! zoo3jH5BC%<6D>b%`jgpmE&ABsk za&kDsR|{NQ9=!=Ppm*P!NeyYVUv7iJ4iWHzfrG3rjx9EhRQ z%@5^g(EIEZ3!NHWve zLO?<+f)gOAol^uHfzc^^1YC!aiMtM#H8&cqN1e__g#8zn>u?-2G`j`WI>Q1-@w@() z#VyFJw)|I9(dO8g?>bm)NB?)1`QbnBNfu3Ta%|i7$l*PV*2#?Q6Fq%>?#0s=M%%jh zJ*th6n4Ww7;)SeUZYd1a%^yq(XD>{}93q-*Jju%=<(zGU&rhOrMwgdMd)Dcn8GJ}+ zk|G%N?11T36QT;Bd&$+@^6@xvCtgva*FVSdq1kjQd~@*780F*N0X@|M28H2tS!eM$ zvUI~-gi;KGPx2MDFE4x(P&styTSY}hGdM3?G=2f5V*O-E2vy#T#A2&gXi$K&Vd3;h zg9aVPBDeX3gxEnk=O~Fo17S!5Ul33m8wq!9116D`g=>xM9Nb@IA7NKySK)&HGj}2Y z*Z`p5AJSoin62*@z!3iR5&CD7^(zk8kf*03?@J&p`7D8-xn;f6(RCZb@YV)gi-18% zWN^Xz|G};PHzxon;SEp3{I3_tJu|GHO=f3vM;0UdMv&7C`jO2eIP&JrVL>USw)(6W zD!tbd;4B=+PTShr-Zu5|^*#QRE>*RSC9=SUaY;kig0f6`QBjUjhM$0tkV>Eb#qqW= z?yC{IX z!5K7XBAgZ+Bax5iSn6nfy>M*FG!Y$YZb{mD!9K zY|?BK$;;0t`qUQ|6lC4IYbn-y*#>)FYOv#le1vMIX?P zQYSuWe@W@3HVENqXSvfMzO7Dm=i3P(kkt?@lz#Xc&s8S~4JJB3?o8=-tI?){ATvTm z0HrHkEBNs~vxva_Q7yA~jM>u@k&WDI$|j4M*Y@?xk9&FZ?J5rCzl19%%FIKM`r`BW(HQIP zzy}qV0{NkbODBOsRy_4J&cr5oe!`;4=EWh&S63Q)du`U}Yt)6hy1L>mweM?kj1vdj z+M#ocszD=NJ~8S$ze`PE*XG;b8}~cK1Y2Qbt}sE+ySxwdoJ8SQ+tUZ7Xs_N`XEbhwngE zAT60ud-o08>sRB%A&7@&tbTh15Sv%gt(sJ`#xH_=j7xsn5p^aJ!i!1ex0(ytyiZm^^}R zm8!IU-AKQBj23;C(cV8RCzjE@2NgMAA-6uu9dMReSdEnf{y(M`DXVsKLihR9CKi+2 zPCGtgUvASEYMzWl#`|*%&bM)>aQ*C3XRgUefEWqC{`u!V!l%^y zz6V6t?SxO{+`d-=d-m8c!^{<7;wD5G69ngk7@-wlTLqJ2$#tAxaFgG;j8fDc4JI^P z>K)vKQ&$tKIB+QmOXag>mna$+XA!R7zcA~R{rg-f__Y|`lOJ;eGQj~kxnf3MpFMEH z5-bj3zMZ5M1OsPJw#p~GXy{)O!Acnk;87 zo>}Kt3+bvx`DFGv*N}3;2K1Pmx{3AyC~^udkwoX^;n{Z;(p;SLTXei2vw;fpw*c#! z0x{XOXp5VrJC3!wjMz9A%=6JS!2}T7+O;S7EG&Jv2O7!}1!dmxg;fm+bjZb$~WVb%IdgkF4VT@L| zjcxL+Ghx8mZ;==?BD9yy?PK}~hp>ufD6OG*A$%7 z56u|vMO(C-b)`$tr0L*tL#jr=Hx41~O98Q>=S>S2F3g2j^IE**cb&F=?Y?#{ z6nC2yMv$jr_lnXD;>D*zg#M2c9T(d~v;)6qq>V8}+?Q=D&Wh2ujXQ)TFYVP4wqnWN z9(IAY<%M+o>69Uho zuHP^GZk-jAyST@7+#=)Lh`oO^BWQbE5QDx}i19wn!6aPr91@!skk%Xu&C`K(uA*4c zxK*F0S(CBr#5*~P#@1J2@>+3wHsRzVNfxi-Pa702JO{Vk*~l1}3vKr$e7LqwSsvM@ zxlrskaX;)x%kpr2fFbSpnZ^83wKCJ2_#k5eNkN%M&p0?(3(D`vwpeEte*N2EiG&2* zdQ!x}xP^cJsk+;sFp!(TzUyq}|MC$-0ElIjFl02i=&CBMJ0G*t0hvrzW?TyhSn7|$ zYg%!}9Rq;d2#~0k44fZLN&xG;Gb=+g$DGTfToDIszL_Y!3%gGKeVVAC;V(ybps&mlvjBOIdnM!I}{_jk-kX ze%5(WX?EyE4q+!3$awj0;+Q5?hYgM%mMfu)qd?T3{}Qyh(sVaT9PG?3BP-jPdGy-% z;lonRzGd=YA*iTpZGv8sBB7u_Fgq9L3@fxx}!H0;+RSvVn;3dzBmrMKUsa%}c(V@El+!!5e zPM(V)z52tzz>p1puy;9#2ainT-$q`V24%zy4Y(go2<&8gctgh)yYc<5QI2A|dP7W1 z%<9aHrxI?L!L(Yhzl-584Qj2tEd|R<_Xvm&5;W7+tjXwz)4f~ed$0AjGkOYK$E|1@ z;*L;i4xs?pqJO*K$m;6VihHz`@pN6IL{bIn@mtM2TSrMqn9s1`$_2gs?n_Eaisl&K zMMBLEBWx~{eOm#3WWo$DFQ3Zx69F*xka`Z1izDki-yEy1&LwRJ%Latq!;n^I9{&E_ z{NFcKRptEWrouDM5|+jPW6qDY2CAS2lScr|x?7M4{y7{bqq?L-(z5)Yn!^02W5f%m z2dh_Hg*=5!?r6}}JcMXM2tR}6UI_P%6$IVMJG|{{&()u6@U2DS`HMa94+wxuV2WBE z4(A9hdHM2XDyg+0;qUQWNu8-69@~o=HPH0e)YnW*+k~589{$>x2-k=g6loTqbRDDn#Wh~h+v`2SDTIqz^jHhnjOuQ=1EHyLty~U4TJE0 zIDRgGXpxzSpo6F(#5?%XtYRRwj+lt?+fP5u0vFF{FX-#*Tc2wZr6}6rE+MpzC=TWj zz5E!k;c(&i9ILI=>6)!_rzcB`D>CTN>TCitu zFzq*y9HYWXVMLX^Fqb+MepW1_V7;M>hlhundL5Ly)y-Wp*K^>|iWZ;p=lpK2!)O@C zNCf;XL31C+PX)Z&T_cremCi!lC^yt@w>P>1+>xJ*;X?uQn+1%hoggVE0kn-(*ln7yqE#3Y)Zn@t_KTRB znwmEKF`ka+k+!=!jp4gdY0+=Jx|8u7Q%iw#F+&+0UyP28eeL7F*RouUWukbe_XFcZ zxvDvY$)0bgP>%v|{|K;omkf7?7>vRoj>>@bTjz=Q8tuy!b!@zHmAbHv6^MSq`wf!ZS4>Mm8NT1u=34wUVnN$q83#m zp?DHRTlOh9-rwKEi*&3TUc$ z4W@Yc#h%nXVq~-YtgXI<8Vo~>`$30KWRoSbyBU02Q1I-rdze7dI{KpaF zHBe7FFS6dcFWLt21^E4L`BYh>7M_s)l@BP%9RJ`9;>xZGTiWYA|SL=XSR5BRAN12fuZ8&0ReMc<09&m zg@pwb(oCjr(`f3zNa<_Wx}LKWWcOvr8-3Fc=l^ctOnDhF-CMLG)xS$dzRm;>(5n^I5;@yscp^KGN9gPPfA%E|4|BrdC{EQ z@W3)v%hloNc8p`IyVM^b+nwwdu?Cal4tHKRKdGDj?YC(g|L@1L_D^07ZYpn?@|g^QA%u3s2#5A0~d3+2( z?+)Q`T{-~5019lSJ;sAa!4Kk&VR!U5!n$=%LRD2&zbhX~>g{ZzA-LJ|#Wkt< zHw1X$>cgYkW%dtZART&|dBGah5VyfLABzE4e|~^-_t698vI|oZD7~N7jTAR$45>pt zmBjS(ZGJlm@U&5(TfJW-;TCl7gBu{c`R5No2sAH@a^xr)8O=x@9tY+X?)V~% zdf(^+g#cB3RN%^w^E1b-P^TbQ(g_P*B%ijem$+hL_nlrPVLSbeuQ$Ucq@Srn-o zKsl<y?z2%JrNi*9xA7i*HL5mJW}{nt`SaTwCF*@w*C$=0#!?f_ zd*E`qA{&nLhFq$TnPPZe{x2W5+=3I$t7>=|pgy-pe|MZ+3|iwu(E99TM`w6PpKE+giE@|KvgiI02Yvq?LR)?J3`I669B_%N*wE#@3}BTa3^(8?_oy3t zk$#)@F^gFI4zBI4)46l$>O;xA@mgafcm{VcUFq0&V}4pnw-g52IKBmUsrv2``(AMG)045n zCcW;PeCNp(%0+H27|sz6d~$8sI{-4zudoTeFM z8BL-N4`+l(R%!Awpp%aI)X&!YsKgR?|5<%=IThaAlm9uU1v#}pT9{iZm-e71N8JC_ zlzri|Ld=g!F)^({MEx(RT4tQMJ$mYD5tS@emrkG0Rbho9Qe_@l!F7j*TD|Y%W1(CQ zAqyv|WuunY2bpns>xWF+uKD^FnBS0$Rf(r4imch{V-24}=~k?M?sIORu!csQuJf)zGpBkV zV#M^cKN{d{RaI5Z03$$9q?C)F|VzyB~NFyOug1Am*M2P zD^|mbf?^}A`h*^D{3amBawUJNV%Aj`zg3qm;B+D64ElQq*1NjCS2tm@ZN z?%7m#N~uzW_Uy6R?V397Z}q9SGw&nCL@8?S>+ZF7%i2RlB@br135b1L*pUnkphb3;jF^+oa%y<+bGy6FLyiT)Z%YFc(nX18hJC>H_w z)sa??tR6G`t>mqpgvXWHUqeUjXLet{BfUnxpXw2CIu1~ zUm3tMuPwp8MJNlsbvs{~YHf_m>U4q-b8fP*-#vn79dxL>4ee7KHew&_*s)hI}2PQqpwcTcxBzmL~O4y*SFE|JErh6-yt39le{TEruvd zcQNz(>61-Y;CW`nL-1vEdCpun7T9(RhO`R^*$BoaHvIE>~ zOC(51#E>bJmV>MzMZT9EX!yl)ybA15(g=h?=G)G&+XZav=GgZswE=5@-UM~k+hluc zY9x{WB*^r36;iTo8g(t1qNl!N3|L|Ob`X@ql#kJqzYJpF5m9;J&h)2)%!HBj9Vpdk zjLv6IzaP;9Q9(4a{{YczwPz)Vm%+ zvjOi|aZQ7irOJ2Qj3hqQ4~jKzo~HN5P}$Rw=MMg6zX_KYjrY$jG_+GnEe6iw!Vyau zi5Q)>DeF(Sr0EI@^3;+fPFveoe7!WdjS7c#&x3V(81mFY8;QStzPMbF7cRzP-DJZD@{&gbT@kk z6CQH$B4i7=uxNZ5#_<$O#6xPX487Cdok4w3f}PUSduOsoz@;D~lzr}@?)Eq*?GIB^ z2PflTk2lfyL5w3G%Z1eKafL@MN(}L-=?zaRgti@j3B_F31j1Qt!6~}R2X}J+cUNxI z#2IGJdpwezH+N6JgPD9qEY+v}%QH6~h9)a67n99$v1hBD)5=hUD}zae7Afk}+p{`u zL2D63WnFW@uQWQ`RF4h4N58q9&{2O>UE&p+V@dLkx~&oYyEt)q6a5}uHg(v1bbJDV zEO(=4={qdKN95~>z8@X19|sp)Q|DEhB(U!;@hERYO%$~-q}DB+I(eizN&d0zcL|j&2)i_NpS7W& z73a?_9OEA|l}B)!bhxdUJ$)~Ajp_YfuW?=U4^eQGn^6*6^-!TBU5+_hHmt?S-OX|O zdG{S#6&agdKAlIz^$yj`0yj5D6IRWZLmeJsVo{eL&F@y3QZr+DUz}Pv-%^AJL0_TT zs?Na`zZr!bu#_*PZQWNmuKtDJHQrTFZ_kyM-^hc^P=YcX43xABh*P52-#geYoCPF@h0c%^(-0Q zCU!3efkGMYjsiyeb4P>yydNKH+!Hu#lG0s1r#wTE`ottoJwuQXfJ=cWq7+8J1V+x9fO=+m3Uc36rTygo+E@lP3 zpP%gKv-FAS8`=baF>tPoH25$uws6vPY_39aLMyrv)p_wCwVGpqbguR+9?yu`TKKx; zt`!XxPe@^_c~VC_iL)Y2-PEe`lu>TNytSWN3O=?tRdU9s!y~%lj!U2Z*<-=RIu?TC zx2Xs%B~|U-v~!po%$pvpKBz3p$*d(Yf5rG}HEDa+;ga}GfGZwC>akf4(=t~E-i{*{ z-Iu>*X@8By@T!(WK3bK$ST`G->xMIoecjz7dAMQM@{gBq?`k*1Kj15SA61hv9vvh) zsn&iSTPK8jD(-m3xn)>AKw3aDi<@x?wZ}hh&9gh4AN_-rQ82qqU9KXH#|}(y(h8u3 z(Ckaj3HfP^7RWd>RUfc8k!28j9AhbBYCNN-#pE@>Ic2n16}^ILlW_Xeu_SwncDk&f zg9A4She!?5^h^n>n^Pt=?a}?X@Wn@a+${?4^of7TkLOm`!t#fg#$xsU!Zv+~mv`>V!>OLgtHt!jzu}BwUaDB! zV>`92f;;~lX4uI6RQaJl-AAE(bs6pY)vF}U^-&AdV}AX^wJkHw9V!E1e`fyy@5%b< zp7J~H<>D7`_VRh)6eQ;aB|vBAAh~mwgS`E`Yx}KMV|Mx^uS=aNNm-G3{Pd4Fa P5MzeAraE~?9Dn;i{uUhC literal 0 HcmV?d00001 diff --git a/assets/kenney-ui-gray-sheet.xml b/assets/kenney-ui-gray-sheet.xml new file mode 100644 index 00000000..d7f87ddf --- /dev/null +++ b/assets/kenney-ui-gray-sheet.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua new file mode 100644 index 00000000..21c3c30a --- /dev/null +++ b/plugin/src/Assets.lua @@ -0,0 +1,52 @@ +local sheetAsset = "rbxassetid://2738712459" + +local Assets = { + Sprites = { + WhiteCross = { + asset = sheetAsset, + offset = Vector2.new(190, 318), + size = Vector2.new(18, 18), + }, + }, + Slices = { + GrayBox = { + asset = sheetAsset, + offset = Vector2.new(148, 433), + size = Vector2.new(36, 36), + center = Rect.new(8, 8, 9, 9), + }, + GrayButton02 = { + asset = sheetAsset, + offset = Vector2.new(0, 98), + size = Vector2.new(190, 45), + center = Rect.new(16, 16, 17, 17), + }, + GrayButton07 = { + asset = sheetAsset, + offset = Vector2.new(195, 0), + size = Vector2.new(49, 49), + center = Rect.new(16, 16, 17, 17), + }, + }, + StartSession = "", + SessionActive = "", + Configure = "", +} + +local function guardForTypos(name, map) + setmetatable(map, { + __index = function(_, key) + error(("%q is not a valid member of %s"):format(tostring(key), name), 2) + end + }) + + for key, child in pairs(map) do + if type(child) == "table" then + guardForTypos(("%s.%s"):format(name, key), child) + end + end +end + +guardForTypos("Assets", Assets) + +return Assets \ No newline at end of file diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 53b4ee51..35bed493 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -2,7 +2,7 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) local Plugin = script:FindFirstAncestor("Plugin") -local Icons = require(Plugin.Icons) +local Assets = require(Plugin.Assets) local Session = require(Plugin.Session) local Config = require(Plugin.Config) local Version = require(Plugin.Version) @@ -123,7 +123,10 @@ function App:render() } end - return e("ScreenGui", nil, children) + return e("ScreenGui", { + AutoLocalize = false, + ZIndexBehavior = Enum.ZIndexBehavior.Sibling, + }, children) end function App:didMount() @@ -134,7 +137,7 @@ function App:didMount() self.connectButton = toolbar:CreateButton( "Connect", "Connect to a running Rojo session", - Icons.StartSession) + Assets.StartSession) self.connectButton.ClickableWhenViewportHidden = false self.connectButton.Click:Connect(function() checkUpgrade(self.props.plugin) @@ -166,7 +169,7 @@ function App:didMount() self.configButton = toolbar:CreateButton( "Configure", "Configure the Rojo plugin", - Icons.Configure) + Assets.Configure) self.configButton.ClickableWhenViewportHidden = false self.configButton.Click:Connect(function() self.configButton:SetActive(false) @@ -180,9 +183,9 @@ function App:didUpdate() self.connectButton:SetActive(connectActive) if self.state.sessionStatus == SessionStatus.Connected then - self.connectButton.Icon = Icons.SessionActive + self.connectButton.Icon = Assets.SessionActive else - self.connectButton.Icon = Icons.StartSession + self.connectButton.Icon = Assets.StartSession end end diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index d4d6e2eb..afeedc3c 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -1,12 +1,21 @@ -local Roact = require(script:FindFirstAncestor("Rojo").Roact) +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin -local Config = require(script.Parent.Parent.Config) +local Roact = require(Rojo.Roact) -local FitList = require(script.Parent.FitList) -local FitText = require(script.Parent.FitText) +local Config = require(Plugin.Config) +local Assets = require(Plugin.Assets) + +local FitList = require(Plugin.Components.FitList) +local FitText = require(Plugin.Components.FitText) +local FormButton = require(Plugin.Components.FormButton) + +local WhiteCross = Assets.Sprites.WhiteCross +local GrayBox = Assets.Slices.GrayBox local e = Roact.createElement +local TEXT_COLOR = Color3.new(0.05, 0.05, 0.05) local FORM_TEXT_SIZE = 20 local ConnectPanel = Roact.Component:extend("ConnectPanel") @@ -40,34 +49,69 @@ function ConnectPanel:render() local cancel = self.props.cancel return e(FitList, { + containerKind = "ImageLabel", containerProps = { - BackgroundColor3 = Color3.fromRGB(32, 32, 32), - BorderColor3 = Color3.fromRGB(64, 64, 64), - Position = UDim2.new(0.5, 0, 0, 0), - AnchorPoint = Vector2.new(0.5, 0), + Image = GrayBox.asset, + ImageRectOffset = GrayBox.offset, + ImageRectSize = GrayBox.size, + ScaleType = Enum.ScaleType.Slice, + SliceCenter = GrayBox.center, + BackgroundTransparency = 1, + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + }, + layoutProps = { + HorizontalAlignment = Enum.HorizontalAlignment.Center, }, }, { - Title = e("TextLabel", { + Head = e("Frame", { LayoutOrder = 1, - Font = Enum.Font.SourceSans, - TextSize = 22, - Text = "Start New Rojo Session", - Size = UDim2.new(1, 0, 0, 28), + Size = UDim2.new(1, 0, 0, 36), BackgroundTransparency = 1, - TextColor3 = Color3.new(1, 1, 1), }, { - BottomBorder = e("Frame", { - BorderSizePixel = 0, - BackgroundColor3 = Color3.fromRGB(48, 48, 48), - Size = UDim2.new(1, 0, 0, 1), - Position = UDim2.new(0, 0, 1, -1), + Padding = e("UIPadding", { + PaddingTop = UDim.new(0, 8), + PaddingBottom = UDim.new(0, 8), + PaddingLeft = UDim.new(0, 8), + PaddingRight = UDim.new(0, 8), }), + + Title = e("TextLabel", { + Font = Enum.Font.SourceSansBold, + TextSize = 22, + Text = "Start New Rojo Session", + Size = UDim2.new(1, 0, 1, 0), + TextXAlignment = Enum.TextXAlignment.Left, + BackgroundTransparency = 1, + TextColor3 = TEXT_COLOR, + }), + + Close = e("ImageButton", { + Image = WhiteCross.asset, + ImageRectOffset = WhiteCross.offset, + ImageRectSize = WhiteCross.size, + Size = UDim2.new(0, 18, 0, 18), + Position = UDim2.new(1, 0, 0.5, 0), + AnchorPoint = Vector2.new(1, 0.5), + ImageColor3 = TEXT_COLOR, + BackgroundTransparency = 1, + [Roact.Event.Activated] = function() + cancel() + end, + }), + }), + + Border = e("Frame", { + BorderSizePixel = 0, + BackgroundColor3 = Color3.new(0.7, 0.7, 0.7), + Size = UDim2.new(1, -4, 0, 2), + LayoutOrder = 2, }), Body = e(FitList, { containerProps = { BackgroundTransparency = 1, - LayoutOrder = 2, + LayoutOrder = 3, }, layoutProps = { Padding = UDim.new(0, 8), @@ -95,10 +139,10 @@ function ConnectPanel:render() LayoutOrder = 1, BackgroundTransparency = 1, TextXAlignment = Enum.TextXAlignment.Left, - Font = Enum.Font.SourceSans, + Font = Enum.Font.SourceSansBold, TextSize = FORM_TEXT_SIZE, Text = "Address", - TextColor3 = Color3.fromRGB(245, 245, 245), + TextColor3 = TEXT_COLOR, [Roact.Change.AbsoluteSize] = function(rbx) self:updateLabelSize("address", rbx.AbsoluteSize) @@ -109,11 +153,15 @@ function ConnectPanel:render() }), }), - InputOuter = e("Frame", { + InputOuter = e("ImageLabel", { LayoutOrder = 2, + Image = GrayBox.asset, + ImageRectOffset = GrayBox.offset, + ImageRectSize = GrayBox.size, + ScaleType = Enum.ScaleType.Slice, + SliceCenter = GrayBox.center, Size = UDim2.new(0, 300, 0, 24), - BackgroundColor3 = Color3.fromRGB(32, 32, 32), - BorderColor3 = Color3.fromRGB(64, 64, 64), + BackgroundTransparency = 1, }, { InputInner = e("TextBox", { BackgroundTransparency = 1, @@ -125,7 +173,7 @@ function ConnectPanel:render() TextXAlignment = Enum.TextXAlignment.Left, TextSize = FORM_TEXT_SIZE, Text = self.state.address, - TextColor3 = Color3.fromRGB(245, 245, 245), + TextColor3 = TEXT_COLOR, [Roact.Change.Text] = function(rbx) self:setState({ @@ -152,10 +200,10 @@ function ConnectPanel:render() LayoutOrder = 1, BackgroundTransparency = 1, TextXAlignment = Enum.TextXAlignment.Left, - Font = Enum.Font.SourceSans, + Font = Enum.Font.SourceSansBold, TextSize = FORM_TEXT_SIZE, Text = "Port", - TextColor3 = Color3.fromRGB(245, 245, 245), + TextColor3 = TEXT_COLOR, [Roact.Change.AbsoluteSize] = function(rbx) self:updateLabelSize("port", rbx.AbsoluteSize) @@ -166,11 +214,15 @@ function ConnectPanel:render() }), }), - InputOuter = e("Frame", { + InputOuter = e("ImageLabel", { LayoutOrder = 2, + Image = GrayBox.asset, + ImageRectOffset = GrayBox.offset, + ImageRectSize = GrayBox.size, + ScaleType = Enum.ScaleType.Slice, + SliceCenter = GrayBox.center, Size = UDim2.new(0, 300, 0, 24), - BackgroundColor3 = Color3.fromRGB(32, 32, 32), - BorderColor3 = Color3.fromRGB(64, 64, 64), + BackgroundTransparency = 1, }, { InputInner = e("TextBox", { BackgroundTransparency = 1, @@ -182,7 +234,7 @@ function ConnectPanel:render() TextXAlignment = Enum.TextXAlignment.Left, TextSize = FORM_TEXT_SIZE, Text = self.state.port, - TextColor3 = Color3.fromRGB(245, 245, 245), + TextColor3 = TEXT_COLOR, [Roact.Change.Text] = function(rbx) self:setState({ @@ -203,36 +255,18 @@ function ConnectPanel:render() Padding = UDim.new(0, 8), }, }, { - e(FitText, { - Kind = "TextButton", - LayoutOrder = 1, - BackgroundColor3 = Color3.fromRGB(32, 32, 32), - BorderColor3 = Color3.fromRGB(64, 64, 64), - TextColor3 = Color3.fromRGB(245, 245, 245), - Text = "Start", - Font = Enum.Font.SourceSans, - TextSize = FORM_TEXT_SIZE, - Padding = Vector2.new(12, 3), - - [Roact.Event.Activated] = function() + e(FormButton, { + text = "Start", + onClick = function() if startSession ~= nil then startSession(self.state.address, self.state.port) end end, }), - e(FitText, { - Kind = "TextButton", - LayoutOrder = 2, - BackgroundColor3 = Color3.fromRGB(32, 32, 32), - BorderColor3 = Color3.fromRGB(64, 64, 64), - TextColor3 = Color3.fromRGB(245, 245, 245), - Text = "Cancel", - Font = Enum.Font.SourceSans, - TextSize = FORM_TEXT_SIZE, - Padding = Vector2.new(12, 3), - - [Roact.Event.Activated] = function() + e(FormButton, { + text = "Cancel", + onClick = function() if cancel ~= nil then cancel() end diff --git a/plugin/src/Components/ConnectionActivePanel.lua b/plugin/src/Components/ConnectionActivePanel.lua index a63ea6aa..846a10ce 100644 --- a/plugin/src/Components/ConnectionActivePanel.lua +++ b/plugin/src/Components/ConnectionActivePanel.lua @@ -1,24 +1,38 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) +local Assets = require(script.Parent.Parent.Assets) + +local FitList = require(script.Parent.FitList) local FitText = require(script.Parent.FitText) local e = Roact.createElement +local GrayBox = Assets.Slices.GrayBox + local ConnectionActivePanel = Roact.Component:extend("ConnectionActivePanel") function ConnectionActivePanel:render() - return e(FitText, { - Kind = "TextLabel", - Padding = Vector2.new(4, 4), - Font = Enum.Font.SourceSans, - TextSize = 16, - Text = "Rojo Connected", - TextColor3 = Color3.new(1, 1, 1), - BackgroundColor3 = Color3.new(0, 0, 0), - BorderSizePixel = 0, - BackgroundTransparency = 0.6, - Position = UDim2.new(0.5, 0, 0, 0), - AnchorPoint = Vector2.new(0.5, 0), + return e(FitList, { + containerKind = "ImageButton", + containerProps = { + Image = GrayBox.asset, + ImageRectOffset = GrayBox.offset, + ImageRectSize = GrayBox.size, + SliceCenter = GrayBox.center, + ScaleType = Enum.ScaleType.Slice, + BackgroundTransparency = 1, + Position = UDim2.new(0.5, 0, 0, 0), + AnchorPoint = Vector2.new(0.5, 0), + }, + }, { + Text = e(FitText, { + Padding = Vector2.new(12, 6), + Font = Enum.Font.SourceSans, + TextSize = 18, + Text = "Rojo Connected", + TextColor3 = Color3.new(0.05, 0.05, 0.05), + BackgroundTransparency = 1, + }), }) end diff --git a/plugin/src/Components/FitList.lua b/plugin/src/Components/FitList.lua index 4aa49cb9..50d2f581 100644 --- a/plugin/src/Components/FitList.lua +++ b/plugin/src/Components/FitList.lua @@ -11,6 +11,7 @@ function FitList:init() end function FitList:render() + local containerKind = self.props.containerKind or "Frame" local containerProps = self.props.containerProps local layoutProps = self.props.layoutProps local paddingProps = self.props.paddingProps @@ -43,7 +44,7 @@ function FitList:render() Size = self.sizeBinding, }) - return e("Frame", fullContainerProps, children) + return e(containerKind, fullContainerProps, children) end return FitList \ No newline at end of file diff --git a/plugin/src/Components/FitText.lua b/plugin/src/Components/FitText.lua index 673bcf03..2f9e6bc6 100644 --- a/plugin/src/Components/FitText.lua +++ b/plugin/src/Components/FitText.lua @@ -13,7 +13,7 @@ function FitText:init() end function FitText:render() - local kind = self.props.Kind + local kind = self.props.Kind or "TextLabel" local containerProps = Dictionary.merge(self.props, { Kind = Dictionary.None, diff --git a/plugin/src/Components/FormButton.lua b/plugin/src/Components/FormButton.lua new file mode 100644 index 00000000..17bc8b67 --- /dev/null +++ b/plugin/src/Components/FormButton.lua @@ -0,0 +1,49 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Assets = require(Plugin.Assets) +local FitList = require(Plugin.Components.FitList) +local FitText = require(Plugin.Components.FitText) + +local e = Roact.createElement + +local GrayButton07 = Assets.Slices.GrayButton07 + +local function FormButton(props) + local text = props.text + local layoutOrder = props.layoutOrder + local onClick = props.onClick + + return e(FitList, { + containerKind = "ImageButton", + containerProps = { + LayoutOrder = layoutOrder, + BackgroundTransparency = 1, + Image = GrayButton07.asset, + ImageRectOffset = GrayButton07.offset, + ImageRectSize = GrayButton07.size, + ScaleType = Enum.ScaleType.Slice, + SliceCenter = GrayButton07.center, + + [Roact.Event.Activated] = function() + if onClick ~= nil then + onClick() + end + end, + }, + }, { + Text = e(FitText, { + Kind = "TextLabel", + Text = text, + TextSize = 22, + Font = Enum.Font.SourceSansBold, + Padding = Vector2.new(14, 6), + TextColor3 = Color3.new(0.05, 0.05, 0.05), + BackgroundTransparency = 1, + }), + }) +end + +return FormButton \ No newline at end of file diff --git a/plugin/src/Icons.lua b/plugin/src/Icons.lua deleted file mode 100644 index ef631416..00000000 --- a/plugin/src/Icons.lua +++ /dev/null @@ -1,13 +0,0 @@ -local Icons = { - StartSession = "", - SessionActive = "", - Configure = "", -} - -setmetatable(Icons, { - __index = function(_, key) - error(("%q is not a valid member of Icons"):format(tostring(key)), 2) - end -}) - -return Icons \ No newline at end of file From f21f01be1a475af574df408be26f2694ad792fea Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 11 Jan 2019 15:26:25 -0800 Subject: [PATCH 0356/1504] Factor out form text input --- plugin/src/Components/ConnectPanel.lua | 75 +++++++------------------ plugin/src/Components/FormTextInput.lua | 47 ++++++++++++++++ 2 files changed, 66 insertions(+), 56 deletions(-) create mode 100644 plugin/src/Components/FormTextInput.lua diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index afeedc3c..adbd8710 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -9,6 +9,7 @@ local Assets = require(Plugin.Assets) local FitList = require(Plugin.Components.FitList) local FitText = require(Plugin.Components.FitText) local FormButton = require(Plugin.Components.FormButton) +local FormTextInput = require(Plugin.Components.FormTextInput) local WhiteCross = Assets.Sprites.WhiteCross local GrayBox = Assets.Slices.GrayBox @@ -153,34 +154,15 @@ function ConnectPanel:render() }), }), - InputOuter = e("ImageLabel", { - LayoutOrder = 2, - Image = GrayBox.asset, - ImageRectOffset = GrayBox.offset, - ImageRectSize = GrayBox.size, - ScaleType = Enum.ScaleType.Slice, - SliceCenter = GrayBox.center, - Size = UDim2.new(0, 300, 0, 24), - BackgroundTransparency = 1, - }, { - InputInner = e("TextBox", { - BackgroundTransparency = 1, - Size = UDim2.new(1, -8, 1, -8), - Position = UDim2.new(0.5, 0, 0.5, 0), - AnchorPoint = Vector2.new(0.5, 0.5), - Font = Enum.Font.SourceSans, - ClearTextOnFocus = false, - TextXAlignment = Enum.TextXAlignment.Left, - TextSize = FORM_TEXT_SIZE, - Text = self.state.address, - TextColor3 = TEXT_COLOR, - - [Roact.Change.Text] = function(rbx) - self:setState({ - address = rbx.Text, - }) - end, - }), + Input = e(FormTextInput, { + layoutOrder = 2, + size = UDim2.new(0, 300, 0, 24), + value = self.state.address, + onValueChange = function(newValue) + self:setState({ + address = newValue, + }) + end, }), }), @@ -214,34 +196,15 @@ function ConnectPanel:render() }), }), - InputOuter = e("ImageLabel", { - LayoutOrder = 2, - Image = GrayBox.asset, - ImageRectOffset = GrayBox.offset, - ImageRectSize = GrayBox.size, - ScaleType = Enum.ScaleType.Slice, - SliceCenter = GrayBox.center, - Size = UDim2.new(0, 300, 0, 24), - BackgroundTransparency = 1, - }, { - InputInner = e("TextBox", { - BackgroundTransparency = 1, - Size = UDim2.new(1, -8, 1, -8), - Position = UDim2.new(0.5, 0, 0.5, 0), - AnchorPoint = Vector2.new(0.5, 0.5), - Font = Enum.Font.SourceSans, - ClearTextOnFocus = false, - TextXAlignment = Enum.TextXAlignment.Left, - TextSize = FORM_TEXT_SIZE, - Text = self.state.port, - TextColor3 = TEXT_COLOR, - - [Roact.Change.Text] = function(rbx) - self:setState({ - port = rbx.Text, - }) - end, - }), + Input = e(FormTextInput, { + layoutOrder = 2, + size = UDim2.new(0, 300, 0, 24), + value = self.state.port, + onValueChange = function(newValue) + self:setState({ + port = newValue, + }) + end, }), }), diff --git a/plugin/src/Components/FormTextInput.lua b/plugin/src/Components/FormTextInput.lua new file mode 100644 index 00000000..0b3016fc --- /dev/null +++ b/plugin/src/Components/FormTextInput.lua @@ -0,0 +1,47 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Assets = require(Plugin.Assets) + +local e = Roact.createElement + +local GrayBox = Assets.Slices.GrayBox + +local function FormTextInput(props) + local value = props.value + local onValueChange = props.onValueChange + local layoutOrder = props.layoutOrder + local size = props.size + + return e("ImageLabel", { + LayoutOrder = layoutOrder, + Image = GrayBox.asset, + ImageRectOffset = GrayBox.offset, + ImageRectSize = GrayBox.size, + ScaleType = Enum.ScaleType.Slice, + SliceCenter = GrayBox.center, + Size = size, + BackgroundTransparency = 1, + }, { + InputInner = e("TextBox", { + BackgroundTransparency = 1, + Size = UDim2.new(1, -8, 1, -8), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + Font = Enum.Font.SourceSans, + ClearTextOnFocus = false, + TextXAlignment = Enum.TextXAlignment.Left, + TextSize = 20, + Text = value, + TextColor3 = Color3.new(0.05, 0.05, 0.05), + + [Roact.Change.Text] = function(rbx) + onValueChange(rbx.Text) + end, + }), + }) +end + +return FormTextInput \ No newline at end of file From 30ce9276214fcf215be937d29d5345c04d277dd0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 11 Jan 2019 15:45:32 -0800 Subject: [PATCH 0357/1504] Refactor Session and ApiContext to allow cancelation --- plugin/src/ApiContext.lua | 29 +------- plugin/src/Components/App.lua | 8 ++- plugin/src/Session.lua | 121 +++++++++++++++++++++------------- 3 files changed, 83 insertions(+), 75 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index c16535d0..a3e321cd 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -19,17 +19,14 @@ setmetatable(ApiContext.Error, { end }) --- TODO: Switch to onMessages and batch processing function ApiContext.new(baseUrl) assert(type(baseUrl) == "string") local self = { baseUrl = baseUrl, - onMessageCallback = nil, serverId = nil, rootInstanceId = nil, instanceMetadataMap = nil, - connected = false, messageCursor = -1, partitionRoutes = nil, } @@ -100,21 +97,14 @@ function ApiContext:connect() self.partitionRoutes = body.partitions self.rootInstanceId = body.rootInstanceId self.instanceMetadataMap = body.instanceMetadataMap - self.connected = true end) end function ApiContext:read(ids) - if not self.connected then - return Promise.reject() - end - local url = ("%s/api/read/%s"):format(self.baseUrl, table.concat(ids, ",")) return Http.get(url) :catch(function(err) - self.connected = false - return Promise.reject(err) end) :andThen(function(response) @@ -131,10 +121,6 @@ function ApiContext:read(ids) end function ApiContext:retrieveMessages() - if not self.connected then - return Promise.reject() - end - local url = ("%s/api/subscribe/%s"):format(self.baseUrl, self.messageCursor) return Http.get(url) @@ -143,8 +129,6 @@ function ApiContext:retrieveMessages() return self:retrieveMessages() end - self.connected = false - return Promise.reject(err) end) :andThen(function(response) @@ -154,20 +138,9 @@ function ApiContext:retrieveMessages() return Promise.reject("Server changed ID") end - local promise = Promise.resolve(nil) - - for _, message in ipairs(body.messages) do - promise = promise:andThen(function() - return self.onMessageCallback(message) - end) - end - self.messageCursor = body.messageCursor - return promise - end) - :andThen(function() - return self:retrieveMessages() + return body.messages end) end diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 35bed493..2b99c764 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -95,8 +95,9 @@ function App:render() local success, session = Session.new({ address = address, port = port, - onError = function() - Logging.trace("Session terminated") + onError = function(message) + Logging.warn("%s", tostring(message)) + Logging.trace("Session terminated due to error") self.currentSession = nil self:setState({ @@ -145,12 +146,13 @@ function App:didMount() if self.state.sessionStatus == SessionStatus.Connected then Logging.trace("Disconnecting session") + self.currentSession:disconnect() self.currentSession = nil self:setState({ sessionStatus = SessionStatus.Disconnected, }) - error("TODO: Actually disconnect old session") + Logging.trace("Session terminated by user") elseif self.state.sessionStatus == SessionStatus.Disconnected then Logging.trace("Starting session configuration") diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 5e1d15df..77d1c75b 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -1,66 +1,99 @@ +local Rojo = script:FindFirstAncestor("Rojo") + +local Promise = require(Rojo.Promise) + local ApiContext = require(script.Parent.ApiContext) -local Logging = require(script.Parent.Logging) local Reconciler = require(script.Parent.Reconciler) local Session = {} Session.__index = Session function Session.new(config) - local self = {} - - self.onError = config.onError - - local hasErrors = false - - local reconciler - local remoteUrl = ("http://%s:%s"):format(config.address, config.port) - local api = ApiContext.new(remoteUrl) - ApiContext:onMessage(function(message) - local requestedIds = {} - - for _, id in ipairs(message.added) do - table.insert(requestedIds, id) - end - - for _, id in ipairs(message.updated) do - table.insert(requestedIds, id) - end - - for _, id in ipairs(message.removed) do - table.insert(requestedIds, id) - end - - return api:read(requestedIds) - :andThen(function(response) - return reconciler:applyUpdate(requestedIds, response.instances) - end) - :catch(function(message) - hasErrors = true - Logging.warn("%s", tostring(message)) - self.onError() - end) - end) + local self = { + onError = config.onError, + disconnected = false, + reconciler = nil, + api = api, + } api:connect() :andThen(function() - reconciler = Reconciler.new(api.instanceMetadataMap) + if self.disconnected then + return Promise.resolve() + end + + self.reconciler = Reconciler.new(api.instanceMetadataMap) return api:read({api.rootInstanceId}) - end) - :andThen(function(response) - reconciler:reconcile(response.instances, api.rootInstanceId, game) - return api:retrieveMessages() + :andThen(function(response) + if self.disconnected then + return Promise.resolve() + end + + self.reconciler:reconcile(response.instances, api.rootInstanceId, game) + return self:__processMessages() + end) end) :catch(function(message) - hasErrors = true - Logging.warn("%s", tostring(message)) - self.onError() + self.disconnected = true + self.onError(message) end) - return not hasErrors, setmetatable(self, Session) + return not self.disconnected, setmetatable(self, Session) +end + +function Session:__processMessages() + if self.disconnected then + return Promise.resolve() + end + + return self.api:retrieveMessages() + :andThen(function(messages) + local promise = Promise.resolve(nil) + + for _, message in ipairs(messages) do + promise = promise:andThen(function() + return self:__onMessage(message) + end) + end + + return promise + end) + :andThen(function() + return self:__processMessages() + end) +end + +function Session:__onMessage(message) + if self.disconnected then + return Promise.resolve() + end + + local requestedIds = {} + + for _, id in ipairs(message.added) do + table.insert(requestedIds, id) + end + + for _, id in ipairs(message.updated) do + table.insert(requestedIds, id) + end + + for _, id in ipairs(message.removed) do + table.insert(requestedIds, id) + end + + return self.api:read(requestedIds) + :andThen(function(response) + return self.reconciler:applyUpdate(requestedIds, response.instances) + end) +end + +function Session:disconnect() + self.disconnected = true end return Session \ No newline at end of file From f833642733b2f01fdaaa64703211d7e63103301e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 11 Jan 2019 15:51:25 -0800 Subject: [PATCH 0358/1504] Adjust sizing on connection box --- plugin/src/Assets.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index 21c3c30a..b73955ab 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -11,8 +11,8 @@ local Assets = { Slices = { GrayBox = { asset = sheetAsset, - offset = Vector2.new(148, 433), - size = Vector2.new(36, 36), + offset = Vector2.new(147, 433), + size = Vector2.new(38, 36), center = Rect.new(8, 8, 9, 9), }, GrayButton02 = { From 811db2e66843a6baf5139c5a8486db97de74b352 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 11 Jan 2019 17:53:47 -0800 Subject: [PATCH 0359/1504] 0.5.0-alpha.0 --- server/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/Cargo.toml b/server/Cargo.toml index ba818366..40d8b2ca 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0" +version = "0.5.0-alpha.0" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 3e1c467b65096b81b78973b4cfcee379d178c3f6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 11 Jan 2019 18:19:06 -0800 Subject: [PATCH 0360/1504] Upgrade and pin deps so that rbx-tree can break some APIs --- Cargo.lock | 260 ++++------------------------------ server/Cargo.toml | 6 +- server/src/commands/build.rs | 13 +- server/src/commands/upload.rs | 13 +- 4 files changed, 51 insertions(+), 241 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4f5f8835..dec520e9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -340,14 +340,6 @@ dependencies = [ "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "error-chain" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "error-chain" version = "0.12.0" @@ -475,20 +467,11 @@ dependencies = [ "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "hostname" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "http" version = "0.1.14" @@ -596,18 +579,6 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ipconfig" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "itoa" version = "0.4.3" @@ -647,11 +618,6 @@ dependencies = [ "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "linked-hash-map" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "lock_api" version = "0.1.5" @@ -677,14 +643,6 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "lru-cache" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "lz4" version = "1.23.1" @@ -747,7 +705,7 @@ dependencies = [ [[package]] name = "mime" -version = "0.3.12" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -769,7 +727,7 @@ name = "mime_guess" version = "2.0.0-alpha.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -789,7 +747,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -801,17 +759,7 @@ dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mio-uds" -version = "0.6.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1166,18 +1114,18 @@ dependencies = [ [[package]] name = "rbx_binary" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#f20378979f555e7e090bc62eb82afe7274a32ed4" +source = "git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad#8442d57a7a21072a380134962724281d044c65ad" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", + "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)", ] [[package]] name = "rbx_tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#f20378979f555e7e090bc62eb82afe7274a32ed4" +source = "git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad#8442d57a7a21072a380134962724281d044c65ad" dependencies = [ "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1187,10 +1135,10 @@ dependencies = [ [[package]] name = "rbx_xml" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git#f20378979f555e7e090bc62eb82afe7274a32ed4" +source = "git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad#8442d57a7a21072a380134962724281d044c65ad" dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", + "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1245,7 +1193,7 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.7" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1257,7 +1205,7 @@ dependencies = [ "hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1268,23 +1216,13 @@ dependencies = [ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-resolver 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "resolv-conf" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rojo" -version = "0.5.0" +version = "0.5.0-alpha.0" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1295,11 +1233,11 @@ dependencies = [ "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", - "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", - "rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)", + "rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)", + "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)", + "rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1485,7 +1423,7 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1496,17 +1434,6 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "socket2" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "stable_deref_trait" version = "1.1.1" @@ -1647,27 +1574,12 @@ dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-codec" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1688,16 +1600,6 @@ dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "tokio-fs" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "tokio-io" version = "0.1.11" @@ -1720,7 +1622,7 @@ dependencies = [ "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1760,82 +1662,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "tokio-udp" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-uds" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "trust-dns-proto" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "trust-dns-resolver" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "trust-dns-proto 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "try-lock" version = "0.2.2" @@ -1965,11 +1795,6 @@ dependencies = [ "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "widestring" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi" version = "0.2.8" @@ -2016,22 +1841,6 @@ dependencies = [ "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "winreg" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "winutil" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -2090,7 +1899,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7" "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" -"checksum error-chain 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6930e04918388a9a2e41d518c25cf679ccafe26733fb4127dbf21993f2575d46" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" @@ -2106,7 +1914,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9e59524a909fe98bb6c6f2cf1f27f2f6772887a496bf4c68cae0d94f884586" "checksum h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac030ae20dee464c5d0f36544d8b914a6bc606da44a57e052d2b0f5dae129e0" -"checksum hostname 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "21ceb46a83a85e824ef93669c8b390009623863b5c195d1ba747292c0c72f94e" "checksum http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "02096a6d2c55e63f7fcb800690e4f889a25f6ec342e3adb4594e293b625215ab" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" @@ -2117,18 +1924,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" -"checksum ipconfig 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "08f7eadeaf4b52700de180d147c4805f199854600b36faa963d91114827b2ffc" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)" = "023a4cd09b2ff695f9734c1934145a315594b7986398496841c7031a5a1bbdbd" "checksum libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "bff3ac7d6f23730d3b533c35ed75eef638167634476a499feef16c428d74b57b" -"checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" -"checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" @@ -2137,12 +1941,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" -"checksum mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)" = "0a907b83e7b9e987032439a387e187119cddafc92d5c2aaeb1d92580a793f630" +"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" "checksum mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2d4c0961143b8efdcfa29c3ae63281601b446a4a668165454b6c90f8024954c5" "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" -"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92f54eb45230c3aa20864ccf0c277eeaeadcf5e437e91731db498dbf7fbe0ec6" "checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" @@ -2180,17 +1983,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" -"checksum rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" -"checksum rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git)" = "" +"checksum rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)" = "" +"checksum rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)" = "" +"checksum rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)" = "" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.7 (registry+https://github.com/rust-lang/crates.io-index)" = "519ae6326d2e2863bd9e03cf5bd57758a330076a4b2be42eb00cea9a35f4084a" -"checksum resolv-conf 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b263b4aa1b5de9ffc0054a2386f96992058bb6870aab516f8cdeb8a667d56dcb" +"checksum reqwest 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0e60f169af3915c294818d55dde549f00d2966cef36d6c5e7255d75df3f2b16f" "checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" @@ -2211,9 +2013,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" -"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d" +"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" -"checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" @@ -2230,19 +2031,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1661fa0a44c95d01604bd05c66732a446c657efb62b5164a7a083a3b552b4951" "checksum tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4790d0be6f4ba6ae4f48190efa2ed7780c9e3567796abdb285003cf39840d9c5" -"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" "checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" "checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" -"checksum tokio-fs 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "0e9cbbc8a3698b7ab652340f46633364f9eaa928ddaaee79d8b8f356dd79a09d" "checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" "checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" "checksum tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "17465013014410310f9f61fa10bf4724803c149ea1d51efece131c38efca93aa" "checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" -"checksum tokio-udp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "66268575b80f4a4a710ef83d087fdfeeabdce9b74c797535fbac18a2cb906e92" -"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" -"checksum trust-dns-proto 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e33f29df428f112ffeda24b328b814b61d6916be29aa89f19bc3f684ba5437b8" -"checksum trust-dns-resolver 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "de630f95a192f793436ffae5137e88253cc4142a97d9a8e73c8d804fa85ddf0a" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" @@ -2262,7 +2057,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" -"checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" @@ -2270,7 +2064,5 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" -"checksum winreg 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a27a759395c1195c4cc5cda607ef6f8f6498f64e78f7900f5de0a127a424704a" -"checksum winutil 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7daf138b6b14196e3830a588acf1e86966c694d3e8fb026fb105b8b5dca07e6e" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" diff --git a/server/Cargo.toml b/server/Cargo.toml index 40d8b2ca..ac3cf933 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -35,9 +35,9 @@ serde = "1.0" serde_derive = "1.0" serde_json = "1.0" uuid = { version = "0.7", features = ["v4", "serde"] } -rbx_tree = { git = "https://github.com/LPGhatguy/rbx-tree.git" } -rbx_xml = { git = "https://github.com/LPGhatguy/rbx-tree.git" } -rbx_binary = { git = "https://github.com/LPGhatguy/rbx-tree.git" } +rbx_tree = { rev = "8442d57a7a21072a380134962724281d044c65ad", git = "https://github.com/LPGhatguy/rbx-tree.git" } +rbx_xml = { rev = "8442d57a7a21072a380134962724281d044c65ad", git = "https://github.com/LPGhatguy/rbx-tree.git" } +rbx_binary = { rev = "8442d57a7a21072a380134962724281d044c65ad", git = "https://github.com/LPGhatguy/rbx-tree.git" } [dev-dependencies] tempfile = "3.0" diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index 83ba2346..90a5981c 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -49,6 +49,9 @@ pub enum BuildError { #[fail(display = "IO error: {}", _0)] IoError(#[fail(cause)] io::Error), + + #[fail(display = "XML model file error")] + XmlModelEncodeError(rbx_xml::EncodeError), } impl From for BuildError { @@ -63,6 +66,12 @@ impl From for BuildError { } } +impl From for BuildError { + fn from(error: rbx_xml::EncodeError) -> BuildError { + BuildError::XmlModelEncodeError(error) + } +} + pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let output_kind = options.output_kind .or_else(|| detect_output_kind(options)) @@ -88,7 +97,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { // descendants. let root_id = tree.get_root_id(); - rbx_xml::encode(&tree, &[root_id], &mut file); + rbx_xml::encode(&tree, &[root_id], &mut file)?; }, OutputKind::Rbxlx => { // Place files don't contain an entry for the DataModel, but our @@ -96,7 +105,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let root_id = tree.get_root_id(); let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); - rbx_xml::encode(&tree, top_level_ids, &mut file); + rbx_xml::encode(&tree, top_level_ids, &mut file)?; }, OutputKind::Rbxm => { let root_id = tree.get_root_id(); diff --git a/server/src/commands/upload.rs b/server/src/commands/upload.rs index 1685275e..70cdf0cd 100644 --- a/server/src/commands/upload.rs +++ b/server/src/commands/upload.rs @@ -29,6 +29,9 @@ pub enum UploadError { #[fail(display = "HTTP error: {}", _0)] HttpError(#[fail(cause)] reqwest::Error), + + #[fail(display = "XML model file error")] + XmlModelEncodeError(rbx_xml::EncodeError), } impl From for UploadError { @@ -49,6 +52,12 @@ impl From for UploadError { } } +impl From for UploadError { + fn from(error: rbx_xml::EncodeError) -> UploadError { + UploadError::XmlModelEncodeError(error) + } +} + #[derive(Debug)] pub struct UploadOptions<'a> { pub fuzzy_project_path: PathBuf, @@ -77,10 +86,10 @@ pub fn upload(options: &UploadOptions) -> Result<(), UploadError> { match options.kind { Some("place") | None => { let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); - rbx_xml::encode(&tree, top_level_ids, &mut contents); + rbx_xml::encode(&tree, top_level_ids, &mut contents)?; }, Some("model") => { - rbx_xml::encode(&tree, &[root_id], &mut contents); + rbx_xml::encode(&tree, &[root_id], &mut contents)?; }, Some(invalid) => return Err(UploadError::InvalidKind(invalid.to_owned())), } From 94082477085d1bfdf813604779bc42b0a2ec8272 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 12 Jan 2019 15:58:45 -0800 Subject: [PATCH 0361/1504] Update CHANGELOG --- CHANGES.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index c7187d4c..a2cc6a0a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -10,13 +10,14 @@ * Generates `rbxm`, `rbxmx`, `rbxl`, or `rbxlx` files out of your project * Usage: `rojo build --output .rbxm` * Added `rojo upload` command - * Generates and uploads a place file to roblox.com out of your project - * Usage: `rojo upload --cookie "" --place_id ` + * Generates and uploads a place or model to roblox.com out of your project + * Usage: `rojo upload --cookie "" --asset_id ` * New plugin * Only one button now, "Connect" * New UI to pick server address and port * Better error reporting * Added support for `.csv` files turning into `LocalizationTable` instances +* Added support for `.txt` files turning into `StringValue` instances * Added debug visualization code to diagnose problems * `/visualize/rbx` and `/visualize/imfs` show instance and file state respectively; they require GraphViz to be installed on your machine. * Added optional place ID restrictions to project files From 8ce2e605a23608d55364054c9da9338b2e472854 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 12 Jan 2019 16:34:02 -0800 Subject: [PATCH 0362/1504] Remove site_url --- mkdocs.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/mkdocs.yml b/mkdocs.yml index 711d3fd5..a45c478e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,5 +1,4 @@ site_name: Rojo Documentation -site_url: https://lpghatguy.github.io/rojo/ repo_name: LPGhatguy/rojo repo_url: https://github.com/LPGhatguy/rojo From e23056ac2f2bc9c61e7f1ef93fb8faa3758819d2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Jan 2019 17:00:04 -0800 Subject: [PATCH 0363/1504] Change API to message metadata inline and add visualization --- server/src/rbx_session.rs | 4 ++-- server/src/visualize.rs | 29 +++++++++++++++++++++-------- server/src/web.rs | 39 +++++++++++++++++++++++++++++++-------- 3 files changed, 54 insertions(+), 18 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 13342379..071ced15 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -155,8 +155,8 @@ impl RbxSession { &self.tree } - pub fn get_instance_metadata_map(&self) -> &HashMap { - &self.instance_metadata_map + pub fn get_instance_metadata(&self, id: RbxId) -> Option<&InstanceProjectNodeMetadata> { + self.instance_metadata_map.get(&id) } pub fn debug_get_path_map(&self) -> &PathMap { diff --git a/server/src/visualize.rs b/server/src/visualize.rs index 74696eda..0a39212e 100644 --- a/server/src/visualize.rs +++ b/server/src/visualize.rs @@ -5,10 +5,11 @@ use std::{ process::{Command, Stdio}, }; -use rbx_tree::{RbxTree, RbxId}; +use rbx_tree::RbxId; use crate::{ imfs::{Imfs, ImfsItem}, + rbx_session::RbxSession, }; static GRAPHVIZ_HEADER: &str = r#" @@ -41,13 +42,13 @@ pub fn graphviz_to_svg(source: &str) -> String { String::from_utf8(output.stdout).expect("Failed to parse stdout as UTF-8") } -pub struct VisualizeRbxTree<'a>(pub &'a RbxTree); +pub struct VisualizeRbxSession<'a>(pub &'a RbxSession); -impl<'a> fmt::Display for VisualizeRbxTree<'a> { +impl<'a> fmt::Display for VisualizeRbxSession<'a> { fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { writeln!(output, "{}", GRAPHVIZ_HEADER)?; - visualize_rbx_node(self.0, self.0.get_root_id(), output)?; + visualize_rbx_node(self.0, self.0.get_tree().get_root_id(), output)?; writeln!(output, "}}")?; @@ -55,14 +56,26 @@ impl<'a> fmt::Display for VisualizeRbxTree<'a> { } } -fn visualize_rbx_node(tree: &RbxTree, id: RbxId, output: &mut fmt::Formatter) -> fmt::Result { - let node = tree.get_instance(id).unwrap(); +fn visualize_rbx_node(session: &RbxSession, id: RbxId, output: &mut fmt::Formatter) -> fmt::Result { + let node = session.get_tree().get_instance(id).unwrap(); - writeln!(output, " \"{}\" [label=\"{} ({})|{}\"]", id, node.name, node.class_name, id)?; + let mut node_label = format!("{}|{}|{}", node.name, node.class_name, id); + + if let Some(metadata) = session.get_instance_metadata(id) { + node_label.push('|'); + node_label.push_str(&serde_json::to_string(metadata).unwrap()); + } + + node_label = node_label + .replace("\"", """) + .replace("{", "\\{") + .replace("}", "\\}"); + + writeln!(output, " \"{}\" [label=\"{}\"]", id, node_label)?; for &child_id in node.get_children_ids() { writeln!(output, " \"{}\" -> \"{}\"", id, child_id)?; - visualize_rbx_node(tree, child_id, output)?; + visualize_rbx_node(session, child_id, output)?; } Ok(()) diff --git a/server/src/web.rs b/server/src/web.rs index 5be2cef5..e02ae511 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -17,9 +17,23 @@ use crate::{ session_id::SessionId, project::InstanceProjectNodeMetadata, rbx_snapshot::InstanceChanges, - visualize::{VisualizeRbxTree, VisualizeImfs, graphviz_to_svg}, + visualize::{VisualizeRbxSession, VisualizeImfs, graphviz_to_svg}, }; +/// Used to attach metadata specific to Rojo to instances, which come from the +/// rbx_tree crate. +/// +/// Both fields are wrapped in Cow in order to make owned-vs-borrowed simpler +/// for tests. +#[derive(Debug, Serialize, Deserialize)] +pub struct InstanceWithMetadata<'a> { + #[serde(flatten)] + pub instance: Cow<'a, RootedRbxInstance>, + + #[serde(rename = "Metadata")] + pub metadata: Option>, +} + #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ServerInfoResponse<'a> { @@ -28,7 +42,6 @@ pub struct ServerInfoResponse<'a> { pub protocol_version: u64, pub expected_place_ids: Option>, pub root_instance_id: RbxId, - pub instance_metadata_map: Cow<'a, HashMap>, } #[derive(Debug, Serialize, Deserialize)] @@ -36,7 +49,7 @@ pub struct ServerInfoResponse<'a> { pub struct ReadResponse<'a> { pub session_id: SessionId, pub message_cursor: u32, - pub instances: HashMap>, + pub instances: HashMap>, } #[derive(Debug, Serialize, Deserialize)] @@ -81,7 +94,6 @@ impl Server { session_id: self.session.session_id, expected_place_ids: self.session.project.serve_place_ids.clone(), root_instance_id: tree.get_root_id(), - instance_metadata_map: Cow::Borrowed(rbx_session.get_instance_metadata_map()), }) }, @@ -148,10 +160,22 @@ impl Server { for &requested_id in &requested_ids { if let Some(instance) = tree.get_instance(requested_id) { - instances.insert(instance.get_id(), Cow::Borrowed(instance)); + let metadata = rbx_session.get_instance_metadata(requested_id) + .map(Cow::Borrowed); + + instances.insert(instance.get_id(), InstanceWithMetadata { + instance: Cow::Borrowed(instance), + metadata, + }); for descendant in tree.descendants(requested_id) { - instances.insert(descendant.get_id(), Cow::Borrowed(descendant)); + let descendant_meta = rbx_session.get_instance_metadata(descendant.get_id()) + .map(Cow::Borrowed); + + instances.insert(descendant.get_id(), InstanceWithMetadata { + instance: Cow::Borrowed(descendant), + metadata: descendant_meta, + }); } } } @@ -165,9 +189,8 @@ impl Server { (GET) (/visualize/rbx) => { let rbx_session = self.session.rbx_session.lock().unwrap(); - let tree = rbx_session.get_tree(); - let dot_source = format!("{}", VisualizeRbxTree(tree)); + let dot_source = format!("{}", VisualizeRbxSession(&rbx_session)); Response::svg(graphviz_to_svg(&dot_source)) }, From c284b7de40b039f0e8b3ea6372a36d3a4e251331 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Jan 2019 17:04:47 -0800 Subject: [PATCH 0364/1504] Remove instanceMetadataMap from plugin --- plugin/src/Reconciler.lua | 11 +++++------ plugin/src/Session.lua | 4 +--- 2 files changed, 6 insertions(+), 9 deletions(-) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index df925325..07e9db76 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -100,10 +100,9 @@ end local Reconciler = {} Reconciler.__index = Reconciler -function Reconciler.new(instanceMetadataMap) +function Reconciler.new() local self = { instanceMap = makeInstanceMap(), - instanceMetadataMap = instanceMetadataMap, } return setmetatable(self, Reconciler) @@ -176,7 +175,7 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) end end - if self:__shouldClearUnknownInstances(id) then + if self:__shouldClearUnknownInstances(virtualInstance) then for existingChildInstance in pairs(unvisitedExistingChildren) do self.instanceMap:removeInstance(existingChildInstance) existingChildInstance:Destroy() @@ -204,9 +203,9 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) return instance end -function Reconciler:__shouldClearUnknownInstances(id) - if self.instanceMetadataMap[id] then - return not self.instanceMetadataMap[id].ignoreUnknownInstances +function Reconciler:__shouldClearUnknownInstances(virtualInstance) + if virtualInstance.Metadata ~= nil then + return not virtualInstance.Metadata.ignoreUnknownInstances else return true end diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 77d1c75b..4fdd7262 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -15,7 +15,7 @@ function Session.new(config) local self = { onError = config.onError, disconnected = false, - reconciler = nil, + reconciler = Reconciler.new(), api = api, } @@ -25,8 +25,6 @@ function Session.new(config) return Promise.resolve() end - self.reconciler = Reconciler.new(api.instanceMetadataMap) - return api:read({api.rootInstanceId}) :andThen(function(response) if self.disconnected then From 14ab85adbdacaec046344f3db3f00e5caa268595 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Jan 2019 17:05:27 -0800 Subject: [PATCH 0365/1504] Remove instanceMetadataMap from ApiContext --- plugin/src/ApiContext.lua | 2 -- 1 file changed, 2 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index a3e321cd..30f8c8b5 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -26,7 +26,6 @@ function ApiContext.new(baseUrl) baseUrl = baseUrl, serverId = nil, rootInstanceId = nil, - instanceMetadataMap = nil, messageCursor = -1, partitionRoutes = nil, } @@ -96,7 +95,6 @@ function ApiContext:connect() self.serverId = body.serverId self.partitionRoutes = body.partitions self.rootInstanceId = body.rootInstanceId - self.instanceMetadataMap = body.instanceMetadataMap end) end From a54364642a5df1fd54681df1031b1711b0ff3c34 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Jan 2019 18:21:01 -0800 Subject: [PATCH 0366/1504] Upgrade to rbx_tree and friends 0.1.0 --- Cargo.lock | 22 +++++++++++----------- server/Cargo.toml | 6 +++--- server/src/commands/build.rs | 9 +++++++++ server/src/rbx_session.rs | 6 +++--- server/src/rbx_snapshot.rs | 8 ++++---- server/src/web.rs | 4 ++-- 6 files changed, 32 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dec520e9..04fd0121 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1114,18 +1114,18 @@ dependencies = [ [[package]] name = "rbx_binary" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad#8442d57a7a21072a380134962724281d044c65ad" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)", + "rbx_tree 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_tree" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad#8442d57a7a21072a380134962724281d044c65ad" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1135,10 +1135,10 @@ dependencies = [ [[package]] name = "rbx_xml" version = "0.1.0" -source = "git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad#8442d57a7a21072a380134962724281d044c65ad" +source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)", + "rbx_tree 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1233,9 +1233,9 @@ dependencies = [ "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)", - "rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)", - "rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)", + "rbx_binary 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_tree 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1983,9 +1983,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rbx_binary 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)" = "" -"checksum rbx_tree 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)" = "" -"checksum rbx_xml 0.1.0 (git+https://github.com/LPGhatguy/rbx-tree.git?rev=8442d57a7a21072a380134962724281d044c65ad)" = "" +"checksum rbx_binary 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "646399297679f409cdc669b1b7b38a4f31cf97f1f5b6b2d56b5f03eaed8fa468" +"checksum rbx_tree 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea5723859bf48caa1ae9fdb94dbd24dd436d17543147081fca2862446bcaaec7" +"checksum rbx_xml 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdc27210e7e234f5af5af22f55c280a07fcc12566c37446d5b4fd0ae39ddea78" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" diff --git a/server/Cargo.toml b/server/Cargo.toml index ac3cf933..b4c4aa22 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -35,9 +35,9 @@ serde = "1.0" serde_derive = "1.0" serde_json = "1.0" uuid = { version = "0.7", features = ["v4", "serde"] } -rbx_tree = { rev = "8442d57a7a21072a380134962724281d044c65ad", git = "https://github.com/LPGhatguy/rbx-tree.git" } -rbx_xml = { rev = "8442d57a7a21072a380134962724281d044c65ad", git = "https://github.com/LPGhatguy/rbx-tree.git" } -rbx_binary = { rev = "8442d57a7a21072a380134962724281d044c65ad", git = "https://github.com/LPGhatguy/rbx-tree.git" } +rbx_tree = "0.1.0" +rbx_xml = "0.1.0" +rbx_binary = "0.1.0" [dev-dependencies] tempfile = "3.0" diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index 90a5981c..f488fae4 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -52,6 +52,9 @@ pub enum BuildError { #[fail(display = "XML model file error")] XmlModelEncodeError(rbx_xml::EncodeError), + + #[fail(display = "Binary model file error")] + BinaryModelEncodeError(rbx_binary::EncodeError) } impl From for BuildError { @@ -72,6 +75,12 @@ impl From for BuildError { } } +impl From for BuildError { + fn from(error: rbx_binary::EncodeError) -> BuildError { + BuildError::BinaryModelEncodeError(error) + } +} + pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let output_kind = options.output_kind .or_else(|| detect_output_kind(options)) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 071ced15..c8266c55 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -9,7 +9,7 @@ use std::{ use failure::Fail; -use rbx_tree::{RbxTree, RbxInstance, RbxValue, RbxId}; +use rbx_tree::{RbxTree, RbxInstanceProperties, RbxValue, RbxId}; use crate::{ project::{Project, ProjectNode, InstanceProjectNodeMetadata}, @@ -346,7 +346,7 @@ fn snapshot_xml_model<'a>( instance_name: Cow<'a, str>, file: &ImfsFile, ) -> Result>, SnapshotError> { - let mut temp_tree = RbxTree::new(RbxInstance { + let mut temp_tree = RbxTree::new(RbxInstanceProperties { name: "Temp".to_owned(), class_name: "Folder".to_owned(), properties: HashMap::new(), @@ -377,7 +377,7 @@ fn snapshot_binary_model<'a>( instance_name: Cow<'a, str>, file: &ImfsFile, ) -> Result>, SnapshotError> { - let mut temp_tree = RbxTree::new(RbxInstance { + let mut temp_tree = RbxTree::new(RbxInstanceProperties { name: "Temp".to_owned(), class_name: "Folder".to_owned(), properties: HashMap::new(), diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 4ffac64a..6d8387b1 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -6,7 +6,7 @@ use std::{ path::PathBuf, }; -use rbx_tree::{RbxTree, RbxId, RbxInstance, RbxValue}; +use rbx_tree::{RbxTree, RbxId, RbxInstanceProperties, RbxValue}; use crate::{ path_map::PathMap, @@ -159,14 +159,14 @@ pub fn reconcile_subtree( reconcile_instance_children(tree, id, snapshot, path_map, instance_metadata_map, changes); } -fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstance { +fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstanceProperties { let mut properties = HashMap::new(); for (key, value) in &snapshot.properties { properties.insert(key.clone(), value.clone()); } - let instance = RbxInstance { + let instance = RbxInstanceProperties { name: snapshot.name.to_string(), class_name: snapshot.class_name.to_string(), properties, @@ -175,7 +175,7 @@ fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstance { instance } -fn reconcile_instance_properties(instance: &mut RbxInstance, snapshot: &RbxSnapshotInstance) -> bool { +fn reconcile_instance_properties(instance: &mut RbxInstanceProperties, snapshot: &RbxSnapshotInstance) -> bool { let mut has_diffs = false; if instance.name != snapshot.name { diff --git a/server/src/web.rs b/server/src/web.rs index e02ae511..6700531a 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -10,7 +10,7 @@ use rouille::{ Request, Response, }; -use rbx_tree::{RbxId, RootedRbxInstance}; +use rbx_tree::{RbxId, RbxInstance}; use crate::{ session::Session, @@ -28,7 +28,7 @@ use crate::{ #[derive(Debug, Serialize, Deserialize)] pub struct InstanceWithMetadata<'a> { #[serde(flatten)] - pub instance: Cow<'a, RootedRbxInstance>, + pub instance: Cow<'a, RbxInstance>, #[serde(rename = "Metadata")] pub metadata: Option>, From a1395a382a5d458c29f2c03b0b27a332f89408a2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Jan 2019 18:23:10 -0800 Subject: [PATCH 0367/1504] Support semver metadata in plugin version --- plugin/src/Config.lua | 2 +- plugin/src/Version.lua | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 09cb5eb8..657e873e 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0}, + version = {0, 5, 0, "-alpha.0"}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/plugin/src/Version.lua b/plugin/src/Version.lua index 24483fa0..f7dd88f3 100644 --- a/plugin/src/Version.lua +++ b/plugin/src/Version.lua @@ -34,7 +34,13 @@ function Version.compare(a, b) end function Version.display(version) - return table.concat(version, ".") + local output = ("%d.%d.%d"):format(version[1], version[2], version[3]) + + if version[4] ~= nil then + output = output .. version[4] + end + + return output end -return Version +return Version \ No newline at end of file From c421fd0b253bf0a94f7b1833803049587c753d59 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Jan 2019 18:36:04 -0800 Subject: [PATCH 0368/1504] Add docs link for 0.5.x to complement 0.4.x --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f0804bfc..8ee5b6c6 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,10 @@ Latest server version - Rojo Documentation + Rojo Documentation + + + Rojo Documentation From b87943e39d8ccde1f67f110c7c71ab0859a27c72 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 15 Jan 2019 12:38:31 -0800 Subject: [PATCH 0369/1504] Clean up and document code throughout the server --- server/src/lib.rs | 1 - server/src/message_queue.rs | 4 +++ server/src/path_map.rs | 13 +++++-- server/src/project.rs | 69 ++++++++++++++++++++++--------------- server/src/roblox_studio.rs | 63 --------------------------------- server/src/visualize.rs | 3 ++ 6 files changed, 60 insertions(+), 93 deletions(-) delete mode 100644 server/src/roblox_studio.rs diff --git a/server/src/lib.rs b/server/src/lib.rs index d15c4d68..6b021803 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -7,7 +7,6 @@ extern crate serde_derive; #[cfg(test)] extern crate tempfile; -// pub mod roblox_studio; pub mod commands; pub mod fs_watcher; pub mod imfs; diff --git a/server/src/message_queue.rs b/server/src/message_queue.rs index dd86bc04..9eefb749 100644 --- a/server/src/message_queue.rs +++ b/server/src/message_queue.rs @@ -19,6 +19,10 @@ pub fn get_listener_id() -> ListenerId { ListenerId(LAST_ID.fetch_add(1, Ordering::SeqCst)) } +/// A message queue with persistent history that can be subscribed to. +/// +/// Definitely non-optimal, but a simple design that works well for the +/// synchronous web server Rojo uses, Rouille. #[derive(Default)] pub struct MessageQueue { messages: RwLock>, diff --git a/server/src/path_map.rs b/server/src/path_map.rs index b32302e2..a62e2c55 100644 --- a/server/src/path_map.rs +++ b/server/src/path_map.rs @@ -9,8 +9,9 @@ struct PathMapNode { children: HashSet, } -/// A map from paths to instance IDs, with a bit of additional data that enables -/// removing a path and all of its child paths from the tree more quickly. +/// A map from paths to another type, like instance IDs, with a bit of +/// additional data that enables removing a path and all of its child paths from +/// the tree more quickly. #[derive(Debug, Serialize)] pub struct PathMap { nodes: HashMap>, @@ -71,6 +72,14 @@ impl PathMap { Some(root_value) } + /// Traverses the route between `start_path` and `target_path` and returns + /// the path closest to `target_path` in the tree. + /// + /// This is useful when trying to determine what paths need to be marked as + /// altered when a change to a path is registered. Depending on the order of + /// FS events, a file remove event could be followed by that file's + /// directory being removed, in which case we should process that + /// directory's parent. pub fn descend(&self, start_path: &Path, target_path: &Path) -> PathBuf { let relative_path = target_path.strip_prefix(start_path) .expect("target_path did not begin with start_path"); diff --git a/server/src/project.rs b/server/src/project.rs index 6cfd147f..95b71402 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -12,7 +12,8 @@ use rbx_tree::RbxValue; pub static PROJECT_FILENAME: &'static str = "roblox-project.json"; -// Serde is silly. +// Methods used for Serde's default value system, which doesn't support using +// value literals directly, only functions that return values. const fn yeah() -> bool { true } @@ -21,6 +22,40 @@ const fn is_true(value: &bool) -> bool { *value } +/// SourceProject is the format that users author projects on-disk. Since we +/// want to do things like transforming paths to be absolute before handing them +/// off to the rest of Rojo, we use this intermediate struct. +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct SourceProject { + name: String, + tree: SourceProjectNode, + + #[serde(skip_serializing_if = "Option::is_none")] + serve_port: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + serve_place_ids: Option>, +} + +impl SourceProject { + /// Consumes the SourceProject and yields a Project, ready for prime-time. + pub fn into_project(self, project_file_location: &Path) -> Project { + let tree = self.tree.into_project_node(project_file_location); + + Project { + name: self.name, + tree, + serve_port: self.serve_port, + serve_place_ids: self.serve_place_ids, + file_location: PathBuf::from(project_file_location), + } + } +} + +/// Similar to SourceProject, the structure of nodes in the project tree is +/// slightly different on-disk than how we want to handle them in the rest of +/// Rojo. #[derive(Debug, Serialize, Deserialize)] #[serde(untagged)] enum SourceProjectNode { @@ -44,6 +79,7 @@ enum SourceProjectNode { } impl SourceProjectNode { + /// Consumes the SourceProjectNode and turns it into a ProjectNode. pub fn into_project_node(self, project_file_location: &Path) -> ProjectNode { match self { SourceProjectNode::Instance { class_name, mut children, properties, ignore_unknown_instances } => { @@ -78,31 +114,7 @@ impl SourceProjectNode { } } -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct SourceProject { - name: String, - tree: SourceProjectNode, - #[serde(skip_serializing_if = "Option::is_none")] - serve_port: Option, - #[serde(skip_serializing_if = "Option::is_none")] - serve_place_ids: Option>, -} - -impl SourceProject { - pub fn into_project(self, project_file_location: &Path) -> Project { - let tree = self.tree.into_project_node(project_file_location); - - Project { - name: self.name, - tree, - serve_port: self.serve_port, - serve_place_ids: self.serve_place_ids, - file_location: PathBuf::from(project_file_location), - } - } -} - +/// Error returned by Project::load_exact #[derive(Debug, Fail)] pub enum ProjectLoadExactError { #[fail(display = "IO error: {}", _0)] @@ -112,6 +124,7 @@ pub enum ProjectLoadExactError { JsonError(#[fail(cause)] serde_json::Error), } +/// Error returned by Project::load_fuzzy #[derive(Debug, Fail)] pub enum ProjectLoadFuzzyError { #[fail(display = "Project not found")] @@ -133,6 +146,7 @@ impl From for ProjectLoadFuzzyError { } } +/// Error returned by Project::init_place and Project::init_model #[derive(Debug, Fail)] pub enum ProjectInitError { AlreadyExists(PathBuf), @@ -150,6 +164,7 @@ impl fmt::Display for ProjectInitError { } } +/// Error returned by Project::save #[derive(Debug, Fail)] pub enum ProjectSaveError { #[fail(display = "JSON error: {}", _0)] @@ -340,7 +355,7 @@ impl Project { // TODO: Check for specific error kinds, convert 'not found' to Result. let location_metadata = fs::metadata(start_location).ok()?; - // If this is a file, we should assume it's the config we want + // If this is a file, assume it's the config the user was looking for. if location_metadata.is_file() { return Some(start_location.to_path_buf()); } else if location_metadata.is_dir() { diff --git a/server/src/roblox_studio.rs b/server/src/roblox_studio.rs deleted file mode 100644 index 195e86be..00000000 --- a/server/src/roblox_studio.rs +++ /dev/null @@ -1,63 +0,0 @@ -//! Interactions with Roblox Studio's installation, including its location and -//! mechanisms like PluginSettings. - -#![allow(dead_code)] - -use std::path::PathBuf; - -#[cfg(all(not(debug_assertions), not(feature = "bundle-plugin")))] -compile_error!("`bundle-plugin` feature must be set for release builds."); - -#[cfg(feature = "bundle-plugin")] -static PLUGIN_RBXM: &'static [u8] = include_bytes!("../target/plugin.rbxmx"); - -#[cfg(target_os = "windows")] -pub fn get_install_location() -> Option { - use std::env; - - let local_app_data = env::var("LocalAppData").ok()?; - let mut location = PathBuf::from(local_app_data); - - location.push("Roblox"); - - Some(location) -} - -#[cfg(target_os = "macos")] -pub fn get_install_location() -> Option { - unimplemented!(); -} - -#[cfg(not(any(target_os = "windows", target_os = "macos")))] -pub fn get_install_location() -> Option { - // Roblox Studio doesn't install on any other platforms! - None -} - -pub fn get_plugin_location() -> Option { - let mut location = get_install_location()?; - - location.push("Plugins/Rojo.rbxmx"); - - Some(location) -} - -#[cfg(feature = "bundle-plugin")] -pub fn install_bundled_plugin() -> Option<()> { - use std::fs::File; - use std::io::Write; - - info!("Installing plugin..."); - - let mut file = File::create(get_plugin_location()?).ok()?; - file.write_all(PLUGIN_RBXM).ok()?; - - Some(()) -} - -#[cfg(not(feature = "bundle-plugin"))] -pub fn install_bundled_plugin() -> Option<()> { - info!("Skipping plugin installation, bundle-plugin not set."); - - Some(()) -} \ No newline at end of file diff --git a/server/src/visualize.rs b/server/src/visualize.rs index 0a39212e..22f91591 100644 --- a/server/src/visualize.rs +++ b/server/src/visualize.rs @@ -25,6 +25,7 @@ digraph RojoTree { ]; "#; +/// Compiles DOT source to SVG by invoking dot on the command line. pub fn graphviz_to_svg(source: &str) -> String { let mut child = Command::new("dot") .arg("-Tsvg") @@ -42,6 +43,7 @@ pub fn graphviz_to_svg(source: &str) -> String { String::from_utf8(output.stdout).expect("Failed to parse stdout as UTF-8") } +/// A Display wrapper struct to visualize an RbxSession as SVG. pub struct VisualizeRbxSession<'a>(pub &'a RbxSession); impl<'a> fmt::Display for VisualizeRbxSession<'a> { @@ -81,6 +83,7 @@ fn visualize_rbx_node(session: &RbxSession, id: RbxId, output: &mut fmt::Formatt Ok(()) } +/// A Display wrapper struct to visualize an Imfs as SVG. pub struct VisualizeImfs<'a>(pub &'a Imfs); impl<'a> fmt::Display for VisualizeImfs<'a> { From 5b2a830d2d9095da359c68801810055e757d6dba Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 15 Jan 2019 12:43:02 -0800 Subject: [PATCH 0370/1504] Remove #[macro_use] from log crate --- server/src/bin.rs | 3 +-- server/src/commands/build.rs | 1 + server/src/commands/serve.rs | 1 + server/src/commands/upload.rs | 1 + server/src/fs_watcher.rs | 1 + server/src/lib.rs | 3 --- server/src/path_map.rs | 2 ++ server/src/rbx_session.rs | 2 +- server/src/web.rs | 1 + 9 files changed, 9 insertions(+), 6 deletions(-) diff --git a/server/src/bin.rs b/server/src/bin.rs index d57230d2..534d7c6a 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -1,11 +1,10 @@ -#[macro_use] extern crate log; - use std::{ path::{Path, PathBuf}, env, process, }; +use log::error; use clap::clap_app; use librojo::commands; diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index f488fae4..540650ce 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -4,6 +4,7 @@ use std::{ io, }; +use log::info; use failure::Fail; use crate::{ diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 3ed97e85..28d456db 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -3,6 +3,7 @@ use std::{ sync::Arc, }; +use log::info; use failure::Fail; use crate::{ diff --git a/server/src/commands/upload.rs b/server/src/commands/upload.rs index 70cdf0cd..950783e3 100644 --- a/server/src/commands/upload.rs +++ b/server/src/commands/upload.rs @@ -3,6 +3,7 @@ use std::{ io, }; +use log::info; use failure::Fail; use reqwest::header::{ACCEPT, USER_AGENT, CONTENT_TYPE, COOKIE}; diff --git a/server/src/fs_watcher.rs b/server/src/fs_watcher.rs index 9737aa4e..84741941 100644 --- a/server/src/fs_watcher.rs +++ b/server/src/fs_watcher.rs @@ -4,6 +4,7 @@ use std::{ thread, }; +use log::info; use notify::{ self, DebouncedEvent, diff --git a/server/src/lib.rs b/server/src/lib.rs index 6b021803..7fa923cf 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,6 +1,3 @@ -#[macro_use] -extern crate log; - #[macro_use] extern crate serde_derive; diff --git a/server/src/path_map.rs b/server/src/path_map.rs index a62e2c55..f205d9f4 100644 --- a/server/src/path_map.rs +++ b/server/src/path_map.rs @@ -3,6 +3,8 @@ use std::{ collections::{HashMap, HashSet}, }; +use log::warn; + #[derive(Debug, Serialize)] struct PathMapNode { value: T, diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index c8266c55..89c71173 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -7,8 +7,8 @@ use std::{ sync::{Arc, Mutex}, }; +use log::{info, trace}; use failure::Fail; - use rbx_tree::{RbxTree, RbxInstanceProperties, RbxValue, RbxId}; use crate::{ diff --git a/server/src/web.rs b/server/src/web.rs index 6700531a..4686950a 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -4,6 +4,7 @@ use std::{ sync::{mpsc, Arc}, }; +use log::trace; use rouille::{ self, router, From 9d3638fa46b97a438067348c556ebff399e67d51 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 15 Jan 2019 12:44:49 -0800 Subject: [PATCH 0371/1504] Remove remaining 'extern crate' declarations --- server/src/imfs.rs | 2 ++ server/src/lib.rs | 6 ------ server/src/path_map.rs | 1 + server/src/project.rs | 3 ++- server/src/rbx_session.rs | 1 + server/src/rbx_snapshot.rs | 1 + server/src/web.rs | 1 + 7 files changed, 8 insertions(+), 7 deletions(-) diff --git a/server/src/imfs.rs b/server/src/imfs.rs index 21f6be1e..08fe7157 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -5,6 +5,8 @@ use std::{ io, }; +use serde_derive::{Serialize, Deserialize}; + use crate::project::{Project, ProjectNode}; fn add_sync_points(imfs: &mut Imfs, project_node: &ProjectNode) -> io::Result<()> { diff --git a/server/src/lib.rs b/server/src/lib.rs index 7fa923cf..fb87682f 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,9 +1,3 @@ -#[macro_use] -extern crate serde_derive; - -#[cfg(test)] -extern crate tempfile; - pub mod commands; pub mod fs_watcher; pub mod imfs; diff --git a/server/src/path_map.rs b/server/src/path_map.rs index f205d9f4..cc9265c4 100644 --- a/server/src/path_map.rs +++ b/server/src/path_map.rs @@ -3,6 +3,7 @@ use std::{ collections::{HashMap, HashSet}, }; +use serde_derive::Serialize; use log::warn; #[derive(Debug, Serialize)] diff --git a/server/src/project.rs b/server/src/project.rs index 95b71402..e6c1509c 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -6,9 +6,10 @@ use std::{ path::{Path, PathBuf}, }; -use maplit::hashmap; use failure::Fail; +use maplit::hashmap; use rbx_tree::RbxValue; +use serde_derive::{Serialize, Deserialize}; pub static PROJECT_FILENAME: &'static str = "roblox-project.json"; diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 89c71173..23738af1 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -7,6 +7,7 @@ use std::{ sync::{Arc, Mutex}, }; +use serde_derive::{Serialize, Deserialize}; use log::{info, trace}; use failure::Fail; use rbx_tree::{RbxTree, RbxInstanceProperties, RbxValue, RbxId}; diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 6d8387b1..64c702c3 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -7,6 +7,7 @@ use std::{ }; use rbx_tree::{RbxTree, RbxId, RbxInstanceProperties, RbxValue}; +use serde_derive::{Serialize, Deserialize}; use crate::{ path_map::PathMap, diff --git a/server/src/web.rs b/server/src/web.rs index 4686950a..ee681269 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -4,6 +4,7 @@ use std::{ sync::{mpsc, Arc}, }; +use serde_derive::{Serialize, Deserialize}; use log::trace; use rouille::{ self, From aae1d8b34f8c5120a2adfc2ca7f241b454ae5adf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 15 Jan 2019 13:08:02 -0800 Subject: [PATCH 0372/1504] Add impl_from! macro to shorten up error code --- server/src/commands/build.rs | 29 ++++++----------------------- server/src/commands/init.rs | 8 +++----- server/src/commands/serve.rs | 8 +++----- server/src/commands/upload.rs | 29 ++++++----------------------- server/src/impl_from.rs | 18 ++++++++++++++++++ server/src/lib.rs | 5 +++++ 6 files changed, 41 insertions(+), 56 deletions(-) create mode 100644 server/src/impl_from.rs diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index 540650ce..14819b51 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -58,29 +58,12 @@ pub enum BuildError { BinaryModelEncodeError(rbx_binary::EncodeError) } -impl From for BuildError { - fn from(error: ProjectLoadFuzzyError) -> BuildError { - BuildError::ProjectLoadError(error) - } -} - -impl From for BuildError { - fn from(error: io::Error) -> BuildError { - BuildError::IoError(error) - } -} - -impl From for BuildError { - fn from(error: rbx_xml::EncodeError) -> BuildError { - BuildError::XmlModelEncodeError(error) - } -} - -impl From for BuildError { - fn from(error: rbx_binary::EncodeError) -> BuildError { - BuildError::BinaryModelEncodeError(error) - } -} +impl_from!(BuildError { + ProjectLoadFuzzyError => ProjectLoadError, + io::Error => IoError, + rbx_xml::EncodeError => XmlModelEncodeError, + rbx_binary::EncodeError => BinaryModelEncodeError +}); pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let output_kind = options.output_kind diff --git a/server/src/commands/init.rs b/server/src/commands/init.rs index 9bc5bd71..b4b0aa69 100644 --- a/server/src/commands/init.rs +++ b/server/src/commands/init.rs @@ -15,11 +15,9 @@ pub enum InitError { ProjectInitError(#[fail(cause)] ProjectInitError) } -impl From for InitError { - fn from(error: ProjectInitError) -> InitError { - InitError::ProjectInitError(error) - } -} +impl_from!(InitError { + ProjectInitError => ProjectInitError, +}); #[derive(Debug)] pub struct InitOptions<'a> { diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 28d456db..48567d2e 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -26,11 +26,9 @@ pub enum ServeError { ProjectLoadError(#[fail(cause)] ProjectLoadFuzzyError), } -impl From for ServeError { - fn from(error: ProjectLoadFuzzyError) -> ServeError { - ServeError::ProjectLoadError(error) - } -} +impl_from!(ServeError { + ProjectLoadFuzzyError => ProjectLoadError, +}); pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { info!("Looking for project at {}", options.fuzzy_project_path.display()); diff --git a/server/src/commands/upload.rs b/server/src/commands/upload.rs index 950783e3..229eae6c 100644 --- a/server/src/commands/upload.rs +++ b/server/src/commands/upload.rs @@ -35,29 +35,12 @@ pub enum UploadError { XmlModelEncodeError(rbx_xml::EncodeError), } -impl From for UploadError { - fn from(error: ProjectLoadFuzzyError) -> UploadError { - UploadError::ProjectLoadError(error) - } -} - -impl From for UploadError { - fn from(error: io::Error) -> UploadError { - UploadError::IoError(error) - } -} - -impl From for UploadError { - fn from(error: reqwest::Error) -> UploadError { - UploadError::HttpError(error) - } -} - -impl From for UploadError { - fn from(error: rbx_xml::EncodeError) -> UploadError { - UploadError::XmlModelEncodeError(error) - } -} +impl_from!(UploadError { + ProjectLoadFuzzyError => ProjectLoadError, + io::Error => IoError, + reqwest::Error => HttpError, + rbx_xml::EncodeError => XmlModelEncodeError, +}); #[derive(Debug)] pub struct UploadOptions<'a> { diff --git a/server/src/impl_from.rs b/server/src/impl_from.rs new file mode 100644 index 00000000..eb26af42 --- /dev/null +++ b/server/src/impl_from.rs @@ -0,0 +1,18 @@ +/// Implements 'From' for a list of variants, intended for use with error enums +/// that are wrapping a number of errors from other methods. +#[macro_export] +macro_rules! impl_from { + ( + $enum_name: ident { + $($error_type: ty => $variant_name: ident),* $(,)* + } + ) => { + $( + impl From<$error_type> for $enum_name { + fn from(error: $error_type) -> $enum_name { + $enum_name::$variant_name(error) + } + } + )* + } +} \ No newline at end of file diff --git a/server/src/lib.rs b/server/src/lib.rs index fb87682f..aee18bc4 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,3 +1,8 @@ +// Macros +#[macro_use] +pub mod impl_from; + +// Other modules pub mod commands; pub mod fs_watcher; pub mod imfs; From 249aa999a3ccba5b141177e77e830c37eccdda61 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 15 Jan 2019 17:26:51 -0800 Subject: [PATCH 0373/1504] Refactor mostly complete --- server/src/lib.rs | 1 + server/src/rbx_session.rs | 2 +- server/src/rbx_snapshot.rs | 609 +++++++++++++++++------------- server/src/session.rs | 2 +- server/src/snapshot_reconciler.rs | 308 +++++++++++++++ server/src/web.rs | 2 +- 6 files changed, 664 insertions(+), 260 deletions(-) create mode 100644 server/src/snapshot_reconciler.rs diff --git a/server/src/lib.rs b/server/src/lib.rs index aee18bc4..2848092d 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -13,6 +13,7 @@ pub mod rbx_session; pub mod rbx_snapshot; pub mod session; pub mod session_id; +pub mod snapshot_reconciler; pub mod visualize; pub mod web; pub mod web_util; \ No newline at end of file diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 23738af1..7b740f09 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -17,7 +17,7 @@ use crate::{ message_queue::MessageQueue, imfs::{Imfs, ImfsItem, ImfsFile}, path_map::PathMap, - rbx_snapshot::{RbxSnapshotInstance, InstanceChanges, snapshot_from_tree, reify_root, reconcile_subtree}, + snapshot_reconciler::{RbxSnapshotInstance, InstanceChanges, snapshot_from_tree, reify_root, reconcile_subtree}, }; const INIT_SCRIPT: &str = "init.lua"; diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 64c702c3..3ccc4926 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -1,308 +1,403 @@ use std::{ - str, borrow::Cow, - collections::{HashMap, HashSet}, + collections::HashMap, fmt, - path::PathBuf, + path::{Path, PathBuf}, + str, }; -use rbx_tree::{RbxTree, RbxId, RbxInstanceProperties, RbxValue}; use serde_derive::{Serialize, Deserialize}; +use maplit::hashmap; +use rbx_tree::RbxValue; +use failure::Fail; use crate::{ - path_map::PathMap, - project::InstanceProjectNodeMetadata, + imfs::{ + Imfs, + ImfsItem, + ImfsFile, + ImfsDirectory, + }, + project::{ + Project, + ProjectNode, + InstanceProjectNode, + SyncPointProjectNode, + }, + snapshot_reconciler::RbxSnapshotInstance, }; -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -pub struct InstanceChanges { - pub added: HashSet, - pub removed: HashSet, - pub updated: HashSet, +const INIT_MODULE_NAME: &str = "init.lua"; +const INIT_SERVER_NAME: &str = "init.server.lua"; +const INIT_CLIENT_NAME: &str = "init.client.lua"; + +pub type SnapshotResult<'a> = Result>, SnapshotError>; + +pub struct SnapshotMetadata<'meta> { + sync_point_names: &'meta mut HashMap, } -impl fmt::Display for InstanceChanges { +#[derive(Debug, Fail)] +pub enum SnapshotError { + DidNotExist(PathBuf), + + Utf8Error { + #[fail(cause)] + inner: str::Utf8Error, + path: PathBuf, + }, + + XmlModelDecodeError { + inner: rbx_xml::DecodeError, + path: PathBuf, + }, + + BinaryModelDecodeError { + inner: rbx_binary::DecodeError, + path: PathBuf, + }, +} + +impl fmt::Display for SnapshotError { fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - writeln!(output, "InstanceChanges {{")?; - - if !self.added.is_empty() { - writeln!(output, " Added:")?; - for id in &self.added { - writeln!(output, " {}", id)?; - } + match self { + SnapshotError::DidNotExist(path) => write!(output, "Path did not exist: {}", path.display()), + SnapshotError::Utf8Error { inner, path } => { + write!(output, "Invalid UTF-8: {} in path {}", inner, path.display()) + }, + SnapshotError::XmlModelDecodeError { inner, path } => { + write!(output, "Malformed rbxmx model: {:?} in path {}", inner, path.display()) + }, + SnapshotError::BinaryModelDecodeError { inner, path } => { + write!(output, "Malformed rbxm model: {:?} in path {}", inner, path.display()) + }, } - - if !self.removed.is_empty() { - writeln!(output, " Removed:")?; - for id in &self.removed { - writeln!(output, " {}", id)?; - } - } - - if !self.updated.is_empty() { - writeln!(output, " Updated:")?; - for id in &self.updated { - writeln!(output, " {}", id)?; - } - } - - writeln!(output, "}}") } } -impl InstanceChanges { - pub fn is_empty(&self) -> bool { - self.added.is_empty() && self.removed.is_empty() && self.updated.is_empty() +pub fn snapshot_project_tree<'source>( + imfs: &'source Imfs, + metadata: &mut SnapshotMetadata, + project: &'source Project, +) -> SnapshotResult<'source> { + snapshot_project_node(imfs, metadata, &project.tree, &project.name) +} + +fn snapshot_project_node<'source>( + imfs: &'source Imfs, + metadata: &mut SnapshotMetadata, + node: &'source ProjectNode, + instance_name: &'source str, +) -> SnapshotResult<'source> { + match node { + ProjectNode::Instance(instance_node) => snapshot_instance_node(imfs, metadata, instance_node, instance_name), + ProjectNode::SyncPoint(sync_node) => snapshot_sync_point_node(imfs, metadata, sync_node, instance_name), } } -#[derive(Debug)] -pub struct RbxSnapshotInstance<'a> { - pub name: Cow<'a, str>, - pub class_name: Cow<'a, str>, - pub properties: HashMap, - pub children: Vec>, - pub source_path: Option, - pub metadata: Option, -} - -pub fn snapshot_from_tree(tree: &RbxTree, id: RbxId) -> Option> { - let instance = tree.get_instance(id)?; - +fn snapshot_instance_node<'source>( + imfs: &'source Imfs, + metadata: &mut SnapshotMetadata, + node: &'source InstanceProjectNode, + instance_name: &'source str, +) -> SnapshotResult<'source> { let mut children = Vec::new(); - for &child_id in instance.get_children_ids() { - children.push(snapshot_from_tree(tree, child_id)?); + + for (child_name, child_project_node) in &node.children { + if let Some(child) = snapshot_project_node(imfs, metadata, child_project_node, child_name)? { + children.push(child); + } } - Some(RbxSnapshotInstance { - name: Cow::Owned(instance.name.to_owned()), - class_name: Cow::Owned(instance.class_name.to_owned()), - properties: instance.properties.clone(), + Ok(Some(RbxSnapshotInstance { + class_name: Cow::Borrowed(&node.class_name), + name: Cow::Borrowed(instance_name), + properties: node.properties.clone(), children, source_path: None, - metadata: None, - }) + metadata: Some(node.metadata.clone()), + })) } -pub fn reify_root( - snapshot: &RbxSnapshotInstance, - path_map: &mut PathMap, - instance_metadata_map: &mut HashMap, - changes: &mut InstanceChanges, -) -> RbxTree { - let instance = reify_core(snapshot); - let mut tree = RbxTree::new(instance); - let root_id = tree.get_root_id(); - - if let Some(source_path) = &snapshot.source_path { - path_map.insert(source_path.clone(), root_id); - } - - if let Some(metadata) = &snapshot.metadata { - instance_metadata_map.insert(root_id, metadata.clone()); - } - - changes.added.insert(root_id); - - for child in &snapshot.children { - reify_subtree(child, &mut tree, root_id, path_map, instance_metadata_map, changes); - } - - tree -} - -pub fn reify_subtree( - snapshot: &RbxSnapshotInstance, - tree: &mut RbxTree, - parent_id: RbxId, - path_map: &mut PathMap, - instance_metadata_map: &mut HashMap, - changes: &mut InstanceChanges, -) { - let instance = reify_core(snapshot); - let id = tree.insert_instance(instance, parent_id); - - if let Some(source_path) = &snapshot.source_path { - path_map.insert(source_path.clone(), id); - } - - if let Some(metadata) = &snapshot.metadata { - instance_metadata_map.insert(id, metadata.clone()); - } - - changes.added.insert(id); - - for child in &snapshot.children { - reify_subtree(child, tree, id, path_map, instance_metadata_map, changes); - } -} - -pub fn reconcile_subtree( - tree: &mut RbxTree, - id: RbxId, - snapshot: &RbxSnapshotInstance, - path_map: &mut PathMap, - instance_metadata_map: &mut HashMap, - changes: &mut InstanceChanges, -) { - if let Some(source_path) = &snapshot.source_path { - path_map.insert(source_path.clone(), id); - } - - if let Some(metadata) = &snapshot.metadata { - instance_metadata_map.insert(id, metadata.clone()); - } - - if reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot) { - changes.updated.insert(id); - } - - reconcile_instance_children(tree, id, snapshot, path_map, instance_metadata_map, changes); -} - -fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstanceProperties { - let mut properties = HashMap::new(); - - for (key, value) in &snapshot.properties { - properties.insert(key.clone(), value.clone()); - } - - let instance = RbxInstanceProperties { - name: snapshot.name.to_string(), - class_name: snapshot.class_name.to_string(), - properties, +fn snapshot_sync_point_node<'source>( + imfs: &'source Imfs, + metadata: &mut SnapshotMetadata, + node: &'source SyncPointProjectNode, + instance_name: &'source str, +) -> SnapshotResult<'source> { + // If the snapshot resulted in no instances, like if it targets an unknown + // file or an empty model file, we can early-return. + let mut snapshot = match snapshot_imfs_path(imfs, metadata, &node.path)? { + Some(snapshot) => snapshot, + None => return Ok(None), }; - instance + // Otherwise, we can mutate the snapshot we got back and track some extra + // metadata. + snapshot.name = Cow::Borrowed(instance_name); + metadata.sync_point_names.insert(node.path.to_owned(), instance_name.to_owned()); + + Ok(Some(snapshot)) } -fn reconcile_instance_properties(instance: &mut RbxInstanceProperties, snapshot: &RbxSnapshotInstance) -> bool { - let mut has_diffs = false; - - if instance.name != snapshot.name { - instance.name = snapshot.name.to_string(); - has_diffs = true; +fn snapshot_imfs_path<'source>( + imfs: &'source Imfs, + metadata: &mut SnapshotMetadata, + path: &Path +) -> SnapshotResult<'source> { + // If the given path doesn't exist in the in-memory filesystem, we consider + // that an error. + match imfs.get(path) { + Some(imfs_item) => snapshot_imfs_item(imfs, metadata, imfs_item), + None => return Err(SnapshotError::DidNotExist(path.to_owned())), } - - if instance.class_name != snapshot.class_name { - instance.class_name = snapshot.class_name.to_string(); - has_diffs = true; - } - - let mut property_updates = HashMap::new(); - - for (key, instance_value) in &instance.properties { - match snapshot.properties.get(key) { - Some(snapshot_value) => { - if snapshot_value != instance_value { - property_updates.insert(key.clone(), Some(snapshot_value.clone())); - } - }, - None => { - property_updates.insert(key.clone(), None); - }, - } - } - - for (key, snapshot_value) in &snapshot.properties { - if property_updates.contains_key(key) { - continue; - } - - match instance.properties.get(key) { - Some(instance_value) => { - if snapshot_value != instance_value { - property_updates.insert(key.clone(), Some(snapshot_value.clone())); - } - }, - None => { - property_updates.insert(key.clone(), Some(snapshot_value.clone())); - }, - } - } - - has_diffs = has_diffs || !property_updates.is_empty(); - - for (key, change) in property_updates.drain() { - match change { - Some(value) => instance.properties.insert(key, value), - None => instance.properties.remove(&key), - }; - } - - has_diffs } -fn reconcile_instance_children( - tree: &mut RbxTree, - id: RbxId, - snapshot: &RbxSnapshotInstance, - path_map: &mut PathMap, - instance_metadata_map: &mut HashMap, - changes: &mut InstanceChanges, -) { - let mut visited_snapshot_indices = HashSet::new(); +fn snapshot_imfs_item<'source>( + imfs: &'source Imfs, + metadata: &mut SnapshotMetadata, + item: &'source ImfsItem, +) -> SnapshotResult<'source> { + match item { + ImfsItem::File(file) => snapshot_imfs_file(imfs, metadata, file), + ImfsItem::Directory(directory) => snapshot_imfs_directory(imfs, metadata, directory), + } +} - let mut children_to_update: Vec<(RbxId, &RbxSnapshotInstance)> = Vec::new(); - let mut children_to_add: Vec<&RbxSnapshotInstance> = Vec::new(); - let mut children_to_remove: Vec = Vec::new(); +fn snapshot_imfs_directory<'source>( + imfs: &'source Imfs, + metadata: &mut SnapshotMetadata, + directory: &'source ImfsDirectory, +) -> SnapshotResult<'source> { + let init_path = directory.path.join(INIT_MODULE_NAME); + let init_server_path = directory.path.join(INIT_SERVER_NAME); + let init_client_path = directory.path.join(INIT_CLIENT_NAME); - let children_ids = tree.get_instance(id).unwrap().get_children_ids(); - - // Find all instances that were removed or updated, which we derive by - // trying to pair up existing instances to snapshots. - for &child_id in children_ids { - let child_instance = tree.get_instance(child_id).unwrap(); - - // Locate a matching snapshot for this instance - let mut matching_snapshot = None; - for (snapshot_index, child_snapshot) in snapshot.children.iter().enumerate() { - if visited_snapshot_indices.contains(&snapshot_index) { - continue; - } - - // We assume that instances with the same name are probably pretty - // similar. This heuristic is similar to React's reconciliation - // strategy. - if child_snapshot.name == child_instance.name { - visited_snapshot_indices.insert(snapshot_index); - matching_snapshot = Some(child_snapshot); - break; - } + let mut snapshot = if directory.children.contains(&init_path) { + snapshot_imfs_path(imfs, metadata, &init_path)?.unwrap() + } else if directory.children.contains(&init_server_path) { + snapshot_imfs_path(imfs, metadata, &init_server_path)?.unwrap() + } else if directory.children.contains(&init_client_path) { + snapshot_imfs_path(imfs, metadata, &init_client_path)?.unwrap() + } else { + RbxSnapshotInstance { + class_name: Cow::Borrowed("Folder"), + name: Cow::Borrowed(""), + properties: HashMap::new(), + children: Vec::new(), + source_path: Some(directory.path.clone()), + metadata: None, } + }; - match matching_snapshot { - Some(child_snapshot) => { - children_to_update.push((child_instance.get_id(), child_snapshot)); + // We have to be careful not to lose instance names that are specified in + // the project manifest. We store them in sync_point_names when the original + // tree is constructed. + snapshot.name = if let Some(actual_name) = metadata.sync_point_names.get(&directory.path) { + Cow::Owned(actual_name.clone()) + } else { + Cow::Borrowed(directory.path + .file_name().expect("Could not extract file name") + .to_str().expect("Could not convert path to UTF-8")) + }; + + for child_path in &directory.children { + let child_name = child_path + .file_name().expect("Couldn't extract file name") + .to_str().expect("Couldn't convert file name to UTF-8"); + + match child_name { + INIT_MODULE_NAME | INIT_SERVER_NAME | INIT_CLIENT_NAME => { + // The existence of files with these names modifies the + // parent instance and is handled above, so we can skip + // them here. }, - None => { - children_to_remove.push(child_instance.get_id()); + _ => { + if let Some(child) = snapshot_imfs_path(imfs, metadata, child_path)? { + snapshot.children.push(child); + } }, } } - // Find all instancs that were added, which is just the snapshots we didn't - // match up to existing instances above. - for (snapshot_index, child_snapshot) in snapshot.children.iter().enumerate() { - if !visited_snapshot_indices.contains(&snapshot_index) { - children_to_add.push(child_snapshot); + Ok(Some(snapshot)) +} + +fn snapshot_imfs_file<'source>( + imfs: &'source Imfs, + metadata: &mut SnapshotMetadata, + file: &'source ImfsFile, +) -> SnapshotResult<'source> { + let extension = file.path.extension() + .map(|v| v.to_str().expect("Could not convert extension to UTF-8")); + + let mut maybe_snapshot = match extension { + Some("lua") => snapshot_lua_file(metadata, file)?, + Some("csv") => snapshot_csv_file(metadata, file)?, + Some("txt") => snapshot_txt_file(metadata, file)?, + Some("rbxmx") => snapshot_xml_model_file(metadata, file)?, + Some("rbxm") => snapshot_binary_model_file(metadata, file)?, + Some(_) | None => return Ok(None), + }; + + if let Some(snapshot) = maybe_snapshot.as_mut() { + // Carefully preserve name from project manifest if present. + if let Some(actual_name) = metadata.sync_point_names.get(&file.path) { + snapshot.name = Cow::Owned(actual_name.clone()); } } - for child_snapshot in &children_to_add { - reify_subtree(child_snapshot, tree, id, path_map, instance_metadata_map, changes); - } + Ok(maybe_snapshot) +} - for child_id in &children_to_remove { - if let Some(subtree) = tree.remove_instance(*child_id) { - for id in subtree.iter_all_ids() { - instance_metadata_map.remove(&id); - changes.removed.insert(id); - } +fn snapshot_lua_file<'source>( + metadata: &mut SnapshotMetadata, + file: &'source ImfsFile, +) -> SnapshotResult<'source> { + let file_name = file.path + .file_name().expect("Could not extract file stem") + .to_str().expect("Could not convert path to UTF-8"); + + let (instance_name, class_name) = if let Some(name) = match_trailing(file_name, ".server.lua") { + (name, "Script") + } else if let Some(name) = match_trailing(file_name, ".client.lua") { + (name, "LocalScript") + } else { + (file_name, "ModuleScript") + }; + + let contents = str::from_utf8(&file.contents) + .map_err(|inner| SnapshotError::Utf8Error { + inner, + path: file.path.to_path_buf(), + })?; + + Ok(Some(RbxSnapshotInstance { + name: Cow::Borrowed(instance_name), + class_name: Cow::Borrowed(class_name), + properties: hashmap! { + "Source".to_owned() => RbxValue::String { + value: contents.to_owned(), + }, + }, + children: Vec::new(), + metadata: None, + source_path: Some(file.path.to_path_buf()), + })) +} + +fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { + if input.ends_with(trailer) { + let end = input.len().saturating_sub(trailer.len()); + Some(&input[..end]) + } else { + None + } +} + +fn snapshot_txt_file<'source>( + metadata: &mut SnapshotMetadata, + file: &'source ImfsFile, +) -> SnapshotResult<'source> { + let instance_name = file.path + .file_stem().expect("Could not extract file stem") + .to_str().expect("Could not convert path to UTF-8"); + + let contents = str::from_utf8(&file.contents) + .map_err(|inner| SnapshotError::Utf8Error { + inner, + path: file.path.to_path_buf(), + })?; + + Ok(Some(RbxSnapshotInstance { + name: Cow::Borrowed(instance_name), + class_name: Cow::Borrowed("StringValue"), + properties: hashmap! { + "Value".to_owned() => RbxValue::String { + value: contents.to_owned(), + }, + }, + children: Vec::new(), + metadata: None, + source_path: Some(file.path.to_path_buf()), + })) +} + +fn snapshot_csv_file<'source>( + metadata: &mut SnapshotMetadata, + file: &'source ImfsFile, +) -> SnapshotResult<'source> { + let instance_name = file.path + .file_stem().expect("Could not extract file stem") + .to_str().expect("Could not convert path to UTF-8"); + + let entries: Vec = csv::Reader::from_reader(file.contents.as_slice()) + .deserialize() + // TODO: Propagate error upward instead of panicking + .map(|result| result.expect("Malformed localization table found!")) + .map(LocalizationEntryCsv::to_json) + .collect(); + + let table_contents = serde_json::to_string(&entries) + .expect("Could not encode JSON for localization table"); + + Ok(Some(RbxSnapshotInstance { + name: Cow::Borrowed(instance_name), + class_name: Cow::Borrowed("LocalizationTable"), + properties: hashmap! { + "Contents".to_owned() => RbxValue::String { + value: table_contents, + }, + }, + children: Vec::new(), + metadata: None, + source_path: Some(file.path.to_path_buf()), + })) +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +struct LocalizationEntryCsv { + key: String, + context: String, + example: String, + source: String, + #[serde(flatten)] + values: HashMap, +} + +impl LocalizationEntryCsv { + fn to_json(self) -> LocalizationEntryJson { + LocalizationEntryJson { + key: self.key, + context: self.context, + example: self.example, + source: self.source, + values: self.values, } } +} - for (child_id, child_snapshot) in &children_to_update { - reconcile_subtree(tree, *child_id, child_snapshot, path_map, instance_metadata_map, changes); - } +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +struct LocalizationEntryJson { + key: String, + context: String, + example: String, + source: String, + values: HashMap, +} + +fn snapshot_xml_model_file<'source>( + metadata: &mut SnapshotMetadata, + file: &'source ImfsFile, +) -> SnapshotResult<'source> { + unimplemented!() +} + +fn snapshot_binary_model_file<'source>( + metadata: &mut SnapshotMetadata, + file: &'source ImfsFile, +) -> SnapshotResult<'source> { + unimplemented!() } \ No newline at end of file diff --git a/server/src/session.rs b/server/src/session.rs index 76953e9f..025c26f8 100644 --- a/server/src/session.rs +++ b/server/src/session.rs @@ -9,7 +9,7 @@ use crate::{ imfs::Imfs, session_id::SessionId, rbx_session::RbxSession, - rbx_snapshot::InstanceChanges, + snapshot_reconciler::InstanceChanges, fs_watcher::FsWatcher, }; diff --git a/server/src/snapshot_reconciler.rs b/server/src/snapshot_reconciler.rs new file mode 100644 index 00000000..64c702c3 --- /dev/null +++ b/server/src/snapshot_reconciler.rs @@ -0,0 +1,308 @@ +use std::{ + str, + borrow::Cow, + collections::{HashMap, HashSet}, + fmt, + path::PathBuf, +}; + +use rbx_tree::{RbxTree, RbxId, RbxInstanceProperties, RbxValue}; +use serde_derive::{Serialize, Deserialize}; + +use crate::{ + path_map::PathMap, + project::InstanceProjectNodeMetadata, +}; + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct InstanceChanges { + pub added: HashSet, + pub removed: HashSet, + pub updated: HashSet, +} + +impl fmt::Display for InstanceChanges { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + writeln!(output, "InstanceChanges {{")?; + + if !self.added.is_empty() { + writeln!(output, " Added:")?; + for id in &self.added { + writeln!(output, " {}", id)?; + } + } + + if !self.removed.is_empty() { + writeln!(output, " Removed:")?; + for id in &self.removed { + writeln!(output, " {}", id)?; + } + } + + if !self.updated.is_empty() { + writeln!(output, " Updated:")?; + for id in &self.updated { + writeln!(output, " {}", id)?; + } + } + + writeln!(output, "}}") + } +} + +impl InstanceChanges { + pub fn is_empty(&self) -> bool { + self.added.is_empty() && self.removed.is_empty() && self.updated.is_empty() + } +} + +#[derive(Debug)] +pub struct RbxSnapshotInstance<'a> { + pub name: Cow<'a, str>, + pub class_name: Cow<'a, str>, + pub properties: HashMap, + pub children: Vec>, + pub source_path: Option, + pub metadata: Option, +} + +pub fn snapshot_from_tree(tree: &RbxTree, id: RbxId) -> Option> { + let instance = tree.get_instance(id)?; + + let mut children = Vec::new(); + for &child_id in instance.get_children_ids() { + children.push(snapshot_from_tree(tree, child_id)?); + } + + Some(RbxSnapshotInstance { + name: Cow::Owned(instance.name.to_owned()), + class_name: Cow::Owned(instance.class_name.to_owned()), + properties: instance.properties.clone(), + children, + source_path: None, + metadata: None, + }) +} + +pub fn reify_root( + snapshot: &RbxSnapshotInstance, + path_map: &mut PathMap, + instance_metadata_map: &mut HashMap, + changes: &mut InstanceChanges, +) -> RbxTree { + let instance = reify_core(snapshot); + let mut tree = RbxTree::new(instance); + let root_id = tree.get_root_id(); + + if let Some(source_path) = &snapshot.source_path { + path_map.insert(source_path.clone(), root_id); + } + + if let Some(metadata) = &snapshot.metadata { + instance_metadata_map.insert(root_id, metadata.clone()); + } + + changes.added.insert(root_id); + + for child in &snapshot.children { + reify_subtree(child, &mut tree, root_id, path_map, instance_metadata_map, changes); + } + + tree +} + +pub fn reify_subtree( + snapshot: &RbxSnapshotInstance, + tree: &mut RbxTree, + parent_id: RbxId, + path_map: &mut PathMap, + instance_metadata_map: &mut HashMap, + changes: &mut InstanceChanges, +) { + let instance = reify_core(snapshot); + let id = tree.insert_instance(instance, parent_id); + + if let Some(source_path) = &snapshot.source_path { + path_map.insert(source_path.clone(), id); + } + + if let Some(metadata) = &snapshot.metadata { + instance_metadata_map.insert(id, metadata.clone()); + } + + changes.added.insert(id); + + for child in &snapshot.children { + reify_subtree(child, tree, id, path_map, instance_metadata_map, changes); + } +} + +pub fn reconcile_subtree( + tree: &mut RbxTree, + id: RbxId, + snapshot: &RbxSnapshotInstance, + path_map: &mut PathMap, + instance_metadata_map: &mut HashMap, + changes: &mut InstanceChanges, +) { + if let Some(source_path) = &snapshot.source_path { + path_map.insert(source_path.clone(), id); + } + + if let Some(metadata) = &snapshot.metadata { + instance_metadata_map.insert(id, metadata.clone()); + } + + if reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot) { + changes.updated.insert(id); + } + + reconcile_instance_children(tree, id, snapshot, path_map, instance_metadata_map, changes); +} + +fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstanceProperties { + let mut properties = HashMap::new(); + + for (key, value) in &snapshot.properties { + properties.insert(key.clone(), value.clone()); + } + + let instance = RbxInstanceProperties { + name: snapshot.name.to_string(), + class_name: snapshot.class_name.to_string(), + properties, + }; + + instance +} + +fn reconcile_instance_properties(instance: &mut RbxInstanceProperties, snapshot: &RbxSnapshotInstance) -> bool { + let mut has_diffs = false; + + if instance.name != snapshot.name { + instance.name = snapshot.name.to_string(); + has_diffs = true; + } + + if instance.class_name != snapshot.class_name { + instance.class_name = snapshot.class_name.to_string(); + has_diffs = true; + } + + let mut property_updates = HashMap::new(); + + for (key, instance_value) in &instance.properties { + match snapshot.properties.get(key) { + Some(snapshot_value) => { + if snapshot_value != instance_value { + property_updates.insert(key.clone(), Some(snapshot_value.clone())); + } + }, + None => { + property_updates.insert(key.clone(), None); + }, + } + } + + for (key, snapshot_value) in &snapshot.properties { + if property_updates.contains_key(key) { + continue; + } + + match instance.properties.get(key) { + Some(instance_value) => { + if snapshot_value != instance_value { + property_updates.insert(key.clone(), Some(snapshot_value.clone())); + } + }, + None => { + property_updates.insert(key.clone(), Some(snapshot_value.clone())); + }, + } + } + + has_diffs = has_diffs || !property_updates.is_empty(); + + for (key, change) in property_updates.drain() { + match change { + Some(value) => instance.properties.insert(key, value), + None => instance.properties.remove(&key), + }; + } + + has_diffs +} + +fn reconcile_instance_children( + tree: &mut RbxTree, + id: RbxId, + snapshot: &RbxSnapshotInstance, + path_map: &mut PathMap, + instance_metadata_map: &mut HashMap, + changes: &mut InstanceChanges, +) { + let mut visited_snapshot_indices = HashSet::new(); + + let mut children_to_update: Vec<(RbxId, &RbxSnapshotInstance)> = Vec::new(); + let mut children_to_add: Vec<&RbxSnapshotInstance> = Vec::new(); + let mut children_to_remove: Vec = Vec::new(); + + let children_ids = tree.get_instance(id).unwrap().get_children_ids(); + + // Find all instances that were removed or updated, which we derive by + // trying to pair up existing instances to snapshots. + for &child_id in children_ids { + let child_instance = tree.get_instance(child_id).unwrap(); + + // Locate a matching snapshot for this instance + let mut matching_snapshot = None; + for (snapshot_index, child_snapshot) in snapshot.children.iter().enumerate() { + if visited_snapshot_indices.contains(&snapshot_index) { + continue; + } + + // We assume that instances with the same name are probably pretty + // similar. This heuristic is similar to React's reconciliation + // strategy. + if child_snapshot.name == child_instance.name { + visited_snapshot_indices.insert(snapshot_index); + matching_snapshot = Some(child_snapshot); + break; + } + } + + match matching_snapshot { + Some(child_snapshot) => { + children_to_update.push((child_instance.get_id(), child_snapshot)); + }, + None => { + children_to_remove.push(child_instance.get_id()); + }, + } + } + + // Find all instancs that were added, which is just the snapshots we didn't + // match up to existing instances above. + for (snapshot_index, child_snapshot) in snapshot.children.iter().enumerate() { + if !visited_snapshot_indices.contains(&snapshot_index) { + children_to_add.push(child_snapshot); + } + } + + for child_snapshot in &children_to_add { + reify_subtree(child_snapshot, tree, id, path_map, instance_metadata_map, changes); + } + + for child_id in &children_to_remove { + if let Some(subtree) = tree.remove_instance(*child_id) { + for id in subtree.iter_all_ids() { + instance_metadata_map.remove(&id); + changes.removed.insert(id); + } + } + } + + for (child_id, child_snapshot) in &children_to_update { + reconcile_subtree(tree, *child_id, child_snapshot, path_map, instance_metadata_map, changes); + } +} \ No newline at end of file diff --git a/server/src/web.rs b/server/src/web.rs index ee681269..c992e8ad 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -18,7 +18,7 @@ use crate::{ session::Session, session_id::SessionId, project::InstanceProjectNodeMetadata, - rbx_snapshot::InstanceChanges, + snapshot_reconciler::InstanceChanges, visualize::{VisualizeRbxSession, VisualizeImfs, graphviz_to_svg}, }; From 585806837e07320bddb990333c90646631c81929 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 15 Jan 2019 18:04:06 -0800 Subject: [PATCH 0374/1504] Port over to new snapshot system --- server/src/rbx_session.rs | 381 ++----------------------------------- server/src/rbx_snapshot.rs | 89 +++++++-- 2 files changed, 88 insertions(+), 382 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 7b740f09..1820424e 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -1,23 +1,20 @@ use std::{ - borrow::Cow, collections::HashMap, - fmt, path::{Path, PathBuf}, str, sync::{Arc, Mutex}, }; -use serde_derive::{Serialize, Deserialize}; use log::{info, trace}; -use failure::Fail; -use rbx_tree::{RbxTree, RbxInstanceProperties, RbxValue, RbxId}; +use rbx_tree::{RbxTree, RbxId}; use crate::{ - project::{Project, ProjectNode, InstanceProjectNodeMetadata}, + project::{Project, InstanceProjectNodeMetadata}, message_queue::MessageQueue, - imfs::{Imfs, ImfsItem, ImfsFile}, + imfs::{Imfs, ImfsItem}, path_map::PathMap, - snapshot_reconciler::{RbxSnapshotInstance, InstanceChanges, snapshot_from_tree, reify_root, reconcile_subtree}, + rbx_snapshot::{SnapshotMetadata, snapshot_project_tree, snapshot_imfs_path}, + snapshot_reconciler::{InstanceChanges, reify_root, reconcile_subtree}, }; const INIT_SCRIPT: &str = "init.lua"; @@ -45,7 +42,7 @@ impl RbxSession { let tree = { let temp_imfs = imfs.lock().unwrap(); - construct_initial_tree(&project, &temp_imfs, &mut path_map, &mut instance_metadata_map, &mut sync_point_names) + reify_initial_tree(&project, &temp_imfs, &mut path_map, &mut instance_metadata_map, &mut sync_point_names) }; RbxSession { @@ -83,7 +80,10 @@ impl RbxSession { trace!("Snapshotting path {}", path_to_snapshot.display()); - let maybe_snapshot = snapshot_instances_from_imfs(&imfs, &path_to_snapshot, &mut self.sync_point_names) + let mut snapshot_meta = SnapshotMetadata { + sync_point_names: &mut self.sync_point_names, + }; + let maybe_snapshot = snapshot_imfs_path(&imfs, &mut snapshot_meta, &path_to_snapshot) .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())); let snapshot = match maybe_snapshot { @@ -169,372 +169,25 @@ pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { let mut path_map = PathMap::new(); let mut instance_metadata_map = HashMap::new(); let mut sync_point_names = HashMap::new(); - construct_initial_tree(project, imfs, &mut path_map, &mut instance_metadata_map, &mut sync_point_names) + reify_initial_tree(project, imfs, &mut path_map, &mut instance_metadata_map, &mut sync_point_names) } -fn construct_initial_tree( +fn reify_initial_tree( project: &Project, imfs: &Imfs, path_map: &mut PathMap, instance_metadata_map: &mut HashMap, sync_point_names: &mut HashMap, ) -> RbxTree { - let snapshot = construct_project_node( - imfs, - &project.name, - &project.tree, + let mut meta = SnapshotMetadata { sync_point_names, - ); + }; + let snapshot = snapshot_project_tree(imfs, &mut meta, project) + .expect("Could not snapshot project tree") + .expect("Project did not produce any instances"); let mut changes = InstanceChanges::default(); let tree = reify_root(&snapshot, path_map, instance_metadata_map, &mut changes); tree -} - -fn construct_project_node<'a>( - imfs: &'a Imfs, - instance_name: &'a str, - project_node: &'a ProjectNode, - sync_point_names: &mut HashMap, -) -> RbxSnapshotInstance<'a> { - match project_node { - ProjectNode::Instance(node) => { - let mut children = Vec::new(); - - for (child_name, child_project_node) in &node.children { - children.push(construct_project_node(imfs, child_name, child_project_node, sync_point_names)); - } - - RbxSnapshotInstance { - class_name: Cow::Borrowed(&node.class_name), - name: Cow::Borrowed(instance_name), - properties: node.properties.clone(), - children, - source_path: None, - metadata: Some(node.metadata.clone()), - } - }, - ProjectNode::SyncPoint(node) => { - // TODO: Propagate errors upward instead of dying - let mut snapshot = snapshot_instances_from_imfs(imfs, &node.path, sync_point_names) - .expect("Could not reify nodes from Imfs") - .expect("Sync point node did not result in an instance"); - - snapshot.name = Cow::Borrowed(instance_name); - sync_point_names.insert(node.path.clone(), instance_name.to_string()); - - snapshot - }, - } -} - -#[derive(Debug, Clone, Copy)] -enum FileType { - ModuleScript, - ServerScript, - ClientScript, - StringValue, - LocalizationTable, - XmlModel, - BinaryModel, -} - -fn get_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { - if input.ends_with(trailer) { - let end = input.len().saturating_sub(trailer.len()); - Some(&input[..end]) - } else { - None - } -} - -fn classify_file(file: &ImfsFile) -> Option<(&str, FileType)> { - static EXTENSIONS_TO_TYPES: &[(&str, FileType)] = &[ - (".server.lua", FileType::ServerScript), - (".client.lua", FileType::ClientScript), - (".lua", FileType::ModuleScript), - (".csv", FileType::LocalizationTable), - (".txt", FileType::StringValue), - (".rbxmx", FileType::XmlModel), - (".rbxm", FileType::BinaryModel), - ]; - - let file_name = file.path.file_name()?.to_str()?; - - for (extension, file_type) in EXTENSIONS_TO_TYPES { - if let Some(instance_name) = get_trailing(file_name, extension) { - return Some((instance_name, *file_type)) - } - } - - None -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "PascalCase")] -struct LocalizationEntryCsv { - key: String, - context: String, - example: String, - source: String, - #[serde(flatten)] - values: HashMap, -} - -impl LocalizationEntryCsv { - fn to_json(self) -> LocalizationEntryJson { - LocalizationEntryJson { - key: self.key, - context: self.context, - example: self.example, - source: self.source, - values: self.values, - } - } -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct LocalizationEntryJson { - key: String, - context: String, - example: String, - source: String, - values: HashMap, -} - -#[derive(Debug, Fail)] -enum SnapshotError { - DidNotExist(PathBuf), - - // TODO: Add file path to the error message? - Utf8Error { - #[fail(cause)] - inner: str::Utf8Error, - path: PathBuf, - }, - - XmlModelDecodeError { - inner: rbx_xml::DecodeError, - path: PathBuf, - }, - - BinaryModelDecodeError { - inner: rbx_binary::DecodeError, - path: PathBuf, - }, -} - -impl fmt::Display for SnapshotError { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - match self { - SnapshotError::DidNotExist(path) => write!(output, "Path did not exist: {}", path.display()), - SnapshotError::Utf8Error { inner, path } => { - write!(output, "Invalid UTF-8: {} in path {}", inner, path.display()) - }, - SnapshotError::XmlModelDecodeError { inner, path } => { - write!(output, "Malformed rbxmx model: {:?} in path {}", inner, path.display()) - }, - SnapshotError::BinaryModelDecodeError { inner, path } => { - write!(output, "Malformed rbxm model: {:?} in path {}", inner, path.display()) - }, - } - } -} - -fn snapshot_xml_model<'a>( - instance_name: Cow<'a, str>, - file: &ImfsFile, -) -> Result>, SnapshotError> { - let mut temp_tree = RbxTree::new(RbxInstanceProperties { - name: "Temp".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), - }); - - let root_id = temp_tree.get_root_id(); - rbx_xml::decode(&mut temp_tree, root_id, file.contents.as_slice()) - .map_err(|inner| SnapshotError::XmlModelDecodeError { - inner, - path: file.path.clone(), - })?; - - let root_instance = temp_tree.get_instance(root_id).unwrap(); - let children = root_instance.get_children_ids(); - - match children.len() { - 0 => Ok(None), - 1 => { - let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); - snapshot.name = instance_name; - Ok(Some(snapshot)) - }, - _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), - } -} - -fn snapshot_binary_model<'a>( - instance_name: Cow<'a, str>, - file: &ImfsFile, -) -> Result>, SnapshotError> { - let mut temp_tree = RbxTree::new(RbxInstanceProperties { - name: "Temp".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), - }); - - let root_id = temp_tree.get_root_id(); - rbx_binary::decode(&mut temp_tree, root_id, file.contents.as_slice()) - .map_err(|inner| SnapshotError::BinaryModelDecodeError { - inner, - path: file.path.clone(), - })?; - - let root_instance = temp_tree.get_instance(root_id).unwrap(); - let children = root_instance.get_children_ids(); - - match children.len() { - 0 => Ok(None), - 1 => { - let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); - snapshot.name = instance_name; - Ok(Some(snapshot)) - }, - _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), - } -} - -fn snapshot_instances_from_imfs<'a>( - imfs: &'a Imfs, - imfs_path: &Path, - sync_point_names: &HashMap, -) -> Result>, SnapshotError> { - match imfs.get(imfs_path) { - Some(ImfsItem::File(file)) => { - let (instance_name, file_type) = match classify_file(file) { - Some(info) => info, - None => return Ok(None), - }; - - let instance_name = if let Some(actual_name) = sync_point_names.get(imfs_path) { - Cow::Owned(actual_name.clone()) - } else { - Cow::Borrowed(instance_name) - }; - - let class_name = match file_type { - FileType::ModuleScript => "ModuleScript", - FileType::ServerScript => "Script", - FileType::ClientScript => "LocalScript", - FileType::StringValue => "StringValue", - FileType::LocalizationTable => "LocalizationTable", - FileType::XmlModel => return snapshot_xml_model(instance_name, file), - FileType::BinaryModel => return snapshot_binary_model(instance_name, file), - }; - - let contents = str::from_utf8(&file.contents) - .map_err(|inner| SnapshotError::Utf8Error { - inner, - path: imfs_path.to_path_buf(), - })?; - - let mut properties = HashMap::new(); - - match file_type { - FileType::ModuleScript | FileType::ServerScript | FileType::ClientScript => { - properties.insert(String::from("Source"), RbxValue::String { - value: contents.to_string(), - }); - }, - FileType::StringValue => { - properties.insert(String::from("Value"), RbxValue::String { - value: contents.to_string(), - }); - }, - FileType::LocalizationTable => { - let entries: Vec = csv::Reader::from_reader(contents.as_bytes()) - .deserialize() - .map(|result| result.expect("Malformed localization table found!")) - .map(LocalizationEntryCsv::to_json) - .collect(); - - let table_contents = serde_json::to_string(&entries) - .expect("Could not encode JSON for localization table"); - - properties.insert(String::from("Contents"), RbxValue::String { - value: table_contents, - }); - }, - FileType::XmlModel | FileType::BinaryModel => unreachable!(), - } - - Ok(Some(RbxSnapshotInstance { - name: instance_name, - class_name: Cow::Borrowed(class_name), - properties, - children: Vec::new(), - source_path: Some(file.path.clone()), - metadata: None, - })) - }, - Some(ImfsItem::Directory(directory)) => { - // TODO: Expand init support to handle server and client scripts - let init_path = directory.path.join(INIT_SCRIPT); - let init_server_path = directory.path.join(INIT_SERVER_SCRIPT); - let init_client_path = directory.path.join(INIT_CLIENT_SCRIPT); - - let mut instance = if directory.children.contains(&init_path) { - snapshot_instances_from_imfs(imfs, &init_path, sync_point_names)? - .expect("Could not snapshot instance from file that existed!") - } else if directory.children.contains(&init_server_path) { - snapshot_instances_from_imfs(imfs, &init_server_path, sync_point_names)? - .expect("Could not snapshot instance from file that existed!") - } else if directory.children.contains(&init_client_path) { - snapshot_instances_from_imfs(imfs, &init_client_path, sync_point_names)? - .expect("Could not snapshot instance from file that existed!") - } else { - RbxSnapshotInstance { - class_name: Cow::Borrowed("Folder"), - name: Cow::Borrowed(""), - properties: HashMap::new(), - children: Vec::new(), - source_path: Some(directory.path.clone()), - metadata: None, - } - }; - - // We have to be careful not to lose instance names that are - // specified in the project manifest. We store them in - // sync_point_names when the original tree is constructed. - instance.name = if let Some(actual_name) = sync_point_names.get(&directory.path) { - Cow::Owned(actual_name.clone()) - } else { - Cow::Borrowed(directory.path - .file_name().expect("Could not extract file name") - .to_str().expect("Could not convert path to UTF-8")) - }; - - for child_path in &directory.children { - match child_path.file_name().unwrap().to_str().unwrap() { - INIT_SCRIPT | INIT_SERVER_SCRIPT | INIT_CLIENT_SCRIPT => { - // The existence of files with these names modifies the - // parent instance and is handled above, so we can skip - // them here. - }, - _ => { - match snapshot_instances_from_imfs(imfs, child_path, sync_point_names)? { - Some(child) => { - instance.children.push(child); - }, - None => {}, - } - }, - } - } - - Ok(Some(instance)) - }, - None => Err(SnapshotError::DidNotExist(imfs_path.to_path_buf())), - } } \ No newline at end of file diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 3ccc4926..35446f14 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -8,7 +8,7 @@ use std::{ use serde_derive::{Serialize, Deserialize}; use maplit::hashmap; -use rbx_tree::RbxValue; +use rbx_tree::{RbxTree, RbxValue, RbxInstanceProperties}; use failure::Fail; use crate::{ @@ -24,7 +24,10 @@ use crate::{ InstanceProjectNode, SyncPointProjectNode, }, - snapshot_reconciler::RbxSnapshotInstance, + snapshot_reconciler::{ + RbxSnapshotInstance, + snapshot_from_tree, + }, }; const INIT_MODULE_NAME: &str = "init.lua"; @@ -34,7 +37,7 @@ const INIT_CLIENT_NAME: &str = "init.client.lua"; pub type SnapshotResult<'a> = Result>, SnapshotError>; pub struct SnapshotMetadata<'meta> { - sync_point_names: &'meta mut HashMap, + pub sync_point_names: &'meta mut HashMap, } #[derive(Debug, Fail)] @@ -140,7 +143,7 @@ fn snapshot_sync_point_node<'source>( Ok(Some(snapshot)) } -fn snapshot_imfs_path<'source>( +pub fn snapshot_imfs_path<'source>( imfs: &'source Imfs, metadata: &mut SnapshotMetadata, path: &Path @@ -159,7 +162,7 @@ fn snapshot_imfs_item<'source>( item: &'source ImfsItem, ) -> SnapshotResult<'source> { match item { - ImfsItem::File(file) => snapshot_imfs_file(imfs, metadata, file), + ImfsItem::File(file) => snapshot_imfs_file(metadata, file), ImfsItem::Directory(directory) => snapshot_imfs_directory(imfs, metadata, directory), } } @@ -224,7 +227,6 @@ fn snapshot_imfs_directory<'source>( } fn snapshot_imfs_file<'source>( - imfs: &'source Imfs, metadata: &mut SnapshotMetadata, file: &'source ImfsFile, ) -> SnapshotResult<'source> { @@ -232,11 +234,11 @@ fn snapshot_imfs_file<'source>( .map(|v| v.to_str().expect("Could not convert extension to UTF-8")); let mut maybe_snapshot = match extension { - Some("lua") => snapshot_lua_file(metadata, file)?, - Some("csv") => snapshot_csv_file(metadata, file)?, - Some("txt") => snapshot_txt_file(metadata, file)?, - Some("rbxmx") => snapshot_xml_model_file(metadata, file)?, - Some("rbxm") => snapshot_binary_model_file(metadata, file)?, + Some("lua") => snapshot_lua_file(file)?, + Some("csv") => snapshot_csv_file(file)?, + Some("txt") => snapshot_txt_file(file)?, + Some("rbxmx") => snapshot_xml_model_file(file)?, + Some("rbxm") => snapshot_binary_model_file(file)?, Some(_) | None => return Ok(None), }; @@ -251,7 +253,6 @@ fn snapshot_imfs_file<'source>( } fn snapshot_lua_file<'source>( - metadata: &mut SnapshotMetadata, file: &'source ImfsFile, ) -> SnapshotResult<'source> { let file_name = file.path @@ -296,7 +297,6 @@ fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { } fn snapshot_txt_file<'source>( - metadata: &mut SnapshotMetadata, file: &'source ImfsFile, ) -> SnapshotResult<'source> { let instance_name = file.path @@ -324,7 +324,6 @@ fn snapshot_txt_file<'source>( } fn snapshot_csv_file<'source>( - metadata: &mut SnapshotMetadata, file: &'source ImfsFile, ) -> SnapshotResult<'source> { let instance_name = file.path @@ -389,15 +388,69 @@ struct LocalizationEntryJson { } fn snapshot_xml_model_file<'source>( - metadata: &mut SnapshotMetadata, file: &'source ImfsFile, ) -> SnapshotResult<'source> { - unimplemented!() + let instance_name = file.path + .file_stem().expect("Could not extract file stem") + .to_str().expect("Could not convert path to UTF-8"); + + let mut temp_tree = RbxTree::new(RbxInstanceProperties { + name: "Temp".to_owned(), + class_name: "Folder".to_owned(), + properties: HashMap::new(), + }); + + let root_id = temp_tree.get_root_id(); + rbx_xml::decode(&mut temp_tree, root_id, file.contents.as_slice()) + .map_err(|inner| SnapshotError::XmlModelDecodeError { + inner, + path: file.path.clone(), + })?; + + let root_instance = temp_tree.get_instance(root_id).unwrap(); + let children = root_instance.get_children_ids(); + + match children.len() { + 0 => Ok(None), + 1 => { + let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); + snapshot.name = Cow::Borrowed(instance_name); + Ok(Some(snapshot)) + }, + _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), + } } fn snapshot_binary_model_file<'source>( - metadata: &mut SnapshotMetadata, file: &'source ImfsFile, ) -> SnapshotResult<'source> { - unimplemented!() + let instance_name = file.path + .file_stem().expect("Could not extract file stem") + .to_str().expect("Could not convert path to UTF-8"); + + let mut temp_tree = RbxTree::new(RbxInstanceProperties { + name: "Temp".to_owned(), + class_name: "Folder".to_owned(), + properties: HashMap::new(), + }); + + let root_id = temp_tree.get_root_id(); + rbx_binary::decode(&mut temp_tree, root_id, file.contents.as_slice()) + .map_err(|inner| SnapshotError::BinaryModelDecodeError { + inner, + path: file.path.clone(), + })?; + + let root_instance = temp_tree.get_instance(root_id).unwrap(); + let children = root_instance.get_children_ids(); + + match children.len() { + 0 => Ok(None), + 1 => { + let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); + snapshot.name = Cow::Borrowed(instance_name); + Ok(Some(snapshot)) + }, + _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), + } } \ No newline at end of file From a400abff4cbd9295a079367a22b12d66dba50b22 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 15 Jan 2019 23:58:10 -0800 Subject: [PATCH 0375/1504] Switch assets to use custom rounded rectangle --- assets/round-rect-8px-radius-2px-border.png | Bin 0 -> 513 bytes plugin/src/Assets.lua | 20 ++++-------------- plugin/src/Components/ConnectPanel.lua | 19 +++++++++-------- .../src/Components/ConnectionActivePanel.lua | 10 ++++----- plugin/src/Components/FormButton.lua | 13 +++++++----- plugin/src/Components/FormTextInput.lua | 13 ++++++------ 6 files changed, 34 insertions(+), 41 deletions(-) create mode 100644 assets/round-rect-8px-radius-2px-border.png diff --git a/assets/round-rect-8px-radius-2px-border.png b/assets/round-rect-8px-radius-2px-border.png new file mode 100644 index 0000000000000000000000000000000000000000..9c976f19eed6397143f175e1acd3e27614c5e98d GIT binary patch literal 513 zcmV+c0{;DpP)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ-he+}YsB)>a`slY1mZ%DG5Vha|@cY!PyY zz_7&_!Y&5)!n*{S87qw(%(R1@6#go~5Bi>d)I8z6r=OxIegK!i1#k)^92WxAQN+Lva1BU?NekQqYh%p&CqO8F0+vDulu~3_MjXdTc^pgIwlqycUDsG^ z2@ie&E{rivcl#}{jG_pwHF=(srs>h;08&cQG$qe-wAMsX1aKaVkOer;ZIY5#mD5U^qz@-FM09lqXR(f443CugPvC`|BOCSai zLW~B`>xv~`oC#n8m;fe#319-403^@=9QwhKY1_6t{*yr(aL$be&@@eV{40a8P}lWn z0KKkf2|NOOYwajoaL!?^1=s@*(ipP=?!5O@RW&GtbB?O2y8m`(jM+qCwg%32yWO%Z z%dymK{e9&0K+hMzRS=draB^hnf8Y=B9Q1tCAASq~I)kR17F-$$00000NkvXXu0mjf D0CmUZ literal 0 HcmV?d00001 diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index b73955ab..ad0b4ee5 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -9,22 +9,10 @@ local Assets = { }, }, Slices = { - GrayBox = { - asset = sheetAsset, - offset = Vector2.new(147, 433), - size = Vector2.new(38, 36), - center = Rect.new(8, 8, 9, 9), - }, - GrayButton02 = { - asset = sheetAsset, - offset = Vector2.new(0, 98), - size = Vector2.new(190, 45), - center = Rect.new(16, 16, 17, 17), - }, - GrayButton07 = { - asset = sheetAsset, - offset = Vector2.new(195, 0), - size = Vector2.new(49, 49), + RoundBox = { + asset = "rbxassetid://2754309674", + offset = Vector2.new(0, 0), + size = Vector2.new(0, 0), center = Rect.new(16, 16, 17, 17), }, }, diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index adbd8710..1bf7735d 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -12,7 +12,7 @@ local FormButton = require(Plugin.Components.FormButton) local FormTextInput = require(Plugin.Components.FormTextInput) local WhiteCross = Assets.Sprites.WhiteCross -local GrayBox = Assets.Slices.GrayBox +local RoundBox = Assets.Slices.RoundBox local e = Roact.createElement @@ -52,11 +52,11 @@ function ConnectPanel:render() return e(FitList, { containerKind = "ImageLabel", containerProps = { - Image = GrayBox.asset, - ImageRectOffset = GrayBox.offset, - ImageRectSize = GrayBox.size, + Image = RoundBox.asset, + ImageRectOffset = RoundBox.offset, + ImageRectSize = RoundBox.size, + SliceCenter = RoundBox.center, ScaleType = Enum.ScaleType.Slice, - SliceCenter = GrayBox.center, BackgroundTransparency = 1, Position = UDim2.new(0.5, 0, 0.5, 0), AnchorPoint = Vector2.new(0.5, 0.5), @@ -135,7 +135,7 @@ function ConnectPanel:render() }, }, { Label = e(FitText, { - MinSize = Vector2.new(0, 24), + MinSize = Vector2.new(0, 28), Kind = "TextLabel", LayoutOrder = 1, BackgroundTransparency = 1, @@ -156,7 +156,7 @@ function ConnectPanel:render() Input = e(FormTextInput, { layoutOrder = 2, - size = UDim2.new(0, 300, 0, 24), + size = UDim2.new(0, 300, 0, 28), value = self.state.address, onValueChange = function(newValue) self:setState({ @@ -177,7 +177,7 @@ function ConnectPanel:render() }, }, { Label = e(FitText, { - MinSize = Vector2.new(0, 24), + MinSize = Vector2.new(0, 28), Kind = "TextLabel", LayoutOrder = 1, BackgroundTransparency = 1, @@ -198,7 +198,7 @@ function ConnectPanel:render() Input = e(FormTextInput, { layoutOrder = 2, - size = UDim2.new(0, 300, 0, 24), + size = UDim2.new(0, 300, 0, 28), value = self.state.port, onValueChange = function(newValue) self:setState({ @@ -234,6 +234,7 @@ function ConnectPanel:render() cancel() end end, + secondary = true, }), }) }) diff --git a/plugin/src/Components/ConnectionActivePanel.lua b/plugin/src/Components/ConnectionActivePanel.lua index 846a10ce..b1d766b6 100644 --- a/plugin/src/Components/ConnectionActivePanel.lua +++ b/plugin/src/Components/ConnectionActivePanel.lua @@ -7,7 +7,7 @@ local FitText = require(script.Parent.FitText) local e = Roact.createElement -local GrayBox = Assets.Slices.GrayBox +local RoundBox = Assets.Slices.RoundBox local ConnectionActivePanel = Roact.Component:extend("ConnectionActivePanel") @@ -15,10 +15,10 @@ function ConnectionActivePanel:render() return e(FitList, { containerKind = "ImageButton", containerProps = { - Image = GrayBox.asset, - ImageRectOffset = GrayBox.offset, - ImageRectSize = GrayBox.size, - SliceCenter = GrayBox.center, + Image = RoundBox.asset, + ImageRectOffset = RoundBox.offset, + ImageRectSize = RoundBox.size, + SliceCenter = RoundBox.center, ScaleType = Enum.ScaleType.Slice, BackgroundTransparency = 1, Position = UDim2.new(0.5, 0, 0, 0), diff --git a/plugin/src/Components/FormButton.lua b/plugin/src/Components/FormButton.lua index 17bc8b67..719d27b6 100644 --- a/plugin/src/Components/FormButton.lua +++ b/plugin/src/Components/FormButton.lua @@ -9,23 +9,26 @@ local FitText = require(Plugin.Components.FitText) local e = Roact.createElement -local GrayButton07 = Assets.Slices.GrayButton07 +local RoundBox = Assets.Slices.RoundBox local function FormButton(props) local text = props.text local layoutOrder = props.layoutOrder local onClick = props.onClick + local imageColor = props.secondary and Color3.new(0.95, 0.95, 0.95) or nil + return e(FitList, { containerKind = "ImageButton", containerProps = { LayoutOrder = layoutOrder, BackgroundTransparency = 1, - Image = GrayButton07.asset, - ImageRectOffset = GrayButton07.offset, - ImageRectSize = GrayButton07.size, + Image = RoundBox.asset, + ImageRectOffset = RoundBox.offset, + ImageRectSize = RoundBox.size, + SliceCenter = RoundBox.center, ScaleType = Enum.ScaleType.Slice, - SliceCenter = GrayButton07.center, + ImageColor3 = imageColor, [Roact.Event.Activated] = function() if onClick ~= nil then diff --git a/plugin/src/Components/FormTextInput.lua b/plugin/src/Components/FormTextInput.lua index 0b3016fc..962cb716 100644 --- a/plugin/src/Components/FormTextInput.lua +++ b/plugin/src/Components/FormTextInput.lua @@ -7,7 +7,7 @@ local Assets = require(Plugin.Assets) local e = Roact.createElement -local GrayBox = Assets.Slices.GrayBox +local RoundBox = Assets.Slices.RoundBox local function FormTextInput(props) local value = props.value @@ -17,17 +17,18 @@ local function FormTextInput(props) return e("ImageLabel", { LayoutOrder = layoutOrder, - Image = GrayBox.asset, - ImageRectOffset = GrayBox.offset, - ImageRectSize = GrayBox.size, + Image = RoundBox.asset, + ImageRectOffset = RoundBox.offset, + ImageRectSize = RoundBox.size, ScaleType = Enum.ScaleType.Slice, - SliceCenter = GrayBox.center, + SliceCenter = RoundBox.center, + ImageColor3 = Color3.new(0.95, 0.95, 0.95), Size = size, BackgroundTransparency = 1, }, { InputInner = e("TextBox", { BackgroundTransparency = 1, - Size = UDim2.new(1, -8, 1, -8), + Size = UDim2.new(1, -12, 1, -12), Position = UDim2.new(0.5, 0, 0.5, 0), AnchorPoint = Vector2.new(0.5, 0.5), Font = Enum.Font.SourceSans, From 99bbe58255d41d52fca746153310e5e372c6c3f3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 15 Jan 2019 23:58:25 -0800 Subject: [PATCH 0376/1504] Fix server to correctly resolve module script names --- server/src/rbx_snapshot.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 35446f14..73ee3ea5 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -255,16 +255,16 @@ fn snapshot_imfs_file<'source>( fn snapshot_lua_file<'source>( file: &'source ImfsFile, ) -> SnapshotResult<'source> { - let file_name = file.path - .file_name().expect("Could not extract file stem") + let file_stem = file.path + .file_stem().expect("Could not extract file stem") .to_str().expect("Could not convert path to UTF-8"); - let (instance_name, class_name) = if let Some(name) = match_trailing(file_name, ".server.lua") { + let (instance_name, class_name) = if let Some(name) = match_trailing(file_stem, ".server") { (name, "Script") - } else if let Some(name) = match_trailing(file_name, ".client.lua") { + } else if let Some(name) = match_trailing(file_stem, ".client") { (name, "LocalScript") } else { - (file_name, "ModuleScript") + (file_stem, "ModuleScript") }; let contents = str::from_utf8(&file.contents) From f254a51d592dd0cd542d00836c85430aec8fd290 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 16 Jan 2019 00:01:40 -0800 Subject: [PATCH 0377/1504] Remove unused config button --- plugin/src/Components/App.lua | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 2b99c764..913165d5 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -71,7 +71,6 @@ function App:init() }) self.connectButton = nil - self.configButton = nil self.currentSession = nil self.displayedVersion = DevSettings:isEnabled() @@ -167,15 +166,6 @@ function App:didMount() }) end end) - - self.configButton = toolbar:CreateButton( - "Configure", - "Configure the Rojo plugin", - Assets.Configure) - self.configButton.ClickableWhenViewportHidden = false - self.configButton.Click:Connect(function() - self.configButton:SetActive(false) - end) end function App:didUpdate() From 3620a9d25690c9c4b18aa345585ce7ab23607c09 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 16 Jan 2019 16:36:22 -0800 Subject: [PATCH 0378/1504] Thread Cow<'str> through for naming nodes --- server/src/rbx_session.rs | 5 ++- server/src/rbx_snapshot.rs | 67 +++++++++++++++++++------------------- 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 1820424e..052d2c1e 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -1,4 +1,5 @@ use std::{ + borrow::Cow, collections::HashMap, path::{Path, PathBuf}, str, @@ -80,10 +81,12 @@ impl RbxSession { trace!("Snapshotting path {}", path_to_snapshot.display()); + let instance_name = self.sync_point_names.get(&path_to_snapshot) + .map(|value| Cow::Owned(value.to_owned())); let mut snapshot_meta = SnapshotMetadata { sync_point_names: &mut self.sync_point_names, }; - let maybe_snapshot = snapshot_imfs_path(&imfs, &mut snapshot_meta, &path_to_snapshot) + let maybe_snapshot = snapshot_imfs_path(&imfs, &mut snapshot_meta, &path_to_snapshot, instance_name) .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())); let snapshot = match maybe_snapshot { diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 73ee3ea5..2a10de3b 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -83,14 +83,14 @@ pub fn snapshot_project_tree<'source>( metadata: &mut SnapshotMetadata, project: &'source Project, ) -> SnapshotResult<'source> { - snapshot_project_node(imfs, metadata, &project.tree, &project.name) + snapshot_project_node(imfs, metadata, &project.tree, Cow::Borrowed(&project.name)) } fn snapshot_project_node<'source>( imfs: &'source Imfs, metadata: &mut SnapshotMetadata, node: &'source ProjectNode, - instance_name: &'source str, + instance_name: Cow<'source, str>, ) -> SnapshotResult<'source> { match node { ProjectNode::Instance(instance_node) => snapshot_instance_node(imfs, metadata, instance_node, instance_name), @@ -102,19 +102,19 @@ fn snapshot_instance_node<'source>( imfs: &'source Imfs, metadata: &mut SnapshotMetadata, node: &'source InstanceProjectNode, - instance_name: &'source str, + instance_name: Cow<'source, str>, ) -> SnapshotResult<'source> { let mut children = Vec::new(); for (child_name, child_project_node) in &node.children { - if let Some(child) = snapshot_project_node(imfs, metadata, child_project_node, child_name)? { + if let Some(child) = snapshot_project_node(imfs, metadata, child_project_node, Cow::Borrowed(child_name))? { children.push(child); } } Ok(Some(RbxSnapshotInstance { class_name: Cow::Borrowed(&node.class_name), - name: Cow::Borrowed(instance_name), + name: instance_name, properties: node.properties.clone(), children, source_path: None, @@ -126,19 +126,19 @@ fn snapshot_sync_point_node<'source>( imfs: &'source Imfs, metadata: &mut SnapshotMetadata, node: &'source SyncPointProjectNode, - instance_name: &'source str, + instance_name: Cow<'source, str>, ) -> SnapshotResult<'source> { + let maybe_snapshot = snapshot_imfs_path(imfs, metadata, &node.path, Some(instance_name))?; + // If the snapshot resulted in no instances, like if it targets an unknown // file or an empty model file, we can early-return. - let mut snapshot = match snapshot_imfs_path(imfs, metadata, &node.path)? { + let snapshot = match maybe_snapshot { Some(snapshot) => snapshot, None => return Ok(None), }; - // Otherwise, we can mutate the snapshot we got back and track some extra - // metadata. - snapshot.name = Cow::Borrowed(instance_name); - metadata.sync_point_names.insert(node.path.to_owned(), instance_name.to_owned()); + // Otherwise, we can log the name of the sync point we just snapshotted. + metadata.sync_point_names.insert(node.path.to_owned(), snapshot.name.clone().into_owned()); Ok(Some(snapshot)) } @@ -146,12 +146,13 @@ fn snapshot_sync_point_node<'source>( pub fn snapshot_imfs_path<'source>( imfs: &'source Imfs, metadata: &mut SnapshotMetadata, - path: &Path + path: &Path, + instance_name: Option>, ) -> SnapshotResult<'source> { // If the given path doesn't exist in the in-memory filesystem, we consider // that an error. match imfs.get(path) { - Some(imfs_item) => snapshot_imfs_item(imfs, metadata, imfs_item), + Some(imfs_item) => snapshot_imfs_item(imfs, metadata, imfs_item, instance_name), None => return Err(SnapshotError::DidNotExist(path.to_owned())), } } @@ -160,10 +161,11 @@ fn snapshot_imfs_item<'source>( imfs: &'source Imfs, metadata: &mut SnapshotMetadata, item: &'source ImfsItem, + instance_name: Option>, ) -> SnapshotResult<'source> { match item { - ImfsItem::File(file) => snapshot_imfs_file(metadata, file), - ImfsItem::Directory(directory) => snapshot_imfs_directory(imfs, metadata, directory), + ImfsItem::File(file) => snapshot_imfs_file(file, instance_name), + ImfsItem::Directory(directory) => snapshot_imfs_directory(imfs, metadata, directory, instance_name), } } @@ -171,39 +173,36 @@ fn snapshot_imfs_directory<'source>( imfs: &'source Imfs, metadata: &mut SnapshotMetadata, directory: &'source ImfsDirectory, + instance_name: Option>, ) -> SnapshotResult<'source> { let init_path = directory.path.join(INIT_MODULE_NAME); let init_server_path = directory.path.join(INIT_SERVER_NAME); let init_client_path = directory.path.join(INIT_CLIENT_NAME); + let snapshot_name = instance_name + .unwrap_or_else(|| { + Cow::Borrowed(directory.path + .file_name().expect("Could not extract file name") + .to_str().expect("Could not convert path to UTF-8")) + }); + let mut snapshot = if directory.children.contains(&init_path) { - snapshot_imfs_path(imfs, metadata, &init_path)?.unwrap() + snapshot_imfs_path(imfs, metadata, &init_path, Some(snapshot_name.clone()))?.unwrap() } else if directory.children.contains(&init_server_path) { - snapshot_imfs_path(imfs, metadata, &init_server_path)?.unwrap() + snapshot_imfs_path(imfs, metadata, &init_server_path, Some(snapshot_name.clone()))?.unwrap() } else if directory.children.contains(&init_client_path) { - snapshot_imfs_path(imfs, metadata, &init_client_path)?.unwrap() + snapshot_imfs_path(imfs, metadata, &init_client_path, Some(snapshot_name.clone()))?.unwrap() } else { RbxSnapshotInstance { class_name: Cow::Borrowed("Folder"), name: Cow::Borrowed(""), properties: HashMap::new(), children: Vec::new(), - source_path: Some(directory.path.clone()), + source_path: Some(directory.path.to_owned()), metadata: None, } }; - // We have to be careful not to lose instance names that are specified in - // the project manifest. We store them in sync_point_names when the original - // tree is constructed. - snapshot.name = if let Some(actual_name) = metadata.sync_point_names.get(&directory.path) { - Cow::Owned(actual_name.clone()) - } else { - Cow::Borrowed(directory.path - .file_name().expect("Could not extract file name") - .to_str().expect("Could not convert path to UTF-8")) - }; - for child_path in &directory.children { let child_name = child_path .file_name().expect("Couldn't extract file name") @@ -216,7 +215,7 @@ fn snapshot_imfs_directory<'source>( // them here. }, _ => { - if let Some(child) = snapshot_imfs_path(imfs, metadata, child_path)? { + if let Some(child) = snapshot_imfs_path(imfs, metadata, child_path, None)? { snapshot.children.push(child); } }, @@ -227,8 +226,8 @@ fn snapshot_imfs_directory<'source>( } fn snapshot_imfs_file<'source>( - metadata: &mut SnapshotMetadata, file: &'source ImfsFile, + instance_name: Option>, ) -> SnapshotResult<'source> { let extension = file.path.extension() .map(|v| v.to_str().expect("Could not convert extension to UTF-8")); @@ -244,8 +243,8 @@ fn snapshot_imfs_file<'source>( if let Some(snapshot) = maybe_snapshot.as_mut() { // Carefully preserve name from project manifest if present. - if let Some(actual_name) = metadata.sync_point_names.get(&file.path) { - snapshot.name = Cow::Owned(actual_name.clone()); + if let Some(snapshot_name) = instance_name { + snapshot.name = snapshot_name; } } From 4cfdc72c00333cc234b9ebcad90ab291332b8555 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 16 Jan 2019 17:28:06 -0800 Subject: [PATCH 0379/1504] Fix folders having empty names --- server/src/rbx_snapshot.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 2a10de3b..3979ce91 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -187,15 +187,15 @@ fn snapshot_imfs_directory<'source>( }); let mut snapshot = if directory.children.contains(&init_path) { - snapshot_imfs_path(imfs, metadata, &init_path, Some(snapshot_name.clone()))?.unwrap() + snapshot_imfs_path(imfs, metadata, &init_path, Some(snapshot_name))?.unwrap() } else if directory.children.contains(&init_server_path) { - snapshot_imfs_path(imfs, metadata, &init_server_path, Some(snapshot_name.clone()))?.unwrap() + snapshot_imfs_path(imfs, metadata, &init_server_path, Some(snapshot_name))?.unwrap() } else if directory.children.contains(&init_client_path) { - snapshot_imfs_path(imfs, metadata, &init_client_path, Some(snapshot_name.clone()))?.unwrap() + snapshot_imfs_path(imfs, metadata, &init_client_path, Some(snapshot_name))?.unwrap() } else { RbxSnapshotInstance { class_name: Cow::Borrowed("Folder"), - name: Cow::Borrowed(""), + name: snapshot_name, properties: HashMap::new(), children: Vec::new(), source_path: Some(directory.path.to_owned()), From bd3a4a719df10bf7adcf1c9044146ccf885a2691 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 17 Jan 2019 16:48:49 -0800 Subject: [PATCH 0380/1504] Normalize metadata into metadata per instance and metadata per path (#107) * Begin the metadata merge trek * Tidy up path metadata, entry API, begin implementing * Flesh out use of PathMap Entry API * Metadata per instance is a go * Tidy up naming for metadata per instance * SnapshotMetadata -> SnapshotContext --- server/src/path_map.rs | 35 ++++++++++++ server/src/rbx_session.rs | 91 ++++++++++++++++++------------- server/src/rbx_snapshot.rs | 76 +++++++++++++++----------- server/src/snapshot_reconciler.rs | 65 +++++++++++----------- server/src/web.rs | 26 +++++++-- 5 files changed, 185 insertions(+), 108 deletions(-) diff --git a/server/src/path_map.rs b/server/src/path_map.rs index cc9265c4..af3f473c 100644 --- a/server/src/path_map.rs +++ b/server/src/path_map.rs @@ -1,4 +1,5 @@ use std::{ + collections::hash_map, path::{self, Path, PathBuf}, collections::{HashMap, HashSet}, }; @@ -31,6 +32,16 @@ impl PathMap { self.nodes.get(path).map(|v| &v.value) } + pub fn get_mut(&mut self, path: &Path) -> Option<&mut T> { + self.nodes.get_mut(path).map(|v| &mut v.value) + } + + pub fn entry<'a>(&'a mut self, path: PathBuf) -> Entry<'a, T> { + Entry { + internal: self.nodes.entry(path), + } + } + pub fn insert(&mut self, path: PathBuf, value: T) { if let Some(parent_path) = path.parent() { if let Some(parent) = self.nodes.get_mut(parent_path) { @@ -105,4 +116,28 @@ impl PathMap { current_path } +} + +pub struct Entry<'a, T> { + internal: hash_map::Entry<'a, PathBuf, PathMapNode>, +} + +impl<'a, T> Entry<'a, T> { + pub fn or_insert(self, value: T) -> &'a mut T { + &mut self.internal.or_insert(PathMapNode { + value, + children: HashSet::new(), + }).value + } +} + +impl<'a, T> Entry<'a, T> + where T: Default +{ + pub fn or_default(self) -> &'a mut T { + &mut self.internal.or_insert(PathMapNode { + value: Default::default(), + children: HashSet::new(), + }).value + } } \ No newline at end of file diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 052d2c1e..37dbe1d0 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -6,15 +6,16 @@ use std::{ sync::{Arc, Mutex}, }; +use serde_derive::{Serialize, Deserialize}; use log::{info, trace}; use rbx_tree::{RbxTree, RbxId}; use crate::{ - project::{Project, InstanceProjectNodeMetadata}, + project::Project, message_queue::MessageQueue, imfs::{Imfs, ImfsItem}, path_map::PathMap, - rbx_snapshot::{SnapshotMetadata, snapshot_project_tree, snapshot_imfs_path}, + rbx_snapshot::{SnapshotContext, snapshot_project_tree, snapshot_imfs_path}, snapshot_reconciler::{InstanceChanges, reify_root, reconcile_subtree}, }; @@ -22,11 +23,25 @@ const INIT_SCRIPT: &str = "init.lua"; const INIT_SERVER_SCRIPT: &str = "init.server.lua"; const INIT_CLIENT_SCRIPT: &str = "init.client.lua"; +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct MetadataPerPath { + pub instance_id: Option, + pub instance_name: Option, +} + +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct MetadataPerInstance { + pub source_path: Option, + pub ignore_unknown_instances: bool, +} + pub struct RbxSession { tree: RbxTree, - path_map: PathMap, - instance_metadata_map: HashMap, - sync_point_names: HashMap, + + // TODO(#105): Change metadata_per_path to PathMap> for + // path aliasing. + metadata_per_path: PathMap, + metadata_per_instance: HashMap, message_queue: Arc>, imfs: Arc>, } @@ -37,20 +52,18 @@ impl RbxSession { imfs: Arc>, message_queue: Arc>, ) -> RbxSession { - let mut sync_point_names = HashMap::new(); - let mut path_map = PathMap::new(); - let mut instance_metadata_map = HashMap::new(); + let mut metadata_per_path = PathMap::new(); + let mut metadata_per_instance = HashMap::new(); let tree = { let temp_imfs = imfs.lock().unwrap(); - reify_initial_tree(&project, &temp_imfs, &mut path_map, &mut instance_metadata_map, &mut sync_point_names) + reify_initial_tree(&project, &temp_imfs, &mut metadata_per_path, &mut metadata_per_instance) }; RbxSession { tree, - path_map, - instance_metadata_map, - sync_point_names, + metadata_per_path, + metadata_per_instance, message_queue, imfs, } @@ -67,8 +80,7 @@ impl RbxSession { .expect("Path was outside in-memory filesystem roots"); // Find the closest instance in the tree that currently exists - let mut path_to_snapshot = self.path_map.descend(root_path, path); - let &instance_id = self.path_map.get(&path_to_snapshot).unwrap(); + let mut path_to_snapshot = self.metadata_per_path.descend(root_path, path); // If this is a file that might affect its parent if modified, we // should snapshot its parent instead. @@ -81,12 +93,19 @@ impl RbxSession { trace!("Snapshotting path {}", path_to_snapshot.display()); - let instance_name = self.sync_point_names.get(&path_to_snapshot) + let path_metadata = self.metadata_per_path.get(&path_to_snapshot).unwrap(); + let instance_id = path_metadata.instance_id + .expect("Instance did not exist in tree"); + + // If this instance is a sync point, pull its name out of our + // per-path metadata store. + let instance_name = path_metadata.instance_name.as_ref() .map(|value| Cow::Owned(value.to_owned())); - let mut snapshot_meta = SnapshotMetadata { - sync_point_names: &mut self.sync_point_names, + + let mut context = SnapshotContext { + metadata_per_path: &mut self.metadata_per_path, }; - let maybe_snapshot = snapshot_imfs_path(&imfs, &mut snapshot_meta, &path_to_snapshot, instance_name) + let maybe_snapshot = snapshot_imfs_path(&imfs, &mut context, &path_to_snapshot, instance_name) .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())); let snapshot = match maybe_snapshot { @@ -103,8 +122,8 @@ impl RbxSession { &mut self.tree, instance_id, &snapshot, - &mut self.path_map, - &mut self.instance_metadata_map, + &mut self.metadata_per_path, + &mut self.metadata_per_instance, &mut changes, ); } @@ -144,13 +163,13 @@ impl RbxSession { pub fn path_removed(&mut self, path: &Path) { info!("Path removed: {}", path.display()); - self.path_map.remove(path); + self.metadata_per_path.remove(path); self.path_created_or_updated(path); } pub fn path_renamed(&mut self, from_path: &Path, to_path: &Path) { info!("Path renamed from {} to {}", from_path.display(), to_path.display()); - self.path_map.remove(from_path); + self.metadata_per_path.remove(from_path); self.path_created_or_updated(from_path); self.path_created_or_updated(to_path); } @@ -159,38 +178,36 @@ impl RbxSession { &self.tree } - pub fn get_instance_metadata(&self, id: RbxId) -> Option<&InstanceProjectNodeMetadata> { - self.instance_metadata_map.get(&id) + pub fn get_instance_metadata(&self, id: RbxId) -> Option<&MetadataPerInstance> { + self.metadata_per_instance.get(&id) } - pub fn debug_get_path_map(&self) -> &PathMap { - &self.path_map + pub fn debug_get_metadata_per_path(&self) -> &PathMap { + &self.metadata_per_path } } pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { - let mut path_map = PathMap::new(); - let mut instance_metadata_map = HashMap::new(); - let mut sync_point_names = HashMap::new(); - reify_initial_tree(project, imfs, &mut path_map, &mut instance_metadata_map, &mut sync_point_names) + let mut metadata_per_path = PathMap::new(); + let mut metadata_per_instance = HashMap::new(); + reify_initial_tree(project, imfs, &mut metadata_per_path, &mut metadata_per_instance) } fn reify_initial_tree( project: &Project, imfs: &Imfs, - path_map: &mut PathMap, - instance_metadata_map: &mut HashMap, - sync_point_names: &mut HashMap, + metadata_per_path: &mut PathMap, + metadata_per_instance: &mut HashMap, ) -> RbxTree { - let mut meta = SnapshotMetadata { - sync_point_names, + let mut context = SnapshotContext { + metadata_per_path, }; - let snapshot = snapshot_project_tree(imfs, &mut meta, project) + let snapshot = snapshot_project_tree(imfs, &mut context, project) .expect("Could not snapshot project tree") .expect("Project did not produce any instances"); let mut changes = InstanceChanges::default(); - let tree = reify_root(&snapshot, path_map, instance_metadata_map, &mut changes); + let tree = reify_root(&snapshot, metadata_per_path, metadata_per_instance, &mut changes); tree } \ No newline at end of file diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 3979ce91..06a8e2ce 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -28,6 +28,9 @@ use crate::{ RbxSnapshotInstance, snapshot_from_tree, }, + path_map::PathMap, + // TODO: Move MetadataPerPath into this module? + rbx_session::{MetadataPerPath, MetadataPerInstance}, }; const INIT_MODULE_NAME: &str = "init.lua"; @@ -36,8 +39,8 @@ const INIT_CLIENT_NAME: &str = "init.client.lua"; pub type SnapshotResult<'a> = Result>, SnapshotError>; -pub struct SnapshotMetadata<'meta> { - pub sync_point_names: &'meta mut HashMap, +pub struct SnapshotContext<'meta> { + pub metadata_per_path: &'meta mut PathMap, } #[derive(Debug, Fail)] @@ -80,34 +83,34 @@ impl fmt::Display for SnapshotError { pub fn snapshot_project_tree<'source>( imfs: &'source Imfs, - metadata: &mut SnapshotMetadata, + context: &mut SnapshotContext, project: &'source Project, ) -> SnapshotResult<'source> { - snapshot_project_node(imfs, metadata, &project.tree, Cow::Borrowed(&project.name)) + snapshot_project_node(imfs, context, &project.tree, Cow::Borrowed(&project.name)) } fn snapshot_project_node<'source>( imfs: &'source Imfs, - metadata: &mut SnapshotMetadata, + context: &mut SnapshotContext, node: &'source ProjectNode, instance_name: Cow<'source, str>, ) -> SnapshotResult<'source> { match node { - ProjectNode::Instance(instance_node) => snapshot_instance_node(imfs, metadata, instance_node, instance_name), - ProjectNode::SyncPoint(sync_node) => snapshot_sync_point_node(imfs, metadata, sync_node, instance_name), + ProjectNode::Instance(instance_node) => snapshot_instance_node(imfs, context, instance_node, instance_name), + ProjectNode::SyncPoint(sync_node) => snapshot_sync_point_node(imfs, context, sync_node, instance_name), } } fn snapshot_instance_node<'source>( imfs: &'source Imfs, - metadata: &mut SnapshotMetadata, + context: &mut SnapshotContext, node: &'source InstanceProjectNode, instance_name: Cow<'source, str>, ) -> SnapshotResult<'source> { let mut children = Vec::new(); for (child_name, child_project_node) in &node.children { - if let Some(child) = snapshot_project_node(imfs, metadata, child_project_node, Cow::Borrowed(child_name))? { + if let Some(child) = snapshot_project_node(imfs, context, child_project_node, Cow::Borrowed(child_name))? { children.push(child); } } @@ -117,18 +120,20 @@ fn snapshot_instance_node<'source>( name: instance_name, properties: node.properties.clone(), children, - source_path: None, - metadata: Some(node.metadata.clone()), + metadata: MetadataPerInstance { + source_path: None, + ignore_unknown_instances: node.metadata.ignore_unknown_instances, + }, })) } fn snapshot_sync_point_node<'source>( imfs: &'source Imfs, - metadata: &mut SnapshotMetadata, + context: &mut SnapshotContext, node: &'source SyncPointProjectNode, instance_name: Cow<'source, str>, ) -> SnapshotResult<'source> { - let maybe_snapshot = snapshot_imfs_path(imfs, metadata, &node.path, Some(instance_name))?; + let maybe_snapshot = snapshot_imfs_path(imfs, context, &node.path, Some(instance_name))?; // If the snapshot resulted in no instances, like if it targets an unknown // file or an empty model file, we can early-return. @@ -138,40 +143,41 @@ fn snapshot_sync_point_node<'source>( }; // Otherwise, we can log the name of the sync point we just snapshotted. - metadata.sync_point_names.insert(node.path.to_owned(), snapshot.name.clone().into_owned()); + let path_meta = context.metadata_per_path.entry(node.path.to_owned()).or_default(); + path_meta.instance_name = Some(snapshot.name.clone().into_owned()); Ok(Some(snapshot)) } pub fn snapshot_imfs_path<'source>( imfs: &'source Imfs, - metadata: &mut SnapshotMetadata, + context: &mut SnapshotContext, path: &Path, instance_name: Option>, ) -> SnapshotResult<'source> { // If the given path doesn't exist in the in-memory filesystem, we consider // that an error. match imfs.get(path) { - Some(imfs_item) => snapshot_imfs_item(imfs, metadata, imfs_item, instance_name), + Some(imfs_item) => snapshot_imfs_item(imfs, context, imfs_item, instance_name), None => return Err(SnapshotError::DidNotExist(path.to_owned())), } } fn snapshot_imfs_item<'source>( imfs: &'source Imfs, - metadata: &mut SnapshotMetadata, + context: &mut SnapshotContext, item: &'source ImfsItem, instance_name: Option>, ) -> SnapshotResult<'source> { match item { ImfsItem::File(file) => snapshot_imfs_file(file, instance_name), - ImfsItem::Directory(directory) => snapshot_imfs_directory(imfs, metadata, directory, instance_name), + ImfsItem::Directory(directory) => snapshot_imfs_directory(imfs, context, directory, instance_name), } } fn snapshot_imfs_directory<'source>( imfs: &'source Imfs, - metadata: &mut SnapshotMetadata, + context: &mut SnapshotContext, directory: &'source ImfsDirectory, instance_name: Option>, ) -> SnapshotResult<'source> { @@ -187,19 +193,21 @@ fn snapshot_imfs_directory<'source>( }); let mut snapshot = if directory.children.contains(&init_path) { - snapshot_imfs_path(imfs, metadata, &init_path, Some(snapshot_name))?.unwrap() + snapshot_imfs_path(imfs, context, &init_path, Some(snapshot_name))?.unwrap() } else if directory.children.contains(&init_server_path) { - snapshot_imfs_path(imfs, metadata, &init_server_path, Some(snapshot_name))?.unwrap() + snapshot_imfs_path(imfs, context, &init_server_path, Some(snapshot_name))?.unwrap() } else if directory.children.contains(&init_client_path) { - snapshot_imfs_path(imfs, metadata, &init_client_path, Some(snapshot_name))?.unwrap() + snapshot_imfs_path(imfs, context, &init_client_path, Some(snapshot_name))?.unwrap() } else { RbxSnapshotInstance { class_name: Cow::Borrowed("Folder"), name: snapshot_name, properties: HashMap::new(), children: Vec::new(), - source_path: Some(directory.path.to_owned()), - metadata: None, + metadata: MetadataPerInstance { + source_path: Some(directory.path.to_owned()), + ignore_unknown_instances: false, + }, } }; @@ -215,7 +223,7 @@ fn snapshot_imfs_directory<'source>( // them here. }, _ => { - if let Some(child) = snapshot_imfs_path(imfs, metadata, child_path, None)? { + if let Some(child) = snapshot_imfs_path(imfs, context, child_path, None)? { snapshot.children.push(child); } }, @@ -281,8 +289,10 @@ fn snapshot_lua_file<'source>( }, }, children: Vec::new(), - metadata: None, - source_path: Some(file.path.to_path_buf()), + metadata: MetadataPerInstance { + source_path: Some(file.path.to_path_buf()), + ignore_unknown_instances: false, + }, })) } @@ -317,8 +327,10 @@ fn snapshot_txt_file<'source>( }, }, children: Vec::new(), - metadata: None, - source_path: Some(file.path.to_path_buf()), + metadata: MetadataPerInstance { + source_path: Some(file.path.to_path_buf()), + ignore_unknown_instances: false, + }, })) } @@ -348,8 +360,10 @@ fn snapshot_csv_file<'source>( }, }, children: Vec::new(), - metadata: None, - source_path: Some(file.path.to_path_buf()), + metadata: MetadataPerInstance { + source_path: Some(file.path.to_path_buf()), + ignore_unknown_instances: false, + }, })) } diff --git a/server/src/snapshot_reconciler.rs b/server/src/snapshot_reconciler.rs index 64c702c3..2562c4cb 100644 --- a/server/src/snapshot_reconciler.rs +++ b/server/src/snapshot_reconciler.rs @@ -3,7 +3,6 @@ use std::{ borrow::Cow, collections::{HashMap, HashSet}, fmt, - path::PathBuf, }; use rbx_tree::{RbxTree, RbxId, RbxInstanceProperties, RbxValue}; @@ -11,7 +10,7 @@ use serde_derive::{Serialize, Deserialize}; use crate::{ path_map::PathMap, - project::InstanceProjectNodeMetadata, + rbx_session::{MetadataPerPath, MetadataPerInstance}, }; #[derive(Debug, Clone, Default, Serialize, Deserialize)] @@ -62,8 +61,7 @@ pub struct RbxSnapshotInstance<'a> { pub class_name: Cow<'a, str>, pub properties: HashMap, pub children: Vec>, - pub source_path: Option, - pub metadata: Option, + pub metadata: MetadataPerInstance, } pub fn snapshot_from_tree(tree: &RbxTree, id: RbxId) -> Option> { @@ -79,33 +77,34 @@ pub fn snapshot_from_tree(tree: &RbxTree, id: RbxId) -> Option, - instance_metadata_map: &mut HashMap, + metadata_per_path: &mut PathMap, + instance_metadata_map: &mut HashMap, changes: &mut InstanceChanges, ) -> RbxTree { let instance = reify_core(snapshot); let mut tree = RbxTree::new(instance); let root_id = tree.get_root_id(); - if let Some(source_path) = &snapshot.source_path { - path_map.insert(source_path.clone(), root_id); + if let Some(source_path) = &snapshot.metadata.source_path { + let path_meta = metadata_per_path.entry(source_path.to_owned()).or_default(); + path_meta.instance_id = Some(root_id); } - if let Some(metadata) = &snapshot.metadata { - instance_metadata_map.insert(root_id, metadata.clone()); - } + instance_metadata_map.insert(root_id, snapshot.metadata.clone()); changes.added.insert(root_id); for child in &snapshot.children { - reify_subtree(child, &mut tree, root_id, path_map, instance_metadata_map, changes); + reify_subtree(child, &mut tree, root_id, metadata_per_path, instance_metadata_map, changes); } tree @@ -115,25 +114,24 @@ pub fn reify_subtree( snapshot: &RbxSnapshotInstance, tree: &mut RbxTree, parent_id: RbxId, - path_map: &mut PathMap, - instance_metadata_map: &mut HashMap, + metadata_per_path: &mut PathMap, + instance_metadata_map: &mut HashMap, changes: &mut InstanceChanges, ) { let instance = reify_core(snapshot); let id = tree.insert_instance(instance, parent_id); - if let Some(source_path) = &snapshot.source_path { - path_map.insert(source_path.clone(), id); + if let Some(source_path) = &snapshot.metadata.source_path { + let path_meta = metadata_per_path.entry(source_path.clone()).or_default(); + path_meta.instance_id = Some(id); } - if let Some(metadata) = &snapshot.metadata { - instance_metadata_map.insert(id, metadata.clone()); - } + instance_metadata_map.insert(id, snapshot.metadata.clone()); changes.added.insert(id); for child in &snapshot.children { - reify_subtree(child, tree, id, path_map, instance_metadata_map, changes); + reify_subtree(child, tree, id, metadata_per_path, instance_metadata_map, changes); } } @@ -141,23 +139,22 @@ pub fn reconcile_subtree( tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance, - path_map: &mut PathMap, - instance_metadata_map: &mut HashMap, + metadata_per_path: &mut PathMap, + instance_metadata_map: &mut HashMap, changes: &mut InstanceChanges, ) { - if let Some(source_path) = &snapshot.source_path { - path_map.insert(source_path.clone(), id); + if let Some(source_path) = &snapshot.metadata.source_path { + let path_meta = metadata_per_path.entry(source_path.to_owned()).or_default(); + path_meta.instance_id = Some(id); } - if let Some(metadata) = &snapshot.metadata { - instance_metadata_map.insert(id, metadata.clone()); - } + instance_metadata_map.insert(id, snapshot.metadata.clone()); if reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot) { changes.updated.insert(id); } - reconcile_instance_children(tree, id, snapshot, path_map, instance_metadata_map, changes); + reconcile_instance_children(tree, id, snapshot, metadata_per_path, instance_metadata_map, changes); } fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstanceProperties { @@ -237,8 +234,8 @@ fn reconcile_instance_children( tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance, - path_map: &mut PathMap, - instance_metadata_map: &mut HashMap, + metadata_per_path: &mut PathMap, + instance_metadata_map: &mut HashMap, changes: &mut InstanceChanges, ) { let mut visited_snapshot_indices = HashSet::new(); @@ -290,7 +287,7 @@ fn reconcile_instance_children( } for child_snapshot in &children_to_add { - reify_subtree(child_snapshot, tree, id, path_map, instance_metadata_map, changes); + reify_subtree(child_snapshot, tree, id, metadata_per_path, instance_metadata_map, changes); } for child_id in &children_to_remove { @@ -303,6 +300,6 @@ fn reconcile_instance_children( } for (child_id, child_snapshot) in &children_to_update { - reconcile_subtree(tree, *child_id, child_snapshot, path_map, instance_metadata_map, changes); + reconcile_subtree(tree, *child_id, child_snapshot, metadata_per_path, instance_metadata_map, changes); } } \ No newline at end of file diff --git a/server/src/web.rs b/server/src/web.rs index c992e8ad..ccb7822c 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -17,11 +17,25 @@ use rbx_tree::{RbxId, RbxInstance}; use crate::{ session::Session, session_id::SessionId, - project::InstanceProjectNodeMetadata, snapshot_reconciler::InstanceChanges, visualize::{VisualizeRbxSession, VisualizeImfs, graphviz_to_svg}, + rbx_session::{MetadataPerInstance}, }; +/// Contains the instance metadata relevant to Rojo clients. +#[derive(Debug, Serialize, Deserialize)] +pub struct InstanceMetadata { + ignore_unknown_instances: bool, +} + +impl InstanceMetadata { + fn from_session_metadata(meta: &MetadataPerInstance) -> InstanceMetadata { + InstanceMetadata { + ignore_unknown_instances: meta.ignore_unknown_instances, + } + } +} + /// Used to attach metadata specific to Rojo to instances, which come from the /// rbx_tree crate. /// @@ -33,7 +47,7 @@ pub struct InstanceWithMetadata<'a> { pub instance: Cow<'a, RbxInstance>, #[serde(rename = "Metadata")] - pub metadata: Option>, + pub metadata: Option, } #[derive(Debug, Serialize, Deserialize)] @@ -163,7 +177,7 @@ impl Server { for &requested_id in &requested_ids { if let Some(instance) = tree.get_instance(requested_id) { let metadata = rbx_session.get_instance_metadata(requested_id) - .map(Cow::Borrowed); + .map(InstanceMetadata::from_session_metadata); instances.insert(instance.get_id(), InstanceWithMetadata { instance: Cow::Borrowed(instance), @@ -172,7 +186,7 @@ impl Server { for descendant in tree.descendants(requested_id) { let descendant_meta = rbx_session.get_instance_metadata(descendant.get_id()) - .map(Cow::Borrowed); + .map(InstanceMetadata::from_session_metadata); instances.insert(descendant.get_id(), InstanceWithMetadata { instance: Cow::Borrowed(descendant), @@ -205,10 +219,10 @@ impl Server { Response::svg(graphviz_to_svg(&dot_source)) }, - (GET) (/visualize/path_map) => { + (GET) (/visualize/path_metadata) => { let rbx_session = self.session.rbx_session.lock().unwrap(); - Response::json(&rbx_session.debug_get_path_map()) + Response::json(&rbx_session.debug_get_metadata_per_path()) }, _ => Response::empty_404() From e301116e87e17fb3bdcc71eb778301115c188419 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 17 Jan 2019 17:45:24 -0800 Subject: [PATCH 0381/1504] Make rbx visualization less noisy, removing paths --- server/src/visualize.rs | 6 ++++-- server/src/web.rs | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/server/src/visualize.rs b/server/src/visualize.rs index 22f91591..75b51b19 100644 --- a/server/src/visualize.rs +++ b/server/src/visualize.rs @@ -10,6 +10,7 @@ use rbx_tree::RbxId; use crate::{ imfs::{Imfs, ImfsItem}, rbx_session::RbxSession, + web::InstanceMetadata, }; static GRAPHVIZ_HEADER: &str = r#" @@ -63,9 +64,10 @@ fn visualize_rbx_node(session: &RbxSession, id: RbxId, output: &mut fmt::Formatt let mut node_label = format!("{}|{}|{}", node.name, node.class_name, id); - if let Some(metadata) = session.get_instance_metadata(id) { + if let Some(session_metadata) = session.get_instance_metadata(id) { + let metadata = InstanceMetadata::from_session_metadata(session_metadata); node_label.push('|'); - node_label.push_str(&serde_json::to_string(metadata).unwrap()); + node_label.push_str(&serde_json::to_string(&metadata).unwrap()); } node_label = node_label diff --git a/server/src/web.rs b/server/src/web.rs index ccb7822c..6ae45983 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -29,7 +29,7 @@ pub struct InstanceMetadata { } impl InstanceMetadata { - fn from_session_metadata(meta: &MetadataPerInstance) -> InstanceMetadata { + pub fn from_session_metadata(meta: &MetadataPerInstance) -> InstanceMetadata { InstanceMetadata { ignore_unknown_instances: meta.ignore_unknown_instances, } From 779d46293276fffb98af633aed3d8dfb5becd10b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 17 Jan 2019 18:24:49 -0800 Subject: [PATCH 0382/1504] Rename Session to LiveSession, a better name --- server/src/commands/serve.rs | 6 ++-- server/src/lib.rs | 2 +- server/src/{session.rs => live_session.rs} | 9 +++--- server/src/web.rs | 32 +++++++++++----------- 4 files changed, 25 insertions(+), 24 deletions(-) rename server/src/{session.rs => live_session.rs} (86%) diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 48567d2e..69ec0e75 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -9,7 +9,7 @@ use failure::Fail; use crate::{ project::{Project, ProjectLoadFuzzyError}, web::Server, - session::Session, + live_session::LiveSession, }; const DEFAULT_PORT: u16 = 34872; @@ -38,8 +38,8 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { info!("Found project at {}", project.file_location.display()); info!("Using project {:#?}", project); - let session = Arc::new(Session::new(Arc::clone(&project)).unwrap()); - let server = Server::new(Arc::clone(&session)); + let live_session = Arc::new(LiveSession::new(Arc::clone(&project)).unwrap()); + let server = Server::new(Arc::clone(&live_session)); let port = options.port .or(project.serve_port) diff --git a/server/src/lib.rs b/server/src/lib.rs index 2848092d..6befeb64 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -11,7 +11,7 @@ pub mod path_map; pub mod project; pub mod rbx_session; pub mod rbx_snapshot; -pub mod session; +pub mod live_session; pub mod session_id; pub mod snapshot_reconciler; pub mod visualize; diff --git a/server/src/session.rs b/server/src/live_session.rs similarity index 86% rename from server/src/session.rs rename to server/src/live_session.rs index 025c26f8..6d0b9485 100644 --- a/server/src/session.rs +++ b/server/src/live_session.rs @@ -13,7 +13,8 @@ use crate::{ fs_watcher::FsWatcher, }; -pub struct Session { +/// Contains all of the state for a Rojo live-sync session. +pub struct LiveSession { pub project: Arc, pub session_id: SessionId, pub message_queue: Arc>, @@ -22,8 +23,8 @@ pub struct Session { _fs_watcher: FsWatcher, } -impl Session { - pub fn new(project: Arc) -> io::Result { +impl LiveSession { + pub fn new(project: Arc) -> io::Result { let imfs = { let mut imfs = Imfs::new(); imfs.add_roots_from_project(&project)?; @@ -45,7 +46,7 @@ impl Session { let session_id = SessionId::new(); - Ok(Session { + Ok(LiveSession { project, session_id, message_queue, diff --git a/server/src/web.rs b/server/src/web.rs index 6ae45983..7efef666 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -15,7 +15,7 @@ use rouille::{ use rbx_tree::{RbxId, RbxInstance}; use crate::{ - session::Session, + live_session::LiveSession, session_id::SessionId, snapshot_reconciler::InstanceChanges, visualize::{VisualizeRbxSession, VisualizeImfs, graphviz_to_svg}, @@ -77,14 +77,14 @@ pub struct SubscribeResponse<'a> { } pub struct Server { - session: Arc, + live_session: Arc, server_version: &'static str, } impl Server { - pub fn new(session: Arc) -> Server { + pub fn new(live_session: Arc) -> Server { Server { - session, + live_session, server_version: env!("CARGO_PKG_VERSION"), } } @@ -101,14 +101,14 @@ impl Server { (GET) (/api/rojo) => { // Get a summary of information about the server. - let rbx_session = self.session.rbx_session.lock().unwrap(); + let rbx_session = self.live_session.rbx_session.lock().unwrap(); let tree = rbx_session.get_tree(); Response::json(&ServerInfoResponse { server_version: self.server_version, protocol_version: 2, - session_id: self.session.session_id, - expected_place_ids: self.session.project.serve_place_ids.clone(), + session_id: self.live_session.session_id, + expected_place_ids: self.live_session.project.serve_place_ids.clone(), root_instance_id: tree.get_root_id(), }) }, @@ -117,7 +117,7 @@ impl Server { // Retrieve any messages past the given cursor index, and if // there weren't any, subscribe to receive any new messages. - let message_queue = Arc::clone(&self.session.message_queue); + let message_queue = Arc::clone(&self.live_session.message_queue); // Did the client miss any messages since the last subscribe? { @@ -125,7 +125,7 @@ impl Server { if !new_messages.is_empty() { return Response::json(&SubscribeResponse { - session_id: self.session.session_id, + session_id: self.live_session.session_id, messages: Cow::Borrowed(&new_messages), message_cursor: new_cursor, }) @@ -147,7 +147,7 @@ impl Server { let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); return Response::json(&SubscribeResponse { - session_id: self.session.session_id, + session_id: self.live_session.session_id, messages: Cow::Owned(new_messages), message_cursor: new_cursor, }) @@ -155,7 +155,7 @@ impl Server { }, (GET) (/api/read/{ id_list: String }) => { - let message_queue = Arc::clone(&self.session.message_queue); + let message_queue = Arc::clone(&self.live_session.message_queue); let requested_ids: Option> = id_list .split(',') @@ -167,7 +167,7 @@ impl Server { None => return rouille::Response::text("Malformed ID list").with_status_code(400), }; - let rbx_session = self.session.rbx_session.lock().unwrap(); + let rbx_session = self.live_session.rbx_session.lock().unwrap(); let tree = rbx_session.get_tree(); let message_cursor = message_queue.get_message_cursor(); @@ -197,14 +197,14 @@ impl Server { } Response::json(&ReadResponse { - session_id: self.session.session_id, + session_id: self.live_session.session_id, message_cursor, instances, }) }, (GET) (/visualize/rbx) => { - let rbx_session = self.session.rbx_session.lock().unwrap(); + let rbx_session = self.live_session.rbx_session.lock().unwrap(); let dot_source = format!("{}", VisualizeRbxSession(&rbx_session)); @@ -212,7 +212,7 @@ impl Server { }, (GET) (/visualize/imfs) => { - let imfs = self.session.imfs.lock().unwrap(); + let imfs = self.live_session.imfs.lock().unwrap(); let dot_source = format!("{}", VisualizeImfs(&imfs)); @@ -220,7 +220,7 @@ impl Server { }, (GET) (/visualize/path_metadata) => { - let rbx_session = self.session.rbx_session.lock().unwrap(); + let rbx_session = self.live_session.rbx_session.lock().unwrap(); Response::json(&rbx_session.debug_get_metadata_per_path()) }, From 5a98ede45efbd0c1112c153165ea38f3ac7a90ed Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 18 Jan 2019 13:49:47 -0800 Subject: [PATCH 0383/1504] Tweak features section of README --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 8ee5b6c6..b1a89b91 100644 --- a/README.md +++ b/README.md @@ -31,15 +31,14 @@ Rojo is designed for **power users** who want to use the **best tools available* Rojo lets you: * Work on scripts from the filesystem, in your favorite editor -* Version your place, library, or plugin using Git or another VCS -* Sync JSON-format models from the filesystem into your game +* Version your place, model, or plugin using Git or another VCS +* Sync `rbxmx` and `rbxm` models into your game in real time +* Package and deploy your project to Roblox.com from the command line Soon, Rojo will be able to: -* Sync scripts from Roblox Studio to the filesystem -* Compile MoonScript and sync it into Roblox Studio -* Sync `rbxmx` models between the filesystem and Roblox Studio -* Package projects into `rbxmx` files from the command line +* Sync instances from Roblox Studio to the filesystem +* Compile MoonScript and other custom things for your project ## [Documentation](https://lpghatguy.github.io/rojo/0.4.x) You can also view the documentation by browsing the [docs](https://github.com/LPGhatguy/rojo/tree/master/docs) folder of the repository, but because it uses a number of Markdown extensions, it may not be very readable. From 6fcb895d709e67209dc38520e81030b6a04615e6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 18 Jan 2019 20:57:19 -0800 Subject: [PATCH 0384/1504] Tweak bottom of README, move LICENSE to LICENSE.txt --- LICENSE => LICENSE.txt | 0 README.md | 4 +--- 2 files changed, 1 insertion(+), 3 deletions(-) rename LICENSE => LICENSE.txt (100%) diff --git a/LICENSE b/LICENSE.txt similarity index 100% rename from LICENSE rename to LICENSE.txt diff --git a/README.md b/README.md index b1a89b91..3ca74319 100644 --- a/README.md +++ b/README.md @@ -60,11 +60,9 @@ Here are a few, if you're looking for alternatives or supplements to Rojo: If you use a plugin that _isn't_ Rojo for syncing code, open an issue and let me know why! I'd like Rojo to be the end-all tool so that people stop reinventing solutions to this problem. ## Contributing -The `master` branch is a rewrite known as **Epiphany**. It includes a breaking change to the project configuration format and an infrastructure overhaul. - Pull requests are welcome! All pull requests are run against a test suite on Travis CI. That test suite should always pass! ## License -Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE](LICENSE) for details. \ No newline at end of file +Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file From 614f8860084c7522a6146d71272a30310a525f2e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 Jan 2019 10:56:01 -0800 Subject: [PATCH 0385/1504] Fix misnamed metadata coming from server --- server/src/web.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/server/src/web.rs b/server/src/web.rs index 7efef666..b8512831 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -24,6 +24,7 @@ use crate::{ /// Contains the instance metadata relevant to Rojo clients. #[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] pub struct InstanceMetadata { ignore_unknown_instances: bool, } From fecb11cba4f88d4684e2f03cbc24e3af1f96c8be Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 Jan 2019 10:57:03 -0800 Subject: [PATCH 0386/1504] Adjust logging and error handling in the client * HTTP responses in the error range (400+) now properly turn into errors * ROJO_EPIPHANY_DEV_CREATE now creates more verbose configuration * Default configuration values are now much more explicit * Errors that cause session termination are labeled more clearly. --- plugin/src/ApiContext.lua | 26 +++++++++++++++++++++++--- plugin/src/Components/App.lua | 3 +-- plugin/src/DevSettings.lua | 24 ++++++++++++++++++------ plugin/src/HttpResponse.lua | 2 +- plugin/src/Logging.lua | 11 +++-------- 5 files changed, 46 insertions(+), 20 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 30f8c8b5..f8fd2fe6 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -11,6 +11,14 @@ ApiContext.__index = ApiContext -- TODO: Audit cases of errors and create enum values for each of them. ApiContext.Error = { ServerIdMismatch = "ServerIdMismatch", + + -- The server gave an unexpected 400-category error, which may be the + -- client's fault. + ClientError = "ClientError", + + -- The server gave an unexpected 500-category error, which may be the + -- server's fault. + ServerError = "ServerError", } setmetatable(ApiContext.Error, { @@ -19,6 +27,18 @@ setmetatable(ApiContext.Error, { end }) +local function rejectFailedRequests(response) + if response.code >= 400 then + if response.code < 500 then + return Promise.reject(ApiContext.Error.ClientError) + else + return Promise.reject(ApiContext.Error.ServerError) + end + end + + return response +end + function ApiContext.new(baseUrl) assert(type(baseUrl) == "string") @@ -43,6 +63,7 @@ function ApiContext:connect() local url = ("%s/api/rojo"):format(self.baseUrl) return Http.get(url) + :andThen(rejectFailedRequests) :andThen(function(response) local body = response:json() @@ -102,9 +123,7 @@ function ApiContext:read(ids) local url = ("%s/api/read/%s"):format(self.baseUrl, table.concat(ids, ",")) return Http.get(url) - :catch(function(err) - return Promise.reject(err) - end) + :andThen(rejectFailedRequests) :andThen(function(response) local body = response:json() @@ -129,6 +148,7 @@ function ApiContext:retrieveMessages() return Promise.reject(err) end) + :andThen(rejectFailedRequests) :andThen(function(response) local body = response:json() diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 913165d5..dd79be33 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -95,8 +95,7 @@ function App:render() address = address, port = port, onError = function(message) - Logging.warn("%s", tostring(message)) - Logging.trace("Session terminated due to error") + Logging.warn("Rojo session terminated because of an error:\n%s", tostring(message)) self.currentSession = nil self:setState({ diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua index 9dcc4fca..8edf7efb 100644 --- a/plugin/src/DevSettings.lua +++ b/plugin/src/DevSettings.lua @@ -1,12 +1,22 @@ local Config = require(script.Parent.Config) +local VALUES = { + LogLevel = { + type = "IntValue", + defaultUserValue = 2, + defaultDevValue = 3, + }, +} + +local CONTAINER_NAME = "RojoDevSettings" .. Config.codename + local function getValueContainer() - return game:FindFirstChild("RojoDev-" .. Config.codename) + return game:FindFirstChild(CONTAINER_NAME) end local valueContainer = getValueContainer() -local function getValue(name) +local function getStoredValue(name) if valueContainer == nil then return nil end @@ -20,7 +30,7 @@ local function getValue(name) return valueObject.Value end -local function setValue(name, kind, value) +local function setStoredValue(name, kind, value) local object = valueContainer:FindFirstChild(name) if object == nil then @@ -37,11 +47,13 @@ local function createAllValues() if valueContainer == nil then valueContainer = Instance.new("Folder") - valueContainer.Name = "RojoDev-" .. Config.codename + valueContainer.Name = CONTAINER_NAME valueContainer.Parent = game end - setValue("LogLevel", "IntValue", getValue("LogLevel") or 2) + for name, value in pairs(VALUES) do + setStoredValue(name, value.type, value.defaultDevValue) + end end _G[("ROJO_%s_DEV_CREATE"):format(Config.codename:upper())] = createAllValues @@ -53,7 +65,7 @@ function DevSettings:isEnabled() end function DevSettings:getLogLevel() - return getValue("LogLevel") + return getStoredValue("LogLevel") or VALUES.LogLevel.defaultUserValue end return DevSettings \ No newline at end of file diff --git a/plugin/src/HttpResponse.lua b/plugin/src/HttpResponse.lua index 637f57de..039f8538 100644 --- a/plugin/src/HttpResponse.lua +++ b/plugin/src/HttpResponse.lua @@ -31,4 +31,4 @@ function HttpResponse:json() return HttpService:JSONDecode(self.body) end -return HttpResponse +return HttpResponse \ No newline at end of file diff --git a/plugin/src/Logging.lua b/plugin/src/Logging.lua index c57130b5..4b4f90af 100644 --- a/plugin/src/Logging.lua +++ b/plugin/src/Logging.lua @@ -1,7 +1,5 @@ local DevSettings = require(script.Parent.DevSettings) -local testLogLevel = nil - local Level = { Error = 0, Warning = 1, @@ -9,17 +7,14 @@ local Level = { Trace = 3, } +local testLogLevel = nil + local function getLogLevel() if testLogLevel ~= nil then return testLogLevel end - local devValue = DevSettings:getLogLevel() - if devValue ~= nil then - return devValue - end - - return Level.Info + return DevSettings:getLogLevel() end local function addTags(tag, message) From af4d4e0246f22c6a3176fe42f1a28f98f069953f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 Jan 2019 13:06:14 -0800 Subject: [PATCH 0387/1504] Revamp CHANGES, rename to CHANGELOG --- CHANGES.md => CHANGELOG.md | 50 +++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 22 deletions(-) rename CHANGES.md => CHANGELOG.md (75%) diff --git a/CHANGES.md b/CHANGELOG.md similarity index 75% rename from CHANGES.md rename to CHANGELOG.md index a2cc6a0a..ccf26fad 100644 --- a/CHANGES.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Rojo Change Log ## Current master +* Updated plugin UI to be simpler and more flat +* Updated plugin error messages to be a little more useful +* Removed unused 'Config' button in plugin UI +* Fixed bug where bad server responses could cause the plugin to be in a bad state + +## [0.5.0 Alpha 0](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.0) (January 14, 2019) * "Epiphany" rewrite, in progress since the beginning of time * New live sync protocol * Uses HTTP long polling to reduce request count and improve responsiveness @@ -25,36 +31,36 @@ * Multiple places can be specified, like when building a multi-place game * Added support for specifying properties on services in project files -## 0.4.13 (November 12, 2018) +## [0.4.13](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.13) (November 12, 2018) * When `rojo.json` points to a file or directory that does not exist, Rojo now issues a warning instead of throwing an error and exiting -## 0.4.12 (June 21, 2018) +## [0.4.12](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.12) (June 21, 2018) * Fixed obscure assertion failure when renaming or deleting files ([#78](https://github.com/LPGhatguy/rojo/issues/78)) * Added a `PluginAction` for the sync in command, which should help with some automation scripts ([#80](https://github.com/LPGhatguy/rojo/pull/80)) -## 0.4.11 (June 10, 2018) +## [0.4.11](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.11) (June 10, 2018) * Defensively insert existing instances into RouteMap; should fix most duplication cases when syncing into existing trees. * Fixed incorrect synchronization from `Plugin:_pull` that would cause polling to create issues * Fixed incorrect file routes being assigned to `init.lua` and `init.model.json` files * Untangled route handling-internals slightly -## 0.4.10 (June 2, 2018) +## [0.4.10](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.10) (June 2, 2018) * Added support for `init.model.json` files, which enable versioning `Tool` instances (among other things) with Rojo. ([#66](https://github.com/LPGhatguy/rojo/issues/66)) * Fixed obscure error when syncing into an invalid service. * Fixed multiple sync processes occurring when a server ID mismatch is detected. -## 0.4.9 (May 26, 2018) +## [0.4.9](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.9) (May 26, 2018) * Fixed warning when renaming or removing files that would sometimes corrupt the instance cache ([#72](https://github.com/LPGhatguy/rojo/pull/72)) * JSON models are no longer as strict -- `Children` and `Properties` are now optional. -## 0.4.8 (May 26, 2018) +## [0.4.8](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.8) (May 26, 2018) * Hotfix to prevent errors from being thrown when objects managed by Rojo are deleted -## 0.4.7 (May 25, 2018) +## [0.4.7](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.7) (May 25, 2018) * Added icons to the Rojo plugin, made by [@Vorlias](https://github.com/Vorlias)! ([#70](https://github.com/LPGhatguy/rojo/pull/70)) * Server will now issue a warning if no partitions are specified in `rojo serve` ([#40](https://github.com/LPGhatguy/rojo/issues/40)) -## 0.4.6 (May 21, 2018) +## [0.4.6](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.6) (May 21, 2018) * Rojo handles being restarted by Roblox Studio more gracefully ([#67](https://github.com/LPGhatguy/rojo/issues/67)) * Folders should no longer get collapsed when syncing occurs. * **Significant** robustness improvements with regards to caching. @@ -62,7 +68,7 @@ * If there are any bugs with script duplication or caching in the future, restarting the Rojo server process will fix them for that session. * Fixed message in plugin not being prefixed with `Rojo: `. -## 0.4.5 (May 1, 2018) +## [0.4.5](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.5) (May 1, 2018) * Rojo messages are now prefixed with `Rojo: ` to make them stand out in the output more. * Fixed server to notice file changes *much* more quickly. (200ms vs 1000ms) * Server now lists name of project when starting up. @@ -70,23 +76,23 @@ * Fixed multiple sync operations occuring at the same time. ([#61](https://github.com/LPGhatguy/rojo/issues/61)) * Partitions targeting files directly now work as expected. ([#57](https://github.com/LPGhatguy/rojo/issues/57)) -## 0.4.4 (April 7, 2018) +## [0.4.4](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.4) (April 7, 2018) * Fix small regression introduced in 0.4.3 -## 0.4.3 (April 7, 2018) +## [0.4.3](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.3) (April 7, 2018) * Plugin now automatically selects `HttpService` if it determines that HTTP isn't enabled ([#58](https://github.com/LPGhatguy/rojo/pull/58)) * Plugin now has much more robust handling and will wipe all state when the server changes. * This should fix issues that would otherwise be solved by restarting Roblox Studio. -## 0.4.2 (April 4, 2018) +## [0.4.2](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.2) (April 4, 2018) * Fixed final case of duplicated instance insertion, caused by reconciled instances not being inserted into `RouteMap`. * The reconciler is still not a perfect solution, especially if script instances get moved around without being destroyed. I don't think this can be fixed before a big refactor. -## 0.4.1 (April 1, 2018) +## [0.4.1](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.1) (April 1, 2018) * Merged plugin repository into main Rojo repository for easier tracking. * Improved `RouteMap` object tracking; this should fix some cases of duplicated instances being synced into the tree. -## 0.4.0 (March 27, 2018) +## [0.4.0](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.0) (March 27, 2018) * Protocol version 1, which shifts more responsibility onto the server * This is a **major breaking** change! * The server now has a content of 'filter plugins', which transform data at various stages in the pipeline @@ -94,36 +100,36 @@ * Added `*.model.json` files, which let you embed small Roblox objects into your Rojo tree. * Improved error messages in some cases ([#46](https://github.com/LPGhatguy/rojo/issues/46)) -## 0.3.2 (December 20, 2017) +## [0.3.2](https://github.com/LPGhatguy/rojo/releases/tag/v0.3.2) (December 20, 2017) * Fixed `rojo serve` failing to correctly construct an absolute root path when passed as an argument * Fixed intense CPU usage when running `rojo serve` -## 0.3.1 (December 14, 2017) +## [0.3.1](https://github.com/LPGhatguy/rojo/releases/tag/v0.3.1) (December 14, 2017) * Improved error reporting when invalid JSON is found in a `rojo.json` project * These messages are passed on from Serde -## 0.3.0 (December 12, 2017) +## [0.3.0](https://github.com/LPGhatguy/rojo/releases/tag/v0.3.0) (December 12, 2017) * Factored out the plugin into a separate repository * Fixed server when using a file as a partition * Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory! * Started running automatic tests on Travis CI (#9) -## 0.2.3 (December 4, 2017) +## [0.2.3](https://github.com/LPGhatguy/rojo/releases/tag/v0.2.3) (December 4, 2017) * Plugin only release * Tightened `init` file rules to only match script files * Previously, Rojo would sometimes pick up the wrong file when syncing -## 0.2.2 (December 1, 2017) +## [0.2.2](https://github.com/LPGhatguy/rojo/releases/tag/v0.2.2) (December 1, 2017) * Plugin only release * Fixed broken reconciliation behavior with `init` files -## 0.2.1 (December 1, 2017) +## [0.2.1](https://github.com/LPGhatguy/rojo/releases/tag/v0.2.1) (December 1, 2017) * Plugin only release * Changes default port to 8000 -## 0.2.0 (December 1, 2017) +## [0.2.0](https://github.com/LPGhatguy/rojo/releases/tag/v0.2.0) (December 1, 2017) * Support for `init.lua` like rbxfs and rbxpacker * More robust syncing with a new reconciler -## 0.1.0 (November 29, 2017) +## [0.1.0](https://github.com/LPGhatguy/rojo/releases/tag/v0.1.0) (November 29, 2017) * Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) \ No newline at end of file From aa7b7e43ff06aaad242e5c2fd575a38979710758 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 Jan 2019 13:08:50 -0800 Subject: [PATCH 0388/1504] Move CHANGELOG closer to keepachangelog.com format --- CHANGELOG.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ccf26fad..8c23eeee 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ -# Rojo Change Log +# Rojo Changelog -## Current master -* Updated plugin UI to be simpler and more flat -* Updated plugin error messages to be a little more useful +## [Unreleased] +* Changed plugin UI to be simpler and more flat +* Changed plugin error messages to be a little more useful * Removed unused 'Config' button in plugin UI * Fixed bug where bad server responses could cause the plugin to be in a bad state From 578abfabb341620af18a458b095812e96cad0add Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 Jan 2019 16:02:51 -0800 Subject: [PATCH 0389/1504] Partial plugin retheme --- assets/round-rect-8px-radius.png | Bin 0 -> 251 bytes plugin/src/Assets.lua | 12 ++- plugin/src/Components/ConnectPanel.lua | 104 +++++++++++++----------- plugin/src/Components/FitList.lua | 23 +++++- plugin/src/Components/FormButton.lua | 18 +++- plugin/src/Components/FormTextInput.lua | 5 +- plugin/src/Theme.lua | 16 ++++ 7 files changed, 119 insertions(+), 59 deletions(-) create mode 100644 assets/round-rect-8px-radius.png create mode 100644 plugin/src/Theme.lua diff --git a/assets/round-rect-8px-radius.png b/assets/round-rect-8px-radius.png new file mode 100644 index 0000000000000000000000000000000000000000..55d1ac410e5b0af42a273cc4777b7c30dccf12c2 GIT binary patch literal 251 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJL!K^ Date: Mon, 21 Jan 2019 17:50:49 -0800 Subject: [PATCH 0390/1504] Redesign UI --- CHANGELOG.md | 3 +- assets/round-rect-4px-radius.png | Bin 0 -> 175 bytes assets/round-rect-8px-radius-2px-border.png | Bin 513 -> 0 bytes assets/round-rect-8px-radius.png | Bin 251 -> 0 bytes plugin/src/Assets.lua | 13 +- plugin/src/Components/App.lua | 14 +- plugin/src/Components/ConnectPanel.lua | 178 +++++++++--------- .../src/Components/ConnectionActivePanel.lua | 50 +++-- plugin/src/Components/FitList.lua | 4 - plugin/src/Components/FormButton.lua | 4 +- plugin/src/Components/FormTextInput.lua | 4 +- plugin/src/Theme.lua | 11 +- plugin/src/joinBindings.lua | 34 ++++ 13 files changed, 191 insertions(+), 124 deletions(-) create mode 100644 assets/round-rect-4px-radius.png delete mode 100644 assets/round-rect-8px-radius-2px-border.png delete mode 100644 assets/round-rect-8px-radius.png create mode 100644 plugin/src/joinBindings.lua diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c23eeee..176810fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Rojo Changelog ## [Unreleased] -* Changed plugin UI to be simpler and more flat +* Changed plugin UI to be way prettier + * Thanks to [Reselim](https://github.com/Reselim) for the design! * Changed plugin error messages to be a little more useful * Removed unused 'Config' button in plugin UI * Fixed bug where bad server responses could cause the plugin to be in a bad state diff --git a/assets/round-rect-4px-radius.png b/assets/round-rect-4px-radius.png new file mode 100644 index 0000000000000000000000000000000000000000..f2b59bd1d1f29551bbccbbbc5168e3f074a7058c GIT binary patch literal 175 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJGEW!Bkcv5PuW#gSFyL_s+|00M zlAwU_2EimHBPX{6(TD>z-?tnQDZiwtH~-Sz2k+dt?!Itx|5d7W_oZaRp^Im77TFeG zv}9mE?qwXrEHFv#{=aF~4Cf|_F|r6aFu;fh;tgLCC)u6la^HNU@YHPc^YY6=J3U{2 SeYP0r0tQc4KbLh*2~7ZIJwC+% literal 0 HcmV?d00001 diff --git a/assets/round-rect-8px-radius-2px-border.png b/assets/round-rect-8px-radius-2px-border.png deleted file mode 100644 index 9c976f19eed6397143f175e1acd3e27614c5e98d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 513 zcmV+c0{;DpP)(_`g8%^e{{R4h=>PzAFaQARU;qF*m;eA5Z<1fd zMgRZ-he+}YsB)>a`slY1mZ%DG5Vha|@cY!PyY zz_7&_!Y&5)!n*{S87qw(%(R1@6#go~5Bi>d)I8z6r=OxIegK!i1#k)^92WxAQN+Lva1BU?NekQqYh%p&CqO8F0+vDulu~3_MjXdTc^pgIwlqycUDsG^ z2@ie&E{rivcl#}{jG_pwHF=(srs>h;08&cQG$qe-wAMsX1aKaVkOer;ZIY5#mD5U^qz@-FM09lqXR(f443CugPvC`|BOCSai zLW~B`>xv~`oC#n8m;fe#319-403^@=9QwhKY1_6t{*yr(aL$be&@@eV{40a8P}lWn z0KKkf2|NOOYwajoaL!?^1=s@*(ipP=?!5O@RW&GtbB?O2y8m`(jM+qCwg%32yWO%Z z%dymK{e9&0K+hMzRS=draB^hnf8Y=B9Q1tCAASq~I)kR17F-$$00000NkvXXu0mjf D0CmUZ diff --git a/assets/round-rect-8px-radius.png b/assets/round-rect-8px-radius.png deleted file mode 100644 index 55d1ac410e5b0af42a273cc4777b7c30dccf12c2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 251 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE1|*BCs=ffJL!K^ Date: Mon, 21 Jan 2019 18:34:10 -0800 Subject: [PATCH 0391/1504] UI visual tweaks --- plugin/src/Components/ConnectPanel.lua | 45 +++++++++++++++---------- plugin/src/Components/FormButton.lua | 2 +- plugin/src/Components/FormTextInput.lua | 18 ++++++---- plugin/src/Theme.lua | 3 +- 4 files changed, 43 insertions(+), 25 deletions(-) diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index 3308569c..f1ec4280 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -33,13 +33,13 @@ function ConnectPanel:init() self.footerVersionSize, }, function(container, other) - return UDim2.new(0, container.X - other.X - 16, 0, 18) + return UDim2.new(0, container.X - other.X - 16, 0, 32) end ) self:setState({ - address = Config.defaultHost, - port = Config.defaultPort, + address = "", + port = "", }) end @@ -73,10 +73,10 @@ function ConnectPanel:render() Padding = UDim.new(0, 8), }, paddingProps = { - PaddingTop = UDim.new(0, 8), - PaddingBottom = UDim.new(0, 8), - PaddingLeft = UDim.new(0, 8), - PaddingRight = UDim.new(0, 8), + PaddingTop = UDim.new(0, 20), + PaddingBottom = UDim.new(0, 10), + PaddingLeft = UDim.new(0, 24), + PaddingRight = UDim.new(0, 24), }, }, { Address = e(FitList, { @@ -89,7 +89,6 @@ function ConnectPanel:render() }, }, { Label = e(FitText, { - MinSize = Vector2.new(0, 20), Kind = "TextLabel", LayoutOrder = 1, BackgroundTransparency = 1, @@ -102,8 +101,9 @@ function ConnectPanel:render() Input = e(FormTextInput, { layoutOrder = 2, - size = UDim2.new(0, 200, 0, 28), + width = UDim.new(0, 220), value = self.state.address, + placeholderValue = Config.defaultHost, onValueChange = function(newValue) self:setState({ address = newValue, @@ -122,7 +122,6 @@ function ConnectPanel:render() }, }, { Label = e(FitText, { - MinSize = Vector2.new(0, 20), Kind = "TextLabel", LayoutOrder = 1, BackgroundTransparency = 1, @@ -135,8 +134,9 @@ function ConnectPanel:render() Input = e(FormTextInput, { layoutOrder = 2, - size = UDim2.new(0, 65, 0, 28), + width = UDim.new(0, 80), value = self.state.port, + placeholderValue = Config.defaultPort, onValueChange = function(newValue) self:setState({ port = newValue, @@ -160,9 +160,9 @@ function ConnectPanel:render() }, paddingProps = { PaddingTop = UDim.new(0, 0), - PaddingBottom = UDim.new(0, 8), - PaddingLeft = UDim.new(0, 8), - PaddingRight = UDim.new(0, 8), + PaddingBottom = UDim.new(0, 20), + PaddingLeft = UDim.new(0, 24), + PaddingRight = UDim.new(0, 24), }, }, { e(FormButton, { @@ -181,7 +181,17 @@ function ConnectPanel:render() text = "Connect", onClick = function() if startSession ~= nil then - startSession(self.state.address, self.state.port) + local address = self.state.address + if address:len() == 0 then + address = Config.defaultHost + end + + local port = self.state.port + if port:len() == 0 then + port = Config.defaultPort + end + + startSession(address, port) end end, }), @@ -208,6 +218,7 @@ function ConnectPanel:render() layoutProps = { FillDirection = Enum.FillDirection.Horizontal, HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, }, paddingProps = { PaddingTop = UDim.new(0, 4), @@ -223,10 +234,10 @@ function ConnectPanel:render() }, { Logo = e("ImageLabel", { Image = Assets.Images.Logo, - Size = UDim2.new(0, 60, 0, 40), + Size = UDim2.new(0, 80, 0, 40), ScaleType = Enum.ScaleType.Fit, BackgroundTransparency = 1, - Position = UDim2.new(0, 0, 1, 0), + Position = UDim2.new(0, 0, 1, -10), AnchorPoint = Vector2.new(0, 1), }), }), diff --git a/plugin/src/Components/FormButton.lua b/plugin/src/Components/FormButton.lua index 845fd06b..94ffba5e 100644 --- a/plugin/src/Components/FormButton.lua +++ b/plugin/src/Components/FormButton.lua @@ -53,7 +53,7 @@ local function FormButton(props) TextSize = 18, TextColor3 = textColor, Font = Theme.ButtonFont, - Padding = Vector2.new(16, 6), + Padding = Vector2.new(16, 8), BackgroundTransparency = 1, }), }) diff --git a/plugin/src/Components/FormTextInput.lua b/plugin/src/Components/FormTextInput.lua index 07765919..5246bfcd 100644 --- a/plugin/src/Components/FormTextInput.lua +++ b/plugin/src/Components/FormTextInput.lua @@ -10,11 +10,15 @@ local e = Roact.createElement local RoundBox = Assets.Slices.RoundBox +local TEXT_SIZE = 22 +local PADDING = 8 + local function FormTextInput(props) local value = props.value + local placeholderValue = props.placeholderValue local onValueChange = props.onValueChange local layoutOrder = props.layoutOrder - local size = props.size + local width = props.width return e("ImageLabel", { LayoutOrder = layoutOrder, @@ -24,20 +28,22 @@ local function FormTextInput(props) ScaleType = Enum.ScaleType.Slice, SliceCenter = RoundBox.center, ImageColor3 = Theme.SecondaryColor, - Size = size, + Size = UDim2.new(width.Scale, width.Offset, 0, TEXT_SIZE + PADDING * 2), BackgroundTransparency = 1, }, { InputInner = e("TextBox", { BackgroundTransparency = 1, - Size = UDim2.new(1, -12, 1, -12), + Size = UDim2.new(1, -PADDING * 2, 1, -PADDING * 2), Position = UDim2.new(0.5, 0, 0.5, 0), AnchorPoint = Vector2.new(0.5, 0.5), Font = Theme.InputFont, ClearTextOnFocus = false, - TextXAlignment = Enum.TextXAlignment.Left, - TextSize = 18, + TextXAlignment = Enum.TextXAlignment.Center, + TextSize = TEXT_SIZE, Text = value, - TextColor3 = Theme.PrimaryColor, + PlaceholderText = placeholderValue, + PlaceholderColor3 = Theme.AccentLightColor, + TextColor3 = Theme.AccentColor, [Roact.Change.Text] = function(rbx) onValueChange(rbx.Text) diff --git a/plugin/src/Theme.lua b/plugin/src/Theme.lua index 1b860387..85473ea8 100644 --- a/plugin/src/Theme.lua +++ b/plugin/src/Theme.lua @@ -1,10 +1,11 @@ local Theme = { ButtonFont = Enum.Font.GothamSemibold, - InputFont = Enum.Font.Gotham, + InputFont = Enum.Font.Code, TitleFont = Enum.Font.GothamBold, MainFont = Enum.Font.Gotham, AccentColor = Color3.fromRGB(136, 0, 27), + AccentLightColor = Color3.fromRGB(210, 145, 157), PrimaryColor = Color3.fromRGB(20, 20, 20), SecondaryColor = Color3.fromRGB(235, 235, 235), LightTextColor = Color3.fromRGB(140, 140, 140), From b1ddfc3a49439fa0e13d51c0868f5ba5573ef14d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 23 Jan 2019 18:10:29 -0800 Subject: [PATCH 0392/1504] Fix adding/removing files in folders that have init scripts --- server/src/rbx_session.rs | 3 +++ server/src/rbx_snapshot.rs | 4 +++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 37dbe1d0..e1edfa29 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -94,6 +94,9 @@ impl RbxSession { trace!("Snapshotting path {}", path_to_snapshot.display()); let path_metadata = self.metadata_per_path.get(&path_to_snapshot).unwrap(); + + trace!("Metadata for path: {:?}", path_metadata); + let instance_id = path_metadata.instance_id .expect("Instance did not exist in tree"); diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 06a8e2ce..c1f4c39a 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -205,12 +205,14 @@ fn snapshot_imfs_directory<'source>( properties: HashMap::new(), children: Vec::new(), metadata: MetadataPerInstance { - source_path: Some(directory.path.to_owned()), + source_path: None, ignore_unknown_instances: false, }, } }; + snapshot.metadata.source_path = Some(directory.path.to_owned()); + for child_path in &directory.children { let child_name = child_path .file_name().expect("Couldn't extract file name") From 87f64108779872f9d3f8f946fe6ae5958cd14f67 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 23 Jan 2019 18:10:53 -0800 Subject: [PATCH 0393/1504] Clean up error handling in plugin --- plugin/src/Session.lua | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 4fdd7262..50d47cd0 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -22,18 +22,18 @@ function Session.new(config) api:connect() :andThen(function() if self.disconnected then - return Promise.resolve() + return end return api:read({api.rootInstanceId}) - :andThen(function(response) - if self.disconnected then - return Promise.resolve() - end + end) + :andThen(function(response) + if self.disconnected then + return + end - self.reconciler:reconcile(response.instances, api.rootInstanceId, game) - return self:__processMessages() - end) + self.reconciler:reconcile(response.instances, api.rootInstanceId, game) + return self:__processMessages() end) :catch(function(message) self.disconnected = true From 6bc331be75a1d358420842a3ff72a51c684259c8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 23 Jan 2019 18:10:59 -0800 Subject: [PATCH 0394/1504] Update formatting of test plugin project --- plugin/test-plugin-project.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/test-plugin-project.json b/plugin/test-plugin-project.json index ab8cf8d0..efc6e26b 100644 --- a/plugin/test-plugin-project.json +++ b/plugin/test-plugin-project.json @@ -5,6 +5,7 @@ "ReplicatedStorage": { "$className": "ReplicatedStorage", + "Rojo": { "$className": "Folder", "Plugin": { @@ -30,6 +31,7 @@ "TestService": { "$className": "TestService", + "TestBootstrap": { "$path": "testBootstrap.server.lua" } From 23463b620eec3e09e3ba21f0f412bffb8cbe8fb7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 23 Jan 2019 18:14:05 -0800 Subject: [PATCH 0395/1504] Rename test-plugin-project to place-project.json --- .../{test-plugin-project.json => place-project.json} | 11 +++++++++++ 1 file changed, 11 insertions(+) rename plugin/{test-plugin-project.json => place-project.json} (80%) diff --git a/plugin/test-plugin-project.json b/plugin/place-project.json similarity index 80% rename from plugin/test-plugin-project.json rename to plugin/place-project.json index efc6e26b..9beb7df5 100644 --- a/plugin/test-plugin-project.json +++ b/plugin/place-project.json @@ -8,6 +8,7 @@ "Rojo": { "$className": "Folder", + "Plugin": { "$path": "src" }, @@ -29,6 +30,16 @@ } }, + "HttpService": { + "$className": "HttpService", + "$properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + } + }, + "TestService": { "$className": "TestService", From 6490b77d4c008a5e72bc988045a47565302e05bd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 23 Jan 2019 18:18:00 -0800 Subject: [PATCH 0396/1504] plugin: Hide placeholder inputs when focused --- plugin/src/Components/FormTextInput.lua | 39 ++++++++++++++++++++----- 1 file changed, 32 insertions(+), 7 deletions(-) diff --git a/plugin/src/Components/FormTextInput.lua b/plugin/src/Components/FormTextInput.lua index 5246bfcd..78e40c78 100644 --- a/plugin/src/Components/FormTextInput.lua +++ b/plugin/src/Components/FormTextInput.lua @@ -13,12 +13,27 @@ local RoundBox = Assets.Slices.RoundBox local TEXT_SIZE = 22 local PADDING = 8 -local function FormTextInput(props) - local value = props.value - local placeholderValue = props.placeholderValue - local onValueChange = props.onValueChange - local layoutOrder = props.layoutOrder - local width = props.width +local FormTextInput = Roact.Component:extend("FormTextInput") + +function FormTextInput:init() + self:setState({ + focused = false, + }) +end + +function FormTextInput:render() + local value = self.props.value + local placeholderValue = self.props.placeholderValue + local onValueChange = self.props.onValueChange + local layoutOrder = self.props.layoutOrder + local width = self.props.width + + local shownPlaceholder + if self.state.focused then + shownPlaceholder = "" + else + shownPlaceholder = placeholderValue + end return e("ImageLabel", { LayoutOrder = layoutOrder, @@ -41,13 +56,23 @@ local function FormTextInput(props) TextXAlignment = Enum.TextXAlignment.Center, TextSize = TEXT_SIZE, Text = value, - PlaceholderText = placeholderValue, + PlaceholderText = shownPlaceholder, PlaceholderColor3 = Theme.AccentLightColor, TextColor3 = Theme.AccentColor, [Roact.Change.Text] = function(rbx) onValueChange(rbx.Text) end, + [Roact.Event.Focused] = function() + self:setState({ + focused = true, + }) + end, + [Roact.Event.FocusLost] = function() + self:setState({ + focused = false, + }) + end, }), }) end From 1659adb4195e9f036a9316bbc4252ebcac2eb6b3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 25 Jan 2019 10:32:10 -0800 Subject: [PATCH 0397/1504] Refactor entrypoint to be a bit easier to read --- server/src/bin.rs | 222 ++++++++++++++++++++++++---------------------- 1 file changed, 115 insertions(+), 107 deletions(-) diff --git a/server/src/bin.rs b/server/src/bin.rs index 534d7c6a..6280b29c 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -5,7 +5,7 @@ use std::{ }; use log::error; -use clap::clap_app; +use clap::{clap_app, ArgMatches}; use librojo::commands; @@ -55,117 +55,125 @@ fn main() { ) ); - // `get_matches` consumes self for some reason. + // `get_matches` consumes our App, but we might need it in the 'help' case. let matches = app.clone().get_matches(); match matches.subcommand() { - ("init", Some(sub_matches)) => { - let fuzzy_project_path = make_path_absolute(Path::new(sub_matches.value_of("PATH").unwrap_or(""))); - let kind = sub_matches.value_of("kind"); - - let options = commands::InitOptions { - fuzzy_project_path, - kind, - }; - - match commands::init(&options) { - Ok(_) => {}, - Err(e) => { - error!("{}", e); - process::exit(1); - }, - } - }, - ("serve", Some(sub_matches)) => { - let fuzzy_project_path = match sub_matches.value_of("PROJECT") { - Some(v) => make_path_absolute(Path::new(v)), - None => std::env::current_dir().unwrap(), - }; - - let port = match sub_matches.value_of("port") { - Some(v) => match v.parse::() { - Ok(port) => Some(port), - Err(_) => { - error!("Invalid port {}", v); - process::exit(1); - }, - }, - None => None, - }; - - let options = commands::ServeOptions { - fuzzy_project_path, - port, - }; - - match commands::serve(&options) { - Ok(_) => {}, - Err(e) => { - error!("{}", e); - process::exit(1); - }, - } - }, - ("build", Some(sub_matches)) => { - let fuzzy_project_path = match sub_matches.value_of("PROJECT") { - Some(v) => make_path_absolute(Path::new(v)), - None => std::env::current_dir().unwrap(), - }; - - let output_file = make_path_absolute(Path::new(sub_matches.value_of("output").unwrap())); - - let options = commands::BuildOptions { - fuzzy_project_path, - output_file, - output_kind: None, // TODO: Accept from argument - }; - - match commands::build(&options) { - Ok(_) => {}, - Err(e) => { - error!("{}", e); - process::exit(1); - }, - } - }, - ("upload", Some(sub_matches)) => { - let fuzzy_project_path = match sub_matches.value_of("PROJECT") { - Some(v) => make_path_absolute(Path::new(v)), - None => std::env::current_dir().unwrap(), - }; - - let kind = sub_matches.value_of("kind"); - let security_cookie = sub_matches.value_of("cookie").unwrap(); - - let asset_id: u64 = { - let arg = sub_matches.value_of("asset_id").unwrap(); - - match arg.parse() { - Ok(v) => v, - Err(_) => { - error!("Invalid place ID {}", arg); - process::exit(1); - }, - } - }; - - let options = commands::UploadOptions { - fuzzy_project_path, - security_cookie: security_cookie.to_string(), - asset_id, - kind, - }; - - match commands::upload(&options) { - Ok(_) => {}, - Err(e) => { - error!("{}", e); - process::exit(1); - }, - } - }, + ("init", Some(sub_matches)) => start_init(sub_matches), + ("serve", Some(sub_matches)) => start_serve(sub_matches), + ("build", Some(sub_matches)) => start_build(sub_matches), + ("upload", Some(sub_matches)) => start_upload(sub_matches), _ => { app.print_help().expect("Could not print help text to stdout!"); }, } +} + +fn start_init(sub_matches: &ArgMatches) { + let fuzzy_project_path = make_path_absolute(Path::new(sub_matches.value_of("PATH").unwrap_or(""))); + let kind = sub_matches.value_of("kind"); + + let options = commands::InitOptions { + fuzzy_project_path, + kind, + }; + + match commands::init(&options) { + Ok(_) => {}, + Err(e) => { + error!("{}", e); + process::exit(1); + }, + } +} + +fn start_serve(sub_matches: &ArgMatches) { + let fuzzy_project_path = match sub_matches.value_of("PROJECT") { + Some(v) => make_path_absolute(Path::new(v)), + None => std::env::current_dir().unwrap(), + }; + + let port = match sub_matches.value_of("port") { + Some(v) => match v.parse::() { + Ok(port) => Some(port), + Err(_) => { + error!("Invalid port {}", v); + process::exit(1); + }, + }, + None => None, + }; + + let options = commands::ServeOptions { + fuzzy_project_path, + port, + }; + + match commands::serve(&options) { + Ok(_) => {}, + Err(e) => { + error!("{}", e); + process::exit(1); + }, + } +} + +fn start_build(sub_matches: &ArgMatches) { + let fuzzy_project_path = match sub_matches.value_of("PROJECT") { + Some(v) => make_path_absolute(Path::new(v)), + None => std::env::current_dir().unwrap(), + }; + + let output_file = make_path_absolute(Path::new(sub_matches.value_of("output").unwrap())); + + let options = commands::BuildOptions { + fuzzy_project_path, + output_file, + output_kind: None, // TODO: Accept from argument + }; + + match commands::build(&options) { + Ok(_) => {}, + Err(e) => { + error!("{}", e); + process::exit(1); + }, + } +} + +fn start_upload(sub_matches: &ArgMatches) { + let fuzzy_project_path = match sub_matches.value_of("PROJECT") { + Some(v) => make_path_absolute(Path::new(v)), + None => std::env::current_dir().unwrap(), + }; + + let kind = sub_matches.value_of("kind"); + let security_cookie = sub_matches.value_of("cookie").unwrap(); + + let asset_id: u64 = { + let arg = sub_matches.value_of("asset_id").unwrap(); + + match arg.parse() { + Ok(v) => v, + Err(_) => { + error!("Invalid place ID {}", arg); + process::exit(1); + }, + } + }; + + let options = commands::UploadOptions { + fuzzy_project_path, + security_cookie: security_cookie.to_string(), + asset_id, + kind, + }; + + match commands::upload(&options) { + Ok(_) => {}, + Err(e) => { + error!("{}", e); + process::exit(1); + }, + } } \ No newline at end of file From fc8d9dc1fe51222cc7978b209360ef4b0146b985 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 25 Jan 2019 10:54:54 -0800 Subject: [PATCH 0398/1504] Wrap main call in a panic handler to show a nice error message on panic --- server/src/bin.rs | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/server/src/bin.rs b/server/src/bin.rs index 6280b29c..61ef05f0 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -1,6 +1,7 @@ use std::{ - path::{Path, PathBuf}, env, + panic, + path::{Path, PathBuf}, process, }; @@ -23,7 +24,7 @@ fn main() { .default_format_timestamp(false) .init(); - let mut app = clap_app!(Rojo => + let app = clap_app!(Rojo => (version: env!("CARGO_PKG_VERSION")) (author: env!("CARGO_PKG_AUTHORS")) (about: env!("CARGO_PKG_DESCRIPTION")) @@ -55,20 +56,39 @@ fn main() { ) ); - // `get_matches` consumes our App, but we might need it in the 'help' case. - let matches = app.clone().get_matches(); + let matches = app.get_matches(); - match matches.subcommand() { + let result = panic::catch_unwind(|| match matches.subcommand() { ("init", Some(sub_matches)) => start_init(sub_matches), ("serve", Some(sub_matches)) => start_serve(sub_matches), ("build", Some(sub_matches)) => start_build(sub_matches), ("upload", Some(sub_matches)) => start_upload(sub_matches), - _ => { - app.print_help().expect("Could not print help text to stdout!"); - }, + _ => eprintln!("Usage: rojo \nUse 'rojo help' for more help."), + }); + + if let Err(error) = result { + let message = match error.downcast_ref::<&str>() { + Some(message) => message.to_string(), + None => match error.downcast_ref::() { + Some(message) => message.clone(), + None => "".to_string(), + }, + }; + + show_crash_message(&message); + process::exit(1); } } +fn show_crash_message(message: &str) { + error!("Rojo crashed!"); + error!("This is a bug in Rojo."); + error!(""); + error!("Please consider filing a bug: https://github.com/LPGhatguy/rojo/issues"); + error!(""); + error!("Details: {}", message); +} + fn start_init(sub_matches: &ArgMatches) { let fuzzy_project_path = make_path_absolute(Path::new(sub_matches.value_of("PATH").unwrap_or(""))); let kind = sub_matches.value_of("kind"); From 14fd470363f54a548e5076cccbbae083f42641ae Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 25 Jan 2019 17:54:16 -0800 Subject: [PATCH 0399/1504] Upgrade all dependencies, including new rbx_ crates --- CHANGELOG.md | 1 + Cargo.lock | 403 +++++++++++++++++++++++++--------------------- server/Cargo.toml | 6 +- 3 files changed, 222 insertions(+), 188 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 176810fa..a8d6c726 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Changed plugin error messages to be a little more useful * Removed unused 'Config' button in plugin UI * Fixed bug where bad server responses could cause the plugin to be in a bad state +* Upgraded to rbx\_tree, rbx\_xml, and rbx\_binary 0.2.0, which dramatically expands the kinds of properties that Rojo can handle, especially in XML. ## [0.5.0 Alpha 0](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.0) (January 14, 2019) * "Epiphany" rewrite, in progress since the beginning of time diff --git a/Cargo.lock b/Cargo.lock index 04fd0121..a5bd994c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,9 +1,9 @@ [[package]] name = "MacTypes-sys" -version = "1.3.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -16,7 +16,7 @@ name = "aho-corasick" version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -45,14 +45,14 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -60,10 +60,10 @@ name = "backtrace" version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -74,7 +74,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -82,16 +82,16 @@ name = "base64" version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "base64" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -110,7 +110,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -119,7 +119,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -143,7 +143,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.2.7" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -151,7 +151,7 @@ name = "bytes" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -162,9 +162,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -220,7 +220,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -228,7 +228,7 @@ name = "core-foundation-sys" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -247,6 +247,21 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-channel" version = "0.3.6" @@ -255,7 +270,7 @@ dependencies = [ "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -294,7 +309,7 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -302,7 +317,7 @@ name = "csv-core" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -311,7 +326,7 @@ version = "0.7.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -362,9 +377,9 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -374,8 +389,8 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -403,7 +418,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -411,7 +426,7 @@ name = "fsevent-sys" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -457,14 +472,14 @@ dependencies = [ [[package]] name = "h2" -version = "0.1.14" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -474,7 +489,7 @@ dependencies = [ [[package]] name = "http" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -497,27 +512,27 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.20" +version = "0.12.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -528,7 +543,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.20 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.23 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -540,7 +555,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -556,7 +571,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -567,7 +582,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -575,7 +590,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -605,7 +620,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.46" +version = "0.2.48" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -614,7 +629,7 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -648,7 +663,7 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -659,7 +674,7 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -677,17 +692,16 @@ name = "memchr" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memchr" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -743,7 +757,7 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -795,14 +809,14 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -812,7 +826,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -823,7 +837,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "notify" -version = "4.0.6" +version = "4.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -832,7 +846,7 @@ dependencies = [ "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -857,7 +871,7 @@ name = "num_cpus" version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -869,7 +883,7 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -884,7 +898,7 @@ version = "0.9.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -911,10 +925,10 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -965,7 +979,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.24" +version = "0.4.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -986,10 +1000,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -998,7 +1012,7 @@ version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1008,8 +1022,8 @@ version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1021,7 +1035,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1031,10 +1045,10 @@ name = "rand" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1048,8 +1062,8 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1057,12 +1071,20 @@ name = "rand_core" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.3.0" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand_core" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1070,7 +1092,7 @@ name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1078,7 +1100,7 @@ name = "rand_isaac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1088,8 +1110,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1099,7 +1121,7 @@ name = "rand_pcg" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1108,37 +1130,41 @@ name = "rand_xorshift" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_binary" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_tree 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_tree 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_tree" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_xml" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_tree 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_tree 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1147,12 +1173,12 @@ name = "rdrand" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "redox_syscall" -version = "0.1.50" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1160,7 +1186,7 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1169,7 +1195,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1193,29 +1219,29 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.20 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.23 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1231,17 +1257,17 @@ dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_binary 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_tree 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_binary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_tree 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1264,9 +1290,9 @@ dependencies = [ "multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1327,23 +1353,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "security-framework" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "security-framework-sys" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "MacTypes-sys 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1352,7 +1378,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1362,27 +1388,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.84" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.84" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.34" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1392,7 +1418,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1416,7 +1442,7 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1428,7 +1454,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1451,11 +1477,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.24" +version = "0.15.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1464,9 +1490,9 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1485,9 +1511,9 @@ version = "3.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1497,7 +1523,7 @@ name = "term" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1514,8 +1540,8 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1548,8 +1574,8 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1567,7 +1593,7 @@ dependencies = [ [[package]] name = "tokio" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1578,8 +1604,8 @@ dependencies = [ "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1642,9 +1668,10 @@ dependencies = [ [[package]] name = "tokio-threadpool" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1652,12 +1679,13 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1676,7 +1704,7 @@ name = "twoway" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1710,8 +1738,11 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "unicode-width" @@ -1752,7 +1783,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1856,17 +1887,17 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum MacTypes-sys 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7dbbe033994ae2198a18517c7132d952a29fb1db44249a1234779da7c50f4698" +"checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum autocfg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4e5f34df7a019573fb8bdc7e24a2bfebe51a2a1d6bfdbaeccedb3c41fc574727" +"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" "checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" -"checksum base64 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "621fc7ecb8008f86d7fb9b95356cd692ce9514b80a86d85b397f32a22da7b9e2" +"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" @@ -1875,7 +1906,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9279646319ff816b05fb5897883ece50d7d854d12b59992683d4f8a71b0f949" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" -"checksum byteorder 1.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94f88df23a25417badc922ab0f5716cc1330e87f71ddd9203b3a3ccd9cedf75d" +"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" "checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" @@ -1888,6 +1919,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" +"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" "checksum crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "137bc235f622ffaa0428e3854e24acb53291fc0b3ff6fb2cb75a8be6fb02f06b" "checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" "checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c" @@ -1913,11 +1945,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9e59524a909fe98bb6c6f2cf1f27f2f6772887a496bf4c68cae0d94f884586" -"checksum h2 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "1ac030ae20dee464c5d0f36544d8b914a6bc606da44a57e052d2b0f5dae129e0" -"checksum http 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "02096a6d2c55e63f7fcb800690e4f889a25f6ec342e3adb4594e293b625215ab" +"checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e" +"checksum http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1a10e5b573b9a0146545010f50772b9e8b1dd0a256564cc4307694c68832a2f5" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.12.20 (registry+https://github.com/rust-lang/crates.io-index)" = "80eeda66c9ef8e18f5122fff2c54604c053420b11dae951cfb74cf1dcba2e93f" +"checksum hyper 0.12.23 (registry+https://github.com/rust-lang/crates.io-index)" = "860faf61a9957c9cb0e23e69f1c8290e92f6eb660fcdd1f2d6777043a2ae1a46" "checksum hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd73f14ad370d3b4d4b7dce08f69b81536c82e39fcc89731930fe5788cd661" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" @@ -1928,7 +1960,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.46 (registry+https://github.com/rust-lang/crates.io-index)" = "023a4cd09b2ff695f9734c1934145a315594b7986398496841c7031a5a1bbdbd" +"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" "checksum libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "bff3ac7d6f23730d3b533c35ed75eef638167634476a499feef16c428d74b57b" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" @@ -1938,7 +1970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" -"checksum memchr 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "db4c41318937f6e76648f42826b1d9ade5c09cafb5aef7e351240a70f39206e9" +"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" @@ -1951,7 +1983,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "873ecfd8c174964ae30f401329d140142312c8e5590719cf1199d5f1717d8078" +"checksum notify 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c968cf37cf949114b00d51b0b23536d1c3a4a3963767cf4c969c65a6af78dc7d" "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" @@ -1967,32 +1999,33 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)" = "77619697826f31a02ae974457af0b29b723e5619e113e9397b8b82c6bd253f09" +"checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" +"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" "checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dee497e66d8d76bf08ce20c8d36e16f93749ab0bf89975b4f8ae5cee660c2da2" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3906503e80ac6cbcacb2c2973fa8e473f24d7e2747c8c92bb230c2441cad96b5" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" -"checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" +"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rbx_binary 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "646399297679f409cdc669b1b7b38a4f31cf97f1f5b6b2d56b5f03eaed8fa468" -"checksum rbx_tree 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ea5723859bf48caa1ae9fdb94dbd24dd436d17543147081fca2862446bcaaec7" -"checksum rbx_xml 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cdc27210e7e234f5af5af22f55c280a07fcc12566c37446d5b4fd0ae39ddea78" +"checksum rbx_binary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4cdf4806920e6e1cd9f91651b8fdb5d811f4e5a98a76b2893e97effa40d62054" +"checksum rbx_tree 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b605ef3e2ff864705720e382a5499fc29a8d93cd3fbfc4724770825f6760462" +"checksum rbx_xml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e4cf33e0a240f367ad98d553e55e755b5cb4790b02284a34e130ba646b4f191" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2" +"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0e60f169af3915c294818d55dde549f00d2966cef36d6c5e7255d75df3f2b16f" +"checksum reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "09d6e187a58d923ee132fcda141c94e716bcfe301c2ea2bef5c81536e0085376" "checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" @@ -2002,23 +2035,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum security-framework 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "697d3f3c23a618272ead9e1fb259c1411102b31c6af8b93f1d64cca9c3b0e8e0" -"checksum security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "40d95f3d7da09612affe897f320d78264f0d2320f3e8eea27d12bd1bd94445e2" +"checksum security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfab8dda0e7a327c696d893df9ffa19cadc4bd195797997f5223cf5831beaf05" +"checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "0e732ed5a5592c17d961555e3b552985baf98d50ce418b7b655f31f6ba7eb1b7" -"checksum serde_derive 1.0.84 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d6115a3ca25c224e409185325afc16a0d5aaaabc15c42b09587d6f1ba39a5b" -"checksum serde_json 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "bdf540260cfee6da923831f4776ddc495ada940c30117977c70f1313a6130545" +"checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752" +"checksum serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "a915306b0f1ac5607797697148c223bedeaa36bcc2e28a01441cd638cc6567b4" +"checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" "checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" "checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db" +"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.15.24 (registry+https://github.com/rust-lang/crates.io-index)" = "734ecc29cd36e8123850d9bf21dfd62ef8300aaa8f879aabaa899721808be37c" +"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" @@ -2030,21 +2063,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1661fa0a44c95d01604bd05c66732a446c657efb62b5164a7a083a3b552b4951" -"checksum tokio 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4790d0be6f4ba6ae4f48190efa2ed7780c9e3567796abdb285003cf39840d9c5" +"checksum tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "e0500b88064f08bebddd0c0bed39e19f5c567a5f30975bee52b0c0d3e2eeb38c" "checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" "checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" "checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" "checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "17465013014410310f9f61fa10bf4724803c149ea1d51efece131c38efca93aa" -"checksum tokio-timer 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "4f37f0111d76cc5da132fe9bc0590b9b9cfd079bc7e75ac3846278430a299ff8" +"checksum tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c3fd86cb15547d02daa2b21aadaf4e37dee3368df38a526178a5afa3c034d2fb" +"checksum tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "21c04a314a1f69f73c0227beba6250e06cdc1e9a62e7eff912bf54a59b6d1b94" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6a0180bc61fc5a987082bfa111f4cc95c4caff7f9799f3e46df09163a937aa25" +"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" diff --git a/server/Cargo.toml b/server/Cargo.toml index b4c4aa22..01d4940a 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -35,9 +35,9 @@ serde = "1.0" serde_derive = "1.0" serde_json = "1.0" uuid = { version = "0.7", features = ["v4", "serde"] } -rbx_tree = "0.1.0" -rbx_xml = "0.1.0" -rbx_binary = "0.1.0" +rbx_tree = "0.2.0" +rbx_xml = "0.2.0" +rbx_binary = "0.2.0" [dev-dependencies] tempfile = "3.0" From 38cd13dc0cac65e9cec2a918d2aee64d604bbf98 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 25 Jan 2019 18:01:37 -0800 Subject: [PATCH 0400/1504] 0.5.0-alpha.1 --- CHANGELOG.md | 2 ++ Cargo.lock | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8d6c726..3d5894d2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## [Unreleased] + +## [0.5.0 Alpha 1](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.1) (January 14, 2019) * Changed plugin UI to be way prettier * Thanks to [Reselim](https://github.com/Reselim) for the design! * Changed plugin error messages to be a little more useful diff --git a/Cargo.lock b/Cargo.lock index a5bd994c..1b847720 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0-alpha.0" +version = "0.5.0-alpha.1" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 657e873e..e88d4057 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0, "-alpha.0"}, + version = {0, 5, 0, "-alpha.1"}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/server/Cargo.toml b/server/Cargo.toml index 01d4940a..4924c80e 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0-alpha.0" +version = "0.5.0-alpha.1" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From e81f0a4a95eac296b63f6062cffb487bce506bb2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 11:03:48 -0800 Subject: [PATCH 0401/1504] Improve IMFS robustness with out-of-order events Fixes #111. --- .gitignore | 2 +- CHANGELOG.md | 1 + server/src/fs_watcher.rs | 18 ++++++++--- server/src/imfs.rs | 59 ++++++++++++++++++++++++++++++++----- server/test-scratch-project | 18 ----------- server/tests/imfs.rs | 14 +++++++++ test-scratch-project | 21 +++++++++++++ 7 files changed, 102 insertions(+), 31 deletions(-) delete mode 100755 server/test-scratch-project create mode 100644 test-scratch-project diff --git a/.gitignore b/.gitignore index f6839452..d77fcf54 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,5 @@ /site /target -/server/scratch +/scratch-project **/*.rs.bk /generate-docs.run \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d5894d2..b15b44eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## [Unreleased] +* Fixed in-memory filesystem not handling out-of-order filesystem change events ## [0.5.0 Alpha 1](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.1) (January 14, 2019) * Changed plugin UI to be way prettier diff --git a/server/src/fs_watcher.rs b/server/src/fs_watcher.rs index 84741941..178994d2 100644 --- a/server/src/fs_watcher.rs +++ b/server/src/fs_watcher.rs @@ -4,7 +4,7 @@ use std::{ thread, }; -use log::info; +use log::trace; use notify::{ self, DebouncedEvent, @@ -23,6 +23,8 @@ const WATCH_TIMEOUT: Duration = Duration::from_millis(100); fn handle_event(imfs: &Mutex, rbx_session: &Mutex, event: DebouncedEvent) { match event { DebouncedEvent::Create(path) => { + trace!("Path created: {}", path.display()); + { let mut imfs = imfs.lock().unwrap(); imfs.path_created(&path).unwrap(); @@ -34,6 +36,8 @@ fn handle_event(imfs: &Mutex, rbx_session: &Mutex, event: Debo } }, DebouncedEvent::Write(path) => { + trace!("Path created: {}", path.display()); + { let mut imfs = imfs.lock().unwrap(); imfs.path_updated(&path).unwrap(); @@ -45,6 +49,8 @@ fn handle_event(imfs: &Mutex, rbx_session: &Mutex, event: Debo } }, DebouncedEvent::Remove(path) => { + trace!("Path removed: {}", path.display()); + { let mut imfs = imfs.lock().unwrap(); imfs.path_removed(&path).unwrap(); @@ -56,6 +62,8 @@ fn handle_event(imfs: &Mutex, rbx_session: &Mutex, event: Debo } }, DebouncedEvent::Rename(from_path, to_path) => { + trace!("Path rename: {} to {}", from_path.display(), to_path.display()); + { let mut imfs = imfs.lock().unwrap(); imfs.path_moved(&from_path, &to_path).unwrap(); @@ -66,7 +74,9 @@ fn handle_event(imfs: &Mutex, rbx_session: &Mutex, event: Debo rbx_session.path_renamed(&from_path, &to_path); } }, - _ => {}, + other => { + trace!("Unhandled FS event: {:?}", other); + }, } } @@ -100,11 +110,11 @@ impl FsWatcher { let root_path = root_path.clone(); thread::spawn(move || { - info!("Watcher thread ({}) started", root_path.display()); + trace!("Watcher thread ({}) started", root_path.display()); while let Ok(event) = watch_rx.recv() { handle_event(&imfs, &rbx_session, event); } - info!("Watcher thread ({}) stopped", root_path.display()); + trace!("Watcher thread ({}) stopped", root_path.display()); }); } } diff --git a/server/src/imfs.rs b/server/src/imfs.rs index 08fe7157..f2c611e0 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -1,6 +1,6 @@ use std::{ collections::{HashMap, HashSet}, - path::{Path, PathBuf}, + path::{self, Path, PathBuf}, fs, io, }; @@ -24,9 +24,12 @@ fn add_sync_points(imfs: &mut Imfs, project_node: &ProjectNode) -> io::Result<() Ok(()) } -/// The in-memory filesystem keeps a mirror of all files being watcher by Rojo +/// The in-memory filesystem keeps a mirror of all files being watched by Rojo /// in order to deduplicate file changes in the case of bidirectional syncing /// from Roblox Studio. +/// +/// It also enables Rojo to quickly generate React-like snapshots to make +/// reasoning about instances and how they relate to files easier. #[derive(Debug, Clone)] pub struct Imfs { items: HashMap, @@ -66,21 +69,21 @@ impl Imfs { self.roots.insert(path.to_path_buf()); - self.read_from_disk(path) + self.descend_and_read_from_disk(path) } pub fn path_created(&mut self, path: &Path) -> io::Result<()> { debug_assert!(path.is_absolute()); debug_assert!(self.is_within_roots(path)); - self.read_from_disk(path) + self.descend_and_read_from_disk(path) } pub fn path_updated(&mut self, path: &Path) -> io::Result<()> { debug_assert!(path.is_absolute()); debug_assert!(self.is_within_roots(path)); - self.read_from_disk(path) + self.descend_and_read_from_disk(path) } pub fn path_removed(&mut self, path: &Path) -> io::Result<()> { @@ -132,9 +135,7 @@ impl Imfs { Some(ImfsItem::Directory(directory)) => { directory.children.remove(child); }, - _ => { - panic!("Tried to unlink child of path that wasn't a directory!"); - }, + _ => {}, } } @@ -153,6 +154,38 @@ impl Imfs { } } + fn descend_and_read_from_disk(&mut self, path: &Path) -> io::Result<()> { + let root_path = self.get_root_path(path) + .expect("Tried to mkdirp for path that wasn't within roots!"); + + // If this path is a root, we should read the entire thing. + if root_path == path { + self.read_from_disk(path)?; + return Ok(()); + } + + let relative_path = path.strip_prefix(root_path).unwrap(); + let mut current_path = root_path.to_path_buf(); + + for component in relative_path.components() { + match component { + path::Component::Normal(name) => { + let next_path = current_path.join(name); + + if self.items.contains_key(&next_path) { + current_path = next_path; + } else { + self.read_from_disk(¤t_path)?; + break; + } + }, + _ => unreachable!(), + } + } + + Ok(()) + } + fn read_from_disk(&mut self, path: &Path) -> io::Result<()> { let metadata = fs::metadata(path)?; @@ -195,6 +228,16 @@ impl Imfs { } } + fn get_root_path<'a>(&'a self, path: &Path) -> Option<&'a Path> { + for root_path in &self.roots { + if path.starts_with(root_path) { + return Some(root_path) + } + } + + None + } + fn is_within_roots(&self, path: &Path) -> bool { for root_path in &self.roots { if path.starts_with(root_path) { diff --git a/server/test-scratch-project b/server/test-scratch-project deleted file mode 100755 index f227ef13..00000000 --- a/server/test-scratch-project +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -set -e - -if [ ! -d "../test-projects/$1" ] -then - echo "Pick a project that exists!" - exit 1 -fi - -if [ -d "scratch" ] -then - rm -rf scratch -fi - -mkdir -p scratch -cp -r "../test-projects/$1" scratch -cargo run -- serve "scratch/$1" \ No newline at end of file diff --git a/server/tests/imfs.rs b/server/tests/imfs.rs index 39ffafc9..f9f55393 100644 --- a/server/tests/imfs.rs +++ b/server/tests/imfs.rs @@ -232,6 +232,16 @@ fn adding_folder() -> io::Result<()> { FsEvent::Created(file1_path.clone()), FsEvent::Created(file2_path.clone()), ], + vec![ + FsEvent::Created(file1_path.clone()), + FsEvent::Created(file2_path.clone()), + FsEvent::Created(folder_path.clone()), + ], + vec![ + FsEvent::Created(file1_path.clone()), + FsEvent::Created(folder_path.clone()), + FsEvent::Created(file2_path.clone()), + ], ]; for events in &possible_event_sequences { @@ -294,6 +304,10 @@ fn removing_folder() -> io::Result<()> { FsEvent::Removed(resources.baz_path.clone()), FsEvent::Removed(resources.foo_path.clone()), ], + vec![ + FsEvent::Removed(resources.foo_path.clone()), + FsEvent::Removed(resources.baz_path.clone()), + ], ]; for events in &possible_event_sequences { diff --git a/test-scratch-project b/test-scratch-project new file mode 100644 index 00000000..da79446a --- /dev/null +++ b/test-scratch-project @@ -0,0 +1,21 @@ +#!/bin/sh + +# Copies a project from 'test-projects' into a folder that can be messed with +# without accidentally checking the results into version control. + +set -e + +if [ ! -d "test-projects/$1" ] +then + echo "Pick a project that exists!" + exit 1 +fi + +if [ -d "scratch-project/$1" ] +then + rm -rf "scratch-project/$1" +fi + +mkdir -p scratch-project +cp -r "test-projects/$1" scratch-project +cargo run -- serve "scratch-project/$1" \ No newline at end of file From 663df7bdc28fd5cd665cf0f86dc873906c50eb28 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 11:23:19 -0800 Subject: [PATCH 0402/1504] Remove redundant debug assertions in imfs --- server/src/imfs.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/server/src/imfs.rs b/server/src/imfs.rs index f2c611e0..26ccc4db 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -100,11 +100,6 @@ impl Imfs { } pub fn path_moved(&mut self, from_path: &Path, to_path: &Path) -> io::Result<()> { - debug_assert!(from_path.is_absolute()); - debug_assert!(self.is_within_roots(from_path)); - debug_assert!(to_path.is_absolute()); - debug_assert!(self.is_within_roots(to_path)); - self.path_removed(from_path)?; self.path_created(to_path)?; Ok(()) From 4516df5aac4c9296ba30256d5437e9ffe06564f9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 13:58:24 -0800 Subject: [PATCH 0403/1504] Fix message in rbx_session --- server/src/rbx_session.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index e1edfa29..47a22535 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -153,10 +153,14 @@ impl RbxSession { // If the path doesn't exist or is a directory, we don't care if it // updated match imfs.get(path) { - Some(ImfsItem::Directory(_)) | None => { + Some(ImfsItem::Directory(_)) => { trace!("Updated path was a directory, ignoring."); return; }, + None => { + trace!("Updated path did not exist in IMFS, ignoring."); + return; + }, Some(ImfsItem::File(_)) => {}, } } From deb4118c5d24acc99db0ef55d9fe724413192a19 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 14:00:22 -0800 Subject: [PATCH 0404/1504] Fix long-polling mixup Fixes #110. --- CHANGELOG.md | 1 + plugin/src/ApiContext.lua | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b15b44eb..6df231e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [Unreleased] * Fixed in-memory filesystem not handling out-of-order filesystem change events +* Fixed long-polling error caused by a promise mixup ([#110](https://github.com/LPGhatguy/rojo/issues/110)) ## [0.5.0 Alpha 1](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.1) (January 14, 2019) * Changed plugin UI to be way prettier diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index f8fd2fe6..540a978e 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -143,7 +143,7 @@ function ApiContext:retrieveMessages() return Http.get(url) :catch(function(err) if err.type == HttpError.Error.Timeout then - return self:retrieveMessages() + return Http.get(url) end return Promise.reject(err) From 4767cbd12b7bdff0f42ed5fda0fa52e6dbc19179 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 14:36:17 -0800 Subject: [PATCH 0405/1504] Fix composing-models XML to only contain stuff implemented so far --- test-projects/composing-models/src/XML.rbxmx | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/test-projects/composing-models/src/XML.rbxmx b/test-projects/composing-models/src/XML.rbxmx index 67e8b820..eadb6971 100644 --- a/test-projects/composing-models/src/XML.rbxmx +++ b/test-projects/composing-models/src/XML.rbxmx @@ -5,12 +5,10 @@ false - Lone Script {C62CD9FB-FF28-4FD9-9712-AD28A1E92C84} - - + \ No newline at end of file From e5d3204b6caae15347d5284e28c5a5d9923af71b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 14:37:35 -0800 Subject: [PATCH 0406/1504] Implement .model.json files Closes #97. --- CHANGELOG.md | 1 + server/src/rbx_snapshot.rs | 79 ++++++++++++++++++- .../composing-models/src/Remotes.model.json | 14 ++++ 3 files changed, 91 insertions(+), 3 deletions(-) create mode 100644 test-projects/composing-models/src/Remotes.model.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 6df231e4..b635a506 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## [Unreleased] +* Added support for `.model.json` files, compatible with 0.4.x * Fixed in-memory filesystem not handling out-of-order filesystem change events * Fixed long-polling error caused by a promise mixup ([#110](https://github.com/LPGhatguy/rojo/issues/110)) diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index c1f4c39a..fe3a2637 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -6,10 +6,11 @@ use std::{ str, }; -use serde_derive::{Serialize, Deserialize}; +use failure::Fail; +use log::info; use maplit::hashmap; use rbx_tree::{RbxTree, RbxValue, RbxInstanceProperties}; -use failure::Fail; +use serde_derive::{Serialize, Deserialize}; use crate::{ imfs::{ @@ -53,6 +54,11 @@ pub enum SnapshotError { path: PathBuf, }, + JsonModelDecodeError { + inner: serde_json::Error, + path: PathBuf, + }, + XmlModelDecodeError { inner: rbx_xml::DecodeError, path: PathBuf, @@ -71,6 +77,9 @@ impl fmt::Display for SnapshotError { SnapshotError::Utf8Error { inner, path } => { write!(output, "Invalid UTF-8: {} in path {}", inner, path.display()) }, + SnapshotError::JsonModelDecodeError { inner, path } => { + write!(output, "Malformed .model.json model: {:?} in path {}", inner, path.display()) + }, SnapshotError::XmlModelDecodeError { inner, path } => { write!(output, "Malformed rbxmx model: {:?} in path {}", inner, path.display()) }, @@ -248,7 +257,18 @@ fn snapshot_imfs_file<'source>( Some("txt") => snapshot_txt_file(file)?, Some("rbxmx") => snapshot_xml_model_file(file)?, Some("rbxm") => snapshot_binary_model_file(file)?, - Some(_) | None => return Ok(None), + Some("json") => { + let file_stem = file.path + .file_stem().expect("Could not extract file stem") + .to_str().expect("Could not convert path to UTF-8"); + + if file_stem.ends_with(".model") { + snapshot_json_model_file(file)? + } else { + None + } + }, + Some(_) | None => None, }; if let Some(snapshot) = maybe_snapshot.as_mut() { @@ -256,6 +276,8 @@ fn snapshot_imfs_file<'source>( if let Some(snapshot_name) = instance_name { snapshot.name = snapshot_name; } + } else { + info!("File generated no snapshot: {}", file.path.display()); } Ok(maybe_snapshot) @@ -402,6 +424,57 @@ struct LocalizationEntryJson { values: HashMap, } +fn snapshot_json_model_file<'source>( + file: &'source ImfsFile, +) -> SnapshotResult<'source> { + let contents = str::from_utf8(&file.contents) + .map_err(|inner| SnapshotError::Utf8Error { + inner, + path: file.path.to_owned(), + })?; + + let json_instance: JsonModelInstance = serde_json::from_str(contents) + .map_err(|inner| SnapshotError::JsonModelDecodeError { + inner, + path: file.path.to_owned(), + })?; + + let mut snapshot = json_instance.into_snapshot(); + snapshot.metadata.source_path = Some(file.path.to_owned()); + + Ok(Some(snapshot)) +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +struct JsonModelInstance { + name: String, + class_name: String, + + #[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")] + children: Vec, + + #[serde(default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")] + properties: HashMap, +} + +impl JsonModelInstance { + fn into_snapshot(mut self) -> RbxSnapshotInstance<'static> { + let children = self.children + .drain(..) + .map(JsonModelInstance::into_snapshot) + .collect(); + + RbxSnapshotInstance { + name: Cow::Owned(self.name), + class_name: Cow::Owned(self.class_name), + properties: self.properties, + children, + metadata: Default::default(), + } + } +} + fn snapshot_xml_model_file<'source>( file: &'source ImfsFile, ) -> SnapshotResult<'source> { diff --git a/test-projects/composing-models/src/Remotes.model.json b/test-projects/composing-models/src/Remotes.model.json new file mode 100644 index 00000000..67748fe8 --- /dev/null +++ b/test-projects/composing-models/src/Remotes.model.json @@ -0,0 +1,14 @@ +{ + "Name": "All my Remote Events", + "ClassName": "Folder", + "Children": [ + { + "Name": "SendMoney", + "ClassName": "RemoteEvent" + }, + { + "Name": "SendItems", + "ClassName": "RemoteEvent" + } + ] +} \ No newline at end of file From c6766bbe77d0f0023541104c841eb54306f1d1fb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 14:55:56 -0800 Subject: [PATCH 0407/1504] Fix timeout issue for real this time --- plugin/src/ApiContext.lua | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 540a978e..898564c6 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -140,14 +140,18 @@ end function ApiContext:retrieveMessages() local url = ("%s/api/subscribe/%s"):format(self.baseUrl, self.messageCursor) - return Http.get(url) - :catch(function(err) - if err.type == HttpError.Error.Timeout then - return Http.get(url) - end + local function sendRequest() + return Http.get(url) + :catch(function(err) + if err.type == HttpError.Error.Timeout then + return sendRequest() + end - return Promise.reject(err) - end) + return Promise.reject(err) + end) + end + + return sendRequest() :andThen(rejectFailedRequests) :andThen(function(response) local body = response:json() From dd2a730b4ade6324d45e7aba6a748fd7f012b8c6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 15:16:42 -0800 Subject: [PATCH 0408/1504] Update documentation --- docs/extra.css | 3 + docs/images/connection-error.png | Bin 5928 -> 0 bytes docs/images/plugin-buttons.png | Bin 17614 -> 0 bytes docs/images/sync-example-files.gv | 17 ++++++ docs/images/sync-example-files.svg | 38 ++++++++++++ docs/images/sync-example-instances.gv | 15 +++++ docs/images/sync-example-instances.svg | 28 +++++++++ docs/images/sync-example-json-model.gv | 17 ++++++ docs/images/sync-example-json-model.svg | 38 ++++++++++++ docs/images/sync-example.png | Bin 1931 -> 0 bytes docs/migrating-to-epiphany.md | 3 - docs/sync-details.md | 76 ++++++++++++++++++++++-- mkdocs.yml | 3 + 13 files changed, 230 insertions(+), 8 deletions(-) create mode 100644 docs/extra.css delete mode 100644 docs/images/connection-error.png delete mode 100644 docs/images/plugin-buttons.png create mode 100644 docs/images/sync-example-files.gv create mode 100644 docs/images/sync-example-files.svg create mode 100644 docs/images/sync-example-instances.gv create mode 100644 docs/images/sync-example-instances.svg create mode 100644 docs/images/sync-example-json-model.gv create mode 100644 docs/images/sync-example-json-model.svg delete mode 100644 docs/images/sync-example.png diff --git a/docs/extra.css b/docs/extra.css new file mode 100644 index 00000000..020a7103 --- /dev/null +++ b/docs/extra.css @@ -0,0 +1,3 @@ +.md-typeset__table { + width: 100%; +} \ No newline at end of file diff --git a/docs/images/connection-error.png b/docs/images/connection-error.png deleted file mode 100644 index af3c16faa69226f1e3a2e58a4c6fff74be10cab2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5928 zcmdT|XH-*7yN!b4D=0`+stSs9rHIlZ(xeNBbPz>~5ds7Pp(GZhNR!Zs5NSf_Aib(c zCq!x}0xvZXN`%lu!VSLPx9+;@e(V0fKTesmX3soj&pc;O#6u&Ub7y(a0sw$>x(_r> z0f3Vq>F)t&PSWq`g`Ar7#|en3&V4{hAOAAF!RVrHs15*>$1)!}o}#z^@_b+g0RYao z9$zOq!1+$}kL*5LmOf@+XCFUD@8%BhnS z1``<>$M)9a_I%{lJJSv+7Ag zFVy*Q8lRVN_ElkFSvfs(adRTYh(C^t3pO{!r#PD@p7=A)29G#9vBp_3;J zvQ13{5!5KNt-HXzSRieAjx`nm+xfWls|iM!Xn6=s$dV*hOrQ@8Gimp->>>_33&)8d*l>qfPyO>$%iN z*R7k$PxjZ}hWRC9@qs-9@(cm)f-i8YgTl{5qLFN=ppDi!q;~2GD$*g6L4s8Jk6HK4-49<53p$>K!1^C-!*mL3sp=KvIZ57vr4dljZz`RZ<>Re zm5T5FtfHUClzrgVUfT%S!q~w>4eq_RX};Xzzy3WMgl}s$n2+wPiej0luS`_HYo~)Y z&F{x=%X)R$l2YrOv_$M|K*mm2tz@m#{@NKx<}oA+stg3Cze}u&PW08S!c~J&->Sgg zl*G~&)xZNeMSMqINzit&ljX>RBpV{Rw`&mT)K$P4@ujZbQF?U^>4Is`S4}L1Myzco zf!Qakz@_kwWrC=h^-yhz9nEO*V1vji8~H<`M-;|A*WPD6+&C6p>|&guhS*%Kql)7P zeiTJ{8M~($?TZ@*#V;hCRE8afjAZuG{lw?RpcA4m?AH7zX%3qrsnJLxQ!wsXK_ zHzW>AFx>&dci%qR9ysm;(fXdCCns#keAEftF|x;{vWyQ&^R z2)pL))XQ8F)G6nR)EgO1mNqa+P%vr7PVD9~3-&sy_Zp>tRc{O_0YVPAzN)^F72UA{ zv}=LQ?nMlW8aq^1r8Rr?DA=jHeO6mo3EeNivV^Z!7>WiQy815v+6M{-?v9dTn|4X0 zuKW5v6%guLiTgOW?a<<+yp}RAhkWV-@tI+AGAl_2txRcaIUEEE9sSPsgYTA-Xft+W zq>7Dea?Z+33Sfh=z{#o_HmUR zjdLObCQJZ8ir>ea!u%sqdZ%6~qk#*)0Kh9)hptlAc{+;pf1!klbPT08?(}+umlrZ7 zpP@I+Avs21*e-Z$lvr9Khb`6D7Z5g$^5X#*uug7XS&ul4bwR1ViTBYIc=GwM-e;@R zB(JWeL{Qm#ezaiC`0CqOX|5i!zu$?koNmO*20cfuU+2!0YJAM0&-6uv+cwTOSdu5P z(IQ!UlZ))RJ=*`QJgX4^E_&=_M&prlc>l-ssy0!H>WR6I;vc4S*-@qXO2g zs^yA*JSInkA3W$e@%M*6iAphM^95X-`R|2Q>gqOQfOfU^j>ap zmFJDt&c?bykn37@G&&Vt)iE3s;NqD-e7JY-m>#E3{>eKVeKNqS*Piz@gI!=Vo!>WO z0)70iu+kZ!CXm(Kv_$g`?A$95Ui={WT7}Lf&LxUou&iuIir74TjL%=~k6~WlnxGCW zXgSgqWp3`8?TAmtm#jDjO=7?ODywZ;b7oU6amZgxv`P-d%yst1Y206GAz`r-twJj% zs-f+TZ7{a?hm3$%tv!2L9`gC7;@MJ(MV3{V(Dj$35XIbPg|ZYB5oft=V_D5Hl%YT- zGAO&Z|9u9O&)%B8wx-9eal}BWgF&dpum@PsjZO^=8UXP0zi{Db`YgGuG+#&Qsi2Yq z$SmdLt-@`_Mf17U=M>wRzejj|Ewp33$<7C$$qfz+OzITu#x@7N(#r&1*gjJ#t~}8b z$-J|?w6?^4t8n?z@5`dzcbzo#NLhdBWFMoj<{@fvsTN)J?!Chq5lZ#cKOWd?HkoPj zvJX4-R%DrT^enocdjUO3EQu0aSj27-dI{*8ob#DO#sI*b#wZD5wN6M5aeS-<9-vnL zLN9>}U4JRe8p6tA)h{bNymS$0mK-QfIC-Q2gpd~x$gmH$vPFqP(q+55J#;7aq~&s{ z^fVbq$q=>kqd0FcGxr!h(tM)bBwPjAv*8^%lq)cj$}$h;4SJ7;gVkKgqNz+*1)GNeNyDNaw(nRBPI zH#46B0JwKnQ-IFF%a@6eK2+Oep$-&*+A_W}R8*~40uK5-KYwxSJ!nFup?Os>x?^H( zvS!^|T5KC(y3r1WLh;YbxhJ!!gufG{?*Wyxf&=}6GnJTlpa`;%LNbl$nef>2b7e-`=)bUeH$NUPwGxZ!>%LS_m!VV>63W#&eGt<1vvKxw9YvwxSVw1?yv?y z5fyeNqJH3l1;V7p{FXTKz3zhhQ3PBgO?w%(Uq3f-mgQAWJofyopr&84^Y#^4f~ z0kKTY)#t~%e4c*|E>2`}KOWr3gf;vJE}qSoa<#V3J<33O)Nb5t$PD_ZxM@piRsGkN zl>QyHt#3k0viknDr0o2aM%v{-6ii1Q+|S*N?2IF)Z4@^+zn|^i zkKdKEVa34oso+ZvkHV~!Z%dCYpYqC08KV`%Cf^GhURZVYdT}AmnL2dnulRkiwDUaw zNj=R;bKN=5giYQisnSuU$XJGkGKoP3?MW&a=K+H9E-^tfB(Ni;vI7i9R`}jcL z);+AuG^W#!wY?_v&ho1+c0na+?&$hW_3wXm_-9Q{-Br_Oy;JDvt<=uvpO6z}GKvz6tEO#UEd{{+ub) z7;J(+J2J_Y={sHLW*9d%8>2bd5?yLO>ZYUnzJB6xd$x}q9%f@mR4icRiU`1<+gm>k zixj^mx4fA0_xY@8!rcF=Z{yast=62v!1xtD!K>dgAEWRwUa&8k_Lsi@+OaAPHN3_L zZa2=oWHE>!7-P^$np55h?R1+5r!&xtje4(-l462(FdF(#rv_?edtV|jN3%P#>!?pB zZB|{`56uLD*Bkv?>*j!;Y z_b~Ev1?jJ5Y;)n(?64jaUW-1oK}&!sDEd%d?DzBlzk_X9(vQYmujj|i@YpcS25kV7 zgQ|q7&i8^ni+#slXAbHNt=YdQoIFs|WjC*`uKl|x{g*n&1#sTMmEpQEpLqOj7az|~ zv%0sXKX4iIj1^?Ih|@kXv2IwKS=%%1E?Sc@f2~~E?EY}K=!^VI@iBinxHz^pji!vy zqgHZ$%**v!IPBUIl`VBzG}qhyB#aIw{zRtK$d|ClO*n9EcB=!qKa9%wR&>?Ov{biH z<{~}$m2Y|~Y1t{7XM5&q>!9H^@3;ihOc9O?S|Q3;Dzk+qFkG%AG={l3Z+|E7i>S)w zESIKq&sLwkI+qvUIRu@Ct0D@o7~O9yY-sNo9nI}p#H)lb1wVbxF#Q5|diMpwwFAb! z2#hMvIO2Dsl=9!Hwn))ItrOrpM3hH6BSlEz-a4K9946`s6hjeE+$`?pwTE z<|g*wb=qu+bz}BHWPocPj%nS;>>XCWfwQvsnOi^80#b|L$c|5FbVIqi6{l)8@q0LQ zs92(pflBHX#b>JtDRCa4=!@2mk!N58C3DqsL85`GhB1-4~w-j;+v6j)K{?@3y@!uWlx}Ur+s*PZ8Q%8@~1`RSxqH zkY0KiPW>M zT;r*$QE)+>w%#KT%L&f6Y%M?XKCo>wuw<>5ne)Oqhe%fLSch}iThn6h^O@b{%*<7 zl3Lo2PpbZfyE?S*Y0nWED66$_WE(#!@;03LbWHKU=X_ACy-40UkPu$q<6IUpF5Dw@#0r9@&t7()M`F?hnRKI~_>fS^ zxcrs-2WU;jn3 zk4Lb2{Iy;eXs05OMy*e zMjH=2%+ip^WB&%}-Ty|;VBffu7qw|utzEukO4PK&X-zUFtU;vg=wL5V$V=*7~Q9lSPT&z`H*+0?MOf$+%-3`ISfWP){`njcyP7 zR3%d<#^Yt_Y+Lqaq5$bLJbRYfzf!QTG+0qswWIQgYZWEOwV2l(fh=0RwaCT(`TIo% zq3c{0k?BshZycEAKB?7?)UQ^4P|+M%L5iw^Jp|;AU0{bhx8t=#pKZ?X==ZC2x1+jT zdX%_tr47hy*kKD@xkhX_ z)SQc^kV#FQYmaZNA)k3h^&RCABXkb)#wMPp=*u0S8BiOiRHI6w#2a>CAiIaiH*lFX zZ25jZT8-f7(#)?MM|!!{VdNplSgsTHtfHa=rRXUB4YV`#{u8aJhC|vt3?0~> zpwAX#BsH9Us-W2|PvYk%OVEDlQ?KR8<%3n-bz_aiRX_KFX0r8n7G-agr>WP%TIH&x z8GCiKtw4{_d4l6blfEOBWf){7r3X?njokY3yy-h^GQ}-Ewx&|>ef}5=#MCa5I2j+&k?4SfgI8lagA?an$>adK?L+7bHL23{B@g6sK%s_tC z?l?bgjRCZ*TC1i#Q)(8G%8F9R2>1vP5D>^R(&DNR5YSrS*GWJq@NYt1CT#E@NM}_k zQHZK>!Xxk-fVqf*2n0lJ9OAPv4EQ~~gS56Y1O!U&pC8Bp`w~;|hZrsrS}tn#pIqFH zoy;JloXpJZoGt8K4Ag<(DdG|`;vyeB3{JA(ld*5I&d?3UJ%>hlJk43{_eV`r?$%A~ z#@?|Vn38j|r2jPiwqttr8Q%=!!=xu$x;$0_jV`8JNQwlOh*`MZ?Vek31Up~D@HgRl zTK4Ek8(H_@YtAA>*mF+Lr$tlVhKQhm3SQ>^wGRxcx%z1BcW zQ(_P@v9q(mw((?7C{h~mb1o}q|0dx`zxbow_8Me3P&9u9I(f9L`u3X&_D0|9U)B`J z!}pNfy)e<N_aO3ouGgtDUn?u?Wzztiw2nZ@M7|P6=E53+lvi`##o!6p}O)j{Og7VIZ zSnsF(4UN}}f?lqU>AZvB7rBj%VT~WxBcA7lYg*~*$h#oiOA9gudxAoed>9uz$BJ`1 z0=X-EBCKNFyMtLJgWzv@e@CCOEbz5@O4qgVE=}gF_L)iD^!iyz@jHEnMUmmS*|L!H zuS>S;{GV)eu=nimY7*x*NgVNYYgbf|T-9V}wHez~ITd`vc+&P;BonCCaz(>6QKnW; zl+I1{iA1{sZqBmwah%&2Zqj~9DY8YIWK)?Ib)@S)pf}G&wV3DKSpG89Eee>L`bSC_ zER+C|t)rkbx!(DjXQA}x>}*so70xMn{l3Pyu+L-=7!EJR*n>Cglu+WLNrvBAEnp3SvATL3Hv>0eDnQgWFgJ-^{NBlubt>}%nuOQ#VKCRsYKZs9j6uGECoflF zUXgKH-RIb_zXPY)5p@5#_|q>drDf_*4X@`yVQ&6~`uoqjc^iZM=|>CRCPfEcN~}X! z6vZwM*JAd#57vmqA4xxH;OWp-qwe5KB@{JdD}J&)y%|`H>+xU8)7Y5Q)leJjp{r8P zdPxm23NZQk13?4_q4}AkFwg%#22RV&2zc}QjY4~)ciWmk(8X_qE$9EMFS@R9=K8pk zy_7jMEPlb;5m!O~Qot(Ujuhr|cD1J4+5|a|jdiSiP0iPT=K*{9LIRO`%~y_v&6~||6Lr# z#o5Wj6J}f;R%^G14!6iZ-q@^?Y>wDpmaE^j-m3jNZX9_&;yNDEXAdwuBO(i+G8Jo< zbS#QgMyo+pk`SBeB@<7ctb62IBI3TInKlAO{-zLjZWj8f{x;;rTfo%~v|(IdGGh^t z{a`|yHxysk6YH5FolxvLf~*4{k`$|rcMG}03KR3MR8k@$!zE7J?{Y|p&*wJA9)91i z<)nJ5;|3YM)nB5$9Xl&^km`O5We#T*`*+BFfd`c=`QEMF^}ccKg7NRoWjm0VshNer zV+K=Ai0x=miNt4A{T;)kGVovHEL=bmRc`k7e!B!?>vMY^-P_0K40nG1N%g3dvH$I= zI^cf*n!Q2wzacaY;9uLC9G?BJ33*>iU9Bb203zF)Yl#6$up;r75TT?&q|*EWQQOs` zOghRyGU?VpQ8W=W3S#hUpsGtQnm8ID5)LZ}7=%Sc13(AQh5R!`Lh1s(2mT9POn-EA z_(k~&^{3@^LANjVZ1#V5I0Z&=HlB2kV>=uL*Jkn&}+^h0L^9ZCqzl-V^WiyJTR!U z^Qp5!r{?KE(%)6`iQ2o9)nWCR9u6b^A-s9?DXHrw=T+S|j-=xE>)ermpwRvX+*}QU zr0{LvD*=bq>}VR>!9&fdM=E1EaF!*z>a7Qe8{GZ z0WH81BWN7k-R9)oOfmJ_m)r@}3qHtMhu>t&oHDW>9~sDuxVsm`6ek3KAXeMQ=erX^ z$Fcw?zdPzhUQeXTEV98;(Yz!JCOr;&rxCqdLydAo81qiy-L|vBMo(?-f~$Qu?AfND z2t#i~R%!NxDGKDA$aHBSY3@&JuZkY6Z?}xvUgh^{GPGq=T3K*k;H=xnZu}}p%2UUB z^qKqZ_h~f!1TI*rs&-g~Xsf>cZcCevYy~jZJp`|xK2-PJlB}}Y zA3D3%JdEXZF7J$BzCCh1y?rvBq5iJ9wqrfh?r)~kd{%krrdu@dl`6*5k z>6!4`7??-gX1^C}o%cuI3HkBw3f-+bD;GC4-5wR^e7Zx_ro)wgM%FsNi0C7UF>tc_ zxm`c!ikz{|)9N=7X{L+s_FJfRXKlxx*oNQ#NNl}3{3BY>ZqTwblA7kODBYz96vQ^Z zLe+wR_wcuS_w0bJXMtpAQm;^s+sBlUW-O_Jz#WWgfzwj?Iu=+{(DRO29X?_-H6J4( zk(W0$&uFiJ+&~O`2_9tKEE&Q#bDjWi3iY(#SY$r2j6U$xfY8DAMSf>LlQ5e48c_## zhQsfl%HD+6^_`k1JJkbb$t^pvONFhcsZ?nn1Hd*p{F#OXxm_{;^s2Pf2`OOQ`!4gO zZm51<-ph5*xw@jn$J3J gP^_yV_)_OyGr@cJsnFjNpBA%_(f zg)n-RPNUUkcc6ACX-RiV+{!X9uRAgSjiYXOgFc*6qq~bJx`hasfn;bwr_nT6HMXkx zN+h18p$)&gm(=<1QE?CRT*PKC|K*!@KQ@7&ZMU~{scjk=JX!=lMC`od=HcWFpNAPC zlL1%54K~pTq&#C}Vzx>D`3q&HP%FI1``?EG9S)-B+l5gNzZr95sQ@D9Csq|k?(c3i zV#n+M;gQ|*TaAZO`0K$;{J}UOWS0A3$4MQw>zOnnIY7wuN>AFS?qHO_(BdioiPQCM zwZxpNqsN+^>(0+d;_iFS>PhTPF3>XtbJA_(D-#K;>0pQFl?ToXJ>F$FG6C#1Dg|jl zFR*7yPEo&e-E&U|4k&U@TiLb6z8gHI=YCn4-=&0O*y==y1ELWu-|lyIhSgY&oTvh^ z9=^#vP4bC~r;6yz&bCKcGhLD>ejY)8HxAVW^Csi7JP?|{)9o1f?a~70i%cRrrJO#z zvVe=4H4$noim})a=Ow92=6m8_)YPB2Ox@FmcX$lGdZ14QdVBaT(Whpf0TqY$VsqWB zmBlnZMee8lF3Qz-2-e@tH+G_9SvmLtfgl2)<%&`T61Q8xX=#A&E8jnr+l@qf0mFDB(%0o4OsdteD8UGZk#Q#)M$-6*d-DSTl*9Q3f&CX zT*;_vu;p_=@RNns2R;}nLzXG%FN|k+Mo0kdTz)t^_qT4pwucQGy@>!c)O?28;ik$}>FkPGRL46sJRL zCg>2NJlus?PtdCHP`@Qvv-EI;*b2#g{#@?3Kc&}2UeZ8x7P9`F^hIL(PY%?AK?MggQ+IP_pM%S0^VOz~~|ojU#eYW85nlgNLpP%(l0)?zq0# zcUStMWXXq;=)(*Gtaz}YZiQ}sq0{upC~&B1S^bEskuDVo)ih>}rrv)#Q;L$Q-xvJm zu*7c~p(jPvmw}0Sdg0sedT&1*!u~Z3OO??(34Yngvc=nQ%hBUx(IKCYP>Y46WOPpQ zT+vXZJ|)o*`%v;ech^lyd22XC!L2x+j56yu-x$qD5@caGF={_b*eSl7i+B}2g7Vjm zqgSJSh&V2kEWxyN6F$gl{RpE4hKFAnS0~@S+AjQ`&BgBgJ+{IKa?W1A;F3;(aThLT zZvy?za$<;Um0jqbFX+pcFFONqB)l#(BifBtb81QgFwxpA0OB!bg!3<~$#0HD!b=T^?1)D3n2%D-Bq=hnO)Ov8U-oS^R~8V}zk$p|t4%DnQG4U*34=b56xnv}BD9 zhqfE9fh9SH10kExpRvKl8?;2xXn<6lm|Q6If>n4BU8Av^b7Z#7F8lowm7CeqkPh)LcF_|> z6UL4pRS^b7kV;RfB#YKmt|8Pshipb8uK&IWt>s#6+YQSo2h}=0u^4PBiHSi=cN=3# z+pJmnJvERpf?BRNOW8;agw|($ZdDN}e%+dR`sPwd{<$00f1=-A`3z0e$LgnrPu&ym zqSv=umlm6B38cHhSlBbcpxbo5>L3lzU0bwsVzSUg!hN$IYArQk@URKKpTUN6(87qM zx;l15M};uQI)q5PDR`-Pwe7BAVsaT5o%Pb8MjAWn&LOK<&)eMhL(RQC#DqgPZluh1 zu1_KI89rn!c4rr^?MgPQ-g;D8fC<38+ag!0wTSth$|pgX0*zpxl_x)YX-v0F^{= z6&b}F01o(ZTC(5k+_T4P8857rm6gFD;?V0h*-!?#(AtD&^1A+tdBY|MBqz253<~2iTK>0MA}fA#HxyZueM_TNfCfS6p?DcA7Ac&gd&oVN#pjo z4I&e8R_Hd{EmY~#0CpgIwIG-W`w*-2#fNzU3Yp#G&_bdwZjKjL&kA9_c88L{b*FF?B3|Fe>$!4GhLP>Qi=aPqU@(JjZf>I4 zjgoMa$wGM)&Nlo>lS)gg43JS6`&K$-H3 z9qMi>yn;Na>gBmr=Lsfo8kVnuzwo1o?iTZkuXmAcE-Uz}mbuU_@=hN|N)EElDvwQ? zYhGIOaE8-7ORe%CMAg%gPPQ!E#Wvs;ZjP@$xW?-S92Qp^&Bic1`irVD@lvZ{ilt$|PLNQF{JY(q74NaRykSXc-K z0G7-<-kSa20;8g~lp!(r%jF!8ge*I_@e4szsc4zCQ#$q3gDKz5L>h~6+%)Lx85_@= zSfH|$bdHH+| zU>X_@<@ZuOb<$A7_)F!@BjWrxeE2?pt#NPI%hMefC#PsuY9r|%p8jM6Yy|{%3I7t& ztTE3K^lhuEswyjsIuarp3?VCln9BtNd2dT>vvcKquyxgj%1!OUYwP2VxjU8jAf%5YO+Y>=#~snXkdaD)^H z9^WB&l_u%0YU(cRp#6suVSS+D)2U5Lyac_9^mZ0sNq0Td+v)5mweI}w+2XTdmiqTo zA6uP+^&t|5U*3BUa2Zm!51V)20StKcvSOf!f+&yB+z)}Cm|t-+uk708-dcapegT{b zx;?m}jN9clw>|3yx82Wt#+4%XijT`|G_0y`BB|wTKUH*56g_Wso$r1hZPD{(KD^fN zmBauTt7mp&Xmn#}@ws~Ft;^^u32C1q2pVW*e>k?I_3_-jzk6b8BaJMYYL%79Z~Xoh z>R#L1{A75=T1&<0C*K{I{d#47mzTOs`u1sdu3Z*H8S}NiR!>v3l}}Vn6?hx`{;N-7 zr?8dtU}=dmG(82;01`f+=c6^y(|toQ6{emNBKK?Q_u*4s4tgQ#u!8#Om;PxYbar8Z zi-Y5$!bbQ-isXf3#T;*&sIf%25a~Cjm|TC%SGC@(3M1Q>s@7r$5CAhh$K8hts7s; z9H|Fh_>+cyuQa3jRm1WOW=H`3SjR`Kps}$ryM7Blwyj@ zJ`)@hdu--GLc=O%+=@!{IVh{te;Px1;0DgZ@eFdcLH(ms=mLXkhV|K1r-bcgCPvsQ zArs#}WjXoSHll$em^l5qyPW!*N)U=rYmM`pu|Qr80n6twZ*AZ|!KoPv!0Z7bzr z>48vcBAX}*i?*B90R!ybFVHpo1kY?jrUF*E!S?Z&x4GH_mU5GLGlklXvz6N8z_^sR zU!!uJ6H0Ao%S|kmy2Pic?!^LEIaP}73{4YSU~gDTCJ6#|3yu})0dg_d^`|fvN~21J zUxwm}im2k(x5?f8$lRZ0b0kp z9n<0`hSgK%!FTO#&gY5a&YB*L9grlV2qO6c`dJwz2(50DR}DAwZSLD#hd8_ky}P2a zdQqB4djK`>X{vSJU`kW;@)SZa;rVfbRu&do;0S%Mnb_v-Ui<0icUR6;ci$U<1;f|x zCy4&*tp`2h*4SBD!3@^taMi0ZqG+@V+t@+HN;&&h<3nK24%W;-f7c%){KC{7?LLl2 zO<*?fDA5;}$rpWkzK8ee9jef-7uiz(fMgEKp-+Mn-2D+1SB&_bk?oOiU2v<586aPn6&FI=~L6C?6E*`ycaM2az*w|9Jm11s7~5+d!X3@KD=oDsv&6fH)U<9~=uwLV#URKV6TWE6ZsAd6%Us#Q@e!-d>~c>J>U_8*8bF$Y z)(nb-gE4XEuou_Rf%G?E&u6$3hVV86pq*6>^=y38XIyPbH_<90k5JJ`>5h*yWNr7s z*Y(XEgItNA_12_t2^678FXPn#h8`o?fEkXYwic`d!MuMI9Njh&uAYlitVop z;Be(Hn0B}vCBAlb50Ln0(siK)sP2v(KEddprH^BOwPRb(Z(Nw*Y*#w0;`QsdegdoR zFdYEw>_yH4J%RuwG}&^-8&tFESOs|~C6dfLQlqsH#IowR(Sap<`sQFC0v$qHUt7-W zCzV4Um`*KLp2@6dyEE?*X%Wp3uC5r+>T!g8sn~;h`JzkiHL=-y*~}m?FcG7b(&^QF zV?$LT3RYuU6@A{n!o?z&aF;^!I&QhPC$crMd9qs}HeT^P8Rt8>C0TN_Um-Si6`Z;K zEp)n6UtCyNSXqf|ND`b(RSWESe0+30o@X%VNR{Im7PwpORW|^-fPli9lg9I0)K6Q} zwvyg&bz3&4Wjp2_O+vMqWvprVU*AK)4+_$Ma);C|07gGZi3f5Q5 z(A)&Aab^kG4(DRSr}l{^sioVq(zVv8k6eBWP5$O9&=qDIydLL9*Y;I>;9$QXN-Ko) ztG!~&&#UkS#1PbYa>g|(+m%Q{#g|+x{jtIe{MVmOWmez-54qWppLO&Uij#u_Tx21= z)Dnb9%SF#){a_@tH$y>Ml%y6Ytb*7>3jzyd$a*E5={VP3u2$o$Y57}cFh)O7+pNxW zN>-8xrgBvWA_A}{FnTZ;pOn<5+{#`LPi zvuv^)Db16HF#1}nJKlcZrxt;aFrM?puL6k{XQcRu__2DH9GP3L+ZaKbRZBA)HQ7~7 z220|%Q7^^6w?-o6j_m2o)!XA5I5fmSc!?edD8&QwYVOTG=k+P|LS0^a zvHK(LguE^#;LXQ}?lH~vuA}XFe;Yk7x>qywf}gZ>pvCNwwC^LKq}_t&W@k_U2_RXd zuN0aoNjXHoY%n;%G;h$Z|5UG(ln08CC_ybtP?w8fMGqRyF1ID=Xo0Spk9OlumZ}O! z@oEa|_>5|E_U=-(ySTh!`Q`Qz_UVqUf~CCDmt>J#LnnNEC46EfUsGF(DKT9c89xXw zXn6FIDIh0HZN3RrU$i5=l_i`yEC0T`z2>Ac-1afv^&mw4DYuV^w8>!Y=jVlU(C+e4 zne_q-!S#G3;_dIT`PIt#)189rn-|WCKDB82m&tX8u?YOmZ_a+JL+lka~TrMrrd!wt0t1Bo*7 zsyh&RlHobz8XJKEg_s{0h4wbjtooSz1#P$QwdL2-yXq5gbn$-DpY*6(_$^QoYHXl@ z7qA76Hr@?vyNvbsijqZNR$`nG|?6b1}+R<}BE z6Y&{EVkugib9~e?X3S{S=a}z>IUIH-;hGE-65oTgz(MIYN#!;HE%{L^E)-UfbeS-y zWT))xFBs&M37?y>a^%81G(iB!+6@PdbfWAd!sUL*m1{v*9;$jn7I|mTO$8Gg02K!t zPz~g(X2>Q{_RUqsJK zLqFvVR8yV(geB?^ho^`_J;*q@u$E>IV>(NfRnHx%>(XG}UG70sb+xss5rN8XGc~jV zaorZ6CBv7PYwsSss!^D4$atS>Y*PSx$jwjUs+P$$b>!SG*1<+sZC588V9@%BEfPMx z`T@Vy93BdtGg4@la?um#q^8Q?pcz7c4zCm=$k{H7ogR+uLllD(f{P8 z)(cgYRaN_!pPkM+@0|K@q0V~ACXIiiMxTH5*SmR%S-7Q+RKxZrk9k#L`U&SkypbEA z>H>rOAy-q7N;W-|RL`O}waPNPoRXyD)=;?1wCN(3=*8Xxq77KCXU*UlO(E<-WK)Nl z)jVKEuWWLb-8fLu)L&7HlIa{#0|5eZ+R#44q@rRmYxo2olFMm)0b`8TU1v zSeCcb{W0l^+yS-IZRtITp?b1}6W%Su z?j}gJY|m_(5hr@*H5@Oa$>S5_IBq>kZr)#D7Q_dUDF^m@mynW(WL|vUr9}pDTTyzN zAr+Y0H!=Ra#?X#r{Lvk2Kz6sKg^y7~8|{)Liq?^M+x~vr){Mb|iA;-&n?wVdGzxWc z^@*rQFhKO#T_9F5nnBNHlz~^ z4h(>Q(*^_3;T`q9f#1Vkm+zAkB+Z}IK4Ch`q3-4a)Mx;Z%7MQ<6TnHtJ^cLgGJ+6j z=Bzy+j`!_QdOEpVs`q<2)z@9xP=2-jPzN_OQ>MzhZj^0kj)SfH~ zoZcV1V2}xz;s?l61u{TN$Z@)2UHJF%9GZX|PvRsSHn3_&U+1iZ6EC_DQgb+1{YPPTV7u^!Kpdn5R~Y z!`9D8%%{7vjcUX1>z&>k&JzM1-D208?rkm^Q?dH&nPd8{&wos63T#r=q?oF?Z<_~T zX*{1k1j>gX_~ero=mFa>400`Y5v;2x=+cjmkH24hwqJEyvGw6&Lh(0Z@*nxwWCYjx z{Jka69+rT8*7FD%%{lAkC?j*?z+*-A4id?yq~c`O`FV6tZ2Am6vuPbF6sujN8S+UO z0vu;qvH;5Lwkz38b+|N94kgn3UQQRR{4?(t5R(2ka@Y^77@?-(od1M~>}6KMRcJ$PS6$iM(580!NQ=y&<5+Z*|6mLLw! z;1H{bKXM7mb7BbeLgfCUT7OKGXEVuwSkd$KX4r6(?TxZe!W<7Xtnfdna+Tq?OT1o1 zg#25_p#kXX=(Hq9Bf0ePjUj%uyQ(MA^yhbzdn&r)i!*Gh@{wPcIWF5Y_rdc|*d zEHA+mw4S$_REnGa&W+@R<_CMof7>VWJtGue#YI$EGq9!<*VVvYdFE}YX-I$o*Y*Ad zYv-@q^mKoXI#i={`@-8VB8!ABKjqSx-3 zUnv~RtgNh@N=v}?fgs+H98$Q>I~b987#~Mwp2e@YBK5zjg2LlV4{E4$^CM>YgKV&Z zCit&LbJ7CHxcP)G2g%*nTs6VX4d9Y&yZhO?(A$;J*-G=--S;=&_^=93ac~-PHFmp> zxm#VLAM=bGpAQtV7~Ed+NH8-k#;V%Wmkoq2LF7~Ru3l?obcUM>t>Jlsdv@oM*0jo@ zss~3BL3=-?{}&AaUOql@D-jFgm$-)(7v10e;TK>Z@}&b8C|lmuMLbOkDI#6V7n=K! z3uO}&cuyeYC;GKSI8yGGrKk8nycKtFkbF=Qgy$gTu-sr7j~WTKq+m2c9;e-2RG|*% zgK==~_OfUAYIa?m9zY|C77#W`$QucC!O#bW{j=Jy0Oc}XX=wuY5%#pB7oDy5Z^bcJ zMObdcSV4PoMTX6O@3Lbfe!q9hxj+yRwh}o+xV34~nxC6HI>SvCros||DS`b0qQ=1n zUT;k9C)%;#yNv%O0eePi=FspR?8QN%T5dxw5DQcYf4hkAL9=J)IKz!S!7V0R70vjf$^& zZ7xGM?oviGH}e)27#EmZ*YQ8WUTzDOV)joK|4ZZ}IHlJwzlD;nL_;#^;M{w>IgWfS z8V@lNkCp&RvahRf%Wmnc7ZxxFHOn0DKR!8?l4Xf9hw63O*)NjJeS9vb4$WhquR@gZgh<0N z?XTa?2Xl!(B)5f<>hvTbL&)a|SUQ++^FjgcFia8E_%55k;Pg4ofQyhvk&FGT7v&dp zS~+3dCK8fdxSLkvcpqGtv(ZGsZke*h*K9%)tpfW1!LTM{JjIL%F5~p{1p&pL5F=k- zfrS99osDjqcNhrdfX}`(dLnOH(pL6xP+;SQa5y1T9fzb3Z9RAo;82H?Ni2@K7Z7Sb zO~Q7GKr@;1=o%%Spi!kpSY#2rGq%9~r zSB^6`t{3GF??)}6FX>=WnYpcMeCee{3YU}{DB2?Ni^?uu12#b)ccuy1I-tM;S^(e9 z901;IFoOw04<*Hb_|LA%9bqVGYl`(`Igj3mch8*OAc1EBuCz>U9($mPSb14un0z%s zEDC%ZL5DVDFsw60?=I;(VI+X@=FS7R&7t=E=o*~Kgp(Mz1Wcw<>|qf5G+I4GZcs=C zvuRqmnj#!ULqX3wNQ54WZe|<^B&UlYYup4U6eHSE0aVaohXY$|ye{AG_1KOfG zsp=ky+8UPPx?tgdevTAKy81=*qGp17hz)c1jr>am%4~dMgvd$_fov|s`=dg`8!?LH zNjS+Vqv7keygkC9Zml+gZ`vrqj}T+`;w33tk0+g9D&{p z^7cue8KGv*_K$>$b4bz_GQn)%+(9Pb|JY0Nt`dzeT9S(Fd{lvvzJb^%T5!8%;H71t z;g6fgU>#hG{p2YT%ri5Uc~in8`l4#b?FHm2A$b-vo)5)xQ8YF=o!ldqz&Y53mZ<)e ziZx}8fj7kz-hKj4)i;2hvt^;liq6kb{Xaih8WaJ5z?h&(Z9|#VmQDRM*l(RpSUUyd zv8Fbj9EkQiXbq;?`R~RUMXQ^3+}*6c5P*kUW1P>Qc9ba8i2bmV;e^;w2hIHi;xvn^ z81cfL$`AxRpdXMK>0IMLV**^lTE!mtdM0r|fqJFy_JuddxRWLc*2Ro;LIFMz9s-k{ z1*RJ^@@Jd z!Yn%bsLpFZibZZJbIIE)HPDLScq}B-V4X)A-bvmcPt~9lcE>ywOx8}oV>seWYTe84 zMWwJ9vwhzS>$kh9)sSUKK(mdW9z0S@B*=5dubnwdM6RA>XaNqHha()MY7B)gc5f48 zrOSgAUR5dCQEV~{oKC7FW2MtYjIjk=p&SV>K8k&^D%6=~E7924Y$`!PiH!7s$Cf;V z?^nsj3uogI3)^>8vEzY;8RIrp%cv})()lG&{`xH!xtQ}qk@1%+vgJnQT)yL&y!YSe zU~~z!h5WBoXvb?y=yvbF?O3v~G8t0pcNx5#=9vk*q3(Gs|01|8FIXLX&{3S!o6EfT zt++hvA^HJ?x%)7x*_lHs4F_x9kpS=hE4ruFg73Ra04ZmK{1^5Cy}Y~K>~<43$6`pfD-RPfuVFUE zB8NjUe@|Iza9xj7nN7XV3K^j&?aQHS3tX?CH^eHKc#KF#9S)TamT1R8D5%%zCZ+Wa z9ZVI)N5^mu#5W*7d|$&s<%kiz-|q9H@|<|sGHL(y37d!ylIw^52&J9omtZHFMm`Y^ zbJ0)dCiAmOoQw7GrlI#8xtL0((&@;cHP%>4LX5YAtv_-`8I??|ijw~_x}R7QbGN>OPaK`pP#ButNHBSXY$`=e-&F@ER+z@{s2qc>r{!sBfiU9g5BE5!+48>e3A1jebnH8qepWt)B}! z#p`XI+!gYx52iF53`$wq3r74aek#DxMUNfg@LD#Z#%?nigAyM_P+5XAPv}OIX1JAB zLm(Eb8lAe#UGCB^%!a$xj3Hu4Rxae}ua4ZoY!pt6nhHI$<97TL=t_-wUh_%l%&oa? zx3K(5-}Dh-((A)oXAo1gEC+nP86z~9(04*9nHzQy@+Vh*aIUP)`%q-!NPb|=BQl~g zarzX20ag0 zcuP4~V;wy>pP0n#+=Qh_4a{s4FAeR!qB8!?Ex)0CfJ<0CkqO$5-&u9`0DMrBN`-Km zJ;8J8FcTw?&O;sYB7eE$Kg(6b^|XHrH7NY>(9yd z&e`|lH~e=IQo{2y-e4+~JB5c&%1$-e|ByMYjZG+BpM@L*Fq_`F*IN*!aQIwER{T7z zy1zHlBeo>Vv4DSE7}=6=)tH&PH&|dyqfLcz`bUqMT^tu_n9X^;UrB}%E=W74LJ(pc z=@X*<;MK-fR78$^BE02ZAmflcHjMO4?|=ZGZRwA!e`x0}J!@+-Sr4V^+qQ#~D;qA_ z+b^`DA^)33r~_p`!14eVs}Hv!F)E#uITFOSzQ0cti?OX!lVT>W2L6iwAXbJM@2y@=ma^v!X4baruiBe^}Ubii0G+%~*hn>Rd zJalZG|LXCK_B+DGr4N}BvWS-AMjw#xY+tfy|Ik; z9^T;UJ;Y7I?qq@lA3*0c4y`OmJi70g!Wx5`TPUKaM$B9X>h0(YrnG?*k+1`hpe|s3F$pJ$u zKmBoM{0QVS#bFr^W?VQwB6`Tcy$dyxZrd#YJF4HTs{HO?+i^^!0%`I7e`^&1_pki1 zHepaI0Iwe^K!nlYzrw|Qu;+vMA3`XiKQ+2-oFLkVL~lI#s{UQS?cy>r1UBkdi~LlY zzw-wn>b}y3Z%N;mq0@wB!Tp&)1{7(Dk=xZxbLwbH;$rE09fn(DdHD2!=|T=uhOqek z0R1XUqMsEc|BsDn9SD~VsGPYEr+p+R4k9Vl^yIOZ9S&H`*=AC-dL!-0KVZZ0dg+e$~nqK0;Ay!pP4n;tKiTGqGgM_61Ytceurz^nL5I64(3 zgmD=M{gdQ`StJZSL|GtlNMQk+^*^@`f&qtpIlb8Luhsl*#j10#z&XQT5at(EwjGqO z{2=$kGU!bdKAtU1F9n6*@32+_w~Wwe2`Y{jtu(B8xs^o;PH ztx+{C8TXUZzJq!&I0Vnr)FB)?GC({~_!~h@j1WccLm`Vud<&#Q75HQ+yMOGiuYuANW>T=JGO zroN}G{<`aRT=uC9wbYuy) ze#)>%I@BL>Y?Kf7Cd=c(K6?JcFhAc(A)4W^>l>Nq;`|`lvg9FuiU`$~6nENCgj_k` zaBm11q6%;y;cpejSxOlM=FUkJyo_7rHNW1+3Z-2CJpN+m=z4*6#Sx^&o^l>p2{kFI zfi+u*KQc4VLoh=aepp&mQM29M^yehhj|}|te17B1Q1Ybwn|-lcQp5?uczLHcr7JBG zxuTnX9hfg4Xp`Qg(Fz?H&QuYwyCFc*w_b1+Xmyx^II_kEB7b(*C_+j3LMN|6`K4Nz zM!kHeGKP01Y{Ps>1M^+`NEsc>H-AzgNN}hQ3nh;a(zRJZS-MG0&r}M5mlRWfeqUN< z*@K*Ik7S`wYe<@eiolaCBJqP8agVv6SCUUW-tznNCyrKR=`d2F_K)NO3q*kh4l?Sb zdq0@Q#Df3V!h{#=_lytyrFr+h$x@5`r%2L__Tj6z*BD@sjr7~M!Td?KnBU^Z3RFjh z>FQ&9s~??4CzDR!(-p=c4HoHOzNd`2;=mjzMF^Y8CC_;NU~r+zN!jb;eEvs;tN=4n zBO*I-ZY`wIQ_>T9=(1c-7c52<2Av^lPRat=fol0JFH%7?q1K*XRcj!AWHZIuzlmYE z`JGUZCd#NF@S*;ZnK)Vy4>UM}NF4MyLrFpL$fAR|fZ=IB6yJtHjgP=$3}~h0Q^25- z{CE8-(jaLi%E4sMmS(5CjGCr!F{o*ES2c+26z!IE9x!Wu8xq+$X4GvK=|w-+Z|wII1Kp0pmc|hWqIP{ zFhel$V~j;*6mpb}wcwpx&LUD>#6Bew5^W>SyX1n*^>T*0inVJl;Fj$z}{!LAUT(m^sKK{#-gw%TZm5eoQ~&ZS z>I>#XUx#`eN}yDq9y$g(x^~5v#MJY}AuqCEtm$PJXwr;jSv(Uvyk_AGCHleTWXiDC zcHvOKa8`=y^mp2(GrrL9Ui9SYlYc$O!lY9>4=6ImCgho5=ELfQH>Togb{ zI+{AuGa1c!3n!T@aLnHa<1yk$!cs>IS&rCz0tA6_e4<+x7MZj$7K`StXEzMyepsNA z%&mMe5Zo`1ZHU5E1=Tp*1mQ{k9XseB0ehas2e}QQxm{b4t@%ZH$;Q7GK7l(~WF`WO z=D3Ka0M1HKP5GkMXHKwK*yNVDL8i9aB}b09V6sb^^b4Ueaf58AXNwTvrKciF>eKR) z3mzxqL>s)QIqQWZ4b-8~vf>~6Q?Ihs{hby=c5<}h_W*$Y)^d4*@tuZIY{{j#aeQdXJR_WTs50^%+36MXk$~BGR0J_0thwM=wgqMc z>XmWmo2;7oVJ_dC1w9Iaaqfr&km2g1%6O_9ftwvAbOiIg^0qrbqGXIk)0pE6>-D-R zyIGOO`y?kKY4a+p_y8=15EcnFVNR#Qca!Ktn{PZon)kA*i~yn$D$ba+GGy&c!CywF z2pA~&t0sH9d#g7EIA{r!y1eO`i%8VMx5pS`(^ipI??(fcCwWzdp!$SrNv)H<;T@a~ znzr=PJUO}mr&I`7qzuGN@iWYi*)FhS8r&Xd*)2Bpvc<69DTUE$bs-j0nkntp{j8Ip zgV40k4x?&z?k5!9k~B!j^P3so-?s__AHVQio;9ruNaMvHCi4Y~9VFWD#kG=z+gm}a zb~%!M9`YB5v%`^by@vhGNu09=*7)Re(ubd!a0A83TfaV6#>bT57^H;|FUsP_Dy#WM z+3d<0%LuC^s78s#I|M!J1}j(x9T#ADKH^ z;in%c_ql$%1w?8+e>0)z5Mj=XII20dIhvp4~1zYp@!zQ3T()NjJe+OS#BK ztm{B-WS{qIM*s!BuOB63-!R(hSlJ_SJc-iM`aIQghN_JU8rkHLr*{*7U+BeA_hQl~ZbgM?NRf=p zVbbof0E9d^?CsaX44Rz>2!+>H&J!S&`WSG}(;L`4XxfY7shk@#K;J%COQRrcq)kKd zlpIDPjk7A*gdu$7KbU+#5E%n2dAQzI9v4bO3zV{q`clKnxhh982_-#XEO63<(JEc; zT^Sd08m$zm{yD#Nn@QCIZf7fB(aK~DJrBb2 zQav*msv+jKTX$CL%hu4Cud>6*!_)X9^3%|WnxVtrKosgk0^ZxdXs|ycV!izgLSj=n zcSzeWP{10eSZ7WoT+R&dpRr#}SeRn_jQDX73x)c7P{RDUxz)4H>9t-oH8eh*MUy*r zOfB{tP0h9r4$^+<{wgv>Mc&HEDj4l12G3E&v}x}KPV&|{gnyI-m3`qwMX(pb&{iS% z5RHwB)x+V^1+G~ZvQ2-bcO)ggh_sUF>a((HSI7~pfFAQ^qhtVR(|8mhu`F1nYlM8e zqf(*E{dOjBP2&P%N*#;7M&wNLGo9ya8U*&Do3Ki4k}61R_unjtwyiN(E`WE({&wB_ zoboKJC;4hTXTFu7F&dSU2GE-%mn)hy8K}YdzxCcrw76}r!;sqJhLW9yiTrbYJ{l4v z06sQY++aF&@V{UFU#S}-ocgU2BT|GN init_server + my_model -> foo +} \ No newline at end of file diff --git a/docs/images/sync-example-files.svg b/docs/images/sync-example-files.svg new file mode 100644 index 00000000..64de9f10 --- /dev/null +++ b/docs/images/sync-example-files.svg @@ -0,0 +1,38 @@ + + + + + + +Sync Files + + +my_model + +MyModel + + +init_server + +init.server.lua + + +my_model->init_server + + + + +foo + +foo.lua + + +my_model->foo + + + + + diff --git a/docs/images/sync-example-instances.gv b/docs/images/sync-example-instances.gv new file mode 100644 index 00000000..4902a8b1 --- /dev/null +++ b/docs/images/sync-example-instances.gv @@ -0,0 +1,15 @@ +digraph "Sync Files" { + graph [ + ranksep = "0.7", + nodesep = "0.5", + ]; + node [ + fontname = "monospace", + shape = "record", + ]; + + my_model [label = "MyModel (Script)"] + foo [label = "foo (ModuleScript)"] + + my_model -> foo +} \ No newline at end of file diff --git a/docs/images/sync-example-instances.svg b/docs/images/sync-example-instances.svg new file mode 100644 index 00000000..24f4a52d --- /dev/null +++ b/docs/images/sync-example-instances.svg @@ -0,0 +1,28 @@ + + + + + + +Sync Files + + +my_model + +MyModel (Script) + + +foo + +foo (ModuleScript) + + +my_model->foo + + + + + diff --git a/docs/images/sync-example-json-model.gv b/docs/images/sync-example-json-model.gv new file mode 100644 index 00000000..376108d3 --- /dev/null +++ b/docs/images/sync-example-json-model.gv @@ -0,0 +1,17 @@ +digraph "Sync Files" { + graph [ + ranksep = "0.7", + nodesep = "0.5", + ]; + node [ + fontname = "monospace", + shape = "record", + ]; + + model [label = "My Cool Model (Folder)"] + root_part [label = "RootPart (Part)"] + send_money [label = "SendMoney (RemoteEvent)"] + + model -> root_part + model -> send_money +} \ No newline at end of file diff --git a/docs/images/sync-example-json-model.svg b/docs/images/sync-example-json-model.svg new file mode 100644 index 00000000..27dd3251 --- /dev/null +++ b/docs/images/sync-example-json-model.svg @@ -0,0 +1,38 @@ + + + + + + +Sync Files + + +model + +My Cool Model (Folder) + + +root_part + +RootPart (Part) + + +model->root_part + + + + +send_money + +SendMoney (RemoteEvent) + + +model->send_money + + + + + diff --git a/docs/images/sync-example.png b/docs/images/sync-example.png deleted file mode 100644 index ab56863bf121de868e023953815aaa6aea2ccc06..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1931 zcmV;62Xy#}P)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D01|XXSaefwW^{L9 za%BKVa%E+1b7*gLUR4MM000L9Nkln!;j3Q&>b;lYGkgxkPum$@(K^K2$e% zpvIUeHY8N(KCRa8tI{5*(SKcMkPh2daW5JWBSctJmSXN#nH4oymOZ5PKB2O?hv(d# z+Lf|COMIE8pxc7FV}uB6O2>5hoi+&SB~|&!aoKxB`CrC0*NazilG{M51SOkX-c>xo zG-8JcYf6z!UhlOH^>$tP?9Hrr5%&YJLeXJdVmuu#)OiT{>>VvvA1erGq9_VQJP&8q z;=uKxI^{yyiBI#B-<6#DY^>}!Tp=zxx=(HOk~ID8wIR7`@q^$0K?7oh2Q?KI7N(}A z5(I(TGz~Fiii(O*J0$Uc^vP9AlJf`Et>uo6D}=HLt`Jvb9#qcaBt?JnTi<&*z16)& zG$2L@(&Y7e!H7sC@|ofsaT)04%0jT?V%vmirLdx5^!gF!pqLz&z!l=Wl7?23^7pMbKR>PiSMdm(O}-rz z7Z>+PjvOoQZ5a)}*J?gaRm#kCW@Yt>Kg(0H3$OOBrsNoRrrn!&dbXayND|H{LHxTU z;4}M@e2%xoERcoi_6-0{{3H;=-rez zIQi2U{Y5XGAfrF5r#~vEvpeYc6Jy{1T>r*V391$#v?e4-XfFYb9&Uk2TsJcXvtgjY zPZ4T)QI3dy)UI_@%A z{MXItE8DlGRiSDDLM;QuuykQd{s9PP9GhX!Aa;t7^E00KoSKmv$eNlS6|Kp>{g`+x zXS+D#+g<71`y1(f7@bf<@2R7A!-hIHoqpu(T){ir(kjsa0oK(dV1tKQr4ROK;WJy3 zlF$_E&CmGcMzF_L01?x4p`vqh@}DWcl;q|9@zz(jUOL<-N*@xX4~vcuzIwF(xt+B) z#Wh%+c;~SYn${!m+zBQ~AGW5;$0lN$63&P-O7Ectio+C_tP#lB3qa1x#>wKihT zPMo?X|1PT@4TvcscQzU46VuDz{^sgy`>(vRH~YoiSxjP4*c$*<8rG3)jcJmMN_9{QT(^X z#DtlcU0l6buQ^$(LUkeFp2H*m1kMmGni_^oO=Alqb9l?7N3QX-Pvc!$PoDwT+g#~Y zqZ;!vs#}wwZ*>tTS~T70m{RKOpr%>vk*Ph3DO@q-xu?aaEz2c}X*jb`-J1LlG?5fl z)G{$?a>~^1R<#?hGL1(*<>}Sq&CSgU76?$a5EyzV$G<=bcqQUjCzuS6sL+HH4o+LBQ?Xx4{m8VOW2Ezg#XaD=S08g7_b3 z%9He5zdJInThv?c&pX^smsci}!Odkf8oRo>R4UcvsaXid$P-mzI_+7K>i5pO~0{BOEet1x@AUl3xIBIKaYiVgIC@4Th{~=MT3I4Rf!2~xN+;KXc4vuXw z1^cL{r)Q17bWfHj)#RhJv=kl!;AtSt|Mhr6M7t&cPAC91o)R&j>FGn${{qtuuUA#Q RSAqZl002ovPDHLkV1nI2o$3Gp diff --git a/docs/migrating-to-epiphany.md b/docs/migrating-to-epiphany.md index 98fca7b8..fbd48481 100644 --- a/docs/migrating-to-epiphany.md +++ b/docs/migrating-to-epiphany.md @@ -50,9 +50,6 @@ Metadata begins with a dollar sign (`$`), like `$className`. This is so that chi All other values are considered children, where the key is the instance's name, and the value is an object, repeating the process. -## Migrating `.model.json` Files -No upgrade path yet, stay tuned. - ## Migrating Unknown Files If you used Rojo to sync in files as `StringValue` objects, you'll need to make sure those files end with the `txt` extension to preserve this in Rojo 0.5.x. diff --git a/docs/sync-details.md b/docs/sync-details.md index 55a1e543..b655bb13 100644 --- a/docs/sync-details.md +++ b/docs/sync-details.md @@ -9,6 +9,20 @@ This page aims to describe how Rojo turns files on the filesystem into Roblox ob | `*.lua` | `ModuleScript` | | `*.csv` | `LocalizationTable` | | `*.txt` | `StringValue` | +| `*.model.json` | Any | +| `*.rbxm` | Any | +| `*.rbxmx` | Any | + +## Limitations +Not all property types can be synced by Rojo in real-time due to limitations of the Roblox Studio plugin API. In these cases, you can usually generate a place file and open it when you start working on a project. + +Some common cases you might hit are: + +* Binary data (Terrain, CSG, CollectionService tags) +* `MeshPart.MeshId` +* `HttpService.HttpEnabled` + +For a list of all property types that Rojo can reason about, both when live-syncing and when building place files, look at [rbx_tree's type coverage documentation](https://github.com/LPGhatguy/rbx-tree/tree/master/rbx_tree#coverage). ## Folders Any directory on the filesystem will turn into a `Folder` instance unless it contains an 'init' script, described below. @@ -20,16 +34,68 @@ If a directory contains a file named `init.server.lua`, `init.client.lua`, or `i For example, these files: -* my-game - * init.client.lua - * foo.lua + Will turn into these instances in Roblox: -![Example of Roblox instances](/images/sync-example.png) + ## Localization Tables Any CSV files are transformed into `LocalizationTable` instances. Rojo expects these files to follow the same format that Roblox does when importing and exporting localization information. ## Plain Text Files -Plain text files (`.txt`) files are transformed into `StringValue` instances. This is useful for bringing in text data that can be read by scripts at runtime. \ No newline at end of file +Plain text files (`.txt`) files are transformed into `StringValue` instances. This is useful for bringing in text data that can be read by scripts at runtime. + +## JSON Models +Files ending in `.model.json` can be used to describe simple models. They're designed to be hand-written and are useful for instances like `RemoteEvent`. + +A JSON model describing a folder containing a `Part` and a `RemoteEvent` could be described as: + +```json +{ + "Name": "My Cool Model", + "ClassName": "Folder", + "Children": [ + { + "Name": "RootPart", + "ClassName": "Part", + "Properties": { + "Size": { + "Type": "Vector3", + "Value": [4, 4, 4] + } + } + }, + { + "Name": "SendMoney", + "ClassName": "RemoteEvent" + } + ] +} +``` + +It would turn into instances in this shape: + + + +## Binary and XML Models +Rojo supports both binary (`.rbxm`) and XML (`.rbxmx`) models generated by Roblox Studio or another tool. + +Not all property types are supported! + +For a rundown of supported types, see: + +* [rbxm Type Coverage](https://github.com/LPGhatguy/rbx-tree/tree/master/rbx_binary#coverage) +* [rbxmx Type Coverage](https://github.com/LPGhatguy/rbx-tree/tree/master/rbx_xml#coverage) \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index a45c478e..e07ab8bc 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -17,6 +17,9 @@ nav: - Sync Details: sync-details.md - Migrating from 0.4.x to 0.5.x: migrating-to-epiphany.md +extra_css: + - extra.css + markdown_extensions: - attr_list - admonition From e700b3105aba75a54ce865a4d19e6c754b77ea15 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 15:31:20 -0800 Subject: [PATCH 0409/1504] New, less-kludgy doc generator --- generate-docs | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/generate-docs b/generate-docs index 6366a096..fc64fb30 100644 --- a/generate-docs +++ b/generate-docs @@ -3,23 +3,23 @@ # Kludged documentation generator to support multiple versions. # Make sure the `site` folder is a checkout of this repository's `gh-pages` # branch. -# To use, copy this file to `generate-docs.run` so that Git will leave it alone, -# then run `generate-docs.run` in the root of the repository. set -e -CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) +REMOTE=$(git remote get-url origin) +CHECKOUT="$(mktemp -d)" +OUTPUT="$(pwd)/site" -echo "Building 0.4.x" -git checkout v0.4.x -git pull -mkdocs build --site-dir site/0.4.x +git clone "$REMOTE" "$CHECKOUT" +cd "$CHECKOUT" echo "Building master" git checkout master -mkdocs build --site-dir site/master +mkdocs build --site-dir "$OUTPUT/master" echo "Building 0.5.x" -mkdocs build --site-dir site/0.5.x +mkdocs build --site-dir "$OUTPUT/0.5.x" -git checkout "$CURRENT_BRANCH" \ No newline at end of file +echo "Building 0.4.x" +git checkout v0.4.x +mkdocs build --site-dir "$OUTPUT/0.4.x" \ No newline at end of file From 350eec3bc70a8afae967e539e6ce67dd589d4da9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 15:39:11 -0800 Subject: [PATCH 0410/1504] Update docs and generator to be even smarter --- docs/index.md | 2 +- generate-docs | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/docs/index.md b/docs/index.md index 712f95a3..54735204 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,9 +2,9 @@ This is the documentation home for Rojo. Available versions of these docs: +* [Latest version (currently 0.5.x)](https://lpghatguy.github.io/rojo) * [0.5.x](https://lpghatguy.github.io/rojo/0.5.x) * [0.4.x](https://lpghatguy.github.io/rojo/0.4.x) -* [`master` branch](https://lpghatguy.github.io/rojo/master) **Rojo** is a flexible multi-tool designed for creating robust Roblox projects. diff --git a/generate-docs b/generate-docs index fc64fb30..22991a29 100644 --- a/generate-docs +++ b/generate-docs @@ -10,12 +10,22 @@ REMOTE=$(git remote get-url origin) CHECKOUT="$(mktemp -d)" OUTPUT="$(pwd)/site" +if [ -d site ] +then + cd site + git pull +else + git clone "$REMOTE" site + cd site + git checkout gh-pages +fi + git clone "$REMOTE" "$CHECKOUT" cd "$CHECKOUT" echo "Building master" git checkout master -mkdocs build --site-dir "$OUTPUT/master" +mkdocs build --site-dir "$OUTPUT" echo "Building 0.5.x" mkdocs build --site-dir "$OUTPUT/0.5.x" From 0d9406d991489ca159277c10c641829f54a42336 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 15:40:54 -0800 Subject: [PATCH 0411/1504] Update docs links in README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 3ca74319..b5535ddd 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Soon, Rojo will be able to: * Sync instances from Roblox Studio to the filesystem * Compile MoonScript and other custom things for your project -## [Documentation](https://lpghatguy.github.io/rojo/0.4.x) +## [Documentation](https://lpghatguy.github.io/rojo) You can also view the documentation by browsing the [docs](https://github.com/LPGhatguy/rojo/tree/master/docs) folder of the repository, but because it uses a number of Markdown extensions, it may not be very readable. ## Inspiration and Alternatives From 821122a33da0a27b187322a56045bee3655fe017 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 15:45:52 -0800 Subject: [PATCH 0412/1504] 0.5.0-alpha.2 --- CHANGELOG.md | 4 +++- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b635a506..13dbf4f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,13 @@ # Rojo Changelog ## [Unreleased] + +## [0.5.0 Alpha 2](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.2) (January 28, 2019) * Added support for `.model.json` files, compatible with 0.4.x * Fixed in-memory filesystem not handling out-of-order filesystem change events * Fixed long-polling error caused by a promise mixup ([#110](https://github.com/LPGhatguy/rojo/issues/110)) -## [0.5.0 Alpha 1](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.1) (January 14, 2019) +## [0.5.0 Alpha 1](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.1) (January 25, 2019) * Changed plugin UI to be way prettier * Thanks to [Reselim](https://github.com/Reselim) for the design! * Changed plugin error messages to be a little more useful diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index e88d4057..3f2f03fe 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0, "-alpha.1"}, + version = {0, 5, 0, "-alpha.2"}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/server/Cargo.toml b/server/Cargo.toml index 4924c80e..881dafe9 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0-alpha.1" +version = "0.5.0-alpha.2" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 12fd9aa1efc20194e144833e66bb9b9167568ea2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 16:03:12 -0800 Subject: [PATCH 0413/1504] Tack on Cargo.lock, missing from previous commit --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 1b847720..194e45af 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0-alpha.1" +version = "0.5.0-alpha.2" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", From 3c0fe4d6840b1674cb018e6a064c7653d49cafcd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 17:11:01 -0800 Subject: [PATCH 0414/1504] Reduce number of threads needed for FsWatcher --- server/src/fs_watcher.rs | 120 +++++++++++++++++++++---------------- server/src/imfs.rs | 12 ++++ server/src/live_session.rs | 2 +- 3 files changed, 81 insertions(+), 53 deletions(-) diff --git a/server/src/fs_watcher.rs b/server/src/fs_watcher.rs index 178994d2..33159a55 100644 --- a/server/src/fs_watcher.rs +++ b/server/src/fs_watcher.rs @@ -1,10 +1,12 @@ use std::{ sync::{mpsc, Arc, Mutex}, time::Duration, + path::Path, + ops::Deref, thread, }; -use log::trace; +use log::{warn, trace}; use notify::{ self, DebouncedEvent, @@ -20,7 +22,66 @@ use crate::{ const WATCH_TIMEOUT: Duration = Duration::from_millis(100); -fn handle_event(imfs: &Mutex, rbx_session: &Mutex, event: DebouncedEvent) { +/// Watches for changes on the filesystem and links together the in-memory +/// filesystem and in-memory Roblox tree. +pub struct FsWatcher { + watcher: RecommendedWatcher, +} + +impl FsWatcher { + /// Start a new FS watcher, watching all of the roots currently attached to + /// the given Imfs. + /// + /// `rbx_session` is optional to make testing easier. If it isn't `None`, + /// events will be passed to it after they're given to the Imfs. + pub fn start(imfs: Arc>, rbx_session: Option>>) -> FsWatcher { + let (watch_tx, watch_rx) = mpsc::channel(); + + let mut watcher = notify::watcher(watch_tx, WATCH_TIMEOUT) + .expect("Could not create filesystem watcher"); + + { + let imfs = imfs.lock().unwrap(); + + for root_path in imfs.get_roots() { + watcher.watch(root_path, RecursiveMode::Recursive) + .expect("Could not watch directory"); + } + } + + { + let imfs = Arc::clone(&imfs); + let rbx_session = rbx_session.as_ref().map(Arc::clone); + + thread::spawn(move || { + trace!("Watcher thread started"); + while let Ok(event) = watch_rx.recv() { + // handle_fs_event expects an Option<&Mutex>, but we have + // an Option>>, so we coerce with Deref. + let session_ref = rbx_session.as_ref().map(Deref::deref); + + handle_fs_event(&imfs, session_ref, event); + } + trace!("Watcher thread stopped"); + }); + } + + FsWatcher { + watcher, + } + } + + pub fn stop_watching_path(&mut self, path: &Path) { + match self.watcher.unwatch(path) { + Ok(_) => {}, + Err(e) => { + warn!("Could not unwatch path {}: {}", path.display(), e); + }, + } + } +} + +fn handle_fs_event(imfs: &Mutex, rbx_session: Option<&Mutex>, event: DebouncedEvent) { match event { DebouncedEvent::Create(path) => { trace!("Path created: {}", path.display()); @@ -30,7 +91,7 @@ fn handle_event(imfs: &Mutex, rbx_session: &Mutex, event: Debo imfs.path_created(&path).unwrap(); } - { + if let Some(rbx_session) = rbx_session { let mut rbx_session = rbx_session.lock().unwrap(); rbx_session.path_created(&path); } @@ -43,7 +104,7 @@ fn handle_event(imfs: &Mutex, rbx_session: &Mutex, event: Debo imfs.path_updated(&path).unwrap(); } - { + if let Some(rbx_session) = rbx_session { let mut rbx_session = rbx_session.lock().unwrap(); rbx_session.path_updated(&path); } @@ -56,20 +117,20 @@ fn handle_event(imfs: &Mutex, rbx_session: &Mutex, event: Debo imfs.path_removed(&path).unwrap(); } - { + if let Some(rbx_session) = rbx_session { let mut rbx_session = rbx_session.lock().unwrap(); rbx_session.path_removed(&path); } }, DebouncedEvent::Rename(from_path, to_path) => { - trace!("Path rename: {} to {}", from_path.display(), to_path.display()); + trace!("Path renamed: {} to {}", from_path.display(), to_path.display()); { let mut imfs = imfs.lock().unwrap(); imfs.path_moved(&from_path, &to_path).unwrap(); } - { + if let Some(rbx_session) = rbx_session { let mut rbx_session = rbx_session.lock().unwrap(); rbx_session.path_renamed(&from_path, &to_path); } @@ -78,49 +139,4 @@ fn handle_event(imfs: &Mutex, rbx_session: &Mutex, event: Debo trace!("Unhandled FS event: {:?}", other); }, } -} - -/// Watches for changes on the filesystem and links together the in-memory -/// filesystem and in-memory Roblox tree. -pub struct FsWatcher { - #[allow(unused)] - watchers: Vec, -} - -impl FsWatcher { - pub fn start(imfs: Arc>, rbx_session: Arc>) -> FsWatcher { - let mut watchers = Vec::new(); - - { - let imfs_temp = imfs.lock().unwrap(); - - for root_path in imfs_temp.get_roots() { - let (watch_tx, watch_rx) = mpsc::channel(); - - let mut watcher = notify::watcher(watch_tx, WATCH_TIMEOUT) - .expect("Could not create `notify` watcher"); - - watcher.watch(root_path, RecursiveMode::Recursive) - .expect("Could not watch directory"); - - watchers.push(watcher); - - let imfs = Arc::clone(&imfs); - let rbx_session = Arc::clone(&rbx_session); - let root_path = root_path.clone(); - - thread::spawn(move || { - trace!("Watcher thread ({}) started", root_path.display()); - while let Ok(event) = watch_rx.recv() { - handle_event(&imfs, &rbx_session, event); - } - trace!("Watcher thread ({}) stopped", root_path.display()); - }); - } - } - - FsWatcher { - watchers, - } - } } \ No newline at end of file diff --git a/server/src/imfs.rs b/server/src/imfs.rs index 26ccc4db..dec13807 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -72,6 +72,18 @@ impl Imfs { self.descend_and_read_from_disk(path) } + pub fn remove_root(&mut self, path: &Path) { + debug_assert!(path.is_absolute()); + + if self.roots.get(path).is_some() { + self.remove_item(path); + + if let Some(parent_path) = path.parent() { + self.unlink_child(parent_path, path); + } + } + } + pub fn path_created(&mut self, path: &Path) -> io::Result<()> { debug_assert!(path.is_absolute()); debug_assert!(self.is_within_roots(path)); diff --git a/server/src/live_session.rs b/server/src/live_session.rs index 6d0b9485..1f6cac87 100644 --- a/server/src/live_session.rs +++ b/server/src/live_session.rs @@ -41,7 +41,7 @@ impl LiveSession { let fs_watcher = FsWatcher::start( Arc::clone(&imfs), - Arc::clone(&rbx_session), + Some(Arc::clone(&rbx_session)), ); let session_id = SessionId::new(); From 6c3e118ee31284200cba4061a5d15eb7e570645d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 17:50:47 -0800 Subject: [PATCH 0415/1504] Sort inputs in LiveSession --- server/src/live_session.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/live_session.rs b/server/src/live_session.rs index 1f6cac87..57f18ac3 100644 --- a/server/src/live_session.rs +++ b/server/src/live_session.rs @@ -4,13 +4,13 @@ use std::{ }; use crate::{ + fs_watcher::FsWatcher, + imfs::Imfs, message_queue::MessageQueue, project::Project, - imfs::Imfs, - session_id::SessionId, rbx_session::RbxSession, + session_id::SessionId, snapshot_reconciler::InstanceChanges, - fs_watcher::FsWatcher, }; /// Contains all of the state for a Rojo live-sync session. From aeb18eb124f8778093ae53cb068f3509875e4e28 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 18:23:57 -0800 Subject: [PATCH 0416/1504] Refactor web code to make routing more clear --- server/src/web.rs | 238 ++++++++++++++++++++++++---------------------- 1 file changed, 126 insertions(+), 112 deletions(-) diff --git a/server/src/web.rs b/server/src/web.rs index b8512831..31c4d824 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -96,136 +96,31 @@ impl Server { router!(request, (GET) (/) => { - Response::text("Rojo is up and running!") + self.handle_home() }, - (GET) (/api/rojo) => { - // Get a summary of information about the server. - - let rbx_session = self.live_session.rbx_session.lock().unwrap(); - let tree = rbx_session.get_tree(); - - Response::json(&ServerInfoResponse { - server_version: self.server_version, - protocol_version: 2, - session_id: self.live_session.session_id, - expected_place_ids: self.live_session.project.serve_place_ids.clone(), - root_instance_id: tree.get_root_id(), - }) + self.handle_api_rojo() }, - (GET) (/api/subscribe/{ cursor: u32 }) => { - // Retrieve any messages past the given cursor index, and if - // there weren't any, subscribe to receive any new messages. - - let message_queue = Arc::clone(&self.live_session.message_queue); - - // Did the client miss any messages since the last subscribe? - { - let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); - - if !new_messages.is_empty() { - return Response::json(&SubscribeResponse { - session_id: self.live_session.session_id, - messages: Cow::Borrowed(&new_messages), - message_cursor: new_cursor, - }) - } - } - - let (tx, rx) = mpsc::channel(); - - let sender_id = message_queue.subscribe(tx); - - match rx.recv() { - Ok(_) => (), - Err(_) => return Response::text("error!").with_status_code(500), - } - - message_queue.unsubscribe(sender_id); - - { - let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); - - return Response::json(&SubscribeResponse { - session_id: self.live_session.session_id, - messages: Cow::Owned(new_messages), - message_cursor: new_cursor, - }) - } + self.handle_api_subscribe(cursor) }, - (GET) (/api/read/{ id_list: String }) => { - let message_queue = Arc::clone(&self.live_session.message_queue); - let requested_ids: Option> = id_list .split(',') .map(RbxId::parse_str) .collect(); - let requested_ids = match requested_ids { - Some(id) => id, - None => return rouille::Response::text("Malformed ID list").with_status_code(400), - }; - - let rbx_session = self.live_session.rbx_session.lock().unwrap(); - let tree = rbx_session.get_tree(); - - let message_cursor = message_queue.get_message_cursor(); - - let mut instances = HashMap::new(); - - for &requested_id in &requested_ids { - if let Some(instance) = tree.get_instance(requested_id) { - let metadata = rbx_session.get_instance_metadata(requested_id) - .map(InstanceMetadata::from_session_metadata); - - instances.insert(instance.get_id(), InstanceWithMetadata { - instance: Cow::Borrowed(instance), - metadata, - }); - - for descendant in tree.descendants(requested_id) { - let descendant_meta = rbx_session.get_instance_metadata(descendant.get_id()) - .map(InstanceMetadata::from_session_metadata); - - instances.insert(descendant.get_id(), InstanceWithMetadata { - instance: Cow::Borrowed(descendant), - metadata: descendant_meta, - }); - } - } - } - - Response::json(&ReadResponse { - session_id: self.live_session.session_id, - message_cursor, - instances, - }) + self.handle_api_read(requested_ids) }, - (GET) (/visualize/rbx) => { - let rbx_session = self.live_session.rbx_session.lock().unwrap(); - - let dot_source = format!("{}", VisualizeRbxSession(&rbx_session)); - - Response::svg(graphviz_to_svg(&dot_source)) + self.handle_visualize_rbx() }, - (GET) (/visualize/imfs) => { - let imfs = self.live_session.imfs.lock().unwrap(); - - let dot_source = format!("{}", VisualizeImfs(&imfs)); - - Response::svg(graphviz_to_svg(&dot_source)) + self.handle_visualize_imfs() }, - (GET) (/visualize/path_metadata) => { - let rbx_session = self.live_session.rbx_session.lock().unwrap(); - - Response::json(&rbx_session.debug_get_metadata_per_path()) + self.handle_visualize_path_metadata() }, - _ => Response::empty_404() ) } @@ -235,4 +130,123 @@ impl Server { rouille::start_server(address, move |request| self.handle_request(request)); } + + fn handle_home(&self) -> Response { + Response::text("Rojo is up and running!") + } + + /// Get a summary of information about the server + fn handle_api_rojo(&self) -> Response { + let rbx_session = self.live_session.rbx_session.lock().unwrap(); + let tree = rbx_session.get_tree(); + + Response::json(&ServerInfoResponse { + server_version: self.server_version, + protocol_version: 2, + session_id: self.live_session.session_id, + expected_place_ids: self.live_session.project.serve_place_ids.clone(), + root_instance_id: tree.get_root_id(), + }) + } + + /// Retrieve any messages past the given cursor index, and if + /// there weren't any, subscribe to receive any new messages. + fn handle_api_subscribe(&self, cursor: u32) -> Response { + let message_queue = Arc::clone(&self.live_session.message_queue); + + // Did the client miss any messages since the last subscribe? + { + let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); + + if !new_messages.is_empty() { + return Response::json(&SubscribeResponse { + session_id: self.live_session.session_id, + messages: Cow::Borrowed(&new_messages), + message_cursor: new_cursor, + }) + } + } + + let (tx, rx) = mpsc::channel(); + + let sender_id = message_queue.subscribe(tx); + + match rx.recv() { + Ok(_) => (), + Err(_) => return Response::text("error!").with_status_code(500), + } + + message_queue.unsubscribe(sender_id); + + { + let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); + + return Response::json(&SubscribeResponse { + session_id: self.live_session.session_id, + messages: Cow::Owned(new_messages), + message_cursor: new_cursor, + }) + } + } + + fn handle_api_read(&self, requested_ids: Option>) -> Response { + let message_queue = Arc::clone(&self.live_session.message_queue); + + let requested_ids = match requested_ids { + Some(id) => id, + None => return rouille::Response::text("Malformed ID list").with_status_code(400), + }; + + let rbx_session = self.live_session.rbx_session.lock().unwrap(); + let tree = rbx_session.get_tree(); + + let message_cursor = message_queue.get_message_cursor(); + + let mut instances = HashMap::new(); + + for &requested_id in &requested_ids { + if let Some(instance) = tree.get_instance(requested_id) { + let metadata = rbx_session.get_instance_metadata(requested_id) + .map(InstanceMetadata::from_session_metadata); + + instances.insert(instance.get_id(), InstanceWithMetadata { + instance: Cow::Borrowed(instance), + metadata, + }); + + for descendant in tree.descendants(requested_id) { + let descendant_meta = rbx_session.get_instance_metadata(descendant.get_id()) + .map(InstanceMetadata::from_session_metadata); + + instances.insert(descendant.get_id(), InstanceWithMetadata { + instance: Cow::Borrowed(descendant), + metadata: descendant_meta, + }); + } + } + } + + Response::json(&ReadResponse { + session_id: self.live_session.session_id, + message_cursor, + instances, + }) + } + + fn handle_visualize_rbx(&self) -> Response { + let rbx_session = self.live_session.rbx_session.lock().unwrap(); + let dot_source = format!("{}", VisualizeRbxSession(&rbx_session)); + Response::svg(graphviz_to_svg(&dot_source)) + } + + fn handle_visualize_imfs(&self) -> Response { + let imfs = self.live_session.imfs.lock().unwrap(); + let dot_source = format!("{}", VisualizeImfs(&imfs)); + Response::svg(graphviz_to_svg(&dot_source)) + } + + fn handle_visualize_path_metadata(&self) -> Response { + let rbx_session = self.live_session.rbx_session.lock().unwrap(); + Response::json(&rbx_session.debug_get_metadata_per_path()) + } } \ No newline at end of file From aa243d1b8af49731e9977dd6f0413652f0b5dd07 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 28 Jan 2019 18:30:42 -0800 Subject: [PATCH 0417/1504] Add sweet new live sync homepage --- CHANGELOG.md | 1 + server/assets/index.html | 54 ++++++++++++++++++++++++++++++++++++++++ server/src/web.rs | 4 ++- 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 server/assets/index.html diff --git a/CHANGELOG.md b/CHANGELOG.md index 13dbf4f3..3d42e6bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## [Unreleased] +* Added new (empty) diagnostic page served from the server ## [0.5.0 Alpha 2](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.2) (January 28, 2019) * Added support for `.model.json` files, compatible with 0.4.x diff --git a/server/assets/index.html b/server/assets/index.html new file mode 100644 index 00000000..93e93848 --- /dev/null +++ b/server/assets/index.html @@ -0,0 +1,54 @@ + + + + Rojo + + + + +
+

Rojo Live Sync is up and running!

+ Rojo Documentation +
+ + + \ No newline at end of file diff --git a/server/src/web.rs b/server/src/web.rs index 31c4d824..0822f1cb 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -22,6 +22,8 @@ use crate::{ rbx_session::{MetadataPerInstance}, }; +static HOME_CONTENT: &str = include_str!("../assets/index.html"); + /// Contains the instance metadata relevant to Rojo clients. #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -132,7 +134,7 @@ impl Server { } fn handle_home(&self) -> Response { - Response::text("Rojo is up and running!") + Response::html(HOME_CONTENT) } /// Get a summary of information about the server From 8757834e074c96d65c9d3dd96a4baa2eccefff51 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 29 Jan 2019 17:29:47 -0800 Subject: [PATCH 0418/1504] Improve error reporting for IO issues --- CHANGELOG.md | 1 + server/src/commands/build.rs | 10 ++- server/src/commands/serve.rs | 7 ++- server/src/commands/upload.rs | 6 +- server/src/imfs.rs | 61 ++++++++++++++----- server/src/live_session.rs | 5 +- .../missing-files/roblox-project.json | 6 ++ 7 files changed, 74 insertions(+), 22 deletions(-) create mode 100644 test-projects/missing-files/roblox-project.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d42e6bb..8d4e05f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [Unreleased] * Added new (empty) diagnostic page served from the server +* Added better error messages for when a file is missing that's referenced by a Rojo project ## [0.5.0 Alpha 2](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.2) (January 28, 2019) * Added support for `.model.json` files, compatible with 0.4.x diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index 14819b51..e5880aea 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -10,7 +10,7 @@ use failure::Fail; use crate::{ rbx_session::construct_oneoff_tree, project::{Project, ProjectLoadFuzzyError}, - imfs::Imfs, + imfs::{Imfs, FsError}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -55,14 +55,18 @@ pub enum BuildError { XmlModelEncodeError(rbx_xml::EncodeError), #[fail(display = "Binary model file error")] - BinaryModelEncodeError(rbx_binary::EncodeError) + BinaryModelEncodeError(rbx_binary::EncodeError), + + #[fail(display = "{}", _0)] + FsError(#[fail(cause)] FsError), } impl_from!(BuildError { ProjectLoadFuzzyError => ProjectLoadError, io::Error => IoError, rbx_xml::EncodeError => XmlModelEncodeError, - rbx_binary::EncodeError => BinaryModelEncodeError + rbx_binary::EncodeError => BinaryModelEncodeError, + FsError => FsError, }); pub fn build(options: &BuildOptions) -> Result<(), BuildError> { diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 69ec0e75..9b2db9dd 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -9,6 +9,7 @@ use failure::Fail; use crate::{ project::{Project, ProjectLoadFuzzyError}, web::Server, + imfs::FsError, live_session::LiveSession, }; @@ -24,10 +25,14 @@ pub struct ServeOptions { pub enum ServeError { #[fail(display = "Project load error: {}", _0)] ProjectLoadError(#[fail(cause)] ProjectLoadFuzzyError), + + #[fail(display = "{}", _0)] + FsError(#[fail(cause)] FsError), } impl_from!(ServeError { ProjectLoadFuzzyError => ProjectLoadError, + FsError => FsError, }); pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { @@ -38,7 +43,7 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { info!("Found project at {}", project.file_location.display()); info!("Using project {:#?}", project); - let live_session = Arc::new(LiveSession::new(Arc::clone(&project)).unwrap()); + let live_session = Arc::new(LiveSession::new(Arc::clone(&project))?); let server = Server::new(Arc::clone(&live_session)); let port = options.port diff --git a/server/src/commands/upload.rs b/server/src/commands/upload.rs index 229eae6c..0498693c 100644 --- a/server/src/commands/upload.rs +++ b/server/src/commands/upload.rs @@ -11,7 +11,7 @@ use reqwest::header::{ACCEPT, USER_AGENT, CONTENT_TYPE, COOKIE}; use crate::{ rbx_session::construct_oneoff_tree, project::{Project, ProjectLoadFuzzyError}, - imfs::Imfs, + imfs::{Imfs, FsError}, }; #[derive(Debug, Fail)] @@ -33,6 +33,9 @@ pub enum UploadError { #[fail(display = "XML model file error")] XmlModelEncodeError(rbx_xml::EncodeError), + + #[fail(display = "{}", _0)] + FsError(#[fail(cause)] FsError), } impl_from!(UploadError { @@ -40,6 +43,7 @@ impl_from!(UploadError { io::Error => IoError, reqwest::Error => HttpError, rbx_xml::EncodeError => XmlModelEncodeError, + FsError => FsError, }); #[derive(Debug)] diff --git a/server/src/imfs.rs b/server/src/imfs.rs index dec13807..4c30a423 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -1,15 +1,41 @@ use std::{ collections::{HashMap, HashSet}, path::{self, Path, PathBuf}, + fmt, fs, io, }; +use failure::Fail; use serde_derive::{Serialize, Deserialize}; use crate::project::{Project, ProjectNode}; -fn add_sync_points(imfs: &mut Imfs, project_node: &ProjectNode) -> io::Result<()> { +/// A wrapper around io::Error that also attaches the path associated with the +/// error. +#[derive(Debug, Fail)] +pub struct FsError { + #[fail(cause)] + inner: io::Error, + path: PathBuf, +} + +impl FsError { + fn new>(inner: io::Error, path: P) -> FsError { + FsError { + inner, + path: path.into(), + } + } +} + +impl fmt::Display for FsError { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + write!(output, "{}: {}", self.path.display(), self.inner) + } +} + +fn add_sync_points(imfs: &mut Imfs, project_node: &ProjectNode) -> Result<(), FsError> { match project_node { ProjectNode::Instance(node) => { for child in node.children.values() { @@ -44,7 +70,7 @@ impl Imfs { } } - pub fn add_roots_from_project(&mut self, project: &Project) -> io::Result<()> { + pub fn add_roots_from_project(&mut self, project: &Project) -> Result<(), FsError> { add_sync_points(self, &project.tree) } @@ -63,7 +89,7 @@ impl Imfs { self.items.get(path) } - pub fn add_root(&mut self, path: &Path) -> io::Result<()> { + pub fn add_root(&mut self, path: &Path) -> Result<(), FsError> { debug_assert!(path.is_absolute()); debug_assert!(!self.is_within_roots(path)); @@ -84,21 +110,21 @@ impl Imfs { } } - pub fn path_created(&mut self, path: &Path) -> io::Result<()> { + pub fn path_created(&mut self, path: &Path) -> Result<(), FsError> { debug_assert!(path.is_absolute()); debug_assert!(self.is_within_roots(path)); self.descend_and_read_from_disk(path) } - pub fn path_updated(&mut self, path: &Path) -> io::Result<()> { + pub fn path_updated(&mut self, path: &Path) -> Result<(), FsError> { debug_assert!(path.is_absolute()); debug_assert!(self.is_within_roots(path)); self.descend_and_read_from_disk(path) } - pub fn path_removed(&mut self, path: &Path) -> io::Result<()> { + pub fn path_removed(&mut self, path: &Path) -> Result<(), FsError> { debug_assert!(path.is_absolute()); debug_assert!(self.is_within_roots(path)); @@ -111,7 +137,7 @@ impl Imfs { Ok(()) } - pub fn path_moved(&mut self, from_path: &Path, to_path: &Path) -> io::Result<()> { + pub fn path_moved(&mut self, from_path: &Path, to_path: &Path) -> Result<(), FsError> { self.path_removed(from_path)?; self.path_created(to_path)?; Ok(()) @@ -161,9 +187,9 @@ impl Imfs { } } - fn descend_and_read_from_disk(&mut self, path: &Path) -> io::Result<()> { + fn descend_and_read_from_disk(&mut self, path: &Path) -> Result<(), FsError> { let root_path = self.get_root_path(path) - .expect("Tried to mkdirp for path that wasn't within roots!"); + .expect("Tried to descent and read for path that wasn't within roots!"); // If this path is a root, we should read the entire thing. if root_path == path { @@ -193,11 +219,13 @@ impl Imfs { Ok(()) } - fn read_from_disk(&mut self, path: &Path) -> io::Result<()> { - let metadata = fs::metadata(path)?; + fn read_from_disk(&mut self, path: &Path) -> Result<(), FsError> { + let metadata = fs::metadata(path) + .map_err(|e| FsError::new(e, path))?; if metadata.is_file() { - let contents = fs::read(path)?; + let contents = fs::read(path) + .map_err(|e| FsError::new(e, path))?; let item = ImfsItem::File(ImfsFile { path: path.to_path_buf(), contents, @@ -218,8 +246,13 @@ impl Imfs { self.items.insert(path.to_path_buf(), item); - for entry in fs::read_dir(path)? { - let entry = entry?; + let dir_children = fs::read_dir(path) + .map_err(|e| FsError::new(e, path))?; + + for entry in dir_children { + let entry = entry + .map_err(|e| FsError::new(e, path))?; + let child_path = entry.path(); self.read_from_disk(&child_path)?; diff --git a/server/src/live_session.rs b/server/src/live_session.rs index 57f18ac3..f229fb4a 100644 --- a/server/src/live_session.rs +++ b/server/src/live_session.rs @@ -1,11 +1,10 @@ use std::{ sync::{Arc, Mutex}, - io, }; use crate::{ fs_watcher::FsWatcher, - imfs::Imfs, + imfs::{Imfs, FsError}, message_queue::MessageQueue, project::Project, rbx_session::RbxSession, @@ -24,7 +23,7 @@ pub struct LiveSession { } impl LiveSession { - pub fn new(project: Arc) -> io::Result { + pub fn new(project: Arc) -> Result { let imfs = { let mut imfs = Imfs::new(); imfs.add_roots_from_project(&project)?; diff --git a/test-projects/missing-files/roblox-project.json b/test-projects/missing-files/roblox-project.json new file mode 100644 index 00000000..69fc0af0 --- /dev/null +++ b/test-projects/missing-files/roblox-project.json @@ -0,0 +1,6 @@ +{ + "name": "missing-files", + "tree": { + "$path": "does-not-exist" + } +} \ No newline at end of file From 6719be02c34202fb16b7a8903154264da5c492d9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 29 Jan 2019 18:10:14 -0800 Subject: [PATCH 0419/1504] Fall back to showing GraphViz source when GraphViz is not installed --- CHANGELOG.md | 1 + Cargo.lock | 6 +++--- server/Cargo.toml | 2 +- server/src/bin.rs | 11 ++++++++--- server/src/visualize.rs | 19 ++++++++++++++----- server/src/web.rs | 12 ++++++++++-- 6 files changed, 37 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d4e05f1..587bee13 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] * Added new (empty) diagnostic page served from the server * Added better error messages for when a file is missing that's referenced by a Rojo project +* Added support for visualization endpoints returning GraphViz source when Dot is not available ## [0.5.0 Alpha 2](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.2) (January 28, 2019) * Added support for `.model.json` files, compatible with 0.4.x diff --git a/Cargo.lock b/Cargo.lock index 194e45af..d0f41761 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -345,7 +345,7 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.5.13" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1252,7 +1252,7 @@ version = "0.5.0-alpha.2" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1929,7 +1929,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7" -"checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38" +"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" diff --git a/server/Cargo.toml b/server/Cargo.toml index 881dafe9..df5be7f6 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -22,7 +22,7 @@ bundle-plugin = [] [dependencies] clap = "2.27" csv = "1.0" -env_logger = "0.5" +env_logger = "0.6" failure = "0.1.3" log = "0.4" maplit = "1.0.1" diff --git a/server/src/bin.rs b/server/src/bin.rs index 61ef05f0..7f5b80e7 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -20,9 +20,14 @@ fn make_path_absolute(value: &Path) -> PathBuf { } fn main() { - env_logger::Builder::from_default_env() - .default_format_timestamp(false) - .init(); + { + let log_env = env_logger::Env::default() + .default_filter_or("warn"); + + env_logger::Builder::from_env(log_env) + .default_format_timestamp(false) + .init(); + } let app = clap_app!(Rojo => (version: env!("CARGO_PKG_VERSION")) diff --git a/server/src/visualize.rs b/server/src/visualize.rs index 75b51b19..a09326e8 100644 --- a/server/src/visualize.rs +++ b/server/src/visualize.rs @@ -5,6 +5,7 @@ use std::{ process::{Command, Stdio}, }; +use log::warn; use rbx_tree::RbxId; use crate::{ @@ -27,13 +28,21 @@ digraph RojoTree { "#; /// Compiles DOT source to SVG by invoking dot on the command line. -pub fn graphviz_to_svg(source: &str) -> String { - let mut child = Command::new("dot") +pub fn graphviz_to_svg(source: &str) -> Option { + let command = Command::new("dot") .arg("-Tsvg") .stdin(Stdio::piped()) .stdout(Stdio::piped()) - .spawn() - .expect("Failed to spawn GraphViz process -- make sure it's installed in order to use /api/visualize"); + .spawn(); + + let mut child = match command { + Ok(child) => child, + Err(_) => { + warn!("Failed to spawn GraphViz process to visualize current state."); + warn!("If you want pretty graphs, install GraphViz and make sure 'dot' is on your PATH!"); + return None; + }, + }; { let stdin = child.stdin.as_mut().expect("Failed to open stdin"); @@ -41,7 +50,7 @@ pub fn graphviz_to_svg(source: &str) -> String { } let output = child.wait_with_output().expect("Failed to read stdout"); - String::from_utf8(output.stdout).expect("Failed to parse stdout as UTF-8") + Some(String::from_utf8(output.stdout).expect("Failed to parse stdout as UTF-8")) } /// A Display wrapper struct to visualize an RbxSession as SVG. diff --git a/server/src/web.rs b/server/src/web.rs index 0822f1cb..5c78bdfa 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -238,13 +238,21 @@ impl Server { fn handle_visualize_rbx(&self) -> Response { let rbx_session = self.live_session.rbx_session.lock().unwrap(); let dot_source = format!("{}", VisualizeRbxSession(&rbx_session)); - Response::svg(graphviz_to_svg(&dot_source)) + + match graphviz_to_svg(&dot_source) { + Some(svg) => Response::svg(svg), + None => Response::text(dot_source), + } } fn handle_visualize_imfs(&self) -> Response { let imfs = self.live_session.imfs.lock().unwrap(); let dot_source = format!("{}", VisualizeImfs(&imfs)); - Response::svg(graphviz_to_svg(&dot_source)) + + match graphviz_to_svg(&dot_source) { + Some(svg) => Response::svg(svg), + None => Response::text(dot_source), + } } fn handle_visualize_path_metadata(&self) -> Response { From b58fed16b42ebc48c3d1b992a65b26f4574221af Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 30 Jan 2019 10:29:38 -0800 Subject: [PATCH 0420/1504] Fix uses using failure::Error --- server/tests/imfs.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/server/tests/imfs.rs b/server/tests/imfs.rs index f9f55393..4d0292c6 100644 --- a/server/tests/imfs.rs +++ b/server/tests/imfs.rs @@ -1,10 +1,10 @@ use std::{ collections::{HashMap, HashSet}, - io, fs, path::PathBuf, }; +use failure::Error; use tempfile::{TempDir, tempdir}; use librojo::{ @@ -19,7 +19,7 @@ enum FsEvent { Moved(PathBuf, PathBuf), } -fn send_events(imfs: &mut Imfs, events: &[FsEvent]) -> io::Result<()> { +fn send_events(imfs: &mut Imfs, events: &[FsEvent]) -> Result<(), Error> { for event in events { match event { FsEvent::Created(path) => imfs.path_created(path)?, @@ -56,7 +56,7 @@ fn check_expected(real: &Imfs, expected: &ExpectedImfs) { } } -fn base_tree() -> io::Result<(TempDir, Imfs, ExpectedImfs, TestResources)> { +fn base_tree() -> Result<(TempDir, Imfs, ExpectedImfs, TestResources), Error> { let root = tempdir()?; let foo_path = root.path().join("foo"); @@ -125,7 +125,7 @@ fn base_tree() -> io::Result<(TempDir, Imfs, ExpectedImfs, TestResources)> { } #[test] -fn initial_read() -> io::Result<()> { +fn initial_read() -> Result<(), Error> { let (_root, imfs, expected_imfs, _resources) = base_tree()?; check_expected(&imfs, &expected_imfs); @@ -134,7 +134,7 @@ fn initial_read() -> io::Result<()> { } #[test] -fn adding_files() -> io::Result<()> { +fn adding_files() -> Result<(), Error> { let (root, mut imfs, mut expected_imfs, resources) = base_tree()?; check_expected(&imfs, &expected_imfs); @@ -178,7 +178,7 @@ fn adding_files() -> io::Result<()> { } #[test] -fn adding_folder() -> io::Result<()> { +fn adding_folder() -> Result<(), Error> { let (root, imfs, mut expected_imfs, _resources) = base_tree()?; check_expected(&imfs, &expected_imfs); @@ -255,7 +255,7 @@ fn adding_folder() -> io::Result<()> { } #[test] -fn removing_file() -> io::Result<()> { +fn removing_file() -> Result<(), Error> { let (root, mut imfs, mut expected_imfs, resources) = base_tree()?; check_expected(&imfs, &expected_imfs); @@ -279,7 +279,7 @@ fn removing_file() -> io::Result<()> { } #[test] -fn removing_folder() -> io::Result<()> { +fn removing_folder() -> Result<(), Error> { let (root, imfs, mut expected_imfs, resources) = base_tree()?; check_expected(&imfs, &expected_imfs); From 0ff59ecb4e6f7984adba0de0834882e6919e3a51 Mon Sep 17 00:00:00 2001 From: Paul Doyle <37384169+ZoteTheMighty@users.noreply.github.com> Date: Thu, 31 Jan 2019 20:24:42 -0800 Subject: [PATCH 0421/1504] Fix issue w/ existing files not being updated in imfs (#119) * Fix issue w/ existing files not being updated in imfs * Add a test for updating files --- server/src/imfs.rs | 3 +-- server/tests/imfs.rs | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/server/src/imfs.rs b/server/src/imfs.rs index 4c30a423..cd14b5b1 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -208,7 +208,6 @@ impl Imfs { if self.items.contains_key(&next_path) { current_path = next_path; } else { - self.read_from_disk(¤t_path)?; break; } }, @@ -216,7 +215,7 @@ impl Imfs { } } - Ok(()) + self.read_from_disk(¤t_path) } fn read_from_disk(&mut self, path: &Path) -> Result<(), FsError> { diff --git a/server/tests/imfs.rs b/server/tests/imfs.rs index 4d0292c6..617ce06a 100644 --- a/server/tests/imfs.rs +++ b/server/tests/imfs.rs @@ -254,6 +254,35 @@ fn adding_folder() -> Result<(), Error> { Ok(()) } +#[test] +fn updating_files() -> Result<(), Error> { + let (_root, mut imfs, mut expected_imfs, resources) = base_tree()?; + + check_expected(&imfs, &expected_imfs); + + fs::write(&resources.bar_path, b"bar updated")?; + fs::write(&resources.baz_path, b"baz updated")?; + + imfs.path_updated(&resources.bar_path)?; + imfs.path_updated(&resources.baz_path)?; + + let bar_updated_item = ImfsItem::File(ImfsFile { + path: resources.bar_path.clone(), + contents: b"bar updated".to_vec(), + }); + let baz_updated_item = ImfsItem::File(ImfsFile { + path: resources.baz_path.clone(), + contents: b"baz updated".to_vec(), + }); + + expected_imfs.items.insert(resources.bar_path.clone(), bar_updated_item); + expected_imfs.items.insert(resources.baz_path.clone(), baz_updated_item); + + check_expected(&imfs, &expected_imfs); + + Ok(()) +} + #[test] fn removing_file() -> Result<(), Error> { let (root, mut imfs, mut expected_imfs, resources) = base_tree()?; From 78a1947cec354e95678f34ed253755b6816a2f78 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Feb 2019 13:07:15 -0800 Subject: [PATCH 0422/1504] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 587bee13..d5c2692d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Added new (empty) diagnostic page served from the server * Added better error messages for when a file is missing that's referenced by a Rojo project * Added support for visualization endpoints returning GraphViz source when Dot is not available +* Fixed an in-memory filesystem regression introduced recently ([#119](https://github.com/LPGhatguy/rojo/pull/119)) ## [0.5.0 Alpha 2](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.2) (January 28, 2019) * Added support for `.model.json` files, compatible with 0.4.x From 785bdb8ecbaa432d7de95c2b12b493093bfd38c4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Feb 2019 17:06:03 -0800 Subject: [PATCH 0423/1504] Implement new project file name, default.project.json (#120) * Implement new project file name, default.project.json * Rename all test projects to default.project.json * Update CHANGELOG * Fix warning message typo --- CHANGELOG.md | 4 ++ ...blox-project.json => default.project.json} | 0 ...{place-project.json => place.project.json} | 0 server/src/commands/build.rs | 1 + server/src/commands/serve.rs | 1 + server/src/commands/upload.rs | 1 + server/src/project.rs | 37 ++++++++++++++++--- server/tests/read_projects.rs | 8 ++-- ...blox-project.json => default.project.json} | 0 ...blox-project.json => default.project.json} | 0 ...blox-project.json => default.project.json} | 0 ...blox-project.json => default.project.json} | 0 ...blox-project.json => default.project.json} | 0 13 files changed, 43 insertions(+), 9 deletions(-) rename plugin/{roblox-project.json => default.project.json} (100%) rename plugin/{place-project.json => place.project.json} (100%) rename test-projects/composing-models/{roblox-project.json => default.project.json} (100%) rename test-projects/empty/{roblox-project.json => default.project.json} (100%) rename test-projects/missing-files/{roblox-project.json => default.project.json} (100%) rename test-projects/single-sync-point/{roblox-project.json => default.project.json} (100%) rename test-projects/test-model/{roblox-project.json => default.project.json} (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5c2692d..6618b9c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Rojo Changelog ## [Unreleased] +* Changed default project file name from `roblox-project.json` to `default.project.json` ([#120](https://github.com/LPGhatguy/rojo/pull/120)) + * The old file name will still be supported until 0.5.0 is fully released. +* Added warning when loading project files that don't end in `.project.json` + * This new extension enables Rojo to distinguish project files from random JSON files, which is necessary to support nested projects. * Added new (empty) diagnostic page served from the server * Added better error messages for when a file is missing that's referenced by a Rojo project * Added support for visualization endpoints returning GraphViz source when Dot is not available diff --git a/plugin/roblox-project.json b/plugin/default.project.json similarity index 100% rename from plugin/roblox-project.json rename to plugin/default.project.json diff --git a/plugin/place-project.json b/plugin/place.project.json similarity index 100% rename from plugin/place-project.json rename to plugin/place.project.json diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index e5880aea..2c839e69 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -79,6 +79,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { info!("Looking for project at {}", options.fuzzy_project_path.display()); let project = Project::load_fuzzy(&options.fuzzy_project_path)?; + project.check_compatibility(); info!("Found project at {}", project.file_location.display()); info!("Using project {:#?}", project); diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 9b2db9dd..58c0d16e 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -39,6 +39,7 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { info!("Looking for project at {}", options.fuzzy_project_path.display()); let project = Arc::new(Project::load_fuzzy(&options.fuzzy_project_path)?); + project.check_compatibility(); info!("Found project at {}", project.file_location.display()); info!("Using project {:#?}", project); diff --git a/server/src/commands/upload.rs b/server/src/commands/upload.rs index 0498693c..fb26e0ab 100644 --- a/server/src/commands/upload.rs +++ b/server/src/commands/upload.rs @@ -60,6 +60,7 @@ pub fn upload(options: &UploadOptions) -> Result<(), UploadError> { info!("Looking for project at {}", options.fuzzy_project_path.display()); let project = Project::load_fuzzy(&options.fuzzy_project_path)?; + project.check_compatibility(); info!("Found project at {}", project.file_location.display()); info!("Using project {:#?}", project); diff --git a/server/src/project.rs b/server/src/project.rs index e6c1509c..c391e02d 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -6,12 +6,14 @@ use std::{ path::{Path, PathBuf}, }; +use log::warn; use failure::Fail; use maplit::hashmap; use rbx_tree::RbxValue; use serde_derive::{Serialize, Deserialize}; -pub static PROJECT_FILENAME: &'static str = "roblox-project.json"; +pub static PROJECT_FILENAME: &'static str = "default.project.json"; +pub static COMPAT_PROJECT_FILENAME: &'static str = "roblox-project.json"; // Methods used for Serde's default value system, which doesn't support using // value literals directly, only functions that return values. @@ -362,11 +364,17 @@ impl Project { } else if location_metadata.is_dir() { let with_file = start_location.join(PROJECT_FILENAME); - if let Ok(with_file_metadata) = fs::metadata(&with_file) { - if with_file_metadata.is_file() { + if let Ok(file_metadata) = fs::metadata(&with_file) { + if file_metadata.is_file() { return Some(with_file); - } else { - return None; + } + } + + let with_compat_file = start_location.join(COMPAT_PROJECT_FILENAME); + + if let Ok(file_metadata) = fs::metadata(&with_compat_file) { + if file_metadata.is_file() { + return Some(with_compat_file); } } } @@ -405,6 +413,25 @@ impl Project { Ok(()) } + /// Checks if there are any compatibility issues with this project file and + /// warns the user if there are any. + pub fn check_compatibility(&self) { + let file_name = self.file_location + .file_name().unwrap() + .to_str().expect("Project file path was not valid Unicode!"); + + if file_name == COMPAT_PROJECT_FILENAME { + warn!("Rojo's default project file name changed in 0.5.0-alpha3."); + warn!("Support for the old project file name will be dropped before 0.5.0 releases."); + warn!("Your project file is named {}", COMPAT_PROJECT_FILENAME); + warn!("Rename your project file to {}", PROJECT_FILENAME); + } else if !file_name.ends_with(".project.json") { + warn!("Starting in Rojo 0.5.0-alpha3, it's recommended to give all project files the"); + warn!(".project.json extension. This helps Rojo differentiate project files from"); + warn!("other JSON files!"); + } + } + fn to_source_project(&self) -> SourceProject { SourceProject { name: self.name.clone(), diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index af30ed99..55ae5550 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -21,7 +21,7 @@ lazy_static! { #[test] fn empty() { - let project_file_location = TEST_PROJECTS_ROOT.join("empty/roblox-project.json"); + let project_file_location = TEST_PROJECTS_ROOT.join("empty/default.project.json"); let project = Project::load_exact(&project_file_location).unwrap(); assert_eq!(project.name, "empty"); @@ -29,7 +29,7 @@ fn empty() { #[test] fn empty_fuzzy_file() { - let project_file_location = TEST_PROJECTS_ROOT.join("empty/roblox-project.json"); + let project_file_location = TEST_PROJECTS_ROOT.join("empty/default.project.json"); let project = Project::load_fuzzy(&project_file_location).unwrap(); assert_eq!(project.name, "empty"); @@ -45,7 +45,7 @@ fn empty_fuzzy_folder() { #[test] fn single_sync_point() { - let project_file_location = TEST_PROJECTS_ROOT.join("single-sync-point/roblox-project.json"); + let project_file_location = TEST_PROJECTS_ROOT.join("single-sync-point/default.project.json"); let project = Project::load_exact(&project_file_location).unwrap(); let expected_project = { @@ -100,7 +100,7 @@ fn single_sync_point() { #[test] fn test_model() { - let project_file_location = TEST_PROJECTS_ROOT.join("test-model/roblox-project.json"); + let project_file_location = TEST_PROJECTS_ROOT.join("test-model/default.project.json"); let project = Project::load_exact(&project_file_location).unwrap(); assert_eq!(project.name, "test-model"); diff --git a/test-projects/composing-models/roblox-project.json b/test-projects/composing-models/default.project.json similarity index 100% rename from test-projects/composing-models/roblox-project.json rename to test-projects/composing-models/default.project.json diff --git a/test-projects/empty/roblox-project.json b/test-projects/empty/default.project.json similarity index 100% rename from test-projects/empty/roblox-project.json rename to test-projects/empty/default.project.json diff --git a/test-projects/missing-files/roblox-project.json b/test-projects/missing-files/default.project.json similarity index 100% rename from test-projects/missing-files/roblox-project.json rename to test-projects/missing-files/default.project.json diff --git a/test-projects/single-sync-point/roblox-project.json b/test-projects/single-sync-point/default.project.json similarity index 100% rename from test-projects/single-sync-point/roblox-project.json rename to test-projects/single-sync-point/default.project.json diff --git a/test-projects/test-model/roblox-project.json b/test-projects/test-model/default.project.json similarity index 100% rename from test-projects/test-model/roblox-project.json rename to test-projects/test-model/default.project.json From 69d1accf3f63608be2766c487a517201b8843dfa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Feb 2019 17:19:00 -0800 Subject: [PATCH 0424/1504] 0.5.0-alpha.3 --- CHANGELOG.md | 2 ++ Cargo.lock | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6618b9c8..c8d4472a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## [Unreleased] + +## [0.5.0 Alpha 3](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.3) (February 1, 2019) * Changed default project file name from `roblox-project.json` to `default.project.json` ([#120](https://github.com/LPGhatguy/rojo/pull/120)) * The old file name will still be supported until 0.5.0 is fully released. * Added warning when loading project files that don't end in `.project.json` diff --git a/Cargo.lock b/Cargo.lock index d0f41761..5824f1d5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1248,7 +1248,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0-alpha.2" +version = "0.5.0-alpha.3" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 3f2f03fe..0354e518 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0, "-alpha.2"}, + version = {0, 5, 0, "-alpha.3"}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/server/Cargo.toml b/server/Cargo.toml index df5be7f6..fa96ef5e 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0-alpha.2" +version = "0.5.0-alpha.3" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 2c2554d73d6d26b55e21b6a17a673fd20453ac45 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Feb 2019 18:03:41 -0800 Subject: [PATCH 0425/1504] Update docs to talk about default.project.json --- docs/getting-started/creating-a-place.md | 2 +- docs/migrating-to-epiphany.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/getting-started/creating-a-place.md b/docs/getting-started/creating-a-place.md index fb2b493f..49acbd01 100644 --- a/docs/getting-started/creating-a-place.md +++ b/docs/getting-started/creating-a-place.md @@ -9,7 +9,7 @@ cd my-new-project rojo init ``` -Rojo will make a small project file in your directory, named `roblox-project.json`. It'll make sure that any code in the directory `src` will get put into `ReplicatedStorage.Source`. +Rojo will make a small project file in your directory, named `default.project.json`. It'll make sure that any code in the directory `src` will get put into `ReplicatedStorage.Source`. Speaking of, let's make sure we create a directory named `src`, and maybe a Lua file inside of it: diff --git a/docs/migrating-to-epiphany.md b/docs/migrating-to-epiphany.md index fbd48481..598b1e5f 100644 --- a/docs/migrating-to-epiphany.md +++ b/docs/migrating-to-epiphany.md @@ -1,7 +1,7 @@ Rojo underwent a large refactor during most of 2018 to enable a bunch of new features and lay groundwork for lots more in 2019. As such, Rojo **0.5.x** projects are not compatible with Rojo **0.4.x** projects. ## Supporting Both 0.4.x and 0.5.x -Rojo 0.5.x uses a different name for its project format. While 0.4.x used `rojo.json`, 0.5.x uses `roblox-project.json`, which allows them to coexist. +Rojo 0.5.x uses a different name for its project format. While 0.4.x used `rojo.json`, 0.5.x uses `default.project.json`, which allows them to coexist. If you aren't sure about upgrading or want to upgrade gradually, it's possible to keep both files in the same project without causing problems. From 2f64501556c9578db42c8a82553ea080c28f3681 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 5 Feb 2019 10:17:13 -0800 Subject: [PATCH 0426/1504] Add Rust 1.31.1 as fixed build target to Travis-CI --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.travis.yml b/.travis.yml index b8ea5d69..34e0a69e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,14 +25,23 @@ matrix: - cd plugin - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install + - language: rust + rust: 1.31.1 + cache: cargo + + script: + - cargo test --verbose + - language: rust rust: stable + cache: cargo script: - cargo test --verbose - language: rust rust: beta + cache: cargo script: - cargo test --verbose \ No newline at end of file From 38e3c198f294ad6aebaa5d1f3f202f66f832d48e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 5 Feb 2019 10:30:09 -0800 Subject: [PATCH 0427/1504] Update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b5535ddd..458fed60 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ If you use a plugin that _isn't_ Rojo for syncing code, open an issue and let me ## Contributing Pull requests are welcome! -All pull requests are run against a test suite on Travis CI. That test suite should always pass! +Rojo supports Rust 1.31.1 and newer. Any changes to the minimum required compiler version require a _minor_ version bump. ## License Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file From ecb9b5e28f3579d338fc92ded7428fbe5c20a728 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Feb 2019 14:55:01 -0800 Subject: [PATCH 0428/1504] Support nested partitions and partitions directly targeting services (#122) * Do the nested partition thing * Tidy up touched code * Add nested partition test project, not fully functional * Clean up variable names, move path_metadata mutation strictly into snapshot_reconciler * Remove path_metadata, snapshotting is now pure * Factor out snapshot metadata storage to fix a missing case * Pull instance_name out of per_path_metadata, closer to what we need * Refactor to make metadata make more sense, part one * All appears to be well * Cull 'metadata_per_path' in favor of 'instances_per_path' * Remove SnapshotContext * InstanceMetadata -> PublicInstanceMetadata in web module * Build in snapshot testing system for testing... snapshots? * Remove pretty_assertions to see if it fixes a snapshot comparison bug * Reintroduce pretty assertions, it's not the cause of inequality * Fix snapshot tests with custom relative path serializer --- Cargo.lock | 51 +++++ server/Cargo.toml | 10 +- server/src/fs_watcher.rs | 3 +- server/src/imfs.rs | 17 +- server/src/lib.rs | 3 +- server/src/path_map.rs | 31 --- server/src/path_serializer.rs | 69 ++++++ server/src/project.rs | 215 +++++++----------- server/src/rbx_session.rs | 125 +++++----- server/src/rbx_snapshot.rs | 160 +++++++------ server/src/snapshot_reconciler.rs | 89 +++++--- server/src/visualize.rs | 4 +- server/src/web.rs | 22 +- server/tests/read_projects.rs | 61 ++--- server/tests/snapshots.rs | 124 ++++++++++ .../default.project.json | 0 .../src/Binary.rbxm | Bin .../src/Remotes.model.json | 0 .../src/XML.rbxmx | 0 test-projects/empty/expected-snapshot.json | 20 ++ .../default.project.json | 0 .../nested_partitions/default.project.json | 9 + .../nested_partitions/expected-snapshot.json | 82 +++++++ .../nested_partitions/inner/hello.lua | 1 + .../nested_partitions/outer/world.lua | 1 + .../lib/sampleTranslation.csv | 6 - .../default.project.json | 0 .../expected-snapshot.json | 161 +++++++++++++ .../lib/foo.txt | 0 .../lib/main.lua | 0 .../default.project.json | 0 .../expected-snapshot.json | 53 +++++ .../src/main.server.lua | 0 .../src/other.lua | 0 .../ReplicatedStorage/hello.lua | 1 + .../transmute_partition/default.project.json | 11 + .../expected-snapshot.json | 66 ++++++ 37 files changed, 999 insertions(+), 396 deletions(-) create mode 100644 server/src/path_serializer.rs create mode 100644 server/tests/snapshots.rs rename test-projects/{composing-models => composing_models}/default.project.json (100%) rename test-projects/{composing-models => composing_models}/src/Binary.rbxm (100%) rename test-projects/{composing-models => composing_models}/src/Remotes.model.json (100%) rename test-projects/{composing-models => composing_models}/src/XML.rbxmx (100%) create mode 100644 test-projects/empty/expected-snapshot.json rename test-projects/{missing-files => missing_files}/default.project.json (100%) create mode 100644 test-projects/nested_partitions/default.project.json create mode 100644 test-projects/nested_partitions/expected-snapshot.json create mode 100644 test-projects/nested_partitions/inner/hello.lua create mode 100644 test-projects/nested_partitions/outer/world.lua delete mode 100644 test-projects/single-sync-point/lib/sampleTranslation.csv rename test-projects/{single-sync-point => single_partition_game}/default.project.json (100%) create mode 100644 test-projects/single_partition_game/expected-snapshot.json rename test-projects/{single-sync-point => single_partition_game}/lib/foo.txt (100%) rename test-projects/{single-sync-point => single_partition_game}/lib/main.lua (100%) rename test-projects/{test-model => single_partition_model}/default.project.json (100%) create mode 100644 test-projects/single_partition_model/expected-snapshot.json rename test-projects/{test-model => single_partition_model}/src/main.server.lua (100%) rename test-projects/{test-model => single_partition_model}/src/other.lua (100%) create mode 100644 test-projects/transmute_partition/ReplicatedStorage/hello.lua create mode 100644 test-projects/transmute_partition/default.project.json create mode 100644 test-projects/transmute_partition/expected-snapshot.json diff --git a/Cargo.lock b/Cargo.lock index 5824f1d5..027834be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -330,6 +330,11 @@ dependencies = [ "gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "difference" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "dtoa" version = "0.4.3" @@ -932,6 +937,26 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "paste" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "paste-impl" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "percent-encoding" version = "1.0.1" @@ -977,6 +1002,25 @@ name = "pkg-config" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "pretty_assertions" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-hack" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro2" version = "0.4.26" @@ -1258,6 +1302,8 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_tree 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1927,6 +1973,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" "checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86" +"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" @@ -1993,12 +2040,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f50392d1265092fbee9273414cc40eb6d47d307bd66222c477bb8450c8504f9d" +"checksum paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3cd512fe3a55e8933b2dcad913e365639db86d512e4004c3084b86864d9467a" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" +"checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" "checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" diff --git a/server/Cargo.toml b/server/Cargo.toml index fa96ef5e..0e878811 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -28,6 +28,9 @@ log = "0.4" maplit = "1.0.1" notify = "4.0" rand = "0.4" +rbx_binary = "0.2.0" +rbx_tree = "0.2.0" +rbx_xml = "0.2.0" regex = "1.0" reqwest = "0.9.5" rouille = "2.1" @@ -35,11 +38,10 @@ serde = "1.0" serde_derive = "1.0" serde_json = "1.0" uuid = { version = "0.7", features = ["v4", "serde"] } -rbx_tree = "0.2.0" -rbx_xml = "0.2.0" -rbx_binary = "0.2.0" [dev-dependencies] tempfile = "3.0" walkdir = "2.1" -lazy_static = "1.2" \ No newline at end of file +lazy_static = "1.2" +pretty_assertions = "0.5.1" +paste = "0.1" \ No newline at end of file diff --git a/server/src/fs_watcher.rs b/server/src/fs_watcher.rs index 33159a55..9641b293 100644 --- a/server/src/fs_watcher.rs +++ b/server/src/fs_watcher.rs @@ -44,13 +44,14 @@ impl FsWatcher { let imfs = imfs.lock().unwrap(); for root_path in imfs.get_roots() { + trace!("Watching path {}", root_path.display()); watcher.watch(root_path, RecursiveMode::Recursive) .expect("Could not watch directory"); } } { - let imfs = Arc::clone(&imfs); + let imfs = Arc::clone(&imfs); let rbx_session = rbx_session.as_ref().map(Arc::clone); thread::spawn(move || { diff --git a/server/src/imfs.rs b/server/src/imfs.rs index cd14b5b1..c144ae5e 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -35,16 +35,13 @@ impl fmt::Display for FsError { } } -fn add_sync_points(imfs: &mut Imfs, project_node: &ProjectNode) -> Result<(), FsError> { - match project_node { - ProjectNode::Instance(node) => { - for child in node.children.values() { - add_sync_points(imfs, child)?; - } - }, - ProjectNode::SyncPoint(node) => { - imfs.add_root(&node.path)?; - }, +fn add_sync_points(imfs: &mut Imfs, node: &ProjectNode) -> Result<(), FsError> { + if let Some(path) = &node.path { + imfs.add_root(path)?; + } + + for child in node.children.values() { + add_sync_points(imfs, child)?; } Ok(()) diff --git a/server/src/lib.rs b/server/src/lib.rs index 6befeb64..2239a23c 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -6,12 +6,13 @@ pub mod impl_from; pub mod commands; pub mod fs_watcher; pub mod imfs; +pub mod live_session; pub mod message_queue; pub mod path_map; +pub mod path_serializer; pub mod project; pub mod rbx_session; pub mod rbx_snapshot; -pub mod live_session; pub mod session_id; pub mod snapshot_reconciler; pub mod visualize; diff --git a/server/src/path_map.rs b/server/src/path_map.rs index af3f473c..d944541e 100644 --- a/server/src/path_map.rs +++ b/server/src/path_map.rs @@ -1,5 +1,4 @@ use std::{ - collections::hash_map, path::{self, Path, PathBuf}, collections::{HashMap, HashSet}, }; @@ -36,12 +35,6 @@ impl PathMap { self.nodes.get_mut(path).map(|v| &mut v.value) } - pub fn entry<'a>(&'a mut self, path: PathBuf) -> Entry<'a, T> { - Entry { - internal: self.nodes.entry(path), - } - } - pub fn insert(&mut self, path: PathBuf, value: T) { if let Some(parent_path) = path.parent() { if let Some(parent) = self.nodes.get_mut(parent_path) { @@ -116,28 +109,4 @@ impl PathMap { current_path } -} - -pub struct Entry<'a, T> { - internal: hash_map::Entry<'a, PathBuf, PathMapNode>, -} - -impl<'a, T> Entry<'a, T> { - pub fn or_insert(self, value: T) -> &'a mut T { - &mut self.internal.or_insert(PathMapNode { - value, - children: HashSet::new(), - }).value - } -} - -impl<'a, T> Entry<'a, T> - where T: Default -{ - pub fn or_default(self) -> &'a mut T { - &mut self.internal.or_insert(PathMapNode { - value: Default::default(), - children: HashSet::new(), - }).value - } } \ No newline at end of file diff --git a/server/src/path_serializer.rs b/server/src/path_serializer.rs new file mode 100644 index 00000000..214a773a --- /dev/null +++ b/server/src/path_serializer.rs @@ -0,0 +1,69 @@ +//! path_serializer is used in cases where we need to serialize relative Path +//! and PathBuf objects in a way that's cross-platform. +//! +//! This is used for the snapshot testing system to make sure that snapshots +//! that reference local paths that are generated on Windows don't fail when run +//! in systems that use a different directory separator. +//! +//! To use, annotate your PathBuf or Option field with the correct +//! serializer function: +//! +//! ``` +//! # use std::path::PathBuf; +//! # use serde_derive::{Serialize, Deserialize}; +//! +//! #[derive(Serialize, Deserialize)] +//! struct Mine { +//! name: String, +//! +//! // Use 'crate' instead of librojo if writing code inside Rojo +//! #[serde(serialize_with = "librojo::path_serializer::serialize")] +//! source_path: PathBuf, +//! +//! #[serde(serialize_with = "librojo::path_serializer::serialize_option")] +//! maybe_path: Option, +//! } +//! ``` +//! +//! **The methods in this module can only handle relative paths, since absolute +//! paths are never portable.** + +use std::path::{Component, Path}; + +use serde::Serializer; + +pub fn serialize_option(maybe_path: &Option, serializer: S) -> Result + where S: Serializer, + T: AsRef, +{ + match maybe_path { + Some(path) => serialize(path, serializer), + None => serializer.serialize_none() + } +} + +pub fn serialize(path: T, serializer: S) -> Result + where S: Serializer, + T: AsRef, +{ + let path = path.as_ref(); + + assert!(path.is_relative(), "path_serializer can only handle relative paths"); + + let mut output = String::new(); + + for component in path.components() { + if !output.is_empty() { + output.push('/'); + } + + match component { + Component::CurDir => output.push('.'), + Component::ParentDir => output.push_str(".."), + Component::Normal(piece) => output.push_str(piece.to_str().unwrap()), + _ => panic!("path_serializer cannot handle absolute path components"), + } + } + + serializer.serialize_str(&output) +} \ No newline at end of file diff --git a/server/src/project.rs b/server/src/project.rs index c391e02d..46ea7492 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -15,16 +15,6 @@ use serde_derive::{Serialize, Deserialize}; pub static PROJECT_FILENAME: &'static str = "default.project.json"; pub static COMPAT_PROJECT_FILENAME: &'static str = "roblox-project.json"; -// Methods used for Serde's default value system, which doesn't support using -// value literals directly, only functions that return values. -const fn yeah() -> bool { - true -} - -const fn is_true(value: &bool) -> bool { - *value -} - /// SourceProject is the format that users author projects on-disk. Since we /// want to do things like transforming paths to be absolute before handing them /// off to the rest of Rojo, we use this intermediate struct. @@ -60,59 +50,47 @@ impl SourceProject { /// slightly different on-disk than how we want to handle them in the rest of /// Rojo. #[derive(Debug, Serialize, Deserialize)] -#[serde(untagged)] -enum SourceProjectNode { - Instance { - #[serde(rename = "$className")] - class_name: String, +struct SourceProjectNode { + #[serde(rename = "$className", skip_serializing_if = "Option::is_none")] + class_name: Option, - #[serde(rename = "$properties", default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")] - properties: HashMap, + #[serde(rename = "$properties", default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")] + properties: HashMap, - #[serde(rename = "$ignoreUnknownInstances", default = "yeah", skip_serializing_if = "is_true")] - ignore_unknown_instances: bool, + #[serde(rename = "$ignoreUnknownInstances", skip_serializing_if = "Option::is_none")] + ignore_unknown_instances: Option, - #[serde(flatten)] - children: HashMap, - }, - SyncPoint { - #[serde(rename = "$path")] - path: String, - } + #[serde(rename = "$path", skip_serializing_if = "Option::is_none")] + path: Option, + + #[serde(flatten)] + children: HashMap, } impl SourceProjectNode { /// Consumes the SourceProjectNode and turns it into a ProjectNode. - pub fn into_project_node(self, project_file_location: &Path) -> ProjectNode { - match self { - SourceProjectNode::Instance { class_name, mut children, properties, ignore_unknown_instances } => { - let mut new_children = HashMap::new(); + pub fn into_project_node(mut self, project_file_location: &Path) -> ProjectNode { + let children = self.children.drain() + .map(|(key, value)| (key, value.into_project_node(project_file_location))) + .collect(); - for (node_name, node) in children.drain() { - new_children.insert(node_name, node.into_project_node(project_file_location)); - } + // Make sure that paths are absolute, transforming them by adding the + // project folder if they're not already absolute. + let path = self.path.as_ref().map(|source_path| { + if Path::new(source_path).is_absolute() { + PathBuf::from(source_path) + } else { + let project_folder_location = project_file_location.parent().unwrap(); + project_folder_location.join(source_path) + } + }); - ProjectNode::Instance(InstanceProjectNode { - class_name, - children: new_children, - properties, - metadata: InstanceProjectNodeMetadata { - ignore_unknown_instances, - }, - }) - }, - SourceProjectNode::SyncPoint { path: source_path } => { - let path = if Path::new(&source_path).is_absolute() { - PathBuf::from(source_path) - } else { - let project_folder_location = project_file_location.parent().unwrap(); - project_folder_location.join(source_path) - }; - - ProjectNode::SyncPoint(SyncPointProjectNode { - path, - }) - }, + ProjectNode { + class_name: self.class_name, + properties: self.properties, + ignore_unknown_instances: self.ignore_unknown_instances, + path, + children, } } } @@ -177,75 +155,49 @@ pub enum ProjectSaveError { IoError(#[fail(cause)] io::Error), } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct InstanceProjectNodeMetadata { - pub ignore_unknown_instances: bool, -} +#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] +pub struct ProjectNode { + pub class_name: Option, + pub children: HashMap, + pub properties: HashMap, + pub ignore_unknown_instances: Option, -impl Default for InstanceProjectNodeMetadata { - fn default() -> InstanceProjectNodeMetadata { - InstanceProjectNodeMetadata { - ignore_unknown_instances: true, - } - } -} - -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(tag = "type")] -pub enum ProjectNode { - Instance(InstanceProjectNode), - SyncPoint(SyncPointProjectNode), + #[serde(serialize_with = "crate::path_serializer::serialize_option")] + pub path: Option, } impl ProjectNode { fn to_source_node(&self, project_file_location: &Path) -> SourceProjectNode { - match self { - ProjectNode::Instance(node) => { - let mut children = HashMap::new(); + let children = self.children.iter() + .map(|(key, value)| (key.clone(), value.to_source_node(project_file_location))) + .collect(); - for (key, child) in &node.children { - children.insert(key.clone(), child.to_source_node(project_file_location)); - } + // If paths are relative to the project file, transform them to look + // Unixy and write relative paths instead. + // + // This isn't perfect, since it means that paths like .. will stay as + // absolute paths and make projects non-portable. Fixing this probably + // means keeping the paths relative in the project format and making + // everywhere else in Rojo do the resolution locally. + let path = self.path.as_ref().map(|path| { + let project_folder_location = project_file_location.parent().unwrap(); - SourceProjectNode::Instance { - class_name: node.class_name.clone(), - children, - properties: node.properties.clone(), - ignore_unknown_instances: node.metadata.ignore_unknown_instances, - } - }, - ProjectNode::SyncPoint(sync_node) => { - let project_folder_location = project_file_location.parent().unwrap(); + match path.strip_prefix(project_folder_location) { + Ok(stripped) => stripped.to_str().unwrap().replace("\\", "/"), + Err(_) => format!("{}", path.display()), + } + }); - let friendly_path = match sync_node.path.strip_prefix(project_folder_location) { - Ok(stripped) => stripped.to_str().unwrap().replace("\\", "/"), - Err(_) => format!("{}", sync_node.path.display()), - }; - - SourceProjectNode::SyncPoint { - path: friendly_path, - } - }, + SourceProjectNode { + class_name: self.class_name.clone(), + properties: self.properties.clone(), + ignore_unknown_instances: self.ignore_unknown_instances, + children, + path, } } } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct InstanceProjectNode { - pub class_name: String, - pub children: HashMap, - pub properties: HashMap, - pub metadata: InstanceProjectNodeMetadata, -} - -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SyncPointProjectNode { - pub path: PathBuf, -} - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Project { pub name: String, @@ -265,33 +217,31 @@ impl Project { project_fuzzy_path.file_name().unwrap().to_str().unwrap() }; - let tree = ProjectNode::Instance(InstanceProjectNode { - class_name: "DataModel".to_string(), + let tree = ProjectNode { + class_name: Some(String::from("DataModel")), children: hashmap! { - String::from("ReplicatedStorage") => ProjectNode::Instance(InstanceProjectNode { - class_name: String::from("ReplicatedStorage"), + String::from("ReplicatedStorage") => ProjectNode { + class_name: Some(String::from("ReplicatedStorage")), children: hashmap! { - String::from("Source") => ProjectNode::SyncPoint(SyncPointProjectNode { - path: project_folder_path.join("src"), - }), + String::from("Source") => ProjectNode { + path: Some(project_folder_path.join("src")), + ..Default::default() + }, }, - properties: HashMap::new(), - metadata: Default::default(), - }), - String::from("HttpService") => ProjectNode::Instance(InstanceProjectNode { - class_name: String::from("HttpService"), - children: HashMap::new(), + ..Default::default() + }, + String::from("HttpService") => ProjectNode { + class_name: Some(String::from("HttpService")), properties: hashmap! { String::from("HttpEnabled") => RbxValue::Bool { value: true, }, }, - metadata: Default::default(), - }), + ..Default::default() + }, }, - properties: HashMap::new(), - metadata: Default::default(), - }); + ..Default::default() + }; let project = Project { name: project_name.to_string(), @@ -316,9 +266,10 @@ impl Project { project_fuzzy_path.file_name().unwrap().to_str().unwrap() }; - let tree = ProjectNode::SyncPoint(SyncPointProjectNode { - path: project_folder_path.join("src"), - }); + let tree = ProjectNode { + path: Some(project_folder_path.join("src")), + ..Default::default() + }; let project = Project { name: project_name.to_string(), diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 47a22535..c6e32375 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -1,6 +1,6 @@ use std::{ borrow::Cow, - collections::HashMap, + collections::{HashSet, HashMap}, path::{Path, PathBuf}, str, sync::{Arc, Mutex}, @@ -11,11 +11,11 @@ use log::{info, trace}; use rbx_tree::{RbxTree, RbxId}; use crate::{ - project::Project, + project::{Project, ProjectNode}, message_queue::MessageQueue, imfs::{Imfs, ImfsItem}, path_map::PathMap, - rbx_snapshot::{SnapshotContext, snapshot_project_tree, snapshot_imfs_path}, + rbx_snapshot::{snapshot_project_tree, snapshot_project_node, snapshot_imfs_path}, snapshot_reconciler::{InstanceChanges, reify_root, reconcile_subtree}, }; @@ -23,24 +23,28 @@ const INIT_SCRIPT: &str = "init.lua"; const INIT_SERVER_SCRIPT: &str = "init.server.lua"; const INIT_CLIENT_SCRIPT: &str = "init.client.lua"; -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -pub struct MetadataPerPath { - pub instance_id: Option, - pub instance_name: Option, -} - -#[derive(Debug, Clone, Default, Serialize, Deserialize)] +/// `source_path` or `project_definition` or both must both be Some. +#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct MetadataPerInstance { - pub source_path: Option, pub ignore_unknown_instances: bool, + + /// The path on the filesystem that the instance was read from the + /// filesystem if it came from the filesystem. + #[serde(serialize_with = "crate::path_serializer::serialize_option")] + pub source_path: Option, + + /// Information about the instance that came from the project that defined + /// it, if that's where it was defined. + /// + /// A key-value pair where the key should be the name of the instance and + /// the value is the ProjectNode from the instance's project. + pub project_definition: Option<(String, ProjectNode)>, } pub struct RbxSession { tree: RbxTree, - // TODO(#105): Change metadata_per_path to PathMap> for - // path aliasing. - metadata_per_path: PathMap, + instances_per_path: PathMap>, metadata_per_instance: HashMap, message_queue: Arc>, imfs: Arc>, @@ -52,17 +56,17 @@ impl RbxSession { imfs: Arc>, message_queue: Arc>, ) -> RbxSession { - let mut metadata_per_path = PathMap::new(); + let mut instances_per_path = PathMap::new(); let mut metadata_per_instance = HashMap::new(); let tree = { let temp_imfs = imfs.lock().unwrap(); - reify_initial_tree(&project, &temp_imfs, &mut metadata_per_path, &mut metadata_per_instance) + reify_initial_tree(&project, &temp_imfs, &mut instances_per_path, &mut metadata_per_instance) }; RbxSession { tree, - metadata_per_path, + instances_per_path, metadata_per_instance, message_queue, imfs, @@ -80,7 +84,7 @@ impl RbxSession { .expect("Path was outside in-memory filesystem roots"); // Find the closest instance in the tree that currently exists - let mut path_to_snapshot = self.metadata_per_path.descend(root_path, path); + let mut path_to_snapshot = self.instances_per_path.descend(root_path, path); // If this is a file that might affect its parent if modified, we // should snapshot its parent instead. @@ -93,42 +97,44 @@ impl RbxSession { trace!("Snapshotting path {}", path_to_snapshot.display()); - let path_metadata = self.metadata_per_path.get(&path_to_snapshot).unwrap(); + let instances_at_path = self.instances_per_path.get(&path_to_snapshot) + .expect("Metadata did not exist for path") + .clone(); - trace!("Metadata for path: {:?}", path_metadata); + for instance_id in &instances_at_path { + let instance_metadata = self.metadata_per_instance.get(&instance_id) + .expect("Metadata for instance ID did not exist"); - let instance_id = path_metadata.instance_id - .expect("Instance did not exist in tree"); + let maybe_snapshot = match &instance_metadata.project_definition { + Some((instance_name, project_node)) => { + snapshot_project_node(&imfs, &project_node, Cow::Owned(instance_name.clone())) + .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())) + }, + None => { + snapshot_imfs_path(&imfs, &path_to_snapshot, None) + .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())) + }, + }; - // If this instance is a sync point, pull its name out of our - // per-path metadata store. - let instance_name = path_metadata.instance_name.as_ref() - .map(|value| Cow::Owned(value.to_owned())); + let snapshot = match maybe_snapshot { + Some(snapshot) => snapshot, + None => { + trace!("Path resulted in no snapshot being generated."); + return; + }, + }; - let mut context = SnapshotContext { - metadata_per_path: &mut self.metadata_per_path, - }; - let maybe_snapshot = snapshot_imfs_path(&imfs, &mut context, &path_to_snapshot, instance_name) - .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())); + trace!("Snapshot: {:#?}", snapshot); - let snapshot = match maybe_snapshot { - Some(snapshot) => snapshot, - None => { - trace!("Path resulted in no snapshot being generated."); - return; - }, - }; - - trace!("Snapshot: {:#?}", snapshot); - - reconcile_subtree( - &mut self.tree, - instance_id, - &snapshot, - &mut self.metadata_per_path, - &mut self.metadata_per_instance, - &mut changes, - ); + reconcile_subtree( + &mut self.tree, + *instance_id, + &snapshot, + &mut self.instances_per_path, + &mut self.metadata_per_instance, + &mut changes, + ); + } } if changes.is_empty() { @@ -170,13 +176,13 @@ impl RbxSession { pub fn path_removed(&mut self, path: &Path) { info!("Path removed: {}", path.display()); - self.metadata_per_path.remove(path); + self.instances_per_path.remove(path); self.path_created_or_updated(path); } pub fn path_renamed(&mut self, from_path: &Path, to_path: &Path) { info!("Path renamed from {} to {}", from_path.display(), to_path.display()); - self.metadata_per_path.remove(from_path); + self.instances_per_path.remove(from_path); self.path_created_or_updated(from_path); self.path_created_or_updated(to_path); } @@ -188,33 +194,26 @@ impl RbxSession { pub fn get_instance_metadata(&self, id: RbxId) -> Option<&MetadataPerInstance> { self.metadata_per_instance.get(&id) } - - pub fn debug_get_metadata_per_path(&self) -> &PathMap { - &self.metadata_per_path - } } pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { - let mut metadata_per_path = PathMap::new(); + let mut instances_per_path = PathMap::new(); let mut metadata_per_instance = HashMap::new(); - reify_initial_tree(project, imfs, &mut metadata_per_path, &mut metadata_per_instance) + reify_initial_tree(project, imfs, &mut instances_per_path, &mut metadata_per_instance) } fn reify_initial_tree( project: &Project, imfs: &Imfs, - metadata_per_path: &mut PathMap, + instances_per_path: &mut PathMap>, metadata_per_instance: &mut HashMap, ) -> RbxTree { - let mut context = SnapshotContext { - metadata_per_path, - }; - let snapshot = snapshot_project_tree(imfs, &mut context, project) + let snapshot = snapshot_project_tree(imfs, project) .expect("Could not snapshot project tree") .expect("Project did not produce any instances"); let mut changes = InstanceChanges::default(); - let tree = reify_root(&snapshot, metadata_per_path, metadata_per_instance, &mut changes); + let tree = reify_root(&snapshot, instances_per_path, metadata_per_instance, &mut changes); tree } \ No newline at end of file diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index fe3a2637..4b08be4f 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -22,16 +22,13 @@ use crate::{ project::{ Project, ProjectNode, - InstanceProjectNode, - SyncPointProjectNode, }, snapshot_reconciler::{ RbxSnapshotInstance, snapshot_from_tree, }, - path_map::PathMap, - // TODO: Move MetadataPerPath into this module? - rbx_session::{MetadataPerPath, MetadataPerInstance}, + // TODO: Move MetadataPerInstance into this module? + rbx_session::MetadataPerInstance, }; const INIT_MODULE_NAME: &str = "init.lua"; @@ -40,10 +37,6 @@ const INIT_CLIENT_NAME: &str = "init.client.lua"; pub type SnapshotResult<'a> = Result>, SnapshotError>; -pub struct SnapshotContext<'meta> { - pub metadata_per_path: &'meta mut PathMap, -} - #[derive(Debug, Fail)] pub enum SnapshotError { DidNotExist(PathBuf), @@ -55,6 +48,7 @@ pub enum SnapshotError { }, JsonModelDecodeError { + #[fail(cause)] inner: serde_json::Error, path: PathBuf, }, @@ -68,6 +62,12 @@ pub enum SnapshotError { inner: rbx_binary::DecodeError, path: PathBuf, }, + + ProjectNodeUnusable, + + ProjectNodeInvalidTransmute { + partition_path: PathBuf, + }, } impl fmt::Display for SnapshotError { @@ -78,7 +78,7 @@ impl fmt::Display for SnapshotError { write!(output, "Invalid UTF-8: {} in path {}", inner, path.display()) }, SnapshotError::JsonModelDecodeError { inner, path } => { - write!(output, "Malformed .model.json model: {:?} in path {}", inner, path.display()) + write!(output, "Malformed .model.json model: {} in path {}", inner, path.display()) }, SnapshotError::XmlModelDecodeError { inner, path } => { write!(output, "Malformed rbxmx model: {:?} in path {}", inner, path.display()) @@ -86,107 +86,131 @@ impl fmt::Display for SnapshotError { SnapshotError::BinaryModelDecodeError { inner, path } => { write!(output, "Malformed rbxm model: {:?} in path {}", inner, path.display()) }, + SnapshotError::ProjectNodeUnusable => { + write!(output, "Rojo project nodes must specify either $path or $className.") + }, + SnapshotError::ProjectNodeInvalidTransmute { partition_path } => { + writeln!(output, "Rojo project nodes that specify both $path and $className require that the")?; + writeln!(output, "instance produced by the files pointed to by $path has a ClassName of")?; + writeln!(output, "Folder.")?; + writeln!(output, "")?; + writeln!(output, "Partition target ($path): {}", partition_path.display()) + }, } } } pub fn snapshot_project_tree<'source>( imfs: &'source Imfs, - context: &mut SnapshotContext, project: &'source Project, ) -> SnapshotResult<'source> { - snapshot_project_node(imfs, context, &project.tree, Cow::Borrowed(&project.name)) + snapshot_project_node(imfs, &project.tree, Cow::Borrowed(&project.name)) } -fn snapshot_project_node<'source>( +pub fn snapshot_project_node<'source>( imfs: &'source Imfs, - context: &mut SnapshotContext, - node: &'source ProjectNode, + node: &ProjectNode, instance_name: Cow<'source, str>, ) -> SnapshotResult<'source> { - match node { - ProjectNode::Instance(instance_node) => snapshot_instance_node(imfs, context, instance_node, instance_name), - ProjectNode::SyncPoint(sync_node) => snapshot_sync_point_node(imfs, context, sync_node, instance_name), - } -} + let maybe_snapshot = match &node.path { + Some(path) => snapshot_imfs_path(imfs, &path, Some(instance_name.clone()))?, + None => match &node.class_name { + Some(_class_name) => Some(RbxSnapshotInstance { + name: instance_name.clone(), -fn snapshot_instance_node<'source>( - imfs: &'source Imfs, - context: &mut SnapshotContext, - node: &'source InstanceProjectNode, - instance_name: Cow<'source, str>, -) -> SnapshotResult<'source> { - let mut children = Vec::new(); - - for (child_name, child_project_node) in &node.children { - if let Some(child) = snapshot_project_node(imfs, context, child_project_node, Cow::Borrowed(child_name))? { - children.push(child); - } - } - - Ok(Some(RbxSnapshotInstance { - class_name: Cow::Borrowed(&node.class_name), - name: instance_name, - properties: node.properties.clone(), - children, - metadata: MetadataPerInstance { - source_path: None, - ignore_unknown_instances: node.metadata.ignore_unknown_instances, + // These properties are replaced later in the function to + // reduce code duplication. + class_name: Cow::Borrowed("Folder"), + properties: HashMap::new(), + children: Vec::new(), + metadata: MetadataPerInstance { + source_path: None, + ignore_unknown_instances: true, + project_definition: None, + }, + }), + None => { + return Err(SnapshotError::ProjectNodeUnusable); + }, }, - })) -} - -fn snapshot_sync_point_node<'source>( - imfs: &'source Imfs, - context: &mut SnapshotContext, - node: &'source SyncPointProjectNode, - instance_name: Cow<'source, str>, -) -> SnapshotResult<'source> { - let maybe_snapshot = snapshot_imfs_path(imfs, context, &node.path, Some(instance_name))?; + }; // If the snapshot resulted in no instances, like if it targets an unknown // file or an empty model file, we can early-return. - let snapshot = match maybe_snapshot { + // + // In the future, we might want to issue a warning if the project also + // specified fields like class_name, since the user will probably be + // confused as to why nothing showed up in the tree. + let mut snapshot = match maybe_snapshot { Some(snapshot) => snapshot, - None => return Ok(None), + None => { + // TODO: Return some other sort of marker here instead? If a node + // transitions from None into Some, it's possible that configuration + // from the ProjectNode might be lost since there's nowhere to put + // it! + return Ok(None); + }, }; - // Otherwise, we can log the name of the sync point we just snapshotted. - let path_meta = context.metadata_per_path.entry(node.path.to_owned()).or_default(); - path_meta.instance_name = Some(snapshot.name.clone().into_owned()); + // Applies the class name specified in `class_name` from the project, if it's + // set. + if let Some(class_name) = &node.class_name { + // This can only happen if `path` was specified in the project node and + // that path represented a non-Folder instance. + if snapshot.class_name != "Folder" { + return Err(SnapshotError::ProjectNodeInvalidTransmute { + partition_path: node.path.as_ref().unwrap().to_owned(), + }); + } + + snapshot.class_name = Cow::Owned(class_name.to_owned()); + } + + for (child_name, child_project_node) in &node.children { + if let Some(child) = snapshot_project_node(imfs, child_project_node, Cow::Owned(child_name.clone()))? { + snapshot.children.push(child); + } + } + + for (key, value) in &node.properties { + snapshot.properties.insert(key.clone(), value.clone()); + } + + if let Some(ignore_unknown_instances) = node.ignore_unknown_instances { + snapshot.metadata.ignore_unknown_instances = ignore_unknown_instances; + } + + snapshot.metadata.project_definition = Some((instance_name.into_owned(), node.clone())); Ok(Some(snapshot)) } pub fn snapshot_imfs_path<'source>( imfs: &'source Imfs, - context: &mut SnapshotContext, path: &Path, instance_name: Option>, ) -> SnapshotResult<'source> { // If the given path doesn't exist in the in-memory filesystem, we consider // that an error. match imfs.get(path) { - Some(imfs_item) => snapshot_imfs_item(imfs, context, imfs_item, instance_name), + Some(imfs_item) => snapshot_imfs_item(imfs, imfs_item, instance_name), None => return Err(SnapshotError::DidNotExist(path.to_owned())), } } fn snapshot_imfs_item<'source>( imfs: &'source Imfs, - context: &mut SnapshotContext, item: &'source ImfsItem, instance_name: Option>, ) -> SnapshotResult<'source> { match item { ImfsItem::File(file) => snapshot_imfs_file(file, instance_name), - ImfsItem::Directory(directory) => snapshot_imfs_directory(imfs, context, directory, instance_name), + ImfsItem::Directory(directory) => snapshot_imfs_directory(imfs, directory, instance_name), } } fn snapshot_imfs_directory<'source>( imfs: &'source Imfs, - context: &mut SnapshotContext, directory: &'source ImfsDirectory, instance_name: Option>, ) -> SnapshotResult<'source> { @@ -202,11 +226,11 @@ fn snapshot_imfs_directory<'source>( }); let mut snapshot = if directory.children.contains(&init_path) { - snapshot_imfs_path(imfs, context, &init_path, Some(snapshot_name))?.unwrap() + snapshot_imfs_path(imfs, &init_path, Some(snapshot_name))?.unwrap() } else if directory.children.contains(&init_server_path) { - snapshot_imfs_path(imfs, context, &init_server_path, Some(snapshot_name))?.unwrap() + snapshot_imfs_path(imfs, &init_server_path, Some(snapshot_name))?.unwrap() } else if directory.children.contains(&init_client_path) { - snapshot_imfs_path(imfs, context, &init_client_path, Some(snapshot_name))?.unwrap() + snapshot_imfs_path(imfs, &init_client_path, Some(snapshot_name))?.unwrap() } else { RbxSnapshotInstance { class_name: Cow::Borrowed("Folder"), @@ -216,6 +240,7 @@ fn snapshot_imfs_directory<'source>( metadata: MetadataPerInstance { source_path: None, ignore_unknown_instances: false, + project_definition: None, }, } }; @@ -234,7 +259,7 @@ fn snapshot_imfs_directory<'source>( // them here. }, _ => { - if let Some(child) = snapshot_imfs_path(imfs, context, child_path, None)? { + if let Some(child) = snapshot_imfs_path(imfs, child_path, None)? { snapshot.children.push(child); } }, @@ -316,6 +341,7 @@ fn snapshot_lua_file<'source>( metadata: MetadataPerInstance { source_path: Some(file.path.to_path_buf()), ignore_unknown_instances: false, + project_definition: None, }, })) } @@ -354,6 +380,7 @@ fn snapshot_txt_file<'source>( metadata: MetadataPerInstance { source_path: Some(file.path.to_path_buf()), ignore_unknown_instances: false, + project_definition: None, }, })) } @@ -387,6 +414,7 @@ fn snapshot_csv_file<'source>( metadata: MetadataPerInstance { source_path: Some(file.path.to_path_buf()), ignore_unknown_instances: false, + project_definition: None, }, })) } diff --git a/server/src/snapshot_reconciler.rs b/server/src/snapshot_reconciler.rs index 2562c4cb..0255bc8d 100644 --- a/server/src/snapshot_reconciler.rs +++ b/server/src/snapshot_reconciler.rs @@ -1,8 +1,9 @@ use std::{ - str, borrow::Cow, + cmp::Ordering, collections::{HashMap, HashSet}, fmt, + str, }; use rbx_tree::{RbxTree, RbxId, RbxInstanceProperties, RbxValue}; @@ -10,7 +11,7 @@ use serde_derive::{Serialize, Deserialize}; use crate::{ path_map::PathMap, - rbx_session::{MetadataPerPath, MetadataPerInstance}, + rbx_session::MetadataPerInstance, }; #[derive(Debug, Clone, Default, Serialize, Deserialize)] @@ -55,7 +56,7 @@ impl InstanceChanges { } } -#[derive(Debug)] +#[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct RbxSnapshotInstance<'a> { pub name: Cow<'a, str>, pub class_name: Cow<'a, str>, @@ -64,6 +65,13 @@ pub struct RbxSnapshotInstance<'a> { pub metadata: MetadataPerInstance, } +impl<'a> PartialOrd for RbxSnapshotInstance<'a> { + fn partial_cmp(&self, other: &RbxSnapshotInstance) -> Option { + Some(self.name.cmp(&other.name) + .then(self.class_name.cmp(&other.class_name))) + } +} + pub fn snapshot_from_tree(tree: &RbxTree, id: RbxId) -> Option> { let instance = tree.get_instance(id)?; @@ -80,31 +88,27 @@ pub fn snapshot_from_tree(tree: &RbxTree, id: RbxId) -> Option, - instance_metadata_map: &mut HashMap, + instance_per_path: &mut PathMap>, + metadata_per_instance: &mut HashMap, changes: &mut InstanceChanges, ) -> RbxTree { let instance = reify_core(snapshot); let mut tree = RbxTree::new(instance); - let root_id = tree.get_root_id(); + let id = tree.get_root_id(); - if let Some(source_path) = &snapshot.metadata.source_path { - let path_meta = metadata_per_path.entry(source_path.to_owned()).or_default(); - path_meta.instance_id = Some(root_id); - } + reify_metadata(snapshot, id, instance_per_path, metadata_per_instance); - instance_metadata_map.insert(root_id, snapshot.metadata.clone()); - - changes.added.insert(root_id); + changes.added.insert(id); for child in &snapshot.children { - reify_subtree(child, &mut tree, root_id, metadata_per_path, instance_metadata_map, changes); + reify_subtree(child, &mut tree, id, instance_per_path, metadata_per_instance, changes); } tree @@ -114,47 +118,58 @@ pub fn reify_subtree( snapshot: &RbxSnapshotInstance, tree: &mut RbxTree, parent_id: RbxId, - metadata_per_path: &mut PathMap, - instance_metadata_map: &mut HashMap, + instance_per_path: &mut PathMap>, + metadata_per_instance: &mut HashMap, changes: &mut InstanceChanges, ) { let instance = reify_core(snapshot); let id = tree.insert_instance(instance, parent_id); - if let Some(source_path) = &snapshot.metadata.source_path { - let path_meta = metadata_per_path.entry(source_path.clone()).or_default(); - path_meta.instance_id = Some(id); - } - - instance_metadata_map.insert(id, snapshot.metadata.clone()); + reify_metadata(snapshot, id, instance_per_path, metadata_per_instance); changes.added.insert(id); for child in &snapshot.children { - reify_subtree(child, tree, id, metadata_per_path, instance_metadata_map, changes); + reify_subtree(child, tree, id, instance_per_path, metadata_per_instance, changes); } } +pub fn reify_metadata( + snapshot: &RbxSnapshotInstance, + instance_id: RbxId, + instance_per_path: &mut PathMap>, + metadata_per_instance: &mut HashMap, +) { + if let Some(source_path) = &snapshot.metadata.source_path { + let path_metadata = match instance_per_path.get_mut(&source_path) { + Some(v) => v, + None => { + instance_per_path.insert(source_path.clone(), Default::default()); + instance_per_path.get_mut(&source_path).unwrap() + }, + }; + + path_metadata.insert(instance_id); + } + + metadata_per_instance.insert(instance_id, snapshot.metadata.clone()); +} + pub fn reconcile_subtree( tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance, - metadata_per_path: &mut PathMap, - instance_metadata_map: &mut HashMap, + instance_per_path: &mut PathMap>, + metadata_per_instance: &mut HashMap, changes: &mut InstanceChanges, ) { - if let Some(source_path) = &snapshot.metadata.source_path { - let path_meta = metadata_per_path.entry(source_path.to_owned()).or_default(); - path_meta.instance_id = Some(id); - } - - instance_metadata_map.insert(id, snapshot.metadata.clone()); + reify_metadata(snapshot, id, instance_per_path, metadata_per_instance); if reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot) { changes.updated.insert(id); } - reconcile_instance_children(tree, id, snapshot, metadata_per_path, instance_metadata_map, changes); + reconcile_instance_children(tree, id, snapshot, instance_per_path, metadata_per_instance, changes); } fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstanceProperties { @@ -234,8 +249,8 @@ fn reconcile_instance_children( tree: &mut RbxTree, id: RbxId, snapshot: &RbxSnapshotInstance, - metadata_per_path: &mut PathMap, - instance_metadata_map: &mut HashMap, + instance_per_path: &mut PathMap>, + metadata_per_instance: &mut HashMap, changes: &mut InstanceChanges, ) { let mut visited_snapshot_indices = HashSet::new(); @@ -287,19 +302,19 @@ fn reconcile_instance_children( } for child_snapshot in &children_to_add { - reify_subtree(child_snapshot, tree, id, metadata_per_path, instance_metadata_map, changes); + reify_subtree(child_snapshot, tree, id, instance_per_path, metadata_per_instance, changes); } for child_id in &children_to_remove { if let Some(subtree) = tree.remove_instance(*child_id) { for id in subtree.iter_all_ids() { - instance_metadata_map.remove(&id); + metadata_per_instance.remove(&id); changes.removed.insert(id); } } } for (child_id, child_snapshot) in &children_to_update { - reconcile_subtree(tree, *child_id, child_snapshot, metadata_per_path, instance_metadata_map, changes); + reconcile_subtree(tree, *child_id, child_snapshot, instance_per_path, metadata_per_instance, changes); } } \ No newline at end of file diff --git a/server/src/visualize.rs b/server/src/visualize.rs index a09326e8..c64bd328 100644 --- a/server/src/visualize.rs +++ b/server/src/visualize.rs @@ -11,7 +11,7 @@ use rbx_tree::RbxId; use crate::{ imfs::{Imfs, ImfsItem}, rbx_session::RbxSession, - web::InstanceMetadata, + web::PublicInstanceMetadata, }; static GRAPHVIZ_HEADER: &str = r#" @@ -74,7 +74,7 @@ fn visualize_rbx_node(session: &RbxSession, id: RbxId, output: &mut fmt::Formatt let mut node_label = format!("{}|{}|{}", node.name, node.class_name, id); if let Some(session_metadata) = session.get_instance_metadata(id) { - let metadata = InstanceMetadata::from_session_metadata(session_metadata); + let metadata = PublicInstanceMetadata::from_session_metadata(session_metadata); node_label.push('|'); node_label.push_str(&serde_json::to_string(&metadata).unwrap()); } diff --git a/server/src/web.rs b/server/src/web.rs index 5c78bdfa..1efd174b 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -27,13 +27,13 @@ static HOME_CONTENT: &str = include_str!("../assets/index.html"); /// Contains the instance metadata relevant to Rojo clients. #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct InstanceMetadata { +pub struct PublicInstanceMetadata { ignore_unknown_instances: bool, } -impl InstanceMetadata { - pub fn from_session_metadata(meta: &MetadataPerInstance) -> InstanceMetadata { - InstanceMetadata { +impl PublicInstanceMetadata { + pub fn from_session_metadata(meta: &MetadataPerInstance) -> PublicInstanceMetadata { + PublicInstanceMetadata { ignore_unknown_instances: meta.ignore_unknown_instances, } } @@ -50,7 +50,7 @@ pub struct InstanceWithMetadata<'a> { pub instance: Cow<'a, RbxInstance>, #[serde(rename = "Metadata")] - pub metadata: Option, + pub metadata: Option, } #[derive(Debug, Serialize, Deserialize)] @@ -120,9 +120,6 @@ impl Server { (GET) (/visualize/imfs) => { self.handle_visualize_imfs() }, - (GET) (/visualize/path_metadata) => { - self.handle_visualize_path_metadata() - }, _ => Response::empty_404() ) } @@ -209,7 +206,7 @@ impl Server { for &requested_id in &requested_ids { if let Some(instance) = tree.get_instance(requested_id) { let metadata = rbx_session.get_instance_metadata(requested_id) - .map(InstanceMetadata::from_session_metadata); + .map(PublicInstanceMetadata::from_session_metadata); instances.insert(instance.get_id(), InstanceWithMetadata { instance: Cow::Borrowed(instance), @@ -218,7 +215,7 @@ impl Server { for descendant in tree.descendants(requested_id) { let descendant_meta = rbx_session.get_instance_metadata(descendant.get_id()) - .map(InstanceMetadata::from_session_metadata); + .map(PublicInstanceMetadata::from_session_metadata); instances.insert(descendant.get_id(), InstanceWithMetadata { instance: Cow::Borrowed(descendant), @@ -254,9 +251,4 @@ impl Server { None => Response::text(dot_source), } } - - fn handle_visualize_path_metadata(&self) -> Response { - let rbx_session = self.live_session.rbx_session.lock().unwrap(); - Response::json(&rbx_session.debug_get_metadata_per_path()) - } } \ No newline at end of file diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index 55ae5550..d5314a21 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -1,16 +1,15 @@ #[macro_use] extern crate lazy_static; -extern crate librojo; - use std::{ collections::HashMap, path::{Path, PathBuf}, }; +use pretty_assertions::assert_eq; use rbx_tree::RbxValue; use librojo::{ - project::{Project, ProjectNode, InstanceProjectNode, SyncPointProjectNode}, + project::{Project, ProjectNode}, }; lazy_static! { @@ -44,54 +43,52 @@ fn empty_fuzzy_folder() { } #[test] -fn single_sync_point() { - let project_file_location = TEST_PROJECTS_ROOT.join("single-sync-point/default.project.json"); - let project = Project::load_exact(&project_file_location).unwrap(); +fn single_partition_game() { + let project_location = TEST_PROJECTS_ROOT.join("single_partition_game"); + let project = Project::load_fuzzy(&project_location).unwrap(); let expected_project = { - let foo = ProjectNode::SyncPoint(SyncPointProjectNode { - path: project_file_location.parent().unwrap().join("lib"), - }); + let foo = ProjectNode { + path: Some(project_location.join("lib")), + ..Default::default() + }; let mut replicated_storage_children = HashMap::new(); replicated_storage_children.insert("Foo".to_string(), foo); - let replicated_storage = ProjectNode::Instance(InstanceProjectNode { - class_name: "ReplicatedStorage".to_string(), + let replicated_storage = ProjectNode { + class_name: Some(String::from("ReplicatedStorage")), children: replicated_storage_children, - properties: HashMap::new(), - metadata: Default::default(), - }); + ..Default::default() + }; let mut http_service_properties = HashMap::new(); http_service_properties.insert("HttpEnabled".to_string(), RbxValue::Bool { value: true, }); - let http_service = ProjectNode::Instance(InstanceProjectNode { - class_name: "HttpService".to_string(), - children: HashMap::new(), + let http_service = ProjectNode { + class_name: Some(String::from("HttpService")), properties: http_service_properties, - metadata: Default::default(), - }); + ..Default::default() + }; let mut root_children = HashMap::new(); root_children.insert("ReplicatedStorage".to_string(), replicated_storage); root_children.insert("HttpService".to_string(), http_service); - let root_node = ProjectNode::Instance(InstanceProjectNode { - class_name: "DataModel".to_string(), + let root_node = ProjectNode { + class_name: Some(String::from("DataModel")), children: root_children, - properties: HashMap::new(), - metadata: Default::default(), - }); + ..Default::default() + }; Project { name: "single-sync-point".to_string(), tree: root_node, serve_port: None, serve_place_ids: None, - file_location: project_file_location.clone(), + file_location: project_location.join("default.project.json"), } }; @@ -99,9 +96,17 @@ fn single_sync_point() { } #[test] -fn test_model() { - let project_file_location = TEST_PROJECTS_ROOT.join("test-model/default.project.json"); - let project = Project::load_exact(&project_file_location).unwrap(); +fn single_partition_model() { + let project_file_location = TEST_PROJECTS_ROOT.join("single_partition_model"); + let project = Project::load_fuzzy(&project_file_location).unwrap(); assert_eq!(project.name, "test-model"); +} + +#[test] +fn composing_models() { + let project_file_location = TEST_PROJECTS_ROOT.join("composing_models"); + let project = Project::load_fuzzy(&project_file_location).unwrap(); + + assert_eq!(project.name, "composing-models"); } \ No newline at end of file diff --git a/server/tests/snapshots.rs b/server/tests/snapshots.rs new file mode 100644 index 00000000..aab2193e --- /dev/null +++ b/server/tests/snapshots.rs @@ -0,0 +1,124 @@ +use std::{ + fs::{self, File}, + path::{Path, PathBuf}, +}; + +use pretty_assertions::assert_eq; + +use librojo::{ + imfs::Imfs, + project::{Project, ProjectNode}, + rbx_snapshot::snapshot_project_tree, + snapshot_reconciler::{RbxSnapshotInstance}, +}; + +macro_rules! generate_snapshot_tests { + ($($name: ident),*) => { + $( + paste::item! { + #[test] + fn []() { + let tests_folder = Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects"); + let project_folder = tests_folder.join(stringify!($name)); + run_snapshot_test(&project_folder); + } + } + )* + }; +} + +generate_snapshot_tests!( + empty, + nested_partitions, + single_partition_game, + single_partition_model, + transmute_partition +); + +const SNAPSHOT_EXPECTED_NAME: &str = "expected-snapshot.json"; + +fn run_snapshot_test(path: &Path) { + println!("Running snapshot from project: {}", path.display()); + + let project = Project::load_fuzzy(path) + .expect("Couldn't load project file for snapshot test"); + + let mut imfs = Imfs::new(); + imfs.add_roots_from_project(&project) + .expect("Could not add IMFS roots to snapshot project"); + + let mut snapshot = snapshot_project_tree(&imfs, &project) + .expect("Could not generate snapshot for snapshot test"); + + if let Some(snapshot) = snapshot.as_mut() { + anonymize_snapshot(path, snapshot); + } + + match read_expected_snapshot(path) { + Some(expected_snapshot) => assert_eq!(snapshot, expected_snapshot), + None => write_expected_snapshot(path, &snapshot), + } +} + +/// Snapshots contain absolute paths, which simplifies much of Rojo. +/// +/// For saving snapshots to the disk, we should strip off the project folder +/// path to make them machine-independent. This doesn't work for paths that fall +/// outside of the project folder, but that's okay here. +/// +/// We also need to sort children, since Rojo tends to enumerate the filesystem +/// in an unpredictable order. +fn anonymize_snapshot(project_folder_path: &Path, snapshot: &mut RbxSnapshotInstance) { + match snapshot.metadata.source_path.as_mut() { + Some(path) => *path = anonymize_path(project_folder_path, path), + None => {}, + } + + match snapshot.metadata.project_definition.as_mut() { + Some((_, project_node)) => anonymize_project_node(project_folder_path, project_node), + None => {}, + } + + snapshot.children.sort_by(|a, b| a.partial_cmp(b).unwrap()); + + for child in snapshot.children.iter_mut() { + anonymize_snapshot(project_folder_path, child); + } +} + +fn anonymize_project_node(project_folder_path: &Path, project_node: &mut ProjectNode) { + match project_node.path.as_mut() { + Some(path) => *path = anonymize_path(project_folder_path, path), + None => {}, + } + + for child_node in project_node.children.values_mut() { + anonymize_project_node(project_folder_path, child_node); + } +} + +fn anonymize_path(project_folder_path: &Path, path: &Path) -> PathBuf { + if path.is_absolute() { + path.strip_prefix(project_folder_path) + .expect("Could not anonymize absolute path") + .to_path_buf() + } else { + path.to_path_buf() + } +} + +fn read_expected_snapshot(path: &Path) -> Option>> { + let contents = fs::read(path.join(SNAPSHOT_EXPECTED_NAME)).ok()?; + let snapshot: Option> = serde_json::from_slice(&contents) + .expect("Could not deserialize snapshot"); + + Some(snapshot) +} + +fn write_expected_snapshot(path: &Path, snapshot: &Option) { + let mut file = File::create(path.join(SNAPSHOT_EXPECTED_NAME)) + .expect("Could not open file to write snapshot"); + + serde_json::to_writer_pretty(&mut file, snapshot) + .expect("Could not serialize snapshot to file"); +} \ No newline at end of file diff --git a/test-projects/composing-models/default.project.json b/test-projects/composing_models/default.project.json similarity index 100% rename from test-projects/composing-models/default.project.json rename to test-projects/composing_models/default.project.json diff --git a/test-projects/composing-models/src/Binary.rbxm b/test-projects/composing_models/src/Binary.rbxm similarity index 100% rename from test-projects/composing-models/src/Binary.rbxm rename to test-projects/composing_models/src/Binary.rbxm diff --git a/test-projects/composing-models/src/Remotes.model.json b/test-projects/composing_models/src/Remotes.model.json similarity index 100% rename from test-projects/composing-models/src/Remotes.model.json rename to test-projects/composing_models/src/Remotes.model.json diff --git a/test-projects/composing-models/src/XML.rbxmx b/test-projects/composing_models/src/XML.rbxmx similarity index 100% rename from test-projects/composing-models/src/XML.rbxmx rename to test-projects/composing_models/src/XML.rbxmx diff --git a/test-projects/empty/expected-snapshot.json b/test-projects/empty/expected-snapshot.json new file mode 100644 index 00000000..266896f3 --- /dev/null +++ b/test-projects/empty/expected-snapshot.json @@ -0,0 +1,20 @@ +{ + "name": "empty", + "class_name": "DataModel", + "properties": {}, + "children": [], + "metadata": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "empty", + { + "class_name": "DataModel", + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + } +} \ No newline at end of file diff --git a/test-projects/missing-files/default.project.json b/test-projects/missing_files/default.project.json similarity index 100% rename from test-projects/missing-files/default.project.json rename to test-projects/missing_files/default.project.json diff --git a/test-projects/nested_partitions/default.project.json b/test-projects/nested_partitions/default.project.json new file mode 100644 index 00000000..ad736a81 --- /dev/null +++ b/test-projects/nested_partitions/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "nested-partitions", + "tree": { + "$path": "outer", + "inner": { + "$path": "inner" + } + } +} \ No newline at end of file diff --git a/test-projects/nested_partitions/expected-snapshot.json b/test-projects/nested_partitions/expected-snapshot.json new file mode 100644 index 00000000..3741f613 --- /dev/null +++ b/test-projects/nested_partitions/expected-snapshot.json @@ -0,0 +1,82 @@ +{ + "name": "nested-partitions", + "class_name": "Folder", + "properties": {}, + "children": [ + { + "name": "inner", + "class_name": "Folder", + "properties": {}, + "children": [ + { + "name": "hello", + "class_name": "ModuleScript", + "properties": { + "Source": { + "Type": "String", + "Value": "-- inner/hello.lua" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "inner/hello.lua", + "project_definition": null + } + } + ], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "inner", + "project_definition": [ + "inner", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "inner" + } + ] + } + }, + { + "name": "world", + "class_name": "ModuleScript", + "properties": { + "Source": { + "Type": "String", + "Value": "-- outer/world.lua" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "outer/world.lua", + "project_definition": null + } + } + ], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "outer", + "project_definition": [ + "nested-partitions", + { + "class_name": null, + "children": { + "inner": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "inner" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": "outer" + } + ] + } +} \ No newline at end of file diff --git a/test-projects/nested_partitions/inner/hello.lua b/test-projects/nested_partitions/inner/hello.lua new file mode 100644 index 00000000..147fcfca --- /dev/null +++ b/test-projects/nested_partitions/inner/hello.lua @@ -0,0 +1 @@ +-- inner/hello.lua \ No newline at end of file diff --git a/test-projects/nested_partitions/outer/world.lua b/test-projects/nested_partitions/outer/world.lua new file mode 100644 index 00000000..aeab2c49 --- /dev/null +++ b/test-projects/nested_partitions/outer/world.lua @@ -0,0 +1 @@ +-- outer/world.lua \ No newline at end of file diff --git a/test-projects/single-sync-point/lib/sampleTranslation.csv b/test-projects/single-sync-point/lib/sampleTranslation.csv deleted file mode 100644 index 525fbdb2..00000000 --- a/test-projects/single-sync-point/lib/sampleTranslation.csv +++ /dev/null @@ -1,6 +0,0 @@ -Key,Context,Example,Source,es-es,de -,ClickableGroup:BuilderGui:TextLabel,You got 22 hearts!,You got {1} hearts!,, -,,"Team ""Red"" wins!","Team ""{1}"" wins!","¡Gana el equipo ""{1}""!","¡Gana el equipo ""{1}""!" -,Frame:TextLabel,,"{1} killed {2}, with a {3}","{1} mató a {2} con -una escopeta","{1} mató a {2} con -una escopeta" \ No newline at end of file diff --git a/test-projects/single-sync-point/default.project.json b/test-projects/single_partition_game/default.project.json similarity index 100% rename from test-projects/single-sync-point/default.project.json rename to test-projects/single_partition_game/default.project.json diff --git a/test-projects/single_partition_game/expected-snapshot.json b/test-projects/single_partition_game/expected-snapshot.json new file mode 100644 index 00000000..d3cfcc7d --- /dev/null +++ b/test-projects/single_partition_game/expected-snapshot.json @@ -0,0 +1,161 @@ +{ + "name": "single-sync-point", + "class_name": "DataModel", + "properties": {}, + "children": [ + { + "name": "HttpService", + "class_name": "HttpService", + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "HttpService", + { + "class_name": "HttpService", + "children": {}, + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "ignore_unknown_instances": null, + "path": null + } + ] + } + }, + { + "name": "ReplicatedStorage", + "class_name": "ReplicatedStorage", + "properties": {}, + "children": [ + { + "name": "Foo", + "class_name": "Folder", + "properties": {}, + "children": [ + { + "name": "foo", + "class_name": "StringValue", + "properties": { + "Value": { + "Type": "String", + "Value": "Hello world, from foo.txt" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "lib/foo.txt", + "project_definition": null + } + }, + { + "name": "main", + "class_name": "ModuleScript", + "properties": { + "Source": { + "Type": "String", + "Value": "-- hello, from main" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "lib/main.lua", + "project_definition": null + } + } + ], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "lib", + "project_definition": [ + "Foo", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "lib" + } + ] + } + } + ], + "metadata": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "ReplicatedStorage", + { + "class_name": "ReplicatedStorage", + "children": { + "Foo": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "lib" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + } + } + ], + "metadata": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "single-sync-point", + { + "class_name": "DataModel", + "children": { + "HttpService": { + "class_name": "HttpService", + "children": {}, + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "ignore_unknown_instances": null, + "path": null + }, + "ReplicatedStorage": { + "class_name": "ReplicatedStorage", + "children": { + "Foo": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "lib" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + } +} \ No newline at end of file diff --git a/test-projects/single-sync-point/lib/foo.txt b/test-projects/single_partition_game/lib/foo.txt similarity index 100% rename from test-projects/single-sync-point/lib/foo.txt rename to test-projects/single_partition_game/lib/foo.txt diff --git a/test-projects/single-sync-point/lib/main.lua b/test-projects/single_partition_game/lib/main.lua similarity index 100% rename from test-projects/single-sync-point/lib/main.lua rename to test-projects/single_partition_game/lib/main.lua diff --git a/test-projects/test-model/default.project.json b/test-projects/single_partition_model/default.project.json similarity index 100% rename from test-projects/test-model/default.project.json rename to test-projects/single_partition_model/default.project.json diff --git a/test-projects/single_partition_model/expected-snapshot.json b/test-projects/single_partition_model/expected-snapshot.json new file mode 100644 index 00000000..9014aaaa --- /dev/null +++ b/test-projects/single_partition_model/expected-snapshot.json @@ -0,0 +1,53 @@ +{ + "name": "test-model", + "class_name": "Folder", + "properties": {}, + "children": [ + { + "name": "main", + "class_name": "Script", + "properties": { + "Source": { + "Type": "String", + "Value": "local other = require(script.Parent.other)\n\nprint(other)" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src/main.server.lua", + "project_definition": null + } + }, + { + "name": "other", + "class_name": "ModuleScript", + "properties": { + "Source": { + "Type": "String", + "Value": "return \"Hello, world!\"" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src/other.lua", + "project_definition": null + } + } + ], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src", + "project_definition": [ + "test-model", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "src" + } + ] + } +} \ No newline at end of file diff --git a/test-projects/test-model/src/main.server.lua b/test-projects/single_partition_model/src/main.server.lua similarity index 100% rename from test-projects/test-model/src/main.server.lua rename to test-projects/single_partition_model/src/main.server.lua diff --git a/test-projects/test-model/src/other.lua b/test-projects/single_partition_model/src/other.lua similarity index 100% rename from test-projects/test-model/src/other.lua rename to test-projects/single_partition_model/src/other.lua diff --git a/test-projects/transmute_partition/ReplicatedStorage/hello.lua b/test-projects/transmute_partition/ReplicatedStorage/hello.lua new file mode 100644 index 00000000..cf4cd25e --- /dev/null +++ b/test-projects/transmute_partition/ReplicatedStorage/hello.lua @@ -0,0 +1 @@ +-- ReplicatedStorage/hello.lua \ No newline at end of file diff --git a/test-projects/transmute_partition/default.project.json b/test-projects/transmute_partition/default.project.json new file mode 100644 index 00000000..d5f20f34 --- /dev/null +++ b/test-projects/transmute_partition/default.project.json @@ -0,0 +1,11 @@ +{ + "name": "transmute-partition", + "tree": { + "$className": "DataModel", + + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + "$path": "ReplicatedStorage" + } + } +} \ No newline at end of file diff --git a/test-projects/transmute_partition/expected-snapshot.json b/test-projects/transmute_partition/expected-snapshot.json new file mode 100644 index 00000000..a6c65c4c --- /dev/null +++ b/test-projects/transmute_partition/expected-snapshot.json @@ -0,0 +1,66 @@ +{ + "name": "transmute-partition", + "class_name": "DataModel", + "properties": {}, + "children": [ + { + "name": "ReplicatedStorage", + "class_name": "ReplicatedStorage", + "properties": {}, + "children": [ + { + "name": "hello", + "class_name": "ModuleScript", + "properties": { + "Source": { + "Type": "String", + "Value": "-- ReplicatedStorage/hello.lua" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "ReplicatedStorage/hello.lua", + "project_definition": null + } + } + ], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "ReplicatedStorage", + "project_definition": [ + "ReplicatedStorage", + { + "class_name": "ReplicatedStorage", + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "ReplicatedStorage" + } + ] + } + } + ], + "metadata": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "transmute-partition", + { + "class_name": "DataModel", + "children": { + "ReplicatedStorage": { + "class_name": "ReplicatedStorage", + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "ReplicatedStorage" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + } +} \ No newline at end of file From 4d3036d030011572404d1c741d350de3dfcfbd14 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Feb 2019 15:26:01 -0800 Subject: [PATCH 0429/1504] Add more design documentation into the codebase for high-level concepts --- server/src/rbx_session.rs | 3 +++ server/src/rbx_snapshot.rs | 3 +++ server/src/snapshot_reconciler.rs | 20 +++++++++++++++++++- server/src/web.rs | 3 +++ 4 files changed, 28 insertions(+), 1 deletion(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index c6e32375..50124916 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -41,6 +41,9 @@ pub struct MetadataPerInstance { pub project_definition: Option<(String, ProjectNode)>, } +/// Contains all of the state needed to update an `RbxTree` in real time using +/// the in-memory filesystem, as well as messaging to Rojo clients what +/// instances have actually updated at any point. pub struct RbxSession { tree: RbxTree, diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 4b08be4f..e8318d70 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -1,3 +1,6 @@ +//! Defines how Rojo transforms files into instances through the snapshot +//! system. + use std::{ borrow::Cow, collections::HashMap, diff --git a/server/src/snapshot_reconciler.rs b/server/src/snapshot_reconciler.rs index 0255bc8d..ff98aa16 100644 --- a/server/src/snapshot_reconciler.rs +++ b/server/src/snapshot_reconciler.rs @@ -1,3 +1,7 @@ +//! Defines the snapshot subsystem of Rojo, which defines a lightweight instance +//! representation (`RbxSnapshotInstance`) and a system to incrementally update +//! an `RbxTree` based on snapshots. + use std::{ borrow::Cow, cmp::Ordering, @@ -14,6 +18,8 @@ use crate::{ rbx_session::MetadataPerInstance, }; +/// Contains all of the IDs that were modified when the snapshot reconciler +/// applied an update. #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct InstanceChanges { pub added: HashSet, @@ -56,6 +62,8 @@ impl InstanceChanges { } } +/// A lightweight, hierarchical representation of an instance that can be +/// applied to the tree. #[derive(Debug, PartialEq, Serialize, Deserialize)] pub struct RbxSnapshotInstance<'a> { pub name: Cow<'a, str>, @@ -72,6 +80,11 @@ impl<'a> PartialOrd for RbxSnapshotInstance<'a> { } } +/// Generates an `RbxSnapshotInstance` from an existing `RbxTree` and an ID to +/// use as the root of the snapshot. +/// +/// This is used to transform instances created by rbx_xml and rbx_binary into +/// snapshots that can be applied to the tree to reduce instance churn. pub fn snapshot_from_tree(tree: &RbxTree, id: RbxId) -> Option> { let instance = tree.get_instance(id)?; @@ -93,6 +106,7 @@ pub fn snapshot_from_tree(tree: &RbxTree, id: RbxId) -> Option>, @@ -114,6 +128,8 @@ pub fn reify_root( tree } +/// Adds instances to a portion of the given `RbxTree`, used for when new +/// instances are created. pub fn reify_subtree( snapshot: &RbxSnapshotInstance, tree: &mut RbxTree, @@ -134,7 +150,7 @@ pub fn reify_subtree( } } -pub fn reify_metadata( +fn reify_metadata( snapshot: &RbxSnapshotInstance, instance_id: RbxId, instance_per_path: &mut PathMap>, @@ -155,6 +171,8 @@ pub fn reify_metadata( metadata_per_instance.insert(instance_id, snapshot.metadata.clone()); } +/// Updates existing instances in an existing `RbxTree`, potentially adding, +/// updating, or removing children and properties. pub fn reconcile_subtree( tree: &mut RbxTree, id: RbxId, diff --git a/server/src/web.rs b/server/src/web.rs index 1efd174b..e3d31c84 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -1,3 +1,6 @@ +//! Defines Rojo's web interface that all clients use to communicate with a +//! running live-sync session. + use std::{ borrow::Cow, collections::{HashMap, HashSet}, From be853ba2a7bcb66b4fa59f6a5712ef7a3880e1e7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Feb 2019 17:11:35 -0800 Subject: [PATCH 0430/1504] Improve docs, add internals guide --- docs/getting-started/creating-a-place.md | 4 +++ docs/internals/overview.md | 45 ++++++++++++++++++++++++ docs/migrating-to-epiphany.md | 2 ++ docs/sync-details.md | 11 +++--- mkdocs.yml | 2 ++ 5 files changed, 58 insertions(+), 6 deletions(-) create mode 100644 docs/internals/overview.md diff --git a/docs/getting-started/creating-a-place.md b/docs/getting-started/creating-a-place.md index 49acbd01..7ffcd418 100644 --- a/docs/getting-started/creating-a-place.md +++ b/docs/getting-started/creating-a-place.md @@ -1,3 +1,7 @@ +[TOC] + +## Creating the Rojo Project + To use Rojo to build a place, you'll need to create a new project file, which tells Rojo how your project is structured on-disk and in Roblox. Create a new folder, then run `rojo init` inside that folder to initialize an empty project. diff --git a/docs/internals/overview.md b/docs/internals/overview.md new file mode 100644 index 00000000..186a5e02 --- /dev/null +++ b/docs/internals/overview.md @@ -0,0 +1,45 @@ +This document aims to give a general overview of how Rojo works. It's intended for people who want to contribute to the project as well as anyone who's just curious how the tool works! + +[TOC] + +## CLI + +### RbxTree +Rojo uses a library named [`rbx_tree`](https://github.com/LPGhatguy/rbx-tree) as its implementation of the Roblox DOM. It serves as a common format for serialization to all the formats Rojo supports! + +Rojo uses two related libraries to deserialize instances from Roblox's file formats, `rbx_xml` and `rbx_binary`. + +### In-Memory Filesystem (IMFS) +Relevant source files: + +* [`server/src/imfs.rs`](https://github.com/LPGhatguy/rojo/blob/master/server/src/imfs.rs) +* [`server/src/fs_watcher.rs`](https://github.com/LPGhatguy/rojo/blob/master/server/src/fs_watcher.rs) + +Rojo keeps an in-memory copy of all files that it needs reasons about. This enables taking fast, stateless, tear-tree snapshots of files to turn them into instances. + +Keeping an in-memory copy of file contents will also enable Rojo to debounce changes that are caused by Rojo itself. This'll happen when two-way sync finally happens. + +### Snapshot Reconciler +Relevant source files: + +* [`server/src/snapshot_reconciler.rs`](https://github.com/LPGhatguy/rojo/blob/master/server/src/snapshot_reconciler.rs) +* [`server/src/rbx_snapshot.rs`](https://github.com/LPGhatguy/rojo/blob/master/server/src/rbx_snapshot.rs) +* [`server/src/rbx_session.rs`](https://github.com/LPGhatguy/rojo/blob/master/server/src/rbx_session.rs) + +To simplify incremental updates of instances, Rojo generates lightweight snapshots describing how files map to instances. This means that Rojo can treat file change events similarly to damage painting as opposed to trying to surgically update the correct instances. + +This approach reduces the number of desynchronization bugs, reduces the complexity of important pieces of the codebase, and makes writing plugins a lot easier. + +### HTTP API +Relevant source files: + +* [`server/src/web.rs`](https://github.com/LPGhatguy/rojo/blob/master/server/src/web.rs) + +The Rojo live-sync server and Roblox Studio plugin communicate via HTTP. + +Requests sent from the plugin to the server are regular HTTP requests. + +Messages sent from the server to the plugin are delivered via HTTP long-polling. This is an approach that uses long-lived HTTP requests that restart on timeout. It's largely been replaced by WebSockets, but Roblox doesn't have support for them. + +## Roblox Studio Plugin +TODO \ No newline at end of file diff --git a/docs/migrating-to-epiphany.md b/docs/migrating-to-epiphany.md index 598b1e5f..5adb36f9 100644 --- a/docs/migrating-to-epiphany.md +++ b/docs/migrating-to-epiphany.md @@ -1,5 +1,7 @@ Rojo underwent a large refactor during most of 2018 to enable a bunch of new features and lay groundwork for lots more in 2019. As such, Rojo **0.5.x** projects are not compatible with Rojo **0.4.x** projects. +[TOC] + ## Supporting Both 0.4.x and 0.5.x Rojo 0.5.x uses a different name for its project format. While 0.4.x used `rojo.json`, 0.5.x uses `default.project.json`, which allows them to coexist. diff --git a/docs/sync-details.md b/docs/sync-details.md index b655bb13..d260feb8 100644 --- a/docs/sync-details.md +++ b/docs/sync-details.md @@ -1,5 +1,7 @@ This page aims to describe how Rojo turns files on the filesystem into Roblox objects. +[TOC] + ## Overview | File Name | Instance Type | | -------------- | ------------------- | @@ -22,7 +24,7 @@ Some common cases you might hit are: * `MeshPart.MeshId` * `HttpService.HttpEnabled` -For a list of all property types that Rojo can reason about, both when live-syncing and when building place files, look at [rbx_tree's type coverage documentation](https://github.com/LPGhatguy/rbx-tree/tree/master/rbx_tree#coverage). +For a list of all property types that Rojo can reason about, both when live-syncing and when building place files, look at [rbx_tree's type coverage chart](https://github.com/LPGhatguy/rbx-tree#property-type-coverage). ## Folders Any directory on the filesystem will turn into a `Folder` instance unless it contains an 'init' script, described below. @@ -93,9 +95,6 @@ It would turn into instances in this shape: ## Binary and XML Models Rojo supports both binary (`.rbxm`) and XML (`.rbxmx`) models generated by Roblox Studio or another tool. -Not all property types are supported! +Not all property types are supported for all formats! -For a rundown of supported types, see: - -* [rbxm Type Coverage](https://github.com/LPGhatguy/rbx-tree/tree/master/rbx_binary#coverage) -* [rbxmx Type Coverage](https://github.com/LPGhatguy/rbx-tree/tree/master/rbx_xml#coverage) \ No newline at end of file +For a rundown of supported types, check out [rbx_tree's type coverage chart](https://github.com/LPGhatguy/rbx-tree#property-type-coverage). \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index e07ab8bc..6b657f6d 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -16,6 +16,8 @@ nav: - Creating a Place with Rojo: getting-started/creating-a-place.md - Sync Details: sync-details.md - Migrating from 0.4.x to 0.5.x: migrating-to-epiphany.md + - Rojo Internals: + - Internals Overview: internals/overview.md extra_css: - extra.css From 80154bbf9f32e296834b8eaf7a4e61b3caf7114c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Feb 2019 13:52:57 -0800 Subject: [PATCH 0431/1504] Build with static CRT on Windows, fixes #89. --- .cargo/config | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .cargo/config diff --git a/.cargo/config b/.cargo/config new file mode 100644 index 00000000..0beee4e0 --- /dev/null +++ b/.cargo/config @@ -0,0 +1,2 @@ +[target.x86_64-pc-windows-msvc] +rustflags = ["-Ctarget-feature=+crt-static"] \ No newline at end of file From d86e655ad29c52c0219e5c19ad3a226fceb32200 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Feb 2019 14:07:21 -0800 Subject: [PATCH 0432/1504] Update CHANGELOG --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8d4472a..d855885c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Rojo Changelog ## [Unreleased] +* Added support for nested partitions ([#102](https://github.com/LPGhatguy/rojo/issues/102)) +* Added support for 'transmuting' partitions ([#112](https://github.com/LPGhatguy/rojo/issues/112)) +* Added support for aliasing filesystem paths ([#105](https://github.com/LPGhatguy/rojo/issues/105)) +* Changed Windows builds to statically link the CRT ([#89](https://github.com/LPGhatguy/rojo/issues/89)) ## [0.5.0 Alpha 3](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.3) (February 1, 2019) * Changed default project file name from `roblox-project.json` to `default.project.json` ([#120](https://github.com/LPGhatguy/rojo/pull/120)) From 5e4c1a8359a814f8af5ad3025a69b73d593a80dd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Feb 2019 15:41:17 -0800 Subject: [PATCH 0433/1504] Flatten out docs --- docs/{getting-started => }/creating-a-place.md | 0 docs/index.md | 2 +- docs/{getting-started => }/installation.md | 0 docs/project-format.md | 1 + docs/why-rojo.md | 17 ++++++++++------- mkdocs.yml | 8 ++++---- 6 files changed, 16 insertions(+), 12 deletions(-) rename docs/{getting-started => }/creating-a-place.md (100%) rename docs/{getting-started => }/installation.md (100%) create mode 100644 docs/project-format.md diff --git a/docs/getting-started/creating-a-place.md b/docs/creating-a-place.md similarity index 100% rename from docs/getting-started/creating-a-place.md rename to docs/creating-a-place.md diff --git a/docs/index.md b/docs/index.md index 54735204..e725b55d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,4 +1,4 @@ -This is the documentation home for Rojo. +This is the documentation home for Rojo 0.5.x. Available versions of these docs: diff --git a/docs/getting-started/installation.md b/docs/installation.md similarity index 100% rename from docs/getting-started/installation.md rename to docs/installation.md diff --git a/docs/project-format.md b/docs/project-format.md new file mode 100644 index 00000000..6d3f6659 --- /dev/null +++ b/docs/project-format.md @@ -0,0 +1 @@ +WIP \ No newline at end of file diff --git a/docs/why-rojo.md b/docs/why-rojo.md index f4ecae06..247dad7b 100644 --- a/docs/why-rojo.md +++ b/docs/why-rojo.md @@ -1,16 +1,19 @@ There are a number of existing plugins for Roblox that move code from the filesystem into Roblox. -Besides Rojo, there is: +Besides Rojo, you might consider: -* [Studio Bridge](https://github.com/vocksel/studio-bridge) by [Vocksel](https://github.com/vocksel) -* [RbxRefresh](https://github.com/osyrisrblx/RbxRefresh) by [Osyris](https://github.com/osyrisrblx) -* [RbxSync](https://github.com/evaera/RbxSync) by [evaera](https://github.com/evaera) -* [CodeSync](https://github.com/MemoryPenguin/CodeSync) and [rbx-exteditor](https://github.com/MemoryPenguin/rbx-exteditor) by [MemoryPenguin](https://github.com/MemoryPenguin) -* [rbxmk](https://github.com/anaminus/rbxmk) by [Anaminus](https://github.com/anaminus) +* [rbxmk by Anaminus](https://github.com/anaminus/rbxmk) +* [Rofresh by Osyris](https://github.com/osyrisrblx/rofresh) +* [RbxRefresh by Osyris](https://github.com/osyrisrblx/RbxRefresh) +* [Studio Bridge by Vocksel](https://github.com/vocksel/studio-bridge) +* [Elixir by Vocksel](https://github.com/vocksel/elixir) +* [RbxSync by evaera](https://github.com/evaera/RbxSync) +* [CodeSync by MemoryPenguin](https://github.com/MemoryPenguin/CodeSync) +* [rbx-exteditor by MemoryPenguin](https://github.com/MemoryPenguin/rbx-exteditor) So why did I build Rojo? -Each of these tools solves what is essentially the same problem from a few different angles. The goal of Rojo is to take all of the lessons and ideas learned from these projects and build a tool that can solve the problem for good. +Each of these tools solves what is essentially the same problem from a few different angles. The goal of Rojo is to take all of the lessons and ideas learned from these projects and build a tool that can solve this problem for good. Additionally: diff --git a/mkdocs.yml b/mkdocs.yml index 6b657f6d..2f27e470 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -11,11 +11,11 @@ theme: nav: - Home: index.md - Why Rojo?: why-rojo.md - - Getting Started: - - Installation: getting-started/installation.md - - Creating a Place with Rojo: getting-started/creating-a-place.md - - Sync Details: sync-details.md + - Installation: installation.md + - Creating a Place with Rojo: creating-a-place.md - Migrating from 0.4.x to 0.5.x: migrating-to-epiphany.md + - Project Format: project-format.md + - Sync Details: sync-details.md - Rojo Internals: - Internals Overview: internals/overview.md From d5f3e25bea17d809067d52e8173a2ddbf8855ee2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Feb 2019 18:03:46 -0800 Subject: [PATCH 0434/1504] New docs --- docs/images/plugins-folder-in-studio.png | Bin 0 -> 19363 bytes docs/installation.md | 46 ++++++++--- docs/project-format.md | 101 ++++++++++++++++++++++- docs/sync-details.md | 21 ++--- 4 files changed, 139 insertions(+), 29 deletions(-) create mode 100644 docs/images/plugins-folder-in-studio.png diff --git a/docs/images/plugins-folder-in-studio.png b/docs/images/plugins-folder-in-studio.png new file mode 100644 index 0000000000000000000000000000000000000000..742e5a6aaf5ec0200f94f99fa26a09bfb04cb77f GIT binary patch literal 19363 zcmcHgWmH^omp%#-Ja`~La1AcO-GT>qDBRsGI0S;byE_zKxFitVt#AlVaCey^dAtAJ zcV@oayY5+wqD~$8$=>_f9;PTSiHd}e1O)|!DlH|Z3sx}7s(GU)D{?^XcO}~Aq3FJpi7jaD&6?-!m zcS9#rC`l(%Q#)r1dlx-5M93pD_|jq`s$cbvvfieu_O{#%`r4l_dpYMExTmCUS=r@N z;fMGn5ShUnYIaBG($vw?WFQXYqkKZ_Db6K@KCb+t>VS&>?gQyN6N6ZBH<9-!&HhMi z(@#&gS=^4_X3`^H4~8t@q9lorn3bHw>ybRBel%Ze%+t~$GIQUg0)9LwkYvu#_U>(% ztLpG8V@&z`P$Yx6`qAEG0py*}!^1+i$_vMC$J+aL@0Fn5 z#%_~;2N?iFAsKD5yY)-;K!0o=D(=~IJvc}3It;_cbj@#Ls*8d9S*X78+3ppx>KN zrq4W8J&U$9W~qwk<4l{N(1kmLDf7DxE9ybAS2CJLvw-ZdWq`~%ElMd{ejb8E=&1YQA@Z^^ocPvY^o#v5} z>DAP9dysej0YHZE5O(KmjHbTFVyMB<>nrj61&%`PRlaP?&sixPG{u$Um=^)oY1gu|}0Y9LeTDZ+J8 z>$Ev$ihCZ97~A_Juv>`UkA06Xv+tBH^DwtYB%#ax$1lVlUhiN zL5-1-pSfMBPMgP7exy6KBVCb(tGi!2LWOM6p4J#xtTpEB7`E7$LCK3HkN3O_sY>k= z_6GGht6ZlQOQITR6Ijz> zr**|})KLw*6_>_CH8B`#VLkq2I9jJsZb{xIy7(&|)*hDf7BZYRc2DXQvW}Nh@$4*I zPgmtSlO5rg>cLrk9Zu}WI1(Y#b|`DMvc`CH8ko`qrP<_a zcFdZ)J#@Y|2f{V=)a@Beoy~e~Zrt4HvQnf!nF7eNRrJu`v34&;X8<0!`xr_A5oI-9 z5{}3PKFZdRFr#djv!-ZC9Er63(*-f*roxP`y$x%DE zX`-fpNH_KB?DO3tOk;TPAA$xmo4}nzp30-%-PMJju>xVcq2#P|1Xc02Sj`?AE-sAm z@ThRR99H9@pWHsTM2^Xzn|u^q8dZunMK9@3tK&Gnj~&!QK?W~YeflpRlYc5M zQkIYs?(oYvUO`PuF+u_8+IIb1q#^5d^)kx%JSQ3R>~@Z?&7{RZ@ejF?t->n)-VC|D z_rt&E@U&V9{-1o)I8X=Xg1g8NzmX!6GqTLKqKROL6@6nY8>62rx1Q7Y6Ci*VDTGqC z{zf_lCq)EX{YBJDt`PCxIpp&cqBTfET>>DV?WN^b0$#^5RaEtx2niFpA~1N;(aX!r z_g4qQQVj5;D|`m(j&@CXtnwIZhEl+{-4S$^;1lBL{YHa@jOvbhYL=g4gM)vjiexmc zR;qN{qKWw6ZH}@{x4YrTRvFnJ@`@^&js$AA17mg=v>1nA$(Wg|eV`O&)k#Ay17F9N z(gcPucqkYTVq|wePeUWgtZNjz#ScnDsWI{5%%WO7-OZ(JU>~-+9yD4`7qd|_fP%^0 z4#23Ws}4P=tb+taVCDMVLtp!sL50rducsqi88?}+-=U#CKCAq%VI+WA@rMQA#zd0< z%9p2tQoGMUL%vlZLd6;aF1zJCQH0ELugkrF9L2iB!$XNE{J}%+GW{;!2pqw=%h zD{U11ExpLlTHUA_fSy7?PB6fa5*d!vcBWO~XZbflR+|VAkyecZwz;85P9y8PkC#ZE znQ++1lK33)-6ed#|Kyn%2CRRd<|^Dn4e>8RhhKER)-JIniI}zn#TOn8e80bph$}x^ z)K$i7&quNzT!mFUc*mTnYU5>SM@@0|{T=_WS_#Hlc?!LGGhk(%*07lfFj>z$Xm5f* z*_vEj)ez+SvROJxg~O!2!#vL|fvnX__F;(5zcZYTMHOf|ocv5z0Ta;gfsajg=NSk^ zOT_19v)E9^urEw=xwpM0@AEtp$efva|43cIb?D`OBYEIXtljCmd(=a<%3`Iw*4D>v z2mY*nN_sS#Zo7;uiS*WlpfwJy>`gGvCtXd%$@Mtl2d~Uqm))a0e3)r*rG-D*bnV-k z_--c}ktMb{aTGpCRBtk#!$REo^z<*!_z&y;fEAPTP|(d*&qC zhox1lBGc`GZwA9i#D#5uB`#}|P;Po9#oR`hAT<~_JVcn2V{ZXfyAMT~okiW+(M5)m z%(CxR?osE6Y@H&5)e!8M@OY3VqZ1Q|MsjXv79%w=kCdoTBp021 zhy`HL<|E|*Z*syG4~tOSlI|)vew?-1E;V8R5XHAFi-^{^ipsh&R5lsQ$%hxbJO-B&a)Ur;d94Q1Lj{le!Qr z7GBzI<+DekL=sU3{#GoP@mcZvr_CQ(2?^6xx_qUTiaLc9a|dzF+_@1(rD%*cE3K}> z$&7q%hcwxxyE{95-kDW1_ZQVN3Vt4Cdx2QDWhfg_E+3F`HM{=!CCm~A<%6AuIbzGs z4AtKH$TS^;CBEJ2+Z`$@01FG`5x=_c?u|;-m<^;BG{}6B(!{^sFR~@cTR4Xz?BuHx zP;pg57|T{1sG9cfGi^lwIRnVcwpwzT$5&%v)8gzdT8(48Tx4L_WB+W?c;R68eI{M% zoth>vCMV)nQy2t)bufpU!=aM%RuU;uld$b<`asv5?4lI$?MzPE?)ElWtyaAm>v4qg z0h_)qukZCz)JKx_k~*N57Vn7Sfo)xSpbM|IwO3Pk7;0vTV=UQ59c+TU;|2#o4JS6* z>PqjqqCp`5lV>b3w&vz!B|4k}==B8$?WcN$w3a2sbq22}gl?YOCfQ-|%xw^t2@@0(8n6AiMO$QJ>_nS@4 zC>5S+8MM?C_W=2d`^Cfs}6T(bcy8S|Y z`r(xi#7i@+4-Q)WQ7#(R#gr2~C*uyZM4u`&GmsE+j*UEMRE}m*GHJ;SE$1gAFqDW* zj*H}h9ufPDen6O}?B7ZEpGbDps&{3itVTD^m!l|Z?;6>>kO5i!3m3NTAe?d=@86Lm zAX98GQyGU64`n4d3FX)A$X#emZxL8ec(v8-X#eUB%N{%I(r(ldDI!Qc=dC`-@MY~f zOS5b96H0&@0a~P&%hQo)KUZ1oc+fEQZ+KP?!Ah^Dk5sD$rZfSL3kRdHLF|O#u^56Y zZ^NeP?BD_Ub!mB^-= z&L}TG+A@eXt;_%#XpGPCn$>&J|AVg2j~SscAFII_mZ7y5dzJq3qQmv|^``t}K>+%P zht33Creq(d>&LWlX3`p0`w3>Lw+A+iH_Na^>7?=G{(us`|B{<$)23ReC0- zs(dS-GWHGQ!BP&iQ6gTKA9*}G)U6_$eNkiqJUl!iNPM+rSB)Lig3pf|lhgX^U!#5m z>-L+rXa<#nVU@HXXcUAy>vp^>Z3Xn-;N1Of!i1dZtSJlI?sl zx;)|YVMbt%x5xgW2kh#ihiq~L+>;tQISeU?3X!?|X?(k@Jl~3F+GO(5Y(n$_eq^<% z^RDppOwGR2uhQYn3LE1O?3u3re~b({46&VmYY+fMt5>Lhlx>y45Hol+DUelwwFBj_ zoJz9V3CEbQ@6eSm%Nd+Lz`o*oNve4ll!=w(g@vc(g=@f$`w#X$0wW=OvM8;IAoM;RO3YV87LV;+@TDk zlop3k2*wi)PhKW@xs{~3JPtXDtRhsqo)NI_zZQNU#>!`dN&H>K)VQ33d&RsGh$6dV zNvhkB&tE@~15zN>xHhQ#m z%Gn+2mKav-a~upnA_3}G_#ms9N|g>X+aMF8&j#D7L4ffbA$=qcg#Vh+o(x(%ibH%= zlB=!D=={LW$H^NU-&PkW`FSbXI0I^aq>>?cC2IqEm;^k0sl*jnDpx+JQl$cT*lO#! z<19XR+m(BXJU`pTEixq04{#=vL&cIY89H)i)RJGQTe>YK+B@zy1D-j3UGHkB1?}fI z6za@M=kL$!-j1iBYv0GfkDi-=6bFW^7I%_G&^uLbzuXnri|;&rWW5^Kzxi+`)*;bC z-X!0X997rWxW`>OI(p+y_^HjO3lHcOZMj&CUR7O?(PaIu_eP(nt= z!?N?ZblwhWxLDe#2)1fsoMtS*9A*7jXJXU3ss+B=dsa=N61lQ3-~?Gw*G|` zM8NymD4aO#-=b9yri@AY8G^+Y;uf7zBR{NWv-xY|fr-4JPFEiw2{V>9)D; zj%6VuA*oktl8FHj!UjISc`s^MxV5{B;O$7Hf^5w`Ht2JxxTLnm3mhG)&WO^d7%qaB zr6_Y1?p|pjoy}qBIQbRtHQvQiZnJrMt|mJCQkUEQbv4cWJ~MmeVB}YJNWZI0FU47q z*6reIJu|rcy|8!2Os-%bjgoz1I6hfX--dR=`B+xflP&B)Soz}8&kxIsuIDiP zYYwBsbmM?4%A->}4-YoYLW84AH(jphe6|m=^5;GiCZRGw5>GZ( zH?^R!?Qb#r97Az(K_U(yCQW1n@*4(b6800}I_ks9%0ni1fqS>DUmBBH)CCc%VarYB z-c#x4b6?02Uf!*E@$%ZKS&s6e5;WdojZM4S4@jU&ffNraEBBv>m(@e~CR%s*RyV;r zE4<%9cuIa{6}&$tQ~G2 z<`$8bWFh$Fz>I)FLeo>$styFO(&EspwK!|wl~LM|17#r?ah|Z;l#6%{)8_mfr=E3^ zT!t;9WA*gtHQ7ZHBY)3^b@)yp%RbpX!{(#q#8+XEubuT)^+SQNx`YHHJxS-KO#)}r z02L-_g=frq#N45QRfn&=$uH+a0E%Cu_qBE0N=ZJ64_;Oyr_({J1b9fqpX)_2KH~99p*D-s<)?5yDs;R;W0S;a3LIDCV`yyW3tX!DtpRmii@Z(;4;_iO`5 zBIJ9K7UJcj!v54<9AG*QieR#Qy834GK6y5tYF$ZKaof!ZBLx7Xc1TiSzJL-|m+>R$ zD^EJRU_QKvkbWaVLGO-)y|Re~xE8 zEKyApD8KytdyQcCI@SYQyd7fC+qjIEOlnovHpQN3sV`QYurDY&<$``&p^`KbhRJ`; z?yzV!*V0=05dz@Tn)Qm-yx(|G21*L{XV=DjZS+1Sh>KT91t@sLy**ut$+DSm7u^JR z;BUKhS&pRZ8PBng9ffJoN#V8Lx;*%P2lAp?&fZmVa;>eIPu(~AoSSa0LImxaQm6eX zlhQ(rb2q9BXXqe-)#Sf+EuSBXFvYRGb0eI-b5*G3aB6uEp()As#MxK;WSr#4!&kaV zCgVOOMLta8q5zkK`$^L|G4b!NarbiTftdKt!ZcVYhwPxSz}pzgKtB@{b8CxFzqI>& zermNl#msTWssG!gU_gw%?(;xK(Zw1Ke}ssHrkI&AmTPU)-yP> zO$}s_**Sbj#T?@OuU=$!Y(=1XJ7$1E53x_g-4D37$Ku+zKEbr~^i2-~-~AY0ZoS{1 zx8JS|Oq2|tXsbonKdjeJZp0My5DSH|T}E~E4W2(9?MDZWAhaIY`C%Yf<7{-5qP~^% z2<08Wgr%ou2SMDz#zY+ih$}_Uz(C03WYXpPZ+a+P; z>pzP`^PIH#deQnjAZN+f>rYdCe!m^<+T6iLD=}`08>8-Ii}&u)_S#lTibA9qRkmlo zv{@;~DcxTk_PK=+!%PZv(P2(lnFoF&Bo>VGO^6>It~n$HxBFEbv8DQ&wy3qrKs6rK zDLd7)ZM!XXapT@gcgMXP2keR4%F@E1PECAWz4uzRy+%@LwN>65$lIs@m)OydUmQSg zAjgVfQ&C6d3g796?7N0NhpoNcNpzuzn6^d z`RI}R4_fybA1n8X;79g(JVBA3{z+Kr0Qci%tuIwcy%D%KM@vl^*lD}DGAT@TJoZvR zwqV6A5yw%EIqw$pAA?-?zHTmJ3%%WYciC~yD?`_Aw0>gMk1-#a~~^^t9oN;+TP02q!f5u;MguU`-QXd@gcBAiZ*^qY!Dy_K?;wFrohb) zg;EvzeQ`l~_Rg~8V11}W@j`cvB2(=l@ zP@K6}VD{#-Un&~y9~Qc2J)iBB@}RV$|7}`FVE@+`ek)G={!qmX;a=~y@^tCq`?jgO zSiv-T9Btfy$@S&K$mq7d>|=4RmfB0=LW^aDiPYvPdQ}1$>P!;E%1az3>%10|Kq2kn z)`ZXkTbVk#gxf?kJ}y6}ySIf5 zyU@sHh~X0r*xlON>(UT#+LEFje&e4xZ1s3kGnr^J6Sy^dUp2?C$R_ z9}Nj_5nYHe2oWTCP~ZB8a+L3)P|DOQJR3xIy89Rscv5^LS7DwsKSV!v{x$hJ`_bQ{d!_iJbi_x;KuFh)KnzB;qAlt%kI$&=u#V8}H{{^4+E3MQ1 zg~ez(hv{^{q>um45L|aLo0XPy`Z%eE;fbO^;zefdm;`(f!6k9q{oM_De^=!3Ee)^b zb_*}p)@R4I<)>zbpM&LkFkcQI4RqJa2((>Ug-Vj9ZN+Zl#>4fGo#5!HwLrvdW+Of5 zLN*VLb;JUmQnYCPRbVK&JP~$!K8M(L0140TxzmVx-|&A!bvQqbLu0gr*SZu@l>9pQ z7)k!}YlOvRr-h5l);OwS@fSZnq?yIEJ*4nK2pkV>{~(*C(w(q8v(d>c5zmM24inQ& z>W$-dRYqmi1{$8jSPZ9{-DIDB>F5KRZd2}Y*f9cRek5aSU2B(eVD?u?k?p#6cG@YikUTD>Uaf?DfArX~ z|Ehsx9#WT38ToELfZ81o^jMFfURRxrZ!NxG!&R5bTnB>?R^~cc>*SFH4aL)>ra{$q z20txjMHKrVWYOWCe0nUC-xd0EdX-{3o;CQLGm!a){n^N?N5v1=_7Ik?_S7~K1R!Z^ zPmA;lGe8`*n6KxO2yT*YnQ%P%%k+Gq2!P__rR_%g| z*za7|jqM4j`y4GwFP{JqE73C&FnO-vKGY0TnRyZpNa-U37lN_HXwGw+WE^W9MlPxK-o^^6GXuXG;FisRfQsv>}ljP@@6sO@G z5?vIpeSb!zWNnDvp~oBN2L;?sE$no`GrxxzAZvhNY`+m-56|WDfdjAngB$UZ_V;O> z(L^jIorDX1RGzfd8b_Wu(%1) zwHzupf3zGuU^jO8c(!%I***j^U#Y(teP>iDYxaQ# zB>31NG(d^2C;_p5F_;m=@LQ1sr9?+aM?S~EDOymLJ9E~lGP&Sm66-u-!W@UmC*`Sp z>|jAXUMN2pM|qU?jo(x|=yo+VzFV5lf@hAEqYSD_gxLN3wJdcv><{^)E%suoi?}OS zEHXJaxYtRBCxoGb_sI;jiB7YeZn0Sn#j^7=DMLZ_aLg?I$KG2OJvco=!lOz4*yCh~ zk7RYt@i(DaATg#scR1@4@>(0mi|uvtwQdCIsctaSA6^$r2)?Xd95x|ROl)TFI@A#J zpY*8f1`mOW47OtdGB(>CvTmEG#c?ydq+~;)ALAh&lMzbc2WP%#nFp*B72tjOvI0a) zl-cF_LmbFFeY8?m`FRW*JTCw6h=e9##Oz3ipN#@+)lj)>oYL1UD@$J?+Z0&AF&4e4 z!NNmWcWPo6<7N6JHkpLEI~RqZ1$BM>y!Q*2Jc3IM%^OFziT>V2X)BE}ZtjaomGS`# z{jyJXOSI3=;m{JM0XuK$z7RHjar4gZLeKLE(-?=cMy>WPU)=&Xm{Qi6rlru5-nHEy z*3kj=5!N&1+687rkCj?&f|Yg!%f}SiKgkHzAs+aw11?ZCM8vM_eG2NAPeUvrN~6he$5_Ueo$-HS~y#L zvF4+>jbCRv$xmE9eMV5153l?ztJBlf75?tV*P{#iIZd9ya?p=!0v#-B`9x(x|L{9h zrk0TZB{tIE`BnMf#z24bJbUVJdV&-E)4&Qbd9_}bxCcR-KGtr9sfC3d0kpKB%;8XY zF_zgAy@SFQ0P?KTn-Ve^spvX4e*vje|M@{rIz=2Q~t0 zHL#tFl~;1cm*cL1g6NOER3qF9qLa?8QHhR$BF;hLMdXpR0upUH_6L`|In51_4!)PpqfCm zWJ3P1p;t<)Tn2xU+rT%~B{VR!1^;_h31tPd(yNA)ZF}1lr3GD~WeRaKyZSDT> zc)Io^?>OfsXTh)O)o4j@L-^Alup}r5-s;OZ$-K#nbXZ(@HfUN`P`~j-f_S^>056}5 zJxKER;pT){ZBclKM{0#Drs|Fqt%V9y^+A~u9b2}$;1f0%6t149c2ZLsgCX3XSF#;D z377XGj9Sf>f6w`pnQ?{{rgx&?-sn53RX*rXy>6WAJv@Xkvi$aK90w}I{_%ZSTGNAg z|3}vuXT*ynpmy2$4*H=J-2g0Sls0p%t;wsn%^Y!e!X(ZEwd=IgZjJe+*`Az7q;o1h zME?x*?MC7(D(_gX;7zu5(UeTnoW~6+h*1x0jcSeYZaiX4Fv(=QJX64Dx2C30Jb;KG z(Y09P)uwTi+`>fboDXYv*J5RV={DCjG4rO~-+++o{!Co_fkAILw)4&i9*5P8{~H*) z&bu9mg*1SIfPJAMfcDh0&22=#`QP9#oyD(8`8I~Uc!O>xW1;H0H?zcq2eoh*Lfxrh zGT$~pDUleykmJBLuYl;VlCT6_5W9x8qnz50w{^h`+;P)S#9IABB+sWI`p@SnUC&q5 zkmLiv<-@$~R(-b}{tc$5_u zOLfXpt20LidfsCv=y#vqre~C{N=d+7*He+D+({2gx7zu0QT}}uj@3mCn)EZN%RU&eg z4sygf5!yWAu$mn$*SolXjr>Eh`gIs3&Nx>P)1DACHZ(LeKAz&40c!y(Hz*;1C=SHp zT!`ZO8`CTNOiY(O@&Qh&R~RCurU|W(0Fy}f8CLoczo96H&+3Rg(FUq(d(DLI_YkQW zm0!C{2_7Hgen9-WtJ|~9mwwblNVP$C!}R1^}%Zj1Wb+Fy#@lk!|}a|?pl z4?hRJCNkp%(c8lqN^d8`OYY@Y=523PLfu-d-^tH5$$GE6;59>R_y+3r<})gVYz8$h zGR2jbyHx)fUSp|$s$>H}==P`IW4|A%VpQM{NO1onw9xZej5xW0cy-rv-7r&vW46=X zcFM36$Z9@C91pKr{U}7}F;6NiLRAONwLF-R(`p9MaF2aPKC^{vgvOr+1t|)~y+{hw zT|D|Z=_=7ge)bzI)q)z(XAI0OESmA|he9cb|JRr7iwONk^2CsJ2%Uw+RjZe~Qp;v| z8A#{dneRWadW%*tMLBylLe$JeZ%M}XO0aN_^Z_4QX5i^>50dM4cT@SMIAAM^?V5ex zKne3DL3u5+Km;zQnJ)II>jH z?&qwAKBH4$LijM*YEbalItr?Q1Qf#FP?8DBlsYgll|h#b5hOqLS?PdMj`KY+#%8-V zHG1mZ^U-wUC1HoBFxdmvW>yG4eA%(jn#_bf&CTz-5Ig+(V(AR+a)LE~9N5at*xALT zyNg{JNG6Jo4RfQd0<70+N!T>UsNNz4$h4;ukDHt4GR7gO(?I z_MVjNBkh`&%^y6d8SbT8ZJi86A1X7$6%Sa9`=s)AZoLt{Vsy4yp>Df;p`z6J!t5u- zg#0NEJH#RRB%!neS~#{S4OK5ECFG?6(=Y*&X6-Jx{iEQANKH6v<<$6uLzUB%*$?Ib;I!{4Bj{;2~*r3zLBTk=v%wdS=>9rNUuo$8Sk0@2rTJ z3cxI!aWiEJcWGX`-+lap**26HD_-#KA^L<8h*tfswZ2ynu9p7rJN}fU1 z$@V_TPh_1El}hugx4XttZbf)l@A|^kV3*%$=F~EYcI%~Se45FFgHkE~#2Nek7UOG% ztK>~QmX{y$NgE<#RtPt9fB<{4k5#C3K4vop{M%?~dTKI|9zvw`cQ{mK?hv>3*+qwM zN7LP1GkUrj|KgD~Ta_B0`mRi@CpA+lOA&WbyLAVql|@IC_UyhlP^#3`1RgOg?R9y>?AB zNWRRl-u(&Y3;!F(l#_9%_r@x{Sls!!1(BqUfQ)xZrQ22_k|h8S+@`1vhk=KDqt~hc zOoKs74dgu*XODq{K-srLHP%IHTP^3G>zr7TZA01TTqDGprXt~f%O5IPJovLfb6_sz zEB{H(jqqYsuvReK;+9ApPife7fIfmc#YIi;tPOKorcL*vOF>nJoEi+upr1+`fcqBB2plGf33tw6;YY@!#-CZI0=%_>UmhnKn0sCv*k%S#r? zbyuwr8G0JSFP#gz;_!Np-S4VM=;d$U)Xw5Z4MY@Tf^@K5+^lG0FveBwGO(X^aQ?=; zpk$(T5s~*72W3W1RO3pS@p0a{uaiD|S?+9aRx{fU!vMMGj(E>>Ms(zeVF|vUYr{sq zXOra4-AK;O@B+J0rlRNxXS^+tNxUSHBqd|P2NMa0azrrn;HKzI3Lsl;6K*QMF<|c= z8rC@iv|VSQ44HRGjv`EdFXTmTAHC1doTWk$*`_z^v;C3~G};od&;iCp;y%VV@zfFQ z0sbZ~H>}@ZJqW+a`pm^X;h+B2{2@E*JXR~^0UxRzL&f0jc-8tu5<&>=GV9w`_hb4_^NNk%$sqM1x=R=Zb@7 zV!BFj`sPkgr`Qp!k5@&A;YV`VF8WQJB!sXnjwV=UG39bg`BV2(ZC5S|%)b^f-*JA# zce({gYe1ujjea`#xgSRC;;1m&pjsOvLvQ+CMSx`_6dZ~p3*C^fc+hPDxHCP*ev1iV zW$_D{){!{pew8Q>)hg$h7?RcmPV$Y>Jo*DY%{NV%ts2;qcJ(7yV2wJ$5a5#?0cYyg=5P=`PZ#kjsU2cF zR}34iiRAs4(Ebr$Ki2u~q8W9*+o@&Er0&)p!^_~EbdJ+}FO*T#Ll9nmAIHe6Yy<~FFduDCMs3E#n1 zNVudHPCOtfp&5`-pwdwfrC>-L%09}LV^mHHN01Rm*=amXsszFT*1DOd*Q-=S)N!!M z`I=xbtEd)Z{e?kj2A-qOP}poKAuTfu8t=;#C5cT47!@QM&!AOcN4xC~)OXT#JunXY z41H1s%H!s7llD_w>HD{jv(u(N41wjGCSulL6y6o%Ueu6CvFk2d z9RRJ`2w{XTa5VYK05cUxYT~YTL(c}D7@B&0l9OShtOw|E8>b=Ked;W-N)>ph&hJf;=!6IQDG23+acARDkopM~N(MH3OH z;5+QV_+JI!MVm6F(K1K3a(qYU425QzeP<<>*P5oc5ZFvni)qnCt@KJBU~2J(XZrG? z6_^}IoXDc2tljjrcUWcH>5}qyR3HwBI4X`CCu!|7XqCC0WdY4vhs?8fO;93c^%p)O zF9!mtca672FG_iATA`YH*q9@kw62KEuoZ*EOR^5OEOZBUP?WT)?^|^4TJ<23fF>>d z%CUXi#Y}UGLOIL$Tn*HRY1*Lq_LgOi=M-i%bT!8M)<1zCxr*#8_E4J}PSO!mJg9%d zzLL}*5E8?=`5~Lwk&J;cvSRx8-$c1`m<$t6^3r?`JF&R8$%yc0>R%n?1=KvzZB$8x zVFYA>NeMVsqdOYyLs0vaTOwZpA0$hD{$t=McP3@)&(saC_ovP9emB@I3#^kmmua9SSc&T}mb+ zR%CP#!|B%yKC*hAuNK3Yn$06vtNqq0?>O~r84~y=9R;hi0H)?rv)YR14+u$YC z-nIJyYlUkK-7VwzdzTVyhRIb$^N3O!P9##MLjLEUuhJhS{tKLRGbI0}c7`_;eSIwm z>8})Y$A%11vq`+^{t$YiyA^MFC%5yyz%>W=@Ss4sMhP~}d3wzFbSZ zkd%0{8uj1w--;5`W*&j`M4D4(3$3`w?n4`H!T24d- zieZj6?`x?SL>)l(oytCpjZeB#&Gd$*{K3Uu7WN5J`ZZ47+}gvSe9RT~Fu*sP$%Sw- ze~fXLRk7$UDjXRgcDtbU#C=}v%QhLM$TIMoQM-_~A3!1BQU;&q{GGk#0Y+XQ$*2;l35~?K2Y!{?Oi+T*|&?5Q2&LNtw z_XubDvz30RYelgCYT~|zjEmzq;+|TRgAsxFq4c#C#RQ2f$L_T950rE=u9vV&h{qm8 zy$(+|>6-K@38$j_tc-o`9Ayr&@_c}{Q&f4fSlIuMaXPtj)5<;%RKEwQ6Iq8b9S`~+ z&@hBy0y)r)6zbN~;F3RV#kB4xfuPMMP+IO33Yj%|XqByNjpjXLEtzB#ne7|Qiank= zYMW=$+eov{zG5=v{DjoR&Q*SMnCRjx{qb6UNr~c7>it@N85z*L>L0B=!ccsK{M=-P zXd#!@38_mAe=k`g@x%3faSvk1wYjuu+j-bWKE-+_&7Q^JSOC)${J;g~W-l*{8T4+bi)W0V*P$G~!CeXVM!g*1xCXkIM(PN#+&RKy;7A zjzrab|LTy)(32F*BB6s=FqUcYAs5u)7Rgj~4@4^Yzt)Rl zty1>;nhKj>YVu$gf_Eyo4cc{NQC@@cY+Gay>0*V{hsu6UkhOYRfu=9%p5bMGtwb1! z4S`6)!2iWaxr#43+p7La z3BKkBn)G={<)C!}cFKkAUTsn2O4_AZAF7`v$@I^?(40oGY_j3((BSaeODtTga#6GBMT_DzDR2Eq!sN9o8B@N zTvMJ#ZE_HTvohrmD2KZ_Z$?UY(q(l%nFesWX!mLsdL#UB4WJf5sM^j?cZ^fzSyB__ zcpK3=mYvQt=Sy#KAeCavN!##8t$CzAdm#Mbh>hGpPuwFT*e9vtlO~U4CHV0AUHu4i zTAYPNUUKPvsw=%r;MhD($rggf9P&MTPSKzNE9Ey^ZRHmddZwZ5d zucxpYg(~e7wMBW~oW>_Z;pq`BA5!0052jJXhjwaO=Og?0GCXa3h#_9+qgRf6Lq^0p z5`iaOiM@N8^>qveZCof+Ofdb;J8nj<-^wuVHmJ(i z2tOID#IjtWlLS$a`k+SH+IK%+igD6EHdJ&P1hhzMz^6)t0O+@h|M0SNAjRmw8(Ed@ z8wNCgoDVl0PNa6s1Zh?fYB7}H&d5=oy|)z{OaqgR7NqWn8A>!rj2OV#68)(grTWepKse{oNQne}#CG^4H7>T= z2^*fCx@RUmu1C+na<0wjCp+&<`UA9ml<5vHyV?{*N&)H&s~P<@!wX=9#mymUVJlGzNEvm<+;uHm>*pGE~1v!jm& zgO~`zPUTP5FgeJR#R}lGdr1r35Dd^PKdn8&S5fDcvp6oE9%{(Zn-*$O{ftayJP=WQ zqb=ELQ!j0p#SsIUGxRS3d-h@MNj-^@EjkS)2!b3+H$S%LZeGY@BNR{S0zIUd*yr-f z;*VRP_29JzYH|8vd*?lHs_hy#ON)A@Y&yz}Bvd?&&8k4Tz;~l8t4({loMfS(t%hj- z@Ro6O<*2?mx;FL)vFrB+@DNkJC#A(qV->c`QM0X^CG*1was_-bLR9R|8!tKw2~cgl zm}Fb)!FibsigGIqA_?%_T7b1Qja}p~DU+9_ViEeH@U(&TPK{o$HD zDppvBPJDaJCL!!syQTcG8xAla@QJ7 zSg(#$J7y?ppmD|-trvNgDDq|_YJED6fL3g%|L(gGo&JzHl3EejveDo| z|KG2F``Q%y+As*|jtzDB*D69fMWg~Wg%*J{kYHE_Z`;Vdei6g}tkA83C`SwV`5jUr zm^P?5@wKf4&J!~mu*Ht`dJCrJ%)Pr1? znvJeNAy5_#K?r2W=WI660r%Px3z@?A!WmvZ>W8y_k{5#$gqnB(uf~&QL63ctwB2u1 zrMBk5KJTxU4jS2-?6UA;075_F-bJ&0MEtK2OTiktu4)yB>c}M8xAzCtS&z3{WeSjv z$fv;&gqyDWdu#U<*Axbm{(P`@l*1BPMH7C%ZJa+p9xkRev;Xb>tVB9lkJ)A;d>q-k zyKC_BNV$us>5~t@qV;A>5Q+gURnAitFZh$?I@Fu16C6 z}Gbhan;6hV17v z%!9sOo7>P#S=~1{6-8hjkIBwHaHE~R_v?W=qNTQ|lSg#W+~ksyA>-s~?m~*TwJ#;b z>}y-n>qg(swAy$1DhNHvPVS7796tR1{ZljqooLbBV6AFHm(Tt1@f1qspdbXDK_ z`yVHMCKCj88V~$-Wv*V))p6Q7jWh0#AqpVkbK3f(N-*RT*rSr!{4%s=yF+^pvwR+CA!`uD=AiAkDnTUYV>)56ypUTAwga{lL^Kdb zBmajDH&p&V0Y(P7`Rk!0hQGY_eZ`;-hH>MCV`MDwhBoV`Y94t3%%7oBqob!30%jST5lC;=3CE7haC;FBwkv` zw7oSKobv2U2?D7#K@bEH3h}9RuU@?tKDKb}x^-JN7QMf7=eBKIi;9XiYA0t2GfEQfq=B z2qF|nty2i8H9-&r5elT%DTLITAP9m81ybu2LTXJA1VMxXsdWk=wI&FHAVR^S)&xNi z1VN-Brdm(fSUlcp6E_t5FB#n756 z$qiwoD6?d3VlBWBK(qL11a^(zTs*#r8w>B2wu#xqO}i#<_OwZxc0aJGL>Z!!Ht&95 z^DbrgGusWD$ZY})W8ov>y_9I(A?z^b1262f%@)($Ku3BOe9-(cx|1e)QO#O&;gT?f zi(q@k7VQ~RwCBE}J>!c?c#1M!#%u@u$|2lWR5H3~x3V!sC1^w#8btJ7i^(jb0DAE< zR$UYuXYt3(^)U>AkAl^OA

QW@$>4R0TxXC@HH8V=2a{rD-KmYwYF{(^$)_0DdB@ zhAfPC!Fo4LHgbQ_o(I@ZTw-B-MJe0F4HshLF5M<*#!~dlButiM3;uykyC-kjosYog z64(Sb5PenXUNM^he|Sk40?JjSPvnL~W<~6$D5h+pwW)D(D%hN3K3RA(Ce56141ZG5 zp2?c!TceY=ln9%$rDWRH-P7^2sHC81H|)VJB{Q~^%-p(r*47dj0)<<4BL#+HFc#j* zY&y4TTlY-eQZluOH6pBVOUaxqyXR^)Q`F-2V9}mwnjy*(x9&kZ_z9b_b=xHLe+yRE9{gmpp$fD4XFoB($(uDZ+=IbebToq(Mim648RNntf#IUh+p7`W7jm7zp zKsTEtB%BL2v{p$q3m`?;X~UrF!jwGYr`dw&aTBWx6M8QMTSQs2n~U$?Ts*O;cmizm zF1G8b9fWUu`3{lRY&RAnjEOW?N~EYY>S|oSnHl=cHbl0=VyD~W*zWl&26I=1@hz1F zG(CnXsfOLp^wrG5pmYa#U)ts?dlBvHSxD5>8YU#ilq(@=hOn{nnxCu+Z+vqJBw1H$ zvGWQ;Q#Q38t%(-4Z+Riyja4^ZJ-~KxGyKuIkW%Vqq9daPVW^81L{nxv!3{zsOv)96 z3i`@^vZZCLE)}# zvluhsn=}l;rokAsa1{ZkJPYHmXjuRS^wwbFMU1#!xG2JKf%M@k!G=`x4N)^gt%Y&< zfljbn6@lqYp0WR87cQB}!)jla#?{);Y^IcKpVj1i&Xy8gt!HhqN`4VHtvnQ3S)r!Z zv$=_|6lrCeT0_X$5HvINl^J9}hyfIWn-B(z$RR4yl}+I?kLo-Zde0;uDOxQyX}aNs zjvAEHkc(z*Vhm%uB2F*-0OM3^RB>ptJw=Epe|=z>q1LbmnP6KkH(sKNaS20pq1G6q zrq(b|wVqkDrx3W5W)frtQq6x(FDjk}6KY+w`~L%p_xHOS_?R{T0000< KMNUMnLSTZPWX3rF literal 0 HcmV?d00001 diff --git a/docs/installation.md b/docs/installation.md index 77a5728c..22b9ccc3 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -1,25 +1,45 @@ +[TOC] + +## Overview + Rojo has two components: -* The server, a binary written in Rust -* The plugin, a Roblox Studio plugin written in Lua +* The command line interface (CLI) +* The Roblox Studio plugin -It's important that the plugin and server are compatible. The plugin will show errors in the Roblox Studio Output window if there is a version mismatch. +!!! info + It's important that your installed version of the plugin and CLI are compatible. -## Installing the Server -To install the server, either: + The plugin will show errors in the Roblox Studio output window if there is a version mismatch. -* If you have Rust installed, use `cargo install rojo` -* Or, download a pre-built Windows binary from [the GitHub releases page](https://github.com/LPGhatguy/rojo/releases) +## Installing the CLI -**The Rojo binary must be run from the command line, like Terminal on MacOS or `cmd.exe` on Windows. It's recommended that you put the Rojo binary on your `PATH` to make this easier.** +### Installing from GitHub +If you're on Windows, there are pre-built binaries available from Rojo's [GitHub Releases page](https://github.com/LPGhatguy/rojo/releases). + +The Rojo CLI must be run from the command line, like Terminal.app on MacOS or `cmd.exe` on Windows. It's recommended that you put the Rojo CLI executable on your `PATH` to make this easier. + +### Installing from Cargo +If you have Rust installed, the easiest way to get Rojo is with Cargo! + +To install the latest 0.5.0 alpha, use: + +```sh +cargo install rojo --version 0.5.0-alpha.3 +``` ## Installing the Plugin -To install the plugin, either: -* Install the plugin from the [Roblox plugin page](https://www.roblox.com/library/1211549683/Rojo). - * This gives you less control over what version you install -- you will always have the latest version. -* Or, download the latest release from [the GitHub releases section](https://github.com/LPGhatguy/rojo/releases) and install it into your Roblox plugins folder - * You can open this folder by clicking the "Plugins Folder" button from the Plugins toolbar in Roblox Studio +### Installing from GitHub +The Rojo Roblox Studio plugin is available available from Rojo's [GitHub Releases page](https://github.com/LPGhatguy/rojo/releases). + +Download the attached `rbxm` file and put it into your Roblox Studio plugins folder. You can find that folder by pressing **Plugins Folder** from your Plugins toolbar in Roblox Studio: + +!['Plugins Folder' button in Roblox Studio](images/plugins-folder-in-studio.png) +{: align="center" } + +### Installing from Roblox.com +Visit [Rojo's Roblox.com Plugin page](https://www.roblox.com/library/1997686364/Rojo-0-5-0-alpha-3) in Roblox Studio and press **Install**. ## Visual Studio Code Extension If you use Visual Studio Code on Windows, you can install [Evaera's unofficial Rojo extension](https://marketplace.visualstudio.com/items?itemName=evaera.vscode-rojo), which will install both halves of Rojo for you. It even has a nifty UI to add partitions and start/stop the Rojo server! \ No newline at end of file diff --git a/docs/project-format.md b/docs/project-format.md index 6d3f6659..c21e32ff 100644 --- a/docs/project-format.md +++ b/docs/project-format.md @@ -1 +1,100 @@ -WIP \ No newline at end of file +[TOC] + +## Project File + +Rojo projects are JSON files that have the `.project.json` extension. They have these fields: + +* `name`: A string indicating the name of the project. + * This is only used for diagnostics. +* `tree`: An [Instance Description](#instance-description) describing the root instance of the project. + +## Instance Description +Instance Descriptions correspond one-to-one with the actual Roblox Instances in the project. They can be specified directly in the project file or be pulled from the filesystem. + +* `$className`: The ClassName of the Instance being described. + * Optional if `$path` is specified. +* `$path`: The path on the filesystem to pull files from into the project. + * Optional if `$className` is specified. + * Paths are relative to the folder containing the project file. +* `$properties`: Properties to apply to the instance. Values should be [Instance Property Values](#instance-property-value). + * Optional +* `$ignoreUnknownInstances`: Whether instances that Rojo doesn't know about should be deleted. + * Optional + * Default is `false` if `$path` is specified, otherwise `true`. + +All other fields in an Instance Description are turned into instances whose name is the key. These values should also be Instance Descriptions! + +Instance Descriptions are fairly verbose and strict. In the future, it'll be possible for Rojo to infer class names for known services like `Workspace`. + +## Instance Property Value +The shape of Instance Property Values is defined by the [rbx_tree](https://github.com/LPGhatguy/rbx-tree) library, so it uses slightly different conventions than the rest of Rojo. + +Each value should be an object with the following required fields: + +* `Type`: The type of property to represent. + * [Supported types can be found here](https://github.com/LPGhatguy/rbx-tree#property-type-coverage). +* `Value`: The value of the property. + * The shape of this field depends on which property type is being used. `Vector3` and `Color3` values are both represented as a list of numbers, for example. + +Instance Property Values are intentionally very strict. Rojo will eventually be able to infer types for you! + +## Example Projects +This project bundles up everything in the `src` directory. It'd be suitable for making a plugin or model: + +```json +{ + "name": "AwesomeLibrary", + "tree": { + "$path": "src" + } +} +``` + +This project describes the layout you might use if you were making the next hit simulator game, *Sisyphus Simulator*: + +```json +{ + "name": "Sisyphus Simulator", + "tree": { + "$className": "DataModel", + + "HttpService": { + "$className": "HttpService", + "$properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + } + }, + + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + "$path": "src/ReplicatedStorage" + }, + + "StarterPlayer": { + "$className": "StarterPlayer", + + "StarterPlayerScripts": { + "$className": "StarterPlayerScripts", + "$path": "src/StarterPlayerScripts" + } + }, + + "Workspace": { + "$className": "Workspace", + "$properties": { + "Gravity": { + "Type": "Float32", + "Value": 67.3 + } + }, + + "Terrain": { + "$path": "Terrain.rbxm" + } + } + } +} +``` \ No newline at end of file diff --git a/docs/sync-details.md b/docs/sync-details.md index d260feb8..a016e019 100644 --- a/docs/sync-details.md +++ b/docs/sync-details.md @@ -36,19 +36,13 @@ If a directory contains a file named `init.server.lua`, `init.client.lua`, or `i For example, these files: -

+![Tree of files on disk](images/sync-example-files.svg) +{: align="center" } Will turn into these instances in Roblox: - +![Tree of instances in Roblox](images/sync-example-instances.svg) +{: align="center" } ## Localization Tables Any CSV files are transformed into `LocalizationTable` instances. Rojo expects these files to follow the same format that Roblox does when importing and exporting localization information. @@ -86,11 +80,8 @@ A JSON model describing a folder containing a `Part` and a `RemoteEvent` could b It would turn into instances in this shape: - +![Tree of instances in Roblox](images/sync-example-json-model.svg) +{: align="center" } ## Binary and XML Models Rojo supports both binary (`.rbxm`) and XML (`.rbxmx`) models generated by Roblox Studio or another tool. From 4a597e0ba7d864fa17b1148a31aefc7e561459ea Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Feb 2019 18:20:48 -0800 Subject: [PATCH 0435/1504] 0.5.0-alpha.4 --- CHANGELOG.md | 2 ++ Cargo.lock | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d855885c..49fd719b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## [Unreleased] + +## [0.5.0 Alpha 4](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.4) (February 8, 2019) * Added support for nested partitions ([#102](https://github.com/LPGhatguy/rojo/issues/102)) * Added support for 'transmuting' partitions ([#112](https://github.com/LPGhatguy/rojo/issues/112)) * Added support for aliasing filesystem paths ([#105](https://github.com/LPGhatguy/rojo/issues/105)) diff --git a/Cargo.lock b/Cargo.lock index 027834be..ce0a6905 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1292,7 +1292,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0-alpha.3" +version = "0.5.0-alpha.4" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 0354e518..08ed8052 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0, "-alpha.3"}, + version = {0, 5, 0, "-alpha.4"}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/server/Cargo.toml b/server/Cargo.toml index 0e878811..09a63a18 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0-alpha.3" +version = "0.5.0-alpha.4" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From c3baf73455d90827c7c18599341b5d05bb1ffba1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Feb 2019 18:29:23 -0800 Subject: [PATCH 0436/1504] Update documentation for alpha 4 --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 22b9ccc3..e12b22de 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -25,7 +25,7 @@ If you have Rust installed, the easiest way to get Rojo is with Cargo! To install the latest 0.5.0 alpha, use: ```sh -cargo install rojo --version 0.5.0-alpha.3 +cargo install rojo --version 0.5.0-alpha.4 ``` ## Installing the Plugin From b9ee14a0f9bf4118f310b512d07e0c6e7fedebe9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Feb 2019 10:27:09 -0800 Subject: [PATCH 0437/1504] Remove unused Cargo features section --- server/Cargo.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/server/Cargo.toml b/server/Cargo.toml index 09a63a18..479e99f8 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -15,10 +15,6 @@ path = "src/lib.rs" name = "rojo" path = "src/bin.rs" -[features] -default = [] -bundle-plugin = [] - [dependencies] clap = "2.27" csv = "1.0" From 5f062b8ea3d076c508be307fac8704b66d5594f7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Feb 2019 10:55:03 -0800 Subject: [PATCH 0438/1504] Make the plugin support non-primitive types --- plugin/.luacheckrc | 1 + plugin/src/InstanceMap.lua | 71 +++++++++++++++++ plugin/src/Reconciler.lua | 110 ++------------------------ plugin/src/rojoValueToRobloxValue.lua | 32 ++++++++ plugin/src/setProperty.lua | 45 +++++++++++ 5 files changed, 155 insertions(+), 104 deletions(-) create mode 100644 plugin/src/InstanceMap.lua create mode 100644 plugin/src/rojoValueToRobloxValue.lua create mode 100644 plugin/src/setProperty.lua diff --git a/plugin/.luacheckrc b/plugin/.luacheckrc index 5e011987..9a0c40a1 100644 --- a/plugin/.luacheckrc +++ b/plugin/.luacheckrc @@ -13,6 +13,7 @@ stds.roblox = { -- Types "Vector2", "Vector3", + "Vector2int16", "Vector3int16", "Color3", "UDim", "UDim2", "Rect", diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua new file mode 100644 index 00000000..5356ac7b --- /dev/null +++ b/plugin/src/InstanceMap.lua @@ -0,0 +1,71 @@ +local Logging = require(script.Parent.Logging) + +--[[ + A bidirectional map between instance IDs and Roblox instances. It lets us + keep track of every instance we know about. + + TODO: Track ancestry to catch when stuff moves? +]] +local InstanceMap = {} +InstanceMap.__index = InstanceMap + +function InstanceMap.new() + local self = { + fromIds = {}, + fromInstances = {}, + } + + return setmetatable(self, InstanceMap) +end + +function InstanceMap:insert(id, instance) + self.fromIds[id] = instance + self.fromInstances[instance] = id +end + +function InstanceMap:removeId(id) + local instance = self.fromIds[id] + + if instance ~= nil then + self.fromIds[id] = nil + self.fromInstances[instance] = nil + else + Logging.warn("Attempted to remove nonexistant ID %s", tostring(id)) + end +end + +function InstanceMap:removeInstance(instance) + local id = self.fromInstances[instance] + + if id ~= nil then + self.fromInstances[instance] = nil + self.fromIds[id] = nil + else + Logging.warn("Attempted to remove nonexistant instance %s", tostring(instance)) + end +end + +function InstanceMap:destroyId(id) + local instance = self.fromIds[id] + self:removeId(id) + + if instance ~= nil then + local descendantsToDestroy = {} + + for otherInstance in pairs(self.fromInstances) do + if otherInstance:IsDescendantOf(instance) then + table.insert(descendantsToDestroy, otherInstance) + end + end + + for _, otherInstance in ipairs(descendantsToDestroy) do + self:removeInstance(otherInstance) + end + + instance:Destroy() + else + Logging.warn("Attempted to destroy nonexistant ID %s", tostring(id)) + end +end + +return InstanceMap \ No newline at end of file diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 07e9db76..e3a7bc40 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -1,108 +1,14 @@ +local InstanceMap = require(script.Parent.InstanceMap) local Logging = require(script.Parent.Logging) - -local function makeInstanceMap() - local self = { - fromIds = {}, - fromInstances = {}, - } - - function self:insert(id, instance) - self.fromIds[id] = instance - self.fromInstances[instance] = id - end - - function self:removeId(id) - local instance = self.fromIds[id] - - if instance ~= nil then - self.fromIds[id] = nil - self.fromInstances[instance] = nil - else - Logging.warn("Attempted to remove nonexistant ID %s", tostring(id)) - end - end - - function self:removeInstance(instance) - local id = self.fromInstances[instance] - - if id ~= nil then - self.fromInstances[instance] = nil - self.fromIds[id] = nil - else - Logging.warn("Attempted to remove nonexistant instance %s", tostring(instance)) - end - end - - function self:destroyId(id) - local instance = self.fromIds[id] - self:removeId(id) - - if instance ~= nil then - local descendantsToDestroy = {} - - for otherInstance in pairs(self.fromInstances) do - if otherInstance:IsDescendantOf(instance) then - table.insert(descendantsToDestroy, otherInstance) - end - end - - for _, otherInstance in ipairs(descendantsToDestroy) do - self:removeInstance(otherInstance) - end - - instance:Destroy() - else - Logging.warn("Attempted to destroy nonexistant ID %s", tostring(id)) - end - end - - return self -end - -local function setProperty(instance, key, value) - -- The 'Contents' property of LocalizationTable isn't directly exposed, but - -- has corresponding (deprecated) getters and setters. - if key == "Contents" and instance.ClassName == "LocalizationTable" then - instance:SetContents(value) - return - end - - -- If we don't have permissions to access this value at all, we can skip it. - local readSuccess, existingValue = pcall(function() - return instance[key] - end) - - if not readSuccess then - -- An error will be thrown if there was a permission issue or if the - -- property doesn't exist. In the latter case, we should tell the user - -- because it's probably their fault. - if existingValue:find("lacking permission") then - Logging.trace("Permission error reading property %s on class %s", tostring(key), instance.ClassName) - return - else - error(("Invalid property %s on class %s: %s"):format(tostring(key), instance.ClassName, existingValue), 2) - end - end - - local writeSuccess, err = pcall(function() - if existingValue ~= value then - instance[key] = value - end - end) - - if not writeSuccess then - error(("Cannot set property %s on class %s: %s"):format(tostring(key), instance.ClassName, err), 2) - end - - return true -end +local setProperty = require(script.Parent.setProperty) +local rojoValueToRobloxValue = require(script.Parent.rojoValueToRobloxValue) local Reconciler = {} Reconciler.__index = Reconciler function Reconciler.new() local self = { - instanceMap = makeInstanceMap(), + instanceMap = InstanceMap.new(), } return setmetatable(self, Reconciler) @@ -140,7 +46,7 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) setProperty(instance, "Name", virtualInstance.Name) for key, value in pairs(virtualInstance.Properties) do - setProperty(instance, key, value.Value) + setProperty(instance, key, rojoValueToRobloxValue(value)) end local existingChildren = instance:GetChildren() @@ -195,9 +101,6 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) -- Some instances, like services, don't like having their Parent -- property poked, even if we're setting it to the same value. setProperty(instance, "Parent", parent) - if instance.Parent ~= parent then - instance.Parent = parent - end end return instance @@ -217,8 +120,7 @@ function Reconciler:__reify(virtualInstancesById, id, parent) local instance = Instance.new(virtualInstance.ClassName) for key, value in pairs(virtualInstance.Properties) do - -- TODO: Branch on value.Type - setProperty(instance, key, value.Value) + setProperty(instance, key, rojoValueToRobloxValue(value)) end instance.Name = virtualInstance.Name diff --git a/plugin/src/rojoValueToRobloxValue.lua b/plugin/src/rojoValueToRobloxValue.lua new file mode 100644 index 00000000..995a8e4b --- /dev/null +++ b/plugin/src/rojoValueToRobloxValue.lua @@ -0,0 +1,32 @@ +local primitiveTypes = { + String = true, + Bool = true, + Int32 = true, + Float32 = true, + Enum = true, +} + +local directConstructors = { + CFrame = CFrame.new, + Color3 = Color3.new, + Vector2 = Vector2.new, + Vector2int16 = Vector2int16.new, + Vector3 = Vector3.new, + Vector3int16 = Vector3int16.new, +} + +local function rojoValueToRobloxValue(value) + if primitiveTypes[value.Type] then + return value.Value + end + + local constructor = directConstructors[value.Type] + if constructor ~= nil then + return constructor(unpack(value.Value)) + end + + local errorMessage = ("The Rojo plugin doesn't know how to handle values of type %q yet!"):format(tostring(value.Type)) + error(errorMessage) +end + +return rojoValueToRobloxValue \ No newline at end of file diff --git a/plugin/src/setProperty.lua b/plugin/src/setProperty.lua new file mode 100644 index 00000000..76a44f82 --- /dev/null +++ b/plugin/src/setProperty.lua @@ -0,0 +1,45 @@ +local Logging = require(script.Parent.Logging) + +--[[ + Attempts to set a property on the given instance, correctly handling + 'virtual properties', which aren't reflected directly to Lua. +]] +local function setProperty(instance, key, value) + -- The 'Contents' property of LocalizationTable isn't directly exposed, but + -- has corresponding (deprecated) getters and setters. + if instance.ClassName == "LocalizationTable" and key == "Contents" then + instance:SetContents(value) + return + end + + -- If we don't have permissions to access this value at all, we can skip it. + local readSuccess, existingValue = pcall(function() + return instance[key] + end) + + if not readSuccess then + -- An error will be thrown if there was a permission issue or if the + -- property doesn't exist. In the latter case, we should tell the user + -- because it's probably their fault. + if existingValue:find("lacking permission") then + Logging.trace("Permission error reading property %s on class %s", tostring(key), instance.ClassName) + return + else + error(("Invalid property %s on class %s: %s"):format(tostring(key), instance.ClassName, existingValue), 2) + end + end + + local writeSuccess, err = pcall(function() + if existingValue ~= value then + instance[key] = value + end + end) + + if not writeSuccess then + error(("Cannot set property %s on class %s: %s"):format(tostring(key), instance.ClassName, err), 2) + end + + return true +end + +return setProperty \ No newline at end of file From 7a8389bf11fe8a0552bb0465fe9cce556b2019e2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Feb 2019 11:42:40 -0800 Subject: [PATCH 0439/1504] Update CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49fd719b..8ccdf2cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## [Unreleased] +* Added support for non-primitive types in the Rojo plugin. + * Types like `Color3` and `CFrame` can now be updated live! ## [0.5.0 Alpha 4](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.4) (February 8, 2019) * Added support for nested partitions ([#102](https://github.com/LPGhatguy/rojo/issues/102)) From c7c739dc00891629a2a01ce2fb1fb534c9f84f04 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Feb 2019 11:43:06 -0800 Subject: [PATCH 0440/1504] Fix test bootstrap script for testing in Studio --- plugin/testBootstrap.server.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/testBootstrap.server.lua b/plugin/testBootstrap.server.lua index ae53be9f..4d10558a 100644 --- a/plugin/testBootstrap.server.lua +++ b/plugin/testBootstrap.server.lua @@ -1,2 +1,2 @@ local TestEZ = require(game.ReplicatedStorage.TestEZ) -TestEZ.TestBootstrap:run(game.ReplicatedStorage.Rojo.plugin) \ No newline at end of file +TestEZ.TestBootstrap:run({game.ReplicatedStorage.Rojo.Plugin}) \ No newline at end of file From 91d1ba1910679b69411609c70536cc52a13872c5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Feb 2019 11:43:17 -0800 Subject: [PATCH 0441/1504] Add test for rojoValueToRobloxValue, fails Lemur because of missing APIs right now --- plugin/src/rojoValueToRobloxValue.spec.lua | 40 ++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 plugin/src/rojoValueToRobloxValue.spec.lua diff --git a/plugin/src/rojoValueToRobloxValue.spec.lua b/plugin/src/rojoValueToRobloxValue.spec.lua new file mode 100644 index 00000000..fe7cbaec --- /dev/null +++ b/plugin/src/rojoValueToRobloxValue.spec.lua @@ -0,0 +1,40 @@ +local rojoValueToRobloxValue = require(script.Parent.rojoValueToRobloxValue) + +return function() + it("should convert primitives", function() + local inputString = { + Type = "String", + Value = "Hello, world!", + } + + local inputFloat32 = { + Type = "Float32", + Value = 12341.512, + } + + expect(rojoValueToRobloxValue(inputString)).to.equal(inputString.Value) + expect(rojoValueToRobloxValue(inputFloat32)).to.equal(inputFloat32.Value) + end) + + it("should convert properties with direct constructors", function() + local inputColor3 = { + Type = "Color3", + Value = {0, 1, 0.5}, + } + local outputColor3 = Color3.new(0, 1, 0.5) + + local inputCFrame = { + Type = "CFrame", + Value = { + 1, 2, 3, + 4, 5, 6, + 7, 8, 9, + 10, 11, 12, + }, + } + local outputCFrame = CFrame.new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) + + expect(rojoValueToRobloxValue(inputColor3)).to.equal(outputColor3) + expect(rojoValueToRobloxValue(inputCFrame)).to.equal(outputCFrame) + end) +end \ No newline at end of file From ca0aabd8147de7d52a25a3832a024d02759f3cc8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Feb 2019 13:47:49 -0800 Subject: [PATCH 0442/1504] Preload plugin assets at start. Closes #121. --- plugin/src/Assets.lua | 4 +--- plugin/src/Components/App.lua | 3 +++ plugin/src/preloadAssets.lua | 28 ++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 plugin/src/preloadAssets.lua diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index 9b94d6e8..156dde61 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -1,9 +1,7 @@ -local sheetAsset = "rbxassetid://2738712459" - local Assets = { Sprites = { WhiteCross = { - asset = sheetAsset, + asset = "rbxassetid://2738712459", offset = Vector2.new(190, 318), size = Vector2.new(18, 18), }, diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 893754ab..7d534759 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -8,6 +8,7 @@ local Config = require(Plugin.Config) local Version = require(Plugin.Version) local Logging = require(Plugin.Logging) local DevSettings = require(Plugin.DevSettings) +local preloadAssets = require(Plugin.preloadAssets) local ConnectPanel = require(Plugin.Components.ConnectPanel) local ConnectionActivePanel = require(Plugin.Components.ConnectionActivePanel) @@ -177,6 +178,8 @@ function App:didMount() }) end end) + + preloadAssets() end function App:didUpdate() diff --git a/plugin/src/preloadAssets.lua b/plugin/src/preloadAssets.lua new file mode 100644 index 00000000..6f40e001 --- /dev/null +++ b/plugin/src/preloadAssets.lua @@ -0,0 +1,28 @@ +local ContentProvider = game:GetService("ContentProvider") + +local Logging = require(script.Parent.Logging) +local Assets = require(script.Parent.Assets) + +local function preloadAssets() + local contentUrls = {} + + for _, sprite in pairs(Assets.Sprites) do + table.insert(contentUrls, sprite.asset) + end + + for _, slice in pairs(Assets.Slices) do + table.insert(contentUrls, slice.asset) + end + + for _, url in pairs(Assets.Images) do + table.insert(contentUrls, url) + end + + Logging.trace("Preloading assets: %s", table.concat(contentUrls, ", ")) + + coroutine.wrap(function() + ContentProvider:PreloadAsync(contentUrls) + end)() +end + +return preloadAssets \ No newline at end of file From 51a010de006e1f4194358076d49f8a5313bf8eeb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Feb 2019 13:48:20 -0800 Subject: [PATCH 0443/1504] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ccdf2cf..8f82530f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] * Added support for non-primitive types in the Rojo plugin. * Types like `Color3` and `CFrame` can now be updated live! +* Fixed plugin assets flashing in on first load ([#121](https://github.com/LPGhatguy/rojo/issues/121)) ## [0.5.0 Alpha 4](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.4) (February 8, 2019) * Added support for nested partitions ([#102](https://github.com/LPGhatguy/rojo/issues/102)) From 2890c677d4d2d6886b6de619ec2d4a81f52c1a21 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Feb 2019 17:22:44 -0800 Subject: [PATCH 0444/1504] Bump dependency from rbx_tree 0.2.0 to rbx_dom_weak 0.3.0 --- Cargo.lock | 24 ++++++++++++------------ server/Cargo.toml | 6 +++--- server/src/project.rs | 2 +- server/src/rbx_session.rs | 2 +- server/src/rbx_snapshot.rs | 2 +- server/src/snapshot_reconciler.rs | 2 +- server/src/visualize.rs | 2 +- server/src/web.rs | 4 ++-- server/tests/read_projects.rs | 2 +- 9 files changed, 23 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ce0a6905..7440e5a1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1179,18 +1179,18 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_tree 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] -name = "rbx_tree" -version = "0.2.0" +name = "rbx_dom_weak" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1200,7 +1200,7 @@ dependencies = [ [[package]] name = "rbx_xml" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1208,7 +1208,7 @@ dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_tree 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1305,9 +1305,9 @@ dependencies = [ "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_binary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_tree 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_binary 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2067,9 +2067,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rbx_binary 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4cdf4806920e6e1cd9f91651b8fdb5d811f4e5a98a76b2893e97effa40d62054" -"checksum rbx_tree 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b605ef3e2ff864705720e382a5499fc29a8d93cd3fbfc4724770825f6760462" -"checksum rbx_xml 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5e4cf33e0a240f367ad98d553e55e755b5cb4790b02284a34e130ba646b4f191" +"checksum rbx_binary 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c4d3bffbec1f20f66684448e46ef45dad2fbf1185c3d8f3e29018f027484ffc" +"checksum rbx_dom_weak 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a67bbec623f2f12992dbf2e647deb3fe38613d4f874a8feeae566a931bebe63a" +"checksum rbx_xml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b394e64979c52190e6462dd81d5b2258cdfb7e3891cefaff5d3c4af7cdc07b5" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" diff --git a/server/Cargo.toml b/server/Cargo.toml index 479e99f8..cab9a2a1 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -24,9 +24,9 @@ log = "0.4" maplit = "1.0.1" notify = "4.0" rand = "0.4" -rbx_binary = "0.2.0" -rbx_tree = "0.2.0" -rbx_xml = "0.2.0" +rbx_binary = "0.3.0" +rbx_dom_weak = "0.3.0" +rbx_xml = "0.3.0" regex = "1.0" reqwest = "0.9.5" rouille = "2.1" diff --git a/server/src/project.rs b/server/src/project.rs index 46ea7492..6b03a176 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -9,7 +9,7 @@ use std::{ use log::warn; use failure::Fail; use maplit::hashmap; -use rbx_tree::RbxValue; +use rbx_dom_weak::RbxValue; use serde_derive::{Serialize, Deserialize}; pub static PROJECT_FILENAME: &'static str = "default.project.json"; diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 50124916..66b2af17 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -8,7 +8,7 @@ use std::{ use serde_derive::{Serialize, Deserialize}; use log::{info, trace}; -use rbx_tree::{RbxTree, RbxId}; +use rbx_dom_weak::{RbxTree, RbxId}; use crate::{ project::{Project, ProjectNode}, diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index e8318d70..fe5443be 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -12,7 +12,7 @@ use std::{ use failure::Fail; use log::info; use maplit::hashmap; -use rbx_tree::{RbxTree, RbxValue, RbxInstanceProperties}; +use rbx_dom_weak::{RbxTree, RbxValue, RbxInstanceProperties}; use serde_derive::{Serialize, Deserialize}; use crate::{ diff --git a/server/src/snapshot_reconciler.rs b/server/src/snapshot_reconciler.rs index ff98aa16..cc4b686e 100644 --- a/server/src/snapshot_reconciler.rs +++ b/server/src/snapshot_reconciler.rs @@ -10,7 +10,7 @@ use std::{ str, }; -use rbx_tree::{RbxTree, RbxId, RbxInstanceProperties, RbxValue}; +use rbx_dom_weak::{RbxTree, RbxId, RbxInstanceProperties, RbxValue}; use serde_derive::{Serialize, Deserialize}; use crate::{ diff --git a/server/src/visualize.rs b/server/src/visualize.rs index c64bd328..4afa60b0 100644 --- a/server/src/visualize.rs +++ b/server/src/visualize.rs @@ -6,7 +6,7 @@ use std::{ }; use log::warn; -use rbx_tree::RbxId; +use rbx_dom_weak::RbxId; use crate::{ imfs::{Imfs, ImfsItem}, diff --git a/server/src/web.rs b/server/src/web.rs index e3d31c84..91ec9a89 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -15,7 +15,7 @@ use rouille::{ Request, Response, }; -use rbx_tree::{RbxId, RbxInstance}; +use rbx_dom_weak::{RbxId, RbxInstance}; use crate::{ live_session::LiveSession, @@ -43,7 +43,7 @@ impl PublicInstanceMetadata { } /// Used to attach metadata specific to Rojo to instances, which come from the -/// rbx_tree crate. +/// rbx_dom_weak crate. /// /// Both fields are wrapped in Cow in order to make owned-vs-borrowed simpler /// for tests. diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index d5314a21..1746cf56 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -6,7 +6,7 @@ use std::{ }; use pretty_assertions::assert_eq; -use rbx_tree::RbxValue; +use rbx_dom_weak::RbxValue; use librojo::{ project::{Project, ProjectNode}, From aaa78c618c5ed0fa13528f739def27b340528a45 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Feb 2019 11:27:22 -0800 Subject: [PATCH 0445/1504] Move diagnostics page to use Ritz, show server version --- Cargo.lock | 46 ++++++++++++++++++++++++++++++++++ server/Cargo.toml | 1 + server/assets/index.css | 43 ++++++++++++++++++++++++++++++++ server/assets/index.html | 54 ---------------------------------------- server/src/lib.rs | 2 ++ server/src/web.rs | 30 ++++++++++++++++++++-- 6 files changed, 120 insertions(+), 56 deletions(-) create mode 100644 server/assets/index.css delete mode 100644 server/assets/index.html diff --git a/Cargo.lock b/Cargo.lock index 7440e5a1..0590b2da 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -492,6 +492,11 @@ dependencies = [ "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "htmlescape" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "http" version = "0.1.15" @@ -1021,6 +1026,11 @@ dependencies = [ "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro-nested" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "proc-macro2" version = "0.4.26" @@ -1290,6 +1300,28 @@ dependencies = [ "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ritz" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-nested 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ritz_impl" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rojo" version = "0.5.0-alpha.4" @@ -1310,6 +1342,7 @@ dependencies = [ "rbx_xml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1506,6 +1539,14 @@ dependencies = [ "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "snax" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "stable_deref_trait" version = "1.1.1" @@ -1993,6 +2034,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9e59524a909fe98bb6c6f2cf1f27f2f6772887a496bf4c68cae0d94f884586" "checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e" +"checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" "checksum http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1a10e5b573b9a0146545010f50772b9e8b1dd0a256564cc4307694c68832a2f5" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" @@ -2050,6 +2092,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" +"checksum proc-macro-nested 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9968e025d6368d1273a93bc23051e30dbf5482475e716d7385d8ec8fbd5b5b6" "checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" @@ -2077,6 +2120,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "09d6e187a58d923ee132fcda141c94e716bcfe301c2ea2bef5c81536e0085376" +"checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" +"checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" @@ -2099,6 +2144,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" +"checksum snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef82be0baf3ae45701ab992230f1f4889c15984736d87f37558aea3e4e321af" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" diff --git a/server/Cargo.toml b/server/Cargo.toml index cab9a2a1..84c8f653 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -29,6 +29,7 @@ rbx_dom_weak = "0.3.0" rbx_xml = "0.3.0" regex = "1.0" reqwest = "0.9.5" +ritz = "0.1.0" rouille = "2.1" serde = "1.0" serde_derive = "1.0" diff --git a/server/assets/index.css b/server/assets/index.css new file mode 100644 index 00000000..7621a0d9 --- /dev/null +++ b/server/assets/index.css @@ -0,0 +1,43 @@ +* { + margin: 0; + padding: 0; + font: inherit; +} + +html { + font-family: sans-serif; + height: 100%; +} + +body { + height: 100%; + display: flex; + flex-direction: column; + justify-content: center; +} + +.main { + padding: 1rem; + text-align: center; + margin: 0 auto; + width: 100%; + max-width: 60rem; + background-color: #efefef; + border: 1px solid #666; + border-radius: 4px; +} + +.title { + font-size: 2rem; + font-weight: bold; +} + +.subtitle { + font-size: 1.5rem; + font-weight: bold; +} + +.docs { + font-size: 1.3rem; + font-weight: bold; +} \ No newline at end of file diff --git a/server/assets/index.html b/server/assets/index.html deleted file mode 100644 index 93e93848..00000000 --- a/server/assets/index.html +++ /dev/null @@ -1,54 +0,0 @@ - - - - Rojo - - - - -
-

Rojo Live Sync is up and running!

- Rojo Documentation -
- - - \ No newline at end of file diff --git a/server/src/lib.rs b/server/src/lib.rs index 2239a23c..1f4fa5f1 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,3 +1,5 @@ +#![recursion_limit="128"] + // Macros #[macro_use] pub mod impl_from; diff --git a/server/src/web.rs b/server/src/web.rs index 91ec9a89..0e46e79f 100644 --- a/server/src/web.rs +++ b/server/src/web.rs @@ -16,6 +16,7 @@ use rouille::{ Response, }; use rbx_dom_weak::{RbxId, RbxInstance}; +use ritz::{html}; use crate::{ live_session::LiveSession, @@ -25,7 +26,7 @@ use crate::{ rbx_session::{MetadataPerInstance}, }; -static HOME_CONTENT: &str = include_str!("../assets/index.html"); +static HOME_CSS: &str = include_str!("../assets/index.css"); /// Contains the instance metadata relevant to Rojo clients. #[derive(Debug, Serialize, Deserialize)] @@ -134,7 +135,32 @@ impl Server { } fn handle_home(&self) -> Response { - Response::html(HOME_CONTENT) + let page = html! { + + + "Rojo" + + + + +
+

+ "Rojo Live Sync is up and running!" +

+

+ "Version " { self.server_version } +

+ + "Rojo Documentation" + +
+ + + }; + + Response::html(format!("{}", page)) } /// Get a summary of information about the server From c13291a5986581aae16895b6ca36b6c161673d71 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Feb 2019 11:44:24 -0800 Subject: [PATCH 0446/1504] Break apart web interface between UI and API --- server/src/visualize.rs | 2 +- server/src/{web.rs => web/api.rs} | 83 ++------------------------ server/src/web/interface.rs | 97 +++++++++++++++++++++++++++++++ server/src/web/mod.rs | 47 +++++++++++++++ 4 files changed, 151 insertions(+), 78 deletions(-) rename server/src/{web.rs => web/api.rs} (71%) create mode 100644 server/src/web/interface.rs create mode 100644 server/src/web/mod.rs diff --git a/server/src/visualize.rs b/server/src/visualize.rs index 4afa60b0..32ab0786 100644 --- a/server/src/visualize.rs +++ b/server/src/visualize.rs @@ -11,7 +11,7 @@ use rbx_dom_weak::RbxId; use crate::{ imfs::{Imfs, ImfsItem}, rbx_session::RbxSession, - web::PublicInstanceMetadata, + web::api::PublicInstanceMetadata, }; static GRAPHVIZ_HEADER: &str = r#" diff --git a/server/src/web.rs b/server/src/web/api.rs similarity index 71% rename from server/src/web.rs rename to server/src/web/api.rs index 0e46e79f..9b1950c9 100644 --- a/server/src/web.rs +++ b/server/src/web/api.rs @@ -1,5 +1,5 @@ -//! Defines Rojo's web interface that all clients use to communicate with a -//! running live-sync session. +//! Defines Rojo's HTTP API, all under /api. These endpoints generally return +//! JSON. use std::{ borrow::Cow, @@ -8,7 +8,6 @@ use std::{ }; use serde_derive::{Serialize, Deserialize}; -use log::trace; use rouille::{ self, router, @@ -16,18 +15,14 @@ use rouille::{ Response, }; use rbx_dom_weak::{RbxId, RbxInstance}; -use ritz::{html}; use crate::{ live_session::LiveSession, session_id::SessionId, snapshot_reconciler::InstanceChanges, - visualize::{VisualizeRbxSession, VisualizeImfs, graphviz_to_svg}, rbx_session::{MetadataPerInstance}, }; -static HOME_CSS: &str = include_str!("../assets/index.css"); - /// Contains the instance metadata relevant to Rojo clients. #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -83,14 +78,14 @@ pub struct SubscribeResponse<'a> { pub messages: Cow<'a, [InstanceChanges]>, } -pub struct Server { +pub struct ApiServer { live_session: Arc, server_version: &'static str, } -impl Server { - pub fn new(live_session: Arc) -> Server { - Server { +impl ApiServer { + pub fn new(live_session: Arc) -> ApiServer { + ApiServer { live_session, server_version: env!("CARGO_PKG_VERSION"), } @@ -98,12 +93,7 @@ impl Server { #[allow(unreachable_code)] pub fn handle_request(&self, request: &Request) -> Response { - trace!("Request {} {}", request.method(), request.url()); - router!(request, - (GET) (/) => { - self.handle_home() - }, (GET) (/api/rojo) => { self.handle_api_rojo() }, @@ -118,51 +108,10 @@ impl Server { self.handle_api_read(requested_ids) }, - (GET) (/visualize/rbx) => { - self.handle_visualize_rbx() - }, - (GET) (/visualize/imfs) => { - self.handle_visualize_imfs() - }, _ => Response::empty_404() ) } - pub fn listen(self, port: u16) { - let address = format!("0.0.0.0:{}", port); - - rouille::start_server(address, move |request| self.handle_request(request)); - } - - fn handle_home(&self) -> Response { - let page = html! { - - - "Rojo" - - - - -
-

- "Rojo Live Sync is up and running!" -

-

- "Version " { self.server_version } -

- - "Rojo Documentation" - -
- - - }; - - Response::html(format!("{}", page)) - } - /// Get a summary of information about the server fn handle_api_rojo(&self) -> Response { let rbx_session = self.live_session.rbx_session.lock().unwrap(); @@ -260,24 +209,4 @@ impl Server { instances, }) } - - fn handle_visualize_rbx(&self) -> Response { - let rbx_session = self.live_session.rbx_session.lock().unwrap(); - let dot_source = format!("{}", VisualizeRbxSession(&rbx_session)); - - match graphviz_to_svg(&dot_source) { - Some(svg) => Response::svg(svg), - None => Response::text(dot_source), - } - } - - fn handle_visualize_imfs(&self) -> Response { - let imfs = self.live_session.imfs.lock().unwrap(); - let dot_source = format!("{}", VisualizeImfs(&imfs)); - - match graphviz_to_svg(&dot_source) { - Some(svg) => Response::svg(svg), - None => Response::text(dot_source), - } - } } \ No newline at end of file diff --git a/server/src/web/interface.rs b/server/src/web/interface.rs new file mode 100644 index 00000000..24f8b6d0 --- /dev/null +++ b/server/src/web/interface.rs @@ -0,0 +1,97 @@ +//! Defines the HTTP-based UI. These endpoints generally return HTML and SVG. + +use std::sync::Arc; + +use rouille::{ + self, + router, + Request, + Response, +}; +use ritz::{html}; + +use crate::{ + live_session::LiveSession, + visualize::{VisualizeRbxSession, VisualizeImfs, graphviz_to_svg}, +}; + +static HOME_CSS: &str = include_str!("../../assets/index.css"); + +pub struct InterfaceServer { + live_session: Arc, + server_version: &'static str, +} + +impl InterfaceServer { + pub fn new(live_session: Arc) -> InterfaceServer { + InterfaceServer { + live_session, + server_version: env!("CARGO_PKG_VERSION"), + } + } + + #[allow(unreachable_code)] + pub fn handle_request(&self, request: &Request) -> Response { + router!(request, + (GET) (/) => { + self.handle_home() + }, + (GET) (/visualize/rbx) => { + self.handle_visualize_rbx() + }, + (GET) (/visualize/imfs) => { + self.handle_visualize_imfs() + }, + _ => Response::empty_404() + ) + } + + fn handle_home(&self) -> Response { + let page = html! { + + + "Rojo" + + + + +
+

+ "Rojo Live Sync is up and running!" +

+

+ "Version " { self.server_version } +

+ + "Rojo Documentation" + +
+ + + }; + + Response::html(format!("{}", page)) + } + + fn handle_visualize_rbx(&self) -> Response { + let rbx_session = self.live_session.rbx_session.lock().unwrap(); + let dot_source = format!("{}", VisualizeRbxSession(&rbx_session)); + + match graphviz_to_svg(&dot_source) { + Some(svg) => Response::svg(svg), + None => Response::text(dot_source), + } + } + + fn handle_visualize_imfs(&self) -> Response { + let imfs = self.live_session.imfs.lock().unwrap(); + let dot_source = format!("{}", VisualizeImfs(&imfs)); + + match graphviz_to_svg(&dot_source) { + Some(svg) => Response::svg(svg), + None => Response::text(dot_source), + } + } +} \ No newline at end of file diff --git a/server/src/web/mod.rs b/server/src/web/mod.rs new file mode 100644 index 00000000..e988b524 --- /dev/null +++ b/server/src/web/mod.rs @@ -0,0 +1,47 @@ +// TODO: This module needs to be public for visualize, we should move +// PublicInstanceMetadata and switch this private! +pub mod api; +mod interface; + +use std::sync::Arc; + +use log::trace; +use rouille::{find_route, Request, Response}; + +use crate::{ + live_session::LiveSession, +}; + +use self::{ + api::ApiServer, + interface::InterfaceServer, +}; + +pub struct Server { + api: api::ApiServer, + interface: interface::InterfaceServer, +} + +impl Server { + pub fn new(live_session: Arc) -> Server { + Server { + api: ApiServer::new(Arc::clone(&live_session)), + interface: InterfaceServer::new(Arc::clone(&live_session)), + } + } + + pub fn handle_request(&self, request: &Request) -> Response { + trace!("Request {} {}", request.method(), request.url()); + + find_route!( + self.api.handle_request(request), + self.interface.handle_request(request) + ) + } + + pub fn listen(self, port: u16) { + let address = format!("0.0.0.0:{}", port); + + rouille::start_server(address, move |request| self.handle_request(request)); + } +} \ No newline at end of file From 6ea1211bc5c0dc3f1bda948612cbbbe0985e0295 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 22 Feb 2019 10:50:14 -0800 Subject: [PATCH 0447/1504] It's alive! --- Cargo.lock | 2 ++ server/Cargo.toml | 2 ++ server/src/web/mod.rs | 45 ++++++++++++++++++++++++++++++------------- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0590b2da..108ee0c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1330,6 +1330,8 @@ dependencies = [ "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.23 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/server/Cargo.toml b/server/Cargo.toml index 84c8f653..344bc01e 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -20,6 +20,8 @@ clap = "2.27" csv = "1.0" env_logger = "0.6" failure = "0.1.3" +futures = "0.1" +hyper = "0.12" log = "0.4" maplit = "1.0.1" notify = "4.0" diff --git a/server/src/web/mod.rs b/server/src/web/mod.rs index e988b524..8e4e2978 100644 --- a/server/src/web/mod.rs +++ b/server/src/web/mod.rs @@ -5,8 +5,16 @@ mod interface; use std::sync::Arc; -use log::trace; -use rouille::{find_route, Request, Response}; +use futures::{ + future::{self, FutureResult}, + Future, +}; +use hyper::{ + service::Service, + Body, + Request, + Response, +}; use crate::{ live_session::LiveSession, @@ -22,6 +30,19 @@ pub struct Server { interface: interface::InterfaceServer, } +struct Blah; + +impl Service for Blah { + type ReqBody = Body; + type ResBody = Body; + type Error = hyper::Error; + type Future = Box, Error = Self::Error> + Send>; + + fn call(&mut self, request: Request) -> Self::Future { + Box::new(future::ok(Response::new(Body::from("Hello, world!")))) + } +} + impl Server { pub fn new(live_session: Arc) -> Server { Server { @@ -30,18 +51,16 @@ impl Server { } } - pub fn handle_request(&self, request: &Request) -> Response { - trace!("Request {} {}", request.method(), request.url()); - - find_route!( - self.api.handle_request(request), - self.interface.handle_request(request) - ) - } - pub fn listen(self, port: u16) { - let address = format!("0.0.0.0:{}", port); + let address = ([127, 0, 0, 1], port).into(); - rouille::start_server(address, move |request| self.handle_request(request)); + let server = hyper::Server::bind(&address) + .serve(move || { + let service: FutureResult = future::ok(Blah); + service + }) + .map_err(|e| eprintln!("Server error: {}", e)); + + hyper::rt::run(server); } } \ No newline at end of file From 105d8aeb6b795e4016c72e5f4f800e87a883d505 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 22 Feb 2019 13:08:07 -0800 Subject: [PATCH 0448/1504] Start to stub out sub-services --- server/src/commands/serve.rs | 6 +++--- server/src/web/api.rs | 16 +++++++++++++++ server/src/web/interface.rs | 16 +++++++++++++++ server/src/web/mod.rs | 38 +++++++++++++++++++++++++----------- 4 files changed, 62 insertions(+), 14 deletions(-) diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 58c0d16e..9e7fac63 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -8,7 +8,7 @@ use failure::Fail; use crate::{ project::{Project, ProjectLoadFuzzyError}, - web::Server, + web::LiveServer, imfs::FsError, live_session::LiveSession, }; @@ -45,7 +45,7 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { info!("Using project {:#?}", project); let live_session = Arc::new(LiveSession::new(Arc::clone(&project))?); - let server = Server::new(Arc::clone(&live_session)); + let server = LiveServer::new(live_session); let port = options.port .or(project.serve_port) @@ -53,7 +53,7 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { println!("Rojo server listening on port {}", port); - server.listen(port); + server.start(port); Ok(()) } \ No newline at end of file diff --git a/server/src/web/api.rs b/server/src/web/api.rs index 9b1950c9..239bf994 100644 --- a/server/src/web/api.rs +++ b/server/src/web/api.rs @@ -7,6 +7,11 @@ use std::{ sync::{mpsc, Arc}, }; +use futures::{future, Future}; +use hyper::{ + service::Service, + Body, +}; use serde_derive::{Serialize, Deserialize}; use rouille::{ self, @@ -83,6 +88,17 @@ pub struct ApiServer { server_version: &'static str, } +impl Service for ApiServer { + type ReqBody = Body; + type ResBody = Body; + type Error = hyper::Error; + type Future = Box, Error = Self::Error> + Send>; + + fn call(&mut self, request: hyper::Request) -> Self::Future { + Box::new(future::ok(hyper::Response::new(Body::from("Hello, from API!")))) + } +} + impl ApiServer { pub fn new(live_session: Arc) -> ApiServer { ApiServer { diff --git a/server/src/web/interface.rs b/server/src/web/interface.rs index 24f8b6d0..1734a5d0 100644 --- a/server/src/web/interface.rs +++ b/server/src/web/interface.rs @@ -2,6 +2,11 @@ use std::sync::Arc; +use futures::{future, Future}; +use hyper::{ + service::Service, + Body, +}; use rouille::{ self, router, @@ -22,6 +27,17 @@ pub struct InterfaceServer { server_version: &'static str, } +impl Service for InterfaceServer { + type ReqBody = Body; + type ResBody = Body; + type Error = hyper::Error; + type Future = Box, Error = Self::Error> + Send>; + + fn call(&mut self, request: hyper::Request) -> Self::Future { + Box::new(future::ok(hyper::Response::new(Body::from("Hello, from interface!")))) + } +} + impl InterfaceServer { pub fn new(live_session: Arc) -> InterfaceServer { InterfaceServer { diff --git a/server/src/web/mod.rs b/server/src/web/mod.rs index 8e4e2978..3c3454d5 100644 --- a/server/src/web/mod.rs +++ b/server/src/web/mod.rs @@ -14,6 +14,7 @@ use hyper::{ Body, Request, Response, + Server, }; use crate::{ @@ -25,38 +26,53 @@ use self::{ interface::InterfaceServer, }; -pub struct Server { +pub struct RootService { api: api::ApiServer, interface: interface::InterfaceServer, } -struct Blah; - -impl Service for Blah { +impl Service for RootService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; type Future = Box, Error = Self::Error> + Send>; fn call(&mut self, request: Request) -> Self::Future { - Box::new(future::ok(Response::new(Body::from("Hello, world!")))) + if request.uri().path().starts_with("/api") { + self.api.call(request) + } else { + self.interface.call(request) + } } } -impl Server { - pub fn new(live_session: Arc) -> Server { - Server { +impl RootService { + pub fn new(live_session: Arc) -> RootService { + RootService { api: ApiServer::new(Arc::clone(&live_session)), interface: InterfaceServer::new(Arc::clone(&live_session)), } } +} - pub fn listen(self, port: u16) { +pub struct LiveServer { + live_session: Arc, +} + +impl LiveServer { + pub fn new(live_session: Arc) -> LiveServer { + LiveServer { + live_session, + } + } + + pub fn start(self, port: u16) { let address = ([127, 0, 0, 1], port).into(); - let server = hyper::Server::bind(&address) + let server = Server::bind(&address) .serve(move || { - let service: FutureResult = future::ok(Blah); + let service: FutureResult = + future::ok(RootService::new(Arc::clone(&self.live_session))); service }) .map_err(|e| eprintln!("Server error: {}", e)); From c9a663ed3971ed1159f7aa6c30373cdf5b66efd3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 22 Feb 2019 15:11:27 -0800 Subject: [PATCH 0449/1504] Remove Rouille and port everything to Hyper --- Cargo.lock | 265 ------------------------------------ server/Cargo.toml | 1 - server/src/lib.rs | 3 +- server/src/web/api.rs | 121 ++++++++++------ server/src/web/interface.rs | 82 ++++++----- server/src/web/mod.rs | 16 +-- server/src/web_util.rs | 43 ------ 7 files changed, 132 insertions(+), 399 deletions(-) delete mode 100644 server/src/web_util.rs diff --git a/Cargo.lock b/Cargo.lock index 108ee0c8..f8a56af5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,11 +35,6 @@ dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ascii" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "atty" version = "0.2.11" @@ -77,15 +72,6 @@ dependencies = [ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "base64" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "base64" version = "0.10.1" @@ -104,38 +90,6 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "brotli-sys" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "brotli2" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "buf_redux" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "build_const" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bytecount" version = "0.4.0" @@ -177,21 +131,6 @@ name = "cfg-if" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "chrono" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "chunked_transfer" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "clap" version = "2.32.0" @@ -231,14 +170,6 @@ dependencies = [ "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "crc" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crc32fast" version = "1.1.2" @@ -320,16 +251,6 @@ dependencies = [ "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "deflate" -version = "0.7.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "difference" version = "2.0.0" @@ -467,14 +388,6 @@ name = "glob" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "gzip-header" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "h2" version = "0.1.16" @@ -652,14 +565,6 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "log" version = "0.4.6" @@ -697,14 +602,6 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "memchr" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "memchr" version = "2.1.3" @@ -719,14 +616,6 @@ name = "memoffset" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "mime" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "mime" version = "0.3.13" @@ -735,17 +624,6 @@ dependencies = [ "unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "mime_guess" -version = "1.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "mime_guess" version = "2.0.0-alpha.6" @@ -797,22 +675,6 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "multipart" -version = "0.13.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", - "safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "native-tls" version = "0.2.2" @@ -863,19 +725,6 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num-integer" -version = "0.1.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-traits" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "num_cpus" version = "1.9.0" @@ -1060,16 +909,6 @@ dependencies = [ "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand" -version = "0.3.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand" version = "0.4.5" @@ -1345,7 +1184,6 @@ dependencies = [ "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1358,30 +1196,6 @@ dependencies = [ name = "rojo-e2e" version = "0.1.0" -[[package]] -name = "rouille" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)", - "brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rustc-demangle" version = "0.1.13" @@ -1400,16 +1214,6 @@ name = "ryu" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "safemem" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "safemem" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "same-file" version = "1.0.4" @@ -1503,11 +1307,6 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "sha1" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "siphasher" version = "0.2.3" @@ -1607,15 +1406,6 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "term" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "termcolor" version = "1.0.4" @@ -1650,14 +1440,6 @@ dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "threadpool" -version = "1.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "time" version = "0.1.42" @@ -1668,18 +1450,6 @@ dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "tiny_http" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)", - "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "tokio" version = "0.1.15" @@ -1788,14 +1558,6 @@ name = "try-lock" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "twoway" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ucd-util" version = "0.1.3" @@ -1981,32 +1743,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum ascii 0.8.7 (registry+https://github.com/rust-lang/crates.io-index)" = "97be891acc47ca214468e09425d02cef3af2c94d0d82081cd02061f996802f14" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" "checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum base64 0.9.3 (registry+https://github.com/rust-lang/crates.io-index)" = "489d6c0ed21b11d038c31b6ceccca973e65d73ba3bd8ecb9a2babf5546164643" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" -"checksum brotli-sys 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4445dea95f4c2b41cde57cc9fee236ae4dbae88d8fcbdb4750fc1bb5d86aaecd" -"checksum brotli2 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0cb036c3eade309815c15ddbacec5b22c4d1f3983a774ab2eac2e3e9ea85568e" -"checksum buf_redux 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b9279646319ff816b05fb5897883ece50d7d854d12b59992683d4f8a71b0f949" -"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" "checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" -"checksum chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "45912881121cb26fad7c38c17ba7daa18764771836b34fab7d3fbd93ed633878" -"checksum chunked_transfer 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "498d20a7aaf62625b9bf26e637cf7736417cde1d0c99f1d04d1170229a85cf87" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" -"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" "checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" "checksum crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "137bc235f622ffaa0428e3854e24acb53291fc0b3ff6fb2cb75a8be6fb02f06b" @@ -2015,7 +1768,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a" "checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" -"checksum deflate 0.7.19 (registry+https://github.com/rust-lang/crates.io-index)" = "8a6abb26e16e8d419b5c78662aa9f82857c2386a073da266840e474d5055ec86" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7" @@ -2034,7 +1786,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum gzip-header 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9e59524a909fe98bb6c6f2cf1f27f2f6772887a496bf4c68cae0d94f884586" "checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" "checksum http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1a10e5b573b9a0146545010f50772b9e8b1dd0a256564cc4307694c68832a2f5" @@ -2054,29 +1805,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" "checksum libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "bff3ac7d6f23730d3b533c35ed75eef638167634476a499feef16c428d74b57b" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" "checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" -"checksum mime 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ba626b8a6de5da682e1caa06bdb42a335aee5a84db8e5046a3e8ab17ba0a3ae0" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" -"checksum mime_guess 1.8.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2d4c0961143b8efdcfa29c3ae63281601b446a4a668165454b6c90f8024954c5" "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum multipart 0.13.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92f54eb45230c3aa20864ccf0c277eeaeadcf5e437e91731db498dbf7fbe0ec6" "checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum notify 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c968cf37cf949114b00d51b0b23536d1c3a4a3963767cf4c969c65a6af78dc7d" -"checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea" -"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" "checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" @@ -2099,7 +1843,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" -"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" "checksum rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dee497e66d8d76bf08ce20c8d36e16f93749ab0bf89975b4f8ae5cee660c2da2" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3906503e80ac6cbcacb2c2973fa8e473f24d7e2747c8c92bb230c2441cad96b5" @@ -2124,12 +1867,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "09d6e187a58d923ee132fcda141c94e716bcfe301c2ea2bef5c81536e0085376" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" -"checksum rouille 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0845b9c39ba772da769fe2aaa4d81bfd10695a7ea051d0510702260ff4159841" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" -"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" -"checksum safemem 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8dca453248a96cb0749e36ccdfe2b0b4e54a61bfef89fb97ec621eb8e0a93dd9" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" @@ -2141,7 +1881,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "a915306b0f1ac5607797697148c223bedeaa36bcc2e28a01441cd638cc6567b4" "checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" "checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" -"checksum sha1 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2579985fda508104f7587689507983eadd6a6e84dd35d6d115361f530916fa0d" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" @@ -2154,14 +1893,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" -"checksum term 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5e6b677dd1e8214ea1ef4297f85dbcbed8e8cdddb561040cc998ca2551c37561" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" -"checksum threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e2f0c90a5f3459330ac8bc0d2f879c693bb7a2f59689c1083fc4ef83834da865" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tiny_http 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1661fa0a44c95d01604bd05c66732a446c657efb62b5164a7a083a3b552b4951" "checksum tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "e0500b88064f08bebddd0c0bed39e19f5c567a5f30975bee52b0c0d3e2eeb38c" "checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" "checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" @@ -2171,7 +1907,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c3fd86cb15547d02daa2b21aadaf4e37dee3368df38a526178a5afa3c034d2fb" "checksum tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "21c04a314a1f69f73c0227beba6250e06cdc1e9a62e7eff912bf54a59b6d1b94" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum twoway 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90" diff --git a/server/Cargo.toml b/server/Cargo.toml index 344bc01e..c5b3ddd2 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -32,7 +32,6 @@ rbx_xml = "0.3.0" regex = "1.0" reqwest = "0.9.5" ritz = "0.1.0" -rouille = "2.1" serde = "1.0" serde_derive = "1.0" serde_json = "1.0" diff --git a/server/src/lib.rs b/server/src/lib.rs index 1f4fa5f1..dbcb8c66 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -18,5 +18,4 @@ pub mod rbx_snapshot; pub mod session_id; pub mod snapshot_reconciler; pub mod visualize; -pub mod web; -pub mod web_util; \ No newline at end of file +pub mod web; \ No newline at end of file diff --git a/server/src/web/api.rs b/server/src/web/api.rs index 239bf994..deb6efb4 100644 --- a/server/src/web/api.rs +++ b/server/src/web/api.rs @@ -10,15 +10,14 @@ use std::{ use futures::{future, Future}; use hyper::{ service::Service, + StatusCode, + header, + Method, Body, -}; -use serde_derive::{Serialize, Deserialize}; -use rouille::{ - self, - router, Request, Response, }; +use serde_derive::{Serialize, Deserialize}; use rbx_dom_weak::{RbxId, RbxInstance}; use crate::{ @@ -83,57 +82,66 @@ pub struct SubscribeResponse<'a> { pub messages: Cow<'a, [InstanceChanges]>, } -pub struct ApiServer { +fn response_json(value: T) -> Response { + let serialized = match serde_json::to_string(&value) { + Ok(v) => v, + Err(err) => { + return Response::builder() + .status(StatusCode::BAD_REQUEST) + .header(header::CONTENT_TYPE, "text/plain") + .body(Body::from(err.to_string())) + .unwrap(); + }, + }; + + Response::builder() + .header(header::CONTENT_TYPE, "application/json") + .body(Body::from(serialized)) + .unwrap() +} + +pub struct ApiService { live_session: Arc, server_version: &'static str, } -impl Service for ApiServer { +impl Service for ApiService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; - type Future = Box, Error = Self::Error> + Send>; + type Future = Box, Error = Self::Error> + Send>; fn call(&mut self, request: hyper::Request) -> Self::Future { - Box::new(future::ok(hyper::Response::new(Body::from("Hello, from API!")))) + let response = match (request.method(), request.uri().path()) { + (&Method::GET, "/api/rojo") => self.handle_api_rojo(), + (&Method::GET, path) if path.starts_with("/api/subscribe/") => self.handle_api_subscribe(request), + (&Method::GET, path) if path.starts_with("/api/read/") => self.handle_api_read(request), + _ => { + Response::builder() + .status(StatusCode::NOT_FOUND) + .body(Body::empty()) + .unwrap() + }, + }; + + Box::new(future::ok(response)) } } -impl ApiServer { - pub fn new(live_session: Arc) -> ApiServer { - ApiServer { +impl ApiService { + pub fn new(live_session: Arc) -> ApiService { + ApiService { live_session, server_version: env!("CARGO_PKG_VERSION"), } } - #[allow(unreachable_code)] - pub fn handle_request(&self, request: &Request) -> Response { - router!(request, - (GET) (/api/rojo) => { - self.handle_api_rojo() - }, - (GET) (/api/subscribe/{ cursor: u32 }) => { - self.handle_api_subscribe(cursor) - }, - (GET) (/api/read/{ id_list: String }) => { - let requested_ids: Option> = id_list - .split(',') - .map(RbxId::parse_str) - .collect(); - - self.handle_api_read(requested_ids) - }, - _ => Response::empty_404() - ) - } - /// Get a summary of information about the server - fn handle_api_rojo(&self) -> Response { + fn handle_api_rojo(&self) -> Response { let rbx_session = self.live_session.rbx_session.lock().unwrap(); let tree = rbx_session.get_tree(); - Response::json(&ServerInfoResponse { + response_json(&ServerInfoResponse { server_version: self.server_version, protocol_version: 2, session_id: self.live_session.session_id, @@ -144,7 +152,19 @@ impl ApiServer { /// Retrieve any messages past the given cursor index, and if /// there weren't any, subscribe to receive any new messages. - fn handle_api_subscribe(&self, cursor: u32) -> Response { + fn handle_api_subscribe(&self, request: Request) -> Response { + let argument = &request.uri().path()["/api/subscribe".len()..]; + let cursor: u32 = match argument.parse() { + Ok(v) => v, + Err(err) => { + return Response::builder() + .status(StatusCode::BAD_REQUEST) + .header(header::CONTENT_TYPE, "text/plain") + .body(Body::from(err.to_string())) + .unwrap(); + }, + }; + let message_queue = Arc::clone(&self.live_session.message_queue); // Did the client miss any messages since the last subscribe? @@ -152,7 +172,7 @@ impl ApiServer { let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); if !new_messages.is_empty() { - return Response::json(&SubscribeResponse { + return response_json(&SubscribeResponse { session_id: self.live_session.session_id, messages: Cow::Borrowed(&new_messages), message_cursor: new_cursor, @@ -160,13 +180,16 @@ impl ApiServer { } } + // TOOD: Switch to futures mpsc instead to not block this task let (tx, rx) = mpsc::channel(); - let sender_id = message_queue.subscribe(tx); match rx.recv() { Ok(_) => (), - Err(_) => return Response::text("error!").with_status_code(500), + Err(_) => return Response::builder() + .status(500) + .body(Body::from("error!")) + .unwrap(), } message_queue.unsubscribe(sender_id); @@ -174,7 +197,7 @@ impl ApiServer { { let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); - return Response::json(&SubscribeResponse { + return response_json(&SubscribeResponse { session_id: self.live_session.session_id, messages: Cow::Owned(new_messages), message_cursor: new_cursor, @@ -182,12 +205,24 @@ impl ApiServer { } } - fn handle_api_read(&self, requested_ids: Option>) -> Response { + fn handle_api_read(&self, request: Request) -> Response { + let argument = &request.uri().path()["/api/subscribe".len()..]; + let requested_ids: Option> = argument + .split(',') + .map(RbxId::parse_str) + .collect(); + let message_queue = Arc::clone(&self.live_session.message_queue); let requested_ids = match requested_ids { Some(id) => id, - None => return rouille::Response::text("Malformed ID list").with_status_code(400), + None => { + return Response::builder() + .status(StatusCode::BAD_REQUEST) + .header(header::CONTENT_TYPE, "text/plain") + .body(Body::from("Malformed ID list")) + .unwrap(); + }, }; let rbx_session = self.live_session.rbx_session.lock().unwrap(); @@ -219,7 +254,7 @@ impl ApiServer { } } - Response::json(&ReadResponse { + response_json(&ReadResponse { session_id: self.live_session.session_id, message_cursor, instances, diff --git a/server/src/web/interface.rs b/server/src/web/interface.rs index 1734a5d0..4015f933 100644 --- a/server/src/web/interface.rs +++ b/server/src/web/interface.rs @@ -5,15 +5,14 @@ use std::sync::Arc; use futures::{future, Future}; use hyper::{ service::Service, + header, Body, -}; -use rouille::{ - self, - router, + Method, + StatusCode, Request, Response, }; -use ritz::{html}; +use ritz::html; use crate::{ live_session::LiveSession, @@ -22,47 +21,41 @@ use crate::{ static HOME_CSS: &str = include_str!("../../assets/index.css"); -pub struct InterfaceServer { +pub struct InterfaceService { live_session: Arc, server_version: &'static str, } -impl Service for InterfaceServer { +impl Service for InterfaceService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; - type Future = Box, Error = Self::Error> + Send>; + type Future = Box, Error = Self::Error> + Send>; - fn call(&mut self, request: hyper::Request) -> Self::Future { - Box::new(future::ok(hyper::Response::new(Body::from("Hello, from interface!")))) + fn call(&mut self, request: Request) -> Self::Future { + let response = match (request.method(), request.uri().path()) { + (&Method::GET, "/") => self.handle_home(), + (&Method::GET, "/visualize/rbx") => self.handle_visualize_rbx(), + (&Method::GET, "/visualize/imfs") => self.handle_visualize_imfs(), + _ => Response::builder() + .status(StatusCode::NOT_FOUND) + .body(Body::empty()) + .unwrap(), + }; + + Box::new(future::ok(response)) } } -impl InterfaceServer { - pub fn new(live_session: Arc) -> InterfaceServer { - InterfaceServer { +impl InterfaceService { + pub fn new(live_session: Arc) -> InterfaceService { + InterfaceService { live_session, server_version: env!("CARGO_PKG_VERSION"), } } - #[allow(unreachable_code)] - pub fn handle_request(&self, request: &Request) -> Response { - router!(request, - (GET) (/) => { - self.handle_home() - }, - (GET) (/visualize/rbx) => { - self.handle_visualize_rbx() - }, - (GET) (/visualize/imfs) => { - self.handle_visualize_imfs() - }, - _ => Response::empty_404() - ) - } - - fn handle_home(&self) -> Response { + fn handle_home(&self) -> Response { let page = html! { @@ -88,26 +81,41 @@ impl InterfaceServer { }; - Response::html(format!("{}", page)) + Response::builder() + .header(header::CONTENT_TYPE, "text/html") + .body(Body::from(format!("{}", page))) + .unwrap() } - fn handle_visualize_rbx(&self) -> Response { + fn handle_visualize_rbx(&self) -> Response { let rbx_session = self.live_session.rbx_session.lock().unwrap(); let dot_source = format!("{}", VisualizeRbxSession(&rbx_session)); match graphviz_to_svg(&dot_source) { - Some(svg) => Response::svg(svg), - None => Response::text(dot_source), + Some(svg) => Response::builder() + .header(header::CONTENT_TYPE, "image/svg+xml") + .body(Body::from(svg)) + .unwrap(), + None => Response::builder() + .header(header::CONTENT_TYPE, "text/plain") + .body(Body::from(dot_source)) + .unwrap(), } } - fn handle_visualize_imfs(&self) -> Response { + fn handle_visualize_imfs(&self) -> Response { let imfs = self.live_session.imfs.lock().unwrap(); let dot_source = format!("{}", VisualizeImfs(&imfs)); match graphviz_to_svg(&dot_source) { - Some(svg) => Response::svg(svg), - None => Response::text(dot_source), + Some(svg) => Response::builder() + .header(header::CONTENT_TYPE, "image/svg+xml") + .body(Body::from(svg)) + .unwrap(), + None => Response::builder() + .header(header::CONTENT_TYPE, "text/plain") + .body(Body::from(dot_source)) + .unwrap(), } } } \ No newline at end of file diff --git a/server/src/web/mod.rs b/server/src/web/mod.rs index 3c3454d5..35be0e3b 100644 --- a/server/src/web/mod.rs +++ b/server/src/web/mod.rs @@ -22,20 +22,20 @@ use crate::{ }; use self::{ - api::ApiServer, - interface::InterfaceServer, + api::ApiService, + interface::InterfaceService, }; pub struct RootService { - api: api::ApiServer, - interface: interface::InterfaceServer, + api: api::ApiService, + interface: interface::InterfaceService, } impl Service for RootService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; - type Future = Box, Error = Self::Error> + Send>; + type Future = Box, Error = Self::Error> + Send>; fn call(&mut self, request: Request) -> Self::Future { if request.uri().path().starts_with("/api") { @@ -49,8 +49,8 @@ impl Service for RootService { impl RootService { pub fn new(live_session: Arc) -> RootService { RootService { - api: ApiServer::new(Arc::clone(&live_session)), - interface: InterfaceServer::new(Arc::clone(&live_session)), + api: ApiService::new(Arc::clone(&live_session)), + interface: InterfaceService::new(Arc::clone(&live_session)), } } } @@ -71,7 +71,7 @@ impl LiveServer { let server = Server::bind(&address) .serve(move || { - let service: FutureResult = + let service: FutureResult<_, hyper::Error> = future::ok(RootService::new(Arc::clone(&self.live_session))); service }) diff --git a/server/src/web_util.rs b/server/src/web_util.rs deleted file mode 100644 index a6aea450..00000000 --- a/server/src/web_util.rs +++ /dev/null @@ -1,43 +0,0 @@ -use std::io::Read; - -use rouille; -use serde; -use serde_json; - -static MAX_BODY_SIZE: usize = 100 * 1024 * 1024; // 100 MiB - -/// Pulls text that may be JSON out of a Rouille Request object. -/// -/// Doesn't do any actual parsing -- all this method does is verify the content -/// type of the request and read the request's body. -fn read_json_text(request: &rouille::Request) -> Option { - // Bail out if the request body isn't marked as JSON - let content_type = request.header("Content-Type")?; - - if !content_type.starts_with("application/json") { - return None; - } - - let body = request.data()?; - - // Allocate a buffer and read up to MAX_BODY_SIZE+1 bytes into it. - let mut out = Vec::new(); - body.take(MAX_BODY_SIZE.saturating_add(1) as u64).read_to_end(&mut out).ok()?; - - // If the body was too big (MAX_BODY_SIZE+1), we abort instead of trying to - // process it. - if out.len() > MAX_BODY_SIZE { - return None; - } - - String::from_utf8(out).ok() -} - -/// Reads the body out of a Rouille Request and attempts to turn it into JSON. -pub fn read_json(request: &rouille::Request) -> Option -where - T: serde::de::DeserializeOwned, -{ - let body = read_json_text(&request)?; - serde_json::from_str(&body).ok()? -} \ No newline at end of file From 4f31c9e72f5957c2e04d6d16baa06c3c6c217ca1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 22 Feb 2019 15:56:24 -0800 Subject: [PATCH 0450/1504] Fix /api/read and /api/subscribe, re-add debug output --- server/src/web/api.rs | 6 +++--- server/src/web/mod.rs | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/server/src/web/api.rs b/server/src/web/api.rs index deb6efb4..2bbc96f2 100644 --- a/server/src/web/api.rs +++ b/server/src/web/api.rs @@ -10,8 +10,8 @@ use std::{ use futures::{future, Future}; use hyper::{ service::Service, - StatusCode, header, + StatusCode, Method, Body, Request, @@ -153,7 +153,7 @@ impl ApiService { /// Retrieve any messages past the given cursor index, and if /// there weren't any, subscribe to receive any new messages. fn handle_api_subscribe(&self, request: Request) -> Response { - let argument = &request.uri().path()["/api/subscribe".len()..]; + let argument = &request.uri().path()["/api/subscribe/".len()..]; let cursor: u32 = match argument.parse() { Ok(v) => v, Err(err) => { @@ -206,7 +206,7 @@ impl ApiService { } fn handle_api_read(&self, request: Request) -> Response { - let argument = &request.uri().path()["/api/subscribe".len()..]; + let argument = &request.uri().path()["/api/read/".len()..]; let requested_ids: Option> = argument .split(',') .map(RbxId::parse_str) diff --git a/server/src/web/mod.rs b/server/src/web/mod.rs index 35be0e3b..cd01f8d7 100644 --- a/server/src/web/mod.rs +++ b/server/src/web/mod.rs @@ -5,6 +5,7 @@ mod interface; use std::sync::Arc; +use log::trace; use futures::{ future::{self, FutureResult}, Future, @@ -38,6 +39,8 @@ impl Service for RootService { type Future = Box, Error = Self::Error> + Send>; fn call(&mut self, request: Request) -> Self::Future { + trace!("{} {}", request.method(), request.uri().path()); + if request.uri().path().starts_with("/api") { self.api.call(request) } else { From 7f324f19579fb6aa69d51994ad3a2ad00f391c05 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 22 Feb 2019 15:57:46 -0800 Subject: [PATCH 0451/1504] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f82530f..c2dff637 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Added support for non-primitive types in the Rojo plugin. * Types like `Color3` and `CFrame` can now be updated live! * Fixed plugin assets flashing in on first load ([#121](https://github.com/LPGhatguy/rojo/issues/121)) +* Changed Rojo's HTTP server from Rouille to Hyper, which reduced the release size by around a megabyte. ## [0.5.0 Alpha 4](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.4) (February 8, 2019) * Added support for nested partitions ([#102](https://github.com/LPGhatguy/rojo/issues/102)) From 88e739090daca335c31f49ce02ef03aab61b47cd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 24 Feb 2019 00:31:58 -0800 Subject: [PATCH 0452/1504] WIP: Server plugins via rlua (Lua 5.3) (#125) * Add 'plugins' field to project and add rlua * Scaffold out new SnapshotContext type (again) with plugin state * Almost functional snapshot system with rlua proof-of-concept * Gate plugin config on 'plugins-enabled' feature, tell Travis to test all features * Guard remaining plugin setup code behind feature * Bump minimum version to 1.33, should've caught this before * Whoops, latest Rust is 1.32, not 1.33 --- .travis.yml | 7 +- Cargo.lock | 449 +++++++++++++++--------------- README.md | 2 +- server/Cargo.toml | 5 + server/src/project.rs | 59 +++- server/src/rbx_session.rs | 60 +++- server/src/rbx_snapshot.rs | 88 +++++- server/src/snapshot_reconciler.rs | 18 +- server/tests/read_projects.rs | 1 + server/tests/snapshots.rs | 8 +- 10 files changed, 445 insertions(+), 252 deletions(-) diff --git a/.travis.yml b/.travis.yml index 34e0a69e..f974e23f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -26,11 +26,12 @@ matrix: - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install - language: rust - rust: 1.31.1 + rust: 1.32.0 cache: cargo script: - cargo test --verbose + - cargo test --verbose --all-features - language: rust rust: stable @@ -38,10 +39,12 @@ matrix: script: - cargo test --verbose + - cargo test --verbose --all-features - language: rust rust: beta cache: cargo script: - - cargo test --verbose \ No newline at end of file + - cargo test --verbose + - cargo test --verbose --all-features \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index f8a56af5..f3cc9caf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,7 +3,7 @@ name = "MacTypes-sys" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -13,10 +13,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "aho-corasick" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -40,7 +40,7 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -52,13 +52,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -68,8 +68,8 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -116,14 +116,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -159,7 +159,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -167,7 +167,7 @@ name = "core-foundation-sys" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -184,24 +184,22 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-channel" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -209,18 +207,18 @@ name = "crossbeam-deque" version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -228,10 +226,11 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -240,7 +239,7 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -248,7 +247,7 @@ name = "csv-core" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -263,7 +262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "encoding_rs" -version = "0.8.14" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -286,7 +285,7 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -294,7 +293,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -303,7 +302,7 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -315,7 +314,7 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -344,7 +343,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -352,9 +351,14 @@ name = "fsevent-sys" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -380,7 +384,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -397,7 +401,7 @@ dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -412,7 +416,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "http" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -435,14 +439,14 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.23" +version = "0.12.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -455,7 +459,7 @@ dependencies = [ "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -466,7 +470,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.23 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -492,12 +496,8 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -505,7 +505,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -513,7 +513,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -543,12 +543,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.48" +version = "0.2.49" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libflate" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -578,7 +578,7 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -588,8 +588,8 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -604,11 +604,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "2.1.3" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -645,7 +644,7 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -681,15 +680,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.18 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.41 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -698,7 +697,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -709,7 +708,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "notify" -version = "4.0.7" +version = "4.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -718,32 +717,37 @@ dependencies = [ "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-traits" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "num_cpus" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl" -version = "0.10.16" +version = "0.10.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -753,11 +757,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.40" +version = "0.9.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -784,10 +788,10 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -806,7 +810,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -839,7 +843,7 @@ version = "0.7.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -870,7 +874,7 @@ name = "proc-macro-hack" version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -882,7 +886,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -906,16 +910,16 @@ name = "quote" version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -923,28 +927,17 @@ dependencies = [ [[package]] name = "rand" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "rand" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -959,14 +952,6 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand_core" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand_core" version = "0.3.1" @@ -996,15 +981,25 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_jitter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_os" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1042,9 +1037,9 @@ name = "rbx_dom_weak" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1087,16 +1082,16 @@ name = "regex" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1112,31 +1107,31 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.16 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.23 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "libflate 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1156,11 +1151,22 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rlua" +version = "0.16.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rojo" version = "0.5.0-alpha.4" @@ -1170,25 +1176,26 @@ dependencies = [ "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.23 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1219,7 +1226,7 @@ name = "same-file" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1243,7 +1250,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1254,7 +1261,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1263,7 +1270,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1273,27 +1280,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.85" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.85" +version = "1.0.88" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1303,7 +1310,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1322,7 +1329,7 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1334,18 +1341,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.8" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "snax" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1368,7 +1372,7 @@ name = "syn" version = "0.15.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1378,7 +1382,7 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1389,18 +1393,18 @@ name = "tempdir" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tempfile" -version = "3.0.5" +version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1419,7 +1423,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1445,7 +1449,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1458,13 +1462,13 @@ dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1481,7 +1485,7 @@ name = "tokio-executor" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1500,12 +1504,12 @@ name = "tokio-reactor" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1531,23 +1535,23 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1592,7 +1596,7 @@ name = "unicode-normalization" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1605,14 +1609,6 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "url" version = "1.7.2" @@ -1630,11 +1626,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uuid" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1652,11 +1648,6 @@ name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "walkdir" version = "2.2.7" @@ -1664,7 +1655,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1703,7 +1694,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1720,7 +1711,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1740,12 +1731,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" -"checksum aho-corasick 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "1e9a933f4e58658d7b12defcf96dc5c720f20832deebe3e0a19efd3b6aaeeb9e" +"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "b5b493b66e03090ebc4343eb02f94ff944e0cbc9ac6571491d170ba026741eb5" +"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" @@ -1754,7 +1745,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cc 1.0.28 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4a8b715cb4597106ea87c7c84b2f1d452c7492033765df7f32651e66fcf749" +"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -1762,15 +1753,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" "checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" "checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" -"checksum crossbeam-channel 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "137bc235f622ffaa0428e3854e24acb53291fc0b3ff6fb2cb75a8be6fb02f06b" +"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" "checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" -"checksum crossbeam-epoch 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f10a4f8f409aaac4b16a5474fb233624238fcdeefb9ba50d5ea059aab63ba31c" -"checksum crossbeam-utils 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "41ee4864f4797060e52044376f7d107429ce1fb43460021b126424b7180ee21a" +"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" -"checksum encoding_rs 0.8.14 (registry+https://github.com/rust-lang/crates.io-index)" = "a69d152eaa438a291636c1971b0a370212165ca8a75759eb66818c5ce9b538f7" +"checksum encoding_rs 0.8.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0535f350c60aac0b87ccf28319abc749391e912192255b0c00a2c12c6917bd73" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" @@ -1781,6 +1772,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05" "checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874" +"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" @@ -1788,10 +1780,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" -"checksum http 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "1a10e5b573b9a0146545010f50772b9e8b1dd0a256564cc4307694c68832a2f5" +"checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.12.23 (registry+https://github.com/rust-lang/crates.io-index)" = "860faf61a9957c9cb0e23e69f1c8290e92f6eb660fcdd1f2d6777043a2ae1a46" +"checksum hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)" = "fdfa9b401ef6c4229745bb6e9b2529192d07b920eed624cdee2a82348cd550af" "checksum hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd73f14ad370d3b4d4b7dce08f69b81536c82e39fcc89731930fe5788cd661" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" @@ -1802,15 +1794,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.48 (registry+https://github.com/rust-lang/crates.io-index)" = "e962c7641008ac010fa60a7dfdc1712449f29c44ef2d4702394aea943ee75047" -"checksum libflate 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "bff3ac7d6f23730d3b533c35ed75eef638167634476a499feef16c428d74b57b" +"checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" +"checksum libflate 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "54d1ddf9c52870243c5689d7638d888331c1116aa5b398f3ba1acfa7d8758ca1" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum memchr 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e1dd4eaac298c32ce07eb6ed9242eda7d82955b9170b7d6db59b2e02cc63fcb8" +"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" @@ -1820,11 +1812,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum notify 4.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c968cf37cf949114b00d51b0b23536d1c3a4a3963767cf4c969c65a6af78dc7d" -"checksum num_cpus 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5a69d464bdc213aaaff628444e99578ede64e9c854025aa43b9796530afa9238" -"checksum openssl 0.10.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ec7bd7ca4cce6dbdc77e7c1230682740d307d1218a87fb0349a571272be749f9" +"checksum notify 4.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9cc7ed2bd4b7edad3ee93b659c38e53dabb619f7274e127a0fab054ad2bb998d" +"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" +"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum openssl 0.10.18 (registry+https://github.com/rust-lang/crates.io-index)" = "b90119d71b0a3596588da04bf7c2c42f2978cfa1217a94119d8ec9e963c7729c" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.40 (registry+https://github.com/rust-lang/crates.io-index)" = "1bb974e77de925ef426b6bc82fce15fd45bdcbeb5728bffcfc7cdeeb7ce1c2d6" +"checksum openssl-sys 0.9.41 (registry+https://github.com/rust-lang/crates.io-index)" = "e4c77cdd67d31759b22aa72cfda3c65c12348f9e6c5420946b403c022fd0311a" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" @@ -1839,20 +1832,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" "checksum proc-macro-nested 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9968e025d6368d1273a93bc23051e30dbf5482475e716d7385d8ec8fbd5b5b6" -"checksum proc-macro2 0.4.26 (registry+https://github.com/rust-lang/crates.io-index)" = "38fddd23d98b2144d197c0eca5705632d4fe2667d14a6be5df8934f8d74f1978" +"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" -"checksum rand 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "dee497e66d8d76bf08ce20c8d36e16f93749ab0bf89975b4f8ae5cee660c2da2" -"checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" -"checksum rand 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3906503e80ac6cbcacb2c2973fa8e473f24d7e2747c8c92bb230c2441cad96b5" +"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_os 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f46fbd5550acf75b0c2730f5dd1873751daf9beb8f11b44027778fae50d7feca" +"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c4d3bffbec1f20f66684448e46ef45dad2fbf1185c3d8f3e29018f027484ffc" @@ -1862,11 +1854,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" -"checksum regex-syntax 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4e47a2ed29da7a9e1960e1639e7a982e6edc6d49be308a3b02daf511504a16d1" +"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.9 (registry+https://github.com/rust-lang/crates.io-index)" = "09d6e187a58d923ee132fcda141c94e716bcfe301c2ea2bef5c81536e0085376" +"checksum reqwest 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f205a95638627fc0d21c53901671b06f439dc2830311ff11ecdff34ae2d839a8" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" +"checksum rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "51acb42c134a6568911a2aef2cea5feb80503804cc8986b903983ebfb1342a2c" "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" @@ -1877,14 +1870,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "534b8b91a95e0f71bca3ed5824752d558da048d4248c91af873b63bd60519752" -"checksum serde_derive 1.0.85 (registry+https://github.com/rust-lang/crates.io-index)" = "a915306b0f1ac5607797697148c223bedeaa36bcc2e28a01441cd638cc6567b4" -"checksum serde_json 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "4b90a9fbe1211e57d3e1c15670f1cb00802988fb23a1a4aad7a2b63544f1920e" +"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850" +"checksum serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4" +"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" "checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "88aea073965ab29f6edb5493faf96ad662fb18aa9eeb186a3b7057951605ed15" +"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" "checksum snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef82be0baf3ae45701ab992230f1f4889c15984736d87f37558aea3e4e321af" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" @@ -1892,7 +1885,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum tempfile 3.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "7e91405c14320e5c79b3d148e1c86f40749a36e490642202a31689cb1a3452b2" +"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" @@ -1905,7 +1898,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" "checksum tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c3fd86cb15547d02daa2b21aadaf4e37dee3368df38a526178a5afa3c034d2fb" -"checksum tokio-timer 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "21c04a314a1f69f73c0227beba6250e06cdc1e9a62e7eff912bf54a59b6d1b94" +"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" @@ -1914,21 +1907,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unreachable 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" -"checksum uuid 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dab5c5526c5caa3d106653401a267fed923e7046f35895ffcb5ca42db64942e6" +"checksum uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0238db0c5b605dd1cf51de0f21766f97fba2645897024461d6a00c036819a768" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -"checksum void 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "afc5508759c5bf4285e61feb862b6083c8480aec864fa17a81fdec6f69b461ab" +"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" diff --git a/README.md b/README.md index 458fed60..c5321cf6 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ If you use a plugin that _isn't_ Rojo for syncing code, open an issue and let me ## Contributing Pull requests are welcome! -Rojo supports Rust 1.31.1 and newer. Any changes to the minimum required compiler version require a _minor_ version bump. +Rojo supports Rust 1.32 and newer. Any changes to the minimum required compiler version require a _minor_ version bump. ## License Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file diff --git a/server/Cargo.toml b/server/Cargo.toml index c5b3ddd2..2ee9623c 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -7,6 +7,10 @@ license = "MIT" repository = "https://github.com/LPGhatguy/rojo" edition = "2018" +[features] +default = [] +server-plugins = [] + [lib] name = "librojo" path = "src/lib.rs" @@ -31,6 +35,7 @@ rbx_dom_weak = "0.3.0" rbx_xml = "0.3.0" regex = "1.0" reqwest = "0.9.5" +rlua = "0.16" ritz = "0.1.0" serde = "1.0" serde_derive = "1.0" diff --git a/server/src/project.rs b/server/src/project.rs index 6b03a176..acefea5e 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -24,6 +24,10 @@ struct SourceProject { name: String, tree: SourceProjectNode, + #[cfg_attr(not(feature = "plugins-enabled"), serde(skip_deserializing))] + #[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")] + plugins: Vec, + #[serde(skip_serializing_if = "Option::is_none")] serve_port: Option, @@ -33,12 +37,17 @@ struct SourceProject { impl SourceProject { /// Consumes the SourceProject and yields a Project, ready for prime-time. - pub fn into_project(self, project_file_location: &Path) -> Project { + pub fn into_project(mut self, project_file_location: &Path) -> Project { let tree = self.tree.into_project_node(project_file_location); + let plugins = self.plugins + .drain(..) + .map(|source_plugin| source_plugin.into_plugin(project_file_location)) + .collect(); Project { name: self.name, tree, + plugins, serve_port: self.serve_port, serve_place_ids: self.serve_place_ids, file_location: PathBuf::from(project_file_location), @@ -95,6 +104,26 @@ impl SourceProjectNode { } } +#[derive(Debug, Serialize, Deserialize)] +struct SourcePlugin { + path: String, +} + +impl SourcePlugin { + pub fn into_plugin(self, project_file_location: &Path) -> Plugin { + let path = if Path::new(&self.path).is_absolute() { + PathBuf::from(self.path) + } else { + let project_folder_location = project_file_location.parent().unwrap(); + project_folder_location.join(self.path) + }; + + Plugin { + path, + } + } +} + /// Error returned by Project::load_exact #[derive(Debug, Fail)] pub enum ProjectLoadExactError { @@ -198,10 +227,30 @@ impl ProjectNode { } } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct Plugin { + pub path: PathBuf, +} + +impl Plugin { + fn to_source_plugin(&self, project_file_location: &Path) -> SourcePlugin { + let project_folder_location = project_file_location.parent().unwrap(); + let path = match self.path.strip_prefix(project_folder_location) { + Ok(stripped) => stripped.to_str().unwrap().replace("\\", "/"), + Err(_) => format!("{}", self.path.display()), + }; + + SourcePlugin { + path, + } + } +} + #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Project { pub name: String, pub tree: ProjectNode, + pub plugins: Vec, pub serve_port: Option, pub serve_place_ids: Option>, pub file_location: PathBuf, @@ -246,6 +295,7 @@ impl Project { let project = Project { name: project_name.to_string(), tree, + plugins: Vec::new(), serve_port: None, serve_place_ids: None, file_location: project_path.clone(), @@ -274,6 +324,7 @@ impl Project { let project = Project { name: project_name.to_string(), tree, + plugins: Vec::new(), serve_port: None, serve_place_ids: None, file_location: project_path.clone(), @@ -384,9 +435,15 @@ impl Project { } fn to_source_project(&self) -> SourceProject { + let plugins = self.plugins + .iter() + .map(|plugin| plugin.to_source_plugin(&self.file_location)) + .collect(); + SourceProject { name: self.name.clone(), tree: self.tree.to_source_node(&self.file_location), + plugins, serve_port: self.serve_port, serve_place_ids: self.serve_place_ids.clone(), } diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 66b2af17..6927cff8 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -6,6 +6,7 @@ use std::{ sync::{Arc, Mutex}, }; +use rlua::Lua; use serde_derive::{Serialize, Deserialize}; use log::{info, trace}; use rbx_dom_weak::{RbxTree, RbxId}; @@ -15,7 +16,14 @@ use crate::{ message_queue::MessageQueue, imfs::{Imfs, ImfsItem}, path_map::PathMap, - rbx_snapshot::{snapshot_project_tree, snapshot_project_node, snapshot_imfs_path}, + rbx_snapshot::{ + SnapshotContext, + SnapshotPluginContext, + SnapshotPluginEntry, + snapshot_project_tree, + snapshot_project_node, + snapshot_imfs_path, + }, snapshot_reconciler::{InstanceChanges, reify_root, reconcile_subtree}, }; @@ -62,9 +70,41 @@ impl RbxSession { let mut instances_per_path = PathMap::new(); let mut metadata_per_instance = HashMap::new(); + let plugin_context = if cfg!(feature = "server-plugins") { + let lua = Lua::new(); + let mut callback_key = None; + + lua.context(|context| { + let callback = context.load(r#" + return function(snapshot) + print("got my snapshot:", snapshot) + print("name:", snapshot.name, "class name:", snapshot.className) + end"#) + .set_name("a cool plugin").unwrap() + .call::<(), rlua::Function>(()).unwrap(); + + callback_key = Some(context.create_registry_value(callback).unwrap()); + }); + + let plugins = vec![ + SnapshotPluginEntry { + file_name_filter: String::new(), + callback: callback_key.unwrap(), + } + ]; + + Some(SnapshotPluginContext { lua, plugins }) + } else { + None + }; + + let context = SnapshotContext { + plugin_context, + }; + let tree = { let temp_imfs = imfs.lock().unwrap(); - reify_initial_tree(&project, &temp_imfs, &mut instances_per_path, &mut metadata_per_instance) + reify_initial_tree(&project, &context, &temp_imfs, &mut instances_per_path, &mut metadata_per_instance) }; RbxSession { @@ -104,17 +144,21 @@ impl RbxSession { .expect("Metadata did not exist for path") .clone(); + let context = SnapshotContext { + plugin_context: None, + }; + for instance_id in &instances_at_path { let instance_metadata = self.metadata_per_instance.get(&instance_id) .expect("Metadata for instance ID did not exist"); let maybe_snapshot = match &instance_metadata.project_definition { Some((instance_name, project_node)) => { - snapshot_project_node(&imfs, &project_node, Cow::Owned(instance_name.clone())) + snapshot_project_node(&context, &imfs, &project_node, Cow::Owned(instance_name.clone())) .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())) }, None => { - snapshot_imfs_path(&imfs, &path_to_snapshot, None) + snapshot_imfs_path(&context, &imfs, &path_to_snapshot, None) .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())) }, }; @@ -202,16 +246,20 @@ impl RbxSession { pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { let mut instances_per_path = PathMap::new(); let mut metadata_per_instance = HashMap::new(); - reify_initial_tree(project, imfs, &mut instances_per_path, &mut metadata_per_instance) + let context = SnapshotContext { + plugin_context: None, + }; + reify_initial_tree(project, &context, imfs, &mut instances_per_path, &mut metadata_per_instance) } fn reify_initial_tree( project: &Project, + context: &SnapshotContext, imfs: &Imfs, instances_per_path: &mut PathMap>, metadata_per_instance: &mut HashMap, ) -> RbxTree { - let snapshot = snapshot_project_tree(imfs, project) + let snapshot = snapshot_project_tree(&context, imfs, project) .expect("Could not snapshot project tree") .expect("Project did not produce any instances"); diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index fe5443be..c3301918 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -9,6 +9,7 @@ use std::{ str, }; +use rlua::Lua; use failure::Fail; use log::info; use maplit::hashmap; @@ -38,6 +39,53 @@ const INIT_MODULE_NAME: &str = "init.lua"; const INIT_SERVER_NAME: &str = "init.server.lua"; const INIT_CLIENT_NAME: &str = "init.client.lua"; +pub struct SnapshotContext { + pub plugin_context: Option, +} + +/// Context that's only relevant to generating snapshots if there are plugins +/// associated with the project. +/// +/// It's possible that this needs some sort of extra nesting/filtering to +/// support nested projects, since their plugins should only apply to +/// themselves. +pub struct SnapshotPluginContext { + pub lua: Lua, + pub plugins: Vec, +} + +pub struct SnapshotPluginEntry { + /// Simple file name suffix filter to avoid running plugins on every file + /// change. + pub file_name_filter: String, + + /// A key into the Lua registry created by [`create_registry_value`] that + /// refers to a function that can be called to transform a file/instance + /// pair according to how the plugin needs to operate. + /// + /// [`create_registry_value`]: https://docs.rs/rlua/0.16.2/rlua/struct.Context.html#method.create_registry_value + pub callback: rlua::RegistryKey, +} + +#[derive(Debug, Clone)] +struct LuaRbxSnapshot(RbxSnapshotInstance<'static>); + +impl rlua::UserData for LuaRbxSnapshot { + fn add_methods<'lua, M: rlua::UserDataMethods<'lua, Self>>(methods: &mut M) { + methods.add_meta_method(rlua::MetaMethod::Index, |_context, this, key: String| { + match key.as_str() { + "name" => Ok(this.0.name.clone().into_owned()), + "className" => Ok(this.0.class_name.clone().into_owned()), + _ => Err(rlua::Error::RuntimeError(format!("{} is not a valid member of RbxSnapshotInstance", &key))), + } + }); + + methods.add_meta_method(rlua::MetaMethod::ToString, |_context, this, _args: ()| { + Ok("RbxSnapshotInstance") + }); + } +} + pub type SnapshotResult<'a> = Result>, SnapshotError>; #[derive(Debug, Fail)] @@ -104,19 +152,21 @@ impl fmt::Display for SnapshotError { } pub fn snapshot_project_tree<'source>( + context: &SnapshotContext, imfs: &'source Imfs, project: &'source Project, ) -> SnapshotResult<'source> { - snapshot_project_node(imfs, &project.tree, Cow::Borrowed(&project.name)) + snapshot_project_node(context, imfs, &project.tree, Cow::Borrowed(&project.name)) } pub fn snapshot_project_node<'source>( + context: &SnapshotContext, imfs: &'source Imfs, node: &ProjectNode, instance_name: Cow<'source, str>, ) -> SnapshotResult<'source> { let maybe_snapshot = match &node.path { - Some(path) => snapshot_imfs_path(imfs, &path, Some(instance_name.clone()))?, + Some(path) => snapshot_imfs_path(context, imfs, &path, Some(instance_name.clone()))?, None => match &node.class_name { Some(_class_name) => Some(RbxSnapshotInstance { name: instance_name.clone(), @@ -170,7 +220,7 @@ pub fn snapshot_project_node<'source>( } for (child_name, child_project_node) in &node.children { - if let Some(child) = snapshot_project_node(imfs, child_project_node, Cow::Owned(child_name.clone()))? { + if let Some(child) = snapshot_project_node(context, imfs, child_project_node, Cow::Owned(child_name.clone()))? { snapshot.children.push(child); } } @@ -189,6 +239,7 @@ pub fn snapshot_project_node<'source>( } pub fn snapshot_imfs_path<'source>( + context: &SnapshotContext, imfs: &'source Imfs, path: &Path, instance_name: Option>, @@ -196,23 +247,25 @@ pub fn snapshot_imfs_path<'source>( // If the given path doesn't exist in the in-memory filesystem, we consider // that an error. match imfs.get(path) { - Some(imfs_item) => snapshot_imfs_item(imfs, imfs_item, instance_name), + Some(imfs_item) => snapshot_imfs_item(context, imfs, imfs_item, instance_name), None => return Err(SnapshotError::DidNotExist(path.to_owned())), } } fn snapshot_imfs_item<'source>( + context: &SnapshotContext, imfs: &'source Imfs, item: &'source ImfsItem, instance_name: Option>, ) -> SnapshotResult<'source> { match item { - ImfsItem::File(file) => snapshot_imfs_file(file, instance_name), - ImfsItem::Directory(directory) => snapshot_imfs_directory(imfs, directory, instance_name), + ImfsItem::File(file) => snapshot_imfs_file(context, file, instance_name), + ImfsItem::Directory(directory) => snapshot_imfs_directory(context, imfs, directory, instance_name), } } fn snapshot_imfs_directory<'source>( + context: &SnapshotContext, imfs: &'source Imfs, directory: &'source ImfsDirectory, instance_name: Option>, @@ -229,11 +282,11 @@ fn snapshot_imfs_directory<'source>( }); let mut snapshot = if directory.children.contains(&init_path) { - snapshot_imfs_path(imfs, &init_path, Some(snapshot_name))?.unwrap() + snapshot_imfs_path(context, imfs, &init_path, Some(snapshot_name))?.unwrap() } else if directory.children.contains(&init_server_path) { - snapshot_imfs_path(imfs, &init_server_path, Some(snapshot_name))?.unwrap() + snapshot_imfs_path(context, imfs, &init_server_path, Some(snapshot_name))?.unwrap() } else if directory.children.contains(&init_client_path) { - snapshot_imfs_path(imfs, &init_client_path, Some(snapshot_name))?.unwrap() + snapshot_imfs_path(context, imfs, &init_client_path, Some(snapshot_name))?.unwrap() } else { RbxSnapshotInstance { class_name: Cow::Borrowed("Folder"), @@ -262,7 +315,7 @@ fn snapshot_imfs_directory<'source>( // them here. }, _ => { - if let Some(child) = snapshot_imfs_path(imfs, child_path, None)? { + if let Some(child) = snapshot_imfs_path(context, imfs, child_path, None)? { snapshot.children.push(child); } }, @@ -273,6 +326,7 @@ fn snapshot_imfs_directory<'source>( } fn snapshot_imfs_file<'source>( + context: &SnapshotContext, file: &'source ImfsFile, instance_name: Option>, ) -> SnapshotResult<'source> { @@ -308,6 +362,20 @@ fn snapshot_imfs_file<'source>( info!("File generated no snapshot: {}", file.path.display()); } + if let Some(snapshot) = maybe_snapshot.as_ref() { + if let Some(plugin_context) = &context.plugin_context { + for plugin in &plugin_context.plugins { + let owned_snapshot = snapshot.get_owned(); + let registry_key = &plugin.callback; + + plugin_context.lua.context(move |context| { + let callback: rlua::Function = context.registry_value(registry_key).unwrap(); + callback.call::<_, ()>(LuaRbxSnapshot(owned_snapshot)).unwrap(); + }); + } + } + } + Ok(maybe_snapshot) } diff --git a/server/src/snapshot_reconciler.rs b/server/src/snapshot_reconciler.rs index cc4b686e..42024ecb 100644 --- a/server/src/snapshot_reconciler.rs +++ b/server/src/snapshot_reconciler.rs @@ -64,7 +64,7 @@ impl InstanceChanges { /// A lightweight, hierarchical representation of an instance that can be /// applied to the tree. -#[derive(Debug, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct RbxSnapshotInstance<'a> { pub name: Cow<'a, str>, pub class_name: Cow<'a, str>, @@ -73,6 +73,22 @@ pub struct RbxSnapshotInstance<'a> { pub metadata: MetadataPerInstance, } +impl<'a> RbxSnapshotInstance<'a> { + pub fn get_owned(&'a self) -> RbxSnapshotInstance<'static> { + let children: Vec> = self.children.iter() + .map(RbxSnapshotInstance::get_owned) + .collect(); + + RbxSnapshotInstance { + name: Cow::Owned(self.name.clone().into_owned()), + class_name: Cow::Owned(self.class_name.clone().into_owned()), + properties: self.properties.clone(), + children, + metadata: self.metadata.clone(), + } + } +} + impl<'a> PartialOrd for RbxSnapshotInstance<'a> { fn partial_cmp(&self, other: &RbxSnapshotInstance) -> Option { Some(self.name.cmp(&other.name) diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index 1746cf56..38cf93b4 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -86,6 +86,7 @@ fn single_partition_game() { Project { name: "single-sync-point".to_string(), tree: root_node, + plugins: Vec::new(), serve_port: None, serve_place_ids: None, file_location: project_location.join("default.project.json"), diff --git a/server/tests/snapshots.rs b/server/tests/snapshots.rs index aab2193e..1707495d 100644 --- a/server/tests/snapshots.rs +++ b/server/tests/snapshots.rs @@ -8,7 +8,7 @@ use pretty_assertions::assert_eq; use librojo::{ imfs::Imfs, project::{Project, ProjectNode}, - rbx_snapshot::snapshot_project_tree, + rbx_snapshot::{SnapshotContext, snapshot_project_tree}, snapshot_reconciler::{RbxSnapshotInstance}, }; @@ -47,7 +47,11 @@ fn run_snapshot_test(path: &Path) { imfs.add_roots_from_project(&project) .expect("Could not add IMFS roots to snapshot project"); - let mut snapshot = snapshot_project_tree(&imfs, &project) + let context = SnapshotContext { + plugin_context: None, + }; + + let mut snapshot = snapshot_project_tree(&context, &imfs, &project) .expect("Could not generate snapshot for snapshot test"); if let Some(snapshot) = snapshot.as_mut() { From be81de74cda2146f07e654711e9ae12ce4c4ce10 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 24 Feb 2019 00:58:02 -0800 Subject: [PATCH 0453/1504] Disable Lua tests for now, since they need features Lemur doesn't have --- .travis.yml | 44 ++++++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 20 deletions(-) diff --git a/.travis.yml b/.travis.yml index f974e23f..71caeae1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,29 +1,33 @@ matrix: include: - - language: python - env: - - LUA="lua=5.1" + # Lua tests are currently disabled because of holes in Lemur that are pretty + # tedious to fix. It should be fixed by either adding missing features to + # Lemur or by migrating to a CI system based on real Roblox instead. - before_install: - - pip install hererocks - - hererocks lua_install -r^ --$LUA - - export PATH=$PATH:$PWD/lua_install/bin + # - language: python + # env: + # - LUA="lua=5.1" - install: - - luarocks install luafilesystem - - luarocks install busted - - luarocks install luacov - - luarocks install luacov-coveralls - - luarocks install luacheck + # before_install: + # - pip install hererocks + # - hererocks lua_install -r^ --$LUA + # - export PATH=$PATH:$PWD/lua_install/bin - script: - - cd plugin - - luacheck src - - lua -lluacov spec.lua + # install: + # - luarocks install luafilesystem + # - luarocks install busted + # - luarocks install luacov + # - luarocks install luacov-coveralls + # - luarocks install luacheck - after_success: - - cd plugin - - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install + # script: + # - cd plugin + # - luacheck src + # - lua -lluacov spec.lua + + # after_success: + # - cd plugin + # - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install - language: rust rust: 1.32.0 From 93349ae2dc69a808b630a5d255ec717764578c67 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 26 Feb 2019 22:51:21 -0800 Subject: [PATCH 0454/1504] Use rbx_reflection to allow type inference on projects (#130) * Start dependency on rbx_reflection * Alive and working, all tests pass * Update CHANGELOG --- CHANGELOG.md | 1 + Cargo.lock | 22 ++++++++++++++----- server/Cargo.toml | 3 ++- server/src/project.rs | 8 +++---- server/src/rbx_snapshot.rs | 18 ++++++++++++++- server/tests/read_projects.rs | 2 +- .../default.project.json | 5 +---- 7 files changed, 43 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2dff637..9de2f88e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Types like `Color3` and `CFrame` can now be updated live! * Fixed plugin assets flashing in on first load ([#121](https://github.com/LPGhatguy/rojo/issues/121)) * Changed Rojo's HTTP server from Rouille to Hyper, which reduced the release size by around a megabyte. +* Added property type inference to projects, which makes specifying services a lot easier ([#130](https://github.com/LPGhatguy/rojo/pull/130)) ## [0.5.0 Alpha 4](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.4) (February 8, 2019) * Added support for nested partitions ([#102](https://github.com/LPGhatguy/rojo/issues/102)) diff --git a/Cargo.lock b/Cargo.lock index f3cc9caf..f55103cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1029,12 +1029,12 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_dom_weak" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1042,6 +1042,16 @@ dependencies = [ "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rbx_reflection" +version = "1.0.373" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rbx_xml" version = "0.3.0" @@ -1052,7 +1062,7 @@ dependencies = [ "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1185,7 +1195,8 @@ dependencies = [ "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 1.0.373 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1848,7 +1859,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c4d3bffbec1f20f66684448e46ef45dad2fbf1185c3d8f3e29018f027484ffc" -"checksum rbx_dom_weak 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a67bbec623f2f12992dbf2e647deb3fe38613d4f874a8feeae566a931bebe63a" +"checksum rbx_dom_weak 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "673606053dba942f6c4607661c423424711a60cb40481f1e20c55acc21f53a38" +"checksum rbx_reflection 1.0.373 (registry+https://github.com/rust-lang/crates.io-index)" = "b37499dc2e097063be0eff716f54fb060ef3beb732e5f699b56feb6d9aa2442b" "checksum rbx_xml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b394e64979c52190e6462dd81d5b2258cdfb7e3891cefaff5d3c4af7cdc07b5" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" diff --git a/server/Cargo.toml b/server/Cargo.toml index 2ee9623c..2a1bfc71 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -31,8 +31,9 @@ maplit = "1.0.1" notify = "4.0" rand = "0.4" rbx_binary = "0.3.0" -rbx_dom_weak = "0.3.0" +rbx_dom_weak = "0.3.1" rbx_xml = "0.3.0" +rbx_reflection = "1.0.373" regex = "1.0" reqwest = "0.9.5" rlua = "0.16" diff --git a/server/src/project.rs b/server/src/project.rs index acefea5e..bfafc31d 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -9,7 +9,7 @@ use std::{ use log::warn; use failure::Fail; use maplit::hashmap; -use rbx_dom_weak::RbxValue; +use rbx_dom_weak::{UnresolvedRbxValue, RbxValue}; use serde_derive::{Serialize, Deserialize}; pub static PROJECT_FILENAME: &'static str = "default.project.json"; @@ -64,7 +64,7 @@ struct SourceProjectNode { class_name: Option, #[serde(rename = "$properties", default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")] - properties: HashMap, + properties: HashMap, #[serde(rename = "$ignoreUnknownInstances", skip_serializing_if = "Option::is_none")] ignore_unknown_instances: Option, @@ -188,7 +188,7 @@ pub enum ProjectSaveError { pub struct ProjectNode { pub class_name: Option, pub children: HashMap, - pub properties: HashMap, + pub properties: HashMap, pub ignore_unknown_instances: Option, #[serde(serialize_with = "crate::path_serializer::serialize_option")] @@ -284,7 +284,7 @@ impl Project { properties: hashmap! { String::from("HttpEnabled") => RbxValue::Bool { value: true, - }, + }.into(), }, ..Default::default() }, diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index c3301918..5cbd0b3c 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -15,6 +15,7 @@ use log::info; use maplit::hashmap; use rbx_dom_weak::{RbxTree, RbxValue, RbxInstanceProperties}; use serde_derive::{Serialize, Deserialize}; +use rbx_reflection::{try_resolve_value, ValueResolveError}; use crate::{ imfs::{ @@ -119,6 +120,19 @@ pub enum SnapshotError { ProjectNodeInvalidTransmute { partition_path: PathBuf, }, + + PropertyResolveError { + #[fail(cause)] + inner: ValueResolveError, + }, +} + +impl From for SnapshotError { + fn from(inner: ValueResolveError) -> SnapshotError { + SnapshotError::PropertyResolveError { + inner, + } + } } impl fmt::Display for SnapshotError { @@ -147,6 +161,7 @@ impl fmt::Display for SnapshotError { writeln!(output, "")?; writeln!(output, "Partition target ($path): {}", partition_path.display()) }, + SnapshotError::PropertyResolveError { inner } => write!(output, "{}", inner), } } } @@ -226,7 +241,8 @@ pub fn snapshot_project_node<'source>( } for (key, value) in &node.properties { - snapshot.properties.insert(key.clone(), value.clone()); + let resolved_value = try_resolve_value(&snapshot.class_name, key, value)?; + snapshot.properties.insert(key.clone(), resolved_value); } if let Some(ignore_unknown_instances) = node.ignore_unknown_instances { diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index 38cf93b4..63195acf 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -65,7 +65,7 @@ fn single_partition_game() { let mut http_service_properties = HashMap::new(); http_service_properties.insert("HttpEnabled".to_string(), RbxValue::Bool { value: true, - }); + }.into()); let http_service = ProjectNode { class_name: Some(String::from("HttpService")), diff --git a/test-projects/single_partition_game/default.project.json b/test-projects/single_partition_game/default.project.json index 3fbff1ac..04222f69 100644 --- a/test-projects/single_partition_game/default.project.json +++ b/test-projects/single_partition_game/default.project.json @@ -11,10 +11,7 @@ "HttpService": { "$className": "HttpService", "$properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } + "HttpEnabled": true } } } From 20be37dd8ba04b3a7ddae177923e3d6afe5ebe36 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 27 Feb 2019 00:47:02 -0800 Subject: [PATCH 0455/1504] Improve error messages from bad snapshots --- CHANGELOG.md | 1 + server/src/commands/build.rs | 11 +++-- server/src/commands/serve.rs | 6 ++- server/src/commands/upload.rs | 11 +++-- server/src/live_session.rs | 21 +++++++- server/src/rbx_session.rs | 49 +++++++++++++------ .../malformed-stuff/default.project.json | 6 +++ .../malformed-stuff/src/bad-model.model.json | 2 + 8 files changed, 83 insertions(+), 24 deletions(-) create mode 100644 test-projects/malformed-stuff/default.project.json create mode 100644 test-projects/malformed-stuff/src/bad-model.model.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 9de2f88e..b5f4d18f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * Fixed plugin assets flashing in on first load ([#121](https://github.com/LPGhatguy/rojo/issues/121)) * Changed Rojo's HTTP server from Rouille to Hyper, which reduced the release size by around a megabyte. * Added property type inference to projects, which makes specifying services a lot easier ([#130](https://github.com/LPGhatguy/rojo/pull/130)) +* Made error messages from invalid and missing files more user-friendly ## [0.5.0 Alpha 4](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.4) (February 8, 2019) * Added support for nested partitions ([#102](https://github.com/LPGhatguy/rojo/issues/102)) diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index 2c839e69..16301ed3 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -8,9 +8,10 @@ use log::info; use failure::Fail; use crate::{ - rbx_session::construct_oneoff_tree, - project::{Project, ProjectLoadFuzzyError}, imfs::{Imfs, FsError}, + project::{Project, ProjectLoadFuzzyError}, + rbx_session::construct_oneoff_tree, + rbx_snapshot::SnapshotError, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -59,6 +60,9 @@ pub enum BuildError { #[fail(display = "{}", _0)] FsError(#[fail(cause)] FsError), + + #[fail(display = "{}", _0)] + SnapshotError(#[fail(cause)] SnapshotError), } impl_from!(BuildError { @@ -67,6 +71,7 @@ impl_from!(BuildError { rbx_xml::EncodeError => XmlModelEncodeError, rbx_binary::EncodeError => BinaryModelEncodeError, FsError => FsError, + SnapshotError => SnapshotError, }); pub fn build(options: &BuildOptions) -> Result<(), BuildError> { @@ -86,7 +91,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let mut imfs = Imfs::new(); imfs.add_roots_from_project(&project)?; - let tree = construct_oneoff_tree(&project, &imfs); + let tree = construct_oneoff_tree(&project, &imfs)?; let mut file = File::create(&options.output_file)?; match output_kind { diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 9e7fac63..896bbc1b 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -10,7 +10,7 @@ use crate::{ project::{Project, ProjectLoadFuzzyError}, web::LiveServer, imfs::FsError, - live_session::LiveSession, + live_session::{LiveSession, LiveSessionError}, }; const DEFAULT_PORT: u16 = 34872; @@ -28,11 +28,15 @@ pub enum ServeError { #[fail(display = "{}", _0)] FsError(#[fail(cause)] FsError), + + #[fail(display = "{}", _0)] + LiveSessionError(#[fail(cause)] LiveSessionError), } impl_from!(ServeError { ProjectLoadFuzzyError => ProjectLoadError, FsError => FsError, + LiveSessionError => LiveSessionError, }); pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { diff --git a/server/src/commands/upload.rs b/server/src/commands/upload.rs index fb26e0ab..a142d43e 100644 --- a/server/src/commands/upload.rs +++ b/server/src/commands/upload.rs @@ -9,9 +9,10 @@ use failure::Fail; use reqwest::header::{ACCEPT, USER_AGENT, CONTENT_TYPE, COOKIE}; use crate::{ - rbx_session::construct_oneoff_tree, - project::{Project, ProjectLoadFuzzyError}, imfs::{Imfs, FsError}, + project::{Project, ProjectLoadFuzzyError}, + rbx_session::construct_oneoff_tree, + rbx_snapshot::SnapshotError, }; #[derive(Debug, Fail)] @@ -36,6 +37,9 @@ pub enum UploadError { #[fail(display = "{}", _0)] FsError(#[fail(cause)] FsError), + + #[fail(display = "{}", _0)] + SnapshotError(#[fail(cause)] SnapshotError), } impl_from!(UploadError { @@ -44,6 +48,7 @@ impl_from!(UploadError { reqwest::Error => HttpError, rbx_xml::EncodeError => XmlModelEncodeError, FsError => FsError, + SnapshotError => SnapshotError, }); #[derive(Debug)] @@ -67,7 +72,7 @@ pub fn upload(options: &UploadOptions) -> Result<(), UploadError> { let mut imfs = Imfs::new(); imfs.add_roots_from_project(&project)?; - let tree = construct_oneoff_tree(&project, &imfs); + let tree = construct_oneoff_tree(&project, &imfs)?; let root_id = tree.get_root_id(); let mut contents = Vec::new(); diff --git a/server/src/live_session.rs b/server/src/live_session.rs index f229fb4a..668353e1 100644 --- a/server/src/live_session.rs +++ b/server/src/live_session.rs @@ -2,16 +2,33 @@ use std::{ sync::{Arc, Mutex}, }; +use failure::Fail; + use crate::{ fs_watcher::FsWatcher, imfs::{Imfs, FsError}, message_queue::MessageQueue, project::Project, rbx_session::RbxSession, + rbx_snapshot::SnapshotError, session_id::SessionId, snapshot_reconciler::InstanceChanges, }; +#[derive(Debug, Fail)] +pub enum LiveSessionError { + #[fail(display = "{}", _0)] + Fs(#[fail(cause)] FsError), + + #[fail(display = "{}", _0)] + Snapshot(#[fail(cause)] SnapshotError), +} + +impl_from!(LiveSessionError { + FsError => Fs, + SnapshotError => Snapshot, +}); + /// Contains all of the state for a Rojo live-sync session. pub struct LiveSession { pub project: Arc, @@ -23,7 +40,7 @@ pub struct LiveSession { } impl LiveSession { - pub fn new(project: Arc) -> Result { + pub fn new(project: Arc) -> Result { let imfs = { let mut imfs = Imfs::new(); imfs.add_roots_from_project(&project)?; @@ -36,7 +53,7 @@ impl LiveSession { Arc::clone(&project), Arc::clone(&imfs), Arc::clone(&message_queue), - ))); + )?)); let fs_watcher = FsWatcher::start( Arc::clone(&imfs), diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 6927cff8..f2bb71d0 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -8,7 +8,7 @@ use std::{ use rlua::Lua; use serde_derive::{Serialize, Deserialize}; -use log::{info, trace}; +use log::{info, trace, error}; use rbx_dom_weak::{RbxTree, RbxId}; use crate::{ @@ -17,6 +17,7 @@ use crate::{ imfs::{Imfs, ImfsItem}, path_map::PathMap, rbx_snapshot::{ + SnapshotError, SnapshotContext, SnapshotPluginContext, SnapshotPluginEntry, @@ -31,6 +32,12 @@ const INIT_SCRIPT: &str = "init.lua"; const INIT_SERVER_SCRIPT: &str = "init.server.lua"; const INIT_CLIENT_SCRIPT: &str = "init.client.lua"; +fn show_snapshot_error(path: &Path, error: SnapshotError) { + error!("Rojo couldn't turn one of the project's files into Roblox instances."); + error!("Any changes to the file have been ignored."); + error!("{}", error); +} + /// `source_path` or `project_definition` or both must both be Some. #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct MetadataPerInstance { @@ -66,7 +73,7 @@ impl RbxSession { project: Arc, imfs: Arc>, message_queue: Arc>, - ) -> RbxSession { + ) -> Result { let mut instances_per_path = PathMap::new(); let mut metadata_per_instance = HashMap::new(); @@ -104,16 +111,22 @@ impl RbxSession { let tree = { let temp_imfs = imfs.lock().unwrap(); - reify_initial_tree(&project, &context, &temp_imfs, &mut instances_per_path, &mut metadata_per_instance) + reify_initial_tree( + &project, + &context, + &temp_imfs, + &mut instances_per_path, + &mut metadata_per_instance, + )? }; - RbxSession { + Ok(RbxSession { tree, instances_per_path, metadata_per_instance, message_queue, imfs, - } + }) } fn path_created_or_updated(&mut self, path: &Path) { @@ -155,20 +168,24 @@ impl RbxSession { let maybe_snapshot = match &instance_metadata.project_definition { Some((instance_name, project_node)) => { snapshot_project_node(&context, &imfs, &project_node, Cow::Owned(instance_name.clone())) - .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())) + // .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())) }, None => { snapshot_imfs_path(&context, &imfs, &path_to_snapshot, None) - .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())) + // .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())) }, }; let snapshot = match maybe_snapshot { - Some(snapshot) => snapshot, - None => { + Ok(Some(snapshot)) => snapshot, + Ok(None) => { trace!("Path resulted in no snapshot being generated."); return; }, + Err(err) => { + show_snapshot_error(&path_to_snapshot, err); + return; + }, }; trace!("Snapshot: {:#?}", snapshot); @@ -243,12 +260,13 @@ impl RbxSession { } } -pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> RbxTree { +pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> Result { let mut instances_per_path = PathMap::new(); let mut metadata_per_instance = HashMap::new(); let context = SnapshotContext { plugin_context: None, }; + reify_initial_tree(project, &context, imfs, &mut instances_per_path, &mut metadata_per_instance) } @@ -258,13 +276,14 @@ fn reify_initial_tree( imfs: &Imfs, instances_per_path: &mut PathMap>, metadata_per_instance: &mut HashMap, -) -> RbxTree { - let snapshot = snapshot_project_tree(&context, imfs, project) - .expect("Could not snapshot project tree") - .expect("Project did not produce any instances"); +) -> Result { + let snapshot = match snapshot_project_tree(&context, imfs, project)? { + Some(snapshot) => snapshot, + None => panic!("Project did not produce any instances"), + }; let mut changes = InstanceChanges::default(); let tree = reify_root(&snapshot, instances_per_path, metadata_per_instance, &mut changes); - tree + Ok(tree) } \ No newline at end of file diff --git a/test-projects/malformed-stuff/default.project.json b/test-projects/malformed-stuff/default.project.json new file mode 100644 index 00000000..710bd36c --- /dev/null +++ b/test-projects/malformed-stuff/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "malformed-stuff", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/test-projects/malformed-stuff/src/bad-model.model.json b/test-projects/malformed-stuff/src/bad-model.model.json new file mode 100644 index 00000000..b6fc298c --- /dev/null +++ b/test-projects/malformed-stuff/src/bad-model.model.json @@ -0,0 +1,2 @@ +ahhh this isn't a JSON model +bamboozled again \ No newline at end of file From cf5036eec65c01f8cf5b91fb48b3616fda1027a1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 27 Feb 2019 00:49:38 -0800 Subject: [PATCH 0456/1504] Fix warnings compiling server --- server/src/rbx_session.rs | 10 +++------- server/src/rbx_snapshot.rs | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index f2bb71d0..00940dca 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -32,12 +32,6 @@ const INIT_SCRIPT: &str = "init.lua"; const INIT_SERVER_SCRIPT: &str = "init.server.lua"; const INIT_CLIENT_SCRIPT: &str = "init.client.lua"; -fn show_snapshot_error(path: &Path, error: SnapshotError) { - error!("Rojo couldn't turn one of the project's files into Roblox instances."); - error!("Any changes to the file have been ignored."); - error!("{}", error); -} - /// `source_path` or `project_definition` or both must both be Some. #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct MetadataPerInstance { @@ -183,7 +177,9 @@ impl RbxSession { return; }, Err(err) => { - show_snapshot_error(&path_to_snapshot, err); + error!("Rojo couldn't turn one of the project's files into Roblox instances."); + error!("Any changes to the file have been ignored."); + error!("{}", err); return; }, }; diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 5cbd0b3c..9f9be279 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -81,7 +81,7 @@ impl rlua::UserData for LuaRbxSnapshot { } }); - methods.add_meta_method(rlua::MetaMethod::ToString, |_context, this, _args: ()| { + methods.add_meta_method(rlua::MetaMethod::ToString, |_context, _this, _args: ()| { Ok("RbxSnapshotInstance") }); } From 5073fce2f76655a846ee862beffa2a47f014e034 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 27 Feb 2019 14:42:41 -0800 Subject: [PATCH 0457/1504] Implement LiveSession::restart_with_new_project as foundation for reloading --- server/src/live_session.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/server/src/live_session.rs b/server/src/live_session.rs index 668353e1..957a2d37 100644 --- a/server/src/live_session.rs +++ b/server/src/live_session.rs @@ -1,4 +1,5 @@ use std::{ + mem, sync::{Arc, Mutex}, }; @@ -63,8 +64,8 @@ impl LiveSession { let session_id = SessionId::new(); Ok(LiveSession { - project, session_id, + project, message_queue, rbx_session, imfs, @@ -72,7 +73,14 @@ impl LiveSession { }) } - pub fn get_project(&self) -> &Project { - &self.project + /// Restarts the live session using the given project while preserving the + /// internal session ID. + pub fn restart_with_new_project(&mut self, project: Arc) -> Result<(), LiveSessionError> { + let mut new_session = LiveSession::new(project)?; + new_session.session_id = self.session_id; + + mem::replace(self, new_session); + + Ok(()) } } \ No newline at end of file From 16f8975b18e126f45d03ee84be6560f4bb8fde26 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 27 Feb 2019 14:51:53 -0800 Subject: [PATCH 0458/1504] Flip project field of LiveSession private to prepare for multi-project future --- server/src/live_session.rs | 7 ++++++- server/src/web/api.rs | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/server/src/live_session.rs b/server/src/live_session.rs index 957a2d37..50e83c9a 100644 --- a/server/src/live_session.rs +++ b/server/src/live_session.rs @@ -1,4 +1,5 @@ use std::{ + collections::HashSet, mem, sync::{Arc, Mutex}, }; @@ -32,7 +33,7 @@ impl_from!(LiveSessionError { /// Contains all of the state for a Rojo live-sync session. pub struct LiveSession { - pub project: Arc, + project: Arc, pub session_id: SessionId, pub message_queue: Arc>, pub rbx_session: Arc>, @@ -83,4 +84,8 @@ impl LiveSession { Ok(()) } + + pub fn serve_place_ids(&self) -> &Option> { + &self.project.serve_place_ids + } } \ No newline at end of file diff --git a/server/src/web/api.rs b/server/src/web/api.rs index 2bbc96f2..58da6ecb 100644 --- a/server/src/web/api.rs +++ b/server/src/web/api.rs @@ -145,7 +145,7 @@ impl ApiService { server_version: self.server_version, protocol_version: 2, session_id: self.live_session.session_id, - expected_place_ids: self.live_session.project.serve_place_ids.clone(), + expected_place_ids: self.live_session.serve_place_ids().clone(), root_instance_id: tree.get_root_id(), }) } From eb97e925e6eabd113870658fbb6b92988559fefd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 27 Feb 2019 14:54:05 -0800 Subject: [PATCH 0459/1504] Flip LiveSession::session_id private, add getter --- server/src/live_session.rs | 6 +++++- server/src/web/api.rs | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/server/src/live_session.rs b/server/src/live_session.rs index 50e83c9a..1b9db569 100644 --- a/server/src/live_session.rs +++ b/server/src/live_session.rs @@ -34,7 +34,7 @@ impl_from!(LiveSessionError { /// Contains all of the state for a Rojo live-sync session. pub struct LiveSession { project: Arc, - pub session_id: SessionId, + session_id: SessionId, pub message_queue: Arc>, pub rbx_session: Arc>, pub imfs: Arc>, @@ -85,6 +85,10 @@ impl LiveSession { Ok(()) } + pub fn session_id(&self) -> SessionId { + self.session_id + } + pub fn serve_place_ids(&self) -> &Option> { &self.project.serve_place_ids } diff --git a/server/src/web/api.rs b/server/src/web/api.rs index 58da6ecb..c66408c6 100644 --- a/server/src/web/api.rs +++ b/server/src/web/api.rs @@ -144,7 +144,7 @@ impl ApiService { response_json(&ServerInfoResponse { server_version: self.server_version, protocol_version: 2, - session_id: self.live_session.session_id, + session_id: self.live_session.session_id(), expected_place_ids: self.live_session.serve_place_ids().clone(), root_instance_id: tree.get_root_id(), }) @@ -173,7 +173,7 @@ impl ApiService { if !new_messages.is_empty() { return response_json(&SubscribeResponse { - session_id: self.live_session.session_id, + session_id: self.live_session.session_id(), messages: Cow::Borrowed(&new_messages), message_cursor: new_cursor, }) @@ -198,7 +198,7 @@ impl ApiService { let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); return response_json(&SubscribeResponse { - session_id: self.live_session.session_id, + session_id: self.live_session.session_id(), messages: Cow::Owned(new_messages), message_cursor: new_cursor, }) @@ -255,7 +255,7 @@ impl ApiService { } response_json(&ReadResponse { - session_id: self.live_session.session_id, + session_id: self.live_session.session_id(), message_cursor, instances, }) From 9b0e0c175b8b9679cde44f0081bc68fef7cc7ffd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 27 Feb 2019 17:32:36 -0800 Subject: [PATCH 0460/1504] Add missing CHANGELOG note --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b5f4d18f..e87ae521 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## [Unreleased] +* Upgraded from `rbx_tree` 0.2.0 to `rbx_dom_weak` 0.3.0, which improves compatibility for lots of instance types * Added support for non-primitive types in the Rojo plugin. * Types like `Color3` and `CFrame` can now be updated live! * Fixed plugin assets flashing in on first load ([#121](https://github.com/LPGhatguy/rojo/issues/121)) From 5fc4f6323872a1ff479bfbd5def750c0a8bd64be Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Mar 2019 15:34:16 -0800 Subject: [PATCH 0461/1504] Upgrade dependencies --- CHANGELOG.md | 5 +- Cargo.lock | 183 +++++++++++++++++++++++----------------------- server/Cargo.toml | 8 +- 3 files changed, 101 insertions(+), 95 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e87ae521..297fcd9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,10 @@ # Rojo Changelog ## [Unreleased] -* Upgraded from `rbx_tree` 0.2.0 to `rbx_dom_weak` 0.3.0, which improves compatibility for lots of instance types +* Upgraded core dependencies, which improves compatibility for lots of instance types + * Upgraded from `rbx_tree` 0.2.0 to `rbx_dom_weak` 1.0.0 + * Upgraded from `rbx_xml` 0.2.0 to `rbx_xml` 0.4.0 + * Upgraded from `rbx_binary` 0.2.0 to `rbx_binary` 0.4.0 * Added support for non-primitive types in the Rojo plugin. * Types like `Color3` and `CFrame` can now be updated live! * Fixed plugin assets flashing in on first load ([#121](https://github.com/LPGhatguy/rojo/issues/121)) diff --git a/Cargo.lock b/Cargo.lock index f55103cb..644d6825 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,7 +68,7 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -116,14 +116,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.29" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -188,7 +188,7 @@ dependencies = [ "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -219,7 +219,7 @@ dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -230,7 +230,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -239,7 +239,7 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -262,7 +262,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "encoding_rs" -version = "0.8.16" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -276,7 +276,7 @@ dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -304,7 +304,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -439,7 +439,7 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.24" +version = "0.12.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -452,6 +452,7 @@ dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -470,7 +471,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -533,7 +534,7 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -588,7 +589,7 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -679,13 +680,13 @@ name = "native-tls" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.18 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.41 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -739,15 +740,15 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.18" +version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.41 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -757,12 +758,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.41" +version = "0.9.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -812,7 +814,7 @@ dependencies = [ "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -876,7 +878,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -938,7 +940,7 @@ dependencies = [ "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1006,11 +1008,11 @@ dependencies = [ [[package]] name = "rand_pcg" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1023,46 +1025,47 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_dom_weak" -version = "0.3.1" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_reflection" -version = "1.0.373" +version = "2.0.374" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_xml" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1089,7 +1092,7 @@ dependencies = [ [[package]] name = "regex" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1122,18 +1125,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.16 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "libflate 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1172,7 +1175,7 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1186,25 +1189,25 @@ dependencies = [ "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_binary 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 1.0.373 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 2.0.374 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1242,10 +1245,10 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1281,7 +1284,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1291,27 +1294,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.38" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1321,7 +1324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1340,7 +1343,7 @@ dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1380,7 +1383,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.26" +version = "0.15.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1395,7 +1398,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1452,7 +1455,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1517,7 +1520,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1641,7 +1644,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1756,7 +1759,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cc 1.0.29 (registry+https://github.com/rust-lang/crates.io-index)" = "4390a3b5f4f6bce9c1d0c00128379df433e53777fdd30e92f16a529332baec4e" +"checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -1772,7 +1775,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" -"checksum encoding_rs 0.8.16 (registry+https://github.com/rust-lang/crates.io-index)" = "0535f350c60aac0b87ccf28319abc749391e912192255b0c00a2c12c6917bd73" +"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" @@ -1794,7 +1797,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.12.24 (registry+https://github.com/rust-lang/crates.io-index)" = "fdfa9b401ef6c4229745bb6e9b2529192d07b920eed624cdee2a82348cd550af" +"checksum hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)" = "7d5b6658b016965ae301fa995306db965c93677880ea70765a84235a96eae896" "checksum hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd73f14ad370d3b4d4b7dce08f69b81536c82e39fcc89731930fe5788cd661" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" @@ -1803,7 +1806,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a374c89b9db55895453a74c1e38861d9deec0b01b405a82516e9d5de4820dea1" +"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" "checksum libflate 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "54d1ddf9c52870243c5689d7638d888331c1116aa5b398f3ba1acfa7d8758ca1" @@ -1826,9 +1829,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum notify 4.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9cc7ed2bd4b7edad3ee93b659c38e53dabb619f7274e127a0fab054ad2bb998d" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" -"checksum openssl 0.10.18 (registry+https://github.com/rust-lang/crates.io-index)" = "b90119d71b0a3596588da04bf7c2c42f2978cfa1217a94119d8ec9e963c7729c" +"checksum openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)" = "84321fb9004c3bce5611188a644d6171f895fa2889d155927d528782edb21c5d" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.41 (registry+https://github.com/rust-lang/crates.io-index)" = "e4c77cdd67d31759b22aa72cfda3c65c12348f9e6c5420946b403c022fd0311a" +"checksum openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cb534d752bf98cf363b473950659ac2546517f9c6be9723771614ab3f03bbc9e" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" @@ -1856,16 +1859,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" "checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" -"checksum rand_pcg 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "086bd09a33c7044e56bb44d5bdde5a60e7f119a9e95b0775f545de759a32fe05" +"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rbx_binary 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c4d3bffbec1f20f66684448e46ef45dad2fbf1185c3d8f3e29018f027484ffc" -"checksum rbx_dom_weak 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "673606053dba942f6c4607661c423424711a60cb40481f1e20c55acc21f53a38" -"checksum rbx_reflection 1.0.373 (registry+https://github.com/rust-lang/crates.io-index)" = "b37499dc2e097063be0eff716f54fb060ef3beb732e5f699b56feb6d9aa2442b" -"checksum rbx_xml 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b394e64979c52190e6462dd81d5b2258cdfb7e3891cefaff5d3c4af7cdc07b5" +"checksum rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147f236284747ac1b4643476265dd36b402877d97adb7cbd0fafc1d247de0a5" +"checksum rbx_dom_weak 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "088a494e42fed50a2b12ba51807910187133ee7e81077cf7c08a57323b8d755f" +"checksum rbx_reflection 2.0.374 (registry+https://github.com/rust-lang/crates.io-index)" = "8a826ff869b33b54db727f9776f1dc7a8a779791f5a46ddd4941b8334bf909fe" +"checksum rbx_xml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de8408fec1a0b4b73fda1bfcd70757f34a38ef2af84618b57da69d422ea13841" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "37e7cbbd370869ce2e8dff25c7018702d10b21a20ef7135316f8daecd6c25b7f" +"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" "checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" "checksum reqwest 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f205a95638627fc0d21c53901671b06f439dc2830311ff11ecdff34ae2d839a8" @@ -1876,15 +1879,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" -"checksum schannel 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "0e1a231dc10abf6749cfa5d7767f25888d484201accbd919b66ab5413c502d56" +"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfab8dda0e7a327c696d893df9ffa19cadc4bd195797997f5223cf5831beaf05" "checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "9f301d728f2b94c9a7691c90f07b0b4e8a4517181d9461be94c04bddeb4bd850" -"checksum serde_derive 1.0.88 (registry+https://github.com/rust-lang/crates.io-index)" = "beed18e6f5175aef3ba670e57c60ef3b1b74d250d962a26604bff4c80e970dd4" -"checksum serde_json 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "27dce848e7467aa0e2fcaf0a413641499c0b745452aaca1194d24dedde9e13c9" +"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" +"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" +"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" @@ -1894,7 +1897,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.15.26 (registry+https://github.com/rust-lang/crates.io-index)" = "f92e629aa1d9c827b2bb8297046c1ccffc57c99b947a680d3ccff1f136a3bee9" +"checksum syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)" = "525bd55255f03c816e5d7f615587bd13030c7103354fadb104993dcee6a788ec" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" diff --git a/server/Cargo.toml b/server/Cargo.toml index 2a1bfc71..9aa544d1 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -30,10 +30,10 @@ log = "0.4" maplit = "1.0.1" notify = "4.0" rand = "0.4" -rbx_binary = "0.3.0" -rbx_dom_weak = "0.3.1" -rbx_xml = "0.3.0" -rbx_reflection = "1.0.373" +rbx_binary = "0.4.0" +rbx_dom_weak = "1.0.0" +rbx_xml = "0.4.0" +rbx_reflection = "2.0.374" regex = "1.0" reqwest = "0.9.5" rlua = "0.16" From b65a8ce680548a2cbc0097609bf23d548b3cf41f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 1 Mar 2019 15:40:30 -0800 Subject: [PATCH 0462/1504] 0.5.0-alpha.5 --- CHANGELOG.md | 2 ++ Cargo.lock | 2 +- docs/installation.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 297fcd9a..2069a998 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## [Unreleased] + +## [0.5.0 Alpha 5](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.5) (March 1, 2019) * Upgraded core dependencies, which improves compatibility for lots of instance types * Upgraded from `rbx_tree` 0.2.0 to `rbx_dom_weak` 1.0.0 * Upgraded from `rbx_xml` 0.2.0 to `rbx_xml` 0.4.0 diff --git a/Cargo.lock b/Cargo.lock index 644d6825..d0b5559f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1182,7 +1182,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0-alpha.4" +version = "0.5.0-alpha.5" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/docs/installation.md b/docs/installation.md index e12b22de..0a87cbd1 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -25,7 +25,7 @@ If you have Rust installed, the easiest way to get Rojo is with Cargo! To install the latest 0.5.0 alpha, use: ```sh -cargo install rojo --version 0.5.0-alpha.4 +cargo install rojo --version 0.5.0-alpha.5 ``` ## Installing the Plugin diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 08ed8052..ab777370 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0, "-alpha.4"}, + version = {0, 5, 0, "-alpha.5"}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/server/Cargo.toml b/server/Cargo.toml index 9aa544d1..63edfa00 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0-alpha.4" +version = "0.5.0-alpha.5" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 01bef0c2b85da9560e2233bd05ccb00233f44ae5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Mar 2019 13:47:33 -0700 Subject: [PATCH 0463/1504] Update dependencies --- Cargo.lock | 295 ++++++++++++++++++++++++++--------------------------- 1 file changed, 144 insertions(+), 151 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d0b5559f..69c3c8b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,7 +3,7 @@ name = "MacTypes-sys" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -40,7 +40,7 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -57,8 +57,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -69,7 +69,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -102,7 +102,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bytes" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -128,7 +128,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -159,7 +159,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -167,44 +167,20 @@ name = "core-foundation-sys" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crc32fast" -version = "1.1.2" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-channel" -version = "0.3.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-deque" -version = "0.6.3" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -217,19 +193,27 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-queue" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-utils" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -265,12 +249,12 @@ name = "encoding_rs" version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "env_logger" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -304,7 +288,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -313,8 +297,8 @@ name = "filetime" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -343,7 +327,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -351,7 +335,7 @@ name = "fsevent-sys" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -398,7 +382,7 @@ version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -406,7 +390,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -419,7 +403,7 @@ name = "http" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -442,7 +426,7 @@ name = "hyper" version = "0.12.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -454,12 +438,12 @@ dependencies = [ "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -469,11 +453,11 @@ name = "hyper-tls" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -498,7 +482,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -506,7 +490,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -514,7 +498,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -544,17 +528,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.49" +version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libflate" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -571,7 +555,7 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -579,7 +563,7 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -590,7 +574,7 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -608,7 +592,7 @@ name = "memchr" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -621,7 +605,7 @@ name = "mime" version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -645,7 +629,7 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -681,7 +665,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -697,8 +681,8 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -709,7 +693,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "notify" -version = "4.0.9" +version = "4.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -718,7 +702,7 @@ dependencies = [ "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -735,7 +719,7 @@ name = "num_cpus" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -744,10 +728,10 @@ version = "0.10.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -762,7 +746,7 @@ version = "0.9.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -790,7 +774,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -814,7 +798,7 @@ dependencies = [ "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -878,12 +862,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro-nested" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -921,7 +905,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -933,13 +917,13 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -988,19 +972,19 @@ name = "rand_jitter" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_os" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1031,12 +1015,12 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_dom_weak" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1052,7 +1036,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1065,7 +1049,7 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1120,17 +1104,17 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.10" +version = "0.9.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libflate 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", + "libflate 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1138,10 +1122,10 @@ dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1154,7 +1138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-nested 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1176,7 +1160,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1186,23 +1170,23 @@ version = "0.5.0-alpha.5" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 2.0.374 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1264,7 +1248,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1275,7 +1259,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1304,7 +1288,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1383,7 +1367,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.27" +version = "0.15.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1398,7 +1382,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1416,8 +1400,8 @@ name = "tempfile" version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1437,7 +1421,7 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1463,31 +1447,31 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-current-thread" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1505,17 +1489,17 @@ dependencies = [ [[package]] name = "tokio-io" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1527,7 +1511,17 @@ dependencies = [ "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-sync" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1535,22 +1529,21 @@ name = "tokio-tcp" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1591,7 +1584,7 @@ dependencies = [ [[package]] name = "unicase" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1757,26 +1750,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" -"checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa" +"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" "checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" -"checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4" +"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" -"checksum crc32fast 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e91d5240c6975ef33aeb5f148f35275c25eda8e8a5f95abe421978b05b8bf192" -"checksum crossbeam 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad4c7ea749d9fb09e23c5cb17e3b70650860553a0e2744e38446b1803bf7db94" -"checksum crossbeam-channel 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f0ed1a4de2235cabda8558ff5840bffb97fcb64c97827f354a451307df5f72b" -"checksum crossbeam-deque 0.6.3 (registry+https://github.com/rust-lang/crates.io-index)" = "05e44b8cf3e1a625844d1750e1f7820da46044ff6d28f4d43e455ba3e5bb2c13" +"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" -"checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e" +"checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" "checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" @@ -1808,8 +1800,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e" -"checksum libflate 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "54d1ddf9c52870243c5689d7638d888331c1116aa5b398f3ba1acfa7d8758ca1" +"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" +"checksum libflate 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "7346a83e8a2c3958d44d24225d905385dc31fc16e89dffb356c457b278914d20" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" @@ -1826,7 +1818,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum notify 4.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9cc7ed2bd4b7edad3ee93b659c38e53dabb619f7274e127a0fab054ad2bb998d" +"checksum notify 4.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "abb1581693e44d8a0ec347ef12289625063f52a1dddc3f3c9befd5fc59e88943" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" "checksum openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)" = "84321fb9004c3bce5611188a644d6171f895fa2889d155927d528782edb21c5d" @@ -1845,7 +1837,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" "checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" -"checksum proc-macro-nested 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e9968e025d6368d1273a93bc23051e30dbf5482475e716d7385d8ec8fbd5b5b6" +"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" @@ -1858,11 +1850,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" -"checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d" +"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147f236284747ac1b4643476265dd36b402877d97adb7cbd0fafc1d247de0a5" -"checksum rbx_dom_weak 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "088a494e42fed50a2b12ba51807910187133ee7e81077cf7c08a57323b8d755f" +"checksum rbx_dom_weak 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c44f210860e85fa3ea733a3a03e8585f9a47a1f6fcd218f3d577fadd5de089bc" "checksum rbx_reflection 2.0.374 (registry+https://github.com/rust-lang/crates.io-index)" = "8a826ff869b33b54db727f9776f1dc7a8a779791f5a46ddd4941b8334bf909fe" "checksum rbx_xml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de8408fec1a0b4b73fda1bfcd70757f34a38ef2af84618b57da69d422ea13841" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" @@ -1871,7 +1863,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" "checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)" = "f205a95638627fc0d21c53901671b06f439dc2830311ff11ecdff34ae2d839a8" +"checksum reqwest 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e542d9f077c126af32536b6aacc75bb7325400eab8cd0743543be5d91660780d" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "51acb42c134a6568911a2aef2cea5feb80503804cc8986b903983ebfb1342a2c" @@ -1897,7 +1889,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)" = "525bd55255f03c816e5d7f615587bd13030c7103354fadb104993dcee6a788ec" +"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" @@ -1906,18 +1898,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "e0500b88064f08bebddd0c0bed39e19f5c567a5f30975bee52b0c0d3e2eeb38c" -"checksum tokio-current-thread 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "331c8acc267855ec06eb0c94618dcbbfea45bed2d20b77252940095273fb58f6" +"checksum tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fcaabb3cec70485d0df6e9454fe514393ad1c4070dee8915f11041e95630b230" +"checksum tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c756b04680eea21902a46fca4e9f410a2332c04995af590e07ff262e2193a9a3" "checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" -"checksum tokio-io 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b53aeb9d3f5ccf2ebb29e19788f96987fa1355f8fe45ea193928eaaaf3ae820f" -"checksum tokio-reactor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "afbcdb0f0d2a1e4c440af82d7bbf0bf91a8a8c0575bcd20c05d15be7e9d3a02f" +"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" +"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" +"checksum tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1bf2b9dac2a0509b5cfd1df5aa25eafacb616a42a491a13604d6bbeab4486363" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c3fd86cb15547d02daa2b21aadaf4e37dee3368df38a526178a5afa3c034d2fb" +"checksum tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "742e511f6ce2298aeb86fc9ea0d8df81c2388c6ebae3dc8a7316e8c9df0df801" "checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"checksum unicase 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9d3218ea14b4edcaccfa0df0a64a3792a2c32cc706f1b336e48867f9d3147f90" +"checksum unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41d17211f887da8e4a70a45b9536f26fc5de166b81e2d5d80de4a17fd22553bd" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" From 2deb3bbf239e21e941399f52af1513edb043bb07 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Mar 2019 13:48:02 -0700 Subject: [PATCH 0464/1504] Add notable feature from dependency upgrade --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2069a998..da22c734 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## [Unreleased] +* Fixed `cargo init` giving unexpected results by upgrading to `rbx_dom_weak` 1.1.0 ## [0.5.0 Alpha 5](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.5) (March 1, 2019) * Upgraded core dependencies, which improves compatibility for lots of instance types From 5fd0bd3db921b3532b2a6ad5a685ab8c52674386 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Mar 2019 14:12:49 -0700 Subject: [PATCH 0465/1504] Update/prune dependencies with help of cargo-outdated --- Cargo.lock | 28 ++++++++++++++++++++++++---- server/Cargo.toml | 3 +-- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 69c3c8b0..bff54a52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -234,6 +234,15 @@ dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ctor" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "difference" version = "2.0.0" @@ -752,6 +761,14 @@ dependencies = [ "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "output_vt100" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "owning_ref" version = "0.4.0" @@ -848,11 +865,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pretty_assertions" -version = "0.5.1" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ctor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1179,8 +1198,7 @@ dependencies = [ "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.10 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 2.0.374 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1765,6 +1783,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" "checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" +"checksum ctor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9a43db2bba5cafdc6aa068c892a518e477ee0df3705e53ec70247a9ff93546d5" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" @@ -1824,6 +1843,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)" = "84321fb9004c3bce5611188a644d6171f895fa2889d155927d528782edb21c5d" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cb534d752bf98cf363b473950659ac2546517f9c6be9723771614ab3f03bbc9e" +"checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" @@ -1835,7 +1855,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" -"checksum pretty_assertions 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3a029430f0d744bc3d15dd474d591bed2402b645d024583082b9f63bb936dac6" +"checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" "checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" diff --git a/server/Cargo.toml b/server/Cargo.toml index 63edfa00..155e04ff 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -29,7 +29,6 @@ hyper = "0.12" log = "0.4" maplit = "1.0.1" notify = "4.0" -rand = "0.4" rbx_binary = "0.4.0" rbx_dom_weak = "1.0.0" rbx_xml = "0.4.0" @@ -47,5 +46,5 @@ uuid = { version = "0.7", features = ["v4", "serde"] } tempfile = "3.0" walkdir = "2.1" lazy_static = "1.2" -pretty_assertions = "0.5.1" +pretty_assertions = "0.6.1" paste = "0.1" \ No newline at end of file From 376f2a554ac590f017afbb2ceb6eb2c2637da4a3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Mar 2019 16:28:40 -0700 Subject: [PATCH 0466/1504] Better default project, including minimal property types --- CHANGELOG.md | 3 + server/assets/place.project.json | 66 ++++++++++++++++ server/src/project.rs | 124 ++++++++++++++++++++++--------- 3 files changed, 157 insertions(+), 36 deletions(-) create mode 100644 server/assets/place.project.json diff --git a/CHANGELOG.md b/CHANGELOG.md index da22c734..a2ea4be8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## [Unreleased] * Fixed `cargo init` giving unexpected results by upgrading to `rbx_dom_weak` 1.1.0 +* Updated default place file: + * Improved default properties to be closer to Studio's built-in 'Baseplate' template + * Added a baseplate to the project file (Thanks, [@AmaranthineCodices](https://github.com/AmaranthineCodices/)!) ## [0.5.0 Alpha 5](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.5) (March 1, 2019) * Upgraded core dependencies, which improves compatibility for lots of instance types diff --git a/server/assets/place.project.json b/server/assets/place.project.json new file mode 100644 index 00000000..4cf32314 --- /dev/null +++ b/server/assets/place.project.json @@ -0,0 +1,66 @@ +{ + "name": "[placeholder]", + "tree": { + "$className": "DataModel", + "HttpService": { + "$className": "HttpService", + "$properties": { + "HttpEnabled": true + } + }, + "Lighting": { + "$className": "Lighting", + "$properties": { + "Ambient": [ + 0, + 0, + 0 + ], + "Brightness": 2, + "GlobalShadows": true, + "Outlines": false, + "Technology": "Voxel" + } + }, + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + "Source": { + "$path": "src" + } + }, + "SoundService": { + "$className": "SoundService", + "$properties": { + "RespectFilteringEnabled": true + } + }, + "Workspace": { + "$className": "Workspace", + "$properties": { + "FilteringEnabled": true + }, + "Baseplate": { + "$className": "Part", + "$properties": { + "Anchored": true, + "Color": [ + 0.38823, + 0.37254, + 0.38823 + ], + "Locked": true, + "Position": [ + 0, + -10, + 0 + ], + "Size": [ + 512, + 20, + 512 + ] + } + } + } + } +} \ No newline at end of file diff --git a/server/src/project.rs b/server/src/project.rs index bfafc31d..212cb27a 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -8,9 +8,11 @@ use std::{ use log::warn; use failure::Fail; -use maplit::hashmap; use rbx_dom_weak::{UnresolvedRbxValue, RbxValue}; use serde_derive::{Serialize, Deserialize}; +use serde::{Serialize, Serializer}; + +static DEFAULT_PLACE: &'static str = include_str!("../assets/place.project.json"); pub static PROJECT_FILENAME: &'static str = "default.project.json"; pub static COMPAT_PROJECT_FILENAME: &'static str = "roblox-project.json"; @@ -55,6 +57,74 @@ impl SourceProject { } } +/// An alternative serializer for `UnresolvedRbxValue` that uses the minimum +/// representation of the value. +/// +/// For example, the default Serialize impl might give you: +/// +/// ```json +/// { +/// "Type": "Bool", +/// "Value": true +/// } +/// ``` +/// +/// But in reality, users are expected to write just: +/// +/// ```json +/// true +/// ``` +/// +/// This holds true for other values that might be ambiguous or just have more +/// complicated representations like enums. +fn serialize_unresolved_minimal(value: &UnresolvedRbxValue, serializer: S) -> Result + where S: Serializer +{ + match value { + UnresolvedRbxValue::Ambiguous(_) => value.serialize(serializer), + UnresolvedRbxValue::Concrete(concrete) => { + match concrete { + RbxValue::Bool { value } => value.serialize(serializer), + RbxValue::CFrame { value } => value.serialize(serializer), + RbxValue::Color3 { value } => value.serialize(serializer), + RbxValue::Color3uint8 { value } => value.serialize(serializer), + RbxValue::Content { value } => value.serialize(serializer), + RbxValue::Enum { value } => value.serialize(serializer), + RbxValue::Float32 { value } => value.serialize(serializer), + RbxValue::Int32 { value } => value.serialize(serializer), + RbxValue::String { value } => value.serialize(serializer), + RbxValue::UDim { value } => value.serialize(serializer), + RbxValue::UDim2 { value } => value.serialize(serializer), + RbxValue::Vector2 { value } => value.serialize(serializer), + RbxValue::Vector2int16 { value } => value.serialize(serializer), + RbxValue::Vector3 { value } => value.serialize(serializer), + RbxValue::Vector3int16 { value } => value.serialize(serializer), + _ => concrete.serialize(serializer), + } + }, + } +} + +/// A wrapper around serialize_unresolved_minimal that handles the HashMap case. +fn serialize_unresolved_map(value: &HashMap, serializer: S) -> Result + where S: Serializer +{ + use serde::ser::SerializeMap; + + #[derive(Serialize)] + struct Minimal<'a>( + #[serde(serialize_with = "serialize_unresolved_minimal")] + &'a UnresolvedRbxValue + ); + + let mut map = serializer.serialize_map(Some(value.len()))?; + for (k, v) in value { + map.serialize_key(k)?; + map.serialize_value(&Minimal(v))?; + } + map.end() +} + /// Similar to SourceProject, the structure of nodes in the project tree is /// slightly different on-disk than how we want to handle them in the rest of /// Rojo. @@ -63,7 +133,12 @@ struct SourceProjectNode { #[serde(rename = "$className", skip_serializing_if = "Option::is_none")] class_name: Option, - #[serde(rename = "$properties", default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")] + #[serde( + rename = "$properties", + default = "HashMap::new", + skip_serializing_if = "HashMap::is_empty", + serialize_with = "serialize_unresolved_map", + )] properties: HashMap, #[serde(rename = "$ignoreUnknownInstances", skip_serializing_if = "Option::is_none")] @@ -162,6 +237,7 @@ pub enum ProjectInitError { AlreadyExists(PathBuf), IoError(#[fail(cause)] io::Error), SaveError(#[fail(cause)] ProjectSaveError), + JsonError(#[fail(cause)] serde_json::Error), } impl fmt::Display for ProjectInitError { @@ -170,6 +246,7 @@ impl fmt::Display for ProjectInitError { ProjectInitError::AlreadyExists(path) => write!(output, "Path {} already exists", path.display()), ProjectInitError::IoError(inner) => write!(output, "IO error: {}", inner), ProjectInitError::SaveError(inner) => write!(output, "{}", inner), + ProjectInitError::JsonError(inner) => write!(output, "{}", inner), } } } @@ -259,47 +336,16 @@ pub struct Project { impl Project { pub fn init_place(project_fuzzy_path: &Path) -> Result { let project_path = Project::init_pick_path(project_fuzzy_path)?; - let project_folder_path = project_path.parent().unwrap(); let project_name = if project_fuzzy_path == project_path { project_fuzzy_path.parent().unwrap().file_name().unwrap().to_str().unwrap() } else { project_fuzzy_path.file_name().unwrap().to_str().unwrap() }; - let tree = ProjectNode { - class_name: Some(String::from("DataModel")), - children: hashmap! { - String::from("ReplicatedStorage") => ProjectNode { - class_name: Some(String::from("ReplicatedStorage")), - children: hashmap! { - String::from("Source") => ProjectNode { - path: Some(project_folder_path.join("src")), - ..Default::default() - }, - }, - ..Default::default() - }, - String::from("HttpService") => ProjectNode { - class_name: Some(String::from("HttpService")), - properties: hashmap! { - String::from("HttpEnabled") => RbxValue::Bool { - value: true, - }.into(), - }, - ..Default::default() - }, - }, - ..Default::default() - }; + let mut project = Project::load_from_str(DEFAULT_PLACE, &project_path) + .map_err(ProjectInitError::JsonError)?; - let project = Project { - name: project_name.to_string(), - tree, - plugins: Vec::new(), - serve_port: None, - serve_place_ids: None, - file_location: project_path.clone(), - }; + project.name = project_name.to_owned(); project.save() .map_err(ProjectInitError::SaveError)?; @@ -387,6 +433,12 @@ impl Project { } } + fn load_from_str(contents: &str, project_file_location: &Path) -> Result { + let parsed: SourceProject = serde_json::from_str(&contents)?; + + Ok(parsed.into_project(project_file_location)) + } + pub fn load_fuzzy(fuzzy_project_location: &Path) -> Result { let project_path = Self::locate(fuzzy_project_location) .ok_or(ProjectLoadFuzzyError::NotFound)?; From 5b9facee00fe54196c59c9a001b5fee800030a5c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Mar 2019 16:35:54 -0700 Subject: [PATCH 0467/1504] Fix up variable naming in serialize_unresolved_minimal --- server/src/project.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/server/src/project.rs b/server/src/project.rs index 212cb27a..878591c2 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -77,11 +77,11 @@ impl SourceProject { /// /// This holds true for other values that might be ambiguous or just have more /// complicated representations like enums. -fn serialize_unresolved_minimal(value: &UnresolvedRbxValue, serializer: S) -> Result +fn serialize_unresolved_minimal(unresolved: &UnresolvedRbxValue, serializer: S) -> Result where S: Serializer { - match value { - UnresolvedRbxValue::Ambiguous(_) => value.serialize(serializer), + match unresolved { + UnresolvedRbxValue::Ambiguous(_) => unresolved.serialize(serializer), UnresolvedRbxValue::Concrete(concrete) => { match concrete { RbxValue::Bool { value } => value.serialize(serializer), From 3b6238ff933a89f749828fead32913bc6ec4cac8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Mar 2019 16:55:42 -0700 Subject: [PATCH 0468/1504] Add more types to plugin --- CHANGELOG.md | 1 + plugin/src/rojoValueToRobloxValue.lua | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2ea4be8..3f80ac55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Updated default place file: * Improved default properties to be closer to Studio's built-in 'Baseplate' template * Added a baseplate to the project file (Thanks, [@AmaranthineCodices](https://github.com/AmaranthineCodices/)!) +* Added more type support to Rojo plugin ## [0.5.0 Alpha 5](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.5) (March 1, 2019) * Upgraded core dependencies, which improves compatibility for lots of instance types diff --git a/plugin/src/rojoValueToRobloxValue.lua b/plugin/src/rojoValueToRobloxValue.lua index 995a8e4b..b5855b2a 100644 --- a/plugin/src/rojoValueToRobloxValue.lua +++ b/plugin/src/rojoValueToRobloxValue.lua @@ -1,14 +1,20 @@ local primitiveTypes = { - String = true, Bool = true, - Int32 = true, - Float32 = true, Enum = true, + Float32 = true, + Float64 = true, + Int32 = true, + Int64 = true, + String = true, } local directConstructors = { CFrame = CFrame.new, Color3 = Color3.new, + Color3uint8 = Color3.fromRGB, + Rect = Rect.new, + UDim = UDim.new, + UDim2 = UDim2.new, Vector2 = Vector2.new, Vector2int16 = Vector2int16.new, Vector3 = Vector3.new, From ad93631ef84a75a68f8f40ceeedbd55baf016434 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 12 Mar 2019 11:45:39 -0700 Subject: [PATCH 0469/1504] Port to futures channel instead of std one. Fixes #133. --- CHANGELOG.md | 1 + server/src/message_queue.rs | 12 ++++---- server/src/web/api.rs | 57 +++++++++++++++++++------------------ 3 files changed, 37 insertions(+), 33 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3f80ac55..2cc5b4e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [Unreleased] * Fixed `cargo init` giving unexpected results by upgrading to `rbx_dom_weak` 1.1.0 +* Fixed API not responding when the Rojo plugin is connected ([#133](https://github.com/LPGhatguy/rojo/issues/133)) * Updated default place file: * Improved default properties to be closer to Studio's built-in 'Baseplate' template * Added a baseplate to the project file (Thanks, [@AmaranthineCodices](https://github.com/AmaranthineCodices/)!) diff --git a/server/src/message_queue.rs b/server/src/message_queue.rs index 9eefb749..e8d0e5c7 100644 --- a/server/src/message_queue.rs +++ b/server/src/message_queue.rs @@ -1,13 +1,14 @@ use std::{ collections::HashMap, sync::{ - mpsc, atomic::{AtomicUsize, Ordering}, RwLock, Mutex, }, }; +use futures::sync::mpsc; + /// A unique identifier, not guaranteed to be generated in any order. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct ListenerId(usize); @@ -21,8 +22,7 @@ pub fn get_listener_id() -> ListenerId { /// A message queue with persistent history that can be subscribed to. /// -/// Definitely non-optimal, but a simple design that works well for the -/// synchronous web server Rojo uses, Rouille. +/// Definitely non-optimal. This would ideally be a lockless mpmc queue. #[derive(Default)] pub struct MessageQueue { messages: RwLock>, @@ -38,15 +38,15 @@ impl MessageQueue { } pub fn push_messages(&self, new_messages: &[T]) { - let message_listeners = self.message_listeners.lock().unwrap(); + let mut message_listeners = self.message_listeners.lock().unwrap(); { let mut messages = self.messages.write().unwrap(); messages.extend_from_slice(new_messages); } - for listener in message_listeners.values() { - listener.send(()).unwrap(); + for listener in message_listeners.values_mut() { + listener.try_send(()).unwrap(); } } diff --git a/server/src/web/api.rs b/server/src/web/api.rs index c66408c6..a36d02c8 100644 --- a/server/src/web/api.rs +++ b/server/src/web/api.rs @@ -4,10 +4,10 @@ use std::{ borrow::Cow, collections::{HashMap, HashSet}, - sync::{mpsc, Arc}, + sync::Arc, }; -use futures::{future, Future}; +use futures::{future, Future, stream::Stream, sync::mpsc}; use hyper::{ service::Service, header, @@ -114,14 +114,16 @@ impl Service for ApiService { fn call(&mut self, request: hyper::Request) -> Self::Future { let response = match (request.method(), request.uri().path()) { (&Method::GET, "/api/rojo") => self.handle_api_rojo(), - (&Method::GET, path) if path.starts_with("/api/subscribe/") => self.handle_api_subscribe(request), (&Method::GET, path) if path.starts_with("/api/read/") => self.handle_api_read(request), + (&Method::GET, path) if path.starts_with("/api/subscribe/") => { + return self.handle_api_subscribe(request); + } _ => { Response::builder() .status(StatusCode::NOT_FOUND) .body(Body::empty()) .unwrap() - }, + } }; Box::new(future::ok(response)) @@ -152,16 +154,16 @@ impl ApiService { /// Retrieve any messages past the given cursor index, and if /// there weren't any, subscribe to receive any new messages. - fn handle_api_subscribe(&self, request: Request) -> Response { + fn handle_api_subscribe(&self, request: Request) -> ::Future { let argument = &request.uri().path()["/api/subscribe/".len()..]; let cursor: u32 = match argument.parse() { Ok(v) => v, Err(err) => { - return Response::builder() + return Box::new(future::ok(Response::builder() .status(StatusCode::BAD_REQUEST) .header(header::CONTENT_TYPE, "text/plain") .body(Body::from(err.to_string())) - .unwrap(); + .unwrap())); }, }; @@ -172,37 +174,38 @@ impl ApiService { let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); if !new_messages.is_empty() { - return response_json(&SubscribeResponse { + return Box::new(future::ok(response_json(&SubscribeResponse { session_id: self.live_session.session_id(), messages: Cow::Borrowed(&new_messages), message_cursor: new_cursor, - }) + }))); } } - // TOOD: Switch to futures mpsc instead to not block this task - let (tx, rx) = mpsc::channel(); + let (tx, rx) = mpsc::channel(1024); let sender_id = message_queue.subscribe(tx); + let session_id = self.live_session.session_id(); - match rx.recv() { - Ok(_) => (), - Err(_) => return Response::builder() - .status(500) - .body(Body::from("error!")) - .unwrap(), - } + let result = rx.into_future() + .and_then(move |_| { + message_queue.unsubscribe(sender_id); - message_queue.unsubscribe(sender_id); + let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); - { - let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); - - return response_json(&SubscribeResponse { - session_id: self.live_session.session_id(), - messages: Cow::Owned(new_messages), - message_cursor: new_cursor, + Box::new(future::ok(response_json(SubscribeResponse { + session_id: session_id, + messages: Cow::Owned(new_messages), + message_cursor: new_cursor, + }))) }) - } + .or_else(|e| { + Box::new(future::ok(Response::builder() + .status(500) + .body(Body::from(format!("Internal Error: {:?}", e))) + .unwrap())) + }); + + Box::new(result) } fn handle_api_read(&self, request: Request) -> Response { From ec0a1f1ce4c3749f638bb3ab2df41a0bbeb97ee9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Mar 2019 14:20:03 -0700 Subject: [PATCH 0470/1504] New snapshot tests (#134) * Changes project-related structures to use `BTreeMap` instead of `HashMap` for children to aid determiniusm * Changes imfs-related structures to have total ordering and use `BTreeSet` instead of `HashSet` * Upgrades dependencies to `bx_dom_weak`1.2.0 and rbx_xml 0.5.0 to aid in more determinism stuff * Re-exposes the `RbxSession`'s root project via `root_project()` * Implements `Default` for a couple things * Tweaks visualization code to support visualizing trees not attached to an `RbxSession` * Adds an ID-invariant comparison method for `rbx_tree` relying on previous determinism changes * Adds a (disabled) test to start finding issues in the reconciler with regards to communicativity of snapshot application * Adds a snapshot testing system that operates on `RbxTree` and associated metadata, which are committed in this change --- .gitignore | 3 +- Cargo.lock | 18 +- server/Cargo.toml | 4 +- server/src/imfs.rs | 43 ++- server/src/live_session.rs | 4 + server/src/path_map.rs | 6 + server/src/project.rs | 18 +- server/src/rbx_session.rs | 4 + server/src/snapshot_reconciler.rs | 2 +- server/src/visualize.rs | 55 ++- server/tests/imfs.rs | 8 +- server/tests/read_projects.rs | 6 +- server/tests/snapshot_reconciler.rs | 115 ++++++ server/tests/snapshot_snapshots.rs | 68 ++++ server/tests/snapshots.rs | 128 ------- server/tests/test_util/mod.rs | 28 +- server/tests/test_util/snapshot.rs | 79 ++++ server/tests/test_util/tree.rs | 351 ++++++++++++++++++ server/tests/tree_snapshots.rs | 68 ++++ test-projects/multi_partition_game/a/foo.txt | 1 + test-projects/multi_partition_game/a/main.lua | 1 + .../multi_partition_game/b/something.lua | 1 + .../multi_partition_game/default.project.json | 21 ++ .../expected-snapshot.json | 212 +++++++++++ .../multi_partition_game/initial.tree.json | 242 ++++++++++++ .../multi_partition_game/with_dir.tree.json | 256 +++++++++++++ .../with_moved_dir.tree.json | 256 +++++++++++++ 27 files changed, 1793 insertions(+), 205 deletions(-) create mode 100644 server/tests/snapshot_reconciler.rs create mode 100644 server/tests/snapshot_snapshots.rs delete mode 100644 server/tests/snapshots.rs create mode 100644 server/tests/test_util/snapshot.rs create mode 100644 server/tests/test_util/tree.rs create mode 100644 server/tests/tree_snapshots.rs create mode 100644 test-projects/multi_partition_game/a/foo.txt create mode 100644 test-projects/multi_partition_game/a/main.lua create mode 100644 test-projects/multi_partition_game/b/something.lua create mode 100644 test-projects/multi_partition_game/default.project.json create mode 100644 test-projects/multi_partition_game/expected-snapshot.json create mode 100644 test-projects/multi_partition_game/initial.tree.json create mode 100644 test-projects/multi_partition_game/with_dir.tree.json create mode 100644 test-projects/multi_partition_game/with_moved_dir.tree.json diff --git a/.gitignore b/.gitignore index d77fcf54..216fc1c5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ /target /scratch-project **/*.rs.bk -/generate-docs.run \ No newline at end of file +/generate-docs.run +/server/failed-snapshots/ \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index bff54a52..189076f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1034,12 +1034,12 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_dom_weak" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1055,12 +1055,12 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_xml" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1068,7 +1068,7 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1200,9 +1200,9 @@ dependencies = [ "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 2.0.374 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1874,9 +1874,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147f236284747ac1b4643476265dd36b402877d97adb7cbd0fafc1d247de0a5" -"checksum rbx_dom_weak 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c44f210860e85fa3ea733a3a03e8585f9a47a1f6fcd218f3d577fadd5de089bc" +"checksum rbx_dom_weak 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e31ec3223caeb1a57254a8a10b33614a2d457517be01ef93694f83d995833b04" "checksum rbx_reflection 2.0.374 (registry+https://github.com/rust-lang/crates.io-index)" = "8a826ff869b33b54db727f9776f1dc7a8a779791f5a46ddd4941b8334bf909fe" -"checksum rbx_xml 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "de8408fec1a0b4b73fda1bfcd70757f34a38ef2af84618b57da69d422ea13841" +"checksum rbx_xml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a240c155684b744c4985f283702b61f6ab0a2d4479694051d875844632c9f454" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" diff --git a/server/Cargo.toml b/server/Cargo.toml index 155e04ff..47b4dccf 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -30,8 +30,8 @@ log = "0.4" maplit = "1.0.1" notify = "4.0" rbx_binary = "0.4.0" -rbx_dom_weak = "1.0.0" -rbx_xml = "0.4.0" +rbx_dom_weak = "1.2.0" +rbx_xml = "0.5.0" rbx_reflection = "2.0.374" regex = "1.0" reqwest = "0.9.5" diff --git a/server/src/imfs.rs b/server/src/imfs.rs index c144ae5e..0672ddb1 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -1,9 +1,10 @@ use std::{ - collections::{HashMap, HashSet}, - path::{self, Path, PathBuf}, + cmp::Ordering, + collections::{HashMap, HashSet, BTreeSet}, fmt, fs, io, + path::{self, Path, PathBuf}, }; use failure::Fail; @@ -237,7 +238,7 @@ impl Imfs { } else if metadata.is_dir() { let item = ImfsItem::Directory(ImfsDirectory { path: path.to_path_buf(), - children: HashSet::new(), + children: BTreeSet::new(), }); self.items.insert(path.to_path_buf(), item); @@ -285,19 +286,43 @@ impl Imfs { } } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] pub struct ImfsFile { pub path: PathBuf, pub contents: Vec, } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct ImfsDirectory { - pub path: PathBuf, - pub children: HashSet, +impl PartialOrd for ImfsFile { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +impl Ord for ImfsFile { + fn cmp(&self, other: &Self) -> Ordering { + self.path.cmp(&other.path) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub struct ImfsDirectory { + pub path: PathBuf, + pub children: BTreeSet, +} + +impl PartialOrd for ImfsDirectory { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for ImfsDirectory { + fn cmp(&self, other: &Self) -> Ordering { + self.path.cmp(&other.path) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] pub enum ImfsItem { File(ImfsFile), Directory(ImfsDirectory), diff --git a/server/src/live_session.rs b/server/src/live_session.rs index 1b9db569..b90b6e87 100644 --- a/server/src/live_session.rs +++ b/server/src/live_session.rs @@ -85,6 +85,10 @@ impl LiveSession { Ok(()) } + pub fn root_project(&self) -> &Project { + &self.project + } + pub fn session_id(&self) -> SessionId { self.session_id } diff --git a/server/src/path_map.rs b/server/src/path_map.rs index d944541e..8df2d83a 100644 --- a/server/src/path_map.rs +++ b/server/src/path_map.rs @@ -20,6 +20,12 @@ pub struct PathMap { nodes: HashMap>, } +impl Default for PathMap { + fn default() -> Self { + Self::new() + } +} + impl PathMap { pub fn new() -> PathMap { PathMap { diff --git a/server/src/project.rs b/server/src/project.rs index 878591c2..24d945e4 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -1,5 +1,5 @@ use std::{ - collections::{HashMap, HashSet}, + collections::{HashMap, HashSet, BTreeMap}, fmt, fs::{self, File}, io, @@ -128,7 +128,7 @@ fn serialize_unresolved_map(value: &HashMap, seri /// Similar to SourceProject, the structure of nodes in the project tree is /// slightly different on-disk than how we want to handle them in the rest of /// Rojo. -#[derive(Debug, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] struct SourceProjectNode { #[serde(rename = "$className", skip_serializing_if = "Option::is_none")] class_name: Option, @@ -148,14 +148,14 @@ struct SourceProjectNode { path: Option, #[serde(flatten)] - children: HashMap, + children: BTreeMap, } impl SourceProjectNode { /// Consumes the SourceProjectNode and turns it into a ProjectNode. - pub fn into_project_node(mut self, project_file_location: &Path) -> ProjectNode { - let children = self.children.drain() - .map(|(key, value)| (key, value.into_project_node(project_file_location))) + pub fn into_project_node(self, project_file_location: &Path) -> ProjectNode { + let children = self.children.iter() + .map(|(key, value)| (key.clone(), value.clone().into_project_node(project_file_location))) .collect(); // Make sure that paths are absolute, transforming them by adding the @@ -264,7 +264,7 @@ pub enum ProjectSaveError { #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct ProjectNode { pub class_name: Option, - pub children: HashMap, + pub children: BTreeMap, pub properties: HashMap, pub ignore_unknown_instances: Option, @@ -486,6 +486,10 @@ impl Project { } } + pub fn folder_location(&self) -> &Path { + self.file_location.parent().unwrap() + } + fn to_source_project(&self) -> SourceProject { let plugins = self.plugins .iter() diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 00940dca..7310736a 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -251,6 +251,10 @@ impl RbxSession { &self.tree } + pub fn get_all_instance_metadata(&self) -> &HashMap { + &self.metadata_per_instance + } + pub fn get_instance_metadata(&self, id: RbxId) -> Option<&MetadataPerInstance> { self.metadata_per_instance.get(&id) } diff --git a/server/src/snapshot_reconciler.rs b/server/src/snapshot_reconciler.rs index 42024ecb..2b52ca52 100644 --- a/server/src/snapshot_reconciler.rs +++ b/server/src/snapshot_reconciler.rs @@ -64,7 +64,7 @@ impl InstanceChanges { /// A lightweight, hierarchical representation of an instance that can be /// applied to the tree. -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] pub struct RbxSnapshotInstance<'a> { pub name: Cow<'a, str>, pub class_name: Cow<'a, str>, diff --git a/server/src/visualize.rs b/server/src/visualize.rs index 32ab0786..d0b36604 100644 --- a/server/src/visualize.rs +++ b/server/src/visualize.rs @@ -1,4 +1,5 @@ use std::{ + collections::HashMap, fmt, io::Write, path::Path, @@ -6,12 +7,13 @@ use std::{ }; use log::warn; -use rbx_dom_weak::RbxId; +use rbx_dom_weak::{RbxTree, RbxId}; use crate::{ imfs::{Imfs, ImfsItem}, rbx_session::RbxSession, web::api::PublicInstanceMetadata, + rbx_session::MetadataPerInstance, }; static GRAPHVIZ_HEADER: &str = r#" @@ -53,42 +55,59 @@ pub fn graphviz_to_svg(source: &str) -> Option { Some(String::from_utf8(output.stdout).expect("Failed to parse stdout as UTF-8")) } +pub struct VisualizeRbxTree<'a, 'b> { + pub tree: &'a RbxTree, + pub metadata: &'b HashMap, +} + +impl<'a, 'b> fmt::Display for VisualizeRbxTree<'a, 'b> { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + writeln!(output, "{}", GRAPHVIZ_HEADER)?; + + visualize_instance(&self.tree, self.tree.get_root_id(), &self.metadata, output)?; + + writeln!(output, "}}") + } +} + /// A Display wrapper struct to visualize an RbxSession as SVG. pub struct VisualizeRbxSession<'a>(pub &'a RbxSession); impl<'a> fmt::Display for VisualizeRbxSession<'a> { fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - writeln!(output, "{}", GRAPHVIZ_HEADER)?; - - visualize_rbx_node(self.0, self.0.get_tree().get_root_id(), output)?; - - writeln!(output, "}}")?; - - Ok(()) + writeln!(output, "{}", VisualizeRbxTree { + tree: self.0.get_tree(), + metadata: self.0.get_all_instance_metadata(), + }) } } -fn visualize_rbx_node(session: &RbxSession, id: RbxId, output: &mut fmt::Formatter) -> fmt::Result { - let node = session.get_tree().get_instance(id).unwrap(); +fn visualize_instance( + tree: &RbxTree, + id: RbxId, + metadata: &HashMap, + output: &mut fmt::Formatter, +) -> fmt::Result { + let instance = tree.get_instance(id).unwrap(); - let mut node_label = format!("{}|{}|{}", node.name, node.class_name, id); + let mut instance_label = format!("{}|{}|{}", instance.name, instance.class_name, id); - if let Some(session_metadata) = session.get_instance_metadata(id) { + if let Some(session_metadata) = metadata.get(&id) { let metadata = PublicInstanceMetadata::from_session_metadata(session_metadata); - node_label.push('|'); - node_label.push_str(&serde_json::to_string(&metadata).unwrap()); + instance_label.push('|'); + instance_label.push_str(&serde_json::to_string(&metadata).unwrap()); } - node_label = node_label + instance_label = instance_label .replace("\"", """) .replace("{", "\\{") .replace("}", "\\}"); - writeln!(output, " \"{}\" [label=\"{}\"]", id, node_label)?; + writeln!(output, " \"{}\" [label=\"{}\"]", id, instance_label)?; - for &child_id in node.get_children_ids() { + for &child_id in instance.get_children_ids() { writeln!(output, " \"{}\" -> \"{}\"", id, child_id)?; - visualize_rbx_node(session, child_id, output)?; + visualize_instance(tree, child_id, metadata, output)?; } Ok(()) diff --git a/server/tests/imfs.rs b/server/tests/imfs.rs index 617ce06a..6dc3f49d 100644 --- a/server/tests/imfs.rs +++ b/server/tests/imfs.rs @@ -1,5 +1,5 @@ use std::{ - collections::{HashMap, HashSet}, + collections::{HashMap, HashSet, BTreeSet}, fs, path::PathBuf, }; @@ -80,7 +80,7 @@ fn base_tree() -> Result<(TempDir, Imfs, ExpectedImfs, TestResources), Error> { expected_roots.insert(root.path().to_path_buf()); let root_item = { - let mut children = HashSet::new(); + let mut children = BTreeSet::new(); children.insert(foo_path.clone()); children.insert(bar_path.clone()); @@ -91,7 +91,7 @@ fn base_tree() -> Result<(TempDir, Imfs, ExpectedImfs, TestResources), Error> { }; let foo_item = { - let mut children = HashSet::new(); + let mut children = BTreeSet::new(); children.insert(baz_path.clone()); ImfsItem::Directory(ImfsDirectory { @@ -199,7 +199,7 @@ fn adding_folder() -> Result<(), Error> { } let folder_item = { - let mut children = HashSet::new(); + let mut children = BTreeSet::new(); children.insert(file1_path.clone()); children.insert(file2_path.clone()); diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index 63195acf..38cb5f89 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -1,7 +1,7 @@ #[macro_use] extern crate lazy_static; use std::{ - collections::HashMap, + collections::{HashMap, BTreeMap}, path::{Path, PathBuf}, }; @@ -53,7 +53,7 @@ fn single_partition_game() { ..Default::default() }; - let mut replicated_storage_children = HashMap::new(); + let mut replicated_storage_children = BTreeMap::new(); replicated_storage_children.insert("Foo".to_string(), foo); let replicated_storage = ProjectNode { @@ -73,7 +73,7 @@ fn single_partition_game() { ..Default::default() }; - let mut root_children = HashMap::new(); + let mut root_children = BTreeMap::new(); root_children.insert("ReplicatedStorage".to_string(), replicated_storage); root_children.insert("HttpService".to_string(), http_service); diff --git a/server/tests/snapshot_reconciler.rs b/server/tests/snapshot_reconciler.rs new file mode 100644 index 00000000..4888e917 --- /dev/null +++ b/server/tests/snapshot_reconciler.rs @@ -0,0 +1,115 @@ +mod test_util; + +use std::collections::HashMap; + +use pretty_assertions::assert_eq; +use rbx_dom_weak::{RbxTree, RbxInstanceProperties}; + +use librojo::{ + snapshot_reconciler::{RbxSnapshotInstance, reconcile_subtree}, +}; + +use test_util::tree::trees_equal; + +// TODO: Snapshot application isn't communicative right now with the current +// snapshot reconciler. In practice this mostly isn't a problem, but presents +// a problem trying to rely on determinism to make snapshot tests. +// #[test] +fn patch_communicativity() { + let base_tree = RbxTree::new(RbxInstanceProperties { + name: "DataModel".into(), + class_name: "DataModel".into(), + properties: HashMap::new(), + }); + + let patch_a = RbxSnapshotInstance { + name: "DataModel".into(), + class_name: "DataModel".into(), + children: vec![ + RbxSnapshotInstance { + name: "Child-A".into(), + class_name: "Folder".into(), + ..Default::default() + }, + ], + ..Default::default() + }; + + let patch_b = RbxSnapshotInstance { + name: "DataModel".into(), + class_name: "DataModel".into(), + children: vec![ + RbxSnapshotInstance { + name: "Child-B".into(), + class_name: "Folder".into(), + ..Default::default() + }, + ], + ..Default::default() + }; + + let patch_combined = RbxSnapshotInstance { + name: "DataModel".into(), + class_name: "DataModel".into(), + children: vec![ + RbxSnapshotInstance { + name: "Child-A".into(), + class_name: "Folder".into(), + ..Default::default() + }, + RbxSnapshotInstance { + name: "Child-B".into(), + class_name: "Folder".into(), + ..Default::default() + }, + ], + ..Default::default() + }; + + let root_id = base_tree.get_root_id(); + + let mut tree_a = base_tree.clone(); + + reconcile_subtree( + &mut tree_a, + root_id, + &patch_a, + &mut Default::default(), + &mut Default::default(), + &mut Default::default(), + ); + + reconcile_subtree( + &mut tree_a, + root_id, + &patch_combined, + &mut Default::default(), + &mut Default::default(), + &mut Default::default(), + ); + + let mut tree_b = base_tree.clone(); + + reconcile_subtree( + &mut tree_b, + root_id, + &patch_b, + &mut Default::default(), + &mut Default::default(), + &mut Default::default(), + ); + + reconcile_subtree( + &mut tree_b, + root_id, + &patch_combined, + &mut Default::default(), + &mut Default::default(), + &mut Default::default(), + ); + + match trees_equal(&tree_a, &tree_b) { + Ok(_) => {} + Err(e) => panic!("{}", e), + } +} \ No newline at end of file diff --git a/server/tests/snapshot_snapshots.rs b/server/tests/snapshot_snapshots.rs new file mode 100644 index 00000000..d697f50f --- /dev/null +++ b/server/tests/snapshot_snapshots.rs @@ -0,0 +1,68 @@ +mod test_util; + +use std::path::Path; + +use pretty_assertions::assert_eq; + +use librojo::{ + imfs::Imfs, + project::Project, + rbx_snapshot::{SnapshotContext, snapshot_project_tree}, +}; + +use crate::test_util::{ + snapshot::*, +}; + +macro_rules! generate_snapshot_tests { + ($($name: ident),*) => { + $( + paste::item! { + #[test] + fn []() { + let _ = env_logger::try_init(); + + let tests_folder = Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects"); + let project_folder = tests_folder.join(stringify!($name)); + run_snapshot_test(&project_folder); + } + } + )* + }; +} + +generate_snapshot_tests!( + empty, + multi_partition_game, + nested_partitions, + single_partition_game, + single_partition_model, + transmute_partition +); + +fn run_snapshot_test(path: &Path) { + println!("Running snapshot from project: {}", path.display()); + + let project = Project::load_fuzzy(path) + .expect("Couldn't load project file for snapshot test"); + + let mut imfs = Imfs::new(); + imfs.add_roots_from_project(&project) + .expect("Could not add IMFS roots to snapshot project"); + + let context = SnapshotContext { + plugin_context: None, + }; + + let mut snapshot = snapshot_project_tree(&context, &imfs, &project) + .expect("Could not generate snapshot for snapshot test"); + + if let Some(snapshot) = snapshot.as_mut() { + anonymize_snapshot(path, snapshot); + } + + match read_expected_snapshot(path) { + Some(expected_snapshot) => assert_eq!(snapshot, expected_snapshot), + None => write_expected_snapshot(path, &snapshot), + } +} \ No newline at end of file diff --git a/server/tests/snapshots.rs b/server/tests/snapshots.rs deleted file mode 100644 index 1707495d..00000000 --- a/server/tests/snapshots.rs +++ /dev/null @@ -1,128 +0,0 @@ -use std::{ - fs::{self, File}, - path::{Path, PathBuf}, -}; - -use pretty_assertions::assert_eq; - -use librojo::{ - imfs::Imfs, - project::{Project, ProjectNode}, - rbx_snapshot::{SnapshotContext, snapshot_project_tree}, - snapshot_reconciler::{RbxSnapshotInstance}, -}; - -macro_rules! generate_snapshot_tests { - ($($name: ident),*) => { - $( - paste::item! { - #[test] - fn []() { - let tests_folder = Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects"); - let project_folder = tests_folder.join(stringify!($name)); - run_snapshot_test(&project_folder); - } - } - )* - }; -} - -generate_snapshot_tests!( - empty, - nested_partitions, - single_partition_game, - single_partition_model, - transmute_partition -); - -const SNAPSHOT_EXPECTED_NAME: &str = "expected-snapshot.json"; - -fn run_snapshot_test(path: &Path) { - println!("Running snapshot from project: {}", path.display()); - - let project = Project::load_fuzzy(path) - .expect("Couldn't load project file for snapshot test"); - - let mut imfs = Imfs::new(); - imfs.add_roots_from_project(&project) - .expect("Could not add IMFS roots to snapshot project"); - - let context = SnapshotContext { - plugin_context: None, - }; - - let mut snapshot = snapshot_project_tree(&context, &imfs, &project) - .expect("Could not generate snapshot for snapshot test"); - - if let Some(snapshot) = snapshot.as_mut() { - anonymize_snapshot(path, snapshot); - } - - match read_expected_snapshot(path) { - Some(expected_snapshot) => assert_eq!(snapshot, expected_snapshot), - None => write_expected_snapshot(path, &snapshot), - } -} - -/// Snapshots contain absolute paths, which simplifies much of Rojo. -/// -/// For saving snapshots to the disk, we should strip off the project folder -/// path to make them machine-independent. This doesn't work for paths that fall -/// outside of the project folder, but that's okay here. -/// -/// We also need to sort children, since Rojo tends to enumerate the filesystem -/// in an unpredictable order. -fn anonymize_snapshot(project_folder_path: &Path, snapshot: &mut RbxSnapshotInstance) { - match snapshot.metadata.source_path.as_mut() { - Some(path) => *path = anonymize_path(project_folder_path, path), - None => {}, - } - - match snapshot.metadata.project_definition.as_mut() { - Some((_, project_node)) => anonymize_project_node(project_folder_path, project_node), - None => {}, - } - - snapshot.children.sort_by(|a, b| a.partial_cmp(b).unwrap()); - - for child in snapshot.children.iter_mut() { - anonymize_snapshot(project_folder_path, child); - } -} - -fn anonymize_project_node(project_folder_path: &Path, project_node: &mut ProjectNode) { - match project_node.path.as_mut() { - Some(path) => *path = anonymize_path(project_folder_path, path), - None => {}, - } - - for child_node in project_node.children.values_mut() { - anonymize_project_node(project_folder_path, child_node); - } -} - -fn anonymize_path(project_folder_path: &Path, path: &Path) -> PathBuf { - if path.is_absolute() { - path.strip_prefix(project_folder_path) - .expect("Could not anonymize absolute path") - .to_path_buf() - } else { - path.to_path_buf() - } -} - -fn read_expected_snapshot(path: &Path) -> Option>> { - let contents = fs::read(path.join(SNAPSHOT_EXPECTED_NAME)).ok()?; - let snapshot: Option> = serde_json::from_slice(&contents) - .expect("Could not deserialize snapshot"); - - Some(snapshot) -} - -fn write_expected_snapshot(path: &Path, snapshot: &Option) { - let mut file = File::create(path.join(SNAPSHOT_EXPECTED_NAME)) - .expect("Could not open file to write snapshot"); - - serde_json::to_writer_pretty(&mut file, snapshot) - .expect("Could not serialize snapshot to file"); -} \ No newline at end of file diff --git a/server/tests/test_util/mod.rs b/server/tests/test_util/mod.rs index ec3c51fd..5988865d 100644 --- a/server/tests/test_util/mod.rs +++ b/server/tests/test_util/mod.rs @@ -1,31 +1,13 @@ +#![allow(dead_code)] + use std::fs::{create_dir, copy}; use std::path::Path; use std::io; -use rouille::Request; - use walkdir::WalkDir; -use librojo::web::Server; - -pub trait HttpTestUtil { - fn get_string(&self, url: &str) -> String; -} - -impl HttpTestUtil for Server { - fn get_string(&self, url: &str) -> String { - let info_request = Request::fake_http("GET", url, vec![], vec![]); - let response = self.handle_request(&info_request); - - assert_eq!(response.status_code, 200); - - let (mut reader, _) = response.data.into_reader_and_size(); - let mut body = String::new(); - reader.read_to_string(&mut body).unwrap(); - - body - } -} +pub mod snapshot; +pub mod tree; pub fn copy_recursive(from: &Path, to: &Path) -> io::Result<()> { for entry in WalkDir::new(from) { @@ -51,4 +33,4 @@ pub fn copy_recursive(from: &Path, to: &Path) -> io::Result<()> { } Ok(()) -} +} \ No newline at end of file diff --git a/server/tests/test_util/snapshot.rs b/server/tests/test_util/snapshot.rs new file mode 100644 index 00000000..43088684 --- /dev/null +++ b/server/tests/test_util/snapshot.rs @@ -0,0 +1,79 @@ +use std::{ + fs::{self, File}, + path::{Path, PathBuf}, +}; + +use librojo::{ + project::ProjectNode, + snapshot_reconciler::RbxSnapshotInstance, + rbx_session::MetadataPerInstance, +}; + +const SNAPSHOT_EXPECTED_NAME: &str = "expected-snapshot.json"; + +/// Snapshots contain absolute paths, which simplifies much of Rojo. +/// +/// For saving snapshots to the disk, we should strip off the project folder +/// path to make them machine-independent. This doesn't work for paths that fall +/// outside of the project folder, but that's okay here. +/// +/// We also need to sort children, since Rojo tends to enumerate the filesystem +/// in an unpredictable order. +pub fn anonymize_snapshot(project_folder_path: &Path, snapshot: &mut RbxSnapshotInstance) { + anonymize_metadata(project_folder_path, &mut snapshot.metadata); + + snapshot.children.sort_by(|a, b| a.partial_cmp(b).unwrap()); + + for child in snapshot.children.iter_mut() { + anonymize_snapshot(project_folder_path, child); + } +} + +pub fn anonymize_metadata(project_folder_path: &Path, metadata: &mut MetadataPerInstance) { + match metadata.source_path.as_mut() { + Some(path) => *path = anonymize_path(project_folder_path, path), + None => {}, + } + + match metadata.project_definition.as_mut() { + Some((_, project_node)) => anonymize_project_node(project_folder_path, project_node), + None => {}, + } +} + +pub fn anonymize_project_node(project_folder_path: &Path, project_node: &mut ProjectNode) { + match project_node.path.as_mut() { + Some(path) => *path = anonymize_path(project_folder_path, path), + None => {}, + } + + for child_node in project_node.children.values_mut() { + anonymize_project_node(project_folder_path, child_node); + } +} + +pub fn anonymize_path(project_folder_path: &Path, path: &Path) -> PathBuf { + if path.is_absolute() { + path.strip_prefix(project_folder_path) + .expect("Could not anonymize absolute path") + .to_path_buf() + } else { + path.to_path_buf() + } +} + +pub fn read_expected_snapshot(path: &Path) -> Option>> { + let contents = fs::read(path.join(SNAPSHOT_EXPECTED_NAME)).ok()?; + let snapshot: Option> = serde_json::from_slice(&contents) + .expect("Could not deserialize snapshot"); + + Some(snapshot) +} + +pub fn write_expected_snapshot(path: &Path, snapshot: &Option) { + let mut file = File::create(path.join(SNAPSHOT_EXPECTED_NAME)) + .expect("Could not open file to write snapshot"); + + serde_json::to_writer_pretty(&mut file, snapshot) + .expect("Could not serialize snapshot to file"); +} \ No newline at end of file diff --git a/server/tests/test_util/tree.rs b/server/tests/test_util/tree.rs new file mode 100644 index 00000000..4f2525de --- /dev/null +++ b/server/tests/test_util/tree.rs @@ -0,0 +1,351 @@ +//! Defines a mechanism to compare two RbxTree objects and generate a useful +//! diff if they aren't the same. These methods ignore IDs, which are randomly +//! generated whenever a tree is constructed anyways. This makes matching up +//! pairs of instances that should be the same potentially difficult. +//! +//! It relies on a couple different ideas: +//! - Instances with the same name and class name are matched as the same +//! instance. See basic_equal for this logic +//! - A path of period-delimited names (like Roblox's GetFullName) should be +//! enough to debug most issues. If it isn't, we can do something fun like +//! generate GraphViz graphs. + +use std::{ + borrow::Cow, + collections::{HashMap, HashSet}, + fmt, + fs::{self, File}, + hash::Hash, + path::{Path, PathBuf}, +}; + +use log::error; +use serde_derive::{Serialize, Deserialize}; +use rbx_dom_weak::{RbxId, RbxTree}; + +use librojo::{ + rbx_session::MetadataPerInstance, + live_session::LiveSession, + visualize::{VisualizeRbxTree, graphviz_to_svg}, +}; + +use super::snapshot::anonymize_metadata; + +/// Marks a 'step' in the test, which will snapshot the session's current +/// RbxTree object and compare it against the saved snapshot if it exists. +pub fn tree_step(step: &str, live_session: &LiveSession, source_path: &Path) { + let rbx_session = live_session.rbx_session.lock().unwrap(); + let tree = rbx_session.get_tree(); + + let project_folder = live_session.root_project().folder_location(); + let metadata = rbx_session.get_all_instance_metadata() + .iter() + .map(|(key, meta)| { + let mut meta = meta.clone(); + anonymize_metadata(project_folder, &mut meta); + (*key, meta) + }) + .collect(); + + let tree_with_metadata = TreeWithMetadata { + tree: Cow::Borrowed(&tree), + metadata: Cow::Owned(metadata), + }; + + match read_tree_by_name(source_path, step) { + Some(expected) => match trees_and_metadata_equal(&expected, &tree_with_metadata) { + Ok(_) => {} + Err(e) => { + error!("Trees at step '{}' were not equal.\n{}", step, e); + + let expected_gv = format!("{}", VisualizeRbxTree { + tree: &expected.tree, + metadata: &expected.metadata, + }); + + let actual_gv = format!("{}", VisualizeRbxTree { + tree: &tree_with_metadata.tree, + metadata: &tree_with_metadata.metadata, + }); + + let output_dir = PathBuf::from("failed-snapshots"); + fs::create_dir_all(&output_dir) + .expect("Could not create failed-snapshots directory"); + + let expected_basename = format!("{}-{}-expected", live_session.root_project().name, step); + let actual_basename = format!("{}-{}-actual", live_session.root_project().name, step); + + let mut expected_out = output_dir.join(expected_basename); + let mut actual_out = output_dir.join(actual_basename); + + match (graphviz_to_svg(&expected_gv), graphviz_to_svg(&actual_gv)) { + (Some(expected_svg), Some(actual_svg)) => { + expected_out.set_extension("svg"); + actual_out.set_extension("svg"); + + fs::write(&expected_out, expected_svg) + .expect("Couldn't write expected SVG"); + + fs::write(&actual_out, actual_svg) + .expect("Couldn't write actual SVG"); + } + _ => { + expected_out.set_extension("gv"); + actual_out.set_extension("gv"); + + fs::write(&expected_out, expected_gv) + .expect("Couldn't write expected GV"); + + fs::write(&actual_out, actual_gv) + .expect("Couldn't write actual GV"); + } + } + + error!("Output at {} and {}", expected_out.display(), actual_out.display()); + + panic!("Tree mismatch at step '{}'", step); + } + } + None => { + write_tree_by_name(source_path, step, &tree_with_metadata); + } + } +} + +fn new_cow_map() -> Cow<'static, HashMap> { + Cow::Owned(HashMap::new()) +} + +#[derive(Debug, Serialize, Deserialize)] +struct TreeWithMetadata<'a> { + #[serde(flatten)] + pub tree: Cow<'a, RbxTree>, + + #[serde(default = "new_cow_map")] + pub metadata: Cow<'a, HashMap>, +} + +fn read_tree_by_name(path: &Path, identifier: &str) -> Option> { + let mut file_path = path.join(identifier); + file_path.set_extension("tree.json"); + + let contents = fs::read(&file_path).ok()?; + let tree: TreeWithMetadata = serde_json::from_slice(&contents) + .expect("Could not deserialize tree"); + + Some(tree) +} + +fn write_tree_by_name(path: &Path, identifier: &str, tree: &TreeWithMetadata) { + let mut file_path = path.join(identifier); + file_path.set_extension("tree.json"); + + let mut file = File::create(file_path) + .expect("Could not open file to write tree"); + + serde_json::to_writer_pretty(&mut file, tree) + .expect("Could not serialize tree to file"); +} + +#[derive(Debug)] +pub struct TreeMismatch { + pub path: Cow<'static, str>, + pub detail: Cow<'static, str>, +} + +impl TreeMismatch { + pub fn new<'a, A: Into>, B: Into>>(path: A, detail: B) -> TreeMismatch { + TreeMismatch { + path: Cow::Owned(path.into().into_owned()), + detail: Cow::Owned(detail.into().into_owned()), + } + } + + fn add_parent(mut self, name: &str) -> TreeMismatch { + self.path.to_mut().insert(0, '.'); + self.path.to_mut().insert_str(0, name); + + TreeMismatch { + path: self.path, + detail: self.detail, + } + } +} + +impl fmt::Display for TreeMismatch { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + writeln!(formatter, "Tree mismatch at path {}", self.path)?; + writeln!(formatter, "{}", self.detail) + } +} + +pub fn trees_equal( + left_tree: &RbxTree, + right_tree: &RbxTree, +) -> Result<(), TreeMismatch> { + let left = TreeWithMetadata { + tree: Cow::Borrowed(left_tree), + metadata: Cow::Owned(HashMap::new()), + }; + + let right = TreeWithMetadata { + tree: Cow::Borrowed(right_tree), + metadata: Cow::Owned(HashMap::new()), + }; + + trees_and_metadata_equal(&left, &right) +} + +fn trees_and_metadata_equal( + left_tree: &TreeWithMetadata, + right_tree: &TreeWithMetadata, +) -> Result<(), TreeMismatch> { + let left_id = left_tree.tree.get_root_id(); + let right_id = right_tree.tree.get_root_id(); + + instances_equal(left_tree, left_id, right_tree, right_id) +} + +fn instances_equal( + left_tree: &TreeWithMetadata, + left_id: RbxId, + right_tree: &TreeWithMetadata, + right_id: RbxId, +) -> Result<(), TreeMismatch> { + basic_equal(left_tree, left_id, right_tree, right_id)?; + properties_equal(left_tree, left_id, right_tree, right_id)?; + children_equal(left_tree, left_id, right_tree, right_id)?; + metadata_equal(left_tree, left_id, right_tree, right_id) +} + +fn basic_equal( + left_tree: &TreeWithMetadata, + left_id: RbxId, + right_tree: &TreeWithMetadata, + right_id: RbxId, +) -> Result<(), TreeMismatch> { + let left_instance = left_tree.tree.get_instance(left_id) + .expect("ID did not exist in left tree"); + + let right_instance = right_tree.tree.get_instance(right_id) + .expect("ID did not exist in right tree"); + + if left_instance.name != right_instance.name { + let message = format!("Name did not match ('{}' vs '{}')", left_instance.name, right_instance.name); + + return Err(TreeMismatch::new(&left_instance.name, message)); + } + + if left_instance.class_name != right_instance.class_name { + let message = format!("Class name did not match ('{}' vs '{}')", left_instance.class_name, right_instance.class_name); + + return Err(TreeMismatch::new(&left_instance.name, message)); + } + + Ok(()) +} + +fn properties_equal( + left_tree: &TreeWithMetadata, + left_id: RbxId, + right_tree: &TreeWithMetadata, + right_id: RbxId, +) -> Result<(), TreeMismatch> { + let left_instance = left_tree.tree.get_instance(left_id) + .expect("ID did not exist in left tree"); + + let right_instance = right_tree.tree.get_instance(right_id) + .expect("ID did not exist in right tree"); + + let mut visited = HashSet::new(); + + for (key, left_value) in &left_instance.properties { + visited.insert(key); + + let right_value = right_instance.properties.get(key); + + if Some(left_value) != right_value { + let message = format!( + "Property {}:\n\tLeft: {:?}\n\tRight: {:?}", + key, + Some(left_value), + right_value, + ); + + return Err(TreeMismatch::new(&left_instance.name, message)); + } + } + + for (key, right_value) in &right_instance.properties { + if visited.contains(key) { + continue; + } + + let left_value = left_instance.properties.get(key); + + if left_value != Some(right_value) { + let message = format!( + "Property {}:\n\tLeft: {:?}\n\tRight: {:?}", + key, + left_value, + Some(right_value), + ); + + return Err(TreeMismatch::new(&left_instance.name, message)); + } + } + + Ok(()) +} + +fn children_equal( + left_tree: &TreeWithMetadata, + left_id: RbxId, + right_tree: &TreeWithMetadata, + right_id: RbxId, +) -> Result<(), TreeMismatch> { + let left_instance = left_tree.tree.get_instance(left_id) + .expect("ID did not exist in left tree"); + + let right_instance = right_tree.tree.get_instance(right_id) + .expect("ID did not exist in right tree"); + + let left_children = left_instance.get_children_ids(); + let right_children = right_instance.get_children_ids(); + + if left_children.len() != right_children.len() { + return Err(TreeMismatch::new(&left_instance.name, "Instances had different numbers of children")); + } + + for (left_child_id, right_child_id) in left_children.iter().zip(right_children) { + instances_equal(left_tree, *left_child_id, right_tree, *right_child_id) + .map_err(|e| e.add_parent(&left_instance.name))?; + } + + Ok(()) +} + +fn metadata_equal( + left_tree: &TreeWithMetadata, + left_id: RbxId, + right_tree: &TreeWithMetadata, + right_id: RbxId, +) -> Result<(), TreeMismatch> { + let left_meta = left_tree.metadata.get(&left_id); + let right_meta = right_tree.metadata.get(&right_id); + + if left_meta != right_meta { + let left_instance = left_tree.tree.get_instance(left_id) + .expect("Left instance didn't exist in tree"); + + let message = format!( + "Metadata mismatch:\n\tLeft: {:?}\n\tRight: {:?}", + left_meta, + right_meta, + ); + + return Err(TreeMismatch::new(&left_instance.name, message)); + } + + Ok(()) +} \ No newline at end of file diff --git a/server/tests/tree_snapshots.rs b/server/tests/tree_snapshots.rs new file mode 100644 index 00000000..f5b991fa --- /dev/null +++ b/server/tests/tree_snapshots.rs @@ -0,0 +1,68 @@ +mod test_util; + +use std::{ + fs, + path::{Path, PathBuf}, + sync::Arc, + thread, + time::Duration, +}; + +use tempfile::{tempdir, TempDir}; + +use librojo::{ + live_session::LiveSession, + project::Project, +}; + +use crate::test_util::{ + copy_recursive, + tree::tree_step, +}; + +#[test] +fn multi_partition_game() { + let _ = env_logger::try_init(); + let source_path = project_path("multi_partition_game"); + + let (dir, live_session) = start_session(&source_path); + tree_step("initial", &live_session, &source_path); + + let added_path = dir.path().join("a/added"); + fs::create_dir_all(&added_path) + .expect("Couldn't create directory"); + thread::sleep(Duration::from_millis(250)); + + tree_step("with_dir", &live_session, &source_path); + + let moved_path = dir.path().join("b/added"); + fs::rename(&added_path, &moved_path) + .expect("Couldn't rename directory"); + thread::sleep(Duration::from_millis(250)); + + tree_step("with_moved_dir", &live_session, &source_path); +} + +/// Find the path to the given test project relative to the manifest. +fn project_path(name: &str) -> PathBuf { + let mut path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects"); + path.push(name); + path +} + +/// Starts a new LiveSession for the project located at the given file path. +fn start_session(source_path: &Path) -> (TempDir, LiveSession) { + let dir = tempdir() + .expect("Couldn't create temporary directory"); + + copy_recursive(&source_path, dir.path()) + .expect("Couldn't copy project to temporary directory"); + + let project = Arc::new(Project::load_fuzzy(dir.path()) + .expect("Couldn't load project from temp directory")); + + let live_session = LiveSession::new(Arc::clone(&project)) + .expect("Couldn't start live session"); + + (dir, live_session) +} \ No newline at end of file diff --git a/test-projects/multi_partition_game/a/foo.txt b/test-projects/multi_partition_game/a/foo.txt new file mode 100644 index 00000000..20b6566e --- /dev/null +++ b/test-projects/multi_partition_game/a/foo.txt @@ -0,0 +1 @@ +Hello world, from a/foo.txt \ No newline at end of file diff --git a/test-projects/multi_partition_game/a/main.lua b/test-projects/multi_partition_game/a/main.lua new file mode 100644 index 00000000..23bf7c82 --- /dev/null +++ b/test-projects/multi_partition_game/a/main.lua @@ -0,0 +1 @@ +-- hello, from a/main.lua \ No newline at end of file diff --git a/test-projects/multi_partition_game/b/something.lua b/test-projects/multi_partition_game/b/something.lua new file mode 100644 index 00000000..415e8ebc --- /dev/null +++ b/test-projects/multi_partition_game/b/something.lua @@ -0,0 +1 @@ +-- b/something.lua \ No newline at end of file diff --git a/test-projects/multi_partition_game/default.project.json b/test-projects/multi_partition_game/default.project.json new file mode 100644 index 00000000..9862db3f --- /dev/null +++ b/test-projects/multi_partition_game/default.project.json @@ -0,0 +1,21 @@ +{ + "name": "multi_partition_game", + "tree": { + "$className": "DataModel", + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + "Ack": { + "$path": "a" + }, + "Bar": { + "$path": "b" + } + }, + "HttpService": { + "$className": "HttpService", + "$properties": { + "HttpEnabled": true + } + } + } +} \ No newline at end of file diff --git a/test-projects/multi_partition_game/expected-snapshot.json b/test-projects/multi_partition_game/expected-snapshot.json new file mode 100644 index 00000000..49e76960 --- /dev/null +++ b/test-projects/multi_partition_game/expected-snapshot.json @@ -0,0 +1,212 @@ +{ + "name": "multi_partition_game", + "class_name": "DataModel", + "properties": {}, + "children": [ + { + "name": "HttpService", + "class_name": "HttpService", + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "HttpService", + { + "class_name": "HttpService", + "children": {}, + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "ignore_unknown_instances": null, + "path": null + } + ] + } + }, + { + "name": "ReplicatedStorage", + "class_name": "ReplicatedStorage", + "properties": {}, + "children": [ + { + "name": "Ack", + "class_name": "Folder", + "properties": {}, + "children": [ + { + "name": "foo", + "class_name": "StringValue", + "properties": { + "Value": { + "Type": "String", + "Value": "Hello world, from a/foo.txt" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "a/foo.txt", + "project_definition": null + } + }, + { + "name": "main", + "class_name": "ModuleScript", + "properties": { + "Source": { + "Type": "String", + "Value": "-- hello, from a/main.lua" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "a/main.lua", + "project_definition": null + } + } + ], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "a", + "project_definition": [ + "Ack", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + } + ] + } + }, + { + "name": "Bar", + "class_name": "Folder", + "properties": {}, + "children": [ + { + "name": "something", + "class_name": "ModuleScript", + "properties": { + "Source": { + "Type": "String", + "Value": "-- b/something.lua" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "b/something.lua", + "project_definition": null + } + } + ], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "b", + "project_definition": [ + "Bar", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + ] + } + } + ], + "metadata": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "ReplicatedStorage", + { + "class_name": "ReplicatedStorage", + "children": { + "Bar": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + }, + "Ack": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + } + } + ], + "metadata": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "multi_partition_game", + { + "class_name": "DataModel", + "children": { + "ReplicatedStorage": { + "class_name": "ReplicatedStorage", + "children": { + "Bar": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + }, + "Ack": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + }, + "HttpService": { + "class_name": "HttpService", + "children": {}, + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "ignore_unknown_instances": null, + "path": null + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + } +} \ No newline at end of file diff --git a/test-projects/multi_partition_game/initial.tree.json b/test-projects/multi_partition_game/initial.tree.json new file mode 100644 index 00000000..b6a2208c --- /dev/null +++ b/test-projects/multi_partition_game/initial.tree.json @@ -0,0 +1,242 @@ +{ + "instances": { + "8d44bb30-db3c-4366-a6c5-633bd1441885": { + "Name": "main", + "ClassName": "ModuleScript", + "Properties": { + "Source": { + "Type": "String", + "Value": "-- hello, from a/main.lua" + } + }, + "Id": "8d44bb30-db3c-4366-a6c5-633bd1441885", + "Children": [], + "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" + }, + "b1c9928c-bf11-427f-90eb-b672c811d859": { + "Name": "Bar", + "ClassName": "Folder", + "Properties": {}, + "Id": "b1c9928c-bf11-427f-90eb-b672c811d859", + "Children": [ + "8d690a2a-e987-4c86-b9ac-18e6d3a98503" + ], + "Parent": "9f141826-14c2-492b-b360-2558712f0c08" + }, + "645ba594-4482-441f-9f41-5bb9c444405b": { + "Name": "multi_partition_game", + "ClassName": "DataModel", + "Properties": {}, + "Id": "645ba594-4482-441f-9f41-5bb9c444405b", + "Children": [ + "b1298bcc-e370-44a6-9ef4-fbefa290124c", + "9f141826-14c2-492b-b360-2558712f0c08" + ], + "Parent": null + }, + "9f141826-14c2-492b-b360-2558712f0c08": { + "Name": "ReplicatedStorage", + "ClassName": "ReplicatedStorage", + "Properties": {}, + "Id": "9f141826-14c2-492b-b360-2558712f0c08", + "Children": [ + "1aafa29b-bdca-40a0-a677-7ead327b84ce", + "b1c9928c-bf11-427f-90eb-b672c811d859" + ], + "Parent": "645ba594-4482-441f-9f41-5bb9c444405b" + }, + "8d690a2a-e987-4c86-b9ac-18e6d3a98503": { + "Name": "something", + "ClassName": "ModuleScript", + "Properties": { + "Source": { + "Type": "String", + "Value": "-- b/something.lua" + } + }, + "Id": "8d690a2a-e987-4c86-b9ac-18e6d3a98503", + "Children": [], + "Parent": "b1c9928c-bf11-427f-90eb-b672c811d859" + }, + "b1298bcc-e370-44a6-9ef4-fbefa290124c": { + "Name": "HttpService", + "ClassName": "HttpService", + "Properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "Id": "b1298bcc-e370-44a6-9ef4-fbefa290124c", + "Children": [], + "Parent": "645ba594-4482-441f-9f41-5bb9c444405b" + }, + "54f2f276-964f-4c60-87d8-5fb2209c97c9": { + "Name": "foo", + "ClassName": "StringValue", + "Properties": { + "Value": { + "Type": "String", + "Value": "Hello world, from a/foo.txt" + } + }, + "Id": "54f2f276-964f-4c60-87d8-5fb2209c97c9", + "Children": [], + "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" + }, + "1aafa29b-bdca-40a0-a677-7ead327b84ce": { + "Name": "Ack", + "ClassName": "Folder", + "Properties": {}, + "Id": "1aafa29b-bdca-40a0-a677-7ead327b84ce", + "Children": [ + "54f2f276-964f-4c60-87d8-5fb2209c97c9", + "8d44bb30-db3c-4366-a6c5-633bd1441885" + ], + "Parent": "9f141826-14c2-492b-b360-2558712f0c08" + } + }, + "root_id": "645ba594-4482-441f-9f41-5bb9c444405b", + "metadata": { + "645ba594-4482-441f-9f41-5bb9c444405b": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "multi_partition_game", + { + "class_name": "DataModel", + "children": { + "HttpService": { + "class_name": "HttpService", + "children": {}, + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "ignore_unknown_instances": null, + "path": null + }, + "ReplicatedStorage": { + "class_name": "ReplicatedStorage", + "children": { + "Ack": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + }, + "Bar": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + }, + "1aafa29b-bdca-40a0-a677-7ead327b84ce": { + "ignore_unknown_instances": false, + "source_path": "a", + "project_definition": [ + "Ack", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + } + ] + }, + "b1c9928c-bf11-427f-90eb-b672c811d859": { + "ignore_unknown_instances": false, + "source_path": "b", + "project_definition": [ + "Bar", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + ] + }, + "54f2f276-964f-4c60-87d8-5fb2209c97c9": { + "ignore_unknown_instances": false, + "source_path": "a/foo.txt", + "project_definition": null + }, + "9f141826-14c2-492b-b360-2558712f0c08": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "ReplicatedStorage", + { + "class_name": "ReplicatedStorage", + "children": { + "Ack": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + }, + "Bar": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + }, + "8d44bb30-db3c-4366-a6c5-633bd1441885": { + "ignore_unknown_instances": false, + "source_path": "a/main.lua", + "project_definition": null + }, + "b1298bcc-e370-44a6-9ef4-fbefa290124c": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "HttpService", + { + "class_name": "HttpService", + "children": {}, + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "ignore_unknown_instances": null, + "path": null + } + ] + }, + "8d690a2a-e987-4c86-b9ac-18e6d3a98503": { + "ignore_unknown_instances": false, + "source_path": "b/something.lua", + "project_definition": null + } + } +} \ No newline at end of file diff --git a/test-projects/multi_partition_game/with_dir.tree.json b/test-projects/multi_partition_game/with_dir.tree.json new file mode 100644 index 00000000..5237c507 --- /dev/null +++ b/test-projects/multi_partition_game/with_dir.tree.json @@ -0,0 +1,256 @@ +{ + "instances": { + "8d44bb30-db3c-4366-a6c5-633bd1441885": { + "Name": "main", + "ClassName": "ModuleScript", + "Properties": { + "Source": { + "Type": "String", + "Value": "-- hello, from a/main.lua" + } + }, + "Id": "8d44bb30-db3c-4366-a6c5-633bd1441885", + "Children": [], + "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" + }, + "b1c9928c-bf11-427f-90eb-b672c811d859": { + "Name": "Bar", + "ClassName": "Folder", + "Properties": {}, + "Id": "b1c9928c-bf11-427f-90eb-b672c811d859", + "Children": [ + "8d690a2a-e987-4c86-b9ac-18e6d3a98503" + ], + "Parent": "9f141826-14c2-492b-b360-2558712f0c08" + }, + "645ba594-4482-441f-9f41-5bb9c444405b": { + "Name": "multi_partition_game", + "ClassName": "DataModel", + "Properties": {}, + "Id": "645ba594-4482-441f-9f41-5bb9c444405b", + "Children": [ + "b1298bcc-e370-44a6-9ef4-fbefa290124c", + "9f141826-14c2-492b-b360-2558712f0c08" + ], + "Parent": null + }, + "9f141826-14c2-492b-b360-2558712f0c08": { + "Name": "ReplicatedStorage", + "ClassName": "ReplicatedStorage", + "Properties": {}, + "Id": "9f141826-14c2-492b-b360-2558712f0c08", + "Children": [ + "1aafa29b-bdca-40a0-a677-7ead327b84ce", + "b1c9928c-bf11-427f-90eb-b672c811d859" + ], + "Parent": "645ba594-4482-441f-9f41-5bb9c444405b" + }, + "8d690a2a-e987-4c86-b9ac-18e6d3a98503": { + "Name": "something", + "ClassName": "ModuleScript", + "Properties": { + "Source": { + "Type": "String", + "Value": "-- b/something.lua" + } + }, + "Id": "8d690a2a-e987-4c86-b9ac-18e6d3a98503", + "Children": [], + "Parent": "b1c9928c-bf11-427f-90eb-b672c811d859" + }, + "b1298bcc-e370-44a6-9ef4-fbefa290124c": { + "Name": "HttpService", + "ClassName": "HttpService", + "Properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "Id": "b1298bcc-e370-44a6-9ef4-fbefa290124c", + "Children": [], + "Parent": "645ba594-4482-441f-9f41-5bb9c444405b" + }, + "46353305-8818-48fe-94fd-80cf0c5d974c": { + "Name": "added", + "ClassName": "Folder", + "Properties": {}, + "Id": "46353305-8818-48fe-94fd-80cf0c5d974c", + "Children": [], + "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" + }, + "54f2f276-964f-4c60-87d8-5fb2209c97c9": { + "Name": "foo", + "ClassName": "StringValue", + "Properties": { + "Value": { + "Type": "String", + "Value": "Hello world, from a/foo.txt" + } + }, + "Id": "54f2f276-964f-4c60-87d8-5fb2209c97c9", + "Children": [], + "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" + }, + "1aafa29b-bdca-40a0-a677-7ead327b84ce": { + "Name": "Ack", + "ClassName": "Folder", + "Properties": {}, + "Id": "1aafa29b-bdca-40a0-a677-7ead327b84ce", + "Children": [ + "54f2f276-964f-4c60-87d8-5fb2209c97c9", + "8d44bb30-db3c-4366-a6c5-633bd1441885", + "46353305-8818-48fe-94fd-80cf0c5d974c" + ], + "Parent": "9f141826-14c2-492b-b360-2558712f0c08" + } + }, + "root_id": "645ba594-4482-441f-9f41-5bb9c444405b", + "metadata": { + "b1c9928c-bf11-427f-90eb-b672c811d859": { + "ignore_unknown_instances": false, + "source_path": "b", + "project_definition": [ + "Bar", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + ] + }, + "54f2f276-964f-4c60-87d8-5fb2209c97c9": { + "ignore_unknown_instances": false, + "source_path": "a/foo.txt", + "project_definition": null + }, + "8d44bb30-db3c-4366-a6c5-633bd1441885": { + "ignore_unknown_instances": false, + "source_path": "a/main.lua", + "project_definition": null + }, + "9f141826-14c2-492b-b360-2558712f0c08": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "ReplicatedStorage", + { + "class_name": "ReplicatedStorage", + "children": { + "Ack": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + }, + "Bar": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + }, + "b1298bcc-e370-44a6-9ef4-fbefa290124c": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "HttpService", + { + "class_name": "HttpService", + "children": {}, + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "ignore_unknown_instances": null, + "path": null + } + ] + }, + "46353305-8818-48fe-94fd-80cf0c5d974c": { + "ignore_unknown_instances": false, + "source_path": "a/added", + "project_definition": null + }, + "1aafa29b-bdca-40a0-a677-7ead327b84ce": { + "ignore_unknown_instances": false, + "source_path": "a", + "project_definition": [ + "Ack", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + } + ] + }, + "8d690a2a-e987-4c86-b9ac-18e6d3a98503": { + "ignore_unknown_instances": false, + "source_path": "b/something.lua", + "project_definition": null + }, + "645ba594-4482-441f-9f41-5bb9c444405b": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "multi_partition_game", + { + "class_name": "DataModel", + "children": { + "HttpService": { + "class_name": "HttpService", + "children": {}, + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "ignore_unknown_instances": null, + "path": null + }, + "ReplicatedStorage": { + "class_name": "ReplicatedStorage", + "children": { + "Ack": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + }, + "Bar": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + } + } +} \ No newline at end of file diff --git a/test-projects/multi_partition_game/with_moved_dir.tree.json b/test-projects/multi_partition_game/with_moved_dir.tree.json new file mode 100644 index 00000000..4da8884a --- /dev/null +++ b/test-projects/multi_partition_game/with_moved_dir.tree.json @@ -0,0 +1,256 @@ +{ + "instances": { + "8d44bb30-db3c-4366-a6c5-633bd1441885": { + "Name": "main", + "ClassName": "ModuleScript", + "Properties": { + "Source": { + "Type": "String", + "Value": "-- hello, from a/main.lua" + } + }, + "Id": "8d44bb30-db3c-4366-a6c5-633bd1441885", + "Children": [], + "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" + }, + "b1c9928c-bf11-427f-90eb-b672c811d859": { + "Name": "Bar", + "ClassName": "Folder", + "Properties": {}, + "Id": "b1c9928c-bf11-427f-90eb-b672c811d859", + "Children": [ + "8d690a2a-e987-4c86-b9ac-18e6d3a98503", + "a8566e76-0495-45a3-a713-1c59ab39453b" + ], + "Parent": "9f141826-14c2-492b-b360-2558712f0c08" + }, + "645ba594-4482-441f-9f41-5bb9c444405b": { + "Name": "multi_partition_game", + "ClassName": "DataModel", + "Properties": {}, + "Id": "645ba594-4482-441f-9f41-5bb9c444405b", + "Children": [ + "b1298bcc-e370-44a6-9ef4-fbefa290124c", + "9f141826-14c2-492b-b360-2558712f0c08" + ], + "Parent": null + }, + "9f141826-14c2-492b-b360-2558712f0c08": { + "Name": "ReplicatedStorage", + "ClassName": "ReplicatedStorage", + "Properties": {}, + "Id": "9f141826-14c2-492b-b360-2558712f0c08", + "Children": [ + "1aafa29b-bdca-40a0-a677-7ead327b84ce", + "b1c9928c-bf11-427f-90eb-b672c811d859" + ], + "Parent": "645ba594-4482-441f-9f41-5bb9c444405b" + }, + "8d690a2a-e987-4c86-b9ac-18e6d3a98503": { + "Name": "something", + "ClassName": "ModuleScript", + "Properties": { + "Source": { + "Type": "String", + "Value": "-- b/something.lua" + } + }, + "Id": "8d690a2a-e987-4c86-b9ac-18e6d3a98503", + "Children": [], + "Parent": "b1c9928c-bf11-427f-90eb-b672c811d859" + }, + "b1298bcc-e370-44a6-9ef4-fbefa290124c": { + "Name": "HttpService", + "ClassName": "HttpService", + "Properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "Id": "b1298bcc-e370-44a6-9ef4-fbefa290124c", + "Children": [], + "Parent": "645ba594-4482-441f-9f41-5bb9c444405b" + }, + "54f2f276-964f-4c60-87d8-5fb2209c97c9": { + "Name": "foo", + "ClassName": "StringValue", + "Properties": { + "Value": { + "Type": "String", + "Value": "Hello world, from a/foo.txt" + } + }, + "Id": "54f2f276-964f-4c60-87d8-5fb2209c97c9", + "Children": [], + "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" + }, + "a8566e76-0495-45a3-a713-1c59ab39453b": { + "Name": "added", + "ClassName": "Folder", + "Properties": {}, + "Id": "a8566e76-0495-45a3-a713-1c59ab39453b", + "Children": [], + "Parent": "b1c9928c-bf11-427f-90eb-b672c811d859" + }, + "1aafa29b-bdca-40a0-a677-7ead327b84ce": { + "Name": "Ack", + "ClassName": "Folder", + "Properties": {}, + "Id": "1aafa29b-bdca-40a0-a677-7ead327b84ce", + "Children": [ + "54f2f276-964f-4c60-87d8-5fb2209c97c9", + "8d44bb30-db3c-4366-a6c5-633bd1441885" + ], + "Parent": "9f141826-14c2-492b-b360-2558712f0c08" + } + }, + "root_id": "645ba594-4482-441f-9f41-5bb9c444405b", + "metadata": { + "645ba594-4482-441f-9f41-5bb9c444405b": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "multi_partition_game", + { + "class_name": "DataModel", + "children": { + "HttpService": { + "class_name": "HttpService", + "children": {}, + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "ignore_unknown_instances": null, + "path": null + }, + "ReplicatedStorage": { + "class_name": "ReplicatedStorage", + "children": { + "Ack": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + }, + "Bar": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + }, + "1aafa29b-bdca-40a0-a677-7ead327b84ce": { + "ignore_unknown_instances": false, + "source_path": "a", + "project_definition": [ + "Ack", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + } + ] + }, + "a8566e76-0495-45a3-a713-1c59ab39453b": { + "ignore_unknown_instances": false, + "source_path": "b/added", + "project_definition": null + }, + "8d690a2a-e987-4c86-b9ac-18e6d3a98503": { + "ignore_unknown_instances": false, + "source_path": "b/something.lua", + "project_definition": null + }, + "8d44bb30-db3c-4366-a6c5-633bd1441885": { + "ignore_unknown_instances": false, + "source_path": "a/main.lua", + "project_definition": null + }, + "9f141826-14c2-492b-b360-2558712f0c08": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "ReplicatedStorage", + { + "class_name": "ReplicatedStorage", + "children": { + "Ack": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + }, + "Bar": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + }, + "b1c9928c-bf11-427f-90eb-b672c811d859": { + "ignore_unknown_instances": false, + "source_path": "b", + "project_definition": [ + "Bar", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + ] + }, + "54f2f276-964f-4c60-87d8-5fb2209c97c9": { + "ignore_unknown_instances": false, + "source_path": "a/foo.txt", + "project_definition": null + }, + "b1298bcc-e370-44a6-9ef4-fbefa290124c": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "HttpService", + { + "class_name": "HttpService", + "children": {}, + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "ignore_unknown_instances": null, + "path": null + } + ] + } + } +} \ No newline at end of file From 312724189b4b85747d416565b997b2e022ec6605 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Mar 2019 14:20:38 -0700 Subject: [PATCH 0471/1504] Remove ignore from old doc generator script --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 216fc1c5..b11f390d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,4 @@ /target /scratch-project **/*.rs.bk -/generate-docs.run /server/failed-snapshots/ \ No newline at end of file From 469f9c927f9cb7a0de28725ec217663f400b4a2e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Mar 2019 16:29:31 -0700 Subject: [PATCH 0472/1504] Improve plugin place project for testing --- plugin/place.project.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/place.project.json b/plugin/place.project.json index 9beb7df5..bed97daf 100644 --- a/plugin/place.project.json +++ b/plugin/place.project.json @@ -40,8 +40,8 @@ } }, - "TestService": { - "$className": "TestService", + "ServerScriptService": { + "$className": "ServerScriptService", "TestBootstrap": { "$path": "testBootstrap.server.lua" From f9e86e58d6144f613d1f25390c598ac5a8f41c9a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Mar 2019 16:29:56 -0700 Subject: [PATCH 0473/1504] Add InstanceMap:destroyInstance for forgetting and destroying in one step --- plugin/src/InstanceMap.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 5356ac7b..16cefbd9 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -45,6 +45,16 @@ function InstanceMap:removeInstance(instance) end end +function InstanceMap:destroyInstance(instance) + local id = self.fromInstances[instance] + + if id ~= nil then + self:destroyId(id) + else + Logging.warn("Attempted to destroy untracked instance %s", tostring(instance)) + end +end + function InstanceMap:destroyId(id) local instance = self.fromIds[id] self:removeId(id) From 9f382ed9bd4c21141ecd55cfb3e896d536426390 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Mar 2019 16:30:06 -0700 Subject: [PATCH 0474/1504] Iterate on plugin reconciler - Renamed setProperty to setCanonicalProperty, which is more usefully descriptive. Also added a detailed comment. - Fixed reconciler behavior with regards to removing known instances when $ignoreUnknownInstances is set --- plugin/src/Reconciler.lua | 31 ++- plugin/src/Reconciler.spec.lua | 218 ++++++++++++++++++ ...tProperty.lua => setCanonicalProperty.lua} | 15 +- 3 files changed, 248 insertions(+), 16 deletions(-) create mode 100644 plugin/src/Reconciler.spec.lua rename plugin/src/{setProperty.lua => setCanonicalProperty.lua} (69%) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index e3a7bc40..d63bfddd 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -1,6 +1,6 @@ local InstanceMap = require(script.Parent.InstanceMap) local Logging = require(script.Parent.Logging) -local setProperty = require(script.Parent.setProperty) +local setCanonicalProperty = require(script.Parent.setCanonicalProperty) local rojoValueToRobloxValue = require(script.Parent.rojoValueToRobloxValue) local Reconciler = {} @@ -43,10 +43,10 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) self.instanceMap:insert(id, instance) -- Some instances don't like being named, even if their name already matches - setProperty(instance, "Name", virtualInstance.Name) + setCanonicalProperty(instance, "Name", virtualInstance.Name) for key, value in pairs(virtualInstance.Properties) do - setProperty(instance, key, rojoValueToRobloxValue(value)) + setCanonicalProperty(instance, key, rojoValueToRobloxValue(value)) end local existingChildren = instance:GetChildren() @@ -81,10 +81,17 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) end end - if self:__shouldClearUnknownInstances(virtualInstance) then - for existingChildInstance in pairs(unvisitedExistingChildren) do - self.instanceMap:removeInstance(existingChildInstance) - existingChildInstance:Destroy() + local shouldClearUnknown = self:__shouldClearUnknownChildren(virtualInstance) + + for existingChildInstance in pairs(unvisitedExistingChildren) do + local childId = self.instanceMap.fromInstances[existingChildInstance] + + if childId == nil then + if shouldClearUnknown then + existingChildInstance:Destroy() + end + else + self.instanceMap:destroyInstance(existingChildInstance) end end @@ -100,13 +107,13 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) -- Some instances, like services, don't like having their Parent -- property poked, even if we're setting it to the same value. - setProperty(instance, "Parent", parent) + setCanonicalProperty(instance, "Parent", parent) end return instance end -function Reconciler:__shouldClearUnknownInstances(virtualInstance) +function Reconciler:__shouldClearUnknownChildren(virtualInstance) if virtualInstance.Metadata ~= nil then return not virtualInstance.Metadata.ignoreUnknownInstances else @@ -120,16 +127,16 @@ function Reconciler:__reify(virtualInstancesById, id, parent) local instance = Instance.new(virtualInstance.ClassName) for key, value in pairs(virtualInstance.Properties) do - setProperty(instance, key, rojoValueToRobloxValue(value)) + setCanonicalProperty(instance, key, rojoValueToRobloxValue(value)) end - instance.Name = virtualInstance.Name + setCanonicalProperty(instance, "Name", virtualInstance.Name) for _, childId in ipairs(virtualInstance.Children) do self:__reify(virtualInstancesById, childId, instance) end - setProperty(instance, "Parent", parent) + setCanonicalProperty(instance, "Parent", parent) self.instanceMap:insert(id, instance) return instance diff --git a/plugin/src/Reconciler.spec.lua b/plugin/src/Reconciler.spec.lua new file mode 100644 index 00000000..794c4d08 --- /dev/null +++ b/plugin/src/Reconciler.spec.lua @@ -0,0 +1,218 @@ +local Reconciler = require(script.Parent.Reconciler) + +return function() + it("should leave instances alone if there's nothing specified", function() + local instance = Instance.new("Folder") + instance.Name = "TestFolder" + + local instanceId = "test-id" + local virtualInstancesById = { + [instanceId] = { + Name = "TestFolder", + ClassName = "Folder", + Children = {}, + Properties = {}, + }, + } + + local reconciler = Reconciler.new() + reconciler:reconcile(virtualInstancesById, instanceId, instance) + end) + + it("should assign names from virtual instances", function() + local instance = Instance.new("Folder") + instance.Name = "InitialName" + + local instanceId = "test-id" + local virtualInstancesById = { + [instanceId] = { + Name = "NewName", + ClassName = "Folder", + Children = {}, + Properties = {}, + }, + } + + local reconciler = Reconciler.new() + reconciler:reconcile(virtualInstancesById, instanceId, instance) + + expect(instance.Name).to.equal("NewName") + end) + + it("should assign properties from virtual instances", function() + local instance = Instance.new("IntValue") + instance.Name = "TestValue" + instance.Value = 5 + + local instanceId = "test-id" + local virtualInstancesById = { + [instanceId] = { + Name = "TestValue", + ClassName = "IntValue", + Children = {}, + Properties = { + Value = { + Type = "Int32", + Value = 9 + } + }, + }, + } + + local reconciler = Reconciler.new() + reconciler:reconcile(virtualInstancesById, instanceId, instance) + + expect(instance.Value).to.equal(9) + end) + + it("should wipe unknown children by default", function() + local parent = Instance.new("Folder") + parent.Name = "Parent" + + local child = Instance.new("Folder") + child.Name = "Child" + + local parentId = "test-id" + local virtualInstancesById = { + [parentId] = { + Name = "Parent", + ClassName = "Folder", + Children = {}, + Properties = {}, + }, + } + + local reconciler = Reconciler.new() + reconciler:reconcile(virtualInstancesById, parentId, parent) + + expect(#parent:GetChildren()).to.equal(0) + end) + + it("should preserve unknown children if ignoreUnknownInstances is set", function() + local parent = Instance.new("Folder") + parent.Name = "Parent" + + local child = Instance.new("Folder") + child.Parent = parent + child.Name = "Child" + + local parentId = "test-id" + local virtualInstancesById = { + [parentId] = { + Name = "Parent", + ClassName = "Folder", + Children = {}, + Properties = {}, + Metadata = { + ignoreUnknownInstances = true, + }, + }, + } + + local reconciler = Reconciler.new() + reconciler:reconcile(virtualInstancesById, parentId, parent) + + expect(child.Parent).to.equal(parent) + expect(#parent:GetChildren()).to.equal(1) + end) + + it("should remove known removed children", function() + local parent = Instance.new("Folder") + parent.Name = "Parent" + + local child = Instance.new("Folder") + child.Parent = parent + child.Name = "Child" + + local parentId = "parent-id" + local childId = "child-id" + + local reconciler = Reconciler.new() + + local virtualInstancesById = { + [parentId] = { + Name = "Parent", + ClassName = "Folder", + Children = {childId}, + Properties = {}, + }, + [childId] = { + Name = "Child", + ClassName = "Folder", + Children = {}, + Properties = {}, + }, + } + reconciler:reconcile(virtualInstancesById, parentId, parent) + + expect(child.Parent).to.equal(parent) + expect(#parent:GetChildren()).to.equal(1) + + local newVirtualInstances = { + [parentId] = { + Name = "Parent", + ClassName = "Folder", + Children = {}, + Properties = {}, + }, + [childId] = nil, + } + reconciler:reconcile(newVirtualInstances, parentId, parent) + + expect(child.Parent).to.equal(nil) + expect(#parent:GetChildren()).to.equal(0) + end) + + it("should remove known removed children if ignoreUnknownInstances is set", function() + local parent = Instance.new("Folder") + parent.Name = "Parent" + + local child = Instance.new("Folder") + child.Parent = parent + child.Name = "Child" + + local parentId = "parent-id" + local childId = "child-id" + + local reconciler = Reconciler.new() + + local virtualInstancesById = { + [parentId] = { + Name = "Parent", + ClassName = "Folder", + Children = {childId}, + Properties = {}, + Metadata = { + ignoreUnknownInstances = true, + }, + }, + [childId] = { + Name = "Child", + ClassName = "Folder", + Children = {}, + Properties = {}, + }, + } + reconciler:reconcile(virtualInstancesById, parentId, parent) + + expect(child.Parent).to.equal(parent) + expect(#parent:GetChildren()).to.equal(1) + + local newVirtualInstances = { + [parentId] = { + Name = "Parent", + ClassName = "Folder", + Children = {}, + Properties = {}, + Metadata = { + ignoreUnknownInstances = true, + }, + }, + [childId] = nil, + } + reconciler:reconcile(newVirtualInstances, parentId, parent) + + expect(child.Parent).to.equal(nil) + expect(#parent:GetChildren()).to.equal(0) + end) +end \ No newline at end of file diff --git a/plugin/src/setProperty.lua b/plugin/src/setCanonicalProperty.lua similarity index 69% rename from plugin/src/setProperty.lua rename to plugin/src/setCanonicalProperty.lua index 76a44f82..d7e1e7d8 100644 --- a/plugin/src/setProperty.lua +++ b/plugin/src/setCanonicalProperty.lua @@ -1,10 +1,17 @@ local Logging = require(script.Parent.Logging) --[[ - Attempts to set a property on the given instance, correctly handling - 'virtual properties', which aren't reflected directly to Lua. + Attempts to set a property on the given instance. + + This method deals in terms of what Rojo calls 'canonical properties', which + don't necessarily exist either in serialization or in Lua-reflected APIs, + but may be present in the API dump. + + Ideally, canonical properties map 1:1 with properties we can assign, but in + some cases like LocalizationTable contents and CollectionService tags, we + have to read/write properties a little differently. ]] -local function setProperty(instance, key, value) +local function setCanonicalProperty(instance, key, value) -- The 'Contents' property of LocalizationTable isn't directly exposed, but -- has corresponding (deprecated) getters and setters. if instance.ClassName == "LocalizationTable" and key == "Contents" then @@ -42,4 +49,4 @@ local function setProperty(instance, key, value) return true end -return setProperty \ No newline at end of file +return setCanonicalProperty \ No newline at end of file From 6c3737df68eb37466b69bda4d529b51a26d451dc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Mar 2019 16:31:34 -0700 Subject: [PATCH 0475/1504] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2cc5b4e5..e201ba49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Improved default properties to be closer to Studio's built-in 'Baseplate' template * Added a baseplate to the project file (Thanks, [@AmaranthineCodices](https://github.com/AmaranthineCodices/)!) * Added more type support to Rojo plugin +* Fixed some cases where the Rojo plugin would leave around objects that it knows should be deleted ## [0.5.0 Alpha 5](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.5) (March 1, 2019) * Upgraded core dependencies, which improves compatibility for lots of instance types From 4d6a5048369cae617b8b705c35a3cf576b73cfb7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Mar 2019 16:34:53 -0700 Subject: [PATCH 0476/1504] Remove Rodux and Roact-Rodux, add t dependency --- .gitmodules | 9 +++------ plugin/default.project.json | 9 +++------ plugin/modules/roact-rodux | 1 - plugin/modules/rodux | 1 - plugin/modules/t | 1 + plugin/place.project.json | 9 +++------ 6 files changed, 10 insertions(+), 20 deletions(-) delete mode 160000 plugin/modules/roact-rodux delete mode 160000 plugin/modules/rodux create mode 160000 plugin/modules/t diff --git a/.gitmodules b/.gitmodules index a43f0aff..741d18ac 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,12 +1,6 @@ [submodule "plugin/modules/roact"] path = plugin/modules/roact url = https://github.com/Roblox/roact.git -[submodule "plugin/modules/rodux"] - path = plugin/modules/rodux - url = https://github.com/Roblox/rodux.git -[submodule "plugin/modules/roact-rodux"] - path = plugin/modules/roact-rodux - url = https://github.com/Roblox/roact-rodux.git [submodule "plugin/modules/testez"] path = plugin/modules/testez url = https://github.com/Roblox/testez.git @@ -16,3 +10,6 @@ [submodule "plugin/modules/promise"] path = plugin/modules/promise url = https://github.com/LPGhatguy/roblox-lua-promise.git +[submodule "plugin/modules/t"] + path = plugin/modules/t + url = https://github.com/osyrisrblx/t.git \ No newline at end of file diff --git a/plugin/default.project.json b/plugin/default.project.json index 1d1ace9f..2cf6eadc 100644 --- a/plugin/default.project.json +++ b/plugin/default.project.json @@ -8,14 +8,11 @@ "Roact": { "$path": "modules/roact/lib" }, - "Rodux": { - "$path": "modules/rodux/lib" - }, - "RoactRodux": { - "$path": "modules/roact-rodux/lib" - }, "Promise": { "$path": "modules/promise/lib" + }, + "t": { + "$path": "modules/t/lib/t.lua" } } } \ No newline at end of file diff --git a/plugin/modules/roact-rodux b/plugin/modules/roact-rodux deleted file mode 160000 index 5d2e6885..00000000 --- a/plugin/modules/roact-rodux +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5d2e6885fc7a340e4d4e455a928419ec3cbd2e65 diff --git a/plugin/modules/rodux b/plugin/modules/rodux deleted file mode 160000 index 862f1c76..00000000 --- a/plugin/modules/rodux +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 862f1c769ac31f9041f89433458336397988538c diff --git a/plugin/modules/t b/plugin/modules/t new file mode 160000 index 00000000..a3a80ebf --- /dev/null +++ b/plugin/modules/t @@ -0,0 +1 @@ +Subproject commit a3a80ebf0a45f435c38cc3e719844ad1b6245cec diff --git a/plugin/place.project.json b/plugin/place.project.json index bed97daf..9ba8c85b 100644 --- a/plugin/place.project.json +++ b/plugin/place.project.json @@ -15,14 +15,11 @@ "Roact": { "$path": "modules/roact/lib" }, - "Rodux": { - "$path": "modules/rodux/lib" - }, - "RoactRodux": { - "$path": "modules/roact-rodux/lib" - }, "Promise": { "$path": "modules/promise/lib" + }, + "t": { + "$path": "modules/t/lib/t.lua" } }, "TestEZ": { From b6989a18fc347c5674176e1d4423cdc4d941b6f4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Mar 2019 17:57:19 -0700 Subject: [PATCH 0477/1504] Add conditionally-enabled typechecking using t --- plugin/src/DevSettings.lua | 68 ++++++++++++++++++++++++++++++--- plugin/src/Reconciler.lua | 26 +++++++++++++ plugin/src/Types.lua | 36 +++++++++++++++++ plugin/testBootstrap.server.lua | 21 +++++++++- 4 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 plugin/src/Types.lua diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua index 8edf7efb..060742c2 100644 --- a/plugin/src/DevSettings.lua +++ b/plugin/src/DevSettings.lua @@ -1,10 +1,27 @@ local Config = require(script.Parent.Config) +local Environment = { + User = "User", + Dev = "Dev", + Test = "Test", +} + local VALUES = { LogLevel = { type = "IntValue", - defaultUserValue = 2, - defaultDevValue = 3, + values = { + [Environment.User] = 2, + [Environment.Dev] = 3, + [Environment.Test] = 3, + }, + }, + TypecheckingEnabled = { + type = "BoolValue", + values = { + [Environment.User] = false, + [Environment.Dev] = true, + [Environment.Test] = true, + }, }, } @@ -42,7 +59,9 @@ local function setStoredValue(name, kind, value) object.Value = value end -local function createAllValues() +local function createAllValues(environment) + assert(Environment[environment] ~= nil, "Invalid environment") + valueContainer = getValueContainer() if valueContainer == nil then @@ -52,20 +71,57 @@ local function createAllValues() end for name, value in pairs(VALUES) do - setStoredValue(name, value.type, value.defaultDevValue) + setStoredValue(name, value.type, value.values[environment]) end end -_G[("ROJO_%s_DEV_CREATE"):format(Config.codename:upper())] = createAllValues +local function getValue(name) + assert(VALUES[name] ~= nil, "Invalid DevSettings name") + + local stored = getStoredValue(name) + + if stored ~= nil then + return stored + end + + return VALUES[name].values[Environment.User] +end local DevSettings = {} +function DevSettings:createDevSettings() + createAllValues(Environment.Dev) +end + +function DevSettings:createTestSettings() + createAllValues(Environment.Test) +end + +function DevSettings:hasChangedValues() + return valueContainer ~= nil +end + +function DevSettings:resetValues() + if valueContainer then + valueContainer:Destroy() + valueContainer = nil + end +end + function DevSettings:isEnabled() return valueContainer ~= nil end function DevSettings:getLogLevel() - return getStoredValue("LogLevel") or VALUES.LogLevel.defaultUserValue + return getValue("LogLevel") +end + +function DevSettings:shouldTypecheck() + return getValue("TypecheckingEnabled") +end + +function _G.ROJO_DEV_CREATE() + DevSettings:createDevSettings() end return DevSettings \ No newline at end of file diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index d63bfddd..58eb4182 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -1,7 +1,10 @@ +local t = require(script.Parent.Parent.t) + local InstanceMap = require(script.Parent.InstanceMap) local Logging = require(script.Parent.Logging) local setCanonicalProperty = require(script.Parent.setCanonicalProperty) local rojoValueToRobloxValue = require(script.Parent.rojoValueToRobloxValue) +local Types = require(script.Parent.Types) local Reconciler = {} Reconciler.__index = Reconciler @@ -24,11 +27,18 @@ function Reconciler:applyUpdate(requestedIds, virtualInstancesById) end end +local reconcileSchema = Types.ifEnabled(t.tuple( + t.map(t.string, Types.VirtualInstance), + t.string, + t.Instance +)) --[[ Update an existing instance, including its properties and children, to match the given information. ]] function Reconciler:reconcile(virtualInstancesById, id, instance) + assert(reconcileSchema(virtualInstancesById, id, instance)) + local virtualInstance = virtualInstancesById[id] -- If an instance changes ClassName, we assume it's very different. That's @@ -121,7 +131,15 @@ function Reconciler:__shouldClearUnknownChildren(virtualInstance) end end +local reifySchema = Types.ifEnabled(t.tuple( + t.map(t.string, Types.VirtualInstance), + t.string, + t.Instance +)) + function Reconciler:__reify(virtualInstancesById, id, parent) + assert(reifySchema(virtualInstancesById, id, parent)) + local virtualInstance = virtualInstancesById[id] local instance = Instance.new(virtualInstance.ClassName) @@ -142,7 +160,15 @@ function Reconciler:__reify(virtualInstancesById, id, parent) return instance end +local applyUpdatePieceSchema = Types.ifEnabled(t.tuple( + t.string, + t.map(t.string, t.boolean), + t.map(t.string, Types.VirtualInstance) +)) + function Reconciler:__applyUpdatePiece(id, visitedIds, virtualInstancesById) + assert(applyUpdatePieceSchema(id, visitedIds, virtualInstancesById)) + if visitedIds[id] then return end diff --git a/plugin/src/Types.lua b/plugin/src/Types.lua new file mode 100644 index 00000000..f182d60a --- /dev/null +++ b/plugin/src/Types.lua @@ -0,0 +1,36 @@ +local t = require(script.Parent.Parent.t) + +local DevSettings = require(script.Parent.DevSettings) + +local VirtualValue = t.interface({ + Type = t.string, + Value = t.optional(t.any), +}) + +local VirtualMetadata = t.interface({ + ignoreUnknownInstances = t.optional(t.boolean), +}) + +local VirtualInstance = t.interface({ + Name = t.string, + ClassName = t.string, + Properties = t.map(t.string, VirtualValue), + Metadata = t.optional(VirtualMetadata) +}) + +local function ifEnabled(innerCheck) + return function(...) + if DevSettings:shouldTypecheck() then + return innerCheck(...) + else + return true + end + end +end + +return { + ifEnabled = ifEnabled, + VirtualInstance = VirtualInstance, + VirtualMetadata = VirtualMetadata, + VirtualValue = VirtualValue, +} \ No newline at end of file diff --git a/plugin/testBootstrap.server.lua b/plugin/testBootstrap.server.lua index 4d10558a..81ed88b2 100644 --- a/plugin/testBootstrap.server.lua +++ b/plugin/testBootstrap.server.lua @@ -1,2 +1,19 @@ -local TestEZ = require(game.ReplicatedStorage.TestEZ) -TestEZ.TestBootstrap:run({game.ReplicatedStorage.Rojo.Plugin}) \ No newline at end of file +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local TestEZ = require(ReplicatedStorage.TestEZ) + +local Rojo = ReplicatedStorage.Rojo + +local DevSettings = require(Rojo.Plugin.DevSettings) + +local setDevSettings = not DevSettings:hasChangedValues() + +if setDevSettings then + DevSettings:createTestSettings() +end + +TestEZ.TestBootstrap:run({Rojo.Plugin}) + +if setDevSettings then + DevSettings:resetValues() +end \ No newline at end of file From 2968b70e6b19a0fa096cbe9f810f4d52f15502bc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Mar 2019 18:17:03 -0700 Subject: [PATCH 0478/1504] Listen to Plugin.Unloading. Closes #127. --- plugin/src/Components/App.lua | 7 +++++++ plugin/src/init.server.lua | 8 +++----- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 7d534759..79436972 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -182,6 +182,13 @@ function App:didMount() preloadAssets() end +function App:willUnmount() + if self.currentSession ~= nil then + self.currentSession:disconnect() + self.currentSession = nil + end +end + function App:didUpdate() local connectActive = self.state.sessionStatus == SessionStatus.ConfiguringSession or self.state.sessionStatus == SessionStatus.Connected diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index dc547c85..b3b52bd0 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -4,10 +4,6 @@ end local Roact = require(script.Parent.Roact) -Roact.setGlobalConfig({ - elementTracing = true, -}) - local App = require(script.Components.App) local app = Roact.createElement(App, { @@ -16,4 +12,6 @@ local app = Roact.createElement(App, { Roact.mount(app, game:GetService("CoreGui"), "Rojo UI") --- TODO: Detect another instance of Rojo coming online and shut down this one. \ No newline at end of file +plugin.Unloading:Connect(function() + Roact.unmount(app) +end) \ No newline at end of file From 459673bd59e0b57c1df080c3e6cc91053ee2b1eb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Mar 2019 18:24:30 -0700 Subject: [PATCH 0479/1504] 0.5.0-alpha.6 --- CHANGELOG.md | 7 +++++-- Cargo.lock | 2 +- docs/installation.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 5 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e201ba49..45fd9b5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,13 +1,16 @@ # Rojo Changelog ## [Unreleased] -* Fixed `cargo init` giving unexpected results by upgrading to `rbx_dom_weak` 1.1.0 -* Fixed API not responding when the Rojo plugin is connected ([#133](https://github.com/LPGhatguy/rojo/issues/133)) + +## [0.5.0 Alpha 6](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.6) (March 19, 2019) +* Fixed `rojo init` giving unexpected results by upgrading to `rbx_dom_weak` 1.1.0 +* Fixed live server not responding when the Rojo plugin is connected ([#133](https://github.com/LPGhatguy/rojo/issues/133)) * Updated default place file: * Improved default properties to be closer to Studio's built-in 'Baseplate' template * Added a baseplate to the project file (Thanks, [@AmaranthineCodices](https://github.com/AmaranthineCodices/)!) * Added more type support to Rojo plugin * Fixed some cases where the Rojo plugin would leave around objects that it knows should be deleted +* Updated plugin to correctly listen to `Plugin.Unloading` when installing or uninstalling new plugins ## [0.5.0 Alpha 5](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.5) (March 1, 2019) * Upgraded core dependencies, which improves compatibility for lots of instance types diff --git a/Cargo.lock b/Cargo.lock index 189076f3..12d98bff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0-alpha.5" +version = "0.5.0-alpha.6" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/docs/installation.md b/docs/installation.md index 0a87cbd1..ea27f3d1 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -25,7 +25,7 @@ If you have Rust installed, the easiest way to get Rojo is with Cargo! To install the latest 0.5.0 alpha, use: ```sh -cargo install rojo --version 0.5.0-alpha.5 +cargo install rojo --version 0.5.0-alpha.6 ``` ## Installing the Plugin diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index ab777370..666418e9 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0, "-alpha.5"}, + version = {0, 5, 0, "-alpha.6"}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/server/Cargo.toml b/server/Cargo.toml index 47b4dccf..e005a52d 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0-alpha.5" +version = "0.5.0-alpha.6" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From be094d5b7cea1d767bde79eca6cf33496954cadf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 20 Mar 2019 10:39:53 -0700 Subject: [PATCH 0480/1504] Make snapshot application communicative (#135) * Add children sorting to snapshot_reconciler * Update snapshot tests to include stable children order * Bump dependencies, which should make this PR work --- Cargo.lock | 12 +- server/Cargo.toml | 2 +- server/src/snapshot_reconciler.rs | 59 ++- server/tests/snapshot_reconciler.rs | 5 +- .../multi_partition_game/initial.tree.json | 316 ++++++++-------- .../multi_partition_game/with_dir.tree.json | 236 ++++++------ .../with_moved_dir.tree.json | 340 +++++++++--------- 7 files changed, 496 insertions(+), 474 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 12d98bff..9b25678f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1034,12 +1034,12 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_dom_weak" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1055,7 +1055,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1068,7 +1068,7 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1200,7 +1200,7 @@ dependencies = [ "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 2.0.374 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1874,7 +1874,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147f236284747ac1b4643476265dd36b402877d97adb7cbd0fafc1d247de0a5" -"checksum rbx_dom_weak 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e31ec3223caeb1a57254a8a10b33614a2d457517be01ef93694f83d995833b04" +"checksum rbx_dom_weak 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f2a2ba185abc08fa3fce3de6dc5446ccf82b759583aee20fc07fced859dcc31f" "checksum rbx_reflection 2.0.374 (registry+https://github.com/rust-lang/crates.io-index)" = "8a826ff869b33b54db727f9776f1dc7a8a779791f5a46ddd4941b8334bf909fe" "checksum rbx_xml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a240c155684b744c4985f283702b61f6ab0a2d4479694051d875844632c9f454" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" diff --git a/server/Cargo.toml b/server/Cargo.toml index e005a52d..d7732f3d 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -30,7 +30,7 @@ log = "0.4" maplit = "1.0.1" notify = "4.0" rbx_binary = "0.4.0" -rbx_dom_weak = "1.2.0" +rbx_dom_weak = "1.3.0" rbx_xml = "0.5.0" rbx_reflection = "2.0.374" regex = "1.0" diff --git a/server/src/snapshot_reconciler.rs b/server/src/snapshot_reconciler.rs index 2b52ca52..baaa3309 100644 --- a/server/src/snapshot_reconciler.rs +++ b/server/src/snapshot_reconciler.rs @@ -153,7 +153,7 @@ pub fn reify_subtree( instance_per_path: &mut PathMap>, metadata_per_instance: &mut HashMap, changes: &mut InstanceChanges, -) { +) -> RbxId { let instance = reify_core(snapshot); let id = tree.insert_instance(instance, parent_id); @@ -164,6 +164,8 @@ pub fn reify_subtree( for child in &snapshot.children { reify_subtree(child, tree, id, instance_per_path, metadata_per_instance, changes); } + + id } fn reify_metadata( @@ -222,6 +224,9 @@ fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstanceProperties { instance } +/// Updates the given instance to match the properties defined on the snapshot. +/// +/// Returns whether any changes were applied. fn reconcile_instance_properties(instance: &mut RbxInstanceProperties, snapshot: &RbxSnapshotInstance) -> bool { let mut has_diffs = false; @@ -279,6 +284,8 @@ fn reconcile_instance_properties(instance: &mut RbxInstanceProperties, snapshot: has_diffs } +/// Updates the children of the instance in the `RbxTree` to match the children +/// of the `RbxSnapshotInstance`. Order will be updated to match. fn reconcile_instance_children( tree: &mut RbxTree, id: RbxId, @@ -287,12 +294,21 @@ fn reconcile_instance_children( metadata_per_instance: &mut HashMap, changes: &mut InstanceChanges, ) { - let mut visited_snapshot_indices = HashSet::new(); - - let mut children_to_update: Vec<(RbxId, &RbxSnapshotInstance)> = Vec::new(); - let mut children_to_add: Vec<&RbxSnapshotInstance> = Vec::new(); + // These lists are kept so that we can apply all the changes we figure out + let mut children_to_maybe_update: Vec<(RbxId, &RbxSnapshotInstance)> = Vec::new(); + let mut children_to_add: Vec<(usize, &RbxSnapshotInstance)> = Vec::new(); let mut children_to_remove: Vec = Vec::new(); + // This map is used once we're done mutating children to sort them according + // to the order specified in the snapshot. Without it, a snapshot with a new + // child prepended will cause the RbxTree instance to have out-of-order + // children and would make Rojo non-deterministic. + let mut ids_to_snapshot_indices = HashMap::new(); + + // Since we have to enumerate the children of both the RbxTree instance and + // our snapshot, we keep a set of the snapshot children we've seen. + let mut visited_snapshot_indices = vec![false; snapshot.children.len()]; + let children_ids = tree.get_instance(id).unwrap().get_children_ids(); // Find all instances that were removed or updated, which we derive by @@ -303,7 +319,7 @@ fn reconcile_instance_children( // Locate a matching snapshot for this instance let mut matching_snapshot = None; for (snapshot_index, child_snapshot) in snapshot.children.iter().enumerate() { - if visited_snapshot_indices.contains(&snapshot_index) { + if visited_snapshot_indices[snapshot_index] { continue; } @@ -311,7 +327,8 @@ fn reconcile_instance_children( // similar. This heuristic is similar to React's reconciliation // strategy. if child_snapshot.name == child_instance.name { - visited_snapshot_indices.insert(snapshot_index); + ids_to_snapshot_indices.insert(child_id, snapshot_index); + visited_snapshot_indices[snapshot_index] = true; matching_snapshot = Some(child_snapshot); break; } @@ -319,26 +336,23 @@ fn reconcile_instance_children( match matching_snapshot { Some(child_snapshot) => { - children_to_update.push((child_instance.get_id(), child_snapshot)); - }, + children_to_maybe_update.push((child_instance.get_id(), child_snapshot)); + } None => { children_to_remove.push(child_instance.get_id()); - }, + } } } // Find all instancs that were added, which is just the snapshots we didn't // match up to existing instances above. for (snapshot_index, child_snapshot) in snapshot.children.iter().enumerate() { - if !visited_snapshot_indices.contains(&snapshot_index) { - children_to_add.push(child_snapshot); + if !visited_snapshot_indices[snapshot_index] { + children_to_add.push((snapshot_index, child_snapshot)); } } - for child_snapshot in &children_to_add { - reify_subtree(child_snapshot, tree, id, instance_per_path, metadata_per_instance, changes); - } - + // Apply all of our removals we gathered from our diff for child_id in &children_to_remove { if let Some(subtree) = tree.remove_instance(*child_id) { for id in subtree.iter_all_ids() { @@ -348,7 +362,18 @@ fn reconcile_instance_children( } } - for (child_id, child_snapshot) in &children_to_update { + // Apply all of our children additions + for (snapshot_index, child_snapshot) in &children_to_add { + let id = reify_subtree(child_snapshot, tree, id, instance_per_path, metadata_per_instance, changes); + ids_to_snapshot_indices.insert(id, *snapshot_index); + } + + // Apply any updates that might have updates + for (child_id, child_snapshot) in &children_to_maybe_update { reconcile_subtree(tree, *child_id, child_snapshot, instance_per_path, metadata_per_instance, changes); } + + // Apply the sort mapping defined by ids_to_snapshot_indices above + let instance = tree.get_instance_mut(id).unwrap(); + instance.sort_children_unstable_by_key(|id| ids_to_snapshot_indices.get(&id).unwrap()); } \ No newline at end of file diff --git a/server/tests/snapshot_reconciler.rs b/server/tests/snapshot_reconciler.rs index 4888e917..34dec829 100644 --- a/server/tests/snapshot_reconciler.rs +++ b/server/tests/snapshot_reconciler.rs @@ -11,10 +11,7 @@ use librojo::{ use test_util::tree::trees_equal; -// TODO: Snapshot application isn't communicative right now with the current -// snapshot reconciler. In practice this mostly isn't a problem, but presents -// a problem trying to rely on determinism to make snapshot tests. -// #[test] +#[test] fn patch_communicativity() { let base_tree = RbxTree::new(RbxInstanceProperties { name: "DataModel".into(), diff --git a/test-projects/multi_partition_game/initial.tree.json b/test-projects/multi_partition_game/initial.tree.json index b6a2208c..9b5d5f08 100644 --- a/test-projects/multi_partition_game/initial.tree.json +++ b/test-projects/multi_partition_game/initial.tree.json @@ -1,6 +1,6 @@ { "instances": { - "8d44bb30-db3c-4366-a6c5-633bd1441885": { + "00f207b1-fc18-4088-a45e-caf8cd98f5dd": { "Name": "main", "ClassName": "ModuleScript", "Properties": { @@ -9,69 +9,32 @@ "Value": "-- hello, from a/main.lua" } }, - "Id": "8d44bb30-db3c-4366-a6c5-633bd1441885", + "Id": "00f207b1-fc18-4088-a45e-caf8cd98f5dd", "Children": [], - "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" + "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" }, - "b1c9928c-bf11-427f-90eb-b672c811d859": { + "14fed1a3-ba97-46a6-ae93-ac26bd9471df": { + "Name": "Ack", + "ClassName": "Folder", + "Properties": {}, + "Id": "14fed1a3-ba97-46a6-ae93-ac26bd9471df", + "Children": [ + "c55fd55c-258e-4a93-a63a-ea243038c9b9", + "00f207b1-fc18-4088-a45e-caf8cd98f5dd" + ], + "Parent": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" + }, + "c910510c-37a8-4fd8-ae41-01169ccb739c": { "Name": "Bar", "ClassName": "Folder", "Properties": {}, - "Id": "b1c9928c-bf11-427f-90eb-b672c811d859", + "Id": "c910510c-37a8-4fd8-ae41-01169ccb739c", "Children": [ - "8d690a2a-e987-4c86-b9ac-18e6d3a98503" + "71a95983-c856-4cf2-aee6-bd8a523e80e4" ], - "Parent": "9f141826-14c2-492b-b360-2558712f0c08" + "Parent": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" }, - "645ba594-4482-441f-9f41-5bb9c444405b": { - "Name": "multi_partition_game", - "ClassName": "DataModel", - "Properties": {}, - "Id": "645ba594-4482-441f-9f41-5bb9c444405b", - "Children": [ - "b1298bcc-e370-44a6-9ef4-fbefa290124c", - "9f141826-14c2-492b-b360-2558712f0c08" - ], - "Parent": null - }, - "9f141826-14c2-492b-b360-2558712f0c08": { - "Name": "ReplicatedStorage", - "ClassName": "ReplicatedStorage", - "Properties": {}, - "Id": "9f141826-14c2-492b-b360-2558712f0c08", - "Children": [ - "1aafa29b-bdca-40a0-a677-7ead327b84ce", - "b1c9928c-bf11-427f-90eb-b672c811d859" - ], - "Parent": "645ba594-4482-441f-9f41-5bb9c444405b" - }, - "8d690a2a-e987-4c86-b9ac-18e6d3a98503": { - "Name": "something", - "ClassName": "ModuleScript", - "Properties": { - "Source": { - "Type": "String", - "Value": "-- b/something.lua" - } - }, - "Id": "8d690a2a-e987-4c86-b9ac-18e6d3a98503", - "Children": [], - "Parent": "b1c9928c-bf11-427f-90eb-b672c811d859" - }, - "b1298bcc-e370-44a6-9ef4-fbefa290124c": { - "Name": "HttpService", - "ClassName": "HttpService", - "Properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "Id": "b1298bcc-e370-44a6-9ef4-fbefa290124c", - "Children": [], - "Parent": "645ba594-4482-441f-9f41-5bb9c444405b" - }, - "54f2f276-964f-4c60-87d8-5fb2209c97c9": { + "c55fd55c-258e-4a93-a63a-ea243038c9b9": { "Name": "foo", "ClassName": "StringValue", "Properties": { @@ -80,25 +43,153 @@ "Value": "Hello world, from a/foo.txt" } }, - "Id": "54f2f276-964f-4c60-87d8-5fb2209c97c9", + "Id": "c55fd55c-258e-4a93-a63a-ea243038c9b9", "Children": [], - "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" + "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" }, - "1aafa29b-bdca-40a0-a677-7ead327b84ce": { - "Name": "Ack", - "ClassName": "Folder", + "71a95983-c856-4cf2-aee6-bd8a523e80e4": { + "Name": "something", + "ClassName": "ModuleScript", + "Properties": { + "Source": { + "Type": "String", + "Value": "-- b/something.lua" + } + }, + "Id": "71a95983-c856-4cf2-aee6-bd8a523e80e4", + "Children": [], + "Parent": "c910510c-37a8-4fd8-ae41-01169ccb739c" + }, + "3b5af13f-c997-4009-915c-0810b0e83032": { + "Name": "multi_partition_game", + "ClassName": "DataModel", "Properties": {}, - "Id": "1aafa29b-bdca-40a0-a677-7ead327b84ce", + "Id": "3b5af13f-c997-4009-915c-0810b0e83032", "Children": [ - "54f2f276-964f-4c60-87d8-5fb2209c97c9", - "8d44bb30-db3c-4366-a6c5-633bd1441885" + "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c", + "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" ], - "Parent": "9f141826-14c2-492b-b360-2558712f0c08" + "Parent": null + }, + "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c": { + "Name": "HttpService", + "ClassName": "HttpService", + "Properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "Id": "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c", + "Children": [], + "Parent": "3b5af13f-c997-4009-915c-0810b0e83032" + }, + "99eefe5f-ef74-49e6-8a8b-c833e00ca56b": { + "Name": "ReplicatedStorage", + "ClassName": "ReplicatedStorage", + "Properties": {}, + "Id": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b", + "Children": [ + "14fed1a3-ba97-46a6-ae93-ac26bd9471df", + "c910510c-37a8-4fd8-ae41-01169ccb739c" + ], + "Parent": "3b5af13f-c997-4009-915c-0810b0e83032" } }, - "root_id": "645ba594-4482-441f-9f41-5bb9c444405b", + "root_id": "3b5af13f-c997-4009-915c-0810b0e83032", "metadata": { - "645ba594-4482-441f-9f41-5bb9c444405b": { + "00f207b1-fc18-4088-a45e-caf8cd98f5dd": { + "ignore_unknown_instances": false, + "source_path": "a/main.lua", + "project_definition": null + }, + "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "HttpService", + { + "class_name": "HttpService", + "children": {}, + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "ignore_unknown_instances": null, + "path": null + } + ] + }, + "14fed1a3-ba97-46a6-ae93-ac26bd9471df": { + "ignore_unknown_instances": false, + "source_path": "a", + "project_definition": [ + "Ack", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + } + ] + }, + "c55fd55c-258e-4a93-a63a-ea243038c9b9": { + "ignore_unknown_instances": false, + "source_path": "a/foo.txt", + "project_definition": null + }, + "71a95983-c856-4cf2-aee6-bd8a523e80e4": { + "ignore_unknown_instances": false, + "source_path": "b/something.lua", + "project_definition": null + }, + "c910510c-37a8-4fd8-ae41-01169ccb739c": { + "ignore_unknown_instances": false, + "source_path": "b", + "project_definition": [ + "Bar", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + ] + }, + "99eefe5f-ef74-49e6-8a8b-c833e00ca56b": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "ReplicatedStorage", + { + "class_name": "ReplicatedStorage", + "children": { + "Ack": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + }, + "Bar": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + }, + "3b5af13f-c997-4009-915c-0810b0e83032": { "ignore_unknown_instances": true, "source_path": null, "project_definition": [ @@ -146,97 +237,6 @@ "path": null } ] - }, - "1aafa29b-bdca-40a0-a677-7ead327b84ce": { - "ignore_unknown_instances": false, - "source_path": "a", - "project_definition": [ - "Ack", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - } - ] - }, - "b1c9928c-bf11-427f-90eb-b672c811d859": { - "ignore_unknown_instances": false, - "source_path": "b", - "project_definition": [ - "Bar", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - ] - }, - "54f2f276-964f-4c60-87d8-5fb2209c97c9": { - "ignore_unknown_instances": false, - "source_path": "a/foo.txt", - "project_definition": null - }, - "9f141826-14c2-492b-b360-2558712f0c08": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "ReplicatedStorage", - { - "class_name": "ReplicatedStorage", - "children": { - "Ack": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - }, - "Bar": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - }, - "8d44bb30-db3c-4366-a6c5-633bd1441885": { - "ignore_unknown_instances": false, - "source_path": "a/main.lua", - "project_definition": null - }, - "b1298bcc-e370-44a6-9ef4-fbefa290124c": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "HttpService", - { - "class_name": "HttpService", - "children": {}, - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "ignore_unknown_instances": null, - "path": null - } - ] - }, - "8d690a2a-e987-4c86-b9ac-18e6d3a98503": { - "ignore_unknown_instances": false, - "source_path": "b/something.lua", - "project_definition": null } } } \ No newline at end of file diff --git a/test-projects/multi_partition_game/with_dir.tree.json b/test-projects/multi_partition_game/with_dir.tree.json index 5237c507..c8875416 100644 --- a/test-projects/multi_partition_game/with_dir.tree.json +++ b/test-projects/multi_partition_game/with_dir.tree.json @@ -1,6 +1,14 @@ { "instances": { - "8d44bb30-db3c-4366-a6c5-633bd1441885": { + "b48b369f-5706-4029-9fa6-90651a4910ea": { + "Name": "added", + "ClassName": "Folder", + "Properties": {}, + "Id": "b48b369f-5706-4029-9fa6-90651a4910ea", + "Children": [], + "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" + }, + "00f207b1-fc18-4088-a45e-caf8cd98f5dd": { "Name": "main", "ClassName": "ModuleScript", "Properties": { @@ -9,77 +17,33 @@ "Value": "-- hello, from a/main.lua" } }, - "Id": "8d44bb30-db3c-4366-a6c5-633bd1441885", + "Id": "00f207b1-fc18-4088-a45e-caf8cd98f5dd", "Children": [], - "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" + "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" }, - "b1c9928c-bf11-427f-90eb-b672c811d859": { + "14fed1a3-ba97-46a6-ae93-ac26bd9471df": { + "Name": "Ack", + "ClassName": "Folder", + "Properties": {}, + "Id": "14fed1a3-ba97-46a6-ae93-ac26bd9471df", + "Children": [ + "b48b369f-5706-4029-9fa6-90651a4910ea", + "c55fd55c-258e-4a93-a63a-ea243038c9b9", + "00f207b1-fc18-4088-a45e-caf8cd98f5dd" + ], + "Parent": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" + }, + "c910510c-37a8-4fd8-ae41-01169ccb739c": { "Name": "Bar", "ClassName": "Folder", "Properties": {}, - "Id": "b1c9928c-bf11-427f-90eb-b672c811d859", + "Id": "c910510c-37a8-4fd8-ae41-01169ccb739c", "Children": [ - "8d690a2a-e987-4c86-b9ac-18e6d3a98503" + "71a95983-c856-4cf2-aee6-bd8a523e80e4" ], - "Parent": "9f141826-14c2-492b-b360-2558712f0c08" + "Parent": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" }, - "645ba594-4482-441f-9f41-5bb9c444405b": { - "Name": "multi_partition_game", - "ClassName": "DataModel", - "Properties": {}, - "Id": "645ba594-4482-441f-9f41-5bb9c444405b", - "Children": [ - "b1298bcc-e370-44a6-9ef4-fbefa290124c", - "9f141826-14c2-492b-b360-2558712f0c08" - ], - "Parent": null - }, - "9f141826-14c2-492b-b360-2558712f0c08": { - "Name": "ReplicatedStorage", - "ClassName": "ReplicatedStorage", - "Properties": {}, - "Id": "9f141826-14c2-492b-b360-2558712f0c08", - "Children": [ - "1aafa29b-bdca-40a0-a677-7ead327b84ce", - "b1c9928c-bf11-427f-90eb-b672c811d859" - ], - "Parent": "645ba594-4482-441f-9f41-5bb9c444405b" - }, - "8d690a2a-e987-4c86-b9ac-18e6d3a98503": { - "Name": "something", - "ClassName": "ModuleScript", - "Properties": { - "Source": { - "Type": "String", - "Value": "-- b/something.lua" - } - }, - "Id": "8d690a2a-e987-4c86-b9ac-18e6d3a98503", - "Children": [], - "Parent": "b1c9928c-bf11-427f-90eb-b672c811d859" - }, - "b1298bcc-e370-44a6-9ef4-fbefa290124c": { - "Name": "HttpService", - "ClassName": "HttpService", - "Properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "Id": "b1298bcc-e370-44a6-9ef4-fbefa290124c", - "Children": [], - "Parent": "645ba594-4482-441f-9f41-5bb9c444405b" - }, - "46353305-8818-48fe-94fd-80cf0c5d974c": { - "Name": "added", - "ClassName": "Folder", - "Properties": {}, - "Id": "46353305-8818-48fe-94fd-80cf0c5d974c", - "Children": [], - "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" - }, - "54f2f276-964f-4c60-87d8-5fb2209c97c9": { + "c55fd55c-258e-4a93-a63a-ea243038c9b9": { "Name": "foo", "ClassName": "StringValue", "Properties": { @@ -88,50 +52,67 @@ "Value": "Hello world, from a/foo.txt" } }, - "Id": "54f2f276-964f-4c60-87d8-5fb2209c97c9", + "Id": "c55fd55c-258e-4a93-a63a-ea243038c9b9", "Children": [], - "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" + "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" }, - "1aafa29b-bdca-40a0-a677-7ead327b84ce": { - "Name": "Ack", - "ClassName": "Folder", + "71a95983-c856-4cf2-aee6-bd8a523e80e4": { + "Name": "something", + "ClassName": "ModuleScript", + "Properties": { + "Source": { + "Type": "String", + "Value": "-- b/something.lua" + } + }, + "Id": "71a95983-c856-4cf2-aee6-bd8a523e80e4", + "Children": [], + "Parent": "c910510c-37a8-4fd8-ae41-01169ccb739c" + }, + "3b5af13f-c997-4009-915c-0810b0e83032": { + "Name": "multi_partition_game", + "ClassName": "DataModel", "Properties": {}, - "Id": "1aafa29b-bdca-40a0-a677-7ead327b84ce", + "Id": "3b5af13f-c997-4009-915c-0810b0e83032", "Children": [ - "54f2f276-964f-4c60-87d8-5fb2209c97c9", - "8d44bb30-db3c-4366-a6c5-633bd1441885", - "46353305-8818-48fe-94fd-80cf0c5d974c" + "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c", + "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" ], - "Parent": "9f141826-14c2-492b-b360-2558712f0c08" + "Parent": null + }, + "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c": { + "Name": "HttpService", + "ClassName": "HttpService", + "Properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "Id": "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c", + "Children": [], + "Parent": "3b5af13f-c997-4009-915c-0810b0e83032" + }, + "99eefe5f-ef74-49e6-8a8b-c833e00ca56b": { + "Name": "ReplicatedStorage", + "ClassName": "ReplicatedStorage", + "Properties": {}, + "Id": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b", + "Children": [ + "14fed1a3-ba97-46a6-ae93-ac26bd9471df", + "c910510c-37a8-4fd8-ae41-01169ccb739c" + ], + "Parent": "3b5af13f-c997-4009-915c-0810b0e83032" } }, - "root_id": "645ba594-4482-441f-9f41-5bb9c444405b", + "root_id": "3b5af13f-c997-4009-915c-0810b0e83032", "metadata": { - "b1c9928c-bf11-427f-90eb-b672c811d859": { - "ignore_unknown_instances": false, - "source_path": "b", - "project_definition": [ - "Bar", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - ] - }, - "54f2f276-964f-4c60-87d8-5fb2209c97c9": { + "c55fd55c-258e-4a93-a63a-ea243038c9b9": { "ignore_unknown_instances": false, "source_path": "a/foo.txt", "project_definition": null }, - "8d44bb30-db3c-4366-a6c5-633bd1441885": { - "ignore_unknown_instances": false, - "source_path": "a/main.lua", - "project_definition": null - }, - "9f141826-14c2-492b-b360-2558712f0c08": { + "99eefe5f-ef74-49e6-8a8b-c833e00ca56b": { "ignore_unknown_instances": true, "source_path": null, "project_definition": [ @@ -160,7 +141,17 @@ } ] }, - "b1298bcc-e370-44a6-9ef4-fbefa290124c": { + "71a95983-c856-4cf2-aee6-bd8a523e80e4": { + "ignore_unknown_instances": false, + "source_path": "b/something.lua", + "project_definition": null + }, + "00f207b1-fc18-4088-a45e-caf8cd98f5dd": { + "ignore_unknown_instances": false, + "source_path": "a/main.lua", + "project_definition": null + }, + "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c": { "ignore_unknown_instances": true, "source_path": null, "project_definition": [ @@ -179,31 +170,12 @@ } ] }, - "46353305-8818-48fe-94fd-80cf0c5d974c": { + "b48b369f-5706-4029-9fa6-90651a4910ea": { "ignore_unknown_instances": false, "source_path": "a/added", "project_definition": null }, - "1aafa29b-bdca-40a0-a677-7ead327b84ce": { - "ignore_unknown_instances": false, - "source_path": "a", - "project_definition": [ - "Ack", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - } - ] - }, - "8d690a2a-e987-4c86-b9ac-18e6d3a98503": { - "ignore_unknown_instances": false, - "source_path": "b/something.lua", - "project_definition": null - }, - "645ba594-4482-441f-9f41-5bb9c444405b": { + "3b5af13f-c997-4009-915c-0810b0e83032": { "ignore_unknown_instances": true, "source_path": null, "project_definition": [ @@ -251,6 +223,34 @@ "path": null } ] + }, + "c910510c-37a8-4fd8-ae41-01169ccb739c": { + "ignore_unknown_instances": false, + "source_path": "b", + "project_definition": [ + "Bar", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + ] + }, + "14fed1a3-ba97-46a6-ae93-ac26bd9471df": { + "ignore_unknown_instances": false, + "source_path": "a", + "project_definition": [ + "Ack", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + } + ] } } } \ No newline at end of file diff --git a/test-projects/multi_partition_game/with_moved_dir.tree.json b/test-projects/multi_partition_game/with_moved_dir.tree.json index 4da8884a..4e996829 100644 --- a/test-projects/multi_partition_game/with_moved_dir.tree.json +++ b/test-projects/multi_partition_game/with_moved_dir.tree.json @@ -1,6 +1,14 @@ { "instances": { - "8d44bb30-db3c-4366-a6c5-633bd1441885": { + "866071d6-465a-4b88-8c63-07489d950916": { + "Name": "added", + "ClassName": "Folder", + "Properties": {}, + "Id": "866071d6-465a-4b88-8c63-07489d950916", + "Children": [], + "Parent": "c910510c-37a8-4fd8-ae41-01169ccb739c" + }, + "00f207b1-fc18-4088-a45e-caf8cd98f5dd": { "Name": "main", "ClassName": "ModuleScript", "Properties": { @@ -9,70 +17,33 @@ "Value": "-- hello, from a/main.lua" } }, - "Id": "8d44bb30-db3c-4366-a6c5-633bd1441885", + "Id": "00f207b1-fc18-4088-a45e-caf8cd98f5dd", "Children": [], - "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" + "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" }, - "b1c9928c-bf11-427f-90eb-b672c811d859": { + "14fed1a3-ba97-46a6-ae93-ac26bd9471df": { + "Name": "Ack", + "ClassName": "Folder", + "Properties": {}, + "Id": "14fed1a3-ba97-46a6-ae93-ac26bd9471df", + "Children": [ + "c55fd55c-258e-4a93-a63a-ea243038c9b9", + "00f207b1-fc18-4088-a45e-caf8cd98f5dd" + ], + "Parent": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" + }, + "c910510c-37a8-4fd8-ae41-01169ccb739c": { "Name": "Bar", "ClassName": "Folder", "Properties": {}, - "Id": "b1c9928c-bf11-427f-90eb-b672c811d859", + "Id": "c910510c-37a8-4fd8-ae41-01169ccb739c", "Children": [ - "8d690a2a-e987-4c86-b9ac-18e6d3a98503", - "a8566e76-0495-45a3-a713-1c59ab39453b" + "866071d6-465a-4b88-8c63-07489d950916", + "71a95983-c856-4cf2-aee6-bd8a523e80e4" ], - "Parent": "9f141826-14c2-492b-b360-2558712f0c08" + "Parent": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" }, - "645ba594-4482-441f-9f41-5bb9c444405b": { - "Name": "multi_partition_game", - "ClassName": "DataModel", - "Properties": {}, - "Id": "645ba594-4482-441f-9f41-5bb9c444405b", - "Children": [ - "b1298bcc-e370-44a6-9ef4-fbefa290124c", - "9f141826-14c2-492b-b360-2558712f0c08" - ], - "Parent": null - }, - "9f141826-14c2-492b-b360-2558712f0c08": { - "Name": "ReplicatedStorage", - "ClassName": "ReplicatedStorage", - "Properties": {}, - "Id": "9f141826-14c2-492b-b360-2558712f0c08", - "Children": [ - "1aafa29b-bdca-40a0-a677-7ead327b84ce", - "b1c9928c-bf11-427f-90eb-b672c811d859" - ], - "Parent": "645ba594-4482-441f-9f41-5bb9c444405b" - }, - "8d690a2a-e987-4c86-b9ac-18e6d3a98503": { - "Name": "something", - "ClassName": "ModuleScript", - "Properties": { - "Source": { - "Type": "String", - "Value": "-- b/something.lua" - } - }, - "Id": "8d690a2a-e987-4c86-b9ac-18e6d3a98503", - "Children": [], - "Parent": "b1c9928c-bf11-427f-90eb-b672c811d859" - }, - "b1298bcc-e370-44a6-9ef4-fbefa290124c": { - "Name": "HttpService", - "ClassName": "HttpService", - "Properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "Id": "b1298bcc-e370-44a6-9ef4-fbefa290124c", - "Children": [], - "Parent": "645ba594-4482-441f-9f41-5bb9c444405b" - }, - "54f2f276-964f-4c60-87d8-5fb2209c97c9": { + "c55fd55c-258e-4a93-a63a-ea243038c9b9": { "Name": "foo", "ClassName": "StringValue", "Properties": { @@ -81,33 +52,158 @@ "Value": "Hello world, from a/foo.txt" } }, - "Id": "54f2f276-964f-4c60-87d8-5fb2209c97c9", + "Id": "c55fd55c-258e-4a93-a63a-ea243038c9b9", "Children": [], - "Parent": "1aafa29b-bdca-40a0-a677-7ead327b84ce" + "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" }, - "a8566e76-0495-45a3-a713-1c59ab39453b": { - "Name": "added", - "ClassName": "Folder", - "Properties": {}, - "Id": "a8566e76-0495-45a3-a713-1c59ab39453b", + "71a95983-c856-4cf2-aee6-bd8a523e80e4": { + "Name": "something", + "ClassName": "ModuleScript", + "Properties": { + "Source": { + "Type": "String", + "Value": "-- b/something.lua" + } + }, + "Id": "71a95983-c856-4cf2-aee6-bd8a523e80e4", "Children": [], - "Parent": "b1c9928c-bf11-427f-90eb-b672c811d859" + "Parent": "c910510c-37a8-4fd8-ae41-01169ccb739c" }, - "1aafa29b-bdca-40a0-a677-7ead327b84ce": { - "Name": "Ack", - "ClassName": "Folder", + "3b5af13f-c997-4009-915c-0810b0e83032": { + "Name": "multi_partition_game", + "ClassName": "DataModel", "Properties": {}, - "Id": "1aafa29b-bdca-40a0-a677-7ead327b84ce", + "Id": "3b5af13f-c997-4009-915c-0810b0e83032", "Children": [ - "54f2f276-964f-4c60-87d8-5fb2209c97c9", - "8d44bb30-db3c-4366-a6c5-633bd1441885" + "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c", + "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" ], - "Parent": "9f141826-14c2-492b-b360-2558712f0c08" + "Parent": null + }, + "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c": { + "Name": "HttpService", + "ClassName": "HttpService", + "Properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "Id": "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c", + "Children": [], + "Parent": "3b5af13f-c997-4009-915c-0810b0e83032" + }, + "99eefe5f-ef74-49e6-8a8b-c833e00ca56b": { + "Name": "ReplicatedStorage", + "ClassName": "ReplicatedStorage", + "Properties": {}, + "Id": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b", + "Children": [ + "14fed1a3-ba97-46a6-ae93-ac26bd9471df", + "c910510c-37a8-4fd8-ae41-01169ccb739c" + ], + "Parent": "3b5af13f-c997-4009-915c-0810b0e83032" } }, - "root_id": "645ba594-4482-441f-9f41-5bb9c444405b", + "root_id": "3b5af13f-c997-4009-915c-0810b0e83032", "metadata": { - "645ba594-4482-441f-9f41-5bb9c444405b": { + "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "HttpService", + { + "class_name": "HttpService", + "children": {}, + "properties": { + "HttpEnabled": { + "Type": "Bool", + "Value": true + } + }, + "ignore_unknown_instances": null, + "path": null + } + ] + }, + "c910510c-37a8-4fd8-ae41-01169ccb739c": { + "ignore_unknown_instances": false, + "source_path": "b", + "project_definition": [ + "Bar", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + ] + }, + "866071d6-465a-4b88-8c63-07489d950916": { + "ignore_unknown_instances": false, + "source_path": "b/added", + "project_definition": null + }, + "14fed1a3-ba97-46a6-ae93-ac26bd9471df": { + "ignore_unknown_instances": false, + "source_path": "a", + "project_definition": [ + "Ack", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + } + ] + }, + "00f207b1-fc18-4088-a45e-caf8cd98f5dd": { + "ignore_unknown_instances": false, + "source_path": "a/main.lua", + "project_definition": null + }, + "99eefe5f-ef74-49e6-8a8b-c833e00ca56b": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": [ + "ReplicatedStorage", + { + "class_name": "ReplicatedStorage", + "children": { + "Ack": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "a" + }, + "Bar": { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "b" + } + }, + "properties": {}, + "ignore_unknown_instances": null, + "path": null + } + ] + }, + "71a95983-c856-4cf2-aee6-bd8a523e80e4": { + "ignore_unknown_instances": false, + "source_path": "b/something.lua", + "project_definition": null + }, + "c55fd55c-258e-4a93-a63a-ea243038c9b9": { + "ignore_unknown_instances": false, + "source_path": "a/foo.txt", + "project_definition": null + }, + "3b5af13f-c997-4009-915c-0810b0e83032": { "ignore_unknown_instances": true, "source_path": null, "project_definition": [ @@ -155,102 +251,6 @@ "path": null } ] - }, - "1aafa29b-bdca-40a0-a677-7ead327b84ce": { - "ignore_unknown_instances": false, - "source_path": "a", - "project_definition": [ - "Ack", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - } - ] - }, - "a8566e76-0495-45a3-a713-1c59ab39453b": { - "ignore_unknown_instances": false, - "source_path": "b/added", - "project_definition": null - }, - "8d690a2a-e987-4c86-b9ac-18e6d3a98503": { - "ignore_unknown_instances": false, - "source_path": "b/something.lua", - "project_definition": null - }, - "8d44bb30-db3c-4366-a6c5-633bd1441885": { - "ignore_unknown_instances": false, - "source_path": "a/main.lua", - "project_definition": null - }, - "9f141826-14c2-492b-b360-2558712f0c08": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "ReplicatedStorage", - { - "class_name": "ReplicatedStorage", - "children": { - "Ack": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - }, - "Bar": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - }, - "b1c9928c-bf11-427f-90eb-b672c811d859": { - "ignore_unknown_instances": false, - "source_path": "b", - "project_definition": [ - "Bar", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - ] - }, - "54f2f276-964f-4c60-87d8-5fb2209c97c9": { - "ignore_unknown_instances": false, - "source_path": "a/foo.txt", - "project_definition": null - }, - "b1298bcc-e370-44a6-9ef4-fbefa290124c": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "HttpService", - { - "class_name": "HttpService", - "children": {}, - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "ignore_unknown_instances": null, - "path": null - } - ] } } } \ No newline at end of file From 3faf3d2a5685ceb15be80e7ee3ed59e017fac2fa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 20 Mar 2019 10:42:18 -0700 Subject: [PATCH 0481/1504] Update Changelog for #135 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45fd9b5c..1d56d892 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## [Unreleased] +* Improved server instance ordering behavior when files are added during a live session ([#135](https://github.com/LPGhatguy/rojo/pull/135)) ## [0.5.0 Alpha 6](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.6) (March 19, 2019) * Fixed `rojo init` giving unexpected results by upgrading to `rbx_dom_weak` 1.1.0 From 07c7b28c03120f49a4991b300687b13084b7635c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 21 Mar 2019 22:35:30 -0700 Subject: [PATCH 0482/1504] Fix plugin unloading --- CHANGELOG.md | 1 + plugin/src/init.server.lua | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d56d892..dd59e202 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## [Unreleased] * Improved server instance ordering behavior when files are added during a live session ([#135](https://github.com/LPGhatguy/rojo/pull/135)) +* Fixed error being thrown when trying to unload the Rojo plugin. ## [0.5.0 Alpha 6](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.6) (March 19, 2019) * Fixed `rojo init` giving unexpected results by upgrading to `rbx_dom_weak` 1.1.0 diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index b3b52bd0..08de686e 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -10,8 +10,8 @@ local app = Roact.createElement(App, { plugin = plugin, }) -Roact.mount(app, game:GetService("CoreGui"), "Rojo UI") +local tree = Roact.mount(app, game:GetService("CoreGui"), "Rojo UI") plugin.Unloading:Connect(function() - Roact.unmount(app) + Roact.unmount(tree) end) \ No newline at end of file From 41025225b224b768cea788b10cf60cc374b4514a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 27 Mar 2019 13:27:50 -0700 Subject: [PATCH 0483/1504] Rewrite message queue with oneshot futures (#139) --- server/src/message_queue.rs | 72 ++++++++++++++++++++++--------------- server/src/web/api.rs | 31 +++++----------- 2 files changed, 53 insertions(+), 50 deletions(-) diff --git a/server/src/message_queue.rs b/server/src/message_queue.rs index e8d0e5c7..08d93e8e 100644 --- a/server/src/message_queue.rs +++ b/server/src/message_queue.rs @@ -1,23 +1,28 @@ use std::{ - collections::HashMap, + mem, sync::{ - atomic::{AtomicUsize, Ordering}, RwLock, Mutex, }, }; -use futures::sync::mpsc; +use futures::sync::oneshot; -/// A unique identifier, not guaranteed to be generated in any order. -#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] -pub struct ListenerId(usize); +struct Listener { + sender: oneshot::Sender<(u32, Vec)>, + cursor: u32, +} -/// Generate a new ID, which has no defined ordering. -pub fn get_listener_id() -> ListenerId { - static LAST_ID: AtomicUsize = AtomicUsize::new(0); +fn fire_listener_if_ready(messages: &[T], listener: Listener) -> Result<(), Listener> { + let current_cursor = messages.len() as u32; - ListenerId(LAST_ID.fetch_add(1, Ordering::SeqCst)) + if listener.cursor < current_cursor { + let new_messages = messages[(listener.cursor as usize)..].to_vec(); + let _ = listener.sender.send((current_cursor, new_messages)); + Ok(()) + } else { + Err(listener) + } } /// A message queue with persistent history that can be subscribed to. @@ -26,42 +31,53 @@ pub fn get_listener_id() -> ListenerId { #[derive(Default)] pub struct MessageQueue { messages: RwLock>, - message_listeners: Mutex>>, + message_listeners: Mutex>>, } impl MessageQueue { pub fn new() -> MessageQueue { MessageQueue { messages: RwLock::new(Vec::new()), - message_listeners: Mutex::new(HashMap::new()), + message_listeners: Mutex::new(Vec::new()), } } pub fn push_messages(&self, new_messages: &[T]) { let mut message_listeners = self.message_listeners.lock().unwrap(); + let mut messages = self.messages.write().unwrap(); + messages.extend_from_slice(new_messages); - { - let mut messages = self.messages.write().unwrap(); - messages.extend_from_slice(new_messages); + let mut remaining_listeners = Vec::new(); + + for listener in message_listeners.drain(..) { + match fire_listener_if_ready(&messages, listener) { + Ok(_) => {} + Err(listener) => remaining_listeners.push(listener) + } } - for listener in message_listeners.values_mut() { - listener.try_send(()).unwrap(); - } + // Without this annotation, Rust gets confused since the first argument + // is a MutexGuard, but the second is a Vec. + mem::replace::>(&mut message_listeners, remaining_listeners); } - pub fn subscribe(&self, sender: mpsc::Sender<()>) -> ListenerId { - let id = get_listener_id(); + pub fn subscribe(&self, cursor: u32, sender: oneshot::Sender<(u32, Vec)>) { + let listener = { + let listener = Listener { + sender, + cursor, + }; + + let messages = self.messages.read().unwrap(); + + match fire_listener_if_ready(&messages, listener) { + Ok(_) => return, + Err(listener) => listener + } + }; let mut message_listeners = self.message_listeners.lock().unwrap(); - message_listeners.insert(id, sender); - - id - } - - pub fn unsubscribe(&self, id: ListenerId) { - let mut message_listeners = self.message_listeners.lock().unwrap(); - message_listeners.remove(&id); + message_listeners.push(listener); } pub fn get_message_cursor(&self) -> u32 { diff --git a/server/src/web/api.rs b/server/src/web/api.rs index a36d02c8..0b6cbe03 100644 --- a/server/src/web/api.rs +++ b/server/src/web/api.rs @@ -7,7 +7,11 @@ use std::{ sync::Arc, }; -use futures::{future, Future, stream::Stream, sync::mpsc}; +use futures::{ + future::{self, IntoFuture}, + Future, + sync::oneshot, +}; use hyper::{ service::Service, header, @@ -168,30 +172,13 @@ impl ApiService { }; let message_queue = Arc::clone(&self.live_session.message_queue); - - // Did the client miss any messages since the last subscribe? - { - let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); - - if !new_messages.is_empty() { - return Box::new(future::ok(response_json(&SubscribeResponse { - session_id: self.live_session.session_id(), - messages: Cow::Borrowed(&new_messages), - message_cursor: new_cursor, - }))); - } - } - - let (tx, rx) = mpsc::channel(1024); - let sender_id = message_queue.subscribe(tx); let session_id = self.live_session.session_id(); + let (tx, rx) = oneshot::channel(); + message_queue.subscribe(cursor, tx); + let result = rx.into_future() - .and_then(move |_| { - message_queue.unsubscribe(sender_id); - - let (new_cursor, new_messages) = message_queue.get_messages_since(cursor); - + .and_then(move |(new_cursor, new_messages)| { Box::new(future::ok(response_json(SubscribeResponse { session_id: session_id, messages: Cow::Owned(new_messages), From eecbfd29e7358c4ce1f8599a3878808ce2a1c9e2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 27 Mar 2019 13:31:12 -0700 Subject: [PATCH 0484/1504] Update dependencies, adding a bunch of new features --- CHANGELOG.md | 10 +++ Cargo.lock | 202 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 134 insertions(+), 78 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd59e202..a33ea483 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ # Rojo Changelog ## [Unreleased] +* Added support for a bunch of new types when dealing with XML model/place files: + * `ColorSequence` + * `Float64` + * `Int64` + * `NumberRange` + * `NumberSequence` + * `PhysicalProperties` + * `Ray` + * `Rect` + * `Ref` * Improved server instance ordering behavior when files are added during a live session ([#135](https://github.com/LPGhatguy/rojo/pull/135)) * Fixed error being thrown when trying to unload the Rojo plugin. diff --git a/Cargo.lock b/Cargo.lock index 9b25678f..a454758c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,7 +68,7 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -90,6 +90,11 @@ name = "bitflags" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "build_const" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bytecount" version = "0.4.0" @@ -123,7 +128,7 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.30" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -170,6 +175,14 @@ dependencies = [ "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crc" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crc32fast" version = "1.2.0" @@ -311,6 +324,16 @@ dependencies = [ "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "flate2" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fnv" version = "1.0.6" @@ -387,7 +410,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "h2" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -438,7 +461,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -447,19 +470,19 @@ dependencies = [ "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "hyper-tls" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -540,16 +563,6 @@ name = "libc" version = "0.2.50" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "libflate" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "lock_api" version = "0.1.5" @@ -582,7 +595,7 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -628,6 +641,25 @@ dependencies = [ "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "miniz_oxide" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miniz_oxide_c_api" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mio" version = "0.6.16" @@ -676,9 +708,9 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.20 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -733,7 +765,7 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.19" +version = "0.10.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -741,7 +773,7 @@ dependencies = [ "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -751,10 +783,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.42" +version = "0.9.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -800,16 +832,16 @@ dependencies = [ [[package]] name = "paste" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "paste-impl" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1034,28 +1066,28 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_dom_weak" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_reflection" -version = "2.0.374" +version = "2.0.377" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1068,7 +1100,7 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1123,17 +1155,17 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.11" +version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libflate 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1141,13 +1173,13 @@ dependencies = [ "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1178,7 +1210,7 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1197,21 +1229,21 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 2.0.374 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 2.0.377 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1472,33 +1504,34 @@ dependencies = [ [[package]] name = "tokio" -version = "0.1.16" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-current-thread" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1528,14 +1561,14 @@ dependencies = [ "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-sync" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1557,7 +1590,7 @@ dependencies = [ [[package]] name = "tokio-threadpool" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1568,7 +1601,7 @@ dependencies = [ "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1579,7 +1612,15 @@ dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-trace-core" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1651,7 +1692,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uuid" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1766,16 +1807,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92" +"checksum cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ad0daef304fa0b4238f5f7ed7178774b43b06f6a9b6509f6642bef4ff1f7b9b2" "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" +"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" @@ -1792,6 +1835,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" +"checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" @@ -1803,13 +1847,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e" +"checksum h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "910a5e7be6283a9c91b3982fa5188368c8719cce2a3cf3b86048673bf9d9c36b" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" "checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)" = "7d5b6658b016965ae301fa995306db965c93677880ea70765a84235a96eae896" -"checksum hyper-tls 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "32cd73f14ad370d3b4d4b7dce08f69b81536c82e39fcc89731930fe5788cd661" +"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" @@ -1820,7 +1864,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" -"checksum libflate 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "7346a83e8a2c3958d44d24225d905385dc31fc16e89dffb356c457b278914d20" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" @@ -1831,6 +1874,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" +"checksum miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c468f2369f07d651a5d0bb2c9079f8488a66d5466efe42d0c5c6466edcb7f71e" +"checksum miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fe927a42e3807ef71defb191dc87d4e24479b221e67015fe38ae2b7b447bab" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" @@ -1840,15 +1885,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum notify 4.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "abb1581693e44d8a0ec347ef12289625063f52a1dddc3f3c9befd5fc59e88943" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" -"checksum openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)" = "84321fb9004c3bce5611188a644d6171f895fa2889d155927d528782edb21c5d" +"checksum openssl 0.10.20 (registry+https://github.com/rust-lang/crates.io-index)" = "5a0d6b781aac4ac1bd6cafe2a2f0ad8c16ae8e1dd5184822a16c50139f8838d9" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cb534d752bf98cf363b473950659ac2546517f9c6be9723771614ab3f03bbc9e" +"checksum openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)" = "33c86834957dd5b915623e94f2f4ab2c70dd8f6b70679824155d5ae21dbd495d" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum paste 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "f50392d1265092fbee9273414cc40eb6d47d307bd66222c477bb8450c8504f9d" -"checksum paste-impl 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a3cd512fe3a55e8933b2dcad913e365639db86d512e4004c3084b86864d9467a" +"checksum paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4a4a1c555c6505821f9d58b8779d0f630a6b7e4e1be24ba718610acf01fa79" +"checksum paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26e796e623b8b257215f27e6c80a5478856cae305f5b59810ff9acdaa34570e6" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" @@ -1874,8 +1919,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147f236284747ac1b4643476265dd36b402877d97adb7cbd0fafc1d247de0a5" -"checksum rbx_dom_weak 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f2a2ba185abc08fa3fce3de6dc5446ccf82b759583aee20fc07fced859dcc31f" -"checksum rbx_reflection 2.0.374 (registry+https://github.com/rust-lang/crates.io-index)" = "8a826ff869b33b54db727f9776f1dc7a8a779791f5a46ddd4941b8334bf909fe" +"checksum rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d581dcb6e5eb395a5923e1efe39883124115d725dacae07cdf084204345611e7" +"checksum rbx_reflection 2.0.377 (registry+https://github.com/rust-lang/crates.io-index)" = "21ba49260081530590ee48dd1ce6014ac5abc79f581ccb4be0626d436af59e92" "checksum rbx_xml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a240c155684b744c4985f283702b61f6ab0a2d4479694051d875844632c9f454" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" @@ -1883,7 +1928,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" "checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e542d9f077c126af32536b6aacc75bb7325400eab8cd0743543be5d91660780d" +"checksum reqwest 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "962fa64e670e70b9d3a81c3688832eb59293ef490e0af5ad169763f62016ac5e" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "51acb42c134a6568911a2aef2cea5feb80503804cc8986b903983ebfb1342a2c" @@ -1918,15 +1963,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fcaabb3cec70485d0df6e9454fe514393ad1c4070dee8915f11041e95630b230" -"checksum tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c756b04680eea21902a46fca4e9f410a2332c04995af590e07ff262e2193a9a3" -"checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0" +"checksum tokio 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "65641e515a437b308ab131a82ce3042ff9795bef5d6c5a9be4eb24195c417fd9" +"checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" +"checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" "checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" -"checksum tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1bf2b9dac2a0509b5cfd1df5aa25eafacb616a42a491a13604d6bbeab4486363" +"checksum tokio-sync 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fda385df506bf7546e70872767f71e81640f1f251bdf2fd8eb81a0eaec5fe022" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "742e511f6ce2298aeb86fc9ea0d8df81c2388c6ebae3dc8a7316e8c9df0df801" +"checksum tokio-threadpool 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ec5759cf26cf9659555f36c431b515e3d05f66831741c85b4b5d5dfb9cf1323c" "checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" +"checksum tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "350c9edade9830dc185ae48ba45667a445ab59f6167ef6d0254ec9d2430d9dd3" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" @@ -1937,7 +1983,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" -"checksum uuid 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0238db0c5b605dd1cf51de0f21766f97fba2645897024461d6a00c036819a768" +"checksum uuid 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "600ef8213e9f8a0ac1f876e470e90780ae0478eabce7f76aff41b0f4ef0fd5c0" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" From 913ac7c9f5d014ea5850342bef46b88ada437691 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 28 Mar 2019 15:44:56 -0700 Subject: [PATCH 0485/1504] Update dependencies --- Cargo.lock | 7 ++++--- server/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a454758c..6c7440ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1092,7 +1092,7 @@ dependencies = [ [[package]] name = "rbx_xml" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1100,6 +1100,7 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1234,7 +1235,7 @@ dependencies = [ "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 2.0.377 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1921,7 +1922,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147f236284747ac1b4643476265dd36b402877d97adb7cbd0fafc1d247de0a5" "checksum rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d581dcb6e5eb395a5923e1efe39883124115d725dacae07cdf084204345611e7" "checksum rbx_reflection 2.0.377 (registry+https://github.com/rust-lang/crates.io-index)" = "21ba49260081530590ee48dd1ce6014ac5abc79f581ccb4be0626d436af59e92" -"checksum rbx_xml 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a240c155684b744c4985f283702b61f6ab0a2d4479694051d875844632c9f454" +"checksum rbx_xml 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891a97bd72d0c6847fe624e724ff3080e3369de74e4ef3b3dab07c6d8ce2bc23" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" diff --git a/server/Cargo.toml b/server/Cargo.toml index d7732f3d..90ff1dc3 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -31,7 +31,7 @@ maplit = "1.0.1" notify = "4.0" rbx_binary = "0.4.0" rbx_dom_weak = "1.3.0" -rbx_xml = "0.5.0" +rbx_xml = "0.6.0" rbx_reflection = "2.0.374" regex = "1.0" reqwest = "0.9.5" From 6db714a2b1bf8d78d799fb8e0aa16a36398f786c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 29 Mar 2019 17:25:57 -0700 Subject: [PATCH 0486/1504] Special-case Lighting.Technology in setCanonicalProperty, temporary fix --- CHANGELOG.md | 1 + plugin/src/setCanonicalProperty.lua | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a33ea483..82e7ea27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * `Ref` * Improved server instance ordering behavior when files are added during a live session ([#135](https://github.com/LPGhatguy/rojo/pull/135)) * Fixed error being thrown when trying to unload the Rojo plugin. +* Added partial fix for [issue #141](https://github.com/LPGhatguy/rojo/issues/141) for `Lighting.Technology`, which should restore live sync functionality for the default project file. ## [0.5.0 Alpha 6](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.6) (March 19, 2019) * Fixed `rojo init` giving unexpected results by upgrading to `rbx_dom_weak` 1.1.0 diff --git a/plugin/src/setCanonicalProperty.lua b/plugin/src/setCanonicalProperty.lua index d7e1e7d8..6e5eacd6 100644 --- a/plugin/src/setCanonicalProperty.lua +++ b/plugin/src/setCanonicalProperty.lua @@ -19,6 +19,11 @@ local function setCanonicalProperty(instance, key, value) return end + -- Temporary workaround for fixing issue #141 in this specific case. + if instance.ClassName == "Lighting" and key == "Technology" then + return + end + -- If we don't have permissions to access this value at all, we can skip it. local readSuccess, existingValue = pcall(function() return instance[key] From 77f79fa913d1df2e240359d9b188a297954851e1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 29 Mar 2019 17:32:52 -0700 Subject: [PATCH 0487/1504] 0.5.0-alpha.8 --- CHANGELOG.md | 2 ++ Cargo.lock | 2 +- docs/installation.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 5 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82e7ea27..2dc4fe4c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## [Unreleased] + +## [0.5.0 Alpha 8](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.8) (March 29, 2019) * Added support for a bunch of new types when dealing with XML model/place files: * `ColorSequence` * `Float64` diff --git a/Cargo.lock b/Cargo.lock index 6c7440ed..cb75d9cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1218,7 +1218,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0-alpha.6" +version = "0.5.0-alpha.8" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/docs/installation.md b/docs/installation.md index ea27f3d1..9166a581 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -25,7 +25,7 @@ If you have Rust installed, the easiest way to get Rojo is with Cargo! To install the latest 0.5.0 alpha, use: ```sh -cargo install rojo --version 0.5.0-alpha.6 +cargo install rojo --version 0.5.0-alpha.8 ``` ## Installing the Plugin diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 666418e9..78bdeabf 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0, "-alpha.6"}, + version = {0, 5, 0, "-alpha.8"}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/server/Cargo.toml b/server/Cargo.toml index 90ff1dc3..30be6d84 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0-alpha.6" +version = "0.5.0-alpha.8" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 54b82760cdd7e39608f2da69d350bb9e37e1b5d7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 1 Apr 2019 18:02:46 -0700 Subject: [PATCH 0488/1504] Switch 'rojo build' to use BufWriter, magic performance increase --- CHANGELOG.md | 2 ++ server/src/commands/build.rs | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2dc4fe4c..234a8cbd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## [Unreleased] +* Changed `rojo build` to use buffered I/O, which can make it up to 2x faster in some cases. + * Building [*Road Not Taken*](https://github.com/LPGhatguy/roads) to an `rbxlx` file dropped from 150ms to 70ms on my machine ## [0.5.0 Alpha 8](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.8) (March 29, 2019) * Added support for a bunch of new types when dealing with XML model/place files: diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index 16301ed3..8a65387f 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -1,7 +1,7 @@ use std::{ path::PathBuf, fs::File, - io, + io::{self, Write, BufWriter}, }; use log::info; @@ -92,7 +92,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let mut imfs = Imfs::new(); imfs.add_roots_from_project(&project)?; let tree = construct_oneoff_tree(&project, &imfs)?; - let mut file = File::create(&options.output_file)?; + let mut file = BufWriter::new(File::create(&options.output_file)?); match output_kind { OutputKind::Rbxmx => { @@ -121,5 +121,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { }, } + file.flush()?; + Ok(()) } \ No newline at end of file From d725970e6ecf6e3380a86fa19af88cd86da86fec Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 4 Apr 2019 13:16:10 -0700 Subject: [PATCH 0489/1504] Fix handling of CSV files with empty columns and rows (#149) * Fix #147 * Add localization test project, fix empty rows in general * Fill out 'normal' CSV in localization test project * Update Changelog --- CHANGELOG.md | 1 + server/src/rbx_snapshot.rs | 47 ++++++++++++---- server/tests/snapshot_snapshots.rs | 1 + .../localization/default.project.json | 6 +++ .../localization/expected-snapshot.json | 53 +++++++++++++++++++ .../localization/src/empty-column-bug-147.csv | 17 ++++++ test-projects/localization/src/normal.csv | 2 + 7 files changed, 118 insertions(+), 9 deletions(-) create mode 100644 test-projects/localization/default.project.json create mode 100644 test-projects/localization/expected-snapshot.json create mode 100644 test-projects/localization/src/empty-column-bug-147.csv create mode 100644 test-projects/localization/src/normal.csv diff --git a/CHANGELOG.md b/CHANGELOG.md index 234a8cbd..d9ee305e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] * Changed `rojo build` to use buffered I/O, which can make it up to 2x faster in some cases. * Building [*Road Not Taken*](https://github.com/LPGhatguy/roads) to an `rbxlx` file dropped from 150ms to 70ms on my machine +* Fixed `LocalizationTable` instances being made from `csv` files not supporting empty rows or columns. ([#149](https://github.com/LPGhatguy/rojo/pull/149)) ## [0.5.0 Alpha 8](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.8) (March 29, 2019) * Added support for a bunch of new types when dealing with XML model/place files: diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 9f9be279..902b5402 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -483,6 +483,7 @@ fn snapshot_csv_file<'source>( .deserialize() // TODO: Propagate error upward instead of panicking .map(|result| result.expect("Malformed localization table found!")) + .filter(|entry: &LocalizationEntryCsv| !(entry.key.is_empty() && entry.source.is_empty())) .map(LocalizationEntryCsv::to_json) .collect(); @@ -519,12 +520,32 @@ struct LocalizationEntryCsv { impl LocalizationEntryCsv { fn to_json(self) -> LocalizationEntryJson { + fn none_if_empty(value: String) -> Option { + if value.is_empty() { + None + } else { + Some(value) + } + } + + let key = none_if_empty(self.key); + let context = none_if_empty(self.context); + let example = none_if_empty(self.example); + let source = none_if_empty(self.source); + + let mut values = HashMap::with_capacity(self.values.len()); + for (key, value) in self.values.into_iter() { + if !key.is_empty() { + values.insert(key, value); + } + } + LocalizationEntryJson { - key: self.key, - context: self.context, - example: self.example, - source: self.source, - values: self.values, + key, + context, + example, + source, + values, } } } @@ -532,10 +553,18 @@ impl LocalizationEntryCsv { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] struct LocalizationEntryJson { - key: String, - context: String, - example: String, - source: String, + #[serde(skip_serializing_if = "Option::is_none")] + key: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + context: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + example: Option, + + #[serde(skip_serializing_if = "Option::is_none")] + source: Option, + values: HashMap, } diff --git a/server/tests/snapshot_snapshots.rs b/server/tests/snapshot_snapshots.rs index d697f50f..1efeffa6 100644 --- a/server/tests/snapshot_snapshots.rs +++ b/server/tests/snapshot_snapshots.rs @@ -33,6 +33,7 @@ macro_rules! generate_snapshot_tests { generate_snapshot_tests!( empty, + localization, multi_partition_game, nested_partitions, single_partition_game, diff --git a/test-projects/localization/default.project.json b/test-projects/localization/default.project.json new file mode 100644 index 00000000..64722c35 --- /dev/null +++ b/test-projects/localization/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "localization", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/test-projects/localization/expected-snapshot.json b/test-projects/localization/expected-snapshot.json new file mode 100644 index 00000000..1b706d65 --- /dev/null +++ b/test-projects/localization/expected-snapshot.json @@ -0,0 +1,53 @@ +{ + "name": "localization", + "class_name": "Folder", + "properties": {}, + "children": [ + { + "name": "empty-column-bug-147", + "class_name": "LocalizationTable", + "properties": { + "Contents": { + "Type": "String", + "Value": "[{\"key\":\"Language.Name\",\"source\":\"English\",\"values\":{}},{\"key\":\"Language.Region\",\"source\":\"United States\",\"values\":{}},{\"key\":\"Label.Thickness\",\"source\":\"Thickness\",\"values\":{}},{\"key\":\"Label.Opacity\",\"source\":\"Opacity\",\"values\":{}},{\"key\":\"Toolbar.Undo\",\"source\":\"Undo\",\"values\":{}},{\"key\":\"Toolbar.Redo\",\"source\":\"Redo\",\"values\":{}},{\"key\":\"Toolbar.Camera\",\"source\":\"Top-down camera\",\"values\":{}},{\"key\":\"Toolbar.Saves\",\"source\":\"Saved drawings\",\"values\":{}},{\"key\":\"Toolbar.Preferences\",\"source\":\"Settings\",\"values\":{}},{\"key\":\"Toolbar.Mode.Vector\",\"source\":\"Vector mode\",\"values\":{}},{\"key\":\"Toolbar.Mode.Pixel\",\"source\":\"Pixel mode\",\"values\":{}}]" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src/empty-column-bug-147.csv", + "project_definition": null + } + }, + { + "name": "normal", + "class_name": "LocalizationTable", + "properties": { + "Contents": { + "Type": "String", + "Value": "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src/normal.csv", + "project_definition": null + } + } + ], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src", + "project_definition": [ + "localization", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "src" + } + ] + } +} \ No newline at end of file diff --git a/test-projects/localization/src/empty-column-bug-147.csv b/test-projects/localization/src/empty-column-bug-147.csv new file mode 100644 index 00000000..c58bd359 --- /dev/null +++ b/test-projects/localization/src/empty-column-bug-147.csv @@ -0,0 +1,17 @@ +,Key,Source,Context,Example +,,,, +Metadata,Language.Name,English,, +,Language.Region,United States,, +,,,, +Options,Label.Thickness,Thickness,, +,Label.Opacity,Opacity,, +,,,, +Toolbar,Toolbar.Undo,Undo,, +,Toolbar.Redo,Redo,, +,,,, +,Toolbar.Camera,Top-down camera,, +,Toolbar.Saves,Saved drawings,, +,Toolbar.Preferences,Settings,, +,,,, +,Toolbar.Mode.Vector,Vector mode,, +,Toolbar.Mode.Pixel,Pixel mode,, \ No newline at end of file diff --git a/test-projects/localization/src/normal.csv b/test-projects/localization/src/normal.csv new file mode 100644 index 00000000..220cbe87 --- /dev/null +++ b/test-projects/localization/src/normal.csv @@ -0,0 +1,2 @@ +Key,Source,Context,Example,es +Ack,Ack!,,An exclamation of despair,¡Ay! \ No newline at end of file From 5d681a72ac90ea9a3c45c71193f11ba60ce94069 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 4 Apr 2019 18:21:55 -0700 Subject: [PATCH 0490/1504] Rewrite CSV conversion to dodge Serde (#152) * Rewrite CSV conversion to dodge Serde * Update CHANGELOG --- CHANGELOG.md | 2 + server/src/rbx_snapshot.rs | 155 ++++++++++-------- .../localization/expected-snapshot.json | 16 ++ .../localization/src/integers-bug-145.csv | 2 + 4 files changed, 107 insertions(+), 68 deletions(-) create mode 100644 test-projects/localization/src/integers-bug-145.csv diff --git a/CHANGELOG.md b/CHANGELOG.md index d9ee305e..2c659d0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ * Changed `rojo build` to use buffered I/O, which can make it up to 2x faster in some cases. * Building [*Road Not Taken*](https://github.com/LPGhatguy/roads) to an `rbxlx` file dropped from 150ms to 70ms on my machine * Fixed `LocalizationTable` instances being made from `csv` files not supporting empty rows or columns. ([#149](https://github.com/LPGhatguy/rojo/pull/149)) +* Fixed CSV files with entries that parse as numbers causing Rojo to panic ([#152](https://github.com/LPGhatguy/rojo/pull/152)) +* Improved error messages when malformed CSV files are found in a Rojo project ## [0.5.0 Alpha 8](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.8) (March 29, 2019) * Added support for a bunch of new types when dealing with XML model/place files: diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 902b5402..d5fb72ad 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -106,6 +106,7 @@ pub enum SnapshotError { }, XmlModelDecodeError { + #[fail(cause)] inner: rbx_xml::DecodeError, path: PathBuf, }, @@ -115,6 +116,12 @@ pub enum SnapshotError { path: PathBuf, }, + CsvDecodeError { + #[fail(cause)] + inner: csv::Error, + path: PathBuf, + }, + ProjectNodeUnusable, ProjectNodeInvalidTransmute { @@ -151,6 +158,9 @@ impl fmt::Display for SnapshotError { SnapshotError::BinaryModelDecodeError { inner, path } => { write!(output, "Malformed rbxm model: {:?} in path {}", inner, path.display()) }, + SnapshotError::CsvDecodeError { inner, path } => { + write!(output, "Malformed csv file: {} in path {}", inner, path.display()) + }, SnapshotError::ProjectNodeUnusable => { write!(output, "Rojo project nodes must specify either $path or $className.") }, @@ -475,17 +485,87 @@ fn snapshot_txt_file<'source>( fn snapshot_csv_file<'source>( file: &'source ImfsFile, ) -> SnapshotResult<'source> { + /// Struct that holds any valid row from a Roblox CSV translation table. + /// + /// We manually deserialize into this table from CSV, but let JSON handle + /// serializing. + #[derive(Debug, Default, Serialize)] + #[serde(rename_all = "camelCase")] + struct LocalizationEntry<'a> { + #[serde(skip_serializing_if = "Option::is_none")] + key: Option<&'a str>, + + #[serde(skip_serializing_if = "Option::is_none")] + context: Option<&'a str>, + + #[serde(skip_serializing_if = "Option::is_none")] + example: Option<&'a str>, + + #[serde(skip_serializing_if = "Option::is_none")] + source: Option<&'a str>, + + values: HashMap<&'a str, &'a str>, + } + let instance_name = file.path .file_stem().expect("Could not extract file stem") .to_str().expect("Could not convert path to UTF-8"); - let entries: Vec = csv::Reader::from_reader(file.contents.as_slice()) - .deserialize() - // TODO: Propagate error upward instead of panicking - .map(|result| result.expect("Malformed localization table found!")) - .filter(|entry: &LocalizationEntryCsv| !(entry.key.is_empty() && entry.source.is_empty())) - .map(LocalizationEntryCsv::to_json) - .collect(); + // Normally, we'd be able to let the csv crate construct our struct for us. + // + // However, because of a limitation with Serde's 'flatten' feature, it's not + // possible presently to losslessly collect extra string values while using + // csv+Serde. + // + // https://github.com/BurntSushi/rust-csv/issues/151 + let mut reader = csv::Reader::from_reader(file.contents.as_slice()); + + let headers = reader.headers() + .map_err(|inner| SnapshotError::CsvDecodeError { + inner, + path: file.path.to_path_buf(), + })? + .clone(); + + let mut records = Vec::new(); + + for record in reader.into_records() { + let record = record + .map_err(|inner| SnapshotError::CsvDecodeError { + inner, + path: file.path.to_path_buf(), + })?; + + records.push(record); + } + + let mut entries = Vec::new(); + + for record in &records { + let mut entry = LocalizationEntry::default(); + + for (header, value) in headers.iter().zip(record.into_iter()) { + if header.is_empty() || value.is_empty() { + continue; + } + + match header { + "Key" => entry.key = Some(value), + "Source" => entry.source = Some(value), + "Context" => entry.context = Some(value), + "Example" => entry.example = Some(value), + _ => { + entry.values.insert(header, value); + } + } + } + + if entry.key.is_none() && entry.source.is_none() { + continue; + } + + entries.push(entry); + } let table_contents = serde_json::to_string(&entries) .expect("Could not encode JSON for localization table"); @@ -507,67 +587,6 @@ fn snapshot_csv_file<'source>( })) } -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "PascalCase")] -struct LocalizationEntryCsv { - key: String, - context: String, - example: String, - source: String, - #[serde(flatten)] - values: HashMap, -} - -impl LocalizationEntryCsv { - fn to_json(self) -> LocalizationEntryJson { - fn none_if_empty(value: String) -> Option { - if value.is_empty() { - None - } else { - Some(value) - } - } - - let key = none_if_empty(self.key); - let context = none_if_empty(self.context); - let example = none_if_empty(self.example); - let source = none_if_empty(self.source); - - let mut values = HashMap::with_capacity(self.values.len()); - for (key, value) in self.values.into_iter() { - if !key.is_empty() { - values.insert(key, value); - } - } - - LocalizationEntryJson { - key, - context, - example, - source, - values, - } - } -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -struct LocalizationEntryJson { - #[serde(skip_serializing_if = "Option::is_none")] - key: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - context: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - example: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - source: Option, - - values: HashMap, -} - fn snapshot_json_model_file<'source>( file: &'source ImfsFile, ) -> SnapshotResult<'source> { diff --git a/test-projects/localization/expected-snapshot.json b/test-projects/localization/expected-snapshot.json index 1b706d65..dc093685 100644 --- a/test-projects/localization/expected-snapshot.json +++ b/test-projects/localization/expected-snapshot.json @@ -19,6 +19,22 @@ "project_definition": null } }, + { + "name": "integers-bug-145", + "class_name": "LocalizationTable", + "properties": { + "Contents": { + "Type": "String", + "Value": "[{\"key\":\"Count\",\"example\":\"A number demonstrating issue 145\",\"source\":\"3\",\"values\":{\"es\":\"7\"}}]" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src/integers-bug-145.csv", + "project_definition": null + } + }, { "name": "normal", "class_name": "LocalizationTable", diff --git a/test-projects/localization/src/integers-bug-145.csv b/test-projects/localization/src/integers-bug-145.csv new file mode 100644 index 00000000..a865f3fd --- /dev/null +++ b/test-projects/localization/src/integers-bug-145.csv @@ -0,0 +1,2 @@ +Key,Source,Context,Example,es +Count,3,,A number demonstrating issue 145,7 \ No newline at end of file From 7de646c2905c09e34e113fb0469a56f280d3c946 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 4 Apr 2019 18:35:18 -0700 Subject: [PATCH 0491/1504] Upgrade dependencies --- Cargo.lock | 284 +++++++++++++++++++++++++++-------------------------- 1 file changed, 143 insertions(+), 141 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb75d9cb..f0e1615a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,7 +3,7 @@ name = "MacTypes-sys" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -13,7 +13,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "aho-corasick" -version = "0.6.10" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -24,7 +24,7 @@ name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -40,9 +40,9 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -52,15 +52,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -68,8 +68,8 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -121,14 +121,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.32" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -164,7 +164,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -172,7 +172,7 @@ name = "core-foundation-sys" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -232,11 +232,13 @@ dependencies = [ [[package]] name = "csv" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -249,11 +251,11 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -282,7 +284,7 @@ dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -291,7 +293,7 @@ name = "error-chain" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -299,7 +301,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -310,7 +312,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -320,8 +322,8 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -330,7 +332,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -359,7 +361,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -367,7 +369,7 @@ name = "fsevent-sys" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -391,7 +393,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -399,7 +401,7 @@ name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -416,7 +418,7 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -459,7 +461,7 @@ version = "0.12.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -486,7 +488,7 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -514,7 +516,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -522,7 +524,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -530,7 +532,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -560,7 +562,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.50" +version = "0.2.51" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -585,7 +587,7 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -595,8 +597,8 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -614,7 +616,7 @@ name = "memchr" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -654,9 +656,9 @@ name = "miniz_oxide_c_api" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -670,7 +672,7 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -706,7 +708,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.20 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -723,8 +725,8 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -743,11 +745,11 @@ dependencies = [ "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -760,7 +762,7 @@ name = "num_cpus" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -772,7 +774,7 @@ dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -786,8 +788,8 @@ name = "openssl-sys" version = "0.9.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -798,7 +800,7 @@ name = "output_vt100" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -823,11 +825,11 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -847,7 +849,7 @@ dependencies = [ "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -901,7 +903,7 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ctor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "ctor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -913,7 +915,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -956,10 +958,10 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -968,7 +970,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -977,7 +979,7 @@ dependencies = [ "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1023,9 +1025,9 @@ name = "rand_jitter" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1035,10 +1037,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1074,9 +1076,9 @@ name = "rbx_dom_weak" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1115,7 +1117,7 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1123,24 +1125,24 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.1.2" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1151,19 +1153,19 @@ name = "remove_dir_all" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "reqwest" -version = "0.9.12" +version = "0.9.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1171,7 +1173,7 @@ dependencies = [ "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1180,7 +1182,7 @@ dependencies = [ "tokio-threadpool 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1211,8 +1213,8 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1221,10 +1223,10 @@ name = "rojo" version = "0.5.0-alpha.8" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1236,15 +1238,15 @@ dependencies = [ "rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 2.0.377 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1284,7 +1286,7 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1299,7 +1301,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1310,7 +1312,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1319,7 +1321,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1329,17 +1331,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.89" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde_derive" -version = "1.0.89" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1349,7 +1351,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1359,7 +1361,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1418,7 +1420,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.29" +version = "0.15.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1433,7 +1435,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1452,11 +1454,11 @@ version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1472,8 +1474,8 @@ name = "termion" version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1498,9 +1500,9 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1509,7 +1511,7 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1526,7 +1528,7 @@ name = "tokio-current-thread" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1536,7 +1538,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1545,7 +1547,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1555,7 +1557,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1573,7 +1575,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1582,7 +1584,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1597,7 +1599,7 @@ dependencies = [ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1611,7 +1613,7 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1693,11 +1695,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "uuid" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1721,7 +1723,7 @@ version = "2.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1730,7 +1732,7 @@ name = "want" version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1742,7 +1744,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1764,7 +1766,7 @@ name = "winapi-util" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1777,7 +1779,7 @@ name = "wincolor" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1798,12 +1800,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" -"checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5" +"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4" +"checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" @@ -1813,7 +1815,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cc 1.0.32 (registry+https://github.com/rust-lang/crates.io-index)" = "ad0daef304fa0b4238f5f7ed7178774b43b06f6a9b6509f6642bef4ff1f7b9b2" +"checksum cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "30f813bf45048a18eda9190fd3c6b78644146056740c43172a5a3699118588fd" "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -1825,9 +1827,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" -"checksum csv 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "9fd1c44c58078cfbeaf11fbb3eac9ae5534c23004ed770cc4bfb48e658ae4f04" +"checksum csv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f0782c7154d8dd08f4adeb5aa22ab178c10281915f7da68d10bb646f03aaee73" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" -"checksum ctor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9a43db2bba5cafdc6aa068c892a518e477ee0df3705e53ec70247a9ff93546d5" +"checksum ctor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "e5cc1c7c759bf979c651ce1da82d06065375e2223b65c070190b8000787da58b" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" @@ -1845,7 +1847,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b" +"checksum futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "62941eff9507c8177d448bd83a44d9b9760856e184081d8cd79ba9f03dd24981" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "910a5e7be6283a9c91b3982fa5188368c8719cce2a3cf3b86048673bf9d9c36b" @@ -1864,7 +1866,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "aab692d7759f5cd8c859e169db98ae5b52c924add2af5fbbca11d12fefb567c1" +"checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" @@ -1924,12 +1926,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rbx_reflection 2.0.377 (registry+https://github.com/rust-lang/crates.io-index)" = "21ba49260081530590ee48dd1ce6014ac5abc79f581ccb4be0626d436af59e92" "checksum rbx_xml 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891a97bd72d0c6847fe624e724ff3080e3369de74e4ef3b3dab07c6d8ce2bc23" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85" +"checksum redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)" = "d32b3053e5ced86e4bc0411fec997389532bf56b000e66cb4884eeeb41413d69" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f" -"checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861" +"checksum regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "559008764a17de49a3146b234641644ed37d118d1ef641a0bb573d146edc6ce0" +"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.12 (registry+https://github.com/rust-lang/crates.io-index)" = "962fa64e670e70b9d3a81c3688832eb59293ef490e0af5ad169763f62016ac5e" +"checksum reqwest 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3c4ef83e0beb14bfe38b9f01330a5bc8e965a9f9628690aa28383746dac1e925" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "51acb42c134a6568911a2aef2cea5feb80503804cc8986b903983ebfb1342a2c" @@ -1943,8 +1945,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560" -"checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c" +"checksum serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "aa5f7c20820475babd2c077c3ab5f8c77a31c15e16ea38687b4c02d3e48680f4" +"checksum serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "58fc82bec244f168b23d1963b45c8bf5726e9a15a9d146a067f9081aeed2de79" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" @@ -1955,7 +1957,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.15.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1825685f977249735d510a242a6727b46efe914bb67e38d30c071b1b72b1d5c2" +"checksum syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)" = "66c8865bf5a7cbb662d8b011950060b3c8743dca141b054bf7195b20d314d8e2" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" @@ -1984,14 +1986,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" -"checksum uuid 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "600ef8213e9f8a0ac1f876e470e90780ae0478eabce7f76aff41b0f4ef0fd5c0" +"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" +"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" From 83a0ae673c267ea5b36d306f9c126722dbfe5f7d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 4 Apr 2019 21:20:00 -0700 Subject: [PATCH 0492/1504] 0.5.0-alpha.9 --- CHANGELOG.md | 8 +++++--- Cargo.lock | 2 +- docs/installation.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c659d0a..da7de71d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,13 @@ # Rojo Changelog ## [Unreleased] + +## [0.5.0 Alpha 9](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.9) (April 4, 2019) * Changed `rojo build` to use buffered I/O, which can make it up to 2x faster in some cases. * Building [*Road Not Taken*](https://github.com/LPGhatguy/roads) to an `rbxlx` file dropped from 150ms to 70ms on my machine -* Fixed `LocalizationTable` instances being made from `csv` files not supporting empty rows or columns. ([#149](https://github.com/LPGhatguy/rojo/pull/149)) -* Fixed CSV files with entries that parse as numbers causing Rojo to panic ([#152](https://github.com/LPGhatguy/rojo/pull/152)) -* Improved error messages when malformed CSV files are found in a Rojo project +* Fixed `LocalizationTable` instances being made from `csv` files incorrectly interpreting empty rows and columns. ([#149](https://github.com/LPGhatguy/rojo/pull/149)) +* Fixed CSV files with entries that parse as numbers causing Rojo to panic. ([#152](https://github.com/LPGhatguy/rojo/pull/152)) +* Improved error messages when malformed CSV files are found in a Rojo project. ## [0.5.0 Alpha 8](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.8) (March 29, 2019) * Added support for a bunch of new types when dealing with XML model/place files: diff --git a/Cargo.lock b/Cargo.lock index f0e1615a..fdc651ee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1220,7 +1220,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0-alpha.8" +version = "0.5.0-alpha.9" dependencies = [ "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/docs/installation.md b/docs/installation.md index 9166a581..d9faec48 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -25,7 +25,7 @@ If you have Rust installed, the easiest way to get Rojo is with Cargo! To install the latest 0.5.0 alpha, use: ```sh -cargo install rojo --version 0.5.0-alpha.8 +cargo install rojo --version 0.5.0-alpha.9 ``` ## Installing the Plugin diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 78bdeabf..55703420 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0, "-alpha.8"}, + version = {0, 5, 0, "-alpha.9"}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/server/Cargo.toml b/server/Cargo.toml index 30be6d84..82e9e130 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0-alpha.8" +version = "0.5.0-alpha.9" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From f290e7b5b2d08faf06da92c4cccb41500451bbaa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 5 Apr 2019 15:17:58 -0700 Subject: [PATCH 0493/1504] Support implicit values in JSON models (#154) * Support implicit values in JSON models * Update Changelog --- CHANGELOG.md | 1 + server/src/rbx_snapshot.rs | 30 +++++--- server/tests/snapshot_snapshots.rs | 1 + test-projects/json_model/default.project.json | 6 ++ .../json_model/expected-snapshot.json | 76 +++++++++++++++++++ .../json_model/src/children.model.json | 10 +++ .../json_model/src/explicit.model.json | 11 +++ .../json_model/src/implicit.model.json | 7 ++ 8 files changed, 131 insertions(+), 11 deletions(-) create mode 100644 test-projects/json_model/default.project.json create mode 100644 test-projects/json_model/expected-snapshot.json create mode 100644 test-projects/json_model/src/children.model.json create mode 100644 test-projects/json_model/src/explicit.model.json create mode 100644 test-projects/json_model/src/implicit.model.json diff --git a/CHANGELOG.md b/CHANGELOG.md index da7de71d..fc397b09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## [Unreleased] +* Added support for implicit property values in JSON model files ([#154](https://github.com/LPGhatguy/rojo/pull/154)) ## [0.5.0 Alpha 9](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.9) (April 4, 2019) * Changed `rojo build` to use buffered I/O, which can make it up to 2x faster in some cases. diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index d5fb72ad..c31e98e1 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -13,7 +13,7 @@ use rlua::Lua; use failure::Fail; use log::info; use maplit::hashmap; -use rbx_dom_weak::{RbxTree, RbxValue, RbxInstanceProperties}; +use rbx_dom_weak::{RbxTree, RbxValue, RbxInstanceProperties, UnresolvedRbxValue}; use serde_derive::{Serialize, Deserialize}; use rbx_reflection::{try_resolve_value, ValueResolveError}; @@ -602,7 +602,7 @@ fn snapshot_json_model_file<'source>( path: file.path.to_owned(), })?; - let mut snapshot = json_instance.into_snapshot(); + let mut snapshot = json_instance.into_snapshot()?; snapshot.metadata.source_path = Some(file.path.to_owned()); Ok(Some(snapshot)) @@ -618,23 +618,31 @@ struct JsonModelInstance { children: Vec, #[serde(default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")] - properties: HashMap, + properties: HashMap, } impl JsonModelInstance { - fn into_snapshot(mut self) -> RbxSnapshotInstance<'static> { - let children = self.children - .drain(..) - .map(JsonModelInstance::into_snapshot) - .collect(); + fn into_snapshot(self) -> Result, SnapshotError> { + let mut children = Vec::with_capacity(self.children.len()); - RbxSnapshotInstance { + for child in self.children { + children.push(child.into_snapshot()?); + } + + let mut properties = HashMap::with_capacity(self.properties.len()); + + for (key, value) in self.properties { + let resolved_value = try_resolve_value(&self.class_name, &key, &value)?; + properties.insert(key, resolved_value); + } + + Ok(RbxSnapshotInstance { name: Cow::Owned(self.name), class_name: Cow::Owned(self.class_name), - properties: self.properties, + properties, children, metadata: Default::default(), - } + }) } } diff --git a/server/tests/snapshot_snapshots.rs b/server/tests/snapshot_snapshots.rs index 1efeffa6..7c3d1e78 100644 --- a/server/tests/snapshot_snapshots.rs +++ b/server/tests/snapshot_snapshots.rs @@ -33,6 +33,7 @@ macro_rules! generate_snapshot_tests { generate_snapshot_tests!( empty, + json_model, localization, multi_partition_game, nested_partitions, diff --git a/test-projects/json_model/default.project.json b/test-projects/json_model/default.project.json new file mode 100644 index 00000000..603a4ca8 --- /dev/null +++ b/test-projects/json_model/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "json_model", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/test-projects/json_model/expected-snapshot.json b/test-projects/json_model/expected-snapshot.json new file mode 100644 index 00000000..e4f223d8 --- /dev/null +++ b/test-projects/json_model/expected-snapshot.json @@ -0,0 +1,76 @@ +{ + "name": "json_model", + "class_name": "Folder", + "properties": {}, + "children": [ + { + "name": "children", + "class_name": "Folder", + "properties": {}, + "children": [ + { + "name": "The Child", + "class_name": "StringValue", + "properties": {}, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": null, + "project_definition": null + } + } + ], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src/children.model.json", + "project_definition": null + } + }, + { + "name": "explicit", + "class_name": "StringValue", + "properties": { + "Value": { + "Type": "String", + "Value": "Hello, world!" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src/explicit.model.json", + "project_definition": null + } + }, + { + "name": "implicit", + "class_name": "StringValue", + "properties": { + "Value": { + "Type": "String", + "Value": "What's happenin', Earth?" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src/implicit.model.json", + "project_definition": null + } + } + ], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src", + "project_definition": [ + "json_model", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "src" + } + ] + } +} \ No newline at end of file diff --git a/test-projects/json_model/src/children.model.json b/test-projects/json_model/src/children.model.json new file mode 100644 index 00000000..d5a9ea91 --- /dev/null +++ b/test-projects/json_model/src/children.model.json @@ -0,0 +1,10 @@ +{ + "Name": "children", + "ClassName": "Folder", + "Children": [ + { + "Name": "The Child", + "ClassName": "StringValue" + } + ] +} \ No newline at end of file diff --git a/test-projects/json_model/src/explicit.model.json b/test-projects/json_model/src/explicit.model.json new file mode 100644 index 00000000..99d0b11a --- /dev/null +++ b/test-projects/json_model/src/explicit.model.json @@ -0,0 +1,11 @@ +{ + "Name": "explicit", + "ClassName": "StringValue", + "Properties": { + "Value": { + "Type": "String", + "Value": "Hello, world!" + } + }, + "Children": [] +} \ No newline at end of file diff --git a/test-projects/json_model/src/implicit.model.json b/test-projects/json_model/src/implicit.model.json new file mode 100644 index 00000000..91a2c778 --- /dev/null +++ b/test-projects/json_model/src/implicit.model.json @@ -0,0 +1,7 @@ +{ + "Name": "implicit", + "ClassName": "StringValue", + "Properties": { + "Value": "What's happenin', Earth?" + } +} \ No newline at end of file From a365f071a4122ea353fd4ba06f91a77f32768833 Mon Sep 17 00:00:00 2001 From: "eryn L. K" Date: Fri, 5 Apr 2019 20:20:53 -0400 Subject: [PATCH 0494/1504] Update installation.md (#155) --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index d9faec48..808f70a4 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -42,4 +42,4 @@ Download the attached `rbxm` file and put it into your Roblox Studio plugins fol Visit [Rojo's Roblox.com Plugin page](https://www.roblox.com/library/1997686364/Rojo-0-5-0-alpha-3) in Roblox Studio and press **Install**. ## Visual Studio Code Extension -If you use Visual Studio Code on Windows, you can install [Evaera's unofficial Rojo extension](https://marketplace.visualstudio.com/items?itemName=evaera.vscode-rojo), which will install both halves of Rojo for you. It even has a nifty UI to add partitions and start/stop the Rojo server! \ No newline at end of file +If you use Visual Studio Code, you can install [Evaera's unofficial Rojo extension](https://marketplace.visualstudio.com/items?itemName=evaera.vscode-rojo), which will install both halves of Rojo for you. It even has a nifty UI to sync files and start/stop the Rojo server! From ff0a830e0cb9d73723a11c3c0934587dffa3d10e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Diego=20Alp=C3=ADzar?= <48010731+DiegoAlpizar@users.noreply.github.com> Date: Sun, 7 Apr 2019 00:38:29 -0600 Subject: [PATCH 0495/1504] Minor typo fix (#156) Fix repeated "available available" --- docs/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/installation.md b/docs/installation.md index 808f70a4..4823de28 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -31,7 +31,7 @@ cargo install rojo --version 0.5.0-alpha.9 ## Installing the Plugin ### Installing from GitHub -The Rojo Roblox Studio plugin is available available from Rojo's [GitHub Releases page](https://github.com/LPGhatguy/rojo/releases). +The Rojo Roblox Studio plugin is available from Rojo's [GitHub Releases page](https://github.com/LPGhatguy/rojo/releases). Download the attached `rbxm` file and put it into your Roblox Studio plugins folder. You can find that folder by pressing **Plugins Folder** from your Plugins toolbar in Roblox Studio: From fb5245e2af9f8fc0174f03a164584ac035ddab45 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 22 Apr 2019 18:26:28 -0700 Subject: [PATCH 0496/1504] Update dependencies --- Cargo.lock | 275 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 170 insertions(+), 105 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fdc651ee..96c99ba0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,3 +1,5 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "MacTypes-sys" version = "2.1.0" @@ -41,7 +43,7 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -59,7 +61,7 @@ dependencies = [ "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -68,7 +70,7 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -128,7 +130,7 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -138,14 +140,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "clap" -version = "2.32.0" +version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -158,6 +160,34 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cookie" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cookie_store" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "core-foundation" version = "0.5.1" @@ -232,7 +262,7 @@ dependencies = [ [[package]] name = "csv" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -251,11 +281,11 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -284,7 +314,7 @@ dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -310,9 +340,9 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -323,7 +353,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -412,14 +442,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "h2" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -434,7 +464,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "http" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -457,14 +487,14 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.25" +version = "0.12.27" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -472,12 +502,12 @@ dependencies = [ "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -489,7 +519,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.27 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -597,7 +627,7 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -656,7 +686,7 @@ name = "miniz_oxide_c_api" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -765,6 +795,11 @@ dependencies = [ "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "numtoa" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "openssl" version = "0.10.20" @@ -788,7 +823,7 @@ name = "openssl-sys" version = "0.9.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -838,7 +873,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -846,10 +881,10 @@ name = "paste-impl" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -903,19 +938,19 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ctor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro-hack" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -925,12 +960,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.27" +version = "0.4.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "publicsuffix" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pulldown-cmark" version = "0.2.0" @@ -946,10 +993,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1117,7 +1164,7 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.52" +version = "0.1.54" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1125,12 +1172,12 @@ name = "redox_termios" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex" -version = "1.1.5" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1158,16 +1205,18 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.13" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie_store 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.27 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1175,11 +1224,12 @@ dependencies = [ "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1191,7 +1241,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1201,9 +1251,9 @@ name = "ritz_impl" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1213,7 +1263,7 @@ version = "0.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1222,12 +1272,12 @@ dependencies = [ name = "rojo" version = "0.5.0-alpha.9" dependencies = [ - "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.27 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1238,8 +1288,8 @@ dependencies = [ "rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 2.0.377 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1256,7 +1306,7 @@ version = "0.1.0" [[package]] name = "rustc-demangle" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1339,9 +1389,9 @@ name = "serde_derive" version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1356,7 +1406,7 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1400,7 +1450,7 @@ name = "snax" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1415,16 +1465,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strsim" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.30" +version = "0.15.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1433,9 +1483,9 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1456,7 +1506,7 @@ dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1471,17 +1521,18 @@ dependencies = [ [[package]] name = "termion" -version = "1.5.1" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", + "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "textwrap" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1501,13 +1552,13 @@ version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1518,7 +1569,8 @@ dependencies = [ "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1566,12 +1618,12 @@ dependencies = [ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-sync" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1593,7 +1645,7 @@ dependencies = [ [[package]] name = "tokio-threadpool" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1631,6 +1683,14 @@ name = "try-lock" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "try_from" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ucd-util" version = "0.1.3" @@ -1815,10 +1875,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cc 1.0.34 (registry+https://github.com/rust-lang/crates.io-index)" = "30f813bf45048a18eda9190fd3c6b78644146056740c43172a5a3699118588fd" +"checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83" "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" -"checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf" +"checksum cookie_store 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b0d2f2ecb21dce00e2453268370312978af9b8024020c7a37ae2cc6dbbe64685" "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" @@ -1827,9 +1889,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" -"checksum csv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f0782c7154d8dd08f4adeb5aa22ab178c10281915f7da68d10bb646f03aaee73" +"checksum csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9044e25afb0924b5a5fc5511689b0918629e85d68ea591e5e87fbf1e85ea1b3b" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" -"checksum ctor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "e5cc1c7c759bf979c651ce1da82d06065375e2223b65c070190b8000787da58b" +"checksum ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3b4c17619643c1252b5f690084b82639dd7fac141c57c8e77a00e0148132092c" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" @@ -1850,12 +1912,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "62941eff9507c8177d448bd83a44d9b9760856e184081d8cd79ba9f03dd24981" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum h2 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "910a5e7be6283a9c91b3982fa5188368c8719cce2a3cf3b86048673bf9d9c36b" +"checksum h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "85ab6286db06040ddefb71641b50017c06874614001a134b423783e2db2920bd" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" -"checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a" +"checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)" = "7d5b6658b016965ae301fa995306db965c93677880ea70765a84235a96eae896" +"checksum hyper 0.12.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4f2777434f26af6e4ce4fdcdccd3bed9d861d11e87bcbe72c0f51ddaca8ff848" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" @@ -1888,6 +1950,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum notify 4.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "abb1581693e44d8a0ec347ef12289625063f52a1dddc3f3c9befd5fc59e88943" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" "checksum openssl 0.10.20 (registry+https://github.com/rust-lang/crates.io-index)" = "5a0d6b781aac4ac1bd6cafe2a2f0ad8c16ae8e1dd5184822a16c50139f8838d9" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)" = "33c86834957dd5b915623e94f2f4ab2c70dd8f6b70679824155d5ae21dbd495d" @@ -1904,12 +1967,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" -"checksum proc-macro-hack 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3e90aa19cd73dedc2d0e1e8407473f073d735fef0ab521438de6da8ee449ab66" +"checksum proc-macro-hack 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6a9bed9ebc40cf53e3a76d7486c54d05002eae6485b2711ab9104476fb2eb8bc" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" -"checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915" +"checksum proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)" = "ba92c84f814b3f9a44c5cfca7d2ad77fa10710867d2bbb1b3d175ab5f47daa12" +"checksum publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5afecba86dcf1e4fd610246f89899d1924fe12e1e89f555eb7c7f710f3c5ad1d" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1" +"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" @@ -1926,16 +1990,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rbx_reflection 2.0.377 (registry+https://github.com/rust-lang/crates.io-index)" = "21ba49260081530590ee48dd1ce6014ac5abc79f581ccb4be0626d436af59e92" "checksum rbx_xml 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891a97bd72d0c6847fe624e724ff3080e3369de74e4ef3b3dab07c6d8ce2bc23" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.52 (registry+https://github.com/rust-lang/crates.io-index)" = "d32b3053e5ced86e4bc0411fec997389532bf56b000e66cb4884eeeb41413d69" +"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "559008764a17de49a3146b234641644ed37d118d1ef641a0bb573d146edc6ce0" +"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" "checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3c4ef83e0beb14bfe38b9f01330a5bc8e965a9f9628690aa28383746dac1e925" +"checksum reqwest 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "943b9f85622f53bcf71721e0996f23688e3942e51fc33766c2e24a959316767b" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "51acb42c134a6568911a2aef2cea5feb80503804cc8986b903983ebfb1342a2c" -"checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619" +"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" @@ -1948,7 +2012,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "aa5f7c20820475babd2c077c3ab5f8c77a31c15e16ea38687b4c02d3e48680f4" "checksum serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "58fc82bec244f168b23d1963b45c8bf5726e9a15a9d146a067f9081aeed2de79" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" -"checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2" +"checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" @@ -1956,27 +2020,28 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef82be0baf3ae45701ab992230f1f4889c15984736d87f37558aea3e4e321af" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" -"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" -"checksum syn 0.15.30 (registry+https://github.com/rust-lang/crates.io-index)" = "66c8865bf5a7cbb662d8b011950060b3c8743dca141b054bf7195b20d314d8e2" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)" = "846620ec526c1599c070eff393bfeeeb88a93afa2513fc3b49f1fea84cf7b0ed" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" -"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" -"checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6" +"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "65641e515a437b308ab131a82ce3042ff9795bef5d6c5a9be4eb24195c417fd9" +"checksum tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "cec6c34409089be085de9403ba2010b80e36938c9ca992c4f67f407bb13db0b1" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" "checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" "checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" -"checksum tokio-sync 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "fda385df506bf7546e70872767f71e81640f1f251bdf2fd8eb81a0eaec5fe022" +"checksum tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2f843ffdf8d6e1f90bddd48da43f99ab071660cd92b7ec560ef3cdfd7a409a" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "ec5759cf26cf9659555f36c431b515e3d05f66831741c85b4b5d5dfb9cf1323c" +"checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2" "checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" "checksum tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "350c9edade9830dc185ae48ba45667a445ab59f6167ef6d0254ec9d2430d9dd3" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" +"checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41d17211f887da8e4a70a45b9536f26fc5de166b81e2d5d80de4a17fd22553bd" From 34b99a51c370750b208ae07121a5d5c1b3f92360 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 30 Apr 2019 23:06:59 -0700 Subject: [PATCH 0497/1504] Relax debug assert in IMFS, since paths can alias now --- server/src/imfs.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/server/src/imfs.rs b/server/src/imfs.rs index 0672ddb1..db8ebcd5 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -89,11 +89,13 @@ impl Imfs { pub fn add_root(&mut self, path: &Path) -> Result<(), FsError> { debug_assert!(path.is_absolute()); - debug_assert!(!self.is_within_roots(path)); - self.roots.insert(path.to_path_buf()); + if !self.is_within_roots(path) { + self.roots.insert(path.to_path_buf()); + self.descend_and_read_from_disk(path)?; + } - self.descend_and_read_from_disk(path) + Ok(()) } pub fn remove_root(&mut self, path: &Path) { From 84832955dd6ecca9f4f2e681311f0553ba3b9fd7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 4 May 2019 00:05:45 -0700 Subject: [PATCH 0498/1504] Upgrade to Roact 1.0 and latest t --- plugin/modules/roact | 2 +- plugin/modules/t | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/modules/roact b/plugin/modules/roact index 8da5b298..41af74df 160000 --- a/plugin/modules/roact +++ b/plugin/modules/roact @@ -1 +1 @@ -Subproject commit 8da5b298059382499df05102d62ba01a20bd4e1e +Subproject commit 41af74df730723ed39c02f54cae7c6c97c6c5d9c diff --git a/plugin/modules/t b/plugin/modules/t index a3a80ebf..f643b506 160000 --- a/plugin/modules/t +++ b/plugin/modules/t @@ -1 +1 @@ -Subproject commit a3a80ebf0a45f435c38cc3e719844ad1b6245cec +Subproject commit f643b50682c24ec8d6ac3e11f41ee8cbbb2bcecb From 379b162e6461352ea0e9b5f6ce2ceea139ce7522 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 4 May 2019 19:33:08 -0700 Subject: [PATCH 0499/1504] Fix dependency paths changing. Roact 1.0 changed from lib to src! t changed from lib/t.lua to lib/init.lua, so we just use lib --- plugin/default.project.json | 4 ++-- plugin/place.project.json | 4 ++-- plugin/rojo.json | 34 ---------------------------------- 3 files changed, 4 insertions(+), 38 deletions(-) delete mode 100644 plugin/rojo.json diff --git a/plugin/default.project.json b/plugin/default.project.json index 2cf6eadc..0e84f4f9 100644 --- a/plugin/default.project.json +++ b/plugin/default.project.json @@ -6,13 +6,13 @@ "$path": "src" }, "Roact": { - "$path": "modules/roact/lib" + "$path": "modules/roact/src" }, "Promise": { "$path": "modules/promise/lib" }, "t": { - "$path": "modules/t/lib/t.lua" + "$path": "modules/t/lib" } } } \ No newline at end of file diff --git a/plugin/place.project.json b/plugin/place.project.json index 9ba8c85b..50bbeb18 100644 --- a/plugin/place.project.json +++ b/plugin/place.project.json @@ -13,13 +13,13 @@ "$path": "src" }, "Roact": { - "$path": "modules/roact/lib" + "$path": "modules/roact/src" }, "Promise": { "$path": "modules/promise/lib" }, "t": { - "$path": "modules/t/lib/t.lua" + "$path": "modules/t/lib" } }, "TestEZ": { diff --git a/plugin/rojo.json b/plugin/rojo.json deleted file mode 100644 index 3882435a..00000000 --- a/plugin/rojo.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "name": "rojo", - "servePort": 8000, - "partitions": { - "plugin": { - "path": "src", - "target": "ReplicatedStorage.Rojo.Plugin" - }, - "modules/roact": { - "path": "modules/roact/lib", - "target": "ReplicatedStorage.Rojo.Roact" - }, - "modules/rodux": { - "path": "modules/rodux/lib", - "target": "ReplicatedStorage.Rojo.Rodux" - }, - "modules/roact-rodux": { - "path": "modules/roact-rodux/lib", - "target": "ReplicatedStorage.Rojo.RoactRodux" - }, - "modules/promise": { - "path": "modules/promise/lib", - "target": "ReplicatedStorage.Rojo.Promise" - }, - "modules/testez": { - "path": "modules/testez/lib", - "target": "ReplicatedStorage.TestEZ" - }, - "tests": { - "path": "testBootstrap.server.lua", - "target": "TestService.testBootstrap" - } - } -} \ No newline at end of file From fe6acbc1e3fc11e43605a0cc4b19024d91091870 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 4 May 2019 21:01:10 -0700 Subject: [PATCH 0500/1504] Clean up repo cruft --- Cargo.lock | 4 -- Cargo.toml | 1 - generate-docs => bin/generate-docs | 0 .../test-scratch-project | 0 design.gv | 39 ------------------- rojo-e2e/Cargo.toml | 6 --- rojo-e2e/README.md | 2 - rojo-e2e/src/lib.rs | 32 --------------- 8 files changed, 84 deletions(-) rename generate-docs => bin/generate-docs (100%) rename test-scratch-project => bin/test-scratch-project (100%) delete mode 100644 design.gv delete mode 100644 rojo-e2e/Cargo.toml delete mode 100644 rojo-e2e/README.md delete mode 100644 rojo-e2e/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 96c99ba0..f3cb776a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1300,10 +1300,6 @@ dependencies = [ "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rojo-e2e" -version = "0.1.0" - [[package]] name = "rustc-demangle" version = "0.1.14" diff --git a/Cargo.toml b/Cargo.toml index 27dc248a..90f1b5a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,4 @@ [workspace] members = [ "server", - "rojo-e2e", ] \ No newline at end of file diff --git a/generate-docs b/bin/generate-docs similarity index 100% rename from generate-docs rename to bin/generate-docs diff --git a/test-scratch-project b/bin/test-scratch-project similarity index 100% rename from test-scratch-project rename to bin/test-scratch-project diff --git a/design.gv b/design.gv deleted file mode 100644 index 479ab71c..00000000 --- a/design.gv +++ /dev/null @@ -1,39 +0,0 @@ -digraph G { - graph [ - ranksep = "0.7", - nodesep = "1.0", - ]; - node [ - fontname = "Hack", - shape = "record", - ]; - - roblox_studio -> plugin [dir = "both"]; - plugin -> web_server [style = "dashed", dir = "both"]; - - web_server -> session; - - session -> rbx_session; - session -> fs_watcher; - session -> message_queue; - - fs_watcher -> imfs [weight = "10"]; - fs_watcher -> rbx_session [constraint = "false"]; - - imfs -> fs; - - rbx_session -> imfs; - rbx_session -> middlewares [weight = "10"]; - rbx_session -> message_queue [constraint = "false"]; - - plugin [label = "Studio Plugin"]; - roblox_studio [label = "Roblox Studio"]; - fs [label = "Filesystem"]; - fs_watcher [label = "Filesystem Watcher"]; - session [label = "Session"]; - web_server [label = "Web API"]; - imfs [label = "In-Memory Filesystem"]; - rbx_session [label = "RbxSession"]; - message_queue [label = "MessageQueue"]; - middlewares [label = "Middlewares"]; -} \ No newline at end of file diff --git a/rojo-e2e/Cargo.toml b/rojo-e2e/Cargo.toml deleted file mode 100644 index 8afc532d..00000000 --- a/rojo-e2e/Cargo.toml +++ /dev/null @@ -1,6 +0,0 @@ -[package] -name = "rojo-e2e" -version = "0.1.0" -authors = ["Lucien Greathouse "] - -[dependencies] diff --git a/rojo-e2e/README.md b/rojo-e2e/README.md deleted file mode 100644 index 6dbb1cca..00000000 --- a/rojo-e2e/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# Rojo End-to-End -This is a WIP test runner designed for Rojo. It will eventually start up the Rojo server and plugin and test functionality end-to-end. \ No newline at end of file diff --git a/rojo-e2e/src/lib.rs b/rojo-e2e/src/lib.rs deleted file mode 100644 index 4e4883b1..00000000 --- a/rojo-e2e/src/lib.rs +++ /dev/null @@ -1,32 +0,0 @@ -use std::{ - path::Path, - process::Command, - thread, - time::Duration, -}; - -fn main() { - let plugin_path = Path::new("../plugin"); - let server_path = Path::new("../server"); - let tests_path = Path::new("../tests"); - - let server = Command::new("cargo") - .args(&["run", "--", "serve", "../test-projects/empty"]) - .current_dir(server_path) - .spawn(); - - thread::sleep(Duration::from_millis(1000)); - - // TODO: Wait for server to start responding on the right port - - let test_client = Command::new("lua") - .args(&["runTest.lua", "tests/empty.lua"]) - .current_dir(plugin_path) - .spawn(); - - thread::sleep(Duration::from_millis(300)); - - // TODO: Collect output from the client for success/failure? - - println!("Dying!"); -} From 3ea432ef2d03442c1c6bb1f4af6eaebde3214fdf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 9 May 2019 13:29:03 -0700 Subject: [PATCH 0501/1504] Fix up docs on model/place files a little --- docs/creating-a-place.md | 6 +++--- docs/sync-details.md | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/creating-a-place.md b/docs/creating-a-place.md index 7ffcd418..d20f8ffd 100644 --- a/docs/creating-a-place.md +++ b/docs/creating-a-place.md @@ -28,13 +28,13 @@ Now that we have a project, one thing we can do is build a Roblox place file for All we have to do is call `rojo build`: ```sh -rojo build -o MyNewProject.rbxl +rojo build -o MyNewProject.rbxlx ``` -If you open `MyNewProject.rbxl` in Roblox Studio now, you should see a `Folder` containing a `ModuleScript` under `ReplicatedStorage`! +If you open `MyNewProject.rbxlx` in Roblox Studio now, you should see a `Folder` containing a `ModuleScript` under `ReplicatedStorage`! !!! info - To generate an XML place file instead, like if you're checking the place file into version control, just use `rbxlx` as the extension on the output file instead. + To generate a binary place file instead, use `rbxl`. Note that support for binary model/place files (`rbxm` and `rbxl`) is very limited in Rojo presently. ## Live-Syncing into Studio Building a place file is great for the initial build, but for actively working on your place, you'll want something quicker. diff --git a/docs/sync-details.md b/docs/sync-details.md index a016e019..2bb6ec53 100644 --- a/docs/sync-details.md +++ b/docs/sync-details.md @@ -86,6 +86,6 @@ It would turn into instances in this shape: ## Binary and XML Models Rojo supports both binary (`.rbxm`) and XML (`.rbxmx`) models generated by Roblox Studio or another tool. -Not all property types are supported for all formats! +Support for the `rbxmx` is very good, while support for `rbxm` is still very early, buggy, and lacking features. -For a rundown of supported types, check out [rbx_tree's type coverage chart](https://github.com/LPGhatguy/rbx-tree#property-type-coverage). \ No newline at end of file +For a rundown of supported types, check out [rbx-dom's type coverage chart](https://github.com/LPGhatguy/rbx-dom#property-type-coverage). \ No newline at end of file From 27e2612fc9368554429cbaa766169edfa6d1f702 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 12 May 2019 12:57:24 -0700 Subject: [PATCH 0502/1504] Upgrade rbx_dom_weak, rbx_reflection, and rbx_xml --- CHANGELOG.md | 11 ++++++++++ Cargo.lock | 35 +++++++++++++++---------------- Cargo.toml | 5 ++++- server/Cargo.toml | 9 ++++---- server/src/commands/build.rs | 4 ++-- server/src/commands/upload.rs | 4 ++-- server/src/imfs.rs | 2 +- server/src/path_map.rs | 2 +- server/src/path_serializer.rs | 2 +- server/src/project.rs | 3 +-- server/src/rbx_session.rs | 2 +- server/src/rbx_snapshot.rs | 13 +++--------- server/src/session_id.rs | 2 +- server/src/snapshot_reconciler.rs | 2 +- server/src/web/api.rs | 2 +- server/tests/test_util/tree.rs | 2 +- 16 files changed, 52 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc397b09..86cabe8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,17 @@ # Rojo Changelog ## [Unreleased] +* Upgraded significant dependencies: + * rbx_dom_weak 1.6.0 + * `Content` properties can now be specified in projects and model files as strings + * Added support for `BrickColor`, but with no handy conversions yet + * rbx_reflection 3.0.384 + * Updated reflection database to client release 384 + * Adds support for new enum variants like `Lighting.Technology` as `"ShadowMap"` + * rbx_xml 0.7.0 + * Performance improvements dealing with model/place files due to smaller error type + * Fixed serializing empty `Content` properties + * Improved content compatibility utilizing the reflection database * Added support for implicit property values in JSON model files ([#154](https://github.com/LPGhatguy/rojo/pull/154)) ## [0.5.0 Alpha 9](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.9) (April 4, 2019) diff --git a/Cargo.lock b/Cargo.lock index f3cb776a..49fa12ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1115,12 +1115,12 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_dom_weak" -version = "1.4.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1130,27 +1130,24 @@ dependencies = [ [[package]] name = "rbx_reflection" -version = "2.0.377" +version = "3.0.384" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_xml" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.0.384 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1285,15 +1282,14 @@ dependencies = [ "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 2.0.377 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.0.384 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1379,6 +1375,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "serde" version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "serde_derive" @@ -1982,9 +1981,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147f236284747ac1b4643476265dd36b402877d97adb7cbd0fafc1d247de0a5" -"checksum rbx_dom_weak 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d581dcb6e5eb395a5923e1efe39883124115d725dacae07cdf084204345611e7" -"checksum rbx_reflection 2.0.377 (registry+https://github.com/rust-lang/crates.io-index)" = "21ba49260081530590ee48dd1ce6014ac5abc79f581ccb4be0626d436af59e92" -"checksum rbx_xml 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "891a97bd72d0c6847fe624e724ff3080e3369de74e4ef3b3dab07c6d8ce2bc23" +"checksum rbx_dom_weak 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9af92582e8ac283fce50fe223d741e8f7f865a13ec99fdecc38cfb431de3ccf" +"checksum rbx_reflection 3.0.384 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf0e45a2f1abeddf8096591c1081151e9114f4426fed97cab1d123b3fe4010f" +"checksum rbx_xml 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1142b88066f633c05a6589b8c19b69f04e9474dc9d1b659df6fc523ca8712ead" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" diff --git a/Cargo.toml b/Cargo.toml index 90f1b5a4..9c4ce1b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,7 @@ [workspace] members = [ "server", -] \ No newline at end of file +] + +[profile.dev] +opt-level = 1 \ No newline at end of file diff --git a/server/Cargo.toml b/server/Cargo.toml index 82e9e130..27a7672a 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -30,15 +30,14 @@ log = "0.4" maplit = "1.0.1" notify = "4.0" rbx_binary = "0.4.0" -rbx_dom_weak = "1.3.0" -rbx_xml = "0.6.0" -rbx_reflection = "2.0.374" +rbx_dom_weak = "1.6.0" +rbx_xml = "0.7.0" +rbx_reflection = "3.0.384" regex = "1.0" reqwest = "0.9.5" rlua = "0.16" ritz = "0.1.0" -serde = "1.0" -serde_derive = "1.0" +serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" uuid = { version = "0.7", features = ["v4", "serde"] } diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index 8a65387f..ffb054e0 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -100,7 +100,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { // descendants. let root_id = tree.get_root_id(); - rbx_xml::encode(&tree, &[root_id], &mut file)?; + rbx_xml::to_writer_default(&mut file, &tree, &[root_id])?; }, OutputKind::Rbxlx => { // Place files don't contain an entry for the DataModel, but our @@ -108,7 +108,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let root_id = tree.get_root_id(); let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); - rbx_xml::encode(&tree, top_level_ids, &mut file)?; + rbx_xml::to_writer_default(&mut file, &tree, top_level_ids)?; }, OutputKind::Rbxm => { let root_id = tree.get_root_id(); diff --git a/server/src/commands/upload.rs b/server/src/commands/upload.rs index a142d43e..6c80485a 100644 --- a/server/src/commands/upload.rs +++ b/server/src/commands/upload.rs @@ -80,10 +80,10 @@ pub fn upload(options: &UploadOptions) -> Result<(), UploadError> { match options.kind { Some("place") | None => { let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); - rbx_xml::encode(&tree, top_level_ids, &mut contents)?; + rbx_xml::to_writer_default(&mut contents, &tree, top_level_ids)?; }, Some("model") => { - rbx_xml::encode(&tree, &[root_id], &mut contents)?; + rbx_xml::to_writer_default(&mut contents, &tree, &[root_id])?; }, Some(invalid) => return Err(UploadError::InvalidKind(invalid.to_owned())), } diff --git a/server/src/imfs.rs b/server/src/imfs.rs index db8ebcd5..75cb0314 100644 --- a/server/src/imfs.rs +++ b/server/src/imfs.rs @@ -8,7 +8,7 @@ use std::{ }; use failure::Fail; -use serde_derive::{Serialize, Deserialize}; +use serde::{Serialize, Deserialize}; use crate::project::{Project, ProjectNode}; diff --git a/server/src/path_map.rs b/server/src/path_map.rs index 8df2d83a..bebf4f9d 100644 --- a/server/src/path_map.rs +++ b/server/src/path_map.rs @@ -3,7 +3,7 @@ use std::{ collections::{HashMap, HashSet}, }; -use serde_derive::Serialize; +use serde::Serialize; use log::warn; #[derive(Debug, Serialize)] diff --git a/server/src/path_serializer.rs b/server/src/path_serializer.rs index 214a773a..41cfc5d0 100644 --- a/server/src/path_serializer.rs +++ b/server/src/path_serializer.rs @@ -10,7 +10,7 @@ //! //! ``` //! # use std::path::PathBuf; -//! # use serde_derive::{Serialize, Deserialize}; +//! # use serde::{Serialize, Deserialize}; //! //! #[derive(Serialize, Deserialize)] //! struct Mine { diff --git a/server/src/project.rs b/server/src/project.rs index 24d945e4..346158ee 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -9,8 +9,7 @@ use std::{ use log::warn; use failure::Fail; use rbx_dom_weak::{UnresolvedRbxValue, RbxValue}; -use serde_derive::{Serialize, Deserialize}; -use serde::{Serialize, Serializer}; +use serde::{Serialize, Serializer, Deserialize}; static DEFAULT_PLACE: &'static str = include_str!("../assets/place.project.json"); diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs index 7310736a..80fe58e2 100644 --- a/server/src/rbx_session.rs +++ b/server/src/rbx_session.rs @@ -7,7 +7,7 @@ use std::{ }; use rlua::Lua; -use serde_derive::{Serialize, Deserialize}; +use serde::{Serialize, Deserialize}; use log::{info, trace, error}; use rbx_dom_weak::{RbxTree, RbxId}; diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index c31e98e1..9cf875ce 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -14,7 +14,7 @@ use failure::Fail; use log::info; use maplit::hashmap; use rbx_dom_weak::{RbxTree, RbxValue, RbxInstanceProperties, UnresolvedRbxValue}; -use serde_derive::{Serialize, Deserialize}; +use serde::{Serialize, Deserialize}; use rbx_reflection::{try_resolve_value, ValueResolveError}; use crate::{ @@ -653,20 +653,13 @@ fn snapshot_xml_model_file<'source>( .file_stem().expect("Could not extract file stem") .to_str().expect("Could not convert path to UTF-8"); - let mut temp_tree = RbxTree::new(RbxInstanceProperties { - name: "Temp".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), - }); - - let root_id = temp_tree.get_root_id(); - rbx_xml::decode(&mut temp_tree, root_id, file.contents.as_slice()) + let temp_tree = rbx_xml::from_reader_default(file.contents.as_slice()) .map_err(|inner| SnapshotError::XmlModelDecodeError { inner, path: file.path.clone(), })?; - let root_instance = temp_tree.get_instance(root_id).unwrap(); + let root_instance = temp_tree.get_instance(temp_tree.get_root_id()).unwrap(); let children = root_instance.get_children_ids(); match children.len() { diff --git a/server/src/session_id.rs b/server/src/session_id.rs index 67783a7f..5aae5661 100644 --- a/server/src/session_id.rs +++ b/server/src/session_id.rs @@ -1,4 +1,4 @@ -use serde_derive::{Serialize, Deserialize}; +use serde::{Serialize, Deserialize}; use uuid::Uuid; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] diff --git a/server/src/snapshot_reconciler.rs b/server/src/snapshot_reconciler.rs index baaa3309..424ee8ec 100644 --- a/server/src/snapshot_reconciler.rs +++ b/server/src/snapshot_reconciler.rs @@ -11,7 +11,7 @@ use std::{ }; use rbx_dom_weak::{RbxTree, RbxId, RbxInstanceProperties, RbxValue}; -use serde_derive::{Serialize, Deserialize}; +use serde::{Serialize, Deserialize}; use crate::{ path_map::PathMap, diff --git a/server/src/web/api.rs b/server/src/web/api.rs index 0b6cbe03..82d9e70f 100644 --- a/server/src/web/api.rs +++ b/server/src/web/api.rs @@ -21,7 +21,7 @@ use hyper::{ Request, Response, }; -use serde_derive::{Serialize, Deserialize}; +use serde::{Serialize, Deserialize}; use rbx_dom_weak::{RbxId, RbxInstance}; use crate::{ diff --git a/server/tests/test_util/tree.rs b/server/tests/test_util/tree.rs index 4f2525de..4d4ff3b1 100644 --- a/server/tests/test_util/tree.rs +++ b/server/tests/test_util/tree.rs @@ -20,7 +20,7 @@ use std::{ }; use log::error; -use serde_derive::{Serialize, Deserialize}; +use serde::{Serialize, Deserialize}; use rbx_dom_weak::{RbxId, RbxTree}; use librojo::{ From 20976814bae495fe1dbe4d0f4b1a647bc185c7c1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 12 May 2019 12:57:59 -0700 Subject: [PATCH 0503/1504] Upgrade a bunch of small dependencies --- Cargo.lock | 434 +++++++++++++++++++++++++---------------------------- 1 file changed, 206 insertions(+), 228 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 49fa12ae..d6752fba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,11 +1,32 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -[[package]] -name = "MacTypes-sys" -version = "2.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +[root] +name = "rojo" +version = "0.5.0-alpha.9" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.0.384 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)", + "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -42,7 +63,7 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -60,7 +81,7 @@ dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -70,8 +91,8 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -82,11 +103,6 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bitflags" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "bitflags" version = "1.0.4" @@ -121,16 +137,16 @@ name = "cargo_metadata" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -162,7 +178,7 @@ dependencies = [ [[package]] name = "cookie" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -174,14 +190,14 @@ name = "cookie_store" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -190,20 +206,17 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.5.1" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "core-foundation-sys" -version = "0.5.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "crc" @@ -266,9 +279,9 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -285,7 +298,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -295,7 +308,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "dtoa" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -320,10 +333,11 @@ dependencies = [ [[package]] name = "error-chain" -version = "0.12.0" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -340,19 +354,19 @@ name = "failure_derive" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "filetime" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -362,7 +376,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -386,20 +400,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "fsevent" -version = "0.2.17" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "fsevent-sys" -version = "0.1.6" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -423,7 +436,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -431,7 +444,7 @@ name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -448,7 +461,7 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -469,7 +482,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -487,17 +500,17 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.27" +version = "0.12.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -518,9 +531,9 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.27 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -546,7 +559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -554,7 +567,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -562,13 +575,13 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itoa" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -592,7 +605,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.51" +version = "0.2.54" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -617,7 +630,7 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -627,8 +640,8 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -646,7 +659,7 @@ name = "memchr" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -659,7 +672,7 @@ name = "mime" version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -686,9 +699,9 @@ name = "miniz_oxide_c_api" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -702,7 +715,7 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -734,18 +747,18 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.20 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -755,7 +768,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -766,16 +779,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "notify" -version = "4.0.10" +version = "4.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)", - "fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -792,7 +805,7 @@ name = "num_cpus" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -802,15 +815,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.20" +version = "0.10.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -820,13 +833,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.43" +version = "0.9.46" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -860,7 +873,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -873,7 +886,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -881,10 +894,10 @@ name = "paste-impl" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -945,12 +958,12 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.5" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -960,7 +973,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "proc-macro2" -version = "0.4.28" +version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -971,7 +984,7 @@ name = "publicsuffix" version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -996,7 +1009,7 @@ name = "quote" version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1005,7 +1018,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1017,12 +1030,12 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1069,10 +1082,10 @@ dependencies = [ [[package]] name = "rand_jitter" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1084,7 +1097,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1123,8 +1136,8 @@ name = "rbx_dom_weak" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1136,7 +1149,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1202,24 +1215,24 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.15" +version = "0.9.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "cookie_store 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.27 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1238,7 +1251,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1248,54 +1261,23 @@ name = "ritz_impl" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rlua" -version = "0.16.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rojo" -version = "0.5.0-alpha.9" -dependencies = [ - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.27 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.10 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.0.384 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)", - "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rustc-demangle" version = "0.1.14" @@ -1311,7 +1293,7 @@ dependencies = [ [[package]] name = "ryu" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1338,23 +1320,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "security-framework" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "security-framework-sys" -version = "0.2.3" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1363,7 +1343,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1373,20 +1353,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.90" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.90" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1394,9 +1374,9 @@ name = "serde_json" version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1404,9 +1384,9 @@ name = "serde_urlencoded" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1422,7 +1402,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1445,7 +1425,7 @@ name = "snax" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1465,10 +1445,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.32" +version = "0.15.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1478,9 +1458,9 @@ name = "synstructure" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1499,7 +1479,7 @@ version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1519,7 +1499,7 @@ name = "termion" version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1546,7 +1526,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1557,7 +1537,7 @@ version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1575,7 +1555,7 @@ name = "tokio-current-thread" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1585,7 +1565,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1594,7 +1574,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1604,7 +1584,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1622,7 +1602,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1631,7 +1611,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1646,7 +1626,7 @@ dependencies = [ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1660,7 +1640,7 @@ version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1701,7 +1681,7 @@ dependencies = [ [[package]] name = "unicase" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1754,7 +1734,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1787,7 +1767,7 @@ name = "want" version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1853,7 +1833,6 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] -"checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" @@ -1863,21 +1842,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cc 1.0.35 (registry+https://github.com/rust-lang/crates.io-index)" = "5e5f3fee5eeb60324c2781f1e41286bdee933850fff9b3c672587fed5ec58c83" +"checksum cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c56216487bb80eec9c4516337b2588a4f2a2290d72a1416d930e4dcdb0c90d" "checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum cookie 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1465f8134efa296b4c19db34d909637cb2bf0f7aaf21299e23e18fa29ac557cf" +"checksum cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "99be24cfcf40d56ed37fd11c2123be833959bbc5bddecb46e1c2e442e15fa3e0" "checksum cookie_store 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b0d2f2ecb21dce00e2453268370312978af9b8024020c7a37ae2cc6dbbe64685" -"checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980" -"checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa" +"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" +"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" @@ -1888,23 +1866,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" "checksum ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3b4c17619643c1252b5f690084b82639dd7fac141c57c8e77a00e0148132092c" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" -"checksum dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6d301140eb411af13d3115f9a562c85cc6b541ade9dfa314132244aaee7489dd" +"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" "checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" -"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" +"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" -"checksum filetime 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a2df5c1a8c4be27e7707789dc42ae65976e60b394afd293d1419ab915833e646" +"checksum filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2f8c63033fcba1f51ef744505b3cad42510432b904c062afa67ad7ece008429d" "checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum fsevent 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "c4bbbf71584aeed076100b5665ac14e3d85eeb31fdbb45fbd41ef9a682b5ec05" -"checksum fsevent-sys 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "1a772d36c338d07a032d5375a36f15f9a7043bf0cb8ce7cee658e037c6032874" +"checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" +"checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "62941eff9507c8177d448bd83a44d9b9760856e184081d8cd79ba9f03dd24981" +"checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "85ab6286db06040ddefb71641b50017c06874614001a134b423783e2db2920bd" @@ -1912,18 +1890,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.12.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4f2777434f26af6e4ce4fdcdccd3bed9d861d11e87bcbe72c0f51ddaca8ff848" +"checksum hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)" = "e8e4606fed1c162e3a63d408c07584429f49a4f34c7176cb6cbee60e78f2372c" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" -"checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b" +"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.51 (registry+https://github.com/rust-lang/crates.io-index)" = "bedcc7a809076656486ffe045abeeac163da1b558e963a31e29fbfbeba916917" +"checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" @@ -1939,16 +1917,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2" +"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum notify 4.0.10 (registry+https://github.com/rust-lang/crates.io-index)" = "abb1581693e44d8a0ec347ef12289625063f52a1dddc3f3c9befd5fc59e88943" +"checksum notify 4.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ceb1a496a81dd6125f68ce772b41b83efe89a54d21768ed6d0c33c95832604e6" "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" "checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" -"checksum openssl 0.10.20 (registry+https://github.com/rust-lang/crates.io-index)" = "5a0d6b781aac4ac1bd6cafe2a2f0ad8c16ae8e1dd5184822a16c50139f8838d9" +"checksum openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)" = "a51f452b82d622fc8dd973d7266e9055ac64af25b957d9ced3989142dc61cb6b" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.43 (registry+https://github.com/rust-lang/crates.io-index)" = "33c86834957dd5b915623e94f2f4ab2c70dd8f6b70679824155d5ae21dbd495d" +"checksum openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)" = "05636e06b4f8762d4b81d24a351f3966f38bd25ccbcfd235606c91fdb82cc60f" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" @@ -1962,9 +1940,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" -"checksum proc-macro-hack 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6a9bed9ebc40cf53e3a76d7486c54d05002eae6485b2711ab9104476fb2eb8bc" +"checksum proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0c1dd4172a1e1f96f709341418f49b11ea6c2d95d53dca08c0f74cbd332d9cf3" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" -"checksum proc-macro2 0.4.28 (registry+https://github.com/rust-lang/crates.io-index)" = "ba92c84f814b3f9a44c5cfca7d2ad77fa10710867d2bbb1b3d175ab5f47daa12" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5afecba86dcf1e4fd610246f89899d1924fe12e1e89f555eb7c7f710f3c5ad1d" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" @@ -1976,7 +1954,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832" +"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" @@ -1990,22 +1968,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" "checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.15 (registry+https://github.com/rust-lang/crates.io-index)" = "943b9f85622f53bcf71721e0996f23688e3942e51fc33766c2e24a959316767b" +"checksum reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddcfd2c13c6af0f9c45a1086be3b9c68af79e4430b42790759e2d34cce2a6c60" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" -"checksum rlua 0.16.2 (registry+https://github.com/rust-lang/crates.io-index)" = "51acb42c134a6568911a2aef2cea5feb80503804cc8986b903983ebfb1342a2c" +"checksum rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62fc0e980c94fe9ef795b1bb3874649c8c6e9bb67d3b90d48380ba24c69c23ea" "checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7" +"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" -"checksum security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfab8dda0e7a327c696d893df9ffa19cadc4bd195797997f5223cf5831beaf05" -"checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc" +"checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" +"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "aa5f7c20820475babd2c077c3ab5f8c77a31c15e16ea38687b4c02d3e48680f4" -"checksum serde_derive 1.0.90 (registry+https://github.com/rust-lang/crates.io-index)" = "58fc82bec244f168b23d1963b45c8bf5726e9a15a9d146a067f9081aeed2de79" +"checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd" +"checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" @@ -2016,7 +1994,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum syn 0.15.32 (registry+https://github.com/rust-lang/crates.io-index)" = "846620ec526c1599c070eff393bfeeeb88a93afa2513fc3b49f1fea84cf7b0ed" +"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" @@ -2039,7 +2017,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" -"checksum unicase 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41d17211f887da8e4a70a45b9536f26fc5de166b81e2d5d80de4a17fd22553bd" +"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" From 5a147fccc2eecfe4212d62a1a7ceb7d86cbc060c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 13 May 2019 15:28:40 -0700 Subject: [PATCH 0504/1504] Add rbx-dom as Git submodule to plugin --- .gitmodules | 5 ++++- plugin/modules/rbx-dom | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) create mode 160000 plugin/modules/rbx-dom diff --git a/.gitmodules b/.gitmodules index 741d18ac..a9420e24 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,4 +12,7 @@ url = https://github.com/LPGhatguy/roblox-lua-promise.git [submodule "plugin/modules/t"] path = plugin/modules/t - url = https://github.com/osyrisrblx/t.git \ No newline at end of file + url = https://github.com/osyrisrblx/t.git +[submodule "plugin/modules/rbx-dom"] + path = plugin/modules/rbx-dom + url = http://github.com/LPGhatguy/rbx-dom diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom new file mode 160000 index 00000000..50a640c5 --- /dev/null +++ b/plugin/modules/rbx-dom @@ -0,0 +1 @@ +Subproject commit 50a640c51a667441d4c63f9ff4ae41ad331e5ca6 From 19135bfaf49a93c7b30dc8684c1a5f10bace0fe3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 13 May 2019 17:28:08 -0700 Subject: [PATCH 0505/1504] Add RbxDom library as piece of plugin --- plugin/default.project.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugin/default.project.json b/plugin/default.project.json index 0e84f4f9..791edc0e 100644 --- a/plugin/default.project.json +++ b/plugin/default.project.json @@ -13,6 +13,9 @@ }, "t": { "$path": "modules/t/lib" + }, + "RbxDom": { + "$path": "modules/rbx-dom/rbx_dom_lua/src" } } } \ No newline at end of file From fef85877e61f41fd9ef12f4cede87712a18efdf9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 13 May 2019 17:28:31 -0700 Subject: [PATCH 0506/1504] Add safeguards against accidentally committing model or place files --- .gitignore | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index b11f390d..816129e7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,8 @@ /target /scratch-project **/*.rs.bk -/server/failed-snapshots/ \ No newline at end of file +/server/failed-snapshots/ +/*.rbxm +/*.rbxmx +/*.rbxl +/*.rbxlx \ No newline at end of file From d377e107718c42795cba7dc212e0a0973a771d3c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 13 May 2019 17:35:55 -0700 Subject: [PATCH 0507/1504] Update rbx-dom --- plugin/modules/rbx-dom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index 50a640c5..d79de039 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit 50a640c51a667441d4c63f9ff4ae41ad331e5ca6 +Subproject commit d79de0399426fa54cfb9b39d1d579ea6e6e7fe20 From efc569f6ed2037f3afe4f9882bf71a2e615943c6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 14 May 2019 14:22:44 -0700 Subject: [PATCH 0508/1504] Plugin: Update rbx-dom --- plugin/modules/rbx-dom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index d79de039..d2cafc62 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit d79de0399426fa54cfb9b39d1d579ea6e6e7fe20 +Subproject commit d2cafc629217af4be174fbfa69b200c7ff0b9d5d From 28ea625b01f7cdf73ed95a4e13ca21ffcbbaae6c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 14 May 2019 14:22:55 -0700 Subject: [PATCH 0509/1504] Plugin: Port reconciler to use rbx_dom_lua --- plugin/src/Reconciler.lua | 10 ++++- plugin/src/rojoValueToRobloxValue.lua | 53 ++++++++++++--------------- plugin/src/setCanonicalProperty.lua | 34 ++++------------- 3 files changed, 39 insertions(+), 58 deletions(-) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 58eb4182..69a24916 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -6,6 +6,12 @@ local setCanonicalProperty = require(script.Parent.setCanonicalProperty) local rojoValueToRobloxValue = require(script.Parent.rojoValueToRobloxValue) local Types = require(script.Parent.Types) +local function setParent(instance, newParent) + pcall(function() + instance.Parent = newParent + end) +end + local Reconciler = {} Reconciler.__index = Reconciler @@ -117,7 +123,7 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) -- Some instances, like services, don't like having their Parent -- property poked, even if we're setting it to the same value. - setCanonicalProperty(instance, "Parent", parent) + setParent(instance, parent) end return instance @@ -154,7 +160,7 @@ function Reconciler:__reify(virtualInstancesById, id, parent) self:__reify(virtualInstancesById, childId, instance) end - setCanonicalProperty(instance, "Parent", parent) + setParent(instance, parent) self.instanceMap:insert(id, instance) return instance diff --git a/plugin/src/rojoValueToRobloxValue.lua b/plugin/src/rojoValueToRobloxValue.lua index b5855b2a..94c57664 100644 --- a/plugin/src/rojoValueToRobloxValue.lua +++ b/plugin/src/rojoValueToRobloxValue.lua @@ -1,38 +1,33 @@ -local primitiveTypes = { - Bool = true, - Enum = true, - Float32 = true, - Float64 = true, - Int32 = true, - Int64 = true, - String = true, -} - -local directConstructors = { - CFrame = CFrame.new, - Color3 = Color3.new, - Color3uint8 = Color3.fromRGB, - Rect = Rect.new, - UDim = UDim.new, - UDim2 = UDim2.new, - Vector2 = Vector2.new, - Vector2int16 = Vector2int16.new, - Vector3 = Vector3.new, - Vector3int16 = Vector3int16.new, -} +local RbxDom = require(script:FindFirstAncestor("Rojo").RbxDom) local function rojoValueToRobloxValue(value) - if primitiveTypes[value.Type] then - return value.Value + -- TODO: Manually decode this value by looking up its GUID The Rojo server + -- doesn't give us valid ref values yet, so this isn't important yet. + if value.Type == "Ref" then + return nil end - local constructor = directConstructors[value.Type] - if constructor ~= nil then - return constructor(unpack(value.Value)) + -- TODO: Remove this once rbx_dom_weak and rbx_dom_lua agree on encoding + if value.Type == "BinaryString" then + local actualValue = "" + + for i = 1, #value.Value do + actualValue = actualValue .. string.char(i) + end + + value = { + Type = "BinaryString", + Value = actualValue, + } end - local errorMessage = ("The Rojo plugin doesn't know how to handle values of type %q yet!"):format(tostring(value.Type)) - error(errorMessage) + local success, decodedValue = RbxDom.EncodedValue.decode(value) + + if not success then + error(decodedValue, 2) + end + + return decodedValue end return rojoValueToRobloxValue \ No newline at end of file diff --git a/plugin/src/setCanonicalProperty.lua b/plugin/src/setCanonicalProperty.lua index 6e5eacd6..fabbd733 100644 --- a/plugin/src/setCanonicalProperty.lua +++ b/plugin/src/setCanonicalProperty.lua @@ -1,33 +1,17 @@ +local RbxDom = require(script:FindFirstAncestor("Rojo").RbxDom) + local Logging = require(script.Parent.Logging) --[[ Attempts to set a property on the given instance. - - This method deals in terms of what Rojo calls 'canonical properties', which - don't necessarily exist either in serialization or in Lua-reflected APIs, - but may be present in the API dump. - - Ideally, canonical properties map 1:1 with properties we can assign, but in - some cases like LocalizationTable contents and CollectionService tags, we - have to read/write properties a little differently. ]] local function setCanonicalProperty(instance, key, value) - -- The 'Contents' property of LocalizationTable isn't directly exposed, but - -- has corresponding (deprecated) getters and setters. - if instance.ClassName == "LocalizationTable" and key == "Contents" then - instance:SetContents(value) - return - end - - -- Temporary workaround for fixing issue #141 in this specific case. - if instance.ClassName == "Lighting" and key == "Technology" then - return + if not RbxDom.CanonicalProperty.isScriptable(instance.ClassName, key) then + return false end -- If we don't have permissions to access this value at all, we can skip it. - local readSuccess, existingValue = pcall(function() - return instance[key] - end) + local readSuccess, existingValue = RbxDom.CanonicalProperty.read(instance, key) if not readSuccess then -- An error will be thrown if there was a permission issue or if the @@ -35,17 +19,13 @@ local function setCanonicalProperty(instance, key, value) -- because it's probably their fault. if existingValue:find("lacking permission") then Logging.trace("Permission error reading property %s on class %s", tostring(key), instance.ClassName) - return + return false else error(("Invalid property %s on class %s: %s"):format(tostring(key), instance.ClassName, existingValue), 2) end end - local writeSuccess, err = pcall(function() - if existingValue ~= value then - instance[key] = value - end - end) + local writeSuccess, err = RbxDom.CanonicalProperty.write(instance, key, value) if not writeSuccess then error(("Cannot set property %s on class %s: %s"):format(tostring(key), instance.ClassName, err), 2) From 8395782a2ee465d26afb6fd21912ba1cac5d0382 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 14 May 2019 17:55:18 -0700 Subject: [PATCH 0510/1504] Use Display instead of Debug for rbx_xml errors now --- server/src/rbx_snapshot.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 9cf875ce..8e9ba51d 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -153,7 +153,7 @@ impl fmt::Display for SnapshotError { write!(output, "Malformed .model.json model: {} in path {}", inner, path.display()) }, SnapshotError::XmlModelDecodeError { inner, path } => { - write!(output, "Malformed rbxmx model: {:?} in path {}", inner, path.display()) + write!(output, "Malformed rbxmx model: {} in path {}", inner, path.display()) }, SnapshotError::BinaryModelDecodeError { inner, path } => { write!(output, "Malformed rbxm model: {:?} in path {}", inner, path.display()) From a8ff6d7e6e4b3ec9cebbcdbc8af53ad350cfabcf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 14 May 2019 18:23:01 -0700 Subject: [PATCH 0511/1504] Update dependencies --- Cargo.lock | 158 +++++++++++++++++++++++----------------------- server/Cargo.toml | 4 +- 2 files changed, 82 insertions(+), 80 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d6752fba..5a1efa5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,34 +1,5 @@ -[root] -name = "rojo" -version = "0.5.0-alpha.9" -dependencies = [ - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.0.384 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)", - "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. [[package]] name = "adler32" version = "1.0.3" @@ -75,15 +46,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -91,7 +61,7 @@ name = "backtrace-sys" version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -146,12 +116,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -231,7 +201,7 @@ name = "crc32fast" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -249,7 +219,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -269,7 +239,7 @@ name = "crossbeam-utils" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -316,7 +286,7 @@ name = "encoding_rs" version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -336,7 +306,7 @@ name = "error-chain" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -345,7 +315,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -357,7 +327,7 @@ dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -365,7 +335,7 @@ name = "filetime" version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -515,13 +485,13 @@ dependencies = [ "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -622,7 +592,7 @@ name = "log" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -640,7 +610,7 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -699,7 +669,7 @@ name = "miniz_oxide_c_api" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -767,7 +737,7 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -819,7 +789,7 @@ version = "0.10.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", @@ -837,7 +807,7 @@ version = "0.9.46" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1128,14 +1098,15 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_dom_weak" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1143,24 +1114,24 @@ dependencies = [ [[package]] name = "rbx_reflection" -version = "3.0.384" +version = "3.1.384" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_xml" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.0.384 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.1.384 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1236,11 +1207,11 @@ dependencies = [ "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1273,11 +1244,42 @@ version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rojo" +version = "0.5.0-alpha.9" +dependencies = [ + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.1.384 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)", + "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-demangle" version = "0.1.14" @@ -1455,7 +1457,7 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1478,7 +1480,7 @@ name = "tempfile" version = "3.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1533,7 +1535,7 @@ dependencies = [ [[package]] name = "tokio" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1546,7 +1548,7 @@ dependencies = [ "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1636,7 +1638,7 @@ dependencies = [ [[package]] name = "tokio-timer" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1663,7 +1665,7 @@ name = "try_from" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1839,7 +1841,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f106c02a3604afcdc0df5d36cc47b44b55917dbaf3d808f71c163a0ddba64637" +"checksum backtrace 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "56acb7e9c23cb8c3a1f51713695c552a81ee667d9fd060d1ef407908480b7174" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" @@ -1848,8 +1850,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cc 1.0.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a0c56216487bb80eec9c4516337b2588a4f2a2290d72a1416d930e4dcdb0c90d" -"checksum cfg-if 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "11d43355396e872eefb45ce6342e4374ed7bc2b3a502d1b28e36d6e23c05d1f4" +"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" +"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "99be24cfcf40d56ed37fd11c2123be833959bbc5bddecb46e1c2e442e15fa3e0" @@ -1959,9 +1961,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147f236284747ac1b4643476265dd36b402877d97adb7cbd0fafc1d247de0a5" -"checksum rbx_dom_weak 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d9af92582e8ac283fce50fe223d741e8f7f865a13ec99fdecc38cfb431de3ccf" -"checksum rbx_reflection 3.0.384 (registry+https://github.com/rust-lang/crates.io-index)" = "8bf0e45a2f1abeddf8096591c1081151e9114f4426fed97cab1d123b3fe4010f" -"checksum rbx_xml 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1142b88066f633c05a6589b8c19b69f04e9474dc9d1b659df6fc523ca8712ead" +"checksum rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9582ea95ea28d99bea189b90eab04a34ab6e9d04f295ccb46eb997b87754030" +"checksum rbx_reflection 3.1.384 (registry+https://github.com/rust-lang/crates.io-index)" = "1209361806b9238226f1f8427bab9b5171ec13b3bf2dffdd2f97a96bb641164c" +"checksum rbx_xml 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3f8e8b5e991ded26e6955d4b8db5ff74a07ad6752785e2991dc9b417a0c1594" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" @@ -1995,7 +1997,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" -"checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015" +"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" @@ -2003,7 +2005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)" = "cec6c34409089be085de9403ba2010b80e36938c9ca992c4f67f407bb13db0b1" +"checksum tokio 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "94a1f9396aec29d31bb16c24d155cfa144d1af91c40740125db3131bdaf76da8" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" "checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" @@ -2011,7 +2013,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2f843ffdf8d6e1f90bddd48da43f99ab071660cd92b7ec560ef3cdfd7a409a" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" "checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2" -"checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6" +"checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" "checksum tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "350c9edade9830dc185ae48ba45667a445ab59f6167ef6d0254ec9d2430d9dd3" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" diff --git a/server/Cargo.toml b/server/Cargo.toml index 27a7672a..9fbfa972 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -30,8 +30,8 @@ log = "0.4" maplit = "1.0.1" notify = "4.0" rbx_binary = "0.4.0" -rbx_dom_weak = "1.6.0" -rbx_xml = "0.7.0" +rbx_dom_weak = "1.7.0" +rbx_xml = "0.8.0" rbx_reflection = "3.0.384" regex = "1.0" reqwest = "0.9.5" From f16474815cb9ea2ee25ebe5698e51c4abab2a9bd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 15 May 2019 11:19:05 -0700 Subject: [PATCH 0512/1504] plugin: update rbx-dom --- plugin/modules/rbx-dom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index d2cafc62..a983cdf9 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit d2cafc629217af4be174fbfa69b200c7ff0b9d5d +Subproject commit a983cdf94422701c3861255a6ce51dd7994cd716 From 91780f236eb933e6cadd83896562ef0d56715bf7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 16 May 2019 17:58:19 -0700 Subject: [PATCH 0513/1504] Update dependencies --- CHANGELOG.md | 7 ++++--- Cargo.lock | 6 +++--- server/Cargo.toml | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86cabe8f..e7ac7e04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,16 +2,17 @@ ## [Unreleased] * Upgraded significant dependencies: - * rbx_dom_weak 1.6.0 + * rbx_dom_weak 1.7.0 * `Content` properties can now be specified in projects and model files as strings * Added support for `BrickColor`, but with no handy conversions yet * rbx_reflection 3.0.384 * Updated reflection database to client release 384 * Adds support for new enum variants like `Lighting.Technology` as `"ShadowMap"` - * rbx_xml 0.7.0 + * rbx_xml 0.9.0 * Performance improvements dealing with model/place files due to smaller error type * Fixed serializing empty `Content` properties - * Improved content compatibility utilizing the reflection database + * Fixed serializing infinite and NaN values + * Improved content compatibility utilizing reflection database * Added support for implicit property values in JSON model files ([#154](https://github.com/LPGhatguy/rojo/pull/154)) ## [0.5.0 Alpha 9](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.9) (April 4, 2019) diff --git a/Cargo.lock b/Cargo.lock index 5a1efa5c..e21cec69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1125,7 +1125,7 @@ dependencies = [ [[package]] name = "rbx_xml" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1268,7 +1268,7 @@ dependencies = [ "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 3.1.384 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1963,7 +1963,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147f236284747ac1b4643476265dd36b402877d97adb7cbd0fafc1d247de0a5" "checksum rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9582ea95ea28d99bea189b90eab04a34ab6e9d04f295ccb46eb997b87754030" "checksum rbx_reflection 3.1.384 (registry+https://github.com/rust-lang/crates.io-index)" = "1209361806b9238226f1f8427bab9b5171ec13b3bf2dffdd2f97a96bb641164c" -"checksum rbx_xml 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e3f8e8b5e991ded26e6955d4b8db5ff74a07ad6752785e2991dc9b417a0c1594" +"checksum rbx_xml 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb23d19c983457fa6c65803190a23b2c4b9d08290f3431528adb9b74ab3488da" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" diff --git a/server/Cargo.toml b/server/Cargo.toml index 9fbfa972..f4b65124 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -31,7 +31,7 @@ maplit = "1.0.1" notify = "4.0" rbx_binary = "0.4.0" rbx_dom_weak = "1.7.0" -rbx_xml = "0.8.0" +rbx_xml = "0.9.0" rbx_reflection = "3.0.384" regex = "1.0" reqwest = "0.9.5" From 8f6dda5cd3ccf9fa844159c7c438633660606d87 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 16 May 2019 17:58:32 -0700 Subject: [PATCH 0514/1504] Use rbx_xml 0.9.0's config to read unknown properties --- server/src/commands/build.rs | 9 +++++++-- server/src/rbx_snapshot.rs | 5 ++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index ffb054e0..716ed717 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -74,6 +74,11 @@ impl_from!(BuildError { SnapshotError => SnapshotError, }); +fn xml_encode_config() -> rbx_xml::EncodeOptions { + rbx_xml::EncodeOptions::new() + .property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown) +} + pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let output_kind = options.output_kind .or_else(|| detect_output_kind(options)) @@ -100,7 +105,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { // descendants. let root_id = tree.get_root_id(); - rbx_xml::to_writer_default(&mut file, &tree, &[root_id])?; + rbx_xml::to_writer(&mut file, &tree, &[root_id], xml_encode_config())?; }, OutputKind::Rbxlx => { // Place files don't contain an entry for the DataModel, but our @@ -108,7 +113,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let root_id = tree.get_root_id(); let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); - rbx_xml::to_writer_default(&mut file, &tree, top_level_ids)?; + rbx_xml::to_writer(&mut file, &tree, top_level_ids, xml_encode_config())?; }, OutputKind::Rbxm => { let root_id = tree.get_root_id(); diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 8e9ba51d..7be71d3b 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -653,7 +653,10 @@ fn snapshot_xml_model_file<'source>( .file_stem().expect("Could not extract file stem") .to_str().expect("Could not convert path to UTF-8"); - let temp_tree = rbx_xml::from_reader_default(file.contents.as_slice()) + let options = rbx_xml::DecodeOptions::new() + .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); + + let temp_tree = rbx_xml::from_reader(file.contents.as_slice(), options) .map_err(|inner| SnapshotError::XmlModelDecodeError { inner, path: file.path.clone(), From 9b8a6b1168084b2573fde9b9314c8259cdee8f53 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 16 May 2019 18:03:11 -0700 Subject: [PATCH 0515/1504] Add terrain test project --- test-projects/terrain/Terrain.rbxmx | 411 +++++++++++++++++++++ test-projects/terrain/default.project.json | 13 + 2 files changed, 424 insertions(+) create mode 100644 test-projects/terrain/Terrain.rbxmx create mode 100644 test-projects/terrain/default.project.json diff --git a/test-projects/terrain/Terrain.rbxmx b/test-projects/terrain/Terrain.rbxmx new file mode 100644 index 00000000..b8474e28 --- /dev/null +++ b/test-projects/terrain/Terrain.rbxmx @@ -0,0 +1,411 @@ + + true + null + nil + + + true + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 4 + 0 + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4288914085 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + true + false + 256 + + Terrain + + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + + -0.5 + 0.5 + 3 + 0 + 0 + + 0 + 0 + 0 + + + 0.0470588244 + 0.329411775 + 0.360784322 + + 1 + 0.300000012 + 0.150000006 + 10 + + 2044 + 252 + 2044 + + + + \ No newline at end of file diff --git a/test-projects/terrain/default.project.json b/test-projects/terrain/default.project.json new file mode 100644 index 00000000..d62a6cd4 --- /dev/null +++ b/test-projects/terrain/default.project.json @@ -0,0 +1,13 @@ +{ + "name": "terrain", + "tree": { + "$className": "DataModel", + "Workspace": { + "$className": "Workspace", + + "Terrain": { + "$path": "Terrain.rbxmx" + } + } + } +} \ No newline at end of file From 1e130971269367da2f58c8a78b464cfcd26650af Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 16 May 2019 18:33:37 -0700 Subject: [PATCH 0516/1504] plugin: update rbx-dom --- plugin/modules/rbx-dom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index a983cdf9..ac129152 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit a983cdf94422701c3861255a6ce51dd7994cd716 +Subproject commit ac129152f250bf6a1ad51a1cbc9f9315130c8fbb From ae12ffdefb8e8e26dd0f8731c86d19644e02b61a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 16 May 2019 18:45:00 -0700 Subject: [PATCH 0517/1504] Work around Roact bug --- plugin/src/Components/App.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 79436972..ef561c85 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -80,7 +80,8 @@ function App:init() end function App:render() - local children + -- FIXME: https://github.com/Roblox/roact/issues/209 + local children = {} if self.state.sessionStatus == SessionStatus.Connected then children = { From 9ca2ed2c934e2f93b3440f1982d5e6b549fb5097 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 16 May 2019 18:45:35 -0700 Subject: [PATCH 0518/1504] plugin: upgrade Roact --- plugin/modules/roact | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/modules/roact b/plugin/modules/roact index 41af74df..2fb60ea6 160000 --- a/plugin/modules/roact +++ b/plugin/modules/roact @@ -1 +1 @@ -Subproject commit 41af74df730723ed39c02f54cae7c6c97c6c5d9c +Subproject commit 2fb60ea648caafb155f5f0363cec7a8149c8e8fc From d4704a02c55c1a32363ce520fe0974f3907dcc3f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 29 May 2019 13:15:22 -0700 Subject: [PATCH 0519/1504] Upgrade dependencies --- Cargo.lock | 210 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 121 insertions(+), 89 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e21cec69..771be6ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,25 +34,25 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.16" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -62,7 +62,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -99,6 +99,7 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -148,7 +149,7 @@ dependencies = [ [[package]] name = "cookie" -version = "0.11.1" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -157,17 +158,15 @@ dependencies = [ [[package]] name = "cookie_store" -version = "0.5.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -180,7 +179,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -281,6 +280,11 @@ name = "dtoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "either" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "encoding_rs" version = "0.8.17" @@ -306,7 +310,7 @@ name = "error-chain" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -315,7 +319,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -336,7 +340,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -346,7 +350,7 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -382,7 +386,7 @@ name = "fsevent-sys" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -425,7 +429,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "h2" -version = "0.1.18" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -455,6 +459,17 @@ dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "http-body" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "httparse" version = "1.3.3" @@ -470,14 +485,15 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.28" +version = "0.12.29" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -486,6 +502,7 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -502,7 +519,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.29 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -529,7 +546,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -537,7 +554,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -545,7 +562,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -575,7 +592,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.54" +version = "0.2.55" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -600,7 +617,7 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -611,7 +628,7 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -629,7 +646,7 @@ name = "memchr" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -671,21 +688,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "mio" -version = "0.6.16" +version = "0.6.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -700,7 +716,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -721,15 +737,15 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -738,7 +754,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -749,7 +765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "notify" -version = "4.0.11" +version = "4.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -758,8 +774,8 @@ dependencies = [ "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -767,15 +783,18 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.6" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "num_cpus" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -785,15 +804,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.22" +version = "0.10.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -803,12 +822,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.46" +version = "0.9.47" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -843,7 +862,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -988,7 +1007,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -999,8 +1018,8 @@ name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1017,7 +1036,7 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1055,7 +1074,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1067,7 +1086,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1078,7 +1097,7 @@ name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1186,18 +1205,18 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.16" +version = "0.9.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie_store 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.29 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1245,8 +1264,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1258,11 +1277,11 @@ dependencies = [ "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1270,12 +1289,12 @@ dependencies = [ "rbx_reflection 3.1.384 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1327,7 +1346,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1477,11 +1496,11 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.0.7" +version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1501,7 +1520,7 @@ name = "termion" version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1528,7 +1547,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1540,7 +1559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1552,6 +1571,16 @@ dependencies = [ "tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-buf" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-current-thread" version = "0.1.6" @@ -1589,7 +1618,7 @@ dependencies = [ "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1615,7 +1644,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1840,8 +1869,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" -"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799" -"checksum backtrace 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "56acb7e9c23cb8c3a1f51713695c552a81ee667d9fd060d1ef407908480b7174" +"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" +"checksum backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)" = "1a13fc43f04daf08ab4f71e3d27e1fc27fc437d3e95ac0063a796d92fb40f39b" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" @@ -1854,8 +1883,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum cookie 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "99be24cfcf40d56ed37fd11c2123be833959bbc5bddecb46e1c2e442e15fa3e0" -"checksum cookie_store 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b0d2f2ecb21dce00e2453268370312978af9b8024020c7a37ae2cc6dbbe64685" +"checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" +"checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" @@ -1869,6 +1898,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3b4c17619643c1252b5f690084b82639dd7fac141c57c8e77a00e0148132092c" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" +"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" "checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" @@ -1887,12 +1917,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum h2 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "85ab6286db06040ddefb71641b50017c06874614001a134b423783e2db2920bd" +"checksum h2 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "2b53def7bb0253af7718036fe9338c15defd209136819464384f3a553e07481b" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" "checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" +"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.12.28 (registry+https://github.com/rust-lang/crates.io-index)" = "e8e4606fed1c162e3a63d408c07584429f49a4f34c7176cb6cbee60e78f2372c" +"checksum hyper 0.12.29 (registry+https://github.com/rust-lang/crates.io-index)" = "e2cd6adf83b3347d36e271f030621a8cf95fd1fd0760546b9fc5a24a0f1447c7" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" @@ -1903,7 +1934,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.54 (registry+https://github.com/rust-lang/crates.io-index)" = "c6785aa7dd976f5fbf3b71cfd9cd49d7f783c1ff565a858d71031c6c313aa5c6" +"checksum libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "42914d39aad277d9e176efbdad68acb1d5443ab65afe0e0e4f0d49352a950880" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" @@ -1916,19 +1947,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" "checksum miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c468f2369f07d651a5d0bb2c9079f8488a66d5466efe42d0c5c6466edcb7f71e" "checksum miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fe927a42e3807ef71defb191dc87d4e24479b221e67015fe38ae2b7b447bab" -"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432" +"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum notify 4.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ceb1a496a81dd6125f68ce772b41b83efe89a54d21768ed6d0c33c95832604e6" -"checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1" +"checksum notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3572d71f13ea8ed41867accd971fd564aa75934cf7a1fae03ddb8c74a8a49943" +"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" "checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" -"checksum openssl 0.10.22 (registry+https://github.com/rust-lang/crates.io-index)" = "a51f452b82d622fc8dd973d7266e9055ac64af25b957d9ced3989142dc61cb6b" +"checksum openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)" = "97c140cbb82f3b3468193dd14c1b88def39f341f68257f8a7fe8ed9ed3f628a5" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.46 (registry+https://github.com/rust-lang/crates.io-index)" = "05636e06b4f8762d4b81d24a351f3966f38bd25ccbcfd235606c91fdb82cc60f" +"checksum openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)" = "75bdd6dbbb4958d38e47a1d2348847ad1eb4dc205dc5d37473ae504391865acc" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" @@ -1970,7 +2001,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" "checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddcfd2c13c6af0f9c45a1086be3b9c68af79e4430b42790759e2d34cce2a6c60" +"checksum reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e57803405f8ea0eb041c1567dac36127e0c8caa1251c843cb03d43fd767b3d50" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62fc0e980c94fe9ef795b1bb3874649c8c6e9bb67d3b90d48380ba24c69c23ea" @@ -1999,13 +2030,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a" +"checksum tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dc4738f2e68ed2855de5ac9cdbe05c9216773ecde4739b2f095002ab03a13ef" "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" "checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tokio 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "94a1f9396aec29d31bb16c24d155cfa144d1af91c40740125db3131bdaf76da8" +"checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" "checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" From 0f9f1782ae852e8676addf57ffc09fb8f9ea6b76 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 29 May 2019 13:24:06 -0700 Subject: [PATCH 0520/1504] 0.5.0-alpha.10 --- CHANGELOG.md | 22 ++++++++++------------ Cargo.lock | 2 +- docs/installation.md | 4 ++-- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 5 files changed, 15 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7ac7e04..a79dd223 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,17 @@ # Rojo Changelog ## [Unreleased] -* Upgraded significant dependencies: - * rbx_dom_weak 1.7.0 - * `Content` properties can now be specified in projects and model files as strings - * Added support for `BrickColor`, but with no handy conversions yet - * rbx_reflection 3.0.384 - * Updated reflection database to client release 384 - * Adds support for new enum variants like `Lighting.Technology` as `"ShadowMap"` - * rbx_xml 0.9.0 - * Performance improvements dealing with model/place files due to smaller error type - * Fixed serializing empty `Content` properties - * Fixed serializing infinite and NaN values - * Improved content compatibility utilizing reflection database + +## [0.5.0 Alpha 10](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.10) (May 29, 2019) * Added support for implicit property values in JSON model files ([#154](https://github.com/LPGhatguy/rojo/pull/154)) +* `Content` propertyes can now be specified in projects and model files as regular string literals. +* Added support for `BrickColor` properties. +* Added support for properties added in client release 384, like `Lighting.Technology` being set to `"ShadowMap"`. +* Improved performance when working with XML models and places +* Fixed serializing empty `Content` properties as XML +* Fixed serializing infinite and NaN floating point properties in XML +* Improved compatibility with XML models +* Plugin should now be able to live-sync more properties, and ignore ones it can't, like `Lighting.Technology`. ## [0.5.0 Alpha 9](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.9) (April 4, 2019) * Changed `rojo build` to use buffered I/O, which can make it up to 2x faster in some cases. diff --git a/Cargo.lock b/Cargo.lock index 771be6ba..c9cca0ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1270,7 +1270,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0-alpha.9" +version = "0.5.0-alpha.10" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/docs/installation.md b/docs/installation.md index 4823de28..8c88423d 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -25,7 +25,7 @@ If you have Rust installed, the easiest way to get Rojo is with Cargo! To install the latest 0.5.0 alpha, use: ```sh -cargo install rojo --version 0.5.0-alpha.9 +cargo install rojo --version 0.5.0-alpha.10 ``` ## Installing the Plugin @@ -42,4 +42,4 @@ Download the attached `rbxm` file and put it into your Roblox Studio plugins fol Visit [Rojo's Roblox.com Plugin page](https://www.roblox.com/library/1997686364/Rojo-0-5-0-alpha-3) in Roblox Studio and press **Install**. ## Visual Studio Code Extension -If you use Visual Studio Code, you can install [Evaera's unofficial Rojo extension](https://marketplace.visualstudio.com/items?itemName=evaera.vscode-rojo), which will install both halves of Rojo for you. It even has a nifty UI to sync files and start/stop the Rojo server! +If you use Visual Studio Code, you can install [Evaera's unofficial Rojo extension](https://marketplace.visualstudio.com/items?itemName=evaera.vscode-rojo), which will install both halves of Rojo for you. It even has a nifty UI to sync files and start/stop the Rojo server! \ No newline at end of file diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 55703420..9633a1a7 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0, "-alpha.9"}, + version = {0, 5, 0, "-alpha.10"}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/server/Cargo.toml b/server/Cargo.toml index f4b65124..e5967c0c 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0-alpha.9" +version = "0.5.0-alpha.10" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From ce3a409997cb21ed49cef138469d032e0d3bc857 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 29 May 2019 13:38:36 -0700 Subject: [PATCH 0521/1504] Undo 0.5.0-alpha.10 release due to regression --- CHANGELOG.md | 2 -- docs/installation.md | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a79dd223..b1ed405a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,6 @@ # Rojo Changelog ## [Unreleased] - -## [0.5.0 Alpha 10](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.10) (May 29, 2019) * Added support for implicit property values in JSON model files ([#154](https://github.com/LPGhatguy/rojo/pull/154)) * `Content` propertyes can now be specified in projects and model files as regular string literals. * Added support for `BrickColor` properties. diff --git a/docs/installation.md b/docs/installation.md index 8c88423d..6794ff5f 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -25,7 +25,7 @@ If you have Rust installed, the easiest way to get Rojo is with Cargo! To install the latest 0.5.0 alpha, use: ```sh -cargo install rojo --version 0.5.0-alpha.10 +cargo install rojo --version 0.5.0-alpha.9 ``` ## Installing the Plugin From 420627d892072ad85010ba7c63a14c1329ff0095 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 29 May 2019 14:07:15 -0700 Subject: [PATCH 0522/1504] 0.5.0-alpha.11 --- CHANGELOG.md | 5 +++++ Cargo.lock | 8 ++++---- docs/installation.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b1ed405a..3ec32f81 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## [Unreleased] + +## [0.5.0 Alpha 11](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) * Added support for implicit property values in JSON model files ([#154](https://github.com/LPGhatguy/rojo/pull/154)) * `Content` propertyes can now be specified in projects and model files as regular string literals. * Added support for `BrickColor` properties. @@ -11,6 +13,9 @@ * Improved compatibility with XML models * Plugin should now be able to live-sync more properties, and ignore ones it can't, like `Lighting.Technology`. +## 0.5.0 Alpha 10 +* This release was a dud due to [issue #176](https://github.com/LPGhatguy/rojo/issues/176) and was rolled back. + ## [0.5.0 Alpha 9](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.9) (April 4, 2019) * Changed `rojo build` to use buffered I/O, which can make it up to 2x faster in some cases. * Building [*Road Not Taken*](https://github.com/LPGhatguy/roads) to an `rbxlx` file dropped from 150ms to 70ms on my machine diff --git a/Cargo.lock b/Cargo.lock index c9cca0ae..a74e53c1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1111,7 +1111,7 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1270,7 +1270,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0-alpha.10" +version = "0.5.0-alpha.11" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1284,7 +1284,7 @@ dependencies = [ "notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 3.1.384 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1991,7 +1991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rbx_binary 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147f236284747ac1b4643476265dd36b402877d97adb7cbd0fafc1d247de0a5" +"checksum rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81428c521a07a3feac9c31180a886e467eecf81b769987f70d51d567a09c321d" "checksum rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9582ea95ea28d99bea189b90eab04a34ab6e9d04f295ccb46eb997b87754030" "checksum rbx_reflection 3.1.384 (registry+https://github.com/rust-lang/crates.io-index)" = "1209361806b9238226f1f8427bab9b5171ec13b3bf2dffdd2f97a96bb641164c" "checksum rbx_xml 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb23d19c983457fa6c65803190a23b2c4b9d08290f3431528adb9b74ab3488da" diff --git a/docs/installation.md b/docs/installation.md index 6794ff5f..728c8dfd 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -25,7 +25,7 @@ If you have Rust installed, the easiest way to get Rojo is with Cargo! To install the latest 0.5.0 alpha, use: ```sh -cargo install rojo --version 0.5.0-alpha.9 +cargo install rojo --version 0.5.0-alpha.11 ``` ## Installing the Plugin diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 9633a1a7..2db8bd9f 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0, "-alpha.10"}, + version = {0, 5, 0, "-alpha.11"}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/server/Cargo.toml b/server/Cargo.toml index e5967c0c..442923ad 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0-alpha.10" +version = "0.5.0-alpha.11" authors = ["Lucien Greathouse "] description = "A tool to create robust Roblox projects" license = "MIT" From 4c263bbb3e01d70a0353544b617950c5c8964609 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 29 May 2019 18:40:58 -0700 Subject: [PATCH 0523/1504] plugin: Update to newer rbx-dom with better error handling --- plugin/modules/rbx-dom | 2 +- plugin/src/rojoValueToRobloxValue.lua | 14 ------------- plugin/src/setCanonicalProperty.lua | 30 +++++++++++++-------------- 3 files changed, 15 insertions(+), 31 deletions(-) diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index ac129152..74ec3e7d 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit ac129152f250bf6a1ad51a1cbc9f9315130c8fbb +Subproject commit 74ec3e7d885868252b02f227c0e0ad86e3332120 diff --git a/plugin/src/rojoValueToRobloxValue.lua b/plugin/src/rojoValueToRobloxValue.lua index 94c57664..1e30dfde 100644 --- a/plugin/src/rojoValueToRobloxValue.lua +++ b/plugin/src/rojoValueToRobloxValue.lua @@ -7,20 +7,6 @@ local function rojoValueToRobloxValue(value) return nil end - -- TODO: Remove this once rbx_dom_weak and rbx_dom_lua agree on encoding - if value.Type == "BinaryString" then - local actualValue = "" - - for i = 1, #value.Value do - actualValue = actualValue .. string.char(i) - end - - value = { - Type = "BinaryString", - Value = actualValue, - } - end - local success, decodedValue = RbxDom.EncodedValue.decode(value) if not success then diff --git a/plugin/src/setCanonicalProperty.lua b/plugin/src/setCanonicalProperty.lua index fabbd733..eb3fd5aa 100644 --- a/plugin/src/setCanonicalProperty.lua +++ b/plugin/src/setCanonicalProperty.lua @@ -1,34 +1,32 @@ local RbxDom = require(script:FindFirstAncestor("Rojo").RbxDom) -local Logging = require(script.Parent.Logging) - --[[ Attempts to set a property on the given instance. ]] local function setCanonicalProperty(instance, key, value) - if not RbxDom.CanonicalProperty.isScriptable(instance.ClassName, key) then - return false - end - -- If we don't have permissions to access this value at all, we can skip it. - local readSuccess, existingValue = RbxDom.CanonicalProperty.read(instance, key) + local readSuccess, existingValue = RbxDom.readProperty(instance, key) if not readSuccess then - -- An error will be thrown if there was a permission issue or if the - -- property doesn't exist. In the latter case, we should tell the user - -- because it's probably their fault. - if existingValue:find("lacking permission") then - Logging.trace("Permission error reading property %s on class %s", tostring(key), instance.ClassName) + if existingValue.kind == RbxDom.Error.Kind.UnknownProperty + or existingValue.kind == RbxDom.Error.Kind.PropertyNotReadable then + -- this is fine return false - else - error(("Invalid property %s on class %s: %s"):format(tostring(key), instance.ClassName, existingValue), 2) end + + -- If we don't have permission to write a property, we just silently + -- ignore it. + if existingValue.kind == RbxDom.Error.Kind.Roblox and existingValue.extra:find("lacking permission") then + return false + end + + error(("Invalid property %s on class %s: %s"):format(tostring(key), instance.ClassName, tostring(existingValue)), 2) end - local writeSuccess, err = RbxDom.CanonicalProperty.write(instance, key, value) + local writeSuccess, err = RbxDom.writeProperty(instance, key, value) if not writeSuccess then - error(("Cannot set property %s on class %s: %s"):format(tostring(key), instance.ClassName, err), 2) + error(("Cannot set property %s on class %s: %s"):format(tostring(key), instance.ClassName, tostring(err)), 2) end return true From 075b6cca30f12bc5d087308e15114b397d7e4ae5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 30 May 2019 18:37:56 -0700 Subject: [PATCH 0524/1504] Use new rbx_dom_lua API --- plugin/modules/rbx-dom | 2 +- plugin/src/setCanonicalProperty.lua | 42 +++++++++++++++-------------- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index 74ec3e7d..4b5f8c22 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit 74ec3e7d885868252b02f227c0e0ad86e3332120 +Subproject commit 4b5f8c22c7a377becac6b9929ce01467bd561481 diff --git a/plugin/src/setCanonicalProperty.lua b/plugin/src/setCanonicalProperty.lua index eb3fd5aa..8314cfcd 100644 --- a/plugin/src/setCanonicalProperty.lua +++ b/plugin/src/setCanonicalProperty.lua @@ -3,30 +3,32 @@ local RbxDom = require(script:FindFirstAncestor("Rojo").RbxDom) --[[ Attempts to set a property on the given instance. ]] -local function setCanonicalProperty(instance, key, value) - -- If we don't have permissions to access this value at all, we can skip it. - local readSuccess, existingValue = RbxDom.readProperty(instance, key) +local function setCanonicalProperty(instance, propertyName, value) + local descriptor = RbxDom.findCanonicalPropertyDescriptor(instance.ClassName, propertyName) - if not readSuccess then - if existingValue.kind == RbxDom.Error.Kind.UnknownProperty - or existingValue.kind == RbxDom.Error.Kind.PropertyNotReadable then - -- this is fine - return false - end - - -- If we don't have permission to write a property, we just silently - -- ignore it. - if existingValue.kind == RbxDom.Error.Kind.Roblox and existingValue.extra:find("lacking permission") then - return false - end - - error(("Invalid property %s on class %s: %s"):format(tostring(key), instance.ClassName, tostring(existingValue)), 2) + -- We can skip unknown properties; they're not likely reflected to Lua. + -- + -- A good example of a property like this is `Model.ModelInPrimary`, which + -- is serialized but not reflected to Lua. + if descriptor == nil then + return false, "unknown property" end - local writeSuccess, err = RbxDom.writeProperty(instance, key, value) + if descriptor.scriptability == "None" or descriptor.scriptability == "Read" then + return false, "unwritable property" + end - if not writeSuccess then - error(("Cannot set property %s on class %s: %s"):format(tostring(key), instance.ClassName, tostring(err)), 2) + local success, err = descriptor:write(instance, value) + + if not success then + -- If we don't have permission to write a property, we just silently + -- ignore it. + if err.kind == RbxDom.Error.Kind.Roblox and err.extra:find("lacking permission") then + return false, "permission error" + end + + local message = ("Invalid property %s.%s: %s"):format(descriptor.className, descriptor.name, tostring(err)) + error(message, 2) end return true From a587ba45589de88c061a6bf9cee70265948760eb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 30 May 2019 23:57:35 -0700 Subject: [PATCH 0525/1504] Add warning for rojo build to rbxl --- CHANGELOG.md | 1 + server/src/commands/build.rs | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ec32f81..33245fa2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## [Unreleased] +* Added a warning when building binary place files, since they're still experimental. ## [0.5.0 Alpha 11](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) * Added support for implicit property values in JSON model files ([#154](https://github.com/LPGhatguy/rojo/pull/154)) diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index 716ed717..ab353662 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -120,6 +120,10 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { rbx_binary::encode(&tree, &[root_id], &mut file)?; }, OutputKind::Rbxl => { + log::warn!("Support for building binary places (rbxl) is still experimental."); + log::warn!("Using the XML place format (rbxlx) is recommended instead."); + log::warn!("For more info, see https://github.com/LPGhatguy/rojo/issues/180"); + let root_id = tree.get_root_id(); let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); rbx_binary::encode(&tree, top_level_ids, &mut file)?; From 51bbab803fd94eab0f19ba953ad1522f39b4888b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 30 May 2019 23:59:14 -0700 Subject: [PATCH 0526/1504] Update CHANGELOG --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33245fa2..d9ab7b90 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,9 @@ # Rojo Changelog ## [Unreleased] -* Added a warning when building binary place files, since they're still experimental. +* Added support for live-syncing `CollectionService` tags. +* Added a warning when building binary place files, since they're still experimental and have bugs. +* Fixed plugin live-sync not ignoring unknown properties. ## [0.5.0 Alpha 11](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) * Added support for implicit property values in JSON model files ([#154](https://github.com/LPGhatguy/rojo/pull/154)) From 5bd88dc82fd5b5eba97e63fdd21f5594f755a524 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 31 May 2019 13:23:17 -0700 Subject: [PATCH 0527/1504] plugin: Switch to Roact refactored bindings branch, with real joinBindings! --- plugin/src/Components/App.lua | 3 +-- plugin/src/Components/ConnectPanel.lua | 21 +++++----------- plugin/src/joinBindings.lua | 34 -------------------------- 3 files changed, 7 insertions(+), 51 deletions(-) delete mode 100644 plugin/src/joinBindings.lua diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index ef561c85..79436972 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -80,8 +80,7 @@ function App:init() end function App:render() - -- FIXME: https://github.com/Roblox/roact/issues/209 - local children = {} + local children if self.state.sessionStatus == SessionStatus.Connected then children = { diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index f1ec4280..9d26215f 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -7,7 +7,6 @@ local Config = require(Plugin.Config) local Version = require(Plugin.Version) local Assets = require(Plugin.Assets) local Theme = require(Plugin.Theme) -local joinBindings = require(Plugin.joinBindings) local FitList = require(Plugin.Components.FitList) local FitText = require(Plugin.Components.FitText) @@ -24,19 +23,6 @@ function ConnectPanel:init() self.footerSize, self.setFooterSize = Roact.createBinding(Vector2.new()) self.footerVersionSize, self.setFooterVersionSize = Roact.createBinding(Vector2.new()) - -- This is constructed in init because 'joinBindings' is a hack and we'd - -- leak memory constructing it every render. When this kind of feature lands - -- in Roact properly, we can do this inline in render without fear. - self.footerRestSize = joinBindings( - { - self.footerSize, - self.footerVersionSize, - }, - function(container, other) - return UDim2.new(0, container.X - other.X - 16, 0, 32) - end - ) - self:setState({ address = "", port = "", @@ -230,7 +216,12 @@ function ConnectPanel:render() LogoContainer = e("Frame", { BackgroundTransparency = 1, - Size = self.footerRestSize, + Size = Roact.joinBindings({ + container = self.footerSize, + other = self.footerVersionSize + }):map(function(values) + return UDim2.new(0, values.container.X - values.other.X - 16, 0, 32) + end), }, { Logo = e("ImageLabel", { Image = Assets.Images.Logo, diff --git a/plugin/src/joinBindings.lua b/plugin/src/joinBindings.lua deleted file mode 100644 index 1dca84a6..00000000 --- a/plugin/src/joinBindings.lua +++ /dev/null @@ -1,34 +0,0 @@ ---[[ - joinBindings is a crazy hack that allows combining multiple Roact bindings - in the same spirit as `map`. - - It's implemented in terms of Roact internals that will probably break at - some point; please don't do that or use this module in your own code! -]] - -local Binding = require(script:FindFirstAncestor("Rojo").Roact.Binding) - -local function evaluate(fun, bindings) - local input = {} - - for index, binding in ipairs(bindings) do - input[index] = binding:getValue() - end - - return fun(unpack(input, 1, #bindings)) -end - -local function joinBindings(bindings, joinFunction) - local initialValue = evaluate(joinFunction, bindings) - local binding, setValue = Binding.create(initialValue) - - for _, binding in ipairs(bindings) do - Binding.subscribe(binding, function() - setValue(evaluate(joinFunction, bindings)) - end) - end - - return binding -end - -return joinBindings \ No newline at end of file From 983d44947ec6f8969fbbf9c691c96a4c192414f5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 31 May 2019 13:34:54 -0700 Subject: [PATCH 0528/1504] Upgrade rbx-dom --- plugin/modules/rbx-dom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index 4b5f8c22..77b7e79f 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit 4b5f8c22c7a377becac6b9929ce01467bd561481 +Subproject commit 77b7e79ff6e9973ca1a603c37622ce4ce05c7e24 From 0ed6c57c7f2e0e836ef90e7f9e360e0c5e538f38 Mon Sep 17 00:00:00 2001 From: boyned//Kampfkarren Date: Thu, 6 Jun 2019 16:58:58 -0700 Subject: [PATCH 0529/1504] init.meta.json support (#183) * A minimum viable product for init.meta.json * Properties support * Add ignoreUnknownChildren support * Apply requested changes * Use reflection guiding * Add a script to the test * Change to ignoreUnknownInstances * Apply requested changes --- server/src/rbx_snapshot.rs | 42 ++++++++++++++ server/tests/snapshot_snapshots.rs | 1 + test-projects/meta_files/default.project.json | 6 ++ .../meta_files/expected-snapshot.json | 57 +++++++++++++++++++ test-projects/meta_files/src/A/init.meta.json | 3 + .../meta_files/src/Script/init.meta.json | 5 ++ .../meta_files/src/Script/init.server.lua | 1 + test-projects/meta_files/src/init.meta.json | 6 ++ 8 files changed, 121 insertions(+) create mode 100644 test-projects/meta_files/default.project.json create mode 100644 test-projects/meta_files/expected-snapshot.json create mode 100644 test-projects/meta_files/src/A/init.meta.json create mode 100644 test-projects/meta_files/src/Script/init.meta.json create mode 100644 test-projects/meta_files/src/Script/init.server.lua create mode 100644 test-projects/meta_files/src/init.meta.json diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 7be71d3b..c3e4fef9 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -39,6 +39,7 @@ use crate::{ const INIT_MODULE_NAME: &str = "init.lua"; const INIT_SERVER_NAME: &str = "init.server.lua"; const INIT_CLIENT_NAME: &str = "init.client.lua"; +const INIT_META_NAME: &str = "init.meta.json"; pub struct SnapshotContext { pub plugin_context: Option, @@ -105,6 +106,12 @@ pub enum SnapshotError { path: PathBuf, }, + InitMetaError { + #[fail(cause)] + inner: serde_json::Error, + path: PathBuf, + }, + XmlModelDecodeError { #[fail(cause)] inner: rbx_xml::DecodeError, @@ -152,6 +159,9 @@ impl fmt::Display for SnapshotError { SnapshotError::JsonModelDecodeError { inner, path } => { write!(output, "Malformed .model.json model: {} in path {}", inner, path.display()) }, + SnapshotError::InitMetaError { inner, path } => { + write!(output, "Malformed init.meta.json: {} in path {}", inner, path.display()) + }, SnapshotError::XmlModelDecodeError { inner, path } => { write!(output, "Malformed rbxmx model: {} in path {}", inner, path.display()) }, @@ -299,6 +309,7 @@ fn snapshot_imfs_directory<'source>( let init_path = directory.path.join(INIT_MODULE_NAME); let init_server_path = directory.path.join(INIT_SERVER_NAME); let init_client_path = directory.path.join(INIT_CLIENT_NAME); + let init_meta_path = directory.path.join(INIT_META_NAME); let snapshot_name = instance_name .unwrap_or_else(|| { @@ -327,6 +338,27 @@ fn snapshot_imfs_directory<'source>( } }; + if let Some(ImfsItem::File(file)) = imfs.get(&init_meta_path) { + let meta: InitMeta = serde_json::from_slice(&file.contents) + .map_err(|inner| SnapshotError::InitMetaError { + inner, + path: file.path.to_path_buf(), + })?; + + if let Some(meta_class) = meta.class_name { + snapshot.class_name = Cow::Owned(meta_class); + } + + if let Some(meta_ignore_instances) = meta.ignore_unknown_instances { + snapshot.metadata.ignore_unknown_instances = meta_ignore_instances; + } + + for (key, value) in meta.properties { + let resolved_value = try_resolve_value(&snapshot.class_name, &key, &value)?; + snapshot.properties.insert(key, resolved_value); + } + } + snapshot.metadata.source_path = Some(directory.path.to_owned()); for child_path in &directory.children { @@ -351,6 +383,16 @@ fn snapshot_imfs_directory<'source>( Ok(Some(snapshot)) } +#[derive(Debug, Default, Deserialize)] +#[serde(rename_all = "camelCase")] +struct InitMeta { + class_name: Option, + ignore_unknown_instances: Option, + + #[serde(default = "HashMap::new")] + properties: HashMap, +} + fn snapshot_imfs_file<'source>( context: &SnapshotContext, file: &'source ImfsFile, diff --git a/server/tests/snapshot_snapshots.rs b/server/tests/snapshot_snapshots.rs index 7c3d1e78..4c143f38 100644 --- a/server/tests/snapshot_snapshots.rs +++ b/server/tests/snapshot_snapshots.rs @@ -35,6 +35,7 @@ generate_snapshot_tests!( empty, json_model, localization, + meta_files, multi_partition_game, nested_partitions, single_partition_game, diff --git a/test-projects/meta_files/default.project.json b/test-projects/meta_files/default.project.json new file mode 100644 index 00000000..0eb0c8ea --- /dev/null +++ b/test-projects/meta_files/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "test-model", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/test-projects/meta_files/expected-snapshot.json b/test-projects/meta_files/expected-snapshot.json new file mode 100644 index 00000000..060c5109 --- /dev/null +++ b/test-projects/meta_files/expected-snapshot.json @@ -0,0 +1,57 @@ +{ + "name": "test-model", + "class_name": "Tool", + "properties": { + "Enabled": { + "Type": "Bool", + "Value": true + } + }, + "children": [ + { + "name": "A", + "class_name": "Folder", + "properties": {}, + "children": [], + "metadata": { + "ignore_unknown_instances": true, + "source_path": "src/A", + "project_definition": null + } + }, + { + "name": "Script", + "class_name": "Script", + "properties": { + "Disabled": { + "Type": "Bool", + "Value": true + }, + "Source": { + "Type": "String", + "Value": "print(\"Hello, world\")" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src/Script", + "project_definition": null + } + } + ], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src", + "project_definition": [ + "test-model", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "src" + } + ] + } +} \ No newline at end of file diff --git a/test-projects/meta_files/src/A/init.meta.json b/test-projects/meta_files/src/A/init.meta.json new file mode 100644 index 00000000..1025b06a --- /dev/null +++ b/test-projects/meta_files/src/A/init.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/test-projects/meta_files/src/Script/init.meta.json b/test-projects/meta_files/src/Script/init.meta.json new file mode 100644 index 00000000..54f46925 --- /dev/null +++ b/test-projects/meta_files/src/Script/init.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} \ No newline at end of file diff --git a/test-projects/meta_files/src/Script/init.server.lua b/test-projects/meta_files/src/Script/init.server.lua new file mode 100644 index 00000000..2c9b8de6 --- /dev/null +++ b/test-projects/meta_files/src/Script/init.server.lua @@ -0,0 +1 @@ +print("Hello, world") \ No newline at end of file diff --git a/test-projects/meta_files/src/init.meta.json b/test-projects/meta_files/src/init.meta.json new file mode 100644 index 00000000..fa412de2 --- /dev/null +++ b/test-projects/meta_files/src/init.meta.json @@ -0,0 +1,6 @@ +{ + "className": "Tool", + "properties": { + "Enabled": true + } +} \ No newline at end of file From 2a4ca21050a1a5aa17a5368cbae450869d63d40f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 7 Jun 2019 18:29:09 -0700 Subject: [PATCH 0530/1504] Substantial documentation improvements --- docs/creating-a-place.md | 68 ---------------- docs/extra.css | 10 +++ docs/guide/existing-game.md | 0 docs/{ => guide}/installation.md | 5 +- docs/{ => guide}/migrating-to-epiphany.md | 0 docs/guide/new-game.md | 90 ++++++++++++++++++++++ docs/images/connection-dialog.png | Bin 0 -> 13716 bytes docs/{ => reference}/project-format.md | 69 ++++++++++++++--- docs/{ => reference}/sync-details.md | 6 +- docs/rojo-alternatives.md | 23 ++++++ docs/why-rojo.md | 43 +++++++---- mkdocs.yml | 14 ++-- 12 files changed, 221 insertions(+), 107 deletions(-) delete mode 100644 docs/creating-a-place.md create mode 100644 docs/guide/existing-game.md rename docs/{ => guide}/installation.md (92%) rename docs/{ => guide}/migrating-to-epiphany.md (100%) create mode 100644 docs/guide/new-game.md create mode 100644 docs/images/connection-dialog.png rename docs/{ => reference}/project-format.md (58%) rename docs/{ => reference}/sync-details.md (94%) create mode 100644 docs/rojo-alternatives.md diff --git a/docs/creating-a-place.md b/docs/creating-a-place.md deleted file mode 100644 index d20f8ffd..00000000 --- a/docs/creating-a-place.md +++ /dev/null @@ -1,68 +0,0 @@ -[TOC] - -## Creating the Rojo Project - -To use Rojo to build a place, you'll need to create a new project file, which tells Rojo how your project is structured on-disk and in Roblox. - -Create a new folder, then run `rojo init` inside that folder to initialize an empty project. - -```sh -mkdir my-new-project -cd my-new-project - -rojo init -``` - -Rojo will make a small project file in your directory, named `default.project.json`. It'll make sure that any code in the directory `src` will get put into `ReplicatedStorage.Source`. - -Speaking of, let's make sure we create a directory named `src`, and maybe a Lua file inside of it: - -```sh -mkdir src -echo 'print("Hello, world!")' > src/hello.lua -``` - -## Building Your Place -Now that we have a project, one thing we can do is build a Roblox place file for our project. This is a great way to get started with a project quickly with no fuss. - -All we have to do is call `rojo build`: - -```sh -rojo build -o MyNewProject.rbxlx -``` - -If you open `MyNewProject.rbxlx` in Roblox Studio now, you should see a `Folder` containing a `ModuleScript` under `ReplicatedStorage`! - -!!! info - To generate a binary place file instead, use `rbxl`. Note that support for binary model/place files (`rbxm` and `rbxl`) is very limited in Rojo presently. - -## Live-Syncing into Studio -Building a place file is great for the initial build, but for actively working on your place, you'll want something quicker. - -In Roblox Studio, make sure the Rojo plugin is installed. If you need it, check out [the installation guide](installation) to learn how to install it. - -To expose your project to the plugin, you'll need to _serve_ it from the command line: - -```sh -rojo serve -``` - -This will start up a web server that tells Roblox Studio what instances are in your project and sends notifications if any of them change. - -Note the port number, then switch into Roblox Studio and press the Rojo **Connect** button in the plugins tab. Type in the port number, if necessary, and press **Start**. - -If everything went well, you should now be able to change files in the `src` directory and watch them sync into Roblox Studio in real time! - -## Uploading Your Place -Aimed at teams that want serious levels of automation, Rojo can upload places to Roblox.com automatically. - -You'll need an existing place on Roblox.com as well as the `.ROBLOSECURITY` cookie of an account that has write access to that place. - -!!! warning - It's recommended that you set up a Roblox account dedicated to deploying your place instead of your personal account in case your security cookie is compromised. - -Generating and uploading your place file is as simple as: - -```sh -rojo upload --asset_id [PLACE ID] --cookie "[SECURITY COOKIE]" -``` \ No newline at end of file diff --git a/docs/extra.css b/docs/extra.css index 020a7103..ed31fbc9 100644 --- a/docs/extra.css +++ b/docs/extra.css @@ -1,3 +1,13 @@ .md-typeset__table { width: 100%; +} + +.feature-image img { + border: 1px solid rgba(0, 0, 0, 0.2); + box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2); +} + +.codehilite { + border: 1px solid rgba(0, 0, 0, 0.2); + box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2); } \ No newline at end of file diff --git a/docs/guide/existing-game.md b/docs/guide/existing-game.md new file mode 100644 index 00000000..e69de29b diff --git a/docs/installation.md b/docs/guide/installation.md similarity index 92% rename from docs/installation.md rename to docs/guide/installation.md index 728c8dfd..b56f31c8 100644 --- a/docs/installation.md +++ b/docs/guide/installation.md @@ -1,7 +1,8 @@ +This is this installation guide for Rojo **0.5.x**. + [TOC] ## Overview - Rojo has two components: * The command line interface (CLI) @@ -35,7 +36,7 @@ The Rojo Roblox Studio plugin is available from Rojo's [GitHub Releases page](ht Download the attached `rbxm` file and put it into your Roblox Studio plugins folder. You can find that folder by pressing **Plugins Folder** from your Plugins toolbar in Roblox Studio: -!['Plugins Folder' button in Roblox Studio](images/plugins-folder-in-studio.png) +!['Plugins Folder' button in Roblox Studio](../images/plugins-folder-in-studio.png) {: align="center" } ### Installing from Roblox.com diff --git a/docs/migrating-to-epiphany.md b/docs/guide/migrating-to-epiphany.md similarity index 100% rename from docs/migrating-to-epiphany.md rename to docs/guide/migrating-to-epiphany.md diff --git a/docs/guide/new-game.md b/docs/guide/new-game.md new file mode 100644 index 00000000..7a3f46ca --- /dev/null +++ b/docs/guide/new-game.md @@ -0,0 +1,90 @@ +[TOC] + +## Creating the Rojo Project +To use Rojo to build a game, you'll need to create a new project file, which tells Rojo how to turn your files into a Roblox place. + +First, create a new folder to contain the files for your game and open up a new terminal inside of it, like cmd.exe or Bash. + +It's convenient to make the folder from the command line: + +```sh +mkdir my-new-project +cd my-new-project +``` + +Inside the folder, initialize a new Rojo project: + +```sh +rojo init +``` + +Rojo will make a small project file in your directory, named `default.project.json`. It matches the "Baseplate" template from Roblox Studio, except that it'll take any files you put in a folder called `src` and put it into `ReplicatedStorage.Source`. + +Speaking of files, make sure to create a directory named `src` in this folder, or Rojo will be upset about missing files! + +```sh +mkdir src +``` + +Let's also add a Lua file, `hello.lua` to the `src` folder, so that we can make this project our own. + +```sh +echo 'return "Hello, Rojo!"' > src/hello.lua +``` + +## Building Your Place +Now that we have a project, one thing we can do is build a Roblox place file for our project. This is a great way to get started with a project quickly with no fuss. + +All we have to do is call `rojo build`: + +```sh +rojo build -o MyNewProject.rbxlx +``` + +If you open `MyNewProject.rbxlx` in Roblox Studio now, you should see a `Folder` containing a `ModuleScript` under `ReplicatedStorage`! + +!!! info + To generate a binary place file instead, use `rbxl`. Note that support for binary model/place files (`rbxm` and `rbxl`) is very limited in Rojo presently. + +## Live-Syncing into Studio +Building a place file is great for starting to work on a game, but for active iteration, you'll want something faster. + +In Roblox Studio, make sure the Rojo plugin is installed. If you need it, check out [the installation guide](installation) to learn how to install it. + +To expose your project to the plugin, you'll need to start a new **live sync session** from the command line: + +```sh +rojo serve +``` + +You should see output like this in your terminal: + +```sh +$ rojo serve +Rojo server listening on port 34872 +``` + +Switch into Roblox Studio and press the **Connect** button on the Rojo plugin toolbar. A dialog should appear: + +![Rojo plugin connection dialog](../images/connection-dialog.png) +{: class="feature-image" align="center" } + +If the port number doesn't match the output from the command line, change it, and then press **Connect**. + +If all went well, you should now be able to change files in the `src` directory and watch them sync into Roblox Studio in real time! + +## Uploading Your Place +Aimed at teams that want serious levels of automation, Rojo can upload places to Roblox.com automatically. + +You'll need an existing game on Roblox.com as well as the `.ROBLOSECURITY` cookie of an account that has write access to that game. + +!!! warning + It's recommended that you set up a Roblox account dedicated to deploying your game instead of your personal account in case your security cookie is compromised. + +Generating and publishing your game is as simple as: + +```sh +rojo upload --asset_id [PLACE ID] --cookie "[SECURITY COOKIE]" +``` + +An example project is available on GitHub that deploys to Roblox.com from GitHub and Travis-CI automatically: [https://github.com/LPGhatguy/roads](https://github.com/LPGhatguy/roads) \ No newline at end of file diff --git a/docs/images/connection-dialog.png b/docs/images/connection-dialog.png new file mode 100644 index 0000000000000000000000000000000000000000..5a3d5f29def79d087cc0d9d58e28e2f8d7f6eafd GIT binary patch literal 13716 zcmbWeWmp_Rx9^K+(ZZ0;YPL{P4YjU@5LB4g*sckN#qe_})f!l+$*Bfx!g-=L0+FP-^ym64zB)%T?9E z!qvmr*&IgJ+1%XT<)?$IfjY{6y3qXRs-&~Iv8$DXJ++#ZojD8_2d4mlgBQTTN6pCx z;QRvM<|bA)_yq&QvnDSkuI6cQnvLv>Z~ipca(_~MZ$OP2h%JGtpMftf{yE=r(BSL_ z|5^LYVQ{cG@R=QbJCGy6e8a>m1r5D5;hB5f!@)X5zjfcWikt``_sE z%i4Z=J=l$(oIHp+0`p>_2SFTrU-C!{JH%3s0ww6;Lm9j{b`FgjHA+8sAtr*jXV`2Y zHOj;<05-xV$q(cpYN7wXH!IXAhsVZuUQqIpQ%OqV>COh8HPWEuBOiLXl?pfqac(E` zt&S1mNY&8z9HLqHHUmW>iR(>LsHxEHGGRkiFP$3LTyFu@h4z*_O*;LjOZXhDz5f|j#bOND z>13v6kw^T7>j%+jZtcUZ6ICbI#@q5EEzQ@v*LB&ZK_#vxgac!@p{Fh6%zvYs&XQq; zv_4y+BP`zVs&ip;Mk|k7f`)fwP!Ny3)zfVL?eZcTU%PFC_nqVg>N=4WXm=ny7dpgV zbg2eAOyT~V;QzAUG1bDR!SKfDHeD=hD0D6q3U<0N{MMsD0tKAO@4vUKK&@suVyeyY_9&n)f;>jY zY#eZ$Z#^V_+%rbUGc^T$d?egyCv$S&%Y#>~&9g#V%eG~@9?5Zw3Ej@_E%i}}Gzw5V z&U-tc)+lTsDojj8}2M zJB&X?j|!YK4;%RtyrP$1CC9DERiuO+T{INB!Ig7v2GV-hQfnMp@{NSa04P5>vGfSz z7`s-3yuL={lzO`zJ3S0(;O3^aC+0nlXY5qck#eg$y8B05tN1kvmu=$n1-Zg_zZZhL zri!(HefMwbsmak&V$eUCDQr1+bL%gOTe{zd({;km8jT$nY!{)gIH)zXMuAekH-=F2 z&KQ~rA=mSSTh*Qiu}`VSNgH9U87}obI)UeZ+PEoM1stDK%>Q|elim(A(1vziGi_y* z`0m3pY^JUtuM4cde!#*X^vv2E>;!ek5akX&i?-N@_ z`Y@U8GVd?wcX_OEXI;oRw>c!*)8E3yB;h@_^A5nQiW!u zP~2mwmHRAMGtGs(SR=N*5e`*f@ipTyzNYP!(-#}iuH%%}fD3Iep>VaU15HwV#j94_DoEGX`;X(ITt&pp_S-7Sj2=ZDrKn^%wUXFU|C z;j3$Bqvp#fop%SEZaJJ^ z;oxm)XA+QW&2>6?UpCl1L-4QZJQ7&aKe2Hyxfz7dOMgDIG$wBfKE|b&a@n{6EtKBC zYjfyV?jPP};C}aNe_A^cQe2fMa8l%Yh7^r&8nXgh9jO??CXKBW+WtT?Ndg~5tG|?e zQJ@*z9D3a(dI`-yC@SJG?*$?>gDvW6%PLZGRKk;>uL%NOqW;TKybZ2?C%X~d%6>2F z>r1Q}^tk&9gDu_Nm(O)A*)QH7319q1tA_GxW8argU{nXHfJ2jr3Zvw)Ap~GTkuV2E^D#aW zK1jeiz>MLT>(4+fY-S;=2hjT-Y#R{Bi@M%zg z5$sG5B5yX^Rb;#$hd}mTO{LDZ9B06iM@&9{ zx3vPO`hv=vU8w#viQi2Vp!g&NoMZC=X;l{}!%bJ=CoKG%vc_^gTKAVO+CWD}NhoEh zYtu)m!ZEEodPz8Wx8o>?Tq}G8gf|3#+b&{QiJ9~U2`Xx6cgF34x5x!W>F`-~9fh8RJqV4}HTCu|60Z5oz08 zB~l^dqQ3=k`ydHB8BXTCIb!eh!75jH>8A9(36`07GgPy;u2?}IFPaVC;MsrR;C{Nj z4rEh!-3ngjgH9F+My8*nnCCv+9|s$s6Hwyv*$L@75lq8(zlU!Ky|Bw#Aa#Td*8dc+ zg9`@NB(I&_-B%va}@t#K-2x`<^_#I#h=V30aR#jEGt|Ls5 zZ8*0vB_BzIIlacrjo(Z19R?1;eN~tiyTRqa=cHa#K(5ZMTYB_6V0iC^uZ-OlrG&KO z_CRp|PELfg(zf@nuV2>;8Frc8PPb0Jn*wP9G#Zyz z+AVoq_~&EV>HQ=lc0)=F`3F>^#;nBjV@YkB3Sx%VWjqo$T&;%j5?|6Frv_1dT5by+PKVGf{u{!WSKd2D9o z>bX4+~^R@L3zAL=W{(Q=jqWzu04-EZ!qvP1ZxM@r;Wj_{lJg4A zBAi9`MgtAwR!w$M5xcj;qv3p~;Ga}5NsL%(c<1zJ9I|Hv`O$+EqLbN^YPGj~AGkiR z_?&#?^(Rc@`A&2{bPq-y?zb?q{juNOlqoDqZeCd`lgu)HD8gZ+EtPR5EZ3i9 zA6nEmL2FUDGV}puMK?QhY$CY(H$D&<3#!z6ENP1qh?){AW_7F?!PsIj3 zLD$qzBg^3Q*(eZpLVM+})BxpT-P=0;w6d0#I;tE46tS~3G?(K1xeD3G6aa@d_f1d6 zz!1PPcI)0z%#n|9YRsak8Ths>KQFZ}$%T&J+@z+BWb#G|iaxu~xmwZB205u$K|Lkzm7WNI&Xj(v{v$7}y(p|1lMp@T*AlSjm zTD&pd!Q9)w`G$qVN?U>d9FBeHM{x-?;O9y`)^)h5BeRV<7^yis*%i3}?lOp;sdDwt z45p-tz;9{tJ>Se5f`C~NccT|#ngmd$C_3n+&6mI2RwD+*>;cuAWqh(ps{M|AX#|KdRdL$Qf0Caj*Rx!q?WM&^d@A`vX8Ud$j)$}yW( z&c-)wTxW!Y7mm!0;c0@yJMFMFk4$v3ID?lS}OQC(a@vrlZ6^^V&D?j4$6sTfA6F)@Gr6)?O!!|9elf=m@p)jytX zcH+7dc29d*&Fpy}3LH4owMo!ysVfLBt-y8s8^w1I@sbB@!{dE$oC$KsJ?k|1mGWUk zN_jw|)i-KhQrnSWDvb3A=FaQ7yWrh1!57B|(^kaqw%%`GViK-QxNAzT2L9=#AqYqE zE@G&c?h!4-Bti&7@c*7??au%wJ7v$qX<=b!wL3yjKQY0%=vEa z*^#V@)b6&vX-@Pd3d@B~68x0?MYP(I3_oSF_fz6l8q3AkW8~#|qB;?MG8Ekl)<_id z`qO}6KD%WsOXXzFi?3hdsoh$s(>OUyb#=ekzOi6CTP8D$5Iymi{PaXtP?wz@yvAPh zi6`FajG)Hnl5MejYx8YyNH|03+==jeWr%Aei&^S~Yo5h;_+lHypXD=c?`GHB&yH`V9h?z|j zA79VYoOV2}Z_s@Bp|~7i^}%Oag_P*;=H&((*J2$1s7200XLM@&%wNok*s&V~eS7*w zuvhgm#=hbrg#`_RNc&_L078L@yd}}=Sv^$$G2uKFMzqt*qqwXcGl{8lxcC(LA^ zUOzkNY^#&qAl}gKb#Kg;d){ffjseQ$+xrCc<3#8$=4)5#_i7b<0KoD_7R=W}iSLl& zvhQ}RfW~FcM)e)+lLGbKoC`&)KJj8@Q}BR4oVZWVL(ftTta`*FOqZ;euG6sJHb2P~ z^oMlsXII(o|9$b(gM2sEKj0)@zXbp7J4t3tOJb|RcB#4MB#tDORY{nJyxx5=vi~`~ zi=TE(cB(;U$bb`$z?6u$kc2+|{5vYk zqrw9DzMEa!8;K9$WjeuoZwhl|kGY}=7sz9u9^$yQBIQ}~pawnYQ~wXL%?$j} zS7KLm#aYe`voF-)Js}ZxU}0NshFEjeNkh<@b9|70^pAcnFz^958j14ym;D0V&{AW( zlPTmHXY;?g6b{zv;Vo>j7?b^t7C@`vwOVJoYmSB>P1uFvi2-TT+Fl=2GUBEPfQU^` zD%KX%b}Wn*NgPc^=Y{KuGYZ1OB4*OI_wAmu{XpI--&_)eTy!`;c0~Vg0qlnM-~;D@ z8RN}{_Um!r$h!Xjmptakx>396((_9)&z?FqmomCA5!Q-B1^%#?h;jOvDFS5V_;$?nS!jP412UR%@=zX!(j$ zuRZT^x%HxZ2;;%$N&_iLN%+ho-jeP&tMgoFc}!fZ+r-yytTd!oG}^nCfBeVUiAhY7OVLV@7CVE$qU9R_WSk3DV>H z>#@%-s|(tyX^Cgs=jRi}qo?pDZ*HMgw_Mw}9TCMYKSk|h0` z^CBH_6Hm6ngiaUz>sP)Lq01?MTZ=otKvYB4s2mZe)lo#J7RBf`FWjfk`aRo|$I*3` z?UjhrVo;F(qv=INpKn>~+eIYU!9RwsUk&zT|AvSXogx#2f@Lq1ZrE<`Gv3n!-u%}3 zy2lCiO|siDv3lUR_Xi0IotGM^rXoCIYVr~2x^D}fE{3lZ!5ZCgPs4n`P(&1cWB5HH zA%h`)0E^nIZ116AGQsU&qUS9gLQ0mQ^y;zO*W)|%J2OMapHh%$doG{*0ZYMtR3x;V z?%fb3h0anYt+$Hr>#cb);sncg)#=Wfk{WCcM(nUi@#m(|A`X_C96h{N*kzp-_PQxg zC5X6G>Zc$UFRhEb(D>1X2Mj~!H8zUdmL4&ZFT3iv{_B5yEUNR2-&p@RP*s+!d>Q^ma*EvTaM zvrZQdRXF%e=U`a;$k8o$5o!G`TcngsNC>z#b&Jx#$o}j(-e-v8+FJ`kv~5DKDXm>@ z;LRJ06@9^5?9ZKd(No$D>|yEWIKAJXaN&k1J$s?jrv8?Fn}kOCsJI<8^@w{6_`N{L z{2z#~_kZu^YTbr`9R!HZg?ktKJiwRa497Ucg-jxV`;lE{r1eJQak`P2;*_^$40KGL zhfmA>p~a2P+DE_Vw)gBZp!D_c|NL%iSK_rqljORm%+Yzrb)+WWm_MBTQkYjfs@ZfO zyWny_3}5bT)Q1u6tJf%+8OWG7cHqRniSDsC&(G!7cN7B62kUaP?{wyW;pKa>$Nc(> zvJ5;I3!cCA?Z>;=r3s8c&$u36uxox0m{CEo%q%mP^V@JAc<$W^`-kUlZ)+{S|FOqD z5Q}T)R@CWn97KDQi1mEj@JU?#FpMH9V)CJFd<}*ikDn-FpMC!MRo|Gm18>9Z?}{_s z3ra-xs~vS=b7DDkqe*lYVrc!#T2sPZd#U-sDt8)qXNXlb}*- zgeO=Kh6)xgwkvk&fCR7ZXcPh+Czp+u@wk|iwo@8|lK%*=$UGa3C0M?H`Qr8qwdTOFTkelqQy^33REQJQ+-NBk z7Cs$oKv)P(rDw<{YeiJBy7Svqi(uLmJ(^ zPG`B$Vn)Z5@`S?x=AA9T-wvi@@!;EsYPu3z)6kBq=L+{tEx&VJJ1Q9;-1^{KbKz^u zspEmo(IwH$)Vxnl-A}iq?$-mX5|44=&Xh>>_F$e*Fu}{)7s*IZU}p|tC4;vb_gn)v zP@(g)h;NDTwNb}4SM7IgN0>KK>th<1;WU(cB*%n2(v0b-5!XEoH;e;VgM|UF_?Bnt zR#S~r6<;6J!uRDIc|YE#SIEYs>%UBATf5ysv$JR>>nX&yG0;W=^6=(E4 zk`n7H4rMGCuk+FO+|LF2saCCe3VTW22ENDR$s+QX5e#4F?eNMv!(MME9{g3X=EyF` z(dCGs^^1#dT(!ED>K#}TlACnYTaJFs=iv4uOiS^mI%_G*vp_O4lgWNr?8PS5I0tDh zl%%e!_b{|-gdMMYm179~vlKk&N6uxs*!%fC8Z`P&Hr8VZcH)^xe+~6m*NW+xzFqc! zUfyO+^eo@*R4hWD*gG8ghCF>}kZi^i&v7!126S@(y9>y<=KfC@=N2IWs95TCEj;y*h zM%F{|v@`=U4L4?JIrxAb4XP0pw!0?co*+%b z^yqrLrFCw&cgtyYG2&et3_yibFCmsHp(GE@!lJk7{^&?fmrJa;hI0}324DRzoh9X_MdaO|FKLM zZh!zeP478QQF0H`I{aH4Vej}Kjsg+U;OF@4?Y9>tWn&BY(f>cR6>bosz|b+iiv04t zfNEO||ITQT?YOHT`?WVgYk0oK|Cn`B~!L<3;3*Q z={4J(H{B1cQu<;Uy+h)!uwEs9yi&pcu3AR1{2%I?={DC<3~!&4{uM$FGmefb(4ush z%Zr$5CJVc}Vc*vLx=kWO&a@dK*xHWf`p)|Ig5>!PX{>ltcXI_AyewC%6?Dy6HLJGe zKhp4hCw^KG_A>@eSKGJIpup*^9>EAq9^Z~(#Ktx?9Ss!k)ejfXNH29tT&MrgRjmM< z?Jd}nXTtjh$(5nx@M#sR201YUq10NQ1eJJ zCD&);A~?Z%Cje@l0&RRAe7pae)ag_yj2dx~B1(YdOKJdK@0MCJd_N_Ag!va)bSCTsGdJ^14vpW7fGMi>If{D zr4pi;{|Jnas`!;YTv1u2gPF=48GS*;$8y@e3{HHC`eR~IvC@<7hJ!Hmk*EqYhLHHi z+s(!XD6Ot8uA*uj3F?;b-5&{tmq4Z;EWXox@?^$Ga}QK<5=ktb5yw|L6l89o;-$cWb^1WsNpjfX++395e@0UysQI|s~K_>>WLl#~Pr+sYk?AnuwOt%|&_EtXwfT-aD#c=D%YofvJz zwn~SXWALZ@_y`v&Wck~dQbTC?nF6Ii<@Gms6!I7uQ&WB5e8%m^^_tCcx9+|``TNoN z=m%Ql`vuE&Vr#M!89WIjHhgimZIaQa41hu2`K)>_omPMgP4ZVo2GzZz^{cgq67?#T z;*Z~-t?L|&U|f`7Up4Uw_);}*DMX~$&ZQmP=_4vaqm_{xLxic;I$8HuCmJ86d8^{! z&)4i_1-zY_1J>h8a|Zveh-?%wPFpHo{{XDto+Z?8B_@%z5U@S==_yx7eNerL)+}TQ zGb_9&`Hi+-cp(+%5s<3}n&jbqL_oIsl5u+f+V-WS*MBK((U6U>!yxrT&-OvF-JEDO zyFrt<2nXkB(V*&JyfguxNZQ!m^b2>ms5am%xg;1Yp?^$|vPFAP4fxr#G`y8aH{w^V z+cVc>mo4g(q?&_I$|whlhp-z1j&0 zKbI!!GB9-I;yb@S&$uH`Ktv8(_s~7MA?pJArp+0%MgZepo69yzZt>RrKMDbco1BBF z*@CL)`mC&w!0DAIz#6DxYWnFUDLF6MiAD}SWIsU=F6mhg2=s&#dE#s;AGxO-2HvmF z6Jp5Hl0ruk8!t^)gV9|P**9iEbUsx6a~hB#9JC@Q9Qd40KJ#IOwp5}5bc(=u$Dgak zs|{31gVJ~Y`)vs`B_^l0O-&ty-R2HIt*ffZZbpNh_!Mu1pRc4V|C;ges;QYn+oyhL zr@rj~H#w&i2*j~hOO8i;P&U4wiMHO)VKoYJhw9}h(}odVNJ~JM8RES+u>KXu{wby( zr2ja;!1%YQIkRuNY7JXOyVd#l`fnE=BAV{k^y2>ckR+W&!y!=tNFkgveb*!}W z&kHV6f~_;)02^USK))28{GmUoE#2XDMoW25ke2nOtiuadB(1$j92OS1O^=IONxBA` z4-=3k`iV*6qyYEx4mJwtWn~O;{Bgw$&}so(TkmdcvF;kc8qvBLzUbIP3PC79c1;6r zOhyK$Q&ObQ7h3?WKBj_kWI~ZbLh~=v@fdBIPc|1Q%KcFL4qsov;9B?QCL4X3u5Jcq zSr&;j$fT6G5YU8@v@&>oB z@|LMTN>r4qCh`Mm^2ee!e`w-NCBbd9qW=x0p{Qtc9Cd{K%wnf?gAUoZ5qLPb=`~;P ztqykC`)|__zNJ`(ZYdMZVfuZjJAX_k{r&9J-)|=vV|uXb{*M0U0sfii${DGK4JO&V z&yADoe4FXWxM7&qE)T}1fY^DxA67QD#$T6I60&WEnPoJuHef0dH&IE^Lur9_!7y<# zyvcuhmZ~aZ^dkLOV&hI>&F`s4dXRb1 zo3*1`EVn}G!a)+NXc<*VTF?q^z^ZlGx0{U}b8iS`PDL6V1o0_WENN-Y|4y19LfZwJ z_`<<2m%$ST#+#OwwPYxQtUjL|)1u@*yOv`L87P}cX{{rasYNxeT5uEnc2dw73V{aD zmt_H&BmbIASvQvOohmzs{VjrX#!2Y$7m6f+@t#aO3S^_i#x9hI&1ank{yG7Phw^b`;CPYVv55;L8ObzfiTq524|7 z-U#%#s&&2FzwvS2mI|AE<_fbroX(*^6X9LUO*&QH=Q!Pq@M#vaR(!2y<+>xqKQ1chVjm=ERW`-i}q{efQRB*g;Tv zX{*(kdv)KZ?{P#C(solA;@Cve9;|~uc{Fx*mtDQt;+d6)fc=s<9{lGTY^#g~II2Se+}X?FqB*na6g89(2~+bb zzw^5K%B1;*GkCa^;wYx-zMWt4xO?mQ%1qg-OQ-c4V%on%eaW1{TgvAkv-oeFea0O8 zJ3o3<4$mx^QG;4PwO3#|LMq}d1X(l`Amt%HBNd_^ptF~i!OcSJ>_V~P9 zmy+&7rDTT2MId>0>J=VTfwXCjfat}O-Th@J2EM}^-iE&`<(pStw?3G;k9+%9LA0$* zrCg*jAA9T?Y;N2s`FxGgf>7|$%(=SNPI5EMxQXATMn^)uRet!az2f4Rs*bjgb3)x> z={dLnj?j0BkS*Q5BDgPajCpI}L@#oP`OB1bGr9Jw?j5&7Q{_^BnS=YqqhE^><--mT zl#p=NA~a7(==0Bvv=wR1AS&>mL|r&pQsa11oP~T|F7)K{P_zAl+s(BDjyQD{#QNBO zjg}DQv75;i-8}G|`nSLY7gK(}Ex=TDoP=%#0rEwqODVO@+HR(1`Nk`>esW`@%#;pq zOR$~kol%m`%7dGW{;H{uG%a$Lpu_oI^V#j^G9_Mx3bB31ru=;|Tp&r=!N|`QWCu*y zi?Vi!meJL*B0_z6`iLT!MQv+kJ&&L4sDXx+#w3H~wi2MMoOVCc!43bUlI3JSklzdmGa2p+ zXOI4PXK%Pwb!0_-I@zjV9>*$oo22%$UZ?239YNqqZA&hh_wm?Tw+ID0dH=&l=XC1H zc=ja6P&mr-&gB$kn})?Gzf}_fb=#K3SKMvH>dgA*6|T@+TuW=~&(FSIw;ndw-%wtC zJ0*kD&2jYPihh`{6Gv+q*{gg50?kY~TRKxTwI^ms5Ye}w1 zFchl;G}>kFPqan}=clLkc4Sheoa3X}%vtm;TG7)1iTF;hl&9RB<7FqVxC8K3@5YEp z-6pCma3)Im91-9u`hF6icRG*@xE?-}V678ilPhR)qHbLsE=3tlGbH_6ncb?T&iBZH z;yrndAQwGIg?v_Lk^_e-;8@r;Eru8e;u9v-+4taLh8M_F8!@xiuZ@Ahpk`#fo2bZ|be*5tOWhOzsLp zG%3lRmU6ddW_*2tp|lA;rtg4;@zx)TzPN)JKwhe=gEsHLXPN7?XXox>7Yx`}Xi%w% zKua1jJYQN?&=7hA8q$A0zR@vW%a|Ati682nC)dcm-Q_8 zzP%^+D{X>Q5f)2D&6jE7*$AJ3UGb6mSp)2qK{k5*X5bn+U{b$9QDYtsu?8@*QzT@w*@8i)-v28|NP zx~Dhb@8^o#4bygy|C}MixQ*pyPv%4%;1i~?Zaf$I4V1EXsL3$eMmx!RyBV=POW zg>c>P`P6pLm#zHztk!feZhHEME0@(YeRHYme6{}a!a~}wUmPZXP?`_6-qXXmxjA!l z^WELu2>3|?z>U@rn`25f5cwoEqdsbQy?ObVH1thmO;r|sij{sRcZL_ z#f%`j!%sPV{fd_9v~41Ij(LFh>gnb6_wV02>1^kx8>`^Hjs1NhoT)eWz_X;>+#bsb z$``s?bF-=c4ClbwFRpqHwp-F%-1yW%kQ#aGA!0{#P1I<7EUwh3LfoOe+T-BEe7*J9 z86AeUz+92JOq}HA`3MmT$D^q>KYrln$ldTb>+h-5#~WAV8f3D)L?OtbYd*^dqQdz2 zlnku_yOI{aMb`W_jp;E$WQ}+;dF}c)G?a3ecL)F#Q6A}_A4L#yoDJw zBczua_@0Z8je9~xfa48z{5$z3Q$@%PRPN~(O44?DFdG}t56$%8&5VVkDpF<%+Kv8* zdoKPuy2hnw75dkhNIG14O@Quo0&5UcKFR0vhWTVV+}1R|_su6?zYic1Zj0Vi%`&yA zsVNS|G#(Zv28J-ZeWXrT{=3@K#zvk`5@fbbWT}$^l9H0(O>lU8E5F;3nxY~`N^&-k zx-=U=?YPk6-(yfC+ahOXVbMP!Ybu93)2&DmBSS};_uZBti)b$hxPNRdNt@6s(9dgW zZca0T5;!QKdF|p_g&84_)_gW)VL|7cP<#{FbBR}AM3y2i*d>#vpZ>9b7ykXUa^ zll6&Wm0lHScQP^qUY41OIdhg(BTjO!2<7V;8Nf+xqjeK#pN*R?qI|dw79voZ7SrPz zjH3wNHDYi;Pus-roi^eoZlnwjeR}dv%U!i+|MV$9nt+fn|08!oJ?pqLYBskK!C*Yq zU>4dv$t8+~MI~Z2vgyR>Y#^tfYlNq4$&3IM%H;9pYF=PXje{<{vYuXyLj(%o57WlE zYg;w1k$DWL4gGyk^ecy9=SE!FPhQ!NYMj$+U?iD%r|tnHs|DV>)YPveq*O%0uD?Es zOmEiI+qe?Oju+2sRUF5rFOEIOYf^}68>)_I4h5U$`vwPh{{EVv6%*WNOCqjET8li| z_z)Krg@%f1{7ry-K}%X1vGNlqC(d>ft1$WrayNX62@9HqwytipV?j3iWcGMM=w$CK z2@fg8o*h0DKHBKo;o)IfSy^9S-_PJX;)~Hkh4`a@4PgNRuakv3Es776x`^yBG*}8T zRsob@SX660{{FU1JMdx+)Ueq#6?BxLd3bIIPkzV;=|%M^rgh>$^ly}BkqEwl)U<5w z7oFPM-4E2a1)49GaYVAA7lkH14NJe%RiV4XV63jjyLsdm|3-SgYdL*4j1~G5Z+GLM z0|7v;TOQo@`(p>Ve%cDPnkfzq4==!$nVX&c!*f7>KMrCSTv=$a#8SnCM@2`sv9}M4 z>kUYdp}`LU%yTgK+%fG|w9Ju`st_|Z#GAvIL0aM}I$A1jaZ4s5QJe>+!xF5k#b75MAMD%9RyH$vG)QhCmo|mozaRR zQE_(z$5Z;V8XXeA?1xD1{>KEJdrG{KLW#g$3*O@|I_~m8t#U?d4+EnU3WYFifFO5z zHrFYf2Ar7y&{*K<0glI_fZmhON}8y@2pSF5;^Ly*2QpsUwN9@Fi?OJf7^!BLm8LS* zu_0B#mF(1Sx)AB9PyoO5tZwqo(@`rT)fV@Vd0Uexny@btY#P#GB2uIY!`#_2-K~t ztQ0ceBNYX}wKOj;;2))sCpP!#-RbgFcYC|{{&@DMKff#_?BCVj!%jLoJdrHl2O?$c zs_T3MA|75|3kwU0u%qMSO~gC|m)Z`=%>*{c+?jt5Lc7R0b@D$rNy#TnvJ)cWjmtuC zXs=SZ*alQeY`5r#4E-Oh?(;a1gDBPY{&NBH9T9)-QlSmupP~ZgPh4DF98t5@UudCK zx-Ii_bH-9MVGi6?+?L}zySshO2?IOvDRRG)lR?6xlyHHz@6oB<8qzA5?Sa4qUKn!d zd2M#u9xxwCX^Pesf+PDkHm2X^yxZ<}tfP~4ZbvNS>6qH`=-S41@4r8Nu;kH;*)PKp zuW4A%DJY18)&&IS<8C3xQ88NVl zF<-6K%URN&)2f`SzHIifUqBpSaTGPXx}} z+ZzX`Z#)1-5(& Date: Fri, 7 Jun 2019 18:45:30 -0700 Subject: [PATCH 0531/1504] Add a warning when trying to load 0.4.x projects --- CHANGELOG.md | 1 + server/src/project.rs | 24 ++++++++++++++++++++++-- test-projects/legacy/rojo.json | 4 ++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 test-projects/legacy/rojo.json diff --git a/CHANGELOG.md b/CHANGELOG.md index d9ab7b90..5c4a1a8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## [Unreleased] * Added support for live-syncing `CollectionService` tags. * Added a warning when building binary place files, since they're still experimental and have bugs. +* Added a warning when trying to use Rojo 0.5.x with a Rojo 0.4.x-only project. * Fixed plugin live-sync not ignoring unknown properties. ## [0.5.0 Alpha 11](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) diff --git a/server/src/project.rs b/server/src/project.rs index 346158ee..5d190d0b 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -439,8 +439,13 @@ impl Project { } pub fn load_fuzzy(fuzzy_project_location: &Path) -> Result { - let project_path = Self::locate(fuzzy_project_location) - .ok_or(ProjectLoadFuzzyError::NotFound)?; + let project_path = match Self::locate(fuzzy_project_location) { + Some(path) => path, + None => { + Project::warn_if_4x_project_present(fuzzy_project_location); + return Err(ProjectLoadFuzzyError::NotFound); + } + }; Self::load_exact(&project_path).map_err(From::from) } @@ -485,6 +490,21 @@ impl Project { } } + /// Issues a warning if no Rojo 0.5.x project is found, but there's a legacy + /// 0.4.x project in the directory. + fn warn_if_4x_project_present(folder: &Path) { + let file_path = folder.join("rojo.json"); + + if fs::metadata(file_path).is_ok() { + warn!("No Rojo 0.5 project file was found, but a Rojo 0.4 project was."); + warn!("Rojo 0.5.x uses 'default.project.json' files"); + warn!("Rojo 0.5.x uses 'rojo.json' files"); + warn!(""); + warn!("For help upgrading, see:"); + warn!("https://lpghatguy.github.io/rojo/guide/migrating-to-epiphany/"); + } + } + pub fn folder_location(&self) -> &Path { self.file_location.parent().unwrap() } diff --git a/test-projects/legacy/rojo.json b/test-projects/legacy/rojo.json new file mode 100644 index 00000000..547d3943 --- /dev/null +++ b/test-projects/legacy/rojo.json @@ -0,0 +1,4 @@ +{ + "name": "legacy", + "parittions": {} +} \ No newline at end of file From ba1826587cd052256b6ca59538be867611f36173 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 7 Jun 2019 20:45:59 -0700 Subject: [PATCH 0532/1504] docs: Add TypeScript section to 'Why Rojo?' --- docs/why-rojo.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/why-rojo.md b/docs/why-rojo.md index 290c6208..aac22acb 100644 --- a/docs/why-rojo.md +++ b/docs/why-rojo.md @@ -22,6 +22,13 @@ Hundreds of thousands of companies and individual developers use Git to version Using a repository hosting service like GitHub or GitLab brings powerful features to Roblox developers like code reviews and issue tracking that professional engineers can't live without. +## TypeScript +TypeScript enables static type safety, which helps prevent typos and adds unparalleled autocompletion. It also brings features like arrow functions, object destructuring, functional programming methods, and more! + +With Rojo, you can use [roblox-ts](https://roblox-ts.github.io) to compile TypeScript to Lua and take advantage of a huge ecosystem of TypeScript tooling. + +It's also possible to use other languages that compile to Lua like [MoonScript](https://moonscript.org) and [Haxe](https://haxe.org). + ## Other Tools There are decades of excellent tools available that operate on files. With Rojo, it's possible to take advantage of any of them! From 68a34dc28b2452bd57f39618f3a15657854d9ea1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 10 Jun 2019 16:46:05 -0700 Subject: [PATCH 0533/1504] Add a test project with unions --- test-projects/unions/default.project.json | 6 + test-projects/unions/src/two-parts.rbxmx | 357 ++++++++++++++++++++++ 2 files changed, 363 insertions(+) create mode 100644 test-projects/unions/default.project.json create mode 100644 test-projects/unions/src/two-parts.rbxmx diff --git a/test-projects/unions/default.project.json b/test-projects/unions/default.project.json new file mode 100644 index 00000000..652e43e6 --- /dev/null +++ b/test-projects/unions/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "unions", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/test-projects/unions/src/two-parts.rbxmx b/test-projects/unions/src/two-parts.rbxmx new file mode 100644 index 00000000..375bf986 --- /dev/null +++ b/test-projects/unions/src/two-parts.rbxmx @@ -0,0 +1,357 @@ + + true + null + nil + + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -5.5 + 1.00000095 + -10.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + + 0 + 4288914085 + + false + + 3 + -0.5 + 0.5 + 0 + 0 + + 5 + 2 + 3 + + -0.5 + 0.5 + 0 + 0 + false + false + 256 + + Union + MpkZJVsLUKCPlqSHCAWUqw== + + 0 + 1 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + false + + 0 + 0 + 0 + + + 5 + 2 + 3 + + + + + Q1NHUEhTBgAAAI4mRUFT5Hi8ReB1vToHcL0i+nRBg+FvwAg5dcDGrAZCL4ppwKxM7kEQAAAA +AAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAIA/DAAAAAQAAAAAACBAAAAAAAAA +QD8AAPA/AAAAAAAAQD8AACBAAAAAAAAAAAAAAPA/AAAAAAAAAAAMAAAAAAAAAAEAAAADAAAA +AAAAAAMAAAACAAAAAAAAAAIAAAADAAAAAAAAAAMAAAABAAAAEAAAAAAAAAAAAAAAAAAAAAAA +AAAQAAAAAAAAAAAAAAAAAAAAAACAPwwAAAAEAAAAAAAAAAAAAAAAAEA/AAAAAAAAAAAAAMA/ +AACgPwAAAAAAAEA/AACgPwAAAAAAAMA/DAAAAAAAAAABAAAAAwAAAAAAAAADAAAAAgAAAAAA +AAACAAAAAwAAAAAAAAADAAAAAQAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAA +AAAAAAAAgD8PAAAABAAAAAAAoL8AAAAAAADAPzP/v78AAIAzAADAPwAAwL8AAAAAAADAPwAA +oL8AAAAAAABAPwAAwL8AAAAAAABAPxIAAAAAAAAAAQAAAAIAAAAAAAAAAgAAAAQAAAAAAAAA +BAAAAAMAAAAAAAAAAwAAAAEAAAABAAAAAwAAAAQAAAABAAAABAAAAAIAAAAQAAAAAAAAAAAA +AAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAIA/DwAAAAQAAAAAAPA/AAAAAAAAAL8AAPA/ +AAAAAAAAAAAAACBAAACAMwAAAAAAACBAAAAAAAAAAL/NAABAAAAAAAAAAAASAAAAAAAAAAEA +AAACAAAAAAAAAAIAAAADAAAAAAAAAAMAAAAEAAAAAAAAAAQAAAABAAAAAQAAAAQAAAACAAAA +AgAAAAQAAAADAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAACAPw8A +AAAEAAAAAACgvwAAAAAAAEA/AACgvwAAAAAAAMA//vufvwAAgDMAAMA/AAAAAAAAAAAAAEA/ +AAAAAAAAAAAAAMA/EgAAAAAAAAABAAAAAgAAAAAAAAACAAAAAwAAAAAAAAADAAAABAAAAAAA +AAAEAAAAAQAAAAEAAAAEAAAAAgAAAAIAAAAEAAAAAwAAABAAAAAAAAAAAAAAAAAAAAAAAAAA +EAAAAAAAAAAAAAAAAAAAAAAAgD8PAAAABAAAAAAAoD8AAAAAAABAPwAAoD8AAAAAAADAPwAA +IEAAAIAzMPu/PwAAIEAAAAAAAABAPwAAIEAAAAAAAADAPxIAAAAAAAAAAQAAAAIAAAAAAAAA +AgAAAAMAAAAAAAAAAwAAAAQAAAAAAAAABAAAAAEAAAABAAAABAAAAAIAAAACAAAABAAAAAMA +AAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAIA/GAAAAAQAAAAAAKC/ +AACAPwAAAAAAAMC/AACAPwAAAAAAAMC/AAAAPwAAAAAAAMC/AEDNOABATbgAAKC/AEDNOAAA +AL8AAKC/AACAPwAAAL8AAMC/AACAPwAAAL8AAMC/AEDNOAAAAL8kAAAAAAAAAAEAAAACAAAA +AAAAAAIAAAADAAAAAAAAAAMAAAAEAAAAAAAAAAQAAAAFAAAAAAAAAAUAAAAGAAAAAAAAAAYA +AAABAAAAAQAAAAYAAAAHAAAAAQAAAAcAAAADAAAAAQAAAAMAAAACAAAAAwAAAAcAAAAEAAAA +BAAAAAcAAAAGAAAABAAAAAYAAAAFAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAA +AAAAAAAAAACAPxgAAAAEAAAAAADAPwAAAAAAAEC/AACgPwAAAAAAAEC/AADAP///f78AAEC/ +AADAPwAAAAAAAMC/AACgPwAAAAAAAMC/AACgP///f78AAEC/AADAP///f78AAMC/AACgP/// +f78AAMC/JAAAAAAAAAABAAAABQAAAAAAAAAFAAAAAgAAAAAAAAACAAAABgAAAAAAAAAGAAAA +AwAAAAAAAAADAAAABAAAAAAAAAAEAAAAAQAAAAEAAAAEAAAABwAAAAEAAAAHAAAABQAAAAIA +AAAFAAAABwAAAAIAAAAHAAAABgAAAAMAAAAGAAAABwAAAAMAAAAHAAAABAAAABAAAAAAAAAA +AAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAgD8YAAAABAAAAAAAID8AAAAAAABAPwAA +AAAAAAAAAABAPwAAID///3+/lvn/PgAAID8AAAAAlvn/PgAAAAAAAAAAlvn/PgAAAAD//3+/ +lvn/PgAAID///3+/AAAAAAAAAAD//3+/AAAAACQAAAAAAAAAAQAAAAUAAAAAAAAABQAAAAIA +AAAAAAAAAgAAAAYAAAAAAAAABgAAAAMAAAAAAAAAAwAAAAQAAAAAAAAABAAAAAEAAAABAAAA +BAAAAAcAAAABAAAABwAAAAUAAAACAAAABQAAAAcAAAACAAAABwAAAAYAAAADAAAABgAAAAcA +AAADAAAABwAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAIA/ +GAAAAAQAAAAAACC/AAAAAAAAQD8AAKC/AAAAAAAAQD8AACC///9/v5b5/z4AACC/AAAAAJb5 +/z4AAKC/AAAAAJb5/z4AAKC///9/v5b5/z4AACC///9/vwAAAAAAAKC///9/vwAAAAAkAAAA +AAAAAAEAAAAFAAAAAAAAAAUAAAACAAAAAAAAAAIAAAAGAAAAAAAAAAYAAAADAAAAAAAAAAMA +AAAEAAAAAAAAAAQAAAABAAAAAQAAAAQAAAAHAAAAAQAAAAcAAAAFAAAAAgAAAAUAAAAHAAAA +AgAAAAcAAAAGAAAAAwAAAAYAAAAHAAAAAwAAAAcAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAA +AAAQAAAAAAAAAAAAAAAAAAAAAACAPxgAAAAEAAAAAAAAAAAAAAAAAEA/AAAgvwAAAAAAAEA/ +AAAAAP//f7+W+f8+AAAAAAAAAACW+f8+AAAgvwAAAACW+f8+AAAgv///f7+W+f8+AAAAAP// +f78AAAAAAAAgv///f78AAAAAJAAAAAAAAAABAAAABQAAAAAAAAAFAAAAAgAAAAAAAAACAAAA +BgAAAAAAAAAGAAAAAwAAAAAAAAADAAAABAAAAAAAAAAEAAAAAQAAAAEAAAAEAAAABwAAAAEA +AAAHAAAABQAAAAIAAAAFAAAABwAAAAIAAAAHAAAABgAAAAMAAAAGAAAABwAAAAMAAAAHAAAA +BAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAgD8YAAAABAAAAAAA +oD8AAAAAAABAPwAAID8AAAAAAABAPwAAoD///3+/lvn/PgAAoD8AAAAAlvn/PgAAID8AAAAA +lvn/PgAAID///3+/lvn/PgAAoD///3+/AAAAAAAAID///3+/AAAAACQAAAAAAAAAAQAAAAUA +AAAAAAAABQAAAAIAAAAAAAAAAgAAAAYAAAAAAAAABgAAAAMAAAAAAAAAAwAAAAQAAAAAAAAA +BAAAAAEAAAABAAAABAAAAAcAAAABAAAABwAAAAUAAAACAAAABQAAAAcAAAACAAAABwAAAAYA +AAADAAAABgAAAAcAAAADAAAABwAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAA +AAAAAAAAAAAAAIA/GwAAAAQAAAAAAPA/AAAAAAAAQD8AAKA/AAAAAAAAQD81A8A///9/v5b5 +/z4AAPA/AAAAAAAAAAAAAKA/AAAAAJb5/z4AAKA///9/v5b5/z41A8A///9/vwAAAAA1A8A/ +AAAAAAAAAAAAAKA///9/vwAAAAAqAAAAAAAAAAEAAAAFAAAAAAAAAAUAAAACAAAAAAAAAAIA +AAAGAAAAAAAAAAYAAAADAAAAAAAAAAMAAAAHAAAAAAAAAAcAAAAEAAAAAAAAAAQAAAABAAAA +AQAAAAQAAAAIAAAAAQAAAAgAAAAFAAAAAgAAAAUAAAAIAAAAAgAAAAgAAAAGAAAAAwAAAAYA +AAAIAAAAAwAAAAgAAAAHAAAABAAAAAcAAAAIAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAA +AAAAAAAAAAAAAAAAAACAPyEAAAAEAAAAAADwPwAgzbgAAAAANQPAPwAAgDOW+f++NQPAPwAg +zbgAAAAANQPAP///f78AAAAAAADwPwAgzbiW+f++NQPAPwAgzbgAAEC/AACgPwAgzbgAAEC/ +AACgPwAgzbiW+f++AACgP///f78AAAAANQPAP///f78AAEC/AACgP///f78AAEC/NgAAAAAA +AAABAAAAAgAAAAAAAAACAAAACAAAAAAAAAAIAAAAAwAAAAAAAAADAAAACQAAAAAAAAAJAAAA +BAAAAAAAAAAEAAAAAQAAAAEAAAAEAAAABQAAAAEAAAAFAAAABgAAAAEAAAAGAAAABwAAAAEA +AAAHAAAAAgAAAAIAAAAHAAAACAAAAAMAAAAIAAAACgAAAAMAAAAKAAAACQAAAAQAAAAJAAAA +BQAAAAUAAAAJAAAACgAAAAUAAAAKAAAABgAAAAYAAAAKAAAACAAAAAYAAAAIAAAABwAAABAA +AAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAgD8YAAAABAAAAAAAIMD//3+/ +AAAAAAAAIMD//3+/AAAAPwAAIMAAAAAAAAAAAAAA8L///3+/AAAAAAAA8L///3+/AAAAPwAA +IMAAAAAAAAAAPwAA8L8AAAAAAAAAAAAA8L8AAAAAAAAAPyQAAAAAAAAAAQAAAAUAAAAAAAAA +BQAAAAIAAAAAAAAAAgAAAAYAAAAAAAAABgAAAAMAAAAAAAAAAwAAAAQAAAAAAAAABAAAAAEA +AAABAAAABAAAAAcAAAABAAAABwAAAAUAAAACAAAABQAAAAcAAAACAAAABwAAAAYAAAADAAAA +BgAAAAcAAAADAAAABwAAAAQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAA +AAAAAIA/FQAAAAQAAAAAAMC/AEDNOAAAAAAAAKC/AACAPwAAAAAAAKC/AEDNOAAAwD8AAMC/ +AEDNOAAAwD8AAMC/AACAPwAAAAAAAKC/AACAPwAAwD8AAMC/AACAPwAAwD8eAAAAAAAAAAEA +AAACAAAAAAAAAAIAAAADAAAAAAAAAAMAAAAGAAAAAAAAAAYAAAAEAAAAAAAAAAQAAAABAAAA +AQAAAAQAAAAGAAAAAQAAAAYAAAAFAAAAAQAAAAUAAAACAAAAAgAAAAUAAAAGAAAAAgAAAAYA +AAADAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAACAPxIAAAAEAAAA +AACgPwAAgD8AAAAAAACgPwAAgD8AAAC/AAAAAAAAgD8AAAAAAACgPwBAzTgAAAC/AAAAAAAA +gD8AAAC/AAAAAABAzTgAAAC/GAAAAAAAAAABAAAABAAAAAAAAAAEAAAAAgAAAAAAAAACAAAA +BQAAAAAAAAAFAAAAAwAAAAAAAAADAAAAAQAAAAEAAAADAAAABQAAAAEAAAAFAAAABAAAAAIA +AAAEAAAABQAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAgD8SAAAA +BAAAAAAAAAAAAIA/AAAAAAAAAAAAAIA/AAAAvwAAoL8AAIA/AAAAAAAAAAAAQM04AAAAvwAA +oL8AAIA/AAAAvwAAoL8AQM04AAAAvxgAAAAAAAAAAQAAAAQAAAAAAAAABAAAAAIAAAAAAAAA +AgAAAAUAAAAAAAAABQAAAAMAAAAAAAAAAwAAAAEAAAABAAAAAwAAAAUAAAABAAAABQAAAAQA +AAACAAAABAAAAAUAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAIA/ +IQAAAAQAAAAAAKC/ACDNuAAAQD81A8C/AACAM5b5/z41A8C/ACDNuAAAQD8AAKC///9/v5b5 +/z4AAKC/ACDNuJb5/z41A8C/ACDNuAAAAAAAAPC/ACDNuAAAAAAAAPC/ACDNuJb5/z4AAPC/ +//9/v5b5/z4AAKC///9/vwAAAAAAAPC///9/vwAAAAA2AAAAAAAAAAEAAAACAAAAAAAAAAIA +AAAIAAAAAAAAAAgAAAADAAAAAAAAAAMAAAAJAAAAAAAAAAkAAAAEAAAAAAAAAAQAAAABAAAA +AQAAAAQAAAAFAAAAAQAAAAUAAAAGAAAAAQAAAAYAAAAHAAAAAQAAAAcAAAACAAAAAgAAAAcA +AAAIAAAAAwAAAAgAAAAKAAAAAwAAAAoAAAAJAAAABAAAAAkAAAAFAAAABQAAAAkAAAAKAAAA +BQAAAAoAAAAGAAAABgAAAAoAAAAIAAAABgAAAAgAAAAHAAAAEAAAAAAAAAAAAAAAAAAAAAAA +AAAQAAAAAAAAAAAAAAAAAAAAAACAPxUAAAAEAAAAAAAgQAAAgD8AAAAAAAAgQAAAgD8AAAC/ +AACgPwAAgD8AAAAAAAAgQABAzTgAAAAAAAAgQABAzTgAAAC/AACgPwAAgD8AAAC/AACgPwBA +zTgAAAC/HgAAAAAAAAABAAAABQAAAAAAAAAFAAAAAgAAAAAAAAACAAAAAwAAAAAAAAADAAAA +BAAAAAAAAAAEAAAAAQAAAAEAAAAEAAAABgAAAAEAAAAGAAAABQAAAAIAAAAFAAAABgAAAAIA +AAAGAAAAAwAAAAMAAAAGAAAABAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAA +AAAAAAAAgD8VAAAABAAAAAAAoD8AAIA/AADAPwAAoD8AQM04AADAPwAAoD8AAIA/AAAAAAAA +AAAAAIA/AADAPwBQADkAQM04AADAPwAAAAAAAIA/AAAAAAAAAAAAAMA+AADAPx4AAAAAAAAA +AQAAAAIAAAAAAAAAAgAAAAUAAAAAAAAABQAAAAMAAAAAAAAAAwAAAAYAAAAAAAAABgAAAAQA +AAAAAAAABAAAAAEAAAABAAAABAAAAAUAAAABAAAABQAAAAIAAAADAAAABQAAAAYAAAAEAAAA +BgAAAAUAAAAQAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAIA/EgAAAAQA +AAAAAAAAAACAPwAAwD8AAAAAAEDNOAAAwD8AAAAAAACAPwAAAAAAAKC/AACAPwAAwD8AAKC/ +AEDNOAAAwD8AAKC/AACAPwAAAAAYAAAAAAAAAAEAAAACAAAAAAAAAAIAAAAFAAAAAAAAAAUA +AAADAAAAAAAAAAMAAAAEAAAAAAAAAAQAAAABAAAAAQAAAAQAAAAFAAAAAQAAAAUAAAACAAAA +AwAAAAUAAAAEAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAACAPxgA +AAAEAAAAAAAAAP//f78AAAAAAAAAAAAAgDNqBgC/AACgv///f78AAAAAAAAAAP//f78AAMC/ +AACgvwAgzbhqBgC/AAAAAAAgzbgAAMC/AACgvwAgzbgAAMC/AACgv///f78AAMC/JAAAAAAA +AAABAAAAAgAAAAAAAAACAAAABwAAAAAAAAAHAAAAAwAAAAAAAAADAAAABQAAAAAAAAAFAAAA +AQAAAAEAAAAEAAAAAgAAAAEAAAAFAAAABgAAAAEAAAAGAAAABAAAAAIAAAAEAAAABgAAAAIA +AAAGAAAABwAAAAMAAAAHAAAABgAAAAMAAAAGAAAABQAAABAAAAAAAAAAAAAAAAAAAAAAAAAA +EAAAAAAAAAAAAAAAAAAAAAAAgD8bAAAABAAAAAAAoD///3+/AAAAAAAAAAD//3+/AAAAAAAA +oD///3+/AADAvwAAoD8AAIAzagYAv/77nz8AAIAzagYAvwAAAAAAIM24agYAvwAAAAD//3+/ +AADAvwAAoD8AIM24AADAvwAAAAAAIM24AADAvyoAAAAAAAAAAQAAAAYAAAAAAAAABgAAAAIA +AAAAAAAAAgAAAAcAAAAAAAAABwAAAAMAAAAAAAAAAwAAAAQAAAAAAAAABAAAAAEAAAABAAAA +BAAAAAUAAAABAAAABQAAAAgAAAABAAAACAAAAAYAAAACAAAABgAAAAgAAAACAAAACAAAAAcA +AAADAAAABwAAAAgAAAADAAAACAAAAAQAAAAEAAAACAAAAAUAAAAQAAAAAAAAAAAAAAAAAAAA +AAAAABAAAAAAAAAAAAAAAAAAAAAAAIA/GAAAAAQAAAAAACBAAACAPwAAwD8AACBAAEDNOAAA +wD8AACBAAACAPwAAAAAAAKA/AACAPwAAwD8CBKA/AEDNOAAAwD8AACBAAEDNOAAAAAAAAKA/ +AACAPwAAAAAAAKA/AAAAPwAAwD8kAAAAAAAAAAEAAAAFAAAAAAAAAAUAAAACAAAAAAAAAAIA +AAAGAAAAAAAAAAYAAAADAAAAAAAAAAMAAAAHAAAAAAAAAAcAAAAEAAAAAAAAAAQAAAABAAAA +AQAAAAQAAAAFAAAAAgAAAAUAAAAGAAAAAwAAAAYAAAAHAAAABAAAAAcAAAAGAAAABAAAAAYA +AAAFAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAACAPxsAAAAEAAAA +AACgv///f78AAAAANQPAvwAgzbgAAAAAAAAgwP//f78AAAAAAACgv///f78AAMC/AACgvwAA +gDNqBgC/AAAgwAAgzbgAAAAAAAAgwP//f78AAMC/AACgvwAgzbgAAMC/AAAgwAAgzbgAAMC/ +KgAAAAAAAAABAAAABQAAAAAAAAAFAAAAAgAAAAAAAAACAAAABgAAAAAAAAAGAAAAAwAAAAAA +AAADAAAABwAAAAAAAAAHAAAABAAAAAAAAAAEAAAAAQAAAAEAAAAEAAAABQAAAAIAAAAFAAAA +CAAAAAIAAAAIAAAABgAAAAMAAAAGAAAACAAAAAMAAAAIAAAABwAAAAQAAAAHAAAACAAAAAQA +AAAIAAAABQAAAA== + + \ No newline at end of file From 4459663510997d834247dc18a6f24b73a0d0bd75 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 10 Jun 2019 17:26:34 -0700 Subject: [PATCH 0534/1504] Upgrade rbx-dom dependencies --- Cargo.lock | 34 +++++++++++++++++++++------------- server/Cargo.toml | 8 ++++---- 2 files changed, 25 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a74e53c1..dd27e467 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -641,6 +641,11 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "md5" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "memchr" version = "2.2.0" @@ -1117,15 +1122,17 @@ dependencies = [ "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_dom_weak" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1133,24 +1140,24 @@ dependencies = [ [[package]] name = "rbx_reflection" -version = "3.1.384" +version = "3.1.388" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_xml" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.1.384 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.1.388 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1285,9 +1292,9 @@ dependencies = [ "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.1.384 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.1.388 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1941,6 +1948,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e6bcd6433cff03a4bfc3d9834d504467db1f1cf6d0ea765d37d330249ed629d" "checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" @@ -1992,9 +2000,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81428c521a07a3feac9c31180a886e467eecf81b769987f70d51d567a09c321d" -"checksum rbx_dom_weak 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e9582ea95ea28d99bea189b90eab04a34ab6e9d04f295ccb46eb997b87754030" -"checksum rbx_reflection 3.1.384 (registry+https://github.com/rust-lang/crates.io-index)" = "1209361806b9238226f1f8427bab9b5171ec13b3bf2dffdd2f97a96bb641164c" -"checksum rbx_xml 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cb23d19c983457fa6c65803190a23b2c4b9d08290f3431528adb9b74ab3488da" +"checksum rbx_dom_weak 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08ae7950cd5c252ae9596aac109ab7bfd12018d28d02afb8db1e39098769413b" +"checksum rbx_reflection 3.1.388 (registry+https://github.com/rust-lang/crates.io-index)" = "715007d1aa2401570e5778fd628c30e89a7e5251ae3324caf2c5a4033c7f4539" +"checksum rbx_xml 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f6df95f079a20ccdfc3a59bf119afa2ef48155a909e7afceea4a9f2122c164f" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" diff --git a/server/Cargo.toml b/server/Cargo.toml index 442923ad..7444835a 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -29,10 +29,10 @@ hyper = "0.12" log = "0.4" maplit = "1.0.1" notify = "4.0" -rbx_binary = "0.4.0" -rbx_dom_weak = "1.7.0" -rbx_xml = "0.9.0" -rbx_reflection = "3.0.384" +rbx_binary = "0.4.1" +rbx_dom_weak = "1.8.0" +rbx_xml = "0.10.0" +rbx_reflection = "3.1.388" regex = "1.0" reqwest = "0.9.5" rlua = "0.16" From bf706f7586126e8730d33a70d260794763a10ef6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 10 Jun 2019 17:29:03 -0700 Subject: [PATCH 0535/1504] plugin: Upgrade Roact and rbx-dom --- plugin/modules/rbx-dom | 2 +- plugin/modules/roact | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index 77b7e79f..d7be961e 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit 77b7e79ff6e9973ca1a603c37622ce4ce05c7e24 +Subproject commit d7be961eb387c3fdaf6817cca2866909758fc7c4 diff --git a/plugin/modules/roact b/plugin/modules/roact index 2fb60ea6..b1db3f82 160000 --- a/plugin/modules/roact +++ b/plugin/modules/roact @@ -1 +1 @@ -Subproject commit 2fb60ea648caafb155f5f0363cec7a8149c8e8fc +Subproject commit b1db3f82a2510c4e5e5b2bdc2c47298ea02dabd8 From abb5a72fc4feb537799b91d85a5a9fe1b055e3af Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 10 Jun 2019 17:47:04 -0700 Subject: [PATCH 0536/1504] Update Changelog --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c4a1a8b..dd82acc9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,15 @@ # Rojo Changelog ## [Unreleased] +* Added support for infinite and NaN values in types like `Vector2` when building models and places. + * These types aren't supported for live-syncing yet due to limitations around JSON encoding. +* Added support for using `SharedString` values when building XML models and places. * Added support for live-syncing `CollectionService` tags. * Added a warning when building binary place files, since they're still experimental and have bugs. * Added a warning when trying to use Rojo 0.5.x with a Rojo 0.4.x-only project. -* Fixed plugin live-sync not ignoring unknown properties. +* Changed plugin to ignore unknown properties when live-syncing. + * Rojo's approach this problem might change later, like with a strict model mode ([#190](https://github.com/LPGhatguy/rojo/issues/190)) or another approach. +* Upgraded to reflection database from client release 388. ## [0.5.0 Alpha 11](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) * Added support for implicit property values in JSON model files ([#154](https://github.com/LPGhatguy/rojo/pull/154)) From 1b0beccd3df594c3624ab4a752ef2503f3e49b18 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 10 Jun 2019 17:52:44 -0700 Subject: [PATCH 0537/1504] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index dd82acc9..23c45eca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## [Unreleased] +* Added `init.meta.json` files, which replace `init.model.json` files from Rojo 0.4.x ([#183](https://github.com/LPGhatguy/rojo/pull/183)) * Added support for infinite and NaN values in types like `Vector2` when building models and places. * These types aren't supported for live-syncing yet due to limitations around JSON encoding. * Added support for using `SharedString` values when building XML models and places. From 2e89cdcfadbcad167366a2f338fd6cb241bff3d4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 10 Jun 2019 18:05:10 -0700 Subject: [PATCH 0538/1504] Fix malformed Enum being emitted when using Project::save --- server/src/project.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/server/src/project.rs b/server/src/project.rs index 5d190d0b..87361dd4 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -88,7 +88,6 @@ fn serialize_unresolved_minimal(unresolved: &UnresolvedRbxValue, serializer: RbxValue::Color3 { value } => value.serialize(serializer), RbxValue::Color3uint8 { value } => value.serialize(serializer), RbxValue::Content { value } => value.serialize(serializer), - RbxValue::Enum { value } => value.serialize(serializer), RbxValue::Float32 { value } => value.serialize(serializer), RbxValue::Int32 { value } => value.serialize(serializer), RbxValue::String { value } => value.serialize(serializer), From 1eb11ac377abb5127c7df53e787b9051207f6f41 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 11 Jun 2019 15:00:09 -0700 Subject: [PATCH 0539/1504] Add R logo icons --- assets/rojo-r-black.png | Bin 0 -> 559 bytes assets/rojo-r-light-gray.png | Bin 0 -> 986 bytes assets/rojo-r.png | Bin 0 -> 1001 bytes 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/rojo-r-black.png create mode 100644 assets/rojo-r-light-gray.png create mode 100644 assets/rojo-r.png diff --git a/assets/rojo-r-black.png b/assets/rojo-r-black.png new file mode 100644 index 0000000000000000000000000000000000000000..3b417db155efe0f027e711a9648d0b5f83ac77c4 GIT binary patch literal 559 zcmV+~0?_@5P)+9>x?C;fWv$&kv^W4_f)`_k3{?k6c+Iq6}To2dh zab@niW&PN*wm!_~vM)v6`=%qY0)wStqXH_aRa^S~aWwmFA@M^d=$XAIp#o~caOk{9 zaJ_v0w&$@#_{v0lZ^~40@|7bxs_N;hGDi!W?7+O}`JFAQ=6MlRUki354qdFE_P3?# z6o+@70a(ddG%bv8v%vtAds9*61jv82Rl^hD0Z_3I9BnRuR=?)nm*`Oe=IEzwJwk16 ziS}RV-v*TflJ~3FOM(9Tpz1WXt0X5#w4>$D1$wRm{udBv^Z-yaBSj(=+$w5UwAz2b z&=P+*0R+D(rt?o?uL*un7m+CdqGOnfnS|9;UP2z7@zdy5ASyr=;}pt$(9&fDFjK_` zkmyzuwFI3^(Sr(*-sd);G@j8RHQcJw!NL^eE};PLI{zbtkpR_?`7Z%MBj{+zdhT=p z!C$xL#1QW}w7NDdt&H8T#Y#W`gs_`*qL+(aDr-Q{2|ig?yuezkj~GIX(M?I?{}F8x x7k^}}VcZeWf$AiEPscm0pKhL&wAUn-H^1tPJjB*mb@KoK002ovPDHLkV1kcO0(k%c literal 0 HcmV?d00001 diff --git a/assets/rojo-r-light-gray.png b/assets/rojo-r-light-gray.png new file mode 100644 index 0000000000000000000000000000000000000000..8479b957cd84a3cb0fdcc1f06a3a6fa78b656b0c GIT binary patch literal 986 zcmV<0110>4P)V`8Szlj&K|kN$-!E)zY`kAvTg$JnufO)o zC*OxEEr`eCiLtS<=fu?3)}HZ84w&ib>BlxeJOK<042%p9503{aEP?g+_uo>iyz>Lh z`;#K`0kT3UM3)6;XWrl#gpkR&ojfj+&uy86m`?a5j7mLNOZb^4`c0LC!<`!4QLw0T!=L}^qO7|+X zy}kX(e1{l=f~w-omDncO_1xUtgi`)>Tj6o$W9*%#jUNakE5fb5A?#0j*i=A zLcn>cnr@+8&3HT^CuOeSB*;<;Qd6BK}J+~(%y4^!0?l7XmS z#wi2Zvn}k1(EO0t)ByCmIU8LgwW64Ocx(V|ZEY3l=RG@bZf?G+iviNc{Y;Q$AJ7lG zy1IJ31jW6ONF*Lffl}N?`R4k+?gGx<3{baV$m?F9-v2EfEyX#rgT8~D8!TR{rSn6eR(*wnz()Rg0RUV|xuOsCTTvL3}v5M>6W z05KSPy|uOVEL|Xx!@|PC0>1_J15nxSQ$4!LA{bOAlbKDW zQj<0SoUxo8m?nhLNT*W;enEFWpU+ZEX{N;-+xeRu*mhlA-MK=c@P##gV4NdhEHeX3 zrP4RAg@9w191SxhV9Z#=%8kj<(7tZNj2Z7Rz*MYIpVu!q^GZ{&jw5Dqaq$`7B_lkG zL?Y4d?(VxVjH9ZJeV42_8ZfV5)a^Ew`%$Tn60b0a6}gW5+S+*+(&ExLp+b8tNU=&W znJ}R>QX@4pYnc#} z@)u}KCA4NH)XYp7VL;6oc+`lAmIRfEw(+XB@9Vw$+UNA%+k4vD$;r7ncki{nwbr*D zyM_#_1-9#H56=WV8HbT)a6N;V#MYWh2b*E@B#a$~Ypu}H0Qxj{eTB(Uxbgrlcz+f! z6#?|Z-Sx7%oZ_@1D<6a{SpY06wK)f!J#c3O>{t%cU)?g$wUEmalDf3$Zn)eIGCsK^ zblA@nyo~>m!q#2TXR!Xh4GvZZH@_e>`D zE3nlvV?@74b0VP?eu9ZcXi3LC4aS@at`|Y>W${9t-Dl9=m-pmIpa=x?vx@a2xi9S8#g;{8+6L z|3`dLTF!Plvt0%2$U@y7pPK`qAEYb4eoOgJ)gv*rL9wcLNN&L?0TAbwW+ga~CZJqC z^9`ouf#z`)BaJ;r7sB*PP!j;$TI0>1;e!?1V!xNh=A@KF9dJpG|6U1Ao&o-sa_dR} zNQb};M)TmXXTm_trS?Jsz?xJDf--f?Zf8d)oL*`GiJ9;K3 Date: Tue, 11 Jun 2019 15:00:21 -0700 Subject: [PATCH 0540/1504] Add a square Rojo logo with transparent background --- assets/rojo-logo-square.png | Bin 0 -> 42801 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 assets/rojo-logo-square.png diff --git a/assets/rojo-logo-square.png b/assets/rojo-logo-square.png new file mode 100644 index 0000000000000000000000000000000000000000..57a339f47ae51fa6b4a932c7f5893bed69e06e3c GIT binary patch literal 42801 zcmeEtWm6nX&|q+PUEEpR-QC^Yo#5{7?(P~09v}pFCrHo)SlkzP*n8gh{>9Z*P1jV< zhncRnYMXd30bm!^4=)Bg}y zI|&tuFJD?yQQj@!{=<>nxP&)a(_8F==>{`h-sFJ3|g@c*y>7dXIK!;$;NC4`7HmwF-& zL0kh@#-A8IJ1VjCDqmhLKdvK-+0Vm-U8%tQz(v9&nB$%Jmc8MEx3S};hy=+Kuq%Rx zxU;%2kXV@@rGabXW$}rDT(f@7<~CH~I%Fy>Auq1EV?^^#FXB`M|J% zlQT)BmHkG9pv{zj%*RN{@5OyWRe@Bx>1P#v`mT~cIVImWm% z@?JiAl4Quy4S)?pgD75d$kq8+P5`p4wosM#r1%{8y|-!i1xr-j5ju7lvAH3#&l?Tg zEUUsauw26^qmi{ZtC#kp<;&+?otSDZd#M_faD11R|ESH4xQ&NzGo|uaYxV>ambB?j z#p4`w)Fb&9$u4i%FSoiMBIB!LnAzt?Fzk^15iHG-h3A7naS3GP<8r!R#| ze#IJ|XbN!?wm`<0$%9Gps^3Y}J+;mLFAGQS4+{+Ci(i8?rB#ogKrH#Jg(HEzauho3EU>uyVE zgbu|CRK*d6YaG!WN&IrpJF)>ha?e-v(Do+o#6(1giR){wV?Fq^CD0`wX472Uk@GFke@JjU^GOr zBiWH5*^XRD+sN|CwsN*8-jxALy2ow3yhvo|WJ{s19#w}6^*2X7==AyHS82T13Lw4U z)s!|WoHnWq2OOw|9#n7?lRpQpqbc&roR*yTpH$yy^6=!I{7nSEkHwf`) zFN=89$he}mg}5LbAh$m;l9>&ohyO5Z9YFhn>W98iFO&of-G2m1V*HIbn-k7G7u6Um z2Tmiw@JQIQ{?$qpe5JNDm8KNdVnD3NB_WI9<`~P4Vt!fFkxkL{XE24sgTFdXm#7|m z=5Gg(GsdhddkSpINL`Ok#9G~yO|0;UKD-x#-_Z}Bu3)PC8`OF}%PWA>`eXVL7fDEQ z-T0OY`(O0|zxCxE8 zP3!kc91+TBEV=&?StZ;#<3aTS1xpYCI;;)tnsc|^WL=FVW884cXWUc}EAM@Fn`+F! zcufCoiBj~&7AA&eCfr*;l6^oE?Dw~MXhXkdGsOye?(cXq0C$h@8$Ig4MO1g-?goiC z{~W?TJTlPWoh`Doby0;BnOatFquQgf(ySt$NJ6laIG;j=w`dwT{L~cgbZAwVR=tey zoqf+ff+>MhyZZ>bA6hx3u?k`6ynEM!O?LC1O5g5xW}XQ8)oDGu4UhhY+FlEkomlpm zfbc+sT#yRA#GwwtLs%aa`>6=ODP00-wAL|2N2%&~I3m^C+`655j&c`5kAaq%y(};x z164YQ@OUf-)fW$cI6ECdttPx~4F(df2ioW(*^<27jh0{N`?8U!B7J&ub4Efe!sY-nSuGHJRa!;o)xu+13pvMB6#Wi?{Y7AAZjvckZ(ugd(4 zjdG17pc_8q04c{0@+?QRCzZ&cN2?R#!HJ+pCXD6}4rDK?jr1B%#7R}3 zt#F{B3$UA69GI20t(V03aD~M+0BnMIEaCzfGzc@4a?ypkn`6F9Ushad6)qexlt|x z7LZSwJMpruf2?I3d1Vd`GY+22Da=|b`==&j^b4yW+sAxUcGjFFd!Dovj0xFE`718)WKzm_hY%D#U5rb(z3xkspU z5mG7ZUrlhd4&2|erPYe;0S!QUT)0-AeB)&$^TT7RkEuX)-K`fL-=tG*Omgw5=u_g;UZYHWXdCF7oGvg2 z7idW6bLRrP)|d2Z($@Rqf?Na973Al~H8FIXHE4HJ@^z48!irZU-XGT%2X)=$3_W`h5n<0@s>cU)oSV)U1QbI&S z7>xSS>5^$m9rLc(?(9C*k=C4S_<#5Ij(owa4jQh6Q`dM+eKV|LGl{w%%X+wD=vJ-x zDOUPqQ;#ZfrbC>{emEY9YGu)ayZCkAuKE)<0gk}K@x=St%G(=aMXTnL#_Vnc89bm zW8Cm$oVDNKIwvWT_Dz!6Jfw7Z-`KW}`GM4xEFtt!RwPxfUi|7?RG%-j^GwV+3Gw(Z z23$6f?~Tc60F`NsDy;Pj8Y8?NN@ZX6+Mb3pn;bJ$lul8oe8 z_slfTV*g;y?|(lgahyaSdG|z%TYg9#Sc^%S0iKVX&fyTD+DF?m2jn9 zKah_8OcwYF2JvmSxRiC~4F|$pZrNK1itWlCq&5!+Sg|TbO10v?+(`EhGD_QSOv5rV z#{cYKRAY>BazUQ0n4e~S!&e&0LRL;}m0ONU9Zx$#Y~?(3wH}*Ui)`V$6n{IqaU1Xw zV%*=JG}`RVPNyZEER0@}S)=+;W=zn^AGyl|)4nU7DfBko>)2K4%j4kTMbB2IWvgC# zuvHw=y?^?wzq1mh#a6_rwwNn(nX_am;m7bjkKFpg!K3C|X-qnu!sb$T1owF|x1`=M z?%Rp%4)?*5!Y}vaB+|57Yp@wBPc5kPgM9jfM^={mT3P; zSza*SGHoDJO(5dkl`mSs3U^*f)K6C=c{3O=2{cO4tmnQ>;!I+;5CBU0Xh2bHA5@^~ z>v7JUppE9hq#g$j`>VybufaVzB3wF2*{=`p{L4*#Z2SH$VKCT)`(Het6`D82kwLLs}%~~L6a>Z0|R1hb(zSXOchU@ z`eB3kJ_Y{0XD~T!Y3HsyBn`M0&aDOqSS1j?{y3!N7J;y>Oxkyra~~KJP&fr~%-%5D z6^0}`0={tAp1O)yq zjMn@{hYE_8S~H5u&>Hh??%4gOAODzZD*FI2Mdsx&hbQ51qsWwyS*Om zC!|(icwpqpv^`*ra3keJ_C0Zz<$Zp=((vD%*>jRgZavv=1sdjmGiXt?>qIs46{?20i_H?q>d= z47Eq6Aej;$77BY3w21NbXR0vkN6Y@>QMvz_Ms*qc^OzER#&8`HvqsOcTft59{t*u& zBK>Ce2Qd_UT(>cI4nlm>aFNkn_39qbMP7(~Im=$rA23b6^;S!fpmwK0z9@U9xy@0H zI98&g5(`GwF%n`aCIpDj+o|7^1prFzMy+x3ISxO4_kL5=S0VMzg}t;yXCZ{7n0Qx{ z7RQbl{+qcQIcop4$^m>9VnPcg^_*3`5Q-hT$bau6-_9Yfaa9^9$8M z1R>a#pCvnmkNa~ga=tXfZoea4;}HxN?F|ySQYco7hemB%!#=($^Z$}``lMZkk{N_;(L`Z1LdEzW< z3jkZhNYTkp4@UIIaQe!e&4Yjyr9E(RC7_qI0J**!ohsv;*hW`&bbq?pw{7u#*PKcP zL(*|v7zc6^4OO|#?EIFaU*<0UP;;^Qdy6wbRMEKMY66OLBW4-M5HedOv$gcHew4SA zFs&7*((4kCs+Lv8ksIdfM7avir$R*}O|(q=Mmfs&)mScgGBQ)3H_&1>_UVM?n6` zxP`K#9X$kH!33=z$GGajh97fjJavS}tPOW?K;bFRPrq$u(J`zyt0 zv+ut;hKJ_No$YufEAlbV_LfrgBksV9C+y;uN_UC5zG}@=_5>I^8wR&?UJ9$5{2i63 zn#+F@4d7tl$A-+tZLYCy2|v;k1N!6{VNqG=RrNz`A~c=hTD)$i#{{%yJ2zPPsmgBB z&W>i*jd*H;g3oNYXAozxkQT&GE5D?O<}CJfWA3}CMtZ}c%$u!Jx3rO^pQ7vz@MByh z=G|%m%ELSKQf)0iC~$cf@>;F};V+r=$~0xIfvywpNXR*hXQ3Es3wFbE<`O4@n)OT? ztA89rTEi6&RZxa%sjpo?A5XX22>#56{tTh}UGH~#mDe_`(*G``+=^FGpDaVz?%?w< zVrGA?PwWIlKa~Kb%ptZbKNfLvf^aM_aS&(H0+w_pUxB4RQ*zq`zyBq$p(v5l!>B8Y zZH%Rn+_4pS;*aC)-feb@RZ!XzzK}c@dj5c8#_4!2CL&w19#!K?w24~!*XT{zOZUao zh>WxA>u3)3!z6)PVnjow*j^%Vk|pAt4;50~TU<;SGD`kBC-`!idgrq^IHL zE&7);tW5tl-2E*ZY$i)I5!#@@?ZEZvHjS3P$~nFzmnTh-9s=NG1HthXm|;+L(Bd3zGj`}c@VYAt zmlLb|al*ZY^0TAVW4_}XdrRb@X=85vvu`%fJ9$~xCIp$IM=Vme6bjonl=+lf@?&hZ zETu0RcA3A|pR&*2QQ^8%8xK|fjdj})g-yNI`P%SIF5-GVm2#BV4IPN0M}3^J41(~g zsU4=vx97jlGl@pI)XP0EB^{^nK1`~gZcO%j@xJd^m)v5raY=p8iNP;N77ipT(lCvqf7}1MHc+MnquTOlAji`(yKLw&Q2}+^gJf+B3+1 z8SJha{+IWd_pQfiYHagHYZzlb(5C6ffY@ZuI*{TzrGKk}LBfs0ii`5|hRD;tw_LIC z61h8xcRAHposleOt$~DKGGNETTDm3VnJ<_ z^i}@;?gw;~e@A-%#S#%*XnRuymg1k+m_$DsKztOfa14k0}!G?TqHqoMW>Y+f#}NQWPq!tg^|?K6 z%=Y#hp$xHi#bzlP0yzH#c1zXrzw%FCEKF;-#JB1P!G3U{0nrE|K!FgQJk5<lZzPtLb{~m=$${h^%2+`9QPUr7|lU zNHIuQTJ22=H5zftiUIA0@eq-Ny!31A%P)-z?w~tRJ{P*nhF&!CcdO4hDEh+1sRap| z^jjfE!aoW7iq>kqcrs>c;de^-5i-4hegHtQ5_GM^YPSQqew2#R1*$nq89hhF2g)C# zNEPyS8iQtujqR#(uYBW+ch*GAXB{~RnlUfOt`Y@RK8wGejbI-`W3gUt73}*i1xWfK ziR)c@n|J8D<^klr$tt&uhN zH4sV&D&0iK&Qm#1mxTZ5g>>EgjD2C4OK>G@xeCCv84)$Bq_-X6yAnJIbr% z)Ned`WuV^)DL%m(_!DSLrx)Rr)Z-rhG}@4Q^{4!}D`(lcG&JIDD0Dt5$OwLtTD$Yx zbH;Jr{gY5!iAv=SvS`NippV|OiCapG^Is*a;jw|Qo#vt~aN%ow-m?Y(_a-UZ9we&- z1dV_WA5%MN8kRocr?=0(h@m|56^4}m>M7SQxMqQ5OZ{1JcOKhB7cQn&r161d)w#^M zR3miz4jj=gSI0_e20@pEjBXzw#qlSmNwF6cU`Uwz2U;qV{&JN8Bj8ZCpwN`l;v+ui zbknPfRaFKAF-pof7XjinxXHsF$Y)~gJZtB1B2X>bs%{9D#h4Cm{*>Y#G057G#x>T3 zU3gITss|I-HD2x6H6a}{GDb?4JY^p*89?|)4CH9JGLPAEsNcO99A$gCgjMk>ID>wz z#K=(duQD?_kSm3L=7Od86HnRC4%}Una>5EqWdg3g0(xo~(DJ%tl??%TwSj=3yIz~G!~Q`Qn3%QCN*l$MLhYpER3eqTfzLwlg*PKBuD9>!S_<&wI1@= zjD94>tNA}30-L8G6g(l>%s~attLW<~>7GyLfP>%EfgvPBv6gjpH!f8w#25>)b+guK zQaEN$a%bNN>MK=`C=;ZtC0xfPqcVI%#K_G}Q;w~Y3jO6smw20rZSIO3F&(N~=B(bW z-4cP9tnMDSPA?)e|I!}FX$!G*NW`SKho30laB3+onNSmwD&kU8PQRA{|Cz%tX{InU zNU!GUk#H(p$pL$vv6n)oEh+GUaK@!~oUe(fp~ky|-9?g9my-7jv~fWew9sPyaMf%k za4T)Q$$*CDfuad{IrCz<#D1|4OVzZGxgk67$Xw|&K@HnWrWEL zLH~GW6AgNI3ZWQYv|WZ?ijgX#5wer~2hiRQ%`6wx(Fv~jG@Ewfl^uw(=_CP*bPbdf z=MAHkgOPPn{Zvg9nt?3|`R=04f~A3!y*zRZVz`0-b&|mt zW$_MJ?ur2{x%ibkDs;k#lSzLsd-j$hBGv!Qxw7Tw2+EoYj{CtIUzy`_W}VZSv1#C} z_TO-JoQ*O3BtPOnsyLZ}wa8g&=KHC~;S*JS7Hjy>jAKs2Z<~_$YO|RiHj{7sU?spw zgK~R{%mAI!s)m8Fij{d{{3H&OI&THnh>(AxvCXE!M#dlHguF*>q7+nyrbEhU$!R}+ zyd1BT)O;xM5th2||0ShMK~+J*XyZS6b9~N0=u&#t&?Y=^p?HytlVKe~En8os9D^qt z-G%~N0E@w_+~i1R<_W8*p3>**(p`s!r4s`R~-umo|i6q&( zNXfRyaZbjCbBa&tX1(xl=ZA3`dNl_T0Fdc;L7 z>UPFw0VNRUvH!njmms1@E4GSI>81L$)S|7JA%~0PYIb`%@ z$PJM{P#GS}cGuv4ZNt;YV~NTeTe2bOBJ8@waKJ{913yFw)0Z{~?j2iA#kFwz5m2}W zh*Y#2fl7&@-C4;EhozX$haQhF5{5r_S?bnD?^;(x!LL}iYQDSaaOZo&R0cMhjlx(y zh4pph=+v**vfA40YWrl?rT%`s?qoBdYGBV|m_G_zbv;eG7pt%Nb}!Cqq%TN(33l_p zzMTkhJ)}Ot>Vh%F;xsJh-uc10fU)VZa z->{QZ3V+{rATXeZI^#19o7;tTX=3#+hUEm~RW@q1u(=F%kCFL>jK(RoON%{4pO6y4 zwh51)v+6%pQN2%asoz|9+t*(?bMo7MlBW8lYqlVMIvG4!i>g;7!mJv^eZJNLv+)8m zGhCLoL+RRB=fh-ZZIvx^$jcTV&$&Cml@brzh{oVOt3H-UY%lWx?fBot3vH~)a^phv zi1eK!pEHcwu67%_@1z_xlw+(hU>cm1(oLsx^r#fZ6llM3wb)!TZ)X8N4s)|3fy3q@ z8uv4_?h?n*=g2K}kqUSDED+}Qb|S}35P}QGs)NF)?Hiqp_~L-4TWqEi?j{1Busc^O=${h1 zyDb5xUhuB}nQ8qx+kuZ-zt@diA6+WFZRhagJsgQ3M3nK+b+=oIY-x4i1jsA zNaEMlpC^;9rVehogEwXlipIer#mDeqpIoBMrGR{Mzn+9w;=B?COg9w+dg514QY+$& zu_cd=L&FPl1qqUgTWb3N|UZJ95U zhI^YyPYqb){l!M;E9+h}6rR8`Gg_i~4zzA2L&xOFgC7?jSt<5+=q89@A&m|%;mzi+ zQcesa_1Y+(!$0!^J4DH(#o=e<+l!{2`2^!!Y}$^9-Kv@yMBo-VmNh9*v-j9-LdF&3 z-_~*c#OBW}e-gae`lUmgkwwesb(;RY)S#7~mzsaB?@;y=1SS^d6ef+cF9$wc%ONa> zCuOF4p7Q&Njh#%(_gE)U3Cu)q@rv?@|4?a+S7Tvc_ZXZ7RVF@0{h#$E;{2YLvd6rU%d;dybFyaXc zp+`v}jsDmhXfb^<^?gXTCc=fSjb1cBu}#R;2VIIV!cV16;|(*Gl!PegyA@)g&9;t736ZVpZUj&`!GKjT9qfQn_!X@Rp{-a+AE!!AHRjvJ$!Arw6$5~12JT%^38yz2 z_#qj}wc(4XE7U< z^%$W{?;b{Ey?A0u4rD7+IUMIMpd}d#UD0iv@*WsCV!6w`2y-JJn<^}XFWm@mj42oOC#n5i*4%wYO(p@5-$gYX@*|Plf0S6Al%#UVg>cly_ij?H-~GwW zqL2Qd_VN&Hk8x)WhrpT|#o6Y!b1>FPw{-bi(D4e@KSK zUeqqj9$MV^YtU6NSJ1tG^%@yZ$}Q3!;~<+9Apnruj)!EQatKW+N@4#fMRIaR9r~;0 z>7@OGT=SL(R#5l$9Tz3<-W}D4Mn;G!?*$b-RS?7=x$ij{$ku-Kgj%3q7zxCgm%v{i z=%Vm?Q(R$#KtE=cBH}#3$2WZ0#?EPX_>d1ww7E-ON!gfJXo+Y)Dqv>=VZ=w+*V0t) z`F=ZHoJ_ib3yx|i2I+$(p6iu<{|#cewFS79swRd6fBCWHN-VNn4TQRxZBrpMU?sGy zQ`Ap9E~lyCXT;+CO6b5`$624TK!o~>E5(88)QN{uTaH#lUx3}2M#-H}kAmyXWb#)! z?QR1viF zS9E)e^7|g4O(i+B#I$U0&hg+DSX00NtI|G3hqAoQ*5Gq6A6ogAPsQsg{UTNS>ksn% zbyy>)fWX%5Y#bJHO8|HyK8(8>^_y}$hX72;-3!;AL&Ah-oMev9QptqxXrV)300LM5 z4gVsxUH!)kN^9@q)K$+F@3Y>A-bBVzWdv=~n((tBfIPrQLkQYP7YHnSpPG|XpYHXC z3%bKYkVV*XxEs+s+h{TMEtOBO|oSYOz`8=l|rdRr}`6>6Z$R@pf zWg!VE$cej%e1}hEHH~P`hJ56U^@NuqF+$Z2g$1WU>u_4DM~BA6xyYITBd%3T=*vkr z5N$??c<^Ve3-XnAdxUXvP*ciu1kys9);U?W{NFjD7Z3{6A9EMVdOY%alRk4m8dIFl z6Iw(nme#LaKimF>|LYLqb@f(1b!L(Aapw?jLoY^cN8|ibXs<7;&(>UVtqe*9?|zi5 z=47DFSX=&`dD2V|hJUHm;GNti!MKoWU|!>JjB3>H;8iyGW)Hn@%U;B(XahY`%7=AY z!S5{g4oGUg=g7}e!b1&0AIJ?@z-X9`)dtWNGfRa`0=&fQIl0(kA^+fwaWPv{u0IX4 zzcQmXOYinX5`jXg?fsJ-7)F>|2JyS#Yd_aHQs;@iyaX1tD`N zFlRY8^dGp_Yuvj*H&xo%9sq{%-f8v5UcDGD^oClZ8Gc(%E7AG#^b0kBQ3vs| zmms^+(dWl3CI)53`0!o@NmdIU7pDu%qA)ph8&8x$%5UcowyljNai1Akoy-G3h};^r zp)QKjf%X$O;SW?pcjNG0rn}u&;cUhkg#jTE2E-(SEsIZco&xX-@3b!jC!AV&099k8 zc%kKy2xWGC-kgx&moj4QHiqxUv_=u&e$Bw+{V++>)l{2_1qa~b$IQm0h|>BppJz;J zp!fxXmUoQ~Q{u{gsf_?Ep6QI{-G589$Wz~RQ;t?O2zKtoJW}1H5=xt z#FrEm+`Q%+!{LWc&`HPUS|?RU$)nT^bGKT}Atl+&I7`d)v%uLa^fV?uTV=_#CF^-3 z5Xm53pq5ni)jz8puNCz3nuE=HO(7pKZ`$sF3^E??B3?`wT&b(;Z8w-86{8nYxVmBN zCpJ72?iIB>&HlNGdd{__{+iUN&dA3W&+|5>J9BaNGcFfv`EP4O6#KR^-~&LJt!@0b zY?ya^rOJwNHhz=H+@VyUz9O5iK zcgIYyw8+o=;s?v36ZC{m_fP~ZYQ`TV3U$IxYDkY5=KV_c-X@@F7HH@tCHtC(z?sfE zEHE^1ilv5wnqNf^U+q`ayxyXpnoNtTmWX!8fuqZ`;7~j;M~wVilkvOky*RAHssFW- zQskxF$q$>ltN@Np_DzeKTZs_H=$Sgi(ZUQC=R1|>zqJ;QXWV|(Bx42Nl%;L-WI{+Y z-JxJ?-R6PkrNa0y-*KDT)5X~Ew%ORB<`29h=H%q+EqgwuP}aWhj10jPe_f4GS&*bd zh~MHRY>?cPWAYsWJdmnZlaAb5dwyJ*!hLtP!y9Ng#T^Vj)L~%?Ov`7tj8;R9KLvJI z!8WC8U{1 zD;&hFS<_Dxv4|VS@WEwwoxkQ}q2tAh!Tqhw)@va$wj}c2Xfj5-jfhuRn9W|2y&L8G zwy}QxyD4{TYP`lA4VDe-cK3yd=Aq=jvZcUofP6H2v#hQHM^I@+ShqZO#a#%Md=0od z=A)8a#rG2qVe~R6(Y#JPi|jE>ZfCT(fiOSI^^1YhI-;)yO!Yd@9 z>kok~X+<`Zoc%h-9Mewzq{sxyxm9l#WmiV?`OC(RK_4#R__#@&b1)|Z4E*atSIfXX zresBnP0C<4CG3$h*glcW)0l-R$jguTV=7Y9a273eA_dAfsU7;bD7C{gFQ(NdM(}D} zFp*%=b*rTmnaa>*FlSNsU#aK)#Cp$U{pp|>oJ3o3(s=*rB%${4wwroN zS_fFs;+)JZUzj1Wd+PId@DH_RMc)XQZhQ7rWsp%)k<8e2XiWC8vTlM%?*oqRdo94{ zQ>puBWWuojh~&XdJUYo??NN9yu_0}A+Wg0pl{Hd`jAX7b%7T#yq` z50PEDby-fIJE;edAMNx@ZU8fN+2_2}?Mm6K-%#?Aou6QQNi}NCDH*Rr`-UxL-lKcg ztk+nhubnrmp*2u+fGAk~r2T^E#$fM;y+9c06;x#wy>c%f8#W)ohbwjxAy=o3i z8|~rxT58W8l$tF1kYjG67MnCRdRZI9D_zH@MWQaU)7-so{EcIRVcG_LpMNMlU5H9l z<1D*|qF%0~5d$xw_WYygWGwse9nmkwNTCq@V7dwY(fJLVp*Yc;yx&9|j)GaW-1PVD zXs;|C8|-{w*>g9H<92*1*8(IkfnNwEP5}9cJD*6Y9$L2z)52#`onytHhb}!V{U6^e z&8$Y#=4){C{wT{cR94KY%}0oI!P3GIk@9M0QAz(A&6BOH5c^1N)S4gCCWJA?)XpKP zNE1#yEMFd$WnI1vDp4}q9^pp!;iL4lg>8cCy|S2WcMps2A4-(3fhr96TQ3&T`HxAi z?vzs^$yT~LC{9_Jhp8~6Eu)g%Q-AjQ1qF)x}KV^$hk+Kg4-!bx85MEdu{wmcv2x4`ZfFm5)vWk@OJe> zyd;V{(=4HSNsl&p8hq!;mugy2QN)PQ6v8l;z8i3Gut-(47sv8lm;zYF(30Gl8`HH5 z(4%&e#1h`I_?)5gM(cerBDna2I+NUZ4Yt}y!=j1*J#UvwE`1G7Et4&vhNo%CfWt!= zu`(?FQ7WUN>%)7DHzJgC-{<*DV;r8ab7CqjJYbV z{2hO6=>ACt)7C#hF|*$}p4pq5*Qm%nbAkO_Y0j@(w#wCmorcEPW+O}~-6t7opVJgR zj|Or(=*tH&<~2`6@jty!r%Pb#P7lCq2AiACz$-o>n16!a>e5;(f^9#&p6z@(5cq=; zG2|Xs{L-V7!6T$M>}D>J{yQjjI8x@^`X-Bt^$Vm@Wmbo= zHUUM%;rh|J=N#f4q?gQ=!A<;II6S!aa%2*fUfYjG>dRx3LH zh>a}bQaNaA{=M{bJpY#4lkq?|mL#m6)B&_`uDZC7n=6X~uunia^|>jV;Bo?5_yP2y@Gfuz-KjpH2AegafD&*%m-)y-~~ zmX>;6qQ5f-tB<-W-vl?M-_*sam7tbvs|JI4nO4G{OzmFz7JEWP;#Mz54$l(Yx)A|j zmGBo)(}d`NSd?+<4w?l!Khe=ZEupKY1Vku}Pfgpr-0{*i%GcLU)4mCd5n+T+t|pnQ zdV?0tQyEg7(GJ3iACv_$cfQK^o_}GVgTgK_7I%i25DaX-&4r_(@yv?{4B`5X=B3%@ zH$~~&=^=m`fO7qQ>o?ycerb(+ndybUPrd(Ke&%DVrcn1aI?k=k-qbfpdC>Ct%3x8< zO9+kw;*Ha;TAx_F19vLyI9w|9^M9xJ$k{|Lag1}otvbjTbK#j9P?^L`^&5sws^trM zQ%0TWjOIw$67d%r+Yjt}uY5S67mVR~ha_*x@s&S5GX3tMO)t;poZ%s+JJfV8e%)rY zPm9o%HNm~vw>Ev^$IT=9ob>aPZFsXgSPou@e9|@~ujRUd|2r@=Z2vnT(4K?HDw968 zz{%ixAfexbmqi2)JI!_sjeEJp^@XN-~|8b1`B^4BjN9@UBj|(wTD)78-Ga`^nJEUgLI(e zM9ckm?yMLJ!&-o#kCTyH*Ui90rH2xfFp9E1=VJ8Luh!)F$3&C5VCxqnJ?0;8?S!OC znw!ji^lj!3e|WEK=V!|XgT+ESYs-Tolv~m*7H>@|vTfzl7qv=dhQ@YehBytzEzvb? zXCuML@M>8%VIz}bLE|wxv^5a*kpgg)f70 zp@qG%LOk zv|{v^;ot<-tZ<`^NLKkIOlz3UGx+5_xk)OQwohNVNUy>zTQ1Fq4yVHjBBxjIa&5tQ z;uW%BcR^%$j@R(}IwxJR5{pRt(<{%_$ThKTwtOi~C#+g|Y#KY=Z$@Bwz1~rJ1}k98 z>YJ5uoLmjP@iFCbM35gV$RBR*Nvs#yY7Rn4+fMSS1aQDtwo65OBWQ5&-rnG_a2y28 zX3!9q&sM9SE+(Etfq0NlHN0G<=a3EeXv;HtV;ba)AZK`x@gh^;|HRrTsvl2MZ|;ov7c zK9HLY-??cIId{Auy_vt}f5URN{h80K;6TYZuC(^7YzbZXv(-MyrEXX24wTc!Hwt~# z5aK&AlC-WLQN|5;6e=MXSJi-5Hh7T0oiIJR!w;F>CFDT$`HA(&Az{<(o|9d2)}$e8 z&?c6Eh}Z3vP`Mi2nS7iQgmc8}3ezbO@3hXQHenKmC&BEqLU_NPK3ZD;FXjqUaK`Gvi5+O&*k>n+!u7_YqLV$9` z+!iTB<>KHTh9rBW5uzF>uI$o^Bq62_91GfoXW~ax?tz%(Ou!Lv)<#&xOWUZ(5M?|C z%|6TaTgY0muJlnm^Q0zM8%rZ0*ZB)|MvONzI9oWu;HbLs9+&k-(U4i6Q=F=FVTs?X zQ+K$LG+8Ohs}{L4wPe6~Zfk5kjzKP;g;nKDgm1+SmDs&5)@;M>lRhqD z(%+G< zw6+VWXczgkv`+CINyCb?O$2QgE~D| z$-WMvB%fJdZpw(Z9ghXd@^ntSNl!e&lmCNY~ijwS40J~NiS18gupYlXE7h!ysV0SO76X~)K zr`W$)ruutqSpof~*?Y?kfLE3lyd7CG?#{ljFb5onw zsS;eyTx;UKIUllnRZ>9s1`cY&9i5qSwcV6zx|53Ex07`A`v1NFJM;Al`0S`$h_o(7 z+j|}nUe^UwEDS#=t?-D%91#J|`~^63YlgG>lcijuAYPacf$)~a_oK$v)+{naCL&f8 zaQ#djUKe({WzM5Q#x?>eT)XMX4>mIDH&q_~tX4k}n1bxHWxxTXrZ@L7+RvsDNzq!M zOaTEdfA#f3NC#HHScE@g>Wslq;16d&3p{eF*cRfpngnm|akMtY0BP(v40Yqm_j++U z7IVXh@g*SM+Z(&hFaTJFK)6L96Vp0{YEi<=}_?qI&LDpues&t#1XDt%39RDdfqntJ7zRaOvy&&qD&r1*f_h36{_4ecS3yQD5g|EO@ihDbZ*i}VvnSQ?AqO`3ceN@Q)b0(j;!4&sp~TF;rz zR%0Wqy5+~K;$W_)(xqRP14~9aJpCrxo*e85s_uLlIkI)#4E|(qf+zuGaWrGwW<+Eu z?-6xzKY=2j8`dXiRb0q$^);`dzpOT4z3>uhx(<6D3cS}LgTla(S>Pfq_e2rBpT(ux z4gY6&|Ljg-(-X2iCY6TyD-R5(4Ib(Wb5{Jxy8-Wv8frdwU z+e0t)Llks*jF;@0Ad5!I?rm%6DM?4Mbl`g}7`2&5k@~_%MkPiXY(K*;{YZT^ANIt4 z=I_BL2T-P{5!}VFL^((^6)|Kjx&Xr=by>o3CGW}Hj$XsWw04*uGMQDBi{VCe+c~Hk z6N)1ZsWbdA<69pjS~da}oNf82mX?vE$Et`|oMA#c2KwfSd z%o}+sb2FM~Mm=D_y@^(#%%8cO@#<~FjwtNSl+9E!kpq10N?MV{UId?8kCv_*c8v(s zw#@-VrL#UW6?VZ&G&j^D{5Z>A)I#(lj9YxwQc-^M>5VL9L2}3B8XWTxS#D{B%T^ya zS0P8%k&{m9ew8_v)ph)Xmh%P>HxK*;UbqVQhtdfw6LcvIoqB%CB;7(L*mRzYC()a% zk=^hj4#K;lFld|_lJ+}3IX0T9d~@KF8RN20X@3kvi|O*pwt-Ew92Fc>aa@G-*zy4^ zT=)MN71Hk5@4|H~$`CGM;puC}cp@~0Vedl6-n}En0(fVo#WvQDE#j7}CMvOdclr>1 zW;*JIboebT$js@mK1>T+nit#@{4deVS!uzZNe}93Dg$xJdnz|lE-Lu_quUT!{VD?E zO?afgU`r{2Np0F322X`R-u>U^z8P z`EuzXkBuf`K{=K+C_;3P3HK~MJDKI>jiCHw|Kczr(3*D7fM1&FVlpyOm{u!Xa0h8f zjaiPRIP4m2X@2RHX8OCC`UAnagYvu7J6d? z<9AXB?O(JJ{R;2P>Ih;X3sS~u@;X}#L}H`!_`Of&C1fCX)K>ITfF53K9!2-L1mc1B z7H)}a#09)^HtGh_G42$>Gt-DQ<#o)VVp;`wE&GahnFrH5e4c5{9DymGQZxUcx)v$o z1&wya;bDTwh)HSAjimw} z9!w{4fHh-R4cdo$Gov`>50E$ILS)Hekf$?R-7D{4s9}Vjd=<^5>xNJOv-JDUM*10i z*M+pe#cE{%H~(qEmBajbA1k!1dfQuh5n=J`D!5*0LBKN;zH51JcLdgR_l}Y!u`3WR zW4>h3y7s0Zw4b*aRYTTilG*TG6{3tFD`tFT-K0VaHjCHk)S@TnAkd$YGsB7dJ;)Ws zC(B#J%bt{#9X!_a=&kuy1p96qR>k`UP;X?&ITflj@5SbCI53!IF$FC9O(c{~Oxs4j zI-R;rMjtw@u=j^hIqKW~uSVvCVz|Tu@7jMO%6AJdrFEvqen=*G8`EfWHmb*L|Avr= z;uuOCe{2)?*eu%jkM27ESyF9JuV!mOgl@IhAQ^I54o1w)VQ=JzWeLdC(w zNXZ=s*Af%v?lov!_i9J~z-Yjkg%nwJmF2`Jrc#hu&6SLh2-9bozT$y&5mtuG9RD=G zynu0w^}X@gEdK2c+3>#GLi(V}YqFtx=Z(UaPTKBXdlQ2$%0%w>lz+7L?dqpdEtYb> z6?_#!DO40$Ob8K@0j6176wyj5jsm7zf=$nccqa|?=*BTS_GF2((sNix4SQm9lgzUj z$gTrmB>kv3V@gvDj-C{U)UDMfA|j_obsUeyh!*}Vq-SKnlCkqLY;~Yv5#dzUj?jVO zwp1n~E9)e9u3^cM+0{}(2U{4V@X1bz_w(4n8g!8Q;;DR859xjtK?J3(_5xO1#=)ti zfP9>XG}Bzg2uX#O(Kb?{-vVzmFw>shhUS$tStBPQ{S*q4LJPsyPC|n$boaKu87V4a z%fB0yE|_U1ELMCGbeP0AzQOxqC3aVG(oP>2#EpD*3!jxVdC&PsKkHiL$NNM^919r> zsH|nt%%NTn>7G7$*VQXT$Z599XifxaCpap0=$n;ncXsmo>4KjScuj-u&?BW+^gcz(^3>R)4j}v$di-MP+mu`(S}Rg-y;>hlb9vGsKWx1WV)Op5R76O%K-QGsF?Fk`LCPr50^_XQO z6^Ahq9u{=tB&P6yml|P3ZlXC{x&@756%Pw68U7nkaQ<9)Kgmm3+-)!&`*9o_&eJT3 z_c2psc;jnKmo>McdMKNFJSW39KMiKQIZD>Q+D#!epVzYXkZkcP-j68dZe=C5ck-J7 zMBkv2h<*;mXYl4ZJbm<492v^~m;q6Vc4ZjLPR`@cz-aye@(N8D^t_yhcA}|l zAQQ=knsIPfGkmc=+Y2ugiS1ZiTE9U)U~rhhvsN3Bpzhi`l;JhIAlFPl;I2^EL2H5D!yj3H@0 zrWr}aVbMR9ksyh-h4w_01@(xDltcN$pvA>a{TjwyZ^8ZvbAAy8O@9kdPl#f8nZNbh z$5FlQRWvrZ(eke&sC#zJ(9RNf&Vg?p1>rk*PN8E+bHy5dzK2qTmD#w*fc+RB6VKyq z9wFnuo+e{AtQ;1glc^ND)+6zpWEi)2 ztGy`&F$ik6p?SatS2^0H>`FRNjyN70k@hemyLj&v{-9Xci6G5u^w?t-yzDPCS`~-C z04dT8brBP^w?2%%h%k@VJcpX0Y(W?{Moe*BiS+ConE5PVVkr$Y93cw6<|@=z4)Hoj z)&=lQDnY?#b79`hcgjk>gHd>KXq`E)7%+di4X!nGVM8yWt>Pbt{g;2JPer;E_o*-`J`X1k(D`*Qp+lXO^a6++3abf>|!kk(6AZ-Y3y=_%$iA}pi5&UQcGN4SE2I8Z@m_+iO}Jr*THCg7&D z!8!0UYG_f*j(@T`?lF-jEm2?$gSo|mnL)`sBI$SxjK%PdKN)@*EFvSRdP~#3SQCL! zI|^3rP6{KYIHHJ7;Ok}6mcew4v%orA`5|q&Lxpt{(q~+XoSV|%`6$bbOtMNw(}Y-S z47>g3Ivieg7Y=l-z*4w|w18cXoHMfFUc}eLmwFM4Pn3x4mHd*Mvebk%i(kmZtnQvw z0~4Uqg41ThoX2BM6wbz15g4^@cqJmTG`cLPCre|*^DoGg)N_&HSqQhuc*~kYk`|IT z-Qz*a+B~1PFQIq!0u`rBu9Hb`=lWoO>=fkpYrUdmAWOtB%#(OZhdVZmT8J`C<@8`> z);lfZ9{0eAFmkm4gmwoyF#Qc$ea?&gl=&jkG`5p*U2Vc8lK@ZSb$rxJ7aTDscNN37PC}}z%hk&3mnno2 zZJro*$`O%S;xw?|vUI=n#M&uHPf3GIMkR?7mF;e2=5J3!pmUiv*I00+&`Xq&Z?*i* zOy0X82kvu!fyv39$I~adNX?oImv~arbP|7W8}qG|o{@Nd5}%&xcsp;tX&`4%&5BhB z%dqCo&901UzAAGr)3h963P%}eaMbINcZebp!TFZD$_G;UrEE#;bs@X`+#&R`2g)ar zw;)9px#;K@YhZNN@`&wYZ!O=JCSxTbNaKq6`N5V`*QGzp#8r+X#eMPXdd=HfrDt0c7Cy*MBqsC zjI>ivqm@d_$a&t6);IXQjL(;uu|14d(RIQ*|4RVieAA{ z%UqzBWj6ZZZ;HY^x{(;u;cxtijS`aUE_6-=#LX5Wn|b{Tk9t-jDh%V(0YuKAQclKT ziG+wC>ZJnfz5$vHlU~b1gj{cZF9rqm+De25)vQ>Ckc&z)HhGX~+v0{DkHCnrp{|~_c(e0|3gm;I08y6sV{3Q5fDIw|KV0?^KEHf|g zRKl5v{1h*@qMZhA_0W!x99Bk3aX7VzoX%Vrj3AawJk)~rs*}4}F@r&d+?|K4$rmH% ztGTd##!MHhTPkLJxrfP2(#9~t z|M0Tn+lWY~xhVGTNa6p7fk>l?u(*E_XdTU$wZf3+2S3lvZ$ZT1Mu*xT&Rabgs*;XR=^m zSC4SSC;|Kzz;}8YtPe0>#e0)x$tP?WG&W*$oD$M<%!fCa)(_t|u+@i0EkjiF?U5rTi7 zh6b@_hh1q1>By7W-K+?2TfKB&6w%FL1nF8k;*IpQM7Om2Z*jxD%LUIA79I*H`%n;3 z*~)g%c`%feBPtf-TP$o=>Si9&FENpU?_4^=kkxRU8Qe77xw9eOIi^?dliW;7ojtOaZ$ zNY6sH+>O1*SKLvi#3HGuaUq68JiYn7yx;a-p5ecc^+Oa~BCu@Ok7nUWPtBfVnqgNQb6GhrMWz&XS*Clyg@hSM zjqhxJ9W{fpbQd8j>w4r~I1k0YX2Ja#OLV;LKWS;hLf1@X^c2m~KmISOx4f^L02?l5 zBRw}8rgUb{UVINIFt*uPo4k$;@z?J zx?+7CqJUZrcqY(A_gsLy944}O)bYAm#xU_;R6IUO%N`Vm;bytYn>o1V>ttX|gMa)o zWZuX!AZxgJX-KTJVc+c_B5P`OUAn#}L_tXWq>itpVYTj$z?j~9qbG)4acpD3@E|H3 zdQyo8^ZxZFoCdlZ0~Nxq>F`cl1oNi(@PFG2<7(c^X2D2$nouykFdKm%u0Z+gL%m;k zU-;>A=fW**;-a{_BD2*uGH4YhqO&MCMJaS|rjmjmU|d!+>8NOoi+C;1?;MRY#k*lG zgOBMRTXLjp{$?;*)aSPB$srxILO#ot?6EJ`lz+yr_>6Rfi=gdZ`Q^73Q?M-NXV)g9 zllhxh7s5AnsOBXcK|qAI?1j-apTZ6-TK1MGy`DPhCH%I9@P@l^pf_chF!bW6bYp!% zQl=w(Z!Rq^s}5m56Gptyc)1X7+ho}hWg=nd9xg#v+VzznFX{EKKiq_@%#S1cx>T4~ zF<)hv^9~vUcUdrKNSV?^)ssObBk?xzSk6P1aFICH^1s!)VQ(ABIzLnldnU;aKT#O6 zzLQimN#FrNcky5=0?m|w{r(M^to2hA%>6iWJ~IpcFY&j|WJwr`p_H=x!mk?;`bq@# z+ef$nxhBG$OQATAkrZJgR-zn|er+_Np7S6xYQm6?Kyk&pr-fW^rB_zPXk5Yz$_VHA zZ5@kCj(Qw;()fS(@}ACk$Z%sBW_{GsWr9eXyKp!H`%Nm+|Km9oYmc4f@~8;uu9mW- z?>lV-FB^xGSB)D3Z=X!lW;5Sa~Ke5GKr@>^VC_(_fBV=BtAVg`2-oJ9TjMic|!@sqc4u2 zO`0gnS%*XsW%CDToxF%~ypV@@q1|N`m87$a@shG714?{+q=^qbJQX4FR7bkr z4++DrIF2AVl?h$IV-SVIs5fA3b9by}8m~BgVayz#OFfFbn1vnXyzDv3CCM z1!1tTpg8-f9RIQ%fxmnS+eT#cRClJcVm8B;CKZWuxeZ&|n`OBN8A`f73|DFdrVPRD zrET00>#K^-=5?ms5t@|ZmdAy|XvSdNrNg^xe}EJmnb#qey(e!|^0A>F?G<0gzUIf# zu##nVE$=7VpJVX{Po_ft`uL7fIY|?SmmsYm9hU4d-n9>cg;;(&kR7*iOMJ&74xcGx^?Ar^EEKP}DiFMRACSChtjMeGM`F#PjItiF9X?1#2;d zcu%AGh6>|6WM#brx$nt@`#-7Nq#0fEN}AUmayk|zyq<>`Ts@^}E&pZ@KcyT=Qz$dU zSm8(8vulo%b*Xw{SQQ6_mvXS6xJ#iS;fjh^BQ8gfjRdKL{c}w6O&&(LC>%N1Pq;fg7^=iq>M82Dl zwdfld_tSAOA7UZ+95Yus6Gbo%MWK|i9Oi$wZ${JqeGkpMc|9r$&Sf!$ZAv@-B&LH5 zq^I{_?BKcN1C@c@LP5EV$s&cnr!pZ!bm@xQ2V{mdD@Hag$Y+~SGL)EGzO1W6p3QC>$&YkM*`*(yi7coO2dvWysBzGK#8Wc$L1H1mGkyWn|* z=^xo=BlHTBPUgMzlz#ksoN*dbX5ECz!{K$fE=B&?He8?L`9dDCcQRnx8TO}G*3aUV zY|hl1yjsWbw((gRX(e838#CgudbnQx32J1tS)yfR%rUHrgXXTR1}h_22H64TFk?f( z^E$7(Ba?TQBImr>Ncm1CtdB7>C1d*~I0nFOTJHZ&O*hSL%YRfxoec!lA;1bAXC_RCrUz;$X)Xr!twd zAHpam+)BTX16?b>LreND3dl7)?@u#CfsM!w7a--r!7jnh4D=VlE3^E?^NW{foB3H2 zfom&`02xZ%Q~jchGhWU@YO=hI7)KD6CNfc^QWnH0TS}Kca{_`g*;Ve#tZ=U#Q+C1n zC?Z>UU!Lu**aTS$<&-eOA1{GZbn6hyryG%bUM@WU$x{&}QuZZGVj#W7JQf4@N?wbn z*i$&lXuKZerwme%IX%n*hl<4f;~E?o@a9-!g<(}37b8z5jrBB~tv`qr-&Tc4U2h%Z z%t=}jMmh_uxR~jDXOHjW_hJ!=OFbCNK*F5a4#ufW1PT;~ zR;n%gB~0UWn#0P?bLkY9-R%0v7iTN2=DAGEbUyY5rRHd#yK$5+plA*wCS@VvK@fa? zLli~}P4~A5fUT(6v>kzeP{3_qx+OZKRlK~@Lx_B2CcN{-1MIxtZFiCn;HDSi(9?*mJ2HU^ z?bIkz(_BauFR9mjpuo=Hv)7~|dSO0hOP_)KW>T4pjGQl_@S}6!zk|V(xf(~C#u(ls zw3B2w^Lu%S67DIlS{TmFHlkv9$zT%3$*AD*$97no$3pY%U>R1$QI06BK7$t5+lEE< z2buYLxFyyp*K-9}&5TV)>l@5mT8+}Q`!>YAl#b4ad5H2DXhjlt^d&d^zgmOfAGOV~Q3R^5I%Rsd9Wi(0K|ETvk zXiEB0VO-49?sHfALMndgF0@px>m~$5C~QRQi!57DupIVU2H%e1X5ycg3**y^Q6k>L zfS83W3bokCqoV?q0cfz{>~j#6X2hdHuq(W=kBXzF8v7Deb_sD9AqrZf%T9w1m9#O# zhnyM;U>Uq3idVLioom6Q5RNG>Nw>brP8yZRhg;CNlm)KGKDPnlItRWfXTx*TIJjrSy<9ryw3+BNPX_MB+QQ)3k;{?a8W&H zvJ@3CFA}!=dcbmE?I=QKZy6*bs3xyL#^pRO=DXr;$}GgPcL#n)>r7^a$}Vuy!6*Xd zZ51s6#EM@*&*%G(qVb_eP$liWqtZRCK$uq1(dEPsME|{Hg5n!|+Jc zUQ9_a9Lo%tvi=#pk(iR8u*F=4ZN3fHZiYpcXgNl@8K?63PhE?`OQ`&N65##CTng{B z%aHToDe!%a*W!Wp^qX=|%1Li!rHryemJpFivND&69-#4Z1g?Ls#x5BQ@V4@DJd$Wd z8Z!O&4A_V~?nT?reF*)9 zg43k6@D&CkZZY&HJYp#wqV@K33Z$>CN9C%Os7}i8#-TtaHBFDLYZ%+Gi5R6k#EKS$ zDFQ~~eysS@Gl@;;lJ;INJ&zrSQ90@rhs1pf|1o1karCEoD98k&aBJwXA49y3DG2Rg zIl7(c+MiKYlF%~J>LUfPuKES$6kOXs<>B>pw7s)jA2q&2Sl3f{wbF|$;?YafigSQo zdO6RN?j@EZT*mOo{uHq~$?`F?9pTBHLvmw^gW;3OmM5_~N}q=a-(xlB$U>4A7sB@#X2SaBH&8S~jDgPY65=9cXMP!l*G1uaf(1bK)ew(tfO5|`#IQ>r zp>&8#eUdG5?`uKpGs{umk7moU&#);Dx|}IYWLar)z*Ylc<+N*#AlOX7Wz%)Zejl>V zxeRGvn2(h2=EC|2Eg7){wlQjVr6KY^OHucmci_k#6XyIdGCt7`kBrxrO<5%4`=vBk z(qA$W{pCB+_~3P@kY$!feL*Qhz@cS4iIrF?oDBUa=OG@FcpQo3zsX1*bl^IZr?QsU zOI~D%fap)!jReL5q>6PelN!7BZ^&Q(8B!~IM)WAWm?*FN(caE7)@T0Si^|sZX#G14 ziB-Jpk5HC6u!v>#rjwB^iy2If zAL%o1#bimdUdy1&1V0O@3zxwA#lnu+;4(*}>x9XE!Mu_<%7TY8`4ggi>Un-o7@>PS zXp#QDKFiAS#;_@l{j^s3Iw=GL$~b{J(`>WAWy3$=R*d_^H&F7s#Ynx=f%zp`JoEYe z4p!n@QxW;_CN%v|7{-<@NIUZ>6#Xp<_k(=qGyEB8TkeTmo(kudTQOmYv^JEyT_O0+ zLH4;l0H@_LKLZsbLqwr?b zL|{rsxn#Ih&bL*pV^Bt6`;$flKKUGKS1upL{TV%x2G<;>4Fy`PO<9_#0#u+m{7kU0 z$JVHF^I?f|8-m2K&#og%nReDt570CY5S}jH3*5-EFHyN>#a;QNugm=%zE%P z#li1n?oHWiXzOotTEdhvU7x|Bm-yqNkfm%$_+%m?Wx5P9I6BXR_l95N^N z=6T56k4bP#zm$vw?3!;BUZzQfK8f*t+r&TKYv8ea{17X9){XWf2(9L6e3=nJhCxgJ zMr>xe+@R2%WgS9aJQ^kp*WyON{hm3?z;+9P^n7!vA|1M;`g+7;2j8hBZF6)?Uoh zqd;w4Emlu`{MH~{#HCZf$cj98Coz0+kUqZ#te9dQ^ zr0K4Q_{(zG&L$ha>i#xAT!=tfJwm_ZpY^uMro40G+BsOV20%z&ssSeA6(%hPz%)G}U+g5FJm8ylg< zaLVG07um3@nHMrVelQA67EP4=rEy>s@?3Uuj2WlA8Be36!Fupo6~e!H67?@W($P;i z7G*+G7>H2qHx2y9nnX9-=+BVIo{&QJCUa{IJ&fsXNcp-OIp6Ri^Hw)JpJ2wyq#aQf zu??gLfK;>^S}+fU(faL&Q1$3Fh z5&^TtzrQzW?pplD#RGr#{Z-VtEXAkl24ob zutdlWd7d4Hy_v6}@;JJxzzo*ODGcN5{FFW=LBhO*`IBkHl&lkfR_gZ4JmP~E`djBD z?(rkpM5y>)jKKNs4phIeqWAu>6NX_C05>9g0VUUfM>ND?<^`EsIsB0eSPH2at@-HyJ*o%M zQu8F5o~9-JGSj!87Jh6|MJj;kEk1Z;72~&f51&SHAp<>&;qR*OnTckF1N$VNclR~~ zXB< z=OLZl5`Jk@eSszN2SHfZ9YWa^79!u^Jt>fhAlBuZHk>;`@ci(4ls|hrDqD|}krKf= zL?&}Y#zrcjy8V>n--f{U-NAY0C! z#x#;y@JE+f=e=bNq}hh%&(MzhvJ26>c`Z$UBO$CMy<{-SKOzYI>}KrScpFxpuzecc z8FIxToqhA+lA(urEE+voMg4*S7Ud&{2(ah8i2jUu{B4%UhdhX8m0;X2qHx{AdorIx zp6iPM6~;?Z1aE&6^}l);`!-DYx0^lYnG0F-$8gi?lXPcV80HSRBL@){k4%<*Poyng z1d<#LCd>epj{J>Os!@j*84KNTU%^wE;og%V?Tbb#)`NRt)C|UGpqU)J8Hd(IV9VYe zz0MWs1L+UE(FNzmi!pnqOn5sF`Dx?ek(twP88yXx4Msb5bd=Fc-RqXk@5@>d-d#3~ z8wyGMD-dD*!xkR#@^urHTQkEbUPSz!pXu{qe#+=JQQA_bCbNED=|;-*bhuU(pyj($ z(Ei{2yFc)|T|5#guQB*z()u9AQNn-I4gS6PuLxRy^H)^8!Rvwk&T+|*D-K#AX=(5l zv$RVm*|7xqv5-nA1?YDjl`HiFnP~i*iAs z@*rxKFGrw!g!cqbIwi=-&W05)@O7+C_8!!QUPp616EfcB+y^m>S;pbVhH|oYmrjCz zR8}BL&YU86Wd8)2&(Pn#G!a_u7M#~I&?J`fpxKI+d)nYU&(nVQk?~>i@~#b`<+`(w zJ9QE432r#jeARW*DixjKV+EFu{+{Yqh~HN;+xB-~sBx$%hqF2eb0tq>Bdi#(Dg2zz z@N^HyG9I!IMm%2PiCk{M{6;fU&UPU!KOM$)dMbak5T$V#+eE8}w2YNcF@_#xdi>6W zb1RRZ^Zq(2&qTcH?(F7EzJCy{-`|XeE!$LSyp8@^W&MV=#yKAuH?Tm+sGR;bA9QCA zGxRPhhsXHIf1#^d;r{}K;73{Rq!7wZTz!q)l7f4P&pgba+%X$%k9-2vRabRbJjWe0 zPc!Djzkq3T3gb+x(^>6;{rYRH2g{IpJ`+%u8}B1e_$`co@jn@{QewjXO(jzIzmB@m zmR_E7ka^lkNcjZ4hS?0Wlxy)E#V|_5IFg9&Vf=o7OUGU+Oq#*51)%_ywlx7B8CW1f zzrST)nq?u>Z$~Bb%^X#2S>~@TMBT|vlS&1sAASGOZb{SGDi_Ue;6Y)S~dF-wolKeYok)$sVSz^Ka zDE1s9jfbD<@E4qc)b}%Br!c+}r}+NhiCT&gmZukdXisKefU_Ub7b9r9pOPoh{-mzR z#G8pGj8DqJbJ^3nYko;Sl<>da45bFvm8~zKZX~>DrvlBJqX^y4#N5kE34)$eO?L)Hm8qa0K-+ao0OPSUm;q_OkP-IkHTrM07 zDJMJlu0Mp){NN$Ll^sWYhZ* z>CokS8#kc(A%^|86v$Gh`dj~{e8%f&PYQ?fz_^6Rt^DDy^Y}0ykqL*g60(fEOjNc- z>7mG`Tz6EX{+HiE?Yg^80NF5DhFoz_Q024C$fTUX3LIG`<0RHHBP7C5nr+Id4a^r%DXYx+d@!Y5_^42!by`M&yO#+g zi@9}8pIC+Ef4pgA-UCRPiM9TRe|Mmr@TIFkh>Nv+hqF z$}y=t5=(ctbneD2?}5-$d6)XsOJ2w_G3LQqL=O#j|3+7qGi@J4;Jyaf|Kw$Vysp=o ze}7?lTfsvXr0m);9#`xVe~~MqP$eBCedOq_V0uEzx2z1Y$$|ZYMntcD8fAa@IRdif zYkxh%6Oy4;9KK?B#Ve3XJy?Mg+rCbY&gQ!=Q1UoHK=RagYfSd_Xl|?Moc1UypV>B3~~^|@1Hj8|KssF8iW7Kd$OzG zVB$o>Q99i5dl#IqPDI5oevFFvazZ1TR%3}F6#{uc`qxk_E7!_ydot{9D3F3k;V8`w z);fb0iXWa;wb&C|4fM8-!f-+sh%=Fw{!aLBq+tASX0(j5xpO0$|MwL%I-f!D^)%g> zJVq{)M|Lq=#pk|j!n~7zD)S(^LxJafI|V7f{Q~y%cQLsoM9tX|90Huuxp}{s&#gU8_i%pb*49#0l3-bXJ zp~q>vx3e5fNoB zX(dX+G~w*!k;e;Z!s@Xtp591qE6l7VgKu^mFeQNR0{G6Ow{ascWvHi=tw(Gauh83& z$$wpktae43uzty+v6<(LpY%64Pgw};eq?y&?>Mb!+gO9>Z|QC9U;!PfCM)qQUr)if z_#WV+0$TXdsc5ZSkBUF~(f%_7_A|UKVLVn{mHd_bl=jnpmb=*e4(74-qZ|ZpJ%G}u zZo`2_35$Fgdqf!!L#jBc;F`b+9v_C648kltEDZMgRs>(T83%TXXCVdQME5Rw!Kpwb z#6+p$DV2vaH43Ll1b-#M(h*G0EjB@lj~H$$4jKC|%R=^U3OeJZRG#8^8Bf1}=&)`7 zD-+3XN7ZXg$6qtt(vd$D@2z1zHav~;VOgK5zeruJL+!l=8vomc$hR55*LYjXVzQdl zC6?}!#8%NMCyOq^RcF^LUsL1r6^L9#sp<1Q+MOvdjWJY<=f?q!-q#@IuTga(Hp6VPOq zbsN2tHKnjuJ&8K$Y#mOVH(}i01p9Y9m1V_~?Rm&D>pRj=H)@BJijntUXj``hmG|0c z{S5Q-7c^L?*kc<(4J19J43{&1SMc~5^Y$ZNxUXwQ)gOL{y6r1a8TYJ}Br#-74m9h$ z??#?XT6#YZsjNwXg-rg*5Z^hOu=3AEdSxY=WxB6eZ)#0+gMv11COk`-X49B(OdlC> zW^LY%h-(4-GTVL%?}vD7H4&yYY@E!BC(CsAG?Z1=7Ye4qw_+8VhE3qgdS{m-cgb|P zze53Y1;Z+{fom9-e^5`Xv0zIXlfA{eZ)7CpLG~Dbm7f{>JMl<7{M_9J`!^4w;&p1& zVevM)vJFjOKfuek-y&p(Ci z=R;^e?CJ0XX}~xI%xf9QAnDRIZ6r^{un}b-o`tL?@t7B(2SNzkbqQLZ{RV2c{S6Im zt5hBg8AGNxWZd1w$hew0cMdCRPfH>U2L7ZWI||OWV9s5Lj8Fm01`n<43bib{<2?l_ zXVbHo&GeG_0Clv|SH6LUre(;uNYaq^D8QW62AmZRELqk;Rv&)bZgND*i!}SZ_&k~i zvVh+}@Scn8Q>VlG6%*!V44aJG5At&j!|?zGjBMB?{T)5*vEf8m{?q4Y`_AKNtThbvM zl}--HVx_ReJCJ-xXIf3ogE#F6P#b_F`!z_%u$PLZ!GUe^d)8%Xj_Q6iH9EL;@L?3G>hsbypGSF7J>hS4M%pVl5IkzIkbneEd4dcdd6uH%So(R zlkwc{MewnWXp-L;QH%6(1P{IkHGkvj(>#*l!HJi#aTQ7>??yCk13~(lo3kVF>2e|joR z=}e~JHBxD{y|x!k2lC-PHCI->?-0nlf^co4RnPQvWKl#}(X^+&DGF;RvlwnF8gutP zv`cfskZ?P4W=%!fR~VLe^RnxfsfT&U{?_kiT$b==Pvt8>3GxKLmjxQ*69TIY*gtJX z#zk>}7*y9(9Ob*Qju*{G5jL556m2Pq>DQyA=)YZVm1hTmvaqiUta$G`PDv!L>+$LMc!PQYaLc;94jZ zT*?m%?r=CCIJ1^e9=kHW< zlosBqtB_IJZukbQh{k(Bl1pNVtkwKP8@o6P}LP%~;TmmxEIELFte zUV$8m1s^roDWVlCLY>%v2G`<1N2P7Hq&?>yd{tycU2VKTpE?bumG|@UX8Y($j*Lrt zW2Z=hH?2gzO$6nUH10N|J!2~}5;#L|w)@h%Vk$gZWINNTLSJQv&FLU!pu-Sf3;Ar!>jo-gG{yK0GyMrfk6?*|GZqFW?Ue z-27u|+^PtwN(*CfZ1Pi?PF~94&vR4sWn&+=8|Wp%D5K5X3wZrtB6#Hl?cY;L78 zqx}Fw{=e86cfbkRp;}18dw0yS7VKrdDz<~0Pw3!e%TUr7XIOumy2U_Rz1H$5sGH=@ zp7}J4nS}y&8IE(C%Uxp{>gCUUd(MzErUfsaXOw2+uJeyW#)XC@Gg&BZEv6yf{x*kw zG}cg3tCW6<{2j21B#Q++NG5qmuM#-|3-Q$&rD^?b$BQG+7G#tUETcjGMarfY;=#DH zv_>^LD=}#&5@XTrOEJy4j3C&i!cq=IUTx{UH%?`?cy3Yuo9Gg-m$;Q)mKU)n9ulMhutvHLz{nBr<8jJi*hEaNiLPddM|OP{K{RK zRaC%?UoGF-A73Ad$w#MjkOPDc(DTe1uaG=8DLTKxr$1>GuI-`Hh@Ilh*Iv#S6<8xbd9{lWDsOvD+e?t1z(WiJ z87zJs69Ga0LXI^pS;3S zmyK~OG<|B>P%Ie!kK+EvUiGqM&PAq8jQgJ8mG7ILf*$$j>c28ievUZckXd}nV=iwg zBk47>a(2~%xCo3Y1D+42w%p5%J;yl&#N*$<68mLeg)S%rx z%T6{vsP5kVXb*+j#QrgQR`yS>ft9zPcS}X*;%+ZJY+LV2seojUemMhdXiU>VH2m-+ zSLS7jTeETK_qnyqstak%mEkMT&zv#!;uC}c0KUm9VZ>9fINc7eYgeHoo~FPgT!`x1E{Q!~>4dvVr^4&USUhxSTT1X|+0J z8~h3-e}#D6Dwpk4|8ztQN>a1)x*v)pGT}tPJ}nw${PR8 zgd6)w7`Rx+U=8bUef|in1vMOVUWt61E}MZFdC&zwIFTaaLch$PP8|1GAY@5$fB50M zo@V!0!e)DgkWvcf!&lBk6atc$WFDzMuOIeCX9uRO+Wc{ut7Ze8C|>z0{= zdtx6PtZ3@~P^_480uJ7mVK2dc8$@Y;DX%#oh&(c2(lIe^^tC3If!Q(qOZnDQ775x^Y&kR_qE^ z2>JA9RSw=KdnaNvMPgdX*CxnUd>Y=ox8hHc%425t*Yy`#c)u7-6~XC}gMU)AUrBDF zBVRF6Y4VAax-jC`^N9Oyk<#lCB@XfR-ygZ7Rxl>su;1fTA1>*My4Ytom#@Pup4u4{ zkz}0-Lp3taOV0faEvp4itUntVgtAG7wcB56uxOhxA~SY5D_*b1jm(*6qVgiBO|Xli z12Rb7ha8Bt#tExr`F#%LG0h;WjkRHsr+koQj*yBQ(J|TX&WJ5!I2X= zQtPw24_q_KAIK5NbrQ@s{~EJsf1UU&Gib#08J1&76q-zu6}{=;oCDYx*2im%`17At z^hcz@$k5AmHoRSloRdNV$l;Gcci%hmGRaamUEJ9s)o2Dk!~s4D^8u$>Y;=V{s%piy zNW`NRA!3dXjw^@YckT~tD$f|$riwRWAO+ElI+yb`cTUlhO(ol3c^Rl!vXV@kvnyQR z=QTSetr6;n=UPXz-FoUaQGF-4Wu5W^b`b&2f1+JJw%59FdEG!+h%9z=uuT=t2meBN z$&6glh7Mjr1G<3cQxY%iZ!5dU(aV;p90Cu?tJTGyUyzfQvSr{j1w0Q1hMg1epLPg= zo|62XO2lU0@rwVG7nf4#y*Z(`B>jk}yRkTz%wpr*rCugUO61t$Cu9Pw=c9}!m(7Qf zVd^r*?_ug2zLu}>_y!!Sxv1l%ar^Cehp6z=K1uGY&qpTd!i&Yo9yolQQ;chLD5vtC z8+VY`D3SP16Rq$O2Qr_IOgYc?yIV`yj!sWq;TL;r2xb=#JLqBW?!mYD16m7oHi{v1 zX{}{j4FqZ8ZxX85^}&7an@Oy@lY*kfPA?v=1G5w#cTyEoHgsGDM%1deLmK={5f}O& zZ$Fa%YF%VUZ+B40SjB%Uc)arqOBH-pEjFCZ#3qIms#A4-?*8OtU#go_E0Yq`=L(K!z8zzPCqS&9_zHo;e5jsmI@o4^ z&F|=iMsdQir4;v5fR;#u9ZHcLLD!U@gHb%j9)~2&I#W0A6kgqs+z=#snRv;&tB^?p z1AOSl3Wanv(w3z#x0U$y>TR4N=G7y##7u3PPyNVFEsi-WWz?7bYP)w6dE@v40c1O@ zXK|mZ%});^>W;*nY*p0{)v8m9K}M!2*&EdK!rczm%L*ErseBH(6+w)PtU)S-wSLDC z!NmvssCtMoQ2qu#^79yZJVA671@XArtLqq1)1ye&&qS?iu0M6{xb(UDCCotU8lHd-b_?T-Gh~6nY1T1!EHqG7@`8CkeI;c9qqAR%0n-k{SfBsLS z`LI^a|7gQGtMy{$kBmz&Q-IW)-dnJS1HFj)Pu<|>`f5uh!7MC_eO>?s9*!1ce?xg{ zl>*%hAdDGlXLkB#w;eSgFGI}FFDPj{meUHnHtfs?EekLhj=&x+t(z50qHmm*y1$*u zse@w^ph1lFndwMDvO}T(#c3Hvc6ZWwjE@KN|Kxe6)x|cttly z*|s`8-sMt{EdTDJn>4T}SErABN}2SU1WcT9@q%mSKnoj;qz=A&D#?c-F?xrI=OM-} z|3ppH0d^U+(&P%XyEaH$tg;(gqkI>?2 zz8-shzQ(H9xcW#hV9bBJ*X|{HQqIR*sDXfnbfUB-61Iemcs{u7_R=XnOZziG5S=+d zRft)|@N;7q4u48Ju`eYVKZ$D;!KvcINa39mrqV_x5ng0PT-g zI13Z?eQzf)rNPqe6*-j)G;0nX(s$&&4V@BQjqeK(+3;ch;;4NZA)L0%o_YOm;?9wW z{_$7@;ucE&12_+%jzuK1XVge@_k8!4|3ho!PwXwmOhJyfXZv_Q<*YCtpuk%3xZ%rR zyfZxuk6Os4v^(&!J@BwiEicWy#y!cqqm|QswzOB4uC%vNqVjlHaMQx+mw^=Z9{tJdO7U4Ew!L01a? zdoGI_%%cbj~dzvUd zfv-TQhzpw4xls9Opmt?OV>QKa_bT>l@#RK8n5#2^aFXr=*;ri3f-H5t2N=67Gtq8B z4!~DTX7^TK;N8ZvUjsMHG+ZaLh;xi)m?G@~teH)}6T@Yl^2i~4A`KQr_~HhMx7Izb zd~377-g$y2ZCs}7$UFM8)JFA?&ObDo;F0L36gs#xF$y`??#9&TC#-pH1p5ZNqteQc ztIdCv-Z~$9D%_>lDv~XcA4mxYO09`f)+L8MC{Pa7ldE1s*k>`qxU*5zkRo81x@;ca ze+l@{VH7`G&U#4EnmI7F-wY)9ho^`Zr)xBU`Nk9^o*HF=N+T;2eIuGmM5hVneEt=* z!K0xp^XSX)XnMhG2~ZwnfKb^D#RMqI6N156o1#X&7m|t*h^$@FP*}e|kI0}bQx8l| zQ%_nc5TjQ~DM5D0&`w%(+Zbh|`}tQCf=Dn=>SS4*8JYFeBbEfcXu^L_=zFVDTQIu>zm92WuW;t(%5(nfNpZA;bacH3 zB@#H?Uu^O0Xj9VP5f)E$_4XKPPstiEkX^?c7CQ!?0nhS4?0Q1`HJsgq*kA3i1vZe^ zo#$SL4HO}G%cCp!QW@YhVg%*i&83zIo3i z&h@vvASq4(W4G21Jf?f^7w4~!WY7-H}6xt??wCo3WNpK&5m})_R7t=__RzoU~(dEejYGQfibo zV(LbAG)#`Xp_45v!+uGX=*gHaIA|Bb)V|}?d-DPU7{NsKGBWrjt>s$j^k|MiqzsbKiwHopN+w5wy|^hU$Pyr~}wq z7o)Geg%E{%Yn{eviNJ$!Q!1`}PFLyo-hkQq;~qFz+e0^)wG*V$c|u{bj zBi}-2F*gMo?Fwly(IqD}-GiH{gK@QusfMir8Bfz6-b*D9c2ccLDBHOlru3Z-u*|SF zHETA-F#e7>2*4iYF5UW}@spv+Uf<+>E(TBLOzzbfZ@EKdRC00#4(65xpp0`$w-YZf zRI~Al<3kWsI_b5jq7UI6R~36z!?X80f_m>QlinWx!@Xrz2OB77AfzWXbb3KoQ)P^n zdfJ?r?yTY_s5(B)tK-EPc1$0=28{Sx%{E|S&mmvD{85~r2{xF}QMWk`|7dwTTI;bN z18-<$x3N+ z)xU22>DeBR#%1{1^-PzjY@*lX86rf<4Hk-g%j5 z{(d};ROhmBH=)~Mv^pamt_WFkqtM|6_DMCN*Yfq^iDn>Wr2N}p=VxI z9Fv^oDyldtQg`4?Ii*D%k0|QlRP!*eVn4?u%=7XWRx`$PmSA`({L>I`8fhY1BnM+Q ztHq5ZV>P!c4_TxF+2}+ZWwWwV5akF0*ma<#VuzV2n`OkGnKh-LHAMcJbY*^2{Sxmb zgXN8D8L8%(l-2&|W*9zgNOIgd=}A?mh38k3AMfBXN4VcKs67z43X4G zSdio?jz2e?1()~F>kPO1f4=YO$lc{BuOal0znp0SxK_X~lcYE~wod#T#VNOum~FWR z>Ssks@IwWFFb}5R8F92K@+jdh9l<*+6-A?GvQ~J-g1Q$eUPiGn3>4^1Qs7NyuPEa% zrBc4nDDY7F-eP%$+)HomiM~~vXFz%iW}#Q|UTcqZ6HoXq@m1eIoxF3PYbWD`roq6{#8|}Y zM!fiTshgoBS{0*6sLq|Vuz^#bNDk`$&VH>lJLEY$-1}mTZX+O6gK8}%-~IKP%FU7& z9B|yLm7nOXr~K;H`4x^bIIH)CGus(Sa!EeHT}lHfOszO}9pzLB&tYArG~z_0cepn%zV5{#NcQd-fZc0J+DJ-1pZCAAlBWH>Ig~g<;sp@uz{+QhjV~zSW@5V z`73vH{GWeqU(OkDf}Mau*21yRGi*_#7N{Kn$@?1N3-B%IGctZ^-P4n}3M422Vll@Cg>b ziWuE+8M<<(_RW{^3XX*>%>}qpc7?I@diL)@yGhPeqvO#S`jO6StA@1iYSD zRy-U^xm{)oT6ohF?2Wa56N10^MI$AP;K0f(3p`LNH2bJ>Z1YESdBP-LRFeGgXF|^7 zy%;?i+6rfYwJoQ3NQ7@X45JO1{=}=zA5+DrGHUFO0thwTaE0K_eX{O#z)PB7e#p}P z6!r~6?c%ZFifi9cY72 zO-x+j(I38@;Nd`qwV;RCkItm>x26b{3%^`ezC_?SagCS{dvKD@YEGpF_whejDzgIS zR-`H3Cz=0^%U_}%D8nq$dhWlJy^fB~fI_)1$MAnB#O3tAL0tb3^k*4Ub|%Ump5(P^ z880E;PV=rwg6GQrHwXWB1#InF5Pvv>U^yia4aqv)5xJoi?GS4%;#7({B5~KS3iLHi z7e{tU2+17HnvIHMYr)ztSdaC@PB&$Y&{%`GN$=KaATG& z1xh3jo#d8#7J1%zUl7DEp71pT-a18OrRZ5mTi95l;D?4t^AN|o85r1nzl!aa$J%h~ zIOh^wMj~1J*ohOzJ7v#QKZ>TLT>a|1X%R~%Q-#%)>F))AS-tBa7g6a<2Ne`yv1?x@qbb5G`<0E(=_Hja{_~J{3{(RPZkDNg6^e(`K3c9)dh{ zuN74KoUI~NA91R^Ux=1zP<sr@Y}`BEIm(?-%(>mq^;_Rk7#wA903J9ve842)Gn)#&Lv@GccL|W{SQr z@u)rRmHtV(aSHxfg0RoHX6o4e@Ziia`se{uy0BeK8(y%sP@UR|%9ECf{KvxH5Y|Lb zeK{91J5fdD7!OEZ?^!fLpIWuSHeI+spBnH-cf6awJ9vek6-INtQu1tS`07J*!tlzR z&e0}Jj-qYDuzIC;Z^QHYYy&^4Z>fcx?^@SxQ-W=8T$DYxV=Y6m4j>QJdXMmyAg_>* z&ya!kKD;F#%Gs)heTY&1aS|F>ikw@Qe^|biy>a>0r3TJov+pUl76t{r$F;JT(8(M! zrS0tg9f|VfPZ@o(u_|I%Q;^OwQkc=RS>{fO_gu}n!l`*6F1(3|WOdv>GKyFa9&@Wo z`IcoZ6q5&XGdE}(u#mo?FL!cL0D5Al{aq%1kT*(i)r~Z{q%QI{yTy5WJNiYWpx+61 z--Iqj{R2(G;yp#3;ZEN#EPrU;JBE~C3o%{6dxw-H&A?aiM?!wd{7 z|C}2jSaBD?dv2kTY)>?K0hxCTBV~L2&ls%nBEb}04DZhVSkL@Br}AJaX8owmu4q8S z#vtlCZEB-oT;6mKeWfB<3jBH^7Cx??k1lcQD}W7fN7K)eJvSjfDU!c~K|_FQohD#% z;a!b-h3-^At+Y$B+3g zCTVp92Ko=lyRTcV#XV!3*K^b{3CSHKS#j?T=^$IypKx~JSLeNQg(OMU=qB=x^1jic z*5rATPE~nCvbs9WPZ_;uciHmr0x0Y`~@rHuT>8$QX$NG$1d+vyQMv^eFt=mX` zdsghbKC)l)Qwgfrp;e zNN24LWaR%xnGT%9nX0wC;>NXuG-K_-)MCc3Ob5%JHqKch8$*Qt;R>g!I+*JJzyJGx eAPY={e#8i@-M`EE@WbfY)6iBo0M)D7M*a`W-Z16> literal 0 HcmV?d00001 From f29b0f2f26a5b33a88152f94ecf6468c5c07e73f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 11 Jun 2019 17:31:42 -0700 Subject: [PATCH 0541/1504] New UI, simpler --- plugin/src/Components/App.lua | 86 ++++++-------- plugin/src/Components/ConnectPanel.lua | 105 ++---------------- .../src/Components/ConnectionActivePanel.lua | 57 +++------- plugin/src/Components/Panel.lua | 34 ++++++ plugin/src/Components/RojoFooter.lua | 69 ++++++++++++ 5 files changed, 160 insertions(+), 191 deletions(-) create mode 100644 plugin/src/Components/Panel.lua create mode 100644 plugin/src/Components/RojoFooter.lua diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 79436972..d6a3ebe4 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -54,7 +54,6 @@ end local SessionStatus = { Disconnected = "Disconnected", Connected = "Connected", - ConfiguringSession = "ConfiguringSession", -- TODO: Error? } @@ -71,12 +70,39 @@ function App:init() sessionStatus = SessionStatus.Disconnected, }) - self.connectButton = nil self.currentSession = nil self.displayedVersion = DevSettings:isEnabled() and Config.codename or Version.display(Config.version) + + local toolbar = self.props.plugin:CreateToolbar("Rojo " .. self.displayedVersion) + + self.toggleButton = toolbar:CreateButton( + "Rojo", + "Show or hide the Rojo panel", + "") + self.toggleButton.ClickableWhenViewportHidden = true + self.toggleButton.Click:Connect(function() + self.dockWidget.Enabled = not self.dockWidget.Enabled + end) + + local widgetInfo = DockWidgetPluginGuiInfo.new( + Enum.InitialDockState.Right, + false, -- Initially enabled state + false, -- Whether to override the widget's previous state + 360, 190, -- Floating size + 360, 190 -- Minimum size + ) + + self.dockWidget = self.props.plugin:CreateDockWidgetPluginGui("Rojo-0.5.x", widgetInfo) + self.dockWidget.Title = self.displayedVersion + self.dockWidget.AutoLocalize = false + self.dockWidget.ZIndexBehavior = Enum.ZIndexBehavior.Sibling + + self.dockWidget:GetPropertyChangedSignal("Enabled"):Connect(function() + self.toggleButton:SetActive(self.dockWidget.Enabled) + end) end function App:render() @@ -98,7 +124,7 @@ function App:render() end, }), } - elseif self.state.sessionStatus == SessionStatus.ConfiguringSession then + elseif self.state.sessionStatus == SessionStatus.Disconnected then children = { ConnectPanel = e(ConnectPanel, { startSession = function(address, port) @@ -135,50 +161,15 @@ function App:render() } end - return e("ScreenGui", { - AutoLocalize = false, - ZIndexBehavior = Enum.ZIndexBehavior.Sibling, + return Roact.createElement(Roact.Portal, { + target = self.dockWidget, }, children) end function App:didMount() Logging.trace("Rojo %s initializing", self.displayedVersion) - local toolbar = self.props.plugin:CreateToolbar("Rojo " .. self.displayedVersion) - - self.connectButton = toolbar:CreateButton( - "Connect", - "Connect to a running Rojo session", - Assets.StartSession) - self.connectButton.ClickableWhenViewportHidden = false - self.connectButton.Click:Connect(function() - checkUpgrade(self.props.plugin) - - if self.state.sessionStatus == SessionStatus.Connected then - Logging.trace("Disconnecting session") - - self.currentSession:disconnect() - self.currentSession = nil - self:setState({ - sessionStatus = SessionStatus.Disconnected, - }) - - Logging.trace("Session terminated by user") - elseif self.state.sessionStatus == SessionStatus.Disconnected then - Logging.trace("Starting session configuration") - - self:setState({ - sessionStatus = SessionStatus.ConfiguringSession, - }) - elseif self.state.sessionStatus == SessionStatus.ConfiguringSession then - Logging.trace("Canceling session configuration") - - self:setState({ - sessionStatus = SessionStatus.Disconnected, - }) - end - end) - + checkUpgrade(self.props.plugin) preloadAssets() end @@ -189,17 +180,4 @@ function App:willUnmount() end end -function App:didUpdate() - local connectActive = self.state.sessionStatus == SessionStatus.ConfiguringSession - or self.state.sessionStatus == SessionStatus.Connected - - self.connectButton:SetActive(connectActive) - - if self.state.sessionStatus == SessionStatus.Connected then - self.connectButton.Icon = Assets.SessionActive - else - self.connectButton.Icon = Assets.StartSession - end -end - return App \ No newline at end of file diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index 9d26215f..0d47eec1 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -4,25 +4,19 @@ local Plugin = Rojo.Plugin local Roact = require(Rojo.Roact) local Config = require(Plugin.Config) -local Version = require(Plugin.Version) -local Assets = require(Plugin.Assets) local Theme = require(Plugin.Theme) +local Panel = require(Plugin.Components.Panel) local FitList = require(Plugin.Components.FitList) local FitText = require(Plugin.Components.FitText) local FormButton = require(Plugin.Components.FormButton) local FormTextInput = require(Plugin.Components.FormTextInput) -local RoundBox = Assets.Slices.RoundBox - local e = Roact.createElement local ConnectPanel = Roact.Component:extend("ConnectPanel") function ConnectPanel:init() - self.footerSize, self.setFooterSize = Roact.createBinding(Vector2.new()) - self.footerVersionSize, self.setFooterVersionSize = Roact.createBinding(Vector2.new()) - self:setState({ address = "", port = "", @@ -31,24 +25,14 @@ end function ConnectPanel:render() local startSession = self.props.startSession - local cancel = self.props.cancel - return e(FitList, { - containerKind = "ImageLabel", - containerProps = { - Image = RoundBox.asset, - ImageRectOffset = RoundBox.offset, - ImageRectSize = RoundBox.size, - SliceCenter = RoundBox.center, - ScaleType = Enum.ScaleType.Slice, - BackgroundTransparency = 1, - Position = UDim2.new(0.5, 0, 0.5, 0), - AnchorPoint = Vector2.new(0.5, 0.5), - }, - layoutProps = { + return e(Panel, nil, { + Layout = e("UIListLayout", { + SortOrder = Enum.SortOrder.LayoutOrder, HorizontalAlignment = Enum.HorizontalAlignment.Center, - }, - }, { + VerticalAlignment = Enum.VerticalAlignment.Center, + }), + Inputs = e(FitList, { containerProps = { BackgroundTransparency = 1, @@ -151,17 +135,6 @@ function ConnectPanel:render() PaddingRight = UDim.new(0, 24), }, }, { - e(FormButton, { - layoutOrder = 1, - text = "Cancel", - onClick = function() - if cancel ~= nil then - cancel() - end - end, - secondary = true, - }), - e(FormButton, { layoutOrder = 2, text = "Connect", @@ -182,70 +155,6 @@ function ConnectPanel:render() end, }), }), - - Footer = e(FitList, { - fitAxes = "Y", - containerKind = "ImageLabel", - containerProps = { - Image = RoundBox.asset, - ImageRectOffset = RoundBox.offset + Vector2.new(0, RoundBox.size.Y / 2), - ImageRectSize = RoundBox.size * Vector2.new(1, 0.5), - SliceCenter = RoundBox.center, - ScaleType = Enum.ScaleType.Slice, - ImageColor3 = Theme.SecondaryColor, - Size = UDim2.new(1, 0, 0, 0), - LayoutOrder = 3, - BackgroundTransparency = 1, - - [Roact.Change.AbsoluteSize] = function(rbx) - self.setFooterSize(rbx.AbsoluteSize) - end, - }, - layoutProps = { - FillDirection = Enum.FillDirection.Horizontal, - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - }, - paddingProps = { - PaddingTop = UDim.new(0, 4), - PaddingBottom = UDim.new(0, 4), - PaddingLeft = UDim.new(0, 8), - PaddingRight = UDim.new(0, 8), - }, - }, { - LogoContainer = e("Frame", { - BackgroundTransparency = 1, - - Size = Roact.joinBindings({ - container = self.footerSize, - other = self.footerVersionSize - }):map(function(values) - return UDim2.new(0, values.container.X - values.other.X - 16, 0, 32) - end), - }, { - Logo = e("ImageLabel", { - Image = Assets.Images.Logo, - Size = UDim2.new(0, 80, 0, 40), - ScaleType = Enum.ScaleType.Fit, - BackgroundTransparency = 1, - Position = UDim2.new(0, 0, 1, -10), - AnchorPoint = Vector2.new(0, 1), - }), - }), - - Version = e(FitText, { - Font = Theme.TitleFont, - TextSize = 18, - Text = Version.display(Config.version), - TextXAlignment = Enum.TextXAlignment.Right, - TextColor3 = Theme.LightTextColor, - BackgroundTransparency = 1, - - [Roact.Change.AbsoluteSize] = function(rbx) - self.setFooterVersionSize(rbx.AbsoluteSize) - end, - }), - }), }) end diff --git a/plugin/src/Components/ConnectionActivePanel.lua b/plugin/src/Components/ConnectionActivePanel.lua index e0a8da26..47cb1aa5 100644 --- a/plugin/src/Components/ConnectionActivePanel.lua +++ b/plugin/src/Components/ConnectionActivePanel.lua @@ -3,63 +3,42 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) local Plugin = script:FindFirstAncestor("Plugin") local Theme = require(Plugin.Theme) -local Assets = require(Plugin.Assets) -local FitList = require(Plugin.Components.FitList) +local Panel = require(Plugin.Components.Panel) local FitText = require(Plugin.Components.FitText) +local FormButton = require(Plugin.Components.FormButton) local e = Roact.createElement -local RoundBox = Assets.Slices.RoundBox -local WhiteCross = Assets.Sprites.WhiteCross +local ConnectionActivePanel = Roact.Component:extend("ConnectionActivePanel") -local function ConnectionActivePanel(props) - local stopSession = props.stopSession +function ConnectionActivePanel:render() + local stopSession = self.props.stopSession - return e(FitList, { - containerKind = "ImageLabel", - containerProps = { - Image = RoundBox.asset, - ImageRectOffset = RoundBox.offset + Vector2.new(0, RoundBox.size.Y / 2), - ImageRectSize = RoundBox.size * Vector2.new(1, 0.5), - SliceCenter = Rect.new(4, 4, 4, 4), - ScaleType = Enum.ScaleType.Slice, - BackgroundTransparency = 1, - Position = UDim2.new(0.5, 0, 0, 0), - AnchorPoint = Vector2.new(0.5, 0), - }, - layoutProps = { - FillDirection = Enum.FillDirection.Horizontal, + return e(Panel, nil, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, VerticalAlignment = Enum.VerticalAlignment.Center, - }, - }, { + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 8), + }), + Text = e(FitText, { Padding = Vector2.new(12, 6), Font = Theme.ButtonFont, TextSize = 18, - Text = "Rojo Connected", + Text = "Connected to Live-Sync Server", TextColor3 = Theme.PrimaryColor, BackgroundTransparency = 1, }), - CloseContainer = e("ImageButton", { - Size = UDim2.new(0, 30, 0, 30), - BackgroundTransparency = 1, - - [Roact.Event.Activated] = function() + DisconnectButton = e(FormButton, { + layoutOrder = 2, + text = "Disconnect", + secondary = true, + onClick = function() stopSession() end, - }, { - CloseImage = e("ImageLabel", { - Size = UDim2.new(0, 16, 0, 16), - Position = UDim2.new(0.5, 0, 0.5, 0), - AnchorPoint = Vector2.new(0.5, 0.5), - Image = WhiteCross.asset, - ImageRectOffset = WhiteCross.offset, - ImageRectSize = WhiteCross.size, - ImageColor3 = Theme.PrimaryColor, - BackgroundTransparency = 1, - }), }), }) end diff --git a/plugin/src/Components/Panel.lua b/plugin/src/Components/Panel.lua new file mode 100644 index 00000000..5ae1e874 --- /dev/null +++ b/plugin/src/Components/Panel.lua @@ -0,0 +1,34 @@ +local Roact = require(script:FindFirstAncestor("Rojo").Roact) + +local Plugin = script:FindFirstAncestor("Plugin") + +local RojoFooter = require(Plugin.Components.RojoFooter) + +local e = Roact.createElement + +local Panel = Roact.Component:extend("Panel") + +function Panel:init() + self.footerSize, self.setFooterSize = Roact.createBinding(Vector2.new()) +end + +function Panel:render() + return e("Frame", { + Size = UDim2.new(1, 0, 1, 0), + BackgroundTransparency = 1, + }, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + }), + + Body = e("Frame", { + Size = UDim2.new(0, 360, 1, -32), + BackgroundTransparency = 1, + }, self.props[Roact.Children]), + + Footer = e(RojoFooter), + }) +end + +return Panel \ No newline at end of file diff --git a/plugin/src/Components/RojoFooter.lua b/plugin/src/Components/RojoFooter.lua new file mode 100644 index 00000000..767e82bf --- /dev/null +++ b/plugin/src/Components/RojoFooter.lua @@ -0,0 +1,69 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Config = require(Plugin.Config) +local Version = require(Plugin.Version) +local Assets = require(Plugin.Assets) +local Theme = require(Plugin.Theme) + +local FitText = require(Plugin.Components.FitText) + +local e = Roact.createElement + +local RojoFooter = Roact.Component:extend("RojoFooter") + +function RojoFooter:init() + self.footerSize, self.setFooterSize = Roact.createBinding(Vector2.new()) + self.footerVersionSize, self.setFooterVersionSize = Roact.createBinding(Vector2.new()) +end + +function RojoFooter:render() + return e("Frame", { + LayoutOrder = 3, + Size = UDim2.new(1, 0, 0, 32), + BackgroundColor3 = Theme.SecondaryColor, + BorderSizePixel = 0, + }, { + Padding = e("UIPadding", { + PaddingTop = UDim.new(0, 4), + PaddingBottom = UDim.new(0, 4), + PaddingLeft = UDim.new(0, 8), + PaddingRight = UDim.new(0, 8), + }), + + LogoContainer = e("Frame", { + BackgroundTransparency = 1, + + Size = UDim2.new(0, 0, 0, 32), + }, { + Logo = e("ImageLabel", { + Image = Assets.Images.Logo, + Size = UDim2.new(0, 80, 0, 40), + ScaleType = Enum.ScaleType.Fit, + BackgroundTransparency = 1, + Position = UDim2.new(0, 0, 1, -10), + AnchorPoint = Vector2.new(0, 1), + }), + }), + + Version = e("TextLabel", { + Position = UDim2.new(1, 0, 0, 0), + Size = UDim2.new(0, 0, 1, 0), + AnchorPoint = Vector2.new(1, 0), + Font = Theme.TitleFont, + TextSize = 18, + Text = Version.display(Config.version), + TextXAlignment = Enum.TextXAlignment.Right, + TextColor3 = Theme.LightTextColor, + BackgroundTransparency = 1, + + [Roact.Change.AbsoluteSize] = function(rbx) + self.setFooterVersionSize(rbx.AbsoluteSize) + end, + }), + }) +end + +return RojoFooter \ No newline at end of file From f0fa7326dd2e1237e823976468aa7fd89359bc2e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 11 Jun 2019 17:52:12 -0700 Subject: [PATCH 0542/1504] Add an icon to the plugin toolbar button --- plugin/src/Components/App.lua | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index d6a3ebe4..55df97d2 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -1,8 +1,10 @@ -local Roact = require(script:FindFirstAncestor("Rojo").Roact) +local Studio = settings().Studio -local Plugin = script:FindFirstAncestor("Plugin") +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) -local Assets = require(Plugin.Assets) local Session = require(Plugin.Session) local Config = require(Plugin.Config) local Version = require(Plugin.Version) @@ -51,10 +53,16 @@ local function checkUpgrade(plugin) plugin:SetSetting("LastRojoVersion", Config.version) end +-- Since we need to switch our plugin icon based on the theme, we use the +-- insta-deprecated theme API. There isn't really an alternative here! +local pluginButtonIcons = { + [Enum.UITheme.Dark] = "rbxassetid://3294408143", + [Enum.UITheme.Light] = "rbxassetid://3294218933", +} + local SessionStatus = { Disconnected = "Disconnected", Connected = "Connected", - -- TODO: Error? } setmetatable(SessionStatus, { @@ -70,6 +78,7 @@ function App:init() sessionStatus = SessionStatus.Disconnected, }) + self.signals = {} self.currentSession = nil self.displayedVersion = DevSettings:isEnabled() @@ -87,6 +96,11 @@ function App:init() self.dockWidget.Enabled = not self.dockWidget.Enabled end) + self:setToolbarButtonIcon() + self.signals.theme = Studio.ThemeChanged:Connect(function() + self:setToolbarButtonIcon() + end) + local widgetInfo = DockWidgetPluginGuiInfo.new( Enum.InitialDockState.Right, false, -- Initially enabled state @@ -96,15 +110,19 @@ function App:init() ) self.dockWidget = self.props.plugin:CreateDockWidgetPluginGui("Rojo-0.5.x", widgetInfo) - self.dockWidget.Title = self.displayedVersion + self.dockWidget.Title = "Rojo " .. self.displayedVersion self.dockWidget.AutoLocalize = false self.dockWidget.ZIndexBehavior = Enum.ZIndexBehavior.Sibling - self.dockWidget:GetPropertyChangedSignal("Enabled"):Connect(function() + self.signals.dockWidgetEnabled = self.dockWidget:GetPropertyChangedSignal("Enabled"):Connect(function() self.toggleButton:SetActive(self.dockWidget.Enabled) end) end +function App:setToolbarButtonIcon() + self.toggleButton.Icon = pluginButtonIcons[Studio["UI Theme"]] +end + function App:render() local children @@ -178,6 +196,10 @@ function App:willUnmount() self.currentSession:disconnect() self.currentSession = nil end + + for _, signal in pairs(self.signals) do + signal:Disconnect() + end end return App \ No newline at end of file From 288c52a2cd2eab0196188d86e52c42cb49b0904b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 11 Jun 2019 17:56:06 -0700 Subject: [PATCH 0543/1504] Updated changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23c45eca..0be0f4c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,9 @@ * Added support for live-syncing `CollectionService` tags. * Added a warning when building binary place files, since they're still experimental and have bugs. * Added a warning when trying to use Rojo 0.5.x with a Rojo 0.4.x-only project. -* Changed plugin to ignore unknown properties when live-syncing. +* Added an icon to the plugin's toolbar button +* Changed the plugin to use a docking widget for all UI. +* Changed the plugin to ignore unknown properties when live-syncing. * Rojo's approach this problem might change later, like with a strict model mode ([#190](https://github.com/LPGhatguy/rojo/issues/190)) or another approach. * Upgraded to reflection database from client release 388. From c77c754f6dd3ad9e9776fba981cc4db48ea8d51d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 11 Jun 2019 18:00:12 -0700 Subject: [PATCH 0544/1504] Give plugin GUI a name --- plugin/src/Components/App.lua | 1 + 1 file changed, 1 insertion(+) diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 55df97d2..b566c1db 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -110,6 +110,7 @@ function App:init() ) self.dockWidget = self.props.plugin:CreateDockWidgetPluginGui("Rojo-0.5.x", widgetInfo) + self.dockWidget.Name = "Rojo " .. self.displayedVersion self.dockWidget.Title = "Rojo " .. self.displayedVersion self.dockWidget.AutoLocalize = false self.dockWidget.ZIndexBehavior = Enum.ZIndexBehavior.Sibling From 90516e035dc1902a9076cdbfb0b7b5b1a6d467be Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 12 Jun 2019 15:11:19 -0700 Subject: [PATCH 0545/1504] Refactor project to start making a little more sense --- server/src/commands/build.rs | 7 +- server/src/commands/serve.rs | 7 +- server/src/commands/upload.rs | 7 +- server/src/project.rs | 122 +++++++++++------- .../{legacy => legacy-0.4.x}/rojo.json | 0 .../legacy-old-0.5.x/roblox-project.json | 6 + 6 files changed, 89 insertions(+), 60 deletions(-) rename test-projects/{legacy => legacy-0.4.x}/rojo.json (100%) create mode 100644 test-projects/legacy-old-0.5.x/roblox-project.json diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index ab353662..fbbb2e2f 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -9,7 +9,7 @@ use failure::Fail; use crate::{ imfs::{Imfs, FsError}, - project::{Project, ProjectLoadFuzzyError}, + project::{Project, ProjectLoadError}, rbx_session::construct_oneoff_tree, rbx_snapshot::SnapshotError, }; @@ -47,7 +47,7 @@ pub enum BuildError { UnknownOutputKind, #[fail(display = "Project load error: {}", _0)] - ProjectLoadError(#[fail(cause)] ProjectLoadFuzzyError), + ProjectLoadError(#[fail(cause)] ProjectLoadError), #[fail(display = "IO error: {}", _0)] IoError(#[fail(cause)] io::Error), @@ -66,7 +66,7 @@ pub enum BuildError { } impl_from!(BuildError { - ProjectLoadFuzzyError => ProjectLoadError, + ProjectLoadError => ProjectLoadError, io::Error => IoError, rbx_xml::EncodeError => XmlModelEncodeError, rbx_binary::EncodeError => BinaryModelEncodeError, @@ -89,7 +89,6 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { info!("Looking for project at {}", options.fuzzy_project_path.display()); let project = Project::load_fuzzy(&options.fuzzy_project_path)?; - project.check_compatibility(); info!("Found project at {}", project.file_location.display()); info!("Using project {:#?}", project); diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 896bbc1b..567c35ef 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -7,7 +7,7 @@ use log::info; use failure::Fail; use crate::{ - project::{Project, ProjectLoadFuzzyError}, + project::{Project, ProjectLoadError}, web::LiveServer, imfs::FsError, live_session::{LiveSession, LiveSessionError}, @@ -24,7 +24,7 @@ pub struct ServeOptions { #[derive(Debug, Fail)] pub enum ServeError { #[fail(display = "Project load error: {}", _0)] - ProjectLoadError(#[fail(cause)] ProjectLoadFuzzyError), + ProjectLoadError(#[fail(cause)] ProjectLoadError), #[fail(display = "{}", _0)] FsError(#[fail(cause)] FsError), @@ -34,7 +34,7 @@ pub enum ServeError { } impl_from!(ServeError { - ProjectLoadFuzzyError => ProjectLoadError, + ProjectLoadError => ProjectLoadError, FsError => FsError, LiveSessionError => LiveSessionError, }); @@ -43,7 +43,6 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { info!("Looking for project at {}", options.fuzzy_project_path.display()); let project = Arc::new(Project::load_fuzzy(&options.fuzzy_project_path)?); - project.check_compatibility(); info!("Found project at {}", project.file_location.display()); info!("Using project {:#?}", project); diff --git a/server/src/commands/upload.rs b/server/src/commands/upload.rs index 6c80485a..c8c0650c 100644 --- a/server/src/commands/upload.rs +++ b/server/src/commands/upload.rs @@ -10,7 +10,7 @@ use reqwest::header::{ACCEPT, USER_AGENT, CONTENT_TYPE, COOKIE}; use crate::{ imfs::{Imfs, FsError}, - project::{Project, ProjectLoadFuzzyError}, + project::{Project, ProjectLoadError}, rbx_session::construct_oneoff_tree, rbx_snapshot::SnapshotError, }; @@ -24,7 +24,7 @@ pub enum UploadError { InvalidKind(String), #[fail(display = "Project load error: {}", _0)] - ProjectLoadError(#[fail(cause)] ProjectLoadFuzzyError), + ProjectLoadError(#[fail(cause)] ProjectLoadError), #[fail(display = "IO error: {}", _0)] IoError(#[fail(cause)] io::Error), @@ -43,7 +43,7 @@ pub enum UploadError { } impl_from!(UploadError { - ProjectLoadFuzzyError => ProjectLoadError, + ProjectLoadError => ProjectLoadError, io::Error => IoError, reqwest::Error => HttpError, rbx_xml::EncodeError => XmlModelEncodeError, @@ -65,7 +65,6 @@ pub fn upload(options: &UploadOptions) -> Result<(), UploadError> { info!("Looking for project at {}", options.fuzzy_project_path.display()); let project = Project::load_fuzzy(&options.fuzzy_project_path)?; - project.check_compatibility(); info!("Found project at {}", project.file_location.display()); info!("Using project {:#?}", project); diff --git a/server/src/project.rs b/server/src/project.rs index 87361dd4..ae2662ec 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -197,34 +197,37 @@ impl SourcePlugin { } } -/// Error returned by Project::load_exact #[derive(Debug, Fail)] -pub enum ProjectLoadExactError { - #[fail(display = "IO error: {}", _0)] - IoError(#[fail(cause)] io::Error), - - #[fail(display = "JSON error: {}", _0)] - JsonError(#[fail(cause)] serde_json::Error), -} - -/// Error returned by Project::load_fuzzy -#[derive(Debug, Fail)] -pub enum ProjectLoadFuzzyError { - #[fail(display = "Project not found")] +pub enum ProjectLoadError { NotFound, - #[fail(display = "IO error: {}", _0)] - IoError(#[fail(cause)] io::Error), + Io { + #[fail(cause)] + inner: io::Error, + path: PathBuf, + }, - #[fail(display = "JSON error: {}", _0)] - JsonError(#[fail(cause)] serde_json::Error), + Json { + #[fail(cause)] + inner: serde_json::Error, + path: PathBuf, + }, } -impl From for ProjectLoadFuzzyError { - fn from(error: ProjectLoadExactError) -> ProjectLoadFuzzyError { - match error { - ProjectLoadExactError::IoError(inner) => ProjectLoadFuzzyError::IoError(inner), - ProjectLoadExactError::JsonError(inner) => ProjectLoadFuzzyError::JsonError(inner), +impl fmt::Display for ProjectLoadError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + use self::ProjectLoadError::*; + + match self { + NotFound => { + write!(formatter, "Project file not found") + } + Io { inner, path } => { + write!(formatter, "I/O error: {} in path {}", inner, path.display()) + } + Json { inner, path } => { + write!(formatter, "JSON error: {} in path {}", inner, path.display()) + } } } } @@ -333,11 +336,17 @@ pub struct Project { impl Project { pub fn init_place(project_fuzzy_path: &Path) -> Result { - let project_path = Project::init_pick_path(project_fuzzy_path)?; + let project_path = Project::pick_path_for_init(project_fuzzy_path)?; + let project_name = if project_fuzzy_path == project_path { - project_fuzzy_path.parent().unwrap().file_name().unwrap().to_str().unwrap() + project_fuzzy_path + .parent().expect("Path did not have a parent directory") + .file_name().expect("Path did not have a file name") + .to_str().expect("Path had invalid Unicode") } else { - project_fuzzy_path.file_name().unwrap().to_str().unwrap() + project_fuzzy_path + .file_name().expect("Path did not have a file name") + .to_str().expect("Path had invalid Unicode") }; let mut project = Project::load_from_str(DEFAULT_PLACE, &project_path) @@ -352,14 +361,22 @@ impl Project { } pub fn init_model(project_fuzzy_path: &Path) -> Result { - let project_path = Project::init_pick_path(project_fuzzy_path)?; - let project_folder_path = project_path.parent().unwrap(); + let project_path = Project::pick_path_for_init(project_fuzzy_path)?; + let project_name = if project_fuzzy_path == project_path { - project_fuzzy_path.parent().unwrap().file_name().unwrap().to_str().unwrap() + project_fuzzy_path + .parent().expect("Path did not have a parent directory") + .file_name().expect("Path did not have a file name") + .to_str().expect("Path had invalid Unicode") } else { - project_fuzzy_path.file_name().unwrap().to_str().unwrap() + project_fuzzy_path + .file_name().expect("Path did not have a file name") + .to_str().expect("Path had invalid Unicode") }; + let project_folder_path = project_path + .parent().expect("Path did not have a parent directory"); + let tree = ProjectNode { path: Some(project_folder_path.join("src")), ..Default::default() @@ -380,7 +397,7 @@ impl Project { Ok(project_path) } - fn init_pick_path(project_fuzzy_path: &Path) -> Result { + fn pick_path_for_init(project_fuzzy_path: &Path) -> Result { let is_exact = project_fuzzy_path.extension().is_some(); let project_path = if is_exact { @@ -400,7 +417,7 @@ impl Project { Ok(project_path) } - pub fn locate(start_location: &Path) -> Option { + fn locate(start_location: &Path) -> Option { // TODO: Check for specific error kinds, convert 'not found' to Result. let location_metadata = fs::metadata(start_location).ok()?; @@ -437,26 +454,35 @@ impl Project { Ok(parsed.into_project(project_file_location)) } - pub fn load_fuzzy(fuzzy_project_location: &Path) -> Result { - let project_path = match Self::locate(fuzzy_project_location) { - Some(path) => path, - None => { - Project::warn_if_4x_project_present(fuzzy_project_location); - return Err(ProjectLoadFuzzyError::NotFound); - } - }; - - Self::load_exact(&project_path).map_err(From::from) + pub fn load_fuzzy(fuzzy_project_location: &Path) -> Result { + if let Some(project_path) = Self::locate(fuzzy_project_location) { + Self::load_exact(&project_path) + } else { + Project::warn_if_4x_project_present(fuzzy_project_location); + Err(ProjectLoadError::NotFound) + } } - pub fn load_exact(project_file_location: &Path) -> Result { + pub fn load_exact(project_file_location: &Path) -> Result { let contents = fs::read_to_string(project_file_location) - .map_err(ProjectLoadExactError::IoError)?; + .map_err(|error| match error.kind() { + io::ErrorKind::NotFound => ProjectLoadError::NotFound, + _ => ProjectLoadError::Io { + inner: error, + path: project_file_location.to_path_buf(), + } + })?; let parsed: SourceProject = serde_json::from_str(&contents) - .map_err(ProjectLoadExactError::JsonError)?; + .map_err(|error| ProjectLoadError::Json { + inner: error, + path: project_file_location.to_path_buf(), + })?; - Ok(parsed.into_project(project_file_location)) + let project = parsed.into_project(project_file_location); + project.check_compatibility(); + + Ok(project) } pub fn save(&self) -> Result<(), ProjectSaveError> { @@ -472,10 +498,10 @@ impl Project { /// Checks if there are any compatibility issues with this project file and /// warns the user if there are any. - pub fn check_compatibility(&self) { + fn check_compatibility(&self) { let file_name = self.file_location - .file_name().unwrap() - .to_str().expect("Project file path was not valid Unicode!"); + .file_name().expect("Project file path did not have a file name") + .to_str().expect("Project file path was not valid Unicode"); if file_name == COMPAT_PROJECT_FILENAME { warn!("Rojo's default project file name changed in 0.5.0-alpha3."); diff --git a/test-projects/legacy/rojo.json b/test-projects/legacy-0.4.x/rojo.json similarity index 100% rename from test-projects/legacy/rojo.json rename to test-projects/legacy-0.4.x/rojo.json diff --git a/test-projects/legacy-old-0.5.x/roblox-project.json b/test-projects/legacy-old-0.5.x/roblox-project.json new file mode 100644 index 00000000..4fcf72e3 --- /dev/null +++ b/test-projects/legacy-old-0.5.x/roblox-project.json @@ -0,0 +1,6 @@ +{ + "name": "Foo", + "tree": { + "$className": "Folder" + } +} \ No newline at end of file From 94cbe15b545f8db4339f8a0ee1fd0defa183dbdf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 12 Jun 2019 15:54:28 -0700 Subject: [PATCH 0546/1504] Reserve names starting with a dollar sign, closes #191. --- CHANGELOG.md | 1 + server/src/project.rs | 15 ++++++++++++++- .../default.project.json | 9 +++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 test-projects/legacy-0.5.x-reserved-names/default.project.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 0be0f4c6..6bce35a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Added support for live-syncing `CollectionService` tags. * Added a warning when building binary place files, since they're still experimental and have bugs. * Added a warning when trying to use Rojo 0.5.x with a Rojo 0.4.x-only project. +* Added a warning when a Rojo project contains keys that start with `$`, which are reserved names. ([#191](https://github.com/LPGhatguy/rojo/issues/191)) * Added an icon to the plugin's toolbar button * Changed the plugin to use a docking widget for all UI. * Changed the plugin to ignore unknown properties when live-syncing. diff --git a/server/src/project.rs b/server/src/project.rs index ae2662ec..9a96dad7 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -20,7 +20,7 @@ pub static COMPAT_PROJECT_FILENAME: &'static str = "roblox-project.json"; /// want to do things like transforming paths to be absolute before handing them /// off to the rest of Rojo, we use this intermediate struct. #[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] +#[serde(deny_unknown_fields, rename_all = "camelCase")] struct SourceProject { name: String, tree: SourceProjectNode, @@ -274,6 +274,17 @@ pub struct ProjectNode { } impl ProjectNode { + fn validate_reserved_names(&self) { + for (name, child) in &self.children { + if name.starts_with('$') { + warn!("Keys starting with '$' are reserved by Rojo to ensure forward compatibility."); + warn!("This project uses the key '{}', which should be renamed.", name); + } + + child.validate_reserved_names(); + } + } + fn to_source_node(&self, project_file_location: &Path) -> SourceProjectNode { let children = self.children.iter() .map(|(key, value)| (key.clone(), value.to_source_node(project_file_location))) @@ -513,6 +524,8 @@ impl Project { warn!(".project.json extension. This helps Rojo differentiate project files from"); warn!("other JSON files!"); } + + self.tree.validate_reserved_names(); } /// Issues a warning if no Rojo 0.5.x project is found, but there's a legacy diff --git a/test-projects/legacy-0.5.x-reserved-names/default.project.json b/test-projects/legacy-0.5.x-reserved-names/default.project.json new file mode 100644 index 00000000..7901b391 --- /dev/null +++ b/test-projects/legacy-0.5.x-reserved-names/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "legacy-0.5.x-reserved-names", + "tree": { + "$className": "Folder", + "$warn-about-me": { + "$className": "Folder" + } + } +} \ No newline at end of file From ff53113358d6b6d22acc00e8bf8a7645343b546b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 12 Jun 2019 16:02:27 -0700 Subject: [PATCH 0547/1504] Add test project for recent project strictness change --- CHANGELOG.md | 1 + .../legacy-0.5.x-unknown-names/default.project.json | 7 +++++++ 2 files changed, 8 insertions(+) create mode 100644 test-projects/legacy-0.5.x-unknown-names/default.project.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 6bce35a8..83f041f3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Added a warning when building binary place files, since they're still experimental and have bugs. * Added a warning when trying to use Rojo 0.5.x with a Rojo 0.4.x-only project. * Added a warning when a Rojo project contains keys that start with `$`, which are reserved names. ([#191](https://github.com/LPGhatguy/rojo/issues/191)) +* Rojo now throws an error if unknown keys are found in the project file. * Added an icon to the plugin's toolbar button * Changed the plugin to use a docking widget for all UI. * Changed the plugin to ignore unknown properties when live-syncing. diff --git a/test-projects/legacy-0.5.x-unknown-names/default.project.json b/test-projects/legacy-0.5.x-unknown-names/default.project.json new file mode 100644 index 00000000..3c784f36 --- /dev/null +++ b/test-projects/legacy-0.5.x-unknown-names/default.project.json @@ -0,0 +1,7 @@ +{ + "name": "legacy-0.5.x-reserved-names", + "tree": { + "$className": "Folder" + }, + "some field Rojo doesn't have": true +} \ No newline at end of file From a3dc4fa0016f83117cc495fe8d2691d968dddfaa Mon Sep 17 00:00:00 2001 From: boyned//Kampfkarren Date: Wed, 12 Jun 2019 18:22:47 -0700 Subject: [PATCH 0548/1504] Support for .meta.json files other than init (#189) * Support for .meta.json files other than init * Localize .meta.json application --- server/src/rbx_snapshot.rs | 111 ++++++++++++------ .../meta_files/expected-snapshot.json | 72 ++++++++++++ .../meta_files/src/DisableMe.meta.json | 6 + .../meta_files/src/DisableMe.server.lua | 0 .../meta_files/src/LocalizationTable.csv | 2 + .../src/LocalizationTable.meta.json | 5 + .../meta_files/src/RobloxInstance.meta.json | 3 + .../meta_files/src/RobloxInstance.rbxmx | 11 ++ .../meta_files/src/StringValue.meta.json | 3 + test-projects/meta_files/src/StringValue.txt | 1 + 10 files changed, 179 insertions(+), 35 deletions(-) create mode 100644 test-projects/meta_files/src/DisableMe.meta.json create mode 100644 test-projects/meta_files/src/DisableMe.server.lua create mode 100644 test-projects/meta_files/src/LocalizationTable.csv create mode 100644 test-projects/meta_files/src/LocalizationTable.meta.json create mode 100644 test-projects/meta_files/src/RobloxInstance.meta.json create mode 100644 test-projects/meta_files/src/RobloxInstance.rbxmx create mode 100644 test-projects/meta_files/src/StringValue.meta.json create mode 100644 test-projects/meta_files/src/StringValue.txt diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index c3e4fef9..5b280163 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -39,7 +39,6 @@ use crate::{ const INIT_MODULE_NAME: &str = "init.lua"; const INIT_SERVER_NAME: &str = "init.server.lua"; const INIT_CLIENT_NAME: &str = "init.client.lua"; -const INIT_META_NAME: &str = "init.meta.json"; pub struct SnapshotContext { pub plugin_context: Option, @@ -295,7 +294,7 @@ fn snapshot_imfs_item<'source>( instance_name: Option>, ) -> SnapshotResult<'source> { match item { - ImfsItem::File(file) => snapshot_imfs_file(context, file, instance_name), + ImfsItem::File(file) => snapshot_imfs_file(context, imfs, file, instance_name), ImfsItem::Directory(directory) => snapshot_imfs_directory(context, imfs, directory, instance_name), } } @@ -309,7 +308,6 @@ fn snapshot_imfs_directory<'source>( let init_path = directory.path.join(INIT_MODULE_NAME); let init_server_path = directory.path.join(INIT_SERVER_NAME); let init_client_path = directory.path.join(INIT_CLIENT_NAME); - let init_meta_path = directory.path.join(INIT_META_NAME); let snapshot_name = instance_name .unwrap_or_else(|| { @@ -338,26 +336,7 @@ fn snapshot_imfs_directory<'source>( } }; - if let Some(ImfsItem::File(file)) = imfs.get(&init_meta_path) { - let meta: InitMeta = serde_json::from_slice(&file.contents) - .map_err(|inner| SnapshotError::InitMetaError { - inner, - path: file.path.to_path_buf(), - })?; - - if let Some(meta_class) = meta.class_name { - snapshot.class_name = Cow::Owned(meta_class); - } - - if let Some(meta_ignore_instances) = meta.ignore_unknown_instances { - snapshot.metadata.ignore_unknown_instances = meta_ignore_instances; - } - - for (key, value) in meta.properties { - let resolved_value = try_resolve_value(&snapshot.class_name, &key, &value)?; - snapshot.properties.insert(key, resolved_value); - } - } + InitMeta::locate_and_apply(&mut snapshot, &imfs, &directory.path.join("init"))?; snapshot.metadata.source_path = Some(directory.path.to_owned()); @@ -393,8 +372,46 @@ struct InitMeta { properties: HashMap, } +impl InitMeta { + fn apply(self, snapshot: &mut RbxSnapshotInstance) -> Result<(), SnapshotError> { + if let Some(meta_class) = self.class_name { + snapshot.class_name = Cow::Owned(meta_class); + } + + if let Some(meta_ignore_instances) = self.ignore_unknown_instances { + snapshot.metadata.ignore_unknown_instances = meta_ignore_instances; + } + + for (key, value) in self.properties { + let resolved_value = try_resolve_value(&snapshot.class_name, &key, &value)?; + snapshot.properties.insert(key, resolved_value); + } + + Ok(()) + } + + fn locate_and_apply( + snapshot: &mut RbxSnapshotInstance, + imfs: &Imfs, + path: &Path, + ) -> Result<(), SnapshotError> { + if let Some(ImfsItem::File(file)) = imfs.get(&path.with_extension("meta.json")) { + let meta: InitMeta = serde_json::from_slice(&file.contents) + .map_err(|inner| SnapshotError::InitMetaError { + inner, + path: file.path.to_path_buf(), + })?; + + meta.apply(snapshot)?; + } + + Ok(()) + } +} + fn snapshot_imfs_file<'source>( context: &SnapshotContext, + imfs: &'source Imfs, file: &'source ImfsFile, instance_name: Option>, ) -> SnapshotResult<'source> { @@ -402,11 +419,11 @@ fn snapshot_imfs_file<'source>( .map(|v| v.to_str().expect("Could not convert extension to UTF-8")); let mut maybe_snapshot = match extension { - Some("lua") => snapshot_lua_file(file)?, - Some("csv") => snapshot_csv_file(file)?, - Some("txt") => snapshot_txt_file(file)?, - Some("rbxmx") => snapshot_xml_model_file(file)?, - Some("rbxm") => snapshot_binary_model_file(file)?, + Some("lua") => snapshot_lua_file(file, imfs)?, + Some("csv") => snapshot_csv_file(file, imfs)?, + Some("txt") => snapshot_txt_file(file, imfs)?, + Some("rbxmx") => snapshot_xml_model_file(file, imfs)?, + Some("rbxm") => snapshot_binary_model_file(file, imfs)?, Some("json") => { let file_stem = file.path .file_stem().expect("Could not extract file stem") @@ -414,6 +431,11 @@ fn snapshot_imfs_file<'source>( if file_stem.ends_with(".model") { snapshot_json_model_file(file)? + } else if file_stem.ends_with(".meta") { + // Meta files are handled on a per-file basis + // None is *returned* instead of passed through + // so that it isn't treated as a mistake + return Ok(None); } else { None } @@ -421,7 +443,7 @@ fn snapshot_imfs_file<'source>( Some(_) | None => None, }; - if let Some(snapshot) = maybe_snapshot.as_mut() { + if let Some(mut snapshot) = maybe_snapshot.as_mut() { // Carefully preserve name from project manifest if present. if let Some(snapshot_name) = instance_name { snapshot.name = snapshot_name; @@ -449,6 +471,7 @@ fn snapshot_imfs_file<'source>( fn snapshot_lua_file<'source>( file: &'source ImfsFile, + imfs: &'source Imfs, ) -> SnapshotResult<'source> { let file_stem = file.path .file_stem().expect("Could not extract file stem") @@ -468,7 +491,7 @@ fn snapshot_lua_file<'source>( path: file.path.to_path_buf(), })?; - Ok(Some(RbxSnapshotInstance { + let mut snapshot = RbxSnapshotInstance { name: Cow::Borrowed(instance_name), class_name: Cow::Borrowed(class_name), properties: hashmap! { @@ -482,7 +505,11 @@ fn snapshot_lua_file<'source>( ignore_unknown_instances: false, project_definition: None, }, - })) + }; + + InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path.with_file_name(instance_name))?; + + Ok(Some(snapshot)) } fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { @@ -496,6 +523,7 @@ fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { fn snapshot_txt_file<'source>( file: &'source ImfsFile, + imfs: &'source Imfs, ) -> SnapshotResult<'source> { let instance_name = file.path .file_stem().expect("Could not extract file stem") @@ -507,7 +535,7 @@ fn snapshot_txt_file<'source>( path: file.path.to_path_buf(), })?; - Ok(Some(RbxSnapshotInstance { + let mut snapshot = RbxSnapshotInstance { name: Cow::Borrowed(instance_name), class_name: Cow::Borrowed("StringValue"), properties: hashmap! { @@ -521,11 +549,16 @@ fn snapshot_txt_file<'source>( ignore_unknown_instances: false, project_definition: None, }, - })) + }; + + InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path)?; + + Ok(Some(snapshot)) } fn snapshot_csv_file<'source>( file: &'source ImfsFile, + imfs: &'source Imfs, ) -> SnapshotResult<'source> { /// Struct that holds any valid row from a Roblox CSV translation table. /// @@ -612,7 +645,7 @@ fn snapshot_csv_file<'source>( let table_contents = serde_json::to_string(&entries) .expect("Could not encode JSON for localization table"); - Ok(Some(RbxSnapshotInstance { + let mut snapshot = RbxSnapshotInstance { name: Cow::Borrowed(instance_name), class_name: Cow::Borrowed("LocalizationTable"), properties: hashmap! { @@ -626,7 +659,11 @@ fn snapshot_csv_file<'source>( ignore_unknown_instances: false, project_definition: None, }, - })) + }; + + InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path)?; + + Ok(Some(snapshot)) } fn snapshot_json_model_file<'source>( @@ -690,6 +727,7 @@ impl JsonModelInstance { fn snapshot_xml_model_file<'source>( file: &'source ImfsFile, + imfs: &'source Imfs, ) -> SnapshotResult<'source> { let instance_name = file.path .file_stem().expect("Could not extract file stem") @@ -712,6 +750,7 @@ fn snapshot_xml_model_file<'source>( 1 => { let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); snapshot.name = Cow::Borrowed(instance_name); + InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path)?; Ok(Some(snapshot)) }, _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), @@ -720,6 +759,7 @@ fn snapshot_xml_model_file<'source>( fn snapshot_binary_model_file<'source>( file: &'source ImfsFile, + imfs: &'source Imfs, ) -> SnapshotResult<'source> { let instance_name = file.path .file_stem().expect("Could not extract file stem") @@ -746,6 +786,7 @@ fn snapshot_binary_model_file<'source>( 1 => { let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); snapshot.name = Cow::Borrowed(instance_name); + InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path)?; Ok(Some(snapshot)) }, _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), diff --git a/test-projects/meta_files/expected-snapshot.json b/test-projects/meta_files/expected-snapshot.json index 060c5109..f84244b9 100644 --- a/test-projects/meta_files/expected-snapshot.json +++ b/test-projects/meta_files/expected-snapshot.json @@ -19,6 +19,62 @@ "project_definition": null } }, + { + "name": "DisableMe", + "class_name": "Script", + "properties": { + "Disabled": { + "Type": "Bool", + "Value": true + }, + "Source": { + "Type": "String", + "Value": "" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": true, + "source_path": "src/DisableMe.server.lua", + "project_definition": null + } + }, + { + "name": "LocalizationTable", + "class_name": "LocalizationTable", + "properties": { + "Contents": { + "Type": "String", + "Value": "[{\"key\":\"Doge\",\"example\":\"A funny dog\",\"source\":\"Perro!\",\"values\":{\"en\":\"Doge!\"}}]" + }, + "SourceLocaleId": { + "Type": "String", + "Value": "es" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": false, + "source_path": "src/LocalizationTable.csv", + "project_definition": null + } + }, + { + "name": "RobloxInstance", + "class_name": "Folder", + "properties": { + "Tags": { + "Type": "BinaryString", + "Value": "" + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": true, + "source_path": null, + "project_definition": null + } + }, { "name": "Script", "class_name": "Script", @@ -38,6 +94,22 @@ "source_path": "src/Script", "project_definition": null } + }, + { + "name": "StringValue", + "class_name": "StringValue", + "properties": { + "Value": { + "Type": "String", + "Value": "I'm supposed to put funny text here, aren't I? Oh well." + } + }, + "children": [], + "metadata": { + "ignore_unknown_instances": true, + "source_path": "src/StringValue.txt", + "project_definition": null + } } ], "metadata": { diff --git a/test-projects/meta_files/src/DisableMe.meta.json b/test-projects/meta_files/src/DisableMe.meta.json new file mode 100644 index 00000000..3ae03779 --- /dev/null +++ b/test-projects/meta_files/src/DisableMe.meta.json @@ -0,0 +1,6 @@ +{ + "ignoreUnknownInstances": true, + "properties": { + "Disabled": true + } +} \ No newline at end of file diff --git a/test-projects/meta_files/src/DisableMe.server.lua b/test-projects/meta_files/src/DisableMe.server.lua new file mode 100644 index 00000000..e69de29b diff --git a/test-projects/meta_files/src/LocalizationTable.csv b/test-projects/meta_files/src/LocalizationTable.csv new file mode 100644 index 00000000..e5a90bbd --- /dev/null +++ b/test-projects/meta_files/src/LocalizationTable.csv @@ -0,0 +1,2 @@ +Key,Source,Context,Example,en +Doge,Perro!,,A funny dog,Doge! \ No newline at end of file diff --git a/test-projects/meta_files/src/LocalizationTable.meta.json b/test-projects/meta_files/src/LocalizationTable.meta.json new file mode 100644 index 00000000..3685ca81 --- /dev/null +++ b/test-projects/meta_files/src/LocalizationTable.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "SourceLocaleId": "es" + } +} \ No newline at end of file diff --git a/test-projects/meta_files/src/RobloxInstance.meta.json b/test-projects/meta_files/src/RobloxInstance.meta.json new file mode 100644 index 00000000..1025b06a --- /dev/null +++ b/test-projects/meta_files/src/RobloxInstance.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/test-projects/meta_files/src/RobloxInstance.rbxmx b/test-projects/meta_files/src/RobloxInstance.rbxmx new file mode 100644 index 00000000..f1b17e7c --- /dev/null +++ b/test-projects/meta_files/src/RobloxInstance.rbxmx @@ -0,0 +1,11 @@ + + true + null + nil + + + Folder + + + + \ No newline at end of file diff --git a/test-projects/meta_files/src/StringValue.meta.json b/test-projects/meta_files/src/StringValue.meta.json new file mode 100644 index 00000000..1025b06a --- /dev/null +++ b/test-projects/meta_files/src/StringValue.meta.json @@ -0,0 +1,3 @@ +{ + "ignoreUnknownInstances": true +} \ No newline at end of file diff --git a/test-projects/meta_files/src/StringValue.txt b/test-projects/meta_files/src/StringValue.txt new file mode 100644 index 00000000..154159f9 --- /dev/null +++ b/test-projects/meta_files/src/StringValue.txt @@ -0,0 +1 @@ +I'm supposed to put funny text here, aren't I? Oh well. \ No newline at end of file From 212fe31cb3ca348ab99e335789c0cbc0836db84a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 12 Jun 2019 18:29:48 -0700 Subject: [PATCH 0549/1504] Tweak mechanism that ignores .meta.json files --- server/src/rbx_snapshot.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 5b280163..d25e93e1 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -345,17 +345,24 @@ fn snapshot_imfs_directory<'source>( .file_name().expect("Couldn't extract file name") .to_str().expect("Couldn't convert file name to UTF-8"); + if child_name.ends_with(".meta.json") { + // meta.json files don't turn into instances themselves, they just + // modify other instances. + continue; + } + match child_name { INIT_MODULE_NAME | INIT_SERVER_NAME | INIT_CLIENT_NAME => { // The existence of files with these names modifies the // parent instance and is handled above, so we can skip // them here. - }, - _ => { - if let Some(child) = snapshot_imfs_path(context, imfs, child_path, None)? { - snapshot.children.push(child); - } - }, + continue; + } + _ => {} + } + + if let Some(child) = snapshot_imfs_path(context, imfs, child_path, None)? { + snapshot.children.push(child); } } @@ -431,11 +438,6 @@ fn snapshot_imfs_file<'source>( if file_stem.ends_with(".model") { snapshot_json_model_file(file)? - } else if file_stem.ends_with(".meta") { - // Meta files are handled on a per-file basis - // None is *returned* instead of passed through - // so that it isn't treated as a mistake - return Ok(None); } else { None } From 711e009e6d38857a37b479f87b80b674860af57d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 12 Jun 2019 18:33:59 -0700 Subject: [PATCH 0550/1504] Rename InitMeta to ExtraMetadata --- server/src/rbx_snapshot.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index d25e93e1..9a881b37 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -105,7 +105,7 @@ pub enum SnapshotError { path: PathBuf, }, - InitMetaError { + ExtraMetadataError { #[fail(cause)] inner: serde_json::Error, path: PathBuf, @@ -158,7 +158,7 @@ impl fmt::Display for SnapshotError { SnapshotError::JsonModelDecodeError { inner, path } => { write!(output, "Malformed .model.json model: {} in path {}", inner, path.display()) }, - SnapshotError::InitMetaError { inner, path } => { + SnapshotError::ExtraMetadataError { inner, path } => { write!(output, "Malformed init.meta.json: {} in path {}", inner, path.display()) }, SnapshotError::XmlModelDecodeError { inner, path } => { @@ -336,7 +336,7 @@ fn snapshot_imfs_directory<'source>( } }; - InitMeta::locate_and_apply(&mut snapshot, &imfs, &directory.path.join("init"))?; + ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &directory.path.join("init"))?; snapshot.metadata.source_path = Some(directory.path.to_owned()); @@ -371,7 +371,7 @@ fn snapshot_imfs_directory<'source>( #[derive(Debug, Default, Deserialize)] #[serde(rename_all = "camelCase")] -struct InitMeta { +struct ExtraMetadata { class_name: Option, ignore_unknown_instances: Option, @@ -379,7 +379,7 @@ struct InitMeta { properties: HashMap, } -impl InitMeta { +impl ExtraMetadata { fn apply(self, snapshot: &mut RbxSnapshotInstance) -> Result<(), SnapshotError> { if let Some(meta_class) = self.class_name { snapshot.class_name = Cow::Owned(meta_class); @@ -403,8 +403,8 @@ impl InitMeta { path: &Path, ) -> Result<(), SnapshotError> { if let Some(ImfsItem::File(file)) = imfs.get(&path.with_extension("meta.json")) { - let meta: InitMeta = serde_json::from_slice(&file.contents) - .map_err(|inner| SnapshotError::InitMetaError { + let meta: ExtraMetadata = serde_json::from_slice(&file.contents) + .map_err(|inner| SnapshotError::ExtraMetadataError { inner, path: file.path.to_path_buf(), })?; @@ -509,7 +509,7 @@ fn snapshot_lua_file<'source>( }, }; - InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path.with_file_name(instance_name))?; + ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &file.path.with_file_name(instance_name))?; Ok(Some(snapshot)) } @@ -553,7 +553,7 @@ fn snapshot_txt_file<'source>( }, }; - InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path)?; + ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &file.path)?; Ok(Some(snapshot)) } @@ -663,7 +663,7 @@ fn snapshot_csv_file<'source>( }, }; - InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path)?; + ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &file.path)?; Ok(Some(snapshot)) } @@ -752,7 +752,7 @@ fn snapshot_xml_model_file<'source>( 1 => { let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); snapshot.name = Cow::Borrowed(instance_name); - InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path)?; + ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &file.path)?; Ok(Some(snapshot)) }, _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), @@ -788,7 +788,7 @@ fn snapshot_binary_model_file<'source>( 1 => { let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); snapshot.name = Cow::Borrowed(instance_name); - InitMeta::locate_and_apply(&mut snapshot, &imfs, &file.path)?; + ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &file.path)?; Ok(Some(snapshot)) }, _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), From 8f66fb6fef55fb4a3514c99115c4dda2ab004a89 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 13 Jun 2019 17:40:28 -0700 Subject: [PATCH 0551/1504] Set source path on rbxm/rbxmx models --- server/src/rbx_snapshot.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 9a881b37..bcc8a875 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -752,6 +752,7 @@ fn snapshot_xml_model_file<'source>( 1 => { let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); snapshot.name = Cow::Borrowed(instance_name); + snapshot.metadata.source_path = Some(file.path.clone()); ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &file.path)?; Ok(Some(snapshot)) }, @@ -788,6 +789,7 @@ fn snapshot_binary_model_file<'source>( 1 => { let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); snapshot.name = Cow::Borrowed(instance_name); + snapshot.metadata.source_path = Some(file.path.clone()); ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &file.path)?; Ok(Some(snapshot)) }, From 7bce1f6df4a80ea5150eefd928373f34a382fad9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 16 Jun 2019 16:29:08 -0700 Subject: [PATCH 0552/1504] docs: Fix typos on 'Why Rojo' page --- docs/why-rojo.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/why-rojo.md b/docs/why-rojo.md index aac22acb..64e135c9 100644 --- a/docs/why-rojo.md +++ b/docs/why-rojo.md @@ -3,9 +3,9 @@ Adding a tool like Rojo to your Roblox workflow can be daunting, but it comes wi [TOC] ## External Text Editors -Rojo opens the door to use the absolute best text editors in the world and their rich plugin ecosystem. +Rojo opens the door to use the absolute best text editors in the world and their rich plugin ecosystems. -Some very popular, free editors include [Visual Studio Code](https://code.visualstudio.com) and [Sublime Text](https://www.sublimetext.com). +Some very popular editors include [Visual Studio Code](https://code.visualstudio.com) and [Sublime Text](https://www.sublimetext.com). These advanced text editors have features like multi-cursor editing, goto symbol, multi-file regex find and replace, bookmarks and much more. From 125e8766c5e31c3eac1ade452a9cad4930645846 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 16 Jun 2019 16:46:38 -0700 Subject: [PATCH 0553/1504] Fix failing snapshot test from previous change --- test-projects/meta_files/expected-snapshot.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test-projects/meta_files/expected-snapshot.json b/test-projects/meta_files/expected-snapshot.json index f84244b9..d2f68f1f 100644 --- a/test-projects/meta_files/expected-snapshot.json +++ b/test-projects/meta_files/expected-snapshot.json @@ -71,7 +71,7 @@ "children": [], "metadata": { "ignore_unknown_instances": true, - "source_path": null, + "source_path": "src/RobloxInstance.rbxmx", "project_definition": null } }, @@ -79,13 +79,13 @@ "name": "Script", "class_name": "Script", "properties": { - "Disabled": { - "Type": "Bool", - "Value": true - }, "Source": { "Type": "String", "Value": "print(\"Hello, world\")" + }, + "Disabled": { + "Type": "Bool", + "Value": true } }, "children": [], From dcb5c121979f3420812110442b50a2ebb5fdb166 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 17 Jun 2019 16:06:25 -0700 Subject: [PATCH 0554/1504] Fill out some new docs --- docs/guide/existing-game.md | 7 ++++++ docs/reference/full-vs-partial.md | 37 +++++++++++++++++++++++++++++++ mkdocs.yml | 3 ++- 3 files changed, 46 insertions(+), 1 deletion(-) create mode 100644 docs/reference/full-vs-partial.md diff --git a/docs/guide/existing-game.md b/docs/guide/existing-game.md index e69de29b..3abd2d04 100644 --- a/docs/guide/existing-game.md +++ b/docs/guide/existing-game.md @@ -0,0 +1,7 @@ +**TODO** + +## Summary +* Can port as much or as little of your game as you like + * Rojo can manage just a slice of your game! +* Some Roblox idioms aren't very well supported + * Redundant copies of scripts don't work well with files \ No newline at end of file diff --git a/docs/reference/full-vs-partial.md b/docs/reference/full-vs-partial.md new file mode 100644 index 00000000..91003f0d --- /dev/null +++ b/docs/reference/full-vs-partial.md @@ -0,0 +1,37 @@ +Rojo is designed to be adopted incrementally. How much of your project Rojo manages is up to you! + +There are two primary categories of ways to use Rojo: *Fully Managed*, where everything is managed by Rojo, and *Partially Managed*, where Rojo only manages a slice of your project. + +## Fully Managed +In a fully managed game project, Rojo controls every instance. A fully managed Rojo project can be built from scratch using `rojo build`. + +Fully managed projects are most practical for libraries, plugins, and simple games. + +Rojo's goal is to make it practical and easy for _every_ project to be fully managed, but we're not quite there yet! + +### Pros +* Fully reproducible builds from scratch +* Everything checked into version control + +### Cons +* Without two-way sync, models have to be saved manually + * This can be done with the 'Save to File...' menu in Roblox Studio + * This will be solved by Two-Way Sync ([issue #164](https://github.com/LPGhatguy/rojo/issues/164)) +* Rojo can't manage everything yet + * Refs are currently broken ([issue #142](https://github.com/LPGhatguy/rojo/issues/142)) + +## Partially Managed +In a partially managed project, Rojo only handles a slice of the game. This could be as small as a couple scripts, or as large as everything except `Workspace`! + +The rest of the place's content can be versioned using Team Create or checked into source control. + +Partially managed projects are most practical for complicated games, or games that are migrating to use Rojo. + +### Pros +* Easier to adopt gradually +* Integrates with Team Create + +### Cons +* Not everything is in version control, which makes merges tougher +* Rojo can't live-sync instances like Terrain, MeshPart, or CSG operations yet + * Will be fixed with plugin escalation ([issue #169](https://github.com/LPGhatguy/rojo/issues/169)) \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index c0dac993..30cc1c47 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -14,9 +14,10 @@ nav: - Guide: - Installation: guide/installation.md - Creating a Game with Rojo: guide/new-game.md - # - Moving an Existing Game to Rojo: guide/existing-game.md + - Porting an Existing Game to Rojo: guide/existing-game.md - Migrating from 0.4.x to 0.5.x: guide/migrating-to-epiphany.md - Reference: + - Fully vs Partially Managed Rojo: reference/full-vs-partial.md - Project Format: reference/project-format.md - Sync Details: reference/sync-details.md - Rojo Alternatives: rojo-alternatives.md From 21d04a9f8517b31e44f91527a4d6be90567730e3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 19 Jun 2019 10:41:44 -0700 Subject: [PATCH 0555/1504] Add another bullet point --- docs/guide/existing-game.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/guide/existing-game.md b/docs/guide/existing-game.md index 3abd2d04..5a8fab7c 100644 --- a/docs/guide/existing-game.md +++ b/docs/guide/existing-game.md @@ -4,4 +4,5 @@ * Can port as much or as little of your game as you like * Rojo can manage just a slice of your game! * Some Roblox idioms aren't very well supported - * Redundant copies of scripts don't work well with files \ No newline at end of file + * Redundant copies of scripts don't work well with files + * Having only a couple places with scripts simplifies your project dramatically! \ No newline at end of file From fd997d4bdadc256e64b67a42d498c9a44c6bc196 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 20 Jun 2019 15:34:35 -0700 Subject: [PATCH 0556/1504] Update README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c5321cf6..919ea248 100644 --- a/README.md +++ b/README.md @@ -21,9 +21,9 @@
-**Rojo** is a flexible multi-tool designed for creating robust Roblox projects. +**Rojo** is a tool designed to enable Roblox developers to use professional-grade software engineering tools. -It lets Roblox developers use industry-leading tools like Git and VS Code, and crucial utilities like Luacheck. +With Rojo, it's possible to use industry-leading tools like **Visual Studio Code** and **Git**. Rojo is designed for **power users** who want to use the **best tools available** for building games, libraries, and plugins. From b511d4ba5315275c372d61a67ee3a9ef26bc017c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 21 Jun 2019 17:20:38 -0700 Subject: [PATCH 0557/1504] Update dependencies --- Cargo.lock | 317 +++++++++++++++++++++++++++-------------------------- 1 file changed, 160 insertions(+), 157 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index dd27e467..05795565 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,8 +34,8 @@ name = "atty" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -46,14 +46,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.26" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -62,7 +62,7 @@ version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -70,12 +70,12 @@ name = "base64" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "bitflags" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -90,7 +90,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.3.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -98,7 +98,7 @@ name = "bytes" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -110,8 +110,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -132,7 +132,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -144,7 +144,7 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -166,7 +166,7 @@ dependencies = [ "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -179,7 +179,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -250,7 +250,7 @@ dependencies = [ "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -267,7 +267,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -301,8 +301,8 @@ dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -310,7 +310,7 @@ name = "error-chain" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -319,7 +319,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -330,7 +330,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -340,17 +340,17 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "flate2" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -377,7 +377,7 @@ name = "fsevent" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -386,7 +386,7 @@ name = "fsevent-sys" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -399,7 +399,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -419,7 +419,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -429,10 +429,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "h2" -version = "0.1.20" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", @@ -440,7 +440,7 @@ dependencies = [ "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -485,13 +485,13 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.29" +version = "0.12.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -501,7 +501,7 @@ dependencies = [ "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -519,7 +519,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.30 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -544,9 +544,9 @@ name = "inotify" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -554,7 +554,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -562,7 +562,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -592,7 +592,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.55" +version = "0.2.58" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -617,7 +617,7 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -628,7 +628,7 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -651,7 +651,7 @@ name = "memchr" version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -693,7 +693,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -706,7 +706,7 @@ dependencies = [ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -742,7 +742,7 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -759,7 +759,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -773,16 +773,16 @@ name = "notify" version = "4.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -796,10 +796,10 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -812,11 +812,11 @@ name = "openssl" version = "0.10.23" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -832,7 +832,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -867,10 +867,10 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -891,7 +891,7 @@ dependencies = [ "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -957,7 +957,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -981,7 +981,7 @@ dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -990,7 +990,7 @@ name = "pulldown-cmark" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1012,7 +1012,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1024,7 +1024,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1079,7 +1079,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1091,7 +1091,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1119,34 +1119,34 @@ name = "rbx_binary" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_dom_weak" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_reflection" -version = "3.1.388" +version = "3.2.390" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1156,8 +1156,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.1.388 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.2.390 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1184,19 +1184,19 @@ dependencies = [ [[package]] name = "regex" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "remove_dir_all" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1212,7 +1212,7 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.17" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1220,20 +1220,20 @@ dependencies = [ "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.30 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1269,9 +1269,9 @@ name = "rlua" version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1284,7 +1284,7 @@ dependencies = [ "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.30 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1292,23 +1292,23 @@ dependencies = [ "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.1.388 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.2.390 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1353,7 +1353,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1371,7 +1371,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1381,20 +1381,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.91" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.91" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1404,7 +1404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1414,7 +1414,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1435,7 +1435,7 @@ dependencies = [ "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1445,7 +1445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1463,8 +1463,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "string" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "strsim" @@ -1473,7 +1476,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.34" +version = "0.15.36" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1488,7 +1491,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1498,7 +1501,7 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1507,16 +1510,16 @@ version = "3.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "termcolor" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1524,10 +1527,10 @@ dependencies = [ [[package]] name = "termion" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1554,20 +1557,20 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1575,7 +1578,7 @@ dependencies = [ "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-trace-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1626,17 +1629,17 @@ dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-sync" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1666,7 +1669,7 @@ dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1685,7 +1688,7 @@ dependencies = [ [[package]] name = "tokio-trace-core" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1738,7 +1741,7 @@ name = "unicode-normalization" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1763,7 +1766,7 @@ dependencies = [ [[package]] name = "utf8-ranges" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1772,7 +1775,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1792,7 +1795,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" -version = "2.2.7" +version = "2.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1877,13 +1880,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" -"checksum backtrace 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)" = "1a13fc43f04daf08ab4f71e3d27e1fc27fc437d3e95ac0063a796d92fb40f39b" +"checksum backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)" = "ada4c783bb7e7443c14e0480f429ae2cc99da95065aeab7ee1b81ada0419404f" "checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" -"checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb" +"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" "checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" @@ -1912,7 +1915,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2f8c63033fcba1f51ef744505b3cad42510432b904c062afa67ad7ece008429d" -"checksum flate2 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f87e68aa82b2de08a6e037f1385455759df6e445a8df5e005b4297191dbf18aa" +"checksum flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "550934ad4808d5d39365e5d61727309bf18b3b02c6c56b729cb92e7dd84bc3d8" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" @@ -1924,13 +1927,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum h2 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "2b53def7bb0253af7718036fe9338c15defd209136819464384f3a553e07481b" +"checksum h2 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "69b2a5a3092cbebbc951fe55408402e696ee2ed09019137d1800fc2c411265d2" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" "checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.12.29 (registry+https://github.com/rust-lang/crates.io-index)" = "e2cd6adf83b3347d36e271f030621a8cf95fd1fd0760546b9fc5a24a0f1447c7" +"checksum hyper 0.12.30 (registry+https://github.com/rust-lang/crates.io-index)" = "40e7692b2009a70b1e9b362284add4d8b75880fefddb4acaa5e67194e843f219" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" @@ -1941,7 +1944,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.55 (registry+https://github.com/rust-lang/crates.io-index)" = "42914d39aad277d9e176efbdad68acb1d5443ab65afe0e0e4f0d49352a950880" +"checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" @@ -1963,7 +1966,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3572d71f13ea8ed41867accd971fd564aa75934cf7a1fae03ddb8c74a8a49943" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba" +"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" "checksum openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)" = "97c140cbb82f3b3468193dd14c1b88def39f341f68257f8a7fe8ed9ed3f628a5" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" @@ -2000,20 +2003,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81428c521a07a3feac9c31180a886e467eecf81b769987f70d51d567a09c321d" -"checksum rbx_dom_weak 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08ae7950cd5c252ae9596aac109ab7bfd12018d28d02afb8db1e39098769413b" -"checksum rbx_reflection 3.1.388 (registry+https://github.com/rust-lang/crates.io-index)" = "715007d1aa2401570e5778fd628c30e89a7e5251ae3324caf2c5a4033c7f4539" +"checksum rbx_dom_weak 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28fb22188872a75cb66f4937de3ec27fe114a5af3580d34a0a483c42ea1608a2" +"checksum rbx_reflection 3.2.390 (registry+https://github.com/rust-lang/crates.io-index)" = "4f00e0d9e70f1825341e45ff610264778fc2fe72a733027feeca85bfcd6a7305" "checksum rbx_xml 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f6df95f079a20ccdfc3a59bf119afa2ef48155a909e7afceea4a9f2122c164f" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f0a0bcab2fd7d1d7c54fa9eae6f43eddeb9ce2e7352f8518a814a4f65d60c58" -"checksum regex-syntax 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "dcfd8681eebe297b81d98498869d4aae052137651ad7b96822f09ceb690d0a96" -"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5" -"checksum reqwest 0.9.17 (registry+https://github.com/rust-lang/crates.io-index)" = "e57803405f8ea0eb041c1567dac36127e0c8caa1251c843cb03d43fd767b3d50" +"checksum regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0b2f0808e7d7e4fb1cb07feb6ff2f4bc827938f24f8c2e6a3beb7370af544bdd" +"checksum regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d76410686f9e3a17f06128962e0ecc5755870bb890c34820c7af7f1db2e1d48" +"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +"checksum reqwest 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)" = "00eb63f212df0e358b427f0f40aa13aaea010b470be642ad422bcbca2feff2e4" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62fc0e980c94fe9ef795b1bb3874649c8c6e9bb67d3b90d48380ba24c69c23ea" -"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288" +"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" @@ -2023,38 +2026,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "a72e9b96fa45ce22a4bc23da3858dfccfd60acd28a25bcd328a98fdd6bea43fd" -"checksum serde_derive 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)" = "101b495b109a3e3ca8c4cbe44cf62391527cdfb6ba15821c5ce80bcd5ea23f9f" +"checksum serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "32746bf0f26eab52f06af0d0aa1984f641341d06d8d673c693871da2d188c9be" +"checksum serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "46a3223d0c9ba936b61c0d2e3e559e3217dbfb8d65d06d26e8b3c25de38bae3e" "checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be" +"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef82be0baf3ae45701ab992230f1f4889c15984736d87f37558aea3e4e321af" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b" +"checksum string 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0bbfb8937e38e34c3444ff00afb28b0811d9554f15c5ad64d12b0308d1d1995" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum syn 0.15.34 (registry+https://github.com/rust-lang/crates.io-index)" = "a1393e4a97a19c01e900df2aec855a29f71cf02c402e2f443b8d2747c25c5dbe" +"checksum syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)" = "8b4f551a91e2e3848aeef8751d0d4eec9489b6474c720fd4c55958d8d31a430c" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dc4738f2e68ed2855de5ac9cdbe05c9216773ecde4739b2f095002ab03a13ef" -"checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f" -"checksum termion 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dde0593aeb8d47accea5392b39350015b5eccb12c0d98044d856983d89548dea" +"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" +"checksum termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a8fb22f7cde82c8220e5aeacb3258ed7ce996142c77cba193f203515e26c330" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.1.20 (registry+https://github.com/rust-lang/crates.io-index)" = "94a1f9396aec29d31bb16c24d155cfa144d1af91c40740125db3131bdaf76da8" +"checksum tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "ec2ffcf4bcfc641413fa0f1427bf8f91dfc78f56a6559cbf50e04837ae442a87" "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" "checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" "checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" -"checksum tokio-sync 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "5b2f843ffdf8d6e1f90bddd48da43f99ab071660cd92b7ec560ef3cdfd7a409a" +"checksum tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" "checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" -"checksum tokio-trace-core 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "350c9edade9830dc185ae48ba45667a445ab59f6167ef6d0254ec9d2430d9dd3" +"checksum tokio-trace-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9c8a256d6956f7cb5e2bdfe8b1e8022f1a09206c6c2b1ba00f3b746b260c613" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" @@ -2065,12 +2068,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737" +"checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" "checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -"checksum walkdir 2.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d9d7ed3431229a144296213105a390676cc49c9b6a72bd19f3176c98e129fa1" +"checksum walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c7904a7e2bb3cdf0cf5e783f44204a85a37a93151738fa349f06680f59a98b45" "checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" From bb8a3e82e6acb5c8bd76c072e502ff1988495225 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 21 Jun 2019 17:44:08 -0700 Subject: [PATCH 0558/1504] New doc site --- bin/docs-index.html | 10 ++++++++++ bin/generate-docs | 13 +++++++------ 2 files changed, 17 insertions(+), 6 deletions(-) create mode 100644 bin/docs-index.html diff --git a/bin/docs-index.html b/bin/docs-index.html new file mode 100644 index 00000000..098d9e79 --- /dev/null +++ b/bin/docs-index.html @@ -0,0 +1,10 @@ + + + + redirect + + + + + + \ No newline at end of file diff --git a/bin/generate-docs b/bin/generate-docs index 22991a29..28543eee 100644 --- a/bin/generate-docs +++ b/bin/generate-docs @@ -1,31 +1,32 @@ #!/bin/sh # Kludged documentation generator to support multiple versions. -# Make sure the `site` folder is a checkout of this repository's `gh-pages` -# branch. set -e REMOTE=$(git remote get-url origin) CHECKOUT="$(mktemp -d)" -OUTPUT="$(pwd)/site" +OUTPUT="$(pwd)/site/docs" if [ -d site ] then cd site git pull else - git clone "$REMOTE" site + git clone https://github.com/rojo-rbx/rojo-rbx.github.io site cd site - git checkout gh-pages fi +rm -rf docs +mkdir docs +cp ../bin/docs-index.html docs/index.html + git clone "$REMOTE" "$CHECKOUT" cd "$CHECKOUT" echo "Building master" git checkout master -mkdocs build --site-dir "$OUTPUT" +mkdocs build --site-dir "$OUTPUT/latest" echo "Building 0.5.x" mkdocs build --site-dir "$OUTPUT/0.5.x" From c68277be2c0ff2c573bf4e1e37c6f4ef3838a56b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 21 Jun 2019 17:51:38 -0700 Subject: [PATCH 0559/1504] Update docs links --- docs/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/index.md b/docs/index.md index e725b55d..2c72998b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,9 +2,9 @@ This is the documentation home for Rojo 0.5.x. Available versions of these docs: -* [Latest version (currently 0.5.x)](https://lpghatguy.github.io/rojo) -* [0.5.x](https://lpghatguy.github.io/rojo/0.5.x) -* [0.4.x](https://lpghatguy.github.io/rojo/0.4.x) +* [Latest version (currently 0.5.x)](https://rojo.space/docs/latest) +* [0.5.x](https://rojo.space/docs/0.5.x) +* [0.4.x](https://rojo.space/docs/0.4.x) **Rojo** is a flexible multi-tool designed for creating robust Roblox projects. From 3eca4bc439e0d91addb3edde68aaa58aec5e93ad Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 21 Jun 2019 18:02:09 -0700 Subject: [PATCH 0560/1504] Rework README --- README.md | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 919ea248..bb05579d 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@
- Rojo + + Rojo +
 
@@ -11,10 +13,10 @@ Latest server version - + Rojo Documentation - + Rojo Documentation @@ -40,24 +42,8 @@ Soon, Rojo will be able to: * Sync instances from Roblox Studio to the filesystem * Compile MoonScript and other custom things for your project -## [Documentation](https://lpghatguy.github.io/rojo) -You can also view the documentation by browsing the [docs](https://github.com/LPGhatguy/rojo/tree/master/docs) folder of the repository, but because it uses a number of Markdown extensions, it may not be very readable. - -## Inspiration and Alternatives -There are lots of other tools that sync scripts into Roblox or provide other tools for working with Roblox places. - -Here are a few, if you're looking for alternatives or supplements to Rojo: - -* [rbxmk by Anaminus](https://github.com/anaminus/rbxmk) -* [Rofresh by Osyris](https://github.com/osyrisrblx/rofresh) -* [RbxRefresh by Osyris](https://github.com/osyrisrblx/RbxRefresh) -* [Studio Bridge by Vocksel](https://github.com/vocksel/studio-bridge) -* [Elixir by Vocksel](https://github.com/vocksel/elixir) -* [RbxSync by evaera](https://github.com/evaera/RbxSync) -* [CodeSync by MemoryPenguin](https://github.com/MemoryPenguin/CodeSync) -* [rbx-exteditor by MemoryPenguin](https://github.com/MemoryPenguin/rbx-exteditor) - -If you use a plugin that _isn't_ Rojo for syncing code, open an issue and let me know why! I'd like Rojo to be the end-all tool so that people stop reinventing solutions to this problem. +## [Documentation](https://rojo.space/docs/latest/) +Documentation is hosted from the [docs](https://github.com/LPGhatguy/rojo/tree/master/docs) folder of this repository. ## Contributing Pull requests are welcome! From 522f26cf4eb4b521a1f88df2116930892d8a21c1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 22 Jun 2019 23:41:16 -0700 Subject: [PATCH 0561/1504] Update docs config for new repo --- mkdocs.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mkdocs.yml b/mkdocs.yml index 30cc1c47..5124905e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,6 +1,6 @@ site_name: Rojo Documentation -repo_name: LPGhatguy/rojo -repo_url: https://github.com/LPGhatguy/rojo +repo_name: rojo-rbx/rojo +repo_url: https://github.com/rojo-rbx/rojo theme: name: material From 4dab6e5008a08714d1baef7cde34fc504e65c41f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 24 Jun 2019 11:24:50 -0700 Subject: [PATCH 0562/1504] Update README --- README.md | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index bb05579d..7fd3fe27 100644 --- a/README.md +++ b/README.md @@ -7,17 +7,17 @@
 
@@ -27,28 +27,30 @@ With Rojo, it's possible to use industry-leading tools like **Visual Studio Code** and **Git**. -Rojo is designed for **power users** who want to use the **best tools available** for building games, libraries, and plugins. +Rojo is designed for power users who want to use the best tools available for building games, libraries, and plugins. ## Features -Rojo lets you: +Rojo enables: -* Work on scripts from the filesystem, in your favorite editor -* Version your place, model, or plugin using Git or another VCS -* Sync `rbxmx` and `rbxm` models into your game in real time -* Package and deploy your project to Roblox.com from the command line +* Working on scripts and models from the filesystem, in your favorite editor +* Versioning your game, library, or plugin using Git or another VCS +* Streaming `rbxmx` and `rbxm` models into your game in real time +* Packaging and deploying your project to Roblox.com from the command line Soon, Rojo will be able to: +* Automatically convert your existing game to work with Rojo * Sync instances from Roblox Studio to the filesystem -* Compile MoonScript and other custom things for your project +* Automatically manage your assets on Roblox.com, like images and sounds +* Import custom instances like MoonScript code -## [Documentation](https://rojo.space/docs/latest/) -Documentation is hosted from the [docs](https://github.com/LPGhatguy/rojo/tree/master/docs) folder of this repository. +## [Documentation](https://rojo.space/docs/latest) +If you find any mistakes, feel free to make changes in the [docs](https://github.com/LPGhatguy/rojo/tree/master/docs) folder of this repository and submit a pull request! ## Contributing Pull requests are welcome! -Rojo supports Rust 1.32 and newer. Any changes to the minimum required compiler version require a _minor_ version bump. +Rojo supports Rust 1.32 and newer. ## License Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file From ad5695210d9dd08bfc89bb0ad08b4ff94465645b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 27 Jun 2019 22:24:44 -0700 Subject: [PATCH 0563/1504] More strict .meta.json files --- server/src/rbx_snapshot.rs | 80 ++++++++++++++----- .../meta_files_bad/default.project.json | 6 ++ .../src/RobloxInstance.meta.json | 5 ++ .../meta_files_bad/src/RobloxInstance.rbxmx | 11 +++ 4 files changed, 83 insertions(+), 19 deletions(-) create mode 100644 test-projects/meta_files_bad/default.project.json create mode 100644 test-projects/meta_files_bad/src/RobloxInstance.meta.json create mode 100644 test-projects/meta_files_bad/src/RobloxInstance.rbxmx diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index bcc8a875..280dde4c 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -111,6 +111,11 @@ pub enum SnapshotError { path: PathBuf, }, + InvalidMetadataField { + field_name: String, + path: PathBuf, + }, + XmlModelDecodeError { #[fail(cause)] inner: rbx_xml::DecodeError, @@ -161,6 +166,10 @@ impl fmt::Display for SnapshotError { SnapshotError::ExtraMetadataError { inner, path } => { write!(output, "Malformed init.meta.json: {} in path {}", inner, path.display()) }, + SnapshotError::InvalidMetadataField { field_name, path } => { + writeln!(output, "The field '{}' cannot be specified on .meta.json files attached to models.", field_name)?; + writeln!(output, "Model path: {}", path.display()) + }, SnapshotError::XmlModelDecodeError { inner, path } => { write!(output, "Malformed rbxmx model: {} in path {}", inner, path.display()) }, @@ -336,7 +345,9 @@ fn snapshot_imfs_directory<'source>( } }; - ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &directory.path.join("init"))?; + if let Some(meta) = ExtraMetadata::locate(&imfs, &directory.path.join("init"))? { + meta.apply(&mut snapshot)?; + } snapshot.metadata.source_path = Some(directory.path.to_owned()); @@ -370,7 +381,7 @@ fn snapshot_imfs_directory<'source>( } #[derive(Debug, Default, Deserialize)] -#[serde(rename_all = "camelCase")] +#[serde(rename_all = "camelCase", deny_unknown_fields)] struct ExtraMetadata { class_name: Option, ignore_unknown_instances: Option, @@ -397,19 +408,34 @@ impl ExtraMetadata { Ok(()) } - fn locate_and_apply( - snapshot: &mut RbxSnapshotInstance, - imfs: &Imfs, - path: &Path, - ) -> Result<(), SnapshotError> { - if let Some(ImfsItem::File(file)) = imfs.get(&path.with_extension("meta.json")) { - let meta: ExtraMetadata = serde_json::from_slice(&file.contents) - .map_err(|inner| SnapshotError::ExtraMetadataError { - inner, - path: file.path.to_path_buf(), - })?; + fn locate(imfs: &Imfs, path: &Path) -> Result, SnapshotError> { + match imfs.get(&path.with_extension("meta.json")) { + Some(ImfsItem::File(file)) => { + let meta: ExtraMetadata = serde_json::from_slice(&file.contents) + .map_err(|inner| SnapshotError::ExtraMetadataError { + inner, + path: file.path.to_path_buf(), + })?; - meta.apply(snapshot)?; + Ok(Some(meta)) + } + _ => Ok(None) + } + } + + fn validate_for_model(&self, path: &Path) -> Result<(), SnapshotError> { + if self.class_name.is_some() { + return Err(SnapshotError::InvalidMetadataField { + field_name: "className".to_owned(), + path: path.to_owned(), + }); + } + + if !self.properties.is_empty() { + return Err(SnapshotError::InvalidMetadataField { + field_name: "properties".to_owned(), + path: path.to_owned(), + }); } Ok(()) @@ -509,7 +535,9 @@ fn snapshot_lua_file<'source>( }, }; - ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &file.path.with_file_name(instance_name))?; + if let Some(meta) = ExtraMetadata::locate(&imfs, &file.path.with_file_name(instance_name))? { + meta.apply(&mut snapshot)?; + } Ok(Some(snapshot)) } @@ -553,7 +581,9 @@ fn snapshot_txt_file<'source>( }, }; - ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &file.path)?; + if let Some(meta) = ExtraMetadata::locate(&imfs, &file.path)? { + meta.apply(&mut snapshot)?; + } Ok(Some(snapshot)) } @@ -663,7 +693,9 @@ fn snapshot_csv_file<'source>( }, }; - ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &file.path)?; + if let Some(meta) = ExtraMetadata::locate(&imfs, &file.path)? { + meta.apply(&mut snapshot)?; + } Ok(Some(snapshot)) } @@ -753,7 +785,12 @@ fn snapshot_xml_model_file<'source>( let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); snapshot.name = Cow::Borrowed(instance_name); snapshot.metadata.source_path = Some(file.path.clone()); - ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &file.path)?; + + if let Some(meta) = ExtraMetadata::locate(&imfs, &file.path)? { + meta.validate_for_model(&file.path)?; + meta.apply(&mut snapshot)?; + } + Ok(Some(snapshot)) }, _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), @@ -790,7 +827,12 @@ fn snapshot_binary_model_file<'source>( let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); snapshot.name = Cow::Borrowed(instance_name); snapshot.metadata.source_path = Some(file.path.clone()); - ExtraMetadata::locate_and_apply(&mut snapshot, &imfs, &file.path)?; + + if let Some(meta) = ExtraMetadata::locate(&imfs, &file.path)? { + meta.validate_for_model(&file.path)?; + meta.apply(&mut snapshot)?; + } + Ok(Some(snapshot)) }, _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), diff --git a/test-projects/meta_files_bad/default.project.json b/test-projects/meta_files_bad/default.project.json new file mode 100644 index 00000000..b0aed992 --- /dev/null +++ b/test-projects/meta_files_bad/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "meta_files_bad", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/test-projects/meta_files_bad/src/RobloxInstance.meta.json b/test-projects/meta_files_bad/src/RobloxInstance.meta.json new file mode 100644 index 00000000..7b8e67a9 --- /dev/null +++ b/test-projects/meta_files_bad/src/RobloxInstance.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "x": true + } +} \ No newline at end of file diff --git a/test-projects/meta_files_bad/src/RobloxInstance.rbxmx b/test-projects/meta_files_bad/src/RobloxInstance.rbxmx new file mode 100644 index 00000000..f1b17e7c --- /dev/null +++ b/test-projects/meta_files_bad/src/RobloxInstance.rbxmx @@ -0,0 +1,11 @@ + + true + null + nil + + + Folder + + + + \ No newline at end of file From e045989d39c28c8e26731035c626d6c081726b2e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 27 Jun 2019 22:31:05 -0700 Subject: [PATCH 0564/1504] Update Changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83f041f3..e92fa730 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ * Added an icon to the plugin's toolbar button * Changed the plugin to use a docking widget for all UI. * Changed the plugin to ignore unknown properties when live-syncing. - * Rojo's approach this problem might change later, like with a strict model mode ([#190](https://github.com/LPGhatguy/rojo/issues/190)) or another approach. + * Rojo's approach to this problem might change later, like with a strict model mode ([#190](https://github.com/LPGhatguy/rojo/issues/190)) or another approach. * Upgraded to reflection database from client release 388. ## [0.5.0 Alpha 11](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) From aa3e43207f431e2bb534a35ccd4f4a36c4cf4bda Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 2 Jul 2019 15:30:56 -0700 Subject: [PATCH 0565/1504] Update documentation to include meta docs --- docs/guide/existing-game.md | 5 +- docs/guide/installation.md | 8 +-- docs/guide/migrating-to-epiphany.md | 7 ++- docs/reference/sync-details.md | 79 ++++++++++++++++++++++++----- 4 files changed, 80 insertions(+), 19 deletions(-) diff --git a/docs/guide/existing-game.md b/docs/guide/existing-game.md index 5a8fab7c..7edb4a0d 100644 --- a/docs/guide/existing-game.md +++ b/docs/guide/existing-game.md @@ -1,6 +1,9 @@ -**TODO** +**This page is under construction!** ## Summary +* Tools to port existing games are in progress! + * [rbxlx-to-rojo](https://github.com/rojo/rbxlx-to-rojo) + * `rojo export` ([issue #208](https://github.com/rojo-rbx/rojo/issues/208)) * Can port as much or as little of your game as you like * Rojo can manage just a slice of your game! * Some Roblox idioms aren't very well supported diff --git a/docs/guide/installation.md b/docs/guide/installation.md index b56f31c8..7fc21d1e 100644 --- a/docs/guide/installation.md +++ b/docs/guide/installation.md @@ -13,6 +13,9 @@ Rojo has two components: The plugin will show errors in the Roblox Studio output window if there is a version mismatch. +## Visual Studio Code Extension +If you use Visual Studio Code, you can install [the Rojo VS Code extension](https://marketplace.visualstudio.com/items?itemName=evaera.vscode-rojo), which will install both halves of Rojo for you. It even has a nifty UI to sync files and start/stop the Rojo server! + ## Installing the CLI ### Installing from GitHub @@ -40,7 +43,4 @@ Download the attached `rbxm` file and put it into your Roblox Studio plugins fol {: align="center" } ### Installing from Roblox.com -Visit [Rojo's Roblox.com Plugin page](https://www.roblox.com/library/1997686364/Rojo-0-5-0-alpha-3) in Roblox Studio and press **Install**. - -## Visual Studio Code Extension -If you use Visual Studio Code, you can install [Evaera's unofficial Rojo extension](https://marketplace.visualstudio.com/items?itemName=evaera.vscode-rojo), which will install both halves of Rojo for you. It even has a nifty UI to sync files and start/stop the Rojo server! \ No newline at end of file +Visit [Rojo's Roblox.com Plugin page](https://www.roblox.com/library/1997686364/Rojo-0-5-0-alpha-3) in Roblox Studio and press **Install**. \ No newline at end of file diff --git a/docs/guide/migrating-to-epiphany.md b/docs/guide/migrating-to-epiphany.md index 5adb36f9..87acf09c 100644 --- a/docs/guide/migrating-to-epiphany.md +++ b/docs/guide/migrating-to-epiphany.md @@ -55,4 +55,9 @@ All other values are considered children, where the key is the instance's name, ## Migrating Unknown Files If you used Rojo to sync in files as `StringValue` objects, you'll need to make sure those files end with the `txt` extension to preserve this in Rojo 0.5.x. -Unknown files are now ignored in Rojo instead of being converted to `StringValue` objects. \ No newline at end of file +Unknown files are now ignored in Rojo instead of being converted to `StringValue` objects. + +## Migrating `init.model.json` files +In Rojo 0.4.x, it's possible to create a file named `init.model.json` that lets you describe a model that becomes the container for all of the other files in the folder, just like `init.lua`. + +In Rojo 0.5.x, this feature has been replaced with `init.meta.json` files. See [Sync Details](../reference/sync-details) for more information about these new files. \ No newline at end of file diff --git a/docs/reference/sync-details.md b/docs/reference/sync-details.md index ae64e7fe..75a6e6f3 100644 --- a/docs/reference/sync-details.md +++ b/docs/reference/sync-details.md @@ -3,17 +3,18 @@ This page aims to describe how Rojo turns files on the filesystem into Roblox ob [TOC] ## Overview -| File Name | Instance Type | -| -------------- | ------------------- | -| any directory | `Folder` | -| `*.server.lua` | `Script` | -| `*.client.lua` | `LocalScript` | -| `*.lua` | `ModuleScript` | -| `*.csv` | `LocalizationTable` | -| `*.txt` | `StringValue` | -| `*.model.json` | Any | -| `*.rbxm` | Any | -| `*.rbxmx` | Any | +| File Name | Instance Type | +| -------------- | ------------------------- | +| any directory | `Folder` | +| `*.server.lua` | `Script` | +| `*.client.lua` | `LocalScript` | +| `*.lua` | `ModuleScript` | +| `*.csv` | `LocalizationTable` | +| `*.txt` | `StringValue` | +| `*.model.json` | Any | +| `*.rbxm` | Any | +| `*.rbxmx` | Any | +| `*.meta.json` | Modifies another instance | ## Limitations Not all property types can be synced by Rojo in real-time due to limitations of the Roblox Studio plugin API. In these cases, you can usually generate a place file and open it when you start working on a project. @@ -24,7 +25,9 @@ Some common cases you might hit are: * `MeshPart.MeshId` * `HttpService.HttpEnabled` -For a list of all property types that Rojo can reason about, both when live-syncing and when building place files, look at [rbx_tree's type coverage chart](https://github.com/LPGhatguy/rbx-tree#property-type-coverage). +For a list of all property types that Rojo can reason about, both when live-syncing and when building place files, look at [rbx-dom's type coverage chart](https://github.com/rojo-rbx/rbx-dom#property-type-coverage). + +This limitation may be solved by [issue #205](https://github.com/rojo-rbx/rojo/issues/205) in the future. ## Folders Any directory on the filesystem will turn into a `Folder` instance unless it contains an 'init' script, described below. @@ -88,4 +91,54 @@ Rojo supports both binary (`.rbxm`) and XML (`.rbxmx`) models generated by Roblo Support for the `rbxmx` is very good, while support for `rbxm` is still very early, buggy, and lacking features. -For a rundown of supported types, check out [rbx-dom's type coverage chart](https://github.com/LPGhatguy/rbx-dom#property-type-coverage). \ No newline at end of file +For a rundown of supported types, check out [rbx-dom's type coverage chart](https://github.com/rojo-rbx/rbx-dom#property-type-coverage). + +## Meta Files +New in Rojo 0.5.0-alpha.12 are meta files, named `.meta.json`. + +Meta files allow attaching extra Rojo data to models defined in other formats, like Roblox's `rbxm` and `rbxmx` model formats, or even Lua scripts. + +This can be used to set Rojo-specific settings like `ignoreUnknownInstances`, or can be used to set properties like `Disabled` on a script. + +Meta files can contain: + +* `className`: Changes the `className` of a containing `Folder` into something else. + * Usable only in `init.meta.json` files +* `properties`: A map of properties to set on the instance, just like projects + * Usable on anything except `.rbxmx`, `.rbxm`, and `.model.json` files, which already have properties +* `ignoreUnknownInstances`: Works just like `$ignoreUnknownInstances` in project files + +### Meta Files to set Rojo metadata +Sometimes it's useful to apply properties like `ignoreUnknownInstances` on instances that are defined on the filesystem instead of within the project itself. + +### Meta Files for Disabled Scripts +Meta files can be used to set properties on `Script` instances, like `Disabled`. + +If your project had `foo.server.lua` and you wanted to make sure it would be disabled, you could create a `foo.meta.json` next to it with: + +```json +{ + "properties": { + "Disabled": true + } +} +``` + +### Meta Files for Tools +If you wanted to represent a tool containing a script and a model for its handle, create a directory with an `init.meta.json` file in it: + +```json +{ + "className": "Tool", + "properties": { + "Grip": [ + 0, 0, 0, + 1, 0, 0, + 0, 1, 0, + 0, 0, 1, + ] + } +} +``` + +Instead of a `Folder` instance, you'll end up with a `Tool` instance with the `Grip` property set! \ No newline at end of file From 714fb10facdfc51be221ad827aec9c29e84ef46c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 2 Jul 2019 15:35:29 -0700 Subject: [PATCH 0566/1504] Remove old docs scripts and update links to new repo --- CHANGELOG.md | 130 ++++++++++++++++++++++---------------------- README.md | 2 +- bin/docs-index.html | 10 ---- bin/generate-docs | 36 ------------ 4 files changed, 66 insertions(+), 112 deletions(-) delete mode 100644 bin/docs-index.html delete mode 100644 bin/generate-docs diff --git a/CHANGELOG.md b/CHANGELOG.md index e92fa730..866e77be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,23 +1,23 @@ # Rojo Changelog ## [Unreleased] -* Added `init.meta.json` files, which replace `init.model.json` files from Rojo 0.4.x ([#183](https://github.com/LPGhatguy/rojo/pull/183)) +* Added `init.meta.json` files, which replace `init.model.json` files from Rojo 0.4.x ([#183](https://github.com/rojo-rbx/rojo/pull/183)) * Added support for infinite and NaN values in types like `Vector2` when building models and places. * These types aren't supported for live-syncing yet due to limitations around JSON encoding. * Added support for using `SharedString` values when building XML models and places. * Added support for live-syncing `CollectionService` tags. * Added a warning when building binary place files, since they're still experimental and have bugs. * Added a warning when trying to use Rojo 0.5.x with a Rojo 0.4.x-only project. -* Added a warning when a Rojo project contains keys that start with `$`, which are reserved names. ([#191](https://github.com/LPGhatguy/rojo/issues/191)) +* Added a warning when a Rojo project contains keys that start with `$`, which are reserved names. ([#191](https://github.com/rojo-rbx/rojo/issues/191)) * Rojo now throws an error if unknown keys are found in the project file. * Added an icon to the plugin's toolbar button * Changed the plugin to use a docking widget for all UI. * Changed the plugin to ignore unknown properties when live-syncing. - * Rojo's approach to this problem might change later, like with a strict model mode ([#190](https://github.com/LPGhatguy/rojo/issues/190)) or another approach. + * Rojo's approach to this problem might change later, like with a strict model mode ([#190](https://github.com/rojo-rbx/rojo/issues/190)) or another approach. * Upgraded to reflection database from client release 388. -## [0.5.0 Alpha 11](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) -* Added support for implicit property values in JSON model files ([#154](https://github.com/LPGhatguy/rojo/pull/154)) +## [0.5.0 Alpha 11](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) +* Added support for implicit property values in JSON model files ([#154](https://github.com/rojo-rbx/rojo/pull/154)) * `Content` propertyes can now be specified in projects and model files as regular string literals. * Added support for `BrickColor` properties. * Added support for properties added in client release 384, like `Lighting.Technology` being set to `"ShadowMap"`. @@ -28,16 +28,16 @@ * Plugin should now be able to live-sync more properties, and ignore ones it can't, like `Lighting.Technology`. ## 0.5.0 Alpha 10 -* This release was a dud due to [issue #176](https://github.com/LPGhatguy/rojo/issues/176) and was rolled back. +* This release was a dud due to [issue #176](https://github.com/rojo-rbx/rojo/issues/176) and was rolled back. -## [0.5.0 Alpha 9](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.9) (April 4, 2019) +## [0.5.0 Alpha 9](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.9) (April 4, 2019) * Changed `rojo build` to use buffered I/O, which can make it up to 2x faster in some cases. - * Building [*Road Not Taken*](https://github.com/LPGhatguy/roads) to an `rbxlx` file dropped from 150ms to 70ms on my machine -* Fixed `LocalizationTable` instances being made from `csv` files incorrectly interpreting empty rows and columns. ([#149](https://github.com/LPGhatguy/rojo/pull/149)) -* Fixed CSV files with entries that parse as numbers causing Rojo to panic. ([#152](https://github.com/LPGhatguy/rojo/pull/152)) + * Building [*Road Not Taken*](https://github.com/rojo-rbx/roads) to an `rbxlx` file dropped from 150ms to 70ms on my machine +* Fixed `LocalizationTable` instances being made from `csv` files incorrectly interpreting empty rows and columns. ([#149](https://github.com/rojo-rbx/rojo/pull/149)) +* Fixed CSV files with entries that parse as numbers causing Rojo to panic. ([#152](https://github.com/rojo-rbx/rojo/pull/152)) * Improved error messages when malformed CSV files are found in a Rojo project. -## [0.5.0 Alpha 8](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.8) (March 29, 2019) +## [0.5.0 Alpha 8](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.8) (March 29, 2019) * Added support for a bunch of new types when dealing with XML model/place files: * `ColorSequence` * `Float64` @@ -48,13 +48,13 @@ * `Ray` * `Rect` * `Ref` -* Improved server instance ordering behavior when files are added during a live session ([#135](https://github.com/LPGhatguy/rojo/pull/135)) +* Improved server instance ordering behavior when files are added during a live session ([#135](https://github.com/rojo-rbx/rojo/pull/135)) * Fixed error being thrown when trying to unload the Rojo plugin. -* Added partial fix for [issue #141](https://github.com/LPGhatguy/rojo/issues/141) for `Lighting.Technology`, which should restore live sync functionality for the default project file. +* Added partial fix for [issue #141](https://github.com/rojo-rbx/rojo/issues/141) for `Lighting.Technology`, which should restore live sync functionality for the default project file. -## [0.5.0 Alpha 6](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.6) (March 19, 2019) +## [0.5.0 Alpha 6](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.6) (March 19, 2019) * Fixed `rojo init` giving unexpected results by upgrading to `rbx_dom_weak` 1.1.0 -* Fixed live server not responding when the Rojo plugin is connected ([#133](https://github.com/LPGhatguy/rojo/issues/133)) +* Fixed live server not responding when the Rojo plugin is connected ([#133](https://github.com/rojo-rbx/rojo/issues/133)) * Updated default place file: * Improved default properties to be closer to Studio's built-in 'Baseplate' template * Added a baseplate to the project file (Thanks, [@AmaranthineCodices](https://github.com/AmaranthineCodices/)!) @@ -62,40 +62,40 @@ * Fixed some cases where the Rojo plugin would leave around objects that it knows should be deleted * Updated plugin to correctly listen to `Plugin.Unloading` when installing or uninstalling new plugins -## [0.5.0 Alpha 5](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.5) (March 1, 2019) +## [0.5.0 Alpha 5](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.5) (March 1, 2019) * Upgraded core dependencies, which improves compatibility for lots of instance types * Upgraded from `rbx_tree` 0.2.0 to `rbx_dom_weak` 1.0.0 * Upgraded from `rbx_xml` 0.2.0 to `rbx_xml` 0.4.0 * Upgraded from `rbx_binary` 0.2.0 to `rbx_binary` 0.4.0 * Added support for non-primitive types in the Rojo plugin. * Types like `Color3` and `CFrame` can now be updated live! -* Fixed plugin assets flashing in on first load ([#121](https://github.com/LPGhatguy/rojo/issues/121)) +* Fixed plugin assets flashing in on first load ([#121](https://github.com/rojo-rbx/rojo/issues/121)) * Changed Rojo's HTTP server from Rouille to Hyper, which reduced the release size by around a megabyte. -* Added property type inference to projects, which makes specifying services a lot easier ([#130](https://github.com/LPGhatguy/rojo/pull/130)) +* Added property type inference to projects, which makes specifying services a lot easier ([#130](https://github.com/rojo-rbx/rojo/pull/130)) * Made error messages from invalid and missing files more user-friendly -## [0.5.0 Alpha 4](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.4) (February 8, 2019) -* Added support for nested partitions ([#102](https://github.com/LPGhatguy/rojo/issues/102)) -* Added support for 'transmuting' partitions ([#112](https://github.com/LPGhatguy/rojo/issues/112)) -* Added support for aliasing filesystem paths ([#105](https://github.com/LPGhatguy/rojo/issues/105)) -* Changed Windows builds to statically link the CRT ([#89](https://github.com/LPGhatguy/rojo/issues/89)) +## [0.5.0 Alpha 4](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.4) (February 8, 2019) +* Added support for nested partitions ([#102](https://github.com/rojo-rbx/rojo/issues/102)) +* Added support for 'transmuting' partitions ([#112](https://github.com/rojo-rbx/rojo/issues/112)) +* Added support for aliasing filesystem paths ([#105](https://github.com/rojo-rbx/rojo/issues/105)) +* Changed Windows builds to statically link the CRT ([#89](https://github.com/rojo-rbx/rojo/issues/89)) -## [0.5.0 Alpha 3](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.3) (February 1, 2019) -* Changed default project file name from `roblox-project.json` to `default.project.json` ([#120](https://github.com/LPGhatguy/rojo/pull/120)) +## [0.5.0 Alpha 3](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.3) (February 1, 2019) +* Changed default project file name from `roblox-project.json` to `default.project.json` ([#120](https://github.com/rojo-rbx/rojo/pull/120)) * The old file name will still be supported until 0.5.0 is fully released. * Added warning when loading project files that don't end in `.project.json` * This new extension enables Rojo to distinguish project files from random JSON files, which is necessary to support nested projects. * Added new (empty) diagnostic page served from the server * Added better error messages for when a file is missing that's referenced by a Rojo project * Added support for visualization endpoints returning GraphViz source when Dot is not available -* Fixed an in-memory filesystem regression introduced recently ([#119](https://github.com/LPGhatguy/rojo/pull/119)) +* Fixed an in-memory filesystem regression introduced recently ([#119](https://github.com/rojo-rbx/rojo/pull/119)) -## [0.5.0 Alpha 2](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.2) (January 28, 2019) +## [0.5.0 Alpha 2](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.2) (January 28, 2019) * Added support for `.model.json` files, compatible with 0.4.x * Fixed in-memory filesystem not handling out-of-order filesystem change events -* Fixed long-polling error caused by a promise mixup ([#110](https://github.com/LPGhatguy/rojo/issues/110)) +* Fixed long-polling error caused by a promise mixup ([#110](https://github.com/rojo-rbx/rojo/issues/110)) -## [0.5.0 Alpha 1](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.1) (January 25, 2019) +## [0.5.0 Alpha 1](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.1) (January 25, 2019) * Changed plugin UI to be way prettier * Thanks to [Reselim](https://github.com/Reselim) for the design! * Changed plugin error messages to be a little more useful @@ -103,7 +103,7 @@ * Fixed bug where bad server responses could cause the plugin to be in a bad state * Upgraded to rbx\_tree, rbx\_xml, and rbx\_binary 0.2.0, which dramatically expands the kinds of properties that Rojo can handle, especially in XML. -## [0.5.0 Alpha 0](https://github.com/LPGhatguy/rojo/releases/tag/v0.5.0-alpha.0) (January 14, 2019) +## [0.5.0 Alpha 0](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.0) (January 14, 2019) * "Epiphany" rewrite, in progress since the beginning of time * New live sync protocol * Uses HTTP long polling to reduce request count and improve responsiveness @@ -128,105 +128,105 @@ * Multiple places can be specified, like when building a multi-place game * Added support for specifying properties on services in project files -## [0.4.13](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.13) (November 12, 2018) +## [0.4.13](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.13) (November 12, 2018) * When `rojo.json` points to a file or directory that does not exist, Rojo now issues a warning instead of throwing an error and exiting -## [0.4.12](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.12) (June 21, 2018) -* Fixed obscure assertion failure when renaming or deleting files ([#78](https://github.com/LPGhatguy/rojo/issues/78)) -* Added a `PluginAction` for the sync in command, which should help with some automation scripts ([#80](https://github.com/LPGhatguy/rojo/pull/80)) +## [0.4.12](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.12) (June 21, 2018) +* Fixed obscure assertion failure when renaming or deleting files ([#78](https://github.com/rojo-rbx/rojo/issues/78)) +* Added a `PluginAction` for the sync in command, which should help with some automation scripts ([#80](https://github.com/rojo-rbx/rojo/pull/80)) -## [0.4.11](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.11) (June 10, 2018) +## [0.4.11](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.11) (June 10, 2018) * Defensively insert existing instances into RouteMap; should fix most duplication cases when syncing into existing trees. * Fixed incorrect synchronization from `Plugin:_pull` that would cause polling to create issues * Fixed incorrect file routes being assigned to `init.lua` and `init.model.json` files * Untangled route handling-internals slightly -## [0.4.10](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.10) (June 2, 2018) -* Added support for `init.model.json` files, which enable versioning `Tool` instances (among other things) with Rojo. ([#66](https://github.com/LPGhatguy/rojo/issues/66)) +## [0.4.10](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.10) (June 2, 2018) +* Added support for `init.model.json` files, which enable versioning `Tool` instances (among other things) with Rojo. ([#66](https://github.com/rojo-rbx/rojo/issues/66)) * Fixed obscure error when syncing into an invalid service. * Fixed multiple sync processes occurring when a server ID mismatch is detected. -## [0.4.9](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.9) (May 26, 2018) -* Fixed warning when renaming or removing files that would sometimes corrupt the instance cache ([#72](https://github.com/LPGhatguy/rojo/pull/72)) +## [0.4.9](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.9) (May 26, 2018) +* Fixed warning when renaming or removing files that would sometimes corrupt the instance cache ([#72](https://github.com/rojo-rbx/rojo/pull/72)) * JSON models are no longer as strict -- `Children` and `Properties` are now optional. -## [0.4.8](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.8) (May 26, 2018) +## [0.4.8](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.8) (May 26, 2018) * Hotfix to prevent errors from being thrown when objects managed by Rojo are deleted -## [0.4.7](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.7) (May 25, 2018) -* Added icons to the Rojo plugin, made by [@Vorlias](https://github.com/Vorlias)! ([#70](https://github.com/LPGhatguy/rojo/pull/70)) -* Server will now issue a warning if no partitions are specified in `rojo serve` ([#40](https://github.com/LPGhatguy/rojo/issues/40)) +## [0.4.7](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.7) (May 25, 2018) +* Added icons to the Rojo plugin, made by [@Vorlias](https://github.com/Vorlias)! ([#70](https://github.com/rojo-rbx/rojo/pull/70)) +* Server will now issue a warning if no partitions are specified in `rojo serve` ([#40](https://github.com/rojo-rbx/rojo/issues/40)) -## [0.4.6](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.6) (May 21, 2018) -* Rojo handles being restarted by Roblox Studio more gracefully ([#67](https://github.com/LPGhatguy/rojo/issues/67)) +## [0.4.6](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.6) (May 21, 2018) +* Rojo handles being restarted by Roblox Studio more gracefully ([#67](https://github.com/rojo-rbx/rojo/issues/67)) * Folders should no longer get collapsed when syncing occurs. * **Significant** robustness improvements with regards to caching. * **This should catch all existing script duplication bugs.** * If there are any bugs with script duplication or caching in the future, restarting the Rojo server process will fix them for that session. * Fixed message in plugin not being prefixed with `Rojo: `. -## [0.4.5](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.5) (May 1, 2018) +## [0.4.5](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.5) (May 1, 2018) * Rojo messages are now prefixed with `Rojo: ` to make them stand out in the output more. * Fixed server to notice file changes *much* more quickly. (200ms vs 1000ms) * Server now lists name of project when starting up. -* Rojo now throws an error if no project file is found. ([#63](https://github.com/LPGhatguy/rojo/issues/63)) -* Fixed multiple sync operations occuring at the same time. ([#61](https://github.com/LPGhatguy/rojo/issues/61)) -* Partitions targeting files directly now work as expected. ([#57](https://github.com/LPGhatguy/rojo/issues/57)) +* Rojo now throws an error if no project file is found. ([#63](https://github.com/rojo-rbx/rojo/issues/63)) +* Fixed multiple sync operations occuring at the same time. ([#61](https://github.com/rojo-rbx/rojo/issues/61)) +* Partitions targeting files directly now work as expected. ([#57](https://github.com/rojo-rbx/rojo/issues/57)) -## [0.4.4](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.4) (April 7, 2018) +## [0.4.4](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.4) (April 7, 2018) * Fix small regression introduced in 0.4.3 -## [0.4.3](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.3) (April 7, 2018) -* Plugin now automatically selects `HttpService` if it determines that HTTP isn't enabled ([#58](https://github.com/LPGhatguy/rojo/pull/58)) +## [0.4.3](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.3) (April 7, 2018) +* Plugin now automatically selects `HttpService` if it determines that HTTP isn't enabled ([#58](https://github.com/rojo-rbx/rojo/pull/58)) * Plugin now has much more robust handling and will wipe all state when the server changes. * This should fix issues that would otherwise be solved by restarting Roblox Studio. -## [0.4.2](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.2) (April 4, 2018) +## [0.4.2](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.2) (April 4, 2018) * Fixed final case of duplicated instance insertion, caused by reconciled instances not being inserted into `RouteMap`. * The reconciler is still not a perfect solution, especially if script instances get moved around without being destroyed. I don't think this can be fixed before a big refactor. -## [0.4.1](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.1) (April 1, 2018) +## [0.4.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.1) (April 1, 2018) * Merged plugin repository into main Rojo repository for easier tracking. * Improved `RouteMap` object tracking; this should fix some cases of duplicated instances being synced into the tree. -## [0.4.0](https://github.com/LPGhatguy/rojo/releases/tag/v0.4.0) (March 27, 2018) +## [0.4.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.0) (March 27, 2018) * Protocol version 1, which shifts more responsibility onto the server * This is a **major breaking** change! * The server now has a content of 'filter plugins', which transform data at various stages in the pipeline * The server now exposes Roblox instance objects instead of file contents, which lines up with how `rojo pack` will work, and paves the way for more robust syncing. * Added `*.model.json` files, which let you embed small Roblox objects into your Rojo tree. -* Improved error messages in some cases ([#46](https://github.com/LPGhatguy/rojo/issues/46)) +* Improved error messages in some cases ([#46](https://github.com/rojo-rbx/rojo/issues/46)) -## [0.3.2](https://github.com/LPGhatguy/rojo/releases/tag/v0.3.2) (December 20, 2017) +## [0.3.2](https://github.com/rojo-rbx/rojo/releases/tag/v0.3.2) (December 20, 2017) * Fixed `rojo serve` failing to correctly construct an absolute root path when passed as an argument * Fixed intense CPU usage when running `rojo serve` -## [0.3.1](https://github.com/LPGhatguy/rojo/releases/tag/v0.3.1) (December 14, 2017) +## [0.3.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.3.1) (December 14, 2017) * Improved error reporting when invalid JSON is found in a `rojo.json` project * These messages are passed on from Serde -## [0.3.0](https://github.com/LPGhatguy/rojo/releases/tag/v0.3.0) (December 12, 2017) +## [0.3.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.3.0) (December 12, 2017) * Factored out the plugin into a separate repository * Fixed server when using a file as a partition * Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory! * Started running automatic tests on Travis CI (#9) -## [0.2.3](https://github.com/LPGhatguy/rojo/releases/tag/v0.2.3) (December 4, 2017) +## [0.2.3](https://github.com/rojo-rbx/rojo/releases/tag/v0.2.3) (December 4, 2017) * Plugin only release * Tightened `init` file rules to only match script files * Previously, Rojo would sometimes pick up the wrong file when syncing -## [0.2.2](https://github.com/LPGhatguy/rojo/releases/tag/v0.2.2) (December 1, 2017) +## [0.2.2](https://github.com/rojo-rbx/rojo/releases/tag/v0.2.2) (December 1, 2017) * Plugin only release * Fixed broken reconciliation behavior with `init` files -## [0.2.1](https://github.com/LPGhatguy/rojo/releases/tag/v0.2.1) (December 1, 2017) +## [0.2.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.2.1) (December 1, 2017) * Plugin only release * Changes default port to 8000 -## [0.2.0](https://github.com/LPGhatguy/rojo/releases/tag/v0.2.0) (December 1, 2017) +## [0.2.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.2.0) (December 1, 2017) * Support for `init.lua` like rbxfs and rbxpacker * More robust syncing with a new reconciler -## [0.1.0](https://github.com/LPGhatguy/rojo/releases/tag/v0.1.0) (November 29, 2017) -* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) \ No newline at end of file +## [0.1.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.1.0) (November 29, 2017) +* Initial release, functionally very similar to [rbxfs](https://github.com/rojo-rbx/rbxfs) \ No newline at end of file diff --git a/README.md b/README.md index 7fd3fe27..808f0f6b 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Soon, Rojo will be able to: * Import custom instances like MoonScript code ## [Documentation](https://rojo.space/docs/latest) -If you find any mistakes, feel free to make changes in the [docs](https://github.com/LPGhatguy/rojo/tree/master/docs) folder of this repository and submit a pull request! +If you find any mistakes, feel free to make changes in the [docs](https://github.com/rojo-rbx/rojo/tree/master/docs) folder of this repository and submit a pull request! ## Contributing Pull requests are welcome! diff --git a/bin/docs-index.html b/bin/docs-index.html deleted file mode 100644 index 098d9e79..00000000 --- a/bin/docs-index.html +++ /dev/null @@ -1,10 +0,0 @@ - - - - redirect - - - - - - \ No newline at end of file diff --git a/bin/generate-docs b/bin/generate-docs deleted file mode 100644 index 28543eee..00000000 --- a/bin/generate-docs +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh - -# Kludged documentation generator to support multiple versions. - -set -e - -REMOTE=$(git remote get-url origin) -CHECKOUT="$(mktemp -d)" -OUTPUT="$(pwd)/site/docs" - -if [ -d site ] -then - cd site - git pull -else - git clone https://github.com/rojo-rbx/rojo-rbx.github.io site - cd site -fi - -rm -rf docs -mkdir docs -cp ../bin/docs-index.html docs/index.html - -git clone "$REMOTE" "$CHECKOUT" -cd "$CHECKOUT" - -echo "Building master" -git checkout master -mkdocs build --site-dir "$OUTPUT/latest" - -echo "Building 0.5.x" -mkdocs build --site-dir "$OUTPUT/0.5.x" - -echo "Building 0.4.x" -git checkout v0.4.x -mkdocs build --site-dir "$OUTPUT/0.4.x" \ No newline at end of file From 91023c52397f41b60947cb53970af26f694a302a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 2 Jul 2019 15:37:10 -0700 Subject: [PATCH 0567/1504] Update more repository links --- docs/index.md | 2 +- server/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/index.md b/docs/index.md index 2c72998b..5f1b54d9 100644 --- a/docs/index.md +++ b/docs/index.md @@ -8,4 +8,4 @@ Available versions of these docs: **Rojo** is a flexible multi-tool designed for creating robust Roblox projects. -This documentation is a continual work in progress. If you find any issues, please file an issue on [Rojo's issue tracker](https://github.com/LPGhatguy/rojo/issues)! \ No newline at end of file +This documentation is a continual work in progress. If you find any issues, please file an issue on [Rojo's issue tracker](https://github.com/rojo-rbx/rojo/issues)! \ No newline at end of file diff --git a/server/Cargo.toml b/server/Cargo.toml index 7444835a..5a675ddb 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -2,9 +2,9 @@ name = "rojo" version = "0.5.0-alpha.11" authors = ["Lucien Greathouse "] -description = "A tool to create robust Roblox projects" +description = "Enables professional-grade development tools for Roblox developers" license = "MIT" -repository = "https://github.com/LPGhatguy/rojo" +repository = "https://github.com/rojo-rbx/rojo" edition = "2018" [features] From ce09e57315bfd4c888c49b5712feba463a68c338 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 2 Jul 2019 15:53:44 -0700 Subject: [PATCH 0568/1504] Tighten up meta files a bit more --- server/src/rbx_snapshot.rs | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 280dde4c..72369dce 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -111,11 +111,15 @@ pub enum SnapshotError { path: PathBuf, }, - InvalidMetadataField { + InvalidMetadataModelField { field_name: String, path: PathBuf, }, + MetadataClassNameNonInit { + path: PathBuf, + }, + XmlModelDecodeError { #[fail(cause)] inner: rbx_xml::DecodeError, @@ -166,10 +170,14 @@ impl fmt::Display for SnapshotError { SnapshotError::ExtraMetadataError { inner, path } => { write!(output, "Malformed init.meta.json: {} in path {}", inner, path.display()) }, - SnapshotError::InvalidMetadataField { field_name, path } => { + SnapshotError::InvalidMetadataModelField { field_name, path } => { writeln!(output, "The field '{}' cannot be specified on .meta.json files attached to models.", field_name)?; writeln!(output, "Model path: {}", path.display()) }, + SnapshotError::MetadataClassNameNonInit { path } => { + writeln!(output, "The field 'className' cannot be specified on .meta.json files besides init.meta.json")?; + writeln!(output, "Model path: {}", path.display()) + }, SnapshotError::XmlModelDecodeError { inner, path } => { write!(output, "Malformed rbxmx model: {} in path {}", inner, path.display()) }, @@ -423,16 +431,26 @@ impl ExtraMetadata { } } + fn validate_for_non_init(&self, path: &Path) -> Result<(), SnapshotError> { + if self.class_name.is_some() { + return Err(SnapshotError::MetadataClassNameNonInit { + path: path.to_owned(), + }); + } + + Ok(()) + } + fn validate_for_model(&self, path: &Path) -> Result<(), SnapshotError> { if self.class_name.is_some() { - return Err(SnapshotError::InvalidMetadataField { + return Err(SnapshotError::InvalidMetadataModelField { field_name: "className".to_owned(), path: path.to_owned(), }); } if !self.properties.is_empty() { - return Err(SnapshotError::InvalidMetadataField { + return Err(SnapshotError::InvalidMetadataModelField { field_name: "properties".to_owned(), path: path.to_owned(), }); @@ -536,6 +554,7 @@ fn snapshot_lua_file<'source>( }; if let Some(meta) = ExtraMetadata::locate(&imfs, &file.path.with_file_name(instance_name))? { + meta.validate_for_non_init(&file.path)?; meta.apply(&mut snapshot)?; } @@ -582,6 +601,7 @@ fn snapshot_txt_file<'source>( }; if let Some(meta) = ExtraMetadata::locate(&imfs, &file.path)? { + meta.validate_for_non_init(&file.path)?; meta.apply(&mut snapshot)?; } @@ -694,6 +714,7 @@ fn snapshot_csv_file<'source>( }; if let Some(meta) = ExtraMetadata::locate(&imfs, &file.path)? { + meta.validate_for_non_init(&file.path)?; meta.apply(&mut snapshot)?; } From 2a0efe70a52197997bb4e432a9ce2e064ce9ca5e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 2 Jul 2019 16:09:49 -0700 Subject: [PATCH 0569/1504] Add rough tests to ensure broken projects stay broken --- server/tests/malformed_projects.rs | 45 +++++++++++++++++++ .../default.project.json | 2 +- .../src/bad-model.model.json | 0 .../default.project.json | 6 +++ .../src/RobloxInstance.meta.json | 0 .../src/RobloxInstance.rbxmx | 0 .../default.project.json | 2 +- .../malformed-stuff/default.project.json | 6 --- 8 files changed, 53 insertions(+), 8 deletions(-) create mode 100644 server/tests/malformed_projects.rs rename test-projects/{meta_files_bad => bad_json_model}/default.project.json (57%) rename test-projects/{malformed-stuff => bad_json_model}/src/bad-model.model.json (100%) create mode 100644 test-projects/bad_meta_rbxmx_properties/default.project.json rename test-projects/{meta_files_bad => bad_meta_rbxmx_properties}/src/RobloxInstance.meta.json (100%) rename test-projects/{meta_files_bad => bad_meta_rbxmx_properties}/src/RobloxInstance.rbxmx (100%) rename test-projects/{missing_files => bad_missing_files}/default.project.json (61%) delete mode 100644 test-projects/malformed-stuff/default.project.json diff --git a/server/tests/malformed_projects.rs b/server/tests/malformed_projects.rs new file mode 100644 index 00000000..a5bee0a9 --- /dev/null +++ b/server/tests/malformed_projects.rs @@ -0,0 +1,45 @@ +use std::{ + path::{Path, PathBuf}, + sync::Arc, +}; + +use librojo::{ + live_session::LiveSession, + project::Project, +}; + +lazy_static::lazy_static! { + static ref TEST_PROJECTS_ROOT: PathBuf = { + Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects") + }; +} + +#[test] +fn bad_json_model() { + let project = Project::load_fuzzy(&TEST_PROJECTS_ROOT.join("bad_json_model")) + .expect("Project file didn't load"); + + if LiveSession::new(Arc::new(project)).is_ok() { + panic!("Project should not have succeeded"); + } +} + +#[test] +fn bad_meta_rbxmx_properties() { + let project = Project::load_fuzzy(&TEST_PROJECTS_ROOT.join("bad_meta_rbxmx_properties")) + .expect("Project file didn't load"); + + if LiveSession::new(Arc::new(project)).is_ok() { + panic!("Project should not have succeeded"); + } +} + +#[test] +fn bad_missing_files() { + let project = Project::load_fuzzy(&TEST_PROJECTS_ROOT.join("bad_missing_files")) + .expect("Project file didn't load"); + + if LiveSession::new(Arc::new(project)).is_ok() { + panic!("Project should not have succeeded"); + } +} \ No newline at end of file diff --git a/test-projects/meta_files_bad/default.project.json b/test-projects/bad_json_model/default.project.json similarity index 57% rename from test-projects/meta_files_bad/default.project.json rename to test-projects/bad_json_model/default.project.json index b0aed992..6ee28290 100644 --- a/test-projects/meta_files_bad/default.project.json +++ b/test-projects/bad_json_model/default.project.json @@ -1,5 +1,5 @@ { - "name": "meta_files_bad", + "name": "bad_json_model", "tree": { "$path": "src" } diff --git a/test-projects/malformed-stuff/src/bad-model.model.json b/test-projects/bad_json_model/src/bad-model.model.json similarity index 100% rename from test-projects/malformed-stuff/src/bad-model.model.json rename to test-projects/bad_json_model/src/bad-model.model.json diff --git a/test-projects/bad_meta_rbxmx_properties/default.project.json b/test-projects/bad_meta_rbxmx_properties/default.project.json new file mode 100644 index 00000000..8481c7f7 --- /dev/null +++ b/test-projects/bad_meta_rbxmx_properties/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "bad_meta_rbxmx_properties", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/test-projects/meta_files_bad/src/RobloxInstance.meta.json b/test-projects/bad_meta_rbxmx_properties/src/RobloxInstance.meta.json similarity index 100% rename from test-projects/meta_files_bad/src/RobloxInstance.meta.json rename to test-projects/bad_meta_rbxmx_properties/src/RobloxInstance.meta.json diff --git a/test-projects/meta_files_bad/src/RobloxInstance.rbxmx b/test-projects/bad_meta_rbxmx_properties/src/RobloxInstance.rbxmx similarity index 100% rename from test-projects/meta_files_bad/src/RobloxInstance.rbxmx rename to test-projects/bad_meta_rbxmx_properties/src/RobloxInstance.rbxmx diff --git a/test-projects/missing_files/default.project.json b/test-projects/bad_missing_files/default.project.json similarity index 61% rename from test-projects/missing_files/default.project.json rename to test-projects/bad_missing_files/default.project.json index 69fc0af0..e5ada9db 100644 --- a/test-projects/missing_files/default.project.json +++ b/test-projects/bad_missing_files/default.project.json @@ -1,5 +1,5 @@ { - "name": "missing-files", + "name": "bad_missing_files", "tree": { "$path": "does-not-exist" } diff --git a/test-projects/malformed-stuff/default.project.json b/test-projects/malformed-stuff/default.project.json deleted file mode 100644 index 710bd36c..00000000 --- a/test-projects/malformed-stuff/default.project.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "malformed-stuff", - "tree": { - "$path": "src" - } -} \ No newline at end of file From d900887d977a0b0b32fb98c45be83a5fade41cdd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 2 Jul 2019 16:15:24 -0700 Subject: [PATCH 0570/1504] Add a test for meta files attached to Lua scripts --- server/tests/malformed_projects.rs | 10 ++++++++++ .../bad_meta_lua_classname/default.project.json | 6 ++++++ test-projects/bad_meta_lua_classname/src/foo.lua | 1 + test-projects/bad_meta_lua_classname/src/foo.meta.json | 3 +++ 4 files changed, 20 insertions(+) create mode 100644 test-projects/bad_meta_lua_classname/default.project.json create mode 100644 test-projects/bad_meta_lua_classname/src/foo.lua create mode 100644 test-projects/bad_meta_lua_classname/src/foo.meta.json diff --git a/server/tests/malformed_projects.rs b/server/tests/malformed_projects.rs index a5bee0a9..8910c178 100644 --- a/server/tests/malformed_projects.rs +++ b/server/tests/malformed_projects.rs @@ -24,6 +24,16 @@ fn bad_json_model() { } } +#[test] +fn bad_meta_lua_classname() { + let project = Project::load_fuzzy(&TEST_PROJECTS_ROOT.join("bad_meta_lua_classname")) + .expect("Project file didn't load"); + + if LiveSession::new(Arc::new(project)).is_ok() { + panic!("Project should not have succeeded"); + } +} + #[test] fn bad_meta_rbxmx_properties() { let project = Project::load_fuzzy(&TEST_PROJECTS_ROOT.join("bad_meta_rbxmx_properties")) diff --git a/test-projects/bad_meta_lua_classname/default.project.json b/test-projects/bad_meta_lua_classname/default.project.json new file mode 100644 index 00000000..8e664968 --- /dev/null +++ b/test-projects/bad_meta_lua_classname/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "bad_meta_lua_classname", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/test-projects/bad_meta_lua_classname/src/foo.lua b/test-projects/bad_meta_lua_classname/src/foo.lua new file mode 100644 index 00000000..4c3ac65c --- /dev/null +++ b/test-projects/bad_meta_lua_classname/src/foo.lua @@ -0,0 +1 @@ +-- foo.lua \ No newline at end of file diff --git a/test-projects/bad_meta_lua_classname/src/foo.meta.json b/test-projects/bad_meta_lua_classname/src/foo.meta.json new file mode 100644 index 00000000..71f29683 --- /dev/null +++ b/test-projects/bad_meta_lua_classname/src/foo.meta.json @@ -0,0 +1,3 @@ +{ + "className": "Script" +} \ No newline at end of file From dd0327ba85be63c9e9184e59b2b146192c09d0ec Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 2 Jul 2019 16:18:04 -0700 Subject: [PATCH 0571/1504] Update Changelog in prep for next release --- CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 866e77be..19cc79af 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,9 @@ # Rojo Changelog ## [Unreleased] -* Added `init.meta.json` files, which replace `init.model.json` files from Rojo 0.4.x ([#183](https://github.com/rojo-rbx/rojo/pull/183)) +* Added `.meta.json` files + * `init.meta.json` files replace `init.model.json` files from Rojo 0.4.x ([#183](https://github.com/rojo-rbx/rojo/pull/183)) + * Other `.meta.json` files allow attaching extra data to other files ([#189](https://github.com/rojo-rbx/rojo/pull/189)) * Added support for infinite and NaN values in types like `Vector2` when building models and places. * These types aren't supported for live-syncing yet due to limitations around JSON encoding. * Added support for using `SharedString` values when building XML models and places. @@ -9,12 +11,13 @@ * Added a warning when building binary place files, since they're still experimental and have bugs. * Added a warning when trying to use Rojo 0.5.x with a Rojo 0.4.x-only project. * Added a warning when a Rojo project contains keys that start with `$`, which are reserved names. ([#191](https://github.com/rojo-rbx/rojo/issues/191)) -* Rojo now throws an error if unknown keys are found in the project file. +* Rojo now throws an error if unknown keys are found most files. * Added an icon to the plugin's toolbar button * Changed the plugin to use a docking widget for all UI. * Changed the plugin to ignore unknown properties when live-syncing. * Rojo's approach to this problem might change later, like with a strict model mode ([#190](https://github.com/rojo-rbx/rojo/issues/190)) or another approach. * Upgraded to reflection database from client release 388. +* Updated Rojo's branding ## [0.5.0 Alpha 11](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) * Added support for implicit property values in JSON model files ([#154](https://github.com/rojo-rbx/rojo/pull/154)) From 09a0a803a193d496527e1ba38288759a81881d75 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 2 Jul 2019 16:22:01 -0700 Subject: [PATCH 0572/1504] Update image branding in the plugin --- assets/rojo-logo-square.png | Bin 42801 -> 0 bytes assets/rojo-logo.png | Bin 42784 -> 0 bytes assets/rojo-plugin-logo.png | Bin 44173 -> 0 bytes assets/rojo-polling-icon.png | Bin 375 -> 0 bytes assets/rojo-r-black.png | Bin 559 -> 0 bytes assets/rojo-r-light-gray.png | Bin 986 -> 0 bytes assets/rojo-r.png | Bin 1001 -> 0 bytes assets/rojo-sync-in.png | Bin 382 -> 0 bytes assets/rojo-test-icon.png | Bin 430 -> 0 bytes plugin/src/Assets.lua | 3 ++- plugin/src/Components/App.lua | 27 +++++---------------------- 11 files changed, 7 insertions(+), 23 deletions(-) delete mode 100644 assets/rojo-logo-square.png delete mode 100644 assets/rojo-logo.png delete mode 100644 assets/rojo-plugin-logo.png delete mode 100644 assets/rojo-polling-icon.png delete mode 100644 assets/rojo-r-black.png delete mode 100644 assets/rojo-r-light-gray.png delete mode 100644 assets/rojo-r.png delete mode 100644 assets/rojo-sync-in.png delete mode 100644 assets/rojo-test-icon.png diff --git a/assets/rojo-logo-square.png b/assets/rojo-logo-square.png deleted file mode 100644 index 57a339f47ae51fa6b4a932c7f5893bed69e06e3c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42801 zcmeEtWm6nX&|q+PUEEpR-QC^Yo#5{7?(P~09v}pFCrHo)SlkzP*n8gh{>9Z*P1jV< zhncRnYMXd30bm!^4=)Bg}y zI|&tuFJD?yQQj@!{=<>nxP&)a(_8F==>{`h-sFJ3|g@c*y>7dXIK!;$;NC4`7HmwF-& zL0kh@#-A8IJ1VjCDqmhLKdvK-+0Vm-U8%tQz(v9&nB$%Jmc8MEx3S};hy=+Kuq%Rx zxU;%2kXV@@rGabXW$}rDT(f@7<~CH~I%Fy>Auq1EV?^^#FXB`M|J% zlQT)BmHkG9pv{zj%*RN{@5OyWRe@Bx>1P#v`mT~cIVImWm% z@?JiAl4Quy4S)?pgD75d$kq8+P5`p4wosM#r1%{8y|-!i1xr-j5ju7lvAH3#&l?Tg zEUUsauw26^qmi{ZtC#kp<;&+?otSDZd#M_faD11R|ESH4xQ&NzGo|uaYxV>ambB?j z#p4`w)Fb&9$u4i%FSoiMBIB!LnAzt?Fzk^15iHG-h3A7naS3GP<8r!R#| ze#IJ|XbN!?wm`<0$%9Gps^3Y}J+;mLFAGQS4+{+Ci(i8?rB#ogKrH#Jg(HEzauho3EU>uyVE zgbu|CRK*d6YaG!WN&IrpJF)>ha?e-v(Do+o#6(1giR){wV?Fq^CD0`wX472Uk@GFke@JjU^GOr zBiWH5*^XRD+sN|CwsN*8-jxALy2ow3yhvo|WJ{s19#w}6^*2X7==AyHS82T13Lw4U z)s!|WoHnWq2OOw|9#n7?lRpQpqbc&roR*yTpH$yy^6=!I{7nSEkHwf`) zFN=89$he}mg}5LbAh$m;l9>&ohyO5Z9YFhn>W98iFO&of-G2m1V*HIbn-k7G7u6Um z2Tmiw@JQIQ{?$qpe5JNDm8KNdVnD3NB_WI9<`~P4Vt!fFkxkL{XE24sgTFdXm#7|m z=5Gg(GsdhddkSpINL`Ok#9G~yO|0;UKD-x#-_Z}Bu3)PC8`OF}%PWA>`eXVL7fDEQ z-T0OY`(O0|zxCxE8 zP3!kc91+TBEV=&?StZ;#<3aTS1xpYCI;;)tnsc|^WL=FVW884cXWUc}EAM@Fn`+F! zcufCoiBj~&7AA&eCfr*;l6^oE?Dw~MXhXkdGsOye?(cXq0C$h@8$Ig4MO1g-?goiC z{~W?TJTlPWoh`Doby0;BnOatFquQgf(ySt$NJ6laIG;j=w`dwT{L~cgbZAwVR=tey zoqf+ff+>MhyZZ>bA6hx3u?k`6ynEM!O?LC1O5g5xW}XQ8)oDGu4UhhY+FlEkomlpm zfbc+sT#yRA#GwwtLs%aa`>6=ODP00-wAL|2N2%&~I3m^C+`655j&c`5kAaq%y(};x z164YQ@OUf-)fW$cI6ECdttPx~4F(df2ioW(*^<27jh0{N`?8U!B7J&ub4Efe!sY-nSuGHJRa!;o)xu+13pvMB6#Wi?{Y7AAZjvckZ(ugd(4 zjdG17pc_8q04c{0@+?QRCzZ&cN2?R#!HJ+pCXD6}4rDK?jr1B%#7R}3 zt#F{B3$UA69GI20t(V03aD~M+0BnMIEaCzfGzc@4a?ypkn`6F9Ushad6)qexlt|x z7LZSwJMpruf2?I3d1Vd`GY+22Da=|b`==&j^b4yW+sAxUcGjFFd!Dovj0xFE`718)WKzm_hY%D#U5rb(z3xkspU z5mG7ZUrlhd4&2|erPYe;0S!QUT)0-AeB)&$^TT7RkEuX)-K`fL-=tG*Omgw5=u_g;UZYHWXdCF7oGvg2 z7idW6bLRrP)|d2Z($@Rqf?Na973Al~H8FIXHE4HJ@^z48!irZU-XGT%2X)=$3_W`h5n<0@s>cU)oSV)U1QbI&S z7>xSS>5^$m9rLc(?(9C*k=C4S_<#5Ij(owa4jQh6Q`dM+eKV|LGl{w%%X+wD=vJ-x zDOUPqQ;#ZfrbC>{emEY9YGu)ayZCkAuKE)<0gk}K@x=St%G(=aMXTnL#_Vnc89bm zW8Cm$oVDNKIwvWT_Dz!6Jfw7Z-`KW}`GM4xEFtt!RwPxfUi|7?RG%-j^GwV+3Gw(Z z23$6f?~Tc60F`NsDy;Pj8Y8?NN@ZX6+Mb3pn;bJ$lul8oe8 z_slfTV*g;y?|(lgahyaSdG|z%TYg9#Sc^%S0iKVX&fyTD+DF?m2jn9 zKah_8OcwYF2JvmSxRiC~4F|$pZrNK1itWlCq&5!+Sg|TbO10v?+(`EhGD_QSOv5rV z#{cYKRAY>BazUQ0n4e~S!&e&0LRL;}m0ONU9Zx$#Y~?(3wH}*Ui)`V$6n{IqaU1Xw zV%*=JG}`RVPNyZEER0@}S)=+;W=zn^AGyl|)4nU7DfBko>)2K4%j4kTMbB2IWvgC# zuvHw=y?^?wzq1mh#a6_rwwNn(nX_am;m7bjkKFpg!K3C|X-qnu!sb$T1owF|x1`=M z?%Rp%4)?*5!Y}vaB+|57Yp@wBPc5kPgM9jfM^={mT3P; zSza*SGHoDJO(5dkl`mSs3U^*f)K6C=c{3O=2{cO4tmnQ>;!I+;5CBU0Xh2bHA5@^~ z>v7JUppE9hq#g$j`>VybufaVzB3wF2*{=`p{L4*#Z2SH$VKCT)`(Het6`D82kwLLs}%~~L6a>Z0|R1hb(zSXOchU@ z`eB3kJ_Y{0XD~T!Y3HsyBn`M0&aDOqSS1j?{y3!N7J;y>Oxkyra~~KJP&fr~%-%5D z6^0}`0={tAp1O)yq zjMn@{hYE_8S~H5u&>Hh??%4gOAODzZD*FI2Mdsx&hbQ51qsWwyS*Om zC!|(icwpqpv^`*ra3keJ_C0Zz<$Zp=((vD%*>jRgZavv=1sdjmGiXt?>qIs46{?20i_H?q>d= z47Eq6Aej;$77BY3w21NbXR0vkN6Y@>QMvz_Ms*qc^OzER#&8`HvqsOcTft59{t*u& zBK>Ce2Qd_UT(>cI4nlm>aFNkn_39qbMP7(~Im=$rA23b6^;S!fpmwK0z9@U9xy@0H zI98&g5(`GwF%n`aCIpDj+o|7^1prFzMy+x3ISxO4_kL5=S0VMzg}t;yXCZ{7n0Qx{ z7RQbl{+qcQIcop4$^m>9VnPcg^_*3`5Q-hT$bau6-_9Yfaa9^9$8M z1R>a#pCvnmkNa~ga=tXfZoea4;}HxN?F|ySQYco7hemB%!#=($^Z$}``lMZkk{N_;(L`Z1LdEzW< z3jkZhNYTkp4@UIIaQe!e&4Yjyr9E(RC7_qI0J**!ohsv;*hW`&bbq?pw{7u#*PKcP zL(*|v7zc6^4OO|#?EIFaU*<0UP;;^Qdy6wbRMEKMY66OLBW4-M5HedOv$gcHew4SA zFs&7*((4kCs+Lv8ksIdfM7avir$R*}O|(q=Mmfs&)mScgGBQ)3H_&1>_UVM?n6` zxP`K#9X$kH!33=z$GGajh97fjJavS}tPOW?K;bFRPrq$u(J`zyt0 zv+ut;hKJ_No$YufEAlbV_LfrgBksV9C+y;uN_UC5zG}@=_5>I^8wR&?UJ9$5{2i63 zn#+F@4d7tl$A-+tZLYCy2|v;k1N!6{VNqG=RrNz`A~c=hTD)$i#{{%yJ2zPPsmgBB z&W>i*jd*H;g3oNYXAozxkQT&GE5D?O<}CJfWA3}CMtZ}c%$u!Jx3rO^pQ7vz@MByh z=G|%m%ELSKQf)0iC~$cf@>;F};V+r=$~0xIfvywpNXR*hXQ3Es3wFbE<`O4@n)OT? ztA89rTEi6&RZxa%sjpo?A5XX22>#56{tTh}UGH~#mDe_`(*G``+=^FGpDaVz?%?w< zVrGA?PwWIlKa~Kb%ptZbKNfLvf^aM_aS&(H0+w_pUxB4RQ*zq`zyBq$p(v5l!>B8Y zZH%Rn+_4pS;*aC)-feb@RZ!XzzK}c@dj5c8#_4!2CL&w19#!K?w24~!*XT{zOZUao zh>WxA>u3)3!z6)PVnjow*j^%Vk|pAt4;50~TU<;SGD`kBC-`!idgrq^IHL zE&7);tW5tl-2E*ZY$i)I5!#@@?ZEZvHjS3P$~nFzmnTh-9s=NG1HthXm|;+L(Bd3zGj`}c@VYAt zmlLb|al*ZY^0TAVW4_}XdrRb@X=85vvu`%fJ9$~xCIp$IM=Vme6bjonl=+lf@?&hZ zETu0RcA3A|pR&*2QQ^8%8xK|fjdj})g-yNI`P%SIF5-GVm2#BV4IPN0M}3^J41(~g zsU4=vx97jlGl@pI)XP0EB^{^nK1`~gZcO%j@xJd^m)v5raY=p8iNP;N77ipT(lCvqf7}1MHc+MnquTOlAji`(yKLw&Q2}+^gJf+B3+1 z8SJha{+IWd_pQfiYHagHYZzlb(5C6ffY@ZuI*{TzrGKk}LBfs0ii`5|hRD;tw_LIC z61h8xcRAHposleOt$~DKGGNETTDm3VnJ<_ z^i}@;?gw;~e@A-%#S#%*XnRuymg1k+m_$DsKztOfa14k0}!G?TqHqoMW>Y+f#}NQWPq!tg^|?K6 z%=Y#hp$xHi#bzlP0yzH#c1zXrzw%FCEKF;-#JB1P!G3U{0nrE|K!FgQJk5<lZzPtLb{~m=$${h^%2+`9QPUr7|lU zNHIuQTJ22=H5zftiUIA0@eq-Ny!31A%P)-z?w~tRJ{P*nhF&!CcdO4hDEh+1sRap| z^jjfE!aoW7iq>kqcrs>c;de^-5i-4hegHtQ5_GM^YPSQqew2#R1*$nq89hhF2g)C# zNEPyS8iQtujqR#(uYBW+ch*GAXB{~RnlUfOt`Y@RK8wGejbI-`W3gUt73}*i1xWfK ziR)c@n|J8D<^klr$tt&uhN zH4sV&D&0iK&Qm#1mxTZ5g>>EgjD2C4OK>G@xeCCv84)$Bq_-X6yAnJIbr% z)Ned`WuV^)DL%m(_!DSLrx)Rr)Z-rhG}@4Q^{4!}D`(lcG&JIDD0Dt5$OwLtTD$Yx zbH;Jr{gY5!iAv=SvS`NippV|OiCapG^Is*a;jw|Qo#vt~aN%ow-m?Y(_a-UZ9we&- z1dV_WA5%MN8kRocr?=0(h@m|56^4}m>M7SQxMqQ5OZ{1JcOKhB7cQn&r161d)w#^M zR3miz4jj=gSI0_e20@pEjBXzw#qlSmNwF6cU`Uwz2U;qV{&JN8Bj8ZCpwN`l;v+ui zbknPfRaFKAF-pof7XjinxXHsF$Y)~gJZtB1B2X>bs%{9D#h4Cm{*>Y#G057G#x>T3 zU3gITss|I-HD2x6H6a}{GDb?4JY^p*89?|)4CH9JGLPAEsNcO99A$gCgjMk>ID>wz z#K=(duQD?_kSm3L=7Od86HnRC4%}Una>5EqWdg3g0(xo~(DJ%tl??%TwSj=3yIz~G!~Q`Qn3%QCN*l$MLhYpER3eqTfzLwlg*PKBuD9>!S_<&wI1@= zjD94>tNA}30-L8G6g(l>%s~attLW<~>7GyLfP>%EfgvPBv6gjpH!f8w#25>)b+guK zQaEN$a%bNN>MK=`C=;ZtC0xfPqcVI%#K_G}Q;w~Y3jO6smw20rZSIO3F&(N~=B(bW z-4cP9tnMDSPA?)e|I!}FX$!G*NW`SKho30laB3+onNSmwD&kU8PQRA{|Cz%tX{InU zNU!GUk#H(p$pL$vv6n)oEh+GUaK@!~oUe(fp~ky|-9?g9my-7jv~fWew9sPyaMf%k za4T)Q$$*CDfuad{IrCz<#D1|4OVzZGxgk67$Xw|&K@HnWrWEL zLH~GW6AgNI3ZWQYv|WZ?ijgX#5wer~2hiRQ%`6wx(Fv~jG@Ewfl^uw(=_CP*bPbdf z=MAHkgOPPn{Zvg9nt?3|`R=04f~A3!y*zRZVz`0-b&|mt zW$_MJ?ur2{x%ibkDs;k#lSzLsd-j$hBGv!Qxw7Tw2+EoYj{CtIUzy`_W}VZSv1#C} z_TO-JoQ*O3BtPOnsyLZ}wa8g&=KHC~;S*JS7Hjy>jAKs2Z<~_$YO|RiHj{7sU?spw zgK~R{%mAI!s)m8Fij{d{{3H&OI&THnh>(AxvCXE!M#dlHguF*>q7+nyrbEhU$!R}+ zyd1BT)O;xM5th2||0ShMK~+J*XyZS6b9~N0=u&#t&?Y=^p?HytlVKe~En8os9D^qt z-G%~N0E@w_+~i1R<_W8*p3>**(p`s!r4s`R~-umo|i6q&( zNXfRyaZbjCbBa&tX1(xl=ZA3`dNl_T0Fdc;L7 z>UPFw0VNRUvH!njmms1@E4GSI>81L$)S|7JA%~0PYIb`%@ z$PJM{P#GS}cGuv4ZNt;YV~NTeTe2bOBJ8@waKJ{913yFw)0Z{~?j2iA#kFwz5m2}W zh*Y#2fl7&@-C4;EhozX$haQhF5{5r_S?bnD?^;(x!LL}iYQDSaaOZo&R0cMhjlx(y zh4pph=+v**vfA40YWrl?rT%`s?qoBdYGBV|m_G_zbv;eG7pt%Nb}!Cqq%TN(33l_p zzMTkhJ)}Ot>Vh%F;xsJh-uc10fU)VZa z->{QZ3V+{rATXeZI^#19o7;tTX=3#+hUEm~RW@q1u(=F%kCFL>jK(RoON%{4pO6y4 zwh51)v+6%pQN2%asoz|9+t*(?bMo7MlBW8lYqlVMIvG4!i>g;7!mJv^eZJNLv+)8m zGhCLoL+RRB=fh-ZZIvx^$jcTV&$&Cml@brzh{oVOt3H-UY%lWx?fBot3vH~)a^phv zi1eK!pEHcwu67%_@1z_xlw+(hU>cm1(oLsx^r#fZ6llM3wb)!TZ)X8N4s)|3fy3q@ z8uv4_?h?n*=g2K}kqUSDED+}Qb|S}35P}QGs)NF)?Hiqp_~L-4TWqEi?j{1Busc^O=${h1 zyDb5xUhuB}nQ8qx+kuZ-zt@diA6+WFZRhagJsgQ3M3nK+b+=oIY-x4i1jsA zNaEMlpC^;9rVehogEwXlipIer#mDeqpIoBMrGR{Mzn+9w;=B?COg9w+dg514QY+$& zu_cd=L&FPl1qqUgTWb3N|UZJ95U zhI^YyPYqb){l!M;E9+h}6rR8`Gg_i~4zzA2L&xOFgC7?jSt<5+=q89@A&m|%;mzi+ zQcesa_1Y+(!$0!^J4DH(#o=e<+l!{2`2^!!Y}$^9-Kv@yMBo-VmNh9*v-j9-LdF&3 z-_~*c#OBW}e-gae`lUmgkwwesb(;RY)S#7~mzsaB?@;y=1SS^d6ef+cF9$wc%ONa> zCuOF4p7Q&Njh#%(_gE)U3Cu)q@rv?@|4?a+S7Tvc_ZXZ7RVF@0{h#$E;{2YLvd6rU%d;dybFyaXc zp+`v}jsDmhXfb^<^?gXTCc=fSjb1cBu}#R;2VIIV!cV16;|(*Gl!PegyA@)g&9;t736ZVpZUj&`!GKjT9qfQn_!X@Rp{-a+AE!!AHRjvJ$!Arw6$5~12JT%^38yz2 z_#qj}wc(4XE7U< z^%$W{?;b{Ey?A0u4rD7+IUMIMpd}d#UD0iv@*WsCV!6w`2y-JJn<^}XFWm@mj42oOC#n5i*4%wYO(p@5-$gYX@*|Plf0S6Al%#UVg>cly_ij?H-~GwW zqL2Qd_VN&Hk8x)WhrpT|#o6Y!b1>FPw{-bi(D4e@KSK zUeqqj9$MV^YtU6NSJ1tG^%@yZ$}Q3!;~<+9Apnruj)!EQatKW+N@4#fMRIaR9r~;0 z>7@OGT=SL(R#5l$9Tz3<-W}D4Mn;G!?*$b-RS?7=x$ij{$ku-Kgj%3q7zxCgm%v{i z=%Vm?Q(R$#KtE=cBH}#3$2WZ0#?EPX_>d1ww7E-ON!gfJXo+Y)Dqv>=VZ=w+*V0t) z`F=ZHoJ_ib3yx|i2I+$(p6iu<{|#cewFS79swRd6fBCWHN-VNn4TQRxZBrpMU?sGy zQ`Ap9E~lyCXT;+CO6b5`$624TK!o~>E5(88)QN{uTaH#lUx3}2M#-H}kAmyXWb#)! z?QR1viF zS9E)e^7|g4O(i+B#I$U0&hg+DSX00NtI|G3hqAoQ*5Gq6A6ogAPsQsg{UTNS>ksn% zbyy>)fWX%5Y#bJHO8|HyK8(8>^_y}$hX72;-3!;AL&Ah-oMev9QptqxXrV)300LM5 z4gVsxUH!)kN^9@q)K$+F@3Y>A-bBVzWdv=~n((tBfIPrQLkQYP7YHnSpPG|XpYHXC z3%bKYkVV*XxEs+s+h{TMEtOBO|oSYOz`8=l|rdRr}`6>6Z$R@pf zWg!VE$cej%e1}hEHH~P`hJ56U^@NuqF+$Z2g$1WU>u_4DM~BA6xyYITBd%3T=*vkr z5N$??c<^Ve3-XnAdxUXvP*ciu1kys9);U?W{NFjD7Z3{6A9EMVdOY%alRk4m8dIFl z6Iw(nme#LaKimF>|LYLqb@f(1b!L(Aapw?jLoY^cN8|ibXs<7;&(>UVtqe*9?|zi5 z=47DFSX=&`dD2V|hJUHm;GNti!MKoWU|!>JjB3>H;8iyGW)Hn@%U;B(XahY`%7=AY z!S5{g4oGUg=g7}e!b1&0AIJ?@z-X9`)dtWNGfRa`0=&fQIl0(kA^+fwaWPv{u0IX4 zzcQmXOYinX5`jXg?fsJ-7)F>|2JyS#Yd_aHQs;@iyaX1tD`N zFlRY8^dGp_Yuvj*H&xo%9sq{%-f8v5UcDGD^oClZ8Gc(%E7AG#^b0kBQ3vs| zmms^+(dWl3CI)53`0!o@NmdIU7pDu%qA)ph8&8x$%5UcowyljNai1Akoy-G3h};^r zp)QKjf%X$O;SW?pcjNG0rn}u&;cUhkg#jTE2E-(SEsIZco&xX-@3b!jC!AV&099k8 zc%kKy2xWGC-kgx&moj4QHiqxUv_=u&e$Bw+{V++>)l{2_1qa~b$IQm0h|>BppJz;J zp!fxXmUoQ~Q{u{gsf_?Ep6QI{-G589$Wz~RQ;t?O2zKtoJW}1H5=xt z#FrEm+`Q%+!{LWc&`HPUS|?RU$)nT^bGKT}Atl+&I7`d)v%uLa^fV?uTV=_#CF^-3 z5Xm53pq5ni)jz8puNCz3nuE=HO(7pKZ`$sF3^E??B3?`wT&b(;Z8w-86{8nYxVmBN zCpJ72?iIB>&HlNGdd{__{+iUN&dA3W&+|5>J9BaNGcFfv`EP4O6#KR^-~&LJt!@0b zY?ya^rOJwNHhz=H+@VyUz9O5iK zcgIYyw8+o=;s?v36ZC{m_fP~ZYQ`TV3U$IxYDkY5=KV_c-X@@F7HH@tCHtC(z?sfE zEHE^1ilv5wnqNf^U+q`ayxyXpnoNtTmWX!8fuqZ`;7~j;M~wVilkvOky*RAHssFW- zQskxF$q$>ltN@Np_DzeKTZs_H=$Sgi(ZUQC=R1|>zqJ;QXWV|(Bx42Nl%;L-WI{+Y z-JxJ?-R6PkrNa0y-*KDT)5X~Ew%ORB<`29h=H%q+EqgwuP}aWhj10jPe_f4GS&*bd zh~MHRY>?cPWAYsWJdmnZlaAb5dwyJ*!hLtP!y9Ng#T^Vj)L~%?Ov`7tj8;R9KLvJI z!8WC8U{1 zD;&hFS<_Dxv4|VS@WEwwoxkQ}q2tAh!Tqhw)@va$wj}c2Xfj5-jfhuRn9W|2y&L8G zwy}QxyD4{TYP`lA4VDe-cK3yd=Aq=jvZcUofP6H2v#hQHM^I@+ShqZO#a#%Md=0od z=A)8a#rG2qVe~R6(Y#JPi|jE>ZfCT(fiOSI^^1YhI-;)yO!Yd@9 z>kok~X+<`Zoc%h-9Mewzq{sxyxm9l#WmiV?`OC(RK_4#R__#@&b1)|Z4E*atSIfXX zresBnP0C<4CG3$h*glcW)0l-R$jguTV=7Y9a273eA_dAfsU7;bD7C{gFQ(NdM(}D} zFp*%=b*rTmnaa>*FlSNsU#aK)#Cp$U{pp|>oJ3o3(s=*rB%${4wwroN zS_fFs;+)JZUzj1Wd+PId@DH_RMc)XQZhQ7rWsp%)k<8e2XiWC8vTlM%?*oqRdo94{ zQ>puBWWuojh~&XdJUYo??NN9yu_0}A+Wg0pl{Hd`jAX7b%7T#yq` z50PEDby-fIJE;edAMNx@ZU8fN+2_2}?Mm6K-%#?Aou6QQNi}NCDH*Rr`-UxL-lKcg ztk+nhubnrmp*2u+fGAk~r2T^E#$fM;y+9c06;x#wy>c%f8#W)ohbwjxAy=o3i z8|~rxT58W8l$tF1kYjG67MnCRdRZI9D_zH@MWQaU)7-so{EcIRVcG_LpMNMlU5H9l z<1D*|qF%0~5d$xw_WYygWGwse9nmkwNTCq@V7dwY(fJLVp*Yc;yx&9|j)GaW-1PVD zXs;|C8|-{w*>g9H<92*1*8(IkfnNwEP5}9cJD*6Y9$L2z)52#`onytHhb}!V{U6^e z&8$Y#=4){C{wT{cR94KY%}0oI!P3GIk@9M0QAz(A&6BOH5c^1N)S4gCCWJA?)XpKP zNE1#yEMFd$WnI1vDp4}q9^pp!;iL4lg>8cCy|S2WcMps2A4-(3fhr96TQ3&T`HxAi z?vzs^$yT~LC{9_Jhp8~6Eu)g%Q-AjQ1qF)x}KV^$hk+Kg4-!bx85MEdu{wmcv2x4`ZfFm5)vWk@OJe> zyd;V{(=4HSNsl&p8hq!;mugy2QN)PQ6v8l;z8i3Gut-(47sv8lm;zYF(30Gl8`HH5 z(4%&e#1h`I_?)5gM(cerBDna2I+NUZ4Yt}y!=j1*J#UvwE`1G7Et4&vhNo%CfWt!= zu`(?FQ7WUN>%)7DHzJgC-{<*DV;r8ab7CqjJYbV z{2hO6=>ACt)7C#hF|*$}p4pq5*Qm%nbAkO_Y0j@(w#wCmorcEPW+O}~-6t7opVJgR zj|Or(=*tH&<~2`6@jty!r%Pb#P7lCq2AiACz$-o>n16!a>e5;(f^9#&p6z@(5cq=; zG2|Xs{L-V7!6T$M>}D>J{yQjjI8x@^`X-Bt^$Vm@Wmbo= zHUUM%;rh|J=N#f4q?gQ=!A<;II6S!aa%2*fUfYjG>dRx3LH zh>a}bQaNaA{=M{bJpY#4lkq?|mL#m6)B&_`uDZC7n=6X~uunia^|>jV;Bo?5_yP2y@Gfuz-KjpH2AegafD&*%m-)y-~~ zmX>;6qQ5f-tB<-W-vl?M-_*sam7tbvs|JI4nO4G{OzmFz7JEWP;#Mz54$l(Yx)A|j zmGBo)(}d`NSd?+<4w?l!Khe=ZEupKY1Vku}Pfgpr-0{*i%GcLU)4mCd5n+T+t|pnQ zdV?0tQyEg7(GJ3iACv_$cfQK^o_}GVgTgK_7I%i25DaX-&4r_(@yv?{4B`5X=B3%@ zH$~~&=^=m`fO7qQ>o?ycerb(+ndybUPrd(Ke&%DVrcn1aI?k=k-qbfpdC>Ct%3x8< zO9+kw;*Ha;TAx_F19vLyI9w|9^M9xJ$k{|Lag1}otvbjTbK#j9P?^L`^&5sws^trM zQ%0TWjOIw$67d%r+Yjt}uY5S67mVR~ha_*x@s&S5GX3tMO)t;poZ%s+JJfV8e%)rY zPm9o%HNm~vw>Ev^$IT=9ob>aPZFsXgSPou@e9|@~ujRUd|2r@=Z2vnT(4K?HDw968 zz{%ixAfexbmqi2)JI!_sjeEJp^@XN-~|8b1`B^4BjN9@UBj|(wTD)78-Ga`^nJEUgLI(e zM9ckm?yMLJ!&-o#kCTyH*Ui90rH2xfFp9E1=VJ8Luh!)F$3&C5VCxqnJ?0;8?S!OC znw!ji^lj!3e|WEK=V!|XgT+ESYs-Tolv~m*7H>@|vTfzl7qv=dhQ@YehBytzEzvb? zXCuML@M>8%VIz}bLE|wxv^5a*kpgg)f70 zp@qG%LOk zv|{v^;ot<-tZ<`^NLKkIOlz3UGx+5_xk)OQwohNVNUy>zTQ1Fq4yVHjBBxjIa&5tQ z;uW%BcR^%$j@R(}IwxJR5{pRt(<{%_$ThKTwtOi~C#+g|Y#KY=Z$@Bwz1~rJ1}k98 z>YJ5uoLmjP@iFCbM35gV$RBR*Nvs#yY7Rn4+fMSS1aQDtwo65OBWQ5&-rnG_a2y28 zX3!9q&sM9SE+(Etfq0NlHN0G<=a3EeXv;HtV;ba)AZK`x@gh^;|HRrTsvl2MZ|;ov7c zK9HLY-??cIId{Auy_vt}f5URN{h80K;6TYZuC(^7YzbZXv(-MyrEXX24wTc!Hwt~# z5aK&AlC-WLQN|5;6e=MXSJi-5Hh7T0oiIJR!w;F>CFDT$`HA(&Az{<(o|9d2)}$e8 z&?c6Eh}Z3vP`Mi2nS7iQgmc8}3ezbO@3hXQHenKmC&BEqLU_NPK3ZD;FXjqUaK`Gvi5+O&*k>n+!u7_YqLV$9` z+!iTB<>KHTh9rBW5uzF>uI$o^Bq62_91GfoXW~ax?tz%(Ou!Lv)<#&xOWUZ(5M?|C z%|6TaTgY0muJlnm^Q0zM8%rZ0*ZB)|MvONzI9oWu;HbLs9+&k-(U4i6Q=F=FVTs?X zQ+K$LG+8Ohs}{L4wPe6~Zfk5kjzKP;g;nKDgm1+SmDs&5)@;M>lRhqD z(%+G< zw6+VWXczgkv`+CINyCb?O$2QgE~D| z$-WMvB%fJdZpw(Z9ghXd@^ntSNl!e&lmCNY~ijwS40J~NiS18gupYlXE7h!ysV0SO76X~)K zr`W$)ruutqSpof~*?Y?kfLE3lyd7CG?#{ljFb5onw zsS;eyTx;UKIUllnRZ>9s1`cY&9i5qSwcV6zx|53Ex07`A`v1NFJM;Al`0S`$h_o(7 z+j|}nUe^UwEDS#=t?-D%91#J|`~^63YlgG>lcijuAYPacf$)~a_oK$v)+{naCL&f8 zaQ#djUKe({WzM5Q#x?>eT)XMX4>mIDH&q_~tX4k}n1bxHWxxTXrZ@L7+RvsDNzq!M zOaTEdfA#f3NC#HHScE@g>Wslq;16d&3p{eF*cRfpngnm|akMtY0BP(v40Yqm_j++U z7IVXh@g*SM+Z(&hFaTJFK)6L96Vp0{YEi<=}_?qI&LDpues&t#1XDt%39RDdfqntJ7zRaOvy&&qD&r1*f_h36{_4ecS3yQD5g|EO@ihDbZ*i}VvnSQ?AqO`3ceN@Q)b0(j;!4&sp~TF;rz zR%0Wqy5+~K;$W_)(xqRP14~9aJpCrxo*e85s_uLlIkI)#4E|(qf+zuGaWrGwW<+Eu z?-6xzKY=2j8`dXiRb0q$^);`dzpOT4z3>uhx(<6D3cS}LgTla(S>Pfq_e2rBpT(ux z4gY6&|Ljg-(-X2iCY6TyD-R5(4Ib(Wb5{Jxy8-Wv8frdwU z+e0t)Llks*jF;@0Ad5!I?rm%6DM?4Mbl`g}7`2&5k@~_%MkPiXY(K*;{YZT^ANIt4 z=I_BL2T-P{5!}VFL^((^6)|Kjx&Xr=by>o3CGW}Hj$XsWw04*uGMQDBi{VCe+c~Hk z6N)1ZsWbdA<69pjS~da}oNf82mX?vE$Et`|oMA#c2KwfSd z%o}+sb2FM~Mm=D_y@^(#%%8cO@#<~FjwtNSl+9E!kpq10N?MV{UId?8kCv_*c8v(s zw#@-VrL#UW6?VZ&G&j^D{5Z>A)I#(lj9YxwQc-^M>5VL9L2}3B8XWTxS#D{B%T^ya zS0P8%k&{m9ew8_v)ph)Xmh%P>HxK*;UbqVQhtdfw6LcvIoqB%CB;7(L*mRzYC()a% zk=^hj4#K;lFld|_lJ+}3IX0T9d~@KF8RN20X@3kvi|O*pwt-Ew92Fc>aa@G-*zy4^ zT=)MN71Hk5@4|H~$`CGM;puC}cp@~0Vedl6-n}En0(fVo#WvQDE#j7}CMvOdclr>1 zW;*JIboebT$js@mK1>T+nit#@{4deVS!uzZNe}93Dg$xJdnz|lE-Lu_quUT!{VD?E zO?afgU`r{2Np0F322X`R-u>U^z8P z`EuzXkBuf`K{=K+C_;3P3HK~MJDKI>jiCHw|Kczr(3*D7fM1&FVlpyOm{u!Xa0h8f zjaiPRIP4m2X@2RHX8OCC`UAnagYvu7J6d? z<9AXB?O(JJ{R;2P>Ih;X3sS~u@;X}#L}H`!_`Of&C1fCX)K>ITfF53K9!2-L1mc1B z7H)}a#09)^HtGh_G42$>Gt-DQ<#o)VVp;`wE&GahnFrH5e4c5{9DymGQZxUcx)v$o z1&wya;bDTwh)HSAjimw} z9!w{4fHh-R4cdo$Gov`>50E$ILS)Hekf$?R-7D{4s9}Vjd=<^5>xNJOv-JDUM*10i z*M+pe#cE{%H~(qEmBajbA1k!1dfQuh5n=J`D!5*0LBKN;zH51JcLdgR_l}Y!u`3WR zW4>h3y7s0Zw4b*aRYTTilG*TG6{3tFD`tFT-K0VaHjCHk)S@TnAkd$YGsB7dJ;)Ws zC(B#J%bt{#9X!_a=&kuy1p96qR>k`UP;X?&ITflj@5SbCI53!IF$FC9O(c{~Oxs4j zI-R;rMjtw@u=j^hIqKW~uSVvCVz|Tu@7jMO%6AJdrFEvqen=*G8`EfWHmb*L|Avr= z;uuOCe{2)?*eu%jkM27ESyF9JuV!mOgl@IhAQ^I54o1w)VQ=JzWeLdC(w zNXZ=s*Af%v?lov!_i9J~z-Yjkg%nwJmF2`Jrc#hu&6SLh2-9bozT$y&5mtuG9RD=G zynu0w^}X@gEdK2c+3>#GLi(V}YqFtx=Z(UaPTKBXdlQ2$%0%w>lz+7L?dqpdEtYb> z6?_#!DO40$Ob8K@0j6176wyj5jsm7zf=$nccqa|?=*BTS_GF2((sNix4SQm9lgzUj z$gTrmB>kv3V@gvDj-C{U)UDMfA|j_obsUeyh!*}Vq-SKnlCkqLY;~Yv5#dzUj?jVO zwp1n~E9)e9u3^cM+0{}(2U{4V@X1bz_w(4n8g!8Q;;DR859xjtK?J3(_5xO1#=)ti zfP9>XG}Bzg2uX#O(Kb?{-vVzmFw>shhUS$tStBPQ{S*q4LJPsyPC|n$boaKu87V4a z%fB0yE|_U1ELMCGbeP0AzQOxqC3aVG(oP>2#EpD*3!jxVdC&PsKkHiL$NNM^919r> zsH|nt%%NTn>7G7$*VQXT$Z599XifxaCpap0=$n;ncXsmo>4KjScuj-u&?BW+^gcz(^3>R)4j}v$di-MP+mu`(S}Rg-y;>hlb9vGsKWx1WV)Op5R76O%K-QGsF?Fk`LCPr50^_XQO z6^Ahq9u{=tB&P6yml|P3ZlXC{x&@756%Pw68U7nkaQ<9)Kgmm3+-)!&`*9o_&eJT3 z_c2psc;jnKmo>McdMKNFJSW39KMiKQIZD>Q+D#!epVzYXkZkcP-j68dZe=C5ck-J7 zMBkv2h<*;mXYl4ZJbm<492v^~m;q6Vc4ZjLPR`@cz-aye@(N8D^t_yhcA}|l zAQQ=knsIPfGkmc=+Y2ugiS1ZiTE9U)U~rhhvsN3Bpzhi`l;JhIAlFPl;I2^EL2H5D!yj3H@0 zrWr}aVbMR9ksyh-h4w_01@(xDltcN$pvA>a{TjwyZ^8ZvbAAy8O@9kdPl#f8nZNbh z$5FlQRWvrZ(eke&sC#zJ(9RNf&Vg?p1>rk*PN8E+bHy5dzK2qTmD#w*fc+RB6VKyq z9wFnuo+e{AtQ;1glc^ND)+6zpWEi)2 ztGy`&F$ik6p?SatS2^0H>`FRNjyN70k@hemyLj&v{-9Xci6G5u^w?t-yzDPCS`~-C z04dT8brBP^w?2%%h%k@VJcpX0Y(W?{Moe*BiS+ConE5PVVkr$Y93cw6<|@=z4)Hoj z)&=lQDnY?#b79`hcgjk>gHd>KXq`E)7%+di4X!nGVM8yWt>Pbt{g;2JPer;E_o*-`J`X1k(D`*Qp+lXO^a6++3abf>|!kk(6AZ-Y3y=_%$iA}pi5&UQcGN4SE2I8Z@m_+iO}Jr*THCg7&D z!8!0UYG_f*j(@T`?lF-jEm2?$gSo|mnL)`sBI$SxjK%PdKN)@*EFvSRdP~#3SQCL! zI|^3rP6{KYIHHJ7;Ok}6mcew4v%orA`5|q&Lxpt{(q~+XoSV|%`6$bbOtMNw(}Y-S z47>g3Ivieg7Y=l-z*4w|w18cXoHMfFUc}eLmwFM4Pn3x4mHd*Mvebk%i(kmZtnQvw z0~4Uqg41ThoX2BM6wbz15g4^@cqJmTG`cLPCre|*^DoGg)N_&HSqQhuc*~kYk`|IT z-Qz*a+B~1PFQIq!0u`rBu9Hb`=lWoO>=fkpYrUdmAWOtB%#(OZhdVZmT8J`C<@8`> z);lfZ9{0eAFmkm4gmwoyF#Qc$ea?&gl=&jkG`5p*U2Vc8lK@ZSb$rxJ7aTDscNN37PC}}z%hk&3mnno2 zZJro*$`O%S;xw?|vUI=n#M&uHPf3GIMkR?7mF;e2=5J3!pmUiv*I00+&`Xq&Z?*i* zOy0X82kvu!fyv39$I~adNX?oImv~arbP|7W8}qG|o{@Nd5}%&xcsp;tX&`4%&5BhB z%dqCo&901UzAAGr)3h963P%}eaMbINcZebp!TFZD$_G;UrEE#;bs@X`+#&R`2g)ar zw;)9px#;K@YhZNN@`&wYZ!O=JCSxTbNaKq6`N5V`*QGzp#8r+X#eMPXdd=HfrDt0c7Cy*MBqsC zjI>ivqm@d_$a&t6);IXQjL(;uu|14d(RIQ*|4RVieAA{ z%UqzBWj6ZZZ;HY^x{(;u;cxtijS`aUE_6-=#LX5Wn|b{Tk9t-jDh%V(0YuKAQclKT ziG+wC>ZJnfz5$vHlU~b1gj{cZF9rqm+De25)vQ>Ckc&z)HhGX~+v0{DkHCnrp{|~_c(e0|3gm;I08y6sV{3Q5fDIw|KV0?^KEHf|g zRKl5v{1h*@qMZhA_0W!x99Bk3aX7VzoX%Vrj3AawJk)~rs*}4}F@r&d+?|K4$rmH% ztGTd##!MHhTPkLJxrfP2(#9~t z|M0Tn+lWY~xhVGTNa6p7fk>l?u(*E_XdTU$wZf3+2S3lvZ$ZT1Mu*xT&Rabgs*;XR=^m zSC4SSC;|Kzz;}8YtPe0>#e0)x$tP?WG&W*$oD$M<%!fCa)(_t|u+@i0EkjiF?U5rTi7 zh6b@_hh1q1>By7W-K+?2TfKB&6w%FL1nF8k;*IpQM7Om2Z*jxD%LUIA79I*H`%n;3 z*~)g%c`%feBPtf-TP$o=>Si9&FENpU?_4^=kkxRU8Qe77xw9eOIi^?dliW;7ojtOaZ$ zNY6sH+>O1*SKLvi#3HGuaUq68JiYn7yx;a-p5ecc^+Oa~BCu@Ok7nUWPtBfVnqgNQb6GhrMWz&XS*Clyg@hSM zjqhxJ9W{fpbQd8j>w4r~I1k0YX2Ja#OLV;LKWS;hLf1@X^c2m~KmISOx4f^L02?l5 zBRw}8rgUb{UVINIFt*uPo4k$;@z?J zx?+7CqJUZrcqY(A_gsLy944}O)bYAm#xU_;R6IUO%N`Vm;bytYn>o1V>ttX|gMa)o zWZuX!AZxgJX-KTJVc+c_B5P`OUAn#}L_tXWq>itpVYTj$z?j~9qbG)4acpD3@E|H3 zdQyo8^ZxZFoCdlZ0~Nxq>F`cl1oNi(@PFG2<7(c^X2D2$nouykFdKm%u0Z+gL%m;k zU-;>A=fW**;-a{_BD2*uGH4YhqO&MCMJaS|rjmjmU|d!+>8NOoi+C;1?;MRY#k*lG zgOBMRTXLjp{$?;*)aSPB$srxILO#ot?6EJ`lz+yr_>6Rfi=gdZ`Q^73Q?M-NXV)g9 zllhxh7s5AnsOBXcK|qAI?1j-apTZ6-TK1MGy`DPhCH%I9@P@l^pf_chF!bW6bYp!% zQl=w(Z!Rq^s}5m56Gptyc)1X7+ho}hWg=nd9xg#v+VzznFX{EKKiq_@%#S1cx>T4~ zF<)hv^9~vUcUdrKNSV?^)ssObBk?xzSk6P1aFICH^1s!)VQ(ABIzLnldnU;aKT#O6 zzLQimN#FrNcky5=0?m|w{r(M^to2hA%>6iWJ~IpcFY&j|WJwr`p_H=x!mk?;`bq@# z+ef$nxhBG$OQATAkrZJgR-zn|er+_Np7S6xYQm6?Kyk&pr-fW^rB_zPXk5Yz$_VHA zZ5@kCj(Qw;()fS(@}ACk$Z%sBW_{GsWr9eXyKp!H`%Nm+|Km9oYmc4f@~8;uu9mW- z?>lV-FB^xGSB)D3Z=X!lW;5Sa~Ke5GKr@>^VC_(_fBV=BtAVg`2-oJ9TjMic|!@sqc4u2 zO`0gnS%*XsW%CDToxF%~ypV@@q1|N`m87$a@shG714?{+q=^qbJQX4FR7bkr z4++DrIF2AVl?h$IV-SVIs5fA3b9by}8m~BgVayz#OFfFbn1vnXyzDv3CCM z1!1tTpg8-f9RIQ%fxmnS+eT#cRClJcVm8B;CKZWuxeZ&|n`OBN8A`f73|DFdrVPRD zrET00>#K^-=5?ms5t@|ZmdAy|XvSdNrNg^xe}EJmnb#qey(e!|^0A>F?G<0gzUIf# zu##nVE$=7VpJVX{Po_ft`uL7fIY|?SmmsYm9hU4d-n9>cg;;(&kR7*iOMJ&74xcGx^?Ar^EEKP}DiFMRACSChtjMeGM`F#PjItiF9X?1#2;d zcu%AGh6>|6WM#brx$nt@`#-7Nq#0fEN}AUmayk|zyq<>`Ts@^}E&pZ@KcyT=Qz$dU zSm8(8vulo%b*Xw{SQQ6_mvXS6xJ#iS;fjh^BQ8gfjRdKL{c}w6O&&(LC>%N1Pq;fg7^=iq>M82Dl zwdfld_tSAOA7UZ+95Yus6Gbo%MWK|i9Oi$wZ${JqeGkpMc|9r$&Sf!$ZAv@-B&LH5 zq^I{_?BKcN1C@c@LP5EV$s&cnr!pZ!bm@xQ2V{mdD@Hag$Y+~SGL)EGzO1W6p3QC>$&YkM*`*(yi7coO2dvWysBzGK#8Wc$L1H1mGkyWn|* z=^xo=BlHTBPUgMzlz#ksoN*dbX5ECz!{K$fE=B&?He8?L`9dDCcQRnx8TO}G*3aUV zY|hl1yjsWbw((gRX(e838#CgudbnQx32J1tS)yfR%rUHrgXXTR1}h_22H64TFk?f( z^E$7(Ba?TQBImr>Ncm1CtdB7>C1d*~I0nFOTJHZ&O*hSL%YRfxoec!lA;1bAXC_RCrUz;$X)Xr!twd zAHpam+)BTX16?b>LreND3dl7)?@u#CfsM!w7a--r!7jnh4D=VlE3^E?^NW{foB3H2 zfom&`02xZ%Q~jchGhWU@YO=hI7)KD6CNfc^QWnH0TS}Kca{_`g*;Ve#tZ=U#Q+C1n zC?Z>UU!Lu**aTS$<&-eOA1{GZbn6hyryG%bUM@WU$x{&}QuZZGVj#W7JQf4@N?wbn z*i$&lXuKZerwme%IX%n*hl<4f;~E?o@a9-!g<(}37b8z5jrBB~tv`qr-&Tc4U2h%Z z%t=}jMmh_uxR~jDXOHjW_hJ!=OFbCNK*F5a4#ufW1PT;~ zR;n%gB~0UWn#0P?bLkY9-R%0v7iTN2=DAGEbUyY5rRHd#yK$5+plA*wCS@VvK@fa? zLli~}P4~A5fUT(6v>kzeP{3_qx+OZKRlK~@Lx_B2CcN{-1MIxtZFiCn;HDSi(9?*mJ2HU^ z?bIkz(_BauFR9mjpuo=Hv)7~|dSO0hOP_)KW>T4pjGQl_@S}6!zk|V(xf(~C#u(ls zw3B2w^Lu%S67DIlS{TmFHlkv9$zT%3$*AD*$97no$3pY%U>R1$QI06BK7$t5+lEE< z2buYLxFyyp*K-9}&5TV)>l@5mT8+}Q`!>YAl#b4ad5H2DXhjlt^d&d^zgmOfAGOV~Q3R^5I%Rsd9Wi(0K|ETvk zXiEB0VO-49?sHfALMndgF0@px>m~$5C~QRQi!57DupIVU2H%e1X5ycg3**y^Q6k>L zfS83W3bokCqoV?q0cfz{>~j#6X2hdHuq(W=kBXzF8v7Deb_sD9AqrZf%T9w1m9#O# zhnyM;U>Uq3idVLioom6Q5RNG>Nw>brP8yZRhg;CNlm)KGKDPnlItRWfXTx*TIJjrSy<9ryw3+BNPX_MB+QQ)3k;{?a8W&H zvJ@3CFA}!=dcbmE?I=QKZy6*bs3xyL#^pRO=DXr;$}GgPcL#n)>r7^a$}Vuy!6*Xd zZ51s6#EM@*&*%G(qVb_eP$liWqtZRCK$uq1(dEPsME|{Hg5n!|+Jc zUQ9_a9Lo%tvi=#pk(iR8u*F=4ZN3fHZiYpcXgNl@8K?63PhE?`OQ`&N65##CTng{B z%aHToDe!%a*W!Wp^qX=|%1Li!rHryemJpFivND&69-#4Z1g?Ls#x5BQ@V4@DJd$Wd z8Z!O&4A_V~?nT?reF*)9 zg43k6@D&CkZZY&HJYp#wqV@K33Z$>CN9C%Os7}i8#-TtaHBFDLYZ%+Gi5R6k#EKS$ zDFQ~~eysS@Gl@;;lJ;INJ&zrSQ90@rhs1pf|1o1karCEoD98k&aBJwXA49y3DG2Rg zIl7(c+MiKYlF%~J>LUfPuKES$6kOXs<>B>pw7s)jA2q&2Sl3f{wbF|$;?YafigSQo zdO6RN?j@EZT*mOo{uHq~$?`F?9pTBHLvmw^gW;3OmM5_~N}q=a-(xlB$U>4A7sB@#X2SaBH&8S~jDgPY65=9cXMP!l*G1uaf(1bK)ew(tfO5|`#IQ>r zp>&8#eUdG5?`uKpGs{umk7moU&#);Dx|}IYWLar)z*Ylc<+N*#AlOX7Wz%)Zejl>V zxeRGvn2(h2=EC|2Eg7){wlQjVr6KY^OHucmci_k#6XyIdGCt7`kBrxrO<5%4`=vBk z(qA$W{pCB+_~3P@kY$!feL*Qhz@cS4iIrF?oDBUa=OG@FcpQo3zsX1*bl^IZr?QsU zOI~D%fap)!jReL5q>6PelN!7BZ^&Q(8B!~IM)WAWm?*FN(caE7)@T0Si^|sZX#G14 ziB-Jpk5HC6u!v>#rjwB^iy2If zAL%o1#bimdUdy1&1V0O@3zxwA#lnu+;4(*}>x9XE!Mu_<%7TY8`4ggi>Un-o7@>PS zXp#QDKFiAS#;_@l{j^s3Iw=GL$~b{J(`>WAWy3$=R*d_^H&F7s#Ynx=f%zp`JoEYe z4p!n@QxW;_CN%v|7{-<@NIUZ>6#Xp<_k(=qGyEB8TkeTmo(kudTQOmYv^JEyT_O0+ zLH4;l0H@_LKLZsbLqwr?b zL|{rsxn#Ih&bL*pV^Bt6`;$flKKUGKS1upL{TV%x2G<;>4Fy`PO<9_#0#u+m{7kU0 z$JVHF^I?f|8-m2K&#og%nReDt570CY5S}jH3*5-EFHyN>#a;QNugm=%zE%P z#li1n?oHWiXzOotTEdhvU7x|Bm-yqNkfm%$_+%m?Wx5P9I6BXR_l95N^N z=6T56k4bP#zm$vw?3!;BUZzQfK8f*t+r&TKYv8ea{17X9){XWf2(9L6e3=nJhCxgJ zMr>xe+@R2%WgS9aJQ^kp*WyON{hm3?z;+9P^n7!vA|1M;`g+7;2j8hBZF6)?Uoh zqd;w4Emlu`{MH~{#HCZf$cj98Coz0+kUqZ#te9dQ^ zr0K4Q_{(zG&L$ha>i#xAT!=tfJwm_ZpY^uMro40G+BsOV20%z&ssSeA6(%hPz%)G}U+g5FJm8ylg< zaLVG07um3@nHMrVelQA67EP4=rEy>s@?3Uuj2WlA8Be36!Fupo6~e!H67?@W($P;i z7G*+G7>H2qHx2y9nnX9-=+BVIo{&QJCUa{IJ&fsXNcp-OIp6Ri^Hw)JpJ2wyq#aQf zu??gLfK;>^S}+fU(faL&Q1$3Fh z5&^TtzrQzW?pplD#RGr#{Z-VtEXAkl24ob zutdlWd7d4Hy_v6}@;JJxzzo*ODGcN5{FFW=LBhO*`IBkHl&lkfR_gZ4JmP~E`djBD z?(rkpM5y>)jKKNs4phIeqWAu>6NX_C05>9g0VUUfM>ND?<^`EsIsB0eSPH2at@-HyJ*o%M zQu8F5o~9-JGSj!87Jh6|MJj;kEk1Z;72~&f51&SHAp<>&;qR*OnTckF1N$VNclR~~ zXB< z=OLZl5`Jk@eSszN2SHfZ9YWa^79!u^Jt>fhAlBuZHk>;`@ci(4ls|hrDqD|}krKf= zL?&}Y#zrcjy8V>n--f{U-NAY0C! z#x#;y@JE+f=e=bNq}hh%&(MzhvJ26>c`Z$UBO$CMy<{-SKOzYI>}KrScpFxpuzecc z8FIxToqhA+lA(urEE+voMg4*S7Ud&{2(ah8i2jUu{B4%UhdhX8m0;X2qHx{AdorIx zp6iPM6~;?Z1aE&6^}l);`!-DYx0^lYnG0F-$8gi?lXPcV80HSRBL@){k4%<*Poyng z1d<#LCd>epj{J>Os!@j*84KNTU%^wE;og%V?Tbb#)`NRt)C|UGpqU)J8Hd(IV9VYe zz0MWs1L+UE(FNzmi!pnqOn5sF`Dx?ek(twP88yXx4Msb5bd=Fc-RqXk@5@>d-d#3~ z8wyGMD-dD*!xkR#@^urHTQkEbUPSz!pXu{qe#+=JQQA_bCbNED=|;-*bhuU(pyj($ z(Ei{2yFc)|T|5#guQB*z()u9AQNn-I4gS6PuLxRy^H)^8!Rvwk&T+|*D-K#AX=(5l zv$RVm*|7xqv5-nA1?YDjl`HiFnP~i*iAs z@*rxKFGrw!g!cqbIwi=-&W05)@O7+C_8!!QUPp616EfcB+y^m>S;pbVhH|oYmrjCz zR8}BL&YU86Wd8)2&(Pn#G!a_u7M#~I&?J`fpxKI+d)nYU&(nVQk?~>i@~#b`<+`(w zJ9QE432r#jeARW*DixjKV+EFu{+{Yqh~HN;+xB-~sBx$%hqF2eb0tq>Bdi#(Dg2zz z@N^HyG9I!IMm%2PiCk{M{6;fU&UPU!KOM$)dMbak5T$V#+eE8}w2YNcF@_#xdi>6W zb1RRZ^Zq(2&qTcH?(F7EzJCy{-`|XeE!$LSyp8@^W&MV=#yKAuH?Tm+sGR;bA9QCA zGxRPhhsXHIf1#^d;r{}K;73{Rq!7wZTz!q)l7f4P&pgba+%X$%k9-2vRabRbJjWe0 zPc!Djzkq3T3gb+x(^>6;{rYRH2g{IpJ`+%u8}B1e_$`co@jn@{QewjXO(jzIzmB@m zmR_E7ka^lkNcjZ4hS?0Wlxy)E#V|_5IFg9&Vf=o7OUGU+Oq#*51)%_ywlx7B8CW1f zzrST)nq?u>Z$~Bb%^X#2S>~@TMBT|vlS&1sAASGOZb{SGDi_Ue;6Y)S~dF-wolKeYok)$sVSz^Ka zDE1s9jfbD<@E4qc)b}%Br!c+}r}+NhiCT&gmZukdXisKefU_Ub7b9r9pOPoh{-mzR z#G8pGj8DqJbJ^3nYko;Sl<>da45bFvm8~zKZX~>DrvlBJqX^y4#N5kE34)$eO?L)Hm8qa0K-+ao0OPSUm;q_OkP-IkHTrM07 zDJMJlu0Mp){NN$Ll^sWYhZ* z>CokS8#kc(A%^|86v$Gh`dj~{e8%f&PYQ?fz_^6Rt^DDy^Y}0ykqL*g60(fEOjNc- z>7mG`Tz6EX{+HiE?Yg^80NF5DhFoz_Q024C$fTUX3LIG`<0RHHBP7C5nr+Id4a^r%DXYx+d@!Y5_^42!by`M&yO#+g zi@9}8pIC+Ef4pgA-UCRPiM9TRe|Mmr@TIFkh>Nv+hqF z$}y=t5=(ctbneD2?}5-$d6)XsOJ2w_G3LQqL=O#j|3+7qGi@J4;Jyaf|Kw$Vysp=o ze}7?lTfsvXr0m);9#`xVe~~MqP$eBCedOq_V0uEzx2z1Y$$|ZYMntcD8fAa@IRdif zYkxh%6Oy4;9KK?B#Ve3XJy?Mg+rCbY&gQ!=Q1UoHK=RagYfSd_Xl|?Moc1UypV>B3~~^|@1Hj8|KssF8iW7Kd$OzG zVB$o>Q99i5dl#IqPDI5oevFFvazZ1TR%3}F6#{uc`qxk_E7!_ydot{9D3F3k;V8`w z);fb0iXWa;wb&C|4fM8-!f-+sh%=Fw{!aLBq+tASX0(j5xpO0$|MwL%I-f!D^)%g> zJVq{)M|Lq=#pk|j!n~7zD)S(^LxJafI|V7f{Q~y%cQLsoM9tX|90Huuxp}{s&#gU8_i%pb*49#0l3-bXJ zp~q>vx3e5fNoB zX(dX+G~w*!k;e;Z!s@Xtp591qE6l7VgKu^mFeQNR0{G6Ow{ascWvHi=tw(Gauh83& z$$wpktae43uzty+v6<(LpY%64Pgw};eq?y&?>Mb!+gO9>Z|QC9U;!PfCM)qQUr)if z_#WV+0$TXdsc5ZSkBUF~(f%_7_A|UKVLVn{mHd_bl=jnpmb=*e4(74-qZ|ZpJ%G}u zZo`2_35$Fgdqf!!L#jBc;F`b+9v_C648kltEDZMgRs>(T83%TXXCVdQME5Rw!Kpwb z#6+p$DV2vaH43Ll1b-#M(h*G0EjB@lj~H$$4jKC|%R=^U3OeJZRG#8^8Bf1}=&)`7 zD-+3XN7ZXg$6qtt(vd$D@2z1zHav~;VOgK5zeruJL+!l=8vomc$hR55*LYjXVzQdl zC6?}!#8%NMCyOq^RcF^LUsL1r6^L9#sp<1Q+MOvdjWJY<=f?q!-q#@IuTga(Hp6VPOq zbsN2tHKnjuJ&8K$Y#mOVH(}i01p9Y9m1V_~?Rm&D>pRj=H)@BJijntUXj``hmG|0c z{S5Q-7c^L?*kc<(4J19J43{&1SMc~5^Y$ZNxUXwQ)gOL{y6r1a8TYJ}Br#-74m9h$ z??#?XT6#YZsjNwXg-rg*5Z^hOu=3AEdSxY=WxB6eZ)#0+gMv11COk`-X49B(OdlC> zW^LY%h-(4-GTVL%?}vD7H4&yYY@E!BC(CsAG?Z1=7Ye4qw_+8VhE3qgdS{m-cgb|P zze53Y1;Z+{fom9-e^5`Xv0zIXlfA{eZ)7CpLG~Dbm7f{>JMl<7{M_9J`!^4w;&p1& zVevM)vJFjOKfuek-y&p(Ci z=R;^e?CJ0XX}~xI%xf9QAnDRIZ6r^{un}b-o`tL?@t7B(2SNzkbqQLZ{RV2c{S6Im zt5hBg8AGNxWZd1w$hew0cMdCRPfH>U2L7ZWI||OWV9s5Lj8Fm01`n<43bib{<2?l_ zXVbHo&GeG_0Clv|SH6LUre(;uNYaq^D8QW62AmZRELqk;Rv&)bZgND*i!}SZ_&k~i zvVh+}@Scn8Q>VlG6%*!V44aJG5At&j!|?zGjBMB?{T)5*vEf8m{?q4Y`_AKNtThbvM zl}--HVx_ReJCJ-xXIf3ogE#F6P#b_F`!z_%u$PLZ!GUe^d)8%Xj_Q6iH9EL;@L?3G>hsbypGSF7J>hS4M%pVl5IkzIkbneEd4dcdd6uH%So(R zlkwc{MewnWXp-L;QH%6(1P{IkHGkvj(>#*l!HJi#aTQ7>??yCk13~(lo3kVF>2e|joR z=}e~JHBxD{y|x!k2lC-PHCI->?-0nlf^co4RnPQvWKl#}(X^+&DGF;RvlwnF8gutP zv`cfskZ?P4W=%!fR~VLe^RnxfsfT&U{?_kiT$b==Pvt8>3GxKLmjxQ*69TIY*gtJX z#zk>}7*y9(9Ob*Qju*{G5jL556m2Pq>DQyA=)YZVm1hTmvaqiUta$G`PDv!L>+$LMc!PQYaLc;94jZ zT*?m%?r=CCIJ1^e9=kHW< zlosBqtB_IJZukbQh{k(Bl1pNVtkwKP8@o6P}LP%~;TmmxEIELFte zUV$8m1s^roDWVlCLY>%v2G`<1N2P7Hq&?>yd{tycU2VKTpE?bumG|@UX8Y($j*Lrt zW2Z=hH?2gzO$6nUH10N|J!2~}5;#L|w)@h%Vk$gZWINNTLSJQv&FLU!pu-Sf3;Ar!>jo-gG{yK0GyMrfk6?*|GZqFW?Ue z-27u|+^PtwN(*CfZ1Pi?PF~94&vR4sWn&+=8|Wp%D5K5X3wZrtB6#Hl?cY;L78 zqx}Fw{=e86cfbkRp;}18dw0yS7VKrdDz<~0Pw3!e%TUr7XIOumy2U_Rz1H$5sGH=@ zp7}J4nS}y&8IE(C%Uxp{>gCUUd(MzErUfsaXOw2+uJeyW#)XC@Gg&BZEv6yf{x*kw zG}cg3tCW6<{2j21B#Q++NG5qmuM#-|3-Q$&rD^?b$BQG+7G#tUETcjGMarfY;=#DH zv_>^LD=}#&5@XTrOEJy4j3C&i!cq=IUTx{UH%?`?cy3Yuo9Gg-m$;Q)mKU)n9ulMhutvHLz{nBr<8jJi*hEaNiLPddM|OP{K{RK zRaC%?UoGF-A73Ad$w#MjkOPDc(DTe1uaG=8DLTKxr$1>GuI-`Hh@Ilh*Iv#S6<8xbd9{lWDsOvD+e?t1z(WiJ z87zJs69Ga0LXI^pS;3S zmyK~OG<|B>P%Ie!kK+EvUiGqM&PAq8jQgJ8mG7ILf*$$j>c28ievUZckXd}nV=iwg zBk47>a(2~%xCo3Y1D+42w%p5%J;yl&#N*$<68mLeg)S%rx z%T6{vsP5kVXb*+j#QrgQR`yS>ft9zPcS}X*;%+ZJY+LV2seojUemMhdXiU>VH2m-+ zSLS7jTeETK_qnyqstak%mEkMT&zv#!;uC}c0KUm9VZ>9fINc7eYgeHoo~FPgT!`x1E{Q!~>4dvVr^4&USUhxSTT1X|+0J z8~h3-e}#D6Dwpk4|8ztQN>a1)x*v)pGT}tPJ}nw${PR8 zgd6)w7`Rx+U=8bUef|in1vMOVUWt61E}MZFdC&zwIFTaaLch$PP8|1GAY@5$fB50M zo@V!0!e)DgkWvcf!&lBk6atc$WFDzMuOIeCX9uRO+Wc{ut7Ze8C|>z0{= zdtx6PtZ3@~P^_480uJ7mVK2dc8$@Y;DX%#oh&(c2(lIe^^tC3If!Q(qOZnDQ775x^Y&kR_qE^ z2>JA9RSw=KdnaNvMPgdX*CxnUd>Y=ox8hHc%425t*Yy`#c)u7-6~XC}gMU)AUrBDF zBVRF6Y4VAax-jC`^N9Oyk<#lCB@XfR-ygZ7Rxl>su;1fTA1>*My4Ytom#@Pup4u4{ zkz}0-Lp3taOV0faEvp4itUntVgtAG7wcB56uxOhxA~SY5D_*b1jm(*6qVgiBO|Xli z12Rb7ha8Bt#tExr`F#%LG0h;WjkRHsr+koQj*yBQ(J|TX&WJ5!I2X= zQtPw24_q_KAIK5NbrQ@s{~EJsf1UU&Gib#08J1&76q-zu6}{=;oCDYx*2im%`17At z^hcz@$k5AmHoRSloRdNV$l;Gcci%hmGRaamUEJ9s)o2Dk!~s4D^8u$>Y;=V{s%piy zNW`NRA!3dXjw^@YckT~tD$f|$riwRWAO+ElI+yb`cTUlhO(ol3c^Rl!vXV@kvnyQR z=QTSetr6;n=UPXz-FoUaQGF-4Wu5W^b`b&2f1+JJw%59FdEG!+h%9z=uuT=t2meBN z$&6glh7Mjr1G<3cQxY%iZ!5dU(aV;p90Cu?tJTGyUyzfQvSr{j1w0Q1hMg1epLPg= zo|62XO2lU0@rwVG7nf4#y*Z(`B>jk}yRkTz%wpr*rCugUO61t$Cu9Pw=c9}!m(7Qf zVd^r*?_ug2zLu}>_y!!Sxv1l%ar^Cehp6z=K1uGY&qpTd!i&Yo9yolQQ;chLD5vtC z8+VY`D3SP16Rq$O2Qr_IOgYc?yIV`yj!sWq;TL;r2xb=#JLqBW?!mYD16m7oHi{v1 zX{}{j4FqZ8ZxX85^}&7an@Oy@lY*kfPA?v=1G5w#cTyEoHgsGDM%1deLmK={5f}O& zZ$Fa%YF%VUZ+B40SjB%Uc)arqOBH-pEjFCZ#3qIms#A4-?*8OtU#go_E0Yq`=L(K!z8zzPCqS&9_zHo;e5jsmI@o4^ z&F|=iMsdQir4;v5fR;#u9ZHcLLD!U@gHb%j9)~2&I#W0A6kgqs+z=#snRv;&tB^?p z1AOSl3Wanv(w3z#x0U$y>TR4N=G7y##7u3PPyNVFEsi-WWz?7bYP)w6dE@v40c1O@ zXK|mZ%});^>W;*nY*p0{)v8m9K}M!2*&EdK!rczm%L*ErseBH(6+w)PtU)S-wSLDC z!NmvssCtMoQ2qu#^79yZJVA671@XArtLqq1)1ye&&qS?iu0M6{xb(UDCCotU8lHd-b_?T-Gh~6nY1T1!EHqG7@`8CkeI;c9qqAR%0n-k{SfBsLS z`LI^a|7gQGtMy{$kBmz&Q-IW)-dnJS1HFj)Pu<|>`f5uh!7MC_eO>?s9*!1ce?xg{ zl>*%hAdDGlXLkB#w;eSgFGI}FFDPj{meUHnHtfs?EekLhj=&x+t(z50qHmm*y1$*u zse@w^ph1lFndwMDvO}T(#c3Hvc6ZWwjE@KN|Kxe6)x|cttly z*|s`8-sMt{EdTDJn>4T}SErABN}2SU1WcT9@q%mSKnoj;qz=A&D#?c-F?xrI=OM-} z|3ppH0d^U+(&P%XyEaH$tg;(gqkI>?2 zz8-shzQ(H9xcW#hV9bBJ*X|{HQqIR*sDXfnbfUB-61Iemcs{u7_R=XnOZziG5S=+d zRft)|@N;7q4u48Ju`eYVKZ$D;!KvcINa39mrqV_x5ng0PT-g zI13Z?eQzf)rNPqe6*-j)G;0nX(s$&&4V@BQjqeK(+3;ch;;4NZA)L0%o_YOm;?9wW z{_$7@;ucE&12_+%jzuK1XVge@_k8!4|3ho!PwXwmOhJyfXZv_Q<*YCtpuk%3xZ%rR zyfZxuk6Os4v^(&!J@BwiEicWy#y!cqqm|QswzOB4uC%vNqVjlHaMQx+mw^=Z9{tJdO7U4Ew!L01a? zdoGI_%%cbj~dzvUd zfv-TQhzpw4xls9Opmt?OV>QKa_bT>l@#RK8n5#2^aFXr=*;ri3f-H5t2N=67Gtq8B z4!~DTX7^TK;N8ZvUjsMHG+ZaLh;xi)m?G@~teH)}6T@Yl^2i~4A`KQr_~HhMx7Izb zd~377-g$y2ZCs}7$UFM8)JFA?&ObDo;F0L36gs#xF$y`??#9&TC#-pH1p5ZNqteQc ztIdCv-Z~$9D%_>lDv~XcA4mxYO09`f)+L8MC{Pa7ldE1s*k>`qxU*5zkRo81x@;ca ze+l@{VH7`G&U#4EnmI7F-wY)9ho^`Zr)xBU`Nk9^o*HF=N+T;2eIuGmM5hVneEt=* z!K0xp^XSX)XnMhG2~ZwnfKb^D#RMqI6N156o1#X&7m|t*h^$@FP*}e|kI0}bQx8l| zQ%_nc5TjQ~DM5D0&`w%(+Zbh|`}tQCf=Dn=>SS4*8JYFeBbEfcXu^L_=zFVDTQIu>zm92WuW;t(%5(nfNpZA;bacH3 zB@#H?Uu^O0Xj9VP5f)E$_4XKPPstiEkX^?c7CQ!?0nhS4?0Q1`HJsgq*kA3i1vZe^ zo#$SL4HO}G%cCp!QW@YhVg%*i&83zIo3i z&h@vvASq4(W4G21Jf?f^7w4~!WY7-H}6xt??wCo3WNpK&5m})_R7t=__RzoU~(dEejYGQfibo zV(LbAG)#`Xp_45v!+uGX=*gHaIA|Bb)V|}?d-DPU7{NsKGBWrjt>s$j^k|MiqzsbKiwHopN+w5wy|^hU$Pyr~}wq z7o)Geg%E{%Yn{eviNJ$!Q!1`}PFLyo-hkQq;~qFz+e0^)wG*V$c|u{bj zBi}-2F*gMo?Fwly(IqD}-GiH{gK@QusfMir8Bfz6-b*D9c2ccLDBHOlru3Z-u*|SF zHETA-F#e7>2*4iYF5UW}@spv+Uf<+>E(TBLOzzbfZ@EKdRC00#4(65xpp0`$w-YZf zRI~Al<3kWsI_b5jq7UI6R~36z!?X80f_m>QlinWx!@Xrz2OB77AfzWXbb3KoQ)P^n zdfJ?r?yTY_s5(B)tK-EPc1$0=28{Sx%{E|S&mmvD{85~r2{xF}QMWk`|7dwTTI;bN z18-<$x3N+ z)xU22>DeBR#%1{1^-PzjY@*lX86rf<4Hk-g%j5 z{(d};ROhmBH=)~Mv^pamt_WFkqtM|6_DMCN*Yfq^iDn>Wr2N}p=VxI z9Fv^oDyldtQg`4?Ii*D%k0|QlRP!*eVn4?u%=7XWRx`$PmSA`({L>I`8fhY1BnM+Q ztHq5ZV>P!c4_TxF+2}+ZWwWwV5akF0*ma<#VuzV2n`OkGnKh-LHAMcJbY*^2{Sxmb zgXN8D8L8%(l-2&|W*9zgNOIgd=}A?mh38k3AMfBXN4VcKs67z43X4G zSdio?jz2e?1()~F>kPO1f4=YO$lc{BuOal0znp0SxK_X~lcYE~wod#T#VNOum~FWR z>Ssks@IwWFFb}5R8F92K@+jdh9l<*+6-A?GvQ~J-g1Q$eUPiGn3>4^1Qs7NyuPEa% zrBc4nDDY7F-eP%$+)HomiM~~vXFz%iW}#Q|UTcqZ6HoXq@m1eIoxF3PYbWD`roq6{#8|}Y zM!fiTshgoBS{0*6sLq|Vuz^#bNDk`$&VH>lJLEY$-1}mTZX+O6gK8}%-~IKP%FU7& z9B|yLm7nOXr~K;H`4x^bIIH)CGus(Sa!EeHT}lHfOszO}9pzLB&tYArG~z_0cepn%zV5{#NcQd-fZc0J+DJ-1pZCAAlBWH>Ig~g<;sp@uz{+QhjV~zSW@5V z`73vH{GWeqU(OkDf}Mau*21yRGi*_#7N{Kn$@?1N3-B%IGctZ^-P4n}3M422Vll@Cg>b ziWuE+8M<<(_RW{^3XX*>%>}qpc7?I@diL)@yGhPeqvO#S`jO6StA@1iYSD zRy-U^xm{)oT6ohF?2Wa56N10^MI$AP;K0f(3p`LNH2bJ>Z1YESdBP-LRFeGgXF|^7 zy%;?i+6rfYwJoQ3NQ7@X45JO1{=}=zA5+DrGHUFO0thwTaE0K_eX{O#z)PB7e#p}P z6!r~6?c%ZFifi9cY72 zO-x+j(I38@;Nd`qwV;RCkItm>x26b{3%^`ezC_?SagCS{dvKD@YEGpF_whejDzgIS zR-`H3Cz=0^%U_}%D8nq$dhWlJy^fB~fI_)1$MAnB#O3tAL0tb3^k*4Ub|%Ump5(P^ z880E;PV=rwg6GQrHwXWB1#InF5Pvv>U^yia4aqv)5xJoi?GS4%;#7({B5~KS3iLHi z7e{tU2+17HnvIHMYr)ztSdaC@PB&$Y&{%`GN$=KaATG& z1xh3jo#d8#7J1%zUl7DEp71pT-a18OrRZ5mTi95l;D?4t^AN|o85r1nzl!aa$J%h~ zIOh^wMj~1J*ohOzJ7v#QKZ>TLT>a|1X%R~%Q-#%)>F))AS-tBa7g6a<2Ne`yv1?x@qbb5G`<0E(=_Hja{_~J{3{(RPZkDNg6^e(`K3c9)dh{ zuN74KoUI~NA91R^Ux=1zP<sr@Y}`BEIm(?-%(>mq^;_Rk7#wA903J9ve842)Gn)#&Lv@GccL|W{SQr z@u)rRmHtV(aSHxfg0RoHX6o4e@Ziia`se{uy0BeK8(y%sP@UR|%9ECf{KvxH5Y|Lb zeK{91J5fdD7!OEZ?^!fLpIWuSHeI+spBnH-cf6awJ9vek6-INtQu1tS`07J*!tlzR z&e0}Jj-qYDuzIC;Z^QHYYy&^4Z>fcx?^@SxQ-W=8T$DYxV=Y6m4j>QJdXMmyAg_>* z&ya!kKD;F#%Gs)heTY&1aS|F>ikw@Qe^|biy>a>0r3TJov+pUl76t{r$F;JT(8(M! zrS0tg9f|VfPZ@o(u_|I%Q;^OwQkc=RS>{fO_gu}n!l`*6F1(3|WOdv>GKyFa9&@Wo z`IcoZ6q5&XGdE}(u#mo?FL!cL0D5Al{aq%1kT*(i)r~Z{q%QI{yTy5WJNiYWpx+61 z--Iqj{R2(G;yp#3;ZEN#EPrU;JBE~C3o%{6dxw-H&A?aiM?!wd{7 z|C}2jSaBD?dv2kTY)>?K0hxCTBV~L2&ls%nBEb}04DZhVSkL@Br}AJaX8owmu4q8S z#vtlCZEB-oT;6mKeWfB<3jBH^7Cx??k1lcQD}W7fN7K)eJvSjfDU!c~K|_FQohD#% z;a!b-h3-^At+Y$B+3g zCTVp92Ko=lyRTcV#XV!3*K^b{3CSHKS#j?T=^$IypKx~JSLeNQg(OMU=qB=x^1jic z*5rATPE~nCvbs9WPZ_;uciHmr0x0Y`~@rHuT>8$QX$NG$1d+vyQMv^eFt=mX` zdsghbKC)l)Qwgfrp;e zNN24LWaR%xnGT%9nX0wC;>NXuG-K_-)MCc3Ob5%JHqKch8$*Qt;R>g!I+*JJzyJGx eAPY={e#8i@-M`EE@WbfY)6iBo0M)D7M*a`W-Z16> diff --git a/assets/rojo-logo.png b/assets/rojo-logo.png deleted file mode 100644 index 49b2a572af012006d9a74c6389092eb717feb25e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42784 zcma&NV{|1?v_2f$wrv{|+fHWUOl&(Rwrx)`F(u@mt?z}In5&s_GuIe)4V6`(uXa6Qp zmSRd`U|&dRle49{aiagGG#u-E+h@D=z9wt$ph8%0gxnLnp&L}Re!D+6_DX!;# zwZ3vmTJTXhOY;AkEjJW&RCScUhrK)aJa56`vV3oI+8YQ%{Qo&X!Wl`@`JZ=_2I2a+ zeo+`_v88m*?Gd#L(>Os#{P&qdJOmSbY@j#I;6)w`BNy?uDn7^prfX3j(8z4%P>!Zo zkWf5fWcFt(wABAlrD|RBj&zUn9{No2q?e2fl#1IW&c}>k0+Ic_#%4jZ!aV}F7 zjmec_y+OJ{g2Rn5tLT^`5T@y$cU zWB(Y{n|uW@Q^4LCOEd1;7sNLLLn^Y+rR_L+>tc5ZP5GxzHeaYQ?f6Ej;Cf%+^iio2 z;Bo+kzEb~#9+5ZP$no8Jh`c}Sh>DW61rPqGU1>1R zy%b+7gh^+OUE#PoOK)SM(S!*-2&Vns!RZi6&;%_Vwu4gtdN)dvLBbi0LJ3YnpqJL+jVqdHjolNVl@m(AyR4#xHx}Y zW%{CpQZ3p_ep??_4v8G8^MNm2+z^q&0HyKHhr=XhynY6kchsl46=)Q5Xsc4#;!J2d zUQ7EP!N~Vd)y|58kb^nsNR4DP#NLksbbF)Ldrp$F6?B@df;&^tBpZEqWYD9tB~CWT zLv{#!g8+^1AuH_{d%^(woCzN6MFEE6rY1V;3B6nOo{TxU+Yi(O+3kD#CHv^Xd6>a~ zB*Zw6|7<}`jAV)eA)Frr3E!m1HXs!pX)7!=qD(MhN-KcAsyLlv*FhgG3ztnIvQhFN9p# ziyi|T81*1*37|u8s!mkG9R+q~_qr?nx_$*EcFLX3ppH^HPPLV3J_D9|*Co%d38);} z39krIDMS2G$8E=IIBvM;f$2nB&P&G{ zBxScs@bD-_Px`SvKFe5)S=uT+)-%|oLi1!kn~A7Sj8!SdxH&cklaCV3Kz$Pi9{&Gs zd49kvP`?QsZdyujUyf_Y22C4k4iuX>SL_bm)%0Q|@Sqij#6>|$y!X`d&vr(LEP#ssun5Z8F?~pw+e#)>caUtN-(boP1H=5L ztEEo0PG>s5i=@va$M8I*;k0UPSUE12C${-Bt1}K*MGK{u5i$_A5nulU2^}22HzHl! z80IdSTXv|mM0mOl!Pxs`P&6TZNDl<^>X||8*W_8Fno%lB5cjAKwnHVR98llv0<;~%Q)Q6Q@8yx?B*}ng=bUZW~4`PH= zQRp6_ZtXtIortl1>ARK~HJ@bg`P%%&8!cuoN4 z>v#Gr)y%p^J}S1<9*KFClDt~8YVx9uA(uq|Cyw_^y{E}mG}E6DQQv4W#^Gfp>F8c! zw+v?jNlpf3?qUj^p~55`|JQNEN6TU1ILeIMA;g%H#vt`sVUo*^Ns<1L@swX%F-+4;Aj-$(%>RujvXo$p0?_^Yl|Ww!AonK< zcb%mcb9mYpx8fVt>&m)0A;Kg-;Knn{=~}se!+{L{wvR6#!mJ3~HfgcNRjue3;f;?ZTF)=!dwNA=&I6UdFGm5REf&{8q#cO9`X;nubX`cM7&GfrCw4m^2b>poA}V2= z=~X1XN3FaiK;JHye5SqcY>84%Qj~8}0)P{P(zD)urm=88Br3-}bNVnblV0x4BJJ$N zWFDOP9DNW=Xuq2}@0rHlqF}M|As4lq%eto2Z+cSPZp56fwZk^(qE}NOL?Phxy!oZ< zwa6Q<`*|dTA9%S`V-oQ#((`rY&M?dLsB4FZhE_)@PB;~H);lE;Q}qezdE8Ay2E2R< zpf3~tBG2wByl67RU;%G;Vpq(BstY6lJsEPO(NHZamf;yTK}U&jFO4){P`m zA+o$T?jP~On^N);w+Z{74d@u3*6T$lYTNTk&&O7a9+E~X0Uw_fy~oG;Yjr$DHU8KF zmsdZ;Uo#^Vf>^#Iq2VCiw9xTc;NN8k*5jmjGqZQzG16;=7kZb4S%q0&Q%iK#;EY@H zkT+c5H<#XXD~0_zg@RJ)MT0ilJK_gH)=0R?jM(t4po>xv(NQfBp0%EKkW|J~`ch)h zlBsfFeavANt*jc8O{(rqR9RX4#TC12r&a5IE~{;Df|llO3+0D9>}SeHx_KA} zrrmMtq09o(PAjUUi-T96s7eW}XGVCE*TmW403^x#6rO0I_`8|PIScMAL+U;G6RY?9 zh4PPi&ZriK@4+*!0d&y!D-1(Va{>+OY%{LLJt2xf^?-c-v|3&w1qjJAUXIS{*XU`K zTzhztgLqq|?wE&~*I|iYKd-LB}=7xa?>4MxHM(wsqE;pnjzz;}RFAZABy27<$ zwp@@dhw%_Npe};v;LVn3TAXdrjWSNta3lnh2xDfLaZGF=6m%a}ygQi3h>LQ~-*RX~ z+8JPc4^Sj|l_a(izd{DtvsY#UBzJc2J=k06Lb><6UQ{}8!Yotp^Q3@k2_((Npp4ZoKuGU3 zGGH_5L#+nCcoqEe)k`JFbsdmx{J65aYlYjtutD2-JGO`_l5;4{@mJCty(llgQn!v76fp8IXR2-VanRMcoiT)d(Ek;WNaWczP6KKz>*Z& zQ9-1LG`B>G+VCjVZ}Cu_ZHzw}+p&b!C(I8VO;yPXT8W_g4ttQl;ODmz(MLR6@|dMF zXQ&gi7D?|SmPw*7qcQGS?qh7)d7HB!qrcn25@m5TYg7uR6lv&f(|Eu$w0l z=Y&AWYOjtXg)gHTF=7sUE1L6%if;rH>#-#tXPJgs`~CyxsXv~9D!whNwBz&CT?y_{IKrxoUEFXW6;Od3T~ zyT;Mv-2JjD@bHKdrF!Q}5QTeaq!KvhksM2?+UPqg_E}sB?6Jh?8qO`Op&<%6t_Tf9 z$xzD$TQ53%D- zj)x0;Qpc%LK_2;CO?B_h610R#(p>F>9R>M^5`XWb*9;1CFH8K$f+h{e{?I`3;-?x( zHQ$*_4)Q_4%b-A)6PO7V5Apr66UtyrbcRj@Xi~b+lLD_w zEXI&CPU6^SU)axru3+7(kO~5B&s$vfvql%)ubDsChcZSzs7fmKGR@uoL@=|l*n>nI ze6OG~*%1p=()P3wQz(U9+Xs+W{;Mfz;`FGr!9lTjm01@ zUuNc59odLx9A^ENBc>E;x{5Z%lM81qYEzhM7{VtWmyXGCuI-W0mU!}gZdkR1y`bZ1 z;{YAEw-c%V+VU3 z;^XS=NnVtyYD#+Tt&)yLG34Ie0@{+Nqy#rTUCQ_-w5dSG=c@op4Dn$VF zM;M1^#PLiK)}_iP)T7EuY`yyuZciwPaYF5ZwR#F_=0&U z0ZkU#xLo<0TNijA?A8PP&u zqmf1DQ)WG>+3OFC8C2nVl08cdV@%z~BS`bsnGZSL=MRkAj&L>I7>)C1)Z$B1?OP)+ z{sIf?oG(|8pzpICGdxf_wDq6uNcPV?p}ILUHdh_O9Tj1F2Ju}AdVvfy%GPKrX5gXO z&&95a=bX9^GC};X9KpLfsWy#%S4zHbo{DMIkEJ(FONwpZ3bwq@RB& zLZ!bF+d!ICgY6hnE3t{HC1v0^H=U+@?DMVqy0yE}z_)Z6Pei&roV+l_oqGDAm-elF zu|j%;gT#N{6Ekz^$J`MC&%Xhx`|26W^}SWX zJ`uIPGG0PLw?0@1dqf=1Rf$PD{ta5e4U8!b9m^zx?gSf7_`qzn zLY-|BbHrqzRTC=*dSDf>5sKN6#Cu#bMBk8c(`Qu)I7vH%Ia`WZAh!OA3wh+C|1^j& zacsw5zTOx`@4|cq(8C#W!EXmrH0jM4$g{HOpT<-{ACtJi{i<^(322lE399tF@ycDA5_ED70cE33qfnDYOdugzO|DG^T&|V!!@s zz`%V$S9yDBe~NlZs;HK3qzPW%+u{>~|swGom zq9A`bDP9^{lJ0yT7c?ZpocM!Y1MJV973~b&X#UQt4>?XYa^oiX-ETSm`iI}o7T6ir zFra8Ju7@cp%7*%@=lx)hxFa;__@gOQ2q&ODCF!*A8(-?s?OL!$HZJ-v6yj~$B)4Rc zayDDMViGY^8k6SL4zSy^|DZs*%7psHmRM=a9Q);otTAZbuan>+NSj5@3%*aHZDrqdX55riaY1jdOg%Bh0MuX`eTNwmQH!S(RSPkF_5)n zktVjpSnOqe_?-EJ zjSBk`3GG>FwVL6M#Jl33vDE9@ow!uzU9Kx6E^|bsOInj+E9cNyr1qv_)PNS+ zhZ0>(yB9o|PfAtu-m6A)jL7B*>MR1@Bq|sEKCu9LYvDTk?7eMU=-{!k1%C7J4jf^toxmjqb>hNjvGa# zF&y1JDTyc(WoEom9Sx0>(2_0=u^5JKx{%6TXQXf0$z?4EjGP$mX87@o0<(~Adh1ao zQMWwbQK5vxYQC!r>|LSCt$pQ7ULw*Ke~4-qo?YMU1M|NqDBoxVLEPyrW>Z1o2xaYK z5g89=R>ZUhlJ;wi&y?GVK`B4IC;{+5tZqc90xsh(O2MqyB`-SY*?aTmg2TsA-NXEI z$F7zS1H@Su##(mctv51#4=GpUkS(Manr_sx0)yB@ugv)8>8VYO)q zaODk1{R50@ZfEdtAWyXNyLmeObKNGc_&)L?{+p8=PCX9&hRB--yyA?sf$IRS(;N&e zf+Ce7kh)E=QK5(QH0Hf-xP-(a{(@}<=%XILrr`S9H11Q$laB9PvkSC7sz|hxhgT!_5rUqKr>V~1a5`zFwvN}11glIF`OlFgPDQ_hg`EqiXQ(7)1z1@>emmNK$; z#7L|6$ANK#Rg@=CqgilDfvC|t?jm=hMo1U(+XUyb0An>=L~e|pm^FL{f0(N7(Z7=ngns2k zjNgbx`h7ij(mdv%lmQi|L&~6?E8Etms<5)0A!~w`SK!L}^-y{}!NqkHgP%Vx-KIUm zWOpXifA)DZ1{!4rzZ1IF7<{CaMFrMTrOmEV+`ibjE&chG!VxQMlcf35DwLKzst&gN zeD--FdSo~h{cCW7Kj1H}OL1|^F1u)0a-*Z!xy4DzODD?I*Rj<_5FxYIPl>;dKJ}PB zPa*1Biud5Sc@bSv*#Dp?79{vNV4D}$B^87AHX!L0FzqoxTIZyz!ur96Cj0J}baY`Z zkE_wyos=g{z*%?S?;8wl>y9v^08`C-grcB#e^lRG^}{x7{kly#alOW}mkU(MXl$&j zhLUi@bXY)qDd76Ut)Vp&EDsLX3_^C>xhY)ov&9fEIzLjZ9EIO z!a&u6R@)S^EbXn*vFMxxU%-wj#ZP|N*q_OfLl5*)mbMzq&w9atKI` z8uWC=N?fRor|8lYv`hF)u&O$7S(OyHz)c4#CCyK`TXB+}S978>vG=h*+~mpa)U7R) z_9cV6UkR(|ydu!F4nf^j)bGVAjzhhrWjVURyIQx(e;#13Hg zV;n1*2DrummhM4%#D&!T4YDVus&g5hw8i(I)j&M_ex>eMauBjCs@1b!M-9CRKJXltkz!G^f$Cigx#IY zM`$g9IEP9N#^!#P>))DtM`J+Q^mGK;jMZ@ICm)(b^jvNtVO+O9kWY@k3QdfVCq!o0 zF_0f*7IV#>bQJk=_^ljiN!JxI&yx)1*EZNk)HJ=>cKUP@a_uVYpi|Zj;gQ3z7&9`x z;;e+!;F{V({Rf^8AW9}GPWo+`#hu305B-Hmk2}2-0xr~QBv9!X%b+BQVO!F$qXg

!O~rsrEHu5}BeX_8v=$$z%KSsq|^R(dcJn24X4EFC?w=pdHyF zXZYEvCQO$W#tJ1tw25OU^M|a3G->1{N`~k!s++8U=0@VE=MUU-s<{#DV^u3A@zcMq zs^4Jt>A(vY;u64=_ea1Z(AD)N71>|MO?2la%0h=${^T7xapTm+|J4@l9m;>M^VIB4ETO-d?gQ2La z@n;lKw%-tcg6lbI)!gfvu+@t6Fnd3&8izfBpAkd&iRBmIyxU~0ZgDk3?KU1B2%_Dw zDe8@c`efSVOS!Soa%?pYjPnQm#TgnIe%q*EzoG{o{)h!>sC)y$5C~-4ugp_WhZ7PE z`7_lej#&w>J@Vw1gY8$6VJL}E5fCI+*h@7k6E<(qFFtgj=1ri6-j5&1jfeN_velf+ zGnh^4mI{nj^G!7txQXD>6QBHy47mv%%?0ChV!;@vf*ym1o3;&g^@9}`u)p^6=%K0S zx+tnWxpYhPxp`LYZLkP+g+rz-HStHbuv`N&nB)bMQ<+D^(3BlTt=sS8iX@7I0K`@` zwUR>ZfCGj_%8w=XU`}+nF67}{-xXdj`eEvvfZ9eAzjl}>|F4MOVvatSQTK^P9_R=? z1VOK;U8%qJD*ZxxrH-we$#0CTgw3src)1$)1NZMm@5%HwLI-9wA}{%3*XpiiHurwB zYr=fuWBybMyXmE$yY7O1RJjtnd~`2*E_v`*Km$?i*fba!Mn&ijL8dj?2zxICiUOW! z3#2dVAMa&NHE{|v`fgsKh#&IkBQPdg8LUUQJ}O1p zZN;zkSSD3_LwSr+rqWI1w?UhnfGH4Szr_wE6+~l<7M;lvE{=e2Z;mzQNzp3}9!ep= z&liap=-E^{UrI3a1k-%o%Z_YE$xb6iI(CCc#Tm?fwxNtCE8n=8>x~MalfN& z8YE~cGb21juo~aFhzfm8hfgxI&$*JnLAEHHr9oe`LJT?b=cTm45I^q7FqGX+M)iHF zNrSBn9gUTEILHpp^6(cna(sdQSXG?kmDjJV1K(LB`>CaXfBSCIN4j@nhGs(|H6&2K zX9Pd;Y+o=UBeXc5gb@q{ejpWdFRHpB<6pISu zVHkLj-FEEKMR=Znf3Z-r&6Bu1lxhtFt2W)lOaDAe#Duvk=;*DFj;{<1AXChsFZYdHrZQsPp)g!eZKe)+?c?l}gMaJhu4{S0)hZ{o3Dvny ziThtKL}^W@?;!)xo+XC`LQW1pVd?#w0-LE}$jd>RNVmSLMGc?)l2^q11CpPlNS3_G z`m&_IjZ$1Ut23d#Ds&Siz`19FQ&fQ~a=^17>O5O^q5%3!K^n_FW4ScYzAdpYbJwT zO_0D&FMhCX^5|qUeRF zBC&0O4fIdWh%O~Wv3Nr3yas3O+EFPyTNM?be)<~Pd-+X7c+oJVHFlpdu*6S|L9{+I z$iUG$fu&BoXA-HN+~Q1(VCg)T#vyIXB+v=sA;p08hf}a3y7G&A-%NZNWTC=PK<^p} zE|M1xB(%xa7c;X#Qp-aTX_B3NqKDakr+2D^+wi7lGx~LtP@;Kl#r(IbR&dP&8pZ;` zoZ;2)70WAPvW?I=7LK!*;5DUAX8!TDKJ`xDJ8Yy{0x7#eWG%;W7?8^jY1wDyPf~`- zD%D?By))dEcEz&YL-uU+uE?W<*?ghxV8YV1ty1#vHw6u3IfHGTCt=?N8fD$A7nNXs za7`$AycR?kU0SmB_`@_cdnL^F`Q8^B%fW8fUOqE0jG&fNRrxhSc9(%CeJH1m+n z^zr7C&tw|6TL+R7=P;~bPlVF+Bz#vS2i2W6yk>ckwUuYKw%IO&5Bv@@re(GtxmKG2 z3f^Xo@b855OB!#YceYC>n)$x!3S!U@Msoe1?90e`2_lEiWW&Q zf`E+m>qog8K{jKezde{p9@jC}tiipH(jo+|x*D~6xmnZ}M zp&K&j?5o3oligWx6nE!B%}240zX;%mzn9v*@PRAY-x=%z_^l_WwU_cmc>?ob;k!8_Gl(FPJY74%;|JF$jY~l%8Gt((4`9S!W0X4XU!&}-TTy09fy=>U2 z!6|%DPgaMzFY?1`YUV-X2x*j)=#l+0W~T?cm#e65>bIPx`ud51_!S`)Q)>N=CliJY zHAul1%=V9kXXL^k?EoBj!N3n);R@e(!WDZkhnZ-oW6E5|h*AG}vlXvh&fMpC_Lz zElDUK^P*bB3rUa|E!83JRCfDQfpj6(^F|_CJ7UEJHlY%jJ}t2;-jh~FA9F%BX?uv? z7{uYQu^k}stUne>3Rh&mxSCX7Ic+2XIEW*E`TG&c2qjF*h8Q4f{o^r9*2Ic-aWk|z zX_-C;qM)pziV>|8&F!ZX3Ra`Z1m7M|>mp~re;Vg9ec4K&l_~xJjfo%e^`-#6Kpk3> zD5)3{Ky~HtbTs>qrO`MOcI`lIXY%VSzM$sh-7YLB-bQ5iB*^W!5U~U%YAK+3I0c~` zuVa@i_5};dRoW~I#ql<4tg{i$5L!mIifBq8!^)U&Qbiru^^16gn4W93Csy`%R!B~O zX(-y*d`mH4-|bL|ns*@}3Sd`TZF`fn8<5^&^00Pi_KuZy?CcN z`$JosRx(Uxv(RUfxoqdhtff&G;`mq#onW5O?)SbPOUi+`+5T~S8iQqb>8Q`F8Pm-A zmSes=rOZN3p6rUg`y;1r=;m@#Fpsk(JK!;MX2W4@5JKq z^@rT_L2`%Dc&F#hPy?j{Q|L`A`LVS?NZA7-`P2u2xrB&@v%rG z;y?r%s+EX1{n^UJa~tBV!6DlDi|AseH!%{5N}o7~(C*|r0 zy+0U?v{)ZqQ8(PRn^0^uWIa^DnD5I_-8pzJrMvEobr$+^#ar&MJm5Q}G-0TzmX6g| zdJ7>)5aQdak>O+ML{|e)epGQSCd=DPXjF6L!8-dH&jlY)y>#=c3kre*5`Zpjh*sF12iBXy8;3AD_< zeapD>-i#Ql!kjDjPSThoxJh!I4#5i5sb9pRujENfarb5w_ulSe;ax)4NlV)2^f44t zp0{nlS4~`g=`W;_g6_({S9KFd+n&9lQT_AuG+-Wto zaa9#)R(ghkM;5;Vr!o-eu&9`l(xgDAK)2rO{iRiuS3cXo1$1TK{T%t7gvmVOjL*5B zLeYTbogr^#Nu7GDvGIH2+j*&oS3lsf3U{vIQ*CHazvBGO>QGE7!Y5`p3qId86A!}AlP<4zVhlZ4U-eAu% z!6^aeldWH#bUFVGoWG|GBlHBL60muAZ}F+L=>@tf+eCXu2sk!@K8msMDgI(^Z{-;N zL}$Hcl>Rj2QEJ+W{y14S>w$n#{AgDY+Md6+#^*jF>#;l?6 zX*fr3XnV6p!+YB$B9X`!*HT*!*6+j;UVG+Vux9*m{I%bbM#Pb9$jqEF@0*T9h+;`d zN-sh;+|Q)w_!6|81g2G2w;mjB%eq!g2fdl1LOsfj#uhk{qXRVF$?}b&R$jcvdXp7b zjZ^fA>;X3}3v6;CmAxH`Xhg4;~g5yD&M5Z(yYC0`L1n zF6NS4um60q8TYf}epdb>djQWizx(ks*~216-(&kK2d(|_r=*A7b<(&yI|MYs4rS4U zn-($_L1;H88o|Q;wpAgH-0Om*o$zMWbc#OO((ByE>#wr1QM$P*Pci|TAy4ps6ywm{ zU;Oyy{@2H)Um}wSOdwHP+$gAF0#=N`AK^6Cj%L9Uk!4oU4ByoQvX2hUELELiJ6llb zz3gSJ)bx9v08{rcXXMy$Nb*gr#(%moz0Gsapq-}8i2rqPapEe)iXQApidB;5XQ)_J z*_38G@Vk1KL(D&ERReNiN8pJfGA8D=d3`fE9#D9HC&f1WK&V+Jnpsl2iau&ksFf5G zD^~bs!?ILnoGS^=5N4o%Z%dOq1Ym!_L4twAAfk$%v!Lr*LA;0TB0BXZpdx$sbdLmm zYPnsmuPMAaVoC>)R|kO}WgL)k!l-EA};* zW21|yBj({RepXxv!N7?w$KEB6QQG-oN%r^+&AErbqSR7%d>Tx3mqwE4ETY7Ni-})-2>L}_8Ot_MvYuPV#d;$>!@&)J8I!va}sQDv|mzyZ1N=*GG?@U;;0g|ou zpHrj;@=T;Fe>*00xPS{BKGtY!CFZ)xj9?i%Ev;#*iEzRqk_r|%f) z6x6py8(~f8;KbHk+dF;s9}Xt_A{jr$tW+k zPKNcQiXs_?2a!#2%z|jO8$q(ljP1fnExUa9MF$y_6{TSt3Tg@vFZdQC&ua?NFXP{a zR)+cm!s=A&>2Qo_&VS_9e?9wJ)%cZ@1`A=6r;y5PoH-`jh+n+7d=;VUq)JSWaHNrn zX56x1DHVo`lyVVK4Rv280_9(%p&>_3`#%xyXA z@_xY}3;bx==`VoZah3srf3Tz4p9JO`JrEfAE{pTwu@mOQi28Nw^Rx$Xq5)^ZZ{#t< z|H6lOgd~dnp-B|V#T!ofikC57iGmAAb#%X^HrW{v*|GXp*WK)l6J}Fw(W)Au@p>h3 zUe9EpZA+C4AM5KRr`s?uj3&sFPt47hlI>G3R>l&w&saB;r6Euz@u&0UIFA(q9yIT< zvMJp|jF+&1I4Z#^7YqWWm7RSHZQ2oN2EypX!zfI8R4%Izm$PhvUv=146%Tzq+1RYg z{f6D`o9NZ;kqkp0)ql1QU5Ek*5y z>~$kSpQxw2ps|(-3uTCp&T51IWdzM@_n|fI=yJHT`l)_!^b9jvm3ycaTk;1vNhKK6@+hM%YQTfixma!^@_J7oO}u{~H}dOt$c_1Bb-D|YiMs2u%k;KQ26R8>xh z0?AS5%csvyKmI~v=i{9;tk8G*%5(iXIFxDxE#Y*Rhe2-!q8L%@=8VbYIEY!y-2KB& zGu$0P9Pxyr5bI3e*Q*R-ob)BhPM+dc+t60#x7Uj_swr=c#6@?3WVJVB*tvq0-zhiO zC(yasu?KapL|#*Qf=tQoRf@XoJ-d*A>?7YVd{Wm38JcE(S#ehFz78&34T3Qc0~B2+ z8e&0rK`4!|^1(S*?6i$OIt=&P69lg_8+0Swwe*Uj;w(fWKhQB3ew)yhZd)o^&@ts5 zcII%hLtNhSc#l^t^BLN~u7cPE^*K?Bi-@TR{KpAA$-MisE$KO$=ARfS)PCW zXa6QYJRsM>$njLiNipmX2Uj2}V)*=Dj!XP{?e1F-aECp{Wc zHMasBNQy1HkcE3r!3(^5hFV}mFg|Ae_AR(Vbf=A|?w)?w-Bj1H$WJ_ImZ)6c7Uwup zC0o2++8ScZ+g4X^(d5xp(ipVma^RNxM^;E-?WW0VjpF9|#i_A88TFVkS7 zmr`fQhw!O@Z^|6v3AuW5{%NPw>PLOgnNl3499F^*n%`+g1wM9>CzobFOPN#Rj$TZ< z__HFkMt5^pf&wkiwEa}@YBp-!-vW$%NOB~4{Wx-lA1xtc0#ofjTj$RYUp$O-H3R91 zXC`^37!doL){C}QMLQ%a$HuMlAbQTTU=SKoXD;nn6k6AVV#k?aqFkxXQLWf3N=-Ue3deiA!T@dqWqJTdY2%nQ{ zKIq2|uuosrQYR9BC^mjSw4RBQKp~jOUQCtJo+AEsgl3M;7g@TV3-5S(pU1GD1hhG# zBHjBPlFBfDq<}x2IcMUvVMwhLrFnCWRR_M+Syk7P>z~dFOQjG8mKAzuDjwP;kK+*Tb>@pJ{opo*{Haa}V4!kK9A`?ZUvH`3 z=@#Z3pPRy`TP&TmuIId;*vnDaNQC)&0=kASl`KeeRO-yv_h`ll`J{V9TF+#%u5(r^~gTU=TgG`N~s(`q7TEH;PJ*A&Lv0Rh-czE74ws za}1eK_ydZA>U+Fj_DbNNm}cI{-|v){5;T{m%|zoLjcA`;)Nnm1_7~=52Kw_r?Vg^z zGG5aO9AeNrHhHK~UepZv^T)gs4+4!+#7)zs>J=1C5}~JWqF=OqvAPM75}15N%^|7q zn5D}8dm-+)DDk(G<7ul|{PNw1`Sc*As`2^XKq8!FLC&HS8sxPClM~}n+ogIek(`b0 zzvS!EEf#aK3IXpik)!&s=qp>nr98hUw5S0F)2xXK>i%nzF!~A_ZU}-Z%?k$I4@A}* zf29cMY3+6D5B?B^{<%dBBn-)w!cGSNP3W@ap~FK(giS}5;Zt{Q@Hu@95$baMJqb{_ z8pRg%^Mrfs{#Jqm>K=es?VJD2Qdp_c1$GAOW{WbUW7OY95c{_pT}#zWx;9 z#9`|AAJ)jVx3W{Bd)ZhF-R*ldCkL?Ou;%10`b@`z(ibk#1t`Kx@hY0f0FIpq>*MP# zNXi^;4-rsG2IT{I)1(d~?%=`Yq3>%+N+r4BwC$_oI|1ji(uwuoQ4idDCR$e?A;1ha zA^Hu~9#WwZ%)HR`Urq5k%pMr} zcO$jl9*n4jYRQv?f^QcA#I|ejv+sPB%9h^bQBONtAsZ6JgS#kq3sW%zYFt_ZBmDlZ zPP;?AJS${wzzF`r%G?BywZ>kWdr{k?g4YEjlRh3{bd0=ZTD48Y*K35#3s$pGCIC^@ z$(nrX!mIKFDW_t3`zNK`)!(jU;_B9iKYG&qRi8txjz?ABH6#2YKLTI{2({yj=Fo7+ z>R-$c{f%j8^4(z&#IJtnn_!+<;>6$u(R80z6jL_^SHdBM@yI}H)vFkPShS-y*V<1z z{np<_(nYV7T2Lsjb61@3AT*=A`EvBYRu4OIv&Lgh}>H zv1T%rV&voLeJHX1x*1WeFkq{;24Z`6C>ID0174qO)!09fQYRr&pJ-t!rmce;abia3 zC3Cyz18+uW=oN$h9{`O&a=#}OgeA>i`)CGY(Q3X_wjk2H4lM&7n~$KRgySpsm;?od zgmL(Y@RAVOz}NJ_O}b|34J{l8ox`($g&MlCikHEn zie5nN$@^ZK-a~Oq^@RHT);h#@uSDap2<^Tw7yii?qTpIi2u08F#dwbD-(MWWCwSp` zKMB9T1#$KN14$%*>Fe4xdogeQWfGcR`*fH4YD_SXZTdE*eC(f4e*Gc@52Ro|Pr5tX zM)X5bM1o{^#jLoF|CFGVn?w;{>T?NvXA<(ql&+43a(GJF#<{Gd>f4t|5q4sTm8^@D3t6W9<;*%nfga^tk@Bd`bge~Q{hsqU1NnKA;8ReK zEb?sUIs4gYrG?jYU=R^(xqzbzjxu=iPD9?AC9v2z#^W0hfAnXFwCeb-BaaLj|AZoG z7K%RTixFi5MKNq;{hFGP8dDSZTI2_O@PERAEr!|a!q_13k^%GC6^Jy{ji9EI57Yl1 zl$=e@qg~)~KkTN}aCZ=%dOrf6=KFKm*L}51QEd;zVf-`++ljz?J?Um=2|Av-4GC#w zV+JzD4$f?8!RM!7M;=GpLmVF;8Px}ANloCZ&P-6!$O5)uB?XE0GiU){XUH}dqrjYk zAm8R5IFUIZrrd_hS;79?hrMAR`{TeQw!H-+JqY*$|qI}+HN*yOt@$M@4R zxtdn$lmKE+Z$x=QSkqlNeWN@7WQVCy8yOx98fi^XiW zLXWlHA;rdg5S4aSjvntxj_$1+75= zU^G+cDrlmDUpS9NmPB8?Ml_M6b-L5;I-??GT0?=-s!VNsFDsK5?p$5Rvt_V>}zQ#*x}-AvUIiu>`>d zdGP2Q4f)B3%S9zdw!@3~lgrRJqT#p85iFXIz=tdtaxZu(BwjFKuHgIQY}jw-wM_Ef z=tgu=O_F(N8{#j$fXGw}o>O^qb2aRh&kdt%b1*m`1^J)B#3BmyO=N1-DVU4ij!6X} z1fJo?%CV;NWitDS>dASv4?#+j7($rWMV_(qvKUuI!4ZdJ*CG;4q2u?Dpm8fr{b6^HEJC3CbmXh!2kMvY z4%Lg3+ulJfa?JJyOn|5OG~``MO+@Pg1I-iE7sQa;$?P6%MbY-JceQmyPyvtsbmX0v z59=CUN=sB0? znH+)h9@=61sNE`k$WTI5bz0l%JOrZ6W2C82Sa?rF@Z|aMYtv*Vhu3gG#I@Ey^7(sF zIbw0`)L0D)y%{s$QxuibBvAWwp5uV8;G0t@I4)s>WEJ)X)p0*H&)c^kx^osh3&^N1 zA>+O05W-uZN9&lo9cb0&lld=Xo%o-%p0}1H5dT~X$uF{vaxF?j7DVHm7xrc{!Ax`> znWD~g&&%0~UWe3Fj!$oU3B;)Ss<+yjqyTvN6f_TbVO#_<1-|3RJT<;5`}k84Uh7=( z?)zZ+gIrszh#^am(+v0>J)MRUh4 zZ4Vl!II7@yk)5F}!bdKL6*>UrDrHXYiqIK~-6qHL&Po_z?-=YD*CwE^qjdILP^e^( zS}5x|d53}qGQ3AuA$)l62!2NUm3&+ zbPM3~c;Lvrm)^g@FF54DR6Rr|+4hs%fd!;7MISm;B==P!p7Xx{^N}}wGQ6_DyRY9! z_-yUDLZj!6&$o06yQ3c0HBE`8&D$|ZqX(t0F+zj}K2UD;bD8(a{W3YJn zF%$(I_&!5|ke_^@5iLi~j=FaHY%WsQT> zhbXwx>mBKbdjbFE!34~wpGQ;pR0PlV!KAP;U-}aoYnpN(PMt(4YiE zP5TTUXNNZNwMQKt3JT-h)P5I;vmU_(w7TB)DJlpH;U7x$->{$c~u?B zz#OfKNr?1HJG{BpkHX0GL3mbm^l>RX%KWH5R#!!7b;j6t0}0+x;!+892|ZdX=AI3R zjhKQo95@Mn?`a4uW}W4x>fUh;Y>TW}@qpgui`rEaLvr{1Xc*A|myyPp3JxtU1-g=+ zb;4Q0w=VX)C#%t(!Z4<&dkuri( zfogG3Rs-n-Q^=gOt67`-_@dPCjx3Pw%!-rV`4m4?QohXETQM2p2TI_7$1DVkigV~t zr|XgLXB)Ig`v$9>m6jVw!bJCb8^2cGtbYb|om&PGid%(Lh!zH|xHOZL)fuJ$t7X3_ z$|_seGyBoe8q*|}-KFq5Md^s>+y&ds`H)`6>>dE4{u8}xp6V3S-UNpl_7Y2+^pn$V zJQ~K7_=~Bn6v88+p|I7#)po_7rmR(`Oj5+$oB( zQlDIVE`sM=je^XYNDe^fcc;&=euE{%&evgE{RK2s@tMOG>_G|mY9!=#$wX9J*vr2Y6J}pKdr17Tz#E&9bNCc0W>bmKx>$Gbf_!~@ST12Z#M63%=Jxh` z(bCy64i^9W!K7zb^Myn ziSAhkT~|^_JUSPxRn)>bSxl|()Hfio{*e*1kOqS)B%}cXg54mI>N%~4}?4jZsD z=i~P^nVZ=szu|{l_G2J7o}HjXpmOW>71_2s38%6Io}6~YWrHyj9E#$Z1s@6BSi&AwDBobwMk+hJ1MR6m zpYwiru>ii{M^Jp>LIiZ`opKw!!9_4gP(61Z=j6GQ{h{#2S2?p+-j3E0bN47Rr!e6xGOzPYq#k+^;pUxv zGvP4-1&6qi7ICM0;3V0YQVQw0CahQp#ZR)jIxD2Fo$dO&=SZvU3rA}uCsXQt=z5e) zFCOE?atmgl1inI!ml$}aE@@vni!7zSln#y0o+1j)%Ji|=1IOven?WT?w4uMRChgiR z(zazGXFL8gSa(^qO2g4P1>Ql`Wi%ky`T~S5qT-Cu9)<08_Xx*b1#$}Khn5Xe?UZHSY#~aenKk9|&nyXMaX(qg5COoQ(jSw0tq~DtLfX(AIQZMj3M**KxzeI1bQTV;CA6|#Z|j^ zelY?UEP#K^);pFVRGNabjN{gQ9?5cQ;2?;J_azjl5IBuHk&HJCl95$+DK%1@#7BJW zk7xpM8k=~TUnoYI4dh;v#a=?ez4IZo=A_^#fEAn!|HQVI(OC((UYv(Q3cPb$q6UuTQbaWkuz|c-NUIoc%#m^z5Ti!94g+^mIkN zb%%Ch>zv!Z+$O?)KT_4fK`xAI50)QBJHK2mGHt*OQ4!q#9Gcn3MlG+ip7+L+bTvTEUdGKW-{li>tT`h~3Q2CCsr zPmFNA2a6gc)Xo&^t>~)E_{9v^c^4w+TL!O~pHkoOB|SDh+d<7beG1~G{ODPJsLgf! z9^?EVjE_x&InaDXL&ijSw4r1s-%0_?FkC566zEDenAVJYqgA!9F^trX2E+!X;VWY9 z8WifgWi4nPhJ7%dS70PtkdVOAoIIK`r%bw9Q)@Ng9PlBUoB?mn(GRT+?^P(ef`rli zm}J#6+q%ly*tQd~rj9Yr+&x?v6TvYpt-*%^>~%#W4aMCPGhuIjUox zp3c%+m@$XW**Tfx$nQCqA9u!Jy?7hivUN|4I%pk!*uwHXTm2-N&+JDyQ+65 z>mp% zqP^ysM&i}N*ia_gP6rm5t~u<)HW}W~S1|d?D^Pel>HeR1E4`yS{o&Bj$qN5$2V#F& zi%9d{Axz%Epa$_N)U>5NiQ$Nma`HMd!KoQJ&*YZ{xAhG&1!G4FJ}qjV z%I|u74r+(x?D>&GF$^&+Sq0q%2dyll)eB#n4deBL#Mq`k@I^U?deW6vk&A7ZU-rP> z#P=`rUbF5|pnNKV_*o~SAa6qY_>Pf>2M&MeZ}mO`oA*|89L41NT6#xBJ+tAT5-!ydD!8>>{qm;3m9G;w9+sNP& z$kjf7i zQm#^wK0d) z&a4d{4GKE>>jA_!uN0}hNiZgY<6S77T@Ej`-d@8zvjrKL)82+;{hmR_q4z`{%)t9m zblT-8{L~2u=wKhYa)z^y8mSHbF@?_Gzl6HV{fLjM&=9Ugo*9I3HM>2tpeij|`v81= z`)7*v=0@b7ObuKSZ(^)Hv6aGQO%kR;TKSAowI1Qa8wTksA1zeD(OQi*GIpQ5oeu2$ z6jF023^dLfk5;xz0Rp=2i#Fx1yp{}D!d8q#ZW!IWG=|9gj)Q07c_<(8xzz~cB37}d z>+~hg3#C`r{a)+OwjN9&(Hw#?B>Jo7+~W`EH`LZ?m1ys{o5H9X3GI;9+|F2cV!At6 zfwAWwJ?`%~5%=Pn*${rw#Gz9J3(4xI06IF}xH z7%cP z%;u!v7&-?HBpSjw?z^RSEaufy!-06 zTBviwB$yXoisGJ;PQ!}#q99ZXOTw_nDU<1aH~MV_JM>1s5}y0FB6?`U(6cSevdGNi z04;P&`-3LI*PMVOMIzJR9$G=$*iUg*R2FM5wBp24@RUzZZwek;kSUrcBXs;+_!VWS z2s~EUd7gB#mgQm!UIim$1JalMPz4&RCympy#rwjj3yvA^`7S|`h+Pp?Lm`p?2XWK- zA!@pd5G;N_$}XObyq`NTe?*GT`2L5pZ^T?4YlCsichSE2ZLo*rA{ZqqsGE2THVr}WVqNe8_x{tpP(qeQ4iCc3cSAaP*CcH zq0>S$bF-4nmUVO_wA7cq2o8hvn3yn?!sp11F##LUUUwM2^YZh zEP#LRX$XCI34;F?fT;tRN=V%!(I?Lyhwyh-p<~rH#K+8~!%0z529JE=65QRPsICnr zlGPSc3rOKw6z}P#65*5S7%!!eO49t+MyP5sTi3HTK{V_^d$_lMh#*LA=6rr`Zk$@RW=2Fs|s-mt_GG2 zT{MyTD%@GZM0My{FCpZ>3RECC>O84C-h+aokE8T`oGVK3Nz206&Mv#vgi*#e$VJtg zLZx^X+oF6HS`XF6H1&JbA`JFV;)WL&EjXjJikkfVz^VH3)E1U$uECS1!atOKT|>eJ2>RwDcqOa*US7&|*+3=Y zLAHf$Oe;!qTlG`~(*4e|m5ox0d0BzlFSM;4&SQ_FO`pB#FzSNC5AQTe@61H&jexR& z2sP1wWMlmRv|Ua(&j&GK@jFrW{~UN9OcMc;c8(fuEjLN3$hH<{_WLhY4Z(3U zY&i2L!tz%mE(=zDm03g4nwqZbS=qkkfrR)1N{zCDF-ROa8@|w)D7=zZkIvSSRj&1z zS6QbO6nIK6qzuxsLeJwRp zLLAN1jOCASCwIom^(rCM{2Z(Sc9GUFBS(_Y3r==O~)qlZ(_D9gNg7*|bmF;?tPU=}^ z!Twq?oQi4i4;wSQ5``1W1&-YS1dh1iUq;|8Bq$5YJP!5RkL}-0aV6dHNHkGgIe?^8~L~KJsNuomL9Za0!q3{GxP@sIJR2YN)I&QMMF?IxVsN72})Ca>K2A3@1UU&o{$l*788zxmI+ zt;NLQ+|1VXTS)>X{5i2aBbL2)I8lux8B#h;$Ux{_Nt4#h!Q^xs`5hfA(ez*n zju?sJTjtrR!M$FD;7nhQ*BXCE9D}@6@JXYki}83X%-; zOj8ubwuguDkSz*SFAq z^24pLUVI!@=b_%)_@=<93Xb{k(6miQunchlOflh!*u*~g|3r9$ry~D?1qgnVTK2~{ zdK%b)GLC^_7n$n+YeeFCZjjSP~`g-(@2Vl7G+Oz*JsLNLK9#iOuQ?^x`IS0aw#M}=57W-eH{133ps*$>t400te z2jYg9Xv6-%*~q_mDT1QIL4!mUoCM!2Rz+4{hMu)Z-H?Q}h2x@7>fYv;Cd-TY$PZTz z$=H7**tZg_5~QL9Sy-oB3}4X-;ea!>E11sNw*=!@FBY5>}ZG@kwwd zUxmpd%Ac-B=>;Y5ewA-8U=i)>_o*N`ukwvtwpX(#)lhHss3aX|C%lv~J)?F~ka%v{ ziumD;O2Y6a#;6L8WeCmYfDAQ1m9+S94WiVZ;=MAixiCFf00o>(GBFGIV}1Re7@Z8o*)Y+d0~5~+_YMsV>}C>^vmeFA(5Dkzx)#4_-3TsBy+6=fxBqc^m1toN=#IMxJZ z3K<@Bt!JbIB{UDz&f`q@3oLkLg=qhheoM4<8t>;@2uf=8Hx7mTlXnJTUwkq0OA69U zMZ=4w2$g;w6(2nTft&c{+N+_y%=}Ib1)TQrT*vnk!o7`E2ZhEa(ts2%1(T>vIsomK zCipfzfT}mGizTg+}_aqQ} z`gb@mto@s-7&XCB2+QMzq1gZ44h9+sEKY#!Mab)Qfbw8k9-8tmA@53FDiR{&Qx*|# zVfhsY{st01r^gL!8hRbj!M`{NU5;U?tiva;&7PK$mKGAM%b6*pl>e-WMM6UN7nv|P4(2Y_Mk!j3(r;-C z`IA?n=+d*0m#@gUuKR<7ABK4x0&}lM;fLnHry~+%f%f*Dx+gm6i&iQ*hSePtMH0HeEm=ynR=ACh4XB+5!1sda#ll)?MfZ(#n!lTnRMshA3?He(;zb~^oJ@WXlNTcpCUac$yASvBRPu` zLQz#|!ND=mK8+<5Dypv{tB&T*Q5f7M74UrZauk2~gD9Us9x`A-o58nGHsLyye2%~W zDPCqmZU+kXqandJk>8UETiG@wp#Sf;zuZ?{o4#iZj<3s<&=TEWG`3dram0jmhIA7prN{ijw zhMxW)MzVpO_U+lgk1j^#-e*Vf5UJq+D_m~Dli9-%BV*|_VQWGwEk!n~q#Cz~h2#eI zo5rs_2=n0c7@K@s0|6OVKAFvltiLv(4TRP^$dz}kM@PS7dkAQ6Gix8CX7Hwz#M$Aguz80c2KE1hi6x;ej8&bm(hT9WWi0gdw zeSDiy=9aL1C-Pn`i(J8^Ax8r9RKBG^aTJM^jdd=i?o=P}l?CvA{U1;^e>w8Bu8=jZ zL2=O+QSm+pez_KPu0~&*J+pzfjd9L6S`gQKs^wg|vlE?9u0eBK%P_7TS*~C2dy;_oSaTWJ)-Rv5_SQslCzO_-lZt`>|zAJRSM5XIC9biwi+;R&4c~zWvKtf zHE7xGLEhpRNgZHXAan~&SrNhm)8q^6eh|>Db9YdV5N;k2#6N6sZnjspqYcFkXj`K z?3H=3VXH#4HYgPO9p7J~s&g$m|48jqhx-hKDQga#eSb%#v( z4N+6l%-8T$!bAeHw{h9ThU|R;?IWV(R3jm)VlRIqqj49J&K9z=5~y{&e?+LJ>#hZS z_Pvpcp~s&sfae?ULh0MDNAYoA#JoU7+IZ_7li&@V!@fNMfzMHS&~9+;(dfQm za-dKfWzEUOCE+70@3t_aw;e=h<47O%oNE|0!BLggR+RyB&;uv5)8vg8A~gM7nDmKn zVDhh)A^+D7%+GVw7PD;UjJ&ZBi4Sc>_<@g2c?bR=bz?xD8gevS_=`j z;jBm@_WhM;|I23)Z#p+LL3VednH)gdJQz^~Hb zNds};i3U$jBJt&kNX)ttrAJ-&dk2ceuzE(n(b{khag5}1@5}AFF$TLie*{j-6sVlg zs<2k^hcm*nlD^9U^uq|8kAm~BLhs(eJH-d<+d-J$A`!lW-$`xFd7AhCEd=i;=ArWYZ$)#< z7KG1;!TFakeBVsM)Ixb?QT}xT%M#iN`u%n!{&6eXR@{q@j>mI6H&b`y!&=D6D~2X* zvw=cZ8E#A2fNY6f;h$bUtTtLUb;m}86ZfF$RsO_1{1IuT1A%Dw3O}3=zXkcTCLG0w--Lv;=AP+9w9!Oa z02Bz)o8VByRplyl)@(;~AnvrRQHglu8MME^FPA_TZK!^8Nq5s&9a$ZjeIB}h0_!SM zE`4$$%Rr#Nm*BZ7h2*E%Z-00z3cmkgl)dlmDEa97Q2LoKq2eq5fyp;5L+~d4{s;KH zESzjyvPT6wRx9+f)}N*#ddsgVH2D6gH1cM|s0fb52o#)-kQT;!jrbS<#iT@^r&i{-f_GdD*$PP?>_Z_JC)^#ZPo&iIIBlnnG0X-+w(ID;VIUDvj;%NQp z%cwte*DxMYJ6fnlA|tHT{{8F|=~KU7drX8{8DK*NE=eSb|RY7ffDgz1Ab_$NwespHtM)q;TnP|Jqf}i(HyNt{3X84q!}R$ zg+Z%N(>u#`haIzkv?T9?c3o$)NZu2oW3^ZPFo#Obhmx>=Iu+J`E=BN56XE$XAJL{? zg_#f4!_gDk!2GNa;a{&n{l;1(#vMNxE{uxcs6*1?4=EaCpe~}`p!n%$_+6h1B6%VC z+U+)yigM6`_wBs@8lS#z?Z$FwJ{1G~vo*Ni5$O+7#2FnSh zi6h}5h7>c9qM4mOoh@4}On<+Z|D4PY@C0B~@67T28;cQ~u?(SeS@oVNRFn&;oJFp? z-rBErZA`(azh!{#hx5^1*@DEcNG5%yU+)j)6dv!LiQv_95bAaJekJT;2bP#+_q_$$ zU{_D($=@@2I~YxEh{j>A{uNqBWMRBJC_t6ceGf~k#h9wT-@`iO~`qEu`#a z?B#)kMD_*|na)R8$?uvMhUaT0O8&)*q8mN%eS!n4O*;}6>Eqr80Zp_9n)dg^5c#(! z(ecpJh_6&cPah4To?n@Mrj!v?>id>7kma& z<#Kuh$dqMeENA_@TNOG;X)7%qxv;uNT4kVd+USS3qZFPIAG0bXbl{bQM<#=?_6W_U zFx5S+DG93c$)v*~7Dei1p4HrbktGwfFwi-twr9$4Ln(TmPr~@tT120H1o2K*a-j8l zQ(;sXzzrx{>Vq+qh=vSe94%>G7qPsXMPaue8!zlEbFh9$N^_m8oZRyVn-D1FQ_$jPGSyV5gz2R}RJkH-1101M^PeJZ1Ghu(D z7|x_AJx&h%Bq}OcX}Nj23w)i&TFqBQEA{5$QY7H!!)S~IMsdel*+->K$w>dqTf6z1`JSU{nN0dsoIznXF<~LxKGAO8tEXix#_8fB96OB}INGN{y`&byr!i|AqHN zkl8@mqRi`yMns^{t_$io#J_3=>YB7eT)TO9#(LE6#>N zTAV%VYazZ5$#8RyMwDHKkiQiE_wlXPHnO#-GGJdAyYdm)cRZpQSIdCVh=jcp(M?`> zZsMhw>-Hf2p85-~|>jea&}T9O+XhUuIpk)*)Jy)p0r%HCZIDr&;H{GexFxG=17Y#3 zzvpea{>Fk?tG~2A zkw*74HRvCa0RN3l@qYeD@f1w>pA^j7_?cq(^<005P++`}Li~s8(e~5ZQN4aP!r30w zlk+$p{(N?T7^wQ47KdSyi6jpoDT_>g=WKlOVn`}2)Z}TE1>%&{BhG{dgFJXo^uoG| zZ__!o(l@h5s{!Z078nhG=wfbzLM7s{FXO;#N!YiNQTDl4q#sx&j2k#HZ@3Dj$DKk8 z>O2(WPliwP=M7O)9E6w+Lzb1=+spcfQyE5lR|L^Px!wkY{fNe@k<|QC7TgSdeVBD^ z=RB1ak+~-i#D`cU^rXOure?9-SDPrDmxttY(-8UAOvL`3O}?3*N!iJUUNg|fLn%iC z`J3*LrEzZ(oxgY(t!tXoi9%guFyexPy`7&AuZVj%EDlXV5l}kcQ~>_>l%eep9yn8Y z{V58MZx}F@piDxeKaEqG!#Y;yU#Ly|<3_aoc{Mt!cD~6Dm7flONeMg|g4aoA_FlBa zSD{Ut;4(hv{-FLi#FE|_&CWkO6@@uDfu_J)S^=M2YTC~*(6ux%ttjc|)dgsiraWY9 zLFBeDoM-q}3{2mjHTbZsymv(re&4C^%~=NjbV`MuCm2%DrFXz-p})7e#c?v~$&vSM z9_8qtYS=HuVCclebc7WvCaXhfUwYO6%4q13(grRY=2&_nzZ@&??<@?$>w8ijW@R&`J40H^;tgxG&QkIv1nD!#zQ8!%9< zY`}=XcFsrP2RM-0tvyipK~G3yp(bZM%vVxG>aFbve3lIDqr4Uo>LjlIBDX}i2PtG8 zaNxUX4(ta#sHyvJq*9vQZ#INr7A`?>Df{G9UPk%)l7ZB!HHhLgh zx6WonBgODo)8SKKftdb4XwPBjOZ_c$f1iOO-{zCyzqJ+Syn1-G@P8HO{JU7@ z^Rw5VXZv2@%dNbzf@LF%(w->ll7iQ{h)*o%Gd=gc^at$*f5->VjcsVZ_fa%8zY2Sx z7UMC25w|!lM1B#uwFthaDLqisQ}dv}ke}3fC(E}<96E&MEu2BwZtmL=NAl)fXuauo zsCn+)INbh^T@&z4iK?zcc63y%7^%)BshxxTL^b$799?%G6ImcikKKJiQh#@n`j>^1 z%J4s?^J{Vp)8U;+!SQZZOafAETEY5icXGCxqSB~8TYz?LhtITqsBo$fc|L{6-TcCA z*OR(K{XBzx{*NZif8>SEM(;je`dq@iFGWeZ(3V#a8+9vMVX9T>qjqC=^D+~jE8!u2 zqk8uTeXe#Eu?w%^99J5lt9ko4e$f4IIkpa!z%<<|UPEg=m$B&iFHy)SsxHG9jt0@m zb_e#&afE;LDk@+7HdNJtCq z&djt|LmSw-ZQx2{8Skf$#Uyi`IJHN#&sc+XGpdi=u@33#rUN;kfHbZ@-|>_*fMA z-#iUXtN)C)==OmV@wi1b;>rmmw@no_D)VVnI*Skt_+iQ~+?}aZvQwlT_6%drOjw7L zt8nrl&X5>MdeG-%7ibtKw0PH!Y8>Q>jbae6<0|*PcUi*f+^Nh(uKio|{>p z?i=FA7O)7B`<(V#?pFFAEjbkIHz#%sQBS8Hk_Z?u(iMA|5$V&+fdphYhoL%px=05 zd}$i$|L2#eI&>!vC!ZbTz8X&$QNdxt@Ge9^dpLScqcBVmAu8-~4T+NkYJSiU@0s=J z{Krjb{^K9fzWWYD!{Kp~&2~6JArY7kpVCr@fy&iaFd2TUD!r#qzTwxqL_1?WWV%WL zp)kqbtV5mb);R^CVRPjS787BaZ%4tbGm-Z}60lrU^7C(C8^|XOZIWBS>ufAsY2zC` za2`*hW5iN&>_j+u7|B0dFdyWl7H>zg504D0vD!pIPPklNMEmyV(f%`5?dQByl-|)S zFKq_Yn$G7qme;dfMB4i(|NcVW8%p1CjExmR#D2US?f>^08lL|=k}WN+z!)$_RB%j% z6-jm_nj5N{DgzC$G&XJSQ)u2=Y7Y09i2u|^_`8K@xhaUcN56*s4L?SEQu&5%K8A^+ zs>{OC+Jq)s0X4V6DKL#HB%`Tx(!2C&Y=X>)N(y>0HKDi3>0@6Pco8j{2JeW{O@Hvw z=v;jZe-#ami`siRQT`SFyH&LtdjSsT4U{UK(WX&*btyv2w5%Ksf%W{$_u z+Hf}-DL9-bS&3l@`RxPB5U?SIME&j9mlL#KgG8zhZM)us#$VV-eV4bkvtmcHyrkS{ zY%iwJxQ69)jsW`P%xql;4Fm7 zC^4iB4rHMFgEW<$CcMAML(%8_@V!5Zs`po;{<~YyeE;v!vHf$1b;ey{NTV9@P6`WY zS<3>6Wt@b^O@V))dlH5X??uVU4m`?)tc`CcV| zL^mtRthA>>>9(cJ>}PWye;(1j+eRr}J}tob_fhvM$K~g&w-)k8;&&VP-7OE`U}Q%+ zd2Vh&b9EgWZ#U8U?;a%ojTL;Aw?&J?wZ5e95e+}e@4vAX;jhx#`_0eMzWx^2`W=@? z3htOF;oe0 zt!r$lLt=jf&cxa9pT?fkUVtRaW)`gzXp@za=JghlM4o5tO~G0B8p5OQKYt&}=FURk zUs*q$$D&B1?KaGxkgzED99bY~VZzcK(z4UT9ktFse?$~em`2O5~EB% zA$WEc!88KtbRkC1^EHNwz3h`ew!_%91)amijE5ELIbLl@RC|!v!G3tjg160pNo6Fx z%Uk0*(EiW>D%s;Jr1ATx+}xB8^M7qry|N0?`o|E9*QNC)7sG`S6C6|F^IwY+EpRD| zZEuI>3<{k5`d?vq3k%^XKMVP_ZAf)=P>{GTs=r4GJQEfmpgk{h*>Pg9d%{R<+Ksqp zDMH$9Kb!ZpTE2x^JGEg$`!=*&w>QC|UA?g&tS45WUC}M0f<^Fo-ie}<=OUmzJXf(O z*rI_<;!mW7m8`dDOlOPtJjh7&p!6!Q@VP?%odl>{b-O4ye{nxrSB=GCJUbCh79)9Z zDol?Fk9JdQO=dV0D_K@sTaocs^g1C{Sl^+);s! zJN}4{&QX^dN3avg_B(-0C9R9cwfICene^B4Bh(;VNCIVX0Qu@;W~6GWWn(cEGq zx~U4OHD@6FLMQSbu#noHg0Gc|!6tT0C51@^EfYRxz3NBs0hZejqvmD<&3AgxxpEz% z)l`T&9z!ZQ+E(PTh7l7Sa#bxw-n)V@6=N^KG1N)X6Z$?)wwY8%PMQR7!E|^dRFmru zATi>Lo#O@6tfLp8P+^Qq*kMXD(iVc}(I?Sbbvp8|qF_Wx159mc_8c=vb0>1Y~37eEC(z7r5U`3&TLnwQ!=ok`}`#(!?%YX|G{MOI)QuY1$j zYk2=@zMjn2%u%9Sf{5R=5v}`P9iv^;D5ChuhKq!W!h=>qU6=WOTd~MbR%hkoV0)u?p|C&km6RXxLb?6dvGb%;#S}WT3m`d6pCA+xO+3o_DR~DQ>tAgqP9sz;x>L{K&PkXizYo0Fw7p~0&1BeRHaqT) z0=wRj7R&la6|&1&+sRwxBR!&PH%WTRQ0lSV`qfNhjNG%Q|2`=3i^e>lS=6Pr6_mq@ z>~o@?lwTEXdB5X_?j<#@$p*=&u$5XlBZGWsr8l}36{n(;Gj-xNKK(uKibsFi)R8rm zV=)LA0r>4tDap25?>OT^RKw^P-duQw%G_{>Q%j5-xsPOO#vA1N>PYOek2F+y1bVzmZ3$ z^vuXEIQ?d6DQ!J~zHz_WQDFb_)Ln!4?&8dK@LoVVgVt8Gwhq>X=Ty=A``Q@P3i=;U z93&fjxCO6vrjuI1{<*xND7+*zpgRrM6Xe+@Z{^IVZ6Yom6R(T%H`_Ab<*p|;_EM)u z>FL%7hWLn^a7e>NbA(R0@$&4y5{6#gi_BQs@OTh2GKgMTK1fH#d4No&#w`;ne~~?z z;)}@>nrk+1=E@*Rze)m55;i}|Ko1QiT9jx*atdrQ*!$J7w}{XbK{W?g7W09d!Ms13 z>uRi3S6wLZ{ZpN`PRcv8m}kicm+f+F3=J&%!#M`6X_fy(nr1Nl_9FxFJ$mhSg$f7J z30mIx>SM?Rba};wm{31w>?n_9+Vy+h1#UhuMGcdhm!keU$s0g|d?sXaBGc*P|5+n{ z_VxVZ+BaSZO^%FtWOD7}Uq~>IA_bxr+ip7c^sn3@6!EPW=efYQF!bg*Jv9%OxAo;U zXRo*&nV)%83Z-+VuLX8+RMxO$f@~6(s+AhC(EEr3e;m#R=O6FeIeCF z3&jqi<-Uh0{ztA^-%`K&2w<&%>sHt$OKKxWu@%Gl?`WHZ;;u|}8`>mt} z@|YxIC_>yiaqnOLz+5qeC5Pcsx(c~_vSb&4ZFM2tb zDpT06yHorY$#Kh@hOXVyCfWgH0&d9(ZVLZlwPGxk-Sg}qRB~zRGGN9>D;+2h&M%j0lix!jEQ?g=l8R73g&gO7>!M}4u|8^qh$7bF}+<8z* zSjJAtTE&uw57E%khW}j(Q2NIGWeRu>xr$zc3csa|#FR2kp?<*oI}0{BGC(#yzgGNBw%`Z>{2!n}Op zxEm05o^TJe7>k11mEKpoR?IehFnQA$g!Y6gxFyww?QYKz+tZw#y7u{h>A@#T1RLpI z94sio+Jnrs8t>UiR4EdQEo%^n7B1zwZI6&N@V8 zU6?7f2w8cD;5f3<`fl2pZ0b}OvBa{D_){wgKSKl~-QvU$Mpvfmo(F;8FJ`vD%Ag0< ztbs-$Kt&KpGAShI(r0;0L{~_~SFiV^l(bU8HD81XR6kK+y|>`1V7@%R*4FaCi{HstE}tAITUKoPMoD#|^8zHvm%{H$$?Cn< zSl4+I9n!(-NyBDis|>Hi<)qD#2?A~{IM0ZEZ$f4!=s>GSQ_*>~gxl5W1^}ZJ8N3VJ z30^I+>LbyDRG4L$@x!Tz3rtUjjRH**WpFw+weSi!(+rFO7bAXE7-_`gG5Ze z#li=9yW#HVE`S<#Sb2Kg2dCjQpRe3k77E!#VT+N$guKn?5bnjeRX*TeAonmwbxjTS z{gTM%Bk7O5Ge+dbWwaO&UGa0hM^+vckpFNHz+N-r_;S1=T^)@D<}xw)KcaVA6i;zl!E5q>*LDEQU4Hz6g0GNM>QSJQ}1W|!8#V$#M`Rx5Yc##A5eVtc?Q zsxHg;xuL3a{958OIn}QBPHMX{th!-&8R*wc*u!F-KQdT6qL1!wPTl0dR=6Xl2KkkN z+m8;EOO{m&%8;HUhc)S4U-MX^<<=P5sDEli;RC+K?n@qkTq(XE#YP@}!dG}*@rw=< zrcA#4U<#i;5EpoTFS;&6*0l%}ZH>y$YrCE=ce0b=;Wvc^I+8+pSqUghKjYewiZY;# zI!SdXZ3&HUbuNq{BI8(4e%tJ6WT+y>V~{djJrUI&6QS_6Ht2NLrz545LZ=1Ce5%SO zD&2%fDe6}p_*30)cG1^6iWRzGvYD3K?*YlqPgFjSVr(^*75U?;?S>1!EY#na!ivXW z7v@QmKQSHFQe$O*MZ8^-E3w75YR09wvpHc<;zvj<0N|3W^lt3Up!^iRbfsZDiP15V z{%Uc~s5>?60>P}*jlDjPtP&=d-uR`NZ&Xt`DYEa_C0D$;Ipud;8-5!*kjiJnromia zK5L+O`CJKN5_4CMCpG8V3ML4d^Yg7ye?sCjJoQd}n$(8?g9-Dw|COeOxi@XbwsvFe z=h3TubjggaVMN7;LVBsIji$AzPueZ2CY4*Q4dtd~(oE@9cc z3Wq^g#O;hRRNADCmbHSL4(Se>;W;Y~vJ+Y>a2F@<1GQ+^7a_Px#XurpOK6FHk7?ME z>hl zL*U0BESja_S`2ZC(2vt(G-cn#aW?Q7 z50}Zp{ClI=H-h#jEHl$$Lgd-i_Lu84v3d=qQC?>6VGCZ!RXf@lqEJ|yl@4ey*B(TA z%~<(6%($lrrpzjAqOi}|s>c$cbY3NizCUmZsP#THKCgWsk!(e9O~#i#r=k`v653Ra zk}@X_w_zOnp8fIr8*{&t36=JgFlJ2mI?~**$-%7H%71_b= zuOy(w6#>2zEU`wtW%%L|9g~nYSciqjnXe+HB}(3>`8m+x(sNoZD%3BOW;kA^xW$oI z9M2?dH*2hJv89)I&wgc)<-}Ugg!u`n-LnbZCI)k-2JFXUu1JQ!%ELB(xr?RNe<79& z>GkJfb0K6`EaH4#cu`z&L|C}B_G~x?6}w|Zgdf>HRI68&1Zg$^7dA$W>NwT??nb8D zzM;+FO2Z54E%vW3nCF>gnV=7m8u*ff45~WkB+u(JFW)4XXqp(G!gU5+%@T(*&6OT2 z3zbE`E+^<+;W71dT8tFfKYCM)UDpx!D3&~Hl>LQ$ATN!#B>K`$F+@mVTo3vQ}s* zoG>QjH{X1~N%KA1gu%R}*|i-M@->NyMjq0M*cX=CphK;RIetId={-}x3wo2&$I-FM^U&c;b_ z@q3&USDq_IW{g4n@|37i^<73CT|lV&8(_45y!-f7PT+2Hpv>)JMZmrd%KBaiT!WP` zI4ovB1YV@`mCdN6$bI$qU8`>SG*y(w<$U`z5mN~D@Vlo|q3$W0h_f@_0ES<9YjWea z*XV@z3mQ%O(nl;eo?BM){51&a%Pf0PguOl2!KgXH=fTA>;m zY-bDKEXJSB7*)7r5xi-|G$VB5Z9ig6>2HymHMI?GgFKO&H(N6XjKxu2#OAixzXGmd zmP~nLLORACr*%Q@?pVp+j$jAWZeHijEBpjYBp;)ylfitYash{;2XP)q(r+59K22!VNV&=cXsy6f~YlZ~1 zpqEvE(J?#my6nKMJRPKq`_q)k&)U0j^fMtCae498DgBPcx9fbQ1z?{&Nnuc9Z$7S* zo`btKjH0U@t9hv?qtNj+oNRmVYIeJ0u|kN)Ba&9#0s~XJWhVS?afk4EfJf-#Bbk-! z&-`bErK~vBn?>=IlGy%B9wmkSU!A#R`8G-=><`FTa|DrQ7uVd=TWv`$E27IN zzs^v|Rqas|IE$l>MY3=!=$o9-8r70t{*k!9qS~mn63igc27|N03>Vk)R(stPr@kVyR{lYx4Aiak z{6z{=k-HY^%JcVx8)g9e+PE-{h`ET`<8+_$xGR!m&{HeLFi|_iK4BG4LTdhvZyIeW1j(AoW8r#A)pknwcO@?!Urg-x z_sLp!7s`aTq8GR-SiWAl>s^GRZ7rW$-vE@zc|33tNamrl+Dd;Q0*7b?$EvuC?J6qvLS=K;vqDPxa4&ySP|Z&G5N645^mY#JNB8 zRw(M%w*i9|lIYrz(k4&xmANW8Me1L}5AVJ7sbDTnvG3JDtiv0wP%i4S5Iz0HdoCi; zB{4Ui&A@UYI+uVOyp|UQ;(gkV>6;3P>6Rn8rormrWdYBv{vm3FV_8#mj#uhx9U4n~xj3*-V-#l#KNV(YUz16!|K)uSRPeyRvh8{yY- z8KY~h>b1JO3ZqEz#&CiJ;u3F#jOi<~dc~V*H2UI3tE-ie6SUJs`F>GjUxZn=f;{{f z@_vDH)|qP9Yffj#CKiASHdUJJZd!vX&LhvV(J_+g)wIj6?R538f0A}RIcM~J->@%n z@AWI-Ss9{^Fu^sxqQ6SO^}jaf{E`K|!p#KcH>ARZ`Hw97>;(K#>QU?&>dSG46KY{X zS0WMfHA91qf9hBq8dth(67T9Quf71_|Gmul;(V)ppw3Uyz+DrY4DI7l z2^IN(PY+B=vf7=N&LU&tNJw2KR4F7locq@8vKV(`^x*k2x8b=~j6k__6=HZjw*$Vq ztjC32#AhF?2{arplCcq8PdtF2{}?cUn`IQpe|Jaa-TRLMha~R041E&YneYgT$2j+Q zz(Yo7MhdzFgghqbrW$|2*W`SAB6`Ag7jGg6Hc!+HR`|V);9Y)U=Pl&79A*#OJsOKD z{jd9vz@$*JWDR*fJ~-UDlQ|Baj^(EziiEV$!QTi%T6Iul5Tl~TZl(<+J+(uxSGQ;E z{zeQkLh-m9d!VR!tY<9=doIDhlt`ApNycr$2#s7kjwMue{2co~tEmxI56<&|w_@S? zBSUz?l*Q`nkJEM#g9}KFynP^!h|}gWdYH{yqGoKu4~;a#F=+7COU8fEL5~ge0gbXY zUna_ZItRn=$pqjAoiJ%4R?od1&e8j7HV6yM^URzea={lz4|?eToZs}c6UjHFP9JjQ z;ul1`$zRc5n1d5~^TvviNA|WcrG>#LkWkzV+WX2;tyulr!IqjdBv1&nN}P`VXmmsl z52y&AZn)Vxbc7DbBWm5VY|xi52W>vOHPn-($k=;Y~GaY zLfTqbRTNE%G67BXYjA;^ZZ(xZeNAYoPzSV9^X)YntTp39p69w~19)Y+XKgyAqHR#i zA$i_r=E+&Cqgod#y{o@sZ)oL>pi38ruB2N+N#qCGZh4Z_()ncu0w}=zgZ!_^J#$}^ zjcF+>Q-I&zjLEnChdZeX8WbVv3u4Ah!69ar($mXCruf@4~l+V0G1j?y$dl0da(nU#3h zS!;>6UKbhjX@YNEUQ{|e2@ZMGmc+v03epcis8zgFG?bpjANu54ie5!-1v{Sa^ufNp zf7<-~q^8}9@<(rp)sWTc$uTA<^}_d3BxFy)?M|w4t(9mC=1}HuK6q=6pYke+wQ#V- zi^0$|fp4wI3PvT{7Nn&ZUw)s3>s*RC6@v^AUWU3>4NRh`P#h?Ppi9ga#|dwHdm}6# zwOj^_D6qA`bV$~e3yPYEBE8?gN2;2lfjpXrCQtIKn%ps8wW7e(zeGN@mt*A1-@8$E zs5}zeINmG@-zSSNe`yc~ZeF90O4>K_X2337LcaeC--=*@L~N+a*>&#rhPX&rIiv6` z%0%DB$U|2zwT-o2?QeB+VrGzb@28a7=3{17qK@jRAo<2V?}$%4C@h6K9(hgL{B$i1 z0V6_wHTXsFCo6d9m@4zH@iuNWto&R5EtJZ27*-xX{!kFF+QrhFDY`9gPQ^=Rvt8bJ zMuFJ1Te1)?gRF-i9UYoDItpOTKjy43LIrhPA$+}-Y1gB}=-{Bnx0sLX1~ctjdvQLc=x&Gg44~*1w^^A*+GGtEkRYd=Mz4vkNK`aN>wNX< z_bDif@+7EoiFsDRxx|fjYoUN~Ecmf-sDj#+PS9=R3?gKua>X0-S_RQNrT5#$pRN zDdN>?ZC}Tz4li6Ah6%??$uT|7Jj|U2q&*oV$FalqR5#yUnn~gVHIXDQ>(!bL`=b*s zqb&((qG1!FNPV26P%pE87I!=ZD|+^|et2gd&xzD*pZrAf{3zmXc}s&=OQF&d*uyUr zPaUI4_VwmX2Xcw+kI3!oCvPhCQ55%2&kW!>WE;$qF@gN~GMPS%lWrDtu6=&1G;m%~ zOn+O!O-`e*rXe-tNV;Z43{XFFL92LEf?oC*1xKzEz;Hxh(7rnDZ|Aq zVbRZqrs0Q5R$+ZjG%+XGYpEmEWFw;YGbY7bn??WKHDkzBTN$9sX`rlO+^Gjz)6&NR zogjNqk0x=JvZH!@;$k)~WA;!HOZ;=d_~X`V5KIWLeh=*s7(_s>&{&WlTW-WoB-_y2}9 z6oifEo<20%!G*tXWFs!`UQZ){V5Cgk%`z1uiUHL3VOc1^2GbJgps3p}TT}lt#F&sGo*J(%r``A4Rze?kG z->MRvRYp1f!g4oQG;Qf{RW-T30o}h8~`MIp(V%8V$c=lEIzne*2pR`JM03pJSaSz0?N3qg?ML z0sGh9`;HhxEPboMJ_eLrk(J?djdyv_F!~q;d8a zU@w!8FVyUk!wsZ9O=OoV2nl|Ln#WM|jD|0@Tj9PoiNbmM?*10j<6=hye;)70r1&ZH(zl)u6{1>u5)a!p_@${TZT(ZT{uHu#^1y@ zchLL=S`*jT6Hcc(PQLWs?F!vJUVBCo(JDLBpmSDai5TlPpn;r7kP3g za?ad3vP>8;B~WG2!^A&)aXKe-Q@OBCn&|e}2c+SvdQ=e*8M#PF+EQU!`I=q3h zk#M>y^x#?tyO|P->5%qeyZ>mR zOaITX0S|Up^7JE3&;XrV00k}wx*o7G+lAr>ETAiTUJYeY>|IWIkW6l2{xAbbKo3-2 zHh^`%*0*tF@w~)B*mL%&sa(bKJeYKA5yR#E7-D`eO$4?7XV(`xs|U|;vSCs6&4&J^ z{2*FwZ6hSUT-mx&s z$cU=RNSCInns97&MO7L?8plY-@iu-kvrv9Z@Hh7LTe?JhYd#?V^re$Di*$yp-VQHz zQ>0MpNYBZXDa*e3?@+UC-c!NN&cTakJFIu*mW~IH9xu;9(k*|Z?(3N`3M9#2`~|n} zOya7NEJfXUxw&N2Dg@VX5I`$Y2+^kTmcONd;hb>&s$RjB@+-C4JxEV%V%P+#uK(J# zuZ^kX4B+XIZ2p(+g;f;&(KPt?6RGG}55r0bDMQDHw7+gdCDnM0mz9_spNz5IRh+;- z7=e@|G!?EGM?<|@o-l3T7YAWe0;xAE%8JMsUE-wZKv#t=T@b`aTlS2}@z7P}-$>ND zZ!1KcjV9zX_*6u}Av6G49N0xw`=eHVgz=x-VkW&S?FqayXBiqb%>*Q2={tEv&oD(CfXL39wql5A8d2$f;$*#( zHhaoi@-z&1nS3Cr`SF7PU!k*XzbOG7N@tRF198kfP*ej)-x7#5#YboiP7e8odq9+2 zSOYL({L_{zbk5Dy;XtZ46K3Q*@Mwbhb#*0egHl1M8|gxg_@(+ChW(Y85toN0M;`o~ zj6!BP{M#8fl*!r8^TX1eCFn#n2~8DgV$&ZZ5Po+V5QW7fJ4+r*`~l@v0Kd~C^Qt3J z=0bjZ*t|IF;eT;lktni7wDQ3yyJ!>HBeNAI(8$-l5%XM25B42NYm1*aKwj6)`Q+QD zEq``vkW%t5Zf!oy^q_y)0zCmw)~N3aInUwEj1;v+j}Mi&nFa&Ag2{#7#|VXLwRCTM z7S0jjj1`@{C^lIPYh%IMAfn!PL9r{&&PpO*M8V4=Qi-+=QrzI(+fM%I5O@iUDt+{q zxBqEhbQhTB)&eT$+{FWMu0TqVT*DOSa}X;7fo4r9M`guo5PS4% znVQ9X*^7s9BsAmqFUKT#cQ9|D%v_A@^K&@8jtsZrhu@7T$}ab835#x2sVaFf7TOr= zpIaC`mOeXFvzppHOCg{l1q~Xv=%jqeA28rYiv`#I9uIy{&z~@O@Lf^u0~5&}@4E`) z5lXHv&$J%zq}GuiE2c__H?4=o z8LC0E5Xz6AvO3(~oNaF;WOMyWXXrB*b5jQ=uXitsXSAzFNIfP_l}*;|Ko>=w3L+ZU9SW zO-LV}#!}!S!_Tb{A;{NRMFpy1M_4u`pRK#H;768hxFbbDpsQSSKbL8uAe;52rjc-e zG6_S2r&QkigQA^GHgM>>UY;V@bO7{kx^c%SMr^6v%|YorVUiku_(xQzi$r4b=+^gt z?uZ#`m%br?GZbA$trQ2?NacRk|IlIdBG$__vg;aP!BedNU_}rvvj&Y^s8#++v!x!< zURG#6AXFIpF-qG_2NPV83!9$xnmkZiS^Z3g!zFd3wjX{a!T~V+UQI^4-_`8)DUhi7 zgD}IEaT%g4KEw!U=p$w00+D|Sc}w(G1oX#`m*~^rcrMA6Q5NH7K5pqY6MTF%&DRdA zN>$xZu!>#nfN{#v(B^xpju7s4s>va^?Sb?bY}lR@?SM>i7_9( zc-@C|WeC@xPbmIB+Q(*_ZNwk*Mxe$tJSK=xd)Ny&p=r{%Dk+;lG5H+f{}ZJ&aj>H9 zFDZXn_q9yr#_Bc;pVyX^NiQi4k0S0pU+q-C&wi;xI;OoGV}zhp-G7XAi|a8D-=3jA zBL)y5jmP9Bc}mw&47b|?wKGy`Wa$5WLo8qW|G!_>2j9HNBnRGOT`+yte}j15DQG~x IgDoQd4}J~y9RL6T diff --git a/assets/rojo-plugin-logo.png b/assets/rojo-plugin-logo.png deleted file mode 100644 index b86e4197e2c039ec9178714452a44ed89603b6e3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 44173 zcmc$_bx<79w>3%<2=4Cg1a}R=ZE*Jh!QDN$dvFVG0fIXOcemi~u7l6({O`vX;4tO z_KAl5l2A~;FlEF=)jXC@U)??Q4?If{H>@kyp4a~#b_9_@-BZY7&3o5TkE*8-3t*Ov zrH-YikMVIhPqa^!ArbJQ6BI5+i=W zSHJU6F8_Onrl;t>X$r?G%|3 zmBK{�n_>FD4UDF@TQ?<-O>RVCj{5F59@puvbcI+}ks6^xawltfE)b3@ymCo}wa zE++3hObX^bE{Uhm6a^Hew?n0&hEsKCFADJAF-y7A0kVB4EvZ)KuWuJpBLLlPe(6l z&4%gfIW&ZSZTDBw&hv=+eZha0bPt1oLhuLC7fe-;*5}J?yTOg=sHTdzsluqVQ89*` z&!7_Ann*<6#rdxc3}o0b7(|&=yzHUN7Jt;z;%dlnon^=uYQJ7La&BoE#?`QrW>5b< zL`(gzRi&9;Gkbvde2Hcf2HNId4DfgOVaj`L+2dU{dSwnmPSlZ@c={OWZd+ur_zi)l zvR6Yppmh2>8Pm}ZM{-#wJz#3L5YS@89pV&N=jTWJ5>y|A`2xBsau4e>)tLM&A1wLC zUWk$nr1prtEuPj3{#rAzrr_jr;G>H>E`81Wue-yh!a?C^1Y>?&UzzNSaDMQD4R01K zOrj5FeDGGC#uFnY?o<0A)x9qwYR>(MkErOs&!WIWU|U@oRJ(xc%y~zV{VE=pL(M8E z$&MvD;ghk8Q`K`2@%%peROHL1E+rnq4c32FWOItVq5|9UN?e6X^b2W3I|cpt0ia&0fZY zl{R1CobE}aMIoTiAItTTVIj?IEcN#dJ5vesNw8xSJzhx-ugpY~4+>XL>0L7>movb? zgs^Z7nO=nWp*Ofhs82{3?eh<+Mo0yzGWc?hH*=9( zCedm8->&6V{BvPmSe;w8{_dqCsLv}b{#nvo5&b}d0v{nsrbshedQ4($r{H3|!(vQw zI{>Y-lU$HkNL-nK-n)UWwp#LQ8p-Qpnn;+BG83jfdWIKNTXoJ3JxX+$qmf9Ch&RFNBFCePvb2Y zuuih*ea8#;?S5f)_ARQal?~Y%NX<5p=I<})r&TbZDHLNLk!k*mgj*RL!u%t*Wg0VL zJGFSj{>L!w`o4Yd^Oj~7#VyW#f-kAN{1P>S7QRZFa1}J@OzFr2i{O|4X~mCq z7a@WUPz{l?l9JYIp$a`l4IV=>L4yWIn*(){jHK7o;oB};K&(NckeJ2H(g>-uCAt%T z?`3E2ZRgutNe+nPeO|o6w*y-naTE50*g$`A^z~c+p~l%qZ^(qeU~sZF?9R|4&+O6dQ~E z!kxy)U~Gp!>i>DpjFOxft?ggpU}}v0#gL3Dh9J8)wCGpbw*CrT zmnSaYi4_{VWnv9pDOJ4}u}&Cq%u+O2q+at*ml9Q#+7V(C1x#5_5Y; zQ1BqFOmGjdC{`eQBE6d~n`b0{L|CKACnLx=B1#Hy6*Wn7V(nJXgqoMzWI`$GO0Z;- zDi3AGIg5Sq%X6b2TYxp%KdlrsVJv3NMlMa^L=#if8hxE|XAy-EU$4`bj@hU8-tm+2 zfA0TtV>$iq4JEB=n)9i&)!k{=s3|*AM@{PV2Psjsbi1=YW!>&psf)pBB{_B?09+RdP7?qbu-|vdzaJ{?No&(?(XoS5JjoUKOBj_ zkI@NPuzGa?J(%~%S6sEy{b#$JQsl_8J={yl=bjYqJsS?jr;4$sQzc8sgQ%|DZ}Yhc zF2Tr-mt8NP;NDvm$Mf#0_RWmWl6rs!!^ z8_!yq^Iu|k2#lAeI=ndk*3Ouz8t!tJbWYG`(O|?hHfW$KI&(s6%bl2F_BDa7%!5ez zBYBc&?0{pF`;O)4K1J-yo}yzDI6hjOMOeaTSmLW&cPdr%BPi0%CjUM_ptRWp^+^vl zkV-$HTc+atnK6$6CZu85!JXw`-2)e#Fgw&iiHCT@hP`LPFqZjfD10OyXv)ioVHHFo ziZxWoE?%q$9V&T+8oPOR+`G2)T!hN?Ns=?`sb8>l)!tVHjbflFf zPA5OML&?5J!G6|qc>6QFuSe;q{;w57X{!mUf?*r3oE#-V_I)Jh-^wTJJV6u$gvFHU z3A?Wyy${~7O6f7YjhsoEnlX|U)SKX)^el>VR0^8J(iwIuWhz0on396jqXnA_F`D$x z=5=Nv)CpwASLk>|=?zFCETDt_FUEPg*6(7bzjstcF2i2@++SZAwk?xVEBpL#O_2Q$ z%>MpDwe2XbEZ+Jjhd*gpk9%K;n{_C?3&N$ZC@8f`+Lx9pc9e56wWygGF@Q$txcvs@ zSe;usDCOW1ICa?f3(a(t2LJ>FUooJ!-lX(w*M^R6Pv4g|q)7);6i(2VBxCkU@E$V^+gha^#gz8yXiud3 zKYcozY?mB6F`U`Fq)GuiWg+p;O0p@=OIc(pwFnoStnNnxtD&0hvp2 z!r6n?G~tziXFY*o2N$;hO~Tu7E9}N{_62`1x~yFbiMcH`L(IqTKQ|N?w{~10{UWT_ zSLib}57gus5@fX+L@f$;OCMYBv=bb-xqhQW5U?n)Uo>&-Z$>fkBX|SF0aE z7J2A=ieP?=E@BHkpM=yaIpgJ8CE62IOk1K9MX^9M zXcOpM$^AfQ8qxn%J~ou~kA_Kf=rDPVqpo=h8+OR3! z#aYQ256cXA7x4jBGG))vY{+@$VH~#9_tGs(mnV-0KiORqJ+_FAUr>Idg_}l4;40^Y zVxB8p7(>dIn_QN{i5~z%wD=K;i!hoZ9^{Ls|cX4o-EK;g_8YEK8 zwiDpqBIsX)f;>Qt?7qdw_7K**1jl>>kunF%L}*PXorNuq4Hq_+ja9zGisUs<<)Dhe zdj@z%Nh+T5L0RThjxQUfPDF%xzb$YqDkL-*qFS}VErI|%i! zA1c8n5lFZ9Y|Hb#YPz_cb=g!aUNSL?0N@;^QZ-ef-*pL<=g)3n?lg6#8zZT9bz?j- zMd;|2+`3ob)gfTzUaYYLyM}Yr!3z`KXf!uA>oa>PW>b4^LYqi|wye%*c-cEQ_jyFI zlnHMSvr(c$TC_%GS+VzwKaEflE0E*4l-}x?{t*!j>~fDknk9xy6z^WZK?1>U(c>o2 z^K1=Ueks5d7wY8l-~O$hY|OwcZr(&zu4Xaz&1peBsjUoMSD!0%m57snEq@)hdQ@Rj zmBr!ZB8QBXwU)|Qo$!`7^SBJM{5t2mXLp)R{Sz*fg6Jkeo+cd+->lXj&0Ul9t&X^F z!X@DvRz@n7>rc zGDvM(e`ZMU6A&I2w}#D8wMFW>7tX2j0|JHW=*7kI?)XPd2dmvR`-qC{Mi2UeI+};yw~)46k&A^o%P=TX7{) z(Nj2KrxB43-VHkrtV4op3Q8{TkkRj+aP3ZnR5$D^>GB?0KdG&GGg9-M16YqDJeN8A z;Gzi1;tu1`6$<*pJBnKQRZ=o^xI_@uqDJZPR~ma0O3!g*UUNM|;=B2u8sw#FxOe#0W~sOkroznbF1Ejgm1U7ShkjuCR2u2?jSU1!7z~Hv3XaI z_v9x|p*OBuP}sJ5Lk0-5*ET!rVJ!-%SZp*H1DP=K@CN}fXJql?vJg=;W!UGNrhC7A z9#fLcx1HZx5thrjp2=_EdlT=P=$A7>EpW2;bSk#-r%!6vu}ef=p%QOGr!ecVftWuIf#4+f;@^Zf2Yo{fixHrJ|7HilU!{gUeT$d}D^O zf}^YIn!Q{I2@n&u)e&&z5`!%`lA;HAuXbo_G?G=FR*><=X!?o4R*B(*%GR8zdbiT7 zeM8Rn>{oq=RAT6f2aFoRm?Z|t@1XdS$d9klZl2QlXF-GZ2F2I0LO)jBgkahl6Ae{E z3N+gN2k*j>h4~T zTnHxX5hov@JG;>-dUyKTK2BM29cF{FPRij?6xn}+(SR)-uW)UUv?U?;YXM`PVdVa_ za4X@Nb=M%9xQ=P`VUI5Q0_|%jW2r@hpc}U-FLT@dOsMbp&;sHgW!!nB|4D(+1*mD7rA@i z`y7XslSVsE)Xfqq^=DZ|}$1lFV7JyJ~F%Ow7D26+yoc zn~cY@f{RV01%$PGT84rn|EK$3x;8(;7FTr(8x2VmBD3pVzI?k$8+NeOs>_vjjX1$z7<)-Ny z_EM?SrCIp|zf96f;d{OM`dkoG?cW*tF_n@1Nb@!gk=iyA0j3JX*LY8EAT?#Q!tBB`d_XKOW%TRn3!AazXNp<7kLzoLeODZ6>wc6cU9akq zcFPeH7D`xOQP|UwRHYQBUwblzo--9?7eWsBrwOQ_++s)Al(PKHd%>zDSJq`aFuFz>BBL?Ew5CbD{^rs_^nfP zAT~?qHxy#N^jk5_g6|!uzGcFife6N|h|GMbP(_|dBH-+~m&9$#Ec7y_hhoCAFu|qwIPR1Kr5%WoNGXnMdZ>)V&#)dITs!Dnqo1Pc zFqQen`sh*D3x4MtxvbsaiBM8MOw;uB#dS*lGXn?ws+RijlnY_`^M#nwDn~8pALNt~ zb=eoM7rxQXzCw-5k$j9(SX){ew~{owSM2xaev-m`k{(|()_LwJBDW8gg?yByp#zcH z+eqa+=>;HhA_Hj$FEfatlRJ4Q5A^T7QQ2SirR1Aj$qm1Onab6$Y;5!H^V;avI^pNh_VxFOR|mWjhuGmkKD93lsGB26B%Ub2n054RWNSI;a> zaQy|!eF^mMgD97#7Qf&ibi}Uif3&&dg42AcPY55x7jy`I1HvNMh8Bi!p>9vHGmK3n zb%8e5U66}9#Qai?1h`OUgeAEA@WN>$=1&y-Cewiq(xp^KA*|mcD$mq#o3FB$N|{i8Dh)% zx=DzqDKja~gfoipcg&kGBaMcYQ+A7hao7N}hpqJj4i<8vm?peflW*{Bz5VgXRZBKX zx*rpumm=ib`0h}xf7yI#==k^)>eJfP&X+06Z~I4isS*a$=0$6kd+7{$B1Y&EsN?re?n7uQ!!lfu3%%AleDms~LgY&Z~Fp>)l1U zydrg@DfI+Qd(>Dqz%qXRh|pyFM_VO))8*&%iMgVyA+#qBbilMpiA*pKGXX<(N)K`7 z6z`cPCq2pKvnAw6HS29DiA;8G)gQKq$6#omS z;|f;2ZdP@6oSiwA+^sPHd@`i`e0p24^tcrc1(OyZ+<~P-DO0hL0YQTcbzQ>rD?-DP zcyBK_vCa1be~_QLp1UjSm!JN4+4J&!dlMtUWbv`I(h??pzVGI~?PRbC>$~=_2?_S} zwUN$(UkK%WoT5F*ZudwmC`ZNhNhs_tBv@j*{L^+IH@T&)2ROGHH|lku<_w??(#sYi zdT4^g4DXmnc)k|S9$_EVYaG@8lfeLXVL7`ScIzE#Y|^hwG%jY z`N}%M+_xx%z0WAhUOOnV=k4gub`$03kl{DcG3pTQsC3g~iVx#}EEPN%rA;jF zPa`&WVzT{LTPN2i79b%g_V4^H6E_eM*nIY>Q#tUzQ0^dI2z_T83=kGMKun@jESW`e zcjI{3*1hexMNutT{^qPZs{L{9qtIh!W?AO}jx6|891S{Dn7{9kRtlXeVcRy7zSED< zs&XIk5ox$q-oh&5$T=JFyg6l#;hLNK8}eh-pPOW9D!i9nI$K4-sJ0GRRmXRqL|$kB z0%1bvkqDp9zO0l-*$GU{<-`ci7j4=qRSr5SsUG~&0WcJ#qK)8 zYI=89PX*;!f;?S55kIr1D=kkd@blv*o}UXR8ZS3PwPR}bB5Pe<0ST{CfCy3lvPt-3 zy*X$LD7{vn*?^?K-tZZaIyP3tUwgre8PqiMx~+@U4rZ%bsEXQ0r(xZ;dqJ^q2wWv8z#=$H<#{KtlKuF^U3DnZPCKx5>%gTb{HKR<;C6^E}cL0 zCk$2wx)<@y{+fp?uP%K!oPx3AS4fcP!1_ac=OQ>UvY&pnB|S9kB0xHP;=pilc1gg0 zP81CwM(U1GJA(#HO)W0o5s>(P2SO^jrADd+6(+o_3(ZH#ftp2ibOMs+dP8ZnaQPM` z%ej$=otv~%!rierf0;#lLmKwvGbsHC(}T!%JpwL7#5nZd71 z=Nt66{B78(%I~ZS0$iA4n@V!!8Dhv;VEMAo9)wv!^L3Id3$=`m<)M2$_`O-I^mMI( zL^+@%aOAnA;N|y7v_%h&45Nop?u*Y1s;fyUZ?h{tEk3FFf$O`~zy0OK1QYrxRGJod zL6Ejw?Qi)g8#dOjW-~8_S1LwZ zu0$Yw6RxgA&$*D`y0U;{Z#zj_F2frbUVyB{;>Mwd2h?8&pUBNi-hezdpjra>mLqWt zUS|ORM`I&)$c4|@a z?->PUIayB6{BlTBNt`L`7YCoj%}cGuFIEu?3%DKMYw$Wdjd!`Y;SRq{TWt8pcjvyw zPAkTmoefm~;V=g1kgJ-o(#`{oUv~|M=BHC#Ou*uvqOg?&E)F1HIa?aByEFo7;O`;1 z{-Q<>&<&!Kt@eV_M^&F(gunzJ?0p}Oc!OKc&CIkH#B3J1`Ez_@hU&ux?1jUN_LrC4 zJR}ErA2dbG7D*u_3+1)iSMgNvU4uajriFmEN=2y*hzLC*yn)sJaLFJ!(~*!*`X3@4 z^yI0CzFi*5Jmvc2bTa@7|pgc(Sc=l*xd*6!zh zw?LWaB|sW_E`^w-EBII^ma6 zB@yHf%&*6E@{+E>TlG&;`KD_y**oI{36(Ej|p;OI?jYM(_N@5K%10UW8<@rZeT25G!Z%R#pRT zd%em(h!T)KBbY-`OC~Tg&p&C^pnyY(S`Yq(D`NQ3VZY z|H{PiwI(IMSrmXYiXYo&0oXTY9}<>-Y(S<>r#SDN6_B~nG#%2k*b|H#HpnIK{k~A( z4d`f(JlU_tEm#%bl^x&skY|q=F#3#@y!*g(<&jn6E5&;W zc_o$466Bes_H<=S#j4#?^p6X*7Y=qTZhX!-<%J=)j@bNd;{3N|OXQU=Cr9{ceYxqE zxB~;uKmLs&A((5*FJ6}F&5?20fUvjRCs#4zqQ#pNE zba&IrDsQGzmd@+PEzoQkfMwVOGmpSMHC!9*?T|LjBm8G^EpGW|$sD zO^ldf>3-X`vghM9JZDYq>L9ZCDrT`6D>5vDr=Uz(^c7B27x=+U-K`J}2+ z-HU=`(Df7v;HZg^xu|-TDU$4%%&6;-ePOW8I6AG^2`XR?p7<$dnc0V_B8>3n2?)`B zC4_Bhl8miPe@v7Z7;ToN!o?^UB$d;PVgU-{>_c`K8!q;*){s6f{@8B932u{5l=74% zGaUKttzv9>pT94-3l~C4y3Aewz_;4hl=EhRBImyg8T$ z;kg$HI#9*=K4bkbjNkI4QN@JrUkC>_{0gV^e^dl%4`T(A88I-E0dYu0KekkxaJ)ow7x^Ymk^Oee`u1giFCAmv+8m_SZ2Q4e z;jXSKy&?dxUd)}DZD+qCb#(b}IVT;ElfdP(WulqkYo}AJiKPu=Xad2Y-aPMO~JK1dts?X~zGBnA>PwRyA9asGPx!yq&xa(v0DPuQF*E~G4*B#Zy70l-O1(|MCb5`+G5vJ@BWzA5A5VZY#A3$nj=s*$0n%0po z#5BC#_4sp^caXlw``lOOfy0(^Eo(G1o_Cz1i#A@tcu9)zk?#suWNS|3CBu}rkv-H` z2ib|Cj)AlmNUaaun5WNR|A>kPli|r=vPcUi8UW@@Uk>@s2|K`s_MFZMNwDsB-AB;l z&Q`7!ZX=G`!*Te+F4S&gFF8=}IO^nj<#aZQP@LbG(0|H5p2&1)a(6!0oJ4Py$4;&x zOFj0sr@nZqG@Y@0p`9QvoBwgT`hD6;Td0IT=wmWf0-O}OIJ}}ciznei-l!{?491o; zbb~<{IS*`usEB}wFy$y*V(_w&o@(Aa_G_U*Q)Z)~@ZfaUllLld2O|SPARTjSilDt1 z<-$m&W?p(iHe=ub-1vh&@wYyRGq5-Icezo;o1IRytYd{6x z>cn(2+ZQ@aQu(M}ZM7W{p#E|eH%y+!UM7QOONxw~Ik?=6u(r|1#5d5jG; z+pO~807^YsLvHMZ_8jpiN9Lu=J)o+70h#kSN62S*&;|ZfA-8M@XTaWypoi9$1eHwl z{?hcR-7Xh!1XTOK2M4=JlQZ|4kk1xAR@x}V`LYr;zK*F4Y#R|wK&iD36Vj>1|7oF| z-KGDrf_?u?&k!KDgVz_q7(^t1sLA|jUZyZ$)3D5-`#DHhWR0bxza{qt!Ej?LF$oM< zD(cE|&itP~FkH04>)XXTjcAb(RHg(34c1LAz9$5!dlBDfAV7DxEiL{%apSn{rj7P< zidGX81&JX86fnTYu|K>GE=hK^2&a<$Y|t+CzC_6yM>Z8t$kE)OO_EosHOFNraGclM zF%<-LPRl?4KorHA+T*Y7P`6`o;#Z(aB9|(m<>masj@G9Yj~E!wk>boUvu3rQ6HLkEDTpK{Oj)t_%>@P; z2!N~|pDM?n(%e_Ri};D?U03b|?ndF=0T3LI3|(;Rmw(dw%OT#y34h)@4#AL~sy!vo8rdWT6U>A1lYCDDrDfYuIJ({os1Mk!c$Rl)BW0k~UwM25{ z4554Nk)r?S>8ekM@{+4HtXH2MxVhn2eT#|hH8;!{S(sbW-53|Pd(_uHF?~qM@9{Kg zuqq(eUB-pezwgJTf^S%omQ86{P@d7^9Jy>Gbv}fEO=u?T$ywM+lxxjtKZ!hX0~C?_ zJdOjnkBS)bz?mR}3;4Q7m0Wro)jO`VhB_`$6lBolFSz2Ji$_LBlv+tJ7EEjU_# zFh(WhwZtQZ7gMijRs}qzZ}U(`nz*4CC+UCZ_O(%vmJgW=$^QX9403F~s-YcO(CRau zK`!})eCF&`9LJa=QKtB}+7EJ>afENz0M;-#>o$& zNgg4PrI`f)6BB-bDQ{rb@EDHE&=IFq!MkLQsQLj=qnsC|N*PvCWp>ufiXl*39OmP? zisdAwY&`R~0fk&dWxgplGqXLB4CWRch(a0 zMc!^-9r)vu%0^R8j{)bM&KcKQO<|(U)5c@`y1x&BJp?ULC;5(7r_UTiok7;^!l;*2 zP;zTPvi@VQ`YQ;fBx%6jAG>mVWOMyPw2w=8+Mpr;-fSsMegEL3i#T&HP%z)rvw1Ye z40X=}s#XFAzE4NcKbG*aFsi5W6PBGN1uuJSwfSYDY8g;6JhWCGGJT_g4a0xk#gka! z`ARotn0(>PkY4!roNWJ!tro&swZJ?RL6ty{8>j);T%|6<(7pqF0{Noo+!KWcV5xn)9dQ3@#L2GO=zdkTFgq^=R5hFY zi=Im_p``#g;L<|4sn$MqzntUK@qfXhgpD<>C^H(&g^;Vep9iFa?nB5dx&FyJ`|G-_ z%ax0#e$t7-N}J*nrfK|+Dbr%K(oA)AkPI7XcKnZ^-0|gmmhHYmcm64zO1Y}@1T%aJ zwkJTIE**^$9-IJZitq_L!0a?)-QMorw^i^;v~+Kk*IIM!QUa}r_^r$ zWFw4_m)HNDJ|SVoS=DmfAptM-3`@#!dut8-6eg??I(ZYK&VP1#C6{Yr{%V3+w}sjj z)$z-8J-Y@d4)E|Ht6348N%A?UQu^xLOU%{hf9qu{zdhLu=9^66=5rr9a#xFS9#$Rq zrh-Zw!6;5I_Ws?Q&!i?53?)ZbQuHl$i~tPm{kx@#$lN=xBmWDsAB1(f6fognduD9< zC-G!#LPokMP0$m?UU#v!qoIo1E)~)6Vk*#9asn|709JC!-HFcd@0!B$P*E|!W)kH4 z_v{bdw1pJPR;2A8ylt`1tNdstT@tfQnBxGWMPST{%){~2#VKMsdIFe%in7M0tZF5!aQbJH_7v`3C7;Ozj0o`uV*TiseeB|i zdXuq9vsqG+i3$H3DZK31C=$W!Udd@!-G7E!f~0rZYqC2{Bwt5!U(w_ox6DYT*(i68 zPdiTK7^E>I02a(Zm+wN!OUwYp>DwJ)sDvKLzjDCiCmNE(? ztgHB@WpR4h#^!0-I#kj8QT!~& zJtXk6g$;(LHSVy{LwW9D3gvOJ$47T>aDF*4M;VqUVdiJF)E9l&$@*>Evk~t45%vhB zwC2IEGP+zqgsP>kI9mg{Tv+JQ0X<}wdtSBKgabVlS5ucKw$)00B1^r4GA@L2_e6dP z{1AAO5({K|PAV~S3RPzDWX{=7IpoK8JpIyZZ_G^pvYL5uek}GL z+VQQ+e8^SFYiGj7#vw;Pyl_6>oxjSX_pcMse0AG#CA>8qA$Ls}C2G!P!a(0#?x$Dq zAt>v)qy+!%5DkjZ@6y#tcVQZGFXbW(;ZGED1k(!`jg ze?>?7u^q|JBki(pj+&e^SyXYnqvvNV%Vy=f7k0{~fwUmWWR5yZ^FkmU z#+?WHycJ-{@B6Scn@krWUc3r;Du8Yk0GliVwqWh)#K~twpsnWZHSFkV&l!MIR;0~A z3jVjmiQRM^K+!;fCplv^WNT#vfac7nwtF&un}?ux3qtp3+Tf&rO!UNPd)D&Ec?Aubar-+(%b-589`El2U&PWabU`Ye|FCq zVYMf@7+~Qzn^JaR;0i9lO)dzfrHOcYNt-!RU-EGq79fmbbG^kHRx))gS-i$TYC)Nk zqeD(MOP~6I2$7Pi(;&n}NS9O?zFT3%!ePCgCI{%53}=iyfZhi@A`c%W|LK!6YXYpi zzlMIdKG)O}ynLXx@mBZ&5Occ<4hkseUpbi$IOo9|cQ zg~9OnHW!5l5eIZ#lt%ZbKGDvuK5Y znlEBuGN=3Vl~p=FbEoqtQmD*W#hby!D6)Chx~{XOg$A~(d%q+BfrNK#Ga(7kWIKPo zgfflJ3A*s`M?D^AC1Su!8hGa>Y;;JPE-TEh@u&jAI+Bk=e3HmBSNB%Us77zLyMP21 zfFyrE#&t>oHk_aOFl$Q*pW`2<>!{`ls5)X@n1mS*x2`M`6aHqTr?RdBLg`FLDLyJd zZP)3tsV9G;&m|jWk9bq20cDNrSn7Es4v**E7N4L|B>>z2Epgl2UnMjNz)llbsLb*3 z_73o+0=*L!8fA;CA$STjg3OE5i_3aCeVeekXatZsYWLgCE1Mfb8nNz_Z=3@Sme$VN zTMmkfvp1*K@}xovKwCr=U{ByVRk)KU749B-E9h(Y%ZhQedBGJayw1^`(iX1t(K@vg z!9XBKQHV#H?27-ENZ-EZ3&6z7JJiV*RmJ{oEm?#*Y?+F_Qf4e9cBeyVnxuqwOK<5sM%@G3KWb)J@eXqHoQN&mf8EsN{ z&+!Erpqlnc(E^MS3qu}DnL6Mv*Fv~XaZ#BxWq0wtWIIBXOEvdm2U-lf)zto62ADMK z3Yg!J;^wmvvZdkx&J4!}w|w_yHtc=o6^kpY_;AS@yqIX;duIgJwPlI1vsaf&ei0i5 zEC9IvWEs*wgdjHWWC|orxVza2(lq#?*_Y@t55_w3GP(+scUjT1*uyAg?I`f2w-6M)bx4Ndg3VpmVVH`~)?AV`d0=fc>-U zzDt)s3YArzFDlj6+z|n6x2`XC+ygDHE%EH7V1Fa%c$tu1Txz>lz((^jK)~xL z-fK(&be|cNN(6tNji3TL5|ypz9pt{ zYc9lqyQXTW0kXRG(1%q5xM=YNoDf8@0LOwKgI!wypu~TDaE4Zjr$TVIDSirA0W6S` z3w=UfN!FNYjMm{;$DtshrP!}&= z12)jGwqY3eU=58=4@C{$)=|^}v{@oOkdfFtuUFe+*C&cU)=Pe{MtAJguO(0T0-`GQ zyaZX1cEXz2p-fxyR4R5z&+QexZFyV13R$Q|fYT!_T5x@f~bk?$HwHudre1k5Q$ z4?#hIEXZ)t9sy)|1q+|V9Kd8ID9lw2g^(ERtdHz!*b-&RIyM(kr?%#aNzHTi#W^N3 zrzZdk-QTDYi=UN008~wj9fO|kmLx-E?!FGBm!bMh7ppr&DI<>`L%VbNic+40izW{I zDZ9$p@F7YuAWS?03AHk%6W7uPg5Y#(^Xf9ACl|ubx4f2IZ0!N9_5W#sSY^LrI`l(~Nkac1FEM^(s1=?PW&5 zW4Z0h6+8a2*23i-tONIgebBNBhF06B_1F>u#DCSX(-Y$22vGGqq38I< z6I)ku5iXjh9oObDKxOww_opkYy8s;rmn)>k^o(D70TWVXu~WYnY@o16sHK17ic5Nr zvgh-;dV+&OiOK^g%j{vNfa;63NV!ef)in;Osj?ggU{v)1{N0ypkfNaS)4(>xBK*#{m?8y5>?EMGIn|nq}TbyVZPr$w) zBUwAIw!Gait8kW+@x_|^(?bi6I681M3>BW^2!ny=V||x!Ym@DvS<*At1%pE?HTZW3 zp@F8RKnwCs$|CcRz;OjUM5pRUJMN@mG$N9M*QV-!?KCOIJLVxZkKS=#E6bXq&b!5oqe-PLFzg z)0T}=I&oQYFcJ({u#zk>B>YgHzXcc2Nb*lk$FXjh{=Q%(dhok?Nt-42xr}m)RSY%` z-SQ;wdLpy5{rTH1qYZDdW?9`@aoOBV7eGta)u0R;x9v-<0y+H%=%4#=aiRM|bLv3Z z>6IHG0fY&oIs;Mlfad3?KWzND{@H1Zah1h^Pf{1XX_>vlq>#wG*RbKf15mge0apX+ z`tUyB8xAC!dK$ClJuWZnJo8ffcEi=d;+2HXm;LRbAP68#fNslV7Yfmp>Kw}LYg0J~ zReFqWv=9MqKnIZ~KrZv3$Q&IVs#tIn2YRli=>U@7jQ04`dtEd9lK z8uN{3M9I)~%Kh^F;qOY_tG+Wi{cIUNPGm5XP-gHroj#T@%C;u9BumvMeT#{JX*ITs4Upc6^#;}^FG4I z!bXa@%TjMCHpuLd?nK0Ak4uKq*d&Y(?yg?FWtLg}w58o-5COTi`vww|yo7cUlYws9 zSk@k)tC9E9du8V9_`PVXw+S1lg%>rMK92nCv*)tje7I(ar$qY%!IdGdwiUpJaXXbe z2}Oz!NgCOZi5k@TGebsvXM|^u5j*!4W|W#&o4zEX3Xd#>3g(qz?iWsf+$L||Q_5^o zQt!0W;t!YfN>4?5kM%WIzl12&6E~~hfyE>?DN*4~x#>o2w6re9{O_n4X&zx`k>!Oi z%=-(0K_U1Dr_mp@3o0~=M^)J-A2??ct!}0r{B_)AwYFP#t#Oiaz) z)pxy5oE4lx8zHAu>4N@&f2#@ftZ`XOT#AH57hD_^xD7$HQs`{l@`JuzpkF$|ns2no z$rxZ1-mhbGL|(Wb2+Db%!CB*n-aIl>ijFW~bt~FQTBG(i=;(b?l}k}D`cg3Yh4}#f z3A%d4mIT~-c9w{t%b%to0lp}R-fb2d;l=da#Ft_Q8Tfa_gGk_K+XyDvi^no15k5!Y zR*b65t!+|saL7SL4X2g&Jwu#y)-Jh#wO?!33X~5hR5V#lo4@HLuPm45QTcy=Gkkd3 zJh5(C_{yn;d#h>T9v(JIOsx>1IBtcgqJrBf?-thXh3jE`8TQF_dH{uueYHVtn_1ej zr%*BPh|XZFF%?C&2U65W$1SC!oYbH`qEyQgUVdwC%c_vQPN+hNfmrU`?2t!MdnZb? z{j~erUCal=mtIBbTBzB-=WVx6vB}!iv^}ACKJWHzU=_>Q+{mu-2j$S&isDMKlEVQT z)i4D#n|)2}9kN=Obb2l$-sHSd^!}wRizFoPm!eLzcL>wRG z7F6!TnMf^4)uK~}Hhkq2A~e1$Mvv*Ep(qaukd)!V_-1moP8cjsCEDNq?QU?OE>A)S zREWMS`5Ul&Gpw5aNKw?O`Odj1roI`mgxq5Zx8?|rOK zAwu3?`=!CsYF0Z^rpVxc(k&)UTT7Y_?+`*!$A4tHEbHEnzSW-!xDUm(j74jxM`C>W zoTJ9+u=H^7KB`hQTyNh)dR=&pE}{+chm6D&w05OI9jIrd(Ah4_r9c?W)CNVGcqLCS`|$3O$Iz0g`!IxIt^|8?O{)*69~8e zY3{V7bFZq>>NuvK!}_v^HaMG5`QkTuDm>wi}>1uvGe7*xFl zs~w_}xb~X*_5VdVZo^wq8}C{cve?2`Ov!!8lc$#h-%f1Ng(#&3<= zoG_}^NSV=w#8fE(b5g1HKv)QpyfKL${wQL;o*a9xi42LO6aq3v+43%gljQV)NHO*7 zvu07Vl6J}Z1wT~l8*P(d+7ny2z2RIpEPCB`l##~CWs8ZxS7i!Btp?gn=-AwDmV|d+ z;UN}Wf$>k+i#Qc5tMrTV#WSnV`Kj?RY?d0XVuQ1FpDf@1k%OCDoe`QRbn<$ncH3V~ znKqqM;d)8kNwCy5?S5tX>t6_Z^9HxLM(pREefF^{E|aFrxxgRE+ShNgz@A-10Ke!x zvXmmo!ak7?3~6%A^ol8rVEONSs~k&0xG0|fQx3x^()dI~Nv!DoG;b0wJ0ry1+_|{v z=YO*QuFlqZkvTrR3js$wI)HBV1xZiUOYfi3x7ugl@oJ)egbF_vW z{luvz*^UhFMd^GqS^njdZNxG|NVQH(T+sW{O5gvIwb%DcvB|rF6>7lrl-_hmpmMCZ zc!*b!C?a+eNekqdBtU}-H43B|hi57No)is^`0=;Wh^}Y`GRSk-THhM;56`cEbNBqx zuKtwHt*ABv%aP>`PoHDtqn$rphj9*ePaXb+8F~ql)d!FEo}isj09io4$5GjSr{F8S zHW>5|!XRkzF{|q@H&W5G>|b>Gp2Z)}jBqRRXYx)%@>gPxbKsDvvP<$jYL4BZA@C2y zkbry6DY_KH#GjXjT@r>(5>$t4-4w}*^~RnRk&keRNYW3y`HRO@)2ffU)PJ%@rg9gw zOxMeve-}*t6g7fsEAc!aH|IZF>A`SR9n%50Iwd7tK#H_=&d!jq4|SQvT=hfXX1{+j zWb@$NY?XFJeb`X8lQ#SCX+)!@cHi%si_&N02WBX?Bqn2W`yQh{dAB|PgYw!3Z$}6m z{=5FO4nA!+gpI!xJ`G%09L4?2cudpMuN5#`gVuJE5460B83C5{GzV77zM@ zM-+h3t9tnGjKG1IqT9=1aa*((jQ)J@&{5rtNYP%jk@;` zRE*|x82!ep0nK5NW!z5J!n}$T|B5D7aJ;bv9Ub~ZAWgxE825a9Brt z@SOX8=wrVnOA{)~4YW|2>6Ao0;1&SL04vGuNZuUZo&>-E|59&J;?s-G<3gaED}TC> zADMO}B{`U;_l+Hw0zL)&EO(wq)bP3*I_^f?eGsC3VE9S+k=TQ;e!3h_4_sNaO?mqp z)^JcZM+qim{G-Wi4zPpLhK)<<|2A#@m-AD^x9fX~`d9Wz;RkSgkCg;zg^wgu%^K2A zaTy*v?Sb1u;aib6fdVwtgPYQ(4+dYa*~iM><5Z9Sadz3pOYlGx2gCk2Z1*Cjq5~|D zfhm?(@%h|88RO)*&gY*zxT#73AKZBC(jtzY9J0oX<%s+~yhs5WiCCz3qWlrCOG?{!of4y=@+PL!mpC@SloSkkFbS>%3^@hc?aq}P zmsN$sR@D5V(UG_WSu3YN@yFs5f2m<=o#GC~nv7g}b5n7_vAoh(J&=XZ*cOtQ23P1M z^DZ^Uq_b?~;Klj{3SCxVu9Kl*95i_+QI1gGNB9)YgcRhF?Qta=ooU5~p+>tZpE%cc zaQBC&KE{?Vkjxy`W9g94)Dux1*`kH?GI6k8M}OS{g;{qauV5P_JP>Yw9%($y9on!e zENWjZE;{2F7m~ul8L0_t(7n21! z%1SoP4*%|kHl!P&W=87`&h#Iuv^^xg@!b9LxuJsDGziZh3^2w&C4Pm3voy=cLx(d( zO14PzKnh{L6+aFSTm0oADjFrj(`Lm1BCI7|e!b$NKH@=5CBSk(X47V~$X!MlM?7;B z2c#M~I=?W{6a%T)#ie+E$$vF66f~)vx*fHBz5;sU;DNm!=0G>6&=#)cHujj}_V$TR z+sS%AVjd%E=WJ@BetilhP#X*ziX`inE~3=@XqqRj-U^1nXbLBp65K?GZg&@hZI$cv z<>z=vdZEeac3b)&gI9Y$$LTEa5$3{Y51=18))E+odUu}JWv=e|(#QVN$TI3kYGLaMuoAVEZ`!FiU`AM zVNx9>7n4aAh5ejw@cP|+AiOvv0=yAp?L@-_GNRE6Kw7FO-o(UKn7sx~GXrKLaeS7!09mQ@JsE)DE7 z>m$K8GE@#DTJ~2i=f=Mg-#bXrt`H6RV@QLG88$rff(nN!Nk%(Leont3-_$N}O?|d~ zO6X?>hS*@R{Ho37{Ri`m^ueEEDJUAp`D=~o`vWYD>AY;+$OSi|Y_;XHhvn=~1`k?n z?JkGQoN6xA#d*NzS~+*ttiNHPb*W6R*Q2+gOAPS(mGI zuV}7nb@{_6l2#F45=BUz+oF1QNfRO6HhbwCcE6n_rAkF(wWhxCQ53Zhjv{XG2bQ*9 zZ}BYqf0zFHp{mIWoEmkz%Y~)iIOHNXM_HB&aFHIwn9zvP{fAe&1 zj2Yw(&G-TR2mPx|{_XD|dkn+|LKhn_ErM};cF zPmvB7kMx$(#ai4v^G*5)_s_!UW(YN$K{)4;yptv=Cd}a&SMx6%`sPigrUmhRdxnQi z0ueDBOUpPX=$#qEEws0SCVj20N1k9z5|cjAQj27N2;Ec_8c8M!sZ8!4GB;U!+~%0I z`)q(vvE#cBF?YQJ25qazW@WXn6~D;5de6N(EZ=d@<4Az8Ykdj)Hkn5Qs$R?w@!2v&U!hEtB6LNyzL~;qCjSbMa35EaJTF8{&5Pu0rz86W}9$~NJkGIIO%(CGd3DN{MsvHl*3^aMZ3R2GzYO- zdd$M?$CunP`sdSNuC@VJ`0(3r9#)34oTyKO>~ngJ-WuI?(JXiw`*bUtN@>Jr6Vv>S zJ6n(4XR*q(4iFP6YM1oi$9`lY5Dzn?@h|TR+?aVYY!+|P7ckPJ_z26t6yb%gCYaT1qnjQzY0bCN7&yiAVy3-!> zRUx1VDLL}D@0Wak3=uoC=DzD*K#KrBx*;)meGs418={uMtESZ`Yd*-Xfw*9LJ&6)t zXU|^Tk{n$EBEca-llHk@iE(6@So_-9O#WB;?7@|Ze{E0YJ(P5GMHZ(X`}r}f5n(6# zc-r8gG*e<&6TdzKB9q&L!k6W|HCHqR@-)z{Jf z4My;#N}e=M5{zI4E11fN&gSN_n_M#$g2Na}uHWM|?n>N7baX$#^#{fb+Zqizd`qBY zaz;O5b3xzi=}*AA$<()Qu_MulE}7iwFc~#_@Hj#yqO1^2DZSIjblFLbrogA89HDBr zh~OfY6#TV%Ga3Lih+7QM^MFe=vFpu$gCEDgxCet`2K8i)ejX|Ju%GLQY(px~Cq&KT z`~oXpb#n$bEDA6OG;ulp5=}`-UCdtlv@U_B^NHV7ke#{ZgKdOV?21yzBEse8GT1Ny=^iMBjB9(rHv`9;J( z3?RJUM&DIbuw7_Z)XQZ^)ib@%1VB9B^}|&ns8&k!#{{Bc{C%EcN*ud13$F32tPM#^>*sF50}n_;NxeO^fIl`@=3{={^Vt7 zx!}gQG&*dm?`y=7k*8mD5)xetY^18X9~}K7BcUOuLaJ(ZN>g9GH*!vW?ElbW>ILKn zXd?FRM?7pWY6_Fd-gB_SKRAyeKzSB?Si<05w6A*9D-a|0jKh}5O< zg?`!Qvi9_$$0euFdAupf(4L$EuEo|9Tuf~ij7Rt|Mu2n9xjXCL7Sj7ZoeBfQe9&Bc za>7?Vb_}2dDzK5S{vrERB0yPCK3LPGlbaCxE0k*i7y8`qMP)8C*B0IKad@90&gWi_ zeK%(vH*`lW$FVnCUsl8*ttepqs6y03slyoPI=^(B@7Fa47Zfh|PanLd39Ko&pc2I& zWlG#wj};t#UX||o*bv>z-0WSc$f!iZZd_)4Y|B_2<%yj&>; z=^UcyD-W?c{@7>e`w<|^S)<{)GH0n{v>N5;r{DtFz0@_A5FA?GLTra`P8&FiYAUf`GeuD?A1_#J(EyGpPo?bY9!O+e zAO}aP*fpF!3j27HIsP)*8aSJwD;YOn5uVs8V)5pV458}W9*<~?3 zs6sP6fyRJ+=$I-`?)A8Qw$I1Ym&6kDA$-0=g1~Xj=?io)GEaKzTGULw?s^B9arp@d zczVozvC4b=-BFNXq8?Xw=lAr7#Zozlm7qj9OW1IfGW;_zMt$b?7E^Vb~Mz*&LDhiCwNL_Gpa~78)mIMZ+tAFweXTPPZijO zf5_U?9BQC@?iXzFOV|Bdu*WHDY6-E_AhT6haU=m~@#$ul^Hm(tOS%VKV$$IlwK4ky?D@5#SNeN>23g#1_d{(n=`2L!P?g}Qz7}2HrJU*kAxCP3& zu@t0G>nltB8YeM4XE$)xlt3tNU4x?~kE&S~S4!%*K%PPa*bQjjh|+)XK;me#*LtSc z$M0)76d2p66sQfC?L5vk+#jxFophO6kYv^#?r{;1$Jq$+#wo(2$1T%)c1l9$l5Lr6XeLA$88}XLMvA$aV$&Z$O$3W+S zQp~sC0}O3|HKg@6O>21_{ox&cLN(h>;_@mGm zHVnubc2czST4bC8xBWiZx9bgLSXuoe(@&lLtW@>6AMw)POwOG3tc=A5!ccbiLD2tT zKl_O%1JF}<_SWAfNqQ92`t|X>mReB|2E>Egilbt_JN_x7=MjBO;0F{anr2)(KG{ly zK`_E>U4@hVefv-v5g%%{5HVE^SMxA z;d5vAb5ft{DJ1vd>@_nT$%>e9Z-`rzJ@V>aU*5iI*&=A)l15Duf?=_7Sme}6a-jTk z5Dg&SIHfgRD3!{ zGF5FcZVT2#O}A;n55O-2eyWNV@SJnh(g#scJ}QAm}ogg2-yrWfa5_d zXdhj5edIA0_09daU&94zVdXY~`Et!_-9rh$T$x>{i=>@}P|{~tI*($SNw+PE3%UUP z){wP0=|LhEuLkpmFg*}x2EE$vVg~h|eSzknOn#%L(wF@77+{06n)9de#*MXzQ3Oer zWe4>%?YIcWW$2l9Z$^rwcZ&Dkaa3}j!h*>X73y|&@xwQ}r028OzH{X+lM7)A*|=h1 zX3Yyd%gjQNonN7Nm+h$6M}-X)%%^4(Y%Bi12Av+_rmN@YS#3W+lFM&6=snIKLZ86M0|8?$rV^IN(M|uc+f53DAk~(j@CMb=x5+StSpckbwE+=3oNDhEbw(bcI7X#DK z^7T&_at4D8Gn5o_ryi%If;W2~r)REWl6)%h;A@&ZKwgvolYwmuZB;esPwSq$)`^K{ zKLZ3LQ~@zHn9YLX<(OJKuEl7UrI)(ac$ULo+VL^NgTP6+40?6k@E2F!G|tt%W6Yk( z0Rc+Qd}8ocKh8JF*Zlsq^Gs$hxR+1^;c5|U)zw;^os77=Qj9ilqzI7o!wNK#RYxQv z{(WZTOFxPb>m$|GNOp~^C7&&0H31Zwc+AO0?Qn6XM~H<9;-TyRg2`NtQv#?UQ!367 zkHyJ9iZ}?jHJ>$%^GnZudUSwf5r`=#6BH5t?RRti#^-s@11_=XuyPWAM++(*LD3!4 z9b7WvlmlCM6%|Lv;1Q8^@`?E0h7WUc*UM6$k@2+Y$lNtL{}=7?F*fT|ii}Ebsieh& zsan51IVNvjqNbTqDTw*TuAD&rWN5FYRN)CYhA>lUUQap#+ns-1HI^ls#{^CvD&k%? zP3S|-FL5B=MJ>6-D6(_b}f%1^5#3yhY2mjpO8 z#;N#UVg&*BY9)yvwIsG!Ey~N`1A6ir86Rf#)5+pMvS#jsKH>wLGJFD5PpB3Gc|h5H ztG&O=9+8Uk!Kk>>~nz$y2h<9VxOIz4B6Lx7DswN5mA^w$we)k_~=xoAcYRtO) ziISnN^Q*xInw{ExTXI|USB{g&@7r(Bo;s=;WJZ{=ky{Om$O;}I(M3zym5>- zIvrjj49g#JSNbcbZJQ;xj}Q0nUQmYz8f3bHbJCI9XqvJnj86hXHSHkVfkq%q+1 znVoTz-sxH~M+1(J@xCpa1`17-e;28vvRgm&ot9C*{eZc7@tdN}F?|ETFxa$FfQ{vr z74yQhOs{~cd1g>vpCUp+OI5<*XN1Ft?rd_@GpOPi(PRCZs)3{{WZeei%hF93uOAmy zvcZcxTrEOAM|XJ=9D&4(zue&O$qQH7{H=yjW$#)v`1zht-}PT4v2l)FCm&Sy8B@+Puk$$Scr`iZ^N2zARM8v zXq=Pe*zQpO#bkXe#3+xylnPKkF#G%ymzgXZaG}2N?Rp_Q<}DwK5uq*w7UHi@Ya%x% z0xbyIc`o`ZddDubm}TxN)|8RX%b_Vc-fR{+J@5HTJ1Jn#5T1n4e*0OnhL1@SZey_O z1m5i|PR$_7m8lvWOz5o;5YD?UvHd&!AbqcgOalsdds)#!PEp!k4cyQHwpuS%Im);G>s6P7r?%n4S4t8df>&I!D5JKOPP=sqDnuX zNh}t@w`ZtDm~?Z<^9+bkRy?FBDr@!tvBl@Dg0Qc;n4W7q_01wB(Il*MphEcE5B~~r zcYEadJyMTT`JVjRQiix!dcG~CcM`z5`*#3P5hYgBN-z{INZN5VLomU3<=$@=7V(e>w$>r0XOEppA`zwUyMRyNs_B@t!H zH=`~CE3CDIj1(b@l;re0f_rOobV>k520A_zV#4F7L((~kOVlFaQ*WTszW%e|`hy@7 z%rWV9{GT=FyI7d%j(-Lxl`5lceTrodmr0J`Bi?+6^S|+r9wz1l*A>4Caft=#3sa4~yei^b7~fu=DmvoCCF+d4Oywl*%q_T_ZY{X1 zoQa&a#_uFV((rKB>Fw=e2ZD%!D2txLM%K;U5((48_-H6N#m;dsEkk1O@G5-9Kfl7X zZ&(rbsTiIFKmGQm07WpH-1Gx6@Npx8>4Bu)2SOrjSui$xgrf8qQq$IlJfOLL=URRA zkVesm8jM2;E5k%s5yR@SOAZ+H9Kw0?QN6uxNV4z&3Fi< z8JPEA_hH-yaPN>G3JCNpT~g*;c-U-aV>OALdW`Jvmwt2V&;AE2k>HFm!=P!ky_1*^ z#K={FD@(T*R7CZwE%6X38=nmRB-9pAX(?VX?7Dq5N`j^0y7+vEf^w#)zGhC?A6x?ANAB5S%*pfUEQGqzmk$5fAbi*cG_i*)*`*5v5a1rWIa$3AH^9by=tkDZ3yG zR%PxKiALK~7F zqp*6bjvSyzwziKB$xW*)>9(-uwzd!pDpO5)Ka3t-g0C%b86)yHtKrlU<~9-jrMSdn z2(8u#a9Z#hu(2BMPpthwjJ<0bEPb#g_i;1ow_%xbxf?!-SMtwxsh&lHxulSZLv&=L zvZk+00Udb|e5$Qeqf#@?CqOcOM8Fl!P5j6G01pr=5pUF`XMKzyd`4~{!6}%2D@cL= zLZMBcQ&8mmYY75r2uKAKskUhCKcv_we!XUx<#f~)*wc+!BJN~wlp13ccnb5Z1@n+~E zkX*pO$dN-!tqNt3i;!?&{{oq{cA?w+PNjHRW-IGY4R95FneKuN1Pm78=cxDJiG$T; z$K@?-;FDuJp;X}6@-yEO2Pm$vXKa4U}#HS@C zV2HS~*VoVg5M8=0-Ma8EfjfOvVRm|DX;8>gXNKu9w?vGWQi2c1ZFpb{q+>!cbp?s! zVOC&bd!Zic(waAC=lo2frplm@p;z-~3qDl3APZ&y;V;uFqx`y|kFca>#Qlf@m^_da zc{Dmqi{Ntlbq7DW>|MY;LC>+d{xw=@t0 z(91DW`r#wlY}Dt7ON#XQ4l*xyRq3!CszlNin)8 zI$R94Rh^t5H03Y`U=~1FD!1V6k>8#Qlf?MEfs^1bcK*qHsqYF!R`q>R&* z@0HvhK{q`J=^T1JK5M{31T|>jR0tddAO`*vjJRL9n`PP(YSAoOFYSHQr$9=~>p(o) zhR(~w%C1szB~4<+s8vbpQ)~Vl4**Lx_;EKW<9km)48Rsk#s@KBeoq>>-rIdT?+TIt z-PvegxTyaP>D~Gm;svqoQqzRLr})LEEOjMK%N~EM$Ve~QMB|N!tMV}I49HZFo$MVi zIZJW#N{nWgYJg-zu!>+(0g8s9&ilS%>EI-QH0QzwtaTvC<{FYYN)c}LH}tL6r^_Xo z(Gmnig#D!z5zx#BmBpdtx<)s1b9rNM@`tH15B!Uq|Mpnn(}o6!hX53$;cK6Vxi#*__1wRY z2BHG2dH$e-W^Glmr}L3~blS`(G9Qz@R`|U_zrLqCqV=6KVPIwXu?f%Vg%2B}EyPUW zm~X5MGA?|rfBAC1%96%z_aTVVDv(NOT>K{wLJCkg$qlkIuwwzUzA6RsToGmU$pfb& z;q>Oo4OIY87|Ga3LmbQ07PJag6<=dhrt6(N0NOyzak=&A*JhJ4PUn5HT#2{Od%VG% zfY&)x3il2VZFd{4+2LI>jQF#Aj0px|XNEF>YMSsA_*Sl5foz*p;BkD146EW5(`dZg z3(ydpH6ACuqI!h~0iurH_nULpT%F#2PSceCRJ5LrY^QOxCBtwzx-t`6GN@RJ_v27g zy4y&5D>>Q3d!8IeBxjdOM$&Xy{PC8lD#urCHFxnn48cwATBdqb_88{!j~BhNv9bX< zKiy7f`8GT4{5$axWl^8GL9U0~kX(weRL@4kl2B)y9ACqGE}bYBwUOyph8J08?e>62 ztf7PmIkbR{R=pH`(Mxw$TK3BRY30{G_Mq6lV*V56W()fKFlRGDU7_&Eo zI?7G&k6-C}NCHSicKclYt3eoM%13XB==#31_Z6A|WC8>?SY`1+^eL31Ib~Y^a4E4%$ECx{K0I_C@Uq6_3xhk1Uj^Hc2WAj@ep=1kT+=U^YkIUY4L_WZ z^(vXYrgb#dEx*7*0kr+`ut5%sL5FSll#1fu(G}g{|-@W$R3()}Q z&i!eNZLeDw)0Cx&Qg?md+O|TI6~CFf%r-RW(^JERyEf}40NRY$^mE@X6o7DRybXNn zG(l+A1lSfbZHwjC%MyS)xsTo2>yt~fSrIkCEUUy`Qlt4$f+>NthvWyqJZqY-=ld<apnHF@`qnNh%S1jD#1Mx zsA6y2kml3Zi#I(Jjp>-RXHUe?gW=w&qq1t5DgHkVeYED|`F67a9}h#CHLo{ylFWO# z3|M~HT}l#Hm%_~+^vC$S@rsej_JsUAmQbjjCS>qjciFEgC81I*{P%o1$zP@@{nW=C zfVjB#PTqZ^Whb1!&qFDIcP~sjD-^*byA&uVnc4K~)4#Lhwpe-!GuaCMs$lk=3Y`#{ zbd8E8POEdWtD>D=!FV<Zq`s}B;TpZkAi(xh)bK|@ zHi&@fVWr0s2#m#JYCTi8JZJ}uD@NQ;-d|od zgFi1O7`C*D-~Za>W^2MU&)4P7WTH4v+obOEgo>?DnxQYB!EFO%dNV|zCX+W9XDj`D zyxNUjPX2=nPO}I{?c6mp;GO`2w7$>s3vnN|NxeQ9b(uK*hHNV-v`~`&=5O`mzxmg` z6BBlo{vYD#ft*${uJRgE^GrJvVrxM{o#M@b6wl?6Q;yiW8Jr^&)d~)ZR07fS_wcm=@lodU5+q zn8N4z^QM-P;Q(aPy_c1Zwkt;E+z0&8vWqaD9@>#M7uAU%uIKl&YkA1~>wR+6-rSrv zW0cC-=`(F?@f_F!*L3YInWO1=;!bpi60{x~bu=7C^F5dfk$n^LHM`is;Bm~Sl(?O3 z2D`x#JLI?YqZsna=d%;CR76I=V0jQ+`qFG;-I$R%bF*#B^>F7}2+-KF_4%;%6KJuZ z%Jy()v!HlFQES!1@+M8Bp{_DK2re`xly%sqN{#VW(x**#zo`|qk4`4YzhcAJvVYo( zbcqa~5dvo@@qF?Prkh=8?yz}EG^5Tk>a!hZP4@#flKSh%nKgXrT*Twz=%>mZ7~lDb zMISEI|#*i z?(9xGs_Np1Z!Ca&Xw^}#&`0)1E`Fc8*7C)Ms`+Y58e#y&r`;G5Zyg=~-hhRb0nNN? z;^E>9f!XPZK5~1(xHRJnI!v{0RV2>GAhg7j=~ve3>`+vF1t}*dWa{SH$(IvbHkU}) z2nJ#y=V9Y58F)@O`RTRpj!$}JJMN~*bV8hZUje2*U$SG7PLj~^XZ6jCc%g>D9_U+b@sjL=!eCS5$bQ@O7^mTE*YjY z*c(UnW_$8$2Hd?qg#9Q;xjpW>qZ7J?aAdGfq4E^iT#>x4>AEYHj zJmzs!nV`e&+ILQKY`5JE60h5lI0vVM z7k^4{j%M+_mHJ;L*?&Au%CaWuQ9L!1(zF_phXKYfp@NB)m=a`+5j<1hTTT0oNZ> zHz)q=ITeNOu@U=RA%B~Sd#ORW2#_qiRrhX8+9hH zjK2p!7_VhYchfN&oxAb{x95G^^>Hxp<7`+x8a4C;WHN{KS=chn`W^BtXC&4t<#YV+ zD{UO<3JwBXf+$b<|4 zH9=5sbwbd^9XJ7K_Wn>VLixEc759(Fk?@t}CT-HI*8pRH*5n5)4j~u9$Ttwe1l9_y zN|9F|2^Uk&H9q@u#j(A7Se~$(VLEA15HlrzN28%YHN2VGBuCj{n z$4gNle+drDjaOorYJSiL!h)rv`KBJtuJpV#XJO(r@!$JzWITT zBRTuSAMf71!wDT>8j%zm%Whx$t@cL2-IhGKO>=*2^gR=^=n?HnSlqLWyOS{z4^iqAH0b!T#{nm!;2XX>)X)#Y>eHte4PhZDjj`!F=|Fh}2NOMtb z_imXb%%!j@`3(>TCf{__T)gTTFJU#z@9vBF3oN7qFt_Z5h$28DLKO9wibNVghJyX|83-Xy~P1(u*to^^3qTbw9h={rK zLy5PBOAD86T&8c&?Yk_iDSCT^DL(|g&1}MTaCs8;mb3dm=>lj|N&uGSO|3b8rO!Px z-oGiyO!Y0<0Z*GzB&nIa*o2t)mP8?wCrvXr#nPfI4KbfDQvo2t6|upb0+Pb-aS8k-ZXAYp_cP54x8$3>C%7ov50EE2HP2JLc&=9oMa-1y&+#%!4m%F-qFVX?4rQk?sIV2apa0D!HZ?)4j#PhQJU{b9 z;(8_5+B0*05Fk`}#u=n`|LG*l#bq`piGAY5Wd7-_(D7im!p_bu_oUSKM@IA7b%8@Q zRm!#YtiiMdtG!0V)Q_C4Fi*~3i7y`Tv5v1Ey{(&E`jJO{(`Qda#&?F}+M-9mzgleQ z5=%i$Juuk2^qWJnD&lLaFC#bgOpLbbuq-+^?K@Z?NZ@5qoEnxE{eY`0U~ndl^cWU| zSRK}Qw69hhDf^+&I>H*9vXFtA8`vB|TI9t4B7Hop%KgKyu-96Ioo^F+{PAQQ&D+(~ zT!;BWk6^b8san~-;k52K6us20wTHtzDO&?7V)`rX|E!Ys&rB!u?rM>M@&w+m44eiSaaV)X3EszBv6C zyUoddL*#FC3gw|uG?@~oGGf6`(Ql2JW(KXVm|$uBZ?meILyjVMeSXm!0oXJ_Y(Ti| zST-I0x2+=McJuA}^bBL3r5`$e>1lzrLSuvb2ji=gj>gLrZF5Hr6#idW`4fI*%68}| zNexzFEm>-MHNKBf^=*Abw)YlOmZQh;W}ud0UPUEp@SuR~VjGFGx|+2e*KVZ}tylVX z$!|eMvAPd4kl5j2kWa4XliOP}OP1Op&-l^Px$j8iOPCHs_|p$)^)Qh9&1+@IM*FrV zWcTG4g2IdWFz}~RxF1TrPg&yW!HvR7zKgWnw_(DUjyo+Hnl06oSAmVN5=CH+;a*k` zW@+>&&K`Q~>Z+)Grd9MK<>Os8F4_B*o!|925^_G-@XHv+w>8|H9r1JjS`UOPQ+H5V z-ovE#@5kT0d59V??DsJ@DDi`RpySDK$%#2#Uj^5QRq%B>mNCzt?(K)#u8O>xtb%2C zBZfU`r^Nc!ookO&o%jnHlM=kvyTsY6>Io56#`c1jy<4{1jn+|XnE2XtJlDI3z$DAe z?KP>+Y6I3j;T=}3ml`>n8Wwg&_zd^nh^51m_dDD;@WFd7WXR*2mKzd)3Jt zNw6bmY^OPGuNwP|?T^P9T}kdokm5d^Y<)MoXw%Yk?2d|&os7U1mFeEQId&8;OusoE z&47Eh+NgnpQHG@^`xnoH1=QA_q1$S%+tPIHcQVkvVFaTP3A-j<`xupL`l8XTK64`T zYW;#ZQ@*EO^w{MSYvmuRQl{>~^`n?SPh|C27Uo_*^qy}_m6g(8smr?VDfqKp_wP%| z+MmB*aMeRUGmSQY--)E8`OYK#;%o$2$p8&L`3w!-SG3F;}qn6{e}?& zzTdA#>oCd8e=dYKI=S#ayLh1A(@R%2*EU-k)UIEiEG*xSeeKydj+Bmh`NS>q=O(_; ztG30&tC|#!dD5Q?S9qqC=sS7NXu(NF&NObeliF{j|K1TA(6qejtogA(HJ#%ApNB1} zIeT65cF1#dqmY2jzZH6K6Q$%T1j>C{#j75mcgs$3bhAKkM8wZr|dVvWh0ij7i~X zc#cUeYE6nN_1yzU{;}Pth3Nq;bfqmf7Dlk$Tju<@F*he#{Mny-k1mE|KU||8%%i`P zJ|m+q*fZhHC)r=2*V+FhF3E4q@aq6gYQ1Qdwm74b`?JgxnD5&yPC4$#rLuk|I}3O1cq8$eEg)kz$&{? zU-6P>r$Wips}w{7SXeDIbpokci}0|!}A#e6V0gxX632yBuvkDHFc;F3C5S- zR)~e&eJ1SH-0IZ4R_HChuw|5`wfk{i|n> zs21^w%+&Ir9^Qq%-4t6=?A(#S#r^j9h&{aF1G!|4xf;O(9zpVBSN5#SL@iCDB}r7j z9+u~H+`+H7q`#+M_{6B6_WsS^%}EJr|T{+!F;#94Ir>_ImgaY1yCzj7iiDkg=9Sn zGl<(i+|if52LnBFH&UbtaqHxd zYl=CvIoP7~ot+|6eIx_ph$E3z>ynFNjCqQ!L@DCl{UDqvg zvWtt9f$OUkjCVh6jNjc0U{)1XeJH1Z-q)pk9+Iq|QR1gUhis4qEaB67%J?`jfnfV?7w^LE5-88@*zM$Z<}XVUCiT$a$clAL{!-9R%i z$eq8Kt63M^)1|DBFM8Wt8_v2PPc>9T97I|j%_YlzyRaA;8&*p&Z|Cd1lq3R7#_Al&n)ZO z4+j_|6A0>r@ayc;%}^g2D(x!PH_Hni$TGe(B3am0I?Folp&Yxh+^>D1AYVhYnc ze8)X3MxE1%jeT`G!jm4<8^~LgI&Q+b?DP-uTKf(!NPM@>F|e)S`U&B6f56vsG=$qu zdwhiVWK`!{TcHw|4|Jqv5R_T455_;R=~ANP*s@g9nw8N2esYAHn7a15DqHk_DRK6y zo3ql5WA?E#aiuD>j}TU;7wCIi&pHM=+ctJ?T<_eW;d|OT;KzOXfQ*{+seDgPb9|WR znAL@P2N@;#hXph4h^sZvNxh0W9c58rGNVH?{Jk{}6Dq&n1PMv&TThVx!JBS;MC7G> zCdLsK*U*HVQ;VVik6#@FrD}w`d=XD*s{yB^i)$^cBmLd!aiF^@$@@@>D3SWZd$mzXKf z+dDcX<8Ssp=r7{021)*3abFn~)%&%rl1d6l3qKkpBt#lyNTs`^VL(8-TS6KHqy+?| zhHhz)66r>fp<}2496IK?{eO9$^;^$c?^^GN_nmL|Ix}a^xzBy}z4vwPy)O$xtb)NX zD74hU!72=N(0_AlDphbs;g?QJnUl6Lye%7f?oKIJz~I#LWH#W26LGxyzE7}Dn+&UU zAe@sN`q?Jjf__t_gfY&*fO;ByYR4+`oo(OSN6TMtcCk2vG0RF94&52m-z;^ zNs&@rT@!!x@Om@TM)b8fL1pI)8=@5rDHgFN*IRm%uazK4V#$Qi9rfAv8NSdn*A;Y! z;%(~5yu{D*9%m~9-k>l~L&Pv`lAaHF|`nWv-eTyZ7| zC&_1Zx-+%N1$4^GrK(+LgtGj!?7bMFtfWZ@ikt>{yDL?EQaCrb(1sn_=Rf0X3E}$w z*DvUu7oK?Gypn77iuHa%94S?<*_WD(PdX>s5*K&+&frnSUy0@XuBP{dj4G@g4c`@f z;ayA;pziVd`fjF%GQ(O9)$a8XY>vJ3pEvp>$dGLqbz*Lwa$DLblahUkmUv)(rcz=B zsY#~Hla6G4i9cn3*lv2xk8I53ezv~hbd)TH}$jEz+^mITs zCxMBDvBRi3e0tHSOht<$Uv&?|dLVF4L@cLKZ7sYl5tym&Cluuz2C9p=$6{v9{+XXr z;1Z6?eD#nD??bDnh-gfP`jS~o=-SoNz-|Dyc8V3V=#(+9kBlT~w0x)yfZ526lx!=Dp z*L_fLc>*1BP0<%u(&^@t`ZbPfa~GPTCh$(>mMhbsdgIXHBmK+`qy4JFi^@@03En^R z@pp6h^<$c&X>H&mQtWqWS3^a*Jvedey^>>9czyFy%B__SD-HU)Cf+M;NL&)q^_bNy zmsVIEo@by+Iduwm64lI3pcA)4LX_e^6+gG{rXE>Na3iHLe4%zNT0?Pd+Q@5v~ zKpSZ7EZImiR=&6|CoMEnnb-j-n`_R-Pu{g%ZONNaGG8OINUjH^vEUmK?w40U_#j3y zj9Tl07*8rq`q!$iKb$O`^T+>k{nU4%OcY0QU->olZ>RTQ;eIZN$eW78&vjtlBQiUM zCQiPY;Ql6m)~L)z*?>>)#4Ns<%K^FHysO9iQ%KR>oW zX^9QB@#WSHU+rPv4RzE!HF!3;C`8>_YEtD3UYfS0w5VFtU`D`TvN8;#{%8?M`;8m* z?=s+V0hXAr`P0{Eyg?H~l|fjc*>h4nRiKIYv_Y(WMU!JSSqsze5+UUsa$vfz5D_9j zW9Dql1+)7CR_{)ABIS{QerDiC9&M0S0!3^M(;LDXUjQ@JcNX_&} zZP^LYm55|1_!9ZMfzz4W6mn#26se|4`Z)I=s;Gc<4vy@>$aY?O1#=$iiubb2z5#4y zWLWl%5kDdh%ugsJRp9Sawv~$(e5Tv7uqD8*_Y|WJrR{taBP>iNXMR46 zC2HcEjnF`s<9OJsl0PCkVD|cBh%eB|E?P&W)sZ&IZ9n+hFfP9YfXMlzc|QBR=Nd}- zgZi#o+NBhQ>(Z(*?IS7Rx2zyl zh!8_#1i1~Ar@?B|=75}6hw5PE+wCAr^{?mqs`0VBhnr&0+G}&;_27)upV}_izCv^S zM-G(5Pn1f21rQbOkktNAs^&VhYlFd#4}xy(4R3F^Vw;M0MUB;ZxGN@J$Q$rIcOsv7 z@!_bEXLZUPG`@Ktpkp@_Q+m1Ho?iEwodQEgLs2##KgR*QWp9eG-z&;m&Y_Sy%JKl4 zX-K-m{gTH=`D5&!>m}6UoRYE+iCYgdskuLuB1xLD(Wfo`HF-xt@}1Yd>(A>)tDg7cOU-bH ztgIXbBeYY1E9u}kr*K;ZRCI=;T|b3mkvT1Zf`$vejwT`j*OsW#?!+w5*QnKCnrz&O zKcf$^<8!`gqz{B|1@<4?Millb*rP)%_|17U^wAAf>b3SX7*1_6e>ktGgeRSE zXsX--lJs-{;c`2xde6Asy{#nyV8iTRExF(Sas}jbnBYKYK6{ftdHxiFUB3l$C{1!? zxzsK8lVs3{97h@5ukeWtS(PH(%S%MS6>$^-7j*Uua2HC+oJw?vQ;iTDkQtO%&_8Y- z_-?F|Fld)p$iYA!?6XKaXV*Y`6Vu5uy?^!H^|zj-r;R4S9)Azn^QBihO=)S6Is7!R z;wtTGg%RrMh%lH++3}}z*gGemy_mLYDesqUN_fXafJr?n;9C0-3+p2&nFeMKPeSnNCq{K~UH%O3Zl0^V(Olgk=-2#^+vP*0emk)F^O2>3 z>*OF~gR?w@Be;F5n(wuAt7hG!3OL!(_Q-R86ry zsnHZRskZkS)v<3Y;Gpl&m?ep)f$|lnnXA>r@JtKEd%AB8tXdDo3!VF?r=$SYysU$< z&(*I4{EQfPV6@rLObuF@B0KmUEwK=~`MiXPwRhjnBn@V$mRpDpp9?aM-S@@u%OQWF35=|IllfF+h6&Hs8=IhVWuGW^G@Q`I5iND zH+jN$r4(5zn^Y~;1yYkc&f>=}ztOozLo6()ADPD8|B9l*Zw7wgr^szUF#5{7l*hx5WmgQY(9KMDn?IOc2LTdM^m>8MGBcwMoUH~%D|gm97k zX&eB6!2H?O((3PoAiiCTuxR<7O{bf?9;Vk^R3ZjK?!+28DZQv?E2*9>@j{cA=)iE~ zvWrDtX&K#`&NJ%0aG&`c~3*IPnvwKeA*o7%aMp2b(|2Xpo_x zq);!`_#{ZG`0X7k`_xqq&i)mbrFvK~43-ovPbC_VQwQMVce6b2M?bOgi{?lg`o&4* zc0>D8(?VMtA0T&pqZ^%iTcK3c?YF51ySNOF9?r@UJ~wzvpHI@90;_|11Z#ck=Fgv^ zIRwWfqx#G{MXG{fBnbmivGJ4bXT)29D7<_7#vtCUYBMchXa9@3M!_Py5<7jkv1s%x zhg=gQ`-Ra{X>S5th-8XKjem`$_pC_)mjiCmuVwV|_Pvf(mC?(K8?kXCZd<2G(iRvj zj4cE~!f7no0+&!7gJUq~YpfZePcD2!X zd{EJe??p|-B(xYKZ)tBgb0>~|br=w(j~;`1%KeyW@f%9{tdpV+Vv1ZKWC>#GAflxj z0ryUi4@a}A(;qWC?xSg*&h$|!p4PIEE!M2h4 z(p3Z92rr+<%|rGsGbxtGR{87?c7`?6hk3(3EZ{(bGuX1dPY01 zwSF9Q;w^IfGwNt@T;E_Q*L(4y;4ei38xqu!T{;UTc5&FK=bT0OVkt!Xj0M8EN2>Ie zDitVt;hdazBMV|hKwn)w8R*_s6{6s8=XGZ^+Vbhj20XN4xJ<;giDUXBFK#FWXl>(I z)uHz+Hm%Yz!@=Cqe^6#c_+I_v6mXFR_!XM~tp&5DBSZjNarW4-9`AFxED-d3$&4F! zf$&)~?jQ5wo1IWS%R(C4Ik^9HnTgq`jKdc9&4v~nHw~2{nXld#%5Jz@LsjE z+V?fE&x5i_QKLMJxBt9-+9rRs>qKh1+i`3jd?sbRv`w=skc9xr*2BjnKRn+KXqc+3 z6bTCdX|KJ@9hR>5=UCB>mvURmkHHvf@tk4}Dm)Z3kwF2Kp_40+wi#cB!Tw2k1vn=V zBK}qyDD$Hd_k7=-9EXsEQ>f7_4j;3^G9~XxJcb_jQpt~+bfs<;R#Z|We?8&~ICWtZ zCE!V*X@7R}5W*F<4Cr)a0>b3zv5GTyAR1?5Fdx20CMPZCM*H09#;#V6%euNW{OG;B zVNOtX_gZmOc+sRWO47pTl~aS+(2%*WH)`%ic9Xb`g2mDW?C`)_-wr_H4&1H=XSLfdD6aB*j4igIQ)HaLZz5NVLrV@t&6``4z;E*rOoz!Z>j_Rq~m zN0WZkLn3J?XfYI2k0)&c6QU~N22vbZ5iYhE7=&!Wqi>B~L;JXl(tg zpMviSxNhE?D!3hr!5Qs=_m?lp$VnHlQwr>X*Fpby9)rwbF<5i2(0|6Y+`utdt}cu{ z>}$3o3?k8oW?p-g1+7Z{H9ALbh*d{@cZtDfAkGgE25R z+#T6l)aoGG-Klpz_i<5Wx)RD8JU(n2-6x(TP-jeKM2o=2k5x;Al8w!qCe|6tB(>+_4}N zUqMQKhZ6c^3<(M$G~oPvcIQ4AYpIMBobh{a-rLIY%X#5P1W-@&ATw1Q!c8sUrQ11& zmF8*G55zvZSw{on`{OsUrVly>(x+ADYYs*NUkTlAh7<_6UTOf0C7We5Uf^Wc!D+G1(-6 zM<1>da-hrS2DBhW)mZhlPNB9`2aQT1g`Noym4Rbv21^*`z(&%V^fx9;HyYsv!`F`r z=WC7WcjNS|i{>H(#qf4V_pK_8rTcEY1SVz_rqoO=)|E+^*Ny|y*q{kVE99_MWOCah&|1-|;zd1c?f&;k_< z=Ab6X`Sq$1T^uBLG+JR>h`SUKJ7m|Q_dOgMk}a8;v(&R3HKj~+6%~sEUBuadhAsEq z()!TotyNY8=f8d~c_IuOiT!EOZT9SkvTS66j5842$OP^(@_HhdPhx1}Nt}toelfkp zLeM2sIh>11ypr#QW)0;RP5f-9BJ_SiY_@$da@(cfP&BZe!nI7zIzTZJ;Ojtz5=gff zSuL<8`8Xb@X|D{QnTTeyW0%KvT3qTL<{9afNh3w>g`nU^Y*$aF$tS zvxBe%KXx=^Eg?{K;ptMBfuXE|#@$MthUq!r+B;7rPyF25 zs<$S6(7O$rWw|y#ky0_OUlg$;MP9KavnS$C$cBv0o$|YvBrYG`dF*#eN`Sf5MsG1R z0&)aG0FebKkB%O;^c{MLN>QYW%GmyVbv}UN#tnvTPkbLVRTi5~iSBLmSyhyDXXN5h zH#@NR<`WSHB_s%S97doz0=AFY7Bb@9fgcInd{O<4a+pm|(=AounM02)|6nU$0?&R# zy%)a(F9dljF@)#3`yub^$F4PyG<(GM6!G}F?(M05Yx`Y;N zN78n12`lrk9qhP%1Bw9d?xrqNvzf_#Kb9_NIRnuK<)ipMY>sBZUo<(Uy+4&m1*4}8 z-j6j+E;-)?OEyfQA7rp0&bAFD9|#1DW~UUcmzNhGXc1XF{Vs>BCOy80j8mOB{z2z^ zO3x@Ms4_0}Vy7o{hz!ff@wvf}og$0YyjxvKAS&?J=^o4YtXy?j0!Z>u*8vEN2u!twLHIE{|D@v$dbFP!NWHjoPdqc&N%62_7uBrH!q-sJO?BwuJvv6)C@ru1DBR z*@KFpL&>z{ANExIh&DW-y=&H%P( z#o^a`S09)e`6au@j|5_$KX+@-mq#DXn+2dLk?$D7}H(NQM{m%$dhFCEJaShcV=@n^l=uetl(H=H%53|LOQrI;~ zn_te~m0AnJ!oR}?`k;x6zt1%9G3s1zgq3skz7<-Flq+z*wv%!SyvR}}z&G~wtp{C> zFOj!cRE2VFmka1mFBHaba;)m~rfY7*f|PF?Pbk;V_qns9Y{|lHc@@zsq=0YELyzAV zUGl~eOw0*?J>@zz%*9++OQvALBT@#EBpUC>^u+etF^N(!g2i*Q5rCo>1vv#203!li zdJ>yw-6oAGgZ)d9%#5L23L8R-tEPc(4;6bSsPScGw6-ny$O`V7$}stXwG5g)!{~#8 zRnVvQ`o^k0ZsA|Mp^JBUGhR(}qIo5pI+Xl3IRp#pBUP3zG3;{vKQ!vWznty&Afl^~ zc!Xs_F^^1rGp~)k%o-M~eOAavWuH+KMCX4N$Z$?gOKNY)Syd@3@i}I&m|(|lO#z)b zRM<*@2uJdb3}%b(UrMmiv}4rSQh?N05=3nvT7XG5$JqXpo)aKzDLfQi;5f`q$}v2Q0!$R3^^WJNz?n>tLNWK!xyXwML|=oFl?tPGx>adHnvvnOw16Xc<(#R_ z_^!Az`cW>LE1U=(F2a`OY@39yqr`u?%cfHytu{DXF@1Yl{Jru?8uSI8@Qd{3;IyW; zoKG#(tP1i57Z+>@5$BLpy(Kf4U+~fFC`x&~r(;&x;Pl*GcyZ-0;BII>uf&cGAgJ9% zNpwjM_PE^Vn%y%DbcX|^E_sHBbHa%6goTSj8HPQ@u#9H4&icmGYXg{A{VqvN&Fmhu z&&0YOVOQ(Mv=${<=c38rDM}MV9sT+DA7+~*2t1{j$qMy*Ly)5Od#vl7CF15o4;$iV z&DEj&MUdOE>LWP2JQH39;i=gzn~DV{AFjWW`m0q z8_>lUps(BTCS|i)gTZpH?!8fF@=v`VGo){}=!$Kx`gcuJiSd|Zq1d)r3o3mF#$-!% z*^yNVr8WO3ppTvIdtM$2H2~{gb#dF@7ZSN36)Z5vVZoX4k=lSLjj&DeIk&Mq@x$!%}zuC`JLMB!VU6^!hEj|z3V1g zj3*6I&xsNN`ekdIzW$xEJ%W1MJ3uP$AduDf>S0S`IX2|2B$MiFvS7u*f) z<5E(C`2P-Fo7CdaM4;A~0VbnC24P~tfBeP_X7lm(J$7bp5P={_IgPV$wW&pwDge3n zcllyM7S)5tA3>l985S1?y1igij*P|HKHs1@kAFr?hsP@@3;{_$4(FT5RW8odd+#BN z&bThk>%+>-;=;<+&5we{?ri?1{hK!BD#9WR0&e2f9vj9QMNCk6#DvGt%@9Vs>d9)4 z0l@`sUl{S^Tn3{jz`oG8jJr)07PaIixfyTHqDRmFCfR+sF4*0y3QNSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!CBxDS21sKVp<&7Yj08)YrcEAssUev|Hhs#+s| zOk(;4rqssgZ}-*yG4FmNa3;cw$!JsRB}2!}r!pIFI<8{q({x{K()ePB5N|NcrpI08 zbx{kdVh%EkFtV@Ir^4oD-3v@W^j}@!KgTn{+sip_eCOHKFun7`E)hn> z$sJWDjEa*iUInnW+_Z^xxZtN6E#zSEIPmOJru)yzS=J@S-cy#gIjB1M$OWJW7(8A5 KT-G@yGywn_n}03< diff --git a/assets/rojo-r-black.png b/assets/rojo-r-black.png deleted file mode 100644 index 3b417db155efe0f027e711a9648d0b5f83ac77c4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 559 zcmV+~0?_@5P)+9>x?C;fWv$&kv^W4_f)`_k3{?k6c+Iq6}To2dh zab@niW&PN*wm!_~vM)v6`=%qY0)wStqXH_aRa^S~aWwmFA@M^d=$XAIp#o~caOk{9 zaJ_v0w&$@#_{v0lZ^~40@|7bxs_N;hGDi!W?7+O}`JFAQ=6MlRUki354qdFE_P3?# z6o+@70a(ddG%bv8v%vtAds9*61jv82Rl^hD0Z_3I9BnRuR=?)nm*`Oe=IEzwJwk16 ziS}RV-v*TflJ~3FOM(9Tpz1WXt0X5#w4>$D1$wRm{udBv^Z-yaBSj(=+$w5UwAz2b z&=P+*0R+D(rt?o?uL*un7m+CdqGOnfnS|9;UP2z7@zdy5ASyr=;}pt$(9&fDFjK_` zkmyzuwFI3^(Sr(*-sd);G@j8RHQcJw!NL^eE};PLI{zbtkpR_?`7Z%MBj{+zdhT=p z!C$xL#1QW}w7NDdt&H8T#Y#W`gs_`*qL+(aDr-Q{2|ig?yuezkj~GIX(M?I?{}F8x x7k^}}VcZeWf$AiEPscm0pKhL&wAUn-H^1tPJjB*mb@KoK002ovPDHLkV1kcO0(k%c diff --git a/assets/rojo-r-light-gray.png b/assets/rojo-r-light-gray.png deleted file mode 100644 index 8479b957cd84a3cb0fdcc1f06a3a6fa78b656b0c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 986 zcmV<0110>4P)V`8Szlj&K|kN$-!E)zY`kAvTg$JnufO)o zC*OxEEr`eCiLtS<=fu?3)}HZ84w&ib>BlxeJOK<042%p9503{aEP?g+_uo>iyz>Lh z`;#K`0kT3UM3)6;XWrl#gpkR&ojfj+&uy86m`?a5j7mLNOZb^4`c0LC!<`!4QLw0T!=L}^qO7|+X zy}kX(e1{l=f~w-omDncO_1xUtgi`)>Tj6o$W9*%#jUNakE5fb5A?#0j*i=A zLcn>cnr@+8&3HT^CuOeSB*;<;Qd6BK}J+~(%y4^!0?l7XmS z#wi2Zvn}k1(EO0t)ByCmIU8LgwW64Ocx(V|ZEY3l=RG@bZf?G+iviNc{Y;Q$AJ7lG zy1IJ31jW6ONF*Lffl}N?`R4k+?gGx<3{baV$m?F9-v2EfEyX#rgT8~D8!TR{rSn6eR(*wnz()Rg0RUV|xuOsCTTvL3}v5M>6W z05KSPy|uOVEL|Xx!@|PC0>1_J15nxSQ$4!LA{bOAlbKDW zQj<0SoUxo8m?nhLNT*W;enEFWpU+ZEX{N;-+xeRu*mhlA-MK=c@P##gV4NdhEHeX3 zrP4RAg@9w191SxhV9Z#=%8kj<(7tZNj2Z7Rz*MYIpVu!q^GZ{&jw5Dqaq$`7B_lkG zL?Y4d?(VxVjH9ZJeV42_8ZfV5)a^Ew`%$Tn60b0a6}gW5+S+*+(&ExLp+b8tNU=&W znJ}R>QX@4pYnc#} z@)u}KCA4NH)XYp7VL;6oc+`lAmIRfEw(+XB@9Vw$+UNA%+k4vD$;r7ncki{nwbr*D zyM_#_1-9#H56=WV8HbT)a6N;V#MYWh2b*E@B#a$~Ypu}H0Qxj{eTB(Uxbgrlcz+f! z6#?|Z-Sx7%oZ_@1D<6a{SpY06wK)f!J#c3O>{t%cU)?g$wUEmalDf3$Zn)eIGCsK^ zblA@nyo~>m!q#2TXR!Xh4GvZZH@_e>`D zE3nlvV?@74b0VP?eu9ZcXi3LC4aS@at`|Y>W${9t-Dl9=m-pmIpa=x?vx@a2xi9S8#g;{8+6L z|3`dLTF!Plvt0%2$U@y7pPK`qAEYb4eoOgJ)gv*rL9wcLNN&L?0TAbwW+ga~CZJqC z^9`ouf#z`)BaJ;r7sB*PP!j;$TI0>1;e!?1V!xNh=A@KF9dJpG|6U1Ao&o-sa_dR} zNQb};M)TmXXTm_trS?Jsz?xJDf--f?Zf8d)oL*`GiJ9;K3NSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!CBxDSa_frA*_i`{BuiW)N`mv#O3D+9QW**oGxJLH@={9_O!N%&j0`_2 zWKIPt+T-cs7!u+B_Cg|GlL3!IVjlBzgLxgsRqIb0Uz>7qW1hyv8}joNBO~ScG?xaS zeY_=!uTn=}UDsYeab+4`<%Tb1JMBKqnLqu-Q-gM!h+mT#m6((inBo}!L@=8Q3NQ+O zh-cK<@Pfg+u7BH{-^>SEH*Hw9P3A1)2bYRzi?tc51@Aq5!Pg*qag$6t(*otF>B+(e zRA!TNSwWJ?9znhg z3{`3j3=J&|48MRv4KElNN(~qoUL`OvSj}Ky5HFasE6@fg!CBxDSa_frA*_i`{BuiW)N`mv#O3D+9QW**oGxJLH@={9_O!N%&j0`_2 zWKIPtdgJNh7!u+B_F^F4Aq4@J3-{d4C)!L*{}Oki<^s=S5iSj>x5v9vr^l)law^tL z(LI;aZG1DS$a-$`CF{jGh6kI!pDrzB`EiP2#nuZy-z+fLpw4h#^XFfNA7x&jZ#sVb zaINVU^VYhu0GpVqhMoVSnXmZpH&|y?G0aQ+FV1k^>wP+VYvV! Date: Tue, 2 Jul 2019 16:27:19 -0700 Subject: [PATCH 0573/1504] Adjust theme colors with new brand, not very pretty yet --- plugin/src/Components/ConnectPanel.lua | 4 ++-- plugin/src/Theme.lua | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index 0d47eec1..8dd092d1 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -66,7 +66,7 @@ function ConnectPanel:render() Font = Theme.TitleFont, TextSize = 20, Text = "Address", - TextColor3 = Theme.AccentColor, + TextColor3 = Theme.PrimaryColor, }), Input = e(FormTextInput, { @@ -99,7 +99,7 @@ function ConnectPanel:render() Font = Theme.TitleFont, TextSize = 20, Text = "Port", - TextColor3 = Theme.AccentColor, + TextColor3 = Theme.PrimaryColor, }), Input = e(FormTextInput, { diff --git a/plugin/src/Theme.lua b/plugin/src/Theme.lua index 85473ea8..e2129096 100644 --- a/plugin/src/Theme.lua +++ b/plugin/src/Theme.lua @@ -4,9 +4,9 @@ local Theme = { TitleFont = Enum.Font.GothamBold, MainFont = Enum.Font.Gotham, - AccentColor = Color3.fromRGB(136, 0, 27), - AccentLightColor = Color3.fromRGB(210, 145, 157), - PrimaryColor = Color3.fromRGB(20, 20, 20), + AccentColor = Color3.fromRGB(225, 56, 53), + AccentLightColor = Color3.fromRGB(255, 146, 145), + PrimaryColor = Color3.fromRGB(48, 48, 48), SecondaryColor = Color3.fromRGB(235, 235, 235), LightTextColor = Color3.fromRGB(140, 140, 140), } From d07571ea7ee9da92e94a4606b950e3411d76adb1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 2 Jul 2019 16:29:59 -0700 Subject: [PATCH 0574/1504] Theme adjustments --- plugin/src/Components/FormTextInput.lua | 4 ++-- plugin/src/Theme.lua | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin/src/Components/FormTextInput.lua b/plugin/src/Components/FormTextInput.lua index 78e40c78..22748c4b 100644 --- a/plugin/src/Components/FormTextInput.lua +++ b/plugin/src/Components/FormTextInput.lua @@ -57,8 +57,8 @@ function FormTextInput:render() TextSize = TEXT_SIZE, Text = value, PlaceholderText = shownPlaceholder, - PlaceholderColor3 = Theme.AccentLightColor, - TextColor3 = Theme.AccentColor, + PlaceholderColor3 = Theme.LightTextColor, + TextColor3 = Theme.PrimaryColor, [Roact.Change.Text] = function(rbx) onValueChange(rbx.Text) diff --git a/plugin/src/Theme.lua b/plugin/src/Theme.lua index e2129096..9595efce 100644 --- a/plugin/src/Theme.lua +++ b/plugin/src/Theme.lua @@ -6,9 +6,9 @@ local Theme = { AccentColor = Color3.fromRGB(225, 56, 53), AccentLightColor = Color3.fromRGB(255, 146, 145), - PrimaryColor = Color3.fromRGB(48, 48, 48), + PrimaryColor = Color3.fromRGB(64, 64, 64), SecondaryColor = Color3.fromRGB(235, 235, 235), - LightTextColor = Color3.fromRGB(140, 140, 140), + LightTextColor = Color3.fromRGB(160, 160, 160), } setmetatable(Theme, { From 90661b7743d5c2de4e9b8505acaa043613d6d514 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 2 Jul 2019 16:46:11 -0700 Subject: [PATCH 0575/1504] Release 0.5.0-alpha.12 --- CHANGELOG.md | 4 +- Cargo.lock | 319 +++++++++++++++++++++++-------------- docs/guide/installation.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 5 files changed, 206 insertions(+), 123 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 19cc79af..0341c8bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ # Rojo Changelog -## [Unreleased] +## [0.5.0 Alpha 12](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.12) (July 2, 2019) * Added `.meta.json` files * `init.meta.json` files replace `init.model.json` files from Rojo 0.4.x ([#183](https://github.com/rojo-rbx/rojo/pull/183)) * Other `.meta.json` files allow attaching extra data to other files ([#189](https://github.com/rojo-rbx/rojo/pull/189)) @@ -17,7 +17,7 @@ * Changed the plugin to ignore unknown properties when live-syncing. * Rojo's approach to this problem might change later, like with a strict model mode ([#190](https://github.com/rojo-rbx/rojo/issues/190)) or another approach. * Upgraded to reflection database from client release 388. -* Updated Rojo's branding +* Updated Rojo's branding to shift the color palette to make it work better on dark backgrounds ## [0.5.0 Alpha 11](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) * Added support for implicit property values in JSON model files ([#154](https://github.com/rojo-rbx/rojo/pull/154)) diff --git a/Cargo.lock b/Cargo.lock index 05795565..1f6872d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,7 +7,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "aho-corasick" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -46,11 +46,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.30" +version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", @@ -58,7 +57,7 @@ dependencies = [ [[package]] name = "backtrace-sys" -version = "0.1.28" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -79,9 +78,15 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] -name = "build_const" +name = "bstr" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-automata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "bytecount" @@ -103,6 +108,15 @@ dependencies = [ "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "c2-chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cargo_metadata" version = "0.6.4" @@ -110,9 +124,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -166,8 +180,8 @@ dependencies = [ "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -187,14 +201,6 @@ name = "core-foundation-sys" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "crc" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crc32fast" version = "1.2.0" @@ -244,18 +250,19 @@ dependencies = [ [[package]] name = "csv" -version = "1.0.7" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "csv-core" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -267,7 +274,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -295,7 +302,7 @@ dependencies = [ [[package]] name = "env_logger" -version = "0.6.1" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -310,7 +317,7 @@ name = "error-chain" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -319,7 +326,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -330,7 +337,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -351,7 +358,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide_c_api 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -410,7 +417,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -418,10 +425,19 @@ name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "getrandom" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "glob" version = "0.2.11" @@ -429,18 +445,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "h2" -version = "0.1.24" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -465,7 +481,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -485,13 +501,13 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.30" +version = "0.12.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -509,7 +525,7 @@ dependencies = [ "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -518,8 +534,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.30 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.31 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -584,6 +600,9 @@ dependencies = [ name = "lazy_static" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "lazycell" @@ -680,7 +699,7 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -688,13 +707,13 @@ dependencies = [ [[package]] name = "miniz_oxide_c_api" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -750,7 +769,7 @@ dependencies = [ "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -834,7 +853,7 @@ dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -891,7 +910,7 @@ dependencies = [ "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -939,6 +958,11 @@ name = "pkg-config" version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "ppv-lite86" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pretty_assertions" version = "0.6.1" @@ -957,7 +981,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1036,6 +1060,18 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_chacha" version = "0.1.1" @@ -1045,6 +1081,16 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_chacha" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -1058,6 +1104,14 @@ name = "rand_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "rand_core" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_hc" version = "0.1.0" @@ -1066,6 +1120,14 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_hc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_isaac" version = "0.1.1" @@ -1133,8 +1195,8 @@ dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1146,7 +1208,7 @@ dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1187,13 +1249,21 @@ name = "regex" version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "regex-automata" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "regex-syntax" version = "0.6.7" @@ -1221,16 +1291,16 @@ dependencies = [ "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.30 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.31 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1277,14 +1347,14 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0-alpha.11" +version = "0.5.0-alpha.12" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.30 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.31 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1299,9 +1369,9 @@ dependencies = [ "reqwest 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1321,7 +1391,7 @@ dependencies = [ [[package]] name = "ryu" -version = "0.2.8" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1371,7 +1441,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1381,30 +1451,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.92" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.92" +version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1414,7 +1484,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1433,7 +1503,7 @@ dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1456,6 +1526,11 @@ dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "spin" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "stable_deref_trait" version = "1.1.1" @@ -1463,7 +1538,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "string" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1476,7 +1551,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.36" +version = "0.15.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1491,7 +1566,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1506,12 +1581,12 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.0.8" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1568,7 +1643,7 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1588,7 +1663,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1596,7 +1671,7 @@ name = "tokio-current-thread" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1606,7 +1681,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1615,7 +1690,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1625,7 +1700,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1643,7 +1718,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1652,7 +1727,7 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1667,7 +1742,7 @@ dependencies = [ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1681,7 +1756,7 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1775,12 +1850,12 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "vcpkg" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1805,10 +1880,10 @@ dependencies = [ [[package]] name = "want" -version = "0.0.6" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1875,19 +1950,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [metadata] "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" -"checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c" +"checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" "checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" "checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" -"checksum backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)" = "ada4c783bb7e7443c14e0480f429ae2cc99da95065aeab7ee1b81ada0419404f" -"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6" +"checksum backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "18b50f5258d1a9ad8396d2d345827875de4261b158124d4c819d9b351454fae5" +"checksum backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "5b3a000b9c543553af61bc01cbfc403b04b5caa9e421033866f2e98061eb3e61" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" -"checksum build_const 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "39092a32794787acd8525ee150305ff051b0aa6cc2abaf193924f5ab05425f39" +"checksum bstr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc0572e02f76cb335f309b19e0a0d585b4f62788f7d26de2a13a836a637385f" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" +"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" "checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" @@ -1897,20 +1973,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" -"checksum crc 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" "checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" -"checksum csv 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9044e25afb0924b5a5fc5511689b0918629e85d68ea591e5e87fbf1e85ea1b3b" -"checksum csv-core 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa5cdef62f37e6ffe7d1f07a381bc0db32b7a3ff1cac0de56cb0d81e71f53d65" +"checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" +"checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" "checksum ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3b4c17619643c1252b5f690084b82639dd7fac141c57c8e77a00e0148132092c" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" -"checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a" +"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" @@ -1924,16 +1999,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139" +"checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum h2 0.1.24 (registry+https://github.com/rust-lang/crates.io-index)" = "69b2a5a3092cbebbc951fe55408402e696ee2ed09019137d1800fc2c411265d2" +"checksum h2 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "a539b63339fbbb00e081e84b6e11bd1d9634a82d91da2984a18ac74a8823f392" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" "checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" "checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.12.30 (registry+https://github.com/rust-lang/crates.io-index)" = "40e7692b2009a70b1e9b362284add4d8b75880fefddb4acaa5e67194e843f219" +"checksum hyper 0.12.31 (registry+https://github.com/rust-lang/crates.io-index)" = "6481fff8269772d4463253ca83c788104a7305cb3fb9136bc651a6211e46e03f" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" @@ -1956,8 +2032,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" -"checksum miniz_oxide 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c468f2369f07d651a5d0bb2c9079f8488a66d5466efe42d0c5c6466edcb7f71e" -"checksum miniz_oxide_c_api 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7fe927a42e3807ef71defb191dc87d4e24479b221e67015fe38ae2b7b447bab" +"checksum miniz_oxide 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b6c3756d66cf286314d5f7ebe74886188a9a92f5eee68b06f31ac2b4f314c99d" +"checksum miniz_oxide_c_api 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5b78ca5446dd9fe0dab00e058731b6b08a8c1d2b9cdb8efb10876e24e9ae2494" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" @@ -1983,6 +2059,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" "checksum proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0c1dd4172a1e1f96f709341418f49b11ea6c2d95d53dca08c0f74cbd332d9cf3" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" @@ -1993,10 +2070,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" +"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" +"checksum rand_chacha 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e193067942ef6f485a349a113329140d0ab9e2168ce92274499bb0e9a4190d9d" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" +"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" @@ -2010,6 +2091,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" "checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" "checksum regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0b2f0808e7d7e4fb1cb07feb6ff2f4bc827938f24f8c2e6a3beb7370af544bdd" +"checksum regex-automata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ed09217220c272b29ef237a974ad58515bde75f194e3ffa7e6d0bf0f3b01f86" "checksum regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d76410686f9e3a17f06128962e0ecc5755870bb890c34820c7af7f1db2e1d48" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum reqwest 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)" = "00eb63f212df0e358b427f0f40aa13aaea010b470be642ad422bcbca2feff2e4" @@ -2018,7 +2100,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62fc0e980c94fe9ef795b1bb3874649c8c6e9bb67d3b90d48380ba24c69c23ea" "checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f" +"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" "checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" @@ -2026,22 +2108,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "32746bf0f26eab52f06af0d0aa1984f641341d06d8d673c693871da2d188c9be" -"checksum serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "46a3223d0c9ba936b61c0d2e3e559e3217dbfb8d65d06d26e8b3c25de38bae3e" -"checksum serde_json 1.0.39 (registry+https://github.com/rust-lang/crates.io-index)" = "5a23aa71d4a4d43fdbfaac00eff68ba8a06a51759a89ac3304323e800c4dd40d" +"checksum serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "076a696fdea89c19d3baed462576b8f6d663064414b5c793642da8dfeb99475b" +"checksum serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "ef45eb79d6463b22f5f9e16d283798b7c0175ba6050bc25c1a946c122727fe7b" +"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef82be0baf3ae45701ab992230f1f4889c15984736d87f37558aea3e4e321af" +"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" -"checksum string 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0bbfb8937e38e34c3444ff00afb28b0811d9554f15c5ad64d12b0308d1d1995" +"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)" = "8b4f551a91e2e3848aeef8751d0d4eec9489b6474c720fd4c55958d8d31a430c" +"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dc4738f2e68ed2855de5ac9cdbe05c9216773ecde4739b2f095002ab03a13ef" +"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" "checksum termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a8fb22f7cde82c8220e5aeacb3258ed7ce996142c77cba193f203515e26c330" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" @@ -2070,11 +2153,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" -"checksum vcpkg 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "def296d3eb3b12371b2c7d0e83bfe1403e4db2d7a0bba324a12b21c4ee13143d" +"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c7904a7e2bb3cdf0cf5e783f44204a85a37a93151738fa349f06680f59a98b45" -"checksum want 0.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "797464475f30ddb8830cc529aaaae648d581f99e2036a928877dfde027ddf6b3" +"checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/docs/guide/installation.md b/docs/guide/installation.md index 7fc21d1e..3a453475 100644 --- a/docs/guide/installation.md +++ b/docs/guide/installation.md @@ -29,7 +29,7 @@ If you have Rust installed, the easiest way to get Rojo is with Cargo! To install the latest 0.5.0 alpha, use: ```sh -cargo install rojo --version 0.5.0-alpha.11 +cargo install rojo --version 0.5.0-alpha.12 ``` ## Installing the Plugin diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 2db8bd9f..c04453d4 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0, "-alpha.11"}, + version = {0, 5, 0, "-alpha.12"}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/server/Cargo.toml b/server/Cargo.toml index 5a675ddb..95de7117 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0-alpha.11" +version = "0.5.0-alpha.12" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MIT" From dc7c27e619fd9b5860103e413907d36576a49b3e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 3 Jul 2019 14:39:25 -0700 Subject: [PATCH 0576/1504] Remove old crusty docs --- .gitignore | 3 +-- plugin/README.md | 5 ----- server/README.md | 4 ---- 3 files changed, 1 insertion(+), 11 deletions(-) delete mode 100644 plugin/README.md delete mode 100644 server/README.md diff --git a/.gitignore b/.gitignore index 816129e7..dcad1526 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,7 @@ -/site /target /scratch-project -**/*.rs.bk /server/failed-snapshots/ +**/*.rs.bk /*.rbxm /*.rbxmx /*.rbxl diff --git a/plugin/README.md b/plugin/README.md deleted file mode 100644 index f3f68394..00000000 --- a/plugin/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Rojo Plugin - -This is the source to the Rojo Roblox Studio plugin. - -Documentation is WIP. \ No newline at end of file diff --git a/server/README.md b/server/README.md deleted file mode 100644 index b3801934..00000000 --- a/server/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Rojo Server -This is the source to the Rojo server. - -Documentation is WIP. \ No newline at end of file From 39da45f0bda8faaeddb11d547fd6d88960ce3994 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 8 Jul 2019 18:34:26 -0700 Subject: [PATCH 0577/1504] Fix broken logo --- README.md | 2 +- assets/logo-512.png | Bin 0 -> 33553 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 assets/logo-512.png diff --git a/README.md b/README.md index 808f0f6b..95496343 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@

diff --git a/assets/logo-512.png b/assets/logo-512.png new file mode 100644 index 0000000000000000000000000000000000000000..75a65ed0363d67dfd0637cf07c3a6de456288e7c GIT binary patch literal 33553 zcmX`Sb9iLU7cJbeF|j$ZHL-1*lXPrnVoWBsZQHhOb7D?x^q2Q{@BRL0JWtoDsy@5w z)Y@yU9j2rpi3E=a4*&p=q@~1E008i>uYhA%=&yH+;(w=KA8-y*+Rgv~%Fq8^V5Nd3 zmH+?=Kw3;#&13ySAI3;`X{q~IV2l?I3{AvXb~>MQmbo(R_m5c>*osPK8H7YE>LSy` zF4;GTV3E~=$y$VfdePMYRNaZ+(BqS}Kq?{dHG}wVeo&iYJvm)6!$v#FY2PImJWe(W?fcN)9hB#*UBQNadHySrd8-J?8@Rtu8T|7+P^G0j z5@o-peqlS!@Nryk1$+I0M2$6M^BJ_Wi~W3~nCAD(06-@Om-eJUyQGR1b@IDA~6_&WPg0IU2NoSZ$i z$L2Y~QMjC610%8m{DtNIeQbO}!n#|vquq!H?=Ok?XMoAAR9X#Fo*!uR6dhhOnbEdy zz5Wfsk4*c&7YX&L%$f>jW&dNU-Pry;Y8S@r`v$CWZ>WR+-~T}bC^6q(Hd-ED7E!b? z_p%{);4ClPw$`;4UH)U4Nanz==>Ko*Q2?NwqHSmApqaRktRoBBjMGGnT}Ra9CWSTz zq)qPJ`~Mmh#17OE(|YLht^6p<=;IZ-LSfv z@F(&#!%>CW+gh7GcuaKvUpK$RM{(?3xXhTRqeUqd@=0+l>4O9oXi*))hmLh^5QD$s z2#f^-I3)vJyTgADm^t(oe7nXG0qek1%>knic4(kx=8 z)vtp9yCm&XAJT^EI15>X-V|JKQ_nh}kzu9(+t6s#qG+HlC2Zezbd}!36DEqRF}}KP z@x{IniX!qa^Z$uNZ|)rD+a((D`A>x<|14EB>y8^r- z_x{&~Ff?Ekr^;zXPC0glVv2PmwSSXB%mYt$LV>Lw@_!L@ijjM9sq0H)ldP9|TLP+n z!rfi0BcSPnXOHS+2mG3)l~4)iJSxq1yj` zRwnV&12mVxtQF0e@?zs|3fV`vvUbyvR$SV zrNdc9uGWdYn~yak{{Qw^E;uA$-iOeI`x6iIY57F_DygbeI<`^c&u?HvcD!#D>xT=>h_CdI4Od<#wOtC1K+3H%z zzqIUe(GOUgBOq0L8BNc$BM!AHK3c^W97XE89tM_-I!Pz&kCyK0S&O#Uho&&XlKgQ? z=yOFkt*vjG1%e>|F-X#dI-OQfsnz9KVysR`o=V%&G6J|(4*Z#R05u&-C3G7!jKH!T z`yN=Egt%ODvP$)raJh%?<>BzM9Sl%$`B+}s4;1h5sdtxrE=C>a*zYn>-1`fiVq(Xs ze5!I_1F7nQq9(sG-?4*YvpnRhVgC{GLfuRECy8*{-w?9SsNZIPTDFR4C+bh?D2fh; zwMH1)HV>TokKn`?3^Y8!d`Su#2l-mdB_bHcF!0`89@(s`As5hh1L})P+serw3ml)e zojaf^7Heoz-M$cws`~t}kI)7jL)6u#_*Tmb9Xe5r6sfdrDj1I?1)#o*nQ5PcllMB z-7!fB34&|R;w$_u>*%eyH9a!7e|_Si*j`D649jo7j;9r`o2CWs&QS3Z7Bj0R&#s59 z37ID@(tds{A=T8fy!mt6_?ngJbe*|%opsx-#815M71mbcv%vMbeNJflO#NyryaE;G zwC*PF=fA_=H;+2ED)F2JXEvit zy$I&FakDB0rhYcZCtoj_Br{n5`-i}a%19ustOdLFD>h(}Tg+F#n+^~~bMCDeT)g6; z+^b8ktB%9Mgg|gQ5g2DQ^SAVfBy*G`Sp?o@$3vMGw-WblIXA-cdBB2APFq>k`C#z% zRlW=pc;LD`)r=XCOfHqyvS3m2@OeSkG%(o)s}$ z&wN^hwu`?cCOdOpr)6tWeoNq?Q|!qM_pl3Hh`3z2UaMht{lc2e!uTc6kwP$ZB*;)T z?Y)y9Q3}VT>IPT!owopXu1oBB|4%kvh@c6ske#Pw4N5Rr(w342E>Tyk8oxi;kIeY` z914A{RI>XIf0oV#SCs~WXvI7V2I`n-sUd_)7QBv)hJEh!S^rumkKgqCez{v>?7VQe z2q7RYNLhm5@!~(-t59YvX`MKZv`kLIT-q}!2-NBZy z+N*AAqI{YhRey;6K9xl%M(!b6Z~^pUMo0|f9wyJ*C!9=08%JCr!MObwS5z3MQWa{?n((*jp`#A zSdZ1zJACOYSgu`%_`|BI26v+n3~|tH_!mBZLj3R#fQ6)36Y;#M#NOJya1t&An`5um6BMw4fP@DZsg>B(`A8`^Vacpq>d`p|Z*lcrOAJ>3o&?fU`8=ke zwFQpAW!S-EHMci0R#23yp_Ai(B+?3H9%65UD0R#M4Fw9>?jdeYL&xKB^+ zgfGtqG$0*!Pg}!&_of>K=94xf4jI)H<=hs^k_d0`4bfm+KAyz0aja4BX6^=duaw^0 z##EXRAPY`E&}#qUIh1JhMtjD!Q8t;(;QhKCn| zaRI#~T`CC7TDiBQcj#6r&@I|90RmayO#ojIMNee>V_bm~(&Sk8?A_h1l|W?S(hVcs zI)+Lrx(36@Ty5!PN0BcDgX_Kw(Wcd9;;5>{4G`KLFO4)qDxC*Zq}?xQ*HHodNKX`P z0P)frU)y^wDycTmaSqsvBKo2rvZW=rX=Clg>EPi$%Ynb|cWy5czT+vPZwj8&gW?Q` z#ByuNERjKy8jmLM{in2HIH(S|z)-vLi&V9Z}RNVX-{>4q)_dzM7a)5VoED>wiz zv$-Mc@bjBr2V5+1idHO@MT0!aVa?LMqR^dU8rj}`G)9J4INdt}w5LAcx`JLohzoBh z<)JaZobNLtJ#%_Q4fWU+-7il1;9fAu&kHAu+c~kg7#g?B51OW)Txr>7jNXSVHs@!c z1sk|F8i@|4ofW7%-d6|VJAsC;Ug$Fl;7LKHgjMbeIqi>m6@qtWXAX52#zfY1I4h|{ zsTqMVpI~4#(y`P`W|YzB;oG;~L1yD=W6D}F0rXbtqgz}pM|uMou}Q!z?H`4IvDnH) zU76LrQj%<=xeE9$Mt03$ZzzYp2h?o#VF7Sjj6(e0-ufTdggFz9Xr%c~_p*ZF#42O) zZKdPrtqd8z?vRj2Ja$v%pWZ7pVn7c3jO8}VcA+)v++VwdJIJRap5CD#{KOJc&yN%G zZH4y6o-pDU?r_m_^!?@}c`>2H@{_~sKUmM4XPjl2G_qek!W#p?3p#Kx!!dJpB)W(KGscK)Il1Qy4Kv7MJhf|{oUv|P!K544OL9&EzF1!{h)2LE-+S)H4R3qp z2N!jU*17jNuRsFFpt$aYEZjKAOUyTO>D-5DqW}^b#>iE+IciaswQE9-1Y zrhO5p^8$Dxe#bCDb}pSi4`Uxp=M0*^z*B-Zn}b=uwPA;c?p;p|*I!^)wY+*GL7@Z! zO$ACW9Uxmn;WFcny_R)D1B~ZJBk6yYT?F5%r`FY|s&~kW3zu9X#=C)7R|iRg&<>zN zL#ncS$9A zok`_`#ll@GKBO%^Nd_$2%kLSe^$2KuCNDy)jOJ}eKkrF{+)_jevyT7Y2z%D7-s=jHM06k+EZ z)r8CD-}_XF7~?fV>G69d-8;H3u&Zza+dabtfNduXiA!=w!JvfoP;k}Xt?nZzVKSS< z8D1Q%c@5;Wun@3t*|5*Q;bY3Wl9X>%+KE7tFhi)$>lGrssfs*7`GYr&j*}FnIqt01 z3Mq6=w>UqKqVh=i^a6bsSSY32XY4~A>EjoKD3jwxxyIn-dl9#HH$ZN7xMlyiaeS?h z&7_~A%=`VoVKug3@>CNRGE?mmiBE9Vop?j^x6MCNU$ckjr`bDrG7K7B&YX0@tH84Q z@@hL*QinZS_bCjh7xMZnb7XxD*-Cb%J2ad-wA2TAJ(ZfF!^+Y!+&pR-q%uQ%Ts%$LUu{-2{*>rX4lt~(D2l%d5JX1%Yf1L|T$Gi!>=xS0oO@K%m=^GL&we9xnIKekI z)+4Z3OZUOdnz^(Ae}~^o$A)}j%jaop9LcNaP_+V&XNS((d`DnL9^73-J0a>%j!BZB zal?k!42_TA=iRG8iy>|oOIZerL*zD?=l?@j9r?(CM^pBi7o0aPtZ!E}Afx724zLsg zgf@Ou)}(Ab9PHm^`}aGQIH!h5jyUzXL04bUkHUiwX2FeK$mLui>iorEs5Z(Z{Y0X5 ziSHz0*jq6jgh0*Y{*UljnV*0!t`Dm61;t``hIx^^uYF+h&7Q$^R_Ru7U=>n!0Ez)2 zwN0%>wsNwTmcig>$3A7EiV>F}dLoc|`(rj&mMSjnsqokkN%K-6Sdxe44^im?~l=3f|9B45Xor!JG$!XA9`ju!nQjp82g;? zv{ag}FirFpnoE;6lk^}lS&xI^Ax{HBnT=(`SXX4MAzPC5}{#xx7R%Wa)yA6?C$mGXh>$x{u( z_KB|}P~X27DUkijTmLz7rabn$c;iv*x1@!hO`CTX`y*-l^oq0=y$$xYouTtRLV(7~ zVxl-VF$%nb4RPBIlIcP%OZa#NeKMSDR0Y1->{-?9o1XEk|4SfIA+E%H@Sc&_6QBL zocj5lv;-s>_fu8ePggvIR=PoBtgd8*&O&~&qz)8K%D&*OLDI|oYJ(#K7|)CUERNsS z91=dnX5ablrMz5|mU%=WcEb5t)7tit{2zb%q)K@r2HQd4mmBP3kL72aAZ;p0bo|75 zrv5xO%w}{{p@sEWWlBL8vGT;rACwjDh~M_E)C9 zlY|6@-ORdPZ52dKO|K8XnbEeRNoA28Z??^HR~^E}I<8Fii5`oh%k%;%E)ssj!4?Dt z3e4@n&S$yUO$i2bYxx3fpXMg_$zh|Wfx7+H`g(c76;igfaCO&`?ayXvv^AdDDjt0R zfIF15%<3f&~=T ztxF_N1DwO77RsgNY7PzCNSAMj3kS_>mdOpJ@1!_HZ3Zic(xMC2l=-7N&_kX^JBM*0^Q|-Uy}66PsYa=4aoi~oG2?EMOwJXIXd)6)RsBX$KQBL<6QV+sXL9ve z$y^I{-kHzFMR98>v0xi|42+P-t0)ZoeLfE1pD0K%a3%^=Jp+Q%h&bygO>6uAV3 zBjWMBn)Ucd1e0G>%5kC97GB(Xx7pj`PY%{#jxw5xqDuZjOo==5)B9Uof>2am3I=Fz znIuWv8uvSo&|N254o_p16ao|Eu68G7&!y$%@XOdY9B0aAB^r3<~P^{BpDeEib09??ZzTeQ+ zxTn>JIk~-5uq>|ad;g<0e!Fl-kM1e@Sv`1S zA8vRIm6O_ag^Atez}%SY7OD^6ZkoWhdMo|@M+jB!hi9Qd@$vBX1yBWFjBGgCFG^s4 z^X|JsK?eg*T}gNCDwf)riG#?I0I^d;0T-F{+1>o%@73NpySZE4Fy$8%dxcVBEIYZ{ z%?cZ&fqmY|htRbC?}6SEyer|ajU0mVnmxxP9|!RDk5>|^W1W4IOFt}(zKh-K?Ue=4 zihQT!7F_uy2K^eGfBD2xCA6BWcSebq8iM)Ti#O;6x(UAs3~&n;5QC1xPZ=?LHwQ;_ z<^ICgcJmHgYxjUrVMQ5xUx}UYrLDUTa*-Rmoe{LY@!XkAsf))_n6>4_huWNM#}d&| zj3I2ePRJqcO29ktEwJ2!$Kh55rHF(nDmll?^&b^ZjJ zGzT`I-V9mU@0NOJsc{R4?49t{UVU_TNIW5EmG9fP^{6|oWwahkp=BW**bW3vz3^k;Ws5lnn)Fp#}-hw zvrjV3%qiJp$wY@d8$g5m+Ex@uBN_ALffu>N@jQ5UlOOTppNF>wc?0)5n<16jQ6)N8 zIwx>Er!ORV{dH~Zqa8R7nSZb0#C(=&T-Au3Y@LWnti?(*UwO2-!f`AV&n*KZhg+5OO;*juuW;i zB`F~klkb6K&IgPCp-1eAtLX7=D0H^QQli@Bmw)Vo^1cbnG^l_3!I)rxeltzu`E|yc zk8~aFk3YF#-SU@?5iBmNH=3u5f=0|wV0t#|i(U@+1>fjxD(N8rg)vGcym}U|vuOXt!V26PfPuC3WH#rI2 zKXr4d+G>;1O|#JS_Y#Y5nZoEip1C+acgaVY<@B_=Wg%Pw5}DT%w(Z2()`v$6#U9Bv zaW`Ul%SYxXtHNn$4WobU|J-r{gm$D&{icl%`qxKCk!B8yZr#^n$p5mthx&ec^(C%# zFh15y9I{wBti@0!(LcTM&bR1*?P_YoT!}Lv^jf|l!TTyg-(~h3=}k5-zG~v+Q}#$N z|1r9p!bZVC1>a7T4YyC~FoT!80UwKoY!TSD_{vcj8&voO{>c zRg41wKKZkeKEwIp&h@Uoz-J+WA0MPct|a`@DUV8!t`b7MbNfDR9WhiHgi!dJ`m#aJ z;vz(MI=dIlvQ;xZ>vlC(YN;2%AH1r+rt4Xx>$sg-H&sR-9tvzL+6Y7PducRk{Ho)U zTls0Krb(r(U$Sl$VMjo0;X& z4Sm>j_DAWAv3Hz~o|#M|$H&LdhJ|&q3vY#v&vv%NlqOwbVTcQyCE^Sv)eaD|zu}}VukLHJ@tJk;^G7+30co(` z65yAq3C`bb(v$+HugUraxT=536THaDzwi?Lz__p-W-WV9s~IIo%T^p06tH}#qvEqX zMBIq^I;4NAHTo91d|bs>-9_-xzE!l@=tuVeV6`o4T&Sx901ITYmM`LMh|x;dJj)#M zpgD$&bn^*gavgCoBM5m-8~OCq3Ht0_;=4Mp?_|SOzL^*{mfWGZg>m$uq8hvYyboaJ z?h0SLItq>A;^KwQVDO{^582Nt-^sp%_zx<)Ee=76X#3f@zYx!9z}+_)N7*;9ms-qb zLPdw|zi|697@tM}|Ge);Yc`X&+TH9`ac^s+CHn?IYC25hq@u^F@_KY<^*N4Kn+D;E zz*L;c5Wgmm_nss$t-|*hDpU@@43rHNup}VzIz~B>{bWp|21NX_{FdwN0_o+SO~zsx zEQwbxC{ZvuUUOpk4p3ak|2-7zHl)YxLrj5zE}Ujo!X`v6 zq@_A2+lxuqaXF2DX+wAf(Kq4nSF>}U#auto0og&36#xfd|18s;&IvC)OKji*e<7Z1_YPgeu$HcHeXVr_X3XiB>J`Q8c;;Z1O@}VCZ%Vop; zd?tx^O@oKG4k##g;RPYmRrsRj_&{CUA0MaZPvL;#$xYPm1r;RY_Ht0Y$wu?41m|xN zH;vuJ)y6X}9mNi$YxZx|rJ~E4Vr~$aB;R{9D5#soi%Yq5%=o0+zzKGW2KHZRP?8sR zI;0ZRhFfIv5qB{ns2qH{JqOyiiCoNl9il_<0Y z18S)Clpm3#-H9pEY1^3zCI|I7$aQK`6v8hv6o=kP#qXw?Y_sry2R2>s>LxXHV%$UO z2{B?}1oI+z<){Cw7@nw*NJvNpXd}p}seSONz(T%&Av#uva&vmw+$hN1E#TOG9}I_)UcK>nokK-SfTN?gzC*GqOD2Djm}0Px(|us;5Ih>yjwS7 z(-44ai+^^`SX~HD2WMRqlOeeazI39Aai6?MH;0wR#e1sGERvbSQq5*vITROjae$tb zL{RWNe4MTn^)AP9kN?;daP58m?B;_51AbfR_^nFqvzR)ABhSrJiPLHNx4zS+bgUv1 z5P<5k9xb!Ubk*aJDT=1Ix!bG=GrV(7%ULUc_bp^pqeC8fL;*guj#biKvoXl)ce=iFQ zm-(9fENmZTAzMU7m9*&bBB;emO(NV_!=xHsB`}KO}LrusOkvH z#b(Esq<{$uHe?9jL%J9-9*}hCjVZ<_Hwfc;KV_%dPx&S&ko zM#oL=Z`xAzSk;3dx$F5OS1l7vSCAF$oej-^BYg?+x^-yZkK{P9XTXt~IWwiQaYcMd zwfuNS)AXPr^wR#{CQ6@=Y0`*$kOl&OGRJi;eLNN9hF_qhpdF|%V|#kb7F-?N|Bpz+ zCq8ZmAB2tGG!s-jW-P-Hv!5cfIQEUFn+5F_duL|be=TFrnju(aw0 zU1aeIspvMPDpp(UVkizBR@m6?v1jk7xxtAco%5tJ4UQn^9NZ|btL~Tc9bEJ4tJJJn z2CC+#&jXP->hAY64pjT!x9C8U2KZ$ojHjB%7md^L`7Ard(EE_Gv78F(=34Lq%9c#$ zqj7+_AXloXU(sb#;<#GR#;_PKg3P%rP46OLu@n9c;~q^&SSD%wM7C#abV_Li~_ z;aS&V?!99m0$DCaimRi7icNSIL_l4eplO;3L9?|9p@MI4AwA~Ge0n-m^^ZOI{cn{q z+*3{)5RjAg9$ofsT3~w2Z6$3N^9DVmi%6>)(A7Ky zwcm)%5o^@r2&_Y9B*g62`^Ke-#ip5bTV;ST;O)^L)^!M-8xEkePOD&)b~&AlI0Msl zZn(MRr!;HnCs_P^6H9R2V3XU&wW@>ND$n|o&Y%md-9*Ig6!YIr(=$;pgKq0dJ6T@Q z`6hd=C-Igb-VyrHWhj;q=>2Et7{LV|?10rl$>E^kwkAM29S2AGht#W@Mk$1vncGuV z{m&|>LokwAcT2NjH;32o(N@x;s+TfgOLt|z=H(4YQsONGtf<4cM<83rE|}0dYUFd2 zO!?Mb>dU(XfBpN6X9uA@(+{eV2|e#YAD$w1(PfKCx-(|#rXM0`#?H4l)>U7XTe2p^uA|-Rvf+?YSjp)WAGdy zpjSCU!1^bYNYpVTke4@6JJBXsu46>V%TPP0N~mHvow*4jtwxitdGaXp~XEfLZBDVw2+jy#LFE%^2_$J7|xa^IEZ$UQ~SwP}JL;pOMz#qW4HMaNm;WxoyifP5kFO0p_ zgv{A5$Y8L;hl@&$iWQ4>UNK^U1mmiqekn=E!_RIzRj*$W1-YAt)pOdaJ_mQK)#GtRCUC+pgBrC+5r>_d-&2g}N(Gc$-jB>VV#*2`bjh(qB&p zq+KDH??jQlv@59Xi;e?wPOL+>1j9UDJ(0lK9ZKc_UB0N4@SfBgB99`=^Ssv&8Fy8J zt%11+vZ9t%#@OZBx9&E4sj>=BzN4loACwA3J3JeEbCSXdtIcru33}D3Y_51#IN==Q z9xxdC{B(}5$(XQXKiUS7O3ZfE81mWUT`8m`=6!+RKiH&SLh?sr*jrkzzNaRGEv$S# zlpk$BJ@Ybvau=lkq{h4|S!h0GU(EXXVZMqbiU zeNfiG-1mB3dRRo)wvV~XaOR-OX6?iP)h_1$_?HHxGo?Ori*d9Lj&a1~fiyJ6Zx)^@ zl=dQm3O*Y7UWUbQELHB%pEacv-u2sE!r#QxpjpRIv`rEgUQF7z{^xG;J zX6odSH1dsFJUYoHjtXR`$qn zz?y_x!MZDrlU!x|ga9WZP}oc1yD4*aASI1IS_D~e+&~~)5qmk z!Pp241OQ|*q&4uT#D?ddb|i1AYz)p%$b3H@g$EtJjQ5!E*`@D2xxeHqpz2(%bUV8l z*H8xjsBa2Km>7b`grJzVy9_608o|s*2@st#B%ncFVkUg6O;UST4(>jFMQzgvrPziqJTrc}K>aGtt2ZRI7oI48Eeak~mFkE12EMbWs zoshe)K(%iv8EV^fCgA-8K(Ng$ST4~b@fg$-f(USe7sy!8x}(~G+l5zBX37TgXmfDJ zg5!ihHuGrU+~fFaZf^!$I!P?o5oEFp3gCZ&5l&`GSSUH(y}2po_{A?bn-PmX5B*bQ zTq*cogYv3JV3a-?=!^ZA3Eu=+uJ{eKUjlag!6F~kA4 zP32p0uA!FVA+5lz%y=pnSb!515~|0Kj?V|~XGNVnRv)I5`ks7$Ey64JEbMW^qZ{m& z-3K^mu!pSg^2Sb2IEzGe%cHR=C!IgNRomN$-$=8k*|D}na}eQYm?c@?n>rc zO&z7)omEE{E$y2%fX}wh=mUZX}w@{riM`b5dO-PzI+o(=A7}^?q=sa8{^@h$;Q_A(a48P z`x%9|De8m~%Q1X8$nqD5o*-Ryj?dxfr+Q^2wV(BX3@6%7=48mHOcGFvT6Ye z)PDw-nPhQzlqb{;XvcbsdyC(3g@UZri`pw&-)`P;{C?im{bGg|x#HUSVmuuA)Bl}9 z$9X3)i9M$PpAni1c7H>aI#uqeA~vABUX)-kAACE^Z$ZpnLH6~$W$e|j&>G0?`B3>@ zG?@otoSHpdu8ax=0rz=KTO{_v?&AHJJ~#WYf3~NX6y2gstx6u%8LquK{Y;@87KQs3 z7Zve{0nbailJ57gbEau!aYzh5XYsZ?Rh2XDsM1y{l?P2l5j8W=!D!GPtq`vzb=q;$ zBrEz=G12(2=P;Rnnx4pSHUjg8_a2fPJ&n*dbDd`)_Rdw8Y2TgisvX!$hu%->f2~7C zOLhK$gIigWbRjM`Fa^gc-M4zvt%kHC3}2THmd)%rXYN^k!jWXxEZrRnkOK66TMPRe z`qEOGRE*tGXcQe)?vG$8=ew@%VVso>CNyd)$gT=D!ruL4M*ghmIS30b7)xCsoje8A zTOHunBBtCTA-Qf*g8+!6*PU6I>onnCEYW=J`7 zqtkw3*j{-0%fY%BLU$}+s@Vg)XXfd|wJaA>^>Zj*4+OrZII5GC&^u?Y@vBScQ^4Ln z*(k3)MOAV!{(1{e1mrP-iDr;c4}e6#AjR~=ZcoBx9+ z>Mds@ZxrZ0rDcOe|5YsEerA==Ed{7`yFH)S*th1FlMrp$m4cOG7s4;^GO)L7+)64X zw!Gl?JP0900$)^0#uK3QqOLvuQs>@)nA6}!Fu|zELEDdz0Y2os({sk2G317gmJ`Xl zwSP^W{Mv0||3qT3ZTF_V6qmQRYw*+eN|azd_z7`tM@^uc-3nB2UbhyHmTX*7uMTwu zefMrCpw+D`MNJ?nXdd71kXJ<9G-|mLF>-*ZN9I8B5C6LrP)MxJ$CS|9(P^%T%~!R= zf92Uaq{C{HX7J^_9AHUU{=>^AM39}PrrYu3j_+?Ky^!8Ql+c^Jh<>G_obux1c~cbw z$GZ~V(P{GaDAKxHDLoL&$~HOJF*eBQ&u69XX4a?W8Ni2hkYC&irMD2W@6JAo%6~?R z;4A770ATvK)XP4J#;3JQhdYq|3^h~%E%pt4VYI%>Z19 zA5v5@IBsAIu80a3E+&&2B)8R#MCwkZ*MleZ(%!4-Rmy*Ju#to}EL-dwwyLNOQ2i#e-%Mh%G5o4=&9sPoEDDdKqmJZcDRTk6q)G!IZ|N>TU_jT zrb%zmqmi7H2pXy<<~bd#sOZX`aUJOkPsL+8-@wonYDdmAi3Cy_~|TKH1ni>@%ETAH&m!9 zS~Q07P3K)`z$GLDt~37k*nhgSaM#qGg18M?R2VKVA3)g@g<*lXc?VqU&_PZWC;9@= zlVos3mF`|xwU%_Jt6Fl`b#4h=>vtmpK%oIh`@N?=cG`!;b6ffP zWOHSoK(XKep$E>j^Vf}iCZ-Z%zbMpe>%WAYzOz5|-Qvo=mau#joo!%W-{`ZAQGb99 zY7N#dH{zge(B}Ih#rWVE{~>5*KDuSO2vS+lDRTjBLwd}4|_b=7Ez@GyXD-G5Bm}m!tZwSnKE&TU3J)xgndWu09 z)?Sfcf~d=m-B#m6TO`*gCJ`?&Vh@l6)AZJ;5)io8f<~ z1wu8qML|?j!<<84eU%>1$B)APnS}EJIk427-*Q4l(OED9&WFB^wnFgP$2Q>ESguE7 z0s9T{Xd)})Y6W3+!zJY4m$GQA_L8RdoHzW(aJKOZ1LBn{72*yI#?et-zpMJLR@9b( z>RbAHl{o}L4ek|+MOVudzFTbEjMt-pFIUex{_NvNph5;>Y`QR&j!hK;{USx|{3FxY zUI~X?RSl@xvE7FRzWKx;bN4PWva~#j%IpWb{$k{ccY;l8% zJLZ|+^vk>$tmr;8KJT-`!1q_c(7u;?_k6p642r_lqMF8hJ`~2dgqg^Mzkk(HXsd9| zEtD}|A7rfr0})BLK7urnzZTVK^y6ji!&~iH44a1WGGf;7`yVg>tCVod7E)^0reAT} z%o=(jszC(vA%pXG9R={)425V1E;lszhA{~gAk^Bamz&y}mTis&b@N)lhvM=M<&m#^ zOj~hSA&VPPW4zl+au|8paU4gDWq3;_&Fh3GKZB}I*E^T)oq4dHX!pppXN1R*i{0QZsw>JXbZb`P@Zx#C94Nazt3W#n z|2luiZqaX{;zmb?|5f`ykKvJB*NGfH^OG@({Q*gigHrBcOhPQ)HOY6c=#!SbzMyK& znf{CH`dVeCh&wmw-`N8C7+^OCoXPm#rj4)(8Ud0lWbGu4+{8}g*bRi7VWMF z;xkuz+(w7?yCG^@O7f@re!Mqo>Q~v%;~)-Rf~)1#M6X!R44dx`uM%b zQAVQ}pbn|U20EgGJXd3&(Cv$~h_l_7WUIsAxoy@>m-k?=xLC_rX{CJGH%p64ZBa6U z^7D6_=ONshrkQTo@!k^kD%8d>DyIvfN_H)1rZIVs609Ksa-zaBc_auK0Nk>~TikDW zqhpTeauo;ww87BJ79vv(Ck3#LP|)P$j^BQw}fJmyy|8v zgIzL_?A}HGV9Yu!0)<5&aa>d1(f{)TcxqzVz%Up>8yWQfRfVgKnK{|U9Y#yFYfQ*Z9m+@QlQhDed=VN&e4xL|dxp)O$hjcUJXvnu9IdSNSb$%NRSrg(w zJtyJw4$_2oj>Lr~j!~-8rCp+U<4NYk@1|<#>vT@WG1q^KVAoh)^0NZ?PtMbbdi2=V z+fuTus1}CSeE;d*2q1mpBOWam4D{zE;nht{jA`-kc78}#T}PKbA`|x!pKslyQ<9ca z4La1Ac*f4ioR;ywKNbUX>@p(^*7#uDR+3VO)T{dci2BCx%7SL=6Wf{C6Ppv;wr!ge zClgO>+qP{?Y}=Y(;^chieeZXl`+q;(d)Mx+s$R8fwIlZ!7r#v_k~y}{;>aX~RM}0> zpRALORItX_T1$&>-vcIAS)!l7hATUe!^w0w5-l13ryQ%TzO3~RBH&V`b@B1 z(k_doL}%fJsjUGcn1moU(#+7kJDPj$&M~6Uq=*Jt_e0pR^It?#Gb#sD>=$NeBJ>`{ zdx)>hoiSUdCV<>WvG89WSTV0KjW7L`0~f>9#?pTcCis+2u3?MPT;rL09K|29taf)m zO~95J1EY_|s=4~RNu;xfG+C;|=&88&nhbd55YH!3KRc-9JP)O(?RDFO$VewBPlba_ zwa`pPw=4KVrzg%jxrkrg7+z;J2S75oes_*lPqI%_HN?L=EFXsuZGe5c?2^(XxcFfB z@JCccgoyD^wuy0@*%lt8vv%V13C3?KC2W^<-UH@z8Tjr2^(Lmz$K7|Q2Txfh({8U7 zW0ttUc3OOW1lLHjfgk8Vb(#TEg}}Mk(v&N zJiz#QVqK4U$COk_&}C2gw>F~krqs#9k67U|)J?k%q^t0oxf{^z9_Fd(-6IdhT+OCJ zhgGepq(}7>B>4=_LlCaEy4)inbj5(4>Fk)pWqDm)!Fj5Ra15PxT^3^SB+nv*aOPlM z>(#j~h?IKJh|OyAIh)O$D86~>mh;2IFsVvH;$o~SW-wfQ{;aV)W9pT?j3GkkC;1b7 zZJ^fr15o29#Oy^5DOUt8e|l&R-vCr@dSKT^UtGN+AhX2N{8UU|1(rqU7ZwDn+a~$Y zbw&$uyf71=H!|A*k#O5*7<8K7JT=>{6g4jZ)-%!R{o7?vs9iw*G_?1YR3HDq#T~J2 z#lHX}YM>b%p??~?=B)xqS^^y{Zrfs^aqL@cqkn)h@rfR^tnpHD3Ogai@1K}i%K?~! z>4_$a>%T>uN>dbLVbZU&_A+#m!^GO*IV=G_saZH0I&$u)P+uD0F5iP9v|aZV&mkgw0=mZ*Nq&F1Sq#Cpi^Nd`yboeL zo+rM%%q;|BphI7MpJpS=r^7LQF(VyM0MU%u&(>SMCI;0)Duf@vNxIm34O6Fo^sw?g zBC10EhkjB*$bAM)k)goBv2ZU)Zq2c^dbZ=4sL|HDhz;cu;BI4Rp@;V2oS`FidL9wj zCoUm-=_l8sXK7Xe{_c;{N1i_-Sl)g4)p!N9%bQoo1`_GWPfhL)l4}#|Iv~eMKsghxPgo*$USkn9X#F&1{lsVW2+W`b2E#xab-%5 ztqqs07T66AM*TtN9u0{b)R0TYnAIhV1ZCupYZMt6`3}6~bac?xf))Ki4G`))ur>zD zz#J}9vcaOhf?>r4;AwxLVCv8s=0W9XC(tNFhWhqyHdskt?gwvexAIOc>(rUO!jxh88_|= z9O|u4pqD+V7kNu#Z~v1F2cxa}zrF_Nn@J3I=3XP}M+_Mjq>H$?qnJG+#-TAnX&7Gk|A^G6nUEQF@La$Fz1y|6+lcTL9}&-QPp*tm&N! z#FLue*lV~#Bds9@RL#TdN-fC-9c># z!Bjd?7WK(Un{%7ms5CT4`ocHg!(?Jds9~Rh`Cx!l`{w`;DQ97WiNFh z|3c|=EL_NO#(hM|DE2U|5a&P8C*k4a$4(y?C}UEB87qe=Jm1Q}B#&MgMG&Z}bo6J+dC0F_OQh<&& zs1u{S&EP1rNp~+;Xt|VUe48rj_6;kqOi2SaVYIhYs+8J1V#E_NHfR_hCV^%C3Z>kn z5ly_1|G4`48c;{w#N}hu_I%1-xWJ>(t=yKm+NN+NPhj?3-}2>(bMTs_g3D8_Z+L zutjzpsOBpRe)C=X90|A2tZO#@8p$tu2yB!IhT7y1=4~o)XKq%KsWs?4&rs?p(FKg%Fi#H)|v*&y16SYY* z*TH^`u3{`ik=TYbbIqkWxK@9#Gf;NYn-CC4>I|GpChS=4NC-K=3p>E?jOWPSw*mWb z74I)g!J3j0ov@74*_<>#3iyewfN9q&Hw5>uU`~SJ}+v0MY8v;z&d?3wTLoxizg2T{>2kQ9_;Pu(;Xpd%|tr)-e>e|em#4;4e z_IKVm#mHcKf1mb$kA|1*to2J&oE?39?iXU2XvO{yQA1uyeuZbfP-5g4sO~gQ1~U&^ z8YTZ~sE49IKmE3wM!}qf#ioq^lKc(T{2QP;+xQ(#6{dN0lj=7S6oCl?-8)H5wtn5} z+`_uJf4FtS+2*+B^+Qb}+MHSB%~pUYjDcm51Sva59>ugWWP6trBw-L$zo<$alD~rC z8>j4;c$|qKw4MgfJWpbNwkn6t^H>~*nbbu@tI=8 z?B&!g|F>;7d|4C0To0cRIfL>?X?Wd7Zb{niSL?DakTmA_x3zDYmzLcwTKu6ocPOW} z$nNuX(7ax0rn%)rGb>K~U5EBM4AwzCxzKa#RRgNq@_2e|&Rf9ki;mTa94@|#%9Z8b zS8xJHlZEtm4-Zg&@FbC{cG&l>ytPr7jxhO|rw+)6f(Ju%xe<)UB-vTuLxD!h;b`SK zlfts9lpcOIbSCl1QEp-HjDL6$p!yY#V4kPiWjKR;c}y3}{_|m{{iI!x0XN9Wmh&{d zrX$-m@Te8$cgpLH0wrXdor6CMH(?8m&Tk5HMNm@S;*SG>p@7@fl0#I5ZUx3&eTxXA z=%*)2Y+dGknO=RPe9>kxn%zlefeK|U{SQ=emTQljp7YLYV#dzNSq}s4 z)W{7I068LU0hF!E760>4i;ClHxjzU$nIaoG`n0bvOZtc7K&o-yZ6p8K2 zj|RR^PfD(gTw6p9KHQ~2xVppl;+Vc~xj5e5iQs7_P1a5ITdN_TFdAT}J87Tx_H9z@ z1-5%h!9c&h(yPyXAN>68B@6ePbL9L}@2}O0x3tmffjo%`A1O20!`%C}X;A#%DsWzW zVt%GeQ%rcp5ItmV3*X7WGH5Mf5WNEeP%x_g-qgF=Fas@5gPy=?o?Bj!2@{^|)U*|@ zP(BPj#T)e)pZw(j0DqJP+gJ%k^stE|2`Et-W$zvPyae0ij{eVisg37u4YKZ;mq#D~ zP{waw&S$Taz+zTb^1@|5q?aSj{c@)mb08A~V?w=pP!$2-+U=RcWoQU8k*7(sJ5N2>=d)S_rkHe_k?o=0g4=6>; zCl_rY)5?Q+P&l4~1Q4x#b`cZi`lR@0ha!yYn#KSjcj*0(zV; zPf|VM#b+>Cx)c9pqb1eC9PdxmF*$z5k6z6|Ef1L1&8k^VO@*m<^M4uSMT z^fa~r891?w_LBMibX?o7q%e|@EA=FD$TU5KYIQOM9rq_%e3e46>#dfr$;Dd70RNqKH|Vs zUPpKN>6u?Fj1Bf^2`-ypU=9g2hSGGU%O4T+=emvS9C5W}2mqmPykLPDRT+Dc9-&#g zbdb4LPU{v;xwOE4<`XU+rUg@1(cpjzK*Vq4sXHGc3DrK5qt+a&@+(BT>iVBL3kA2@ zzvk?UI+j_DG`d&`O4RwwDMg1E~hQhHcD{ROmzI=%M{iWLM4$&9R&Pv-V@8 zxUkR%K=RxM1*@I9l2lx% zo_7Gz*00yADLXn#%tg>qwU?GR0e+0B5}a*_V8HHceoRQ}*!0(FIfvuY(q>f>?tb~O z{uy>af3^qEb4ZGr^QaYw0aL)>B8*zk=<@-t=C}~3c=k2B$LI}ThI-~X&*$!i)vA`3 z3hg$VTrkT$siWhRS$@zZDF;xTS*g+~Ddh#QQ9z*>3cqXpILzvFNfTnn+_LLSsy>OT_YuVsv*R)_%KG^#V8) z1kA+rAq5a)b$XcBx$$@k4~P5U9F2t-xgaiFgp!WG&074C6b1)4gkfm$*h{%4`SaU} zt<$kyY-piFpnF8FC@`}yR17!}Z`UMBo(Q`(bLF&1{kF}>9aEGofkIrZ}{EcEs7|fcX9P09X&vAET0VXQ5Y|Gy=#~(YsBP4#c7eEIG8rm3s-B zO#&6t1}q|7Q(d(IIGfik-@n+f1B0TZy}*#|mylKc1zWDu!_HN#znO)l6ldgqm6pO~E;R{L zYeaxK!_eSHFhy_f=W*crGflFAO}nkpR3PEjo|D-YKD834J5@%tKi1MrU9`5Jc;PXY zZ&f+k5|tk?sG^J}^ESEWfHjnOAx`XAh@E0xodrDCE)LmhWz(7sI*tR}Pc)w)%P9Ui zWbl3_L*@a@!LykaD^JAJ)f3auzJOF>M59aQITO)3=`~8*M0J33>H<~U-~ccaFsE`E z*Om*7HK=W5?fL6;BFIl3ydiHD>T?U|ZjqG_%g>I~#Kf9L!ka+7!~PNZjOdz#`Nw_} z`}{6Lyo1_0OGVmJ$1l>J%PE8XJn{_=V{}d`+B~oC`Gj3yYzV#Ej>H)%846gx{C^If zXK(1!UDW!L-h7MR&OV_DpteR9G?BVQgaD*88J=6og(a!K+05DZA%d_jQ&TDY#9t({m8FW@UYEp4nVc+Cp=o@)dmAy zP-i}WB9Y=;=Zj1nUqOlk%pI-l@!ffMz!!YX9g#JjmnWu5Q?W1@fQ2HmZ(+TC+@onV z3E=a#X}vfZW4^#EE|;zcSz1z6f^yi2d$h`t#%6jB%j=%F+9mFIxB|jg&|Q3k{@t|x z_*Y=ErK_Q6G|~Sz+uIY`;r2~PK8BkOaa~j%GC70no-QZInLkfvG~T{Id(OFD{lQ;}JuD~h%&qK@4fK%ArpSh;bT<=jv3 z5at~YnUBb7bm%RQs+`N0H|8Yq0lp_Cf1X|cOk|4XhFJgyWIbYa&{Zubr~~n2JrxD* zOR+SO9tqUli5bf7{QUyUGPpK|6^YMUthAxxx6CRR0ovF*&WBB;Y4+Zk{20Bp_t4NK z$!@*~*RL%K)tta7U$I;Qb*lP@j*nZVj4U=#H zlE#~_@cil$3UQQ|Yza)b+^z)k?m9J961F%-yd29}riW|It19K|)I5-FS8PrN!CySV_6ywF?hH z*1Sgs*Cy+X+xJD8Ih49jzWpdU^RQ5| z01MRn1F$aHdenV&T<>=0tXdTuQBg6F-*{;y#VgC<{?&%R)hdYV3|0Zjk4YuHQF~)E zOb!6(GGNL2Dhe`qmN}4l9^>H&bYBs9ZwMYzVNY^o@T4qb#E+=-675+_q*VfUciaQp zwDqrjZm8B3vO^%Lq0nVLz!@Mjf2`@i4b3g2rs@ycy%q=+B(ut_C$mn%cG*qJ6qrNF ztj#T;%b3_^Fsn+0QBXxAf=g$wrMk@q)D{QU?2oUMndd$KM7Q;Q8|``CddT&eJ^R`= z3h1`lV3#Lvq6tZdis?$_CGh_Epbz&jv=&=3{QaXtCZjU|DbK&tYO2m0dd#AI3=(Wy zo>HtCFFabW*(Y046+%w~!0&Rc@NkOKaXplX5%{<9$>O5^8ou-kjcF58wzkJI5;j|W zB%XE^WjTt zE0TCpq?rG2fwS{QUyc>wk{ZA;J(^y;9{0pF9J5I@K0IpyLbGtdgg>-mt7dGuc0iX= zx+1^|fNl4h$8$5(iPnNr;_vVPZ6RIoRJ?wkw4mkaB(i*ZXdrJPU}lFW6=4mTe`_PX z%K(sL1ZoC!jD!#{v9vB|8a{r8Z^zP|saK}dic&rpr2Yu`xdNnIvb)L-Ng;TR;v0I3MSl-w$pc?3YpdrwpC1NEBVnm^`&{XrxH!DNWjYvm`pxKpf@N!NQ+N z0g5ZVz~}az&khte4*NKbH%L?nB4KFU*bbE$5MAK{pO(b>hu}R-BLe=U)(hV{2S;CY zLwqGR4LO;0T$(wzYi@d9+3G8|Z@aLo8t8o?@$#1O)9(vO@_O%qT-Ronia;_f7 zl+9Dva-?(H*lo7OYiRxkfU8`!(VT=2ykg5cCdUpu;fcrEz4s)@SK`Yl{1AkQWX!be z`I-C0W}6_rTTcp@Tdqhtj;5LOW2k4T;hBwa!R7Z^L$Y8dw^L0ur%T)}w&QA&+dF%)U%*el9q-co| z7Bg3x-bkLh!$GBeb4aW|`xE$j!=bA*K?n1s_8I=w!}+r@#o#Cr>!+!jPSgz~G|P8+ zN=&n~Nck$0Na8ZJg+Crh<0|Zx;Bz<5L?QvXm_2P?LcWDU90(N1#mYU3xxt?9EN#AF z*kGuk4_}h~ysmdk%N&2~d-t44lz4F~RGNvmPrvQQK4B-#$P8hTH(UGTvKT))B=yok zHfZrt^5l*Y40mryg}JB~-rqX$Iu@{aYfPRpB^(FjQz##}?RI0vpvJ911O=OiRN2}u zqjAM$I8}ZhRIpUQ73JlVSFri+nJV#F=xsW?D;Y=hQ%`Ur$onvtP)A1tv+K5qbt6e& zU*wh{u(J0MzssBDNYgbtI6H;QFobUg_py6p{4$5iBty-GNwi-L)5$zH?L{l5yhoS$ z4;5gdkoz6`EVmQM*v|`)M7+^GkQE^S)j+7tJve17+pux6ku^$MWj=%UR&!!eI>^sa-p!R{1-+}yW7Es(SR!XSP_EK z$0{WEdfCwNh3Clkb0Z%w4O+6h*m+YMV4T5*D@iFzED9u#3~PtZ_ibDUt9Jueef8bm zLLl4h?6}xXZd`c$B*xh*_d) zfFfvskU<9EDF%FDQ`*1$g3$d8l@?21+5T%U>vnrM)I)w#8dz3G=dsQB~pX%a=Uf_=G z=GB3n!gRl?Mbsz)7#d3?pnZ+6vGH3(W=Gy6BTXzSMuk0_X{+Sy8cP~$0Y*2*b@_i^ z8r$AHcm4F*eLf$^AuP+rhr`k7ebgnR6+%Z5$bi-9RY(+ZCs6@VWPm&GO_3|rbU29+ z`_?evk!viWUvJ9~$30Y@)jXNC+B=3I_APSTS2@?1CYg|K$Qq zaVP+)(Fl}!yycF9sCOf04zrD=?4+9%z=#@Gmx0|ymN|qAJ-INy)QyJyYh7tDFV`>Z zkY?w9(X;NWb%k}VT2^nAwS{0tsWvKVIc=7+6g8g)_#v-m@DJQFX*Xn>T}Mex0&-uL z6ZxMg0A^b2-Z2kBpyr7Qo9ts6jLu5K=CL~2+A`l3R8x~WEBAjF>1cJ~2>~)c0}tIC zU^T8mA88aB{`Ji)GAntIo{f_IT1bj~4}~4)k=4YyTS(bX5@S686z0T-jAeyrOwGfP zW5WI1$4utkxaH|RDbp->afEiixHKgj4?No9uWw2PBSTCV$1$f~1vVky?+A&R-Y98b zncl1}KkCBAE~L^;1d3AS8+YXIN~zG@I(8_fKf7(FQzf5NAJ2+v8*B|qp1P^qQo=sk zwC=OR-L9k5I&jcz?6!Vzze}h(to23`%(2bj_LoRV){I&ob1{YJ%fl#JzMt)TNa6N5 zYHAlv|7&TfGJ6h_JpaXip9a@Hv2zg+yX;L02bla0|06PU?_(aH9mj$Wmx;EaS?yXD z;#1LBaWOs)ywaC72{vT=2mBWZ!MRz zmMI28;ProwGlgOCBd0kRJCc$QxSRh0dR*<2sVK*W8wKgLyYn#uZAt5WOr;nx4x42H; z#k0wJ)DuBxlNlGlymJfWyK?Bv;JLttAW`Kc$$!F-+E&q{Bl8+AZN7^JM*~24dF`jO z3TT(RZk|r-nm#}ymsVv{$s{q6)P7fv)QtQFbf#WGmpZYR+9Zblou2%`n0T*l-?eF< z1js|a_ikg#*m=B8)aEj?58aOCW)C_)V9ls*8ME8j%ebDNUjD8YXE5V_^yTD*rTq#s zCz_jK!taO2u@tSM=mw2vK@KfLZ$Yy4$i*PLYLfbu5Hs=D5!kaBgUrWtA@=I)Xtdj`32Y3yT zm|R>kvS&BAk=F)ODc`g5VQvpu{uu-ZfTv%(50KN!rELyw^!Z$!6!X2dEU|TLZ?>6k zCp{;D#Z5bjmNsm7T&hdnFz=pzlJ0(oiDihU=F9mbt*llhcxA(rSj~{*b=q$SFSWcx z^t_%-^F6=np#sdD9l|+Ah&$Dwm}k&FfA%?#y^lff!hc0UV`()m%dOLT-|3zEF3KMe zZh=jpm0Z;#CE}spF&=`MZr$N+;zD0Doqy&bO@u*IjJTrn_-%T%3VAh$<&_z*whydzCg&oV~L{plpUVV9c^m`6~>K)nR+@SQ>1R zgdrdNi^7}3ENJ%Jsl$VQ^r6Nomrq9bQza4rJDyspTMz<4)!f?J8FTk9b0rO>F{1h-lX?Nu*vZwS3#@V*2nTydTb; zLEj~`oFNA@koVFo?T@L#XI|XxSnpC8aLIWz)Vmfr&Qdm~Uo2`3W=S#J!6J0;3f3(q zR{Ed!idt)iGZVG%H-N*m(?SzyF|!>nt^Vi}OmF`4Cy?UOM#d!Hmo2SWa01Lzec`>A z9-yv{z#9Edlc$iOA{+H~h`4*5n4S5M5P1i`)V=fdt#r!UwTa@$n&+pf=5=B5vg3q5 z^OkA;9p%K_kQw=h1ps3*YnVV`r2SsenH7nL%$=%ryvA2>v-1w7$xo&RXoN3QAbS!_Udh`h&_L^ zdN4I^q4P04%>i0Ew<%GK3Y5$hlfwC>xRdt+G4s&Tg@?A)$Ar|`)Ah^=;sH~HWi616MKsrgpvYi@#%r|G(x zqoC^AO5WCw4DadQEBYLO?e{oM0PPhscvcv6hKe5CR;)HA(=WOBDNtY2*>st1a?+2p z0!eaX2X){B)fpa&RAYaeCMVPrWGRm5p4^X5aSey+6CBY~VmdK#K%gA?%lci&D5Lfy z<=%NZUAd@q?lj{`q_1Y^JJ@`5D^Ni#s%>I&Jgc12wRbi>*o`=VNkf$JaNGJ8TiN%3HGr2!0Ck^B*x{ytFDgk!b@JOOga( zjUiDY(kd)4!vQ$(@a-Q=U&_`Lp*A)Fd6 z*(jQmAk98S>$-Yz>vBg93wgO_Y$=RwxaR~gjd_R^oRrRX@5O4wdFz@*lq$jc$UVL` z7u~z47K4wx7L6@=iz1IP{%Uw}Phd-|uuP6OU_*bhQ+So7P+as!eDqM6T$MFtZA{x4 zG+)*i0~hL1VFu5assG4>>vT!pJ{1h5G|jPaW4=-ee@y4lRwVoV*St}LxS}0WByiTU z-h*#>MT@z~o&2eJb=i+={KssVsaUgZgF)|XiPs!!nJZmRgYzR+%Qa7R9kC@PTS48S zC}d6Z+f^RAc4iR*^!3X@;f>4f&G;JA4GRswQ!m7Ar%MdP7Kr>XLZhTD~h${aGQXwr}YKNsgAPEN7UFQ$d8neSG2(tog_X;6*;V=W*8p z$O>9s;<8-p2@0R8$!VlnOdtM6bL8@krunXDEZUcCXy=9Z(N1-IFgJ&6Xav#>HDA06<9;7_&Zn&V{L3~f2&QB zFWk6&VUnlPLsiXWTE&#V-PzmYPqxH}5J?6)G%I=$N$rc3h~h6E?weA#aTN1p_`7OP ziZuy{TJ!{&6e(oUm3SA|+AO{IAe>r-Yf= zwBA+Q;@)9|nFcuHKbNCXkRN1Vf6Y@)t@ay56dj}bEjAv-5uWGEsB~le@cM;)&lLwA zw3fk3h4Hn^-=?d*Q zZRhCwQd!lx|0DU^Cp!D=F61E9Qr@ZA%MFXlS6?~#F)$_Al{c?U;Y&Kwq5vV(wYFx-2qrqjGA}*-mwKEbbdzBB+|%fa~OJK4mGX4oerx@ zsC@M0gQBEYw`lSEv8Mi+rSNIr95^WC5T?E8tKYu`1UIDBwP5%0_;Z7xS7fF)w==y@ zr3BE6LAciyN_k7Vk-^f3`@1RPf0+d5oWG=HKqYN0cE z!XGuses6R2seuTEk}(dts?C)0pkr(1MxJKj{VH?v+)PwS z`*X`Yk-Ox2n<64HW(A#BprkgZ*yC2>iIj8{keaL?H`~-SX|?8hOH?vE-OctpIvvIf zMrVhpOu+{STA}T3lJIL^m5GU?#uo({fYkGFX^B>WvTze`V0E%5$c+I^UG;JfN^AHe zZBKH6w8)NZH$7HabLqVt+^dj{w2Ijw%|PNuxV+N7gZ+ubs4=CYnq{Ph#o z1S=yHmZ${KD~F#gLr_k)QxiS>R3LrO37^(7#?r7Fpwihw#aPhbVn?ycteCt#k`?7| zjM=7WWBcB?wMk|0PleaFblmlMJaecq`76f(3MZ+Qsf0`EooB6QU{Sg>R?ZGijUH=Z zEg+dkIlMzhWqkgDpSp|_59MY&U23+@$q_QS#wUd+}=@bU4))9|3n!`S{;;*(KAH?lEl+RQtzC!PfYd#1Mz0+lluXL(ZadYL7u;Ob4 zJ1!PNbm66IyGH<8G6rB;7cLzXN}vD!*$BS@152xm7_Ma~<3EZYd)*V7^t15$5eOmu8j!N9AN~Y_8g#|Njvr+J z@P8wvuHp;Y+bWW%L-k{SvNw6b`&L*jDJ4x7a4iI$AjLgc3H{+U1k;|-j8E}hrxefl zGv}EoRh(E`+3(zh4oPJ441L<9!}#kPfMy9TH2GK9>i`N}$G#gBEnMn^4r)u{#-Du{ z8PRTh7Y;%!V9n~gU>0Y6-CP31NxqB^PQVb^XXqaw|KEXcJ$&J<>mN;|y_g={x4L{i z^H^=(ZZpu1dz$R_db&ZPr&!gv>wId2StPj|-wjsU@=2@Q?!#&2U&l1TDkTMoX5G?m zABtW?B_-eaa&i=t7zuZ5K+uwi;gw;KsfEKICHd-)DKjXNnS*U)Lct!tpy6l6iz`Ev z6p5vjw&dZ<#GT_TG(9iKZ(j;^&>{S>Q!OM}J?$b`CvqyRnpWc47p*k?Y@o}Ox}qrO zsgVo`iL^9nh9JKYNDki#4jG$(F6P;&dLI@!2c`${YF@ybtetN`P<*WppJ<7u0>{`p z+~#*P;qPJ27PR5*d;4oLxf*#GF~CuCPu4Kh_a~2o`+rT=bY{@7b(c+4pt@Dx_GWQ6 zCrPbvpe47d1ue`&g=$Uu6H|ON_Kxi8Z2Y*3R>E0cpTP@j$exapSjtG*t8u_eg z<)OK#2-x#)c$LvMn?4|fKduFMsgcrCTd=# zXW|xRnKLPS>o$4@{KCA4{2RxX93RE#pQHRQv$1DMigE=ecJN+2D;!8bN96dm@swXU z1%jwDSJDCQg&FhQ9|yO^+rQRhBypf3>1`Izb~T{9w{Qa6r_PkqVjXRDIrON~%(U_i zpqOiNp%N<7E_#AK!-i?42j}116FA^WvZVS)?zX@J)0BQ4C8CfEjR|D8$bZwa>h@1l z;A0qjK*Fk%O14~m^>sv$_=yf^T=5qo238qqpzU=G@6_QV$KXHzap!#$D6dWb(TM19 zzGEf!*^4PVf44L_C8Bt8K$Q?2TVCK%7mJg_(%)n~Yy;D@!Fuy_s)TcDBdM5c5b@GM zP(~K9DW6r3d1d|ZZb*D`jqwc-UVRnW)9s$(Oh4>r2XD~9%ETBEVY%ryfK6ABJK-b} zMh&1YeinqQzx!Y|(X@JozG1dqjTB}NgT-vDv@rokM02k@7DW$> zQrEg)5JFY;JT%Xk`JH-9Bbm=e6aI6_mq1_&a8(OUeFOLJ_auq=?ts zuq1Bm+mQ|RPO-G_g_GTxk!g`TepPn}`JPBZKqxO8&zJG{!Wrr(ba#{6CS6ByIl|$W zpSX}S=wV)Ml4>>ODhaL?{IiTT2iU~${TWYiNCC%36dCh3HgC89zJvhXL&b}p0qk&{ zcXCbmTdZHs(6Ofr*a2WPI;Lpz#!_yi{n_Y(bJ&l-92>Etjj#?!{{eI*Qb>~X?k8U` zCXeoE{B(|Ne7EQ@)(`NtL)TUXeK)?*Fpa66_>~%FWC?Mu7O5i2DP)+k5yji=jow4m_9u*bv)}tZ zNL49YzQc2I?Nn7&1z5Fnwkvqd7a>3zck^gfq^xmT9sFd!au)cOE8zZaqObW*B4z#B zfP7k6f3s*X6@X2hC3Sae{|udLew??+C7NkHGX*-3SB2f9yMQJI>Y?UqHq+Y44e&v7 zE&V9?(*0L6u&MQ`xd$)A+EY1G#oq~7JqLqYwD%8)&+2}*2|RSlT(~JUz{wigZ#v_` zCp0XFjbd^q^2}oLa%@P}8N6`LW<*cHVldxQzg_4Nun^|94W4a_mb@Vu>l(W=ym;h? zW>F9T9TXIa7jWNO-Tb5`OzAzmc;Pp& z+0n7s07C3glP>DGsh>{AFZh@fZgqF&0*rII_oxt_)w*U^HL8C|Q7U!D8Qkbd6gI#@ z3dmq=nYO0xb@8c8lK^Huty#T1T*cBTOO|{5cv1gCHqze`E7-SKZ8Y0g)4IU)d}zOJ zeXAwy@Ct4oHEq4vSmlZhfJF=RXgf?0^Rr&O|6RCh|g=O?{0PoM3$*I?|# zXA8~00So}DL{KLEM@L{=vj`yD)b^jC8ol}2&RRR6+Qh?|O<9Ck#nRvfIi|teJ7Vx% z^Y*1*UW)&KCRi**=>4i4R_QeUmdx|O!pUt+ioQmUh_?@_7qOrJfs=jH@Y7XTQn|Jp zsm$0#V2gMhA7-A`rF={X-45F{YS^RY!R(}7(4 zBH$Btf|4WaSA5Zdr~FYG?Qm)O=9voeM*4Piq`6|$3oU}$bb{devoOQnWY9V2%wO2T zHSCb|&=lBl&#wX}s6F??tYr_nERn=!4N?Xmpx(dJ+HSrPU6I(y68uOO){ zX5D0I2mX%4rino~o*p(43hc5(DaTCASNP!$U6}RmxYM0E(k_ zg$H}n{vYS%96tZJL`;Q#s%TKYLgFSdl4f|0h;c<%g*Nz>=AH;4#0VV=gksfF=2i4U zFujkxd+e;q;f<{8I9=9GD5zv{e&sjTsBp3)xrY>802j{el>LTnJ zDgWi7^rbJe_f`EdE%}R+tF5!i2mW7*#|vFrPX{p$i&xq9b+^k;(?h8niqSwyBGfSu z6SD_MdXPO#8+fJ4OslMb%LG+`e3WX+{6`PWiPtU1i$92oynwH(mgBF=g|MHf3#$o3 zAz%B>sZUB)^IWRxq8n!Z`=RbJdo*Af*S&X-?TT+0haR2gSB~X*Jt$puvbyjjjT=(k z#k1N^HDUgf*`XhcWwML1vK-ybsoM^d0NDeR#=vgh0oh`xZ@bC6l|2&l1TBHqL!kVj zkSuImP$!A;rAmEBANyf+^s5AUtd$^VzzEZLa%T%{f&lEYk>I^H$VKppi~$YJiL)~~ z5JnCeZW5aXkERW-=#BNg`=@Pt8V(|K5nn>pzx0B3h~7#YGN1Z;Cc=wudjWMen>I84 zJC}(hhq=#e(!y=xFg|&z!)RRSXUty%MrwQTffD1#T)$$wU+I?P{z{om&BpECjfih= zg&YUPPc2gm@e48asail>F#wz;^lkSzZYZFC4U{v32To6?I%%Hjd3Pj96(4s8npRJt z@aVZdo^AXt*L0tpyRWPb=i;>(p2=8iBpK!(F=EE~CIY}ofzns)C%a?B9MrdHTcJ?W z)9q<^->~2H?@IEC8Zcr`2QdHn(e559-1d-0;zZfA-T24B5tk%a^%Oy1)c6-7XmZFv zWdOaS-4>5c%7%13K~=@HWPw86b8FAQe`k>c;6MqzvzNh`c)@_KDVn@md4%uxL$mI& z`p+?NOZ9(-Fm5fC=W@-ZMNe59O@8508_L8<|Phu;QK)g5a< zq#E|!1@6wp6e$ zJ+!3s3W+6y9cE95Rmt~jCH)qQtp;|USxyE-w2`Sv)Kku8$ep7dlmGq;#3VGA4oZXy z2a3?HSrQElfn=3zGh4V1&ad8%b@Yo1K5$4qnOhHL>wdv#;0@KYW8(AORLZSF59IEqNxaWRk2)r;3I5Ul zZUY=j6Y+;5W&AE%CNhcq2N*4wH&@7Rlg~8#uSS|{N2}-UG2!NSGBTXLk~Ve9tpgr0 z=k0N{98P;S&wcM3mj7;)0cJGWQck~3r30*>zeBWR2CP6dO$1?~4zZdD+1rCMH==>Oj_lwr@5`qI@6gf{-^u|$~r;?+Bn zMqO%3ER(feH39(ONz!7%YNi`HaqswE+2L@*8ISIw8+WkJbrGWq)^@hP-Q{dE=?fbz zel5QZfGBEpmw(y0zYXfUtt}=0b~^jdk^t{F!UQMG-S$ut*`Y`E=UGz?49w!hS@CIR zb@b#WhVCzVi*@iCT)7bJ7PK|c6hQ3C>{T4QunU2COn^fsH2d#wiXJ36@~|p-Kb2eY ziG4|w8ZI)s$jdHV)71HHa}Oe=sdwaBRcz`ri9ceZBlM`(tJk^mE8QY}B>MdR?bK)^povD z)i*=;e9LGapo>U-73$44)Vd1je@of;+c_eAWch@H0tl-YLZI?WI;aq8=lE}y#MH;o zyUQuQOq)TtdivQQ8K*(HV9Qj@y)4cr?0?=xnf&Y`aR25X70KW?cBj4sW3Ied6-clY zgcLWKerTR2_maP(VM2SV4#NNACd-X{k6dCZ&@X)Pdisjm{@zow(-kC1?&&+ZD_MU&zJ6nN83@{ldb12Wd9N(dB7Aoz+xUXvc{j<7< zfyFB@Zys*s*bx&fqOn)k;M6-_nPa+#fZ{hl{-1R4F6-7^E@2En;OXk;vd$@?2>>hL BQ^^1T literal 0 HcmV?d00001 From 65569c4a60eeddd15799f93f35d4623ba7985a3c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 12 Jul 2019 18:21:48 -0700 Subject: [PATCH 0578/1504] Update dependencies --- Cargo.lock | 306 +++++++++++++++++++++------------------------- server/Cargo.toml | 4 +- 2 files changed, 142 insertions(+), 168 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1f6872d7..ddd9b520 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,7 +10,7 @@ name = "aho-corasick" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -23,7 +23,7 @@ dependencies = [ [[package]] name = "arrayvec" -version = "0.4.10" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -31,11 +31,10 @@ dependencies = [ [[package]] name = "atty" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -51,7 +50,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -61,7 +60,7 @@ version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -83,7 +82,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-automata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -145,7 +144,7 @@ version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -178,7 +177,7 @@ dependencies = [ "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -193,7 +192,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -223,7 +222,7 @@ name = "crossbeam-epoch" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)", + "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -265,7 +264,7 @@ name = "csv-core" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -273,7 +272,7 @@ name = "ctor" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -305,10 +304,10 @@ name = "env_logger" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -336,7 +335,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -347,8 +346,8 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -357,7 +356,7 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide_c_api 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -393,7 +392,7 @@ name = "fsevent-sys" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -435,7 +434,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -454,7 +453,7 @@ dependencies = [ "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -488,7 +487,7 @@ dependencies = [ [[package]] name = "httparse" -version = "1.3.3" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -501,7 +500,7 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.31" +version = "0.12.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -510,20 +509,20 @@ dependencies = [ "h2 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -535,7 +534,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.31 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.32 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -562,7 +561,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -570,7 +569,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -578,7 +577,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -611,7 +610,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.58" +version = "0.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -625,7 +624,7 @@ dependencies = [ [[package]] name = "log" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -636,7 +635,7 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -647,7 +646,7 @@ version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -667,10 +666,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "2.2.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -712,7 +711,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -725,8 +724,8 @@ dependencies = [ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -739,7 +738,7 @@ version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -761,8 +760,8 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)", @@ -778,7 +777,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -798,7 +797,7 @@ dependencies = [ "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -818,14 +817,9 @@ name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "numtoa" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "openssl" version = "0.10.23" @@ -835,7 +829,7 @@ dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -851,7 +845,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -886,7 +880,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -899,7 +893,7 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -907,9 +901,9 @@ name = "paste-impl" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -976,11 +970,11 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1005,7 +999,7 @@ dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1024,7 +1018,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "quote" -version = "0.6.12" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1036,7 +1030,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1048,7 +1042,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1066,7 +1060,7 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1141,7 +1135,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1153,7 +1147,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1182,14 +1176,14 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_dom_weak" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1197,6 +1191,7 @@ dependencies = [ "md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_repr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1207,18 +1202,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_xml" -version = "0.10.0" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 3.2.390 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1233,25 +1228,17 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.54" +version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "redox_termios" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "regex" -version = "1.1.7" +version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1266,7 +1253,7 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1293,9 +1280,9 @@ dependencies = [ "flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.31 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.32 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1303,10 +1290,10 @@ dependencies = [ "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1318,7 +1305,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1328,9 +1315,9 @@ name = "ritz_impl" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1341,7 +1328,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1354,18 +1341,18 @@ dependencies = [ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.31 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.32 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 3.2.390 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1423,7 +1410,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1463,7 +1450,7 @@ version = "1.0.94" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1477,6 +1464,16 @@ dependencies = [ "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_repr" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde_urlencoded" version = "0.5.5" @@ -1555,7 +1552,7 @@ version = "0.15.39" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1565,7 +1562,7 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1585,9 +1582,9 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1600,17 +1597,6 @@ dependencies = [ "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "termion" -version = "1.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "textwrap" version = "0.11.0" @@ -1632,14 +1618,14 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1647,13 +1633,12 @@ dependencies = [ "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-trace-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1672,12 +1657,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1691,7 +1676,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1702,12 +1687,12 @@ dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1736,18 +1721,18 @@ dependencies = [ [[package]] name = "tokio-threadpool" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1758,15 +1743,7 @@ dependencies = [ "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "tokio-trace-core" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1884,7 +1861,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1952,8 +1929,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71" -"checksum atty 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "9a7d5b8723950951411ee34d271d99dddcc2035a16ab25310ea2c8cfd4369652" +"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" +"checksum atty 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ecaaea69f52b3b18633611ec0007d188517d0366f47ff703d400fa6879d6f8d5" "checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" "checksum backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "18b50f5258d1a9ad8396d2d345827875de4261b158124d4c819d9b351454fae5" "checksum backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "5b3a000b9c543553af61bc01cbfc403b04b5caa9e421033866f2e98061eb3e61" @@ -2007,9 +1984,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" "checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" -"checksum httparse 1.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e8734b0cfd3bc3e101ec59100e101c2eecd19282202e87808b3037b442777a83" +"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.12.31 (registry+https://github.com/rust-lang/crates.io-index)" = "6481fff8269772d4463253ca83c788104a7305cb3fb9136bc651a6211e46e03f" +"checksum hyper 0.12.32 (registry+https://github.com/rust-lang/crates.io-index)" = "a64d71c1e77d39da024f06f5821ee00ad9c38febb90370bad1f07a94e0bc8793" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" @@ -2020,15 +1997,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319" +"checksum libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "3262021842bf00fe07dbd6cf34ff25c99d7a7ebef8deea84db72be3ea3bb0aff" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c84ec4b527950aa83a329754b01dbe3f58361d1c5efacd1f6d68c494d08a17c6" +"checksum log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c275b6ad54070ac2d665eef9197db647b32239c9d244bfb6f041a766d00da5b3" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e6bcd6433cff03a4bfc3d9834d504467db1f1cf6d0ea765d37d330249ed629d" -"checksum memchr 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2efc7bc57c883d4a4d6e3246905283d8dae951bb3bd32f49d6ef297f546e1c39" +"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" @@ -2043,7 +2020,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3572d71f13ea8ed41867accd971fd564aa75934cf7a1fae03ddb8c74a8a49943" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" -"checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef" "checksum openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)" = "97c140cbb82f3b3468193dd14c1b88def39f341f68257f8a7fe8ed9ed3f628a5" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)" = "75bdd6dbbb4958d38e47a1d2348847ad1eb4dc205dc5d37473ae504391865acc" @@ -2061,13 +2037,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" -"checksum proc-macro-hack 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0c1dd4172a1e1f96f709341418f49b11ea6c2d95d53dca08c0f74cbd332d9cf3" +"checksum proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "982a35d1194084ba319d65c4a68d24ca28f5fdb5b8bc20899e4eef8641ea5178" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5afecba86dcf1e4fd610246f89899d1924fe12e1e89f555eb7c7f710f3c5ad1d" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" -"checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" @@ -2084,15 +2060,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81428c521a07a3feac9c31180a886e467eecf81b769987f70d51d567a09c321d" -"checksum rbx_dom_weak 1.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "28fb22188872a75cb66f4937de3ec27fe114a5af3580d34a0a483c42ea1608a2" +"checksum rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb8079fe850096bd18582a8661f5d7a6afee61bc914691be2f287050f3ac0ec4" "checksum rbx_reflection 3.2.390 (registry+https://github.com/rust-lang/crates.io-index)" = "4f00e0d9e70f1825341e45ff610264778fc2fe72a733027feeca85bfcd6a7305" -"checksum rbx_xml 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f6df95f079a20ccdfc3a59bf119afa2ef48155a909e7afceea4a9f2122c164f" +"checksum rbx_xml 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e6728d8701e2d78f7b15e793f2b5b4926cb4f0281d6f19371f506816ac89424" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252" -"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" -"checksum regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0b2f0808e7d7e4fb1cb07feb6ff2f4bc827938f24f8c2e6a3beb7370af544bdd" +"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +"checksum regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d9d8297cc20bbb6184f8b45ff61c8ee6a9ac56c156cec8e38c3e5084773c44ad" "checksum regex-automata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ed09217220c272b29ef237a974ad58515bde75f194e3ffa7e6d0bf0f3b01f86" -"checksum regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d76410686f9e3a17f06128962e0ecc5755870bb890c34820c7af7f1db2e1d48" +"checksum regex-syntax 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9b01330cce219c1c6b2e209e5ed64ccd587ae5c67bed91c0b49eecf02ae40e21" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum reqwest 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)" = "00eb63f212df0e358b427f0f40aa13aaea010b470be642ad422bcbca2feff2e4" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" @@ -2111,6 +2086,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "076a696fdea89c19d3baed462576b8f6d663064414b5c793642da8dfeb99475b" "checksum serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "ef45eb79d6463b22f5f9e16d283798b7c0175ba6050bc25c1a946c122727fe7b" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" +"checksum serde_repr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "29a734c298df0346c4cd5919595981c266dabbf12dc747c85e1a95e96077a52b" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" @@ -2126,21 +2102,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" -"checksum termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a8fb22f7cde82c8220e5aeacb3258ed7ce996142c77cba193f203515e26c330" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "ec2ffcf4bcfc641413fa0f1427bf8f91dfc78f56a6559cbf50e04837ae442a87" +"checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" -"checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e" +"checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" "checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" "checksum tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2" +"checksum tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "90ca01319dea1e376a001e8dc192d42ebde6dd532532a5bad988ac37db365b19" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" -"checksum tokio-trace-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9c8a256d6956f7cb5e2bdfe8b1e8022f1a09206c6c2b1ba00f3b746b260c613" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" diff --git a/server/Cargo.toml b/server/Cargo.toml index 95de7117..9ce79e2f 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -30,8 +30,8 @@ log = "0.4" maplit = "1.0.1" notify = "4.0" rbx_binary = "0.4.1" -rbx_dom_weak = "1.8.0" -rbx_xml = "0.10.0" +rbx_dom_weak = "1.9.0" +rbx_xml = "0.11.0" rbx_reflection = "3.1.388" regex = "1.0" reqwest = "0.9.5" From 974760f020e39b893213cbb9c402884707dcda5f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 15 Jul 2019 16:34:42 -0700 Subject: [PATCH 0579/1504] Fix installation link from new game guide --- docs/guide/new-game.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/new-game.md b/docs/guide/new-game.md index 7a3f46ca..74c967be 100644 --- a/docs/guide/new-game.md +++ b/docs/guide/new-game.md @@ -49,7 +49,7 @@ If you open `MyNewProject.rbxlx` in Roblox Studio now, you should see a `Folder` ## Live-Syncing into Studio Building a place file is great for starting to work on a game, but for active iteration, you'll want something faster. -In Roblox Studio, make sure the Rojo plugin is installed. If you need it, check out [the installation guide](installation) to learn how to install it. +In Roblox Studio, make sure the Rojo plugin is installed. If you need it, check out [the installation guide](../installation) to learn how to install it. To expose your project to the plugin, you'll need to start a new **live sync session** from the command line: From d788dd30420a44adad15b0e2625140882a278bc1 Mon Sep 17 00:00:00 2001 From: Gskartwii Date: Thu, 18 Jul 2019 00:30:15 +0300 Subject: [PATCH 0580/1504] Fix broken link in existing-game.md (#218) --- docs/guide/existing-game.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guide/existing-game.md b/docs/guide/existing-game.md index 7edb4a0d..735b83ca 100644 --- a/docs/guide/existing-game.md +++ b/docs/guide/existing-game.md @@ -2,10 +2,10 @@ ## Summary * Tools to port existing games are in progress! - * [rbxlx-to-rojo](https://github.com/rojo/rbxlx-to-rojo) + * [rbxlx-to-rojo](https://github.com/rojo-rbx/rbxlx-to-rojo) * `rojo export` ([issue #208](https://github.com/rojo-rbx/rojo/issues/208)) * Can port as much or as little of your game as you like * Rojo can manage just a slice of your game! * Some Roblox idioms aren't very well supported * Redundant copies of scripts don't work well with files - * Having only a couple places with scripts simplifies your project dramatically! \ No newline at end of file + * Having only a couple places with scripts simplifies your project dramatically! From a4a6e3b8f63ff8416917a6cbce9f2c4ca0004d2a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 31 Jul 2019 12:54:46 -0700 Subject: [PATCH 0581/1504] Fix serve help message. Fixes #219. --- CHANGELOG.md | 3 +++ server/src/bin.rs | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0341c8bb..068732e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ # Rojo Changelog +## Unreleased Changes +* Fixed default port documentation in `rojo serve --help` ([#219](https://github.com/rojo-rbx/rojo/issues/219)) + ## [0.5.0 Alpha 12](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.12) (July 2, 2019) * Added `.meta.json` files * `init.meta.json` files replace `init.model.json` files from Rojo 0.4.x ([#183](https://github.com/rojo-rbx/rojo/pull/183)) diff --git a/server/src/bin.rs b/server/src/bin.rs index 7f5b80e7..2bf96da7 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -43,7 +43,7 @@ fn main() { (@subcommand serve => (about: "Serves the project's files for use with the Rojo Studio plugin.") (@arg PROJECT: "Path to the project to serve. Defaults to the current directory.") - (@arg port: --port +takes_value "The port to listen on. Defaults to 8000.") + (@arg port: --port +takes_value "The port to listen on. Defaults to 34872.") ) (@subcommand build => From 972338d86a24a52f6dc14dfd799634612204b5c2 Mon Sep 17 00:00:00 2001 From: nukropina <52841548+nukropina@users.noreply.github.com> Date: Wed, 31 Jul 2019 13:18:24 -0700 Subject: [PATCH 0582/1504] Corrected folder name. (#220) * Corrected folder name. * Update docs/guide/new-game.md Co-Authored-By: Lucien Greathouse --- docs/guide/new-game.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/guide/new-game.md b/docs/guide/new-game.md index 74c967be..638d4263 100644 --- a/docs/guide/new-game.md +++ b/docs/guide/new-game.md @@ -41,7 +41,7 @@ All we have to do is call `rojo build`: rojo build -o MyNewProject.rbxlx ``` -If you open `MyNewProject.rbxlx` in Roblox Studio now, you should see a `Folder` containing a `ModuleScript` under `ReplicatedStorage`! +If you open `MyNewProject.rbxlx` in Roblox Studio now, you should see a `Folder` named "Source" containing a `ModuleScript` under `ReplicatedStorage`. !!! info To generate a binary place file instead, use `rbxl`. Note that support for binary model/place files (`rbxm` and `rbxl`) is very limited in Rojo presently. @@ -87,4 +87,4 @@ Generating and publishing your game is as simple as: rojo upload --asset_id [PLACE ID] --cookie "[SECURITY COOKIE]" ``` -An example project is available on GitHub that deploys to Roblox.com from GitHub and Travis-CI automatically: [https://github.com/LPGhatguy/roads](https://github.com/LPGhatguy/roads) \ No newline at end of file +An example project is available on GitHub that deploys to Roblox.com from GitHub and Travis-CI automatically: [https://github.com/LPGhatguy/roads](https://github.com/LPGhatguy/roads) From 93ae8187cd3afe49fb5498f68ef1d6cadfeb10ad Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 1 Aug 2019 16:11:21 -0700 Subject: [PATCH 0583/1504] Update CHANGELOG --- CHANGELOG.md | 1 + Cargo.lock | 401 ++++++++++++++++++++++++++------------------------- 2 files changed, 206 insertions(+), 196 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 068732e2..c171198f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased Changes * Fixed default port documentation in `rojo serve --help` ([#219](https://github.com/rojo-rbx/rojo/issues/219)) +* Fixed BrickColor support by upgrading Roblox-related dependencies ## [0.5.0 Alpha 12](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.12) (July 2, 2019) * Added `.meta.json` files diff --git a/Cargo.lock b/Cargo.lock index ddd9b520..1b211f5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,36 +31,36 @@ dependencies = [ [[package]] name = "atty" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -78,13 +78,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bstr" -version = "0.2.1" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-automata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -123,14 +123,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.37" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -144,7 +144,7 @@ version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -177,9 +177,9 @@ dependencies = [ "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -192,7 +192,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -213,21 +213,21 @@ name = "crossbeam-deque" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -235,12 +235,12 @@ name = "crossbeam-queue" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-utils" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -252,11 +252,11 @@ name = "csv" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bstr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -273,7 +273,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -304,10 +304,10 @@ name = "env_logger" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -316,7 +316,7 @@ name = "error-chain" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -325,7 +325,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -336,7 +336,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -346,7 +346,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -356,8 +356,8 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide_c_api 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide_c_api 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -392,7 +392,7 @@ name = "fsevent-sys" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -430,11 +430,11 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -444,16 +444,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "h2" -version = "0.1.25" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -466,7 +466,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "http" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -481,7 +481,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -500,19 +500,19 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.32" +version = "0.12.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -534,7 +534,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.32 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -561,7 +561,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -569,7 +569,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -577,7 +577,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -599,9 +599,6 @@ dependencies = [ name = "lazy_static" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "lazycell" @@ -610,7 +607,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.59" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -624,7 +621,7 @@ dependencies = [ [[package]] name = "log" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -635,7 +632,7 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -645,8 +642,8 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -669,13 +666,16 @@ name = "memchr" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memoffset" -version = "0.2.1" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "mime" @@ -698,7 +698,7 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.2.2" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -706,13 +706,13 @@ dependencies = [ [[package]] name = "miniz_oxide_c_api" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -724,8 +724,8 @@ dependencies = [ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -738,7 +738,7 @@ version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -760,11 +760,11 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.48 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -777,7 +777,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -797,10 +797,10 @@ dependencies = [ "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -809,7 +809,7 @@ name = "num-traits" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -817,20 +817,20 @@ name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "openssl" -version = "0.10.23" +version = "0.10.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -840,13 +840,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.47" +version = "0.9.48" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -880,7 +880,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -904,7 +904,7 @@ dependencies = [ "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -949,7 +949,7 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.14" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -975,7 +975,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -999,7 +999,7 @@ dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1030,7 +1030,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1041,8 +1041,8 @@ name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1059,9 +1059,9 @@ name = "rand" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1071,16 +1071,15 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_chacha" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1103,7 +1102,7 @@ name = "rand_core" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1135,7 +1134,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1147,7 +1146,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1158,7 +1157,7 @@ name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1176,7 +1175,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1189,8 +1188,8 @@ dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde_repr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1203,7 +1202,7 @@ dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1212,7 +1211,7 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 3.2.390 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1233,19 +1232,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex" -version = "1.1.9" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-automata" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1253,10 +1252,10 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.8" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1269,7 +1268,7 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.18" +version = "0.9.19" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1279,14 +1278,14 @@ dependencies = [ "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.32 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1297,6 +1296,7 @@ dependencies = [ "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1327,8 +1327,8 @@ version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1341,9 +1341,9 @@ dependencies = [ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.32 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1352,15 +1352,15 @@ dependencies = [ "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 3.2.390 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1383,7 +1383,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "same-file" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1403,6 +1403,11 @@ name = "scopeguard" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "scopeguard" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "security-framework" version = "0.3.1" @@ -1410,7 +1415,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1428,7 +1433,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1438,20 +1443,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.94" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.94" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1461,7 +1466,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1471,7 +1476,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1481,7 +1486,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1502,7 +1507,7 @@ dependencies = [ "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1523,11 +1528,6 @@ dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "spin" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "stable_deref_trait" version = "1.1.1" @@ -1548,7 +1548,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.39" +version = "0.15.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1563,7 +1563,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1582,7 +1582,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1618,7 +1618,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1665,7 +1665,7 @@ name = "tokio-executor" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1676,7 +1676,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1684,10 +1684,10 @@ name = "tokio-reactor" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1726,9 +1726,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1740,7 +1740,7 @@ name = "tokio-timer" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1761,7 +1761,7 @@ dependencies = [ [[package]] name = "ucd-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1827,7 +1827,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1847,10 +1847,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "walkdir" -version = "2.2.8" +version = "2.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1861,7 +1861,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1911,6 +1911,14 @@ dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -1930,19 +1938,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" -"checksum atty 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ecaaea69f52b3b18633611ec0007d188517d0366f47ff703d400fa6879d6f8d5" -"checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf" -"checksum backtrace 0.3.32 (registry+https://github.com/rust-lang/crates.io-index)" = "18b50f5258d1a9ad8396d2d345827875de4261b158124d4c819d9b351454fae5" -"checksum backtrace-sys 0.1.30 (registry+https://github.com/rust-lang/crates.io-index)" = "5b3a000b9c543553af61bc01cbfc403b04b5caa9e421033866f2e98061eb3e61" +"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b" +"checksum backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)" = "b5164d292487f037ece34ec0de2fcede2faa162f085dd96d2385ab81b12765ba" +"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" -"checksum bstr 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6cc0572e02f76cb335f309b19e0a0d585b4f62788f7d26de2a13a836a637385f" +"checksum bstr 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e0a692f1c740e7e821ca71a22cf99b9b2322dfa94d10f71443befb1797b3946a" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d" +"checksum cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "ce400c638d48ee0e9ab75aef7997609ec57367ccfe1463f21bf53c3eca67bf46" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -1952,9 +1960,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -"checksum crossbeam-epoch 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "04c9e3102cc2d69cd681412141b390abd55a362afc1540965dad0ad4d34280b4" +"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f8306fcef4a7b563b76b7dd949ca48f52bc1141aa067d2ea09565f3e2652aa5c" +"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" "checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" "checksum ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3b4c17619643c1252b5f690084b82639dd7fac141c57c8e77a00e0148132092c" @@ -1978,15 +1986,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum getrandom 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e65cce4e5084b14874c4e7097f38cab54f47ee554f9194673456ea379dcc4c55" +"checksum getrandom 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8e190892c840661957ba9f32dacfb3eb405e657f9f9f60485605f0bb37d6f8" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum h2 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "a539b63339fbbb00e081e84b6e11bd1d9634a82d91da2984a18ac74a8823f392" +"checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" -"checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a" +"checksum http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "372bcb56f939e449117fb0869c2e8fd8753a8223d92a172c6e808cf123a5b6e4" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" -"checksum hyper 0.12.32 (registry+https://github.com/rust-lang/crates.io-index)" = "a64d71c1e77d39da024f06f5821ee00ad9c38febb90370bad1f07a94e0bc8793" +"checksum hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)" = "7cb44cbce9d8ee4fb36e4c0ad7b794ac44ebaad924b9c8291a63215bb44c2c8f" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" @@ -1997,20 +2005,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "3262021842bf00fe07dbd6cf34ff25c99d7a7ebef8deea84db72be3ea3bb0aff" +"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum log 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "c275b6ad54070ac2d665eef9197db647b32239c9d244bfb6f041a766d00da5b3" +"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e6bcd6433cff03a4bfc3d9834d504467db1f1cf6d0ea765d37d330249ed629d" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -"checksum memoffset 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0f9dc261e2b62d7a622bf416ea3c5245cdd5d9a7fcc428c0d06804dfce1775b3" +"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" "checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" -"checksum miniz_oxide 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b6c3756d66cf286314d5f7ebe74886188a9a92f5eee68b06f31ac2b4f314c99d" -"checksum miniz_oxide_c_api 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5b78ca5446dd9fe0dab00e058731b6b08a8c1d2b9cdb8efb10876e24e9ae2494" +"checksum miniz_oxide 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c061edee74a88eb35d876ce88b94d77a0448a201de111c244b70d047f5820516" +"checksum miniz_oxide_c_api 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6c675792957b0d19933816c4e1d56663c341dd9bfa31cb2140ff2267c1d8ecf4" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" @@ -2020,9 +2028,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3572d71f13ea8ed41867accd971fd564aa75934cf7a1fae03ddb8c74a8a49943" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" -"checksum openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)" = "97c140cbb82f3b3468193dd14c1b88def39f341f68257f8a7fe8ed9ed3f628a5" +"checksum openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)" = "8152bb5a9b5b721538462336e3bef9a539f892715e5037fda0f984577311af15" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)" = "75bdd6dbbb4958d38e47a1d2348847ad1eb4dc205dc5d37473ae504391865acc" +"checksum openssl-sys 0.9.48 (registry+https://github.com/rust-lang/crates.io-index)" = "b5ba300217253bcc5dc68bed23d782affa45000193866e025329aa8a7a9f05b8" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" @@ -2034,7 +2042,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" "checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" -"checksum pkg-config 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "676e8eb2b1b4c9043511a9b7bea0915320d7e502b0a079fb03f9635a5252b18c" +"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" "checksum proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "982a35d1194084ba319d65c4a68d24ca28f5fdb5b8bc20899e4eef8641ea5178" @@ -2048,7 +2056,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_chacha 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e193067942ef6f485a349a113329140d0ab9e2168ce92274499bb0e9a4190d9d" +"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" "checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" @@ -2065,26 +2073,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rbx_xml 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e6728d8701e2d78f7b15e793f2b5b4926cb4f0281d6f19371f506816ac89424" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum regex 1.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d9d8297cc20bbb6184f8b45ff61c8ee6a9ac56c156cec8e38c3e5084773c44ad" -"checksum regex-automata 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "3ed09217220c272b29ef237a974ad58515bde75f194e3ffa7e6d0bf0f3b01f86" -"checksum regex-syntax 0.6.8 (registry+https://github.com/rust-lang/crates.io-index)" = "9b01330cce219c1c6b2e209e5ed64ccd587ae5c67bed91c0b49eecf02ae40e21" +"checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc" +"checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" +"checksum regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5485bf1523a9ed51c4964273f22f63f24e31632adb5dad134f488f86a3875c" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum reqwest 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)" = "00eb63f212df0e358b427f0f40aa13aaea010b470be642ad422bcbca2feff2e4" +"checksum reqwest 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0777154c2c3eb54f5c480db01de845652d941e47191277cc673634c3853939" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62fc0e980c94fe9ef795b1bb3874649c8c6e9bb67d3b90d48380ba24c69c23ea" "checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" -"checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267" +"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" "checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "076a696fdea89c19d3baed462576b8f6d663064414b5c793642da8dfeb99475b" -"checksum serde_derive 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)" = "ef45eb79d6463b22f5f9e16d283798b7c0175ba6050bc25c1a946c122727fe7b" +"checksum serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113" +"checksum serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "01e69e1b8a631f245467ee275b8c757b818653c6d704cdbcaeb56b56767b529c" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum serde_repr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "29a734c298df0346c4cd5919595981c266dabbf12dc747c85e1a95e96077a52b" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" @@ -2093,11 +2102,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef82be0baf3ae45701ab992230f1f4889c15984736d87f37558aea3e4e321af" -"checksum spin 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "44363f6f51401c34e7be73db0db371c04705d35efbe9f7d6082e03a921a32c55" "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum syn 0.15.39 (registry+https://github.com/rust-lang/crates.io-index)" = "b4d960b829a55e56db167e861ddb43602c003c7be0bee1d345021703fac2fb7c" +"checksum syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)" = "eadc09306ca51a40555dd6fc2b415538e9e18bc9f870e47b1a524a79fe2dcf5e" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" @@ -2117,7 +2125,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" -"checksum ucd-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "535c204ee4d8434478593480b8f86ab45ec9aae0e83c568ca81abf0fd0e88f86" +"checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" @@ -2130,7 +2138,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" -"checksum walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c7904a7e2bb3cdf0cf5e783f44204a85a37a93151738fa349f06680f59a98b45" +"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" @@ -2139,5 +2147,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" +"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" From 8417d18eecd6d7e28528f4396f4a39ac08d479eb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 1 Aug 2019 17:53:15 -0700 Subject: [PATCH 0584/1504] Upgrade to latest rbx_dom_lua --- plugin/modules/rbx-dom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index d7be961e..9d5aad1f 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit d7be961eb387c3fdaf6817cca2866909758fc7c4 +Subproject commit 9d5aad1faa00cfbc956a961cfd2b90ebb97c828f From cbe4467a2259b3ec05f3e18a493b9a354868859e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 1 Aug 2019 17:53:29 -0700 Subject: [PATCH 0585/1504] Upgrade dependencies and add SpawnLocation test case --- Cargo.lock | 14 +- server/tests/tree_snapshots.rs | 9 + .../spawn_location/default.project.json | 6 + .../spawn_location/initial.tree.json | 266 ++++++++++++++++++ test-projects/spawn_location/src/spawn.rbxmx | 85 ++++++ 5 files changed, 373 insertions(+), 7 deletions(-) create mode 100644 test-projects/spawn_location/default.project.json create mode 100644 test-projects/spawn_location/initial.tree.json create mode 100644 test-projects/spawn_location/src/spawn.rbxmx diff --git a/Cargo.lock b/Cargo.lock index 1b211f5a..7d6d8919 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1196,7 +1196,7 @@ dependencies = [ [[package]] name = "rbx_reflection" -version = "3.2.390" +version = "3.2.395" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1207,13 +1207,13 @@ dependencies = [ [[package]] name = "rbx_xml" -version = "0.11.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.2.390 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.2.395 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1350,8 +1350,8 @@ dependencies = [ "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.2.390 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.2.395 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2069,8 +2069,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81428c521a07a3feac9c31180a886e467eecf81b769987f70d51d567a09c321d" "checksum rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb8079fe850096bd18582a8661f5d7a6afee61bc914691be2f287050f3ac0ec4" -"checksum rbx_reflection 3.2.390 (registry+https://github.com/rust-lang/crates.io-index)" = "4f00e0d9e70f1825341e45ff610264778fc2fe72a733027feeca85bfcd6a7305" -"checksum rbx_xml 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1e6728d8701e2d78f7b15e793f2b5b4926cb4f0281d6f19371f506816ac89424" +"checksum rbx_reflection 3.2.395 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b43ccce9c29e9f1774359cb96b6ea0c1b897d416dc00f5b45cf54866ca7997" +"checksum rbx_xml 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b837fbcbbd4e0c82c0ba96d6b688a1a3b504a5b95aa4f09e2ede5b9deeb8186" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc" diff --git a/server/tests/tree_snapshots.rs b/server/tests/tree_snapshots.rs index f5b991fa..d8f2d849 100644 --- a/server/tests/tree_snapshots.rs +++ b/server/tests/tree_snapshots.rs @@ -43,6 +43,15 @@ fn multi_partition_game() { tree_step("with_moved_dir", &live_session, &source_path); } +#[test] +fn spawn_location() { + let _ = env_logger::try_init(); + let source_path = project_path("spawn_location"); + + let (_dir, live_session) = start_session(&source_path); + tree_step("initial", &live_session, &source_path); +} + /// Find the path to the given test project relative to the manifest. fn project_path(name: &str) -> PathBuf { let mut path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects"); diff --git a/test-projects/spawn_location/default.project.json b/test-projects/spawn_location/default.project.json new file mode 100644 index 00000000..b078dfaf --- /dev/null +++ b/test-projects/spawn_location/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "spawn_location", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/test-projects/spawn_location/initial.tree.json b/test-projects/spawn_location/initial.tree.json new file mode 100644 index 00000000..af079189 --- /dev/null +++ b/test-projects/spawn_location/initial.tree.json @@ -0,0 +1,266 @@ +{ + "instances": { + "21406306-61c7-45f6-9e3e-50cd6b609214": { + "Name": "spawn_location", + "ClassName": "Folder", + "Properties": {}, + "Id": "21406306-61c7-45f6-9e3e-50cd6b609214", + "Children": [ + "da5dd362-4eb6-488a-984b-c96327927a70" + ], + "Parent": null + }, + "da5dd362-4eb6-488a-984b-c96327927a70": { + "Name": "spawn", + "ClassName": "SpawnLocation", + "Properties": { + "Size": { + "Type": "Vector3", + "Value": [ + 12.0, + 1.0, + 12.0 + ] + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "Color": { + "Type": "Color3", + "Value": [ + 0.6392157, + 0.63529414, + 0.64705884 + ] + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Neutral": { + "Type": "Bool", + "Value": true + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Anchored": { + "Type": "Bool", + "Value": true + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "BottomSurface": { + "Type": "Enum", + "Value": 0 + }, + "Duration": { + "Type": "Int32", + "Value": 10 + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "TopSurface": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": [ + -6.0, + 0.500001, + -11.0, + 1.0, + 0.0, + 0.0, + 0.0, + 1.0, + 0.0, + 0.0, + 0.0, + 1.0 + ] + }, + "TeamColor": { + "Type": "BrickColor", + "Value": 194 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "AllowTeamChangeOnTouch": { + "Type": "Bool", + "Value": false + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Shape": { + "Type": "Enum", + "Value": 1 + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FormFactor": { + "Type": "Enum", + "Value": 1 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": null + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "Material": { + "Type": "Enum", + "Value": 256 + } + }, + "Id": "da5dd362-4eb6-488a-984b-c96327927a70", + "Children": [], + "Parent": "21406306-61c7-45f6-9e3e-50cd6b609214" + } + }, + "root_id": "21406306-61c7-45f6-9e3e-50cd6b609214", + "metadata": { + "da5dd362-4eb6-488a-984b-c96327927a70": { + "ignore_unknown_instances": false, + "source_path": "src/spawn.rbxmx", + "project_definition": null + }, + "21406306-61c7-45f6-9e3e-50cd6b609214": { + "ignore_unknown_instances": false, + "source_path": "src", + "project_definition": [ + "spawn_location", + { + "class_name": null, + "children": {}, + "properties": {}, + "ignore_unknown_instances": null, + "path": "src" + } + ] + } + } +} \ No newline at end of file diff --git a/test-projects/spawn_location/src/spawn.rbxmx b/test-projects/spawn_location/src/spawn.rbxmx new file mode 100644 index 00000000..98a5cbe5 --- /dev/null +++ b/test-projects/spawn_location/src/spawn.rbxmx @@ -0,0 +1,85 @@ + + true + null + nil + + + false + true + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -6 + 0.500001013 + -11 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4288914085 + + false + + 10 + true + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + SpawnLocation + true + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + 194 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 12 + 1 + 12 + + + + \ No newline at end of file From a5b6db74e54c140345fe1660337efa45e1b9cdce Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 1 Aug 2019 17:57:13 -0700 Subject: [PATCH 0586/1504] Bump minimum Rust version to 1.34.0 --- .travis.yml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 71caeae1..b0571af9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ matrix: # - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install - language: rust - rust: 1.32.0 + rust: 1.34.0 cache: cargo script: diff --git a/README.md b/README.md index 95496343..f1ca5e16 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ If you find any mistakes, feel free to make changes in the [docs](https://github ## Contributing Pull requests are welcome! -Rojo supports Rust 1.32 and newer. +Rojo supports Rust 1.34.0 and newer. ## License Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file From f768b200d27dcab289c38565def6adc5e6f42e67 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 1 Aug 2019 18:07:38 -0700 Subject: [PATCH 0587/1504] Nudge README, hopefully to fix Travis too --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f1ca5e16..70ce6f9d 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ If you find any mistakes, feel free to make changes in the [docs](https://github ## Contributing Pull requests are welcome! -Rojo supports Rust 1.34.0 and newer. +Rojo supports Rust 1.34.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. ## License Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file From 62bb5a28aa36808fd1f697d2642411e1a4ce97bd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 2 Aug 2019 15:05:58 -0700 Subject: [PATCH 0588/1504] v0.5.0-alpha.13 --- CHANGELOG.md | 3 +++ Cargo.lock | 2 +- docs/guide/installation.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c171198f..0087a89c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Rojo Changelog ## Unreleased Changes + +## [0.5.0 Alpha 13](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.13) (August 2, 2019) +* Bumped minimum Rust version to 1.34.0. * Fixed default port documentation in `rojo serve --help` ([#219](https://github.com/rojo-rbx/rojo/issues/219)) * Fixed BrickColor support by upgrading Roblox-related dependencies diff --git a/Cargo.lock b/Cargo.lock index 7d6d8919..2f230c69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1334,7 +1334,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0-alpha.12" +version = "0.5.0-alpha.13" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/docs/guide/installation.md b/docs/guide/installation.md index 3a453475..bae79754 100644 --- a/docs/guide/installation.md +++ b/docs/guide/installation.md @@ -29,7 +29,7 @@ If you have Rust installed, the easiest way to get Rojo is with Cargo! To install the latest 0.5.0 alpha, use: ```sh -cargo install rojo --version 0.5.0-alpha.12 +cargo install rojo --version 0.5.0-alpha.13 ``` ## Installing the Plugin diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index c04453d4..66cbbc8e 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0, "-alpha.12"}, + version = {0, 5, 0, "-alpha.13"}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/server/Cargo.toml b/server/Cargo.toml index 9ce79e2f..6300ce39 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0-alpha.12" +version = "0.5.0-alpha.13" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MIT" From 77db25b4d9b36c875bcd363e54d79269a3f455d5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 7 Aug 2019 17:41:17 -0700 Subject: [PATCH 0589/1504] Add end-to-end build tests --- Cargo.lock | 265 ++++++++++++++++++ Cargo.toml | 1 + rojo-test/Cargo.toml | 10 + .../build-tests/gitkeep/default.project.json | 6 + rojo-test/build-tests/gitkeep/src/.gitkeep | 0 .../txt_in_folder/default.project.json | 6 + .../build-tests/txt_in_folder/src/foo.txt | 0 rojo-test/src/lib.rs | 43 +++ .../snapshots/rojo_test__build_gitkeep.snap | 13 + .../rojo_test__build_txt_in_folder.snap | 19 ++ 10 files changed, 363 insertions(+) create mode 100644 rojo-test/Cargo.toml create mode 100644 rojo-test/build-tests/gitkeep/default.project.json create mode 100644 rojo-test/build-tests/gitkeep/src/.gitkeep create mode 100644 rojo-test/build-tests/txt_in_folder/default.project.json create mode 100644 rojo-test/build-tests/txt_in_folder/src/foo.txt create mode 100644 rojo-test/src/lib.rs create mode 100644 rojo-test/src/snapshots/rojo_test__build_gitkeep.snap create mode 100644 rojo-test/src/snapshots/rojo_test__build_txt_in_folder.snap diff --git a/Cargo.lock b/Cargo.lock index 2f230c69..c70d5de0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -76,6 +76,25 @@ name = "bitflags" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "block-buffer" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "block-padding" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bstr" version = "0.2.6" @@ -87,6 +106,11 @@ dependencies = [ "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "byte-tools" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bytecount" version = "0.4.0" @@ -138,6 +162,23 @@ name = "cfg-if" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "chrono" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ci_info" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "clap" version = "2.33.0" @@ -152,6 +193,17 @@ dependencies = [ "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "clicolors-control" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cloudabi" version = "0.0.3" @@ -160,6 +212,23 @@ dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "console" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "clicolors-control 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cookie" version = "0.12.0" @@ -281,6 +350,14 @@ name = "difference" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "digest" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "dtoa" version = "0.4.4" @@ -291,6 +368,11 @@ name = "either" version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "encode_unicode" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "encoding_rs" version = "0.8.17" @@ -340,6 +422,11 @@ dependencies = [ "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fake-simd" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "filetime" version = "0.2.5" @@ -428,6 +515,14 @@ dependencies = [ "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "generic-array" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "getrandom" version = "0.1.7" @@ -572,6 +667,26 @@ dependencies = [ "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "insta" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "ci_info 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "iovec" version = "0.1.2" @@ -610,6 +725,11 @@ name = "libc" version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "linked-hash-map" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "lock_api" version = "0.1.5" @@ -804,6 +924,15 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-integer" +version = "0.1.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-traits" version = "0.2.8" @@ -820,6 +949,11 @@ dependencies = [ "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "opaque-debug" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "openssl" version = "0.10.24" @@ -912,6 +1046,45 @@ name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "pest" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest_derive" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest_generator" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_meta 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "pest_meta" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "phf" version = "0.7.24" @@ -1363,6 +1536,24 @@ dependencies = [ "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rojo-test" +version = "0.1.0" +dependencies = [ + "insta 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ron" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rustc-demangle" version = "0.1.15" @@ -1490,6 +1681,28 @@ dependencies = [ "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_yaml" +version = "0.8.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "sha-1" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "siphasher" version = "0.2.3" @@ -1597,6 +1810,14 @@ dependencies = [ "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "termios" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "textwrap" version = "0.11.0" @@ -1759,6 +1980,16 @@ dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "typenum" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "ucd-trie" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ucd-util" version = "0.1.5" @@ -1933,6 +2164,14 @@ name = "xml-rs" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "yaml-rust" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [metadata] "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282" @@ -1944,7 +2183,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" +"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" "checksum bstr 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e0a692f1c740e7e821ca71a22cf99b9b2322dfa94d10f71443befb1797b3946a" +"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" @@ -1952,8 +2194,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" "checksum cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "ce400c638d48ee0e9ab75aef7997609ec57367ccfe1463f21bf53c3eca67bf46" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" +"checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe" +"checksum ci_info 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e5e881307a989a3a5e20d52a32cc05950e3c2178cccfcc9428271a6cde09f902" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +"checksum clicolors-control 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73abfd4c73d003a674ce5d2933fca6ce6c42480ea84a5ffe0a2dc39ed56300f9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +"checksum console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ca57c2c14b8a2bf3105bc9d15574aad80babf6a9c44b1058034cdf8bd169628" "checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" "checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" @@ -1967,13 +2213,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" "checksum ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3b4c17619643c1252b5f690084b82639dd7fac141c57c8e77a00e0148132092c" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" +"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" +"checksum encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90b2c9496c001e8cb61827acdefad780795c42264c137744cae6f7d9e3450abd" "checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2f8c63033fcba1f51ef744505b3cad42510432b904c062afa67ad7ece008429d" "checksum flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "550934ad4808d5d39365e5d61727309bf18b3b02c6c56b729cb92e7dd84bc3d8" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" @@ -1986,6 +2235,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" +"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum getrandom 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8e190892c840661957ba9f32dacfb3eb405e657f9f9f60485605f0bb37d6f8" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" @@ -2000,12 +2250,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" +"checksum insta 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00eef45accbe65bfb859ad16649c6b4bed246768d89493473d9ab6c6a0eb908f" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" +"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" @@ -2026,8 +2278,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3572d71f13ea8ed41867accd971fd564aa75934cf7a1fae03ddb8c74a8a49943" +"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" +"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)" = "8152bb5a9b5b721538462336e3bef9a539f892715e5037fda0f984577311af15" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.48 (registry+https://github.com/rust-lang/crates.io-index)" = "b5ba300217253bcc5dc68bed23d782affa45000193866e025329aa8a7a9f05b8" @@ -2038,6 +2292,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4a4a1c555c6505821f9d58b8779d0f630a6b7e4e1be24ba718610acf01fa79" "checksum paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26e796e623b8b257215f27e6c80a5478856cae305f5b59810ff9acdaa34570e6" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "933085deae3f32071f135d799d75667b63c8dc1f4537159756e3d4ceab41868c" +"checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +"checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646" +"checksum pest_meta 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f249ea6de7c7b7aba92b4ff4376a994c6dbd98fd2166c89d5c4947397ecb574d" "checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" "checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" "checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" @@ -2081,6 +2339,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62fc0e980c94fe9ef795b1bb3874649c8c6e9bb67d3b90d48380ba24c69c23ea" +"checksum ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "17f52a24414403f81528b67488cf8edc4eda977d3af1646bb6b106a600ead78f" "checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" @@ -2097,6 +2356,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum serde_repr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "29a734c298df0346c4cd5919595981c266dabbf12dc747c85e1a95e96077a52b" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" +"checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" +"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" @@ -2110,6 +2371,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" +"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" @@ -2125,6 +2387,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" +"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" "checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" "checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" @@ -2150,3 +2414,4 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" +"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" diff --git a/Cargo.toml b/Cargo.toml index 9c4ce1b1..f41eb04a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [workspace] members = [ "server", + "rojo-test", ] [profile.dev] diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml new file mode 100644 index 00000000..56736dbd --- /dev/null +++ b/rojo-test/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "rojo-test" +version = "0.1.0" +authors = ["Lucien Greathouse "] +edition = "2018" +publish = false + +[dependencies] +insta = "0.10.0" +tempfile = "3.1.0" \ No newline at end of file diff --git a/rojo-test/build-tests/gitkeep/default.project.json b/rojo-test/build-tests/gitkeep/default.project.json new file mode 100644 index 00000000..baec6224 --- /dev/null +++ b/rojo-test/build-tests/gitkeep/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "gitkeep", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/gitkeep/src/.gitkeep b/rojo-test/build-tests/gitkeep/src/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/rojo-test/build-tests/txt_in_folder/default.project.json b/rojo-test/build-tests/txt_in_folder/default.project.json new file mode 100644 index 00000000..bb71350c --- /dev/null +++ b/rojo-test/build-tests/txt_in_folder/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "txt_in_folder", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/txt_in_folder/src/foo.txt b/rojo-test/build-tests/txt_in_folder/src/foo.txt new file mode 100644 index 00000000..e69de29b diff --git a/rojo-test/src/lib.rs b/rojo-test/src/lib.rs new file mode 100644 index 00000000..79e4d643 --- /dev/null +++ b/rojo-test/src/lib.rs @@ -0,0 +1,43 @@ +use std::{ + fs, + path::Path, + process::Command, +}; + +use insta::assert_snapshot_matches; +use tempfile::tempdir; + +static BUILD_TESTS: &[&str] = &[ + "gitkeep", + "txt_in_folder", +]; + +#[test] +fn build_tests() { + let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + let build_test_path = manifest_dir.join("build-tests"); + let working_dir = manifest_dir.parent().unwrap(); + + let output_dir = tempdir().expect("couldn't create temporary directory"); + + for &test_name in BUILD_TESTS { + let input_path = build_test_path.join(test_name); + let output_path = output_dir.path().join(format!("{}.rbxmx", test_name)); + + let status = Command::new("cargo") + .args(&[ + "run", "--", + "build", input_path.to_str().unwrap(), "-o", output_path.to_str().unwrap(), + ]) + .current_dir(working_dir) + .status() + .expect("Couldn't start Rojo"); + + assert!(status.success(), "Rojo did not exit successfully"); + + let contents = fs::read_to_string(&output_path) + .expect("Couldn't read output file"); + + assert_snapshot_matches!(format!("build_{}", test_name), contents); + } +} \ No newline at end of file diff --git a/rojo-test/src/snapshots/rojo_test__build_gitkeep.snap b/rojo-test/src/snapshots/rojo_test__build_gitkeep.snap new file mode 100644 index 00000000..f3c5e8e5 --- /dev/null +++ b/rojo-test/src/snapshots/rojo_test__build_gitkeep.snap @@ -0,0 +1,13 @@ +--- +created: "2019-08-08T00:40:36.892733600Z" +creator: insta@0.10.0 +source: rojo-test/src/lib.rs +expression: contents +--- + + + + gitkeep + + + diff --git a/rojo-test/src/snapshots/rojo_test__build_txt_in_folder.snap b/rojo-test/src/snapshots/rojo_test__build_txt_in_folder.snap new file mode 100644 index 00000000..f7119804 --- /dev/null +++ b/rojo-test/src/snapshots/rojo_test__build_txt_in_folder.snap @@ -0,0 +1,19 @@ +--- +created: "2019-08-08T00:40:50.026718300Z" +creator: insta@0.10.0 +source: rojo-test/src/lib.rs +expression: contents +--- + + + + txt_in_folder + + + + foo + + + + + From 08df71a7e4f5930ebd362a3f0411664f7c1bdc7d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 7 Aug 2019 17:50:05 -0700 Subject: [PATCH 0590/1504] Change rojo-test to be macro-based --- Cargo.lock | 1 + rojo-test/Cargo.toml | 1 + rojo-test/src/build_test.rs | 53 +++++++++++++++++++ rojo-test/src/lib.rs | 45 +--------------- ..._gitkeep.snap => build_test__gitkeep.snap} | 4 +- ...er.snap => build_test__txt_in_folder.snap} | 4 +- 6 files changed, 61 insertions(+), 47 deletions(-) create mode 100644 rojo-test/src/build_test.rs rename rojo-test/src/snapshots/{rojo_test__build_gitkeep.snap => build_test__gitkeep.snap} (72%) rename rojo-test/src/snapshots/{rojo_test__build_txt_in_folder.snap => build_test__txt_in_folder.snap} (83%) diff --git a/Cargo.lock b/Cargo.lock index c70d5de0..016d4c2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1541,6 +1541,7 @@ name = "rojo-test" version = "0.1.0" dependencies = [ "insta 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index 56736dbd..cb768b77 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -7,4 +7,5 @@ publish = false [dependencies] insta = "0.10.0" +paste = "0.1.5" tempfile = "3.1.0" \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs new file mode 100644 index 00000000..3d2734f3 --- /dev/null +++ b/rojo-test/src/build_test.rs @@ -0,0 +1,53 @@ +use std::{ + fs, + path::Path, + process::Command, +}; + +use insta::assert_snapshot_matches; +use tempfile::tempdir; + +macro_rules! gen_build_tests { + ( $($test_name: ident,)* ) => { + $( + paste::item! { + #[test] + fn []() { + run_build_test(stringify!($test_name)); + } + } + )* + }; +} + +gen_build_tests! { + gitkeep, + txt_in_folder, +} + +fn run_build_test(test_name: &str) { + let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + let build_test_path = manifest_dir.join("build-tests"); + let working_dir = manifest_dir.parent().unwrap(); + + let output_dir = tempdir().expect("couldn't create temporary directory"); + + let input_path = build_test_path.join(test_name); + let output_path = output_dir.path().join(format!("{}.rbxmx", test_name)); + + let status = Command::new("cargo") + .args(&[ + "run", "--quiet", "--", + "build", input_path.to_str().unwrap(), "-o", output_path.to_str().unwrap(), + ]) + .current_dir(working_dir) + .status() + .expect("Couldn't start Rojo"); + + assert!(status.success(), "Rojo did not exit successfully"); + + let contents = fs::read_to_string(&output_path) + .expect("Couldn't read output file"); + + assert_snapshot_matches!(test_name, contents); +} \ No newline at end of file diff --git a/rojo-test/src/lib.rs b/rojo-test/src/lib.rs index 79e4d643..58bd5ab1 100644 --- a/rojo-test/src/lib.rs +++ b/rojo-test/src/lib.rs @@ -1,43 +1,2 @@ -use std::{ - fs, - path::Path, - process::Command, -}; - -use insta::assert_snapshot_matches; -use tempfile::tempdir; - -static BUILD_TESTS: &[&str] = &[ - "gitkeep", - "txt_in_folder", -]; - -#[test] -fn build_tests() { - let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); - let build_test_path = manifest_dir.join("build-tests"); - let working_dir = manifest_dir.parent().unwrap(); - - let output_dir = tempdir().expect("couldn't create temporary directory"); - - for &test_name in BUILD_TESTS { - let input_path = build_test_path.join(test_name); - let output_path = output_dir.path().join(format!("{}.rbxmx", test_name)); - - let status = Command::new("cargo") - .args(&[ - "run", "--", - "build", input_path.to_str().unwrap(), "-o", output_path.to_str().unwrap(), - ]) - .current_dir(working_dir) - .status() - .expect("Couldn't start Rojo"); - - assert!(status.success(), "Rojo did not exit successfully"); - - let contents = fs::read_to_string(&output_path) - .expect("Couldn't read output file"); - - assert_snapshot_matches!(format!("build_{}", test_name), contents); - } -} \ No newline at end of file +#[cfg(test)] +mod build_test; \ No newline at end of file diff --git a/rojo-test/src/snapshots/rojo_test__build_gitkeep.snap b/rojo-test/src/snapshots/build_test__gitkeep.snap similarity index 72% rename from rojo-test/src/snapshots/rojo_test__build_gitkeep.snap rename to rojo-test/src/snapshots/build_test__gitkeep.snap index f3c5e8e5..5db8bcd0 100644 --- a/rojo-test/src/snapshots/rojo_test__build_gitkeep.snap +++ b/rojo-test/src/snapshots/build_test__gitkeep.snap @@ -1,7 +1,7 @@ --- -created: "2019-08-08T00:40:36.892733600Z" +created: "2019-08-08T00:48:33.382271800Z" creator: insta@0.10.0 -source: rojo-test/src/lib.rs +source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/src/snapshots/rojo_test__build_txt_in_folder.snap b/rojo-test/src/snapshots/build_test__txt_in_folder.snap similarity index 83% rename from rojo-test/src/snapshots/rojo_test__build_txt_in_folder.snap rename to rojo-test/src/snapshots/build_test__txt_in_folder.snap index f7119804..71292e94 100644 --- a/rojo-test/src/snapshots/rojo_test__build_txt_in_folder.snap +++ b/rojo-test/src/snapshots/build_test__txt_in_folder.snap @@ -1,7 +1,7 @@ --- -created: "2019-08-08T00:40:50.026718300Z" +created: "2019-08-08T00:48:33.502257600Z" creator: insta@0.10.0 -source: rojo-test/src/lib.rs +source: rojo-test/src/build_test.rs expression: contents --- From 3fe15641c7adb350a8cbe19efe5c94b45f052140 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 7 Aug 2019 17:54:15 -0700 Subject: [PATCH 0591/1504] Ignore new insta snaps --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index dcad1526..506a95be 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ /*.rbxm /*.rbxmx /*.rbxl -/*.rbxlx \ No newline at end of file +/*.rbxlx +**/*.snap.new \ No newline at end of file From d4a7de80700cabb73a726d55d31fc8af5c8c2baa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 8 Aug 2019 16:57:01 -0700 Subject: [PATCH 0592/1504] Update dependencies --- Cargo.lock | 195 ++++++++++++++++++++++------------------------------- 1 file changed, 79 insertions(+), 116 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 016d4c2a..ad7afd3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,7 +7,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "aho-corasick" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -222,8 +222,8 @@ dependencies = [ "encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -342,7 +342,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -389,7 +389,7 @@ dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -418,7 +418,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -525,7 +525,7 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -739,6 +739,14 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "lock_api" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "log" version = "0.4.8" @@ -807,18 +815,16 @@ dependencies = [ [[package]] name = "mime_guess" -version = "2.0.0-alpha.6" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "miniz_oxide" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -832,7 +838,7 @@ dependencies = [ "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1009,6 +1015,16 @@ dependencies = [ "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "parking_lot_core" version = "0.4.0" @@ -1021,6 +1037,20 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "parking_lot_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "paste" version = "0.1.5" @@ -1038,7 +1068,7 @@ dependencies = [ "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1072,7 +1102,7 @@ dependencies = [ "pest_meta 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1085,41 +1115,6 @@ dependencies = [ "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "phf" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_codegen" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_generator" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "phf_shared" -version = "0.7.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "pkg-config" version = "0.3.15" @@ -1148,7 +1143,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1172,7 +1167,7 @@ dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1217,7 +1212,7 @@ dependencies = [ "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1232,7 +1227,7 @@ name = "rand" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1262,12 +1257,12 @@ name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rand_core" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1275,7 +1270,7 @@ name = "rand_core" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1308,7 +1303,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1320,7 +1315,7 @@ dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1331,7 +1326,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1380,7 +1375,7 @@ dependencies = [ [[package]] name = "rbx_xml" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1405,14 +1400,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1425,11 +1419,8 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.10" +version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "remove_dir_all" @@ -1456,7 +1447,7 @@ dependencies = [ "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1524,8 +1515,8 @@ dependencies = [ "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 3.2.395 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1648,7 +1639,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1668,7 +1659,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1704,11 +1695,6 @@ dependencies = [ "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "siphasher" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "skeptic" version = "0.13.4" @@ -1762,7 +1748,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.42" +version = "0.15.43" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1777,7 +1763,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1991,19 +1977,6 @@ name = "ucd-trie" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "ucd-util" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicase" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "unicase" version = "2.4.0" @@ -2048,11 +2021,6 @@ dependencies = [ "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "utf8-ranges" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "uuid" version = "0.7.4" @@ -2175,7 +2143,7 @@ dependencies = [ [metadata] "checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" -"checksum aho-corasick 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "36b7aa1ccb7d7ea3f437cf025a2ab1c47cc6c1bc9fc84918ff449def12f5e282" +"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" @@ -2237,7 +2205,7 @@ dependencies = [ "checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum getrandom 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8e190892c840661957ba9f32dacfb3eb405e657f9f9f60485605f0bb37d6f8" +"checksum getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "34f33de6f0ae7c9cb5e574502a562e2b512799e32abb801cd1e79ad952b62b49" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" @@ -2260,6 +2228,7 @@ dependencies = [ "checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" @@ -2269,8 +2238,8 @@ dependencies = [ "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" "checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" -"checksum mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30de2e4613efcba1ec63d8133f344076952090c122992a903359be5a4f99c3ed" -"checksum miniz_oxide 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c061edee74a88eb35d876ce88b94d77a0448a201de111c244b70d047f5820516" +"checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" +"checksum miniz_oxide 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fe2959c5a0747a8d7a56b4444c252ffd2dda5d452cfd147cdfdda73b1c3ece5b" "checksum miniz_oxide_c_api 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6c675792957b0d19933816c4e1d56663c341dd9bfa31cb2140ff2267c1d8ecf4" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" @@ -2289,7 +2258,9 @@ dependencies = [ "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4a4a1c555c6505821f9d58b8779d0f630a6b7e4e1be24ba718610acf01fa79" "checksum paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26e796e623b8b257215f27e6c80a5478856cae305f5b59810ff9acdaa34570e6" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" @@ -2297,10 +2268,6 @@ dependencies = [ "checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" "checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646" "checksum pest_meta 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f249ea6de7c7b7aba92b4ff4376a994c6dbd98fd2166c89d5c4947397ecb574d" -"checksum phf 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b3da44b85f8e8dfaec21adae67f95d93244b2ecf6ad2a692320598dcc8e6dd18" -"checksum phf_codegen 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "b03e85129e324ad4166b06b2c7491ae27fe3ec353af72e72cd1654c7225d517e" -"checksum phf_generator 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "09364cc93c159b8b06b1f4dd8a4398984503483891b0c26b867cf431fb132662" -"checksum phf_shared 0.7.24 (registry+https://github.com/rust-lang/crates.io-index)" = "234f71a15de2288bcb7e3b6515828d22af7ec8598ee6d24c3b526fa0a80b67a0" "checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" @@ -2317,7 +2284,7 @@ dependencies = [ "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0e7a549d590831370895ab7ba4ea0c1b6b011d106b5ff2da6eee112615e6dc0" +"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" "checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" @@ -2329,12 +2296,12 @@ dependencies = [ "checksum rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81428c521a07a3feac9c31180a886e467eecf81b769987f70d51d567a09c321d" "checksum rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb8079fe850096bd18582a8661f5d7a6afee61bc914691be2f287050f3ac0ec4" "checksum rbx_reflection 3.2.395 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b43ccce9c29e9f1774359cb96b6ea0c1b897d416dc00f5b45cf54866ca7997" -"checksum rbx_xml 0.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1b837fbcbbd4e0c82c0ba96d6b688a1a3b504a5b95aa4f09e2ede5b9deeb8186" +"checksum rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0236363b0af0c78f3e972ac7f46a1f355f663518e276253136d0180f3c8742c" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum regex 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b23da8dfd98a84bd7e08700190a5d9f7d2d38abd4369dd1dae651bc40bfd2cc" +"checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26" "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" -"checksum regex-syntax 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5485bf1523a9ed51c4964273f22f63f24e31632adb5dad134f488f86a3875c" +"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum reqwest 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0777154c2c3eb54f5c480db01de845652d941e47191277cc673634c3853939" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" @@ -2359,7 +2326,6 @@ dependencies = [ "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" -"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" @@ -2367,7 +2333,7 @@ dependencies = [ "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)" = "eadc09306ca51a40555dd6fc2b415538e9e18bc9f870e47b1a524a79fe2dcf5e" +"checksum syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ee06ea4b620ab59a2267c6b48be16244a3389f8bfa0986bdd15c35b890b00af3" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" @@ -2390,15 +2356,12 @@ dependencies = [ "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" -"checksum ucd-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa9b3b49edd3468c0e6565d85783f51af95212b6fa3986a5500954f00b460874" -"checksum unicase 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7f4765f83163b74f957c797ad9253caf97f103fb064d3999aea9568d09fc8a33" "checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" "checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" From 5d53f8bfb356c1e728f39f5827881e3f3c480134 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 8 Aug 2019 18:30:53 -0700 Subject: [PATCH 0593/1504] Add script build tests --- .../client_in_folder/default.project.json | 6 ++++++ .../folder/localScript.client.lua | 1 + .../module_in_folder/default.project.json | 6 ++++++ .../module_in_folder/folder/aModule.lua | 1 + .../server_in_folder/default.project.json | 6 ++++++ .../folder/serverScript.server.lua | 1 + rojo-test/src/build_test.rs | 3 +++ .../build_test__client_in_folder.snap | 19 +++++++++++++++++++ .../build_test__module_in_folder.snap | 19 +++++++++++++++++++ .../build_test__server_in_folder.snap | 19 +++++++++++++++++++ 10 files changed, 81 insertions(+) create mode 100644 rojo-test/build-tests/client_in_folder/default.project.json create mode 100644 rojo-test/build-tests/client_in_folder/folder/localScript.client.lua create mode 100644 rojo-test/build-tests/module_in_folder/default.project.json create mode 100644 rojo-test/build-tests/module_in_folder/folder/aModule.lua create mode 100644 rojo-test/build-tests/server_in_folder/default.project.json create mode 100644 rojo-test/build-tests/server_in_folder/folder/serverScript.server.lua create mode 100644 rojo-test/src/snapshots/build_test__client_in_folder.snap create mode 100644 rojo-test/src/snapshots/build_test__module_in_folder.snap create mode 100644 rojo-test/src/snapshots/build_test__server_in_folder.snap diff --git a/rojo-test/build-tests/client_in_folder/default.project.json b/rojo-test/build-tests/client_in_folder/default.project.json new file mode 100644 index 00000000..6e6f94d3 --- /dev/null +++ b/rojo-test/build-tests/client_in_folder/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "client_in_folder", + "tree": { + "$path": "folder" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/client_in_folder/folder/localScript.client.lua b/rojo-test/build-tests/client_in_folder/folder/localScript.client.lua new file mode 100644 index 00000000..849d9791 --- /dev/null +++ b/rojo-test/build-tests/client_in_folder/folder/localScript.client.lua @@ -0,0 +1 @@ +-- This is a Lua client script \ No newline at end of file diff --git a/rojo-test/build-tests/module_in_folder/default.project.json b/rojo-test/build-tests/module_in_folder/default.project.json new file mode 100644 index 00000000..4d98a2d2 --- /dev/null +++ b/rojo-test/build-tests/module_in_folder/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "module_in_folder", + "tree": { + "$path": "folder" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/module_in_folder/folder/aModule.lua b/rojo-test/build-tests/module_in_folder/folder/aModule.lua new file mode 100644 index 00000000..9f842de3 --- /dev/null +++ b/rojo-test/build-tests/module_in_folder/folder/aModule.lua @@ -0,0 +1 @@ +-- This is a Lua module \ No newline at end of file diff --git a/rojo-test/build-tests/server_in_folder/default.project.json b/rojo-test/build-tests/server_in_folder/default.project.json new file mode 100644 index 00000000..ca33d6cd --- /dev/null +++ b/rojo-test/build-tests/server_in_folder/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "server_in_folder", + "tree": { + "$path": "folder" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/server_in_folder/folder/serverScript.server.lua b/rojo-test/build-tests/server_in_folder/folder/serverScript.server.lua new file mode 100644 index 00000000..dd72db00 --- /dev/null +++ b/rojo-test/build-tests/server_in_folder/folder/serverScript.server.lua @@ -0,0 +1 @@ +-- This is a Lua server script \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index 3d2734f3..bcd2e750 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -21,7 +21,10 @@ macro_rules! gen_build_tests { } gen_build_tests! { + client_in_folder, gitkeep, + module_in_folder, + server_in_folder, txt_in_folder, } diff --git a/rojo-test/src/snapshots/build_test__client_in_folder.snap b/rojo-test/src/snapshots/build_test__client_in_folder.snap new file mode 100644 index 00000000..d43e50c2 --- /dev/null +++ b/rojo-test/src/snapshots/build_test__client_in_folder.snap @@ -0,0 +1,19 @@ +--- +created: "2019-08-09T01:29:47.650277200Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + client_in_folder + + + + localScript + -- This is a Lua client script + + + + diff --git a/rojo-test/src/snapshots/build_test__module_in_folder.snap b/rojo-test/src/snapshots/build_test__module_in_folder.snap new file mode 100644 index 00000000..dd5d9895 --- /dev/null +++ b/rojo-test/src/snapshots/build_test__module_in_folder.snap @@ -0,0 +1,19 @@ +--- +created: "2019-08-09T01:27:22.597759700Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + module_in_folder + + + + aModule + -- This is a Lua module + + + + diff --git a/rojo-test/src/snapshots/build_test__server_in_folder.snap b/rojo-test/src/snapshots/build_test__server_in_folder.snap new file mode 100644 index 00000000..14037d0a --- /dev/null +++ b/rojo-test/src/snapshots/build_test__server_in_folder.snap @@ -0,0 +1,19 @@ +--- +created: "2019-08-09T01:29:48.071133300Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + server_in_folder + + + + serverScript + -- This is a Lua server script + + + + From de0bb069aa1ac21fd24b810dd169578cf47738e1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 8 Aug 2019 21:08:10 -0700 Subject: [PATCH 0594/1504] Reduce Travis-CI build load - Remove testing with --all-features, no features are supported - Remove testing beta, it isn't useful and takes up valuable CI time --- .travis.yml | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/.travis.yml b/.travis.yml index b0571af9..211045be 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,20 +35,10 @@ matrix: script: - cargo test --verbose - - cargo test --verbose --all-features - language: rust rust: stable cache: cargo script: - - cargo test --verbose - - cargo test --verbose --all-features - - - language: rust - rust: beta - cache: cargo - - script: - - cargo test --verbose - - cargo test --verbose --all-features \ No newline at end of file + - cargo test --verbose \ No newline at end of file From eeedcc50abd9272fcd31c3906595d954ba41d0ac Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 8 Aug 2019 21:36:21 -0700 Subject: [PATCH 0595/1504] Update rbx-dom dependency URL --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index a9420e24..c399195f 100644 --- a/.gitmodules +++ b/.gitmodules @@ -15,4 +15,4 @@ url = https://github.com/osyrisrblx/t.git [submodule "plugin/modules/rbx-dom"] path = plugin/modules/rbx-dom - url = http://github.com/LPGhatguy/rbx-dom + url = http://github.com/rojo-rbx/rbx-dom \ No newline at end of file From 89671c71fa9999222ed739dcb77c4c0bf81d9b0e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 10 Aug 2019 00:52:16 -0700 Subject: [PATCH 0596/1504] Add basic rbxmx snapshot test --- .../rbxmx_in_folder/default.project.json | 6 +++ .../rbxmx_in_folder/folder/test-model.rbxmx | 33 +++++++++++++++ rojo-test/src/build_test.rs | 1 + .../build_test__rbxmx_in_folder.snap | 41 +++++++++++++++++++ 4 files changed, 81 insertions(+) create mode 100644 rojo-test/build-tests/rbxmx_in_folder/default.project.json create mode 100644 rojo-test/build-tests/rbxmx_in_folder/folder/test-model.rbxmx create mode 100644 rojo-test/src/snapshots/build_test__rbxmx_in_folder.snap diff --git a/rojo-test/build-tests/rbxmx_in_folder/default.project.json b/rojo-test/build-tests/rbxmx_in_folder/default.project.json new file mode 100644 index 00000000..ca93cbfc --- /dev/null +++ b/rojo-test/build-tests/rbxmx_in_folder/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "rbxmx_in_folder", + "tree": { + "$path": "folder" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/rbxmx_in_folder/folder/test-model.rbxmx b/rojo-test/build-tests/rbxmx_in_folder/folder/test-model.rbxmx new file mode 100644 index 00000000..dbdd2969 --- /dev/null +++ b/rojo-test/build-tests/rbxmx_in_folder/folder/test-model.rbxmx @@ -0,0 +1,33 @@ + + true + null + nil + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Awesome Model + null + + + + + Cool StringValue + + Did you know that BaseValue.Changed is different than Instance.Changed? + + + + \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index bcd2e750..ccc26c43 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -24,6 +24,7 @@ gen_build_tests! { client_in_folder, gitkeep, module_in_folder, + rbxmx_in_folder, server_in_folder, txt_in_folder, } diff --git a/rojo-test/src/snapshots/build_test__rbxmx_in_folder.snap b/rojo-test/src/snapshots/build_test__rbxmx_in_folder.snap new file mode 100644 index 00000000..831fba35 --- /dev/null +++ b/rojo-test/src/snapshots/build_test__rbxmx_in_folder.snap @@ -0,0 +1,41 @@ +--- +created: "2019-08-10T07:45:07.961823500Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + rbxmx_in_folder + + + + test-model + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + null + + + + + Cool StringValue + + Did you know that BaseValue.Changed is different than Instance.Changed? + + + + + From edf157215c547494f2bd0287685a82924d9e6b6e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 12 Aug 2019 10:28:29 -0700 Subject: [PATCH 0597/1504] docs: Embed RDC 2019 video into 'Why Rojo' page. Closes #227. --- docs/why-rojo.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/why-rojo.md b/docs/why-rojo.md index 64e135c9..05324834 100644 --- a/docs/why-rojo.md +++ b/docs/why-rojo.md @@ -2,6 +2,11 @@ Adding a tool like Rojo to your Roblox workflow can be daunting, but it comes wi [TOC] +## Rojo at RDC 2019 +Nathan Riemer (Kampfkarren) gave a talk at RDC 2019 talking about some of the benefits of using a tool like Rojo. + + + ## External Text Editors Rojo opens the door to use the absolute best text editors in the world and their rich plugin ecosystems. From 97985dd4583e8668b540f438ddf96e99df0e8bbe Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 13 Aug 2019 11:00:33 -0700 Subject: [PATCH 0598/1504] Fix test warning that's been in the codebase forever --- server/tests/snapshot_snapshots.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/server/tests/snapshot_snapshots.rs b/server/tests/snapshot_snapshots.rs index 4c143f38..e964858c 100644 --- a/server/tests/snapshot_snapshots.rs +++ b/server/tests/snapshot_snapshots.rs @@ -2,8 +2,6 @@ mod test_util; use std::path::Path; -use pretty_assertions::assert_eq; - use librojo::{ imfs::Imfs, project::Project, From 08211a77401b67ef2a63e80642930dc6f207082b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 14 Aug 2019 15:07:37 -0700 Subject: [PATCH 0599/1504] Add rbxm build test --- .../rbxm_in_folder/default.project.json | 6 ++++++ .../rbxm_in_folder/folder/foo.rbxm | Bin 0 -> 176 bytes rojo-test/src/build_test.rs | 1 + .../snapshots/build_test__rbxm_in_folder.snap | 18 ++++++++++++++++++ 4 files changed, 25 insertions(+) create mode 100644 rojo-test/build-tests/rbxm_in_folder/default.project.json create mode 100644 rojo-test/build-tests/rbxm_in_folder/folder/foo.rbxm create mode 100644 rojo-test/src/snapshots/build_test__rbxm_in_folder.snap diff --git a/rojo-test/build-tests/rbxm_in_folder/default.project.json b/rojo-test/build-tests/rbxm_in_folder/default.project.json new file mode 100644 index 00000000..fcd46779 --- /dev/null +++ b/rojo-test/build-tests/rbxm_in_folder/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "rbxm_in_folder", + "tree": { + "$path": "folder" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/rbxm_in_folder/folder/foo.rbxm b/rojo-test/build-tests/rbxm_in_folder/folder/foo.rbxm new file mode 100644 index 0000000000000000000000000000000000000000..b152415df26f24d108cf457b29cd72e064eab9f6 GIT binary patch literal 176 zcmcC1%1_G4uTbp#&&wsn#lXPG0Kq^C3_SgULnMJLaVY--2Z+H2#BTXHDXB$Z4IrU_ zApZabAT0;t0Ko@-5Xl0>eu=rMjJ!ZbK~7?3UVM6HNp@;#K|qjS2p>=oBmn{!;3fe% UjIMqzU{Ovm$-rQv4{@g*0KEJeKL7v# literal 0 HcmV?d00001 diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index ccc26c43..dd678c0c 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -24,6 +24,7 @@ gen_build_tests! { client_in_folder, gitkeep, module_in_folder, + rbxm_in_folder, rbxmx_in_folder, server_in_folder, txt_in_folder, diff --git a/rojo-test/src/snapshots/build_test__rbxm_in_folder.snap b/rojo-test/src/snapshots/build_test__rbxm_in_folder.snap new file mode 100644 index 00000000..574500ce --- /dev/null +++ b/rojo-test/src/snapshots/build_test__rbxm_in_folder.snap @@ -0,0 +1,18 @@ +--- +created: "2019-08-14T22:05:46.597722600Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + rbxm_in_folder + + + + foo + + + + From b84cb93d2c8561166f9a60fdc762c77553bf398d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 14 Aug 2019 15:33:00 -0700 Subject: [PATCH 0600/1504] Remove test warning --- server/tests/snapshot_reconciler.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/server/tests/snapshot_reconciler.rs b/server/tests/snapshot_reconciler.rs index 34dec829..02bfd5a9 100644 --- a/server/tests/snapshot_reconciler.rs +++ b/server/tests/snapshot_reconciler.rs @@ -2,7 +2,6 @@ mod test_util; use std::collections::HashMap; -use pretty_assertions::assert_eq; use rbx_dom_weak::{RbxTree, RbxInstanceProperties}; use librojo::{ From cc34c3679408db1865c37c75f0bd0a74778546ca Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 14 Aug 2019 15:34:25 -0700 Subject: [PATCH 0601/1504] Add CSV snapshot test --- .../csv_in_folder/default.project.json | 6 ++++++ .../csv_in_folder/folder/normal.csv | 2 ++ rojo-test/src/build_test.rs | 1 + .../snapshots/build_test__csv_in_folder.snap | 19 +++++++++++++++++++ 4 files changed, 28 insertions(+) create mode 100644 rojo-test/build-tests/csv_in_folder/default.project.json create mode 100644 rojo-test/build-tests/csv_in_folder/folder/normal.csv create mode 100644 rojo-test/src/snapshots/build_test__csv_in_folder.snap diff --git a/rojo-test/build-tests/csv_in_folder/default.project.json b/rojo-test/build-tests/csv_in_folder/default.project.json new file mode 100644 index 00000000..4ee64843 --- /dev/null +++ b/rojo-test/build-tests/csv_in_folder/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "csv_in_folder", + "tree": { + "$path": "folder" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/csv_in_folder/folder/normal.csv b/rojo-test/build-tests/csv_in_folder/folder/normal.csv new file mode 100644 index 00000000..220cbe87 --- /dev/null +++ b/rojo-test/build-tests/csv_in_folder/folder/normal.csv @@ -0,0 +1,2 @@ +Key,Source,Context,Example,es +Ack,Ack!,,An exclamation of despair,¡Ay! \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index dd678c0c..660befa1 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -22,6 +22,7 @@ macro_rules! gen_build_tests { gen_build_tests! { client_in_folder, + csv_in_folder, gitkeep, module_in_folder, rbxm_in_folder, diff --git a/rojo-test/src/snapshots/build_test__csv_in_folder.snap b/rojo-test/src/snapshots/build_test__csv_in_folder.snap new file mode 100644 index 00000000..e6c5fb15 --- /dev/null +++ b/rojo-test/src/snapshots/build_test__csv_in_folder.snap @@ -0,0 +1,19 @@ +--- +created: "2019-08-14T22:34:06.206495600Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + csv_in_folder + + + + normal + [{"key":"Ack","example":"An exclamation of despair","source":"Ack!","values":{"es":"¡Ay!"}}] + + + + From 36bcb611f192d144ab570d8a8812b63b5ded0e02 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 14 Aug 2019 15:50:28 -0700 Subject: [PATCH 0602/1504] Port CSV regression tests to insta --- .../csv_bug_145/default.project.json | 6 ++ .../build-tests/csv_bug_145/folder/normal.csv | 0 .../csv_bug_147/default.project.json | 6 ++ .../build-tests/csv_bug_147/folder/normal.csv | 0 rojo-test/src/build_test.rs | 2 + .../snapshots/build_test__csv_bug_145.snap | 19 +++++ .../snapshots/build_test__csv_bug_147.snap | 19 +++++ server/tests/snapshot_snapshots.rs | 1 - .../localization/default.project.json | 6 -- .../localization/expected-snapshot.json | 69 ------------------- test-projects/localization/src/normal.csv | 2 - 11 files changed, 52 insertions(+), 78 deletions(-) create mode 100644 rojo-test/build-tests/csv_bug_145/default.project.json rename test-projects/localization/src/integers-bug-145.csv => rojo-test/build-tests/csv_bug_145/folder/normal.csv (100%) create mode 100644 rojo-test/build-tests/csv_bug_147/default.project.json rename test-projects/localization/src/empty-column-bug-147.csv => rojo-test/build-tests/csv_bug_147/folder/normal.csv (100%) create mode 100644 rojo-test/src/snapshots/build_test__csv_bug_145.snap create mode 100644 rojo-test/src/snapshots/build_test__csv_bug_147.snap delete mode 100644 test-projects/localization/default.project.json delete mode 100644 test-projects/localization/expected-snapshot.json delete mode 100644 test-projects/localization/src/normal.csv diff --git a/rojo-test/build-tests/csv_bug_145/default.project.json b/rojo-test/build-tests/csv_bug_145/default.project.json new file mode 100644 index 00000000..770ec7c3 --- /dev/null +++ b/rojo-test/build-tests/csv_bug_145/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "csv_bug_145", + "tree": { + "$path": "folder" + } +} \ No newline at end of file diff --git a/test-projects/localization/src/integers-bug-145.csv b/rojo-test/build-tests/csv_bug_145/folder/normal.csv similarity index 100% rename from test-projects/localization/src/integers-bug-145.csv rename to rojo-test/build-tests/csv_bug_145/folder/normal.csv diff --git a/rojo-test/build-tests/csv_bug_147/default.project.json b/rojo-test/build-tests/csv_bug_147/default.project.json new file mode 100644 index 00000000..32bdf51a --- /dev/null +++ b/rojo-test/build-tests/csv_bug_147/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "csv_bug_147", + "tree": { + "$path": "folder" + } +} \ No newline at end of file diff --git a/test-projects/localization/src/empty-column-bug-147.csv b/rojo-test/build-tests/csv_bug_147/folder/normal.csv similarity index 100% rename from test-projects/localization/src/empty-column-bug-147.csv rename to rojo-test/build-tests/csv_bug_147/folder/normal.csv diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index 660befa1..336430f9 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -22,6 +22,8 @@ macro_rules! gen_build_tests { gen_build_tests! { client_in_folder, + csv_bug_145, + csv_bug_147, csv_in_folder, gitkeep, module_in_folder, diff --git a/rojo-test/src/snapshots/build_test__csv_bug_145.snap b/rojo-test/src/snapshots/build_test__csv_bug_145.snap new file mode 100644 index 00000000..052c049d --- /dev/null +++ b/rojo-test/src/snapshots/build_test__csv_bug_145.snap @@ -0,0 +1,19 @@ +--- +created: "2019-08-14T22:42:52.297447700Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + csv_bug_145 + + + + normal + [{"key":"Count","example":"A number demonstrating issue 145","source":"3","values":{"es":"7"}}] + + + + \ No newline at end of file diff --git a/rojo-test/src/snapshots/build_test__csv_bug_147.snap b/rojo-test/src/snapshots/build_test__csv_bug_147.snap new file mode 100644 index 00000000..023ff8da --- /dev/null +++ b/rojo-test/src/snapshots/build_test__csv_bug_147.snap @@ -0,0 +1,19 @@ +--- +created: "2019-08-14T22:42:52.310414Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + csv_bug_147 + + + + normal + [{"key":"Language.Name","source":"English","values":{}},{"key":"Language.Region","source":"United States","values":{}},{"key":"Label.Thickness","source":"Thickness","values":{}},{"key":"Label.Opacity","source":"Opacity","values":{}},{"key":"Toolbar.Undo","source":"Undo","values":{}},{"key":"Toolbar.Redo","source":"Redo","values":{}},{"key":"Toolbar.Camera","source":"Top-down camera","values":{}},{"key":"Toolbar.Saves","source":"Saved drawings","values":{}},{"key":"Toolbar.Preferences","source":"Settings","values":{}},{"key":"Toolbar.Mode.Vector","source":"Vector mode","values":{}},{"key":"Toolbar.Mode.Pixel","source":"Pixel mode","values":{}}] + + + + \ No newline at end of file diff --git a/server/tests/snapshot_snapshots.rs b/server/tests/snapshot_snapshots.rs index e964858c..21bad786 100644 --- a/server/tests/snapshot_snapshots.rs +++ b/server/tests/snapshot_snapshots.rs @@ -32,7 +32,6 @@ macro_rules! generate_snapshot_tests { generate_snapshot_tests!( empty, json_model, - localization, meta_files, multi_partition_game, nested_partitions, diff --git a/test-projects/localization/default.project.json b/test-projects/localization/default.project.json deleted file mode 100644 index 64722c35..00000000 --- a/test-projects/localization/default.project.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "localization", - "tree": { - "$path": "src" - } -} \ No newline at end of file diff --git a/test-projects/localization/expected-snapshot.json b/test-projects/localization/expected-snapshot.json deleted file mode 100644 index dc093685..00000000 --- a/test-projects/localization/expected-snapshot.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "name": "localization", - "class_name": "Folder", - "properties": {}, - "children": [ - { - "name": "empty-column-bug-147", - "class_name": "LocalizationTable", - "properties": { - "Contents": { - "Type": "String", - "Value": "[{\"key\":\"Language.Name\",\"source\":\"English\",\"values\":{}},{\"key\":\"Language.Region\",\"source\":\"United States\",\"values\":{}},{\"key\":\"Label.Thickness\",\"source\":\"Thickness\",\"values\":{}},{\"key\":\"Label.Opacity\",\"source\":\"Opacity\",\"values\":{}},{\"key\":\"Toolbar.Undo\",\"source\":\"Undo\",\"values\":{}},{\"key\":\"Toolbar.Redo\",\"source\":\"Redo\",\"values\":{}},{\"key\":\"Toolbar.Camera\",\"source\":\"Top-down camera\",\"values\":{}},{\"key\":\"Toolbar.Saves\",\"source\":\"Saved drawings\",\"values\":{}},{\"key\":\"Toolbar.Preferences\",\"source\":\"Settings\",\"values\":{}},{\"key\":\"Toolbar.Mode.Vector\",\"source\":\"Vector mode\",\"values\":{}},{\"key\":\"Toolbar.Mode.Pixel\",\"source\":\"Pixel mode\",\"values\":{}}]" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src/empty-column-bug-147.csv", - "project_definition": null - } - }, - { - "name": "integers-bug-145", - "class_name": "LocalizationTable", - "properties": { - "Contents": { - "Type": "String", - "Value": "[{\"key\":\"Count\",\"example\":\"A number demonstrating issue 145\",\"source\":\"3\",\"values\":{\"es\":\"7\"}}]" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src/integers-bug-145.csv", - "project_definition": null - } - }, - { - "name": "normal", - "class_name": "LocalizationTable", - "properties": { - "Contents": { - "Type": "String", - "Value": "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src/normal.csv", - "project_definition": null - } - } - ], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src", - "project_definition": [ - "localization", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "src" - } - ] - } -} \ No newline at end of file diff --git a/test-projects/localization/src/normal.csv b/test-projects/localization/src/normal.csv deleted file mode 100644 index 220cbe87..00000000 --- a/test-projects/localization/src/normal.csv +++ /dev/null @@ -1,2 +0,0 @@ -Key,Source,Context,Example,es -Ack,Ack!,,An exclamation of despair,¡Ay! \ No newline at end of file From 7575504b802e0fd0e8070b40cf0e98107c89d6b5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 14 Aug 2019 18:03:19 -0700 Subject: [PATCH 0603/1504] Add build test for JSON model --- .../json_model_in_folder/default.project.json | 6 +++++ .../folder/foo.model.json | 13 ++++++++++ rojo-test/src/build_test.rs | 1 + .../build_test__json_model_in_folder.snap | 24 +++++++++++++++++++ 4 files changed, 44 insertions(+) create mode 100644 rojo-test/build-tests/json_model_in_folder/default.project.json create mode 100644 rojo-test/build-tests/json_model_in_folder/folder/foo.model.json create mode 100644 rojo-test/src/snapshots/build_test__json_model_in_folder.snap diff --git a/rojo-test/build-tests/json_model_in_folder/default.project.json b/rojo-test/build-tests/json_model_in_folder/default.project.json new file mode 100644 index 00000000..273ff10b --- /dev/null +++ b/rojo-test/build-tests/json_model_in_folder/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "json_model_in_folder", + "tree": { + "$path": "folder" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/json_model_in_folder/folder/foo.model.json b/rojo-test/build-tests/json_model_in_folder/folder/foo.model.json new file mode 100644 index 00000000..260f6c7e --- /dev/null +++ b/rojo-test/build-tests/json_model_in_folder/folder/foo.model.json @@ -0,0 +1,13 @@ +{ + "Name": "Top-Level Value", + "ClassName": "IntValue", + "Properties": { + "Value": 5 + }, + "Children": [ + { + "Name": "A Child", + "ClassName": "Folder" + } + ] +} \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index 336430f9..6f0b9614 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -26,6 +26,7 @@ gen_build_tests! { csv_bug_147, csv_in_folder, gitkeep, + json_model_in_folder, module_in_folder, rbxm_in_folder, rbxmx_in_folder, diff --git a/rojo-test/src/snapshots/build_test__json_model_in_folder.snap b/rojo-test/src/snapshots/build_test__json_model_in_folder.snap new file mode 100644 index 00000000..5151ba9a --- /dev/null +++ b/rojo-test/src/snapshots/build_test__json_model_in_folder.snap @@ -0,0 +1,24 @@ +--- +created: "2019-08-15T01:02:40.318937300Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + json_model_in_folder + + + + Top-Level Value + 5 + + + + A Child + + + + + From 7d45b456671bfb8af28c988797a64a68c30929d5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 15 Aug 2019 14:09:16 -0700 Subject: [PATCH 0604/1504] Change JSON model naming behavior. - JSON model names now come from the file name - The 'Name' field is now optional for the top-level instance - Snapshot tests run way faster by executing Rojo directly instead of Cargo --- Cargo.lock | 1 + rojo-test/Cargo.toml | 5 +- ...foo.model.json => simple-model.model.json} | 1 - .../default.project.json | 6 +++ .../folder/Expected Name.model.json | 4 ++ rojo-test/src/build_test.rs | 10 +++- .../build_test__json_model_in_folder.snap | 4 +- .../build_test__json_model_legacy_name.snap | 18 +++++++ server/src/rbx_snapshot.rs | 47 ++++++++++++++++--- 9 files changed, 84 insertions(+), 12 deletions(-) rename rojo-test/build-tests/json_model_in_folder/folder/{foo.model.json => simple-model.model.json} (84%) create mode 100644 rojo-test/build-tests/json_model_legacy_name/default.project.json create mode 100644 rojo-test/build-tests/json_model_legacy_name/folder/Expected Name.model.json create mode 100644 rojo-test/src/snapshots/build_test__json_model_legacy_name.snap diff --git a/Cargo.lock b/Cargo.lock index ad7afd3d..ebc23612 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1533,6 +1533,7 @@ version = "0.1.0" dependencies = [ "insta 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rojo 0.5.0-alpha.13", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index cb768b77..43403be0 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -8,4 +8,7 @@ publish = false [dependencies] insta = "0.10.0" paste = "0.1.5" -tempfile = "3.1.0" \ No newline at end of file +tempfile = "3.1.0" + +# We execute Rojo via std::process::Command, so depend on it so it's built! +rojo = { path = "../server" } \ No newline at end of file diff --git a/rojo-test/build-tests/json_model_in_folder/folder/foo.model.json b/rojo-test/build-tests/json_model_in_folder/folder/simple-model.model.json similarity index 84% rename from rojo-test/build-tests/json_model_in_folder/folder/foo.model.json rename to rojo-test/build-tests/json_model_in_folder/folder/simple-model.model.json index 260f6c7e..0de9921e 100644 --- a/rojo-test/build-tests/json_model_in_folder/folder/foo.model.json +++ b/rojo-test/build-tests/json_model_in_folder/folder/simple-model.model.json @@ -1,5 +1,4 @@ { - "Name": "Top-Level Value", "ClassName": "IntValue", "Properties": { "Value": 5 diff --git a/rojo-test/build-tests/json_model_legacy_name/default.project.json b/rojo-test/build-tests/json_model_legacy_name/default.project.json new file mode 100644 index 00000000..c7c56c0d --- /dev/null +++ b/rojo-test/build-tests/json_model_legacy_name/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "json_model_legacy_name", + "tree": { + "$path": "folder" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/json_model_legacy_name/folder/Expected Name.model.json b/rojo-test/build-tests/json_model_legacy_name/folder/Expected Name.model.json new file mode 100644 index 00000000..b816d601 --- /dev/null +++ b/rojo-test/build-tests/json_model_legacy_name/folder/Expected Name.model.json @@ -0,0 +1,4 @@ +{ + "Name": "Overridden Name", + "ClassName": "Folder" +} \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index 6f0b9614..c2f21bdd 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -27,6 +27,7 @@ gen_build_tests! { csv_in_folder, gitkeep, json_model_in_folder, + json_model_legacy_name, module_in_folder, rbxm_in_folder, rbxmx_in_folder, @@ -44,11 +45,16 @@ fn run_build_test(test_name: &str) { let input_path = build_test_path.join(test_name); let output_path = output_dir.path().join(format!("{}.rbxmx", test_name)); - let status = Command::new("cargo") + let mut exe_path = working_dir.join("target/debug/rojo"); + if cfg!(windows) { + exe_path.set_extension("exe"); + } + + let status = Command::new(exe_path) .args(&[ - "run", "--quiet", "--", "build", input_path.to_str().unwrap(), "-o", output_path.to_str().unwrap(), ]) + .env("RUST_LOG", "error") .current_dir(working_dir) .status() .expect("Couldn't start Rojo"); diff --git a/rojo-test/src/snapshots/build_test__json_model_in_folder.snap b/rojo-test/src/snapshots/build_test__json_model_in_folder.snap index 5151ba9a..f6242974 100644 --- a/rojo-test/src/snapshots/build_test__json_model_in_folder.snap +++ b/rojo-test/src/snapshots/build_test__json_model_in_folder.snap @@ -1,5 +1,5 @@ --- -created: "2019-08-15T01:02:40.318937300Z" +created: "2019-08-15T20:40:50.467761900Z" creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents @@ -11,7 +11,7 @@ expression: contents - Top-Level Value + simple-model 5 diff --git a/rojo-test/src/snapshots/build_test__json_model_legacy_name.snap b/rojo-test/src/snapshots/build_test__json_model_legacy_name.snap new file mode 100644 index 00000000..adf985c7 --- /dev/null +++ b/rojo-test/src/snapshots/build_test__json_model_legacy_name.snap @@ -0,0 +1,18 @@ +--- +created: "2019-08-15T20:41:28.743618200Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + json_model_legacy_name + + + + Expected Name + + + + diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs index 72369dce..8ed65ea7 100644 --- a/server/src/rbx_snapshot.rs +++ b/server/src/rbx_snapshot.rs @@ -724,28 +724,63 @@ fn snapshot_csv_file<'source>( fn snapshot_json_model_file<'source>( file: &'source ImfsFile, ) -> SnapshotResult<'source> { + let file_name = file.path + .file_name().expect("Could not extract file stem") + .to_str().expect("Could not convert path to UTF-8"); + + let instance_name = match_trailing(file_name, ".model.json") + .expect("JSON model file did not end in .model.json"); + let contents = str::from_utf8(&file.contents) .map_err(|inner| SnapshotError::Utf8Error { inner, path: file.path.to_owned(), })?; - let json_instance: JsonModelInstance = serde_json::from_str(contents) + let json_instance: JsonModel = serde_json::from_str(contents) .map_err(|inner| SnapshotError::JsonModelDecodeError { inner, path: file.path.to_owned(), })?; - let mut snapshot = json_instance.into_snapshot()?; + if let Some(json_name) = &json_instance.name { + if json_name != instance_name { + log::warn!("Name from JSON model did not match its file name: {}", file.path.display()); + log::warn!("In Rojo < alpha 14, this model is named \"{}\" (from its 'Name' property)", json_name); + log::warn!("In Rojo >= alpha 14, this model is named \"{}\" (from its file name)", instance_name); + log::warn!("'Name' for the top-level instance in a JSON model is now optional and will be ignored."); + } + } + + let mut snapshot = json_instance.core.into_snapshot(instance_name.to_owned())?; + + snapshot.name = Cow::Borrowed(instance_name); snapshot.metadata.source_path = Some(file.path.to_owned()); Ok(Some(snapshot)) } +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +struct JsonModel { + name: Option, + + #[serde(flatten)] + core: JsonModelCore, +} + #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "PascalCase")] struct JsonModelInstance { name: String, + + #[serde(flatten)] + core: JsonModelCore, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +struct JsonModelCore { class_name: String, #[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")] @@ -755,12 +790,12 @@ struct JsonModelInstance { properties: HashMap, } -impl JsonModelInstance { - fn into_snapshot(self) -> Result, SnapshotError> { +impl JsonModelCore { + fn into_snapshot(self, name: String) -> Result, SnapshotError> { let mut children = Vec::with_capacity(self.children.len()); for child in self.children { - children.push(child.into_snapshot()?); + children.push(child.core.into_snapshot(child.name)?); } let mut properties = HashMap::with_capacity(self.properties.len()); @@ -771,7 +806,7 @@ impl JsonModelInstance { } Ok(RbxSnapshotInstance { - name: Cow::Owned(self.name), + name: Cow::Owned(name), class_name: Cow::Owned(self.class_name), properties, children, From 6979f5c82d08a72a9e4bc0fc9d30383d799440e6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 16 Aug 2019 12:50:11 -0700 Subject: [PATCH 0605/1504] Add build tests for init Lua files --- .../build-tests/client_init/default.project.json | 6 ++++++ .../build-tests/client_init/folder/init.client.lua | 1 + .../build-tests/module_init/default.project.json | 6 ++++++ rojo-test/build-tests/module_init/folder/init.lua | 1 + .../build-tests/server_init/default.project.json | 6 ++++++ .../build-tests/server_init/folder/init.server.lua | 1 + rojo-test/src/build_test.rs | 3 +++ .../src/snapshots/build_test__client_init.snap | 14 ++++++++++++++ .../src/snapshots/build_test__module_init.snap | 14 ++++++++++++++ .../src/snapshots/build_test__server_init.snap | 14 ++++++++++++++ 10 files changed, 66 insertions(+) create mode 100644 rojo-test/build-tests/client_init/default.project.json create mode 100644 rojo-test/build-tests/client_init/folder/init.client.lua create mode 100644 rojo-test/build-tests/module_init/default.project.json create mode 100644 rojo-test/build-tests/module_init/folder/init.lua create mode 100644 rojo-test/build-tests/server_init/default.project.json create mode 100644 rojo-test/build-tests/server_init/folder/init.server.lua create mode 100644 rojo-test/src/snapshots/build_test__client_init.snap create mode 100644 rojo-test/src/snapshots/build_test__module_init.snap create mode 100644 rojo-test/src/snapshots/build_test__server_init.snap diff --git a/rojo-test/build-tests/client_init/default.project.json b/rojo-test/build-tests/client_init/default.project.json new file mode 100644 index 00000000..9a32ba8b --- /dev/null +++ b/rojo-test/build-tests/client_init/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "client_init", + "tree": { + "$path": "folder" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/client_init/folder/init.client.lua b/rojo-test/build-tests/client_init/folder/init.client.lua new file mode 100644 index 00000000..529e0b29 --- /dev/null +++ b/rojo-test/build-tests/client_init/folder/init.client.lua @@ -0,0 +1 @@ +return "From folder/init.client.lua" \ No newline at end of file diff --git a/rojo-test/build-tests/module_init/default.project.json b/rojo-test/build-tests/module_init/default.project.json new file mode 100644 index 00000000..b531bd8b --- /dev/null +++ b/rojo-test/build-tests/module_init/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "module_init", + "tree": { + "$path": "folder" + } +} diff --git a/rojo-test/build-tests/module_init/folder/init.lua b/rojo-test/build-tests/module_init/folder/init.lua new file mode 100644 index 00000000..16d316ff --- /dev/null +++ b/rojo-test/build-tests/module_init/folder/init.lua @@ -0,0 +1 @@ +return "From folder/init.lua" \ No newline at end of file diff --git a/rojo-test/build-tests/server_init/default.project.json b/rojo-test/build-tests/server_init/default.project.json new file mode 100644 index 00000000..f5585d83 --- /dev/null +++ b/rojo-test/build-tests/server_init/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "server_init", + "tree": { + "$path": "folder" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/server_init/folder/init.server.lua b/rojo-test/build-tests/server_init/folder/init.server.lua new file mode 100644 index 00000000..30d3d49a --- /dev/null +++ b/rojo-test/build-tests/server_init/folder/init.server.lua @@ -0,0 +1 @@ +return "From folder/init.server.lua" \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index c2f21bdd..fa15b73e 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -22,6 +22,7 @@ macro_rules! gen_build_tests { gen_build_tests! { client_in_folder, + client_init, csv_bug_145, csv_bug_147, csv_in_folder, @@ -29,9 +30,11 @@ gen_build_tests! { json_model_in_folder, json_model_legacy_name, module_in_folder, + module_init, rbxm_in_folder, rbxmx_in_folder, server_in_folder, + server_init, txt_in_folder, } diff --git a/rojo-test/src/snapshots/build_test__client_init.snap b/rojo-test/src/snapshots/build_test__client_init.snap new file mode 100644 index 00000000..ce20f536 --- /dev/null +++ b/rojo-test/src/snapshots/build_test__client_init.snap @@ -0,0 +1,14 @@ +--- +created: "2019-08-16T19:37:51.277332900Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + client_init + return "From folder/init.client.lua" + + + diff --git a/rojo-test/src/snapshots/build_test__module_init.snap b/rojo-test/src/snapshots/build_test__module_init.snap new file mode 100644 index 00000000..ce0c3533 --- /dev/null +++ b/rojo-test/src/snapshots/build_test__module_init.snap @@ -0,0 +1,14 @@ +--- +created: "2019-08-16T19:36:55.442461700Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + module_init + return "From folder/init.lua" + + + diff --git a/rojo-test/src/snapshots/build_test__server_init.snap b/rojo-test/src/snapshots/build_test__server_init.snap new file mode 100644 index 00000000..8a104912 --- /dev/null +++ b/rojo-test/src/snapshots/build_test__server_init.snap @@ -0,0 +1,14 @@ +--- +created: "2019-08-16T19:36:55.442461700Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + server_init + return "From folder/init.server.lua" + + + From ca61a3e83f86fa9b3ec3e5adde72dcb549cbced0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 21 Aug 2019 15:45:22 -0700 Subject: [PATCH 0606/1504] Add test case for #201 --- .../slice-center-gh-201/default.project.json | 12 +++ .../folder/image-label.rbxmx | 89 +++++++++++++++++++ 2 files changed, 101 insertions(+) create mode 100644 test-projects/slice-center-gh-201/default.project.json create mode 100644 test-projects/slice-center-gh-201/folder/image-label.rbxmx diff --git a/test-projects/slice-center-gh-201/default.project.json b/test-projects/slice-center-gh-201/default.project.json new file mode 100644 index 00000000..b7ef2cbd --- /dev/null +++ b/test-projects/slice-center-gh-201/default.project.json @@ -0,0 +1,12 @@ +{ + "name": "slice-center-gh-201", + "tree": { + "$className": "DataModel", + + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + + "$path": "folder" + } + } +} \ No newline at end of file diff --git a/test-projects/slice-center-gh-201/folder/image-label.rbxmx b/test-projects/slice-center-gh-201/folder/image-label.rbxmx new file mode 100644 index 00000000..e3ceabe6 --- /dev/null +++ b/test-projects/slice-center-gh-201/folder/image-label.rbxmx @@ -0,0 +1,89 @@ + + true + null + nil + + + false + + 0 + 0 + + true + + 1 + 1 + 1 + + 0 + + 0.105882362 + 0.164705887 + 0.207843155 + + 0 + 1 + false + false + rbxasset://textures/ui/GuiImagePlaceholder.png + + 1 + 1 + 1 + + + 0 + 0 + + + 0 + 0 + + 0 + 0 + ImageLabel + null + null + null + null + + 0 + 0 + 0 + 0 + + null + 0 + 1 + false + null + + 0 + 100 + 0 + 100 + + 0 + + + 1 + 2 + + + 3 + 4 + + + 1 + + + 1 + 0 + 1 + 0 + + true + 1 + + + \ No newline at end of file From 0231e114d58b922c282c07d949299589d8ac5023 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 21 Aug 2019 15:59:57 -0700 Subject: [PATCH 0607/1504] Upgrade rbx_dom_lua. Fixes #201. --- plugin/modules/rbx-dom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index 9d5aad1f..093a68fd 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit 9d5aad1faa00cfbc956a961cfd2b90ebb97c828f +Subproject commit 093a68fd64e824625c089dac4c92a5a542a57bd5 From f40b7361e85c473dac3633b87a1e9d35cc940c96 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 21 Aug 2019 16:08:58 -0700 Subject: [PATCH 0608/1504] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0087a89c..f43eaa3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Fixed `Rect` values being set to `0, 0, 0, 0` when synced with the Rojo plugin. ([#201](https://github.com/rojo-rbx/rojo/issues/201)) ## [0.5.0 Alpha 13](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.13) (August 2, 2019) * Bumped minimum Rust version to 1.34.0. From d6f51f8eba68c549fafcaf4b8666627600d4633e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 26 Aug 2019 13:52:06 -0700 Subject: [PATCH 0609/1504] Upgrade rbx_dom_lua --- plugin/modules/rbx-dom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index 093a68fd..6739c42b 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit 093a68fd64e824625c089dac4c92a5a542a57bd5 +Subproject commit 6739c42bebca95fcb3f847b920d5ac2841846d8f From 32af8783baa2bd5e18fa11b1aacd692af0769d38 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 26 Aug 2019 13:52:16 -0700 Subject: [PATCH 0610/1504] Update Changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f43eaa3a..9e44af46 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,12 @@ # Rojo Changelog ## Unreleased Changes +* Changed `.model.json` naming, which may require projects to migrate ambiguous cases: + * The file name now takes precedence over the `Name` field in the model, like Rojo 0.4.x. + * The `Name` field of the top-level instance is now optional. It's recommended that you remove it from your models. + * Rojo will emit a warning when `Name` is specified and does not match the name from the file. * Fixed `Rect` values being set to `0, 0, 0, 0` when synced with the Rojo plugin. ([#201](https://github.com/rojo-rbx/rojo/issues/201)) +* Fixed live-syncing of `PhysicalProperties`, `NumberSequence`, and `ColorSequence` values ## [0.5.0 Alpha 13](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.13) (August 2, 2019) * Bumped minimum Rust version to 1.34.0. From 53793f7dd234abb6489ece0828aedf3b4ee7a778 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 26 Aug 2019 17:23:59 -0700 Subject: [PATCH 0611/1504] Update and improve reference documentation --- docs/reference/project-format.md | 24 +++++++++++++++--------- docs/reference/sync-details.md | 5 +++++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/docs/reference/project-format.md b/docs/reference/project-format.md index 4b6f80d3..fa27c3c8 100644 --- a/docs/reference/project-format.md +++ b/docs/reference/project-format.md @@ -1,25 +1,31 @@ [TOC] ## Project File +Rojo projects are JSON files that have the `.project.json` extension. They have the following fields: -Rojo projects are JSON files that have the `.project.json` extension. They have these fields: - -* `name`: A string indicating the name of the project. - * This is only used for diagnostics. +* `name`: A string indicating the name of the project. This name is used when building the project into a model or place file. + * **Required** * `tree`: An [Instance Description](#instance-description) describing the root instance of the project. + * **Required** +* `servePort`: The port that `rojo serve` should listen on. Passing `--port` will override this setting. + * **Optional** + * Default is `34872` +* `servePlaceIds`: A list of place IDs that this project may be live-synced to. This feature can help prevent overwriting the wrong game with source from Rojo. + * **Optional** + * Default is `null` ## Instance Description -Instance Descriptions correspond one-to-one with the actual Roblox Instances in the project. They can be specified directly in the project file or be pulled from the filesystem. +Instance Descriptions correspond one-to-one with the actual Roblox Instances in the project. * `$className`: The ClassName of the Instance being described. - * Optional if `$path` is specified. + * **Optional if `$path` is specified.** * `$path`: The path on the filesystem to pull files from into the project. - * Optional if `$className` is specified. + * **Optional if `$className` is specified.** * Paths are relative to the folder containing the project file. * `$properties`: Properties to apply to the instance. Values should be [Instance Property Values](#instance-property-value). - * Optional + * **Optional** * `$ignoreUnknownInstances`: Whether instances that Rojo doesn't know about should be deleted. - * Optional + * **Optional** * Default is `false` if `$path` is specified, otherwise `true`. All other fields in an Instance Description are turned into instances whose name is the key. These values should also be Instance Descriptions! diff --git a/docs/reference/sync-details.md b/docs/reference/sync-details.md index 75a6e6f3..7c43322a 100644 --- a/docs/reference/sync-details.md +++ b/docs/reference/sync-details.md @@ -86,6 +86,11 @@ It would turn into instances in this shape: ![Tree of instances in Roblox](../images/sync-example-json-model.svg) {: align="center" } +!!! warning + Starting in Rojo 0.5.0 Beta 1, the `Name` field is no longer required. The name of the top-level instance in a JSON model is now based on its file name, and the `Name` field is now ignored. + + Rojo will emit a warning if the `Name` field is specified and does not match the file's name. + ## Binary and XML Models Rojo supports both binary (`.rbxm`) and XML (`.rbxmx`) models generated by Roblox Studio or another tool. From 91caa67e047b642a7732e77823662e827cc23693 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 14:14:48 -0700 Subject: [PATCH 0612/1504] Release 0.5.0 stable (#234) * This should be everything? * Add contributing guide --- CHANGELOG.md | 2 ++ CONTRIBUTING.md | 48 ++++++++++++++++++++++++++++++++++ Cargo.lock | 4 +-- README.md | 2 ++ docs/reference/sync-details.md | 2 +- plugin/src/Config.lua | 2 +- server/Cargo.toml | 2 +- 7 files changed, 57 insertions(+), 5 deletions(-) create mode 100644 CONTRIBUTING.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 9e44af46..e937be08 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes + +## [0.5.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0) (August XX, 2019) * Changed `.model.json` naming, which may require projects to migrate ambiguous cases: * The file name now takes precedence over the `Name` field in the model, like Rojo 0.4.x. * The `Name` field of the top-level instance is now optional. It's recommended that you remove it from your models. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..a3f62a56 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,48 @@ +# Contributing to the Rojo Project +Rojo is a big project and can always use more help! This guide covers all repositories underneath the [rojo-rbx organization on GitHub](https://github.com/rojo-rbx). + +Some of the repositories covered are: + +* https://github.com/rojo-rbx/rojo +* https://github.com/rojo-rbx/rbx-dom +* https://github.com/rojo-rbx/vscode-rojo +* https://github.com/rojo-rbx/rbxlx-to-rojo + +## Code +Code contributions are welcome for features and bugs that have been reported in the project's bug tracker. We want to make sure that no one wastes their time, so be sure to talk with maintainers about what changes would be accepted before doing any work! + +## Documentation +Documentation impacts way more people than the individual lines of code we write. + +If you find any problems in documentation, including typos, bad grammar, misleading phrasing, or missing content, feel free to file issues and pull requests to fix them. + +## Bug Reports and Feature Requests +Most of the tools around Rojo try to be clear when an issue is a bug. Even if they aren't, sometimes things don't work quite right. + +Sometimes there's something that Rojo doesn't do that it probably should. + +Please file issues and we'll try to help figure out what the best way forward is. + +## Pushing a Rojo Release +The Rojo release process is pretty manual right now. If you need to do it, here's how: + +1. Bump server version in [`server/Cargo.toml`](server/Cargo.toml) +2. Bump plugin version in [`plugin/src/Config.lua`](plugin/src/Config.lua) +3. Run `cargo test` to update `Cargo.lock` and double-check tests +4. Update [`CHANGELOG.md`](CHANGELOG.md) +5. Commit! + * `git add . && git commit -m "Release vX.Y.Z"` +6. Tag the commit with the version from `Cargo.toml` prepended with a v, like `v0.4.13` +7. Build Windows release build of CLI + * `cargo build --release` +7. Publish the CLI + * `cargo publish` +8. Build and upload the plugin + * `rojo build plugin -o Rojo.rbxm` + * Upload `Rojo.rbxm` to Roblox.com, keep it for later +9. Push commits and tags + * `git push && git push --tags` +10. Copy GitHub release content from previous release + * Update the leading text with a summary about the release + * Paste the changelog notes (as-is!) from [`CHANGELOG.md`](CHANGELOG.md) + * Write a small summary of each major feature \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index ebc23612..9bd31bd2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1498,7 +1498,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0-alpha.13" +version = "0.5.0" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1533,7 +1533,7 @@ version = "0.1.0" dependencies = [ "insta 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "rojo 0.5.0-alpha.13", + "rojo 0.5.0", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/README.md b/README.md index 70ce6f9d..c96d5866 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,8 @@ Soon, Rojo will be able to: If you find any mistakes, feel free to make changes in the [docs](https://github.com/rojo-rbx/rojo/tree/master/docs) folder of this repository and submit a pull request! ## Contributing +Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions for helping work on Rojo! + Pull requests are welcome! Rojo supports Rust 1.34.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. diff --git a/docs/reference/sync-details.md b/docs/reference/sync-details.md index 7c43322a..3caa3da0 100644 --- a/docs/reference/sync-details.md +++ b/docs/reference/sync-details.md @@ -87,7 +87,7 @@ It would turn into instances in this shape: {: align="center" } !!! warning - Starting in Rojo 0.5.0 Beta 1, the `Name` field is no longer required. The name of the top-level instance in a JSON model is now based on its file name, and the `Name` field is now ignored. + Starting in Rojo 0.5.0 (stable), the `Name` field is no longer required. The name of the top-level instance in a JSON model is now based on its file name, and the `Name` field is now ignored. Rojo will emit a warning if the `Name` field is specified and does not match the file's name. diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 66cbbc8e..09cb5eb8 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,6 +1,6 @@ return { codename = "Epiphany", - version = {0, 5, 0, "-alpha.13"}, + version = {0, 5, 0}, expectedServerVersionString = "0.5.0 or newer", protocolVersion = 2, defaultHost = "localhost", diff --git a/server/Cargo.toml b/server/Cargo.toml index 6300ce39..10735387 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0-alpha.13" +version = "0.5.0" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MIT" From 009a99a8eba8ec64bcc4da58e36393211e1f8e61 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 14:26:00 -0700 Subject: [PATCH 0613/1504] Fix date on Changelog (oops) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e937be08..a4c55f1f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased Changes -## [0.5.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0) (August XX, 2019) +## [0.5.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0) (August 27, 2019) * Changed `.model.json` naming, which may require projects to migrate ambiguous cases: * The file name now takes precedence over the `Name` field in the model, like Rojo 0.4.x. * The `Name` field of the top-level instance is now optional. It's recommended that you remove it from your models. From 4dc175fcd22aa6303f8cb4f5eb0089db20386631 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 14:38:51 -0700 Subject: [PATCH 0614/1504] Update docs home for 0.5.x --- docs/index.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/index.md b/docs/index.md index 5f1b54d9..8d04590b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,11 +1,11 @@ -This is the documentation home for Rojo 0.5.x. +This is the documentation home for **the Rojo `master` branch**. Available versions of these docs: -* [Latest version (currently 0.5.x)](https://rojo.space/docs/latest) +* [Latest version from `master` branch](https://rojo.space/docs/latest) * [0.5.x](https://rojo.space/docs/0.5.x) * [0.4.x](https://rojo.space/docs/0.4.x) -**Rojo** is a flexible multi-tool designed for creating robust Roblox projects. +**Rojo** is a tool designed to enable Roblox developers to use professional-grade software engineering tools. This documentation is a continual work in progress. If you find any issues, please file an issue on [Rojo's issue tracker](https://github.com/rojo-rbx/rojo/issues)! \ No newline at end of file From 8e8291a0bdd320d3189d2c704655c3b847e5a140 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 14:52:40 -0700 Subject: [PATCH 0615/1504] Add more stern warning about docs from master branch --- docs/index.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/index.md b/docs/index.md index 8d04590b..19c949e0 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,5 +1,12 @@ This is the documentation home for **the Rojo `master` branch**. +!!! warning + Documentation here may not apply to the latest release of Rojo yet. + + For documentation for the latest stable release series, 0.5.x, go to: + + [https://rojo.space/docs/0.5.x](https://rojo.space/docs/0.5.x) + Available versions of these docs: * [Latest version from `master` branch](https://rojo.space/docs/latest) From fea303ac8ba268d8586d47dd726accb315b15efc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 15:00:37 -0700 Subject: [PATCH 0616/1504] Major Subsystem Rewrite (Reconciler Mk5) (#217) --- Cargo.lock | 17 + design.gv | 30 + rojo-test/build-tests/plain.txt | 1 + rojo-test/build-tests/plain_gitkeep/.gitkeep | 0 rojo-test/build-tests/rbxmx_ref.rbxmx | 25 + .../build-tests/txt/default.project.json | 6 + rojo-test/build-tests/txt/foo.txt | 1 + rojo-test/src/build_test.rs | 12 + .../src/snapshots/build_test__plain.txt.snap | 14 + .../snapshots/build_test__plain_gitkeep.snap | 13 + .../build_test__rbxmx_ref.rbxmx.snap | 28 + rojo-test/src/snapshots/build_test__txt.snap | 14 + server/Cargo.toml | 12 +- server/assets/test-folder.rbxm | Bin 0 -> 270 bytes server/src/commands/build.rs | 58 +- server/src/commands/serve.rs | 75 +- server/src/commands/upload.rs | 96 +- server/src/fs_watcher.rs | 143 --- server/src/imfs.rs | 331 ------- server/src/imfs/error.rs | 65 ++ server/src/imfs/fetcher.rs | 32 + server/src/imfs/imfs.rs | 530 +++++++++++ server/src/imfs/mod.rs | 17 + server/src/imfs/noop_fetcher.rs | 49 + server/src/imfs/real_fetcher.rs | 155 +++ server/src/imfs/snapshot.rs | 38 + server/src/lib.rs | 24 +- server/src/live_session.rs | 99 -- server/src/path_map.rs | 212 ++++- server/src/path_serializer.rs | 2 +- server/src/project.rs | 6 + server/src/rbx_session.rs | 289 ------ server/src/rbx_snapshot.rs | 896 ------------------ server/src/serve_session.rs | 33 + server/src/snapshot/instance_snapshot.rs | 62 ++ server/src/snapshot/mod.rs | 29 + server/src/snapshot/patch.rs | 44 + server/src/snapshot/patch_apply.rs | 239 +++++ server/src/snapshot/patch_compute.rs | 322 +++++++ server/src/snapshot_middleware/context.rs | 7 + server/src/snapshot_middleware/csv.rs | 174 ++++ server/src/snapshot_middleware/dir.rs | 126 +++ server/src/snapshot_middleware/error.rs | 99 ++ server/src/snapshot_middleware/json_model.rs | 181 ++++ server/src/snapshot_middleware/lua.rs | 173 ++++ server/src/snapshot_middleware/middleware.rs | 39 + server/src/snapshot_middleware/mod.rs | 76 ++ server/src/snapshot_middleware/project.rs | 489 ++++++++++ server/src/snapshot_middleware/rbxm.rs | 96 ++ server/src/snapshot_middleware/rbxmx.rs | 94 ++ server/src/snapshot_middleware/txt.rs | 147 +++ server/src/snapshot_reconciler.rs | 379 -------- server/src/visualize.rs | 174 ---- server/src/web/api.rs | 147 +-- server/src/web/interface.rs | 51 +- server/src/web/mod.rs | 22 +- server/tests/imfs.rs | 350 ------- server/tests/malformed_projects.rs | 55 -- server/tests/snapshot_reconciler.rs | 111 --- server/tests/snapshot_snapshots.rs | 68 -- server/tests/test_util/mod.rs | 36 - server/tests/test_util/snapshot.rs | 79 -- server/tests/test_util/tree.rs | 351 ------- server/tests/tree_snapshots.rs | 77 -- test-projects/empty/expected-snapshot.json | 20 - .../empty_folder/default.project.json | 6 + test-projects/empty_folder/src/.gitkeep | 0 .../json_model/expected-snapshot.json | 76 -- .../meta_files/expected-snapshot.json | 129 --- .../expected-snapshot.json | 212 ----- .../multi_partition_game/initial.tree.json | 242 ----- .../multi_partition_game/with_dir.tree.json | 256 ----- .../with_moved_dir.tree.json | 256 ----- .../nested_partitions/expected-snapshot.json | 82 -- .../expected-snapshot.json | 161 ---- .../expected-snapshot.json | 53 -- .../spawn_location/initial.tree.json | 266 ------ .../expected-snapshot.json | 66 -- test-projects/txt_file/default.project.json | 6 + test-projects/txt_file/src/foo.txt | 1 + 80 files changed, 3843 insertions(+), 5609 deletions(-) create mode 100644 design.gv create mode 100644 rojo-test/build-tests/plain.txt create mode 100644 rojo-test/build-tests/plain_gitkeep/.gitkeep create mode 100644 rojo-test/build-tests/rbxmx_ref.rbxmx create mode 100644 rojo-test/build-tests/txt/default.project.json create mode 100644 rojo-test/build-tests/txt/foo.txt create mode 100644 rojo-test/src/snapshots/build_test__plain.txt.snap create mode 100644 rojo-test/src/snapshots/build_test__plain_gitkeep.snap create mode 100644 rojo-test/src/snapshots/build_test__rbxmx_ref.rbxmx.snap create mode 100644 rojo-test/src/snapshots/build_test__txt.snap create mode 100644 server/assets/test-folder.rbxm delete mode 100644 server/src/fs_watcher.rs delete mode 100644 server/src/imfs.rs create mode 100644 server/src/imfs/error.rs create mode 100644 server/src/imfs/fetcher.rs create mode 100644 server/src/imfs/imfs.rs create mode 100644 server/src/imfs/mod.rs create mode 100644 server/src/imfs/noop_fetcher.rs create mode 100644 server/src/imfs/real_fetcher.rs create mode 100644 server/src/imfs/snapshot.rs delete mode 100644 server/src/live_session.rs delete mode 100644 server/src/rbx_session.rs delete mode 100644 server/src/rbx_snapshot.rs create mode 100644 server/src/serve_session.rs create mode 100644 server/src/snapshot/instance_snapshot.rs create mode 100644 server/src/snapshot/mod.rs create mode 100644 server/src/snapshot/patch.rs create mode 100644 server/src/snapshot/patch_apply.rs create mode 100644 server/src/snapshot/patch_compute.rs create mode 100644 server/src/snapshot_middleware/context.rs create mode 100644 server/src/snapshot_middleware/csv.rs create mode 100644 server/src/snapshot_middleware/dir.rs create mode 100644 server/src/snapshot_middleware/error.rs create mode 100644 server/src/snapshot_middleware/json_model.rs create mode 100644 server/src/snapshot_middleware/lua.rs create mode 100644 server/src/snapshot_middleware/middleware.rs create mode 100644 server/src/snapshot_middleware/mod.rs create mode 100644 server/src/snapshot_middleware/project.rs create mode 100644 server/src/snapshot_middleware/rbxm.rs create mode 100644 server/src/snapshot_middleware/rbxmx.rs create mode 100644 server/src/snapshot_middleware/txt.rs delete mode 100644 server/src/snapshot_reconciler.rs delete mode 100644 server/src/visualize.rs delete mode 100644 server/tests/imfs.rs delete mode 100644 server/tests/malformed_projects.rs delete mode 100644 server/tests/snapshot_reconciler.rs delete mode 100644 server/tests/snapshot_snapshots.rs delete mode 100644 server/tests/test_util/mod.rs delete mode 100644 server/tests/test_util/snapshot.rs delete mode 100644 server/tests/test_util/tree.rs delete mode 100644 server/tests/tree_snapshots.rs delete mode 100644 test-projects/empty/expected-snapshot.json create mode 100644 test-projects/empty_folder/default.project.json create mode 100644 test-projects/empty_folder/src/.gitkeep delete mode 100644 test-projects/json_model/expected-snapshot.json delete mode 100644 test-projects/meta_files/expected-snapshot.json delete mode 100644 test-projects/multi_partition_game/expected-snapshot.json delete mode 100644 test-projects/multi_partition_game/initial.tree.json delete mode 100644 test-projects/multi_partition_game/with_dir.tree.json delete mode 100644 test-projects/multi_partition_game/with_moved_dir.tree.json delete mode 100644 test-projects/nested_partitions/expected-snapshot.json delete mode 100644 test-projects/single_partition_game/expected-snapshot.json delete mode 100644 test-projects/single_partition_model/expected-snapshot.json delete mode 100644 test-projects/spawn_location/initial.tree.json delete mode 100644 test-projects/transmute_partition/expected-snapshot.json create mode 100644 test-projects/txt_file/default.project.json create mode 100644 test-projects/txt_file/src/foo.txt diff --git a/Cargo.lock b/Cargo.lock index 9bd31bd2..5d3837cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -277,6 +277,14 @@ dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-channel" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-deque" version = "0.7.1" @@ -701,6 +709,11 @@ name = "itoa" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "jod-thread" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -1501,11 +1514,13 @@ name = "rojo" version = "0.5.0" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", + "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2175,6 +2190,7 @@ dependencies = [ "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" @@ -2223,6 +2239,7 @@ dependencies = [ "checksum insta 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00eef45accbe65bfb859ad16649c6b4bed246768d89493473d9ab6c6a0eb908f" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +"checksum jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f52a11f73b88fab829a0e4d9e13ea5982c7ac457c72eb3541d82a4afdfce4ff" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" diff --git a/design.gv b/design.gv new file mode 100644 index 00000000..f44e7db7 --- /dev/null +++ b/design.gv @@ -0,0 +1,30 @@ +digraph Rojo { + concentrate = true; + node [fontname = "sans-serif"]; + + plugin [label="Roblox Studio Plugin"] + session [label="Session"] + rbx_tree [label="Instance Tree"] + imfs [label="In-Memory Filesystem"] + fs_impl [label="Filesystem Implementation\n(stubbed in tests)"] + fs [label="Real Filesystem"] + snapshot_subsystem [label="Snapshot Subsystem\n(reconciler)"] + snapshot_generator [label="Snapshot Generator"] + user_middleware [label="User Middleware\n(MoonScript, etc.)"] + builtin_middleware [label="Built-in Middleware\n(.lua, .rbxm, etc.)"] + api [label="Web API"] + file_watcher [label="File Watcher"] + + session -> imfs + session -> rbx_tree + session -> snapshot_subsystem + session -> snapshot_generator + session -> file_watcher [dir="both"] + file_watcher -> imfs + snapshot_generator -> user_middleware + snapshot_generator -> builtin_middleware + plugin -> api [style="dotted"; dir="both"; minlen=2] + api -> session + imfs -> fs_impl + fs_impl -> fs +} \ No newline at end of file diff --git a/rojo-test/build-tests/plain.txt b/rojo-test/build-tests/plain.txt new file mode 100644 index 00000000..8948f215 --- /dev/null +++ b/rojo-test/build-tests/plain.txt @@ -0,0 +1 @@ +This is a bare text file with no project. \ No newline at end of file diff --git a/rojo-test/build-tests/plain_gitkeep/.gitkeep b/rojo-test/build-tests/plain_gitkeep/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/rojo-test/build-tests/rbxmx_ref.rbxmx b/rojo-test/build-tests/rbxmx_ref.rbxmx new file mode 100644 index 00000000..fcfc2af3 --- /dev/null +++ b/rojo-test/build-tests/rbxmx_ref.rbxmx @@ -0,0 +1,25 @@ + + true + null + nil + + + Container + + + + + Target + + Pointed to by ObjectValue + + + + + Pointer + + RBX42D96C32E905427DBA530A1881C962FD + + + + \ No newline at end of file diff --git a/rojo-test/build-tests/txt/default.project.json b/rojo-test/build-tests/txt/default.project.json new file mode 100644 index 00000000..4590455f --- /dev/null +++ b/rojo-test/build-tests/txt/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "txt", + "tree": { + "$path": "foo.txt" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/txt/foo.txt b/rojo-test/build-tests/txt/foo.txt new file mode 100644 index 00000000..8bba57d2 --- /dev/null +++ b/rojo-test/build-tests/txt/foo.txt @@ -0,0 +1 @@ +This is a txt file in a project. \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index fa15b73e..f45e520a 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -31,13 +31,25 @@ gen_build_tests! { json_model_legacy_name, module_in_folder, module_init, + plain_gitkeep, rbxm_in_folder, rbxmx_in_folder, server_in_folder, server_init, + txt, txt_in_folder, } +#[test] +fn build_plain_txt() { + run_build_test("plain.txt"); +} + +#[test] +fn build_rbxmx_ref() { + run_build_test("rbxmx_ref.rbxmx"); +} + fn run_build_test(test_name: &str) { let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); let build_test_path = manifest_dir.join("build-tests"); diff --git a/rojo-test/src/snapshots/build_test__plain.txt.snap b/rojo-test/src/snapshots/build_test__plain.txt.snap new file mode 100644 index 00000000..93316de9 --- /dev/null +++ b/rojo-test/src/snapshots/build_test__plain.txt.snap @@ -0,0 +1,14 @@ +--- +created: "2019-08-09T00:17:42.253380600Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + plain + This is a bare text file with no project. + + + diff --git a/rojo-test/src/snapshots/build_test__plain_gitkeep.snap b/rojo-test/src/snapshots/build_test__plain_gitkeep.snap new file mode 100644 index 00000000..204b47e9 --- /dev/null +++ b/rojo-test/src/snapshots/build_test__plain_gitkeep.snap @@ -0,0 +1,13 @@ +--- +created: "2019-08-09T00:17:42.175575800Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + plain_gitkeep + + + diff --git a/rojo-test/src/snapshots/build_test__rbxmx_ref.rbxmx.snap b/rojo-test/src/snapshots/build_test__rbxmx_ref.rbxmx.snap new file mode 100644 index 00000000..c631c482 --- /dev/null +++ b/rojo-test/src/snapshots/build_test__rbxmx_ref.rbxmx.snap @@ -0,0 +1,28 @@ +--- +created: "2019-08-10T07:57:42.835269100Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + rbxmx_ref + + + + + Target + + Pointed to by ObjectValue + + + + + Pointer + + 1 + + + + \ No newline at end of file diff --git a/rojo-test/src/snapshots/build_test__txt.snap b/rojo-test/src/snapshots/build_test__txt.snap new file mode 100644 index 00000000..4794a928 --- /dev/null +++ b/rojo-test/src/snapshots/build_test__txt.snap @@ -0,0 +1,14 @@ +--- +created: "2019-08-09T00:22:01.983322Z" +creator: insta@0.10.0 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + txt + This is a txt file in a project. + + + diff --git a/server/Cargo.toml b/server/Cargo.toml index 10735387..6f15bcf3 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -21,29 +21,31 @@ path = "src/bin.rs" [dependencies] clap = "2.27" +crossbeam-channel = "0.3.9" csv = "1.0" env_logger = "0.6" failure = "0.1.3" futures = "0.1" hyper = "0.12" +jod-thread = "0.1.0" log = "0.4" maplit = "1.0.1" notify = "4.0" rbx_binary = "0.4.1" rbx_dom_weak = "1.9.0" -rbx_xml = "0.11.0" rbx_reflection = "3.1.388" +rbx_xml = "0.11.0" regex = "1.0" reqwest = "0.9.5" -rlua = "0.16" ritz = "0.1.0" +rlua = "0.16" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" uuid = { version = "0.7", features = ["v4", "serde"] } [dev-dependencies] -tempfile = "3.0" -walkdir = "2.1" lazy_static = "1.2" +paste = "0.1" pretty_assertions = "0.6.1" -paste = "0.1" \ No newline at end of file +tempfile = "3.0" +walkdir = "2.1" \ No newline at end of file diff --git a/server/assets/test-folder.rbxm b/server/assets/test-folder.rbxm new file mode 100644 index 0000000000000000000000000000000000000000..98da04121defefdb6535272ca7a38c1e1bec8763 GIT binary patch literal 270 zcmcC1%1_G4uTbp#&&wsn#lXPG0Kq^C418Tf994iUB`E)cFi3?E5W7|se@kf ProjectLoadError, io::Error => IoError, rbx_xml::EncodeError => XmlModelEncodeError, rbx_binary::EncodeError => BinaryModelEncodeError, FsError => FsError, - SnapshotError => SnapshotError, }); fn xml_encode_config() -> rbx_xml::EncodeOptions { @@ -84,18 +76,34 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { .or_else(|| detect_output_kind(options)) .ok_or(BuildError::UnknownOutputKind)?; - info!("Hoping to generate file of type {:?}", output_kind); + log::info!("Hoping to generate file of type {:?}", output_kind); - info!("Looking for project at {}", options.fuzzy_project_path.display()); + let mut tree = RbxTree::new(RbxInstanceProperties { + name: "ROOT".to_owned(), + class_name: "Folder".to_owned(), + properties: HashMap::new(), + }); + let root_id = tree.get_root_id(); - let project = Project::load_fuzzy(&options.fuzzy_project_path)?; + log::trace!("Constructing in-memory filesystem"); + let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Disabled)); - info!("Found project at {}", project.file_location.display()); - info!("Using project {:#?}", project); + log::trace!("Reading project root"); + let entry = imfs.get(&options.fuzzy_project_path) + .expect("could not get project path"); - let mut imfs = Imfs::new(); - imfs.add_roots_from_project(&project)?; - let tree = construct_oneoff_tree(&project, &imfs)?; + log::trace!("Generating snapshot of instances from IMFS"); + let snapshot = snapshot_from_imfs(&mut imfs, &entry) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + log::trace!("Computing patch set"); + let patch_set = compute_patch_set(&snapshot, &tree, root_id); + + log::trace!("Applying patch set"); + apply_patch_set(&mut tree, &patch_set); + + log::trace!("Opening output file for write"); let mut file = BufWriter::new(File::create(&options.output_file)?); match output_kind { @@ -103,19 +111,16 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { // Model files include the root instance of the tree and all its // descendants. - let root_id = tree.get_root_id(); rbx_xml::to_writer(&mut file, &tree, &[root_id], xml_encode_config())?; }, OutputKind::Rbxlx => { // Place files don't contain an entry for the DataModel, but our // RbxTree representation does. - let root_id = tree.get_root_id(); let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); rbx_xml::to_writer(&mut file, &tree, top_level_ids, xml_encode_config())?; }, OutputKind::Rbxm => { - let root_id = tree.get_root_id(); rbx_binary::encode(&tree, &[root_id], &mut file)?; }, OutputKind::Rbxl => { @@ -123,7 +128,6 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { log::warn!("Using the XML place format (rbxlx) is recommended instead."); log::warn!("For more info, see https://github.com/LPGhatguy/rojo/issues/180"); - let root_id = tree.get_root_id(); let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); rbx_binary::encode(&tree, top_level_ids, &mut file)?; }, @@ -131,5 +135,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { file.flush()?; + log::trace!("Done!"); + Ok(()) } \ No newline at end of file diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index 567c35ef..fbaaaed4 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -1,16 +1,19 @@ use std::{ + collections::HashMap, path::PathBuf, sync::Arc, }; -use log::info; +use rbx_dom_weak::{RbxTree, RbxInstanceProperties}; use failure::Fail; use crate::{ + imfs::new::{Imfs, RealFetcher, WatchMode}, project::{Project, ProjectLoadError}, + serve_session::ServeSession, + snapshot::{apply_patch_set, compute_patch_set}, + snapshot_middleware::snapshot_from_imfs, web::LiveServer, - imfs::FsError, - live_session::{LiveSession, LiveSessionError}, }; const DEFAULT_PORT: u16 = 34872; @@ -23,40 +26,64 @@ pub struct ServeOptions { #[derive(Debug, Fail)] pub enum ServeError { - #[fail(display = "Project load error: {}", _0)] - ProjectLoadError(#[fail(cause)] ProjectLoadError), - - #[fail(display = "{}", _0)] - FsError(#[fail(cause)] FsError), - - #[fail(display = "{}", _0)] - LiveSessionError(#[fail(cause)] LiveSessionError), + #[fail(display = "Couldn't load project: {}", _0)] + ProjectLoad(#[fail(cause)] ProjectLoadError), } impl_from!(ServeError { - ProjectLoadError => ProjectLoadError, - FsError => FsError, - LiveSessionError => LiveSessionError, + ProjectLoadError => ProjectLoad, }); pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { - info!("Looking for project at {}", options.fuzzy_project_path.display()); - - let project = Arc::new(Project::load_fuzzy(&options.fuzzy_project_path)?); - - info!("Found project at {}", project.file_location.display()); - info!("Using project {:#?}", project); - - let live_session = Arc::new(LiveSession::new(Arc::clone(&project))?); - let server = LiveServer::new(live_session); + let maybe_project = match Project::load_fuzzy(&options.fuzzy_project_path) { + Ok(project) => Some(project), + Err(ProjectLoadError::NotFound) => None, + Err(other) => return Err(other.into()), + }; let port = options.port - .or(project.serve_port) + .or(maybe_project.as_ref().and_then(|project| project.serve_port)) .unwrap_or(DEFAULT_PORT); println!("Rojo server listening on port {}", port); + let mut tree = RbxTree::new(RbxInstanceProperties { + name: "ROOT".to_owned(), + class_name: "Folder".to_owned(), + properties: HashMap::new(), + }); + let root_id = tree.get_root_id(); + + let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Enabled)); + let entry = imfs.get(&options.fuzzy_project_path) + .expect("could not get project path"); + + let snapshot = snapshot_from_imfs(&mut imfs, &entry) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + let patch_set = compute_patch_set(&snapshot, &tree, root_id); + apply_patch_set(&mut tree, &patch_set); + + let session = Arc::new(ServeSession::new(maybe_project)); + let server = LiveServer::new(session); + server.start(port); + // let receiver = imfs.change_receiver(); + + // while let Ok(change) = receiver.recv() { + // imfs.commit_change(&change) + // .expect("Failed to commit Imfs change"); + + // use notify::DebouncedEvent; + // if let DebouncedEvent::Write(path) = change { + // let contents = imfs.get_contents(path) + // .expect("Failed to read changed path"); + + // println!("{:?}", std::str::from_utf8(contents)); + // } + // } + Ok(()) } \ No newline at end of file diff --git a/server/src/commands/upload.rs b/server/src/commands/upload.rs index c8c0650c..a6218a19 100644 --- a/server/src/commands/upload.rs +++ b/server/src/commands/upload.rs @@ -1,56 +1,13 @@ -use std::{ - path::PathBuf, - io, -}; +use std::path::PathBuf; -use log::info; use failure::Fail; -use reqwest::header::{ACCEPT, USER_AGENT, CONTENT_TYPE, COOKIE}; - -use crate::{ - imfs::{Imfs, FsError}, - project::{Project, ProjectLoadError}, - rbx_session::construct_oneoff_tree, - rbx_snapshot::SnapshotError, -}; - #[derive(Debug, Fail)] pub enum UploadError { - #[fail(display = "Roblox API Error: {}", _0)] - RobloxApiError(String), - - #[fail(display = "Invalid asset kind: {}", _0)] - InvalidKind(String), - - #[fail(display = "Project load error: {}", _0)] - ProjectLoadError(#[fail(cause)] ProjectLoadError), - - #[fail(display = "IO error: {}", _0)] - IoError(#[fail(cause)] io::Error), - - #[fail(display = "HTTP error: {}", _0)] - HttpError(#[fail(cause)] reqwest::Error), - - #[fail(display = "XML model file error")] - XmlModelEncodeError(rbx_xml::EncodeError), - - #[fail(display = "{}", _0)] - FsError(#[fail(cause)] FsError), - - #[fail(display = "{}", _0)] - SnapshotError(#[fail(cause)] SnapshotError), + #[fail(display = "This error cannot happen")] + StubError, } -impl_from!(UploadError { - ProjectLoadError => ProjectLoadError, - io::Error => IoError, - reqwest::Error => HttpError, - rbx_xml::EncodeError => XmlModelEncodeError, - FsError => FsError, - SnapshotError => SnapshotError, -}); - #[derive(Debug)] pub struct UploadOptions<'a> { pub fuzzy_project_path: PathBuf, @@ -59,49 +16,6 @@ pub struct UploadOptions<'a> { pub kind: Option<&'a str>, } -pub fn upload(options: &UploadOptions) -> Result<(), UploadError> { - // TODO: Switch to uploading binary format? - - info!("Looking for project at {}", options.fuzzy_project_path.display()); - - let project = Project::load_fuzzy(&options.fuzzy_project_path)?; - - info!("Found project at {}", project.file_location.display()); - info!("Using project {:#?}", project); - - let mut imfs = Imfs::new(); - imfs.add_roots_from_project(&project)?; - let tree = construct_oneoff_tree(&project, &imfs)?; - - let root_id = tree.get_root_id(); - let mut contents = Vec::new(); - - match options.kind { - Some("place") | None => { - let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); - rbx_xml::to_writer_default(&mut contents, &tree, top_level_ids)?; - }, - Some("model") => { - rbx_xml::to_writer_default(&mut contents, &tree, &[root_id])?; - }, - Some(invalid) => return Err(UploadError::InvalidKind(invalid.to_owned())), - } - - let url = format!("https://data.roblox.com/Data/Upload.ashx?assetid={}", options.asset_id); - - let client = reqwest::Client::new(); - let mut response = client.post(&url) - .header(COOKIE, format!(".ROBLOSECURITY={}", &options.security_cookie)) - .header(USER_AGENT, "Roblox/WinInet") - .header("Requester", "Client") - .header(CONTENT_TYPE, "application/xml") - .header(ACCEPT, "application/json") - .body(contents) - .send()?; - - if !response.status().is_success() { - return Err(UploadError::RobloxApiError(response.text()?)); - } - - Ok(()) +pub fn upload(_options: &UploadOptions) -> Result<(), UploadError> { + unimplemented!("TODO: Reimplement upload command"); } \ No newline at end of file diff --git a/server/src/fs_watcher.rs b/server/src/fs_watcher.rs deleted file mode 100644 index 9641b293..00000000 --- a/server/src/fs_watcher.rs +++ /dev/null @@ -1,143 +0,0 @@ -use std::{ - sync::{mpsc, Arc, Mutex}, - time::Duration, - path::Path, - ops::Deref, - thread, -}; - -use log::{warn, trace}; -use notify::{ - self, - DebouncedEvent, - RecommendedWatcher, - RecursiveMode, - Watcher, -}; - -use crate::{ - imfs::Imfs, - rbx_session::RbxSession, -}; - -const WATCH_TIMEOUT: Duration = Duration::from_millis(100); - -/// Watches for changes on the filesystem and links together the in-memory -/// filesystem and in-memory Roblox tree. -pub struct FsWatcher { - watcher: RecommendedWatcher, -} - -impl FsWatcher { - /// Start a new FS watcher, watching all of the roots currently attached to - /// the given Imfs. - /// - /// `rbx_session` is optional to make testing easier. If it isn't `None`, - /// events will be passed to it after they're given to the Imfs. - pub fn start(imfs: Arc>, rbx_session: Option>>) -> FsWatcher { - let (watch_tx, watch_rx) = mpsc::channel(); - - let mut watcher = notify::watcher(watch_tx, WATCH_TIMEOUT) - .expect("Could not create filesystem watcher"); - - { - let imfs = imfs.lock().unwrap(); - - for root_path in imfs.get_roots() { - trace!("Watching path {}", root_path.display()); - watcher.watch(root_path, RecursiveMode::Recursive) - .expect("Could not watch directory"); - } - } - - { - let imfs = Arc::clone(&imfs); - let rbx_session = rbx_session.as_ref().map(Arc::clone); - - thread::spawn(move || { - trace!("Watcher thread started"); - while let Ok(event) = watch_rx.recv() { - // handle_fs_event expects an Option<&Mutex>, but we have - // an Option>>, so we coerce with Deref. - let session_ref = rbx_session.as_ref().map(Deref::deref); - - handle_fs_event(&imfs, session_ref, event); - } - trace!("Watcher thread stopped"); - }); - } - - FsWatcher { - watcher, - } - } - - pub fn stop_watching_path(&mut self, path: &Path) { - match self.watcher.unwatch(path) { - Ok(_) => {}, - Err(e) => { - warn!("Could not unwatch path {}: {}", path.display(), e); - }, - } - } -} - -fn handle_fs_event(imfs: &Mutex, rbx_session: Option<&Mutex>, event: DebouncedEvent) { - match event { - DebouncedEvent::Create(path) => { - trace!("Path created: {}", path.display()); - - { - let mut imfs = imfs.lock().unwrap(); - imfs.path_created(&path).unwrap(); - } - - if let Some(rbx_session) = rbx_session { - let mut rbx_session = rbx_session.lock().unwrap(); - rbx_session.path_created(&path); - } - }, - DebouncedEvent::Write(path) => { - trace!("Path created: {}", path.display()); - - { - let mut imfs = imfs.lock().unwrap(); - imfs.path_updated(&path).unwrap(); - } - - if let Some(rbx_session) = rbx_session { - let mut rbx_session = rbx_session.lock().unwrap(); - rbx_session.path_updated(&path); - } - }, - DebouncedEvent::Remove(path) => { - trace!("Path removed: {}", path.display()); - - { - let mut imfs = imfs.lock().unwrap(); - imfs.path_removed(&path).unwrap(); - } - - if let Some(rbx_session) = rbx_session { - let mut rbx_session = rbx_session.lock().unwrap(); - rbx_session.path_removed(&path); - } - }, - DebouncedEvent::Rename(from_path, to_path) => { - trace!("Path renamed: {} to {}", from_path.display(), to_path.display()); - - { - let mut imfs = imfs.lock().unwrap(); - imfs.path_moved(&from_path, &to_path).unwrap(); - } - - if let Some(rbx_session) = rbx_session { - let mut rbx_session = rbx_session.lock().unwrap(); - rbx_session.path_renamed(&from_path, &to_path); - } - }, - other => { - trace!("Unhandled FS event: {:?}", other); - }, - } -} \ No newline at end of file diff --git a/server/src/imfs.rs b/server/src/imfs.rs deleted file mode 100644 index 75cb0314..00000000 --- a/server/src/imfs.rs +++ /dev/null @@ -1,331 +0,0 @@ -use std::{ - cmp::Ordering, - collections::{HashMap, HashSet, BTreeSet}, - fmt, - fs, - io, - path::{self, Path, PathBuf}, -}; - -use failure::Fail; -use serde::{Serialize, Deserialize}; - -use crate::project::{Project, ProjectNode}; - -/// A wrapper around io::Error that also attaches the path associated with the -/// error. -#[derive(Debug, Fail)] -pub struct FsError { - #[fail(cause)] - inner: io::Error, - path: PathBuf, -} - -impl FsError { - fn new>(inner: io::Error, path: P) -> FsError { - FsError { - inner, - path: path.into(), - } - } -} - -impl fmt::Display for FsError { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - write!(output, "{}: {}", self.path.display(), self.inner) - } -} - -fn add_sync_points(imfs: &mut Imfs, node: &ProjectNode) -> Result<(), FsError> { - if let Some(path) = &node.path { - imfs.add_root(path)?; - } - - for child in node.children.values() { - add_sync_points(imfs, child)?; - } - - Ok(()) -} - -/// The in-memory filesystem keeps a mirror of all files being watched by Rojo -/// in order to deduplicate file changes in the case of bidirectional syncing -/// from Roblox Studio. -/// -/// It also enables Rojo to quickly generate React-like snapshots to make -/// reasoning about instances and how they relate to files easier. -#[derive(Debug, Clone)] -pub struct Imfs { - items: HashMap, - roots: HashSet, -} - -impl Imfs { - pub fn new() -> Imfs { - Imfs { - items: HashMap::new(), - roots: HashSet::new(), - } - } - - pub fn add_roots_from_project(&mut self, project: &Project) -> Result<(), FsError> { - add_sync_points(self, &project.tree) - } - - pub fn get_roots(&self) -> &HashSet { - &self.roots - } - - pub fn get_items(&self) -> &HashMap { - &self.items - } - - pub fn get(&self, path: &Path) -> Option<&ImfsItem> { - debug_assert!(path.is_absolute()); - debug_assert!(self.is_within_roots(path)); - - self.items.get(path) - } - - pub fn add_root(&mut self, path: &Path) -> Result<(), FsError> { - debug_assert!(path.is_absolute()); - - if !self.is_within_roots(path) { - self.roots.insert(path.to_path_buf()); - self.descend_and_read_from_disk(path)?; - } - - Ok(()) - } - - pub fn remove_root(&mut self, path: &Path) { - debug_assert!(path.is_absolute()); - - if self.roots.get(path).is_some() { - self.remove_item(path); - - if let Some(parent_path) = path.parent() { - self.unlink_child(parent_path, path); - } - } - } - - pub fn path_created(&mut self, path: &Path) -> Result<(), FsError> { - debug_assert!(path.is_absolute()); - debug_assert!(self.is_within_roots(path)); - - self.descend_and_read_from_disk(path) - } - - pub fn path_updated(&mut self, path: &Path) -> Result<(), FsError> { - debug_assert!(path.is_absolute()); - debug_assert!(self.is_within_roots(path)); - - self.descend_and_read_from_disk(path) - } - - pub fn path_removed(&mut self, path: &Path) -> Result<(), FsError> { - debug_assert!(path.is_absolute()); - debug_assert!(self.is_within_roots(path)); - - self.remove_item(path); - - if let Some(parent_path) = path.parent() { - self.unlink_child(parent_path, path); - } - - Ok(()) - } - - pub fn path_moved(&mut self, from_path: &Path, to_path: &Path) -> Result<(), FsError> { - self.path_removed(from_path)?; - self.path_created(to_path)?; - Ok(()) - } - - pub fn get_root_for_path<'a>(&'a self, path: &Path) -> Option<&'a Path> { - for root_path in &self.roots { - if path.starts_with(root_path) { - return Some(root_path); - } - } - - None - } - - fn remove_item(&mut self, path: &Path) { - if let Some(ImfsItem::Directory(directory)) = self.items.remove(path) { - for child_path in &directory.children { - self.remove_item(child_path); - } - } - } - - fn unlink_child(&mut self, parent: &Path, child: &Path) { - let parent_item = self.items.get_mut(parent); - - match parent_item { - Some(ImfsItem::Directory(directory)) => { - directory.children.remove(child); - }, - _ => {}, - } - } - - fn link_child(&mut self, parent: &Path, child: &Path) { - if self.is_within_roots(parent) { - let parent_item = self.items.get_mut(parent); - - match parent_item { - Some(ImfsItem::Directory(directory)) => { - directory.children.insert(child.to_path_buf()); - }, - _ => { - panic!("Tried to link child of path that wasn't a directory!"); - }, - } - } - } - - fn descend_and_read_from_disk(&mut self, path: &Path) -> Result<(), FsError> { - let root_path = self.get_root_path(path) - .expect("Tried to descent and read for path that wasn't within roots!"); - - // If this path is a root, we should read the entire thing. - if root_path == path { - self.read_from_disk(path)?; - return Ok(()); - } - - let relative_path = path.strip_prefix(root_path).unwrap(); - let mut current_path = root_path.to_path_buf(); - - for component in relative_path.components() { - match component { - path::Component::Normal(name) => { - let next_path = current_path.join(name); - - if self.items.contains_key(&next_path) { - current_path = next_path; - } else { - break; - } - }, - _ => unreachable!(), - } - } - - self.read_from_disk(¤t_path) - } - - fn read_from_disk(&mut self, path: &Path) -> Result<(), FsError> { - let metadata = fs::metadata(path) - .map_err(|e| FsError::new(e, path))?; - - if metadata.is_file() { - let contents = fs::read(path) - .map_err(|e| FsError::new(e, path))?; - let item = ImfsItem::File(ImfsFile { - path: path.to_path_buf(), - contents, - }); - - self.items.insert(path.to_path_buf(), item); - - if let Some(parent_path) = path.parent() { - self.link_child(parent_path, path); - } - - Ok(()) - } else if metadata.is_dir() { - let item = ImfsItem::Directory(ImfsDirectory { - path: path.to_path_buf(), - children: BTreeSet::new(), - }); - - self.items.insert(path.to_path_buf(), item); - - let dir_children = fs::read_dir(path) - .map_err(|e| FsError::new(e, path))?; - - for entry in dir_children { - let entry = entry - .map_err(|e| FsError::new(e, path))?; - - let child_path = entry.path(); - - self.read_from_disk(&child_path)?; - } - - if let Some(parent_path) = path.parent() { - self.link_child(parent_path, path); - } - - Ok(()) - } else { - panic!("Unexpected non-file, non-directory item"); - } - } - - fn get_root_path<'a>(&'a self, path: &Path) -> Option<&'a Path> { - for root_path in &self.roots { - if path.starts_with(root_path) { - return Some(root_path) - } - } - - None - } - - fn is_within_roots(&self, path: &Path) -> bool { - for root_path in &self.roots { - if path.starts_with(root_path) { - return true; - } - } - - false - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct ImfsFile { - pub path: PathBuf, - pub contents: Vec, -} - -impl PartialOrd for ImfsFile { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for ImfsFile { - fn cmp(&self, other: &Self) -> Ordering { - self.path.cmp(&other.path) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -pub struct ImfsDirectory { - pub path: PathBuf, - pub children: BTreeSet, -} - -impl PartialOrd for ImfsDirectory { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for ImfsDirectory { - fn cmp(&self, other: &Self) -> Ordering { - self.path.cmp(&other.path) - } -} - -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)] -pub enum ImfsItem { - File(ImfsFile), - Directory(ImfsDirectory), -} \ No newline at end of file diff --git a/server/src/imfs/error.rs b/server/src/imfs/error.rs new file mode 100644 index 00000000..70799785 --- /dev/null +++ b/server/src/imfs/error.rs @@ -0,0 +1,65 @@ +use std::{ + io, + fmt, + path::PathBuf, +}; + +use failure::Fail; + +pub type FsResult = Result; +pub use io::ErrorKind as FsErrorKind; + +pub trait FsResultExt { + fn with_not_found(self) -> Result, FsError>; +} + +impl FsResultExt for Result { + fn with_not_found(self) -> Result, FsError> { + match self { + Ok(value) => Ok(Some(value)), + Err(ref err) if err.kind() == FsErrorKind::NotFound => Ok(None), + Err(err) => Err(err), + } + } +} + +// TODO: New error type that contains errors specific to our application, +// wrapping io::Error either directly or through another error type that has +// path information. +// +// It's possible that we should hoist up the path information one more level, or +// destructure/restructure information to hoist the path out of FsError and just +// embed io::Error? +pub enum ImfsError { + NotFound, + WrongKind, + Io(io::Error), +} + +/// A wrapper around io::Error that also attaches the path associated with the +/// error. +#[derive(Debug, Fail)] +pub struct FsError { + #[fail(cause)] + inner: io::Error, + path: PathBuf, +} + +impl FsError { + pub fn new>(inner: io::Error, path: P) -> FsError { + FsError { + inner, + path: path.into(), + } + } + + pub fn kind(&self) -> FsErrorKind { + self.inner.kind() + } +} + +impl fmt::Display for FsError { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + write!(output, "{}: {}", self.path.display(), self.inner) + } +} \ No newline at end of file diff --git a/server/src/imfs/fetcher.rs b/server/src/imfs/fetcher.rs new file mode 100644 index 00000000..a2b62e92 --- /dev/null +++ b/server/src/imfs/fetcher.rs @@ -0,0 +1,32 @@ +use std::{ + io, + path::{Path, PathBuf}, +}; + +use crossbeam_channel::Receiver; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum FileType { + File, + Directory, +} + +// TODO: Use our own event type instead of notify's. +pub type ImfsEvent = notify::DebouncedEvent; + +/// The generic interface that `Imfs` uses to lazily read files from the disk. +/// In tests, it's stubbed out to do different versions of absolutely nothing +/// depending on the test. +pub trait ImfsFetcher { + fn file_type(&mut self, path: &Path) -> io::Result; + fn read_children(&mut self, path: &Path) -> io::Result>; + fn read_contents(&mut self, path: &Path) -> io::Result>; + + fn create_directory(&mut self, path: &Path) -> io::Result<()>; + fn write_file(&mut self, path: &Path, contents: &[u8]) -> io::Result<()>; + fn remove(&mut self, path: &Path) -> io::Result<()>; + + fn watch(&mut self, path: &Path); + fn unwatch(&mut self, path: &Path); + fn receiver(&self) -> Receiver; +} \ No newline at end of file diff --git a/server/src/imfs/imfs.rs b/server/src/imfs/imfs.rs new file mode 100644 index 00000000..913de546 --- /dev/null +++ b/server/src/imfs/imfs.rs @@ -0,0 +1,530 @@ +use std::{ + io, + path::{Path, PathBuf}, +}; + +use crossbeam_channel::Receiver; + +use crate::path_map::PathMap; + +use super::{ + snapshot::ImfsSnapshot, + error::{FsResult, FsError}, + fetcher::{ImfsFetcher, FileType, ImfsEvent}, +}; + +/// An in-memory filesystem that can be incrementally populated and updated as +/// filesystem modification events occur. +/// +/// All operations on the `Imfs` are lazy and do I/O as late as they can to +/// avoid reading extraneous files or directories from the disk. This means that +/// they all take `self` mutably, and means that it isn't possible to hold +/// references to the internal state of the Imfs while traversing it! +/// +/// Most operations return `ImfsEntry` objects to work around this, which is +/// effectively a index into the `Imfs`. +pub struct Imfs { + inner: PathMap, + fetcher: F, +} + +impl Imfs { + pub fn new(fetcher: F) -> Imfs { + Imfs { + inner: PathMap::new(), + fetcher, + } + } + + pub fn change_receiver(&self) -> Receiver { + self.fetcher.receiver() + } + + pub fn commit_pending_changes(&mut self) -> FsResult> { + let receiver = self.fetcher.receiver(); + let mut changes = Vec::new(); + + while let Ok(event) = receiver.try_recv() { + self.commit_change(&event)?; + changes.push(event); + } + + Ok(changes) + } + + pub fn commit_change(&mut self, event: &ImfsEvent) -> FsResult<()> { + use notify::DebouncedEvent::*; + + log::trace!("Committing Imfs change {:?}", event); + + match event { + Create(path) => { + self.raise_file_changed(path)?; + } + Write(path) => { + self.raise_file_changed(path)?; + } + Remove(path) => { + self.raise_file_removed(path)?; + } + Rename(from_path, to_path) => { + self.raise_file_removed(from_path)?; + self.raise_file_changed(to_path)?; + } + Error(err, path) => { + log::warn!("Filesystem error detected: {:?} on path {:?}", err, path); + } + Rescan => { + // FIXME: Implement rescanning + log::warn!("Unhandled filesystem rescan event"); + } + NoticeWrite(_) | NoticeRemove(_) | Chmod(_) => {} + } + + Ok(()) + } + + pub fn load_from_snapshot(&mut self, path: impl AsRef, snapshot: ImfsSnapshot) { + let path = path.as_ref(); + + match snapshot { + ImfsSnapshot::File(file) => { + self.inner.insert(path.to_path_buf(), ImfsItem::File(ImfsFile { + path: path.to_path_buf(), + contents: Some(file.contents), + })); + } + ImfsSnapshot::Directory(directory) => { + self.inner.insert(path.to_path_buf(), ImfsItem::Directory(ImfsDirectory { + path: path.to_path_buf(), + children_enumerated: true, + })); + + for (child_name, child) in directory.children.into_iter() { + self.load_from_snapshot(path.join(child_name), child); + } + } + } + } + + fn raise_file_changed(&mut self, path: impl AsRef) -> FsResult<()> { + let path = path.as_ref(); + + if !self.would_be_resident(path) { + return Ok(()); + } + + let new_type = self.fetcher.file_type(path) + .map_err(|err| FsError::new(err, path.to_path_buf()))?; + + match self.inner.get_mut(path) { + Some(existing_item) => { + match (existing_item, &new_type) { + (ImfsItem::File(existing_file), FileType::File) => { + // Invalidate the existing file contents. + // We can probably be smarter about this by reading the changed file. + existing_file.contents = None; + } + (ImfsItem::Directory(_), FileType::Directory) => { + // No changes required, a directory updating doesn't mean anything to us. + self.fetcher.watch(path); + } + (ImfsItem::File(_), FileType::Directory) => { + self.inner.remove(path); + self.inner.insert(path.to_path_buf(), ImfsItem::new_from_type(FileType::Directory, path)); + self.fetcher.watch(path); + } + (ImfsItem::Directory(_), FileType::File) => { + self.inner.remove(path); + self.inner.insert(path.to_path_buf(), ImfsItem::new_from_type(FileType::File, path)); + self.fetcher.unwatch(path); + } + } + } + None => { + self.inner.insert(path.to_path_buf(), ImfsItem::new_from_type(new_type, path)); + } + } + + Ok(()) + } + + fn raise_file_removed(&mut self, path: impl AsRef) -> FsResult<()> { + let path = path.as_ref(); + + if !self.would_be_resident(path) { + return Ok(()); + } + + self.inner.remove(path); + self.fetcher.unwatch(path); + Ok(()) + } + + pub fn get(&mut self, path: impl AsRef) -> FsResult { + self.read_if_not_exists(path.as_ref())?; + + let item = self.inner.get(path.as_ref()).unwrap(); + + let is_file = match item { + ImfsItem::File(_) => true, + ImfsItem::Directory(_) => false, + }; + + Ok(ImfsEntry { + path: item.path().to_path_buf(), + is_file, + }) + } + + pub fn get_contents(&mut self, path: impl AsRef) -> FsResult<&[u8]> { + let path = path.as_ref(); + + self.read_if_not_exists(path)?; + + match self.inner.get_mut(path).unwrap() { + ImfsItem::File(file) => { + if file.contents.is_none() { + file.contents = Some(self.fetcher.read_contents(path) + .map_err(|err| FsError::new(err, path.to_path_buf()))?); + } + + Ok(file.contents.as_ref().unwrap()) + } + ImfsItem::Directory(_) => Err(FsError::new(io::Error::new(io::ErrorKind::Other, "Can't read a directory"), path.to_path_buf())) + } + } + + pub fn get_children(&mut self, path: impl AsRef) -> FsResult> { + let path = path.as_ref(); + + self.read_if_not_exists(path)?; + + match self.inner.get(path).unwrap() { + ImfsItem::Directory(dir) => { + self.fetcher.watch(path); + + if dir.children_enumerated { + return self.inner.children(path) + .unwrap() // TODO: Handle None here, which means the PathMap entry did not exist. + .into_iter() + .map(PathBuf::from) // Convert paths from &Path to PathBuf + .collect::>() // Collect all PathBufs, since self.get needs to borrow self mutably. + .into_iter() + .map(|path| self.get(path)) + .collect::>>(); + } + + self.fetcher.read_children(path) + .map_err(|err| FsError::new(err, path.to_path_buf()))? + .into_iter() + .map(|path| self.get(path)) + .collect::>>() + } + ImfsItem::File(_) => Err(FsError::new(io::Error::new(io::ErrorKind::Other, "Can't read a directory"), path.to_path_buf())) + } + } + + /// Tells whether the given path, if it were loaded, would be loaded if it + /// existed. + /// + /// Returns true if the path is loaded or if its parent is loaded, is a + /// directory, and is marked as having been enumerated before. + /// + /// This idea corresponds to whether a file change event should result in + /// tangible changes to the in-memory filesystem. If a path would be + /// resident, we need to read it, and if its contents were known before, we + /// need to update them. + fn would_be_resident(&self, path: &Path) -> bool { + if self.inner.contains_key(path) { + return true; + } + + if let Some(parent) = path.parent() { + if let Some(ImfsItem::Directory(dir)) = self.inner.get(parent) { + return !dir.children_enumerated; + } + } + + false + } + + /// Attempts to read the path into the `Imfs` if it doesn't exist. + /// + /// This does not necessitate that file contents or directory children will + /// be read. Depending on the `ImfsFetcher` implementation that the `Imfs` + /// is using, this call may read exactly only the given path and no more. + fn read_if_not_exists(&mut self, path: &Path) -> FsResult<()> { + if !self.inner.contains_key(path) { + let kind = self.fetcher.file_type(path) + .map_err(|err| FsError::new(err, path.to_path_buf()))?; + + if kind == FileType::Directory { + self.fetcher.watch(path); + } + + self.inner.insert(path.to_path_buf(), ImfsItem::new_from_type(kind, path)); + } + + Ok(()) + } +} + +/// A reference to file or folder in an `Imfs`. Can only be produced by the +/// entry existing in the Imfs, but can later point to nothing if something +/// would invalidate that path. +/// +/// This struct does not borrow from the Imfs since every operation has the +/// possibility to mutate the underlying data structure and move memory around. +pub struct ImfsEntry { + path: PathBuf, + is_file: bool, +} + +impl ImfsEntry { + pub fn path(&self) -> &Path { + &self.path + } + + pub fn contents<'imfs>( + &self, + imfs: &'imfs mut Imfs, + ) -> FsResult<&'imfs [u8]> { + imfs.get_contents(&self.path) + } + + pub fn children( + &self, + imfs: &mut Imfs, + ) -> FsResult> { + imfs.get_children(&self.path) + } + + pub fn is_file(&self) -> bool { + self.is_file + } + + pub fn is_directory(&self) -> bool { + !self.is_file + } +} + +/// Internal structure describing potentially partially-resident files and +/// folders in the `Imfs`. +pub enum ImfsItem { + File(ImfsFile), + Directory(ImfsDirectory), +} + +impl ImfsItem { + fn path(&self) -> &Path { + match self { + ImfsItem::File(file) => &file.path, + ImfsItem::Directory(dir) => &dir.path, + } + } + + fn new_from_type(kind: FileType, path: impl Into) -> ImfsItem { + match kind { + FileType::Directory => ImfsItem::Directory(ImfsDirectory { + path: path.into(), + children_enumerated: false, + }), + FileType::File => ImfsItem::File(ImfsFile { + path: path.into(), + contents: None, + }), + } + } +} + +pub struct ImfsFile { + pub(super) path: PathBuf, + pub(super) contents: Option>, +} + +pub struct ImfsDirectory { + pub(super) path: PathBuf, + pub(super) children_enumerated: bool, +} + +#[cfg(test)] +mod test { + use super::*; + + use std::{ + rc::Rc, + cell::RefCell, + }; + + use crossbeam_channel::Receiver; + use maplit::hashmap; + + use super::super::{ + noop_fetcher::NoopFetcher, + error::FsErrorKind, + fetcher::ImfsEvent, + }; + + #[test] + fn from_snapshot_file() { + let mut imfs = Imfs::new(NoopFetcher); + let file = ImfsSnapshot::file("hello, world!"); + + imfs.load_from_snapshot("/hello.txt", file); + + let entry = imfs.get_contents("/hello.txt").unwrap(); + assert_eq!(entry, b"hello, world!"); + } + + #[test] + fn from_snapshot_dir() { + let mut imfs = Imfs::new(NoopFetcher); + let dir = ImfsSnapshot::dir(hashmap! { + "a.txt" => ImfsSnapshot::file("contents of a.txt"), + "b.lua" => ImfsSnapshot::file("contents of b.lua"), + }); + + imfs.load_from_snapshot("/dir", dir); + + let children = imfs.get_children("/dir").unwrap(); + + let mut has_a = false; + let mut has_b = false; + + for child in children.into_iter() { + if child.path() == Path::new("/dir/a.txt") { + has_a = true; + } else if child.path() == Path::new("/dir/b.lua") { + has_b = true; + } else { + panic!("Unexpected child in /dir"); + } + } + + assert!(has_a, "/dir/a.txt was missing"); + assert!(has_b, "/dir/b.lua was missing"); + + let a = imfs.get_contents("/dir/a.txt").unwrap(); + assert_eq!(a, b"contents of a.txt"); + + let b = imfs.get_contents("/dir/b.lua").unwrap(); + assert_eq!(b, b"contents of b.lua"); + } + + #[test] + fn changed_event() { + #[derive(Default)] + struct MockState { + a_contents: &'static str, + } + + struct MockFetcher { + inner: Rc>, + } + + impl ImfsFetcher for MockFetcher { + fn file_type(&mut self, path: &Path) -> io::Result { + if path == Path::new("/dir/a.txt") { + return Ok(FileType::File); + } + + unimplemented!(); + } + + fn read_contents(&mut self, path: &Path) -> io::Result> { + if path == Path::new("/dir/a.txt") { + let inner = self.inner.borrow(); + + return Ok(Vec::from(inner.a_contents)); + } + + unimplemented!(); + } + + fn read_children(&mut self, _path: &Path) -> io::Result> { + unimplemented!(); + } + + fn create_directory(&mut self, _path: &Path) -> io::Result<()> { + unimplemented!(); + } + + fn write_file(&mut self, _path: &Path, _contents: &[u8]) -> io::Result<()> { + unimplemented!(); + } + + fn remove(&mut self, _path: &Path) -> io::Result<()> { + unimplemented!(); + } + + fn watch(&mut self, _path: &Path) { + } + + fn unwatch(&mut self, _path: &Path) { + } + + fn receiver(&self) -> Receiver { + crossbeam_channel::never() + } + } + + let mock_state = Rc::new(RefCell::new(MockState { + a_contents: "Initial contents", + })); + + let mut imfs = Imfs::new(MockFetcher { + inner: mock_state.clone(), + }); + + let a = imfs.get("/dir/a.txt") + .expect("mock file did not exist"); + + let contents = a.contents(&mut imfs) + .expect("mock file contents error"); + + assert_eq!(contents, b"Initial contents"); + + { + let mut mock_state = mock_state.borrow_mut(); + mock_state.a_contents = "Changed contents"; + } + + imfs.raise_file_changed("/dir/a.txt") + .expect("error processing file change"); + + let contents = a.contents(&mut imfs) + .expect("mock file contents error"); + + assert_eq!(contents, b"Changed contents"); + } + + #[test] + fn removed_event_existing() { + let mut imfs = Imfs::new(NoopFetcher); + + let file = ImfsSnapshot::file("hello, world!"); + imfs.load_from_snapshot("/hello.txt", file); + + let hello = imfs.get("/hello.txt") + .expect("couldn't get hello.txt"); + + let contents = hello.contents(&mut imfs) + .expect("couldn't get hello.txt contents"); + + assert_eq!(contents, b"hello, world!"); + + imfs.raise_file_removed("/hello.txt") + .expect("error processing file removal"); + + match imfs.get("hello.txt") { + Err(ref err) if err.kind() == FsErrorKind::NotFound => {} + Ok(_) => { + panic!("hello.txt was not removed from Imfs"); + } + Err(err) => { + panic!("Unexpected error: {:?}", err); + } + } + } +} \ No newline at end of file diff --git a/server/src/imfs/mod.rs b/server/src/imfs/mod.rs new file mode 100644 index 00000000..a9e035dd --- /dev/null +++ b/server/src/imfs/mod.rs @@ -0,0 +1,17 @@ +mod error; +mod fetcher; +mod imfs; +mod noop_fetcher; +mod real_fetcher; +mod snapshot; + +pub use error::*; + +pub mod new { + pub use super::error::*; + pub use super::imfs::*; + pub use super::fetcher::*; + pub use super::real_fetcher::*; + pub use super::noop_fetcher::*; + pub use super::snapshot::*; +} \ No newline at end of file diff --git a/server/src/imfs/noop_fetcher.rs b/server/src/imfs/noop_fetcher.rs new file mode 100644 index 00000000..663744b6 --- /dev/null +++ b/server/src/imfs/noop_fetcher.rs @@ -0,0 +1,49 @@ +//! Implements the IMFS fetcher interface for a fake filesystem using Rust's +//! std::fs interface. + +use std::{ + io, + path::{Path, PathBuf}, +}; + +use crossbeam_channel::Receiver; + +use super::fetcher::{ImfsFetcher, FileType, ImfsEvent}; + +pub struct NoopFetcher; + +impl ImfsFetcher for NoopFetcher { + fn file_type(&mut self, _path: &Path) -> io::Result { + Err(io::Error::new(io::ErrorKind::NotFound, "NoopFetcher always returns NotFound")) + } + + fn read_children(&mut self, _path: &Path) -> io::Result> { + Err(io::Error::new(io::ErrorKind::NotFound, "NoopFetcher always returns NotFound")) + } + + fn read_contents(&mut self, _path: &Path) -> io::Result> { + Err(io::Error::new(io::ErrorKind::NotFound, "NoopFetcher always returns NotFound")) + } + + fn create_directory(&mut self, _path: &Path) -> io::Result<()> { + Ok(()) + } + + fn write_file(&mut self, _path: &Path, _contents: &[u8]) -> io::Result<()> { + Ok(()) + } + + fn remove(&mut self, _path: &Path) -> io::Result<()> { + Ok(()) + } + + fn watch(&mut self, _path: &Path) { + } + + fn unwatch(&mut self, _path: &Path) { + } + + fn receiver(&self) -> Receiver { + crossbeam_channel::never() + } +} \ No newline at end of file diff --git a/server/src/imfs/real_fetcher.rs b/server/src/imfs/real_fetcher.rs new file mode 100644 index 00000000..aa4c05b4 --- /dev/null +++ b/server/src/imfs/real_fetcher.rs @@ -0,0 +1,155 @@ +//! Implements the IMFS fetcher interface for the real filesystem using Rust's +//! std::fs interface and notify as the file watcher. + +use std::{ + fs, + io, + path::{Path, PathBuf}, + sync::mpsc, + time::Duration, +}; + +use jod_thread::JoinHandle; +use crossbeam_channel::{Receiver, unbounded}; +use notify::{RecursiveMode, RecommendedWatcher, Watcher}; + +use super::fetcher::{ImfsFetcher, FileType, ImfsEvent}; + +/// Workaround to disable the file watcher for processes that don't need it, +/// since notify appears hang on to mpsc Sender objects too long, causing Rojo +/// to deadlock on drop. +/// +/// We can make constructing the watcher optional in order to hotfix rojo build. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum WatchMode { + Enabled, + Disabled, +} + +pub struct RealFetcher { + // Drop order is relevant here! + // + // `watcher` must be dropped before `_converter_thread` or else joining the + // thread will cause a deadlock. + watcher: Option, + + /// Thread handle to convert notify's mpsc channel messages into + /// crossbeam_channel messages. + _converter_thread: JoinHandle<()>, + receiver: Receiver, +} + +impl RealFetcher { + pub fn new(watch_mode: WatchMode) -> RealFetcher { + log::trace!("Starting RealFetcher with watch mode {:?}", watch_mode); + + let (notify_sender, notify_receiver) = mpsc::channel(); + let (sender, receiver) = unbounded(); + + let handle = jod_thread::Builder::new() + .name("notify message converter".to_owned()) + .spawn(move || { + notify_receiver + .into_iter() + .for_each(|event| { sender.send(event).unwrap() }); + }) + .expect("Could not start message converter thread"); + + // TODO: Investigate why notify hangs onto notify_sender too long, + // causing our program to deadlock. Once this is fixed, watcher no + // longer needs to be optional, but is still maybe useful? + let watcher = match watch_mode { + WatchMode::Enabled => { + Some(notify::watcher(notify_sender, Duration::from_millis(300)) + .expect("Couldn't start 'notify' file watcher")) + } + WatchMode::Disabled => None, + }; + + RealFetcher { + watcher, + _converter_thread: handle, + receiver, + } + } +} + +impl ImfsFetcher for RealFetcher { + fn file_type(&mut self, path: &Path) -> io::Result { + let metadata = fs::metadata(path)?; + + if metadata.is_file() { + Ok(FileType::File) + } else { + Ok(FileType::Directory) + } + } + + fn read_children(&mut self, path: &Path) -> io::Result> { + log::trace!("Reading directory {}", path.display()); + + let mut result = Vec::new(); + + let iter = fs::read_dir(path)?; + + for entry in iter { + result.push(entry?.path()); + } + + Ok(result) + } + + fn read_contents(&mut self, path: &Path) -> io::Result> { + log::trace!("Reading file {}", path.display()); + + fs::read(path) + } + + fn create_directory(&mut self, path: &Path) -> io::Result<()> { + log::trace!("Creating directory {}", path.display()); + + fs::create_dir(path) + } + + fn write_file(&mut self, path: &Path, contents: &[u8]) -> io::Result<()> { + log::trace!("Writing path {}", path.display()); + + fs::write(path, contents) + } + + fn remove(&mut self, path: &Path) -> io::Result<()> { + log::trace!("Removing path {}", path.display()); + + let metadata = fs::metadata(path)?; + + if metadata.is_file() { + fs::remove_file(path) + } else { + fs::remove_dir_all(path) + } + } + + fn watch(&mut self, path: &Path) { + log::trace!("Watching path {}", path.display()); + + if let Some(watcher) = self.watcher.as_mut() { + if let Err(err) = watcher.watch(path, RecursiveMode::NonRecursive) { + log::warn!("Couldn't watch path {}: {:?}", path.display(), err); + } + } + } + + fn unwatch(&mut self, path: &Path) { + log::trace!("Stopped watching path {}", path.display()); + + if let Some(watcher) = self.watcher.as_mut() { + if let Err(err) = watcher.unwatch(path) { + log::warn!("Couldn't unwatch path {}: {:?}", path.display(), err); + } + } + } + + fn receiver(&self) -> Receiver { + self.receiver.clone() + } +} \ No newline at end of file diff --git a/server/src/imfs/snapshot.rs b/server/src/imfs/snapshot.rs new file mode 100644 index 00000000..5f57f8fd --- /dev/null +++ b/server/src/imfs/snapshot.rs @@ -0,0 +1,38 @@ +use std::collections::HashMap; + +#[derive(Debug, Clone)] +pub enum ImfsSnapshot { + File(FileSnapshot), + Directory(DirectorySnapshot), +} + +impl ImfsSnapshot { + /// Create a new file ImfsSnapshot with the given contents. + pub fn file(contents: impl Into>) -> ImfsSnapshot { + ImfsSnapshot::File(FileSnapshot { + contents: contents.into(), + }) + } + + /// Create a new directory ImfsSnapshot with the given children. + pub fn dir>(children: HashMap) -> ImfsSnapshot { + let children = children + .into_iter() + .map(|(k, v)| (k.into(), v)) + .collect(); + + ImfsSnapshot::Directory(DirectorySnapshot { + children, + }) + } +} + +#[derive(Debug, Clone)] +pub struct FileSnapshot { + pub contents: Vec, +} + +#[derive(Debug, Clone)] +pub struct DirectorySnapshot { + pub children: HashMap, +} \ No newline at end of file diff --git a/server/src/lib.rs b/server/src/lib.rs index dbcb8c66..fa05ab7f 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -2,20 +2,18 @@ // Macros #[macro_use] -pub mod impl_from; +mod impl_from; // Other modules pub mod commands; -pub mod fs_watcher; -pub mod imfs; -pub mod live_session; -pub mod message_queue; -pub mod path_map; -pub mod path_serializer; pub mod project; -pub mod rbx_session; -pub mod rbx_snapshot; -pub mod session_id; -pub mod snapshot_reconciler; -pub mod visualize; -pub mod web; \ No newline at end of file + +mod imfs; +mod message_queue; +mod path_map; +mod path_serializer; +mod serve_session; +mod session_id; +mod snapshot; +mod snapshot_middleware; +mod web; \ No newline at end of file diff --git a/server/src/live_session.rs b/server/src/live_session.rs deleted file mode 100644 index b90b6e87..00000000 --- a/server/src/live_session.rs +++ /dev/null @@ -1,99 +0,0 @@ -use std::{ - collections::HashSet, - mem, - sync::{Arc, Mutex}, -}; - -use failure::Fail; - -use crate::{ - fs_watcher::FsWatcher, - imfs::{Imfs, FsError}, - message_queue::MessageQueue, - project::Project, - rbx_session::RbxSession, - rbx_snapshot::SnapshotError, - session_id::SessionId, - snapshot_reconciler::InstanceChanges, -}; - -#[derive(Debug, Fail)] -pub enum LiveSessionError { - #[fail(display = "{}", _0)] - Fs(#[fail(cause)] FsError), - - #[fail(display = "{}", _0)] - Snapshot(#[fail(cause)] SnapshotError), -} - -impl_from!(LiveSessionError { - FsError => Fs, - SnapshotError => Snapshot, -}); - -/// Contains all of the state for a Rojo live-sync session. -pub struct LiveSession { - project: Arc, - session_id: SessionId, - pub message_queue: Arc>, - pub rbx_session: Arc>, - pub imfs: Arc>, - _fs_watcher: FsWatcher, -} - -impl LiveSession { - pub fn new(project: Arc) -> Result { - let imfs = { - let mut imfs = Imfs::new(); - imfs.add_roots_from_project(&project)?; - - Arc::new(Mutex::new(imfs)) - }; - let message_queue = Arc::new(MessageQueue::new()); - - let rbx_session = Arc::new(Mutex::new(RbxSession::new( - Arc::clone(&project), - Arc::clone(&imfs), - Arc::clone(&message_queue), - )?)); - - let fs_watcher = FsWatcher::start( - Arc::clone(&imfs), - Some(Arc::clone(&rbx_session)), - ); - - let session_id = SessionId::new(); - - Ok(LiveSession { - session_id, - project, - message_queue, - rbx_session, - imfs, - _fs_watcher: fs_watcher, - }) - } - - /// Restarts the live session using the given project while preserving the - /// internal session ID. - pub fn restart_with_new_project(&mut self, project: Arc) -> Result<(), LiveSessionError> { - let mut new_session = LiveSession::new(project)?; - new_session.session_id = self.session_id; - - mem::replace(self, new_session); - - Ok(()) - } - - pub fn root_project(&self) -> &Project { - &self.project - } - - pub fn session_id(&self) -> SessionId { - self.session_id - } - - pub fn serve_place_ids(&self) -> &Option> { - &self.project.serve_place_ids - } -} \ No newline at end of file diff --git a/server/src/path_map.rs b/server/src/path_map.rs index bebf4f9d..b67aee1b 100644 --- a/server/src/path_map.rs +++ b/server/src/path_map.rs @@ -18,6 +18,14 @@ struct PathMapNode { #[derive(Debug, Serialize)] pub struct PathMap { nodes: HashMap>, + + /// Contains the set of all paths whose parent either does not exist, or is + /// not present in the PathMap. + /// + /// Note that these paths may have other _ancestors_ in the tree, but if an + /// orphan's parent path is ever inserted, it will stop being an orphan. It + /// will be... adopted! + orphan_paths: HashSet, } impl Default for PathMap { @@ -30,49 +38,71 @@ impl PathMap { pub fn new() -> PathMap { PathMap { nodes: HashMap::new(), + orphan_paths: HashSet::new(), } } - pub fn get(&self, path: &Path) -> Option<&T> { - self.nodes.get(path).map(|v| &v.value) + pub fn get(&self, path: impl AsRef) -> Option<&T> { + self.nodes.get(path.as_ref()).map(|v| &v.value) } - pub fn get_mut(&mut self, path: &Path) -> Option<&mut T> { - self.nodes.get_mut(path).map(|v| &mut v.value) + pub fn get_mut(&mut self, path: impl AsRef) -> Option<&mut T> { + self.nodes.get_mut(path.as_ref()).map(|v| &mut v.value) } - pub fn insert(&mut self, path: PathBuf, value: T) { - if let Some(parent_path) = path.parent() { - if let Some(parent) = self.nodes.get_mut(parent_path) { - parent.children.insert(path.to_path_buf()); + pub fn children(&self, path: impl AsRef) -> Option> { + self.nodes.get(path.as_ref()).map(|v| v.children.iter().map(AsRef::as_ref).collect()) + } + + pub fn contains_key(&self, path: impl AsRef) -> bool { + self.nodes.contains_key(path.as_ref()) + } + + pub fn insert(&mut self, path: impl Into, value: T) { + let path = path.into(); + + self.add_to_parent(path.clone()); + + // Collect any children that are currently marked as orphaned paths, but + // are actually children of this new node. + let mut children = HashSet::new(); + for orphan_path in &self.orphan_paths { + if orphan_path.parent() == Some(&path) { + children.insert(orphan_path.clone()); } } + for child in &children { + self.orphan_paths.remove(child); + } + self.nodes.insert(path, PathMapNode { value, - children: HashSet::new(), + children, }); } - pub fn remove(&mut self, root_path: &Path) -> Option { - if let Some(parent_path) = root_path.parent() { - if let Some(parent) = self.nodes.get_mut(parent_path) { - parent.children.remove(root_path); - } - } + /// Remove the given path and all of its linked descendants, returning all + /// values stored in the map. + pub fn remove(&mut self, root_path: impl AsRef) -> Vec<(PathBuf, T)> { + let root_path = root_path.as_ref(); - let mut root_node = match self.nodes.remove(root_path) { + self.remove_from_parent(root_path); + + let (root_path, root_node) = match self.nodes.remove_entry(root_path) { Some(node) => node, - None => return None, + None => return Vec::new(), }; - let root_value = root_node.value; - let mut to_visit: Vec = root_node.children.drain().collect(); + let mut removed_entries = vec![(root_path, root_node.value)]; + let mut to_visit: Vec = root_node.children.into_iter().collect(); while let Some(path) = to_visit.pop() { - match self.nodes.remove(&path) { - Some(mut node) => { - for child in node.children.drain() { + match self.nodes.remove_entry(&path) { + Some((path, node)) => { + removed_entries.push((path, node.value)); + + for child in node.children.into_iter() { to_visit.push(child); } }, @@ -82,7 +112,7 @@ impl PathMap { } } - Some(root_value) + removed_entries } /// Traverses the route between `start_path` and `target_path` and returns @@ -93,10 +123,13 @@ impl PathMap { /// FS events, a file remove event could be followed by that file's /// directory being removed, in which case we should process that /// directory's parent. - pub fn descend(&self, start_path: &Path, target_path: &Path) -> PathBuf { - let relative_path = target_path.strip_prefix(start_path) + pub fn descend(&self, start_path: impl Into, target_path: impl AsRef) -> PathBuf { + let start_path = start_path.into(); + let target_path = target_path.as_ref(); + + let relative_path = target_path.strip_prefix(&start_path) .expect("target_path did not begin with start_path"); - let mut current_path = start_path.to_path_buf(); + let mut current_path = start_path; for component in relative_path.components() { match component { @@ -115,4 +148,131 @@ impl PathMap { current_path } + + /// Adds the path to its parent if it's present in the tree, or the set of + /// orphaned paths if it is not. + fn add_to_parent(&mut self, path: PathBuf) { + if let Some(parent_path) = path.parent() { + if let Some(parent) = self.nodes.get_mut(parent_path) { + parent.children.insert(path); + return; + } + } + + // In this branch, the path is orphaned because it either doesn't have a + // parent according to Path, or because its parent doesn't exist in the + // PathMap. + self.orphan_paths.insert(path); + } + + /// Removes the path from its parent, or from the orphaned paths set if it + /// has no parent. + fn remove_from_parent(&mut self, path: &Path) { + if let Some(parent_path) = path.parent() { + if let Some(parent) = self.nodes.get_mut(parent_path) { + parent.children.remove(path); + return; + } + } + + // In this branch, the path is orphaned because it either doesn't have a + // parent according to Path, or because its parent doesn't exist in the + // PathMap. + self.orphan_paths.remove(path); + } +} + +#[cfg(test)] +mod test { + use super::*; + + use maplit::hashset; + + #[test] + fn smoke_test() { + let mut map = PathMap::new(); + + assert_eq!(map.get("/foo"), None); + map.insert("/foo", 5); + assert_eq!(map.get("/foo"), Some(&5)); + + map.insert("/foo/bar", 6); + assert_eq!(map.get("/foo"), Some(&5)); + assert_eq!(map.get("/foo/bar"), Some(&6)); + assert_eq!(map.children("/foo"), Some(vec![Path::new("/foo/bar")])); + } + + #[test] + fn orphans() { + let mut map = PathMap::new(); + + map.insert("/foo/bar", 5); + assert_eq!(map.orphan_paths, hashset!["/foo/bar".into()]); + + map.insert("/foo", 6); + assert_eq!(map.orphan_paths, hashset!["/foo".into()]); + } + + #[test] + fn remove_one() { + let mut map = PathMap::new(); + + map.insert("/foo", 6); + + assert_eq!(map.remove("/foo"), vec![ + (PathBuf::from("/foo"), 6), + ]); + + assert_eq!(map.get("/foo"), None); + } + + #[test] + fn remove_child() { + let mut map = PathMap::new(); + + map.insert("/foo", 6); + map.insert("/foo/bar", 12); + + assert_eq!(map.remove("/foo"), vec![ + (PathBuf::from("/foo"), 6), + (PathBuf::from("/foo/bar"), 12), + ]); + + assert_eq!(map.get("/foo"), None); + assert_eq!(map.get("/foo/bar"), None); + } + + #[test] + fn remove_descendant() { + let mut map = PathMap::new(); + + map.insert("/foo", 6); + map.insert("/foo/bar", 12); + map.insert("/foo/bar/baz", 18); + + assert_eq!(map.remove("/foo"), vec![ + (PathBuf::from("/foo"), 6), + (PathBuf::from("/foo/bar"), 12), + (PathBuf::from("/foo/bar/baz"), 18), + ]); + + assert_eq!(map.get("/foo"), None); + assert_eq!(map.get("/foo/bar"), None); + assert_eq!(map.get("/foo/bar/baz"), None); + } + + #[test] + fn remove_not_orphan_descendants() { + let mut map = PathMap::new(); + + map.insert("/foo", 6); + map.insert("/foo/bar/baz", 12); + + assert_eq!(map.remove("/foo"), vec![ + (PathBuf::from("/foo"), 6), + ]); + + assert_eq!(map.get("/foo"), None); + assert_eq!(map.get("/foo/bar/baz"), Some(&12)); + } } \ No newline at end of file diff --git a/server/src/path_serializer.rs b/server/src/path_serializer.rs index 41cfc5d0..d7880b88 100644 --- a/server/src/path_serializer.rs +++ b/server/src/path_serializer.rs @@ -8,7 +8,7 @@ //! To use, annotate your PathBuf or Option field with the correct //! serializer function: //! -//! ``` +//! ```ignore //! # use std::path::PathBuf; //! # use serde::{Serialize, Deserialize}; //! diff --git a/server/src/project.rs b/server/src/project.rs index 9a96dad7..f788b0e3 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -465,6 +465,12 @@ impl Project { Ok(parsed.into_project(project_file_location)) } + pub fn load_from_slice(contents: &[u8], project_file_location: &Path) -> Result { + let parsed: SourceProject = serde_json::from_slice(&contents)?; + + Ok(parsed.into_project(project_file_location)) + } + pub fn load_fuzzy(fuzzy_project_location: &Path) -> Result { if let Some(project_path) = Self::locate(fuzzy_project_location) { Self::load_exact(&project_path) diff --git a/server/src/rbx_session.rs b/server/src/rbx_session.rs deleted file mode 100644 index 80fe58e2..00000000 --- a/server/src/rbx_session.rs +++ /dev/null @@ -1,289 +0,0 @@ -use std::{ - borrow::Cow, - collections::{HashSet, HashMap}, - path::{Path, PathBuf}, - str, - sync::{Arc, Mutex}, -}; - -use rlua::Lua; -use serde::{Serialize, Deserialize}; -use log::{info, trace, error}; -use rbx_dom_weak::{RbxTree, RbxId}; - -use crate::{ - project::{Project, ProjectNode}, - message_queue::MessageQueue, - imfs::{Imfs, ImfsItem}, - path_map::PathMap, - rbx_snapshot::{ - SnapshotError, - SnapshotContext, - SnapshotPluginContext, - SnapshotPluginEntry, - snapshot_project_tree, - snapshot_project_node, - snapshot_imfs_path, - }, - snapshot_reconciler::{InstanceChanges, reify_root, reconcile_subtree}, -}; - -const INIT_SCRIPT: &str = "init.lua"; -const INIT_SERVER_SCRIPT: &str = "init.server.lua"; -const INIT_CLIENT_SCRIPT: &str = "init.client.lua"; - -/// `source_path` or `project_definition` or both must both be Some. -#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] -pub struct MetadataPerInstance { - pub ignore_unknown_instances: bool, - - /// The path on the filesystem that the instance was read from the - /// filesystem if it came from the filesystem. - #[serde(serialize_with = "crate::path_serializer::serialize_option")] - pub source_path: Option, - - /// Information about the instance that came from the project that defined - /// it, if that's where it was defined. - /// - /// A key-value pair where the key should be the name of the instance and - /// the value is the ProjectNode from the instance's project. - pub project_definition: Option<(String, ProjectNode)>, -} - -/// Contains all of the state needed to update an `RbxTree` in real time using -/// the in-memory filesystem, as well as messaging to Rojo clients what -/// instances have actually updated at any point. -pub struct RbxSession { - tree: RbxTree, - - instances_per_path: PathMap>, - metadata_per_instance: HashMap, - message_queue: Arc>, - imfs: Arc>, -} - -impl RbxSession { - pub fn new( - project: Arc, - imfs: Arc>, - message_queue: Arc>, - ) -> Result { - let mut instances_per_path = PathMap::new(); - let mut metadata_per_instance = HashMap::new(); - - let plugin_context = if cfg!(feature = "server-plugins") { - let lua = Lua::new(); - let mut callback_key = None; - - lua.context(|context| { - let callback = context.load(r#" - return function(snapshot) - print("got my snapshot:", snapshot) - print("name:", snapshot.name, "class name:", snapshot.className) - end"#) - .set_name("a cool plugin").unwrap() - .call::<(), rlua::Function>(()).unwrap(); - - callback_key = Some(context.create_registry_value(callback).unwrap()); - }); - - let plugins = vec![ - SnapshotPluginEntry { - file_name_filter: String::new(), - callback: callback_key.unwrap(), - } - ]; - - Some(SnapshotPluginContext { lua, plugins }) - } else { - None - }; - - let context = SnapshotContext { - plugin_context, - }; - - let tree = { - let temp_imfs = imfs.lock().unwrap(); - reify_initial_tree( - &project, - &context, - &temp_imfs, - &mut instances_per_path, - &mut metadata_per_instance, - )? - }; - - Ok(RbxSession { - tree, - instances_per_path, - metadata_per_instance, - message_queue, - imfs, - }) - } - - fn path_created_or_updated(&mut self, path: &Path) { - // TODO: Track paths actually updated in each step so we can ignore - // redundant changes. - let mut changes = InstanceChanges::default(); - - { - let imfs = self.imfs.lock().unwrap(); - let root_path = imfs.get_root_for_path(path) - .expect("Path was outside in-memory filesystem roots"); - - // Find the closest instance in the tree that currently exists - let mut path_to_snapshot = self.instances_per_path.descend(root_path, path); - - // If this is a file that might affect its parent if modified, we - // should snapshot its parent instead. - match path_to_snapshot.file_name().unwrap().to_str() { - Some(INIT_SCRIPT) | Some(INIT_SERVER_SCRIPT) | Some(INIT_CLIENT_SCRIPT) => { - path_to_snapshot.pop(); - }, - _ => {}, - } - - trace!("Snapshotting path {}", path_to_snapshot.display()); - - let instances_at_path = self.instances_per_path.get(&path_to_snapshot) - .expect("Metadata did not exist for path") - .clone(); - - let context = SnapshotContext { - plugin_context: None, - }; - - for instance_id in &instances_at_path { - let instance_metadata = self.metadata_per_instance.get(&instance_id) - .expect("Metadata for instance ID did not exist"); - - let maybe_snapshot = match &instance_metadata.project_definition { - Some((instance_name, project_node)) => { - snapshot_project_node(&context, &imfs, &project_node, Cow::Owned(instance_name.clone())) - // .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())) - }, - None => { - snapshot_imfs_path(&context, &imfs, &path_to_snapshot, None) - // .unwrap_or_else(|_| panic!("Could not generate instance snapshot for path {}", path_to_snapshot.display())) - }, - }; - - let snapshot = match maybe_snapshot { - Ok(Some(snapshot)) => snapshot, - Ok(None) => { - trace!("Path resulted in no snapshot being generated."); - return; - }, - Err(err) => { - error!("Rojo couldn't turn one of the project's files into Roblox instances."); - error!("Any changes to the file have been ignored."); - error!("{}", err); - return; - }, - }; - - trace!("Snapshot: {:#?}", snapshot); - - reconcile_subtree( - &mut self.tree, - *instance_id, - &snapshot, - &mut self.instances_per_path, - &mut self.metadata_per_instance, - &mut changes, - ); - } - } - - if changes.is_empty() { - trace!("No instance changes triggered from file update."); - } else { - trace!("Pushing changes: {}", changes); - self.message_queue.push_messages(&[changes]); - } - } - - pub fn path_created(&mut self, path: &Path) { - info!("Path created: {}", path.display()); - self.path_created_or_updated(path); - } - - pub fn path_updated(&mut self, path: &Path) { - info!("Path updated: {}", path.display()); - - { - let imfs = self.imfs.lock().unwrap(); - - // If the path doesn't exist or is a directory, we don't care if it - // updated - match imfs.get(path) { - Some(ImfsItem::Directory(_)) => { - trace!("Updated path was a directory, ignoring."); - return; - }, - None => { - trace!("Updated path did not exist in IMFS, ignoring."); - return; - }, - Some(ImfsItem::File(_)) => {}, - } - } - - self.path_created_or_updated(path); - } - - pub fn path_removed(&mut self, path: &Path) { - info!("Path removed: {}", path.display()); - self.instances_per_path.remove(path); - self.path_created_or_updated(path); - } - - pub fn path_renamed(&mut self, from_path: &Path, to_path: &Path) { - info!("Path renamed from {} to {}", from_path.display(), to_path.display()); - self.instances_per_path.remove(from_path); - self.path_created_or_updated(from_path); - self.path_created_or_updated(to_path); - } - - pub fn get_tree(&self) -> &RbxTree { - &self.tree - } - - pub fn get_all_instance_metadata(&self) -> &HashMap { - &self.metadata_per_instance - } - - pub fn get_instance_metadata(&self, id: RbxId) -> Option<&MetadataPerInstance> { - self.metadata_per_instance.get(&id) - } -} - -pub fn construct_oneoff_tree(project: &Project, imfs: &Imfs) -> Result { - let mut instances_per_path = PathMap::new(); - let mut metadata_per_instance = HashMap::new(); - let context = SnapshotContext { - plugin_context: None, - }; - - reify_initial_tree(project, &context, imfs, &mut instances_per_path, &mut metadata_per_instance) -} - -fn reify_initial_tree( - project: &Project, - context: &SnapshotContext, - imfs: &Imfs, - instances_per_path: &mut PathMap>, - metadata_per_instance: &mut HashMap, -) -> Result { - let snapshot = match snapshot_project_tree(&context, imfs, project)? { - Some(snapshot) => snapshot, - None => panic!("Project did not produce any instances"), - }; - - let mut changes = InstanceChanges::default(); - let tree = reify_root(&snapshot, instances_per_path, metadata_per_instance, &mut changes); - - Ok(tree) -} \ No newline at end of file diff --git a/server/src/rbx_snapshot.rs b/server/src/rbx_snapshot.rs deleted file mode 100644 index 8ed65ea7..00000000 --- a/server/src/rbx_snapshot.rs +++ /dev/null @@ -1,896 +0,0 @@ -//! Defines how Rojo transforms files into instances through the snapshot -//! system. - -use std::{ - borrow::Cow, - collections::HashMap, - fmt, - path::{Path, PathBuf}, - str, -}; - -use rlua::Lua; -use failure::Fail; -use log::info; -use maplit::hashmap; -use rbx_dom_weak::{RbxTree, RbxValue, RbxInstanceProperties, UnresolvedRbxValue}; -use serde::{Serialize, Deserialize}; -use rbx_reflection::{try_resolve_value, ValueResolveError}; - -use crate::{ - imfs::{ - Imfs, - ImfsItem, - ImfsFile, - ImfsDirectory, - }, - project::{ - Project, - ProjectNode, - }, - snapshot_reconciler::{ - RbxSnapshotInstance, - snapshot_from_tree, - }, - // TODO: Move MetadataPerInstance into this module? - rbx_session::MetadataPerInstance, -}; - -const INIT_MODULE_NAME: &str = "init.lua"; -const INIT_SERVER_NAME: &str = "init.server.lua"; -const INIT_CLIENT_NAME: &str = "init.client.lua"; - -pub struct SnapshotContext { - pub plugin_context: Option, -} - -/// Context that's only relevant to generating snapshots if there are plugins -/// associated with the project. -/// -/// It's possible that this needs some sort of extra nesting/filtering to -/// support nested projects, since their plugins should only apply to -/// themselves. -pub struct SnapshotPluginContext { - pub lua: Lua, - pub plugins: Vec, -} - -pub struct SnapshotPluginEntry { - /// Simple file name suffix filter to avoid running plugins on every file - /// change. - pub file_name_filter: String, - - /// A key into the Lua registry created by [`create_registry_value`] that - /// refers to a function that can be called to transform a file/instance - /// pair according to how the plugin needs to operate. - /// - /// [`create_registry_value`]: https://docs.rs/rlua/0.16.2/rlua/struct.Context.html#method.create_registry_value - pub callback: rlua::RegistryKey, -} - -#[derive(Debug, Clone)] -struct LuaRbxSnapshot(RbxSnapshotInstance<'static>); - -impl rlua::UserData for LuaRbxSnapshot { - fn add_methods<'lua, M: rlua::UserDataMethods<'lua, Self>>(methods: &mut M) { - methods.add_meta_method(rlua::MetaMethod::Index, |_context, this, key: String| { - match key.as_str() { - "name" => Ok(this.0.name.clone().into_owned()), - "className" => Ok(this.0.class_name.clone().into_owned()), - _ => Err(rlua::Error::RuntimeError(format!("{} is not a valid member of RbxSnapshotInstance", &key))), - } - }); - - methods.add_meta_method(rlua::MetaMethod::ToString, |_context, _this, _args: ()| { - Ok("RbxSnapshotInstance") - }); - } -} - -pub type SnapshotResult<'a> = Result>, SnapshotError>; - -#[derive(Debug, Fail)] -pub enum SnapshotError { - DidNotExist(PathBuf), - - Utf8Error { - #[fail(cause)] - inner: str::Utf8Error, - path: PathBuf, - }, - - JsonModelDecodeError { - #[fail(cause)] - inner: serde_json::Error, - path: PathBuf, - }, - - ExtraMetadataError { - #[fail(cause)] - inner: serde_json::Error, - path: PathBuf, - }, - - InvalidMetadataModelField { - field_name: String, - path: PathBuf, - }, - - MetadataClassNameNonInit { - path: PathBuf, - }, - - XmlModelDecodeError { - #[fail(cause)] - inner: rbx_xml::DecodeError, - path: PathBuf, - }, - - BinaryModelDecodeError { - inner: rbx_binary::DecodeError, - path: PathBuf, - }, - - CsvDecodeError { - #[fail(cause)] - inner: csv::Error, - path: PathBuf, - }, - - ProjectNodeUnusable, - - ProjectNodeInvalidTransmute { - partition_path: PathBuf, - }, - - PropertyResolveError { - #[fail(cause)] - inner: ValueResolveError, - }, -} - -impl From for SnapshotError { - fn from(inner: ValueResolveError) -> SnapshotError { - SnapshotError::PropertyResolveError { - inner, - } - } -} - -impl fmt::Display for SnapshotError { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - match self { - SnapshotError::DidNotExist(path) => write!(output, "Path did not exist: {}", path.display()), - SnapshotError::Utf8Error { inner, path } => { - write!(output, "Invalid UTF-8: {} in path {}", inner, path.display()) - }, - SnapshotError::JsonModelDecodeError { inner, path } => { - write!(output, "Malformed .model.json model: {} in path {}", inner, path.display()) - }, - SnapshotError::ExtraMetadataError { inner, path } => { - write!(output, "Malformed init.meta.json: {} in path {}", inner, path.display()) - }, - SnapshotError::InvalidMetadataModelField { field_name, path } => { - writeln!(output, "The field '{}' cannot be specified on .meta.json files attached to models.", field_name)?; - writeln!(output, "Model path: {}", path.display()) - }, - SnapshotError::MetadataClassNameNonInit { path } => { - writeln!(output, "The field 'className' cannot be specified on .meta.json files besides init.meta.json")?; - writeln!(output, "Model path: {}", path.display()) - }, - SnapshotError::XmlModelDecodeError { inner, path } => { - write!(output, "Malformed rbxmx model: {} in path {}", inner, path.display()) - }, - SnapshotError::BinaryModelDecodeError { inner, path } => { - write!(output, "Malformed rbxm model: {:?} in path {}", inner, path.display()) - }, - SnapshotError::CsvDecodeError { inner, path } => { - write!(output, "Malformed csv file: {} in path {}", inner, path.display()) - }, - SnapshotError::ProjectNodeUnusable => { - write!(output, "Rojo project nodes must specify either $path or $className.") - }, - SnapshotError::ProjectNodeInvalidTransmute { partition_path } => { - writeln!(output, "Rojo project nodes that specify both $path and $className require that the")?; - writeln!(output, "instance produced by the files pointed to by $path has a ClassName of")?; - writeln!(output, "Folder.")?; - writeln!(output, "")?; - writeln!(output, "Partition target ($path): {}", partition_path.display()) - }, - SnapshotError::PropertyResolveError { inner } => write!(output, "{}", inner), - } - } -} - -pub fn snapshot_project_tree<'source>( - context: &SnapshotContext, - imfs: &'source Imfs, - project: &'source Project, -) -> SnapshotResult<'source> { - snapshot_project_node(context, imfs, &project.tree, Cow::Borrowed(&project.name)) -} - -pub fn snapshot_project_node<'source>( - context: &SnapshotContext, - imfs: &'source Imfs, - node: &ProjectNode, - instance_name: Cow<'source, str>, -) -> SnapshotResult<'source> { - let maybe_snapshot = match &node.path { - Some(path) => snapshot_imfs_path(context, imfs, &path, Some(instance_name.clone()))?, - None => match &node.class_name { - Some(_class_name) => Some(RbxSnapshotInstance { - name: instance_name.clone(), - - // These properties are replaced later in the function to - // reduce code duplication. - class_name: Cow::Borrowed("Folder"), - properties: HashMap::new(), - children: Vec::new(), - metadata: MetadataPerInstance { - source_path: None, - ignore_unknown_instances: true, - project_definition: None, - }, - }), - None => { - return Err(SnapshotError::ProjectNodeUnusable); - }, - }, - }; - - // If the snapshot resulted in no instances, like if it targets an unknown - // file or an empty model file, we can early-return. - // - // In the future, we might want to issue a warning if the project also - // specified fields like class_name, since the user will probably be - // confused as to why nothing showed up in the tree. - let mut snapshot = match maybe_snapshot { - Some(snapshot) => snapshot, - None => { - // TODO: Return some other sort of marker here instead? If a node - // transitions from None into Some, it's possible that configuration - // from the ProjectNode might be lost since there's nowhere to put - // it! - return Ok(None); - }, - }; - - // Applies the class name specified in `class_name` from the project, if it's - // set. - if let Some(class_name) = &node.class_name { - // This can only happen if `path` was specified in the project node and - // that path represented a non-Folder instance. - if snapshot.class_name != "Folder" { - return Err(SnapshotError::ProjectNodeInvalidTransmute { - partition_path: node.path.as_ref().unwrap().to_owned(), - }); - } - - snapshot.class_name = Cow::Owned(class_name.to_owned()); - } - - for (child_name, child_project_node) in &node.children { - if let Some(child) = snapshot_project_node(context, imfs, child_project_node, Cow::Owned(child_name.clone()))? { - snapshot.children.push(child); - } - } - - for (key, value) in &node.properties { - let resolved_value = try_resolve_value(&snapshot.class_name, key, value)?; - snapshot.properties.insert(key.clone(), resolved_value); - } - - if let Some(ignore_unknown_instances) = node.ignore_unknown_instances { - snapshot.metadata.ignore_unknown_instances = ignore_unknown_instances; - } - - snapshot.metadata.project_definition = Some((instance_name.into_owned(), node.clone())); - - Ok(Some(snapshot)) -} - -pub fn snapshot_imfs_path<'source>( - context: &SnapshotContext, - imfs: &'source Imfs, - path: &Path, - instance_name: Option>, -) -> SnapshotResult<'source> { - // If the given path doesn't exist in the in-memory filesystem, we consider - // that an error. - match imfs.get(path) { - Some(imfs_item) => snapshot_imfs_item(context, imfs, imfs_item, instance_name), - None => return Err(SnapshotError::DidNotExist(path.to_owned())), - } -} - -fn snapshot_imfs_item<'source>( - context: &SnapshotContext, - imfs: &'source Imfs, - item: &'source ImfsItem, - instance_name: Option>, -) -> SnapshotResult<'source> { - match item { - ImfsItem::File(file) => snapshot_imfs_file(context, imfs, file, instance_name), - ImfsItem::Directory(directory) => snapshot_imfs_directory(context, imfs, directory, instance_name), - } -} - -fn snapshot_imfs_directory<'source>( - context: &SnapshotContext, - imfs: &'source Imfs, - directory: &'source ImfsDirectory, - instance_name: Option>, -) -> SnapshotResult<'source> { - let init_path = directory.path.join(INIT_MODULE_NAME); - let init_server_path = directory.path.join(INIT_SERVER_NAME); - let init_client_path = directory.path.join(INIT_CLIENT_NAME); - - let snapshot_name = instance_name - .unwrap_or_else(|| { - Cow::Borrowed(directory.path - .file_name().expect("Could not extract file name") - .to_str().expect("Could not convert path to UTF-8")) - }); - - let mut snapshot = if directory.children.contains(&init_path) { - snapshot_imfs_path(context, imfs, &init_path, Some(snapshot_name))?.unwrap() - } else if directory.children.contains(&init_server_path) { - snapshot_imfs_path(context, imfs, &init_server_path, Some(snapshot_name))?.unwrap() - } else if directory.children.contains(&init_client_path) { - snapshot_imfs_path(context, imfs, &init_client_path, Some(snapshot_name))?.unwrap() - } else { - RbxSnapshotInstance { - class_name: Cow::Borrowed("Folder"), - name: snapshot_name, - properties: HashMap::new(), - children: Vec::new(), - metadata: MetadataPerInstance { - source_path: None, - ignore_unknown_instances: false, - project_definition: None, - }, - } - }; - - if let Some(meta) = ExtraMetadata::locate(&imfs, &directory.path.join("init"))? { - meta.apply(&mut snapshot)?; - } - - snapshot.metadata.source_path = Some(directory.path.to_owned()); - - for child_path in &directory.children { - let child_name = child_path - .file_name().expect("Couldn't extract file name") - .to_str().expect("Couldn't convert file name to UTF-8"); - - if child_name.ends_with(".meta.json") { - // meta.json files don't turn into instances themselves, they just - // modify other instances. - continue; - } - - match child_name { - INIT_MODULE_NAME | INIT_SERVER_NAME | INIT_CLIENT_NAME => { - // The existence of files with these names modifies the - // parent instance and is handled above, so we can skip - // them here. - continue; - } - _ => {} - } - - if let Some(child) = snapshot_imfs_path(context, imfs, child_path, None)? { - snapshot.children.push(child); - } - } - - Ok(Some(snapshot)) -} - -#[derive(Debug, Default, Deserialize)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -struct ExtraMetadata { - class_name: Option, - ignore_unknown_instances: Option, - - #[serde(default = "HashMap::new")] - properties: HashMap, -} - -impl ExtraMetadata { - fn apply(self, snapshot: &mut RbxSnapshotInstance) -> Result<(), SnapshotError> { - if let Some(meta_class) = self.class_name { - snapshot.class_name = Cow::Owned(meta_class); - } - - if let Some(meta_ignore_instances) = self.ignore_unknown_instances { - snapshot.metadata.ignore_unknown_instances = meta_ignore_instances; - } - - for (key, value) in self.properties { - let resolved_value = try_resolve_value(&snapshot.class_name, &key, &value)?; - snapshot.properties.insert(key, resolved_value); - } - - Ok(()) - } - - fn locate(imfs: &Imfs, path: &Path) -> Result, SnapshotError> { - match imfs.get(&path.with_extension("meta.json")) { - Some(ImfsItem::File(file)) => { - let meta: ExtraMetadata = serde_json::from_slice(&file.contents) - .map_err(|inner| SnapshotError::ExtraMetadataError { - inner, - path: file.path.to_path_buf(), - })?; - - Ok(Some(meta)) - } - _ => Ok(None) - } - } - - fn validate_for_non_init(&self, path: &Path) -> Result<(), SnapshotError> { - if self.class_name.is_some() { - return Err(SnapshotError::MetadataClassNameNonInit { - path: path.to_owned(), - }); - } - - Ok(()) - } - - fn validate_for_model(&self, path: &Path) -> Result<(), SnapshotError> { - if self.class_name.is_some() { - return Err(SnapshotError::InvalidMetadataModelField { - field_name: "className".to_owned(), - path: path.to_owned(), - }); - } - - if !self.properties.is_empty() { - return Err(SnapshotError::InvalidMetadataModelField { - field_name: "properties".to_owned(), - path: path.to_owned(), - }); - } - - Ok(()) - } -} - -fn snapshot_imfs_file<'source>( - context: &SnapshotContext, - imfs: &'source Imfs, - file: &'source ImfsFile, - instance_name: Option>, -) -> SnapshotResult<'source> { - let extension = file.path.extension() - .map(|v| v.to_str().expect("Could not convert extension to UTF-8")); - - let mut maybe_snapshot = match extension { - Some("lua") => snapshot_lua_file(file, imfs)?, - Some("csv") => snapshot_csv_file(file, imfs)?, - Some("txt") => snapshot_txt_file(file, imfs)?, - Some("rbxmx") => snapshot_xml_model_file(file, imfs)?, - Some("rbxm") => snapshot_binary_model_file(file, imfs)?, - Some("json") => { - let file_stem = file.path - .file_stem().expect("Could not extract file stem") - .to_str().expect("Could not convert path to UTF-8"); - - if file_stem.ends_with(".model") { - snapshot_json_model_file(file)? - } else { - None - } - }, - Some(_) | None => None, - }; - - if let Some(mut snapshot) = maybe_snapshot.as_mut() { - // Carefully preserve name from project manifest if present. - if let Some(snapshot_name) = instance_name { - snapshot.name = snapshot_name; - } - } else { - info!("File generated no snapshot: {}", file.path.display()); - } - - if let Some(snapshot) = maybe_snapshot.as_ref() { - if let Some(plugin_context) = &context.plugin_context { - for plugin in &plugin_context.plugins { - let owned_snapshot = snapshot.get_owned(); - let registry_key = &plugin.callback; - - plugin_context.lua.context(move |context| { - let callback: rlua::Function = context.registry_value(registry_key).unwrap(); - callback.call::<_, ()>(LuaRbxSnapshot(owned_snapshot)).unwrap(); - }); - } - } - } - - Ok(maybe_snapshot) -} - -fn snapshot_lua_file<'source>( - file: &'source ImfsFile, - imfs: &'source Imfs, -) -> SnapshotResult<'source> { - let file_stem = file.path - .file_stem().expect("Could not extract file stem") - .to_str().expect("Could not convert path to UTF-8"); - - let (instance_name, class_name) = if let Some(name) = match_trailing(file_stem, ".server") { - (name, "Script") - } else if let Some(name) = match_trailing(file_stem, ".client") { - (name, "LocalScript") - } else { - (file_stem, "ModuleScript") - }; - - let contents = str::from_utf8(&file.contents) - .map_err(|inner| SnapshotError::Utf8Error { - inner, - path: file.path.to_path_buf(), - })?; - - let mut snapshot = RbxSnapshotInstance { - name: Cow::Borrowed(instance_name), - class_name: Cow::Borrowed(class_name), - properties: hashmap! { - "Source".to_owned() => RbxValue::String { - value: contents.to_owned(), - }, - }, - children: Vec::new(), - metadata: MetadataPerInstance { - source_path: Some(file.path.to_path_buf()), - ignore_unknown_instances: false, - project_definition: None, - }, - }; - - if let Some(meta) = ExtraMetadata::locate(&imfs, &file.path.with_file_name(instance_name))? { - meta.validate_for_non_init(&file.path)?; - meta.apply(&mut snapshot)?; - } - - Ok(Some(snapshot)) -} - -fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { - if input.ends_with(trailer) { - let end = input.len().saturating_sub(trailer.len()); - Some(&input[..end]) - } else { - None - } -} - -fn snapshot_txt_file<'source>( - file: &'source ImfsFile, - imfs: &'source Imfs, -) -> SnapshotResult<'source> { - let instance_name = file.path - .file_stem().expect("Could not extract file stem") - .to_str().expect("Could not convert path to UTF-8"); - - let contents = str::from_utf8(&file.contents) - .map_err(|inner| SnapshotError::Utf8Error { - inner, - path: file.path.to_path_buf(), - })?; - - let mut snapshot = RbxSnapshotInstance { - name: Cow::Borrowed(instance_name), - class_name: Cow::Borrowed("StringValue"), - properties: hashmap! { - "Value".to_owned() => RbxValue::String { - value: contents.to_owned(), - }, - }, - children: Vec::new(), - metadata: MetadataPerInstance { - source_path: Some(file.path.to_path_buf()), - ignore_unknown_instances: false, - project_definition: None, - }, - }; - - if let Some(meta) = ExtraMetadata::locate(&imfs, &file.path)? { - meta.validate_for_non_init(&file.path)?; - meta.apply(&mut snapshot)?; - } - - Ok(Some(snapshot)) -} - -fn snapshot_csv_file<'source>( - file: &'source ImfsFile, - imfs: &'source Imfs, -) -> SnapshotResult<'source> { - /// Struct that holds any valid row from a Roblox CSV translation table. - /// - /// We manually deserialize into this table from CSV, but let JSON handle - /// serializing. - #[derive(Debug, Default, Serialize)] - #[serde(rename_all = "camelCase")] - struct LocalizationEntry<'a> { - #[serde(skip_serializing_if = "Option::is_none")] - key: Option<&'a str>, - - #[serde(skip_serializing_if = "Option::is_none")] - context: Option<&'a str>, - - #[serde(skip_serializing_if = "Option::is_none")] - example: Option<&'a str>, - - #[serde(skip_serializing_if = "Option::is_none")] - source: Option<&'a str>, - - values: HashMap<&'a str, &'a str>, - } - - let instance_name = file.path - .file_stem().expect("Could not extract file stem") - .to_str().expect("Could not convert path to UTF-8"); - - // Normally, we'd be able to let the csv crate construct our struct for us. - // - // However, because of a limitation with Serde's 'flatten' feature, it's not - // possible presently to losslessly collect extra string values while using - // csv+Serde. - // - // https://github.com/BurntSushi/rust-csv/issues/151 - let mut reader = csv::Reader::from_reader(file.contents.as_slice()); - - let headers = reader.headers() - .map_err(|inner| SnapshotError::CsvDecodeError { - inner, - path: file.path.to_path_buf(), - })? - .clone(); - - let mut records = Vec::new(); - - for record in reader.into_records() { - let record = record - .map_err(|inner| SnapshotError::CsvDecodeError { - inner, - path: file.path.to_path_buf(), - })?; - - records.push(record); - } - - let mut entries = Vec::new(); - - for record in &records { - let mut entry = LocalizationEntry::default(); - - for (header, value) in headers.iter().zip(record.into_iter()) { - if header.is_empty() || value.is_empty() { - continue; - } - - match header { - "Key" => entry.key = Some(value), - "Source" => entry.source = Some(value), - "Context" => entry.context = Some(value), - "Example" => entry.example = Some(value), - _ => { - entry.values.insert(header, value); - } - } - } - - if entry.key.is_none() && entry.source.is_none() { - continue; - } - - entries.push(entry); - } - - let table_contents = serde_json::to_string(&entries) - .expect("Could not encode JSON for localization table"); - - let mut snapshot = RbxSnapshotInstance { - name: Cow::Borrowed(instance_name), - class_name: Cow::Borrowed("LocalizationTable"), - properties: hashmap! { - "Contents".to_owned() => RbxValue::String { - value: table_contents, - }, - }, - children: Vec::new(), - metadata: MetadataPerInstance { - source_path: Some(file.path.to_path_buf()), - ignore_unknown_instances: false, - project_definition: None, - }, - }; - - if let Some(meta) = ExtraMetadata::locate(&imfs, &file.path)? { - meta.validate_for_non_init(&file.path)?; - meta.apply(&mut snapshot)?; - } - - Ok(Some(snapshot)) -} - -fn snapshot_json_model_file<'source>( - file: &'source ImfsFile, -) -> SnapshotResult<'source> { - let file_name = file.path - .file_name().expect("Could not extract file stem") - .to_str().expect("Could not convert path to UTF-8"); - - let instance_name = match_trailing(file_name, ".model.json") - .expect("JSON model file did not end in .model.json"); - - let contents = str::from_utf8(&file.contents) - .map_err(|inner| SnapshotError::Utf8Error { - inner, - path: file.path.to_owned(), - })?; - - let json_instance: JsonModel = serde_json::from_str(contents) - .map_err(|inner| SnapshotError::JsonModelDecodeError { - inner, - path: file.path.to_owned(), - })?; - - if let Some(json_name) = &json_instance.name { - if json_name != instance_name { - log::warn!("Name from JSON model did not match its file name: {}", file.path.display()); - log::warn!("In Rojo < alpha 14, this model is named \"{}\" (from its 'Name' property)", json_name); - log::warn!("In Rojo >= alpha 14, this model is named \"{}\" (from its file name)", instance_name); - log::warn!("'Name' for the top-level instance in a JSON model is now optional and will be ignored."); - } - } - - let mut snapshot = json_instance.core.into_snapshot(instance_name.to_owned())?; - - snapshot.name = Cow::Borrowed(instance_name); - snapshot.metadata.source_path = Some(file.path.to_owned()); - - Ok(Some(snapshot)) -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "PascalCase")] -struct JsonModel { - name: Option, - - #[serde(flatten)] - core: JsonModelCore, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "PascalCase")] -struct JsonModelInstance { - name: String, - - #[serde(flatten)] - core: JsonModelCore, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "PascalCase")] -struct JsonModelCore { - class_name: String, - - #[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")] - children: Vec, - - #[serde(default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")] - properties: HashMap, -} - -impl JsonModelCore { - fn into_snapshot(self, name: String) -> Result, SnapshotError> { - let mut children = Vec::with_capacity(self.children.len()); - - for child in self.children { - children.push(child.core.into_snapshot(child.name)?); - } - - let mut properties = HashMap::with_capacity(self.properties.len()); - - for (key, value) in self.properties { - let resolved_value = try_resolve_value(&self.class_name, &key, &value)?; - properties.insert(key, resolved_value); - } - - Ok(RbxSnapshotInstance { - name: Cow::Owned(name), - class_name: Cow::Owned(self.class_name), - properties, - children, - metadata: Default::default(), - }) - } -} - -fn snapshot_xml_model_file<'source>( - file: &'source ImfsFile, - imfs: &'source Imfs, -) -> SnapshotResult<'source> { - let instance_name = file.path - .file_stem().expect("Could not extract file stem") - .to_str().expect("Could not convert path to UTF-8"); - - let options = rbx_xml::DecodeOptions::new() - .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); - - let temp_tree = rbx_xml::from_reader(file.contents.as_slice(), options) - .map_err(|inner| SnapshotError::XmlModelDecodeError { - inner, - path: file.path.clone(), - })?; - - let root_instance = temp_tree.get_instance(temp_tree.get_root_id()).unwrap(); - let children = root_instance.get_children_ids(); - - match children.len() { - 0 => Ok(None), - 1 => { - let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); - snapshot.name = Cow::Borrowed(instance_name); - snapshot.metadata.source_path = Some(file.path.clone()); - - if let Some(meta) = ExtraMetadata::locate(&imfs, &file.path)? { - meta.validate_for_model(&file.path)?; - meta.apply(&mut snapshot)?; - } - - Ok(Some(snapshot)) - }, - _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), - } -} - -fn snapshot_binary_model_file<'source>( - file: &'source ImfsFile, - imfs: &'source Imfs, -) -> SnapshotResult<'source> { - let instance_name = file.path - .file_stem().expect("Could not extract file stem") - .to_str().expect("Could not convert path to UTF-8"); - - let mut temp_tree = RbxTree::new(RbxInstanceProperties { - name: "Temp".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), - }); - - let root_id = temp_tree.get_root_id(); - rbx_binary::decode(&mut temp_tree, root_id, file.contents.as_slice()) - .map_err(|inner| SnapshotError::BinaryModelDecodeError { - inner, - path: file.path.clone(), - })?; - - let root_instance = temp_tree.get_instance(root_id).unwrap(); - let children = root_instance.get_children_ids(); - - match children.len() { - 0 => Ok(None), - 1 => { - let mut snapshot = snapshot_from_tree(&temp_tree, children[0]).unwrap(); - snapshot.name = Cow::Borrowed(instance_name); - snapshot.metadata.source_path = Some(file.path.clone()); - - if let Some(meta) = ExtraMetadata::locate(&imfs, &file.path)? { - meta.validate_for_model(&file.path)?; - meta.apply(&mut snapshot)?; - } - - Ok(Some(snapshot)) - }, - _ => panic!("Rojo doesn't have support for model files with multiple roots yet"), - } -} \ No newline at end of file diff --git a/server/src/serve_session.rs b/server/src/serve_session.rs new file mode 100644 index 00000000..6f909e1d --- /dev/null +++ b/server/src/serve_session.rs @@ -0,0 +1,33 @@ +use std::collections::HashSet; + +use crate::{ + project::Project, + session_id::SessionId, +}; + +/// Contains all of the state for a Rojo serve session. +pub struct ServeSession { + root_project: Option, + session_id: SessionId, +} + +impl ServeSession { + pub fn new(root_project: Option) -> ServeSession { + let session_id = SessionId::new(); + + ServeSession { + session_id, + root_project, + } + } + + pub fn session_id(&self) -> SessionId { + self.session_id + } + + pub fn serve_place_ids(&self) -> Option<&HashSet> { + self.root_project + .as_ref() + .and_then(|project| project.serve_place_ids.as_ref()) + } +} \ No newline at end of file diff --git a/server/src/snapshot/instance_snapshot.rs b/server/src/snapshot/instance_snapshot.rs new file mode 100644 index 00000000..a7e1f7cb --- /dev/null +++ b/server/src/snapshot/instance_snapshot.rs @@ -0,0 +1,62 @@ +//! Defines the structure of an instance snapshot. + +use std::{ + borrow::Cow, + collections::HashMap, +}; + +use rbx_dom_weak::{RbxTree, RbxId, RbxValue}; + +/// A lightweight description of what an instance should look like. Attempts to +/// be somewhat memory efficient by borrowing from its source data, indicated by +/// the lifetime parameter, `'source`. +/// +// Possible future improvements: +// - Use refcounted/interned strings +// - Replace use of RbxValue with a sum of RbxValue + borrowed value +#[derive(Debug, Clone, PartialEq)] +pub struct InstanceSnapshot<'source> { + pub snapshot_id: Option, + + pub name: Cow<'source, str>, + pub class_name: Cow<'source, str>, + pub properties: HashMap, + pub children: Vec>, + + // TODO: Snapshot source, like a file or a project node? +} + +impl<'source> InstanceSnapshot<'source> { + pub fn get_owned(&'source self) -> InstanceSnapshot<'static> { + let children: Vec> = self.children.iter() + .map(InstanceSnapshot::get_owned) + .collect(); + + InstanceSnapshot { + snapshot_id: None, + name: Cow::Owned(self.name.clone().into_owned()), + class_name: Cow::Owned(self.class_name.clone().into_owned()), + properties: self.properties.clone(), + children, + } + } + + pub fn from_tree(tree: &RbxTree, id: RbxId) -> InstanceSnapshot<'static> { + let instance = tree.get_instance(id) + .expect("instance did not exist in tree"); + + let children = instance.get_children_ids() + .iter() + .cloned() + .map(|id| InstanceSnapshot::from_tree(tree, id)) + .collect(); + + InstanceSnapshot { + snapshot_id: Some(id), + name: Cow::Owned(instance.name.clone()), + class_name: Cow::Owned(instance.class_name.clone()), + properties: instance.properties.clone(), + children, + } + } +} \ No newline at end of file diff --git a/server/src/snapshot/mod.rs b/server/src/snapshot/mod.rs new file mode 100644 index 00000000..b83dd771 --- /dev/null +++ b/server/src/snapshot/mod.rs @@ -0,0 +1,29 @@ +//! This module defines the instance snapshot subsystem of Rojo. +//! +//! It defines a way to define the instance tree of a project as a pure function +//! of the filesystem by providing a lightweight instance 'snapshot' type, a +//! method to generate minimal patches, and a method that applies those patches. +//! +//! The aim with this approach is to reduce the number of bugs that arise from +//! attempting to manually update instances in response to filesystem updates. +//! Instead of surgically identifying what needs to change, we can do rough +//! "damage-painting", running our relatively fast snapshot function over +//! anything that could have changed and running it through a diffing function +//! to minimize the set of real changes. +//! +//! Building out a snapshot reconciler is mostly overkill for scripts, since +//! their relationships are mostly simple and well-defined. It becomes very +//! important, however, when dealing with large opaque model files and +//! user-defined plugins. + +#![allow(dead_code)] + +mod patch; +mod patch_apply; +mod patch_compute; +mod instance_snapshot; + +pub use instance_snapshot::InstanceSnapshot; +pub use patch_apply::apply_patch_set; +pub use patch_compute::compute_patch_set; +pub use patch::*; \ No newline at end of file diff --git a/server/src/snapshot/patch.rs b/server/src/snapshot/patch.rs new file mode 100644 index 00000000..4dcb6a6b --- /dev/null +++ b/server/src/snapshot/patch.rs @@ -0,0 +1,44 @@ +//! Defines the data structures used for describing instance patches. + +use std::collections::HashMap; + +use rbx_dom_weak::{RbxValue, RbxId}; + +use super::InstanceSnapshot; + +/// A set of different kinds of patches that can be applied to an RbxTree. +#[derive(Debug, Default, Clone, PartialEq)] +pub struct PatchSet<'a> { + pub removed_instances: Vec, + pub added_instances: Vec>, + pub updated_instances: Vec, +} + +impl<'a> PatchSet<'a> { + pub fn new() -> PatchSet<'a> { + PatchSet { + removed_instances: Vec::new(), + added_instances: Vec::new(), + updated_instances: Vec::new(), + } + } +} + +/// A patch containing an instance that was added to the tree. +#[derive(Debug, Clone, PartialEq)] +pub struct PatchAddInstance<'a> { + pub parent_id: RbxId, + pub instance: InstanceSnapshot<'a>, +} + +/// A patch indicating that properties (or the name) of an instance changed. +#[derive(Debug, Clone, PartialEq)] +pub struct PatchUpdateInstance { + pub id: RbxId, + pub changed_name: Option, + pub changed_class_name: Option, + + /// Contains all changed properties. If a property is assigned to `None`, + /// then that property has been removed. + pub changed_properties: HashMap>, +} \ No newline at end of file diff --git a/server/src/snapshot/patch_apply.rs b/server/src/snapshot/patch_apply.rs new file mode 100644 index 00000000..b21a8fb6 --- /dev/null +++ b/server/src/snapshot/patch_apply.rs @@ -0,0 +1,239 @@ +//! Defines the algorithm for applying generated patches. + +use std::collections::HashMap; + +use rbx_dom_weak::{RbxTree, RbxValue, RbxId, RbxInstanceProperties}; + +use super::{ + patch::{PatchSet, PatchUpdateInstance}, + InstanceSnapshot, +}; + +pub fn apply_patch_set( + tree: &mut RbxTree, + patch_set: &PatchSet, +) { + let mut context = PatchApplyContext::default(); + + for removed_id in &patch_set.removed_instances { + tree.remove_instance(*removed_id); + } + + for add_patch in &patch_set.added_instances { + apply_add_child(&mut context, tree, add_patch.parent_id, &add_patch.instance); + } + + for update_patch in &patch_set.updated_instances { + apply_update_child(&context, tree, update_patch); + } + + apply_deferred_properties(context, tree); +} + +#[derive(Default)] +struct PatchApplyContext { + snapshot_id_to_instance_id: HashMap, + properties_to_apply: HashMap>, +} + +/// Apply properties that were deferred in order to get more information. +/// +/// Ref properties from snapshots refer to eachother via snapshot ID. Some of +/// these properties are transformed when the patch is computed, notably the +/// instances that the patch computing method is able to pair up. +/// +/// The remaining Ref properties need to be handled during patch application, +/// where we build up a map of snapshot IDs to instance IDs as they're created, +/// then apply properties all at once at the end. +fn apply_deferred_properties(context: PatchApplyContext, tree: &mut RbxTree) { + for (id, mut properties) in context.properties_to_apply { + let instance = tree.get_instance_mut(id) + .expect("Invalid instance ID in deferred property map"); + + for property_value in properties.values_mut() { + if let RbxValue::Ref { value: Some(id) } = property_value { + if let Some(&instance_id) = context.snapshot_id_to_instance_id.get(id) { + *property_value = RbxValue::Ref { value: Some(instance_id) }; + } + } + } + + instance.properties = properties; + } +} + +fn apply_add_child( + context: &mut PatchApplyContext, + tree: &mut RbxTree, + parent_id: RbxId, + snapshot: &InstanceSnapshot, +) { + let properties = RbxInstanceProperties { + name: snapshot.name.clone().into_owned(), + class_name: snapshot.class_name.clone().into_owned(), + + // Property assignment is deferred until after we know about all + // instances in this patch. + properties: HashMap::new(), + }; + + let id = tree.insert_instance(properties, parent_id); + + context.properties_to_apply.insert(id, snapshot.properties.clone()); + + if let Some(snapshot_id) = snapshot.snapshot_id { + context.snapshot_id_to_instance_id.insert(snapshot_id, id); + } + + for child_snapshot in &snapshot.children { + apply_add_child(context, tree, id, child_snapshot); + } +} + +fn apply_update_child( + context: &PatchApplyContext, + tree: &mut RbxTree, + patch: &PatchUpdateInstance, +) { + let instance = tree.get_instance_mut(patch.id) + .expect("Instance referred to by patch does not exist"); + + if let Some(name) = &patch.changed_name { + instance.name = name.clone(); + } + + if let Some(class_name) = &patch.changed_class_name { + instance.class_name = class_name.clone(); + } + + for (key, property_entry) in &patch.changed_properties { + match property_entry { + // Ref values need to be potentially rewritten from snapshot IDs to + // instance IDs if they referred to an instance that was created as + // part of this patch. + Some(RbxValue::Ref { value: Some(id) }) => { + let new_id = context.snapshot_id_to_instance_id.get(id).unwrap_or(id); + + instance.properties.insert(key.clone(), RbxValue::Ref { + value: Some(*new_id), + }); + } + Some(value) => { + instance.properties.insert(key.clone(), value.clone()); + } + None => { + instance.properties.remove(key); + } + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + use std::{ + borrow::Cow, + collections::HashMap, + }; + + use maplit::hashmap; + use rbx_dom_weak::RbxValue; + + use super::super::patch::PatchAddInstance; + + #[test] + fn add_from_empty() { + let _ = env_logger::try_init(); + + let mut tree = RbxTree::new(RbxInstanceProperties { + name: "Folder".to_owned(), + class_name: "Folder".to_owned(), + properties: HashMap::new(), + }); + + let root_id = tree.get_root_id(); + + let snapshot = InstanceSnapshot { + snapshot_id: None, + name: Cow::Borrowed("Foo"), + class_name: Cow::Borrowed("Bar"), + properties: hashmap! { + "Baz".to_owned() => RbxValue::Int32 { value: 5 }, + }, + children: Vec::new(), + }; + + let patch_set = PatchSet { + added_instances: vec![ + PatchAddInstance { + parent_id: root_id, + instance: snapshot.clone(), + } + ], + ..Default::default() + }; + + apply_patch_set(&mut tree, &patch_set); + + let root_instance = tree.get_instance(root_id).unwrap(); + let child_id = root_instance.get_children_ids()[0]; + let child_instance = tree.get_instance(child_id).unwrap(); + + assert_eq!(child_instance.name.as_str(), &snapshot.name); + assert_eq!(child_instance.class_name.as_str(), &snapshot.class_name); + assert_eq!(&child_instance.properties, &snapshot.properties); + assert!(child_instance.get_children_ids().is_empty()); + } + + #[test] + fn update_existing() { + let _ = env_logger::try_init(); + + let mut tree = RbxTree::new(RbxInstanceProperties { + name: "OldName".to_owned(), + class_name: "OldClassName".to_owned(), + properties: hashmap! { + "Foo".to_owned() => RbxValue::Int32 { value: 7 }, + "Bar".to_owned() => RbxValue::Int32 { value: 3 }, + "Unchanged".to_owned() => RbxValue::Int32 { value: -5 }, + }, + }); + + let root_id = tree.get_root_id(); + + let patch = PatchUpdateInstance { + id: root_id, + changed_name: Some("Foo".to_owned()), + changed_class_name: Some("NewClassName".to_owned()), + changed_properties: hashmap! { + // The value of Foo has changed + "Foo".to_owned() => Some(RbxValue::Int32 { value: 8 }), + + // Bar has been deleted + "Bar".to_owned() => None, + + // Baz has been added + "Baz".to_owned() => Some(RbxValue::Int32 { value: 10 }), + }, + }; + + let patch_set = PatchSet { + updated_instances: vec![patch], + ..Default::default() + }; + + apply_patch_set(&mut tree, &patch_set); + + let expected_properties = hashmap! { + "Foo".to_owned() => RbxValue::Int32 { value: 8 }, + "Baz".to_owned() => RbxValue::Int32 { value: 10 }, + "Unchanged".to_owned() => RbxValue::Int32 { value: -5 }, + }; + + let root_instance = tree.get_instance(root_id).unwrap(); + assert_eq!(root_instance.name, "Foo"); + assert_eq!(root_instance.class_name, "NewClassName"); + assert_eq!(root_instance.properties, expected_properties); + } +} \ No newline at end of file diff --git a/server/src/snapshot/patch_compute.rs b/server/src/snapshot/patch_compute.rs new file mode 100644 index 00000000..78ed2769 --- /dev/null +++ b/server/src/snapshot/patch_compute.rs @@ -0,0 +1,322 @@ +//! Defines the algorithm for computing a roughly-minimal patch set given an +//! existing instance tree and an instance snapshot. + +use std::collections::{HashMap, HashSet}; + +use rbx_dom_weak::{RbxTree, RbxValue, RbxId, RbxInstance}; + +use super::{ + InstanceSnapshot, + patch::{PatchSet, PatchAddInstance, PatchUpdateInstance}, +}; + +pub fn compute_patch_set<'a>( + snapshot: &'a InstanceSnapshot, + tree: &RbxTree, + id: RbxId, +) -> PatchSet<'a> { + let mut patch_set = PatchSet::new(); + let mut context = ComputePatchContext::default(); + + compute_patch_set_internal(&mut context, snapshot, tree, id, &mut patch_set); + + // Rewrite Ref properties to refer to instance IDs instead of snapshot IDs + // for all of the IDs that we know about so far. + rewrite_refs_in_updates(&context, &mut patch_set.updated_instances); + rewrite_refs_in_additions(&context, &mut patch_set.added_instances); + + patch_set +} + +#[derive(Default)] +struct ComputePatchContext { + snapshot_id_to_instance_id: HashMap, +} + +fn rewrite_refs_in_updates(context: &ComputePatchContext, updates: &mut [PatchUpdateInstance]) { + for update in updates { + for property_value in update.changed_properties.values_mut() { + if let Some(RbxValue::Ref { value: Some(id) }) = property_value { + if let Some(&instance_id) = context.snapshot_id_to_instance_id.get(id) { + *property_value = Some(RbxValue::Ref { value: Some(instance_id) }); + } + } + } + } +} + +fn rewrite_refs_in_additions(context: &ComputePatchContext, additions: &mut [PatchAddInstance]) { + for addition in additions { + rewrite_refs_in_snapshot(context, &mut addition.instance); + } +} + +fn rewrite_refs_in_snapshot(context: &ComputePatchContext, snapshot: &mut InstanceSnapshot) { + for property_value in snapshot.properties.values_mut() { + if let RbxValue::Ref { value: Some(id) } = property_value { + if let Some(&instance_id) = context.snapshot_id_to_instance_id.get(id) { + *property_value = RbxValue::Ref { value: Some(instance_id) }; + } + } + } + + for child in &mut snapshot.children { + rewrite_refs_in_snapshot(context, child); + } +} + +fn compute_patch_set_internal<'a>( + context: &mut ComputePatchContext, + snapshot: &'a InstanceSnapshot, + tree: &RbxTree, + id: RbxId, + patch_set: &mut PatchSet<'a>, +) { + if let Some(snapshot_id) = snapshot.snapshot_id { + context.snapshot_id_to_instance_id.insert(snapshot_id, id); + } + + let instance = tree.get_instance(id) + .expect("Instance did not exist in tree"); + + compute_property_patches(snapshot, instance, patch_set); + compute_children_patches(context, snapshot, tree, id, patch_set); +} + +fn compute_property_patches( + snapshot: &InstanceSnapshot, + instance: &RbxInstance, + patch_set: &mut PatchSet, +) { + let mut visited_properties = HashSet::new(); + let mut changed_properties = HashMap::new(); + + let changed_name = if snapshot.name == instance.name { + None + } else { + Some(snapshot.name.clone().into_owned()) + }; + + let changed_class_name = if snapshot.class_name == instance.class_name { + None + } else { + Some(snapshot.class_name.clone().into_owned()) + }; + + for (name, snapshot_value) in &snapshot.properties { + visited_properties.insert(name.as_str()); + + match instance.properties.get(name) { + Some(instance_value) => { + if snapshot_value != instance_value { + changed_properties.insert(name.clone(), Some(snapshot_value.clone())); + } + } + None => { + changed_properties.insert(name.clone(), Some(snapshot_value.clone())); + } + } + } + + for name in instance.properties.keys() { + if visited_properties.contains(name.as_str()) { + continue; + } + + changed_properties.insert(name.clone(), None); + } + + if changed_properties.is_empty() && changed_name.is_none() { + return; + } + + patch_set.updated_instances.push(PatchUpdateInstance { + id: instance.get_id(), + changed_name, + changed_class_name, + changed_properties, + }); +} + +fn compute_children_patches<'a>( + context: &mut ComputePatchContext, + snapshot: &'a InstanceSnapshot, + tree: &RbxTree, + id: RbxId, + patch_set: &mut PatchSet<'a>, +) { + let instance = tree.get_instance(id) + .expect("Instance did not exist in tree"); + + let instance_children = instance.get_children_ids(); + + let mut paired_instances = vec![false; instance_children.len()]; + + for snapshot_child in snapshot.children.iter() { + let matching_instance = instance_children + .iter() + .enumerate() + .find(|(instance_index, instance_child_id)| { + if paired_instances[*instance_index] { + return false; + } + + let instance_child = tree.get_instance(**instance_child_id) + .expect("Instance did not exist in tree"); + + if snapshot_child.name == instance_child.name && + instance_child.class_name == instance_child.class_name + { + paired_instances[*instance_index] = true; + return true; + } + + false + }); + + match matching_instance { + Some((_, instance_child_id)) => { + compute_patch_set_internal(context, snapshot_child, tree, *instance_child_id, patch_set); + } + None => { + patch_set.added_instances.push(PatchAddInstance { + parent_id: id, + instance: snapshot_child.clone(), + }); + } + } + } + + for (instance_index, instance_child_id) in instance_children.iter().enumerate() { + if paired_instances[instance_index] { + continue; + } + + patch_set.removed_instances.push(*instance_child_id); + } +} + +#[cfg(test)] +mod test { + use super::*; + + use std::borrow::Cow; + + use maplit::hashmap; + use rbx_dom_weak::RbxInstanceProperties; + + /// This test makes sure that rewriting refs in instance update patches to + /// instances that already exists works. We should be able to correlate the + /// snapshot ID and instance ID during patch computation and replace the + /// value before returning from compute_patch_set. + #[test] + fn rewrite_ref_existing_instance_update() { + let tree = RbxTree::new(RbxInstanceProperties { + name: "foo".to_owned(), + class_name: "foo".to_owned(), + properties: HashMap::new(), + }); + + let root_id = tree.get_root_id(); + + // This snapshot should be identical to the existing tree except for the + // addition of a prop named Self, which is a self-referential Ref. + let snapshot_id = RbxId::new(); + let snapshot = InstanceSnapshot { + snapshot_id: Some(snapshot_id), + properties: hashmap! { + "Self".to_owned() => RbxValue::Ref { + value: Some(snapshot_id), + } + }, + + name: Cow::Borrowed("foo"), + class_name: Cow::Borrowed("foo"), + children: Vec::new(), + }; + + let patch_set = compute_patch_set(&snapshot, &tree, root_id); + + let expected_patch_set = PatchSet { + updated_instances: vec![ + PatchUpdateInstance { + id: root_id, + changed_name: None, + changed_class_name: None, + changed_properties: hashmap! { + "Self".to_owned() => Some(RbxValue::Ref { + value: Some(root_id), + }), + }, + }, + ], + added_instances: Vec::new(), + removed_instances: Vec::new(), + }; + + assert_eq!(patch_set, expected_patch_set); + } + + /// The same as rewrite_ref_existing_instance_update, except that the + /// property is added in a new instance instead of modifying an existing + /// one. + #[test] + fn rewrite_ref_existing_instance_addition() { + let tree = RbxTree::new(RbxInstanceProperties { + name: "foo".to_owned(), + class_name: "foo".to_owned(), + properties: HashMap::new(), + }); + + let root_id = tree.get_root_id(); + + // This patch describes the existing instance with a new child added. + let snapshot_id = RbxId::new(); + let snapshot = InstanceSnapshot { + snapshot_id: Some(snapshot_id), + children: vec![ + InstanceSnapshot { + properties: hashmap! { + "Self".to_owned() => RbxValue::Ref { + value: Some(snapshot_id), + }, + }, + + snapshot_id: None, + name: Cow::Borrowed("child"), + class_name: Cow::Borrowed("child"), + children: Vec::new(), + } + ], + + properties: HashMap::new(), + name: Cow::Borrowed("foo"), + class_name: Cow::Borrowed("foo"), + }; + + let patch_set = compute_patch_set(&snapshot, &tree, root_id); + + let expected_patch_set = PatchSet { + added_instances: vec![ + PatchAddInstance { + parent_id: root_id, + instance: InstanceSnapshot { + snapshot_id: None, + properties: hashmap! { + "Self".to_owned() => RbxValue::Ref { + value: Some(root_id), + }, + }, + name: Cow::Borrowed("child"), + class_name: Cow::Borrowed("child"), + children: Vec::new(), + }, + }, + ], + updated_instances: Vec::new(), + removed_instances: Vec::new(), + }; + + assert_eq!(patch_set, expected_patch_set); + } +} \ No newline at end of file diff --git a/server/src/snapshot_middleware/context.rs b/server/src/snapshot_middleware/context.rs new file mode 100644 index 00000000..7dfc9c6c --- /dev/null +++ b/server/src/snapshot_middleware/context.rs @@ -0,0 +1,7 @@ +pub struct InstanceSnapshotContext { + /// Empty struct that will be used later to fill out required Lua state for + /// user plugins. + pub plugin_context: Option<()>, +} + +pub struct ImfsSnapshotContext; \ No newline at end of file diff --git a/server/src/snapshot_middleware/csv.rs b/server/src/snapshot_middleware/csv.rs new file mode 100644 index 00000000..a211d466 --- /dev/null +++ b/server/src/snapshot_middleware/csv.rs @@ -0,0 +1,174 @@ +use std::{ + borrow::Cow, + collections::BTreeMap, +}; + +use maplit::hashmap; +use rbx_dom_weak::{RbxTree, RbxValue, RbxId}; +use serde::Serialize; + +use crate::{ + imfs::new::{Imfs, ImfsFetcher, ImfsEntry}, + snapshot::InstanceSnapshot, +}; + +use super::{ + middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, +}; + +pub struct SnapshotCsv; + +impl SnapshotMiddleware for SnapshotCsv { + fn from_imfs( + imfs: &mut Imfs, + entry: &ImfsEntry, + ) -> SnapshotInstanceResult<'static> { + if entry.is_directory() { + return Ok(None); + } + + let file_name = entry.path() + .file_name().unwrap().to_string_lossy(); + + if !file_name.ends_with(".csv") { + return Ok(None); + } + + let instance_name = entry.path() + .file_stem().expect("Could not extract file stem") + .to_string_lossy().to_string(); + + let table_contents = convert_localization_csv(entry.contents(imfs)?); + + Ok(Some(InstanceSnapshot { + snapshot_id: None, + name: Cow::Owned(instance_name), + class_name: Cow::Borrowed("LocalizationTable"), + properties: hashmap! { + "Contents".to_owned() => RbxValue::String { + value: table_contents, + }, + }, + children: Vec::new(), + })) + } + + fn from_instance( + _tree: &RbxTree, + _id: RbxId, + ) -> SnapshotFileResult { + unimplemented!("Snapshotting CSV localization tables"); + } +} + +/// Struct that holds any valid row from a Roblox CSV translation table. +/// +/// We manually deserialize into this table from CSV, but let serde_json handle +/// serialization. +#[derive(Debug, Default, Serialize)] +#[serde(rename_all = "camelCase")] +struct LocalizationEntry<'a> { + #[serde(skip_serializing_if = "Option::is_none")] + key: Option<&'a str>, + + #[serde(skip_serializing_if = "Option::is_none")] + context: Option<&'a str>, + + #[serde(skip_serializing_if = "Option::is_none")] + example: Option<&'a str>, + + #[serde(skip_serializing_if = "Option::is_none")] + source: Option<&'a str>, + + // We use a BTreeMap here to get deterministic output order. + values: BTreeMap<&'a str, &'a str>, +} + +/// Normally, we'd be able to let the csv crate construct our struct for us. +/// +/// However, because of a limitation with Serde's 'flatten' feature, it's not +/// possible presently to losslessly collect extra string values while using +/// csv+Serde. +/// +/// https://github.com/BurntSushi/rust-csv/issues/151 +/// +/// This function operates in one step in order to minimize data-copying. +fn convert_localization_csv(contents: &[u8]) -> String { + let mut reader = csv::Reader::from_reader(contents); + + let headers = reader.headers() + .expect("TODO: Handle csv errors") + .clone(); + + let mut records = Vec::new(); + + for record in reader.into_records() { + let record = record + .expect("TODO: Handle csv errors"); + + records.push(record); + } + + let mut entries = Vec::new(); + + for record in &records { + let mut entry = LocalizationEntry::default(); + + for (header, value) in headers.iter().zip(record.into_iter()) { + if header.is_empty() || value.is_empty() { + continue; + } + + match header { + "Key" => entry.key = Some(value), + "Source" => entry.source = Some(value), + "Context" => entry.context = Some(value), + "Example" => entry.example = Some(value), + _ => { + entry.values.insert(header, value); + } + } + } + + if entry.key.is_none() && entry.source.is_none() { + continue; + } + + entries.push(entry); + } + + serde_json::to_string(&entries) + .expect("Could not encode JSON for localization table") +} + +#[cfg(test)] +mod test { + use super::*; + + use crate::imfs::new::{ImfsSnapshot, NoopFetcher}; + + #[test] + fn csv_from_imfs() { + let mut imfs = Imfs::new(NoopFetcher); + let file = ImfsSnapshot::file(r#" +Key,Source,Context,Example,es +Ack,Ack!,,An exclamation of despair,¡Ay!"#); + + imfs.load_from_snapshot("/foo.csv", file); + + let entry = imfs.get("/foo.csv").unwrap(); + let instance_snapshot = SnapshotCsv::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + let expected_contents = + r#"[{"key":"Ack","example":"An exclamation of despair","source":"Ack!","values":{"es":"¡Ay!"}}]"#; + + assert_eq!(instance_snapshot.name, "foo"); + assert_eq!(instance_snapshot.class_name, "LocalizationTable"); + assert_eq!(instance_snapshot.children, Vec::new()); + assert_eq!(instance_snapshot.properties, hashmap! { + "Contents".to_owned() => RbxValue::String { + value: expected_contents.to_owned(), + }, + }); + } +} \ No newline at end of file diff --git a/server/src/snapshot_middleware/dir.rs b/server/src/snapshot_middleware/dir.rs new file mode 100644 index 00000000..3708abb2 --- /dev/null +++ b/server/src/snapshot_middleware/dir.rs @@ -0,0 +1,126 @@ +use std::{ + borrow::Cow, + collections::HashMap, +}; + +use rbx_dom_weak::{RbxTree, RbxId}; + +use crate::{ + imfs::new::{Imfs, ImfsSnapshot, DirectorySnapshot, ImfsFetcher, ImfsEntry}, + snapshot::InstanceSnapshot, +}; + +use super::{ + snapshot_from_imfs, + snapshot_from_instance, + middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, +}; + +pub struct SnapshotDir; + +impl SnapshotMiddleware for SnapshotDir { + fn from_imfs( + imfs: &mut Imfs, + entry: &ImfsEntry, + ) -> SnapshotInstanceResult<'static> { + if entry.is_file() { + return Ok(None); + } + + let children: Vec = entry.children(imfs)?; + + let mut snapshot_children = Vec::new(); + + for child in children.into_iter() { + if let Some(child_snapshot) = snapshot_from_imfs(imfs, &child)? { + snapshot_children.push(child_snapshot); + } + } + + let instance_name = entry.path() + .file_name().expect("Could not extract file name") + .to_str().unwrap().to_string(); + + Ok(Some(InstanceSnapshot { + snapshot_id: None, + name: Cow::Owned(instance_name), + class_name: Cow::Borrowed("Folder"), + properties: HashMap::new(), + children: snapshot_children, + })) + } + + fn from_instance( + tree: &RbxTree, + id: RbxId, + ) -> SnapshotFileResult { + let instance = tree.get_instance(id).unwrap(); + + if instance.class_name != "Folder" { + return None; + } + + let mut children = HashMap::new(); + + for child_id in instance.get_children_ids() { + if let Some((name, child)) = snapshot_from_instance(tree, *child_id) { + children.insert(name, child); + } + } + + let snapshot = ImfsSnapshot::Directory(DirectorySnapshot { + children, + }); + + Some((instance.name.clone(), snapshot)) + } +} + +#[cfg(test)] +mod test { + use super::*; + + use maplit::hashmap; + + use crate::imfs::new::NoopFetcher; + + #[test] + fn empty_folder() { + let mut imfs = Imfs::new(NoopFetcher); + let dir = ImfsSnapshot::dir::(HashMap::new()); + + imfs.load_from_snapshot("/foo", dir); + + let entry = imfs.get("/foo").unwrap(); + let instance_snapshot = SnapshotDir::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + assert_eq!(instance_snapshot.name, "foo"); + assert_eq!(instance_snapshot.class_name, "Folder"); + assert_eq!(instance_snapshot.properties, HashMap::new()); + assert_eq!(instance_snapshot.children, Vec::new()); + } + + #[test] + fn folder_in_folder() { + let mut imfs = Imfs::new(NoopFetcher); + let dir = ImfsSnapshot::dir(hashmap! { + "Child" => ImfsSnapshot::dir::(HashMap::new()), + }); + + imfs.load_from_snapshot("/foo", dir); + + let entry = imfs.get("/foo").unwrap(); + let instance_snapshot = SnapshotDir::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + assert_eq!(instance_snapshot.name, "foo"); + assert_eq!(instance_snapshot.class_name, "Folder"); + assert_eq!(instance_snapshot.properties, HashMap::new()); + assert_eq!(instance_snapshot.children.len(), 1); + + let child = &instance_snapshot.children[0]; + assert_eq!(child.name, "Child"); + assert_eq!(child.class_name, "Folder"); + assert_eq!(child.properties, HashMap::new()); + assert_eq!(child.children, Vec::new()); + } +} \ No newline at end of file diff --git a/server/src/snapshot_middleware/error.rs b/server/src/snapshot_middleware/error.rs new file mode 100644 index 00000000..263d89b0 --- /dev/null +++ b/server/src/snapshot_middleware/error.rs @@ -0,0 +1,99 @@ +use std::{ + fmt, + error::Error, + path::PathBuf, +}; + +use crate::{ + snapshot::InstanceSnapshot, +}; + +pub type SnapshotResult<'a> = Result>, SnapshotError>; + +#[derive(Debug)] +pub struct SnapshotError { + detail: SnapshotErrorDetail, + path: Option, +} + +impl SnapshotError { + pub fn new(detail: SnapshotErrorDetail, path: Option>) -> Self { + SnapshotError { + detail, + path: path.map(Into::into), + } + } + + pub(crate) fn file_did_not_exist(path: impl Into) -> SnapshotError { + SnapshotError { + detail: SnapshotErrorDetail::FileDidNotExist, + path: Some(path.into()), + } + } + + pub(crate) fn file_name_bad_unicode(path: impl Into) -> SnapshotError { + SnapshotError { + detail: SnapshotErrorDetail::FileNameBadUnicode, + path: Some(path.into()), + } + } + + pub(crate) fn file_contents_bad_unicode( + inner: std::str::Utf8Error, + path: impl Into, + ) -> SnapshotError { + SnapshotError { + detail: SnapshotErrorDetail::FileContentsBadUnicode { + inner, + }, + path: Some(path.into()), + } + } +} + +impl Error for SnapshotError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + self.detail.source() + } +} + +impl fmt::Display for SnapshotError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + match &self.path { + Some(path) => write!(formatter, "{} in path {}", self.detail, path.display()), + None => write!(formatter, "{}", self.detail), + } + } +} + +#[derive(Debug)] +pub enum SnapshotErrorDetail { + FileDidNotExist, + FileNameBadUnicode, + FileContentsBadUnicode { + inner: std::str::Utf8Error, + }, +} + +impl SnapshotErrorDetail { + fn source(&self) -> Option<&(dyn Error + 'static)> { + use self::SnapshotErrorDetail::*; + + match self { + FileContentsBadUnicode { inner } => Some(inner), + _ => None + } + } +} + +impl fmt::Display for SnapshotErrorDetail { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + use self::SnapshotErrorDetail::*; + + match self { + FileDidNotExist => write!(formatter, "file did not exist"), + FileNameBadUnicode => write!(formatter, "file name had malformed Unicode"), + FileContentsBadUnicode { inner } => write!(formatter, "file had malformed unicode: {}", inner), + } + } +} \ No newline at end of file diff --git a/server/src/snapshot_middleware/json_model.rs b/server/src/snapshot_middleware/json_model.rs new file mode 100644 index 00000000..b7744d5b --- /dev/null +++ b/server/src/snapshot_middleware/json_model.rs @@ -0,0 +1,181 @@ +use std::{ + borrow::Cow, + collections::HashMap, +}; + +use rbx_reflection::try_resolve_value; +use rbx_dom_weak::{RbxTree, RbxId, UnresolvedRbxValue}; +use serde::{Deserialize}; + +use crate::{ + imfs::new::{Imfs, ImfsFetcher, ImfsEntry}, + snapshot::InstanceSnapshot, +}; + +use super::{ + middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, +}; + +pub struct SnapshotJsonModel; + +impl SnapshotMiddleware for SnapshotJsonModel { + fn from_imfs( + imfs: &mut Imfs, + entry: &ImfsEntry, + ) -> SnapshotInstanceResult<'static> { + if entry.is_directory() { + return Ok(None); + } + + let file_name = entry.path() + .file_name().unwrap().to_string_lossy(); + + let instance_name = match match_trailing(&file_name, ".model.json") { + Some(name) => name.to_owned(), + None => return Ok(None), + }; + + let instance: JsonModel = serde_json::from_slice(entry.contents(imfs)?) + .expect("TODO: Handle serde_json errors"); + + if let Some(json_name) = &instance.name { + if json_name != &instance_name { + log::warn!("Name from JSON model did not match its file name: {}", entry.path().display()); + log::warn!("In Rojo < alpha 14, this model is named \"{}\" (from its 'Name' property)", json_name); + log::warn!("In Rojo >= alpha 14, this model is named \"{}\" (from its file name)", instance_name); + log::warn!("'Name' for the top-level instance in a JSON model is now optional and will be ignored."); + } + } + + let snapshot = instance.core.into_snapshot(instance_name); + + Ok(Some(snapshot)) + } + + fn from_instance( + _tree: &RbxTree, + _id: RbxId, + ) -> SnapshotFileResult { + unimplemented!("Snapshotting models"); + } +} + +fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { + if input.ends_with(trailer) { + let end = input.len().saturating_sub(trailer.len()); + Some(&input[..end]) + } else { + None + } +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "PascalCase")] +struct JsonModel { + name: Option, + + #[serde(flatten)] + core: JsonModelCore, +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "PascalCase")] +struct JsonModelInstance { + name: String, + + #[serde(flatten)] + core: JsonModelCore, +} + +#[derive(Debug, Deserialize)] +#[serde(rename_all = "PascalCase")] +struct JsonModelCore { + class_name: String, + + #[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")] + children: Vec, + + #[serde(default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")] + properties: HashMap, +} + +impl JsonModelCore { + fn into_snapshot(self, name: String) -> InstanceSnapshot<'static> { + let class_name = self.class_name; + + let children = self.children.into_iter() + .map(|child| child.core.into_snapshot(child.name)) + .collect(); + + let properties = self.properties.into_iter() + .map(|(key, value)| { + try_resolve_value(&class_name, &key, &value) + .map(|resolved| (key, resolved)) + }) + .collect::, _>>() + .expect("TODO: Handle rbx_reflection errors"); + + InstanceSnapshot { + snapshot_id: None, + name: Cow::Owned(name), + class_name: Cow::Owned(class_name), + properties, + children, + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + use maplit::hashmap; + use rbx_dom_weak::RbxValue; + + use crate::imfs::new::{ImfsSnapshot, NoopFetcher}; + + #[test] + fn model_from_imfs() { + let mut imfs = Imfs::new(NoopFetcher); + let file = ImfsSnapshot::file(r#" + { + "Name": "children", + "ClassName": "IntValue", + "Properties": { + "Value": 5 + }, + "Children": [ + { + "Name": "The Child", + "ClassName": "StringValue" + } + ] + } + "#); + + imfs.load_from_snapshot("/foo.model.json", file); + + let entry = imfs.get("/foo.model.json").unwrap(); + let instance_snapshot = SnapshotJsonModel::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + assert_eq!(instance_snapshot, InstanceSnapshot { + snapshot_id: None, + name: Cow::Borrowed("foo"), + class_name: Cow::Borrowed("IntValue"), + properties: hashmap! { + "Value".to_owned() => RbxValue::Int32 { + value: 5, + }, + }, + children: vec![ + InstanceSnapshot { + snapshot_id: None, + name: Cow::Borrowed("The Child"), + class_name: Cow::Borrowed("StringValue"), + properties: HashMap::new(), + children: Vec::new(), + }, + ], + }); + } +} \ No newline at end of file diff --git a/server/src/snapshot_middleware/lua.rs b/server/src/snapshot_middleware/lua.rs new file mode 100644 index 00000000..a69728eb --- /dev/null +++ b/server/src/snapshot_middleware/lua.rs @@ -0,0 +1,173 @@ +use std::{ + borrow::Cow, + str, +}; + +use maplit::hashmap; +use rbx_dom_weak::{RbxTree, RbxValue, RbxId}; + +use crate::{ + imfs::new::{Imfs, ImfsFetcher, ImfsEntry, FsResultExt}, + snapshot::InstanceSnapshot, +}; + +use super::{ + middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, +}; + +pub struct SnapshotLua; + +impl SnapshotMiddleware for SnapshotLua { + fn from_imfs( + imfs: &mut Imfs, + entry: &ImfsEntry, + ) -> SnapshotInstanceResult<'static> { + let file_name = entry.path() + .file_name().unwrap().to_string_lossy(); + + if entry.is_directory() { + let module_init_path = entry.path().join("init.lua"); + if let Some(init_entry) = imfs.get(module_init_path).with_not_found()? { + if let Some(mut snapshot) = SnapshotLua::from_imfs(imfs, &init_entry)? { + snapshot.name = Cow::Owned(file_name.into_owned()); + + return Ok(Some(snapshot)); + } + } + + let server_init_path = entry.path().join("init.server.lua"); + if let Some(init_entry) = imfs.get(server_init_path).with_not_found()? { + if let Some(mut snapshot) = SnapshotLua::from_imfs(imfs, &init_entry)? { + snapshot.name = Cow::Owned(file_name.into_owned()); + + return Ok(Some(snapshot)); + } + } + + let client_init_path = entry.path().join("init.client.lua"); + if let Some(init_entry) = imfs.get(client_init_path).with_not_found()? { + if let Some(mut snapshot) = SnapshotLua::from_imfs(imfs, &init_entry)? { + snapshot.name = Cow::Owned(file_name.into_owned()); + + return Ok(Some(snapshot)); + } + } + } + + let (class_name, instance_name) = if let Some(name) = match_trailing(&file_name, ".server.lua") { + ("Script", name) + } else if let Some(name) = match_trailing(&file_name, ".client.lua") { + ("LocalScript", name) + } else if let Some(name) = match_trailing(&file_name, ".lua") { + ("ModuleScript", name) + } else { + return Ok(None); + }; + + let contents = entry.contents(imfs)?; + let contents_str = str::from_utf8(contents) + .expect("File content was not valid UTF-8") + .to_string(); + + let properties = hashmap! { + "Source".to_owned() => RbxValue::String { + value: contents_str, + }, + }; + + Ok(Some(InstanceSnapshot { + snapshot_id: None, + name: Cow::Owned(instance_name.to_owned()), + class_name: Cow::Borrowed(class_name), + properties, + children: Vec::new(), + })) + } + + fn from_instance( + tree: &RbxTree, + id: RbxId, + ) -> SnapshotFileResult { + let instance = tree.get_instance(id).unwrap(); + + match instance.class_name.as_str() { + "ModuleScript" | "LocalScript" | "Script" => unimplemented!("Snapshotting Script instances"), + _ => None, + } + } +} + +fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { + if input.ends_with(trailer) { + let end = input.len().saturating_sub(trailer.len()); + Some(&input[..end]) + } else { + None + } +} + +#[cfg(test)] +mod test { + use super::*; + + use maplit::hashmap; + + use crate::imfs::new::{ImfsSnapshot, NoopFetcher}; + + #[test] + fn module_from_imfs() { + let mut imfs = Imfs::new(NoopFetcher); + let file = ImfsSnapshot::file("Hello there!"); + + imfs.load_from_snapshot("/foo.lua", file); + + let entry = imfs.get("/foo.lua").unwrap(); + let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + assert_eq!(instance_snapshot.name, "foo"); + assert_eq!(instance_snapshot.class_name, "ModuleScript"); + assert_eq!(instance_snapshot.properties, hashmap! { + "Source".to_owned() => RbxValue::String { + value: "Hello there!".to_owned(), + }, + }); + } + + #[test] + fn server_from_imfs() { + let mut imfs = Imfs::new(NoopFetcher); + let file = ImfsSnapshot::file("Hello there!"); + + imfs.load_from_snapshot("/foo.server.lua", file); + + let entry = imfs.get("/foo.server.lua").unwrap(); + let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + assert_eq!(instance_snapshot.name, "foo"); + assert_eq!(instance_snapshot.class_name, "Script"); + assert_eq!(instance_snapshot.properties, hashmap! { + "Source".to_owned() => RbxValue::String { + value: "Hello there!".to_owned(), + }, + }); + } + + #[test] + fn client_from_imfs() { + let mut imfs = Imfs::new(NoopFetcher); + let file = ImfsSnapshot::file("Hello there!"); + + imfs.load_from_snapshot("/foo.client.lua", file); + + let entry = imfs.get("/foo.client.lua").unwrap(); + let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + assert_eq!(instance_snapshot.name, "foo"); + assert_eq!(instance_snapshot.class_name, "LocalScript"); + assert_eq!(instance_snapshot.properties, hashmap! { + "Source".to_owned() => RbxValue::String { + value: "Hello there!".to_owned(), + }, + }); + } +} \ No newline at end of file diff --git a/server/src/snapshot_middleware/middleware.rs b/server/src/snapshot_middleware/middleware.rs new file mode 100644 index 00000000..9dc54f53 --- /dev/null +++ b/server/src/snapshot_middleware/middleware.rs @@ -0,0 +1,39 @@ +use std::{ + path::{PathBuf, Path}, +}; + +use rbx_dom_weak::{RbxTree, RbxId}; + +use crate::{ + imfs::{ + FsResult, + new::{ + Imfs, + ImfsEntry, + ImfsFetcher, + ImfsSnapshot, + }, + }, + snapshot::InstanceSnapshot, +}; + +pub type SnapshotInstanceResult<'a> = FsResult>>; +pub type SnapshotFileResult = Option<(String, ImfsSnapshot)>; + +pub trait SnapshotMiddleware { + fn from_imfs( + imfs: &mut Imfs, + entry: &ImfsEntry, + ) -> SnapshotInstanceResult<'static>; + + fn from_instance( + tree: &RbxTree, + id: RbxId, + ) -> SnapshotFileResult; + + fn change_affects_paths( + path: &Path + ) -> Vec { + vec![path.to_path_buf()] + } +} \ No newline at end of file diff --git a/server/src/snapshot_middleware/mod.rs b/server/src/snapshot_middleware/mod.rs new file mode 100644 index 00000000..4a9183c0 --- /dev/null +++ b/server/src/snapshot_middleware/mod.rs @@ -0,0 +1,76 @@ +//! Defines the semantics that Rojo uses to turn entries on the filesystem into +//! Roblox instances using the instance snapshot subsystem. + +#![allow(dead_code)] + +mod context; +mod csv; +mod dir; +mod error; +mod json_model; +mod lua; +mod middleware; +mod project; +mod rbxm; +mod rbxmx; +mod txt; + +use rbx_dom_weak::{RbxTree, RbxId}; + +use crate::imfs::new::{Imfs, ImfsEntry, ImfsFetcher}; +use self::{ + middleware::{SnapshotInstanceResult, SnapshotFileResult, SnapshotMiddleware}, + csv::SnapshotCsv, + dir::SnapshotDir, + json_model::SnapshotJsonModel, + lua::SnapshotLua, + project::SnapshotProject, + rbxm::SnapshotRbxm, + rbxmx::SnapshotRbxmx, + txt::SnapshotTxt, +}; + +macro_rules! middlewares { + ( $($middleware: ident,)* ) => { + /// Generates a snapshot of instances from the given ImfsEntry. + pub fn snapshot_from_imfs( + imfs: &mut Imfs, + entry: &ImfsEntry, + ) -> SnapshotInstanceResult<'static> { + $( + log::trace!("trying middleware {} on {}", stringify!($middleware), entry.path().display()); + + if let Some(snapshot) = $middleware::from_imfs(imfs, entry)? { + log::trace!("middleware {} success on {}", stringify!($middleware), entry.path().display()); + return Ok(Some(snapshot)); + } + )* + + log::trace!("no middleware returned Ok(Some)"); + Ok(None) + } + + /// Generates an in-memory filesystem snapshot of the given Roblox + /// instance. + pub fn snapshot_from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult { + $( + if let Some(result) = $middleware::from_instance(tree, id) { + return Some(result); + } + )* + + None + } + }; +} + +middlewares! { + SnapshotProject, + SnapshotJsonModel, + SnapshotRbxmx, + SnapshotRbxm, + SnapshotLua, + SnapshotCsv, + SnapshotTxt, + SnapshotDir, +} \ No newline at end of file diff --git a/server/src/snapshot_middleware/project.rs b/server/src/snapshot_middleware/project.rs new file mode 100644 index 00000000..9cafa91b --- /dev/null +++ b/server/src/snapshot_middleware/project.rs @@ -0,0 +1,489 @@ +use std::{ + borrow::Cow, + collections::HashMap, +}; + +use rbx_dom_weak::{RbxTree, RbxId}; +use rbx_reflection::try_resolve_value; + +use crate::{ + project::{Project, ProjectNode}, + imfs::{ + FsErrorKind, + new::{Imfs, ImfsFetcher, ImfsEntry}, + }, + snapshot::InstanceSnapshot, +}; + +use super::{ + snapshot_from_imfs, + middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, +}; + +pub struct SnapshotProject; + +impl SnapshotMiddleware for SnapshotProject { + fn from_imfs( + imfs: &mut Imfs, + entry: &ImfsEntry, + ) -> SnapshotInstanceResult<'static> { + if entry.is_directory() { + let project_path = entry.path().join("default.project.json"); + + match imfs.get(project_path) { + Err(ref err) if err.kind() == FsErrorKind::NotFound => {} + Err(err) => return Err(err), + Ok(entry) => return SnapshotProject::from_imfs(imfs, &entry), + } + } + + if !entry.path().to_string_lossy().ends_with(".project.json") { + return Ok(None) + } + + let project = Project::load_from_slice(entry.contents(imfs)?, entry.path()) + .expect("Invalid project file"); + + snapshot_project_node(&project.name, &project.tree, imfs) + } + + fn from_instance( + _tree: &RbxTree, + _id: RbxId, + ) -> SnapshotFileResult { + // TODO: Supporting turning instances into projects + None + } +} + +fn snapshot_project_node( + instance_name: &str, + node: &ProjectNode, + imfs: &mut Imfs, +) -> SnapshotInstanceResult<'static> { + assert!(node.ignore_unknown_instances.is_none(), "TODO: Support $ignoreUnknownInstances"); + + let name = Cow::Owned(instance_name.to_owned()); + let mut class_name = node.class_name + .as_ref() + .map(|name| Cow::Owned(name.clone())); + let mut properties = HashMap::new(); + let mut children = Vec::new(); + + if let Some(path) = &node.path { + let entry = imfs.get(path)?; + + if let Some(snapshot) = snapshot_from_imfs(imfs, &entry)? { + // If a class name was already specified, then it'll override the + // class name of this snapshot ONLY if it's a Folder. + // + // This restriction is in place to prevent applying properties to + // instances that don't make sense. The primary use-case for using + // $className and $path at the same time is to use a directory as a + // service in a place file. + class_name = match class_name { + Some(class_name) => { + if snapshot.class_name == "Folder" { + Some(class_name) + } else { + // TODO: Turn this into an error object. + panic!("If $className and $path are specified, $path must yield an instance of class Folder"); + } + } + None => Some(snapshot.class_name) + }; + + // Properties from the snapshot are pulled in unchanged, and + // overridden by properties set on the project node. + properties.reserve(snapshot.properties.len()); + for (key, value) in snapshot.properties.into_iter() { + properties.insert(key, value); + } + + // The snapshot's children will be merged with the children defined + // in the project node, if there are any. + children.reserve(snapshot.children.len()); + for child in snapshot.children.into_iter() { + children.push(child); + } + } else { + // TODO: Should this issue an error instead? + log::warn!("$path referred to a path that could not be turned into an instance by Rojo"); + } + } + + let class_name = class_name + // TODO: Turn this into an error object. + .expect("$className or $path must be specified"); + + for (child_name, child_project_node) in &node.children { + if let Some(child) = snapshot_project_node(child_name, child_project_node, imfs)? { + children.push(child); + } + } + + for (key, value) in &node.properties { + let resolved_value = try_resolve_value(&class_name, key, value) + .expect("TODO: Properly handle value resolution errors"); + + properties.insert(key.clone(), resolved_value); + } + + Ok(Some(InstanceSnapshot { + snapshot_id: None, + name, + class_name, + properties, + children, + })) +} + +#[cfg(test)] +mod test { + use super::*; + + use rbx_dom_weak::RbxValue; + use maplit::hashmap; + + use crate::imfs::new::{ImfsSnapshot, NoopFetcher}; + + #[test] + fn project_from_folder() { + let _ = env_logger::try_init(); + + let mut imfs = Imfs::new(NoopFetcher); + let dir = ImfsSnapshot::dir(hashmap! { + "default.project.json" => ImfsSnapshot::file(r#" + { + "name": "indirect-project", + "tree": { + "$className": "Folder" + } + } + "#), + }); + + imfs.load_from_snapshot("/foo", dir); + + let entry = imfs.get("/foo").unwrap(); + let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); + + assert_eq!(instance_snapshot.name, "indirect-project"); + assert_eq!(instance_snapshot.class_name, "Folder"); + assert_eq!(instance_snapshot.properties, HashMap::new()); + assert_eq!(instance_snapshot.children, Vec::new()); + } + + #[test] + fn project_from_direct_file() { + let _ = env_logger::try_init(); + + let mut imfs = Imfs::new(NoopFetcher); + let dir = ImfsSnapshot::dir(hashmap! { + "hello.project.json" => ImfsSnapshot::file(r#" + { + "name": "direct-project", + "tree": { + "$className": "Model" + } + } + "#), + }); + + imfs.load_from_snapshot("/foo", dir); + + let entry = imfs.get("/foo/hello.project.json").unwrap(); + let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); + + assert_eq!(instance_snapshot.name, "direct-project"); + assert_eq!(instance_snapshot.class_name, "Model"); + assert_eq!(instance_snapshot.properties, HashMap::new()); + assert_eq!(instance_snapshot.children, Vec::new()); + } + + #[test] + fn project_with_resolved_properties() { + let _ = env_logger::try_init(); + + let mut imfs = Imfs::new(NoopFetcher); + let dir = ImfsSnapshot::dir(hashmap! { + "default.project.json" => ImfsSnapshot::file(r#" + { + "name": "resolved-properties", + "tree": { + "$className": "StringValue", + "$properties": { + "Value": { + "Type": "String", + "Value": "Hello, world!" + } + } + } + } + "#), + }); + + imfs.load_from_snapshot("/foo", dir); + + let entry = imfs.get("/foo").unwrap(); + let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); + + assert_eq!(instance_snapshot.name, "resolved-properties"); + assert_eq!(instance_snapshot.class_name, "StringValue"); + assert_eq!(instance_snapshot.properties, hashmap! { + "Value".to_owned() => RbxValue::String { + value: "Hello, world!".to_owned(), + }, + }); + assert_eq!(instance_snapshot.children, Vec::new()); + } + + #[test] + fn project_with_unresolved_properties() { + let _ = env_logger::try_init(); + + let mut imfs = Imfs::new(NoopFetcher); + let dir = ImfsSnapshot::dir(hashmap! { + "default.project.json" => ImfsSnapshot::file(r#" + { + "name": "unresolved-properties", + "tree": { + "$className": "StringValue", + "$properties": { + "Value": "Hi!" + } + } + } + "#), + }); + + imfs.load_from_snapshot("/foo", dir); + + let entry = imfs.get("/foo").unwrap(); + let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); + + assert_eq!(instance_snapshot.name, "unresolved-properties"); + assert_eq!(instance_snapshot.class_name, "StringValue"); + assert_eq!(instance_snapshot.properties, hashmap! { + "Value".to_owned() => RbxValue::String { + value: "Hi!".to_owned(), + }, + }); + assert_eq!(instance_snapshot.children, Vec::new()); + } + + #[test] + fn project_with_children() { + let _ = env_logger::try_init(); + + let mut imfs = Imfs::new(NoopFetcher); + let dir = ImfsSnapshot::dir(hashmap! { + "default.project.json" => ImfsSnapshot::file(r#" + { + "name": "children", + "tree": { + "$className": "Folder", + + "Child": { + "$className": "Model" + } + } + } + "#), + }); + + imfs.load_from_snapshot("/foo", dir); + + let entry = imfs.get("/foo").unwrap(); + let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); + + assert_eq!(instance_snapshot.name, "children"); + assert_eq!(instance_snapshot.class_name, "Folder"); + assert_eq!(instance_snapshot.properties, HashMap::new()); + assert_eq!(instance_snapshot.children.len(), 1); + + let child = &instance_snapshot.children[0]; + assert_eq!(child.name, "Child"); + assert_eq!(child.class_name, "Model"); + assert_eq!(child.properties, HashMap::new()); + assert_eq!(child.children, Vec::new()); + } + + #[test] + fn project_with_path_to_txt() { + let _ = env_logger::try_init(); + + let mut imfs = Imfs::new(NoopFetcher); + let dir = ImfsSnapshot::dir(hashmap! { + "default.project.json" => ImfsSnapshot::file(r#" + { + "name": "path-project", + "tree": { + "$path": "other.txt" + } + } + "#), + "other.txt" => ImfsSnapshot::file("Hello, world!"), + }); + + imfs.load_from_snapshot("/foo", dir); + + let entry = imfs.get("/foo").unwrap(); + let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); + + assert_eq!(instance_snapshot.name, "path-project"); + assert_eq!(instance_snapshot.class_name, "StringValue"); + assert_eq!(instance_snapshot.properties, hashmap! { + "Value".to_owned() => RbxValue::String { + value: "Hello, world!".to_owned(), + }, + }); + assert_eq!(instance_snapshot.children, Vec::new()); + } + + #[test] + fn project_with_path_to_project() { + let _ = env_logger::try_init(); + + let mut imfs = Imfs::new(NoopFetcher); + let dir = ImfsSnapshot::dir(hashmap! { + "default.project.json" => ImfsSnapshot::file(r#" + { + "name": "path-project", + "tree": { + "$path": "other.project.json" + } + } + "#), + "other.project.json" => ImfsSnapshot::file(r#" + { + "name": "other-project", + "tree": { + "$className": "Model" + } + } + "#), + }); + + imfs.load_from_snapshot("/foo", dir); + + let entry = imfs.get("/foo").unwrap(); + let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); + + assert_eq!(instance_snapshot.name, "path-project"); + assert_eq!(instance_snapshot.class_name, "Model"); + assert_eq!(instance_snapshot.properties, HashMap::new()); + assert_eq!(instance_snapshot.children, Vec::new()); + } + + #[test] + fn project_with_path_to_project_with_children() { + let _ = env_logger::try_init(); + + let mut imfs = Imfs::new(NoopFetcher); + let dir = ImfsSnapshot::dir(hashmap! { + "default.project.json" => ImfsSnapshot::file(r#" + { + "name": "path-child-project", + "tree": { + "$path": "other.project.json" + } + } + "#), + "other.project.json" => ImfsSnapshot::file(r#" + { + "name": "other-project", + "tree": { + "$className": "Folder", + + "SomeChild": { + "$className": "Model" + } + } + } + "#), + }); + + imfs.load_from_snapshot("/foo", dir); + + let entry = imfs.get("/foo").unwrap(); + let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); + + assert_eq!(instance_snapshot.name, "path-child-project"); + assert_eq!(instance_snapshot.class_name, "Folder"); + assert_eq!(instance_snapshot.properties, HashMap::new()); + assert_eq!(instance_snapshot.children.len(), 1); + + let child = &instance_snapshot.children[0]; + assert_eq!(child.name, "SomeChild"); + assert_eq!(child.class_name, "Model"); + assert_eq!(child.properties, HashMap::new()); + assert_eq!(child.children, Vec::new()); + } + + /// Ensures that if a property is defined both in the resulting instance + /// from $path and also in $properties, that the $properties value takes + /// precedence. + #[test] + fn project_path_property_overrides() { + let _ = env_logger::try_init(); + + let mut imfs = Imfs::new(NoopFetcher); + let dir = ImfsSnapshot::dir(hashmap! { + "default.project.json" => ImfsSnapshot::file(r#" + { + "name": "path-property-override", + "tree": { + "$path": "other.project.json", + "$properties": { + "Value": "Changed" + } + } + } + "#), + "other.project.json" => ImfsSnapshot::file(r#" + { + "name": "other-project", + "tree": { + "$className": "StringValue", + "$properties": { + "Value": "Original" + } + } + } + "#), + }); + + imfs.load_from_snapshot("/foo", dir); + + let entry = imfs.get("/foo").unwrap(); + let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); + + assert_eq!(instance_snapshot.name, "path-property-override"); + assert_eq!(instance_snapshot.class_name, "StringValue"); + assert_eq!(instance_snapshot.properties, hashmap! { + "Value".to_owned() => RbxValue::String { + value: "Changed".to_owned(), + }, + }); + assert_eq!(instance_snapshot.children, Vec::new()); + } +} \ No newline at end of file diff --git a/server/src/snapshot_middleware/rbxm.rs b/server/src/snapshot_middleware/rbxm.rs new file mode 100644 index 00000000..97d7efd9 --- /dev/null +++ b/server/src/snapshot_middleware/rbxm.rs @@ -0,0 +1,96 @@ +use std::{ + borrow::Cow, + collections::HashMap, +}; + +use rbx_dom_weak::{RbxTree, RbxInstanceProperties, RbxId}; + +use crate::{ + imfs::new::{Imfs, ImfsFetcher, ImfsEntry}, + snapshot::InstanceSnapshot, +}; + +use super::{ + middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, +}; + +pub struct SnapshotRbxm; + +impl SnapshotMiddleware for SnapshotRbxm { + fn from_imfs( + imfs: &mut Imfs, + entry: &ImfsEntry, + ) -> SnapshotInstanceResult<'static> { + if entry.is_directory() { + return Ok(None); + } + + let file_name = entry.path() + .file_name().unwrap().to_string_lossy(); + + if !file_name.ends_with(".rbxm") { + return Ok(None); + } + + let instance_name = entry.path() + .file_stem().expect("Could not extract file stem") + .to_string_lossy().to_string(); + + let mut temp_tree = RbxTree::new(RbxInstanceProperties { + name: "DataModel".to_owned(), + class_name: "DataModel".to_owned(), + properties: HashMap::new(), + }); + + let root_id = temp_tree.get_root_id(); + rbx_binary::decode(&mut temp_tree, root_id, entry.contents(imfs)?) + .expect("TODO: Handle rbx_binary errors"); + + let root_instance = temp_tree.get_instance(root_id).unwrap(); + let children = root_instance.get_children_ids(); + + if children.len() == 1 { + let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); + snapshot.name = Cow::Owned(instance_name); + + Ok(Some(snapshot)) + } else { + panic!("Rojo doesn't have support for model files with zero or more than one top-level instances yet."); + } + } + + fn from_instance( + _tree: &RbxTree, + _id: RbxId, + ) -> SnapshotFileResult { + unimplemented!("Snapshotting models"); + } +} + +#[cfg(test)] +mod test { + use super::*; + + use crate::imfs::new::{ImfsSnapshot, NoopFetcher}; + + #[test] + fn model_from_imfs() { + let mut imfs = Imfs::new(NoopFetcher); + let file = ImfsSnapshot::file(include_bytes!("../../assets/test-folder.rbxm").to_vec()); + + imfs.load_from_snapshot("/foo.rbxm", file); + + let entry = imfs.get("/foo.rbxm").unwrap(); + let instance_snapshot = SnapshotRbxm::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + assert_eq!(instance_snapshot.name, "foo"); + assert_eq!(instance_snapshot.class_name, "Folder"); + assert_eq!(instance_snapshot.children, Vec::new()); + + // We intentionally don't assert on properties. rbx_binary does not + // distinguish between String and BinaryString. The sample model was + // created by Roblox Studio and has an empty BinaryString "Tags" + // property that currently deserializes incorrectly. + // See: https://github.com/rojo-rbx/rbx-dom/issues/49 + } +} \ No newline at end of file diff --git a/server/src/snapshot_middleware/rbxmx.rs b/server/src/snapshot_middleware/rbxmx.rs new file mode 100644 index 00000000..d509fdab --- /dev/null +++ b/server/src/snapshot_middleware/rbxmx.rs @@ -0,0 +1,94 @@ +use std::borrow::Cow; + +use rbx_dom_weak::{RbxTree, RbxId}; + +use crate::{ + imfs::new::{Imfs, ImfsFetcher, ImfsEntry}, + snapshot::InstanceSnapshot, +}; + +use super::{ + middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, +}; + +pub struct SnapshotRbxmx; + +impl SnapshotMiddleware for SnapshotRbxmx { + fn from_imfs( + imfs: &mut Imfs, + entry: &ImfsEntry, + ) -> SnapshotInstanceResult<'static> { + if entry.is_directory() { + return Ok(None); + } + + let file_name = entry.path() + .file_name().unwrap().to_string_lossy(); + + if !file_name.ends_with(".rbxmx") { + return Ok(None); + } + + let instance_name = entry.path() + .file_stem().expect("Could not extract file stem") + .to_string_lossy().to_string(); + + let options = rbx_xml::DecodeOptions::new() + .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); + + let temp_tree = rbx_xml::from_reader(entry.contents(imfs)?, options) + .expect("TODO: Handle rbx_xml errors"); + + let root_instance = temp_tree.get_instance(temp_tree.get_root_id()).unwrap(); + let children = root_instance.get_children_ids(); + + if children.len() == 1 { + let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); + snapshot.name = Cow::Owned(instance_name); + + Ok(Some(snapshot)) + } else { + panic!("Rojo doesn't have support for model files with zero or more than one top-level instances yet."); + } + } + + fn from_instance( + _tree: &RbxTree, + _id: RbxId, + ) -> SnapshotFileResult { + unimplemented!("Snapshotting models"); + } +} + +#[cfg(test)] +mod test { + use super::*; + + use std::collections::HashMap; + + use crate::imfs::new::{ImfsSnapshot, NoopFetcher}; + + #[test] + fn model_from_imfs() { + let mut imfs = Imfs::new(NoopFetcher); + let file = ImfsSnapshot::file(r#" + + + + THIS NAME IS IGNORED + + + + "#); + + imfs.load_from_snapshot("/foo.rbxmx", file); + + let entry = imfs.get("/foo.rbxmx").unwrap(); + let instance_snapshot = SnapshotRbxmx::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + assert_eq!(instance_snapshot.name, "foo"); + assert_eq!(instance_snapshot.class_name, "Folder"); + assert_eq!(instance_snapshot.properties, HashMap::new()); + assert_eq!(instance_snapshot.children, Vec::new()); + } +} \ No newline at end of file diff --git a/server/src/snapshot_middleware/txt.rs b/server/src/snapshot_middleware/txt.rs new file mode 100644 index 00000000..3fdb6580 --- /dev/null +++ b/server/src/snapshot_middleware/txt.rs @@ -0,0 +1,147 @@ +use std::{ + borrow::Cow, + str, +}; + +use maplit::hashmap; +use rbx_dom_weak::{RbxTree, RbxValue, RbxId}; + +use crate::{ + imfs::new::{Imfs, ImfsSnapshot, FileSnapshot, ImfsFetcher, ImfsEntry}, + snapshot::InstanceSnapshot, +}; + +use super::{ + middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, +}; + +pub struct SnapshotTxt; + +impl SnapshotMiddleware for SnapshotTxt { + fn from_imfs( + imfs: &mut Imfs, + entry: &ImfsEntry, + ) -> SnapshotInstanceResult<'static> { + if entry.is_directory() { + return Ok(None); + } + + let extension = match entry.path().extension() { + Some(x) => x.to_str().unwrap(), + None => return Ok(None), + }; + + if extension != "txt" { + return Ok(None); + } + + let instance_name = entry.path() + .file_stem().expect("Could not extract file stem") + .to_str().unwrap().to_string(); + + let contents = entry.contents(imfs)?; + let contents_str = str::from_utf8(contents) + .expect("File content was not valid UTF-8").to_string(); + + let properties = hashmap! { + "Value".to_owned() => RbxValue::String { + value: contents_str, + }, + }; + + Ok(Some(InstanceSnapshot { + snapshot_id: None, + name: Cow::Owned(instance_name), + class_name: Cow::Borrowed("StringValue"), + properties, + children: Vec::new(), + })) + } + + fn from_instance( + tree: &RbxTree, + id: RbxId, + ) -> SnapshotFileResult { + let instance = tree.get_instance(id).unwrap(); + + if instance.class_name != "StringValue" { + return None; + } + + if !instance.get_children_ids().is_empty() { + return None; + } + + let value = match instance.properties.get("Value") { + Some(RbxValue::String { value }) => value.clone(), + Some(_) => panic!("wrong type ahh"), + None => String::new(), + }; + + let snapshot = ImfsSnapshot::File(FileSnapshot { + contents: value.into_bytes(), + }); + + let mut file_name = instance.name.clone(); + file_name.push_str(".txt"); + + Some((file_name, snapshot)) + } +} + +#[cfg(test)] +mod test { + use super::*; + + use maplit::hashmap; + use rbx_dom_weak::{RbxInstanceProperties}; + + use crate::imfs::new::NoopFetcher; + + #[test] + fn instance_from_imfs() { + let mut imfs = Imfs::new(NoopFetcher); + let file = ImfsSnapshot::file("Hello there!"); + + imfs.load_from_snapshot("/foo.txt", file); + + let entry = imfs.get("/foo.txt").unwrap(); + let instance_snapshot = SnapshotTxt::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + assert_eq!(instance_snapshot.name, "foo"); + assert_eq!(instance_snapshot.class_name, "StringValue"); + assert_eq!(instance_snapshot.properties, hashmap! { + "Value".to_owned() => RbxValue::String { + value: "Hello there!".to_owned(), + }, + }); + } + + #[test] + fn imfs_from_instance() { + let tree = RbxTree::new(string_value("Root", "Hello, world!")); + let root_id = tree.get_root_id(); + + let (_file_name, _file) = SnapshotTxt::from_instance(&tree, root_id).unwrap(); + } + + fn folder(name: impl Into) -> RbxInstanceProperties { + RbxInstanceProperties { + name: name.into(), + class_name: "Folder".to_owned(), + properties: Default::default(), + } + } + + fn string_value(name: impl Into, value: impl Into) -> RbxInstanceProperties { + RbxInstanceProperties { + name: name.into(), + class_name: "StringValue".to_owned(), + properties: hashmap! { + "Value".to_owned() => RbxValue::String { + value: value.into(), + }, + }, + } + } +} \ No newline at end of file diff --git a/server/src/snapshot_reconciler.rs b/server/src/snapshot_reconciler.rs deleted file mode 100644 index 424ee8ec..00000000 --- a/server/src/snapshot_reconciler.rs +++ /dev/null @@ -1,379 +0,0 @@ -//! Defines the snapshot subsystem of Rojo, which defines a lightweight instance -//! representation (`RbxSnapshotInstance`) and a system to incrementally update -//! an `RbxTree` based on snapshots. - -use std::{ - borrow::Cow, - cmp::Ordering, - collections::{HashMap, HashSet}, - fmt, - str, -}; - -use rbx_dom_weak::{RbxTree, RbxId, RbxInstanceProperties, RbxValue}; -use serde::{Serialize, Deserialize}; - -use crate::{ - path_map::PathMap, - rbx_session::MetadataPerInstance, -}; - -/// Contains all of the IDs that were modified when the snapshot reconciler -/// applied an update. -#[derive(Debug, Clone, Default, Serialize, Deserialize)] -pub struct InstanceChanges { - pub added: HashSet, - pub removed: HashSet, - pub updated: HashSet, -} - -impl fmt::Display for InstanceChanges { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - writeln!(output, "InstanceChanges {{")?; - - if !self.added.is_empty() { - writeln!(output, " Added:")?; - for id in &self.added { - writeln!(output, " {}", id)?; - } - } - - if !self.removed.is_empty() { - writeln!(output, " Removed:")?; - for id in &self.removed { - writeln!(output, " {}", id)?; - } - } - - if !self.updated.is_empty() { - writeln!(output, " Updated:")?; - for id in &self.updated { - writeln!(output, " {}", id)?; - } - } - - writeln!(output, "}}") - } -} - -impl InstanceChanges { - pub fn is_empty(&self) -> bool { - self.added.is_empty() && self.removed.is_empty() && self.updated.is_empty() - } -} - -/// A lightweight, hierarchical representation of an instance that can be -/// applied to the tree. -#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] -pub struct RbxSnapshotInstance<'a> { - pub name: Cow<'a, str>, - pub class_name: Cow<'a, str>, - pub properties: HashMap, - pub children: Vec>, - pub metadata: MetadataPerInstance, -} - -impl<'a> RbxSnapshotInstance<'a> { - pub fn get_owned(&'a self) -> RbxSnapshotInstance<'static> { - let children: Vec> = self.children.iter() - .map(RbxSnapshotInstance::get_owned) - .collect(); - - RbxSnapshotInstance { - name: Cow::Owned(self.name.clone().into_owned()), - class_name: Cow::Owned(self.class_name.clone().into_owned()), - properties: self.properties.clone(), - children, - metadata: self.metadata.clone(), - } - } -} - -impl<'a> PartialOrd for RbxSnapshotInstance<'a> { - fn partial_cmp(&self, other: &RbxSnapshotInstance) -> Option { - Some(self.name.cmp(&other.name) - .then(self.class_name.cmp(&other.class_name))) - } -} - -/// Generates an `RbxSnapshotInstance` from an existing `RbxTree` and an ID to -/// use as the root of the snapshot. -/// -/// This is used to transform instances created by rbx_xml and rbx_binary into -/// snapshots that can be applied to the tree to reduce instance churn. -pub fn snapshot_from_tree(tree: &RbxTree, id: RbxId) -> Option> { - let instance = tree.get_instance(id)?; - - let mut children = Vec::new(); - for &child_id in instance.get_children_ids() { - children.push(snapshot_from_tree(tree, child_id)?); - } - - Some(RbxSnapshotInstance { - name: Cow::Owned(instance.name.to_owned()), - class_name: Cow::Owned(instance.class_name.to_owned()), - properties: instance.properties.clone(), - children, - metadata: MetadataPerInstance { - source_path: None, - ignore_unknown_instances: false, - project_definition: None, - }, - }) -} - -/// Constructs a new `RbxTree` out of a snapshot and places to attach metadata. -pub fn reify_root( - snapshot: &RbxSnapshotInstance, - instance_per_path: &mut PathMap>, - metadata_per_instance: &mut HashMap, - changes: &mut InstanceChanges, -) -> RbxTree { - let instance = reify_core(snapshot); - let mut tree = RbxTree::new(instance); - let id = tree.get_root_id(); - - reify_metadata(snapshot, id, instance_per_path, metadata_per_instance); - - changes.added.insert(id); - - for child in &snapshot.children { - reify_subtree(child, &mut tree, id, instance_per_path, metadata_per_instance, changes); - } - - tree -} - -/// Adds instances to a portion of the given `RbxTree`, used for when new -/// instances are created. -pub fn reify_subtree( - snapshot: &RbxSnapshotInstance, - tree: &mut RbxTree, - parent_id: RbxId, - instance_per_path: &mut PathMap>, - metadata_per_instance: &mut HashMap, - changes: &mut InstanceChanges, -) -> RbxId { - let instance = reify_core(snapshot); - let id = tree.insert_instance(instance, parent_id); - - reify_metadata(snapshot, id, instance_per_path, metadata_per_instance); - - changes.added.insert(id); - - for child in &snapshot.children { - reify_subtree(child, tree, id, instance_per_path, metadata_per_instance, changes); - } - - id -} - -fn reify_metadata( - snapshot: &RbxSnapshotInstance, - instance_id: RbxId, - instance_per_path: &mut PathMap>, - metadata_per_instance: &mut HashMap, -) { - if let Some(source_path) = &snapshot.metadata.source_path { - let path_metadata = match instance_per_path.get_mut(&source_path) { - Some(v) => v, - None => { - instance_per_path.insert(source_path.clone(), Default::default()); - instance_per_path.get_mut(&source_path).unwrap() - }, - }; - - path_metadata.insert(instance_id); - } - - metadata_per_instance.insert(instance_id, snapshot.metadata.clone()); -} - -/// Updates existing instances in an existing `RbxTree`, potentially adding, -/// updating, or removing children and properties. -pub fn reconcile_subtree( - tree: &mut RbxTree, - id: RbxId, - snapshot: &RbxSnapshotInstance, - instance_per_path: &mut PathMap>, - metadata_per_instance: &mut HashMap, - changes: &mut InstanceChanges, -) { - reify_metadata(snapshot, id, instance_per_path, metadata_per_instance); - - if reconcile_instance_properties(tree.get_instance_mut(id).unwrap(), snapshot) { - changes.updated.insert(id); - } - - reconcile_instance_children(tree, id, snapshot, instance_per_path, metadata_per_instance, changes); -} - -fn reify_core(snapshot: &RbxSnapshotInstance) -> RbxInstanceProperties { - let mut properties = HashMap::new(); - - for (key, value) in &snapshot.properties { - properties.insert(key.clone(), value.clone()); - } - - let instance = RbxInstanceProperties { - name: snapshot.name.to_string(), - class_name: snapshot.class_name.to_string(), - properties, - }; - - instance -} - -/// Updates the given instance to match the properties defined on the snapshot. -/// -/// Returns whether any changes were applied. -fn reconcile_instance_properties(instance: &mut RbxInstanceProperties, snapshot: &RbxSnapshotInstance) -> bool { - let mut has_diffs = false; - - if instance.name != snapshot.name { - instance.name = snapshot.name.to_string(); - has_diffs = true; - } - - if instance.class_name != snapshot.class_name { - instance.class_name = snapshot.class_name.to_string(); - has_diffs = true; - } - - let mut property_updates = HashMap::new(); - - for (key, instance_value) in &instance.properties { - match snapshot.properties.get(key) { - Some(snapshot_value) => { - if snapshot_value != instance_value { - property_updates.insert(key.clone(), Some(snapshot_value.clone())); - } - }, - None => { - property_updates.insert(key.clone(), None); - }, - } - } - - for (key, snapshot_value) in &snapshot.properties { - if property_updates.contains_key(key) { - continue; - } - - match instance.properties.get(key) { - Some(instance_value) => { - if snapshot_value != instance_value { - property_updates.insert(key.clone(), Some(snapshot_value.clone())); - } - }, - None => { - property_updates.insert(key.clone(), Some(snapshot_value.clone())); - }, - } - } - - has_diffs = has_diffs || !property_updates.is_empty(); - - for (key, change) in property_updates.drain() { - match change { - Some(value) => instance.properties.insert(key, value), - None => instance.properties.remove(&key), - }; - } - - has_diffs -} - -/// Updates the children of the instance in the `RbxTree` to match the children -/// of the `RbxSnapshotInstance`. Order will be updated to match. -fn reconcile_instance_children( - tree: &mut RbxTree, - id: RbxId, - snapshot: &RbxSnapshotInstance, - instance_per_path: &mut PathMap>, - metadata_per_instance: &mut HashMap, - changes: &mut InstanceChanges, -) { - // These lists are kept so that we can apply all the changes we figure out - let mut children_to_maybe_update: Vec<(RbxId, &RbxSnapshotInstance)> = Vec::new(); - let mut children_to_add: Vec<(usize, &RbxSnapshotInstance)> = Vec::new(); - let mut children_to_remove: Vec = Vec::new(); - - // This map is used once we're done mutating children to sort them according - // to the order specified in the snapshot. Without it, a snapshot with a new - // child prepended will cause the RbxTree instance to have out-of-order - // children and would make Rojo non-deterministic. - let mut ids_to_snapshot_indices = HashMap::new(); - - // Since we have to enumerate the children of both the RbxTree instance and - // our snapshot, we keep a set of the snapshot children we've seen. - let mut visited_snapshot_indices = vec![false; snapshot.children.len()]; - - let children_ids = tree.get_instance(id).unwrap().get_children_ids(); - - // Find all instances that were removed or updated, which we derive by - // trying to pair up existing instances to snapshots. - for &child_id in children_ids { - let child_instance = tree.get_instance(child_id).unwrap(); - - // Locate a matching snapshot for this instance - let mut matching_snapshot = None; - for (snapshot_index, child_snapshot) in snapshot.children.iter().enumerate() { - if visited_snapshot_indices[snapshot_index] { - continue; - } - - // We assume that instances with the same name are probably pretty - // similar. This heuristic is similar to React's reconciliation - // strategy. - if child_snapshot.name == child_instance.name { - ids_to_snapshot_indices.insert(child_id, snapshot_index); - visited_snapshot_indices[snapshot_index] = true; - matching_snapshot = Some(child_snapshot); - break; - } - } - - match matching_snapshot { - Some(child_snapshot) => { - children_to_maybe_update.push((child_instance.get_id(), child_snapshot)); - } - None => { - children_to_remove.push(child_instance.get_id()); - } - } - } - - // Find all instancs that were added, which is just the snapshots we didn't - // match up to existing instances above. - for (snapshot_index, child_snapshot) in snapshot.children.iter().enumerate() { - if !visited_snapshot_indices[snapshot_index] { - children_to_add.push((snapshot_index, child_snapshot)); - } - } - - // Apply all of our removals we gathered from our diff - for child_id in &children_to_remove { - if let Some(subtree) = tree.remove_instance(*child_id) { - for id in subtree.iter_all_ids() { - metadata_per_instance.remove(&id); - changes.removed.insert(id); - } - } - } - - // Apply all of our children additions - for (snapshot_index, child_snapshot) in &children_to_add { - let id = reify_subtree(child_snapshot, tree, id, instance_per_path, metadata_per_instance, changes); - ids_to_snapshot_indices.insert(id, *snapshot_index); - } - - // Apply any updates that might have updates - for (child_id, child_snapshot) in &children_to_maybe_update { - reconcile_subtree(tree, *child_id, child_snapshot, instance_per_path, metadata_per_instance, changes); - } - - // Apply the sort mapping defined by ids_to_snapshot_indices above - let instance = tree.get_instance_mut(id).unwrap(); - instance.sort_children_unstable_by_key(|id| ids_to_snapshot_indices.get(&id).unwrap()); -} \ No newline at end of file diff --git a/server/src/visualize.rs b/server/src/visualize.rs deleted file mode 100644 index d0b36604..00000000 --- a/server/src/visualize.rs +++ /dev/null @@ -1,174 +0,0 @@ -use std::{ - collections::HashMap, - fmt, - io::Write, - path::Path, - process::{Command, Stdio}, -}; - -use log::warn; -use rbx_dom_weak::{RbxTree, RbxId}; - -use crate::{ - imfs::{Imfs, ImfsItem}, - rbx_session::RbxSession, - web::api::PublicInstanceMetadata, - rbx_session::MetadataPerInstance, -}; - -static GRAPHVIZ_HEADER: &str = r#" -digraph RojoTree { - rankdir = "LR"; - graph [ - ranksep = "0.7", - nodesep = "0.5", - ]; - node [ - fontname = "Hack", - shape = "record", - ]; -"#; - -/// Compiles DOT source to SVG by invoking dot on the command line. -pub fn graphviz_to_svg(source: &str) -> Option { - let command = Command::new("dot") - .arg("-Tsvg") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn(); - - let mut child = match command { - Ok(child) => child, - Err(_) => { - warn!("Failed to spawn GraphViz process to visualize current state."); - warn!("If you want pretty graphs, install GraphViz and make sure 'dot' is on your PATH!"); - return None; - }, - }; - - { - let stdin = child.stdin.as_mut().expect("Failed to open stdin"); - stdin.write_all(source.as_bytes()).expect("Failed to write to stdin"); - } - - let output = child.wait_with_output().expect("Failed to read stdout"); - Some(String::from_utf8(output.stdout).expect("Failed to parse stdout as UTF-8")) -} - -pub struct VisualizeRbxTree<'a, 'b> { - pub tree: &'a RbxTree, - pub metadata: &'b HashMap, -} - -impl<'a, 'b> fmt::Display for VisualizeRbxTree<'a, 'b> { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - writeln!(output, "{}", GRAPHVIZ_HEADER)?; - - visualize_instance(&self.tree, self.tree.get_root_id(), &self.metadata, output)?; - - writeln!(output, "}}") - } -} - -/// A Display wrapper struct to visualize an RbxSession as SVG. -pub struct VisualizeRbxSession<'a>(pub &'a RbxSession); - -impl<'a> fmt::Display for VisualizeRbxSession<'a> { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - writeln!(output, "{}", VisualizeRbxTree { - tree: self.0.get_tree(), - metadata: self.0.get_all_instance_metadata(), - }) - } -} - -fn visualize_instance( - tree: &RbxTree, - id: RbxId, - metadata: &HashMap, - output: &mut fmt::Formatter, -) -> fmt::Result { - let instance = tree.get_instance(id).unwrap(); - - let mut instance_label = format!("{}|{}|{}", instance.name, instance.class_name, id); - - if let Some(session_metadata) = metadata.get(&id) { - let metadata = PublicInstanceMetadata::from_session_metadata(session_metadata); - instance_label.push('|'); - instance_label.push_str(&serde_json::to_string(&metadata).unwrap()); - } - - instance_label = instance_label - .replace("\"", """) - .replace("{", "\\{") - .replace("}", "\\}"); - - writeln!(output, " \"{}\" [label=\"{}\"]", id, instance_label)?; - - for &child_id in instance.get_children_ids() { - writeln!(output, " \"{}\" -> \"{}\"", id, child_id)?; - visualize_instance(tree, child_id, metadata, output)?; - } - - Ok(()) -} - -/// A Display wrapper struct to visualize an Imfs as SVG. -pub struct VisualizeImfs<'a>(pub &'a Imfs); - -impl<'a> fmt::Display for VisualizeImfs<'a> { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - writeln!(output, "{}", GRAPHVIZ_HEADER)?; - - for root_path in self.0.get_roots() { - visualize_root_path(self.0, root_path, output)?; - } - - writeln!(output, "}}")?; - - Ok(()) - } -} - -fn normalize_name(path: &Path) -> String { - path.to_str().unwrap().replace("\\", "/") -} - -fn visualize_root_path(imfs: &Imfs, path: &Path, output: &mut fmt::Formatter) -> fmt::Result { - let normalized_name = normalize_name(path); - let item = imfs.get(path).unwrap(); - - writeln!(output, " \"{}\"", normalized_name)?; - - match item { - ImfsItem::File(_) => {}, - ImfsItem::Directory(directory) => { - for child_path in &directory.children { - writeln!(output, " \"{}\" -> \"{}\"", normalized_name, normalize_name(child_path))?; - visualize_path(imfs, child_path, output)?; - } - }, - } - - Ok(()) -} - -fn visualize_path(imfs: &Imfs, path: &Path, output: &mut fmt::Formatter) -> fmt::Result { - let normalized_name = normalize_name(path); - let short_name = path.file_name().unwrap().to_string_lossy(); - let item = imfs.get(path).unwrap(); - - writeln!(output, " \"{}\" [label = \"{}\"]", normalized_name, short_name)?; - - match item { - ImfsItem::File(_) => {}, - ImfsItem::Directory(directory) => { - for child_path in &directory.children { - writeln!(output, " \"{}\" -> \"{}\"", normalized_name, normalize_name(child_path))?; - visualize_path(imfs, child_path, output)?; - } - }, - } - - Ok(()) -} \ No newline at end of file diff --git a/server/src/web/api.rs b/server/src/web/api.rs index 82d9e70f..a04da71e 100644 --- a/server/src/web/api.rs +++ b/server/src/web/api.rs @@ -2,16 +2,15 @@ //! JSON. use std::{ - borrow::Cow, - collections::{HashMap, HashSet}, + collections::HashSet, sync::Arc, }; use futures::{ - future::{self, IntoFuture}, + future, Future, - sync::oneshot, }; + use hyper::{ service::Service, header, @@ -22,43 +21,15 @@ use hyper::{ Response, }; use serde::{Serialize, Deserialize}; -use rbx_dom_weak::{RbxId, RbxInstance}; +use rbx_dom_weak::RbxId; use crate::{ - live_session::LiveSession, + serve_session::ServeSession, session_id::SessionId, - snapshot_reconciler::InstanceChanges, - rbx_session::{MetadataPerInstance}, }; -/// Contains the instance metadata relevant to Rojo clients. -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct PublicInstanceMetadata { - ignore_unknown_instances: bool, -} - -impl PublicInstanceMetadata { - pub fn from_session_metadata(meta: &MetadataPerInstance) -> PublicInstanceMetadata { - PublicInstanceMetadata { - ignore_unknown_instances: meta.ignore_unknown_instances, - } - } -} - -/// Used to attach metadata specific to Rojo to instances, which come from the -/// rbx_dom_weak crate. -/// -/// Both fields are wrapped in Cow in order to make owned-vs-borrowed simpler -/// for tests. -#[derive(Debug, Serialize, Deserialize)] -pub struct InstanceWithMetadata<'a> { - #[serde(flatten)] - pub instance: Cow<'a, RbxInstance>, - - #[serde(rename = "Metadata")] - pub metadata: Option, -} +const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); +const PROTOCOL_VERSION: u64 = 3; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -67,23 +38,23 @@ pub struct ServerInfoResponse<'a> { pub server_version: &'a str, pub protocol_version: u64, pub expected_place_ids: Option>, - pub root_instance_id: RbxId, + // pub root_instance_id: RbxId, } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ReadResponse<'a> { +pub struct ReadResponse { pub session_id: SessionId, - pub message_cursor: u32, - pub instances: HashMap>, + // pub message_cursor: u32, + // pub instances: HashMap>, } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SubscribeResponse<'a> { +pub struct SubscribeResponse { pub session_id: SessionId, - pub message_cursor: u32, - pub messages: Cow<'a, [InstanceChanges]>, + // pub message_cursor: u32, + // pub messages: Cow<'a, [InstanceChanges]>, } fn response_json(value: T) -> Response { @@ -91,11 +62,11 @@ fn response_json(value: T) -> Response { Ok(v) => v, Err(err) => { return Response::builder() - .status(StatusCode::BAD_REQUEST) + .status(StatusCode::INTERNAL_SERVER_ERROR) .header(header::CONTENT_TYPE, "text/plain") .body(Body::from(err.to_string())) .unwrap(); - }, + } }; Response::builder() @@ -105,8 +76,7 @@ fn response_json(value: T) -> Response { } pub struct ApiService { - live_session: Arc, - server_version: &'static str, + serve_session: Arc, } impl Service for ApiService { @@ -135,24 +105,19 @@ impl Service for ApiService { } impl ApiService { - pub fn new(live_session: Arc) -> ApiService { + pub fn new(serve_session: Arc) -> ApiService { ApiService { - live_session, - server_version: env!("CARGO_PKG_VERSION"), + serve_session, } } /// Get a summary of information about the server fn handle_api_rojo(&self) -> Response { - let rbx_session = self.live_session.rbx_session.lock().unwrap(); - let tree = rbx_session.get_tree(); - response_json(&ServerInfoResponse { - server_version: self.server_version, - protocol_version: 2, - session_id: self.live_session.session_id(), - expected_place_ids: self.live_session.serve_place_ids().clone(), - root_instance_id: tree.get_root_id(), + server_version: SERVER_VERSION, + protocol_version: PROTOCOL_VERSION, + session_id: self.serve_session.session_id(), + expected_place_ids: self.serve_session.serve_place_ids().map(Clone::clone), }) } @@ -160,7 +125,7 @@ impl ApiService { /// there weren't any, subscribe to receive any new messages. fn handle_api_subscribe(&self, request: Request) -> ::Future { let argument = &request.uri().path()["/api/subscribe/".len()..]; - let cursor: u32 = match argument.parse() { + let _cursor: u32 = match argument.parse() { Ok(v) => v, Err(err) => { return Box::new(future::ok(Response::builder() @@ -171,28 +136,9 @@ impl ApiService { }, }; - let message_queue = Arc::clone(&self.live_session.message_queue); - let session_id = self.live_session.session_id(); - - let (tx, rx) = oneshot::channel(); - message_queue.subscribe(cursor, tx); - - let result = rx.into_future() - .and_then(move |(new_cursor, new_messages)| { - Box::new(future::ok(response_json(SubscribeResponse { - session_id: session_id, - messages: Cow::Owned(new_messages), - message_cursor: new_cursor, - }))) - }) - .or_else(|e| { - Box::new(future::ok(Response::builder() - .status(500) - .body(Body::from(format!("Internal Error: {:?}", e))) - .unwrap())) - }); - - Box::new(result) + Box::new(future::ok(response_json(SubscribeResponse { + session_id: self.serve_session.session_id(), + }))) } fn handle_api_read(&self, request: Request) -> Response { @@ -202,9 +148,7 @@ impl ApiService { .map(RbxId::parse_str) .collect(); - let message_queue = Arc::clone(&self.live_session.message_queue); - - let requested_ids = match requested_ids { + let _requested_ids = match requested_ids { Some(id) => id, None => { return Response::builder() @@ -215,39 +159,8 @@ impl ApiService { }, }; - let rbx_session = self.live_session.rbx_session.lock().unwrap(); - let tree = rbx_session.get_tree(); - - let message_cursor = message_queue.get_message_cursor(); - - let mut instances = HashMap::new(); - - for &requested_id in &requested_ids { - if let Some(instance) = tree.get_instance(requested_id) { - let metadata = rbx_session.get_instance_metadata(requested_id) - .map(PublicInstanceMetadata::from_session_metadata); - - instances.insert(instance.get_id(), InstanceWithMetadata { - instance: Cow::Borrowed(instance), - metadata, - }); - - for descendant in tree.descendants(requested_id) { - let descendant_meta = rbx_session.get_instance_metadata(descendant.get_id()) - .map(PublicInstanceMetadata::from_session_metadata); - - instances.insert(descendant.get_id(), InstanceWithMetadata { - instance: Cow::Borrowed(descendant), - metadata: descendant_meta, - }); - } - } - } - - response_json(&ReadResponse { - session_id: self.live_session.session_id(), - message_cursor, - instances, + response_json(ReadResponse { + session_id: self.serve_session.session_id(), }) } } \ No newline at end of file diff --git a/server/src/web/interface.rs b/server/src/web/interface.rs index 4015f933..0007247c 100644 --- a/server/src/web/interface.rs +++ b/server/src/web/interface.rs @@ -14,16 +14,14 @@ use hyper::{ }; use ritz::html; -use crate::{ - live_session::LiveSession, - visualize::{VisualizeRbxSession, VisualizeImfs, graphviz_to_svg}, -}; +use crate::serve_session::ServeSession; +const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); static HOME_CSS: &str = include_str!("../../assets/index.css"); pub struct InterfaceService { - live_session: Arc, - server_version: &'static str, + #[allow(unused)] // TODO: Fill out interface service + serve_session: Arc, } impl Service for InterfaceService { @@ -48,10 +46,9 @@ impl Service for InterfaceService { } impl InterfaceService { - pub fn new(live_session: Arc) -> InterfaceService { + pub fn new(serve_session: Arc) -> InterfaceService { InterfaceService { - live_session, - server_version: env!("CARGO_PKG_VERSION"), + serve_session, } } @@ -71,7 +68,7 @@ impl InterfaceService { "Rojo Live Sync is up and running!"

- "Version " { self.server_version } + "Version " { SERVER_VERSION }

"Rojo Documentation" @@ -88,34 +85,16 @@ impl InterfaceService { } fn handle_visualize_rbx(&self) -> Response { - let rbx_session = self.live_session.rbx_session.lock().unwrap(); - let dot_source = format!("{}", VisualizeRbxSession(&rbx_session)); - - match graphviz_to_svg(&dot_source) { - Some(svg) => Response::builder() - .header(header::CONTENT_TYPE, "image/svg+xml") - .body(Body::from(svg)) - .unwrap(), - None => Response::builder() - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from(dot_source)) - .unwrap(), - } + Response::builder() + .header(header::CONTENT_TYPE, "text/plain") + .body(Body::from("TODO: /visualize/rbx")) + .unwrap() } fn handle_visualize_imfs(&self) -> Response { - let imfs = self.live_session.imfs.lock().unwrap(); - let dot_source = format!("{}", VisualizeImfs(&imfs)); - - match graphviz_to_svg(&dot_source) { - Some(svg) => Response::builder() - .header(header::CONTENT_TYPE, "image/svg+xml") - .body(Body::from(svg)) - .unwrap(), - None => Response::builder() - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from(dot_source)) - .unwrap(), - } + Response::builder() + .header(header::CONTENT_TYPE, "text/plain") + .body(Body::from("TODO: /visualize/imfs")) + .unwrap() } } \ No newline at end of file diff --git a/server/src/web/mod.rs b/server/src/web/mod.rs index cd01f8d7..f3d5fbd2 100644 --- a/server/src/web/mod.rs +++ b/server/src/web/mod.rs @@ -1,6 +1,4 @@ -// TODO: This module needs to be public for visualize, we should move -// PublicInstanceMetadata and switch this private! -pub mod api; +mod api; mod interface; use std::sync::Arc; @@ -18,9 +16,7 @@ use hyper::{ Server, }; -use crate::{ - live_session::LiveSession, -}; +use crate::serve_session::ServeSession; use self::{ api::ApiService, @@ -50,22 +46,22 @@ impl Service for RootService { } impl RootService { - pub fn new(live_session: Arc) -> RootService { + pub fn new(serve_session: Arc) -> RootService { RootService { - api: ApiService::new(Arc::clone(&live_session)), - interface: InterfaceService::new(Arc::clone(&live_session)), + api: ApiService::new(Arc::clone(&serve_session)), + interface: InterfaceService::new(Arc::clone(&serve_session)), } } } pub struct LiveServer { - live_session: Arc, + serve_session: Arc, } impl LiveServer { - pub fn new(live_session: Arc) -> LiveServer { + pub fn new(serve_session: Arc) -> LiveServer { LiveServer { - live_session, + serve_session, } } @@ -75,7 +71,7 @@ impl LiveServer { let server = Server::bind(&address) .serve(move || { let service: FutureResult<_, hyper::Error> = - future::ok(RootService::new(Arc::clone(&self.live_session))); + future::ok(RootService::new(Arc::clone(&self.serve_session))); service }) .map_err(|e| eprintln!("Server error: {}", e)); diff --git a/server/tests/imfs.rs b/server/tests/imfs.rs deleted file mode 100644 index 6dc3f49d..00000000 --- a/server/tests/imfs.rs +++ /dev/null @@ -1,350 +0,0 @@ -use std::{ - collections::{HashMap, HashSet, BTreeSet}, - fs, - path::PathBuf, -}; - -use failure::Error; -use tempfile::{TempDir, tempdir}; - -use librojo::{ - imfs::{Imfs, ImfsItem, ImfsFile, ImfsDirectory}, -}; - -#[allow(unused)] -enum FsEvent { - Created(PathBuf), - Updated(PathBuf), - Removed(PathBuf), - Moved(PathBuf, PathBuf), -} - -fn send_events(imfs: &mut Imfs, events: &[FsEvent]) -> Result<(), Error> { - for event in events { - match event { - FsEvent::Created(path) => imfs.path_created(path)?, - FsEvent::Updated(path) => imfs.path_updated(path)?, - FsEvent::Removed(path) => imfs.path_removed(path)?, - FsEvent::Moved(from, to) => imfs.path_moved(from, to)?, - } - } - - Ok(()) -} - -#[derive(Debug, Clone, PartialEq)] -struct ExpectedImfs { - roots: HashSet, - items: HashMap, -} - -struct TestResources { - foo_path: PathBuf, - bar_path: PathBuf, - baz_path: PathBuf, -} - -fn check_expected(real: &Imfs, expected: &ExpectedImfs) { - assert_eq!(real.get_roots(), &expected.roots); - - let real_items = real.get_items(); - if real_items != &expected.items { - let real_str = serde_json::to_string(real_items).unwrap(); - let expected_str = serde_json::to_string(&expected.items).unwrap(); - - panic!("Items differed!\nReal:\n{}\nExpected:\n{}\n", real_str, expected_str); - } -} - -fn base_tree() -> Result<(TempDir, Imfs, ExpectedImfs, TestResources), Error> { - let root = tempdir()?; - - let foo_path = root.path().join("foo"); - let bar_path = root.path().join("bar.txt"); - let baz_path = foo_path.join("baz.txt"); - - let resources = TestResources { - foo_path: foo_path.clone(), - bar_path: bar_path.clone(), - baz_path: baz_path.clone(), - }; - - fs::create_dir(&foo_path)?; - fs::write(&bar_path, b"bar")?; - fs::write(&baz_path, b"baz")?; - - let mut imfs = Imfs::new(); - imfs.add_root(root.path())?; - - let mut expected_roots = HashSet::new(); - expected_roots.insert(root.path().to_path_buf()); - - let root_item = { - let mut children = BTreeSet::new(); - children.insert(foo_path.clone()); - children.insert(bar_path.clone()); - - ImfsItem::Directory(ImfsDirectory { - path: root.path().to_path_buf(), - children, - }) - }; - - let foo_item = { - let mut children = BTreeSet::new(); - children.insert(baz_path.clone()); - - ImfsItem::Directory(ImfsDirectory { - path: foo_path.clone(), - children, - }) - }; - - let bar_item = ImfsItem::File(ImfsFile { - path: bar_path.clone(), - contents: b"bar".to_vec(), - }); - - let baz_item = ImfsItem::File(ImfsFile { - path: baz_path.clone(), - contents: b"baz".to_vec(), - }); - - let mut expected_items = HashMap::new(); - expected_items.insert(root.path().to_path_buf(), root_item); - expected_items.insert(foo_path.clone(), foo_item); - expected_items.insert(bar_path.clone(), bar_item); - expected_items.insert(baz_path.clone(), baz_item); - - let expected_imfs = ExpectedImfs { - roots: expected_roots, - items: expected_items, - }; - - Ok((root, imfs, expected_imfs, resources)) -} - -#[test] -fn initial_read() -> Result<(), Error> { - let (_root, imfs, expected_imfs, _resources) = base_tree()?; - - check_expected(&imfs, &expected_imfs); - - Ok(()) -} - -#[test] -fn adding_files() -> Result<(), Error> { - let (root, mut imfs, mut expected_imfs, resources) = base_tree()?; - - check_expected(&imfs, &expected_imfs); - - let add_one_path = root.path().join("add_one.txt"); - let add_two_path = resources.foo_path.join("add_two.txt"); - - fs::write(&add_one_path, b"add_one")?; - fs::write(&add_two_path, b"add_two")?; - - match expected_imfs.items.get_mut(root.path()) { - Some(ImfsItem::Directory(directory)) => { - directory.children.insert(add_one_path.clone()); - }, - _ => unreachable!(), - } - - match expected_imfs.items.get_mut(&resources.foo_path) { - Some(ImfsItem::Directory(directory)) => { - directory.children.insert(add_two_path.clone()); - }, - _ => unreachable!(), - } - - expected_imfs.items.insert(add_one_path.clone(), ImfsItem::File(ImfsFile { - path: add_one_path.clone(), - contents: b"add_one".to_vec(), - })); - - expected_imfs.items.insert(add_two_path.clone(), ImfsItem::File(ImfsFile { - path: add_two_path.clone(), - contents: b"add_two".to_vec(), - })); - - imfs.path_created(&add_one_path)?; - imfs.path_created(&add_two_path)?; - - check_expected(&imfs, &expected_imfs); - - Ok(()) -} - -#[test] -fn adding_folder() -> Result<(), Error> { - let (root, imfs, mut expected_imfs, _resources) = base_tree()?; - - check_expected(&imfs, &expected_imfs); - - let folder_path = root.path().join("folder"); - let file1_path = folder_path.join("file1.txt"); - let file2_path = folder_path.join("file2.txt"); - - fs::create_dir(&folder_path)?; - fs::write(&file1_path, b"file1")?; - fs::write(&file2_path, b"file2")?; - - match expected_imfs.items.get_mut(root.path()) { - Some(ImfsItem::Directory(directory)) => { - directory.children.insert(folder_path.clone()); - }, - _ => unreachable!(), - } - - let folder_item = { - let mut children = BTreeSet::new(); - children.insert(file1_path.clone()); - children.insert(file2_path.clone()); - - ImfsItem::Directory(ImfsDirectory { - path: folder_path.clone(), - children, - }) - }; - - expected_imfs.items.insert(folder_path.clone(), folder_item); - - let file1_item = ImfsItem::File(ImfsFile { - path: file1_path.clone(), - contents: b"file1".to_vec(), - }); - expected_imfs.items.insert(file1_path.clone(), file1_item); - - let file2_item = ImfsItem::File(ImfsFile { - path: file2_path.clone(), - contents: b"file2".to_vec(), - }); - expected_imfs.items.insert(file2_path.clone(), file2_item); - - let possible_event_sequences = vec![ - vec![ - FsEvent::Created(folder_path.clone()) - ], - vec![ - FsEvent::Created(folder_path.clone()), - FsEvent::Created(file1_path.clone()), - FsEvent::Created(file2_path.clone()), - ], - vec![ - FsEvent::Created(file1_path.clone()), - FsEvent::Created(file2_path.clone()), - FsEvent::Created(folder_path.clone()), - ], - vec![ - FsEvent::Created(file1_path.clone()), - FsEvent::Created(folder_path.clone()), - FsEvent::Created(file2_path.clone()), - ], - ]; - - for events in &possible_event_sequences { - let mut imfs = imfs.clone(); - - send_events(&mut imfs, events)?; - check_expected(&imfs, &expected_imfs); - } - - Ok(()) -} - -#[test] -fn updating_files() -> Result<(), Error> { - let (_root, mut imfs, mut expected_imfs, resources) = base_tree()?; - - check_expected(&imfs, &expected_imfs); - - fs::write(&resources.bar_path, b"bar updated")?; - fs::write(&resources.baz_path, b"baz updated")?; - - imfs.path_updated(&resources.bar_path)?; - imfs.path_updated(&resources.baz_path)?; - - let bar_updated_item = ImfsItem::File(ImfsFile { - path: resources.bar_path.clone(), - contents: b"bar updated".to_vec(), - }); - let baz_updated_item = ImfsItem::File(ImfsFile { - path: resources.baz_path.clone(), - contents: b"baz updated".to_vec(), - }); - - expected_imfs.items.insert(resources.bar_path.clone(), bar_updated_item); - expected_imfs.items.insert(resources.baz_path.clone(), baz_updated_item); - - check_expected(&imfs, &expected_imfs); - - Ok(()) -} - -#[test] -fn removing_file() -> Result<(), Error> { - let (root, mut imfs, mut expected_imfs, resources) = base_tree()?; - - check_expected(&imfs, &expected_imfs); - - fs::remove_file(&resources.bar_path)?; - - imfs.path_removed(&resources.bar_path)?; - - match expected_imfs.items.get_mut(root.path()) { - Some(ImfsItem::Directory(directory)) => { - directory.children.remove(&resources.bar_path); - }, - _ => unreachable!(), - } - - expected_imfs.items.remove(&resources.bar_path); - - check_expected(&imfs, &expected_imfs); - - Ok(()) -} - -#[test] -fn removing_folder() -> Result<(), Error> { - let (root, imfs, mut expected_imfs, resources) = base_tree()?; - - check_expected(&imfs, &expected_imfs); - - fs::remove_dir_all(&resources.foo_path)?; - - match expected_imfs.items.get_mut(root.path()) { - Some(ImfsItem::Directory(directory)) => { - directory.children.remove(&resources.foo_path); - }, - _ => unreachable!(), - } - - expected_imfs.items.remove(&resources.foo_path); - expected_imfs.items.remove(&resources.baz_path); - - let possible_event_sequences = vec![ - vec![ - FsEvent::Removed(resources.foo_path.clone()), - ], - vec![ - FsEvent::Removed(resources.baz_path.clone()), - FsEvent::Removed(resources.foo_path.clone()), - ], - vec![ - FsEvent::Removed(resources.foo_path.clone()), - FsEvent::Removed(resources.baz_path.clone()), - ], - ]; - - for events in &possible_event_sequences { - let mut imfs = imfs.clone(); - - send_events(&mut imfs, events)?; - check_expected(&imfs, &expected_imfs); - } - - Ok(()) -} \ No newline at end of file diff --git a/server/tests/malformed_projects.rs b/server/tests/malformed_projects.rs deleted file mode 100644 index 8910c178..00000000 --- a/server/tests/malformed_projects.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::{ - path::{Path, PathBuf}, - sync::Arc, -}; - -use librojo::{ - live_session::LiveSession, - project::Project, -}; - -lazy_static::lazy_static! { - static ref TEST_PROJECTS_ROOT: PathBuf = { - Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects") - }; -} - -#[test] -fn bad_json_model() { - let project = Project::load_fuzzy(&TEST_PROJECTS_ROOT.join("bad_json_model")) - .expect("Project file didn't load"); - - if LiveSession::new(Arc::new(project)).is_ok() { - panic!("Project should not have succeeded"); - } -} - -#[test] -fn bad_meta_lua_classname() { - let project = Project::load_fuzzy(&TEST_PROJECTS_ROOT.join("bad_meta_lua_classname")) - .expect("Project file didn't load"); - - if LiveSession::new(Arc::new(project)).is_ok() { - panic!("Project should not have succeeded"); - } -} - -#[test] -fn bad_meta_rbxmx_properties() { - let project = Project::load_fuzzy(&TEST_PROJECTS_ROOT.join("bad_meta_rbxmx_properties")) - .expect("Project file didn't load"); - - if LiveSession::new(Arc::new(project)).is_ok() { - panic!("Project should not have succeeded"); - } -} - -#[test] -fn bad_missing_files() { - let project = Project::load_fuzzy(&TEST_PROJECTS_ROOT.join("bad_missing_files")) - .expect("Project file didn't load"); - - if LiveSession::new(Arc::new(project)).is_ok() { - panic!("Project should not have succeeded"); - } -} \ No newline at end of file diff --git a/server/tests/snapshot_reconciler.rs b/server/tests/snapshot_reconciler.rs deleted file mode 100644 index 02bfd5a9..00000000 --- a/server/tests/snapshot_reconciler.rs +++ /dev/null @@ -1,111 +0,0 @@ -mod test_util; - -use std::collections::HashMap; - -use rbx_dom_weak::{RbxTree, RbxInstanceProperties}; - -use librojo::{ - snapshot_reconciler::{RbxSnapshotInstance, reconcile_subtree}, -}; - -use test_util::tree::trees_equal; - -#[test] -fn patch_communicativity() { - let base_tree = RbxTree::new(RbxInstanceProperties { - name: "DataModel".into(), - class_name: "DataModel".into(), - properties: HashMap::new(), - }); - - let patch_a = RbxSnapshotInstance { - name: "DataModel".into(), - class_name: "DataModel".into(), - children: vec![ - RbxSnapshotInstance { - name: "Child-A".into(), - class_name: "Folder".into(), - ..Default::default() - }, - ], - ..Default::default() - }; - - let patch_b = RbxSnapshotInstance { - name: "DataModel".into(), - class_name: "DataModel".into(), - children: vec![ - RbxSnapshotInstance { - name: "Child-B".into(), - class_name: "Folder".into(), - ..Default::default() - }, - ], - ..Default::default() - }; - - let patch_combined = RbxSnapshotInstance { - name: "DataModel".into(), - class_name: "DataModel".into(), - children: vec![ - RbxSnapshotInstance { - name: "Child-A".into(), - class_name: "Folder".into(), - ..Default::default() - }, - RbxSnapshotInstance { - name: "Child-B".into(), - class_name: "Folder".into(), - ..Default::default() - }, - ], - ..Default::default() - }; - - let root_id = base_tree.get_root_id(); - - let mut tree_a = base_tree.clone(); - - reconcile_subtree( - &mut tree_a, - root_id, - &patch_a, - &mut Default::default(), - &mut Default::default(), - &mut Default::default(), - ); - - reconcile_subtree( - &mut tree_a, - root_id, - &patch_combined, - &mut Default::default(), - &mut Default::default(), - &mut Default::default(), - ); - - let mut tree_b = base_tree.clone(); - - reconcile_subtree( - &mut tree_b, - root_id, - &patch_b, - &mut Default::default(), - &mut Default::default(), - &mut Default::default(), - ); - - reconcile_subtree( - &mut tree_b, - root_id, - &patch_combined, - &mut Default::default(), - &mut Default::default(), - &mut Default::default(), - ); - - match trees_equal(&tree_a, &tree_b) { - Ok(_) => {} - Err(e) => panic!("{}", e), - } -} \ No newline at end of file diff --git a/server/tests/snapshot_snapshots.rs b/server/tests/snapshot_snapshots.rs deleted file mode 100644 index 21bad786..00000000 --- a/server/tests/snapshot_snapshots.rs +++ /dev/null @@ -1,68 +0,0 @@ -mod test_util; - -use std::path::Path; - -use librojo::{ - imfs::Imfs, - project::Project, - rbx_snapshot::{SnapshotContext, snapshot_project_tree}, -}; - -use crate::test_util::{ - snapshot::*, -}; - -macro_rules! generate_snapshot_tests { - ($($name: ident),*) => { - $( - paste::item! { - #[test] - fn []() { - let _ = env_logger::try_init(); - - let tests_folder = Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects"); - let project_folder = tests_folder.join(stringify!($name)); - run_snapshot_test(&project_folder); - } - } - )* - }; -} - -generate_snapshot_tests!( - empty, - json_model, - meta_files, - multi_partition_game, - nested_partitions, - single_partition_game, - single_partition_model, - transmute_partition -); - -fn run_snapshot_test(path: &Path) { - println!("Running snapshot from project: {}", path.display()); - - let project = Project::load_fuzzy(path) - .expect("Couldn't load project file for snapshot test"); - - let mut imfs = Imfs::new(); - imfs.add_roots_from_project(&project) - .expect("Could not add IMFS roots to snapshot project"); - - let context = SnapshotContext { - plugin_context: None, - }; - - let mut snapshot = snapshot_project_tree(&context, &imfs, &project) - .expect("Could not generate snapshot for snapshot test"); - - if let Some(snapshot) = snapshot.as_mut() { - anonymize_snapshot(path, snapshot); - } - - match read_expected_snapshot(path) { - Some(expected_snapshot) => assert_eq!(snapshot, expected_snapshot), - None => write_expected_snapshot(path, &snapshot), - } -} \ No newline at end of file diff --git a/server/tests/test_util/mod.rs b/server/tests/test_util/mod.rs deleted file mode 100644 index 5988865d..00000000 --- a/server/tests/test_util/mod.rs +++ /dev/null @@ -1,36 +0,0 @@ -#![allow(dead_code)] - -use std::fs::{create_dir, copy}; -use std::path::Path; -use std::io; - -use walkdir::WalkDir; - -pub mod snapshot; -pub mod tree; - -pub fn copy_recursive(from: &Path, to: &Path) -> io::Result<()> { - for entry in WalkDir::new(from) { - let entry = entry?; - let path = entry.path(); - let new_path = to.join(path.strip_prefix(from).unwrap()); - - let file_type = entry.file_type(); - - if file_type.is_dir() { - match create_dir(new_path) { - Ok(_) => {}, - Err(err) => match err.kind() { - io::ErrorKind::AlreadyExists => {}, - _ => panic!(err), - } - } - } else if file_type.is_file() { - copy(path, new_path)?; - } else { - unimplemented!("no symlinks please"); - } - } - - Ok(()) -} \ No newline at end of file diff --git a/server/tests/test_util/snapshot.rs b/server/tests/test_util/snapshot.rs deleted file mode 100644 index 43088684..00000000 --- a/server/tests/test_util/snapshot.rs +++ /dev/null @@ -1,79 +0,0 @@ -use std::{ - fs::{self, File}, - path::{Path, PathBuf}, -}; - -use librojo::{ - project::ProjectNode, - snapshot_reconciler::RbxSnapshotInstance, - rbx_session::MetadataPerInstance, -}; - -const SNAPSHOT_EXPECTED_NAME: &str = "expected-snapshot.json"; - -/// Snapshots contain absolute paths, which simplifies much of Rojo. -/// -/// For saving snapshots to the disk, we should strip off the project folder -/// path to make them machine-independent. This doesn't work for paths that fall -/// outside of the project folder, but that's okay here. -/// -/// We also need to sort children, since Rojo tends to enumerate the filesystem -/// in an unpredictable order. -pub fn anonymize_snapshot(project_folder_path: &Path, snapshot: &mut RbxSnapshotInstance) { - anonymize_metadata(project_folder_path, &mut snapshot.metadata); - - snapshot.children.sort_by(|a, b| a.partial_cmp(b).unwrap()); - - for child in snapshot.children.iter_mut() { - anonymize_snapshot(project_folder_path, child); - } -} - -pub fn anonymize_metadata(project_folder_path: &Path, metadata: &mut MetadataPerInstance) { - match metadata.source_path.as_mut() { - Some(path) => *path = anonymize_path(project_folder_path, path), - None => {}, - } - - match metadata.project_definition.as_mut() { - Some((_, project_node)) => anonymize_project_node(project_folder_path, project_node), - None => {}, - } -} - -pub fn anonymize_project_node(project_folder_path: &Path, project_node: &mut ProjectNode) { - match project_node.path.as_mut() { - Some(path) => *path = anonymize_path(project_folder_path, path), - None => {}, - } - - for child_node in project_node.children.values_mut() { - anonymize_project_node(project_folder_path, child_node); - } -} - -pub fn anonymize_path(project_folder_path: &Path, path: &Path) -> PathBuf { - if path.is_absolute() { - path.strip_prefix(project_folder_path) - .expect("Could not anonymize absolute path") - .to_path_buf() - } else { - path.to_path_buf() - } -} - -pub fn read_expected_snapshot(path: &Path) -> Option>> { - let contents = fs::read(path.join(SNAPSHOT_EXPECTED_NAME)).ok()?; - let snapshot: Option> = serde_json::from_slice(&contents) - .expect("Could not deserialize snapshot"); - - Some(snapshot) -} - -pub fn write_expected_snapshot(path: &Path, snapshot: &Option) { - let mut file = File::create(path.join(SNAPSHOT_EXPECTED_NAME)) - .expect("Could not open file to write snapshot"); - - serde_json::to_writer_pretty(&mut file, snapshot) - .expect("Could not serialize snapshot to file"); -} \ No newline at end of file diff --git a/server/tests/test_util/tree.rs b/server/tests/test_util/tree.rs deleted file mode 100644 index 4d4ff3b1..00000000 --- a/server/tests/test_util/tree.rs +++ /dev/null @@ -1,351 +0,0 @@ -//! Defines a mechanism to compare two RbxTree objects and generate a useful -//! diff if they aren't the same. These methods ignore IDs, which are randomly -//! generated whenever a tree is constructed anyways. This makes matching up -//! pairs of instances that should be the same potentially difficult. -//! -//! It relies on a couple different ideas: -//! - Instances with the same name and class name are matched as the same -//! instance. See basic_equal for this logic -//! - A path of period-delimited names (like Roblox's GetFullName) should be -//! enough to debug most issues. If it isn't, we can do something fun like -//! generate GraphViz graphs. - -use std::{ - borrow::Cow, - collections::{HashMap, HashSet}, - fmt, - fs::{self, File}, - hash::Hash, - path::{Path, PathBuf}, -}; - -use log::error; -use serde::{Serialize, Deserialize}; -use rbx_dom_weak::{RbxId, RbxTree}; - -use librojo::{ - rbx_session::MetadataPerInstance, - live_session::LiveSession, - visualize::{VisualizeRbxTree, graphviz_to_svg}, -}; - -use super::snapshot::anonymize_metadata; - -/// Marks a 'step' in the test, which will snapshot the session's current -/// RbxTree object and compare it against the saved snapshot if it exists. -pub fn tree_step(step: &str, live_session: &LiveSession, source_path: &Path) { - let rbx_session = live_session.rbx_session.lock().unwrap(); - let tree = rbx_session.get_tree(); - - let project_folder = live_session.root_project().folder_location(); - let metadata = rbx_session.get_all_instance_metadata() - .iter() - .map(|(key, meta)| { - let mut meta = meta.clone(); - anonymize_metadata(project_folder, &mut meta); - (*key, meta) - }) - .collect(); - - let tree_with_metadata = TreeWithMetadata { - tree: Cow::Borrowed(&tree), - metadata: Cow::Owned(metadata), - }; - - match read_tree_by_name(source_path, step) { - Some(expected) => match trees_and_metadata_equal(&expected, &tree_with_metadata) { - Ok(_) => {} - Err(e) => { - error!("Trees at step '{}' were not equal.\n{}", step, e); - - let expected_gv = format!("{}", VisualizeRbxTree { - tree: &expected.tree, - metadata: &expected.metadata, - }); - - let actual_gv = format!("{}", VisualizeRbxTree { - tree: &tree_with_metadata.tree, - metadata: &tree_with_metadata.metadata, - }); - - let output_dir = PathBuf::from("failed-snapshots"); - fs::create_dir_all(&output_dir) - .expect("Could not create failed-snapshots directory"); - - let expected_basename = format!("{}-{}-expected", live_session.root_project().name, step); - let actual_basename = format!("{}-{}-actual", live_session.root_project().name, step); - - let mut expected_out = output_dir.join(expected_basename); - let mut actual_out = output_dir.join(actual_basename); - - match (graphviz_to_svg(&expected_gv), graphviz_to_svg(&actual_gv)) { - (Some(expected_svg), Some(actual_svg)) => { - expected_out.set_extension("svg"); - actual_out.set_extension("svg"); - - fs::write(&expected_out, expected_svg) - .expect("Couldn't write expected SVG"); - - fs::write(&actual_out, actual_svg) - .expect("Couldn't write actual SVG"); - } - _ => { - expected_out.set_extension("gv"); - actual_out.set_extension("gv"); - - fs::write(&expected_out, expected_gv) - .expect("Couldn't write expected GV"); - - fs::write(&actual_out, actual_gv) - .expect("Couldn't write actual GV"); - } - } - - error!("Output at {} and {}", expected_out.display(), actual_out.display()); - - panic!("Tree mismatch at step '{}'", step); - } - } - None => { - write_tree_by_name(source_path, step, &tree_with_metadata); - } - } -} - -fn new_cow_map() -> Cow<'static, HashMap> { - Cow::Owned(HashMap::new()) -} - -#[derive(Debug, Serialize, Deserialize)] -struct TreeWithMetadata<'a> { - #[serde(flatten)] - pub tree: Cow<'a, RbxTree>, - - #[serde(default = "new_cow_map")] - pub metadata: Cow<'a, HashMap>, -} - -fn read_tree_by_name(path: &Path, identifier: &str) -> Option> { - let mut file_path = path.join(identifier); - file_path.set_extension("tree.json"); - - let contents = fs::read(&file_path).ok()?; - let tree: TreeWithMetadata = serde_json::from_slice(&contents) - .expect("Could not deserialize tree"); - - Some(tree) -} - -fn write_tree_by_name(path: &Path, identifier: &str, tree: &TreeWithMetadata) { - let mut file_path = path.join(identifier); - file_path.set_extension("tree.json"); - - let mut file = File::create(file_path) - .expect("Could not open file to write tree"); - - serde_json::to_writer_pretty(&mut file, tree) - .expect("Could not serialize tree to file"); -} - -#[derive(Debug)] -pub struct TreeMismatch { - pub path: Cow<'static, str>, - pub detail: Cow<'static, str>, -} - -impl TreeMismatch { - pub fn new<'a, A: Into>, B: Into>>(path: A, detail: B) -> TreeMismatch { - TreeMismatch { - path: Cow::Owned(path.into().into_owned()), - detail: Cow::Owned(detail.into().into_owned()), - } - } - - fn add_parent(mut self, name: &str) -> TreeMismatch { - self.path.to_mut().insert(0, '.'); - self.path.to_mut().insert_str(0, name); - - TreeMismatch { - path: self.path, - detail: self.detail, - } - } -} - -impl fmt::Display for TreeMismatch { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - writeln!(formatter, "Tree mismatch at path {}", self.path)?; - writeln!(formatter, "{}", self.detail) - } -} - -pub fn trees_equal( - left_tree: &RbxTree, - right_tree: &RbxTree, -) -> Result<(), TreeMismatch> { - let left = TreeWithMetadata { - tree: Cow::Borrowed(left_tree), - metadata: Cow::Owned(HashMap::new()), - }; - - let right = TreeWithMetadata { - tree: Cow::Borrowed(right_tree), - metadata: Cow::Owned(HashMap::new()), - }; - - trees_and_metadata_equal(&left, &right) -} - -fn trees_and_metadata_equal( - left_tree: &TreeWithMetadata, - right_tree: &TreeWithMetadata, -) -> Result<(), TreeMismatch> { - let left_id = left_tree.tree.get_root_id(); - let right_id = right_tree.tree.get_root_id(); - - instances_equal(left_tree, left_id, right_tree, right_id) -} - -fn instances_equal( - left_tree: &TreeWithMetadata, - left_id: RbxId, - right_tree: &TreeWithMetadata, - right_id: RbxId, -) -> Result<(), TreeMismatch> { - basic_equal(left_tree, left_id, right_tree, right_id)?; - properties_equal(left_tree, left_id, right_tree, right_id)?; - children_equal(left_tree, left_id, right_tree, right_id)?; - metadata_equal(left_tree, left_id, right_tree, right_id) -} - -fn basic_equal( - left_tree: &TreeWithMetadata, - left_id: RbxId, - right_tree: &TreeWithMetadata, - right_id: RbxId, -) -> Result<(), TreeMismatch> { - let left_instance = left_tree.tree.get_instance(left_id) - .expect("ID did not exist in left tree"); - - let right_instance = right_tree.tree.get_instance(right_id) - .expect("ID did not exist in right tree"); - - if left_instance.name != right_instance.name { - let message = format!("Name did not match ('{}' vs '{}')", left_instance.name, right_instance.name); - - return Err(TreeMismatch::new(&left_instance.name, message)); - } - - if left_instance.class_name != right_instance.class_name { - let message = format!("Class name did not match ('{}' vs '{}')", left_instance.class_name, right_instance.class_name); - - return Err(TreeMismatch::new(&left_instance.name, message)); - } - - Ok(()) -} - -fn properties_equal( - left_tree: &TreeWithMetadata, - left_id: RbxId, - right_tree: &TreeWithMetadata, - right_id: RbxId, -) -> Result<(), TreeMismatch> { - let left_instance = left_tree.tree.get_instance(left_id) - .expect("ID did not exist in left tree"); - - let right_instance = right_tree.tree.get_instance(right_id) - .expect("ID did not exist in right tree"); - - let mut visited = HashSet::new(); - - for (key, left_value) in &left_instance.properties { - visited.insert(key); - - let right_value = right_instance.properties.get(key); - - if Some(left_value) != right_value { - let message = format!( - "Property {}:\n\tLeft: {:?}\n\tRight: {:?}", - key, - Some(left_value), - right_value, - ); - - return Err(TreeMismatch::new(&left_instance.name, message)); - } - } - - for (key, right_value) in &right_instance.properties { - if visited.contains(key) { - continue; - } - - let left_value = left_instance.properties.get(key); - - if left_value != Some(right_value) { - let message = format!( - "Property {}:\n\tLeft: {:?}\n\tRight: {:?}", - key, - left_value, - Some(right_value), - ); - - return Err(TreeMismatch::new(&left_instance.name, message)); - } - } - - Ok(()) -} - -fn children_equal( - left_tree: &TreeWithMetadata, - left_id: RbxId, - right_tree: &TreeWithMetadata, - right_id: RbxId, -) -> Result<(), TreeMismatch> { - let left_instance = left_tree.tree.get_instance(left_id) - .expect("ID did not exist in left tree"); - - let right_instance = right_tree.tree.get_instance(right_id) - .expect("ID did not exist in right tree"); - - let left_children = left_instance.get_children_ids(); - let right_children = right_instance.get_children_ids(); - - if left_children.len() != right_children.len() { - return Err(TreeMismatch::new(&left_instance.name, "Instances had different numbers of children")); - } - - for (left_child_id, right_child_id) in left_children.iter().zip(right_children) { - instances_equal(left_tree, *left_child_id, right_tree, *right_child_id) - .map_err(|e| e.add_parent(&left_instance.name))?; - } - - Ok(()) -} - -fn metadata_equal( - left_tree: &TreeWithMetadata, - left_id: RbxId, - right_tree: &TreeWithMetadata, - right_id: RbxId, -) -> Result<(), TreeMismatch> { - let left_meta = left_tree.metadata.get(&left_id); - let right_meta = right_tree.metadata.get(&right_id); - - if left_meta != right_meta { - let left_instance = left_tree.tree.get_instance(left_id) - .expect("Left instance didn't exist in tree"); - - let message = format!( - "Metadata mismatch:\n\tLeft: {:?}\n\tRight: {:?}", - left_meta, - right_meta, - ); - - return Err(TreeMismatch::new(&left_instance.name, message)); - } - - Ok(()) -} \ No newline at end of file diff --git a/server/tests/tree_snapshots.rs b/server/tests/tree_snapshots.rs deleted file mode 100644 index d8f2d849..00000000 --- a/server/tests/tree_snapshots.rs +++ /dev/null @@ -1,77 +0,0 @@ -mod test_util; - -use std::{ - fs, - path::{Path, PathBuf}, - sync::Arc, - thread, - time::Duration, -}; - -use tempfile::{tempdir, TempDir}; - -use librojo::{ - live_session::LiveSession, - project::Project, -}; - -use crate::test_util::{ - copy_recursive, - tree::tree_step, -}; - -#[test] -fn multi_partition_game() { - let _ = env_logger::try_init(); - let source_path = project_path("multi_partition_game"); - - let (dir, live_session) = start_session(&source_path); - tree_step("initial", &live_session, &source_path); - - let added_path = dir.path().join("a/added"); - fs::create_dir_all(&added_path) - .expect("Couldn't create directory"); - thread::sleep(Duration::from_millis(250)); - - tree_step("with_dir", &live_session, &source_path); - - let moved_path = dir.path().join("b/added"); - fs::rename(&added_path, &moved_path) - .expect("Couldn't rename directory"); - thread::sleep(Duration::from_millis(250)); - - tree_step("with_moved_dir", &live_session, &source_path); -} - -#[test] -fn spawn_location() { - let _ = env_logger::try_init(); - let source_path = project_path("spawn_location"); - - let (_dir, live_session) = start_session(&source_path); - tree_step("initial", &live_session, &source_path); -} - -/// Find the path to the given test project relative to the manifest. -fn project_path(name: &str) -> PathBuf { - let mut path = Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects"); - path.push(name); - path -} - -/// Starts a new LiveSession for the project located at the given file path. -fn start_session(source_path: &Path) -> (TempDir, LiveSession) { - let dir = tempdir() - .expect("Couldn't create temporary directory"); - - copy_recursive(&source_path, dir.path()) - .expect("Couldn't copy project to temporary directory"); - - let project = Arc::new(Project::load_fuzzy(dir.path()) - .expect("Couldn't load project from temp directory")); - - let live_session = LiveSession::new(Arc::clone(&project)) - .expect("Couldn't start live session"); - - (dir, live_session) -} \ No newline at end of file diff --git a/test-projects/empty/expected-snapshot.json b/test-projects/empty/expected-snapshot.json deleted file mode 100644 index 266896f3..00000000 --- a/test-projects/empty/expected-snapshot.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "empty", - "class_name": "DataModel", - "properties": {}, - "children": [], - "metadata": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "empty", - { - "class_name": "DataModel", - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - } -} \ No newline at end of file diff --git a/test-projects/empty_folder/default.project.json b/test-projects/empty_folder/default.project.json new file mode 100644 index 00000000..5d67b95b --- /dev/null +++ b/test-projects/empty_folder/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "empty_folder", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/test-projects/empty_folder/src/.gitkeep b/test-projects/empty_folder/src/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/test-projects/json_model/expected-snapshot.json b/test-projects/json_model/expected-snapshot.json deleted file mode 100644 index e4f223d8..00000000 --- a/test-projects/json_model/expected-snapshot.json +++ /dev/null @@ -1,76 +0,0 @@ -{ - "name": "json_model", - "class_name": "Folder", - "properties": {}, - "children": [ - { - "name": "children", - "class_name": "Folder", - "properties": {}, - "children": [ - { - "name": "The Child", - "class_name": "StringValue", - "properties": {}, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": null, - "project_definition": null - } - } - ], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src/children.model.json", - "project_definition": null - } - }, - { - "name": "explicit", - "class_name": "StringValue", - "properties": { - "Value": { - "Type": "String", - "Value": "Hello, world!" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src/explicit.model.json", - "project_definition": null - } - }, - { - "name": "implicit", - "class_name": "StringValue", - "properties": { - "Value": { - "Type": "String", - "Value": "What's happenin', Earth?" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src/implicit.model.json", - "project_definition": null - } - } - ], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src", - "project_definition": [ - "json_model", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "src" - } - ] - } -} \ No newline at end of file diff --git a/test-projects/meta_files/expected-snapshot.json b/test-projects/meta_files/expected-snapshot.json deleted file mode 100644 index d2f68f1f..00000000 --- a/test-projects/meta_files/expected-snapshot.json +++ /dev/null @@ -1,129 +0,0 @@ -{ - "name": "test-model", - "class_name": "Tool", - "properties": { - "Enabled": { - "Type": "Bool", - "Value": true - } - }, - "children": [ - { - "name": "A", - "class_name": "Folder", - "properties": {}, - "children": [], - "metadata": { - "ignore_unknown_instances": true, - "source_path": "src/A", - "project_definition": null - } - }, - { - "name": "DisableMe", - "class_name": "Script", - "properties": { - "Disabled": { - "Type": "Bool", - "Value": true - }, - "Source": { - "Type": "String", - "Value": "" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": true, - "source_path": "src/DisableMe.server.lua", - "project_definition": null - } - }, - { - "name": "LocalizationTable", - "class_name": "LocalizationTable", - "properties": { - "Contents": { - "Type": "String", - "Value": "[{\"key\":\"Doge\",\"example\":\"A funny dog\",\"source\":\"Perro!\",\"values\":{\"en\":\"Doge!\"}}]" - }, - "SourceLocaleId": { - "Type": "String", - "Value": "es" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src/LocalizationTable.csv", - "project_definition": null - } - }, - { - "name": "RobloxInstance", - "class_name": "Folder", - "properties": { - "Tags": { - "Type": "BinaryString", - "Value": "" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": true, - "source_path": "src/RobloxInstance.rbxmx", - "project_definition": null - } - }, - { - "name": "Script", - "class_name": "Script", - "properties": { - "Source": { - "Type": "String", - "Value": "print(\"Hello, world\")" - }, - "Disabled": { - "Type": "Bool", - "Value": true - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src/Script", - "project_definition": null - } - }, - { - "name": "StringValue", - "class_name": "StringValue", - "properties": { - "Value": { - "Type": "String", - "Value": "I'm supposed to put funny text here, aren't I? Oh well." - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": true, - "source_path": "src/StringValue.txt", - "project_definition": null - } - } - ], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src", - "project_definition": [ - "test-model", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "src" - } - ] - } -} \ No newline at end of file diff --git a/test-projects/multi_partition_game/expected-snapshot.json b/test-projects/multi_partition_game/expected-snapshot.json deleted file mode 100644 index 49e76960..00000000 --- a/test-projects/multi_partition_game/expected-snapshot.json +++ /dev/null @@ -1,212 +0,0 @@ -{ - "name": "multi_partition_game", - "class_name": "DataModel", - "properties": {}, - "children": [ - { - "name": "HttpService", - "class_name": "HttpService", - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "HttpService", - { - "class_name": "HttpService", - "children": {}, - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "ignore_unknown_instances": null, - "path": null - } - ] - } - }, - { - "name": "ReplicatedStorage", - "class_name": "ReplicatedStorage", - "properties": {}, - "children": [ - { - "name": "Ack", - "class_name": "Folder", - "properties": {}, - "children": [ - { - "name": "foo", - "class_name": "StringValue", - "properties": { - "Value": { - "Type": "String", - "Value": "Hello world, from a/foo.txt" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "a/foo.txt", - "project_definition": null - } - }, - { - "name": "main", - "class_name": "ModuleScript", - "properties": { - "Source": { - "Type": "String", - "Value": "-- hello, from a/main.lua" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "a/main.lua", - "project_definition": null - } - } - ], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "a", - "project_definition": [ - "Ack", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - } - ] - } - }, - { - "name": "Bar", - "class_name": "Folder", - "properties": {}, - "children": [ - { - "name": "something", - "class_name": "ModuleScript", - "properties": { - "Source": { - "Type": "String", - "Value": "-- b/something.lua" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "b/something.lua", - "project_definition": null - } - } - ], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "b", - "project_definition": [ - "Bar", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - ] - } - } - ], - "metadata": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "ReplicatedStorage", - { - "class_name": "ReplicatedStorage", - "children": { - "Bar": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - }, - "Ack": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - } - } - ], - "metadata": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "multi_partition_game", - { - "class_name": "DataModel", - "children": { - "ReplicatedStorage": { - "class_name": "ReplicatedStorage", - "children": { - "Bar": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - }, - "Ack": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - }, - "HttpService": { - "class_name": "HttpService", - "children": {}, - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "ignore_unknown_instances": null, - "path": null - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - } -} \ No newline at end of file diff --git a/test-projects/multi_partition_game/initial.tree.json b/test-projects/multi_partition_game/initial.tree.json deleted file mode 100644 index 9b5d5f08..00000000 --- a/test-projects/multi_partition_game/initial.tree.json +++ /dev/null @@ -1,242 +0,0 @@ -{ - "instances": { - "00f207b1-fc18-4088-a45e-caf8cd98f5dd": { - "Name": "main", - "ClassName": "ModuleScript", - "Properties": { - "Source": { - "Type": "String", - "Value": "-- hello, from a/main.lua" - } - }, - "Id": "00f207b1-fc18-4088-a45e-caf8cd98f5dd", - "Children": [], - "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" - }, - "14fed1a3-ba97-46a6-ae93-ac26bd9471df": { - "Name": "Ack", - "ClassName": "Folder", - "Properties": {}, - "Id": "14fed1a3-ba97-46a6-ae93-ac26bd9471df", - "Children": [ - "c55fd55c-258e-4a93-a63a-ea243038c9b9", - "00f207b1-fc18-4088-a45e-caf8cd98f5dd" - ], - "Parent": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" - }, - "c910510c-37a8-4fd8-ae41-01169ccb739c": { - "Name": "Bar", - "ClassName": "Folder", - "Properties": {}, - "Id": "c910510c-37a8-4fd8-ae41-01169ccb739c", - "Children": [ - "71a95983-c856-4cf2-aee6-bd8a523e80e4" - ], - "Parent": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" - }, - "c55fd55c-258e-4a93-a63a-ea243038c9b9": { - "Name": "foo", - "ClassName": "StringValue", - "Properties": { - "Value": { - "Type": "String", - "Value": "Hello world, from a/foo.txt" - } - }, - "Id": "c55fd55c-258e-4a93-a63a-ea243038c9b9", - "Children": [], - "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" - }, - "71a95983-c856-4cf2-aee6-bd8a523e80e4": { - "Name": "something", - "ClassName": "ModuleScript", - "Properties": { - "Source": { - "Type": "String", - "Value": "-- b/something.lua" - } - }, - "Id": "71a95983-c856-4cf2-aee6-bd8a523e80e4", - "Children": [], - "Parent": "c910510c-37a8-4fd8-ae41-01169ccb739c" - }, - "3b5af13f-c997-4009-915c-0810b0e83032": { - "Name": "multi_partition_game", - "ClassName": "DataModel", - "Properties": {}, - "Id": "3b5af13f-c997-4009-915c-0810b0e83032", - "Children": [ - "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c", - "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" - ], - "Parent": null - }, - "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c": { - "Name": "HttpService", - "ClassName": "HttpService", - "Properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "Id": "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c", - "Children": [], - "Parent": "3b5af13f-c997-4009-915c-0810b0e83032" - }, - "99eefe5f-ef74-49e6-8a8b-c833e00ca56b": { - "Name": "ReplicatedStorage", - "ClassName": "ReplicatedStorage", - "Properties": {}, - "Id": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b", - "Children": [ - "14fed1a3-ba97-46a6-ae93-ac26bd9471df", - "c910510c-37a8-4fd8-ae41-01169ccb739c" - ], - "Parent": "3b5af13f-c997-4009-915c-0810b0e83032" - } - }, - "root_id": "3b5af13f-c997-4009-915c-0810b0e83032", - "metadata": { - "00f207b1-fc18-4088-a45e-caf8cd98f5dd": { - "ignore_unknown_instances": false, - "source_path": "a/main.lua", - "project_definition": null - }, - "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "HttpService", - { - "class_name": "HttpService", - "children": {}, - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "ignore_unknown_instances": null, - "path": null - } - ] - }, - "14fed1a3-ba97-46a6-ae93-ac26bd9471df": { - "ignore_unknown_instances": false, - "source_path": "a", - "project_definition": [ - "Ack", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - } - ] - }, - "c55fd55c-258e-4a93-a63a-ea243038c9b9": { - "ignore_unknown_instances": false, - "source_path": "a/foo.txt", - "project_definition": null - }, - "71a95983-c856-4cf2-aee6-bd8a523e80e4": { - "ignore_unknown_instances": false, - "source_path": "b/something.lua", - "project_definition": null - }, - "c910510c-37a8-4fd8-ae41-01169ccb739c": { - "ignore_unknown_instances": false, - "source_path": "b", - "project_definition": [ - "Bar", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - ] - }, - "99eefe5f-ef74-49e6-8a8b-c833e00ca56b": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "ReplicatedStorage", - { - "class_name": "ReplicatedStorage", - "children": { - "Ack": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - }, - "Bar": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - }, - "3b5af13f-c997-4009-915c-0810b0e83032": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "multi_partition_game", - { - "class_name": "DataModel", - "children": { - "HttpService": { - "class_name": "HttpService", - "children": {}, - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "ignore_unknown_instances": null, - "path": null - }, - "ReplicatedStorage": { - "class_name": "ReplicatedStorage", - "children": { - "Ack": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - }, - "Bar": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - } - } -} \ No newline at end of file diff --git a/test-projects/multi_partition_game/with_dir.tree.json b/test-projects/multi_partition_game/with_dir.tree.json deleted file mode 100644 index c8875416..00000000 --- a/test-projects/multi_partition_game/with_dir.tree.json +++ /dev/null @@ -1,256 +0,0 @@ -{ - "instances": { - "b48b369f-5706-4029-9fa6-90651a4910ea": { - "Name": "added", - "ClassName": "Folder", - "Properties": {}, - "Id": "b48b369f-5706-4029-9fa6-90651a4910ea", - "Children": [], - "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" - }, - "00f207b1-fc18-4088-a45e-caf8cd98f5dd": { - "Name": "main", - "ClassName": "ModuleScript", - "Properties": { - "Source": { - "Type": "String", - "Value": "-- hello, from a/main.lua" - } - }, - "Id": "00f207b1-fc18-4088-a45e-caf8cd98f5dd", - "Children": [], - "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" - }, - "14fed1a3-ba97-46a6-ae93-ac26bd9471df": { - "Name": "Ack", - "ClassName": "Folder", - "Properties": {}, - "Id": "14fed1a3-ba97-46a6-ae93-ac26bd9471df", - "Children": [ - "b48b369f-5706-4029-9fa6-90651a4910ea", - "c55fd55c-258e-4a93-a63a-ea243038c9b9", - "00f207b1-fc18-4088-a45e-caf8cd98f5dd" - ], - "Parent": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" - }, - "c910510c-37a8-4fd8-ae41-01169ccb739c": { - "Name": "Bar", - "ClassName": "Folder", - "Properties": {}, - "Id": "c910510c-37a8-4fd8-ae41-01169ccb739c", - "Children": [ - "71a95983-c856-4cf2-aee6-bd8a523e80e4" - ], - "Parent": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" - }, - "c55fd55c-258e-4a93-a63a-ea243038c9b9": { - "Name": "foo", - "ClassName": "StringValue", - "Properties": { - "Value": { - "Type": "String", - "Value": "Hello world, from a/foo.txt" - } - }, - "Id": "c55fd55c-258e-4a93-a63a-ea243038c9b9", - "Children": [], - "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" - }, - "71a95983-c856-4cf2-aee6-bd8a523e80e4": { - "Name": "something", - "ClassName": "ModuleScript", - "Properties": { - "Source": { - "Type": "String", - "Value": "-- b/something.lua" - } - }, - "Id": "71a95983-c856-4cf2-aee6-bd8a523e80e4", - "Children": [], - "Parent": "c910510c-37a8-4fd8-ae41-01169ccb739c" - }, - "3b5af13f-c997-4009-915c-0810b0e83032": { - "Name": "multi_partition_game", - "ClassName": "DataModel", - "Properties": {}, - "Id": "3b5af13f-c997-4009-915c-0810b0e83032", - "Children": [ - "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c", - "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" - ], - "Parent": null - }, - "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c": { - "Name": "HttpService", - "ClassName": "HttpService", - "Properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "Id": "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c", - "Children": [], - "Parent": "3b5af13f-c997-4009-915c-0810b0e83032" - }, - "99eefe5f-ef74-49e6-8a8b-c833e00ca56b": { - "Name": "ReplicatedStorage", - "ClassName": "ReplicatedStorage", - "Properties": {}, - "Id": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b", - "Children": [ - "14fed1a3-ba97-46a6-ae93-ac26bd9471df", - "c910510c-37a8-4fd8-ae41-01169ccb739c" - ], - "Parent": "3b5af13f-c997-4009-915c-0810b0e83032" - } - }, - "root_id": "3b5af13f-c997-4009-915c-0810b0e83032", - "metadata": { - "c55fd55c-258e-4a93-a63a-ea243038c9b9": { - "ignore_unknown_instances": false, - "source_path": "a/foo.txt", - "project_definition": null - }, - "99eefe5f-ef74-49e6-8a8b-c833e00ca56b": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "ReplicatedStorage", - { - "class_name": "ReplicatedStorage", - "children": { - "Ack": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - }, - "Bar": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - }, - "71a95983-c856-4cf2-aee6-bd8a523e80e4": { - "ignore_unknown_instances": false, - "source_path": "b/something.lua", - "project_definition": null - }, - "00f207b1-fc18-4088-a45e-caf8cd98f5dd": { - "ignore_unknown_instances": false, - "source_path": "a/main.lua", - "project_definition": null - }, - "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "HttpService", - { - "class_name": "HttpService", - "children": {}, - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "ignore_unknown_instances": null, - "path": null - } - ] - }, - "b48b369f-5706-4029-9fa6-90651a4910ea": { - "ignore_unknown_instances": false, - "source_path": "a/added", - "project_definition": null - }, - "3b5af13f-c997-4009-915c-0810b0e83032": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "multi_partition_game", - { - "class_name": "DataModel", - "children": { - "HttpService": { - "class_name": "HttpService", - "children": {}, - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "ignore_unknown_instances": null, - "path": null - }, - "ReplicatedStorage": { - "class_name": "ReplicatedStorage", - "children": { - "Ack": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - }, - "Bar": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - }, - "c910510c-37a8-4fd8-ae41-01169ccb739c": { - "ignore_unknown_instances": false, - "source_path": "b", - "project_definition": [ - "Bar", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - ] - }, - "14fed1a3-ba97-46a6-ae93-ac26bd9471df": { - "ignore_unknown_instances": false, - "source_path": "a", - "project_definition": [ - "Ack", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - } - ] - } - } -} \ No newline at end of file diff --git a/test-projects/multi_partition_game/with_moved_dir.tree.json b/test-projects/multi_partition_game/with_moved_dir.tree.json deleted file mode 100644 index 4e996829..00000000 --- a/test-projects/multi_partition_game/with_moved_dir.tree.json +++ /dev/null @@ -1,256 +0,0 @@ -{ - "instances": { - "866071d6-465a-4b88-8c63-07489d950916": { - "Name": "added", - "ClassName": "Folder", - "Properties": {}, - "Id": "866071d6-465a-4b88-8c63-07489d950916", - "Children": [], - "Parent": "c910510c-37a8-4fd8-ae41-01169ccb739c" - }, - "00f207b1-fc18-4088-a45e-caf8cd98f5dd": { - "Name": "main", - "ClassName": "ModuleScript", - "Properties": { - "Source": { - "Type": "String", - "Value": "-- hello, from a/main.lua" - } - }, - "Id": "00f207b1-fc18-4088-a45e-caf8cd98f5dd", - "Children": [], - "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" - }, - "14fed1a3-ba97-46a6-ae93-ac26bd9471df": { - "Name": "Ack", - "ClassName": "Folder", - "Properties": {}, - "Id": "14fed1a3-ba97-46a6-ae93-ac26bd9471df", - "Children": [ - "c55fd55c-258e-4a93-a63a-ea243038c9b9", - "00f207b1-fc18-4088-a45e-caf8cd98f5dd" - ], - "Parent": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" - }, - "c910510c-37a8-4fd8-ae41-01169ccb739c": { - "Name": "Bar", - "ClassName": "Folder", - "Properties": {}, - "Id": "c910510c-37a8-4fd8-ae41-01169ccb739c", - "Children": [ - "866071d6-465a-4b88-8c63-07489d950916", - "71a95983-c856-4cf2-aee6-bd8a523e80e4" - ], - "Parent": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" - }, - "c55fd55c-258e-4a93-a63a-ea243038c9b9": { - "Name": "foo", - "ClassName": "StringValue", - "Properties": { - "Value": { - "Type": "String", - "Value": "Hello world, from a/foo.txt" - } - }, - "Id": "c55fd55c-258e-4a93-a63a-ea243038c9b9", - "Children": [], - "Parent": "14fed1a3-ba97-46a6-ae93-ac26bd9471df" - }, - "71a95983-c856-4cf2-aee6-bd8a523e80e4": { - "Name": "something", - "ClassName": "ModuleScript", - "Properties": { - "Source": { - "Type": "String", - "Value": "-- b/something.lua" - } - }, - "Id": "71a95983-c856-4cf2-aee6-bd8a523e80e4", - "Children": [], - "Parent": "c910510c-37a8-4fd8-ae41-01169ccb739c" - }, - "3b5af13f-c997-4009-915c-0810b0e83032": { - "Name": "multi_partition_game", - "ClassName": "DataModel", - "Properties": {}, - "Id": "3b5af13f-c997-4009-915c-0810b0e83032", - "Children": [ - "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c", - "99eefe5f-ef74-49e6-8a8b-c833e00ca56b" - ], - "Parent": null - }, - "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c": { - "Name": "HttpService", - "ClassName": "HttpService", - "Properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "Id": "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c", - "Children": [], - "Parent": "3b5af13f-c997-4009-915c-0810b0e83032" - }, - "99eefe5f-ef74-49e6-8a8b-c833e00ca56b": { - "Name": "ReplicatedStorage", - "ClassName": "ReplicatedStorage", - "Properties": {}, - "Id": "99eefe5f-ef74-49e6-8a8b-c833e00ca56b", - "Children": [ - "14fed1a3-ba97-46a6-ae93-ac26bd9471df", - "c910510c-37a8-4fd8-ae41-01169ccb739c" - ], - "Parent": "3b5af13f-c997-4009-915c-0810b0e83032" - } - }, - "root_id": "3b5af13f-c997-4009-915c-0810b0e83032", - "metadata": { - "bf8e2d4f-33a0-42a0-8168-1b62d6ac050c": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "HttpService", - { - "class_name": "HttpService", - "children": {}, - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "ignore_unknown_instances": null, - "path": null - } - ] - }, - "c910510c-37a8-4fd8-ae41-01169ccb739c": { - "ignore_unknown_instances": false, - "source_path": "b", - "project_definition": [ - "Bar", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - ] - }, - "866071d6-465a-4b88-8c63-07489d950916": { - "ignore_unknown_instances": false, - "source_path": "b/added", - "project_definition": null - }, - "14fed1a3-ba97-46a6-ae93-ac26bd9471df": { - "ignore_unknown_instances": false, - "source_path": "a", - "project_definition": [ - "Ack", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - } - ] - }, - "00f207b1-fc18-4088-a45e-caf8cd98f5dd": { - "ignore_unknown_instances": false, - "source_path": "a/main.lua", - "project_definition": null - }, - "99eefe5f-ef74-49e6-8a8b-c833e00ca56b": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "ReplicatedStorage", - { - "class_name": "ReplicatedStorage", - "children": { - "Ack": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - }, - "Bar": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - }, - "71a95983-c856-4cf2-aee6-bd8a523e80e4": { - "ignore_unknown_instances": false, - "source_path": "b/something.lua", - "project_definition": null - }, - "c55fd55c-258e-4a93-a63a-ea243038c9b9": { - "ignore_unknown_instances": false, - "source_path": "a/foo.txt", - "project_definition": null - }, - "3b5af13f-c997-4009-915c-0810b0e83032": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "multi_partition_game", - { - "class_name": "DataModel", - "children": { - "HttpService": { - "class_name": "HttpService", - "children": {}, - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "ignore_unknown_instances": null, - "path": null - }, - "ReplicatedStorage": { - "class_name": "ReplicatedStorage", - "children": { - "Ack": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "a" - }, - "Bar": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "b" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - } - } -} \ No newline at end of file diff --git a/test-projects/nested_partitions/expected-snapshot.json b/test-projects/nested_partitions/expected-snapshot.json deleted file mode 100644 index 3741f613..00000000 --- a/test-projects/nested_partitions/expected-snapshot.json +++ /dev/null @@ -1,82 +0,0 @@ -{ - "name": "nested-partitions", - "class_name": "Folder", - "properties": {}, - "children": [ - { - "name": "inner", - "class_name": "Folder", - "properties": {}, - "children": [ - { - "name": "hello", - "class_name": "ModuleScript", - "properties": { - "Source": { - "Type": "String", - "Value": "-- inner/hello.lua" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "inner/hello.lua", - "project_definition": null - } - } - ], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "inner", - "project_definition": [ - "inner", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "inner" - } - ] - } - }, - { - "name": "world", - "class_name": "ModuleScript", - "properties": { - "Source": { - "Type": "String", - "Value": "-- outer/world.lua" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "outer/world.lua", - "project_definition": null - } - } - ], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "outer", - "project_definition": [ - "nested-partitions", - { - "class_name": null, - "children": { - "inner": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "inner" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": "outer" - } - ] - } -} \ No newline at end of file diff --git a/test-projects/single_partition_game/expected-snapshot.json b/test-projects/single_partition_game/expected-snapshot.json deleted file mode 100644 index d3cfcc7d..00000000 --- a/test-projects/single_partition_game/expected-snapshot.json +++ /dev/null @@ -1,161 +0,0 @@ -{ - "name": "single-sync-point", - "class_name": "DataModel", - "properties": {}, - "children": [ - { - "name": "HttpService", - "class_name": "HttpService", - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "HttpService", - { - "class_name": "HttpService", - "children": {}, - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "ignore_unknown_instances": null, - "path": null - } - ] - } - }, - { - "name": "ReplicatedStorage", - "class_name": "ReplicatedStorage", - "properties": {}, - "children": [ - { - "name": "Foo", - "class_name": "Folder", - "properties": {}, - "children": [ - { - "name": "foo", - "class_name": "StringValue", - "properties": { - "Value": { - "Type": "String", - "Value": "Hello world, from foo.txt" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "lib/foo.txt", - "project_definition": null - } - }, - { - "name": "main", - "class_name": "ModuleScript", - "properties": { - "Source": { - "Type": "String", - "Value": "-- hello, from main" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "lib/main.lua", - "project_definition": null - } - } - ], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "lib", - "project_definition": [ - "Foo", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "lib" - } - ] - } - } - ], - "metadata": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "ReplicatedStorage", - { - "class_name": "ReplicatedStorage", - "children": { - "Foo": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "lib" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - } - } - ], - "metadata": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "single-sync-point", - { - "class_name": "DataModel", - "children": { - "HttpService": { - "class_name": "HttpService", - "children": {}, - "properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - }, - "ignore_unknown_instances": null, - "path": null - }, - "ReplicatedStorage": { - "class_name": "ReplicatedStorage", - "children": { - "Foo": { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "lib" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - } -} \ No newline at end of file diff --git a/test-projects/single_partition_model/expected-snapshot.json b/test-projects/single_partition_model/expected-snapshot.json deleted file mode 100644 index 9014aaaa..00000000 --- a/test-projects/single_partition_model/expected-snapshot.json +++ /dev/null @@ -1,53 +0,0 @@ -{ - "name": "test-model", - "class_name": "Folder", - "properties": {}, - "children": [ - { - "name": "main", - "class_name": "Script", - "properties": { - "Source": { - "Type": "String", - "Value": "local other = require(script.Parent.other)\n\nprint(other)" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src/main.server.lua", - "project_definition": null - } - }, - { - "name": "other", - "class_name": "ModuleScript", - "properties": { - "Source": { - "Type": "String", - "Value": "return \"Hello, world!\"" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src/other.lua", - "project_definition": null - } - } - ], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "src", - "project_definition": [ - "test-model", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "src" - } - ] - } -} \ No newline at end of file diff --git a/test-projects/spawn_location/initial.tree.json b/test-projects/spawn_location/initial.tree.json deleted file mode 100644 index af079189..00000000 --- a/test-projects/spawn_location/initial.tree.json +++ /dev/null @@ -1,266 +0,0 @@ -{ - "instances": { - "21406306-61c7-45f6-9e3e-50cd6b609214": { - "Name": "spawn_location", - "ClassName": "Folder", - "Properties": {}, - "Id": "21406306-61c7-45f6-9e3e-50cd6b609214", - "Children": [ - "da5dd362-4eb6-488a-984b-c96327927a70" - ], - "Parent": null - }, - "da5dd362-4eb6-488a-984b-c96327927a70": { - "Name": "spawn", - "ClassName": "SpawnLocation", - "Properties": { - "Size": { - "Type": "Vector3", - "Value": [ - 12.0, - 1.0, - 12.0 - ] - }, - "Massless": { - "Type": "Bool", - "Value": false - }, - "LeftSurface": { - "Type": "Enum", - "Value": 0 - }, - "Color": { - "Type": "Color3", - "Value": [ - 0.6392157, - 0.63529414, - 0.64705884 - ] - }, - "RightSurfaceInput": { - "Type": "Enum", - "Value": 0 - }, - "Neutral": { - "Type": "Bool", - "Value": true - }, - "Locked": { - "Type": "Bool", - "Value": false - }, - "Anchored": { - "Type": "Bool", - "Value": true - }, - "CanCollide": { - "Type": "Bool", - "Value": true - }, - "FrontSurfaceInput": { - "Type": "Enum", - "Value": 0 - }, - "LeftSurfaceInput": { - "Type": "Enum", - "Value": 0 - }, - "RightSurface": { - "Type": "Enum", - "Value": 0 - }, - "FrontSurface": { - "Type": "Enum", - "Value": 0 - }, - "TopSurfaceInput": { - "Type": "Enum", - "Value": 0 - }, - "CastShadow": { - "Type": "Bool", - "Value": true - }, - "BottomSurface": { - "Type": "Enum", - "Value": 0 - }, - "Duration": { - "Type": "Int32", - "Value": 10 - }, - "Velocity": { - "Type": "Vector3", - "Value": [ - 0.0, - 0.0, - 0.0 - ] - }, - "BottomSurfaceInput": { - "Type": "Enum", - "Value": 0 - }, - "TopSurface": { - "Type": "Enum", - "Value": 0 - }, - "CFrame": { - "Type": "CFrame", - "Value": [ - -6.0, - 0.500001, - -11.0, - 1.0, - 0.0, - 0.0, - 0.0, - 1.0, - 0.0, - 0.0, - 0.0, - 1.0 - ] - }, - "TeamColor": { - "Type": "BrickColor", - "Value": 194 - }, - "RotVelocity": { - "Type": "Vector3", - "Value": [ - 0.0, - 0.0, - 0.0 - ] - }, - "Reflectance": { - "Type": "Float32", - "Value": 0.0 - }, - "AllowTeamChangeOnTouch": { - "Type": "Bool", - "Value": false - }, - "RightParamA": { - "Type": "Float32", - "Value": -0.5 - }, - "LeftParamA": { - "Type": "Float32", - "Value": -0.5 - }, - "Tags": { - "Type": "BinaryString", - "Value": "" - }, - "Transparency": { - "Type": "Float32", - "Value": 0.0 - }, - "Shape": { - "Type": "Enum", - "Value": 1 - }, - "FrontParamA": { - "Type": "Float32", - "Value": -0.5 - }, - "RootPriority": { - "Type": "Int32", - "Value": 0 - }, - "FrontParamB": { - "Type": "Float32", - "Value": 0.5 - }, - "FormFactor": { - "Type": "Enum", - "Value": 1 - }, - "BottomParamB": { - "Type": "Float32", - "Value": 0.5 - }, - "BackSurface": { - "Type": "Enum", - "Value": 0 - }, - "BottomParamA": { - "Type": "Float32", - "Value": -0.5 - }, - "Enabled": { - "Type": "Bool", - "Value": true - }, - "BackParamB": { - "Type": "Float32", - "Value": 0.5 - }, - "BackParamA": { - "Type": "Float32", - "Value": -0.5 - }, - "LeftParamB": { - "Type": "Float32", - "Value": 0.5 - }, - "TopParamA": { - "Type": "Float32", - "Value": -0.5 - }, - "RightParamB": { - "Type": "Float32", - "Value": 0.5 - }, - "CollisionGroupId": { - "Type": "Int32", - "Value": 0 - }, - "BackSurfaceInput": { - "Type": "Enum", - "Value": 0 - }, - "CustomPhysicalProperties": { - "Type": "PhysicalProperties", - "Value": null - }, - "TopParamB": { - "Type": "Float32", - "Value": 0.5 - }, - "Material": { - "Type": "Enum", - "Value": 256 - } - }, - "Id": "da5dd362-4eb6-488a-984b-c96327927a70", - "Children": [], - "Parent": "21406306-61c7-45f6-9e3e-50cd6b609214" - } - }, - "root_id": "21406306-61c7-45f6-9e3e-50cd6b609214", - "metadata": { - "da5dd362-4eb6-488a-984b-c96327927a70": { - "ignore_unknown_instances": false, - "source_path": "src/spawn.rbxmx", - "project_definition": null - }, - "21406306-61c7-45f6-9e3e-50cd6b609214": { - "ignore_unknown_instances": false, - "source_path": "src", - "project_definition": [ - "spawn_location", - { - "class_name": null, - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "src" - } - ] - } - } -} \ No newline at end of file diff --git a/test-projects/transmute_partition/expected-snapshot.json b/test-projects/transmute_partition/expected-snapshot.json deleted file mode 100644 index a6c65c4c..00000000 --- a/test-projects/transmute_partition/expected-snapshot.json +++ /dev/null @@ -1,66 +0,0 @@ -{ - "name": "transmute-partition", - "class_name": "DataModel", - "properties": {}, - "children": [ - { - "name": "ReplicatedStorage", - "class_name": "ReplicatedStorage", - "properties": {}, - "children": [ - { - "name": "hello", - "class_name": "ModuleScript", - "properties": { - "Source": { - "Type": "String", - "Value": "-- ReplicatedStorage/hello.lua" - } - }, - "children": [], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "ReplicatedStorage/hello.lua", - "project_definition": null - } - } - ], - "metadata": { - "ignore_unknown_instances": false, - "source_path": "ReplicatedStorage", - "project_definition": [ - "ReplicatedStorage", - { - "class_name": "ReplicatedStorage", - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "ReplicatedStorage" - } - ] - } - } - ], - "metadata": { - "ignore_unknown_instances": true, - "source_path": null, - "project_definition": [ - "transmute-partition", - { - "class_name": "DataModel", - "children": { - "ReplicatedStorage": { - "class_name": "ReplicatedStorage", - "children": {}, - "properties": {}, - "ignore_unknown_instances": null, - "path": "ReplicatedStorage" - } - }, - "properties": {}, - "ignore_unknown_instances": null, - "path": null - } - ] - } -} \ No newline at end of file diff --git a/test-projects/txt_file/default.project.json b/test-projects/txt_file/default.project.json new file mode 100644 index 00000000..5d67b95b --- /dev/null +++ b/test-projects/txt_file/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "empty_folder", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/test-projects/txt_file/src/foo.txt b/test-projects/txt_file/src/foo.txt new file mode 100644 index 00000000..ca77661c --- /dev/null +++ b/test-projects/txt_file/src/foo.txt @@ -0,0 +1 @@ +Hello, from foo.txt! \ No newline at end of file From 7fb9aa21159952247f69ffd44e9f2f20cdf71bf7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 15:10:34 -0700 Subject: [PATCH 0617/1504] rustfmt the codebase --- rojo-test/src/build_test.rs | 16 +- rojo-test/src/lib.rs | 2 +- server/rustfmt.toml | 12 -- server/src/bin.rs | 33 ++-- server/src/commands/build.rs | 25 +-- server/src/commands/init.rs | 23 ++- server/src/commands/mod.rs | 10 +- server/src/commands/serve.rs | 20 +- server/src/commands/upload.rs | 2 +- server/src/imfs/error.rs | 8 +- server/src/imfs/fetcher.rs | 2 +- server/src/imfs/imfs.rs | 113 ++++++----- server/src/imfs/mod.rs | 6 +- server/src/imfs/noop_fetcher.rs | 25 ++- server/src/imfs/real_fetcher.rs | 21 +- server/src/imfs/snapshot.rs | 11 +- server/src/impl_from.rs | 2 +- server/src/lib.rs | 4 +- server/src/message_queue.rs | 25 ++- server/src/path_map.rs | 64 +++--- server/src/path_serializer.rs | 19 +- server/src/project.rs | 198 +++++++++++-------- server/src/serve_session.rs | 7 +- server/src/session_id.rs | 4 +- server/src/snapshot/instance_snapshot.rs | 20 +- server/src/snapshot/mod.rs | 4 +- server/src/snapshot/patch.rs | 4 +- server/src/snapshot/patch_apply.rs | 47 ++--- server/src/snapshot/patch_compute.rs | 130 ++++++------ server/src/snapshot_middleware/context.rs | 2 +- server/src/snapshot_middleware/csv.rs | 63 +++--- server/src/snapshot_middleware/dir.rs | 35 ++-- server/src/snapshot_middleware/error.rs | 26 +-- server/src/snapshot_middleware/json_model.rs | 92 +++++---- server/src/snapshot_middleware/lua.rs | 85 ++++---- server/src/snapshot_middleware/middleware.rs | 24 +-- server/src/snapshot_middleware/mod.rs | 8 +- server/src/snapshot_middleware/project.rs | 90 +++++---- server/src/snapshot_middleware/rbxm.rs | 34 ++-- server/src/snapshot_middleware/rbxmx.rs | 39 ++-- server/src/snapshot_middleware/txt.rs | 48 ++--- server/src/web/api.rs | 67 +++---- server/src/web/interface.rs | 16 +- server/src/web/mod.rs | 21 +- server/tests/read_projects.rs | 23 ++- 45 files changed, 766 insertions(+), 764 deletions(-) delete mode 100644 server/rustfmt.toml diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index f45e520a..c7754baa 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -1,8 +1,4 @@ -use std::{ - fs, - path::Path, - process::Command, -}; +use std::{fs, path::Path, process::Command}; use insta::assert_snapshot_matches; use tempfile::tempdir; @@ -67,7 +63,10 @@ fn run_build_test(test_name: &str) { let status = Command::new(exe_path) .args(&[ - "build", input_path.to_str().unwrap(), "-o", output_path.to_str().unwrap(), + "build", + input_path.to_str().unwrap(), + "-o", + output_path.to_str().unwrap(), ]) .env("RUST_LOG", "error") .current_dir(working_dir) @@ -76,8 +75,7 @@ fn run_build_test(test_name: &str) { assert!(status.success(), "Rojo did not exit successfully"); - let contents = fs::read_to_string(&output_path) - .expect("Couldn't read output file"); + let contents = fs::read_to_string(&output_path).expect("Couldn't read output file"); assert_snapshot_matches!(test_name, contents); -} \ No newline at end of file +} diff --git a/rojo-test/src/lib.rs b/rojo-test/src/lib.rs index 58bd5ab1..d7961940 100644 --- a/rojo-test/src/lib.rs +++ b/rojo-test/src/lib.rs @@ -1,2 +1,2 @@ #[cfg(test)] -mod build_test; \ No newline at end of file +mod build_test; diff --git a/server/rustfmt.toml b/server/rustfmt.toml deleted file mode 100644 index 8fc5c69f..00000000 --- a/server/rustfmt.toml +++ /dev/null @@ -1,12 +0,0 @@ -reorder_imports = true -reorder_imported_names = true -reorder_imports_in_group = true -attributes_on_same_line_as_field = false -attributes_on_same_line_as_variant = false -chain_split_single_child = true -wrap_comments = true -imports_indent = "Block" -match_block_trailing_comma = true -match_pattern_separator_break_point = "Front" -error_on_line_overflow = false -struct_lit_multiline_style = "ForceMulti" diff --git a/server/src/bin.rs b/server/src/bin.rs index 2bf96da7..f55c61aa 100644 --- a/server/src/bin.rs +++ b/server/src/bin.rs @@ -1,12 +1,11 @@ use std::{ - env, - panic, + env, panic, path::{Path, PathBuf}, process, }; -use log::error; use clap::{clap_app, ArgMatches}; +use log::error; use librojo::commands; @@ -21,8 +20,7 @@ fn make_path_absolute(value: &Path) -> PathBuf { fn main() { { - let log_env = env_logger::Env::default() - .default_filter_or("warn"); + let log_env = env_logger::Env::default().default_filter_or("warn"); env_logger::Builder::from_env(log_env) .default_format_timestamp(false) @@ -95,7 +93,8 @@ fn show_crash_message(message: &str) { } fn start_init(sub_matches: &ArgMatches) { - let fuzzy_project_path = make_path_absolute(Path::new(sub_matches.value_of("PATH").unwrap_or(""))); + let fuzzy_project_path = + make_path_absolute(Path::new(sub_matches.value_of("PATH").unwrap_or(""))); let kind = sub_matches.value_of("kind"); let options = commands::InitOptions { @@ -104,11 +103,11 @@ fn start_init(sub_matches: &ArgMatches) { }; match commands::init(&options) { - Ok(_) => {}, + Ok(_) => {} Err(e) => { error!("{}", e); process::exit(1); - }, + } } } @@ -124,7 +123,7 @@ fn start_serve(sub_matches: &ArgMatches) { Err(_) => { error!("Invalid port {}", v); process::exit(1); - }, + } }, None => None, }; @@ -135,11 +134,11 @@ fn start_serve(sub_matches: &ArgMatches) { }; match commands::serve(&options) { - Ok(_) => {}, + Ok(_) => {} Err(e) => { error!("{}", e); process::exit(1); - }, + } } } @@ -158,11 +157,11 @@ fn start_build(sub_matches: &ArgMatches) { }; match commands::build(&options) { - Ok(_) => {}, + Ok(_) => {} Err(e) => { error!("{}", e); process::exit(1); - }, + } } } @@ -183,7 +182,7 @@ fn start_upload(sub_matches: &ArgMatches) { Err(_) => { error!("Invalid place ID {}", arg); process::exit(1); - }, + } } }; @@ -195,10 +194,10 @@ fn start_upload(sub_matches: &ArgMatches) { }; match commands::upload(&options) { - Ok(_) => {}, + Ok(_) => {} Err(e) => { error!("{}", e); process::exit(1); - }, + } } -} \ No newline at end of file +} diff --git a/server/src/commands/build.rs b/server/src/commands/build.rs index e8efc6c3..453b42f6 100644 --- a/server/src/commands/build.rs +++ b/server/src/commands/build.rs @@ -1,15 +1,15 @@ use std::{ collections::HashMap, fs::File, - io::{self, Write, BufWriter}, + io::{self, BufWriter, Write}, path::PathBuf, }; -use rbx_dom_weak::{RbxTree, RbxInstanceProperties}; use failure::Fail; +use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; use crate::{ - imfs::new::{Imfs, RealFetcher, WatchMode, FsError}, + imfs::new::{FsError, Imfs, RealFetcher, WatchMode}, snapshot::{apply_patch_set, compute_patch_set}, snapshot_middleware::snapshot_from_imfs, }; @@ -67,12 +67,12 @@ impl_from!(BuildError { }); fn xml_encode_config() -> rbx_xml::EncodeOptions { - rbx_xml::EncodeOptions::new() - .property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown) + rbx_xml::EncodeOptions::new().property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown) } pub fn build(options: &BuildOptions) -> Result<(), BuildError> { - let output_kind = options.output_kind + let output_kind = options + .output_kind .or_else(|| detect_output_kind(options)) .ok_or(BuildError::UnknownOutputKind)?; @@ -89,7 +89,8 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Disabled)); log::trace!("Reading project root"); - let entry = imfs.get(&options.fuzzy_project_path) + let entry = imfs + .get(&options.fuzzy_project_path) .expect("could not get project path"); log::trace!("Generating snapshot of instances from IMFS"); @@ -112,17 +113,17 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { // descendants. rbx_xml::to_writer(&mut file, &tree, &[root_id], xml_encode_config())?; - }, + } OutputKind::Rbxlx => { // Place files don't contain an entry for the DataModel, but our // RbxTree representation does. let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); rbx_xml::to_writer(&mut file, &tree, top_level_ids, xml_encode_config())?; - }, + } OutputKind::Rbxm => { rbx_binary::encode(&tree, &[root_id], &mut file)?; - }, + } OutputKind::Rbxl => { log::warn!("Support for building binary places (rbxl) is still experimental."); log::warn!("Using the XML place format (rbxlx) is recommended instead."); @@ -130,7 +131,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); rbx_binary::encode(&tree, top_level_ids, &mut file)?; - }, + } } file.flush()?; @@ -138,4 +139,4 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { log::trace!("Done!"); Ok(()) -} \ No newline at end of file +} diff --git a/server/src/commands/init.rs b/server/src/commands/init.rs index b4b0aa69..e17ba6dd 100644 --- a/server/src/commands/init.rs +++ b/server/src/commands/init.rs @@ -1,6 +1,4 @@ -use std::{ - path::PathBuf, -}; +use std::path::PathBuf; use failure::Fail; @@ -8,11 +6,14 @@ use crate::project::{Project, ProjectInitError}; #[derive(Debug, Fail)] pub enum InitError { - #[fail(display = "Invalid project kind '{}', valid kinds are 'place' and 'model'", _0)] + #[fail( + display = "Invalid project kind '{}', valid kinds are 'place' and 'model'", + _0 + )] InvalidKind(String), #[fail(display = "Project init error: {}", _0)] - ProjectInitError(#[fail(cause)] ProjectInitError) + ProjectInitError(#[fail(cause)] ProjectInitError), } impl_from!(InitError { @@ -30,15 +31,19 @@ pub fn init(options: &InitOptions) -> Result<(), InitError> { Some("place") | None => { let path = Project::init_place(&options.fuzzy_project_path)?; (path, "place") - }, + } Some("model") => { let path = Project::init_model(&options.fuzzy_project_path)?; (path, "model") - }, + } Some(invalid) => return Err(InitError::InvalidKind(invalid.to_string())), }; - println!("Created new {} project file at {}", project_kind, project_path.display()); + println!( + "Created new {} project file at {}", + project_kind, + project_path.display() + ); Ok(()) -} \ No newline at end of file +} diff --git a/server/src/commands/mod.rs b/server/src/commands/mod.rs index 966d67db..b4b53557 100644 --- a/server/src/commands/mod.rs +++ b/server/src/commands/mod.rs @@ -1,9 +1,9 @@ -mod serve; -mod init; mod build; +mod init; +mod serve; mod upload; -pub use self::serve::*; -pub use self::init::*; pub use self::build::*; -pub use self::upload::*; \ No newline at end of file +pub use self::init::*; +pub use self::serve::*; +pub use self::upload::*; diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index fbaaaed4..d074a116 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -1,11 +1,7 @@ -use std::{ - collections::HashMap, - path::PathBuf, - sync::Arc, -}; +use std::{collections::HashMap, path::PathBuf, sync::Arc}; -use rbx_dom_weak::{RbxTree, RbxInstanceProperties}; use failure::Fail; +use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; use crate::{ imfs::new::{Imfs, RealFetcher, WatchMode}, @@ -41,8 +37,11 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { Err(other) => return Err(other.into()), }; - let port = options.port - .or(maybe_project.as_ref().and_then(|project| project.serve_port)) + let port = options + .port + .or(maybe_project + .as_ref() + .and_then(|project| project.serve_port)) .unwrap_or(DEFAULT_PORT); println!("Rojo server listening on port {}", port); @@ -55,7 +54,8 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { let root_id = tree.get_root_id(); let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Enabled)); - let entry = imfs.get(&options.fuzzy_project_path) + let entry = imfs + .get(&options.fuzzy_project_path) .expect("could not get project path"); let snapshot = snapshot_from_imfs(&mut imfs, &entry) @@ -86,4 +86,4 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { // } Ok(()) -} \ No newline at end of file +} diff --git a/server/src/commands/upload.rs b/server/src/commands/upload.rs index a6218a19..c4a67afa 100644 --- a/server/src/commands/upload.rs +++ b/server/src/commands/upload.rs @@ -18,4 +18,4 @@ pub struct UploadOptions<'a> { pub fn upload(_options: &UploadOptions) -> Result<(), UploadError> { unimplemented!("TODO: Reimplement upload command"); -} \ No newline at end of file +} diff --git a/server/src/imfs/error.rs b/server/src/imfs/error.rs index 70799785..07c7a8df 100644 --- a/server/src/imfs/error.rs +++ b/server/src/imfs/error.rs @@ -1,8 +1,4 @@ -use std::{ - io, - fmt, - path::PathBuf, -}; +use std::{fmt, io, path::PathBuf}; use failure::Fail; @@ -62,4 +58,4 @@ impl fmt::Display for FsError { fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { write!(output, "{}: {}", self.path.display(), self.inner) } -} \ No newline at end of file +} diff --git a/server/src/imfs/fetcher.rs b/server/src/imfs/fetcher.rs index a2b62e92..f86f702a 100644 --- a/server/src/imfs/fetcher.rs +++ b/server/src/imfs/fetcher.rs @@ -29,4 +29,4 @@ pub trait ImfsFetcher { fn watch(&mut self, path: &Path); fn unwatch(&mut self, path: &Path); fn receiver(&self) -> Receiver; -} \ No newline at end of file +} diff --git a/server/src/imfs/imfs.rs b/server/src/imfs/imfs.rs index 913de546..21aaf9d4 100644 --- a/server/src/imfs/imfs.rs +++ b/server/src/imfs/imfs.rs @@ -8,9 +8,9 @@ use crossbeam_channel::Receiver; use crate::path_map::PathMap; use super::{ + error::{FsError, FsResult}, + fetcher::{FileType, ImfsEvent, ImfsFetcher}, snapshot::ImfsSnapshot, - error::{FsResult, FsError}, - fetcher::{ImfsFetcher, FileType, ImfsEvent}, }; /// An in-memory filesystem that can be incrementally populated and updated as @@ -89,16 +89,22 @@ impl Imfs { match snapshot { ImfsSnapshot::File(file) => { - self.inner.insert(path.to_path_buf(), ImfsItem::File(ImfsFile { - path: path.to_path_buf(), - contents: Some(file.contents), - })); + self.inner.insert( + path.to_path_buf(), + ImfsItem::File(ImfsFile { + path: path.to_path_buf(), + contents: Some(file.contents), + }), + ); } ImfsSnapshot::Directory(directory) => { - self.inner.insert(path.to_path_buf(), ImfsItem::Directory(ImfsDirectory { - path: path.to_path_buf(), - children_enumerated: true, - })); + self.inner.insert( + path.to_path_buf(), + ImfsItem::Directory(ImfsDirectory { + path: path.to_path_buf(), + children_enumerated: true, + }), + ); for (child_name, child) in directory.children.into_iter() { self.load_from_snapshot(path.join(child_name), child); @@ -114,7 +120,9 @@ impl Imfs { return Ok(()); } - let new_type = self.fetcher.file_type(path) + let new_type = self + .fetcher + .file_type(path) .map_err(|err| FsError::new(err, path.to_path_buf()))?; match self.inner.get_mut(path) { @@ -131,18 +139,25 @@ impl Imfs { } (ImfsItem::File(_), FileType::Directory) => { self.inner.remove(path); - self.inner.insert(path.to_path_buf(), ImfsItem::new_from_type(FileType::Directory, path)); + self.inner.insert( + path.to_path_buf(), + ImfsItem::new_from_type(FileType::Directory, path), + ); self.fetcher.watch(path); } (ImfsItem::Directory(_), FileType::File) => { self.inner.remove(path); - self.inner.insert(path.to_path_buf(), ImfsItem::new_from_type(FileType::File, path)); + self.inner.insert( + path.to_path_buf(), + ImfsItem::new_from_type(FileType::File, path), + ); self.fetcher.unwatch(path); } } } None => { - self.inner.insert(path.to_path_buf(), ImfsItem::new_from_type(new_type, path)); + self.inner + .insert(path.to_path_buf(), ImfsItem::new_from_type(new_type, path)); } } @@ -185,13 +200,19 @@ impl Imfs { match self.inner.get_mut(path).unwrap() { ImfsItem::File(file) => { if file.contents.is_none() { - file.contents = Some(self.fetcher.read_contents(path) - .map_err(|err| FsError::new(err, path.to_path_buf()))?); + file.contents = Some( + self.fetcher + .read_contents(path) + .map_err(|err| FsError::new(err, path.to_path_buf()))?, + ); } Ok(file.contents.as_ref().unwrap()) } - ImfsItem::Directory(_) => Err(FsError::new(io::Error::new(io::ErrorKind::Other, "Can't read a directory"), path.to_path_buf())) + ImfsItem::Directory(_) => Err(FsError::new( + io::Error::new(io::ErrorKind::Other, "Can't read a directory"), + path.to_path_buf(), + )), } } @@ -205,7 +226,9 @@ impl Imfs { self.fetcher.watch(path); if dir.children_enumerated { - return self.inner.children(path) + return self + .inner + .children(path) .unwrap() // TODO: Handle None here, which means the PathMap entry did not exist. .into_iter() .map(PathBuf::from) // Convert paths from &Path to PathBuf @@ -215,13 +238,17 @@ impl Imfs { .collect::>>(); } - self.fetcher.read_children(path) + self.fetcher + .read_children(path) .map_err(|err| FsError::new(err, path.to_path_buf()))? .into_iter() .map(|path| self.get(path)) .collect::>>() } - ImfsItem::File(_) => Err(FsError::new(io::Error::new(io::ErrorKind::Other, "Can't read a directory"), path.to_path_buf())) + ImfsItem::File(_) => Err(FsError::new( + io::Error::new(io::ErrorKind::Other, "Can't read a directory"), + path.to_path_buf(), + )), } } @@ -256,14 +283,17 @@ impl Imfs { /// is using, this call may read exactly only the given path and no more. fn read_if_not_exists(&mut self, path: &Path) -> FsResult<()> { if !self.inner.contains_key(path) { - let kind = self.fetcher.file_type(path) + let kind = self + .fetcher + .file_type(path) .map_err(|err| FsError::new(err, path.to_path_buf()))?; if kind == FileType::Directory { self.fetcher.watch(path); } - self.inner.insert(path.to_path_buf(), ImfsItem::new_from_type(kind, path)); + self.inner + .insert(path.to_path_buf(), ImfsItem::new_from_type(kind, path)); } Ok(()) @@ -293,10 +323,7 @@ impl ImfsEntry { imfs.get_contents(&self.path) } - pub fn children( - &self, - imfs: &mut Imfs, - ) -> FsResult> { + pub fn children(&self, imfs: &mut Imfs) -> FsResult> { imfs.get_children(&self.path) } @@ -352,19 +379,12 @@ pub struct ImfsDirectory { mod test { use super::*; - use std::{ - rc::Rc, - cell::RefCell, - }; + use std::{cell::RefCell, rc::Rc}; use crossbeam_channel::Receiver; use maplit::hashmap; - use super::super::{ - noop_fetcher::NoopFetcher, - error::FsErrorKind, - fetcher::ImfsEvent, - }; + use super::super::{error::FsErrorKind, fetcher::ImfsEvent, noop_fetcher::NoopFetcher}; #[test] fn from_snapshot_file() { @@ -458,11 +478,9 @@ mod test { unimplemented!(); } - fn watch(&mut self, _path: &Path) { - } + fn watch(&mut self, _path: &Path) {} - fn unwatch(&mut self, _path: &Path) { - } + fn unwatch(&mut self, _path: &Path) {} fn receiver(&self) -> Receiver { crossbeam_channel::never() @@ -477,11 +495,9 @@ mod test { inner: mock_state.clone(), }); - let a = imfs.get("/dir/a.txt") - .expect("mock file did not exist"); + let a = imfs.get("/dir/a.txt").expect("mock file did not exist"); - let contents = a.contents(&mut imfs) - .expect("mock file contents error"); + let contents = a.contents(&mut imfs).expect("mock file contents error"); assert_eq!(contents, b"Initial contents"); @@ -493,8 +509,7 @@ mod test { imfs.raise_file_changed("/dir/a.txt") .expect("error processing file change"); - let contents = a.contents(&mut imfs) - .expect("mock file contents error"); + let contents = a.contents(&mut imfs).expect("mock file contents error"); assert_eq!(contents, b"Changed contents"); } @@ -506,10 +521,10 @@ mod test { let file = ImfsSnapshot::file("hello, world!"); imfs.load_from_snapshot("/hello.txt", file); - let hello = imfs.get("/hello.txt") - .expect("couldn't get hello.txt"); + let hello = imfs.get("/hello.txt").expect("couldn't get hello.txt"); - let contents = hello.contents(&mut imfs) + let contents = hello + .contents(&mut imfs) .expect("couldn't get hello.txt contents"); assert_eq!(contents, b"hello, world!"); @@ -527,4 +542,4 @@ mod test { } } } -} \ No newline at end of file +} diff --git a/server/src/imfs/mod.rs b/server/src/imfs/mod.rs index a9e035dd..3ddfed49 100644 --- a/server/src/imfs/mod.rs +++ b/server/src/imfs/mod.rs @@ -9,9 +9,9 @@ pub use error::*; pub mod new { pub use super::error::*; - pub use super::imfs::*; pub use super::fetcher::*; - pub use super::real_fetcher::*; + pub use super::imfs::*; pub use super::noop_fetcher::*; + pub use super::real_fetcher::*; pub use super::snapshot::*; -} \ No newline at end of file +} diff --git a/server/src/imfs/noop_fetcher.rs b/server/src/imfs/noop_fetcher.rs index 663744b6..02784fd2 100644 --- a/server/src/imfs/noop_fetcher.rs +++ b/server/src/imfs/noop_fetcher.rs @@ -8,21 +8,30 @@ use std::{ use crossbeam_channel::Receiver; -use super::fetcher::{ImfsFetcher, FileType, ImfsEvent}; +use super::fetcher::{FileType, ImfsEvent, ImfsFetcher}; pub struct NoopFetcher; impl ImfsFetcher for NoopFetcher { fn file_type(&mut self, _path: &Path) -> io::Result { - Err(io::Error::new(io::ErrorKind::NotFound, "NoopFetcher always returns NotFound")) + Err(io::Error::new( + io::ErrorKind::NotFound, + "NoopFetcher always returns NotFound", + )) } fn read_children(&mut self, _path: &Path) -> io::Result> { - Err(io::Error::new(io::ErrorKind::NotFound, "NoopFetcher always returns NotFound")) + Err(io::Error::new( + io::ErrorKind::NotFound, + "NoopFetcher always returns NotFound", + )) } fn read_contents(&mut self, _path: &Path) -> io::Result> { - Err(io::Error::new(io::ErrorKind::NotFound, "NoopFetcher always returns NotFound")) + Err(io::Error::new( + io::ErrorKind::NotFound, + "NoopFetcher always returns NotFound", + )) } fn create_directory(&mut self, _path: &Path) -> io::Result<()> { @@ -37,13 +46,11 @@ impl ImfsFetcher for NoopFetcher { Ok(()) } - fn watch(&mut self, _path: &Path) { - } + fn watch(&mut self, _path: &Path) {} - fn unwatch(&mut self, _path: &Path) { - } + fn unwatch(&mut self, _path: &Path) {} fn receiver(&self) -> Receiver { crossbeam_channel::never() } -} \ No newline at end of file +} diff --git a/server/src/imfs/real_fetcher.rs b/server/src/imfs/real_fetcher.rs index aa4c05b4..b3159950 100644 --- a/server/src/imfs/real_fetcher.rs +++ b/server/src/imfs/real_fetcher.rs @@ -2,18 +2,17 @@ //! std::fs interface and notify as the file watcher. use std::{ - fs, - io, + fs, io, path::{Path, PathBuf}, sync::mpsc, time::Duration, }; +use crossbeam_channel::{unbounded, Receiver}; use jod_thread::JoinHandle; -use crossbeam_channel::{Receiver, unbounded}; -use notify::{RecursiveMode, RecommendedWatcher, Watcher}; +use notify::{RecommendedWatcher, RecursiveMode, Watcher}; -use super::fetcher::{ImfsFetcher, FileType, ImfsEvent}; +use super::fetcher::{FileType, ImfsEvent, ImfsFetcher}; /// Workaround to disable the file watcher for processes that don't need it, /// since notify appears hang on to mpsc Sender objects too long, causing Rojo @@ -51,7 +50,7 @@ impl RealFetcher { .spawn(move || { notify_receiver .into_iter() - .for_each(|event| { sender.send(event).unwrap() }); + .for_each(|event| sender.send(event).unwrap()); }) .expect("Could not start message converter thread"); @@ -59,10 +58,10 @@ impl RealFetcher { // causing our program to deadlock. Once this is fixed, watcher no // longer needs to be optional, but is still maybe useful? let watcher = match watch_mode { - WatchMode::Enabled => { - Some(notify::watcher(notify_sender, Duration::from_millis(300)) - .expect("Couldn't start 'notify' file watcher")) - } + WatchMode::Enabled => Some( + notify::watcher(notify_sender, Duration::from_millis(300)) + .expect("Couldn't start 'notify' file watcher"), + ), WatchMode::Disabled => None, }; @@ -152,4 +151,4 @@ impl ImfsFetcher for RealFetcher { fn receiver(&self) -> Receiver { self.receiver.clone() } -} \ No newline at end of file +} diff --git a/server/src/imfs/snapshot.rs b/server/src/imfs/snapshot.rs index 5f57f8fd..f84f9b3b 100644 --- a/server/src/imfs/snapshot.rs +++ b/server/src/imfs/snapshot.rs @@ -16,14 +16,9 @@ impl ImfsSnapshot { /// Create a new directory ImfsSnapshot with the given children. pub fn dir>(children: HashMap) -> ImfsSnapshot { - let children = children - .into_iter() - .map(|(k, v)| (k.into(), v)) - .collect(); + let children = children.into_iter().map(|(k, v)| (k.into(), v)).collect(); - ImfsSnapshot::Directory(DirectorySnapshot { - children, - }) + ImfsSnapshot::Directory(DirectorySnapshot { children }) } } @@ -35,4 +30,4 @@ pub struct FileSnapshot { #[derive(Debug, Clone)] pub struct DirectorySnapshot { pub children: HashMap, -} \ No newline at end of file +} diff --git a/server/src/impl_from.rs b/server/src/impl_from.rs index eb26af42..ed1db996 100644 --- a/server/src/impl_from.rs +++ b/server/src/impl_from.rs @@ -15,4 +15,4 @@ macro_rules! impl_from { } )* } -} \ No newline at end of file +} diff --git a/server/src/lib.rs b/server/src/lib.rs index fa05ab7f..7e1f570c 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1,4 +1,4 @@ -#![recursion_limit="128"] +#![recursion_limit = "128"] // Macros #[macro_use] @@ -16,4 +16,4 @@ mod serve_session; mod session_id; mod snapshot; mod snapshot_middleware; -mod web; \ No newline at end of file +mod web; diff --git a/server/src/message_queue.rs b/server/src/message_queue.rs index 08d93e8e..2ae52b28 100644 --- a/server/src/message_queue.rs +++ b/server/src/message_queue.rs @@ -1,9 +1,6 @@ use std::{ mem, - sync::{ - RwLock, - Mutex, - }, + sync::{Mutex, RwLock}, }; use futures::sync::oneshot; @@ -13,7 +10,10 @@ struct Listener { cursor: u32, } -fn fire_listener_if_ready(messages: &[T], listener: Listener) -> Result<(), Listener> { +fn fire_listener_if_ready( + messages: &[T], + listener: Listener, +) -> Result<(), Listener> { let current_cursor = messages.len() as u32; if listener.cursor < current_cursor { @@ -30,8 +30,8 @@ fn fire_listener_if_ready(messages: &[T], listener: Listener) -> Re /// Definitely non-optimal. This would ideally be a lockless mpmc queue. #[derive(Default)] pub struct MessageQueue { - messages: RwLock>, - message_listeners: Mutex>>, + messages: RwLock>, + message_listeners: Mutex>>, } impl MessageQueue { @@ -52,7 +52,7 @@ impl MessageQueue { for listener in message_listeners.drain(..) { match fire_listener_if_ready(&messages, listener) { Ok(_) => {} - Err(listener) => remaining_listeners.push(listener) + Err(listener) => remaining_listeners.push(listener), } } @@ -63,16 +63,13 @@ impl MessageQueue { pub fn subscribe(&self, cursor: u32, sender: oneshot::Sender<(u32, Vec)>) { let listener = { - let listener = Listener { - sender, - cursor, - }; + let listener = Listener { sender, cursor }; let messages = self.messages.read().unwrap(); match fire_listener_if_ready(&messages, listener) { Ok(_) => return, - Err(listener) => listener + Err(listener) => listener, } }; @@ -96,4 +93,4 @@ impl MessageQueue { (current_cursor, messages[(cursor as usize)..].to_vec()) } -} \ No newline at end of file +} diff --git a/server/src/path_map.rs b/server/src/path_map.rs index b67aee1b..506f29f4 100644 --- a/server/src/path_map.rs +++ b/server/src/path_map.rs @@ -1,10 +1,10 @@ use std::{ - path::{self, Path, PathBuf}, collections::{HashMap, HashSet}, + path::{self, Path, PathBuf}, }; -use serde::Serialize; use log::warn; +use serde::Serialize; #[derive(Debug, Serialize)] struct PathMapNode { @@ -51,7 +51,9 @@ impl PathMap { } pub fn children(&self, path: impl AsRef) -> Option> { - self.nodes.get(path.as_ref()).map(|v| v.children.iter().map(AsRef::as_ref).collect()) + self.nodes + .get(path.as_ref()) + .map(|v| v.children.iter().map(AsRef::as_ref).collect()) } pub fn contains_key(&self, path: impl AsRef) -> bool { @@ -76,10 +78,7 @@ impl PathMap { self.orphan_paths.remove(child); } - self.nodes.insert(path, PathMapNode { - value, - children, - }); + self.nodes.insert(path, PathMapNode { value, children }); } /// Remove the given path and all of its linked descendants, returning all @@ -105,10 +104,13 @@ impl PathMap { for child in node.children.into_iter() { to_visit.push(child); } - }, + } None => { - warn!("Consistency issue; tried to remove {} but it was already removed", path.display()); - }, + warn!( + "Consistency issue; tried to remove {} but it was already removed", + path.display() + ); + } } } @@ -123,11 +125,16 @@ impl PathMap { /// FS events, a file remove event could be followed by that file's /// directory being removed, in which case we should process that /// directory's parent. - pub fn descend(&self, start_path: impl Into, target_path: impl AsRef) -> PathBuf { + pub fn descend( + &self, + start_path: impl Into, + target_path: impl AsRef, + ) -> PathBuf { let start_path = start_path.into(); let target_path = target_path.as_ref(); - let relative_path = target_path.strip_prefix(&start_path) + let relative_path = target_path + .strip_prefix(&start_path) .expect("target_path did not begin with start_path"); let mut current_path = start_path; @@ -141,7 +148,7 @@ impl PathMap { } else { return current_path; } - }, + } _ => unreachable!(), } } @@ -219,9 +226,7 @@ mod test { map.insert("/foo", 6); - assert_eq!(map.remove("/foo"), vec![ - (PathBuf::from("/foo"), 6), - ]); + assert_eq!(map.remove("/foo"), vec![(PathBuf::from("/foo"), 6),]); assert_eq!(map.get("/foo"), None); } @@ -233,10 +238,10 @@ mod test { map.insert("/foo", 6); map.insert("/foo/bar", 12); - assert_eq!(map.remove("/foo"), vec![ - (PathBuf::from("/foo"), 6), - (PathBuf::from("/foo/bar"), 12), - ]); + assert_eq!( + map.remove("/foo"), + vec![(PathBuf::from("/foo"), 6), (PathBuf::from("/foo/bar"), 12),] + ); assert_eq!(map.get("/foo"), None); assert_eq!(map.get("/foo/bar"), None); @@ -250,11 +255,14 @@ mod test { map.insert("/foo/bar", 12); map.insert("/foo/bar/baz", 18); - assert_eq!(map.remove("/foo"), vec![ - (PathBuf::from("/foo"), 6), - (PathBuf::from("/foo/bar"), 12), - (PathBuf::from("/foo/bar/baz"), 18), - ]); + assert_eq!( + map.remove("/foo"), + vec![ + (PathBuf::from("/foo"), 6), + (PathBuf::from("/foo/bar"), 12), + (PathBuf::from("/foo/bar/baz"), 18), + ] + ); assert_eq!(map.get("/foo"), None); assert_eq!(map.get("/foo/bar"), None); @@ -268,11 +276,9 @@ mod test { map.insert("/foo", 6); map.insert("/foo/bar/baz", 12); - assert_eq!(map.remove("/foo"), vec![ - (PathBuf::from("/foo"), 6), - ]); + assert_eq!(map.remove("/foo"), vec![(PathBuf::from("/foo"), 6),]); assert_eq!(map.get("/foo"), None); assert_eq!(map.get("/foo/bar/baz"), Some(&12)); } -} \ No newline at end of file +} diff --git a/server/src/path_serializer.rs b/server/src/path_serializer.rs index d7880b88..fefe22e4 100644 --- a/server/src/path_serializer.rs +++ b/server/src/path_serializer.rs @@ -33,22 +33,27 @@ use std::path::{Component, Path}; use serde::Serializer; pub fn serialize_option(maybe_path: &Option, serializer: S) -> Result - where S: Serializer, - T: AsRef, +where + S: Serializer, + T: AsRef, { match maybe_path { Some(path) => serialize(path, serializer), - None => serializer.serialize_none() + None => serializer.serialize_none(), } } pub fn serialize(path: T, serializer: S) -> Result - where S: Serializer, - T: AsRef, +where + S: Serializer, + T: AsRef, { let path = path.as_ref(); - assert!(path.is_relative(), "path_serializer can only handle relative paths"); + assert!( + path.is_relative(), + "path_serializer can only handle relative paths" + ); let mut output = String::new(); @@ -66,4 +71,4 @@ pub fn serialize(path: T, serializer: S) -> Result } serializer.serialize_str(&output) -} \ No newline at end of file +} diff --git a/server/src/project.rs b/server/src/project.rs index f788b0e3..4d0b70a8 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -1,15 +1,15 @@ use std::{ - collections::{HashMap, HashSet, BTreeMap}, + collections::{BTreeMap, HashMap, HashSet}, fmt, fs::{self, File}, io, path::{Path, PathBuf}, }; -use log::warn; use failure::Fail; -use rbx_dom_weak::{UnresolvedRbxValue, RbxValue}; -use serde::{Serialize, Serializer, Deserialize}; +use log::warn; +use rbx_dom_weak::{RbxValue, UnresolvedRbxValue}; +use serde::{Deserialize, Serialize, Serializer}; static DEFAULT_PLACE: &'static str = include_str!("../assets/place.project.json"); @@ -40,7 +40,8 @@ impl SourceProject { /// Consumes the SourceProject and yields a Project, ready for prime-time. pub fn into_project(mut self, project_file_location: &Path) -> Project { let tree = self.tree.into_project_node(project_file_location); - let plugins = self.plugins + let plugins = self + .plugins .drain(..) .map(|source_plugin| source_plugin.into_plugin(project_file_location)) .collect(); @@ -76,43 +77,48 @@ impl SourceProject { /// /// This holds true for other values that might be ambiguous or just have more /// complicated representations like enums. -fn serialize_unresolved_minimal(unresolved: &UnresolvedRbxValue, serializer: S) -> Result - where S: Serializer +fn serialize_unresolved_minimal( + unresolved: &UnresolvedRbxValue, + serializer: S, +) -> Result +where + S: Serializer, { match unresolved { UnresolvedRbxValue::Ambiguous(_) => unresolved.serialize(serializer), - UnresolvedRbxValue::Concrete(concrete) => { - match concrete { - RbxValue::Bool { value } => value.serialize(serializer), - RbxValue::CFrame { value } => value.serialize(serializer), - RbxValue::Color3 { value } => value.serialize(serializer), - RbxValue::Color3uint8 { value } => value.serialize(serializer), - RbxValue::Content { value } => value.serialize(serializer), - RbxValue::Float32 { value } => value.serialize(serializer), - RbxValue::Int32 { value } => value.serialize(serializer), - RbxValue::String { value } => value.serialize(serializer), - RbxValue::UDim { value } => value.serialize(serializer), - RbxValue::UDim2 { value } => value.serialize(serializer), - RbxValue::Vector2 { value } => value.serialize(serializer), - RbxValue::Vector2int16 { value } => value.serialize(serializer), - RbxValue::Vector3 { value } => value.serialize(serializer), - RbxValue::Vector3int16 { value } => value.serialize(serializer), - _ => concrete.serialize(serializer), - } + UnresolvedRbxValue::Concrete(concrete) => match concrete { + RbxValue::Bool { value } => value.serialize(serializer), + RbxValue::CFrame { value } => value.serialize(serializer), + RbxValue::Color3 { value } => value.serialize(serializer), + RbxValue::Color3uint8 { value } => value.serialize(serializer), + RbxValue::Content { value } => value.serialize(serializer), + RbxValue::Float32 { value } => value.serialize(serializer), + RbxValue::Int32 { value } => value.serialize(serializer), + RbxValue::String { value } => value.serialize(serializer), + RbxValue::UDim { value } => value.serialize(serializer), + RbxValue::UDim2 { value } => value.serialize(serializer), + RbxValue::Vector2 { value } => value.serialize(serializer), + RbxValue::Vector2int16 { value } => value.serialize(serializer), + RbxValue::Vector3 { value } => value.serialize(serializer), + RbxValue::Vector3int16 { value } => value.serialize(serializer), + _ => concrete.serialize(serializer), }, } } /// A wrapper around serialize_unresolved_minimal that handles the HashMap case. -fn serialize_unresolved_map(value: &HashMap, serializer: S) -> Result - where S: Serializer +fn serialize_unresolved_map( + value: &HashMap, + serializer: S, +) -> Result +where + S: Serializer, { use serde::ser::SerializeMap; #[derive(Serialize)] struct Minimal<'a>( - #[serde(serialize_with = "serialize_unresolved_minimal")] - &'a UnresolvedRbxValue + #[serde(serialize_with = "serialize_unresolved_minimal")] &'a UnresolvedRbxValue, ); let mut map = serializer.serialize_map(Some(value.len()))?; @@ -135,11 +141,14 @@ struct SourceProjectNode { rename = "$properties", default = "HashMap::new", skip_serializing_if = "HashMap::is_empty", - serialize_with = "serialize_unresolved_map", + serialize_with = "serialize_unresolved_map" )] properties: HashMap, - #[serde(rename = "$ignoreUnknownInstances", skip_serializing_if = "Option::is_none")] + #[serde( + rename = "$ignoreUnknownInstances", + skip_serializing_if = "Option::is_none" + )] ignore_unknown_instances: Option, #[serde(rename = "$path", skip_serializing_if = "Option::is_none")] @@ -152,8 +161,15 @@ struct SourceProjectNode { impl SourceProjectNode { /// Consumes the SourceProjectNode and turns it into a ProjectNode. pub fn into_project_node(self, project_file_location: &Path) -> ProjectNode { - let children = self.children.iter() - .map(|(key, value)| (key.clone(), value.clone().into_project_node(project_file_location))) + let children = self + .children + .iter() + .map(|(key, value)| { + ( + key.clone(), + value.clone().into_project_node(project_file_location), + ) + }) .collect(); // Make sure that paths are absolute, transforming them by adding the @@ -191,9 +207,7 @@ impl SourcePlugin { project_folder_location.join(self.path) }; - Plugin { - path, - } + Plugin { path } } } @@ -219,15 +233,16 @@ impl fmt::Display for ProjectLoadError { use self::ProjectLoadError::*; match self { - NotFound => { - write!(formatter, "Project file not found") - } + NotFound => write!(formatter, "Project file not found"), Io { inner, path } => { write!(formatter, "I/O error: {} in path {}", inner, path.display()) } - Json { inner, path } => { - write!(formatter, "JSON error: {} in path {}", inner, path.display()) - } + Json { inner, path } => write!( + formatter, + "JSON error: {} in path {}", + inner, + path.display() + ), } } } @@ -244,7 +259,9 @@ pub enum ProjectInitError { impl fmt::Display for ProjectInitError { fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { match self { - ProjectInitError::AlreadyExists(path) => write!(output, "Path {} already exists", path.display()), + ProjectInitError::AlreadyExists(path) => { + write!(output, "Path {} already exists", path.display()) + } ProjectInitError::IoError(inner) => write!(output, "IO error: {}", inner), ProjectInitError::SaveError(inner) => write!(output, "{}", inner), ProjectInitError::JsonError(inner) => write!(output, "{}", inner), @@ -277,8 +294,13 @@ impl ProjectNode { fn validate_reserved_names(&self) { for (name, child) in &self.children { if name.starts_with('$') { - warn!("Keys starting with '$' are reserved by Rojo to ensure forward compatibility."); - warn!("This project uses the key '{}', which should be renamed.", name); + warn!( + "Keys starting with '$' are reserved by Rojo to ensure forward compatibility." + ); + warn!( + "This project uses the key '{}', which should be renamed.", + name + ); } child.validate_reserved_names(); @@ -286,7 +308,9 @@ impl ProjectNode { } fn to_source_node(&self, project_file_location: &Path) -> SourceProjectNode { - let children = self.children.iter() + let children = self + .children + .iter() .map(|(key, value)| (key.clone(), value.to_source_node(project_file_location))) .collect(); @@ -329,9 +353,7 @@ impl Plugin { Err(_) => format!("{}", self.path.display()), }; - SourcePlugin { - path, - } + SourcePlugin { path } } } @@ -351,13 +373,18 @@ impl Project { let project_name = if project_fuzzy_path == project_path { project_fuzzy_path - .parent().expect("Path did not have a parent directory") - .file_name().expect("Path did not have a file name") - .to_str().expect("Path had invalid Unicode") + .parent() + .expect("Path did not have a parent directory") + .file_name() + .expect("Path did not have a file name") + .to_str() + .expect("Path had invalid Unicode") } else { project_fuzzy_path - .file_name().expect("Path did not have a file name") - .to_str().expect("Path had invalid Unicode") + .file_name() + .expect("Path did not have a file name") + .to_str() + .expect("Path had invalid Unicode") }; let mut project = Project::load_from_str(DEFAULT_PLACE, &project_path) @@ -365,8 +392,7 @@ impl Project { project.name = project_name.to_owned(); - project.save() - .map_err(ProjectInitError::SaveError)?; + project.save().map_err(ProjectInitError::SaveError)?; Ok(project_path) } @@ -376,17 +402,23 @@ impl Project { let project_name = if project_fuzzy_path == project_path { project_fuzzy_path - .parent().expect("Path did not have a parent directory") - .file_name().expect("Path did not have a file name") - .to_str().expect("Path had invalid Unicode") + .parent() + .expect("Path did not have a parent directory") + .file_name() + .expect("Path did not have a file name") + .to_str() + .expect("Path had invalid Unicode") } else { project_fuzzy_path - .file_name().expect("Path did not have a file name") - .to_str().expect("Path had invalid Unicode") + .file_name() + .expect("Path did not have a file name") + .to_str() + .expect("Path had invalid Unicode") }; let project_folder_path = project_path - .parent().expect("Path did not have a parent directory"); + .parent() + .expect("Path did not have a parent directory"); let tree = ProjectNode { path: Some(project_folder_path.join("src")), @@ -402,8 +434,7 @@ impl Project { file_location: project_path.clone(), }; - project.save() - .map_err(ProjectInitError::SaveError)?; + project.save().map_err(ProjectInitError::SaveError)?; Ok(project_path) } @@ -419,7 +450,7 @@ impl Project { match fs::metadata(&project_path) { Err(error) => match error.kind() { - io::ErrorKind::NotFound => {}, + io::ErrorKind::NotFound => {} _ => return Err(ProjectInitError::IoError(error)), }, Ok(_) => return Err(ProjectInitError::AlreadyExists(project_path)), @@ -459,13 +490,19 @@ impl Project { } } - fn load_from_str(contents: &str, project_file_location: &Path) -> Result { + fn load_from_str( + contents: &str, + project_file_location: &Path, + ) -> Result { let parsed: SourceProject = serde_json::from_str(&contents)?; Ok(parsed.into_project(project_file_location)) } - pub fn load_from_slice(contents: &[u8], project_file_location: &Path) -> Result { + pub fn load_from_slice( + contents: &[u8], + project_file_location: &Path, + ) -> Result { let parsed: SourceProject = serde_json::from_slice(&contents)?; Ok(parsed.into_project(project_file_location)) @@ -481,17 +518,17 @@ impl Project { } pub fn load_exact(project_file_location: &Path) -> Result { - let contents = fs::read_to_string(project_file_location) - .map_err(|error| match error.kind() { + let contents = + fs::read_to_string(project_file_location).map_err(|error| match error.kind() { io::ErrorKind::NotFound => ProjectLoadError::NotFound, _ => ProjectLoadError::Io { inner: error, path: project_file_location.to_path_buf(), - } + }, })?; - let parsed: SourceProject = serde_json::from_str(&contents) - .map_err(|error| ProjectLoadError::Json { + let parsed: SourceProject = + serde_json::from_str(&contents).map_err(|error| ProjectLoadError::Json { inner: error, path: project_file_location.to_path_buf(), })?; @@ -504,8 +541,7 @@ impl Project { pub fn save(&self) -> Result<(), ProjectSaveError> { let source_project = self.to_source_project(); - let mut file = File::create(&self.file_location) - .map_err(ProjectSaveError::IoError)?; + let mut file = File::create(&self.file_location).map_err(ProjectSaveError::IoError)?; serde_json::to_writer_pretty(&mut file, &source_project) .map_err(ProjectSaveError::JsonError)?; @@ -516,9 +552,12 @@ impl Project { /// Checks if there are any compatibility issues with this project file and /// warns the user if there are any. fn check_compatibility(&self) { - let file_name = self.file_location - .file_name().expect("Project file path did not have a file name") - .to_str().expect("Project file path was not valid Unicode"); + let file_name = self + .file_location + .file_name() + .expect("Project file path did not have a file name") + .to_str() + .expect("Project file path was not valid Unicode"); if file_name == COMPAT_PROJECT_FILENAME { warn!("Rojo's default project file name changed in 0.5.0-alpha3."); @@ -554,7 +593,8 @@ impl Project { } fn to_source_project(&self) -> SourceProject { - let plugins = self.plugins + let plugins = self + .plugins .iter() .map(|plugin| plugin.to_source_plugin(&self.file_location)) .collect(); @@ -567,4 +607,4 @@ impl Project { serve_place_ids: self.serve_place_ids.clone(), } } -} \ No newline at end of file +} diff --git a/server/src/serve_session.rs b/server/src/serve_session.rs index 6f909e1d..2eb40af8 100644 --- a/server/src/serve_session.rs +++ b/server/src/serve_session.rs @@ -1,9 +1,6 @@ use std::collections::HashSet; -use crate::{ - project::Project, - session_id::SessionId, -}; +use crate::{project::Project, session_id::SessionId}; /// Contains all of the state for a Rojo serve session. pub struct ServeSession { @@ -30,4 +27,4 @@ impl ServeSession { .as_ref() .and_then(|project| project.serve_place_ids.as_ref()) } -} \ No newline at end of file +} diff --git a/server/src/session_id.rs b/server/src/session_id.rs index 5aae5661..e025de1b 100644 --- a/server/src/session_id.rs +++ b/server/src/session_id.rs @@ -1,4 +1,4 @@ -use serde::{Serialize, Deserialize}; +use serde::{Deserialize, Serialize}; use uuid::Uuid; #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] @@ -8,4 +8,4 @@ impl SessionId { pub fn new() -> SessionId { SessionId(Uuid::new_v4()) } -} \ No newline at end of file +} diff --git a/server/src/snapshot/instance_snapshot.rs b/server/src/snapshot/instance_snapshot.rs index a7e1f7cb..6adeb5b2 100644 --- a/server/src/snapshot/instance_snapshot.rs +++ b/server/src/snapshot/instance_snapshot.rs @@ -1,11 +1,8 @@ //! Defines the structure of an instance snapshot. -use std::{ - borrow::Cow, - collections::HashMap, -}; +use std::{borrow::Cow, collections::HashMap}; -use rbx_dom_weak::{RbxTree, RbxId, RbxValue}; +use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; /// A lightweight description of what an instance should look like. Attempts to /// be somewhat memory efficient by borrowing from its source data, indicated by @@ -22,13 +19,14 @@ pub struct InstanceSnapshot<'source> { pub class_name: Cow<'source, str>, pub properties: HashMap, pub children: Vec>, - // TODO: Snapshot source, like a file or a project node? } impl<'source> InstanceSnapshot<'source> { pub fn get_owned(&'source self) -> InstanceSnapshot<'static> { - let children: Vec> = self.children.iter() + let children: Vec> = self + .children + .iter() .map(InstanceSnapshot::get_owned) .collect(); @@ -42,10 +40,12 @@ impl<'source> InstanceSnapshot<'source> { } pub fn from_tree(tree: &RbxTree, id: RbxId) -> InstanceSnapshot<'static> { - let instance = tree.get_instance(id) + let instance = tree + .get_instance(id) .expect("instance did not exist in tree"); - let children = instance.get_children_ids() + let children = instance + .get_children_ids() .iter() .cloned() .map(|id| InstanceSnapshot::from_tree(tree, id)) @@ -59,4 +59,4 @@ impl<'source> InstanceSnapshot<'source> { children, } } -} \ No newline at end of file +} diff --git a/server/src/snapshot/mod.rs b/server/src/snapshot/mod.rs index b83dd771..f6cc3c3f 100644 --- a/server/src/snapshot/mod.rs +++ b/server/src/snapshot/mod.rs @@ -18,12 +18,12 @@ #![allow(dead_code)] +mod instance_snapshot; mod patch; mod patch_apply; mod patch_compute; -mod instance_snapshot; pub use instance_snapshot::InstanceSnapshot; +pub use patch::*; pub use patch_apply::apply_patch_set; pub use patch_compute::compute_patch_set; -pub use patch::*; \ No newline at end of file diff --git a/server/src/snapshot/patch.rs b/server/src/snapshot/patch.rs index 4dcb6a6b..15fdc6ba 100644 --- a/server/src/snapshot/patch.rs +++ b/server/src/snapshot/patch.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; -use rbx_dom_weak::{RbxValue, RbxId}; +use rbx_dom_weak::{RbxId, RbxValue}; use super::InstanceSnapshot; @@ -41,4 +41,4 @@ pub struct PatchUpdateInstance { /// Contains all changed properties. If a property is assigned to `None`, /// then that property has been removed. pub changed_properties: HashMap>, -} \ No newline at end of file +} diff --git a/server/src/snapshot/patch_apply.rs b/server/src/snapshot/patch_apply.rs index b21a8fb6..246fdd02 100644 --- a/server/src/snapshot/patch_apply.rs +++ b/server/src/snapshot/patch_apply.rs @@ -2,17 +2,14 @@ use std::collections::HashMap; -use rbx_dom_weak::{RbxTree, RbxValue, RbxId, RbxInstanceProperties}; +use rbx_dom_weak::{RbxId, RbxInstanceProperties, RbxTree, RbxValue}; use super::{ patch::{PatchSet, PatchUpdateInstance}, InstanceSnapshot, }; -pub fn apply_patch_set( - tree: &mut RbxTree, - patch_set: &PatchSet, -) { +pub fn apply_patch_set(tree: &mut RbxTree, patch_set: &PatchSet) { let mut context = PatchApplyContext::default(); for removed_id in &patch_set.removed_instances { @@ -47,13 +44,16 @@ struct PatchApplyContext { /// then apply properties all at once at the end. fn apply_deferred_properties(context: PatchApplyContext, tree: &mut RbxTree) { for (id, mut properties) in context.properties_to_apply { - let instance = tree.get_instance_mut(id) + let instance = tree + .get_instance_mut(id) .expect("Invalid instance ID in deferred property map"); for property_value in properties.values_mut() { if let RbxValue::Ref { value: Some(id) } = property_value { if let Some(&instance_id) = context.snapshot_id_to_instance_id.get(id) { - *property_value = RbxValue::Ref { value: Some(instance_id) }; + *property_value = RbxValue::Ref { + value: Some(instance_id), + }; } } } @@ -79,7 +79,9 @@ fn apply_add_child( let id = tree.insert_instance(properties, parent_id); - context.properties_to_apply.insert(id, snapshot.properties.clone()); + context + .properties_to_apply + .insert(id, snapshot.properties.clone()); if let Some(snapshot_id) = snapshot.snapshot_id { context.snapshot_id_to_instance_id.insert(snapshot_id, id); @@ -95,7 +97,8 @@ fn apply_update_child( tree: &mut RbxTree, patch: &PatchUpdateInstance, ) { - let instance = tree.get_instance_mut(patch.id) + let instance = tree + .get_instance_mut(patch.id) .expect("Instance referred to by patch does not exist"); if let Some(name) = &patch.changed_name { @@ -114,9 +117,12 @@ fn apply_update_child( Some(RbxValue::Ref { value: Some(id) }) => { let new_id = context.snapshot_id_to_instance_id.get(id).unwrap_or(id); - instance.properties.insert(key.clone(), RbxValue::Ref { - value: Some(*new_id), - }); + instance.properties.insert( + key.clone(), + RbxValue::Ref { + value: Some(*new_id), + }, + ); } Some(value) => { instance.properties.insert(key.clone(), value.clone()); @@ -132,10 +138,7 @@ fn apply_update_child( mod test { use super::*; - use std::{ - borrow::Cow, - collections::HashMap, - }; + use std::{borrow::Cow, collections::HashMap}; use maplit::hashmap; use rbx_dom_weak::RbxValue; @@ -165,12 +168,10 @@ mod test { }; let patch_set = PatchSet { - added_instances: vec![ - PatchAddInstance { - parent_id: root_id, - instance: snapshot.clone(), - } - ], + added_instances: vec![PatchAddInstance { + parent_id: root_id, + instance: snapshot.clone(), + }], ..Default::default() }; @@ -236,4 +237,4 @@ mod test { assert_eq!(root_instance.class_name, "NewClassName"); assert_eq!(root_instance.properties, expected_properties); } -} \ No newline at end of file +} diff --git a/server/src/snapshot/patch_compute.rs b/server/src/snapshot/patch_compute.rs index 78ed2769..6ef5d36a 100644 --- a/server/src/snapshot/patch_compute.rs +++ b/server/src/snapshot/patch_compute.rs @@ -3,11 +3,11 @@ use std::collections::{HashMap, HashSet}; -use rbx_dom_weak::{RbxTree, RbxValue, RbxId, RbxInstance}; +use rbx_dom_weak::{RbxId, RbxInstance, RbxTree, RbxValue}; use super::{ + patch::{PatchAddInstance, PatchSet, PatchUpdateInstance}, InstanceSnapshot, - patch::{PatchSet, PatchAddInstance, PatchUpdateInstance}, }; pub fn compute_patch_set<'a>( @@ -38,7 +38,9 @@ fn rewrite_refs_in_updates(context: &ComputePatchContext, updates: &mut [PatchUp for property_value in update.changed_properties.values_mut() { if let Some(RbxValue::Ref { value: Some(id) }) = property_value { if let Some(&instance_id) = context.snapshot_id_to_instance_id.get(id) { - *property_value = Some(RbxValue::Ref { value: Some(instance_id) }); + *property_value = Some(RbxValue::Ref { + value: Some(instance_id), + }); } } } @@ -55,7 +57,9 @@ fn rewrite_refs_in_snapshot(context: &ComputePatchContext, snapshot: &mut Instan for property_value in snapshot.properties.values_mut() { if let RbxValue::Ref { value: Some(id) } = property_value { if let Some(&instance_id) = context.snapshot_id_to_instance_id.get(id) { - *property_value = RbxValue::Ref { value: Some(instance_id) }; + *property_value = RbxValue::Ref { + value: Some(instance_id), + }; } } } @@ -76,7 +80,8 @@ fn compute_patch_set_internal<'a>( context.snapshot_id_to_instance_id.insert(snapshot_id, id); } - let instance = tree.get_instance(id) + let instance = tree + .get_instance(id) .expect("Instance did not exist in tree"); compute_property_patches(snapshot, instance, patch_set); @@ -145,7 +150,8 @@ fn compute_children_patches<'a>( id: RbxId, patch_set: &mut PatchSet<'a>, ) { - let instance = tree.get_instance(id) + let instance = tree + .get_instance(id) .expect("Instance did not exist in tree"); let instance_children = instance.get_children_ids(); @@ -153,30 +159,38 @@ fn compute_children_patches<'a>( let mut paired_instances = vec![false; instance_children.len()]; for snapshot_child in snapshot.children.iter() { - let matching_instance = instance_children - .iter() - .enumerate() - .find(|(instance_index, instance_child_id)| { - if paired_instances[*instance_index] { - return false; - } + let matching_instance = + instance_children + .iter() + .enumerate() + .find(|(instance_index, instance_child_id)| { + if paired_instances[*instance_index] { + return false; + } - let instance_child = tree.get_instance(**instance_child_id) - .expect("Instance did not exist in tree"); + let instance_child = tree + .get_instance(**instance_child_id) + .expect("Instance did not exist in tree"); - if snapshot_child.name == instance_child.name && - instance_child.class_name == instance_child.class_name - { - paired_instances[*instance_index] = true; - return true; - } + if snapshot_child.name == instance_child.name + && instance_child.class_name == instance_child.class_name + { + paired_instances[*instance_index] = true; + return true; + } - false - }); + false + }); match matching_instance { Some((_, instance_child_id)) => { - compute_patch_set_internal(context, snapshot_child, tree, *instance_child_id, patch_set); + compute_patch_set_internal( + context, + snapshot_child, + tree, + *instance_child_id, + patch_set, + ); } None => { patch_set.added_instances.push(PatchAddInstance { @@ -238,18 +252,16 @@ mod test { let patch_set = compute_patch_set(&snapshot, &tree, root_id); let expected_patch_set = PatchSet { - updated_instances: vec![ - PatchUpdateInstance { - id: root_id, - changed_name: None, - changed_class_name: None, - changed_properties: hashmap! { - "Self".to_owned() => Some(RbxValue::Ref { - value: Some(root_id), - }), - }, + updated_instances: vec![PatchUpdateInstance { + id: root_id, + changed_name: None, + changed_class_name: None, + changed_properties: hashmap! { + "Self".to_owned() => Some(RbxValue::Ref { + value: Some(root_id), + }), }, - ], + }], added_instances: Vec::new(), removed_instances: Vec::new(), }; @@ -274,20 +286,18 @@ mod test { let snapshot_id = RbxId::new(); let snapshot = InstanceSnapshot { snapshot_id: Some(snapshot_id), - children: vec![ - InstanceSnapshot { - properties: hashmap! { - "Self".to_owned() => RbxValue::Ref { - value: Some(snapshot_id), - }, + children: vec![InstanceSnapshot { + properties: hashmap! { + "Self".to_owned() => RbxValue::Ref { + value: Some(snapshot_id), }, + }, - snapshot_id: None, - name: Cow::Borrowed("child"), - class_name: Cow::Borrowed("child"), - children: Vec::new(), - } - ], + snapshot_id: None, + name: Cow::Borrowed("child"), + class_name: Cow::Borrowed("child"), + children: Vec::new(), + }], properties: HashMap::new(), name: Cow::Borrowed("foo"), @@ -297,26 +307,24 @@ mod test { let patch_set = compute_patch_set(&snapshot, &tree, root_id); let expected_patch_set = PatchSet { - added_instances: vec![ - PatchAddInstance { - parent_id: root_id, - instance: InstanceSnapshot { - snapshot_id: None, - properties: hashmap! { - "Self".to_owned() => RbxValue::Ref { - value: Some(root_id), - }, + added_instances: vec![PatchAddInstance { + parent_id: root_id, + instance: InstanceSnapshot { + snapshot_id: None, + properties: hashmap! { + "Self".to_owned() => RbxValue::Ref { + value: Some(root_id), }, - name: Cow::Borrowed("child"), - class_name: Cow::Borrowed("child"), - children: Vec::new(), }, + name: Cow::Borrowed("child"), + class_name: Cow::Borrowed("child"), + children: Vec::new(), }, - ], + }], updated_instances: Vec::new(), removed_instances: Vec::new(), }; assert_eq!(patch_set, expected_patch_set); } -} \ No newline at end of file +} diff --git a/server/src/snapshot_middleware/context.rs b/server/src/snapshot_middleware/context.rs index 7dfc9c6c..f423c027 100644 --- a/server/src/snapshot_middleware/context.rs +++ b/server/src/snapshot_middleware/context.rs @@ -4,4 +4,4 @@ pub struct InstanceSnapshotContext { pub plugin_context: Option<()>, } -pub struct ImfsSnapshotContext; \ No newline at end of file +pub struct ImfsSnapshotContext; diff --git a/server/src/snapshot_middleware/csv.rs b/server/src/snapshot_middleware/csv.rs index a211d466..fdf532af 100644 --- a/server/src/snapshot_middleware/csv.rs +++ b/server/src/snapshot_middleware/csv.rs @@ -1,20 +1,15 @@ -use std::{ - borrow::Cow, - collections::BTreeMap, -}; +use std::{borrow::Cow, collections::BTreeMap}; use maplit::hashmap; -use rbx_dom_weak::{RbxTree, RbxValue, RbxId}; +use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; use serde::Serialize; use crate::{ - imfs::new::{Imfs, ImfsFetcher, ImfsEntry}, + imfs::new::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, }; -use super::{ - middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, -}; +use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; pub struct SnapshotCsv; @@ -27,16 +22,18 @@ impl SnapshotMiddleware for SnapshotCsv { return Ok(None); } - let file_name = entry.path() - .file_name().unwrap().to_string_lossy(); + let file_name = entry.path().file_name().unwrap().to_string_lossy(); if !file_name.ends_with(".csv") { - return Ok(None); + return Ok(None); } - let instance_name = entry.path() - .file_stem().expect("Could not extract file stem") - .to_string_lossy().to_string(); + let instance_name = entry + .path() + .file_stem() + .expect("Could not extract file stem") + .to_string_lossy() + .to_string(); let table_contents = convert_localization_csv(entry.contents(imfs)?); @@ -53,10 +50,7 @@ impl SnapshotMiddleware for SnapshotCsv { })) } - fn from_instance( - _tree: &RbxTree, - _id: RbxId, - ) -> SnapshotFileResult { + fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { unimplemented!("Snapshotting CSV localization tables"); } } @@ -96,15 +90,12 @@ struct LocalizationEntry<'a> { fn convert_localization_csv(contents: &[u8]) -> String { let mut reader = csv::Reader::from_reader(contents); - let headers = reader.headers() - .expect("TODO: Handle csv errors") - .clone(); + let headers = reader.headers().expect("TODO: Handle csv errors").clone(); let mut records = Vec::new(); for record in reader.into_records() { - let record = record - .expect("TODO: Handle csv errors"); + let record = record.expect("TODO: Handle csv errors"); records.push(record); } @@ -137,8 +128,7 @@ fn convert_localization_csv(contents: &[u8]) -> String { entries.push(entry); } - serde_json::to_string(&entries) - .expect("Could not encode JSON for localization table") + serde_json::to_string(&entries).expect("Could not encode JSON for localization table") } #[cfg(test)] @@ -150,9 +140,11 @@ mod test { #[test] fn csv_from_imfs() { let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file(r#" + let file = ImfsSnapshot::file( + r#" Key,Source,Context,Example,es -Ack,Ack!,,An exclamation of despair,¡Ay!"#); +Ack,Ack!,,An exclamation of despair,¡Ay!"#, + ); imfs.load_from_snapshot("/foo.csv", file); @@ -165,10 +157,13 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#); assert_eq!(instance_snapshot.name, "foo"); assert_eq!(instance_snapshot.class_name, "LocalizationTable"); assert_eq!(instance_snapshot.children, Vec::new()); - assert_eq!(instance_snapshot.properties, hashmap! { - "Contents".to_owned() => RbxValue::String { - value: expected_contents.to_owned(), - }, - }); + assert_eq!( + instance_snapshot.properties, + hashmap! { + "Contents".to_owned() => RbxValue::String { + value: expected_contents.to_owned(), + }, + } + ); } -} \ No newline at end of file +} diff --git a/server/src/snapshot_middleware/dir.rs b/server/src/snapshot_middleware/dir.rs index 3708abb2..1d7de937 100644 --- a/server/src/snapshot_middleware/dir.rs +++ b/server/src/snapshot_middleware/dir.rs @@ -1,19 +1,15 @@ -use std::{ - borrow::Cow, - collections::HashMap, -}; +use std::{borrow::Cow, collections::HashMap}; -use rbx_dom_weak::{RbxTree, RbxId}; +use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ - imfs::new::{Imfs, ImfsSnapshot, DirectorySnapshot, ImfsFetcher, ImfsEntry}, + imfs::new::{DirectorySnapshot, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, snapshot::InstanceSnapshot, }; use super::{ - snapshot_from_imfs, - snapshot_from_instance, - middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, + middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + snapshot_from_imfs, snapshot_from_instance, }; pub struct SnapshotDir; @@ -37,9 +33,13 @@ impl SnapshotMiddleware for SnapshotDir { } } - let instance_name = entry.path() - .file_name().expect("Could not extract file name") - .to_str().unwrap().to_string(); + let instance_name = entry + .path() + .file_name() + .expect("Could not extract file name") + .to_str() + .unwrap() + .to_string(); Ok(Some(InstanceSnapshot { snapshot_id: None, @@ -50,10 +50,7 @@ impl SnapshotMiddleware for SnapshotDir { })) } - fn from_instance( - tree: &RbxTree, - id: RbxId, - ) -> SnapshotFileResult { + fn from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult { let instance = tree.get_instance(id).unwrap(); if instance.class_name != "Folder" { @@ -68,9 +65,7 @@ impl SnapshotMiddleware for SnapshotDir { } } - let snapshot = ImfsSnapshot::Directory(DirectorySnapshot { - children, - }); + let snapshot = ImfsSnapshot::Directory(DirectorySnapshot { children }); Some((instance.name.clone(), snapshot)) } @@ -123,4 +118,4 @@ mod test { assert_eq!(child.properties, HashMap::new()); assert_eq!(child.children, Vec::new()); } -} \ No newline at end of file +} diff --git a/server/src/snapshot_middleware/error.rs b/server/src/snapshot_middleware/error.rs index 263d89b0..7eb43e55 100644 --- a/server/src/snapshot_middleware/error.rs +++ b/server/src/snapshot_middleware/error.rs @@ -1,12 +1,6 @@ -use std::{ - fmt, - error::Error, - path::PathBuf, -}; +use std::{error::Error, fmt, path::PathBuf}; -use crate::{ - snapshot::InstanceSnapshot, -}; +use crate::snapshot::InstanceSnapshot; pub type SnapshotResult<'a> = Result>, SnapshotError>; @@ -43,9 +37,7 @@ impl SnapshotError { path: impl Into, ) -> SnapshotError { SnapshotError { - detail: SnapshotErrorDetail::FileContentsBadUnicode { - inner, - }, + detail: SnapshotErrorDetail::FileContentsBadUnicode { inner }, path: Some(path.into()), } } @@ -70,9 +62,7 @@ impl fmt::Display for SnapshotError { pub enum SnapshotErrorDetail { FileDidNotExist, FileNameBadUnicode, - FileContentsBadUnicode { - inner: std::str::Utf8Error, - }, + FileContentsBadUnicode { inner: std::str::Utf8Error }, } impl SnapshotErrorDetail { @@ -81,7 +71,7 @@ impl SnapshotErrorDetail { match self { FileContentsBadUnicode { inner } => Some(inner), - _ => None + _ => None, } } } @@ -93,7 +83,9 @@ impl fmt::Display for SnapshotErrorDetail { match self { FileDidNotExist => write!(formatter, "file did not exist"), FileNameBadUnicode => write!(formatter, "file name had malformed Unicode"), - FileContentsBadUnicode { inner } => write!(formatter, "file had malformed unicode: {}", inner), + FileContentsBadUnicode { inner } => { + write!(formatter, "file had malformed unicode: {}", inner) + } } } -} \ No newline at end of file +} diff --git a/server/src/snapshot_middleware/json_model.rs b/server/src/snapshot_middleware/json_model.rs index b7744d5b..4d4834f7 100644 --- a/server/src/snapshot_middleware/json_model.rs +++ b/server/src/snapshot_middleware/json_model.rs @@ -1,20 +1,15 @@ -use std::{ - borrow::Cow, - collections::HashMap, -}; +use std::{borrow::Cow, collections::HashMap}; +use rbx_dom_weak::{RbxId, RbxTree, UnresolvedRbxValue}; use rbx_reflection::try_resolve_value; -use rbx_dom_weak::{RbxTree, RbxId, UnresolvedRbxValue}; -use serde::{Deserialize}; +use serde::Deserialize; use crate::{ - imfs::new::{Imfs, ImfsFetcher, ImfsEntry}, + imfs::new::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, }; -use super::{ - middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, -}; +use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; pub struct SnapshotJsonModel; @@ -27,22 +22,30 @@ impl SnapshotMiddleware for SnapshotJsonModel { return Ok(None); } - let file_name = entry.path() - .file_name().unwrap().to_string_lossy(); + let file_name = entry.path().file_name().unwrap().to_string_lossy(); let instance_name = match match_trailing(&file_name, ".model.json") { Some(name) => name.to_owned(), None => return Ok(None), }; - let instance: JsonModel = serde_json::from_slice(entry.contents(imfs)?) - .expect("TODO: Handle serde_json errors"); + let instance: JsonModel = + serde_json::from_slice(entry.contents(imfs)?).expect("TODO: Handle serde_json errors"); if let Some(json_name) = &instance.name { if json_name != &instance_name { - log::warn!("Name from JSON model did not match its file name: {}", entry.path().display()); - log::warn!("In Rojo < alpha 14, this model is named \"{}\" (from its 'Name' property)", json_name); - log::warn!("In Rojo >= alpha 14, this model is named \"{}\" (from its file name)", instance_name); + log::warn!( + "Name from JSON model did not match its file name: {}", + entry.path().display() + ); + log::warn!( + "In Rojo < alpha 14, this model is named \"{}\" (from its 'Name' property)", + json_name + ); + log::warn!( + "In Rojo >= alpha 14, this model is named \"{}\" (from its file name)", + instance_name + ); log::warn!("'Name' for the top-level instance in a JSON model is now optional and will be ignored."); } } @@ -52,10 +55,7 @@ impl SnapshotMiddleware for SnapshotJsonModel { Ok(Some(snapshot)) } - fn from_instance( - _tree: &RbxTree, - _id: RbxId, - ) -> SnapshotFileResult { + fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { unimplemented!("Snapshotting models"); } } @@ -103,14 +103,17 @@ impl JsonModelCore { fn into_snapshot(self, name: String) -> InstanceSnapshot<'static> { let class_name = self.class_name; - let children = self.children.into_iter() + let children = self + .children + .into_iter() .map(|child| child.core.into_snapshot(child.name)) .collect(); - let properties = self.properties.into_iter() + let properties = self + .properties + .into_iter() .map(|(key, value)| { - try_resolve_value(&class_name, &key, &value) - .map(|resolved| (key, resolved)) + try_resolve_value(&class_name, &key, &value).map(|resolved| (key, resolved)) }) .collect::, _>>() .expect("TODO: Handle rbx_reflection errors"); @@ -137,7 +140,8 @@ mod test { #[test] fn model_from_imfs() { let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file(r#" + let file = ImfsSnapshot::file( + r#" { "Name": "children", "ClassName": "IntValue", @@ -151,31 +155,35 @@ mod test { } ] } - "#); + "#, + ); imfs.load_from_snapshot("/foo.model.json", file); let entry = imfs.get("/foo.model.json").unwrap(); - let instance_snapshot = SnapshotJsonModel::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = SnapshotJsonModel::from_imfs(&mut imfs, &entry) + .unwrap() + .unwrap(); - assert_eq!(instance_snapshot, InstanceSnapshot { - snapshot_id: None, - name: Cow::Borrowed("foo"), - class_name: Cow::Borrowed("IntValue"), - properties: hashmap! { - "Value".to_owned() => RbxValue::Int32 { - value: 5, + assert_eq!( + instance_snapshot, + InstanceSnapshot { + snapshot_id: None, + name: Cow::Borrowed("foo"), + class_name: Cow::Borrowed("IntValue"), + properties: hashmap! { + "Value".to_owned() => RbxValue::Int32 { + value: 5, + }, }, - }, - children: vec![ - InstanceSnapshot { + children: vec![InstanceSnapshot { snapshot_id: None, name: Cow::Borrowed("The Child"), class_name: Cow::Borrowed("StringValue"), properties: HashMap::new(), children: Vec::new(), - }, - ], - }); + },], + } + ); } -} \ No newline at end of file +} diff --git a/server/src/snapshot_middleware/lua.rs b/server/src/snapshot_middleware/lua.rs index a69728eb..a2e86495 100644 --- a/server/src/snapshot_middleware/lua.rs +++ b/server/src/snapshot_middleware/lua.rs @@ -1,19 +1,14 @@ -use std::{ - borrow::Cow, - str, -}; +use std::{borrow::Cow, str}; use maplit::hashmap; -use rbx_dom_weak::{RbxTree, RbxValue, RbxId}; +use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; use crate::{ - imfs::new::{Imfs, ImfsFetcher, ImfsEntry, FsResultExt}, + imfs::new::{FsResultExt, Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, }; -use super::{ - middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, -}; +use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; pub struct SnapshotLua; @@ -22,8 +17,7 @@ impl SnapshotMiddleware for SnapshotLua { imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { - let file_name = entry.path() - .file_name().unwrap().to_string_lossy(); + let file_name = entry.path().file_name().unwrap().to_string_lossy(); if entry.is_directory() { let module_init_path = entry.path().join("init.lua"); @@ -54,15 +48,16 @@ impl SnapshotMiddleware for SnapshotLua { } } - let (class_name, instance_name) = if let Some(name) = match_trailing(&file_name, ".server.lua") { - ("Script", name) - } else if let Some(name) = match_trailing(&file_name, ".client.lua") { - ("LocalScript", name) - } else if let Some(name) = match_trailing(&file_name, ".lua") { - ("ModuleScript", name) - } else { - return Ok(None); - }; + let (class_name, instance_name) = + if let Some(name) = match_trailing(&file_name, ".server.lua") { + ("Script", name) + } else if let Some(name) = match_trailing(&file_name, ".client.lua") { + ("LocalScript", name) + } else if let Some(name) = match_trailing(&file_name, ".lua") { + ("ModuleScript", name) + } else { + return Ok(None); + }; let contents = entry.contents(imfs)?; let contents_str = str::from_utf8(contents) @@ -84,14 +79,13 @@ impl SnapshotMiddleware for SnapshotLua { })) } - fn from_instance( - tree: &RbxTree, - id: RbxId, - ) -> SnapshotFileResult { + fn from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult { let instance = tree.get_instance(id).unwrap(); match instance.class_name.as_str() { - "ModuleScript" | "LocalScript" | "Script" => unimplemented!("Snapshotting Script instances"), + "ModuleScript" | "LocalScript" | "Script" => { + unimplemented!("Snapshotting Script instances") + } _ => None, } } @@ -126,11 +120,14 @@ mod test { assert_eq!(instance_snapshot.name, "foo"); assert_eq!(instance_snapshot.class_name, "ModuleScript"); - assert_eq!(instance_snapshot.properties, hashmap! { - "Source".to_owned() => RbxValue::String { - value: "Hello there!".to_owned(), - }, - }); + assert_eq!( + instance_snapshot.properties, + hashmap! { + "Source".to_owned() => RbxValue::String { + value: "Hello there!".to_owned(), + }, + } + ); } #[test] @@ -145,11 +142,14 @@ mod test { assert_eq!(instance_snapshot.name, "foo"); assert_eq!(instance_snapshot.class_name, "Script"); - assert_eq!(instance_snapshot.properties, hashmap! { - "Source".to_owned() => RbxValue::String { - value: "Hello there!".to_owned(), - }, - }); + assert_eq!( + instance_snapshot.properties, + hashmap! { + "Source".to_owned() => RbxValue::String { + value: "Hello there!".to_owned(), + }, + } + ); } #[test] @@ -164,10 +164,13 @@ mod test { assert_eq!(instance_snapshot.name, "foo"); assert_eq!(instance_snapshot.class_name, "LocalScript"); - assert_eq!(instance_snapshot.properties, hashmap! { - "Source".to_owned() => RbxValue::String { - value: "Hello there!".to_owned(), - }, - }); + assert_eq!( + instance_snapshot.properties, + hashmap! { + "Source".to_owned() => RbxValue::String { + value: "Hello there!".to_owned(), + }, + } + ); } -} \ No newline at end of file +} diff --git a/server/src/snapshot_middleware/middleware.rs b/server/src/snapshot_middleware/middleware.rs index 9dc54f53..045d1bde 100644 --- a/server/src/snapshot_middleware/middleware.rs +++ b/server/src/snapshot_middleware/middleware.rs @@ -1,18 +1,11 @@ -use std::{ - path::{PathBuf, Path}, -}; +use std::path::{Path, PathBuf}; -use rbx_dom_weak::{RbxTree, RbxId}; +use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ imfs::{ + new::{Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, FsResult, - new::{ - Imfs, - ImfsEntry, - ImfsFetcher, - ImfsSnapshot, - }, }, snapshot::InstanceSnapshot, }; @@ -26,14 +19,9 @@ pub trait SnapshotMiddleware { entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static>; - fn from_instance( - tree: &RbxTree, - id: RbxId, - ) -> SnapshotFileResult; + fn from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult; - fn change_affects_paths( - path: &Path - ) -> Vec { + fn change_affects_paths(path: &Path) -> Vec { vec![path.to_path_buf()] } -} \ No newline at end of file +} diff --git a/server/src/snapshot_middleware/mod.rs b/server/src/snapshot_middleware/mod.rs index 4a9183c0..840d4d35 100644 --- a/server/src/snapshot_middleware/mod.rs +++ b/server/src/snapshot_middleware/mod.rs @@ -15,20 +15,20 @@ mod rbxm; mod rbxmx; mod txt; -use rbx_dom_weak::{RbxTree, RbxId}; +use rbx_dom_weak::{RbxId, RbxTree}; -use crate::imfs::new::{Imfs, ImfsEntry, ImfsFetcher}; use self::{ - middleware::{SnapshotInstanceResult, SnapshotFileResult, SnapshotMiddleware}, csv::SnapshotCsv, dir::SnapshotDir, json_model::SnapshotJsonModel, lua::SnapshotLua, + middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, project::SnapshotProject, rbxm::SnapshotRbxm, rbxmx::SnapshotRbxmx, txt::SnapshotTxt, }; +use crate::imfs::new::{Imfs, ImfsEntry, ImfsFetcher}; macro_rules! middlewares { ( $($middleware: ident,)* ) => { @@ -73,4 +73,4 @@ middlewares! { SnapshotCsv, SnapshotTxt, SnapshotDir, -} \ No newline at end of file +} diff --git a/server/src/snapshot_middleware/project.rs b/server/src/snapshot_middleware/project.rs index 9cafa91b..ceaa4d7b 100644 --- a/server/src/snapshot_middleware/project.rs +++ b/server/src/snapshot_middleware/project.rs @@ -1,23 +1,20 @@ -use std::{ - borrow::Cow, - collections::HashMap, -}; +use std::{borrow::Cow, collections::HashMap}; -use rbx_dom_weak::{RbxTree, RbxId}; +use rbx_dom_weak::{RbxId, RbxTree}; use rbx_reflection::try_resolve_value; use crate::{ - project::{Project, ProjectNode}, imfs::{ + new::{Imfs, ImfsEntry, ImfsFetcher}, FsErrorKind, - new::{Imfs, ImfsFetcher, ImfsEntry}, }, + project::{Project, ProjectNode}, snapshot::InstanceSnapshot, }; use super::{ + middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, snapshot_from_imfs, - middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, }; pub struct SnapshotProject; @@ -38,7 +35,7 @@ impl SnapshotMiddleware for SnapshotProject { } if !entry.path().to_string_lossy().ends_with(".project.json") { - return Ok(None) + return Ok(None); } let project = Project::load_from_slice(entry.contents(imfs)?, entry.path()) @@ -47,10 +44,7 @@ impl SnapshotMiddleware for SnapshotProject { snapshot_project_node(&project.name, &project.tree, imfs) } - fn from_instance( - _tree: &RbxTree, - _id: RbxId, - ) -> SnapshotFileResult { + fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { // TODO: Supporting turning instances into projects None } @@ -61,10 +55,14 @@ fn snapshot_project_node( node: &ProjectNode, imfs: &mut Imfs, ) -> SnapshotInstanceResult<'static> { - assert!(node.ignore_unknown_instances.is_none(), "TODO: Support $ignoreUnknownInstances"); + assert!( + node.ignore_unknown_instances.is_none(), + "TODO: Support $ignoreUnknownInstances" + ); let name = Cow::Owned(instance_name.to_owned()); - let mut class_name = node.class_name + let mut class_name = node + .class_name .as_ref() .map(|name| Cow::Owned(name.clone())); let mut properties = HashMap::new(); @@ -90,7 +88,7 @@ fn snapshot_project_node( panic!("If $className and $path are specified, $path must yield an instance of class Folder"); } } - None => Some(snapshot.class_name) + None => Some(snapshot.class_name), }; // Properties from the snapshot are pulled in unchanged, and @@ -108,7 +106,9 @@ fn snapshot_project_node( } } else { // TODO: Should this issue an error instead? - log::warn!("$path referred to a path that could not be turned into an instance by Rojo"); + log::warn!( + "$path referred to a path that could not be turned into an instance by Rojo" + ); } } @@ -142,8 +142,8 @@ fn snapshot_project_node( mod test { use super::*; - use rbx_dom_weak::RbxValue; use maplit::hashmap; + use rbx_dom_weak::RbxValue; use crate::imfs::new::{ImfsSnapshot, NoopFetcher}; @@ -236,11 +236,14 @@ mod test { assert_eq!(instance_snapshot.name, "resolved-properties"); assert_eq!(instance_snapshot.class_name, "StringValue"); - assert_eq!(instance_snapshot.properties, hashmap! { - "Value".to_owned() => RbxValue::String { - value: "Hello, world!".to_owned(), - }, - }); + assert_eq!( + instance_snapshot.properties, + hashmap! { + "Value".to_owned() => RbxValue::String { + value: "Hello, world!".to_owned(), + }, + } + ); assert_eq!(instance_snapshot.children, Vec::new()); } @@ -272,11 +275,14 @@ mod test { assert_eq!(instance_snapshot.name, "unresolved-properties"); assert_eq!(instance_snapshot.class_name, "StringValue"); - assert_eq!(instance_snapshot.properties, hashmap! { - "Value".to_owned() => RbxValue::String { - value: "Hi!".to_owned(), - }, - }); + assert_eq!( + instance_snapshot.properties, + hashmap! { + "Value".to_owned() => RbxValue::String { + value: "Hi!".to_owned(), + }, + } + ); assert_eq!(instance_snapshot.children, Vec::new()); } @@ -345,11 +351,14 @@ mod test { assert_eq!(instance_snapshot.name, "path-project"); assert_eq!(instance_snapshot.class_name, "StringValue"); - assert_eq!(instance_snapshot.properties, hashmap! { - "Value".to_owned() => RbxValue::String { - value: "Hello, world!".to_owned(), - }, - }); + assert_eq!( + instance_snapshot.properties, + hashmap! { + "Value".to_owned() => RbxValue::String { + value: "Hello, world!".to_owned(), + }, + } + ); assert_eq!(instance_snapshot.children, Vec::new()); } @@ -479,11 +488,14 @@ mod test { assert_eq!(instance_snapshot.name, "path-property-override"); assert_eq!(instance_snapshot.class_name, "StringValue"); - assert_eq!(instance_snapshot.properties, hashmap! { - "Value".to_owned() => RbxValue::String { - value: "Changed".to_owned(), - }, - }); + assert_eq!( + instance_snapshot.properties, + hashmap! { + "Value".to_owned() => RbxValue::String { + value: "Changed".to_owned(), + }, + } + ); assert_eq!(instance_snapshot.children, Vec::new()); } -} \ No newline at end of file +} diff --git a/server/src/snapshot_middleware/rbxm.rs b/server/src/snapshot_middleware/rbxm.rs index 97d7efd9..156aa052 100644 --- a/server/src/snapshot_middleware/rbxm.rs +++ b/server/src/snapshot_middleware/rbxm.rs @@ -1,18 +1,13 @@ -use std::{ - borrow::Cow, - collections::HashMap, -}; +use std::{borrow::Cow, collections::HashMap}; -use rbx_dom_weak::{RbxTree, RbxInstanceProperties, RbxId}; +use rbx_dom_weak::{RbxId, RbxInstanceProperties, RbxTree}; use crate::{ - imfs::new::{Imfs, ImfsFetcher, ImfsEntry}, + imfs::new::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, }; -use super::{ - middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, -}; +use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; pub struct SnapshotRbxm; @@ -25,16 +20,18 @@ impl SnapshotMiddleware for SnapshotRbxm { return Ok(None); } - let file_name = entry.path() - .file_name().unwrap().to_string_lossy(); + let file_name = entry.path().file_name().unwrap().to_string_lossy(); if !file_name.ends_with(".rbxm") { - return Ok(None); + return Ok(None); } - let instance_name = entry.path() - .file_stem().expect("Could not extract file stem") - .to_string_lossy().to_string(); + let instance_name = entry + .path() + .file_stem() + .expect("Could not extract file stem") + .to_string_lossy() + .to_string(); let mut temp_tree = RbxTree::new(RbxInstanceProperties { name: "DataModel".to_owned(), @@ -59,10 +56,7 @@ impl SnapshotMiddleware for SnapshotRbxm { } } - fn from_instance( - _tree: &RbxTree, - _id: RbxId, - ) -> SnapshotFileResult { + fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { unimplemented!("Snapshotting models"); } } @@ -93,4 +87,4 @@ mod test { // property that currently deserializes incorrectly. // See: https://github.com/rojo-rbx/rbx-dom/issues/49 } -} \ No newline at end of file +} diff --git a/server/src/snapshot_middleware/rbxmx.rs b/server/src/snapshot_middleware/rbxmx.rs index d509fdab..6cfc9b1a 100644 --- a/server/src/snapshot_middleware/rbxmx.rs +++ b/server/src/snapshot_middleware/rbxmx.rs @@ -1,15 +1,13 @@ use std::borrow::Cow; -use rbx_dom_weak::{RbxTree, RbxId}; +use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ - imfs::new::{Imfs, ImfsFetcher, ImfsEntry}, + imfs::new::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, }; -use super::{ - middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, -}; +use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; pub struct SnapshotRbxmx; @@ -22,16 +20,18 @@ impl SnapshotMiddleware for SnapshotRbxmx { return Ok(None); } - let file_name = entry.path() - .file_name().unwrap().to_string_lossy(); + let file_name = entry.path().file_name().unwrap().to_string_lossy(); if !file_name.ends_with(".rbxmx") { - return Ok(None); + return Ok(None); } - let instance_name = entry.path() - .file_stem().expect("Could not extract file stem") - .to_string_lossy().to_string(); + let instance_name = entry + .path() + .file_stem() + .expect("Could not extract file stem") + .to_string_lossy() + .to_string(); let options = rbx_xml::DecodeOptions::new() .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); @@ -52,10 +52,7 @@ impl SnapshotMiddleware for SnapshotRbxmx { } } - fn from_instance( - _tree: &RbxTree, - _id: RbxId, - ) -> SnapshotFileResult { + fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { unimplemented!("Snapshotting models"); } } @@ -71,7 +68,8 @@ mod test { #[test] fn model_from_imfs() { let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file(r#" + let file = ImfsSnapshot::file( + r#" @@ -79,16 +77,19 @@ mod test { - "#); + "#, + ); imfs.load_from_snapshot("/foo.rbxmx", file); let entry = imfs.get("/foo.rbxmx").unwrap(); - let instance_snapshot = SnapshotRbxmx::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = SnapshotRbxmx::from_imfs(&mut imfs, &entry) + .unwrap() + .unwrap(); assert_eq!(instance_snapshot.name, "foo"); assert_eq!(instance_snapshot.class_name, "Folder"); assert_eq!(instance_snapshot.properties, HashMap::new()); assert_eq!(instance_snapshot.children, Vec::new()); } -} \ No newline at end of file +} diff --git a/server/src/snapshot_middleware/txt.rs b/server/src/snapshot_middleware/txt.rs index 3fdb6580..22d7cd83 100644 --- a/server/src/snapshot_middleware/txt.rs +++ b/server/src/snapshot_middleware/txt.rs @@ -1,19 +1,14 @@ -use std::{ - borrow::Cow, - str, -}; +use std::{borrow::Cow, str}; use maplit::hashmap; -use rbx_dom_weak::{RbxTree, RbxValue, RbxId}; +use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; use crate::{ - imfs::new::{Imfs, ImfsSnapshot, FileSnapshot, ImfsFetcher, ImfsEntry}, + imfs::new::{FileSnapshot, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, snapshot::InstanceSnapshot, }; -use super::{ - middleware::{SnapshotMiddleware, SnapshotInstanceResult, SnapshotFileResult}, -}; +use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; pub struct SnapshotTxt; @@ -35,13 +30,18 @@ impl SnapshotMiddleware for SnapshotTxt { return Ok(None); } - let instance_name = entry.path() - .file_stem().expect("Could not extract file stem") - .to_str().unwrap().to_string(); + let instance_name = entry + .path() + .file_stem() + .expect("Could not extract file stem") + .to_str() + .unwrap() + .to_string(); let contents = entry.contents(imfs)?; let contents_str = str::from_utf8(contents) - .expect("File content was not valid UTF-8").to_string(); + .expect("File content was not valid UTF-8") + .to_string(); let properties = hashmap! { "Value".to_owned() => RbxValue::String { @@ -58,10 +58,7 @@ impl SnapshotMiddleware for SnapshotTxt { })) } - fn from_instance( - tree: &RbxTree, - id: RbxId, - ) -> SnapshotFileResult { + fn from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult { let instance = tree.get_instance(id).unwrap(); if instance.class_name != "StringValue" { @@ -94,7 +91,7 @@ mod test { use super::*; use maplit::hashmap; - use rbx_dom_weak::{RbxInstanceProperties}; + use rbx_dom_weak::RbxInstanceProperties; use crate::imfs::new::NoopFetcher; @@ -110,11 +107,14 @@ mod test { assert_eq!(instance_snapshot.name, "foo"); assert_eq!(instance_snapshot.class_name, "StringValue"); - assert_eq!(instance_snapshot.properties, hashmap! { - "Value".to_owned() => RbxValue::String { - value: "Hello there!".to_owned(), - }, - }); + assert_eq!( + instance_snapshot.properties, + hashmap! { + "Value".to_owned() => RbxValue::String { + value: "Hello there!".to_owned(), + }, + } + ); } #[test] @@ -144,4 +144,4 @@ mod test { }, } } -} \ No newline at end of file +} diff --git a/server/src/web/api.rs b/server/src/web/api.rs index a04da71e..f8bede16 100644 --- a/server/src/web/api.rs +++ b/server/src/web/api.rs @@ -1,32 +1,15 @@ //! Defines Rojo's HTTP API, all under /api. These endpoints generally return //! JSON. -use std::{ - collections::HashSet, - sync::Arc, -}; +use std::{collections::HashSet, sync::Arc}; -use futures::{ - future, - Future, -}; +use futures::{future, Future}; -use hyper::{ - service::Service, - header, - StatusCode, - Method, - Body, - Request, - Response, -}; -use serde::{Serialize, Deserialize}; +use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; use rbx_dom_weak::RbxId; +use serde::{Deserialize, Serialize}; -use crate::{ - serve_session::ServeSession, - session_id::SessionId, -}; +use crate::{serve_session::ServeSession, session_id::SessionId}; const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); const PROTOCOL_VERSION: u64 = 3; @@ -83,7 +66,8 @@ impl Service for ApiService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; - type Future = Box, Error = Self::Error> + Send>; + type Future = + Box, Error = Self::Error> + Send>; fn call(&mut self, request: hyper::Request) -> Self::Future { let response = match (request.method(), request.uri().path()) { @@ -92,12 +76,10 @@ impl Service for ApiService { (&Method::GET, path) if path.starts_with("/api/subscribe/") => { return self.handle_api_subscribe(request); } - _ => { - Response::builder() - .status(StatusCode::NOT_FOUND) - .body(Body::empty()) - .unwrap() - } + _ => Response::builder() + .status(StatusCode::NOT_FOUND) + .body(Body::empty()) + .unwrap(), }; Box::new(future::ok(response)) @@ -106,9 +88,7 @@ impl Service for ApiService { impl ApiService { pub fn new(serve_session: Arc) -> ApiService { - ApiService { - serve_session, - } + ApiService { serve_session } } /// Get a summary of information about the server @@ -128,12 +108,14 @@ impl ApiService { let _cursor: u32 = match argument.parse() { Ok(v) => v, Err(err) => { - return Box::new(future::ok(Response::builder() - .status(StatusCode::BAD_REQUEST) - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from(err.to_string())) - .unwrap())); - }, + return Box::new(future::ok( + Response::builder() + .status(StatusCode::BAD_REQUEST) + .header(header::CONTENT_TYPE, "text/plain") + .body(Body::from(err.to_string())) + .unwrap(), + )); + } }; Box::new(future::ok(response_json(SubscribeResponse { @@ -143,10 +125,7 @@ impl ApiService { fn handle_api_read(&self, request: Request) -> Response { let argument = &request.uri().path()["/api/read/".len()..]; - let requested_ids: Option> = argument - .split(',') - .map(RbxId::parse_str) - .collect(); + let requested_ids: Option> = argument.split(',').map(RbxId::parse_str).collect(); let _requested_ids = match requested_ids { Some(id) => id, @@ -156,11 +135,11 @@ impl ApiService { .header(header::CONTENT_TYPE, "text/plain") .body(Body::from("Malformed ID list")) .unwrap(); - }, + } }; response_json(ReadResponse { session_id: self.serve_session.session_id(), }) } -} \ No newline at end of file +} diff --git a/server/src/web/interface.rs b/server/src/web/interface.rs index 0007247c..3fbf18b4 100644 --- a/server/src/web/interface.rs +++ b/server/src/web/interface.rs @@ -3,15 +3,7 @@ use std::sync::Arc; use futures::{future, Future}; -use hyper::{ - service::Service, - header, - Body, - Method, - StatusCode, - Request, - Response, -}; +use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; use ritz::html; use crate::serve_session::ServeSession; @@ -47,9 +39,7 @@ impl Service for InterfaceService { impl InterfaceService { pub fn new(serve_session: Arc) -> InterfaceService { - InterfaceService { - serve_session, - } + InterfaceService { serve_session } } fn handle_home(&self) -> Response { @@ -97,4 +87,4 @@ impl InterfaceService { .body(Body::from("TODO: /visualize/imfs")) .unwrap() } -} \ No newline at end of file +} diff --git a/server/src/web/mod.rs b/server/src/web/mod.rs index f3d5fbd2..a5d116fc 100644 --- a/server/src/web/mod.rs +++ b/server/src/web/mod.rs @@ -3,25 +3,16 @@ mod interface; use std::sync::Arc; -use log::trace; use futures::{ future::{self, FutureResult}, Future, }; -use hyper::{ - service::Service, - Body, - Request, - Response, - Server, -}; +use hyper::{service::Service, Body, Request, Response, Server}; +use log::trace; use crate::serve_session::ServeSession; -use self::{ - api::ApiService, - interface::InterfaceService, -}; +use self::{api::ApiService, interface::InterfaceService}; pub struct RootService { api: api::ApiService, @@ -60,9 +51,7 @@ pub struct LiveServer { impl LiveServer { pub fn new(serve_session: Arc) -> LiveServer { - LiveServer { - serve_session, - } + LiveServer { serve_session } } pub fn start(self, port: u16) { @@ -78,4 +67,4 @@ impl LiveServer { hyper::rt::run(server); } -} \ No newline at end of file +} diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index 38cb5f89..c9b02adc 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -1,21 +1,19 @@ -#[macro_use] extern crate lazy_static; +#[macro_use] +extern crate lazy_static; use std::{ - collections::{HashMap, BTreeMap}, + collections::{BTreeMap, HashMap}, path::{Path, PathBuf}, }; use pretty_assertions::assert_eq; use rbx_dom_weak::RbxValue; -use librojo::{ - project::{Project, ProjectNode}, -}; +use librojo::project::{Project, ProjectNode}; lazy_static! { - static ref TEST_PROJECTS_ROOT: PathBuf = { - Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects") - }; + static ref TEST_PROJECTS_ROOT: PathBuf = + { Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects") }; } #[test] @@ -63,9 +61,10 @@ fn single_partition_game() { }; let mut http_service_properties = HashMap::new(); - http_service_properties.insert("HttpEnabled".to_string(), RbxValue::Bool { - value: true, - }.into()); + http_service_properties.insert( + "HttpEnabled".to_string(), + RbxValue::Bool { value: true }.into(), + ); let http_service = ProjectNode { class_name: Some(String::from("HttpService")), @@ -110,4 +109,4 @@ fn composing_models() { let project = Project::load_fuzzy(&project_file_location).unwrap(); assert_eq!(project.name, "composing-models"); -} \ No newline at end of file +} From 5a7d6a673a8abaa59f462245a66b09227a882589 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 15:26:51 -0700 Subject: [PATCH 0618/1504] Fix bug caught by clippy --- server/src/snapshot/patch_compute.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/src/snapshot/patch_compute.rs b/server/src/snapshot/patch_compute.rs index 6ef5d36a..ec60500c 100644 --- a/server/src/snapshot/patch_compute.rs +++ b/server/src/snapshot/patch_compute.rs @@ -173,7 +173,7 @@ fn compute_children_patches<'a>( .expect("Instance did not exist in tree"); if snapshot_child.name == instance_child.name - && instance_child.class_name == instance_child.class_name + && snapshot_child.class_name == instance_child.class_name { paired_instances[*instance_index] = true; return true; @@ -327,4 +327,4 @@ mod test { assert_eq!(patch_set, expected_patch_set); } -} +} \ No newline at end of file From f465af964ace37fcee0e23b807a334d5fc8868c0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 15:27:25 -0700 Subject: [PATCH 0619/1504] Make Travis test rustfmt and clippy --- .travis.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 211045be..35cf2188 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,11 +34,15 @@ matrix: cache: cargo script: - - cargo test --verbose + - cargo test --locked --verbose - language: rust rust: stable cache: cargo script: - - cargo test --verbose \ No newline at end of file + - rustup component add rustfmt + - rustup component add clippy + - cargo test --locked --verbose + - cargo fmt -- --check + - cargo clippy \ No newline at end of file From b2b317342022c6f3d1380e720c23b0e7af9cf6ab Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 15:42:07 -0700 Subject: [PATCH 0620/1504] Fix editorconfig to stop fighting rustfmt --- .editorconfig | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/.editorconfig b/.editorconfig index 198a492d..7f5ae2b9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -3,16 +3,21 @@ root = true [*] end_of_line = lf charset = utf-8 -insert_final_newline = false trim_trailing_whitespace = true +insert_final_newline = false [*.{json,js,css}] indent_style = space indent_size = 2 -[*.{md,rs}] +[*.md] indent_style = space indent_size = 4 +[*.rs] +indent_style = space +indent_size = 4 +insert_final_newline = true + [*.lua] indent_style = tab \ No newline at end of file From aed160994a10986690111112685421f8dccb301d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 15:42:20 -0700 Subject: [PATCH 0621/1504] Fix rustfmt error --- server/src/snapshot/patch_compute.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/src/snapshot/patch_compute.rs b/server/src/snapshot/patch_compute.rs index ec60500c..451736ae 100644 --- a/server/src/snapshot/patch_compute.rs +++ b/server/src/snapshot/patch_compute.rs @@ -327,4 +327,4 @@ mod test { assert_eq!(patch_set, expected_patch_set); } -} \ No newline at end of file +} From 8e1536b59ba2614acba81005edc79cfc80b3046c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 15:42:55 -0700 Subject: [PATCH 0622/1504] Restructure Travis config to fail fast --- .travis.yml | 7 +++---- bin/run-tests.sh | 7 +++++++ 2 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 bin/run-tests.sh diff --git a/.travis.yml b/.travis.yml index 35cf2188..5fb8a2b2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -40,9 +40,8 @@ matrix: rust: stable cache: cargo - script: + install: - rustup component add rustfmt - rustup component add clippy - - cargo test --locked --verbose - - cargo fmt -- --check - - cargo clippy \ No newline at end of file + + script: ./bin/run-tests.sh \ No newline at end of file diff --git a/bin/run-tests.sh b/bin/run-tests.sh new file mode 100644 index 00000000..b218506d --- /dev/null +++ b/bin/run-tests.sh @@ -0,0 +1,7 @@ +#!/bin/sh + +set -ev + +cargo test --locked --verbose +cargo fmt -- --check +cargo clippy \ No newline at end of file From 49e10698b151682cd99ed6000c28e47536b20074 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 16:06:30 -0700 Subject: [PATCH 0623/1504] Mark bin/run-tests.sh as executable --- bin/run-tests.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 bin/run-tests.sh diff --git a/bin/run-tests.sh b/bin/run-tests.sh old mode 100644 new mode 100755 From 4d0dee7ee8282a6aed8db7944a0be8447654a9cf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 16:23:58 -0700 Subject: [PATCH 0624/1504] Fix or_fun clippy lint --- server/src/commands/serve.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/server/src/commands/serve.rs b/server/src/commands/serve.rs index d074a116..ac2dab5a 100644 --- a/server/src/commands/serve.rs +++ b/server/src/commands/serve.rs @@ -39,9 +39,11 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { let port = options .port - .or(maybe_project - .as_ref() - .and_then(|project| project.serve_port)) + .or_else(|| { + maybe_project + .as_ref() + .and_then(|project| project.serve_port) + }) .unwrap_or(DEFAULT_PORT); println!("Rojo server listening on port {}", port); From 94dbcd5c0696ce78b4fc86cb4f859ca0cbad9945 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 16:30:10 -0700 Subject: [PATCH 0625/1504] Remove unused dependencies, reqwest and rlua (for now) --- Cargo.lock | 394 ---------------------------------------------- server/Cargo.toml | 2 - 2 files changed, 396 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5d3837cb..4b75746c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,10 +1,5 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -[[package]] -name = "adler32" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "aho-corasick" version = "0.7.6" @@ -229,54 +224,6 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "cookie" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "cookie_store" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "core-foundation-sys" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "crc32fast" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "crossbeam-channel" version = "0.3.9" @@ -381,14 +328,6 @@ name = "encode_unicode" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "encoding_rs" -version = "0.8.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "env_logger" version = "0.6.2" @@ -445,34 +384,11 @@ dependencies = [ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "flate2" -version = "1.0.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide_c_api 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "fsevent" version = "0.4.0" @@ -630,28 +546,6 @@ dependencies = [ "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "hyper-tls" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "indexmap" version = "1.0.2" @@ -792,11 +686,6 @@ name = "maplit" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "matches" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "md5" version = "0.6.1" @@ -818,42 +707,6 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "mime" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "mime_guess" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miniz_oxide" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "miniz_oxide_c_api" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "mio" version = "0.6.19" @@ -893,23 +746,6 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "native-tls" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.48 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "net2" version = "0.2.33" @@ -973,36 +809,6 @@ name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "openssl" -version = "0.10.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.48 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "openssl-probe" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "openssl-sys" -version = "0.9.48" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "output_vt100" version = "0.1.2" @@ -1084,11 +890,6 @@ dependencies = [ "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "pest" version = "2.1.1" @@ -1128,11 +929,6 @@ dependencies = [ "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "pkg-config" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "ppv-lite86" version = "0.2.5" @@ -1172,18 +968,6 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "publicsuffix" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "pulldown-cmark" version = "0.2.0" @@ -1443,39 +1227,6 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "reqwest" -version = "0.9.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ritz" version = "0.1.0" @@ -1498,17 +1249,6 @@ dependencies = [ "snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rlua" -version = "0.16.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rojo" version = "0.5.0" @@ -1532,9 +1272,7 @@ dependencies = [ "rbx_reflection 3.2.395 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1588,15 +1326,6 @@ dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "schannel" -version = "0.1.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "scopeguard" version = "0.3.3" @@ -1607,25 +1336,6 @@ name = "scopeguard" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "security-framework" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "security-framework-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "semver" version = "0.9.0" @@ -1678,17 +1388,6 @@ dependencies = [ "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "serde_urlencoded" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "serde_yaml" version = "0.8.9" @@ -1860,7 +1559,6 @@ dependencies = [ "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1975,14 +1673,6 @@ name = "try-lock" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "try_from" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "typenum" version = "1.10.0" @@ -1993,30 +1683,6 @@ name = "ucd-trie" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "unicase" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-bidi" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-normalization" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "unicode-width" version = "0.1.5" @@ -2027,16 +1693,6 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "uuid" version = "0.7.4" @@ -2046,11 +1702,6 @@ dependencies = [ "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "vcpkg" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "vec_map" version = "0.8.1" @@ -2127,14 +1778,6 @@ dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "winreg" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -2158,7 +1801,6 @@ dependencies = [ ] [metadata] -"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" @@ -2185,11 +1827,6 @@ dependencies = [ "checksum clicolors-control 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73abfd4c73d003a674ce5d2933fca6ce6c42480ea84a5ffe0a2dc39ed56300f9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ca57c2c14b8a2bf3105bc9d15574aad80babf6a9c44b1058034cdf8bd169628" -"checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" -"checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" -"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" -"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" -"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" @@ -2203,17 +1840,13 @@ dependencies = [ "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90b2c9496c001e8cb61827acdefad780795c42264c137744cae6f7d9e3450abd" -"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2f8c63033fcba1f51ef744505b3cad42510432b904c062afa67ad7ece008429d" -"checksum flate2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "550934ad4808d5d39365e5d61727309bf18b3b02c6c56b729cb92e7dd84bc3d8" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" "checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" @@ -2231,8 +1864,6 @@ dependencies = [ "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)" = "7cb44cbce9d8ee4fb36e4c0ad7b794ac44ebaad924b9c8291a63215bb44c2c8f" -"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" -"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" @@ -2251,18 +1882,12 @@ dependencies = [ "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" "checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e6bcd6433cff03a4bfc3d9834d504467db1f1cf6d0ea765d37d330249ed629d" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" -"checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" -"checksum miniz_oxide 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fe2959c5a0747a8d7a56b4444c252ffd2dda5d452cfd147cdfdda73b1c3ece5b" -"checksum miniz_oxide_c_api 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6c675792957b0d19933816c4e1d56663c341dd9bfa31cb2140ff2267c1d8ecf4" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3572d71f13ea8ed41867accd971fd564aa75934cf7a1fae03ddb8c74a8a49943" @@ -2270,9 +1895,6 @@ dependencies = [ "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)" = "8152bb5a9b5b721538462336e3bef9a539f892715e5037fda0f984577311af15" -"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.48 (registry+https://github.com/rust-lang/crates.io-index)" = "b5ba300217253bcc5dc68bed23d782affa45000193866e025329aa8a7a9f05b8" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" @@ -2281,18 +1903,15 @@ dependencies = [ "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4a4a1c555c6505821f9d58b8779d0f630a6b7e4e1be24ba718610acf01fa79" "checksum paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26e796e623b8b257215f27e6c80a5478856cae305f5b59810ff9acdaa34570e6" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "933085deae3f32071f135d799d75667b63c8dc1f4537159756e3d4ceab41868c" "checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" "checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646" "checksum pest_meta 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f249ea6de7c7b7aba92b4ff4376a994c6dbd98fd2166c89d5c4947397ecb574d" -"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" "checksum proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "982a35d1194084ba319d65c4a68d24ca28f5fdb5b8bc20899e4eef8641ea5178" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum publicsuffix 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5afecba86dcf1e4fd610246f89899d1924fe12e1e89f555eb7c7f710f3c5ad1d" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" @@ -2321,27 +1940,21 @@ dependencies = [ "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" "checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum reqwest 0.9.19 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0777154c2c3eb54f5c480db01de845652d941e47191277cc673634c3853939" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" -"checksum rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62fc0e980c94fe9ef795b1bb3874649c8c6e9bb67d3b90d48380ba24c69c23ea" "checksum ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "17f52a24414403f81528b67488cf8edc4eda977d3af1646bb6b106a600ead78f" "checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" -"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" -"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113" "checksum serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "01e69e1b8a631f245467ee275b8c757b818653c6d704cdbcaeb56b56767b529c" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum serde_repr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "29a734c298df0346c4cd5919595981c266dabbf12dc747c85e1a95e96077a52b" -"checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" @@ -2371,17 +1984,11 @@ dependencies = [ "checksum tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "90ca01319dea1e376a001e8dc192d42ebde6dd532532a5bad988ac37db365b19" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" "checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" -"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" -"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" @@ -2393,7 +2000,6 @@ dependencies = [ "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" -"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" "checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" diff --git a/server/Cargo.toml b/server/Cargo.toml index 6f15bcf3..066c123e 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -36,9 +36,7 @@ rbx_dom_weak = "1.9.0" rbx_reflection = "3.1.388" rbx_xml = "0.11.0" regex = "1.0" -reqwest = "0.9.5" ritz = "0.1.0" -rlua = "0.16" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" uuid = { version = "0.7", features = ["v4", "serde"] } From 6164c5d78dd29b2c775e1e45c3c4b372fa6501dd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 16:30:35 -0700 Subject: [PATCH 0626/1504] Update dependencies --- Cargo.lock | 352 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 197 insertions(+), 155 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b75746c..9b2d2844 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -29,24 +29,24 @@ name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.34" +version = "0.3.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -54,8 +54,8 @@ name = "backtrace-sys" version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -92,13 +92,13 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -131,7 +131,7 @@ name = "c2-chacha" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -142,14 +142,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.38" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -162,10 +162,10 @@ name = "chrono" version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -184,18 +184,18 @@ dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "clicolors-control" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -213,14 +213,14 @@ version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "clicolors-control 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -249,7 +249,7 @@ dependencies = [ "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -268,7 +268,7 @@ version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -276,11 +276,11 @@ name = "csv" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bstr 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -293,11 +293,11 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -325,7 +325,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "encode_unicode" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -345,7 +345,7 @@ name = "error-chain" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -354,7 +354,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -365,7 +365,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -380,7 +380,7 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -403,7 +403,7 @@ name = "fsevent-sys" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -444,16 +444,17 @@ name = "generic-array" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "getrandom" -version = "0.1.8" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -471,7 +472,7 @@ dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -548,7 +549,7 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.0.2" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -558,7 +559,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -566,12 +567,12 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "insta" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -579,11 +580,11 @@ dependencies = [ "console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -594,7 +595,7 @@ name = "iovec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -619,7 +620,7 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -629,7 +630,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.60" +version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -667,7 +668,7 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -677,13 +678,13 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "maplit" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -696,7 +697,7 @@ name = "memchr" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -716,7 +717,7 @@ dependencies = [ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -752,7 +753,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -772,7 +773,7 @@ dependencies = [ "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -784,7 +785,7 @@ name = "num-integer" version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -793,7 +794,7 @@ name = "num-traits" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -801,7 +802,7 @@ name = "num_cpus" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -849,7 +850,7 @@ name = "parking_lot_core" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -863,7 +864,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -872,22 +873,22 @@ dependencies = [ [[package]] name = "paste" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "paste-impl" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -916,7 +917,7 @@ dependencies = [ "pest_meta 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -924,7 +925,7 @@ name = "pest_meta" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -940,19 +941,19 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "ctor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro-hack" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -968,6 +969,14 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pulldown-cmark" version = "0.2.0" @@ -989,13 +998,21 @@ dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "quote" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1006,8 +1023,8 @@ name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1024,8 +1041,8 @@ name = "rand" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1036,7 +1053,7 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1067,7 +1084,7 @@ name = "rand_core" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1099,7 +1116,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1111,7 +1128,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1122,7 +1139,7 @@ name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1151,11 +1168,11 @@ version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_repr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1165,9 +1182,9 @@ version = "3.2.395" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1233,7 +1250,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1243,7 +1260,7 @@ name = "ritz_impl" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1261,11 +1278,11 @@ dependencies = [ "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1273,7 +1290,7 @@ dependencies = [ "rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1284,8 +1301,8 @@ dependencies = [ name = "rojo-test" version = "0.1.0" dependencies = [ - "insta 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "insta 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rojo 0.5.0", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1297,12 +1314,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rustc-demangle" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1342,7 +1359,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1352,20 +1369,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.98" +version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1375,17 +1392,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_repr" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1395,7 +1412,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1463,7 +1480,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.43" +version = "0.15.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1471,6 +1488,16 @@ dependencies = [ "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synstructure" version = "0.10.2" @@ -1478,7 +1505,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1497,7 +1524,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1509,7 +1536,7 @@ name = "termcolor" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1517,7 +1544,7 @@ name = "termios" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1525,7 +1552,7 @@ name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1533,7 +1560,7 @@ name = "thread_local" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1541,7 +1568,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1608,7 +1635,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1675,7 +1702,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "typenum" -version = "1.10.0" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1685,7 +1712,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicode-width" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1693,13 +1720,18 @@ name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicode-xid" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "uuid" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1732,6 +1764,11 @@ dependencies = [ "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "wasi" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" @@ -1771,7 +1808,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "wincolor" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1805,26 +1842,26 @@ dependencies = [ "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "22130e92352b948e7e82a49cdb0aa94f2211761117f29e052dd397c1ac33542b" -"checksum backtrace 0.3.34 (registry+https://github.com/rust-lang/crates.io-index)" = "b5164d292487f037ece34ec0de2fcede2faa162f085dd96d2385ab81b12765ba" +"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" +"checksum backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "1371048253fa3bac6704bfd6bbfc922ee9bdcee8881330d40f308b81cc5adc55" "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" -"checksum bstr 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e0a692f1c740e7e821ca71a22cf99b9b2322dfa94d10f71443befb1797b3946a" +"checksum bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94cdf78eb7e94c566c1f5dbe2abf8fc70a548fc902942a48c4b3a98b48ca9ade" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cc 1.0.38 (registry+https://github.com/rust-lang/crates.io-index)" = "ce400c638d48ee0e9ab75aef7997609ec57367ccfe1463f21bf53c3eca67bf46" +"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" "checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe" "checksum ci_info 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e5e881307a989a3a5e20d52a32cc05950e3c2178cccfcc9428271a6cde09f902" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum clicolors-control 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73abfd4c73d003a674ce5d2933fca6ce6c42480ea84a5ffe0a2dc39ed56300f9" +"checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ca57c2c14b8a2bf3105bc9d15574aad80babf6a9c44b1058034cdf8bd169628" "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" @@ -1834,12 +1871,12 @@ dependencies = [ "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" "checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" -"checksum ctor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3b4c17619643c1252b5f690084b82639dd7fac141c57c8e77a00e0148132092c" +"checksum ctor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5b6b2f4752cc29efbfd03474c532ce8f916f2d44ec5bb8c21f93bc76e5365528" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" -"checksum encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90b2c9496c001e8cb61827acdefad780795c42264c137744cae6f7d9e3450abd" +"checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" @@ -1855,7 +1892,7 @@ dependencies = [ "checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum getrandom 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "34f33de6f0ae7c9cb5e574502a562e2b512799e32abb801cd1e79ad952b62b49" +"checksum getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fc344b02d3868feb131e8b5fe2b9b0a1cc42942679af493061fc13b853243872" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" @@ -1864,24 +1901,24 @@ dependencies = [ "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)" = "7cb44cbce9d8ee4fb36e4c0ad7b794ac44ebaad924b9c8291a63215bb44c2c8f" -"checksum indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e81a7c05f79578dbc15793d8b619db9ba32b4577003ef3af1a91c416798c58d" +"checksum indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4d6d89e0948bf10c08b9ecc8ac5b83f07f857ebe2c0cbe38de15b4e4f510356" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" -"checksum insta 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "00eef45accbe65bfb859ad16649c6b4bed246768d89493473d9ab6c6a0eb908f" +"checksum insta 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb8917b02e8fee27da19291be792fa53acec68ea0b7a45a914dcb80a67d42ab" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f52a11f73b88fab829a0e4d9e13ea5982c7ac457c72eb3541d82a4afdfce4ff" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bc5729f27f159ddd61f4df6228e827e86643d4d3e7c32183cb30a1c08f604a14" +"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.60 (registry+https://github.com/rust-lang/crates.io-index)" = "d44e80633f007889c7eff624b709ab43c92d708caad982295768a7b13ca3b5eb" +"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" -"checksum maplit 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "08cbb6b4fef96b6d77bfc40ec491b1690c779e77b05cd9f07f787ed376fd4c43" +"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" "checksum md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e6bcd6433cff03a4bfc3d9834d504467db1f1cf6d0ea765d37d330249ed629d" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" @@ -1901,20 +1938,22 @@ dependencies = [ "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -"checksum paste 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1f4a4a1c555c6505821f9d58b8779d0f630a6b7e4e1be24ba718610acf01fa79" -"checksum paste-impl 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "26e796e623b8b257215f27e6c80a5478856cae305f5b59810ff9acdaa34570e6" +"checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" +"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" "checksum pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "933085deae3f32071f135d799d75667b63c8dc1f4537159756e3d4ceab41868c" "checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" "checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646" "checksum pest_meta 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f249ea6de7c7b7aba92b4ff4376a994c6dbd98fd2166c89d5c4947397ecb574d" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" -"checksum proc-macro-hack 0.5.8 (registry+https://github.com/rust-lang/crates.io-index)" = "982a35d1194084ba319d65c4a68d24ca28f5fdb5b8bc20899e4eef8641ea5178" +"checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" "checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" @@ -1943,7 +1982,7 @@ dependencies = [ "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "17f52a24414403f81528b67488cf8edc4eda977d3af1646bb6b106a600ead78f" -"checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af" +"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" @@ -1951,10 +1990,10 @@ dependencies = [ "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "7fe5626ac617da2f2d9c48af5515a21d5a480dbd151e01bb1c355e26a3e68113" -"checksum serde_derive 1.0.98 (registry+https://github.com/rust-lang/crates.io-index)" = "01e69e1b8a631f245467ee275b8c757b818653c6d704cdbcaeb56b56767b529c" +"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" +"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" -"checksum serde_repr 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "29a734c298df0346c4cd5919595981c266dabbf12dc747c85e1a95e96077a52b" +"checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" "checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" @@ -1964,7 +2003,8 @@ dependencies = [ "checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum syn 0.15.43 (registry+https://github.com/rust-lang/crates.io-index)" = "ee06ea4b620ab59a2267c6b48be16244a3389f8bfa0986bdd15c35b890b00af3" +"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" +"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" @@ -1984,22 +2024,24 @@ dependencies = [ "checksum tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "90ca01319dea1e376a001e8dc192d42ebde6dd532532a5bad988ac37db365b19" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum typenum 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "612d636f949607bdf9b123b4a6f6d966dedf3ff669f7f045890d3a4a73948169" +"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" -"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" +"checksum wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd5442abcac6525a045cc8c795aedb60da7a2e5e89c7bf18a0d5357849bb23c7" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "561ed901ae465d6185fa7864d63fbd5720d0ef718366c9a4dc83cf6170d7e9ba" +"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" "checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" From ec9afba029d50298ada3b5fc6cc0de6c4f6e4e5f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 16:44:40 -0700 Subject: [PATCH 0627/1504] Remove unfinished plugin scaffolding --- server/src/project.rs | 54 ----------------------------------- server/tests/read_projects.rs | 1 - 2 files changed, 55 deletions(-) diff --git a/server/src/project.rs b/server/src/project.rs index 4d0b70a8..1b736a63 100644 --- a/server/src/project.rs +++ b/server/src/project.rs @@ -25,10 +25,6 @@ struct SourceProject { name: String, tree: SourceProjectNode, - #[cfg_attr(not(feature = "plugins-enabled"), serde(skip_deserializing))] - #[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")] - plugins: Vec, - #[serde(skip_serializing_if = "Option::is_none")] serve_port: Option, @@ -40,16 +36,10 @@ impl SourceProject { /// Consumes the SourceProject and yields a Project, ready for prime-time. pub fn into_project(mut self, project_file_location: &Path) -> Project { let tree = self.tree.into_project_node(project_file_location); - let plugins = self - .plugins - .drain(..) - .map(|source_plugin| source_plugin.into_plugin(project_file_location)) - .collect(); Project { name: self.name, tree, - plugins, serve_port: self.serve_port, serve_place_ids: self.serve_place_ids, file_location: PathBuf::from(project_file_location), @@ -193,24 +183,6 @@ impl SourceProjectNode { } } -#[derive(Debug, Serialize, Deserialize)] -struct SourcePlugin { - path: String, -} - -impl SourcePlugin { - pub fn into_plugin(self, project_file_location: &Path) -> Plugin { - let path = if Path::new(&self.path).is_absolute() { - PathBuf::from(self.path) - } else { - let project_folder_location = project_file_location.parent().unwrap(); - project_folder_location.join(self.path) - }; - - Plugin { path } - } -} - #[derive(Debug, Fail)] pub enum ProjectLoadError { NotFound, @@ -340,28 +312,10 @@ impl ProjectNode { } } -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct Plugin { - pub path: PathBuf, -} - -impl Plugin { - fn to_source_plugin(&self, project_file_location: &Path) -> SourcePlugin { - let project_folder_location = project_file_location.parent().unwrap(); - let path = match self.path.strip_prefix(project_folder_location) { - Ok(stripped) => stripped.to_str().unwrap().replace("\\", "/"), - Err(_) => format!("{}", self.path.display()), - }; - - SourcePlugin { path } - } -} - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct Project { pub name: String, pub tree: ProjectNode, - pub plugins: Vec, pub serve_port: Option, pub serve_place_ids: Option>, pub file_location: PathBuf, @@ -428,7 +382,6 @@ impl Project { let project = Project { name: project_name.to_string(), tree, - plugins: Vec::new(), serve_port: None, serve_place_ids: None, file_location: project_path.clone(), @@ -593,16 +546,9 @@ impl Project { } fn to_source_project(&self) -> SourceProject { - let plugins = self - .plugins - .iter() - .map(|plugin| plugin.to_source_plugin(&self.file_location)) - .collect(); - SourceProject { name: self.name.clone(), tree: self.tree.to_source_node(&self.file_location), - plugins, serve_port: self.serve_port, serve_place_ids: self.serve_place_ids.clone(), } diff --git a/server/tests/read_projects.rs b/server/tests/read_projects.rs index c9b02adc..c0fa6438 100644 --- a/server/tests/read_projects.rs +++ b/server/tests/read_projects.rs @@ -85,7 +85,6 @@ fn single_partition_game() { Project { name: "single-sync-point".to_string(), tree: root_node, - plugins: Vec::new(), serve_port: None, serve_place_ids: None, file_location: project_location.join("default.project.json"), From 6f7dbe99feeb1296f16c6d59dc88f461685dde0e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 16:56:52 -0700 Subject: [PATCH 0628/1504] Move Rojo server into root of the repository --- Cargo.toml | 51 ++++++++++++++++-- {server/assets => assets}/index.css | 0 {server/assets => assets}/place.project.json | 0 {server/assets => assets}/test-folder.rbxm | Bin rojo-test/Cargo.toml | 2 +- server/Cargo.toml | 49 ----------------- {server/src => src}/bin.rs | 0 {server/src => src}/commands/build.rs | 0 {server/src => src}/commands/init.rs | 0 {server/src => src}/commands/mod.rs | 0 {server/src => src}/commands/serve.rs | 0 {server/src => src}/commands/upload.rs | 0 {server/src => src}/imfs/error.rs | 0 {server/src => src}/imfs/fetcher.rs | 0 {server/src => src}/imfs/imfs.rs | 0 {server/src => src}/imfs/mod.rs | 0 {server/src => src}/imfs/noop_fetcher.rs | 0 {server/src => src}/imfs/real_fetcher.rs | 0 {server/src => src}/imfs/snapshot.rs | 0 {server/src => src}/impl_from.rs | 0 {server/src => src}/lib.rs | 0 {server/src => src}/message_queue.rs | 0 {server/src => src}/path_map.rs | 0 {server/src => src}/path_serializer.rs | 0 {server/src => src}/project.rs | 0 {server/src => src}/serve_session.rs | 0 {server/src => src}/session_id.rs | 0 .../src => src}/snapshot/instance_snapshot.rs | 0 {server/src => src}/snapshot/mod.rs | 0 {server/src => src}/snapshot/patch.rs | 0 {server/src => src}/snapshot/patch_apply.rs | 0 {server/src => src}/snapshot/patch_compute.rs | 0 .../snapshot_middleware/context.rs | 0 .../src => src}/snapshot_middleware/csv.rs | 0 .../src => src}/snapshot_middleware/dir.rs | 0 .../src => src}/snapshot_middleware/error.rs | 0 .../snapshot_middleware/json_model.rs | 0 .../src => src}/snapshot_middleware/lua.rs | 0 .../snapshot_middleware/middleware.rs | 0 .../src => src}/snapshot_middleware/mod.rs | 0 .../snapshot_middleware/project.rs | 0 .../src => src}/snapshot_middleware/rbxm.rs | 0 .../src => src}/snapshot_middleware/rbxmx.rs | 0 .../src => src}/snapshot_middleware/txt.rs | 0 {server/src => src}/web/api.rs | 0 {server/src => src}/web/interface.rs | 0 {server/src => src}/web/mod.rs | 0 {server/tests => tests}/read_projects.rs | 2 +- 48 files changed, 50 insertions(+), 54 deletions(-) rename {server/assets => assets}/index.css (100%) rename {server/assets => assets}/place.project.json (100%) rename {server/assets => assets}/test-folder.rbxm (100%) delete mode 100644 server/Cargo.toml rename {server/src => src}/bin.rs (100%) rename {server/src => src}/commands/build.rs (100%) rename {server/src => src}/commands/init.rs (100%) rename {server/src => src}/commands/mod.rs (100%) rename {server/src => src}/commands/serve.rs (100%) rename {server/src => src}/commands/upload.rs (100%) rename {server/src => src}/imfs/error.rs (100%) rename {server/src => src}/imfs/fetcher.rs (100%) rename {server/src => src}/imfs/imfs.rs (100%) rename {server/src => src}/imfs/mod.rs (100%) rename {server/src => src}/imfs/noop_fetcher.rs (100%) rename {server/src => src}/imfs/real_fetcher.rs (100%) rename {server/src => src}/imfs/snapshot.rs (100%) rename {server/src => src}/impl_from.rs (100%) rename {server/src => src}/lib.rs (100%) rename {server/src => src}/message_queue.rs (100%) rename {server/src => src}/path_map.rs (100%) rename {server/src => src}/path_serializer.rs (100%) rename {server/src => src}/project.rs (100%) rename {server/src => src}/serve_session.rs (100%) rename {server/src => src}/session_id.rs (100%) rename {server/src => src}/snapshot/instance_snapshot.rs (100%) rename {server/src => src}/snapshot/mod.rs (100%) rename {server/src => src}/snapshot/patch.rs (100%) rename {server/src => src}/snapshot/patch_apply.rs (100%) rename {server/src => src}/snapshot/patch_compute.rs (100%) rename {server/src => src}/snapshot_middleware/context.rs (100%) rename {server/src => src}/snapshot_middleware/csv.rs (100%) rename {server/src => src}/snapshot_middleware/dir.rs (100%) rename {server/src => src}/snapshot_middleware/error.rs (100%) rename {server/src => src}/snapshot_middleware/json_model.rs (100%) rename {server/src => src}/snapshot_middleware/lua.rs (100%) rename {server/src => src}/snapshot_middleware/middleware.rs (100%) rename {server/src => src}/snapshot_middleware/mod.rs (100%) rename {server/src => src}/snapshot_middleware/project.rs (100%) rename {server/src => src}/snapshot_middleware/rbxm.rs (100%) rename {server/src => src}/snapshot_middleware/rbxmx.rs (100%) rename {server/src => src}/snapshot_middleware/txt.rs (100%) rename {server/src => src}/web/api.rs (100%) rename {server/src => src}/web/interface.rs (100%) rename {server/src => src}/web/mod.rs (100%) rename {server/tests => tests}/read_projects.rs (97%) diff --git a/Cargo.toml b/Cargo.toml index f41eb04a..a5b14890 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,53 @@ +[package] +name = "rojo" +version = "0.5.0" +authors = ["Lucien Greathouse "] +description = "Enables professional-grade development tools for Roblox developers" +license = "MIT" +repository = "https://github.com/rojo-rbx/rojo" +edition = "2018" + [workspace] members = [ - "server", - "rojo-test", + "rojo-test", ] [profile.dev] -opt-level = 1 \ No newline at end of file +opt-level = 1 + +[lib] +name = "librojo" +path = "src/lib.rs" + +[[bin]] +name = "rojo" +path = "src/bin.rs" + +[dependencies] +clap = "2.27" +crossbeam-channel = "0.3.9" +csv = "1.0" +env_logger = "0.6" +failure = "0.1.3" +futures = "0.1" +hyper = "0.12" +jod-thread = "0.1.0" +log = "0.4" +maplit = "1.0.1" +notify = "4.0" +rbx_binary = "0.4.1" +rbx_dom_weak = "1.9.0" +rbx_reflection = "3.1.388" +rbx_xml = "0.11.0" +regex = "1.0" +ritz = "0.1.0" +serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" +uuid = { version = "0.7", features = ["v4", "serde"] } + +[dev-dependencies] +lazy_static = "1.2" +paste = "0.1" +pretty_assertions = "0.6.1" +tempfile = "3.0" +walkdir = "2.1" \ No newline at end of file diff --git a/server/assets/index.css b/assets/index.css similarity index 100% rename from server/assets/index.css rename to assets/index.css diff --git a/server/assets/place.project.json b/assets/place.project.json similarity index 100% rename from server/assets/place.project.json rename to assets/place.project.json diff --git a/server/assets/test-folder.rbxm b/assets/test-folder.rbxm similarity index 100% rename from server/assets/test-folder.rbxm rename to assets/test-folder.rbxm diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index 43403be0..c8072f3e 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -11,4 +11,4 @@ paste = "0.1.5" tempfile = "3.1.0" # We execute Rojo via std::process::Command, so depend on it so it's built! -rojo = { path = "../server" } \ No newline at end of file +rojo = { path = ".." } \ No newline at end of file diff --git a/server/Cargo.toml b/server/Cargo.toml deleted file mode 100644 index 066c123e..00000000 --- a/server/Cargo.toml +++ /dev/null @@ -1,49 +0,0 @@ -[package] -name = "rojo" -version = "0.5.0" -authors = ["Lucien Greathouse "] -description = "Enables professional-grade development tools for Roblox developers" -license = "MIT" -repository = "https://github.com/rojo-rbx/rojo" -edition = "2018" - -[features] -default = [] -server-plugins = [] - -[lib] -name = "librojo" -path = "src/lib.rs" - -[[bin]] -name = "rojo" -path = "src/bin.rs" - -[dependencies] -clap = "2.27" -crossbeam-channel = "0.3.9" -csv = "1.0" -env_logger = "0.6" -failure = "0.1.3" -futures = "0.1" -hyper = "0.12" -jod-thread = "0.1.0" -log = "0.4" -maplit = "1.0.1" -notify = "4.0" -rbx_binary = "0.4.1" -rbx_dom_weak = "1.9.0" -rbx_reflection = "3.1.388" -rbx_xml = "0.11.0" -regex = "1.0" -ritz = "0.1.0" -serde = { version = "1.0", features = ["derive"] } -serde_json = "1.0" -uuid = { version = "0.7", features = ["v4", "serde"] } - -[dev-dependencies] -lazy_static = "1.2" -paste = "0.1" -pretty_assertions = "0.6.1" -tempfile = "3.0" -walkdir = "2.1" \ No newline at end of file diff --git a/server/src/bin.rs b/src/bin.rs similarity index 100% rename from server/src/bin.rs rename to src/bin.rs diff --git a/server/src/commands/build.rs b/src/commands/build.rs similarity index 100% rename from server/src/commands/build.rs rename to src/commands/build.rs diff --git a/server/src/commands/init.rs b/src/commands/init.rs similarity index 100% rename from server/src/commands/init.rs rename to src/commands/init.rs diff --git a/server/src/commands/mod.rs b/src/commands/mod.rs similarity index 100% rename from server/src/commands/mod.rs rename to src/commands/mod.rs diff --git a/server/src/commands/serve.rs b/src/commands/serve.rs similarity index 100% rename from server/src/commands/serve.rs rename to src/commands/serve.rs diff --git a/server/src/commands/upload.rs b/src/commands/upload.rs similarity index 100% rename from server/src/commands/upload.rs rename to src/commands/upload.rs diff --git a/server/src/imfs/error.rs b/src/imfs/error.rs similarity index 100% rename from server/src/imfs/error.rs rename to src/imfs/error.rs diff --git a/server/src/imfs/fetcher.rs b/src/imfs/fetcher.rs similarity index 100% rename from server/src/imfs/fetcher.rs rename to src/imfs/fetcher.rs diff --git a/server/src/imfs/imfs.rs b/src/imfs/imfs.rs similarity index 100% rename from server/src/imfs/imfs.rs rename to src/imfs/imfs.rs diff --git a/server/src/imfs/mod.rs b/src/imfs/mod.rs similarity index 100% rename from server/src/imfs/mod.rs rename to src/imfs/mod.rs diff --git a/server/src/imfs/noop_fetcher.rs b/src/imfs/noop_fetcher.rs similarity index 100% rename from server/src/imfs/noop_fetcher.rs rename to src/imfs/noop_fetcher.rs diff --git a/server/src/imfs/real_fetcher.rs b/src/imfs/real_fetcher.rs similarity index 100% rename from server/src/imfs/real_fetcher.rs rename to src/imfs/real_fetcher.rs diff --git a/server/src/imfs/snapshot.rs b/src/imfs/snapshot.rs similarity index 100% rename from server/src/imfs/snapshot.rs rename to src/imfs/snapshot.rs diff --git a/server/src/impl_from.rs b/src/impl_from.rs similarity index 100% rename from server/src/impl_from.rs rename to src/impl_from.rs diff --git a/server/src/lib.rs b/src/lib.rs similarity index 100% rename from server/src/lib.rs rename to src/lib.rs diff --git a/server/src/message_queue.rs b/src/message_queue.rs similarity index 100% rename from server/src/message_queue.rs rename to src/message_queue.rs diff --git a/server/src/path_map.rs b/src/path_map.rs similarity index 100% rename from server/src/path_map.rs rename to src/path_map.rs diff --git a/server/src/path_serializer.rs b/src/path_serializer.rs similarity index 100% rename from server/src/path_serializer.rs rename to src/path_serializer.rs diff --git a/server/src/project.rs b/src/project.rs similarity index 100% rename from server/src/project.rs rename to src/project.rs diff --git a/server/src/serve_session.rs b/src/serve_session.rs similarity index 100% rename from server/src/serve_session.rs rename to src/serve_session.rs diff --git a/server/src/session_id.rs b/src/session_id.rs similarity index 100% rename from server/src/session_id.rs rename to src/session_id.rs diff --git a/server/src/snapshot/instance_snapshot.rs b/src/snapshot/instance_snapshot.rs similarity index 100% rename from server/src/snapshot/instance_snapshot.rs rename to src/snapshot/instance_snapshot.rs diff --git a/server/src/snapshot/mod.rs b/src/snapshot/mod.rs similarity index 100% rename from server/src/snapshot/mod.rs rename to src/snapshot/mod.rs diff --git a/server/src/snapshot/patch.rs b/src/snapshot/patch.rs similarity index 100% rename from server/src/snapshot/patch.rs rename to src/snapshot/patch.rs diff --git a/server/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs similarity index 100% rename from server/src/snapshot/patch_apply.rs rename to src/snapshot/patch_apply.rs diff --git a/server/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs similarity index 100% rename from server/src/snapshot/patch_compute.rs rename to src/snapshot/patch_compute.rs diff --git a/server/src/snapshot_middleware/context.rs b/src/snapshot_middleware/context.rs similarity index 100% rename from server/src/snapshot_middleware/context.rs rename to src/snapshot_middleware/context.rs diff --git a/server/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs similarity index 100% rename from server/src/snapshot_middleware/csv.rs rename to src/snapshot_middleware/csv.rs diff --git a/server/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs similarity index 100% rename from server/src/snapshot_middleware/dir.rs rename to src/snapshot_middleware/dir.rs diff --git a/server/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs similarity index 100% rename from server/src/snapshot_middleware/error.rs rename to src/snapshot_middleware/error.rs diff --git a/server/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs similarity index 100% rename from server/src/snapshot_middleware/json_model.rs rename to src/snapshot_middleware/json_model.rs diff --git a/server/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs similarity index 100% rename from server/src/snapshot_middleware/lua.rs rename to src/snapshot_middleware/lua.rs diff --git a/server/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs similarity index 100% rename from server/src/snapshot_middleware/middleware.rs rename to src/snapshot_middleware/middleware.rs diff --git a/server/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs similarity index 100% rename from server/src/snapshot_middleware/mod.rs rename to src/snapshot_middleware/mod.rs diff --git a/server/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs similarity index 100% rename from server/src/snapshot_middleware/project.rs rename to src/snapshot_middleware/project.rs diff --git a/server/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs similarity index 100% rename from server/src/snapshot_middleware/rbxm.rs rename to src/snapshot_middleware/rbxm.rs diff --git a/server/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs similarity index 100% rename from server/src/snapshot_middleware/rbxmx.rs rename to src/snapshot_middleware/rbxmx.rs diff --git a/server/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs similarity index 100% rename from server/src/snapshot_middleware/txt.rs rename to src/snapshot_middleware/txt.rs diff --git a/server/src/web/api.rs b/src/web/api.rs similarity index 100% rename from server/src/web/api.rs rename to src/web/api.rs diff --git a/server/src/web/interface.rs b/src/web/interface.rs similarity index 100% rename from server/src/web/interface.rs rename to src/web/interface.rs diff --git a/server/src/web/mod.rs b/src/web/mod.rs similarity index 100% rename from server/src/web/mod.rs rename to src/web/mod.rs diff --git a/server/tests/read_projects.rs b/tests/read_projects.rs similarity index 97% rename from server/tests/read_projects.rs rename to tests/read_projects.rs index c0fa6438..55f0e1da 100644 --- a/server/tests/read_projects.rs +++ b/tests/read_projects.rs @@ -13,7 +13,7 @@ use librojo::project::{Project, ProjectNode}; lazy_static! { static ref TEST_PROJECTS_ROOT: PathBuf = - { Path::new(env!("CARGO_MANIFEST_DIR")).join("../test-projects") }; + { Path::new(env!("CARGO_MANIFEST_DIR")).join("test-projects") }; } #[test] From 81407ffe3cd8c38269743687b852d874e6197098 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 18:04:58 -0700 Subject: [PATCH 0629/1504] Goodbye Lemur and other cruft, hello run-in-roblox-based testing --- .editorconfig | 2 +- .gitmodules | 3 --- Cargo.toml | 7 +++++- assets/kenney-ui-gray-sheet.png | Bin 12953 -> 0 bytes assets/kenney-ui-gray-sheet.xml | 41 -------------------------------- bin/run-plugin-tests.sh | 6 +++++ plugin/modules/lemur | 1 - plugin/place.project.json | 3 +++ plugin/src/Assets.lua | 8 +------ 9 files changed, 17 insertions(+), 54 deletions(-) delete mode 100644 assets/kenney-ui-gray-sheet.png delete mode 100644 assets/kenney-ui-gray-sheet.xml create mode 100644 bin/run-plugin-tests.sh delete mode 160000 plugin/modules/lemur diff --git a/.editorconfig b/.editorconfig index 7f5ae2b9..42ec20f4 100644 --- a/.editorconfig +++ b/.editorconfig @@ -14,7 +14,7 @@ indent_size = 2 indent_style = space indent_size = 4 -[*.rs] +[*.{rs,toml}] indent_style = space indent_size = 4 insert_final_newline = true diff --git a/.gitmodules b/.gitmodules index c399195f..1e86ae9d 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,9 +4,6 @@ [submodule "plugin/modules/testez"] path = plugin/modules/testez url = https://github.com/Roblox/testez.git -[submodule "plugin/modules/lemur"] - path = plugin/modules/lemur - url = https://github.com/LPGhatguy/lemur.git [submodule "plugin/modules/promise"] path = plugin/modules/promise url = https://github.com/LPGhatguy/roblox-lua-promise.git diff --git a/Cargo.toml b/Cargo.toml index a5b14890..66ba1d29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,6 +7,11 @@ license = "MIT" repository = "https://github.com/rojo-rbx/rojo" edition = "2018" +exclude = [ + "/plugin/**", + "/test-projects/**", +] + [workspace] members = [ "rojo-test", @@ -50,4 +55,4 @@ lazy_static = "1.2" paste = "0.1" pretty_assertions = "0.6.1" tempfile = "3.0" -walkdir = "2.1" \ No newline at end of file +walkdir = "2.1" diff --git a/assets/kenney-ui-gray-sheet.png b/assets/kenney-ui-gray-sheet.png deleted file mode 100644 index 1ebbd975d33283c59cdbe7257a74d02855334d77..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12953 zcmbVz2Ut_f*7hU>m7*Xbpnw#q3P@8riAo1)Dkw-15k#a3Qbb5NSSV5~2ueK^(W8P& zuR*1F1OiBtj-V6?M5L3D{IfyNckj9Pe*gV{pND5Bd(W(yJ+s!k-t|t5G&j}X%DS5s z0I=22K*tgQH2jDLTQrrkt6c%qCpOYBMbckKDnBXZ|^NL&}zb`|H1D|H7HHSu&>>brOEIO5{s68W*# zqE|97*^B)b`-Jpt8M+)+*4E=)U0poL6UJ&c@mr9wdU2NzDPi^?NaEDj*XK=OY2s=d z(;#lPxc%dl%x3Y}3X^XzSXVpjf%7N>RS7fKj)MrjKJ8ZUM0l__Zr*R0`2cqB==b z*X&|TTk&y?xI;s`nJ;Y9(nr}iI2`!$^)}i3>f%8fZLX!vY}~zdKhutp@84hUcBm#Y z)+p0Tdzp`ZNKyW{)1&&};g^pv!gtTRy5`bpD|7wgu~T2ZWIqGh-JEp?LnSGOTsS~r zxu+gK!AV>miFVn%tNZKjR3{~zp%qGbhlfUQ;BIDvc`kw`597Z5UeMERjzP(z!5175 z4Gs?egW2d<;jAetaCLst_B=OXbab@;7659TgabsH<&_!}`TctV2Gq3f1pp-sKMBLD z)Jq^BDEL)-8sH}VLv0=CqgW*%Oc z>MrB>)pX-Z+6Smq>fi5fLHrdlB&7VW z(Jw11lBxgN<;T~?zjtxnNk~mi{rg?aFGJr)>Z1St5O$fKp8osY^)8QvL6MDYVjVWt zoevc;)EJDc4B;s&F2~Z1CnG#O{7BUU)j`!6RXVBrWl2fm)QC_+_sZ`14{&uP_JKGd ztS8U!&CSh!HQVsEv#8}CjR%qiN9gqGZv@L79-6(YL-fUxF-CeyO2k;GS>5`#C8g&#R!~O>DY2=|j9$LNEIETWP<@(EfbLrnd zzhjiA*%n=voEtQ?iig#aC~v0wN_eABsg9O5&hG{$No#9sWzdb!=b+9@^ad6#*bjv#t9X%A zqAZGpbqjVk*w%Lg$G3ARrz0o);uVzCUvPpby^F*b#k8~Kq@kG3&d#!;qN2L`mIQ-6 zk{@!;xeJb;+2z1Q5NKioM(SViuL=hA750tXEmNIQtl9+BO6fwzSxz_S*HOkq;GU>N z(a?p)9)6OJt=V+7<&qa?m$)qPE5W~cDymH2CS4Pvv*F?WH zqR%E9>5s8Nk%hkY0{C6_;r4t-8sezz70p_=kiuoWQziGz?f=Kn6`>;U}V%656_M^G>aCNm7RXl&DFr)AlTq=vpa)#(_8}y^F@UckiA};ac$0Owq01ONxtGXKhAQ+Z8qf_ePks zPhemvm%|4y;#zT!VJKs5Y2PLz-NMNWeQovO7v|a)Dg9-~@yp*on7X#oU_h<26{RHYBCj`5SlhMFB4)cBNmHm#f3&DgLxv#w9)S-02Q! zoo3jH5BC%<6D>b%`jgpmE&ABsk za&kDsR|{NQ9=!=Ppm*P!NeyYVUv7iJ4iWHzfrG3rjx9EhRQ z%@5^g(EIEZ3!NHWve zLO?<+f)gOAol^uHfzc^^1YC!aiMtM#H8&cqN1e__g#8zn>u?-2G`j`WI>Q1-@w@() z#VyFJw)|I9(dO8g?>bm)NB?)1`QbnBNfu3Ta%|i7$l*PV*2#?Q6Fq%>?#0s=M%%jh zJ*th6n4Ww7;)SeUZYd1a%^yq(XD>{}93q-*Jju%=<(zGU&rhOrMwgdMd)Dcn8GJ}+ zk|G%N?11T36QT;Bd&$+@^6@xvCtgva*FVSdq1kjQd~@*780F*N0X@|M28H2tS!eM$ zvUI~-gi;KGPx2MDFE4x(P&styTSY}hGdM3?G=2f5V*O-E2vy#T#A2&gXi$K&Vd3;h zg9aVPBDeX3gxEnk=O~Fo17S!5Ul33m8wq!9116D`g=>xM9Nb@IA7NKySK)&HGj}2Y z*Z`p5AJSoin62*@z!3iR5&CD7^(zk8kf*03?@J&p`7D8-xn;f6(RCZb@YV)gi-18% zWN^Xz|G};PHzxon;SEp3{I3_tJu|GHO=f3vM;0UdMv&7C`jO2eIP&JrVL>USw)(6W zD!tbd;4B=+PTShr-Zu5|^*#QRE>*RSC9=SUaY;kig0f6`QBjUjhM$0tkV>Eb#qqW= z?yC{IX z!5K7XBAgZ+Bax5iSn6nfy>M*FG!Y$YZb{mD!9K zY|?BK$;;0t`qUQ|6lC4IYbn-y*#>)FYOv#le1vMIX?P zQYSuWe@W@3HVENqXSvfMzO7Dm=i3P(kkt?@lz#Xc&s8S~4JJB3?o8=-tI?){ATvTm z0HrHkEBNs~vxva_Q7yA~jM>u@k&WDI$|j4M*Y@?xk9&FZ?J5rCzl19%%FIKM`r`BW(HQIP zzy}qV0{NkbODBOsRy_4J&cr5oe!`;4=EWh&S63Q)du`U}Yt)6hy1L>mweM?kj1vdj z+M#ocszD=NJ~8S$ze`PE*XG;b8}~cK1Y2Qbt}sE+ySxwdoJ8SQ+tUZ7Xs_N`XEbhwngE zAT60ud-o08>sRB%A&7@&tbTh15Sv%gt(sJ`#xH_=j7xsn5p^aJ!i!1ex0(ytyiZm^^}R zm8!IU-AKQBj23;C(cV8RCzjE@2NgMAA-6uu9dMReSdEnf{y(M`DXVsKLihR9CKi+2 zPCGtgUvASEYMzWl#`|*%&bM)>aQ*C3XRgUefEWqC{`u!V!l%^y zz6V6t?SxO{+`d-=d-m8c!^{<7;wD5G69ngk7@-wlTLqJ2$#tAxaFgG;j8fDc4JI^P z>K)vKQ&$tKIB+QmOXag>mna$+XA!R7zcA~R{rg-f__Y|`lOJ;eGQj~kxnf3MpFMEH z5-bj3zMZ5M1OsPJw#p~GXy{)O!Acnk;87 zo>}Kt3+bvx`DFGv*N}3;2K1Pmx{3AyC~^udkwoX^;n{Z;(p;SLTXei2vw;fpw*c#! z0x{XOXp5VrJC3!wjMz9A%=6JS!2}T7+O;S7EG&Jv2O7!}1!dmxg;fm+bjZb$~WVb%IdgkF4VT@L| zjcxL+Ghx8mZ;==?BD9yy?PK}~hp>ufD6OG*A$%7 z56u|vMO(C-b)`$tr0L*tL#jr=Hx41~O98Q>=S>S2F3g2j^IE**cb&F=?Y?#{ z6nC2yMv$jr_lnXD;>D*zg#M2c9T(d~v;)6qq>V8}+?Q=D&Wh2ujXQ)TFYVP4wqnWN z9(IAY<%M+o>69Uho zuHP^GZk-jAyST@7+#=)Lh`oO^BWQbE5QDx}i19wn!6aPr91@!skk%Xu&C`K(uA*4c zxK*F0S(CBr#5*~P#@1J2@>+3wHsRzVNfxi-Pa702JO{Vk*~l1}3vKr$e7LqwSsvM@ zxlrskaX;)x%kpr2fFbSpnZ^83wKCJ2_#k5eNkN%M&p0?(3(D`vwpeEte*N2EiG&2* zdQ!x}xP^cJsk+;sFp!(TzUyq}|MC$-0ElIjFl02i=&CBMJ0G*t0hvrzW?TyhSn7|$ zYg%!}9Rq;d2#~0k44fZLN&xG;Gb=+g$DGTfToDIszL_Y!3%gGKeVVAC;V(ybps&mlvjBOIdnM!I}{_jk-kX ze%5(WX?EyE4q+!3$awj0;+Q5?hYgM%mMfu)qd?T3{}Qyh(sVaT9PG?3BP-jPdGy-% z;lonRzGd=YA*iTpZGv8sBB7u_Fgq9L3@fxx}!H0;+RSvVn;3dzBmrMKUsa%}c(V@El+!!5e zPM(V)z52tzz>p1puy;9#2ainT-$q`V24%zy4Y(go2<&8gctgh)yYc<5QI2A|dP7W1 z%<9aHrxI?L!L(Yhzl-584Qj2tEd|R<_Xvm&5;W7+tjXwz)4f~ed$0AjGkOYK$E|1@ z;*L;i4xs?pqJO*K$m;6VihHz`@pN6IL{bIn@mtM2TSrMqn9s1`$_2gs?n_Eaisl&K zMMBLEBWx~{eOm#3WWo$DFQ3Zx69F*xka`Z1izDki-yEy1&LwRJ%Latq!;n^I9{&E_ z{NFcKRptEWrouDM5|+jPW6qDY2CAS2lScr|x?7M4{y7{bqq?L-(z5)Yn!^02W5f%m z2dh_Hg*=5!?r6}}JcMXM2tR}6UI_P%6$IVMJG|{{&()u6@U2DS`HMa94+wxuV2WBE z4(A9hdHM2XDyg+0;qUQWNu8-69@~o=HPH0e)YnW*+k~589{$>x2-k=g6loTqbRDDn#Wh~h+v`2SDTIqz^jHhnjOuQ=1EHyLty~U4TJE0 zIDRgGXpxzSpo6F(#5?%XtYRRwj+lt?+fP5u0vFF{FX-#*Tc2wZr6}6rE+MpzC=TWj zz5E!k;c(&i9ILI=>6)!_rzcB`D>CTN>TCitu zFzq*y9HYWXVMLX^Fqb+MepW1_V7;M>hlhundL5Ly)y-Wp*K^>|iWZ;p=lpK2!)O@C zNCf;XL31C+PX)Z&T_cremCi!lC^yt@w>P>1+>xJ*;X?uQn+1%hoggVE0kn-(*ln7yqE#3Y)Zn@t_KTRB znwmEKF`ka+k+!=!jp4gdY0+=Jx|8u7Q%iw#F+&+0UyP28eeL7F*RouUWukbe_XFcZ zxvDvY$)0bgP>%v|{|K;omkf7?7>vRoj>>@bTjz=Q8tuy!b!@zHmAbHv6^MSq`wf!ZS4>Mm8NT1u=34wUVnN$q83#m zp?DHRTlOh9-rwKEi*&3TUc$ z4W@Yc#h%nXVq~-YtgXI<8Vo~>`$30KWRoSbyBU02Q1I-rdze7dI{KpaF zHBe7FFS6dcFWLt21^E4L`BYh>7M_s)l@BP%9RJ`9;>xZGTiWYA|SL=XSR5BRAN12fuZ8&0ReMc<09&m zg@pwb(oCjr(`f3zNa<_Wx}LKWWcOvr8-3Fc=l^ctOnDhF-CMLG)xS$dzRm;>(5n^I5;@yscp^KGN9gPPfA%E|4|BrdC{EQ z@W3)v%hloNc8p`IyVM^b+nwwdu?Cal4tHKRKdGDj?YC(g|L@1L_D^07ZYpn?@|g^QA%u3s2#5A0~d3+2( z?+)Q`T{-~5019lSJ;sAa!4Kk&VR!U5!n$=%LRD2&zbhX~>g{ZzA-LJ|#Wkt< zHw1X$>cgYkW%dtZART&|dBGah5VyfLABzE4e|~^-_t698vI|oZD7~N7jTAR$45>pt zmBjS(ZGJlm@U&5(TfJW-;TCl7gBu{c`R5No2sAH@a^xr)8O=x@9tY+X?)V~% zdf(^+g#cB3RN%^w^E1b-P^TbQ(g_P*B%ijem$+hL_nlrPVLSbeuQ$Ucq@Srn-o zKsl<y?z2%JrNi*9xA7i*HL5mJW}{nt`SaTwCF*@w*C$=0#!?f_ zd*E`qA{&nLhFq$TnPPZe{x2W5+=3I$t7>=|pgy-pe|MZ+3|iwu(E99TM`w6PpKE+giE@|KvgiI02Yvq?LR)?J3`I669B_%N*wE#@3}BTa3^(8?_oy3t zk$#)@F^gFI4zBI4)46l$>O;xA@mgafcm{VcUFq0&V}4pnw-g52IKBmUsrv2``(AMG)045n zCcW;PeCNp(%0+H27|sz6d~$8sI{-4zudoTeFM z8BL-N4`+l(R%!Awpp%aI)X&!YsKgR?|5<%=IThaAlm9uU1v#}pT9{iZm-e71N8JC_ zlzri|Ld=g!F)^({MEx(RT4tQMJ$mYD5tS@emrkG0Rbho9Qe_@l!F7j*TD|Y%W1(CQ zAqyv|WuunY2bpns>xWF+uKD^FnBS0$Rf(r4imch{V-24}=~k?M?sIORu!csQuJf)zGpBkV zV#M^cKN{d{RaI5Z03$$9q?C)F|VzyB~NFyOug1Am*M2P zD^|mbf?^}A`h*^D{3amBawUJNV%Aj`zg3qm;B+D64ElQq*1NjCS2tm@ZN z?%7m#N~uzW_Uy6R?V397Z}q9SGw&nCL@8?S>+ZF7%i2RlB@br135b1L*pUnkphb3;jF^+oa%y<+bGy6FLyiT)Z%YFc(nX18hJC>H_w z)sa??tR6G`t>mqpgvXWHUqeUjXLet{BfUnxpXw2CIu1~ zUm3tMuPwp8MJNlsbvs{~YHf_m>U4q-b8fP*-#vn79dxL>4ee7KHew&_*s)hI}2PQqpwcTcxBzmL~O4y*SFE|JErh6-yt39le{TEruvd zcQNz(>61-Y;CW`nL-1vEdCpun7T9(RhO`R^*$BoaHvIE>~ zOC(51#E>bJmV>MzMZT9EX!yl)ybA15(g=h?=G)G&+XZav=GgZswE=5@-UM~k+hluc zY9x{WB*^r36;iTo8g(t1qNl!N3|L|Ob`X@ql#kJqzYJpF5m9;J&h)2)%!HBj9Vpdk zjLv6IzaP;9Q9(4a{{YczwPz)Vm%+ zvjOi|aZQ7irOJ2Qj3hqQ4~jKzo~HN5P}$Rw=MMg6zX_KYjrY$jG_+GnEe6iw!Vyau zi5Q)>DeF(Sr0EI@^3;+fPFveoe7!WdjS7c#&x3V(81mFY8;QStzPMbF7cRzP-DJZD@{&gbT@kk z6CQH$B4i7=uxNZ5#_<$O#6xPX487Cdok4w3f}PUSduOsoz@;D~lzr}@?)Eq*?GIB^ z2PflTk2lfyL5w3G%Z1eKafL@MN(}L-=?zaRgti@j3B_F31j1Qt!6~}R2X}J+cUNxI z#2IGJdpwezH+N6JgPD9qEY+v}%QH6~h9)a67n99$v1hBD)5=hUD}zae7Afk}+p{`u zL2D63WnFW@uQWQ`RF4h4N58q9&{2O>UE&p+V@dLkx~&oYyEt)q6a5}uHg(v1bbJDV zEO(=4={qdKN95~>z8@X19|sp)Q|DEhB(U!;@hERYO%$~-q}DB+I(eizN&d0zcL|j&2)i_NpS7W& z73a?_9OEA|l}B)!bhxdUJ$)~Ajp_YfuW?=U4^eQGn^6*6^-!TBU5+_hHmt?S-OX|O zdG{S#6&agdKAlIz^$yj`0yj5D6IRWZLmeJsVo{eL&F@y3QZr+DUz}Pv-%^AJL0_TT zs?Na`zZr!bu#_*PZQWNmuKtDJHQrTFZ_kyM-^hc^P=YcX43xABh*P52-#geYoCPF@h0c%^(-0Q zCU!3efkGMYjsiyeb4P>yydNKH+!Hu#lG0s1r#wTE`ottoJwuQXfJ=cWq7+8J1V+x9fO=+m3Uc36rTygo+E@lP3 zpP%gKv-FAS8`=baF>tPoH25$uws6vPY_39aLMyrv)p_wCwVGpqbguR+9?yu`TKKx; zt`!XxPe@^_c~VC_iL)Y2-PEe`lu>TNytSWN3O=?tRdU9s!y~%lj!U2Z*<-=RIu?TC zx2Xs%B~|U-v~!po%$pvpKBz3p$*d(Yf5rG}HEDa+;ga}GfGZwC>akf4(=t~E-i{*{ z-Iu>*X@8By@T!(WK3bK$ST`G->xMIoecjz7dAMQM@{gBq?`k*1Kj15SA61hv9vvh) zsn&iSTPK8jD(-m3xn)>AKw3aDi<@x?wZ}hh&9gh4AN_-rQ82qqU9KXH#|}(y(h8u3 z(Ckaj3HfP^7RWd>RUfc8k!28j9AhbBYCNN-#pE@>Ic2n16}^ILlW_Xeu_SwncDk&f zg9A4She!?5^h^n>n^Pt=?a}?X@Wn@a+${?4^of7TkLOm`!t#fg#$xsU!Zv+~mv`>V!>OLgtHt!jzu}BwUaDB! zV>`92f;;~lX4uI6RQaJl-AAE(bs6pY)vF}U^-&AdV}AX^wJkHw9V!E1e`fyy@5%b< zp7J~H<>D7`_VRh)6eQ;aB|vBAAh~mwgS`E`Yx}KMV|Mx^uS=aNNm-G3{Pd4Fa P5MzeAraE~?9Dn;i{uUhC diff --git a/assets/kenney-ui-gray-sheet.xml b/assets/kenney-ui-gray-sheet.xml deleted file mode 100644 index d7f87ddf..00000000 --- a/assets/kenney-ui-gray-sheet.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/bin/run-plugin-tests.sh b/bin/run-plugin-tests.sh new file mode 100644 index 00000000..28d630a9 --- /dev/null +++ b/bin/run-plugin-tests.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +set -ev + +rojo build plugin/place.project.json -o PluginPlace.rbxlx +run-in-roblox -s plugin/testBootstrap.server.lua PluginPlace.rbxlx \ No newline at end of file diff --git a/plugin/modules/lemur b/plugin/modules/lemur deleted file mode 160000 index 96d4166a..00000000 --- a/plugin/modules/lemur +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 96d4166a2d9e146e6955eeacccc0c79a86a177f5 diff --git a/plugin/place.project.json b/plugin/place.project.json index 50bbeb18..2010494e 100644 --- a/plugin/place.project.json +++ b/plugin/place.project.json @@ -20,6 +20,9 @@ }, "t": { "$path": "modules/t/lib" + }, + "RbxDom": { + "$path": "modules/rbx-dom/rbx_dom_lua/src" } }, "TestEZ": { diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index cdeefe59..5c04bd8c 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -1,11 +1,5 @@ local Assets = { - Sprites = { - WhiteCross = { - asset = "rbxassetid://2738712459", - offset = Vector2.new(190, 318), - size = Vector2.new(18, 18), - }, - }, + Sprites = {}, Slices = { RoundBox = { asset = "rbxassetid://2773204550", From f4c8f0a3d80173612ccb3a72a5410acab0fb41fa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 18:05:17 -0700 Subject: [PATCH 0630/1504] Mark bin/run-plugin-tests.sh as executable --- bin/run-plugin-tests.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 bin/run-plugin-tests.sh diff --git a/bin/run-plugin-tests.sh b/bin/run-plugin-tests.sh old mode 100644 new mode 100755 From c0b6ec8ccb33c62e6f4ae960cb64084b02efe711 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 18:10:15 -0700 Subject: [PATCH 0631/1504] Clean up more old plugin gunk --- .travis.yml | 29 ----------------------------- plugin/.gitignore | 1 - plugin/.luacov | 8 -------- plugin/loadEnvironment.lua | 37 ------------------------------------- plugin/runTest.lua | 15 --------------- plugin/spec.lua | 17 ----------------- plugin/tests/empty.lua | 5 ----- 7 files changed, 112 deletions(-) delete mode 100644 plugin/.gitignore delete mode 100644 plugin/.luacov delete mode 100644 plugin/loadEnvironment.lua delete mode 100644 plugin/runTest.lua delete mode 100644 plugin/spec.lua delete mode 100644 plugin/tests/empty.lua diff --git a/.travis.yml b/.travis.yml index 5fb8a2b2..adf57020 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,34 +1,5 @@ matrix: include: - # Lua tests are currently disabled because of holes in Lemur that are pretty - # tedious to fix. It should be fixed by either adding missing features to - # Lemur or by migrating to a CI system based on real Roblox instead. - - # - language: python - # env: - # - LUA="lua=5.1" - - # before_install: - # - pip install hererocks - # - hererocks lua_install -r^ --$LUA - # - export PATH=$PATH:$PWD/lua_install/bin - - # install: - # - luarocks install luafilesystem - # - luarocks install busted - # - luarocks install luacov - # - luarocks install luacov-coveralls - # - luarocks install luacheck - - # script: - # - cd plugin - # - luacheck src - # - lua -lluacov spec.lua - - # after_success: - # - cd plugin - # - luacov-coveralls -e $TRAVIS_BUILD_DIR/lua_install - - language: rust rust: 1.34.0 cache: cargo diff --git a/plugin/.gitignore b/plugin/.gitignore deleted file mode 100644 index 92b37c63..00000000 --- a/plugin/.gitignore +++ /dev/null @@ -1 +0,0 @@ -/luacov.* \ No newline at end of file diff --git a/plugin/.luacov b/plugin/.luacov deleted file mode 100644 index 996d3cc0..00000000 --- a/plugin/.luacov +++ /dev/null @@ -1,8 +0,0 @@ -return { - include = { - "^src", - }, - exclude = { - "%.spec$", - }, -} \ No newline at end of file diff --git a/plugin/loadEnvironment.lua b/plugin/loadEnvironment.lua deleted file mode 100644 index e7065daa..00000000 --- a/plugin/loadEnvironment.lua +++ /dev/null @@ -1,37 +0,0 @@ ---[[ - Loads the Rojo plugin and all of its dependencies. -]] - -local function loadEnvironment() - -- If you add any dependencies, add them to this table so they'll be loaded! - local LOAD_MODULES = { - {"src", "Rojo"}, - {"modules/promise/lib", "Promise"}, - {"modules/testez/lib", "TestEZ"}, - } - - -- This makes sure we can load Lemur and other libraries that depend on init.lua - package.path = package.path .. ";?/init.lua" - - -- If this fails, make sure you've run `lua bin/install-dependencies.lua` first! - local lemur = require("modules.lemur") - - -- Create a virtual Roblox tree - local habitat = lemur.Habitat.new() - - -- We'll put all of our library code and dependencies here - local modules = lemur.Instance.new("Folder") - modules.Name = "Modules" - modules.Parent = habitat.game:GetService("ReplicatedStorage") - - -- Load all of the modules specified above - for _, module in ipairs(LOAD_MODULES) do - local container = habitat:loadFromFs(module[1]) - container.Name = module[2] - container.Parent = modules - end - - return habitat, modules -end - -return loadEnvironment \ No newline at end of file diff --git a/plugin/runTest.lua b/plugin/runTest.lua deleted file mode 100644 index a3a682d0..00000000 --- a/plugin/runTest.lua +++ /dev/null @@ -1,15 +0,0 @@ -local loadEnvironment = require("loadEnvironment") - -local testPath = assert((...), "Please specify a path to a test file.") - -local habitat = loadEnvironment() - -local testModule = habitat:loadFromFs(testPath) - -if testModule == nil then - error("Couldn't find test file at " .. testPath) -end - -print("Starting test module.") - -habitat:require(testModule) \ No newline at end of file diff --git a/plugin/spec.lua b/plugin/spec.lua deleted file mode 100644 index 22ed2543..00000000 --- a/plugin/spec.lua +++ /dev/null @@ -1,17 +0,0 @@ ---[[ - Loads our library and all of its dependencies, then runs tests using TestEZ. -]] - -local loadEnvironment = require("loadEnvironment") - -local habitat, modules = loadEnvironment() - --- Load TestEZ and run our tests -local TestEZ = habitat:require(modules.TestEZ) - -local results = TestEZ.TestBootstrap:run({modules.Rojo}, TestEZ.Reporters.TextReporter) - --- Did something go wrong? -if results.failureCount > 0 then - os.exit(1) -end \ No newline at end of file diff --git a/plugin/tests/empty.lua b/plugin/tests/empty.lua deleted file mode 100644 index bfda7fad..00000000 --- a/plugin/tests/empty.lua +++ /dev/null @@ -1,5 +0,0 @@ -local ReplicatedStorage = game:GetService("ReplicatedStorage") - -local Session = require(ReplicatedStorage.Modules.Rojo.Session) - -Session.new() \ No newline at end of file From cacb02b7c800def66c82f7ff45c5cfd2f9b0181f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 18:12:15 -0700 Subject: [PATCH 0632/1504] Fix incorrect license in Cargo.toml --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 66ba1d29..3b29c352 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ name = "rojo" version = "0.5.0" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" -license = "MIT" +license = "MPL-2.0" repository = "https://github.com/rojo-rbx/rojo" edition = "2018" From 056fc5e087e3645752f33d9fad9945f0fc169d6f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 27 Aug 2019 18:23:05 -0700 Subject: [PATCH 0633/1504] Remove old 'scratch project' test script, clean up .gitignore --- .gitignore | 8 +++++--- bin/test-scratch-project | 21 --------------------- 2 files changed, 5 insertions(+), 24 deletions(-) delete mode 100644 bin/test-scratch-project diff --git a/.gitignore b/.gitignore index 506a95be..835db166 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,11 @@ +# Rust output directory /target -/scratch-project -/server/failed-snapshots/ -**/*.rs.bk + +# Roblox model and place files in the root, used for debugging /*.rbxm /*.rbxmx /*.rbxl /*.rbxlx + +# Snapshot files from the 'insta' Rust crate **/*.snap.new \ No newline at end of file diff --git a/bin/test-scratch-project b/bin/test-scratch-project deleted file mode 100644 index da79446a..00000000 --- a/bin/test-scratch-project +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -# Copies a project from 'test-projects' into a folder that can be messed with -# without accidentally checking the results into version control. - -set -e - -if [ ! -d "test-projects/$1" ] -then - echo "Pick a project that exists!" - exit 1 -fi - -if [ -d "scratch-project/$1" ] -then - rm -rf "scratch-project/$1" -fi - -mkdir -p scratch-project -cp -r "test-projects/$1" scratch-project -cargo run -- serve "scratch-project/$1" \ No newline at end of file From ea112dd93d05cf775209f73fb5351811cd2e6d4e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 28 Aug 2019 12:09:12 -0700 Subject: [PATCH 0634/1504] Mark security cookie as optional --- src/bin.rs | 6 +++--- src/commands/upload.rs | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index f55c61aa..f4d69fdc 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -54,7 +54,7 @@ fn main() { (about: "Generates a place or model file out of the project and uploads it to Roblox.") (@arg PROJECT: "Path to the project to upload. Defaults to the current directory.") (@arg kind: --kind +takes_value "The kind of asset to generate, 'place', or 'model'. Defaults to place.") - (@arg cookie: --cookie +takes_value +required "Security cookie to authenticate with.") + (@arg cookie: --cookie +takes_value "Security cookie to authenticate with. If not specified, Rojo will attempt to find one from the system automatically.") (@arg asset_id: --asset_id +takes_value +required "Asset ID to upload to.") ) ); @@ -172,7 +172,7 @@ fn start_upload(sub_matches: &ArgMatches) { }; let kind = sub_matches.value_of("kind"); - let security_cookie = sub_matches.value_of("cookie").unwrap(); + let security_cookie = sub_matches.value_of("cookie").map(Into::into); let asset_id: u64 = { let arg = sub_matches.value_of("asset_id").unwrap(); @@ -188,7 +188,7 @@ fn start_upload(sub_matches: &ArgMatches) { let options = commands::UploadOptions { fuzzy_project_path, - security_cookie: security_cookie.to_string(), + security_cookie: security_cookie, asset_id, kind, }; diff --git a/src/commands/upload.rs b/src/commands/upload.rs index c4a67afa..b7fced34 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -11,7 +11,7 @@ pub enum UploadError { #[derive(Debug)] pub struct UploadOptions<'a> { pub fuzzy_project_path: PathBuf, - pub security_cookie: String, + pub security_cookie: Option, pub asset_id: u64, pub kind: Option<&'a str>, } From e5575b782c5fc0f2619067a1ca54889fc0f77132 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 28 Aug 2019 12:20:20 -0700 Subject: [PATCH 0635/1504] Hide project module, moving towards Rojo API --- src/lib.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 7e1f570c..ed140a1d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,6 +6,10 @@ mod impl_from; // Other modules pub mod commands; + +// This module is only public for the purpose of testing right now, and won't be +// part of the first version of the Rojo API. +#[doc(hidden)] pub mod project; mod imfs; From 8fe1fa48b80bdaa06511a3301da5917591c181d7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 28 Aug 2019 13:21:30 -0700 Subject: [PATCH 0636/1504] Let Rojo pull auth cookie from registry on Windows --- Cargo.lock | 10 ++++++++++ Cargo.toml | 3 +++ src/auth_cookie.rs | 30 ++++++++++++++++++++++++++++++ src/bin.rs | 8 ++++---- src/commands/upload.rs | 15 +++++++++++---- src/lib.rs | 1 + 6 files changed, 59 insertions(+), 8 deletions(-) create mode 100644 src/auth_cookie.rs diff --git a/Cargo.lock b/Cargo.lock index 9b2d2844..5d35a3f1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1295,6 +1295,7 @@ dependencies = [ "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1815,6 +1816,14 @@ dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "winreg" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -2042,6 +2051,7 @@ dependencies = [ "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" "checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" +"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" "checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" diff --git a/Cargo.toml b/Cargo.toml index 3b29c352..7191172e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,6 +50,9 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" uuid = { version = "0.7", features = ["v4", "serde"] } +[target.'cfg(windows)'.dependencies] +winreg = "0.6.2" + [dev-dependencies] lazy_static = "1.2" paste = "0.1" diff --git a/src/auth_cookie.rs b/src/auth_cookie.rs new file mode 100644 index 00000000..5942994e --- /dev/null +++ b/src/auth_cookie.rs @@ -0,0 +1,30 @@ +//! Implementation of automatically fetching authentication cookie from a Roblox +//! Studio installation. + +#[cfg(windows)] +pub fn get_auth_cookie() -> Option { + use winreg::{enums::HKEY_CURRENT_USER, RegKey}; + + let hkcu = RegKey::predef(HKEY_CURRENT_USER); + let cookies = hkcu + .open_subkey("Software\\Roblox\\RobloxStudioBrowser\\roblox.com") + .ok()?; + + let entry: String = cookies.get_value(".ROBLOSECURITY").ok()?; + let mut cookie = None; + + for kv_pair in entry.split(",") { + let mut pieces = kv_pair.split("::"); + + if let Some("COOK") = pieces.next() { + cookie = pieces.next(); + } + } + + cookie.map(Into::into) +} + +#[cfg(not(windows))] +pub fn get_auth_cookie() -> Option { + None +} diff --git a/src/bin.rs b/src/bin.rs index f4d69fdc..7ed3c83f 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -54,7 +54,7 @@ fn main() { (about: "Generates a place or model file out of the project and uploads it to Roblox.") (@arg PROJECT: "Path to the project to upload. Defaults to the current directory.") (@arg kind: --kind +takes_value "The kind of asset to generate, 'place', or 'model'. Defaults to place.") - (@arg cookie: --cookie +takes_value "Security cookie to authenticate with. If not specified, Rojo will attempt to find one from the system automatically.") + (@arg cookie: --cookie +takes_value "Authenication cookie to authenticate with. If not specified, Rojo will attempt to find one from the system automatically.") (@arg asset_id: --asset_id +takes_value +required "Asset ID to upload to.") ) ); @@ -172,7 +172,7 @@ fn start_upload(sub_matches: &ArgMatches) { }; let kind = sub_matches.value_of("kind"); - let security_cookie = sub_matches.value_of("cookie").map(Into::into); + let auth_cookie = sub_matches.value_of("cookie").map(Into::into); let asset_id: u64 = { let arg = sub_matches.value_of("asset_id").unwrap(); @@ -188,12 +188,12 @@ fn start_upload(sub_matches: &ArgMatches) { let options = commands::UploadOptions { fuzzy_project_path, - security_cookie: security_cookie, + auth_cookie, asset_id, kind, }; - match commands::upload(&options) { + match commands::upload(options) { Ok(_) => {} Err(e) => { error!("{}", e); diff --git a/src/commands/upload.rs b/src/commands/upload.rs index b7fced34..6f8c0dbe 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -2,20 +2,27 @@ use std::path::PathBuf; use failure::Fail; +use crate::auth_cookie::get_auth_cookie; + #[derive(Debug, Fail)] pub enum UploadError { - #[fail(display = "This error cannot happen")] - StubError, + #[fail(display = "Rojo could not find your Roblox auth cookie. Please pass one via --cookie.")] + NeedAuthCookie, } #[derive(Debug)] pub struct UploadOptions<'a> { pub fuzzy_project_path: PathBuf, - pub security_cookie: Option, + pub auth_cookie: Option, pub asset_id: u64, pub kind: Option<&'a str>, } -pub fn upload(_options: &UploadOptions) -> Result<(), UploadError> { +pub fn upload(options: UploadOptions) -> Result<(), UploadError> { + let cookie = options + .auth_cookie + .or_else(get_auth_cookie) + .ok_or(UploadError::NeedAuthCookie)?; + unimplemented!("TODO: Reimplement upload command"); } diff --git a/src/lib.rs b/src/lib.rs index ed140a1d..a99f9114 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,7 @@ pub mod commands; #[doc(hidden)] pub mod project; +mod auth_cookie; mod imfs; mod message_queue; mod path_map; From 68dbb31272577411edd7bdcd424336f1b5a48f0a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 28 Aug 2019 13:34:20 -0700 Subject: [PATCH 0637/1504] Add verbosity level argument --- src/bin.rs | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index 7ed3c83f..56e2f685 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -19,21 +19,15 @@ fn make_path_absolute(value: &Path) -> PathBuf { } fn main() { - { - let log_env = env_logger::Env::default().default_filter_or("warn"); - - env_logger::Builder::from_env(log_env) - .default_format_timestamp(false) - .init(); - } - let app = clap_app!(Rojo => (version: env!("CARGO_PKG_VERSION")) (author: env!("CARGO_PKG_AUTHORS")) (about: env!("CARGO_PKG_DESCRIPTION")) + (@arg verbose: --verbose -v +multiple +global "Sets verbosity level. Can be specified multiple times.") + (@subcommand init => - (about: "Creates a new Rojo project") + (about: "Creates a new Rojo project.") (@arg PATH: "Path to the place to create the project. Defaults to the current directory.") (@arg kind: --kind +takes_value "The kind of project to create, 'place' or 'model'. Defaults to place.") ) @@ -45,7 +39,7 @@ fn main() { ) (@subcommand build => - (about: "Generates an rbxmx model file from the project.") + (about: "Generates a model or place file from the project.") (@arg PROJECT: "Path to the project to serve. Defaults to the current directory.") (@arg output: --output -o +takes_value +required "Where to output the result.") ) @@ -54,13 +48,29 @@ fn main() { (about: "Generates a place or model file out of the project and uploads it to Roblox.") (@arg PROJECT: "Path to the project to upload. Defaults to the current directory.") (@arg kind: --kind +takes_value "The kind of asset to generate, 'place', or 'model'. Defaults to place.") - (@arg cookie: --cookie +takes_value "Authenication cookie to authenticate with. If not specified, Rojo will attempt to find one from the system automatically.") + (@arg cookie: --cookie +takes_value "Authenication cookie to use. If not specified, Rojo will attempt to find one from the system automatically.") (@arg asset_id: --asset_id +takes_value +required "Asset ID to upload to.") ) ); let matches = app.get_matches(); + { + let verbosity = matches.occurrences_of("verbose"); + let log_filter = match verbosity { + 0 => "warn", + 1 => "warn,librojo=info", + 2 => "warn,librojo=trace", + _ => "trace", + }; + + let log_env = env_logger::Env::default().default_filter_or(log_filter); + + env_logger::Builder::from_env(log_env) + .default_format_timestamp(false) + .init(); + } + let result = panic::catch_unwind(|| match matches.subcommand() { ("init", Some(sub_matches)) => start_init(sub_matches), ("serve", Some(sub_matches)) => start_serve(sub_matches), From b7d613ace6c23cb40184260dddc696218ef0cc70 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 28 Aug 2019 13:55:12 -0700 Subject: [PATCH 0638/1504] Correct bug report repository link --- src/bin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin.rs b/src/bin.rs index 56e2f685..f49dc2bb 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -97,7 +97,7 @@ fn show_crash_message(message: &str) { error!("Rojo crashed!"); error!("This is a bug in Rojo."); error!(""); - error!("Please consider filing a bug: https://github.com/LPGhatguy/rojo/issues"); + error!("Please consider filing a bug: https://github.com/rojo-rbx/rojo/issues"); error!(""); error!("Details: {}", message); } From d4c28de2c4f376ceceabd3588c197ba296b6821d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 28 Aug 2019 14:34:14 -0700 Subject: [PATCH 0639/1504] Update changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4c55f1f..8af4578f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes +* Added `--verbose`/`-v` flag, which can be specified multiple times to increase verbosity +* Added support for automatically finding Roblox Studio's auth cookie for `rojo upload` on Windows ## [0.5.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0) (August 27, 2019) * Changed `.model.json` naming, which may require projects to migrate ambiguous cases: From b45d4f6401ccbb853d18ecac64584f62a892059a Mon Sep 17 00:00:00 2001 From: Jaguar <48777426+Jaguar-515@users.noreply.github.com> Date: Wed, 28 Aug 2019 21:29:48 -0700 Subject: [PATCH 0640/1504] Correct capitalization/typos (#240) * Fix typo * Correct capitalization * Correct capitalization --- docs/guide/installation.md | 2 +- docs/guide/new-game.md | 2 +- docs/why-rojo.md | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/guide/installation.md b/docs/guide/installation.md index bae79754..dabd1f75 100644 --- a/docs/guide/installation.md +++ b/docs/guide/installation.md @@ -43,4 +43,4 @@ Download the attached `rbxm` file and put it into your Roblox Studio plugins fol {: align="center" } ### Installing from Roblox.com -Visit [Rojo's Roblox.com Plugin page](https://www.roblox.com/library/1997686364/Rojo-0-5-0-alpha-3) in Roblox Studio and press **Install**. \ No newline at end of file +Visit [Rojo's roblox.com plugin page](https://www.roblox.com/library/1997686364/Rojo-0-5-0-alpha-3) in Roblox Studio and press **Install**. diff --git a/docs/guide/new-game.md b/docs/guide/new-game.md index 638d4263..ffbba4c8 100644 --- a/docs/guide/new-game.md +++ b/docs/guide/new-game.md @@ -87,4 +87,4 @@ Generating and publishing your game is as simple as: rojo upload --asset_id [PLACE ID] --cookie "[SECURITY COOKIE]" ``` -An example project is available on GitHub that deploys to Roblox.com from GitHub and Travis-CI automatically: [https://github.com/LPGhatguy/roads](https://github.com/LPGhatguy/roads) +An example project is available on GitHub that deploys to roblox.com from GitHub and Travis-CI automatically: [https://github.com/LPGhatguy/roads](https://github.com/LPGhatguy/roads) diff --git a/docs/why-rojo.md b/docs/why-rojo.md index 05324834..279cb022 100644 --- a/docs/why-rojo.md +++ b/docs/why-rojo.md @@ -12,7 +12,7 @@ Rojo opens the door to use the absolute best text editors in the world and their Some very popular editors include [Visual Studio Code](https://code.visualstudio.com) and [Sublime Text](https://www.sublimetext.com). -These advanced text editors have features like multi-cursor editing, goto symbol, multi-file regex find and replace, bookmarks and much more. +These advanced text editors have features like multi-cursor editing, go-to symbol, multi-file regex find and replace, bookmarks and much more. Many Rojo VS Code users also use extensions like: @@ -41,4 +41,4 @@ Popular tools include: * [luacheck](https://github.com/mpeterv/luacheck), a static analysis tool to help you write better Lua * [ripgrep](https://github.com/BurntSushi/ripgrep), an extremely fast code search tool -* [Tokei](https://github.com/XAMPPRocky/tokei), a tool for statistics like lines of code \ No newline at end of file +* [Tokei](https://github.com/XAMPPRocky/tokei), a tool for statistics like lines of code From ee3fed97e075e4a85b2519e6cc1fc908c3985f7f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 29 Aug 2019 16:31:32 -0700 Subject: [PATCH 0641/1504] Fix parsing of auth cookie data --- src/auth_cookie.rs | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/auth_cookie.rs b/src/auth_cookie.rs index 5942994e..9d968dd8 100644 --- a/src/auth_cookie.rs +++ b/src/auth_cookie.rs @@ -17,7 +17,22 @@ pub fn get_auth_cookie() -> Option { let mut pieces = kv_pair.split("::"); if let Some("COOK") = pieces.next() { - cookie = pieces.next(); + let value = match pieces.next() { + Some(value) => value, + None => { + log::warn!("Unrecognized Roblox Studio cookie value: missing COOK value"); + return None; + } + }; + + if !value.starts_with('<') || !value.ends_with('>') { + log::warn!("Unrecognized Roblox Studio cookie value: was not wrapped in <>"); + return None; + } + + let value = &value[1..value.len() - 1]; + + cookie = Some(value); } } From 4e512b7023d4ff744a83da23d877941e004c03cf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 29 Aug 2019 16:31:42 -0700 Subject: [PATCH 0642/1504] Revert to using Reqwest, reimplement upload command --- Cargo.lock | 388 +++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/commands/upload.rs | 81 ++++++++- 3 files changed, 467 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5d35a3f1..67242094 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,10 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +[[package]] +name = "adler32" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "aho-corasick" version = "0.7.6" @@ -224,6 +229,54 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cookie" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cookie_store" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "core-foundation-sys" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "crc32fast" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-channel" version = "0.3.9" @@ -328,6 +381,14 @@ name = "encode_unicode" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "encoding_rs" +version = "0.8.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "env_logger" version = "0.6.2" @@ -384,11 +445,34 @@ dependencies = [ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "flate2" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fsevent" version = "0.4.0" @@ -547,6 +631,38 @@ dependencies = [ "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hyper-tls" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "idna" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "idna" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "indexmap" version = "1.1.0" @@ -687,6 +803,11 @@ name = "maplit" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "matches" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "md5" version = "0.6.1" @@ -708,6 +829,31 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mime" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "mime_guess" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "miniz_oxide" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mio" version = "0.6.19" @@ -747,6 +893,23 @@ dependencies = [ "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "native-tls" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "net2" version = "0.2.33" @@ -810,6 +973,36 @@ name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "openssl" +version = "0.10.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl-probe" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "openssl-sys" +version = "0.9.49" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "output_vt100" version = "0.1.2" @@ -891,6 +1084,16 @@ dependencies = [ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "percent-encoding" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "pest" version = "2.1.1" @@ -930,6 +1133,11 @@ dependencies = [ "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "pkg-config" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "ppv-lite86" version = "0.2.5" @@ -977,6 +1185,18 @@ dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "publicsuffix" +version = "1.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "pulldown-cmark" version = "0.2.0" @@ -1244,6 +1464,39 @@ dependencies = [ "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "reqwest" +version = "0.9.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", + "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ritz" version = "0.1.0" @@ -1289,6 +1542,7 @@ dependencies = [ "rbx_reflection 3.2.395 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1344,6 +1598,15 @@ dependencies = [ "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "schannel" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "scopeguard" version = "0.3.3" @@ -1354,6 +1617,25 @@ name = "scopeguard" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "security-framework" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "security-framework-sys" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "semver" version = "0.9.0" @@ -1406,6 +1688,17 @@ dependencies = [ "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "serde_urlencoded" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "serde_yaml" version = "0.8.9" @@ -1587,6 +1880,7 @@ dependencies = [ "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1701,6 +1995,14 @@ name = "try-lock" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "try_from" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "typenum" version = "1.11.2" @@ -1711,6 +2013,30 @@ name = "ucd-trie" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "unicase" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "unicode-width" version = "0.1.6" @@ -1726,6 +2052,26 @@ name = "unicode-xid" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "url" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "url" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "uuid" version = "0.7.4" @@ -1735,6 +2081,11 @@ dependencies = [ "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "vcpkg" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "vec_map" version = "0.8.1" @@ -1847,6 +2198,7 @@ dependencies = [ ] [metadata] +"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" @@ -1873,6 +2225,11 @@ dependencies = [ "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ca57c2c14b8a2bf3105bc9d15574aad80babf6a9c44b1058034cdf8bd169628" +"checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" +"checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" +"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" +"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" @@ -1886,13 +2243,17 @@ dependencies = [ "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" "checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" +"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2f8c63033fcba1f51ef744505b3cad42510432b904c062afa67ad7ece008429d" +"checksum flate2 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "2adaffba6388640136149e18ed080b77a78611c1e1d6de75aedcdf78df5d4682" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" "checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" "checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" @@ -1910,6 +2271,9 @@ dependencies = [ "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" "checksum hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)" = "7cb44cbce9d8ee4fb36e4c0ad7b794ac44ebaad924b9c8291a63215bb44c2c8f" +"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" +"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" +"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" "checksum indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4d6d89e0948bf10c08b9ecc8ac5b83f07f857ebe2c0cbe38de15b4e4f510356" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" @@ -1928,12 +2292,17 @@ dependencies = [ "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" "checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" +"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e6bcd6433cff03a4bfc3d9834d504467db1f1cf6d0ea765d37d330249ed629d" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" +"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" +"checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" +"checksum miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7108aff85b876d06f22503dcce091e29f76733b2bfdd91eebce81f5e68203a10" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3572d71f13ea8ed41867accd971fd564aa75934cf7a1fae03ddb8c74a8a49943" @@ -1941,6 +2310,9 @@ dependencies = [ "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +"checksum openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)" = "8152bb5a9b5b721538462336e3bef9a539f892715e5037fda0f984577311af15" +"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" +"checksum openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)" = "f4fad9e54bd23bd4cbbe48fdc08a1b8091707ac869ef8508edea2fec77dcc884" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" @@ -1949,16 +2321,20 @@ dependencies = [ "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" "checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" +"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" "checksum pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "933085deae3f32071f135d799d75667b63c8dc1f4537159756e3d4ceab41868c" "checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" "checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646" "checksum pest_meta 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f249ea6de7c7b7aba92b4ff4376a994c6dbd98fd2166c89d5c4947397ecb574d" +"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" "checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" "checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802" +"checksum publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9bf259a81de2b2eb9850ec990ec78e6a25319715584fd7652b9b26f96fcb1510" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" @@ -1988,6 +2364,7 @@ dependencies = [ "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" "checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +"checksum reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)" = "0f6d896143a583047512e59ac54a215cb203c29cc941917343edea3be8df9c78" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "17f52a24414403f81528b67488cf8edc4eda977d3af1646bb6b106a600ead78f" @@ -1995,14 +2372,18 @@ dependencies = [ "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" +"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" +"checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" +"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" "checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425" "checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" "checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" +"checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" @@ -2033,12 +2414,19 @@ dependencies = [ "checksum tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "90ca01319dea1e376a001e8dc192d42ebde6dd532532a5bad988ac37db365b19" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" +"checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" +"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" +"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" +"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" diff --git a/Cargo.toml b/Cargo.toml index 7191172e..9c1a5e93 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,6 +36,7 @@ env_logger = "0.6" failure = "0.1.3" futures = "0.1" hyper = "0.12" +reqwest = "0.9.20" jod-thread = "0.1.0" log = "0.4" maplit = "1.0.1" diff --git a/src/commands/upload.rs b/src/commands/upload.rs index 6f8c0dbe..166f293b 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -1,15 +1,36 @@ -use std::path::PathBuf; +use std::{collections::HashMap, path::PathBuf}; use failure::Fail; +use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; +use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}; -use crate::auth_cookie::get_auth_cookie; +use crate::{ + auth_cookie::get_auth_cookie, + imfs::new::{Imfs, RealFetcher, WatchMode}, + snapshot::{apply_patch_set, compute_patch_set}, + snapshot_middleware::snapshot_from_imfs, +}; #[derive(Debug, Fail)] pub enum UploadError { #[fail(display = "Rojo could not find your Roblox auth cookie. Please pass one via --cookie.")] NeedAuthCookie, + + #[fail(display = "XML model file encode error: {}", _0)] + XmlModelEncode(#[fail(cause)] rbx_xml::EncodeError), + + #[fail(display = "HTTP error: {}", _0)] + Http(#[fail(cause)] reqwest::Error), + + #[fail(display = "Roblox API error: {}", _0)] + RobloxApi(String), } +impl_from!(UploadError { + rbx_xml::EncodeError => XmlModelEncode, + reqwest::Error => Http, +}); + #[derive(Debug)] pub struct UploadOptions<'a> { pub fuzzy_project_path: PathBuf, @@ -24,5 +45,59 @@ pub fn upload(options: UploadOptions) -> Result<(), UploadError> { .or_else(get_auth_cookie) .ok_or(UploadError::NeedAuthCookie)?; - unimplemented!("TODO: Reimplement upload command"); + let mut tree = RbxTree::new(RbxInstanceProperties { + name: "ROOT".to_owned(), + class_name: "Folder".to_owned(), + properties: HashMap::new(), + }); + let root_id = tree.get_root_id(); + + log::trace!("Constructing in-memory filesystem"); + let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Disabled)); + + log::trace!("Reading project root"); + let entry = imfs + .get(&options.fuzzy_project_path) + .expect("could not get project path"); + + log::trace!("Generating snapshot of instances from IMFS"); + let snapshot = snapshot_from_imfs(&mut imfs, &entry) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + log::trace!("Computing patch set"); + let patch_set = compute_patch_set(&snapshot, &tree, root_id); + + log::trace!("Applying patch set"); + apply_patch_set(&mut tree, &patch_set); + + let root_id = tree.get_root_id(); + + let mut buffer = Vec::new(); + + let config = rbx_xml::EncodeOptions::new() + .property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown); + rbx_xml::to_writer(&mut buffer, &tree, &[root_id], config)?; + + let url = format!( + "https://data.roblox.com/Data/Upload.ashx?assetid={}", + options.asset_id + ); + + let client = reqwest::Client::new(); + let mut response = client + .post(&url) + .header(COOKIE, format!(".ROBLOSECURITY={}", &cookie)) + .header(USER_AGENT, "Roblox/WinInet") + .header("Requester", "Client") + .header(CONTENT_TYPE, "application/xml") + .header(ACCEPT, "application/json") + .body(buffer) + .send()?; + + if !response.status().is_success() { + return Err(UploadError::RobloxApi(response.text()?)); + } + + Ok(()) } From 78e3cf4ffb6f416b031ae852fa9ee006c653abdf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 29 Aug 2019 16:38:04 -0700 Subject: [PATCH 0643/1504] Fix rojo-test tests not running on CI --- .travis.yml | 2 +- bin/run-tests.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index adf57020..d37159cd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,7 +5,7 @@ matrix: cache: cargo script: - - cargo test --locked --verbose + - cargo test --all --locked --verbose - language: rust rust: stable diff --git a/bin/run-tests.sh b/bin/run-tests.sh index b218506d..03647950 100755 --- a/bin/run-tests.sh +++ b/bin/run-tests.sh @@ -2,6 +2,6 @@ set -ev -cargo test --locked --verbose +cargo test --all --locked --verbose cargo fmt -- --check cargo clippy \ No newline at end of file From 0f530b7e807975f7c0f0134a12e3e5342a80cbd8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 29 Aug 2019 16:38:41 -0700 Subject: [PATCH 0644/1504] Add deep-nesting test for folders in folders --- .../level-1/level-2/level-3/.gitkeep | 0 rojo-test/src/build_test.rs | 1 + .../snapshots/build_test__deep_nesting.snap | 28 +++++++++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 rojo-test/build-tests/deep_nesting/level-1/level-2/level-3/.gitkeep create mode 100644 rojo-test/src/snapshots/build_test__deep_nesting.snap diff --git a/rojo-test/build-tests/deep_nesting/level-1/level-2/level-3/.gitkeep b/rojo-test/build-tests/deep_nesting/level-1/level-2/level-3/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index c7754baa..2a8676b7 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -22,6 +22,7 @@ gen_build_tests! { csv_bug_145, csv_bug_147, csv_in_folder, + deep_nesting, gitkeep, json_model_in_folder, json_model_legacy_name, diff --git a/rojo-test/src/snapshots/build_test__deep_nesting.snap b/rojo-test/src/snapshots/build_test__deep_nesting.snap new file mode 100644 index 00000000..23b0227d --- /dev/null +++ b/rojo-test/src/snapshots/build_test__deep_nesting.snap @@ -0,0 +1,28 @@ +--- +created: "2019-08-29T23:38:13.072820400Z" +creator: insta@0.10.1 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + deep_nesting + + + + level-1 + + + + level-2 + + + + level-3 + + + + + + From 2fb2342fd464d1586d1581b3d8d070492719bd6b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 29 Aug 2019 17:13:36 -0700 Subject: [PATCH 0645/1504] Fix Lua snapshot code to work with children. It's also way easier to read now --- .../build-tests/init_with_children/init.lua | 1 + .../build-tests/init_with_children/other.lua | 1 + rojo-test/src/build_test.rs | 1 + .../build_test__init_with_children.snap | 20 +++ src/snapshot_middleware/lua.rs | 144 +++++++++++------- 5 files changed, 111 insertions(+), 56 deletions(-) create mode 100644 rojo-test/build-tests/init_with_children/init.lua create mode 100644 rojo-test/build-tests/init_with_children/other.lua create mode 100644 rojo-test/src/snapshots/build_test__init_with_children.snap diff --git a/rojo-test/build-tests/init_with_children/init.lua b/rojo-test/build-tests/init_with_children/init.lua new file mode 100644 index 00000000..1bdba462 --- /dev/null +++ b/rojo-test/build-tests/init_with_children/init.lua @@ -0,0 +1 @@ +-- init.lua \ No newline at end of file diff --git a/rojo-test/build-tests/init_with_children/other.lua b/rojo-test/build-tests/init_with_children/other.lua new file mode 100644 index 00000000..2cf052cf --- /dev/null +++ b/rojo-test/build-tests/init_with_children/other.lua @@ -0,0 +1 @@ +-- other.lua \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index 2a8676b7..7a85d0df 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -24,6 +24,7 @@ gen_build_tests! { csv_in_folder, deep_nesting, gitkeep, + init_with_children, json_model_in_folder, json_model_legacy_name, module_in_folder, diff --git a/rojo-test/src/snapshots/build_test__init_with_children.snap b/rojo-test/src/snapshots/build_test__init_with_children.snap new file mode 100644 index 00000000..f35e6e2f --- /dev/null +++ b/rojo-test/src/snapshots/build_test__init_with_children.snap @@ -0,0 +1,20 @@ +--- +created: "2019-08-30T00:12:56.686707700Z" +creator: insta@0.10.1 +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + init_with_children + -- init.lua + + + + other + -- other.lua + + + + diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index a2e86495..8ae12323 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -8,7 +8,10 @@ use crate::{ snapshot::InstanceSnapshot, }; -use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; +use super::{ + dir::SnapshotDir, + middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, +}; pub struct SnapshotLua; @@ -19,64 +22,29 @@ impl SnapshotMiddleware for SnapshotLua { ) -> SnapshotInstanceResult<'static> { let file_name = entry.path().file_name().unwrap().to_string_lossy(); - if entry.is_directory() { - let module_init_path = entry.path().join("init.lua"); - if let Some(init_entry) = imfs.get(module_init_path).with_not_found()? { - if let Some(mut snapshot) = SnapshotLua::from_imfs(imfs, &init_entry)? { - snapshot.name = Cow::Owned(file_name.into_owned()); - - return Ok(Some(snapshot)); - } - } - - let server_init_path = entry.path().join("init.server.lua"); - if let Some(init_entry) = imfs.get(server_init_path).with_not_found()? { - if let Some(mut snapshot) = SnapshotLua::from_imfs(imfs, &init_entry)? { - snapshot.name = Cow::Owned(file_name.into_owned()); - - return Ok(Some(snapshot)); - } - } - - let client_init_path = entry.path().join("init.client.lua"); - if let Some(init_entry) = imfs.get(client_init_path).with_not_found()? { - if let Some(mut snapshot) = SnapshotLua::from_imfs(imfs, &init_entry)? { - snapshot.name = Cow::Owned(file_name.into_owned()); - - return Ok(Some(snapshot)); - } - } + // These paths alter their parent instance, so we don't need to turn + // them into a script instance here. + match &*file_name { + "init.lua" | "init.server.lua" | "init.client.lua" => return Ok(None), + _ => {} } - let (class_name, instance_name) = - if let Some(name) = match_trailing(&file_name, ".server.lua") { - ("Script", name) - } else if let Some(name) = match_trailing(&file_name, ".client.lua") { - ("LocalScript", name) - } else if let Some(name) = match_trailing(&file_name, ".lua") { - ("ModuleScript", name) + if entry.is_file() { + snapshot_lua_file(imfs, entry) + } else { + if let Some(snapshot) = snapshot_init(imfs, entry, "init.lua")? { + // An `init.lua` file turns its parent into a ModuleScript + Ok(Some(snapshot)) + } else if let Some(snapshot) = snapshot_init(imfs, entry, "init.server.lua")? { + // An `init.server.lua` file turns its parent into a Script + Ok(Some(snapshot)) + } else if let Some(snapshot) = snapshot_init(imfs, entry, "init.client.lua")? { + // An `init.client.lua` file turns its parent into a LocalScript + Ok(Some(snapshot)) } else { - return Ok(None); - }; - - let contents = entry.contents(imfs)?; - let contents_str = str::from_utf8(contents) - .expect("File content was not valid UTF-8") - .to_string(); - - let properties = hashmap! { - "Source".to_owned() => RbxValue::String { - value: contents_str, - }, - }; - - Ok(Some(InstanceSnapshot { - snapshot_id: None, - name: Cow::Owned(instance_name.to_owned()), - class_name: Cow::Borrowed(class_name), - properties, - children: Vec::new(), - })) + Ok(None) + } + } } fn from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult { @@ -91,6 +59,70 @@ impl SnapshotMiddleware for SnapshotLua { } } +/// Core routine for turning Lua files into snapshots. +fn snapshot_lua_file( + imfs: &mut Imfs, + entry: &ImfsEntry, +) -> SnapshotInstanceResult<'static> { + let file_name = entry.path().file_name().unwrap().to_string_lossy(); + + let (class_name, instance_name) = if let Some(name) = match_trailing(&file_name, ".server.lua") + { + ("Script", name) + } else if let Some(name) = match_trailing(&file_name, ".client.lua") { + ("LocalScript", name) + } else if let Some(name) = match_trailing(&file_name, ".lua") { + ("ModuleScript", name) + } else { + return Ok(None); + }; + + let contents = entry.contents(imfs)?; + let contents_str = str::from_utf8(contents) + .expect("File content was not valid UTF-8") + .to_string(); + + let properties = hashmap! { + "Source".to_owned() => RbxValue::String { + value: contents_str, + }, + }; + + Ok(Some(InstanceSnapshot { + snapshot_id: None, + name: Cow::Owned(instance_name.to_owned()), + class_name: Cow::Borrowed(class_name), + properties, + children: Vec::new(), + })) +} + +/// Attempts to snapshot an 'init' Lua script contained inside of a folder with +/// the given name. +/// +/// Scripts named `init.lua`, `init.server.lua`, or `init.client.lua` usurp +/// their parents, which acts similarly to `__init__.py` from the Python world. +fn snapshot_init( + imfs: &mut Imfs, + folder_entry: &ImfsEntry, + init_name: &str, +) -> SnapshotInstanceResult<'static> { + let init_path = folder_entry.path().join(init_name); + + if let Some(init_entry) = imfs.get(init_path).with_not_found()? { + if let Some(mut dir_snapshot) = SnapshotDir::from_imfs(imfs, folder_entry)? { + if let Some(mut init_snapshot) = snapshot_lua_file(imfs, &init_entry)? { + init_snapshot.name = dir_snapshot.name; + init_snapshot.children = dir_snapshot.children; + + return Ok(Some(init_snapshot)); + } + } + } + + Ok(None) +} + fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { if input.ends_with(trailer) { let end = input.len().saturating_sub(trailer.len()); From 6747d97d60a69f4afd2d913870470a986f5d7cce Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Sep 2019 10:25:48 -0700 Subject: [PATCH 0646/1504] Factor out test utilities in preparation for serve tests --- Cargo.lock | 217 ++++++++++++++++++++++++------------ rojo-test/Cargo.toml | 1 + rojo-test/src/build_test.rs | 14 +-- rojo-test/src/lib.rs | 5 + rojo-test/src/serve_test.rs | 1 + rojo-test/src/util.rs | 28 +++++ 6 files changed, 186 insertions(+), 80 deletions(-) create mode 100644 rojo-test/src/serve_test.rs create mode 100644 rojo-test/src/util.rs diff --git a/Cargo.lock b/Cargo.lock index 67242094..18471fba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,7 +18,7 @@ name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -35,7 +35,7 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -97,7 +97,7 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -106,6 +106,11 @@ dependencies = [ "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bumpalo" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byte-tools" version = "0.3.1" @@ -164,14 +169,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "chrono" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "js-sys 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -201,7 +208,7 @@ dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -223,10 +230,10 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -329,7 +336,7 @@ name = "csv" version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -397,7 +404,7 @@ dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -437,12 +444,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "filetime" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -691,13 +699,13 @@ name = "insta" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)", + "chrono 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "ci_info 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", @@ -725,6 +733,14 @@ name = "jod-thread" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "js-sys" +version = "0.3.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wasm-bindgen 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -917,7 +933,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -927,11 +943,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "notify" -version = "4.0.12" +version = "4.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -940,7 +956,7 @@ dependencies = [ "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1008,7 +1024,7 @@ name = "output_vt100" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1047,7 +1063,7 @@ dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1061,7 +1077,7 @@ dependencies = [ "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1079,7 +1095,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1096,7 +1112,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pest" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1107,29 +1123,29 @@ name = "pest_derive" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "pest_generator" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_meta 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "pest_meta" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1159,7 +1175,7 @@ name = "proc-macro-hack" version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1179,7 +1195,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1193,7 +1209,7 @@ dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1223,7 +1239,7 @@ name = "quote" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1235,7 +1251,7 @@ dependencies = [ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1253,7 +1269,7 @@ dependencies = [ "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1264,7 +1280,7 @@ dependencies = [ "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1283,7 +1299,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1301,7 +1317,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "rand_core" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1320,7 +1336,7 @@ name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1338,7 +1354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1351,7 +1367,7 @@ dependencies = [ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1434,12 +1450,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1453,7 +1469,7 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.11" +version = "0.6.12" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1461,7 +1477,7 @@ name = "remove_dir_all" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1534,14 +1550,14 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 3.2.395 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1558,6 +1574,7 @@ version = "0.1.0" dependencies = [ "insta 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", "rojo 0.5.0", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1604,7 +1621,7 @@ version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1663,7 +1680,7 @@ name = "serde_derive" version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1683,7 +1700,7 @@ name = "serde_repr" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1787,7 +1804,7 @@ name = "syn" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1822,7 +1839,7 @@ dependencies = [ "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1864,7 +1881,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2102,7 +2119,7 @@ version = "2.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2121,6 +2138,55 @@ name = "wasi" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "wasm-bindgen" +version = "0.2.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro-support 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.50" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.50" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.2.8" @@ -2128,7 +2194,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2150,7 +2216,7 @@ name = "winapi-util" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2163,7 +2229,7 @@ name = "wincolor" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2172,7 +2238,7 @@ name = "winreg" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2210,7 +2276,8 @@ dependencies = [ "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" -"checksum bstr 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "94cdf78eb7e94c566c1f5dbe2abf8fc70a548fc902942a48c4b3a98b48ca9ade" +"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" +"checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" @@ -2219,7 +2286,7 @@ dependencies = [ "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" "checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" -"checksum chrono 0.4.7 (registry+https://github.com/rust-lang/crates.io-index)" = "77d81f58b7301084de3b958691458a53c3f7e0b1d702f77e550b6a88e3a88abe" +"checksum chrono 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "27429a03ca54100bf6bdc726c09adc46a74187ac93f9ce96dc7aaa9594ebf707" "checksum ci_info 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e5e881307a989a3a5e20d52a32cc05950e3c2178cccfcc9428271a6cde09f902" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" @@ -2249,7 +2316,7 @@ dependencies = [ "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum filetime 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "2f8c63033fcba1f51ef744505b3cad42510432b904c062afa67ad7ece008429d" +"checksum filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd7380b54ced79dda72ecc35cc4fbbd1da6bba54afaa37e96fd1c2a308cd469" "checksum flate2 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "2adaffba6388640136149e18ed080b77a78611c1e1d6de75aedcdf78df5d4682" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" @@ -2281,6 +2348,7 @@ dependencies = [ "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f52a11f73b88fab829a0e4d9e13ea5982c7ac457c72eb3541d82a4afdfce4ff" +"checksum js-sys 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)" = "1efc4f2a556c58e79c5500912e221dd826bec64ff4aabd8ce71ccef6da02d7d4" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" @@ -2305,7 +2373,7 @@ dependencies = [ "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum notify 4.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "3572d71f13ea8ed41867accd971fd564aa75934cf7a1fae03ddb8c74a8a49943" +"checksum notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1191efa2b8fe041decb55c238a125b7a1aeb6fad7a525133a02be5ec949ff3cb" "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" @@ -2323,17 +2391,17 @@ dependencies = [ "checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -"checksum pest 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "933085deae3f32071f135d799d75667b63c8dc1f4537159756e3d4ceab41868c" +"checksum pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e4fb201c5c22a55d8b24fef95f78be52738e5e1361129be1b5e862ecdb6894a" "checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" -"checksum pest_generator 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "63120576c4efd69615b5537d3d052257328a4ca82876771d6944424ccfd9f646" -"checksum pest_meta 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f249ea6de7c7b7aba92b4ff4376a994c6dbd98fd2166c89d5c4947397ecb574d" +"checksum pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9fcf299b5712d06ee128a556c94709aaa04512c4dffb8ead07c5c998447fc0" +"checksum pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df43fd99896fd72c485fe47542c7b500e4ac1e8700bf995544d1317a60ded547" "checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" "checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5c2380ae88876faae57698be9e9775e3544decad214599c3a6266cca6ac802" +"checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95" "checksum publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9bf259a81de2b2eb9850ec990ec78e6a25319715584fd7652b9b26f96fcb1510" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" @@ -2346,7 +2414,7 @@ dependencies = [ "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" "checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -"checksum rand_core 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "615e683324e75af5d43d8f7a39ffe3ee4a9dc42c5c701167a71dc59c3a493aca" +"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" "checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" "checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" @@ -2360,9 +2428,9 @@ dependencies = [ "checksum rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0236363b0af0c78f3e972ac7f46a1f355f663518e276253136d0180f3c8742c" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88c3d9193984285d544df4a30c23a4e62ead42edf70a4452ceb76dac1ce05c26" +"checksum regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc98360d9e6ad383647702acc90f80b0582eac3ea577ab47d96325d3575de908" "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" -"checksum regex-syntax 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b143cceb2ca5e56d5671988ef8b15615733e7ee16cd348e064333b251b89343f" +"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)" = "0f6d896143a583047512e59ac54a215cb203c29cc941917343edea3be8df9c78" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" @@ -2432,8 +2500,13 @@ dependencies = [ "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" "checksum wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd5442abcac6525a045cc8c795aedb60da7a2e5e89c7bf18a0d5357849bb23c7" +"checksum wasm-bindgen 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "dcddca308b16cd93c2b67b126c688e5467e4ef2e28200dc7dfe4ae284f2faefc" +"checksum wasm-bindgen-backend 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "f805d9328b5fc7e5c6399960fd1889271b9b58ae17bdb2417472156cc9fafdd0" +"checksum wasm-bindgen-macro 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "3ff88201a482abfc63921621f6cb18eb1efd74f136b05e5841e7f8ca434539e9" +"checksum wasm-bindgen-macro-support 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "6a433d89ecdb9f77d46fcf00c8cf9f3467b7de9954d8710c175f61e2e245bb0e" +"checksum wasm-bindgen-shared 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "d41fc1bc3570cdf8d108c15e014045fd45a95bb5eb36605f96a90461fc34027d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770" +"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index c8072f3e..fdda8754 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -9,6 +9,7 @@ publish = false insta = "0.10.0" paste = "0.1.5" tempfile = "3.1.0" +reqwest = "0.9.20" # We execute Rojo via std::process::Command, so depend on it so it's built! rojo = { path = ".." } \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index 7a85d0df..fcfa7a3f 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -1,8 +1,10 @@ -use std::{fs, path::Path, process::Command}; +use std::{fs, process::Command}; use insta::assert_snapshot_matches; use tempfile::tempdir; +use crate::util::{get_build_tests_path, get_rojo_path, get_working_dir_path}; + macro_rules! gen_build_tests { ( $($test_name: ident,)* ) => { $( @@ -49,19 +51,15 @@ fn build_rbxmx_ref() { } fn run_build_test(test_name: &str) { - let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); - let build_test_path = manifest_dir.join("build-tests"); - let working_dir = manifest_dir.parent().unwrap(); + let build_test_path = get_build_tests_path(); + let working_dir = get_working_dir_path(); let output_dir = tempdir().expect("couldn't create temporary directory"); let input_path = build_test_path.join(test_name); let output_path = output_dir.path().join(format!("{}.rbxmx", test_name)); - let mut exe_path = working_dir.join("target/debug/rojo"); - if cfg!(windows) { - exe_path.set_extension("exe"); - } + let exe_path = get_rojo_path(); let status = Command::new(exe_path) .args(&[ diff --git a/rojo-test/src/lib.rs b/rojo-test/src/lib.rs index d7961940..8e0cd9b6 100644 --- a/rojo-test/src/lib.rs +++ b/rojo-test/src/lib.rs @@ -1,2 +1,7 @@ +mod util; + #[cfg(test)] mod build_test; + +#[cfg(test)] +mod serve_test; diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs new file mode 100644 index 00000000..e5b6a9a6 --- /dev/null +++ b/rojo-test/src/serve_test.rs @@ -0,0 +1 @@ +use std::path::Path; \ No newline at end of file diff --git a/rojo-test/src/util.rs b/rojo-test/src/util.rs new file mode 100644 index 00000000..d4df13ea --- /dev/null +++ b/rojo-test/src/util.rs @@ -0,0 +1,28 @@ +use std::path::{Path, PathBuf}; + +pub fn get_rojo_path() -> PathBuf { + let working_dir = get_working_dir_path(); + + let mut exe_path = working_dir.join("target/debug/rojo"); + if cfg!(windows) { + exe_path.set_extension("exe"); + } + + exe_path +} + +pub fn get_working_dir_path() -> PathBuf { + let mut manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + assert!(manifest_dir.pop(), "Manifest directory did not have a parent"); + manifest_dir +} + +pub fn get_build_tests_path() -> PathBuf { + let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + manifest_dir.join("build-tests") +} + +pub fn get_serve_tests_path() -> PathBuf { + let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + manifest_dir.join("serve-tests") +} \ No newline at end of file From f1729163cffca045241cb078963f83d6b5f32f4f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Sep 2019 13:48:27 -0700 Subject: [PATCH 0647/1504] Add foundations for 'rojo serve' tests --- Cargo.lock | 2 + rojo-test/Cargo.toml | 4 +- .../placeholder/default.project.json | 9 ++++ rojo-test/src/build_test.rs | 5 ++- rojo-test/src/lib.rs | 6 +-- rojo-test/src/serve_test.rs | 42 ++++++++++++++++++- rojo-test/src/util.rs | 7 +++- 7 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 rojo-test/serve-tests/placeholder/default.project.json diff --git a/Cargo.lock b/Cargo.lock index 18471fba..13ac387b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1572,7 +1572,9 @@ dependencies = [ name = "rojo-test" version = "0.1.0" dependencies = [ + "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", "rojo 0.5.0", diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index fdda8754..d8a95026 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -10,6 +10,8 @@ insta = "0.10.0" paste = "0.1.5" tempfile = "3.1.0" reqwest = "0.9.20" +env_logger = "0.6.2" +log = "0.4.8" # We execute Rojo via std::process::Command, so depend on it so it's built! -rojo = { path = ".." } \ No newline at end of file +rojo = { path = ".." } diff --git a/rojo-test/serve-tests/placeholder/default.project.json b/rojo-test/serve-tests/placeholder/default.project.json new file mode 100644 index 00000000..01868e2a --- /dev/null +++ b/rojo-test/serve-tests/placeholder/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "placeholder", + "tree": { + "$className": "StringValue", + "$properties": { + "Value": "Hello, world!" + } + } +} \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index fcfa7a3f..1cb3bfca 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -11,6 +11,7 @@ macro_rules! gen_build_tests { paste::item! { #[test] fn []() { + let _ = env_logger::try_init(); run_build_test(stringify!($test_name)); } } @@ -54,9 +55,9 @@ fn run_build_test(test_name: &str) { let build_test_path = get_build_tests_path(); let working_dir = get_working_dir_path(); - let output_dir = tempdir().expect("couldn't create temporary directory"); - let input_path = build_test_path.join(test_name); + + let output_dir = tempdir().expect("couldn't create temporary directory"); let output_path = output_dir.path().join(format!("{}.rbxmx", test_name)); let exe_path = get_rojo_path(); diff --git a/rojo-test/src/lib.rs b/rojo-test/src/lib.rs index 8e0cd9b6..786d9410 100644 --- a/rojo-test/src/lib.rs +++ b/rojo-test/src/lib.rs @@ -1,7 +1,5 @@ -mod util; +#![cfg(test)] -#[cfg(test)] mod build_test; - -#[cfg(test)] mod serve_test; +mod util; diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index e5b6a9a6..82a089c9 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -1 +1,41 @@ -use std::path::Path; \ No newline at end of file +use std::process::Command; + +use crate::util::{get_rojo_path, get_serve_tests_path, get_working_dir_path}; + +#[test] +fn serve_test() { + let _ = env_logger::try_init(); + + let serve_test_path = get_serve_tests_path(); + let working_dir = get_working_dir_path(); + + let input_path = serve_test_path.join("placeholder"); + + let exe_path = get_rojo_path(); + + let mut handle = Command::new(exe_path) + .args(&["serve", input_path.to_str().unwrap(), "--port", "35103"]) + .current_dir(working_dir) + .spawn() + .expect("Couldn't start Rojo"); + + loop { + let mut response = match reqwest::get("http://localhost:35103/api/rojo") { + Ok(res) => res, + Err(err) => { + log::info!("Server error, retrying: {}", err); + std::thread::sleep(std::time::Duration::from_millis(30)); + continue; + } + }; + + let text = response.text().expect("Couldn't get response text"); + + log::info!("Got response body: {}", text); + break; + } + + handle + .kill() + .expect("Rojo server was not running at end of test"); +} diff --git a/rojo-test/src/util.rs b/rojo-test/src/util.rs index d4df13ea..5835010d 100644 --- a/rojo-test/src/util.rs +++ b/rojo-test/src/util.rs @@ -13,7 +13,10 @@ pub fn get_rojo_path() -> PathBuf { pub fn get_working_dir_path() -> PathBuf { let mut manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); - assert!(manifest_dir.pop(), "Manifest directory did not have a parent"); + assert!( + manifest_dir.pop(), + "Manifest directory did not have a parent" + ); manifest_dir } @@ -25,4 +28,4 @@ pub fn get_build_tests_path() -> PathBuf { pub fn get_serve_tests_path() -> PathBuf { let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); manifest_dir.join("serve-tests") -} \ No newline at end of file +} From a31bfbefa74007dab9a34335bb808ef2a43965a9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Sep 2019 13:57:28 -0700 Subject: [PATCH 0648/1504] Start extracting web interface from implementation --- src/lib.rs | 2 +- src/web/api.rs | 58 ++++++-------------------------------------- src/web/interface.rs | 3 +-- src/web/mod.rs | 1 + src/web/util.rs | 20 +++++++++++++++ src/web_interface.rs | 37 ++++++++++++++++++++++++++++ 6 files changed, 68 insertions(+), 53 deletions(-) create mode 100644 src/web/util.rs create mode 100644 src/web_interface.rs diff --git a/src/lib.rs b/src/lib.rs index a99f9114..9c4ba3f1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,8 +4,8 @@ #[macro_use] mod impl_from; -// Other modules pub mod commands; +pub mod web_interface; // This module is only public for the purpose of testing right now, and won't be // part of the first version of the Rojo API. diff --git a/src/web/api.rs b/src/web/api.rs index f8bede16..d14a0020 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -1,62 +1,20 @@ //! Defines Rojo's HTTP API, all under /api. These endpoints generally return //! JSON. -use std::{collections::HashSet, sync::Arc}; +use std::sync::Arc; use futures::{future, Future}; use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; use rbx_dom_weak::RbxId; -use serde::{Deserialize, Serialize}; -use crate::{serve_session::ServeSession, session_id::SessionId}; - -const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); -const PROTOCOL_VERSION: u64 = 3; - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ServerInfoResponse<'a> { - pub session_id: SessionId, - pub server_version: &'a str, - pub protocol_version: u64, - pub expected_place_ids: Option>, - // pub root_instance_id: RbxId, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct ReadResponse { - pub session_id: SessionId, - // pub message_cursor: u32, - // pub instances: HashMap>, -} - -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct SubscribeResponse { - pub session_id: SessionId, - // pub message_cursor: u32, - // pub messages: Cow<'a, [InstanceChanges]>, -} - -fn response_json(value: T) -> Response { - let serialized = match serde_json::to_string(&value) { - Ok(v) => v, - Err(err) => { - return Response::builder() - .status(StatusCode::INTERNAL_SERVER_ERROR) - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from(err.to_string())) - .unwrap(); - } - }; - - Response::builder() - .header(header::CONTENT_TYPE, "application/json") - .body(Body::from(serialized)) - .unwrap() -} +use crate::{ + serve_session::ServeSession, + web::util::response_json, + web_interface::{ + ReadResponse, ServerInfoResponse, SubscribeResponse, PROTOCOL_VERSION, SERVER_VERSION, + }, +}; pub struct ApiService { serve_session: Arc, diff --git a/src/web/interface.rs b/src/web/interface.rs index 3fbf18b4..9db7c109 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -6,9 +6,8 @@ use futures::{future, Future}; use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; use ritz::html; -use crate::serve_session::ServeSession; +use crate::{serve_session::ServeSession, web_interface::SERVER_VERSION}; -const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); static HOME_CSS: &str = include_str!("../../assets/index.css"); pub struct InterfaceService { diff --git a/src/web/mod.rs b/src/web/mod.rs index a5d116fc..b1be8f7f 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -1,5 +1,6 @@ mod api; mod interface; +mod util; use std::sync::Arc; diff --git a/src/web/util.rs b/src/web/util.rs new file mode 100644 index 00000000..32581c38 --- /dev/null +++ b/src/web/util.rs @@ -0,0 +1,20 @@ +use hyper::{header::CONTENT_TYPE, Body, Response, StatusCode}; +use serde::Serialize; + +pub fn response_json(value: T) -> Response { + let serialized = match serde_json::to_string(&value) { + Ok(v) => v, + Err(err) => { + return Response::builder() + .status(StatusCode::INTERNAL_SERVER_ERROR) + .header(CONTENT_TYPE, "text/plain") + .body(Body::from(err.to_string())) + .unwrap(); + } + }; + + Response::builder() + .header(CONTENT_TYPE, "application/json") + .body(Body::from(serialized)) + .unwrap() +} diff --git a/src/web_interface.rs b/src/web_interface.rs new file mode 100644 index 00000000..3f40b425 --- /dev/null +++ b/src/web_interface.rs @@ -0,0 +1,37 @@ +//! Defines all the structs needed to interact with the Rojo API from an +//! automation test perspective. + +use std::collections::HashSet; + +use serde::{Deserialize, Serialize}; + +use crate::session_id::SessionId; + +pub const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); +pub const PROTOCOL_VERSION: u64 = 3; + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ServerInfoResponse<'a> { + pub session_id: SessionId, + pub server_version: &'a str, + pub protocol_version: u64, + pub expected_place_ids: Option>, + // pub root_instance_id: RbxId, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct ReadResponse { + pub session_id: SessionId, + // pub message_cursor: u32, + // pub instances: HashMap>, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct SubscribeResponse { + pub session_id: SessionId, + // pub message_cursor: u32, + // pub messages: Cow<'a, [InstanceChanges]>, +} From 27517e1aee9ef05bf3b9f879fec7c90bfd3e61ad Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Sep 2019 13:58:44 -0700 Subject: [PATCH 0649/1504] Rename web::interface to web::ui --- src/web/mod.rs | 12 ++++++------ src/web/{interface.rs => ui.rs} | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) rename src/web/{interface.rs => ui.rs} (93%) diff --git a/src/web/mod.rs b/src/web/mod.rs index b1be8f7f..613c2d94 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -1,5 +1,5 @@ mod api; -mod interface; +mod ui; mod util; use std::sync::Arc; @@ -13,11 +13,11 @@ use log::trace; use crate::serve_session::ServeSession; -use self::{api::ApiService, interface::InterfaceService}; +use self::{api::ApiService, ui::UiService}; pub struct RootService { - api: api::ApiService, - interface: interface::InterfaceService, + api: ApiService, + ui: UiService, } impl Service for RootService { @@ -32,7 +32,7 @@ impl Service for RootService { if request.uri().path().starts_with("/api") { self.api.call(request) } else { - self.interface.call(request) + self.ui.call(request) } } } @@ -41,7 +41,7 @@ impl RootService { pub fn new(serve_session: Arc) -> RootService { RootService { api: ApiService::new(Arc::clone(&serve_session)), - interface: InterfaceService::new(Arc::clone(&serve_session)), + ui: UiService::new(Arc::clone(&serve_session)), } } } diff --git a/src/web/interface.rs b/src/web/ui.rs similarity index 93% rename from src/web/interface.rs rename to src/web/ui.rs index 9db7c109..03d0a69f 100644 --- a/src/web/interface.rs +++ b/src/web/ui.rs @@ -10,12 +10,12 @@ use crate::{serve_session::ServeSession, web_interface::SERVER_VERSION}; static HOME_CSS: &str = include_str!("../../assets/index.css"); -pub struct InterfaceService { +pub struct UiService { #[allow(unused)] // TODO: Fill out interface service serve_session: Arc, } -impl Service for InterfaceService { +impl Service for UiService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; @@ -36,9 +36,9 @@ impl Service for InterfaceService { } } -impl InterfaceService { - pub fn new(serve_session: Arc) -> InterfaceService { - InterfaceService { serve_session } +impl UiService { + pub fn new(serve_session: Arc) -> UiService { + UiService { serve_session } } fn handle_home(&self) -> Response { From 27839dfd21b55745d868505063b47b43f26f2f0a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Sep 2019 14:00:31 -0700 Subject: [PATCH 0650/1504] Shuffle web_interface into web::interface --- src/lib.rs | 1 - src/web/api.rs | 8 +++++--- src/{web_interface.rs => web/interface.rs} | 0 src/web/mod.rs | 1 + src/web/ui.rs | 2 +- 5 files changed, 7 insertions(+), 5 deletions(-) rename src/{web_interface.rs => web/interface.rs} (100%) diff --git a/src/lib.rs b/src/lib.rs index 9c4ba3f1..f596b463 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,6 @@ mod impl_from; pub mod commands; -pub mod web_interface; // This module is only public for the purpose of testing right now, and won't be // part of the first version of the Rojo API. diff --git a/src/web/api.rs b/src/web/api.rs index d14a0020..7f95e9aa 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -10,9 +10,11 @@ use rbx_dom_weak::RbxId; use crate::{ serve_session::ServeSession, - web::util::response_json, - web_interface::{ - ReadResponse, ServerInfoResponse, SubscribeResponse, PROTOCOL_VERSION, SERVER_VERSION, + web::{ + interface::{ + ReadResponse, ServerInfoResponse, SubscribeResponse, PROTOCOL_VERSION, SERVER_VERSION, + }, + util::response_json, }, }; diff --git a/src/web_interface.rs b/src/web/interface.rs similarity index 100% rename from src/web_interface.rs rename to src/web/interface.rs diff --git a/src/web/mod.rs b/src/web/mod.rs index 613c2d94..df4c0127 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -1,4 +1,5 @@ mod api; +mod interface; mod ui; mod util; diff --git a/src/web/ui.rs b/src/web/ui.rs index 03d0a69f..01471839 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -6,7 +6,7 @@ use futures::{future, Future}; use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; use ritz::html; -use crate::{serve_session::ServeSession, web_interface::SERVER_VERSION}; +use crate::{serve_session::ServeSession, web::interface::SERVER_VERSION}; static HOME_CSS: &str = include_str!("../../assets/index.css"); From cf5f20bbb5f59cad7e3083b1e7f572a54ee07c2a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Sep 2019 14:09:35 -0700 Subject: [PATCH 0651/1504] Upgrade depdendencies, removing need for opt-level in debug --- Cargo.lock | 16 ++++++++-------- Cargo.toml | 3 --- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 13ac387b..cb12c08a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -850,7 +850,7 @@ name = "mime" version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -859,7 +859,7 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1414,7 +1414,7 @@ dependencies = [ [[package]] name = "rbx_reflection" -version = "3.2.395" +version = "3.2.399" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1431,7 +1431,7 @@ dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.2.395 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.2.399 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1555,7 +1555,7 @@ dependencies = [ "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.2.395 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.2.399 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2034,7 +2034,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicase" -version = "2.4.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2426,7 +2426,7 @@ dependencies = [ "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81428c521a07a3feac9c31180a886e467eecf81b769987f70d51d567a09c321d" "checksum rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb8079fe850096bd18582a8661f5d7a6afee61bc914691be2f287050f3ac0ec4" -"checksum rbx_reflection 3.2.395 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b43ccce9c29e9f1774359cb96b6ea0c1b897d416dc00f5b45cf54866ca7997" +"checksum rbx_reflection 3.2.399 (registry+https://github.com/rust-lang/crates.io-index)" = "13df0adaeaad56d905fecfef8a4c4d6ec31a7e2afaa6e900fef7a5b5ec337813" "checksum rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0236363b0af0c78f3e972ac7f46a1f355f663518e276253136d0180f3c8742c" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" @@ -2487,7 +2487,7 @@ dependencies = [ "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" -"checksum unicase 2.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a84e5511b2a947f3ae965dcb29b13b7b1691b6e7332cf5dbc1744138d5acb7f6" +"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" "checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" diff --git a/Cargo.toml b/Cargo.toml index 9c1a5e93..5af52018 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,9 +17,6 @@ members = [ "rojo-test", ] -[profile.dev] -opt-level = 1 - [lib] name = "librojo" path = "src/lib.rs" From d5c816f24dd65f873e83a9d98d4da6fd5a2f38d4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Sep 2019 14:20:12 -0700 Subject: [PATCH 0652/1504] Document and expose public members for Rojo API --- src/lib.rs | 8 ++++++-- src/session_id.rs | 4 ++++ src/web/interface.rs | 11 ++++++++--- src/web/mod.rs | 2 +- 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f596b463..805c7890 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,12 +1,13 @@ +// Recursion limit bump is to support Ritz, a JSX-like proc macro used for +// Rojo's web UI currently. #![recursion_limit = "128"] -// Macros #[macro_use] mod impl_from; pub mod commands; -// This module is only public for the purpose of testing right now, and won't be +// This module is only public for testing right now, and won't be // part of the first version of the Rojo API. #[doc(hidden)] pub mod project; @@ -21,3 +22,6 @@ mod session_id; mod snapshot; mod snapshot_middleware; mod web; + +pub use crate::session_id::SessionId; +pub use crate::web::interface as web_interface; diff --git a/src/session_id.rs b/src/session_id.rs index e025de1b..51596ba0 100644 --- a/src/session_id.rs +++ b/src/session_id.rs @@ -1,6 +1,10 @@ use serde::{Deserialize, Serialize}; use uuid::Uuid; +/// A randomly generated ID generated by Rojo during a serve session. +/// +/// If the session ID of the server changes between requests, that indicates +/// that a new server has started up and the session should be terminated. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)] pub struct SessionId(Uuid); diff --git a/src/web/interface.rs b/src/web/interface.rs index 3f40b425..c1420275 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -1,5 +1,4 @@ -//! Defines all the structs needed to interact with the Rojo API from an -//! automation test perspective. +//! Defines all the structs needed to interact with the Rojo Serve API. use std::collections::HashSet; @@ -7,9 +6,13 @@ use serde::{Deserialize, Serialize}; use crate::session_id::SessionId; -pub const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); +/// Server version to report over the API, not exposed outside this crate. +pub(crate) const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); + +/// Current protocol version, which is required to match. pub const PROTOCOL_VERSION: u64 = 3; +/// Response body from /api/rojo #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ServerInfoResponse<'a> { @@ -20,6 +23,7 @@ pub struct ServerInfoResponse<'a> { // pub root_instance_id: RbxId, } +/// Response body from /api/read/{id} #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ReadResponse { @@ -28,6 +32,7 @@ pub struct ReadResponse { // pub instances: HashMap>, } +/// Response body from /api/subscribe/{cursor} #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SubscribeResponse { diff --git a/src/web/mod.rs b/src/web/mod.rs index df4c0127..05d55746 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -1,5 +1,5 @@ mod api; -mod interface; +pub mod interface; mod ui; mod util; From ea765eb92984b766d23712fe2eadaa72b09a8d13 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Sep 2019 17:56:23 -0700 Subject: [PATCH 0653/1504] Add serve snapshot test for empty project --- Cargo.lock | 176 +----------------- rojo-test/Cargo.toml | 14 +- .../serve-tests/empty/default.project.json | 6 + .../placeholder/default.project.json | 9 - rojo-test/src/build_test.rs | 4 +- rojo-test/src/serve_test.rs | 124 +++++++++--- .../src/snapshots/serve_test__empty.snap | 8 + rojo-test/src/util.rs | 42 ++++- src/web/api.rs | 2 +- src/web/interface.rs | 4 +- 10 files changed, 176 insertions(+), 213 deletions(-) create mode 100644 rojo-test/serve-tests/empty/default.project.json delete mode 100644 rojo-test/serve-tests/placeholder/default.project.json create mode 100644 rojo-test/src/snapshots/serve_test__empty.snap diff --git a/Cargo.lock b/Cargo.lock index cb12c08a..2ed22933 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -106,11 +106,6 @@ dependencies = [ "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bumpalo" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "byte-tools" version = "0.3.1" @@ -167,25 +162,6 @@ name = "cfg-if" version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "chrono" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "js-sys 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ci_info" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "clap" version = "2.33.0" @@ -221,15 +197,13 @@ dependencies = [ [[package]] name = "console" -version = "0.7.7" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -696,18 +670,14 @@ dependencies = [ [[package]] name = "insta" -version = "0.10.1" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "chrono 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ci_info 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)", + "console 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -733,14 +703,6 @@ name = "jod-thread" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "js-sys" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "wasm-bindgen 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "kernel32-sys" version = "0.2.2" @@ -779,14 +741,6 @@ dependencies = [ "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "lock_api" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "log" version = "0.4.8" @@ -959,23 +913,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "num-integer" -version = "0.1.41" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "num-traits" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "num_cpus" version = "1.10.1" @@ -1044,16 +981,6 @@ dependencies = [ "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot_core" version = "0.4.0" @@ -1066,20 +993,6 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parking_lot_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "paste" version = "0.1.6" @@ -1573,22 +1486,15 @@ name = "rojo-test" version = "0.1.0" dependencies = [ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "insta 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", "rojo 0.5.0", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "ron" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2140,55 +2046,6 @@ name = "wasi" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "wasm-bindgen" -version = "0.2.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-backend" -version = "0.2.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-macro" -version = "0.2.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro-support 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-macro-support" -version = "0.2.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "wasm-bindgen-shared" -version = "0.2.50" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi" version = "0.2.8" @@ -2279,7 +2136,6 @@ dependencies = [ "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" "checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" -"checksum bumpalo 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ad807f2fc2bf185eeb98ff3a901bd46dc5ad58163d0fa4577ba0d25674d71708" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" @@ -2288,12 +2144,10 @@ dependencies = [ "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" "checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" -"checksum chrono 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "27429a03ca54100bf6bdc726c09adc46a74187ac93f9ce96dc7aaa9594ebf707" -"checksum ci_info 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e5e881307a989a3a5e20d52a32cc05950e3c2178cccfcc9428271a6cde09f902" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ca57c2c14b8a2bf3105bc9d15574aad80babf6a9c44b1058034cdf8bd169628" +"checksum console 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147390a412132d75d10dd3b7b175a69cf5fd95032f7503c7091b8831ba10242" "checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" "checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" @@ -2346,18 +2200,16 @@ dependencies = [ "checksum indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4d6d89e0948bf10c08b9ecc8ac5b83f07f857ebe2c0cbe38de15b4e4f510356" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" -"checksum insta 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "fcb8917b02e8fee27da19291be792fa53acec68ea0b7a45a914dcb80a67d42ab" +"checksum insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23f83ab4ee86f38b292f0420c27fd412690a4baa9ea0ad4e3fa624bf34379b76" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f52a11f73b88fab829a0e4d9e13ea5982c7ac457c72eb3541d82a4afdfce4ff" -"checksum js-sys 0.3.27 (registry+https://github.com/rust-lang/crates.io-index)" = "1efc4f2a556c58e79c5500912e221dd826bec64ff4aabd8ce71ccef6da02d7d4" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" -"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" @@ -2376,8 +2228,6 @@ dependencies = [ "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1191efa2b8fe041decb55c238a125b7a1aeb6fad7a525133a02be5ec949ff3cb" -"checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09" -"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)" = "8152bb5a9b5b721538462336e3bef9a539f892715e5037fda0f984577311af15" @@ -2386,9 +2236,7 @@ dependencies = [ "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" "checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" -"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" "checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" @@ -2437,7 +2285,6 @@ dependencies = [ "checksum reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)" = "0f6d896143a583047512e59ac54a215cb203c29cc941917343edea3be8df9c78" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" -"checksum ron 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "17f52a24414403f81528b67488cf8edc4eda977d3af1646bb6b106a600ead78f" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" @@ -2502,11 +2349,6 @@ dependencies = [ "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" "checksum wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd5442abcac6525a045cc8c795aedb60da7a2e5e89c7bf18a0d5357849bb23c7" -"checksum wasm-bindgen 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "dcddca308b16cd93c2b67b126c688e5467e4ef2e28200dc7dfe4ae284f2faefc" -"checksum wasm-bindgen-backend 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "f805d9328b5fc7e5c6399960fd1889271b9b58ae17bdb2417472156cc9fafdd0" -"checksum wasm-bindgen-macro 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "3ff88201a482abfc63921621f6cb18eb1efd74f136b05e5841e7f8ca434539e9" -"checksum wasm-bindgen-macro-support 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "6a433d89ecdb9f77d46fcf00c8cf9f3467b7de9954d8710c175f61e2e245bb0e" -"checksum wasm-bindgen-shared 0.2.50 (registry+https://github.com/rust-lang/crates.io-index)" = "d41fc1bc3570cdf8d108c15e014045fd45a95bb5eb36605f96a90461fc34027d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index d8a95026..3c55212c 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -6,12 +6,18 @@ edition = "2018" publish = false [dependencies] -insta = "0.10.0" -paste = "0.1.5" -tempfile = "3.1.0" -reqwest = "0.9.20" env_logger = "0.6.2" log = "0.4.8" +paste = "0.1.5" +reqwest = "0.9.20" +serde = "1.0.99" +serde_json = "1.0.40" +tempfile = "3.1.0" +walkdir = "2.2.9" # We execute Rojo via std::process::Command, so depend on it so it's built! rojo = { path = ".." } + +[dependencies.insta] +version = "0.11.0" +features = ["redactions"] diff --git a/rojo-test/serve-tests/empty/default.project.json b/rojo-test/serve-tests/empty/default.project.json new file mode 100644 index 00000000..f7cd2015 --- /dev/null +++ b/rojo-test/serve-tests/empty/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "empty", + "tree": { + "$className": "Folder" + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/placeholder/default.project.json b/rojo-test/serve-tests/placeholder/default.project.json deleted file mode 100644 index 01868e2a..00000000 --- a/rojo-test/serve-tests/placeholder/default.project.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "placeholder", - "tree": { - "$className": "StringValue", - "$properties": { - "Value": "Hello, world!" - } - } -} \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index 1cb3bfca..02bee494 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -1,6 +1,6 @@ use std::{fs, process::Command}; -use insta::assert_snapshot_matches; +use insta::assert_snapshot; use tempfile::tempdir; use crate::util::{get_build_tests_path, get_rojo_path, get_working_dir_path}; @@ -78,5 +78,5 @@ fn run_build_test(test_name: &str) { let contents = fs::read_to_string(&output_path).expect("Couldn't read output file"); - assert_snapshot_matches!(test_name, contents); + assert_snapshot!(test_name, contents); } diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index 82a089c9..e7855e5d 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -1,41 +1,111 @@ -use std::process::Command; +use std::{ + fs, + path::PathBuf, + process::Command, + sync::atomic::{AtomicUsize, Ordering}, +}; -use crate::util::{get_rojo_path, get_serve_tests_path, get_working_dir_path}; +use insta::assert_yaml_snapshot; +use tempfile::{tempdir, TempDir}; + +use librojo::web_interface::ServerInfoResponse; + +use crate::util::{ + copy_recursive, get_rojo_path, get_serve_tests_path, get_working_dir_path, KillOnDrop, +}; #[test] -fn serve_test() { +fn empty() { let _ = env_logger::try_init(); - let serve_test_path = get_serve_tests_path(); - let working_dir = get_working_dir_path(); + let mut session = TestServeSession::new("empty"); + let info = session.wait_to_come_online(); - let input_path = serve_test_path.join("placeholder"); + assert_yaml_snapshot!(info, { + ".sessionId" => "[session id]" + }); +} - let exe_path = get_rojo_path(); +fn get_port_number() -> usize { + static NEXT_PORT_NUMBER: AtomicUsize = AtomicUsize::new(35103); - let mut handle = Command::new(exe_path) - .args(&["serve", input_path.to_str().unwrap(), "--port", "35103"]) - .current_dir(working_dir) - .spawn() - .expect("Couldn't start Rojo"); + NEXT_PORT_NUMBER.fetch_add(1, Ordering::SeqCst) +} - loop { - let mut response = match reqwest::get("http://localhost:35103/api/rojo") { - Ok(res) => res, - Err(err) => { - log::info!("Server error, retrying: {}", err); - std::thread::sleep(std::time::Duration::from_millis(30)); - continue; - } - }; +struct TestServeSession { + // Drop order is important here: we want the process to be killed before the + // directory it's operating on is destroyed. + rojo_process: KillOnDrop, + _dir: TempDir, - let text = response.text().expect("Couldn't get response text"); + port: usize, + project_path: PathBuf, +} - log::info!("Got response body: {}", text); - break; +impl TestServeSession { + pub fn new(name: &str) -> Self { + let serve_test_path = get_serve_tests_path(); + let working_dir = get_working_dir_path(); + let exe_path = get_rojo_path(); + + let source_path = serve_test_path.join(name); + let dir = tempdir().expect("Couldn't create temporary directory"); + let project_path = dir.path().join(name); + + fs::create_dir(&project_path).expect("Couldn't create temporary project subdirectory"); + + copy_recursive(&source_path, &project_path) + .expect("Couldn't copy project to temporary directory"); + + let port = get_port_number(); + let port_string = port.to_string(); + + let rojo_process = Command::new(exe_path) + .args(&[ + "serve", + project_path.to_str().unwrap(), + "--port", + port_string.as_str(), + ]) + .current_dir(working_dir) + .spawn() + .expect("Couldn't start Rojo"); + + TestServeSession { + rojo_process: KillOnDrop(rojo_process), + _dir: dir, + port, + project_path, + } } - handle - .kill() - .expect("Rojo server was not running at end of test"); + pub fn wait_to_come_online(&mut self) -> ServerInfoResponse { + loop { + match self.rojo_process.0.try_wait() { + Ok(Some(status)) => panic!("Rojo process exited with status {}", status), + Ok(None) => { /* process is still running */ } + Err(err) => panic!("Failed to wait on Rojo process: {}", err), + } + + let info = match self.get_api_rojo() { + Ok(info) => info, + Err(err) => { + log::debug!("Server error, retrying: {}", err); + std::thread::sleep(std::time::Duration::from_millis(30)); + continue; + } + }; + + log::info!("Got session info: {:?}", info); + + return info; + } + } + + pub fn get_api_rojo(&self) -> Result { + let info_url = format!("http://localhost:{}/api/rojo", self.port); + let body = reqwest::get(&info_url)?.text()?; + + Ok(serde_json::from_str(&body).expect("Server returned malformed response")) + } } diff --git a/rojo-test/src/snapshots/serve_test__empty.snap b/rojo-test/src/snapshots/serve_test__empty.snap new file mode 100644 index 00000000..e768d5fa --- /dev/null +++ b/rojo-test/src/snapshots/serve_test__empty.snap @@ -0,0 +1,8 @@ +--- +source: rojo-test/src/serve_test.rs +expression: info +--- +sessionId: "[session id]" +serverVersion: 0.5.0 +protocolVersion: 3 +expectedPlaceIds: ~ diff --git a/rojo-test/src/util.rs b/rojo-test/src/util.rs index 5835010d..e0b59f87 100644 --- a/rojo-test/src/util.rs +++ b/rojo-test/src/util.rs @@ -1,4 +1,10 @@ -use std::path::{Path, PathBuf}; +use std::{ + fs, io, + path::{Path, PathBuf}, + process::Child, +}; + +use walkdir::WalkDir; pub fn get_rojo_path() -> PathBuf { let working_dir = get_working_dir_path(); @@ -29,3 +35,37 @@ pub fn get_serve_tests_path() -> PathBuf { let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); manifest_dir.join("serve-tests") } + +/// Recursively walk a directory and copy each item to the equivalent location +/// in another directory. Equivalent to `cp -r src/* dst` +pub fn copy_recursive(from: &Path, to: &Path) -> io::Result<()> { + for entry in WalkDir::new(from) { + let entry = entry?; + let path = entry.path(); + let new_path = to.join(path.strip_prefix(from).unwrap()); + + let file_type = entry.file_type(); + + if file_type.is_dir() { + match fs::create_dir(new_path) { + Ok(_) => {} + Err(err) => match err.kind() { + io::ErrorKind::AlreadyExists => {} + _ => panic!(err), + }, + } + } else { + fs::copy(path, new_path)?; + } + } + + Ok(()) +} + +pub struct KillOnDrop(pub Child); + +impl Drop for KillOnDrop { + fn drop(&mut self) { + let _ = self.0.kill(); + } +} diff --git a/src/web/api.rs b/src/web/api.rs index 7f95e9aa..759b3ea9 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -54,7 +54,7 @@ impl ApiService { /// Get a summary of information about the server fn handle_api_rojo(&self) -> Response { response_json(&ServerInfoResponse { - server_version: SERVER_VERSION, + server_version: SERVER_VERSION.to_owned(), protocol_version: PROTOCOL_VERSION, session_id: self.serve_session.session_id(), expected_place_ids: self.serve_session.serve_place_ids().map(Clone::clone), diff --git a/src/web/interface.rs b/src/web/interface.rs index c1420275..1ed2bd94 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -15,9 +15,9 @@ pub const PROTOCOL_VERSION: u64 = 3; /// Response body from /api/rojo #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ServerInfoResponse<'a> { +pub struct ServerInfoResponse { pub session_id: SessionId, - pub server_version: &'a str, + pub server_version: String, pub protocol_version: u64, pub expected_place_ids: Option>, // pub root_instance_id: RbxId, From 93832406271bcba6f177b1ebeb57eb24f072c407 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Sep 2019 18:11:28 -0700 Subject: [PATCH 0654/1504] Move rojo-test snapshots into partitioned folders --- .../build_test__client_in_folder.snap | 0 .../build_test__client_init.snap | 0 .../build_test__csv_bug_145.snap | 0 .../build_test__csv_bug_147.snap | 0 .../build_test__csv_in_folder.snap | 0 .../build_test__deep_nesting.snap | 0 .../build_test__gitkeep.snap | 0 .../build_test__init_with_children.snap | 0 .../build_test__json_model_in_folder.snap | 0 .../build_test__json_model_legacy_name.snap | 0 .../build_test__module_in_folder.snap | 0 .../build_test__module_init.snap | 2 +- .../build_test__plain.txt.snap | 0 .../build_test__plain_gitkeep.snap | 0 .../build_test__rbxm_in_folder.snap | 0 .../build_test__rbxmx_in_folder.snap | 2 +- .../build_test__rbxmx_ref.rbxmx.snap | 0 .../build_test__server_in_folder.snap | 0 .../build_test__server_init.snap | 0 .../build_test__txt.snap | 0 .../build_test__txt_in_folder.snap | 0 .../serve_test__empty.snap | 0 rojo-test/src/build_test.rs | 12 ++++++++++-- rojo-test/src/serve_test.rs | 17 ++++++++++++----- 24 files changed, 24 insertions(+), 9 deletions(-) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__client_in_folder.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__client_init.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__csv_bug_145.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__csv_bug_147.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__csv_in_folder.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__deep_nesting.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__gitkeep.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__init_with_children.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__json_model_in_folder.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__json_model_legacy_name.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__module_in_folder.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__module_init.snap (97%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__plain.txt.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__plain_gitkeep.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__rbxm_in_folder.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__rbxmx_in_folder.snap (99%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__rbxmx_ref.rbxmx.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__server_in_folder.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__server_init.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__txt.snap (100%) rename rojo-test/{src/snapshots => build-test-snapshots}/build_test__txt_in_folder.snap (100%) rename rojo-test/{src/snapshots => serve-test-snapshots}/serve_test__empty.snap (100%) diff --git a/rojo-test/src/snapshots/build_test__client_in_folder.snap b/rojo-test/build-test-snapshots/build_test__client_in_folder.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__client_in_folder.snap rename to rojo-test/build-test-snapshots/build_test__client_in_folder.snap diff --git a/rojo-test/src/snapshots/build_test__client_init.snap b/rojo-test/build-test-snapshots/build_test__client_init.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__client_init.snap rename to rojo-test/build-test-snapshots/build_test__client_init.snap diff --git a/rojo-test/src/snapshots/build_test__csv_bug_145.snap b/rojo-test/build-test-snapshots/build_test__csv_bug_145.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__csv_bug_145.snap rename to rojo-test/build-test-snapshots/build_test__csv_bug_145.snap diff --git a/rojo-test/src/snapshots/build_test__csv_bug_147.snap b/rojo-test/build-test-snapshots/build_test__csv_bug_147.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__csv_bug_147.snap rename to rojo-test/build-test-snapshots/build_test__csv_bug_147.snap diff --git a/rojo-test/src/snapshots/build_test__csv_in_folder.snap b/rojo-test/build-test-snapshots/build_test__csv_in_folder.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__csv_in_folder.snap rename to rojo-test/build-test-snapshots/build_test__csv_in_folder.snap diff --git a/rojo-test/src/snapshots/build_test__deep_nesting.snap b/rojo-test/build-test-snapshots/build_test__deep_nesting.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__deep_nesting.snap rename to rojo-test/build-test-snapshots/build_test__deep_nesting.snap diff --git a/rojo-test/src/snapshots/build_test__gitkeep.snap b/rojo-test/build-test-snapshots/build_test__gitkeep.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__gitkeep.snap rename to rojo-test/build-test-snapshots/build_test__gitkeep.snap diff --git a/rojo-test/src/snapshots/build_test__init_with_children.snap b/rojo-test/build-test-snapshots/build_test__init_with_children.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__init_with_children.snap rename to rojo-test/build-test-snapshots/build_test__init_with_children.snap diff --git a/rojo-test/src/snapshots/build_test__json_model_in_folder.snap b/rojo-test/build-test-snapshots/build_test__json_model_in_folder.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__json_model_in_folder.snap rename to rojo-test/build-test-snapshots/build_test__json_model_in_folder.snap diff --git a/rojo-test/src/snapshots/build_test__json_model_legacy_name.snap b/rojo-test/build-test-snapshots/build_test__json_model_legacy_name.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__json_model_legacy_name.snap rename to rojo-test/build-test-snapshots/build_test__json_model_legacy_name.snap diff --git a/rojo-test/src/snapshots/build_test__module_in_folder.snap b/rojo-test/build-test-snapshots/build_test__module_in_folder.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__module_in_folder.snap rename to rojo-test/build-test-snapshots/build_test__module_in_folder.snap diff --git a/rojo-test/src/snapshots/build_test__module_init.snap b/rojo-test/build-test-snapshots/build_test__module_init.snap similarity index 97% rename from rojo-test/src/snapshots/build_test__module_init.snap rename to rojo-test/build-test-snapshots/build_test__module_init.snap index ce0c3533..e0110640 100644 --- a/rojo-test/src/snapshots/build_test__module_init.snap +++ b/rojo-test/build-test-snapshots/build_test__module_init.snap @@ -11,4 +11,4 @@ expression: contents return "From folder/init.lua"
-
+
\ No newline at end of file diff --git a/rojo-test/src/snapshots/build_test__plain.txt.snap b/rojo-test/build-test-snapshots/build_test__plain.txt.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__plain.txt.snap rename to rojo-test/build-test-snapshots/build_test__plain.txt.snap diff --git a/rojo-test/src/snapshots/build_test__plain_gitkeep.snap b/rojo-test/build-test-snapshots/build_test__plain_gitkeep.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__plain_gitkeep.snap rename to rojo-test/build-test-snapshots/build_test__plain_gitkeep.snap diff --git a/rojo-test/src/snapshots/build_test__rbxm_in_folder.snap b/rojo-test/build-test-snapshots/build_test__rbxm_in_folder.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__rbxm_in_folder.snap rename to rojo-test/build-test-snapshots/build_test__rbxm_in_folder.snap diff --git a/rojo-test/src/snapshots/build_test__rbxmx_in_folder.snap b/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap similarity index 99% rename from rojo-test/src/snapshots/build_test__rbxmx_in_folder.snap rename to rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap index 831fba35..c54f6329 100644 --- a/rojo-test/src/snapshots/build_test__rbxmx_in_folder.snap +++ b/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap @@ -38,4 +38,4 @@ expression: contents - + \ No newline at end of file diff --git a/rojo-test/src/snapshots/build_test__rbxmx_ref.rbxmx.snap b/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__rbxmx_ref.rbxmx.snap rename to rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap diff --git a/rojo-test/src/snapshots/build_test__server_in_folder.snap b/rojo-test/build-test-snapshots/build_test__server_in_folder.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__server_in_folder.snap rename to rojo-test/build-test-snapshots/build_test__server_in_folder.snap diff --git a/rojo-test/src/snapshots/build_test__server_init.snap b/rojo-test/build-test-snapshots/build_test__server_init.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__server_init.snap rename to rojo-test/build-test-snapshots/build_test__server_init.snap diff --git a/rojo-test/src/snapshots/build_test__txt.snap b/rojo-test/build-test-snapshots/build_test__txt.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__txt.snap rename to rojo-test/build-test-snapshots/build_test__txt.snap diff --git a/rojo-test/src/snapshots/build_test__txt_in_folder.snap b/rojo-test/build-test-snapshots/build_test__txt_in_folder.snap similarity index 100% rename from rojo-test/src/snapshots/build_test__txt_in_folder.snap rename to rojo-test/build-test-snapshots/build_test__txt_in_folder.snap diff --git a/rojo-test/src/snapshots/serve_test__empty.snap b/rojo-test/serve-test-snapshots/serve_test__empty.snap similarity index 100% rename from rojo-test/src/snapshots/serve_test__empty.snap rename to rojo-test/serve-test-snapshots/serve_test__empty.snap diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index 02bee494..341af7af 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -1,4 +1,4 @@ -use std::{fs, process::Command}; +use std::{fs, path::Path, process::Command}; use insta::assert_snapshot; use tempfile::tempdir; @@ -12,6 +12,7 @@ macro_rules! gen_build_tests { #[test] fn []() { let _ = env_logger::try_init(); + run_build_test(stringify!($test_name)); } } @@ -78,5 +79,12 @@ fn run_build_test(test_name: &str) { let contents = fs::read_to_string(&output_path).expect("Couldn't read output file"); - assert_snapshot!(test_name, contents); + let mut settings = insta::Settings::new(); + + let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("build-test-snapshots"); + settings.set_snapshot_path(snapshot_path); + + settings.bind(|| { + assert_snapshot!(test_name, contents); + }); } diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index e7855e5d..392d6f9f 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -1,6 +1,6 @@ use std::{ fs, - path::PathBuf, + path::{Path, PathBuf}, process::Command, sync::atomic::{AtomicUsize, Ordering}, }; @@ -18,11 +18,18 @@ use crate::util::{ fn empty() { let _ = env_logger::try_init(); - let mut session = TestServeSession::new("empty"); - let info = session.wait_to_come_online(); + let mut settings = insta::Settings::new(); - assert_yaml_snapshot!(info, { - ".sessionId" => "[session id]" + let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("serve-test-snapshots"); + settings.set_snapshot_path(snapshot_path); + + settings.bind(|| { + let mut session = TestServeSession::new("empty"); + let info = session.wait_to_come_online(); + + assert_yaml_snapshot!(info, { + ".sessionId" => "[session id]" + }); }); } From 439a1a758ea879406b468ec26c198906b145f8bd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Sep 2019 18:15:53 -0700 Subject: [PATCH 0655/1504] Upgrade all snapshots to insta 0.11.0 format --- .../build-test-snapshots/build_test__client_in_folder.snap | 2 -- rojo-test/build-test-snapshots/build_test__client_init.snap | 2 -- rojo-test/build-test-snapshots/build_test__csv_bug_145.snap | 4 +--- rojo-test/build-test-snapshots/build_test__csv_bug_147.snap | 4 +--- rojo-test/build-test-snapshots/build_test__csv_in_folder.snap | 2 -- rojo-test/build-test-snapshots/build_test__deep_nesting.snap | 2 -- rojo-test/build-test-snapshots/build_test__gitkeep.snap | 2 -- .../build-test-snapshots/build_test__init_with_children.snap | 2 -- .../build_test__json_model_in_folder.snap | 2 -- .../build_test__json_model_legacy_name.snap | 2 -- .../build-test-snapshots/build_test__module_in_folder.snap | 2 -- rojo-test/build-test-snapshots/build_test__module_init.snap | 4 +--- rojo-test/build-test-snapshots/build_test__plain.txt.snap | 2 -- rojo-test/build-test-snapshots/build_test__plain_gitkeep.snap | 2 -- .../build-test-snapshots/build_test__rbxm_in_folder.snap | 2 -- .../build-test-snapshots/build_test__rbxmx_in_folder.snap | 4 +--- .../build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap | 4 +--- .../build-test-snapshots/build_test__server_in_folder.snap | 2 -- rojo-test/build-test-snapshots/build_test__server_init.snap | 2 -- rojo-test/build-test-snapshots/build_test__txt.snap | 2 -- rojo-test/build-test-snapshots/build_test__txt_in_folder.snap | 2 -- 21 files changed, 5 insertions(+), 47 deletions(-) diff --git a/rojo-test/build-test-snapshots/build_test__client_in_folder.snap b/rojo-test/build-test-snapshots/build_test__client_in_folder.snap index d43e50c2..27695545 100644 --- a/rojo-test/build-test-snapshots/build_test__client_in_folder.snap +++ b/rojo-test/build-test-snapshots/build_test__client_in_folder.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-09T01:29:47.650277200Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__client_init.snap b/rojo-test/build-test-snapshots/build_test__client_init.snap index ce20f536..eacede5a 100644 --- a/rojo-test/build-test-snapshots/build_test__client_init.snap +++ b/rojo-test/build-test-snapshots/build_test__client_init.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-16T19:37:51.277332900Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__csv_bug_145.snap b/rojo-test/build-test-snapshots/build_test__csv_bug_145.snap index 052c049d..48146d39 100644 --- a/rojo-test/build-test-snapshots/build_test__csv_bug_145.snap +++ b/rojo-test/build-test-snapshots/build_test__csv_bug_145.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-14T22:42:52.297447700Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- @@ -16,4 +14,4 @@ expression: contents - \ No newline at end of file + diff --git a/rojo-test/build-test-snapshots/build_test__csv_bug_147.snap b/rojo-test/build-test-snapshots/build_test__csv_bug_147.snap index 023ff8da..defea874 100644 --- a/rojo-test/build-test-snapshots/build_test__csv_bug_147.snap +++ b/rojo-test/build-test-snapshots/build_test__csv_bug_147.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-14T22:42:52.310414Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- @@ -16,4 +14,4 @@ expression: contents - \ No newline at end of file + diff --git a/rojo-test/build-test-snapshots/build_test__csv_in_folder.snap b/rojo-test/build-test-snapshots/build_test__csv_in_folder.snap index e6c5fb15..3917a988 100644 --- a/rojo-test/build-test-snapshots/build_test__csv_in_folder.snap +++ b/rojo-test/build-test-snapshots/build_test__csv_in_folder.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-14T22:34:06.206495600Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__deep_nesting.snap b/rojo-test/build-test-snapshots/build_test__deep_nesting.snap index 23b0227d..9e4dc471 100644 --- a/rojo-test/build-test-snapshots/build_test__deep_nesting.snap +++ b/rojo-test/build-test-snapshots/build_test__deep_nesting.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-29T23:38:13.072820400Z" -creator: insta@0.10.1 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__gitkeep.snap b/rojo-test/build-test-snapshots/build_test__gitkeep.snap index 5db8bcd0..fe025fc9 100644 --- a/rojo-test/build-test-snapshots/build_test__gitkeep.snap +++ b/rojo-test/build-test-snapshots/build_test__gitkeep.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-08T00:48:33.382271800Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__init_with_children.snap b/rojo-test/build-test-snapshots/build_test__init_with_children.snap index f35e6e2f..98f2f030 100644 --- a/rojo-test/build-test-snapshots/build_test__init_with_children.snap +++ b/rojo-test/build-test-snapshots/build_test__init_with_children.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-30T00:12:56.686707700Z" -creator: insta@0.10.1 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__json_model_in_folder.snap b/rojo-test/build-test-snapshots/build_test__json_model_in_folder.snap index f6242974..67013a05 100644 --- a/rojo-test/build-test-snapshots/build_test__json_model_in_folder.snap +++ b/rojo-test/build-test-snapshots/build_test__json_model_in_folder.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-15T20:40:50.467761900Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__json_model_legacy_name.snap b/rojo-test/build-test-snapshots/build_test__json_model_legacy_name.snap index adf985c7..0a0b7fba 100644 --- a/rojo-test/build-test-snapshots/build_test__json_model_legacy_name.snap +++ b/rojo-test/build-test-snapshots/build_test__json_model_legacy_name.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-15T20:41:28.743618200Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__module_in_folder.snap b/rojo-test/build-test-snapshots/build_test__module_in_folder.snap index dd5d9895..6a73f1fd 100644 --- a/rojo-test/build-test-snapshots/build_test__module_in_folder.snap +++ b/rojo-test/build-test-snapshots/build_test__module_in_folder.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-09T01:27:22.597759700Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__module_init.snap b/rojo-test/build-test-snapshots/build_test__module_init.snap index e0110640..e6cd09e3 100644 --- a/rojo-test/build-test-snapshots/build_test__module_init.snap +++ b/rojo-test/build-test-snapshots/build_test__module_init.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-16T19:36:55.442461700Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- @@ -11,4 +9,4 @@ expression: contents return "From folder/init.lua" - \ No newline at end of file + diff --git a/rojo-test/build-test-snapshots/build_test__plain.txt.snap b/rojo-test/build-test-snapshots/build_test__plain.txt.snap index 93316de9..bd9ec616 100644 --- a/rojo-test/build-test-snapshots/build_test__plain.txt.snap +++ b/rojo-test/build-test-snapshots/build_test__plain.txt.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-09T00:17:42.253380600Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__plain_gitkeep.snap b/rojo-test/build-test-snapshots/build_test__plain_gitkeep.snap index 204b47e9..ccf37852 100644 --- a/rojo-test/build-test-snapshots/build_test__plain_gitkeep.snap +++ b/rojo-test/build-test-snapshots/build_test__plain_gitkeep.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-09T00:17:42.175575800Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__rbxm_in_folder.snap b/rojo-test/build-test-snapshots/build_test__rbxm_in_folder.snap index 574500ce..f67a3d9e 100644 --- a/rojo-test/build-test-snapshots/build_test__rbxm_in_folder.snap +++ b/rojo-test/build-test-snapshots/build_test__rbxm_in_folder.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-14T22:05:46.597722600Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap b/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap index c54f6329..4b9740e1 100644 --- a/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap +++ b/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-10T07:45:07.961823500Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- @@ -38,4 +36,4 @@ expression: contents - \ No newline at end of file + diff --git a/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap b/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap index c631c482..9a796330 100644 --- a/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap +++ b/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-10T07:57:42.835269100Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- @@ -25,4 +23,4 @@ expression: contents - \ No newline at end of file + diff --git a/rojo-test/build-test-snapshots/build_test__server_in_folder.snap b/rojo-test/build-test-snapshots/build_test__server_in_folder.snap index 14037d0a..006917b2 100644 --- a/rojo-test/build-test-snapshots/build_test__server_in_folder.snap +++ b/rojo-test/build-test-snapshots/build_test__server_in_folder.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-09T01:29:48.071133300Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__server_init.snap b/rojo-test/build-test-snapshots/build_test__server_init.snap index 8a104912..9aa4fa5e 100644 --- a/rojo-test/build-test-snapshots/build_test__server_init.snap +++ b/rojo-test/build-test-snapshots/build_test__server_init.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-16T19:36:55.442461700Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__txt.snap b/rojo-test/build-test-snapshots/build_test__txt.snap index 4794a928..004b83c1 100644 --- a/rojo-test/build-test-snapshots/build_test__txt.snap +++ b/rojo-test/build-test-snapshots/build_test__txt.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-09T00:22:01.983322Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/build_test__txt_in_folder.snap b/rojo-test/build-test-snapshots/build_test__txt_in_folder.snap index 71292e94..cc6ba42d 100644 --- a/rojo-test/build-test-snapshots/build_test__txt_in_folder.snap +++ b/rojo-test/build-test-snapshots/build_test__txt_in_folder.snap @@ -1,6 +1,4 @@ --- -created: "2019-08-08T00:48:33.502257600Z" -creator: insta@0.10.0 source: rojo-test/src/build_test.rs expression: contents --- From a914a92cea36cf503e8684d28f6260b2b25328a7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 5 Sep 2019 11:27:16 -0700 Subject: [PATCH 0656/1504] Add SnapshotSource property --- src/snapshot/instance_snapshot.rs | 27 ++++++++++++++++++++++++--- src/snapshot/patch_apply.rs | 1 + src/snapshot/patch_compute.rs | 4 ++++ src/snapshot_middleware/csv.rs | 1 + src/snapshot_middleware/dir.rs | 1 + src/snapshot_middleware/json_model.rs | 3 +++ src/snapshot_middleware/lua.rs | 1 + src/snapshot_middleware/project.rs | 1 + src/snapshot_middleware/rbxm.rs | 1 + src/snapshot_middleware/rbxmx.rs | 1 + src/snapshot_middleware/txt.rs | 1 + 11 files changed, 39 insertions(+), 3 deletions(-) diff --git a/src/snapshot/instance_snapshot.rs b/src/snapshot/instance_snapshot.rs index 6adeb5b2..8182ad5f 100644 --- a/src/snapshot/instance_snapshot.rs +++ b/src/snapshot/instance_snapshot.rs @@ -1,25 +1,32 @@ //! Defines the structure of an instance snapshot. -use std::{borrow::Cow, collections::HashMap}; +use std::{borrow::Cow, collections::HashMap, path::PathBuf}; use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; +use crate::project::ProjectNode; + /// A lightweight description of what an instance should look like. Attempts to /// be somewhat memory efficient by borrowing from its source data, indicated by -/// the lifetime parameter, `'source`. +/// the lifetime parameter `'source`. /// // Possible future improvements: // - Use refcounted/interned strings // - Replace use of RbxValue with a sum of RbxValue + borrowed value #[derive(Debug, Clone, PartialEq)] pub struct InstanceSnapshot<'source> { + /// A temporary ID applied to the snapshot that's used for Ref properties. pub snapshot_id: Option, + /// A complete view of where this snapshot came from. It should contain + /// enough information, if not None, to recreate this snapshot + /// deterministically assuming the source has not changed state. + pub source: Option, + pub name: Cow<'source, str>, pub class_name: Cow<'source, str>, pub properties: HashMap, pub children: Vec>, - // TODO: Snapshot source, like a file or a project node? } impl<'source> InstanceSnapshot<'source> { @@ -32,6 +39,7 @@ impl<'source> InstanceSnapshot<'source> { InstanceSnapshot { snapshot_id: None, + source: self.source.clone(), name: Cow::Owned(self.name.clone().into_owned()), class_name: Cow::Owned(self.class_name.clone().into_owned()), properties: self.properties.clone(), @@ -53,6 +61,7 @@ impl<'source> InstanceSnapshot<'source> { InstanceSnapshot { snapshot_id: Some(id), + source: None, name: Cow::Owned(instance.name.clone()), class_name: Cow::Owned(instance.class_name.clone()), properties: instance.properties.clone(), @@ -60,3 +69,15 @@ impl<'source> InstanceSnapshot<'source> { } } } + +#[derive(Debug, Clone, PartialEq)] +pub enum SnapshotSource { + File { + path: PathBuf, + }, + ProjectFile { + path: PathBuf, + name: String, + node: ProjectNode, + }, +} diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index 246fdd02..dfd5c523 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -159,6 +159,7 @@ mod test { let snapshot = InstanceSnapshot { snapshot_id: None, + source: None, name: Cow::Borrowed("Foo"), class_name: Cow::Borrowed("Bar"), properties: hashmap! { diff --git a/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs index 451736ae..83acbed3 100644 --- a/src/snapshot/patch_compute.rs +++ b/src/snapshot/patch_compute.rs @@ -244,6 +244,7 @@ mod test { } }, + source: None, name: Cow::Borrowed("foo"), class_name: Cow::Borrowed("foo"), children: Vec::new(), @@ -294,11 +295,13 @@ mod test { }, snapshot_id: None, + source: None, name: Cow::Borrowed("child"), class_name: Cow::Borrowed("child"), children: Vec::new(), }], + source: None, properties: HashMap::new(), name: Cow::Borrowed("foo"), class_name: Cow::Borrowed("foo"), @@ -311,6 +314,7 @@ mod test { parent_id: root_id, instance: InstanceSnapshot { snapshot_id: None, + source: None, properties: hashmap! { "Self".to_owned() => RbxValue::Ref { value: Some(root_id), diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index fdf532af..4be88d2b 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -39,6 +39,7 @@ impl SnapshotMiddleware for SnapshotCsv { Ok(Some(InstanceSnapshot { snapshot_id: None, + source: None, // TODO name: Cow::Owned(instance_name), class_name: Cow::Borrowed("LocalizationTable"), properties: hashmap! { diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 1d7de937..2d6b60ef 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -43,6 +43,7 @@ impl SnapshotMiddleware for SnapshotDir { Ok(Some(InstanceSnapshot { snapshot_id: None, + source: None, // TODO name: Cow::Owned(instance_name), class_name: Cow::Borrowed("Folder"), properties: HashMap::new(), diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 4d4834f7..ec5148a8 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -120,6 +120,7 @@ impl JsonModelCore { InstanceSnapshot { snapshot_id: None, + source: None, // TODO name: Cow::Owned(name), class_name: Cow::Owned(class_name), properties, @@ -169,6 +170,7 @@ mod test { instance_snapshot, InstanceSnapshot { snapshot_id: None, + source: None, // TODO name: Cow::Borrowed("foo"), class_name: Cow::Borrowed("IntValue"), properties: hashmap! { @@ -178,6 +180,7 @@ mod test { }, children: vec![InstanceSnapshot { snapshot_id: None, + source: None, // TODO name: Cow::Borrowed("The Child"), class_name: Cow::Borrowed("StringValue"), properties: HashMap::new(), diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 8ae12323..0aa61080 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -90,6 +90,7 @@ fn snapshot_lua_file( Ok(Some(InstanceSnapshot { snapshot_id: None, + source: None, // TODO name: Cow::Owned(instance_name.to_owned()), class_name: Cow::Borrowed(class_name), properties, diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index ceaa4d7b..2d431978 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -131,6 +131,7 @@ fn snapshot_project_node( Ok(Some(InstanceSnapshot { snapshot_id: None, + source: None, // TODO name, class_name, properties, diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 156aa052..47e8ab29 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -49,6 +49,7 @@ impl SnapshotMiddleware for SnapshotRbxm { if children.len() == 1 { let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); snapshot.name = Cow::Owned(instance_name); + // TODO: Assign snapshot.source Ok(Some(snapshot)) } else { diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 6cfc9b1a..6d0aa78b 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -45,6 +45,7 @@ impl SnapshotMiddleware for SnapshotRbxmx { if children.len() == 1 { let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); snapshot.name = Cow::Owned(instance_name); + // TODO: Assign snapshot.source Ok(Some(snapshot)) } else { diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 22d7cd83..058ae408 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -51,6 +51,7 @@ impl SnapshotMiddleware for SnapshotTxt { Ok(Some(InstanceSnapshot { snapshot_id: None, + source: None, // TODO name: Cow::Owned(instance_name), class_name: Cow::Borrowed("StringValue"), properties, From 5eb6754b7c002f66305dd269cbb284b03753cfa5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 6 Sep 2019 14:21:47 -0700 Subject: [PATCH 0657/1504] Implement metadata, replacing source field and laying foundations --- src/snapshot/instance_snapshot.rs | 44 +++++---- src/snapshot/metadata.rs | 127 ++++++++++++++++++++++++++ src/snapshot/mod.rs | 2 + src/snapshot/patch.rs | 5 +- src/snapshot/patch_apply.rs | 5 +- src/snapshot/patch_compute.rs | 10 +- src/snapshot_middleware/csv.rs | 2 +- src/snapshot_middleware/dir.rs | 2 +- src/snapshot_middleware/json_model.rs | 6 +- src/snapshot_middleware/lua.rs | 2 +- src/snapshot_middleware/project.rs | 2 +- src/snapshot_middleware/txt.rs | 2 +- 12 files changed, 176 insertions(+), 33 deletions(-) create mode 100644 src/snapshot/metadata.rs diff --git a/src/snapshot/instance_snapshot.rs b/src/snapshot/instance_snapshot.rs index 8182ad5f..83ad5055 100644 --- a/src/snapshot/instance_snapshot.rs +++ b/src/snapshot/instance_snapshot.rs @@ -1,10 +1,10 @@ //! Defines the structure of an instance snapshot. -use std::{borrow::Cow, collections::HashMap, path::PathBuf}; +use std::{borrow::Cow, collections::HashMap}; use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; -use crate::project::ProjectNode; +use super::InstanceMetadata; /// A lightweight description of what an instance should look like. Attempts to /// be somewhat memory efficient by borrowing from its source data, indicated by @@ -18,14 +18,21 @@ pub struct InstanceSnapshot<'source> { /// A temporary ID applied to the snapshot that's used for Ref properties. pub snapshot_id: Option, - /// A complete view of where this snapshot came from. It should contain - /// enough information, if not None, to recreate this snapshot - /// deterministically assuming the source has not changed state. - pub source: Option, + /// Rojo-specific metadata associated with the instance. + pub metadata: InstanceMetadata, + /// Correpsonds to the Name property of the instance. pub name: Cow<'source, str>, + + /// Corresponds to the ClassName property of the instance. pub class_name: Cow<'source, str>, + + /// All other properties of the instance, weakly-typed. pub properties: HashMap, + + /// The children of the instance represented as more snapshots. + /// + /// Order is relevant for Roblox instances! pub children: Vec>, } @@ -39,7 +46,7 @@ impl<'source> InstanceSnapshot<'source> { InstanceSnapshot { snapshot_id: None, - source: self.source.clone(), + metadata: self.metadata.clone(), name: Cow::Owned(self.name.clone().into_owned()), class_name: Cow::Owned(self.class_name.clone().into_owned()), properties: self.properties.clone(), @@ -61,7 +68,7 @@ impl<'source> InstanceSnapshot<'source> { InstanceSnapshot { snapshot_id: Some(id), - source: None, + metadata: InstanceMetadata::default(), name: Cow::Owned(instance.name.clone()), class_name: Cow::Owned(instance.class_name.clone()), properties: instance.properties.clone(), @@ -70,14 +77,15 @@ impl<'source> InstanceSnapshot<'source> { } } -#[derive(Debug, Clone, PartialEq)] -pub enum SnapshotSource { - File { - path: PathBuf, - }, - ProjectFile { - path: PathBuf, - name: String, - node: ProjectNode, - }, +impl<'source> Default for InstanceSnapshot<'source> { + fn default() -> InstanceSnapshot<'source> { + InstanceSnapshot { + snapshot_id: None, + metadata: InstanceMetadata::default(), + name: Cow::Borrowed("DEFAULT"), + class_name: Cow::Borrowed("DEFAULT"), + properties: HashMap::new(), + children: Vec::new(), + } + } } diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs new file mode 100644 index 00000000..279e4e81 --- /dev/null +++ b/src/snapshot/metadata.rs @@ -0,0 +1,127 @@ +use std::{collections::HashMap, path::PathBuf}; + +use rbx_dom_weak::{RbxId, RbxInstance, RbxInstanceProperties, RbxTree}; + +use crate::project::ProjectNode; + +/// Rojo-specific metadata that can be associated with an instance or a snapshot +/// of an instance. +#[derive(Debug, Clone, PartialEq)] +pub struct InstanceMetadata { + /// Whether instances not present in the source should be ignored when + /// live-syncing. This is useful when there are instances that Rojo does not + /// manage. + pub ignore_unknown_instances: bool, + + /// A complete view of where this snapshot came from. It should contain + /// enough information, if not None, to recreate this snapshot + /// deterministically assuming the source has not changed state. + pub source: Option, +} + +#[derive(Debug, Clone, PartialEq)] +pub enum InstanceSource { + File { + path: PathBuf, + }, + ProjectFile { + path: PathBuf, + name: String, + node: ProjectNode, + }, +} + +impl Default for InstanceMetadata { + fn default() -> Self { + InstanceMetadata { + ignore_unknown_instances: false, + source: None, + } + } +} + +#[derive(Debug, Clone)] +pub struct InstancePropertiesWithMeta { + pub inner: RbxInstanceProperties, + pub metadata: InstanceMetadata, +} + +#[derive(Debug)] +pub struct InstanceWithMeta<'a> { + pub inner: &'a RbxInstance, + pub metadata: &'a InstanceMetadata, +} + +#[derive(Debug)] +pub struct InstanceWithMetaMut<'a> { + pub inner: &'a mut RbxInstance, + pub metadata: &'a mut InstanceMetadata, +} + +#[derive(Debug)] +pub struct TreeWithMetadata { + inner: RbxTree, + metadata: HashMap, +} + +impl TreeWithMetadata { + pub fn new(root: InstancePropertiesWithMeta) -> TreeWithMetadata { + let inner = RbxTree::new(root.inner); + let mut metadata = HashMap::new(); + metadata.insert(inner.get_root_id(), root.metadata); + + TreeWithMetadata { inner, metadata } + } + + pub fn get_root_id(&self) -> RbxId { + self.inner.get_root_id() + } + + pub fn get_instance(&self, id: RbxId) -> Option { + if let Some(inner) = self.inner.get_instance(id) { + let metadata = self.metadata.get(&id).unwrap(); + + Some(InstanceWithMeta { inner, metadata }) + } else { + None + } + } + + pub fn get_instance_mut(&mut self, id: RbxId) -> Option { + if let Some(inner) = self.inner.get_instance_mut(id) { + let metadata = self.metadata.get_mut(&id).unwrap(); + + Some(InstanceWithMetaMut { inner, metadata }) + } else { + None + } + } + + pub fn insert_instance( + &mut self, + properties: InstancePropertiesWithMeta, + parent_id: RbxId, + ) -> RbxId { + let id = self.inner.insert_instance(properties.inner, parent_id); + self.metadata.insert(id, properties.metadata); + id + } + + pub fn remove_instance(&mut self, id: RbxId) -> Option { + if let Some(inner) = self.inner.remove_instance(id) { + let mut metadata = HashMap::new(); + + let root_meta = self.metadata.remove(&id).unwrap(); + metadata.insert(id, root_meta); + + for instance in inner.descendants(id) { + let instance_meta = self.metadata.remove(&instance.get_id()).unwrap(); + metadata.insert(instance.get_id(), instance_meta); + } + + Some(TreeWithMetadata { inner, metadata }) + } else { + None + } + } +} diff --git a/src/snapshot/mod.rs b/src/snapshot/mod.rs index f6cc3c3f..8b3e1864 100644 --- a/src/snapshot/mod.rs +++ b/src/snapshot/mod.rs @@ -19,11 +19,13 @@ #![allow(dead_code)] mod instance_snapshot; +mod metadata; mod patch; mod patch_apply; mod patch_compute; pub use instance_snapshot::InstanceSnapshot; +pub use metadata::*; pub use patch::*; pub use patch_apply::apply_patch_set; pub use patch_compute::compute_patch_set; diff --git a/src/snapshot/patch.rs b/src/snapshot/patch.rs index 15fdc6ba..c89ed885 100644 --- a/src/snapshot/patch.rs +++ b/src/snapshot/patch.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; use rbx_dom_weak::{RbxId, RbxValue}; -use super::InstanceSnapshot; +use super::{InstanceMetadata, InstanceSnapshot}; /// A set of different kinds of patches that can be applied to an RbxTree. #[derive(Debug, Default, Clone, PartialEq)] @@ -41,4 +41,7 @@ pub struct PatchUpdateInstance { /// Contains all changed properties. If a property is assigned to `None`, /// then that property has been removed. pub changed_properties: HashMap>, + + /// Changed Rojo-specific metadata, if any of it changed. + pub changed_metadata: Option, } diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index dfd5c523..3c52da95 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -143,7 +143,7 @@ mod test { use maplit::hashmap; use rbx_dom_weak::RbxValue; - use super::super::patch::PatchAddInstance; + use super::super::PatchAddInstance; #[test] fn add_from_empty() { @@ -159,7 +159,7 @@ mod test { let snapshot = InstanceSnapshot { snapshot_id: None, - source: None, + metadata: Default::default(), name: Cow::Borrowed("Foo"), class_name: Cow::Borrowed("Bar"), properties: hashmap! { @@ -218,6 +218,7 @@ mod test { // Baz has been added "Baz".to_owned() => Some(RbxValue::Int32 { value: 10 }), }, + changed_metadata: None, }; let patch_set = PatchSet { diff --git a/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs index 83acbed3..a5227c57 100644 --- a/src/snapshot/patch_compute.rs +++ b/src/snapshot/patch_compute.rs @@ -140,6 +140,7 @@ fn compute_property_patches( changed_name, changed_class_name, changed_properties, + changed_metadata: None, }); } @@ -244,7 +245,7 @@ mod test { } }, - source: None, + metadata: Default::default(), name: Cow::Borrowed("foo"), class_name: Cow::Borrowed("foo"), children: Vec::new(), @@ -262,6 +263,7 @@ mod test { value: Some(root_id), }), }, + changed_metadata: None, }], added_instances: Vec::new(), removed_instances: Vec::new(), @@ -295,13 +297,13 @@ mod test { }, snapshot_id: None, - source: None, + metadata: Default::default(), name: Cow::Borrowed("child"), class_name: Cow::Borrowed("child"), children: Vec::new(), }], - source: None, + metadata: Default::default(), properties: HashMap::new(), name: Cow::Borrowed("foo"), class_name: Cow::Borrowed("foo"), @@ -314,7 +316,7 @@ mod test { parent_id: root_id, instance: InstanceSnapshot { snapshot_id: None, - source: None, + metadata: Default::default(), properties: hashmap! { "Self".to_owned() => RbxValue::Ref { value: Some(root_id), diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 4be88d2b..ba647114 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -39,7 +39,7 @@ impl SnapshotMiddleware for SnapshotCsv { Ok(Some(InstanceSnapshot { snapshot_id: None, - source: None, // TODO + metadata: Default::default(), // TODO name: Cow::Owned(instance_name), class_name: Cow::Borrowed("LocalizationTable"), properties: hashmap! { diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 2d6b60ef..36170297 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -43,7 +43,7 @@ impl SnapshotMiddleware for SnapshotDir { Ok(Some(InstanceSnapshot { snapshot_id: None, - source: None, // TODO + metadata: Default::default(), // TODO name: Cow::Owned(instance_name), class_name: Cow::Borrowed("Folder"), properties: HashMap::new(), diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index ec5148a8..8420372e 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -120,7 +120,7 @@ impl JsonModelCore { InstanceSnapshot { snapshot_id: None, - source: None, // TODO + metadata: Default::default(), // TODO name: Cow::Owned(name), class_name: Cow::Owned(class_name), properties, @@ -170,7 +170,7 @@ mod test { instance_snapshot, InstanceSnapshot { snapshot_id: None, - source: None, // TODO + metadata: Default::default(), // TODO name: Cow::Borrowed("foo"), class_name: Cow::Borrowed("IntValue"), properties: hashmap! { @@ -180,7 +180,7 @@ mod test { }, children: vec![InstanceSnapshot { snapshot_id: None, - source: None, // TODO + metadata: Default::default(), // TODO name: Cow::Borrowed("The Child"), class_name: Cow::Borrowed("StringValue"), properties: HashMap::new(), diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 0aa61080..91b5d77d 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -90,7 +90,7 @@ fn snapshot_lua_file( Ok(Some(InstanceSnapshot { snapshot_id: None, - source: None, // TODO + metadata: Default::default(), // TODO name: Cow::Owned(instance_name.to_owned()), class_name: Cow::Borrowed(class_name), properties, diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 2d431978..471a91d8 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -131,7 +131,7 @@ fn snapshot_project_node( Ok(Some(InstanceSnapshot { snapshot_id: None, - source: None, // TODO + metadata: Default::default(), // TODO name, class_name, properties, diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 058ae408..98155c10 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -51,7 +51,7 @@ impl SnapshotMiddleware for SnapshotTxt { Ok(Some(InstanceSnapshot { snapshot_id: None, - source: None, // TODO + metadata: Default::default(), // TODO name: Cow::Owned(instance_name), class_name: Cow::Borrowed("StringValue"), properties, From 8dbc6ab7d39ec9cc9e34fce0c03de22b3e5404b1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 6 Sep 2019 17:05:01 -0700 Subject: [PATCH 0658/1504] Start MapSet work --- src/lib.rs | 1 + src/mapset.rs | 69 ++++++++++++++++++++++ src/snapshot/metadata.rs | 90 +---------------------------- src/snapshot/mod.rs | 2 + src/snapshot/tree.rs | 120 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 193 insertions(+), 89 deletions(-) create mode 100644 src/mapset.rs create mode 100644 src/snapshot/tree.rs diff --git a/src/lib.rs b/src/lib.rs index 805c7890..6e64cb1f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,6 +14,7 @@ pub mod project; mod auth_cookie; mod imfs; +mod mapset; mod message_queue; mod path_map; mod path_serializer; diff --git a/src/mapset.rs b/src/mapset.rs new file mode 100644 index 00000000..aeaf4ebd --- /dev/null +++ b/src/mapset.rs @@ -0,0 +1,69 @@ +use std::{ + borrow::Borrow, + collections::HashMap, + fmt::{self, Debug}, + hash::Hash, +}; + +/// A map whose value contains a set of multiple values. +#[derive(Clone)] +pub struct MapSet { + inner: HashMap>, +} + +#[allow(dead_code)] // This is a core library-ish struct, unused stuff is ok +impl MapSet { + pub fn new() -> Self { + MapSet { + inner: HashMap::new(), + } + } + + pub fn get>(&mut self, k: Q) -> &[V] { + self.inner.get(k.borrow()).map(Vec::as_slice).unwrap_or(&[]) + } + + pub fn insert(&mut self, k: K, v: V) { + let bucket = self.inner.entry(k).or_default(); + + for value in &*bucket { + if &*value == &v { + return; + } + } + + bucket.push(v); + } + + pub fn remove, U: Borrow>(&mut self, k: Q, v: U) -> Option { + let b = v.borrow(); + + if let Some(bucket) = self.inner.get_mut(k.borrow()) { + let mut removed_value = None; + + if let Some(index) = bucket.iter().position(|value| value == b) { + removed_value = Some(bucket.swap_remove(index)); + } + + if bucket.len() == 0 { + self.inner.remove(k.borrow()); + } + + removed_value + } else { + None + } + } +} + +impl Debug for MapSet { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + self.inner.fmt(formatter) + } +} + +impl PartialEq for MapSet { + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner + } +} diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index 279e4e81..678b1e9c 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -1,6 +1,4 @@ -use std::{collections::HashMap, path::PathBuf}; - -use rbx_dom_weak::{RbxId, RbxInstance, RbxInstanceProperties, RbxTree}; +use std::path::PathBuf; use crate::project::ProjectNode; @@ -39,89 +37,3 @@ impl Default for InstanceMetadata { } } } - -#[derive(Debug, Clone)] -pub struct InstancePropertiesWithMeta { - pub inner: RbxInstanceProperties, - pub metadata: InstanceMetadata, -} - -#[derive(Debug)] -pub struct InstanceWithMeta<'a> { - pub inner: &'a RbxInstance, - pub metadata: &'a InstanceMetadata, -} - -#[derive(Debug)] -pub struct InstanceWithMetaMut<'a> { - pub inner: &'a mut RbxInstance, - pub metadata: &'a mut InstanceMetadata, -} - -#[derive(Debug)] -pub struct TreeWithMetadata { - inner: RbxTree, - metadata: HashMap, -} - -impl TreeWithMetadata { - pub fn new(root: InstancePropertiesWithMeta) -> TreeWithMetadata { - let inner = RbxTree::new(root.inner); - let mut metadata = HashMap::new(); - metadata.insert(inner.get_root_id(), root.metadata); - - TreeWithMetadata { inner, metadata } - } - - pub fn get_root_id(&self) -> RbxId { - self.inner.get_root_id() - } - - pub fn get_instance(&self, id: RbxId) -> Option { - if let Some(inner) = self.inner.get_instance(id) { - let metadata = self.metadata.get(&id).unwrap(); - - Some(InstanceWithMeta { inner, metadata }) - } else { - None - } - } - - pub fn get_instance_mut(&mut self, id: RbxId) -> Option { - if let Some(inner) = self.inner.get_instance_mut(id) { - let metadata = self.metadata.get_mut(&id).unwrap(); - - Some(InstanceWithMetaMut { inner, metadata }) - } else { - None - } - } - - pub fn insert_instance( - &mut self, - properties: InstancePropertiesWithMeta, - parent_id: RbxId, - ) -> RbxId { - let id = self.inner.insert_instance(properties.inner, parent_id); - self.metadata.insert(id, properties.metadata); - id - } - - pub fn remove_instance(&mut self, id: RbxId) -> Option { - if let Some(inner) = self.inner.remove_instance(id) { - let mut metadata = HashMap::new(); - - let root_meta = self.metadata.remove(&id).unwrap(); - metadata.insert(id, root_meta); - - for instance in inner.descendants(id) { - let instance_meta = self.metadata.remove(&instance.get_id()).unwrap(); - metadata.insert(instance.get_id(), instance_meta); - } - - Some(TreeWithMetadata { inner, metadata }) - } else { - None - } - } -} diff --git a/src/snapshot/mod.rs b/src/snapshot/mod.rs index 8b3e1864..08cb6b31 100644 --- a/src/snapshot/mod.rs +++ b/src/snapshot/mod.rs @@ -23,9 +23,11 @@ mod metadata; mod patch; mod patch_apply; mod patch_compute; +mod tree; pub use instance_snapshot::InstanceSnapshot; pub use metadata::*; pub use patch::*; pub use patch_apply::apply_patch_set; pub use patch_compute::compute_patch_set; +pub use tree::*; diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs new file mode 100644 index 00000000..c21bb4ef --- /dev/null +++ b/src/snapshot/tree.rs @@ -0,0 +1,120 @@ +use std::{collections::HashMap, path::PathBuf}; + +use rbx_dom_weak::{RbxId, RbxInstance, RbxInstanceProperties, RbxTree}; + +use crate::mapset::MapSet; + +use super::InstanceMetadata; + +/// An expanded variant of rbx_dom_weak's `RbxTree` that tracks additional +/// metadata per instance that's Rojo-specific. +/// +/// This tree is also optimized for doing fast incremental updates and patches. +#[derive(Debug)] +pub struct RojoTree { + /// Contains the instances without their Rojo-specific metadata. + inner: RbxTree, + + /// Metadata associated with each instance that is kept up-to-date with the + /// set of actual instances. + metadata: HashMap, + + /// A multimap from source paths to all of the root instances that were + /// constructed from that path. + /// + /// Descendants of those instances should not be contained in the set, the + /// value portion of the map is also a set in order to support the same path + /// appearing multiple times in the same Rojo project. This is sometimes + /// called "path aliasing" in various Rojo documentation. + path_to_id: MapSet, +} + +impl RojoTree { + pub fn new(root: InstancePropertiesWithMeta) -> RojoTree { + let inner = RbxTree::new(root.inner); + let mut metadata = HashMap::new(); + metadata.insert(inner.get_root_id(), root.metadata); + + RojoTree { + inner, + metadata, + path_to_id: MapSet::new(), + } + } + + pub fn get_root_id(&self) -> RbxId { + self.inner.get_root_id() + } + + pub fn get_instance(&self, id: RbxId) -> Option { + if let Some(inner) = self.inner.get_instance(id) { + let metadata = self.metadata.get(&id).unwrap(); + + Some(InstanceWithMeta { inner, metadata }) + } else { + None + } + } + + pub fn get_instance_mut(&mut self, id: RbxId) -> Option { + if let Some(inner) = self.inner.get_instance_mut(id) { + let metadata = self.metadata.get_mut(&id).unwrap(); + + Some(InstanceWithMetaMut { inner, metadata }) + } else { + None + } + } + + pub fn insert_instance( + &mut self, + properties: InstancePropertiesWithMeta, + parent_id: RbxId, + ) -> RbxId { + let id = self.inner.insert_instance(properties.inner, parent_id); + self.metadata.insert(id, properties.metadata); + id + } + + pub fn remove_instance(&mut self, id: RbxId) -> Option { + if let Some(inner) = self.inner.remove_instance(id) { + let mut metadata = HashMap::new(); + let mut path_to_id = MapSet::new(); // TODO + + let root_meta = self.metadata.remove(&id).unwrap(); + + metadata.insert(id, root_meta); + + for instance in inner.descendants(id) { + let instance_meta = self.metadata.remove(&instance.get_id()).unwrap(); + metadata.insert(instance.get_id(), instance_meta); + } + + Some(RojoTree { + inner, + metadata, + path_to_id, + }) + } else { + None + } + } +} + +#[derive(Debug, Clone)] +pub struct InstancePropertiesWithMeta { + pub inner: RbxInstanceProperties, + pub metadata: InstanceMetadata, +} + +#[derive(Debug)] +pub struct InstanceWithMeta<'a> { + pub inner: &'a RbxInstance, + pub metadata: &'a InstanceMetadata, +} + +#[derive(Debug)] +pub struct InstanceWithMetaMut<'a> { + pub inner: &'a mut RbxInstance, + pub metadata: &'a mut InstanceMetadata, +} From 618185a52d0f3d96da72d4315e17df1b84640130 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 9 Sep 2019 11:50:58 -0700 Subject: [PATCH 0659/1504] Start using multimap correctly for path tracking in RojoTree --- src/lib.rs | 2 +- src/{mapset.rs => multimap.rs} | 10 ++--- src/snapshot/metadata.rs | 18 +++------ src/snapshot/tree.rs | 69 ++++++++++++++++++++++------------ 4 files changed, 57 insertions(+), 42 deletions(-) rename src/{mapset.rs => multimap.rs} (87%) diff --git a/src/lib.rs b/src/lib.rs index 6e64cb1f..1c7603ef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,8 +14,8 @@ pub mod project; mod auth_cookie; mod imfs; -mod mapset; mod message_queue; +mod multimap; mod path_map; mod path_serializer; mod serve_session; diff --git a/src/mapset.rs b/src/multimap.rs similarity index 87% rename from src/mapset.rs rename to src/multimap.rs index aeaf4ebd..f3047234 100644 --- a/src/mapset.rs +++ b/src/multimap.rs @@ -7,14 +7,14 @@ use std::{ /// A map whose value contains a set of multiple values. #[derive(Clone)] -pub struct MapSet { +pub struct MultiMap { inner: HashMap>, } #[allow(dead_code)] // This is a core library-ish struct, unused stuff is ok -impl MapSet { +impl MultiMap { pub fn new() -> Self { - MapSet { + MultiMap { inner: HashMap::new(), } } @@ -56,13 +56,13 @@ impl MapSet { } } -impl Debug for MapSet { +impl Debug for MultiMap { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { self.inner.fmt(formatter) } } -impl PartialEq for MapSet { +impl PartialEq for MultiMap { fn eq(&self, other: &Self) -> bool { self.inner == other.inner } diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index 678b1e9c..c231746a 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -17,18 +17,6 @@ pub struct InstanceMetadata { pub source: Option, } -#[derive(Debug, Clone, PartialEq)] -pub enum InstanceSource { - File { - path: PathBuf, - }, - ProjectFile { - path: PathBuf, - name: String, - node: ProjectNode, - }, -} - impl Default for InstanceMetadata { fn default() -> Self { InstanceMetadata { @@ -37,3 +25,9 @@ impl Default for InstanceMetadata { } } } + +#[derive(Debug, Clone, PartialEq)] +pub struct InstanceSource { + pub path: PathBuf, + pub project_node: Option<(String, ProjectNode)>, +} diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index c21bb4ef..3df2e3dc 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, path::PathBuf}; use rbx_dom_weak::{RbxId, RbxInstance, RbxInstanceProperties, RbxTree}; -use crate::mapset::MapSet; +use crate::multimap::MultiMap; use super::InstanceMetadata; @@ -17,7 +17,7 @@ pub struct RojoTree { /// Metadata associated with each instance that is kept up-to-date with the /// set of actual instances. - metadata: HashMap, + metadata_map: HashMap, /// A multimap from source paths to all of the root instances that were /// constructed from that path. @@ -26,20 +26,19 @@ pub struct RojoTree { /// value portion of the map is also a set in order to support the same path /// appearing multiple times in the same Rojo project. This is sometimes /// called "path aliasing" in various Rojo documentation. - path_to_id: MapSet, + path_to_ids: MultiMap, } impl RojoTree { pub fn new(root: InstancePropertiesWithMeta) -> RojoTree { - let inner = RbxTree::new(root.inner); - let mut metadata = HashMap::new(); - metadata.insert(inner.get_root_id(), root.metadata); + let mut tree = RojoTree { + inner: RbxTree::new(root.inner), + metadata_map: HashMap::new(), + path_to_ids: MultiMap::new(), + }; - RojoTree { - inner, - metadata, - path_to_id: MapSet::new(), - } + tree.insert_metadata(tree.inner.get_root_id(), root.metadata); + tree } pub fn get_root_id(&self) -> RbxId { @@ -48,7 +47,7 @@ impl RojoTree { pub fn get_instance(&self, id: RbxId) -> Option { if let Some(inner) = self.inner.get_instance(id) { - let metadata = self.metadata.get(&id).unwrap(); + let metadata = self.metadata_map.get(&id).unwrap(); Some(InstanceWithMeta { inner, metadata }) } else { @@ -58,7 +57,7 @@ impl RojoTree { pub fn get_instance_mut(&mut self, id: RbxId) -> Option { if let Some(inner) = self.inner.get_instance_mut(id) { - let metadata = self.metadata.get_mut(&id).unwrap(); + let metadata = self.metadata_map.get_mut(&id).unwrap(); Some(InstanceWithMetaMut { inner, metadata }) } else { @@ -72,33 +71,55 @@ impl RojoTree { parent_id: RbxId, ) -> RbxId { let id = self.inner.insert_instance(properties.inner, parent_id); - self.metadata.insert(id, properties.metadata); + self.insert_metadata(id, properties.metadata); id } pub fn remove_instance(&mut self, id: RbxId) -> Option { if let Some(inner) = self.inner.remove_instance(id) { - let mut metadata = HashMap::new(); - let mut path_to_id = MapSet::new(); // TODO - - let root_meta = self.metadata.remove(&id).unwrap(); - - metadata.insert(id, root_meta); + let mut metadata_map = HashMap::new(); + let mut path_to_ids = MultiMap::new(); + self.move_metadata(id, &mut metadata_map, &mut path_to_ids); for instance in inner.descendants(id) { - let instance_meta = self.metadata.remove(&instance.get_id()).unwrap(); - metadata.insert(instance.get_id(), instance_meta); + self.move_metadata(instance.get_id(), &mut metadata_map, &mut path_to_ids); } Some(RojoTree { inner, - metadata, - path_to_id, + metadata_map, + path_to_ids, }) } else { None } } + + fn insert_metadata(&mut self, id: RbxId, metadata: InstanceMetadata) { + if let Some(source) = &metadata.source { + self.path_to_ids.insert(source.path.clone(), id); + } + + self.metadata_map.insert(id, metadata); + } + + /// Moves the Rojo metadata from the instance with the given ID from this + /// tree into some loose maps. + fn move_metadata( + &mut self, + id: RbxId, + metadata_map: &mut HashMap, + path_to_ids: &mut MultiMap, + ) { + let metadata = self.metadata_map.remove(&id).unwrap(); + + if let Some(source) = &metadata.source { + self.path_to_ids.remove(&source.path, id); + path_to_ids.insert(source.path.clone(), id); + } + + metadata_map.insert(id, metadata); + } } #[derive(Debug, Clone)] From 824b984a64cef6054a92bc60e766ef8e42afbd13 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 9 Sep 2019 13:50:39 -0700 Subject: [PATCH 0660/1504] First pass converting snapshot code over to RojoTree from RbxTree --- src/commands/build.rs | 37 ++++++++++----- src/commands/serve.rs | 15 +++--- src/commands/upload.rs | 17 ++++--- src/snapshot/patch_apply.rs | 89 ++++++++++++++++++++--------------- src/snapshot/patch_compute.rs | 42 ++++++++++------- src/snapshot/tree.rs | 31 ++++++++---- 6 files changed, 143 insertions(+), 88 deletions(-) diff --git a/src/commands/build.rs b/src/commands/build.rs index 453b42f6..5b745111 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -6,11 +6,11 @@ use std::{ }; use failure::Fail; -use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; +use rbx_dom_weak::RbxInstanceProperties; use crate::{ imfs::new::{FsError, Imfs, RealFetcher, WatchMode}, - snapshot::{apply_patch_set, compute_patch_set}, + snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, snapshot_middleware::snapshot_from_imfs, }; @@ -78,10 +78,13 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { log::info!("Hoping to generate file of type {:?}", output_kind); - let mut tree = RbxTree::new(RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), + let mut tree = RojoTree::new(InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "ROOT".to_owned(), + class_name: "Folder".to_owned(), + properties: HashMap::new(), + }, + metadata: Default::default(), }); let root_id = tree.get_root_id(); @@ -112,25 +115,35 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { // Model files include the root instance of the tree and all its // descendants. - rbx_xml::to_writer(&mut file, &tree, &[root_id], xml_encode_config())?; + rbx_xml::to_writer(&mut file, tree.inner(), &[root_id], xml_encode_config())?; } OutputKind::Rbxlx => { // Place files don't contain an entry for the DataModel, but our // RbxTree representation does. - let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); - rbx_xml::to_writer(&mut file, &tree, top_level_ids, xml_encode_config())?; + let top_level_ids = tree + .get_instance(root_id) + .unwrap() + .instance + .get_children_ids(); + + rbx_xml::to_writer(&mut file, tree.inner(), top_level_ids, xml_encode_config())?; } OutputKind::Rbxm => { - rbx_binary::encode(&tree, &[root_id], &mut file)?; + rbx_binary::encode(tree.inner(), &[root_id], &mut file)?; } OutputKind::Rbxl => { log::warn!("Support for building binary places (rbxl) is still experimental."); log::warn!("Using the XML place format (rbxlx) is recommended instead."); log::warn!("For more info, see https://github.com/LPGhatguy/rojo/issues/180"); - let top_level_ids = tree.get_instance(root_id).unwrap().get_children_ids(); - rbx_binary::encode(&tree, top_level_ids, &mut file)?; + let top_level_ids = tree + .get_instance(root_id) + .unwrap() + .instance + .get_children_ids(); + + rbx_binary::encode(tree.inner(), top_level_ids, &mut file)?; } } diff --git a/src/commands/serve.rs b/src/commands/serve.rs index ac2dab5a..9d6c89d5 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -1,13 +1,13 @@ use std::{collections::HashMap, path::PathBuf, sync::Arc}; use failure::Fail; -use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; +use rbx_dom_weak::RbxInstanceProperties; use crate::{ imfs::new::{Imfs, RealFetcher, WatchMode}, project::{Project, ProjectLoadError}, serve_session::ServeSession, - snapshot::{apply_patch_set, compute_patch_set}, + snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, snapshot_middleware::snapshot_from_imfs, web::LiveServer, }; @@ -48,10 +48,13 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { println!("Rojo server listening on port {}", port); - let mut tree = RbxTree::new(RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), + let mut tree = RojoTree::new(InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "ROOT".to_owned(), + class_name: "Folder".to_owned(), + properties: HashMap::new(), + }, + metadata: Default::default(), }); let root_id = tree.get_root_id(); diff --git a/src/commands/upload.rs b/src/commands/upload.rs index 166f293b..5909e202 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -1,13 +1,13 @@ use std::{collections::HashMap, path::PathBuf}; use failure::Fail; -use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; +use rbx_dom_weak::RbxInstanceProperties; use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}; use crate::{ auth_cookie::get_auth_cookie, imfs::new::{Imfs, RealFetcher, WatchMode}, - snapshot::{apply_patch_set, compute_patch_set}, + snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, snapshot_middleware::snapshot_from_imfs, }; @@ -45,10 +45,13 @@ pub fn upload(options: UploadOptions) -> Result<(), UploadError> { .or_else(get_auth_cookie) .ok_or(UploadError::NeedAuthCookie)?; - let mut tree = RbxTree::new(RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), + let mut tree = RojoTree::new(InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "ROOT".to_owned(), + class_name: "Folder".to_owned(), + properties: HashMap::new(), + }, + metadata: Default::default(), }); let root_id = tree.get_root_id(); @@ -77,7 +80,7 @@ pub fn upload(options: UploadOptions) -> Result<(), UploadError> { let config = rbx_xml::EncodeOptions::new() .property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown); - rbx_xml::to_writer(&mut buffer, &tree, &[root_id], config)?; + rbx_xml::to_writer(&mut buffer, tree.inner(), &[root_id], config)?; let url = format!( "https://data.roblox.com/Data/Upload.ashx?assetid={}", diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index 3c52da95..ed97940c 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -2,14 +2,14 @@ use std::collections::HashMap; -use rbx_dom_weak::{RbxId, RbxInstanceProperties, RbxTree, RbxValue}; +use rbx_dom_weak::{RbxId, RbxInstanceProperties, RbxValue}; use super::{ patch::{PatchSet, PatchUpdateInstance}, - InstanceSnapshot, + InstancePropertiesWithMeta, InstanceSnapshot, RojoTree, }; -pub fn apply_patch_set(tree: &mut RbxTree, patch_set: &PatchSet) { +pub fn apply_patch_set(tree: &mut RojoTree, patch_set: &PatchSet) { let mut context = PatchApplyContext::default(); for removed_id in &patch_set.removed_instances { @@ -42,7 +42,7 @@ struct PatchApplyContext { /// The remaining Ref properties need to be handled during patch application, /// where we build up a map of snapshot IDs to instance IDs as they're created, /// then apply properties all at once at the end. -fn apply_deferred_properties(context: PatchApplyContext, tree: &mut RbxTree) { +fn apply_deferred_properties(context: PatchApplyContext, tree: &mut RojoTree) { for (id, mut properties) in context.properties_to_apply { let instance = tree .get_instance_mut(id) @@ -58,23 +58,26 @@ fn apply_deferred_properties(context: PatchApplyContext, tree: &mut RbxTree) { } } - instance.properties = properties; + instance.instance.properties = properties; } } fn apply_add_child( context: &mut PatchApplyContext, - tree: &mut RbxTree, + tree: &mut RojoTree, parent_id: RbxId, snapshot: &InstanceSnapshot, ) { - let properties = RbxInstanceProperties { - name: snapshot.name.clone().into_owned(), - class_name: snapshot.class_name.clone().into_owned(), + let properties = InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: snapshot.name.clone().into_owned(), + class_name: snapshot.class_name.clone().into_owned(), - // Property assignment is deferred until after we know about all - // instances in this patch. - properties: HashMap::new(), + // Property assignment is deferred until after we know about all + // instances in this patch. + properties: HashMap::new(), + }, + metadata: Default::default(), // TODO }; let id = tree.insert_instance(properties, parent_id); @@ -94,7 +97,7 @@ fn apply_add_child( fn apply_update_child( context: &PatchApplyContext, - tree: &mut RbxTree, + tree: &mut RojoTree, patch: &PatchUpdateInstance, ) { let instance = tree @@ -102,11 +105,11 @@ fn apply_update_child( .expect("Instance referred to by patch does not exist"); if let Some(name) = &patch.changed_name { - instance.name = name.clone(); + instance.instance.name = name.clone(); } if let Some(class_name) = &patch.changed_class_name { - instance.class_name = class_name.clone(); + instance.instance.class_name = class_name.clone(); } for (key, property_entry) in &patch.changed_properties { @@ -117,7 +120,7 @@ fn apply_update_child( Some(RbxValue::Ref { value: Some(id) }) => { let new_id = context.snapshot_id_to_instance_id.get(id).unwrap_or(id); - instance.properties.insert( + instance.instance.properties.insert( key.clone(), RbxValue::Ref { value: Some(*new_id), @@ -125,10 +128,13 @@ fn apply_update_child( ); } Some(value) => { - instance.properties.insert(key.clone(), value.clone()); + instance + .instance + .properties + .insert(key.clone(), value.clone()); } None => { - instance.properties.remove(key); + instance.instance.properties.remove(key); } } } @@ -149,10 +155,13 @@ mod test { fn add_from_empty() { let _ = env_logger::try_init(); - let mut tree = RbxTree::new(RbxInstanceProperties { - name: "Folder".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), + let mut tree = RojoTree::new(InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "Folder".to_owned(), + class_name: "Folder".to_owned(), + properties: HashMap::new(), + }, + metadata: Default::default(), }); let root_id = tree.get_root_id(); @@ -179,27 +188,33 @@ mod test { apply_patch_set(&mut tree, &patch_set); let root_instance = tree.get_instance(root_id).unwrap(); - let child_id = root_instance.get_children_ids()[0]; + let child_id = root_instance.instance.get_children_ids()[0]; let child_instance = tree.get_instance(child_id).unwrap(); - assert_eq!(child_instance.name.as_str(), &snapshot.name); - assert_eq!(child_instance.class_name.as_str(), &snapshot.class_name); - assert_eq!(&child_instance.properties, &snapshot.properties); - assert!(child_instance.get_children_ids().is_empty()); + assert_eq!(child_instance.instance.name.as_str(), &snapshot.name); + assert_eq!( + child_instance.instance.class_name.as_str(), + &snapshot.class_name + ); + assert_eq!(&child_instance.instance.properties, &snapshot.properties); + assert!(child_instance.instance.get_children_ids().is_empty()); } #[test] fn update_existing() { let _ = env_logger::try_init(); - let mut tree = RbxTree::new(RbxInstanceProperties { - name: "OldName".to_owned(), - class_name: "OldClassName".to_owned(), - properties: hashmap! { - "Foo".to_owned() => RbxValue::Int32 { value: 7 }, - "Bar".to_owned() => RbxValue::Int32 { value: 3 }, - "Unchanged".to_owned() => RbxValue::Int32 { value: -5 }, + let mut tree = RojoTree::new(InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "OldName".to_owned(), + class_name: "OldClassName".to_owned(), + properties: hashmap! { + "Foo".to_owned() => RbxValue::Int32 { value: 7 }, + "Bar".to_owned() => RbxValue::Int32 { value: 3 }, + "Unchanged".to_owned() => RbxValue::Int32 { value: -5 }, + }, }, + metadata: Default::default(), }); let root_id = tree.get_root_id(); @@ -235,8 +250,8 @@ mod test { }; let root_instance = tree.get_instance(root_id).unwrap(); - assert_eq!(root_instance.name, "Foo"); - assert_eq!(root_instance.class_name, "NewClassName"); - assert_eq!(root_instance.properties, expected_properties); + assert_eq!(root_instance.instance.name, "Foo"); + assert_eq!(root_instance.instance.class_name, "NewClassName"); + assert_eq!(root_instance.instance.properties, expected_properties); } } diff --git a/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs index a5227c57..2fa9bb61 100644 --- a/src/snapshot/patch_compute.rs +++ b/src/snapshot/patch_compute.rs @@ -3,16 +3,16 @@ use std::collections::{HashMap, HashSet}; -use rbx_dom_weak::{RbxId, RbxInstance, RbxTree, RbxValue}; +use rbx_dom_weak::{RbxId, RbxInstance, RbxValue}; use super::{ patch::{PatchAddInstance, PatchSet, PatchUpdateInstance}, - InstanceSnapshot, + InstanceSnapshot, RojoTree, }; pub fn compute_patch_set<'a>( snapshot: &'a InstanceSnapshot, - tree: &RbxTree, + tree: &RojoTree, id: RbxId, ) -> PatchSet<'a> { let mut patch_set = PatchSet::new(); @@ -72,7 +72,7 @@ fn rewrite_refs_in_snapshot(context: &ComputePatchContext, snapshot: &mut Instan fn compute_patch_set_internal<'a>( context: &mut ComputePatchContext, snapshot: &'a InstanceSnapshot, - tree: &RbxTree, + tree: &RojoTree, id: RbxId, patch_set: &mut PatchSet<'a>, ) { @@ -84,7 +84,7 @@ fn compute_patch_set_internal<'a>( .get_instance(id) .expect("Instance did not exist in tree"); - compute_property_patches(snapshot, instance, patch_set); + compute_property_patches(snapshot, &instance.instance, patch_set); compute_children_patches(context, snapshot, tree, id, patch_set); } @@ -147,7 +147,7 @@ fn compute_property_patches( fn compute_children_patches<'a>( context: &mut ComputePatchContext, snapshot: &'a InstanceSnapshot, - tree: &RbxTree, + tree: &RojoTree, id: RbxId, patch_set: &mut PatchSet<'a>, ) { @@ -155,7 +155,7 @@ fn compute_children_patches<'a>( .get_instance(id) .expect("Instance did not exist in tree"); - let instance_children = instance.get_children_ids(); + let instance_children = instance.instance.get_children_ids(); let mut paired_instances = vec![false; instance_children.len()]; @@ -173,8 +173,8 @@ fn compute_children_patches<'a>( .get_instance(**instance_child_id) .expect("Instance did not exist in tree"); - if snapshot_child.name == instance_child.name - && snapshot_child.class_name == instance_child.class_name + if snapshot_child.name == instance_child.instance.name + && snapshot_child.class_name == instance_child.instance.class_name { paired_instances[*instance_index] = true; return true; @@ -220,16 +220,21 @@ mod test { use maplit::hashmap; use rbx_dom_weak::RbxInstanceProperties; + use super::super::InstancePropertiesWithMeta; + /// This test makes sure that rewriting refs in instance update patches to /// instances that already exists works. We should be able to correlate the /// snapshot ID and instance ID during patch computation and replace the /// value before returning from compute_patch_set. #[test] fn rewrite_ref_existing_instance_update() { - let tree = RbxTree::new(RbxInstanceProperties { - name: "foo".to_owned(), - class_name: "foo".to_owned(), - properties: HashMap::new(), + let tree = RojoTree::new(InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "foo".to_owned(), + class_name: "foo".to_owned(), + properties: HashMap::new(), + }, + metadata: Default::default(), }); let root_id = tree.get_root_id(); @@ -277,10 +282,13 @@ mod test { /// one. #[test] fn rewrite_ref_existing_instance_addition() { - let tree = RbxTree::new(RbxInstanceProperties { - name: "foo".to_owned(), - class_name: "foo".to_owned(), - properties: HashMap::new(), + let tree = RojoTree::new(InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "foo".to_owned(), + class_name: "foo".to_owned(), + properties: HashMap::new(), + }, + metadata: Default::default(), }); let root_id = tree.get_root_id(); diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index 3df2e3dc..e91afec1 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -32,7 +32,7 @@ pub struct RojoTree { impl RojoTree { pub fn new(root: InstancePropertiesWithMeta) -> RojoTree { let mut tree = RojoTree { - inner: RbxTree::new(root.inner), + inner: RbxTree::new(root.properties), metadata_map: HashMap::new(), path_to_ids: MultiMap::new(), }; @@ -41,25 +41,29 @@ impl RojoTree { tree } + pub fn inner(&self) -> &RbxTree { + &self.inner + } + pub fn get_root_id(&self) -> RbxId { self.inner.get_root_id() } pub fn get_instance(&self, id: RbxId) -> Option { - if let Some(inner) = self.inner.get_instance(id) { + if let Some(instance) = self.inner.get_instance(id) { let metadata = self.metadata_map.get(&id).unwrap(); - Some(InstanceWithMeta { inner, metadata }) + Some(InstanceWithMeta { instance, metadata }) } else { None } } pub fn get_instance_mut(&mut self, id: RbxId) -> Option { - if let Some(inner) = self.inner.get_instance_mut(id) { + if let Some(instance) = self.inner.get_instance_mut(id) { let metadata = self.metadata_map.get_mut(&id).unwrap(); - Some(InstanceWithMetaMut { inner, metadata }) + Some(InstanceWithMetaMut { instance, metadata }) } else { None } @@ -70,7 +74,7 @@ impl RojoTree { properties: InstancePropertiesWithMeta, parent_id: RbxId, ) -> RbxId { - let id = self.inner.insert_instance(properties.inner, parent_id); + let id = self.inner.insert_instance(properties.properties, parent_id); self.insert_metadata(id, properties.metadata); id } @@ -124,18 +128,27 @@ impl RojoTree { #[derive(Debug, Clone)] pub struct InstancePropertiesWithMeta { - pub inner: RbxInstanceProperties, + pub properties: RbxInstanceProperties, pub metadata: InstanceMetadata, } +impl InstancePropertiesWithMeta { + pub fn new(properties: RbxInstanceProperties, metadata: InstanceMetadata) -> Self { + InstancePropertiesWithMeta { + properties, + metadata, + } + } +} + #[derive(Debug)] pub struct InstanceWithMeta<'a> { - pub inner: &'a RbxInstance, + pub instance: &'a RbxInstance, pub metadata: &'a InstanceMetadata, } #[derive(Debug)] pub struct InstanceWithMetaMut<'a> { - pub inner: &'a mut RbxInstance, + pub instance: &'a mut RbxInstance, pub metadata: &'a mut InstanceMetadata, } From 47ee8d54a8d9321a880e4a050e5006075602c267 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 9 Sep 2019 13:59:36 -0700 Subject: [PATCH 0661/1504] Clean up some of the instance wrapper APIs --- src/snapshot/patch_apply.rs | 33 +++++++++++------------ src/snapshot/patch_compute.rs | 6 ++--- src/snapshot/tree.rs | 50 ++++++++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 22 deletions(-) diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index ed97940c..3dbd1f62 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -44,7 +44,7 @@ struct PatchApplyContext { /// then apply properties all at once at the end. fn apply_deferred_properties(context: PatchApplyContext, tree: &mut RojoTree) { for (id, mut properties) in context.properties_to_apply { - let instance = tree + let mut instance = tree .get_instance_mut(id) .expect("Invalid instance ID in deferred property map"); @@ -58,7 +58,7 @@ fn apply_deferred_properties(context: PatchApplyContext, tree: &mut RojoTree) { } } - instance.instance.properties = properties; + *instance.properties_mut() = properties; } } @@ -100,16 +100,16 @@ fn apply_update_child( tree: &mut RojoTree, patch: &PatchUpdateInstance, ) { - let instance = tree + let mut instance = tree .get_instance_mut(patch.id) .expect("Instance referred to by patch does not exist"); if let Some(name) = &patch.changed_name { - instance.instance.name = name.clone(); + *instance.name_mut() = name.clone(); } if let Some(class_name) = &patch.changed_class_name { - instance.instance.class_name = class_name.clone(); + *instance.class_name_mut() = class_name.clone(); } for (key, property_entry) in &patch.changed_properties { @@ -120,7 +120,7 @@ fn apply_update_child( Some(RbxValue::Ref { value: Some(id) }) => { let new_id = context.snapshot_id_to_instance_id.get(id).unwrap_or(id); - instance.instance.properties.insert( + instance.properties_mut().insert( key.clone(), RbxValue::Ref { value: Some(*new_id), @@ -134,7 +134,7 @@ fn apply_update_child( .insert(key.clone(), value.clone()); } None => { - instance.instance.properties.remove(key); + instance.properties_mut().remove(key); } } } @@ -188,16 +188,13 @@ mod test { apply_patch_set(&mut tree, &patch_set); let root_instance = tree.get_instance(root_id).unwrap(); - let child_id = root_instance.instance.get_children_ids()[0]; + let child_id = root_instance.children()[0]; let child_instance = tree.get_instance(child_id).unwrap(); - assert_eq!(child_instance.instance.name.as_str(), &snapshot.name); - assert_eq!( - child_instance.instance.class_name.as_str(), - &snapshot.class_name - ); - assert_eq!(&child_instance.instance.properties, &snapshot.properties); - assert!(child_instance.instance.get_children_ids().is_empty()); + assert_eq!(child_instance.name(), &snapshot.name); + assert_eq!(child_instance.class_name(), &snapshot.class_name); + assert_eq!(child_instance.properties(), &snapshot.properties); + assert!(child_instance.children().is_empty()); } #[test] @@ -250,8 +247,8 @@ mod test { }; let root_instance = tree.get_instance(root_id).unwrap(); - assert_eq!(root_instance.instance.name, "Foo"); - assert_eq!(root_instance.instance.class_name, "NewClassName"); - assert_eq!(root_instance.instance.properties, expected_properties); + assert_eq!(root_instance.name(), "Foo"); + assert_eq!(root_instance.class_name(), "NewClassName"); + assert_eq!(root_instance.properties(), &expected_properties); } } diff --git a/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs index 2fa9bb61..bd87dc7d 100644 --- a/src/snapshot/patch_compute.rs +++ b/src/snapshot/patch_compute.rs @@ -155,7 +155,7 @@ fn compute_children_patches<'a>( .get_instance(id) .expect("Instance did not exist in tree"); - let instance_children = instance.instance.get_children_ids(); + let instance_children = instance.children(); let mut paired_instances = vec![false; instance_children.len()]; @@ -173,8 +173,8 @@ fn compute_children_patches<'a>( .get_instance(**instance_child_id) .expect("Instance did not exist in tree"); - if snapshot_child.name == instance_child.instance.name - && snapshot_child.class_name == instance_child.instance.class_name + if snapshot_child.name == instance_child.name() + && snapshot_child.class_name == instance_child.class_name() { paired_instances[*instance_index] = true; return true; diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index e91afec1..00fb8ba4 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, path::PathBuf}; -use rbx_dom_weak::{RbxId, RbxInstance, RbxInstanceProperties, RbxTree}; +use rbx_dom_weak::{RbxId, RbxInstance, RbxInstanceProperties, RbxTree, RbxValue}; use crate::multimap::MultiMap; @@ -147,8 +147,56 @@ pub struct InstanceWithMeta<'a> { pub metadata: &'a InstanceMetadata, } +impl InstanceWithMeta<'_> { + pub fn name(&self) -> &str { + &self.instance.name + } + + pub fn class_name(&self) -> &str { + &self.instance.class_name + } + + pub fn properties(&self) -> &HashMap { + &self.instance.properties + } + + pub fn children(&self) -> &[RbxId] { + self.instance.get_children_ids() + } +} + #[derive(Debug)] pub struct InstanceWithMetaMut<'a> { pub instance: &'a mut RbxInstance, pub metadata: &'a mut InstanceMetadata, } + +impl InstanceWithMetaMut<'_> { + pub fn name(&self) -> &str { + &self.instance.name + } + + pub fn name_mut(&mut self) -> &mut String { + &mut self.instance.name + } + + pub fn class_name(&self) -> &str { + &self.instance.class_name + } + + pub fn class_name_mut(&mut self) -> &mut String { + &mut self.instance.class_name + } + + pub fn properties(&self) -> &HashMap { + &self.instance.properties + } + + pub fn properties_mut(&mut self) -> &mut HashMap { + &mut self.instance.properties + } + + pub fn children(&self) -> &[RbxId] { + self.instance.get_children_ids() + } +} From 3e759b3e8e10ae38a4ccbeed7c2f56b37fff95b8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 9 Sep 2019 15:04:57 -0700 Subject: [PATCH 0662/1504] Finish off bulk of metadata tracking in snapshot system --- src/commands/build.rs | 14 ++----- src/snapshot/metadata.rs | 30 +++++++++----- src/snapshot/patch_apply.rs | 9 +++-- src/snapshot/patch_compute.rs | 32 ++++++++++----- src/snapshot/tree.rs | 76 ++++++++++++++++++++++++++++++----- 5 files changed, 115 insertions(+), 46 deletions(-) diff --git a/src/commands/build.rs b/src/commands/build.rs index 5b745111..1ae1ee48 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -121,11 +121,8 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { // Place files don't contain an entry for the DataModel, but our // RbxTree representation does. - let top_level_ids = tree - .get_instance(root_id) - .unwrap() - .instance - .get_children_ids(); + let root_instance = tree.get_instance(root_id).unwrap(); + let top_level_ids = root_instance.children(); rbx_xml::to_writer(&mut file, tree.inner(), top_level_ids, xml_encode_config())?; } @@ -137,11 +134,8 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { log::warn!("Using the XML place format (rbxlx) is recommended instead."); log::warn!("For more info, see https://github.com/LPGhatguy/rojo/issues/180"); - let top_level_ids = tree - .get_instance(root_id) - .unwrap() - .instance - .get_children_ids(); + let root_instance = tree.get_instance(root_id).unwrap(); + let top_level_ids = root_instance.children(); rbx_binary::encode(tree.inner(), top_level_ids, &mut file)?; } diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index c231746a..4dface7b 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -11,23 +11,31 @@ pub struct InstanceMetadata { /// manage. pub ignore_unknown_instances: bool, - /// A complete view of where this snapshot came from. It should contain - /// enough information, if not None, to recreate this snapshot - /// deterministically assuming the source has not changed state. - pub source: Option, + // TODO: Make source_path a SmallVec in order to support meta + // files? Maybe we should use another member of the snapshot middleware to + // support damage-painting + /// The path that this file came from, if it's the top-level instance from a + /// model that came directly from disk. + /// + /// This path is used to make sure that file changes update all instances + /// that may need updates.. + pub source_path: Option, + + /// If this instance was defined in a project file, this is the name from + /// the project file and the node under it. + /// + /// This information is used to make sure the instance has the correct name, + /// project-added children, and metadata when it's updated in response to a + /// file change. + pub project_node: Option<(String, ProjectNode)>, } impl Default for InstanceMetadata { fn default() -> Self { InstanceMetadata { ignore_unknown_instances: false, - source: None, + source_path: None, + project_node: None, } } } - -#[derive(Debug, Clone, PartialEq)] -pub struct InstanceSource { - pub path: PathBuf, - pub project_node: Option<(String, ProjectNode)>, -} diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index 3dbd1f62..78acc584 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -100,6 +100,10 @@ fn apply_update_child( tree: &mut RojoTree, patch: &PatchUpdateInstance, ) { + if let Some(metadata) = &patch.changed_metadata { + tree.update_metadata(patch.id, metadata.clone()); + } + let mut instance = tree .get_instance_mut(patch.id) .expect("Instance referred to by patch does not exist"); @@ -128,10 +132,7 @@ fn apply_update_child( ); } Some(value) => { - instance - .instance - .properties - .insert(key.clone(), value.clone()); + instance.properties_mut().insert(key.clone(), value.clone()); } None => { instance.properties_mut().remove(key); diff --git a/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs index bd87dc7d..13b308b9 100644 --- a/src/snapshot/patch_compute.rs +++ b/src/snapshot/patch_compute.rs @@ -3,11 +3,11 @@ use std::collections::{HashMap, HashSet}; -use rbx_dom_weak::{RbxId, RbxInstance, RbxValue}; +use rbx_dom_weak::{RbxId, RbxValue}; use super::{ patch::{PatchAddInstance, PatchSet, PatchUpdateInstance}, - InstanceSnapshot, RojoTree, + InstanceSnapshot, InstanceWithMeta, RojoTree, }; pub fn compute_patch_set<'a>( @@ -84,34 +84,40 @@ fn compute_patch_set_internal<'a>( .get_instance(id) .expect("Instance did not exist in tree"); - compute_property_patches(snapshot, &instance.instance, patch_set); + compute_property_patches(snapshot, &instance, patch_set); compute_children_patches(context, snapshot, tree, id, patch_set); } fn compute_property_patches( snapshot: &InstanceSnapshot, - instance: &RbxInstance, + instance: &InstanceWithMeta, patch_set: &mut PatchSet, ) { let mut visited_properties = HashSet::new(); let mut changed_properties = HashMap::new(); - let changed_name = if snapshot.name == instance.name { + let changed_name = if snapshot.name == instance.name() { None } else { Some(snapshot.name.clone().into_owned()) }; - let changed_class_name = if snapshot.class_name == instance.class_name { + let changed_class_name = if snapshot.class_name == instance.class_name() { None } else { Some(snapshot.class_name.clone().into_owned()) }; + let changed_metadata = if &snapshot.metadata == instance.metadata() { + None + } else { + Some(snapshot.metadata.clone()) + }; + for (name, snapshot_value) in &snapshot.properties { visited_properties.insert(name.as_str()); - match instance.properties.get(name) { + match instance.properties().get(name) { Some(instance_value) => { if snapshot_value != instance_value { changed_properties.insert(name.clone(), Some(snapshot_value.clone())); @@ -123,7 +129,7 @@ fn compute_property_patches( } } - for name in instance.properties.keys() { + for name in instance.properties().keys() { if visited_properties.contains(name.as_str()) { continue; } @@ -131,16 +137,20 @@ fn compute_property_patches( changed_properties.insert(name.clone(), None); } - if changed_properties.is_empty() && changed_name.is_none() { + if changed_properties.is_empty() + && changed_name.is_none() + && changed_class_name.is_none() + && changed_metadata.is_none() + { return; } patch_set.updated_instances.push(PatchUpdateInstance { - id: instance.get_id(), + id: instance.id(), changed_name, changed_class_name, changed_properties, - changed_metadata: None, + changed_metadata, }); } diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index 00fb8ba4..374def45 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -99,9 +99,38 @@ impl RojoTree { } } + /// Replaces the metadata associated with the given instance ID. + pub fn update_metadata(&mut self, id: RbxId, metadata: InstanceMetadata) { + use std::collections::hash_map::Entry; + + match self.metadata_map.entry(id) { + Entry::Occupied(mut entry) => { + let existing_metadata = entry.get(); + + // If this instance's source path changed, we need to update our + // path associations so that file changes will trigger updates + // to this instance correctly. + if existing_metadata.source_path != metadata.source_path { + if let Some(existing_path) = &existing_metadata.source_path { + self.path_to_ids.remove(existing_path, id); + } + + if let Some(new_path) = &metadata.source_path { + self.path_to_ids.insert(new_path.clone(), id); + } + } + + entry.insert(metadata); + } + Entry::Vacant(entry) => { + entry.insert(metadata); + } + } + } + fn insert_metadata(&mut self, id: RbxId, metadata: InstanceMetadata) { - if let Some(source) = &metadata.source { - self.path_to_ids.insert(source.path.clone(), id); + if let Some(source_path) = &metadata.source_path { + self.path_to_ids.insert(source_path.clone(), id); } self.metadata_map.insert(id, metadata); @@ -117,15 +146,16 @@ impl RojoTree { ) { let metadata = self.metadata_map.remove(&id).unwrap(); - if let Some(source) = &metadata.source { - self.path_to_ids.remove(&source.path, id); - path_to_ids.insert(source.path.clone(), id); + if let Some(source_path) = &metadata.source_path { + self.path_to_ids.remove(source_path, id); + path_to_ids.insert(source_path.clone(), id); } metadata_map.insert(id, metadata); } } +/// RojoTree's equivalent of `RbxInstanceProperties`. #[derive(Debug, Clone)] pub struct InstancePropertiesWithMeta { pub properties: RbxInstanceProperties, @@ -141,13 +171,22 @@ impl InstancePropertiesWithMeta { } } -#[derive(Debug)] +/// RojoTree's equivalent of `&'a RbxInstance`. +/// +/// This has to be a value type for RojoTree because the instance and metadata +/// are stored in different places. The mutable equivalent is +/// `InstanceWithMetaMut`. +#[derive(Debug, Clone, Copy)] pub struct InstanceWithMeta<'a> { - pub instance: &'a RbxInstance, - pub metadata: &'a InstanceMetadata, + instance: &'a RbxInstance, + metadata: &'a InstanceMetadata, } impl InstanceWithMeta<'_> { + pub fn id(&self) -> RbxId { + self.instance.get_id() + } + pub fn name(&self) -> &str { &self.instance.name } @@ -163,15 +202,28 @@ impl InstanceWithMeta<'_> { pub fn children(&self) -> &[RbxId] { self.instance.get_children_ids() } + + pub fn metadata(&self) -> &InstanceMetadata { + &self.metadata + } } +/// RojoTree's equivalent of `&'a mut RbxInstance`. +/// +/// This has to be a value type for RojoTree because the instance and metadata +/// are stored in different places. The immutable equivalent is +/// `InstanceWithMeta`. #[derive(Debug)] pub struct InstanceWithMetaMut<'a> { - pub instance: &'a mut RbxInstance, - pub metadata: &'a mut InstanceMetadata, + instance: &'a mut RbxInstance, + metadata: &'a mut InstanceMetadata, } impl InstanceWithMetaMut<'_> { + pub fn id(&self) -> RbxId { + self.instance.get_id() + } + pub fn name(&self) -> &str { &self.instance.name } @@ -199,4 +251,8 @@ impl InstanceWithMetaMut<'_> { pub fn children(&self) -> &[RbxId] { self.instance.get_children_ids() } + + pub fn metadata(&self) -> &InstanceMetadata { + &self.metadata + } } From bb6ab74c1934c6cf50e85849527af75dcaedb7da Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 9 Sep 2019 15:17:03 -0700 Subject: [PATCH 0663/1504] Clean up warnings, add RojoTree into ServeSession --- .../serve-test-snapshots/serve_test__empty.snap | 1 + rojo-test/src/serve_test.rs | 3 ++- src/commands/serve.rs | 2 +- src/imfs/error.rs | 13 ------------- src/project.rs | 2 +- src/serve_session.rs | 10 ++++++++-- src/snapshot_middleware/lua.rs | 4 +++- src/web/api.rs | 6 +++++- src/web/interface.rs | 3 ++- 9 files changed, 23 insertions(+), 21 deletions(-) diff --git a/rojo-test/serve-test-snapshots/serve_test__empty.snap b/rojo-test/serve-test-snapshots/serve_test__empty.snap index e768d5fa..e65f8192 100644 --- a/rojo-test/serve-test-snapshots/serve_test__empty.snap +++ b/rojo-test/serve-test-snapshots/serve_test__empty.snap @@ -6,3 +6,4 @@ sessionId: "[session id]" serverVersion: 0.5.0 protocolVersion: 3 expectedPlaceIds: ~ +rootInstanceId: "[root id]" diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index 392d6f9f..e8f4cdeb 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -28,7 +28,8 @@ fn empty() { let info = session.wait_to_come_online(); assert_yaml_snapshot!(info, { - ".sessionId" => "[session id]" + ".sessionId" => "[session id]", + ".rootInstanceId" => "[root id]" }); }); } diff --git a/src/commands/serve.rs b/src/commands/serve.rs index 9d6c89d5..55f187da 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -70,7 +70,7 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { let patch_set = compute_patch_set(&snapshot, &tree, root_id); apply_patch_set(&mut tree, &patch_set); - let session = Arc::new(ServeSession::new(maybe_project)); + let session = Arc::new(ServeSession::new(tree, maybe_project)); let server = LiveServer::new(session); server.start(port); diff --git a/src/imfs/error.rs b/src/imfs/error.rs index 07c7a8df..0369132e 100644 --- a/src/imfs/error.rs +++ b/src/imfs/error.rs @@ -19,19 +19,6 @@ impl FsResultExt for Result { } } -// TODO: New error type that contains errors specific to our application, -// wrapping io::Error either directly or through another error type that has -// path information. -// -// It's possible that we should hoist up the path information one more level, or -// destructure/restructure information to hoist the path out of FsError and just -// embed io::Error? -pub enum ImfsError { - NotFound, - WrongKind, - Io(io::Error), -} - /// A wrapper around io::Error that also attaches the path associated with the /// error. #[derive(Debug, Fail)] diff --git a/src/project.rs b/src/project.rs index 1b736a63..1869fe31 100644 --- a/src/project.rs +++ b/src/project.rs @@ -34,7 +34,7 @@ struct SourceProject { impl SourceProject { /// Consumes the SourceProject and yields a Project, ready for prime-time. - pub fn into_project(mut self, project_file_location: &Path) -> Project { + pub fn into_project(self, project_file_location: &Path) -> Project { let tree = self.tree.into_project_node(project_file_location); Project { diff --git a/src/serve_session.rs b/src/serve_session.rs index 2eb40af8..1396b1de 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -1,23 +1,29 @@ use std::collections::HashSet; -use crate::{project::Project, session_id::SessionId}; +use crate::{project::Project, session_id::SessionId, snapshot::RojoTree}; /// Contains all of the state for a Rojo serve session. pub struct ServeSession { root_project: Option, session_id: SessionId, + tree: RojoTree, } impl ServeSession { - pub fn new(root_project: Option) -> ServeSession { + pub fn new(tree: RojoTree, root_project: Option) -> ServeSession { let session_id = SessionId::new(); ServeSession { session_id, root_project, + tree, } } + pub fn tree(&self) -> &RojoTree { + &self.tree + } + pub fn session_id(&self) -> SessionId { self.session_id } diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 91b5d77d..1b71416d 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -111,10 +111,12 @@ fn snapshot_init( let init_path = folder_entry.path().join(init_name); if let Some(init_entry) = imfs.get(init_path).with_not_found()? { - if let Some(mut dir_snapshot) = SnapshotDir::from_imfs(imfs, folder_entry)? { + if let Some(dir_snapshot) = SnapshotDir::from_imfs(imfs, folder_entry)? { if let Some(mut init_snapshot) = snapshot_lua_file(imfs, &init_entry)? { init_snapshot.name = dir_snapshot.name; init_snapshot.children = dir_snapshot.children; + // TODO: Metadata + // TODO: Validate directory class name is "Folder" return Ok(Some(init_snapshot)); } diff --git a/src/web/api.rs b/src/web/api.rs index 759b3ea9..03962d03 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -53,11 +53,15 @@ impl ApiService { /// Get a summary of information about the server fn handle_api_rojo(&self) -> Response { + let tree = self.serve_session.tree(); + let root_instance_id = tree.get_root_id(); + response_json(&ServerInfoResponse { server_version: SERVER_VERSION.to_owned(), protocol_version: PROTOCOL_VERSION, session_id: self.serve_session.session_id(), - expected_place_ids: self.serve_session.serve_place_ids().map(Clone::clone), + expected_place_ids: self.serve_session.serve_place_ids().cloned(), + root_instance_id, }) } diff --git a/src/web/interface.rs b/src/web/interface.rs index 1ed2bd94..7f8d5d82 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -2,6 +2,7 @@ use std::collections::HashSet; +use rbx_dom_weak::RbxId; use serde::{Deserialize, Serialize}; use crate::session_id::SessionId; @@ -20,7 +21,7 @@ pub struct ServerInfoResponse { pub server_version: String, pub protocol_version: u64, pub expected_place_ids: Option>, - // pub root_instance_id: RbxId, + pub root_instance_id: RbxId, } /// Response body from /api/read/{id} From 57d46287d7b396839b4893db1dfcea3fd5b4087c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 9 Sep 2019 18:32:44 -0700 Subject: [PATCH 0664/1504] Glue message queue onto ServeSession, simplify some HTTP --- src/message_queue.rs | 2 +- src/serve_session.rs | 11 +++++++- src/web/api.rs | 60 ++++++++++++++++++++++++++------------------ src/web/interface.rs | 21 ++++++++++++---- src/web/ui.rs | 13 ++++++---- src/web/util.rs | 17 ++++++++++++- 6 files changed, 87 insertions(+), 37 deletions(-) diff --git a/src/message_queue.rs b/src/message_queue.rs index 2ae52b28..2eb22609 100644 --- a/src/message_queue.rs +++ b/src/message_queue.rs @@ -77,7 +77,7 @@ impl MessageQueue { message_listeners.push(listener); } - pub fn get_message_cursor(&self) -> u32 { + pub fn cursor(&self) -> u32 { self.messages.read().unwrap().len() as u32 } diff --git a/src/serve_session.rs b/src/serve_session.rs index 1396b1de..8d132261 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -1,22 +1,27 @@ use std::collections::HashSet; -use crate::{project::Project, session_id::SessionId, snapshot::RojoTree}; +use crate::{ + message_queue::MessageQueue, project::Project, session_id::SessionId, snapshot::RojoTree, +}; /// Contains all of the state for a Rojo serve session. pub struct ServeSession { root_project: Option, session_id: SessionId, tree: RojoTree, + message_queue: MessageQueue<()>, // TODO: Real message type } impl ServeSession { pub fn new(tree: RojoTree, root_project: Option) -> ServeSession { let session_id = SessionId::new(); + let message_queue = MessageQueue::new(); ServeSession { session_id, root_project, tree, + message_queue, } } @@ -24,6 +29,10 @@ impl ServeSession { &self.tree } + pub fn message_queue(&self) -> &MessageQueue<()> { + &self.message_queue + } + pub fn session_id(&self) -> SessionId { self.session_id } diff --git a/src/web/api.rs b/src/web/api.rs index 03962d03..de88c73a 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -1,7 +1,7 @@ //! Defines Rojo's HTTP API, all under /api. These endpoints generally return //! JSON. -use std::sync::Arc; +use std::{collections::HashMap, sync::Arc}; use futures::{future, Future}; @@ -12,9 +12,10 @@ use crate::{ serve_session::ServeSession, web::{ interface::{ - ReadResponse, ServerInfoResponse, SubscribeResponse, PROTOCOL_VERSION, SERVER_VERSION, + NotFoundError, ReadResponse, ServerInfoResponse, SubscribeResponse, PROTOCOL_VERSION, + SERVER_VERSION, }, - util::response_json, + util::{json, json_ok}, }, }; @@ -30,19 +31,14 @@ impl Service for ApiService { Box, Error = Self::Error> + Send>; fn call(&mut self, request: hyper::Request) -> Self::Future { - let response = match (request.method(), request.uri().path()) { + match (request.method(), request.uri().path()) { (&Method::GET, "/api/rojo") => self.handle_api_rojo(), (&Method::GET, path) if path.starts_with("/api/read/") => self.handle_api_read(request), (&Method::GET, path) if path.starts_with("/api/subscribe/") => { - return self.handle_api_subscribe(request); + self.handle_api_subscribe(request) } - _ => Response::builder() - .status(StatusCode::NOT_FOUND) - .body(Body::empty()) - .unwrap(), - }; - - Box::new(future::ok(response)) + _ => json(NotFoundError, StatusCode::NOT_FOUND), + } } } @@ -52,11 +48,11 @@ impl ApiService { } /// Get a summary of information about the server - fn handle_api_rojo(&self) -> Response { + fn handle_api_rojo(&self) -> ::Future { let tree = self.serve_session.tree(); let root_instance_id = tree.get_root_id(); - response_json(&ServerInfoResponse { + json_ok(&ServerInfoResponse { server_version: SERVER_VERSION.to_owned(), protocol_version: PROTOCOL_VERSION, session_id: self.serve_session.session_id(), @@ -69,7 +65,7 @@ impl ApiService { /// there weren't any, subscribe to receive any new messages. fn handle_api_subscribe(&self, request: Request) -> ::Future { let argument = &request.uri().path()["/api/subscribe/".len()..]; - let _cursor: u32 = match argument.parse() { + let _input_cursor: u32 = match argument.parse() { Ok(v) => v, Err(err) => { return Box::new(future::ok( @@ -82,28 +78,44 @@ impl ApiService { } }; - Box::new(future::ok(response_json(SubscribeResponse { + let message_queue = self.serve_session.message_queue(); + let message_cursor = message_queue.cursor(); + + let messages = Vec::new(); // TODO + + json_ok(SubscribeResponse { session_id: self.serve_session.session_id(), - }))) + message_cursor, + messages, + }) } - fn handle_api_read(&self, request: Request) -> Response { + fn handle_api_read(&self, request: Request) -> ::Future { let argument = &request.uri().path()["/api/read/".len()..]; let requested_ids: Option> = argument.split(',').map(RbxId::parse_str).collect(); let _requested_ids = match requested_ids { Some(id) => id, None => { - return Response::builder() - .status(StatusCode::BAD_REQUEST) - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from("Malformed ID list")) - .unwrap(); + return Box::new(future::ok( + Response::builder() + .status(StatusCode::BAD_REQUEST) + .header(header::CONTENT_TYPE, "text/plain") + .body(Body::from("Malformed ID list")) + .unwrap(), + )); } }; - response_json(ReadResponse { + let message_queue = self.serve_session.message_queue(); + let message_cursor = message_queue.cursor(); + + let instances = HashMap::new(); // TODO + + json_ok(ReadResponse { session_id: self.serve_session.session_id(), + message_cursor, + instances, }) } } diff --git a/src/web/interface.rs b/src/web/interface.rs index 7f8d5d82..162f9395 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -1,6 +1,6 @@ //! Defines all the structs needed to interact with the Rojo Serve API. -use std::collections::HashSet; +use std::collections::{HashMap, HashSet}; use rbx_dom_weak::RbxId; use serde::{Deserialize, Serialize}; @@ -13,6 +13,14 @@ pub(crate) const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); /// Current protocol version, which is required to match. pub const PROTOCOL_VERSION: u64 = 3; +// TODO +#[derive(Debug, Serialize, Deserialize)] +pub struct SubscribeMessage; + +// TODO +#[derive(Debug, Serialize, Deserialize)] +pub struct Instance; + /// Response body from /api/rojo #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -29,8 +37,8 @@ pub struct ServerInfoResponse { #[serde(rename_all = "camelCase")] pub struct ReadResponse { pub session_id: SessionId, - // pub message_cursor: u32, - // pub instances: HashMap>, + pub message_cursor: u32, + pub instances: HashMap, } /// Response body from /api/subscribe/{cursor} @@ -38,6 +46,9 @@ pub struct ReadResponse { #[serde(rename_all = "camelCase")] pub struct SubscribeResponse { pub session_id: SessionId, - // pub message_cursor: u32, - // pub messages: Cow<'a, [InstanceChanges]>, + pub message_cursor: u32, + pub messages: Vec, } + +#[derive(Debug, Serialize, Deserialize)] +pub struct NotFoundError; diff --git a/src/web/ui.rs b/src/web/ui.rs index 01471839..4212f21a 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -6,7 +6,13 @@ use futures::{future, Future}; use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; use ritz::html; -use crate::{serve_session::ServeSession, web::interface::SERVER_VERSION}; +use crate::{ + serve_session::ServeSession, + web::{ + interface::{NotFoundError, SERVER_VERSION}, + util::json, + }, +}; static HOME_CSS: &str = include_str!("../../assets/index.css"); @@ -26,10 +32,7 @@ impl Service for UiService { (&Method::GET, "/") => self.handle_home(), (&Method::GET, "/visualize/rbx") => self.handle_visualize_rbx(), (&Method::GET, "/visualize/imfs") => self.handle_visualize_imfs(), - _ => Response::builder() - .status(StatusCode::NOT_FOUND) - .body(Body::empty()) - .unwrap(), + _ => return json(NotFoundError, StatusCode::NOT_FOUND), }; Box::new(future::ok(response)) diff --git a/src/web/util.rs b/src/web/util.rs index 32581c38..b882b372 100644 --- a/src/web/util.rs +++ b/src/web/util.rs @@ -1,7 +1,8 @@ +use futures::{future, Future}; use hyper::{header::CONTENT_TYPE, Body, Response, StatusCode}; use serde::Serialize; -pub fn response_json(value: T) -> Response { +fn response_json(value: T, code: StatusCode) -> Response { let serialized = match serde_json::to_string(&value) { Ok(v) => v, Err(err) => { @@ -14,7 +15,21 @@ pub fn response_json(value: T) -> Response { }; Response::builder() + .status(code) .header(CONTENT_TYPE, "application/json") .body(Body::from(serialized)) .unwrap() } + +pub fn json( + value: T, + code: StatusCode, +) -> Box, Error = hyper::Error> + Send> { + Box::new(future::ok(response_json(value, code))) +} + +pub fn json_ok( + value: T, +) -> Box, Error = hyper::Error> + Send> { + json(value, StatusCode::OK) +} From 6a786f18e606e47918dacf106a61e890f3fa4287 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Sep 2019 15:37:21 -0700 Subject: [PATCH 0665/1504] Update plugin protocl version, fix error in error --- plugin/src/ApiContext.lua | 4 ++-- plugin/src/Config.lua | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 898564c6..0b6a7531 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -73,10 +73,10 @@ function ApiContext:connect() "\nMake sure you have matching versions of both the Rojo plugin and server!" .. "\n\nYour client is version %s, with protocol version %s. It expects server version %s." .. "\nYour server is version %s, with protocol version %s." .. - "\n\nGo to https://github.com/LPGhatguy/rojo for more details." + "\n\nGo to https://github.com/rojo-rbx/rojo for more details." ):format( Version.display(Config.version), Config.protocolVersion, - Config.expectedApiContextVersionString, + Config.expectedServerVersionString, body.serverVersion, body.protocolVersion ) diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 09cb5eb8..3e9ce414 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -2,7 +2,7 @@ return { codename = "Epiphany", version = {0, 5, 0}, expectedServerVersionString = "0.5.0 or newer", - protocolVersion = 2, + protocolVersion = 3, defaultHost = "localhost", defaultPort = 34872, } \ No newline at end of file From e6ba6203bbab8fe5e3604d3651f1c578287203e8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Sep 2019 15:39:50 -0700 Subject: [PATCH 0666/1504] Expose tree in API, with hacks to make initial sync-in work sort of --- src/snapshot_middleware/project.rs | 12 ++++---- src/web/api.rs | 23 ++++++++++---- src/web/interface.rs | 48 ++++++++++++++++++++++++++---- 3 files changed, 66 insertions(+), 17 deletions(-) diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 471a91d8..72fa3706 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -9,7 +9,7 @@ use crate::{ FsErrorKind, }, project::{Project, ProjectNode}, - snapshot::InstanceSnapshot, + snapshot::{InstanceMetadata, InstanceSnapshot}, }; use super::{ @@ -55,10 +55,7 @@ fn snapshot_project_node( node: &ProjectNode, imfs: &mut Imfs, ) -> SnapshotInstanceResult<'static> { - assert!( - node.ignore_unknown_instances.is_none(), - "TODO: Support $ignoreUnknownInstances" - ); + let ignore_unknown_instances = node.ignore_unknown_instances.unwrap_or(node.path.is_none()); let name = Cow::Owned(instance_name.to_owned()); let mut class_name = node @@ -131,7 +128,10 @@ fn snapshot_project_node( Ok(Some(InstanceSnapshot { snapshot_id: None, - metadata: Default::default(), // TODO + metadata: InstanceMetadata { + ignore_unknown_instances, + ..Default::default() // TODO: Fill out remaining metadata + }, name, class_name, properties, diff --git a/src/web/api.rs b/src/web/api.rs index de88c73a..2d7e9a37 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -12,8 +12,8 @@ use crate::{ serve_session::ServeSession, web::{ interface::{ - NotFoundError, ReadResponse, ServerInfoResponse, SubscribeResponse, PROTOCOL_VERSION, - SERVER_VERSION, + Instance, NotFoundError, ReadResponse, ServerInfoResponse, SubscribeResponse, + PROTOCOL_VERSION, SERVER_VERSION, }, util::{json, json_ok}, }, @@ -94,8 +94,8 @@ impl ApiService { let argument = &request.uri().path()["/api/read/".len()..]; let requested_ids: Option> = argument.split(',').map(RbxId::parse_str).collect(); - let _requested_ids = match requested_ids { - Some(id) => id, + let requested_ids = match requested_ids { + Some(ids) => ids, None => { return Box::new(future::ok( Response::builder() @@ -110,7 +110,20 @@ impl ApiService { let message_queue = self.serve_session.message_queue(); let message_cursor = message_queue.cursor(); - let instances = HashMap::new(); // TODO + let tree = self.serve_session.tree(); + let inner_tree = tree.inner(); + + let mut instances = HashMap::new(); + + for id in requested_ids { + if let Some(instance) = inner_tree.get_instance(id) { + instances.insert(id, Instance::from_rbx_instance(instance)); + + for descendant in inner_tree.descendants(id) { + instances.insert(descendant.get_id(), Instance::from_rbx_instance(descendant)); + } + } + } json_ok(ReadResponse { session_id: self.serve_session.session_id(), diff --git a/src/web/interface.rs b/src/web/interface.rs index 162f9395..1bc6c117 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -1,8 +1,11 @@ //! Defines all the structs needed to interact with the Rojo Serve API. -use std::collections::{HashMap, HashSet}; +use std::{ + borrow::Cow, + collections::{HashMap, HashSet}, +}; -use rbx_dom_weak::RbxId; +use rbx_dom_weak::{RbxId, RbxInstance, RbxValue}; use serde::{Deserialize, Serialize}; use crate::session_id::SessionId; @@ -17,9 +20,42 @@ pub const PROTOCOL_VERSION: u64 = 3; #[derive(Debug, Serialize, Deserialize)] pub struct SubscribeMessage; -// TODO #[derive(Debug, Serialize, Deserialize)] -pub struct Instance; +#[serde(rename_all = "camelCase")] +pub struct InstanceMetadata { + pub ignore_unknown_instances: bool, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +pub struct Instance<'a> { + pub name: Cow<'a, str>, + pub class_name: Cow<'a, str>, + pub properties: Cow<'a, HashMap>, + pub children: Cow<'a, [RbxId]>, + pub metadata: Option, +} + +impl<'a> Instance<'a> { + pub fn from_rbx_instance(source: &RbxInstance) -> Instance<'_> { + // TODO: This is a hack! + let metadata = if source.class_name == "DataModel" { + Some(InstanceMetadata { + ignore_unknown_instances: true, + }) + } else { + None + }; + + Instance { + name: Cow::Borrowed(&source.name), + class_name: Cow::Borrowed(&source.class_name), + properties: Cow::Borrowed(&source.properties), + children: Cow::Borrowed(source.get_children_ids()), + metadata, + } + } +} /// Response body from /api/rojo #[derive(Debug, Serialize, Deserialize)] @@ -35,10 +71,10 @@ pub struct ServerInfoResponse { /// Response body from /api/read/{id} #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct ReadResponse { +pub struct ReadResponse<'a> { pub session_id: SessionId, pub message_cursor: u32, - pub instances: HashMap, + pub instances: HashMap>, } /// Response body from /api/subscribe/{cursor} From fc01eecdcb0b093307ace1ce9d7b2683e41bc6f1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Sep 2019 15:59:36 -0700 Subject: [PATCH 0667/1504] Use real Rojo metadata for live sync --- src/snapshot/tree.rs | 44 +++++++++++++++++++++++++++++++++++++------- src/web/api.rs | 9 ++++----- src/web/interface.rs | 25 +++++++++---------------- 3 files changed, 50 insertions(+), 28 deletions(-) diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index 374def45..27aa3f45 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, path::PathBuf}; -use rbx_dom_weak::{RbxId, RbxInstance, RbxInstanceProperties, RbxTree, RbxValue}; +use rbx_dom_weak::{Descendants, RbxId, RbxInstance, RbxInstanceProperties, RbxTree, RbxValue}; use crate::multimap::MultiMap; @@ -128,6 +128,17 @@ impl RojoTree { } } + pub fn descendants(&self, id: RbxId) -> RojoDescendants<'_> { + RojoDescendants { + inner: self.inner.descendants(id), + tree: self, + } + } + + fn get_metadata(&self, id: RbxId) -> Option<&InstanceMetadata> { + self.metadata_map.get(&id) + } + fn insert_metadata(&mut self, id: RbxId, metadata: InstanceMetadata) { if let Some(source_path) = &metadata.source_path { self.path_to_ids.insert(source_path.clone(), id); @@ -155,6 +166,25 @@ impl RojoTree { } } +pub struct RojoDescendants<'a> { + inner: Descendants<'a>, + tree: &'a RojoTree, +} + +impl<'a> Iterator for RojoDescendants<'a> { + type Item = InstanceWithMeta<'a>; + + fn next(&mut self) -> Option { + let instance = self.inner.next()?; + let metadata = self + .tree + .get_metadata(instance.get_id()) + .expect("Metadata did not exist for instance"); + + Some(InstanceWithMeta { instance, metadata }) + } +} + /// RojoTree's equivalent of `RbxInstanceProperties`. #[derive(Debug, Clone)] pub struct InstancePropertiesWithMeta { @@ -182,28 +212,28 @@ pub struct InstanceWithMeta<'a> { metadata: &'a InstanceMetadata, } -impl InstanceWithMeta<'_> { +impl<'a> InstanceWithMeta<'a> { pub fn id(&self) -> RbxId { self.instance.get_id() } - pub fn name(&self) -> &str { + pub fn name(&self) -> &'a str { &self.instance.name } - pub fn class_name(&self) -> &str { + pub fn class_name(&self) -> &'a str { &self.instance.class_name } - pub fn properties(&self) -> &HashMap { + pub fn properties(&self) -> &'a HashMap { &self.instance.properties } - pub fn children(&self) -> &[RbxId] { + pub fn children(&self) -> &'a [RbxId] { self.instance.get_children_ids() } - pub fn metadata(&self) -> &InstanceMetadata { + pub fn metadata(&self) -> &'a InstanceMetadata { &self.metadata } } diff --git a/src/web/api.rs b/src/web/api.rs index 2d7e9a37..885c941b 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -111,16 +111,15 @@ impl ApiService { let message_cursor = message_queue.cursor(); let tree = self.serve_session.tree(); - let inner_tree = tree.inner(); let mut instances = HashMap::new(); for id in requested_ids { - if let Some(instance) = inner_tree.get_instance(id) { - instances.insert(id, Instance::from_rbx_instance(instance)); + if let Some(instance) = tree.get_instance(id) { + instances.insert(id, Instance::from_rojo_instance(instance)); - for descendant in inner_tree.descendants(id) { - instances.insert(descendant.get_id(), Instance::from_rbx_instance(descendant)); + for descendant in tree.descendants(id) { + instances.insert(descendant.id(), Instance::from_rojo_instance(descendant)); } } } diff --git a/src/web/interface.rs b/src/web/interface.rs index 1bc6c117..18f62104 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -8,7 +8,7 @@ use std::{ use rbx_dom_weak::{RbxId, RbxInstance, RbxValue}; use serde::{Deserialize, Serialize}; -use crate::session_id::SessionId; +use crate::{session_id::SessionId, snapshot::InstanceWithMeta}; /// Server version to report over the API, not exposed outside this crate. pub(crate) const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -37,22 +37,15 @@ pub struct Instance<'a> { } impl<'a> Instance<'a> { - pub fn from_rbx_instance(source: &RbxInstance) -> Instance<'_> { - // TODO: This is a hack! - let metadata = if source.class_name == "DataModel" { - Some(InstanceMetadata { - ignore_unknown_instances: true, - }) - } else { - None - }; - + pub fn from_rojo_instance<'b>(source: InstanceWithMeta<'b>) -> Instance<'b> { Instance { - name: Cow::Borrowed(&source.name), - class_name: Cow::Borrowed(&source.class_name), - properties: Cow::Borrowed(&source.properties), - children: Cow::Borrowed(source.get_children_ids()), - metadata, + name: Cow::Borrowed(source.name()), + class_name: Cow::Borrowed(source.class_name()), + properties: Cow::Borrowed(source.properties()), + children: Cow::Borrowed(source.children()), + metadata: Some(InstanceMetadata { + ignore_unknown_instances: source.metadata().ignore_unknown_instances, + }), } } } From 877fd1af35109bbaddd9d6b06da02fbc012680fc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Sep 2019 16:42:14 -0700 Subject: [PATCH 0668/1504] Make /api/subscribe hang forever instead of returning no messages --- src/web/api.rs | 19 +++++++++++-------- src/web/interface.rs | 2 +- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/web/api.rs b/src/web/api.rs index 885c941b..63f46d34 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -78,16 +78,19 @@ impl ApiService { } }; - let message_queue = self.serve_session.message_queue(); - let message_cursor = message_queue.cursor(); + // Temporary response to prevent Rojo plugin from sending too many + // requests, this will hang the request until it times out. + Box::new(future::empty()) - let messages = Vec::new(); // TODO + // let message_queue = self.serve_session.message_queue(); + // let message_cursor = message_queue.cursor(); + // let messages = Vec::new(); - json_ok(SubscribeResponse { - session_id: self.serve_session.session_id(), - message_cursor, - messages, - }) + // json_ok(SubscribeResponse { + // session_id: self.serve_session.session_id(), + // message_cursor, + // messages, + // }) } fn handle_api_read(&self, request: Request) -> ::Future { diff --git a/src/web/interface.rs b/src/web/interface.rs index 18f62104..b62c77f5 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -5,7 +5,7 @@ use std::{ collections::{HashMap, HashSet}, }; -use rbx_dom_weak::{RbxId, RbxInstance, RbxValue}; +use rbx_dom_weak::{RbxId, RbxValue}; use serde::{Deserialize, Serialize}; use crate::{session_id::SessionId, snapshot::InstanceWithMeta}; From 8ef797d1a49f2b87685283d6b0ecdde87fac296c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Sep 2019 18:04:05 -0700 Subject: [PATCH 0669/1504] Start writing real serve tests --- Cargo.lock | 2 + rojo-test/Cargo.toml | 2 + .../serve_test__empty-2.snap | 14 +++ .../serve_test__empty.snap | 4 +- rojo-test/src/serve_test.rs | 113 ++++++++++++++++-- src/session_id.rs | 8 ++ 6 files changed, 131 insertions(+), 12 deletions(-) create mode 100644 rojo-test/serve-test-snapshots/serve_test__empty-2.snap diff --git a/Cargo.lock b/Cargo.lock index 2ed22933..afba911c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1489,10 +1489,12 @@ dependencies = [ "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", "rojo 0.5.0", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index 3c55212c..2a9e5c56 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -9,9 +9,11 @@ publish = false env_logger = "0.6.2" log = "0.4.8" paste = "0.1.5" +rbx_dom_weak = "1.9.0" reqwest = "0.9.20" serde = "1.0.99" serde_json = "1.0.40" +serde_yaml = "0.8.9" tempfile = "3.1.0" walkdir = "2.2.9" diff --git a/rojo-test/serve-test-snapshots/serve_test__empty-2.snap b/rojo-test/serve-test-snapshots/serve_test__empty-2.snap new file mode 100644 index 00000000..5ef25f8a --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__empty-2.snap @@ -0,0 +1,14 @@ +--- +source: rojo-test/src/serve_test.rs +expression: read_result +--- +sessionId: id-1 +messageCursor: 0 +instances: + id-2: + Name: empty + ClassName: Folder + Properties: {} + Children: [] + Metadata: + ignoreUnknownInstances: true diff --git a/rojo-test/serve-test-snapshots/serve_test__empty.snap b/rojo-test/serve-test-snapshots/serve_test__empty.snap index e65f8192..4ecdb7ea 100644 --- a/rojo-test/serve-test-snapshots/serve_test__empty.snap +++ b/rojo-test/serve-test-snapshots/serve_test__empty.snap @@ -2,8 +2,8 @@ source: rojo-test/src/serve_test.rs expression: info --- -sessionId: "[session id]" +sessionId: id-1 serverVersion: 0.5.0 protocolVersion: 3 expectedPlaceIds: ~ -rootInstanceId: "[root id]" +rootInstanceId: id-2 diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index e8f4cdeb..a5887655 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -1,4 +1,5 @@ use std::{ + collections::HashMap, fs, path::{Path, PathBuf}, process::Command, @@ -6,9 +7,10 @@ use std::{ }; use insta::assert_yaml_snapshot; +use rbx_dom_weak::RbxId; use tempfile::{tempdir, TempDir}; -use librojo::web_interface::ServerInfoResponse; +use librojo::web_interface::{ReadResponse, ServerInfoResponse}; use crate::util::{ copy_recursive, get_rojo_path, get_serve_tests_path, get_working_dir_path, KillOnDrop, @@ -16,6 +18,28 @@ use crate::util::{ #[test] fn empty() { + run_serve_test(|session, mut dm| { + let info = session.get_api_rojo().unwrap(); + + let root_id = info.root_instance_id; + + let mut info = serde_yaml::to_value(info).unwrap(); + dm.redact(&mut info); + + assert_yaml_snapshot!(info); + + let read_result = session.get_api_read(root_id).unwrap(); + + dm.intern_iter(read_result.instances.keys().copied()); + + let mut read_result = serde_yaml::to_value(read_result).unwrap(); + dm.redact(&mut read_result); + + assert_yaml_snapshot!(read_result); + }); +} + +fn run_serve_test(callback: impl FnOnce(TestServeSession, DeterMap)) { let _ = env_logger::try_init(); let mut settings = insta::Settings::new(); @@ -23,15 +47,77 @@ fn empty() { let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("serve-test-snapshots"); settings.set_snapshot_path(snapshot_path); - settings.bind(|| { - let mut session = TestServeSession::new("empty"); - let info = session.wait_to_come_online(); + let mut dm = DeterMap::new(); - assert_yaml_snapshot!(info, { - ".sessionId" => "[session id]", - ".rootInstanceId" => "[root id]" + let mut session = TestServeSession::new("empty"); + let info = session.wait_to_come_online(); + + dm.intern(info.session_id); + dm.intern(info.root_instance_id); + + settings.bind(move || callback(session, dm)); +} + +struct DeterMap { + ids: HashMap, + last_id: usize, +} + +impl DeterMap { + fn new() -> DeterMap { + DeterMap { + ids: HashMap::new(), + last_id: 0, + } + } + + fn intern(&mut self, id: impl ToString) { + let last_id = &mut self.last_id; + + self.ids.entry(id.to_string()).or_insert_with(|| { + *last_id += 1; + *last_id }); - }); + } + + fn intern_iter(&mut self, ids: impl Iterator) { + for id in ids { + self.intern(id.to_string()); + } + } + + fn redact(&self, yaml_value: &mut serde_yaml::Value) { + use serde_yaml::{Mapping, Value}; + + match yaml_value { + Value::String(value) => { + if let Some(redacted) = self.ids.get(value) { + *yaml_value = Value::String(format!("id-{}", *redacted)); + } + } + Value::Sequence(sequence) => { + for value in sequence { + self.redact(value); + } + } + Value::Mapping(mapping) => { + // We can't mutate the keys of a map in-place, so we take + // ownership of the map and rebuild it. + + let owned_map = std::mem::replace(mapping, Mapping::new()); + let mut new_map = Mapping::with_capacity(owned_map.len()); + + for (mut key, mut value) in owned_map { + self.redact(&mut key); + self.redact(&mut value); + new_map.insert(key, value); + } + + *mapping = new_map; + } + _ => {} + } + } } fn get_port_number() -> usize { @@ -111,8 +197,15 @@ impl TestServeSession { } pub fn get_api_rojo(&self) -> Result { - let info_url = format!("http://localhost:{}/api/rojo", self.port); - let body = reqwest::get(&info_url)?.text()?; + let url = format!("http://localhost:{}/api/rojo", self.port); + let body = reqwest::get(&url)?.text()?; + + Ok(serde_json::from_str(&body).expect("Server returned malformed response")) + } + + pub fn get_api_read(&self, id: RbxId) -> Result { + let url = format!("http://localhost:{}/api/read/{}", self.port, id); + let body = reqwest::get(&url)?.text()?; Ok(serde_json::from_str(&body).expect("Server returned malformed response")) } diff --git a/src/session_id.rs b/src/session_id.rs index 51596ba0..d178a5b4 100644 --- a/src/session_id.rs +++ b/src/session_id.rs @@ -1,3 +1,5 @@ +use std::fmt; + use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -13,3 +15,9 @@ impl SessionId { SessionId(Uuid::new_v4()) } } + +impl fmt::Display for SessionId { + fn fmt(&self, writer: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(writer, "{}", self.0) + } +} From 88e462c4e5256f02bf435ba4f4695f05c5471642 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 11 Sep 2019 11:34:52 -0700 Subject: [PATCH 0670/1504] Add help page to direct people to Discord, GitHub, and Twitter --- docs/help.md | 7 +++++++ mkdocs.yml | 1 + 2 files changed, 8 insertions(+) create mode 100644 docs/help.md diff --git a/docs/help.md b/docs/help.md new file mode 100644 index 00000000..3bbf2ae9 --- /dev/null +++ b/docs/help.md @@ -0,0 +1,7 @@ +Rojo is a fairly complex tool to adopt, but there's a community willing to help! + +The [Roblox Open Source Community Discord](https://discord.gg/wH5ncNS) currently hosts a Rojo support channel, **#rojo**, that is a great place to get help as problems come up. + +If you find anything that looks like a bug or have ideas for how to improve Rojo, feel free to file an issue on [Rojo's GitHub issue tracker](https://github.com/rojo-rbx/rojo/issues). + +Rojo's primary maintainer is also available on Twitter, [@LPGhatguy](https://twitter.com/LPGhatguy). \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index 5124905e..c5f86297 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -11,6 +11,7 @@ theme: nav: - Home: index.md - Why Rojo?: why-rojo.md + - Get Help with Rojo: help.md - Guide: - Installation: guide/installation.md - Creating a Game with Rojo: guide/new-game.md From 651e63a0fb343f01004fb19fc94447d0f06e68a1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 11 Sep 2019 11:37:58 -0700 Subject: [PATCH 0671/1504] Tidy up docs links in readme --- README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/README.md b/README.md index c96d5866..2b38a0ee 100644 --- a/README.md +++ b/README.md @@ -13,9 +13,6 @@ Latest server version - - Rojo 0.4.x Documentation - Rojo 0.5.x Documentation @@ -44,7 +41,7 @@ Soon, Rojo will be able to: * Automatically manage your assets on Roblox.com, like images and sounds * Import custom instances like MoonScript code -## [Documentation](https://rojo.space/docs/latest) +## [Documentation](https://rojo.space/docs) If you find any mistakes, feel free to make changes in the [docs](https://github.com/rojo-rbx/rojo/tree/master/docs) folder of this repository and submit a pull request! ## Contributing From 8481caa67c527b253d00b812aae118f214c9ae4d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Sep 2019 12:52:15 -0700 Subject: [PATCH 0672/1504] Add Imfs to ServeSession, threading through generic ImfsFetcher --- src/commands/serve.rs | 2 +- src/serve_session.rs | 14 ++++++++++---- src/web/api.rs | 17 +++++++++-------- src/web/mod.rs | 22 +++++++++++----------- src/web/ui.rs | 11 ++++++----- 5 files changed, 37 insertions(+), 29 deletions(-) diff --git a/src/commands/serve.rs b/src/commands/serve.rs index 55f187da..a29e4439 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -70,7 +70,7 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { let patch_set = compute_patch_set(&snapshot, &tree, root_id); apply_patch_set(&mut tree, &patch_set); - let session = Arc::new(ServeSession::new(tree, maybe_project)); + let session = Arc::new(ServeSession::new(imfs, tree, maybe_project)); let server = LiveServer::new(session); server.start(port); diff --git a/src/serve_session.rs b/src/serve_session.rs index 8d132261..4f4d4e23 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -1,19 +1,24 @@ use std::collections::HashSet; use crate::{ - message_queue::MessageQueue, project::Project, session_id::SessionId, snapshot::RojoTree, + imfs::new::{Imfs, ImfsFetcher}, + message_queue::MessageQueue, + project::Project, + session_id::SessionId, + snapshot::RojoTree, }; /// Contains all of the state for a Rojo serve session. -pub struct ServeSession { +pub struct ServeSession { root_project: Option, session_id: SessionId, tree: RojoTree, message_queue: MessageQueue<()>, // TODO: Real message type + imfs: Imfs, } -impl ServeSession { - pub fn new(tree: RojoTree, root_project: Option) -> ServeSession { +impl ServeSession { + pub fn new(imfs: Imfs, tree: RojoTree, root_project: Option) -> Self { let session_id = SessionId::new(); let message_queue = MessageQueue::new(); @@ -22,6 +27,7 @@ impl ServeSession { root_project, tree, message_queue, + imfs, } } diff --git a/src/web/api.rs b/src/web/api.rs index 63f46d34..4bb6eedd 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -9,6 +9,7 @@ use hyper::{header, service::Service, Body, Method, Request, Response, StatusCod use rbx_dom_weak::RbxId; use crate::{ + imfs::new::ImfsFetcher, serve_session::ServeSession, web::{ interface::{ @@ -19,11 +20,11 @@ use crate::{ }, }; -pub struct ApiService { - serve_session: Arc, +pub struct ApiService { + serve_session: Arc>, } -impl Service for ApiService { +impl Service for ApiService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; @@ -42,13 +43,13 @@ impl Service for ApiService { } } -impl ApiService { - pub fn new(serve_session: Arc) -> ApiService { +impl ApiService { + pub fn new(serve_session: Arc>) -> Self { ApiService { serve_session } } /// Get a summary of information about the server - fn handle_api_rojo(&self) -> ::Future { + fn handle_api_rojo(&self) -> ::Future { let tree = self.serve_session.tree(); let root_instance_id = tree.get_root_id(); @@ -63,7 +64,7 @@ impl ApiService { /// Retrieve any messages past the given cursor index, and if /// there weren't any, subscribe to receive any new messages. - fn handle_api_subscribe(&self, request: Request) -> ::Future { + fn handle_api_subscribe(&self, request: Request) -> ::Future { let argument = &request.uri().path()["/api/subscribe/".len()..]; let _input_cursor: u32 = match argument.parse() { Ok(v) => v, @@ -93,7 +94,7 @@ impl ApiService { // }) } - fn handle_api_read(&self, request: Request) -> ::Future { + fn handle_api_read(&self, request: Request) -> ::Future { let argument = &request.uri().path()["/api/read/".len()..]; let requested_ids: Option> = argument.split(',').map(RbxId::parse_str).collect(); diff --git a/src/web/mod.rs b/src/web/mod.rs index 05d55746..10bcc637 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -12,16 +12,16 @@ use futures::{ use hyper::{service::Service, Body, Request, Response, Server}; use log::trace; -use crate::serve_session::ServeSession; +use crate::{imfs::new::ImfsFetcher, serve_session::ServeSession}; use self::{api::ApiService, ui::UiService}; -pub struct RootService { - api: ApiService, - ui: UiService, +pub struct RootService { + api: ApiService, + ui: UiService, } -impl Service for RootService { +impl Service for RootService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; @@ -38,8 +38,8 @@ impl Service for RootService { } } -impl RootService { - pub fn new(serve_session: Arc) -> RootService { +impl RootService { + pub fn new(serve_session: Arc>) -> Self { RootService { api: ApiService::new(Arc::clone(&serve_session)), ui: UiService::new(Arc::clone(&serve_session)), @@ -47,12 +47,12 @@ impl RootService { } } -pub struct LiveServer { - serve_session: Arc, +pub struct LiveServer { + serve_session: Arc>, } -impl LiveServer { - pub fn new(serve_session: Arc) -> LiveServer { +impl LiveServer { + pub fn new(serve_session: Arc>) -> Self { LiveServer { serve_session } } diff --git a/src/web/ui.rs b/src/web/ui.rs index 4212f21a..9d66efa1 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -7,6 +7,7 @@ use hyper::{header, service::Service, Body, Method, Request, Response, StatusCod use ritz::html; use crate::{ + imfs::new::ImfsFetcher, serve_session::ServeSession, web::{ interface::{NotFoundError, SERVER_VERSION}, @@ -16,12 +17,12 @@ use crate::{ static HOME_CSS: &str = include_str!("../../assets/index.css"); -pub struct UiService { +pub struct UiService { #[allow(unused)] // TODO: Fill out interface service - serve_session: Arc, + serve_session: Arc>, } -impl Service for UiService { +impl Service for UiService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; @@ -39,8 +40,8 @@ impl Service for UiService { } } -impl UiService { - pub fn new(serve_session: Arc) -> UiService { +impl UiService { + pub fn new(serve_session: Arc>) -> Self { UiService { serve_session } } From 7a7e9087e67ceef06ba0ec52e21304febde615ba Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Sep 2019 12:57:22 -0700 Subject: [PATCH 0673/1504] Expose imfs from ServeSession --- src/serve_session.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/serve_session.rs b/src/serve_session.rs index 4f4d4e23..eee32144 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -35,6 +35,10 @@ impl ServeSession { &self.tree } + pub fn imfs(&self) -> &Imfs { + &self.imfs + } + pub fn message_queue(&self) -> &MessageQueue<()> { &self.message_queue } From 1d84d3e4405bc61c4a2346a5b97913a18c73e1b0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Sep 2019 12:57:37 -0700 Subject: [PATCH 0674/1504] Wrap RojoTree in Mutex --- src/serve_session.rs | 13 ++++++++----- src/web/api.rs | 4 ++-- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/serve_session.rs b/src/serve_session.rs index eee32144..a26b8184 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -1,4 +1,7 @@ -use std::collections::HashSet; +use std::{ + collections::HashSet, + sync::{Mutex, MutexGuard}, +}; use crate::{ imfs::new::{Imfs, ImfsFetcher}, @@ -12,7 +15,7 @@ use crate::{ pub struct ServeSession { root_project: Option, session_id: SessionId, - tree: RojoTree, + tree: Mutex, message_queue: MessageQueue<()>, // TODO: Real message type imfs: Imfs, } @@ -25,14 +28,14 @@ impl ServeSession { ServeSession { session_id, root_project, - tree, + tree: Mutex::new(tree), message_queue, imfs, } } - pub fn tree(&self) -> &RojoTree { - &self.tree + pub fn tree(&self) -> MutexGuard<'_, RojoTree> { + self.tree.lock().unwrap() } pub fn imfs(&self) -> &Imfs { diff --git a/src/web/api.rs b/src/web/api.rs index 4bb6eedd..4bd676b9 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -13,8 +13,8 @@ use crate::{ serve_session::ServeSession, web::{ interface::{ - Instance, NotFoundError, ReadResponse, ServerInfoResponse, SubscribeResponse, - PROTOCOL_VERSION, SERVER_VERSION, + Instance, NotFoundError, ReadResponse, ServerInfoResponse, PROTOCOL_VERSION, + SERVER_VERSION, }, util::{json, json_ok}, }, From e34ba844c54ffb4dfee47427029c4166a08776f9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Sep 2019 16:00:08 -0700 Subject: [PATCH 0675/1504] Improve diagnostics for failed instance creation --- plugin/src/Reconciler.lua | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 69a24916..66d41fe6 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -50,6 +50,8 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) -- If an instance changes ClassName, we assume it's very different. That's -- not always the case! if virtualInstance.ClassName ~= instance.ClassName then + Logging.trace("Switching to reify for %s because ClassName is different", instance:GetFullName()) + -- TODO: Preserve existing children instead? local parent = instance.Parent self.instanceMap:destroyId(id) @@ -93,6 +95,12 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) unvisitedExistingChildren[existingChildInstance] = nil self:reconcile(virtualInstancesById, childId, existingChildInstance) else + Logging.trace( + "Switching to reify for %s.%s because it does not exist", + instance:GetFullName(), + virtualInstancesById[childId].Name + ) + self:__reify(virtualInstancesById, childId, instance) end end @@ -148,7 +156,13 @@ function Reconciler:__reify(virtualInstancesById, id, parent) local virtualInstance = virtualInstancesById[id] - local instance = Instance.new(virtualInstance.ClassName) + local ok, instance = pcall(function() + return Instance.new(virtualInstance.ClassName) + end) + + if not ok then + error(("Couldn't create an Instance of type %q, a child of %s"):format(virtualInstance.ClassName, parent:GetFullName())) + end for key, value in pairs(virtualInstance.Properties) do setCanonicalProperty(instance, key, rojoValueToRobloxValue(value)) From 5d48d052876fcea2a26d4c7532b85ee2a0cf552c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Sep 2019 17:31:53 -0700 Subject: [PATCH 0676/1504] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8af4578f..cab4f684 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased Changes * Added `--verbose`/`-v` flag, which can be specified multiple times to increase verbosity * Added support for automatically finding Roblox Studio's auth cookie for `rojo upload` on Windows +* Improved diagnostics for when the Rojo plugin cannot create an instance. ## [0.5.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0) (August 27, 2019) * Changed `.model.json` naming, which may require projects to migrate ambiguous cases: From 2e052e97c58b8b0009ca1f736f42e17cc4997584 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Sep 2019 16:48:51 -0700 Subject: [PATCH 0677/1504] Experimental GitHub Action --- .github/workflows/rust.yml | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 .github/workflows/rust.yml diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml new file mode 100644 index 00000000..74b23f50 --- /dev/null +++ b/.github/workflows/rust.yml @@ -0,0 +1,30 @@ +name: Rust + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + strategy: + matrix: + rust_version: [stable, "1.34.0"] + + steps: + - uses: actions/checkout@v1 + + - name: Setup Rust toolchain + run: rustup default ${{ matrix.rust_version }} + + - name: Build + run: cargo build --all --locked --verbose + + - name: Run tests + run: cargo test --all --locked --verbose + + - name: Rustfmt and Clippy + run: | + cargo fmt -- --check + cargo clippy + if: matrix.rust_version == "stable" \ No newline at end of file From cfc3bcfa41f453199063845c591d4c1f65df9c34 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Sep 2019 16:51:40 -0700 Subject: [PATCH 0678/1504] Switch to single quotes for GitHub action workflow --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 74b23f50..cc2abc12 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -27,4 +27,4 @@ jobs: run: | cargo fmt -- --check cargo clippy - if: matrix.rust_version == "stable" \ No newline at end of file + if: matrix.rust_version == 'stable' \ No newline at end of file From 13dafc20916d45e3a2d17bdbfb7b09b455af7aa7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Sep 2019 17:31:00 -0700 Subject: [PATCH 0679/1504] Bump minimum Rust in GitHub actions to 1.36.0 --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index cc2abc12..2c5e07aa 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: - rust_version: [stable, "1.34.0"] + rust_version: [stable, "1.36.0"] steps: - uses: actions/checkout@v1 From 717c15256fd06916d5c5d910a6d7d2c663343f71 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Sep 2019 18:31:02 -0700 Subject: [PATCH 0680/1504] Update GH workflows, bump minimum Rust to 1.36.0 --- .github/workflows/{rust.yml => ci.yml} | 2 +- .github/workflows/release.yml | 41 ++++++++++++++++++++++++++ .travis.yml | 2 +- README.md | 2 +- 4 files changed, 44 insertions(+), 3 deletions(-) rename .github/workflows/{rust.yml => ci.yml} (97%) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/rust.yml b/.github/workflows/ci.yml similarity index 97% rename from .github/workflows/rust.yml rename to .github/workflows/ci.yml index 2c5e07aa..2ad6cf92 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Rust +name: CI on: [push] diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..5d42f5cf --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,41 @@ +name: Release + +on: + release: + types: [created] + +jobs: + windows: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v1 + + - name: Build release binary + run: cargo build --verbose --locked --release + + - name: Upload artifacts + uses: actions/upload-artifact@v1 + with: + name: rojo-win64 + path: target/release/rojo.exe + + macos: + runs-on: macos-latest + + steps: + - uses: actions/checkout@v1 + + - name: Install Rust + run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y + + - name: Build release binary + run: | + source $HOME/.cargo/env + cargo build --verbose --locked --release + + - name: Upload artifacts + uses: actions/upload-artifact@v1 + with: + name: rojo-macos + path: target/release/rojo \ No newline at end of file diff --git a/.travis.yml b/.travis.yml index d37159cd..8a30fe0d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,7 +1,7 @@ matrix: include: - language: rust - rust: 1.34.0 + rust: 1.36.0 cache: cargo script: diff --git a/README.md b/README.md index 2b38a0ee..0aa29821 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions fo Pull requests are welcome! -Rojo supports Rust 1.34.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. +Rojo supports Rust 1.36.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. ## License Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file From c80d9cbf0144293ee84f0a902101cd2c865612a2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Sep 2019 10:46:09 -0700 Subject: [PATCH 0681/1504] Add default-members to make 'cargo t' work better --- Cargo.toml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index 5af52018..61fa2e82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,11 @@ members = [ "rojo-test", ] +default-members = [ + ".", + "rojo-test", +] + [lib] name = "librojo" path = "src/lib.rs" From 9b601eb9fe657b386c635f461a104f4a201cf648 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Sep 2019 10:56:10 -0700 Subject: [PATCH 0682/1504] Tidy up patch structs, add AppliedPatchSet --- src/snapshot/patch.rs | 56 +++++++++++++++++++++++++++++++---- src/snapshot/patch_apply.rs | 14 ++++----- src/snapshot/patch_compute.rs | 14 ++++----- 3 files changed, 62 insertions(+), 22 deletions(-) diff --git a/src/snapshot/patch.rs b/src/snapshot/patch.rs index c89ed885..c3438cca 100644 --- a/src/snapshot/patch.rs +++ b/src/snapshot/patch.rs @@ -7,15 +7,19 @@ use rbx_dom_weak::{RbxId, RbxValue}; use super::{InstanceMetadata, InstanceSnapshot}; /// A set of different kinds of patches that can be applied to an RbxTree. +/// +/// These patches shouldn't be persisted: there's no mechanism in place to make +/// sure that another patch wasn't applied before this one that could cause a +/// conflict! #[derive(Debug, Default, Clone, PartialEq)] pub struct PatchSet<'a> { pub removed_instances: Vec, - pub added_instances: Vec>, - pub updated_instances: Vec, + pub added_instances: Vec>, + pub updated_instances: Vec, } impl<'a> PatchSet<'a> { - pub fn new() -> PatchSet<'a> { + pub fn new() -> Self { PatchSet { removed_instances: Vec::new(), added_instances: Vec::new(), @@ -26,14 +30,14 @@ impl<'a> PatchSet<'a> { /// A patch containing an instance that was added to the tree. #[derive(Debug, Clone, PartialEq)] -pub struct PatchAddInstance<'a> { +pub struct PatchAdd<'a> { pub parent_id: RbxId, pub instance: InstanceSnapshot<'a>, } -/// A patch indicating that properties (or the name) of an instance changed. +/// A patch indicating that properties of an instance changed. #[derive(Debug, Clone, PartialEq)] -pub struct PatchUpdateInstance { +pub struct PatchUpdate { pub id: RbxId, pub changed_name: Option, pub changed_class_name: Option, @@ -45,3 +49,43 @@ pub struct PatchUpdateInstance { /// Changed Rojo-specific metadata, if any of it changed. pub changed_metadata: Option, } + +/// Applied patch sets have the same rough shape as PatchSet, but are +/// descriptive of the operation that happened instead of prescribing what +/// mutations to apply to the tree. +/// +/// Applied patch sets are generated by applying a patch to a tree, and are +/// suitable for sending over the network to a synchronized tree like the Rojo +/// Studio plugin. +/// +// TODO: Introduce machinery to detect conflicts, like keeping previous + +// current values in all fields. +pub struct AppliedPatchSet { + pub removed: Vec, + pub added: Vec, + pub updated: Vec, +} + +impl AppliedPatchSet { + pub fn new() -> Self { + AppliedPatchSet { + removed: Vec::new(), + added: Vec::new(), + updated: Vec::new(), + } + } +} + +pub struct AppliedPatchAdd { + pub instance_id: RbxId, +} + +pub struct AppliedPatchUpdate { + pub id: RbxId, + + // TODO: Store previous values in order to detect application conflicts + pub changed_name: Option, + pub changed_class_name: Option, + pub changed_properties: HashMap>, + pub changed_metadata: Option, +} diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index 78acc584..986f9c17 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -5,7 +5,7 @@ use std::collections::HashMap; use rbx_dom_weak::{RbxId, RbxInstanceProperties, RbxValue}; use super::{ - patch::{PatchSet, PatchUpdateInstance}, + patch::{PatchSet, PatchUpdate}, InstancePropertiesWithMeta, InstanceSnapshot, RojoTree, }; @@ -95,11 +95,7 @@ fn apply_add_child( } } -fn apply_update_child( - context: &PatchApplyContext, - tree: &mut RojoTree, - patch: &PatchUpdateInstance, -) { +fn apply_update_child(context: &PatchApplyContext, tree: &mut RojoTree, patch: &PatchUpdate) { if let Some(metadata) = &patch.changed_metadata { tree.update_metadata(patch.id, metadata.clone()); } @@ -150,7 +146,7 @@ mod test { use maplit::hashmap; use rbx_dom_weak::RbxValue; - use super::super::PatchAddInstance; + use super::super::PatchAdd; #[test] fn add_from_empty() { @@ -179,7 +175,7 @@ mod test { }; let patch_set = PatchSet { - added_instances: vec![PatchAddInstance { + added_instances: vec![PatchAdd { parent_id: root_id, instance: snapshot.clone(), }], @@ -217,7 +213,7 @@ mod test { let root_id = tree.get_root_id(); - let patch = PatchUpdateInstance { + let patch = PatchUpdate { id: root_id, changed_name: Some("Foo".to_owned()), changed_class_name: Some("NewClassName".to_owned()), diff --git a/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs index 13b308b9..f2405df4 100644 --- a/src/snapshot/patch_compute.rs +++ b/src/snapshot/patch_compute.rs @@ -6,7 +6,7 @@ use std::collections::{HashMap, HashSet}; use rbx_dom_weak::{RbxId, RbxValue}; use super::{ - patch::{PatchAddInstance, PatchSet, PatchUpdateInstance}, + patch::{PatchAdd, PatchSet, PatchUpdate}, InstanceSnapshot, InstanceWithMeta, RojoTree, }; @@ -33,7 +33,7 @@ struct ComputePatchContext { snapshot_id_to_instance_id: HashMap, } -fn rewrite_refs_in_updates(context: &ComputePatchContext, updates: &mut [PatchUpdateInstance]) { +fn rewrite_refs_in_updates(context: &ComputePatchContext, updates: &mut [PatchUpdate]) { for update in updates { for property_value in update.changed_properties.values_mut() { if let Some(RbxValue::Ref { value: Some(id) }) = property_value { @@ -47,7 +47,7 @@ fn rewrite_refs_in_updates(context: &ComputePatchContext, updates: &mut [PatchUp } } -fn rewrite_refs_in_additions(context: &ComputePatchContext, additions: &mut [PatchAddInstance]) { +fn rewrite_refs_in_additions(context: &ComputePatchContext, additions: &mut [PatchAdd]) { for addition in additions { rewrite_refs_in_snapshot(context, &mut addition.instance); } @@ -145,7 +145,7 @@ fn compute_property_patches( return; } - patch_set.updated_instances.push(PatchUpdateInstance { + patch_set.updated_instances.push(PatchUpdate { id: instance.id(), changed_name, changed_class_name, @@ -204,7 +204,7 @@ fn compute_children_patches<'a>( ); } None => { - patch_set.added_instances.push(PatchAddInstance { + patch_set.added_instances.push(PatchAdd { parent_id: id, instance: snapshot_child.clone(), }); @@ -269,7 +269,7 @@ mod test { let patch_set = compute_patch_set(&snapshot, &tree, root_id); let expected_patch_set = PatchSet { - updated_instances: vec![PatchUpdateInstance { + updated_instances: vec![PatchUpdate { id: root_id, changed_name: None, changed_class_name: None, @@ -330,7 +330,7 @@ mod test { let patch_set = compute_patch_set(&snapshot, &tree, root_id); let expected_patch_set = PatchSet { - added_instances: vec![PatchAddInstance { + added_instances: vec![PatchAdd { parent_id: root_id, instance: InstanceSnapshot { snapshot_id: None, From ec8861e9830621b7d0897a2095246e7cfc0af430 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Sep 2019 11:10:25 -0700 Subject: [PATCH 0683/1504] Apply patch sets by value in preparation for AppliedPatchSet --- src/commands/build.rs | 2 +- src/commands/serve.rs | 2 +- src/commands/upload.rs | 2 +- src/snapshot/patch_apply.rs | 44 ++++++++++++++++++++----------------- 4 files changed, 27 insertions(+), 23 deletions(-) diff --git a/src/commands/build.rs b/src/commands/build.rs index 1ae1ee48..86ae0bb3 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -105,7 +105,7 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { let patch_set = compute_patch_set(&snapshot, &tree, root_id); log::trace!("Applying patch set"); - apply_patch_set(&mut tree, &patch_set); + apply_patch_set(&mut tree, patch_set); log::trace!("Opening output file for write"); let mut file = BufWriter::new(File::create(&options.output_file)?); diff --git a/src/commands/serve.rs b/src/commands/serve.rs index a29e4439..26ad77d5 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -68,7 +68,7 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { .expect("snapshot did not return an instance"); let patch_set = compute_patch_set(&snapshot, &tree, root_id); - apply_patch_set(&mut tree, &patch_set); + apply_patch_set(&mut tree, patch_set); let session = Arc::new(ServeSession::new(imfs, tree, maybe_project)); let server = LiveServer::new(session); diff --git a/src/commands/upload.rs b/src/commands/upload.rs index 5909e202..df0879b4 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -72,7 +72,7 @@ pub fn upload(options: UploadOptions) -> Result<(), UploadError> { let patch_set = compute_patch_set(&snapshot, &tree, root_id); log::trace!("Applying patch set"); - apply_patch_set(&mut tree, &patch_set); + apply_patch_set(&mut tree, patch_set); let root_id = tree.get_root_id(); diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index 986f9c17..5521f997 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -9,18 +9,18 @@ use super::{ InstancePropertiesWithMeta, InstanceSnapshot, RojoTree, }; -pub fn apply_patch_set(tree: &mut RojoTree, patch_set: &PatchSet) { +pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) { let mut context = PatchApplyContext::default(); - for removed_id in &patch_set.removed_instances { - tree.remove_instance(*removed_id); + for removed_id in patch_set.removed_instances { + tree.remove_instance(removed_id); } - for add_patch in &patch_set.added_instances { + for add_patch in patch_set.added_instances { apply_add_child(&mut context, tree, add_patch.parent_id, &add_patch.instance); } - for update_patch in &patch_set.updated_instances { + for update_patch in patch_set.updated_instances { apply_update_child(&context, tree, update_patch); } @@ -95,43 +95,47 @@ fn apply_add_child( } } -fn apply_update_child(context: &PatchApplyContext, tree: &mut RojoTree, patch: &PatchUpdate) { - if let Some(metadata) = &patch.changed_metadata { - tree.update_metadata(patch.id, metadata.clone()); +fn apply_update_child(context: &PatchApplyContext, tree: &mut RojoTree, patch: PatchUpdate) { + if let Some(metadata) = patch.changed_metadata { + tree.update_metadata(patch.id, metadata); } let mut instance = tree .get_instance_mut(patch.id) .expect("Instance referred to by patch does not exist"); - if let Some(name) = &patch.changed_name { - *instance.name_mut() = name.clone(); + if let Some(name) = patch.changed_name { + *instance.name_mut() = name; } - if let Some(class_name) = &patch.changed_class_name { - *instance.class_name_mut() = class_name.clone(); + if let Some(class_name) = patch.changed_class_name { + *instance.class_name_mut() = class_name; } - for (key, property_entry) in &patch.changed_properties { + for (key, property_entry) in patch.changed_properties { match property_entry { // Ref values need to be potentially rewritten from snapshot IDs to // instance IDs if they referred to an instance that was created as // part of this patch. Some(RbxValue::Ref { value: Some(id) }) => { - let new_id = context.snapshot_id_to_instance_id.get(id).unwrap_or(id); + let new_id = context + .snapshot_id_to_instance_id + .get(&id) + .copied() + .unwrap_or(id); instance.properties_mut().insert( - key.clone(), + key, RbxValue::Ref { - value: Some(*new_id), + value: Some(new_id), }, ); } Some(value) => { - instance.properties_mut().insert(key.clone(), value.clone()); + instance.properties_mut().insert(key, value); } None => { - instance.properties_mut().remove(key); + instance.properties_mut().remove(&key); } } } @@ -182,7 +186,7 @@ mod test { ..Default::default() }; - apply_patch_set(&mut tree, &patch_set); + apply_patch_set(&mut tree, patch_set); let root_instance = tree.get_instance(root_id).unwrap(); let child_id = root_instance.children()[0]; @@ -235,7 +239,7 @@ mod test { ..Default::default() }; - apply_patch_set(&mut tree, &patch_set); + apply_patch_set(&mut tree, patch_set); let expected_properties = hashmap! { "Foo".to_owned() => RbxValue::Int32 { value: 8 }, From 196d27b9596439115aec2af09bae828a0ba20408 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Sep 2019 11:13:27 -0700 Subject: [PATCH 0684/1504] Allow IMFS testing features to be unused --- src/imfs/noop_fetcher.rs | 3 +++ src/imfs/snapshot.rs | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/imfs/noop_fetcher.rs b/src/imfs/noop_fetcher.rs index 02784fd2..be97aa68 100644 --- a/src/imfs/noop_fetcher.rs +++ b/src/imfs/noop_fetcher.rs @@ -1,6 +1,9 @@ //! Implements the IMFS fetcher interface for a fake filesystem using Rust's //! std::fs interface. +// This interface is only used for testing, so it's okay if it isn't used. +#![allow(unused)] + use std::{ io, path::{Path, PathBuf}, diff --git a/src/imfs/snapshot.rs b/src/imfs/snapshot.rs index f84f9b3b..3f12e519 100644 --- a/src/imfs/snapshot.rs +++ b/src/imfs/snapshot.rs @@ -1,3 +1,6 @@ +// This file is non-critical and used for testing, so it's okay if it's unused. +#![allow(unused)] + use std::collections::HashMap; #[derive(Debug, Clone)] From e773a92e53c58dda5f5261e2ee7da7d02e325e31 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Sep 2019 13:12:21 -0700 Subject: [PATCH 0685/1504] Connect message queue to frontend API --- src/web/api.rs | 41 ++++++++++++++++++++++++++--------------- src/web/interface.rs | 3 +-- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/src/web/api.rs b/src/web/api.rs index 4bd676b9..83f4be56 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, sync::Arc}; -use futures::{future, Future}; +use futures::{future, sync::oneshot, Future}; use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; use rbx_dom_weak::RbxId; @@ -13,8 +13,8 @@ use crate::{ serve_session::ServeSession, web::{ interface::{ - Instance, NotFoundError, ReadResponse, ServerInfoResponse, PROTOCOL_VERSION, - SERVER_VERSION, + Instance, NotFoundError, ReadResponse, ServerInfoResponse, SubscribeResponse, + PROTOCOL_VERSION, SERVER_VERSION, }, util::{json, json_ok}, }, @@ -66,7 +66,7 @@ impl ApiService { /// there weren't any, subscribe to receive any new messages. fn handle_api_subscribe(&self, request: Request) -> ::Future { let argument = &request.uri().path()["/api/subscribe/".len()..]; - let _input_cursor: u32 = match argument.parse() { + let input_cursor: u32 = match argument.parse() { Ok(v) => v, Err(err) => { return Box::new(future::ok( @@ -79,19 +79,30 @@ impl ApiService { } }; - // Temporary response to prevent Rojo plugin from sending too many - // requests, this will hang the request until it times out. - Box::new(future::empty()) + let session_id = self.serve_session.session_id(); + let (sender, receiver) = oneshot::channel(); - // let message_queue = self.serve_session.message_queue(); - // let message_cursor = message_queue.cursor(); - // let messages = Vec::new(); + { + let message_queue = self.serve_session.message_queue(); + message_queue.subscribe(input_cursor, sender); + } - // json_ok(SubscribeResponse { - // session_id: self.serve_session.session_id(), - // message_cursor, - // messages, - // }) + Box::new(receiver.then(move |result| { + match result { + Ok((message_cursor, messages)) => json_ok(SubscribeResponse { + session_id, + message_cursor, + messages, + }), + Err(_) => Box::new(future::ok( + Response::builder() + .status(StatusCode::INTERNAL_SERVER_ERROR) + .header(header::CONTENT_TYPE, "text/plain") + .body(Body::from("Message queue disconnected sender!")) + .unwrap(), + )), + } + })) } fn handle_api_read(&self, request: Request) -> ::Future { diff --git a/src/web/interface.rs b/src/web/interface.rs index b62c77f5..7fb0ac26 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -17,8 +17,7 @@ pub(crate) const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); pub const PROTOCOL_VERSION: u64 = 3; // TODO -#[derive(Debug, Serialize, Deserialize)] -pub struct SubscribeMessage; +pub type SubscribeMessage = (); #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] From 44a42a177ab609f274a09b92af71736009f3aaf9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Sep 2019 13:20:58 -0700 Subject: [PATCH 0686/1504] Change API errors to be JSON --- src/web/api.rs | 9 +++++++-- src/web/interface.rs | 21 ++++++++++++++++++++- src/web/ui.rs | 9 +++++++-- 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/web/api.rs b/src/web/api.rs index 83f4be56..99a87675 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -13,7 +13,7 @@ use crate::{ serve_session::ServeSession, web::{ interface::{ - Instance, NotFoundError, ReadResponse, ServerInfoResponse, SubscribeResponse, + ErrorResponse, Instance, ReadResponse, ServerInfoResponse, SubscribeResponse, PROTOCOL_VERSION, SERVER_VERSION, }, util::{json, json_ok}, @@ -38,7 +38,12 @@ impl Service for ApiService { (&Method::GET, path) if path.starts_with("/api/subscribe/") => { self.handle_api_subscribe(request) } - _ => json(NotFoundError, StatusCode::NOT_FOUND), + (_method, path) => { + return json( + ErrorResponse::not_found(format!("Route not found: {}", path)), + StatusCode::NOT_FOUND, + ) + } } } } diff --git a/src/web/interface.rs b/src/web/interface.rs index 7fb0ac26..73d53b6b 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -78,5 +78,24 @@ pub struct SubscribeResponse { pub messages: Vec, } +/// General response type returned from all Rojo routes #[derive(Debug, Serialize, Deserialize)] -pub struct NotFoundError; +#[serde(rename_all = "camelCase")] +pub struct ErrorResponse { + kind: ErrorResponseKind, + details: String, +} + +impl ErrorResponse { + pub fn not_found>(details: S) -> Self { + Self { + kind: ErrorResponseKind::NotFound, + details: details.into(), + } + } +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum ErrorResponseKind { + NotFound, +} diff --git a/src/web/ui.rs b/src/web/ui.rs index 9d66efa1..3d9093e4 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -10,7 +10,7 @@ use crate::{ imfs::new::ImfsFetcher, serve_session::ServeSession, web::{ - interface::{NotFoundError, SERVER_VERSION}, + interface::{ErrorResponse, SERVER_VERSION}, util::json, }, }; @@ -33,7 +33,12 @@ impl Service for UiService { (&Method::GET, "/") => self.handle_home(), (&Method::GET, "/visualize/rbx") => self.handle_visualize_rbx(), (&Method::GET, "/visualize/imfs") => self.handle_visualize_imfs(), - _ => return json(NotFoundError, StatusCode::NOT_FOUND), + (_method, path) => { + return json( + ErrorResponse::not_found(format!("Route not found: {}", path)), + StatusCode::NOT_FOUND, + ) + } }; Box::new(future::ok(response)) From aababf37a8f6f060ca9767e00af3ad9f513a6e00 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Sep 2019 13:50:42 -0700 Subject: [PATCH 0687/1504] Catch more HTTP API errors --- src/web/api.rs | 51 +++++++++++++++++--------------------------- src/web/interface.rs | 16 ++++++++++++++ 2 files changed, 36 insertions(+), 31 deletions(-) diff --git a/src/web/api.rs b/src/web/api.rs index 99a87675..81096767 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -3,9 +3,9 @@ use std::{collections::HashMap, sync::Arc}; -use futures::{future, sync::oneshot, Future}; +use futures::{sync::oneshot, Future}; -use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; +use hyper::{service::Service, Body, Method, Request, StatusCode}; use rbx_dom_weak::RbxId; use crate::{ @@ -74,13 +74,10 @@ impl ApiService { let input_cursor: u32 = match argument.parse() { Ok(v) => v, Err(err) => { - return Box::new(future::ok( - Response::builder() - .status(StatusCode::BAD_REQUEST) - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from(err.to_string())) - .unwrap(), - )); + return json( + ErrorResponse::bad_request(format!("Malformed message cursor: {}", err)), + StatusCode::BAD_REQUEST, + ); } }; @@ -92,21 +89,16 @@ impl ApiService { message_queue.subscribe(input_cursor, sender); } - Box::new(receiver.then(move |result| { - match result { - Ok((message_cursor, messages)) => json_ok(SubscribeResponse { - session_id, - message_cursor, - messages, - }), - Err(_) => Box::new(future::ok( - Response::builder() - .status(StatusCode::INTERNAL_SERVER_ERROR) - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from("Message queue disconnected sender!")) - .unwrap(), - )), - } + Box::new(receiver.then(move |result| match result { + Ok((message_cursor, messages)) => json_ok(SubscribeResponse { + session_id, + message_cursor, + messages, + }), + Err(_) => json( + ErrorResponse::internal_error("Message queue disconnected sender"), + StatusCode::INTERNAL_SERVER_ERROR, + ), })) } @@ -117,13 +109,10 @@ impl ApiService { let requested_ids = match requested_ids { Some(ids) => ids, None => { - return Box::new(future::ok( - Response::builder() - .status(StatusCode::BAD_REQUEST) - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from("Malformed ID list")) - .unwrap(), - )); + return json( + ErrorResponse::bad_request("Malformed ID list"), + StatusCode::BAD_REQUEST, + ); } }; diff --git a/src/web/interface.rs b/src/web/interface.rs index 73d53b6b..ccc7c0c3 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -93,9 +93,25 @@ impl ErrorResponse { details: details.into(), } } + + pub fn bad_request>(details: S) -> Self { + Self { + kind: ErrorResponseKind::BadRequest, + details: details.into(), + } + } + + pub fn internal_error>(details: S) -> Self { + Self { + kind: ErrorResponseKind::InternalError, + details: details.into(), + } + } } #[derive(Debug, Serialize, Deserialize)] pub enum ErrorResponseKind { NotFound, + BadRequest, + InternalError, } From b31ad4b1f835b0c59b2f3a1e285c840d753b16ce Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Sep 2019 13:58:53 -0700 Subject: [PATCH 0688/1504] Update version to 0.6.0-dev --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- plugin/src/Config.lua | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index afba911c..a09f4eb6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1450,7 +1450,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.5.0" +version = "0.6.0-dev" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1491,7 +1491,7 @@ dependencies = [ "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", - "rojo 0.5.0", + "rojo 0.6.0-dev", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 61fa2e82..e775753e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.5.0" +version = "0.6.0-dev" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 3e9ce414..813591a3 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,7 +1,7 @@ return { codename = "Epiphany", - version = {0, 5, 0}, - expectedServerVersionString = "0.5.0 or newer", + version = {0, 6, 0, "-dev"}, + expectedServerVersionString = "0.6.0 or newer", protocolVersion = 3, defaultHost = "localhost", defaultPort = 34872, From fc6f84897f7a84774adaf55877f2856e974c11fc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Sep 2019 14:02:02 -0700 Subject: [PATCH 0689/1504] Update docs link to rojo.space --- src/web/ui.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/web/ui.rs b/src/web/ui.rs index 3d9093e4..10e5129d 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -68,7 +68,7 @@ impl UiService {

"Version " { SERVER_VERSION }

- + "Rojo Documentation" From 71968fca0d161253f40d3ab511a1e17c0e622622 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Sep 2019 15:25:07 -0700 Subject: [PATCH 0690/1504] Fold imfs::new back into imfs --- src/commands/build.rs | 2 +- src/commands/serve.rs | 2 +- src/commands/upload.rs | 2 +- src/imfs/mod.rs | 14 +++++--------- src/serve_session.rs | 2 +- src/snapshot_middleware/csv.rs | 4 ++-- src/snapshot_middleware/dir.rs | 4 ++-- src/snapshot_middleware/json_model.rs | 4 ++-- src/snapshot_middleware/lua.rs | 4 ++-- src/snapshot_middleware/middleware.rs | 5 +---- src/snapshot_middleware/mod.rs | 2 +- src/snapshot_middleware/project.rs | 7 ++----- src/snapshot_middleware/rbxm.rs | 4 ++-- src/snapshot_middleware/rbxmx.rs | 4 ++-- src/snapshot_middleware/txt.rs | 4 ++-- src/web/api.rs | 2 +- src/web/mod.rs | 2 +- src/web/ui.rs | 2 +- 18 files changed, 30 insertions(+), 40 deletions(-) diff --git a/src/commands/build.rs b/src/commands/build.rs index 86ae0bb3..f3dad7bd 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -9,7 +9,7 @@ use failure::Fail; use rbx_dom_weak::RbxInstanceProperties; use crate::{ - imfs::new::{FsError, Imfs, RealFetcher, WatchMode}, + imfs::{FsError, Imfs, RealFetcher, WatchMode}, snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, snapshot_middleware::snapshot_from_imfs, }; diff --git a/src/commands/serve.rs b/src/commands/serve.rs index 26ad77d5..99b33c90 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -4,7 +4,7 @@ use failure::Fail; use rbx_dom_weak::RbxInstanceProperties; use crate::{ - imfs::new::{Imfs, RealFetcher, WatchMode}, + imfs::{Imfs, RealFetcher, WatchMode}, project::{Project, ProjectLoadError}, serve_session::ServeSession, snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, diff --git a/src/commands/upload.rs b/src/commands/upload.rs index df0879b4..0aaee43e 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -6,7 +6,7 @@ use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}; use crate::{ auth_cookie::get_auth_cookie, - imfs::new::{Imfs, RealFetcher, WatchMode}, + imfs::{Imfs, RealFetcher, WatchMode}, snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, snapshot_middleware::snapshot_from_imfs, }; diff --git a/src/imfs/mod.rs b/src/imfs/mod.rs index 3ddfed49..5b403013 100644 --- a/src/imfs/mod.rs +++ b/src/imfs/mod.rs @@ -6,12 +6,8 @@ mod real_fetcher; mod snapshot; pub use error::*; - -pub mod new { - pub use super::error::*; - pub use super::fetcher::*; - pub use super::imfs::*; - pub use super::noop_fetcher::*; - pub use super::real_fetcher::*; - pub use super::snapshot::*; -} +pub use fetcher::*; +pub use imfs::*; +pub use noop_fetcher::*; +pub use real_fetcher::*; +pub use snapshot::*; diff --git a/src/serve_session.rs b/src/serve_session.rs index a26b8184..b7915619 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -4,7 +4,7 @@ use std::{ }; use crate::{ - imfs::new::{Imfs, ImfsFetcher}, + imfs::{Imfs, ImfsFetcher}, message_queue::MessageQueue, project::Project, session_id::SessionId, diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index ba647114..9c87f200 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -5,7 +5,7 @@ use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; use serde::Serialize; use crate::{ - imfs::new::{Imfs, ImfsEntry, ImfsFetcher}, + imfs::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, }; @@ -136,7 +136,7 @@ fn convert_localization_csv(contents: &[u8]) -> String { mod test { use super::*; - use crate::imfs::new::{ImfsSnapshot, NoopFetcher}; + use crate::imfs::{ImfsSnapshot, NoopFetcher}; #[test] fn csv_from_imfs() { diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 36170297..1e8d50d3 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -3,7 +3,7 @@ use std::{borrow::Cow, collections::HashMap}; use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ - imfs::new::{DirectorySnapshot, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, + imfs::{DirectorySnapshot, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, snapshot::InstanceSnapshot, }; @@ -78,7 +78,7 @@ mod test { use maplit::hashmap; - use crate::imfs::new::NoopFetcher; + use crate::imfs::NoopFetcher; #[test] fn empty_folder() { diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 8420372e..6b026557 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -5,7 +5,7 @@ use rbx_reflection::try_resolve_value; use serde::Deserialize; use crate::{ - imfs::new::{Imfs, ImfsEntry, ImfsFetcher}, + imfs::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, }; @@ -136,7 +136,7 @@ mod test { use maplit::hashmap; use rbx_dom_weak::RbxValue; - use crate::imfs::new::{ImfsSnapshot, NoopFetcher}; + use crate::imfs::{ImfsSnapshot, NoopFetcher}; #[test] fn model_from_imfs() { diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 1b71416d..779fc740 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -4,7 +4,7 @@ use maplit::hashmap; use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; use crate::{ - imfs::new::{FsResultExt, Imfs, ImfsEntry, ImfsFetcher}, + imfs::{FsResultExt, Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, }; @@ -141,7 +141,7 @@ mod test { use maplit::hashmap; - use crate::imfs::new::{ImfsSnapshot, NoopFetcher}; + use crate::imfs::{ImfsSnapshot, NoopFetcher}; #[test] fn module_from_imfs() { diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index 045d1bde..04c6ec94 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -3,10 +3,7 @@ use std::path::{Path, PathBuf}; use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ - imfs::{ - new::{Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, - FsResult, - }, + imfs::{FsResult, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, snapshot::InstanceSnapshot, }; diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 840d4d35..9b2c4980 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -28,7 +28,7 @@ use self::{ rbxmx::SnapshotRbxmx, txt::SnapshotTxt, }; -use crate::imfs::new::{Imfs, ImfsEntry, ImfsFetcher}; +use crate::imfs::{Imfs, ImfsEntry, ImfsFetcher}; macro_rules! middlewares { ( $($middleware: ident,)* ) => { diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 72fa3706..4f68fe1c 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -4,10 +4,7 @@ use rbx_dom_weak::{RbxId, RbxTree}; use rbx_reflection::try_resolve_value; use crate::{ - imfs::{ - new::{Imfs, ImfsEntry, ImfsFetcher}, - FsErrorKind, - }, + imfs::{FsErrorKind, Imfs, ImfsEntry, ImfsFetcher}, project::{Project, ProjectNode}, snapshot::{InstanceMetadata, InstanceSnapshot}, }; @@ -146,7 +143,7 @@ mod test { use maplit::hashmap; use rbx_dom_weak::RbxValue; - use crate::imfs::new::{ImfsSnapshot, NoopFetcher}; + use crate::imfs::{ImfsSnapshot, NoopFetcher}; #[test] fn project_from_folder() { diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 47e8ab29..210d64ee 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -3,7 +3,7 @@ use std::{borrow::Cow, collections::HashMap}; use rbx_dom_weak::{RbxId, RbxInstanceProperties, RbxTree}; use crate::{ - imfs::new::{Imfs, ImfsEntry, ImfsFetcher}, + imfs::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, }; @@ -66,7 +66,7 @@ impl SnapshotMiddleware for SnapshotRbxm { mod test { use super::*; - use crate::imfs::new::{ImfsSnapshot, NoopFetcher}; + use crate::imfs::{ImfsSnapshot, NoopFetcher}; #[test] fn model_from_imfs() { diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 6d0aa78b..3f0c2814 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ - imfs::new::{Imfs, ImfsEntry, ImfsFetcher}, + imfs::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, }; @@ -64,7 +64,7 @@ mod test { use std::collections::HashMap; - use crate::imfs::new::{ImfsSnapshot, NoopFetcher}; + use crate::imfs::{ImfsSnapshot, NoopFetcher}; #[test] fn model_from_imfs() { diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 98155c10..ea750b42 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -4,7 +4,7 @@ use maplit::hashmap; use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; use crate::{ - imfs::new::{FileSnapshot, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, + imfs::{FileSnapshot, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, snapshot::InstanceSnapshot, }; @@ -94,7 +94,7 @@ mod test { use maplit::hashmap; use rbx_dom_weak::RbxInstanceProperties; - use crate::imfs::new::NoopFetcher; + use crate::imfs::NoopFetcher; #[test] fn instance_from_imfs() { diff --git a/src/web/api.rs b/src/web/api.rs index 81096767..1903de90 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -9,7 +9,7 @@ use hyper::{service::Service, Body, Method, Request, StatusCode}; use rbx_dom_weak::RbxId; use crate::{ - imfs::new::ImfsFetcher, + imfs::ImfsFetcher, serve_session::ServeSession, web::{ interface::{ diff --git a/src/web/mod.rs b/src/web/mod.rs index 10bcc637..ab8242d2 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -12,7 +12,7 @@ use futures::{ use hyper::{service::Service, Body, Request, Response, Server}; use log::trace; -use crate::{imfs::new::ImfsFetcher, serve_session::ServeSession}; +use crate::{imfs::ImfsFetcher, serve_session::ServeSession}; use self::{api::ApiService, ui::UiService}; diff --git a/src/web/ui.rs b/src/web/ui.rs index 10e5129d..45945fe4 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -7,7 +7,7 @@ use hyper::{header, service::Service, Body, Method, Request, Response, StatusCod use ritz::html; use crate::{ - imfs::new::ImfsFetcher, + imfs::ImfsFetcher, serve_session::ServeSession, web::{ interface::{ErrorResponse, SERVER_VERSION}, From 500a9f647fc40792d4da62b9b68ae7743114b3cc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Sep 2019 15:26:31 -0700 Subject: [PATCH 0691/1504] Fix snapshot test with new version number --- rojo-test/serve-test-snapshots/serve_test__empty.snap | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rojo-test/serve-test-snapshots/serve_test__empty.snap b/rojo-test/serve-test-snapshots/serve_test__empty.snap index 4ecdb7ea..5f830821 100644 --- a/rojo-test/serve-test-snapshots/serve_test__empty.snap +++ b/rojo-test/serve-test-snapshots/serve_test__empty.snap @@ -3,7 +3,7 @@ source: rojo-test/src/serve_test.rs expression: info --- sessionId: id-1 -serverVersion: 0.5.0 +serverVersion: 0.6.0-dev protocolVersion: 3 expectedPlaceIds: ~ rootInstanceId: id-2 From 8c6981da0d529a3728e81eaebe29b7dfea2f1007 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 20 Sep 2019 11:06:01 -0700 Subject: [PATCH 0692/1504] Fix guide to point to release versions instead of alphas --- docs/guide/installation.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/guide/installation.md b/docs/guide/installation.md index dabd1f75..4b360327 100644 --- a/docs/guide/installation.md +++ b/docs/guide/installation.md @@ -26,12 +26,14 @@ The Rojo CLI must be run from the command line, like Terminal.app on MacOS or `c ### Installing from Cargo If you have Rust installed, the easiest way to get Rojo is with Cargo! -To install the latest 0.5.0 alpha, use: +To install the latest 0.5.x release, use: ```sh -cargo install rojo --version 0.5.0-alpha.13 +cargo install rojo ``` +If you're upgrading from a previous version of Rojo, you may need to pass `--force` to tell Cargo to overwrite your existing version. + ## Installing the Plugin ### Installing from GitHub @@ -43,4 +45,4 @@ Download the attached `rbxm` file and put it into your Roblox Studio plugins fol {: align="center" } ### Installing from Roblox.com -Visit [Rojo's roblox.com plugin page](https://www.roblox.com/library/1997686364/Rojo-0-5-0-alpha-3) in Roblox Studio and press **Install**. +Visit [Rojo's Roblox.com Plugin page](https://www.roblox.com/library/1997686364) in Roblox Studio and press **Install**. \ No newline at end of file From a46d467b753bae665cbc350631353294ca7f98c8 Mon Sep 17 00:00:00 2001 From: boyned//Kampfkarren Date: Sun, 22 Sep 2019 17:37:00 -0700 Subject: [PATCH 0693/1504] Fix broken link to sync details (#248) --- docs/guide/migrating-to-epiphany.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guide/migrating-to-epiphany.md b/docs/guide/migrating-to-epiphany.md index 87acf09c..84709146 100644 --- a/docs/guide/migrating-to-epiphany.md +++ b/docs/guide/migrating-to-epiphany.md @@ -60,4 +60,4 @@ Unknown files are now ignored in Rojo instead of being converted to `StringValue ## Migrating `init.model.json` files In Rojo 0.4.x, it's possible to create a file named `init.model.json` that lets you describe a model that becomes the container for all of the other files in the folder, just like `init.lua`. -In Rojo 0.5.x, this feature has been replaced with `init.meta.json` files. See [Sync Details](../reference/sync-details) for more information about these new files. \ No newline at end of file +In Rojo 0.5.x, this feature has been replaced with `init.meta.json` files. See [Sync Details](../../reference/sync-details) for more information about these new files. From bd33aebc3defd9fca07de34609445322f0419bba Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 23 Sep 2019 10:53:11 -0700 Subject: [PATCH 0694/1504] Turn messages into stub SubscribeMessage struct --- src/serve_session.rs | 5 +++-- src/snapshot/patch.rs | 3 +++ src/snapshot/patch_apply.rs | 7 +++++-- src/web/api.rs | 22 +++++++++++++++------- src/web/interface.rs | 3 ++- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/serve_session.rs b/src/serve_session.rs index b7915619..327b66c7 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -8,6 +8,7 @@ use crate::{ message_queue::MessageQueue, project::Project, session_id::SessionId, + snapshot::AppliedPatchSet, snapshot::RojoTree, }; @@ -16,7 +17,7 @@ pub struct ServeSession { root_project: Option, session_id: SessionId, tree: Mutex, - message_queue: MessageQueue<()>, // TODO: Real message type + message_queue: MessageQueue, imfs: Imfs, } @@ -42,7 +43,7 @@ impl ServeSession { &self.imfs } - pub fn message_queue(&self) -> &MessageQueue<()> { + pub fn message_queue(&self) -> &MessageQueue { &self.message_queue } diff --git a/src/snapshot/patch.rs b/src/snapshot/patch.rs index c3438cca..ca77df7c 100644 --- a/src/snapshot/patch.rs +++ b/src/snapshot/patch.rs @@ -60,6 +60,7 @@ pub struct PatchUpdate { /// // TODO: Introduce machinery to detect conflicts, like keeping previous + // current values in all fields. +#[derive(Debug, Clone)] pub struct AppliedPatchSet { pub removed: Vec, pub added: Vec, @@ -76,10 +77,12 @@ impl AppliedPatchSet { } } +#[derive(Debug, Clone)] pub struct AppliedPatchAdd { pub instance_id: RbxId, } +#[derive(Debug, Clone)] pub struct AppliedPatchUpdate { pub id: RbxId, diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index 5521f997..0d7c9b78 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -5,11 +5,11 @@ use std::collections::HashMap; use rbx_dom_weak::{RbxId, RbxInstanceProperties, RbxValue}; use super::{ - patch::{PatchSet, PatchUpdate}, + patch::{AppliedPatchSet, PatchSet, PatchUpdate}, InstancePropertiesWithMeta, InstanceSnapshot, RojoTree, }; -pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) { +pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) -> AppliedPatchSet { let mut context = PatchApplyContext::default(); for removed_id in patch_set.removed_instances { @@ -25,6 +25,9 @@ pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) { } apply_deferred_properties(context, tree); + + // TODO: Actually calculate patch set + AppliedPatchSet::new() } #[derive(Default)] diff --git a/src/web/api.rs b/src/web/api.rs index 1903de90..6793e089 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -13,8 +13,8 @@ use crate::{ serve_session::ServeSession, web::{ interface::{ - ErrorResponse, Instance, ReadResponse, ServerInfoResponse, SubscribeResponse, - PROTOCOL_VERSION, SERVER_VERSION, + ErrorResponse, Instance, ReadResponse, ServerInfoResponse, SubscribeMessage, + SubscribeResponse, PROTOCOL_VERSION, SERVER_VERSION, }, util::{json, json_ok}, }, @@ -90,11 +90,19 @@ impl ApiService { } Box::new(receiver.then(move |result| match result { - Ok((message_cursor, messages)) => json_ok(SubscribeResponse { - session_id, - message_cursor, - messages, - }), + Ok((message_cursor, messages)) => { + // TODO: Transform applied patch sets into subscribe responses + let api_messages = messages + .into_iter() + .map(|_message| SubscribeMessage) + .collect(); + + json_ok(SubscribeResponse { + session_id, + message_cursor, + messages: api_messages, + }) + } Err(_) => json( ErrorResponse::internal_error("Message queue disconnected sender"), StatusCode::INTERNAL_SERVER_ERROR, diff --git a/src/web/interface.rs b/src/web/interface.rs index ccc7c0c3..c2fd3ca5 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -17,7 +17,8 @@ pub(crate) const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); pub const PROTOCOL_VERSION: u64 = 3; // TODO -pub type SubscribeMessage = (); +#[derive(Debug, Serialize, Deserialize)] +pub struct SubscribeMessage; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] From 2440d9fc48f5af76fc45c35c3d11cbf939d594e0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 23 Sep 2019 16:09:58 -0700 Subject: [PATCH 0695/1504] Create ChangeProcessor for routing events from imfs to tree to message queue --- src/change_processor.rs | 84 +++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/serve_session.rs | 78 ++++++++++++++++++++++++++++++++------ 3 files changed, 152 insertions(+), 11 deletions(-) create mode 100644 src/change_processor.rs diff --git a/src/change_processor.rs b/src/change_processor.rs new file mode 100644 index 00000000..0220025f --- /dev/null +++ b/src/change_processor.rs @@ -0,0 +1,84 @@ +//! Defines the process by which changes are pulled from the Imfs, filtered, and +//! used to mutate Rojo's tree during a live session. +//! +//! This object is owned by a ServeSession. + +use std::sync::{Arc, Mutex}; + +use crossbeam_channel::{select, Sender}; +use jod_thread::JoinHandle; + +use crate::{ + imfs::{Imfs, ImfsFetcher}, + message_queue::MessageQueue, + snapshot::{AppliedPatchSet, RojoTree}, +}; + +pub struct ChangeProcessor { + shutdown_sender: Sender<()>, + thread_handle: JoinHandle<()>, +} + +impl ChangeProcessor { + pub fn start( + tree: Arc>, + message_queue: Arc>, + imfs: Arc>>, + ) -> Self { + let (shutdown_sender, shutdown_receiver) = crossbeam_channel::bounded(1); + let imfs_receiver = { + let imfs = imfs.lock().unwrap(); + imfs.change_receiver() + }; + + let thread_handle = jod_thread::Builder::new() + .name("ChangeProcessor thread".to_owned()) + .spawn(move || { + log::trace!("ChangeProcessor thread started"); + + loop { + select! { + recv(imfs_receiver) -> event => { + let event = event.unwrap(); + + log::trace!("Imfs event: {:?}", event); + + { + let mut imfs = imfs.lock().unwrap(); + imfs.commit_change(&event).expect("Error applying IMFS change"); + } + + let patch_set = { + let _tree = tree.lock().unwrap(); + + // TODO: Apply changes to tree based on IMFS and + // calculate applied patch set from it. + AppliedPatchSet::new() + }; + + { + message_queue.push_messages(&[patch_set]); + } + }, + recv(shutdown_receiver) -> _ => { + break; + }, + } + } + + log::trace!("ChangeProcessor thread stopping"); + }) + .expect("Could not start ChangeProcessor thread"); + + Self { + shutdown_sender, + thread_handle, + } + } +} + +impl Drop for ChangeProcessor { + fn drop(&mut self) { + let _ = self.shutdown_sender.send(()); + } +} diff --git a/src/lib.rs b/src/lib.rs index 1c7603ef..f190593c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,6 +13,7 @@ pub mod commands; pub mod project; mod auth_cookie; +mod change_processor; mod imfs; mod message_queue; mod multimap; diff --git a/src/serve_session.rs b/src/serve_session.rs index 327b66c7..c1e37aeb 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -1,46 +1,102 @@ use std::{ collections::HashSet, - sync::{Mutex, MutexGuard}, + sync::{Arc, Mutex, MutexGuard}, }; use crate::{ + change_processor::ChangeProcessor, imfs::{Imfs, ImfsFetcher}, message_queue::MessageQueue, project::Project, session_id::SessionId, - snapshot::AppliedPatchSet, - snapshot::RojoTree, + snapshot::{AppliedPatchSet, RojoTree}, }; /// Contains all of the state for a Rojo serve session. +/// +/// Nothing here is specific to any Rojo interface. Though the primary way to +/// interact with a serve session is Rojo's HTTP right now, there's no reason +/// why Rojo couldn't expose an IPC or channels-based API for embedding in the +/// future. `ServeSession` would be roughly the right interface to expose for +/// those cases. pub struct ServeSession { + /// The root project for the serve session, if there was one defined. + /// + /// This will be defined if a folder with a `default.project.json` file was + /// used for starting the serve session, or if the user specified a full + /// path to a `.project.json` file. + /// + /// If `root_project` is None, values from the project should be treated as + /// their defaults. root_project: Option, + + /// A randomly generated ID for this serve session. It's used to ensure that + /// a client doesn't begin connecting to a different server part way through + /// an operation that needs to be atomic. session_id: SessionId, - tree: Mutex, - message_queue: MessageQueue, - imfs: Imfs, + + /// The tree of Roblox instances associated with this session that will be + /// updated in real-time. This is derived from the session's IMFS and will + /// eventually be mutable to connected clients. + tree: Arc>, + + /// An in-memory filesystem containing all of the files relevant for this + /// live session. + /// + /// The main use for accessing it from the session is for debugging issues + /// with Rojo's live-sync protocol. + imfs: Arc>>, + + /// A queue of changes that have been applied to `tree` that affect clients. + /// + /// Clients to the serve session will subscribe to this queue either + /// directly or through the HTTP API to be notified of mutations that need + /// to be applied. + message_queue: Arc>, + + /// The object responsible for listening to changes from the in-memory + /// filesystem, applying them, updating the Roblox instance tree, and + /// routing messages through the session's message queue to any connected + /// clients. + change_processor: ChangeProcessor, } -impl ServeSession { +/// Methods that need thread-safety bounds on ImfsFetcher are limited to this +/// block to prevent needing to spread Send + Sync + 'static into everything +/// that handles ServeSession. +impl ServeSession { pub fn new(imfs: Imfs, tree: RojoTree, root_project: Option) -> Self { let session_id = SessionId::new(); let message_queue = MessageQueue::new(); - ServeSession { + let tree = Arc::new(Mutex::new(tree)); + let message_queue = Arc::new(message_queue); + let imfs = Arc::new(Mutex::new(imfs)); + + let change_processor = ChangeProcessor::start( + Arc::clone(&tree), + Arc::clone(&message_queue), + Arc::clone(&imfs), + ); + + Self { session_id, root_project, - tree: Mutex::new(tree), + tree, message_queue, imfs, + change_processor, } } +} +impl ServeSession { pub fn tree(&self) -> MutexGuard<'_, RojoTree> { self.tree.lock().unwrap() } - pub fn imfs(&self) -> &Imfs { - &self.imfs + pub fn imfs(&self) -> MutexGuard<'_, Imfs> { + self.imfs.lock().unwrap() } pub fn message_queue(&self) -> &MessageQueue { From 5a4189a7700255ab025af99b41700a4adbd9ee3b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 23 Sep 2019 16:13:19 -0700 Subject: [PATCH 0696/1504] Move ChangeReceiver main block into its own function --- src/change_processor.rs | 88 ++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 40 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index 0220025f..8e2f7f02 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -5,7 +5,7 @@ use std::sync::{Arc, Mutex}; -use crossbeam_channel::{select, Sender}; +use crossbeam_channel::{select, Receiver, Sender}; use jod_thread::JoinHandle; use crate::{ @@ -26,48 +26,10 @@ impl ChangeProcessor { imfs: Arc>>, ) -> Self { let (shutdown_sender, shutdown_receiver) = crossbeam_channel::bounded(1); - let imfs_receiver = { - let imfs = imfs.lock().unwrap(); - imfs.change_receiver() - }; let thread_handle = jod_thread::Builder::new() .name("ChangeProcessor thread".to_owned()) - .spawn(move || { - log::trace!("ChangeProcessor thread started"); - - loop { - select! { - recv(imfs_receiver) -> event => { - let event = event.unwrap(); - - log::trace!("Imfs event: {:?}", event); - - { - let mut imfs = imfs.lock().unwrap(); - imfs.commit_change(&event).expect("Error applying IMFS change"); - } - - let patch_set = { - let _tree = tree.lock().unwrap(); - - // TODO: Apply changes to tree based on IMFS and - // calculate applied patch set from it. - AppliedPatchSet::new() - }; - - { - message_queue.push_messages(&[patch_set]); - } - }, - recv(shutdown_receiver) -> _ => { - break; - }, - } - } - - log::trace!("ChangeProcessor thread stopping"); - }) + .spawn(move || Self::main_task(shutdown_receiver, tree, message_queue, imfs)) .expect("Could not start ChangeProcessor thread"); Self { @@ -75,6 +37,52 @@ impl ChangeProcessor { thread_handle, } } + + fn main_task( + shutdown_receiver: Receiver<()>, + tree: Arc>, + message_queue: Arc>, + imfs: Arc>>, + ) { + log::trace!("ChangeProcessor thread started"); + + let imfs_receiver = { + let imfs = imfs.lock().unwrap(); + imfs.change_receiver() + }; + + loop { + select! { + recv(imfs_receiver) -> event => { + let event = event.unwrap(); + + log::trace!("Imfs event: {:?}", event); + + { + let mut imfs = imfs.lock().unwrap(); + imfs.commit_change(&event).expect("Error applying IMFS change"); + } + + let patch_set = { + let _tree = tree.lock().unwrap(); + + // TODO: Apply changes to tree based on IMFS and + // calculate applied patch set from it. + AppliedPatchSet::new() + }; + + { + message_queue.push_messages(&[patch_set]); + } + }, + recv(shutdown_receiver) -> _ => { + break; + }, + } + } + + log::trace!("ChangeProcessor thread stopping"); + } } impl Drop for ChangeProcessor { From 5630cea9a0166fa434c2c91b3b2590aa776503da Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 23 Sep 2019 17:54:04 -0700 Subject: [PATCH 0697/1504] Improve command line and web interface --- Cargo.lock | 8 +++-- Cargo.toml | 4 ++- assets/icon-32.png | Bin 0 -> 975 bytes assets/index.css | 53 +++++++++++++++++++++++------ src/commands/serve.rs | 48 +++++++++++++++++++------- src/lib.rs | 2 +- src/serve_session.rs | 18 ++++++++++ src/web/ui.rs | 77 ++++++++++++++++++++++++++++++++++-------- 8 files changed, 168 insertions(+), 42 deletions(-) create mode 100644 assets/icon-32.png diff --git a/Cargo.lock b/Cargo.lock index a09f4eb6..0b0e216e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -376,7 +376,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -578,7 +578,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "humantime" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1458,6 +1458,7 @@ dependencies = [ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1476,6 +1477,7 @@ dependencies = [ "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2194,7 +2196,7 @@ dependencies = [ "checksum http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "372bcb56f939e449117fb0869c2e8fd8753a8223d92a172c6e808cf123a5b6e4" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" -"checksum humantime 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3ca7e5f2e110db35f93b837c81797f3714500b81d517bf20c431b16d3ca4f114" +"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" "checksum hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)" = "7cb44cbce9d8ee4fb36e4c0ad7b794ac44ebaad924b9c8291a63215bb44c2c8f" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" diff --git a/Cargo.toml b/Cargo.toml index e775753e..d9530ff1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,8 +37,8 @@ csv = "1.0" env_logger = "0.6" failure = "0.1.3" futures = "0.1" +humantime = "1.3.0" hyper = "0.12" -reqwest = "0.9.20" jod-thread = "0.1.0" log = "0.4" maplit = "1.0.1" @@ -48,9 +48,11 @@ rbx_dom_weak = "1.9.0" rbx_reflection = "3.1.388" rbx_xml = "0.11.0" regex = "1.0" +reqwest = "0.9.20" ritz = "0.1.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +termcolor = "1.0.5" uuid = { version = "0.7", features = ["v4", "serde"] } [target.'cfg(windows)'.dependencies] diff --git a/assets/icon-32.png b/assets/icon-32.png new file mode 100644 index 0000000000000000000000000000000000000000..d3beb2f81caf4385da98ce4c2e07cbc27aed037e GIT binary patch literal 975 zcmV;=12FuFP)W89RdqSW`s;bQcZfkLc{aDu-s+!nr3?VZ9@z??)a97!H40^9H8yzp$H*BuYxP2t zwI<`0?y}O}ima?^{<}yb5qdD;z4c*f`K5P#{paZF+7P4DF-Ou4n8_MOr%mVP(m{(- z@EWJp(&Vo>w~1d*d09Uw7(QFQOy)p^*td^Q6hEiGm1EC9KM>_DlT*$p%Z6VE7rQZc z$Y3y$V8fi4vS@-0E8Xxe0D*Yi&+#`j7K?o+b2svG8|X-vQWj+sVNe9X-1lHeefa~HwJxnDP=T0d|k2t@Wo-ZxM_uAN?{m4Nt(h7QdG$XfNa>w@A-DII^nhz zwvjl2@tdRLm*mEPPV9yKXug9EzP?cSy%4~j@{|2!9i-Ji?V@8SX%E=V`3^GfoLlIi z-@)B3Ye5r<4^n*KcDb&X1c05BU~A7{#dh0SrVUo;Sgz7X?h3tt2C(jO^ZBgi9?`G!|PMMi%`y09$thHq2eydT@sTH7hI| x3B)%hw+(M1gSac*xMsfunS#Kit0$eZe*qDW+=wbZuYv#o002ovPDHLkV1iYovd91c literal 0 HcmV?d00001 diff --git a/assets/index.css b/assets/index.css index 7621a0d9..c0a1e687 100644 --- a/assets/index.css +++ b/assets/index.css @@ -1,11 +1,17 @@ * { margin: 0; padding: 0; + border: none; + text-decoration: inherit; + color: inherit; font: inherit; + box-sizing: inherit; } html { + box-sizing: border-box; font-family: sans-serif; + text-decoration: none; height: 100%; } @@ -17,27 +23,54 @@ body { } .main { + flex: 0 0; + display: flex; + flex-direction: column; padding: 1rem; - text-align: center; margin: 0 auto; width: 100%; - max-width: 60rem; + max-width: 50rem; background-color: #efefef; border: 1px solid #666; border-radius: 4px; } -.title { - font-size: 2rem; +.header { + flex: 0 0; + display: flex; + justify-content: space-around; + align-items: center; + margin-bottom: 1rem; +} + +.main-logo { + flex: 0 0; + width: 20rem; +} + +.stats { + flex: 0 0 20rem; + padding: 0 1rem; +} + +.stat { + display: block; +} + +.stat-name { + display: inline; font-weight: bold; } -.subtitle { - font-size: 1.5rem; - font-weight: bold; +.button-list { + flex: 0 0; + display: flex; + justify-content: space-around; } -.docs { - font-size: 1.3rem; - font-weight: bold; +.button { + display: inline-block; + border: 1px solid #666; + padding: 0.3em 1em; + margin: 0 0.2rem; } \ No newline at end of file diff --git a/src/commands/serve.rs b/src/commands/serve.rs index 99b33c90..aeded2cd 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -1,7 +1,13 @@ -use std::{collections::HashMap, path::PathBuf, sync::Arc}; +use std::{ + collections::HashMap, + io::{self, Write}, + path::PathBuf, + sync::Arc, +}; use failure::Fail; use rbx_dom_weak::RbxInstanceProperties; +use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; use crate::{ imfs::{Imfs, RealFetcher, WatchMode}, @@ -46,7 +52,7 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { }) .unwrap_or(DEFAULT_PORT); - println!("Rojo server listening on port {}", port); + let _ = show_start_message(port); let mut tree = RojoTree::new(InstancePropertiesWithMeta { properties: RbxInstanceProperties { @@ -75,20 +81,36 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { server.start(port); - // let receiver = imfs.change_receiver(); + Ok(()) +} - // while let Ok(change) = receiver.recv() { - // imfs.commit_change(&change) - // .expect("Failed to commit Imfs change"); +fn show_start_message(port: u16) -> io::Result<()> { + let mut writer = BufferWriter::stderr(ColorChoice::Auto); + let mut buffer = writer.buffer(); - // use notify::DebouncedEvent; - // if let DebouncedEvent::Write(path) = change { - // let contents = imfs.get_contents(path) - // .expect("Failed to read changed path"); + writeln!(&mut buffer, "Rojo server listening:")?; - // println!("{:?}", std::str::from_utf8(contents)); - // } - // } + write!(&mut buffer, " Address: ")?; + buffer.set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))?; + writeln!(&mut buffer, "localhost")?; + + buffer.set_color(&ColorSpec::new())?; + write!(&mut buffer, " Port: ")?; + buffer.set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))?; + writeln!(&mut buffer, "{}", port)?; + + writeln!(&mut buffer, "")?; + + buffer.set_color(&ColorSpec::new())?; + write!(&mut buffer, "Visit ")?; + + buffer.set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))?; + write!(&mut buffer, "http://localhost:{}/", port)?; + + buffer.set_color(&ColorSpec::new())?; + writeln!(&mut buffer, " in your browser for more information.")?; + + writer.print(&buffer)?; Ok(()) } diff --git a/src/lib.rs b/src/lib.rs index f190593c..a8999ccc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ // Recursion limit bump is to support Ritz, a JSX-like proc macro used for // Rojo's web UI currently. -#![recursion_limit = "128"] +#![recursion_limit = "1024"] #[macro_use] mod impl_from; diff --git a/src/serve_session.rs b/src/serve_session.rs index c1e37aeb..e978daf6 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -1,6 +1,7 @@ use std::{ collections::HashSet, sync::{Arc, Mutex, MutexGuard}, + time::Instant, }; use crate::{ @@ -20,6 +21,10 @@ use crate::{ /// future. `ServeSession` would be roughly the right interface to expose for /// those cases. pub struct ServeSession { + /// When the serve session was started. Used only for user-facing + /// diagnostics. + start_time: Instant, + /// The root project for the serve session, if there was one defined. /// /// This will be defined if a folder with a `default.project.json` file was @@ -66,6 +71,8 @@ pub struct ServeSession { /// that handles ServeSession. impl ServeSession { pub fn new(imfs: Imfs, tree: RojoTree, root_project: Option) -> Self { + let start_time = Instant::now(); + let session_id = SessionId::new(); let message_queue = MessageQueue::new(); @@ -80,6 +87,7 @@ impl ServeSession { ); Self { + start_time, session_id, root_project, tree, @@ -107,6 +115,16 @@ impl ServeSession { self.session_id } + pub fn project_name(&self) -> Option<&str> { + self.root_project + .as_ref() + .map(|project| project.name.as_str()) + } + + pub fn start_time(&self) -> Instant { + self.start_time + } + pub fn serve_place_ids(&self) -> Option<&HashSet> { self.root_project .as_ref() diff --git a/src/web/ui.rs b/src/web/ui.rs index 45945fe4..fcb6b5ce 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -1,6 +1,6 @@ //! Defines the HTTP-based UI. These endpoints generally return HTML and SVG. -use std::sync::Arc; +use std::{sync::Arc, time::Duration}; use futures::{future, Future}; use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; @@ -15,10 +15,11 @@ use crate::{ }, }; +static LOGO: &[u8] = include_bytes!("../../assets/logo-512.png"); +static ICON: &[u8] = include_bytes!("../../assets/icon-32.png"); static HOME_CSS: &str = include_str!("../../assets/index.css"); pub struct UiService { - #[allow(unused)] // TODO: Fill out interface service serve_session: Arc>, } @@ -31,6 +32,8 @@ impl Service for UiService { fn call(&mut self, request: Request) -> Self::Future { let response = match (request.method(), request.uri().path()) { (&Method::GET, "/") => self.handle_home(), + (&Method::GET, "/logo.png") => self.handle_logo(), + (&Method::GET, "/icon.png") => self.handle_icon(), (&Method::GET, "/visualize/rbx") => self.handle_visualize_rbx(), (&Method::GET, "/visualize/imfs") => self.handle_visualize_imfs(), (_method, path) => { @@ -50,28 +53,74 @@ impl UiService { UiService { serve_session } } + fn handle_logo(&self) -> Response { + Response::builder() + .header(header::CONTENT_TYPE, "image/png") + .body(Body::from(LOGO)) + .unwrap() + } + + fn handle_icon(&self) -> Response { + Response::builder() + .header(header::CONTENT_TYPE, "image/png") + .body(Body::from(ICON)) + .unwrap() + } + fn handle_home(&self) -> Response { + let project_name = self.serve_session.project_name().unwrap_or(""); + let uptime = { + let elapsed = self.serve_session.start_time().elapsed(); + + // Round off all of our sub-second precision to make timestamps + // nicer. + let just_nanos = Duration::from_nanos(elapsed.subsec_nanos() as u64); + let elapsed = elapsed - just_nanos; + + humantime::format_duration(elapsed).to_string() + }; + let page = html! { - "Rojo" + "Rojo Live Server" + -
-

- "Rojo Live Sync is up and running!" -

-

- "Version " { SERVER_VERSION } -

- - "Rojo Documentation" - -
+
+
+ +
+ + "Server Version: " + { SERVER_VERSION } + + + "Project: " + { project_name } + + + "Server Uptime: " + { uptime.to_string() } + +
+
+ +
}; From 171ab196c8f3bb32e188143bcaa49da0d10c50ae Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 23 Sep 2019 17:54:49 -0700 Subject: [PATCH 0698/1504] Update changelog --- CHANGELOG.md | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cab4f684..b84e3847 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,15 @@ # Rojo Changelog -## Unreleased Changes -* Added `--verbose`/`-v` flag, which can be specified multiple times to increase verbosity -* Added support for automatically finding Roblox Studio's auth cookie for `rojo upload` on Windows +## Unreleased Changes (will be 0.6.0) +* Added support for nested project files. ([#95](https://github.com/rojo-rbx/rojo/issues/95)) +* Added project file hot-reloading. ([#10](https://github.com/rojo-rbx/rojo/issues/10)]) +* Added support for building and serving sources that aren't projects. +* Added `--verbose`/`-v` flag, which can be specified multiple times to increase verbosity. +* Added support for automatically finding Roblox Studio's auth cookie for `rojo upload` on Windows. * Improved diagnostics for when the Rojo plugin cannot create an instance. +* Improved feedback from `rojo serve`. +* Fixed Rojo dropping Ref properties ([#142](https://github.com/rojo-rbx/rojo/issues/142)) + * This means that properties like `PrimaryPart` now work! ## [0.5.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0) (August 27, 2019) * Changed `.model.json` naming, which may require projects to migrate ambiguous cases: From e2761965d5901deb7de928a42d06896504271ae6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 23 Sep 2019 18:00:54 -0700 Subject: [PATCH 0699/1504] Add support for serving non-project files directly --- src/project.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/project.rs b/src/project.rs index 1869fe31..ba0d6616 100644 --- a/src/project.rs +++ b/src/project.rs @@ -322,6 +322,13 @@ pub struct Project { } impl Project { + pub fn is_project_file(path: &Path) -> bool { + path.file_name() + .and_then(|name| name.to_str()) + .map(|name| name.ends_with(".project.json")) + .unwrap_or(false) + } + pub fn init_place(project_fuzzy_path: &Path) -> Result { let project_path = Project::pick_path_for_init(project_fuzzy_path)?; @@ -418,7 +425,11 @@ impl Project { // If this is a file, assume it's the config the user was looking for. if location_metadata.is_file() { - return Some(start_location.to_path_buf()); + if Project::is_project_file(start_location) { + return Some(start_location.to_path_buf()); + } else { + return None; + } } else if location_metadata.is_dir() { let with_file = start_location.join(PROJECT_FILENAME); From 4f3d917c9b7ddbc9798a453de01011916b39a176 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 23 Sep 2019 18:13:38 -0700 Subject: [PATCH 0700/1504] Add support for snapshotting rbxlx files --- src/snapshot_middleware/mod.rs | 3 ++ src/snapshot_middleware/rbxlx.rs | 54 ++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 src/snapshot_middleware/rbxlx.rs diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 9b2c4980..21f5b838 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -11,6 +11,7 @@ mod json_model; mod lua; mod middleware; mod project; +mod rbxlx; mod rbxm; mod rbxmx; mod txt; @@ -24,6 +25,7 @@ use self::{ lua::SnapshotLua, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, project::SnapshotProject, + rbxlx::SnapshotRbxlx, rbxm::SnapshotRbxm, rbxmx::SnapshotRbxmx, txt::SnapshotTxt, @@ -67,6 +69,7 @@ macro_rules! middlewares { middlewares! { SnapshotProject, SnapshotJsonModel, + SnapshotRbxlx, SnapshotRbxmx, SnapshotRbxm, SnapshotLua, diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs new file mode 100644 index 00000000..66282fc8 --- /dev/null +++ b/src/snapshot_middleware/rbxlx.rs @@ -0,0 +1,54 @@ +use std::borrow::Cow; + +use rbx_dom_weak::{RbxId, RbxTree}; + +use crate::{ + imfs::{Imfs, ImfsEntry, ImfsFetcher}, + snapshot::InstanceSnapshot, +}; + +use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; + +pub struct SnapshotRbxlx; + +impl SnapshotMiddleware for SnapshotRbxlx { + fn from_imfs( + imfs: &mut Imfs, + entry: &ImfsEntry, + ) -> SnapshotInstanceResult<'static> { + if entry.is_directory() { + return Ok(None); + } + + let file_name = entry.path().file_name().unwrap().to_string_lossy(); + + if !file_name.ends_with(".rbxlx") { + return Ok(None); + } + + let instance_name = entry + .path() + .file_stem() + .expect("Could not extract file stem") + .to_string_lossy() + .to_string(); + + let options = rbx_xml::DecodeOptions::new() + .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); + + let temp_tree = rbx_xml::from_reader(entry.contents(imfs)?, options) + .expect("TODO: Handle rbx_xml errors"); + + let root_id = temp_tree.get_root_id(); + + let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, root_id); + snapshot.name = Cow::Owned(instance_name); + // TODO: Assign snapshot.source + + Ok(Some(snapshot)) + } + + fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { + None + } +} From 486319407a666e9ee9b49de47980213f795542da Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 24 Sep 2019 11:29:13 -0700 Subject: [PATCH 0701/1504] Refactor web UI to be more readable --- src/web/ui.rs | 114 ++++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 54 deletions(-) diff --git a/src/web/ui.rs b/src/web/ui.rs index fcb6b5ce..e01d7944 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -4,7 +4,7 @@ use std::{sync::Arc, time::Duration}; use futures::{future, Future}; use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; -use ritz::html; +use ritz::{html, HtmlContent}; use crate::{ imfs::ImfsFetcher, @@ -34,8 +34,8 @@ impl Service for UiService { (&Method::GET, "/") => self.handle_home(), (&Method::GET, "/logo.png") => self.handle_logo(), (&Method::GET, "/icon.png") => self.handle_icon(), - (&Method::GET, "/visualize/rbx") => self.handle_visualize_rbx(), - (&Method::GET, "/visualize/imfs") => self.handle_visualize_imfs(), + (&Method::GET, "/show-instances") => self.handle_show_instances(), + (&Method::GET, "/show-imfs") => self.handle_show_imfs(), (_method, path) => { return json( ErrorResponse::not_found(format!("Route not found: {}", path)), @@ -80,7 +80,61 @@ impl UiService { humantime::format_duration(elapsed).to_string() }; - let page = html! { + let page = Self::page(html! { +
+
+ +
+ { Self::stat_item("Server Version", SERVER_VERSION) } + { Self::stat_item("Project", project_name) } + { Self::stat_item("Server Uptime", uptime) } +
+
+
+ { Self::button("Rojo Documentation", "https://rojo.space/docs") } + { Self::button("View in-memory filesystem state", "/show-imfs") } + { Self::button("View instance tree state", "/show-instances") } +
+
+ }); + + Response::builder() + .header(header::CONTENT_TYPE, "text/html") + .body(Body::from(format!("{}", page))) + .unwrap() + } + + fn handle_show_instances(&self) -> Response { + Response::builder() + .header(header::CONTENT_TYPE, "text/plain") + .body(Body::from("TODO: /show-instances")) + .unwrap() + } + + fn handle_show_imfs(&self) -> Response { + Response::builder() + .header(header::CONTENT_TYPE, "text/plain") + .body(Body::from("TODO: /show-imfs")) + .unwrap() + } + + fn stat_item>(name: &str, value: S) -> HtmlContent<'_> { + html! { + + { name } ": " + { value.into() } + + } + } + + fn button<'a>(text: &'a str, href: &'a str) -> HtmlContent<'a> { + html! { + { text } + } + } + + fn page(body: HtmlContent<'_>) -> HtmlContent<'_> { + html! { "Rojo Live Server" @@ -91,57 +145,9 @@ impl UiService { -
-
- -
- - "Server Version: " - { SERVER_VERSION } - - - "Project: " - { project_name } - - - "Server Uptime: " - { uptime.to_string() } - -
-
- -
+ { body } - }; - - Response::builder() - .header(header::CONTENT_TYPE, "text/html") - .body(Body::from(format!("{}", page))) - .unwrap() - } - - fn handle_visualize_rbx(&self) -> Response { - Response::builder() - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from("TODO: /visualize/rbx")) - .unwrap() - } - - fn handle_visualize_imfs(&self) -> Response { - Response::builder() - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from("TODO: /visualize/imfs")) - .unwrap() + } } } From e8a5e443199460960befb1f97842ca940e81555e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 24 Sep 2019 14:00:48 -0700 Subject: [PATCH 0702/1504] Add abstraction for files to make iteration on UI easier --- Cargo.toml | 6 ++++ assets/index.css | 22 +++++++++----- src/web/assets.rs | 37 +++++++++++++++++++++++ src/web/mod.rs | 1 + src/web/ui.rs | 76 +++++++++++++++++++++++++---------------------- 5 files changed, 99 insertions(+), 43 deletions(-) create mode 100644 src/web/assets.rs diff --git a/Cargo.toml b/Cargo.toml index d9530ff1..e16e76d1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,6 +12,12 @@ exclude = [ "/test-projects/**", ] +[features] +default = [] + +# Enable this feature to live-reload assets from the web UI. +dev-live-assets = [] + [workspace] members = [ "rojo-test", diff --git a/assets/index.css b/assets/index.css index c0a1e687..8b96697b 100644 --- a/assets/index.css +++ b/assets/index.css @@ -22,11 +22,10 @@ body { justify-content: center; } -.main { +.root { flex: 0 0; display: flex; flex-direction: column; - padding: 1rem; margin: 0 auto; width: 100%; max-width: 50rem; @@ -38,19 +37,25 @@ body { .header { flex: 0 0; display: flex; - justify-content: space-around; + flex-wrap: wrap; + /*justify-content: space-around;*/ align-items: center; - margin-bottom: 1rem; + border-bottom: 1px solid #666; +} + +.main { + padding: 1rem; } .main-logo { flex: 0 0; - width: 20rem; + width: 10rem; + margin: 1rem; } .stats { flex: 0 0 20rem; - padding: 0 1rem; + margin: 1rem; } .stat { @@ -65,12 +70,13 @@ body { .button-list { flex: 0 0; display: flex; - justify-content: space-around; + flex-wrap: wrap; + justify-content: center; } .button { display: inline-block; border: 1px solid #666; padding: 0.3em 1em; - margin: 0 0.2rem; + margin: 1rem; } \ No newline at end of file diff --git a/src/web/assets.rs b/src/web/assets.rs new file mode 100644 index 00000000..2832f768 --- /dev/null +++ b/src/web/assets.rs @@ -0,0 +1,37 @@ +use std::{fs, path::Path}; + +static LOGO: &[u8] = include_bytes!("../../assets/logo-512.png"); +static ICON: &[u8] = include_bytes!("../../assets/icon-32.png"); +static HOME_CSS: &str = include_str!("../../assets/index.css"); + +macro_rules! declare_asset { + ($name: ident, $path: expr) => { + pub fn $name() -> &'static str { + if cfg!(feature = "dev-live-assets") { + let file_path = Path::new(file!()); + let asset_path = file_path.parent().unwrap().join($path); + + println!("Reloading {}", asset_path.display()); + + let content = fs::read_to_string(asset_path) + .expect("Couldn't read dev live asset") + .into_boxed_str(); + + Box::leak(content) + } else { + static CONTENT: &str = include_str!($path); + CONTENT + } + } + }; +} + +declare_asset!(css, "../../assets/index.css"); + +pub fn logo() -> &'static [u8] { + LOGO +} + +pub fn icon() -> &'static [u8] { + ICON +} diff --git a/src/web/mod.rs b/src/web/mod.rs index ab8242d2..319083fa 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -1,4 +1,5 @@ mod api; +mod assets; pub mod interface; mod ui; mod util; diff --git a/src/web/ui.rs b/src/web/ui.rs index e01d7944..fca27849 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -10,15 +10,12 @@ use crate::{ imfs::ImfsFetcher, serve_session::ServeSession, web::{ + assets, interface::{ErrorResponse, SERVER_VERSION}, util::json, }, }; -static LOGO: &[u8] = include_bytes!("../../assets/logo-512.png"); -static ICON: &[u8] = include_bytes!("../../assets/icon-32.png"); -static HOME_CSS: &str = include_str!("../../assets/index.css"); - pub struct UiService { serve_session: Arc>, } @@ -56,46 +53,24 @@ impl UiService { fn handle_logo(&self) -> Response { Response::builder() .header(header::CONTENT_TYPE, "image/png") - .body(Body::from(LOGO)) + .body(Body::from(assets::logo())) .unwrap() } fn handle_icon(&self) -> Response { Response::builder() .header(header::CONTENT_TYPE, "image/png") - .body(Body::from(ICON)) + .body(Body::from(assets::icon())) .unwrap() } fn handle_home(&self) -> Response { - let project_name = self.serve_session.project_name().unwrap_or(""); - let uptime = { - let elapsed = self.serve_session.start_time().elapsed(); - - // Round off all of our sub-second precision to make timestamps - // nicer. - let just_nanos = Duration::from_nanos(elapsed.subsec_nanos() as u64); - let elapsed = elapsed - just_nanos; - - humantime::format_duration(elapsed).to_string() - }; - - let page = Self::page(html! { -
-
- -
- { Self::stat_item("Server Version", SERVER_VERSION) } - { Self::stat_item("Project", project_name) } - { Self::stat_item("Server Uptime", uptime) } -
-
-
- { Self::button("Rojo Documentation", "https://rojo.space/docs") } - { Self::button("View in-memory filesystem state", "/show-imfs") } - { Self::button("View instance tree state", "/show-instances") } -
-
+ let page = self.normal_page(html! { +
+ { Self::button("Rojo Documentation", "https://rojo.space/docs") } + { Self::button("View in-memory filesystem state", "/show-imfs") } + { Self::button("View instance tree state", "/show-instances") } +
}); Response::builder() @@ -133,14 +108,45 @@ impl UiService { } } + fn normal_page<'a>(&'a self, body: HtmlContent<'a>) -> HtmlContent<'a> { + let project_name = self.serve_session.project_name().unwrap_or(""); + let uptime = { + let elapsed = self.serve_session.start_time().elapsed(); + + // Round off all of our sub-second precision to make timestamps + // nicer. + let just_nanos = Duration::from_nanos(elapsed.subsec_nanos() as u64); + let elapsed = elapsed - just_nanos; + + humantime::format_duration(elapsed).to_string() + }; + + Self::page(html! { +
+
+ +
+ { Self::stat_item("Server Version", SERVER_VERSION) } + { Self::stat_item("Project", project_name) } + { Self::stat_item("Server Uptime", uptime) } +
+
+
+ { body } +
+
+ }) + } + fn page(body: HtmlContent<'_>) -> HtmlContent<'_> { html! { "Rojo Live Server" + From 7a1eda98ca1374d6a9581395ae71456f19a9c60b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 24 Sep 2019 16:46:19 -0700 Subject: [PATCH 0703/1504] Implement instance tree visualization --- assets/index.css | 38 +++++++++++++++--- src/web/assets.rs | 6 +-- src/web/ui.rs | 100 +++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 130 insertions(+), 14 deletions(-) diff --git a/assets/index.css b/assets/index.css index 8b96697b..b501f6a7 100644 --- a/assets/index.css +++ b/assets/index.css @@ -11,22 +11,29 @@ html { box-sizing: border-box; font-family: sans-serif; + font-size: 18px; text-decoration: none; height: 100%; } body { - height: 100%; + min-height: 100%; display: flex; flex-direction: column; justify-content: center; } +img { + max-width:100%; + max-height:100%; + height: auto; +} + .root { flex: 0 0; display: flex; flex-direction: column; - margin: 0 auto; + margin: 0.5rem auto; width: 100%; max-width: 50rem; background-color: #efefef; @@ -48,8 +55,7 @@ body { } .main-logo { - flex: 0 0; - width: 10rem; + flex: 0 0 10rem; margin: 1rem; } @@ -71,7 +77,8 @@ body { flex: 0 0; display: flex; flex-wrap: wrap; - justify-content: center; + justify-content: space-around; + margin: -1rem; } .button { @@ -79,4 +86,25 @@ body { border: 1px solid #666; padding: 0.3em 1em; margin: 1rem; +} + +.instance { + border: 1px solid #666; + border-right-style: none; + border-bottom-style: none; + background-color: #fff; + margin-bottom: 0.5rem; +} + +.instance-title { + font-size: 1.5rem; + padding: 0.5rem; +} + +.instance-properties { + padding: 0.5rem; +} + +.instance-children { + padding: 0.5rem 0 0.5rem 1rem; } \ No newline at end of file diff --git a/src/web/assets.rs b/src/web/assets.rs index 2832f768..3a8a5b4d 100644 --- a/src/web/assets.rs +++ b/src/web/assets.rs @@ -1,5 +1,3 @@ -use std::{fs, path::Path}; - static LOGO: &[u8] = include_bytes!("../../assets/logo-512.png"); static ICON: &[u8] = include_bytes!("../../assets/icon-32.png"); static HOME_CSS: &str = include_str!("../../assets/index.css"); @@ -8,12 +6,14 @@ macro_rules! declare_asset { ($name: ident, $path: expr) => { pub fn $name() -> &'static str { if cfg!(feature = "dev-live-assets") { + use std::{fs::read_to_string, path::Path}; + let file_path = Path::new(file!()); let asset_path = file_path.parent().unwrap().join($path); println!("Reloading {}", asset_path.display()); - let content = fs::read_to_string(asset_path) + let content = read_to_string(asset_path) .expect("Couldn't read dev live asset") .into_boxed_str(); diff --git a/src/web/ui.rs b/src/web/ui.rs index fca27849..b29f44ad 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -4,11 +4,13 @@ use std::{sync::Arc, time::Duration}; use futures::{future, Future}; use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; -use ritz::{html, HtmlContent}; +use rbx_dom_weak::{RbxId, RbxValue}; +use ritz::{html, Fragment, HtmlContent}; use crate::{ imfs::ImfsFetcher, serve_session::ServeSession, + snapshot::RojoTree, web::{ assets, interface::{ErrorResponse, SERVER_VERSION}, @@ -80,19 +82,103 @@ impl UiService { } fn handle_show_instances(&self) -> Response { + let tree = self.serve_session.tree(); + let root_id = tree.get_root_id(); + + let page = self.normal_page(html! { + { Self::instance(&tree, root_id) } + }); + Response::builder() - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from("TODO: /show-instances")) + .header(header::CONTENT_TYPE, "text/html") + .body(Body::from(format!("{}", page))) .unwrap() } fn handle_show_imfs(&self) -> Response { + let page = self.normal_page(html! { + "TODO /show/imfs" + }); + Response::builder() - .header(header::CONTENT_TYPE, "text/plain") - .body(Body::from("TODO: /show-imfs")) + .header(header::CONTENT_TYPE, "text/html") + .body(Body::from(format!("{}", page))) .unwrap() } + fn instance(tree: &RojoTree, id: RbxId) -> HtmlContent<'_> { + let instance = tree.get_instance(id).unwrap(); + let children_list: Vec<_> = instance + .children() + .iter() + .copied() + .map(|id| Self::instance(tree, id)) + .collect(); + + let children_container = if children_list.is_empty() { + HtmlContent::None + } else { + html! { +
+ { Fragment::new(children_list) } +
+ } + }; + + let mut properties: Vec<_> = instance.properties().iter().collect(); + properties.sort_by_key(|pair| pair.0); + + let property_list: Vec<_> = properties + .into_iter() + .map(|(key, value)| { + html! { +
+ { key.clone() } ": " { format!("{:?}", value.get_type()) } +
+ } + }) + .collect(); + + let property_container = if property_list.is_empty() { + HtmlContent::None + } else { + html! { +
+ { Fragment::new(property_list) } +
+ } + }; + + let class_name_specifier = if instance.name() == instance.class_name() { + HtmlContent::None + } else { + html! { + + " (" { instance.class_name().to_owned() } ")" + + } + }; + + html! { +
+
+ { instance.name().to_owned() } + { class_name_specifier } +
+ { property_container } + { children_container } +
+ } + } + + fn display_value(value: &RbxValue) -> String { + match value { + RbxValue::String { value } => value.clone(), + RbxValue::Bool { value } => value.to_string(), + _ => format!("{:?}", value), + } + } + fn stat_item>(name: &str, value: S) -> HtmlContent<'_> { html! { @@ -124,7 +210,9 @@ impl UiService { Self::page(html! {
- +
{ Self::stat_item("Server Version", SERVER_VERSION) } { Self::stat_item("Project", project_name) } From 07fe963bed84f7c6aa83f1cd596a5bddfc16ee51 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 24 Sep 2019 17:53:39 -0700 Subject: [PATCH 0704/1504] Don't include CSS in live asset mode --- src/web/assets.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/web/assets.rs b/src/web/assets.rs index 3a8a5b4d..481c588c 100644 --- a/src/web/assets.rs +++ b/src/web/assets.rs @@ -1,7 +1,3 @@ -static LOGO: &[u8] = include_bytes!("../../assets/logo-512.png"); -static ICON: &[u8] = include_bytes!("../../assets/icon-32.png"); -static HOME_CSS: &str = include_str!("../../assets/index.css"); - macro_rules! declare_asset { ($name: ident, $path: expr) => { pub fn $name() -> &'static str { @@ -29,9 +25,13 @@ macro_rules! declare_asset { declare_asset!(css, "../../assets/index.css"); pub fn logo() -> &'static [u8] { + static LOGO: &[u8] = include_bytes!("../../assets/logo-512.png"); + LOGO } pub fn icon() -> &'static [u8] { + static ICON: &[u8] = include_bytes!("../../assets/icon-32.png"); + ICON } From 061a0966008860965245d417786554d1b3b49f64 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 24 Sep 2019 17:55:39 -0700 Subject: [PATCH 0705/1504] Add PathMap::orphans for traversing the map's roots --- src/path_map.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/path_map.rs b/src/path_map.rs index 506f29f4..9ccf11ea 100644 --- a/src/path_map.rs +++ b/src/path_map.rs @@ -156,6 +156,10 @@ impl PathMap { current_path } + pub fn orphans(&self) -> impl Iterator { + self.orphan_paths.iter().map(|item| item.as_ref()) + } + /// Adds the path to its parent if it's present in the tree, or the set of /// orphaned paths if it is not. fn add_to_parent(&mut self, path: PathBuf) { From 0f2e2406e8db003c9a6f19cd0df2d318bc083b2c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 24 Sep 2019 17:57:06 -0700 Subject: [PATCH 0706/1504] imfs: Correctly mark children_enumerated when calling get_children --- src/imfs/imfs.rs | 27 +++++++++++++++------------ 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/src/imfs/imfs.rs b/src/imfs/imfs.rs index 21aaf9d4..875906c6 100644 --- a/src/imfs/imfs.rs +++ b/src/imfs/imfs.rs @@ -221,13 +221,14 @@ impl Imfs { self.read_if_not_exists(path)?; - match self.inner.get(path).unwrap() { + match self.inner.get_mut(path).unwrap() { ImfsItem::Directory(dir) => { self.fetcher.watch(path); - if dir.children_enumerated { - return self - .inner + let enumerated = dir.children_enumerated; + + if enumerated { + self.inner .children(path) .unwrap() // TODO: Handle None here, which means the PathMap entry did not exist. .into_iter() @@ -235,15 +236,17 @@ impl Imfs { .collect::>() // Collect all PathBufs, since self.get needs to borrow self mutably. .into_iter() .map(|path| self.get(path)) - .collect::>>(); - } + .collect::>>() + } else { + dir.children_enumerated = true; - self.fetcher - .read_children(path) - .map_err(|err| FsError::new(err, path.to_path_buf()))? - .into_iter() - .map(|path| self.get(path)) - .collect::>>() + self.fetcher + .read_children(path) + .map_err(|err| FsError::new(err, path.to_path_buf()))? + .into_iter() + .map(|path| self.get(path)) + .collect::>>() + } } ImfsItem::File(_) => Err(FsError::new( io::Error::new(io::ErrorKind::Other, "Can't read a directory"), From 26fc097672aa8a4142c83b86bc7e4e8154087703 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 24 Sep 2019 18:04:25 -0700 Subject: [PATCH 0707/1504] Add visualizer for IMFS state --- assets/index.css | 26 ++++++++++++++++++ src/imfs/imfs.rs | 38 ++++++++++++++++++++++++++ src/web/ui.rs | 71 ++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 132 insertions(+), 3 deletions(-) diff --git a/assets/index.css b/assets/index.css index b501f6a7..71dd9474 100644 --- a/assets/index.css +++ b/assets/index.css @@ -107,4 +107,30 @@ img { .instance-children { padding: 0.5rem 0 0.5rem 1rem; +} + +.imfs-entry { +} + +.imfs-entry-name { + position: relative; +} + +.imfs-entry-children .imfs-entry-name::before { + content: ""; + width: 0.8rem; + height: 1px; + background-color: #999; + position: absolute; + top: 50%; + left: -1rem; +} + +.imfs-entry-note { + font-style: italic; +} + +.imfs-entry-children { + padding-left: 1rem; + border-left: 1px solid #999; } \ No newline at end of file diff --git a/src/imfs/imfs.rs b/src/imfs/imfs.rs index 875906c6..97eb3806 100644 --- a/src/imfs/imfs.rs +++ b/src/imfs/imfs.rs @@ -303,6 +303,44 @@ impl Imfs { } } +/// Contains extra methods that should only be used for debugging. They're +/// broken out into a separate trait to make it more explicit to depend on them. +pub trait ImfsDebug { + fn debug_is_file(&self, path: &Path) -> bool; + fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]>; + fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)>; + fn debug_orphans(&self) -> Vec<&Path>; +} + +impl ImfsDebug for Imfs { + fn debug_is_file(&self, path: &Path) -> bool { + match self.inner.get(path) { + Some(ImfsItem::File(_)) => true, + _ => false, + } + } + + fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]> { + match self.inner.get(path) { + Some(ImfsItem::File(file)) => file.contents.as_ref().map(|vec| vec.as_slice()), + _ => None, + } + } + + fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)> { + match self.inner.get(path) { + Some(ImfsItem::Directory(dir)) => { + Some((dir.children_enumerated, self.inner.children(path).unwrap())) + } + _ => None, + } + } + + fn debug_orphans(&self) -> Vec<&Path> { + self.inner.orphans().collect() + } +} + /// A reference to file or folder in an `Imfs`. Can only be produced by the /// entry existing in the Imfs, but can later point to nothing if something /// would invalidate that path. diff --git a/src/web/ui.rs b/src/web/ui.rs index b29f44ad..a2b95713 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -1,6 +1,6 @@ //! Defines the HTTP-based UI. These endpoints generally return HTML and SVG. -use std::{sync::Arc, time::Duration}; +use std::{path::Path, sync::Arc, time::Duration}; use futures::{future, Future}; use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; @@ -8,7 +8,7 @@ use rbx_dom_weak::{RbxId, RbxValue}; use ritz::{html, Fragment, HtmlContent}; use crate::{ - imfs::ImfsFetcher, + imfs::{Imfs, ImfsDebug, ImfsFetcher}, serve_session::ServeSession, snapshot::RojoTree, web::{ @@ -96,8 +96,18 @@ impl UiService { } fn handle_show_imfs(&self) -> Response { + let imfs = self.serve_session.imfs(); + + let orphans: Vec<_> = imfs + .debug_orphans() + .into_iter() + .map(|path| Self::render_imfs_path(&imfs, path, true)) + .collect(); + let page = self.normal_page(html! { - "TODO /show/imfs" +
+ { Fragment::new(orphans) } +
}); Response::builder() @@ -106,6 +116,61 @@ impl UiService { .unwrap() } + fn render_imfs_path(imfs: &Imfs, path: &Path, is_root: bool) -> HtmlContent<'static> { + let is_file = imfs.debug_is_file(path); + + let (note, children) = if is_file { + (HtmlContent::None, Vec::new()) + } else { + let (is_exhaustive, mut children) = imfs.debug_children(path).unwrap(); + + // Sort files above directories, then sort how Path does after that. + children.sort_unstable_by(|a, b| { + let a_is_file = imfs.debug_is_file(a); + let b_is_file = imfs.debug_is_file(b); + + b_is_file.cmp(&a_is_file).then_with(|| a.cmp(b)) + }); + + let children: Vec<_> = children + .into_iter() + .map(|child| Self::render_imfs_path(imfs, child, false)) + .collect(); + + let note = if is_exhaustive { + HtmlContent::None + } else { + html!({ " (non-exhaustive)" }) + }; + + (note, children) + }; + + // For root entries, we want the full path to contextualize the path. + let mut name = if is_root { + path.to_str().unwrap().to_owned() + } else { + path.file_name().unwrap().to_str().unwrap().to_owned() + }; + + // Directories should end with `/` in the UI to mark them. + if !is_file && !name.ends_with('/') && !name.ends_with('\\') { + name.push('/'); + } + + html! { +
+
+ { name } + { note } +
+
+ { Fragment::new(children) } +
+
+ } + } + fn instance(tree: &RojoTree, id: RbxId) -> HtmlContent<'_> { let instance = tree.get_instance(id).unwrap(); let children_list: Vec<_> = instance From 7b7c978db641f953ff898fe115b32c39c3d6dd5e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 24 Sep 2019 18:06:31 -0700 Subject: [PATCH 0708/1504] Fix warning and make 'rojo serve' output to stdout --- src/commands/serve.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/serve.rs b/src/commands/serve.rs index aeded2cd..04bf5a63 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -85,7 +85,7 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { } fn show_start_message(port: u16) -> io::Result<()> { - let mut writer = BufferWriter::stderr(ColorChoice::Auto); + let writer = BufferWriter::stdout(ColorChoice::Auto); let mut buffer = writer.buffer(); writeln!(&mut buffer, "Rojo server listening:")?; From 125c9767f1c5686cd7d6f0ac224e0cdc4e00d0bb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 24 Sep 2019 18:07:33 -0700 Subject: [PATCH 0709/1504] Fix warnings around ChangeProcessor --- src/change_processor.rs | 4 ++-- src/serve_session.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index 8e2f7f02..2ce22bc8 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -16,7 +16,7 @@ use crate::{ pub struct ChangeProcessor { shutdown_sender: Sender<()>, - thread_handle: JoinHandle<()>, + _thread_handle: JoinHandle<()>, } impl ChangeProcessor { @@ -34,7 +34,7 @@ impl ChangeProcessor { Self { shutdown_sender, - thread_handle, + _thread_handle: thread_handle, } } diff --git a/src/serve_session.rs b/src/serve_session.rs index e978daf6..cfc6d4f1 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -63,7 +63,7 @@ pub struct ServeSession { /// filesystem, applying them, updating the Roblox instance tree, and /// routing messages through the session's message queue to any connected /// clients. - change_processor: ChangeProcessor, + _change_processor: ChangeProcessor, } /// Methods that need thread-safety bounds on ImfsFetcher are limited to this @@ -93,7 +93,7 @@ impl ServeSession { tree, message_queue, imfs, - change_processor, + _change_processor: change_processor, } } } From f166cc93cd50fea2eea0babdb473c90c2f5c2708 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 24 Sep 2019 18:08:32 -0700 Subject: [PATCH 0710/1504] Remove unused MessageQueue method --- src/message_queue.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/message_queue.rs b/src/message_queue.rs index 2eb22609..23c6cd94 100644 --- a/src/message_queue.rs +++ b/src/message_queue.rs @@ -80,17 +80,4 @@ impl MessageQueue { pub fn cursor(&self) -> u32 { self.messages.read().unwrap().len() as u32 } - - pub fn get_messages_since(&self, cursor: u32) -> (u32, Vec) { - let messages = self.messages.read().unwrap(); - - let current_cursor = messages.len() as u32; - - // Cursor is out of bounds or there are no new messages - if cursor >= current_cursor { - return (current_cursor, Vec::new()); - } - - (current_cursor, messages[(cursor as usize)..].to_vec()) - } } From c140823bea31557a66666ddffc3d3030846fef33 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 24 Sep 2019 18:14:48 -0700 Subject: [PATCH 0711/1504] Move Imfs snapshotting into ImfsDebug --- src/imfs/imfs.rs | 77 ++++++++++++--------------- src/snapshot_middleware/csv.rs | 4 +- src/snapshot_middleware/dir.rs | 6 +-- src/snapshot_middleware/json_model.rs | 4 +- src/snapshot_middleware/lua.rs | 8 +-- src/snapshot_middleware/project.rs | 20 +++---- src/snapshot_middleware/rbxm.rs | 4 +- src/snapshot_middleware/rbxmx.rs | 4 +- src/snapshot_middleware/txt.rs | 4 +- 9 files changed, 60 insertions(+), 71 deletions(-) diff --git a/src/imfs/imfs.rs b/src/imfs/imfs.rs index 97eb3806..915f9f84 100644 --- a/src/imfs/imfs.rs +++ b/src/imfs/imfs.rs @@ -40,18 +40,6 @@ impl Imfs { self.fetcher.receiver() } - pub fn commit_pending_changes(&mut self) -> FsResult> { - let receiver = self.fetcher.receiver(); - let mut changes = Vec::new(); - - while let Ok(event) = receiver.try_recv() { - self.commit_change(&event)?; - changes.push(event); - } - - Ok(changes) - } - pub fn commit_change(&mut self, event: &ImfsEvent) -> FsResult<()> { use notify::DebouncedEvent::*; @@ -84,35 +72,6 @@ impl Imfs { Ok(()) } - pub fn load_from_snapshot(&mut self, path: impl AsRef, snapshot: ImfsSnapshot) { - let path = path.as_ref(); - - match snapshot { - ImfsSnapshot::File(file) => { - self.inner.insert( - path.to_path_buf(), - ImfsItem::File(ImfsFile { - path: path.to_path_buf(), - contents: Some(file.contents), - }), - ); - } - ImfsSnapshot::Directory(directory) => { - self.inner.insert( - path.to_path_buf(), - ImfsItem::Directory(ImfsDirectory { - path: path.to_path_buf(), - children_enumerated: true, - }), - ); - - for (child_name, child) in directory.children.into_iter() { - self.load_from_snapshot(path.join(child_name), child); - } - } - } - } - fn raise_file_changed(&mut self, path: impl AsRef) -> FsResult<()> { let path = path.as_ref(); @@ -306,6 +265,7 @@ impl Imfs { /// Contains extra methods that should only be used for debugging. They're /// broken out into a separate trait to make it more explicit to depend on them. pub trait ImfsDebug { + fn debug_load_snapshot>(&mut self, path: P, snapshot: ImfsSnapshot); fn debug_is_file(&self, path: &Path) -> bool; fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]>; fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)>; @@ -313,6 +273,35 @@ pub trait ImfsDebug { } impl ImfsDebug for Imfs { + fn debug_load_snapshot>(&mut self, path: P, snapshot: ImfsSnapshot) { + let path = path.as_ref(); + + match snapshot { + ImfsSnapshot::File(file) => { + self.inner.insert( + path.to_path_buf(), + ImfsItem::File(ImfsFile { + path: path.to_path_buf(), + contents: Some(file.contents), + }), + ); + } + ImfsSnapshot::Directory(directory) => { + self.inner.insert( + path.to_path_buf(), + ImfsItem::Directory(ImfsDirectory { + path: path.to_path_buf(), + children_enumerated: true, + }), + ); + + for (child_name, child) in directory.children.into_iter() { + self.debug_load_snapshot(path.join(child_name), child); + } + } + } + } + fn debug_is_file(&self, path: &Path) -> bool { match self.inner.get(path) { Some(ImfsItem::File(_)) => true, @@ -432,7 +421,7 @@ mod test { let mut imfs = Imfs::new(NoopFetcher); let file = ImfsSnapshot::file("hello, world!"); - imfs.load_from_snapshot("/hello.txt", file); + imfs.debug_load_snapshot("/hello.txt", file); let entry = imfs.get_contents("/hello.txt").unwrap(); assert_eq!(entry, b"hello, world!"); @@ -446,7 +435,7 @@ mod test { "b.lua" => ImfsSnapshot::file("contents of b.lua"), }); - imfs.load_from_snapshot("/dir", dir); + imfs.debug_load_snapshot("/dir", dir); let children = imfs.get_children("/dir").unwrap(); @@ -560,7 +549,7 @@ mod test { let mut imfs = Imfs::new(NoopFetcher); let file = ImfsSnapshot::file("hello, world!"); - imfs.load_from_snapshot("/hello.txt", file); + imfs.debug_load_snapshot("/hello.txt", file); let hello = imfs.get("/hello.txt").expect("couldn't get hello.txt"); diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 9c87f200..804a03e5 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -136,7 +136,7 @@ fn convert_localization_csv(contents: &[u8]) -> String { mod test { use super::*; - use crate::imfs::{ImfsSnapshot, NoopFetcher}; + use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; #[test] fn csv_from_imfs() { @@ -147,7 +147,7 @@ Key,Source,Context,Example,es Ack,Ack!,,An exclamation of despair,¡Ay!"#, ); - imfs.load_from_snapshot("/foo.csv", file); + imfs.debug_load_snapshot("/foo.csv", file); let entry = imfs.get("/foo.csv").unwrap(); let instance_snapshot = SnapshotCsv::from_imfs(&mut imfs, &entry).unwrap().unwrap(); diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 1e8d50d3..a826c43f 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -78,14 +78,14 @@ mod test { use maplit::hashmap; - use crate::imfs::NoopFetcher; + use crate::imfs::{ImfsDebug, NoopFetcher}; #[test] fn empty_folder() { let mut imfs = Imfs::new(NoopFetcher); let dir = ImfsSnapshot::dir::(HashMap::new()); - imfs.load_from_snapshot("/foo", dir); + imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); let instance_snapshot = SnapshotDir::from_imfs(&mut imfs, &entry).unwrap().unwrap(); @@ -103,7 +103,7 @@ mod test { "Child" => ImfsSnapshot::dir::(HashMap::new()), }); - imfs.load_from_snapshot("/foo", dir); + imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); let instance_snapshot = SnapshotDir::from_imfs(&mut imfs, &entry).unwrap().unwrap(); diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 6b026557..3cbcc81b 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -136,7 +136,7 @@ mod test { use maplit::hashmap; use rbx_dom_weak::RbxValue; - use crate::imfs::{ImfsSnapshot, NoopFetcher}; + use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; #[test] fn model_from_imfs() { @@ -159,7 +159,7 @@ mod test { "#, ); - imfs.load_from_snapshot("/foo.model.json", file); + imfs.debug_load_snapshot("/foo.model.json", file); let entry = imfs.get("/foo.model.json").unwrap(); let instance_snapshot = SnapshotJsonModel::from_imfs(&mut imfs, &entry) diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 779fc740..f7d5b4ee 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -141,14 +141,14 @@ mod test { use maplit::hashmap; - use crate::imfs::{ImfsSnapshot, NoopFetcher}; + use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; #[test] fn module_from_imfs() { let mut imfs = Imfs::new(NoopFetcher); let file = ImfsSnapshot::file("Hello there!"); - imfs.load_from_snapshot("/foo.lua", file); + imfs.debug_load_snapshot("/foo.lua", file); let entry = imfs.get("/foo.lua").unwrap(); let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); @@ -170,7 +170,7 @@ mod test { let mut imfs = Imfs::new(NoopFetcher); let file = ImfsSnapshot::file("Hello there!"); - imfs.load_from_snapshot("/foo.server.lua", file); + imfs.debug_load_snapshot("/foo.server.lua", file); let entry = imfs.get("/foo.server.lua").unwrap(); let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); @@ -192,7 +192,7 @@ mod test { let mut imfs = Imfs::new(NoopFetcher); let file = ImfsSnapshot::file("Hello there!"); - imfs.load_from_snapshot("/foo.client.lua", file); + imfs.debug_load_snapshot("/foo.client.lua", file); let entry = imfs.get("/foo.client.lua").unwrap(); let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 4f68fe1c..6d06e332 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -143,7 +143,7 @@ mod test { use maplit::hashmap; use rbx_dom_weak::RbxValue; - use crate::imfs::{ImfsSnapshot, NoopFetcher}; + use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; #[test] fn project_from_folder() { @@ -161,7 +161,7 @@ mod test { "#), }); - imfs.load_from_snapshot("/foo", dir); + imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) @@ -190,7 +190,7 @@ mod test { "#), }); - imfs.load_from_snapshot("/foo", dir); + imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo/hello.project.json").unwrap(); let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) @@ -225,7 +225,7 @@ mod test { "#), }); - imfs.load_from_snapshot("/foo", dir); + imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) @@ -264,7 +264,7 @@ mod test { "#), }); - imfs.load_from_snapshot("/foo", dir); + imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) @@ -304,7 +304,7 @@ mod test { "#), }); - imfs.load_from_snapshot("/foo", dir); + imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) @@ -340,7 +340,7 @@ mod test { "other.txt" => ImfsSnapshot::file("Hello, world!"), }); - imfs.load_from_snapshot("/foo", dir); + imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) @@ -384,7 +384,7 @@ mod test { "#), }); - imfs.load_from_snapshot("/foo", dir); + imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) @@ -425,7 +425,7 @@ mod test { "#), }); - imfs.load_from_snapshot("/foo", dir); + imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) @@ -477,7 +477,7 @@ mod test { "#), }); - imfs.load_from_snapshot("/foo", dir); + imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 210d64ee..d14f7279 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -66,14 +66,14 @@ impl SnapshotMiddleware for SnapshotRbxm { mod test { use super::*; - use crate::imfs::{ImfsSnapshot, NoopFetcher}; + use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; #[test] fn model_from_imfs() { let mut imfs = Imfs::new(NoopFetcher); let file = ImfsSnapshot::file(include_bytes!("../../assets/test-folder.rbxm").to_vec()); - imfs.load_from_snapshot("/foo.rbxm", file); + imfs.debug_load_snapshot("/foo.rbxm", file); let entry = imfs.get("/foo.rbxm").unwrap(); let instance_snapshot = SnapshotRbxm::from_imfs(&mut imfs, &entry).unwrap().unwrap(); diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 3f0c2814..fde908bd 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -64,7 +64,7 @@ mod test { use std::collections::HashMap; - use crate::imfs::{ImfsSnapshot, NoopFetcher}; + use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; #[test] fn model_from_imfs() { @@ -81,7 +81,7 @@ mod test { "#, ); - imfs.load_from_snapshot("/foo.rbxmx", file); + imfs.debug_load_snapshot("/foo.rbxmx", file); let entry = imfs.get("/foo.rbxmx").unwrap(); let instance_snapshot = SnapshotRbxmx::from_imfs(&mut imfs, &entry) diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index ea750b42..f35495ae 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -94,14 +94,14 @@ mod test { use maplit::hashmap; use rbx_dom_weak::RbxInstanceProperties; - use crate::imfs::NoopFetcher; + use crate::imfs::{ImfsDebug, NoopFetcher}; #[test] fn instance_from_imfs() { let mut imfs = Imfs::new(NoopFetcher); let file = ImfsSnapshot::file("Hello there!"); - imfs.load_from_snapshot("/foo.txt", file); + imfs.debug_load_snapshot("/foo.txt", file); let entry = imfs.get("/foo.txt").unwrap(); let instance_snapshot = SnapshotTxt::from_imfs(&mut imfs, &entry).unwrap().unwrap(); From b4a8dec68cbeb6bed91bc17c1944a9666c734a0b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 25 Sep 2019 10:45:14 -0700 Subject: [PATCH 0712/1504] Track watched paths in ImfsFetcher, exposed via ImfsDebug interface --- src/imfs/fetcher.rs | 5 +++++ src/imfs/imfs.rs | 13 ++++++++++++- src/imfs/real_fetcher.rs | 26 ++++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/src/imfs/fetcher.rs b/src/imfs/fetcher.rs index f86f702a..ac6ca7ac 100644 --- a/src/imfs/fetcher.rs +++ b/src/imfs/fetcher.rs @@ -29,4 +29,9 @@ pub trait ImfsFetcher { fn watch(&mut self, path: &Path); fn unwatch(&mut self, path: &Path); fn receiver(&self) -> Receiver; + + /// A method intended for debugging what paths the fetcher is watching. + fn watched_paths(&self) -> Vec<&Path> { + Vec::new() + } } diff --git a/src/imfs/imfs.rs b/src/imfs/imfs.rs index 915f9f84..3798472c 100644 --- a/src/imfs/imfs.rs +++ b/src/imfs/imfs.rs @@ -24,7 +24,13 @@ use super::{ /// Most operations return `ImfsEntry` objects to work around this, which is /// effectively a index into the `Imfs`. pub struct Imfs { + /// A hierarchical map from paths to items that have been read or partially + /// read into memory by the Imfs. inner: PathMap, + + /// This Imfs's fetcher, which is used for all actual interactions with the + /// filesystem. It's referred to by the type parameter `F` all over, and is + /// generic in order to make it feasible to mock. fetcher: F, } @@ -270,9 +276,10 @@ pub trait ImfsDebug { fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]>; fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)>; fn debug_orphans(&self) -> Vec<&Path>; + fn debug_watched_paths(&self) -> Vec<&Path>; } -impl ImfsDebug for Imfs { +impl ImfsDebug for Imfs { fn debug_load_snapshot>(&mut self, path: P, snapshot: ImfsSnapshot) { let path = path.as_ref(); @@ -328,6 +335,10 @@ impl ImfsDebug for Imfs { fn debug_orphans(&self) -> Vec<&Path> { self.inner.orphans().collect() } + + fn debug_watched_paths(&self) -> Vec<&Path> { + self.fetcher.watched_paths() + } } /// A reference to file or folder in an `Imfs`. Can only be produced by the diff --git a/src/imfs/real_fetcher.rs b/src/imfs/real_fetcher.rs index b3159950..e9dc221a 100644 --- a/src/imfs/real_fetcher.rs +++ b/src/imfs/real_fetcher.rs @@ -2,6 +2,7 @@ //! std::fs interface and notify as the file watcher. use std::{ + collections::HashSet, fs, io, path::{Path, PathBuf}, sync::mpsc, @@ -35,7 +36,13 @@ pub struct RealFetcher { /// Thread handle to convert notify's mpsc channel messages into /// crossbeam_channel messages. _converter_thread: JoinHandle<()>, + + /// The crossbeam receiver filled with events from the converter thread. receiver: Receiver, + + /// All of the paths that the fetcher is watching, tracked here because + /// notify does not expose this information. + watched_paths: HashSet, } impl RealFetcher { @@ -69,6 +76,7 @@ impl RealFetcher { watcher, _converter_thread: handle, receiver, + watched_paths: HashSet::new(), } } } @@ -132,8 +140,13 @@ impl ImfsFetcher for RealFetcher { log::trace!("Watching path {}", path.display()); if let Some(watcher) = self.watcher.as_mut() { - if let Err(err) = watcher.watch(path, RecursiveMode::NonRecursive) { - log::warn!("Couldn't watch path {}: {:?}", path.display(), err); + match watcher.watch(path, RecursiveMode::NonRecursive) { + Ok(_) => { + self.watched_paths.insert(path.to_path_buf()); + } + Err(err) => { + log::warn!("Couldn't watch path {}: {:?}", path.display(), err); + } } } } @@ -142,6 +155,11 @@ impl ImfsFetcher for RealFetcher { log::trace!("Stopped watching path {}", path.display()); if let Some(watcher) = self.watcher.as_mut() { + // Remove the path from our watched paths regardless of the outcome + // of notify's unwatch to ensure we drop old paths in the event of a + // rename. + self.watched_paths.remove(path); + if let Err(err) = watcher.unwatch(path) { log::warn!("Couldn't unwatch path {}: {:?}", path.display(), err); } @@ -151,4 +169,8 @@ impl ImfsFetcher for RealFetcher { fn receiver(&self) -> Receiver { self.receiver.clone() } + + fn watched_paths(&self) -> Vec<&Path> { + self.watched_paths.iter().map(|v| v.as_path()).collect() + } } From 24b9f552eb314e08f0f7090f2f1361bc09b5bd38 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 25 Sep 2019 11:05:56 -0700 Subject: [PATCH 0713/1504] Improve imfs debugging page --- assets/index.css | 23 ++++++++++++++++++++--- src/web/ui.rs | 26 ++++++++++++++++++++++---- 2 files changed, 42 insertions(+), 7 deletions(-) diff --git a/assets/index.css b/assets/index.css index 71dd9474..270a70fc 100644 --- a/assets/index.css +++ b/assets/index.css @@ -6,6 +6,7 @@ color: inherit; font: inherit; box-sizing: inherit; + line-height: inherit; } html { @@ -14,6 +15,7 @@ html { font-size: 18px; text-decoration: none; height: 100%; + line-height: 1.4; } body { @@ -29,6 +31,11 @@ img { height: auto; } +.path-list > li { + margin-left: 1rem; + font-family: monospace; +} + .root { flex: 0 0; display: flex; @@ -73,6 +80,14 @@ img { font-weight: bold; } +.main-section:not(:last-of-type) { + margin-bottom: 1rem; +} + +.section-title { + font-size: 1.8rem; +} + .button-list { flex: 0 0; display: flex; @@ -114,16 +129,17 @@ img { .imfs-entry-name { position: relative; + font-family: monospace; } .imfs-entry-children .imfs-entry-name::before { content: ""; - width: 0.8rem; + width: 0.6em; height: 1px; background-color: #999; position: absolute; top: 50%; - left: -1rem; + left: -0.8em; } .imfs-entry-note { @@ -131,6 +147,7 @@ img { } .imfs-entry-children { - padding-left: 1rem; + padding-left: 0.8em; + margin-left: 0.2em; border-left: 1px solid #999; } \ No newline at end of file diff --git a/src/web/ui.rs b/src/web/ui.rs index a2b95713..973e5845 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -104,10 +104,28 @@ impl UiService { .map(|path| Self::render_imfs_path(&imfs, path, true)) .collect(); + let watched_list: Vec<_> = imfs + .debug_watched_paths() + .into_iter() + .map(|path| { + html! { +
  • { format!("{}", path.display()) }
  • + } + }) + .collect(); + let page = self.normal_page(html! { -
    - { Fragment::new(orphans) } -
    + <> +
    +

    "Known FS Items"

    +
    { Fragment::new(orphans) }
    +
    + +
    +

    "Watched Paths"

    +
      { Fragment::new(watched_list) }
    +
    + }); Response::builder() @@ -140,7 +158,7 @@ impl UiService { let note = if is_exhaustive { HtmlContent::None } else { - html!({ " (non-exhaustive)" }) + html!({ " (not enumerated)" }) }; (note, children) From b3f132201b455e2a101cc616778e9b3d356ebe37 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 25 Sep 2019 14:47:07 -0700 Subject: [PATCH 0714/1504] Better expandables for the instance debugger --- assets/index.css | 43 +++++++++++++++++++++++++++++++++---------- src/web/ui.rs | 43 +++++++++++++++++++++++++++++++++++-------- 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/assets/index.css b/assets/index.css index 270a70fc..2d36296f 100644 --- a/assets/index.css +++ b/assets/index.css @@ -14,17 +14,9 @@ html { font-family: sans-serif; font-size: 18px; text-decoration: none; - height: 100%; line-height: 1.4; } -body { - min-height: 100%; - display: flex; - flex-direction: column; - justify-content: center; -} - img { max-width:100%; max-height:100%; @@ -37,7 +29,6 @@ img { } .root { - flex: 0 0; display: flex; flex-direction: column; margin: 0.5rem auto; @@ -112,7 +103,7 @@ img { } .instance-title { - font-size: 1.5rem; + font-size: 1.2rem; padding: 0.5rem; } @@ -124,6 +115,38 @@ img { padding: 0.5rem 0 0.5rem 1rem; } +.expandable-input { + display: none; +} + +.expandable-input ~ .expandable-label .expandable-visualizer { + font-family: monospace; + display: inline-flex; + justify-content: center; + align-items: center; + align-content: center; + width: 1rem; + height: 1rem; + border: 1px solid #666; + margin: 0 0.5rem; +} + +.expandable-visualizer::before { + content: ""; +} + +.expandable-input:checked ~ .expandable-label .expandable-visualizer::before { + content: "-"; +} + +.expandable-input:not(:checked) ~ .expandable-label .expandable-visualizer::before { + content: "+"; +} + +.expandable-input:not(:checked) ~ .expandable-items { + display: none; +} + .imfs-entry { } diff --git a/src/web/ui.rs b/src/web/ui.rs index 973e5845..2de8ccf4 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -202,9 +202,23 @@ impl UiService { HtmlContent::None } else { html! { -
    - { Fragment::new(children_list) } -
    +
    + + +

    + +

    +
    + { Fragment::new(children_list) } +
    +
    } }; @@ -226,9 +240,22 @@ impl UiService { HtmlContent::None } else { html! { -
    - { Fragment::new(property_list) } -
    +
    + + +

    + +

    +
    + { Fragment::new(property_list) } +
    +
    } }; @@ -244,10 +271,10 @@ impl UiService { html! {
    -
    +
    + { property_container } { children_container }
    From 91d12aeb4facc8575aeedf86575e1ed5bc73c71e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 25 Sep 2019 17:29:47 -0700 Subject: [PATCH 0715/1504] Break out expandable section into a component thing --- assets/index.css | 5 ++- src/web/ui.rs | 107 +++++++++++++++++++++++++++++++---------------- 2 files changed, 74 insertions(+), 38 deletions(-) diff --git a/assets/index.css b/assets/index.css index 2d36296f..14c45247 100644 --- a/assets/index.css +++ b/assets/index.css @@ -43,7 +43,6 @@ img { flex: 0 0; display: flex; flex-wrap: wrap; - /*justify-content: space-around;*/ align-items: center; border-bottom: 1px solid #666; } @@ -119,6 +118,10 @@ img { display: none; } +.expandable-label > label { + cursor: pointer; +} + .expandable-input ~ .expandable-label .expandable-visualizer { font-family: monospace; display: inline-flex; diff --git a/src/web/ui.rs b/src/web/ui.rs index 2de8ccf4..edf0a6a6 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -1,11 +1,12 @@ //! Defines the HTTP-based UI. These endpoints generally return HTML and SVG. -use std::{path::Path, sync::Arc, time::Duration}; +use std::{borrow::Cow, path::Path, sync::Arc, time::Duration}; use futures::{future, Future}; use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; +use maplit::hashmap; use rbx_dom_weak::{RbxId, RbxValue}; -use ritz::{html, Fragment, HtmlContent}; +use ritz::{html, Fragment, HtmlContent, HtmlSelfClosingTag}; use crate::{ imfs::{Imfs, ImfsDebug, ImfsFetcher}, @@ -201,25 +202,17 @@ impl UiService { let children_container = if children_list.is_empty() { HtmlContent::None } else { - html! { -
    - + let section = ExpandableSection { + title: "Children", + class_name: "instance-children", + id, + expanded: true, + content: html! { + { Fragment::new(children_list) } + }, + }; -

    - -

    -
    - { Fragment::new(children_list) } -
    -
    - } + section.render() }; let mut properties: Vec<_> = instance.properties().iter().collect(); @@ -239,24 +232,17 @@ impl UiService { let property_container = if property_list.is_empty() { HtmlContent::None } else { - html! { -
    - + let section = ExpandableSection { + title: "Properties", + class_name: "instance-properties", + id, + expanded: false, + content: html! { + { Fragment::new(property_list) } + }, + }; -

    - -

    -
    - { Fragment::new(property_list) } -
    -
    - } + section.render() }; let class_name_specifier = if instance.name() == instance.class_name() { @@ -355,3 +341,50 @@ impl UiService { } } } + +struct ExpandableSection<'a> { + title: &'a str, + class_name: &'a str, + id: RbxId, + expanded: bool, + content: HtmlContent<'a>, +} + +impl<'a> ExpandableSection<'a> { + fn render(self) -> HtmlContent<'a> { + let input_id = format!("{}-{}", self.class_name, self.id); + + // We need to specify this input manually because Ritz doesn't have + // support for conditional attributes like `checked`. + let mut input = HtmlSelfClosingTag { + name: Cow::Borrowed("input"), + attributes: hashmap! { + Cow::Borrowed("class") => Cow::Borrowed("expandable-input"), + Cow::Borrowed("id") => Cow::Owned(input_id.clone()), + Cow::Borrowed("type") => Cow::Borrowed("checkbox"), + }, + }; + + if self.expanded { + input + .attributes + .insert(Cow::Borrowed("checked"), Cow::Borrowed("checked")); + } + + html! { +
    + { input } + +

    + +

    +
    + { self.content } +
    +
    + } + } +} From 87227c96ed9df224786a2c7ef2b0c5c92fc1e675 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 26 Sep 2019 14:28:04 -0700 Subject: [PATCH 0716/1504] Document snapshot pipeline --- src/snapshot/mod.rs | 32 ++++++++++++++++++++++++++++---- src/snapshot/patch.rs | 2 +- src/snapshot/patch_apply.rs | 31 ++++++++++++++++++++++--------- 3 files changed, 51 insertions(+), 14 deletions(-) diff --git a/src/snapshot/mod.rs b/src/snapshot/mod.rs index 08cb6b31..47ef4794 100644 --- a/src/snapshot/mod.rs +++ b/src/snapshot/mod.rs @@ -1,8 +1,32 @@ //! This module defines the instance snapshot subsystem of Rojo. //! -//! It defines a way to define the instance tree of a project as a pure function -//! of the filesystem by providing a lightweight instance 'snapshot' type, a -//! method to generate minimal patches, and a method that applies those patches. +//! Snapshots define a way to define the instance tree of a project as a pure +//! function of the filesystem by providing a lightweight instance 'snapshot' +//! type, a method to generate minimal patches, and a method that applies those +//! patches. +//! +//! Changes in Rojo go through a pipeline of transformations once they hit the +//! snapshot subsystem. +//! +//! 1. Instance snapshots are generated by Rojo's snapshot middleware, +//! representing a set of instances and their metadata. These will +//! usually contain data that hasn't actually changed, and how coarsely +//! the snapshots happen is defined outside this part of the code. +//! +//! 2. Input snapshots are turned into `PatchSet` objects by Rojo's diffing +//! algorithm via `compute_patch_set`. This operation doesn't mutate the +//! instance tree, so work at this point can be thrown away. +//! +//! `PatchSet` prescribe what changes need to be applied to the current +//! tree to get the next tree. It isn't useful for describing those +//! changes after the fact, since Rojo needs to assign IDs to created +//! instances, which happens during patch application, not generation! +//! +//! 3. Patch sets are applied to the tree with `apply_patch_set`, which +//! mutates the relevant instances. `apply_patch_set` returns a new +//! object, `AppliedPatchSet`. Applied patch sets describe the transform +//! that was applied, and are suitable for cases where another tree needs +//! to be synchronized with Rojo's, like the Rojo Studio plugin. //! //! The aim with this approach is to reduce the number of bugs that arise from //! attempting to manually update instances in response to filesystem updates. @@ -26,7 +50,7 @@ mod patch_compute; mod tree; pub use instance_snapshot::InstanceSnapshot; -pub use metadata::*; +pub use metadata::InstanceMetadata; pub use patch::*; pub use patch_apply::apply_patch_set; pub use patch_compute::compute_patch_set; diff --git a/src/snapshot/patch.rs b/src/snapshot/patch.rs index ca77df7c..7833a677 100644 --- a/src/snapshot/patch.rs +++ b/src/snapshot/patch.rs @@ -60,7 +60,7 @@ pub struct PatchUpdate { /// // TODO: Introduce machinery to detect conflicts, like keeping previous + // current values in all fields. -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Default)] pub struct AppliedPatchSet { pub removed: Vec, pub added: Vec, diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index 0d7c9b78..7463f3c6 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -13,7 +13,7 @@ pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) -> AppliedPatch let mut context = PatchApplyContext::default(); for removed_id in patch_set.removed_instances { - tree.remove_instance(removed_id); + apply_remove_instance(&mut context, tree, removed_id); } for add_patch in patch_set.added_instances { @@ -21,22 +21,21 @@ pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) -> AppliedPatch } for update_patch in patch_set.updated_instances { - apply_update_child(&context, tree, update_patch); + apply_update_child(&mut context, tree, update_patch); } - apply_deferred_properties(context, tree); - - // TODO: Actually calculate patch set - AppliedPatchSet::new() + finalize_patch_application(context, tree) } #[derive(Default)] struct PatchApplyContext { snapshot_id_to_instance_id: HashMap, properties_to_apply: HashMap>, + applied_patch_set: AppliedPatchSet, } -/// Apply properties that were deferred in order to get more information. +/// Finalize this patch application, consuming the context, applying any +/// deferred property updates, and returning the finally applied patch set. /// /// Ref properties from snapshots refer to eachother via snapshot ID. Some of /// these properties are transformed when the patch is computed, notably the @@ -45,7 +44,7 @@ struct PatchApplyContext { /// The remaining Ref properties need to be handled during patch application, /// where we build up a map of snapshot IDs to instance IDs as they're created, /// then apply properties all at once at the end. -fn apply_deferred_properties(context: PatchApplyContext, tree: &mut RojoTree) { +fn finalize_patch_application(context: PatchApplyContext, tree: &mut RojoTree) -> AppliedPatchSet { for (id, mut properties) in context.properties_to_apply { let mut instance = tree .get_instance_mut(id) @@ -63,6 +62,20 @@ fn apply_deferred_properties(context: PatchApplyContext, tree: &mut RojoTree) { *instance.properties_mut() = properties; } + + context.applied_patch_set +} + +fn apply_remove_instance(context: &mut PatchApplyContext, tree: &mut RojoTree, removed_id: RbxId) { + match tree.remove_instance(removed_id) { + Some(_) => context.applied_patch_set.removed.push(removed_id), + None => { + log::warn!( + "Patch application error: Tried to remove instance {} but it did not exist.", + removed_id + ); + } + } } fn apply_add_child( @@ -98,7 +111,7 @@ fn apply_add_child( } } -fn apply_update_child(context: &PatchApplyContext, tree: &mut RojoTree, patch: PatchUpdate) { +fn apply_update_child(context: &mut PatchApplyContext, tree: &mut RojoTree, patch: PatchUpdate) { if let Some(metadata) = patch.changed_metadata { tree.update_metadata(patch.id, metadata); } From a70b7ee1501a239636b37942c98e15b693a55c6b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 27 Sep 2019 15:03:57 -0700 Subject: [PATCH 0717/1504] Add GitHub Actions badge --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0aa29821..1cdb9279 100644 --- a/README.md +++ b/README.md @@ -10,8 +10,11 @@ Travis-CI Build Status + + Actions status + - Latest server version + Latest server version Rojo 0.5.x Documentation From e741f7b557154d4802da9f1c6860949e4da0d04e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 27 Sep 2019 15:07:11 -0700 Subject: [PATCH 0718/1504] Actually generate AppliedPatchSet objects (#250) * Start actually computing AppliedPatchSet values * Improve patch_apply documentation and flesh out applied patch code * Add file link notes * Stub out where tests for snapshot subsystem will go * Create baseline tests * Fix build failure by silencing Clippy --- src/change_processor.rs | 3 + src/snapshot/mod.rs | 9 +++ src/snapshot/patch.rs | 19 ++++-- src/snapshot/patch_apply.rs | 118 ++++++++++++++++++++++++++-------- src/snapshot/tests/apply.rs | 37 +++++++++++ src/snapshot/tests/compute.rs | 35 ++++++++++ src/snapshot/tests/mod.rs | 2 + 7 files changed, 190 insertions(+), 33 deletions(-) create mode 100644 src/snapshot/tests/apply.rs create mode 100644 src/snapshot/tests/compute.rs create mode 100644 src/snapshot/tests/mod.rs diff --git a/src/change_processor.rs b/src/change_processor.rs index 2ce22bc8..77ae51d4 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -51,6 +51,9 @@ impl ChangeProcessor { imfs.change_receiver() }; + // Crossbeam's select macro generates code that Clippy doesn't like, and + // Clippy blames us for it. + #[allow(clippy::drop_copy)] loop { select! { recv(imfs_receiver) -> event => { diff --git a/src/snapshot/mod.rs b/src/snapshot/mod.rs index 47ef4794..de269d5b 100644 --- a/src/snapshot/mod.rs +++ b/src/snapshot/mod.rs @@ -13,6 +13,8 @@ //! usually contain data that hasn't actually changed, and how coarsely //! the snapshots happen is defined outside this part of the code. //! +//! See `src/snapshot_middleware` for implementation. +//! //! 2. Input snapshots are turned into `PatchSet` objects by Rojo's diffing //! algorithm via `compute_patch_set`. This operation doesn't mutate the //! instance tree, so work at this point can be thrown away. @@ -22,12 +24,16 @@ //! changes after the fact, since Rojo needs to assign IDs to created //! instances, which happens during patch application, not generation! //! +//! See `src/snapshot/patch_compute.rs` for implementation. +//! //! 3. Patch sets are applied to the tree with `apply_patch_set`, which //! mutates the relevant instances. `apply_patch_set` returns a new //! object, `AppliedPatchSet`. Applied patch sets describe the transform //! that was applied, and are suitable for cases where another tree needs //! to be synchronized with Rojo's, like the Rojo Studio plugin. //! +//! See `src/snapshot/patch_apply.rs` for implementation. +//! //! The aim with this approach is to reduce the number of bugs that arise from //! attempting to manually update instances in response to filesystem updates. //! Instead of surgically identifying what needs to change, we can do rough @@ -55,3 +61,6 @@ pub use patch::*; pub use patch_apply::apply_patch_set; pub use patch_compute::compute_patch_set; pub use tree::*; + +#[cfg(test)] +mod tests; diff --git a/src/snapshot/patch.rs b/src/snapshot/patch.rs index 7833a677..3908f78b 100644 --- a/src/snapshot/patch.rs +++ b/src/snapshot/patch.rs @@ -63,7 +63,7 @@ pub struct PatchUpdate { #[derive(Debug, Clone, Default)] pub struct AppliedPatchSet { pub removed: Vec, - pub added: Vec, + pub added: Vec, pub updated: Vec, } @@ -77,11 +77,6 @@ impl AppliedPatchSet { } } -#[derive(Debug, Clone)] -pub struct AppliedPatchAdd { - pub instance_id: RbxId, -} - #[derive(Debug, Clone)] pub struct AppliedPatchUpdate { pub id: RbxId, @@ -92,3 +87,15 @@ pub struct AppliedPatchUpdate { pub changed_properties: HashMap>, pub changed_metadata: Option, } + +impl AppliedPatchUpdate { + pub fn new(id: RbxId) -> Self { + Self { + id, + changed_name: None, + changed_class_name: None, + changed_properties: HashMap::new(), + changed_metadata: None, + } + } +} diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index 7463f3c6..ea28f302 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -5,10 +5,13 @@ use std::collections::HashMap; use rbx_dom_weak::{RbxId, RbxInstanceProperties, RbxValue}; use super::{ - patch::{AppliedPatchSet, PatchSet, PatchUpdate}, + patch::{AppliedPatchSet, AppliedPatchUpdate, PatchSet, PatchUpdate}, InstancePropertiesWithMeta, InstanceSnapshot, RojoTree, }; +/// Consumes the input `PatchSet`, applying all of its prescribed changes to the +/// tree and returns an `AppliedPatchSet`, which can be used to keep another +/// tree in sync with Rojo's. pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) -> AppliedPatchSet { let mut context = PatchApplyContext::default(); @@ -17,9 +20,11 @@ pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) -> AppliedPatch } for add_patch in patch_set.added_instances { - apply_add_child(&mut context, tree, add_patch.parent_id, &add_patch.instance); + apply_add_child(&mut context, tree, add_patch.parent_id, add_patch.instance); } + // Updates need to be applied after additions, which reduces the complexity + // of updates significantly. for update_patch in patch_set.updated_instances { apply_update_child(&mut context, tree, update_patch); } @@ -27,10 +32,45 @@ pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) -> AppliedPatch finalize_patch_application(context, tree) } +/// All of the ephemeral state needing during application of a patch. #[derive(Default)] struct PatchApplyContext { + /// A map from transient snapshot IDs (generated by snapshot middleware) to + /// instance IDs in the actual tree. These are both the same data type so + /// that they fit into the same `RbxValue::Ref` type. + /// + /// At this point in the patch process, IDs in instance properties have been + /// partially translated from 'snapshot space' into 'tree space' by the + /// patch computation process. An ID not existing in this map means either: + /// + /// 1. The ID is already in tree space and refers to an instance that + /// existed in the tree before this patch was applied. + /// + /// 2. The ID if in snapshot space, but points to an instance that was not + /// part of the snapshot that was put through the patch computation + /// function. + /// + /// #2 should not occur in well-formed projects, but is indistinguishable + /// from #1 right now. It could happen if two model files try to reference + /// eachother. snapshot_id_to_instance_id: HashMap, - properties_to_apply: HashMap>, + + /// The properties of instances added by the current `PatchSet`. + /// + /// Instances added to the tree can refer to eachother via Ref properties, + /// but we need to make sure they're correctly transformed from snapshot + /// space into tree space (via `snapshot_id_to_instance_id`). + /// + /// It's not possible to do that transformation for refs that refer to added + /// instances until all the instances have actually been inserted into the + /// tree. For simplicity, we defer application of _all_ properties on added + /// instances instead of just Refs. + /// + /// This doesn't affect updated instances, since they're always applied + /// after we've added all the instances from the patch. + added_instance_properties: HashMap>, + + /// The current applied patch result, describing changes made to the tree. applied_patch_set: AppliedPatchSet, } @@ -45,22 +85,24 @@ struct PatchApplyContext { /// where we build up a map of snapshot IDs to instance IDs as they're created, /// then apply properties all at once at the end. fn finalize_patch_application(context: PatchApplyContext, tree: &mut RojoTree) -> AppliedPatchSet { - for (id, mut properties) in context.properties_to_apply { + for (id, properties) in context.added_instance_properties { + // This should always succeed since instances marked as added in our + // patch should be added without fail. let mut instance = tree .get_instance_mut(id) .expect("Invalid instance ID in deferred property map"); - for property_value in properties.values_mut() { + for (key, mut property_value) in properties { if let RbxValue::Ref { value: Some(id) } = property_value { - if let Some(&instance_id) = context.snapshot_id_to_instance_id.get(id) { - *property_value = RbxValue::Ref { + if let Some(&instance_id) = context.snapshot_id_to_instance_id.get(&id) { + property_value = RbxValue::Ref { value: Some(instance_id), }; } } - } - *instance.properties_mut() = properties; + instance.properties_mut().insert(key, property_value); + } } context.applied_patch_set @@ -71,7 +113,7 @@ fn apply_remove_instance(context: &mut PatchApplyContext, tree: &mut RojoTree, r Some(_) => context.applied_patch_set.removed.push(removed_id), None => { log::warn!( - "Patch application error: Tried to remove instance {} but it did not exist.", + "Patch misapplication: Tried to remove instance {} but it did not exist.", removed_id ); } @@ -82,50 +124,64 @@ fn apply_add_child( context: &mut PatchApplyContext, tree: &mut RojoTree, parent_id: RbxId, - snapshot: &InstanceSnapshot, + snapshot: InstanceSnapshot, ) { let properties = InstancePropertiesWithMeta { properties: RbxInstanceProperties { - name: snapshot.name.clone().into_owned(), - class_name: snapshot.class_name.clone().into_owned(), + name: snapshot.name.into_owned(), + class_name: snapshot.class_name.into_owned(), // Property assignment is deferred until after we know about all - // instances in this patch. + // instances in this patch. See `PatchApplyContext` for details. properties: HashMap::new(), }, - metadata: Default::default(), // TODO + metadata: snapshot.metadata, }; let id = tree.insert_instance(properties, parent_id); + context.applied_patch_set.added.push(id); + context - .properties_to_apply - .insert(id, snapshot.properties.clone()); + .added_instance_properties + .insert(id, snapshot.properties); if let Some(snapshot_id) = snapshot.snapshot_id { context.snapshot_id_to_instance_id.insert(snapshot_id, id); } - for child_snapshot in &snapshot.children { + for child_snapshot in snapshot.children { apply_add_child(context, tree, id, child_snapshot); } } fn apply_update_child(context: &mut PatchApplyContext, tree: &mut RojoTree, patch: PatchUpdate) { + let mut applied_patch = AppliedPatchUpdate::new(patch.id); + if let Some(metadata) = patch.changed_metadata { - tree.update_metadata(patch.id, metadata); + tree.update_metadata(patch.id, metadata.clone()); + applied_patch.changed_metadata = Some(metadata); } - let mut instance = tree - .get_instance_mut(patch.id) - .expect("Instance referred to by patch does not exist"); + let mut instance = match tree.get_instance_mut(patch.id) { + Some(instance) => instance, + None => { + log::warn!( + "Patch misapplication: Instance {}, referred to by update patch, did not exist.", + patch.id + ); + return; + } + }; if let Some(name) = patch.changed_name { - *instance.name_mut() = name; + *instance.name_mut() = name.clone(); + applied_patch.changed_name = Some(name); } if let Some(class_name) = patch.changed_class_name { - *instance.class_name_mut() = class_name; + *instance.class_name_mut() = class_name.clone(); + applied_patch.changed_class_name = Some(class_name); } for (key, property_entry) in patch.changed_properties { @@ -134,6 +190,10 @@ fn apply_update_child(context: &mut PatchApplyContext, tree: &mut RojoTree, patc // instance IDs if they referred to an instance that was created as // part of this patch. Some(RbxValue::Ref { value: Some(id) }) => { + // If our ID is not found in this map, then it either refers to + // an existing instance NOT added by this patch, or there was an + // error. See `PatchApplyContext::snapshot_id_to_instance_id` + // for more info. let new_id = context .snapshot_id_to_instance_id .get(&id) @@ -141,20 +201,24 @@ fn apply_update_child(context: &mut PatchApplyContext, tree: &mut RojoTree, patc .unwrap_or(id); instance.properties_mut().insert( - key, + key.clone(), RbxValue::Ref { value: Some(new_id), }, ); } - Some(value) => { - instance.properties_mut().insert(key, value); + Some(ref value) => { + instance.properties_mut().insert(key.clone(), value.clone()); } None => { instance.properties_mut().remove(&key); } } + + applied_patch.changed_properties.insert(key, property_entry); } + + context.applied_patch_set.updated.push(applied_patch) } #[cfg(test)] diff --git a/src/snapshot/tests/apply.rs b/src/snapshot/tests/apply.rs new file mode 100644 index 00000000..f06fa271 --- /dev/null +++ b/src/snapshot/tests/apply.rs @@ -0,0 +1,37 @@ +use rbx_dom_weak::RbxInstanceProperties; + +use crate::snapshot::{ + apply_patch_set, InstancePropertiesWithMeta, PatchSet, PatchUpdate, RojoTree, +}; + +#[test] +fn reify_folder() { + let mut tree = empty_tree(); + + let patch_set = PatchSet { + updated_instances: vec![PatchUpdate { + id: tree.get_root_id(), + changed_name: Some("Hello, world!".to_owned()), + changed_class_name: Some("Folder".to_owned()), + changed_properties: Default::default(), + changed_metadata: None, + }], + ..Default::default() + }; + + let _applied_patch_set = apply_patch_set(&mut tree, patch_set); + + // TODO: Make assertions about tree using snapshots + // TODO: make assertions about applied patch set using snapshots +} + +fn empty_tree() -> RojoTree { + RojoTree::new(InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "ROOT".to_owned(), + class_name: "ROOT".to_owned(), + properties: Default::default(), + }, + metadata: Default::default(), + }) +} diff --git a/src/snapshot/tests/compute.rs b/src/snapshot/tests/compute.rs new file mode 100644 index 00000000..c523c3d1 --- /dev/null +++ b/src/snapshot/tests/compute.rs @@ -0,0 +1,35 @@ +use std::borrow::Cow; + +use rbx_dom_weak::RbxInstanceProperties; + +use crate::snapshot::{compute_patch_set, InstancePropertiesWithMeta, InstanceSnapshot, RojoTree}; + +#[test] +fn reify_folder() { + let tree = empty_tree(); + + let folder = InstanceSnapshot { + snapshot_id: None, + metadata: Default::default(), + name: Cow::Borrowed("Some Folder"), + class_name: Cow::Borrowed("Folder"), + properties: Default::default(), + children: Vec::new(), + }; + + let _patch_set = compute_patch_set(&folder, &tree, tree.get_root_id()); + + // TODO: Make assertions about patch set using snapshots. This needs patches + // to be serializable and also to have ID redactions more readily available. +} + +fn empty_tree() -> RojoTree { + RojoTree::new(InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "ROOT".to_owned(), + class_name: "ROOT".to_owned(), + properties: Default::default(), + }, + metadata: Default::default(), + }) +} diff --git a/src/snapshot/tests/mod.rs b/src/snapshot/tests/mod.rs new file mode 100644 index 00000000..35edf7ae --- /dev/null +++ b/src/snapshot/tests/mod.rs @@ -0,0 +1,2 @@ +mod apply; +mod compute; From fd22482f0657acea1223e8a84d0a453d3e9ac7c3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 27 Sep 2019 15:09:35 -0700 Subject: [PATCH 0719/1504] Goodbye Travis --- .travis.yml | 18 ------------------ README.md | 3 --- 2 files changed, 21 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 8a30fe0d..00000000 --- a/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -matrix: - include: - - language: rust - rust: 1.36.0 - cache: cargo - - script: - - cargo test --all --locked --verbose - - - language: rust - rust: stable - cache: cargo - - install: - - rustup component add rustfmt - - rustup component add clippy - - script: ./bin/run-tests.sh \ No newline at end of file diff --git a/README.md b/README.md index 1cdb9279..cd71f8c7 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,6 @@
     
    - - Travis-CI Build Status - Actions status From ab8aa89f2a546ca31203131a93be4fb34ee506bb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 29 Sep 2019 20:16:54 -0700 Subject: [PATCH 0720/1504] Add real networked message type --- src/web/api.rs | 12 +++++++++++- src/web/interface.rs | 23 +++++++++++++++++++---- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/src/web/api.rs b/src/web/api.rs index 6793e089..1c979e74 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -94,7 +94,17 @@ impl ApiService { // TODO: Transform applied patch sets into subscribe responses let api_messages = messages .into_iter() - .map(|_message| SubscribeMessage) + .map(|message| { + let removed_instances = message.removed; + let added_instances = HashMap::new(); // TODO + let updated_instances = Vec::new(); // TODO + + SubscribeMessage { + removed_instances, + added_instances, + updated_instances, + } + }) .collect(); json_ok(SubscribeResponse { diff --git a/src/web/interface.rs b/src/web/interface.rs index c2fd3ca5..a3ab3432 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -16,9 +16,24 @@ pub(crate) const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); /// Current protocol version, which is required to match. pub const PROTOCOL_VERSION: u64 = 3; -// TODO +/// Message returned by Rojo API when a change has occurred. #[derive(Debug, Serialize, Deserialize)] -pub struct SubscribeMessage; +#[serde(rename_all = "camelCase")] +pub struct SubscribeMessage<'a> { + pub removed_instances: Vec, + pub added_instances: HashMap>, + pub updated_instances: Vec, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct InstanceUpdate { + pub id: RbxId, + pub changed_name: Option, + pub changed_class_name: Option, + pub changed_properties: HashMap, + pub changed_metadata: Option, +} #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] @@ -73,10 +88,10 @@ pub struct ReadResponse<'a> { /// Response body from /api/subscribe/{cursor} #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] -pub struct SubscribeResponse { +pub struct SubscribeResponse<'a> { pub session_id: SessionId, pub message_cursor: u32, - pub messages: Vec, + pub messages: Vec>, } /// General response type returned from all Rojo routes From 3678ddfa364aac3bbc1d6ec142f0926a0cd341e8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 30 Sep 2019 16:27:31 -0700 Subject: [PATCH 0721/1504] Break redaction stuff out into separate crate --- Cargo.lock | 12 ++++- Cargo.toml | 3 ++ rojo-insta-ext/Cargo.toml | 14 +++++ rojo-insta-ext/README.md | 2 + rojo-insta-ext/src/lib.rs | 3 ++ rojo-insta-ext/src/redaction_map.rs | 75 ++++++++++++++++++++++++++ rojo-test/Cargo.toml | 2 +- rojo-test/README.md | 8 +++ rojo-test/src/serve_test.rs | 83 ++++------------------------- 9 files changed, 127 insertions(+), 75 deletions(-) create mode 100644 rojo-insta-ext/Cargo.toml create mode 100644 rojo-insta-ext/README.md create mode 100644 rojo-insta-ext/src/lib.rs create mode 100644 rojo-insta-ext/src/redaction_map.rs create mode 100644 rojo-test/README.md diff --git a/Cargo.lock b/Cargo.lock index 0b0e216e..9a8686aa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1474,6 +1474,7 @@ dependencies = [ "regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rojo-insta-ext 0.1.0", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1483,6 +1484,15 @@ dependencies = [ "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rojo-insta-ext" +version = "0.1.0" +dependencies = [ + "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rojo-test" version = "0.1.0" @@ -1494,9 +1504,9 @@ dependencies = [ "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", "rojo 0.6.0-dev", + "rojo-insta-ext 0.1.0", "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index e16e76d1..b1826785 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,11 +21,13 @@ dev-live-assets = [] [workspace] members = [ "rojo-test", + "rojo-insta-ext", ] default-members = [ ".", "rojo-test", + "rojo-insta-ext", ] [lib] @@ -65,6 +67,7 @@ uuid = { version = "0.7", features = ["v4", "serde"] } winreg = "0.6.2" [dev-dependencies] +rojo-insta-ext = { path = "rojo-insta-ext" } lazy_static = "1.2" paste = "0.1" pretty_assertions = "0.6.1" diff --git a/rojo-insta-ext/Cargo.toml b/rojo-insta-ext/Cargo.toml new file mode 100644 index 00000000..f072ab91 --- /dev/null +++ b/rojo-insta-ext/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "rojo-insta-ext" +version = "0.1.0" +authors = ["Lucien Greathouse "] +edition = "2018" +publish = false + +[dependencies] +serde = "1.0.99" +serde_yaml = "0.8.9" + +[dependencies.insta] +version = "0.11.0" +features = ["redactions"] diff --git a/rojo-insta-ext/README.md b/rojo-insta-ext/README.md new file mode 100644 index 00000000..5ffb9dde --- /dev/null +++ b/rojo-insta-ext/README.md @@ -0,0 +1,2 @@ +# Rojo Insta Extensions +This crate has add-ons intended for use with Insta that are useful for snapshot tests. \ No newline at end of file diff --git a/rojo-insta-ext/src/lib.rs b/rojo-insta-ext/src/lib.rs new file mode 100644 index 00000000..bcfd1f20 --- /dev/null +++ b/rojo-insta-ext/src/lib.rs @@ -0,0 +1,3 @@ +mod redaction_map; + +pub use redaction_map::*; diff --git a/rojo-insta-ext/src/redaction_map.rs b/rojo-insta-ext/src/redaction_map.rs new file mode 100644 index 00000000..dce3cb5d --- /dev/null +++ b/rojo-insta-ext/src/redaction_map.rs @@ -0,0 +1,75 @@ +use std::collections::HashMap; + +use serde::Serialize; + +/// Enables redacting any value that serializes as a string. +/// +/// Used for transforming Rojo instance IDs into something deterministic. +pub struct RedactionMap { + ids: HashMap, + last_id: usize, +} + +impl RedactionMap { + pub fn new() -> Self { + Self { + ids: HashMap::new(), + last_id: 0, + } + } + + pub fn intern(&mut self, id: impl ToString) { + let last_id = &mut self.last_id; + + self.ids.entry(id.to_string()).or_insert_with(|| { + *last_id += 1; + *last_id + }); + } + + pub fn intern_iter(&mut self, ids: impl Iterator) { + for id in ids { + self.intern(id.to_string()); + } + } + + pub fn redacted_yaml(&self, value: impl Serialize) -> serde_yaml::Value { + let mut encoded = serde_yaml::to_value(value).expect("Couldn't encode value as YAML"); + + self.redact(&mut encoded); + encoded + } + + pub fn redact(&self, yaml_value: &mut serde_yaml::Value) { + use serde_yaml::{Mapping, Value}; + + match yaml_value { + Value::String(value) => { + if let Some(redacted) = self.ids.get(value) { + *yaml_value = Value::String(format!("id-{}", *redacted)); + } + } + Value::Sequence(sequence) => { + for value in sequence { + self.redact(value); + } + } + Value::Mapping(mapping) => { + // We can't mutate the keys of a map in-place, so we take + // ownership of the map and rebuild it. + + let owned_map = std::mem::replace(mapping, Mapping::new()); + let mut new_map = Mapping::with_capacity(owned_map.len()); + + for (mut key, mut value) in owned_map { + self.redact(&mut key); + self.redact(&mut value); + new_map.insert(key, value); + } + + *mapping = new_map; + } + _ => {} + } + } +} diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index 2a9e5c56..173cbb16 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -13,9 +13,9 @@ rbx_dom_weak = "1.9.0" reqwest = "0.9.20" serde = "1.0.99" serde_json = "1.0.40" -serde_yaml = "0.8.9" tempfile = "3.1.0" walkdir = "2.2.9" +rojo-insta-ext = { path = "../rojo-insta-ext" } # We execute Rojo via std::process::Command, so depend on it so it's built! rojo = { path = ".." } diff --git a/rojo-test/README.md b/rojo-test/README.md new file mode 100644 index 00000000..166044a1 --- /dev/null +++ b/rojo-test/README.md @@ -0,0 +1,8 @@ +# rojo-test +This project does end-to-end testing of Rojo by executing it and checking what side-effects it has. + +rojo-test is meant to be run as a test with: + +```bash +cargo test +``` \ No newline at end of file diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index a5887655..2cdff469 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -11,6 +11,7 @@ use rbx_dom_weak::RbxId; use tempfile::{tempdir, TempDir}; use librojo::web_interface::{ReadResponse, ServerInfoResponse}; +use rojo_insta_ext::RedactionMap; use crate::util::{ copy_recursive, get_rojo_path, get_serve_tests_path, get_working_dir_path, KillOnDrop, @@ -18,28 +19,26 @@ use crate::util::{ #[test] fn empty() { - run_serve_test(|session, mut dm| { + run_serve_test(|session, mut redactions| { let info = session.get_api_rojo().unwrap(); let root_id = info.root_instance_id; - let mut info = serde_yaml::to_value(info).unwrap(); - dm.redact(&mut info); + let info = redactions.redacted_yaml(info); assert_yaml_snapshot!(info); let read_result = session.get_api_read(root_id).unwrap(); - dm.intern_iter(read_result.instances.keys().copied()); + redactions.intern_iter(read_result.instances.keys().copied()); - let mut read_result = serde_yaml::to_value(read_result).unwrap(); - dm.redact(&mut read_result); + let read_result = redactions.redacted_yaml(read_result); assert_yaml_snapshot!(read_result); }); } -fn run_serve_test(callback: impl FnOnce(TestServeSession, DeterMap)) { +fn run_serve_test(callback: impl FnOnce(TestServeSession, RedactionMap)) { let _ = env_logger::try_init(); let mut settings = insta::Settings::new(); @@ -47,77 +46,15 @@ fn run_serve_test(callback: impl FnOnce(TestServeSession, DeterMap)) { let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("serve-test-snapshots"); settings.set_snapshot_path(snapshot_path); - let mut dm = DeterMap::new(); + let mut redactions = RedactionMap::new(); let mut session = TestServeSession::new("empty"); let info = session.wait_to_come_online(); - dm.intern(info.session_id); - dm.intern(info.root_instance_id); + redactions.intern(info.session_id); + redactions.intern(info.root_instance_id); - settings.bind(move || callback(session, dm)); -} - -struct DeterMap { - ids: HashMap, - last_id: usize, -} - -impl DeterMap { - fn new() -> DeterMap { - DeterMap { - ids: HashMap::new(), - last_id: 0, - } - } - - fn intern(&mut self, id: impl ToString) { - let last_id = &mut self.last_id; - - self.ids.entry(id.to_string()).or_insert_with(|| { - *last_id += 1; - *last_id - }); - } - - fn intern_iter(&mut self, ids: impl Iterator) { - for id in ids { - self.intern(id.to_string()); - } - } - - fn redact(&self, yaml_value: &mut serde_yaml::Value) { - use serde_yaml::{Mapping, Value}; - - match yaml_value { - Value::String(value) => { - if let Some(redacted) = self.ids.get(value) { - *yaml_value = Value::String(format!("id-{}", *redacted)); - } - } - Value::Sequence(sequence) => { - for value in sequence { - self.redact(value); - } - } - Value::Mapping(mapping) => { - // We can't mutate the keys of a map in-place, so we take - // ownership of the map and rebuild it. - - let owned_map = std::mem::replace(mapping, Mapping::new()); - let mut new_map = Mapping::with_capacity(owned_map.len()); - - for (mut key, mut value) in owned_map { - self.redact(&mut key); - self.redact(&mut value); - new_map.insert(key, value); - } - - *mapping = new_map; - } - _ => {} - } - } + settings.bind(move || callback(session, redactions)); } fn get_port_number() -> usize { From b512e707a527552f2754fbd5fc2563077125b0d9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 30 Sep 2019 17:00:12 -0700 Subject: [PATCH 0722/1504] First round of snapshot tests for patch_compute --- Cargo.lock | 1 + Cargo.toml | 5 ++ src/snapshot/instance_snapshot.rs | 3 +- src/snapshot/metadata.rs | 4 +- src/snapshot/patch.rs | 7 +- src/snapshot/tests/compute.rs | 80 +++++++++++++++++-- .../snapshots/compute__remove_property.snap | 13 +++ .../compute__set_name_and_class_name.snap | 12 +++ .../snapshots/compute__set_property.snap | 15 ++++ 9 files changed, 128 insertions(+), 12 deletions(-) create mode 100644 src/snapshot/tests/snapshots/compute__remove_property.snap create mode 100644 src/snapshot/tests/snapshots/compute__set_name_and_class_name.snap create mode 100644 src/snapshot/tests/snapshots/compute__set_property.snap diff --git a/Cargo.lock b/Cargo.lock index 9a8686aa..04940478 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1460,6 +1460,7 @@ dependencies = [ "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", + "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index b1826785..81bdd960 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,8 +68,13 @@ winreg = "0.6.2" [dev-dependencies] rojo-insta-ext = { path = "rojo-insta-ext" } + lazy_static = "1.2" paste = "0.1" pretty_assertions = "0.6.1" tempfile = "3.0" walkdir = "2.1" + +[dev-dependencies.insta] +version = "0.11.0" +features = ["redactions"] diff --git a/src/snapshot/instance_snapshot.rs b/src/snapshot/instance_snapshot.rs index 83ad5055..e609c66c 100644 --- a/src/snapshot/instance_snapshot.rs +++ b/src/snapshot/instance_snapshot.rs @@ -3,6 +3,7 @@ use std::{borrow::Cow, collections::HashMap}; use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; +use serde::{Deserialize, Serialize}; use super::InstanceMetadata; @@ -13,7 +14,7 @@ use super::InstanceMetadata; // Possible future improvements: // - Use refcounted/interned strings // - Replace use of RbxValue with a sum of RbxValue + borrowed value -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct InstanceSnapshot<'source> { /// A temporary ID applied to the snapshot that's used for Ref properties. pub snapshot_id: Option, diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index 4dface7b..eadbd1ca 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -1,10 +1,12 @@ use std::path::PathBuf; +use serde::{Deserialize, Serialize}; + use crate::project::ProjectNode; /// Rojo-specific metadata that can be associated with an instance or a snapshot /// of an instance. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct InstanceMetadata { /// Whether instances not present in the source should be ignored when /// live-syncing. This is useful when there are instances that Rojo does not diff --git a/src/snapshot/patch.rs b/src/snapshot/patch.rs index 3908f78b..f7ce22b0 100644 --- a/src/snapshot/patch.rs +++ b/src/snapshot/patch.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; use rbx_dom_weak::{RbxId, RbxValue}; +use serde::{Deserialize, Serialize}; use super::{InstanceMetadata, InstanceSnapshot}; @@ -11,7 +12,7 @@ use super::{InstanceMetadata, InstanceSnapshot}; /// These patches shouldn't be persisted: there's no mechanism in place to make /// sure that another patch wasn't applied before this one that could cause a /// conflict! -#[derive(Debug, Default, Clone, PartialEq)] +#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] pub struct PatchSet<'a> { pub removed_instances: Vec, pub added_instances: Vec>, @@ -29,14 +30,14 @@ impl<'a> PatchSet<'a> { } /// A patch containing an instance that was added to the tree. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct PatchAdd<'a> { pub parent_id: RbxId, pub instance: InstanceSnapshot<'a>, } /// A patch indicating that properties of an instance changed. -#[derive(Debug, Clone, PartialEq)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct PatchUpdate { pub id: RbxId, pub changed_name: Option, diff --git a/src/snapshot/tests/compute.rs b/src/snapshot/tests/compute.rs index c523c3d1..3478d484 100644 --- a/src/snapshot/tests/compute.rs +++ b/src/snapshot/tests/compute.rs @@ -1,14 +1,21 @@ use std::borrow::Cow; -use rbx_dom_weak::RbxInstanceProperties; +use insta::assert_yaml_snapshot; +use maplit::hashmap; +use rbx_dom_weak::{RbxInstanceProperties, RbxValue}; + +use rojo_insta_ext::RedactionMap; use crate::snapshot::{compute_patch_set, InstancePropertiesWithMeta, InstanceSnapshot, RojoTree}; #[test] -fn reify_folder() { - let tree = empty_tree(); +fn set_name_and_class_name() { + let mut redactions = RedactionMap::new(); - let folder = InstanceSnapshot { + let tree = empty_tree(); + redactions.intern(tree.get_root_id()); + + let snapshot = InstanceSnapshot { snapshot_id: None, metadata: Default::default(), name: Cow::Borrowed("Some Folder"), @@ -17,10 +24,69 @@ fn reify_folder() { children: Vec::new(), }; - let _patch_set = compute_patch_set(&folder, &tree, tree.get_root_id()); + let patch_set = compute_patch_set(&snapshot, &tree, tree.get_root_id()); + let patch_value = redactions.redacted_yaml(patch_set); - // TODO: Make assertions about patch set using snapshots. This needs patches - // to be serializable and also to have ID redactions more readily available. + assert_yaml_snapshot!(patch_value); +} + +#[test] +fn set_property() { + let mut redactions = RedactionMap::new(); + + let tree = empty_tree(); + redactions.intern(tree.get_root_id()); + + let snapshot = InstanceSnapshot { + snapshot_id: None, + metadata: Default::default(), + name: Cow::Borrowed("ROOT"), + class_name: Cow::Borrowed("ROOT"), + properties: hashmap! { + "PropertyName".to_owned() => RbxValue::String { + value: "Hello, world!".to_owned(), + }, + }, + children: Vec::new(), + }; + + let patch_set = compute_patch_set(&snapshot, &tree, tree.get_root_id()); + let patch_value = redactions.redacted_yaml(patch_set); + + assert_yaml_snapshot!(patch_value); +} + +#[test] +fn remove_property() { + let mut redactions = RedactionMap::new(); + + let mut tree = empty_tree(); + redactions.intern(tree.get_root_id()); + + { + let root_id = tree.get_root_id(); + let mut root_instance = tree.get_instance_mut(root_id).unwrap(); + root_instance.properties_mut().insert( + "Foo".to_owned(), + RbxValue::String { + value: "This should be removed by the patch.".to_owned(), + }, + ); + } + + let snapshot = InstanceSnapshot { + snapshot_id: None, + metadata: Default::default(), + name: Cow::Borrowed("ROOT"), + class_name: Cow::Borrowed("ROOT"), + properties: Default::default(), + children: Vec::new(), + }; + + let patch_set = compute_patch_set(&snapshot, &tree, tree.get_root_id()); + let patch_value = redactions.redacted_yaml(patch_set); + + assert_yaml_snapshot!(patch_value); } fn empty_tree() -> RojoTree { diff --git a/src/snapshot/tests/snapshots/compute__remove_property.snap b/src/snapshot/tests/snapshots/compute__remove_property.snap new file mode 100644 index 00000000..44e81098 --- /dev/null +++ b/src/snapshot/tests/snapshots/compute__remove_property.snap @@ -0,0 +1,13 @@ +--- +source: src/snapshot/tests/compute.rs +expression: patch_value +--- +removed_instances: [] +added_instances: [] +updated_instances: + - id: id-1 + changed_name: ~ + changed_class_name: ~ + changed_properties: + Foo: ~ + changed_metadata: ~ diff --git a/src/snapshot/tests/snapshots/compute__set_name_and_class_name.snap b/src/snapshot/tests/snapshots/compute__set_name_and_class_name.snap new file mode 100644 index 00000000..f949a901 --- /dev/null +++ b/src/snapshot/tests/snapshots/compute__set_name_and_class_name.snap @@ -0,0 +1,12 @@ +--- +source: src/snapshot/tests/compute.rs +expression: patch_value +--- +removed_instances: [] +added_instances: [] +updated_instances: + - id: id-1 + changed_name: Some Folder + changed_class_name: Folder + changed_properties: {} + changed_metadata: ~ diff --git a/src/snapshot/tests/snapshots/compute__set_property.snap b/src/snapshot/tests/snapshots/compute__set_property.snap new file mode 100644 index 00000000..8c39d3fd --- /dev/null +++ b/src/snapshot/tests/snapshots/compute__set_property.snap @@ -0,0 +1,15 @@ +--- +source: src/snapshot/tests/compute.rs +expression: patch_value +--- +removed_instances: [] +added_instances: [] +updated_instances: + - id: id-1 + changed_name: ~ + changed_class_name: ~ + changed_properties: + PropertyName: + Type: String + Value: "Hello, world!" + changed_metadata: ~ From 5f5bfadf2b6521c3e3cf91bcfe5d40be872ef9db Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 30 Sep 2019 17:04:45 -0700 Subject: [PATCH 0723/1504] Add compute_patch tests for adding/removing children --- src/snapshot/tests/compute.rs | 68 +++++++++++++++++++ .../tests/snapshots/compute__add_child.snap | 18 +++++ .../snapshots/compute__remove_child.snap | 8 +++ 3 files changed, 94 insertions(+) create mode 100644 src/snapshot/tests/snapshots/compute__add_child.snap create mode 100644 src/snapshot/tests/snapshots/compute__remove_child.snap diff --git a/src/snapshot/tests/compute.rs b/src/snapshot/tests/compute.rs index 3478d484..8564ea34 100644 --- a/src/snapshot/tests/compute.rs +++ b/src/snapshot/tests/compute.rs @@ -89,6 +89,74 @@ fn remove_property() { assert_yaml_snapshot!(patch_value); } +#[test] +fn add_child() { + let mut redactions = RedactionMap::new(); + + let tree = empty_tree(); + redactions.intern(tree.get_root_id()); + + let snapshot = InstanceSnapshot { + snapshot_id: None, + metadata: Default::default(), + name: Cow::Borrowed("ROOT"), + class_name: Cow::Borrowed("ROOT"), + properties: Default::default(), + children: vec![InstanceSnapshot { + snapshot_id: None, + metadata: Default::default(), + name: Cow::Borrowed("New"), + class_name: Cow::Borrowed("Folder"), + properties: Default::default(), + children: Vec::new(), + }], + }; + + let patch_set = compute_patch_set(&snapshot, &tree, tree.get_root_id()); + let patch_value = redactions.redacted_yaml(patch_set); + + assert_yaml_snapshot!(patch_value); +} + +#[test] +fn remove_child() { + let mut redactions = RedactionMap::new(); + + let mut tree = empty_tree(); + redactions.intern(tree.get_root_id()); + + { + let root_id = tree.get_root_id(); + let new_id = tree.insert_instance( + InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "Should not appear in snapshot".to_owned(), + class_name: "Folder".to_owned(), + properties: Default::default(), + }, + metadata: Default::default(), + }, + root_id, + ); + + redactions.intern(new_id); + } + + let snapshot = InstanceSnapshot { + snapshot_id: None, + metadata: Default::default(), + name: Cow::Borrowed("ROOT"), + class_name: Cow::Borrowed("ROOT"), + properties: Default::default(), + children: Vec::new(), + }; + + let patch_set = compute_patch_set(&snapshot, &tree, tree.get_root_id()); + let patch_value = redactions.redacted_yaml(patch_set); + + assert_yaml_snapshot!(patch_value); +} + fn empty_tree() -> RojoTree { RojoTree::new(InstancePropertiesWithMeta { properties: RbxInstanceProperties { diff --git a/src/snapshot/tests/snapshots/compute__add_child.snap b/src/snapshot/tests/snapshots/compute__add_child.snap new file mode 100644 index 00000000..7ea5e6c2 --- /dev/null +++ b/src/snapshot/tests/snapshots/compute__add_child.snap @@ -0,0 +1,18 @@ +--- +source: src/snapshot/tests/compute.rs +expression: patch_value +--- +removed_instances: [] +added_instances: + - parent_id: id-1 + instance: + snapshot_id: ~ + metadata: + ignore_unknown_instances: false + source_path: ~ + project_node: ~ + name: New + class_name: Folder + properties: {} + children: [] +updated_instances: [] diff --git a/src/snapshot/tests/snapshots/compute__remove_child.snap b/src/snapshot/tests/snapshots/compute__remove_child.snap new file mode 100644 index 00000000..16295d07 --- /dev/null +++ b/src/snapshot/tests/snapshots/compute__remove_child.snap @@ -0,0 +1,8 @@ +--- +source: src/snapshot/tests/compute.rs +expression: patch_value +--- +removed_instances: + - id-2 +added_instances: [] +updated_instances: [] From 0a1fa9588fb89142e5404f6565b6393204b314e2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 30 Sep 2019 17:13:56 -0700 Subject: [PATCH 0724/1504] Test for AppliedPatchSet result --- src/snapshot/patch.rs | 4 ++-- src/snapshot/tests/apply.rs | 16 ++++++++++++---- .../apply__set_name_and_class_name.snap | 12 ++++++++++++ 3 files changed, 26 insertions(+), 6 deletions(-) create mode 100644 src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap diff --git a/src/snapshot/patch.rs b/src/snapshot/patch.rs index f7ce22b0..8be68c47 100644 --- a/src/snapshot/patch.rs +++ b/src/snapshot/patch.rs @@ -61,7 +61,7 @@ pub struct PatchUpdate { /// // TODO: Introduce machinery to detect conflicts, like keeping previous + // current values in all fields. -#[derive(Debug, Clone, Default)] +#[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct AppliedPatchSet { pub removed: Vec, pub added: Vec, @@ -78,7 +78,7 @@ impl AppliedPatchSet { } } -#[derive(Debug, Clone)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct AppliedPatchUpdate { pub id: RbxId, diff --git a/src/snapshot/tests/apply.rs b/src/snapshot/tests/apply.rs index f06fa271..a31c392e 100644 --- a/src/snapshot/tests/apply.rs +++ b/src/snapshot/tests/apply.rs @@ -1,12 +1,18 @@ +use insta::assert_yaml_snapshot; use rbx_dom_weak::RbxInstanceProperties; +use rojo_insta_ext::RedactionMap; + use crate::snapshot::{ apply_patch_set, InstancePropertiesWithMeta, PatchSet, PatchUpdate, RojoTree, }; #[test] -fn reify_folder() { +fn set_name_and_class_name() { + let mut redactions = RedactionMap::new(); + let mut tree = empty_tree(); + redactions.intern(tree.get_root_id()); let patch_set = PatchSet { updated_instances: vec![PatchUpdate { @@ -19,10 +25,12 @@ fn reify_folder() { ..Default::default() }; - let _applied_patch_set = apply_patch_set(&mut tree, patch_set); + let applied_patch_set = apply_patch_set(&mut tree, patch_set); - // TODO: Make assertions about tree using snapshots - // TODO: make assertions about applied patch set using snapshots + // TODO: Snapshot tree, requires RojoTree: Serialize (but not Deserialize!) + + let applied_patch_value = redactions.redacted_yaml(applied_patch_set); + assert_yaml_snapshot!(applied_patch_value); } fn empty_tree() -> RojoTree { diff --git a/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap b/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap new file mode 100644 index 00000000..25a10131 --- /dev/null +++ b/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap @@ -0,0 +1,12 @@ +--- +source: src/snapshot/tests/apply.rs +expression: applied_patch_value +--- +removed: [] +added: [] +updated: + - id: id-1 + changed_name: "Hello, world!" + changed_class_name: Folder + changed_properties: {} + changed_metadata: ~ From b2fc6c165b0814da77fe6c54a49246920e704490 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 30 Sep 2019 17:22:54 -0700 Subject: [PATCH 0725/1504] Improve patch application test --- src/snapshot/tests/apply.rs | 43 +++++++++++++++++-- .../apply__set_name_and_class_name-2.snap | 12 ++++++ .../apply__set_name_and_class_name.snap | 19 ++++---- 3 files changed, 62 insertions(+), 12 deletions(-) create mode 100644 src/snapshot/tests/snapshots/apply__set_name_and_class_name-2.snap diff --git a/src/snapshot/tests/apply.rs b/src/snapshot/tests/apply.rs index a31c392e..1deda6db 100644 --- a/src/snapshot/tests/apply.rs +++ b/src/snapshot/tests/apply.rs @@ -1,10 +1,13 @@ +use std::collections::HashMap; + use insta::assert_yaml_snapshot; -use rbx_dom_weak::RbxInstanceProperties; +use rbx_dom_weak::{RbxId, RbxInstanceProperties, RbxValue}; +use serde::Serialize; use rojo_insta_ext::RedactionMap; use crate::snapshot::{ - apply_patch_set, InstancePropertiesWithMeta, PatchSet, PatchUpdate, RojoTree, + apply_patch_set, InstanceMetadata, InstancePropertiesWithMeta, PatchSet, PatchUpdate, RojoTree, }; #[test] @@ -27,7 +30,9 @@ fn set_name_and_class_name() { let applied_patch_set = apply_patch_set(&mut tree, patch_set); - // TODO: Snapshot tree, requires RojoTree: Serialize (but not Deserialize!) + let tree_view = view_tree(&tree); + let tree_value = redactions.redacted_yaml(tree_view); + assert_yaml_snapshot!(tree_value); let applied_patch_value = redactions.redacted_yaml(applied_patch_set); assert_yaml_snapshot!(applied_patch_value); @@ -43,3 +48,35 @@ fn empty_tree() -> RojoTree { metadata: Default::default(), }) } + +#[derive(Debug, Serialize)] +struct InstanceView { + id: RbxId, + name: String, + class_name: String, + properties: HashMap, + metadata: InstanceMetadata, + children: Vec, +} + +fn view_tree(tree: &RojoTree) -> InstanceView { + view_instance(tree, tree.get_root_id()) +} + +fn view_instance(tree: &RojoTree, id: RbxId) -> InstanceView { + let instance = tree.get_instance(id).unwrap(); + + InstanceView { + id: instance.id(), + name: instance.name().to_owned(), + class_name: instance.class_name().to_owned(), + properties: instance.properties().clone(), + metadata: instance.metadata().clone(), + children: instance + .children() + .iter() + .copied() + .map(|id| view_instance(tree, id)) + .collect(), + } +} diff --git a/src/snapshot/tests/snapshots/apply__set_name_and_class_name-2.snap b/src/snapshot/tests/snapshots/apply__set_name_and_class_name-2.snap new file mode 100644 index 00000000..25a10131 --- /dev/null +++ b/src/snapshot/tests/snapshots/apply__set_name_and_class_name-2.snap @@ -0,0 +1,12 @@ +--- +source: src/snapshot/tests/apply.rs +expression: applied_patch_value +--- +removed: [] +added: [] +updated: + - id: id-1 + changed_name: "Hello, world!" + changed_class_name: Folder + changed_properties: {} + changed_metadata: ~ diff --git a/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap b/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap index 25a10131..4d2fb365 100644 --- a/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap +++ b/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap @@ -1,12 +1,13 @@ --- source: src/snapshot/tests/apply.rs -expression: applied_patch_value +expression: tree_value --- -removed: [] -added: [] -updated: - - id: id-1 - changed_name: "Hello, world!" - changed_class_name: Folder - changed_properties: {} - changed_metadata: ~ +id: id-1 +name: "Hello, world!" +class_name: Folder +properties: {} +metadata: + ignore_unknown_instances: false + source_path: ~ + project_node: ~ +children: [] From 282caf10a5ed9c35d3dc87f3b6cc8bebd01e2859 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 30 Sep 2019 17:36:37 -0700 Subject: [PATCH 0726/1504] Expand patch_apply tests --- src/snapshot/tests/apply.rs | 80 +++++++++++++++++++ .../snapshots/apply__add_property-2.snap | 15 ++++ .../tests/snapshots/apply__add_property.snap | 16 ++++ .../apply__remove_property_after_patch.snap | 13 +++ .../apply__remove_property_appied_patch.snap | 13 +++ .../apply__remove_property_initial.snap | 16 ++++ 6 files changed, 153 insertions(+) create mode 100644 src/snapshot/tests/snapshots/apply__add_property-2.snap create mode 100644 src/snapshot/tests/snapshots/apply__add_property.snap create mode 100644 src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap create mode 100644 src/snapshot/tests/snapshots/apply__remove_property_appied_patch.snap create mode 100644 src/snapshot/tests/snapshots/apply__remove_property_initial.snap diff --git a/src/snapshot/tests/apply.rs b/src/snapshot/tests/apply.rs index 1deda6db..d36d6538 100644 --- a/src/snapshot/tests/apply.rs +++ b/src/snapshot/tests/apply.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use insta::assert_yaml_snapshot; +use maplit::hashmap; use rbx_dom_weak::{RbxId, RbxInstanceProperties, RbxValue}; use serde::Serialize; @@ -38,6 +39,84 @@ fn set_name_and_class_name() { assert_yaml_snapshot!(applied_patch_value); } +#[test] +fn add_property() { + let mut redactions = RedactionMap::new(); + + let mut tree = empty_tree(); + redactions.intern(tree.get_root_id()); + + let patch_set = PatchSet { + updated_instances: vec![PatchUpdate { + id: tree.get_root_id(), + changed_name: None, + changed_class_name: None, + changed_properties: hashmap! { + "Foo".to_owned() => Some(RbxValue::String { + value: "Value of Foo".to_owned(), + }), + }, + changed_metadata: None, + }], + ..Default::default() + }; + + let applied_patch_set = apply_patch_set(&mut tree, patch_set); + + let tree_view = view_tree(&tree); + let tree_value = redactions.redacted_yaml(tree_view); + assert_yaml_snapshot!(tree_value); + + let applied_patch_value = redactions.redacted_yaml(applied_patch_set); + assert_yaml_snapshot!(applied_patch_value); +} + +#[test] +fn remove_property() { + let mut redactions = RedactionMap::new(); + + let mut tree = empty_tree(); + redactions.intern(tree.get_root_id()); + + { + let root_id = tree.get_root_id(); + let mut root_instance = tree.get_instance_mut(root_id).unwrap(); + + root_instance.properties_mut().insert( + "Foo".to_owned(), + RbxValue::String { + value: "Should be removed".to_owned(), + }, + ); + } + + let tree_view = view_tree(&tree); + let tree_value = redactions.redacted_yaml(tree_view); + assert_yaml_snapshot!("remove_property_initial", tree_value); + + let patch_set = PatchSet { + updated_instances: vec![PatchUpdate { + id: tree.get_root_id(), + changed_name: None, + changed_class_name: None, + changed_properties: hashmap! { + "Foo".to_owned() => None, + }, + changed_metadata: None, + }], + ..Default::default() + }; + + let applied_patch_set = apply_patch_set(&mut tree, patch_set); + + let tree_view = view_tree(&tree); + let tree_value = redactions.redacted_yaml(tree_view); + assert_yaml_snapshot!("remove_property_after_patch", tree_value); + + let applied_patch_value = redactions.redacted_yaml(applied_patch_set); + assert_yaml_snapshot!("remove_property_appied_patch", applied_patch_value); +} + fn empty_tree() -> RojoTree { RojoTree::new(InstancePropertiesWithMeta { properties: RbxInstanceProperties { @@ -49,6 +128,7 @@ fn empty_tree() -> RojoTree { }) } +/// Copy of data from RojoTree in the right shape to have useful snapshots. #[derive(Debug, Serialize)] struct InstanceView { id: RbxId, diff --git a/src/snapshot/tests/snapshots/apply__add_property-2.snap b/src/snapshot/tests/snapshots/apply__add_property-2.snap new file mode 100644 index 00000000..81500ec3 --- /dev/null +++ b/src/snapshot/tests/snapshots/apply__add_property-2.snap @@ -0,0 +1,15 @@ +--- +source: src/snapshot/tests/apply.rs +expression: applied_patch_value +--- +removed: [] +added: [] +updated: + - id: id-1 + changed_name: ~ + changed_class_name: ~ + changed_properties: + Foo: + Type: String + Value: Value of Foo + changed_metadata: ~ diff --git a/src/snapshot/tests/snapshots/apply__add_property.snap b/src/snapshot/tests/snapshots/apply__add_property.snap new file mode 100644 index 00000000..e702f856 --- /dev/null +++ b/src/snapshot/tests/snapshots/apply__add_property.snap @@ -0,0 +1,16 @@ +--- +source: src/snapshot/tests/apply.rs +expression: tree_value +--- +id: id-1 +name: ROOT +class_name: ROOT +properties: + Foo: + Type: String + Value: Value of Foo +metadata: + ignore_unknown_instances: false + source_path: ~ + project_node: ~ +children: [] diff --git a/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap b/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap new file mode 100644 index 00000000..c267148f --- /dev/null +++ b/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap @@ -0,0 +1,13 @@ +--- +source: src/snapshot/tests/apply.rs +expression: tree_value +--- +id: id-1 +name: ROOT +class_name: ROOT +properties: {} +metadata: + ignore_unknown_instances: false + source_path: ~ + project_node: ~ +children: [] diff --git a/src/snapshot/tests/snapshots/apply__remove_property_appied_patch.snap b/src/snapshot/tests/snapshots/apply__remove_property_appied_patch.snap new file mode 100644 index 00000000..640a62c0 --- /dev/null +++ b/src/snapshot/tests/snapshots/apply__remove_property_appied_patch.snap @@ -0,0 +1,13 @@ +--- +source: src/snapshot/tests/apply.rs +expression: applied_patch_value +--- +removed: [] +added: [] +updated: + - id: id-1 + changed_name: ~ + changed_class_name: ~ + changed_properties: + Foo: ~ + changed_metadata: ~ diff --git a/src/snapshot/tests/snapshots/apply__remove_property_initial.snap b/src/snapshot/tests/snapshots/apply__remove_property_initial.snap new file mode 100644 index 00000000..7b912600 --- /dev/null +++ b/src/snapshot/tests/snapshots/apply__remove_property_initial.snap @@ -0,0 +1,16 @@ +--- +source: src/snapshot/tests/apply.rs +expression: tree_value +--- +id: id-1 +name: ROOT +class_name: ROOT +properties: + Foo: + Type: String + Value: Should be removed +metadata: + ignore_unknown_instances: false + source_path: ~ + project_node: ~ +children: [] From 457a8a5cf83e36265e2a164e1ac4c671f66a439c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 30 Sep 2019 17:37:16 -0700 Subject: [PATCH 0727/1504] Fix warning in serve_test --- rojo-test/src/serve_test.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index 2cdff469..fa6cedd9 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -1,5 +1,4 @@ use std::{ - collections::HashMap, fs, path::{Path, PathBuf}, process::Command, From 1c6788ea4504407ef6144450f1dfde932ff70246 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 30 Sep 2019 18:12:19 -0700 Subject: [PATCH 0728/1504] Migrate from source_path to contributing_paths --- src/snapshot/metadata.rs | 28 +++++++++++++------ .../tests/snapshots/apply__add_property.snap | 2 +- .../apply__remove_property_after_patch.snap | 2 +- .../apply__remove_property_initial.snap | 2 +- .../apply__set_name_and_class_name.snap | 2 +- .../tests/snapshots/compute__add_child.snap | 2 +- src/snapshot/tree.rs | 16 +++++------ 7 files changed, 33 insertions(+), 21 deletions(-) diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index eadbd1ca..0105e34e 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -13,15 +13,27 @@ pub struct InstanceMetadata { /// manage. pub ignore_unknown_instances: bool, - // TODO: Make source_path a SmallVec in order to support meta - // files? Maybe we should use another member of the snapshot middleware to - // support damage-painting - /// The path that this file came from, if it's the top-level instance from a - /// model that came directly from disk. + /// The paths that, when changed, could cause the function that generated + /// this snapshot to generate a different snapshot. Paths should be included + /// even if they don't exist, since the presence of a file can change the + /// outcome of a snapshot function. + /// + /// For example, a file named foo.lua might have these contributing paths: + /// - foo.lua + /// - foo.meta.json (even if this file doesn't exist!) + /// + /// A directory named bar/ included in the project file might have these: + /// - bar/ + /// - bar/init.meta.json + /// - bar/init.lua + /// - bar/init.server.lua + /// - bar/init.client.lua + /// - default.project.json /// /// This path is used to make sure that file changes update all instances - /// that may need updates.. - pub source_path: Option, + /// that may need updates. + // TODO: Change this to be a SmallVec for performance in common cases? + pub contributing_paths: Vec, /// If this instance was defined in a project file, this is the name from /// the project file and the node under it. @@ -36,7 +48,7 @@ impl Default for InstanceMetadata { fn default() -> Self { InstanceMetadata { ignore_unknown_instances: false, - source_path: None, + contributing_paths: Vec::new(), project_node: None, } } diff --git a/src/snapshot/tests/snapshots/apply__add_property.snap b/src/snapshot/tests/snapshots/apply__add_property.snap index e702f856..bb466314 100644 --- a/src/snapshot/tests/snapshots/apply__add_property.snap +++ b/src/snapshot/tests/snapshots/apply__add_property.snap @@ -11,6 +11,6 @@ properties: Value: Value of Foo metadata: ignore_unknown_instances: false - source_path: ~ + contributing_paths: [] project_node: ~ children: [] diff --git a/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap b/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap index c267148f..a732e1b0 100644 --- a/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap +++ b/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap @@ -8,6 +8,6 @@ class_name: ROOT properties: {} metadata: ignore_unknown_instances: false - source_path: ~ + contributing_paths: [] project_node: ~ children: [] diff --git a/src/snapshot/tests/snapshots/apply__remove_property_initial.snap b/src/snapshot/tests/snapshots/apply__remove_property_initial.snap index 7b912600..a8aaaa3e 100644 --- a/src/snapshot/tests/snapshots/apply__remove_property_initial.snap +++ b/src/snapshot/tests/snapshots/apply__remove_property_initial.snap @@ -11,6 +11,6 @@ properties: Value: Should be removed metadata: ignore_unknown_instances: false - source_path: ~ + contributing_paths: [] project_node: ~ children: [] diff --git a/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap b/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap index 4d2fb365..707accac 100644 --- a/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap +++ b/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap @@ -8,6 +8,6 @@ class_name: Folder properties: {} metadata: ignore_unknown_instances: false - source_path: ~ + contributing_paths: [] project_node: ~ children: [] diff --git a/src/snapshot/tests/snapshots/compute__add_child.snap b/src/snapshot/tests/snapshots/compute__add_child.snap index 7ea5e6c2..b2281d8a 100644 --- a/src/snapshot/tests/snapshots/compute__add_child.snap +++ b/src/snapshot/tests/snapshots/compute__add_child.snap @@ -9,7 +9,7 @@ added_instances: snapshot_id: ~ metadata: ignore_unknown_instances: false - source_path: ~ + contributing_paths: [] project_node: ~ name: New class_name: Folder diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index 27aa3f45..f5a30dce 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -110,12 +110,12 @@ impl RojoTree { // If this instance's source path changed, we need to update our // path associations so that file changes will trigger updates // to this instance correctly. - if existing_metadata.source_path != metadata.source_path { - if let Some(existing_path) = &existing_metadata.source_path { + if existing_metadata.contributing_paths != metadata.contributing_paths { + for existing_path in &existing_metadata.contributing_paths { self.path_to_ids.remove(existing_path, id); } - if let Some(new_path) = &metadata.source_path { + for new_path in &metadata.contributing_paths { self.path_to_ids.insert(new_path.clone(), id); } } @@ -140,8 +140,8 @@ impl RojoTree { } fn insert_metadata(&mut self, id: RbxId, metadata: InstanceMetadata) { - if let Some(source_path) = &metadata.source_path { - self.path_to_ids.insert(source_path.clone(), id); + for path in &metadata.contributing_paths { + self.path_to_ids.insert(path.clone(), id); } self.metadata_map.insert(id, metadata); @@ -157,9 +157,9 @@ impl RojoTree { ) { let metadata = self.metadata_map.remove(&id).unwrap(); - if let Some(source_path) = &metadata.source_path { - self.path_to_ids.remove(source_path, id); - path_to_ids.insert(source_path.clone(), id); + for path in &metadata.contributing_paths { + self.path_to_ids.remove(path, id); + path_to_ids.insert(path.clone(), id); } metadata_map.insert(id, metadata); From 95f06d56d86beb51f78768d021ac875f0eaf1861 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 30 Sep 2019 18:33:46 -0700 Subject: [PATCH 0729/1504] Port SnapshotDir tests to use insta snapshots --- src/path_serializer.rs | 38 +++++++++++++++++-- src/snapshot/metadata.rs | 3 +- src/snapshot_middleware/dir.rs | 24 ++++-------- .../snapshots/test__empty_folder.snap | 14 +++++++ .../snapshots/test__folder_in_folder.snap | 24 ++++++++++++ 5 files changed, 83 insertions(+), 20 deletions(-) create mode 100644 src/snapshot_middleware/snapshots/test__empty_folder.snap create mode 100644 src/snapshot_middleware/snapshots/test__folder_in_folder.snap diff --git a/src/path_serializer.rs b/src/path_serializer.rs index fefe22e4..e3212077 100644 --- a/src/path_serializer.rs +++ b/src/path_serializer.rs @@ -25,12 +25,12 @@ //! } //! ``` //! -//! **The methods in this module can only handle relative paths, since absolute -//! paths are never portable.** +//! For absolute paths, which are only safe to serialize if they're artificial, +//! use `serialize_absolute`. use std::path::{Component, Path}; -use serde::Serializer; +use serde::{ser::SerializeSeq, Serialize, Serializer}; pub fn serialize_option(maybe_path: &Option, serializer: S) -> Result where @@ -72,3 +72,35 @@ where serializer.serialize_str(&output) } + +pub fn serialize_absolute(path: T, serializer: S) -> Result +where + S: Serializer, + T: AsRef, +{ + let as_str = path + .as_ref() + .as_os_str() + .to_str() + .expect("Invalid Unicode in file path, cannot serialize"); + let replaced = as_str.replace("\\", "/"); + + serializer.serialize_str(&replaced) +} + +#[derive(Serialize)] +struct WithAbsolute<'a>(#[serde(serialize_with = "serialize_absolute")] &'a Path); + +pub fn serialize_vec_absolute(paths: &Vec, serializer: S) -> Result +where + S: Serializer, + T: AsRef, +{ + let mut seq = serializer.serialize_seq(Some(paths.len()))?; + + for path in paths { + seq.serialize_element(&WithAbsolute(path.as_ref()))?; + } + + seq.end() +} diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index 0105e34e..f4c4f241 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; use serde::{Deserialize, Serialize}; -use crate::project::ProjectNode; +use crate::{path_serializer, project::ProjectNode}; /// Rojo-specific metadata that can be associated with an instance or a snapshot /// of an instance. @@ -33,6 +33,7 @@ pub struct InstanceMetadata { /// This path is used to make sure that file changes update all instances /// that may need updates. // TODO: Change this to be a SmallVec for performance in common cases? + #[serde(serialize_with = "path_serializer::serialize_vec_absolute")] pub contributing_paths: Vec, /// If this instance was defined in a project file, this is the name from diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index a826c43f..04b566c4 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -4,7 +4,7 @@ use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ imfs::{DirectorySnapshot, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, - snapshot::InstanceSnapshot, + snapshot::{InstanceMetadata, InstanceSnapshot}, }; use super::{ @@ -43,7 +43,10 @@ impl SnapshotMiddleware for SnapshotDir { Ok(Some(InstanceSnapshot { snapshot_id: None, - metadata: Default::default(), // TODO + metadata: InstanceMetadata { + contributing_paths: vec![entry.path().to_path_buf()], + ..Default::default() + }, name: Cow::Owned(instance_name), class_name: Cow::Borrowed("Folder"), properties: HashMap::new(), @@ -76,6 +79,7 @@ impl SnapshotMiddleware for SnapshotDir { mod test { use super::*; + use insta::assert_yaml_snapshot; use maplit::hashmap; use crate::imfs::{ImfsDebug, NoopFetcher}; @@ -90,10 +94,7 @@ mod test { let entry = imfs.get("/foo").unwrap(); let instance_snapshot = SnapshotDir::from_imfs(&mut imfs, &entry).unwrap().unwrap(); - assert_eq!(instance_snapshot.name, "foo"); - assert_eq!(instance_snapshot.class_name, "Folder"); - assert_eq!(instance_snapshot.properties, HashMap::new()); - assert_eq!(instance_snapshot.children, Vec::new()); + assert_yaml_snapshot!(instance_snapshot); } #[test] @@ -108,15 +109,6 @@ mod test { let entry = imfs.get("/foo").unwrap(); let instance_snapshot = SnapshotDir::from_imfs(&mut imfs, &entry).unwrap().unwrap(); - assert_eq!(instance_snapshot.name, "foo"); - assert_eq!(instance_snapshot.class_name, "Folder"); - assert_eq!(instance_snapshot.properties, HashMap::new()); - assert_eq!(instance_snapshot.children.len(), 1); - - let child = &instance_snapshot.children[0]; - assert_eq!(child.name, "Child"); - assert_eq!(child.class_name, "Folder"); - assert_eq!(child.properties, HashMap::new()); - assert_eq!(child.children, Vec::new()); + assert_yaml_snapshot!(instance_snapshot); } } diff --git a/src/snapshot_middleware/snapshots/test__empty_folder.snap b/src/snapshot_middleware/snapshots/test__empty_folder.snap new file mode 100644 index 00000000..15556287 --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__empty_folder.snap @@ -0,0 +1,14 @@ +--- +source: src/snapshot_middleware/dir.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: false + contributing_paths: + - /foo + project_node: ~ +name: foo +class_name: Folder +properties: {} +children: [] diff --git a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap new file mode 100644 index 00000000..a65151d7 --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap @@ -0,0 +1,24 @@ +--- +source: src/snapshot_middleware/dir.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: false + contributing_paths: + - /foo + project_node: ~ +name: foo +class_name: Folder +properties: {} +children: + - snapshot_id: ~ + metadata: + ignore_unknown_instances: false + contributing_paths: + - /foo/Child + project_node: ~ + name: Child + class_name: Folder + properties: {} + children: [] From 5f5fb51eaee7e45b6fc4216192f471d8d04ed55a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 10:32:05 -0700 Subject: [PATCH 0730/1504] Make up terminology for 'instigating path' in instance metadata --- src/snapshot/metadata.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index f4c4f241..62ef7fb8 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -18,12 +18,15 @@ pub struct InstanceMetadata { /// even if they don't exist, since the presence of a file can change the /// outcome of a snapshot function. /// + /// The first path in this list is considered the "instigating path", and + /// will be the snapshot target if any of the contributing paths change. + /// /// For example, a file named foo.lua might have these contributing paths: - /// - foo.lua + /// - foo.lua (instigating path) /// - foo.meta.json (even if this file doesn't exist!) /// /// A directory named bar/ included in the project file might have these: - /// - bar/ + /// - bar/ (instigating path) /// - bar/init.meta.json /// - bar/init.lua /// - bar/init.server.lua From 90e41f3ce9200faa477ddc0dc61fe25183c7ccab Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 10:36:20 -0700 Subject: [PATCH 0731/1504] Fix bounds on MultiMap::get --- src/multimap.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/multimap.rs b/src/multimap.rs index f3047234..19708552 100644 --- a/src/multimap.rs +++ b/src/multimap.rs @@ -19,7 +19,11 @@ impl MultiMap { } } - pub fn get>(&mut self, k: Q) -> &[V] { + pub fn get(&self, k: &Q) -> &[V] + where + K: Borrow, + Q: Hash + Eq, + { self.inner.get(k.borrow()).map(Vec::as_slice).unwrap_or(&[]) } From bcf4fea5980dfec0d13ac50efad30ebaed760248 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 10:37:06 -0700 Subject: [PATCH 0732/1504] Add RojoTree::get_ids_at_path --- src/snapshot/tree.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index f5a30dce..47cc3978 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -1,4 +1,7 @@ -use std::{collections::HashMap, path::PathBuf}; +use std::{ + collections::HashMap, + path::{Path, PathBuf}, +}; use rbx_dom_weak::{Descendants, RbxId, RbxInstance, RbxInstanceProperties, RbxTree, RbxValue}; @@ -135,6 +138,10 @@ impl RojoTree { } } + pub fn get_ids_at_path(&self, path: &Path) -> &[RbxId] { + self.path_to_ids.get(path) + } + fn get_metadata(&self, id: RbxId) -> Option<&InstanceMetadata> { self.metadata_map.get(&id) } From 1737da9c1f194df36b59451f53a5679711b1283e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 10:44:35 -0700 Subject: [PATCH 0733/1504] Move ImfsEvent into its own module --- src/imfs/event.rs | 2 ++ src/imfs/fetcher.rs | 5 ++--- src/imfs/imfs.rs | 5 +++-- src/imfs/mod.rs | 2 ++ src/imfs/noop_fetcher.rs | 5 ++++- src/imfs/real_fetcher.rs | 5 ++++- 6 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 src/imfs/event.rs diff --git a/src/imfs/event.rs b/src/imfs/event.rs new file mode 100644 index 00000000..357dc0e1 --- /dev/null +++ b/src/imfs/event.rs @@ -0,0 +1,2 @@ +// TODO: Use our own event type instead of notify's. +pub type ImfsEvent = notify::DebouncedEvent; diff --git a/src/imfs/fetcher.rs b/src/imfs/fetcher.rs index ac6ca7ac..61bb544d 100644 --- a/src/imfs/fetcher.rs +++ b/src/imfs/fetcher.rs @@ -5,15 +5,14 @@ use std::{ use crossbeam_channel::Receiver; +use super::event::ImfsEvent; + #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum FileType { File, Directory, } -// TODO: Use our own event type instead of notify's. -pub type ImfsEvent = notify::DebouncedEvent; - /// The generic interface that `Imfs` uses to lazily read files from the disk. /// In tests, it's stubbed out to do different versions of absolutely nothing /// depending on the test. diff --git a/src/imfs/imfs.rs b/src/imfs/imfs.rs index 3798472c..dcfa8d7d 100644 --- a/src/imfs/imfs.rs +++ b/src/imfs/imfs.rs @@ -9,7 +9,8 @@ use crate::path_map::PathMap; use super::{ error::{FsError, FsResult}, - fetcher::{FileType, ImfsEvent, ImfsFetcher}, + event::ImfsEvent, + fetcher::{FileType, ImfsFetcher}, snapshot::ImfsSnapshot, }; @@ -425,7 +426,7 @@ mod test { use crossbeam_channel::Receiver; use maplit::hashmap; - use super::super::{error::FsErrorKind, fetcher::ImfsEvent, noop_fetcher::NoopFetcher}; + use super::super::{error::FsErrorKind, event::ImfsEvent, noop_fetcher::NoopFetcher}; #[test] fn from_snapshot_file() { diff --git a/src/imfs/mod.rs b/src/imfs/mod.rs index 5b403013..e930e089 100644 --- a/src/imfs/mod.rs +++ b/src/imfs/mod.rs @@ -1,4 +1,5 @@ mod error; +mod event; mod fetcher; mod imfs; mod noop_fetcher; @@ -6,6 +7,7 @@ mod real_fetcher; mod snapshot; pub use error::*; +pub use event::*; pub use fetcher::*; pub use imfs::*; pub use noop_fetcher::*; diff --git a/src/imfs/noop_fetcher.rs b/src/imfs/noop_fetcher.rs index be97aa68..cf3ed829 100644 --- a/src/imfs/noop_fetcher.rs +++ b/src/imfs/noop_fetcher.rs @@ -11,7 +11,10 @@ use std::{ use crossbeam_channel::Receiver; -use super::fetcher::{FileType, ImfsEvent, ImfsFetcher}; +use super::{ + event::ImfsEvent, + fetcher::{FileType, ImfsFetcher}, +}; pub struct NoopFetcher; diff --git a/src/imfs/real_fetcher.rs b/src/imfs/real_fetcher.rs index e9dc221a..4d5a68b9 100644 --- a/src/imfs/real_fetcher.rs +++ b/src/imfs/real_fetcher.rs @@ -13,7 +13,10 @@ use crossbeam_channel::{unbounded, Receiver}; use jod_thread::JoinHandle; use notify::{RecommendedWatcher, RecursiveMode, Watcher}; -use super::fetcher::{FileType, ImfsEvent, ImfsFetcher}; +use super::{ + event::ImfsEvent, + fetcher::{FileType, ImfsFetcher}, +}; /// Workaround to disable the file watcher for processes that don't need it, /// since notify appears hang on to mpsc Sender objects too long, causing Rojo From 694b6101cac09ff868cdd277ad75ad0d4c149a07 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 11:29:09 -0700 Subject: [PATCH 0734/1504] New Imfs event type --- src/imfs/event.rs | 10 ++++++++-- src/imfs/imfs.rs | 21 +++----------------- src/imfs/real_fetcher.rs | 43 +++++++++++++++++++++++++++++++++++----- 3 files changed, 49 insertions(+), 25 deletions(-) diff --git a/src/imfs/event.rs b/src/imfs/event.rs index 357dc0e1..b82e7a0a 100644 --- a/src/imfs/event.rs +++ b/src/imfs/event.rs @@ -1,2 +1,8 @@ -// TODO: Use our own event type instead of notify's. -pub type ImfsEvent = notify::DebouncedEvent; +use std::path::PathBuf; + +#[derive(Debug)] +pub enum ImfsEvent { + Modified(PathBuf), + Created(PathBuf), + Removed(PathBuf), +} diff --git a/src/imfs/imfs.rs b/src/imfs/imfs.rs index dcfa8d7d..5cd2024c 100644 --- a/src/imfs/imfs.rs +++ b/src/imfs/imfs.rs @@ -48,32 +48,17 @@ impl Imfs { } pub fn commit_change(&mut self, event: &ImfsEvent) -> FsResult<()> { - use notify::DebouncedEvent::*; + use ImfsEvent::*; log::trace!("Committing Imfs change {:?}", event); match event { - Create(path) => { + Created(path) | Modified(path) => { self.raise_file_changed(path)?; } - Write(path) => { - self.raise_file_changed(path)?; - } - Remove(path) => { + Removed(path) => { self.raise_file_removed(path)?; } - Rename(from_path, to_path) => { - self.raise_file_removed(from_path)?; - self.raise_file_changed(to_path)?; - } - Error(err, path) => { - log::warn!("Filesystem error detected: {:?} on path {:?}", err, path); - } - Rescan => { - // FIXME: Implement rescanning - log::warn!("Unhandled filesystem rescan event"); - } - NoticeWrite(_) | NoticeRemove(_) | Chmod(_) => {} } Ok(()) diff --git a/src/imfs/real_fetcher.rs b/src/imfs/real_fetcher.rs index 4d5a68b9..55b94e2c 100644 --- a/src/imfs/real_fetcher.rs +++ b/src/imfs/real_fetcher.rs @@ -9,9 +9,9 @@ use std::{ time::Duration, }; -use crossbeam_channel::{unbounded, Receiver}; +use crossbeam_channel::{unbounded, Receiver, Sender}; use jod_thread::JoinHandle; -use notify::{RecommendedWatcher, RecursiveMode, Watcher}; +use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; use super::{ event::ImfsEvent, @@ -58,9 +58,7 @@ impl RealFetcher { let handle = jod_thread::Builder::new() .name("notify message converter".to_owned()) .spawn(move || { - notify_receiver - .into_iter() - .for_each(|event| sender.send(event).unwrap()); + converter_thread(notify_receiver, sender); }) .expect("Could not start message converter thread"); @@ -84,6 +82,41 @@ impl RealFetcher { } } +fn converter_thread(notify_receiver: mpsc::Receiver, sender: Sender) { + notify_receiver.into_iter().for_each(|event| { + use DebouncedEvent::*; + + match event { + Create(path) => sender.send(ImfsEvent::Created(path)).unwrap(), + Write(path) => sender.send(ImfsEvent::Modified(path)).unwrap(), + Remove(path) => sender.send(ImfsEvent::Removed(path)).unwrap(), + Rename(from_path, to_path) => { + sender.send(ImfsEvent::Created(from_path)).unwrap(); + sender.send(ImfsEvent::Removed(to_path)).unwrap(); + } + Rescan => { + log::warn!("Unhandled filesystem rescan event."); + log::warn!( + "Please file an issue! Rojo may need to handle this case, but does not yet." + ); + } + Error(err, maybe_path) => { + log::warn!("Unhandled filesystem error: {}", err); + + match maybe_path { + Some(path) => log::warn!("On path {}", path.display()), + None => log::warn!("No path was associated with this error."), + } + + log::warn!( + "Rojo may need to handle this. If this happens again, please file an issue!" + ); + } + NoticeWrite(_) | NoticeRemove(_) | Chmod(_) => {} + } + }); +} + impl ImfsFetcher for RealFetcher { fn file_type(&mut self, path: &Path) -> io::Result { let metadata = fs::metadata(path)?; From 9f5875d4bbe1e9ba8bc528fa16c1bf3bda46af56 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 13:47:14 -0700 Subject: [PATCH 0735/1504] imfs: move debugging messages outside of converter thread --- src/imfs/real_fetcher.rs | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/imfs/real_fetcher.rs b/src/imfs/real_fetcher.rs index 55b94e2c..814fb704 100644 --- a/src/imfs/real_fetcher.rs +++ b/src/imfs/real_fetcher.rs @@ -58,7 +58,9 @@ impl RealFetcher { let handle = jod_thread::Builder::new() .name("notify message converter".to_owned()) .spawn(move || { + log::trace!("RealFetcher converter thread started"); converter_thread(notify_receiver, sender); + log::trace!("RealFetcher converter thread stopped"); }) .expect("Could not start message converter thread"); @@ -83,8 +85,10 @@ impl RealFetcher { } fn converter_thread(notify_receiver: mpsc::Receiver, sender: Sender) { - notify_receiver.into_iter().for_each(|event| { - use DebouncedEvent::*; + use DebouncedEvent::*; + + for event in notify_receiver { + log::trace!("Notify event: {:?}", event); match event { Create(path) => sender.send(ImfsEvent::Created(path)).unwrap(), @@ -114,7 +118,7 @@ fn converter_thread(notify_receiver: mpsc::Receiver, sender: Sen } NoticeWrite(_) | NoticeRemove(_) | Chmod(_) => {} } - }); + } } impl ImfsFetcher for RealFetcher { From b94f21402c5f610bd7d63ab42aa007869afd15f3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 13:47:25 -0700 Subject: [PATCH 0736/1504] Expose RojoTree::get_metadata publicly --- src/snapshot/tree.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index 47cc3978..0126f5ee 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -142,7 +142,7 @@ impl RojoTree { self.path_to_ids.get(path) } - fn get_metadata(&self, id: RbxId) -> Option<&InstanceMetadata> { + pub fn get_metadata(&self, id: RbxId) -> Option<&InstanceMetadata> { self.metadata_map.get(&id) } From 5b7037550d9d2332c4b3f2e4b4f9ab49d401fd51 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 13:48:16 -0700 Subject: [PATCH 0737/1504] Start ChangeProcessor pumping work --- src/change_processor.rs | 60 +++++++++++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 11 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index 77ae51d4..f023577c 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -9,9 +9,10 @@ use crossbeam_channel::{select, Receiver, Sender}; use jod_thread::JoinHandle; use crate::{ - imfs::{Imfs, ImfsFetcher}, + imfs::{Imfs, ImfsEvent, ImfsFetcher}, message_queue::MessageQueue, - snapshot::{AppliedPatchSet, RojoTree}, + snapshot::{apply_patch_set, compute_patch_set, AppliedPatchSet, RojoTree}, + snapshot_middleware::snapshot_from_imfs, }; pub struct ChangeProcessor { @@ -29,7 +30,11 @@ impl ChangeProcessor { let thread_handle = jod_thread::Builder::new() .name("ChangeProcessor thread".to_owned()) - .spawn(move || Self::main_task(shutdown_receiver, tree, message_queue, imfs)) + .spawn(move || { + log::trace!("ChangeProcessor thread started"); + Self::main_task(shutdown_receiver, tree, message_queue, imfs); + log::trace!("ChangeProcessor thread stopped"); + }) .expect("Could not start ChangeProcessor thread"); Self { @@ -44,8 +49,6 @@ impl ChangeProcessor { message_queue: Arc>, imfs: Arc>>, ) { - log::trace!("ChangeProcessor thread started"); - let imfs_receiver = { let imfs = imfs.lock().unwrap(); imfs.change_receiver() @@ -61,13 +64,49 @@ impl ChangeProcessor { log::trace!("Imfs event: {:?}", event); - { + let patch_set = { let mut imfs = imfs.lock().unwrap(); imfs.commit_change(&event).expect("Error applying IMFS change"); - } - let patch_set = { - let _tree = tree.lock().unwrap(); + let tree = tree.lock().unwrap(); + + match event { + ImfsEvent::Created(path) | ImfsEvent::Modified(path) | ImfsEvent::Removed(path) => { + let affected_ids = tree.get_ids_at_path(&path); + + if affected_ids.len() == 0 { + log::info!("No instances were affected by this change."); + continue; + } + + for &id in affected_ids { + let metadata = tree.get_metadata(id) + .expect("metadata missing for instance present in tree"); + + let instigating_path = match metadata.contributing_paths.get(0) { + Some(path) => path, + None => { + log::warn!("Instance {} did not have an instigating path, but was considered for an update.", id); + log::warn!("This is a Rojo bug. Please file an issue!"); + continue; + } + }; + + let entry = imfs + .get(instigating_path) + .expect("could not get instigating path from filesystem"); + + let snapshot = snapshot_from_imfs(&mut imfs, &entry) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + println!("Snapshot: {:?}", snapshot); + } + } + ImfsEvent::Removed(path) => { + log::warn!("TODO: Handle file remove events"); + } + } // TODO: Apply changes to tree based on IMFS and // calculate applied patch set from it. @@ -79,12 +118,11 @@ impl ChangeProcessor { } }, recv(shutdown_receiver) -> _ => { + log::trace!("ChangeProcessor shutdown signal received..."); break; }, } } - - log::trace!("ChangeProcessor thread stopping"); } } From 3dff4d10618ec4d64164feabf735da8d94c11e5e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 13:59:10 -0700 Subject: [PATCH 0738/1504] Generate and apply patches, routing them through message queue --- src/change_processor.rs | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index f023577c..bd3ef5c4 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -64,22 +64,23 @@ impl ChangeProcessor { log::trace!("Imfs event: {:?}", event); - let patch_set = { + let applied_patches = { let mut imfs = imfs.lock().unwrap(); imfs.commit_change(&event).expect("Error applying IMFS change"); - let tree = tree.lock().unwrap(); + let mut tree = tree.lock().unwrap(); + let mut applied_patches = Vec::new(); match event { ImfsEvent::Created(path) | ImfsEvent::Modified(path) | ImfsEvent::Removed(path) => { - let affected_ids = tree.get_ids_at_path(&path); + let affected_ids = tree.get_ids_at_path(&path).to_vec(); if affected_ids.len() == 0 { log::info!("No instances were affected by this change."); continue; } - for &id in affected_ids { + for id in affected_ids { let metadata = tree.get_metadata(id) .expect("metadata missing for instance present in tree"); @@ -100,7 +101,14 @@ impl ChangeProcessor { .expect("snapshot failed") .expect("snapshot did not return an instance"); - println!("Snapshot: {:?}", snapshot); + log::trace!("Computed snapshot: {:#?}", snapshot); + + let patch_set = compute_patch_set(&snapshot, &tree, id); + let applied_patch_set = apply_patch_set(&mut tree, patch_set); + + log::trace!("Applied patch: {:#?}", applied_patch_set); + + applied_patches.push(applied_patch_set); } } ImfsEvent::Removed(path) => { @@ -108,13 +116,11 @@ impl ChangeProcessor { } } - // TODO: Apply changes to tree based on IMFS and - // calculate applied patch set from it. - AppliedPatchSet::new() + applied_patches }; { - message_queue.push_messages(&[patch_set]); + message_queue.push_messages(&applied_patches); } }, recv(shutdown_receiver) -> _ => { From 7be5b36494657c4c30bdef5c575638400991d0ac Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 14:07:50 -0700 Subject: [PATCH 0739/1504] Fix unreachable pattern warning --- src/change_processor.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index bd3ef5c4..8e57a639 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -111,9 +111,6 @@ impl ChangeProcessor { applied_patches.push(applied_patch_set); } } - ImfsEvent::Removed(path) => { - log::warn!("TODO: Handle file remove events"); - } } applied_patches From 2598ea3577022a78b163c0920a9527a5b358bbcd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 14:09:05 -0700 Subject: [PATCH 0740/1504] Add contributing paths to SnapshotLua, switch to Insta tests --- src/snapshot_middleware/lua.rs | 42 ++++--------------- .../snapshots/test__client_from_imfs.snap | 17 ++++++++ .../snapshots/test__module_from_imfs.snap | 17 ++++++++ .../snapshots/test__server_from_imfs.snap | 17 ++++++++ 4 files changed, 60 insertions(+), 33 deletions(-) create mode 100644 src/snapshot_middleware/snapshots/test__client_from_imfs.snap create mode 100644 src/snapshot_middleware/snapshots/test__module_from_imfs.snap create mode 100644 src/snapshot_middleware/snapshots/test__server_from_imfs.snap diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index f7d5b4ee..77ece285 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -5,7 +5,7 @@ use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; use crate::{ imfs::{FsResultExt, Imfs, ImfsEntry, ImfsFetcher}, - snapshot::InstanceSnapshot, + snapshot::{InstanceMetadata, InstanceSnapshot}, }; use super::{ @@ -90,7 +90,10 @@ fn snapshot_lua_file( Ok(Some(InstanceSnapshot { snapshot_id: None, - metadata: Default::default(), // TODO + metadata: InstanceMetadata { + contributing_paths: vec![entry.path().to_path_buf()], + ..Default::default() + }, name: Cow::Owned(instance_name.to_owned()), class_name: Cow::Borrowed(class_name), properties, @@ -139,7 +142,7 @@ fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { mod test { use super::*; - use maplit::hashmap; + use insta::assert_yaml_snapshot; use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; @@ -153,16 +156,7 @@ mod test { let entry = imfs.get("/foo.lua").unwrap(); let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); - assert_eq!(instance_snapshot.name, "foo"); - assert_eq!(instance_snapshot.class_name, "ModuleScript"); - assert_eq!( - instance_snapshot.properties, - hashmap! { - "Source".to_owned() => RbxValue::String { - value: "Hello there!".to_owned(), - }, - } - ); + assert_yaml_snapshot!(instance_snapshot); } #[test] @@ -175,16 +169,7 @@ mod test { let entry = imfs.get("/foo.server.lua").unwrap(); let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); - assert_eq!(instance_snapshot.name, "foo"); - assert_eq!(instance_snapshot.class_name, "Script"); - assert_eq!( - instance_snapshot.properties, - hashmap! { - "Source".to_owned() => RbxValue::String { - value: "Hello there!".to_owned(), - }, - } - ); + assert_yaml_snapshot!(instance_snapshot); } #[test] @@ -197,15 +182,6 @@ mod test { let entry = imfs.get("/foo.client.lua").unwrap(); let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); - assert_eq!(instance_snapshot.name, "foo"); - assert_eq!(instance_snapshot.class_name, "LocalScript"); - assert_eq!( - instance_snapshot.properties, - hashmap! { - "Source".to_owned() => RbxValue::String { - value: "Hello there!".to_owned(), - }, - } - ); + assert_yaml_snapshot!(instance_snapshot); } } diff --git a/src/snapshot_middleware/snapshots/test__client_from_imfs.snap b/src/snapshot_middleware/snapshots/test__client_from_imfs.snap new file mode 100644 index 00000000..bc4df00b --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__client_from_imfs.snap @@ -0,0 +1,17 @@ +--- +source: src/snapshot_middleware/lua.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: false + contributing_paths: + - /foo.client.lua + project_node: ~ +name: foo +class_name: LocalScript +properties: + Source: + Type: String + Value: Hello there! +children: [] diff --git a/src/snapshot_middleware/snapshots/test__module_from_imfs.snap b/src/snapshot_middleware/snapshots/test__module_from_imfs.snap new file mode 100644 index 00000000..5d0407fe --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__module_from_imfs.snap @@ -0,0 +1,17 @@ +--- +source: src/snapshot_middleware/lua.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: false + contributing_paths: + - /foo.lua + project_node: ~ +name: foo +class_name: ModuleScript +properties: + Source: + Type: String + Value: Hello there! +children: [] diff --git a/src/snapshot_middleware/snapshots/test__server_from_imfs.snap b/src/snapshot_middleware/snapshots/test__server_from_imfs.snap new file mode 100644 index 00000000..c992669a --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__server_from_imfs.snap @@ -0,0 +1,17 @@ +--- +source: src/snapshot_middleware/lua.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: false + contributing_paths: + - /foo.server.lua + project_node: ~ +name: foo +class_name: Script +properties: + Source: + Type: String + Value: Hello there! +children: [] From 099aa26ef89e9159b9f55c7e71902406760f16e9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 14:45:24 -0700 Subject: [PATCH 0741/1504] Rough pass on transforming applied patches into API responses --- src/serve_session.rs | 4 ++++ src/web/api.rs | 42 +++++++++++++++++++++++++++++++++++++----- src/web/interface.rs | 23 +++++++++++++++++------ 3 files changed, 58 insertions(+), 11 deletions(-) diff --git a/src/serve_session.rs b/src/serve_session.rs index cfc6d4f1..05ff0d93 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -99,6 +99,10 @@ impl ServeSession { } impl ServeSession { + pub fn tree_handle(&self) -> Arc> { + Arc::clone(&self.tree) + } + pub fn tree(&self) -> MutexGuard<'_, RojoTree> { self.tree.lock().unwrap() } diff --git a/src/web/api.rs b/src/web/api.rs index 1c979e74..8be66359 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -13,8 +13,9 @@ use crate::{ serve_session::ServeSession, web::{ interface::{ - ErrorResponse, Instance, ReadResponse, ServerInfoResponse, SubscribeMessage, - SubscribeResponse, PROTOCOL_VERSION, SERVER_VERSION, + ErrorResponse, Instance, InstanceMetadata as WebInstanceMetadata, InstanceUpdate, + ReadResponse, ServerInfoResponse, SubscribeMessage, SubscribeResponse, + PROTOCOL_VERSION, SERVER_VERSION, }, util::{json, json_ok}, }, @@ -89,15 +90,46 @@ impl ApiService { message_queue.subscribe(input_cursor, sender); } + let tree_handle = self.serve_session.tree_handle(); + Box::new(receiver.then(move |result| match result { Ok((message_cursor, messages)) => { - // TODO: Transform applied patch sets into subscribe responses + let tree = tree_handle.lock().unwrap(); + let api_messages = messages .into_iter() .map(|message| { let removed_instances = message.removed; - let added_instances = HashMap::new(); // TODO - let updated_instances = Vec::new(); // TODO + + let mut added_instances = HashMap::new(); + for id in message.added { + let instance = tree.get_instance(id).unwrap(); + added_instances.insert(id, Instance::from_rojo_instance(instance)); + + for instance in tree.descendants(id) { + added_instances + .insert(instance.id(), Instance::from_rojo_instance(instance)); + } + } + + let updated_instances = message + .updated + .into_iter() + .map(|update| { + let changed_metadata = update + .changed_metadata + .as_ref() + .map(WebInstanceMetadata::from_rojo_metadata); + + InstanceUpdate { + id: update.id, + changed_name: update.changed_name, + changed_class_name: update.changed_class_name, + changed_properties: update.changed_properties, + changed_metadata, + } + }) + .collect(); SubscribeMessage { removed_instances, diff --git a/src/web/interface.rs b/src/web/interface.rs index a3ab3432..dcfc3bdf 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -8,7 +8,10 @@ use std::{ use rbx_dom_weak::{RbxId, RbxValue}; use serde::{Deserialize, Serialize}; -use crate::{session_id::SessionId, snapshot::InstanceWithMeta}; +use crate::{ + session_id::SessionId, + snapshot::{InstanceMetadata as RojoInstanceMetadata, InstanceWithMeta}, +}; /// Server version to report over the API, not exposed outside this crate. pub(crate) const SERVER_VERSION: &str = env!("CARGO_PKG_VERSION"); @@ -31,7 +34,9 @@ pub struct InstanceUpdate { pub id: RbxId, pub changed_name: Option, pub changed_class_name: Option, - pub changed_properties: HashMap, + // TODO: Transform from HashMap> to something else, since + // null will get lost when decoding from JSON in some languages. + pub changed_properties: HashMap>, pub changed_metadata: Option, } @@ -41,6 +46,14 @@ pub struct InstanceMetadata { pub ignore_unknown_instances: bool, } +impl InstanceMetadata { + pub(crate) fn from_rojo_metadata(meta: &RojoInstanceMetadata) -> Self { + Self { + ignore_unknown_instances: meta.ignore_unknown_instances, + } + } +} + #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "PascalCase")] pub struct Instance<'a> { @@ -52,15 +65,13 @@ pub struct Instance<'a> { } impl<'a> Instance<'a> { - pub fn from_rojo_instance<'b>(source: InstanceWithMeta<'b>) -> Instance<'b> { + pub(crate) fn from_rojo_instance<'b>(source: InstanceWithMeta<'b>) -> Instance<'b> { Instance { name: Cow::Borrowed(source.name()), class_name: Cow::Borrowed(source.class_name()), properties: Cow::Borrowed(source.properties()), children: Cow::Borrowed(source.children()), - metadata: Some(InstanceMetadata { - ignore_unknown_instances: source.metadata().ignore_unknown_instances, - }), + metadata: Some(InstanceMetadata::from_rojo_metadata(source.metadata())), } } } From 53bd02a89052febac18e5105fbb4cdfcf0d4b68b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 16:52:20 -0700 Subject: [PATCH 0742/1504] Add script to quickly install plugin into LocalAppData --- bin/install-dev-plugin.sh | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 bin/install-dev-plugin.sh diff --git a/bin/install-dev-plugin.sh b/bin/install-dev-plugin.sh new file mode 100644 index 00000000..888ec065 --- /dev/null +++ b/bin/install-dev-plugin.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e + +rojo build plugin -o $LOCALAPPDATA/Roblox/Plugins/Rojo.rbxm \ No newline at end of file From c62a5d15adb9e1750497ab40e7edd8fac24eab57 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 16:55:15 -0700 Subject: [PATCH 0743/1504] Add script to build plugin as changes occur --- bin/dev-plugin.sh | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 bin/dev-plugin.sh diff --git a/bin/dev-plugin.sh b/bin/dev-plugin.sh new file mode 100644 index 00000000..6674a00f --- /dev/null +++ b/bin/dev-plugin.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e + +watchexec -c -w plugin "rojo build plugin -o $LOCALAPPDATA/Roblox/Plugins/Rojo.rbxm" \ No newline at end of file From 0dbbf44ab27f16631f421bdd9978c7a2da2ca1fb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 16:55:45 -0700 Subject: [PATCH 0744/1504] plugin: Add API interface for strongly typing responses --- plugin/src/Types.lua | 80 +++++++++++++++++++++++++++++++++++++------ plugin/src/strict.lua | 24 +++++++++++++ 2 files changed, 94 insertions(+), 10 deletions(-) create mode 100644 plugin/src/strict.lua diff --git a/plugin/src/Types.lua b/plugin/src/Types.lua index f182d60a..3d866a1a 100644 --- a/plugin/src/Types.lua +++ b/plugin/src/Types.lua @@ -1,21 +1,68 @@ local t = require(script.Parent.Parent.t) local DevSettings = require(script.Parent.DevSettings) +local strict = require(script.Parent.strict) -local VirtualValue = t.interface({ +local RbxId = t.string + +local ApiValue = t.interface({ Type = t.string, Value = t.optional(t.any), }) -local VirtualMetadata = t.interface({ +local ApiInstanceMetadata = t.interface({ ignoreUnknownInstances = t.optional(t.boolean), }) -local VirtualInstance = t.interface({ +local ApiInstance = t.interface({ Name = t.string, ClassName = t.string, - Properties = t.map(t.string, VirtualValue), - Metadata = t.optional(VirtualMetadata) + Properties = t.map(t.string, ApiValue), + Metadata = t.optional(ApiInstanceMetadata), + Children = t.array(RbxId), +}) + +local ApiInstanceUpdate = t.interface({ + id = RbxId, + changedName = t.optional(t.string), + changedClassName = t.optional(t.string), + changedProperties = t.map(t.string, ApiValue), + changedMetadata = t.optional(ApiInstanceMetadata), +}) + +local ApiSubscribeMessage = t.interface({ + removedInstances = t.array(RbxId), + addedInstances = t.map(RbxId, ApiInstance), + updatedInstances = t.array(ApiInstanceUpdate), +}) + +local ApiInfoResponse = t.interface({ + sessionId = t.string, + serverVersion = t.string, + protocolVersion = t.number, + expectedPlaceIds = t.optional(t.array(t.number)), + rootInstanceId = RbxId, +}) + +local ApiReadResponse = t.interface({ + sessionId = t.string, + messageCursor = t.number, + instances = t.map(RbxId, ApiInstance), +}) + +local ApiSubscribeResponse = t.interface({ + sessionId = t.string, + messageCursor = t.number, + messages = t.array(ApiSubscribeMessage), +}) + +local ApiError = t.interface({ + kind = t.union( + t.literal("NotFound"), + t.literal("BadRequest"), + t.literal("InternalError") + ), + details = t.string, }) local function ifEnabled(innerCheck) @@ -28,9 +75,22 @@ local function ifEnabled(innerCheck) end end -return { +return strict("Types", { ifEnabled = ifEnabled, - VirtualInstance = VirtualInstance, - VirtualMetadata = VirtualMetadata, - VirtualValue = VirtualValue, -} \ No newline at end of file + + ApiInfoResponse = ApiInfoResponse, + ApiReadResponse = ApiReadResponse, + ApiSubscribeResponse = ApiSubscribeResponse, + ApiError = ApiError, + + ApiInstance = ApiInstance, + ApiInstanceMetadata = ApiInstanceMetadata, + ApiSubscribeMessage = ApiSubscribeMessage, + ApiValue = ApiValue, + RbxId = RbxId, + + -- Deprecated aliases during transition + VirtualInstance = ApiInstance, + VirtualMetadata = ApiInstanceMetadata, + VirtualValue = ApiValue, +}) \ No newline at end of file diff --git a/plugin/src/strict.lua b/plugin/src/strict.lua new file mode 100644 index 00000000..239c84a2 --- /dev/null +++ b/plugin/src/strict.lua @@ -0,0 +1,24 @@ +local function strictInner(name, target) + assert(type(name) == "string", "Argument #1 to `strict` must be a string or the table to modify") + assert(type(target) == "table", "Argument #2 to `strict` must be nil or the table to modify") + + setmetatable(target, { + __index = function(_, key) + error(("%q is not a valid member of strict table %q"):format(tostring(key), name), 2) + end, + + __newindex = function() + error(("Strict table %q is read-only"):format(name), 2) + end, + }) + + return target +end + +return function(nameOrTarget, target) + if type(nameOrTarget) == "string" then + return strictInner(nameOrTarget, target) + else + return strictInner("", target) + end +end \ No newline at end of file From 15e848d4bf6ce970edb741cf3da4a05a64ba00bb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 17:13:28 -0700 Subject: [PATCH 0745/1504] Add new scripts and machinery to make working on plugin easier --- bin/dev-plugin.sh | 2 +- bin/install-dev-plugin.sh | 10 +++++++++- bin/mark-plugin-as-dev.lua | 12 ++++++++++++ plugin/src/Config.lua | 9 +++++++-- plugin/src/DevSettings.lua | 4 +++- plugin/src/init.server.lua | 9 ++++++++- plugin/testez.project.json | 6 ++++++ 7 files changed, 46 insertions(+), 6 deletions(-) create mode 100644 bin/mark-plugin-as-dev.lua create mode 100644 plugin/testez.project.json diff --git a/bin/dev-plugin.sh b/bin/dev-plugin.sh index 6674a00f..0b786218 100644 --- a/bin/dev-plugin.sh +++ b/bin/dev-plugin.sh @@ -2,4 +2,4 @@ set -e -watchexec -c -w plugin "rojo build plugin -o $LOCALAPPDATA/Roblox/Plugins/Rojo.rbxm" \ No newline at end of file +watchexec -c -w plugin "sh -c './bin/install-dev-plugin.sh'" \ No newline at end of file diff --git a/bin/install-dev-plugin.sh b/bin/install-dev-plugin.sh index 888ec065..d8a8376c 100644 --- a/bin/install-dev-plugin.sh +++ b/bin/install-dev-plugin.sh @@ -2,4 +2,12 @@ set -e -rojo build plugin -o $LOCALAPPDATA/Roblox/Plugins/Rojo.rbxm \ No newline at end of file +DIR="$( mktemp -d )" +PLUGIN_FILE="$DIR/Rojo.rbxm" +TESTEZ_FILE="$DIR/TestEZ.rbxm" + +rojo build plugin -o "$PLUGIN_FILE" +rojo build plugin/testez.project.json -o "$TESTEZ_FILE" +remodel bin/mark-plugin-as-dev.lua "$PLUGIN_FILE" "$TESTEZ_FILE" 2>/dev/null + +cp "$PLUGIN_FILE" "$LOCALAPPDATA/Roblox/Plugins/Rojo.rbxm" \ No newline at end of file diff --git a/bin/mark-plugin-as-dev.lua b/bin/mark-plugin-as-dev.lua new file mode 100644 index 00000000..49fe902a --- /dev/null +++ b/bin/mark-plugin-as-dev.lua @@ -0,0 +1,12 @@ +local pluginPath, testezPath = ... + +local plugin = remodel.readModelFile(pluginPath)[1] +local testez = remodel.readModelFile(testezPath)[1] + +local marker = Instance.new("Folder") +marker.Name = "ROJO_DEV_BUILD" +marker.Parent = plugin + +testez.Parent = plugin + +remodel.writeModelFile(plugin, pluginPath) \ No newline at end of file diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 813591a3..1497cab1 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -1,8 +1,13 @@ -return { +local strict = require(script.Parent.strict) + +local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil + +return strict("Config", { + isDevBuild = isDevBuild, codename = "Epiphany", version = {0, 6, 0, "-dev"}, expectedServerVersionString = "0.6.0 or newer", protocolVersion = 3, defaultHost = "localhost", defaultPort = 34872, -} \ No newline at end of file +}) \ No newline at end of file diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua index 060742c2..bcf3f983 100644 --- a/plugin/src/DevSettings.lua +++ b/plugin/src/DevSettings.lua @@ -6,6 +6,8 @@ local Environment = { Test = "Test", } +local DEFAULT_ENVIRONMENT = Config.isDevBuild and Environment.Dev or Environment.User + local VALUES = { LogLevel = { type = "IntValue", @@ -84,7 +86,7 @@ local function getValue(name) return stored end - return VALUES[name].values[Environment.User] + return VALUES[name].values[DEFAULT_ENVIRONMENT] end local DevSettings = {} diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index 08de686e..3660d420 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -4,6 +4,7 @@ end local Roact = require(script.Parent.Roact) +local Config = require(script.Config) local App = require(script.Components.App) local app = Roact.createElement(App, { @@ -14,4 +15,10 @@ local tree = Roact.mount(app, game:GetService("CoreGui"), "Rojo UI") plugin.Unloading:Connect(function() Roact.unmount(tree) -end) \ No newline at end of file +end) + +if Config.isDevBuild then + local TestEZ = require(script.Parent.TestEZ) + + TestEZ.TestBootstrap:run({script}) +end \ No newline at end of file diff --git a/plugin/testez.project.json b/plugin/testez.project.json new file mode 100644 index 00000000..8b209162 --- /dev/null +++ b/plugin/testez.project.json @@ -0,0 +1,6 @@ +{ + "name": "TestEZ", + "tree": { + "$path": "modules/testez/lib" + } +} \ No newline at end of file From 581449d9928059dda1a51b9c1ab0fc43de5764e9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 17:13:43 -0700 Subject: [PATCH 0746/1504] Port more code over to use strict --- plugin/src/Assets.lua | 8 +++----- plugin/src/Theme.lua | 14 ++++---------- plugin/src/runTests.lua | 4 ---- 3 files changed, 7 insertions(+), 19 deletions(-) delete mode 100644 plugin/src/runTests.lua diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index 5c04bd8c..86b8500c 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -1,3 +1,5 @@ +local strict = require(script.Parent.strict) + local Assets = { Sprites = {}, Slices = { @@ -18,11 +20,7 @@ local Assets = { } local function guardForTypos(name, map) - setmetatable(map, { - __index = function(_, key) - error(("%q is not a valid member of %s"):format(tostring(key), name), 2) - end - }) + strict(name, map) for key, child in pairs(map) do if type(child) == "table" then diff --git a/plugin/src/Theme.lua b/plugin/src/Theme.lua index 9595efce..0307c287 100644 --- a/plugin/src/Theme.lua +++ b/plugin/src/Theme.lua @@ -1,4 +1,6 @@ -local Theme = { +local strict = require(script.Parent.strict) + +return strict("Theme", { ButtonFont = Enum.Font.GothamSemibold, InputFont = Enum.Font.Code, TitleFont = Enum.Font.GothamBold, @@ -9,12 +11,4 @@ local Theme = { PrimaryColor = Color3.fromRGB(64, 64, 64), SecondaryColor = Color3.fromRGB(235, 235, 235), LightTextColor = Color3.fromRGB(160, 160, 160), -} - -setmetatable(Theme, { - __index = function(_, key) - error(("%s is not a valid member of Theme"):format(key), 2) - end -}) - -return Theme \ No newline at end of file +}) \ No newline at end of file diff --git a/plugin/src/runTests.lua b/plugin/src/runTests.lua deleted file mode 100644 index 9b1da76e..00000000 --- a/plugin/src/runTests.lua +++ /dev/null @@ -1,4 +0,0 @@ -return function() - local TestEZ = require(script.Parent.Parent.TestEZ) - TestEZ.TestBootstrap:run(script.Parent) -end From fe1a96f850fb0b0d5eeaea179bdbae03f7c99dda Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 17:44:24 -0700 Subject: [PATCH 0747/1504] Improve plugin test running, reducing project duplication --- bin/put-plugin-in-test-place.lua | 8 +++++++ bin/run-plugin-tests.sh | 14 +++++++++--- plugin/place.project.json | 37 -------------------------------- 3 files changed, 19 insertions(+), 40 deletions(-) create mode 100644 bin/put-plugin-in-test-place.lua diff --git a/bin/put-plugin-in-test-place.lua b/bin/put-plugin-in-test-place.lua new file mode 100644 index 00000000..f651c1bf --- /dev/null +++ b/bin/put-plugin-in-test-place.lua @@ -0,0 +1,8 @@ +local pluginPath, placePath = ... + +local plugin = remodel.readModelFile(pluginPath)[1] +local place = remodel.readPlaceFile(placePath) + +plugin.Parent = place:GetService("ReplicatedStorage") + +remodel.writePlaceFile(place, placePath) \ No newline at end of file diff --git a/bin/run-plugin-tests.sh b/bin/run-plugin-tests.sh index 28d630a9..9d8672d7 100755 --- a/bin/run-plugin-tests.sh +++ b/bin/run-plugin-tests.sh @@ -1,6 +1,14 @@ #!/bin/sh -set -ev +set -e -rojo build plugin/place.project.json -o PluginPlace.rbxlx -run-in-roblox -s plugin/testBootstrap.server.lua PluginPlace.rbxlx \ No newline at end of file +DIR="$( mktemp -d )" +PLUGIN_FILE="$DIR/Rojo.rbxmx" +PLACE_FILE="$DIR/RojoTestPlace.rbxlx" + +rojo build plugin -o "$PLUGIN_FILE" +rojo build plugin/place.project.json -o "$PLACE_FILE" + +remodel bin/put-plugin-in-test-place.lua "$PLUGIN_FILE" "$PLACE_FILE" + +run-in-roblox -s plugin/testBootstrap.server.lua "$PLACE_FILE" \ No newline at end of file diff --git a/plugin/place.project.json b/plugin/place.project.json index 2010494e..1fa420be 100644 --- a/plugin/place.project.json +++ b/plugin/place.project.json @@ -6,46 +6,9 @@ "ReplicatedStorage": { "$className": "ReplicatedStorage", - "Rojo": { - "$className": "Folder", - - "Plugin": { - "$path": "src" - }, - "Roact": { - "$path": "modules/roact/src" - }, - "Promise": { - "$path": "modules/promise/lib" - }, - "t": { - "$path": "modules/t/lib" - }, - "RbxDom": { - "$path": "modules/rbx-dom/rbx_dom_lua/src" - } - }, "TestEZ": { "$path": "modules/testez/lib" } - }, - - "HttpService": { - "$className": "HttpService", - "$properties": { - "HttpEnabled": { - "Type": "Bool", - "Value": true - } - } - }, - - "ServerScriptService": { - "$className": "ServerScriptService", - - "TestBootstrap": { - "$path": "testBootstrap.server.lua" - } } } } \ No newline at end of file From 46858c45b8335317cff1fa5a2fa23a8e8c99fba6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 17:52:36 -0700 Subject: [PATCH 0748/1504] Add note about tools for contributing --- CONTRIBUTING.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index a3f62a56..3bef6e64 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -11,6 +11,12 @@ Some of the repositories covered are: ## Code Code contributions are welcome for features and bugs that have been reported in the project's bug tracker. We want to make sure that no one wastes their time, so be sure to talk with maintainers about what changes would be accepted before doing any work! +You'll want these tools to work on Rojo: + +* Latest stable Rust compiler +* Latest stable Rojo +* Latest stable Remodel + ## Documentation Documentation impacts way more people than the individual lines of code we write. From 09368e87cfa3d60e1754e7e7fb6f7fe8bc0606ee Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 17:54:53 -0700 Subject: [PATCH 0749/1504] Further update contributing guide on tools --- CONTRIBUTING.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3bef6e64..aff0c400 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,8 +14,9 @@ Code contributions are welcome for features and bugs that have been reported in You'll want these tools to work on Rojo: * Latest stable Rust compiler -* Latest stable Rojo -* Latest stable Remodel +* Latest stable [Rojo](https://github.com/rojo-rbx/rojo) +* Latest stable [Remodel](https://github.com/rojo-rbx/remodel) +* Latest stable [run-in-roblox](https://github.com/rojo-rbx/run-in-roblox) ## Documentation Documentation impacts way more people than the individual lines of code we write. From bdd9c58caefaca934ea41a848d1830b144e66620 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 18:07:32 -0700 Subject: [PATCH 0750/1504] Update all CI scripts and mark as executable --- bin/dev-plugin.sh | 0 bin/install-dev-plugin.sh | 0 bin/run-all-tests.sh | 6 ++++++ bin/run-cli-tests.sh | 9 +++++++++ bin/run-plugin-tests.sh | 14 +++++++++++++- 5 files changed, 28 insertions(+), 1 deletion(-) mode change 100644 => 100755 bin/dev-plugin.sh mode change 100644 => 100755 bin/install-dev-plugin.sh create mode 100755 bin/run-all-tests.sh create mode 100755 bin/run-cli-tests.sh diff --git a/bin/dev-plugin.sh b/bin/dev-plugin.sh old mode 100644 new mode 100755 diff --git a/bin/install-dev-plugin.sh b/bin/install-dev-plugin.sh old mode 100644 new mode 100755 diff --git a/bin/run-all-tests.sh b/bin/run-all-tests.sh new file mode 100755 index 00000000..e17aafa4 --- /dev/null +++ b/bin/run-all-tests.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +set -e + +./bin/run-cli-tests.sh +./bin/run-plugin-tests.sh \ No newline at end of file diff --git a/bin/run-cli-tests.sh b/bin/run-cli-tests.sh new file mode 100755 index 00000000..8f1b49a2 --- /dev/null +++ b/bin/run-cli-tests.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +set -e + +cargo test --all --locked +cargo fmt -- --check + +touch src/lib.rs # Nudge Rust source to make Clippy actually check things +cargo clippy \ No newline at end of file diff --git a/bin/run-plugin-tests.sh b/bin/run-plugin-tests.sh index 9d8672d7..ecbf0c96 100755 --- a/bin/run-plugin-tests.sh +++ b/bin/run-plugin-tests.sh @@ -11,4 +11,16 @@ rojo build plugin/place.project.json -o "$PLACE_FILE" remodel bin/put-plugin-in-test-place.lua "$PLUGIN_FILE" "$PLACE_FILE" -run-in-roblox -s plugin/testBootstrap.server.lua "$PLACE_FILE" \ No newline at end of file +run-in-roblox -s plugin/testBootstrap.server.lua "$PLACE_FILE" + +pushd plugin +luacheck src +popd + +pushd rojo-plugin-http +luacheck src +popd + +pushd rojo-plugin-log +luacheck src +popd \ No newline at end of file From f9a5fee3642936386fa47c63afe64900f3928563 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 18:23:29 -0700 Subject: [PATCH 0751/1504] Reorganize and clean up plugin --- bin/run-plugin-tests.sh | 10 +--- bin/run-tests.sh | 7 --- plugin/.luacheckrc | 1 + plugin/default.project.json | 6 +++ plugin/{src/HttpError.lua => http/Error.lua} | 34 +++++------- .../HttpResponse.lua => http/Response.lua} | 18 +++---- plugin/{src/Http.lua => http/init.lua} | 24 +++++---- plugin/http/init.spec.lua | 5 ++ plugin/log/init.lua | 54 +++++++++++++++++++ plugin/log/init.spec.lua | 5 ++ plugin/src/ApiContext.lua | 5 +- plugin/src/Components/RojoFooter.lua | 2 - plugin/src/Logging.lua | 52 +----------------- plugin/src/Reconciler.lua | 5 +- plugin/src/init.server.lua | 8 +++ plugin/testBootstrap.server.lua | 2 +- 16 files changed, 125 insertions(+), 113 deletions(-) delete mode 100755 bin/run-tests.sh rename plugin/{src/HttpError.lua => http/Error.lua} (58%) rename plugin/{src/HttpResponse.lua => http/Response.lua} (56%) rename plugin/{src/Http.lua => http/init.lua} (63%) create mode 100644 plugin/http/init.spec.lua create mode 100644 plugin/log/init.lua create mode 100644 plugin/log/init.spec.lua diff --git a/bin/run-plugin-tests.sh b/bin/run-plugin-tests.sh index ecbf0c96..4f99bd10 100755 --- a/bin/run-plugin-tests.sh +++ b/bin/run-plugin-tests.sh @@ -14,13 +14,5 @@ remodel bin/put-plugin-in-test-place.lua "$PLUGIN_FILE" "$PLACE_FILE" run-in-roblox -s plugin/testBootstrap.server.lua "$PLACE_FILE" pushd plugin -luacheck src -popd - -pushd rojo-plugin-http -luacheck src -popd - -pushd rojo-plugin-log -luacheck src +luacheck src log http popd \ No newline at end of file diff --git a/bin/run-tests.sh b/bin/run-tests.sh deleted file mode 100755 index 03647950..00000000 --- a/bin/run-tests.sh +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh - -set -ev - -cargo test --all --locked --verbose -cargo fmt -- --check -cargo clippy \ No newline at end of file diff --git a/plugin/.luacheckrc b/plugin/.luacheckrc index 9a0c40a1..b523c1b5 100644 --- a/plugin/.luacheckrc +++ b/plugin/.luacheckrc @@ -20,6 +20,7 @@ stds.roblox = { "CFrame", "Enum", "Instance", + "DockWidgetPluginGuiInfo", } } diff --git a/plugin/default.project.json b/plugin/default.project.json index 791edc0e..bdccf678 100644 --- a/plugin/default.project.json +++ b/plugin/default.project.json @@ -5,6 +5,12 @@ "Plugin": { "$path": "src" }, + "Log": { + "$path": "log" + }, + "Http": { + "$path": "http" + }, "Roact": { "$path": "modules/roact/src" }, diff --git a/plugin/src/HttpError.lua b/plugin/http/Error.lua similarity index 58% rename from plugin/src/HttpError.lua rename to plugin/http/Error.lua index e1ef9b7a..43d6782b 100644 --- a/plugin/src/HttpError.lua +++ b/plugin/http/Error.lua @@ -1,9 +1,7 @@ -local Logging = require(script.Parent.Logging) +local Error = {} +Error.__index = Error -local HttpError = {} -HttpError.__index = HttpError - -HttpError.Error = { +Error.Kind = { HttpNotEnabled = { message = "Rojo requires HTTP access, which is not enabled.\n" .. "Check your game settings, located in the 'Home' tab of Studio.", @@ -20,13 +18,13 @@ HttpError.Error = { }, } -setmetatable(HttpError.Error, { +setmetatable(Error.Kind, { __index = function(_, key) - error(("%q is not a valid member of HttpError.Error"):format(tostring(key)), 2) + error(("%q is not a valid member of Http.Error.Kind"):format(tostring(key)), 2) end, }) -function HttpError.new(type, extraMessage) +function Error.new(type, extraMessage) extraMessage = extraMessage or "" local message = type.message:gsub("{{message}}", extraMessage) @@ -35,38 +33,34 @@ function HttpError.new(type, extraMessage) message = message, } - setmetatable(err, HttpError) + setmetatable(err, Error) return err end -function HttpError:__tostring() +function Error:__tostring() return self.message end --[[ This method shouldn't have to exist. Ugh. ]] -function HttpError.fromErrorString(message) +function Error.fromErrorString(message) local lower = message:lower() if lower:find("^http requests are not enabled") then - return HttpError.new(HttpError.Error.HttpNotEnabled) + return Error.new(Error.Kind.HttpNotEnabled) end if lower:find("^httperror: timedout") then - return HttpError.new(HttpError.Error.Timeout) + return Error.new(Error.Kind.Timeout) end if lower:find("^httperror: connectfail") then - return HttpError.new(HttpError.Error.ConnectFailed) + return Error.new(Error.Kind.ConnectFailed) end - return HttpError.new(HttpError.Error.Unknown, message) + return Error.new(Error.Kind.Unknown, message) end -function HttpError:report() - Logging.warn(self.message) -end - -return HttpError \ No newline at end of file +return Error \ No newline at end of file diff --git a/plugin/src/HttpResponse.lua b/plugin/http/Response.lua similarity index 56% rename from plugin/src/HttpResponse.lua rename to plugin/http/Response.lua index 039f8538..ce4e1b6d 100644 --- a/plugin/src/HttpResponse.lua +++ b/plugin/http/Response.lua @@ -1,34 +1,34 @@ local HttpService = game:GetService("HttpService") local stringTemplate = [[ -HttpResponse { +Http.Response { code: %d body: %s }]] -local HttpResponse = {} -HttpResponse.__index = HttpResponse +local Response = {} +Response.__index = Response -function HttpResponse:__tostring() +function Response:__tostring() return stringTemplate:format(self.code, self.body) end -function HttpResponse.fromRobloxResponse(response) +function Response.fromRobloxResponse(response) local self = { body = response.Body, code = response.StatusCode, headers = response.Headers, } - return setmetatable(self, HttpResponse) + return setmetatable(self, Response) end -function HttpResponse:isSuccess() +function Response:isSuccess() return self.code >= 200 and self.code < 300 end -function HttpResponse:json() +function Response:json() return HttpService:JSONDecode(self.body) end -return HttpResponse \ No newline at end of file +return Response \ No newline at end of file diff --git a/plugin/src/Http.lua b/plugin/http/init.lua similarity index 63% rename from plugin/src/Http.lua rename to plugin/http/init.lua index 03b26658..3cd016bf 100644 --- a/plugin/src/Http.lua +++ b/plugin/http/init.lua @@ -1,21 +1,23 @@ local HttpService = game:GetService("HttpService") -local Promise = require(script.Parent.Parent.Promise) +local Promise = require(script.Parent.Promise) +local Log = require(script.Parent.Log) -local Logging = require(script.Parent.Logging) -local HttpError = require(script.Parent.HttpError) -local HttpResponse = require(script.Parent.HttpResponse) +local HttpError = require(script.Error) +local HttpResponse = require(script.Response) local lastRequestId = 0 --- TODO: Factor out into separate library, especially error handling local Http = {} +Http.Error = HttpError +Http.Response = HttpResponse + function Http.get(url) local requestId = lastRequestId + 1 lastRequestId = requestId - Logging.trace("GET(%d) %s", requestId, url) + Log.trace("GET(%d) %s", requestId, url) return Promise.new(function(resolve, reject) coroutine.wrap(function() @@ -27,10 +29,10 @@ function Http.get(url) end) if success then - Logging.trace("Request %d success: status code %s", requestId, response.StatusCode) + Log.trace("Request %d success: status code %s", requestId, response.StatusCode) resolve(HttpResponse.fromRobloxResponse(response)) else - Logging.trace("Request %d failure: %s", requestId, response) + Log.trace("Request %d failure: %s", requestId, response) reject(HttpError.fromErrorString(response)) end end)() @@ -41,7 +43,7 @@ function Http.post(url, body) local requestId = lastRequestId + 1 lastRequestId = requestId - Logging.trace("POST(%d) %s\n%s", requestId, url, body) + Log.trace("POST(%d) %s\n%s", requestId, url, body) return Promise.new(function(resolve, reject) coroutine.wrap(function() @@ -54,10 +56,10 @@ function Http.post(url, body) end) if success then - Logging.trace("Request %d success: status code %s", requestId, response.StatusCode) + Log.trace("Request %d success: status code %s", requestId, response.StatusCode) resolve(HttpResponse.fromRobloxResponse(response)) else - Logging.trace("Request %d failure: %s", requestId, response) + Log.trace("Request %d failure: %s", requestId, response) reject(HttpError.fromErrorString(response)) end end)() diff --git a/plugin/http/init.spec.lua b/plugin/http/init.spec.lua new file mode 100644 index 00000000..ff7e8e3b --- /dev/null +++ b/plugin/http/init.spec.lua @@ -0,0 +1,5 @@ +return function() + it("should load", function() + require(script.Parent) + end) +end \ No newline at end of file diff --git a/plugin/log/init.lua b/plugin/log/init.lua new file mode 100644 index 00000000..d3defd6d --- /dev/null +++ b/plugin/log/init.lua @@ -0,0 +1,54 @@ +local Level = { + Error = 0, + Warning = 1, + Info = 2, + Debug = 3, + Trace = 4, +} + +local function getLogLevel() + return Level.Info +end + +local function addTags(tag, message) + return tag .. message:gsub("\n", "\n" .. tag) +end + +local TRACE_TAG = (" "):rep(15) .. "[Rojo-Trace] " +local INFO_TAG = (" "):rep(15) .. "[Rojo-Info] " +local DEBUG_TAG = (" "):rep(15) .. "[Rojo-Debug] " +local WARN_TAG = "[Rojo-Warn] " + +local Log = {} + +Log.Level = Level + +function Log.setLogLevelThunk(thunk) + getLogLevel = thunk +end + +function Log.trace(template, ...) + if getLogLevel() >= Level.Trace then + print(addTags(TRACE_TAG, string.format(template, ...))) + end +end + +function Log.info(template, ...) + if getLogLevel() >= Level.Info then + print(addTags(INFO_TAG, string.format(template, ...))) + end +end + +function Log.debug(template, ...) + if getLogLevel() >= Level.Debug then + print(addTags(DEBUG_TAG, string.format(template, ...))) + end +end + +function Log.warn(template, ...) + if getLogLevel() >= Level.Warning then + warn(addTags(WARN_TAG, string.format(template, ...))) + end +end + +return Log \ No newline at end of file diff --git a/plugin/log/init.spec.lua b/plugin/log/init.spec.lua new file mode 100644 index 00000000..ff7e8e3b --- /dev/null +++ b/plugin/log/init.spec.lua @@ -0,0 +1,5 @@ +return function() + it("should load", function() + require(script.Parent) + end) +end \ No newline at end of file diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 0b6a7531..930ca2f3 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -1,9 +1,8 @@ local Promise = require(script.Parent.Parent.Promise) +local Http = require(script.Parent.Parent.Http) local Config = require(script.Parent.Config) local Version = require(script.Parent.Version) -local Http = require(script.Parent.Http) -local HttpError = require(script.Parent.HttpError) local ApiContext = {} ApiContext.__index = ApiContext @@ -143,7 +142,7 @@ function ApiContext:retrieveMessages() local function sendRequest() return Http.get(url) :catch(function(err) - if err.type == HttpError.Error.Timeout then + if err.type == Http.Error.Kind.Timeout then return sendRequest() end diff --git a/plugin/src/Components/RojoFooter.lua b/plugin/src/Components/RojoFooter.lua index 767e82bf..babc1a78 100644 --- a/plugin/src/Components/RojoFooter.lua +++ b/plugin/src/Components/RojoFooter.lua @@ -8,8 +8,6 @@ local Version = require(Plugin.Version) local Assets = require(Plugin.Assets) local Theme = require(Plugin.Theme) -local FitText = require(Plugin.Components.FitText) - local e = Roact.createElement local RojoFooter = Roact.Component:extend("RojoFooter") diff --git a/plugin/src/Logging.lua b/plugin/src/Logging.lua index 4b4f90af..398568ad 100644 --- a/plugin/src/Logging.lua +++ b/plugin/src/Logging.lua @@ -1,50 +1,2 @@ -local DevSettings = require(script.Parent.DevSettings) - -local Level = { - Error = 0, - Warning = 1, - Info = 2, - Trace = 3, -} - -local testLogLevel = nil - -local function getLogLevel() - if testLogLevel ~= nil then - return testLogLevel - end - - return DevSettings:getLogLevel() -end - -local function addTags(tag, message) - return tag .. message:gsub("\n", "\n" .. tag) -end - -local INFO_TAG = (" "):rep(15) .. "[Rojo-Info] " -local TRACE_TAG = (" "):rep(15) .. "[Rojo-Trace] " -local WARN_TAG = "[Rojo-Warn] " - -local Log = {} - -Log.Level = Level - -function Log.trace(template, ...) - if getLogLevel() >= Level.Trace then - print(addTags(TRACE_TAG, string.format(template, ...))) - end -end - -function Log.info(template, ...) - if getLogLevel() >= Level.Info then - print(addTags(INFO_TAG, string.format(template, ...))) - end -end - -function Log.warn(template, ...) - if getLogLevel() >= Level.Warning then - warn(addTags(WARN_TAG, string.format(template, ...))) - end -end - -return Log \ No newline at end of file +-- TODO: Remove this once all references have been updated. +return require(script.Parent.Parent.Log) \ No newline at end of file diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 66d41fe6..0e626bef 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -161,7 +161,10 @@ function Reconciler:__reify(virtualInstancesById, id, parent) end) if not ok then - error(("Couldn't create an Instance of type %q, a child of %s"):format(virtualInstance.ClassName, parent:GetFullName())) + error(("Couldn't create an Instance of type %q, a child of %s"):format( + virtualInstance.ClassName, + parent:GetFullName() + )) end for key, value in pairs(virtualInstance.Properties) do diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index 3660d420..dce195ef 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -2,6 +2,14 @@ if not plugin then return end +local Log = require(script.Parent.Log) + +local DevSettings = require(script.DevSettings) + +Log.setLogLevelThunk(function() + return DevSettings:getLogLevel() +end) + local Roact = require(script.Parent.Roact) local Config = require(script.Config) diff --git a/plugin/testBootstrap.server.lua b/plugin/testBootstrap.server.lua index 81ed88b2..12f6b5f0 100644 --- a/plugin/testBootstrap.server.lua +++ b/plugin/testBootstrap.server.lua @@ -12,7 +12,7 @@ if setDevSettings then DevSettings:createTestSettings() end -TestEZ.TestBootstrap:run({Rojo.Plugin}) +TestEZ.TestBootstrap:run({ Rojo.Plugin, Rojo.Http, Rojo.Log }) if setDevSettings then DevSettings:resetValues() From c4a7f8675fbdd74595c22666d176d94bea6f848c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 18:37:25 -0700 Subject: [PATCH 0752/1504] Fix log level in plugin dev mode --- plugin/src/DevSettings.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua index bcf3f983..1c9d0aa7 100644 --- a/plugin/src/DevSettings.lua +++ b/plugin/src/DevSettings.lua @@ -13,8 +13,8 @@ local VALUES = { type = "IntValue", values = { [Environment.User] = 2, - [Environment.Dev] = 3, - [Environment.Test] = 3, + [Environment.Dev] = 4, + [Environment.Test] = 4, }, }, TypecheckingEnabled = { From 79f09deecb584ac58a7808267a8ec5a45115a22f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 18:37:35 -0700 Subject: [PATCH 0753/1504] Add strong type checking to plugin API client --- plugin/src/ApiContext.lua | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 930ca2f3..4501e7c8 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -3,6 +3,11 @@ local Http = require(script.Parent.Parent.Http) local Config = require(script.Parent.Config) local Version = require(script.Parent.Version) +local Types = require(script.Parent.Types) + +local validateApiInfo = Types.ifEnabled(Types.ApiInfoResponse) +local validateApiRead = Types.ifEnabled(Types.ApiReadResponse) +local validateApiSubscribe = Types.ifEnabled(Types.ApiSubscribeResponse) local ApiContext = {} ApiContext.__index = ApiContext @@ -82,6 +87,8 @@ function ApiContext:connect() return Promise.reject(message) end + assert(validateApiInfo(body)) + if body.expectedPlaceIds ~= nil then local foundId = false @@ -130,6 +137,8 @@ function ApiContext:read(ids) return Promise.reject("Server changed ID") end + assert(validateApiRead(body)) + self.messageCursor = body.messageCursor return body @@ -159,6 +168,8 @@ function ApiContext:retrieveMessages() return Promise.reject("Server changed ID") end + assert(validateApiSubscribe(body)) + self.messageCursor = body.messageCursor return body.messages From 40105515d274909aaaf1234df97b0f65a23fd670 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 18:41:33 -0700 Subject: [PATCH 0754/1504] plugin: Unify test running code --- plugin/src/init.server.lua | 2 +- plugin/src/runTests.lua | 5 +++++ plugin/testBootstrap.server.lua | 2 +- 3 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 plugin/src/runTests.lua diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index dce195ef..c249171b 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -28,5 +28,5 @@ end) if Config.isDevBuild then local TestEZ = require(script.Parent.TestEZ) - TestEZ.TestBootstrap:run({script}) + require(script.runTests)(TestEZ) end \ No newline at end of file diff --git a/plugin/src/runTests.lua b/plugin/src/runTests.lua new file mode 100644 index 00000000..ea6172c2 --- /dev/null +++ b/plugin/src/runTests.lua @@ -0,0 +1,5 @@ +return function(TestEZ) + local Rojo = script.Parent.Parent + + TestEZ.TestBootstrap:run({ Rojo.Plugin, Rojo.Http, Rojo.Log }) +end \ No newline at end of file diff --git a/plugin/testBootstrap.server.lua b/plugin/testBootstrap.server.lua index 12f6b5f0..a9ebcdf6 100644 --- a/plugin/testBootstrap.server.lua +++ b/plugin/testBootstrap.server.lua @@ -12,7 +12,7 @@ if setDevSettings then DevSettings:createTestSettings() end -TestEZ.TestBootstrap:run({ Rojo.Plugin, Rojo.Http, Rojo.Log }) +require(Rojo.Plugin.runTests)(TestEZ) if setDevSettings then DevSettings:resetValues() From 73bbaaf0afdbbb59d4db789f6c0b4efa0b70152d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 1 Oct 2019 18:42:25 -0700 Subject: [PATCH 0755/1504] Add script for installing release plugin --- bin/install-release-plugin.sh | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 bin/install-release-plugin.sh diff --git a/bin/install-release-plugin.sh b/bin/install-release-plugin.sh new file mode 100755 index 00000000..f670c18c --- /dev/null +++ b/bin/install-release-plugin.sh @@ -0,0 +1,5 @@ +#!/bin/sh + +set -e + +rojo build plugin -o "$LOCALAPPDATA/Roblox/Plugins/Rojo.rbxm" \ No newline at end of file From 21d4acebc3980e2c309657b5c6a9929d7b5bdc1b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 2 Oct 2019 10:42:10 -0700 Subject: [PATCH 0756/1504] Move .luacheckrc for better editor detection --- plugin/.luacheckrc => .luacheckrc | 0 bin/run-plugin-tests.sh | 4 +--- 2 files changed, 1 insertion(+), 3 deletions(-) rename plugin/.luacheckrc => .luacheckrc (100%) diff --git a/plugin/.luacheckrc b/.luacheckrc similarity index 100% rename from plugin/.luacheckrc rename to .luacheckrc diff --git a/bin/run-plugin-tests.sh b/bin/run-plugin-tests.sh index 4f99bd10..1da9bb47 100755 --- a/bin/run-plugin-tests.sh +++ b/bin/run-plugin-tests.sh @@ -13,6 +13,4 @@ remodel bin/put-plugin-in-test-place.lua "$PLUGIN_FILE" "$PLACE_FILE" run-in-roblox -s plugin/testBootstrap.server.lua "$PLACE_FILE" -pushd plugin -luacheck src log http -popd \ No newline at end of file +luacheck plugin/src plugin/log plugin/http \ No newline at end of file From 7cada2608fc96acc635a1907af81771fbf5a1766 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 2 Oct 2019 11:04:40 -0700 Subject: [PATCH 0757/1504] plugin: Refactor HTTP and ApiContext foundations --- plugin/http/Error.lua | 6 ++--- plugin/http/init.lua | 51 +++++++++++++++++------------------------- plugin/src/Session.lua | 16 ++++++------- 3 files changed, 31 insertions(+), 42 deletions(-) diff --git a/plugin/http/Error.lua b/plugin/http/Error.lua index 43d6782b..271a8ab7 100644 --- a/plugin/http/Error.lua +++ b/plugin/http/Error.lua @@ -11,10 +11,10 @@ Error.Kind = { "Make sure the server is running -- use 'rojo serve' to run it!", }, Timeout = { - message = "Request timed out.", + message = "HTTP request timed out.", }, Unknown = { - message = "Unknown error: {{message}}", + message = "Unknown HTTP error: {{message}}", }, } @@ -45,7 +45,7 @@ end --[[ This method shouldn't have to exist. Ugh. ]] -function Error.fromErrorString(message) +function Error.fromRobloxErrorString(message) local lower = message:lower() if lower:find("^http requests are not enabled") then diff --git a/plugin/http/init.lua b/plugin/http/init.lua index 3cd016bf..395bcc7e 100644 --- a/plugin/http/init.lua +++ b/plugin/http/init.lua @@ -13,19 +13,20 @@ local Http = {} Http.Error = HttpError Http.Response = HttpResponse -function Http.get(url) +local function performRequest(requestParams) local requestId = lastRequestId + 1 lastRequestId = requestId - Log.trace("GET(%d) %s", requestId, url) + Log.trace("%s(%d) %s", requestParams.Method, requestId, requestParams.Url) + + if requestParams.Body ~= nil then + Log.trace(requestParams.Body) + end return Promise.new(function(resolve, reject) coroutine.wrap(function() local success, response = pcall(function() - return HttpService:RequestAsync({ - Url = url, - Method = "GET", - }) + return HttpService:RequestAsync(requestParams) end) if success then @@ -33,37 +34,25 @@ function Http.get(url) resolve(HttpResponse.fromRobloxResponse(response)) else Log.trace("Request %d failure: %s", requestId, response) - reject(HttpError.fromErrorString(response)) + reject(HttpError.fromRobloxErrorString(response)) end end)() end) end +function Http.get(url) + return performRequest({ + Url = url, + Method = "GET", + }) +end + function Http.post(url, body) - local requestId = lastRequestId + 1 - lastRequestId = requestId - - Log.trace("POST(%d) %s\n%s", requestId, url, body) - - return Promise.new(function(resolve, reject) - coroutine.wrap(function() - local success, response = pcall(function() - return HttpService:RequestAsync({ - Url = url, - Method = "POST", - Body = body, - }) - end) - - if success then - Log.trace("Request %d success: status code %s", requestId, response.StatusCode) - resolve(HttpResponse.fromRobloxResponse(response)) - else - Log.trace("Request %d failure: %s", requestId, response) - reject(HttpError.fromErrorString(response)) - end - end)() - end) + return performRequest({ + Url = url, + Method = "POST", + Body = body, + }) end function Http.jsonEncode(object) diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index 50d47cd0..a9b30005 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -9,30 +9,30 @@ local Session = {} Session.__index = Session function Session.new(config) - local remoteUrl = ("http://%s:%s"):format(config.address, config.port) - local api = ApiContext.new(remoteUrl) + local baseUrl = ("http://%s:%s"):format(config.address, config.port) + local apiContext = ApiContext.new(baseUrl) local self = { onError = config.onError, disconnected = false, reconciler = Reconciler.new(), - api = api, + apiContext = apiContext, } - api:connect() + apiContext:connect() :andThen(function() if self.disconnected then return end - return api:read({api.rootInstanceId}) + return apiContext:read({apiContext.rootInstanceId}) end) :andThen(function(response) if self.disconnected then return end - self.reconciler:reconcile(response.instances, api.rootInstanceId, game) + self.reconciler:reconcile(response.instances, apiContext.rootInstanceId, game) return self:__processMessages() end) :catch(function(message) @@ -48,7 +48,7 @@ function Session:__processMessages() return Promise.resolve() end - return self.api:retrieveMessages() + return self.apiContext:retrieveMessages() :andThen(function(messages) local promise = Promise.resolve(nil) @@ -84,7 +84,7 @@ function Session:__onMessage(message) table.insert(requestedIds, id) end - return self.api:read(requestedIds) + return self.apiContext:read(requestedIds) :andThen(function(response) return self.reconciler:applyUpdate(requestedIds, response.instances) end) From 3554112f31d6a7080c88393429ce26f235675730 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 2 Oct 2019 11:07:22 -0700 Subject: [PATCH 0758/1504] plugin: Add test that loads all modules --- plugin/src/init.spec.lua | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 plugin/src/init.spec.lua diff --git a/plugin/src/init.spec.lua b/plugin/src/init.spec.lua new file mode 100644 index 00000000..ad474338 --- /dev/null +++ b/plugin/src/init.spec.lua @@ -0,0 +1,15 @@ +return function() + it("should load all submodules", function() + local function loadRecursive(container) + if container:IsA("ModuleScript") and not container.Name:find("%.spec$") then + require(container) + end + + for _, child in ipairs(container:GetChildren()) do + loadRecursive(child) + end + end + + loadRecursive(script.Parent) + end) +end \ No newline at end of file From b562d11994950613cc0e51a4f3ca553d12a2ec02 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 2 Oct 2019 11:10:34 -0700 Subject: [PATCH 0759/1504] plugin: Remove Logging alias and update imports --- plugin/src/Components/App.lua | 16 ++++++++-------- plugin/src/InstanceMap.lua | 10 +++++----- plugin/src/Logging.lua | 2 -- plugin/src/Reconciler.lua | 10 +++++----- plugin/src/Session.lua | 4 +--- plugin/src/preloadAssets.lua | 5 +++-- plugin/src/setCanonicalProperty.lua | 2 +- 7 files changed, 23 insertions(+), 26 deletions(-) delete mode 100644 plugin/src/Logging.lua diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 7fcd4095..62150174 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -2,11 +2,11 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin local Roact = require(Rojo.Roact) +local Log = require(Rojo.Log) local Assets = require(Plugin.Assets) local Config = require(Plugin.Config) local DevSettings = require(Plugin.DevSettings) -local Logging = require(Plugin.Logging) local Session = require(Plugin.Session) local Version = require(Plugin.Version) local preloadAssets = require(Plugin.preloadAssets) @@ -26,7 +26,7 @@ local function showUpgradeMessage(lastVersion) Version.display(Config.version), Config.expectedServerVersionString ) - Logging.info(message) + Log.info(message) end --[[ @@ -114,7 +114,7 @@ function App:render() children = { ConnectionActivePanel = e(ConnectionActivePanel, { stopSession = function() - Logging.trace("Disconnecting session") + Log.trace("Disconnecting session") self.currentSession:disconnect() self.currentSession = nil @@ -122,7 +122,7 @@ function App:render() sessionStatus = SessionStatus.Disconnected, }) - Logging.trace("Session terminated by user") + Log.trace("Session terminated by user") end, }), } @@ -130,13 +130,13 @@ function App:render() children = { ConnectPanel = e(ConnectPanel, { startSession = function(address, port) - Logging.trace("Starting new session") + Log.trace("Starting new session") local success, session = Session.new({ address = address, port = port, onError = function(message) - Logging.warn("Rojo session terminated because of an error:\n%s", tostring(message)) + Log.warn("Rojo session terminated because of an error:\n%s", tostring(message)) self.currentSession = nil self:setState({ @@ -153,7 +153,7 @@ function App:render() end end, cancel = function() - Logging.trace("Canceling session configuration") + Log.trace("Canceling session configuration") self:setState({ sessionStatus = SessionStatus.Disconnected, @@ -169,7 +169,7 @@ function App:render() end function App:didMount() - Logging.trace("Rojo %s initializing", self.displayedVersion) + Log.trace("Rojo %s initializing", self.displayedVersion) checkUpgrade(self.props.plugin) preloadAssets() diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 16cefbd9..8ec3bf54 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -1,4 +1,4 @@ -local Logging = require(script.Parent.Logging) +local Log = require(script.Parent.Parent.Log) --[[ A bidirectional map between instance IDs and Roblox instances. It lets us @@ -30,7 +30,7 @@ function InstanceMap:removeId(id) self.fromIds[id] = nil self.fromInstances[instance] = nil else - Logging.warn("Attempted to remove nonexistant ID %s", tostring(id)) + Log.warn("Attempted to remove nonexistant ID %s", tostring(id)) end end @@ -41,7 +41,7 @@ function InstanceMap:removeInstance(instance) self.fromInstances[instance] = nil self.fromIds[id] = nil else - Logging.warn("Attempted to remove nonexistant instance %s", tostring(instance)) + Log.warn("Attempted to remove nonexistant instance %s", tostring(instance)) end end @@ -51,7 +51,7 @@ function InstanceMap:destroyInstance(instance) if id ~= nil then self:destroyId(id) else - Logging.warn("Attempted to destroy untracked instance %s", tostring(instance)) + Log.warn("Attempted to destroy untracked instance %s", tostring(instance)) end end @@ -74,7 +74,7 @@ function InstanceMap:destroyId(id) instance:Destroy() else - Logging.warn("Attempted to destroy nonexistant ID %s", tostring(id)) + Log.warn("Attempted to destroy nonexistant ID %s", tostring(id)) end end diff --git a/plugin/src/Logging.lua b/plugin/src/Logging.lua deleted file mode 100644 index 398568ad..00000000 --- a/plugin/src/Logging.lua +++ /dev/null @@ -1,2 +0,0 @@ --- TODO: Remove this once all references have been updated. -return require(script.Parent.Parent.Log) \ No newline at end of file diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 0e626bef..4a2d0884 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -1,7 +1,7 @@ local t = require(script.Parent.Parent.t) +local Log = require(script.Parent.Parent.Log) local InstanceMap = require(script.Parent.InstanceMap) -local Logging = require(script.Parent.Logging) local setCanonicalProperty = require(script.Parent.setCanonicalProperty) local rojoValueToRobloxValue = require(script.Parent.rojoValueToRobloxValue) local Types = require(script.Parent.Types) @@ -50,7 +50,7 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) -- If an instance changes ClassName, we assume it's very different. That's -- not always the case! if virtualInstance.ClassName ~= instance.ClassName then - Logging.trace("Switching to reify for %s because ClassName is different", instance:GetFullName()) + Log.trace("Switching to reify for %s because ClassName is different", instance:GetFullName()) -- TODO: Preserve existing children instead? local parent = instance.Parent @@ -95,7 +95,7 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) unvisitedExistingChildren[existingChildInstance] = nil self:reconcile(virtualInstancesById, childId, existingChildInstance) else - Logging.trace( + Log.trace( "Switching to reify for %s.%s because it does not exist", instance:GetFullName(), virtualInstancesById[childId].Name @@ -125,7 +125,7 @@ function Reconciler:reconcile(virtualInstancesById, id, instance) local parent = self.instanceMap.fromIds[virtualInstance.Parent] if parent == nil then - Logging.info("Instance %s wanted parent of %s", tostring(id), tostring(virtualInstance.Parent)) + Log.info("Instance %s wanted parent of %s", tostring(id), tostring(virtualInstance.Parent)) error("Rojo bug: During reconciliation, an instance referred to an instance ID as parent that does not exist.") end @@ -232,7 +232,7 @@ function Reconciler:__applyUpdatePiece(id, visitedIds, virtualInstancesById) return end - Logging.trace("Instance ID %s, parent ID %s", tostring(id), tostring(virtualInstance.Parent)) + Log.trace("Instance ID %s, parent ID %s", tostring(id), tostring(virtualInstance.Parent)) error("Rojo NYI: Instances with parents that weren't mentioned in an update payload") end diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua index a9b30005..ef37f16c 100644 --- a/plugin/src/Session.lua +++ b/plugin/src/Session.lua @@ -1,6 +1,4 @@ -local Rojo = script:FindFirstAncestor("Rojo") - -local Promise = require(Rojo.Promise) +local Promise = require(script.Parent.Parent.Promise) local ApiContext = require(script.Parent.ApiContext) local Reconciler = require(script.Parent.Reconciler) diff --git a/plugin/src/preloadAssets.lua b/plugin/src/preloadAssets.lua index 6f40e001..a8a4a4f1 100644 --- a/plugin/src/preloadAssets.lua +++ b/plugin/src/preloadAssets.lua @@ -1,6 +1,7 @@ local ContentProvider = game:GetService("ContentProvider") -local Logging = require(script.Parent.Logging) +local Log = require(script.Parent.Parent.Log) + local Assets = require(script.Parent.Assets) local function preloadAssets() @@ -18,7 +19,7 @@ local function preloadAssets() table.insert(contentUrls, url) end - Logging.trace("Preloading assets: %s", table.concat(contentUrls, ", ")) + Log.trace("Preloading assets: %s", table.concat(contentUrls, ", ")) coroutine.wrap(function() ContentProvider:PreloadAsync(contentUrls) diff --git a/plugin/src/setCanonicalProperty.lua b/plugin/src/setCanonicalProperty.lua index 8314cfcd..9554d020 100644 --- a/plugin/src/setCanonicalProperty.lua +++ b/plugin/src/setCanonicalProperty.lua @@ -1,4 +1,4 @@ -local RbxDom = require(script:FindFirstAncestor("Rojo").RbxDom) +local RbxDom = require(script.Parent.Parent.RbxDom) --[[ Attempts to set a property on the given instance. From 923f661428c28eb90b8abe13c834e1c3fe8ae72c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 2 Oct 2019 18:41:52 -0700 Subject: [PATCH 0760/1504] Start rewriting plugin on top of new sync protocol --- plugin/src/ApiContext.lua | 190 +++++------ plugin/src/Components/App.lua | 134 +++++--- plugin/src/Components/ConnectingPanel.lua | 34 ++ plugin/src/Components/ErrorPanel.lua | 51 +++ plugin/src/Components/FitText.lua | 46 ++- plugin/src/Reconciler.lua | 374 +++++++++++---------- plugin/src/Reconciler.spec.lua | 218 ------------ plugin/src/ServeSession.lua | 99 ++++++ plugin/src/Session.lua | 95 ------ plugin/src/Types.lua | 1 + plugin/src/rojoValueToRobloxValue.lua | 19 -- plugin/src/rojoValueToRobloxValue.spec.lua | 40 --- 12 files changed, 591 insertions(+), 710 deletions(-) create mode 100644 plugin/src/Components/ConnectingPanel.lua create mode 100644 plugin/src/Components/ErrorPanel.lua delete mode 100644 plugin/src/Reconciler.spec.lua create mode 100644 plugin/src/ServeSession.lua delete mode 100644 plugin/src/Session.lua delete mode 100644 plugin/src/rojoValueToRobloxValue.lua delete mode 100644 plugin/src/rojoValueToRobloxValue.spec.lua diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 4501e7c8..31893647 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -1,152 +1,133 @@ -local Promise = require(script.Parent.Parent.Promise) local Http = require(script.Parent.Parent.Http) +local Promise = require(script.Parent.Parent.Promise) local Config = require(script.Parent.Config) -local Version = require(script.Parent.Version) local Types = require(script.Parent.Types) +local Version = require(script.Parent.Version) local validateApiInfo = Types.ifEnabled(Types.ApiInfoResponse) local validateApiRead = Types.ifEnabled(Types.ApiReadResponse) local validateApiSubscribe = Types.ifEnabled(Types.ApiSubscribeResponse) -local ApiContext = {} -ApiContext.__index = ApiContext - --- TODO: Audit cases of errors and create enum values for each of them. -ApiContext.Error = { - ServerIdMismatch = "ServerIdMismatch", - - -- The server gave an unexpected 400-category error, which may be the - -- client's fault. - ClientError = "ClientError", - - -- The server gave an unexpected 500-category error, which may be the - -- server's fault. - ServerError = "ServerError", -} - -setmetatable(ApiContext.Error, { - __index = function(_, key) - error("Invalid ApiContext.Error name " .. key, 2) - end -}) - local function rejectFailedRequests(response) if response.code >= 400 then - if response.code < 500 then - return Promise.reject(ApiContext.Error.ClientError) - else - return Promise.reject(ApiContext.Error.ServerError) - end + -- TODO: Nicer error types for responses, using response JSON if valid. + return Promise.reject(tostring(response.code)) end return response end +local function rejectWrongProtocolVersion(infoResponseBody) + if infoResponseBody.protocolVersion ~= Config.protocolVersion then + local message = ( + "Found a Rojo dev server, but it's using a different protocol version, and is incompatible." .. + "\nMake sure you have matching versions of both the Rojo plugin and server!" .. + "\n\nYour client is version %s, with protocol version %s. It expects server version %s." .. + "\nYour server is version %s, with protocol version %s." .. + "\n\nGo to https://github.com/rojo-rbx/rojo for more details." + ):format( + Version.display(Config.version), Config.protocolVersion, + Config.expectedServerVersionString, + infoResponseBody.serverVersion, infoResponseBody.protocolVersion + ) + + return Promise.reject(message) + end + + return Promise.resolve(infoResponseBody) +end + +local function rejectWrongPlaceId(infoResponseBody) + if infoResponseBody.expectedPlaceIds ~= nil then + local foundId = false + + for _, id in ipairs(infoResponseBody.expectedPlaceIds) do + if id == game.PlaceId then + foundId = true + break + end + end + + if not foundId then + local idList = {} + for _, id in ipairs(infoResponseBody.expectedPlaceIds) do + table.insert(idList, "- " .. tostring(id)) + end + + local message = ( + "Found a Rojo server, but its project is set to only be used with a specific list of places." .. + "\nYour place ID is %s, but needs to be one of these:" .. + "\n%s" .. + "\n\nTo change this list, edit 'servePlaceIds' in your .project.json file." + ):format( + tostring(game.PlaceId), + table.concat(idList, "\n") + ) + + return Promise.reject(message) + end + end + + return Promise.resolve(infoResponseBody) +end + +local ApiContext = {} +ApiContext.__index = ApiContext + function ApiContext.new(baseUrl) assert(type(baseUrl) == "string") local self = { - baseUrl = baseUrl, - serverId = nil, - rootInstanceId = nil, - messageCursor = -1, - partitionRoutes = nil, + __baseUrl = baseUrl, + __serverId = nil, + __messageCursor = -1, } - setmetatable(self, ApiContext) - - return self -end - -function ApiContext:onMessage(callback) - self.onMessageCallback = callback + return setmetatable(self, ApiContext) end function ApiContext:connect() - local url = ("%s/api/rojo"):format(self.baseUrl) + local url = ("%s/api/rojo"):format(self.__baseUrl) return Http.get(url) :andThen(rejectFailedRequests) - :andThen(function(response) - local body = response:json() - - if body.protocolVersion ~= Config.protocolVersion then - local message = ( - "Found a Rojo dev server, but it's using a different protocol version, and is incompatible." .. - "\nMake sure you have matching versions of both the Rojo plugin and server!" .. - "\n\nYour client is version %s, with protocol version %s. It expects server version %s." .. - "\nYour server is version %s, with protocol version %s." .. - "\n\nGo to https://github.com/rojo-rbx/rojo for more details." - ):format( - Version.display(Config.version), Config.protocolVersion, - Config.expectedServerVersionString, - body.serverVersion, body.protocolVersion - ) - - return Promise.reject(message) - end - + :andThen(Http.Response.json) + :andThen(rejectWrongProtocolVersion) + :andThen(function(body) assert(validateApiInfo(body)) - if body.expectedPlaceIds ~= nil then - local foundId = false + return body + end) + :andThen(rejectWrongPlaceId) + :andThen(function(body) + self.__serverId = body.serverId - for _, id in ipairs(body.expectedPlaceIds) do - if id == game.PlaceId then - foundId = true - break - end - end - - if not foundId then - local idList = {} - for _, id in ipairs(body.expectedPlaceIds) do - table.insert(idList, "- " .. tostring(id)) - end - - local message = ( - "Found a Rojo server, but its project is set to only be used with a specific list of places." .. - "\nYour place ID is %s, but needs to be one of these:" .. - "\n%s" .. - "\n\nTo change this list, edit 'servePlaceIds' in roblox-project.json" - ):format( - tostring(game.PlaceId), - table.concat(idList, "\n") - ) - - return Promise.reject(message) - end - end - - self.serverId = body.serverId - self.partitionRoutes = body.partitions - self.rootInstanceId = body.rootInstanceId + return body end) end function ApiContext:read(ids) - local url = ("%s/api/read/%s"):format(self.baseUrl, table.concat(ids, ",")) + local url = ("%s/api/read/%s"):format(self.__baseUrl, table.concat(ids, ",")) return Http.get(url) :andThen(rejectFailedRequests) - :andThen(function(response) - local body = response:json() - - if body.serverId ~= self.serverId then + :andThen(Http.Response.json) + :andThen(function(body) + if body.serverId ~= self.__serverId then return Promise.reject("Server changed ID") end assert(validateApiRead(body)) - self.messageCursor = body.messageCursor + self.__messageCursor = body.messageCursor return body end) end function ApiContext:retrieveMessages() - local url = ("%s/api/subscribe/%s"):format(self.baseUrl, self.messageCursor) + local url = ("%s/api/subscribe/%s"):format(self.__baseUrl, self.__messageCursor) local function sendRequest() return Http.get(url) @@ -161,16 +142,15 @@ function ApiContext:retrieveMessages() return sendRequest() :andThen(rejectFailedRequests) - :andThen(function(response) - local body = response:json() - - if body.serverId ~= self.serverId then + :andThen(Http.Response.json) + :andThen(function(body) + if body.serverId ~= self.__serverId then return Promise.reject("Server changed ID") end assert(validateApiSubscribe(body)) - self.messageCursor = body.messageCursor + self.__messageCursor = body.messageCursor return body.messages end) diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 62150174..246b60cd 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -4,15 +4,20 @@ local Plugin = Rojo.Plugin local Roact = require(Rojo.Roact) local Log = require(Rojo.Log) +local ApiContext = require(Plugin.ApiContext) local Assets = require(Plugin.Assets) local Config = require(Plugin.Config) local DevSettings = require(Plugin.DevSettings) -local Session = require(Plugin.Session) +local Reconciler = require(Plugin.Reconciler) +local ServeSession = require(Plugin.ServeSession) local Version = require(Plugin.Version) local preloadAssets = require(Plugin.preloadAssets) +local strict = require(Plugin.strict) local ConnectPanel = require(Plugin.Components.ConnectPanel) +local ConnectingPanel = require(Plugin.Components.ConnectingPanel) local ConnectionActivePanel = require(Plugin.Components.ConnectionActivePanel) +local ErrorPanel = require(Plugin.Components.ErrorPanel) local e = Roact.createElement @@ -52,26 +57,23 @@ local function checkUpgrade(plugin) plugin:SetSetting("LastRojoVersion", Config.version) end -local SessionStatus = { - Disconnected = "Disconnected", +local AppStatus = strict("AppStatus", { + NotStarted = "NotStarted", + Connecting = "Connecting", Connected = "Connected", -} - -setmetatable(SessionStatus, { - __index = function(_, key) - error(("%q is not a valid member of SessionStatus"):format(tostring(key)), 2) - end, + Error = "Error", }) local App = Roact.Component:extend("App") function App:init() self:setState({ - sessionStatus = SessionStatus.Disconnected, + appStatus = AppStatus.NotStarted, + errorMessage = nil, }) self.signals = {} - self.currentSession = nil + self.serveSession = nil self.displayedVersion = DevSettings:isEnabled() and Config.codename @@ -96,7 +98,7 @@ function App:init() 360, 190 -- Minimum size ) - self.dockWidget = self.props.plugin:CreateDockWidgetPluginGui("Rojo-0.5.x", widgetInfo) + self.dockWidget = self.props.plugin:CreateDockWidgetPluginGui("Rojo-" .. self.displayedVersion, widgetInfo) self.dockWidget.Name = "Rojo " .. self.displayedVersion self.dockWidget.Title = "Rojo " .. self.displayedVersion self.dockWidget.AutoLocalize = false @@ -107,56 +109,92 @@ function App:init() end) end +function App:startSession(address, port) + Log.trace("Starting new session") + + local baseUrl = ("http://%s:%s"):format(address, port) + self.serveSession = ServeSession.new({ + apiContext = ApiContext.new(baseUrl), + reconciler = Reconciler.new(), + }) + + self.serveSession:onStatusChanged(function(status, details) + if status == ServeSession.Status.Connecting then + self:setState({ + appStatus = AppStatus.Connecting, + }) + elseif status == ServeSession.Status.Connected then + self:setState({ + appStatus = AppStatus.Connected, + }) + elseif status == ServeSession.Status.Disconnected then + self.serveSession = nil + + -- Details being present indicates that this + -- disconnection was from an error. + if details ~= nil then + Log.warn(tostring(details)) + + self:setState({ + appStatus = AppStatus.Error, + errorMessage = tostring(details), + }) + else + self:setState({ + appStatus = AppStatus.NotStarted, + }) + end + end + end) + + self.serveSession:start() +end + function App:render() local children - if self.state.sessionStatus == SessionStatus.Connected then + if self.state.appStatus == AppStatus.NotStarted then + children = { + ConnectPanel = e(ConnectPanel, { + startSession = function(address, port) + self:startSession(address, port) + end, + cancel = function() + Log.trace("Canceling session configuration") + + self:setState({ + appStatus = AppStatus.NotStarted, + }) + end, + }), + } + elseif self.state.appStatus == AppStatus.Connecting then + children = { + ConnectingPanel = Roact.createElement(ConnectingPanel), + } + elseif self.state.appStatus == AppStatus.Connected then children = { ConnectionActivePanel = e(ConnectionActivePanel, { stopSession = function() Log.trace("Disconnecting session") - self.currentSession:disconnect() - self.currentSession = nil + self.serveSession:stop() + self.serveSession = nil self:setState({ - sessionStatus = SessionStatus.Disconnected, + appStatus = AppStatus.NotStarted, }) Log.trace("Session terminated by user") end, }), } - elseif self.state.sessionStatus == SessionStatus.Disconnected then + elseif self.state.appStatus == AppStatus.Error then children = { - ConnectPanel = e(ConnectPanel, { - startSession = function(address, port) - Log.trace("Starting new session") - - local success, session = Session.new({ - address = address, - port = port, - onError = function(message) - Log.warn("Rojo session terminated because of an error:\n%s", tostring(message)) - self.currentSession = nil - - self:setState({ - sessionStatus = SessionStatus.Disconnected, - }) - end - }) - - if success then - self.currentSession = session - self:setState({ - sessionStatus = SessionStatus.Connected, - }) - end - end, - cancel = function() - Log.trace("Canceling session configuration") - + ErrorPanel = Roact.createElement(ErrorPanel, { + errorMessage = self.state.errorMessage, + onDismiss = function() self:setState({ - sessionStatus = SessionStatus.Disconnected, + appStatus = AppStatus.NotStarted, }) end, }), @@ -176,9 +214,9 @@ function App:didMount() end function App:willUnmount() - if self.currentSession ~= nil then - self.currentSession:disconnect() - self.currentSession = nil + if self.serveSession ~= nil then + self.serveSession:stop() + self.serveSession = nil end for _, signal in pairs(self.signals) do diff --git a/plugin/src/Components/ConnectingPanel.lua b/plugin/src/Components/ConnectingPanel.lua new file mode 100644 index 00000000..c28d6880 --- /dev/null +++ b/plugin/src/Components/ConnectingPanel.lua @@ -0,0 +1,34 @@ +local Roact = require(script:FindFirstAncestor("Rojo").Roact) + +local Plugin = script:FindFirstAncestor("Plugin") + +local Theme = require(Plugin.Theme) + +local Panel = require(Plugin.Components.Panel) +local FitText = require(Plugin.Components.FitText) + +local e = Roact.createElement + +local ConnectingPanel = Roact.Component:extend("ConnectingPanel") + +function ConnectingPanel:render() + return e(Panel, nil, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 8), + }), + + Text = e(FitText, { + Padding = Vector2.new(12, 6), + Font = Theme.ButtonFont, + TextSize = 18, + Text = "Connecting...", + TextColor3 = Theme.PrimaryColor, + BackgroundTransparency = 1, + }), + }) +end + +return ConnectingPanel \ No newline at end of file diff --git a/plugin/src/Components/ErrorPanel.lua b/plugin/src/Components/ErrorPanel.lua new file mode 100644 index 00000000..469b5390 --- /dev/null +++ b/plugin/src/Components/ErrorPanel.lua @@ -0,0 +1,51 @@ +local Roact = require(script:FindFirstAncestor("Rojo").Roact) + +local Plugin = script:FindFirstAncestor("Plugin") + +local Theme = require(Plugin.Theme) + +local Panel = require(Plugin.Components.Panel) +local FitText = require(Plugin.Components.FitText) +local FormButton = require(Plugin.Components.FormButton) + +local e = Roact.createElement + +local ErrorPanel = Roact.Component:extend("ErrorPanel") + +function ErrorPanel:render() + local errorMessage = self.props.errorMessage + local onDismiss = self.props.onDismiss + + return e(Panel, nil, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 8), + }), + + Text = e(FitText, { + LayoutOrder = 1, + FitAxis = "Y", + Size = UDim2.new(1, 0, 0, 0), + Padding = Vector2.new(12, 6), + Font = Theme.ButtonFont, + TextSize = 18, + Text = errorMessage, + TextWrap = true, + TextColor3 = Theme.PrimaryColor, + BackgroundTransparency = 1, + }), + + DismissButton = e(FormButton, { + layoutOrder = 2, + text = "Dismiss", + secondary = true, + onClick = function() + onDismiss() + end, + }), + }) +end + +return ErrorPanel \ No newline at end of file diff --git a/plugin/src/Components/FitText.lua b/plugin/src/Components/FitText.lua index 2f9e6bc6..1c036ba9 100644 --- a/plugin/src/Components/FitText.lua +++ b/plugin/src/Components/FitText.lua @@ -9,6 +9,7 @@ local e = Roact.createElement local FitText = Roact.Component:extend("FitText") function FitText:init() + self.ref = Roact.createRef() self.sizeBinding, self.setSize = Roact.createBinding(UDim2.new()) end @@ -16,10 +17,15 @@ function FitText:render() local kind = self.props.Kind or "TextLabel" local containerProps = Dictionary.merge(self.props, { + FitAxis = Dictionary.None, Kind = Dictionary.None, Padding = Dictionary.None, MinSize = Dictionary.None, - Size = self.sizeBinding + Size = self.sizeBinding, + [Roact.Ref] = self.ref, + [Roact.Change.AbsoluteSize] = function() + self:updateTextMeasurements() + end }) return e(kind, containerProps) @@ -36,15 +42,45 @@ end function FitText:updateTextMeasurements() local minSize = self.props.MinSize or Vector2.new(0, 0) local padding = self.props.Padding or Vector2.new(0, 0) + local fitAxis = self.props.FitAxis or "XY" + local baseSize = self.props.Size local text = self.props.Text or "" local font = self.props.Font or Enum.Font.Legacy local textSize = self.props.TextSize or 12 - local measuredText = TextService:GetTextSize(text, textSize, font, Vector2.new(9e6, 9e6)) - local totalSize = UDim2.new( - 0, math.max(minSize.X, padding.X * 2 + measuredText.X), - 0, math.max(minSize.Y, padding.Y * 2 + measuredText.Y)) + local containerSize = self.ref.current.AbsoluteSize + + local textBounds + + if fitAxis == "XY" then + textBounds = Vector2.new(9e6, 9e6) + elseif fitAxis == "X" then + textBounds = Vector2.new(9e6, containerSize.Y - padding.Y * 2) + elseif fitAxis == "Y" then + textBounds = Vector2.new(containerSize.X - padding.X * 2, 9e6) + end + + local measuredText = TextService:GetTextSize(text, textSize, font, textBounds) + + local computedX = math.max(minSize.X, padding.X * 2 + measuredText.X) + local computedY = math.max(minSize.Y, padding.Y * 2 + measuredText.Y) + + local totalSize + + if fitAxis == "XY" then + totalSize = UDim2.new( + 0, computedX, + 0, computedY) + elseif fitAxis == "X" then + totalSize = UDim2.new( + 0, computedX, + baseSize.Y.Scale, baseSize.Y.Offset) + elseif fitAxis == "Y" then + totalSize = UDim2.new( + baseSize.X.Scale, baseSize.X.Offset, + 0, computedY) + end self.setSize(totalSize) end diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 4a2d0884..09cfcc25 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -1,239 +1,253 @@ +--[[ + This module defines the meat of the Rojo plugin and how it manages tracking + and mutating the Roblox DOM. +]] + +local RbxDom = require(script.Parent.Parent.RbxDom) local t = require(script.Parent.Parent.t) -local Log = require(script.Parent.Parent.Log) local InstanceMap = require(script.Parent.InstanceMap) -local setCanonicalProperty = require(script.Parent.setCanonicalProperty) -local rojoValueToRobloxValue = require(script.Parent.rojoValueToRobloxValue) local Types = require(script.Parent.Types) +local setCanonicalProperty = require(script.Parent.setCanonicalProperty) -local function setParent(instance, newParent) +--[[ + This interface represents either a patch created by the hydrate method, or a + patch returned from the API. + + This type should be a subset of Types.ApiInstanceUpdate. +]] +local IPatch = t.interface({ + removed = t.array(t.union(Types.RbxId, t.Instance)), + added = t.map(Types.RbxId, Types.ApiInstance), + updated = t.array(Types.ApiInstanceUpdate), +}) + +--[[ + Attempt to safely set the parent of an instance. + + This function will always succeed, even if the actual set failed. This is + important for some types like services that will throw even if their current + parent is already set to the requested parent. + + TODO: See if we can eliminate this by being more nuanced with property + assignment? +]] +local function safeSetParent(instance, newParent) pcall(function() instance.Parent = newParent end) end +--[[ + Similar to setting Parent, some instances really don't like being renamed. + + TODO: Should we be throwing away these results or can we be more careful? +]] +local function safeSetName(instance, name) + pcall(function() + instance.Name = name + end) +end + local Reconciler = {} Reconciler.__index = Reconciler function Reconciler.new() local self = { - instanceMap = InstanceMap.new(), + -- Tracks all of the instances known by the reconciler by ID. + __instanceMap = InstanceMap.new(), } return setmetatable(self, Reconciler) end -function Reconciler:applyUpdate(requestedIds, virtualInstancesById) - -- This function may eventually be asynchronous; it will require calls to - -- the server to resolve instances that don't exist yet. - local visitedIds = {} +--[[ + See Reconciler:__hydrateInternal(). +]] +function Reconciler:hydrate(apiInstances, id, instance) + local hydratePatch = { + removed = {}, + added = {}, + updated = {}, + } - for _, id in ipairs(requestedIds) do - self:__applyUpdatePiece(id, visitedIds, virtualInstancesById) - end + self:__hydrateInternal(apiInstances, id, instance, hydratePatch) + + return hydratePatch end -local reconcileSchema = Types.ifEnabled(t.tuple( - t.map(t.string, Types.VirtualInstance), - t.string, +--[[ + Transforms a value encoded by rbx_dom_weak on the server side into a value + usable by Rojo's reconciler, potentially using RbxDom. +]] +function Reconciler:__decodeApiValue(apiValue) + assert(Types.ApiValue(apiValue)) + + -- Refs are represented as IDs in the same space that Rojo's protocol uses. + if apiValue.Type == "Ref" then + -- TODO: This ref could be pointing at an instance we haven't created + -- yet! + + return self.__instanceMap.fromIds[apiValue.Value] + end + + local success, decodedValue = RbxDom.EncodedValue.decode(apiValue) + + if not success then + error(decodedValue, 2) + end + + return decodedValue +end + +--[[ + Constructs an instance from an ApiInstance without any of its children. +]] +local reifySingleInstanceSchema = Types.ifEnabled(t.tuple( + Types.ApiInstance +)) +function Reconciler:__reifySingleInstance(apiInstance) + assert(reifySingleInstanceSchema(apiInstance)) + + -- Instance.new can fail if we're passing in something that can't be + -- created, like a service, something enabled with a feature flag, or + -- something that requires higher security than we have. + local ok, instance = pcall(Instance.new, apiInstance.ClassName) + if not ok then + return false, instance + end + + -- TODO: When can setting Name fail here? + safeSetName(instance, apiInstance.Name) + + for key, value in pairs(apiInstance.Properties) do + setCanonicalProperty(instance, key, self:__decodeApiValue(value)) + end + + return instance +end + +--[[ + Construct an instance and all of its descendants, parent it to the given + instance, and insert it into the reconciler's internal state. +]] +local reifyInstanceSchema = Types.ifEnabled(t.tuple( + t.map(Types.RbxId, Types.VirtualInstance), + Types.RbxId, t.Instance )) +function Reconciler:__reifyInstance(apiInstances, id, parentInstance) + assert(reifyInstanceSchema(apiInstances, id, parentInstance)) + + local apiInstance = apiInstances[id] + local ok, instance = self:__reifySingleInstance(apiInstance) + + -- TODO: Propagate this error upward to handle it elsewhere? + if not ok then + error(("Couldn't create an instance of type %q, a child of %s"):format( + apiInstance.ClassName, + parentInstance:GetFullName() + )) + end + + for _, childId in ipairs(apiInstance.Children) do + self:__reify(apiInstances, childId, instance) + end + + safeSetParent(instance, parentInstance) + self.__instanceMap:insert(id, instance) + + return instance +end + --[[ - Update an existing instance, including its properties and children, to match - the given information. + Populates the reconciler's internal state, maps IDs to instances that the + Rojo plugin knows about, and generates a patch that would update the Roblox + tree to match Rojo's view of the tree. ]] -function Reconciler:reconcile(virtualInstancesById, id, instance) - assert(reconcileSchema(virtualInstancesById, id, instance)) +local hydrateSchema = Types.ifEnabled(t.tuple( + t.map(Types.RbxId, Types.VirtualInstance), + Types.RbxId, + t.Instance, + IPatch +)) +function Reconciler:__hydrateInternal(apiInstances, id, instance, hydratePatch) + assert(hydrateSchema(apiInstances, id, instance, hydratePatch)) - local virtualInstance = virtualInstancesById[id] + local apiInstance = apiInstances[id] - -- If an instance changes ClassName, we assume it's very different. That's - -- not always the case! - if virtualInstance.ClassName ~= instance.ClassName then - Log.trace("Switching to reify for %s because ClassName is different", instance:GetFullName()) + local function markIdAdded(id) + local apiInstance = apiInstances[id] + hydratePatch.added[id] = apiInstance - -- TODO: Preserve existing children instead? - local parent = instance.Parent - self.instanceMap:destroyId(id) - return self:__reify(virtualInstancesById, id, parent) + for _, childId in ipairs(apiInstance.Children) do + markIdAdded(childId) + end end - self.instanceMap:insert(id, instance) - - -- Some instances don't like being named, even if their name already matches - setCanonicalProperty(instance, "Name", virtualInstance.Name) - - for key, value in pairs(virtualInstance.Properties) do - setCanonicalProperty(instance, key, rojoValueToRobloxValue(value)) - end + -- TODO: Measure differences in properties and add them to + -- hydratePatch.updates local existingChildren = instance:GetChildren() - local unvisitedExistingChildren = {} - for _, child in ipairs(existingChildren) do - unvisitedExistingChildren[child] = true + -- For each existing child, we'll track whether it's been paired with an + -- instance that the Rojo server knows about. + local isExistingChildVisited = {} + for i = 1, #existingChildren do + isExistingChildVisited[i] = false end - for _, childId in ipairs(virtualInstance.Children) do - local childData = virtualInstancesById[childId] + for _, childId in ipairs(apiInstance.Children) do + local apiChild = apiInstances[childId] - local existingChildInstance - for instance in pairs(unvisitedExistingChildren) do - local ok, name, className = pcall(function() - return instance.Name, instance.ClassName - end) + local childInstance - if ok then - if name == childData.Name and className == childData.ClassName then - existingChildInstance = instance + for childIndex, instance in ipairs(existingChildren) do + if not isExistingChildVisited[childIndex] then + -- We guard accessing Name and ClassName in order to avoid + -- tripping over children of DataModel that Rojo won't have + -- permissions to access at all. + local ok, name, className = pcall(function() + return instance.Name, instance.ClassName + end) + + -- This rule is very conservative and could be loosened in the + -- future, or more heuristics could be introduced. + if ok and name == apiChild.Name and className == apiChild.ClassName then + childInstance = instance + isExistingChildVisited[childIndex] = true break end end end - if existingChildInstance ~= nil then - unvisitedExistingChildren[existingChildInstance] = nil - self:reconcile(virtualInstancesById, childId, existingChildInstance) + if childInstance ~= nil then + -- We found an instance that matches the instance from the API, yay! + self:__hydrateInternal(apiInstances, childId, childInstance, hydratePatch) else - Log.trace( - "Switching to reify for %s.%s because it does not exist", - instance:GetFullName(), - virtualInstancesById[childId].Name - ) - - self:__reify(virtualInstancesById, childId, instance) + markIdAdded(childId) end end - local shouldClearUnknown = self:__shouldClearUnknownChildren(virtualInstance) - - for existingChildInstance in pairs(unvisitedExistingChildren) do - local childId = self.instanceMap.fromInstances[existingChildInstance] - - if childId == nil then - if shouldClearUnknown then - existingChildInstance:Destroy() + -- Any unvisited children at this point aren't known by Rojo and we can + -- destroy them unless the user has explicitly asked us to preserve children + -- of this instance. + local shouldClearUnknown = self:__shouldClearUnknownChildren(apiInstance) + if shouldClearUnknown then + for childIndex, visited in ipairs(isExistingChildVisited) do + if not visited then + table.insert(hydratePatch.removedInstances, existingChildren[childIndex]) end - else - self.instanceMap:destroyInstance(existingChildInstance) end end - - -- The root instance of a project won't have a parent, like the DataModel, - -- so we need to be careful here. - if virtualInstance.Parent ~= nil then - local parent = self.instanceMap.fromIds[virtualInstance.Parent] - - if parent == nil then - Log.info("Instance %s wanted parent of %s", tostring(id), tostring(virtualInstance.Parent)) - error("Rojo bug: During reconciliation, an instance referred to an instance ID as parent that does not exist.") - end - - -- Some instances, like services, don't like having their Parent - -- property poked, even if we're setting it to the same value. - setParent(instance, parent) - end - - return instance end -function Reconciler:__shouldClearUnknownChildren(virtualInstance) - if virtualInstance.Metadata ~= nil then - return not virtualInstance.Metadata.ignoreUnknownInstances +function Reconciler:__shouldClearUnknownChildren(apiInstance) + if apiInstance.Metadata ~= nil then + return not apiInstance.Metadata.ignoreUnknownInstances else return true end end -local reifySchema = Types.ifEnabled(t.tuple( - t.map(t.string, Types.VirtualInstance), - t.string, - t.Instance -)) - -function Reconciler:__reify(virtualInstancesById, id, parent) - assert(reifySchema(virtualInstancesById, id, parent)) - - local virtualInstance = virtualInstancesById[id] - - local ok, instance = pcall(function() - return Instance.new(virtualInstance.ClassName) - end) - - if not ok then - error(("Couldn't create an Instance of type %q, a child of %s"):format( - virtualInstance.ClassName, - parent:GetFullName() - )) - end - - for key, value in pairs(virtualInstance.Properties) do - setCanonicalProperty(instance, key, rojoValueToRobloxValue(value)) - end - - setCanonicalProperty(instance, "Name", virtualInstance.Name) - - for _, childId in ipairs(virtualInstance.Children) do - self:__reify(virtualInstancesById, childId, instance) - end - - setParent(instance, parent) - self.instanceMap:insert(id, instance) - - return instance -end - -local applyUpdatePieceSchema = Types.ifEnabled(t.tuple( - t.string, - t.map(t.string, t.boolean), - t.map(t.string, Types.VirtualInstance) -)) - -function Reconciler:__applyUpdatePiece(id, visitedIds, virtualInstancesById) - assert(applyUpdatePieceSchema(id, visitedIds, virtualInstancesById)) - - if visitedIds[id] then - return - end - - visitedIds[id] = true - - local virtualInstance = virtualInstancesById[id] - local instance = self.instanceMap.fromIds[id] - - -- The instance was deleted in this update - if virtualInstance == nil then - self.instanceMap:destroyId(id) - return - end - - -- An instance we know about was updated - if instance ~= nil then - self:reconcile(virtualInstancesById, id, instance) - return instance - end - - -- If the instance's parent already exists, we can stick it there - local parentInstance = self.instanceMap.fromIds[virtualInstance.Parent] - if parentInstance ~= nil then - self:__reify(virtualInstancesById, id, parentInstance) - return - end - - -- Otherwise, we can check if this response payload contained the parent and - -- work from there instead. - local parentData = virtualInstancesById[virtualInstance.Parent] - if parentData ~= nil then - if visitedIds[virtualInstance.Parent] then - error("Rojo bug: An instance was present and marked as visited but its instance was missing") - end - - self:__applyUpdatePiece(virtualInstance.Parent, visitedIds, virtualInstancesById) - return - end - - Log.trace("Instance ID %s, parent ID %s", tostring(id), tostring(virtualInstance.Parent)) - error("Rojo NYI: Instances with parents that weren't mentioned in an update payload") -end - return Reconciler \ No newline at end of file diff --git a/plugin/src/Reconciler.spec.lua b/plugin/src/Reconciler.spec.lua deleted file mode 100644 index 794c4d08..00000000 --- a/plugin/src/Reconciler.spec.lua +++ /dev/null @@ -1,218 +0,0 @@ -local Reconciler = require(script.Parent.Reconciler) - -return function() - it("should leave instances alone if there's nothing specified", function() - local instance = Instance.new("Folder") - instance.Name = "TestFolder" - - local instanceId = "test-id" - local virtualInstancesById = { - [instanceId] = { - Name = "TestFolder", - ClassName = "Folder", - Children = {}, - Properties = {}, - }, - } - - local reconciler = Reconciler.new() - reconciler:reconcile(virtualInstancesById, instanceId, instance) - end) - - it("should assign names from virtual instances", function() - local instance = Instance.new("Folder") - instance.Name = "InitialName" - - local instanceId = "test-id" - local virtualInstancesById = { - [instanceId] = { - Name = "NewName", - ClassName = "Folder", - Children = {}, - Properties = {}, - }, - } - - local reconciler = Reconciler.new() - reconciler:reconcile(virtualInstancesById, instanceId, instance) - - expect(instance.Name).to.equal("NewName") - end) - - it("should assign properties from virtual instances", function() - local instance = Instance.new("IntValue") - instance.Name = "TestValue" - instance.Value = 5 - - local instanceId = "test-id" - local virtualInstancesById = { - [instanceId] = { - Name = "TestValue", - ClassName = "IntValue", - Children = {}, - Properties = { - Value = { - Type = "Int32", - Value = 9 - } - }, - }, - } - - local reconciler = Reconciler.new() - reconciler:reconcile(virtualInstancesById, instanceId, instance) - - expect(instance.Value).to.equal(9) - end) - - it("should wipe unknown children by default", function() - local parent = Instance.new("Folder") - parent.Name = "Parent" - - local child = Instance.new("Folder") - child.Name = "Child" - - local parentId = "test-id" - local virtualInstancesById = { - [parentId] = { - Name = "Parent", - ClassName = "Folder", - Children = {}, - Properties = {}, - }, - } - - local reconciler = Reconciler.new() - reconciler:reconcile(virtualInstancesById, parentId, parent) - - expect(#parent:GetChildren()).to.equal(0) - end) - - it("should preserve unknown children if ignoreUnknownInstances is set", function() - local parent = Instance.new("Folder") - parent.Name = "Parent" - - local child = Instance.new("Folder") - child.Parent = parent - child.Name = "Child" - - local parentId = "test-id" - local virtualInstancesById = { - [parentId] = { - Name = "Parent", - ClassName = "Folder", - Children = {}, - Properties = {}, - Metadata = { - ignoreUnknownInstances = true, - }, - }, - } - - local reconciler = Reconciler.new() - reconciler:reconcile(virtualInstancesById, parentId, parent) - - expect(child.Parent).to.equal(parent) - expect(#parent:GetChildren()).to.equal(1) - end) - - it("should remove known removed children", function() - local parent = Instance.new("Folder") - parent.Name = "Parent" - - local child = Instance.new("Folder") - child.Parent = parent - child.Name = "Child" - - local parentId = "parent-id" - local childId = "child-id" - - local reconciler = Reconciler.new() - - local virtualInstancesById = { - [parentId] = { - Name = "Parent", - ClassName = "Folder", - Children = {childId}, - Properties = {}, - }, - [childId] = { - Name = "Child", - ClassName = "Folder", - Children = {}, - Properties = {}, - }, - } - reconciler:reconcile(virtualInstancesById, parentId, parent) - - expect(child.Parent).to.equal(parent) - expect(#parent:GetChildren()).to.equal(1) - - local newVirtualInstances = { - [parentId] = { - Name = "Parent", - ClassName = "Folder", - Children = {}, - Properties = {}, - }, - [childId] = nil, - } - reconciler:reconcile(newVirtualInstances, parentId, parent) - - expect(child.Parent).to.equal(nil) - expect(#parent:GetChildren()).to.equal(0) - end) - - it("should remove known removed children if ignoreUnknownInstances is set", function() - local parent = Instance.new("Folder") - parent.Name = "Parent" - - local child = Instance.new("Folder") - child.Parent = parent - child.Name = "Child" - - local parentId = "parent-id" - local childId = "child-id" - - local reconciler = Reconciler.new() - - local virtualInstancesById = { - [parentId] = { - Name = "Parent", - ClassName = "Folder", - Children = {childId}, - Properties = {}, - Metadata = { - ignoreUnknownInstances = true, - }, - }, - [childId] = { - Name = "Child", - ClassName = "Folder", - Children = {}, - Properties = {}, - }, - } - reconciler:reconcile(virtualInstancesById, parentId, parent) - - expect(child.Parent).to.equal(parent) - expect(#parent:GetChildren()).to.equal(1) - - local newVirtualInstances = { - [parentId] = { - Name = "Parent", - ClassName = "Folder", - Children = {}, - Properties = {}, - Metadata = { - ignoreUnknownInstances = true, - }, - }, - [childId] = nil, - } - reconciler:reconcile(newVirtualInstances, parentId, parent) - - expect(child.Parent).to.equal(nil) - expect(#parent:GetChildren()).to.equal(0) - end) -end \ No newline at end of file diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua new file mode 100644 index 00000000..969dd643 --- /dev/null +++ b/plugin/src/ServeSession.lua @@ -0,0 +1,99 @@ +local t = require(script.Parent.Parent.t) + +local strict = require(script.Parent.strict) + +local Status = strict("Session.Status", { + NotStarted = "NotStarted", + Connecting = "Connecting", + Connected = "Connected", + Disconnected = "Disconnected", +}) + +local function DEBUG_printPatch(patch) + local HttpService = game:GetService("HttpService") + + + for removed in ipairs(patch.removed) do + print("Remove:", removed) + end + + for id, added in pairs(patch.added) do + print("Add:", id, HttpService:JSONEncode(added)) + end + + for updated in ipairs(patch.updated) do + print("Update:", HttpService:JSONEncode(updated)) + end +end + +local ServeSession = {} +ServeSession.__index = ServeSession + +ServeSession.Status = Status + +local validateServeOptions = t.strictInterface({ + apiContext = t.table, + reconciler = t.table, +}) + +function ServeSession.new(options) + assert(validateServeOptions(options)) + + local self = { + __status = Status.NotStarted, + __apiContext = options.apiContext, + __reconciler = options.reconciler, + __statusChangedCallback = nil, + } + + setmetatable(self, ServeSession) + + return self +end + +function ServeSession:onStatusChanged(callback) + self.__statusChangedCallback = callback +end + +function ServeSession:start() + self:__setStatus(Status.Connecting) + + self.__apiContext:connect() + :andThen(function(serverInfo) + self:__setStatus(Status.Connected) + + local rootInstanceId = serverInfo.rootInstanceId + + return self.__apiContext:read({ rootInstanceId }) + :andThen(function(readResponseBody) + local hydratePatch = self.__reconciler:hydrate( + readResponseBody.instances, + rootInstanceId, + game + ) + + DEBUG_printPatch(hydratePatch) + + -- TODO: Apply the patch generated by hydration. We should + -- eventually prompt the user about this since it's a + -- conflict between Rojo and their current place state. + end) + end) + :catch(function(err) + self:__setStatus(Status.Disconnected, err) + end) +end + +function ServeSession:stop() + self:__setStatus(Status.Disconnected) +end + +function ServeSession:__setStatus(status, detail) + self.__status = status + + if self.__statusChangedCallback ~= nil then + self.__statusChangedCallback(status, detail) + end +end + +return ServeSession \ No newline at end of file diff --git a/plugin/src/Session.lua b/plugin/src/Session.lua deleted file mode 100644 index ef37f16c..00000000 --- a/plugin/src/Session.lua +++ /dev/null @@ -1,95 +0,0 @@ -local Promise = require(script.Parent.Parent.Promise) - -local ApiContext = require(script.Parent.ApiContext) -local Reconciler = require(script.Parent.Reconciler) - -local Session = {} -Session.__index = Session - -function Session.new(config) - local baseUrl = ("http://%s:%s"):format(config.address, config.port) - local apiContext = ApiContext.new(baseUrl) - - local self = { - onError = config.onError, - disconnected = false, - reconciler = Reconciler.new(), - apiContext = apiContext, - } - - apiContext:connect() - :andThen(function() - if self.disconnected then - return - end - - return apiContext:read({apiContext.rootInstanceId}) - end) - :andThen(function(response) - if self.disconnected then - return - end - - self.reconciler:reconcile(response.instances, apiContext.rootInstanceId, game) - return self:__processMessages() - end) - :catch(function(message) - self.disconnected = true - self.onError(message) - end) - - return not self.disconnected, setmetatable(self, Session) -end - -function Session:__processMessages() - if self.disconnected then - return Promise.resolve() - end - - return self.apiContext:retrieveMessages() - :andThen(function(messages) - local promise = Promise.resolve(nil) - - for _, message in ipairs(messages) do - promise = promise:andThen(function() - return self:__onMessage(message) - end) - end - - return promise - end) - :andThen(function() - return self:__processMessages() - end) -end - -function Session:__onMessage(message) - if self.disconnected then - return Promise.resolve() - end - - local requestedIds = {} - - for _, id in ipairs(message.added) do - table.insert(requestedIds, id) - end - - for _, id in ipairs(message.updated) do - table.insert(requestedIds, id) - end - - for _, id in ipairs(message.removed) do - table.insert(requestedIds, id) - end - - return self.apiContext:read(requestedIds) - :andThen(function(response) - return self.reconciler:applyUpdate(requestedIds, response.instances) - end) -end - -function Session:disconnect() - self.disconnected = true -end - -return Session \ No newline at end of file diff --git a/plugin/src/Types.lua b/plugin/src/Types.lua index 3d866a1a..047f4c08 100644 --- a/plugin/src/Types.lua +++ b/plugin/src/Types.lua @@ -84,6 +84,7 @@ return strict("Types", { ApiError = ApiError, ApiInstance = ApiInstance, + ApiInstanceUpdate = ApiInstanceUpdate, ApiInstanceMetadata = ApiInstanceMetadata, ApiSubscribeMessage = ApiSubscribeMessage, ApiValue = ApiValue, diff --git a/plugin/src/rojoValueToRobloxValue.lua b/plugin/src/rojoValueToRobloxValue.lua deleted file mode 100644 index 1e30dfde..00000000 --- a/plugin/src/rojoValueToRobloxValue.lua +++ /dev/null @@ -1,19 +0,0 @@ -local RbxDom = require(script:FindFirstAncestor("Rojo").RbxDom) - -local function rojoValueToRobloxValue(value) - -- TODO: Manually decode this value by looking up its GUID The Rojo server - -- doesn't give us valid ref values yet, so this isn't important yet. - if value.Type == "Ref" then - return nil - end - - local success, decodedValue = RbxDom.EncodedValue.decode(value) - - if not success then - error(decodedValue, 2) - end - - return decodedValue -end - -return rojoValueToRobloxValue \ No newline at end of file diff --git a/plugin/src/rojoValueToRobloxValue.spec.lua b/plugin/src/rojoValueToRobloxValue.spec.lua deleted file mode 100644 index fe7cbaec..00000000 --- a/plugin/src/rojoValueToRobloxValue.spec.lua +++ /dev/null @@ -1,40 +0,0 @@ -local rojoValueToRobloxValue = require(script.Parent.rojoValueToRobloxValue) - -return function() - it("should convert primitives", function() - local inputString = { - Type = "String", - Value = "Hello, world!", - } - - local inputFloat32 = { - Type = "Float32", - Value = 12341.512, - } - - expect(rojoValueToRobloxValue(inputString)).to.equal(inputString.Value) - expect(rojoValueToRobloxValue(inputFloat32)).to.equal(inputFloat32.Value) - end) - - it("should convert properties with direct constructors", function() - local inputColor3 = { - Type = "Color3", - Value = {0, 1, 0.5}, - } - local outputColor3 = Color3.new(0, 1, 0.5) - - local inputCFrame = { - Type = "CFrame", - Value = { - 1, 2, 3, - 4, 5, 6, - 7, 8, 9, - 10, 11, 12, - }, - } - local outputCFrame = CFrame.new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12) - - expect(rojoValueToRobloxValue(inputColor3)).to.equal(outputColor3) - expect(rojoValueToRobloxValue(inputCFrame)).to.equal(outputCFrame) - end) -end \ No newline at end of file From f0eb9556284ae7d6f18f344c4ffdbee9a644f650 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 15:53:50 -0700 Subject: [PATCH 0761/1504] Expose parent from RojoTree instances --- src/snapshot/tree.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index 0126f5ee..bc29dbaa 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -224,6 +224,10 @@ impl<'a> InstanceWithMeta<'a> { self.instance.get_id() } + pub fn parent(&self) -> Option { + self.instance.get_parent_id() + } + pub fn name(&self) -> &'a str { &self.instance.name } From 995685adfe44b1d57ea77a81acbbe441aef839d7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 15:54:11 -0700 Subject: [PATCH 0762/1504] Expose instance ID and parent ID in web API --- rojo-test/serve-test-snapshots/serve_test__empty-2.snap | 2 ++ src/web/interface.rs | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/rojo-test/serve-test-snapshots/serve_test__empty-2.snap b/rojo-test/serve-test-snapshots/serve_test__empty-2.snap index 5ef25f8a..7cd6e0f9 100644 --- a/rojo-test/serve-test-snapshots/serve_test__empty-2.snap +++ b/rojo-test/serve-test-snapshots/serve_test__empty-2.snap @@ -6,6 +6,8 @@ sessionId: id-1 messageCursor: 0 instances: id-2: + Id: id-2 + Parent: ~ Name: empty ClassName: Folder Properties: {} diff --git a/src/web/interface.rs b/src/web/interface.rs index dcfc3bdf..ceab02fd 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -57,6 +57,8 @@ impl InstanceMetadata { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "PascalCase")] pub struct Instance<'a> { + pub id: RbxId, + pub parent: Option, pub name: Cow<'a, str>, pub class_name: Cow<'a, str>, pub properties: Cow<'a, HashMap>, @@ -67,6 +69,8 @@ pub struct Instance<'a> { impl<'a> Instance<'a> { pub(crate) fn from_rojo_instance<'b>(source: InstanceWithMeta<'b>) -> Instance<'b> { Instance { + id: source.id(), + parent: source.parent(), name: Cow::Borrowed(source.name()), class_name: Cow::Borrowed(source.class_name()), properties: Cow::Borrowed(source.properties()), From cf62ee5ccbeda547ff1faea2b685e9fbe5b7a1fe Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 15:54:49 -0700 Subject: [PATCH 0763/1504] plugin: Add Id and ParentId to ApiInstance type definitions --- plugin/src/Types.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/src/Types.lua b/plugin/src/Types.lua index 047f4c08..c3bea3a9 100644 --- a/plugin/src/Types.lua +++ b/plugin/src/Types.lua @@ -15,6 +15,8 @@ local ApiInstanceMetadata = t.interface({ }) local ApiInstance = t.interface({ + Id = RbxId, + ParentId = t.optional(RbxId), Name = t.string, ClassName = t.string, Properties = t.map(t.string, ApiValue), From 1ee679395d96a48c100e31a50eb0719ebff3e42c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 17:12:08 -0700 Subject: [PATCH 0764/1504] Add 'invariant' function for debugging --- plugin/src/invariant.lua | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 plugin/src/invariant.lua diff --git a/plugin/src/invariant.lua b/plugin/src/invariant.lua new file mode 100644 index 00000000..3923095b --- /dev/null +++ b/plugin/src/invariant.lua @@ -0,0 +1,27 @@ +local Config = require(script.Parent.Config) + +local invariant + +if Config.isDevBuild then + function invariant(message, ...) + message = string.format(message, ...) + + error("Invariant violation: " .. message, 2) + end +else + function invariant(message, ...) + message = string.format(message, ...) + + local fullMessage = string.format( + "Rojo detected an invariant violation within itself:\n" .. + "%s\n\n" .. + "This is a bug in Rojo. Please file an issue:\n" .. + "https://github.com/rojo-rbx/rojo/issues", + message + ) + + error(fullMessage, 2) + end +end + +return invariant \ No newline at end of file From b72e6e54e6e5ec0f3915fa37b66b6b529a4306cf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 17:12:43 -0700 Subject: [PATCH 0765/1504] plugin: Add debugging function for InstanceMap state --- plugin/src/InstanceMap.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 8ec3bf54..86b542a1 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -18,6 +18,16 @@ function InstanceMap.new() return setmetatable(self, InstanceMap) end +function InstanceMap:debugState() + local buffer = {} + + for id, instance in pairs(self.fromIds) do + table.insert(buffer, string.format("- %s: %s", id, instance:GetFullName())) + end + + return table.concat(buffer, "\n") +end + function InstanceMap:insert(id, instance) self.fromIds[id] = instance self.fromInstances[instance] = id From 1d441b86d2910491aff68672fd513c329877df42 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 17:13:17 -0700 Subject: [PATCH 0766/1504] plugin: Fix type bindings for instance Parent --- plugin/src/Types.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/Types.lua b/plugin/src/Types.lua index c3bea3a9..ff7d7267 100644 --- a/plugin/src/Types.lua +++ b/plugin/src/Types.lua @@ -16,7 +16,7 @@ local ApiInstanceMetadata = t.interface({ local ApiInstance = t.interface({ Id = RbxId, - ParentId = t.optional(RbxId), + Parent = t.optional(RbxId), Name = t.string, ClassName = t.string, Properties = t.map(t.string, ApiValue), From 6f1469a5516d5a51c5f1a95a35ec072691f23bb1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 17:13:29 -0700 Subject: [PATCH 0767/1504] plugin: Implement patch application, which makes live sync work --- plugin/src/Reconciler.lua | 102 ++++++++++++++++++++++++++++++++++-- plugin/src/ServeSession.lua | 37 +++++++++++-- 2 files changed, 131 insertions(+), 8 deletions(-) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 09cfcc25..96da7de8 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -8,6 +8,7 @@ local t = require(script.Parent.Parent.t) local InstanceMap = require(script.Parent.InstanceMap) local Types = require(script.Parent.Types) +local invariant = require(script.Parent.invariant) local setCanonicalProperty = require(script.Parent.setCanonicalProperty) --[[ @@ -76,6 +77,96 @@ function Reconciler:hydrate(apiInstances, id, instance) return hydratePatch end +--[[ + Applies a patch to the Roblox DOM using the reconciler's internal state. + + TODO: This function might only apply some of the patch in the future and + require content negotiation with the Rojo server to handle types that aren't + editable by scripts. +]] +local applyPatchSchema = Types.ifEnabled(t.tuple( + IPatch +)) +function Reconciler:applyPatch(patch) + assert(applyPatchSchema(patch)) + + for _, removedIdOrInstance in ipairs(patch.removed) do + if Types.RbxId(removedIdOrInstance) then + -- If this value is an ID, it's assumed to be an instance that the + -- Rojo server knows about. + + self.__instanceMap:removeId(removedIdOrInstance) + else + -- Otherwise, this instance is one that the Rojo server doesn't know + -- about, and is located in an area where it should be destroyed to + -- keep our trees in sync. + + removedIdOrInstance:Destroy() + end + end + + -- TODO: This loop assumes that apiInstance.ParentId is never nil. The Rojo + -- plugin can't create a new top-level DataModel anyways, so this should + -- only be violated in cases that are already erroneous. + for id, apiInstance in pairs(patch.added) do + if self.__instanceMap.fromIds[id] == nil then + -- Find the first ancestor of this instance that is marked for an + -- addition. + -- + -- This helps us make sure we only reify each instance once, and we + -- start from the top. + while patch.added[apiInstance.Parent] ~= nil do + id = apiInstance.Parent + apiInstance = patch.added[id] + end + + local parentInstance = self.__instanceMap.fromIds[apiInstance.Parent] + + if parentInstance == nil then + invariant( + "Cannot add an instance from a patch that has no parent.\nInstance %s with parent %s.\nInstanceMap state:\n%s", + id, + tostring(apiInstance.Parent), + self.__instanceMap:debugState() + ) + end + + self:__reifyInstance(patch.added, id, parentInstance) + end + end + + for _, update in ipairs(patch.updated) do + local instance = self.__instanceMap.fromIds[update.id] + + if instance == nil then + invariant( + "Cannot update an instance that does not exist in the reconciler's state.\nInstance ID %s\nInstanceMap state:\n%s", + update.id, + self.__instanceMap:debugState() + ) + end + + if update.changedClassName ~= nil then + error("TODO: Support changing class name by destroying + recreating instance.") + end + + if update.changedName ~= nil then + instance.Name = update.changedName + end + + if update.changedMetadata ~= nil then + print("TODO: Support changing metadata, if necessary.") + end + + if update.changedProperties ~= nil then + for propertyName, propertyValue in pairs(update.changedProperties) do + -- TODO: Gracefully handle this error instead? + assert(setCanonicalProperty(instance, propertyName, self:__decodeApiValue(propertyValue))) + end + end + end +end + --[[ Transforms a value encoded by rbx_dom_weak on the server side into a value usable by Rojo's reconciler, potentially using RbxDom. @@ -124,7 +215,7 @@ function Reconciler:__reifySingleInstance(apiInstance) setCanonicalProperty(instance, key, self:__decodeApiValue(value)) end - return instance + return true, instance end --[[ @@ -150,12 +241,13 @@ function Reconciler:__reifyInstance(apiInstances, id, parentInstance) )) end + self.__instanceMap:insert(id, instance) + for _, childId in ipairs(apiInstance.Children) do - self:__reify(apiInstances, childId, instance) + self:__reifyInstance(apiInstances, childId, instance) end safeSetParent(instance, parentInstance) - self.__instanceMap:insert(id, instance) return instance end @@ -174,6 +266,8 @@ local hydrateSchema = Types.ifEnabled(t.tuple( function Reconciler:__hydrateInternal(apiInstances, id, instance, hydratePatch) assert(hydrateSchema(apiInstances, id, instance, hydratePatch)) + self.__instanceMap:insert(id, instance) + local apiInstance = apiInstances[id] local function markIdAdded(id) @@ -236,7 +330,7 @@ function Reconciler:__hydrateInternal(apiInstances, id, instance, hydratePatch) if shouldClearUnknown then for childIndex, visited in ipairs(isExistingChildVisited) do if not visited then - table.insert(hydratePatch.removedInstances, existingChildren[childIndex]) + table.insert(hydratePatch.removed, existingChildren[childIndex]) end end end diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 969dd643..8b6de64a 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -72,11 +72,40 @@ function ServeSession:start() game ) - DEBUG_printPatch(hydratePatch) + -- TODO: Prompt user to notify them of this patch, since + -- it's effectively a conflict between the Rojo server and + -- the client. - -- TODO: Apply the patch generated by hydration. We should - -- eventually prompt the user about this since it's a - -- conflict between Rojo and their current place state. + self.__reconciler:applyPatch(hydratePatch) + + -- TODO: Applying a patch may eventually only apply part of + -- the patch and start a content negotiation process with + -- the Rojo server. We should handle that! + + local function mainLoop() + return self.__apiContext:retrieveMessages() + :andThen(function(messages) + for _, message in ipairs(messages) do + -- TODO: Update server to return patches in + -- correct format so that we don't have to + -- transform them for the reconciler. + + local asPatch = { + removed = message.removedInstances, + updated = message.updatedInstances, + added = message.addedInstances, + } + + self.__reconciler:applyPatch(asPatch) + end + + if self.__status ~= Status.Disconnected then + return mainLoop() + end + end) + end + + return mainLoop() end) end) :catch(function(err) From b2c515f2e6fa77ead078078863f03e35b88cd181 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 17:28:34 -0700 Subject: [PATCH 0768/1504] plugin: Prevent HTTP timeout cascading after session stop --- plugin/src/ApiContext.lua | 7 ++++++- plugin/src/ServeSession.lua | 9 +++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 31893647..44259c1c 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -82,11 +82,16 @@ function ApiContext.new(baseUrl) __baseUrl = baseUrl, __serverId = nil, __messageCursor = -1, + __connected = true, } return setmetatable(self, ApiContext) end +function ApiContext:disconnect() + self.__connected = false +end + function ApiContext:connect() local url = ("%s/api/rojo"):format(self.__baseUrl) @@ -132,7 +137,7 @@ function ApiContext:retrieveMessages() local function sendRequest() return Http.get(url) :catch(function(err) - if err.type == Http.Error.Kind.Timeout then + if err.type == Http.Error.Kind.Timeout and self.__connected then return sendRequest() end diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 8b6de64a..6033dde4 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -109,12 +109,17 @@ function ServeSession:start() end) end) :catch(function(err) - self:__setStatus(Status.Disconnected, err) + self:__stopInternal(err) end) end function ServeSession:stop() - self:__setStatus(Status.Disconnected) + self:__stopInternal() +end + +function ServeSession:__stopInternal(err) + self:__setStatus(Status.Disconnected, err) + self.__apiContext:disconnect() end function ServeSession:__setStatus(status, detail) From ae0f3b0b02b78d2e802f8690352cc0c2333583f3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 17:34:33 -0700 Subject: [PATCH 0769/1504] Assign contributing paths in simple cases for snapshots --- src/snapshot_middleware/csv.rs | 23 ++++++------------- src/snapshot_middleware/rbxlx.rs | 2 +- src/snapshot_middleware/rbxm.rs | 2 +- src/snapshot_middleware/rbxmx.rs | 2 +- .../snapshots/test__csv_from_imfs.snap | 17 ++++++++++++++ .../snapshots/test__instance_from_imfs.snap | 17 ++++++++++++++ src/snapshot_middleware/txt.rs | 19 ++++++--------- 7 files changed, 51 insertions(+), 31 deletions(-) create mode 100644 src/snapshot_middleware/snapshots/test__csv_from_imfs.snap create mode 100644 src/snapshot_middleware/snapshots/test__instance_from_imfs.snap diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 804a03e5..29a07b59 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -6,7 +6,7 @@ use serde::Serialize; use crate::{ imfs::{Imfs, ImfsEntry, ImfsFetcher}, - snapshot::InstanceSnapshot, + snapshot::{InstanceMetadata, InstanceSnapshot}, }; use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; @@ -39,7 +39,10 @@ impl SnapshotMiddleware for SnapshotCsv { Ok(Some(InstanceSnapshot { snapshot_id: None, - metadata: Default::default(), // TODO + metadata: InstanceMetadata { + contributing_paths: vec![entry.path().to_path_buf()], + ..Default::default() + }, name: Cow::Owned(instance_name), class_name: Cow::Borrowed("LocalizationTable"), properties: hashmap! { @@ -137,6 +140,7 @@ mod test { use super::*; use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; + use insta::assert_yaml_snapshot; #[test] fn csv_from_imfs() { @@ -152,19 +156,6 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, let entry = imfs.get("/foo.csv").unwrap(); let instance_snapshot = SnapshotCsv::from_imfs(&mut imfs, &entry).unwrap().unwrap(); - let expected_contents = - r#"[{"key":"Ack","example":"An exclamation of despair","source":"Ack!","values":{"es":"¡Ay!"}}]"#; - - assert_eq!(instance_snapshot.name, "foo"); - assert_eq!(instance_snapshot.class_name, "LocalizationTable"); - assert_eq!(instance_snapshot.children, Vec::new()); - assert_eq!( - instance_snapshot.properties, - hashmap! { - "Contents".to_owned() => RbxValue::String { - value: expected_contents.to_owned(), - }, - } - ); + assert_yaml_snapshot!(instance_snapshot); } } diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index 66282fc8..9408aa74 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -43,7 +43,7 @@ impl SnapshotMiddleware for SnapshotRbxlx { let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, root_id); snapshot.name = Cow::Owned(instance_name); - // TODO: Assign snapshot.source + snapshot.metadata.contributing_paths = vec![entry.path().to_path_buf()]; Ok(Some(snapshot)) } diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index d14f7279..02e13ad9 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -49,7 +49,7 @@ impl SnapshotMiddleware for SnapshotRbxm { if children.len() == 1 { let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); snapshot.name = Cow::Owned(instance_name); - // TODO: Assign snapshot.source + snapshot.metadata.contributing_paths = vec![entry.path().to_path_buf()]; Ok(Some(snapshot)) } else { diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index fde908bd..fbea42f8 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -45,7 +45,7 @@ impl SnapshotMiddleware for SnapshotRbxmx { if children.len() == 1 { let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); snapshot.name = Cow::Owned(instance_name); - // TODO: Assign snapshot.source + snapshot.metadata.contributing_paths = vec![entry.path().to_path_buf()]; Ok(Some(snapshot)) } else { diff --git a/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap b/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap new file mode 100644 index 00000000..f932eadc --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap @@ -0,0 +1,17 @@ +--- +source: src/snapshot_middleware/csv.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: false + contributing_paths: + - /foo.csv + project_node: ~ +name: foo +class_name: LocalizationTable +properties: + Contents: + Type: String + Value: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" +children: [] diff --git a/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap b/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap new file mode 100644 index 00000000..5d7dca15 --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap @@ -0,0 +1,17 @@ +--- +source: src/snapshot_middleware/txt.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: false + contributing_paths: + - /foo.txt + project_node: ~ +name: foo +class_name: StringValue +properties: + Value: + Type: String + Value: Hello there! +children: [] diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index f35495ae..4f085641 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -5,7 +5,7 @@ use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; use crate::{ imfs::{FileSnapshot, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, - snapshot::InstanceSnapshot, + snapshot::{InstanceMetadata, InstanceSnapshot}, }; use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; @@ -51,7 +51,10 @@ impl SnapshotMiddleware for SnapshotTxt { Ok(Some(InstanceSnapshot { snapshot_id: None, - metadata: Default::default(), // TODO + metadata: InstanceMetadata { + contributing_paths: vec![entry.path().to_path_buf()], + ..Default::default() + }, name: Cow::Owned(instance_name), class_name: Cow::Borrowed("StringValue"), properties, @@ -91,6 +94,7 @@ impl SnapshotMiddleware for SnapshotTxt { mod test { use super::*; + use insta::assert_yaml_snapshot; use maplit::hashmap; use rbx_dom_weak::RbxInstanceProperties; @@ -106,16 +110,7 @@ mod test { let entry = imfs.get("/foo.txt").unwrap(); let instance_snapshot = SnapshotTxt::from_imfs(&mut imfs, &entry).unwrap().unwrap(); - assert_eq!(instance_snapshot.name, "foo"); - assert_eq!(instance_snapshot.class_name, "StringValue"); - assert_eq!( - instance_snapshot.properties, - hashmap! { - "Value".to_owned() => RbxValue::String { - value: "Hello there!".to_owned(), - }, - } - ); + assert_yaml_snapshot!(instance_snapshot); } #[test] From 079fc738ad2ccad8f2c90d2919f509b220beedd4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 18:12:36 -0700 Subject: [PATCH 0770/1504] plugin: Properly handle removals in patches --- plugin/src/Reconciler.lua | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 96da7de8..66762e0d 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -91,17 +91,25 @@ function Reconciler:applyPatch(patch) assert(applyPatchSchema(patch)) for _, removedIdOrInstance in ipairs(patch.removed) do + local removedInstance + if Types.RbxId(removedIdOrInstance) then -- If this value is an ID, it's assumed to be an instance that the -- Rojo server knows about. - + removedInstance = self.__instanceMap.fromIds[removedIdOrInstance] self.__instanceMap:removeId(removedIdOrInstance) - else - -- Otherwise, this instance is one that the Rojo server doesn't know - -- about, and is located in an area where it should be destroyed to - -- keep our trees in sync. + end - removedIdOrInstance:Destroy() + -- If this entry was an ID that we didn't know about, removedInstance + -- will be nil, which we guard against in case of minor tree desync. + if removedInstance ~= nil then + -- Ensure that if any descendants are tracked by Rojo, that we + -- properly un-track them. + for _, descendantInstance in ipairs(removedInstance:GetDescendants()) do + self.__instanceMap:removeInstance(descendantInstance) + end + + removedInstance:Destroy() end end From fb656936271d6c2c8244d86d6b7cca1d82c74f1c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 18:12:52 -0700 Subject: [PATCH 0771/1504] Propagate metadata in project files correctly --- src/snapshot_middleware/project.rs | 47 +++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 6d06e332..ff52a856 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -36,9 +36,28 @@ impl SnapshotMiddleware for SnapshotProject { } let project = Project::load_from_slice(entry.contents(imfs)?, entry.path()) + // TODO: Turn this into an error object .expect("Invalid project file"); - snapshot_project_node(&project.name, &project.tree, imfs) + // Snapshotting a project should always return an instance, so this + // unwrap is safe. + let mut snapshot = snapshot_project_node(&project.name, &project.tree, imfs)?.unwrap(); + + // If the project file updates, we want to trigger a snapshot of the + // entire project tree. We're overwriting the "instigating path" for the + // root instance of the project, since we want to snapshot the project + // file and not the snapshot's original instigating path, or else we + // won't pick up new changes from the project file. + // + // We SHOULD NOT mark the project file as a contributing path for any + // nodes that aren't roots. They'll be updated as part of the project + // file being updated. + snapshot + .metadata + .contributing_paths + .insert(0, entry.path().to_path_buf()); + + Ok(Some(snapshot)) } fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { @@ -52,8 +71,6 @@ fn snapshot_project_node( node: &ProjectNode, imfs: &mut Imfs, ) -> SnapshotInstanceResult<'static> { - let ignore_unknown_instances = node.ignore_unknown_instances.unwrap_or(node.path.is_none()); - let name = Cow::Owned(instance_name.to_owned()); let mut class_name = node .class_name @@ -61,6 +78,7 @@ fn snapshot_project_node( .map(|name| Cow::Owned(name.clone())); let mut properties = HashMap::new(); let mut children = Vec::new(); + let mut metadata = InstanceMetadata::default(); if let Some(path) = &node.path { let entry = imfs.get(path)?; @@ -98,6 +116,10 @@ fn snapshot_project_node( for child in snapshot.children.into_iter() { children.push(child); } + + // Take the snapshot's metadata as-is, which will be mutated later + // on. + metadata = snapshot.metadata; } else { // TODO: Should this issue an error instead? log::warn!( @@ -123,16 +145,27 @@ fn snapshot_project_node( properties.insert(key.clone(), resolved_value); } + // If the user specified $ignoreUnknownInstances, overwrite the existing + // value. + // + // If the user didn't specify it AND $path was not specified (meaning + // there's no existing value we'd be stepping on from a project file or meta + // file), set it to true. + if let Some(ignore) = node.ignore_unknown_instances { + metadata.ignore_unknown_instances = ignore; + } else if node.path.is_none() { + // TODO: Introduce a strict mode where $ignoreUnknownInstances is never + // set implicitly. + metadata.ignore_unknown_instances = true; + } + Ok(Some(InstanceSnapshot { snapshot_id: None, - metadata: InstanceMetadata { - ignore_unknown_instances, - ..Default::default() // TODO: Fill out remaining metadata - }, name, class_name, properties, children, + metadata, })) } From 17d91563d584fb809e606b83a395828b3a3f7e2d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 18:22:20 -0700 Subject: [PATCH 0772/1504] Port project file tests to use insta --- src/snapshot_middleware/project.rs | 87 +++---------------- .../test__project_from_direct_file.snap | 14 +++ .../snapshots/test__project_from_folder.snap | 14 +++ ...test__project_path_property_overrides.snap | 18 ++++ .../test__project_with_children.snap | 23 +++++ .../test__project_with_path_to_project.snap | 15 ++++ ...ct_with_path_to_project_with_children.snap | 24 +++++ .../test__project_with_path_to_txt.snap | 18 ++++ ...est__project_with_resolved_properties.snap | 17 ++++ ...t__project_with_unresolved_properties.snap | 17 ++++ 10 files changed, 170 insertions(+), 77 deletions(-) create mode 100644 src/snapshot_middleware/snapshots/test__project_from_direct_file.snap create mode 100644 src/snapshot_middleware/snapshots/test__project_from_folder.snap create mode 100644 src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap create mode 100644 src/snapshot_middleware/snapshots/test__project_with_children.snap create mode 100644 src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap create mode 100644 src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap create mode 100644 src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap create mode 100644 src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap create mode 100644 src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index ff52a856..56256df7 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -173,8 +173,8 @@ fn snapshot_project_node( mod test { use super::*; + use insta::assert_yaml_snapshot; use maplit::hashmap; - use rbx_dom_weak::RbxValue; use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; @@ -201,10 +201,7 @@ mod test { .expect("snapshot error") .expect("snapshot returned no instances"); - assert_eq!(instance_snapshot.name, "indirect-project"); - assert_eq!(instance_snapshot.class_name, "Folder"); - assert_eq!(instance_snapshot.properties, HashMap::new()); - assert_eq!(instance_snapshot.children, Vec::new()); + assert_yaml_snapshot!(instance_snapshot); } #[test] @@ -230,10 +227,7 @@ mod test { .expect("snapshot error") .expect("snapshot returned no instances"); - assert_eq!(instance_snapshot.name, "direct-project"); - assert_eq!(instance_snapshot.class_name, "Model"); - assert_eq!(instance_snapshot.properties, HashMap::new()); - assert_eq!(instance_snapshot.children, Vec::new()); + assert_yaml_snapshot!(instance_snapshot); } #[test] @@ -265,17 +259,7 @@ mod test { .expect("snapshot error") .expect("snapshot returned no instances"); - assert_eq!(instance_snapshot.name, "resolved-properties"); - assert_eq!(instance_snapshot.class_name, "StringValue"); - assert_eq!( - instance_snapshot.properties, - hashmap! { - "Value".to_owned() => RbxValue::String { - value: "Hello, world!".to_owned(), - }, - } - ); - assert_eq!(instance_snapshot.children, Vec::new()); + assert_yaml_snapshot!(instance_snapshot); } #[test] @@ -304,17 +288,7 @@ mod test { .expect("snapshot error") .expect("snapshot returned no instances"); - assert_eq!(instance_snapshot.name, "unresolved-properties"); - assert_eq!(instance_snapshot.class_name, "StringValue"); - assert_eq!( - instance_snapshot.properties, - hashmap! { - "Value".to_owned() => RbxValue::String { - value: "Hi!".to_owned(), - }, - } - ); - assert_eq!(instance_snapshot.children, Vec::new()); + assert_yaml_snapshot!(instance_snapshot); } #[test] @@ -344,16 +318,7 @@ mod test { .expect("snapshot error") .expect("snapshot returned no instances"); - assert_eq!(instance_snapshot.name, "children"); - assert_eq!(instance_snapshot.class_name, "Folder"); - assert_eq!(instance_snapshot.properties, HashMap::new()); - assert_eq!(instance_snapshot.children.len(), 1); - - let child = &instance_snapshot.children[0]; - assert_eq!(child.name, "Child"); - assert_eq!(child.class_name, "Model"); - assert_eq!(child.properties, HashMap::new()); - assert_eq!(child.children, Vec::new()); + assert_yaml_snapshot!(instance_snapshot); } #[test] @@ -380,17 +345,7 @@ mod test { .expect("snapshot error") .expect("snapshot returned no instances"); - assert_eq!(instance_snapshot.name, "path-project"); - assert_eq!(instance_snapshot.class_name, "StringValue"); - assert_eq!( - instance_snapshot.properties, - hashmap! { - "Value".to_owned() => RbxValue::String { - value: "Hello, world!".to_owned(), - }, - } - ); - assert_eq!(instance_snapshot.children, Vec::new()); + assert_yaml_snapshot!(instance_snapshot); } #[test] @@ -424,10 +379,7 @@ mod test { .expect("snapshot error") .expect("snapshot returned no instances"); - assert_eq!(instance_snapshot.name, "path-project"); - assert_eq!(instance_snapshot.class_name, "Model"); - assert_eq!(instance_snapshot.properties, HashMap::new()); - assert_eq!(instance_snapshot.children, Vec::new()); + assert_yaml_snapshot!(instance_snapshot); } #[test] @@ -465,16 +417,7 @@ mod test { .expect("snapshot error") .expect("snapshot returned no instances"); - assert_eq!(instance_snapshot.name, "path-child-project"); - assert_eq!(instance_snapshot.class_name, "Folder"); - assert_eq!(instance_snapshot.properties, HashMap::new()); - assert_eq!(instance_snapshot.children.len(), 1); - - let child = &instance_snapshot.children[0]; - assert_eq!(child.name, "SomeChild"); - assert_eq!(child.class_name, "Model"); - assert_eq!(child.properties, HashMap::new()); - assert_eq!(child.children, Vec::new()); + assert_yaml_snapshot!(instance_snapshot); } /// Ensures that if a property is defined both in the resulting instance @@ -517,16 +460,6 @@ mod test { .expect("snapshot error") .expect("snapshot returned no instances"); - assert_eq!(instance_snapshot.name, "path-property-override"); - assert_eq!(instance_snapshot.class_name, "StringValue"); - assert_eq!( - instance_snapshot.properties, - hashmap! { - "Value".to_owned() => RbxValue::String { - value: "Changed".to_owned(), - }, - } - ); - assert_eq!(instance_snapshot.children, Vec::new()); + assert_yaml_snapshot!(instance_snapshot); } } diff --git a/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap b/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap new file mode 100644 index 00000000..3eaefb0a --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap @@ -0,0 +1,14 @@ +--- +source: src/snapshot_middleware/project.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: true + contributing_paths: + - /foo/hello.project.json + project_node: ~ +name: direct-project +class_name: Model +properties: {} +children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_from_folder.snap b/src/snapshot_middleware/snapshots/test__project_from_folder.snap new file mode 100644 index 00000000..52f5019c --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__project_from_folder.snap @@ -0,0 +1,14 @@ +--- +source: src/snapshot_middleware/project.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: true + contributing_paths: + - /foo/default.project.json + project_node: ~ +name: indirect-project +class_name: Folder +properties: {} +children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap b/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap new file mode 100644 index 00000000..fd45518e --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap @@ -0,0 +1,18 @@ +--- +source: src/snapshot_middleware/project.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: true + contributing_paths: + - /foo/default.project.json + - /foo/other.project.json + project_node: ~ +name: path-property-override +class_name: StringValue +properties: + Value: + Type: String + Value: Changed +children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_children.snap new file mode 100644 index 00000000..2850c3b5 --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__project_with_children.snap @@ -0,0 +1,23 @@ +--- +source: src/snapshot_middleware/project.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: true + contributing_paths: + - /foo/default.project.json + project_node: ~ +name: children +class_name: Folder +properties: {} +children: + - snapshot_id: ~ + metadata: + ignore_unknown_instances: true + contributing_paths: [] + project_node: ~ + name: Child + class_name: Model + properties: {} + children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap new file mode 100644 index 00000000..4ad043a7 --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap @@ -0,0 +1,15 @@ +--- +source: src/snapshot_middleware/project.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: true + contributing_paths: + - /foo/default.project.json + - /foo/other.project.json + project_node: ~ +name: path-project +class_name: Model +properties: {} +children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap new file mode 100644 index 00000000..6ba03cb5 --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap @@ -0,0 +1,24 @@ +--- +source: src/snapshot_middleware/project.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: true + contributing_paths: + - /foo/default.project.json + - /foo/other.project.json + project_node: ~ +name: path-child-project +class_name: Folder +properties: {} +children: + - snapshot_id: ~ + metadata: + ignore_unknown_instances: true + contributing_paths: [] + project_node: ~ + name: SomeChild + class_name: Model + properties: {} + children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap new file mode 100644 index 00000000..019c88df --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap @@ -0,0 +1,18 @@ +--- +source: src/snapshot_middleware/project.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: false + contributing_paths: + - /foo/default.project.json + - /foo/other.txt + project_node: ~ +name: path-project +class_name: StringValue +properties: + Value: + Type: String + Value: "Hello, world!" +children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap b/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap new file mode 100644 index 00000000..ac0cb468 --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap @@ -0,0 +1,17 @@ +--- +source: src/snapshot_middleware/project.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: true + contributing_paths: + - /foo/default.project.json + project_node: ~ +name: resolved-properties +class_name: StringValue +properties: + Value: + Type: String + Value: "Hello, world!" +children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap b/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap new file mode 100644 index 00000000..32cfe85c --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap @@ -0,0 +1,17 @@ +--- +source: src/snapshot_middleware/project.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: true + contributing_paths: + - /foo/default.project.json + project_node: ~ +name: unresolved-properties +class_name: StringValue +properties: + Value: + Type: String + Value: Hi! +children: [] From 6ef832b3a95b3840d8e5ee7afdbc6c3749a1268e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 18:25:06 -0700 Subject: [PATCH 0773/1504] Improve documentation for SnapshotProject --- src/snapshot_middleware/project.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 56256df7..b4d52ee5 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -14,6 +14,9 @@ use super::{ snapshot_from_imfs, }; +/// Handles snapshots for: +/// * Files ending in `.project.json` +/// * Folders containing a file named `default.project.json` pub struct SnapshotProject; impl SnapshotMiddleware for SnapshotProject { @@ -27,11 +30,16 @@ impl SnapshotMiddleware for SnapshotProject { match imfs.get(project_path) { Err(ref err) if err.kind() == FsErrorKind::NotFound => {} Err(err) => return Err(err), + + // TODO: Do we need to muck with the contributing paths if we're + // a project file within a folder? Should the folder path be the + // contributing path instead of the project file path? Ok(entry) => return SnapshotProject::from_imfs(imfs, &entry), } } if !entry.path().to_string_lossy().ends_with(".project.json") { + // This isn't a project file, so it's not our job. return Ok(None); } From 72d88200e436bc78f5b6ea20095dfbd15e6ceaa2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 18:28:58 -0700 Subject: [PATCH 0774/1504] Snapshot tests for JSON models --- src/snapshot_middleware/json_model.rs | 28 ++++--------------- .../snapshots/test__model_from_imfs.snap | 26 +++++++++++++++++ 2 files changed, 31 insertions(+), 23 deletions(-) create mode 100644 src/snapshot_middleware/snapshots/test__model_from_imfs.snap diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 3cbcc81b..aab58614 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -50,7 +50,9 @@ impl SnapshotMiddleware for SnapshotJsonModel { } } - let snapshot = instance.core.into_snapshot(instance_name); + let mut snapshot = instance.core.into_snapshot(instance_name); + + snapshot.metadata.contributing_paths = vec![entry.path().to_path_buf()]; Ok(Some(snapshot)) } @@ -133,6 +135,7 @@ impl JsonModelCore { mod test { use super::*; + use insta::assert_yaml_snapshot; use maplit::hashmap; use rbx_dom_weak::RbxValue; @@ -166,27 +169,6 @@ mod test { .unwrap() .unwrap(); - assert_eq!( - instance_snapshot, - InstanceSnapshot { - snapshot_id: None, - metadata: Default::default(), // TODO - name: Cow::Borrowed("foo"), - class_name: Cow::Borrowed("IntValue"), - properties: hashmap! { - "Value".to_owned() => RbxValue::Int32 { - value: 5, - }, - }, - children: vec![InstanceSnapshot { - snapshot_id: None, - metadata: Default::default(), // TODO - name: Cow::Borrowed("The Child"), - class_name: Cow::Borrowed("StringValue"), - properties: HashMap::new(), - children: Vec::new(), - },], - } - ); + assert_yaml_snapshot!(instance_snapshot); } } diff --git a/src/snapshot_middleware/snapshots/test__model_from_imfs.snap b/src/snapshot_middleware/snapshots/test__model_from_imfs.snap new file mode 100644 index 00000000..f8a223fb --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__model_from_imfs.snap @@ -0,0 +1,26 @@ +--- +source: src/snapshot_middleware/json_model.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: false + contributing_paths: + - /foo.model.json + project_node: ~ +name: foo +class_name: IntValue +properties: + Value: + Type: Int32 + Value: 5 +children: + - snapshot_id: ~ + metadata: + ignore_unknown_instances: false + contributing_paths: [] + project_node: ~ + name: The Child + class_name: StringValue + properties: {} + children: [] From 10ed353e0a8dd536737e5bf7467a769013123a5c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 3 Oct 2019 18:30:10 -0700 Subject: [PATCH 0775/1504] Add TODO for JSON model metadata --- src/snapshot_middleware/json_model.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index aab58614..8fc41d3b 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -122,7 +122,7 @@ impl JsonModelCore { InstanceSnapshot { snapshot_id: None, - metadata: Default::default(), // TODO + metadata: Default::default(), // TODO: Allow the user to specify metadata in the JSON model again. name: Cow::Owned(name), class_name: Cow::Owned(class_name), properties, From 8bcf12e3177ebe9582c11365528a068f5b02ac29 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Oct 2019 13:18:42 -0700 Subject: [PATCH 0776/1504] Update dependencies --- Cargo.lock | 419 +++++++++++++++++++++++++---------------------------- 1 file changed, 199 insertions(+), 220 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 04940478..56c7d7f6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,7 +2,7 @@ # It is not intended for manual editing. [[package]] name = "adler32" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -45,11 +45,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.35" +version = "0.3.38" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -59,7 +59,7 @@ name = "backtrace-sys" version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -73,7 +73,7 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -103,7 +103,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -127,7 +127,7 @@ version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -147,19 +147,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cc" -version = "1.0.41" +version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "cfg-if" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -169,7 +169,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -192,7 +192,7 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -204,7 +204,7 @@ dependencies = [ "encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -229,8 +229,8 @@ dependencies = [ "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -255,7 +255,7 @@ name = "crc32fast" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -281,7 +281,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -301,7 +301,7 @@ name = "crossbeam-utils" version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -314,7 +314,7 @@ dependencies = [ "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -327,7 +327,7 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.10" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -354,7 +354,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "either" -version = "1.5.2" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -364,10 +364,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "encoding_rs" -version = "0.8.17" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -378,7 +378,7 @@ dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -387,7 +387,7 @@ name = "error-chain" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -396,7 +396,7 @@ name = "failure" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -421,7 +421,7 @@ name = "filetime" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -429,9 +429,10 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -460,7 +461,7 @@ name = "fsevent" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -482,7 +483,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -493,7 +494,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "futures" -version = "0.1.28" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -501,7 +502,7 @@ name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -515,12 +516,12 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -536,9 +537,9 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -566,7 +567,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -586,11 +587,11 @@ dependencies = [ [[package]] name = "hyper" -version = "0.12.33" +version = "0.12.35" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", @@ -606,9 +607,9 @@ dependencies = [ "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -619,8 +620,8 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -647,7 +648,7 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -655,7 +656,7 @@ name = "inotify" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -678,8 +679,8 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -734,11 +735,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lock_api" -version = "0.1.5" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -746,7 +746,7 @@ name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -764,7 +764,7 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -801,18 +801,15 @@ dependencies = [ [[package]] name = "mime" -version = "0.3.13" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "mime_guess" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -821,7 +818,7 @@ name = "miniz_oxide" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -871,10 +868,10 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.50 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -885,7 +882,7 @@ name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -900,7 +897,7 @@ name = "notify" version = "4.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -928,15 +925,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.24" +version = "0.10.25" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.50 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -946,13 +943,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.49" +version = "0.9.50" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -964,30 +961,25 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "owning_ref" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parking_lot" -version = "0.7.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "parking_lot_core" -version = "0.4.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -999,7 +991,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1007,8 +999,8 @@ name = "paste-impl" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1047,7 +1039,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1064,7 +1056,7 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.15" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1078,17 +1070,17 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ctor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro-hack" -version = "0.5.9" +version = "0.5.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1108,7 +1100,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.2" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1122,7 +1114,7 @@ dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1131,7 +1123,7 @@ name = "pulldown-cmark" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1152,7 +1144,7 @@ name = "quote" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1187,10 +1179,10 @@ dependencies = [ [[package]] name = "rand" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1233,7 +1225,7 @@ name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1308,32 +1300,32 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_dom_weak" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_reflection" -version = "3.2.399" +version = "3.2.404" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1343,8 +1335,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.2.399 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.2.404 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1363,7 +1355,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex" -version = "1.3.0" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1395,31 +1387,31 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.20" +version = "0.9.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1432,7 +1424,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1442,7 +1434,7 @@ name = "ritz_impl" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1457,9 +1449,9 @@ dependencies = [ "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)", + "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1469,15 +1461,15 @@ dependencies = [ "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.2.399 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.2.404 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rojo-insta-ext 0.1.0", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1490,7 +1482,7 @@ name = "rojo-insta-ext" version = "0.1.0" dependencies = [ "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1502,12 +1494,12 @@ dependencies = [ "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)", "rojo 0.6.0-dev", "rojo-insta-ext 0.1.0", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1540,18 +1532,13 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "scopeguard" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "scopeguard" version = "1.0.0" @@ -1582,7 +1569,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1592,30 +1579,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.99" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.99" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.40" +version = "1.0.41" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1623,7 +1610,7 @@ name = "serde_repr" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1635,7 +1622,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1646,7 +1633,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1671,7 +1658,7 @@ dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1694,11 +1681,6 @@ dependencies = [ "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "stable_deref_trait" -version = "1.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "string" version = "0.2.1" @@ -1727,7 +1709,7 @@ name = "syn" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1757,9 +1739,9 @@ name = "tempfile" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1813,15 +1795,15 @@ version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1831,8 +1813,8 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1840,7 +1822,7 @@ name = "tokio-current-thread" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1850,7 +1832,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1859,22 +1841,22 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-reactor" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1887,7 +1869,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1896,25 +1878,25 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1925,7 +1907,7 @@ version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1940,7 +1922,7 @@ name = "try_from" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2018,7 +2000,7 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2051,14 +2033,14 @@ name = "want" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "wasi" -version = "0.5.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2138,16 +2120,16 @@ dependencies = [ ] [metadata] -"checksum adler32 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7e522997b529f05601e05166c07ed17789691f562762c7f3b987263d2dedee5c" +"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" "checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" -"checksum backtrace 0.3.35 (registry+https://github.com/rust-lang/crates.io-index)" = "1371048253fa3bac6704bfd6bbfc922ee9bdcee8881330d40f308b81cc5adc55" +"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5" "checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" +"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" "checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" @@ -2157,8 +2139,8 @@ dependencies = [ "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cc 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "8dae9c4b8fedcae85592ba623c4fd08cfdab3e3b72d6df780c6ead964a69bfff" -"checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33" +"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" +"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" @@ -2175,20 +2157,20 @@ dependencies = [ "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" "checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" "checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" -"checksum ctor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "5b6b2f4752cc29efbfd03474c532ce8f916f2d44ec5bb8c21f93bc76e5365528" +"checksum ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" -"checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b" +"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" -"checksum encoding_rs 0.8.17 (registry+https://github.com/rust-lang/crates.io-index)" = "4155785c79f2f6701f185eb2e6b4caf0555ec03477cb4c70db67b465311620ed" +"checksum encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)" = "87240518927716f79692c2ed85bfe6e98196d18c6401ec75355760233a7e12e9" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" "checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd7380b54ced79dda72ecc35cc4fbbd1da6bba54afaa37e96fd1c2a308cd469" -"checksum flate2 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "2adaffba6388640136149e18ed080b77a78611c1e1d6de75aedcdf78df5d4682" +"checksum flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ad3c5233c9a940c8719031b423d7e6c16af66e031cb0420b0896f5245bf181d3" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" @@ -2197,10 +2179,10 @@ dependencies = [ "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "45dc39533a6cae6da2b56da48edae506bb767ec07370f86f70fc062e9d435869" +"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum getrandom 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "fc344b02d3868feb131e8b5fe2b9b0a1cc42942679af493061fc13b853243872" +"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" @@ -2208,11 +2190,11 @@ dependencies = [ "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -"checksum hyper 0.12.33 (registry+https://github.com/rust-lang/crates.io-index)" = "7cb44cbce9d8ee4fb36e4c0ad7b794ac44ebaad924b9c8291a63215bb44c2c8f" +"checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum indexmap 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a4d6d89e0948bf10c08b9ecc8ac5b83f07f857ebe2c0cbe38de15b4e4f510356" +"checksum indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" "checksum insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23f83ab4ee86f38b292f0420c27fd412690a4baa9ea0ad4e3fa624bf34379b76" @@ -2224,7 +2206,7 @@ dependencies = [ "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" -"checksum lock_api 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "62ebf1391f6acad60e5c8b43706dde4582df75c06698ab44511d15016bc2442c" +"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" @@ -2233,7 +2215,7 @@ dependencies = [ "checksum md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e6bcd6433cff03a4bfc3d9834d504467db1f1cf6d0ea765d37d330249ed629d" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" -"checksum mime 0.3.13 (registry+https://github.com/rust-lang/crates.io-index)" = "3e27ca21f40a310bd06d9031785f4801710d566c184a6e15bad4f1d9b65f9425" +"checksum mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "dd1d63acd1b78403cc0c325605908475dd9b9a3acbf65ed8bcab97e27014afcf" "checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" "checksum miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7108aff85b876d06f22503dcce091e29f76733b2bfdd91eebce81f5e68203a10" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" @@ -2245,13 +2227,12 @@ dependencies = [ "checksum notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1191efa2b8fe041decb55c238a125b7a1aeb6fad7a525133a02be5ec949ff3cb" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum openssl 0.10.24 (registry+https://github.com/rust-lang/crates.io-index)" = "8152bb5a9b5b721538462336e3bef9a539f892715e5037fda0f984577311af15" +"checksum openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.49 (registry+https://github.com/rust-lang/crates.io-index)" = "f4fad9e54bd23bd4cbbe48fdc08a1b8091707ac869ef8508edea2fec77dcc884" +"checksum openssl-sys 0.9.50 (registry+https://github.com/rust-lang/crates.io-index)" = "2c42dcccb832556b5926bc9ae61e8775f2a61e725ab07ab3d1e7fcf8ae62c3b6" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" -"checksum owning_ref 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49a4b8ea2179e6a2e27411d3bca09ca6dd630821cf6894c6c7c8467a8ee7ef13" -"checksum parking_lot 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ab41b4aed082705d1056416ae4468b6ea99d52599ecf3169b00088d43113e337" -"checksum parking_lot_core 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94c8c7923936b28d546dfd14d4472eaf34c99b14e1c973a32b3e6d4eb04298c9" +"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" "checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" "checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" @@ -2260,13 +2241,13 @@ dependencies = [ "checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" "checksum pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9fcf299b5712d06ee128a556c94709aaa04512c4dffb8ead07c5c998447fc0" "checksum pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df43fd99896fd72c485fe47542c7b500e4ac1e8700bf995544d1317a60ded547" -"checksum pkg-config 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c1d2cfa5a714db3b5f24f0915e74fcdf91d09d496ba61329705dda7774d2af" +"checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea" "checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" -"checksum proc-macro-hack 0.5.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e688f31d92ffd7c1ddc57a1b4e6d773c0f2a14ee437a4b0a4f5a69c80eb221c8" +"checksum proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "114cdf1f426eb7f550f01af5f53a33c0946156f6814aec939b3bd77e844f9a9d" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "175a40b9cf564ce9bf050654633dbf339978706b8ead1a907bb970b63185dd95" +"checksum proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0" "checksum publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9bf259a81de2b2eb9850ec990ec78e6a25319715584fd7652b9b26f96fcb1510" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" @@ -2274,7 +2255,7 @@ dependencies = [ "checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d47eab0e83d9693d40f825f86948aa16eff6750ead4bdffc4ab95b8b3a7f052c" +"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" @@ -2288,32 +2269,31 @@ dependencies = [ "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81428c521a07a3feac9c31180a886e467eecf81b769987f70d51d567a09c321d" -"checksum rbx_dom_weak 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb8079fe850096bd18582a8661f5d7a6afee61bc914691be2f287050f3ac0ec4" -"checksum rbx_reflection 3.2.399 (registry+https://github.com/rust-lang/crates.io-index)" = "13df0adaeaad56d905fecfef8a4c4d6ec31a7e2afaa6e900fef7a5b5ec337813" +"checksum rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b7c983d7bfcf0811a164e33e99e2da456f38babb33c75e365b17aa1ee5fd2d" +"checksum rbx_reflection 3.2.404 (registry+https://github.com/rust-lang/crates.io-index)" = "7712c0a5ae6524ec5f51c29bc031f21e5ba35b38ffc6277f2ee9439febaec88c" "checksum rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0236363b0af0c78f3e972ac7f46a1f355f663518e276253136d0180f3c8742c" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum regex 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc98360d9e6ad383647702acc90f80b0582eac3ea577ab47d96325d3575de908" +"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum reqwest 0.9.20 (registry+https://github.com/rust-lang/crates.io-index)" = "0f6d896143a583047512e59ac54a215cb203c29cc941917343edea3be8df9c78" +"checksum reqwest 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)" = "02b7e953e14c6f3102b7e8d1f1ee3abf5ecee80b427f5565c9389835cecae95c" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" -"checksum schannel 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f6abf258d99c3c1c5c2131d99d064e94b7b3dd5f416483057f308fea253339" -"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" "checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" "checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "fec2851eb56d010dc9a21b89ca53ee75e6528bab60c11e89d38390904982da9f" -"checksum serde_derive 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)" = "cb4dc18c61206b08dc98216c98faa0232f4337e1e1b8574551d5bad29ea1b425" -"checksum serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)" = "051c49229f282f7c6f3813f8286cc1e3323e8051823fce42c7ea80fe13521704" +"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" +"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" +"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" "checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" @@ -2322,7 +2302,6 @@ dependencies = [ "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" "checksum snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef82be0baf3ae45701ab992230f1f4889c15984736d87f37558aea3e4e321af" -"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" "checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" @@ -2340,10 +2319,10 @@ dependencies = [ "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" "checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" -"checksum tokio-reactor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6af16bfac7e112bea8b0442542161bfc41cbfa4466b580bdda7d18cb88b911ce" +"checksum tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c56391be9805bc80163151c0b9e5164ee64f4b0200962c346fea12773158f22d" "checksum tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "90ca01319dea1e376a001e8dc192d42ebde6dd532532a5bad988ac37db365b19" +"checksum tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd2c6a3885302581f4401c82af70d792bb9df1700e7437b0aeb4ada94d5388c" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" @@ -2363,7 +2342,7 @@ dependencies = [ "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" -"checksum wasi 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fd5442abcac6525a045cc8c795aedb60da7a2e5e89c7bf18a0d5357849bb23c7" +"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" From cd84fb9fc1e8229678462e854f784dc1bb05c509 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Oct 2019 13:19:14 -0700 Subject: [PATCH 0777/1504] Bring forward 0.5.1 release notes --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b84e3847..a204a71c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,12 @@ * Fixed Rojo dropping Ref properties ([#142](https://github.com/rojo-rbx/rojo/issues/142)) * This means that properties like `PrimaryPart` now work! +## [0.5.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.1) (October 4, 2019) +* Fixed an issue where Rojo would drop changes if they happened too quickly ([#252](https://github.com/rojo-rbx/rojo/issues/252)) +* Improved diagnostics for when the Rojo plugin cannot create an instance. +* Updated dependencies + * This brings Rojo's reflection database from client release 395 to client release 404. + ## [0.5.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0) (August 27, 2019) * Changed `.model.json` naming, which may require projects to migrate ambiguous cases: * The file name now takes precedence over the `Name` field in the model, like Rojo 0.4.x. From 35df5f25c725841ce23c1bebb33bded3d552b0ba Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Oct 2019 14:14:45 -0700 Subject: [PATCH 0778/1504] Show metadata in web interface, take one --- assets/index.css | 6 +++++- src/web/ui.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/assets/index.css b/assets/index.css index 14c45247..1eb5893f 100644 --- a/assets/index.css +++ b/assets/index.css @@ -24,7 +24,7 @@ img { } .path-list > li { - margin-left: 1rem; + margin-left: 1.2em; font-family: monospace; } @@ -106,6 +106,10 @@ img { padding: 0.5rem; } +.instance-metadata { + padding: 0.5rem; +} + .instance-properties { padding: 0.5rem; } diff --git a/src/web/ui.rs b/src/web/ui.rs index edf0a6a6..9e4e345a 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -245,6 +245,50 @@ impl UiService { section.render() }; + let metadata_container = { + let metadata = instance.metadata(); + + let contributing_paths = if metadata.contributing_paths.is_empty() { + HtmlContent::None + } else { + let list = metadata + .contributing_paths + .iter() + .map(|path| html! {
  • { format!("{}", path.display()) }
  • }); + + html! { +
    + "contributing_paths: " +
      { Fragment::new(list) }
    +
    + } + }; + + let project_node = match &metadata.project_node { + None => HtmlContent::None, + Some(node) => html! { +
    "project node: " { format!("{:?}", node) }
    + }, + }; + + let content = html! { + <> +
    "ignore_unknown_instances: " { metadata.ignore_unknown_instances.to_string() }
    + { contributing_paths } + + }; + + let section = ExpandableSection { + title: "Metadata", + class_name: "instance-metadata", + id, + expanded: false, + content, + }; + + section.render() + }; + let class_name_specifier = if instance.name() == instance.class_name() { HtmlContent::None } else { @@ -261,6 +305,7 @@ impl UiService { { instance.name().to_owned() } { class_name_specifier } + { metadata_container } { property_container } { children_container }
    From 938c8259c3382df71a0c779cc71ab59c3a4a2c33 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Oct 2019 14:29:02 -0700 Subject: [PATCH 0779/1504] Include project node in debug UI --- src/web/ui.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/web/ui.rs b/src/web/ui.rs index 9e4e345a..ca41f445 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -275,6 +275,7 @@ impl UiService { <>
    "ignore_unknown_instances: " { metadata.ignore_unknown_instances.to_string() }
    { contributing_paths } + { project_node } }; From 238233ca818f79695ef491ce18b3c1cfc5e6f02c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Oct 2019 15:12:21 -0700 Subject: [PATCH 0780/1504] Stop serializing project_node if it's None --- src/snapshot/metadata.rs | 1 + src/snapshot/tests/snapshots/apply__add_property.snap | 1 - .../tests/snapshots/apply__remove_property_initial.snap | 1 - .../tests/snapshots/apply__set_name_and_class_name.snap | 1 - src/snapshot/tests/snapshots/compute__add_child.snap | 1 - src/snapshot_middleware/snapshots/test__client_from_imfs.snap | 1 - src/snapshot_middleware/snapshots/test__csv_from_imfs.snap | 1 - src/snapshot_middleware/snapshots/test__empty_folder.snap | 1 - src/snapshot_middleware/snapshots/test__folder_in_folder.snap | 2 -- src/snapshot_middleware/snapshots/test__instance_from_imfs.snap | 1 - src/snapshot_middleware/snapshots/test__model_from_imfs.snap | 2 -- src/snapshot_middleware/snapshots/test__module_from_imfs.snap | 1 - .../snapshots/test__project_from_direct_file.snap | 1 - .../snapshots/test__project_from_folder.snap | 1 - .../snapshots/test__project_path_property_overrides.snap | 1 - .../snapshots/test__project_with_children.snap | 2 -- .../snapshots/test__project_with_path_to_project.snap | 1 - .../test__project_with_path_to_project_with_children.snap | 2 -- .../snapshots/test__project_with_path_to_txt.snap | 1 - .../snapshots/test__project_with_resolved_properties.snap | 1 - .../snapshots/test__project_with_unresolved_properties.snap | 1 - src/snapshot_middleware/snapshots/test__server_from_imfs.snap | 1 - 22 files changed, 1 insertion(+), 25 deletions(-) diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index 62ef7fb8..d7997489 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -45,6 +45,7 @@ pub struct InstanceMetadata { /// This information is used to make sure the instance has the correct name, /// project-added children, and metadata when it's updated in response to a /// file change. + #[serde(skip_serializing_if = "Option::is_none")] pub project_node: Option<(String, ProjectNode)>, } diff --git a/src/snapshot/tests/snapshots/apply__add_property.snap b/src/snapshot/tests/snapshots/apply__add_property.snap index bb466314..72c85688 100644 --- a/src/snapshot/tests/snapshots/apply__add_property.snap +++ b/src/snapshot/tests/snapshots/apply__add_property.snap @@ -12,5 +12,4 @@ properties: metadata: ignore_unknown_instances: false contributing_paths: [] - project_node: ~ children: [] diff --git a/src/snapshot/tests/snapshots/apply__remove_property_initial.snap b/src/snapshot/tests/snapshots/apply__remove_property_initial.snap index a8aaaa3e..e7d7d8a1 100644 --- a/src/snapshot/tests/snapshots/apply__remove_property_initial.snap +++ b/src/snapshot/tests/snapshots/apply__remove_property_initial.snap @@ -12,5 +12,4 @@ properties: metadata: ignore_unknown_instances: false contributing_paths: [] - project_node: ~ children: [] diff --git a/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap b/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap index 707accac..80941bda 100644 --- a/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap +++ b/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap @@ -9,5 +9,4 @@ properties: {} metadata: ignore_unknown_instances: false contributing_paths: [] - project_node: ~ children: [] diff --git a/src/snapshot/tests/snapshots/compute__add_child.snap b/src/snapshot/tests/snapshots/compute__add_child.snap index b2281d8a..48699fdc 100644 --- a/src/snapshot/tests/snapshots/compute__add_child.snap +++ b/src/snapshot/tests/snapshots/compute__add_child.snap @@ -10,7 +10,6 @@ added_instances: metadata: ignore_unknown_instances: false contributing_paths: [] - project_node: ~ name: New class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/test__client_from_imfs.snap b/src/snapshot_middleware/snapshots/test__client_from_imfs.snap index bc4df00b..8b6b2ebb 100644 --- a/src/snapshot_middleware/snapshots/test__client_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__client_from_imfs.snap @@ -7,7 +7,6 @@ metadata: ignore_unknown_instances: false contributing_paths: - /foo.client.lua - project_node: ~ name: foo class_name: LocalScript properties: diff --git a/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap b/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap index f932eadc..e2d4df4b 100644 --- a/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap @@ -7,7 +7,6 @@ metadata: ignore_unknown_instances: false contributing_paths: - /foo.csv - project_node: ~ name: foo class_name: LocalizationTable properties: diff --git a/src/snapshot_middleware/snapshots/test__empty_folder.snap b/src/snapshot_middleware/snapshots/test__empty_folder.snap index 15556287..36a0eb13 100644 --- a/src/snapshot_middleware/snapshots/test__empty_folder.snap +++ b/src/snapshot_middleware/snapshots/test__empty_folder.snap @@ -7,7 +7,6 @@ metadata: ignore_unknown_instances: false contributing_paths: - /foo - project_node: ~ name: foo class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap index a65151d7..7f01fbdc 100644 --- a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap +++ b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap @@ -7,7 +7,6 @@ metadata: ignore_unknown_instances: false contributing_paths: - /foo - project_node: ~ name: foo class_name: Folder properties: {} @@ -17,7 +16,6 @@ children: ignore_unknown_instances: false contributing_paths: - /foo/Child - project_node: ~ name: Child class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap b/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap index 5d7dca15..45e26d09 100644 --- a/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap @@ -7,7 +7,6 @@ metadata: ignore_unknown_instances: false contributing_paths: - /foo.txt - project_node: ~ name: foo class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/test__model_from_imfs.snap b/src/snapshot_middleware/snapshots/test__model_from_imfs.snap index f8a223fb..1d2ff82d 100644 --- a/src/snapshot_middleware/snapshots/test__model_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__model_from_imfs.snap @@ -7,7 +7,6 @@ metadata: ignore_unknown_instances: false contributing_paths: - /foo.model.json - project_node: ~ name: foo class_name: IntValue properties: @@ -19,7 +18,6 @@ children: metadata: ignore_unknown_instances: false contributing_paths: [] - project_node: ~ name: The Child class_name: StringValue properties: {} diff --git a/src/snapshot_middleware/snapshots/test__module_from_imfs.snap b/src/snapshot_middleware/snapshots/test__module_from_imfs.snap index 5d0407fe..0d036205 100644 --- a/src/snapshot_middleware/snapshots/test__module_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__module_from_imfs.snap @@ -7,7 +7,6 @@ metadata: ignore_unknown_instances: false contributing_paths: - /foo.lua - project_node: ~ name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap b/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap index 3eaefb0a..19350c7d 100644 --- a/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap +++ b/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap @@ -7,7 +7,6 @@ metadata: ignore_unknown_instances: true contributing_paths: - /foo/hello.project.json - project_node: ~ name: direct-project class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/test__project_from_folder.snap b/src/snapshot_middleware/snapshots/test__project_from_folder.snap index 52f5019c..ee08d8a4 100644 --- a/src/snapshot_middleware/snapshots/test__project_from_folder.snap +++ b/src/snapshot_middleware/snapshots/test__project_from_folder.snap @@ -7,7 +7,6 @@ metadata: ignore_unknown_instances: true contributing_paths: - /foo/default.project.json - project_node: ~ name: indirect-project class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap b/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap index fd45518e..c40c7e6b 100644 --- a/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap +++ b/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap @@ -8,7 +8,6 @@ metadata: contributing_paths: - /foo/default.project.json - /foo/other.project.json - project_node: ~ name: path-property-override class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/test__project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_children.snap index 2850c3b5..7d489305 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_children.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_children.snap @@ -7,7 +7,6 @@ metadata: ignore_unknown_instances: true contributing_paths: - /foo/default.project.json - project_node: ~ name: children class_name: Folder properties: {} @@ -16,7 +15,6 @@ children: metadata: ignore_unknown_instances: true contributing_paths: [] - project_node: ~ name: Child class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap index 4ad043a7..2aa19545 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap @@ -8,7 +8,6 @@ metadata: contributing_paths: - /foo/default.project.json - /foo/other.project.json - project_node: ~ name: path-project class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap index 6ba03cb5..0da40c3a 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap @@ -8,7 +8,6 @@ metadata: contributing_paths: - /foo/default.project.json - /foo/other.project.json - project_node: ~ name: path-child-project class_name: Folder properties: {} @@ -17,7 +16,6 @@ children: metadata: ignore_unknown_instances: true contributing_paths: [] - project_node: ~ name: SomeChild class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap index 019c88df..3dac9993 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap @@ -8,7 +8,6 @@ metadata: contributing_paths: - /foo/default.project.json - /foo/other.txt - project_node: ~ name: path-project class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap b/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap index ac0cb468..49e4d4f7 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap @@ -7,7 +7,6 @@ metadata: ignore_unknown_instances: true contributing_paths: - /foo/default.project.json - project_node: ~ name: resolved-properties class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap b/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap index 32cfe85c..adbd6e94 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap @@ -7,7 +7,6 @@ metadata: ignore_unknown_instances: true contributing_paths: - /foo/default.project.json - project_node: ~ name: unresolved-properties class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/test__server_from_imfs.snap b/src/snapshot_middleware/snapshots/test__server_from_imfs.snap index c992669a..02dc90cd 100644 --- a/src/snapshot_middleware/snapshots/test__server_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__server_from_imfs.snap @@ -7,7 +7,6 @@ metadata: ignore_unknown_instances: false contributing_paths: - /foo.server.lua - project_node: ~ name: foo class_name: Script properties: From 2025b8a4944d463328b41d01d99fe22ca00f1397 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Oct 2019 15:49:12 -0700 Subject: [PATCH 0781/1504] Fix patch I missed project_node change --- .../tests/snapshots/apply__remove_property_after_patch.snap | 1 - 1 file changed, 1 deletion(-) diff --git a/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap b/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap index a732e1b0..89d44ecc 100644 --- a/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap +++ b/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap @@ -9,5 +9,4 @@ properties: {} metadata: ignore_unknown_instances: false contributing_paths: [] - project_node: ~ children: [] From 052ca52cc39288086c6caa451d06bd50fe04ee0f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Oct 2019 17:34:05 -0700 Subject: [PATCH 0782/1504] Move instigating source out of contributing paths (#253) * Refactor contributing_paths into contributing_sources, deleting project node sources * Instead of changing contributing_paths, add instigating_source * Remove InstanceMetadata::project_node * Stop pushing project path to front of contributing_paths since it doesn't matter now * Remove accidental UI change for path display --- src/change_processor.rs | 28 ++++++---- src/snapshot/metadata.rs | 52 ++++++++++++------- src/snapshot/mod.rs | 2 +- src/snapshot_middleware/project.rs | 2 +- ...test__project_path_property_overrides.snap | 2 +- .../test__project_with_path_to_project.snap | 2 +- ...ct_with_path_to_project_with_children.snap | 2 +- .../test__project_with_path_to_txt.snap | 2 +- src/web/ui.rs | 9 +--- 9 files changed, 60 insertions(+), 41 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index 8e57a639..7bb5b382 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -11,7 +11,7 @@ use jod_thread::JoinHandle; use crate::{ imfs::{Imfs, ImfsEvent, ImfsFetcher}, message_queue::MessageQueue, - snapshot::{apply_patch_set, compute_patch_set, AppliedPatchSet, RojoTree}, + snapshot::{apply_patch_set, compute_patch_set, AppliedPatchSet, InstigatingSource, RojoTree}, snapshot_middleware::snapshot_from_imfs, }; @@ -84,22 +84,32 @@ impl ChangeProcessor { let metadata = tree.get_metadata(id) .expect("metadata missing for instance present in tree"); - let instigating_path = match metadata.contributing_paths.get(0) { + let instigating_source = match &metadata.instigating_source { Some(path) => path, None => { - log::warn!("Instance {} did not have an instigating path, but was considered for an update.", id); + log::warn!("Instance {} did not have an instigating source, but was considered for an update.", id); log::warn!("This is a Rojo bug. Please file an issue!"); continue; } }; - let entry = imfs - .get(instigating_path) - .expect("could not get instigating path from filesystem"); + let snapshot = match instigating_source { + InstigatingSource::Path(instigating_path) => { + let entry = imfs + .get(instigating_path) + .expect("could not get instigating path from filesystem"); - let snapshot = snapshot_from_imfs(&mut imfs, &entry) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); + let snapshot = snapshot_from_imfs(&mut imfs, &entry) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + snapshot + } + InstigatingSource::ProjectNode(_, _) => { + log::warn!("Instance {} had an instigating source that was a project node, which is not yet supported.", id); + continue; + } + }; log::trace!("Computed snapshot: {:#?}", snapshot); diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index d7997489..f843fd4b 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -1,4 +1,4 @@ -use std::path::PathBuf; +use std::{fmt, path::PathBuf}; use serde::{Deserialize, Serialize}; @@ -13,48 +13,64 @@ pub struct InstanceMetadata { /// manage. pub ignore_unknown_instances: bool, + /// If a change occurs to this instance, the instigating source is what + /// should be run through the snapshot functions to regenerate it. + #[serde(skip_serializing_if = "Option::is_none")] + pub instigating_source: Option, + /// The paths that, when changed, could cause the function that generated /// this snapshot to generate a different snapshot. Paths should be included /// even if they don't exist, since the presence of a file can change the /// outcome of a snapshot function. /// - /// The first path in this list is considered the "instigating path", and - /// will be the snapshot target if any of the contributing paths change. - /// /// For example, a file named foo.lua might have these contributing paths: - /// - foo.lua (instigating path) + /// - foo.lua /// - foo.meta.json (even if this file doesn't exist!) /// - /// A directory named bar/ included in the project file might have these: - /// - bar/ (instigating path) + /// A directory named bar/ might have these: + /// - bar/ /// - bar/init.meta.json /// - bar/init.lua /// - bar/init.server.lua /// - bar/init.client.lua - /// - default.project.json + /// - bar/default.project.json /// /// This path is used to make sure that file changes update all instances /// that may need updates. // TODO: Change this to be a SmallVec for performance in common cases? #[serde(serialize_with = "path_serializer::serialize_vec_absolute")] pub contributing_paths: Vec, - - /// If this instance was defined in a project file, this is the name from - /// the project file and the node under it. - /// - /// This information is used to make sure the instance has the correct name, - /// project-added children, and metadata when it's updated in response to a - /// file change. - #[serde(skip_serializing_if = "Option::is_none")] - pub project_node: Option<(String, ProjectNode)>, } impl Default for InstanceMetadata { fn default() -> Self { InstanceMetadata { ignore_unknown_instances: false, + instigating_source: None, contributing_paths: Vec::new(), - project_node: None, } } } + +#[derive(Clone, PartialEq, Serialize, Deserialize)] +pub enum InstigatingSource { + Path(#[serde(serialize_with = "path_serializer::serialize_absolute")] PathBuf), + ProjectNode(String, ProjectNode), +} + +impl fmt::Debug for InstigatingSource { + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + InstigatingSource::Path(path) => write!(formatter, "Path({})", path.display()), + InstigatingSource::ProjectNode(name, node) => { + write!(formatter, "ProjectNode({}: {:?}", name, node) + } + } + } +} + +impl From for InstigatingSource { + fn from(path: PathBuf) -> Self { + InstigatingSource::Path(path) + } +} diff --git a/src/snapshot/mod.rs b/src/snapshot/mod.rs index de269d5b..5aacdad6 100644 --- a/src/snapshot/mod.rs +++ b/src/snapshot/mod.rs @@ -56,7 +56,7 @@ mod patch_compute; mod tree; pub use instance_snapshot::InstanceSnapshot; -pub use metadata::InstanceMetadata; +pub use metadata::*; pub use patch::*; pub use patch_apply::apply_patch_set; pub use patch_compute::compute_patch_set; diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index b4d52ee5..37b357b0 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -63,7 +63,7 @@ impl SnapshotMiddleware for SnapshotProject { snapshot .metadata .contributing_paths - .insert(0, entry.path().to_path_buf()); + .push(entry.path().to_path_buf()); Ok(Some(snapshot)) } diff --git a/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap b/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap index c40c7e6b..086c55c3 100644 --- a/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap +++ b/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap @@ -6,8 +6,8 @@ snapshot_id: ~ metadata: ignore_unknown_instances: true contributing_paths: - - /foo/default.project.json - /foo/other.project.json + - /foo/default.project.json name: path-property-override class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap index 2aa19545..00984eeb 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap @@ -6,8 +6,8 @@ snapshot_id: ~ metadata: ignore_unknown_instances: true contributing_paths: - - /foo/default.project.json - /foo/other.project.json + - /foo/default.project.json name: path-project class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap index 0da40c3a..374dbfe5 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap @@ -6,8 +6,8 @@ snapshot_id: ~ metadata: ignore_unknown_instances: true contributing_paths: - - /foo/default.project.json - /foo/other.project.json + - /foo/default.project.json name: path-child-project class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap index 3dac9993..5e3ff432 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap @@ -6,8 +6,8 @@ snapshot_id: ~ metadata: ignore_unknown_instances: false contributing_paths: - - /foo/default.project.json - /foo/other.txt + - /foo/default.project.json name: path-project class_name: StringValue properties: diff --git a/src/web/ui.rs b/src/web/ui.rs index ca41f445..9b1a7f5e 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -264,18 +264,11 @@ impl UiService { } }; - let project_node = match &metadata.project_node { - None => HtmlContent::None, - Some(node) => html! { -
    "project node: " { format!("{:?}", node) }
    - }, - }; - let content = html! { <>
    "ignore_unknown_instances: " { metadata.ignore_unknown_instances.to_string() }
    +
    "instigating source: " { format!("{:?}", metadata.instigating_source) }
    { contributing_paths } - { project_node } }; From 530a7aa834600e151b13f55958719016b6467fa0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Oct 2019 17:36:26 -0700 Subject: [PATCH 0783/1504] Rename 'contributing paths' to 'relevant paths' --- src/snapshot/metadata.rs | 6 +++--- src/snapshot/tests/snapshots/apply__add_property.snap | 4 ++-- .../snapshots/apply__remove_property_after_patch.snap | 4 ++-- .../snapshots/apply__remove_property_initial.snap | 4 ++-- .../snapshots/apply__set_name_and_class_name.snap | 4 ++-- src/snapshot/tests/snapshots/compute__add_child.snap | 4 ++-- src/snapshot/tree.rs | 10 +++++----- src/snapshot_middleware/csv.rs | 2 +- src/snapshot_middleware/dir.rs | 2 +- src/snapshot_middleware/json_model.rs | 2 +- src/snapshot_middleware/lua.rs | 2 +- src/snapshot_middleware/project.rs | 10 +++++----- src/snapshot_middleware/rbxlx.rs | 2 +- src/snapshot_middleware/rbxm.rs | 2 +- src/snapshot_middleware/rbxmx.rs | 2 +- .../snapshots/test__client_from_imfs.snap | 4 ++-- .../snapshots/test__csv_from_imfs.snap | 4 ++-- .../snapshots/test__empty_folder.snap | 4 ++-- .../snapshots/test__folder_in_folder.snap | 6 +++--- .../snapshots/test__instance_from_imfs.snap | 4 ++-- .../snapshots/test__model_from_imfs.snap | 6 +++--- .../snapshots/test__module_from_imfs.snap | 4 ++-- .../snapshots/test__project_from_direct_file.snap | 4 ++-- .../snapshots/test__project_from_folder.snap | 4 ++-- .../test__project_path_property_overrides.snap | 4 ++-- .../snapshots/test__project_with_children.snap | 6 +++--- .../snapshots/test__project_with_path_to_project.snap | 4 ++-- ...st__project_with_path_to_project_with_children.snap | 6 +++--- .../snapshots/test__project_with_path_to_txt.snap | 4 ++-- .../test__project_with_resolved_properties.snap | 4 ++-- .../test__project_with_unresolved_properties.snap | 4 ++-- .../snapshots/test__server_from_imfs.snap | 4 ++-- src/snapshot_middleware/txt.rs | 2 +- src/web/ui.rs | 8 ++++---- 34 files changed, 73 insertions(+), 73 deletions(-) diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index f843fd4b..93556cc2 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -23,7 +23,7 @@ pub struct InstanceMetadata { /// even if they don't exist, since the presence of a file can change the /// outcome of a snapshot function. /// - /// For example, a file named foo.lua might have these contributing paths: + /// For example, a file named foo.lua might have these relevant paths: /// - foo.lua /// - foo.meta.json (even if this file doesn't exist!) /// @@ -39,7 +39,7 @@ pub struct InstanceMetadata { /// that may need updates. // TODO: Change this to be a SmallVec for performance in common cases? #[serde(serialize_with = "path_serializer::serialize_vec_absolute")] - pub contributing_paths: Vec, + pub relevant_paths: Vec, } impl Default for InstanceMetadata { @@ -47,7 +47,7 @@ impl Default for InstanceMetadata { InstanceMetadata { ignore_unknown_instances: false, instigating_source: None, - contributing_paths: Vec::new(), + relevant_paths: Vec::new(), } } } diff --git a/src/snapshot/tests/snapshots/apply__add_property.snap b/src/snapshot/tests/snapshots/apply__add_property.snap index 72c85688..33022a76 100644 --- a/src/snapshot/tests/snapshots/apply__add_property.snap +++ b/src/snapshot/tests/snapshots/apply__add_property.snap @@ -11,5 +11,5 @@ properties: Value: Value of Foo metadata: ignore_unknown_instances: false - contributing_paths: [] -children: [] + relevant_paths: [] +children: [] \ No newline at end of file diff --git a/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap b/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap index 89d44ecc..c3c1a929 100644 --- a/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap +++ b/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap @@ -8,5 +8,5 @@ class_name: ROOT properties: {} metadata: ignore_unknown_instances: false - contributing_paths: [] -children: [] + relevant_paths: [] +children: [] \ No newline at end of file diff --git a/src/snapshot/tests/snapshots/apply__remove_property_initial.snap b/src/snapshot/tests/snapshots/apply__remove_property_initial.snap index e7d7d8a1..0b1ecab5 100644 --- a/src/snapshot/tests/snapshots/apply__remove_property_initial.snap +++ b/src/snapshot/tests/snapshots/apply__remove_property_initial.snap @@ -11,5 +11,5 @@ properties: Value: Should be removed metadata: ignore_unknown_instances: false - contributing_paths: [] -children: [] + relevant_paths: [] +children: [] \ No newline at end of file diff --git a/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap b/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap index 80941bda..17045e2d 100644 --- a/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap +++ b/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap @@ -8,5 +8,5 @@ class_name: Folder properties: {} metadata: ignore_unknown_instances: false - contributing_paths: [] -children: [] + relevant_paths: [] +children: [] \ No newline at end of file diff --git a/src/snapshot/tests/snapshots/compute__add_child.snap b/src/snapshot/tests/snapshots/compute__add_child.snap index 48699fdc..54f3d076 100644 --- a/src/snapshot/tests/snapshots/compute__add_child.snap +++ b/src/snapshot/tests/snapshots/compute__add_child.snap @@ -9,9 +9,9 @@ added_instances: snapshot_id: ~ metadata: ignore_unknown_instances: false - contributing_paths: [] + relevant_paths: [] name: New class_name: Folder properties: {} children: [] -updated_instances: [] +updated_instances: [] \ No newline at end of file diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index bc29dbaa..baafe32a 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -113,12 +113,12 @@ impl RojoTree { // If this instance's source path changed, we need to update our // path associations so that file changes will trigger updates // to this instance correctly. - if existing_metadata.contributing_paths != metadata.contributing_paths { - for existing_path in &existing_metadata.contributing_paths { + if existing_metadata.relevant_paths != metadata.relevant_paths { + for existing_path in &existing_metadata.relevant_paths { self.path_to_ids.remove(existing_path, id); } - for new_path in &metadata.contributing_paths { + for new_path in &metadata.relevant_paths { self.path_to_ids.insert(new_path.clone(), id); } } @@ -147,7 +147,7 @@ impl RojoTree { } fn insert_metadata(&mut self, id: RbxId, metadata: InstanceMetadata) { - for path in &metadata.contributing_paths { + for path in &metadata.relevant_paths { self.path_to_ids.insert(path.clone(), id); } @@ -164,7 +164,7 @@ impl RojoTree { ) { let metadata = self.metadata_map.remove(&id).unwrap(); - for path in &metadata.contributing_paths { + for path in &metadata.relevant_paths { self.path_to_ids.remove(path, id); path_to_ids.insert(path.clone(), id); } diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 29a07b59..ccdf4bb2 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -40,7 +40,7 @@ impl SnapshotMiddleware for SnapshotCsv { Ok(Some(InstanceSnapshot { snapshot_id: None, metadata: InstanceMetadata { - contributing_paths: vec![entry.path().to_path_buf()], + relevant_paths: vec![entry.path().to_path_buf()], ..Default::default() }, name: Cow::Owned(instance_name), diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 04b566c4..0d7faf66 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -44,7 +44,7 @@ impl SnapshotMiddleware for SnapshotDir { Ok(Some(InstanceSnapshot { snapshot_id: None, metadata: InstanceMetadata { - contributing_paths: vec![entry.path().to_path_buf()], + relevant_paths: vec![entry.path().to_path_buf()], ..Default::default() }, name: Cow::Owned(instance_name), diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 8fc41d3b..c7e528f7 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -52,7 +52,7 @@ impl SnapshotMiddleware for SnapshotJsonModel { let mut snapshot = instance.core.into_snapshot(instance_name); - snapshot.metadata.contributing_paths = vec![entry.path().to_path_buf()]; + snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; Ok(Some(snapshot)) } diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 77ece285..758a0872 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -91,7 +91,7 @@ fn snapshot_lua_file( Ok(Some(InstanceSnapshot { snapshot_id: None, metadata: InstanceMetadata { - contributing_paths: vec![entry.path().to_path_buf()], + relevant_paths: vec![entry.path().to_path_buf()], ..Default::default() }, name: Cow::Owned(instance_name.to_owned()), diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 37b357b0..ac3106a6 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -31,9 +31,9 @@ impl SnapshotMiddleware for SnapshotProject { Err(ref err) if err.kind() == FsErrorKind::NotFound => {} Err(err) => return Err(err), - // TODO: Do we need to muck with the contributing paths if we're - // a project file within a folder? Should the folder path be the - // contributing path instead of the project file path? + // TODO: Do we need to muck with the relevant paths if we're a + // project file within a folder? Should the folder path be the + // relevant path instead of the project file path? Ok(entry) => return SnapshotProject::from_imfs(imfs, &entry), } } @@ -57,12 +57,12 @@ impl SnapshotMiddleware for SnapshotProject { // file and not the snapshot's original instigating path, or else we // won't pick up new changes from the project file. // - // We SHOULD NOT mark the project file as a contributing path for any + // We SHOULD NOT mark the project file as a relevant path for any // nodes that aren't roots. They'll be updated as part of the project // file being updated. snapshot .metadata - .contributing_paths + .relevant_paths .push(entry.path().to_path_buf()); Ok(Some(snapshot)) diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index 9408aa74..406ea11c 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -43,7 +43,7 @@ impl SnapshotMiddleware for SnapshotRbxlx { let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, root_id); snapshot.name = Cow::Owned(instance_name); - snapshot.metadata.contributing_paths = vec![entry.path().to_path_buf()]; + snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; Ok(Some(snapshot)) } diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 02e13ad9..7744820a 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -49,7 +49,7 @@ impl SnapshotMiddleware for SnapshotRbxm { if children.len() == 1 { let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); snapshot.name = Cow::Owned(instance_name); - snapshot.metadata.contributing_paths = vec![entry.path().to_path_buf()]; + snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; Ok(Some(snapshot)) } else { diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index fbea42f8..0aebe6a6 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -45,7 +45,7 @@ impl SnapshotMiddleware for SnapshotRbxmx { if children.len() == 1 { let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); snapshot.name = Cow::Owned(instance_name); - snapshot.metadata.contributing_paths = vec![entry.path().to_path_buf()]; + snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; Ok(Some(snapshot)) } else { diff --git a/src/snapshot_middleware/snapshots/test__client_from_imfs.snap b/src/snapshot_middleware/snapshots/test__client_from_imfs.snap index 8b6b2ebb..b844fef9 100644 --- a/src/snapshot_middleware/snapshots/test__client_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__client_from_imfs.snap @@ -5,7 +5,7 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false - contributing_paths: + relevant_paths: - /foo.client.lua name: foo class_name: LocalScript @@ -13,4 +13,4 @@ properties: Source: Type: String Value: Hello there! -children: [] +children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap b/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap index e2d4df4b..444aec8f 100644 --- a/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap @@ -5,7 +5,7 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false - contributing_paths: + relevant_paths: - /foo.csv name: foo class_name: LocalizationTable @@ -13,4 +13,4 @@ properties: Contents: Type: String Value: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" -children: [] +children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__empty_folder.snap b/src/snapshot_middleware/snapshots/test__empty_folder.snap index 36a0eb13..f57dade1 100644 --- a/src/snapshot_middleware/snapshots/test__empty_folder.snap +++ b/src/snapshot_middleware/snapshots/test__empty_folder.snap @@ -5,9 +5,9 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false - contributing_paths: + relevant_paths: - /foo name: foo class_name: Folder properties: {} -children: [] +children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap index 7f01fbdc..6682d35f 100644 --- a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap +++ b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap @@ -5,7 +5,7 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false - contributing_paths: + relevant_paths: - /foo name: foo class_name: Folder @@ -14,9 +14,9 @@ children: - snapshot_id: ~ metadata: ignore_unknown_instances: false - contributing_paths: + relevant_paths: - /foo/Child name: Child class_name: Folder properties: {} - children: [] + children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap b/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap index 45e26d09..902efa80 100644 --- a/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap @@ -5,7 +5,7 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false - contributing_paths: + relevant_paths: - /foo.txt name: foo class_name: StringValue @@ -13,4 +13,4 @@ properties: Value: Type: String Value: Hello there! -children: [] +children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__model_from_imfs.snap b/src/snapshot_middleware/snapshots/test__model_from_imfs.snap index 1d2ff82d..4828e278 100644 --- a/src/snapshot_middleware/snapshots/test__model_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__model_from_imfs.snap @@ -5,7 +5,7 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false - contributing_paths: + relevant_paths: - /foo.model.json name: foo class_name: IntValue @@ -17,8 +17,8 @@ children: - snapshot_id: ~ metadata: ignore_unknown_instances: false - contributing_paths: [] + relevant_paths: [] name: The Child class_name: StringValue properties: {} - children: [] + children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__module_from_imfs.snap b/src/snapshot_middleware/snapshots/test__module_from_imfs.snap index 0d036205..ccc9b320 100644 --- a/src/snapshot_middleware/snapshots/test__module_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__module_from_imfs.snap @@ -5,7 +5,7 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false - contributing_paths: + relevant_paths: - /foo.lua name: foo class_name: ModuleScript @@ -13,4 +13,4 @@ properties: Source: Type: String Value: Hello there! -children: [] +children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap b/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap index 19350c7d..3e4c5d40 100644 --- a/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap +++ b/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap @@ -5,9 +5,9 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true - contributing_paths: + relevant_paths: - /foo/hello.project.json name: direct-project class_name: Model properties: {} -children: [] +children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__project_from_folder.snap b/src/snapshot_middleware/snapshots/test__project_from_folder.snap index ee08d8a4..8b7935ab 100644 --- a/src/snapshot_middleware/snapshots/test__project_from_folder.snap +++ b/src/snapshot_middleware/snapshots/test__project_from_folder.snap @@ -5,9 +5,9 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true - contributing_paths: + relevant_paths: - /foo/default.project.json name: indirect-project class_name: Folder properties: {} -children: [] +children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap b/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap index 086c55c3..5c367846 100644 --- a/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap +++ b/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap @@ -5,7 +5,7 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true - contributing_paths: + relevant_paths: - /foo/other.project.json - /foo/default.project.json name: path-property-override @@ -14,4 +14,4 @@ properties: Value: Type: String Value: Changed -children: [] +children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_children.snap index 7d489305..f3270e67 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_children.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_children.snap @@ -5,7 +5,7 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true - contributing_paths: + relevant_paths: - /foo/default.project.json name: children class_name: Folder @@ -14,8 +14,8 @@ children: - snapshot_id: ~ metadata: ignore_unknown_instances: true - contributing_paths: [] + relevant_paths: [] name: Child class_name: Model properties: {} - children: [] + children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap index 00984eeb..d3d51a0d 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap @@ -5,10 +5,10 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true - contributing_paths: + relevant_paths: - /foo/other.project.json - /foo/default.project.json name: path-project class_name: Model properties: {} -children: [] +children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap index 374dbfe5..199b2129 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap @@ -5,7 +5,7 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true - contributing_paths: + relevant_paths: - /foo/other.project.json - /foo/default.project.json name: path-child-project @@ -15,8 +15,8 @@ children: - snapshot_id: ~ metadata: ignore_unknown_instances: true - contributing_paths: [] + relevant_paths: [] name: SomeChild class_name: Model properties: {} - children: [] + children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap index 5e3ff432..48e0fae5 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap @@ -5,7 +5,7 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false - contributing_paths: + relevant_paths: - /foo/other.txt - /foo/default.project.json name: path-project @@ -14,4 +14,4 @@ properties: Value: Type: String Value: "Hello, world!" -children: [] +children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap b/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap index 49e4d4f7..27a3c724 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap @@ -5,7 +5,7 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true - contributing_paths: + relevant_paths: - /foo/default.project.json name: resolved-properties class_name: StringValue @@ -13,4 +13,4 @@ properties: Value: Type: String Value: "Hello, world!" -children: [] +children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap b/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap index adbd6e94..98f76032 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap @@ -5,7 +5,7 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true - contributing_paths: + relevant_paths: - /foo/default.project.json name: unresolved-properties class_name: StringValue @@ -13,4 +13,4 @@ properties: Value: Type: String Value: Hi! -children: [] +children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/snapshots/test__server_from_imfs.snap b/src/snapshot_middleware/snapshots/test__server_from_imfs.snap index 02dc90cd..069017e7 100644 --- a/src/snapshot_middleware/snapshots/test__server_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__server_from_imfs.snap @@ -5,7 +5,7 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false - contributing_paths: + relevant_paths: - /foo.server.lua name: foo class_name: Script @@ -13,4 +13,4 @@ properties: Source: Type: String Value: Hello there! -children: [] +children: [] \ No newline at end of file diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 4f085641..673de4d7 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -52,7 +52,7 @@ impl SnapshotMiddleware for SnapshotTxt { Ok(Some(InstanceSnapshot { snapshot_id: None, metadata: InstanceMetadata { - contributing_paths: vec![entry.path().to_path_buf()], + relevant_paths: vec![entry.path().to_path_buf()], ..Default::default() }, name: Cow::Owned(instance_name), diff --git a/src/web/ui.rs b/src/web/ui.rs index 9b1a7f5e..04d01638 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -248,17 +248,17 @@ impl UiService { let metadata_container = { let metadata = instance.metadata(); - let contributing_paths = if metadata.contributing_paths.is_empty() { + let relevant_paths = if metadata.relevant_paths.is_empty() { HtmlContent::None } else { let list = metadata - .contributing_paths + .relevant_paths .iter() .map(|path| html! {
  • { format!("{}", path.display()) }
  • }); html! {
    - "contributing_paths: " + "relevant_paths: "
      { Fragment::new(list) }
    } @@ -268,7 +268,7 @@ impl UiService { <>
    "ignore_unknown_instances: " { metadata.ignore_unknown_instances.to_string() }
    "instigating source: " { format!("{:?}", metadata.instigating_source) }
    - { contributing_paths } + { relevant_paths } }; From 956d7e091893253dbb031297e1015153fa99fb43 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Oct 2019 17:52:05 -0700 Subject: [PATCH 0784/1504] Fix warning in JSON model snapshot test --- src/snapshot_middleware/json_model.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index c7e528f7..4eed7cfd 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -136,8 +136,6 @@ mod test { use super::*; use insta::assert_yaml_snapshot; - use maplit::hashmap; - use rbx_dom_weak::RbxValue; use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; From c051153a1f60f6d8ee22ee47d02169e10b28ace7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Oct 2019 18:05:27 -0700 Subject: [PATCH 0785/1504] Mark project file as instigating source for top-level instances --- src/snapshot_middleware/project.rs | 17 ++++++++++++----- .../test__project_from_direct_file.snap | 4 +++- .../snapshots/test__project_from_folder.snap | 4 +++- .../test__project_path_property_overrides.snap | 4 +++- .../snapshots/test__project_with_children.snap | 4 +++- .../test__project_with_path_to_project.snap | 4 +++- ...ject_with_path_to_project_with_children.snap | 4 +++- .../test__project_with_path_to_txt.snap | 4 +++- .../test__project_with_resolved_properties.snap | 4 +++- ...est__project_with_unresolved_properties.snap | 4 +++- 10 files changed, 39 insertions(+), 14 deletions(-) diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index ac3106a6..a0b5d6aa 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -51,11 +51,18 @@ impl SnapshotMiddleware for SnapshotProject { // unwrap is safe. let mut snapshot = snapshot_project_node(&project.name, &project.tree, imfs)?.unwrap(); - // If the project file updates, we want to trigger a snapshot of the - // entire project tree. We're overwriting the "instigating path" for the - // root instance of the project, since we want to snapshot the project - // file and not the snapshot's original instigating path, or else we - // won't pick up new changes from the project file. + // Setting the instigating source to the project file path is a little + // coarse. + // + // Ideally, we'd only snapshot the project file if the project file + // actually changed. Because Rojo only has the concept of one + // relevant path -> snapshot path mapping per instance, we pick the more + // conservative approach of snapshotting the project file if any + // relevant paths changed. + snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); + + // Mark this snapshot (the root node of the project file) as being + // related to the project file. // // We SHOULD NOT mark the project file as a relevant path for any // nodes that aren't roots. They'll be updated as part of the project diff --git a/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap b/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap index 3e4c5d40..1d4f7009 100644 --- a/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap +++ b/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap @@ -5,9 +5,11 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true + instigating_source: + Path: /foo/hello.project.json relevant_paths: - /foo/hello.project.json name: direct-project class_name: Model properties: {} -children: [] \ No newline at end of file +children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_from_folder.snap b/src/snapshot_middleware/snapshots/test__project_from_folder.snap index 8b7935ab..d8417c62 100644 --- a/src/snapshot_middleware/snapshots/test__project_from_folder.snap +++ b/src/snapshot_middleware/snapshots/test__project_from_folder.snap @@ -5,9 +5,11 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true + instigating_source: + Path: /foo/default.project.json relevant_paths: - /foo/default.project.json name: indirect-project class_name: Folder properties: {} -children: [] \ No newline at end of file +children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap b/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap index 5c367846..ee98a5c6 100644 --- a/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap +++ b/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap @@ -5,6 +5,8 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true + instigating_source: + Path: /foo/default.project.json relevant_paths: - /foo/other.project.json - /foo/default.project.json @@ -14,4 +16,4 @@ properties: Value: Type: String Value: Changed -children: [] \ No newline at end of file +children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_children.snap index f3270e67..b6329a43 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_children.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_children.snap @@ -5,6 +5,8 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true + instigating_source: + Path: /foo/default.project.json relevant_paths: - /foo/default.project.json name: children @@ -18,4 +20,4 @@ children: name: Child class_name: Model properties: {} - children: [] \ No newline at end of file + children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap index d3d51a0d..406b0b61 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap @@ -5,10 +5,12 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true + instigating_source: + Path: /foo/default.project.json relevant_paths: - /foo/other.project.json - /foo/default.project.json name: path-project class_name: Model properties: {} -children: [] \ No newline at end of file +children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap index 199b2129..e0ffbefd 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap @@ -5,6 +5,8 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true + instigating_source: + Path: /foo/default.project.json relevant_paths: - /foo/other.project.json - /foo/default.project.json @@ -19,4 +21,4 @@ children: name: SomeChild class_name: Model properties: {} - children: [] \ No newline at end of file + children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap index 48e0fae5..de80caa4 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap @@ -5,6 +5,8 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false + instigating_source: + Path: /foo/default.project.json relevant_paths: - /foo/other.txt - /foo/default.project.json @@ -14,4 +16,4 @@ properties: Value: Type: String Value: "Hello, world!" -children: [] \ No newline at end of file +children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap b/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap index 27a3c724..96194799 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap @@ -5,6 +5,8 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true + instigating_source: + Path: /foo/default.project.json relevant_paths: - /foo/default.project.json name: resolved-properties @@ -13,4 +15,4 @@ properties: Value: Type: String Value: "Hello, world!" -children: [] \ No newline at end of file +children: [] diff --git a/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap b/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap index 98f76032..383d0746 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap @@ -5,6 +5,8 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: true + instigating_source: + Path: /foo/default.project.json relevant_paths: - /foo/default.project.json name: unresolved-properties @@ -13,4 +15,4 @@ properties: Value: Type: String Value: Hi! -children: [] \ No newline at end of file +children: [] From cb3211cf4602eb47d5a2aa113ac1d7b56ca8cf42 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Oct 2019 18:10:45 -0700 Subject: [PATCH 0786/1504] Mark project node as instigating source for instances from project --- src/snapshot_middleware/project.rs | 7 ++++++- .../snapshots/test__project_with_children.snap | 8 ++++++++ .../test__project_with_path_to_project_with_children.snap | 8 ++++++++ 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index a0b5d6aa..4ea7b267 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -6,7 +6,7 @@ use rbx_reflection::try_resolve_value; use crate::{ imfs::{FsErrorKind, Imfs, ImfsEntry, ImfsFetcher}, project::{Project, ProjectNode}, - snapshot::{InstanceMetadata, InstanceSnapshot}, + snapshot::{InstanceMetadata, InstanceSnapshot, InstigatingSource}, }; use super::{ @@ -174,6 +174,11 @@ fn snapshot_project_node( metadata.ignore_unknown_instances = true; } + metadata.instigating_source = Some(InstigatingSource::ProjectNode( + instance_name.to_string(), + node.clone(), + )); + Ok(Some(InstanceSnapshot { snapshot_id: None, name, diff --git a/src/snapshot_middleware/snapshots/test__project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_children.snap index b6329a43..1893e242 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_children.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_children.snap @@ -16,6 +16,14 @@ children: - snapshot_id: ~ metadata: ignore_unknown_instances: true + instigating_source: + ProjectNode: + - Child + - class_name: Model + children: {} + properties: {} + ignore_unknown_instances: ~ + path: ~ relevant_paths: [] name: Child class_name: Model diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap index e0ffbefd..06fca8b6 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap @@ -17,6 +17,14 @@ children: - snapshot_id: ~ metadata: ignore_unknown_instances: true + instigating_source: + ProjectNode: + - SomeChild + - class_name: Model + children: {} + properties: {} + ignore_unknown_instances: ~ + path: ~ relevant_paths: [] name: SomeChild class_name: Model From 98519da7d9341e1de368aab240c32ac5a246abe6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 4 Oct 2019 18:36:04 -0700 Subject: [PATCH 0787/1504] Reintroduce instigating paths for snapshot middleware --- src/change_processor.rs | 4 ++-- src/snapshot_middleware/csv.rs | 1 + src/snapshot_middleware/dir.rs | 1 + src/snapshot_middleware/json_model.rs | 1 + src/snapshot_middleware/lua.rs | 1 + src/snapshot_middleware/rbxlx.rs | 1 + src/snapshot_middleware/rbxm.rs | 1 + src/snapshot_middleware/rbxmx.rs | 1 + .../snapshots/test__client_from_imfs.snap | 4 +++- src/snapshot_middleware/snapshots/test__csv_from_imfs.snap | 4 +++- src/snapshot_middleware/snapshots/test__empty_folder.snap | 4 +++- .../snapshots/test__folder_in_folder.snap | 6 +++++- .../snapshots/test__instance_from_imfs.snap | 4 +++- .../snapshots/test__model_from_imfs.snap | 4 +++- .../snapshots/test__module_from_imfs.snap | 4 +++- .../snapshots/test__server_from_imfs.snap | 4 +++- src/snapshot_middleware/txt.rs | 1 + 17 files changed, 36 insertions(+), 10 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index 7bb5b382..533a982c 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -94,9 +94,9 @@ impl ChangeProcessor { }; let snapshot = match instigating_source { - InstigatingSource::Path(instigating_path) => { + InstigatingSource::Path(path) => { let entry = imfs - .get(instigating_path) + .get(path) .expect("could not get instigating path from filesystem"); let snapshot = snapshot_from_imfs(&mut imfs, &entry) diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index ccdf4bb2..17837667 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -40,6 +40,7 @@ impl SnapshotMiddleware for SnapshotCsv { Ok(Some(InstanceSnapshot { snapshot_id: None, metadata: InstanceMetadata { + instigating_source: Some(entry.path().to_path_buf().into()), relevant_paths: vec![entry.path().to_path_buf()], ..Default::default() }, diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 0d7faf66..9c365594 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -44,6 +44,7 @@ impl SnapshotMiddleware for SnapshotDir { Ok(Some(InstanceSnapshot { snapshot_id: None, metadata: InstanceMetadata { + instigating_source: Some(entry.path().to_path_buf().into()), relevant_paths: vec![entry.path().to_path_buf()], ..Default::default() }, diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 4eed7cfd..5b8834b4 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -52,6 +52,7 @@ impl SnapshotMiddleware for SnapshotJsonModel { let mut snapshot = instance.core.into_snapshot(instance_name); + snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; Ok(Some(snapshot)) diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 758a0872..d60ee4b9 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -91,6 +91,7 @@ fn snapshot_lua_file( Ok(Some(InstanceSnapshot { snapshot_id: None, metadata: InstanceMetadata { + instigating_source: Some(entry.path().to_path_buf().into()), relevant_paths: vec![entry.path().to_path_buf()], ..Default::default() }, diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index 406ea11c..334b7d68 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -43,6 +43,7 @@ impl SnapshotMiddleware for SnapshotRbxlx { let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, root_id); snapshot.name = Cow::Owned(instance_name); + snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; Ok(Some(snapshot)) diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 7744820a..f97ed19f 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -49,6 +49,7 @@ impl SnapshotMiddleware for SnapshotRbxm { if children.len() == 1 { let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); snapshot.name = Cow::Owned(instance_name); + snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; Ok(Some(snapshot)) diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 0aebe6a6..51ef1ed4 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -45,6 +45,7 @@ impl SnapshotMiddleware for SnapshotRbxmx { if children.len() == 1 { let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); snapshot.name = Cow::Owned(instance_name); + snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; Ok(Some(snapshot)) diff --git a/src/snapshot_middleware/snapshots/test__client_from_imfs.snap b/src/snapshot_middleware/snapshots/test__client_from_imfs.snap index b844fef9..35ef40fb 100644 --- a/src/snapshot_middleware/snapshots/test__client_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__client_from_imfs.snap @@ -5,6 +5,8 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false + instigating_source: + Path: /foo.client.lua relevant_paths: - /foo.client.lua name: foo @@ -13,4 +15,4 @@ properties: Source: Type: String Value: Hello there! -children: [] \ No newline at end of file +children: [] diff --git a/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap b/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap index 444aec8f..84a1cadc 100644 --- a/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap @@ -5,6 +5,8 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false + instigating_source: + Path: /foo.csv relevant_paths: - /foo.csv name: foo @@ -13,4 +15,4 @@ properties: Contents: Type: String Value: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" -children: [] \ No newline at end of file +children: [] diff --git a/src/snapshot_middleware/snapshots/test__empty_folder.snap b/src/snapshot_middleware/snapshots/test__empty_folder.snap index f57dade1..c08cb8c1 100644 --- a/src/snapshot_middleware/snapshots/test__empty_folder.snap +++ b/src/snapshot_middleware/snapshots/test__empty_folder.snap @@ -5,9 +5,11 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false + instigating_source: + Path: /foo relevant_paths: - /foo name: foo class_name: Folder properties: {} -children: [] \ No newline at end of file +children: [] diff --git a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap index 6682d35f..dafc369a 100644 --- a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap +++ b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap @@ -5,6 +5,8 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false + instigating_source: + Path: /foo relevant_paths: - /foo name: foo @@ -14,9 +16,11 @@ children: - snapshot_id: ~ metadata: ignore_unknown_instances: false + instigating_source: + Path: /foo/Child relevant_paths: - /foo/Child name: Child class_name: Folder properties: {} - children: [] \ No newline at end of file + children: [] diff --git a/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap b/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap index 902efa80..0dcac5ac 100644 --- a/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap @@ -5,6 +5,8 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false + instigating_source: + Path: /foo.txt relevant_paths: - /foo.txt name: foo @@ -13,4 +15,4 @@ properties: Value: Type: String Value: Hello there! -children: [] \ No newline at end of file +children: [] diff --git a/src/snapshot_middleware/snapshots/test__model_from_imfs.snap b/src/snapshot_middleware/snapshots/test__model_from_imfs.snap index 4828e278..a18082b6 100644 --- a/src/snapshot_middleware/snapshots/test__model_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__model_from_imfs.snap @@ -5,6 +5,8 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false + instigating_source: + Path: /foo.model.json relevant_paths: - /foo.model.json name: foo @@ -21,4 +23,4 @@ children: name: The Child class_name: StringValue properties: {} - children: [] \ No newline at end of file + children: [] diff --git a/src/snapshot_middleware/snapshots/test__module_from_imfs.snap b/src/snapshot_middleware/snapshots/test__module_from_imfs.snap index ccc9b320..3ad3d835 100644 --- a/src/snapshot_middleware/snapshots/test__module_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__module_from_imfs.snap @@ -5,6 +5,8 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false + instigating_source: + Path: /foo.lua relevant_paths: - /foo.lua name: foo @@ -13,4 +15,4 @@ properties: Source: Type: String Value: Hello there! -children: [] \ No newline at end of file +children: [] diff --git a/src/snapshot_middleware/snapshots/test__server_from_imfs.snap b/src/snapshot_middleware/snapshots/test__server_from_imfs.snap index 069017e7..3c9c0070 100644 --- a/src/snapshot_middleware/snapshots/test__server_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__server_from_imfs.snap @@ -5,6 +5,8 @@ expression: instance_snapshot snapshot_id: ~ metadata: ignore_unknown_instances: false + instigating_source: + Path: /foo.server.lua relevant_paths: - /foo.server.lua name: foo @@ -13,4 +15,4 @@ properties: Source: Type: String Value: Hello there! -children: [] \ No newline at end of file +children: [] diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 673de4d7..19906ca9 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -52,6 +52,7 @@ impl SnapshotMiddleware for SnapshotTxt { Ok(Some(InstanceSnapshot { snapshot_id: None, metadata: InstanceMetadata { + instigating_source: Some(entry.path().to_path_buf().into()), relevant_paths: vec![entry.path().to_path_buf()], ..Default::default() }, From f830b024d56d0b3f653bfdade72c9d3f6e819cfd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 7 Oct 2019 16:20:04 -0700 Subject: [PATCH 0788/1504] Add ImfsSnapshot::empty_dir() for debugging the Imfs --- src/imfs/snapshot.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/imfs/snapshot.rs b/src/imfs/snapshot.rs index 3f12e519..cc2cfff2 100644 --- a/src/imfs/snapshot.rs +++ b/src/imfs/snapshot.rs @@ -23,6 +23,12 @@ impl ImfsSnapshot { ImfsSnapshot::Directory(DirectorySnapshot { children }) } + + pub fn empty_dir() -> ImfsSnapshot { + ImfsSnapshot::Directory(DirectorySnapshot { + children: Default::default(), + }) + } } #[derive(Debug, Clone)] From e60be94be04646fa64c3b3ea5576f15272a4bb24 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 7 Oct 2019 16:21:25 -0700 Subject: [PATCH 0789/1504] Move patch apply test utility into tree_view module --- Cargo.lock | 1 + Cargo.toml | 1 + src/lib.rs | 3 ++ src/snapshot/tests/apply.rs | 69 ++++++++----------------------------- src/tree_view.rs | 56 ++++++++++++++++++++++++++++++ 5 files changed, 76 insertions(+), 54 deletions(-) create mode 100644 src/tree_view.rs diff --git a/Cargo.lock b/Cargo.lock index 56c7d7f6..2a03d2dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1470,6 +1470,7 @@ dependencies = [ "rojo-insta-ext 0.1.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 81bdd960..5f4a77be 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,6 +72,7 @@ rojo-insta-ext = { path = "rojo-insta-ext" } lazy_static = "1.2" paste = "0.1" pretty_assertions = "0.6.1" +serde_yaml = "0.8.9" tempfile = "3.0" walkdir = "2.1" diff --git a/src/lib.rs b/src/lib.rs index a8999ccc..0ae30678 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -12,6 +12,9 @@ pub mod commands; #[doc(hidden)] pub mod project; +#[cfg(test)] +mod tree_view; + mod auth_cookie; mod change_processor; mod imfs; diff --git a/src/snapshot/tests/apply.rs b/src/snapshot/tests/apply.rs index d36d6538..d9bb0753 100644 --- a/src/snapshot/tests/apply.rs +++ b/src/snapshot/tests/apply.rs @@ -1,14 +1,12 @@ -use std::collections::HashMap; - use insta::assert_yaml_snapshot; use maplit::hashmap; -use rbx_dom_weak::{RbxId, RbxInstanceProperties, RbxValue}; -use serde::Serialize; +use rbx_dom_weak::{RbxInstanceProperties, RbxValue}; use rojo_insta_ext::RedactionMap; -use crate::snapshot::{ - apply_patch_set, InstanceMetadata, InstancePropertiesWithMeta, PatchSet, PatchUpdate, RojoTree, +use crate::{ + snapshot::{apply_patch_set, InstancePropertiesWithMeta, PatchSet, PatchUpdate, RojoTree}, + tree_view::{intern_tree, view_tree}, }; #[test] @@ -16,7 +14,7 @@ fn set_name_and_class_name() { let mut redactions = RedactionMap::new(); let mut tree = empty_tree(); - redactions.intern(tree.get_root_id()); + intern_tree(&tree, &mut redactions); let patch_set = PatchSet { updated_instances: vec![PatchUpdate { @@ -31,9 +29,8 @@ fn set_name_and_class_name() { let applied_patch_set = apply_patch_set(&mut tree, patch_set); - let tree_view = view_tree(&tree); - let tree_value = redactions.redacted_yaml(tree_view); - assert_yaml_snapshot!(tree_value); + let tree_view = view_tree(&tree, &mut redactions); + assert_yaml_snapshot!(tree_view); let applied_patch_value = redactions.redacted_yaml(applied_patch_set); assert_yaml_snapshot!(applied_patch_value); @@ -44,7 +41,7 @@ fn add_property() { let mut redactions = RedactionMap::new(); let mut tree = empty_tree(); - redactions.intern(tree.get_root_id()); + intern_tree(&tree, &mut redactions); let patch_set = PatchSet { updated_instances: vec![PatchUpdate { @@ -63,9 +60,8 @@ fn add_property() { let applied_patch_set = apply_patch_set(&mut tree, patch_set); - let tree_view = view_tree(&tree); - let tree_value = redactions.redacted_yaml(tree_view); - assert_yaml_snapshot!(tree_value); + let tree_view = view_tree(&tree, &mut redactions); + assert_yaml_snapshot!(tree_view); let applied_patch_value = redactions.redacted_yaml(applied_patch_set); assert_yaml_snapshot!(applied_patch_value); @@ -76,7 +72,7 @@ fn remove_property() { let mut redactions = RedactionMap::new(); let mut tree = empty_tree(); - redactions.intern(tree.get_root_id()); + intern_tree(&tree, &mut redactions); { let root_id = tree.get_root_id(); @@ -90,9 +86,8 @@ fn remove_property() { ); } - let tree_view = view_tree(&tree); - let tree_value = redactions.redacted_yaml(tree_view); - assert_yaml_snapshot!("remove_property_initial", tree_value); + let tree_view = view_tree(&tree, &mut redactions); + assert_yaml_snapshot!("remove_property_initial", tree_view); let patch_set = PatchSet { updated_instances: vec![PatchUpdate { @@ -109,9 +104,8 @@ fn remove_property() { let applied_patch_set = apply_patch_set(&mut tree, patch_set); - let tree_view = view_tree(&tree); - let tree_value = redactions.redacted_yaml(tree_view); - assert_yaml_snapshot!("remove_property_after_patch", tree_value); + let tree_view = view_tree(&tree, &mut redactions); + assert_yaml_snapshot!("remove_property_after_patch", tree_view); let applied_patch_value = redactions.redacted_yaml(applied_patch_set); assert_yaml_snapshot!("remove_property_appied_patch", applied_patch_value); @@ -127,36 +121,3 @@ fn empty_tree() -> RojoTree { metadata: Default::default(), }) } - -/// Copy of data from RojoTree in the right shape to have useful snapshots. -#[derive(Debug, Serialize)] -struct InstanceView { - id: RbxId, - name: String, - class_name: String, - properties: HashMap, - metadata: InstanceMetadata, - children: Vec, -} - -fn view_tree(tree: &RojoTree) -> InstanceView { - view_instance(tree, tree.get_root_id()) -} - -fn view_instance(tree: &RojoTree, id: RbxId) -> InstanceView { - let instance = tree.get_instance(id).unwrap(); - - InstanceView { - id: instance.id(), - name: instance.name().to_owned(), - class_name: instance.class_name().to_owned(), - properties: instance.properties().clone(), - metadata: instance.metadata().clone(), - children: instance - .children() - .iter() - .copied() - .map(|id| view_instance(tree, id)) - .collect(), - } -} diff --git a/src/tree_view.rs b/src/tree_view.rs new file mode 100644 index 00000000..a55e7e92 --- /dev/null +++ b/src/tree_view.rs @@ -0,0 +1,56 @@ +use std::collections::HashMap; + +use rbx_dom_weak::{RbxId, RbxValue}; +use rojo_insta_ext::RedactionMap; +use serde::Serialize; + +use crate::snapshot::{InstanceMetadata, RojoTree}; + +/// Adds the given Rojo tree into the redaction map and produces a redacted +/// copy that can be immediately fed to one of Insta's snapshot macros like +/// `assert_snapshot_yaml`. +pub fn view_tree(tree: &RojoTree, redactions: &mut RedactionMap) -> serde_yaml::Value { + intern_tree(tree, redactions); + + let view = extract_instance_view(tree, tree.get_root_id()); + redactions.redacted_yaml(view) +} + +/// Adds the given Rojo tree into the redaction map. +pub fn intern_tree(tree: &RojoTree, redactions: &mut RedactionMap) { + let root_id = tree.get_root_id(); + redactions.intern(root_id); + + for descendant in tree.descendants(root_id) { + redactions.intern(descendant.id()); + } +} + +/// Copy of data from RojoTree in the right shape to have useful snapshots. +#[derive(Debug, Serialize)] +struct InstanceView { + id: RbxId, + name: String, + class_name: String, + properties: HashMap, + metadata: InstanceMetadata, + children: Vec, +} + +fn extract_instance_view(tree: &RojoTree, id: RbxId) -> InstanceView { + let instance = tree.get_instance(id).unwrap(); + + InstanceView { + id: instance.id(), + name: instance.name().to_owned(), + class_name: instance.class_name().to_owned(), + properties: instance.properties().clone(), + metadata: instance.metadata().clone(), + children: instance + .children() + .iter() + .copied() + .map(|id| extract_instance_view(tree, id)) + .collect(), + } +} From ab6cedb659b464b58c8bd4319c2b29a1e0fadcb7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 7 Oct 2019 16:24:36 -0700 Subject: [PATCH 0790/1504] Move some serve code into serve_session.rs, start writing serve session tests --- src/commands/serve.rs | 31 ++----- src/serve_session.rs | 83 ++++++++++++++++++- src/snapshots/serve_session__just_folder.snap | 15 ++++ 3 files changed, 102 insertions(+), 27 deletions(-) create mode 100644 src/snapshots/serve_session__just_folder.snap diff --git a/src/commands/serve.rs b/src/commands/serve.rs index 04bf5a63..22c4a485 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -1,20 +1,16 @@ use std::{ - collections::HashMap, io::{self, Write}, path::PathBuf, sync::Arc, }; use failure::Fail; -use rbx_dom_weak::RbxInstanceProperties; use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; use crate::{ imfs::{Imfs, RealFetcher, WatchMode}, project::{Project, ProjectLoadError}, serve_session::ServeSession, - snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, - snapshot_middleware::snapshot_from_imfs, web::LiveServer, }; @@ -54,29 +50,14 @@ pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { let _ = show_start_message(port); - let mut tree = RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), - }, - metadata: Default::default(), - }); - let root_id = tree.get_root_id(); + let imfs = Imfs::new(RealFetcher::new(WatchMode::Enabled)); - let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Enabled)); - let entry = imfs - .get(&options.fuzzy_project_path) - .expect("could not get project path"); + let session = Arc::new(ServeSession::new( + imfs, + &options.fuzzy_project_path, + maybe_project, + )); - let snapshot = snapshot_from_imfs(&mut imfs, &entry) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); - - let patch_set = compute_patch_set(&snapshot, &tree, root_id); - apply_patch_set(&mut tree, patch_set); - - let session = Arc::new(ServeSession::new(imfs, tree, maybe_project)); let server = LiveServer::new(session); server.start(port); diff --git a/src/serve_session.rs b/src/serve_session.rs index 05ff0d93..54e23c5f 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -1,16 +1,22 @@ use std::{ collections::HashSet, + path::Path, sync::{Arc, Mutex, MutexGuard}, time::Instant, }; +use rbx_dom_weak::RbxInstanceProperties; + use crate::{ change_processor::ChangeProcessor, imfs::{Imfs, ImfsFetcher}, message_queue::MessageQueue, project::Project, session_id::SessionId, - snapshot::{AppliedPatchSet, RojoTree}, + snapshot::{ + apply_patch_set, compute_patch_set, AppliedPatchSet, InstancePropertiesWithMeta, RojoTree, + }, + snapshot_middleware::snapshot_from_imfs, }; /// Contains all of the state for a Rojo serve session. @@ -70,9 +76,52 @@ pub struct ServeSession { /// block to prevent needing to spread Send + Sync + 'static into everything /// that handles ServeSession. impl ServeSession { - pub fn new(imfs: Imfs, tree: RojoTree, root_project: Option) -> Self { + /// Start a new serve session from the given in-memory filesystem and start + /// path. + /// + /// The project file is expected to be loaded out-of-band since it's + /// currently loaded from the filesystem directly instead of through the + /// in-memory filesystem layer. + pub fn new>( + mut imfs: Imfs, + start_path: P, + root_project: Option, + ) -> Self { + let start_path = start_path.as_ref(); + + log::trace!( + "Starting new ServeSession at path {} with project {:#?}", + start_path.display(), + root_project + ); + let start_time = Instant::now(); + log::trace!("Constructing initial tree"); + let mut tree = RojoTree::new(InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "ROOT".to_owned(), + class_name: "Folder".to_owned(), + properties: Default::default(), + }, + metadata: Default::default(), + }); + let root_id = tree.get_root_id(); + + log::trace!("Loading start path: {}", start_path.display()); + let entry = imfs.get(start_path).expect("could not get project path"); + + log::trace!("Snapshotting start path"); + let snapshot = snapshot_from_imfs(&mut imfs, &entry) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + log::trace!("Computing initial patch set"); + let patch_set = compute_patch_set(&snapshot, &tree, root_id); + + log::trace!("Applying initial patch set"); + apply_patch_set(&mut tree, patch_set); + let session_id = SessionId::new(); let message_queue = MessageQueue::new(); @@ -80,6 +129,7 @@ impl ServeSession { let message_queue = Arc::new(message_queue); let imfs = Arc::new(Mutex::new(imfs)); + log::trace!("Starting ChangeProcessor"); let change_processor = ChangeProcessor::start( Arc::clone(&tree), Arc::clone(&message_queue), @@ -135,3 +185,32 @@ impl ServeSession { .and_then(|project| project.serve_place_ids.as_ref()) } } + +/// This module is named to trick Insta into naming the resulting snapshots +/// correctly. +/// +/// See https://github.com/mitsuhiko/insta/issues/78 +#[cfg(test)] +mod serve_session { + use super::*; + + use insta::assert_yaml_snapshot; + use rojo_insta_ext::RedactionMap; + + use crate::{ + imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}, + tree_view::view_tree, + }; + + #[test] + fn just_folder() { + let mut imfs = Imfs::new(NoopFetcher); + + imfs.debug_load_snapshot("/foo", ImfsSnapshot::empty_dir()); + + let session = ServeSession::new(imfs, "/foo", None); + + let mut rm = RedactionMap::new(); + assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); + } +} diff --git a/src/snapshots/serve_session__just_folder.snap b/src/snapshots/serve_session__just_folder.snap new file mode 100644 index 00000000..8a3a74e1 --- /dev/null +++ b/src/snapshots/serve_session__just_folder.snap @@ -0,0 +1,15 @@ +--- +source: src/serve_session.rs +expression: tree_value +--- +id: id-1 +name: foo +class_name: Folder +properties: {} +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /foo + relevant_paths: + - /foo +children: [] From 7b82e3d641f92c8086d6ad648d9668ed9df01db6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 7 Oct 2019 18:22:29 -0700 Subject: [PATCH 0791/1504] Add TestFetcher for mocking more filesystem operations than NoopFetcher --- src/imfs/mod.rs | 6 ++ src/imfs/test_fetcher.rs | 175 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 181 insertions(+) create mode 100644 src/imfs/test_fetcher.rs diff --git a/src/imfs/mod.rs b/src/imfs/mod.rs index e930e089..58f51719 100644 --- a/src/imfs/mod.rs +++ b/src/imfs/mod.rs @@ -13,3 +13,9 @@ pub use imfs::*; pub use noop_fetcher::*; pub use real_fetcher::*; pub use snapshot::*; + +#[cfg(test)] +mod test_fetcher; + +#[cfg(test)] +pub use test_fetcher::*; diff --git a/src/imfs/test_fetcher.rs b/src/imfs/test_fetcher.rs new file mode 100644 index 00000000..96936415 --- /dev/null +++ b/src/imfs/test_fetcher.rs @@ -0,0 +1,175 @@ +//! Implements the IMFS fetcher interface for a fake filesystem that can be +//! mutated and have changes signaled through it. +//! +//! This is useful for testing how things using Imfs react to changed events +//! without relying on the real filesystem implementation, which is very +//! platform-specific. + +// This interface is only used for testing, so it's okay if it isn't used. +#![allow(unused)] + +use std::{ + io, + path::{self, Path, PathBuf}, + sync::{Arc, Mutex}, +}; + +use crossbeam_channel::{unbounded, Receiver, Sender}; + +use crate::path_map::PathMap; + +use super::{ + event::ImfsEvent, + fetcher::{FileType, ImfsFetcher}, + snapshot::ImfsSnapshot, +}; + +#[derive(Clone)] +pub struct TestFetcherState { + inner: Arc>, +} + +impl TestFetcherState { + pub fn load_snapshot>(&self, path: P, snapshot: ImfsSnapshot) { + let mut inner = self.inner.lock().unwrap(); + inner.load_snapshot(path.as_ref().to_path_buf(), snapshot); + } + + pub fn remove>(&self, path: P) { + let mut inner = self.inner.lock().unwrap(); + inner.remove(path.as_ref()); + } + + pub fn raise_event(&self, event: ImfsEvent) { + let mut inner = self.inner.lock().unwrap(); + inner.raise_event(event); + } +} + +pub enum TestFetcherEntry { + File(Vec), + Dir, +} + +struct TestFetcherStateInner { + entries: PathMap, + sender: Sender, +} + +impl TestFetcherStateInner { + fn new(sender: Sender) -> Self { + let mut entries = PathMap::new(); + entries.insert(Path::new("/"), TestFetcherEntry::Dir); + + Self { sender, entries } + } + + fn load_snapshot(&mut self, path: PathBuf, snapshot: ImfsSnapshot) { + match snapshot { + ImfsSnapshot::File(file) => { + self.entries + .insert(path, TestFetcherEntry::File(file.contents)); + } + ImfsSnapshot::Directory(directory) => { + self.entries.insert(path.clone(), TestFetcherEntry::Dir); + + for (child_name, child) in directory.children.into_iter() { + self.load_snapshot(path.join(child_name), child); + } + } + } + } + + fn remove(&mut self, path: &Path) { + self.entries.remove(path); + } + + fn raise_event(&mut self, event: ImfsEvent) { + self.sender.send(event).unwrap(); + } +} + +pub struct TestFetcher { + state: TestFetcherState, + receiver: Receiver, +} + +impl TestFetcher { + pub fn new() -> (TestFetcherState, Self) { + let (sender, receiver) = unbounded(); + + let state = TestFetcherState { + inner: Arc::new(Mutex::new(TestFetcherStateInner::new(sender))), + }; + + (state.clone(), Self { receiver, state }) + } +} + +impl ImfsFetcher for TestFetcher { + fn file_type(&mut self, path: &Path) -> io::Result { + let inner = self.state.inner.lock().unwrap(); + + match inner.entries.get(path) { + Some(TestFetcherEntry::File(_)) => Ok(FileType::File), + Some(TestFetcherEntry::Dir) => Ok(FileType::Directory), + None => Err(io::Error::new(io::ErrorKind::NotFound, "Path not found")), + } + } + + fn read_children(&mut self, path: &Path) -> io::Result> { + let inner = self.state.inner.lock().unwrap(); + + Ok(inner + .entries + .children(path) + .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "Path not found"))? + .into_iter() + .map(|path| path.to_path_buf()) + .collect()) + } + + fn read_contents(&mut self, path: &Path) -> io::Result> { + let inner = self.state.inner.lock().unwrap(); + + let node = inner.entries.get(path); + + match node { + Some(TestFetcherEntry::File(contents)) => Ok(contents.clone()), + Some(TestFetcherEntry::Dir) => Err(io::Error::new( + io::ErrorKind::Other, + "Cannot read contents of a directory", + )), + None => Err(io::Error::new(io::ErrorKind::NotFound, "Path not found")), + } + } + + fn create_directory(&mut self, _path: &Path) -> io::Result<()> { + Err(io::Error::new( + io::ErrorKind::Other, + "TestFetcher is not mutable yet", + )) + } + + fn write_file(&mut self, _path: &Path, _contents: &[u8]) -> io::Result<()> { + Err(io::Error::new( + io::ErrorKind::Other, + "TestFetcher is not mutable yet", + )) + } + + fn remove(&mut self, _path: &Path) -> io::Result<()> { + Err(io::Error::new( + io::ErrorKind::Other, + "TestFetcher is not mutable yet", + )) + } + + fn watch(&mut self, _path: &Path) {} + + fn unwatch(&mut self, _path: &Path) {} + + fn receiver(&self) -> Receiver { + self.receiver.clone() + } +} From ffc146ff9b272637a9af8f4a9e9cf2fc733f1998 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 7 Oct 2019 18:23:39 -0700 Subject: [PATCH 0792/1504] Add ServeSession test for changing text file --- src/serve_session.rs | 26 ++++++++++++++++++- .../serve_session__change_txt_file-2.snap | 18 +++++++++++++ .../serve_session__change_txt_file.snap | 18 +++++++++++++ 3 files changed, 61 insertions(+), 1 deletion(-) create mode 100644 src/snapshots/serve_session__change_txt_file-2.snap create mode 100644 src/snapshots/serve_session__change_txt_file.snap diff --git a/src/serve_session.rs b/src/serve_session.rs index 54e23c5f..03bc8f02 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -194,11 +194,13 @@ impl ServeSession { mod serve_session { use super::*; + use std::{path::PathBuf, thread::sleep, time::Duration}; + use insta::assert_yaml_snapshot; use rojo_insta_ext::RedactionMap; use crate::{ - imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}, + imfs::{ImfsDebug, ImfsEvent, ImfsSnapshot, NoopFetcher, TestFetcher}, tree_view::view_tree, }; @@ -213,4 +215,26 @@ mod serve_session { let mut rm = RedactionMap::new(); assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); } + + #[test] + fn change_txt_file() { + let (state, fetcher) = TestFetcher::new(); + + state.load_snapshot("/foo.txt", ImfsSnapshot::file("Hello!")); + + let imfs = Imfs::new(fetcher); + let session = ServeSession::new(imfs, "/foo.txt", None); + + let mut redactions = RedactionMap::new(); + assert_yaml_snapshot!(view_tree(&session.tree(), &mut redactions)); + + state.load_snapshot("/foo.txt", ImfsSnapshot::file("World!")); + state.raise_event(ImfsEvent::Modified(PathBuf::from("/foo.txt"))); + + // TODO: Listen for a signal that the tree changed instead, using the + // message queue + sleep(Duration::from_millis(20)); + + assert_yaml_snapshot!(view_tree(&session.tree(), &mut redactions)); + } } diff --git a/src/snapshots/serve_session__change_txt_file-2.snap b/src/snapshots/serve_session__change_txt_file-2.snap new file mode 100644 index 00000000..cf4d332d --- /dev/null +++ b/src/snapshots/serve_session__change_txt_file-2.snap @@ -0,0 +1,18 @@ +--- +source: src/serve_session.rs +expression: "view_tree(&session.tree(), &mut redactions)" +--- +id: id-1 +name: foo +class_name: StringValue +properties: + Value: + Type: String + Value: World! +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /foo.txt + relevant_paths: + - /foo.txt +children: [] diff --git a/src/snapshots/serve_session__change_txt_file.snap b/src/snapshots/serve_session__change_txt_file.snap new file mode 100644 index 00000000..ee051327 --- /dev/null +++ b/src/snapshots/serve_session__change_txt_file.snap @@ -0,0 +1,18 @@ +--- +source: src/serve_session.rs +expression: "view_tree(&session.tree(), &mut redactions)" +--- +id: id-1 +name: foo +class_name: StringValue +properties: + Value: + Type: String + Value: Hello! +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /foo.txt + relevant_paths: + - /foo.txt +children: [] From c5839c94ca3e520bd5c25e0266384a4d9b102356 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 13:25:34 -0700 Subject: [PATCH 0793/1504] Add test-only MessageQueue::subscribe_any. This makes writing tests that do async things easier. --- src/message_queue.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/message_queue.rs b/src/message_queue.rs index 23c6cd94..6591e0c7 100644 --- a/src/message_queue.rs +++ b/src/message_queue.rs @@ -61,6 +61,7 @@ impl MessageQueue { mem::replace::>(&mut message_listeners, remaining_listeners); } + /// Subscribe to any messages occurring after the given message cursor. pub fn subscribe(&self, cursor: u32, sender: oneshot::Sender<(u32, Vec)>) { let listener = { let listener = Listener { sender, cursor }; @@ -77,6 +78,22 @@ impl MessageQueue { message_listeners.push(listener); } + /// Subscribe to any messages being pushed into the queue. + /// + /// This method is only useful in tests. Non-test code should use subscribe + /// instead. + #[cfg(test)] + pub fn subscribe_any(&self) -> oneshot::Receiver<(u32, Vec)> { + let cursor = { + let messages = self.messages.read().unwrap(); + messages.len() as u32 + }; + let (sender, receiver) = oneshot::channel(); + + self.subscribe(cursor, sender); + receiver + } + pub fn cursor(&self) -> u32 { self.messages.read().unwrap().len() as u32 } From 18533d594461d4efe1a4e8b052832e7fe197406d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 13:26:21 -0700 Subject: [PATCH 0794/1504] Improve ServeSession test using async and Tokio --- Cargo.lock | 72 +++++++++++++++++++ Cargo.toml | 1 + src/serve_session.rs | 24 +++++-- ...serve_session__change_txt_file_after.snap} | 0 ...erve_session__change_txt_file_before.snap} | 0 .../serve_session__change_txt_file_patch.snap | 16 +++++ 6 files changed, 107 insertions(+), 6 deletions(-) rename src/snapshots/{serve_session__change_txt_file-2.snap => serve_session__change_txt_file_after.snap} (100%) rename src/snapshots/{serve_session__change_txt_file.snap => serve_session__change_txt_file_before.snap} (100%) create mode 100644 src/snapshots/serve_session__change_txt_file_patch.snap diff --git a/Cargo.lock b/Cargo.lock index 2a03d2dc..9f2c1f6a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -849,6 +849,16 @@ dependencies = [ "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "mio-uds" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "miow" version = "0.2.1" @@ -1473,6 +1483,7 @@ dependencies = [ "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1799,13 +1810,18 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1818,6 +1834,16 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-codec" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-current-thread" version = "0.1.6" @@ -1836,6 +1862,16 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-fs" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio-io" version = "0.1.12" @@ -1913,6 +1949,37 @@ dependencies = [ "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tokio-udp" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "tokio-uds" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "try-lock" version = "0.2.2" @@ -2221,6 +2288,7 @@ dependencies = [ "checksum miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7108aff85b876d06f22503dcce091e29f76733b2bfdd91eebce81f5e68203a10" "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" "checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" +"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" @@ -2317,14 +2385,18 @@ dependencies = [ "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" +"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" "checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" +"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" "checksum tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c56391be9805bc80163151c0b9e5164ee64f4b0200962c346fea12773158f22d" "checksum tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" "checksum tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd2c6a3885302581f4401c82af70d792bb9df1700e7437b0aeb4ada94d5388c" "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" +"checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" +"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" diff --git a/Cargo.toml b/Cargo.toml index 5f4a77be..e52c5fae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -74,6 +74,7 @@ paste = "0.1" pretty_assertions = "0.6.1" serde_yaml = "0.8.9" tempfile = "3.0" +tokio = "0.1.22" walkdir = "2.1" [dev-dependencies.insta] diff --git a/src/serve_session.rs b/src/serve_session.rs index 03bc8f02..4f6764ea 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -194,10 +194,11 @@ impl ServeSession { mod serve_session { use super::*; - use std::{path::PathBuf, thread::sleep, time::Duration}; + use std::{path::PathBuf, time::Duration}; use insta::assert_yaml_snapshot; use rojo_insta_ext::RedactionMap; + use tokio::{runtime::Runtime, timer::Timeout}; use crate::{ imfs::{ImfsDebug, ImfsEvent, ImfsSnapshot, NoopFetcher, TestFetcher}, @@ -226,15 +227,26 @@ mod serve_session { let session = ServeSession::new(imfs, "/foo.txt", None); let mut redactions = RedactionMap::new(); - assert_yaml_snapshot!(view_tree(&session.tree(), &mut redactions)); + assert_yaml_snapshot!( + "change_txt_file_before", + view_tree(&session.tree(), &mut redactions) + ); state.load_snapshot("/foo.txt", ImfsSnapshot::file("World!")); + + let receiver = session.message_queue().subscribe_any(); + state.raise_event(ImfsEvent::Modified(PathBuf::from("/foo.txt"))); - // TODO: Listen for a signal that the tree changed instead, using the - // message queue - sleep(Duration::from_millis(20)); + let receiver = Timeout::new(receiver, Duration::from_millis(200)); - assert_yaml_snapshot!(view_tree(&session.tree(), &mut redactions)); + let mut rt = Runtime::new().unwrap(); + let result = rt.block_on(receiver).unwrap(); + + assert_yaml_snapshot!("change_txt_file_patch", redactions.redacted_yaml(result)); + assert_yaml_snapshot!( + "change_txt_file_after", + view_tree(&session.tree(), &mut redactions) + ); } } diff --git a/src/snapshots/serve_session__change_txt_file-2.snap b/src/snapshots/serve_session__change_txt_file_after.snap similarity index 100% rename from src/snapshots/serve_session__change_txt_file-2.snap rename to src/snapshots/serve_session__change_txt_file_after.snap diff --git a/src/snapshots/serve_session__change_txt_file.snap b/src/snapshots/serve_session__change_txt_file_before.snap similarity index 100% rename from src/snapshots/serve_session__change_txt_file.snap rename to src/snapshots/serve_session__change_txt_file_before.snap diff --git a/src/snapshots/serve_session__change_txt_file_patch.snap b/src/snapshots/serve_session__change_txt_file_patch.snap new file mode 100644 index 00000000..5e194e99 --- /dev/null +++ b/src/snapshots/serve_session__change_txt_file_patch.snap @@ -0,0 +1,16 @@ +--- +source: src/serve_session.rs +expression: redactions.redacted_yaml(result) +--- +- 1 +- - removed: [] + added: [] + updated: + - id: id-1 + changed_name: ~ + changed_class_name: ~ + changed_properties: + Value: + Type: String + Value: World! + changed_metadata: ~ From 4e47655b175ed657f3ffc4bdbb9f0c03e9c332bb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 13:49:41 -0700 Subject: [PATCH 0795/1504] Refactor MessageQueue API to return a oneshot receiver --- src/message_queue.rs | 12 +++++++----- src/web/api.rs | 8 ++------ 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/message_queue.rs b/src/message_queue.rs index 6591e0c7..2f20dcab 100644 --- a/src/message_queue.rs +++ b/src/message_queue.rs @@ -62,20 +62,24 @@ impl MessageQueue { } /// Subscribe to any messages occurring after the given message cursor. - pub fn subscribe(&self, cursor: u32, sender: oneshot::Sender<(u32, Vec)>) { + pub fn subscribe(&self, cursor: u32) -> oneshot::Receiver<(u32, Vec)> { + let (sender, receiver) = oneshot::channel(); + let listener = { let listener = Listener { sender, cursor }; let messages = self.messages.read().unwrap(); match fire_listener_if_ready(&messages, listener) { - Ok(_) => return, + Ok(_) => return receiver, Err(listener) => listener, } }; let mut message_listeners = self.message_listeners.lock().unwrap(); message_listeners.push(listener); + + receiver } /// Subscribe to any messages being pushed into the queue. @@ -88,10 +92,8 @@ impl MessageQueue { let messages = self.messages.read().unwrap(); messages.len() as u32 }; - let (sender, receiver) = oneshot::channel(); - self.subscribe(cursor, sender); - receiver + self.subscribe(cursor) } pub fn cursor(&self) -> u32 { diff --git a/src/web/api.rs b/src/web/api.rs index 8be66359..1ba95725 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -3,7 +3,7 @@ use std::{collections::HashMap, sync::Arc}; -use futures::{sync::oneshot, Future}; +use futures::Future; use hyper::{service::Service, Body, Method, Request, StatusCode}; use rbx_dom_weak::RbxId; @@ -83,12 +83,8 @@ impl ApiService { }; let session_id = self.serve_session.session_id(); - let (sender, receiver) = oneshot::channel(); - { - let message_queue = self.serve_session.message_queue(); - message_queue.subscribe(input_cursor, sender); - } + let receiver = self.serve_session.message_queue().subscribe(input_cursor); let tree_handle = self.serve_session.tree_handle(); From 3bd8549f412d7acf9f14e000809e59e33e69a0ea Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 13:57:40 -0700 Subject: [PATCH 0796/1504] Add ServeSession test for project with folder --- src/serve_session.rs | 28 +++++++++++++++++ .../serve_session__project_with_folder.snap | 30 +++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 src/snapshots/serve_session__project_with_folder.snap diff --git a/src/serve_session.rs b/src/serve_session.rs index 4f6764ea..969e7cbf 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -197,6 +197,7 @@ mod serve_session { use std::{path::PathBuf, time::Duration}; use insta::assert_yaml_snapshot; + use maplit::hashmap; use rojo_insta_ext::RedactionMap; use tokio::{runtime::Runtime, timer::Timeout}; @@ -217,6 +218,33 @@ mod serve_session { assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); } + #[test] + fn project_with_folder() { + let mut imfs = Imfs::new(NoopFetcher); + + imfs.debug_load_snapshot( + "/foo", + ImfsSnapshot::dir(hashmap! { + "default.project.json" => ImfsSnapshot::file(r#" + { + "name": "HelloWorld", + "tree": { + "$path": "src" + } + } + "#), + "src" => ImfsSnapshot::dir(hashmap! { + "hello.txt" => ImfsSnapshot::file("Hello, world!"), + }), + }), + ); + + let session = ServeSession::new(imfs, "/foo", None); + + let mut rm = RedactionMap::new(); + assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); + } + #[test] fn change_txt_file() { let (state, fetcher) = TestFetcher::new(); diff --git a/src/snapshots/serve_session__project_with_folder.snap b/src/snapshots/serve_session__project_with_folder.snap new file mode 100644 index 00000000..6b91f347 --- /dev/null +++ b/src/snapshots/serve_session__project_with_folder.snap @@ -0,0 +1,30 @@ +--- +source: src/serve_session.rs +expression: "view_tree(&session.tree(), &mut rm)" +--- +id: id-1 +name: HelloWorld +class_name: Folder +properties: {} +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /foo/default.project.json + relevant_paths: + - /foo/src + - /foo/default.project.json +children: + - id: id-2 + name: hello + class_name: StringValue + properties: + Value: + Type: String + Value: "Hello, world!" + metadata: + ignore_unknown_instances: false + instigating_source: + Path: /foo/src/hello.txt + relevant_paths: + - /foo/src/hello.txt + children: [] From fa817e3cddbae8c3aeabe32087885096fe1e8775 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 14:14:44 -0700 Subject: [PATCH 0797/1504] Add baseline support for adjacent meta files for scripts --- src/snapshot_middleware/lua.rs | 71 +++++++++++++++++-- src/snapshot_middleware/meta_file.rs | 15 ++++ src/snapshot_middleware/mod.rs | 1 + .../snapshots/test__module_with_meta.snap | 18 +++++ .../snapshots/test__script_with_meta.snap | 18 +++++ 5 files changed, 118 insertions(+), 5 deletions(-) create mode 100644 src/snapshot_middleware/meta_file.rs create mode 100644 src/snapshot_middleware/snapshots/test__module_with_meta.snap create mode 100644 src/snapshot_middleware/snapshots/test__script_with_meta.snap diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index d60ee4b9..26dce30d 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -10,6 +10,7 @@ use crate::{ use super::{ dir::SnapshotDir, + meta_file::AdjacentMetadata, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, }; @@ -79,6 +80,7 @@ fn snapshot_lua_file( let contents = entry.contents(imfs)?; let contents_str = str::from_utf8(contents) + // TODO: Turn into error type .expect("File content was not valid UTF-8") .to_string(); @@ -88,13 +90,30 @@ fn snapshot_lua_file( }, }; + let meta_path = entry + .path() + .with_file_name(format!("{}.meta.json", instance_name)); + + let mut metadata = InstanceMetadata { + instigating_source: Some(entry.path().to_path_buf().into()), + relevant_paths: vec![entry.path().to_path_buf()], + ..Default::default() + }; + + if let Some(meta_entry) = imfs.get(meta_path).with_not_found()? { + let meta_contents = meta_entry.contents(imfs)?; + let parsed: AdjacentMetadata = serde_json::from_slice(meta_contents) + // TODO: Turn into error type + .expect(".meta.json file was malformed"); + + if let Some(ignore) = parsed.ignore_unknown_instances { + metadata.ignore_unknown_instances = ignore; + } + } + Ok(Some(InstanceSnapshot { snapshot_id: None, - metadata: InstanceMetadata { - instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf()], - ..Default::default() - }, + metadata, name: Cow::Owned(instance_name.to_owned()), class_name: Cow::Borrowed(class_name), properties, @@ -185,4 +204,46 @@ mod test { assert_yaml_snapshot!(instance_snapshot); } + + #[test] + fn module_with_meta() { + let mut imfs = Imfs::new(NoopFetcher); + let file = ImfsSnapshot::file("Hello there!"); + let meta = ImfsSnapshot::file( + r#" + { + "ignoreUnknownInstances": true + } + "#, + ); + + imfs.debug_load_snapshot("/foo.lua", file); + imfs.debug_load_snapshot("/foo.meta.json", meta); + + let entry = imfs.get("/foo.lua").unwrap(); + let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + assert_yaml_snapshot!(instance_snapshot); + } + + #[test] + fn script_with_meta() { + let mut imfs = Imfs::new(NoopFetcher); + let file = ImfsSnapshot::file("Hello there!"); + let meta = ImfsSnapshot::file( + r#" + { + "ignoreUnknownInstances": true + } + "#, + ); + + imfs.debug_load_snapshot("/foo.server.lua", file); + imfs.debug_load_snapshot("/foo.meta.json", meta); + + let entry = imfs.get("/foo.server.lua").unwrap(); + let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + assert_yaml_snapshot!(instance_snapshot); + } } diff --git a/src/snapshot_middleware/meta_file.rs b/src/snapshot_middleware/meta_file.rs new file mode 100644 index 00000000..f20a5e41 --- /dev/null +++ b/src/snapshot_middleware/meta_file.rs @@ -0,0 +1,15 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct AdjacentMetadata { + #[serde(skip_serializing_if = "Option::is_none")] + pub ignore_unknown_instances: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct InitMetadata { + #[serde(skip_serializing_if = "Option::is_none")] + pub ignore_unknown_instances: Option, +} diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 21f5b838..b16f3e23 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -9,6 +9,7 @@ mod dir; mod error; mod json_model; mod lua; +mod meta_file; mod middleware; mod project; mod rbxlx; diff --git a/src/snapshot_middleware/snapshots/test__module_with_meta.snap b/src/snapshot_middleware/snapshots/test__module_with_meta.snap new file mode 100644 index 00000000..d54f1133 --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__module_with_meta.snap @@ -0,0 +1,18 @@ +--- +source: src/snapshot_middleware/lua.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: true + instigating_source: + Path: /foo.lua + relevant_paths: + - /foo.lua +name: foo +class_name: ModuleScript +properties: + Source: + Type: String + Value: Hello there! +children: [] diff --git a/src/snapshot_middleware/snapshots/test__script_with_meta.snap b/src/snapshot_middleware/snapshots/test__script_with_meta.snap new file mode 100644 index 00000000..ce267c6f --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__script_with_meta.snap @@ -0,0 +1,18 @@ +--- +source: src/snapshot_middleware/lua.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: true + instigating_source: + Path: /foo.server.lua + relevant_paths: + - /foo.server.lua +name: foo +class_name: Script +properties: + Source: + Type: String + Value: Hello there! +children: [] From 13cb0a27a0ede24dd895406a170f3e1b98fe35ee Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 15:30:16 -0700 Subject: [PATCH 0798/1504] Make .meta.json changes cause scripts to be updated --- src/serve_session.rs | 63 +++++++++++++++++++ src/snapshot_middleware/lua.rs | 2 +- .../snapshots/test__client_from_imfs.snap | 1 + .../snapshots/test__module_from_imfs.snap | 1 + .../snapshots/test__module_with_meta.snap | 1 + .../snapshots/test__script_with_meta.snap | 1 + .../snapshots/test__server_from_imfs.snap | 1 + ...rve_session__change_script_meta_after.snap | 30 +++++++++ ...ve_session__change_script_meta_before.snap | 30 +++++++++ ...rve_session__change_script_meta_patch.snap | 19 ++++++ .../serve_session__script_with_meta.snap | 30 +++++++++ 11 files changed, 178 insertions(+), 1 deletion(-) create mode 100644 src/snapshots/serve_session__change_script_meta_after.snap create mode 100644 src/snapshots/serve_session__change_script_meta_before.snap create mode 100644 src/snapshots/serve_session__change_script_meta_patch.snap create mode 100644 src/snapshots/serve_session__script_with_meta.snap diff --git a/src/serve_session.rs b/src/serve_session.rs index 969e7cbf..30438c26 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -245,6 +245,69 @@ mod serve_session { assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); } + #[test] + fn script_with_meta() { + let mut imfs = Imfs::new(NoopFetcher); + + imfs.debug_load_snapshot( + "/root", + ImfsSnapshot::dir(hashmap! { + "test.lua" => ImfsSnapshot::file("This is a test."), + "test.meta.json" => ImfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#), + }), + ); + + let session = ServeSession::new(imfs, "/root", None); + + let mut rm = RedactionMap::new(); + assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); + } + + #[test] + fn change_script_meta() { + let (state, fetcher) = TestFetcher::new(); + + state.load_snapshot( + "/root", + ImfsSnapshot::dir(hashmap! { + "test.lua" => ImfsSnapshot::file("This is a test."), + "test.meta.json" => ImfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#), + }), + ); + + let imfs = Imfs::new(fetcher); + let session = ServeSession::new(imfs, "/root", None); + + let mut redactions = RedactionMap::new(); + assert_yaml_snapshot!( + "change_script_meta_before", + view_tree(&session.tree(), &mut redactions) + ); + + state.load_snapshot( + "/root/test.meta.json", + ImfsSnapshot::file(r#"{ "ignoreUnknownInstances": false }"#), + ); + + let receiver = Timeout::new( + session.message_queue().subscribe_any(), + Duration::from_millis(200), + ); + state.raise_event(ImfsEvent::Modified(PathBuf::from("/root/test.meta.json"))); + + let mut rt = Runtime::new().unwrap(); + let changes = rt.block_on(receiver).unwrap(); + + assert_yaml_snapshot!( + "change_script_meta_patch", + redactions.redacted_yaml(changes) + ); + assert_yaml_snapshot!( + "change_script_meta_after", + view_tree(&session.tree(), &mut redactions) + ); + } + #[test] fn change_txt_file() { let (state, fetcher) = TestFetcher::new(); diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 26dce30d..b59898ea 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -96,7 +96,7 @@ fn snapshot_lua_file( let mut metadata = InstanceMetadata { instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf()], + relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], ..Default::default() }; diff --git a/src/snapshot_middleware/snapshots/test__client_from_imfs.snap b/src/snapshot_middleware/snapshots/test__client_from_imfs.snap index 35ef40fb..f76fb658 100644 --- a/src/snapshot_middleware/snapshots/test__client_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__client_from_imfs.snap @@ -9,6 +9,7 @@ metadata: Path: /foo.client.lua relevant_paths: - /foo.client.lua + - /foo.meta.json name: foo class_name: LocalScript properties: diff --git a/src/snapshot_middleware/snapshots/test__module_from_imfs.snap b/src/snapshot_middleware/snapshots/test__module_from_imfs.snap index 3ad3d835..d6bb90f7 100644 --- a/src/snapshot_middleware/snapshots/test__module_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__module_from_imfs.snap @@ -9,6 +9,7 @@ metadata: Path: /foo.lua relevant_paths: - /foo.lua + - /foo.meta.json name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/test__module_with_meta.snap b/src/snapshot_middleware/snapshots/test__module_with_meta.snap index d54f1133..15b911f3 100644 --- a/src/snapshot_middleware/snapshots/test__module_with_meta.snap +++ b/src/snapshot_middleware/snapshots/test__module_with_meta.snap @@ -9,6 +9,7 @@ metadata: Path: /foo.lua relevant_paths: - /foo.lua + - /foo.meta.json name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/test__script_with_meta.snap b/src/snapshot_middleware/snapshots/test__script_with_meta.snap index ce267c6f..2c7dbf43 100644 --- a/src/snapshot_middleware/snapshots/test__script_with_meta.snap +++ b/src/snapshot_middleware/snapshots/test__script_with_meta.snap @@ -9,6 +9,7 @@ metadata: Path: /foo.server.lua relevant_paths: - /foo.server.lua + - /foo.meta.json name: foo class_name: Script properties: diff --git a/src/snapshot_middleware/snapshots/test__server_from_imfs.snap b/src/snapshot_middleware/snapshots/test__server_from_imfs.snap index 3c9c0070..b9964d27 100644 --- a/src/snapshot_middleware/snapshots/test__server_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__server_from_imfs.snap @@ -9,6 +9,7 @@ metadata: Path: /foo.server.lua relevant_paths: - /foo.server.lua + - /foo.meta.json name: foo class_name: Script properties: diff --git a/src/snapshots/serve_session__change_script_meta_after.snap b/src/snapshots/serve_session__change_script_meta_after.snap new file mode 100644 index 00000000..dacd98cc --- /dev/null +++ b/src/snapshots/serve_session__change_script_meta_after.snap @@ -0,0 +1,30 @@ +--- +source: src/serve_session.rs +expression: "view_tree(&session.tree(), &mut redactions)" +--- +id: id-1 +name: root +class_name: Folder +properties: {} +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /root + relevant_paths: + - /root +children: + - id: id-2 + name: test + class_name: ModuleScript + properties: + Source: + Type: String + Value: This is a test. + metadata: + ignore_unknown_instances: false + instigating_source: + Path: /root/test.lua + relevant_paths: + - /root/test.lua + - /root/test.meta.json + children: [] diff --git a/src/snapshots/serve_session__change_script_meta_before.snap b/src/snapshots/serve_session__change_script_meta_before.snap new file mode 100644 index 00000000..dcf06e97 --- /dev/null +++ b/src/snapshots/serve_session__change_script_meta_before.snap @@ -0,0 +1,30 @@ +--- +source: src/serve_session.rs +expression: "view_tree(&session.tree(), &mut redactions)" +--- +id: id-1 +name: root +class_name: Folder +properties: {} +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /root + relevant_paths: + - /root +children: + - id: id-2 + name: test + class_name: ModuleScript + properties: + Source: + Type: String + Value: This is a test. + metadata: + ignore_unknown_instances: true + instigating_source: + Path: /root/test.lua + relevant_paths: + - /root/test.lua + - /root/test.meta.json + children: [] diff --git a/src/snapshots/serve_session__change_script_meta_patch.snap b/src/snapshots/serve_session__change_script_meta_patch.snap new file mode 100644 index 00000000..1330da20 --- /dev/null +++ b/src/snapshots/serve_session__change_script_meta_patch.snap @@ -0,0 +1,19 @@ +--- +source: src/serve_session.rs +expression: redactions.redacted_yaml(changes) +--- +- 1 +- - removed: [] + added: [] + updated: + - id: id-2 + changed_name: ~ + changed_class_name: ~ + changed_properties: {} + changed_metadata: + ignore_unknown_instances: false + instigating_source: + Path: /root/test.lua + relevant_paths: + - /root/test.lua + - /root/test.meta.json diff --git a/src/snapshots/serve_session__script_with_meta.snap b/src/snapshots/serve_session__script_with_meta.snap new file mode 100644 index 00000000..81247ba5 --- /dev/null +++ b/src/snapshots/serve_session__script_with_meta.snap @@ -0,0 +1,30 @@ +--- +source: src/serve_session.rs +expression: "view_tree(&session.tree(), &mut rm)" +--- +id: id-1 +name: root +class_name: Folder +properties: {} +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /root + relevant_paths: + - /root +children: + - id: id-2 + name: test + class_name: ModuleScript + properties: + Source: + Type: String + Value: This is a test. + metadata: + ignore_unknown_instances: true + instigating_source: + Path: /root/test.lua + relevant_paths: + - /root/test.lua + - /root/test.meta.json + children: [] From 8a9a72fd50e87f5fbb63e66bbccee782a4abcc31 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 15:42:44 -0700 Subject: [PATCH 0799/1504] Refactor .meta.json into AdjacentMetadata type more strongly --- src/snapshot_middleware/lua.rs | 25 ++++++------- src/snapshot_middleware/meta_file.rs | 55 +++++++++++++++++++++++++--- 2 files changed, 61 insertions(+), 19 deletions(-) diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index b59898ea..c13648e9 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -94,31 +94,28 @@ fn snapshot_lua_file( .path() .with_file_name(format!("{}.meta.json", instance_name)); - let mut metadata = InstanceMetadata { + let metadata = InstanceMetadata { instigating_source: Some(entry.path().to_path_buf().into()), relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], ..Default::default() }; - if let Some(meta_entry) = imfs.get(meta_path).with_not_found()? { - let meta_contents = meta_entry.contents(imfs)?; - let parsed: AdjacentMetadata = serde_json::from_slice(meta_contents) - // TODO: Turn into error type - .expect(".meta.json file was malformed"); - - if let Some(ignore) = parsed.ignore_unknown_instances { - metadata.ignore_unknown_instances = ignore; - } - } - - Ok(Some(InstanceSnapshot { + let mut snapshot = InstanceSnapshot { snapshot_id: None, metadata, name: Cow::Owned(instance_name.to_owned()), class_name: Cow::Borrowed(class_name), properties, children: Vec::new(), - })) + }; + + if let Some(meta_entry) = imfs.get(meta_path).with_not_found()? { + let meta_contents = meta_entry.contents(imfs)?; + let mut metadata = AdjacentMetadata::from_slice(meta_contents); + metadata.apply_all(&mut snapshot); + } + + Ok(Some(snapshot)) } /// Attempts to snapshot an 'init' Lua script contained inside of a folder with diff --git a/src/snapshot_middleware/meta_file.rs b/src/snapshot_middleware/meta_file.rs index f20a5e41..f8d8e960 100644 --- a/src/snapshot_middleware/meta_file.rs +++ b/src/snapshot_middleware/meta_file.rs @@ -1,15 +1,60 @@ +use std::{borrow::Cow, collections::HashMap}; + +use rbx_dom_weak::UnresolvedRbxValue; +use rbx_reflection::try_resolve_value; use serde::{Deserialize, Serialize}; +use crate::snapshot::InstanceSnapshot; + #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AdjacentMetadata { #[serde(skip_serializing_if = "Option::is_none")] - pub ignore_unknown_instances: Option, -} + pub class_name: Option, -#[derive(Debug, Serialize, Deserialize)] -#[serde(rename_all = "camelCase")] -pub struct InitMetadata { #[serde(skip_serializing_if = "Option::is_none")] pub ignore_unknown_instances: Option, + + #[serde(default, skip_serializing_if = "HashMap::is_empty")] + pub properties: HashMap, +} + +impl AdjacentMetadata { + pub fn from_slice(slice: &[u8]) -> Self { + serde_json::from_slice(slice) + // TODO: Turn into error type + .expect(".meta.json file was malformed") + } + + pub fn apply_ignore_unknown_instances(&mut self, snapshot: &mut InstanceSnapshot) { + if let Some(ignore) = self.ignore_unknown_instances.take() { + snapshot.metadata.ignore_unknown_instances = ignore; + } + } + + pub fn apply_class_name(&mut self, snapshot: &mut InstanceSnapshot) { + if let Some(class_name) = self.class_name.take() { + snapshot.class_name = Cow::Owned(class_name); + } + } + + pub fn apply_properties(&mut self, snapshot: &mut InstanceSnapshot) { + let class_name = &snapshot.class_name; + + let source_properties = self.properties.drain().map(|(key, value)| { + try_resolve_value(class_name, &key, &value) + .map(|resolved| (key, resolved)) + .expect("TODO: Handle rbx_reflection errors") + }); + + for (key, value) in source_properties { + snapshot.properties.insert(key, value); + } + } + + pub fn apply_all(&mut self, snapshot: &mut InstanceSnapshot) { + self.apply_ignore_unknown_instances(snapshot); + self.apply_class_name(snapshot); + self.apply_properties(snapshot); + } } From 709cba45cea181b63257a7d58265fb35af40c44c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 15:44:47 -0700 Subject: [PATCH 0800/1504] Remove className from adjacent meta files, which is not supported in 0.5.x --- src/snapshot_middleware/meta_file.rs | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/src/snapshot_middleware/meta_file.rs b/src/snapshot_middleware/meta_file.rs index f8d8e960..9b06f0f1 100644 --- a/src/snapshot_middleware/meta_file.rs +++ b/src/snapshot_middleware/meta_file.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::HashMap}; +use std::collections::HashMap; use rbx_dom_weak::UnresolvedRbxValue; use rbx_reflection::try_resolve_value; @@ -9,9 +9,6 @@ use crate::snapshot::InstanceSnapshot; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AdjacentMetadata { - #[serde(skip_serializing_if = "Option::is_none")] - pub class_name: Option, - #[serde(skip_serializing_if = "Option::is_none")] pub ignore_unknown_instances: Option, @@ -32,12 +29,6 @@ impl AdjacentMetadata { } } - pub fn apply_class_name(&mut self, snapshot: &mut InstanceSnapshot) { - if let Some(class_name) = self.class_name.take() { - snapshot.class_name = Cow::Owned(class_name); - } - } - pub fn apply_properties(&mut self, snapshot: &mut InstanceSnapshot) { let class_name = &snapshot.class_name; @@ -54,7 +45,6 @@ impl AdjacentMetadata { pub fn apply_all(&mut self, snapshot: &mut InstanceSnapshot) { self.apply_ignore_unknown_instances(snapshot); - self.apply_class_name(snapshot); self.apply_properties(snapshot); } } From f83abe15cbe5355dee8b51152f3902f777f73240 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 15:46:51 -0700 Subject: [PATCH 0801/1504] Add test for ensuring that scripts can be disabled with .meta.json files --- src/snapshot_middleware/lua.rs | 23 +++++++++++++++++++ .../snapshots/test__script_disabled.snap | 22 ++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 src/snapshot_middleware/snapshots/test__script_disabled.snap diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index c13648e9..3686c21e 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -243,4 +243,27 @@ mod test { assert_yaml_snapshot!(instance_snapshot); } + + #[test] + fn script_disabled() { + let mut imfs = Imfs::new(NoopFetcher); + let file = ImfsSnapshot::file("Hello there!"); + let meta = ImfsSnapshot::file( + r#" + { + "properties": { + "Disabled": true + } + } + "#, + ); + + imfs.debug_load_snapshot("/bar.server.lua", file); + imfs.debug_load_snapshot("/bar.meta.json", meta); + + let entry = imfs.get("/bar.server.lua").unwrap(); + let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + assert_yaml_snapshot!(instance_snapshot); + } } diff --git a/src/snapshot_middleware/snapshots/test__script_disabled.snap b/src/snapshot_middleware/snapshots/test__script_disabled.snap new file mode 100644 index 00000000..e2be6724 --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__script_disabled.snap @@ -0,0 +1,22 @@ +--- +source: src/snapshot_middleware/lua.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /bar.server.lua + relevant_paths: + - /bar.server.lua + - /bar.meta.json +name: bar +class_name: Script +properties: + Disabled: + Type: Bool + Value: true + Source: + Type: String + Value: Hello there! +children: [] From 2957e8ad7320214bd8dfa2a4e98324c0378c3dc0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 16:03:15 -0700 Subject: [PATCH 0802/1504] Make Lua snapshot middleware test sort maps --- src/snapshot_middleware/lua.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 3686c21e..8fe810c4 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -159,7 +159,7 @@ fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { mod test { use super::*; - use insta::assert_yaml_snapshot; + use insta::{assert_yaml_snapshot, with_settings}; use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; @@ -264,6 +264,8 @@ mod test { let entry = imfs.get("/bar.server.lua").unwrap(); let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); - assert_yaml_snapshot!(instance_snapshot); + with_settings!({ sort_maps => true }, { + assert_yaml_snapshot!(instance_snapshot); + }); } } From a02f485040738329d8867e47130195946ec61a34 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 16:05:15 -0700 Subject: [PATCH 0803/1504] Add end-to-end build test for Script.Disabled via .meta.json --- .../build_test__script_meta_disabled.snap | 18 ++++++++++++++++++ .../script_meta_disabled/default.project.json | 6 ++++++ .../folder/hello.meta.json | 5 +++++ .../folder/hello.server.lua | 1 + rojo-test/src/build_test.rs | 1 + 5 files changed, 31 insertions(+) create mode 100644 rojo-test/build-test-snapshots/build_test__script_meta_disabled.snap create mode 100644 rojo-test/build-tests/script_meta_disabled/default.project.json create mode 100644 rojo-test/build-tests/script_meta_disabled/folder/hello.meta.json create mode 100644 rojo-test/build-tests/script_meta_disabled/folder/hello.server.lua diff --git a/rojo-test/build-test-snapshots/build_test__script_meta_disabled.snap b/rojo-test/build-test-snapshots/build_test__script_meta_disabled.snap new file mode 100644 index 00000000..45f01e48 --- /dev/null +++ b/rojo-test/build-test-snapshots/build_test__script_meta_disabled.snap @@ -0,0 +1,18 @@ +--- +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + script_meta_disabled + + + + hello + true + -- This script should be marked 'Disabled' + + + + diff --git a/rojo-test/build-tests/script_meta_disabled/default.project.json b/rojo-test/build-tests/script_meta_disabled/default.project.json new file mode 100644 index 00000000..a4b19a5e --- /dev/null +++ b/rojo-test/build-tests/script_meta_disabled/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "script_meta_disabled", + "tree": { + "$path": "folder" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/script_meta_disabled/folder/hello.meta.json b/rojo-test/build-tests/script_meta_disabled/folder/hello.meta.json new file mode 100644 index 00000000..54f46925 --- /dev/null +++ b/rojo-test/build-tests/script_meta_disabled/folder/hello.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/script_meta_disabled/folder/hello.server.lua b/rojo-test/build-tests/script_meta_disabled/folder/hello.server.lua new file mode 100644 index 00000000..9aa26bc6 --- /dev/null +++ b/rojo-test/build-tests/script_meta_disabled/folder/hello.server.lua @@ -0,0 +1 @@ +-- This script should be marked 'Disabled' \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index 341af7af..aad1b597 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -36,6 +36,7 @@ gen_build_tests! { plain_gitkeep, rbxm_in_folder, rbxmx_in_folder, + script_meta_disabled, server_in_folder, server_init, txt, From 479476561e5c9dbc0c0c4b7e4e0147683b26f7e1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 16:16:06 -0700 Subject: [PATCH 0804/1504] Fix errors in 'Sync Details' page --- docs/reference/sync-details.md | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/docs/reference/sync-details.md b/docs/reference/sync-details.md index 3caa3da0..eeb88853 100644 --- a/docs/reference/sync-details.md +++ b/docs/reference/sync-details.md @@ -116,10 +116,18 @@ Meta files can contain: ### Meta Files to set Rojo metadata Sometimes it's useful to apply properties like `ignoreUnknownInstances` on instances that are defined on the filesystem instead of within the project itself. +If your project has `hello.txt` and there are instances underneath it that you want Rojo to ignore when live-syncing, you could create `hello.meta.json` with: + +```json +{ + "ignoreUnknownInstances": true +} +``` + ### Meta Files for Disabled Scripts Meta files can be used to set properties on `Script` instances, like `Disabled`. -If your project had `foo.server.lua` and you wanted to make sure it would be disabled, you could create a `foo.meta.json` next to it with: +If your project has `foo.server.lua` and you want to make sure it would be disabled, you could create a `foo.meta.json` next to it with: ```json { @@ -140,7 +148,7 @@ If you wanted to represent a tool containing a script and a model for its handle 0, 0, 0, 1, 0, 0, 0, 1, 0, - 0, 0, 1, + 0, 0, 1 ] } } From 2393a1a1140088e9164b734dd6b54d4fd86ecfdf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 16:48:49 -0700 Subject: [PATCH 0805/1504] Add support for .meta.json files affecting .csv LocalizationTables --- src/snapshot_middleware/csv.rs | 44 ++++++++++++++++--- .../snapshots/test__csv_from_imfs.snap | 1 + .../snapshots/test__csv_with_meta.snap | 19 ++++++++ 3 files changed, 59 insertions(+), 5 deletions(-) create mode 100644 src/snapshot_middleware/snapshots/test__csv_with_meta.snap diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 17837667..3b38c3aa 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -5,11 +5,14 @@ use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; use serde::Serialize; use crate::{ - imfs::{Imfs, ImfsEntry, ImfsFetcher}, + imfs::{FsResultExt, Imfs, ImfsEntry, ImfsFetcher}, snapshot::{InstanceMetadata, InstanceSnapshot}, }; -use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; +use super::{ + meta_file::AdjacentMetadata, + middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, +}; pub struct SnapshotCsv; @@ -35,13 +38,17 @@ impl SnapshotMiddleware for SnapshotCsv { .to_string_lossy() .to_string(); + let meta_path = entry + .path() + .with_file_name(format!("{}.meta.json", instance_name)); + let table_contents = convert_localization_csv(entry.contents(imfs)?); - Ok(Some(InstanceSnapshot { + let mut snapshot = InstanceSnapshot { snapshot_id: None, metadata: InstanceMetadata { instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf()], + relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], ..Default::default() }, name: Cow::Owned(instance_name), @@ -52,7 +59,15 @@ impl SnapshotMiddleware for SnapshotCsv { }, }, children: Vec::new(), - })) + }; + + if let Some(meta_entry) = imfs.get(meta_path).with_not_found()? { + let meta_contents = meta_entry.contents(imfs)?; + let mut metadata = AdjacentMetadata::from_slice(meta_contents); + metadata.apply_all(&mut snapshot); + } + + Ok(Some(snapshot)) } fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { @@ -159,4 +174,23 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, assert_yaml_snapshot!(instance_snapshot); } + + #[test] + fn csv_with_meta() { + let mut imfs = Imfs::new(NoopFetcher); + let file = ImfsSnapshot::file( + r#" +Key,Source,Context,Example,es +Ack,Ack!,,An exclamation of despair,¡Ay!"#, + ); + let meta = ImfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#); + + imfs.debug_load_snapshot("/foo.csv", file); + imfs.debug_load_snapshot("/foo.meta.json", meta); + + let entry = imfs.get("/foo.csv").unwrap(); + let instance_snapshot = SnapshotCsv::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + + assert_yaml_snapshot!(instance_snapshot); + } } diff --git a/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap b/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap index 84a1cadc..705eb6e0 100644 --- a/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap @@ -9,6 +9,7 @@ metadata: Path: /foo.csv relevant_paths: - /foo.csv + - /foo.meta.json name: foo class_name: LocalizationTable properties: diff --git a/src/snapshot_middleware/snapshots/test__csv_with_meta.snap b/src/snapshot_middleware/snapshots/test__csv_with_meta.snap new file mode 100644 index 00000000..5721dffd --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__csv_with_meta.snap @@ -0,0 +1,19 @@ +--- +source: src/snapshot_middleware/csv.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: true + instigating_source: + Path: /foo.csv + relevant_paths: + - /foo.csv + - /foo.meta.json +name: foo +class_name: LocalizationTable +properties: + Contents: + Type: String + Value: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" +children: [] From 30351f7b9dd8ab2540d6fde42e904b445adeb3eb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 8 Oct 2019 17:44:23 -0700 Subject: [PATCH 0806/1504] Add support for .meta.json files associated with .txt files --- .../snapshots/test__instance_from_imfs.snap | 1 + .../test__project_with_path_to_txt.snap | 1 + src/snapshot_middleware/txt.rs | 25 +++++++++++++++---- ...serve_session__change_txt_file_before.snap | 1 + .../serve_session__project_with_folder.snap | 1 + 5 files changed, 24 insertions(+), 5 deletions(-) diff --git a/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap b/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap index 0dcac5ac..189e935f 100644 --- a/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap +++ b/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap @@ -9,6 +9,7 @@ metadata: Path: /foo.txt relevant_paths: - /foo.txt + - /foo.meta.json name: foo class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap index de80caa4..a2151784 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap @@ -9,6 +9,7 @@ metadata: Path: /foo/default.project.json relevant_paths: - /foo/other.txt + - /foo/other.meta.json - /foo/default.project.json name: path-project class_name: StringValue diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 19906ca9..f76e4e6d 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -4,11 +4,14 @@ use maplit::hashmap; use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; use crate::{ - imfs::{FileSnapshot, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, + imfs::{FileSnapshot, FsResultExt, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, snapshot::{InstanceMetadata, InstanceSnapshot}, }; -use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; +use super::{ + meta_file::AdjacentMetadata, + middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, +}; pub struct SnapshotTxt; @@ -49,18 +52,30 @@ impl SnapshotMiddleware for SnapshotTxt { }, }; - Ok(Some(InstanceSnapshot { + let meta_path = entry + .path() + .with_file_name(format!("{}.meta.json", instance_name)); + + let mut snapshot = InstanceSnapshot { snapshot_id: None, metadata: InstanceMetadata { instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf()], + relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], ..Default::default() }, name: Cow::Owned(instance_name), class_name: Cow::Borrowed("StringValue"), properties, children: Vec::new(), - })) + }; + + if let Some(meta_entry) = imfs.get(meta_path).with_not_found()? { + let meta_contents = meta_entry.contents(imfs)?; + let mut metadata = AdjacentMetadata::from_slice(meta_contents); + metadata.apply_all(&mut snapshot); + } + + Ok(Some(snapshot)) } fn from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult { diff --git a/src/snapshots/serve_session__change_txt_file_before.snap b/src/snapshots/serve_session__change_txt_file_before.snap index ee051327..644c3700 100644 --- a/src/snapshots/serve_session__change_txt_file_before.snap +++ b/src/snapshots/serve_session__change_txt_file_before.snap @@ -15,4 +15,5 @@ metadata: Path: /foo.txt relevant_paths: - /foo.txt + - /foo.meta.json children: [] diff --git a/src/snapshots/serve_session__project_with_folder.snap b/src/snapshots/serve_session__project_with_folder.snap index 6b91f347..ea3a0f33 100644 --- a/src/snapshots/serve_session__project_with_folder.snap +++ b/src/snapshots/serve_session__project_with_folder.snap @@ -27,4 +27,5 @@ children: Path: /foo/src/hello.txt relevant_paths: - /foo/src/hello.txt + - /foo/src/hello.meta.json children: [] From 321e026e43ac0f7575b30e2ded44116089785c9c Mon Sep 17 00:00:00 2001 From: boyned//Kampfkarren Date: Wed, 9 Oct 2019 12:29:33 -0700 Subject: [PATCH 0807/1504] Fix failing snapshot (#256) --- src/snapshots/serve_session__change_txt_file_after.snap | 1 + 1 file changed, 1 insertion(+) diff --git a/src/snapshots/serve_session__change_txt_file_after.snap b/src/snapshots/serve_session__change_txt_file_after.snap index cf4d332d..9143b804 100644 --- a/src/snapshots/serve_session__change_txt_file_after.snap +++ b/src/snapshots/serve_session__change_txt_file_after.snap @@ -15,4 +15,5 @@ metadata: Path: /foo.txt relevant_paths: - /foo.txt + - /foo.meta.json children: [] From a14aacbcf98ca0544789e273bf1e9b70c9dc9a6e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Oct 2019 12:39:36 -0700 Subject: [PATCH 0808/1504] Improve SnapshotError in preparation for moving middleware to it --- src/imfs/error.rs | 4 ++++ src/snapshot_middleware/error.rs | 19 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/imfs/error.rs b/src/imfs/error.rs index 0369132e..989c64e2 100644 --- a/src/imfs/error.rs +++ b/src/imfs/error.rs @@ -39,6 +39,10 @@ impl FsError { pub fn kind(&self) -> FsErrorKind { self.inner.kind() } + + pub fn into_raw(self) -> (io::Error, PathBuf) { + (self.inner, self.path) + } } impl fmt::Display for FsError { diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs index 7eb43e55..2ee268fb 100644 --- a/src/snapshot_middleware/error.rs +++ b/src/snapshot_middleware/error.rs @@ -1,8 +1,6 @@ -use std::{error::Error, fmt, path::PathBuf}; +use std::{error::Error, fmt, io, path::PathBuf}; -use crate::snapshot::InstanceSnapshot; - -pub type SnapshotResult<'a> = Result>, SnapshotError>; +use crate::{imfs::FsError, snapshot::InstanceSnapshot}; #[derive(Debug)] pub struct SnapshotError { @@ -58,8 +56,19 @@ impl fmt::Display for SnapshotError { } } +impl From for SnapshotError { + fn from(error: FsError) -> Self { + let (inner, path) = error.into_raw(); + + let detail = SnapshotErrorDetail::IoError { inner }; + + Self::new(detail, Some(path)) + } +} + #[derive(Debug)] pub enum SnapshotErrorDetail { + IoError { inner: io::Error }, FileDidNotExist, FileNameBadUnicode, FileContentsBadUnicode { inner: std::str::Utf8Error }, @@ -70,6 +79,7 @@ impl SnapshotErrorDetail { use self::SnapshotErrorDetail::*; match self { + IoError { inner } => Some(inner), FileContentsBadUnicode { inner } => Some(inner), _ => None, } @@ -81,6 +91,7 @@ impl fmt::Display for SnapshotErrorDetail { use self::SnapshotErrorDetail::*; match self { + IoError { inner } => write!(formatter, "I/O error: {}", inner), FileDidNotExist => write!(formatter, "file did not exist"), FileNameBadUnicode => write!(formatter, "file name had malformed Unicode"), FileContentsBadUnicode { inner } => { From 28156bcaf2cd4036084e6fe010cdce820aceb010 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Oct 2019 12:42:08 -0700 Subject: [PATCH 0809/1504] Switch SnapshotMiddleware over to SnapshotError --- src/snapshot_middleware/error.rs | 2 +- src/snapshot_middleware/middleware.rs | 6 ++++-- src/snapshot_middleware/mod.rs | 2 ++ src/snapshot_middleware/project.rs | 2 +- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs index 2ee268fb..486b8324 100644 --- a/src/snapshot_middleware/error.rs +++ b/src/snapshot_middleware/error.rs @@ -1,6 +1,6 @@ use std::{error::Error, fmt, io, path::PathBuf}; -use crate::{imfs::FsError, snapshot::InstanceSnapshot}; +use crate::imfs::FsError; #[derive(Debug)] pub struct SnapshotError { diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index 04c6ec94..66c2f673 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -3,11 +3,13 @@ use std::path::{Path, PathBuf}; use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ - imfs::{FsResult, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, + imfs::{Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, snapshot::InstanceSnapshot, }; -pub type SnapshotInstanceResult<'a> = FsResult>>; +use super::error::SnapshotError; + +pub type SnapshotInstanceResult<'a> = Result>, SnapshotError>; pub type SnapshotFileResult = Option<(String, ImfsSnapshot)>; pub trait SnapshotMiddleware { diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index b16f3e23..d8cfa355 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -17,6 +17,8 @@ mod rbxm; mod rbxmx; mod txt; +pub use self::error::*; + use rbx_dom_weak::{RbxId, RbxTree}; use self::{ diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 4ea7b267..fadd6f90 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -29,7 +29,7 @@ impl SnapshotMiddleware for SnapshotProject { match imfs.get(project_path) { Err(ref err) if err.kind() == FsErrorKind::NotFound => {} - Err(err) => return Err(err), + Err(err) => return Err(err.into()), // TODO: Do we need to muck with the relevant paths if we're a // project file within a folder? Should the folder path be the From 9f947ae2c55ba0e1ae1bb1b99635077cb47205ff Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Oct 2019 12:55:24 -0700 Subject: [PATCH 0810/1504] Improve bad Unicode error handling in txt, CSV, and directory handling --- src/snapshot_middleware/csv.rs | 13 ++++++++++--- src/snapshot_middleware/dir.rs | 3 ++- src/snapshot_middleware/txt.rs | 9 ++++++--- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 3b38c3aa..fe3e6753 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -10,6 +10,7 @@ use crate::{ }; use super::{ + error::SnapshotError, meta_file::AdjacentMetadata, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, }; @@ -25,9 +26,14 @@ impl SnapshotMiddleware for SnapshotCsv { return Ok(None); } - let file_name = entry.path().file_name().unwrap().to_string_lossy(); + let extension = match entry.path().extension() { + Some(x) => x + .to_str() + .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?, + None => return Ok(None), + }; - if !file_name.ends_with(".csv") { + if extension != "csv" { return Ok(None); } @@ -35,7 +41,8 @@ impl SnapshotMiddleware for SnapshotCsv { .path() .file_stem() .expect("Could not extract file stem") - .to_string_lossy() + .to_str() + .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))? .to_string(); let meta_path = entry diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 9c365594..970cc92b 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -8,6 +8,7 @@ use crate::{ }; use super::{ + error::SnapshotError, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, snapshot_from_imfs, snapshot_from_instance, }; @@ -38,7 +39,7 @@ impl SnapshotMiddleware for SnapshotDir { .file_name() .expect("Could not extract file name") .to_str() - .unwrap() + .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))? .to_string(); Ok(Some(InstanceSnapshot { diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index f76e4e6d..a939a100 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -9,6 +9,7 @@ use crate::{ }; use super::{ + error::SnapshotError, meta_file::AdjacentMetadata, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, }; @@ -25,7 +26,9 @@ impl SnapshotMiddleware for SnapshotTxt { } let extension = match entry.path().extension() { - Some(x) => x.to_str().unwrap(), + Some(x) => x + .to_str() + .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?, None => return Ok(None), }; @@ -38,12 +41,12 @@ impl SnapshotMiddleware for SnapshotTxt { .file_stem() .expect("Could not extract file stem") .to_str() - .unwrap() + .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))? .to_string(); let contents = entry.contents(imfs)?; let contents_str = str::from_utf8(contents) - .expect("File content was not valid UTF-8") + .map_err(|err| SnapshotError::file_contents_bad_unicode(err, entry.path()))? .to_string(); let properties = hashmap! { From dca88e827217333f8bc86cb588b0a467099cb919 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Oct 2019 15:30:03 -0700 Subject: [PATCH 0811/1504] Port Project snapshot to use with_not_found --- src/snapshot_middleware/project.rs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index fadd6f90..64f3a71a 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -4,7 +4,7 @@ use rbx_dom_weak::{RbxId, RbxTree}; use rbx_reflection::try_resolve_value; use crate::{ - imfs::{FsErrorKind, Imfs, ImfsEntry, ImfsFetcher}, + imfs::{FsResultExt, Imfs, ImfsEntry, ImfsFetcher}, project::{Project, ProjectNode}, snapshot::{InstanceMetadata, InstanceSnapshot, InstigatingSource}, }; @@ -27,14 +27,12 @@ impl SnapshotMiddleware for SnapshotProject { if entry.is_directory() { let project_path = entry.path().join("default.project.json"); - match imfs.get(project_path) { - Err(ref err) if err.kind() == FsErrorKind::NotFound => {} - Err(err) => return Err(err.into()), - + match imfs.get(project_path).with_not_found()? { // TODO: Do we need to muck with the relevant paths if we're a // project file within a folder? Should the folder path be the // relevant path instead of the project file path? - Ok(entry) => return SnapshotProject::from_imfs(imfs, &entry), + Some(entry) => return SnapshotProject::from_imfs(imfs, &entry), + None => return Ok(None), } } From dfabc07044c819cb30615b8fe1d944dc6aa79485 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Oct 2019 17:15:34 -0700 Subject: [PATCH 0812/1504] More consistent handling of non-Unicode file names (should be rare) --- src/snapshot_middleware/json_model.rs | 12 ++++++++++-- src/snapshot_middleware/rbxlx.rs | 15 ++++++++++++--- src/snapshot_middleware/rbxm.rs | 15 ++++++++++++--- src/snapshot_middleware/rbxmx.rs | 15 ++++++++++++--- 4 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 5b8834b4..65f90d77 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -9,7 +9,10 @@ use crate::{ snapshot::InstanceSnapshot, }; -use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; +use super::{ + error::SnapshotError, + middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, +}; pub struct SnapshotJsonModel; @@ -22,7 +25,12 @@ impl SnapshotMiddleware for SnapshotJsonModel { return Ok(None); } - let file_name = entry.path().file_name().unwrap().to_string_lossy(); + let file_name = entry + .path() + .file_name() + .unwrap() + .to_str() + .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?; let instance_name = match match_trailing(&file_name, ".model.json") { Some(name) => name.to_owned(), diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index 334b7d68..663a4aeb 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -7,7 +7,10 @@ use crate::{ snapshot::InstanceSnapshot, }; -use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; +use super::{ + error::SnapshotError, + middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, +}; pub struct SnapshotRbxlx; @@ -20,7 +23,12 @@ impl SnapshotMiddleware for SnapshotRbxlx { return Ok(None); } - let file_name = entry.path().file_name().unwrap().to_string_lossy(); + let file_name = entry + .path() + .file_name() + .unwrap() + .to_str() + .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?; if !file_name.ends_with(".rbxlx") { return Ok(None); @@ -30,7 +38,8 @@ impl SnapshotMiddleware for SnapshotRbxlx { .path() .file_stem() .expect("Could not extract file stem") - .to_string_lossy() + .to_str() + .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))? .to_string(); let options = rbx_xml::DecodeOptions::new() diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index f97ed19f..d98230ae 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -7,7 +7,10 @@ use crate::{ snapshot::InstanceSnapshot, }; -use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; +use super::{ + error::SnapshotError, + middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, +}; pub struct SnapshotRbxm; @@ -20,7 +23,12 @@ impl SnapshotMiddleware for SnapshotRbxm { return Ok(None); } - let file_name = entry.path().file_name().unwrap().to_string_lossy(); + let file_name = entry + .path() + .file_name() + .unwrap() + .to_str() + .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?; if !file_name.ends_with(".rbxm") { return Ok(None); @@ -30,7 +38,8 @@ impl SnapshotMiddleware for SnapshotRbxm { .path() .file_stem() .expect("Could not extract file stem") - .to_string_lossy() + .to_str() + .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))? .to_string(); let mut temp_tree = RbxTree::new(RbxInstanceProperties { diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 51ef1ed4..e08354aa 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -7,7 +7,10 @@ use crate::{ snapshot::InstanceSnapshot, }; -use super::middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}; +use super::{ + error::SnapshotError, + middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, +}; pub struct SnapshotRbxmx; @@ -20,7 +23,12 @@ impl SnapshotMiddleware for SnapshotRbxmx { return Ok(None); } - let file_name = entry.path().file_name().unwrap().to_string_lossy(); + let file_name = entry + .path() + .file_name() + .unwrap() + .to_str() + .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?; if !file_name.ends_with(".rbxmx") { return Ok(None); @@ -30,7 +38,8 @@ impl SnapshotMiddleware for SnapshotRbxmx { .path() .file_stem() .expect("Could not extract file stem") - .to_string_lossy() + .to_str() + .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))? .to_string(); let options = rbx_xml::DecodeOptions::new() From e5684ad947267815986af7df7d6e018212ae92ae Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Oct 2019 18:15:07 -0700 Subject: [PATCH 0813/1504] Add error for malformed project files --- src/snapshot_middleware/error.rs | 13 +++++++++++++ src/snapshot_middleware/project.rs | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs index 486b8324..3f1805de 100644 --- a/src/snapshot_middleware/error.rs +++ b/src/snapshot_middleware/error.rs @@ -39,6 +39,16 @@ impl SnapshotError { path: Some(path.into()), } } + + pub(crate) fn malformed_project( + inner: serde_json::Error, + path: impl Into, + ) -> SnapshotError { + SnapshotError { + detail: SnapshotErrorDetail::MalformedProject { inner }, + path: Some(path.into()), + } + } } impl Error for SnapshotError { @@ -72,6 +82,7 @@ pub enum SnapshotErrorDetail { FileDidNotExist, FileNameBadUnicode, FileContentsBadUnicode { inner: std::str::Utf8Error }, + MalformedProject { inner: serde_json::Error }, } impl SnapshotErrorDetail { @@ -81,6 +92,7 @@ impl SnapshotErrorDetail { match self { IoError { inner } => Some(inner), FileContentsBadUnicode { inner } => Some(inner), + MalformedProject { inner } => Some(inner), _ => None, } } @@ -97,6 +109,7 @@ impl fmt::Display for SnapshotErrorDetail { FileContentsBadUnicode { inner } => { write!(formatter, "file had malformed unicode: {}", inner) } + MalformedProject { inner } => write!(formatter, "{}", inner), } } } diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 64f3a71a..d110d99b 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -10,6 +10,7 @@ use crate::{ }; use super::{ + error::SnapshotError, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, snapshot_from_imfs, }; @@ -42,8 +43,7 @@ impl SnapshotMiddleware for SnapshotProject { } let project = Project::load_from_slice(entry.contents(imfs)?, entry.path()) - // TODO: Turn this into an error object - .expect("Invalid project file"); + .map_err(|err| SnapshotError::malformed_project(err, entry.path()))?; // Snapshotting a project should always return an instance, so this // unwrap is safe. From 6b620ddceff461dcb3d70bd41e5c759765ca5030 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Oct 2019 18:22:58 -0700 Subject: [PATCH 0814/1504] Add utility for working with file names, port JSON model to use it --- src/snapshot_middleware/json_model.rs | 15 ++++----------- src/snapshot_middleware/mod.rs | 1 + src/snapshot_middleware/util.rs | 20 ++++++++++++++++++++ 3 files changed, 25 insertions(+), 11 deletions(-) create mode 100644 src/snapshot_middleware/util.rs diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 65f90d77..4725545b 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -10,8 +10,8 @@ use crate::{ }; use super::{ - error::SnapshotError, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + util::match_file_name, }; pub struct SnapshotJsonModel; @@ -25,15 +25,8 @@ impl SnapshotMiddleware for SnapshotJsonModel { return Ok(None); } - let file_name = entry - .path() - .file_name() - .unwrap() - .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?; - - let instance_name = match match_trailing(&file_name, ".model.json") { - Some(name) => name.to_owned(), + let instance_name = match match_file_name(entry.path(), ".model.json") { + Some(name) => name, None => return Ok(None), }; @@ -58,7 +51,7 @@ impl SnapshotMiddleware for SnapshotJsonModel { } } - let mut snapshot = instance.core.into_snapshot(instance_name); + let mut snapshot = instance.core.into_snapshot(instance_name.to_owned()); snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index d8cfa355..a31fdb10 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -16,6 +16,7 @@ mod rbxlx; mod rbxm; mod rbxmx; mod txt; +mod util; pub use self::error::*; diff --git a/src/snapshot_middleware/util.rs b/src/snapshot_middleware/util.rs new file mode 100644 index 00000000..153c31c2 --- /dev/null +++ b/src/snapshot_middleware/util.rs @@ -0,0 +1,20 @@ +use std::path::Path; + +/// If the given string ends up with the given suffix, returns the portion of +/// the string before the suffix. +pub fn match_trailing<'a>(input: &'a str, suffix: &str) -> Option<&'a str> { + if input.ends_with(suffix) { + let end = input.len().saturating_sub(suffix.len()); + Some(&input[..end]) + } else { + None + } +} + +/// If the given path has a file name, and that file name ends with the given +/// suffix, returns the portion of the file name before the given suffix. +pub fn match_file_name<'a>(path: &'a Path, suffix: &str) -> Option<&'a str> { + let file_name = path.file_name()?.to_str()?; + + match_trailing(&file_name, suffix) +} From e46f9fd94f16a014263a35824e2f98097709a5aa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Oct 2019 18:27:52 -0700 Subject: [PATCH 0815/1504] Simplify snapshot code using match_file_name utility --- src/snapshot_middleware/csv.rs | 22 ++++------------------ src/snapshot_middleware/lua.rs | 10 +--------- src/snapshot_middleware/rbxlx.rs | 26 ++++++-------------------- src/snapshot_middleware/rbxm.rs | 26 ++++++-------------------- src/snapshot_middleware/rbxmx.rs | 26 ++++++-------------------- src/snapshot_middleware/txt.rs | 21 ++++----------------- 6 files changed, 27 insertions(+), 104 deletions(-) diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index fe3e6753..4aeeb995 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -10,9 +10,9 @@ use crate::{ }; use super::{ - error::SnapshotError, meta_file::AdjacentMetadata, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + util::match_file_name, }; pub struct SnapshotCsv; @@ -26,25 +26,11 @@ impl SnapshotMiddleware for SnapshotCsv { return Ok(None); } - let extension = match entry.path().extension() { - Some(x) => x - .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?, + let instance_name = match match_file_name(entry.path(), ".csv") { + Some(name) => name, None => return Ok(None), }; - if extension != "csv" { - return Ok(None); - } - - let instance_name = entry - .path() - .file_stem() - .expect("Could not extract file stem") - .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))? - .to_string(); - let meta_path = entry .path() .with_file_name(format!("{}.meta.json", instance_name)); @@ -58,7 +44,7 @@ impl SnapshotMiddleware for SnapshotCsv { relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], ..Default::default() }, - name: Cow::Owned(instance_name), + name: Cow::Owned(instance_name.to_owned()), class_name: Cow::Borrowed("LocalizationTable"), properties: hashmap! { "Contents".to_owned() => RbxValue::String { diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 8fe810c4..bd3553d6 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -12,6 +12,7 @@ use super::{ dir::SnapshotDir, meta_file::AdjacentMetadata, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + util::match_trailing, }; pub struct SnapshotLua; @@ -146,15 +147,6 @@ fn snapshot_init( Ok(None) } -fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { - if input.ends_with(trailer) { - let end = input.len().saturating_sub(trailer.len()); - Some(&input[..end]) - } else { - None - } -} - #[cfg(test)] mod test { use super::*; diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index 663a4aeb..8801dd60 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -8,8 +8,8 @@ use crate::{ }; use super::{ - error::SnapshotError, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + util::match_file_name, }; pub struct SnapshotRbxlx; @@ -23,24 +23,10 @@ impl SnapshotMiddleware for SnapshotRbxlx { return Ok(None); } - let file_name = entry - .path() - .file_name() - .unwrap() - .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?; - - if !file_name.ends_with(".rbxlx") { - return Ok(None); - } - - let instance_name = entry - .path() - .file_stem() - .expect("Could not extract file stem") - .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))? - .to_string(); + let instance_name = match match_file_name(entry.path(), ".rbxlx") { + Some(name) => name, + None => return Ok(None), + }; let options = rbx_xml::DecodeOptions::new() .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); @@ -51,7 +37,7 @@ impl SnapshotMiddleware for SnapshotRbxlx { let root_id = temp_tree.get_root_id(); let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, root_id); - snapshot.name = Cow::Owned(instance_name); + snapshot.name = Cow::Owned(instance_name.to_owned()); snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index d98230ae..52983ce6 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -8,8 +8,8 @@ use crate::{ }; use super::{ - error::SnapshotError, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + util::match_file_name, }; pub struct SnapshotRbxm; @@ -23,24 +23,10 @@ impl SnapshotMiddleware for SnapshotRbxm { return Ok(None); } - let file_name = entry - .path() - .file_name() - .unwrap() - .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?; - - if !file_name.ends_with(".rbxm") { - return Ok(None); - } - - let instance_name = entry - .path() - .file_stem() - .expect("Could not extract file stem") - .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))? - .to_string(); + let instance_name = match match_file_name(entry.path(), ".rbxm") { + Some(name) => name, + None => return Ok(None), + }; let mut temp_tree = RbxTree::new(RbxInstanceProperties { name: "DataModel".to_owned(), @@ -57,7 +43,7 @@ impl SnapshotMiddleware for SnapshotRbxm { if children.len() == 1 { let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); - snapshot.name = Cow::Owned(instance_name); + snapshot.name = Cow::Owned(instance_name.to_owned()); snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index e08354aa..df5279f9 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -8,8 +8,8 @@ use crate::{ }; use super::{ - error::SnapshotError, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + util::match_file_name, }; pub struct SnapshotRbxmx; @@ -23,24 +23,10 @@ impl SnapshotMiddleware for SnapshotRbxmx { return Ok(None); } - let file_name = entry - .path() - .file_name() - .unwrap() - .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?; - - if !file_name.ends_with(".rbxmx") { - return Ok(None); - } - - let instance_name = entry - .path() - .file_stem() - .expect("Could not extract file stem") - .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))? - .to_string(); + let instance_name = match match_file_name(entry.path(), ".rbxmx") { + Some(name) => name, + None => return Ok(None), + }; let options = rbx_xml::DecodeOptions::new() .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); @@ -53,7 +39,7 @@ impl SnapshotMiddleware for SnapshotRbxmx { if children.len() == 1 { let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); - snapshot.name = Cow::Owned(instance_name); + snapshot.name = Cow::Owned(instance_name.to_owned()); snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index a939a100..65abb657 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -12,6 +12,7 @@ use super::{ error::SnapshotError, meta_file::AdjacentMetadata, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + util::match_file_name, }; pub struct SnapshotTxt; @@ -25,25 +26,11 @@ impl SnapshotMiddleware for SnapshotTxt { return Ok(None); } - let extension = match entry.path().extension() { - Some(x) => x - .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))?, + let instance_name = match match_file_name(entry.path(), ".txt") { + Some(name) => name, None => return Ok(None), }; - if extension != "txt" { - return Ok(None); - } - - let instance_name = entry - .path() - .file_stem() - .expect("Could not extract file stem") - .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))? - .to_string(); - let contents = entry.contents(imfs)?; let contents_str = str::from_utf8(contents) .map_err(|err| SnapshotError::file_contents_bad_unicode(err, entry.path()))? @@ -66,7 +53,7 @@ impl SnapshotMiddleware for SnapshotTxt { relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], ..Default::default() }, - name: Cow::Owned(instance_name), + name: Cow::Owned(instance_name.to_owned()), class_name: Cow::Borrowed("StringValue"), properties, children: Vec::new(), From 6d38a785ed0dea558675680de060ab1cac1972b0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 10 Oct 2019 10:43:55 -0700 Subject: [PATCH 0816/1504] Make SnapshotMiddleware::from_instance have a default impl --- src/snapshot_middleware/csv.rs | 8 ++------ src/snapshot_middleware/json_model.rs | 8 ++------ src/snapshot_middleware/lua.rs | 15 ++------------- src/snapshot_middleware/middleware.rs | 4 +++- src/snapshot_middleware/project.rs | 8 +------- src/snapshot_middleware/rbxlx.rs | 8 +------- src/snapshot_middleware/rbxm.rs | 8 ++------ src/snapshot_middleware/rbxmx.rs | 8 +------- 8 files changed, 14 insertions(+), 53 deletions(-) diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 4aeeb995..06727820 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -1,7 +1,7 @@ use std::{borrow::Cow, collections::BTreeMap}; use maplit::hashmap; -use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; +use rbx_dom_weak::RbxValue; use serde::Serialize; use crate::{ @@ -11,7 +11,7 @@ use crate::{ use super::{ meta_file::AdjacentMetadata, - middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -62,10 +62,6 @@ impl SnapshotMiddleware for SnapshotCsv { Ok(Some(snapshot)) } - - fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { - unimplemented!("Snapshotting CSV localization tables"); - } } /// Struct that holds any valid row from a Roblox CSV translation table. diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 4725545b..fbee2418 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, collections::HashMap}; -use rbx_dom_weak::{RbxId, RbxTree, UnresolvedRbxValue}; +use rbx_dom_weak::UnresolvedRbxValue; use rbx_reflection::try_resolve_value; use serde::Deserialize; @@ -10,7 +10,7 @@ use crate::{ }; use super::{ - middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -58,10 +58,6 @@ impl SnapshotMiddleware for SnapshotJsonModel { Ok(Some(snapshot)) } - - fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { - unimplemented!("Snapshotting models"); - } } fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index bd3553d6..4c0655cc 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -1,7 +1,7 @@ use std::{borrow::Cow, str}; use maplit::hashmap; -use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; +use rbx_dom_weak::RbxValue; use crate::{ imfs::{FsResultExt, Imfs, ImfsEntry, ImfsFetcher}, @@ -11,7 +11,7 @@ use crate::{ use super::{ dir::SnapshotDir, meta_file::AdjacentMetadata, - middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_trailing, }; @@ -48,17 +48,6 @@ impl SnapshotMiddleware for SnapshotLua { } } } - - fn from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult { - let instance = tree.get_instance(id).unwrap(); - - match instance.class_name.as_str() { - "ModuleScript" | "LocalScript" | "Script" => { - unimplemented!("Snapshotting Script instances") - } - _ => None, - } - } } /// Core routine for turning Lua files into snapshots. diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index 66c2f673..71ed5e9a 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -18,7 +18,9 @@ pub trait SnapshotMiddleware { entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static>; - fn from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult; + fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { + None + } fn change_affects_paths(path: &Path) -> Vec { vec![path.to_path_buf()] diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index d110d99b..3c1d296a 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -1,6 +1,5 @@ use std::{borrow::Cow, collections::HashMap}; -use rbx_dom_weak::{RbxId, RbxTree}; use rbx_reflection::try_resolve_value; use crate::{ @@ -11,7 +10,7 @@ use crate::{ use super::{ error::SnapshotError, - middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + middleware::{SnapshotInstanceResult, SnapshotMiddleware}, snapshot_from_imfs, }; @@ -72,11 +71,6 @@ impl SnapshotMiddleware for SnapshotProject { Ok(Some(snapshot)) } - - fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { - // TODO: Supporting turning instances into projects - None - } } fn snapshot_project_node( diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index 8801dd60..bc88c979 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -1,14 +1,12 @@ use std::borrow::Cow; -use rbx_dom_weak::{RbxId, RbxTree}; - use crate::{ imfs::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, }; use super::{ - middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -43,8 +41,4 @@ impl SnapshotMiddleware for SnapshotRbxlx { Ok(Some(snapshot)) } - - fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { - None - } } diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 52983ce6..1723757e 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, collections::HashMap}; -use rbx_dom_weak::{RbxId, RbxInstanceProperties, RbxTree}; +use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; use crate::{ imfs::{Imfs, ImfsEntry, ImfsFetcher}, @@ -8,7 +8,7 @@ use crate::{ }; use super::{ - middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -52,10 +52,6 @@ impl SnapshotMiddleware for SnapshotRbxm { panic!("Rojo doesn't have support for model files with zero or more than one top-level instances yet."); } } - - fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { - unimplemented!("Snapshotting models"); - } } #[cfg(test)] diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index df5279f9..e3a20a2b 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -1,14 +1,12 @@ use std::borrow::Cow; -use rbx_dom_weak::{RbxId, RbxTree}; - use crate::{ imfs::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, }; use super::{ - middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -48,10 +46,6 @@ impl SnapshotMiddleware for SnapshotRbxmx { panic!("Rojo doesn't have support for model files with zero or more than one top-level instances yet."); } } - - fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { - unimplemented!("Snapshotting models"); - } } #[cfg(test)] From f0cd4333c364e3a4a1402cf453022443c84faa1e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 10 Oct 2019 11:44:33 -0700 Subject: [PATCH 0817/1504] Thread InstanceSnapshotContext through all SnapshotMiddleware --- src/snapshot_middleware/context.rs | 9 ++++ src/snapshot_middleware/csv.rs | 12 ++++- src/snapshot_middleware/dir.rs | 12 ++++- src/snapshot_middleware/json_model.rs | 9 ++-- src/snapshot_middleware/lua.rs | 41 ++++++++++++---- src/snapshot_middleware/middleware.rs | 3 +- src/snapshot_middleware/mod.rs | 5 +- src/snapshot_middleware/project.rs | 67 ++++++++++++++++----------- src/snapshot_middleware/rbxlx.rs | 2 + src/snapshot_middleware/rbxm.rs | 7 ++- src/snapshot_middleware/rbxmx.rs | 9 ++-- src/snapshot_middleware/txt.rs | 7 ++- 12 files changed, 131 insertions(+), 52 deletions(-) diff --git a/src/snapshot_middleware/context.rs b/src/snapshot_middleware/context.rs index f423c027..b10e7192 100644 --- a/src/snapshot_middleware/context.rs +++ b/src/snapshot_middleware/context.rs @@ -1,7 +1,16 @@ +#[derive(Debug)] pub struct InstanceSnapshotContext { /// Empty struct that will be used later to fill out required Lua state for /// user plugins. pub plugin_context: Option<()>, } +impl Default for InstanceSnapshotContext { + fn default() -> Self { + Self { + plugin_context: None, + } + } +} + pub struct ImfsSnapshotContext; diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 06727820..28876634 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -10,6 +10,7 @@ use crate::{ }; use super::{ + context::InstanceSnapshotContext, meta_file::AdjacentMetadata, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, @@ -19,6 +20,7 @@ pub struct SnapshotCsv; impl SnapshotMiddleware for SnapshotCsv { fn from_imfs( + _context: &InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -159,7 +161,10 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, imfs.debug_load_snapshot("/foo.csv", file); let entry = imfs.get("/foo.csv").unwrap(); - let instance_snapshot = SnapshotCsv::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = + SnapshotCsv::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); assert_yaml_snapshot!(instance_snapshot); } @@ -178,7 +183,10 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, imfs.debug_load_snapshot("/foo.meta.json", meta); let entry = imfs.get("/foo.csv").unwrap(); - let instance_snapshot = SnapshotCsv::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = + SnapshotCsv::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); assert_yaml_snapshot!(instance_snapshot); } diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 970cc92b..ba499d26 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -8,6 +8,7 @@ use crate::{ }; use super::{ + context::InstanceSnapshotContext, error::SnapshotError, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, snapshot_from_imfs, snapshot_from_instance, @@ -17,6 +18,7 @@ pub struct SnapshotDir; impl SnapshotMiddleware for SnapshotDir { fn from_imfs( + _context: &InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -94,7 +96,10 @@ mod test { imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); - let instance_snapshot = SnapshotDir::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = + SnapshotDir::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); assert_yaml_snapshot!(instance_snapshot); } @@ -109,7 +114,10 @@ mod test { imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); - let instance_snapshot = SnapshotDir::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = + SnapshotDir::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); assert_yaml_snapshot!(instance_snapshot); } diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index fbee2418..23631439 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -10,6 +10,7 @@ use crate::{ }; use super::{ + context::InstanceSnapshotContext, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -18,6 +19,7 @@ pub struct SnapshotJsonModel; impl SnapshotMiddleware for SnapshotJsonModel { fn from_imfs( + _context: &InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -161,9 +163,10 @@ mod test { imfs.debug_load_snapshot("/foo.model.json", file); let entry = imfs.get("/foo.model.json").unwrap(); - let instance_snapshot = SnapshotJsonModel::from_imfs(&mut imfs, &entry) - .unwrap() - .unwrap(); + let instance_snapshot = + SnapshotJsonModel::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); assert_yaml_snapshot!(instance_snapshot); } diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 4c0655cc..fc7da815 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -9,6 +9,7 @@ use crate::{ }; use super::{ + context::InstanceSnapshotContext, dir::SnapshotDir, meta_file::AdjacentMetadata, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, @@ -19,6 +20,7 @@ pub struct SnapshotLua; impl SnapshotMiddleware for SnapshotLua { fn from_imfs( + context: &InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -34,13 +36,13 @@ impl SnapshotMiddleware for SnapshotLua { if entry.is_file() { snapshot_lua_file(imfs, entry) } else { - if let Some(snapshot) = snapshot_init(imfs, entry, "init.lua")? { + if let Some(snapshot) = snapshot_init(context, imfs, entry, "init.lua")? { // An `init.lua` file turns its parent into a ModuleScript Ok(Some(snapshot)) - } else if let Some(snapshot) = snapshot_init(imfs, entry, "init.server.lua")? { + } else if let Some(snapshot) = snapshot_init(context, imfs, entry, "init.server.lua")? { // An `init.server.lua` file turns its parent into a Script Ok(Some(snapshot)) - } else if let Some(snapshot) = snapshot_init(imfs, entry, "init.client.lua")? { + } else if let Some(snapshot) = snapshot_init(context, imfs, entry, "init.client.lua")? { // An `init.client.lua` file turns its parent into a LocalScript Ok(Some(snapshot)) } else { @@ -114,6 +116,7 @@ fn snapshot_lua_file( /// Scripts named `init.lua`, `init.server.lua`, or `init.client.lua` usurp /// their parents, which acts similarly to `__init__.py` from the Python world. fn snapshot_init( + context: &InstanceSnapshotContext, imfs: &mut Imfs, folder_entry: &ImfsEntry, init_name: &str, @@ -121,7 +124,7 @@ fn snapshot_init( let init_path = folder_entry.path().join(init_name); if let Some(init_entry) = imfs.get(init_path).with_not_found()? { - if let Some(dir_snapshot) = SnapshotDir::from_imfs(imfs, folder_entry)? { + if let Some(dir_snapshot) = SnapshotDir::from_imfs(context, imfs, folder_entry)? { if let Some(mut init_snapshot) = snapshot_lua_file(imfs, &init_entry)? { init_snapshot.name = dir_snapshot.name; init_snapshot.children = dir_snapshot.children; @@ -152,7 +155,10 @@ mod test { imfs.debug_load_snapshot("/foo.lua", file); let entry = imfs.get("/foo.lua").unwrap(); - let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = + SnapshotLua::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); assert_yaml_snapshot!(instance_snapshot); } @@ -165,7 +171,10 @@ mod test { imfs.debug_load_snapshot("/foo.server.lua", file); let entry = imfs.get("/foo.server.lua").unwrap(); - let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = + SnapshotLua::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); assert_yaml_snapshot!(instance_snapshot); } @@ -178,7 +187,10 @@ mod test { imfs.debug_load_snapshot("/foo.client.lua", file); let entry = imfs.get("/foo.client.lua").unwrap(); - let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = + SnapshotLua::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); assert_yaml_snapshot!(instance_snapshot); } @@ -199,7 +211,10 @@ mod test { imfs.debug_load_snapshot("/foo.meta.json", meta); let entry = imfs.get("/foo.lua").unwrap(); - let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = + SnapshotLua::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); assert_yaml_snapshot!(instance_snapshot); } @@ -220,7 +235,10 @@ mod test { imfs.debug_load_snapshot("/foo.meta.json", meta); let entry = imfs.get("/foo.server.lua").unwrap(); - let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = + SnapshotLua::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); assert_yaml_snapshot!(instance_snapshot); } @@ -243,7 +261,10 @@ mod test { imfs.debug_load_snapshot("/bar.meta.json", meta); let entry = imfs.get("/bar.server.lua").unwrap(); - let instance_snapshot = SnapshotLua::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = + SnapshotLua::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); with_settings!({ sort_maps => true }, { assert_yaml_snapshot!(instance_snapshot); diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index 71ed5e9a..5b4d96c8 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -7,13 +7,14 @@ use crate::{ snapshot::InstanceSnapshot, }; -use super::error::SnapshotError; +use super::{context::InstanceSnapshotContext, error::SnapshotError}; pub type SnapshotInstanceResult<'a> = Result>, SnapshotError>; pub type SnapshotFileResult = Option<(String, ImfsSnapshot)>; pub trait SnapshotMiddleware { fn from_imfs( + context: &InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static>; diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index a31fdb10..dae68d5a 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -23,6 +23,7 @@ pub use self::error::*; use rbx_dom_weak::{RbxId, RbxTree}; use self::{ + context::InstanceSnapshotContext, csv::SnapshotCsv, dir::SnapshotDir, json_model::SnapshotJsonModel, @@ -43,10 +44,12 @@ macro_rules! middlewares { imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { + let context = InstanceSnapshotContext::default(); + $( log::trace!("trying middleware {} on {}", stringify!($middleware), entry.path().display()); - if let Some(snapshot) = $middleware::from_imfs(imfs, entry)? { + if let Some(snapshot) = $middleware::from_imfs(&context, imfs, entry)? { log::trace!("middleware {} success on {}", stringify!($middleware), entry.path().display()); return Ok(Some(snapshot)); } diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 3c1d296a..7266c398 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -9,6 +9,7 @@ use crate::{ }; use super::{ + context::InstanceSnapshotContext, error::SnapshotError, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, snapshot_from_imfs, @@ -21,6 +22,7 @@ pub struct SnapshotProject; impl SnapshotMiddleware for SnapshotProject { fn from_imfs( + context: &InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -31,7 +33,7 @@ impl SnapshotMiddleware for SnapshotProject { // TODO: Do we need to muck with the relevant paths if we're a // project file within a folder? Should the folder path be the // relevant path instead of the project file path? - Some(entry) => return SnapshotProject::from_imfs(imfs, &entry), + Some(entry) => return SnapshotProject::from_imfs(context, imfs, &entry), None => return Ok(None), } } @@ -209,9 +211,10 @@ mod test { imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); - let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = + SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); assert_yaml_snapshot!(instance_snapshot); } @@ -235,9 +238,10 @@ mod test { imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo/hello.project.json").unwrap(); - let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = + SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); assert_yaml_snapshot!(instance_snapshot); } @@ -267,9 +271,10 @@ mod test { imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); - let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = + SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); assert_yaml_snapshot!(instance_snapshot); } @@ -296,9 +301,10 @@ mod test { imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); - let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = + SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); assert_yaml_snapshot!(instance_snapshot); } @@ -326,9 +332,10 @@ mod test { imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); - let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = + SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); assert_yaml_snapshot!(instance_snapshot); } @@ -353,9 +360,10 @@ mod test { imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); - let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = + SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); assert_yaml_snapshot!(instance_snapshot); } @@ -387,9 +395,10 @@ mod test { imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); - let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = + SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); assert_yaml_snapshot!(instance_snapshot); } @@ -425,9 +434,10 @@ mod test { imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); - let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = + SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); assert_yaml_snapshot!(instance_snapshot); } @@ -468,9 +478,10 @@ mod test { imfs.debug_load_snapshot("/foo", dir); let entry = imfs.get("/foo").unwrap(); - let instance_snapshot = SnapshotProject::from_imfs(&mut imfs, &entry) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = + SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .expect("snapshot error") + .expect("snapshot returned no instances"); assert_yaml_snapshot!(instance_snapshot); } diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index bc88c979..f5e610df 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -6,6 +6,7 @@ use crate::{ }; use super::{ + context::InstanceSnapshotContext, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -14,6 +15,7 @@ pub struct SnapshotRbxlx; impl SnapshotMiddleware for SnapshotRbxlx { fn from_imfs( + _context: &InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 1723757e..2a1d910a 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -8,6 +8,7 @@ use crate::{ }; use super::{ + context::InstanceSnapshotContext, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -16,6 +17,7 @@ pub struct SnapshotRbxm; impl SnapshotMiddleware for SnapshotRbxm { fn from_imfs( + _context: &InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -68,7 +70,10 @@ mod test { imfs.debug_load_snapshot("/foo.rbxm", file); let entry = imfs.get("/foo.rbxm").unwrap(); - let instance_snapshot = SnapshotRbxm::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = + SnapshotRbxm::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); assert_eq!(instance_snapshot.name, "foo"); assert_eq!(instance_snapshot.class_name, "Folder"); diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index e3a20a2b..8e29cd9c 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -6,6 +6,7 @@ use crate::{ }; use super::{ + context::InstanceSnapshotContext, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -14,6 +15,7 @@ pub struct SnapshotRbxmx; impl SnapshotMiddleware for SnapshotRbxmx { fn from_imfs( + _context: &InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -74,9 +76,10 @@ mod test { imfs.debug_load_snapshot("/foo.rbxmx", file); let entry = imfs.get("/foo.rbxmx").unwrap(); - let instance_snapshot = SnapshotRbxmx::from_imfs(&mut imfs, &entry) - .unwrap() - .unwrap(); + let instance_snapshot = + SnapshotRbxmx::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); assert_eq!(instance_snapshot.name, "foo"); assert_eq!(instance_snapshot.class_name, "Folder"); diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 65abb657..4d952041 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -9,6 +9,7 @@ use crate::{ }; use super::{ + context::InstanceSnapshotContext, error::SnapshotError, meta_file::AdjacentMetadata, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, @@ -19,6 +20,7 @@ pub struct SnapshotTxt; impl SnapshotMiddleware for SnapshotTxt { fn from_imfs( + _context: &InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -114,7 +116,10 @@ mod test { imfs.debug_load_snapshot("/foo.txt", file); let entry = imfs.get("/foo.txt").unwrap(); - let instance_snapshot = SnapshotTxt::from_imfs(&mut imfs, &entry).unwrap().unwrap(); + let instance_snapshot = + SnapshotTxt::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + .unwrap() + .unwrap(); assert_yaml_snapshot!(instance_snapshot); } From f3dc78b7cd35968219d247214a112edd6d51cb2e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 10 Oct 2019 14:07:10 -0700 Subject: [PATCH 0818/1504] Make InstanceSnapshotContext mutable through whole middleware pipeline --- src/snapshot_middleware/csv.rs | 6 +++--- src/snapshot_middleware/dir.rs | 6 +++--- src/snapshot_middleware/json_model.rs | 13 ++++++++----- src/snapshot_middleware/lua.rs | 16 ++++++++-------- src/snapshot_middleware/middleware.rs | 2 +- src/snapshot_middleware/mod.rs | 4 ++-- src/snapshot_middleware/project.rs | 20 ++++++++++---------- src/snapshot_middleware/rbxlx.rs | 2 +- src/snapshot_middleware/rbxm.rs | 4 ++-- src/snapshot_middleware/rbxmx.rs | 4 ++-- src/snapshot_middleware/txt.rs | 4 ++-- 11 files changed, 42 insertions(+), 39 deletions(-) diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 28876634..0cf16cfc 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -20,7 +20,7 @@ pub struct SnapshotCsv; impl SnapshotMiddleware for SnapshotCsv { fn from_imfs( - _context: &InstanceSnapshotContext, + _context: &mut InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -162,7 +162,7 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, let entry = imfs.get("/foo.csv").unwrap(); let instance_snapshot = - SnapshotCsv::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotCsv::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .unwrap() .unwrap(); @@ -184,7 +184,7 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, let entry = imfs.get("/foo.csv").unwrap(); let instance_snapshot = - SnapshotCsv::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotCsv::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index ba499d26..1c36dc6f 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -18,7 +18,7 @@ pub struct SnapshotDir; impl SnapshotMiddleware for SnapshotDir { fn from_imfs( - _context: &InstanceSnapshotContext, + _context: &mut InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -97,7 +97,7 @@ mod test { let entry = imfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotDir::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotDir::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .unwrap() .unwrap(); @@ -115,7 +115,7 @@ mod test { let entry = imfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotDir::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotDir::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 23631439..accec10f 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -19,7 +19,7 @@ pub struct SnapshotJsonModel; impl SnapshotMiddleware for SnapshotJsonModel { fn from_imfs( - _context: &InstanceSnapshotContext, + _context: &mut InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -163,10 +163,13 @@ mod test { imfs.debug_load_snapshot("/foo.model.json", file); let entry = imfs.get("/foo.model.json").unwrap(); - let instance_snapshot = - SnapshotJsonModel::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) - .unwrap() - .unwrap(); + let instance_snapshot = SnapshotJsonModel::from_imfs( + &mut InstanceSnapshotContext::default(), + &mut imfs, + &entry, + ) + .unwrap() + .unwrap(); assert_yaml_snapshot!(instance_snapshot); } diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index fc7da815..13df304f 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -20,7 +20,7 @@ pub struct SnapshotLua; impl SnapshotMiddleware for SnapshotLua { fn from_imfs( - context: &InstanceSnapshotContext, + context: &mut InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -116,7 +116,7 @@ fn snapshot_lua_file( /// Scripts named `init.lua`, `init.server.lua`, or `init.client.lua` usurp /// their parents, which acts similarly to `__init__.py` from the Python world. fn snapshot_init( - context: &InstanceSnapshotContext, + context: &mut InstanceSnapshotContext, imfs: &mut Imfs, folder_entry: &ImfsEntry, init_name: &str, @@ -156,7 +156,7 @@ mod test { let entry = imfs.get("/foo.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .unwrap() .unwrap(); @@ -172,7 +172,7 @@ mod test { let entry = imfs.get("/foo.server.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .unwrap() .unwrap(); @@ -188,7 +188,7 @@ mod test { let entry = imfs.get("/foo.client.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .unwrap() .unwrap(); @@ -212,7 +212,7 @@ mod test { let entry = imfs.get("/foo.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .unwrap() .unwrap(); @@ -236,7 +236,7 @@ mod test { let entry = imfs.get("/foo.server.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .unwrap() .unwrap(); @@ -262,7 +262,7 @@ mod test { let entry = imfs.get("/bar.server.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index 5b4d96c8..08c24df6 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -14,7 +14,7 @@ pub type SnapshotFileResult = Option<(String, ImfsSnapshot)>; pub trait SnapshotMiddleware { fn from_imfs( - context: &InstanceSnapshotContext, + context: &mut InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static>; diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index dae68d5a..26968482 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -44,12 +44,12 @@ macro_rules! middlewares { imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { - let context = InstanceSnapshotContext::default(); + let mut context = InstanceSnapshotContext::default(); $( log::trace!("trying middleware {} on {}", stringify!($middleware), entry.path().display()); - if let Some(snapshot) = $middleware::from_imfs(&context, imfs, entry)? { + if let Some(snapshot) = $middleware::from_imfs(&mut context, imfs, entry)? { log::trace!("middleware {} success on {}", stringify!($middleware), entry.path().display()); return Ok(Some(snapshot)); } diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 7266c398..d1e0d9f4 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -22,7 +22,7 @@ pub struct SnapshotProject; impl SnapshotMiddleware for SnapshotProject { fn from_imfs( - context: &InstanceSnapshotContext, + context: &mut InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -212,7 +212,7 @@ mod test { let entry = imfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -239,7 +239,7 @@ mod test { let entry = imfs.get("/foo/hello.project.json").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -272,7 +272,7 @@ mod test { let entry = imfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -302,7 +302,7 @@ mod test { let entry = imfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -333,7 +333,7 @@ mod test { let entry = imfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -361,7 +361,7 @@ mod test { let entry = imfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -396,7 +396,7 @@ mod test { let entry = imfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -435,7 +435,7 @@ mod test { let entry = imfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -479,7 +479,7 @@ mod test { let entry = imfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index f5e610df..531ef4d8 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -15,7 +15,7 @@ pub struct SnapshotRbxlx; impl SnapshotMiddleware for SnapshotRbxlx { fn from_imfs( - _context: &InstanceSnapshotContext, + _context: &mut InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 2a1d910a..7d11751a 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -17,7 +17,7 @@ pub struct SnapshotRbxm; impl SnapshotMiddleware for SnapshotRbxm { fn from_imfs( - _context: &InstanceSnapshotContext, + _context: &mut InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -71,7 +71,7 @@ mod test { let entry = imfs.get("/foo.rbxm").unwrap(); let instance_snapshot = - SnapshotRbxm::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotRbxm::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 8e29cd9c..663c2f0d 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -15,7 +15,7 @@ pub struct SnapshotRbxmx; impl SnapshotMiddleware for SnapshotRbxmx { fn from_imfs( - _context: &InstanceSnapshotContext, + _context: &mut InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -77,7 +77,7 @@ mod test { let entry = imfs.get("/foo.rbxmx").unwrap(); let instance_snapshot = - SnapshotRbxmx::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotRbxmx::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 4d952041..11584d15 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -20,7 +20,7 @@ pub struct SnapshotTxt; impl SnapshotMiddleware for SnapshotTxt { fn from_imfs( - _context: &InstanceSnapshotContext, + _context: &mut InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -117,7 +117,7 @@ mod test { let entry = imfs.get("/foo.txt").unwrap(); let instance_snapshot = - SnapshotTxt::from_imfs(&InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotTxt::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .unwrap() .unwrap(); From b093626a21fcc72fc30101d6000d10fdba97934c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 11 Oct 2019 15:45:02 -0700 Subject: [PATCH 0819/1504] User plugin foundations for 0.6.0 (#257) Starts work on #55. This is similar to the previous work in #125. It's gated behind a new Cargo feature, `user-plugins`. This time, the config gate is much smaller. The `plugins` member of projects is still accessible when plugins aren't enabled, but is always empty. Additionally, user plugins are only enabled if there's a Lua state present in the snapshot context when the `SnapshotUserPlugins` snapshot middleware runs. This not ever the case currently. This code has very little possibility of rotting while we focus on other work, since it'll be guaranteed to still compile and can be tested in isolation without the feature being turned on. --- Cargo.lock | 22 ++++ Cargo.toml | 5 + src/change_processor.rs | 7 +- src/commands/build.rs | 5 +- src/commands/upload.rs | 5 +- src/project.rs | 28 +++++ src/serve_session.rs | 10 +- src/snapshot_middleware/context.rs | 49 ++++++++- src/snapshot_middleware/dir.rs | 4 +- src/snapshot_middleware/error.rs | 30 +++++- src/snapshot_middleware/mod.rs | 10 +- src/snapshot_middleware/project.rs | 8 +- src/snapshot_middleware/user_plugins.rs | 114 +++++++++++++++++++++ test-projects/plugins/default.project.json | 9 ++ test-projects/plugins/src/hello.moon | 1 + test-projects/plugins/test-plugin.lua | 20 ++++ tests/read_projects.rs | 1 + 17 files changed, 306 insertions(+), 22 deletions(-) create mode 100644 src/snapshot_middleware/user_plugins.rs create mode 100644 test-projects/plugins/default.project.json create mode 100644 test-projects/plugins/src/hello.moon create mode 100644 test-projects/plugins/test-plugin.lua diff --git a/Cargo.lock b/Cargo.lock index 9f2c1f6a..3d072dec 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -920,6 +920,14 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "num-traits" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num_cpus" version = "1.10.1" @@ -1450,6 +1458,17 @@ dependencies = [ "snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rlua" +version = "0.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rojo" version = "0.6.0-dev" @@ -1477,6 +1496,7 @@ dependencies = [ "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", "rojo-insta-ext 0.1.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2294,6 +2314,7 @@ dependencies = [ "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" "checksum notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1191efa2b8fe041decb55c238a125b7a1aeb6fad7a525133a02be5ec949ff3cb" +"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" @@ -2350,6 +2371,7 @@ dependencies = [ "checksum reqwest 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)" = "02b7e953e14c6f3102b7e8d1f1ee3abf5ecee80b427f5565c9389835cecae95c" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" +"checksum rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62fc0e980c94fe9ef795b1bb3874649c8c6e9bb67d3b90d48380ba24c69c23ea" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" diff --git a/Cargo.toml b/Cargo.toml index e52c5fae..3408bb39 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,10 @@ default = [] # Enable this feature to live-reload assets from the web UI. dev-live-assets = [] +# Enables specifying user plugins in the project file. User plugins are Lua +# files and currently not fully implemented. See issue #55. +user-plugins = [] + [workspace] members = [ "rojo-test", @@ -58,6 +62,7 @@ rbx_xml = "0.11.0" regex = "1.0" reqwest = "0.9.20" ritz = "0.1.0" +rlua = "0.16.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" termcolor = "1.0.5" diff --git a/src/change_processor.rs b/src/change_processor.rs index 533a982c..e0ad8496 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -12,7 +12,7 @@ use crate::{ imfs::{Imfs, ImfsEvent, ImfsFetcher}, message_queue::MessageQueue, snapshot::{apply_patch_set, compute_patch_set, AppliedPatchSet, InstigatingSource, RojoTree}, - snapshot_middleware::snapshot_from_imfs, + snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext}, }; pub struct ChangeProcessor { @@ -99,7 +99,10 @@ impl ChangeProcessor { .get(path) .expect("could not get instigating path from filesystem"); - let snapshot = snapshot_from_imfs(&mut imfs, &entry) + // TODO: Use persisted snapshot + // context struct instead of + // recreating it every time. + let snapshot = snapshot_from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .expect("snapshot failed") .expect("snapshot did not return an instance"); diff --git a/src/commands/build.rs b/src/commands/build.rs index f3dad7bd..de10ef34 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -11,7 +11,7 @@ use rbx_dom_weak::RbxInstanceProperties; use crate::{ imfs::{FsError, Imfs, RealFetcher, WatchMode}, snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, - snapshot_middleware::snapshot_from_imfs, + snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -96,8 +96,9 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { .get(&options.fuzzy_project_path) .expect("could not get project path"); + // TODO: Compute snapshot context from project. log::trace!("Generating snapshot of instances from IMFS"); - let snapshot = snapshot_from_imfs(&mut imfs, &entry) + let snapshot = snapshot_from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .expect("snapshot failed") .expect("snapshot did not return an instance"); diff --git a/src/commands/upload.rs b/src/commands/upload.rs index 0aaee43e..ded0446a 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -8,7 +8,7 @@ use crate::{ auth_cookie::get_auth_cookie, imfs::{Imfs, RealFetcher, WatchMode}, snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, - snapshot_middleware::snapshot_from_imfs, + snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext}, }; #[derive(Debug, Fail)] @@ -63,8 +63,9 @@ pub fn upload(options: UploadOptions) -> Result<(), UploadError> { .get(&options.fuzzy_project_path) .expect("could not get project path"); + // TODO: Compute snapshot context from project. log::trace!("Generating snapshot of instances from IMFS"); - let snapshot = snapshot_from_imfs(&mut imfs, &entry) + let snapshot = snapshot_from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) .expect("snapshot failed") .expect("snapshot did not return an instance"); diff --git a/src/project.rs b/src/project.rs index ba0d6616..fa2e7cc8 100644 --- a/src/project.rs +++ b/src/project.rs @@ -30,6 +30,10 @@ struct SourceProject { #[serde(skip_serializing_if = "Option::is_none")] serve_place_ids: Option>, + + #[serde(default, skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(not(feature = "user-plugins"), serde(skip_deserializing))] + plugins: Vec, } impl SourceProject { @@ -37,11 +41,19 @@ impl SourceProject { pub fn into_project(self, project_file_location: &Path) -> Project { let tree = self.tree.into_project_node(project_file_location); + let project_folder = project_file_location.parent().unwrap(); + let plugins = self + .plugins + .into_iter() + .map(|path| project_folder.join(path)) + .collect(); + Project { name: self.name, tree, serve_port: self.serve_port, serve_place_ids: self.serve_place_ids, + plugins, file_location: PathBuf::from(project_file_location), } } @@ -318,6 +330,7 @@ pub struct Project { pub tree: ProjectNode, pub serve_port: Option, pub serve_place_ids: Option>, + pub plugins: Vec, pub file_location: PathBuf, } @@ -391,6 +404,7 @@ impl Project { tree, serve_port: None, serve_place_ids: None, + plugins: Vec::new(), file_location: project_path.clone(), }; @@ -557,10 +571,24 @@ impl Project { } fn to_source_project(&self) -> SourceProject { + // TODO: Use path_serializer instead of transforming paths between + // String and PathBuf? + let plugins = self + .plugins + .iter() + .map(|path| { + path.strip_prefix(self.folder_location()) + .unwrap() + .display() + .to_string() + }) + .collect(); + SourceProject { name: self.name.clone(), tree: self.tree.to_source_node(&self.file_location), serve_port: self.serve_port, + plugins, serve_place_ids: self.serve_place_ids.clone(), } } diff --git a/src/serve_session.rs b/src/serve_session.rs index 30438c26..ebac8567 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -16,7 +16,7 @@ use crate::{ snapshot::{ apply_patch_set, compute_patch_set, AppliedPatchSet, InstancePropertiesWithMeta, RojoTree, }, - snapshot_middleware::snapshot_from_imfs, + snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext}, }; /// Contains all of the state for a Rojo serve session. @@ -111,10 +111,12 @@ impl ServeSession { log::trace!("Loading start path: {}", start_path.display()); let entry = imfs.get(start_path).expect("could not get project path"); + // TODO: Compute snapshot context from project. log::trace!("Snapshotting start path"); - let snapshot = snapshot_from_imfs(&mut imfs, &entry) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); + let snapshot = + snapshot_from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); log::trace!("Computing initial patch set"); let patch_set = compute_patch_set(&snapshot, &tree, root_id); diff --git a/src/snapshot_middleware/context.rs b/src/snapshot_middleware/context.rs index b10e7192..0a7179a8 100644 --- a/src/snapshot_middleware/context.rs +++ b/src/snapshot_middleware/context.rs @@ -1,8 +1,12 @@ +use std::{fmt, ops::Deref, path::PathBuf}; + +use rlua::{Lua, RegistryKey}; + #[derive(Debug)] pub struct InstanceSnapshotContext { /// Empty struct that will be used later to fill out required Lua state for /// user plugins. - pub plugin_context: Option<()>, + pub plugin_context: Option, } impl Default for InstanceSnapshotContext { @@ -13,4 +17,47 @@ impl Default for InstanceSnapshotContext { } } +#[derive(Debug)] +pub struct SnapshotPluginContext { + pub state: IgnoreDebug, + + /// Paths to the user plugins files. These paths are generated by the root + /// project file, if there is one. + pub plugin_paths: Vec, + + /// Lazy-initialized registry keys pointing to the values returned by each + /// user plugin. When processing user plugins, these should be applied in + /// order. + pub plugin_functions: Option>, +} + +impl SnapshotPluginContext { + pub fn new(plugin_paths: Vec) -> Self { + Self { + state: IgnoreDebug(Lua::new()), + plugin_paths, + plugin_functions: None, + } + } +} + +/// Utility type to enable having a field of a struct not implement Debug and +/// instead show a placeholder. +#[derive(Clone)] +pub struct IgnoreDebug(pub T); + +impl fmt::Debug for IgnoreDebug { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!(formatter, "") + } +} + +impl Deref for IgnoreDebug { + type Target = T; + + fn deref(&self) -> &T { + &self.0 + } +} + pub struct ImfsSnapshotContext; diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 1c36dc6f..7f4cab39 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -18,7 +18,7 @@ pub struct SnapshotDir; impl SnapshotMiddleware for SnapshotDir { fn from_imfs( - _context: &mut InstanceSnapshotContext, + context: &mut InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { @@ -31,7 +31,7 @@ impl SnapshotMiddleware for SnapshotDir { let mut snapshot_children = Vec::new(); for child in children.into_iter() { - if let Some(child_snapshot) = snapshot_from_imfs(imfs, &child)? { + if let Some(child_snapshot) = snapshot_from_imfs(context, imfs, &child)? { snapshot_children.push(child_snapshot); } } diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs index 3f1805de..c2a72b59 100644 --- a/src/snapshot_middleware/error.rs +++ b/src/snapshot_middleware/error.rs @@ -16,6 +16,13 @@ impl SnapshotError { } } + pub(crate) fn wrap(inner: impl Into, path: impl Into) -> Self { + SnapshotError { + detail: inner.into(), + path: Some(path.into()), + } + } + pub(crate) fn file_did_not_exist(path: impl Into) -> SnapshotError { SnapshotError { detail: SnapshotErrorDetail::FileDidNotExist, @@ -70,27 +77,45 @@ impl From for SnapshotError { fn from(error: FsError) -> Self { let (inner, path) = error.into_raw(); - let detail = SnapshotErrorDetail::IoError { inner }; + Self::new(inner.into(), Some(path)) + } +} - Self::new(detail, Some(path)) +impl From for SnapshotError { + fn from(error: rlua::Error) -> Self { + Self::new(error.into(), Option::::None) } } #[derive(Debug)] pub enum SnapshotErrorDetail { IoError { inner: io::Error }, + Lua { inner: rlua::Error }, FileDidNotExist, FileNameBadUnicode, FileContentsBadUnicode { inner: std::str::Utf8Error }, MalformedProject { inner: serde_json::Error }, } +impl From for SnapshotErrorDetail { + fn from(inner: io::Error) -> Self { + SnapshotErrorDetail::IoError { inner } + } +} + +impl From for SnapshotErrorDetail { + fn from(inner: rlua::Error) -> Self { + SnapshotErrorDetail::Lua { inner } + } +} + impl SnapshotErrorDetail { fn source(&self) -> Option<&(dyn Error + 'static)> { use self::SnapshotErrorDetail::*; match self { IoError { inner } => Some(inner), + Lua { inner } => Some(inner), FileContentsBadUnicode { inner } => Some(inner), MalformedProject { inner } => Some(inner), _ => None, @@ -104,6 +129,7 @@ impl fmt::Display for SnapshotErrorDetail { match self { IoError { inner } => write!(formatter, "I/O error: {}", inner), + Lua { inner } => write!(formatter, "{}", inner), FileDidNotExist => write!(formatter, "file did not exist"), FileNameBadUnicode => write!(formatter, "file name had malformed Unicode"), FileContentsBadUnicode { inner } => { diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 26968482..4809b87f 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -16,14 +16,15 @@ mod rbxlx; mod rbxm; mod rbxmx; mod txt; +mod user_plugins; mod util; +pub use self::context::*; pub use self::error::*; use rbx_dom_weak::{RbxId, RbxTree}; use self::{ - context::InstanceSnapshotContext, csv::SnapshotCsv, dir::SnapshotDir, json_model::SnapshotJsonModel, @@ -34,6 +35,7 @@ use self::{ rbxm::SnapshotRbxm, rbxmx::SnapshotRbxmx, txt::SnapshotTxt, + user_plugins::SnapshotUserPlugins, }; use crate::imfs::{Imfs, ImfsEntry, ImfsFetcher}; @@ -41,15 +43,14 @@ macro_rules! middlewares { ( $($middleware: ident,)* ) => { /// Generates a snapshot of instances from the given ImfsEntry. pub fn snapshot_from_imfs( + context: &mut InstanceSnapshotContext, imfs: &mut Imfs, entry: &ImfsEntry, ) -> SnapshotInstanceResult<'static> { - let mut context = InstanceSnapshotContext::default(); - $( log::trace!("trying middleware {} on {}", stringify!($middleware), entry.path().display()); - if let Some(snapshot) = $middleware::from_imfs(&mut context, imfs, entry)? { + if let Some(snapshot) = $middleware::from_imfs(context, imfs, entry)? { log::trace!("middleware {} success on {}", stringify!($middleware), entry.path().display()); return Ok(Some(snapshot)); } @@ -75,6 +76,7 @@ macro_rules! middlewares { middlewares! { SnapshotProject, + SnapshotUserPlugins, SnapshotJsonModel, SnapshotRbxlx, SnapshotRbxmx, diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index d1e0d9f4..c275d047 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -48,7 +48,8 @@ impl SnapshotMiddleware for SnapshotProject { // Snapshotting a project should always return an instance, so this // unwrap is safe. - let mut snapshot = snapshot_project_node(&project.name, &project.tree, imfs)?.unwrap(); + let mut snapshot = + snapshot_project_node(context, &project.name, &project.tree, imfs)?.unwrap(); // Setting the instigating source to the project file path is a little // coarse. @@ -76,6 +77,7 @@ impl SnapshotMiddleware for SnapshotProject { } fn snapshot_project_node( + context: &mut InstanceSnapshotContext, instance_name: &str, node: &ProjectNode, imfs: &mut Imfs, @@ -92,7 +94,7 @@ fn snapshot_project_node( if let Some(path) = &node.path { let entry = imfs.get(path)?; - if let Some(snapshot) = snapshot_from_imfs(imfs, &entry)? { + if let Some(snapshot) = snapshot_from_imfs(context, imfs, &entry)? { // If a class name was already specified, then it'll override the // class name of this snapshot ONLY if it's a Folder. // @@ -142,7 +144,7 @@ fn snapshot_project_node( .expect("$className or $path must be specified"); for (child_name, child_project_node) in &node.children { - if let Some(child) = snapshot_project_node(child_name, child_project_node, imfs)? { + if let Some(child) = snapshot_project_node(context, child_name, child_project_node, imfs)? { children.push(child); } } diff --git a/src/snapshot_middleware/user_plugins.rs b/src/snapshot_middleware/user_plugins.rs new file mode 100644 index 00000000..c98dda3b --- /dev/null +++ b/src/snapshot_middleware/user_plugins.rs @@ -0,0 +1,114 @@ +use std::{fs, path::Path}; + +use rlua::{Lua, RegistryKey}; + +use crate::imfs::{Imfs, ImfsEntry, ImfsFetcher}; + +use super::{ + context::InstanceSnapshotContext, + error::SnapshotError, + middleware::{SnapshotInstanceResult, SnapshotMiddleware}, +}; + +/// Handles snapshotting of any file that a user plugin wants to handle. +/// +/// User plugins are specified in the project file, but there are never user +/// plugins specified unless a Cargo feature is enabled, `user-plugins`. +/// Additionally, extra data needs to be set up inside the snapshot context +/// which is not currently wired up. +pub struct SnapshotUserPlugins; + +impl SnapshotMiddleware for SnapshotUserPlugins { + fn from_imfs( + context: &mut InstanceSnapshotContext, + _imfs: &mut Imfs, + _entry: &ImfsEntry, + ) -> SnapshotInstanceResult<'static> { + // User plugins are only enabled if present on the snapshot context. + let plugin_context = match &mut context.plugin_context { + Some(ctx) => ctx, + None => return Ok(None), + }; + + // If the plugins listed for use haven't been loaded yet, read them into + // memory, run them, and keep the result they return as a registry key + // into our Lua state. + let keys = match &plugin_context.plugin_functions { + Some(keys) => keys, + None => { + plugin_context.plugin_functions = Some(initialize_plugins( + &plugin_context.state, + &plugin_context.plugin_paths, + )?); + plugin_context.plugin_functions.as_ref().unwrap() + } + }; + + plugin_context.state.context(|lua_context| { + lua_context.scope(|_scope| { + for _key in keys { + // TODO: Invoke plugin here and get result out. + + // The current plan for plugins here is to make them work + // like Redux/Rodux middleware. A plugin will be a function + // that accepts the next middleware in the chain as a + // function and the snapshot subject (the IMFS entry). + // + // Plugins can (but don't have to) invoke the next snapshot + // function and may or may not mutate the result. The hope + // is that this model enables the most flexibility possible + // for plugins to modify existing Rojo output, as well as + // generate new outputs. + // + // Open questions: + // * How will middleware be ordered? Does putting user + // middleware always at the beginning or always at the end + // of the chain reduce the scope of what that middleware + // can do? + // + // * Will plugins hurt Rojo's ability to parallelize + // snapshotting in the future? + // + // * Do the mutable handles to the Imfs and the snapshot + // context prevent plugins from invoking other plugins + // indirectly? + // + // * Will there be problems using a single Lua state because + // of re-entrancy? + // + // * Can the Lua <-> Rojo bindings used for middleware be + // reused for or from another project like Remodel? + } + }) + }); + + Ok(None) + } +} + +fn initialize_plugins>( + lua_state: &Lua, + plugin_paths: &[P], +) -> Result, SnapshotError> { + plugin_paths + .iter() + .map(|path| { + let path = path.as_ref(); + + let content = fs::read_to_string(path).map_err(|err| SnapshotError::wrap(err, path))?; + + lua_state.context(|lua_context| { + // Plugins are currently expected to return a function that will + // be run when a snapshot needs to be generated. + let result = lua_context + .load(&content) + .set_name(&path.display().to_string())? + .call::<_, rlua::Function>(())?; + + let key = lua_context.create_registry_value(result)?; + + Ok(key) + }) + }) + .collect::, _>>() +} diff --git a/test-projects/plugins/default.project.json b/test-projects/plugins/default.project.json new file mode 100644 index 00000000..02387e7e --- /dev/null +++ b/test-projects/plugins/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "plugins", + "tree": { + "$path": "src" + }, + "plugins": [ + "test-plugin.lua" + ] +} \ No newline at end of file diff --git a/test-projects/plugins/src/hello.moon b/test-projects/plugins/src/hello.moon new file mode 100644 index 00000000..ddb781cf --- /dev/null +++ b/test-projects/plugins/src/hello.moon @@ -0,0 +1 @@ +print 'Hello, world!' \ No newline at end of file diff --git a/test-projects/plugins/test-plugin.lua b/test-projects/plugins/test-plugin.lua new file mode 100644 index 00000000..147463cb --- /dev/null +++ b/test-projects/plugins/test-plugin.lua @@ -0,0 +1,20 @@ +print("test-plugin initializing...") + +return function(nextDispatch, entry) + if entry:isDirectory() then + return nextDispatch(entry) + end + + local name = entry:fileName() + local instanceName = name:match("(.-)%.moon$") + + if instanceName == nil then + return nextDispatch(entry) + end + + return rojo.instance({ + Name = instanceName, + ClassName = "ModuleScript", + Source = compileMoonScript(entry:contents()), + }) +end \ No newline at end of file diff --git a/tests/read_projects.rs b/tests/read_projects.rs index 55f0e1da..25844b9b 100644 --- a/tests/read_projects.rs +++ b/tests/read_projects.rs @@ -87,6 +87,7 @@ fn single_partition_game() { tree: root_node, serve_port: None, serve_place_ids: None, + plugins: Vec::new(), file_location: project_location.join("default.project.json"), } }; From 83665018d419873e28d72595921ad8669cb3b72e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 11 Oct 2019 18:25:12 -0700 Subject: [PATCH 0820/1504] Compute snapshot context from project in build --- src/commands/build.rs | 36 ++++++++++++++++++++++++------ src/snapshot_middleware/context.rs | 6 +++-- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/src/commands/build.rs b/src/commands/build.rs index de10ef34..903c6e10 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -10,8 +10,9 @@ use rbx_dom_weak::RbxInstanceProperties; use crate::{ imfs::{FsError, Imfs, RealFetcher, WatchMode}, + project::{Project, ProjectLoadError}, snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, - snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext}, + snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext, SnapshotPluginContext}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -49,12 +50,15 @@ pub enum BuildError { #[fail(display = "IO error: {}", _0)] IoError(#[fail(cause)] io::Error), - #[fail(display = "XML model file error")] - XmlModelEncodeError(rbx_xml::EncodeError), + #[fail(display = "XML model error: {}", _0)] + XmlModelEncodeError(#[fail(cause)] rbx_xml::EncodeError), - #[fail(display = "Binary model file error")] + #[fail(display = "Binary model error: {:?}", _0)] BinaryModelEncodeError(rbx_binary::EncodeError), + #[fail(display = "{}", _0)] + ProjectLoadError(#[fail(cause)] ProjectLoadError), + #[fail(display = "{}", _0)] FsError(#[fail(cause)] FsError), } @@ -63,6 +67,7 @@ impl_from!(BuildError { io::Error => IoError, rbx_xml::EncodeError => XmlModelEncodeError, rbx_binary::EncodeError => BinaryModelEncodeError, + ProjectLoadError => ProjectLoadError, FsError => FsError, }); @@ -76,7 +81,14 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { .or_else(|| detect_output_kind(options)) .ok_or(BuildError::UnknownOutputKind)?; - log::info!("Hoping to generate file of type {:?}", output_kind); + log::debug!("Hoping to generate file of type {:?}", output_kind); + + let maybe_project = match Project::load_fuzzy(&options.fuzzy_project_path) { + Ok(project) => Some(project), + Err(ProjectLoadError::NotFound) => None, + Err(other) => return Err(other.into()), + }; + log::trace!("Using project file {:#?}", maybe_project); let mut tree = RojoTree::new(InstancePropertiesWithMeta { properties: RbxInstanceProperties { @@ -96,9 +108,19 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { .get(&options.fuzzy_project_path) .expect("could not get project path"); - // TODO: Compute snapshot context from project. + let mut snapshot_context = InstanceSnapshotContext::default(); + + if let Some(project) = maybe_project { + // If the project file defines no plugins, then there's no need to + // initialize the snapshot plugin context. + if !project.plugins.is_empty() { + snapshot_context.plugin_context = + Some(SnapshotPluginContext::new(project.plugins.clone())); + } + } + log::trace!("Generating snapshot of instances from IMFS"); - let snapshot = snapshot_from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + let snapshot = snapshot_from_imfs(&mut snapshot_context, &mut imfs, &entry) .expect("snapshot failed") .expect("snapshot did not return an instance"); diff --git a/src/snapshot_middleware/context.rs b/src/snapshot_middleware/context.rs index 0a7179a8..f479018f 100644 --- a/src/snapshot_middleware/context.rs +++ b/src/snapshot_middleware/context.rs @@ -4,8 +4,10 @@ use rlua::{Lua, RegistryKey}; #[derive(Debug)] pub struct InstanceSnapshotContext { - /// Empty struct that will be used later to fill out required Lua state for - /// user plugins. + /// Holds all the state needed to run user plugins as part of the snapshot + /// process. + /// + /// If this is None, then plugins should not be evaluated at all. pub plugin_context: Option, } From 24c697bea74d67ac188b6a9d1d04d6f2dc3cc3f2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 11 Oct 2019 18:35:10 -0700 Subject: [PATCH 0821/1504] Port commands to use common setup code Initialization logic needed for serve, build, and upload is now much more clear than it was when these functions were written. This commit refactors all of them to use a new common_setup module for all of their initialization that's the same. --- src/commands/build.rs | 52 +++------------------------------ src/commands/serve.rs | 27 ++++------------- src/commands/upload.rs | 36 ++++------------------- src/common_setup.rs | 66 ++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 1 + src/serve_session.rs | 63 ++++++++++------------------------------ 6 files changed, 98 insertions(+), 147 deletions(-) create mode 100644 src/common_setup.rs diff --git a/src/commands/build.rs b/src/commands/build.rs index 903c6e10..4b1b8591 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -1,18 +1,15 @@ use std::{ - collections::HashMap, fs::File, io::{self, BufWriter, Write}, path::PathBuf, }; use failure::Fail; -use rbx_dom_weak::RbxInstanceProperties; use crate::{ + common_setup, imfs::{FsError, Imfs, RealFetcher, WatchMode}, - project::{Project, ProjectLoadError}, - snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, - snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext, SnapshotPluginContext}, + project::ProjectLoadError, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -83,52 +80,11 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { log::debug!("Hoping to generate file of type {:?}", output_kind); - let maybe_project = match Project::load_fuzzy(&options.fuzzy_project_path) { - Ok(project) => Some(project), - Err(ProjectLoadError::NotFound) => None, - Err(other) => return Err(other.into()), - }; - log::trace!("Using project file {:#?}", maybe_project); - - let mut tree = RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), - }, - metadata: Default::default(), - }); - let root_id = tree.get_root_id(); - log::trace!("Constructing in-memory filesystem"); let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Disabled)); - log::trace!("Reading project root"); - let entry = imfs - .get(&options.fuzzy_project_path) - .expect("could not get project path"); - - let mut snapshot_context = InstanceSnapshotContext::default(); - - if let Some(project) = maybe_project { - // If the project file defines no plugins, then there's no need to - // initialize the snapshot plugin context. - if !project.plugins.is_empty() { - snapshot_context.plugin_context = - Some(SnapshotPluginContext::new(project.plugins.clone())); - } - } - - log::trace!("Generating snapshot of instances from IMFS"); - let snapshot = snapshot_from_imfs(&mut snapshot_context, &mut imfs, &entry) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); - - log::trace!("Computing patch set"); - let patch_set = compute_patch_set(&snapshot, &tree, root_id); - - log::trace!("Applying patch set"); - apply_patch_set(&mut tree, patch_set); + let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut imfs); + let root_id = tree.get_root_id(); log::trace!("Opening output file for write"); let mut file = BufWriter::new(File::create(&options.output_file)?); diff --git a/src/commands/serve.rs b/src/commands/serve.rs index 22c4a485..4aaef7df 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -9,7 +9,7 @@ use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; use crate::{ imfs::{Imfs, RealFetcher, WatchMode}, - project::{Project, ProjectLoadError}, + project::ProjectLoadError, serve_session::ServeSession, web::LiveServer, }; @@ -33,33 +33,18 @@ impl_from!(ServeError { }); pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { - let maybe_project = match Project::load_fuzzy(&options.fuzzy_project_path) { - Ok(project) => Some(project), - Err(ProjectLoadError::NotFound) => None, - Err(other) => return Err(other.into()), - }; + let imfs = Imfs::new(RealFetcher::new(WatchMode::Enabled)); + + let session = Arc::new(ServeSession::new(imfs, &options.fuzzy_project_path)); let port = options .port - .or_else(|| { - maybe_project - .as_ref() - .and_then(|project| project.serve_port) - }) + .or_else(|| session.project_port()) .unwrap_or(DEFAULT_PORT); - let _ = show_start_message(port); - - let imfs = Imfs::new(RealFetcher::new(WatchMode::Enabled)); - - let session = Arc::new(ServeSession::new( - imfs, - &options.fuzzy_project_path, - maybe_project, - )); - let server = LiveServer::new(session); + let _ = show_start_message(port); server.start(port); Ok(()) diff --git a/src/commands/upload.rs b/src/commands/upload.rs index ded0446a..08bb7fd9 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -1,14 +1,12 @@ -use std::{collections::HashMap, path::PathBuf}; +use std::path::PathBuf; use failure::Fail; -use rbx_dom_weak::RbxInstanceProperties; use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}; use crate::{ auth_cookie::get_auth_cookie, + common_setup, imfs::{Imfs, RealFetcher, WatchMode}, - snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, - snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext}, }; #[derive(Debug, Fail)] @@ -45,40 +43,15 @@ pub fn upload(options: UploadOptions) -> Result<(), UploadError> { .or_else(get_auth_cookie) .ok_or(UploadError::NeedAuthCookie)?; - let mut tree = RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), - }, - metadata: Default::default(), - }); - let root_id = tree.get_root_id(); - log::trace!("Constructing in-memory filesystem"); let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Disabled)); - log::trace!("Reading project root"); - let entry = imfs - .get(&options.fuzzy_project_path) - .expect("could not get project path"); - - // TODO: Compute snapshot context from project. - log::trace!("Generating snapshot of instances from IMFS"); - let snapshot = snapshot_from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); - - log::trace!("Computing patch set"); - let patch_set = compute_patch_set(&snapshot, &tree, root_id); - - log::trace!("Applying patch set"); - apply_patch_set(&mut tree, patch_set); - + let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut imfs); let root_id = tree.get_root_id(); let mut buffer = Vec::new(); + log::trace!("Encoding XML model"); let config = rbx_xml::EncodeOptions::new() .property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown); rbx_xml::to_writer(&mut buffer, tree.inner(), &[root_id], config)?; @@ -88,6 +61,7 @@ pub fn upload(options: UploadOptions) -> Result<(), UploadError> { options.asset_id ); + log::trace!("POSTing to {}", url); let client = reqwest::Client::new(); let mut response = client .post(&url) diff --git a/src/common_setup.rs b/src/common_setup.rs new file mode 100644 index 00000000..ee94ed65 --- /dev/null +++ b/src/common_setup.rs @@ -0,0 +1,66 @@ +//! Initialization routines that are used by more than one Rojo command or +//! utility. + +use std::path::Path; + +use rbx_dom_weak::RbxInstanceProperties; + +use crate::{ + imfs::{Imfs, ImfsFetcher}, + project::{Project, ProjectLoadError}, + snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, + snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext, SnapshotPluginContext}, +}; + +pub fn start( + fuzzy_project_path: &Path, + imfs: &mut Imfs, +) -> (Option, RojoTree) { + log::trace!("Loading project file from {}", fuzzy_project_path.display()); + let maybe_project = match Project::load_fuzzy(fuzzy_project_path) { + Ok(project) => Some(project), + Err(ProjectLoadError::NotFound) => None, + Err(other) => panic!("{}", other), // TODO: return error upward + }; + + log::trace!("Constructing initial tree"); + let mut tree = RojoTree::new(InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "ROOT".to_owned(), + class_name: "Folder".to_owned(), + properties: Default::default(), + }, + metadata: Default::default(), + }); + + let root_id = tree.get_root_id(); + + log::trace!("Constructing snapshot context"); + let mut snapshot_context = InstanceSnapshotContext::default(); + if let Some(project) = &maybe_project { + // If the project file defines no plugins, then there's no need to + // initialize the snapshot plugin context. + if !project.plugins.is_empty() { + snapshot_context.plugin_context = + Some(SnapshotPluginContext::new(project.plugins.clone())); + } + } + + log::trace!("Reading project root"); + let entry = imfs + .get(fuzzy_project_path) + .expect("could not get project path"); + + log::trace!("Generating snapshot of instances from IMFS"); + let snapshot = snapshot_from_imfs(&mut snapshot_context, imfs, &entry) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + log::trace!("Computing patch set"); + let patch_set = compute_patch_set(&snapshot, &tree, root_id); + + log::trace!("Applying patch set"); + apply_patch_set(&mut tree, patch_set); + + (maybe_project, tree) +} diff --git a/src/lib.rs b/src/lib.rs index 0ae30678..6384b989 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,6 +17,7 @@ mod tree_view; mod auth_cookie; mod change_processor; +mod common_setup; mod imfs; mod message_queue; mod multimap; diff --git a/src/serve_session.rs b/src/serve_session.rs index ebac8567..76486407 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -5,18 +5,14 @@ use std::{ time::Instant, }; -use rbx_dom_weak::RbxInstanceProperties; - use crate::{ change_processor::ChangeProcessor, + common_setup, imfs::{Imfs, ImfsFetcher}, message_queue::MessageQueue, project::Project, session_id::SessionId, - snapshot::{ - apply_patch_set, compute_patch_set, AppliedPatchSet, InstancePropertiesWithMeta, RojoTree, - }, - snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext}, + snapshot::{AppliedPatchSet, RojoTree}, }; /// Contains all of the state for a Rojo serve session. @@ -82,47 +78,14 @@ impl ServeSession { /// The project file is expected to be loaded out-of-band since it's /// currently loaded from the filesystem directly instead of through the /// in-memory filesystem layer. - pub fn new>( - mut imfs: Imfs, - start_path: P, - root_project: Option, - ) -> Self { + pub fn new>(mut imfs: Imfs, start_path: P) -> Self { let start_path = start_path.as_ref(); - log::trace!( - "Starting new ServeSession at path {} with project {:#?}", - start_path.display(), - root_project - ); + log::trace!("Starting new ServeSession at path {}", start_path.display(),); let start_time = Instant::now(); - log::trace!("Constructing initial tree"); - let mut tree = RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "Folder".to_owned(), - properties: Default::default(), - }, - metadata: Default::default(), - }); - let root_id = tree.get_root_id(); - - log::trace!("Loading start path: {}", start_path.display()); - let entry = imfs.get(start_path).expect("could not get project path"); - - // TODO: Compute snapshot context from project. - log::trace!("Snapshotting start path"); - let snapshot = - snapshot_from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); - - log::trace!("Computing initial patch set"); - let patch_set = compute_patch_set(&snapshot, &tree, root_id); - - log::trace!("Applying initial patch set"); - apply_patch_set(&mut tree, patch_set); + let (root_project, tree) = common_setup::start(start_path, &mut imfs); let session_id = SessionId::new(); let message_queue = MessageQueue::new(); @@ -177,6 +140,12 @@ impl ServeSession { .map(|project| project.name.as_str()) } + pub fn project_port(&self) -> Option { + self.root_project + .as_ref() + .and_then(|project| project.serve_port) + } + pub fn start_time(&self) -> Instant { self.start_time } @@ -214,7 +183,7 @@ mod serve_session { imfs.debug_load_snapshot("/foo", ImfsSnapshot::empty_dir()); - let session = ServeSession::new(imfs, "/foo", None); + let session = ServeSession::new(imfs, "/foo"); let mut rm = RedactionMap::new(); assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); @@ -241,7 +210,7 @@ mod serve_session { }), ); - let session = ServeSession::new(imfs, "/foo", None); + let session = ServeSession::new(imfs, "/foo"); let mut rm = RedactionMap::new(); assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); @@ -259,7 +228,7 @@ mod serve_session { }), ); - let session = ServeSession::new(imfs, "/root", None); + let session = ServeSession::new(imfs, "/root"); let mut rm = RedactionMap::new(); assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); @@ -278,7 +247,7 @@ mod serve_session { ); let imfs = Imfs::new(fetcher); - let session = ServeSession::new(imfs, "/root", None); + let session = ServeSession::new(imfs, "/root"); let mut redactions = RedactionMap::new(); assert_yaml_snapshot!( @@ -317,7 +286,7 @@ mod serve_session { state.load_snapshot("/foo.txt", ImfsSnapshot::file("Hello!")); let imfs = Imfs::new(fetcher); - let session = ServeSession::new(imfs, "/foo.txt", None); + let session = ServeSession::new(imfs, "/foo.txt"); let mut redactions = RedactionMap::new(); assert_yaml_snapshot!( From 1031600c6347e70bce9791e671909ae33b5b2c06 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 12 Oct 2019 13:58:00 -0700 Subject: [PATCH 0822/1504] Batch rename: imfs -> vfs --- src/change_processor.rs | 36 ++-- src/commands/build.rs | 6 +- src/commands/serve.rs | 6 +- src/commands/upload.rs | 6 +- src/common_setup.rs | 14 +- src/imfs/snapshot.rs | 42 ---- src/lib.rs | 2 +- src/serve_session.rs | 84 ++++---- src/snapshot_middleware/context.rs | 2 +- src/snapshot_middleware/csv.rs | 42 ++-- src/snapshot_middleware/dir.rs | 40 ++-- src/snapshot_middleware/error.rs | 2 +- src/snapshot_middleware/json_model.rs | 33 ++- src/snapshot_middleware/lua.rs | 120 +++++------ src/snapshot_middleware/middleware.rs | 10 +- src/snapshot_middleware/mod.rs | 12 +- src/snapshot_middleware/project.rs | 146 ++++++------- src/snapshot_middleware/rbxlx.rs | 10 +- src/snapshot_middleware/rbxm.rs | 24 +-- src/snapshot_middleware/rbxmx.rs | 24 +-- ...m_imfs.snap => test__client_from_vfs.snap} | 0 ...from_imfs.snap => test__csv_from_vfs.snap} | 0 ...imfs.snap => test__instance_from_vfs.snap} | 0 ...om_imfs.snap => test__model_from_vfs.snap} | 0 ...m_imfs.snap => test__module_from_vfs.snap} | 0 ...m_imfs.snap => test__server_from_vfs.snap} | 0 src/snapshot_middleware/txt.rs | 32 +-- src/snapshot_middleware/user_plugins.rs | 12 +- src/{imfs => vfs}/error.rs | 0 src/{imfs => vfs}/event.rs | 2 +- src/{imfs => vfs}/fetcher.rs | 8 +- src/{imfs => vfs}/mod.rs | 4 +- src/{imfs => vfs}/noop_fetcher.rs | 10 +- src/{imfs => vfs}/real_fetcher.rs | 24 +-- src/vfs/snapshot.rs | 42 ++++ src/{imfs => vfs}/test_fetcher.rs | 32 +-- src/{imfs/imfs.rs => vfs/vfs.rs} | 203 +++++++++--------- src/web/api.rs | 6 +- src/web/mod.rs | 8 +- src/web/ui.rs | 40 ++-- 40 files changed, 539 insertions(+), 545 deletions(-) delete mode 100644 src/imfs/snapshot.rs rename src/snapshot_middleware/snapshots/{test__client_from_imfs.snap => test__client_from_vfs.snap} (100%) rename src/snapshot_middleware/snapshots/{test__csv_from_imfs.snap => test__csv_from_vfs.snap} (100%) rename src/snapshot_middleware/snapshots/{test__instance_from_imfs.snap => test__instance_from_vfs.snap} (100%) rename src/snapshot_middleware/snapshots/{test__model_from_imfs.snap => test__model_from_vfs.snap} (100%) rename src/snapshot_middleware/snapshots/{test__module_from_imfs.snap => test__module_from_vfs.snap} (100%) rename src/snapshot_middleware/snapshots/{test__server_from_imfs.snap => test__server_from_vfs.snap} (100%) rename src/{imfs => vfs}/error.rs (100%) rename src/{imfs => vfs}/event.rs (84%) rename src/{imfs => vfs}/fetcher.rs (83%) rename src/{imfs => vfs}/mod.rs (91%) rename src/{imfs => vfs}/noop_fetcher.rs (85%) rename src/{imfs => vfs}/real_fetcher.rs (90%) create mode 100644 src/vfs/snapshot.rs rename src/{imfs => vfs}/test_fetcher.rs (85%) rename src/{imfs/imfs.rs => vfs/vfs.rs} (71%) diff --git a/src/change_processor.rs b/src/change_processor.rs index e0ad8496..55238ce8 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -1,4 +1,4 @@ -//! Defines the process by which changes are pulled from the Imfs, filtered, and +//! Defines the process by which changes are pulled from the Vfs, filtered, and //! used to mutate Rojo's tree during a live session. //! //! This object is owned by a ServeSession. @@ -9,10 +9,10 @@ use crossbeam_channel::{select, Receiver, Sender}; use jod_thread::JoinHandle; use crate::{ - imfs::{Imfs, ImfsEvent, ImfsFetcher}, message_queue::MessageQueue, snapshot::{apply_patch_set, compute_patch_set, AppliedPatchSet, InstigatingSource, RojoTree}, - snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext}, + snapshot_middleware::{snapshot_from_vfs, InstanceSnapshotContext}, + vfs::{Vfs, VfsEvent, VfsFetcher}, }; pub struct ChangeProcessor { @@ -21,10 +21,10 @@ pub struct ChangeProcessor { } impl ChangeProcessor { - pub fn start( + pub fn start( tree: Arc>, message_queue: Arc>, - imfs: Arc>>, + vfs: Arc>>, ) -> Self { let (shutdown_sender, shutdown_receiver) = crossbeam_channel::bounded(1); @@ -32,7 +32,7 @@ impl ChangeProcessor { .name("ChangeProcessor thread".to_owned()) .spawn(move || { log::trace!("ChangeProcessor thread started"); - Self::main_task(shutdown_receiver, tree, message_queue, imfs); + Self::main_task(shutdown_receiver, tree, message_queue, vfs); log::trace!("ChangeProcessor thread stopped"); }) .expect("Could not start ChangeProcessor thread"); @@ -43,15 +43,15 @@ impl ChangeProcessor { } } - fn main_task( + fn main_task( shutdown_receiver: Receiver<()>, tree: Arc>, message_queue: Arc>, - imfs: Arc>>, + vfs: Arc>>, ) { - let imfs_receiver = { - let imfs = imfs.lock().unwrap(); - imfs.change_receiver() + let vfs_receiver = { + let vfs = vfs.lock().unwrap(); + vfs.change_receiver() }; // Crossbeam's select macro generates code that Clippy doesn't like, and @@ -59,20 +59,20 @@ impl ChangeProcessor { #[allow(clippy::drop_copy)] loop { select! { - recv(imfs_receiver) -> event => { + recv(vfs_receiver) -> event => { let event = event.unwrap(); - log::trace!("Imfs event: {:?}", event); + log::trace!("Vfs event: {:?}", event); let applied_patches = { - let mut imfs = imfs.lock().unwrap(); - imfs.commit_change(&event).expect("Error applying IMFS change"); + let mut vfs = vfs.lock().unwrap(); + vfs.commit_change(&event).expect("Error applying VFS change"); let mut tree = tree.lock().unwrap(); let mut applied_patches = Vec::new(); match event { - ImfsEvent::Created(path) | ImfsEvent::Modified(path) | ImfsEvent::Removed(path) => { + VfsEvent::Created(path) | VfsEvent::Modified(path) | VfsEvent::Removed(path) => { let affected_ids = tree.get_ids_at_path(&path).to_vec(); if affected_ids.len() == 0 { @@ -95,14 +95,14 @@ impl ChangeProcessor { let snapshot = match instigating_source { InstigatingSource::Path(path) => { - let entry = imfs + let entry = vfs .get(path) .expect("could not get instigating path from filesystem"); // TODO: Use persisted snapshot // context struct instead of // recreating it every time. - let snapshot = snapshot_from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + let snapshot = snapshot_from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .expect("snapshot failed") .expect("snapshot did not return an instance"); diff --git a/src/commands/build.rs b/src/commands/build.rs index 4b1b8591..54054a96 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -8,8 +8,8 @@ use failure::Fail; use crate::{ common_setup, - imfs::{FsError, Imfs, RealFetcher, WatchMode}, project::ProjectLoadError, + vfs::{FsError, RealFetcher, Vfs, WatchMode}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -81,9 +81,9 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { log::debug!("Hoping to generate file of type {:?}", output_kind); log::trace!("Constructing in-memory filesystem"); - let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Disabled)); + let mut vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); - let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut imfs); + let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut vfs); let root_id = tree.get_root_id(); log::trace!("Opening output file for write"); diff --git a/src/commands/serve.rs b/src/commands/serve.rs index 4aaef7df..bc021e91 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -8,9 +8,9 @@ use failure::Fail; use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; use crate::{ - imfs::{Imfs, RealFetcher, WatchMode}, project::ProjectLoadError, serve_session::ServeSession, + vfs::{RealFetcher, Vfs, WatchMode}, web::LiveServer, }; @@ -33,9 +33,9 @@ impl_from!(ServeError { }); pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { - let imfs = Imfs::new(RealFetcher::new(WatchMode::Enabled)); + let vfs = Vfs::new(RealFetcher::new(WatchMode::Enabled)); - let session = Arc::new(ServeSession::new(imfs, &options.fuzzy_project_path)); + let session = Arc::new(ServeSession::new(vfs, &options.fuzzy_project_path)); let port = options .port diff --git a/src/commands/upload.rs b/src/commands/upload.rs index 08bb7fd9..df6d6a0e 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -6,7 +6,7 @@ use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}; use crate::{ auth_cookie::get_auth_cookie, common_setup, - imfs::{Imfs, RealFetcher, WatchMode}, + vfs::{RealFetcher, Vfs, WatchMode}, }; #[derive(Debug, Fail)] @@ -44,9 +44,9 @@ pub fn upload(options: UploadOptions) -> Result<(), UploadError> { .ok_or(UploadError::NeedAuthCookie)?; log::trace!("Constructing in-memory filesystem"); - let mut imfs = Imfs::new(RealFetcher::new(WatchMode::Disabled)); + let mut vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); - let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut imfs); + let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut vfs); let root_id = tree.get_root_id(); let mut buffer = Vec::new(); diff --git a/src/common_setup.rs b/src/common_setup.rs index ee94ed65..d21a07d9 100644 --- a/src/common_setup.rs +++ b/src/common_setup.rs @@ -6,15 +6,15 @@ use std::path::Path; use rbx_dom_weak::RbxInstanceProperties; use crate::{ - imfs::{Imfs, ImfsFetcher}, project::{Project, ProjectLoadError}, snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, - snapshot_middleware::{snapshot_from_imfs, InstanceSnapshotContext, SnapshotPluginContext}, + snapshot_middleware::{snapshot_from_vfs, InstanceSnapshotContext, SnapshotPluginContext}, + vfs::{Vfs, VfsFetcher}, }; -pub fn start( +pub fn start( fuzzy_project_path: &Path, - imfs: &mut Imfs, + vfs: &mut Vfs, ) -> (Option, RojoTree) { log::trace!("Loading project file from {}", fuzzy_project_path.display()); let maybe_project = match Project::load_fuzzy(fuzzy_project_path) { @@ -47,12 +47,12 @@ pub fn start( } log::trace!("Reading project root"); - let entry = imfs + let entry = vfs .get(fuzzy_project_path) .expect("could not get project path"); - log::trace!("Generating snapshot of instances from IMFS"); - let snapshot = snapshot_from_imfs(&mut snapshot_context, imfs, &entry) + log::trace!("Generating snapshot of instances from VFS"); + let snapshot = snapshot_from_vfs(&mut snapshot_context, vfs, &entry) .expect("snapshot failed") .expect("snapshot did not return an instance"); diff --git a/src/imfs/snapshot.rs b/src/imfs/snapshot.rs deleted file mode 100644 index cc2cfff2..00000000 --- a/src/imfs/snapshot.rs +++ /dev/null @@ -1,42 +0,0 @@ -// This file is non-critical and used for testing, so it's okay if it's unused. -#![allow(unused)] - -use std::collections::HashMap; - -#[derive(Debug, Clone)] -pub enum ImfsSnapshot { - File(FileSnapshot), - Directory(DirectorySnapshot), -} - -impl ImfsSnapshot { - /// Create a new file ImfsSnapshot with the given contents. - pub fn file(contents: impl Into>) -> ImfsSnapshot { - ImfsSnapshot::File(FileSnapshot { - contents: contents.into(), - }) - } - - /// Create a new directory ImfsSnapshot with the given children. - pub fn dir>(children: HashMap) -> ImfsSnapshot { - let children = children.into_iter().map(|(k, v)| (k.into(), v)).collect(); - - ImfsSnapshot::Directory(DirectorySnapshot { children }) - } - - pub fn empty_dir() -> ImfsSnapshot { - ImfsSnapshot::Directory(DirectorySnapshot { - children: Default::default(), - }) - } -} - -#[derive(Debug, Clone)] -pub struct FileSnapshot { - pub contents: Vec, -} - -#[derive(Debug, Clone)] -pub struct DirectorySnapshot { - pub children: HashMap, -} diff --git a/src/lib.rs b/src/lib.rs index 6384b989..12953c3a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,6 @@ mod tree_view; mod auth_cookie; mod change_processor; mod common_setup; -mod imfs; mod message_queue; mod multimap; mod path_map; @@ -27,6 +26,7 @@ mod serve_session; mod session_id; mod snapshot; mod snapshot_middleware; +mod vfs; mod web; pub use crate::session_id::SessionId; diff --git a/src/serve_session.rs b/src/serve_session.rs index 76486407..6a24bf65 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -8,11 +8,11 @@ use std::{ use crate::{ change_processor::ChangeProcessor, common_setup, - imfs::{Imfs, ImfsFetcher}, message_queue::MessageQueue, project::Project, session_id::SessionId, snapshot::{AppliedPatchSet, RojoTree}, + vfs::{Vfs, VfsFetcher}, }; /// Contains all of the state for a Rojo serve session. @@ -43,7 +43,7 @@ pub struct ServeSession { session_id: SessionId, /// The tree of Roblox instances associated with this session that will be - /// updated in real-time. This is derived from the session's IMFS and will + /// updated in real-time. This is derived from the session's VFS and will /// eventually be mutable to connected clients. tree: Arc>, @@ -52,7 +52,7 @@ pub struct ServeSession { /// /// The main use for accessing it from the session is for debugging issues /// with Rojo's live-sync protocol. - imfs: Arc>>, + vfs: Arc>>, /// A queue of changes that have been applied to `tree` that affect clients. /// @@ -68,37 +68,37 @@ pub struct ServeSession { _change_processor: ChangeProcessor, } -/// Methods that need thread-safety bounds on ImfsFetcher are limited to this +/// Methods that need thread-safety bounds on VfsFetcher are limited to this /// block to prevent needing to spread Send + Sync + 'static into everything /// that handles ServeSession. -impl ServeSession { +impl ServeSession { /// Start a new serve session from the given in-memory filesystem and start /// path. /// /// The project file is expected to be loaded out-of-band since it's /// currently loaded from the filesystem directly instead of through the /// in-memory filesystem layer. - pub fn new>(mut imfs: Imfs, start_path: P) -> Self { + pub fn new>(mut vfs: Vfs, start_path: P) -> Self { let start_path = start_path.as_ref(); log::trace!("Starting new ServeSession at path {}", start_path.display(),); let start_time = Instant::now(); - let (root_project, tree) = common_setup::start(start_path, &mut imfs); + let (root_project, tree) = common_setup::start(start_path, &mut vfs); let session_id = SessionId::new(); let message_queue = MessageQueue::new(); let tree = Arc::new(Mutex::new(tree)); let message_queue = Arc::new(message_queue); - let imfs = Arc::new(Mutex::new(imfs)); + let vfs = Arc::new(Mutex::new(vfs)); log::trace!("Starting ChangeProcessor"); let change_processor = ChangeProcessor::start( Arc::clone(&tree), Arc::clone(&message_queue), - Arc::clone(&imfs), + Arc::clone(&vfs), ); Self { @@ -107,13 +107,13 @@ impl ServeSession { root_project, tree, message_queue, - imfs, + vfs, _change_processor: change_processor, } } } -impl ServeSession { +impl ServeSession { pub fn tree_handle(&self) -> Arc> { Arc::clone(&self.tree) } @@ -122,8 +122,8 @@ impl ServeSession { self.tree.lock().unwrap() } - pub fn imfs(&self) -> MutexGuard<'_, Imfs> { - self.imfs.lock().unwrap() + pub fn vfs(&self) -> MutexGuard<'_, Vfs> { + self.vfs.lock().unwrap() } pub fn message_queue(&self) -> &MessageQueue { @@ -173,17 +173,17 @@ mod serve_session { use tokio::{runtime::Runtime, timer::Timeout}; use crate::{ - imfs::{ImfsDebug, ImfsEvent, ImfsSnapshot, NoopFetcher, TestFetcher}, tree_view::view_tree, + vfs::{NoopFetcher, TestFetcher, VfsDebug, VfsEvent, VfsSnapshot}, }; #[test] fn just_folder() { - let mut imfs = Imfs::new(NoopFetcher); + let mut vfs = Vfs::new(NoopFetcher); - imfs.debug_load_snapshot("/foo", ImfsSnapshot::empty_dir()); + vfs.debug_load_snapshot("/foo", VfsSnapshot::empty_dir()); - let session = ServeSession::new(imfs, "/foo"); + let session = ServeSession::new(vfs, "/foo"); let mut rm = RedactionMap::new(); assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); @@ -191,12 +191,12 @@ mod serve_session { #[test] fn project_with_folder() { - let mut imfs = Imfs::new(NoopFetcher); + let mut vfs = Vfs::new(NoopFetcher); - imfs.debug_load_snapshot( + vfs.debug_load_snapshot( "/foo", - ImfsSnapshot::dir(hashmap! { - "default.project.json" => ImfsSnapshot::file(r#" + VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" { "name": "HelloWorld", "tree": { @@ -204,13 +204,13 @@ mod serve_session { } } "#), - "src" => ImfsSnapshot::dir(hashmap! { - "hello.txt" => ImfsSnapshot::file("Hello, world!"), + "src" => VfsSnapshot::dir(hashmap! { + "hello.txt" => VfsSnapshot::file("Hello, world!"), }), }), ); - let session = ServeSession::new(imfs, "/foo"); + let session = ServeSession::new(vfs, "/foo"); let mut rm = RedactionMap::new(); assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); @@ -218,17 +218,17 @@ mod serve_session { #[test] fn script_with_meta() { - let mut imfs = Imfs::new(NoopFetcher); + let mut vfs = Vfs::new(NoopFetcher); - imfs.debug_load_snapshot( + vfs.debug_load_snapshot( "/root", - ImfsSnapshot::dir(hashmap! { - "test.lua" => ImfsSnapshot::file("This is a test."), - "test.meta.json" => ImfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#), + VfsSnapshot::dir(hashmap! { + "test.lua" => VfsSnapshot::file("This is a test."), + "test.meta.json" => VfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#), }), ); - let session = ServeSession::new(imfs, "/root"); + let session = ServeSession::new(vfs, "/root"); let mut rm = RedactionMap::new(); assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); @@ -240,14 +240,14 @@ mod serve_session { state.load_snapshot( "/root", - ImfsSnapshot::dir(hashmap! { - "test.lua" => ImfsSnapshot::file("This is a test."), - "test.meta.json" => ImfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#), + VfsSnapshot::dir(hashmap! { + "test.lua" => VfsSnapshot::file("This is a test."), + "test.meta.json" => VfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#), }), ); - let imfs = Imfs::new(fetcher); - let session = ServeSession::new(imfs, "/root"); + let vfs = Vfs::new(fetcher); + let session = ServeSession::new(vfs, "/root"); let mut redactions = RedactionMap::new(); assert_yaml_snapshot!( @@ -257,14 +257,14 @@ mod serve_session { state.load_snapshot( "/root/test.meta.json", - ImfsSnapshot::file(r#"{ "ignoreUnknownInstances": false }"#), + VfsSnapshot::file(r#"{ "ignoreUnknownInstances": false }"#), ); let receiver = Timeout::new( session.message_queue().subscribe_any(), Duration::from_millis(200), ); - state.raise_event(ImfsEvent::Modified(PathBuf::from("/root/test.meta.json"))); + state.raise_event(VfsEvent::Modified(PathBuf::from("/root/test.meta.json"))); let mut rt = Runtime::new().unwrap(); let changes = rt.block_on(receiver).unwrap(); @@ -283,10 +283,10 @@ mod serve_session { fn change_txt_file() { let (state, fetcher) = TestFetcher::new(); - state.load_snapshot("/foo.txt", ImfsSnapshot::file("Hello!")); + state.load_snapshot("/foo.txt", VfsSnapshot::file("Hello!")); - let imfs = Imfs::new(fetcher); - let session = ServeSession::new(imfs, "/foo.txt"); + let vfs = Vfs::new(fetcher); + let session = ServeSession::new(vfs, "/foo.txt"); let mut redactions = RedactionMap::new(); assert_yaml_snapshot!( @@ -294,11 +294,11 @@ mod serve_session { view_tree(&session.tree(), &mut redactions) ); - state.load_snapshot("/foo.txt", ImfsSnapshot::file("World!")); + state.load_snapshot("/foo.txt", VfsSnapshot::file("World!")); let receiver = session.message_queue().subscribe_any(); - state.raise_event(ImfsEvent::Modified(PathBuf::from("/foo.txt"))); + state.raise_event(VfsEvent::Modified(PathBuf::from("/foo.txt"))); let receiver = Timeout::new(receiver, Duration::from_millis(200)); diff --git a/src/snapshot_middleware/context.rs b/src/snapshot_middleware/context.rs index f479018f..ba376085 100644 --- a/src/snapshot_middleware/context.rs +++ b/src/snapshot_middleware/context.rs @@ -62,4 +62,4 @@ impl Deref for IgnoreDebug { } } -pub struct ImfsSnapshotContext; +pub struct VfsSnapshotContext; diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 0cf16cfc..ca2abbc4 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -5,8 +5,8 @@ use rbx_dom_weak::RbxValue; use serde::Serialize; use crate::{ - imfs::{FsResultExt, Imfs, ImfsEntry, ImfsFetcher}, snapshot::{InstanceMetadata, InstanceSnapshot}, + vfs::{FsResultExt, Vfs, VfsEntry, VfsFetcher}, }; use super::{ @@ -19,10 +19,10 @@ use super::{ pub struct SnapshotCsv; impl SnapshotMiddleware for SnapshotCsv { - fn from_imfs( + fn from_vfs( _context: &mut InstanceSnapshotContext, - imfs: &mut Imfs, - entry: &ImfsEntry, + vfs: &mut Vfs, + entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { return Ok(None); @@ -37,7 +37,7 @@ impl SnapshotMiddleware for SnapshotCsv { .path() .with_file_name(format!("{}.meta.json", instance_name)); - let table_contents = convert_localization_csv(entry.contents(imfs)?); + let table_contents = convert_localization_csv(entry.contents(vfs)?); let mut snapshot = InstanceSnapshot { snapshot_id: None, @@ -56,8 +56,8 @@ impl SnapshotMiddleware for SnapshotCsv { children: Vec::new(), }; - if let Some(meta_entry) = imfs.get(meta_path).with_not_found()? { - let meta_contents = meta_entry.contents(imfs)?; + if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { + let meta_contents = meta_entry.contents(vfs)?; let mut metadata = AdjacentMetadata::from_slice(meta_contents); metadata.apply_all(&mut snapshot); } @@ -146,23 +146,23 @@ fn convert_localization_csv(contents: &[u8]) -> String { mod test { use super::*; - use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; + use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot}; use insta::assert_yaml_snapshot; #[test] - fn csv_from_imfs() { - let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file( + fn csv_from_vfs() { + let mut vfs = Vfs::new(NoopFetcher); + let file = VfsSnapshot::file( r#" Key,Source,Context,Example,es Ack,Ack!,,An exclamation of despair,¡Ay!"#, ); - imfs.debug_load_snapshot("/foo.csv", file); + vfs.debug_load_snapshot("/foo.csv", file); - let entry = imfs.get("/foo.csv").unwrap(); + let entry = vfs.get("/foo.csv").unwrap(); let instance_snapshot = - SnapshotCsv::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotCsv::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -171,20 +171,20 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, #[test] fn csv_with_meta() { - let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file( + let mut vfs = Vfs::new(NoopFetcher); + let file = VfsSnapshot::file( r#" Key,Source,Context,Example,es Ack,Ack!,,An exclamation of despair,¡Ay!"#, ); - let meta = ImfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#); + let meta = VfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#); - imfs.debug_load_snapshot("/foo.csv", file); - imfs.debug_load_snapshot("/foo.meta.json", meta); + vfs.debug_load_snapshot("/foo.csv", file); + vfs.debug_load_snapshot("/foo.meta.json", meta); - let entry = imfs.get("/foo.csv").unwrap(); + let entry = vfs.get("/foo.csv").unwrap(); let instance_snapshot = - SnapshotCsv::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotCsv::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 7f4cab39..b3c1a126 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -3,35 +3,35 @@ use std::{borrow::Cow, collections::HashMap}; use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ - imfs::{DirectorySnapshot, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, snapshot::{InstanceMetadata, InstanceSnapshot}, + vfs::{DirectorySnapshot, Vfs, VfsEntry, VfsFetcher, VfsSnapshot}, }; use super::{ context::InstanceSnapshotContext, error::SnapshotError, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, - snapshot_from_imfs, snapshot_from_instance, + snapshot_from_instance, snapshot_from_vfs, }; pub struct SnapshotDir; impl SnapshotMiddleware for SnapshotDir { - fn from_imfs( + fn from_vfs( context: &mut InstanceSnapshotContext, - imfs: &mut Imfs, - entry: &ImfsEntry, + vfs: &mut Vfs, + entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_file() { return Ok(None); } - let children: Vec = entry.children(imfs)?; + let children: Vec = entry.children(vfs)?; let mut snapshot_children = Vec::new(); for child in children.into_iter() { - if let Some(child_snapshot) = snapshot_from_imfs(context, imfs, &child)? { + if let Some(child_snapshot) = snapshot_from_vfs(context, vfs, &child)? { snapshot_children.push(child_snapshot); } } @@ -73,7 +73,7 @@ impl SnapshotMiddleware for SnapshotDir { } } - let snapshot = ImfsSnapshot::Directory(DirectorySnapshot { children }); + let snapshot = VfsSnapshot::Directory(DirectorySnapshot { children }); Some((instance.name.clone(), snapshot)) } @@ -86,18 +86,18 @@ mod test { use insta::assert_yaml_snapshot; use maplit::hashmap; - use crate::imfs::{ImfsDebug, NoopFetcher}; + use crate::vfs::{NoopFetcher, VfsDebug}; #[test] fn empty_folder() { - let mut imfs = Imfs::new(NoopFetcher); - let dir = ImfsSnapshot::dir::(HashMap::new()); + let mut vfs = Vfs::new(NoopFetcher); + let dir = VfsSnapshot::dir::(HashMap::new()); - imfs.debug_load_snapshot("/foo", dir); + vfs.debug_load_snapshot("/foo", dir); - let entry = imfs.get("/foo").unwrap(); + let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotDir::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotDir::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -106,16 +106,16 @@ mod test { #[test] fn folder_in_folder() { - let mut imfs = Imfs::new(NoopFetcher); - let dir = ImfsSnapshot::dir(hashmap! { - "Child" => ImfsSnapshot::dir::(HashMap::new()), + let mut vfs = Vfs::new(NoopFetcher); + let dir = VfsSnapshot::dir(hashmap! { + "Child" => VfsSnapshot::dir::(HashMap::new()), }); - imfs.debug_load_snapshot("/foo", dir); + vfs.debug_load_snapshot("/foo", dir); - let entry = imfs.get("/foo").unwrap(); + let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotDir::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotDir::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs index c2a72b59..b81f5b5f 100644 --- a/src/snapshot_middleware/error.rs +++ b/src/snapshot_middleware/error.rs @@ -1,6 +1,6 @@ use std::{error::Error, fmt, io, path::PathBuf}; -use crate::imfs::FsError; +use crate::vfs::FsError; #[derive(Debug)] pub struct SnapshotError { diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index accec10f..bab2c0c7 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -5,8 +5,8 @@ use rbx_reflection::try_resolve_value; use serde::Deserialize; use crate::{ - imfs::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, + vfs::{Vfs, VfsEntry, VfsFetcher}, }; use super::{ @@ -18,10 +18,10 @@ use super::{ pub struct SnapshotJsonModel; impl SnapshotMiddleware for SnapshotJsonModel { - fn from_imfs( + fn from_vfs( _context: &mut InstanceSnapshotContext, - imfs: &mut Imfs, - entry: &ImfsEntry, + vfs: &mut Vfs, + entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { return Ok(None); @@ -33,7 +33,7 @@ impl SnapshotMiddleware for SnapshotJsonModel { }; let instance: JsonModel = - serde_json::from_slice(entry.contents(imfs)?).expect("TODO: Handle serde_json errors"); + serde_json::from_slice(entry.contents(vfs)?).expect("TODO: Handle serde_json errors"); if let Some(json_name) = &instance.name { if json_name != &instance_name { @@ -137,12 +137,12 @@ mod test { use insta::assert_yaml_snapshot; - use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; + use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot}; #[test] - fn model_from_imfs() { - let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file( + fn model_from_vfs() { + let mut vfs = Vfs::new(NoopFetcher); + let file = VfsSnapshot::file( r#" { "Name": "children", @@ -160,16 +160,13 @@ mod test { "#, ); - imfs.debug_load_snapshot("/foo.model.json", file); + vfs.debug_load_snapshot("/foo.model.json", file); - let entry = imfs.get("/foo.model.json").unwrap(); - let instance_snapshot = SnapshotJsonModel::from_imfs( - &mut InstanceSnapshotContext::default(), - &mut imfs, - &entry, - ) - .unwrap() - .unwrap(); + let entry = vfs.get("/foo.model.json").unwrap(); + let instance_snapshot = + SnapshotJsonModel::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + .unwrap() + .unwrap(); assert_yaml_snapshot!(instance_snapshot); } diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 13df304f..c058895e 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -4,8 +4,8 @@ use maplit::hashmap; use rbx_dom_weak::RbxValue; use crate::{ - imfs::{FsResultExt, Imfs, ImfsEntry, ImfsFetcher}, snapshot::{InstanceMetadata, InstanceSnapshot}, + vfs::{FsResultExt, Vfs, VfsEntry, VfsFetcher}, }; use super::{ @@ -19,10 +19,10 @@ use super::{ pub struct SnapshotLua; impl SnapshotMiddleware for SnapshotLua { - fn from_imfs( + fn from_vfs( context: &mut InstanceSnapshotContext, - imfs: &mut Imfs, - entry: &ImfsEntry, + vfs: &mut Vfs, + entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { let file_name = entry.path().file_name().unwrap().to_string_lossy(); @@ -34,15 +34,15 @@ impl SnapshotMiddleware for SnapshotLua { } if entry.is_file() { - snapshot_lua_file(imfs, entry) + snapshot_lua_file(vfs, entry) } else { - if let Some(snapshot) = snapshot_init(context, imfs, entry, "init.lua")? { + if let Some(snapshot) = snapshot_init(context, vfs, entry, "init.lua")? { // An `init.lua` file turns its parent into a ModuleScript Ok(Some(snapshot)) - } else if let Some(snapshot) = snapshot_init(context, imfs, entry, "init.server.lua")? { + } else if let Some(snapshot) = snapshot_init(context, vfs, entry, "init.server.lua")? { // An `init.server.lua` file turns its parent into a Script Ok(Some(snapshot)) - } else if let Some(snapshot) = snapshot_init(context, imfs, entry, "init.client.lua")? { + } else if let Some(snapshot) = snapshot_init(context, vfs, entry, "init.client.lua")? { // An `init.client.lua` file turns its parent into a LocalScript Ok(Some(snapshot)) } else { @@ -53,9 +53,9 @@ impl SnapshotMiddleware for SnapshotLua { } /// Core routine for turning Lua files into snapshots. -fn snapshot_lua_file( - imfs: &mut Imfs, - entry: &ImfsEntry, +fn snapshot_lua_file( + vfs: &mut Vfs, + entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { let file_name = entry.path().file_name().unwrap().to_string_lossy(); @@ -70,7 +70,7 @@ fn snapshot_lua_file( return Ok(None); }; - let contents = entry.contents(imfs)?; + let contents = entry.contents(vfs)?; let contents_str = str::from_utf8(contents) // TODO: Turn into error type .expect("File content was not valid UTF-8") @@ -101,8 +101,8 @@ fn snapshot_lua_file( children: Vec::new(), }; - if let Some(meta_entry) = imfs.get(meta_path).with_not_found()? { - let meta_contents = meta_entry.contents(imfs)?; + if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { + let meta_contents = meta_entry.contents(vfs)?; let mut metadata = AdjacentMetadata::from_slice(meta_contents); metadata.apply_all(&mut snapshot); } @@ -115,17 +115,17 @@ fn snapshot_lua_file( /// /// Scripts named `init.lua`, `init.server.lua`, or `init.client.lua` usurp /// their parents, which acts similarly to `__init__.py` from the Python world. -fn snapshot_init( +fn snapshot_init( context: &mut InstanceSnapshotContext, - imfs: &mut Imfs, - folder_entry: &ImfsEntry, + vfs: &mut Vfs, + folder_entry: &VfsEntry, init_name: &str, ) -> SnapshotInstanceResult<'static> { let init_path = folder_entry.path().join(init_name); - if let Some(init_entry) = imfs.get(init_path).with_not_found()? { - if let Some(dir_snapshot) = SnapshotDir::from_imfs(context, imfs, folder_entry)? { - if let Some(mut init_snapshot) = snapshot_lua_file(imfs, &init_entry)? { + if let Some(init_entry) = vfs.get(init_path).with_not_found()? { + if let Some(dir_snapshot) = SnapshotDir::from_vfs(context, vfs, folder_entry)? { + if let Some(mut init_snapshot) = snapshot_lua_file(vfs, &init_entry)? { init_snapshot.name = dir_snapshot.name; init_snapshot.children = dir_snapshot.children; // TODO: Metadata @@ -145,18 +145,18 @@ mod test { use insta::{assert_yaml_snapshot, with_settings}; - use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; + use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot}; #[test] - fn module_from_imfs() { - let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file("Hello there!"); + fn module_from_vfs() { + let mut vfs = Vfs::new(NoopFetcher); + let file = VfsSnapshot::file("Hello there!"); - imfs.debug_load_snapshot("/foo.lua", file); + vfs.debug_load_snapshot("/foo.lua", file); - let entry = imfs.get("/foo.lua").unwrap(); + let entry = vfs.get("/foo.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -164,15 +164,15 @@ mod test { } #[test] - fn server_from_imfs() { - let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file("Hello there!"); + fn server_from_vfs() { + let mut vfs = Vfs::new(NoopFetcher); + let file = VfsSnapshot::file("Hello there!"); - imfs.debug_load_snapshot("/foo.server.lua", file); + vfs.debug_load_snapshot("/foo.server.lua", file); - let entry = imfs.get("/foo.server.lua").unwrap(); + let entry = vfs.get("/foo.server.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -180,15 +180,15 @@ mod test { } #[test] - fn client_from_imfs() { - let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file("Hello there!"); + fn client_from_vfs() { + let mut vfs = Vfs::new(NoopFetcher); + let file = VfsSnapshot::file("Hello there!"); - imfs.debug_load_snapshot("/foo.client.lua", file); + vfs.debug_load_snapshot("/foo.client.lua", file); - let entry = imfs.get("/foo.client.lua").unwrap(); + let entry = vfs.get("/foo.client.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -197,9 +197,9 @@ mod test { #[test] fn module_with_meta() { - let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file("Hello there!"); - let meta = ImfsSnapshot::file( + let mut vfs = Vfs::new(NoopFetcher); + let file = VfsSnapshot::file("Hello there!"); + let meta = VfsSnapshot::file( r#" { "ignoreUnknownInstances": true @@ -207,12 +207,12 @@ mod test { "#, ); - imfs.debug_load_snapshot("/foo.lua", file); - imfs.debug_load_snapshot("/foo.meta.json", meta); + vfs.debug_load_snapshot("/foo.lua", file); + vfs.debug_load_snapshot("/foo.meta.json", meta); - let entry = imfs.get("/foo.lua").unwrap(); + let entry = vfs.get("/foo.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -221,9 +221,9 @@ mod test { #[test] fn script_with_meta() { - let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file("Hello there!"); - let meta = ImfsSnapshot::file( + let mut vfs = Vfs::new(NoopFetcher); + let file = VfsSnapshot::file("Hello there!"); + let meta = VfsSnapshot::file( r#" { "ignoreUnknownInstances": true @@ -231,12 +231,12 @@ mod test { "#, ); - imfs.debug_load_snapshot("/foo.server.lua", file); - imfs.debug_load_snapshot("/foo.meta.json", meta); + vfs.debug_load_snapshot("/foo.server.lua", file); + vfs.debug_load_snapshot("/foo.meta.json", meta); - let entry = imfs.get("/foo.server.lua").unwrap(); + let entry = vfs.get("/foo.server.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -245,9 +245,9 @@ mod test { #[test] fn script_disabled() { - let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file("Hello there!"); - let meta = ImfsSnapshot::file( + let mut vfs = Vfs::new(NoopFetcher); + let file = VfsSnapshot::file("Hello there!"); + let meta = VfsSnapshot::file( r#" { "properties": { @@ -257,12 +257,12 @@ mod test { "#, ); - imfs.debug_load_snapshot("/bar.server.lua", file); - imfs.debug_load_snapshot("/bar.meta.json", meta); + vfs.debug_load_snapshot("/bar.server.lua", file); + vfs.debug_load_snapshot("/bar.meta.json", meta); - let entry = imfs.get("/bar.server.lua").unwrap(); + let entry = vfs.get("/bar.server.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index 08c24df6..fe9a2ebb 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -3,20 +3,20 @@ use std::path::{Path, PathBuf}; use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ - imfs::{Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, snapshot::InstanceSnapshot, + vfs::{Vfs, VfsEntry, VfsFetcher, VfsSnapshot}, }; use super::{context::InstanceSnapshotContext, error::SnapshotError}; pub type SnapshotInstanceResult<'a> = Result>, SnapshotError>; -pub type SnapshotFileResult = Option<(String, ImfsSnapshot)>; +pub type SnapshotFileResult = Option<(String, VfsSnapshot)>; pub trait SnapshotMiddleware { - fn from_imfs( + fn from_vfs( context: &mut InstanceSnapshotContext, - imfs: &mut Imfs, - entry: &ImfsEntry, + vfs: &mut Vfs, + entry: &VfsEntry, ) -> SnapshotInstanceResult<'static>; fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 4809b87f..4e466d7b 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -37,20 +37,20 @@ use self::{ txt::SnapshotTxt, user_plugins::SnapshotUserPlugins, }; -use crate::imfs::{Imfs, ImfsEntry, ImfsFetcher}; +use crate::vfs::{Vfs, VfsEntry, VfsFetcher}; macro_rules! middlewares { ( $($middleware: ident,)* ) => { - /// Generates a snapshot of instances from the given ImfsEntry. - pub fn snapshot_from_imfs( + /// Generates a snapshot of instances from the given VfsEntry. + pub fn snapshot_from_vfs( context: &mut InstanceSnapshotContext, - imfs: &mut Imfs, - entry: &ImfsEntry, + vfs: &mut Vfs, + entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { $( log::trace!("trying middleware {} on {}", stringify!($middleware), entry.path().display()); - if let Some(snapshot) = $middleware::from_imfs(context, imfs, entry)? { + if let Some(snapshot) = $middleware::from_vfs(context, vfs, entry)? { log::trace!("middleware {} success on {}", stringify!($middleware), entry.path().display()); return Ok(Some(snapshot)); } diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index c275d047..211ca611 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -3,16 +3,16 @@ use std::{borrow::Cow, collections::HashMap}; use rbx_reflection::try_resolve_value; use crate::{ - imfs::{FsResultExt, Imfs, ImfsEntry, ImfsFetcher}, project::{Project, ProjectNode}, snapshot::{InstanceMetadata, InstanceSnapshot, InstigatingSource}, + vfs::{FsResultExt, Vfs, VfsEntry, VfsFetcher}, }; use super::{ context::InstanceSnapshotContext, error::SnapshotError, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, - snapshot_from_imfs, + snapshot_from_vfs, }; /// Handles snapshots for: @@ -21,19 +21,19 @@ use super::{ pub struct SnapshotProject; impl SnapshotMiddleware for SnapshotProject { - fn from_imfs( + fn from_vfs( context: &mut InstanceSnapshotContext, - imfs: &mut Imfs, - entry: &ImfsEntry, + vfs: &mut Vfs, + entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { let project_path = entry.path().join("default.project.json"); - match imfs.get(project_path).with_not_found()? { + match vfs.get(project_path).with_not_found()? { // TODO: Do we need to muck with the relevant paths if we're a // project file within a folder? Should the folder path be the // relevant path instead of the project file path? - Some(entry) => return SnapshotProject::from_imfs(context, imfs, &entry), + Some(entry) => return SnapshotProject::from_vfs(context, vfs, &entry), None => return Ok(None), } } @@ -43,13 +43,13 @@ impl SnapshotMiddleware for SnapshotProject { return Ok(None); } - let project = Project::load_from_slice(entry.contents(imfs)?, entry.path()) + let project = Project::load_from_slice(entry.contents(vfs)?, entry.path()) .map_err(|err| SnapshotError::malformed_project(err, entry.path()))?; // Snapshotting a project should always return an instance, so this // unwrap is safe. let mut snapshot = - snapshot_project_node(context, &project.name, &project.tree, imfs)?.unwrap(); + snapshot_project_node(context, &project.name, &project.tree, vfs)?.unwrap(); // Setting the instigating source to the project file path is a little // coarse. @@ -76,11 +76,11 @@ impl SnapshotMiddleware for SnapshotProject { } } -fn snapshot_project_node( +fn snapshot_project_node( context: &mut InstanceSnapshotContext, instance_name: &str, node: &ProjectNode, - imfs: &mut Imfs, + vfs: &mut Vfs, ) -> SnapshotInstanceResult<'static> { let name = Cow::Owned(instance_name.to_owned()); let mut class_name = node @@ -92,9 +92,9 @@ fn snapshot_project_node( let mut metadata = InstanceMetadata::default(); if let Some(path) = &node.path { - let entry = imfs.get(path)?; + let entry = vfs.get(path)?; - if let Some(snapshot) = snapshot_from_imfs(context, imfs, &entry)? { + if let Some(snapshot) = snapshot_from_vfs(context, vfs, &entry)? { // If a class name was already specified, then it'll override the // class name of this snapshot ONLY if it's a Folder. // @@ -144,7 +144,7 @@ fn snapshot_project_node( .expect("$className or $path must be specified"); for (child_name, child_project_node) in &node.children { - if let Some(child) = snapshot_project_node(context, child_name, child_project_node, imfs)? { + if let Some(child) = snapshot_project_node(context, child_name, child_project_node, vfs)? { children.push(child); } } @@ -192,15 +192,15 @@ mod test { use insta::assert_yaml_snapshot; use maplit::hashmap; - use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; + use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot}; #[test] fn project_from_folder() { let _ = env_logger::try_init(); - let mut imfs = Imfs::new(NoopFetcher); - let dir = ImfsSnapshot::dir(hashmap! { - "default.project.json" => ImfsSnapshot::file(r#" + let mut vfs = Vfs::new(NoopFetcher); + let dir = VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" { "name": "indirect-project", "tree": { @@ -210,11 +210,11 @@ mod test { "#), }); - imfs.debug_load_snapshot("/foo", dir); + vfs.debug_load_snapshot("/foo", dir); - let entry = imfs.get("/foo").unwrap(); + let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -225,9 +225,9 @@ mod test { fn project_from_direct_file() { let _ = env_logger::try_init(); - let mut imfs = Imfs::new(NoopFetcher); - let dir = ImfsSnapshot::dir(hashmap! { - "hello.project.json" => ImfsSnapshot::file(r#" + let mut vfs = Vfs::new(NoopFetcher); + let dir = VfsSnapshot::dir(hashmap! { + "hello.project.json" => VfsSnapshot::file(r#" { "name": "direct-project", "tree": { @@ -237,11 +237,11 @@ mod test { "#), }); - imfs.debug_load_snapshot("/foo", dir); + vfs.debug_load_snapshot("/foo", dir); - let entry = imfs.get("/foo/hello.project.json").unwrap(); + let entry = vfs.get("/foo/hello.project.json").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -252,9 +252,9 @@ mod test { fn project_with_resolved_properties() { let _ = env_logger::try_init(); - let mut imfs = Imfs::new(NoopFetcher); - let dir = ImfsSnapshot::dir(hashmap! { - "default.project.json" => ImfsSnapshot::file(r#" + let mut vfs = Vfs::new(NoopFetcher); + let dir = VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" { "name": "resolved-properties", "tree": { @@ -270,11 +270,11 @@ mod test { "#), }); - imfs.debug_load_snapshot("/foo", dir); + vfs.debug_load_snapshot("/foo", dir); - let entry = imfs.get("/foo").unwrap(); + let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -285,9 +285,9 @@ mod test { fn project_with_unresolved_properties() { let _ = env_logger::try_init(); - let mut imfs = Imfs::new(NoopFetcher); - let dir = ImfsSnapshot::dir(hashmap! { - "default.project.json" => ImfsSnapshot::file(r#" + let mut vfs = Vfs::new(NoopFetcher); + let dir = VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" { "name": "unresolved-properties", "tree": { @@ -300,11 +300,11 @@ mod test { "#), }); - imfs.debug_load_snapshot("/foo", dir); + vfs.debug_load_snapshot("/foo", dir); - let entry = imfs.get("/foo").unwrap(); + let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -315,9 +315,9 @@ mod test { fn project_with_children() { let _ = env_logger::try_init(); - let mut imfs = Imfs::new(NoopFetcher); - let dir = ImfsSnapshot::dir(hashmap! { - "default.project.json" => ImfsSnapshot::file(r#" + let mut vfs = Vfs::new(NoopFetcher); + let dir = VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" { "name": "children", "tree": { @@ -331,11 +331,11 @@ mod test { "#), }); - imfs.debug_load_snapshot("/foo", dir); + vfs.debug_load_snapshot("/foo", dir); - let entry = imfs.get("/foo").unwrap(); + let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -346,9 +346,9 @@ mod test { fn project_with_path_to_txt() { let _ = env_logger::try_init(); - let mut imfs = Imfs::new(NoopFetcher); - let dir = ImfsSnapshot::dir(hashmap! { - "default.project.json" => ImfsSnapshot::file(r#" + let mut vfs = Vfs::new(NoopFetcher); + let dir = VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" { "name": "path-project", "tree": { @@ -356,14 +356,14 @@ mod test { } } "#), - "other.txt" => ImfsSnapshot::file("Hello, world!"), + "other.txt" => VfsSnapshot::file("Hello, world!"), }); - imfs.debug_load_snapshot("/foo", dir); + vfs.debug_load_snapshot("/foo", dir); - let entry = imfs.get("/foo").unwrap(); + let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -374,9 +374,9 @@ mod test { fn project_with_path_to_project() { let _ = env_logger::try_init(); - let mut imfs = Imfs::new(NoopFetcher); - let dir = ImfsSnapshot::dir(hashmap! { - "default.project.json" => ImfsSnapshot::file(r#" + let mut vfs = Vfs::new(NoopFetcher); + let dir = VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" { "name": "path-project", "tree": { @@ -384,7 +384,7 @@ mod test { } } "#), - "other.project.json" => ImfsSnapshot::file(r#" + "other.project.json" => VfsSnapshot::file(r#" { "name": "other-project", "tree": { @@ -394,11 +394,11 @@ mod test { "#), }); - imfs.debug_load_snapshot("/foo", dir); + vfs.debug_load_snapshot("/foo", dir); - let entry = imfs.get("/foo").unwrap(); + let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -409,9 +409,9 @@ mod test { fn project_with_path_to_project_with_children() { let _ = env_logger::try_init(); - let mut imfs = Imfs::new(NoopFetcher); - let dir = ImfsSnapshot::dir(hashmap! { - "default.project.json" => ImfsSnapshot::file(r#" + let mut vfs = Vfs::new(NoopFetcher); + let dir = VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" { "name": "path-child-project", "tree": { @@ -419,7 +419,7 @@ mod test { } } "#), - "other.project.json" => ImfsSnapshot::file(r#" + "other.project.json" => VfsSnapshot::file(r#" { "name": "other-project", "tree": { @@ -433,11 +433,11 @@ mod test { "#), }); - imfs.debug_load_snapshot("/foo", dir); + vfs.debug_load_snapshot("/foo", dir); - let entry = imfs.get("/foo").unwrap(); + let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -451,9 +451,9 @@ mod test { fn project_path_property_overrides() { let _ = env_logger::try_init(); - let mut imfs = Imfs::new(NoopFetcher); - let dir = ImfsSnapshot::dir(hashmap! { - "default.project.json" => ImfsSnapshot::file(r#" + let mut vfs = Vfs::new(NoopFetcher); + let dir = VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" { "name": "path-property-override", "tree": { @@ -464,7 +464,7 @@ mod test { } } "#), - "other.project.json" => ImfsSnapshot::file(r#" + "other.project.json" => VfsSnapshot::file(r#" { "name": "other-project", "tree": { @@ -477,11 +477,11 @@ mod test { "#), }); - imfs.debug_load_snapshot("/foo", dir); + vfs.debug_load_snapshot("/foo", dir); - let entry = imfs.get("/foo").unwrap(); + let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index 531ef4d8..c758dd34 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -1,8 +1,8 @@ use std::borrow::Cow; use crate::{ - imfs::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, + vfs::{Vfs, VfsEntry, VfsFetcher}, }; use super::{ @@ -14,10 +14,10 @@ use super::{ pub struct SnapshotRbxlx; impl SnapshotMiddleware for SnapshotRbxlx { - fn from_imfs( + fn from_vfs( _context: &mut InstanceSnapshotContext, - imfs: &mut Imfs, - entry: &ImfsEntry, + vfs: &mut Vfs, + entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { return Ok(None); @@ -31,7 +31,7 @@ impl SnapshotMiddleware for SnapshotRbxlx { let options = rbx_xml::DecodeOptions::new() .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); - let temp_tree = rbx_xml::from_reader(entry.contents(imfs)?, options) + let temp_tree = rbx_xml::from_reader(entry.contents(vfs)?, options) .expect("TODO: Handle rbx_xml errors"); let root_id = temp_tree.get_root_id(); diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 7d11751a..03bbc28d 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -3,8 +3,8 @@ use std::{borrow::Cow, collections::HashMap}; use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; use crate::{ - imfs::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, + vfs::{Vfs, VfsEntry, VfsFetcher}, }; use super::{ @@ -16,10 +16,10 @@ use super::{ pub struct SnapshotRbxm; impl SnapshotMiddleware for SnapshotRbxm { - fn from_imfs( + fn from_vfs( _context: &mut InstanceSnapshotContext, - imfs: &mut Imfs, - entry: &ImfsEntry, + vfs: &mut Vfs, + entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { return Ok(None); @@ -37,7 +37,7 @@ impl SnapshotMiddleware for SnapshotRbxm { }); let root_id = temp_tree.get_root_id(); - rbx_binary::decode(&mut temp_tree, root_id, entry.contents(imfs)?) + rbx_binary::decode(&mut temp_tree, root_id, entry.contents(vfs)?) .expect("TODO: Handle rbx_binary errors"); let root_instance = temp_tree.get_instance(root_id).unwrap(); @@ -60,18 +60,18 @@ impl SnapshotMiddleware for SnapshotRbxm { mod test { use super::*; - use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; + use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot}; #[test] - fn model_from_imfs() { - let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file(include_bytes!("../../assets/test-folder.rbxm").to_vec()); + fn model_from_vfs() { + let mut vfs = Vfs::new(NoopFetcher); + let file = VfsSnapshot::file(include_bytes!("../../assets/test-folder.rbxm").to_vec()); - imfs.debug_load_snapshot("/foo.rbxm", file); + vfs.debug_load_snapshot("/foo.rbxm", file); - let entry = imfs.get("/foo.rbxm").unwrap(); + let entry = vfs.get("/foo.rbxm").unwrap(); let instance_snapshot = - SnapshotRbxm::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotRbxm::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 663c2f0d..8c3b142f 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -1,8 +1,8 @@ use std::borrow::Cow; use crate::{ - imfs::{Imfs, ImfsEntry, ImfsFetcher}, snapshot::InstanceSnapshot, + vfs::{Vfs, VfsEntry, VfsFetcher}, }; use super::{ @@ -14,10 +14,10 @@ use super::{ pub struct SnapshotRbxmx; impl SnapshotMiddleware for SnapshotRbxmx { - fn from_imfs( + fn from_vfs( _context: &mut InstanceSnapshotContext, - imfs: &mut Imfs, - entry: &ImfsEntry, + vfs: &mut Vfs, + entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { return Ok(None); @@ -31,7 +31,7 @@ impl SnapshotMiddleware for SnapshotRbxmx { let options = rbx_xml::DecodeOptions::new() .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); - let temp_tree = rbx_xml::from_reader(entry.contents(imfs)?, options) + let temp_tree = rbx_xml::from_reader(entry.contents(vfs)?, options) .expect("TODO: Handle rbx_xml errors"); let root_instance = temp_tree.get_instance(temp_tree.get_root_id()).unwrap(); @@ -56,12 +56,12 @@ mod test { use std::collections::HashMap; - use crate::imfs::{ImfsDebug, ImfsSnapshot, NoopFetcher}; + use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot}; #[test] - fn model_from_imfs() { - let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file( + fn model_from_vfs() { + let mut vfs = Vfs::new(NoopFetcher); + let file = VfsSnapshot::file( r#" @@ -73,11 +73,11 @@ mod test { "#, ); - imfs.debug_load_snapshot("/foo.rbxmx", file); + vfs.debug_load_snapshot("/foo.rbxmx", file); - let entry = imfs.get("/foo.rbxmx").unwrap(); + let entry = vfs.get("/foo.rbxmx").unwrap(); let instance_snapshot = - SnapshotRbxmx::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotRbxmx::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/snapshots/test__client_from_imfs.snap b/src/snapshot_middleware/snapshots/test__client_from_vfs.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__client_from_imfs.snap rename to src/snapshot_middleware/snapshots/test__client_from_vfs.snap diff --git a/src/snapshot_middleware/snapshots/test__csv_from_imfs.snap b/src/snapshot_middleware/snapshots/test__csv_from_vfs.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__csv_from_imfs.snap rename to src/snapshot_middleware/snapshots/test__csv_from_vfs.snap diff --git a/src/snapshot_middleware/snapshots/test__instance_from_imfs.snap b/src/snapshot_middleware/snapshots/test__instance_from_vfs.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__instance_from_imfs.snap rename to src/snapshot_middleware/snapshots/test__instance_from_vfs.snap diff --git a/src/snapshot_middleware/snapshots/test__model_from_imfs.snap b/src/snapshot_middleware/snapshots/test__model_from_vfs.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__model_from_imfs.snap rename to src/snapshot_middleware/snapshots/test__model_from_vfs.snap diff --git a/src/snapshot_middleware/snapshots/test__module_from_imfs.snap b/src/snapshot_middleware/snapshots/test__module_from_vfs.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__module_from_imfs.snap rename to src/snapshot_middleware/snapshots/test__module_from_vfs.snap diff --git a/src/snapshot_middleware/snapshots/test__server_from_imfs.snap b/src/snapshot_middleware/snapshots/test__server_from_vfs.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__server_from_imfs.snap rename to src/snapshot_middleware/snapshots/test__server_from_vfs.snap diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 11584d15..6d34d3d1 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -4,8 +4,8 @@ use maplit::hashmap; use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; use crate::{ - imfs::{FileSnapshot, FsResultExt, Imfs, ImfsEntry, ImfsFetcher, ImfsSnapshot}, snapshot::{InstanceMetadata, InstanceSnapshot}, + vfs::{FileSnapshot, FsResultExt, Vfs, VfsEntry, VfsFetcher, VfsSnapshot}, }; use super::{ @@ -19,10 +19,10 @@ use super::{ pub struct SnapshotTxt; impl SnapshotMiddleware for SnapshotTxt { - fn from_imfs( + fn from_vfs( _context: &mut InstanceSnapshotContext, - imfs: &mut Imfs, - entry: &ImfsEntry, + vfs: &mut Vfs, + entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { return Ok(None); @@ -33,7 +33,7 @@ impl SnapshotMiddleware for SnapshotTxt { None => return Ok(None), }; - let contents = entry.contents(imfs)?; + let contents = entry.contents(vfs)?; let contents_str = str::from_utf8(contents) .map_err(|err| SnapshotError::file_contents_bad_unicode(err, entry.path()))? .to_string(); @@ -61,8 +61,8 @@ impl SnapshotMiddleware for SnapshotTxt { children: Vec::new(), }; - if let Some(meta_entry) = imfs.get(meta_path).with_not_found()? { - let meta_contents = meta_entry.contents(imfs)?; + if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { + let meta_contents = meta_entry.contents(vfs)?; let mut metadata = AdjacentMetadata::from_slice(meta_contents); metadata.apply_all(&mut snapshot); } @@ -87,7 +87,7 @@ impl SnapshotMiddleware for SnapshotTxt { None => String::new(), }; - let snapshot = ImfsSnapshot::File(FileSnapshot { + let snapshot = VfsSnapshot::File(FileSnapshot { contents: value.into_bytes(), }); @@ -106,18 +106,18 @@ mod test { use maplit::hashmap; use rbx_dom_weak::RbxInstanceProperties; - use crate::imfs::{ImfsDebug, NoopFetcher}; + use crate::vfs::{NoopFetcher, VfsDebug}; #[test] - fn instance_from_imfs() { - let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file("Hello there!"); + fn instance_from_vfs() { + let mut vfs = Vfs::new(NoopFetcher); + let file = VfsSnapshot::file("Hello there!"); - imfs.debug_load_snapshot("/foo.txt", file); + vfs.debug_load_snapshot("/foo.txt", file); - let entry = imfs.get("/foo.txt").unwrap(); + let entry = vfs.get("/foo.txt").unwrap(); let instance_snapshot = - SnapshotTxt::from_imfs(&mut InstanceSnapshotContext::default(), &mut imfs, &entry) + SnapshotTxt::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -125,7 +125,7 @@ mod test { } #[test] - fn imfs_from_instance() { + fn vfs_from_instance() { let tree = RbxTree::new(string_value("Root", "Hello, world!")); let root_id = tree.get_root_id(); diff --git a/src/snapshot_middleware/user_plugins.rs b/src/snapshot_middleware/user_plugins.rs index c98dda3b..6e4627ce 100644 --- a/src/snapshot_middleware/user_plugins.rs +++ b/src/snapshot_middleware/user_plugins.rs @@ -2,7 +2,7 @@ use std::{fs, path::Path}; use rlua::{Lua, RegistryKey}; -use crate::imfs::{Imfs, ImfsEntry, ImfsFetcher}; +use crate::vfs::{Vfs, VfsEntry, VfsFetcher}; use super::{ context::InstanceSnapshotContext, @@ -19,10 +19,10 @@ use super::{ pub struct SnapshotUserPlugins; impl SnapshotMiddleware for SnapshotUserPlugins { - fn from_imfs( + fn from_vfs( context: &mut InstanceSnapshotContext, - _imfs: &mut Imfs, - _entry: &ImfsEntry, + _vfs: &mut Vfs, + _entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { // User plugins are only enabled if present on the snapshot context. let plugin_context = match &mut context.plugin_context { @@ -52,7 +52,7 @@ impl SnapshotMiddleware for SnapshotUserPlugins { // The current plan for plugins here is to make them work // like Redux/Rodux middleware. A plugin will be a function // that accepts the next middleware in the chain as a - // function and the snapshot subject (the IMFS entry). + // function and the snapshot subject (the VFS entry). // // Plugins can (but don't have to) invoke the next snapshot // function and may or may not mutate the result. The hope @@ -69,7 +69,7 @@ impl SnapshotMiddleware for SnapshotUserPlugins { // * Will plugins hurt Rojo's ability to parallelize // snapshotting in the future? // - // * Do the mutable handles to the Imfs and the snapshot + // * Do the mutable handles to the Vfs and the snapshot // context prevent plugins from invoking other plugins // indirectly? // diff --git a/src/imfs/error.rs b/src/vfs/error.rs similarity index 100% rename from src/imfs/error.rs rename to src/vfs/error.rs diff --git a/src/imfs/event.rs b/src/vfs/event.rs similarity index 84% rename from src/imfs/event.rs rename to src/vfs/event.rs index b82e7a0a..93c641ff 100644 --- a/src/imfs/event.rs +++ b/src/vfs/event.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; #[derive(Debug)] -pub enum ImfsEvent { +pub enum VfsEvent { Modified(PathBuf), Created(PathBuf), Removed(PathBuf), diff --git a/src/imfs/fetcher.rs b/src/vfs/fetcher.rs similarity index 83% rename from src/imfs/fetcher.rs rename to src/vfs/fetcher.rs index 61bb544d..bb321093 100644 --- a/src/imfs/fetcher.rs +++ b/src/vfs/fetcher.rs @@ -5,7 +5,7 @@ use std::{ use crossbeam_channel::Receiver; -use super::event::ImfsEvent; +use super::event::VfsEvent; #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum FileType { @@ -13,10 +13,10 @@ pub enum FileType { Directory, } -/// The generic interface that `Imfs` uses to lazily read files from the disk. +/// The generic interface that `Vfs` uses to lazily read files from the disk. /// In tests, it's stubbed out to do different versions of absolutely nothing /// depending on the test. -pub trait ImfsFetcher { +pub trait VfsFetcher { fn file_type(&mut self, path: &Path) -> io::Result; fn read_children(&mut self, path: &Path) -> io::Result>; fn read_contents(&mut self, path: &Path) -> io::Result>; @@ -27,7 +27,7 @@ pub trait ImfsFetcher { fn watch(&mut self, path: &Path); fn unwatch(&mut self, path: &Path); - fn receiver(&self) -> Receiver; + fn receiver(&self) -> Receiver; /// A method intended for debugging what paths the fetcher is watching. fn watched_paths(&self) -> Vec<&Path> { diff --git a/src/imfs/mod.rs b/src/vfs/mod.rs similarity index 91% rename from src/imfs/mod.rs rename to src/vfs/mod.rs index 58f51719..32b48f0b 100644 --- a/src/imfs/mod.rs +++ b/src/vfs/mod.rs @@ -1,18 +1,18 @@ mod error; mod event; mod fetcher; -mod imfs; mod noop_fetcher; mod real_fetcher; mod snapshot; +mod vfs; pub use error::*; pub use event::*; pub use fetcher::*; -pub use imfs::*; pub use noop_fetcher::*; pub use real_fetcher::*; pub use snapshot::*; +pub use vfs::*; #[cfg(test)] mod test_fetcher; diff --git a/src/imfs/noop_fetcher.rs b/src/vfs/noop_fetcher.rs similarity index 85% rename from src/imfs/noop_fetcher.rs rename to src/vfs/noop_fetcher.rs index cf3ed829..b0312185 100644 --- a/src/imfs/noop_fetcher.rs +++ b/src/vfs/noop_fetcher.rs @@ -1,4 +1,4 @@ -//! Implements the IMFS fetcher interface for a fake filesystem using Rust's +//! Implements the VFS fetcher interface for a fake filesystem using Rust's //! std::fs interface. // This interface is only used for testing, so it's okay if it isn't used. @@ -12,13 +12,13 @@ use std::{ use crossbeam_channel::Receiver; use super::{ - event::ImfsEvent, - fetcher::{FileType, ImfsFetcher}, + event::VfsEvent, + fetcher::{FileType, VfsFetcher}, }; pub struct NoopFetcher; -impl ImfsFetcher for NoopFetcher { +impl VfsFetcher for NoopFetcher { fn file_type(&mut self, _path: &Path) -> io::Result { Err(io::Error::new( io::ErrorKind::NotFound, @@ -56,7 +56,7 @@ impl ImfsFetcher for NoopFetcher { fn unwatch(&mut self, _path: &Path) {} - fn receiver(&self) -> Receiver { + fn receiver(&self) -> Receiver { crossbeam_channel::never() } } diff --git a/src/imfs/real_fetcher.rs b/src/vfs/real_fetcher.rs similarity index 90% rename from src/imfs/real_fetcher.rs rename to src/vfs/real_fetcher.rs index 814fb704..f2f686d9 100644 --- a/src/imfs/real_fetcher.rs +++ b/src/vfs/real_fetcher.rs @@ -1,4 +1,4 @@ -//! Implements the IMFS fetcher interface for the real filesystem using Rust's +//! Implements the VFS fetcher interface for the real filesystem using Rust's //! std::fs interface and notify as the file watcher. use std::{ @@ -14,8 +14,8 @@ use jod_thread::JoinHandle; use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; use super::{ - event::ImfsEvent, - fetcher::{FileType, ImfsFetcher}, + event::VfsEvent, + fetcher::{FileType, VfsFetcher}, }; /// Workaround to disable the file watcher for processes that don't need it, @@ -41,7 +41,7 @@ pub struct RealFetcher { _converter_thread: JoinHandle<()>, /// The crossbeam receiver filled with events from the converter thread. - receiver: Receiver, + receiver: Receiver, /// All of the paths that the fetcher is watching, tracked here because /// notify does not expose this information. @@ -84,19 +84,19 @@ impl RealFetcher { } } -fn converter_thread(notify_receiver: mpsc::Receiver, sender: Sender) { +fn converter_thread(notify_receiver: mpsc::Receiver, sender: Sender) { use DebouncedEvent::*; for event in notify_receiver { log::trace!("Notify event: {:?}", event); match event { - Create(path) => sender.send(ImfsEvent::Created(path)).unwrap(), - Write(path) => sender.send(ImfsEvent::Modified(path)).unwrap(), - Remove(path) => sender.send(ImfsEvent::Removed(path)).unwrap(), + Create(path) => sender.send(VfsEvent::Created(path)).unwrap(), + Write(path) => sender.send(VfsEvent::Modified(path)).unwrap(), + Remove(path) => sender.send(VfsEvent::Removed(path)).unwrap(), Rename(from_path, to_path) => { - sender.send(ImfsEvent::Created(from_path)).unwrap(); - sender.send(ImfsEvent::Removed(to_path)).unwrap(); + sender.send(VfsEvent::Created(from_path)).unwrap(); + sender.send(VfsEvent::Removed(to_path)).unwrap(); } Rescan => { log::warn!("Unhandled filesystem rescan event."); @@ -121,7 +121,7 @@ fn converter_thread(notify_receiver: mpsc::Receiver, sender: Sen } } -impl ImfsFetcher for RealFetcher { +impl VfsFetcher for RealFetcher { fn file_type(&mut self, path: &Path) -> io::Result { let metadata = fs::metadata(path)?; @@ -206,7 +206,7 @@ impl ImfsFetcher for RealFetcher { } } - fn receiver(&self) -> Receiver { + fn receiver(&self) -> Receiver { self.receiver.clone() } diff --git a/src/vfs/snapshot.rs b/src/vfs/snapshot.rs new file mode 100644 index 00000000..34187232 --- /dev/null +++ b/src/vfs/snapshot.rs @@ -0,0 +1,42 @@ +// This file is non-critical and used for testing, so it's okay if it's unused. +#![allow(unused)] + +use std::collections::HashMap; + +#[derive(Debug, Clone)] +pub enum VfsSnapshot { + File(FileSnapshot), + Directory(DirectorySnapshot), +} + +impl VfsSnapshot { + /// Create a new file VfsSnapshot with the given contents. + pub fn file(contents: impl Into>) -> VfsSnapshot { + VfsSnapshot::File(FileSnapshot { + contents: contents.into(), + }) + } + + /// Create a new directory VfsSnapshot with the given children. + pub fn dir>(children: HashMap) -> VfsSnapshot { + let children = children.into_iter().map(|(k, v)| (k.into(), v)).collect(); + + VfsSnapshot::Directory(DirectorySnapshot { children }) + } + + pub fn empty_dir() -> VfsSnapshot { + VfsSnapshot::Directory(DirectorySnapshot { + children: Default::default(), + }) + } +} + +#[derive(Debug, Clone)] +pub struct FileSnapshot { + pub contents: Vec, +} + +#[derive(Debug, Clone)] +pub struct DirectorySnapshot { + pub children: HashMap, +} diff --git a/src/imfs/test_fetcher.rs b/src/vfs/test_fetcher.rs similarity index 85% rename from src/imfs/test_fetcher.rs rename to src/vfs/test_fetcher.rs index 96936415..9e37717c 100644 --- a/src/imfs/test_fetcher.rs +++ b/src/vfs/test_fetcher.rs @@ -1,7 +1,7 @@ -//! Implements the IMFS fetcher interface for a fake filesystem that can be +//! Implements the VFS fetcher interface for a fake filesystem that can be //! mutated and have changes signaled through it. //! -//! This is useful for testing how things using Imfs react to changed events +//! This is useful for testing how things using Vfs react to changed events //! without relying on the real filesystem implementation, which is very //! platform-specific. @@ -19,9 +19,9 @@ use crossbeam_channel::{unbounded, Receiver, Sender}; use crate::path_map::PathMap; use super::{ - event::ImfsEvent, - fetcher::{FileType, ImfsFetcher}, - snapshot::ImfsSnapshot, + event::VfsEvent, + fetcher::{FileType, VfsFetcher}, + snapshot::VfsSnapshot, }; #[derive(Clone)] @@ -30,7 +30,7 @@ pub struct TestFetcherState { } impl TestFetcherState { - pub fn load_snapshot>(&self, path: P, snapshot: ImfsSnapshot) { + pub fn load_snapshot>(&self, path: P, snapshot: VfsSnapshot) { let mut inner = self.inner.lock().unwrap(); inner.load_snapshot(path.as_ref().to_path_buf(), snapshot); } @@ -40,7 +40,7 @@ impl TestFetcherState { inner.remove(path.as_ref()); } - pub fn raise_event(&self, event: ImfsEvent) { + pub fn raise_event(&self, event: VfsEvent) { let mut inner = self.inner.lock().unwrap(); inner.raise_event(event); } @@ -53,24 +53,24 @@ pub enum TestFetcherEntry { struct TestFetcherStateInner { entries: PathMap, - sender: Sender, + sender: Sender, } impl TestFetcherStateInner { - fn new(sender: Sender) -> Self { + fn new(sender: Sender) -> Self { let mut entries = PathMap::new(); entries.insert(Path::new("/"), TestFetcherEntry::Dir); Self { sender, entries } } - fn load_snapshot(&mut self, path: PathBuf, snapshot: ImfsSnapshot) { + fn load_snapshot(&mut self, path: PathBuf, snapshot: VfsSnapshot) { match snapshot { - ImfsSnapshot::File(file) => { + VfsSnapshot::File(file) => { self.entries .insert(path, TestFetcherEntry::File(file.contents)); } - ImfsSnapshot::Directory(directory) => { + VfsSnapshot::Directory(directory) => { self.entries.insert(path.clone(), TestFetcherEntry::Dir); for (child_name, child) in directory.children.into_iter() { @@ -84,14 +84,14 @@ impl TestFetcherStateInner { self.entries.remove(path); } - fn raise_event(&mut self, event: ImfsEvent) { + fn raise_event(&mut self, event: VfsEvent) { self.sender.send(event).unwrap(); } } pub struct TestFetcher { state: TestFetcherState, - receiver: Receiver, + receiver: Receiver, } impl TestFetcher { @@ -106,7 +106,7 @@ impl TestFetcher { } } -impl ImfsFetcher for TestFetcher { +impl VfsFetcher for TestFetcher { fn file_type(&mut self, path: &Path) -> io::Result { let inner = self.state.inner.lock().unwrap(); @@ -169,7 +169,7 @@ impl ImfsFetcher for TestFetcher { fn unwatch(&mut self, _path: &Path) {} - fn receiver(&self) -> Receiver { + fn receiver(&self) -> Receiver { self.receiver.clone() } } diff --git a/src/imfs/imfs.rs b/src/vfs/vfs.rs similarity index 71% rename from src/imfs/imfs.rs rename to src/vfs/vfs.rs index 5cd2024c..355ce592 100644 --- a/src/imfs/imfs.rs +++ b/src/vfs/vfs.rs @@ -9,48 +9,48 @@ use crate::path_map::PathMap; use super::{ error::{FsError, FsResult}, - event::ImfsEvent, - fetcher::{FileType, ImfsFetcher}, - snapshot::ImfsSnapshot, + event::VfsEvent, + fetcher::{FileType, VfsFetcher}, + snapshot::VfsSnapshot, }; /// An in-memory filesystem that can be incrementally populated and updated as /// filesystem modification events occur. /// -/// All operations on the `Imfs` are lazy and do I/O as late as they can to +/// All operations on the `Vfs` are lazy and do I/O as late as they can to /// avoid reading extraneous files or directories from the disk. This means that /// they all take `self` mutably, and means that it isn't possible to hold -/// references to the internal state of the Imfs while traversing it! +/// references to the internal state of the Vfs while traversing it! /// -/// Most operations return `ImfsEntry` objects to work around this, which is -/// effectively a index into the `Imfs`. -pub struct Imfs { +/// Most operations return `VfsEntry` objects to work around this, which is +/// effectively a index into the `Vfs`. +pub struct Vfs { /// A hierarchical map from paths to items that have been read or partially - /// read into memory by the Imfs. - inner: PathMap, + /// read into memory by the Vfs. + inner: PathMap, - /// This Imfs's fetcher, which is used for all actual interactions with the + /// This Vfs's fetcher, which is used for all actual interactions with the /// filesystem. It's referred to by the type parameter `F` all over, and is /// generic in order to make it feasible to mock. fetcher: F, } -impl Imfs { - pub fn new(fetcher: F) -> Imfs { - Imfs { +impl Vfs { + pub fn new(fetcher: F) -> Vfs { + Vfs { inner: PathMap::new(), fetcher, } } - pub fn change_receiver(&self) -> Receiver { + pub fn change_receiver(&self) -> Receiver { self.fetcher.receiver() } - pub fn commit_change(&mut self, event: &ImfsEvent) -> FsResult<()> { - use ImfsEvent::*; + pub fn commit_change(&mut self, event: &VfsEvent) -> FsResult<()> { + use VfsEvent::*; - log::trace!("Committing Imfs change {:?}", event); + log::trace!("Committing Vfs change {:?}", event); match event { Created(path) | Modified(path) => { @@ -79,28 +79,28 @@ impl Imfs { match self.inner.get_mut(path) { Some(existing_item) => { match (existing_item, &new_type) { - (ImfsItem::File(existing_file), FileType::File) => { + (VfsItem::File(existing_file), FileType::File) => { // Invalidate the existing file contents. // We can probably be smarter about this by reading the changed file. existing_file.contents = None; } - (ImfsItem::Directory(_), FileType::Directory) => { + (VfsItem::Directory(_), FileType::Directory) => { // No changes required, a directory updating doesn't mean anything to us. self.fetcher.watch(path); } - (ImfsItem::File(_), FileType::Directory) => { + (VfsItem::File(_), FileType::Directory) => { self.inner.remove(path); self.inner.insert( path.to_path_buf(), - ImfsItem::new_from_type(FileType::Directory, path), + VfsItem::new_from_type(FileType::Directory, path), ); self.fetcher.watch(path); } - (ImfsItem::Directory(_), FileType::File) => { + (VfsItem::Directory(_), FileType::File) => { self.inner.remove(path); self.inner.insert( path.to_path_buf(), - ImfsItem::new_from_type(FileType::File, path), + VfsItem::new_from_type(FileType::File, path), ); self.fetcher.unwatch(path); } @@ -108,7 +108,7 @@ impl Imfs { } None => { self.inner - .insert(path.to_path_buf(), ImfsItem::new_from_type(new_type, path)); + .insert(path.to_path_buf(), VfsItem::new_from_type(new_type, path)); } } @@ -127,17 +127,17 @@ impl Imfs { Ok(()) } - pub fn get(&mut self, path: impl AsRef) -> FsResult { + pub fn get(&mut self, path: impl AsRef) -> FsResult { self.read_if_not_exists(path.as_ref())?; let item = self.inner.get(path.as_ref()).unwrap(); let is_file = match item { - ImfsItem::File(_) => true, - ImfsItem::Directory(_) => false, + VfsItem::File(_) => true, + VfsItem::Directory(_) => false, }; - Ok(ImfsEntry { + Ok(VfsEntry { path: item.path().to_path_buf(), is_file, }) @@ -149,7 +149,7 @@ impl Imfs { self.read_if_not_exists(path)?; match self.inner.get_mut(path).unwrap() { - ImfsItem::File(file) => { + VfsItem::File(file) => { if file.contents.is_none() { file.contents = Some( self.fetcher @@ -160,20 +160,20 @@ impl Imfs { Ok(file.contents.as_ref().unwrap()) } - ImfsItem::Directory(_) => Err(FsError::new( + VfsItem::Directory(_) => Err(FsError::new( io::Error::new(io::ErrorKind::Other, "Can't read a directory"), path.to_path_buf(), )), } } - pub fn get_children(&mut self, path: impl AsRef) -> FsResult> { + pub fn get_children(&mut self, path: impl AsRef) -> FsResult> { let path = path.as_ref(); self.read_if_not_exists(path)?; match self.inner.get_mut(path).unwrap() { - ImfsItem::Directory(dir) => { + VfsItem::Directory(dir) => { self.fetcher.watch(path); let enumerated = dir.children_enumerated; @@ -187,7 +187,7 @@ impl Imfs { .collect::>() // Collect all PathBufs, since self.get needs to borrow self mutably. .into_iter() .map(|path| self.get(path)) - .collect::>>() + .collect::>>() } else { dir.children_enumerated = true; @@ -196,10 +196,10 @@ impl Imfs { .map_err(|err| FsError::new(err, path.to_path_buf()))? .into_iter() .map(|path| self.get(path)) - .collect::>>() + .collect::>>() } } - ImfsItem::File(_) => Err(FsError::new( + VfsItem::File(_) => Err(FsError::new( io::Error::new(io::ErrorKind::Other, "Can't read a directory"), path.to_path_buf(), )), @@ -222,7 +222,7 @@ impl Imfs { } if let Some(parent) = path.parent() { - if let Some(ImfsItem::Directory(dir)) = self.inner.get(parent) { + if let Some(VfsItem::Directory(dir)) = self.inner.get(parent) { return !dir.children_enumerated; } } @@ -230,10 +230,10 @@ impl Imfs { false } - /// Attempts to read the path into the `Imfs` if it doesn't exist. + /// Attempts to read the path into the `Vfs` if it doesn't exist. /// /// This does not necessitate that file contents or directory children will - /// be read. Depending on the `ImfsFetcher` implementation that the `Imfs` + /// be read. Depending on the `VfsFetcher` implementation that the `Vfs` /// is using, this call may read exactly only the given path and no more. fn read_if_not_exists(&mut self, path: &Path) -> FsResult<()> { if !self.inner.contains_key(path) { @@ -247,7 +247,7 @@ impl Imfs { } self.inner - .insert(path.to_path_buf(), ImfsItem::new_from_type(kind, path)); + .insert(path.to_path_buf(), VfsItem::new_from_type(kind, path)); } Ok(()) @@ -256,8 +256,8 @@ impl Imfs { /// Contains extra methods that should only be used for debugging. They're /// broken out into a separate trait to make it more explicit to depend on them. -pub trait ImfsDebug { - fn debug_load_snapshot>(&mut self, path: P, snapshot: ImfsSnapshot); +pub trait VfsDebug { + fn debug_load_snapshot>(&mut self, path: P, snapshot: VfsSnapshot); fn debug_is_file(&self, path: &Path) -> bool; fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]>; fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)>; @@ -265,24 +265,24 @@ pub trait ImfsDebug { fn debug_watched_paths(&self) -> Vec<&Path>; } -impl ImfsDebug for Imfs { - fn debug_load_snapshot>(&mut self, path: P, snapshot: ImfsSnapshot) { +impl VfsDebug for Vfs { + fn debug_load_snapshot>(&mut self, path: P, snapshot: VfsSnapshot) { let path = path.as_ref(); match snapshot { - ImfsSnapshot::File(file) => { + VfsSnapshot::File(file) => { self.inner.insert( path.to_path_buf(), - ImfsItem::File(ImfsFile { + VfsItem::File(VfsFile { path: path.to_path_buf(), contents: Some(file.contents), }), ); } - ImfsSnapshot::Directory(directory) => { + VfsSnapshot::Directory(directory) => { self.inner.insert( path.to_path_buf(), - ImfsItem::Directory(ImfsDirectory { + VfsItem::Directory(VfsDirectory { path: path.to_path_buf(), children_enumerated: true, }), @@ -297,21 +297,21 @@ impl ImfsDebug for Imfs { fn debug_is_file(&self, path: &Path) -> bool { match self.inner.get(path) { - Some(ImfsItem::File(_)) => true, + Some(VfsItem::File(_)) => true, _ => false, } } fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]> { match self.inner.get(path) { - Some(ImfsItem::File(file)) => file.contents.as_ref().map(|vec| vec.as_slice()), + Some(VfsItem::File(file)) => file.contents.as_ref().map(|vec| vec.as_slice()), _ => None, } } fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)> { match self.inner.get(path) { - Some(ImfsItem::Directory(dir)) => { + Some(VfsItem::Directory(dir)) => { Some((dir.children_enumerated, self.inner.children(path).unwrap())) } _ => None, @@ -327,31 +327,28 @@ impl ImfsDebug for Imfs { } } -/// A reference to file or folder in an `Imfs`. Can only be produced by the -/// entry existing in the Imfs, but can later point to nothing if something +/// A reference to file or folder in an `Vfs`. Can only be produced by the +/// entry existing in the Vfs, but can later point to nothing if something /// would invalidate that path. /// -/// This struct does not borrow from the Imfs since every operation has the +/// This struct does not borrow from the Vfs since every operation has the /// possibility to mutate the underlying data structure and move memory around. -pub struct ImfsEntry { +pub struct VfsEntry { path: PathBuf, is_file: bool, } -impl ImfsEntry { +impl VfsEntry { pub fn path(&self) -> &Path { &self.path } - pub fn contents<'imfs>( - &self, - imfs: &'imfs mut Imfs, - ) -> FsResult<&'imfs [u8]> { - imfs.get_contents(&self.path) + pub fn contents<'vfs>(&self, vfs: &'vfs mut Vfs) -> FsResult<&'vfs [u8]> { + vfs.get_contents(&self.path) } - pub fn children(&self, imfs: &mut Imfs) -> FsResult> { - imfs.get_children(&self.path) + pub fn children(&self, vfs: &mut Vfs) -> FsResult> { + vfs.get_children(&self.path) } pub fn is_file(&self) -> bool { @@ -364,27 +361,27 @@ impl ImfsEntry { } /// Internal structure describing potentially partially-resident files and -/// folders in the `Imfs`. -pub enum ImfsItem { - File(ImfsFile), - Directory(ImfsDirectory), +/// folders in the `Vfs`. +pub enum VfsItem { + File(VfsFile), + Directory(VfsDirectory), } -impl ImfsItem { +impl VfsItem { fn path(&self) -> &Path { match self { - ImfsItem::File(file) => &file.path, - ImfsItem::Directory(dir) => &dir.path, + VfsItem::File(file) => &file.path, + VfsItem::Directory(dir) => &dir.path, } } - fn new_from_type(kind: FileType, path: impl Into) -> ImfsItem { + fn new_from_type(kind: FileType, path: impl Into) -> VfsItem { match kind { - FileType::Directory => ImfsItem::Directory(ImfsDirectory { + FileType::Directory => VfsItem::Directory(VfsDirectory { path: path.into(), children_enumerated: false, }), - FileType::File => ImfsItem::File(ImfsFile { + FileType::File => VfsItem::File(VfsFile { path: path.into(), contents: None, }), @@ -392,12 +389,12 @@ impl ImfsItem { } } -pub struct ImfsFile { +pub struct VfsFile { pub(super) path: PathBuf, pub(super) contents: Option>, } -pub struct ImfsDirectory { +pub struct VfsDirectory { pub(super) path: PathBuf, pub(super) children_enumerated: bool, } @@ -411,30 +408,30 @@ mod test { use crossbeam_channel::Receiver; use maplit::hashmap; - use super::super::{error::FsErrorKind, event::ImfsEvent, noop_fetcher::NoopFetcher}; + use super::super::{error::FsErrorKind, event::VfsEvent, noop_fetcher::NoopFetcher}; #[test] fn from_snapshot_file() { - let mut imfs = Imfs::new(NoopFetcher); - let file = ImfsSnapshot::file("hello, world!"); + let mut vfs = Vfs::new(NoopFetcher); + let file = VfsSnapshot::file("hello, world!"); - imfs.debug_load_snapshot("/hello.txt", file); + vfs.debug_load_snapshot("/hello.txt", file); - let entry = imfs.get_contents("/hello.txt").unwrap(); + let entry = vfs.get_contents("/hello.txt").unwrap(); assert_eq!(entry, b"hello, world!"); } #[test] fn from_snapshot_dir() { - let mut imfs = Imfs::new(NoopFetcher); - let dir = ImfsSnapshot::dir(hashmap! { - "a.txt" => ImfsSnapshot::file("contents of a.txt"), - "b.lua" => ImfsSnapshot::file("contents of b.lua"), + let mut vfs = Vfs::new(NoopFetcher); + let dir = VfsSnapshot::dir(hashmap! { + "a.txt" => VfsSnapshot::file("contents of a.txt"), + "b.lua" => VfsSnapshot::file("contents of b.lua"), }); - imfs.debug_load_snapshot("/dir", dir); + vfs.debug_load_snapshot("/dir", dir); - let children = imfs.get_children("/dir").unwrap(); + let children = vfs.get_children("/dir").unwrap(); let mut has_a = false; let mut has_b = false; @@ -452,10 +449,10 @@ mod test { assert!(has_a, "/dir/a.txt was missing"); assert!(has_b, "/dir/b.lua was missing"); - let a = imfs.get_contents("/dir/a.txt").unwrap(); + let a = vfs.get_contents("/dir/a.txt").unwrap(); assert_eq!(a, b"contents of a.txt"); - let b = imfs.get_contents("/dir/b.lua").unwrap(); + let b = vfs.get_contents("/dir/b.lua").unwrap(); assert_eq!(b, b"contents of b.lua"); } @@ -470,7 +467,7 @@ mod test { inner: Rc>, } - impl ImfsFetcher for MockFetcher { + impl VfsFetcher for MockFetcher { fn file_type(&mut self, path: &Path) -> io::Result { if path == Path::new("/dir/a.txt") { return Ok(FileType::File); @@ -509,7 +506,7 @@ mod test { fn unwatch(&mut self, _path: &Path) {} - fn receiver(&self) -> Receiver { + fn receiver(&self) -> Receiver { crossbeam_channel::never() } } @@ -518,13 +515,13 @@ mod test { a_contents: "Initial contents", })); - let mut imfs = Imfs::new(MockFetcher { + let mut vfs = Vfs::new(MockFetcher { inner: mock_state.clone(), }); - let a = imfs.get("/dir/a.txt").expect("mock file did not exist"); + let a = vfs.get("/dir/a.txt").expect("mock file did not exist"); - let contents = a.contents(&mut imfs).expect("mock file contents error"); + let contents = a.contents(&mut vfs).expect("mock file contents error"); assert_eq!(contents, b"Initial contents"); @@ -533,36 +530,36 @@ mod test { mock_state.a_contents = "Changed contents"; } - imfs.raise_file_changed("/dir/a.txt") + vfs.raise_file_changed("/dir/a.txt") .expect("error processing file change"); - let contents = a.contents(&mut imfs).expect("mock file contents error"); + let contents = a.contents(&mut vfs).expect("mock file contents error"); assert_eq!(contents, b"Changed contents"); } #[test] fn removed_event_existing() { - let mut imfs = Imfs::new(NoopFetcher); + let mut vfs = Vfs::new(NoopFetcher); - let file = ImfsSnapshot::file("hello, world!"); - imfs.debug_load_snapshot("/hello.txt", file); + let file = VfsSnapshot::file("hello, world!"); + vfs.debug_load_snapshot("/hello.txt", file); - let hello = imfs.get("/hello.txt").expect("couldn't get hello.txt"); + let hello = vfs.get("/hello.txt").expect("couldn't get hello.txt"); let contents = hello - .contents(&mut imfs) + .contents(&mut vfs) .expect("couldn't get hello.txt contents"); assert_eq!(contents, b"hello, world!"); - imfs.raise_file_removed("/hello.txt") + vfs.raise_file_removed("/hello.txt") .expect("error processing file removal"); - match imfs.get("hello.txt") { + match vfs.get("hello.txt") { Err(ref err) if err.kind() == FsErrorKind::NotFound => {} Ok(_) => { - panic!("hello.txt was not removed from Imfs"); + panic!("hello.txt was not removed from Vfs"); } Err(err) => { panic!("Unexpected error: {:?}", err); diff --git a/src/web/api.rs b/src/web/api.rs index 1ba95725..676ddfdb 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -9,8 +9,8 @@ use hyper::{service::Service, Body, Method, Request, StatusCode}; use rbx_dom_weak::RbxId; use crate::{ - imfs::ImfsFetcher, serve_session::ServeSession, + vfs::VfsFetcher, web::{ interface::{ ErrorResponse, Instance, InstanceMetadata as WebInstanceMetadata, InstanceUpdate, @@ -25,7 +25,7 @@ pub struct ApiService { serve_session: Arc>, } -impl Service for ApiService { +impl Service for ApiService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; @@ -49,7 +49,7 @@ impl Service for ApiService { } } -impl ApiService { +impl ApiService { pub fn new(serve_session: Arc>) -> Self { ApiService { serve_session } } diff --git a/src/web/mod.rs b/src/web/mod.rs index 319083fa..d6548ef7 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -13,7 +13,7 @@ use futures::{ use hyper::{service::Service, Body, Request, Response, Server}; use log::trace; -use crate::{imfs::ImfsFetcher, serve_session::ServeSession}; +use crate::{serve_session::ServeSession, vfs::VfsFetcher}; use self::{api::ApiService, ui::UiService}; @@ -22,7 +22,7 @@ pub struct RootService { ui: UiService, } -impl Service for RootService { +impl Service for RootService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; @@ -39,7 +39,7 @@ impl Service for RootService { } } -impl RootService { +impl RootService { pub fn new(serve_session: Arc>) -> Self { RootService { api: ApiService::new(Arc::clone(&serve_session)), @@ -52,7 +52,7 @@ pub struct LiveServer { serve_session: Arc>, } -impl LiveServer { +impl LiveServer { pub fn new(serve_session: Arc>) -> Self { LiveServer { serve_session } } diff --git a/src/web/ui.rs b/src/web/ui.rs index 04d01638..a4224948 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -9,9 +9,9 @@ use rbx_dom_weak::{RbxId, RbxValue}; use ritz::{html, Fragment, HtmlContent, HtmlSelfClosingTag}; use crate::{ - imfs::{Imfs, ImfsDebug, ImfsFetcher}, serve_session::ServeSession, snapshot::RojoTree, + vfs::{Vfs, VfsDebug, VfsFetcher}, web::{ assets, interface::{ErrorResponse, SERVER_VERSION}, @@ -23,7 +23,7 @@ pub struct UiService { serve_session: Arc>, } -impl Service for UiService { +impl Service for UiService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; @@ -35,7 +35,7 @@ impl Service for UiService { (&Method::GET, "/logo.png") => self.handle_logo(), (&Method::GET, "/icon.png") => self.handle_icon(), (&Method::GET, "/show-instances") => self.handle_show_instances(), - (&Method::GET, "/show-imfs") => self.handle_show_imfs(), + (&Method::GET, "/show-vfs") => self.handle_show_vfs(), (_method, path) => { return json( ErrorResponse::not_found(format!("Route not found: {}", path)), @@ -48,7 +48,7 @@ impl Service for UiService { } } -impl UiService { +impl UiService { pub fn new(serve_session: Arc>) -> Self { UiService { serve_session } } @@ -71,7 +71,7 @@ impl UiService { let page = self.normal_page(html! {
    { Self::button("Rojo Documentation", "https://rojo.space/docs") } - { Self::button("View in-memory filesystem state", "/show-imfs") } + { Self::button("View in-memory filesystem state", "/show-vfs") } { Self::button("View instance tree state", "/show-instances") }
    }); @@ -96,16 +96,16 @@ impl UiService { .unwrap() } - fn handle_show_imfs(&self) -> Response { - let imfs = self.serve_session.imfs(); + fn handle_show_vfs(&self) -> Response { + let vfs = self.serve_session.vfs(); - let orphans: Vec<_> = imfs + let orphans: Vec<_> = vfs .debug_orphans() .into_iter() - .map(|path| Self::render_imfs_path(&imfs, path, true)) + .map(|path| Self::render_vfs_path(&vfs, path, true)) .collect(); - let watched_list: Vec<_> = imfs + let watched_list: Vec<_> = vfs .debug_watched_paths() .into_iter() .map(|path| { @@ -135,25 +135,25 @@ impl UiService { .unwrap() } - fn render_imfs_path(imfs: &Imfs, path: &Path, is_root: bool) -> HtmlContent<'static> { - let is_file = imfs.debug_is_file(path); + fn render_vfs_path(vfs: &Vfs, path: &Path, is_root: bool) -> HtmlContent<'static> { + let is_file = vfs.debug_is_file(path); let (note, children) = if is_file { (HtmlContent::None, Vec::new()) } else { - let (is_exhaustive, mut children) = imfs.debug_children(path).unwrap(); + let (is_exhaustive, mut children) = vfs.debug_children(path).unwrap(); // Sort files above directories, then sort how Path does after that. children.sort_unstable_by(|a, b| { - let a_is_file = imfs.debug_is_file(a); - let b_is_file = imfs.debug_is_file(b); + let a_is_file = vfs.debug_is_file(a); + let b_is_file = vfs.debug_is_file(b); b_is_file.cmp(&a_is_file).then_with(|| a.cmp(b)) }); let children: Vec<_> = children .into_iter() - .map(|child| Self::render_imfs_path(imfs, child, false)) + .map(|child| Self::render_vfs_path(vfs, child, false)) .collect(); let note = if is_exhaustive { @@ -178,12 +178,12 @@ impl UiService { } html! { -
    +
    - { name } - { note } + { name } + { note }
    -
    +
    { Fragment::new(children) }
    From 1967f738a8643a3b1977feea0057aa1ba7c246dc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 12 Oct 2019 14:17:52 -0700 Subject: [PATCH 0823/1504] Make all file contents be Arc> instead of &[u8] --- src/snapshot_middleware/csv.rs | 4 ++-- src/snapshot_middleware/json_model.rs | 2 +- src/snapshot_middleware/lua.rs | 4 ++-- src/snapshot_middleware/project.rs | 2 +- src/snapshot_middleware/rbxlx.rs | 2 +- src/snapshot_middleware/rbxm.rs | 2 +- src/snapshot_middleware/rbxmx.rs | 2 +- src/snapshot_middleware/txt.rs | 4 ++-- src/vfs/vfs.rs | 30 ++++++++++++++------------- 9 files changed, 27 insertions(+), 25 deletions(-) diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index ca2abbc4..08c2b755 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -37,7 +37,7 @@ impl SnapshotMiddleware for SnapshotCsv { .path() .with_file_name(format!("{}.meta.json", instance_name)); - let table_contents = convert_localization_csv(entry.contents(vfs)?); + let table_contents = convert_localization_csv(&entry.contents(vfs)?); let mut snapshot = InstanceSnapshot { snapshot_id: None, @@ -58,7 +58,7 @@ impl SnapshotMiddleware for SnapshotCsv { if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { let meta_contents = meta_entry.contents(vfs)?; - let mut metadata = AdjacentMetadata::from_slice(meta_contents); + let mut metadata = AdjacentMetadata::from_slice(&meta_contents); metadata.apply_all(&mut snapshot); } diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index bab2c0c7..3ccde84c 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -33,7 +33,7 @@ impl SnapshotMiddleware for SnapshotJsonModel { }; let instance: JsonModel = - serde_json::from_slice(entry.contents(vfs)?).expect("TODO: Handle serde_json errors"); + serde_json::from_slice(&entry.contents(vfs)?).expect("TODO: Handle serde_json errors"); if let Some(json_name) = &instance.name { if json_name != &instance_name { diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index c058895e..8f3266d5 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -71,7 +71,7 @@ fn snapshot_lua_file( }; let contents = entry.contents(vfs)?; - let contents_str = str::from_utf8(contents) + let contents_str = str::from_utf8(&contents) // TODO: Turn into error type .expect("File content was not valid UTF-8") .to_string(); @@ -103,7 +103,7 @@ fn snapshot_lua_file( if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { let meta_contents = meta_entry.contents(vfs)?; - let mut metadata = AdjacentMetadata::from_slice(meta_contents); + let mut metadata = AdjacentMetadata::from_slice(&meta_contents); metadata.apply_all(&mut snapshot); } diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 211ca611..a3050ff0 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -43,7 +43,7 @@ impl SnapshotMiddleware for SnapshotProject { return Ok(None); } - let project = Project::load_from_slice(entry.contents(vfs)?, entry.path()) + let project = Project::load_from_slice(&entry.contents(vfs)?, entry.path()) .map_err(|err| SnapshotError::malformed_project(err, entry.path()))?; // Snapshotting a project should always return an instance, so this diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index c758dd34..631afe22 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -31,7 +31,7 @@ impl SnapshotMiddleware for SnapshotRbxlx { let options = rbx_xml::DecodeOptions::new() .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); - let temp_tree = rbx_xml::from_reader(entry.contents(vfs)?, options) + let temp_tree = rbx_xml::from_reader(entry.contents(vfs)?.as_slice(), options) .expect("TODO: Handle rbx_xml errors"); let root_id = temp_tree.get_root_id(); diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 03bbc28d..8af33296 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -37,7 +37,7 @@ impl SnapshotMiddleware for SnapshotRbxm { }); let root_id = temp_tree.get_root_id(); - rbx_binary::decode(&mut temp_tree, root_id, entry.contents(vfs)?) + rbx_binary::decode(&mut temp_tree, root_id, entry.contents(vfs)?.as_slice()) .expect("TODO: Handle rbx_binary errors"); let root_instance = temp_tree.get_instance(root_id).unwrap(); diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 8c3b142f..bd54160d 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -31,7 +31,7 @@ impl SnapshotMiddleware for SnapshotRbxmx { let options = rbx_xml::DecodeOptions::new() .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); - let temp_tree = rbx_xml::from_reader(entry.contents(vfs)?, options) + let temp_tree = rbx_xml::from_reader(entry.contents(vfs)?.as_slice(), options) .expect("TODO: Handle rbx_xml errors"); let root_instance = temp_tree.get_instance(temp_tree.get_root_id()).unwrap(); diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 6d34d3d1..0b79eaac 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -34,7 +34,7 @@ impl SnapshotMiddleware for SnapshotTxt { }; let contents = entry.contents(vfs)?; - let contents_str = str::from_utf8(contents) + let contents_str = str::from_utf8(&contents) .map_err(|err| SnapshotError::file_contents_bad_unicode(err, entry.path()))? .to_string(); @@ -63,7 +63,7 @@ impl SnapshotMiddleware for SnapshotTxt { if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { let meta_contents = meta_entry.contents(vfs)?; - let mut metadata = AdjacentMetadata::from_slice(meta_contents); + let mut metadata = AdjacentMetadata::from_slice(&meta_contents); metadata.apply_all(&mut snapshot); } diff --git a/src/vfs/vfs.rs b/src/vfs/vfs.rs index 355ce592..16131720 100644 --- a/src/vfs/vfs.rs +++ b/src/vfs/vfs.rs @@ -1,6 +1,7 @@ use std::{ io, path::{Path, PathBuf}, + sync::Arc, }; use crossbeam_channel::Receiver; @@ -143,7 +144,7 @@ impl Vfs { }) } - pub fn get_contents(&mut self, path: impl AsRef) -> FsResult<&[u8]> { + pub fn get_contents(&mut self, path: impl AsRef) -> FsResult>> { let path = path.as_ref(); self.read_if_not_exists(path)?; @@ -154,11 +155,12 @@ impl Vfs { file.contents = Some( self.fetcher .read_contents(path) + .map(Arc::new) .map_err(|err| FsError::new(err, path.to_path_buf()))?, ); } - Ok(file.contents.as_ref().unwrap()) + Ok(file.contents.clone().unwrap()) } VfsItem::Directory(_) => Err(FsError::new( io::Error::new(io::ErrorKind::Other, "Can't read a directory"), @@ -275,7 +277,7 @@ impl VfsDebug for Vfs { path.to_path_buf(), VfsItem::File(VfsFile { path: path.to_path_buf(), - contents: Some(file.contents), + contents: Some(Arc::new(file.contents)), }), ); } @@ -343,7 +345,7 @@ impl VfsEntry { &self.path } - pub fn contents<'vfs>(&self, vfs: &'vfs mut Vfs) -> FsResult<&'vfs [u8]> { + pub fn contents<'vfs>(&self, vfs: &'vfs mut Vfs) -> FsResult>> { vfs.get_contents(&self.path) } @@ -391,7 +393,7 @@ impl VfsItem { pub struct VfsFile { pub(super) path: PathBuf, - pub(super) contents: Option>, + pub(super) contents: Option>>, } pub struct VfsDirectory { @@ -417,8 +419,8 @@ mod test { vfs.debug_load_snapshot("/hello.txt", file); - let entry = vfs.get_contents("/hello.txt").unwrap(); - assert_eq!(entry, b"hello, world!"); + let contents = vfs.get_contents("/hello.txt").unwrap(); + assert_eq!(contents.as_slice(), b"hello, world!"); } #[test] @@ -449,11 +451,11 @@ mod test { assert!(has_a, "/dir/a.txt was missing"); assert!(has_b, "/dir/b.lua was missing"); - let a = vfs.get_contents("/dir/a.txt").unwrap(); - assert_eq!(a, b"contents of a.txt"); + let a_contents = vfs.get_contents("/dir/a.txt").unwrap(); + assert_eq!(a_contents.as_slice(), b"contents of a.txt"); - let b = vfs.get_contents("/dir/b.lua").unwrap(); - assert_eq!(b, b"contents of b.lua"); + let b_contents = vfs.get_contents("/dir/b.lua").unwrap(); + assert_eq!(b_contents.as_slice(), b"contents of b.lua"); } #[test] @@ -523,7 +525,7 @@ mod test { let contents = a.contents(&mut vfs).expect("mock file contents error"); - assert_eq!(contents, b"Initial contents"); + assert_eq!(contents.as_slice(), b"Initial contents"); { let mut mock_state = mock_state.borrow_mut(); @@ -535,7 +537,7 @@ mod test { let contents = a.contents(&mut vfs).expect("mock file contents error"); - assert_eq!(contents, b"Changed contents"); + assert_eq!(contents.as_slice(), b"Changed contents"); } #[test] @@ -551,7 +553,7 @@ mod test { .contents(&mut vfs) .expect("couldn't get hello.txt contents"); - assert_eq!(contents, b"hello, world!"); + assert_eq!(contents.as_slice(), b"hello, world!"); vfs.raise_file_removed("/hello.txt") .expect("error processing file removal"); From dec9ec32dfaa33c73e1a2494e7193abeacc865ee Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 12 Oct 2019 15:24:57 -0700 Subject: [PATCH 0824/1504] Add small place benchmark --- Cargo.lock | 104 + Cargo.toml | 5 + benches/build.rs | 36 + .../default.project.json | 38 + .../models/large-1.rbxmx | 40382 ++++++++++++++++ .../models/small-1.rbxmx | 326 + .../models/small-2.rbxmx | 326 + .../models/small-3.rbxmx | 326 + .../src/client/init.client.lua | 1 + .../src/client/module-1.lua | 1 + .../src/client/module-2.lua | 1 + .../src/client/module-3.lua | 1 + .../src/client/module-4.lua | 1 + .../src/common/init.lua | 1 + .../src/common/module-1.lua | 1 + .../src/common/module-2.lua | 1 + .../src/common/module-3.lua | 1 + .../src/common/module-4.lua | 1 + .../src/server/init.server.lua | 1 + .../src/server/module-1.lua | 1 + .../src/server/module-2.lua | 1 + .../src/server/module-3.lua | 1 + .../src/server/module-4.lua | 1 + 23 files changed, 41558 insertions(+) create mode 100644 benches/build.rs create mode 100644 test-projects/benchmark_project_0.6.0/default.project.json create mode 100644 test-projects/benchmark_project_0.6.0/models/large-1.rbxmx create mode 100644 test-projects/benchmark_project_0.6.0/models/small-1.rbxmx create mode 100644 test-projects/benchmark_project_0.6.0/models/small-2.rbxmx create mode 100644 test-projects/benchmark_project_0.6.0/models/small-3.rbxmx create mode 100644 test-projects/benchmark_project_0.6.0/src/client/init.client.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/client/module-1.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/client/module-2.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/client/module-3.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/client/module-4.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/common/init.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/common/module-1.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/common/module-2.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/common/module-3.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/common/module-4.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/server/init.server.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/server/module-1.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/server/module-2.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/server/module-3.lua create mode 100644 test-projects/benchmark_project_0.6.0/src/server/module-4.lua diff --git a/Cargo.lock b/Cargo.lock index 3d072dec..7251f716 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -152,6 +152,11 @@ dependencies = [ "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "cast" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "cc" version = "1.0.45" @@ -258,6 +263,39 @@ dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "criterion" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "criterion-plot" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-channel" version = "0.3.9" @@ -694,6 +732,14 @@ dependencies = [ "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "itertools" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "itoa" version = "0.4.4" @@ -1293,6 +1339,15 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_os" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand_pcg" version = "0.1.2" @@ -1310,6 +1365,36 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "rand_xoshiro" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rbx_binary" version = "0.4.1" @@ -1474,6 +1559,7 @@ name = "rojo" version = "0.6.0-dev" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1821,6 +1907,15 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "tinytemplate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "tokio" version = "0.1.22" @@ -2227,6 +2322,7 @@ dependencies = [ "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" +"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" "checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" @@ -2238,6 +2334,8 @@ dependencies = [ "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +"checksum criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "938703e165481c8d612ea3479ac8342e5615185db37765162e762ec3523e2fc6" +"checksum criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eccdc6ce8bbe352ca89025bee672aa6d24f4eb8c53e3a8b5d1bc58011da072a2" "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" "checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" "checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" @@ -2287,6 +2385,7 @@ dependencies = [ "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" "checksum insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23f83ab4ee86f38b292f0420c27fd412690a4baa9ea0ad4e3fa624bf34379b76" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" +"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f52a11f73b88fab829a0e4d9e13ea5982c7ac457c72eb3541d82a4afdfce4ff" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" @@ -2356,8 +2455,12 @@ dependencies = [ "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" +"checksum rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a788ae3edb696cfcba1c19bfd388cc4b8c21f8a408432b199c072825084da58a" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" +"checksum rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e18c91676f670f6f0312764c759405f13afb98d5d73819840cf72a518487bff" +"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" +"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" "checksum rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81428c521a07a3feac9c31180a886e467eecf81b769987f70d51d567a09c321d" "checksum rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b7c983d7bfcf0811a164e33e99e2da456f38babb33c75e365b17aa1ee5fd2d" "checksum rbx_reflection 3.2.404 (registry+https://github.com/rust-lang/crates.io-index)" = "7712c0a5ae6524ec5f51c29bc031f21e5ba35b38ffc6277f2ee9439febaec88c" @@ -2405,6 +2508,7 @@ dependencies = [ "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" "checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +"checksum tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4574b75faccaacddb9b284faecdf0b544b80b6b294f3d062d325c5726a209c20" "checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" diff --git a/Cargo.toml b/Cargo.toml index 3408bb39..d13280d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,6 +42,10 @@ path = "src/lib.rs" name = "rojo" path = "src/bin.rs" +[[bench]] +name = "build" +harness = false + [dependencies] clap = "2.27" crossbeam-channel = "0.3.9" @@ -81,6 +85,7 @@ serde_yaml = "0.8.9" tempfile = "3.0" tokio = "0.1.22" walkdir = "2.1" +criterion = "0.3" [dev-dependencies.insta] version = "0.11.0" diff --git a/benches/build.rs b/benches/build.rs new file mode 100644 index 00000000..76ad8f97 --- /dev/null +++ b/benches/build.rs @@ -0,0 +1,36 @@ +use std::path::{Path, PathBuf}; + +use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; +use tempfile::{tempdir, TempDir}; + +use librojo::commands::{build, BuildOptions}; + +fn place_setup>(input_path: P) -> (TempDir, BuildOptions) { + let dir = tempdir().unwrap(); + let input = input_path.as_ref().to_path_buf(); + let output_file = dir.path().join("output.rbxlx"); + + let options = BuildOptions { + fuzzy_project_path: input, + output_file, + output_kind: None, + }; + + (dir, options) +} + +pub fn benchmark_small_place_0_6_0(c: &mut Criterion) { + let mut group = c.benchmark_group("Small place"); + group.sample_size(10); + group.bench_function("build", |b| { + b.iter_batched( + || place_setup("test-projects/benchmark_project_0.6.0"), + |(_dir, options)| build(&options).unwrap(), + BatchSize::SmallInput, + ) + }); + group.finish(); +} + +criterion_group!(benches, benchmark_small_place_0_6_0); +criterion_main!(benches); diff --git a/test-projects/benchmark_project_0.6.0/default.project.json b/test-projects/benchmark_project_0.6.0/default.project.json new file mode 100644 index 00000000..24fd0841 --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/default.project.json @@ -0,0 +1,38 @@ +{ + "name": "benchmark_project_0.6.0", + "tree": { + "$className": "DataModel", + + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + + "Common": { + "$path": "src/common" + }, + + "Models": { + "$path": "models" + } + }, + + "ServerScriptService": { + "$className": "ServerScriptService", + + "Server": { + "$path": "src/server" + } + }, + + "StarterPlayer": { + "$className": "StarterPlayer", + + "StarterPlayerScripts": { + "$className": "StarterPlayerScripts", + + "Client": { + "$path": "src/client" + } + } + } + } +} \ No newline at end of file diff --git a/test-projects/benchmark_project_0.6.0/models/large-1.rbxmx b/test-projects/benchmark_project_0.6.0/models/large-1.rbxmx new file mode 100644 index 00000000..04168fc4 --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/models/large-1.rbxmx @@ -0,0 +1,40382 @@ + + true + null + nil + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + LargeModel + null + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 1.5 + 3.00001383 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 0.5 + 3.00001383 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 2.5 + 3.00001383 + 69.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -0.5 + 3.00001383 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -0.5 + 5.00000811 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 0.5 + 5.00000811 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 1.5 + 5.00000811 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 2.5 + 5.00000811 + 69.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -0.5 + 7.00001764 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 1.5 + 7.00001764 + 69.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 0.5 + 7.00001764 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 2.5 + 7.00001764 + 68.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -0.5 + 1.00001383 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 1.5 + 1.00001383 + 69.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 0.5 + 1.00001383 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 2.5 + 1.00001383 + 68.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 3.0000248 + 22.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 17.5 + 3.0000248 + 23.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 3.0000248 + 21.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 16.5 + 3.0000248 + 24.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 16.5 + 5.00001907 + 24.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 17.5 + 5.00001907 + 23.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 5.00001907 + 22.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 5.00001907 + 21.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 16.5 + 7.0000248 + 23.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 7.0000248 + 21.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 17.5 + 7.0000248 + 22.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 7.0000248 + 20.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 16.5 + 1.0000248 + 23.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 1.0000248 + 21.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 17.5 + 1.0000248 + 22.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 1.0000248 + 20.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 3.00001717 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 3.00001717 + 73.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 3.00001717 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 3.00001717 + 74.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 5.00001144 + 74.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 5.00001144 + 73.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 5.00001144 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 5.00001144 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 7.00002575 + 73.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 7.00002575 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 7.00002575 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 7.00002575 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 1.00001717 + 73.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 1.00001717 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 1.00001717 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 1.00001717 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 3.00002623 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 3.00002623 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 3.00002623 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 3.00002623 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 5.0000205 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 5.0000205 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 5.0000205 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 5.0000205 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 7.00003481 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 7.00003481 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 7.00003481 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 7.00003481 + 35.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 1.00002623 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 1.00002623 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 1.00002623 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 1.00002623 + 35.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 20.5 + 3.00002623 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 3.00002623 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 21.5 + 3.00002623 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 3.00002623 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 5.0000205 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 5.0000205 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 20.5 + 5.0000205 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 21.5 + 5.0000205 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 7.00003481 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 20.5 + 7.00003481 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 7.00003481 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 21.5 + 7.00003481 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 1.00002623 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 20.5 + 1.00002623 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 1.00002623 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 21.5 + 1.00002623 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 3.00001621 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 3.00001621 + 41.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 3.00001621 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 3.00001621 + 42.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 5.00001049 + 42.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 5.00001049 + 41.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 5.00001049 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 5.00001049 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 7.0000248 + 41.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 7.0000248 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 7.0000248 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 7.0000248 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 1.00001621 + 41.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 1.00001621 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 1.00001621 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 1.00001621 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 7.5 + 3.00001001 + 45.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 3.00001001 + 46.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 3.00001001 + 44.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 3.00001001 + 47.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 5.00000811 + 47.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 5.00000811 + 46.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 7.5 + 5.00000811 + 45.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 5.00000811 + 44.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 7.00001717 + 46.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 7.5 + 7.00001717 + 44.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 7.00001717 + 45.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 7.00001717 + 43.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 1.00001097 + 46.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 7.5 + 1.00001097 + 44.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 1.00001097 + 45.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 1.00001097 + 43.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 3.00001717 + 52.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 3.00001717 + 53.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 3.00001717 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 3.00001717 + 54.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 5.00001144 + 54.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 5.00001144 + 53.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 5.00001144 + 52.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 5.00001144 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 7.00001717 + 53.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 7.00001717 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 7.00001717 + 52.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 7.00001717 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 1.00001717 + 53.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 1.00001717 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 1.00001717 + 52.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 1.00001717 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 27.5 + 3.00002623 + 49.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 26.5 + 3.00002623 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 28.5 + 3.00002623 + 48.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 25.5 + 3.00002623 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 25.5 + 5.0000205 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 26.5 + 5.0000205 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 27.5 + 5.0000205 + 49.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 28.5 + 5.0000205 + 48.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 25.5 + 7.00003481 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 27.5 + 7.00003481 + 48.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 26.5 + 7.00003481 + 49.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 28.5 + 7.00003481 + 47.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 25.5 + 1.00002623 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 27.5 + 1.00002623 + 48.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 26.5 + 1.00002623 + 49.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 28.5 + 1.00002623 + 47.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 3.00001717 + 56.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 3.00001717 + 57.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 3.00001717 + 55.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 3.00001717 + 58.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 5.00001144 + 58.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 5.00001144 + 57.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 5.00001144 + 56.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 5.00001144 + 55.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 7.00002575 + 57.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 7.00002575 + 55.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 7.00002575 + 56.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 7.00002575 + 54.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 1.00001717 + 57.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 1.00001717 + 55.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 1.00001717 + 56.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 1.00001717 + 54.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 3.00001335 + 29.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 3.00001335 + 30.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 3.00001335 + 28.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 3.00001335 + 31.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 5.00000763 + 31.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 5.00000763 + 30.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 5.00000763 + 29.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 5.00000763 + 28.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 7.00001717 + 30.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 7.00001717 + 28.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 7.00001717 + 29.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 7.00001717 + 27.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 1.00001335 + 30.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 1.00001335 + 28.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 1.00001335 + 29.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 1.00001335 + 27.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 1.5 + 11.0000439 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 0.5 + 11.0000439 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 2.5 + 11.0000439 + 69.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -0.5 + 11.0000439 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -0.5 + 13.0000324 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 0.5 + 13.0000324 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 1.5 + 13.0000324 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 2.5 + 13.0000324 + 69.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -0.5 + 15.0000458 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 1.5 + 15.0000458 + 69.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 0.5 + 15.0000458 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 2.5 + 15.0000458 + 68.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -0.5 + 9.00004387 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 1.5 + 9.00004387 + 69.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 0.5 + 9.00004387 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 2.5 + 9.00004387 + 68.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 11.0000525 + 22.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 17.5 + 11.0000525 + 23.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 11.0000525 + 21.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 16.5 + 11.0000525 + 24.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 16.5 + 13.0000458 + 24.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 17.5 + 13.0000458 + 23.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 13.0000458 + 22.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 13.0000458 + 21.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 16.5 + 15.0000525 + 23.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 15.0000525 + 21.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 17.5 + 15.0000525 + 22.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 15.0000525 + 20.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 16.5 + 9.00005245 + 23.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 9.00005245 + 21.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 17.5 + 9.00005245 + 22.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 9.00005245 + 20.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 11.0000458 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 11.0000458 + 73.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 11.0000458 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 11.0000458 + 74.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 13.0000401 + 74.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 13.0000401 + 73.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 13.0000401 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 13.0000401 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 15.0000582 + 73.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 15.0000582 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 15.0000582 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 15.0000582 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 9.00004578 + 73.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 9.00004578 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 9.00004578 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 9.00004578 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 11.0000582 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 11.0000582 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 11.0000582 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 11.0000582 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 13.0000458 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 13.0000458 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 13.0000458 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 13.0000458 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 15.0000639 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 15.0000639 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 15.0000639 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 15.0000639 + 35.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 9.00005817 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 9.00005817 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 9.00005817 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 9.00005817 + 35.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 20.5 + 11.0000582 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 11.0000582 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 21.5 + 11.0000582 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 11.0000582 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 13.0000458 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 13.0000458 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 20.5 + 13.0000458 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 21.5 + 13.0000458 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 15.0000639 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 20.5 + 15.0000639 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 15.0000639 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 21.5 + 15.0000639 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 9.00005817 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 20.5 + 9.00005817 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 9.00005817 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 21.5 + 9.00005817 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 11.0000458 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 11.0000458 + 41.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 11.0000458 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 11.0000458 + 42.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 13.0000401 + 42.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 13.0000401 + 41.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 13.0000401 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 13.0000401 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 15.0000525 + 41.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 15.0000525 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 15.0000525 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 15.0000525 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 9.00004578 + 41.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 9.00004578 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 9.00004578 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 9.00004578 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 7.5 + 11.0000401 + 45.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 11.0000401 + 46.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 11.0000401 + 44.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 11.0000401 + 47.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 13.0000324 + 47.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 13.0000324 + 46.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 7.5 + 13.0000324 + 45.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 13.0000324 + 44.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 15.0000458 + 46.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 7.5 + 15.0000458 + 44.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 15.0000458 + 45.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 15.0000458 + 43.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 9.00004005 + 46.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 7.5 + 9.00004005 + 44.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 9.00004005 + 45.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 9.00004005 + 43.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 11.0000458 + 52.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 11.0000458 + 53.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 11.0000458 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 11.0000458 + 54.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 13.0000401 + 54.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 13.0000401 + 53.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 13.0000401 + 52.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 13.0000401 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 15.0000458 + 53.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 15.0000458 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 15.0000458 + 52.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 15.0000458 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 9.00004578 + 53.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 9.00004578 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 9.00004578 + 52.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 9.00004578 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 27.5 + 11.0000582 + 49.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 26.5 + 11.0000582 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 28.5 + 11.0000582 + 48.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 25.5 + 11.0000582 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 25.5 + 13.0000458 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 26.5 + 13.0000458 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 27.5 + 13.0000458 + 49.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 28.5 + 13.0000458 + 48.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 25.5 + 15.0000639 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 27.5 + 15.0000639 + 48.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 26.5 + 15.0000639 + 49.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 28.5 + 15.0000639 + 47.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 25.5 + 9.00005817 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 27.5 + 9.00005817 + 48.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 26.5 + 9.00005817 + 49.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 28.5 + 9.00005817 + 47.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 11.0000458 + 56.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 11.0000458 + 57.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 11.0000458 + 55.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 11.0000458 + 58.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 13.0000401 + 58.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 13.0000401 + 57.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 13.0000401 + 56.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 13.0000401 + 55.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 15.0000582 + 57.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 15.0000582 + 55.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 15.0000582 + 56.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 15.0000582 + 54.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 9.00004578 + 57.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 9.00004578 + 55.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 9.00004578 + 56.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 9.00004578 + 54.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 11.0000439 + 29.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 11.0000439 + 30.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 11.0000439 + 28.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 11.0000439 + 31.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 13.0000324 + 31.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 13.0000324 + 30.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 13.0000324 + 29.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 13.0000324 + 28.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 15.0000458 + 30.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 15.0000458 + 28.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 15.0000458 + 29.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 15.0000458 + 27.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 9.00004387 + 30.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 9.00004387 + 28.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 9.00004387 + 29.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 9.00004387 + 27.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 1.5 + 19.0000877 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 0.5 + 19.0000877 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 2.5 + 19.0000877 + 69.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -0.5 + 19.0000877 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -0.5 + 21.000082 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 0.5 + 21.000082 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 1.5 + 21.000082 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 2.5 + 21.000082 + 69.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -0.5 + 23.0000916 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 1.5 + 23.0000916 + 69.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 0.5 + 23.0000916 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 2.5 + 23.0000916 + 68.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -0.5 + 17.0000877 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 1.5 + 17.0000877 + 69.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 0.5 + 17.0000877 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 2.5 + 17.0000877 + 68.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 19.0000992 + 22.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 17.5 + 19.0000992 + 23.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 19.0000992 + 21.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 16.5 + 19.0000992 + 24.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 16.5 + 21.0000935 + 24.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 17.5 + 21.0000935 + 23.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 21.0000935 + 22.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 21.0000935 + 21.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 16.5 + 23.0000992 + 23.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 23.0000992 + 21.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 17.5 + 23.0000992 + 22.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 23.0000992 + 20.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 16.5 + 17.0000992 + 23.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 17.0000992 + 21.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 17.5 + 17.0000992 + 22.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 17.0000992 + 20.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 19.0000916 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 19.0000916 + 73.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 19.0000916 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 19.0000916 + 74.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 21.0000858 + 74.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 21.0000858 + 73.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 21.0000858 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 21.0000858 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 23.0000992 + 73.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 23.0000992 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 23.0000992 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 23.0000992 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 17.0000916 + 73.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 17.0000916 + 71.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 17.0000916 + 72.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 17.0000916 + 70.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 19.0000992 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 19.0000992 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 19.0000992 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 19.0000992 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 21.0000935 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 21.0000935 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 21.0000935 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 21.0000935 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 23.0001087 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 23.0001087 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 23.0001087 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 23.0001087 + 35.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 17.0000992 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 17.0000992 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 17.0000992 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 17.0000992 + 35.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 20.5 + 19.0000992 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 19.0000992 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 21.5 + 19.0000992 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 19.0000992 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 21.0000935 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 21.0000935 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 20.5 + 21.0000935 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 21.5 + 21.0000935 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 23.0001087 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 20.5 + 23.0001087 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 23.0001087 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 21.5 + 23.0001087 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 18.5 + 17.0000992 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 20.5 + 17.0000992 + 37.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 19.5 + 17.0000992 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 21.5 + 17.0000992 + 36.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 19.0000877 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 19.0000877 + 41.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 19.0000877 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 19.0000877 + 42.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 21.0000858 + 42.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 21.0000858 + 41.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 21.0000858 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 21.0000858 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 23.0000992 + 41.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 23.0000992 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 23.0000992 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 23.0000992 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 17.0000877 + 41.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 17.0000877 + 39.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 17.0000877 + 40.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 17.0000877 + 38.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 7.5 + 19.0000858 + 45.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 19.0000858 + 46.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 19.0000858 + 44.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 19.0000858 + 47.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 21.000082 + 47.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 21.000082 + 46.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 7.5 + 21.000082 + 45.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 21.000082 + 44.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 23.0000916 + 46.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 7.5 + 23.0000916 + 44.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 23.0000916 + 45.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 23.0000916 + 43.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 17.0000858 + 46.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 7.5 + 17.0000858 + 44.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 17.0000858 + 45.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 17.0000858 + 43.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 19.0000916 + 52.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 19.0000916 + 53.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 19.0000916 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 19.0000916 + 54.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 21.0000858 + 54.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 21.0000858 + 53.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 21.0000858 + 52.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 21.0000858 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 23.0000916 + 53.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 23.0000916 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 23.0000916 + 52.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 23.0000916 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 8.5 + 17.0000916 + 53.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 10.5 + 17.0000916 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 9.5 + 17.0000916 + 52.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 17.0000916 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 27.5 + 19.0000992 + 49.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 26.5 + 19.0000992 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 28.5 + 19.0000992 + 48.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 25.5 + 19.0000992 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 25.5 + 21.0000935 + 51.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 26.5 + 21.0000935 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 27.5 + 21.0000935 + 49.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 28.5 + 21.0000935 + 48.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 25.5 + 23.0001087 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 27.5 + 23.0001087 + 48.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 26.5 + 23.0001087 + 49.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 28.5 + 23.0001087 + 47.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 25.5 + 17.0000992 + 50.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 27.5 + 17.0000992 + 48.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 26.5 + 17.0000992 + 49.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 28.5 + 17.0000992 + 47.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 19.0000916 + 56.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 19.0000916 + 57.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 19.0000916 + 55.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 19.0000916 + 58.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 21.0000858 + 58.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 21.0000858 + 57.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 21.0000858 + 56.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 21.0000858 + 55.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 23.0000992 + 57.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 23.0000992 + 55.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 23.0000992 + 56.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 23.0000992 + 54.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 3.5 + 17.0000916 + 57.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 5.5 + 17.0000916 + 55.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 4.5 + 17.0000916 + 56.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 6.5 + 17.0000916 + 54.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + Model + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 19.0000877 + 29.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 19.0000877 + 30.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 19.0000877 + 28.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 19.0000877 + 31.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 21.000082 + 31.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 21.000082 + 30.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 21.000082 + 29.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 21.000082 + 28.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 23.0000916 + 30.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 23.0000916 + 28.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 23.0000916 + 29.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 23.0000916 + 27.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 11.5 + 17.0000877 + 30.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 13.5 + 17.0000877 + 28.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 12.5 + 17.0000877 + 29.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + 14.5 + 17.0000877 + 27.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + + + \ No newline at end of file diff --git a/test-projects/benchmark_project_0.6.0/models/small-1.rbxmx b/test-projects/benchmark_project_0.6.0/models/small-1.rbxmx new file mode 100644 index 00000000..5db0315c --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/models/small-1.rbxmx @@ -0,0 +1,326 @@ + + true + null + nil + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + SmallModel + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -25.5 + 1 + 5.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -23.5 + 1 + 3.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -24.5 + 1 + 4.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -22.5 + 1 + 2.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + \ No newline at end of file diff --git a/test-projects/benchmark_project_0.6.0/models/small-2.rbxmx b/test-projects/benchmark_project_0.6.0/models/small-2.rbxmx new file mode 100644 index 00000000..5db0315c --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/models/small-2.rbxmx @@ -0,0 +1,326 @@ + + true + null + nil + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + SmallModel + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -25.5 + 1 + 5.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -23.5 + 1 + 3.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -24.5 + 1 + 4.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -22.5 + 1 + 2.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + \ No newline at end of file diff --git a/test-projects/benchmark_project_0.6.0/models/small-3.rbxmx b/test-projects/benchmark_project_0.6.0/models/small-3.rbxmx new file mode 100644 index 00000000..5db0315c --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/models/small-3.rbxmx @@ -0,0 +1,326 @@ + + true + null + nil + + + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + SmallModel + null + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -25.5 + 1 + 5.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279430868 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 3 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -23.5 + 1 + 3.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294901760 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 7 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -24.5 + 1 + 4.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4279970357 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 5 + + + + + + false + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -22.5 + 1 + 2.5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + 0 + 4294967040 + + false + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + Part + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + 1 + + 1 + 2 + 9 + + + + + \ No newline at end of file diff --git a/test-projects/benchmark_project_0.6.0/src/client/init.client.lua b/test-projects/benchmark_project_0.6.0/src/client/init.client.lua new file mode 100644 index 00000000..dceca1ca --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/client/init.client.lua @@ -0,0 +1 @@ +print("hello from client") \ No newline at end of file diff --git a/test-projects/benchmark_project_0.6.0/src/client/module-1.lua b/test-projects/benchmark_project_0.6.0/src/client/module-1.lua new file mode 100644 index 00000000..a4325f62 --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/client/module-1.lua @@ -0,0 +1 @@ +return 1 diff --git a/test-projects/benchmark_project_0.6.0/src/client/module-2.lua b/test-projects/benchmark_project_0.6.0/src/client/module-2.lua new file mode 100644 index 00000000..3ee3fcaa --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/client/module-2.lua @@ -0,0 +1 @@ +return 2 diff --git a/test-projects/benchmark_project_0.6.0/src/client/module-3.lua b/test-projects/benchmark_project_0.6.0/src/client/module-3.lua new file mode 100644 index 00000000..32d0c308 --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/client/module-3.lua @@ -0,0 +1 @@ +return 3 diff --git a/test-projects/benchmark_project_0.6.0/src/client/module-4.lua b/test-projects/benchmark_project_0.6.0/src/client/module-4.lua new file mode 100644 index 00000000..857f0f66 --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/client/module-4.lua @@ -0,0 +1 @@ +return 4 diff --git a/test-projects/benchmark_project_0.6.0/src/common/init.lua b/test-projects/benchmark_project_0.6.0/src/common/init.lua new file mode 100644 index 00000000..02022208 --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/common/init.lua @@ -0,0 +1 @@ +print("hello from common") \ No newline at end of file diff --git a/test-projects/benchmark_project_0.6.0/src/common/module-1.lua b/test-projects/benchmark_project_0.6.0/src/common/module-1.lua new file mode 100644 index 00000000..a4325f62 --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/common/module-1.lua @@ -0,0 +1 @@ +return 1 diff --git a/test-projects/benchmark_project_0.6.0/src/common/module-2.lua b/test-projects/benchmark_project_0.6.0/src/common/module-2.lua new file mode 100644 index 00000000..3ee3fcaa --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/common/module-2.lua @@ -0,0 +1 @@ +return 2 diff --git a/test-projects/benchmark_project_0.6.0/src/common/module-3.lua b/test-projects/benchmark_project_0.6.0/src/common/module-3.lua new file mode 100644 index 00000000..32d0c308 --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/common/module-3.lua @@ -0,0 +1 @@ +return 3 diff --git a/test-projects/benchmark_project_0.6.0/src/common/module-4.lua b/test-projects/benchmark_project_0.6.0/src/common/module-4.lua new file mode 100644 index 00000000..857f0f66 --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/common/module-4.lua @@ -0,0 +1 @@ +return 4 diff --git a/test-projects/benchmark_project_0.6.0/src/server/init.server.lua b/test-projects/benchmark_project_0.6.0/src/server/init.server.lua new file mode 100644 index 00000000..02d6e915 --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/server/init.server.lua @@ -0,0 +1 @@ +print("hello from server") \ No newline at end of file diff --git a/test-projects/benchmark_project_0.6.0/src/server/module-1.lua b/test-projects/benchmark_project_0.6.0/src/server/module-1.lua new file mode 100644 index 00000000..a4325f62 --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/server/module-1.lua @@ -0,0 +1 @@ +return 1 diff --git a/test-projects/benchmark_project_0.6.0/src/server/module-2.lua b/test-projects/benchmark_project_0.6.0/src/server/module-2.lua new file mode 100644 index 00000000..3ee3fcaa --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/server/module-2.lua @@ -0,0 +1 @@ +return 2 diff --git a/test-projects/benchmark_project_0.6.0/src/server/module-3.lua b/test-projects/benchmark_project_0.6.0/src/server/module-3.lua new file mode 100644 index 00000000..32d0c308 --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/server/module-3.lua @@ -0,0 +1 @@ +return 3 diff --git a/test-projects/benchmark_project_0.6.0/src/server/module-4.lua b/test-projects/benchmark_project_0.6.0/src/server/module-4.lua new file mode 100644 index 00000000..857f0f66 --- /dev/null +++ b/test-projects/benchmark_project_0.6.0/src/server/module-4.lua @@ -0,0 +1 @@ +return 4 From 7077f0f1f382534bd6e2b49a3d3e3a114da4fc9f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 12 Oct 2019 23:27:12 -0700 Subject: [PATCH 0825/1504] Load user plugins on startup instead of lazily at snapshot time --- src/common_setup.rs | 3 +- src/snapshot_middleware/context.rs | 48 ++++++++++++++++++------- src/snapshot_middleware/user_plugins.rs | 48 +------------------------ 3 files changed, 37 insertions(+), 62 deletions(-) diff --git a/src/common_setup.rs b/src/common_setup.rs index d21a07d9..50734117 100644 --- a/src/common_setup.rs +++ b/src/common_setup.rs @@ -41,8 +41,7 @@ pub fn start( // If the project file defines no plugins, then there's no need to // initialize the snapshot plugin context. if !project.plugins.is_empty() { - snapshot_context.plugin_context = - Some(SnapshotPluginContext::new(project.plugins.clone())); + snapshot_context.plugin_context = Some(SnapshotPluginContext::new(&project.plugins)); } } diff --git a/src/snapshot_middleware/context.rs b/src/snapshot_middleware/context.rs index ba376085..b125b890 100644 --- a/src/snapshot_middleware/context.rs +++ b/src/snapshot_middleware/context.rs @@ -1,7 +1,9 @@ -use std::{fmt, ops::Deref, path::PathBuf}; +use std::{fmt, fs, ops::Deref, path::Path}; use rlua::{Lua, RegistryKey}; +use super::error::SnapshotError; + #[derive(Debug)] pub struct InstanceSnapshotContext { /// Holds all the state needed to run user plugins as part of the snapshot @@ -23,22 +25,42 @@ impl Default for InstanceSnapshotContext { pub struct SnapshotPluginContext { pub state: IgnoreDebug, - /// Paths to the user plugins files. These paths are generated by the root - /// project file, if there is one. - pub plugin_paths: Vec, - - /// Lazy-initialized registry keys pointing to the values returned by each - /// user plugin. When processing user plugins, these should be applied in - /// order. - pub plugin_functions: Option>, + /// Registry keys pointing to the values returned by each user plugin. When + /// processing user plugins, these should be applied in order. + pub plugin_functions: Vec, } impl SnapshotPluginContext { - pub fn new(plugin_paths: Vec) -> Self { + pub fn new>(plugin_paths: &[P]) -> Self { + let lua_state = Lua::new(); + + let plugin_functions = plugin_paths + .iter() + .map(|path| { + let path = path.as_ref(); + + let content = + fs::read_to_string(path).map_err(|err| SnapshotError::wrap(err, path))?; + + lua_state.context(|lua_context| { + // Plugins are currently expected to return a function that will + // be run when a snapshot needs to be generated. + let result = lua_context + .load(&content) + .set_name(&path.display().to_string())? + .call::<_, rlua::Function>(())?; + + let key = lua_context.create_registry_value(result)?; + + Ok(key) + }) + }) + .collect::, SnapshotError>>() + .expect("Plugin initialization error"); + Self { - state: IgnoreDebug(Lua::new()), - plugin_paths, - plugin_functions: None, + state: IgnoreDebug(lua_state), + plugin_functions, } } } diff --git a/src/snapshot_middleware/user_plugins.rs b/src/snapshot_middleware/user_plugins.rs index 6e4627ce..f39d9336 100644 --- a/src/snapshot_middleware/user_plugins.rs +++ b/src/snapshot_middleware/user_plugins.rs @@ -1,12 +1,7 @@ -use std::{fs, path::Path}; - -use rlua::{Lua, RegistryKey}; - use crate::vfs::{Vfs, VfsEntry, VfsFetcher}; use super::{ context::InstanceSnapshotContext, - error::SnapshotError, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, }; @@ -30,23 +25,9 @@ impl SnapshotMiddleware for SnapshotUserPlugins { None => return Ok(None), }; - // If the plugins listed for use haven't been loaded yet, read them into - // memory, run them, and keep the result they return as a registry key - // into our Lua state. - let keys = match &plugin_context.plugin_functions { - Some(keys) => keys, - None => { - plugin_context.plugin_functions = Some(initialize_plugins( - &plugin_context.state, - &plugin_context.plugin_paths, - )?); - plugin_context.plugin_functions.as_ref().unwrap() - } - }; - plugin_context.state.context(|lua_context| { lua_context.scope(|_scope| { - for _key in keys { + for _key in &plugin_context.plugin_functions { // TODO: Invoke plugin here and get result out. // The current plan for plugins here is to make them work @@ -85,30 +66,3 @@ impl SnapshotMiddleware for SnapshotUserPlugins { Ok(None) } } - -fn initialize_plugins>( - lua_state: &Lua, - plugin_paths: &[P], -) -> Result, SnapshotError> { - plugin_paths - .iter() - .map(|path| { - let path = path.as_ref(); - - let content = fs::read_to_string(path).map_err(|err| SnapshotError::wrap(err, path))?; - - lua_state.context(|lua_context| { - // Plugins are currently expected to return a function that will - // be run when a snapshot needs to be generated. - let result = lua_context - .load(&content) - .set_name(&path.display().to_string())? - .call::<_, rlua::Function>(())?; - - let key = lua_context.create_registry_value(result)?; - - Ok(key) - }) - }) - .collect::, _>>() -} From b9ebed14a525938df3e96307add1357f034111fe Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 12 Oct 2019 23:31:33 -0700 Subject: [PATCH 0826/1504] Add documentation for AdjacentMetadata --- src/snapshot_middleware/meta_file.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/snapshot_middleware/meta_file.rs b/src/snapshot_middleware/meta_file.rs index 9b06f0f1..9103dfc0 100644 --- a/src/snapshot_middleware/meta_file.rs +++ b/src/snapshot_middleware/meta_file.rs @@ -6,6 +6,10 @@ use serde::{Deserialize, Serialize}; use crate::snapshot::InstanceSnapshot; +/// Represents metadata in a sibling file with the same basename. +/// +/// As an example, hello.meta.json next to hello.lua would allow assigning +/// additional metadata to the instance resulting from hello.lua. #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AdjacentMetadata { @@ -47,4 +51,7 @@ impl AdjacentMetadata { self.apply_ignore_unknown_instances(snapshot); self.apply_properties(snapshot); } + + // TODO: Add method to allow selectively applying parts of metadata and + // throwing errors if invalid parts are specified. } From 1c6c1298d5aec14e6758a59b479292ee224cff3b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 12 Oct 2019 23:45:38 -0700 Subject: [PATCH 0827/1504] Add init.meta.json support, untested --- src/snapshot_middleware/dir.rs | 17 ++++++-- src/snapshot_middleware/lua.rs | 11 ++++- src/snapshot_middleware/meta_file.rs | 64 +++++++++++++++++++++++++++- 3 files changed, 86 insertions(+), 6 deletions(-) diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index b3c1a126..1a44d88a 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -4,12 +4,13 @@ use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ snapshot::{InstanceMetadata, InstanceSnapshot}, - vfs::{DirectorySnapshot, Vfs, VfsEntry, VfsFetcher, VfsSnapshot}, + vfs::{DirectorySnapshot, FsResultExt, Vfs, VfsEntry, VfsFetcher, VfsSnapshot}, }; use super::{ context::InstanceSnapshotContext, error::SnapshotError, + meta_file::DirectoryMetadata, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, snapshot_from_instance, snapshot_from_vfs, }; @@ -44,7 +45,9 @@ impl SnapshotMiddleware for SnapshotDir { .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))? .to_string(); - Ok(Some(InstanceSnapshot { + let meta_path = entry.path().join("init.meta.json"); + + let mut snapshot = InstanceSnapshot { snapshot_id: None, metadata: InstanceMetadata { instigating_source: Some(entry.path().to_path_buf().into()), @@ -55,7 +58,15 @@ impl SnapshotMiddleware for SnapshotDir { class_name: Cow::Borrowed("Folder"), properties: HashMap::new(), children: snapshot_children, - })) + }; + + if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { + let meta_contents = meta_entry.contents(vfs)?; + let mut metadata = DirectoryMetadata::from_slice(&meta_contents); + metadata.apply_all(&mut snapshot); + } + + Ok(Some(snapshot)) } fn from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult { diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 8f3266d5..bd6c54b2 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -126,10 +126,17 @@ fn snapshot_init( if let Some(init_entry) = vfs.get(init_path).with_not_found()? { if let Some(dir_snapshot) = SnapshotDir::from_vfs(context, vfs, folder_entry)? { if let Some(mut init_snapshot) = snapshot_lua_file(vfs, &init_entry)? { + if dir_snapshot.class_name != "Folder" { + panic!( + "init.lua, init.server.lua, and init.client.lua can \ + only be used if the instance produced by the parent \ + directory would be a Folder." + ); + } + init_snapshot.name = dir_snapshot.name; init_snapshot.children = dir_snapshot.children; - // TODO: Metadata - // TODO: Validate directory class name is "Folder" + // TODO: Apply metadata from folder return Ok(Some(init_snapshot)); } diff --git a/src/snapshot_middleware/meta_file.rs b/src/snapshot_middleware/meta_file.rs index 9103dfc0..db8e1b40 100644 --- a/src/snapshot_middleware/meta_file.rs +++ b/src/snapshot_middleware/meta_file.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::{borrow::Cow, collections::HashMap}; use rbx_dom_weak::UnresolvedRbxValue; use rbx_reflection::try_resolve_value; @@ -55,3 +55,65 @@ impl AdjacentMetadata { // TODO: Add method to allow selectively applying parts of metadata and // throwing errors if invalid parts are specified. } + +/// Represents metadata that affects the instance resulting from the containing +/// folder. +/// +/// This is always sourced from a file named init.meta.json. +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct DirectoryMetadata { + #[serde(skip_serializing_if = "Option::is_none")] + pub ignore_unknown_instances: Option, + + #[serde(default, skip_serializing_if = "HashMap::is_empty")] + pub properties: HashMap, + + #[serde(skip_serializing_if = "Option::is_none")] + pub class_name: Option, +} + +impl DirectoryMetadata { + pub fn from_slice(slice: &[u8]) -> Self { + serde_json::from_slice(slice) + // TODO: Turn into error type + .expect("init.meta.json file was malformed") + } + + pub fn apply_all(&mut self, snapshot: &mut InstanceSnapshot) { + self.apply_ignore_unknown_instances(snapshot); + self.apply_class_name(snapshot); + self.apply_properties(snapshot); + } + + fn apply_class_name(&mut self, snapshot: &mut InstanceSnapshot) { + if let Some(class_name) = self.class_name.take() { + if snapshot.class_name != "Folder" { + // TODO: Turn into error type + panic!("className in init.meta.json can only be specified if the affected directory would turn into a Folder instance."); + } + + snapshot.class_name = Cow::Owned(class_name); + } + } + + fn apply_ignore_unknown_instances(&mut self, snapshot: &mut InstanceSnapshot) { + if let Some(ignore) = self.ignore_unknown_instances.take() { + snapshot.metadata.ignore_unknown_instances = ignore; + } + } + + fn apply_properties(&mut self, snapshot: &mut InstanceSnapshot) { + let class_name = &snapshot.class_name; + + let source_properties = self.properties.drain().map(|(key, value)| { + try_resolve_value(class_name, &key, &value) + .map(|resolved| (key, resolved)) + .expect("TODO: Handle rbx_reflection errors") + }); + + for (key, value) in source_properties { + snapshot.properties.insert(key, value); + } + } +} From db23c3d35a51b621efc368a66ab37b54ce31ac20 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 12 Oct 2019 23:46:49 -0700 Subject: [PATCH 0828/1504] Mark init.meta.json as relevant path for directories --- src/snapshot_middleware/dir.rs | 2 +- src/snapshot_middleware/snapshots/test__empty_folder.snap | 1 + src/snapshot_middleware/snapshots/test__folder_in_folder.snap | 2 ++ src/snapshots/serve_session__change_script_meta_after.snap | 1 + src/snapshots/serve_session__change_script_meta_before.snap | 1 + src/snapshots/serve_session__just_folder.snap | 3 ++- src/snapshots/serve_session__project_with_folder.snap | 1 + src/snapshots/serve_session__script_with_meta.snap | 1 + 8 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 1a44d88a..9b54ef59 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -51,7 +51,7 @@ impl SnapshotMiddleware for SnapshotDir { snapshot_id: None, metadata: InstanceMetadata { instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf()], + relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], ..Default::default() }, name: Cow::Owned(instance_name), diff --git a/src/snapshot_middleware/snapshots/test__empty_folder.snap b/src/snapshot_middleware/snapshots/test__empty_folder.snap index c08cb8c1..8001ff69 100644 --- a/src/snapshot_middleware/snapshots/test__empty_folder.snap +++ b/src/snapshot_middleware/snapshots/test__empty_folder.snap @@ -9,6 +9,7 @@ metadata: Path: /foo relevant_paths: - /foo + - /foo/init.meta.json name: foo class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap index dafc369a..01c6b288 100644 --- a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap +++ b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap @@ -9,6 +9,7 @@ metadata: Path: /foo relevant_paths: - /foo + - /foo/init.meta.json name: foo class_name: Folder properties: {} @@ -20,6 +21,7 @@ children: Path: /foo/Child relevant_paths: - /foo/Child + - /foo/Child/init.meta.json name: Child class_name: Folder properties: {} diff --git a/src/snapshots/serve_session__change_script_meta_after.snap b/src/snapshots/serve_session__change_script_meta_after.snap index dacd98cc..386be8bf 100644 --- a/src/snapshots/serve_session__change_script_meta_after.snap +++ b/src/snapshots/serve_session__change_script_meta_after.snap @@ -12,6 +12,7 @@ metadata: Path: /root relevant_paths: - /root + - /root/init.meta.json children: - id: id-2 name: test diff --git a/src/snapshots/serve_session__change_script_meta_before.snap b/src/snapshots/serve_session__change_script_meta_before.snap index dcf06e97..9acef5ee 100644 --- a/src/snapshots/serve_session__change_script_meta_before.snap +++ b/src/snapshots/serve_session__change_script_meta_before.snap @@ -12,6 +12,7 @@ metadata: Path: /root relevant_paths: - /root + - /root/init.meta.json children: - id: id-2 name: test diff --git a/src/snapshots/serve_session__just_folder.snap b/src/snapshots/serve_session__just_folder.snap index 8a3a74e1..584509b8 100644 --- a/src/snapshots/serve_session__just_folder.snap +++ b/src/snapshots/serve_session__just_folder.snap @@ -1,6 +1,6 @@ --- source: src/serve_session.rs -expression: tree_value +expression: "view_tree(&session.tree(), &mut rm)" --- id: id-1 name: foo @@ -12,4 +12,5 @@ metadata: Path: /foo relevant_paths: - /foo + - /foo/init.meta.json children: [] diff --git a/src/snapshots/serve_session__project_with_folder.snap b/src/snapshots/serve_session__project_with_folder.snap index ea3a0f33..ae1914d6 100644 --- a/src/snapshots/serve_session__project_with_folder.snap +++ b/src/snapshots/serve_session__project_with_folder.snap @@ -12,6 +12,7 @@ metadata: Path: /foo/default.project.json relevant_paths: - /foo/src + - /foo/src/init.meta.json - /foo/default.project.json children: - id: id-2 diff --git a/src/snapshots/serve_session__script_with_meta.snap b/src/snapshots/serve_session__script_with_meta.snap index 81247ba5..016006b9 100644 --- a/src/snapshots/serve_session__script_with_meta.snap +++ b/src/snapshots/serve_session__script_with_meta.snap @@ -12,6 +12,7 @@ metadata: Path: /root relevant_paths: - /root + - /root/init.meta.json children: - id: id-2 name: test From 1b35c98be5f5d5749a37603486781e0f22f21ad9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 12 Oct 2019 23:54:39 -0700 Subject: [PATCH 0829/1504] Add build tests for init.meta.json --- .../build_test__init_meta_class_name.snap | 11 +++++++++++ .../build_test__init_meta_properties.snap | 12 ++++++++++++ .../init_meta_class_name/default.project.json | 6 ++++++ .../should-be-a-model/init.meta.json | 3 +++ .../init_meta_properties/Lighting/init.meta.json | 6 ++++++ .../init_meta_properties/default.project.json | 6 ++++++ rojo-test/src/build_test.rs | 2 ++ 7 files changed, 46 insertions(+) create mode 100644 rojo-test/build-test-snapshots/build_test__init_meta_class_name.snap create mode 100644 rojo-test/build-test-snapshots/build_test__init_meta_properties.snap create mode 100644 rojo-test/build-tests/init_meta_class_name/default.project.json create mode 100644 rojo-test/build-tests/init_meta_class_name/should-be-a-model/init.meta.json create mode 100644 rojo-test/build-tests/init_meta_properties/Lighting/init.meta.json create mode 100644 rojo-test/build-tests/init_meta_properties/default.project.json diff --git a/rojo-test/build-test-snapshots/build_test__init_meta_class_name.snap b/rojo-test/build-test-snapshots/build_test__init_meta_class_name.snap new file mode 100644 index 00000000..8a5f8a06 --- /dev/null +++ b/rojo-test/build-test-snapshots/build_test__init_meta_class_name.snap @@ -0,0 +1,11 @@ +--- +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + init_meta_class_name + + + diff --git a/rojo-test/build-test-snapshots/build_test__init_meta_properties.snap b/rojo-test/build-test-snapshots/build_test__init_meta_properties.snap new file mode 100644 index 00000000..5d24b949 --- /dev/null +++ b/rojo-test/build-test-snapshots/build_test__init_meta_properties.snap @@ -0,0 +1,12 @@ +--- +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + init_meta_properties + 1 + + + diff --git a/rojo-test/build-tests/init_meta_class_name/default.project.json b/rojo-test/build-tests/init_meta_class_name/default.project.json new file mode 100644 index 00000000..0cf270c2 --- /dev/null +++ b/rojo-test/build-tests/init_meta_class_name/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "init_meta_class_name", + "tree": { + "$path": "should-be-a-model" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/init_meta_class_name/should-be-a-model/init.meta.json b/rojo-test/build-tests/init_meta_class_name/should-be-a-model/init.meta.json new file mode 100644 index 00000000..5b52f5e4 --- /dev/null +++ b/rojo-test/build-tests/init_meta_class_name/should-be-a-model/init.meta.json @@ -0,0 +1,3 @@ +{ + "className": "Model" +} \ No newline at end of file diff --git a/rojo-test/build-tests/init_meta_properties/Lighting/init.meta.json b/rojo-test/build-tests/init_meta_properties/Lighting/init.meta.json new file mode 100644 index 00000000..ec43ab19 --- /dev/null +++ b/rojo-test/build-tests/init_meta_properties/Lighting/init.meta.json @@ -0,0 +1,6 @@ +{ + "className": "Lighting", + "properties": { + "Technology": "Voxel" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/init_meta_properties/default.project.json b/rojo-test/build-tests/init_meta_properties/default.project.json new file mode 100644 index 00000000..84e602f0 --- /dev/null +++ b/rojo-test/build-tests/init_meta_properties/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "init_meta_properties", + "tree": { + "$path": "Lighting" + } +} \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index aad1b597..fcdf9ead 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -28,6 +28,8 @@ gen_build_tests! { csv_in_folder, deep_nesting, gitkeep, + init_meta_class_name, + init_meta_properties, init_with_children, json_model_in_folder, json_model_legacy_name, From ccf98d7283cca85de124701b86ba7983d665f035 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Oct 2019 11:38:16 -0700 Subject: [PATCH 0830/1504] Move and tidy up small place benchmark --- benches/build.rs | 39 +++++++++++-------- .../default.project.json | 0 .../models/large-1.rbxmx | 0 .../models/small-1.rbxmx | 0 .../models/small-2.rbxmx | 0 .../models/small-3.rbxmx | 0 .../src/client/init.client.lua | 0 .../src/client/module-1.lua | 0 .../src/client/module-2.lua | 0 .../src/client/module-3.lua | 0 .../src/client/module-4.lua | 0 .../src/common/init.lua | 0 .../src/common/module-1.lua | 0 .../src/common/module-2.lua | 0 .../src/common/module-3.lua | 0 .../src/common/module-4.lua | 0 .../src/server/init.server.lua | 0 .../src/server/module-1.lua | 0 .../src/server/module-2.lua | 0 .../src/server/module-3.lua | 0 .../src/server/module-4.lua | 0 21 files changed, 23 insertions(+), 16 deletions(-) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/default.project.json (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/models/large-1.rbxmx (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/models/small-1.rbxmx (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/models/small-2.rbxmx (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/models/small-3.rbxmx (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/client/init.client.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/client/module-1.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/client/module-2.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/client/module-3.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/client/module-4.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/common/init.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/common/module-1.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/common/module-2.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/common/module-3.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/common/module-4.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/server/init.server.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/server/module-1.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/server/module-2.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/server/module-3.lua (100%) rename test-projects/{benchmark_project_0.6.0 => benchmark_small_place}/src/server/module-4.lua (100%) diff --git a/benches/build.rs b/benches/build.rs index 76ad8f97..5a560153 100644 --- a/benches/build.rs +++ b/benches/build.rs @@ -5,6 +5,29 @@ use tempfile::{tempdir, TempDir}; use librojo::commands::{build, BuildOptions}; +pub fn benchmark_small_place(c: &mut Criterion) { + bench_build_place(c, "Small Place", "test-projects/benchmark_small_place") +} + +criterion_group!(benches, benchmark_small_place); +criterion_main!(benches); + +fn bench_build_place(c: &mut Criterion, name: &str, path: &str) { + let mut group = c.benchmark_group(name); + + // 'rojo build' generally takes a fair bit of time to execute. + group.sample_size(10); + group.bench_function("build", |b| { + b.iter_batched( + || place_setup(path), + |(_dir, options)| build(&options).unwrap(), + BatchSize::SmallInput, + ) + }); + + group.finish(); +} + fn place_setup>(input_path: P) -> (TempDir, BuildOptions) { let dir = tempdir().unwrap(); let input = input_path.as_ref().to_path_buf(); @@ -18,19 +41,3 @@ fn place_setup>(input_path: P) -> (TempDir, BuildOptions) { (dir, options) } - -pub fn benchmark_small_place_0_6_0(c: &mut Criterion) { - let mut group = c.benchmark_group("Small place"); - group.sample_size(10); - group.bench_function("build", |b| { - b.iter_batched( - || place_setup("test-projects/benchmark_project_0.6.0"), - |(_dir, options)| build(&options).unwrap(), - BatchSize::SmallInput, - ) - }); - group.finish(); -} - -criterion_group!(benches, benchmark_small_place_0_6_0); -criterion_main!(benches); diff --git a/test-projects/benchmark_project_0.6.0/default.project.json b/test-projects/benchmark_small_place/default.project.json similarity index 100% rename from test-projects/benchmark_project_0.6.0/default.project.json rename to test-projects/benchmark_small_place/default.project.json diff --git a/test-projects/benchmark_project_0.6.0/models/large-1.rbxmx b/test-projects/benchmark_small_place/models/large-1.rbxmx similarity index 100% rename from test-projects/benchmark_project_0.6.0/models/large-1.rbxmx rename to test-projects/benchmark_small_place/models/large-1.rbxmx diff --git a/test-projects/benchmark_project_0.6.0/models/small-1.rbxmx b/test-projects/benchmark_small_place/models/small-1.rbxmx similarity index 100% rename from test-projects/benchmark_project_0.6.0/models/small-1.rbxmx rename to test-projects/benchmark_small_place/models/small-1.rbxmx diff --git a/test-projects/benchmark_project_0.6.0/models/small-2.rbxmx b/test-projects/benchmark_small_place/models/small-2.rbxmx similarity index 100% rename from test-projects/benchmark_project_0.6.0/models/small-2.rbxmx rename to test-projects/benchmark_small_place/models/small-2.rbxmx diff --git a/test-projects/benchmark_project_0.6.0/models/small-3.rbxmx b/test-projects/benchmark_small_place/models/small-3.rbxmx similarity index 100% rename from test-projects/benchmark_project_0.6.0/models/small-3.rbxmx rename to test-projects/benchmark_small_place/models/small-3.rbxmx diff --git a/test-projects/benchmark_project_0.6.0/src/client/init.client.lua b/test-projects/benchmark_small_place/src/client/init.client.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/client/init.client.lua rename to test-projects/benchmark_small_place/src/client/init.client.lua diff --git a/test-projects/benchmark_project_0.6.0/src/client/module-1.lua b/test-projects/benchmark_small_place/src/client/module-1.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/client/module-1.lua rename to test-projects/benchmark_small_place/src/client/module-1.lua diff --git a/test-projects/benchmark_project_0.6.0/src/client/module-2.lua b/test-projects/benchmark_small_place/src/client/module-2.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/client/module-2.lua rename to test-projects/benchmark_small_place/src/client/module-2.lua diff --git a/test-projects/benchmark_project_0.6.0/src/client/module-3.lua b/test-projects/benchmark_small_place/src/client/module-3.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/client/module-3.lua rename to test-projects/benchmark_small_place/src/client/module-3.lua diff --git a/test-projects/benchmark_project_0.6.0/src/client/module-4.lua b/test-projects/benchmark_small_place/src/client/module-4.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/client/module-4.lua rename to test-projects/benchmark_small_place/src/client/module-4.lua diff --git a/test-projects/benchmark_project_0.6.0/src/common/init.lua b/test-projects/benchmark_small_place/src/common/init.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/common/init.lua rename to test-projects/benchmark_small_place/src/common/init.lua diff --git a/test-projects/benchmark_project_0.6.0/src/common/module-1.lua b/test-projects/benchmark_small_place/src/common/module-1.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/common/module-1.lua rename to test-projects/benchmark_small_place/src/common/module-1.lua diff --git a/test-projects/benchmark_project_0.6.0/src/common/module-2.lua b/test-projects/benchmark_small_place/src/common/module-2.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/common/module-2.lua rename to test-projects/benchmark_small_place/src/common/module-2.lua diff --git a/test-projects/benchmark_project_0.6.0/src/common/module-3.lua b/test-projects/benchmark_small_place/src/common/module-3.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/common/module-3.lua rename to test-projects/benchmark_small_place/src/common/module-3.lua diff --git a/test-projects/benchmark_project_0.6.0/src/common/module-4.lua b/test-projects/benchmark_small_place/src/common/module-4.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/common/module-4.lua rename to test-projects/benchmark_small_place/src/common/module-4.lua diff --git a/test-projects/benchmark_project_0.6.0/src/server/init.server.lua b/test-projects/benchmark_small_place/src/server/init.server.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/server/init.server.lua rename to test-projects/benchmark_small_place/src/server/init.server.lua diff --git a/test-projects/benchmark_project_0.6.0/src/server/module-1.lua b/test-projects/benchmark_small_place/src/server/module-1.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/server/module-1.lua rename to test-projects/benchmark_small_place/src/server/module-1.lua diff --git a/test-projects/benchmark_project_0.6.0/src/server/module-2.lua b/test-projects/benchmark_small_place/src/server/module-2.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/server/module-2.lua rename to test-projects/benchmark_small_place/src/server/module-2.lua diff --git a/test-projects/benchmark_project_0.6.0/src/server/module-3.lua b/test-projects/benchmark_small_place/src/server/module-3.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/server/module-3.lua rename to test-projects/benchmark_small_place/src/server/module-3.lua diff --git a/test-projects/benchmark_project_0.6.0/src/server/module-4.lua b/test-projects/benchmark_small_place/src/server/module-4.lua similarity index 100% rename from test-projects/benchmark_project_0.6.0/src/server/module-4.lua rename to test-projects/benchmark_small_place/src/server/module-4.lua From 9aafccc946dac587ae086750b43671bc1a8f2fdb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Oct 2019 13:46:02 -0700 Subject: [PATCH 0831/1504] Update CHANGELOG --- CHANGELOG.md | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a204a71c..a7c3e77b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,24 @@ # Rojo Changelog ## Unreleased Changes (will be 0.6.0) + +### General * Added support for nested project files. ([#95](https://github.com/rojo-rbx/rojo/issues/95)) * Added project file hot-reloading. ([#10](https://github.com/rojo-rbx/rojo/issues/10)]) -* Added support for building and serving sources that aren't projects. -* Added `--verbose`/`-v` flag, which can be specified multiple times to increase verbosity. -* Added support for automatically finding Roblox Studio's auth cookie for `rojo upload` on Windows. -* Improved diagnostics for when the Rojo plugin cannot create an instance. -* Improved feedback from `rojo serve`. * Fixed Rojo dropping Ref properties ([#142](https://github.com/rojo-rbx/rojo/issues/142)) * This means that properties like `PrimaryPart` now work! +* Improved live sync protocol to reduce round-trips and improve syncing consistency. + +### Command Line +* Added `--verbose`/`-v` flag, which can be specified multiple times to increase verbosity. +* Added support for automatically finding Roblox Studio's auth cookie for `rojo upload` on Windows. +* Added support for building, serving and uploading sources that aren't Rojo projects. +* Improved feedback from `rojo serve`. + +### Roblox Studio Plugin +* Added "connecting" state to improve experience when live syncing. +* Added "error" state to show errors in a place that isn't the output panel. +* Improved diagnostics for when the Rojo plugin cannot create an instance. ## [0.5.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.1) (October 4, 2019) * Fixed an issue where Rojo would drop changes if they happened too quickly ([#252](https://github.com/rojo-rbx/rojo/issues/252)) From b0dcf515f0d435b7976745d2cf5607490806848d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Oct 2019 14:05:25 -0700 Subject: [PATCH 0832/1504] Refactor plugins, port message dropping bugfix from 0.5.1 --- plugin/src/ApiContext.lua | 8 ++-- plugin/src/ServeSession.lua | 89 +++++++++++++++++++------------------ 2 files changed, 51 insertions(+), 46 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 44259c1c..49757dac 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -92,6 +92,10 @@ function ApiContext:disconnect() self.__connected = false end +function ApiContext:setMessageCursor(index) + self.__messageCursor = index +end + function ApiContext:connect() local url = ("%s/api/rojo"):format(self.__baseUrl) @@ -125,8 +129,6 @@ function ApiContext:read(ids) assert(validateApiRead(body)) - self.__messageCursor = body.messageCursor - return body end) end @@ -155,7 +157,7 @@ function ApiContext:retrieveMessages() assert(validateApiSubscribe(body)) - self.__messageCursor = body.messageCursor + self:setMessageCursor(body.messageCursor) return body.messages end) diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 6033dde4..1e1d95b3 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -12,7 +12,6 @@ local Status = strict("Session.Status", { local function DEBUG_printPatch(patch) local HttpService = game:GetService("HttpService") - for removed in ipairs(patch.removed) do print("Remove:", removed) end @@ -64,48 +63,9 @@ function ServeSession:start() local rootInstanceId = serverInfo.rootInstanceId - return self.__apiContext:read({ rootInstanceId }) - :andThen(function(readResponseBody) - local hydratePatch = self.__reconciler:hydrate( - readResponseBody.instances, - rootInstanceId, - game - ) - - -- TODO: Prompt user to notify them of this patch, since - -- it's effectively a conflict between the Rojo server and - -- the client. - - self.__reconciler:applyPatch(hydratePatch) - - -- TODO: Applying a patch may eventually only apply part of - -- the patch and start a content negotiation process with - -- the Rojo server. We should handle that! - - local function mainLoop() - return self.__apiContext:retrieveMessages() - :andThen(function(messages) - for _, message in ipairs(messages) do - -- TODO: Update server to return patches in - -- correct format so that we don't have to - -- transform them for the reconciler. - - local asPatch = { - removed = message.removedInstances, - updated = message.updatedInstances, - added = message.addedInstances, - } - - self.__reconciler:applyPatch(asPatch) - end - - if self.__status ~= Status.Disconnected then - return mainLoop() - end - end) - end - - return mainLoop() + return self:__initialSync(rootInstanceId) + :andThen(function() + return self:__mainSyncLoop() end) end) :catch(function(err) @@ -117,6 +77,49 @@ function ServeSession:stop() self:__stopInternal() end +function ServeSession:__initialSync(rootInstanceId) + return self.__apiContext:read({ rootInstanceId }) + :andThen(function(readResponseBody) + -- Tell the API Context that we're up-to-date with the version of + -- the tree defined in this response. + self.__apiContext:setMessageCursor(readResponseBody.messageCursor) + + -- Calculate the initial patch to apply to the DataModel to catch us + -- up to what Rojo thinks the place should look like. + local hydratePatch = self.__reconciler:hydrate( + readResponseBody.instances, + rootInstanceId, + game + ) + + -- TODO: Prompt user to notify them of this patch, since it's + -- effectively a conflict between the Rojo server and the client. + + self.__reconciler:applyPatch(hydratePatch) + end) +end + +function ServeSession:__mainSyncLoop() + return self.__apiContext:retrieveMessages() + :andThen(function(messages) + for _, message in ipairs(messages) do + -- TODO: Update server to return patches in correct format so + -- that we don't have to transform them for the reconciler. + local asPatch = { + removed = message.removedInstances, + updated = message.updatedInstances, + added = message.addedInstances, + } + + self.__reconciler:applyPatch(asPatch) + end + + if self.__status ~= Status.Disconnected then + return self:__mainSyncLoop() + end + end) +end + function ServeSession:__stopInternal(err) self:__setStatus(Status.Disconnected, err) self.__apiContext:disconnect() From 5123d21290fae1d96d5dfb214a16b55967c65add Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Oct 2019 16:46:15 -0700 Subject: [PATCH 0833/1504] Rename Vfs::inner to Vfs::data, use Self more --- src/vfs/vfs.rs | 52 +++++++++++++++++++++++++------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/src/vfs/vfs.rs b/src/vfs/vfs.rs index 16131720..509e1e2e 100644 --- a/src/vfs/vfs.rs +++ b/src/vfs/vfs.rs @@ -28,7 +28,7 @@ use super::{ pub struct Vfs { /// A hierarchical map from paths to items that have been read or partially /// read into memory by the Vfs. - inner: PathMap, + data: PathMap, /// This Vfs's fetcher, which is used for all actual interactions with the /// filesystem. It's referred to by the type parameter `F` all over, and is @@ -37,9 +37,9 @@ pub struct Vfs { } impl Vfs { - pub fn new(fetcher: F) -> Vfs { - Vfs { - inner: PathMap::new(), + pub fn new(fetcher: F) -> Self { + Self { + data: PathMap::new(), fetcher, } } @@ -77,7 +77,7 @@ impl Vfs { .file_type(path) .map_err(|err| FsError::new(err, path.to_path_buf()))?; - match self.inner.get_mut(path) { + match self.data.get_mut(path) { Some(existing_item) => { match (existing_item, &new_type) { (VfsItem::File(existing_file), FileType::File) => { @@ -90,16 +90,16 @@ impl Vfs { self.fetcher.watch(path); } (VfsItem::File(_), FileType::Directory) => { - self.inner.remove(path); - self.inner.insert( + self.data.remove(path); + self.data.insert( path.to_path_buf(), VfsItem::new_from_type(FileType::Directory, path), ); self.fetcher.watch(path); } (VfsItem::Directory(_), FileType::File) => { - self.inner.remove(path); - self.inner.insert( + self.data.remove(path); + self.data.insert( path.to_path_buf(), VfsItem::new_from_type(FileType::File, path), ); @@ -108,7 +108,7 @@ impl Vfs { } } None => { - self.inner + self.data .insert(path.to_path_buf(), VfsItem::new_from_type(new_type, path)); } } @@ -123,7 +123,7 @@ impl Vfs { return Ok(()); } - self.inner.remove(path); + self.data.remove(path); self.fetcher.unwatch(path); Ok(()) } @@ -131,7 +131,7 @@ impl Vfs { pub fn get(&mut self, path: impl AsRef) -> FsResult { self.read_if_not_exists(path.as_ref())?; - let item = self.inner.get(path.as_ref()).unwrap(); + let item = self.data.get(path.as_ref()).unwrap(); let is_file = match item { VfsItem::File(_) => true, @@ -149,7 +149,7 @@ impl Vfs { self.read_if_not_exists(path)?; - match self.inner.get_mut(path).unwrap() { + match self.data.get_mut(path).unwrap() { VfsItem::File(file) => { if file.contents.is_none() { file.contents = Some( @@ -174,14 +174,14 @@ impl Vfs { self.read_if_not_exists(path)?; - match self.inner.get_mut(path).unwrap() { + match self.data.get_mut(path).unwrap() { VfsItem::Directory(dir) => { self.fetcher.watch(path); let enumerated = dir.children_enumerated; if enumerated { - self.inner + self.data .children(path) .unwrap() // TODO: Handle None here, which means the PathMap entry did not exist. .into_iter() @@ -219,12 +219,12 @@ impl Vfs { /// resident, we need to read it, and if its contents were known before, we /// need to update them. fn would_be_resident(&self, path: &Path) -> bool { - if self.inner.contains_key(path) { + if self.data.contains_key(path) { return true; } if let Some(parent) = path.parent() { - if let Some(VfsItem::Directory(dir)) = self.inner.get(parent) { + if let Some(VfsItem::Directory(dir)) = self.data.get(parent) { return !dir.children_enumerated; } } @@ -238,7 +238,7 @@ impl Vfs { /// be read. Depending on the `VfsFetcher` implementation that the `Vfs` /// is using, this call may read exactly only the given path and no more. fn read_if_not_exists(&mut self, path: &Path) -> FsResult<()> { - if !self.inner.contains_key(path) { + if !self.data.contains_key(path) { let kind = self .fetcher .file_type(path) @@ -248,7 +248,7 @@ impl Vfs { self.fetcher.watch(path); } - self.inner + self.data .insert(path.to_path_buf(), VfsItem::new_from_type(kind, path)); } @@ -273,7 +273,7 @@ impl VfsDebug for Vfs { match snapshot { VfsSnapshot::File(file) => { - self.inner.insert( + self.data.insert( path.to_path_buf(), VfsItem::File(VfsFile { path: path.to_path_buf(), @@ -282,7 +282,7 @@ impl VfsDebug for Vfs { ); } VfsSnapshot::Directory(directory) => { - self.inner.insert( + self.data.insert( path.to_path_buf(), VfsItem::Directory(VfsDirectory { path: path.to_path_buf(), @@ -298,30 +298,30 @@ impl VfsDebug for Vfs { } fn debug_is_file(&self, path: &Path) -> bool { - match self.inner.get(path) { + match self.data.get(path) { Some(VfsItem::File(_)) => true, _ => false, } } fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]> { - match self.inner.get(path) { + match self.data.get(path) { Some(VfsItem::File(file)) => file.contents.as_ref().map(|vec| vec.as_slice()), _ => None, } } fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)> { - match self.inner.get(path) { + match self.data.get(path) { Some(VfsItem::Directory(dir)) => { - Some((dir.children_enumerated, self.inner.children(path).unwrap())) + Some((dir.children_enumerated, self.data.children(path).unwrap())) } _ => None, } } fn debug_orphans(&self) -> Vec<&Path> { - self.inner.orphans().collect() + self.data.orphans().collect() } fn debug_watched_paths(&self) -> Vec<&Path> { From 82678235ab6a417b6f239984a66d210582a8578b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 16 Oct 2019 15:45:23 -0700 Subject: [PATCH 0834/1504] VFS Improvements (#259) This PR refactors all of the methods on `Vfs` from accepting `&mut self` to accepting `&self` and keeping data wrapped in a mutex. This builds on previous changes to make reference count file contents and cleans up the last places where we're returning borrowed data out of the VFS interface. Once this change lands, there are two possible directions we can go that I see: * Conservative: Refactor all remaining `&mut Vfs` handles to `&Vfs` * Interesting: Embrace ref counting by changing `Vfs` methods to accept `self: Arc`, which makes the `VfsEntry` API no longer need an explicit `Vfs` argument for its operations. * Change VfsFetcher to be immutable with internal locking * Refactor Vfs::would_be_resident * Refactor Vfs::read_if_not_exists * Refactor Vfs::raise_file_removed * Refactor Vfs::raise_file_changed * Add Vfs::get_internal as bits of Vfs::get * Switch Vfs to use internal locking * Migrate all Vfs methods from &mut self to &self * Make VfsEntry access Vfs immutably * Remove outer VFS locking (#260) * Refactor all snapshot middleware to accept &Vfs instead of &mut Vfs * Remove outer VFS Mutex across the board --- src/change_processor.rs | 14 +- src/common_setup.rs | 2 +- src/serve_session.rs | 16 +- src/snapshot_middleware/csv.rs | 2 +- src/snapshot_middleware/dir.rs | 2 +- src/snapshot_middleware/json_model.rs | 2 +- src/snapshot_middleware/lua.rs | 6 +- src/snapshot_middleware/middleware.rs | 2 +- src/snapshot_middleware/mod.rs | 2 +- src/snapshot_middleware/project.rs | 4 +- src/snapshot_middleware/rbxlx.rs | 2 +- src/snapshot_middleware/rbxm.rs | 2 +- src/snapshot_middleware/rbxmx.rs | 2 +- src/snapshot_middleware/txt.rs | 2 +- src/snapshot_middleware/user_plugins.rs | 2 +- src/vfs/fetcher.rs | 19 +- src/vfs/noop_fetcher.rs | 16 +- src/vfs/real_fetcher.rs | 53 ++-- src/vfs/test_fetcher.rs | 16 +- src/vfs/vfs.rs | 380 +++++++++++++----------- src/web/ui.rs | 4 +- 21 files changed, 292 insertions(+), 258 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index 55238ce8..5e0d3220 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -21,10 +21,10 @@ pub struct ChangeProcessor { } impl ChangeProcessor { - pub fn start( + pub fn start( tree: Arc>, message_queue: Arc>, - vfs: Arc>>, + vfs: Arc>, ) -> Self { let (shutdown_sender, shutdown_receiver) = crossbeam_channel::bounded(1); @@ -47,12 +47,9 @@ impl ChangeProcessor { shutdown_receiver: Receiver<()>, tree: Arc>, message_queue: Arc>, - vfs: Arc>>, + vfs: Arc>, ) { - let vfs_receiver = { - let vfs = vfs.lock().unwrap(); - vfs.change_receiver() - }; + let vfs_receiver = vfs.change_receiver(); // Crossbeam's select macro generates code that Clippy doesn't like, and // Clippy blames us for it. @@ -65,7 +62,6 @@ impl ChangeProcessor { log::trace!("Vfs event: {:?}", event); let applied_patches = { - let mut vfs = vfs.lock().unwrap(); vfs.commit_change(&event).expect("Error applying VFS change"); let mut tree = tree.lock().unwrap(); @@ -102,7 +98,7 @@ impl ChangeProcessor { // TODO: Use persisted snapshot // context struct instead of // recreating it every time. - let snapshot = snapshot_from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + let snapshot = snapshot_from_vfs(&mut InstanceSnapshotContext::default(), &vfs, &entry) .expect("snapshot failed") .expect("snapshot did not return an instance"); diff --git a/src/common_setup.rs b/src/common_setup.rs index 50734117..51914181 100644 --- a/src/common_setup.rs +++ b/src/common_setup.rs @@ -14,7 +14,7 @@ use crate::{ pub fn start( fuzzy_project_path: &Path, - vfs: &mut Vfs, + vfs: &Vfs, ) -> (Option, RojoTree) { log::trace!("Loading project file from {}", fuzzy_project_path.display()); let maybe_project = match Project::load_fuzzy(fuzzy_project_path) { diff --git a/src/serve_session.rs b/src/serve_session.rs index 6a24bf65..cd3865ce 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -52,7 +52,7 @@ pub struct ServeSession { /// /// The main use for accessing it from the session is for debugging issues /// with Rojo's live-sync protocol. - vfs: Arc>>, + vfs: Arc>, /// A queue of changes that have been applied to `tree` that affect clients. /// @@ -71,7 +71,7 @@ pub struct ServeSession { /// Methods that need thread-safety bounds on VfsFetcher are limited to this /// block to prevent needing to spread Send + Sync + 'static into everything /// that handles ServeSession. -impl ServeSession { +impl ServeSession { /// Start a new serve session from the given in-memory filesystem and start /// path. /// @@ -92,7 +92,7 @@ impl ServeSession { let tree = Arc::new(Mutex::new(tree)); let message_queue = Arc::new(message_queue); - let vfs = Arc::new(Mutex::new(vfs)); + let vfs = Arc::new(vfs); log::trace!("Starting ChangeProcessor"); let change_processor = ChangeProcessor::start( @@ -122,8 +122,8 @@ impl ServeSession { self.tree.lock().unwrap() } - pub fn vfs(&self) -> MutexGuard<'_, Vfs> { - self.vfs.lock().unwrap() + pub fn vfs(&self) -> &Vfs { + &self.vfs } pub fn message_queue(&self) -> &MessageQueue { @@ -179,7 +179,7 @@ mod serve_session { #[test] fn just_folder() { - let mut vfs = Vfs::new(NoopFetcher); + let vfs = Vfs::new(NoopFetcher); vfs.debug_load_snapshot("/foo", VfsSnapshot::empty_dir()); @@ -191,7 +191,7 @@ mod serve_session { #[test] fn project_with_folder() { - let mut vfs = Vfs::new(NoopFetcher); + let vfs = Vfs::new(NoopFetcher); vfs.debug_load_snapshot( "/foo", @@ -218,7 +218,7 @@ mod serve_session { #[test] fn script_with_meta() { - let mut vfs = Vfs::new(NoopFetcher); + let vfs = Vfs::new(NoopFetcher); vfs.debug_load_snapshot( "/root", diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 08c2b755..c9a09ef2 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -21,7 +21,7 @@ pub struct SnapshotCsv; impl SnapshotMiddleware for SnapshotCsv { fn from_vfs( _context: &mut InstanceSnapshotContext, - vfs: &mut Vfs, + vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 9b54ef59..7d1bed84 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -20,7 +20,7 @@ pub struct SnapshotDir; impl SnapshotMiddleware for SnapshotDir { fn from_vfs( context: &mut InstanceSnapshotContext, - vfs: &mut Vfs, + vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_file() { diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 3ccde84c..18aaa53d 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -20,7 +20,7 @@ pub struct SnapshotJsonModel; impl SnapshotMiddleware for SnapshotJsonModel { fn from_vfs( _context: &mut InstanceSnapshotContext, - vfs: &mut Vfs, + vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index bd6c54b2..2ebb7c2a 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -21,7 +21,7 @@ pub struct SnapshotLua; impl SnapshotMiddleware for SnapshotLua { fn from_vfs( context: &mut InstanceSnapshotContext, - vfs: &mut Vfs, + vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { let file_name = entry.path().file_name().unwrap().to_string_lossy(); @@ -54,7 +54,7 @@ impl SnapshotMiddleware for SnapshotLua { /// Core routine for turning Lua files into snapshots. fn snapshot_lua_file( - vfs: &mut Vfs, + vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { let file_name = entry.path().file_name().unwrap().to_string_lossy(); @@ -117,7 +117,7 @@ fn snapshot_lua_file( /// their parents, which acts similarly to `__init__.py` from the Python world. fn snapshot_init( context: &mut InstanceSnapshotContext, - vfs: &mut Vfs, + vfs: &Vfs, folder_entry: &VfsEntry, init_name: &str, ) -> SnapshotInstanceResult<'static> { diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index fe9a2ebb..6282e474 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -15,7 +15,7 @@ pub type SnapshotFileResult = Option<(String, VfsSnapshot)>; pub trait SnapshotMiddleware { fn from_vfs( context: &mut InstanceSnapshotContext, - vfs: &mut Vfs, + vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult<'static>; diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 4e466d7b..25f0bedb 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -44,7 +44,7 @@ macro_rules! middlewares { /// Generates a snapshot of instances from the given VfsEntry. pub fn snapshot_from_vfs( context: &mut InstanceSnapshotContext, - vfs: &mut Vfs, + vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { $( diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index a3050ff0..bb4a8ffe 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -23,7 +23,7 @@ pub struct SnapshotProject; impl SnapshotMiddleware for SnapshotProject { fn from_vfs( context: &mut InstanceSnapshotContext, - vfs: &mut Vfs, + vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { @@ -80,7 +80,7 @@ fn snapshot_project_node( context: &mut InstanceSnapshotContext, instance_name: &str, node: &ProjectNode, - vfs: &mut Vfs, + vfs: &Vfs, ) -> SnapshotInstanceResult<'static> { let name = Cow::Owned(instance_name.to_owned()); let mut class_name = node diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index 631afe22..2935fad4 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -16,7 +16,7 @@ pub struct SnapshotRbxlx; impl SnapshotMiddleware for SnapshotRbxlx { fn from_vfs( _context: &mut InstanceSnapshotContext, - vfs: &mut Vfs, + vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 8af33296..ec9b4ab1 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -18,7 +18,7 @@ pub struct SnapshotRbxm; impl SnapshotMiddleware for SnapshotRbxm { fn from_vfs( _context: &mut InstanceSnapshotContext, - vfs: &mut Vfs, + vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index bd54160d..e7b05752 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -16,7 +16,7 @@ pub struct SnapshotRbxmx; impl SnapshotMiddleware for SnapshotRbxmx { fn from_vfs( _context: &mut InstanceSnapshotContext, - vfs: &mut Vfs, + vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 0b79eaac..54b08aa6 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -21,7 +21,7 @@ pub struct SnapshotTxt; impl SnapshotMiddleware for SnapshotTxt { fn from_vfs( _context: &mut InstanceSnapshotContext, - vfs: &mut Vfs, + vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { if entry.is_directory() { diff --git a/src/snapshot_middleware/user_plugins.rs b/src/snapshot_middleware/user_plugins.rs index f39d9336..10daecd4 100644 --- a/src/snapshot_middleware/user_plugins.rs +++ b/src/snapshot_middleware/user_plugins.rs @@ -16,7 +16,7 @@ pub struct SnapshotUserPlugins; impl SnapshotMiddleware for SnapshotUserPlugins { fn from_vfs( context: &mut InstanceSnapshotContext, - _vfs: &mut Vfs, + _vfs: &Vfs, _entry: &VfsEntry, ) -> SnapshotInstanceResult<'static> { // User plugins are only enabled if present on the snapshot context. diff --git a/src/vfs/fetcher.rs b/src/vfs/fetcher.rs index bb321093..7d38e370 100644 --- a/src/vfs/fetcher.rs +++ b/src/vfs/fetcher.rs @@ -17,20 +17,21 @@ pub enum FileType { /// In tests, it's stubbed out to do different versions of absolutely nothing /// depending on the test. pub trait VfsFetcher { - fn file_type(&mut self, path: &Path) -> io::Result; - fn read_children(&mut self, path: &Path) -> io::Result>; - fn read_contents(&mut self, path: &Path) -> io::Result>; + fn file_type(&self, path: &Path) -> io::Result; + fn read_children(&self, path: &Path) -> io::Result>; + fn read_contents(&self, path: &Path) -> io::Result>; - fn create_directory(&mut self, path: &Path) -> io::Result<()>; - fn write_file(&mut self, path: &Path, contents: &[u8]) -> io::Result<()>; - fn remove(&mut self, path: &Path) -> io::Result<()>; + fn create_directory(&self, path: &Path) -> io::Result<()>; + fn write_file(&self, path: &Path, contents: &[u8]) -> io::Result<()>; + fn remove(&self, path: &Path) -> io::Result<()>; - fn watch(&mut self, path: &Path); - fn unwatch(&mut self, path: &Path); fn receiver(&self) -> Receiver; + fn watch(&self, _path: &Path) {} + fn unwatch(&self, _path: &Path) {} + /// A method intended for debugging what paths the fetcher is watching. - fn watched_paths(&self) -> Vec<&Path> { + fn watched_paths(&self) -> Vec { Vec::new() } } diff --git a/src/vfs/noop_fetcher.rs b/src/vfs/noop_fetcher.rs index b0312185..58533a83 100644 --- a/src/vfs/noop_fetcher.rs +++ b/src/vfs/noop_fetcher.rs @@ -19,42 +19,42 @@ use super::{ pub struct NoopFetcher; impl VfsFetcher for NoopFetcher { - fn file_type(&mut self, _path: &Path) -> io::Result { + fn file_type(&self, _path: &Path) -> io::Result { Err(io::Error::new( io::ErrorKind::NotFound, "NoopFetcher always returns NotFound", )) } - fn read_children(&mut self, _path: &Path) -> io::Result> { + fn read_children(&self, _path: &Path) -> io::Result> { Err(io::Error::new( io::ErrorKind::NotFound, "NoopFetcher always returns NotFound", )) } - fn read_contents(&mut self, _path: &Path) -> io::Result> { + fn read_contents(&self, _path: &Path) -> io::Result> { Err(io::Error::new( io::ErrorKind::NotFound, "NoopFetcher always returns NotFound", )) } - fn create_directory(&mut self, _path: &Path) -> io::Result<()> { + fn create_directory(&self, _path: &Path) -> io::Result<()> { Ok(()) } - fn write_file(&mut self, _path: &Path, _contents: &[u8]) -> io::Result<()> { + fn write_file(&self, _path: &Path, _contents: &[u8]) -> io::Result<()> { Ok(()) } - fn remove(&mut self, _path: &Path) -> io::Result<()> { + fn remove(&self, _path: &Path) -> io::Result<()> { Ok(()) } - fn watch(&mut self, _path: &Path) {} + fn watch(&self, _path: &Path) {} - fn unwatch(&mut self, _path: &Path) {} + fn unwatch(&self, _path: &Path) {} fn receiver(&self) -> Receiver { crossbeam_channel::never() diff --git a/src/vfs/real_fetcher.rs b/src/vfs/real_fetcher.rs index f2f686d9..5dce585c 100644 --- a/src/vfs/real_fetcher.rs +++ b/src/vfs/real_fetcher.rs @@ -5,7 +5,7 @@ use std::{ collections::HashSet, fs, io, path::{Path, PathBuf}, - sync::mpsc, + sync::{mpsc, Mutex}, time::Duration, }; @@ -34,7 +34,7 @@ pub struct RealFetcher { // // `watcher` must be dropped before `_converter_thread` or else joining the // thread will cause a deadlock. - watcher: Option, + watcher: Option>, /// Thread handle to convert notify's mpsc channel messages into /// crossbeam_channel messages. @@ -45,7 +45,7 @@ pub struct RealFetcher { /// All of the paths that the fetcher is watching, tracked here because /// notify does not expose this information. - watched_paths: HashSet, + watched_paths: Mutex>, } impl RealFetcher { @@ -68,10 +68,12 @@ impl RealFetcher { // causing our program to deadlock. Once this is fixed, watcher no // longer needs to be optional, but is still maybe useful? let watcher = match watch_mode { - WatchMode::Enabled => Some( - notify::watcher(notify_sender, Duration::from_millis(300)) - .expect("Couldn't start 'notify' file watcher"), - ), + WatchMode::Enabled => { + let watcher = notify::watcher(notify_sender, Duration::from_millis(300)) + .expect("Couldn't start 'notify' file watcher"); + + Some(Mutex::new(watcher)) + } WatchMode::Disabled => None, }; @@ -79,7 +81,7 @@ impl RealFetcher { watcher, _converter_thread: handle, receiver, - watched_paths: HashSet::new(), + watched_paths: Mutex::new(HashSet::new()), } } } @@ -122,7 +124,7 @@ fn converter_thread(notify_receiver: mpsc::Receiver, sender: Sen } impl VfsFetcher for RealFetcher { - fn file_type(&mut self, path: &Path) -> io::Result { + fn file_type(&self, path: &Path) -> io::Result { let metadata = fs::metadata(path)?; if metadata.is_file() { @@ -132,7 +134,7 @@ impl VfsFetcher for RealFetcher { } } - fn read_children(&mut self, path: &Path) -> io::Result> { + fn read_children(&self, path: &Path) -> io::Result> { log::trace!("Reading directory {}", path.display()); let mut result = Vec::new(); @@ -146,25 +148,25 @@ impl VfsFetcher for RealFetcher { Ok(result) } - fn read_contents(&mut self, path: &Path) -> io::Result> { + fn read_contents(&self, path: &Path) -> io::Result> { log::trace!("Reading file {}", path.display()); fs::read(path) } - fn create_directory(&mut self, path: &Path) -> io::Result<()> { + fn create_directory(&self, path: &Path) -> io::Result<()> { log::trace!("Creating directory {}", path.display()); fs::create_dir(path) } - fn write_file(&mut self, path: &Path, contents: &[u8]) -> io::Result<()> { + fn write_file(&self, path: &Path, contents: &[u8]) -> io::Result<()> { log::trace!("Writing path {}", path.display()); fs::write(path, contents) } - fn remove(&mut self, path: &Path) -> io::Result<()> { + fn remove(&self, path: &Path) -> io::Result<()> { log::trace!("Removing path {}", path.display()); let metadata = fs::metadata(path)?; @@ -176,13 +178,16 @@ impl VfsFetcher for RealFetcher { } } - fn watch(&mut self, path: &Path) { + fn watch(&self, path: &Path) { log::trace!("Watching path {}", path.display()); - if let Some(watcher) = self.watcher.as_mut() { + if let Some(watcher_handle) = &self.watcher { + let mut watcher = watcher_handle.lock().unwrap(); + match watcher.watch(path, RecursiveMode::NonRecursive) { Ok(_) => { - self.watched_paths.insert(path.to_path_buf()); + let mut watched_paths = self.watched_paths.lock().unwrap(); + watched_paths.insert(path.to_path_buf()); } Err(err) => { log::warn!("Couldn't watch path {}: {:?}", path.display(), err); @@ -191,14 +196,17 @@ impl VfsFetcher for RealFetcher { } } - fn unwatch(&mut self, path: &Path) { + fn unwatch(&self, path: &Path) { log::trace!("Stopped watching path {}", path.display()); - if let Some(watcher) = self.watcher.as_mut() { + if let Some(watcher_handle) = &self.watcher { + let mut watcher = watcher_handle.lock().unwrap(); + // Remove the path from our watched paths regardless of the outcome // of notify's unwatch to ensure we drop old paths in the event of a // rename. - self.watched_paths.remove(path); + let mut watched_paths = self.watched_paths.lock().unwrap(); + watched_paths.remove(path); if let Err(err) = watcher.unwatch(path) { log::warn!("Couldn't unwatch path {}: {:?}", path.display(), err); @@ -210,7 +218,8 @@ impl VfsFetcher for RealFetcher { self.receiver.clone() } - fn watched_paths(&self) -> Vec<&Path> { - self.watched_paths.iter().map(|v| v.as_path()).collect() + fn watched_paths(&self) -> Vec { + let watched_paths = self.watched_paths.lock().unwrap(); + watched_paths.iter().map(|v| v.clone()).collect() } } diff --git a/src/vfs/test_fetcher.rs b/src/vfs/test_fetcher.rs index 9e37717c..e97f9334 100644 --- a/src/vfs/test_fetcher.rs +++ b/src/vfs/test_fetcher.rs @@ -107,7 +107,7 @@ impl TestFetcher { } impl VfsFetcher for TestFetcher { - fn file_type(&mut self, path: &Path) -> io::Result { + fn file_type(&self, path: &Path) -> io::Result { let inner = self.state.inner.lock().unwrap(); match inner.entries.get(path) { @@ -117,7 +117,7 @@ impl VfsFetcher for TestFetcher { } } - fn read_children(&mut self, path: &Path) -> io::Result> { + fn read_children(&self, path: &Path) -> io::Result> { let inner = self.state.inner.lock().unwrap(); Ok(inner @@ -129,7 +129,7 @@ impl VfsFetcher for TestFetcher { .collect()) } - fn read_contents(&mut self, path: &Path) -> io::Result> { + fn read_contents(&self, path: &Path) -> io::Result> { let inner = self.state.inner.lock().unwrap(); let node = inner.entries.get(path); @@ -144,31 +144,27 @@ impl VfsFetcher for TestFetcher { } } - fn create_directory(&mut self, _path: &Path) -> io::Result<()> { + fn create_directory(&self, _path: &Path) -> io::Result<()> { Err(io::Error::new( io::ErrorKind::Other, "TestFetcher is not mutable yet", )) } - fn write_file(&mut self, _path: &Path, _contents: &[u8]) -> io::Result<()> { + fn write_file(&self, _path: &Path, _contents: &[u8]) -> io::Result<()> { Err(io::Error::new( io::ErrorKind::Other, "TestFetcher is not mutable yet", )) } - fn remove(&mut self, _path: &Path) -> io::Result<()> { + fn remove(&self, _path: &Path) -> io::Result<()> { Err(io::Error::new( io::ErrorKind::Other, "TestFetcher is not mutable yet", )) } - fn watch(&mut self, _path: &Path) {} - - fn unwatch(&mut self, _path: &Path) {} - fn receiver(&self) -> Receiver { self.receiver.clone() } diff --git a/src/vfs/vfs.rs b/src/vfs/vfs.rs index 509e1e2e..ee3ee177 100644 --- a/src/vfs/vfs.rs +++ b/src/vfs/vfs.rs @@ -1,7 +1,7 @@ use std::{ io, path::{Path, PathBuf}, - sync::Arc, + sync::{Arc, Mutex}, }; use crossbeam_channel::Receiver; @@ -28,7 +28,7 @@ use super::{ pub struct Vfs { /// A hierarchical map from paths to items that have been read or partially /// read into memory by the Vfs. - data: PathMap, + data: Mutex>, /// This Vfs's fetcher, which is used for all actual interactions with the /// filesystem. It's referred to by the type parameter `F` all over, and is @@ -39,7 +39,7 @@ pub struct Vfs { impl Vfs { pub fn new(fetcher: F) -> Self { Self { - data: PathMap::new(), + data: Mutex::new(PathMap::new()), fetcher, } } @@ -48,108 +48,37 @@ impl Vfs { self.fetcher.receiver() } - pub fn commit_change(&mut self, event: &VfsEvent) -> FsResult<()> { + pub fn commit_change(&self, event: &VfsEvent) -> FsResult<()> { use VfsEvent::*; log::trace!("Committing Vfs change {:?}", event); + let mut data = self.data.lock().unwrap(); + match event { Created(path) | Modified(path) => { - self.raise_file_changed(path)?; + Self::raise_file_changed(&mut data, &self.fetcher, path)?; } Removed(path) => { - self.raise_file_removed(path)?; + Self::raise_file_removed(&mut data, &self.fetcher, path)?; } } Ok(()) } - fn raise_file_changed(&mut self, path: impl AsRef) -> FsResult<()> { - let path = path.as_ref(); - - if !self.would_be_resident(path) { - return Ok(()); - } - - let new_type = self - .fetcher - .file_type(path) - .map_err(|err| FsError::new(err, path.to_path_buf()))?; - - match self.data.get_mut(path) { - Some(existing_item) => { - match (existing_item, &new_type) { - (VfsItem::File(existing_file), FileType::File) => { - // Invalidate the existing file contents. - // We can probably be smarter about this by reading the changed file. - existing_file.contents = None; - } - (VfsItem::Directory(_), FileType::Directory) => { - // No changes required, a directory updating doesn't mean anything to us. - self.fetcher.watch(path); - } - (VfsItem::File(_), FileType::Directory) => { - self.data.remove(path); - self.data.insert( - path.to_path_buf(), - VfsItem::new_from_type(FileType::Directory, path), - ); - self.fetcher.watch(path); - } - (VfsItem::Directory(_), FileType::File) => { - self.data.remove(path); - self.data.insert( - path.to_path_buf(), - VfsItem::new_from_type(FileType::File, path), - ); - self.fetcher.unwatch(path); - } - } - } - None => { - self.data - .insert(path.to_path_buf(), VfsItem::new_from_type(new_type, path)); - } - } - - Ok(()) + pub fn get(&self, path: impl AsRef) -> FsResult { + let mut data = self.data.lock().unwrap(); + Self::get_internal(&mut data, &self.fetcher, path) } - fn raise_file_removed(&mut self, path: impl AsRef) -> FsResult<()> { + pub fn get_contents(&self, path: impl AsRef) -> FsResult>> { let path = path.as_ref(); - if !self.would_be_resident(path) { - return Ok(()); - } + let mut data = self.data.lock().unwrap(); + Self::read_if_not_exists(&mut data, &self.fetcher, path)?; - self.data.remove(path); - self.fetcher.unwatch(path); - Ok(()) - } - - pub fn get(&mut self, path: impl AsRef) -> FsResult { - self.read_if_not_exists(path.as_ref())?; - - let item = self.data.get(path.as_ref()).unwrap(); - - let is_file = match item { - VfsItem::File(_) => true, - VfsItem::Directory(_) => false, - }; - - Ok(VfsEntry { - path: item.path().to_path_buf(), - is_file, - }) - } - - pub fn get_contents(&mut self, path: impl AsRef) -> FsResult>> { - let path = path.as_ref(); - - self.read_if_not_exists(path)?; - - match self.data.get_mut(path).unwrap() { + match data.get_mut(path).unwrap() { VfsItem::File(file) => { if file.contents.is_none() { file.contents = Some( @@ -169,26 +98,26 @@ impl Vfs { } } - pub fn get_children(&mut self, path: impl AsRef) -> FsResult> { + pub fn get_children(&self, path: impl AsRef) -> FsResult> { let path = path.as_ref(); - self.read_if_not_exists(path)?; + let mut data = self.data.lock().unwrap(); + Self::read_if_not_exists(&mut data, &self.fetcher, path)?; - match self.data.get_mut(path).unwrap() { + match data.get_mut(path).unwrap() { VfsItem::Directory(dir) => { self.fetcher.watch(path); let enumerated = dir.children_enumerated; if enumerated { - self.data - .children(path) + data.children(path) .unwrap() // TODO: Handle None here, which means the PathMap entry did not exist. .into_iter() .map(PathBuf::from) // Convert paths from &Path to PathBuf .collect::>() // Collect all PathBufs, since self.get needs to borrow self mutably. .into_iter() - .map(|path| self.get(path)) + .map(|path| Self::get_internal(&mut data, &self.fetcher, path)) .collect::>>() } else { dir.children_enumerated = true; @@ -197,7 +126,7 @@ impl Vfs { .read_children(path) .map_err(|err| FsError::new(err, path.to_path_buf()))? .into_iter() - .map(|path| self.get(path)) + .map(|path| Self::get_internal(&mut data, &self.fetcher, path)) .collect::>>() } } @@ -208,6 +137,118 @@ impl Vfs { } } + fn get_internal( + data: &mut PathMap, + fetcher: &F, + path: impl AsRef, + ) -> FsResult { + let path = path.as_ref(); + + Self::read_if_not_exists(data, fetcher, path)?; + + let item = data.get(path).unwrap(); + + let is_file = match item { + VfsItem::File(_) => true, + VfsItem::Directory(_) => false, + }; + + Ok(VfsEntry { + path: item.path().to_path_buf(), + is_file, + }) + } + + fn raise_file_changed( + data: &mut PathMap, + fetcher: &F, + path: impl AsRef, + ) -> FsResult<()> { + let path = path.as_ref(); + + if !Self::would_be_resident(&data, path) { + return Ok(()); + } + + let new_type = fetcher + .file_type(path) + .map_err(|err| FsError::new(err, path.to_path_buf()))?; + + match data.get_mut(path) { + Some(existing_item) => { + match (existing_item, &new_type) { + (VfsItem::File(existing_file), FileType::File) => { + // Invalidate the existing file contents. + // We can probably be smarter about this by reading the changed file. + existing_file.contents = None; + } + (VfsItem::Directory(_), FileType::Directory) => { + // No changes required, a directory updating doesn't mean anything to us. + fetcher.watch(path); + } + (VfsItem::File(_), FileType::Directory) => { + data.remove(path); + data.insert( + path.to_path_buf(), + VfsItem::new_from_type(FileType::Directory, path), + ); + fetcher.watch(path); + } + (VfsItem::Directory(_), FileType::File) => { + data.remove(path); + data.insert( + path.to_path_buf(), + VfsItem::new_from_type(FileType::File, path), + ); + fetcher.unwatch(path); + } + } + } + None => { + data.insert(path.to_path_buf(), VfsItem::new_from_type(new_type, path)); + } + } + + Ok(()) + } + + fn raise_file_removed( + data: &mut PathMap, + fetcher: &F, + path: impl AsRef, + ) -> FsResult<()> { + let path = path.as_ref(); + + if !Self::would_be_resident(data, path) { + return Ok(()); + } + + data.remove(path); + fetcher.unwatch(path); + Ok(()) + } + + /// Attempts to read the path into the `Vfs` if it doesn't exist. + /// + /// This does not necessitate that file contents or directory children will + /// be read. Depending on the `VfsFetcher` implementation that the `Vfs` + /// is using, this call may read exactly only the given path and no more. + fn read_if_not_exists(data: &mut PathMap, fetcher: &F, path: &Path) -> FsResult<()> { + if !data.contains_key(path) { + let kind = fetcher + .file_type(path) + .map_err(|err| FsError::new(err, path.to_path_buf()))?; + + if kind == FileType::Directory { + fetcher.watch(path); + } + + data.insert(path.to_path_buf(), VfsItem::new_from_type(kind, path)); + } + + Ok(()) + } + /// Tells whether the given path, if it were loaded, would be loaded if it /// existed. /// @@ -218,113 +259,108 @@ impl Vfs { /// tangible changes to the in-memory filesystem. If a path would be /// resident, we need to read it, and if its contents were known before, we /// need to update them. - fn would_be_resident(&self, path: &Path) -> bool { - if self.data.contains_key(path) { + fn would_be_resident(data: &PathMap, path: &Path) -> bool { + if data.contains_key(path) { return true; } if let Some(parent) = path.parent() { - if let Some(VfsItem::Directory(dir)) = self.data.get(parent) { + if let Some(VfsItem::Directory(dir)) = data.get(parent) { return !dir.children_enumerated; } } false } - - /// Attempts to read the path into the `Vfs` if it doesn't exist. - /// - /// This does not necessitate that file contents or directory children will - /// be read. Depending on the `VfsFetcher` implementation that the `Vfs` - /// is using, this call may read exactly only the given path and no more. - fn read_if_not_exists(&mut self, path: &Path) -> FsResult<()> { - if !self.data.contains_key(path) { - let kind = self - .fetcher - .file_type(path) - .map_err(|err| FsError::new(err, path.to_path_buf()))?; - - if kind == FileType::Directory { - self.fetcher.watch(path); - } - - self.data - .insert(path.to_path_buf(), VfsItem::new_from_type(kind, path)); - } - - Ok(()) - } } /// Contains extra methods that should only be used for debugging. They're /// broken out into a separate trait to make it more explicit to depend on them. pub trait VfsDebug { - fn debug_load_snapshot>(&mut self, path: P, snapshot: VfsSnapshot); + fn debug_load_snapshot>(&self, path: P, snapshot: VfsSnapshot); fn debug_is_file(&self, path: &Path) -> bool; - fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]>; - fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)>; - fn debug_orphans(&self) -> Vec<&Path>; - fn debug_watched_paths(&self) -> Vec<&Path>; + fn debug_contents(&self, path: &Path) -> Option>>; + fn debug_children(&self, path: &Path) -> Option<(bool, Vec)>; + fn debug_orphans(&self) -> Vec; + fn debug_watched_paths(&self) -> Vec; } impl VfsDebug for Vfs { - fn debug_load_snapshot>(&mut self, path: P, snapshot: VfsSnapshot) { - let path = path.as_ref(); + fn debug_load_snapshot>(&self, path: P, snapshot: VfsSnapshot) { + fn load_snapshot>( + data: &mut PathMap, + path: P, + snapshot: VfsSnapshot, + ) { + let path = path.as_ref(); - match snapshot { - VfsSnapshot::File(file) => { - self.data.insert( - path.to_path_buf(), - VfsItem::File(VfsFile { - path: path.to_path_buf(), - contents: Some(Arc::new(file.contents)), - }), - ); - } - VfsSnapshot::Directory(directory) => { - self.data.insert( - path.to_path_buf(), - VfsItem::Directory(VfsDirectory { - path: path.to_path_buf(), - children_enumerated: true, - }), - ); + match snapshot { + VfsSnapshot::File(file) => { + data.insert( + path.to_path_buf(), + VfsItem::File(VfsFile { + path: path.to_path_buf(), + contents: Some(Arc::new(file.contents)), + }), + ); + } + VfsSnapshot::Directory(directory) => { + data.insert( + path.to_path_buf(), + VfsItem::Directory(VfsDirectory { + path: path.to_path_buf(), + children_enumerated: true, + }), + ); - for (child_name, child) in directory.children.into_iter() { - self.debug_load_snapshot(path.join(child_name), child); + for (child_name, child) in directory.children.into_iter() { + load_snapshot(data, path.join(child_name), child); + } } } } + + let mut data = self.data.lock().unwrap(); + load_snapshot(&mut data, path, snapshot) } fn debug_is_file(&self, path: &Path) -> bool { - match self.data.get(path) { + let data = self.data.lock().unwrap(); + match data.get(path) { Some(VfsItem::File(_)) => true, _ => false, } } - fn debug_contents<'a>(&'a self, path: &Path) -> Option<&'a [u8]> { - match self.data.get(path) { - Some(VfsItem::File(file)) => file.contents.as_ref().map(|vec| vec.as_slice()), + fn debug_contents(&self, path: &Path) -> Option>> { + let data = self.data.lock().unwrap(); + match data.get(path) { + Some(VfsItem::File(file)) => file.contents.clone(), _ => None, } } - fn debug_children<'a>(&'a self, path: &Path) -> Option<(bool, Vec<&'a Path>)> { - match self.data.get(path) { - Some(VfsItem::Directory(dir)) => { - Some((dir.children_enumerated, self.data.children(path).unwrap())) - } + fn debug_children(&self, path: &Path) -> Option<(bool, Vec)> { + let data = self.data.lock().unwrap(); + match data.get(path) { + Some(VfsItem::Directory(dir)) => Some(( + dir.children_enumerated, + data.children(path) + .unwrap() + .iter() + .map(|path| path.to_path_buf()) + .collect(), + )), _ => None, } } - fn debug_orphans(&self) -> Vec<&Path> { - self.data.orphans().collect() + fn debug_orphans(&self) -> Vec { + let data = self.data.lock().unwrap(); + data.orphans().map(|path| path.to_path_buf()).collect() } - fn debug_watched_paths(&self) -> Vec<&Path> { + fn debug_watched_paths(&self) -> Vec { self.fetcher.watched_paths() } } @@ -345,11 +381,11 @@ impl VfsEntry { &self.path } - pub fn contents<'vfs>(&self, vfs: &'vfs mut Vfs) -> FsResult>> { + pub fn contents(&self, vfs: &Vfs) -> FsResult>> { vfs.get_contents(&self.path) } - pub fn children(&self, vfs: &mut Vfs) -> FsResult> { + pub fn children(&self, vfs: &Vfs) -> FsResult> { vfs.get_children(&self.path) } @@ -414,7 +450,7 @@ mod test { #[test] fn from_snapshot_file() { - let mut vfs = Vfs::new(NoopFetcher); + let vfs = Vfs::new(NoopFetcher); let file = VfsSnapshot::file("hello, world!"); vfs.debug_load_snapshot("/hello.txt", file); @@ -425,7 +461,7 @@ mod test { #[test] fn from_snapshot_dir() { - let mut vfs = Vfs::new(NoopFetcher); + let vfs = Vfs::new(NoopFetcher); let dir = VfsSnapshot::dir(hashmap! { "a.txt" => VfsSnapshot::file("contents of a.txt"), "b.lua" => VfsSnapshot::file("contents of b.lua"), @@ -470,7 +506,7 @@ mod test { } impl VfsFetcher for MockFetcher { - fn file_type(&mut self, path: &Path) -> io::Result { + fn file_type(&self, path: &Path) -> io::Result { if path == Path::new("/dir/a.txt") { return Ok(FileType::File); } @@ -478,7 +514,7 @@ mod test { unimplemented!(); } - fn read_contents(&mut self, path: &Path) -> io::Result> { + fn read_contents(&self, path: &Path) -> io::Result> { if path == Path::new("/dir/a.txt") { let inner = self.inner.borrow(); @@ -488,26 +524,22 @@ mod test { unimplemented!(); } - fn read_children(&mut self, _path: &Path) -> io::Result> { + fn read_children(&self, _path: &Path) -> io::Result> { unimplemented!(); } - fn create_directory(&mut self, _path: &Path) -> io::Result<()> { + fn create_directory(&self, _path: &Path) -> io::Result<()> { unimplemented!(); } - fn write_file(&mut self, _path: &Path, _contents: &[u8]) -> io::Result<()> { + fn write_file(&self, _path: &Path, _contents: &[u8]) -> io::Result<()> { unimplemented!(); } - fn remove(&mut self, _path: &Path) -> io::Result<()> { + fn remove(&self, _path: &Path) -> io::Result<()> { unimplemented!(); } - fn watch(&mut self, _path: &Path) {} - - fn unwatch(&mut self, _path: &Path) {} - fn receiver(&self) -> Receiver { crossbeam_channel::never() } @@ -532,7 +564,7 @@ mod test { mock_state.a_contents = "Changed contents"; } - vfs.raise_file_changed("/dir/a.txt") + vfs.commit_change(&VfsEvent::Modified(PathBuf::from("/dir/a.txt"))) .expect("error processing file change"); let contents = a.contents(&mut vfs).expect("mock file contents error"); @@ -555,7 +587,7 @@ mod test { assert_eq!(contents.as_slice(), b"hello, world!"); - vfs.raise_file_removed("/hello.txt") + vfs.commit_change(&VfsEvent::Removed(PathBuf::from("/hello.txt"))) .expect("error processing file removal"); match vfs.get("hello.txt") { diff --git a/src/web/ui.rs b/src/web/ui.rs index a4224948..8f7276be 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -102,7 +102,7 @@ impl UiService { let orphans: Vec<_> = vfs .debug_orphans() .into_iter() - .map(|path| Self::render_vfs_path(&vfs, path, true)) + .map(|path| Self::render_vfs_path(&vfs, &path, true)) .collect(); let watched_list: Vec<_> = vfs @@ -153,7 +153,7 @@ impl UiService { let children: Vec<_> = children .into_iter() - .map(|child| Self::render_vfs_path(vfs, child, false)) + .map(|child| Self::render_vfs_path(vfs, &child, false)) .collect(); let note = if is_exhaustive { From 40540c36372f6a09ac0e023fefda5bc79b612c5e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 16 Oct 2019 16:21:33 -0700 Subject: [PATCH 0835/1504] Improve serve test, add single txt file test --- benches/build.rs | 2 +- .../serve_test__just_txt-2.snap | 19 +++ .../serve_test__just_txt.snap | 9 ++ rojo-test/serve-tests/just-txt.txt | 1 + rojo-test/src/lib.rs | 1 + rojo-test/src/serve_test.rs | 139 +++-------------- rojo-test/src/serve_util.rs | 145 ++++++++++++++++++ 7 files changed, 198 insertions(+), 118 deletions(-) create mode 100644 rojo-test/serve-test-snapshots/serve_test__just_txt-2.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__just_txt.snap create mode 100644 rojo-test/serve-tests/just-txt.txt create mode 100644 rojo-test/src/serve_util.rs diff --git a/benches/build.rs b/benches/build.rs index 5a560153..e502de1e 100644 --- a/benches/build.rs +++ b/benches/build.rs @@ -1,4 +1,4 @@ -use std::path::{Path, PathBuf}; +use std::path::{Path}; use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use tempfile::{tempdir, TempDir}; diff --git a/rojo-test/serve-test-snapshots/serve_test__just_txt-2.snap b/rojo-test/serve-test-snapshots/serve_test__just_txt-2.snap new file mode 100644 index 00000000..03a0565f --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__just_txt-2.snap @@ -0,0 +1,19 @@ +--- +source: rojo-test/src/serve_test.rs +expression: read_result +--- +sessionId: id-1 +messageCursor: 0 +instances: + id-2: + Id: id-2 + Parent: ~ + Name: just-txt + ClassName: StringValue + Properties: + Value: + Type: String + Value: "Hello, world!" + Children: [] + Metadata: + ignoreUnknownInstances: false diff --git a/rojo-test/serve-test-snapshots/serve_test__just_txt.snap b/rojo-test/serve-test-snapshots/serve_test__just_txt.snap new file mode 100644 index 00000000..5f830821 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__just_txt.snap @@ -0,0 +1,9 @@ +--- +source: rojo-test/src/serve_test.rs +expression: info +--- +sessionId: id-1 +serverVersion: 0.6.0-dev +protocolVersion: 3 +expectedPlaceIds: ~ +rootInstanceId: id-2 diff --git a/rojo-test/serve-tests/just-txt.txt b/rojo-test/serve-tests/just-txt.txt new file mode 100644 index 00000000..5dd01c17 --- /dev/null +++ b/rojo-test/serve-tests/just-txt.txt @@ -0,0 +1 @@ +Hello, world! \ No newline at end of file diff --git a/rojo-test/src/lib.rs b/rojo-test/src/lib.rs index 786d9410..218b3483 100644 --- a/rojo-test/src/lib.rs +++ b/rojo-test/src/lib.rs @@ -2,4 +2,5 @@ mod build_test; mod serve_test; +mod serve_util; mod util; diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index fa6cedd9..e488cebc 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -1,24 +1,12 @@ -use std::{ - fs, - path::{Path, PathBuf}, - process::Command, - sync::atomic::{AtomicUsize, Ordering}, -}; +use std::fs; use insta::assert_yaml_snapshot; -use rbx_dom_weak::RbxId; -use tempfile::{tempdir, TempDir}; -use librojo::web_interface::{ReadResponse, ServerInfoResponse}; -use rojo_insta_ext::RedactionMap; - -use crate::util::{ - copy_recursive, get_rojo_path, get_serve_tests_path, get_working_dir_path, KillOnDrop, -}; +use crate::serve_util::run_serve_test; #[test] fn empty() { - run_serve_test(|session, mut redactions| { + run_serve_test("empty", |session, mut redactions| { let info = session.get_api_rojo().unwrap(); let root_id = info.root_instance_id; @@ -37,112 +25,29 @@ fn empty() { }); } -fn run_serve_test(callback: impl FnOnce(TestServeSession, RedactionMap)) { - let _ = env_logger::try_init(); +#[test] +fn just_txt() { + run_serve_test("just-txt.txt", |session, mut redactions| { + let info = session.get_api_rojo().unwrap(); - let mut settings = insta::Settings::new(); + let root_id = info.root_instance_id; + let info = redactions.redacted_yaml(info); - let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("serve-test-snapshots"); - settings.set_snapshot_path(snapshot_path); + assert_yaml_snapshot!(info); - let mut redactions = RedactionMap::new(); + let read_result = session.get_api_read(root_id).unwrap(); + redactions.intern_iter(read_result.instances.keys().copied()); + let read_result = redactions.redacted_yaml(read_result); - let mut session = TestServeSession::new("empty"); - let info = session.wait_to_come_online(); + assert_yaml_snapshot!(read_result); - redactions.intern(info.session_id); - redactions.intern(info.root_instance_id); + fs::write(session.path(), "Changed content!").unwrap(); - settings.bind(move || callback(session, redactions)); -} - -fn get_port_number() -> usize { - static NEXT_PORT_NUMBER: AtomicUsize = AtomicUsize::new(35103); - - NEXT_PORT_NUMBER.fetch_add(1, Ordering::SeqCst) -} - -struct TestServeSession { - // Drop order is important here: we want the process to be killed before the - // directory it's operating on is destroyed. - rojo_process: KillOnDrop, - _dir: TempDir, - - port: usize, - project_path: PathBuf, -} - -impl TestServeSession { - pub fn new(name: &str) -> Self { - let serve_test_path = get_serve_tests_path(); - let working_dir = get_working_dir_path(); - let exe_path = get_rojo_path(); - - let source_path = serve_test_path.join(name); - let dir = tempdir().expect("Couldn't create temporary directory"); - let project_path = dir.path().join(name); - - fs::create_dir(&project_path).expect("Couldn't create temporary project subdirectory"); - - copy_recursive(&source_path, &project_path) - .expect("Couldn't copy project to temporary directory"); - - let port = get_port_number(); - let port_string = port.to_string(); - - let rojo_process = Command::new(exe_path) - .args(&[ - "serve", - project_path.to_str().unwrap(), - "--port", - port_string.as_str(), - ]) - .current_dir(working_dir) - .spawn() - .expect("Couldn't start Rojo"); - - TestServeSession { - rojo_process: KillOnDrop(rojo_process), - _dir: dir, - port, - project_path, - } - } - - pub fn wait_to_come_online(&mut self) -> ServerInfoResponse { - loop { - match self.rojo_process.0.try_wait() { - Ok(Some(status)) => panic!("Rojo process exited with status {}", status), - Ok(None) => { /* process is still running */ } - Err(err) => panic!("Failed to wait on Rojo process: {}", err), - } - - let info = match self.get_api_rojo() { - Ok(info) => info, - Err(err) => { - log::debug!("Server error, retrying: {}", err); - std::thread::sleep(std::time::Duration::from_millis(30)); - continue; - } - }; - - log::info!("Got session info: {:?}", info); - - return info; - } - } - - pub fn get_api_rojo(&self) -> Result { - let url = format!("http://localhost:{}/api/rojo", self.port); - let body = reqwest::get(&url)?.text()?; - - Ok(serde_json::from_str(&body).expect("Server returned malformed response")) - } - - pub fn get_api_read(&self, id: RbxId) -> Result { - let url = format!("http://localhost:{}/api/read/{}", self.port, id); - let body = reqwest::get(&url)?.text()?; - - Ok(serde_json::from_str(&body).expect("Server returned malformed response")) - } + // TODO: Directly served files currently don't trigger changed events! + + // let subscribe_result = session.get_api_subscribe(0).unwrap(); + // let subscribe_result = redactions.redacted_yaml(subscribe_result); + + // assert_yaml_snapshot!(subscribe_result); + }); } diff --git a/rojo-test/src/serve_util.rs b/rojo-test/src/serve_util.rs new file mode 100644 index 00000000..97e307ab --- /dev/null +++ b/rojo-test/src/serve_util.rs @@ -0,0 +1,145 @@ +use std::{ + fs, + path::{Path, PathBuf}, + process::Command, + sync::atomic::{AtomicUsize, Ordering}, +}; + +use rbx_dom_weak::RbxId; +use tempfile::{tempdir, TempDir}; + +use librojo::web_interface::{ReadResponse, ServerInfoResponse, SubscribeResponse}; +use rojo_insta_ext::RedactionMap; + +use crate::util::{ + copy_recursive, get_rojo_path, get_serve_tests_path, get_working_dir_path, KillOnDrop, +}; + +pub fn run_serve_test(test_name: &str, callback: impl FnOnce(TestServeSession, RedactionMap)) { + let _ = env_logger::try_init(); + + let mut settings = insta::Settings::new(); + + let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("serve-test-snapshots"); + settings.set_snapshot_path(snapshot_path); + + let mut redactions = RedactionMap::new(); + + let mut session = TestServeSession::new(test_name); + let info = session.wait_to_come_online(); + + redactions.intern(info.session_id); + redactions.intern(info.root_instance_id); + + settings.bind(move || callback(session, redactions)); +} + +fn get_port_number() -> usize { + static NEXT_PORT_NUMBER: AtomicUsize = AtomicUsize::new(35103); + + NEXT_PORT_NUMBER.fetch_add(1, Ordering::SeqCst) +} + +pub struct TestServeSession { + // Drop order is important here: we want the process to be killed before the + // directory it's operating on is destroyed. + rojo_process: KillOnDrop, + _dir: TempDir, + + port: usize, + project_path: PathBuf, +} + +impl TestServeSession { + pub fn new(name: &str) -> Self { + let serve_test_path = get_serve_tests_path(); + let working_dir = get_working_dir_path(); + let exe_path = get_rojo_path(); + + let source_path = serve_test_path.join(name); + let dir = tempdir().expect("Couldn't create temporary directory"); + let project_path = dir.path().join(name); + + let source_is_file = fs::metadata(&source_path).unwrap().is_file(); + + if source_is_file { + fs::copy(&source_path, &project_path).expect("couldn't copy project file"); + } else { + fs::create_dir(&project_path).expect("Couldn't create temporary project subdirectory"); + + copy_recursive(&source_path, &project_path) + .expect("Couldn't copy project to temporary directory"); + }; + + let port = get_port_number(); + let port_string = port.to_string(); + + let rojo_process = Command::new(exe_path) + .args(&[ + "serve", + project_path.to_str().unwrap(), + "--port", + port_string.as_str(), + ]) + .current_dir(working_dir) + .spawn() + .expect("Couldn't start Rojo"); + + TestServeSession { + rojo_process: KillOnDrop(rojo_process), + _dir: dir, + port, + project_path, + } + } + + pub fn path(&self) -> &Path { + &self.project_path + } + + pub fn wait_to_come_online(&mut self) -> ServerInfoResponse { + loop { + match self.rojo_process.0.try_wait() { + Ok(Some(status)) => panic!("Rojo process exited with status {}", status), + Ok(None) => { /* process is still running */ } + Err(err) => panic!("Failed to wait on Rojo process: {}", err), + } + + let info = match self.get_api_rojo() { + Ok(info) => info, + Err(err) => { + log::debug!("Server error, retrying: {}", err); + std::thread::sleep(std::time::Duration::from_millis(30)); + continue; + } + }; + + log::info!("Got session info: {:?}", info); + + return info; + } + } + + pub fn get_api_rojo(&self) -> Result { + let url = format!("http://localhost:{}/api/rojo", self.port); + let body = reqwest::get(&url)?.text()?; + + Ok(serde_json::from_str(&body).expect("Server returned malformed response")) + } + + pub fn get_api_read(&self, id: RbxId) -> Result { + let url = format!("http://localhost:{}/api/read/{}", self.port, id); + let body = reqwest::get(&url)?.text()?; + + Ok(serde_json::from_str(&body).expect("Server returned malformed response")) + } + + pub fn get_api_subscribe( + &self, + cursor: u32, + ) -> Result, reqwest::Error> { + let url = format!("http://localhost:{}/api/subscribe/{}", self.port, cursor); + + reqwest::get(&url)?.json() + } +} From 56f5a6136207064e56b41f61234f2041a14748f1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 16 Oct 2019 16:55:55 -0700 Subject: [PATCH 0836/1504] Add test for folder of scripts being mutated --- .../serve_test__empty-2.snap | 4 +- .../serve_test__empty.snap | 6 +-- .../serve_test__just_txt-2.snap | 4 +- .../serve_test__just_txt.snap | 6 +-- .../serve_test__scripts-2.snap | 42 +++++++++++++++++++ .../serve_test__scripts-3.snap | 18 ++++++++ .../serve_test__scripts-4.snap | 42 +++++++++++++++++++ .../serve_test__scripts.snap | 9 ++++ rojo-test/serve-tests/scripts/bar.server.lua | 1 + rojo-test/serve-tests/scripts/foo.lua | 1 + rojo-test/src/serve_test.rs | 32 +++++++++++--- rojo-test/src/serve_util.rs | 17 ++++++++ 12 files changed, 167 insertions(+), 15 deletions(-) create mode 100644 rojo-test/serve-test-snapshots/serve_test__scripts-2.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__scripts-3.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__scripts-4.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__scripts.snap create mode 100644 rojo-test/serve-tests/scripts/bar.server.lua create mode 100644 rojo-test/serve-tests/scripts/foo.lua diff --git a/rojo-test/serve-test-snapshots/serve_test__empty-2.snap b/rojo-test/serve-test-snapshots/serve_test__empty-2.snap index 7cd6e0f9..4535414a 100644 --- a/rojo-test/serve-test-snapshots/serve_test__empty-2.snap +++ b/rojo-test/serve-test-snapshots/serve_test__empty-2.snap @@ -2,8 +2,6 @@ source: rojo-test/src/serve_test.rs expression: read_result --- -sessionId: id-1 -messageCursor: 0 instances: id-2: Id: id-2 @@ -14,3 +12,5 @@ instances: Children: [] Metadata: ignoreUnknownInstances: true +messageCursor: 0 +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__empty.snap b/rojo-test/serve-test-snapshots/serve_test__empty.snap index 5f830821..cb619dc5 100644 --- a/rojo-test/serve-test-snapshots/serve_test__empty.snap +++ b/rojo-test/serve-test-snapshots/serve_test__empty.snap @@ -2,8 +2,8 @@ source: rojo-test/src/serve_test.rs expression: info --- -sessionId: id-1 -serverVersion: 0.6.0-dev -protocolVersion: 3 expectedPlaceIds: ~ +protocolVersion: 3 rootInstanceId: id-2 +serverVersion: 0.6.0-dev +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__just_txt-2.snap b/rojo-test/serve-test-snapshots/serve_test__just_txt-2.snap index 03a0565f..541ce33e 100644 --- a/rojo-test/serve-test-snapshots/serve_test__just_txt-2.snap +++ b/rojo-test/serve-test-snapshots/serve_test__just_txt-2.snap @@ -2,8 +2,6 @@ source: rojo-test/src/serve_test.rs expression: read_result --- -sessionId: id-1 -messageCursor: 0 instances: id-2: Id: id-2 @@ -17,3 +15,5 @@ instances: Children: [] Metadata: ignoreUnknownInstances: false +messageCursor: 0 +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__just_txt.snap b/rojo-test/serve-test-snapshots/serve_test__just_txt.snap index 5f830821..cb619dc5 100644 --- a/rojo-test/serve-test-snapshots/serve_test__just_txt.snap +++ b/rojo-test/serve-test-snapshots/serve_test__just_txt.snap @@ -2,8 +2,8 @@ source: rojo-test/src/serve_test.rs expression: info --- -sessionId: id-1 -serverVersion: 0.6.0-dev -protocolVersion: 3 expectedPlaceIds: ~ +protocolVersion: 3 rootInstanceId: id-2 +serverVersion: 0.6.0-dev +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts-2.snap b/rojo-test/serve-test-snapshots/serve_test__scripts-2.snap new file mode 100644 index 00000000..e012c3b9 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__scripts-2.snap @@ -0,0 +1,42 @@ +--- +source: rojo-test/src/serve_test.rs +expression: read_result +--- +instances: + id-2: + Id: id-2 + Parent: ~ + Name: scripts + ClassName: Folder + Properties: {} + Children: + - id-3 + - id-4 + Metadata: + ignoreUnknownInstances: false + id-3: + Id: id-3 + Parent: id-2 + Name: bar + ClassName: Script + Properties: + Source: + Type: String + Value: "-- Hello, from bar!" + Children: [] + Metadata: + ignoreUnknownInstances: false + id-4: + Id: id-4 + Parent: id-2 + Name: foo + ClassName: ModuleScript + Properties: + Source: + Type: String + Value: "-- Hello, from foo!" + Children: [] + Metadata: + ignoreUnknownInstances: false +messageCursor: 0 +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts-3.snap b/rojo-test/serve-test-snapshots/serve_test__scripts-3.snap new file mode 100644 index 00000000..9befdbad --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__scripts-3.snap @@ -0,0 +1,18 @@ +--- +source: rojo-test/src/serve_test.rs +expression: subscribe_result +--- +messageCursor: 1 +messages: + - removedInstances: [] + addedInstances: {} + updatedInstances: + - id: id-4 + changedName: ~ + changedClassName: ~ + changedProperties: + Source: + Type: String + Value: Updated foo! + changedMetadata: ~ +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts-4.snap b/rojo-test/serve-test-snapshots/serve_test__scripts-4.snap new file mode 100644 index 00000000..e21e3002 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__scripts-4.snap @@ -0,0 +1,42 @@ +--- +source: rojo-test/src/serve_test.rs +expression: read_result +--- +instances: + id-2: + Id: id-2 + Parent: ~ + Name: scripts + ClassName: Folder + Properties: {} + Children: + - id-3 + - id-4 + Metadata: + ignoreUnknownInstances: false + id-3: + Id: id-3 + Parent: id-2 + Name: bar + ClassName: Script + Properties: + Source: + Type: String + Value: "-- Hello, from bar!" + Children: [] + Metadata: + ignoreUnknownInstances: false + id-4: + Id: id-4 + Parent: id-2 + Name: foo + ClassName: ModuleScript + Properties: + Source: + Type: String + Value: Updated foo! + Children: [] + Metadata: + ignoreUnknownInstances: false +messageCursor: 1 +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts.snap b/rojo-test/serve-test-snapshots/serve_test__scripts.snap new file mode 100644 index 00000000..cb619dc5 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__scripts.snap @@ -0,0 +1,9 @@ +--- +source: rojo-test/src/serve_test.rs +expression: info +--- +expectedPlaceIds: ~ +protocolVersion: 3 +rootInstanceId: id-2 +serverVersion: 0.6.0-dev +sessionId: id-1 diff --git a/rojo-test/serve-tests/scripts/bar.server.lua b/rojo-test/serve-tests/scripts/bar.server.lua new file mode 100644 index 00000000..ae98ab69 --- /dev/null +++ b/rojo-test/serve-tests/scripts/bar.server.lua @@ -0,0 +1 @@ +-- Hello, from bar! \ No newline at end of file diff --git a/rojo-test/serve-tests/scripts/foo.lua b/rojo-test/serve-tests/scripts/foo.lua new file mode 100644 index 00000000..462ac790 --- /dev/null +++ b/rojo-test/serve-tests/scripts/foo.lua @@ -0,0 +1 @@ +-- Hello, from foo! \ No newline at end of file diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index e488cebc..bdcc65ba 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -2,7 +2,7 @@ use std::fs; use insta::assert_yaml_snapshot; -use crate::serve_util::run_serve_test; +use crate::serve_util::{intern_read_response, run_serve_test}; #[test] fn empty() { @@ -12,15 +12,37 @@ fn empty() { let root_id = info.root_instance_id; let info = redactions.redacted_yaml(info); - assert_yaml_snapshot!(info); let read_result = session.get_api_read(root_id).unwrap(); - - redactions.intern_iter(read_result.instances.keys().copied()); - + intern_read_response(&mut redactions, &read_result, root_id); let read_result = redactions.redacted_yaml(read_result); + assert_yaml_snapshot!(read_result); + }); +} +#[test] +fn scripts() { + run_serve_test("scripts", |session, mut redactions| { + let info = session.get_api_rojo().unwrap(); + let root_id = info.root_instance_id; + + let info = redactions.redacted_yaml(info); + assert_yaml_snapshot!(info); + + let read_result = session.get_api_read(root_id).unwrap(); + intern_read_response(&mut redactions, &read_result, root_id); + let read_result = redactions.redacted_yaml(read_result); + assert_yaml_snapshot!(read_result); + + fs::write(session.path().join("foo.lua"), "Updated foo!").unwrap(); + + let subscribe_result = session.get_api_subscribe(0).unwrap(); + let subscribe_result = redactions.redacted_yaml(subscribe_result); + assert_yaml_snapshot!(subscribe_result); + + let read_result = session.get_api_read(root_id).unwrap(); + let read_result = redactions.redacted_yaml(read_result); assert_yaml_snapshot!(read_result); }); } diff --git a/rojo-test/src/serve_util.rs b/rojo-test/src/serve_util.rs index 97e307ab..e62e63ba 100644 --- a/rojo-test/src/serve_util.rs +++ b/rojo-test/src/serve_util.rs @@ -22,6 +22,7 @@ pub fn run_serve_test(test_name: &str, callback: impl FnOnce(TestServeSession, R let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("serve-test-snapshots"); settings.set_snapshot_path(snapshot_path); + settings.set_sort_maps(true); let mut redactions = RedactionMap::new(); @@ -34,6 +35,22 @@ pub fn run_serve_test(test_name: &str, callback: impl FnOnce(TestServeSession, R settings.bind(move || callback(session, redactions)); } +/// Intern the response to Rojo's read API, doing traversal in a deterministic +/// order. +pub fn intern_read_response( + redactions: &mut RedactionMap, + response: &ReadResponse, + root_id: RbxId, +) { + redactions.intern(root_id); + + let root_instance = response.instances.get(&root_id).unwrap(); + + for &child_id in root_instance.children.iter() { + intern_read_response(redactions, response, child_id); + } +} + fn get_port_number() -> usize { static NEXT_PORT_NUMBER: AtomicUsize = AtomicUsize::new(35103); From cc68d57f1127c4d4640f009eb2aedbb6e4ef29c3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 16 Oct 2019 17:03:21 -0700 Subject: [PATCH 0837/1504] Remove insta dependency for rojo-insta-ext --- Cargo.lock | 1 - rojo-insta-ext/Cargo.toml | 4 ---- 2 files changed, 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7251f716..02fb2029 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1599,7 +1599,6 @@ dependencies = [ name = "rojo-insta-ext" version = "0.1.0" dependencies = [ - "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/rojo-insta-ext/Cargo.toml b/rojo-insta-ext/Cargo.toml index f072ab91..4471c4ac 100644 --- a/rojo-insta-ext/Cargo.toml +++ b/rojo-insta-ext/Cargo.toml @@ -8,7 +8,3 @@ publish = false [dependencies] serde = "1.0.99" serde_yaml = "0.8.9" - -[dependencies.insta] -version = "0.11.0" -features = ["redactions"] From 3880708e1d49f65686c3884173a8036c8cf04216 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 16 Oct 2019 17:36:13 -0700 Subject: [PATCH 0838/1504] Improve serve snapshot test ergonomics --- Cargo.lock | 1 + rojo-test/Cargo.toml | 2 ++ rojo-test/src/lib.rs | 4 +++- rojo-test/src/serve_test.rs | 47 +++++++++++-------------------------- rojo-test/src/serve_util.rs | 37 ++++++++++++++++++++--------- 5 files changed, 46 insertions(+), 45 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 02fb2029..3175ce60 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1617,6 +1617,7 @@ dependencies = [ "rojo-insta-ext 0.1.0", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index 173cbb16..366dfe8c 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -13,8 +13,10 @@ rbx_dom_weak = "1.9.0" reqwest = "0.9.20" serde = "1.0.99" serde_json = "1.0.40" +serde_yaml = "0.8.9" tempfile = "3.1.0" walkdir = "2.2.9" + rojo-insta-ext = { path = "../rojo-insta-ext" } # We execute Rojo via std::process::Command, so depend on it so it's built! diff --git a/rojo-test/src/lib.rs b/rojo-test/src/lib.rs index 218b3483..29258e3b 100644 --- a/rojo-test/src/lib.rs +++ b/rojo-test/src/lib.rs @@ -1,6 +1,8 @@ #![cfg(test)] +#[macro_use] +mod serve_util; + mod build_test; mod serve_test; -mod serve_util; mod util; diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index bdcc65ba..82a8a539 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -2,22 +2,18 @@ use std::fs; use insta::assert_yaml_snapshot; -use crate::serve_util::{intern_read_response, run_serve_test}; +use crate::serve_util::{run_serve_test, InternAndRedact}; #[test] fn empty() { run_serve_test("empty", |session, mut redactions| { let info = session.get_api_rojo().unwrap(); - let root_id = info.root_instance_id; - let info = redactions.redacted_yaml(info); - assert_yaml_snapshot!(info); + assert_yaml_snapshot!(redactions.redacted_yaml(info)); - let read_result = session.get_api_read(root_id).unwrap(); - intern_read_response(&mut redactions, &read_result, root_id); - let read_result = redactions.redacted_yaml(read_result); - assert_yaml_snapshot!(read_result); + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!(read_response.intern_and_redact(&mut redactions, root_id)); }); } @@ -27,23 +23,18 @@ fn scripts() { let info = session.get_api_rojo().unwrap(); let root_id = info.root_instance_id; - let info = redactions.redacted_yaml(info); - assert_yaml_snapshot!(info); + assert_yaml_snapshot!(redactions.redacted_yaml(info)); - let read_result = session.get_api_read(root_id).unwrap(); - intern_read_response(&mut redactions, &read_result, root_id); - let read_result = redactions.redacted_yaml(read_result); - assert_yaml_snapshot!(read_result); + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!(read_response.intern_and_redact(&mut redactions, root_id)); fs::write(session.path().join("foo.lua"), "Updated foo!").unwrap(); - let subscribe_result = session.get_api_subscribe(0).unwrap(); - let subscribe_result = redactions.redacted_yaml(subscribe_result); - assert_yaml_snapshot!(subscribe_result); + let subscribe_response = session.get_api_subscribe(0).unwrap(); + assert_yaml_snapshot!(redactions.redacted_yaml(subscribe_response)); - let read_result = session.get_api_read(root_id).unwrap(); - let read_result = redactions.redacted_yaml(read_result); - assert_yaml_snapshot!(read_result); + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!(read_response.intern_and_redact(&mut redactions, root_id)); }); } @@ -51,25 +42,15 @@ fn scripts() { fn just_txt() { run_serve_test("just-txt.txt", |session, mut redactions| { let info = session.get_api_rojo().unwrap(); - let root_id = info.root_instance_id; - let info = redactions.redacted_yaml(info); - assert_yaml_snapshot!(info); + assert_yaml_snapshot!(redactions.redacted_yaml(info)); - let read_result = session.get_api_read(root_id).unwrap(); - redactions.intern_iter(read_result.instances.keys().copied()); - let read_result = redactions.redacted_yaml(read_result); - - assert_yaml_snapshot!(read_result); + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!(read_response.intern_and_redact(&mut redactions, root_id)); fs::write(session.path(), "Changed content!").unwrap(); // TODO: Directly served files currently don't trigger changed events! - - // let subscribe_result = session.get_api_subscribe(0).unwrap(); - // let subscribe_result = redactions.redacted_yaml(subscribe_result); - - // assert_yaml_snapshot!(subscribe_result); }); } diff --git a/rojo-test/src/serve_util.rs b/rojo-test/src/serve_util.rs index e62e63ba..95695053 100644 --- a/rojo-test/src/serve_util.rs +++ b/rojo-test/src/serve_util.rs @@ -6,6 +6,7 @@ use std::{ }; use rbx_dom_weak::RbxId; +use serde::Serialize; use tempfile::{tempdir, TempDir}; use librojo::web_interface::{ReadResponse, ServerInfoResponse, SubscribeResponse}; @@ -35,19 +36,33 @@ pub fn run_serve_test(test_name: &str, callback: impl FnOnce(TestServeSession, R settings.bind(move || callback(session, redactions)); } -/// Intern the response to Rojo's read API, doing traversal in a deterministic -/// order. -pub fn intern_read_response( - redactions: &mut RedactionMap, - response: &ReadResponse, - root_id: RbxId, -) { - redactions.intern(root_id); +pub trait Internable { + fn intern(&self, redactions: &mut RedactionMap, extra: T); +} - let root_instance = response.instances.get(&root_id).unwrap(); +impl Internable for ReadResponse<'_> { + fn intern(&self, redactions: &mut RedactionMap, root_id: RbxId) { + redactions.intern(root_id); - for &child_id in root_instance.children.iter() { - intern_read_response(redactions, response, child_id); + let root_instance = self.instances.get(&root_id).unwrap(); + + for &child_id in root_instance.children.iter() { + self.intern(redactions, child_id); + } + } +} + +pub trait InternAndRedact { + fn intern_and_redact(&self, redactions: &mut RedactionMap, extra: T) -> serde_yaml::Value; +} + +impl InternAndRedact for I +where + I: Serialize + Internable, +{ + fn intern_and_redact(&self, redactions: &mut RedactionMap, extra: T) -> serde_yaml::Value { + self.intern(redactions, extra); + redactions.redacted_yaml(self) } } From a77495c5620d7b1b93e3f1031e0fd063d5551d74 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 16 Oct 2019 17:41:21 -0700 Subject: [PATCH 0839/1504] Add names to serve test snapshots --- ...mpty-2.snap => serve_test__empty_all.snap} | 2 +- ...empty.snap => serve_test__empty_info.snap} | 2 +- ...t-2.snap => serve_test__just_txt_all.snap} | 4 +-- ...ts.snap => serve_test__just_txt_info.snap} | 2 +- ...-4.snap => serve_test__scripts_all-2.snap} | 2 +- ...ts-2.snap => serve_test__scripts_all.snap} | 2 +- ...txt.snap => serve_test__scripts_info.snap} | 2 +- ...nap => serve_test__scripts_subscribe.snap} | 2 +- .../{just-txt.txt => just_txt.txt} | 0 rojo-test/src/serve_test.rs | 33 ++++++++++++++----- 10 files changed, 33 insertions(+), 18 deletions(-) rename rojo-test/serve-test-snapshots/{serve_test__empty-2.snap => serve_test__empty_all.snap} (77%) rename rojo-test/serve-test-snapshots/{serve_test__empty.snap => serve_test__empty_info.snap} (77%) rename rojo-test/serve-test-snapshots/{serve_test__just_txt-2.snap => serve_test__just_txt_all.snap} (76%) rename rojo-test/serve-test-snapshots/{serve_test__scripts.snap => serve_test__just_txt_info.snap} (77%) rename rojo-test/serve-test-snapshots/{serve_test__scripts-4.snap => serve_test__scripts_all-2.snap} (90%) rename rojo-test/serve-test-snapshots/{serve_test__scripts-2.snap => serve_test__scripts_all.snap} (91%) rename rojo-test/serve-test-snapshots/{serve_test__just_txt.snap => serve_test__scripts_info.snap} (77%) rename rojo-test/serve-test-snapshots/{serve_test__scripts-3.snap => serve_test__scripts_subscribe.snap} (86%) rename rojo-test/serve-tests/{just-txt.txt => just_txt.txt} (100%) diff --git a/rojo-test/serve-test-snapshots/serve_test__empty-2.snap b/rojo-test/serve-test-snapshots/serve_test__empty_all.snap similarity index 77% rename from rojo-test/serve-test-snapshots/serve_test__empty-2.snap rename to rojo-test/serve-test-snapshots/serve_test__empty_all.snap index 4535414a..d8a33da7 100644 --- a/rojo-test/serve-test-snapshots/serve_test__empty-2.snap +++ b/rojo-test/serve-test-snapshots/serve_test__empty_all.snap @@ -1,6 +1,6 @@ --- source: rojo-test/src/serve_test.rs -expression: read_result +expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: id-2: diff --git a/rojo-test/serve-test-snapshots/serve_test__empty.snap b/rojo-test/serve-test-snapshots/serve_test__empty_info.snap similarity index 77% rename from rojo-test/serve-test-snapshots/serve_test__empty.snap rename to rojo-test/serve-test-snapshots/serve_test__empty_info.snap index cb619dc5..f826d7e7 100644 --- a/rojo-test/serve-test-snapshots/serve_test__empty.snap +++ b/rojo-test/serve-test-snapshots/serve_test__empty_info.snap @@ -1,6 +1,6 @@ --- source: rojo-test/src/serve_test.rs -expression: info +expression: redactions.redacted_yaml(info) --- expectedPlaceIds: ~ protocolVersion: 3 diff --git a/rojo-test/serve-test-snapshots/serve_test__just_txt-2.snap b/rojo-test/serve-test-snapshots/serve_test__just_txt_all.snap similarity index 76% rename from rojo-test/serve-test-snapshots/serve_test__just_txt-2.snap rename to rojo-test/serve-test-snapshots/serve_test__just_txt_all.snap index 541ce33e..fb31572b 100644 --- a/rojo-test/serve-test-snapshots/serve_test__just_txt-2.snap +++ b/rojo-test/serve-test-snapshots/serve_test__just_txt_all.snap @@ -1,12 +1,12 @@ --- source: rojo-test/src/serve_test.rs -expression: read_result +expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: id-2: Id: id-2 Parent: ~ - Name: just-txt + Name: just_txt ClassName: StringValue Properties: Value: diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts.snap b/rojo-test/serve-test-snapshots/serve_test__just_txt_info.snap similarity index 77% rename from rojo-test/serve-test-snapshots/serve_test__scripts.snap rename to rojo-test/serve-test-snapshots/serve_test__just_txt_info.snap index cb619dc5..f826d7e7 100644 --- a/rojo-test/serve-test-snapshots/serve_test__scripts.snap +++ b/rojo-test/serve-test-snapshots/serve_test__just_txt_info.snap @@ -1,6 +1,6 @@ --- source: rojo-test/src/serve_test.rs -expression: info +expression: redactions.redacted_yaml(info) --- expectedPlaceIds: ~ protocolVersion: 3 diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts-4.snap b/rojo-test/serve-test-snapshots/serve_test__scripts_all-2.snap similarity index 90% rename from rojo-test/serve-test-snapshots/serve_test__scripts-4.snap rename to rojo-test/serve-test-snapshots/serve_test__scripts_all-2.snap index e21e3002..d65cca84 100644 --- a/rojo-test/serve-test-snapshots/serve_test__scripts-4.snap +++ b/rojo-test/serve-test-snapshots/serve_test__scripts_all-2.snap @@ -1,6 +1,6 @@ --- source: rojo-test/src/serve_test.rs -expression: read_result +expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: id-2: diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts-2.snap b/rojo-test/serve-test-snapshots/serve_test__scripts_all.snap similarity index 91% rename from rojo-test/serve-test-snapshots/serve_test__scripts-2.snap rename to rojo-test/serve-test-snapshots/serve_test__scripts_all.snap index e012c3b9..e11c4e25 100644 --- a/rojo-test/serve-test-snapshots/serve_test__scripts-2.snap +++ b/rojo-test/serve-test-snapshots/serve_test__scripts_all.snap @@ -1,6 +1,6 @@ --- source: rojo-test/src/serve_test.rs -expression: read_result +expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: id-2: diff --git a/rojo-test/serve-test-snapshots/serve_test__just_txt.snap b/rojo-test/serve-test-snapshots/serve_test__scripts_info.snap similarity index 77% rename from rojo-test/serve-test-snapshots/serve_test__just_txt.snap rename to rojo-test/serve-test-snapshots/serve_test__scripts_info.snap index cb619dc5..f826d7e7 100644 --- a/rojo-test/serve-test-snapshots/serve_test__just_txt.snap +++ b/rojo-test/serve-test-snapshots/serve_test__scripts_info.snap @@ -1,6 +1,6 @@ --- source: rojo-test/src/serve_test.rs -expression: info +expression: redactions.redacted_yaml(info) --- expectedPlaceIds: ~ protocolVersion: 3 diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts-3.snap b/rojo-test/serve-test-snapshots/serve_test__scripts_subscribe.snap similarity index 86% rename from rojo-test/serve-test-snapshots/serve_test__scripts-3.snap rename to rojo-test/serve-test-snapshots/serve_test__scripts_subscribe.snap index 9befdbad..f71ad85b 100644 --- a/rojo-test/serve-test-snapshots/serve_test__scripts-3.snap +++ b/rojo-test/serve-test-snapshots/serve_test__scripts_subscribe.snap @@ -1,6 +1,6 @@ --- source: rojo-test/src/serve_test.rs -expression: subscribe_result +expression: redactions.redacted_yaml(subscribe_response) --- messageCursor: 1 messages: diff --git a/rojo-test/serve-tests/just-txt.txt b/rojo-test/serve-tests/just_txt.txt similarity index 100% rename from rojo-test/serve-tests/just-txt.txt rename to rojo-test/serve-tests/just_txt.txt diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index 82a8a539..7b1c3fc0 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -10,10 +10,13 @@ fn empty() { let info = session.get_api_rojo().unwrap(); let root_id = info.root_instance_id; - assert_yaml_snapshot!(redactions.redacted_yaml(info)); + assert_yaml_snapshot!("empty_info", redactions.redacted_yaml(info)); let read_response = session.get_api_read(root_id).unwrap(); - assert_yaml_snapshot!(read_response.intern_and_redact(&mut redactions, root_id)); + assert_yaml_snapshot!( + "empty_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); }); } @@ -23,31 +26,43 @@ fn scripts() { let info = session.get_api_rojo().unwrap(); let root_id = info.root_instance_id; - assert_yaml_snapshot!(redactions.redacted_yaml(info)); + assert_yaml_snapshot!("scripts_info", redactions.redacted_yaml(info)); let read_response = session.get_api_read(root_id).unwrap(); - assert_yaml_snapshot!(read_response.intern_and_redact(&mut redactions, root_id)); + assert_yaml_snapshot!( + "scripts_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); fs::write(session.path().join("foo.lua"), "Updated foo!").unwrap(); let subscribe_response = session.get_api_subscribe(0).unwrap(); - assert_yaml_snapshot!(redactions.redacted_yaml(subscribe_response)); + assert_yaml_snapshot!( + "scripts_subscribe", + redactions.redacted_yaml(subscribe_response) + ); let read_response = session.get_api_read(root_id).unwrap(); - assert_yaml_snapshot!(read_response.intern_and_redact(&mut redactions, root_id)); + assert_yaml_snapshot!( + "scripts_all-2", + read_response.intern_and_redact(&mut redactions, root_id) + ); }); } #[test] fn just_txt() { - run_serve_test("just-txt.txt", |session, mut redactions| { + run_serve_test("just_txt.txt", |session, mut redactions| { let info = session.get_api_rojo().unwrap(); let root_id = info.root_instance_id; - assert_yaml_snapshot!(redactions.redacted_yaml(info)); + assert_yaml_snapshot!("just_txt_info", redactions.redacted_yaml(info)); let read_response = session.get_api_read(root_id).unwrap(); - assert_yaml_snapshot!(read_response.intern_and_redact(&mut redactions, root_id)); + assert_yaml_snapshot!( + "just_txt_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); fs::write(session.path(), "Changed content!").unwrap(); From 64fd2f9cf8f696910f180a3088d59b681fac78d7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 16 Oct 2019 17:54:10 -0700 Subject: [PATCH 0840/1504] Add disabled test for adding a folder, currently failing --- rojo-test/serve-tests/add_folder/.gitkeep | 0 rojo-test/src/serve_test.rs | 32 +++++++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 rojo-test/serve-tests/add_folder/.gitkeep diff --git a/rojo-test/serve-tests/add_folder/.gitkeep b/rojo-test/serve-tests/add_folder/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index 7b1c3fc0..7a322e53 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -69,3 +69,35 @@ fn just_txt() { // TODO: Directly served files currently don't trigger changed events! }); } + +// TODO: Rojo doesn't currently handle files/folders being added. +#[test] +#[ignore] +fn add_folder() { + run_serve_test("add_folder", |session, mut redactions| { + let info = session.get_api_rojo().unwrap(); + let root_id = info.root_instance_id; + + assert_yaml_snapshot!("add_folder_info", redactions.redacted_yaml(info)); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "add_folder_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); + + fs::create_dir(session.path().join("my-new-folder")).unwrap(); + + let subscribe_response = session.get_api_subscribe(0).unwrap(); + assert_yaml_snapshot!( + "add_folder_subscribe", + redactions.redacted_yaml(subscribe_response) + ); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "add_folder_all-2", + read_response.intern_and_redact(&mut redactions, root_id) + ); + }); +} From a5fdc2a9cc3e693e2345d373616fccd1cec9bb2b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 16 Oct 2019 18:28:11 -0700 Subject: [PATCH 0841/1504] Add logging, fix flipped condition on child add --- src/vfs/vfs.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/vfs/vfs.rs b/src/vfs/vfs.rs index ee3ee177..5e0f45ee 100644 --- a/src/vfs/vfs.rs +++ b/src/vfs/vfs.rs @@ -167,6 +167,11 @@ impl Vfs { let path = path.as_ref(); if !Self::would_be_resident(&data, path) { + log::trace!( + "Path would not be resident, skipping change: {}", + path.display() + ); + return Ok(()); } @@ -205,6 +210,7 @@ impl Vfs { } } None => { + log::trace!("Inserting new path {}", path.display()); data.insert(path.to_path_buf(), VfsItem::new_from_type(new_type, path)); } } @@ -266,7 +272,7 @@ impl Vfs { if let Some(parent) = path.parent() { if let Some(VfsItem::Directory(dir)) = data.get(parent) { - return !dir.children_enumerated; + return dir.children_enumerated; } } @@ -400,6 +406,7 @@ impl VfsEntry { /// Internal structure describing potentially partially-resident files and /// folders in the `Vfs`. +#[derive(Debug)] pub enum VfsItem { File(VfsFile), Directory(VfsDirectory), @@ -427,11 +434,13 @@ impl VfsItem { } } +#[derive(Debug)] pub struct VfsFile { pub(super) path: PathBuf, pub(super) contents: Option>>, } +#[derive(Debug)] pub struct VfsDirectory { pub(super) path: PathBuf, pub(super) children_enumerated: bool, From 7c0aa4505751a75eef0d5ee2a394ec6abe15cefe Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 16 Oct 2019 18:28:38 -0700 Subject: [PATCH 0842/1504] Add support for adding new instances, very pedantically --- src/change_processor.rs | 114 ++++++++++++++++++++++++---------------- 1 file changed, 68 insertions(+), 46 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index 5e0d3220..3e89ae5d 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -7,6 +7,7 @@ use std::sync::{Arc, Mutex}; use crossbeam_channel::{select, Receiver, Sender}; use jod_thread::JoinHandle; +use rbx_dom_weak::RbxId; use crate::{ message_queue::MessageQueue, @@ -69,56 +70,24 @@ impl ChangeProcessor { match event { VfsEvent::Created(path) | VfsEvent::Modified(path) | VfsEvent::Removed(path) => { - let affected_ids = tree.get_ids_at_path(&path).to_vec(); + let mut current_path = path.as_path(); + let affected_ids = loop { + let ids = tree.get_ids_at_path(¤t_path); - if affected_ids.len() == 0 { - log::info!("No instances were affected by this change."); - continue; - } + log::trace!("Path {} affects IDs {:?}", current_path.display(), ids); - for id in affected_ids { - let metadata = tree.get_metadata(id) - .expect("metadata missing for instance present in tree"); + if !ids.is_empty() { + break ids.to_vec(); + } - let instigating_source = match &metadata.instigating_source { - Some(path) => path, - None => { - log::warn!("Instance {} did not have an instigating source, but was considered for an update.", id); - log::warn!("This is a Rojo bug. Please file an issue!"); - continue; - } - }; + log::trace!("Trying parent path..."); + match current_path.parent() { + Some(parent) => current_path = parent, + None => break Vec::new(), + } + }; - let snapshot = match instigating_source { - InstigatingSource::Path(path) => { - let entry = vfs - .get(path) - .expect("could not get instigating path from filesystem"); - - // TODO: Use persisted snapshot - // context struct instead of - // recreating it every time. - let snapshot = snapshot_from_vfs(&mut InstanceSnapshotContext::default(), &vfs, &entry) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); - - snapshot - } - InstigatingSource::ProjectNode(_, _) => { - log::warn!("Instance {} had an instigating source that was a project node, which is not yet supported.", id); - continue; - } - }; - - log::trace!("Computed snapshot: {:#?}", snapshot); - - let patch_set = compute_patch_set(&snapshot, &tree, id); - let applied_patch_set = apply_patch_set(&mut tree, patch_set); - - log::trace!("Applied patch: {:#?}", applied_patch_set); - - applied_patches.push(applied_patch_set); - } + update_affected_instances(&mut tree, &vfs, &mut applied_patches, &affected_ids) } } @@ -143,3 +112,56 @@ impl Drop for ChangeProcessor { let _ = self.shutdown_sender.send(()); } } + +fn update_affected_instances( + tree: &mut RojoTree, + vfs: &Vfs, + applied_patches: &mut Vec, + affected_ids: &[RbxId], +) { + for &id in affected_ids { + let metadata = tree + .get_metadata(id) + .expect("metadata missing for instance present in tree"); + + let instigating_source = match &metadata.instigating_source { + Some(path) => path, + None => { + log::warn!("Instance {} did not have an instigating source, but was considered for an update.", id); + log::warn!("This is a Rojo bug. Please file an issue!"); + continue; + } + }; + + let snapshot = match instigating_source { + InstigatingSource::Path(path) => { + let entry = vfs + .get(path) + .expect("could not get instigating path from filesystem"); + + // TODO: Use persisted snapshot + // context struct instead of + // recreating it every time. + let snapshot = + snapshot_from_vfs(&mut InstanceSnapshotContext::default(), &vfs, &entry) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + snapshot + } + InstigatingSource::ProjectNode(_, _) => { + log::warn!("Instance {} had an instigating source that was a project node, which is not yet supported.", id); + continue; + } + }; + + log::trace!("Computed snapshot: {:#?}", snapshot); + + let patch_set = compute_patch_set(&snapshot, &tree, id); + let applied_patch_set = apply_patch_set(tree, patch_set); + + log::trace!("Applied patch: {:#?}", applied_patch_set); + + applied_patches.push(applied_patch_set); + } +} From 51dcfbab7513152cc54f16b7c25db40dbcc8a073 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 16 Oct 2019 19:32:10 -0700 Subject: [PATCH 0843/1504] Fix rustfmt on benches --- benches/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/benches/build.rs b/benches/build.rs index e502de1e..5b3a918d 100644 --- a/benches/build.rs +++ b/benches/build.rs @@ -1,4 +1,4 @@ -use std::path::{Path}; +use std::path::Path; use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use tempfile::{tempdir, TempDir}; From 85e30cc9688e977d8fc4a469bd36841d27795c94 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 17 Oct 2019 13:46:45 -0700 Subject: [PATCH 0844/1504] Write tests and ensure adding instances works --- rojo-insta-ext/src/redaction_map.rs | 10 ++ .../serve_test__add_folder_all-2.snap | 26 +++++ .../serve_test__add_folder_all.snap | 16 +++ .../serve_test__add_folder_info.snap | 9 ++ .../serve_test__add_folder_subscribe.snap | 19 ++++ rojo-test/src/internable.rs | 104 ++++++++++++++++++ rojo-test/src/lib.rs | 5 +- rojo-test/src/serve_test.rs | 8 +- rojo-test/src/serve_util.rs | 79 +++++++------ 9 files changed, 227 insertions(+), 49 deletions(-) create mode 100644 rojo-test/serve-test-snapshots/serve_test__add_folder_all-2.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__add_folder_all.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__add_folder_info.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap create mode 100644 rojo-test/src/internable.rs diff --git a/rojo-insta-ext/src/redaction_map.rs b/rojo-insta-ext/src/redaction_map.rs index dce3cb5d..22574704 100644 --- a/rojo-insta-ext/src/redaction_map.rs +++ b/rojo-insta-ext/src/redaction_map.rs @@ -18,6 +18,16 @@ impl RedactionMap { } } + pub fn get_redacted_value(&self, id: impl ToString) -> Option { + let id = id.to_string(); + + if self.ids.contains_key(&id) { + Some(id) + } else { + None + } + } + pub fn intern(&mut self, id: impl ToString) { let last_id = &mut self.last_id; diff --git a/rojo-test/serve-test-snapshots/serve_test__add_folder_all-2.snap b/rojo-test/serve-test-snapshots/serve_test__add_folder_all-2.snap new file mode 100644 index 00000000..94948cf8 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__add_folder_all-2.snap @@ -0,0 +1,26 @@ +--- +source: rojo-test/src/serve_test.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Id: id-2 + Parent: ~ + Name: add_folder + ClassName: Folder + Properties: {} + Children: + - id-3 + Metadata: + ignoreUnknownInstances: false + id-3: + Id: id-3 + Parent: id-2 + Name: my-new-folder + ClassName: Folder + Properties: {} + Children: [] + Metadata: + ignoreUnknownInstances: false +messageCursor: 1 +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__add_folder_all.snap b/rojo-test/serve-test-snapshots/serve_test__add_folder_all.snap new file mode 100644 index 00000000..03362f41 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__add_folder_all.snap @@ -0,0 +1,16 @@ +--- +source: rojo-test/src/serve_test.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Id: id-2 + Parent: ~ + Name: add_folder + ClassName: Folder + Properties: {} + Children: [] + Metadata: + ignoreUnknownInstances: false +messageCursor: 0 +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__add_folder_info.snap b/rojo-test/serve-test-snapshots/serve_test__add_folder_info.snap new file mode 100644 index 00000000..f826d7e7 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__add_folder_info.snap @@ -0,0 +1,9 @@ +--- +source: rojo-test/src/serve_test.rs +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +protocolVersion: 3 +rootInstanceId: id-2 +serverVersion: 0.6.0-dev +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap b/rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap new file mode 100644 index 00000000..bfdfeadf --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap @@ -0,0 +1,19 @@ +--- +source: rojo-test/src/serve_test.rs +expression: "subscribe_response.intern_and_redact(&mut redactions, ())" +--- +messageCursor: 1 +messages: + - removedInstances: [] + addedInstances: + id-3: + Id: id-3 + Parent: id-2 + Name: my-new-folder + ClassName: Folder + Properties: {} + Children: [] + Metadata: + ignoreUnknownInstances: false + updatedInstances: [] +sessionId: id-1 diff --git a/rojo-test/src/internable.rs b/rojo-test/src/internable.rs new file mode 100644 index 00000000..9c1cbb57 --- /dev/null +++ b/rojo-test/src/internable.rs @@ -0,0 +1,104 @@ +use std::collections::HashMap; + +use rbx_dom_weak::RbxId; +use serde::Serialize; + +use librojo::web_interface::{Instance, InstanceUpdate, ReadResponse, SubscribeResponse}; +use rojo_insta_ext::RedactionMap; + +/// A convenience method to store all of the redactable data from a piece of +/// data, then immediately redact it and return a serde_yaml Value. +pub trait InternAndRedact { + fn intern_and_redact(&self, redactions: &mut RedactionMap, extra: T) -> serde_yaml::Value; +} + +impl InternAndRedact for I +where + I: Serialize + Internable, +{ + fn intern_and_redact(&self, redactions: &mut RedactionMap, extra: T) -> serde_yaml::Value { + self.intern(redactions, extra); + redactions.redacted_yaml(self) + } +} + +/// A trait to describe how to discover redactable data from an type. +/// +/// The 'extra' parameter is a kludge to support types like Instance or +/// ReadResponse that need some additional information in order to be +/// deterministic. +pub trait Internable { + fn intern(&self, redactions: &mut RedactionMap, extra: T); +} + +impl Internable for ReadResponse<'_> { + fn intern(&self, redactions: &mut RedactionMap, root_id: RbxId) { + redactions.intern(root_id); + + let root_instance = self.instances.get(&root_id).unwrap(); + + for &child_id in root_instance.children.iter() { + self.intern(redactions, child_id); + } + } +} + +impl<'a> Internable<&'a HashMap>> for Instance<'a> { + fn intern( + &self, + redactions: &mut RedactionMap, + other_instances: &HashMap>, + ) { + redactions.intern(self.id); + + for child_id in self.children.iter() { + let child = &other_instances[child_id]; + child.intern(redactions, other_instances); + } + } +} + +impl Internable<()> for SubscribeResponse<'_> { + fn intern(&self, redactions: &mut RedactionMap, _extra: ()) { + for message in &self.messages { + intern_instance_updates(redactions, &message.updated_instances); + intern_instance_additions(redactions, &message.added_instances); + } + } +} + +fn intern_instance_updates(redactions: &mut RedactionMap, updates: &[InstanceUpdate]) { + for update in updates { + redactions.intern(update.id); + } +} + +fn intern_instance_additions( + redactions: &mut RedactionMap, + additions: &HashMap>, +) { + // This method redacts in a deterministic order from a HashMap by collecting + // all of the instances that are direct children of instances we've already + // interned. + let mut added_roots = Vec::new(); + + for (id, added) in additions { + let parent_id = added.parent.unwrap(); + let parent_redacted = redactions.get_redacted_value(parent_id); + + // Here, we assume that instances are only added to other instances that + // we've already interned. If that's not true, then we'll have some + // dangling unredacted IDs. + if let Some(parent_redacted) = parent_redacted { + added_roots.push((id, parent_redacted)); + } + } + + // Sort the input by the redacted key, which should match the traversal + // order we need for the tree. + added_roots.sort_unstable_by(|a, b| a.1.cmp(&b.1)); + + for (root_id, _redacted_id) in added_roots { + additions[root_id].intern(redactions, additions); + } +} diff --git a/rojo-test/src/lib.rs b/rojo-test/src/lib.rs index 29258e3b..cd4e7461 100644 --- a/rojo-test/src/lib.rs +++ b/rojo-test/src/lib.rs @@ -1,8 +1,7 @@ #![cfg(test)] -#[macro_use] -mod serve_util; - mod build_test; +mod internable; mod serve_test; +mod serve_util; mod util; diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index 7a322e53..cbb0167f 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -2,7 +2,7 @@ use std::fs; use insta::assert_yaml_snapshot; -use crate::serve_util::{run_serve_test, InternAndRedact}; +use crate::{internable::InternAndRedact, serve_util::run_serve_test}; #[test] fn empty() { @@ -39,7 +39,7 @@ fn scripts() { let subscribe_response = session.get_api_subscribe(0).unwrap(); assert_yaml_snapshot!( "scripts_subscribe", - redactions.redacted_yaml(subscribe_response) + subscribe_response.intern_and_redact(&mut redactions, ()) ); let read_response = session.get_api_read(root_id).unwrap(); @@ -70,9 +70,7 @@ fn just_txt() { }); } -// TODO: Rojo doesn't currently handle files/folders being added. #[test] -#[ignore] fn add_folder() { run_serve_test("add_folder", |session, mut redactions| { let info = session.get_api_rojo().unwrap(); @@ -91,7 +89,7 @@ fn add_folder() { let subscribe_response = session.get_api_subscribe(0).unwrap(); assert_yaml_snapshot!( "add_folder_subscribe", - redactions.redacted_yaml(subscribe_response) + subscribe_response.intern_and_redact(&mut redactions, ()) ); let read_response = session.get_api_read(root_id).unwrap(); diff --git a/rojo-test/src/serve_util.rs b/rojo-test/src/serve_util.rs index 95695053..c0c67c1f 100644 --- a/rojo-test/src/serve_util.rs +++ b/rojo-test/src/serve_util.rs @@ -3,10 +3,12 @@ use std::{ path::{Path, PathBuf}, process::Command, sync::atomic::{AtomicUsize, Ordering}, + thread, + time::Duration, }; use rbx_dom_weak::RbxId; -use serde::Serialize; + use tempfile::{tempdir, TempDir}; use librojo::web_interface::{ReadResponse, ServerInfoResponse, SubscribeResponse}; @@ -16,6 +18,13 @@ use crate::util::{ copy_recursive, get_rojo_path, get_serve_tests_path, get_working_dir_path, KillOnDrop, }; +/// Convenience method to run a `rojo serve` test. +/// +/// Test projects should be defined in the `serve-tests` folder; their filename +/// should be given as the first parameter. +/// +/// The passed in callback is where the actual test body should go. Setup and +/// cleanup happens automatically. pub fn run_serve_test(test_name: &str, callback: impl FnOnce(TestServeSession, RedactionMap)) { let _ = env_logger::try_init(); @@ -36,42 +45,7 @@ pub fn run_serve_test(test_name: &str, callback: impl FnOnce(TestServeSession, R settings.bind(move || callback(session, redactions)); } -pub trait Internable { - fn intern(&self, redactions: &mut RedactionMap, extra: T); -} - -impl Internable for ReadResponse<'_> { - fn intern(&self, redactions: &mut RedactionMap, root_id: RbxId) { - redactions.intern(root_id); - - let root_instance = self.instances.get(&root_id).unwrap(); - - for &child_id in root_instance.children.iter() { - self.intern(redactions, child_id); - } - } -} - -pub trait InternAndRedact { - fn intern_and_redact(&self, redactions: &mut RedactionMap, extra: T) -> serde_yaml::Value; -} - -impl InternAndRedact for I -where - I: Serialize + Internable, -{ - fn intern_and_redact(&self, redactions: &mut RedactionMap, extra: T) -> serde_yaml::Value { - self.intern(redactions, extra); - redactions.redacted_yaml(self) - } -} - -fn get_port_number() -> usize { - static NEXT_PORT_NUMBER: AtomicUsize = AtomicUsize::new(35103); - - NEXT_PORT_NUMBER.fetch_add(1, Ordering::SeqCst) -} - +/// Represents a running Rojo serve session running in a temporary directory. pub struct TestServeSession { // Drop order is important here: we want the process to be killed before the // directory it's operating on is destroyed. @@ -129,19 +103,28 @@ impl TestServeSession { &self.project_path } + /// Waits for the `rojo serve` server to come online with expontential + /// backoff. pub fn wait_to_come_online(&mut self) -> ServerInfoResponse { - loop { + const BASE_DURATION_MS: f32 = 30.0; + const EXP_BACKOFF_FACTOR: f32 = 1.3; + const MAX_TRIES: u32 = 5; + + for i in 1..=MAX_TRIES { match self.rojo_process.0.try_wait() { Ok(Some(status)) => panic!("Rojo process exited with status {}", status), - Ok(None) => { /* process is still running */ } + Ok(None) => { /* The process is still running, as expected */ } Err(err) => panic!("Failed to wait on Rojo process: {}", err), } let info = match self.get_api_rojo() { Ok(info) => info, Err(err) => { - log::debug!("Server error, retrying: {}", err); - std::thread::sleep(std::time::Duration::from_millis(30)); + let retry_time_ms = BASE_DURATION_MS * (i as f32).powf(EXP_BACKOFF_FACTOR); + let retry_time = Duration::from_millis(retry_time_ms as u64); + + log::info!("Server error, retrying in {:?}: {}", retry_time, err); + thread::sleep(retry_time); continue; } }; @@ -150,6 +133,8 @@ impl TestServeSession { return info; } + + panic!("Rojo server did not respond after {} tries.", MAX_TRIES); } pub fn get_api_rojo(&self) -> Result { @@ -175,3 +160,15 @@ impl TestServeSession { reqwest::get(&url)?.json() } } + +/// Probably-okay way to generate random enough port numbers for running the +/// Rojo live server. +/// +/// If this method ends up having problems, we should add an option for Rojo to +/// use a random port chosen by the operating system and figure out a good way +/// to get that port back to the test CLI. +fn get_port_number() -> usize { + static NEXT_PORT_NUMBER: AtomicUsize = AtomicUsize::new(35103); + + NEXT_PORT_NUMBER.fetch_add(1, Ordering::SeqCst) +} From e55b72f73f879c299c7aec4ef49497ee661f6026 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 17 Oct 2019 16:01:03 -0700 Subject: [PATCH 0845/1504] rojo-test: Move settings closer to where settings are applied --- rojo-test/src/serve_util.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/rojo-test/src/serve_util.rs b/rojo-test/src/serve_util.rs index c0c67c1f..8ea23800 100644 --- a/rojo-test/src/serve_util.rs +++ b/rojo-test/src/serve_util.rs @@ -28,12 +28,6 @@ use crate::util::{ pub fn run_serve_test(test_name: &str, callback: impl FnOnce(TestServeSession, RedactionMap)) { let _ = env_logger::try_init(); - let mut settings = insta::Settings::new(); - - let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("serve-test-snapshots"); - settings.set_snapshot_path(snapshot_path); - settings.set_sort_maps(true); - let mut redactions = RedactionMap::new(); let mut session = TestServeSession::new(test_name); @@ -42,6 +36,11 @@ pub fn run_serve_test(test_name: &str, callback: impl FnOnce(TestServeSession, R redactions.intern(info.session_id); redactions.intern(info.root_instance_id); + let mut settings = insta::Settings::new(); + + let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("serve-test-snapshots"); + settings.set_snapshot_path(snapshot_path); + settings.set_sort_maps(true); settings.bind(move || callback(session, redactions)); } From e2e92096558cbbb25ab6caafa816f302c2bf8c9b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 17 Oct 2019 16:03:21 -0700 Subject: [PATCH 0846/1504] rojo-test: Add disabled test for moving big folder of stuff --- .../serve-tests/move_folder_of_stuff/.gitkeep | 0 rojo-test/src/serve_test.rs | 48 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 rojo-test/serve-tests/move_folder_of_stuff/.gitkeep diff --git a/rojo-test/serve-tests/move_folder_of_stuff/.gitkeep b/rojo-test/serve-tests/move_folder_of_stuff/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index cbb0167f..e2335838 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -1,6 +1,7 @@ use std::fs; use insta::assert_yaml_snapshot; +use tempfile::tempdir; use crate::{internable::InternAndRedact, serve_util::run_serve_test}; @@ -99,3 +100,50 @@ fn add_folder() { ); }); } + +#[test] +#[ignore] +fn move_folder_of_stuff() { + run_serve_test("move_folder_of_stuff", |session, mut redactions| { + let info = session.get_api_rojo().unwrap(); + let root_id = info.root_instance_id; + + assert_yaml_snapshot!("move_folder_of_stuff_info", redactions.redacted_yaml(info)); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "move_folder_of_stuff_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); + + // Create a directory full of stuff we can move in + let src_dir = tempdir().unwrap(); + let stuff_path = src_dir.path().join("new-stuff"); + + fs::create_dir(&stuff_path).unwrap(); + + // Make a bunch of random files in our stuff folder + for i in 0..10 { + let file_name = stuff_path.join(format!("{}.txt", i)); + let file_contents = format!("File #{}", i); + + fs::write(file_name, file_contents).unwrap(); + } + + // We're hoping that this rename gets picked up as one event. This test + // will fail otherwise. + fs::rename(stuff_path, session.path().join("new-stuff")).unwrap(); + + let subscribe_response = session.get_api_subscribe(0).unwrap(); + assert_yaml_snapshot!( + "move_folder_of_stuff_subscribe", + subscribe_response.intern_and_redact(&mut redactions, ()) + ); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "move_folder_of_stuff_all-2", + read_response.intern_and_redact(&mut redactions, root_id) + ); + }); +} From 559b509a033b389c76b5b02e63ca4a324de8672d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 17 Oct 2019 17:37:49 -0700 Subject: [PATCH 0847/1504] Upgrade to latest rbx-dom --- plugin/modules/rbx-dom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index 6739c42b..5bca08fe 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit 6739c42bebca95fcb3f847b920d5ac2841846d8f +Subproject commit 5bca08fec3f5708a29811dceb11957b92eafe81f From ec614e19125fde45acbe3a2178c68794e6fb930c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 17 Oct 2019 17:48:30 -0700 Subject: [PATCH 0848/1504] Remove last unused warning. Closes #245. --- src/path_map.rs | 41 +---------------------------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/src/path_map.rs b/src/path_map.rs index 9ccf11ea..86f6a02f 100644 --- a/src/path_map.rs +++ b/src/path_map.rs @@ -1,6 +1,6 @@ use std::{ collections::{HashMap, HashSet}, - path::{self, Path, PathBuf}, + path::{Path, PathBuf}, }; use log::warn; @@ -117,45 +117,6 @@ impl PathMap { removed_entries } - /// Traverses the route between `start_path` and `target_path` and returns - /// the path closest to `target_path` in the tree. - /// - /// This is useful when trying to determine what paths need to be marked as - /// altered when a change to a path is registered. Depending on the order of - /// FS events, a file remove event could be followed by that file's - /// directory being removed, in which case we should process that - /// directory's parent. - pub fn descend( - &self, - start_path: impl Into, - target_path: impl AsRef, - ) -> PathBuf { - let start_path = start_path.into(); - let target_path = target_path.as_ref(); - - let relative_path = target_path - .strip_prefix(&start_path) - .expect("target_path did not begin with start_path"); - let mut current_path = start_path; - - for component in relative_path.components() { - match component { - path::Component::Normal(name) => { - let next_path = current_path.join(name); - - if self.nodes.contains_key(&next_path) { - current_path = next_path; - } else { - return current_path; - } - } - _ => unreachable!(), - } - } - - current_path - } - pub fn orphans(&self) -> impl Iterator { self.orphan_paths.iter().map(|item| item.as_ref()) } From 44c94da2d8f7416f23fba716e6149a2bd5f40994 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 17 Oct 2019 18:22:53 -0700 Subject: [PATCH 0849/1504] Fix clippy warnings --- src/auth_cookie.rs | 2 +- src/change_processor.rs | 21 ++++++++++++--------- src/commands/build.rs | 4 ++-- src/commands/serve.rs | 2 +- src/commands/upload.rs | 4 ++-- src/multimap.rs | 4 ++-- src/path_serializer.rs | 2 +- src/project.rs | 6 +++--- src/serve_session.rs | 4 ++-- src/session_id.rs | 3 +++ src/snapshot_middleware/json_model.rs | 2 +- src/snapshot_middleware/lua.rs | 2 ++ src/vfs/mod.rs | 3 +++ src/vfs/real_fetcher.rs | 2 +- src/web/api.rs | 10 ++++------ src/web/interface.rs | 2 +- src/web/ui.rs | 2 +- 17 files changed, 42 insertions(+), 33 deletions(-) diff --git a/src/auth_cookie.rs b/src/auth_cookie.rs index 9d968dd8..83b2ca61 100644 --- a/src/auth_cookie.rs +++ b/src/auth_cookie.rs @@ -13,7 +13,7 @@ pub fn get_auth_cookie() -> Option { let entry: String = cookies.get_value(".ROBLOSECURITY").ok()?; let mut cookie = None; - for kv_pair in entry.split(",") { + for kv_pair in entry.split(',') { let mut pieces = kv_pair.split("::"); if let Some("COOK") = pieces.next() { diff --git a/src/change_processor.rs b/src/change_processor.rs index 3e89ae5d..f6b7fff6 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -52,9 +52,15 @@ impl ChangeProcessor { ) { let vfs_receiver = vfs.change_receiver(); - // Crossbeam's select macro generates code that Clippy doesn't like, and - // Clippy blames us for it. - #[allow(clippy::drop_copy)] + #[allow( + // Crossbeam's select macro generates code that Clippy doesn't like, + // and Clippy blames us for it. + clippy::drop_copy, + + // Crossbeam uses 0 as *const _ and Clippy doesn't like that either, + // but this isn't our fault. + clippy::zero_ptr, + )] loop { select! { recv(vfs_receiver) -> event => { @@ -142,12 +148,9 @@ fn update_affected_instances( // TODO: Use persisted snapshot // context struct instead of // recreating it every time. - let snapshot = - snapshot_from_vfs(&mut InstanceSnapshotContext::default(), &vfs, &entry) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); - - snapshot + snapshot_from_vfs(&mut InstanceSnapshotContext::default(), &vfs, &entry) + .expect("snapshot failed") + .expect("snapshot did not return an instance") } InstigatingSource::ProjectNode(_, _) => { log::warn!("Instance {} had an instigating source that was a project node, which is not yet supported.", id); diff --git a/src/commands/build.rs b/src/commands/build.rs index 54054a96..8f9fed5c 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -81,9 +81,9 @@ pub fn build(options: &BuildOptions) -> Result<(), BuildError> { log::debug!("Hoping to generate file of type {:?}", output_kind); log::trace!("Constructing in-memory filesystem"); - let mut vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); + let vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); - let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut vfs); + let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &vfs); let root_id = tree.get_root_id(); log::trace!("Opening output file for write"); diff --git a/src/commands/serve.rs b/src/commands/serve.rs index bc021e91..26a35b39 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -65,7 +65,7 @@ fn show_start_message(port: u16) -> io::Result<()> { buffer.set_color(ColorSpec::new().set_fg(Some(Color::Green)).set_bold(true))?; writeln!(&mut buffer, "{}", port)?; - writeln!(&mut buffer, "")?; + writeln!(&mut buffer)?; buffer.set_color(&ColorSpec::new())?; write!(&mut buffer, "Visit ")?; diff --git a/src/commands/upload.rs b/src/commands/upload.rs index df6d6a0e..68054591 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -44,9 +44,9 @@ pub fn upload(options: UploadOptions) -> Result<(), UploadError> { .ok_or(UploadError::NeedAuthCookie)?; log::trace!("Constructing in-memory filesystem"); - let mut vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); + let vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); - let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &mut vfs); + let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &vfs); let root_id = tree.get_root_id(); let mut buffer = Vec::new(); diff --git a/src/multimap.rs b/src/multimap.rs index 19708552..02191e6a 100644 --- a/src/multimap.rs +++ b/src/multimap.rs @@ -31,7 +31,7 @@ impl MultiMap { let bucket = self.inner.entry(k).or_default(); for value in &*bucket { - if &*value == &v { + if *value == v { return; } } @@ -49,7 +49,7 @@ impl MultiMap { removed_value = Some(bucket.swap_remove(index)); } - if bucket.len() == 0 { + if bucket.is_empty() { self.inner.remove(k.borrow()); } diff --git a/src/path_serializer.rs b/src/path_serializer.rs index e3212077..a44e636e 100644 --- a/src/path_serializer.rs +++ b/src/path_serializer.rs @@ -91,7 +91,7 @@ where #[derive(Serialize)] struct WithAbsolute<'a>(#[serde(serialize_with = "serialize_absolute")] &'a Path); -pub fn serialize_vec_absolute(paths: &Vec, serializer: S) -> Result +pub fn serialize_vec_absolute(paths: &[T], serializer: S) -> Result where S: Serializer, T: AsRef, diff --git a/src/project.rs b/src/project.rs index fa2e7cc8..e8da842d 100644 --- a/src/project.rs +++ b/src/project.rs @@ -11,10 +11,10 @@ use log::warn; use rbx_dom_weak::{RbxValue, UnresolvedRbxValue}; use serde::{Deserialize, Serialize, Serializer}; -static DEFAULT_PLACE: &'static str = include_str!("../assets/place.project.json"); +static DEFAULT_PLACE: &str = include_str!("../assets/place.project.json"); -pub static PROJECT_FILENAME: &'static str = "default.project.json"; -pub static COMPAT_PROJECT_FILENAME: &'static str = "roblox-project.json"; +pub static PROJECT_FILENAME: &str = "default.project.json"; +pub static COMPAT_PROJECT_FILENAME: &str = "roblox-project.json"; /// SourceProject is the format that users author projects on-disk. Since we /// want to do things like transforming paths to be absolute before handing them diff --git a/src/serve_session.rs b/src/serve_session.rs index cd3865ce..0652a728 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -78,14 +78,14 @@ impl ServeSession { /// The project file is expected to be loaded out-of-band since it's /// currently loaded from the filesystem directly instead of through the /// in-memory filesystem layer. - pub fn new>(mut vfs: Vfs, start_path: P) -> Self { + pub fn new>(vfs: Vfs, start_path: P) -> Self { let start_path = start_path.as_ref(); log::trace!("Starting new ServeSession at path {}", start_path.display(),); let start_time = Instant::now(); - let (root_project, tree) = common_setup::start(start_path, &mut vfs); + let (root_project, tree) = common_setup::start(start_path, &vfs); let session_id = SessionId::new(); let message_queue = MessageQueue::new(); diff --git a/src/session_id.rs b/src/session_id.rs index d178a5b4..06ca1dd2 100644 --- a/src/session_id.rs +++ b/src/session_id.rs @@ -1,3 +1,6 @@ +// Default doesn't make sense for a type whose constructor is random. +#![allow(clippy::new_without_default)] + use std::fmt; use serde::{Deserialize, Serialize}; diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 18aaa53d..8f1203f3 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -36,7 +36,7 @@ impl SnapshotMiddleware for SnapshotJsonModel { serde_json::from_slice(&entry.contents(vfs)?).expect("TODO: Handle serde_json errors"); if let Some(json_name) = &instance.name { - if json_name != &instance_name { + if json_name != instance_name { log::warn!( "Name from JSON model did not match its file name: {}", entry.path().display() diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 2ebb7c2a..cba22156 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -36,6 +36,8 @@ impl SnapshotMiddleware for SnapshotLua { if entry.is_file() { snapshot_lua_file(vfs, entry) } else { + // At this point, our entry is definitely a directory! + if let Some(snapshot) = snapshot_init(context, vfs, entry, "init.lua")? { // An `init.lua` file turns its parent into a ModuleScript Ok(Some(snapshot)) diff --git a/src/vfs/mod.rs b/src/vfs/mod.rs index 32b48f0b..34a14a3d 100644 --- a/src/vfs/mod.rs +++ b/src/vfs/mod.rs @@ -4,6 +4,9 @@ mod fetcher; mod noop_fetcher; mod real_fetcher; mod snapshot; + +// I don't think module inception is a real problem? +#[allow(clippy::module_inception)] mod vfs; pub use error::*; diff --git a/src/vfs/real_fetcher.rs b/src/vfs/real_fetcher.rs index 5dce585c..7add1022 100644 --- a/src/vfs/real_fetcher.rs +++ b/src/vfs/real_fetcher.rs @@ -220,6 +220,6 @@ impl VfsFetcher for RealFetcher { fn watched_paths(&self) -> Vec { let watched_paths = self.watched_paths.lock().unwrap(); - watched_paths.iter().map(|v| v.clone()).collect() + watched_paths.iter().cloned().collect() } } diff --git a/src/web/api.rs b/src/web/api.rs index 676ddfdb..fe7ad62c 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -39,12 +39,10 @@ impl Service for ApiService { (&Method::GET, path) if path.starts_with("/api/subscribe/") => { self.handle_api_subscribe(request) } - (_method, path) => { - return json( - ErrorResponse::not_found(format!("Route not found: {}", path)), - StatusCode::NOT_FOUND, - ) - } + (_method, path) => json( + ErrorResponse::not_found(format!("Route not found: {}", path)), + StatusCode::NOT_FOUND, + ), } } } diff --git a/src/web/interface.rs b/src/web/interface.rs index ceab02fd..f748758c 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -67,7 +67,7 @@ pub struct Instance<'a> { } impl<'a> Instance<'a> { - pub(crate) fn from_rojo_instance<'b>(source: InstanceWithMeta<'b>) -> Instance<'b> { + pub(crate) fn from_rojo_instance(source: InstanceWithMeta<'_>) -> Instance<'_> { Instance { id: source.id(), parent: source.parent(), diff --git a/src/web/ui.rs b/src/web/ui.rs index 8f7276be..7a6b0b5b 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -336,7 +336,7 @@ impl UiService { // Round off all of our sub-second precision to make timestamps // nicer. - let just_nanos = Duration::from_nanos(elapsed.subsec_nanos() as u64); + let just_nanos = Duration::from_nanos(u64::from(elapsed.subsec_nanos())); let elapsed = elapsed - just_nanos; humantime::format_duration(elapsed).to_string() From 457ed05174727d1b63a0103b6b495fd661b139f8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 18 Oct 2019 15:37:38 -0700 Subject: [PATCH 0850/1504] Fix missed references to IMFS in CSS instead of VFS --- assets/index.css | 10 +++++----- src/web/ui.rs | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/assets/index.css b/assets/index.css index 1eb5893f..1dc6ea39 100644 --- a/assets/index.css +++ b/assets/index.css @@ -154,15 +154,15 @@ img { display: none; } -.imfs-entry { +.vfs-entry { } -.imfs-entry-name { +.vfs-entry-name { position: relative; font-family: monospace; } -.imfs-entry-children .imfs-entry-name::before { +.vfs-entry-children .vfs-entry-name::before { content: ""; width: 0.6em; height: 1px; @@ -172,11 +172,11 @@ img { left: -0.8em; } -.imfs-entry-note { +.vfs-entry-note { font-style: italic; } -.imfs-entry-children { +.vfs-entry-children { padding-left: 0.8em; margin-left: 0.2em; border-left: 1px solid #999; diff --git a/src/web/ui.rs b/src/web/ui.rs index 7a6b0b5b..e7e69380 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -71,7 +71,7 @@ impl UiService { let page = self.normal_page(html! {
    { Self::button("Rojo Documentation", "https://rojo.space/docs") } - { Self::button("View in-memory filesystem state", "/show-vfs") } + { Self::button("View virtual filesystem state", "/show-vfs") } { Self::button("View instance tree state", "/show-instances") }
    }); From d54a5f647e08a47b52cb30c021412a9d9d34a226 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 18 Oct 2019 16:49:03 -0700 Subject: [PATCH 0851/1504] Improve tree explorer UI --- assets/index.css | 36 +++++++++++++++++------------------- src/web/ui.rs | 3 ++- 2 files changed, 19 insertions(+), 20 deletions(-) diff --git a/assets/index.css b/assets/index.css index 1dc6ea39..bbec79cb 100644 --- a/assets/index.css +++ b/assets/index.css @@ -94,10 +94,6 @@ img { } .instance { - border: 1px solid #666; - border-right-style: none; - border-bottom-style: none; - background-color: #fff; margin-bottom: 0.5rem; } @@ -106,16 +102,12 @@ img { padding: 0.5rem; } -.instance-metadata { - padding: 0.5rem; +.expandable-section { + margin: 0.25rem 0.5rem; } -.instance-properties { - padding: 0.5rem; -} - -.instance-children { - padding: 0.5rem 0 0.5rem 1rem; +.expandable-items { + padding: 0.5rem 1rem; } .expandable-input { @@ -124,30 +116,36 @@ img { .expandable-label > label { cursor: pointer; + display: flex; + align-items: center; + align-content: center; } .expandable-input ~ .expandable-label .expandable-visualizer { font-family: monospace; display: inline-flex; - justify-content: center; align-items: center; align-content: center; + text-align: center; width: 1rem; height: 1rem; - border: 1px solid #666; + font-size: 2rem; margin: 0 0.5rem; + transition: transform 100ms ease-in-out; + transform-origin: 60% 60%; } .expandable-visualizer::before { - content: ""; + content: "›"; + font-weight: bold; } -.expandable-input:checked ~ .expandable-label .expandable-visualizer::before { - content: "-"; +.expandable-input:checked ~ .expandable-label { + border-bottom: 1px solid #bbb; } -.expandable-input:not(:checked) ~ .expandable-label .expandable-visualizer::before { - content: "+"; +.expandable-input:checked ~ .expandable-label .expandable-visualizer { + transform: rotate(90deg); } .expandable-input:not(:checked) ~ .expandable-items { diff --git a/src/web/ui.rs b/src/web/ui.rs index e7e69380..0f59b9e8 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -365,6 +365,7 @@ impl UiService { html! { + "Rojo Live Server" @@ -411,7 +412,7 @@ impl<'a> ExpandableSection<'a> { } html! { -
    +
    { input }

    From 30c8ea583ba0ceb96896e14e2e072c25090109e2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 18 Oct 2019 18:06:25 -0700 Subject: [PATCH 0852/1504] Remove special path serialization for ProjectNode --- src/path_serializer.rs | 74 ++---------------------------------------- src/project.rs | 2 -- 2 files changed, 3 insertions(+), 73 deletions(-) diff --git a/src/path_serializer.rs b/src/path_serializer.rs index a44e636e..74eb9534 100644 --- a/src/path_serializer.rs +++ b/src/path_serializer.rs @@ -1,78 +1,10 @@ -//! path_serializer is used in cases where we need to serialize relative Path -//! and PathBuf objects in a way that's cross-platform. -//! -//! This is used for the snapshot testing system to make sure that snapshots -//! that reference local paths that are generated on Windows don't fail when run -//! in systems that use a different directory separator. -//! -//! To use, annotate your PathBuf or Option field with the correct -//! serializer function: -//! -//! ```ignore -//! # use std::path::PathBuf; -//! # use serde::{Serialize, Deserialize}; -//! -//! #[derive(Serialize, Deserialize)] -//! struct Mine { -//! name: String, -//! -//! // Use 'crate' instead of librojo if writing code inside Rojo -//! #[serde(serialize_with = "librojo::path_serializer::serialize")] -//! source_path: PathBuf, -//! -//! #[serde(serialize_with = "librojo::path_serializer::serialize_option")] -//! maybe_path: Option, -//! } -//! ``` -//! -//! For absolute paths, which are only safe to serialize if they're artificial, -//! use `serialize_absolute`. +//! Path serializer is used to serialize absolute paths in a cross-platform way, +//! by replacing all directory separators with /. -use std::path::{Component, Path}; +use std::path::Path; use serde::{ser::SerializeSeq, Serialize, Serializer}; -pub fn serialize_option(maybe_path: &Option, serializer: S) -> Result -where - S: Serializer, - T: AsRef, -{ - match maybe_path { - Some(path) => serialize(path, serializer), - None => serializer.serialize_none(), - } -} - -pub fn serialize(path: T, serializer: S) -> Result -where - S: Serializer, - T: AsRef, -{ - let path = path.as_ref(); - - assert!( - path.is_relative(), - "path_serializer can only handle relative paths" - ); - - let mut output = String::new(); - - for component in path.components() { - if !output.is_empty() { - output.push('/'); - } - - match component { - Component::CurDir => output.push('.'), - Component::ParentDir => output.push_str(".."), - Component::Normal(piece) => output.push_str(piece.to_str().unwrap()), - _ => panic!("path_serializer cannot handle absolute path components"), - } - } - - serializer.serialize_str(&output) -} - pub fn serialize_absolute(path: T, serializer: S) -> Result where S: Serializer, diff --git a/src/project.rs b/src/project.rs index e8da842d..a81bbbf5 100644 --- a/src/project.rs +++ b/src/project.rs @@ -269,8 +269,6 @@ pub struct ProjectNode { pub children: BTreeMap, pub properties: HashMap, pub ignore_unknown_instances: Option, - - #[serde(serialize_with = "crate::path_serializer::serialize_option")] pub path: Option, } From 07801a0283dd5517fe4f94e1d5e67c148c77d0eb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 18 Oct 2019 18:06:40 -0700 Subject: [PATCH 0853/1504] Add support for updating instances defined in project nodes --- src/change_processor.rs | 18 ++++--- src/serve_session.rs | 53 +++++++++++++++++++ src/snapshot_middleware/mod.rs | 2 + src/snapshot_middleware/project.rs | 2 +- ...session__change_file_in_project_after.snap | 36 +++++++++++++ ...ession__change_file_in_project_before.snap | 36 +++++++++++++ ...session__change_file_in_project_patch.snap | 16 ++++++ 7 files changed, 154 insertions(+), 9 deletions(-) create mode 100644 src/snapshots/serve_session__change_file_in_project_after.snap create mode 100644 src/snapshots/serve_session__change_file_in_project_before.snap create mode 100644 src/snapshots/serve_session__change_file_in_project_patch.snap diff --git a/src/change_processor.rs b/src/change_processor.rs index f6b7fff6..0157cc58 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -12,7 +12,7 @@ use rbx_dom_weak::RbxId; use crate::{ message_queue::MessageQueue, snapshot::{apply_patch_set, compute_patch_set, AppliedPatchSet, InstigatingSource, RojoTree}, - snapshot_middleware::{snapshot_from_vfs, InstanceSnapshotContext}, + snapshot_middleware::{snapshot_from_vfs, snapshot_project_node, InstanceSnapshotContext}, vfs::{Vfs, VfsEvent, VfsFetcher}, }; @@ -139,22 +139,24 @@ fn update_affected_instances( } }; + // TODO: Use persisted snapshot context struct instead of recreating it + // every time. + let mut snapshot_context = InstanceSnapshotContext::default(); + let snapshot = match instigating_source { InstigatingSource::Path(path) => { let entry = vfs .get(path) .expect("could not get instigating path from filesystem"); - // TODO: Use persisted snapshot - // context struct instead of - // recreating it every time. - snapshot_from_vfs(&mut InstanceSnapshotContext::default(), &vfs, &entry) + snapshot_from_vfs(&mut snapshot_context, &vfs, &entry) .expect("snapshot failed") .expect("snapshot did not return an instance") } - InstigatingSource::ProjectNode(_, _) => { - log::warn!("Instance {} had an instigating source that was a project node, which is not yet supported.", id); - continue; + InstigatingSource::ProjectNode(instance_name, project_node) => { + snapshot_project_node(&mut snapshot_context, instance_name, project_node, &vfs) + .expect("snapshot failed") + .expect("snapshot did not return an instance") } }; diff --git a/src/serve_session.rs b/src/serve_session.rs index 0652a728..7a90d6b0 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -311,4 +311,57 @@ mod serve_session { view_tree(&session.tree(), &mut redactions) ); } + + #[test] + fn change_file_in_project() { + let (state, fetcher) = TestFetcher::new(); + + state.load_snapshot( + "/foo", + VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" + { + "name": "change_file_in_project", + "tree": { + "$className": "Folder", + + "Child": { + "$path": "file.txt" + } + } + } + "#), + "file.txt" => VfsSnapshot::file("initial content"), + }), + ); + + let vfs = Vfs::new(fetcher); + let session = ServeSession::new(vfs, "/foo"); + + let mut redactions = RedactionMap::new(); + assert_yaml_snapshot!( + "change_file_in_project_before", + view_tree(&session.tree(), &mut redactions) + ); + + state.load_snapshot("/foo/file.txt", VfsSnapshot::file("Changed!")); + + let receiver = session.message_queue().subscribe_any(); + + state.raise_event(VfsEvent::Modified(PathBuf::from("/foo/file.txt"))); + + let receiver = Timeout::new(receiver, Duration::from_millis(200)); + + let mut rt = Runtime::new().unwrap(); + let result = rt.block_on(receiver).unwrap(); + + assert_yaml_snapshot!( + "change_file_in_project_patch", + redactions.redacted_yaml(result) + ); + assert_yaml_snapshot!( + "change_file_in_project_after", + view_tree(&session.tree(), &mut redactions) + ); + } } diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 25f0bedb..6c3174e9 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -39,6 +39,8 @@ use self::{ }; use crate::vfs::{Vfs, VfsEntry, VfsFetcher}; +pub use self::project::snapshot_project_node; + macro_rules! middlewares { ( $($middleware: ident,)* ) => { /// Generates a snapshot of instances from the given VfsEntry. diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index bb4a8ffe..91ed6ccb 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -76,7 +76,7 @@ impl SnapshotMiddleware for SnapshotProject { } } -fn snapshot_project_node( +pub fn snapshot_project_node( context: &mut InstanceSnapshotContext, instance_name: &str, node: &ProjectNode, diff --git a/src/snapshots/serve_session__change_file_in_project_after.snap b/src/snapshots/serve_session__change_file_in_project_after.snap new file mode 100644 index 00000000..0efeb6c5 --- /dev/null +++ b/src/snapshots/serve_session__change_file_in_project_after.snap @@ -0,0 +1,36 @@ +--- +source: src/serve_session.rs +expression: "view_tree(&session.tree(), &mut redactions)" +--- +id: id-1 +name: change_file_in_project +class_name: Folder +properties: {} +metadata: + ignore_unknown_instances: true + instigating_source: + Path: /foo/default.project.json + relevant_paths: + - /foo/default.project.json +children: + - id: id-2 + name: Child + class_name: StringValue + properties: + Value: + Type: String + Value: Changed! + metadata: + ignore_unknown_instances: false + instigating_source: + ProjectNode: + - Child + - class_name: ~ + children: {} + properties: {} + ignore_unknown_instances: ~ + path: "/foo\\file.txt" + relevant_paths: + - /foo/file.txt + - /foo/file.meta.json + children: [] diff --git a/src/snapshots/serve_session__change_file_in_project_before.snap b/src/snapshots/serve_session__change_file_in_project_before.snap new file mode 100644 index 00000000..c824b355 --- /dev/null +++ b/src/snapshots/serve_session__change_file_in_project_before.snap @@ -0,0 +1,36 @@ +--- +source: src/serve_session.rs +expression: "view_tree(&session.tree(), &mut redactions)" +--- +id: id-1 +name: change_file_in_project +class_name: Folder +properties: {} +metadata: + ignore_unknown_instances: true + instigating_source: + Path: /foo/default.project.json + relevant_paths: + - /foo/default.project.json +children: + - id: id-2 + name: Child + class_name: StringValue + properties: + Value: + Type: String + Value: initial content + metadata: + ignore_unknown_instances: false + instigating_source: + ProjectNode: + - Child + - class_name: ~ + children: {} + properties: {} + ignore_unknown_instances: ~ + path: "/foo\\file.txt" + relevant_paths: + - /foo/file.txt + - /foo/file.meta.json + children: [] diff --git a/src/snapshots/serve_session__change_file_in_project_patch.snap b/src/snapshots/serve_session__change_file_in_project_patch.snap new file mode 100644 index 00000000..062181c5 --- /dev/null +++ b/src/snapshots/serve_session__change_file_in_project_patch.snap @@ -0,0 +1,16 @@ +--- +source: src/serve_session.rs +expression: redactions.redacted_yaml(result) +--- +- 1 +- - removed: [] + added: [] + updated: + - id: id-2 + changed_name: ~ + changed_class_name: ~ + changed_properties: + Value: + Type: String + Value: Changed! + changed_metadata: ~ From 114c93fa467501196cd9735fb14f41fe4cf02c58 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 18 Oct 2019 19:40:47 -0700 Subject: [PATCH 0854/1504] Fix non-portable path serialization in ProjectNode. This was failing snapshot tests on the Linux CI machines, since I committed snapshots with backslashes. I think the old path serializer was still the wrong approach, this one is sort of a middleground but I'm still not super happy with it. --- src/path_serializer.rs | 14 ++++++++++++++ src/project.rs | 2 ++ ...erve_session__change_file_in_project_after.snap | 2 +- ...rve_session__change_file_in_project_before.snap | 2 +- 4 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/path_serializer.rs b/src/path_serializer.rs index 74eb9534..18a61707 100644 --- a/src/path_serializer.rs +++ b/src/path_serializer.rs @@ -36,3 +36,17 @@ where seq.end() } + +pub fn serialize_option_absolute( + maybe_path: &Option, + serializer: S, +) -> Result +where + S: Serializer, + T: AsRef, +{ + match maybe_path { + Some(path) => serialize_absolute(path, serializer), + None => serializer.serialize_none(), + } +} diff --git a/src/project.rs b/src/project.rs index a81bbbf5..98aab9d1 100644 --- a/src/project.rs +++ b/src/project.rs @@ -269,6 +269,8 @@ pub struct ProjectNode { pub children: BTreeMap, pub properties: HashMap, pub ignore_unknown_instances: Option, + + #[serde(serialize_with = "crate::path_serializer::serialize_option_absolute")] pub path: Option, } diff --git a/src/snapshots/serve_session__change_file_in_project_after.snap b/src/snapshots/serve_session__change_file_in_project_after.snap index 0efeb6c5..db346fb6 100644 --- a/src/snapshots/serve_session__change_file_in_project_after.snap +++ b/src/snapshots/serve_session__change_file_in_project_after.snap @@ -29,7 +29,7 @@ children: children: {} properties: {} ignore_unknown_instances: ~ - path: "/foo\\file.txt" + path: /foo/file.txt relevant_paths: - /foo/file.txt - /foo/file.meta.json diff --git a/src/snapshots/serve_session__change_file_in_project_before.snap b/src/snapshots/serve_session__change_file_in_project_before.snap index c824b355..715cd903 100644 --- a/src/snapshots/serve_session__change_file_in_project_before.snap +++ b/src/snapshots/serve_session__change_file_in_project_before.snap @@ -29,7 +29,7 @@ children: children: {} properties: {} ignore_unknown_instances: ~ - path: "/foo\\file.txt" + path: /foo/file.txt relevant_paths: - /foo/file.txt - /foo/file.meta.json From 7cc4055d942942a3dbd26a55ff97adc5a4b9c065 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 Oct 2019 15:28:38 -0700 Subject: [PATCH 0855/1504] Upgrade to Insta master to get bugfix. Map sorting in Insta was previously not recursive. As of this PR, it is! https://github.com/mitsuhiko/insta/pull/80 Since it hasn't made it into a release yet, but is important for Rojo to have snapshot determinism, we're moving temporarily to depend on Insta via Git. --- Cargo.lock | 8 ++--- Cargo.toml | 2 +- rojo-test/Cargo.toml | 2 +- .../serve_test__add_folder_all-2.snap | 26 ++++++++-------- .../serve_test__add_folder_all.snap | 10 +++---- .../serve_test__add_folder_subscribe.snap | 14 ++++----- .../serve_test__empty_all.snap | 10 +++---- .../serve_test__just_txt_all.snap | 12 ++++---- .../serve_test__scripts_all-2.snap | 30 +++++++++---------- .../serve_test__scripts_all.snap | 30 +++++++++---------- .../serve_test__scripts_subscribe.snap | 12 ++++---- 11 files changed, 78 insertions(+), 78 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3175ce60..524044bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -710,7 +710,7 @@ dependencies = [ [[package]] name = "insta" version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" +source = "git+https://github.com/mitsuhiko/insta#8e32e354d1db280412592cfb627b26bbd58e0164" dependencies = [ "console 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1567,7 +1567,7 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "insta 0.11.0 (git+https://github.com/mitsuhiko/insta)", "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1608,7 +1608,7 @@ name = "rojo-test" version = "0.1.0" dependencies = [ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "insta 0.11.0 (git+https://github.com/mitsuhiko/insta)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2383,7 +2383,7 @@ dependencies = [ "checksum indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" -"checksum insta 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "23f83ab4ee86f38b292f0420c27fd412690a4baa9ea0ad4e3fa624bf34379b76" +"checksum insta 0.11.0 (git+https://github.com/mitsuhiko/insta)" = "" "checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" "checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" diff --git a/Cargo.toml b/Cargo.toml index d13280d0..f37be268 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -88,5 +88,5 @@ walkdir = "2.1" criterion = "0.3" [dev-dependencies.insta] -version = "0.11.0" +git = "https://github.com/mitsuhiko/insta" features = ["redactions"] diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index 366dfe8c..91b13449 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -23,5 +23,5 @@ rojo-insta-ext = { path = "../rojo-insta-ext" } rojo = { path = ".." } [dependencies.insta] -version = "0.11.0" +git = "https://github.com/mitsuhiko/insta" features = ["redactions"] diff --git a/rojo-test/serve-test-snapshots/serve_test__add_folder_all-2.snap b/rojo-test/serve-test-snapshots/serve_test__add_folder_all-2.snap index 94948cf8..379aa949 100644 --- a/rojo-test/serve-test-snapshots/serve_test__add_folder_all-2.snap +++ b/rojo-test/serve-test-snapshots/serve_test__add_folder_all-2.snap @@ -4,23 +4,23 @@ expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: id-2: - Id: id-2 - Parent: ~ - Name: add_folder - ClassName: Folder - Properties: {} Children: - id-3 - Metadata: - ignoreUnknownInstances: false - id-3: - Id: id-3 - Parent: id-2 - Name: my-new-folder ClassName: Folder - Properties: {} - Children: [] + Id: id-2 Metadata: ignoreUnknownInstances: false + Name: add_folder + Parent: ~ + Properties: {} + id-3: + Children: [] + ClassName: Folder + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: my-new-folder + Parent: id-2 + Properties: {} messageCursor: 1 sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__add_folder_all.snap b/rojo-test/serve-test-snapshots/serve_test__add_folder_all.snap index 03362f41..53d11e9b 100644 --- a/rojo-test/serve-test-snapshots/serve_test__add_folder_all.snap +++ b/rojo-test/serve-test-snapshots/serve_test__add_folder_all.snap @@ -4,13 +4,13 @@ expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: id-2: - Id: id-2 - Parent: ~ - Name: add_folder - ClassName: Folder - Properties: {} Children: [] + ClassName: Folder + Id: id-2 Metadata: ignoreUnknownInstances: false + Name: add_folder + Parent: ~ + Properties: {} messageCursor: 0 sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap b/rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap index bfdfeadf..646fcfea 100644 --- a/rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap +++ b/rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap @@ -4,16 +4,16 @@ expression: "subscribe_response.intern_and_redact(&mut redactions, ())" --- messageCursor: 1 messages: - - removedInstances: [] - addedInstances: + - addedInstances: id-3: - Id: id-3 - Parent: id-2 - Name: my-new-folder - ClassName: Folder - Properties: {} Children: [] + ClassName: Folder + Id: id-3 Metadata: ignoreUnknownInstances: false + Name: my-new-folder + Parent: id-2 + Properties: {} + removedInstances: [] updatedInstances: [] sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__empty_all.snap b/rojo-test/serve-test-snapshots/serve_test__empty_all.snap index d8a33da7..7aca5205 100644 --- a/rojo-test/serve-test-snapshots/serve_test__empty_all.snap +++ b/rojo-test/serve-test-snapshots/serve_test__empty_all.snap @@ -4,13 +4,13 @@ expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: id-2: - Id: id-2 - Parent: ~ - Name: empty - ClassName: Folder - Properties: {} Children: [] + ClassName: Folder + Id: id-2 Metadata: ignoreUnknownInstances: true + Name: empty + Parent: ~ + Properties: {} messageCursor: 0 sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__just_txt_all.snap b/rojo-test/serve-test-snapshots/serve_test__just_txt_all.snap index fb31572b..e67add37 100644 --- a/rojo-test/serve-test-snapshots/serve_test__just_txt_all.snap +++ b/rojo-test/serve-test-snapshots/serve_test__just_txt_all.snap @@ -4,16 +4,16 @@ expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: id-2: - Id: id-2 - Parent: ~ - Name: just_txt + Children: [] ClassName: StringValue + Id: id-2 + Metadata: + ignoreUnknownInstances: false + Name: just_txt + Parent: ~ Properties: Value: Type: String Value: "Hello, world!" - Children: [] - Metadata: - ignoreUnknownInstances: false messageCursor: 0 sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts_all-2.snap b/rojo-test/serve-test-snapshots/serve_test__scripts_all-2.snap index d65cca84..edc0daef 100644 --- a/rojo-test/serve-test-snapshots/serve_test__scripts_all-2.snap +++ b/rojo-test/serve-test-snapshots/serve_test__scripts_all-2.snap @@ -4,39 +4,39 @@ expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: id-2: - Id: id-2 - Parent: ~ - Name: scripts - ClassName: Folder - Properties: {} Children: - id-3 - id-4 + ClassName: Folder + Id: id-2 Metadata: ignoreUnknownInstances: false + Name: scripts + Parent: ~ + Properties: {} id-3: - Id: id-3 - Parent: id-2 - Name: bar + Children: [] ClassName: Script + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: bar + Parent: id-2 Properties: Source: Type: String Value: "-- Hello, from bar!" + id-4: Children: [] + ClassName: ModuleScript + Id: id-4 Metadata: ignoreUnknownInstances: false - id-4: - Id: id-4 - Parent: id-2 Name: foo - ClassName: ModuleScript + Parent: id-2 Properties: Source: Type: String Value: Updated foo! - Children: [] - Metadata: - ignoreUnknownInstances: false messageCursor: 1 sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts_all.snap b/rojo-test/serve-test-snapshots/serve_test__scripts_all.snap index e11c4e25..64542c22 100644 --- a/rojo-test/serve-test-snapshots/serve_test__scripts_all.snap +++ b/rojo-test/serve-test-snapshots/serve_test__scripts_all.snap @@ -4,39 +4,39 @@ expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: id-2: - Id: id-2 - Parent: ~ - Name: scripts - ClassName: Folder - Properties: {} Children: - id-3 - id-4 + ClassName: Folder + Id: id-2 Metadata: ignoreUnknownInstances: false + Name: scripts + Parent: ~ + Properties: {} id-3: - Id: id-3 - Parent: id-2 - Name: bar + Children: [] ClassName: Script + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: bar + Parent: id-2 Properties: Source: Type: String Value: "-- Hello, from bar!" + id-4: Children: [] + ClassName: ModuleScript + Id: id-4 Metadata: ignoreUnknownInstances: false - id-4: - Id: id-4 - Parent: id-2 Name: foo - ClassName: ModuleScript + Parent: id-2 Properties: Source: Type: String Value: "-- Hello, from foo!" - Children: [] - Metadata: - ignoreUnknownInstances: false messageCursor: 0 sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts_subscribe.snap b/rojo-test/serve-test-snapshots/serve_test__scripts_subscribe.snap index f71ad85b..b3ee2237 100644 --- a/rojo-test/serve-test-snapshots/serve_test__scripts_subscribe.snap +++ b/rojo-test/serve-test-snapshots/serve_test__scripts_subscribe.snap @@ -1,18 +1,18 @@ --- source: rojo-test/src/serve_test.rs -expression: redactions.redacted_yaml(subscribe_response) +expression: "subscribe_response.intern_and_redact(&mut redactions, ())" --- messageCursor: 1 messages: - - removedInstances: [] - addedInstances: {} + - addedInstances: {} + removedInstances: [] updatedInstances: - - id: id-4 + - changedClassName: ~ + changedMetadata: ~ changedName: ~ - changedClassName: ~ changedProperties: Source: Type: String Value: Updated foo! - changedMetadata: ~ + id: id-4 sessionId: id-1 From 428a19789df531f5a7c99ccb6e1fb82c6f6b47c6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 Oct 2019 16:00:43 -0700 Subject: [PATCH 0856/1504] Enable 'move folder of stuff' test --- ...erve_test__move_folder_of_stuff_all-2.snap | 156 ++++++++++++++++++ .../serve_test__move_folder_of_stuff_all.snap | 16 ++ ...serve_test__move_folder_of_stuff_info.snap | 9 + ..._test__move_folder_of_stuff_subscribe.snap | 149 +++++++++++++++++ rojo-test/src/serve_test.rs | 1 - 5 files changed, 330 insertions(+), 1 deletion(-) create mode 100644 rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_all-2.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_all.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_info.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_subscribe.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_all-2.snap b/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_all-2.snap new file mode 100644 index 00000000..d73ce024 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_all-2.snap @@ -0,0 +1,156 @@ +--- +source: rojo-test/src/serve_test.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-10: + Children: [] + ClassName: StringValue + Id: id-10 + Metadata: + ignoreUnknownInstances: false + Name: "6" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #6" + id-11: + Children: [] + ClassName: StringValue + Id: id-11 + Metadata: + ignoreUnknownInstances: false + Name: "7" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #7" + id-12: + Children: [] + ClassName: StringValue + Id: id-12 + Metadata: + ignoreUnknownInstances: false + Name: "8" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #8" + id-13: + Children: [] + ClassName: StringValue + Id: id-13 + Metadata: + ignoreUnknownInstances: false + Name: "9" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #9" + id-2: + Children: + - id-3 + ClassName: Folder + Id: id-2 + Metadata: + ignoreUnknownInstances: false + Name: move_folder_of_stuff + Parent: ~ + Properties: {} + id-3: + Children: + - id-4 + - id-5 + - id-6 + - id-7 + - id-8 + - id-9 + - id-10 + - id-11 + - id-12 + - id-13 + ClassName: Folder + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: new-stuff + Parent: id-2 + Properties: {} + id-4: + Children: [] + ClassName: StringValue + Id: id-4 + Metadata: + ignoreUnknownInstances: false + Name: "0" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #0" + id-5: + Children: [] + ClassName: StringValue + Id: id-5 + Metadata: + ignoreUnknownInstances: false + Name: "1" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #1" + id-6: + Children: [] + ClassName: StringValue + Id: id-6 + Metadata: + ignoreUnknownInstances: false + Name: "2" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #2" + id-7: + Children: [] + ClassName: StringValue + Id: id-7 + Metadata: + ignoreUnknownInstances: false + Name: "3" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #3" + id-8: + Children: [] + ClassName: StringValue + Id: id-8 + Metadata: + ignoreUnknownInstances: false + Name: "4" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #4" + id-9: + Children: [] + ClassName: StringValue + Id: id-9 + Metadata: + ignoreUnknownInstances: false + Name: "5" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #5" +messageCursor: 1 +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_all.snap b/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_all.snap new file mode 100644 index 00000000..2f0cfd81 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_all.snap @@ -0,0 +1,16 @@ +--- +source: rojo-test/src/serve_test.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Children: [] + ClassName: Folder + Id: id-2 + Metadata: + ignoreUnknownInstances: false + Name: move_folder_of_stuff + Parent: ~ + Properties: {} +messageCursor: 0 +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_info.snap b/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_info.snap new file mode 100644 index 00000000..f826d7e7 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_info.snap @@ -0,0 +1,9 @@ +--- +source: rojo-test/src/serve_test.rs +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +protocolVersion: 3 +rootInstanceId: id-2 +serverVersion: 0.6.0-dev +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_subscribe.snap b/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_subscribe.snap new file mode 100644 index 00000000..5ba30e26 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_subscribe.snap @@ -0,0 +1,149 @@ +--- +source: rojo-test/src/serve_test.rs +expression: "subscribe_response.intern_and_redact(&mut redactions, ())" +--- +messageCursor: 1 +messages: + - addedInstances: + id-10: + Children: [] + ClassName: StringValue + Id: id-10 + Metadata: + ignoreUnknownInstances: false + Name: "6" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #6" + id-11: + Children: [] + ClassName: StringValue + Id: id-11 + Metadata: + ignoreUnknownInstances: false + Name: "7" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #7" + id-12: + Children: [] + ClassName: StringValue + Id: id-12 + Metadata: + ignoreUnknownInstances: false + Name: "8" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #8" + id-13: + Children: [] + ClassName: StringValue + Id: id-13 + Metadata: + ignoreUnknownInstances: false + Name: "9" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #9" + id-3: + Children: + - id-4 + - id-5 + - id-6 + - id-7 + - id-8 + - id-9 + - id-10 + - id-11 + - id-12 + - id-13 + ClassName: Folder + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: new-stuff + Parent: id-2 + Properties: {} + id-4: + Children: [] + ClassName: StringValue + Id: id-4 + Metadata: + ignoreUnknownInstances: false + Name: "0" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #0" + id-5: + Children: [] + ClassName: StringValue + Id: id-5 + Metadata: + ignoreUnknownInstances: false + Name: "1" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #1" + id-6: + Children: [] + ClassName: StringValue + Id: id-6 + Metadata: + ignoreUnknownInstances: false + Name: "2" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #2" + id-7: + Children: [] + ClassName: StringValue + Id: id-7 + Metadata: + ignoreUnknownInstances: false + Name: "3" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #3" + id-8: + Children: [] + ClassName: StringValue + Id: id-8 + Metadata: + ignoreUnknownInstances: false + Name: "4" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #4" + id-9: + Children: [] + ClassName: StringValue + Id: id-9 + Metadata: + ignoreUnknownInstances: false + Name: "5" + Parent: id-3 + Properties: + Value: + Type: String + Value: "File #5" + removedInstances: [] + updatedInstances: [] +sessionId: id-1 diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index e2335838..2b6394b4 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -102,7 +102,6 @@ fn add_folder() { } #[test] -#[ignore] fn move_folder_of_stuff() { run_serve_test("move_folder_of_stuff", |session, mut redactions| { let info = session.get_api_rojo().unwrap(); From b64d97e808c7fd9521c3b7223712e03547707f1e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 21 Oct 2019 16:25:34 -0700 Subject: [PATCH 0857/1504] Force PathMap to have deterministic ordering by using BTreeSet instead of HashSet --- src/path_map.rs | 49 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 41 insertions(+), 8 deletions(-) diff --git a/src/path_map.rs b/src/path_map.rs index 86f6a02f..19201add 100644 --- a/src/path_map.rs +++ b/src/path_map.rs @@ -1,5 +1,5 @@ use std::{ - collections::{HashMap, HashSet}, + collections::{BTreeSet, HashMap}, path::{Path, PathBuf}, }; @@ -9,7 +9,7 @@ use serde::Serialize; #[derive(Debug, Serialize)] struct PathMapNode { value: T, - children: HashSet, + children: BTreeSet, } /// A map from paths to another type, like instance IDs, with a bit of @@ -25,7 +25,7 @@ pub struct PathMap { /// Note that these paths may have other _ancestors_ in the tree, but if an /// orphan's parent path is ever inserted, it will stop being an orphan. It /// will be... adopted! - orphan_paths: HashSet, + orphan_paths: BTreeSet, } impl Default for PathMap { @@ -38,7 +38,7 @@ impl PathMap { pub fn new() -> PathMap { PathMap { nodes: HashMap::new(), - orphan_paths: HashSet::new(), + orphan_paths: BTreeSet::new(), } } @@ -67,7 +67,7 @@ impl PathMap { // Collect any children that are currently marked as orphaned paths, but // are actually children of this new node. - let mut children = HashSet::new(); + let mut children = BTreeSet::new(); for orphan_path in &self.orphan_paths { if orphan_path.parent() == Some(&path) { children.insert(orphan_path.clone()); @@ -158,7 +158,7 @@ impl PathMap { mod test { use super::*; - use maplit::hashset; + use maplit::btreeset; #[test] fn smoke_test() { @@ -179,10 +179,10 @@ mod test { let mut map = PathMap::new(); map.insert("/foo/bar", 5); - assert_eq!(map.orphan_paths, hashset!["/foo/bar".into()]); + assert_eq!(map.orphan_paths, btreeset!["/foo/bar".into()]); map.insert("/foo", 6); - assert_eq!(map.orphan_paths, hashset!["/foo".into()]); + assert_eq!(map.orphan_paths, btreeset!["/foo".into()]); } #[test] @@ -246,4 +246,37 @@ mod test { assert_eq!(map.get("/foo"), None); assert_eq!(map.get("/foo/bar/baz"), Some(&12)); } + + // Makes sure that regardless of addition order, paths are always sorted + // when asking for children. + #[test] + fn add_order_sorted() { + let mut map = PathMap::new(); + + map.insert("/foo", 5); + map.insert("/foo/b", 2); + map.insert("/foo/d", 0); + map.insert("/foo/c", 3); + + assert_eq!( + map.children("/foo"), + Some(vec![ + Path::new("/foo/b"), + Path::new("/foo/c"), + Path::new("/foo/d"), + ]) + ); + + map.insert("/foo/a", 1); + + assert_eq!( + map.children("/foo"), + Some(vec![ + Path::new("/foo/a"), + Path::new("/foo/b"), + Path::new("/foo/c"), + Path::new("/foo/d"), + ]) + ); + } } From 7c71708de7417058900ef52173ac914b3730a1cb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 2 Nov 2019 23:16:01 -0700 Subject: [PATCH 0858/1504] Drop support for roblox-project.json --- src/project.rs | 32 +++----------------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/src/project.rs b/src/project.rs index 98aab9d1..d84e1244 100644 --- a/src/project.rs +++ b/src/project.rs @@ -14,7 +14,6 @@ use serde::{Deserialize, Serialize, Serializer}; static DEFAULT_PLACE: &str = include_str!("../assets/place.project.json"); pub static PROJECT_FILENAME: &str = "default.project.json"; -pub static COMPAT_PROJECT_FILENAME: &str = "roblox-project.json"; /// SourceProject is the format that users author projects on-disk. Since we /// want to do things like transforming paths to be absolute before handing them @@ -444,7 +443,7 @@ impl Project { } else { return None; } - } else if location_metadata.is_dir() { + } else { let with_file = start_location.join(PROJECT_FILENAME); if let Ok(file_metadata) = fs::metadata(&with_file) { @@ -452,14 +451,6 @@ impl Project { return Some(with_file); } } - - let with_compat_file = start_location.join(COMPAT_PROJECT_FILENAME); - - if let Ok(file_metadata) = fs::metadata(&with_compat_file) { - if file_metadata.is_file() { - return Some(with_compat_file); - } - } } match start_location.parent() { @@ -495,7 +486,7 @@ impl Project { } } - pub fn load_exact(project_file_location: &Path) -> Result { + fn load_exact(project_file_location: &Path) -> Result { let contents = fs::read_to_string(project_file_location).map_err(|error| match error.kind() { io::ErrorKind::NotFound => ProjectLoadError::NotFound, @@ -512,6 +503,7 @@ impl Project { })?; let project = parsed.into_project(project_file_location); + project.check_compatibility(); Ok(project) @@ -530,24 +522,6 @@ impl Project { /// Checks if there are any compatibility issues with this project file and /// warns the user if there are any. fn check_compatibility(&self) { - let file_name = self - .file_location - .file_name() - .expect("Project file path did not have a file name") - .to_str() - .expect("Project file path was not valid Unicode"); - - if file_name == COMPAT_PROJECT_FILENAME { - warn!("Rojo's default project file name changed in 0.5.0-alpha3."); - warn!("Support for the old project file name will be dropped before 0.5.0 releases."); - warn!("Your project file is named {}", COMPAT_PROJECT_FILENAME); - warn!("Rename your project file to {}", PROJECT_FILENAME); - } else if !file_name.ends_with(".project.json") { - warn!("Starting in Rojo 0.5.0-alpha3, it's recommended to give all project files the"); - warn!(".project.json extension. This helps Rojo differentiate project files from"); - warn!("other JSON files!"); - } - self.tree.validate_reserved_names(); } From 3a538f98ed67772189e7bd3fc0e1366ed6ac6047 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 2 Nov 2019 23:36:28 -0700 Subject: [PATCH 0859/1504] Tightened project discovery behavior --- CHANGELOG.md | 3 +++ src/project.rs | 38 ++++++++++++++++++++------------------ tests/read_projects.rs | 8 -------- 3 files changed, 23 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a7c3e77b..7bef57e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,9 @@ * Added support for automatically finding Roblox Studio's auth cookie for `rojo upload` on Windows. * Added support for building, serving and uploading sources that aren't Rojo projects. * Improved feedback from `rojo serve`. +* Removed support for legacy `roblox-project.json` projects, deprecated in an early Rojo 0.5.0 alpha. +* Rojo no longer traverses directories upwards looking for project files. + * Though undocumented, Rojo 0.5.x will search for a project file contained in any ancestor folders. This feature was removed to better support other 0.6.x features. ### Roblox Studio Plugin * Added "connecting" state to improve experience when live syncing. diff --git a/src/project.rs b/src/project.rs index d84e1244..fc039f34 100644 --- a/src/project.rs +++ b/src/project.rs @@ -432,31 +432,33 @@ impl Project { Ok(project_path) } - fn locate(start_location: &Path) -> Option { - // TODO: Check for specific error kinds, convert 'not found' to Result. - let location_metadata = fs::metadata(start_location).ok()?; + /// Attempt to locate a project represented by the given path. + /// + /// This will find a project if the path refers to a `.project.json` file, + /// or is a folder that contains a `default.project.json` file. + fn locate(path: &Path) -> Option { + let meta = fs::metadata(path).ok()?; - // If this is a file, assume it's the config the user was looking for. - if location_metadata.is_file() { - if Project::is_project_file(start_location) { - return Some(start_location.to_path_buf()); + if meta.is_file() { + if Project::is_project_file(path) { + Some(path.to_path_buf()) } else { - return None; + None } } else { - let with_file = start_location.join(PROJECT_FILENAME); + let child_path = path.join(PROJECT_FILENAME); + let child_meta = fs::metadata(&child_path).ok()?; - if let Ok(file_metadata) = fs::metadata(&with_file) { - if file_metadata.is_file() { - return Some(with_file); - } + if child_meta.is_file() { + Some(child_path) + } else { + // This is a folder with the same name as a Rojo default project + // file. + // + // That's pretty weird, but we can roll with it. + None } } - - match start_location.parent() { - Some(parent_location) => Self::locate(parent_location), - None => None, - } } fn load_from_str( diff --git a/tests/read_projects.rs b/tests/read_projects.rs index 25844b9b..e2eeaf60 100644 --- a/tests/read_projects.rs +++ b/tests/read_projects.rs @@ -16,14 +16,6 @@ lazy_static! { { Path::new(env!("CARGO_MANIFEST_DIR")).join("test-projects") }; } -#[test] -fn empty() { - let project_file_location = TEST_PROJECTS_ROOT.join("empty/default.project.json"); - let project = Project::load_exact(&project_file_location).unwrap(); - - assert_eq!(project.name, "empty"); -} - #[test] fn empty_fuzzy_file() { let project_file_location = TEST_PROJECTS_ROOT.join("empty/default.project.json"); From 9a2893c6bc2383999113a56774bc7357039cbaaa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 2 Nov 2019 23:41:32 -0700 Subject: [PATCH 0860/1504] Remove warnings for upgrading from 0.4.x --- src/project.rs | 16 ---------------- test-projects/legacy-0.4.x/rojo.json | 4 ---- .../legacy-old-0.5.x/roblox-project.json | 6 ------ 3 files changed, 26 deletions(-) delete mode 100644 test-projects/legacy-0.4.x/rojo.json delete mode 100644 test-projects/legacy-old-0.5.x/roblox-project.json diff --git a/src/project.rs b/src/project.rs index fc039f34..91bfa6f6 100644 --- a/src/project.rs +++ b/src/project.rs @@ -483,7 +483,6 @@ impl Project { if let Some(project_path) = Self::locate(fuzzy_project_location) { Self::load_exact(&project_path) } else { - Project::warn_if_4x_project_present(fuzzy_project_location); Err(ProjectLoadError::NotFound) } } @@ -527,21 +526,6 @@ impl Project { self.tree.validate_reserved_names(); } - /// Issues a warning if no Rojo 0.5.x project is found, but there's a legacy - /// 0.4.x project in the directory. - fn warn_if_4x_project_present(folder: &Path) { - let file_path = folder.join("rojo.json"); - - if fs::metadata(file_path).is_ok() { - warn!("No Rojo 0.5 project file was found, but a Rojo 0.4 project was."); - warn!("Rojo 0.5.x uses 'default.project.json' files"); - warn!("Rojo 0.5.x uses 'rojo.json' files"); - warn!(""); - warn!("For help upgrading, see:"); - warn!("https://lpghatguy.github.io/rojo/guide/migrating-to-epiphany/"); - } - } - pub fn folder_location(&self) -> &Path { self.file_location.parent().unwrap() } diff --git a/test-projects/legacy-0.4.x/rojo.json b/test-projects/legacy-0.4.x/rojo.json deleted file mode 100644 index 547d3943..00000000 --- a/test-projects/legacy-0.4.x/rojo.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "name": "legacy", - "parittions": {} -} \ No newline at end of file diff --git a/test-projects/legacy-old-0.5.x/roblox-project.json b/test-projects/legacy-old-0.5.x/roblox-project.json deleted file mode 100644 index 4fcf72e3..00000000 --- a/test-projects/legacy-old-0.5.x/roblox-project.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "Foo", - "tree": { - "$className": "Folder" - } -} \ No newline at end of file From 62b626a93197e93467359cd7f348a3454f766b08 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 2 Nov 2019 23:43:24 -0700 Subject: [PATCH 0861/1504] Remove Project::load_from_str in favor of from_slice --- src/project.rs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/project.rs b/src/project.rs index 91bfa6f6..532f6590 100644 --- a/src/project.rs +++ b/src/project.rs @@ -360,7 +360,7 @@ impl Project { .expect("Path had invalid Unicode") }; - let mut project = Project::load_from_str(DEFAULT_PLACE, &project_path) + let mut project = Project::load_from_slice(DEFAULT_PLACE.as_bytes(), &project_path) .map_err(ProjectInitError::JsonError)?; project.name = project_name.to_owned(); @@ -461,15 +461,6 @@ impl Project { } } - fn load_from_str( - contents: &str, - project_file_location: &Path, - ) -> Result { - let parsed: SourceProject = serde_json::from_str(&contents)?; - - Ok(parsed.into_project(project_file_location)) - } - pub fn load_from_slice( contents: &[u8], project_file_location: &Path, From 432e10c205e0dfd74bb6b36c1f2ec947e82fab48 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 2 Nov 2019 23:47:03 -0700 Subject: [PATCH 0862/1504] Scrap old project load tests --- tests/read_projects.rs | 104 ----------------------------------------- 1 file changed, 104 deletions(-) delete mode 100644 tests/read_projects.rs diff --git a/tests/read_projects.rs b/tests/read_projects.rs deleted file mode 100644 index e2eeaf60..00000000 --- a/tests/read_projects.rs +++ /dev/null @@ -1,104 +0,0 @@ -#[macro_use] -extern crate lazy_static; - -use std::{ - collections::{BTreeMap, HashMap}, - path::{Path, PathBuf}, -}; - -use pretty_assertions::assert_eq; -use rbx_dom_weak::RbxValue; - -use librojo::project::{Project, ProjectNode}; - -lazy_static! { - static ref TEST_PROJECTS_ROOT: PathBuf = - { Path::new(env!("CARGO_MANIFEST_DIR")).join("test-projects") }; -} - -#[test] -fn empty_fuzzy_file() { - let project_file_location = TEST_PROJECTS_ROOT.join("empty/default.project.json"); - let project = Project::load_fuzzy(&project_file_location).unwrap(); - - assert_eq!(project.name, "empty"); -} - -#[test] -fn empty_fuzzy_folder() { - let project_location = TEST_PROJECTS_ROOT.join("empty"); - let project = Project::load_fuzzy(&project_location).unwrap(); - - assert_eq!(project.name, "empty"); -} - -#[test] -fn single_partition_game() { - let project_location = TEST_PROJECTS_ROOT.join("single_partition_game"); - let project = Project::load_fuzzy(&project_location).unwrap(); - - let expected_project = { - let foo = ProjectNode { - path: Some(project_location.join("lib")), - ..Default::default() - }; - - let mut replicated_storage_children = BTreeMap::new(); - replicated_storage_children.insert("Foo".to_string(), foo); - - let replicated_storage = ProjectNode { - class_name: Some(String::from("ReplicatedStorage")), - children: replicated_storage_children, - ..Default::default() - }; - - let mut http_service_properties = HashMap::new(); - http_service_properties.insert( - "HttpEnabled".to_string(), - RbxValue::Bool { value: true }.into(), - ); - - let http_service = ProjectNode { - class_name: Some(String::from("HttpService")), - properties: http_service_properties, - ..Default::default() - }; - - let mut root_children = BTreeMap::new(); - root_children.insert("ReplicatedStorage".to_string(), replicated_storage); - root_children.insert("HttpService".to_string(), http_service); - - let root_node = ProjectNode { - class_name: Some(String::from("DataModel")), - children: root_children, - ..Default::default() - }; - - Project { - name: "single-sync-point".to_string(), - tree: root_node, - serve_port: None, - serve_place_ids: None, - plugins: Vec::new(), - file_location: project_location.join("default.project.json"), - } - }; - - assert_eq!(project, expected_project); -} - -#[test] -fn single_partition_model() { - let project_file_location = TEST_PROJECTS_ROOT.join("single_partition_model"); - let project = Project::load_fuzzy(&project_file_location).unwrap(); - - assert_eq!(project.name, "test-model"); -} - -#[test] -fn composing_models() { - let project_file_location = TEST_PROJECTS_ROOT.join("composing_models"); - let project = Project::load_fuzzy(&project_file_location).unwrap(); - - assert_eq!(project.name, "composing-models"); -} From f1daafbf9edbe70a13ef23b1cbc89e7b029b05d9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 3 Nov 2019 00:00:50 -0700 Subject: [PATCH 0863/1504] Fix ordering not being preserved in Vfs --- src/vfs/vfs.rs | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/src/vfs/vfs.rs b/src/vfs/vfs.rs index 5e0f45ee..149834e0 100644 --- a/src/vfs/vfs.rs +++ b/src/vfs/vfs.rs @@ -108,27 +108,29 @@ impl Vfs { VfsItem::Directory(dir) => { self.fetcher.watch(path); - let enumerated = dir.children_enumerated; - - if enumerated { - data.children(path) - .unwrap() // TODO: Handle None here, which means the PathMap entry did not exist. - .into_iter() - .map(PathBuf::from) // Convert paths from &Path to PathBuf - .collect::>() // Collect all PathBufs, since self.get needs to borrow self mutably. - .into_iter() - .map(|path| Self::get_internal(&mut data, &self.fetcher, path)) - .collect::>>() - } else { + // If the directory hasn't been marked as enumerated yet, find + // all of its children and insert them into the VFS. + if !dir.children_enumerated { dir.children_enumerated = true; - self.fetcher + let children = self + .fetcher .read_children(path) - .map_err(|err| FsError::new(err, path.to_path_buf()))? - .into_iter() - .map(|path| Self::get_internal(&mut data, &self.fetcher, path)) - .collect::>>() + .map_err(|err| FsError::new(err, path.to_path_buf()))?; + + for path in children { + Self::get_internal(&mut data, &self.fetcher, path)?; + } } + + data.children(path) + .unwrap() // TODO: Handle None here, which means the PathMap entry did not exist. + .into_iter() + .map(PathBuf::from) // Convert paths from &Path to PathBuf + .collect::>() // Collect all PathBufs, since self.get needs to borrow self mutably. + .into_iter() + .map(|path| Self::get_internal(&mut data, &self.fetcher, path)) + .collect::>>() } VfsItem::File(_) => Err(FsError::new( io::Error::new(io::ErrorKind::Other, "Can't read a directory"), From dfb015acc2e753c291855f8a076118b3c8d6962f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Nov 2019 18:20:55 -0800 Subject: [PATCH 0864/1504] Add Rojo C API experiment --- .gitignore | 3 +++ Cargo.lock | 7 +++++++ Cargo.toml | 2 ++ clibrojo/Cargo.toml | 13 +++++++++++++ clibrojo/README.md | 4 ++++ clibrojo/src/lib.rs | 14 ++++++++++++++ 6 files changed, 43 insertions(+) create mode 100644 clibrojo/Cargo.toml create mode 100644 clibrojo/README.md create mode 100644 clibrojo/src/lib.rs diff --git a/.gitignore b/.gitignore index 835db166..a4ba062d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ # Rust output directory /target +# Headers for clibrojo +/include + # Roblox model and place files in the root, used for debugging /*.rbxm /*.rbxmx diff --git a/Cargo.lock b/Cargo.lock index 524044bd..c7fcbe40 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -181,6 +181,13 @@ dependencies = [ "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "clibrojo" +version = "0.1.0" +dependencies = [ + "rojo 0.6.0-dev", +] + [[package]] name = "clicolors-control" version = "1.0.1" diff --git a/Cargo.toml b/Cargo.toml index f37be268..eb234dfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,12 +26,14 @@ user-plugins = [] members = [ "rojo-test", "rojo-insta-ext", + "clibrojo", ] default-members = [ ".", "rojo-test", "rojo-insta-ext", + "clibrojo", ] [lib] diff --git a/clibrojo/Cargo.toml b/clibrojo/Cargo.toml new file mode 100644 index 00000000..19420607 --- /dev/null +++ b/clibrojo/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "clibrojo" +version = "0.1.0" +authors = ["Lucien Greathouse "] +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +rojo = { path = ".." } diff --git a/clibrojo/README.md b/clibrojo/README.md new file mode 100644 index 00000000..3c315c55 --- /dev/null +++ b/clibrojo/README.md @@ -0,0 +1,4 @@ +# Rojo as a C Library +This is an experiment to expose a C API for Rojo that would be suitable for embedding it into an existing C/C++ application. + +I'm hoping to expand it to drop the HTTP layer and communicate through a channel, which could make it feasible to embed into an existing Roblox IDE with minimal changes or additional code. \ No newline at end of file diff --git a/clibrojo/src/lib.rs b/clibrojo/src/lib.rs new file mode 100644 index 00000000..0c3dbbf7 --- /dev/null +++ b/clibrojo/src/lib.rs @@ -0,0 +1,14 @@ +use std::{ffi::CStr, os::raw::c_char, path::PathBuf}; + +use librojo::commands::{serve, ServeOptions}; + +#[no_mangle] +pub extern "C" fn rojo_serve(path: *const c_char) { + let path = unsafe { PathBuf::from(CStr::from_ptr(path).to_str().unwrap()) }; + + serve(&ServeOptions { + fuzzy_project_path: path, + port: None, + }) + .unwrap(); +} From 94e1501329ed7f3c65d87bf3f717d811e40c7ab3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 7 Nov 2019 18:24:16 -0800 Subject: [PATCH 0865/1504] Stop having clibrojo as a default project, update docs --- Cargo.toml | 1 - clibrojo/README.md | 17 ++++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index eb234dfa..7ced4938 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,7 +33,6 @@ default-members = [ ".", "rojo-test", "rojo-insta-ext", - "clibrojo", ] [lib] diff --git a/clibrojo/README.md b/clibrojo/README.md index 3c315c55..d8821ed9 100644 --- a/clibrojo/README.md +++ b/clibrojo/README.md @@ -1,4 +1,19 @@ # Rojo as a C Library This is an experiment to expose a C API for Rojo that would be suitable for embedding it into an existing C/C++ application. -I'm hoping to expand it to drop the HTTP layer and communicate through a channel, which could make it feasible to embed into an existing Roblox IDE with minimal changes or additional code. \ No newline at end of file +I'm hoping to expand it to drop the HTTP layer and communicate through a channel, which could make it feasible to embed into an existing Roblox IDE with minimal changes or additional code. + +## Building +This project is currently not built by default and could break/disappear at any time. + +```bash +cargo build -p clibrojo +``` + +On Windows, Cargo will generate a `clibrojo.dll` and associated `.lib` file. Link these into your project. + +To generate the associated C header file to include in the project, use [cbindgen](https://github.com/eqrion/cbindgen): + +```bash +cbindgen --crate clibrojo --output include/rojo.h +``` \ No newline at end of file From 47614c3102548f185fad44d5effb6ddd0dc42265 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Nov 2019 17:52:09 -0800 Subject: [PATCH 0866/1504] Update names in subscribe portion of sync protocol --- plugin/src/ServeSession.lua | 10 +--------- .../serve_test__add_folder_subscribe.snap | 6 +++--- ...ve_test__move_folder_of_stuff_subscribe.snap | 6 +++--- .../serve_test__scripts_subscribe.snap | 6 +++--- rojo-test/src/internable.rs | 4 ++-- src/web/api.rs | 17 ++++++++--------- src/web/interface.rs | 6 +++--- 7 files changed, 23 insertions(+), 32 deletions(-) diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 1e1d95b3..0ce9427c 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -103,15 +103,7 @@ function ServeSession:__mainSyncLoop() return self.__apiContext:retrieveMessages() :andThen(function(messages) for _, message in ipairs(messages) do - -- TODO: Update server to return patches in correct format so - -- that we don't have to transform them for the reconciler. - local asPatch = { - removed = message.removedInstances, - updated = message.updatedInstances, - added = message.addedInstances, - } - - self.__reconciler:applyPatch(asPatch) + self.__reconciler:applyPatch(message) end if self.__status ~= Status.Disconnected then diff --git a/rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap b/rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap index 646fcfea..49d489dc 100644 --- a/rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap +++ b/rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap @@ -4,7 +4,7 @@ expression: "subscribe_response.intern_and_redact(&mut redactions, ())" --- messageCursor: 1 messages: - - addedInstances: + - added: id-3: Children: [] ClassName: Folder @@ -14,6 +14,6 @@ messages: Name: my-new-folder Parent: id-2 Properties: {} - removedInstances: [] - updatedInstances: [] + removed: [] + updated: [] sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_subscribe.snap b/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_subscribe.snap index 5ba30e26..fa026ed2 100644 --- a/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_subscribe.snap +++ b/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_subscribe.snap @@ -4,7 +4,7 @@ expression: "subscribe_response.intern_and_redact(&mut redactions, ())" --- messageCursor: 1 messages: - - addedInstances: + - added: id-10: Children: [] ClassName: StringValue @@ -144,6 +144,6 @@ messages: Value: Type: String Value: "File #5" - removedInstances: [] - updatedInstances: [] + removed: [] + updated: [] sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts_subscribe.snap b/rojo-test/serve-test-snapshots/serve_test__scripts_subscribe.snap index b3ee2237..7d52bc4d 100644 --- a/rojo-test/serve-test-snapshots/serve_test__scripts_subscribe.snap +++ b/rojo-test/serve-test-snapshots/serve_test__scripts_subscribe.snap @@ -4,9 +4,9 @@ expression: "subscribe_response.intern_and_redact(&mut redactions, ())" --- messageCursor: 1 messages: - - addedInstances: {} - removedInstances: [] - updatedInstances: + - added: {} + removed: [] + updated: - changedClassName: ~ changedMetadata: ~ changedName: ~ diff --git a/rojo-test/src/internable.rs b/rojo-test/src/internable.rs index 9c1cbb57..40abbdda 100644 --- a/rojo-test/src/internable.rs +++ b/rojo-test/src/internable.rs @@ -61,8 +61,8 @@ impl<'a> Internable<&'a HashMap>> for Instance<'a> { impl Internable<()> for SubscribeResponse<'_> { fn intern(&self, redactions: &mut RedactionMap, _extra: ()) { for message in &self.messages { - intern_instance_updates(redactions, &message.updated_instances); - intern_instance_additions(redactions, &message.added_instances); + intern_instance_updates(redactions, &message.updated); + intern_instance_additions(redactions, &message.added); } } } diff --git a/src/web/api.rs b/src/web/api.rs index fe7ad62c..9a81ef00 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -93,20 +93,19 @@ impl ApiService { let api_messages = messages .into_iter() .map(|message| { - let removed_instances = message.removed; + let removed = message.removed; - let mut added_instances = HashMap::new(); + let mut added = HashMap::new(); for id in message.added { let instance = tree.get_instance(id).unwrap(); - added_instances.insert(id, Instance::from_rojo_instance(instance)); + added.insert(id, Instance::from_rojo_instance(instance)); for instance in tree.descendants(id) { - added_instances - .insert(instance.id(), Instance::from_rojo_instance(instance)); + added.insert(instance.id(), Instance::from_rojo_instance(instance)); } } - let updated_instances = message + let updated = message .updated .into_iter() .map(|update| { @@ -126,9 +125,9 @@ impl ApiService { .collect(); SubscribeMessage { - removed_instances, - added_instances, - updated_instances, + removed, + added, + updated, } }) .collect(); diff --git a/src/web/interface.rs b/src/web/interface.rs index f748758c..01cb62c3 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -23,9 +23,9 @@ pub const PROTOCOL_VERSION: u64 = 3; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SubscribeMessage<'a> { - pub removed_instances: Vec, - pub added_instances: HashMap>, - pub updated_instances: Vec, + pub removed: Vec, + pub added: HashMap>, + pub updated: Vec, } #[derive(Debug, Serialize, Deserialize)] From 339fc979f5d83e5682db4dc1311d0b0db323e014 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Nov 2019 18:03:31 -0800 Subject: [PATCH 0867/1504] Add disabled test for removing file that currently hangs --- rojo-test/src/serve_test.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index 2b6394b4..390038c4 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -101,6 +101,37 @@ fn add_folder() { }); } +#[test] +#[ignore] // TODO: Removing files currently hangs ChangeProcessor +fn remove_file() { + run_serve_test("remove_file", |session, mut redactions| { + let info = session.get_api_rojo().unwrap(); + let root_id = info.root_instance_id; + + assert_yaml_snapshot!("remove_file_info", redactions.redacted_yaml(info)); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "remove_file_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); + + fs::remove_file(session.path().join("hello.txt")).unwrap(); + + let subscribe_response = session.get_api_subscribe(0).unwrap(); + assert_yaml_snapshot!( + "remove_file_subscribe", + subscribe_response.intern_and_redact(&mut redactions, ()) + ); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "remove_file_all-2", + read_response.intern_and_redact(&mut redactions, root_id) + ); + }); +} + #[test] fn move_folder_of_stuff() { run_serve_test("move_folder_of_stuff", |session, mut redactions| { From d0d7c58af17dfc5d81312da5a4f47326436a99d8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 13 Nov 2019 18:34:48 -0800 Subject: [PATCH 0868/1504] Start tracking property changes in plugin --- plugin/src/InstanceMap.lua | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 86b542a1..132accda 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -9,10 +9,12 @@ local Log = require(script.Parent.Parent.Log) local InstanceMap = {} InstanceMap.__index = InstanceMap -function InstanceMap.new() +function InstanceMap.new(onInstanceChanged) local self = { fromIds = {}, fromInstances = {}, + instancesToSignal = {}, + onInstanceChanged = onInstanceChanged, } return setmetatable(self, InstanceMap) @@ -31,12 +33,14 @@ end function InstanceMap:insert(id, instance) self.fromIds[id] = instance self.fromInstances[instance] = id + self:__connectSignals(instance) end function InstanceMap:removeId(id) local instance = self.fromIds[id] if instance ~= nil then + self:__disconnectSignals(instance) self.fromIds[id] = nil self.fromInstances[instance] = nil else @@ -46,6 +50,7 @@ end function InstanceMap:removeInstance(instance) local id = self.fromInstances[instance] + self:__disconnectSignals(instance) if id ~= nil then self.fromInstances[instance] = nil @@ -88,4 +93,23 @@ function InstanceMap:destroyId(id) end end +function InstanceMap:__connectSignals(instance) + -- TODO: Connect to different event for ValueBase objects? + + self.instancesToSignal[instance] = instance.Changed:Connect(function(propertyName) + Log.trace("%s.%s changed", instance:GetFullName(), propertyName) + + if self.onInstanceChanged ~= nil then + self.onInstanceChanged(instance, propertyName) + end + end) +end + +function InstanceMap:__disconnectSignals(instance) + if self.instancesToSignal[instance] ~= nil then + self.instancesToSignal[instance]:Disconnect() + self.instancesToSignal[instance] = nil + end +end + return InstanceMap \ No newline at end of file From 57b28faa741f48a3fe10afd44f3a3f1308037f43 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Nov 2019 18:15:33 -0800 Subject: [PATCH 0869/1504] Update ApiSubcribeMessage signature --- plugin/src/Types.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugin/src/Types.lua b/plugin/src/Types.lua index ff7d7267..dac5f06c 100644 --- a/plugin/src/Types.lua +++ b/plugin/src/Types.lua @@ -33,9 +33,9 @@ local ApiInstanceUpdate = t.interface({ }) local ApiSubscribeMessage = t.interface({ - removedInstances = t.array(RbxId), - addedInstances = t.map(RbxId, ApiInstance), - updatedInstances = t.array(ApiInstanceUpdate), + removed = t.array(RbxId), + added = t.map(RbxId, ApiInstance), + updated = t.array(ApiInstanceUpdate), }) local ApiInfoResponse = t.interface({ From ccafdf250ebb52001751310bdc5007cece324831 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Nov 2019 18:15:53 -0800 Subject: [PATCH 0870/1504] Add counterpart to setCanonicalProperty for reading --- plugin/src/getCanonicalProperty.lua | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 plugin/src/getCanonicalProperty.lua diff --git a/plugin/src/getCanonicalProperty.lua b/plugin/src/getCanonicalProperty.lua new file mode 100644 index 00000000..a7fbc30f --- /dev/null +++ b/plugin/src/getCanonicalProperty.lua @@ -0,0 +1,37 @@ +local RbxDom = require(script.Parent.Parent.RbxDom) + +--[[ + Attempts to set a property on the given instance. +]] +local function getCanonincalProperty(instance, propertyName) + local descriptor = RbxDom.findCanonicalPropertyDescriptor(instance.ClassName, propertyName) + + -- We can skip unknown properties; they're not likely reflected to Lua. + -- + -- A good example of a property like this is `Model.ModelInPrimary`, which + -- is serialized but not reflected to Lua. + if descriptor == nil then + return false, "unknown property" + end + + if descriptor.scriptability == "None" or descriptor.scriptability == "Write" then + return false, "unreadable property" + end + + local success, err = descriptor:read(instance) + + if not success then + -- If we don't have permission to read a property, we can chalk that up + -- to our database being out of date and the engine being right. + if err.kind == RbxDom.Error.Kind.Roblox and err.extra:find("lacking permission") then + return false, "permission error" + end + + local message = ("Invalid property %s.%s: %s"):format(descriptor.className, descriptor.name, tostring(err)) + error(message, 2) + end + + return true +end + +return getCanonincalProperty \ No newline at end of file From 0b2e9ce1ad492cb306e636b3fe9d0bad4a65345c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Nov 2019 18:16:17 -0800 Subject: [PATCH 0871/1504] Improve InstanceMap tracking of ValueBase instances --- plugin/src/InstanceMap.lua | 49 +++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 132accda..e04f918d 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -94,20 +94,51 @@ function InstanceMap:destroyId(id) end function InstanceMap:__connectSignals(instance) - -- TODO: Connect to different event for ValueBase objects? + -- ValueBase instances have an overriden version of the Changed signal that + -- only detects changes to their Value property. + -- + -- We can instead connect listener to each individual property that we care + -- about on those objects (Name and Value) to emulate the same idea. + if instance:IsA("ValueBase") then + local signals = { + instance:GetPropertyChangedSignal("Name"):Connect(function() + self:__maybeFireInstanceChanged(instance, "Name") + end), - self.instancesToSignal[instance] = instance.Changed:Connect(function(propertyName) - Log.trace("%s.%s changed", instance:GetFullName(), propertyName) + instance:GetPropertyChangedSignal("Value"):Connect(function() + self:__maybeFireInstanceChanged(instance, "Value") + end), + } - if self.onInstanceChanged ~= nil then - self.onInstanceChanged(instance, propertyName) - end - end) + self.instancesToSignal[instance] = signals + else + self.instancesToSignal[instance] = instance.Changed:Connect(function(propertyName) + self:__maybeFireInstanceChanged(instance, propertyName) + end) + end +end + +function InstanceMap:__maybeFireInstanceChanged(instance, propertyName) + Log.trace("%s.%s changed", instance:GetFullName(), propertyName) + + if self.onInstanceChanged ~= nil then + self.onInstanceChanged(instance, propertyName) + end end function InstanceMap:__disconnectSignals(instance) - if self.instancesToSignal[instance] ~= nil then - self.instancesToSignal[instance]:Disconnect() + local signals = self.instancesToSignal[instance] + + if signals ~= nil then + -- In the general case, we avoid + if typeof(signals) == "table" then + for _, signal in ipairs(signals) do + signal:Disconnect() + end + else + signals:Disconnect() + end + self.instancesToSignal[instance] = nil end end From 2c88c700cac7c7ba5a101fc30c47e1793d24e623 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Nov 2019 18:16:48 -0800 Subject: [PATCH 0872/1504] Work around plugins loading too early by searching for DevSettings via ChildAdded --- plugin/src/DevSettings.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua index 1c9d0aa7..f1458c00 100644 --- a/plugin/src/DevSettings.lua +++ b/plugin/src/DevSettings.lua @@ -35,6 +35,16 @@ end local valueContainer = getValueContainer() +game.ChildAdded:Connect(function(child) + local success, name = pcall(function() + return child.Name + end) + + if success and name == CONTAINER_NAME then + valueContainer = child + end +end) + local function getStoredValue(name) if valueContainer == nil then return nil From fa736697a9c51dfc27b536adcef23715635b1d36 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Nov 2019 18:18:07 -0800 Subject: [PATCH 0873/1504] Introduce early Lua formatting library inspired by Rust --- plugin/default.project.json | 3 +++ plugin/fmt/init.lua | 54 +++++++++++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+) create mode 100644 plugin/fmt/init.lua diff --git a/plugin/default.project.json b/plugin/default.project.json index bdccf678..36ee57f1 100644 --- a/plugin/default.project.json +++ b/plugin/default.project.json @@ -11,6 +11,9 @@ "Http": { "$path": "http" }, + "Fmt": { + "$path": "fmt" + }, "Roact": { "$path": "modules/roact/src" }, diff --git a/plugin/fmt/init.lua b/plugin/fmt/init.lua new file mode 100644 index 00000000..387802c6 --- /dev/null +++ b/plugin/fmt/init.lua @@ -0,0 +1,54 @@ +local function debugOutputBuffer() + local buffer = {} + local indentLevel = 0 + local indentation = "" + + function buffer:push(template, ...) + local value = string.format(template, ...) + + if #indentation > 0 then + value = indentation .. value:gsub("\n", "\n" .. indentation) + end + + table.insert(self, value) + end + + function buffer:indent() + indentLevel = indentLevel + 1 + indentation = string.rep(" ", indentLevel) + end + + function buffer:unindent() + indentLevel = math.max(0, indentLevel - 1) + indentation = string.rep(" ", indentLevel) + end + + function buffer:finish() + return table.concat(self, "\n") + end + + return buffer +end + +local function debugInner(value) + local valueType = typeof(value) + + if valueType == "string" then + return string.format("%q", value) + elseif valueType == "number" then + return tostring(value) + elseif valueType == "table" then + local debugImpl = getmetatable(value).__fmtDebug + + if debugImpl ~= nil then + return debugImpl() + else + -- TODO: Nicer default debug implementation? + return tostring(value) + end + end +end + +return { + debugOutputBuffer = debugOutputBuffer, +} \ No newline at end of file From 6184f4ce4fcd997619b25038d60663f6c0274532 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Nov 2019 18:18:24 -0800 Subject: [PATCH 0874/1504] Improve debug output for initialization of ServeSession --- plugin/src/ServeSession.lua | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 0ce9427c..c9f0a9e5 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -1,3 +1,5 @@ +local Log = require(script.Parent.Parent.Log) +local Fmt = require(script.Parent.Parent.Fmt) local t = require(script.Parent.Parent.t) local strict = require(script.Parent.strict) @@ -9,20 +11,38 @@ local Status = strict("Session.Status", { Disconnected = "Disconnected", }) -local function DEBUG_printPatch(patch) +local function DEBUG_showPatch(patch) local HttpService = game:GetService("HttpService") + local output = Fmt.debugOutputBuffer() + + output:push("Patch {") + output:indent() + for removed in ipairs(patch.removed) do - print("Remove:", removed) + output:push("Remove ID %s", removed) end for id, added in pairs(patch.added) do - print("Add:", id, HttpService:JSONEncode(added)) + output:push("Add ID %s {", id) + output:indent() + output:push("%s", HttpService:JSONEncode(added)) + output:unindent() + output:push("}") end - for updated in ipairs(patch.updated) do - print("Update:", HttpService:JSONEncode(updated)) + for _, updated in ipairs(patch.updated) do + output:push("Update ID %s {", updated.id) + output:indent() + output:push("%s", HttpService:JSONEncode(updated)) + output:unindent() + output:push("}") end + + output:unindent() + output:push("}") + + return output:finish() end local ServeSession = {} @@ -84,6 +104,8 @@ function ServeSession:__initialSync(rootInstanceId) -- the tree defined in this response. self.__apiContext:setMessageCursor(readResponseBody.messageCursor) + Log.trace("Computing changes that plugin needs to make to catch up to server...") + -- Calculate the initial patch to apply to the DataModel to catch us -- up to what Rojo thinks the place should look like. local hydratePatch = self.__reconciler:hydrate( @@ -92,6 +114,8 @@ function ServeSession:__initialSync(rootInstanceId) game ) + Log.trace("Computed hydration patch: %s", DEBUG_showPatch(hydratePatch)) + -- TODO: Prompt user to notify them of this patch, since it's -- effectively a conflict between the Rojo server and the client. From 3f8b178f88081b48f94710e58e1763a55e1878f8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Nov 2019 18:18:38 -0800 Subject: [PATCH 0875/1504] Add support for computing property and name changes in hydration patch computation --- plugin/src/Reconciler.lua | 33 +++++++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 66762e0d..456ed2aa 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -9,6 +9,7 @@ local t = require(script.Parent.Parent.t) local InstanceMap = require(script.Parent.InstanceMap) local Types = require(script.Parent.Types) local invariant = require(script.Parent.invariant) +local getCanonicalProperty = require(script.Parent.getCanonicalProperty) local setCanonicalProperty = require(script.Parent.setCanonicalProperty) --[[ @@ -287,8 +288,36 @@ function Reconciler:__hydrateInternal(apiInstances, id, instance, hydratePatch) end end - -- TODO: Measure differences in properties and add them to - -- hydratePatch.updates + local changedName = nil + local changedProperties = {} + + if apiInstance.Name ~= instance.Name then + changedName = apiInstance.Name + end + + for propertyName, virtualValue in pairs(apiInstance.Properties) do + local success, existingValue = getCanonicalProperty(instance, propertyName) + + if success then + local decodedValue = self:__decodeApiValue(virtualValue) + + if existingValue ~= decodedValue then + changedProperties[propertyName] = virtualValue + end + end + end + + -- If any properties differed from the virtual instance we read, add it to + -- the hydrate patch so that we can catch up. + if changedName ~= nil or next(changedProperties) ~= nil then + table.insert(hydratePatch.updated, { + id = id, + changedName = changedName, + changedClassName = nil, + changedProperties = changedProperties, + changedMetadata = nil, + }) + end local existingChildren = instance:GetChildren() From b7d026b98ea9e8497c86031cd9189b5585ab380f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Nov 2019 18:43:51 -0800 Subject: [PATCH 0876/1504] Partial implementation of better formatting machinery --- plugin/fmt/init.lua | 77 +++++++++++++++++++++++++++++++++++-- plugin/src/ServeSession.lua | 2 +- 2 files changed, 74 insertions(+), 5 deletions(-) diff --git a/plugin/fmt/init.lua b/plugin/fmt/init.lua index 387802c6..88b4044f 100644 --- a/plugin/fmt/init.lua +++ b/plugin/fmt/init.lua @@ -1,18 +1,85 @@ +local function writeFmt(buffer, template, ...) + local currentArg = 0 + local i = 1 + local len = #template + + while i < len do + local openBrace = template:find("{", i) + + if openBrace == nil then + buffer:writeRaw(template:sub(i)) + break + else + if openBrace - i > 0 then + buffer:writeRaw(template:sub(i, openBrace - 1)) + end + + local charAfterBrace = template:sub(openBrace + 1, openBrace + 1) + if charAfterBrace == "{" then + buffer:writeRaw(template:sub(i, openBrace)) + i = openBrace + 2 + else + local closeBrace = template:find("}", openBrace + 1) + assert(closeBrace ~= nil, "Unclosed formatting specifier. Use '{{' to write an open brace.") + + local formatSpecifier = template:sub(openBrace + 1, closeBrace - 1) + + currentArg = currentArg + 1 + + if formatSpecifier == "" then + local arg = select(currentArg, ...) + buffer:writeRaw(tostring(arg)) + else + error("unsupported format specifier " .. formatSpecifier, 2) + end + + i = closeBrace + 1 + end + end + end +end + +local function writeLineFmt(buffer, template, ...) + writeFmt(buffer, template, ...) + table.insert(buffer, "\n") +end + local function debugOutputBuffer() local buffer = {} local indentLevel = 0 local indentation = "" - function buffer:push(template, ...) - local value = string.format(template, ...) + function buffer:writeLine(template, ...) + return writeLineFmt(self, template, ...) + end + function buffer:write(template, ...) + return writeFmt(self, template, ...) + end + + function buffer:writeRaw(value) if #indentation > 0 then - value = indentation .. value:gsub("\n", "\n" .. indentation) + value = value:gsub("\n", "\n" .. indentation) end table.insert(self, value) end + function buffer:writeLineRaw(piece) + if #indentation > 0 then + self:writeRaw(indentation) + end + + self:writeRaw(piece) + table.insert(self, "\n") + end + + function buffer:push(template, ...) + local value = string.format(template, ...) + + self:writeLineRaw(value) + end + function buffer:indent() indentLevel = indentLevel + 1 indentation = string.rep(" ", indentLevel) @@ -24,7 +91,7 @@ local function debugOutputBuffer() end function buffer:finish() - return table.concat(self, "\n") + return table.concat(self, "") end return buffer @@ -51,4 +118,6 @@ end return { debugOutputBuffer = debugOutputBuffer, + writeFmt = writeFmt, + writeLineFmt = writeLineFmt, } \ No newline at end of file diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index c9f0a9e5..c5263b6e 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -20,7 +20,7 @@ local function DEBUG_showPatch(patch) output:indent() for removed in ipairs(patch.removed) do - output:push("Remove ID %s", removed) + output:writeLine("Remove ID {}", removed) end for id, added in pairs(patch.added) do From 3126de2c379391d013872d565d37ec52cdb2aa8a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 15 Nov 2019 15:00:54 -0800 Subject: [PATCH 0877/1504] Build out real formatting machinery --- plugin/fmt/init.lua | 197 +++++++++++++++++++++++++++--------- plugin/src/ServeSession.lua | 22 ++-- 2 files changed, 156 insertions(+), 63 deletions(-) diff --git a/plugin/fmt/init.lua b/plugin/fmt/init.lua index 88b4044f..8699b2b7 100644 --- a/plugin/fmt/init.lua +++ b/plugin/fmt/init.lua @@ -1,34 +1,155 @@ +--[[ + This library describes a formatting mechanism akin to Rust's std::fmt. + + It has a couple building blocks: + + * A new syntax for formatting strings, taken verbatim from Rust. It'd also + be possible to use printf-style formatting specifiers to integrate with + the existing string.format utility. + + * An equivalent to Rust's `Display` trait. We're mapping the semantics of + tostring and the __tostring metamethod onto this trait. A lot of types + should already have __tostring implementations, too! + + * An equivalent to Rust's `Debug` trait. This library Lua-ifies that idea by + inventing a new metamethod, `__fmtDebug`. We pass along the "extended + form" attribute which is the equivalent of the "alternate mode" in Rust's + Debug trait since it's the author's opinion that treating it as a + verbosity flag is semantically accurate. +]] + +--[[ + The default implementation of __fmtDebug for tables when the extended option + is not set. +]] +local function defaultTableDebug(buffer, input) + buffer:writeRaw("{") + + for key, value in pairs(input) do + buffer:write("[{:?}] = {:?}", key, value) + + if next(input, key) ~= nil then + buffer:writeRaw(", ") + end + end + + buffer:writeRaw("}") +end + +--[[ + The default implementation of __fmtDebug for tables with the extended option + set. +]] +local function defaultTableDebugExtended(buffer, input) + -- Special case for empty tables. + if next(buffer) == nil then + buffer:writeRaw("{}") + return + end + + buffer:writeLineRaw("{") + buffer:indent() + + for key, value in pairs(input) do + buffer:writeLine("[{:?}] = {:#?},", key, value) + end + + buffer:unindent() + buffer:writeRaw("}") +end + +--[[ + The default debug representation for all types. +]] +local function debugImpl(buffer, value, extendedForm) + local valueType = typeof(value) + + if valueType == "string" then + local formatted = string.format("%q", value) + buffer:writeRaw(formatted) + elseif valueType == "table" then + local valueMeta = getmetatable(value) + + if valueMeta ~= nil and valueMeta.__fmtDebug ~= nil then + -- This type implement's the metamethod we made up to line up with + -- Rust's 'Debug' trait. + + valueMeta.__fmtDebug(value, buffer, extendedForm) + else + if extendedForm then + defaultTableDebugExtended(buffer, value) + else + defaultTableDebug(buffer, value) + end + end + else + buffer:writeRaw(tostring(value)) + end +end + +--[[ + Defines and implements the library's template syntax. +]] local function writeFmt(buffer, template, ...) local currentArg = 0 local i = 1 local len = #template - while i < len do + while i <= len do local openBrace = template:find("{", i) if openBrace == nil then + -- There are no remaining open braces in this string, so we can + -- write the rest of the string to the buffer. + buffer:writeRaw(template:sub(i)) break else - if openBrace - i > 0 then - buffer:writeRaw(template:sub(i, openBrace - 1)) - end + -- We found an open brace! This could be: + -- - A literal '{', written as '{{' + -- - The beginning of an interpolation, like '{}' + -- - An error, if there's no matching '}' local charAfterBrace = template:sub(openBrace + 1, openBrace + 1) if charAfterBrace == "{" then + -- This is a literal brace, so we'll write everything up to this + -- point (including the first brace), and then skip over the + -- second brace. + buffer:writeRaw(template:sub(i, openBrace)) i = openBrace + 2 else + -- This SHOULD be an interpolation. We'll find our matching + -- brace and treat the contents as the formatting specifier. + + -- If there were any unwritten characters before this + -- interpolation, write them to the buffer. + if openBrace - i > 0 then + buffer:writeRaw(template:sub(i, openBrace - 1)) + end + local closeBrace = template:find("}", openBrace + 1) assert(closeBrace ~= nil, "Unclosed formatting specifier. Use '{{' to write an open brace.") local formatSpecifier = template:sub(openBrace + 1, closeBrace - 1) - currentArg = currentArg + 1 + local arg = select(currentArg, ...) if formatSpecifier == "" then - local arg = select(currentArg, ...) + -- This should use the equivalent of Rust's 'Display', ie + -- tostring and the __tostring metamethod. + buffer:writeRaw(tostring(arg)) + elseif formatSpecifier == ":?" then + -- This should use the equivalent of Rust's 'Debug', + -- invented for this library as __fmtDebug. + + debugImpl(buffer, arg, false) + elseif formatSpecifier == ":#?" then + -- This should use the equivlant of Rust's 'Debug' with the + -- 'alternate' (ie expanded) flag set. + + debugImpl(buffer, arg, true) else error("unsupported format specifier " .. formatSpecifier, 2) end @@ -39,18 +160,20 @@ local function writeFmt(buffer, template, ...) end end -local function writeLineFmt(buffer, template, ...) - writeFmt(buffer, template, ...) - table.insert(buffer, "\n") -end - local function debugOutputBuffer() local buffer = {} + local startOfLine = true local indentLevel = 0 local indentation = "" function buffer:writeLine(template, ...) - return writeLineFmt(self, template, ...) + writeFmt(self, template, ...) + self:nextLine() + end + + function buffer:writeLineRaw(value) + self:writeRaw(value) + self:nextLine() end function buffer:write(template, ...) @@ -58,26 +181,20 @@ local function debugOutputBuffer() end function buffer:writeRaw(value) - if #indentation > 0 then - value = value:gsub("\n", "\n" .. indentation) - end + if #value > 0 then + if startOfLine and #indentation > 0 then + startOfLine = false + table.insert(self, indentation) + end - table.insert(self, value) + table.insert(self, value) + startOfLine = false + end end - function buffer:writeLineRaw(piece) - if #indentation > 0 then - self:writeRaw(indentation) - end - - self:writeRaw(piece) + function buffer:nextLine() table.insert(self, "\n") - end - - function buffer:push(template, ...) - local value = string.format(template, ...) - - self:writeLineRaw(value) + startOfLine = true end function buffer:indent() @@ -97,27 +214,13 @@ local function debugOutputBuffer() return buffer end -local function debugInner(value) - local valueType = typeof(value) - - if valueType == "string" then - return string.format("%q", value) - elseif valueType == "number" then - return tostring(value) - elseif valueType == "table" then - local debugImpl = getmetatable(value).__fmtDebug - - if debugImpl ~= nil then - return debugImpl() - else - -- TODO: Nicer default debug implementation? - return tostring(value) - end - end +local function fmt(template, ...) + local buffer = debugOutputBuffer() + writeFmt(buffer, template, ...) + return buffer:finish() end return { debugOutputBuffer = debugOutputBuffer, - writeFmt = writeFmt, - writeLineFmt = writeLineFmt, + fmt = fmt, } \ No newline at end of file diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index c5263b6e..0b533893 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -11,12 +11,10 @@ local Status = strict("Session.Status", { Disconnected = "Disconnected", }) -local function DEBUG_showPatch(patch) - local HttpService = game:GetService("HttpService") - +local function fmtPatch(patch) local output = Fmt.debugOutputBuffer() - output:push("Patch {") + output:writeLine("Patch {{") output:indent() for removed in ipairs(patch.removed) do @@ -24,23 +22,15 @@ local function DEBUG_showPatch(patch) end for id, added in pairs(patch.added) do - output:push("Add ID %s {", id) - output:indent() - output:push("%s", HttpService:JSONEncode(added)) - output:unindent() - output:push("}") + output:writeLine("Add ID {} {:#?}", id, added) end for _, updated in ipairs(patch.updated) do - output:push("Update ID %s {", updated.id) - output:indent() - output:push("%s", HttpService:JSONEncode(updated)) - output:unindent() - output:push("}") + output:writeLine("Update ID {} {:#?}", updated.id, updated) end output:unindent() - output:push("}") + output:writeLine("}") return output:finish() end @@ -114,7 +104,7 @@ function ServeSession:__initialSync(rootInstanceId) game ) - Log.trace("Computed hydration patch: %s", DEBUG_showPatch(hydratePatch)) + Log.trace("Computed hydration patch: %s", fmtPatch(hydratePatch)) -- TODO: Prompt user to notify them of this patch, since it's -- effectively a conflict between the Rojo server and the client. From 3a9f4383909f2998cebf3a5342b60fed64a9bb1f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 15 Nov 2019 15:39:15 -0800 Subject: [PATCH 0878/1504] Integrate fmt into log --- plugin/fmt/init.lua | 17 +++++++++++++++++ plugin/http/init.lua | 6 +++--- plugin/log/init.lua | 10 ++++++---- plugin/src/InstanceMap.lua | 2 +- plugin/src/ServeSession.lua | 36 +++++++++++++++++------------------- 5 files changed, 44 insertions(+), 27 deletions(-) diff --git a/plugin/fmt/init.lua b/plugin/fmt/init.lua index 8699b2b7..0fd30fd6 100644 --- a/plugin/fmt/init.lua +++ b/plugin/fmt/init.lua @@ -220,7 +220,24 @@ local function fmt(template, ...) return buffer:finish() end +--[[ + Wrap the given object in a type that implements the given function as its + Debug implementation, and forwards __tostring to the type's underlying + tostring implementation. +]] +local function debugify(object, fmtFunc) + return setmetatable({}, { + __fmtDebug = function(_, ...) + return fmtFunc(object, ...) + end, + __tostring = function() + return tostring(object) + end, + }) +end + return { debugOutputBuffer = debugOutputBuffer, fmt = fmt, + debugify = debugify, } \ No newline at end of file diff --git a/plugin/http/init.lua b/plugin/http/init.lua index 395bcc7e..faffa54a 100644 --- a/plugin/http/init.lua +++ b/plugin/http/init.lua @@ -17,7 +17,7 @@ local function performRequest(requestParams) local requestId = lastRequestId + 1 lastRequestId = requestId - Log.trace("%s(%d) %s", requestParams.Method, requestId, requestParams.Url) + Log.trace("HTTP {}({}) {}", requestParams.Method, requestId, requestParams.Url) if requestParams.Body ~= nil then Log.trace(requestParams.Body) @@ -30,10 +30,10 @@ local function performRequest(requestParams) end) if success then - Log.trace("Request %d success: status code %s", requestId, response.StatusCode) + Log.trace("Request {} success: status code {:?}", requestId, response.StatusCode) resolve(HttpResponse.fromRobloxResponse(response)) else - Log.trace("Request %d failure: %s", requestId, response) + Log.trace("Request {} failure: {:?}", requestId, response) reject(HttpError.fromRobloxErrorString(response)) end end)() diff --git a/plugin/log/init.lua b/plugin/log/init.lua index d3defd6d..dae88594 100644 --- a/plugin/log/init.lua +++ b/plugin/log/init.lua @@ -1,3 +1,5 @@ +local Fmt = require(script.Parent.Fmt) + local Level = { Error = 0, Warning = 1, @@ -29,25 +31,25 @@ end function Log.trace(template, ...) if getLogLevel() >= Level.Trace then - print(addTags(TRACE_TAG, string.format(template, ...))) + print(addTags(TRACE_TAG, Fmt.fmt(template, ...))) end end function Log.info(template, ...) if getLogLevel() >= Level.Info then - print(addTags(INFO_TAG, string.format(template, ...))) + print(addTags(INFO_TAG, Fmt.fmt(template, ...))) end end function Log.debug(template, ...) if getLogLevel() >= Level.Debug then - print(addTags(DEBUG_TAG, string.format(template, ...))) + print(addTags(DEBUG_TAG, Fmt.fmt(template, ...))) end end function Log.warn(template, ...) if getLogLevel() >= Level.Warning then - warn(addTags(WARN_TAG, string.format(template, ...))) + warn(addTags(WARN_TAG, Fmt.fmt(template, ...))) end end diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index e04f918d..43476fb3 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -119,7 +119,7 @@ function InstanceMap:__connectSignals(instance) end function InstanceMap:__maybeFireInstanceChanged(instance, propertyName) - Log.trace("%s.%s changed", instance:GetFullName(), propertyName) + Log.trace("{}.{} changed", instance:GetFullName(), propertyName) if self.onInstanceChanged ~= nil then self.onInstanceChanged(instance, propertyName) diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 0b533893..4bfb3b65 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -11,28 +11,26 @@ local Status = strict("Session.Status", { Disconnected = "Disconnected", }) -local function fmtPatch(patch) - local output = Fmt.debugOutputBuffer() +local function debugPatch(patch) + return Fmt.debugify(patch, function(patch, output) + output:writeLine("Patch {{") + output:indent() - output:writeLine("Patch {{") - output:indent() + for removed in ipairs(patch.removed) do + output:writeLine("Remove ID {}", removed) + end - for removed in ipairs(patch.removed) do - output:writeLine("Remove ID {}", removed) - end + for id, added in pairs(patch.added) do + output:writeLine("Add ID {} {:#?}", id, added) + end - for id, added in pairs(patch.added) do - output:writeLine("Add ID {} {:#?}", id, added) - end + for _, updated in ipairs(patch.updated) do + output:writeLine("Update ID {} {:#?}", updated.id, updated) + end - for _, updated in ipairs(patch.updated) do - output:writeLine("Update ID {} {:#?}", updated.id, updated) - end - - output:unindent() - output:writeLine("}") - - return output:finish() + output:unindent() + output:write("}") + end) end local ServeSession = {} @@ -104,7 +102,7 @@ function ServeSession:__initialSync(rootInstanceId) game ) - Log.trace("Computed hydration patch: %s", fmtPatch(hydratePatch)) + Log.trace("Computed hydration patch: {:#?}", debugPatch(hydratePatch)) -- TODO: Prompt user to notify them of this patch, since it's -- effectively a conflict between the Rojo server and the client. From 2467004dc281c1ce1863c4252493b0d224ab07fe Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 15 Nov 2019 15:40:03 -0800 Subject: [PATCH 0879/1504] Update HTTP logs --- plugin/http/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/http/init.lua b/plugin/http/init.lua index faffa54a..ec7e2713 100644 --- a/plugin/http/init.lua +++ b/plugin/http/init.lua @@ -30,7 +30,7 @@ local function performRequest(requestParams) end) if success then - Log.trace("Request {} success: status code {:?}", requestId, response.StatusCode) + Log.trace("Request {} success, status code {}", requestId, response.StatusCode) resolve(HttpResponse.fromRobloxResponse(response)) else Log.trace("Request {} failure: {:?}", requestId, response) From 3c3359999c9f70a67de3933ceac2e5869a9a11b5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 15 Nov 2019 15:42:11 -0800 Subject: [PATCH 0880/1504] Fix hydration patch incorrectly comparing properties --- plugin/src/Reconciler.lua | 2 ++ plugin/src/getCanonicalProperty.lua | 6 ++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 456ed2aa..7ab35cb6 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -5,6 +5,7 @@ local RbxDom = require(script.Parent.Parent.RbxDom) local t = require(script.Parent.Parent.t) +local Log = require(script.Parent.Parent.Log) local InstanceMap = require(script.Parent.InstanceMap) local Types = require(script.Parent.Types) @@ -302,6 +303,7 @@ function Reconciler:__hydrateInternal(apiInstances, id, instance, hydratePatch) local decodedValue = self:__decodeApiValue(virtualValue) if existingValue ~= decodedValue then + Log.warn("Diff! {:?} vs {:?}", existingValue, decodedValue) changedProperties[propertyName] = virtualValue end end diff --git a/plugin/src/getCanonicalProperty.lua b/plugin/src/getCanonicalProperty.lua index a7fbc30f..288d5989 100644 --- a/plugin/src/getCanonicalProperty.lua +++ b/plugin/src/getCanonicalProperty.lua @@ -18,9 +18,11 @@ local function getCanonincalProperty(instance, propertyName) return false, "unreadable property" end - local success, err = descriptor:read(instance) + local success, valueOrErr = descriptor:read(instance) if not success then + local err = valueOrErr + -- If we don't have permission to read a property, we can chalk that up -- to our database being out of date and the engine being right. if err.kind == RbxDom.Error.Kind.Roblox and err.extra:find("lacking permission") then @@ -31,7 +33,7 @@ local function getCanonincalProperty(instance, propertyName) error(message, 2) end - return true + return true, valueOrErr end return getCanonincalProperty \ No newline at end of file From 2493c70241e0bf2a9828e8910f7b2e3bfd4ebb4c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 15 Nov 2019 15:43:42 -0800 Subject: [PATCH 0881/1504] Fix log special case for empty tables --- plugin/fmt/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/fmt/init.lua b/plugin/fmt/init.lua index 0fd30fd6..7e2db533 100644 --- a/plugin/fmt/init.lua +++ b/plugin/fmt/init.lua @@ -42,7 +42,7 @@ end ]] local function defaultTableDebugExtended(buffer, input) -- Special case for empty tables. - if next(buffer) == nil then + if next(input) == nil then buffer:writeRaw("{}") return end From af866f066565738527243e1d65341c362a816770 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 15 Nov 2019 15:54:58 -0800 Subject: [PATCH 0882/1504] Fix request timeout in long polling causing error to bubble to console --- plugin/src/ApiContext.lua | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 49757dac..5d9ba67e 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -9,6 +9,13 @@ local validateApiInfo = Types.ifEnabled(Types.ApiInfoResponse) local validateApiRead = Types.ifEnabled(Types.ApiReadResponse) local validateApiSubscribe = Types.ifEnabled(Types.ApiSubscribeResponse) +--[[ + Returns a promise that will never resolve nor reject. +]] +local function hangingPromise() + return Promise.new(function() end) +end + local function rejectFailedRequests(response) if response.code >= 400 then -- TODO: Nicer error types for responses, using response JSON if valid. @@ -139,8 +146,12 @@ function ApiContext:retrieveMessages() local function sendRequest() return Http.get(url) :catch(function(err) - if err.type == Http.Error.Kind.Timeout and self.__connected then - return sendRequest() + if err.type == Http.Error.Kind.Timeout then + if self.__connected then + return sendRequest() + else + return hangingPromise() + end end return Promise.reject(err) From 0c7a94c062cb8d12790627c8efaf240a936eba6a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 18 Nov 2019 15:18:06 -0800 Subject: [PATCH 0883/1504] Update more code to new formatting machinery --- plugin/src/Components/App.lua | 4 ++-- plugin/src/InstanceMap.lua | 18 ++++++++++-------- plugin/src/Reconciler.lua | 10 +++++----- plugin/src/invariant.lua | 6 ++++-- plugin/src/preloadAssets.lua | 2 +- 5 files changed, 22 insertions(+), 18 deletions(-) diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 246b60cd..824f6d10 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -133,7 +133,7 @@ function App:startSession(address, port) -- Details being present indicates that this -- disconnection was from an error. if details ~= nil then - Log.warn(tostring(details)) + Log.warn("Disconnected from an error: {}", details) self:setState({ appStatus = AppStatus.Error, @@ -207,7 +207,7 @@ function App:render() end function App:didMount() - Log.trace("Rojo %s initializing", self.displayedVersion) + Log.trace("Rojo {} initializing", self.displayedVersion) checkUpgrade(self.props.plugin) preloadAssets() diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 43476fb3..4c497c0a 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -20,14 +20,16 @@ function InstanceMap.new(onInstanceChanged) return setmetatable(self, InstanceMap) end -function InstanceMap:debugState() - local buffer = {} +function InstanceMap:__fmtDebug(output) + output:writeLine("InstanceMap {{") + output:indent() for id, instance in pairs(self.fromIds) do - table.insert(buffer, string.format("- %s: %s", id, instance:GetFullName())) + output:writeLine("- {}: {}", id, instance:GetFullName()) end - return table.concat(buffer, "\n") + output:unindent() + output:writeLine("}") end function InstanceMap:insert(id, instance) @@ -44,7 +46,7 @@ function InstanceMap:removeId(id) self.fromIds[id] = nil self.fromInstances[instance] = nil else - Log.warn("Attempted to remove nonexistant ID %s", tostring(id)) + Log.warn("Attempted to remove nonexistant ID {}", id) end end @@ -56,7 +58,7 @@ function InstanceMap:removeInstance(instance) self.fromInstances[instance] = nil self.fromIds[id] = nil else - Log.warn("Attempted to remove nonexistant instance %s", tostring(instance)) + Log.warn("Attempted to remove nonexistant instance {}", instance) end end @@ -66,7 +68,7 @@ function InstanceMap:destroyInstance(instance) if id ~= nil then self:destroyId(id) else - Log.warn("Attempted to destroy untracked instance %s", tostring(instance)) + Log.warn("Attempted to destroy untracked instance {}", instance) end end @@ -89,7 +91,7 @@ function InstanceMap:destroyId(id) instance:Destroy() else - Log.warn("Attempted to destroy nonexistant ID %s", tostring(id)) + Log.warn("Attempted to destroy nonexistant ID {}", id) end end diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 7ab35cb6..7bffa2b4 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -134,10 +134,10 @@ function Reconciler:applyPatch(patch) if parentInstance == nil then invariant( - "Cannot add an instance from a patch that has no parent.\nInstance %s with parent %s.\nInstanceMap state:\n%s", + "Cannot add an instance from a patch that has no parent.\nInstance {} with parent {}.\nState: {:#?}", id, - tostring(apiInstance.Parent), - self.__instanceMap:debugState() + apiInstance.Parent, + self.__instanceMap ) end @@ -150,9 +150,9 @@ function Reconciler:applyPatch(patch) if instance == nil then invariant( - "Cannot update an instance that does not exist in the reconciler's state.\nInstance ID %s\nInstanceMap state:\n%s", + "Cannot update an instance that does not exist in the reconciler's state.\nInstance {}\nState: {:#?}", update.id, - self.__instanceMap:debugState() + self.__instanceMap ) end diff --git a/plugin/src/invariant.lua b/plugin/src/invariant.lua index 3923095b..7cb813b4 100644 --- a/plugin/src/invariant.lua +++ b/plugin/src/invariant.lua @@ -1,16 +1,18 @@ +local Fmt = require(script.Parent.Parent.Fmt) + local Config = require(script.Parent.Config) local invariant if Config.isDevBuild then function invariant(message, ...) - message = string.format(message, ...) + message = Fmt.fmt(message, ...) error("Invariant violation: " .. message, 2) end else function invariant(message, ...) - message = string.format(message, ...) + message = Fmt.fmt(message, ...) local fullMessage = string.format( "Rojo detected an invariant violation within itself:\n" .. diff --git a/plugin/src/preloadAssets.lua b/plugin/src/preloadAssets.lua index a8a4a4f1..c23d2dd1 100644 --- a/plugin/src/preloadAssets.lua +++ b/plugin/src/preloadAssets.lua @@ -19,7 +19,7 @@ local function preloadAssets() table.insert(contentUrls, url) end - Log.trace("Preloading assets: %s", table.concat(contentUrls, ", ")) + Log.trace("Preloading assets: {:?}", contentUrls) coroutine.wrap(function() ContentProvider:PreloadAsync(contentUrls) From 463bf9b1164f8986cb0812696bf9b2c1cd6cb009 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 18 Nov 2019 15:57:22 -0800 Subject: [PATCH 0884/1504] Make errors scrollable when too long --- plugin/src/Components/ErrorPanel.lua | 40 +++++++++++++++------ plugin/src/Components/FitScrollingFrame.lua | 33 +++++++++++++++++ 2 files changed, 62 insertions(+), 11 deletions(-) create mode 100644 plugin/src/Components/FitScrollingFrame.lua diff --git a/plugin/src/Components/ErrorPanel.lua b/plugin/src/Components/ErrorPanel.lua index 469b5390..97b16929 100644 --- a/plugin/src/Components/ErrorPanel.lua +++ b/plugin/src/Components/ErrorPanel.lua @@ -6,10 +6,14 @@ local Theme = require(Plugin.Theme) local Panel = require(Plugin.Components.Panel) local FitText = require(Plugin.Components.FitText) +local FitScrollingFrame = require(Plugin.Components.FitScrollingFrame) local FormButton = require(Plugin.Components.FormButton) local e = Roact.createElement +local BUTTON_HEIGHT = 60 +local HOR_PADDING = 8 + local ErrorPanel = Roact.Component:extend("ErrorPanel") function ErrorPanel:render() @@ -24,17 +28,31 @@ function ErrorPanel:render() Padding = UDim.new(0, 8), }), - Text = e(FitText, { - LayoutOrder = 1, - FitAxis = "Y", - Size = UDim2.new(1, 0, 0, 0), - Padding = Vector2.new(12, 6), - Font = Theme.ButtonFont, - TextSize = 18, - Text = errorMessage, - TextWrap = true, - TextColor3 = Theme.PrimaryColor, - BackgroundTransparency = 1, + ErrorContainer = e(FitScrollingFrame, { + containerProps = { + BackgroundTransparency = 1, + BorderSizePixel = 0, + Size = UDim2.new(1, -HOR_PADDING * 2, 1, -BUTTON_HEIGHT), + Position = UDim2.new(0, HOR_PADDING, 0, 0), + ScrollBarImageColor3 = Theme.PrimaryColor, + VerticalScrollBarInset = Enum.ScrollBarInset.ScrollBar, + ScrollingDirection = Enum.ScrollingDirection.Y, + }, + }, { + Text = e(FitText, { + Size = UDim2.new(1, 0, 0, 0), + + LayoutOrder = 1, + TextXAlignment = Enum.TextXAlignment.Left, + TextYAlignment = Enum.TextYAlignment.Top, + FitAxis = "Y", + Font = Theme.ButtonFont, + TextSize = 18, + Text = errorMessage, + TextWrap = true, + TextColor3 = Theme.PrimaryColor, + BackgroundTransparency = 1, + }), }), DismissButton = e(FormButton, { diff --git a/plugin/src/Components/FitScrollingFrame.lua b/plugin/src/Components/FitScrollingFrame.lua new file mode 100644 index 00000000..ede927fd --- /dev/null +++ b/plugin/src/Components/FitScrollingFrame.lua @@ -0,0 +1,33 @@ +local Roact = require(script:FindFirstAncestor("Rojo").Roact) + +local Dictionary = require(script.Parent.Parent.Dictionary) + +local e = Roact.createElement + +local FitScrollingFrame = Roact.Component:extend("FitScrollingFrame") + +function FitScrollingFrame:init() + self.sizeBinding, self.setSize = Roact.createBinding(UDim2.new()) +end + +function FitScrollingFrame:render() + local containerProps = self.props.containerProps + local layoutProps = self.props.layoutProps + + local children = Dictionary.merge(self.props[Roact.Children], { + ["$Layout"] = e("UIListLayout", Dictionary.merge({ + SortOrder = Enum.SortOrder.LayoutOrder, + [Roact.Change.AbsoluteContentSize] = function(instance) + self.setSize(UDim2.new(0, 0, 0, instance.AbsoluteContentSize.Y)) + end, + }, layoutProps)), + }) + + local fullContainerProps = Dictionary.merge(containerProps, { + CanvasSize = self.sizeBinding, + }) + + return e("ScrollingFrame", fullContainerProps, children) +end + +return FitScrollingFrame \ No newline at end of file From bdaa671823e29a02f1d8913884d894bf1f0016f2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 18 Nov 2019 16:30:57 -0800 Subject: [PATCH 0885/1504] Plugin: Pipe InstanceMap around, improve debug output, fix session ID bug --- plugin/src/ApiContext.lua | 21 +++++++++++++++++---- plugin/src/Components/App.lua | 2 -- plugin/src/InstanceMap.lua | 17 +++++++++++++++-- plugin/src/Reconciler.lua | 5 ++--- plugin/src/ServeSession.lua | 20 ++++++++++++++++++-- 5 files changed, 52 insertions(+), 13 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 5d9ba67e..32cea89b 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -87,7 +87,7 @@ function ApiContext.new(baseUrl) local self = { __baseUrl = baseUrl, - __serverId = nil, + __sessionId = nil, __messageCursor = -1, __connected = true, } @@ -95,6 +95,19 @@ function ApiContext.new(baseUrl) return setmetatable(self, ApiContext) end +function ApiContext:__fmtDebug(output) + output:writeLine("ApiContext {{") + output:indent() + + output:writeLine("Connected: {}", self.__connected) + output:writeLine("Base URL: {}", self.__baseUrl) + output:writeLine("Session ID: {}", self.__sessionId) + output:writeLine("Message Cursor: {}", self.__messageCursor) + + output:unindent() + output:write("}") +end + function ApiContext:disconnect() self.__connected = false end @@ -117,7 +130,7 @@ function ApiContext:connect() end) :andThen(rejectWrongPlaceId) :andThen(function(body) - self.__serverId = body.serverId + self.__sessionId = body.sessionId return body end) @@ -130,7 +143,7 @@ function ApiContext:read(ids) :andThen(rejectFailedRequests) :andThen(Http.Response.json) :andThen(function(body) - if body.serverId ~= self.__serverId then + if body.sessionId ~= self.__sessionId then return Promise.reject("Server changed ID") end @@ -162,7 +175,7 @@ function ApiContext:retrieveMessages() :andThen(rejectFailedRequests) :andThen(Http.Response.json) :andThen(function(body) - if body.serverId ~= self.__serverId then + if body.sessionId ~= self.__sessionId then return Promise.reject("Server changed ID") end diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 824f6d10..9fbb3c0a 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -8,7 +8,6 @@ local ApiContext = require(Plugin.ApiContext) local Assets = require(Plugin.Assets) local Config = require(Plugin.Config) local DevSettings = require(Plugin.DevSettings) -local Reconciler = require(Plugin.Reconciler) local ServeSession = require(Plugin.ServeSession) local Version = require(Plugin.Version) local preloadAssets = require(Plugin.preloadAssets) @@ -115,7 +114,6 @@ function App:startSession(address, port) local baseUrl = ("http://%s:%s"):format(address, port) self.serveSession = ServeSession.new({ apiContext = ApiContext.new(baseUrl), - reconciler = Reconciler.new(), }) self.serveSession:onStatusChanged(function(status, details) diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 4c497c0a..d1a6a1a7 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -24,12 +24,25 @@ function InstanceMap:__fmtDebug(output) output:writeLine("InstanceMap {{") output:indent() + -- Collect all of the entries in the InstanceMap and sort them by their + -- label, which helps make our output deterministic. + local entries = {} for id, instance in pairs(self.fromIds) do - output:writeLine("- {}: {}", id, instance:GetFullName()) + local label = string.format("%s (%s)", instance:GetFullName(), instance.ClassName) + + table.insert(entries, {id, label}) + end + + table.sort(entries, function(a, b) + return a[2] < b[2] + end) + + for _, entry in ipairs(entries) do + output:writeLine("{}: {}", entry[1], entry[2]) end output:unindent() - output:writeLine("}") + output:write("}") end function InstanceMap:insert(id, instance) diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 7bffa2b4..36c19037 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -7,7 +7,6 @@ local RbxDom = require(script.Parent.Parent.RbxDom) local t = require(script.Parent.Parent.t) local Log = require(script.Parent.Parent.Log) -local InstanceMap = require(script.Parent.InstanceMap) local Types = require(script.Parent.Types) local invariant = require(script.Parent.invariant) local getCanonicalProperty = require(script.Parent.getCanonicalProperty) @@ -55,10 +54,10 @@ end local Reconciler = {} Reconciler.__index = Reconciler -function Reconciler.new() +function Reconciler.new(instanceMap) local self = { -- Tracks all of the instances known by the reconciler by ID. - __instanceMap = InstanceMap.new(), + __instanceMap = instanceMap, } return setmetatable(self, Reconciler) diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 4bfb3b65..9f33814c 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -2,6 +2,8 @@ local Log = require(script.Parent.Parent.Log) local Fmt = require(script.Parent.Parent.Fmt) local t = require(script.Parent.Parent.t) +local InstanceMap = require(script.Parent.InstanceMap) +local Reconciler = require(script.Parent.Reconciler) local strict = require(script.Parent.strict) local Status = strict("Session.Status", { @@ -40,16 +42,19 @@ ServeSession.Status = Status local validateServeOptions = t.strictInterface({ apiContext = t.table, - reconciler = t.table, }) function ServeSession.new(options) assert(validateServeOptions(options)) + local instanceMap = InstanceMap.new() + local reconciler = Reconciler.new(instanceMap) + local self = { __status = Status.NotStarted, __apiContext = options.apiContext, - __reconciler = options.reconciler, + __reconciler = reconciler, + __instanceMap = instanceMap, __statusChangedCallback = nil, } @@ -58,6 +63,17 @@ function ServeSession.new(options) return self end +function ServeSession:__fmtDebug(output) + output:writeLine("ServeSession {{") + output:indent() + + output:writeLine("API Context: {:#?}", self.__apiContext) + output:writeLine("Instances: {:#?}", self.__instanceMap) + + output:unindent() + output:write("}") +end + function ServeSession:onStatusChanged(callback) self.__statusChangedCallback = callback end From 459bf62fabb2610ff3c02b02efd0657e8948fb49 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 18 Nov 2019 16:52:19 -0800 Subject: [PATCH 0886/1504] Add missing contents for disabled remove_file test --- rojo-test/serve-tests/remove_file/hello.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 rojo-test/serve-tests/remove_file/hello.txt diff --git a/rojo-test/serve-tests/remove_file/hello.txt b/rojo-test/serve-tests/remove_file/hello.txt new file mode 100644 index 00000000..fef1b75f --- /dev/null +++ b/rojo-test/serve-tests/remove_file/hello.txt @@ -0,0 +1 @@ +This file will be removed! \ No newline at end of file From bcffd2eb9956d640b5a6891ac21bd783ac9a792d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 18 Nov 2019 18:08:12 -0800 Subject: [PATCH 0887/1504] Add support for removing files, handled in ChangeProcessor --- src/change_processor.rs | 66 ++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index 0157cc58..2aa76eaa 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -11,9 +11,11 @@ use rbx_dom_weak::RbxId; use crate::{ message_queue::MessageQueue, - snapshot::{apply_patch_set, compute_patch_set, AppliedPatchSet, InstigatingSource, RojoTree}, + snapshot::{ + apply_patch_set, compute_patch_set, AppliedPatchSet, InstigatingSource, PatchSet, RojoTree, + }, snapshot_middleware::{snapshot_from_vfs, snapshot_project_node, InstanceSnapshotContext}, - vfs::{Vfs, VfsEvent, VfsFetcher}, + vfs::{FsResultExt, Vfs, VfsEvent, VfsFetcher}, }; pub struct ChangeProcessor { @@ -143,30 +145,58 @@ fn update_affected_instances( // every time. let mut snapshot_context = InstanceSnapshotContext::default(); - let snapshot = match instigating_source { + // How we process a file change event depends on what created this + // file/folder in the first place. + let applied_patch_set = match instigating_source { InstigatingSource::Path(path) => { - let entry = vfs + let maybe_entry = vfs .get(path) - .expect("could not get instigating path from filesystem"); + .with_not_found() + .expect("unexpected VFS error"); - snapshot_from_vfs(&mut snapshot_context, &vfs, &entry) - .expect("snapshot failed") - .expect("snapshot did not return an instance") + match maybe_entry { + Some(entry) => { + // Our instance was previously created from a path and + // that path still exists. We can generate a snapshot + // starting at that path and use it as the source for + // our patch. + + let snapshot = snapshot_from_vfs(&mut snapshot_context, &vfs, &entry) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + let patch_set = compute_patch_set(&snapshot, &tree, id); + apply_patch_set(tree, patch_set) + } + None => { + // Our instance was previously created from a path, but + // that path no longer exists. + // + // We associate deleting the instigating file for an + // instance with deleting that instance. + + let mut patch_set = PatchSet::new(); + patch_set.removed_instances.push(id); + + apply_patch_set(tree, patch_set) + } + } } InstigatingSource::ProjectNode(instance_name, project_node) => { - snapshot_project_node(&mut snapshot_context, instance_name, project_node, &vfs) - .expect("snapshot failed") - .expect("snapshot did not return an instance") + // This instance is the direct subject of a project node. Since + // there might be information associated with our instance from + // the project file, we snapshot the entire project node again. + + let snapshot = + snapshot_project_node(&mut snapshot_context, instance_name, project_node, &vfs) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + let patch_set = compute_patch_set(&snapshot, &tree, id); + apply_patch_set(tree, patch_set) } }; - log::trace!("Computed snapshot: {:#?}", snapshot); - - let patch_set = compute_patch_set(&snapshot, &tree, id); - let applied_patch_set = apply_patch_set(tree, patch_set); - - log::trace!("Applied patch: {:#?}", applied_patch_set); - applied_patches.push(applied_patch_set); } } From 2d7ebac8e6c346137f1281d2d966f233fa923dd8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 18 Nov 2019 18:08:18 -0800 Subject: [PATCH 0888/1504] Enable test for removing files --- .../serve_test__remove_file_all-2.snap | 16 ++++++++++ .../serve_test__remove_file_all.snap | 29 +++++++++++++++++++ .../serve_test__remove_file_info.snap | 9 ++++++ .../serve_test__remove_file_subscribe.snap | 11 +++++++ rojo-test/src/serve_test.rs | 2 +- 5 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 rojo-test/serve-test-snapshots/serve_test__remove_file_all-2.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__remove_file_all.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__remove_file_info.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__remove_file_subscribe.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__remove_file_all-2.snap b/rojo-test/serve-test-snapshots/serve_test__remove_file_all-2.snap new file mode 100644 index 00000000..ce9ed750 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__remove_file_all-2.snap @@ -0,0 +1,16 @@ +--- +source: rojo-test/src/serve_test.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Children: [] + ClassName: Folder + Id: id-2 + Metadata: + ignoreUnknownInstances: false + Name: remove_file + Parent: ~ + Properties: {} +messageCursor: 1 +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__remove_file_all.snap b/rojo-test/serve-test-snapshots/serve_test__remove_file_all.snap new file mode 100644 index 00000000..e133c4ea --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__remove_file_all.snap @@ -0,0 +1,29 @@ +--- +source: rojo-test/src/serve_test.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Children: + - id-3 + ClassName: Folder + Id: id-2 + Metadata: + ignoreUnknownInstances: false + Name: remove_file + Parent: ~ + Properties: {} + id-3: + Children: [] + ClassName: StringValue + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: hello + Parent: id-2 + Properties: + Value: + Type: String + Value: This file will be removed! +messageCursor: 0 +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__remove_file_info.snap b/rojo-test/serve-test-snapshots/serve_test__remove_file_info.snap new file mode 100644 index 00000000..f826d7e7 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__remove_file_info.snap @@ -0,0 +1,9 @@ +--- +source: rojo-test/src/serve_test.rs +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +protocolVersion: 3 +rootInstanceId: id-2 +serverVersion: 0.6.0-dev +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__remove_file_subscribe.snap b/rojo-test/serve-test-snapshots/serve_test__remove_file_subscribe.snap new file mode 100644 index 00000000..e4f34a28 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__remove_file_subscribe.snap @@ -0,0 +1,11 @@ +--- +source: rojo-test/src/serve_test.rs +expression: "subscribe_response.intern_and_redact(&mut redactions, ())" +--- +messageCursor: 1 +messages: + - added: {} + removed: + - id-3 + updated: [] +sessionId: id-1 diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index 390038c4..fd29fd62 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -102,7 +102,7 @@ fn add_folder() { } #[test] -#[ignore] // TODO: Removing files currently hangs ChangeProcessor +// #[ignore] // TODO: Removing files currently hangs ChangeProcessor fn remove_file() { run_serve_test("remove_file", |session, mut redactions| { let info = session.get_api_rojo().unwrap(); From 78b2bafde16c5f87e56137da7cd0273f7dfe73d2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 18 Nov 2019 18:11:33 -0800 Subject: [PATCH 0889/1504] Add test for #267. --- rojo-test/serve-tests/edit_init/init.lua | 1 + rojo-test/src/serve_test.rs | 34 +++++++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 rojo-test/serve-tests/edit_init/init.lua diff --git a/rojo-test/serve-tests/edit_init/init.lua b/rojo-test/serve-tests/edit_init/init.lua new file mode 100644 index 00000000..0f333a5a --- /dev/null +++ b/rojo-test/serve-tests/edit_init/init.lua @@ -0,0 +1 @@ +-- Original contents \ No newline at end of file diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index fd29fd62..4377a982 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -102,7 +102,6 @@ fn add_folder() { } #[test] -// #[ignore] // TODO: Removing files currently hangs ChangeProcessor fn remove_file() { run_serve_test("remove_file", |session, mut redactions| { let info = session.get_api_rojo().unwrap(); @@ -132,6 +131,39 @@ fn remove_file() { }); } +#[test] +// Editing an init file currently crashes the ChangeProcessor thread. +// https://github.com/rojo-rbx/rojo/issues/267 +#[ignore] +fn edit_init() { + run_serve_test("edit_init", |session, mut redactions| { + let info = session.get_api_rojo().unwrap(); + let root_id = info.root_instance_id; + + assert_yaml_snapshot!("edit_init_info", redactions.redacted_yaml(info)); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "edit_init_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); + + fs::write(session.path().join("init.lua"), b"-- Edited contents.").unwrap(); + + let subscribe_response = session.get_api_subscribe(0).unwrap(); + assert_yaml_snapshot!( + "edit_init_subscribe", + subscribe_response.intern_and_redact(&mut redactions, ()) + ); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "edit_init_all-2", + read_response.intern_and_redact(&mut redactions, root_id) + ); + }); +} + #[test] fn move_folder_of_stuff() { run_serve_test("move_folder_of_stuff", |session, mut redactions| { From 715022def5ac9e380267530bc8273f991b83bbe0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 18 Nov 2019 18:16:37 -0800 Subject: [PATCH 0890/1504] Make init files copy metadata from folder. Fixes #267. --- .../serve_test__edit_init_all-2.snap | 19 +++++++++++++++++++ .../serve_test__edit_init_all.snap | 19 +++++++++++++++++++ .../serve_test__edit_init_info.snap | 9 +++++++++ .../serve_test__edit_init_subscribe.snap | 18 ++++++++++++++++++ rojo-test/src/serve_test.rs | 5 +---- src/snapshot_middleware/lua.rs | 2 +- 6 files changed, 67 insertions(+), 5 deletions(-) create mode 100644 rojo-test/serve-test-snapshots/serve_test__edit_init_all-2.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__edit_init_all.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__edit_init_info.snap create mode 100644 rojo-test/serve-test-snapshots/serve_test__edit_init_subscribe.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__edit_init_all-2.snap b/rojo-test/serve-test-snapshots/serve_test__edit_init_all-2.snap new file mode 100644 index 00000000..d11fbb4b --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__edit_init_all-2.snap @@ -0,0 +1,19 @@ +--- +source: rojo-test/src/serve_test.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Children: [] + ClassName: ModuleScript + Id: id-2 + Metadata: + ignoreUnknownInstances: false + Name: edit_init + Parent: ~ + Properties: + Source: + Type: String + Value: "-- Edited contents" +messageCursor: 1 +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__edit_init_all.snap b/rojo-test/serve-test-snapshots/serve_test__edit_init_all.snap new file mode 100644 index 00000000..9596f3a8 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__edit_init_all.snap @@ -0,0 +1,19 @@ +--- +source: rojo-test/src/serve_test.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Children: [] + ClassName: ModuleScript + Id: id-2 + Metadata: + ignoreUnknownInstances: false + Name: edit_init + Parent: ~ + Properties: + Source: + Type: String + Value: "-- Original contents" +messageCursor: 0 +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__edit_init_info.snap b/rojo-test/serve-test-snapshots/serve_test__edit_init_info.snap new file mode 100644 index 00000000..f826d7e7 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__edit_init_info.snap @@ -0,0 +1,9 @@ +--- +source: rojo-test/src/serve_test.rs +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +protocolVersion: 3 +rootInstanceId: id-2 +serverVersion: 0.6.0-dev +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__edit_init_subscribe.snap b/rojo-test/serve-test-snapshots/serve_test__edit_init_subscribe.snap new file mode 100644 index 00000000..ef6a4fc8 --- /dev/null +++ b/rojo-test/serve-test-snapshots/serve_test__edit_init_subscribe.snap @@ -0,0 +1,18 @@ +--- +source: rojo-test/src/serve_test.rs +expression: "subscribe_response.intern_and_redact(&mut redactions, ())" +--- +messageCursor: 1 +messages: + - added: {} + removed: [] + updated: + - changedClassName: ~ + changedMetadata: ~ + changedName: ~ + changedProperties: + Source: + Type: String + Value: "-- Edited contents" + id: id-2 +sessionId: id-1 diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index 4377a982..80ecae77 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -132,9 +132,6 @@ fn remove_file() { } #[test] -// Editing an init file currently crashes the ChangeProcessor thread. -// https://github.com/rojo-rbx/rojo/issues/267 -#[ignore] fn edit_init() { run_serve_test("edit_init", |session, mut redactions| { let info = session.get_api_rojo().unwrap(); @@ -148,7 +145,7 @@ fn edit_init() { read_response.intern_and_redact(&mut redactions, root_id) ); - fs::write(session.path().join("init.lua"), b"-- Edited contents.").unwrap(); + fs::write(session.path().join("init.lua"), b"-- Edited contents").unwrap(); let subscribe_response = session.get_api_subscribe(0).unwrap(); assert_yaml_snapshot!( diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index cba22156..abeb5773 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -138,7 +138,7 @@ fn snapshot_init( init_snapshot.name = dir_snapshot.name; init_snapshot.children = dir_snapshot.children; - // TODO: Apply metadata from folder + init_snapshot.metadata = dir_snapshot.metadata; return Ok(Some(init_snapshot)); } From 246fd5f6c45b403164ca5c87053b125e4495399d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 18 Nov 2019 18:28:36 -0800 Subject: [PATCH 0891/1504] Add init scripts as relevant paths to all directories. This doesn't feel ideal. Though it's true that all directories are influenced by any init scripts they have, the directory middleware shouldn't need to know about Lua. I don't really want to go back into working on the middleware chain since it mostly feels like busywork when there are other things to build on in Rojo. also all of this feels really complicated --- src/snapshot_middleware/dir.rs | 13 ++++++++++- src/snapshot_middleware/lua.rs | 18 +++++++++++++++ .../snapshots/test__empty_folder.snap | 3 +++ .../snapshots/test__folder_in_folder.snap | 6 +++++ .../snapshots/test__init_module_from_vfs.snap | 22 +++++++++++++++++++ ...rve_session__change_script_meta_after.snap | 3 +++ ...ve_session__change_script_meta_before.snap | 3 +++ src/snapshots/serve_session__just_folder.snap | 3 +++ .../serve_session__project_with_folder.snap | 3 +++ .../serve_session__script_with_meta.snap | 3 +++ 10 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 src/snapshot_middleware/snapshots/test__init_module_from_vfs.snap diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 7d1bed84..63303717 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -47,11 +47,22 @@ impl SnapshotMiddleware for SnapshotDir { let meta_path = entry.path().join("init.meta.json"); + let relevant_paths = vec![ + entry.path().to_path_buf(), + meta_path.clone(), + // TODO: We shouldn't need to know about Lua existing in this + // middleware. Should we figure out a way for that function to add + // relevant paths to this middleware? + entry.path().join("init.lua"), + entry.path().join("init.server.lua"), + entry.path().join("init.client.lua"), + ]; + let mut snapshot = InstanceSnapshot { snapshot_id: None, metadata: InstanceMetadata { instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], + relevant_paths, ..Default::default() }, name: Cow::Owned(instance_name), diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index abeb5773..d5239cb3 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -204,6 +204,24 @@ mod test { assert_yaml_snapshot!(instance_snapshot); } + #[test] + fn init_module_from_vfs() { + let mut vfs = Vfs::new(NoopFetcher); + let dir = VfsSnapshot::dir(hashmap! { + "init.lua" => VfsSnapshot::file("Hello!"), + }); + + vfs.debug_load_snapshot("/root", dir); + + let entry = vfs.get("/root").unwrap(); + let instance_snapshot = + SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + .unwrap() + .unwrap(); + + assert_yaml_snapshot!(instance_snapshot); + } + #[test] fn module_with_meta() { let mut vfs = Vfs::new(NoopFetcher); diff --git a/src/snapshot_middleware/snapshots/test__empty_folder.snap b/src/snapshot_middleware/snapshots/test__empty_folder.snap index 8001ff69..8728c624 100644 --- a/src/snapshot_middleware/snapshots/test__empty_folder.snap +++ b/src/snapshot_middleware/snapshots/test__empty_folder.snap @@ -10,6 +10,9 @@ metadata: relevant_paths: - /foo - /foo/init.meta.json + - /foo/init.lua + - /foo/init.server.lua + - /foo/init.client.lua name: foo class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap index 01c6b288..0f0af127 100644 --- a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap +++ b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap @@ -10,6 +10,9 @@ metadata: relevant_paths: - /foo - /foo/init.meta.json + - /foo/init.lua + - /foo/init.server.lua + - /foo/init.client.lua name: foo class_name: Folder properties: {} @@ -22,6 +25,9 @@ children: relevant_paths: - /foo/Child - /foo/Child/init.meta.json + - /foo/Child/init.lua + - /foo/Child/init.server.lua + - /foo/Child/init.client.lua name: Child class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/test__init_module_from_vfs.snap b/src/snapshot_middleware/snapshots/test__init_module_from_vfs.snap new file mode 100644 index 00000000..9321a249 --- /dev/null +++ b/src/snapshot_middleware/snapshots/test__init_module_from_vfs.snap @@ -0,0 +1,22 @@ +--- +source: src/snapshot_middleware/lua.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /root + relevant_paths: + - /root + - /root/init.meta.json + - /root/init.lua + - /root/init.server.lua + - /root/init.client.lua +name: root +class_name: ModuleScript +properties: + Source: + Type: String + Value: Hello! +children: [] diff --git a/src/snapshots/serve_session__change_script_meta_after.snap b/src/snapshots/serve_session__change_script_meta_after.snap index 386be8bf..02dd0fbe 100644 --- a/src/snapshots/serve_session__change_script_meta_after.snap +++ b/src/snapshots/serve_session__change_script_meta_after.snap @@ -13,6 +13,9 @@ metadata: relevant_paths: - /root - /root/init.meta.json + - /root/init.lua + - /root/init.server.lua + - /root/init.client.lua children: - id: id-2 name: test diff --git a/src/snapshots/serve_session__change_script_meta_before.snap b/src/snapshots/serve_session__change_script_meta_before.snap index 9acef5ee..649ac820 100644 --- a/src/snapshots/serve_session__change_script_meta_before.snap +++ b/src/snapshots/serve_session__change_script_meta_before.snap @@ -13,6 +13,9 @@ metadata: relevant_paths: - /root - /root/init.meta.json + - /root/init.lua + - /root/init.server.lua + - /root/init.client.lua children: - id: id-2 name: test diff --git a/src/snapshots/serve_session__just_folder.snap b/src/snapshots/serve_session__just_folder.snap index 584509b8..1817c3e4 100644 --- a/src/snapshots/serve_session__just_folder.snap +++ b/src/snapshots/serve_session__just_folder.snap @@ -13,4 +13,7 @@ metadata: relevant_paths: - /foo - /foo/init.meta.json + - /foo/init.lua + - /foo/init.server.lua + - /foo/init.client.lua children: [] diff --git a/src/snapshots/serve_session__project_with_folder.snap b/src/snapshots/serve_session__project_with_folder.snap index ae1914d6..598522e8 100644 --- a/src/snapshots/serve_session__project_with_folder.snap +++ b/src/snapshots/serve_session__project_with_folder.snap @@ -13,6 +13,9 @@ metadata: relevant_paths: - /foo/src - /foo/src/init.meta.json + - /foo/src/init.lua + - /foo/src/init.server.lua + - /foo/src/init.client.lua - /foo/default.project.json children: - id: id-2 diff --git a/src/snapshots/serve_session__script_with_meta.snap b/src/snapshots/serve_session__script_with_meta.snap index 016006b9..9e2a4dcf 100644 --- a/src/snapshots/serve_session__script_with_meta.snap +++ b/src/snapshots/serve_session__script_with_meta.snap @@ -13,6 +13,9 @@ metadata: relevant_paths: - /root - /root/init.meta.json + - /root/init.lua + - /root/init.server.lua + - /root/init.client.lua children: - id: id-2 name: test From 72342f3118bba925772ce7acbb0b7ae5c7b1eb19 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Nov 2019 12:55:55 -0800 Subject: [PATCH 0892/1504] Trim vestigial middleware method --- src/snapshot_middleware/middleware.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index 6282e474..f01a9d3a 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -1,5 +1,3 @@ -use std::path::{Path, PathBuf}; - use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ @@ -22,8 +20,4 @@ pub trait SnapshotMiddleware { fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { None } - - fn change_affects_paths(path: &Path) -> Vec { - vec![path.to_path_buf()] - } } From f32cb592e22b1a367705960e20c8c24153643b1c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Nov 2019 13:02:35 -0800 Subject: [PATCH 0893/1504] Remove ownership stuff from InstanceSnapshot --- src/snapshot/instance_snapshot.rs | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/snapshot/instance_snapshot.rs b/src/snapshot/instance_snapshot.rs index e609c66c..c2b51780 100644 --- a/src/snapshot/instance_snapshot.rs +++ b/src/snapshot/instance_snapshot.rs @@ -38,23 +38,6 @@ pub struct InstanceSnapshot<'source> { } impl<'source> InstanceSnapshot<'source> { - pub fn get_owned(&'source self) -> InstanceSnapshot<'static> { - let children: Vec> = self - .children - .iter() - .map(InstanceSnapshot::get_owned) - .collect(); - - InstanceSnapshot { - snapshot_id: None, - metadata: self.metadata.clone(), - name: Cow::Owned(self.name.clone().into_owned()), - class_name: Cow::Owned(self.class_name.clone().into_owned()), - properties: self.properties.clone(), - children, - } - } - pub fn from_tree(tree: &RbxTree, id: RbxId) -> InstanceSnapshot<'static> { let instance = tree .get_instance(id) From d2e2a13479019218299854a8a55c330e1be2bb71 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Nov 2019 13:05:18 -0800 Subject: [PATCH 0894/1504] Start stripping out lifetimes in InstanceSnapshot --- src/snapshot/instance_snapshot.rs | 20 +++++++++----------- src/snapshot/patch.rs | 10 +++++----- src/snapshot/patch_compute.rs | 18 +++++++----------- src/snapshot_middleware/json_model.rs | 2 +- src/snapshot_middleware/middleware.rs | 2 +- 5 files changed, 23 insertions(+), 29 deletions(-) diff --git a/src/snapshot/instance_snapshot.rs b/src/snapshot/instance_snapshot.rs index c2b51780..dcd50fe9 100644 --- a/src/snapshot/instance_snapshot.rs +++ b/src/snapshot/instance_snapshot.rs @@ -7,15 +7,13 @@ use serde::{Deserialize, Serialize}; use super::InstanceMetadata; -/// A lightweight description of what an instance should look like. Attempts to -/// be somewhat memory efficient by borrowing from its source data, indicated by -/// the lifetime parameter `'source`. +/// A lightweight description of what an instance should look like. /// // Possible future improvements: // - Use refcounted/interned strings // - Replace use of RbxValue with a sum of RbxValue + borrowed value #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct InstanceSnapshot<'source> { +pub struct InstanceSnapshot { /// A temporary ID applied to the snapshot that's used for Ref properties. pub snapshot_id: Option, @@ -23,10 +21,10 @@ pub struct InstanceSnapshot<'source> { pub metadata: InstanceMetadata, /// Correpsonds to the Name property of the instance. - pub name: Cow<'source, str>, + pub name: Cow<'static, str>, /// Corresponds to the ClassName property of the instance. - pub class_name: Cow<'source, str>, + pub class_name: Cow<'static, str>, /// All other properties of the instance, weakly-typed. pub properties: HashMap, @@ -34,11 +32,11 @@ pub struct InstanceSnapshot<'source> { /// The children of the instance represented as more snapshots. /// /// Order is relevant for Roblox instances! - pub children: Vec>, + pub children: Vec, } -impl<'source> InstanceSnapshot<'source> { - pub fn from_tree(tree: &RbxTree, id: RbxId) -> InstanceSnapshot<'static> { +impl InstanceSnapshot { + pub fn from_tree(tree: &RbxTree, id: RbxId) -> InstanceSnapshot { let instance = tree .get_instance(id) .expect("instance did not exist in tree"); @@ -61,8 +59,8 @@ impl<'source> InstanceSnapshot<'source> { } } -impl<'source> Default for InstanceSnapshot<'source> { - fn default() -> InstanceSnapshot<'source> { +impl Default for InstanceSnapshot { + fn default() -> InstanceSnapshot { InstanceSnapshot { snapshot_id: None, metadata: InstanceMetadata::default(), diff --git a/src/snapshot/patch.rs b/src/snapshot/patch.rs index 8be68c47..6fa1eb29 100644 --- a/src/snapshot/patch.rs +++ b/src/snapshot/patch.rs @@ -13,13 +13,13 @@ use super::{InstanceMetadata, InstanceSnapshot}; /// sure that another patch wasn't applied before this one that could cause a /// conflict! #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] -pub struct PatchSet<'a> { +pub struct PatchSet { pub removed_instances: Vec, - pub added_instances: Vec>, + pub added_instances: Vec, pub updated_instances: Vec, } -impl<'a> PatchSet<'a> { +impl<'a> PatchSet { pub fn new() -> Self { PatchSet { removed_instances: Vec::new(), @@ -31,9 +31,9 @@ impl<'a> PatchSet<'a> { /// A patch containing an instance that was added to the tree. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct PatchAdd<'a> { +pub struct PatchAdd { pub parent_id: RbxId, - pub instance: InstanceSnapshot<'a>, + pub instance: InstanceSnapshot, } /// A patch indicating that properties of an instance changed. diff --git a/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs index f2405df4..96418d02 100644 --- a/src/snapshot/patch_compute.rs +++ b/src/snapshot/patch_compute.rs @@ -10,11 +10,7 @@ use super::{ InstanceSnapshot, InstanceWithMeta, RojoTree, }; -pub fn compute_patch_set<'a>( - snapshot: &'a InstanceSnapshot, - tree: &RojoTree, - id: RbxId, -) -> PatchSet<'a> { +pub fn compute_patch_set(snapshot: &InstanceSnapshot, tree: &RojoTree, id: RbxId) -> PatchSet { let mut patch_set = PatchSet::new(); let mut context = ComputePatchContext::default(); @@ -69,12 +65,12 @@ fn rewrite_refs_in_snapshot(context: &ComputePatchContext, snapshot: &mut Instan } } -fn compute_patch_set_internal<'a>( +fn compute_patch_set_internal( context: &mut ComputePatchContext, - snapshot: &'a InstanceSnapshot, + snapshot: &InstanceSnapshot, tree: &RojoTree, id: RbxId, - patch_set: &mut PatchSet<'a>, + patch_set: &mut PatchSet, ) { if let Some(snapshot_id) = snapshot.snapshot_id { context.snapshot_id_to_instance_id.insert(snapshot_id, id); @@ -154,12 +150,12 @@ fn compute_property_patches( }); } -fn compute_children_patches<'a>( +fn compute_children_patches( context: &mut ComputePatchContext, - snapshot: &'a InstanceSnapshot, + snapshot: &InstanceSnapshot, tree: &RojoTree, id: RbxId, - patch_set: &mut PatchSet<'a>, + patch_set: &mut PatchSet, ) { let instance = tree .get_instance(id) diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 8f1203f3..737c8bf5 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -102,7 +102,7 @@ struct JsonModelCore { } impl JsonModelCore { - fn into_snapshot(self, name: String) -> InstanceSnapshot<'static> { + fn into_snapshot(self, name: String) -> InstanceSnapshot { let class_name = self.class_name; let children = self diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index f01a9d3a..b77ff15b 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -7,7 +7,7 @@ use crate::{ use super::{context::InstanceSnapshotContext, error::SnapshotError}; -pub type SnapshotInstanceResult<'a> = Result>, SnapshotError>; +pub type SnapshotInstanceResult<'a> = Result, SnapshotError>; pub type SnapshotFileResult = Option<(String, VfsSnapshot)>; pub trait SnapshotMiddleware { From 02f98a40536a817fc3c1cd956a77ceb5f06c5653 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Nov 2019 13:06:31 -0800 Subject: [PATCH 0895/1504] Remove lifetime from SnapshotInstanceResult --- src/snapshot_middleware/csv.rs | 2 +- src/snapshot_middleware/dir.rs | 2 +- src/snapshot_middleware/json_model.rs | 2 +- src/snapshot_middleware/lua.rs | 9 +++------ src/snapshot_middleware/middleware.rs | 4 ++-- src/snapshot_middleware/mod.rs | 2 +- src/snapshot_middleware/project.rs | 4 ++-- src/snapshot_middleware/rbxlx.rs | 2 +- src/snapshot_middleware/rbxm.rs | 2 +- src/snapshot_middleware/rbxmx.rs | 2 +- src/snapshot_middleware/txt.rs | 2 +- src/snapshot_middleware/user_plugins.rs | 2 +- 12 files changed, 16 insertions(+), 19 deletions(-) diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index c9a09ef2..e74a30ad 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -23,7 +23,7 @@ impl SnapshotMiddleware for SnapshotCsv { _context: &mut InstanceSnapshotContext, vfs: &Vfs, entry: &VfsEntry, - ) -> SnapshotInstanceResult<'static> { + ) -> SnapshotInstanceResult { if entry.is_directory() { return Ok(None); } diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 63303717..eefff70c 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -22,7 +22,7 @@ impl SnapshotMiddleware for SnapshotDir { context: &mut InstanceSnapshotContext, vfs: &Vfs, entry: &VfsEntry, - ) -> SnapshotInstanceResult<'static> { + ) -> SnapshotInstanceResult { if entry.is_file() { return Ok(None); } diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 737c8bf5..5bead69d 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -22,7 +22,7 @@ impl SnapshotMiddleware for SnapshotJsonModel { _context: &mut InstanceSnapshotContext, vfs: &Vfs, entry: &VfsEntry, - ) -> SnapshotInstanceResult<'static> { + ) -> SnapshotInstanceResult { if entry.is_directory() { return Ok(None); } diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index d5239cb3..d632c941 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -23,7 +23,7 @@ impl SnapshotMiddleware for SnapshotLua { context: &mut InstanceSnapshotContext, vfs: &Vfs, entry: &VfsEntry, - ) -> SnapshotInstanceResult<'static> { + ) -> SnapshotInstanceResult { let file_name = entry.path().file_name().unwrap().to_string_lossy(); // These paths alter their parent instance, so we don't need to turn @@ -55,10 +55,7 @@ impl SnapshotMiddleware for SnapshotLua { } /// Core routine for turning Lua files into snapshots. -fn snapshot_lua_file( - vfs: &Vfs, - entry: &VfsEntry, -) -> SnapshotInstanceResult<'static> { +fn snapshot_lua_file(vfs: &Vfs, entry: &VfsEntry) -> SnapshotInstanceResult { let file_name = entry.path().file_name().unwrap().to_string_lossy(); let (class_name, instance_name) = if let Some(name) = match_trailing(&file_name, ".server.lua") @@ -122,7 +119,7 @@ fn snapshot_init( vfs: &Vfs, folder_entry: &VfsEntry, init_name: &str, -) -> SnapshotInstanceResult<'static> { +) -> SnapshotInstanceResult { let init_path = folder_entry.path().join(init_name); if let Some(init_entry) = vfs.get(init_path).with_not_found()? { diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index b77ff15b..c62892e7 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -7,7 +7,7 @@ use crate::{ use super::{context::InstanceSnapshotContext, error::SnapshotError}; -pub type SnapshotInstanceResult<'a> = Result, SnapshotError>; +pub type SnapshotInstanceResult = Result, SnapshotError>; pub type SnapshotFileResult = Option<(String, VfsSnapshot)>; pub trait SnapshotMiddleware { @@ -15,7 +15,7 @@ pub trait SnapshotMiddleware { context: &mut InstanceSnapshotContext, vfs: &Vfs, entry: &VfsEntry, - ) -> SnapshotInstanceResult<'static>; + ) -> SnapshotInstanceResult; fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { None diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 6c3174e9..6f018914 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -48,7 +48,7 @@ macro_rules! middlewares { context: &mut InstanceSnapshotContext, vfs: &Vfs, entry: &VfsEntry, - ) -> SnapshotInstanceResult<'static> { + ) -> SnapshotInstanceResult { $( log::trace!("trying middleware {} on {}", stringify!($middleware), entry.path().display()); diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 91ed6ccb..7f6b5018 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -25,7 +25,7 @@ impl SnapshotMiddleware for SnapshotProject { context: &mut InstanceSnapshotContext, vfs: &Vfs, entry: &VfsEntry, - ) -> SnapshotInstanceResult<'static> { + ) -> SnapshotInstanceResult { if entry.is_directory() { let project_path = entry.path().join("default.project.json"); @@ -81,7 +81,7 @@ pub fn snapshot_project_node( instance_name: &str, node: &ProjectNode, vfs: &Vfs, -) -> SnapshotInstanceResult<'static> { +) -> SnapshotInstanceResult { let name = Cow::Owned(instance_name.to_owned()); let mut class_name = node .class_name diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index 2935fad4..ed4d578c 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -18,7 +18,7 @@ impl SnapshotMiddleware for SnapshotRbxlx { _context: &mut InstanceSnapshotContext, vfs: &Vfs, entry: &VfsEntry, - ) -> SnapshotInstanceResult<'static> { + ) -> SnapshotInstanceResult { if entry.is_directory() { return Ok(None); } diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index ec9b4ab1..825e9036 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -20,7 +20,7 @@ impl SnapshotMiddleware for SnapshotRbxm { _context: &mut InstanceSnapshotContext, vfs: &Vfs, entry: &VfsEntry, - ) -> SnapshotInstanceResult<'static> { + ) -> SnapshotInstanceResult { if entry.is_directory() { return Ok(None); } diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index e7b05752..8d0faef3 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -18,7 +18,7 @@ impl SnapshotMiddleware for SnapshotRbxmx { _context: &mut InstanceSnapshotContext, vfs: &Vfs, entry: &VfsEntry, - ) -> SnapshotInstanceResult<'static> { + ) -> SnapshotInstanceResult { if entry.is_directory() { return Ok(None); } diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 54b08aa6..bf1b55d0 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -23,7 +23,7 @@ impl SnapshotMiddleware for SnapshotTxt { _context: &mut InstanceSnapshotContext, vfs: &Vfs, entry: &VfsEntry, - ) -> SnapshotInstanceResult<'static> { + ) -> SnapshotInstanceResult { if entry.is_directory() { return Ok(None); } diff --git a/src/snapshot_middleware/user_plugins.rs b/src/snapshot_middleware/user_plugins.rs index 10daecd4..31d78275 100644 --- a/src/snapshot_middleware/user_plugins.rs +++ b/src/snapshot_middleware/user_plugins.rs @@ -18,7 +18,7 @@ impl SnapshotMiddleware for SnapshotUserPlugins { context: &mut InstanceSnapshotContext, _vfs: &Vfs, _entry: &VfsEntry, - ) -> SnapshotInstanceResult<'static> { + ) -> SnapshotInstanceResult { // User plugins are only enabled if present on the snapshot context. let plugin_context = match &mut context.plugin_context { Some(ctx) => ctx, From 0fbeb7086521a4d2f3a94cb9f8b966e11fc03420 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Nov 2019 13:53:48 -0800 Subject: [PATCH 0896/1504] Remove erroneous comment in SnapshotJsonModel --- src/snapshot_middleware/json_model.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 5bead69d..662d1b34 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -122,7 +122,7 @@ impl JsonModelCore { InstanceSnapshot { snapshot_id: None, - metadata: Default::default(), // TODO: Allow the user to specify metadata in the JSON model again. + metadata: Default::default(), name: Cow::Owned(name), class_name: Cow::Owned(class_name), properties, From c3f6a17baef84c51dd028a53c8b273eb39ca8059 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Nov 2019 14:02:57 -0800 Subject: [PATCH 0897/1504] Add builder-ish methods to InstanceSnapshot to make middleware code more readable --- src/snapshot/instance_snapshot.rs | 63 +++++++++++++++++++++++++------ src/snapshot_middleware/csv.rs | 25 ++++++------ src/snapshot_middleware/dir.rs | 17 ++++----- src/snapshot_middleware/lua.rs | 35 +++++++---------- src/snapshot_middleware/rbxlx.rs | 15 ++++---- src/snapshot_middleware/rbxm.rs | 15 +++++--- src/snapshot_middleware/rbxmx.rs | 15 ++++---- src/snapshot_middleware/txt.rs | 17 ++++----- 8 files changed, 115 insertions(+), 87 deletions(-) diff --git a/src/snapshot/instance_snapshot.rs b/src/snapshot/instance_snapshot.rs index dcd50fe9..aae249a8 100644 --- a/src/snapshot/instance_snapshot.rs +++ b/src/snapshot/instance_snapshot.rs @@ -36,7 +36,53 @@ pub struct InstanceSnapshot { } impl InstanceSnapshot { - pub fn from_tree(tree: &RbxTree, id: RbxId) -> InstanceSnapshot { + pub fn new() -> Self { + Self { + snapshot_id: None, + metadata: InstanceMetadata::default(), + name: Cow::Borrowed("DEFAULT"), + class_name: Cow::Borrowed("DEFAULT"), + properties: HashMap::new(), + children: Vec::new(), + } + } + + pub fn name(self, name: impl Into) -> Self { + Self { + name: Cow::Owned(name.into()), + ..self + } + } + + pub fn class_name(self, class_name: impl Into) -> Self { + Self { + class_name: Cow::Owned(class_name.into()), + ..self + } + } + + pub fn properties(self, properties: impl Into>) -> Self { + Self { + properties: properties.into(), + ..self + } + } + + pub fn children(self, children: impl Into>) -> Self { + Self { + children: children.into(), + ..self + } + } + + pub fn metadata(self, metadata: impl Into) -> Self { + Self { + metadata: metadata.into(), + ..self + } + } + + pub fn from_tree(tree: &RbxTree, id: RbxId) -> Self { let instance = tree .get_instance(id) .expect("instance did not exist in tree"); @@ -45,10 +91,10 @@ impl InstanceSnapshot { .get_children_ids() .iter() .cloned() - .map(|id| InstanceSnapshot::from_tree(tree, id)) + .map(|id| Self::from_tree(tree, id)) .collect(); - InstanceSnapshot { + Self { snapshot_id: Some(id), metadata: InstanceMetadata::default(), name: Cow::Owned(instance.name.clone()), @@ -60,14 +106,7 @@ impl InstanceSnapshot { } impl Default for InstanceSnapshot { - fn default() -> InstanceSnapshot { - InstanceSnapshot { - snapshot_id: None, - metadata: InstanceMetadata::default(), - name: Cow::Borrowed("DEFAULT"), - class_name: Cow::Borrowed("DEFAULT"), - properties: HashMap::new(), - children: Vec::new(), - } + fn default() -> Self { + Self::new() } } diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index e74a30ad..5838602f 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::BTreeMap}; +use std::collections::BTreeMap; use maplit::hashmap; use rbx_dom_weak::RbxValue; @@ -39,22 +39,19 @@ impl SnapshotMiddleware for SnapshotCsv { let table_contents = convert_localization_csv(&entry.contents(vfs)?); - let mut snapshot = InstanceSnapshot { - snapshot_id: None, - metadata: InstanceMetadata { - instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], - ..Default::default() - }, - name: Cow::Owned(instance_name.to_owned()), - class_name: Cow::Borrowed("LocalizationTable"), - properties: hashmap! { + let mut snapshot = InstanceSnapshot::new() + .name(instance_name) + .class_name("LocalizationTable") + .properties(hashmap! { "Contents".to_owned() => RbxValue::String { value: table_contents, }, - }, - children: Vec::new(), - }; + }) + .metadata(InstanceMetadata { + instigating_source: Some(entry.path().to_path_buf().into()), + relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], + ..Default::default() + }); if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { let meta_contents = meta_entry.contents(vfs)?; diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index eefff70c..9a93affc 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::HashMap}; +use std::collections::HashMap; use rbx_dom_weak::{RbxId, RbxTree}; @@ -58,18 +58,15 @@ impl SnapshotMiddleware for SnapshotDir { entry.path().join("init.client.lua"), ]; - let mut snapshot = InstanceSnapshot { - snapshot_id: None, - metadata: InstanceMetadata { + let mut snapshot = InstanceSnapshot::new() + .name(instance_name) + .class_name("Folder") + .children(snapshot_children) + .metadata(InstanceMetadata { instigating_source: Some(entry.path().to_path_buf().into()), relevant_paths, ..Default::default() - }, - name: Cow::Owned(instance_name), - class_name: Cow::Borrowed("Folder"), - properties: HashMap::new(), - children: snapshot_children, - }; + }); if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { let meta_contents = meta_entry.contents(vfs)?; diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index d632c941..0b096018 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, str}; +use std::str; use maplit::hashmap; use rbx_dom_weak::RbxValue; @@ -75,30 +75,23 @@ fn snapshot_lua_file(vfs: &Vfs, entry: &VfsEntry) -> SnapshotI .expect("File content was not valid UTF-8") .to_string(); - let properties = hashmap! { - "Source".to_owned() => RbxValue::String { - value: contents_str, - }, - }; - let meta_path = entry .path() .with_file_name(format!("{}.meta.json", instance_name)); - let metadata = InstanceMetadata { - instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], - ..Default::default() - }; - - let mut snapshot = InstanceSnapshot { - snapshot_id: None, - metadata, - name: Cow::Owned(instance_name.to_owned()), - class_name: Cow::Borrowed(class_name), - properties, - children: Vec::new(), - }; + let mut snapshot = InstanceSnapshot::new() + .name(instance_name) + .class_name(class_name) + .properties(hashmap! { + "Source".to_owned() => RbxValue::String { + value: contents_str, + }, + }) + .metadata(InstanceMetadata { + instigating_source: Some(entry.path().to_path_buf().into()), + relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], + ..Default::default() + }); if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { let meta_contents = meta_entry.contents(vfs)?; diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index ed4d578c..59753ccf 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -1,7 +1,5 @@ -use std::borrow::Cow; - use crate::{ - snapshot::InstanceSnapshot, + snapshot::{InstanceMetadata, InstanceSnapshot}, vfs::{Vfs, VfsEntry, VfsFetcher}, }; @@ -36,10 +34,13 @@ impl SnapshotMiddleware for SnapshotRbxlx { let root_id = temp_tree.get_root_id(); - let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, root_id); - snapshot.name = Cow::Owned(instance_name.to_owned()); - snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); - snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; + let snapshot = InstanceSnapshot::from_tree(&temp_tree, root_id) + .name(instance_name) + .metadata(InstanceMetadata { + instigating_source: Some(entry.path().to_path_buf().into()), + relevant_paths: vec![entry.path().to_path_buf()], + ..Default::default() + }); Ok(Some(snapshot)) } diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 825e9036..41d120b3 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -1,9 +1,9 @@ -use std::{borrow::Cow, collections::HashMap}; +use std::collections::HashMap; use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; use crate::{ - snapshot::InstanceSnapshot, + snapshot::{InstanceMetadata, InstanceSnapshot}, vfs::{Vfs, VfsEntry, VfsFetcher}, }; @@ -44,10 +44,13 @@ impl SnapshotMiddleware for SnapshotRbxm { let children = root_instance.get_children_ids(); if children.len() == 1 { - let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); - snapshot.name = Cow::Owned(instance_name.to_owned()); - snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); - snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; + let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) + .name(instance_name) + .metadata(InstanceMetadata { + instigating_source: Some(entry.path().to_path_buf().into()), + relevant_paths: vec![entry.path().to_path_buf()], + ..Default::default() + }); Ok(Some(snapshot)) } else { diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 8d0faef3..5ff41ce0 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -1,7 +1,5 @@ -use std::borrow::Cow; - use crate::{ - snapshot::InstanceSnapshot, + snapshot::{InstanceMetadata, InstanceSnapshot}, vfs::{Vfs, VfsEntry, VfsFetcher}, }; @@ -38,10 +36,13 @@ impl SnapshotMiddleware for SnapshotRbxmx { let children = root_instance.get_children_ids(); if children.len() == 1 { - let mut snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]); - snapshot.name = Cow::Owned(instance_name.to_owned()); - snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); - snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; + let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) + .name(instance_name) + .metadata(InstanceMetadata { + instigating_source: Some(entry.path().to_path_buf().into()), + relevant_paths: vec![entry.path().to_path_buf()], + ..Default::default() + }); Ok(Some(snapshot)) } else { diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index bf1b55d0..77208168 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, str}; +use std::str; use maplit::hashmap; use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; @@ -48,18 +48,15 @@ impl SnapshotMiddleware for SnapshotTxt { .path() .with_file_name(format!("{}.meta.json", instance_name)); - let mut snapshot = InstanceSnapshot { - snapshot_id: None, - metadata: InstanceMetadata { + let mut snapshot = InstanceSnapshot::new() + .name(instance_name) + .class_name("StringValue") + .properties(properties) + .metadata(InstanceMetadata { instigating_source: Some(entry.path().to_path_buf().into()), relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], ..Default::default() - }, - name: Cow::Owned(instance_name.to_owned()), - class_name: Cow::Borrowed("StringValue"), - properties, - children: Vec::new(), - }; + }); if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { let meta_contents = meta_entry.contents(vfs)?; From 15cbbacc2f7be9974d39360e4bc25a8502164053 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 25 Nov 2019 15:11:58 -0800 Subject: [PATCH 0898/1504] Refcount entries in snapshot context, moving towards sharing --- src/common_setup.rs | 5 +++-- src/snapshot_middleware/context.rs | 6 +++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/common_setup.rs b/src/common_setup.rs index 51914181..989273b4 100644 --- a/src/common_setup.rs +++ b/src/common_setup.rs @@ -1,7 +1,7 @@ //! Initialization routines that are used by more than one Rojo command or //! utility. -use std::path::Path; +use std::{path::Path, sync::Arc}; use rbx_dom_weak::RbxInstanceProperties; @@ -41,7 +41,8 @@ pub fn start( // If the project file defines no plugins, then there's no need to // initialize the snapshot plugin context. if !project.plugins.is_empty() { - snapshot_context.plugin_context = Some(SnapshotPluginContext::new(&project.plugins)); + snapshot_context.plugin_context = + Some(Arc::new(SnapshotPluginContext::new(&project.plugins))); } } diff --git a/src/snapshot_middleware/context.rs b/src/snapshot_middleware/context.rs index b125b890..6d78b79f 100644 --- a/src/snapshot_middleware/context.rs +++ b/src/snapshot_middleware/context.rs @@ -1,16 +1,16 @@ -use std::{fmt, fs, ops::Deref, path::Path}; +use std::{fmt, fs, ops::Deref, path::Path, sync::Arc}; use rlua::{Lua, RegistryKey}; use super::error::SnapshotError; -#[derive(Debug)] +#[derive(Debug, Clone)] pub struct InstanceSnapshotContext { /// Holds all the state needed to run user plugins as part of the snapshot /// process. /// /// If this is None, then plugins should not be evaluated at all. - pub plugin_context: Option, + pub plugin_context: Option>, } impl Default for InstanceSnapshotContext { From da6c7b4d7ae579518ccbd4dbf66029d7268e241e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 25 Nov 2019 18:10:39 -0800 Subject: [PATCH 0899/1504] Fix Insta snapshot files having their line endings truncated when edited --- .editorconfig | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.editorconfig b/.editorconfig index 42ec20f4..aa7f61e9 100644 --- a/.editorconfig +++ b/.editorconfig @@ -19,5 +19,8 @@ indent_style = space indent_size = 4 insert_final_newline = true +[*.snap] +insert_final_newline = true + [*.lua] indent_style = tab \ No newline at end of file From a48c238ed7a65bf346a7418e809b0a321b3a3cde Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Dec 2019 14:49:40 -0800 Subject: [PATCH 0900/1504] Add InstanceMetadata builder (#269) * Add InstanceMetadata builder, with context field for globbing * Revert snapshot changes * Port snapshot functions to InstanceMetadata builder-ish pattern * Remove IgnoreGlob struct * Elide lifetime --- src/snapshot/metadata.rs | 44 +++++++++++++++++++++++++++++--- src/snapshot_middleware/csv.rs | 10 ++++---- src/snapshot_middleware/dir.rs | 10 ++++---- src/snapshot_middleware/lua.rs | 10 ++++---- src/snapshot_middleware/rbxlx.rs | 10 ++++---- src/snapshot_middleware/rbxm.rs | 10 ++++---- src/snapshot_middleware/rbxmx.rs | 10 ++++---- src/snapshot_middleware/txt.rs | 10 ++++---- 8 files changed, 75 insertions(+), 39 deletions(-) diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index 93556cc2..c3272870 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -1,4 +1,7 @@ -use std::{fmt, path::PathBuf}; +use std::{ + fmt, + path::{Path, PathBuf}, +}; use serde::{Deserialize, Serialize}; @@ -42,14 +45,41 @@ pub struct InstanceMetadata { pub relevant_paths: Vec, } -impl Default for InstanceMetadata { - fn default() -> Self { - InstanceMetadata { +impl InstanceMetadata { + pub fn new() -> Self { + Self { ignore_unknown_instances: false, instigating_source: None, relevant_paths: Vec::new(), } } + + pub fn ignore_unknown_instances(self, ignore_unknown_instances: bool) -> Self { + Self { + ignore_unknown_instances, + ..self + } + } + + pub fn instigating_source(self, instigating_source: impl Into) -> Self { + Self { + instigating_source: Some(instigating_source.into()), + ..self + } + } + + pub fn relevant_paths(self, relevant_paths: Vec) -> Self { + Self { + relevant_paths, + ..self + } + } +} + +impl Default for InstanceMetadata { + fn default() -> Self { + Self::new() + } } #[derive(Clone, PartialEq, Serialize, Deserialize)] @@ -74,3 +104,9 @@ impl From for InstigatingSource { InstigatingSource::Path(path) } } + +impl From<&Path> for InstigatingSource { + fn from(path: &Path) -> Self { + InstigatingSource::Path(path.to_path_buf()) + } +} diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 5838602f..388c68de 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -47,11 +47,11 @@ impl SnapshotMiddleware for SnapshotCsv { value: table_contents, }, }) - .metadata(InstanceMetadata { - instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], - ..Default::default() - }); + .metadata( + InstanceMetadata::new() + .instigating_source(entry.path()) + .relevant_paths(vec![entry.path().to_path_buf(), meta_path.clone()]), + ); if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { let meta_contents = meta_entry.contents(vfs)?; diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 9a93affc..bc8cf34a 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -62,11 +62,11 @@ impl SnapshotMiddleware for SnapshotDir { .name(instance_name) .class_name("Folder") .children(snapshot_children) - .metadata(InstanceMetadata { - instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths, - ..Default::default() - }); + .metadata( + InstanceMetadata::new() + .instigating_source(entry.path()) + .relevant_paths(relevant_paths), + ); if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { let meta_contents = meta_entry.contents(vfs)?; diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 0b096018..836911cf 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -87,11 +87,11 @@ fn snapshot_lua_file(vfs: &Vfs, entry: &VfsEntry) -> SnapshotI value: contents_str, }, }) - .metadata(InstanceMetadata { - instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], - ..Default::default() - }); + .metadata( + InstanceMetadata::new() + .instigating_source(entry.path()) + .relevant_paths(vec![entry.path().to_path_buf(), meta_path.clone()]), + ); if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { let meta_contents = meta_entry.contents(vfs)?; diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index 59753ccf..ede21beb 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -36,11 +36,11 @@ impl SnapshotMiddleware for SnapshotRbxlx { let snapshot = InstanceSnapshot::from_tree(&temp_tree, root_id) .name(instance_name) - .metadata(InstanceMetadata { - instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf()], - ..Default::default() - }); + .metadata( + InstanceMetadata::new() + .instigating_source(entry.path()) + .relevant_paths(vec![entry.path().to_path_buf()]), + ); Ok(Some(snapshot)) } diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 41d120b3..c8442f93 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -46,11 +46,11 @@ impl SnapshotMiddleware for SnapshotRbxm { if children.len() == 1 { let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) .name(instance_name) - .metadata(InstanceMetadata { - instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf()], - ..Default::default() - }); + .metadata( + InstanceMetadata::new() + .instigating_source(entry.path()) + .relevant_paths(vec![entry.path().to_path_buf()]), + ); Ok(Some(snapshot)) } else { diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 5ff41ce0..a30d0665 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -38,11 +38,11 @@ impl SnapshotMiddleware for SnapshotRbxmx { if children.len() == 1 { let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) .name(instance_name) - .metadata(InstanceMetadata { - instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf()], - ..Default::default() - }); + .metadata( + InstanceMetadata::new() + .instigating_source(entry.path()) + .relevant_paths(vec![entry.path().to_path_buf()]), + ); Ok(Some(snapshot)) } else { diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 77208168..3075cd3e 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -52,11 +52,11 @@ impl SnapshotMiddleware for SnapshotTxt { .name(instance_name) .class_name("StringValue") .properties(properties) - .metadata(InstanceMetadata { - instigating_source: Some(entry.path().to_path_buf().into()), - relevant_paths: vec![entry.path().to_path_buf(), meta_path.clone()], - ..Default::default() - }); + .metadata( + InstanceMetadata::new() + .instigating_source(entry.path()) + .relevant_paths(vec![entry.path().to_path_buf(), meta_path.clone()]), + ); if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { let meta_contents = meta_entry.contents(vfs)?; From 12df80da56e23f241d3cc2db92799c622f95a1b9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Dec 2019 15:30:20 -0800 Subject: [PATCH 0901/1504] Introduce InstanceContext (#270) * Add instance context with dummy field * Remove stub field --- src/snapshot/metadata.rs | 25 +++++++++++++++++++ .../tests/snapshots/apply__add_property.snap | 5 ++-- .../apply__remove_property_after_patch.snap | 5 ++-- .../apply__remove_property_initial.snap | 5 ++-- .../apply__set_name_and_class_name.snap | 5 ++-- .../tests/snapshots/compute__add_child.snap | 3 ++- .../snapshots/test__client_from_vfs.snap | 1 + .../snapshots/test__csv_from_vfs.snap | 1 + .../snapshots/test__csv_with_meta.snap | 1 + .../snapshots/test__empty_folder.snap | 1 + .../snapshots/test__folder_in_folder.snap | 2 ++ .../snapshots/test__init_module_from_vfs.snap | 1 + .../snapshots/test__instance_from_vfs.snap | 1 + .../snapshots/test__model_from_vfs.snap | 2 ++ .../snapshots/test__module_from_vfs.snap | 1 + .../snapshots/test__module_with_meta.snap | 1 + .../test__project_from_direct_file.snap | 1 + .../snapshots/test__project_from_folder.snap | 1 + ...test__project_path_property_overrides.snap | 1 + .../test__project_with_children.snap | 2 ++ .../test__project_with_path_to_project.snap | 1 + ...ct_with_path_to_project_with_children.snap | 2 ++ .../test__project_with_path_to_txt.snap | 1 + ...est__project_with_resolved_properties.snap | 1 + ...t__project_with_unresolved_properties.snap | 1 + .../snapshots/test__script_disabled.snap | 1 + .../snapshots/test__script_with_meta.snap | 1 + .../snapshots/test__server_from_vfs.snap | 1 + ...session__change_file_in_project_after.snap | 2 ++ ...ession__change_file_in_project_before.snap | 2 ++ ...rve_session__change_script_meta_after.snap | 2 ++ ...ve_session__change_script_meta_before.snap | 2 ++ ...rve_session__change_script_meta_patch.snap | 1 + .../serve_session__change_txt_file_after.snap | 1 + ...serve_session__change_txt_file_before.snap | 1 + src/snapshots/serve_session__just_folder.snap | 1 + .../serve_session__project_with_folder.snap | 2 ++ .../serve_session__script_with_meta.snap | 2 ++ 38 files changed, 81 insertions(+), 9 deletions(-) diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index c3272870..7d956145 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -43,6 +43,14 @@ pub struct InstanceMetadata { // TODO: Change this to be a SmallVec for performance in common cases? #[serde(serialize_with = "path_serializer::serialize_vec_absolute")] pub relevant_paths: Vec, + + /// Contains information about this instance that should persist between + /// snapshot invocations and is generally inherited. + /// + /// If an instance has a piece of context attached to it, then the next time + /// that instance's instigating source is snapshotted directly, the same + /// context will be passed into it. + pub context: InstanceContext, } impl InstanceMetadata { @@ -51,6 +59,7 @@ impl InstanceMetadata { ignore_unknown_instances: false, instigating_source: None, relevant_paths: Vec::new(), + context: InstanceContext::default(), } } @@ -74,6 +83,13 @@ impl InstanceMetadata { ..self } } + + pub fn context(self, context: &InstanceContext) -> Self { + Self { + context: context.clone(), + ..self + } + } } impl Default for InstanceMetadata { @@ -82,6 +98,15 @@ impl Default for InstanceMetadata { } } +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct InstanceContext {} + +impl Default for InstanceContext { + fn default() -> Self { + InstanceContext {} + } +} + #[derive(Clone, PartialEq, Serialize, Deserialize)] pub enum InstigatingSource { Path(#[serde(serialize_with = "path_serializer::serialize_absolute")] PathBuf), diff --git a/src/snapshot/tests/snapshots/apply__add_property.snap b/src/snapshot/tests/snapshots/apply__add_property.snap index 33022a76..fa57996d 100644 --- a/src/snapshot/tests/snapshots/apply__add_property.snap +++ b/src/snapshot/tests/snapshots/apply__add_property.snap @@ -1,6 +1,6 @@ --- source: src/snapshot/tests/apply.rs -expression: tree_value +expression: tree_view --- id: id-1 name: ROOT @@ -12,4 +12,5 @@ properties: metadata: ignore_unknown_instances: false relevant_paths: [] -children: [] \ No newline at end of file + context: {} +children: [] diff --git a/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap b/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap index c3c1a929..f8706912 100644 --- a/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap +++ b/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap @@ -1,6 +1,6 @@ --- source: src/snapshot/tests/apply.rs -expression: tree_value +expression: tree_view --- id: id-1 name: ROOT @@ -9,4 +9,5 @@ properties: {} metadata: ignore_unknown_instances: false relevant_paths: [] -children: [] \ No newline at end of file + context: {} +children: [] diff --git a/src/snapshot/tests/snapshots/apply__remove_property_initial.snap b/src/snapshot/tests/snapshots/apply__remove_property_initial.snap index 0b1ecab5..631eacdf 100644 --- a/src/snapshot/tests/snapshots/apply__remove_property_initial.snap +++ b/src/snapshot/tests/snapshots/apply__remove_property_initial.snap @@ -1,6 +1,6 @@ --- source: src/snapshot/tests/apply.rs -expression: tree_value +expression: tree_view --- id: id-1 name: ROOT @@ -12,4 +12,5 @@ properties: metadata: ignore_unknown_instances: false relevant_paths: [] -children: [] \ No newline at end of file + context: {} +children: [] diff --git a/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap b/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap index 17045e2d..634b4d64 100644 --- a/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap +++ b/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap @@ -1,6 +1,6 @@ --- source: src/snapshot/tests/apply.rs -expression: tree_value +expression: tree_view --- id: id-1 name: "Hello, world!" @@ -9,4 +9,5 @@ properties: {} metadata: ignore_unknown_instances: false relevant_paths: [] -children: [] \ No newline at end of file + context: {} +children: [] diff --git a/src/snapshot/tests/snapshots/compute__add_child.snap b/src/snapshot/tests/snapshots/compute__add_child.snap index 54f3d076..97bd639e 100644 --- a/src/snapshot/tests/snapshots/compute__add_child.snap +++ b/src/snapshot/tests/snapshots/compute__add_child.snap @@ -10,8 +10,9 @@ added_instances: metadata: ignore_unknown_instances: false relevant_paths: [] + context: {} name: New class_name: Folder properties: {} children: [] -updated_instances: [] \ No newline at end of file +updated_instances: [] diff --git a/src/snapshot_middleware/snapshots/test__client_from_vfs.snap b/src/snapshot_middleware/snapshots/test__client_from_vfs.snap index f76fb658..f0ce9fe1 100644 --- a/src/snapshot_middleware/snapshots/test__client_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/test__client_from_vfs.snap @@ -10,6 +10,7 @@ metadata: relevant_paths: - /foo.client.lua - /foo.meta.json + context: {} name: foo class_name: LocalScript properties: diff --git a/src/snapshot_middleware/snapshots/test__csv_from_vfs.snap b/src/snapshot_middleware/snapshots/test__csv_from_vfs.snap index 705eb6e0..ccb2de88 100644 --- a/src/snapshot_middleware/snapshots/test__csv_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/test__csv_from_vfs.snap @@ -10,6 +10,7 @@ metadata: relevant_paths: - /foo.csv - /foo.meta.json + context: {} name: foo class_name: LocalizationTable properties: diff --git a/src/snapshot_middleware/snapshots/test__csv_with_meta.snap b/src/snapshot_middleware/snapshots/test__csv_with_meta.snap index 5721dffd..def16559 100644 --- a/src/snapshot_middleware/snapshots/test__csv_with_meta.snap +++ b/src/snapshot_middleware/snapshots/test__csv_with_meta.snap @@ -10,6 +10,7 @@ metadata: relevant_paths: - /foo.csv - /foo.meta.json + context: {} name: foo class_name: LocalizationTable properties: diff --git a/src/snapshot_middleware/snapshots/test__empty_folder.snap b/src/snapshot_middleware/snapshots/test__empty_folder.snap index 8728c624..f24a53a8 100644 --- a/src/snapshot_middleware/snapshots/test__empty_folder.snap +++ b/src/snapshot_middleware/snapshots/test__empty_folder.snap @@ -13,6 +13,7 @@ metadata: - /foo/init.lua - /foo/init.server.lua - /foo/init.client.lua + context: {} name: foo class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap index 0f0af127..e9bd5b92 100644 --- a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap +++ b/src/snapshot_middleware/snapshots/test__folder_in_folder.snap @@ -13,6 +13,7 @@ metadata: - /foo/init.lua - /foo/init.server.lua - /foo/init.client.lua + context: {} name: foo class_name: Folder properties: {} @@ -28,6 +29,7 @@ children: - /foo/Child/init.lua - /foo/Child/init.server.lua - /foo/Child/init.client.lua + context: {} name: Child class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/test__init_module_from_vfs.snap b/src/snapshot_middleware/snapshots/test__init_module_from_vfs.snap index 9321a249..47340789 100644 --- a/src/snapshot_middleware/snapshots/test__init_module_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/test__init_module_from_vfs.snap @@ -13,6 +13,7 @@ metadata: - /root/init.lua - /root/init.server.lua - /root/init.client.lua + context: {} name: root class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/test__instance_from_vfs.snap index 189e935f..38b62a6f 100644 --- a/src/snapshot_middleware/snapshots/test__instance_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/test__instance_from_vfs.snap @@ -10,6 +10,7 @@ metadata: relevant_paths: - /foo.txt - /foo.meta.json + context: {} name: foo class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/test__model_from_vfs.snap b/src/snapshot_middleware/snapshots/test__model_from_vfs.snap index a18082b6..427f2ab9 100644 --- a/src/snapshot_middleware/snapshots/test__model_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/test__model_from_vfs.snap @@ -9,6 +9,7 @@ metadata: Path: /foo.model.json relevant_paths: - /foo.model.json + context: {} name: foo class_name: IntValue properties: @@ -20,6 +21,7 @@ children: metadata: ignore_unknown_instances: false relevant_paths: [] + context: {} name: The Child class_name: StringValue properties: {} diff --git a/src/snapshot_middleware/snapshots/test__module_from_vfs.snap b/src/snapshot_middleware/snapshots/test__module_from_vfs.snap index d6bb90f7..1fbc5638 100644 --- a/src/snapshot_middleware/snapshots/test__module_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/test__module_from_vfs.snap @@ -10,6 +10,7 @@ metadata: relevant_paths: - /foo.lua - /foo.meta.json + context: {} name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/test__module_with_meta.snap b/src/snapshot_middleware/snapshots/test__module_with_meta.snap index 15b911f3..9c64cab8 100644 --- a/src/snapshot_middleware/snapshots/test__module_with_meta.snap +++ b/src/snapshot_middleware/snapshots/test__module_with_meta.snap @@ -10,6 +10,7 @@ metadata: relevant_paths: - /foo.lua - /foo.meta.json + context: {} name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap b/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap index 1d4f7009..42393420 100644 --- a/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap +++ b/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap @@ -9,6 +9,7 @@ metadata: Path: /foo/hello.project.json relevant_paths: - /foo/hello.project.json + context: {} name: direct-project class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/test__project_from_folder.snap b/src/snapshot_middleware/snapshots/test__project_from_folder.snap index d8417c62..d3a91f3c 100644 --- a/src/snapshot_middleware/snapshots/test__project_from_folder.snap +++ b/src/snapshot_middleware/snapshots/test__project_from_folder.snap @@ -9,6 +9,7 @@ metadata: Path: /foo/default.project.json relevant_paths: - /foo/default.project.json + context: {} name: indirect-project class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap b/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap index ee98a5c6..8fe66f62 100644 --- a/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap +++ b/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap @@ -10,6 +10,7 @@ metadata: relevant_paths: - /foo/other.project.json - /foo/default.project.json + context: {} name: path-property-override class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/test__project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_children.snap index 1893e242..d20102a8 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_children.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_children.snap @@ -9,6 +9,7 @@ metadata: Path: /foo/default.project.json relevant_paths: - /foo/default.project.json + context: {} name: children class_name: Folder properties: {} @@ -25,6 +26,7 @@ children: ignore_unknown_instances: ~ path: ~ relevant_paths: [] + context: {} name: Child class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap index 406b0b61..a520b7c7 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap @@ -10,6 +10,7 @@ metadata: relevant_paths: - /foo/other.project.json - /foo/default.project.json + context: {} name: path-project class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap index 06fca8b6..ffe120ca 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap @@ -10,6 +10,7 @@ metadata: relevant_paths: - /foo/other.project.json - /foo/default.project.json + context: {} name: path-child-project class_name: Folder properties: {} @@ -26,6 +27,7 @@ children: ignore_unknown_instances: ~ path: ~ relevant_paths: [] + context: {} name: SomeChild class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap index a2151784..68802abb 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap @@ -11,6 +11,7 @@ metadata: - /foo/other.txt - /foo/other.meta.json - /foo/default.project.json + context: {} name: path-project class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap b/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap index 96194799..cb6025f7 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap @@ -9,6 +9,7 @@ metadata: Path: /foo/default.project.json relevant_paths: - /foo/default.project.json + context: {} name: resolved-properties class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap b/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap index 383d0746..a8a0e6df 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap @@ -9,6 +9,7 @@ metadata: Path: /foo/default.project.json relevant_paths: - /foo/default.project.json + context: {} name: unresolved-properties class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/test__script_disabled.snap b/src/snapshot_middleware/snapshots/test__script_disabled.snap index e2be6724..329c7d99 100644 --- a/src/snapshot_middleware/snapshots/test__script_disabled.snap +++ b/src/snapshot_middleware/snapshots/test__script_disabled.snap @@ -10,6 +10,7 @@ metadata: relevant_paths: - /bar.server.lua - /bar.meta.json + context: {} name: bar class_name: Script properties: diff --git a/src/snapshot_middleware/snapshots/test__script_with_meta.snap b/src/snapshot_middleware/snapshots/test__script_with_meta.snap index 2c7dbf43..34cdd503 100644 --- a/src/snapshot_middleware/snapshots/test__script_with_meta.snap +++ b/src/snapshot_middleware/snapshots/test__script_with_meta.snap @@ -10,6 +10,7 @@ metadata: relevant_paths: - /foo.server.lua - /foo.meta.json + context: {} name: foo class_name: Script properties: diff --git a/src/snapshot_middleware/snapshots/test__server_from_vfs.snap b/src/snapshot_middleware/snapshots/test__server_from_vfs.snap index b9964d27..357d89d6 100644 --- a/src/snapshot_middleware/snapshots/test__server_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/test__server_from_vfs.snap @@ -10,6 +10,7 @@ metadata: relevant_paths: - /foo.server.lua - /foo.meta.json + context: {} name: foo class_name: Script properties: diff --git a/src/snapshots/serve_session__change_file_in_project_after.snap b/src/snapshots/serve_session__change_file_in_project_after.snap index db346fb6..757dc2c5 100644 --- a/src/snapshots/serve_session__change_file_in_project_after.snap +++ b/src/snapshots/serve_session__change_file_in_project_after.snap @@ -12,6 +12,7 @@ metadata: Path: /foo/default.project.json relevant_paths: - /foo/default.project.json + context: {} children: - id: id-2 name: Child @@ -33,4 +34,5 @@ children: relevant_paths: - /foo/file.txt - /foo/file.meta.json + context: {} children: [] diff --git a/src/snapshots/serve_session__change_file_in_project_before.snap b/src/snapshots/serve_session__change_file_in_project_before.snap index 715cd903..96d9cd93 100644 --- a/src/snapshots/serve_session__change_file_in_project_before.snap +++ b/src/snapshots/serve_session__change_file_in_project_before.snap @@ -12,6 +12,7 @@ metadata: Path: /foo/default.project.json relevant_paths: - /foo/default.project.json + context: {} children: - id: id-2 name: Child @@ -33,4 +34,5 @@ children: relevant_paths: - /foo/file.txt - /foo/file.meta.json + context: {} children: [] diff --git a/src/snapshots/serve_session__change_script_meta_after.snap b/src/snapshots/serve_session__change_script_meta_after.snap index 02dd0fbe..c9cd47a1 100644 --- a/src/snapshots/serve_session__change_script_meta_after.snap +++ b/src/snapshots/serve_session__change_script_meta_after.snap @@ -16,6 +16,7 @@ metadata: - /root/init.lua - /root/init.server.lua - /root/init.client.lua + context: {} children: - id: id-2 name: test @@ -31,4 +32,5 @@ children: relevant_paths: - /root/test.lua - /root/test.meta.json + context: {} children: [] diff --git a/src/snapshots/serve_session__change_script_meta_before.snap b/src/snapshots/serve_session__change_script_meta_before.snap index 649ac820..21e575f1 100644 --- a/src/snapshots/serve_session__change_script_meta_before.snap +++ b/src/snapshots/serve_session__change_script_meta_before.snap @@ -16,6 +16,7 @@ metadata: - /root/init.lua - /root/init.server.lua - /root/init.client.lua + context: {} children: - id: id-2 name: test @@ -31,4 +32,5 @@ children: relevant_paths: - /root/test.lua - /root/test.meta.json + context: {} children: [] diff --git a/src/snapshots/serve_session__change_script_meta_patch.snap b/src/snapshots/serve_session__change_script_meta_patch.snap index 1330da20..abc41b3a 100644 --- a/src/snapshots/serve_session__change_script_meta_patch.snap +++ b/src/snapshots/serve_session__change_script_meta_patch.snap @@ -17,3 +17,4 @@ expression: redactions.redacted_yaml(changes) relevant_paths: - /root/test.lua - /root/test.meta.json + context: {} diff --git a/src/snapshots/serve_session__change_txt_file_after.snap b/src/snapshots/serve_session__change_txt_file_after.snap index 9143b804..4ff19d78 100644 --- a/src/snapshots/serve_session__change_txt_file_after.snap +++ b/src/snapshots/serve_session__change_txt_file_after.snap @@ -16,4 +16,5 @@ metadata: relevant_paths: - /foo.txt - /foo.meta.json + context: {} children: [] diff --git a/src/snapshots/serve_session__change_txt_file_before.snap b/src/snapshots/serve_session__change_txt_file_before.snap index 644c3700..e3324a6a 100644 --- a/src/snapshots/serve_session__change_txt_file_before.snap +++ b/src/snapshots/serve_session__change_txt_file_before.snap @@ -16,4 +16,5 @@ metadata: relevant_paths: - /foo.txt - /foo.meta.json + context: {} children: [] diff --git a/src/snapshots/serve_session__just_folder.snap b/src/snapshots/serve_session__just_folder.snap index 1817c3e4..5851d3f2 100644 --- a/src/snapshots/serve_session__just_folder.snap +++ b/src/snapshots/serve_session__just_folder.snap @@ -16,4 +16,5 @@ metadata: - /foo/init.lua - /foo/init.server.lua - /foo/init.client.lua + context: {} children: [] diff --git a/src/snapshots/serve_session__project_with_folder.snap b/src/snapshots/serve_session__project_with_folder.snap index 598522e8..c6a3a4b2 100644 --- a/src/snapshots/serve_session__project_with_folder.snap +++ b/src/snapshots/serve_session__project_with_folder.snap @@ -17,6 +17,7 @@ metadata: - /foo/src/init.server.lua - /foo/src/init.client.lua - /foo/default.project.json + context: {} children: - id: id-2 name: hello @@ -32,4 +33,5 @@ children: relevant_paths: - /foo/src/hello.txt - /foo/src/hello.meta.json + context: {} children: [] diff --git a/src/snapshots/serve_session__script_with_meta.snap b/src/snapshots/serve_session__script_with_meta.snap index 9e2a4dcf..6542fa39 100644 --- a/src/snapshots/serve_session__script_with_meta.snap +++ b/src/snapshots/serve_session__script_with_meta.snap @@ -16,6 +16,7 @@ metadata: - /root/init.lua - /root/init.server.lua - /root/init.client.lua + context: {} children: - id: id-2 name: test @@ -31,4 +32,5 @@ children: relevant_paths: - /root/test.lua - /root/test.meta.json + context: {} children: [] From 948303aac8adbbfa6b353ede087ae8780bb3df40 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Dec 2019 16:11:51 -0800 Subject: [PATCH 0902/1504] Remove InstanceSnapshotContext in favor of InstanceContext (#271) * Drop plugin context on the floor * Remove redirect from old context to new context * Pass InstanceContext via & instead of &mut reference * Re-use context value in ChangeProcessor from metadata --- src/change_processor.rs | 10 +-- src/common_setup.rs | 15 +++-- src/snapshot_middleware/context.rs | 87 ------------------------- src/snapshot_middleware/csv.rs | 9 ++- src/snapshot_middleware/dir.rs | 9 ++- src/snapshot_middleware/json_model.rs | 7 +- src/snapshot_middleware/lua.rs | 21 +++--- src/snapshot_middleware/middleware.rs | 6 +- src/snapshot_middleware/mod.rs | 9 +-- src/snapshot_middleware/project.rs | 25 ++++--- src/snapshot_middleware/rbxlx.rs | 5 +- src/snapshot_middleware/rbxm.rs | 7 +- src/snapshot_middleware/rbxmx.rs | 7 +- src/snapshot_middleware/txt.rs | 7 +- src/snapshot_middleware/user_plugins.rs | 84 ++++++++++-------------- 15 files changed, 99 insertions(+), 209 deletions(-) delete mode 100644 src/snapshot_middleware/context.rs diff --git a/src/change_processor.rs b/src/change_processor.rs index 2aa76eaa..f13241e7 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -14,7 +14,7 @@ use crate::{ snapshot::{ apply_patch_set, compute_patch_set, AppliedPatchSet, InstigatingSource, PatchSet, RojoTree, }, - snapshot_middleware::{snapshot_from_vfs, snapshot_project_node, InstanceSnapshotContext}, + snapshot_middleware::{snapshot_from_vfs, snapshot_project_node}, vfs::{FsResultExt, Vfs, VfsEvent, VfsFetcher}, }; @@ -141,10 +141,6 @@ fn update_affected_instances( } }; - // TODO: Use persisted snapshot context struct instead of recreating it - // every time. - let mut snapshot_context = InstanceSnapshotContext::default(); - // How we process a file change event depends on what created this // file/folder in the first place. let applied_patch_set = match instigating_source { @@ -161,7 +157,7 @@ fn update_affected_instances( // starting at that path and use it as the source for // our patch. - let snapshot = snapshot_from_vfs(&mut snapshot_context, &vfs, &entry) + let snapshot = snapshot_from_vfs(&metadata.context, &vfs, &entry) .expect("snapshot failed") .expect("snapshot did not return an instance"); @@ -188,7 +184,7 @@ fn update_affected_instances( // the project file, we snapshot the entire project node again. let snapshot = - snapshot_project_node(&mut snapshot_context, instance_name, project_node, &vfs) + snapshot_project_node(&metadata.context, instance_name, project_node, &vfs) .expect("snapshot failed") .expect("snapshot did not return an instance"); diff --git a/src/common_setup.rs b/src/common_setup.rs index 989273b4..160b4c6c 100644 --- a/src/common_setup.rs +++ b/src/common_setup.rs @@ -1,14 +1,16 @@ //! Initialization routines that are used by more than one Rojo command or //! utility. -use std::{path::Path, sync::Arc}; +use std::path::Path; use rbx_dom_weak::RbxInstanceProperties; use crate::{ project::{Project, ProjectLoadError}, - snapshot::{apply_patch_set, compute_patch_set, InstancePropertiesWithMeta, RojoTree}, - snapshot_middleware::{snapshot_from_vfs, InstanceSnapshotContext, SnapshotPluginContext}, + snapshot::{ + apply_patch_set, compute_patch_set, InstanceContext, InstancePropertiesWithMeta, RojoTree, + }, + snapshot_middleware::snapshot_from_vfs, vfs::{Vfs, VfsFetcher}, }; @@ -36,13 +38,12 @@ pub fn start( let root_id = tree.get_root_id(); log::trace!("Constructing snapshot context"); - let mut snapshot_context = InstanceSnapshotContext::default(); + let snapshot_context = InstanceContext::default(); if let Some(project) = &maybe_project { // If the project file defines no plugins, then there's no need to // initialize the snapshot plugin context. if !project.plugins.is_empty() { - snapshot_context.plugin_context = - Some(Arc::new(SnapshotPluginContext::new(&project.plugins))); + // TODO: Initialize plugins in instance context } } @@ -52,7 +53,7 @@ pub fn start( .expect("could not get project path"); log::trace!("Generating snapshot of instances from VFS"); - let snapshot = snapshot_from_vfs(&mut snapshot_context, vfs, &entry) + let snapshot = snapshot_from_vfs(&snapshot_context, vfs, &entry) .expect("snapshot failed") .expect("snapshot did not return an instance"); diff --git a/src/snapshot_middleware/context.rs b/src/snapshot_middleware/context.rs deleted file mode 100644 index 6d78b79f..00000000 --- a/src/snapshot_middleware/context.rs +++ /dev/null @@ -1,87 +0,0 @@ -use std::{fmt, fs, ops::Deref, path::Path, sync::Arc}; - -use rlua::{Lua, RegistryKey}; - -use super::error::SnapshotError; - -#[derive(Debug, Clone)] -pub struct InstanceSnapshotContext { - /// Holds all the state needed to run user plugins as part of the snapshot - /// process. - /// - /// If this is None, then plugins should not be evaluated at all. - pub plugin_context: Option>, -} - -impl Default for InstanceSnapshotContext { - fn default() -> Self { - Self { - plugin_context: None, - } - } -} - -#[derive(Debug)] -pub struct SnapshotPluginContext { - pub state: IgnoreDebug, - - /// Registry keys pointing to the values returned by each user plugin. When - /// processing user plugins, these should be applied in order. - pub plugin_functions: Vec, -} - -impl SnapshotPluginContext { - pub fn new>(plugin_paths: &[P]) -> Self { - let lua_state = Lua::new(); - - let plugin_functions = plugin_paths - .iter() - .map(|path| { - let path = path.as_ref(); - - let content = - fs::read_to_string(path).map_err(|err| SnapshotError::wrap(err, path))?; - - lua_state.context(|lua_context| { - // Plugins are currently expected to return a function that will - // be run when a snapshot needs to be generated. - let result = lua_context - .load(&content) - .set_name(&path.display().to_string())? - .call::<_, rlua::Function>(())?; - - let key = lua_context.create_registry_value(result)?; - - Ok(key) - }) - }) - .collect::, SnapshotError>>() - .expect("Plugin initialization error"); - - Self { - state: IgnoreDebug(lua_state), - plugin_functions, - } - } -} - -/// Utility type to enable having a field of a struct not implement Debug and -/// instead show a placeholder. -#[derive(Clone)] -pub struct IgnoreDebug(pub T); - -impl fmt::Debug for IgnoreDebug { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - write!(formatter, "") - } -} - -impl Deref for IgnoreDebug { - type Target = T; - - fn deref(&self) -> &T { - &self.0 - } -} - -pub struct VfsSnapshotContext; diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 388c68de..5ba626ee 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -5,12 +5,11 @@ use rbx_dom_weak::RbxValue; use serde::Serialize; use crate::{ - snapshot::{InstanceMetadata, InstanceSnapshot}, + snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, vfs::{FsResultExt, Vfs, VfsEntry, VfsFetcher}, }; use super::{ - context::InstanceSnapshotContext, meta_file::AdjacentMetadata, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, @@ -20,7 +19,7 @@ pub struct SnapshotCsv; impl SnapshotMiddleware for SnapshotCsv { fn from_vfs( - _context: &mut InstanceSnapshotContext, + _context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { @@ -159,7 +158,7 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, let entry = vfs.get("/foo.csv").unwrap(); let instance_snapshot = - SnapshotCsv::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotCsv::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -181,7 +180,7 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, let entry = vfs.get("/foo.csv").unwrap(); let instance_snapshot = - SnapshotCsv::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotCsv::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index bc8cf34a..9c64efdf 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -3,12 +3,11 @@ use std::collections::HashMap; use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ - snapshot::{InstanceMetadata, InstanceSnapshot}, + snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, vfs::{DirectorySnapshot, FsResultExt, Vfs, VfsEntry, VfsFetcher, VfsSnapshot}, }; use super::{ - context::InstanceSnapshotContext, error::SnapshotError, meta_file::DirectoryMetadata, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, @@ -19,7 +18,7 @@ pub struct SnapshotDir; impl SnapshotMiddleware for SnapshotDir { fn from_vfs( - context: &mut InstanceSnapshotContext, + context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { @@ -116,7 +115,7 @@ mod test { let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotDir::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotDir::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -134,7 +133,7 @@ mod test { let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotDir::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotDir::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 662d1b34..f5aa7068 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -5,12 +5,11 @@ use rbx_reflection::try_resolve_value; use serde::Deserialize; use crate::{ - snapshot::InstanceSnapshot, + snapshot::{InstanceContext, InstanceSnapshot}, vfs::{Vfs, VfsEntry, VfsFetcher}, }; use super::{ - context::InstanceSnapshotContext, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -19,7 +18,7 @@ pub struct SnapshotJsonModel; impl SnapshotMiddleware for SnapshotJsonModel { fn from_vfs( - _context: &mut InstanceSnapshotContext, + _context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { @@ -164,7 +163,7 @@ mod test { let entry = vfs.get("/foo.model.json").unwrap(); let instance_snapshot = - SnapshotJsonModel::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotJsonModel::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 836911cf..b8b869da 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -4,12 +4,11 @@ use maplit::hashmap; use rbx_dom_weak::RbxValue; use crate::{ - snapshot::{InstanceMetadata, InstanceSnapshot}, + snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, vfs::{FsResultExt, Vfs, VfsEntry, VfsFetcher}, }; use super::{ - context::InstanceSnapshotContext, dir::SnapshotDir, meta_file::AdjacentMetadata, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, @@ -20,7 +19,7 @@ pub struct SnapshotLua; impl SnapshotMiddleware for SnapshotLua { fn from_vfs( - context: &mut InstanceSnapshotContext, + context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { @@ -108,7 +107,7 @@ fn snapshot_lua_file(vfs: &Vfs, entry: &VfsEntry) -> SnapshotI /// Scripts named `init.lua`, `init.server.lua`, or `init.client.lua` usurp /// their parents, which acts similarly to `__init__.py` from the Python world. fn snapshot_init( - context: &mut InstanceSnapshotContext, + context: &InstanceContext, vfs: &Vfs, folder_entry: &VfsEntry, init_name: &str, @@ -155,7 +154,7 @@ mod test { let entry = vfs.get("/foo.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -171,7 +170,7 @@ mod test { let entry = vfs.get("/foo.server.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -187,7 +186,7 @@ mod test { let entry = vfs.get("/foo.client.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -205,7 +204,7 @@ mod test { let entry = vfs.get("/root").unwrap(); let instance_snapshot = - SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -229,7 +228,7 @@ mod test { let entry = vfs.get("/foo.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -253,7 +252,7 @@ mod test { let entry = vfs.get("/foo.server.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); @@ -279,7 +278,7 @@ mod test { let entry = vfs.get("/bar.server.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index c62892e7..da0fbc44 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -1,18 +1,18 @@ use rbx_dom_weak::{RbxId, RbxTree}; use crate::{ - snapshot::InstanceSnapshot, + snapshot::{InstanceContext, InstanceSnapshot}, vfs::{Vfs, VfsEntry, VfsFetcher, VfsSnapshot}, }; -use super::{context::InstanceSnapshotContext, error::SnapshotError}; +use super::error::SnapshotError; pub type SnapshotInstanceResult = Result, SnapshotError>; pub type SnapshotFileResult = Option<(String, VfsSnapshot)>; pub trait SnapshotMiddleware { fn from_vfs( - context: &mut InstanceSnapshotContext, + context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult; diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 6f018914..ea0030ed 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -3,7 +3,6 @@ #![allow(dead_code)] -mod context; mod csv; mod dir; mod error; @@ -19,7 +18,6 @@ mod txt; mod user_plugins; mod util; -pub use self::context::*; pub use self::error::*; use rbx_dom_weak::{RbxId, RbxTree}; @@ -37,7 +35,10 @@ use self::{ txt::SnapshotTxt, user_plugins::SnapshotUserPlugins, }; -use crate::vfs::{Vfs, VfsEntry, VfsFetcher}; +use crate::{ + snapshot::InstanceContext, + vfs::{Vfs, VfsEntry, VfsFetcher}, +}; pub use self::project::snapshot_project_node; @@ -45,7 +46,7 @@ macro_rules! middlewares { ( $($middleware: ident,)* ) => { /// Generates a snapshot of instances from the given VfsEntry. pub fn snapshot_from_vfs( - context: &mut InstanceSnapshotContext, + context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 7f6b5018..caf2dc11 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -4,12 +4,11 @@ use rbx_reflection::try_resolve_value; use crate::{ project::{Project, ProjectNode}, - snapshot::{InstanceMetadata, InstanceSnapshot, InstigatingSource}, + snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot, InstigatingSource}, vfs::{FsResultExt, Vfs, VfsEntry, VfsFetcher}, }; use super::{ - context::InstanceSnapshotContext, error::SnapshotError, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, snapshot_from_vfs, @@ -22,7 +21,7 @@ pub struct SnapshotProject; impl SnapshotMiddleware for SnapshotProject { fn from_vfs( - context: &mut InstanceSnapshotContext, + context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { @@ -77,7 +76,7 @@ impl SnapshotMiddleware for SnapshotProject { } pub fn snapshot_project_node( - context: &mut InstanceSnapshotContext, + context: &InstanceContext, instance_name: &str, node: &ProjectNode, vfs: &Vfs, @@ -214,7 +213,7 @@ mod test { let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -241,7 +240,7 @@ mod test { let entry = vfs.get("/foo/hello.project.json").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -274,7 +273,7 @@ mod test { let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -304,7 +303,7 @@ mod test { let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -335,7 +334,7 @@ mod test { let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -363,7 +362,7 @@ mod test { let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -398,7 +397,7 @@ mod test { let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -437,7 +436,7 @@ mod test { let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -481,7 +480,7 @@ mod test { let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .expect("snapshot error") .expect("snapshot returned no instances"); diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index ede21beb..fadbf3c9 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -1,10 +1,9 @@ use crate::{ - snapshot::{InstanceMetadata, InstanceSnapshot}, + snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, vfs::{Vfs, VfsEntry, VfsFetcher}, }; use super::{ - context::InstanceSnapshotContext, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -13,7 +12,7 @@ pub struct SnapshotRbxlx; impl SnapshotMiddleware for SnapshotRbxlx { fn from_vfs( - _context: &mut InstanceSnapshotContext, + _context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index c8442f93..4a4d2fc6 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -3,12 +3,11 @@ use std::collections::HashMap; use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; use crate::{ - snapshot::{InstanceMetadata, InstanceSnapshot}, + snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, vfs::{Vfs, VfsEntry, VfsFetcher}, }; use super::{ - context::InstanceSnapshotContext, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -17,7 +16,7 @@ pub struct SnapshotRbxm; impl SnapshotMiddleware for SnapshotRbxm { fn from_vfs( - _context: &mut InstanceSnapshotContext, + _context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { @@ -74,7 +73,7 @@ mod test { let entry = vfs.get("/foo.rbxm").unwrap(); let instance_snapshot = - SnapshotRbxm::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotRbxm::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index a30d0665..b8c33902 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -1,10 +1,9 @@ use crate::{ - snapshot::{InstanceMetadata, InstanceSnapshot}, + snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, vfs::{Vfs, VfsEntry, VfsFetcher}, }; use super::{ - context::InstanceSnapshotContext, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -13,7 +12,7 @@ pub struct SnapshotRbxmx; impl SnapshotMiddleware for SnapshotRbxmx { fn from_vfs( - _context: &mut InstanceSnapshotContext, + _context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { @@ -78,7 +77,7 @@ mod test { let entry = vfs.get("/foo.rbxmx").unwrap(); let instance_snapshot = - SnapshotRbxmx::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotRbxmx::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 3075cd3e..c463564b 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -4,12 +4,11 @@ use maplit::hashmap; use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; use crate::{ - snapshot::{InstanceMetadata, InstanceSnapshot}, + snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, vfs::{FileSnapshot, FsResultExt, Vfs, VfsEntry, VfsFetcher, VfsSnapshot}, }; use super::{ - context::InstanceSnapshotContext, error::SnapshotError, meta_file::AdjacentMetadata, middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, @@ -20,7 +19,7 @@ pub struct SnapshotTxt; impl SnapshotMiddleware for SnapshotTxt { fn from_vfs( - _context: &mut InstanceSnapshotContext, + _context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { @@ -114,7 +113,7 @@ mod test { let entry = vfs.get("/foo.txt").unwrap(); let instance_snapshot = - SnapshotTxt::from_vfs(&mut InstanceSnapshotContext::default(), &mut vfs, &entry) + SnapshotTxt::from_vfs(&InstanceContext::default(), &mut vfs, &entry) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/user_plugins.rs b/src/snapshot_middleware/user_plugins.rs index 31d78275..c28a7a76 100644 --- a/src/snapshot_middleware/user_plugins.rs +++ b/src/snapshot_middleware/user_plugins.rs @@ -1,10 +1,10 @@ -use crate::vfs::{Vfs, VfsEntry, VfsFetcher}; - -use super::{ - context::InstanceSnapshotContext, - middleware::{SnapshotInstanceResult, SnapshotMiddleware}, +use crate::{ + snapshot::InstanceContext, + vfs::{Vfs, VfsEntry, VfsFetcher}, }; +use super::middleware::{SnapshotInstanceResult, SnapshotMiddleware}; + /// Handles snapshotting of any file that a user plugin wants to handle. /// /// User plugins are specified in the project file, but there are never user @@ -15,53 +15,41 @@ pub struct SnapshotUserPlugins; impl SnapshotMiddleware for SnapshotUserPlugins { fn from_vfs( - context: &mut InstanceSnapshotContext, + _context: &InstanceContext, _vfs: &Vfs, _entry: &VfsEntry, ) -> SnapshotInstanceResult { - // User plugins are only enabled if present on the snapshot context. - let plugin_context = match &mut context.plugin_context { - Some(ctx) => ctx, - None => return Ok(None), - }; + // TODO: Invoke plugin here and get result out. - plugin_context.state.context(|lua_context| { - lua_context.scope(|_scope| { - for _key in &plugin_context.plugin_functions { - // TODO: Invoke plugin here and get result out. - - // The current plan for plugins here is to make them work - // like Redux/Rodux middleware. A plugin will be a function - // that accepts the next middleware in the chain as a - // function and the snapshot subject (the VFS entry). - // - // Plugins can (but don't have to) invoke the next snapshot - // function and may or may not mutate the result. The hope - // is that this model enables the most flexibility possible - // for plugins to modify existing Rojo output, as well as - // generate new outputs. - // - // Open questions: - // * How will middleware be ordered? Does putting user - // middleware always at the beginning or always at the end - // of the chain reduce the scope of what that middleware - // can do? - // - // * Will plugins hurt Rojo's ability to parallelize - // snapshotting in the future? - // - // * Do the mutable handles to the Vfs and the snapshot - // context prevent plugins from invoking other plugins - // indirectly? - // - // * Will there be problems using a single Lua state because - // of re-entrancy? - // - // * Can the Lua <-> Rojo bindings used for middleware be - // reused for or from another project like Remodel? - } - }) - }); + // The current plan for plugins here is to make them work + // like Redux/Rodux middleware. A plugin will be a function + // that accepts the next middleware in the chain as a + // function and the snapshot subject (the VFS entry). + // + // Plugins can (but don't have to) invoke the next snapshot + // function and may or may not mutate the result. The hope + // is that this model enables the most flexibility possible + // for plugins to modify existing Rojo output, as well as + // generate new outputs. + // + // Open questions: + // * How will middleware be ordered? Does putting user + // middleware always at the beginning or always at the end + // of the chain reduce the scope of what that middleware + // can do? + // + // * Will plugins hurt Rojo's ability to parallelize + // snapshotting in the future? + // + // * Do the mutable handles to the Vfs and the snapshot + // context prevent plugins from invoking other plugins + // indirectly? + // + // * Will there be problems using a single Lua state because + // of re-entrancy? + // + // * Can the Lua <-> Rojo bindings used for middleware be + // reused for or from another project like Remodel? Ok(None) } From fe10da9a6c4bf3cf79f46ab3e7245551208c0df1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Dec 2019 16:34:46 -0800 Subject: [PATCH 0903/1504] Remove some PartialEq derives --- src/snapshot/instance_snapshot.rs | 2 +- src/snapshot/patch.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/snapshot/instance_snapshot.rs b/src/snapshot/instance_snapshot.rs index aae249a8..b779a2cb 100644 --- a/src/snapshot/instance_snapshot.rs +++ b/src/snapshot/instance_snapshot.rs @@ -12,7 +12,7 @@ use super::InstanceMetadata; // Possible future improvements: // - Use refcounted/interned strings // - Replace use of RbxValue with a sum of RbxValue + borrowed value -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct InstanceSnapshot { /// A temporary ID applied to the snapshot that's used for Ref properties. pub snapshot_id: Option, diff --git a/src/snapshot/patch.rs b/src/snapshot/patch.rs index 6fa1eb29..1ac4acec 100644 --- a/src/snapshot/patch.rs +++ b/src/snapshot/patch.rs @@ -12,7 +12,7 @@ use super::{InstanceMetadata, InstanceSnapshot}; /// These patches shouldn't be persisted: there's no mechanism in place to make /// sure that another patch wasn't applied before this one that could cause a /// conflict! -#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, Serialize, Deserialize)] pub struct PatchSet { pub removed_instances: Vec, pub added_instances: Vec, @@ -30,14 +30,14 @@ impl<'a> PatchSet { } /// A patch containing an instance that was added to the tree. -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct PatchAdd { pub parent_id: RbxId, pub instance: InstanceSnapshot, } /// A patch indicating that properties of an instance changed. -#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct PatchUpdate { pub id: RbxId, pub changed_name: Option, From f0a602b48b73367d3211542fa83f3e565774c9de Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 3 Dec 2019 16:47:19 -0800 Subject: [PATCH 0904/1504] Revert "Remove some PartialEq derives" This reverts commit fe10da9a6c4bf3cf79f46ab3e7245551208c0df1. --- src/snapshot/instance_snapshot.rs | 2 +- src/snapshot/patch.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/snapshot/instance_snapshot.rs b/src/snapshot/instance_snapshot.rs index b779a2cb..aae249a8 100644 --- a/src/snapshot/instance_snapshot.rs +++ b/src/snapshot/instance_snapshot.rs @@ -12,7 +12,7 @@ use super::InstanceMetadata; // Possible future improvements: // - Use refcounted/interned strings // - Replace use of RbxValue with a sum of RbxValue + borrowed value -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct InstanceSnapshot { /// A temporary ID applied to the snapshot that's used for Ref properties. pub snapshot_id: Option, diff --git a/src/snapshot/patch.rs b/src/snapshot/patch.rs index 1ac4acec..6fa1eb29 100644 --- a/src/snapshot/patch.rs +++ b/src/snapshot/patch.rs @@ -12,7 +12,7 @@ use super::{InstanceMetadata, InstanceSnapshot}; /// These patches shouldn't be persisted: there's no mechanism in place to make /// sure that another patch wasn't applied before this one that could cause a /// conflict! -#[derive(Debug, Default, Clone, Serialize, Deserialize)] +#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] pub struct PatchSet { pub removed_instances: Vec, pub added_instances: Vec, @@ -30,14 +30,14 @@ impl<'a> PatchSet { } /// A patch containing an instance that was added to the tree. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct PatchAdd { pub parent_id: RbxId, pub instance: InstanceSnapshot, } /// A patch indicating that properties of an instance changed. -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct PatchUpdate { pub id: RbxId, pub changed_name: Option, From 4b89bb087ab561e54a7473786fbe6064cc1da1c6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 4 Dec 2019 11:38:28 -0800 Subject: [PATCH 0905/1504] Attach context to instances produced by middleware (#273) --- src/snapshot_middleware/dir.rs | 3 ++- src/snapshot_middleware/json_model.rs | 9 ++++++--- src/snapshot_middleware/lua.rs | 13 +++++++++---- src/snapshot_middleware/rbxlx.rs | 5 +++-- src/snapshot_middleware/rbxm.rs | 5 +++-- src/snapshot_middleware/rbxmx.rs | 5 +++-- src/snapshot_middleware/txt.rs | 5 +++-- 7 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 9c64efdf..4bfafc38 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -64,7 +64,8 @@ impl SnapshotMiddleware for SnapshotDir { .metadata( InstanceMetadata::new() .instigating_source(entry.path()) - .relevant_paths(relevant_paths), + .relevant_paths(relevant_paths) + .context(context), ); if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index f5aa7068..bff856ed 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -18,7 +18,7 @@ pub struct SnapshotJsonModel; impl SnapshotMiddleware for SnapshotJsonModel { fn from_vfs( - _context: &InstanceContext, + context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { @@ -54,8 +54,11 @@ impl SnapshotMiddleware for SnapshotJsonModel { let mut snapshot = instance.core.into_snapshot(instance_name.to_owned()); - snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); - snapshot.metadata.relevant_paths = vec![entry.path().to_path_buf()]; + snapshot.metadata = snapshot + .metadata + .instigating_source(entry.path()) + .relevant_paths(vec![entry.path().to_path_buf()]) + .context(context); Ok(Some(snapshot)) } diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index b8b869da..c8ac072d 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -33,7 +33,7 @@ impl SnapshotMiddleware for SnapshotLua { } if entry.is_file() { - snapshot_lua_file(vfs, entry) + snapshot_lua_file(context, vfs, entry) } else { // At this point, our entry is definitely a directory! @@ -54,7 +54,11 @@ impl SnapshotMiddleware for SnapshotLua { } /// Core routine for turning Lua files into snapshots. -fn snapshot_lua_file(vfs: &Vfs, entry: &VfsEntry) -> SnapshotInstanceResult { +fn snapshot_lua_file( + context: &InstanceContext, + vfs: &Vfs, + entry: &VfsEntry, +) -> SnapshotInstanceResult { let file_name = entry.path().file_name().unwrap().to_string_lossy(); let (class_name, instance_name) = if let Some(name) = match_trailing(&file_name, ".server.lua") @@ -89,7 +93,8 @@ fn snapshot_lua_file(vfs: &Vfs, entry: &VfsEntry) -> SnapshotI .metadata( InstanceMetadata::new() .instigating_source(entry.path()) - .relevant_paths(vec![entry.path().to_path_buf(), meta_path.clone()]), + .relevant_paths(vec![entry.path().to_path_buf(), meta_path.clone()]) + .context(context), ); if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { @@ -116,7 +121,7 @@ fn snapshot_init( if let Some(init_entry) = vfs.get(init_path).with_not_found()? { if let Some(dir_snapshot) = SnapshotDir::from_vfs(context, vfs, folder_entry)? { - if let Some(mut init_snapshot) = snapshot_lua_file(vfs, &init_entry)? { + if let Some(mut init_snapshot) = snapshot_lua_file(context, vfs, &init_entry)? { if dir_snapshot.class_name != "Folder" { panic!( "init.lua, init.server.lua, and init.client.lua can \ diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index fadbf3c9..0f7df5b1 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -12,7 +12,7 @@ pub struct SnapshotRbxlx; impl SnapshotMiddleware for SnapshotRbxlx { fn from_vfs( - _context: &InstanceContext, + context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { @@ -38,7 +38,8 @@ impl SnapshotMiddleware for SnapshotRbxlx { .metadata( InstanceMetadata::new() .instigating_source(entry.path()) - .relevant_paths(vec![entry.path().to_path_buf()]), + .relevant_paths(vec![entry.path().to_path_buf()]) + .context(context), ); Ok(Some(snapshot)) diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 4a4d2fc6..14f4c11c 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -16,7 +16,7 @@ pub struct SnapshotRbxm; impl SnapshotMiddleware for SnapshotRbxm { fn from_vfs( - _context: &InstanceContext, + context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { @@ -48,7 +48,8 @@ impl SnapshotMiddleware for SnapshotRbxm { .metadata( InstanceMetadata::new() .instigating_source(entry.path()) - .relevant_paths(vec![entry.path().to_path_buf()]), + .relevant_paths(vec![entry.path().to_path_buf()]) + .context(context), ); Ok(Some(snapshot)) diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index b8c33902..91b9ef0c 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -12,7 +12,7 @@ pub struct SnapshotRbxmx; impl SnapshotMiddleware for SnapshotRbxmx { fn from_vfs( - _context: &InstanceContext, + context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { @@ -40,7 +40,8 @@ impl SnapshotMiddleware for SnapshotRbxmx { .metadata( InstanceMetadata::new() .instigating_source(entry.path()) - .relevant_paths(vec![entry.path().to_path_buf()]), + .relevant_paths(vec![entry.path().to_path_buf()]) + .context(context), ); Ok(Some(snapshot)) diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index c463564b..b0307da0 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -19,7 +19,7 @@ pub struct SnapshotTxt; impl SnapshotMiddleware for SnapshotTxt { fn from_vfs( - _context: &InstanceContext, + context: &InstanceContext, vfs: &Vfs, entry: &VfsEntry, ) -> SnapshotInstanceResult { @@ -54,7 +54,8 @@ impl SnapshotMiddleware for SnapshotTxt { .metadata( InstanceMetadata::new() .instigating_source(entry.path()) - .relevant_paths(vec![entry.path().to_path_buf(), meta_path.clone()]), + .relevant_paths(vec![entry.path().to_path_buf(), meta_path.clone()]) + .context(context), ); if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { From eadfb18f748cb6b00ac12f88bd07cb971bc1f02f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Dec 2019 13:39:55 -0800 Subject: [PATCH 0906/1504] Update rbx_xml and rbx_reflection --- Cargo.lock | 8 ++++---- Cargo.toml | 4 ++-- .../build_test__rbxmx_in_folder.snap | 6 ++++-- .../build_test__rbxmx_ref.rbxmx.snap | 9 ++++++--- 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c7fcbe40..a6624e0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1429,7 +1429,7 @@ dependencies = [ [[package]] name = "rbx_reflection" -version = "3.2.404" +version = "3.3.408" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1446,7 +1446,7 @@ dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.2.404 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1584,7 +1584,7 @@ dependencies = [ "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.2.404 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2470,7 +2470,7 @@ dependencies = [ "checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" "checksum rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81428c521a07a3feac9c31180a886e467eecf81b769987f70d51d567a09c321d" "checksum rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b7c983d7bfcf0811a164e33e99e2da456f38babb33c75e365b17aa1ee5fd2d" -"checksum rbx_reflection 3.2.404 (registry+https://github.com/rust-lang/crates.io-index)" = "7712c0a5ae6524ec5f51c29bc031f21e5ba35b38ffc6277f2ee9439febaec88c" +"checksum rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c147f9006c1cfd3a1872d36e91d5fca88d4b94fafa5463f774a00f293b1277" "checksum rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0236363b0af0c78f3e972ac7f46a1f355f663518e276253136d0180f3c8742c" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" diff --git a/Cargo.toml b/Cargo.toml index 7ced4938..4e2c2742 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,8 +62,8 @@ maplit = "1.0.1" notify = "4.0" rbx_binary = "0.4.1" rbx_dom_weak = "1.9.0" -rbx_reflection = "3.1.388" -rbx_xml = "0.11.0" +rbx_reflection = "3.3.408" +rbx_xml = "0.11.2" regex = "1.0" reqwest = "0.9.20" ritz = "0.1.0" diff --git a/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap b/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap index 4b9740e1..21a7a396 100644 --- a/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap +++ b/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap @@ -25,12 +25,14 @@ expression: contents 1 null - + + Cool StringValue - + + Did you know that BaseValue.Changed is different than Instance.Changed? diff --git a/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap b/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap index 9a796330..26ada371 100644 --- a/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap +++ b/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap @@ -6,19 +6,22 @@ expression: contents rbxmx_ref - + + Target - + + Pointed to by ObjectValue Pointer - + + 1 From d15ef40988efb3396e39b2dfb47a37ddbd91a861 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Dec 2019 17:02:08 -0800 Subject: [PATCH 0907/1504] Upgrade dependencies correctly this time --- Cargo.lock | 777 +++++++++--------- .../build_test__rbxmx_in_folder.snap | 6 +- .../build_test__rbxmx_ref.rbxmx.snap | 9 +- 3 files changed, 413 insertions(+), 379 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a6624e0a..9be098ea 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,46 +21,38 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "arrayvec" -version = "0.4.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "atty" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "autocfg" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "backtrace" -version = "0.3.38" +version = "0.3.40" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -73,7 +65,7 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -81,7 +73,7 @@ name = "block-buffer" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -89,7 +81,7 @@ dependencies = [ [[package]] name = "block-padding" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -103,7 +95,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -128,16 +120,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "c2-chacha" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -147,19 +138,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "cast" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "cc" -version = "1.0.45" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -174,10 +168,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -195,7 +189,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -204,21 +198,20 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "console" -version = "0.8.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -237,12 +230,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "publicsuffix 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -254,7 +247,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -276,20 +269,20 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -299,8 +292,8 @@ name = "criterion-plot" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -313,23 +306,23 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.7.2" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -341,6 +334,14 @@ dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-queue" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "crossbeam-utils" version = "0.6.6" @@ -350,6 +351,16 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "crossbeam-utils" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "csv" version = "1.1.1" @@ -358,8 +369,8 @@ dependencies = [ "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -376,7 +387,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -432,28 +443,28 @@ name = "error-chain" version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -463,24 +474,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "filetime" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "flate2" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -506,7 +517,7 @@ name = "fsevent" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -515,7 +526,7 @@ name = "fsevent-sys" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -528,7 +539,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -548,7 +559,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -561,11 +572,11 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -583,14 +594,22 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "hermit-abi" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "htmlescape" version = "0.3.1" @@ -598,7 +617,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "http" -version = "0.1.18" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -613,7 +632,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -639,10 +658,10 @@ dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -650,12 +669,12 @@ dependencies = [ "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -678,7 +697,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -688,22 +707,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "indexmap" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "inotify" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -711,37 +733,36 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "insta" -version = "0.11.0" -source = "git+https://github.com/mitsuhiko/insta#8e32e354d1db280412592cfb627b26bbd58e0164" +version = "0.12.0" +source = "git+https://github.com/mitsuhiko/insta#8cc12dc009c86df0a4a45f45f26b305b6e7eab8f" dependencies = [ - "console 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "iovec" -version = "0.1.2" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "itertools" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -778,7 +799,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.62" +version = "0.2.66" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -788,7 +809,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lock_api" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -807,7 +828,7 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -817,8 +838,8 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -831,6 +852,11 @@ name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "md5" version = "0.6.1" @@ -841,12 +867,12 @@ name = "memchr" version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "memoffset" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -863,12 +889,12 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "miniz_oxide" -version = "0.3.2" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -876,14 +902,15 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.19" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -893,12 +920,12 @@ dependencies = [ [[package]] name = "mio-extras" -version = "2.0.5" +version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -907,9 +934,9 @@ name = "mio-uds" version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -929,14 +956,14 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.50 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)", "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -946,47 +973,43 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "nodrop" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "notify" -version = "4.0.13" +version = "4.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num_cpus" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -996,15 +1019,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.25" +version = "0.10.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1014,14 +1037,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.50" +version = "0.9.53" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1037,7 +1060,7 @@ name = "parking_lot" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1049,10 +1072,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1062,7 +1085,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1070,10 +1093,10 @@ name = "paste-impl" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1110,9 +1133,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1127,12 +1150,12 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "ppv-lite86" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1148,12 +1171,12 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1171,7 +1194,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1179,7 +1202,7 @@ dependencies = [ [[package]] name = "publicsuffix" -version = "1.5.3" +version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1194,7 +1217,7 @@ name = "pulldown-cmark" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1215,7 +1238,7 @@ name = "quote" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1224,7 +1247,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1235,8 +1258,8 @@ name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1253,8 +1276,8 @@ name = "rand" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1265,7 +1288,7 @@ name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1274,7 +1297,7 @@ name = "rand_chacha" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1296,7 +1319,7 @@ name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1328,7 +1351,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1340,7 +1363,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1351,7 +1374,7 @@ name = "rand_os" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1360,7 +1383,7 @@ name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1382,24 +1405,24 @@ dependencies = [ [[package]] name = "rayon" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1421,8 +1444,8 @@ dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1432,10 +1455,10 @@ name = "rbx_reflection" version = "3.3.408" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1497,7 +1520,7 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.21" +version = "0.9.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1505,24 +1528,24 @@ dependencies = [ "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)", + "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1534,7 +1557,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1544,7 +1567,7 @@ name = "ritz_impl" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", "snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1555,10 +1578,10 @@ name = "rlua" version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1570,16 +1593,16 @@ dependencies = [ "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "insta 0.11.0 (git+https://github.com/mitsuhiko/insta)", + "insta 0.12.0 (git+https://github.com/mitsuhiko/insta)", "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1587,13 +1610,13 @@ dependencies = [ "rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", "rojo-insta-ext 0.1.0", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1606,8 +1629,8 @@ dependencies = [ name = "rojo-insta-ext" version = "0.1.0" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1615,16 +1638,16 @@ name = "rojo-test" version = "0.1.0" dependencies = [ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "insta 0.11.0 (git+https://github.com/mitsuhiko/insta)", + "insta 0.12.0 (git+https://github.com/mitsuhiko/insta)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)", "rojo 0.6.0-dev", "rojo-insta-ext 0.1.0", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1644,7 +1667,7 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.0" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1671,18 +1694,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "security-framework" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "security-framework-sys" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1694,7 +1717,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1704,30 +1727,30 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.101" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.101" +version = "1.0.103" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.41" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1735,9 +1758,9 @@ name = "serde_repr" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1747,18 +1770,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_yaml" -version = "0.8.9" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1783,7 +1806,7 @@ dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1795,7 +1818,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "smallvec" -version = "0.6.10" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "smallvec" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1821,33 +1852,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "syn" -version = "0.15.44" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "synstructure" -version = "0.10.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1865,7 +1886,7 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1885,7 +1906,7 @@ name = "termios" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1893,7 +1914,7 @@ name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1909,7 +1930,7 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1919,8 +1940,8 @@ name = "tinytemplate" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1930,18 +1951,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1972,12 +1993,12 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1991,7 +2012,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2006,25 +2027,25 @@ dependencies = [ [[package]] name = "tokio-reactor" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-sync" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2038,37 +2059,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2079,10 +2100,10 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2092,14 +2113,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)", + "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2127,10 +2148,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "unicase" -version = "2.5.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2143,15 +2164,15 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.8" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "unicode-width" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2190,12 +2211,21 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "uuid" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "vcpkg" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -2208,6 +2238,11 @@ name = "version_check" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "version_check" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "walkdir" version = "2.2.9" @@ -2313,29 +2348,28 @@ dependencies = [ "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum arrayvec 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b8d73f9beda665eaa98ab9e4f7442bd4e7de6652587de55b2525e52e29c1b0ba" "checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" -"checksum autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "b671c8fb71b457dd4ae18c4ba1e59aa81793daacc361d82fcd410cef0d491875" -"checksum backtrace 0.3.38 (registry+https://github.com/rust-lang/crates.io-index)" = "690a62be8920ccf773ee00ef0968649b0e724cda8bd5b12286302b4ae955fdf5" -"checksum backtrace-sys 0.1.31 (registry+https://github.com/rust-lang/crates.io-index)" = "82a830b4ef2d1124a711c71d263c5abdc710ef8e907bd508c88be475cebc422b" +"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" +"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum bitflags 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8a606a02debe2813760609f57a64a2ffd27d9fdf5b2f133eaca0b248dd92cdd2" +"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -"checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09" +"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" "checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -"checksum c2-chacha 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7d64d04786e0f528460fc884753cf8dddcc466be308f6026f8e355c41a0e4101" +"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cast 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "926013f2860c46252efceabb19f4a6b308197505082c609025aa6706c011d427" -"checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" +"checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" +"checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum console 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147390a412132d75d10dd3b7b175a69cf5fd95032f7503c7091b8831ba10242" +"checksum console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5d540c2d34ac9dd0deb5f3b5f54c36c79efa78f6b3ad19106a554d07a7b5d9f" "checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" "checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" @@ -2344,10 +2378,12 @@ dependencies = [ "checksum criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "938703e165481c8d612ea3479ac8342e5615185db37765162e762ec3523e2fc6" "checksum criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eccdc6ce8bbe352ca89025bee672aa6d24f4eb8c53e3a8b5d1bc58011da072a2" "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" -"checksum crossbeam-deque 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b18cd2e169ad86297e6bc0ad9aa679aee9daa4f19e8163860faf7c164e4f5a71" -"checksum crossbeam-epoch 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "fedcd6772e37f3da2a9af9bf12ebe046c0dfe657992377b4df982a2b54cd37a9" +"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" +"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" +"checksum crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700" "checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" +"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" "checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" "checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" "checksum ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc" @@ -2359,11 +2395,11 @@ dependencies = [ "checksum encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)" = "87240518927716f79692c2ed85bfe6e98196d18c6401ec75355760233a7e12e9" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" -"checksum failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "795bd83d3abeb9220f257e597aa0080a508b27533824adf336529648f6abf7e2" -"checksum failure_derive 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea1063915fd7ef4309e222a5a07cf9c319fb9c7836b1f89b85458672dbb127e1" +"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" +"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum filetime 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd7380b54ced79dda72ecc35cc4fbbd1da6bba54afaa37e96fd1c2a308cd469" -"checksum flate2 1.0.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ad3c5233c9a940c8719031b423d7e6c16af66e031cb0420b0896f5245bf181d3" +"checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" +"checksum flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" @@ -2375,11 +2411,12 @@ dependencies = [ "checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum getrandom 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571" +"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" +"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" -"checksum http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "372bcb56f939e449117fb0869c2e8fd8753a8223d92a172c6e808cf123a5b6e4" +"checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" "checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" "checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" @@ -2387,45 +2424,45 @@ dependencies = [ "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum indexmap 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a61202fbe46c4a951e9404a720a0180bcf3212c750d735cb5c4ba4dc551299f3" +"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" -"checksum insta 0.11.0 (git+https://github.com/mitsuhiko/insta)" = "" -"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08" -"checksum itertools 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b8467d9c1cebe26feb08c640139247fac215782d35371ade9a2136ed6085358" +"checksum insta 0.12.0 (git+https://github.com/mitsuhiko/insta)" = "" +"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +"checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" "checksum jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f52a11f73b88fab829a0e4d9e13ea5982c7ac457c72eb3541d82a4afdfce4ff" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" -"checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc" +"checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" "checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" "checksum md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e6bcd6433cff03a4bfc3d9834d504467db1f1cf6d0ea765d37d330249ed629d" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" -"checksum memoffset 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ce6075db033bbbb7ee5a0bbd3a3186bbae616f57fb001c485c7ff77955f8177f" +"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" "checksum mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "dd1d63acd1b78403cc0c325605908475dd9b9a3acbf65ed8bcab97e27014afcf" "checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" -"checksum miniz_oxide 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7108aff85b876d06f22503dcce091e29f76733b2bfdd91eebce81f5e68203a10" -"checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23" -"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40" +"checksum miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625" +"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +"checksum mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum nodrop 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "2f9667ddcc6cc8a43afc9b7917599d7216aa09c463919ea32c59ed6cac8bc945" -"checksum notify 4.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1191efa2b8fe041decb55c238a125b7a1aeb6fad7a525133a02be5ec949ff3cb" -"checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32" -"checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273" +"checksum notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "199628fc33b21bc767baa057490b00b382ecbae030803a7b36292422d15b778b" +"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" +"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" +"checksum openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3cc5799d98e1088141b8e01ff760112bbd9f19d850c124500566ca6901a585" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.50 (registry+https://github.com/rust-lang/crates.io-index)" = "2c42dcccb832556b5926bc9ae61e8775f2a61e725ab07ab3d1e7fcf8ae62c3b6" +"checksum openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)" = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" @@ -2437,14 +2474,14 @@ dependencies = [ "checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" "checksum pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9fcf299b5712d06ee128a556c94709aaa04512c4dffb8ead07c5c998447fc0" "checksum pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df43fd99896fd72c485fe47542c7b500e4ac1e8700bf995544d1317a60ded547" -"checksum pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "72d5370d90f49f70bd033c3d75e87fc529fbfff9d6f7cccef07d6170079d91ea" -"checksum ppv-lite86 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e3cbf9f658cdb5000fcf6f362b8ea2ba154b9f146a61c7a20d647034c6b6561b" +"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" +"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" -"checksum proc-macro-hack 0.5.10 (registry+https://github.com/rust-lang/crates.io-index)" = "114cdf1f426eb7f550f01af5f53a33c0946156f6814aec939b3bd77e844f9a9d" +"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "90cf5f418035b98e655e9cdb225047638296b862b42411c4e45bb88d700f7fc0" -"checksum publicsuffix 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9bf259a81de2b2eb9850ec990ec78e6a25319715584fd7652b9b26f96fcb1510" +"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum publicsuffix 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" "checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" @@ -2466,8 +2503,8 @@ dependencies = [ "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" "checksum rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e18c91676f670f6f0312764c759405f13afb98d5d73819840cf72a518487bff" -"checksum rayon 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "83a27732a533a1be0a0035a111fe76db89ad312f6f0347004c220c57f209a123" -"checksum rayon-core 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "98dcf634205083b17d0861252431eb2acbfb698ab7478a2d20de07954f47ec7b" +"checksum rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43739f8831493b276363637423d3622d4bd6394ab6f0a9c4a552e208aeb7fddd" +"checksum rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8bf17de6f23b05473c437eb958b9c850bfc8af0961fe17b4cc92d5a627b4791" "checksum rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81428c521a07a3feac9c31180a886e467eecf81b769987f70d51d567a09c321d" "checksum rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b7c983d7bfcf0811a164e33e99e2da456f38babb33c75e365b17aa1ee5fd2d" "checksum rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c147f9006c1cfd3a1872d36e91d5fca88d4b94fafa5463f774a00f293b1277" @@ -2478,36 +2515,36 @@ dependencies = [ "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum reqwest 0.9.21 (registry+https://github.com/rust-lang/crates.io-index)" = "02b7e953e14c6f3102b7e8d1f1ee3abf5ecee80b427f5565c9389835cecae95c" +"checksum reqwest 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)" = "2c2064233e442ce85c77231ebd67d9eca395207dec2127fe0bbedde4bd29a650" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62fc0e980c94fe9ef795b1bb3874649c8c6e9bb67d3b90d48380ba24c69c23ea" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c92464b447c0ee8c4fb3824ecc8383b81717b9f1e74ba2e72540aef7b9f82997" +"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" "checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" "checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2" -"checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56" +"checksum security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" +"checksum security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "9796c9b7ba2ffe7a9ce53c2287dfc48080f4b2b362fcc245a259b3a7201119dd" -"checksum serde_derive 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)" = "4b133a43a1ecd55d4086bd5b4dc6c1751c68b1bfbeba7a5040442022c7e7c02e" -"checksum serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)" = "2f72eb2a68a7dc3f9a691bfda9305a1c017a6215e5a4545c258500d2099a37c2" +"checksum serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" +"checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" +"checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" "checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" -"checksum serde_yaml 0.8.9 (registry+https://github.com/rust-lang/crates.io-index)" = "38b08a9a90e5260fe01c6480ec7c811606df6d3a660415808c3c3fa8ed95b582" +"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" "checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7" +"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" "checksum snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef82be0baf3ae45701ab992230f1f4889c15984736d87f37558aea3e4e321af" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum syn 0.15.44 (registry+https://github.com/rust-lang/crates.io-index)" = "9ca4b3b69a77cbe1ffc9e198781b7acb0c7365a883670e8f1c1bc66fba79a5c5" -"checksum syn 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "66850e97125af79138385e9b88339cbcd037e3f28ceab8c5ad98e64f0f1f80bf" -"checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f" +"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" +"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" @@ -2520,32 +2557,34 @@ dependencies = [ "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" "checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" -"checksum tokio-executor 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0f27ee0e6db01c5f0b2973824547ce7e637b2ed79b891a9677b0de9bd532b6ac" +"checksum tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ca6df436c42b0c3330a82d855d2ef017cd793090ad550a6bc2184f4b933532ab" "checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" "checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" -"checksum tokio-reactor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "c56391be9805bc80163151c0b9e5164ee64f4b0200962c346fea12773158f22d" -"checksum tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7" +"checksum tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6732fe6b53c8d11178dcb77ac6d9682af27fc6d4cb87789449152e5377377146" +"checksum tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d06554cce1ae4a50f42fba8023918afa931413aded705b560e29600ccf7c6d76" "checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2bd2c6a3885302581f4401c82af70d792bb9df1700e7437b0aeb4ada94d5388c" -"checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e" +"checksum tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c32ffea4827978e9aa392d2f743d973c1dfa3730a2ed3f22ce1e6984da848c" +"checksum tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1739638e364e558128461fc1ad84d997702c8e31c2e6b18fb99842268199e827" "checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" "checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" -"checksum unicase 2.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2e2e6bd1e59e56598518beb94fd6db628ded570326f0a98c679a304bd9f00150" +"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "141339a08b982d942be2ca06ff8b076563cbe223d1befd5450716790d44e2426" -"checksum unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "7007dbd421b92cc6e28410fe7362e2e0a2503394908f417b68ec8d1c364c4e20" +"checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" +"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" "checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" -"checksum vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "33dd455d0f96e90a75803cfeb7f948768c08d70a6de9a8d2362461935698bf95" +"checksum uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" +"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" +"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" "checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" "checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" diff --git a/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap b/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap index 21a7a396..4b9740e1 100644 --- a/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap +++ b/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap @@ -25,14 +25,12 @@ expression: contents 1 null - - + Cool StringValue - - + Did you know that BaseValue.Changed is different than Instance.Changed? diff --git a/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap b/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap index 26ada371..9a796330 100644 --- a/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap +++ b/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap @@ -6,22 +6,19 @@ expression: contents rbxmx_ref - - + Target - - + Pointed to by ObjectValue Pointer - - + 1 From ff4e9fb027c7d5eb0c8e9c1675585c8b2a49e807 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Dec 2019 17:13:37 -0800 Subject: [PATCH 0908/1504] Stop overriding default-members in CI --- .github/workflows/ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2ad6cf92..b127abd4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,10 +18,10 @@ jobs: run: rustup default ${{ matrix.rust_version }} - name: Build - run: cargo build --all --locked --verbose + run: cargo build --locked --verbose - name: Run tests - run: cargo test --all --locked --verbose + run: cargo test --locked --verbose - name: Rustfmt and Clippy run: | From 8b1e85fbb42329acb98e1902c798724ae7960db6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 11 Dec 2019 18:05:44 -0800 Subject: [PATCH 0909/1504] Upgrade dependencies --- Cargo.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9be098ea..ae259aee 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1463,7 +1463,7 @@ dependencies = [ [[package]] name = "rbx_xml" -version = "0.11.2" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1520,7 +1520,7 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.22" +version = "0.9.24" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1608,9 +1608,9 @@ dependencies = [ "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", "rojo-insta-ext 0.1.0", @@ -1642,7 +1642,7 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", "rojo 0.6.0-dev", "rojo-insta-ext 0.1.0", "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2508,14 +2508,14 @@ dependencies = [ "checksum rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81428c521a07a3feac9c31180a886e467eecf81b769987f70d51d567a09c321d" "checksum rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b7c983d7bfcf0811a164e33e99e2da456f38babb33c75e365b17aa1ee5fd2d" "checksum rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c147f9006c1cfd3a1872d36e91d5fca88d4b94fafa5463f774a00f293b1277" -"checksum rbx_xml 0.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b0236363b0af0c78f3e972ac7f46a1f355f663518e276253136d0180f3c8742c" +"checksum rbx_xml 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b58063a6ccf8d27efa772ea816a99d1d411e2fdc47a141e26a493cd1c938ff1" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" "checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum reqwest 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)" = "2c2064233e442ce85c77231ebd67d9eca395207dec2127fe0bbedde4bd29a650" +"checksum reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" "checksum rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62fc0e980c94fe9ef795b1bb3874649c8c6e9bb67d3b90d48380ba24c69c23ea" From 47c7f63d75163c972baaa7b9ddce6e9f52cee1d9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 12 Dec 2019 14:30:47 -0800 Subject: [PATCH 0910/1504] Switch everything to StructOpt (#277) * Add types for Rojo's subcommands * Flesh out CLI types * Port everything to structopt instead of clap --- Cargo.lock | 51 ++++++++++- Cargo.toml | 3 +- src/bin.rs | 200 ++++++----------------------------------- src/cli.rs | 191 +++++++++++++++++++++++++++++++++++++++ src/commands/build.rs | 26 ++---- src/commands/init.rs | 30 ++----- src/commands/serve.rs | 12 +-- src/commands/upload.rs | 17 +--- src/lib.rs | 1 + 9 files changed, 296 insertions(+), 235 deletions(-) create mode 100644 src/cli.rs diff --git a/Cargo.lock b/Cargo.lock index ae259aee..a08937cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -602,6 +602,14 @@ dependencies = [ "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "hermit-abi" version = "0.1.3" @@ -1169,6 +1177,16 @@ dependencies = [ "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro-error" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "proc-macro-hack" version = "0.5.11" @@ -1588,7 +1606,6 @@ dependencies = [ name = "rojo" version = "0.6.0-dev" dependencies = [ - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1617,6 +1634,7 @@ dependencies = [ "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1850,6 +1868,27 @@ name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "structopt" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "syn" version = "1.0.11" @@ -2170,6 +2209,11 @@ dependencies = [ "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "unicode-segmentation" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "unicode-width" version = "0.1.7" @@ -2414,6 +2458,7 @@ dependencies = [ "checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" "checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" @@ -2477,6 +2522,7 @@ dependencies = [ "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" "checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" +"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" "checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" @@ -2543,6 +2589,8 @@ dependencies = [ "checksum snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef82be0baf3ae45701ab992230f1f4889c15984736d87f37558aea3e4e321af" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "30b3a3e93f5ad553c38b3301c8a0a0cec829a36783f6a0c467fc4bf553a5f5bf" +"checksum structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea692d40005b3ceba90a9fe7a78fa8d4b82b0ce627eebbffc329aab850f3410e" "checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" "checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" @@ -2574,6 +2622,7 @@ dependencies = [ "checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" "checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" +"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" "checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" diff --git a/Cargo.toml b/Cargo.toml index 4e2c2742..9e203466 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,7 +48,6 @@ name = "build" harness = false [dependencies] -clap = "2.27" crossbeam-channel = "0.3.9" csv = "1.0" env_logger = "0.6" @@ -57,6 +56,7 @@ futures = "0.1" humantime = "1.3.0" hyper = "0.12" jod-thread = "0.1.0" +lazy_static = "1.4.0" log = "0.4" maplit = "1.0.1" notify = "4.0" @@ -70,6 +70,7 @@ ritz = "0.1.0" rlua = "0.16.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +structopt = "0.3" termcolor = "1.0.5" uuid = { version = "0.7", features = ["v4", "serde"] } diff --git a/src/bin.rs b/src/bin.rs index f49dc2bb..0616517c 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -1,63 +1,19 @@ -use std::{ - env, panic, - path::{Path, PathBuf}, - process, +use std::{panic, process}; + +use failure::Error; +use log::error; +use structopt::StructOpt; + +use librojo::{ + cli::{Options, Subcommand}, + commands, }; -use clap::{clap_app, ArgMatches}; -use log::error; - -use librojo::commands; - -fn make_path_absolute(value: &Path) -> PathBuf { - if value.is_absolute() { - PathBuf::from(value) - } else { - let current_dir = env::current_dir().unwrap(); - current_dir.join(value) - } -} - fn main() { - let app = clap_app!(Rojo => - (version: env!("CARGO_PKG_VERSION")) - (author: env!("CARGO_PKG_AUTHORS")) - (about: env!("CARGO_PKG_DESCRIPTION")) - - (@arg verbose: --verbose -v +multiple +global "Sets verbosity level. Can be specified multiple times.") - - (@subcommand init => - (about: "Creates a new Rojo project.") - (@arg PATH: "Path to the place to create the project. Defaults to the current directory.") - (@arg kind: --kind +takes_value "The kind of project to create, 'place' or 'model'. Defaults to place.") - ) - - (@subcommand serve => - (about: "Serves the project's files for use with the Rojo Studio plugin.") - (@arg PROJECT: "Path to the project to serve. Defaults to the current directory.") - (@arg port: --port +takes_value "The port to listen on. Defaults to 34872.") - ) - - (@subcommand build => - (about: "Generates a model or place file from the project.") - (@arg PROJECT: "Path to the project to serve. Defaults to the current directory.") - (@arg output: --output -o +takes_value +required "Where to output the result.") - ) - - (@subcommand upload => - (about: "Generates a place or model file out of the project and uploads it to Roblox.") - (@arg PROJECT: "Path to the project to upload. Defaults to the current directory.") - (@arg kind: --kind +takes_value "The kind of asset to generate, 'place', or 'model'. Defaults to place.") - (@arg cookie: --cookie +takes_value "Authenication cookie to use. If not specified, Rojo will attempt to find one from the system automatically.") - (@arg asset_id: --asset_id +takes_value +required "Asset ID to upload to.") - ) - ); - - let matches = app.get_matches(); + let options = Options::from_args(); { - let verbosity = matches.occurrences_of("verbose"); - let log_filter = match verbosity { + let log_filter = match options.verbosity { 0 => "warn", 1 => "warn,librojo=info", 2 => "warn,librojo=trace", @@ -71,15 +27,14 @@ fn main() { .init(); } - let result = panic::catch_unwind(|| match matches.subcommand() { - ("init", Some(sub_matches)) => start_init(sub_matches), - ("serve", Some(sub_matches)) => start_serve(sub_matches), - ("build", Some(sub_matches)) => start_build(sub_matches), - ("upload", Some(sub_matches)) => start_upload(sub_matches), - _ => eprintln!("Usage: rojo \nUse 'rojo help' for more help."), + let panic_result = panic::catch_unwind(|| { + if let Err(err) = run(options.subcommand) { + log::error!("{}", err); + process::exit(1); + } }); - if let Err(error) = result { + if let Err(error) = panic_result { let message = match error.downcast_ref::<&str>() { Some(message) => message.to_string(), None => match error.downcast_ref::() { @@ -93,6 +48,17 @@ fn main() { } } +fn run(subcommand: Subcommand) -> Result<(), Error> { + match subcommand { + Subcommand::Init(init_options) => commands::init(init_options)?, + Subcommand::Serve(serve_options) => commands::serve(serve_options)?, + Subcommand::Build(build_options) => commands::build(build_options)?, + Subcommand::Upload(upload_options) => commands::upload(upload_options)?, + } + + Ok(()) +} + fn show_crash_message(message: &str) { error!("Rojo crashed!"); error!("This is a bug in Rojo."); @@ -101,113 +67,3 @@ fn show_crash_message(message: &str) { error!(""); error!("Details: {}", message); } - -fn start_init(sub_matches: &ArgMatches) { - let fuzzy_project_path = - make_path_absolute(Path::new(sub_matches.value_of("PATH").unwrap_or(""))); - let kind = sub_matches.value_of("kind"); - - let options = commands::InitOptions { - fuzzy_project_path, - kind, - }; - - match commands::init(&options) { - Ok(_) => {} - Err(e) => { - error!("{}", e); - process::exit(1); - } - } -} - -fn start_serve(sub_matches: &ArgMatches) { - let fuzzy_project_path = match sub_matches.value_of("PROJECT") { - Some(v) => make_path_absolute(Path::new(v)), - None => std::env::current_dir().unwrap(), - }; - - let port = match sub_matches.value_of("port") { - Some(v) => match v.parse::() { - Ok(port) => Some(port), - Err(_) => { - error!("Invalid port {}", v); - process::exit(1); - } - }, - None => None, - }; - - let options = commands::ServeOptions { - fuzzy_project_path, - port, - }; - - match commands::serve(&options) { - Ok(_) => {} - Err(e) => { - error!("{}", e); - process::exit(1); - } - } -} - -fn start_build(sub_matches: &ArgMatches) { - let fuzzy_project_path = match sub_matches.value_of("PROJECT") { - Some(v) => make_path_absolute(Path::new(v)), - None => std::env::current_dir().unwrap(), - }; - - let output_file = make_path_absolute(Path::new(sub_matches.value_of("output").unwrap())); - - let options = commands::BuildOptions { - fuzzy_project_path, - output_file, - output_kind: None, // TODO: Accept from argument - }; - - match commands::build(&options) { - Ok(_) => {} - Err(e) => { - error!("{}", e); - process::exit(1); - } - } -} - -fn start_upload(sub_matches: &ArgMatches) { - let fuzzy_project_path = match sub_matches.value_of("PROJECT") { - Some(v) => make_path_absolute(Path::new(v)), - None => std::env::current_dir().unwrap(), - }; - - let kind = sub_matches.value_of("kind"); - let auth_cookie = sub_matches.value_of("cookie").map(Into::into); - - let asset_id: u64 = { - let arg = sub_matches.value_of("asset_id").unwrap(); - - match arg.parse() { - Ok(v) => v, - Err(_) => { - error!("Invalid place ID {}", arg); - process::exit(1); - } - } - }; - - let options = commands::UploadOptions { - fuzzy_project_path, - auth_cookie, - asset_id, - kind, - }; - - match commands::upload(options) { - Ok(_) => {} - Err(e) => { - error!("{}", e); - process::exit(1); - } - } -} diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 00000000..4f721b49 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,191 @@ +//! Defines Rojo's CLI through structopt types. + +#![deny(missing_docs)] + +use std::{env, error::Error, fmt, path::PathBuf, str::FromStr}; + +use structopt::StructOpt; + +/// Trick used with structopt to get the initial working directory of the +/// process and store it for use in default values. +fn working_dir() -> &'static str { + lazy_static::lazy_static! { + static ref INITIAL_WORKING_DIR: String = { + env::current_dir().unwrap().display().to_string() + }; + } + + &INITIAL_WORKING_DIR +} + +/// Command line options that Rojo accepts, defined using the structopt crate. +#[derive(Debug, StructOpt)] +#[structopt(name = "Rojo", about, author)] +pub struct Options { + /// Sets verbosity level. Can be specified multiple times. + #[structopt(long = "verbose", short, parse(from_occurrences))] + pub verbosity: u8, + + /// Subcommand to run in this invocation. + #[structopt(subcommand)] + pub subcommand: Subcommand, +} + +/// All of Rojo's subcommands. +#[derive(Debug, StructOpt)] +pub enum Subcommand { + /// Creates a new Rojo project. + Init(InitCommand), + + /// Serves the project's files for use with the Rojo Studio plugin. + Serve(ServeCommand), + + /// Generates a model or place file from the project. + Build(BuildCommand), + + /// Generates a place or model file out of the project and uploads it to Roblox. + Upload(UploadCommand), +} + +/// Initializes a new Rojo project. +#[derive(Debug, StructOpt)] +pub struct InitCommand { + /// Path to the place to create the project. Defaults to the current directory. + #[structopt(default_value = &working_dir())] + pub path: PathBuf, + + /// The kind of project to create, 'place' or 'model'. Defaults to place. + #[structopt(long, default_value = "place")] + pub kind: InitKind, +} + +/// The templates we support for initializing a Rojo project. +#[derive(Debug, Clone, Copy)] +pub enum InitKind { + /// A place that matches what File -> New does in Roblox Studio. + Place, + + /// An empty model, suitable for a library or plugin. + Model, +} + +impl FromStr for InitKind { + type Err = InitKindParseError; + + fn from_str(source: &str) -> Result { + match source { + "place" => Ok(InitKind::Place), + "model" => Ok(InitKind::Model), + _ => Err(InitKindParseError { + attempted: source.to_owned(), + }), + } + } +} + +/// Error type for failing to parse an `InitKind`. +#[derive(Debug)] +pub struct InitKindParseError { + attempted: String, +} + +impl Error for InitKindParseError {} + +impl fmt::Display for InitKindParseError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!( + formatter, + "Invalid init kind '{}'. Valid kinds are: place, model", + self.attempted + ) + } +} + +/// Expose a Rojo project through a web server that can communicate with the +/// Rojo Roblox Studio plugin, or be visited by the user in the browser. +#[derive(Debug, StructOpt)] +pub struct ServeCommand { + /// Path to the project to serve. Defaults to the current directory. + #[structopt(default_value = &working_dir())] + pub project: PathBuf, + + /// The port to listen on. Defaults to the project's preference, or 34872 if + /// it has none. + #[structopt(long)] + pub port: Option, +} + +/// Build a Rojo project into a file. +#[derive(Debug, StructOpt)] +pub struct BuildCommand { + /// Path to the project to serve. Defaults to the current directory. + #[structopt(default_value = &working_dir())] + pub project: PathBuf, + + /// Where to output the result. + #[structopt(long, short)] + pub output: PathBuf, +} + +/// Build and upload a Rojo project to Roblox.com. +#[derive(Debug, StructOpt)] +pub struct UploadCommand { + /// Path to the project to upload. Defaults to the current directory. + #[structopt(default_value = &working_dir())] + pub project: PathBuf, + + /// The kind of asset to generate, 'place', or 'model'. Defaults to place. + #[structopt(long, default_value = "place")] + pub kind: UploadKind, + + /// Authenication cookie to use. If not specified, Rojo will attempt to find one from the system automatically. + #[structopt(long)] + pub cookie: Option, + + /// Asset ID to upload to. + #[structopt(long = "asset_id")] + pub asset_id: u64, +} + +/// The kind of asset to upload to the website. Affects what endpoints Rojo uses +/// and changes how the asset is built. +#[derive(Debug, Clone, Copy)] +pub enum UploadKind { + /// Upload to a place. + Place, + + /// Upload to a model-like asset, like a Model, Plugin, or Package. + Model, +} + +impl FromStr for UploadKind { + type Err = UploadKindParseError; + + fn from_str(source: &str) -> Result { + match source { + "place" => Ok(UploadKind::Place), + "model" => Ok(UploadKind::Model), + _ => Err(UploadKindParseError { + attempted: source.to_owned(), + }), + } + } +} + +/// Error type for failing to parse an `UploadKind`. +#[derive(Debug)] +pub struct UploadKindParseError { + attempted: String, +} + +impl Error for UploadKindParseError {} + +impl fmt::Display for UploadKindParseError { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + write!( + formatter, + "Invalid upload kind '{}'. Valid kinds are: place, model", + self.attempted + ) + } +} diff --git a/src/commands/build.rs b/src/commands/build.rs index 8f9fed5c..d5021dc1 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -1,27 +1,27 @@ use std::{ fs::File, io::{self, BufWriter, Write}, - path::PathBuf, }; use failure::Fail; use crate::{ + cli::BuildCommand, common_setup, project::ProjectLoadError, vfs::{FsError, RealFetcher, Vfs, WatchMode}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum OutputKind { +enum OutputKind { Rbxmx, Rbxlx, Rbxm, Rbxl, } -fn detect_output_kind(options: &BuildOptions) -> Option { - let extension = options.output_file.extension()?.to_str()?; +fn detect_output_kind(options: &BuildCommand) -> Option { + let extension = options.output.extension()?.to_str()?; match extension { "rbxlx" => Some(OutputKind::Rbxlx), @@ -32,13 +32,6 @@ fn detect_output_kind(options: &BuildOptions) -> Option { } } -#[derive(Debug)] -pub struct BuildOptions { - pub fuzzy_project_path: PathBuf, - pub output_file: PathBuf, - pub output_kind: Option, -} - #[derive(Debug, Fail)] pub enum BuildError { #[fail(display = "Could not detect what kind of file to create")] @@ -72,22 +65,19 @@ fn xml_encode_config() -> rbx_xml::EncodeOptions { rbx_xml::EncodeOptions::new().property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown) } -pub fn build(options: &BuildOptions) -> Result<(), BuildError> { - let output_kind = options - .output_kind - .or_else(|| detect_output_kind(options)) - .ok_or(BuildError::UnknownOutputKind)?; +pub fn build(options: BuildCommand) -> Result<(), BuildError> { + let output_kind = detect_output_kind(&options).ok_or(BuildError::UnknownOutputKind)?; log::debug!("Hoping to generate file of type {:?}", output_kind); log::trace!("Constructing in-memory filesystem"); let vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); - let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &vfs); + let (_maybe_project, tree) = common_setup::start(&options.project, &vfs); let root_id = tree.get_root_id(); log::trace!("Opening output file for write"); - let mut file = BufWriter::new(File::create(&options.output_file)?); + let mut file = BufWriter::new(File::create(&options.output)?); match output_kind { OutputKind::Rbxmx => { diff --git a/src/commands/init.rs b/src/commands/init.rs index e17ba6dd..c4fe437f 100644 --- a/src/commands/init.rs +++ b/src/commands/init.rs @@ -1,17 +1,12 @@ -use std::path::PathBuf; - use failure::Fail; -use crate::project::{Project, ProjectInitError}; +use crate::{ + cli::{InitCommand, InitKind}, + project::{Project, ProjectInitError}, +}; #[derive(Debug, Fail)] pub enum InitError { - #[fail( - display = "Invalid project kind '{}', valid kinds are 'place' and 'model'", - _0 - )] - InvalidKind(String), - #[fail(display = "Project init error: {}", _0)] ProjectInitError(#[fail(cause)] ProjectInitError), } @@ -20,23 +15,16 @@ impl_from!(InitError { ProjectInitError => ProjectInitError, }); -#[derive(Debug)] -pub struct InitOptions<'a> { - pub fuzzy_project_path: PathBuf, - pub kind: Option<&'a str>, -} - -pub fn init(options: &InitOptions) -> Result<(), InitError> { +pub fn init(options: InitCommand) -> Result<(), InitError> { let (project_path, project_kind) = match options.kind { - Some("place") | None => { - let path = Project::init_place(&options.fuzzy_project_path)?; + InitKind::Place => { + let path = Project::init_place(&options.path)?; (path, "place") } - Some("model") => { - let path = Project::init_model(&options.fuzzy_project_path)?; + InitKind::Model => { + let path = Project::init_model(&options.path)?; (path, "model") } - Some(invalid) => return Err(InitError::InvalidKind(invalid.to_string())), }; println!( diff --git a/src/commands/serve.rs b/src/commands/serve.rs index 26a35b39..06c83614 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -1,6 +1,5 @@ use std::{ io::{self, Write}, - path::PathBuf, sync::Arc, }; @@ -8,6 +7,7 @@ use failure::Fail; use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; use crate::{ + cli::ServeCommand, project::ProjectLoadError, serve_session::ServeSession, vfs::{RealFetcher, Vfs, WatchMode}, @@ -16,12 +16,6 @@ use crate::{ const DEFAULT_PORT: u16 = 34872; -#[derive(Debug)] -pub struct ServeOptions { - pub fuzzy_project_path: PathBuf, - pub port: Option, -} - #[derive(Debug, Fail)] pub enum ServeError { #[fail(display = "Couldn't load project: {}", _0)] @@ -32,10 +26,10 @@ impl_from!(ServeError { ProjectLoadError => ProjectLoad, }); -pub fn serve(options: &ServeOptions) -> Result<(), ServeError> { +pub fn serve(options: ServeCommand) -> Result<(), ServeError> { let vfs = Vfs::new(RealFetcher::new(WatchMode::Enabled)); - let session = Arc::new(ServeSession::new(vfs, &options.fuzzy_project_path)); + let session = Arc::new(ServeSession::new(vfs, &options.project)); let port = options .port diff --git a/src/commands/upload.rs b/src/commands/upload.rs index 68054591..df6f8429 100644 --- a/src/commands/upload.rs +++ b/src/commands/upload.rs @@ -1,10 +1,9 @@ -use std::path::PathBuf; - use failure::Fail; use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}; use crate::{ auth_cookie::get_auth_cookie, + cli::UploadCommand, common_setup, vfs::{RealFetcher, Vfs, WatchMode}, }; @@ -29,24 +28,16 @@ impl_from!(UploadError { reqwest::Error => Http, }); -#[derive(Debug)] -pub struct UploadOptions<'a> { - pub fuzzy_project_path: PathBuf, - pub auth_cookie: Option, - pub asset_id: u64, - pub kind: Option<&'a str>, -} - -pub fn upload(options: UploadOptions) -> Result<(), UploadError> { +pub fn upload(options: UploadCommand) -> Result<(), UploadError> { let cookie = options - .auth_cookie + .cookie .or_else(get_auth_cookie) .ok_or(UploadError::NeedAuthCookie)?; log::trace!("Constructing in-memory filesystem"); let vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); - let (_maybe_project, tree) = common_setup::start(&options.fuzzy_project_path, &vfs); + let (_maybe_project, tree) = common_setup::start(&options.project, &vfs); let root_id = tree.get_root_id(); let mut buffer = Vec::new(); diff --git a/src/lib.rs b/src/lib.rs index 12953c3a..6e4f8e42 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ #[macro_use] mod impl_from; +pub mod cli; pub mod commands; // This module is only public for testing right now, and won't be From 1f7f2b22e72f6b0a36b41ca9019337af298c710a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 12 Dec 2019 14:45:15 -0800 Subject: [PATCH 0911/1504] Rewrite Project, remove SourceProject (#274) * Rewrite project file to have relative paths and drop SourceProject * Redo project error types * Tidy up and document Project type * Strip out init command --- Cargo.lock | 28 + Cargo.toml | 1 + .../build_test__rbxmx_in_folder.snap | 6 +- .../build_test__rbxmx_ref.rbxmx.snap | 9 +- src/change_processor.rs | 15 +- src/commands/build.rs | 6 +- src/commands/init.rs | 30 +- src/commands/serve.rs | 6 +- src/common_setup.rs | 20 +- src/project.rs | 579 ++++-------------- src/snapshot/metadata.rs | 16 +- src/snapshot_middleware/project.rs | 28 +- .../test__project_with_children.snap | 7 +- ...ct_with_path_to_project_with_children.snap | 7 +- ...session__change_file_in_project_after.snap | 7 +- ...ession__change_file_in_project_before.snap | 7 +- 16 files changed, 233 insertions(+), 539 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a08937cc..e2939241 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -403,6 +403,11 @@ dependencies = [ "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "doc-comment" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "dtoa" version = "0.4.4" @@ -1634,6 +1639,7 @@ dependencies = [ "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", + "snafu 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1847,6 +1853,25 @@ name = "smallvec" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "snafu" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "snafu-derive 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "snafu-derive" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "snax" version = "0.2.0" @@ -2433,6 +2458,7 @@ dependencies = [ "checksum ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +"checksum doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" @@ -2586,6 +2612,8 @@ dependencies = [ "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" "checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" +"checksum snafu 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41207ca11f96a62cd34e6b7fdf73d322b25ae3848eb9d38302169724bb32cf27" +"checksum snafu-derive 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5e338c8b0577457c9dda8e794b6ad7231c96e25b1b0dd5842d52249020c1c0" "checksum snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef82be0baf3ae45701ab992230f1f4889c15984736d87f37558aea3e4e321af" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" diff --git a/Cargo.toml b/Cargo.toml index 9e203466..e501d3eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -70,6 +70,7 @@ ritz = "0.1.0" rlua = "0.16.3" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" +snafu = "0.6.0" structopt = "0.3" termcolor = "1.0.5" uuid = { version = "0.7", features = ["v4", "serde"] } diff --git a/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap b/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap index 4b9740e1..21a7a396 100644 --- a/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap +++ b/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap @@ -25,12 +25,14 @@ expression: contents 1 null - + + Cool StringValue - + + Did you know that BaseValue.Changed is different than Instance.Changed? diff --git a/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap b/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap index 9a796330..26ada371 100644 --- a/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap +++ b/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap @@ -6,19 +6,22 @@ expression: contents rbxmx_ref - + + Target - + + Pointed to by ObjectValue Pointer - + + 1 diff --git a/src/change_processor.rs b/src/change_processor.rs index f13241e7..c721260a 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -178,15 +178,20 @@ fn update_affected_instances( } } } - InstigatingSource::ProjectNode(instance_name, project_node) => { + InstigatingSource::ProjectNode(project_path, instance_name, project_node) => { // This instance is the direct subject of a project node. Since // there might be information associated with our instance from // the project file, we snapshot the entire project node again. - let snapshot = - snapshot_project_node(&metadata.context, instance_name, project_node, &vfs) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); + let snapshot = snapshot_project_node( + &metadata.context, + &project_path, + instance_name, + project_node, + &vfs, + ) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); let patch_set = compute_patch_set(&snapshot, &tree, id); apply_patch_set(tree, patch_set) diff --git a/src/commands/build.rs b/src/commands/build.rs index d5021dc1..1e3a03a5 100644 --- a/src/commands/build.rs +++ b/src/commands/build.rs @@ -8,7 +8,7 @@ use failure::Fail; use crate::{ cli::BuildCommand, common_setup, - project::ProjectLoadError, + project::ProjectError, vfs::{FsError, RealFetcher, Vfs, WatchMode}, }; @@ -47,7 +47,7 @@ pub enum BuildError { BinaryModelEncodeError(rbx_binary::EncodeError), #[fail(display = "{}", _0)] - ProjectLoadError(#[fail(cause)] ProjectLoadError), + ProjectError(#[fail(cause)] ProjectError), #[fail(display = "{}", _0)] FsError(#[fail(cause)] FsError), @@ -57,7 +57,7 @@ impl_from!(BuildError { io::Error => IoError, rbx_xml::EncodeError => XmlModelEncodeError, rbx_binary::EncodeError => BinaryModelEncodeError, - ProjectLoadError => ProjectLoadError, + ProjectError => ProjectError, FsError => FsError, }); diff --git a/src/commands/init.rs b/src/commands/init.rs index c4fe437f..2ea6b5e3 100644 --- a/src/commands/init.rs +++ b/src/commands/init.rs @@ -1,37 +1,17 @@ use failure::Fail; -use crate::{ - cli::{InitCommand, InitKind}, - project::{Project, ProjectInitError}, -}; +use crate::{cli::InitCommand, project::ProjectError}; #[derive(Debug, Fail)] pub enum InitError { #[fail(display = "Project init error: {}", _0)] - ProjectInitError(#[fail(cause)] ProjectInitError), + ProjectError(#[fail(cause)] ProjectError), } impl_from!(InitError { - ProjectInitError => ProjectInitError, + ProjectError => ProjectError, }); -pub fn init(options: InitCommand) -> Result<(), InitError> { - let (project_path, project_kind) = match options.kind { - InitKind::Place => { - let path = Project::init_place(&options.path)?; - (path, "place") - } - InitKind::Model => { - let path = Project::init_model(&options.path)?; - (path, "model") - } - }; - - println!( - "Created new {} project file at {}", - project_kind, - project_path.display() - ); - - Ok(()) +pub fn init(_options: InitCommand) -> Result<(), InitError> { + unimplemented!("init command"); } diff --git a/src/commands/serve.rs b/src/commands/serve.rs index 06c83614..bc47f981 100644 --- a/src/commands/serve.rs +++ b/src/commands/serve.rs @@ -8,7 +8,7 @@ use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; use crate::{ cli::ServeCommand, - project::ProjectLoadError, + project::ProjectError, serve_session::ServeSession, vfs::{RealFetcher, Vfs, WatchMode}, web::LiveServer, @@ -19,11 +19,11 @@ const DEFAULT_PORT: u16 = 34872; #[derive(Debug, Fail)] pub enum ServeError { #[fail(display = "Couldn't load project: {}", _0)] - ProjectLoad(#[fail(cause)] ProjectLoadError), + ProjectError(#[fail(cause)] ProjectError), } impl_from!(ServeError { - ProjectLoadError => ProjectLoad, + ProjectError => ProjectError, }); pub fn serve(options: ServeCommand) -> Result<(), ServeError> { diff --git a/src/common_setup.rs b/src/common_setup.rs index 160b4c6c..a744b5b5 100644 --- a/src/common_setup.rs +++ b/src/common_setup.rs @@ -6,7 +6,7 @@ use std::path::Path; use rbx_dom_weak::RbxInstanceProperties; use crate::{ - project::{Project, ProjectLoadError}, + project::Project, snapshot::{ apply_patch_set, compute_patch_set, InstanceContext, InstancePropertiesWithMeta, RojoTree, }, @@ -19,11 +19,7 @@ pub fn start( vfs: &Vfs, ) -> (Option, RojoTree) { log::trace!("Loading project file from {}", fuzzy_project_path.display()); - let maybe_project = match Project::load_fuzzy(fuzzy_project_path) { - Ok(project) => Some(project), - Err(ProjectLoadError::NotFound) => None, - Err(other) => panic!("{}", other), // TODO: return error upward - }; + let maybe_project = Project::load_fuzzy(fuzzy_project_path).expect("TODO: Project load failed"); log::trace!("Constructing initial tree"); let mut tree = RojoTree::new(InstancePropertiesWithMeta { @@ -37,23 +33,13 @@ pub fn start( let root_id = tree.get_root_id(); - log::trace!("Constructing snapshot context"); - let snapshot_context = InstanceContext::default(); - if let Some(project) = &maybe_project { - // If the project file defines no plugins, then there's no need to - // initialize the snapshot plugin context. - if !project.plugins.is_empty() { - // TODO: Initialize plugins in instance context - } - } - log::trace!("Reading project root"); let entry = vfs .get(fuzzy_project_path) .expect("could not get project path"); log::trace!("Generating snapshot of instances from VFS"); - let snapshot = snapshot_from_vfs(&snapshot_context, vfs, &entry) + let snapshot = snapshot_from_vfs(&InstanceContext::default(), vfs, &entry) .expect("snapshot failed") .expect("snapshot did not return an instance"); diff --git a/src/project.rs b/src/project.rs index 532f6590..3ba7ed7e 100644 --- a/src/project.rs +++ b/src/project.rs @@ -1,339 +1,63 @@ use std::{ collections::{BTreeMap, HashMap, HashSet}, - fmt, - fs::{self, File}, - io, + fs, io, path::{Path, PathBuf}, }; -use failure::Fail; -use log::warn; -use rbx_dom_weak::{RbxValue, UnresolvedRbxValue}; -use serde::{Deserialize, Serialize, Serializer}; - -static DEFAULT_PLACE: &str = include_str!("../assets/place.project.json"); +use rbx_dom_weak::UnresolvedRbxValue; +use serde::{Deserialize, Serialize}; +use snafu::{ResultExt, Snafu}; pub static PROJECT_FILENAME: &str = "default.project.json"; -/// SourceProject is the format that users author projects on-disk. Since we -/// want to do things like transforming paths to be absolute before handing them -/// off to the rest of Rojo, we use this intermediate struct. -#[derive(Debug, Serialize, Deserialize)] -#[serde(deny_unknown_fields, rename_all = "camelCase")] -struct SourceProject { - name: String, - tree: SourceProjectNode, +/// Error type returned by any function that handles projects. +#[derive(Debug, Snafu)] +pub struct ProjectError(Error); - #[serde(skip_serializing_if = "Option::is_none")] - serve_port: Option, - - #[serde(skip_serializing_if = "Option::is_none")] - serve_place_ids: Option>, - - #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[cfg_attr(not(feature = "user-plugins"), serde(skip_deserializing))] - plugins: Vec, -} - -impl SourceProject { - /// Consumes the SourceProject and yields a Project, ready for prime-time. - pub fn into_project(self, project_file_location: &Path) -> Project { - let tree = self.tree.into_project_node(project_file_location); - - let project_folder = project_file_location.parent().unwrap(); - let plugins = self - .plugins - .into_iter() - .map(|path| project_folder.join(path)) - .collect(); - - Project { - name: self.name, - tree, - serve_port: self.serve_port, - serve_place_ids: self.serve_place_ids, - plugins, - file_location: PathBuf::from(project_file_location), - } - } -} - -/// An alternative serializer for `UnresolvedRbxValue` that uses the minimum -/// representation of the value. -/// -/// For example, the default Serialize impl might give you: -/// -/// ```json -/// { -/// "Type": "Bool", -/// "Value": true -/// } -/// ``` -/// -/// But in reality, users are expected to write just: -/// -/// ```json -/// true -/// ``` -/// -/// This holds true for other values that might be ambiguous or just have more -/// complicated representations like enums. -fn serialize_unresolved_minimal( - unresolved: &UnresolvedRbxValue, - serializer: S, -) -> Result -where - S: Serializer, -{ - match unresolved { - UnresolvedRbxValue::Ambiguous(_) => unresolved.serialize(serializer), - UnresolvedRbxValue::Concrete(concrete) => match concrete { - RbxValue::Bool { value } => value.serialize(serializer), - RbxValue::CFrame { value } => value.serialize(serializer), - RbxValue::Color3 { value } => value.serialize(serializer), - RbxValue::Color3uint8 { value } => value.serialize(serializer), - RbxValue::Content { value } => value.serialize(serializer), - RbxValue::Float32 { value } => value.serialize(serializer), - RbxValue::Int32 { value } => value.serialize(serializer), - RbxValue::String { value } => value.serialize(serializer), - RbxValue::UDim { value } => value.serialize(serializer), - RbxValue::UDim2 { value } => value.serialize(serializer), - RbxValue::Vector2 { value } => value.serialize(serializer), - RbxValue::Vector2int16 { value } => value.serialize(serializer), - RbxValue::Vector3 { value } => value.serialize(serializer), - RbxValue::Vector3int16 { value } => value.serialize(serializer), - _ => concrete.serialize(serializer), - }, - } -} - -/// A wrapper around serialize_unresolved_minimal that handles the HashMap case. -fn serialize_unresolved_map( - value: &HashMap, - serializer: S, -) -> Result -where - S: Serializer, -{ - use serde::ser::SerializeMap; - - #[derive(Serialize)] - struct Minimal<'a>( - #[serde(serialize_with = "serialize_unresolved_minimal")] &'a UnresolvedRbxValue, - ); - - let mut map = serializer.serialize_map(Some(value.len()))?; - for (k, v) in value { - map.serialize_key(k)?; - map.serialize_value(&Minimal(v))?; - } - map.end() -} - -/// Similar to SourceProject, the structure of nodes in the project tree is -/// slightly different on-disk than how we want to handle them in the rest of -/// Rojo. -#[derive(Debug, Clone, Serialize, Deserialize)] -struct SourceProjectNode { - #[serde(rename = "$className", skip_serializing_if = "Option::is_none")] - class_name: Option, - - #[serde( - rename = "$properties", - default = "HashMap::new", - skip_serializing_if = "HashMap::is_empty", - serialize_with = "serialize_unresolved_map" - )] - properties: HashMap, - - #[serde( - rename = "$ignoreUnknownInstances", - skip_serializing_if = "Option::is_none" - )] - ignore_unknown_instances: Option, - - #[serde(rename = "$path", skip_serializing_if = "Option::is_none")] - path: Option, - - #[serde(flatten)] - children: BTreeMap, -} - -impl SourceProjectNode { - /// Consumes the SourceProjectNode and turns it into a ProjectNode. - pub fn into_project_node(self, project_file_location: &Path) -> ProjectNode { - let children = self - .children - .iter() - .map(|(key, value)| { - ( - key.clone(), - value.clone().into_project_node(project_file_location), - ) - }) - .collect(); - - // Make sure that paths are absolute, transforming them by adding the - // project folder if they're not already absolute. - let path = self.path.as_ref().map(|source_path| { - if Path::new(source_path).is_absolute() { - PathBuf::from(source_path) - } else { - let project_folder_location = project_file_location.parent().unwrap(); - project_folder_location.join(source_path) - } - }); - - ProjectNode { - class_name: self.class_name, - properties: self.properties, - ignore_unknown_instances: self.ignore_unknown_instances, - path, - children, - } - } -} - -#[derive(Debug, Fail)] -pub enum ProjectLoadError { - NotFound, - - Io { - #[fail(cause)] - inner: io::Error, - path: PathBuf, - }, +#[derive(Debug, Snafu)] +enum Error { + /// A general IO error occurred. + Io { source: io::Error, path: PathBuf }, + /// An error with JSON parsing occurred. Json { - #[fail(cause)] - inner: serde_json::Error, + source: serde_json::Error, path: PathBuf, }, } -impl fmt::Display for ProjectLoadError { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - use self::ProjectLoadError::*; - - match self { - NotFound => write!(formatter, "Project file not found"), - Io { inner, path } => { - write!(formatter, "I/O error: {} in path {}", inner, path.display()) - } - Json { inner, path } => write!( - formatter, - "JSON error: {} in path {}", - inner, - path.display() - ), - } - } -} - -/// Error returned by Project::init_place and Project::init_model -#[derive(Debug, Fail)] -pub enum ProjectInitError { - AlreadyExists(PathBuf), - IoError(#[fail(cause)] io::Error), - SaveError(#[fail(cause)] ProjectSaveError), - JsonError(#[fail(cause)] serde_json::Error), -} - -impl fmt::Display for ProjectInitError { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - match self { - ProjectInitError::AlreadyExists(path) => { - write!(output, "Path {} already exists", path.display()) - } - ProjectInitError::IoError(inner) => write!(output, "IO error: {}", inner), - ProjectInitError::SaveError(inner) => write!(output, "{}", inner), - ProjectInitError::JsonError(inner) => write!(output, "{}", inner), - } - } -} - -/// Error returned by Project::save -#[derive(Debug, Fail)] -pub enum ProjectSaveError { - #[fail(display = "JSON error: {}", _0)] - JsonError(#[fail(cause)] serde_json::Error), - - #[fail(display = "IO error: {}", _0)] - IoError(#[fail(cause)] io::Error), -} - -#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] -pub struct ProjectNode { - pub class_name: Option, - pub children: BTreeMap, - pub properties: HashMap, - pub ignore_unknown_instances: Option, - - #[serde(serialize_with = "crate::path_serializer::serialize_option_absolute")] - pub path: Option, -} - -impl ProjectNode { - fn validate_reserved_names(&self) { - for (name, child) in &self.children { - if name.starts_with('$') { - warn!( - "Keys starting with '$' are reserved by Rojo to ensure forward compatibility." - ); - warn!( - "This project uses the key '{}', which should be renamed.", - name - ); - } - - child.validate_reserved_names(); - } - } - - fn to_source_node(&self, project_file_location: &Path) -> SourceProjectNode { - let children = self - .children - .iter() - .map(|(key, value)| (key.clone(), value.to_source_node(project_file_location))) - .collect(); - - // If paths are relative to the project file, transform them to look - // Unixy and write relative paths instead. - // - // This isn't perfect, since it means that paths like .. will stay as - // absolute paths and make projects non-portable. Fixing this probably - // means keeping the paths relative in the project format and making - // everywhere else in Rojo do the resolution locally. - let path = self.path.as_ref().map(|path| { - let project_folder_location = project_file_location.parent().unwrap(); - - match path.strip_prefix(project_folder_location) { - Ok(stripped) => stripped.to_str().unwrap().replace("\\", "/"), - Err(_) => format!("{}", path.display()), - } - }); - - SourceProjectNode { - class_name: self.class_name.clone(), - properties: self.properties.clone(), - ignore_unknown_instances: self.ignore_unknown_instances, - children, - path, - } - } -} - #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(deny_unknown_fields, rename_all = "camelCase")] pub struct Project { + /// The name of the top-level instance described by the project. pub name: String, + + /// The tree of instances described by this project. Projects always + /// describe at least one instance. pub tree: ProjectNode, + + /// If specified, sets the default port that `rojo serve` should use when + /// using this project for live sync. + #[serde(skip_serializing_if = "Option::is_none")] pub serve_port: Option, + + /// If specified, contains the set of place IDs that this project is + /// compatible with when doing live sync. + /// + /// This setting is intended to help prevent syncing a Rojo project into the + /// wrong Roblox place. + #[serde(skip_serializing_if = "Option::is_none")] pub serve_place_ids: Option>, - pub plugins: Vec, + + /// The path to the file that this project came from. Relative paths in the + /// project should be considered relative to the parent of this field, also + /// given by `Project::folder_location`. + #[serde(skip)] pub file_location: PathBuf, } impl Project { + /// Tells whether the given path describes a Rojo project. pub fn is_project_file(path: &Path) -> bool { path.file_name() .and_then(|name| name.to_str()) @@ -341,97 +65,6 @@ impl Project { .unwrap_or(false) } - pub fn init_place(project_fuzzy_path: &Path) -> Result { - let project_path = Project::pick_path_for_init(project_fuzzy_path)?; - - let project_name = if project_fuzzy_path == project_path { - project_fuzzy_path - .parent() - .expect("Path did not have a parent directory") - .file_name() - .expect("Path did not have a file name") - .to_str() - .expect("Path had invalid Unicode") - } else { - project_fuzzy_path - .file_name() - .expect("Path did not have a file name") - .to_str() - .expect("Path had invalid Unicode") - }; - - let mut project = Project::load_from_slice(DEFAULT_PLACE.as_bytes(), &project_path) - .map_err(ProjectInitError::JsonError)?; - - project.name = project_name.to_owned(); - - project.save().map_err(ProjectInitError::SaveError)?; - - Ok(project_path) - } - - pub fn init_model(project_fuzzy_path: &Path) -> Result { - let project_path = Project::pick_path_for_init(project_fuzzy_path)?; - - let project_name = if project_fuzzy_path == project_path { - project_fuzzy_path - .parent() - .expect("Path did not have a parent directory") - .file_name() - .expect("Path did not have a file name") - .to_str() - .expect("Path had invalid Unicode") - } else { - project_fuzzy_path - .file_name() - .expect("Path did not have a file name") - .to_str() - .expect("Path had invalid Unicode") - }; - - let project_folder_path = project_path - .parent() - .expect("Path did not have a parent directory"); - - let tree = ProjectNode { - path: Some(project_folder_path.join("src")), - ..Default::default() - }; - - let project = Project { - name: project_name.to_string(), - tree, - serve_port: None, - serve_place_ids: None, - plugins: Vec::new(), - file_location: project_path.clone(), - }; - - project.save().map_err(ProjectInitError::SaveError)?; - - Ok(project_path) - } - - fn pick_path_for_init(project_fuzzy_path: &Path) -> Result { - let is_exact = project_fuzzy_path.extension().is_some(); - - let project_path = if is_exact { - project_fuzzy_path.to_path_buf() - } else { - project_fuzzy_path.join(PROJECT_FILENAME) - }; - - match fs::metadata(&project_path) { - Err(error) => match error.kind() { - io::ErrorKind::NotFound => {} - _ => return Err(ProjectInitError::IoError(error)), - }, - Ok(_) => return Err(ProjectInitError::AlreadyExists(project_path)), - } - - Ok(project_path) - } - /// Attempt to locate a project represented by the given path. /// /// This will find a project if the path refers to a `.project.json` file, @@ -464,51 +97,40 @@ impl Project { pub fn load_from_slice( contents: &[u8], project_file_location: &Path, - ) -> Result { - let parsed: SourceProject = serde_json::from_slice(&contents)?; - - Ok(parsed.into_project(project_file_location)) + ) -> Result { + let mut project: Self = serde_json::from_slice(&contents)?; + project.file_location = project_file_location.to_path_buf(); + project.check_compatibility(); + Ok(project) } - pub fn load_fuzzy(fuzzy_project_location: &Path) -> Result { + pub fn load_fuzzy(fuzzy_project_location: &Path) -> Result, ProjectError> { if let Some(project_path) = Self::locate(fuzzy_project_location) { - Self::load_exact(&project_path) + let project = Self::load_exact(&project_path)?; + + Ok(Some(project)) } else { - Err(ProjectLoadError::NotFound) + Ok(None) } } - fn load_exact(project_file_location: &Path) -> Result { - let contents = - fs::read_to_string(project_file_location).map_err(|error| match error.kind() { - io::ErrorKind::NotFound => ProjectLoadError::NotFound, - _ => ProjectLoadError::Io { - inner: error, - path: project_file_location.to_path_buf(), - }, - })?; + fn load_exact(project_file_location: &Path) -> Result { + let contents = fs::read_to_string(project_file_location).context(Io { + path: project_file_location, + })?; - let parsed: SourceProject = - serde_json::from_str(&contents).map_err(|error| ProjectLoadError::Json { - inner: error, - path: project_file_location.to_path_buf(), - })?; - - let project = parsed.into_project(project_file_location); + let mut project: Project = serde_json::from_str(&contents).context(Json { + path: project_file_location, + })?; + project.file_location = project_file_location.to_path_buf(); project.check_compatibility(); Ok(project) } - pub fn save(&self) -> Result<(), ProjectSaveError> { - let source_project = self.to_source_project(); - let mut file = File::create(&self.file_location).map_err(ProjectSaveError::IoError)?; - - serde_json::to_writer_pretty(&mut file, &source_project) - .map_err(ProjectSaveError::JsonError)?; - - Ok(()) + pub fn save(&self) -> Result<(), ProjectError> { + unimplemented!() } /// Checks if there are any compatibility issues with this project file and @@ -520,27 +142,80 @@ impl Project { pub fn folder_location(&self) -> &Path { self.file_location.parent().unwrap() } +} - fn to_source_project(&self) -> SourceProject { - // TODO: Use path_serializer instead of transforming paths between - // String and PathBuf? - let plugins = self - .plugins - .iter() - .map(|path| { - path.strip_prefix(self.folder_location()) - .unwrap() - .display() - .to_string() - }) - .collect(); +/// Describes an instance and its descendants in a project. +#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] +pub struct ProjectNode { + /// If set, defines the ClassName of the described instance. + /// + /// `$className` MUST be set if `$path` is not set. + /// + /// `$className` CANNOT be set if `$path` is set and the instance described + /// by that path has a ClassName other than Folder. + #[serde(rename = "$className", skip_serializing_if = "Option::is_none")] + pub class_name: Option, - SourceProject { - name: self.name.clone(), - tree: self.tree.to_source_node(&self.file_location), - serve_port: self.serve_port, - plugins, - serve_place_ids: self.serve_place_ids.clone(), + /// Contains all of the children of the described instance. + #[serde(flatten)] + pub children: BTreeMap, + + /// The properties that will be assigned to the resulting instance. + /// + // TODO: Is this legal to set if $path is set? + #[serde( + rename = "$properties", + default, + skip_serializing_if = "HashMap::is_empty" + )] + pub properties: HashMap, + + /// Defines the behavior when Rojo encounters unknown instances in Roblox + /// Studio during live sync. `$ignoreUnknownInstances` should be considered + /// a large hammer and used with care. + /// + /// If set to `true`, those instances will be left alone. This may cause + /// issues when files that turn into instances are removed while Rojo is not + /// running. + /// + /// If set to `false`, Rojo will destroy any instances it does not + /// recognize. + /// + /// If unset, its default value depends on other settings: + /// - If `$path` is not set, defaults to `true` + /// - If `$path` is set, defaults to `false` + #[serde( + rename = "$ignoreUnknownInstances", + skip_serializing_if = "Option::is_none" + )] + pub ignore_unknown_instances: Option, + + /// Defines that this instance should come from the given file path. This + /// path can point to any file type supported by Rojo, including Lua files + /// (`.lua`), Roblox models (`.rbxm`, `.rbxmx`), and localization table + /// spreadsheets (`.csv`). + #[serde( + rename = "$path", + serialize_with = "crate::path_serializer::serialize_option_absolute", + skip_serializing_if = "Option::is_none" + )] + pub path: Option, +} + +impl ProjectNode { + fn validate_reserved_names(&self) { + for (name, child) in &self.children { + if name.starts_with('$') { + log::warn!( + "Keys starting with '$' are reserved by Rojo to ensure forward compatibility." + ); + log::warn!( + "This project uses the key '{}', which should be renamed.", + name + ); + } + + child.validate_reserved_names(); } } } diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index 7d956145..d0bba5bc 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -110,16 +110,24 @@ impl Default for InstanceContext { #[derive(Clone, PartialEq, Serialize, Deserialize)] pub enum InstigatingSource { Path(#[serde(serialize_with = "path_serializer::serialize_absolute")] PathBuf), - ProjectNode(String, ProjectNode), + ProjectNode( + #[serde(serialize_with = "path_serializer::serialize_absolute")] PathBuf, + String, + ProjectNode, + ), } impl fmt::Debug for InstigatingSource { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { match self { InstigatingSource::Path(path) => write!(formatter, "Path({})", path.display()), - InstigatingSource::ProjectNode(name, node) => { - write!(formatter, "ProjectNode({}: {:?}", name, node) - } + InstigatingSource::ProjectNode(path, name, node) => write!( + formatter, + "ProjectNode({}: {:?}) from path {}", + name, + node, + path.display() + ), } } } diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index caf2dc11..b4d99eba 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::HashMap}; +use std::{borrow::Cow, collections::HashMap, path::Path}; use rbx_reflection::try_resolve_value; @@ -47,8 +47,14 @@ impl SnapshotMiddleware for SnapshotProject { // Snapshotting a project should always return an instance, so this // unwrap is safe. - let mut snapshot = - snapshot_project_node(context, &project.name, &project.tree, vfs)?.unwrap(); + let mut snapshot = snapshot_project_node( + context, + project.folder_location(), + &project.name, + &project.tree, + vfs, + )? + .unwrap(); // Setting the instigating source to the project file path is a little // coarse. @@ -77,6 +83,7 @@ impl SnapshotMiddleware for SnapshotProject { pub fn snapshot_project_node( context: &InstanceContext, + project_folder: &Path, instance_name: &str, node: &ProjectNode, vfs: &Vfs, @@ -91,7 +98,15 @@ pub fn snapshot_project_node( let mut metadata = InstanceMetadata::default(); if let Some(path) = &node.path { - let entry = vfs.get(path)?; + // If the path specified in the project is relative, we assume it's + // relative to the folder that the project is in, project_folder. + let path = if path.is_relative() { + Cow::Owned(project_folder.join(path)) + } else { + Cow::Borrowed(path) + }; + + let entry = vfs.get(path.as_path())?; if let Some(snapshot) = snapshot_from_vfs(context, vfs, &entry)? { // If a class name was already specified, then it'll override the @@ -143,7 +158,9 @@ pub fn snapshot_project_node( .expect("$className or $path must be specified"); for (child_name, child_project_node) in &node.children { - if let Some(child) = snapshot_project_node(context, child_name, child_project_node, vfs)? { + if let Some(child) = + snapshot_project_node(context, project_folder, child_name, child_project_node, vfs)? + { children.push(child); } } @@ -170,6 +187,7 @@ pub fn snapshot_project_node( } metadata.instigating_source = Some(InstigatingSource::ProjectNode( + project_folder.to_path_buf(), instance_name.to_string(), node.clone(), )); diff --git a/src/snapshot_middleware/snapshots/test__project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_children.snap index d20102a8..ab659524 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_children.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_children.snap @@ -19,12 +19,9 @@ children: ignore_unknown_instances: true instigating_source: ProjectNode: + - /foo - Child - - class_name: Model - children: {} - properties: {} - ignore_unknown_instances: ~ - path: ~ + - $className: Model relevant_paths: [] context: {} name: Child diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap index ffe120ca..ba3fb273 100644 --- a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap +++ b/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap @@ -20,12 +20,9 @@ children: ignore_unknown_instances: true instigating_source: ProjectNode: + - /foo - SomeChild - - class_name: Model - children: {} - properties: {} - ignore_unknown_instances: ~ - path: ~ + - $className: Model relevant_paths: [] context: {} name: SomeChild diff --git a/src/snapshots/serve_session__change_file_in_project_after.snap b/src/snapshots/serve_session__change_file_in_project_after.snap index 757dc2c5..29afd767 100644 --- a/src/snapshots/serve_session__change_file_in_project_after.snap +++ b/src/snapshots/serve_session__change_file_in_project_after.snap @@ -25,12 +25,9 @@ children: ignore_unknown_instances: false instigating_source: ProjectNode: + - /foo - Child - - class_name: ~ - children: {} - properties: {} - ignore_unknown_instances: ~ - path: /foo/file.txt + - $path: file.txt relevant_paths: - /foo/file.txt - /foo/file.meta.json diff --git a/src/snapshots/serve_session__change_file_in_project_before.snap b/src/snapshots/serve_session__change_file_in_project_before.snap index 96d9cd93..9b20d87f 100644 --- a/src/snapshots/serve_session__change_file_in_project_before.snap +++ b/src/snapshots/serve_session__change_file_in_project_before.snap @@ -25,12 +25,9 @@ children: ignore_unknown_instances: false instigating_source: ProjectNode: + - /foo - Child - - class_name: ~ - children: {} - properties: {} - ignore_unknown_instances: ~ - path: /foo/file.txt + - $path: file.txt relevant_paths: - /foo/file.txt - /foo/file.meta.json From ce338a2a7262a2e9f61f6a68cbc6353d41acde14 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Dec 2019 13:40:52 -0800 Subject: [PATCH 0912/1504] Remove impl_from macro from public API --- src/impl_from.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/impl_from.rs b/src/impl_from.rs index ed1db996..a1b4137a 100644 --- a/src/impl_from.rs +++ b/src/impl_from.rs @@ -1,6 +1,5 @@ /// Implements 'From' for a list of variants, intended for use with error enums /// that are wrapping a number of errors from other methods. -#[macro_export] macro_rules! impl_from { ( $enum_name: ident { From 16c9a23d55b7e08304b9b0af0fe3f3df3b67e8f7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Dec 2019 13:58:46 -0800 Subject: [PATCH 0913/1504] Shuffle around Rojo's public API --- rojo-test/src/internable.rs | 2 +- rojo-test/src/serve_util.rs | 2 +- src/bin.rs | 13 +++++-------- src/{commands => cli}/build.rs | 0 src/{commands => cli}/init.rs | 0 src/{cli.rs => cli/mod.rs} | 10 +++++++++- src/{commands => cli}/serve.rs | 0 src/{commands => cli}/upload.rs | 0 src/commands/mod.rs | 9 --------- src/lib.rs | 12 ++++-------- src/project.rs | 5 ++++- 11 files changed, 24 insertions(+), 29 deletions(-) rename src/{commands => cli}/build.rs (100%) rename src/{commands => cli}/init.rs (100%) rename src/{cli.rs => cli/mod.rs} (97%) rename src/{commands => cli}/serve.rs (100%) rename src/{commands => cli}/upload.rs (100%) delete mode 100644 src/commands/mod.rs diff --git a/rojo-test/src/internable.rs b/rojo-test/src/internable.rs index 40abbdda..70b93481 100644 --- a/rojo-test/src/internable.rs +++ b/rojo-test/src/internable.rs @@ -3,7 +3,7 @@ use std::collections::HashMap; use rbx_dom_weak::RbxId; use serde::Serialize; -use librojo::web_interface::{Instance, InstanceUpdate, ReadResponse, SubscribeResponse}; +use librojo::web_api::{Instance, InstanceUpdate, ReadResponse, SubscribeResponse}; use rojo_insta_ext::RedactionMap; /// A convenience method to store all of the redactable data from a piece of diff --git a/rojo-test/src/serve_util.rs b/rojo-test/src/serve_util.rs index 8ea23800..d31a032d 100644 --- a/rojo-test/src/serve_util.rs +++ b/rojo-test/src/serve_util.rs @@ -11,7 +11,7 @@ use rbx_dom_weak::RbxId; use tempfile::{tempdir, TempDir}; -use librojo::web_interface::{ReadResponse, ServerInfoResponse, SubscribeResponse}; +use librojo::web_api::{ReadResponse, ServerInfoResponse, SubscribeResponse}; use rojo_insta_ext::RedactionMap; use crate::util::{ diff --git a/src/bin.rs b/src/bin.rs index 0616517c..aba23d30 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -4,10 +4,7 @@ use failure::Error; use log::error; use structopt::StructOpt; -use librojo::{ - cli::{Options, Subcommand}, - commands, -}; +use librojo::cli::{self, Options, Subcommand}; fn main() { let options = Options::from_args(); @@ -50,10 +47,10 @@ fn main() { fn run(subcommand: Subcommand) -> Result<(), Error> { match subcommand { - Subcommand::Init(init_options) => commands::init(init_options)?, - Subcommand::Serve(serve_options) => commands::serve(serve_options)?, - Subcommand::Build(build_options) => commands::build(build_options)?, - Subcommand::Upload(upload_options) => commands::upload(upload_options)?, + Subcommand::Init(init_options) => cli::init(init_options)?, + Subcommand::Serve(serve_options) => cli::serve(serve_options)?, + Subcommand::Build(build_options) => cli::build(build_options)?, + Subcommand::Upload(upload_options) => cli::upload(upload_options)?, } Ok(()) diff --git a/src/commands/build.rs b/src/cli/build.rs similarity index 100% rename from src/commands/build.rs rename to src/cli/build.rs diff --git a/src/commands/init.rs b/src/cli/init.rs similarity index 100% rename from src/commands/init.rs rename to src/cli/init.rs diff --git a/src/cli.rs b/src/cli/mod.rs similarity index 97% rename from src/cli.rs rename to src/cli/mod.rs index 4f721b49..a2cd56e3 100644 --- a/src/cli.rs +++ b/src/cli/mod.rs @@ -1,11 +1,19 @@ //! Defines Rojo's CLI through structopt types. -#![deny(missing_docs)] +mod build; +mod init; +mod serve; +mod upload; use std::{env, error::Error, fmt, path::PathBuf, str::FromStr}; use structopt::StructOpt; +pub use self::build::*; +pub use self::init::*; +pub use self::serve::*; +pub use self::upload::*; + /// Trick used with structopt to get the initial working directory of the /// process and store it for use in default values. fn working_dir() -> &'static str { diff --git a/src/commands/serve.rs b/src/cli/serve.rs similarity index 100% rename from src/commands/serve.rs rename to src/cli/serve.rs diff --git a/src/commands/upload.rs b/src/cli/upload.rs similarity index 100% rename from src/commands/upload.rs rename to src/cli/upload.rs diff --git a/src/commands/mod.rs b/src/commands/mod.rs deleted file mode 100644 index b4b53557..00000000 --- a/src/commands/mod.rs +++ /dev/null @@ -1,9 +0,0 @@ -mod build; -mod init; -mod serve; -mod upload; - -pub use self::build::*; -pub use self::init::*; -pub use self::serve::*; -pub use self::upload::*; diff --git a/src/lib.rs b/src/lib.rs index 6e4f8e42..4f74156d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -6,12 +6,6 @@ mod impl_from; pub mod cli; -pub mod commands; - -// This module is only public for testing right now, and won't be -// part of the first version of the Rojo API. -#[doc(hidden)] -pub mod project; #[cfg(test)] mod tree_view; @@ -23,6 +17,7 @@ mod message_queue; mod multimap; mod path_map; mod path_serializer; +mod project; mod serve_session; mod session_id; mod snapshot; @@ -30,5 +25,6 @@ mod snapshot_middleware; mod vfs; mod web; -pub use crate::session_id::SessionId; -pub use crate::web::interface as web_interface; +pub use project::*; +pub use session_id::SessionId; +pub use web::interface as web_api; diff --git a/src/project.rs b/src/project.rs index 3ba7ed7e..9bac403f 100644 --- a/src/project.rs +++ b/src/project.rs @@ -8,7 +8,7 @@ use rbx_dom_weak::UnresolvedRbxValue; use serde::{Deserialize, Serialize}; use snafu::{ResultExt, Snafu}; -pub static PROJECT_FILENAME: &str = "default.project.json"; +static PROJECT_FILENAME: &str = "default.project.json"; /// Error type returned by any function that handles projects. #[derive(Debug, Snafu)] @@ -26,6 +26,9 @@ enum Error { }, } +/// Contains all of the configuration for a Rojo-managed project. +/// +/// Project files are stored in `.project.json` files. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] #[serde(deny_unknown_fields, rename_all = "camelCase")] pub struct Project { From 41396367acc8e52b0354cf2ebf45ccd5708c9cfc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Dec 2019 13:59:59 -0800 Subject: [PATCH 0914/1504] Tell Cargo to use Rojo's README.md --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index e501d3eb..417f0c30 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,6 +5,7 @@ authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" repository = "https://github.com/rojo-rbx/rojo" +readme = "README.md" edition = "2018" exclude = [ From 1b9e90e786f8b754bdd1ad62016d0567fd5d848a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Dec 2019 15:44:46 -0800 Subject: [PATCH 0915/1504] Port from Failure to Snafu (#281) * Failure -> Snafu for build command * Port skeletal remains of init to snafu * failure -> snafu for serve * failure -> snafu for upload, remove impl_from macro * failure -> custom error in vfs * Bye bye, failure * Fix Rust 1.36 build regression --- Cargo.lock | 1 - Cargo.toml | 1 - src/bin.rs | 5 ++-- src/cli/build.rs | 65 +++++++++++++++++++++++++++-------------------- src/cli/init.rs | 22 ++++++++-------- src/cli/serve.rs | 19 +++++++------- src/cli/upload.rs | 45 ++++++++++++++++++-------------- src/impl_from.rs | 17 ------------- src/lib.rs | 3 --- src/vfs/error.rs | 25 ++++++++++-------- 10 files changed, 99 insertions(+), 104 deletions(-) delete mode 100644 src/impl_from.rs diff --git a/Cargo.lock b/Cargo.lock index e2939241..bb9bdff5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1615,7 +1615,6 @@ dependencies = [ "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 417f0c30..70599768 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,6 @@ harness = false crossbeam-channel = "0.3.9" csv = "1.0" env_logger = "0.6" -failure = "0.1.3" futures = "0.1" humantime = "1.3.0" hyper = "0.12" diff --git a/src/bin.rs b/src/bin.rs index aba23d30..bf371721 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -1,6 +1,5 @@ -use std::{panic, process}; +use std::{error::Error, panic, process}; -use failure::Error; use log::error; use structopt::StructOpt; @@ -45,7 +44,7 @@ fn main() { } } -fn run(subcommand: Subcommand) -> Result<(), Error> { +fn run(subcommand: Subcommand) -> Result<(), Box> { match subcommand { Subcommand::Init(init_options) => cli::init(init_options)?, Subcommand::Serve(serve_options) => cli::serve(serve_options)?, diff --git a/src/cli/build.rs b/src/cli/build.rs index 1e3a03a5..d845e970 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -3,13 +3,13 @@ use std::{ io::{self, BufWriter, Write}, }; -use failure::Fail; +use snafu::{ResultExt, Snafu}; use crate::{ cli::BuildCommand, common_setup, project::ProjectError, - vfs::{FsError, RealFetcher, Vfs, WatchMode}, + vfs::{RealFetcher, Vfs, WatchMode}, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -32,41 +32,46 @@ fn detect_output_kind(options: &BuildCommand) -> Option { } } -#[derive(Debug, Fail)] -pub enum BuildError { - #[fail(display = "Could not detect what kind of file to create")] +#[derive(Debug, Snafu)] +pub struct BuildError(Error); + +#[derive(Debug, Snafu)] +enum Error { + #[snafu(display("Could not detect what kind of file to create"))] UnknownOutputKind, - #[fail(display = "IO error: {}", _0)] - IoError(#[fail(cause)] io::Error), + #[snafu(display("{}", source))] + Io { source: io::Error }, - #[fail(display = "XML model error: {}", _0)] - XmlModelEncodeError(#[fail(cause)] rbx_xml::EncodeError), + #[snafu(display("{}", source))] + XmlModelEncode { source: rbx_xml::EncodeError }, - #[fail(display = "Binary model error: {:?}", _0)] - BinaryModelEncodeError(rbx_binary::EncodeError), + #[snafu(display("Binary model error: {:?}", source))] + BinaryModelEncode { + #[snafu(source(false))] + source: rbx_binary::EncodeError, + }, - #[fail(display = "{}", _0)] - ProjectError(#[fail(cause)] ProjectError), - - #[fail(display = "{}", _0)] - FsError(#[fail(cause)] FsError), + #[snafu(display("{}", source))] + Project { source: ProjectError }, } -impl_from!(BuildError { - io::Error => IoError, - rbx_xml::EncodeError => XmlModelEncodeError, - rbx_binary::EncodeError => BinaryModelEncodeError, - ProjectError => ProjectError, - FsError => FsError, -}); +impl From for Error { + fn from(source: rbx_binary::EncodeError) -> Self { + Error::BinaryModelEncode { source } + } +} fn xml_encode_config() -> rbx_xml::EncodeOptions { rbx_xml::EncodeOptions::new().property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown) } pub fn build(options: BuildCommand) -> Result<(), BuildError> { - let output_kind = detect_output_kind(&options).ok_or(BuildError::UnknownOutputKind)?; + Ok(build_inner(options)?) +} + +fn build_inner(options: BuildCommand) -> Result<(), Error> { + let output_kind = detect_output_kind(&options).ok_or(Error::UnknownOutputKind)?; log::debug!("Hoping to generate file of type {:?}", output_kind); @@ -77,14 +82,17 @@ pub fn build(options: BuildCommand) -> Result<(), BuildError> { let root_id = tree.get_root_id(); log::trace!("Opening output file for write"); - let mut file = BufWriter::new(File::create(&options.output)?); + + let file = File::create(&options.output).context(Io)?; + let mut file = BufWriter::new(file); match output_kind { OutputKind::Rbxmx => { // Model files include the root instance of the tree and all its // descendants. - rbx_xml::to_writer(&mut file, tree.inner(), &[root_id], xml_encode_config())?; + rbx_xml::to_writer(&mut file, tree.inner(), &[root_id], xml_encode_config()) + .context(XmlModelEncode)?; } OutputKind::Rbxlx => { // Place files don't contain an entry for the DataModel, but our @@ -93,7 +101,8 @@ pub fn build(options: BuildCommand) -> Result<(), BuildError> { let root_instance = tree.get_instance(root_id).unwrap(); let top_level_ids = root_instance.children(); - rbx_xml::to_writer(&mut file, tree.inner(), top_level_ids, xml_encode_config())?; + rbx_xml::to_writer(&mut file, tree.inner(), top_level_ids, xml_encode_config()) + .context(XmlModelEncode)?; } OutputKind::Rbxm => { rbx_binary::encode(tree.inner(), &[root_id], &mut file)?; @@ -110,7 +119,7 @@ pub fn build(options: BuildCommand) -> Result<(), BuildError> { } } - file.flush()?; + file.flush().context(Io)?; log::trace!("Done!"); diff --git a/src/cli/init.rs b/src/cli/init.rs index 2ea6b5e3..c27360b1 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -1,17 +1,17 @@ -use failure::Fail; +use snafu::Snafu; -use crate::{cli::InitCommand, project::ProjectError}; +use crate::cli::InitCommand; -#[derive(Debug, Fail)] -pub enum InitError { - #[fail(display = "Project init error: {}", _0)] - ProjectError(#[fail(cause)] ProjectError), +#[derive(Debug, Snafu)] +pub struct InitError(Error); + +#[derive(Debug, Snafu)] +enum Error {} + +pub fn init(options: InitCommand) -> Result<(), InitError> { + Ok(init_inner(options)?) } -impl_from!(InitError { - ProjectError => ProjectError, -}); - -pub fn init(_options: InitCommand) -> Result<(), InitError> { +fn init_inner(_options: InitCommand) -> Result<(), Error> { unimplemented!("init command"); } diff --git a/src/cli/serve.rs b/src/cli/serve.rs index bc47f981..11e68baa 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -3,12 +3,11 @@ use std::{ sync::Arc, }; -use failure::Fail; +use snafu::Snafu; use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; use crate::{ cli::ServeCommand, - project::ProjectError, serve_session::ServeSession, vfs::{RealFetcher, Vfs, WatchMode}, web::LiveServer, @@ -16,17 +15,17 @@ use crate::{ const DEFAULT_PORT: u16 = 34872; -#[derive(Debug, Fail)] -pub enum ServeError { - #[fail(display = "Couldn't load project: {}", _0)] - ProjectError(#[fail(cause)] ProjectError), -} +#[derive(Debug, Snafu)] +pub struct ServeError(Error); -impl_from!(ServeError { - ProjectError => ProjectError, -}); +#[derive(Debug, Snafu)] +enum Error {} pub fn serve(options: ServeCommand) -> Result<(), ServeError> { + Ok(serve_inner(options)?) +} + +fn serve_inner(options: ServeCommand) -> Result<(), Error> { let vfs = Vfs::new(RealFetcher::new(WatchMode::Enabled)); let session = Arc::new(ServeSession::new(vfs, &options.project)); diff --git a/src/cli/upload.rs b/src/cli/upload.rs index df6f8429..4e14708a 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -1,5 +1,5 @@ -use failure::Fail; use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}; +use snafu::{ResultExt, Snafu}; use crate::{ auth_cookie::get_auth_cookie, @@ -8,31 +8,35 @@ use crate::{ vfs::{RealFetcher, Vfs, WatchMode}, }; -#[derive(Debug, Fail)] -pub enum UploadError { - #[fail(display = "Rojo could not find your Roblox auth cookie. Please pass one via --cookie.")] +#[derive(Debug, Snafu)] +pub struct UploadError(Error); + +#[derive(Debug, Snafu)] +enum Error { + #[snafu(display( + "Rojo could not find your Roblox auth cookie. Please pass one via --cookie.", + ))] NeedAuthCookie, - #[fail(display = "XML model file encode error: {}", _0)] - XmlModelEncode(#[fail(cause)] rbx_xml::EncodeError), + #[snafu(display("XML model file encode error: {}", source))] + XmlModel { source: rbx_xml::EncodeError }, - #[fail(display = "HTTP error: {}", _0)] - Http(#[fail(cause)] reqwest::Error), + #[snafu(display("HTTP error: {}", source))] + Http { source: reqwest::Error }, - #[fail(display = "Roblox API error: {}", _0)] - RobloxApi(String), + #[snafu(display("Roblox API error: {}", body))] + RobloxApi { body: String }, } -impl_from!(UploadError { - rbx_xml::EncodeError => XmlModelEncode, - reqwest::Error => Http, -}); - pub fn upload(options: UploadCommand) -> Result<(), UploadError> { + Ok(upload_inner(options)?) +} + +fn upload_inner(options: UploadCommand) -> Result<(), Error> { let cookie = options .cookie .or_else(get_auth_cookie) - .ok_or(UploadError::NeedAuthCookie)?; + .ok_or(Error::NeedAuthCookie)?; log::trace!("Constructing in-memory filesystem"); let vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); @@ -45,7 +49,7 @@ pub fn upload(options: UploadCommand) -> Result<(), UploadError> { log::trace!("Encoding XML model"); let config = rbx_xml::EncodeOptions::new() .property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown); - rbx_xml::to_writer(&mut buffer, tree.inner(), &[root_id], config)?; + rbx_xml::to_writer(&mut buffer, tree.inner(), &[root_id], config).context(XmlModel)?; let url = format!( "https://data.roblox.com/Data/Upload.ashx?assetid={}", @@ -62,10 +66,13 @@ pub fn upload(options: UploadCommand) -> Result<(), UploadError> { .header(CONTENT_TYPE, "application/xml") .header(ACCEPT, "application/json") .body(buffer) - .send()?; + .send() + .context(Http)?; if !response.status().is_success() { - return Err(UploadError::RobloxApi(response.text()?)); + return Err(Error::RobloxApi { + body: response.text().context(Http)?, + }); } Ok(()) diff --git a/src/impl_from.rs b/src/impl_from.rs deleted file mode 100644 index a1b4137a..00000000 --- a/src/impl_from.rs +++ /dev/null @@ -1,17 +0,0 @@ -/// Implements 'From' for a list of variants, intended for use with error enums -/// that are wrapping a number of errors from other methods. -macro_rules! impl_from { - ( - $enum_name: ident { - $($error_type: ty => $variant_name: ident),* $(,)* - } - ) => { - $( - impl From<$error_type> for $enum_name { - fn from(error: $error_type) -> $enum_name { - $enum_name::$variant_name(error) - } - } - )* - } -} diff --git a/src/lib.rs b/src/lib.rs index 4f74156d..a7ff62a0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,9 +2,6 @@ // Rojo's web UI currently. #![recursion_limit = "1024"] -#[macro_use] -mod impl_from; - pub mod cli; #[cfg(test)] diff --git a/src/vfs/error.rs b/src/vfs/error.rs index 989c64e2..54d4efb1 100644 --- a/src/vfs/error.rs +++ b/src/vfs/error.rs @@ -1,6 +1,4 @@ -use std::{fmt, io, path::PathBuf}; - -use failure::Fail; +use std::{error::Error, fmt, io, path::PathBuf}; pub type FsResult = Result; pub use io::ErrorKind as FsErrorKind; @@ -21,32 +19,37 @@ impl FsResultExt for Result { /// A wrapper around io::Error that also attaches the path associated with the /// error. -#[derive(Debug, Fail)] +#[derive(Debug)] pub struct FsError { - #[fail(cause)] - inner: io::Error, + source: io::Error, path: PathBuf, } impl FsError { - pub fn new>(inner: io::Error, path: P) -> FsError { + pub fn new>(source: io::Error, path: P) -> FsError { FsError { - inner, + source, path: path.into(), } } pub fn kind(&self) -> FsErrorKind { - self.inner.kind() + self.source.kind() } pub fn into_raw(self) -> (io::Error, PathBuf) { - (self.inner, self.path) + (self.source, self.path) + } +} + +impl Error for FsError { + fn source(&self) -> Option<&(dyn Error + 'static)> { + Some(&self.source) } } impl fmt::Display for FsError { fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - write!(output, "{}: {}", self.path.display(), self.inner) + write!(output, "{}: {}", self.path.display(), self.source) } } From 859c7bea8af875765948c130372d35547e745e82 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Dec 2019 15:52:47 -0800 Subject: [PATCH 0916/1504] Update most dependencies --- Cargo.lock | 162 +++++++++++++++++++++++++++++++++-------------------- Cargo.toml | 35 ++++++------ src/bin.rs | 2 +- 3 files changed, 117 insertions(+), 82 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb9bdff5..86261608 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -63,6 +63,11 @@ dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "base64" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "bitflags" version = "1.2.1" @@ -95,7 +100,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -138,8 +143,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -234,7 +239,7 @@ dependencies = [ "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "publicsuffix 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -280,8 +285,8 @@ dependencies = [ "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -298,10 +303,10 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.3.9" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -370,7 +375,7 @@ dependencies = [ "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -425,7 +430,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "encoding_rs" -version = "0.8.20" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -443,6 +448,18 @@ dependencies = [ "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "env_logger" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "error-chain" version = "0.12.1" @@ -617,7 +634,7 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", @@ -759,7 +776,23 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "insta" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -872,7 +905,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "md5" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1021,7 +1054,7 @@ name = "num_cpus" version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1450,27 +1483,29 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)", + "snafu 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_dom_weak" -version = "1.10.0" +version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "md5 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1480,18 +1515,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rbx_xml" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1550,7 +1585,7 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.21 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1560,7 +1595,7 @@ dependencies = [ "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1598,10 +1633,11 @@ dependencies = [ [[package]] name = "rlua" -version = "0.16.3" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1612,13 +1648,13 @@ name = "rojo" version = "0.6.0-dev" dependencies = [ "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "insta 0.12.0 (git+https://github.com/mitsuhiko/insta)", + "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1626,16 +1662,16 @@ dependencies = [ "notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_binary 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_xml 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rlua 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "rojo-insta-ext 0.1.0", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "snafu 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1643,7 +1679,7 @@ dependencies = [ "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", + "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1652,7 +1688,7 @@ dependencies = [ name = "rojo-insta-ext" version = "0.1.0" dependencies = [ - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1664,11 +1700,11 @@ dependencies = [ "insta 0.12.0 (git+https://github.com/mitsuhiko/insta)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", "rojo 0.6.0-dev", "rojo-insta-ext 0.1.0", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1740,7 +1776,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1750,15 +1786,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "serde" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_derive" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1773,7 +1809,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1793,7 +1829,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1804,7 +1840,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2003,7 +2039,7 @@ name = "tinytemplate" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2279,7 +2315,6 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2288,7 +2323,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2421,6 +2456,7 @@ dependencies = [ "checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" "checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" +"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" @@ -2445,7 +2481,7 @@ dependencies = [ "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" "checksum criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "938703e165481c8d612ea3479ac8342e5615185db37765162e762ec3523e2fc6" "checksum criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eccdc6ce8bbe352ca89025bee672aa6d24f4eb8c53e3a8b5d1bc58011da072a2" -"checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa" +"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" "checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" "checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" "checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" @@ -2461,8 +2497,9 @@ dependencies = [ "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" -"checksum encoding_rs 0.8.20 (registry+https://github.com/rust-lang/crates.io-index)" = "87240518927716f79692c2ed85bfe6e98196d18c6401ec75355760233a7e12e9" +"checksum encoding_rs 0.8.21 (registry+https://github.com/rust-lang/crates.io-index)" = "f730a5068736d360795b76e8c53ef51d052a4090d281412da851f5fd6204f36d" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" "checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" "checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" "checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" @@ -2484,7 +2521,7 @@ dependencies = [ "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum hermit-abi 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "307c3c9f937f38e3534b1d6447ecf090cafcc9744e4a6360e8b037b2cf5af120" +"checksum hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" "checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" @@ -2498,6 +2535,7 @@ dependencies = [ "checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" "checksum insta 0.12.0 (git+https://github.com/mitsuhiko/insta)" = "" +"checksum insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d499dc062e841590a67230d853bce62d0abeb91304927871670b7c55c461349" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" @@ -2514,7 +2552,7 @@ dependencies = [ "checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" -"checksum md5 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e6bcd6433cff03a4bfc3d9834d504467db1f1cf6d0ea765d37d330249ed629d" +"checksum md5 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" "checksum mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "dd1d63acd1b78403cc0c325605908475dd9b9a3acbf65ed8bcab97e27014afcf" @@ -2576,10 +2614,10 @@ dependencies = [ "checksum rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e18c91676f670f6f0312764c759405f13afb98d5d73819840cf72a518487bff" "checksum rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43739f8831493b276363637423d3622d4bd6394ab6f0a9c4a552e208aeb7fddd" "checksum rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8bf17de6f23b05473c437eb958b9c850bfc8af0961fe17b4cc92d5a627b4791" -"checksum rbx_binary 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "81428c521a07a3feac9c31180a886e467eecf81b769987f70d51d567a09c321d" -"checksum rbx_dom_weak 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b7c983d7bfcf0811a164e33e99e2da456f38babb33c75e365b17aa1ee5fd2d" +"checksum rbx_binary 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b1c0c2b715bb763be1e27e5118e1f1ce0381f6c396a9cc8dd2c4b818cfa247d" +"checksum rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "978b65ce742f3cb38c0b64ca48601a5590e6be9a14d12025b9cba2fe553b78c4" "checksum rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c147f9006c1cfd3a1872d36e91d5fca88d4b94fafa5463f774a00f293b1277" -"checksum rbx_xml 0.11.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8b58063a6ccf8d27efa772ea816a99d1d411e2fdc47a141e26a493cd1c938ff1" +"checksum rbx_xml 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6431f38b84582ec4e4f40b525cdcc713d4a984dcc2e3eecd1a67ae4da1172fbd" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" "checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" @@ -2589,7 +2627,7 @@ dependencies = [ "checksum reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" "checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" -"checksum rlua 0.16.3 (registry+https://github.com/rust-lang/crates.io-index)" = "62fc0e980c94fe9ef795b1bb3874649c8c6e9bb67d3b90d48380ba24c69c23ea" +"checksum rlua 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25fa5b2c667bae0b6218361e96d365e414fe4a0fa80f476b9631aa2dea2c6881" "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" @@ -2600,8 +2638,8 @@ dependencies = [ "checksum security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "1217f97ab8e8904b57dd22eb61cde455fa7446a9c1cf43966066da047c1f3702" -"checksum serde_derive 1.0.103 (registry+https://github.com/rust-lang/crates.io-index)" = "a8c6faef9a2e64b0064f48570289b4bf8823b7581f1d6157c1b52152306651d0" +"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" +"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" "checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" "checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" diff --git a/Cargo.toml b/Cargo.toml index 70599768..41b0e456 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,31 +49,31 @@ name = "build" harness = false [dependencies] -crossbeam-channel = "0.3.9" -csv = "1.0" -env_logger = "0.6" -futures = "0.1" +crossbeam-channel = "0.4.0" +csv = "1.1.1" +env_logger = "0.7.1" +futures = "0.1.29" humantime = "1.3.0" -hyper = "0.12" +hyper = "0.12.35" jod-thread = "0.1.0" lazy_static = "1.4.0" -log = "0.4" +log = "0.4.8" maplit = "1.0.1" -notify = "4.0" -rbx_binary = "0.4.1" -rbx_dom_weak = "1.9.0" +notify = "4.0.14" +rbx_binary = "0.5.0" +rbx_dom_weak = "1.10.1" rbx_reflection = "3.3.408" -rbx_xml = "0.11.2" -regex = "1.0" +rbx_xml = "0.11.3" +regex = "1.3.1" reqwest = "0.9.20" ritz = "0.1.0" -rlua = "0.16.3" +rlua = "0.17.0" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" snafu = "0.6.0" -structopt = "0.3" +structopt = "0.3.5" termcolor = "1.0.5" -uuid = { version = "0.7", features = ["v4", "serde"] } +uuid = { version = "0.8.1", features = ["v4", "serde"] } [target.'cfg(windows)'.dependencies] winreg = "0.6.2" @@ -81,6 +81,8 @@ winreg = "0.6.2" [dev-dependencies] rojo-insta-ext = { path = "rojo-insta-ext" } +criterion = "0.3" +insta = { version = "0.12.0", features = ["redactions"] } lazy_static = "1.2" paste = "0.1" pretty_assertions = "0.6.1" @@ -88,8 +90,3 @@ serde_yaml = "0.8.9" tempfile = "3.0" tokio = "0.1.22" walkdir = "2.1" -criterion = "0.3" - -[dev-dependencies.insta] -git = "https://github.com/mitsuhiko/insta" -features = ["redactions"] diff --git a/src/bin.rs b/src/bin.rs index bf371721..1b745ded 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -19,7 +19,7 @@ fn main() { let log_env = env_logger::Env::default().default_filter_or(log_filter); env_logger::Builder::from_env(log_env) - .default_format_timestamp(false) + .format_timestamp(None) .init(); } From 1d900a6a3c42a51f5425d1ecd4831f778a51b9c6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Dec 2019 15:56:24 -0800 Subject: [PATCH 0917/1504] Update benchmarks to use new CLI API --- benches/build.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/benches/build.rs b/benches/build.rs index 5b3a918d..802f43a3 100644 --- a/benches/build.rs +++ b/benches/build.rs @@ -3,7 +3,7 @@ use std::path::Path; use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use tempfile::{tempdir, TempDir}; -use librojo::commands::{build, BuildOptions}; +use librojo::cli::{build, BuildCommand}; pub fn benchmark_small_place(c: &mut Criterion) { bench_build_place(c, "Small Place", "test-projects/benchmark_small_place") @@ -20,7 +20,7 @@ fn bench_build_place(c: &mut Criterion, name: &str, path: &str) { group.bench_function("build", |b| { b.iter_batched( || place_setup(path), - |(_dir, options)| build(&options).unwrap(), + |(_dir, options)| build(options).unwrap(), BatchSize::SmallInput, ) }); @@ -28,15 +28,14 @@ fn bench_build_place(c: &mut Criterion, name: &str, path: &str) { group.finish(); } -fn place_setup>(input_path: P) -> (TempDir, BuildOptions) { +fn place_setup>(input_path: P) -> (TempDir, BuildCommand) { let dir = tempdir().unwrap(); let input = input_path.as_ref().to_path_buf(); - let output_file = dir.path().join("output.rbxlx"); + let output = dir.path().join("output.rbxlx"); - let options = BuildOptions { - fuzzy_project_path: input, - output_file, - output_kind: None, + let options = BuildCommand { + project: input, + output, }; (dir, options) From e83437c19395caa3625482d8d74efca5ab21f885 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Dec 2019 17:38:31 -0800 Subject: [PATCH 0918/1504] Add debug formatter for instances --- plugin/fmt/init.lua | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/fmt/init.lua b/plugin/fmt/init.lua index 7e2db533..99c61c9f 100644 --- a/plugin/fmt/init.lua +++ b/plugin/fmt/init.lua @@ -82,6 +82,8 @@ local function debugImpl(buffer, value, extendedForm) defaultTableDebug(buffer, value) end end + elseif valueType == "Instance" then + buffer:writeRaw(value:GetFullName()) else buffer:writeRaw(tostring(value)) end From cfff08cdfdb9e60e2be9c76ca33dadd54e88aca4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Dec 2019 17:39:04 -0800 Subject: [PATCH 0919/1504] Add plugin half of script-only, existing-instance-only, two way sync --- plugin/src/ApiContext.lua | 18 +++++++++++++ plugin/src/DevSettings.lua | 12 +++++++++ plugin/src/Reconciler.lua | 18 ++++++++++++- plugin/src/ServeSession.lua | 50 +++++++++++++++++++++++++++++++++++-- 4 files changed, 95 insertions(+), 3 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 32cea89b..d1c2feed 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -1,4 +1,5 @@ local Http = require(script.Parent.Parent.Http) +local Log = require(script.Parent.Parent.Log) local Promise = require(script.Parent.Parent.Promise) local Config = require(script.Parent.Config) @@ -153,6 +154,23 @@ function ApiContext:read(ids) end) end +function ApiContext:write(patch) + local url = ("%s/write"):format(self.__baseUrl) + local body = Http.jsonEncode({ + sessionId = self.__sessionId, + patch = patch, + }) + + return Http.post(url, body) + :andThen(rejectFailedRequests) + :andThen(Http.Response.json) + :andThen(function(body) + Log.info("Write response: {:?}", body) + + return body + end) +end + function ApiContext:retrieveMessages() local url = ("%s/api/subscribe/%s"):format(self.__baseUrl, self.__messageCursor) diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua index f1458c00..182769da 100644 --- a/plugin/src/DevSettings.lua +++ b/plugin/src/DevSettings.lua @@ -25,6 +25,14 @@ local VALUES = { [Environment.Test] = true, }, }, + ExperimentalTwoWaySync = { + type = "BoolValue", + values = { + [Environment.User] = false, + [Environment.Dev] = false, + [Environment.Test] = false, + }, + }, } local CONTAINER_NAME = "RojoDevSettings" .. Config.codename @@ -132,6 +140,10 @@ function DevSettings:shouldTypecheck() return getValue("TypecheckingEnabled") end +function DevSettings:twoWaySyncEnabled() + return getValue("ExperimentalTwoWaySync") +end + function _G.ROJO_DEV_CREATE() DevSettings:createDevSettings() end diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 36c19037..6050a401 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -176,6 +176,23 @@ function Reconciler:applyPatch(patch) end end +--[[ + Transforms a value into one that can be sent over the network back to the + Rojo server. + + This operation can fail, and so it returns bool, value. +]] +function Reconciler:encodeApiValue(value) + if typeof(value) == "string" then + return true, { + Type = "String", + Value = value, + } + end + + return false +end + --[[ Transforms a value encoded by rbx_dom_weak on the server side into a value usable by Rojo's reconciler, potentially using RbxDom. @@ -302,7 +319,6 @@ function Reconciler:__hydrateInternal(apiInstances, id, instance, hydratePatch) local decodedValue = self:__decodeApiValue(virtualValue) if existingValue ~= decodedValue then - Log.warn("Diff! {:?} vs {:?}", existingValue, decodedValue) changedProperties[propertyName] = virtualValue end end diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 9f33814c..e6cdbb2f 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -2,6 +2,7 @@ local Log = require(script.Parent.Parent.Log) local Fmt = require(script.Parent.Parent.Fmt) local t = require(script.Parent.Parent.t) +local DevSettings = require(script.Parent.DevSettings) local InstanceMap = require(script.Parent.InstanceMap) local Reconciler = require(script.Parent.Reconciler) local strict = require(script.Parent.strict) @@ -47,10 +48,16 @@ local validateServeOptions = t.strictInterface({ function ServeSession.new(options) assert(validateServeOptions(options)) - local instanceMap = InstanceMap.new() + -- Declare self ahead of time to capture it in a closure + local self + local function onInstanceChanged(instance, propertyName) + self:__onInstanceChanged(instance, propertyName) + end + + local instanceMap = InstanceMap.new(onInstanceChanged) local reconciler = Reconciler.new(instanceMap) - local self = { + self = { __status = Status.NotStarted, __apiContext = options.apiContext, __reconciler = reconciler, @@ -101,6 +108,45 @@ function ServeSession:stop() self:__stopInternal() end +function ServeSession:__onInstanceChanged(instance, propertyName) + if not DevSettings:twoWaySyncEnabled() then + return + end + + local instanceId = self.__instanceMap.fromInstances[instance] + + if instanceId == nil then + Log.warn("Ignoring change for instance {:?} as it is unknown to Rojo", instance) + return + end + + local update = { + id = instanceId, + changedProperties = {}, + } + + if propertyName == "Name" then + update.changedName = instance.Name + else + local success, encoded = self.__reconciler:encodeApiValue(instance[propertyName]) + + if not success then + Log.warn("Could not sync back property {:?}.{}", instance, propertyName) + return + end + + update.changedProperties[propertyName] = encoded + end + + local patch = { + removed = {}, + added = {}, + updated = {update}, + } + + self.__apiContext:write(patch) +end + function ServeSession:__initialSync(rootInstanceId) return self.__apiContext:read({ rootInstanceId }) :andThen(function(readResponseBody) From dd592d1d6d4a863b5885d286af87b48300464e50 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Dec 2019 17:44:47 -0800 Subject: [PATCH 0920/1504] Break pathing everywhere (fix coming soon), fix verbosity argument --- src/cli/mod.rs | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index a2cd56e3..e97737f1 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -5,7 +5,7 @@ mod init; mod serve; mod upload; -use std::{env, error::Error, fmt, path::PathBuf, str::FromStr}; +use std::{error::Error, fmt, path::PathBuf, str::FromStr}; use structopt::StructOpt; @@ -14,24 +14,12 @@ pub use self::init::*; pub use self::serve::*; pub use self::upload::*; -/// Trick used with structopt to get the initial working directory of the -/// process and store it for use in default values. -fn working_dir() -> &'static str { - lazy_static::lazy_static! { - static ref INITIAL_WORKING_DIR: String = { - env::current_dir().unwrap().display().to_string() - }; - } - - &INITIAL_WORKING_DIR -} - /// Command line options that Rojo accepts, defined using the structopt crate. #[derive(Debug, StructOpt)] #[structopt(name = "Rojo", about, author)] pub struct Options { /// Sets verbosity level. Can be specified multiple times. - #[structopt(long = "verbose", short, parse(from_occurrences))] + #[structopt(long = "verbose", short, global(true), parse(from_occurrences))] pub verbosity: u8, /// Subcommand to run in this invocation. @@ -59,7 +47,7 @@ pub enum Subcommand { #[derive(Debug, StructOpt)] pub struct InitCommand { /// Path to the place to create the project. Defaults to the current directory. - #[structopt(default_value = &working_dir())] + #[structopt(default_value = "")] pub path: PathBuf, /// The kind of project to create, 'place' or 'model'. Defaults to place. @@ -114,7 +102,7 @@ impl fmt::Display for InitKindParseError { #[derive(Debug, StructOpt)] pub struct ServeCommand { /// Path to the project to serve. Defaults to the current directory. - #[structopt(default_value = &working_dir())] + #[structopt(default_value = "")] pub project: PathBuf, /// The port to listen on. Defaults to the project's preference, or 34872 if @@ -127,7 +115,7 @@ pub struct ServeCommand { #[derive(Debug, StructOpt)] pub struct BuildCommand { /// Path to the project to serve. Defaults to the current directory. - #[structopt(default_value = &working_dir())] + #[structopt(default_value = "")] pub project: PathBuf, /// Where to output the result. @@ -139,7 +127,7 @@ pub struct BuildCommand { #[derive(Debug, StructOpt)] pub struct UploadCommand { /// Path to the project to upload. Defaults to the current directory. - #[structopt(default_value = &working_dir())] + #[structopt(default_value = "")] pub project: PathBuf, /// The kind of asset to generate, 'place', or 'model'. Defaults to place. From f2584cf807572e424728c71316c395fd326bb994 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Dec 2019 17:52:16 -0800 Subject: [PATCH 0921/1504] Fix live sync. The refactor to use StructOpt instead of plain Clap had some absolute vs relative path issues that slipped through. This commit adds getters to each StructOpt struct that exposes an explicitly absolute version of each path value. --- src/cli/build.rs | 2 +- src/cli/mod.rs | 41 ++++++++++++++++++++++++++++++++++++++++- src/cli/serve.rs | 2 +- src/cli/upload.rs | 3 ++- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/cli/build.rs b/src/cli/build.rs index d845e970..fff73fa4 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -78,7 +78,7 @@ fn build_inner(options: BuildCommand) -> Result<(), Error> { log::trace!("Constructing in-memory filesystem"); let vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); - let (_maybe_project, tree) = common_setup::start(&options.project, &vfs); + let (_maybe_project, tree) = common_setup::start(&options.absolute_project(), &vfs); let root_id = tree.get_root_id(); log::trace!("Opening output file for write"); diff --git a/src/cli/mod.rs b/src/cli/mod.rs index e97737f1..20810002 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -5,7 +5,14 @@ mod init; mod serve; mod upload; -use std::{error::Error, fmt, path::PathBuf, str::FromStr}; +use std::{ + borrow::Cow, + env, + error::Error, + fmt, + path::{Path, PathBuf}, + str::FromStr, +}; use structopt::StructOpt; @@ -55,6 +62,12 @@ pub struct InitCommand { pub kind: InitKind, } +impl InitCommand { + pub fn absolute_path(&self) -> Cow<'_, Path> { + resolve_path(&self.path) + } +} + /// The templates we support for initializing a Rojo project. #[derive(Debug, Clone, Copy)] pub enum InitKind { @@ -111,6 +124,12 @@ pub struct ServeCommand { pub port: Option, } +impl ServeCommand { + pub fn absolute_project(&self) -> Cow<'_, Path> { + resolve_path(&self.project) + } +} + /// Build a Rojo project into a file. #[derive(Debug, StructOpt)] pub struct BuildCommand { @@ -123,6 +142,12 @@ pub struct BuildCommand { pub output: PathBuf, } +impl BuildCommand { + pub fn absolute_project(&self) -> Cow<'_, Path> { + resolve_path(&self.project) + } +} + /// Build and upload a Rojo project to Roblox.com. #[derive(Debug, StructOpt)] pub struct UploadCommand { @@ -143,6 +168,12 @@ pub struct UploadCommand { pub asset_id: u64, } +impl UploadCommand { + pub fn absolute_project(&self) -> Cow<'_, Path> { + resolve_path(&self.project) + } +} + /// The kind of asset to upload to the website. Affects what endpoints Rojo uses /// and changes how the asset is built. #[derive(Debug, Clone, Copy)] @@ -185,3 +216,11 @@ impl fmt::Display for UploadKindParseError { ) } } + +fn resolve_path(path: &Path) -> Cow<'_, Path> { + if path.is_absolute() { + Cow::Borrowed(path) + } else { + Cow::Owned(env::current_dir().unwrap().join(path)) + } +} diff --git a/src/cli/serve.rs b/src/cli/serve.rs index 11e68baa..789cb2f1 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -28,7 +28,7 @@ pub fn serve(options: ServeCommand) -> Result<(), ServeError> { fn serve_inner(options: ServeCommand) -> Result<(), Error> { let vfs = Vfs::new(RealFetcher::new(WatchMode::Enabled)); - let session = Arc::new(ServeSession::new(vfs, &options.project)); + let session = Arc::new(ServeSession::new(vfs, &options.absolute_project())); let port = options .port diff --git a/src/cli/upload.rs b/src/cli/upload.rs index 4e14708a..42dca981 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -35,13 +35,14 @@ pub fn upload(options: UploadCommand) -> Result<(), UploadError> { fn upload_inner(options: UploadCommand) -> Result<(), Error> { let cookie = options .cookie + .clone() .or_else(get_auth_cookie) .ok_or(Error::NeedAuthCookie)?; log::trace!("Constructing in-memory filesystem"); let vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); - let (_maybe_project, tree) = common_setup::start(&options.project, &vfs); + let (_maybe_project, tree) = common_setup::start(&options.absolute_project(), &vfs); let root_id = tree.get_root_id(); let mut buffer = Vec::new(); From 1968e1fdb737ae6df5cd743e91b9cf605079ae2e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Dec 2019 14:40:29 -0800 Subject: [PATCH 0922/1504] Fix bad formatting string in plugin HTTP module --- plugin/http/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/http/init.lua b/plugin/http/init.lua index ec7e2713..686130ef 100644 --- a/plugin/http/init.lua +++ b/plugin/http/init.lua @@ -20,7 +20,7 @@ local function performRequest(requestParams) Log.trace("HTTP {}({}) {}", requestParams.Method, requestId, requestParams.Url) if requestParams.Body ~= nil then - Log.trace(requestParams.Body) + Log.trace("{}", requestParams.Body) end return Promise.new(function(resolve, reject) From 57d5610a581e618107d71cc152af31204ba17f5b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Dec 2019 14:41:57 -0800 Subject: [PATCH 0923/1504] plugin: Improve HTTP error messages by using response body --- plugin/src/ApiContext.lua | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index d1c2feed..6e5b36e0 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -19,8 +19,9 @@ end local function rejectFailedRequests(response) if response.code >= 400 then - -- TODO: Nicer error types for responses, using response JSON if valid. - return Promise.reject(tostring(response.code)) + local message = string.format("HTTP %s:\n%s", tostring(response.code), response.body) + + return Promise.reject(message) end return response From 46d7bba87dfa0692bd232648c557dd059ff3bb71 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Dec 2019 14:46:34 -0800 Subject: [PATCH 0924/1504] Add .rbxl.lock and .rbxlx.lock files to gitignore --- .gitignore | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.gitignore b/.gitignore index a4ba062d..3b6e942e 100644 --- a/.gitignore +++ b/.gitignore @@ -10,5 +10,9 @@ /*.rbxl /*.rbxlx +# Roblox Studio holds 'lock' files on places +*.rbxl.lock +*.rbxlx.lock + # Snapshot files from the 'insta' Rust crate **/*.snap.new \ No newline at end of file From 26e2e8118814036fedb832043cc796ea1d592148 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Dec 2019 17:41:35 -0800 Subject: [PATCH 0925/1504] Refactor ChangeProcessor to be easier to follow --- src/change_processor.rs | 336 +++++++++++++++++++++++----------------- 1 file changed, 193 insertions(+), 143 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index c721260a..a131d325 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -1,11 +1,6 @@ -//! Defines the process by which changes are pulled from the Vfs, filtered, and -//! used to mutate Rojo's tree during a live session. -//! -//! This object is owned by a ServeSession. - use std::sync::{Arc, Mutex}; -use crossbeam_channel::{select, Receiver, Sender}; +use crossbeam_channel::{select, Sender}; use jod_thread::JoinHandle; use rbx_dom_weak::RbxId; @@ -18,186 +13,241 @@ use crate::{ vfs::{FsResultExt, Vfs, VfsEvent, VfsFetcher}, }; +/// Owns the connection between Rojo's VFS and its DOM by holding onto another +/// thread that processes messages. +/// +/// Consumers of ChangeProcessor, like ServeSession, are intended to communicate +/// with this object via channels. +/// +/// ChangeProcessor expects to be the only writer to the RojoTree and Vfs +/// objects passed to it. pub struct ChangeProcessor { + /// Controls the runtime of the processor thread. When signaled, the job + /// thread will finish its current work and terminate. + /// + /// This channel should be signaled before dropping ChangeProcessor or we'll + /// hang forever waiting for the message processing loop to terminate. shutdown_sender: Sender<()>, - _thread_handle: JoinHandle<()>, + + /// A handle to the message processing thread. When dropped, we'll block + /// until it's done. + /// + /// Allowed to be unused because dropping this value has side effects. + #[allow(unused)] + job_thread: JoinHandle<()>, } impl ChangeProcessor { + /// Spin up the ChangeProcessor, connecting it to the given tree, VFS, and + /// outbound message queue. pub fn start( tree: Arc>, message_queue: Arc>, vfs: Arc>, ) -> Self { let (shutdown_sender, shutdown_receiver) = crossbeam_channel::bounded(1); + let vfs_receiver = vfs.change_receiver(); + let task = JobThreadContext { + tree, + vfs, + message_queue, + }; - let thread_handle = jod_thread::Builder::new() + let job_thread = jod_thread::Builder::new() .name("ChangeProcessor thread".to_owned()) .spawn(move || { log::trace!("ChangeProcessor thread started"); - Self::main_task(shutdown_receiver, tree, message_queue, vfs); + + #[allow( + // Crossbeam's select macro generates code that Clippy doesn't like, + // and Clippy blames us for it. + clippy::drop_copy, + + // Crossbeam uses 0 as *const _ and Clippy doesn't like that either, + // but this isn't our fault. + clippy::zero_ptr, + )] + loop { + select! { + recv(vfs_receiver) -> event => { + task.handle_vfs_event(event.unwrap()); + }, + recv(shutdown_receiver) -> _ => { + log::trace!("ChangeProcessor shutdown signal received..."); + break; + }, + } + } + log::trace!("ChangeProcessor thread stopped"); }) .expect("Could not start ChangeProcessor thread"); Self { shutdown_sender, - _thread_handle: thread_handle, - } - } - - fn main_task( - shutdown_receiver: Receiver<()>, - tree: Arc>, - message_queue: Arc>, - vfs: Arc>, - ) { - let vfs_receiver = vfs.change_receiver(); - - #[allow( - // Crossbeam's select macro generates code that Clippy doesn't like, - // and Clippy blames us for it. - clippy::drop_copy, - - // Crossbeam uses 0 as *const _ and Clippy doesn't like that either, - // but this isn't our fault. - clippy::zero_ptr, - )] - loop { - select! { - recv(vfs_receiver) -> event => { - let event = event.unwrap(); - - log::trace!("Vfs event: {:?}", event); - - let applied_patches = { - vfs.commit_change(&event).expect("Error applying VFS change"); - - let mut tree = tree.lock().unwrap(); - let mut applied_patches = Vec::new(); - - match event { - VfsEvent::Created(path) | VfsEvent::Modified(path) | VfsEvent::Removed(path) => { - let mut current_path = path.as_path(); - let affected_ids = loop { - let ids = tree.get_ids_at_path(¤t_path); - - log::trace!("Path {} affects IDs {:?}", current_path.display(), ids); - - if !ids.is_empty() { - break ids.to_vec(); - } - - log::trace!("Trying parent path..."); - match current_path.parent() { - Some(parent) => current_path = parent, - None => break Vec::new(), - } - }; - - update_affected_instances(&mut tree, &vfs, &mut applied_patches, &affected_ids) - } - } - - applied_patches - }; - - { - message_queue.push_messages(&applied_patches); - } - }, - recv(shutdown_receiver) -> _ => { - log::trace!("ChangeProcessor shutdown signal received..."); - break; - }, - } + job_thread, } } } impl Drop for ChangeProcessor { fn drop(&mut self) { + // Signal the job thread to start spinning down. Without this we'll hang + // forever waiting for the thread to finish its infinite loop. let _ = self.shutdown_sender.send(()); + + // After this function ends, the job thread will be joined. It might + // block for a small period of time while it processes its last work. } } -fn update_affected_instances( - tree: &mut RojoTree, - vfs: &Vfs, - applied_patches: &mut Vec, - affected_ids: &[RbxId], -) { - for &id in affected_ids { - let metadata = tree - .get_metadata(id) - .expect("metadata missing for instance present in tree"); +/// Contains all of the state needed to synchronize the DOM and VFS. +struct JobThreadContext { + /// A handle to the DOM we're managing. + tree: Arc>, - let instigating_source = match &metadata.instigating_source { - Some(path) => path, - None => { - log::warn!("Instance {} did not have an instigating source, but was considered for an update.", id); - log::warn!("This is a Rojo bug. Please file an issue!"); - continue; - } - }; + /// A handle to the VFS we're managing. + vfs: Arc>, - // How we process a file change event depends on what created this - // file/folder in the first place. - let applied_patch_set = match instigating_source { - InstigatingSource::Path(path) => { - let maybe_entry = vfs - .get(path) - .with_not_found() - .expect("unexpected VFS error"); + /// Whenever changes are applied to the DOM, we should push those changes + /// into this message queue to inform any connected clients. + message_queue: Arc>, +} - match maybe_entry { - Some(entry) => { - // Our instance was previously created from a path and - // that path still exists. We can generate a snapshot - // starting at that path and use it as the source for - // our patch. +impl JobThreadContext { + fn handle_vfs_event(&self, event: VfsEvent) { + log::trace!("Vfs event: {:?}", event); - let snapshot = snapshot_from_vfs(&metadata.context, &vfs, &entry) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); + // Update the VFS immediately with the event. + self.vfs + .commit_change(&event) + .expect("Error applying VFS change"); - let patch_set = compute_patch_set(&snapshot, &tree, id); - apply_patch_set(tree, patch_set) - } - None => { - // Our instance was previously created from a path, but - // that path no longer exists. - // - // We associate deleting the instigating file for an - // instance with deleting that instance. + // For a given VFS event, we might have many changes to different parts + // of the tree. Calculate and apply all of these changes. + let applied_patches = { + let mut tree = self.tree.lock().unwrap(); + let mut applied_patches = Vec::new(); - let mut patch_set = PatchSet::new(); - patch_set.removed_instances.push(id); + match event { + VfsEvent::Created(path) | VfsEvent::Modified(path) | VfsEvent::Removed(path) => { + // Find the nearest ancestor to this path that has + // associated instances in the tree. This helps make sure + // that we handle additions correctly, especially if we + // receive events for descendants of a large tree being + // created all at once. + let mut current_path = path.as_path(); + let affected_ids = loop { + let ids = tree.get_ids_at_path(¤t_path); - apply_patch_set(tree, patch_set) + log::trace!("Path {} affects IDs {:?}", current_path.display(), ids); + + if !ids.is_empty() { + break ids.to_vec(); + } + + log::trace!("Trying parent path..."); + match current_path.parent() { + Some(parent) => current_path = parent, + None => break Vec::new(), + } + }; + + for id in affected_ids { + if let Some(patch) = compute_and_apply_changes(&mut tree, &self.vfs, id) { + applied_patches.push(patch); + } } } } - InstigatingSource::ProjectNode(project_path, instance_name, project_node) => { - // This instance is the direct subject of a project node. Since - // there might be information associated with our instance from - // the project file, we snapshot the entire project node again. - let snapshot = snapshot_project_node( - &metadata.context, - &project_path, - instance_name, - project_node, - &vfs, - ) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); - - let patch_set = compute_patch_set(&snapshot, &tree, id); - apply_patch_set(tree, patch_set) - } + applied_patches }; - applied_patches.push(applied_patch_set); + // Notify anyone listening to the message queue about the changes we + // just made. + self.message_queue.push_messages(&applied_patches); } } + +fn compute_and_apply_changes( + tree: &mut RojoTree, + vfs: &Vfs, + id: RbxId, +) -> Option { + let metadata = tree + .get_metadata(id) + .expect("metadata missing for instance present in tree"); + + let instigating_source = match &metadata.instigating_source { + Some(path) => path, + None => { + log::warn!( + "Instance {} did not have an instigating source, but was considered for an update.", + id + ); + log::warn!("This is a Rojo bug. Please file an issue!"); + + return None; + } + }; + + // How we process a file change event depends on what created this + // file/folder in the first place. + let applied_patch_set = match instigating_source { + InstigatingSource::Path(path) => { + let maybe_entry = vfs + .get(path) + .with_not_found() + .expect("unexpected VFS error"); + + match maybe_entry { + Some(entry) => { + // Our instance was previously created from a path and + // that path still exists. We can generate a snapshot + // starting at that path and use it as the source for + // our patch. + + let snapshot = snapshot_from_vfs(&metadata.context, &vfs, &entry) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + let patch_set = compute_patch_set(&snapshot, &tree, id); + apply_patch_set(tree, patch_set) + } + None => { + // Our instance was previously created from a path, but + // that path no longer exists. + // + // We associate deleting the instigating file for an + // instance with deleting that instance. + + let mut patch_set = PatchSet::new(); + patch_set.removed_instances.push(id); + + apply_patch_set(tree, patch_set) + } + } + } + InstigatingSource::ProjectNode(project_path, instance_name, project_node) => { + // This instance is the direct subject of a project node. Since + // there might be information associated with our instance from + // the project file, we snapshot the entire project node again. + + let snapshot = snapshot_project_node( + &metadata.context, + &project_path, + instance_name, + project_node, + &vfs, + ) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + let patch_set = compute_patch_set(&snapshot, &tree, id); + apply_patch_set(tree, patch_set) + } + }; + + Some(applied_patch_set) +} From a398338c028eaf74cd4598d4d47d474199beddf0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 20 Dec 2019 14:24:28 -0800 Subject: [PATCH 0926/1504] Two way sync V0 (#282) * Unfinished two-way sync API * In-memory two-way sync complete * Move PatchSet application into ChangeProcessor thread, where it can be synchronous * Stop InstanceMap's signals when a ServeSession terminates * Apply patch in ChangeProcessor * Feature flag * Fix error in ChangeProcessor due to wrong drop order --- Cargo.toml | 3 ++ plugin/src/ApiContext.lua | 19 +++++++++--- plugin/src/DevSettings.lua | 4 +-- plugin/src/InstanceMap.lua | 14 ++++++++- plugin/src/ServeSession.lua | 1 + src/change_processor.rs | 22 ++++++++++++-- src/serve_session.rs | 38 +++++++++++++++++++----- src/web/api.rs | 58 +++++++++++++++++++++++++++++++++++-- src/web/interface.rs | 17 +++++++++++ 9 files changed, 156 insertions(+), 20 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 41b0e456..601fecc5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,9 @@ exclude = [ [features] default = [] +# Turn on the server half of Rojo's unstable two-way sync feature. +unstable_two_way_sync = [] + # Enable this feature to live-reload assets from the web UI. dev-live-assets = [] diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 6e5b36e0..c6e89a93 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -156,11 +156,22 @@ function ApiContext:read(ids) end function ApiContext:write(patch) - local url = ("%s/write"):format(self.__baseUrl) - local body = Http.jsonEncode({ + local url = ("%s/api/write"):format(self.__baseUrl) + + local body = { sessionId = self.__sessionId, - patch = patch, - }) + removed = patch.removed, + updated = patch.updated, + } + + -- Only add the 'added' field if the table is non-empty, or else Roblox's + -- JSON implementation will turn the table into an array instead of an + -- object, causing API validation to fail. + if next(patch.added) ~= nil then + body.added = patch.added + end + + body = Http.jsonEncode(body) return Http.post(url, body) :andThen(rejectFailedRequests) diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua index 182769da..c859f8f0 100644 --- a/plugin/src/DevSettings.lua +++ b/plugin/src/DevSettings.lua @@ -25,7 +25,7 @@ local VALUES = { [Environment.Test] = true, }, }, - ExperimentalTwoWaySync = { + UnstableTwoWaySync = { type = "BoolValue", values = { [Environment.User] = false, @@ -141,7 +141,7 @@ function DevSettings:shouldTypecheck() end function DevSettings:twoWaySyncEnabled() - return getValue("ExperimentalTwoWaySync") + return getValue("UnstableTwoWaySync") end function _G.ROJO_DEV_CREATE() diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index d1a6a1a7..1396ed6c 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -20,6 +20,16 @@ function InstanceMap.new(onInstanceChanged) return setmetatable(self, InstanceMap) end +--[[ + Disconnect all connections and release all instance references. +]] +function InstanceMap:stop() + -- I think this is safe. + for instance in pairs(self.fromInstances) do + self:removeInstance(instance) + end +end + function InstanceMap:__fmtDebug(output) output:writeLine("InstanceMap {{") output:indent() @@ -145,7 +155,9 @@ function InstanceMap:__disconnectSignals(instance) local signals = self.instancesToSignal[instance] if signals ~= nil then - -- In the general case, we avoid + -- In most cases, we only have a single signal, so we avoid keeping + -- around the extra table. ValueBase objects force us to use multiple + -- signals to emulate the Instance.Changed event, however. if typeof(signals) == "table" then for _, signal in ipairs(signals) do signal:Disconnect() diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index e6cdbb2f..41580f66 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -189,6 +189,7 @@ end function ServeSession:__stopInternal(err) self:__setStatus(Status.Disconnected, err) self.__apiContext:disconnect() + self.__instanceMap:stop() end function ServeSession:__setStatus(status, detail) diff --git a/src/change_processor.rs b/src/change_processor.rs index a131d325..ebf307fd 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -1,6 +1,6 @@ use std::sync::{Arc, Mutex}; -use crossbeam_channel::{select, Sender}; +use crossbeam_channel::{select, Receiver, Sender}; use jod_thread::JoinHandle; use rbx_dom_weak::RbxId; @@ -42,8 +42,9 @@ impl ChangeProcessor { /// outbound message queue. pub fn start( tree: Arc>, - message_queue: Arc>, vfs: Arc>, + message_queue: Arc>, + tree_mutation_receiver: Receiver, ) -> Self { let (shutdown_sender, shutdown_receiver) = crossbeam_channel::bounded(1); let vfs_receiver = vfs.change_receiver(); @@ -72,6 +73,9 @@ impl ChangeProcessor { recv(vfs_receiver) -> event => { task.handle_vfs_event(event.unwrap()); }, + recv(tree_mutation_receiver) -> patch_set => { + task.handle_tree_event(patch_set.unwrap()); + }, recv(shutdown_receiver) -> _ => { log::trace!("ChangeProcessor shutdown signal received..."); break; @@ -168,6 +172,20 @@ impl JobThreadContext { // just made. self.message_queue.push_messages(&applied_patches); } + + fn handle_tree_event(&self, patch_set: PatchSet) { + log::trace!("Applying PatchSet from client: {:#?}", patch_set); + + // TODO: Calculate a corresponding VFS patch and apply that instead? + + let applied_patch = { + let mut tree = self.tree.lock().unwrap(); + + apply_patch_set(&mut tree, patch_set) + }; + + self.message_queue.push_messages(&[applied_patch]); + } } fn compute_and_apply_changes( diff --git a/src/serve_session.rs b/src/serve_session.rs index 7a90d6b0..34f49ffa 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -5,13 +5,15 @@ use std::{ time::Instant, }; +use crossbeam_channel::Sender; + use crate::{ change_processor::ChangeProcessor, common_setup, message_queue::MessageQueue, project::Project, session_id::SessionId, - snapshot::{AppliedPatchSet, RojoTree}, + snapshot::{AppliedPatchSet, PatchSet, RojoTree}, vfs::{Vfs, VfsFetcher}, }; @@ -23,6 +25,20 @@ use crate::{ /// future. `ServeSession` would be roughly the right interface to expose for /// those cases. pub struct ServeSession { + /// The object responsible for listening to changes from the in-memory + /// filesystem, applying them, updating the Roblox instance tree, and + /// routing messages through the session's message queue to any connected + /// clients. + /// + /// SHOULD BE DROPPED FIRST! ServeSession and ChangeProcessor communicate + /// with eachother via channels. If ServeSession hangs up those channels + /// before dropping the ChangeProcessor, its thread will panic with a + /// RecvError, causing the main thread to panic on drop. + /// + /// Allowed to be unused because it has side effects when dropped. + #[allow(unused)] + change_processor: ChangeProcessor, + /// When the serve session was started. Used only for user-facing /// diagnostics. start_time: Instant, @@ -61,11 +77,9 @@ pub struct ServeSession { /// to be applied. message_queue: Arc>, - /// The object responsible for listening to changes from the in-memory - /// filesystem, applying them, updating the Roblox instance tree, and - /// routing messages through the session's message queue to any connected - /// clients. - _change_processor: ChangeProcessor, + /// A channel to send mutation requests on. These will be handled by the + /// ChangeProcessor and trigger changes in the tree. + tree_mutation_sender: Sender, } /// Methods that need thread-safety bounds on VfsFetcher are limited to this @@ -94,21 +108,25 @@ impl ServeSession { let message_queue = Arc::new(message_queue); let vfs = Arc::new(vfs); + let (tree_mutation_sender, tree_mutation_receiver) = crossbeam_channel::unbounded(); + log::trace!("Starting ChangeProcessor"); let change_processor = ChangeProcessor::start( Arc::clone(&tree), - Arc::clone(&message_queue), Arc::clone(&vfs), + Arc::clone(&message_queue), + tree_mutation_receiver, ); Self { + change_processor, start_time, session_id, root_project, tree, message_queue, + tree_mutation_sender, vfs, - _change_processor: change_processor, } } } @@ -122,6 +140,10 @@ impl ServeSession { self.tree.lock().unwrap() } + pub fn tree_mutation_sender(&self) -> Sender { + self.tree_mutation_sender.clone() + } + pub fn vfs(&self) -> &Vfs { &self.vfs } diff --git a/src/web/api.rs b/src/web/api.rs index 9a81ef00..0ddb21d6 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -3,19 +3,20 @@ use std::{collections::HashMap, sync::Arc}; -use futures::Future; +use futures::{Future, Stream}; use hyper::{service::Service, Body, Method, Request, StatusCode}; use rbx_dom_weak::RbxId; use crate::{ serve_session::ServeSession, + snapshot::{PatchSet, PatchUpdate}, vfs::VfsFetcher, web::{ interface::{ ErrorResponse, Instance, InstanceMetadata as WebInstanceMetadata, InstanceUpdate, - ReadResponse, ServerInfoResponse, SubscribeMessage, SubscribeResponse, - PROTOCOL_VERSION, SERVER_VERSION, + ReadResponse, ServerInfoResponse, SubscribeMessage, SubscribeResponse, WriteRequest, + WriteResponse, PROTOCOL_VERSION, SERVER_VERSION, }, util::{json, json_ok}, }, @@ -39,6 +40,11 @@ impl Service for ApiService { (&Method::GET, path) if path.starts_with("/api/subscribe/") => { self.handle_api_subscribe(request) } + + (&Method::POST, "/api/write") if cfg!(feature = "unstable_two_way_sync") => { + self.handle_api_write(request) + } + (_method, path) => json( ErrorResponse::not_found(format!("Route not found: {}", path)), StatusCode::NOT_FOUND, @@ -145,6 +151,52 @@ impl ApiService { })) } + fn handle_api_write(&self, request: Request) -> ::Future { + let session_id = self.serve_session.session_id(); + let tree_mutation_sender = self.serve_session.tree_mutation_sender(); + + Box::new(request.into_body().concat2().and_then(move |body| { + let request: WriteRequest = match serde_json::from_slice(&body) { + Ok(request) => request, + Err(err) => { + return json( + ErrorResponse::bad_request(format!("Invalid body: {}", err)), + StatusCode::BAD_REQUEST, + ); + } + }; + + if request.session_id != session_id { + return json( + ErrorResponse::bad_request("Wrong session ID"), + StatusCode::BAD_REQUEST, + ); + } + + let updated_instances = request + .updated + .into_iter() + .map(|update| PatchUpdate { + id: update.id, + changed_class_name: update.changed_class_name, + changed_name: update.changed_name, + changed_properties: update.changed_properties, + changed_metadata: None, + }) + .collect(); + + tree_mutation_sender + .send(PatchSet { + removed_instances: Vec::new(), + added_instances: Vec::new(), + updated_instances, + }) + .unwrap(); + + json_ok(&WriteResponse { session_id }) + })) + } + fn handle_api_read(&self, request: Request) -> ::Future { let argument = &request.uri().path()["/api/read/".len()..]; let requested_ids: Option> = argument.split(',').map(RbxId::parse_str).collect(); diff --git a/src/web/interface.rs b/src/web/interface.rs index 01cb62c3..dc315ca7 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -100,6 +100,23 @@ pub struct ReadResponse<'a> { pub instances: HashMap>, } +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WriteRequest { + pub session_id: SessionId, + pub removed: Vec, + + #[serde(default)] + pub added: HashMap, + pub updated: Vec, +} + +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WriteResponse { + pub session_id: SessionId, +} + /// Response body from /api/subscribe/{cursor} #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] From cdc55137265833ae419b9cb2a276f4405b95e9eb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 20 Dec 2019 14:26:08 -0800 Subject: [PATCH 0927/1504] Rename dev-live-assets feature to dev_live_assets --- Cargo.toml | 6 +----- src/web/assets.rs | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 601fecc5..a6486cac 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,11 +20,7 @@ default = [] unstable_two_way_sync = [] # Enable this feature to live-reload assets from the web UI. -dev-live-assets = [] - -# Enables specifying user plugins in the project file. User plugins are Lua -# files and currently not fully implemented. See issue #55. -user-plugins = [] +dev_live_assets = [] [workspace] members = [ diff --git a/src/web/assets.rs b/src/web/assets.rs index 481c588c..09bfc3db 100644 --- a/src/web/assets.rs +++ b/src/web/assets.rs @@ -1,7 +1,7 @@ macro_rules! declare_asset { ($name: ident, $path: expr) => { pub fn $name() -> &'static str { - if cfg!(feature = "dev-live-assets") { + if cfg!(feature = "dev_live_assets") { use std::{fs::read_to_string, path::Path}; let file_path = Path::new(file!()); From f81e8339e360b9e5856cff641c6ed57afd8f5a97 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 20 Dec 2019 16:52:56 -0800 Subject: [PATCH 0928/1504] Add 'homepage' and 'documentation' links to Cargo.toml --- Cargo.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Cargo.toml b/Cargo.toml index a6486cac..a7f086bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,8 @@ version = "0.6.0-dev" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" +homepage = "https://rojo.space" +documentation = "https://rojo.space/docs" repository = "https://github.com/rojo-rbx/rojo" readme = "README.md" edition = "2018" From cc593b465d832114af97735bc3a657c32cf0efd4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 4 Jan 2020 21:31:36 -0800 Subject: [PATCH 0929/1504] Delete unused plugin place project --- plugin/place.project.json | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 plugin/place.project.json diff --git a/plugin/place.project.json b/plugin/place.project.json deleted file mode 100644 index 1fa420be..00000000 --- a/plugin/place.project.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "rojo", - "tree": { - "$className": "DataModel", - - "ReplicatedStorage": { - "$className": "ReplicatedStorage", - - "TestEZ": { - "$path": "modules/testez/lib" - } - } - } -} \ No newline at end of file From ae811aafd033fbeebd120c5fb7ff2bc1ef0038f2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 5 Jan 2020 23:46:12 -0800 Subject: [PATCH 0930/1504] Make ChangeProcessor abort gracefully on RecvError --- src/change_processor.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index ebf307fd..90278bd6 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -1,6 +1,6 @@ use std::sync::{Arc, Mutex}; -use crossbeam_channel::{select, Receiver, Sender}; +use crossbeam_channel::{select, Receiver, RecvError, Sender}; use jod_thread::JoinHandle; use rbx_dom_weak::RbxId; @@ -34,7 +34,7 @@ pub struct ChangeProcessor { /// /// Allowed to be unused because dropping this value has side effects. #[allow(unused)] - job_thread: JoinHandle<()>, + job_thread: JoinHandle>, } impl ChangeProcessor { @@ -71,19 +71,17 @@ impl ChangeProcessor { loop { select! { recv(vfs_receiver) -> event => { - task.handle_vfs_event(event.unwrap()); + task.handle_vfs_event(event?); }, recv(tree_mutation_receiver) -> patch_set => { - task.handle_tree_event(patch_set.unwrap()); + task.handle_tree_event(patch_set?); }, recv(shutdown_receiver) -> _ => { log::trace!("ChangeProcessor shutdown signal received..."); - break; + return Ok(()); }, } } - - log::trace!("ChangeProcessor thread stopped"); }) .expect("Could not start ChangeProcessor thread"); From e261e7a2c7cd1e790f31c7042b9ddc25fd7b3437 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 8 Jan 2020 17:58:37 -0800 Subject: [PATCH 0931/1504] Implement glob ignores (#272) * Add Glob wrapper type with better serialization * Introduce PathIgnoreRule struct * Implement equality for Glob type * Add PathIgnoreRule to InstanceContext * Implement glob ignores in directory middleware * Fix up filters * Use Iterator::all instead of loop * Add project-level configuration for glob ignores * Add test project for glob ignores * Wire up project file and snapshots to make glob ignores work * Better codepaths for adding ignore rules with empty iterators * Add test for globs inherited from parent projects * Add test details, support glob ignores in nested projects * Add feature flag for globs * Switch to use ExactSizeIterator instead of size_hint * Remove glob visitor --- .github/workflows/ci.yml | 8 ++- Cargo.lock | 14 +++++ Cargo.toml | 6 +- rojo-test/Cargo.toml | 5 ++ .../build_test__ignore_glob_inner.snap | 33 +++++++++++ .../build_test__ignore_glob_nested.snap | 17 ++++++ .../build_test__ignore_glob_spec.snap | 17 ++++++ .../build-tests/ignore_glob_inner/README.md | 2 + .../ignore_glob_inner/default.project.json | 14 +++++ .../ignore_glob_inner/src/outer.spec.lua | 1 + .../subproject/default.project.json | 9 +++ .../subproject/src/inner.lua | 1 + .../subproject/src/inner.spec.lua | 1 + .../build-tests/ignore_glob_nested/README.md | 2 + .../ignore_glob_nested/default.project.json | 9 +++ .../subproject/default.project.json | 6 ++ .../subproject/src/exclude.spec.lua | 1 + .../subproject/src/include.lua | 1 + .../build-tests/ignore_glob_spec/README.md | 2 + .../ignore_glob_spec/default.project.json | 9 +++ .../ignore_glob_spec/src/shouldBeIncluded.lua | 1 + .../src/shouldBeRemoved.spec.lua | 1 + rojo-test/src/build_test.rs | 7 +++ src/common_setup.rs | 16 +++++- src/glob.rs | 50 +++++++++++++++++ src/lib.rs | 1 + src/project.rs | 8 +++ src/snapshot/metadata.rs | 55 ++++++++++++++++++- src/snapshot_middleware/dir.rs | 9 ++- src/snapshot_middleware/project.rs | 15 ++++- 30 files changed, 310 insertions(+), 11 deletions(-) create mode 100644 rojo-test/build-test-snapshots/build_test__ignore_glob_inner.snap create mode 100644 rojo-test/build-test-snapshots/build_test__ignore_glob_nested.snap create mode 100644 rojo-test/build-test-snapshots/build_test__ignore_glob_spec.snap create mode 100644 rojo-test/build-tests/ignore_glob_inner/README.md create mode 100644 rojo-test/build-tests/ignore_glob_inner/default.project.json create mode 100644 rojo-test/build-tests/ignore_glob_inner/src/outer.spec.lua create mode 100644 rojo-test/build-tests/ignore_glob_inner/subproject/default.project.json create mode 100644 rojo-test/build-tests/ignore_glob_inner/subproject/src/inner.lua create mode 100644 rojo-test/build-tests/ignore_glob_inner/subproject/src/inner.spec.lua create mode 100644 rojo-test/build-tests/ignore_glob_nested/README.md create mode 100644 rojo-test/build-tests/ignore_glob_nested/default.project.json create mode 100644 rojo-test/build-tests/ignore_glob_nested/subproject/default.project.json create mode 100644 rojo-test/build-tests/ignore_glob_nested/subproject/src/exclude.spec.lua create mode 100644 rojo-test/build-tests/ignore_glob_nested/subproject/src/include.lua create mode 100644 rojo-test/build-tests/ignore_glob_spec/README.md create mode 100644 rojo-test/build-tests/ignore_glob_spec/default.project.json create mode 100644 rojo-test/build-tests/ignore_glob_spec/src/shouldBeIncluded.lua create mode 100644 rojo-test/build-tests/ignore_glob_spec/src/shouldBeRemoved.spec.lua create mode 100644 src/glob.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b127abd4..8c8b8660 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,4 +27,10 @@ jobs: run: | cargo fmt -- --check cargo clippy - if: matrix.rust_version == 'stable' \ No newline at end of file + if: matrix.rust_version == 'stable' + + - name: Build (All Features) + run: cargo build --locked --verbose --all-features + + - name: Run tests (All Features) + run: cargo test --locked --verbose --all-features \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 86261608..21dd6ae2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -607,6 +607,18 @@ name = "glob" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "globset" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "h2" version = "0.1.26" @@ -1652,6 +1664,7 @@ dependencies = [ "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2519,6 +2532,7 @@ dependencies = [ "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" "checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +"checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7" diff --git a/Cargo.toml b/Cargo.toml index a7f086bf..c7be0aa6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,9 @@ exclude = [ [features] default = [] +# Turn on support for specifying glob ignore path rules in the project format. +unstable_glob_ignore_paths = [] + # Turn on the server half of Rojo's unstable two-way sync feature. unstable_two_way_sync = [] @@ -54,6 +57,7 @@ crossbeam-channel = "0.4.0" csv = "1.1.1" env_logger = "0.7.1" futures = "0.1.29" +globset = "0.4.4" humantime = "1.3.0" hyper = "0.12.35" jod-thread = "0.1.0" @@ -69,7 +73,7 @@ regex = "1.3.1" reqwest = "0.9.20" ritz = "0.1.0" rlua = "0.17.0" -serde = { version = "1.0", features = ["derive"] } +serde = { version = "1.0", features = ["derive", "rc"] } serde_json = "1.0" snafu = "0.6.0" structopt = "0.3.5" diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index 91b13449..ddd275b2 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -5,6 +5,11 @@ authors = ["Lucien Greathouse "] edition = "2018" publish = false +[features] +default = [] + +unstable_glob_ignore_paths = [] + [dependencies] env_logger = "0.6.2" log = "0.4.8" diff --git a/rojo-test/build-test-snapshots/build_test__ignore_glob_inner.snap b/rojo-test/build-test-snapshots/build_test__ignore_glob_inner.snap new file mode 100644 index 00000000..9ff1bdec --- /dev/null +++ b/rojo-test/build-test-snapshots/build_test__ignore_glob_inner.snap @@ -0,0 +1,33 @@ +--- +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + ignore_glob_inner + + + + src + + + + outer.spec + -- This file should be included. + + + + + + subproject + + + + inner + -- This file should be included. + + + + + diff --git a/rojo-test/build-test-snapshots/build_test__ignore_glob_nested.snap b/rojo-test/build-test-snapshots/build_test__ignore_glob_nested.snap new file mode 100644 index 00000000..aab8afaf --- /dev/null +++ b/rojo-test/build-test-snapshots/build_test__ignore_glob_nested.snap @@ -0,0 +1,17 @@ +--- +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + ignore_glob_nested + + + + include + -- This file must be present. + + + + diff --git a/rojo-test/build-test-snapshots/build_test__ignore_glob_spec.snap b/rojo-test/build-test-snapshots/build_test__ignore_glob_spec.snap new file mode 100644 index 00000000..7fc338f9 --- /dev/null +++ b/rojo-test/build-test-snapshots/build_test__ignore_glob_spec.snap @@ -0,0 +1,17 @@ +--- +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + ignore_glob_spec + + + + shouldBeIncluded + -- this file should be present + + + + diff --git a/rojo-test/build-tests/ignore_glob_inner/README.md b/rojo-test/build-tests/ignore_glob_inner/README.md new file mode 100644 index 00000000..0430af1c --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_inner/README.md @@ -0,0 +1,2 @@ +# ignore_glob_inner +Tests that glob ignores defined *inside* nested projects apply to those projects, but not anywhere else. \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_inner/default.project.json b/rojo-test/build-tests/ignore_glob_inner/default.project.json new file mode 100644 index 00000000..6a3eabbb --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_inner/default.project.json @@ -0,0 +1,14 @@ +{ + "name": "ignore_glob_inner", + "tree": { + "$className": "Folder", + + "src": { + "$path": "src" + }, + + "subproject": { + "$path": "subproject" + } + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_inner/src/outer.spec.lua b/rojo-test/build-tests/ignore_glob_inner/src/outer.spec.lua new file mode 100644 index 00000000..e60a05ea --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_inner/src/outer.spec.lua @@ -0,0 +1 @@ +-- This file should be included. \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_inner/subproject/default.project.json b/rojo-test/build-tests/ignore_glob_inner/subproject/default.project.json new file mode 100644 index 00000000..335a7161 --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_inner/subproject/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "subproject", + "tree": { + "$path": "src" + }, + "globIgnorePaths": [ + "**/*.spec.lua" + ] +} \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_inner/subproject/src/inner.lua b/rojo-test/build-tests/ignore_glob_inner/subproject/src/inner.lua new file mode 100644 index 00000000..e60a05ea --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_inner/subproject/src/inner.lua @@ -0,0 +1 @@ +-- This file should be included. \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_inner/subproject/src/inner.spec.lua b/rojo-test/build-tests/ignore_glob_inner/subproject/src/inner.spec.lua new file mode 100644 index 00000000..33654edf --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_inner/subproject/src/inner.spec.lua @@ -0,0 +1 @@ +-- This file should not be included. \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_nested/README.md b/rojo-test/build-tests/ignore_glob_nested/README.md new file mode 100644 index 00000000..fc480bfe --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_nested/README.md @@ -0,0 +1,2 @@ +# ignore_glob_nested +Tests that glob ignores defined in the root project also apply to nested projects. \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_nested/default.project.json b/rojo-test/build-tests/ignore_glob_nested/default.project.json new file mode 100644 index 00000000..aab74f71 --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_nested/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "ignore_glob_nested", + "tree": { + "$path": "subproject" + }, + "globIgnorePaths": [ + "**/*.spec.lua" + ] +} \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_nested/subproject/default.project.json b/rojo-test/build-tests/ignore_glob_nested/subproject/default.project.json new file mode 100644 index 00000000..65d48ffe --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_nested/subproject/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "subproject", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_nested/subproject/src/exclude.spec.lua b/rojo-test/build-tests/ignore_glob_nested/subproject/src/exclude.spec.lua new file mode 100644 index 00000000..4b03b204 --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_nested/subproject/src/exclude.spec.lua @@ -0,0 +1 @@ +-- This file must not be present. \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_nested/subproject/src/include.lua b/rojo-test/build-tests/ignore_glob_nested/subproject/src/include.lua new file mode 100644 index 00000000..654ec760 --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_nested/subproject/src/include.lua @@ -0,0 +1 @@ +-- This file must be present. \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_spec/README.md b/rojo-test/build-tests/ignore_glob_spec/README.md new file mode 100644 index 00000000..a427153c --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_spec/README.md @@ -0,0 +1,2 @@ +# ignore_glob_spec +Tests that glob ignores work for the original use case: ignoring files in the same project that end in `.spec.lua`. \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_spec/default.project.json b/rojo-test/build-tests/ignore_glob_spec/default.project.json new file mode 100644 index 00000000..6d6721c1 --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_spec/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "ignore_glob_spec", + "tree": { + "$path": "src" + }, + "globIgnorePaths": [ + "**/*.spec.lua" + ] +} \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_spec/src/shouldBeIncluded.lua b/rojo-test/build-tests/ignore_glob_spec/src/shouldBeIncluded.lua new file mode 100644 index 00000000..a38b13d9 --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_spec/src/shouldBeIncluded.lua @@ -0,0 +1 @@ +-- this file should be present \ No newline at end of file diff --git a/rojo-test/build-tests/ignore_glob_spec/src/shouldBeRemoved.spec.lua b/rojo-test/build-tests/ignore_glob_spec/src/shouldBeRemoved.spec.lua new file mode 100644 index 00000000..e4e78bba --- /dev/null +++ b/rojo-test/build-tests/ignore_glob_spec/src/shouldBeRemoved.spec.lua @@ -0,0 +1 @@ +-- this file should not be present \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index fcdf9ead..a5d18467 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -45,6 +45,13 @@ gen_build_tests! { txt_in_folder, } +#[cfg(feature = "unstable_glob_ignore_paths")] +gen_build_tests! { + ignore_glob_inner, + ignore_glob_nested, + ignore_glob_spec, +} + #[test] fn build_plain_txt() { run_build_test("plain.txt"); diff --git a/src/common_setup.rs b/src/common_setup.rs index a744b5b5..dff3f23d 100644 --- a/src/common_setup.rs +++ b/src/common_setup.rs @@ -8,7 +8,8 @@ use rbx_dom_weak::RbxInstanceProperties; use crate::{ project::Project, snapshot::{ - apply_patch_set, compute_patch_set, InstanceContext, InstancePropertiesWithMeta, RojoTree, + apply_patch_set, compute_patch_set, InstanceContext, InstancePropertiesWithMeta, + PathIgnoreRule, RojoTree, }, snapshot_middleware::snapshot_from_vfs, vfs::{Vfs, VfsFetcher}, @@ -38,8 +39,19 @@ pub fn start( .get(fuzzy_project_path) .expect("could not get project path"); + let mut instance_context = InstanceContext::default(); + + if let Some(project) = &maybe_project { + let rules = project.glob_ignore_paths.iter().map(|glob| PathIgnoreRule { + glob: glob.clone(), + base_path: project.folder_location().to_path_buf(), + }); + + instance_context.add_path_ignore_rules(rules); + } + log::trace!("Generating snapshot of instances from VFS"); - let snapshot = snapshot_from_vfs(&InstanceContext::default(), vfs, &entry) + let snapshot = snapshot_from_vfs(&instance_context, vfs, &entry) .expect("snapshot failed") .expect("snapshot did not return an instance"); diff --git a/src/glob.rs b/src/glob.rs new file mode 100644 index 00000000..7b17286a --- /dev/null +++ b/src/glob.rs @@ -0,0 +1,50 @@ +//! Wrapper around globset's Glob type that has better serialization +//! characteristics by coupling Glob and GlobMatcher into a single type. + +use std::path::Path; + +use globset::{Glob as InnerGlob, GlobMatcher}; +use serde::{de::Error as _, Deserialize, Deserializer, Serialize, Serializer}; + +pub use globset::Error; + +#[derive(Debug, Clone)] +pub struct Glob { + inner: InnerGlob, + matcher: GlobMatcher, +} + +impl Glob { + pub fn new(glob: &str) -> Result { + let inner = InnerGlob::new(glob)?; + let matcher = inner.compile_matcher(); + + Ok(Glob { inner, matcher }) + } + + pub fn is_match>(&self, path: P) -> bool { + self.matcher.is_match(path) + } +} + +impl PartialEq for Glob { + fn eq(&self, other: &Self) -> bool { + self.inner == other.inner + } +} + +impl Eq for Glob {} + +impl Serialize for Glob { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_str(self.inner.glob()) + } +} + +impl<'de> Deserialize<'de> for Glob { + fn deserialize>(deserializer: D) -> Result { + let glob = <&str as Deserialize>::deserialize(deserializer)?; + + Glob::new(glob).map_err(D::Error::custom) + } +} diff --git a/src/lib.rs b/src/lib.rs index a7ff62a0..0a59c819 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ mod tree_view; mod auth_cookie; mod change_processor; mod common_setup; +mod glob; mod message_queue; mod multimap; mod path_map; diff --git a/src/project.rs b/src/project.rs index 9bac403f..f6cc92b5 100644 --- a/src/project.rs +++ b/src/project.rs @@ -8,6 +8,8 @@ use rbx_dom_weak::UnresolvedRbxValue; use serde::{Deserialize, Serialize}; use snafu::{ResultExt, Snafu}; +use crate::glob::Glob; + static PROJECT_FILENAME: &str = "default.project.json"; /// Error type returned by any function that handles projects. @@ -52,6 +54,12 @@ pub struct Project { #[serde(skip_serializing_if = "Option::is_none")] pub serve_place_ids: Option>, + /// A list of globs, relative to the folder the project file is in, that + /// match files that should be excluded if Rojo encounters them. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + #[cfg_attr(not(feature = "unstable_glob_ignore_paths"), serde(skip))] + pub glob_ignore_paths: Vec, + /// The path to the file that this project came from. Relative paths in the /// project should be considered relative to the parent of this field, also /// given by `Project::folder_location`. diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index d0bba5bc..983b426e 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -1,11 +1,12 @@ use std::{ fmt, path::{Path, PathBuf}, + sync::Arc, }; use serde::{Deserialize, Serialize}; -use crate::{path_serializer, project::ProjectNode}; +use crate::{glob::Glob, path_serializer, project::ProjectNode}; /// Rojo-specific metadata that can be associated with an instance or a snapshot /// of an instance. @@ -99,11 +100,59 @@ impl Default for InstanceMetadata { } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] -pub struct InstanceContext {} +pub struct InstanceContext { + #[serde(skip_serializing_if = "Vec::is_empty")] + pub path_ignore_rules: Arc>, +} + +impl InstanceContext { + /// Extend the list of ignore rules in the context with the given new rules. + pub fn add_path_ignore_rules(&mut self, new_rules: I) + where + I: IntoIterator, + I::IntoIter: ExactSizeIterator, + { + let new_rules = new_rules.into_iter(); + + // If the iterator is empty, we can skip cloning our list of ignore + // rules and appending to it. + if new_rules.len() == 0 { + return; + } + + let rules = Arc::make_mut(&mut self.path_ignore_rules); + rules.extend(new_rules); + } +} impl Default for InstanceContext { fn default() -> Self { - InstanceContext {} + InstanceContext { + path_ignore_rules: Arc::new(Vec::new()), + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +pub struct PathIgnoreRule { + /// The path that this glob is relative to. Since ignore globs are defined + /// in project files, this will generally be the folder containing the + /// project file that defined this glob. + #[serde(serialize_with = "path_serializer::serialize_absolute")] + pub base_path: PathBuf, + + /// The actual glob that can be matched against the input path. + pub glob: Glob, +} + +impl PathIgnoreRule { + pub fn passes>(&self, path: P) -> bool { + let path = path.as_ref(); + + match path.strip_prefix(&self.base_path) { + Ok(suffix) => !self.glob.is_match(suffix), + Err(_) => true, + } } } diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 4bfafc38..67c781b2 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -26,11 +26,16 @@ impl SnapshotMiddleware for SnapshotDir { return Ok(None); } - let children: Vec = entry.children(vfs)?; + let passes_filter_rules = |child: &VfsEntry| { + context + .path_ignore_rules + .iter() + .all(|rule| rule.passes(child.path())) + }; let mut snapshot_children = Vec::new(); - for child in children.into_iter() { + for child in entry.children(vfs)?.into_iter().filter(passes_filter_rules) { if let Some(child_snapshot) = snapshot_from_vfs(context, vfs, &child)? { snapshot_children.push(child_snapshot); } diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index b4d99eba..25282dc2 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -4,7 +4,9 @@ use rbx_reflection::try_resolve_value; use crate::{ project::{Project, ProjectNode}, - snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot, InstigatingSource}, + snapshot::{ + InstanceContext, InstanceMetadata, InstanceSnapshot, InstigatingSource, PathIgnoreRule, + }, vfs::{FsResultExt, Vfs, VfsEntry, VfsFetcher}, }; @@ -45,10 +47,19 @@ impl SnapshotMiddleware for SnapshotProject { let project = Project::load_from_slice(&entry.contents(vfs)?, entry.path()) .map_err(|err| SnapshotError::malformed_project(err, entry.path()))?; + let mut context = context.clone(); + + let rules = project.glob_ignore_paths.iter().map(|glob| PathIgnoreRule { + glob: glob.clone(), + base_path: project.folder_location().to_path_buf(), + }); + + context.add_path_ignore_rules(rules); + // Snapshotting a project should always return an instance, so this // unwrap is safe. let mut snapshot = snapshot_project_node( - context, + &context, project.folder_location(), &project.name, &project.tree, From a9f6c20113e18a7a7ed31e9efebf75fa95f4611d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 22 Jan 2020 09:55:21 -0800 Subject: [PATCH 0932/1504] Support Linux release binaries --- .github/workflows/release.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5d42f5cf..b5cfeebd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -38,4 +38,21 @@ jobs: uses: actions/upload-artifact@v1 with: name: rojo-macos + path: target/release/rojo + + linux: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + + - name: Build + run: cargo build --locked --verbose --release + env: + OPENSSL_STATIC: 1 + + - name: Upload artifacts + uses: actions/upload-artifact@v1 + with: + name: rojo-linux path: target/release/rojo \ No newline at end of file From f2227aa7cb8114f07ee69f734e1c4fef7faf8775 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 22 Jan 2020 09:58:30 -0800 Subject: [PATCH 0933/1504] Use static OpenSSL for macOS binaries, too --- .github/workflows/release.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index b5cfeebd..c5db1f35 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -33,6 +33,8 @@ jobs: run: | source $HOME/.cargo/env cargo build --verbose --locked --release + env: + OPENSSL_STATIC: 1 - name: Upload artifacts uses: actions/upload-artifact@v1 From 99b8ada42bd771a5e3c1cf538fa88b4f5f4d60f4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 22 Jan 2020 10:09:07 -0800 Subject: [PATCH 0934/1504] Release v0.6.0-alpha.1 --- CHANGELOG.md | 5 ++++- Cargo.lock | 6 +++--- Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bef57e2..ab7b812a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog -## Unreleased Changes (will be 0.6.0) +## Unreleased Changes + +## [0.6.0 Alpha 1](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.1) (January 22, 2020) ### General * Added support for nested project files. ([#95](https://github.com/rojo-rbx/rojo/issues/95)) @@ -8,6 +10,7 @@ * Fixed Rojo dropping Ref properties ([#142](https://github.com/rojo-rbx/rojo/issues/142)) * This means that properties like `PrimaryPart` now work! * Improved live sync protocol to reduce round-trips and improve syncing consistency. +* Improved support for binary model files and places. ### Command Line * Added `--verbose`/`-v` flag, which can be specified multiple times to increase verbosity. diff --git a/Cargo.lock b/Cargo.lock index 21dd6ae2..c59f3e99 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -184,7 +184,7 @@ dependencies = [ name = "clibrojo" version = "0.1.0" dependencies = [ - "rojo 0.6.0-dev", + "rojo 0.6.0-alpha.1", ] [[package]] @@ -1657,7 +1657,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.6.0-dev" +version = "0.6.0-alpha.1" dependencies = [ "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1715,7 +1715,7 @@ dependencies = [ "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rojo 0.6.0-dev", + "rojo 0.6.0-alpha.1", "rojo-insta-ext 0.1.0", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index c7be0aa6..c01c5acc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.6.0-dev" +version = "0.6.0-alpha.1" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 1497cab1..f31b1df0 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {0, 6, 0, "-dev"}, + version = {0, 6, 0, "-alpha.1"}, expectedServerVersionString = "0.6.0 or newer", protocolVersion = 3, defaultHost = "localhost", From f46a391873b6abf7054b2e33f8f679ca81a33e7c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 22 Jan 2020 10:20:37 -0800 Subject: [PATCH 0935/1504] Build releases on tag push instead of release creation --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c5db1f35..779566c5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,8 +1,8 @@ name: Release on: - release: - types: [created] + push: + tags: ["*"] jobs: windows: From ff47f79c62c3398a1c8c24753dc49e68c9d26cce Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 14 Feb 2020 17:57:01 -0800 Subject: [PATCH 0936/1504] Fix serverVersion in snapshots failing tests --- rojo-test/serve-test-snapshots/serve_test__add_folder_info.snap | 2 +- rojo-test/serve-test-snapshots/serve_test__edit_init_info.snap | 2 +- rojo-test/serve-test-snapshots/serve_test__empty_info.snap | 2 +- rojo-test/serve-test-snapshots/serve_test__just_txt_info.snap | 2 +- .../serve_test__move_folder_of_stuff_info.snap | 2 +- .../serve-test-snapshots/serve_test__remove_file_info.snap | 2 +- rojo-test/serve-test-snapshots/serve_test__scripts_info.snap | 2 +- rojo-test/src/serve_util.rs | 1 + 8 files changed, 8 insertions(+), 7 deletions(-) diff --git a/rojo-test/serve-test-snapshots/serve_test__add_folder_info.snap b/rojo-test/serve-test-snapshots/serve_test__add_folder_info.snap index f826d7e7..ffc35c89 100644 --- a/rojo-test/serve-test-snapshots/serve_test__add_folder_info.snap +++ b/rojo-test/serve-test-snapshots/serve_test__add_folder_info.snap @@ -5,5 +5,5 @@ expression: redactions.redacted_yaml(info) expectedPlaceIds: ~ protocolVersion: 3 rootInstanceId: id-2 -serverVersion: 0.6.0-dev +serverVersion: "[server-version]" sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__edit_init_info.snap b/rojo-test/serve-test-snapshots/serve_test__edit_init_info.snap index f826d7e7..ffc35c89 100644 --- a/rojo-test/serve-test-snapshots/serve_test__edit_init_info.snap +++ b/rojo-test/serve-test-snapshots/serve_test__edit_init_info.snap @@ -5,5 +5,5 @@ expression: redactions.redacted_yaml(info) expectedPlaceIds: ~ protocolVersion: 3 rootInstanceId: id-2 -serverVersion: 0.6.0-dev +serverVersion: "[server-version]" sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__empty_info.snap b/rojo-test/serve-test-snapshots/serve_test__empty_info.snap index f826d7e7..ffc35c89 100644 --- a/rojo-test/serve-test-snapshots/serve_test__empty_info.snap +++ b/rojo-test/serve-test-snapshots/serve_test__empty_info.snap @@ -5,5 +5,5 @@ expression: redactions.redacted_yaml(info) expectedPlaceIds: ~ protocolVersion: 3 rootInstanceId: id-2 -serverVersion: 0.6.0-dev +serverVersion: "[server-version]" sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__just_txt_info.snap b/rojo-test/serve-test-snapshots/serve_test__just_txt_info.snap index f826d7e7..ffc35c89 100644 --- a/rojo-test/serve-test-snapshots/serve_test__just_txt_info.snap +++ b/rojo-test/serve-test-snapshots/serve_test__just_txt_info.snap @@ -5,5 +5,5 @@ expression: redactions.redacted_yaml(info) expectedPlaceIds: ~ protocolVersion: 3 rootInstanceId: id-2 -serverVersion: 0.6.0-dev +serverVersion: "[server-version]" sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_info.snap b/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_info.snap index f826d7e7..ffc35c89 100644 --- a/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_info.snap +++ b/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_info.snap @@ -5,5 +5,5 @@ expression: redactions.redacted_yaml(info) expectedPlaceIds: ~ protocolVersion: 3 rootInstanceId: id-2 -serverVersion: 0.6.0-dev +serverVersion: "[server-version]" sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__remove_file_info.snap b/rojo-test/serve-test-snapshots/serve_test__remove_file_info.snap index f826d7e7..ffc35c89 100644 --- a/rojo-test/serve-test-snapshots/serve_test__remove_file_info.snap +++ b/rojo-test/serve-test-snapshots/serve_test__remove_file_info.snap @@ -5,5 +5,5 @@ expression: redactions.redacted_yaml(info) expectedPlaceIds: ~ protocolVersion: 3 rootInstanceId: id-2 -serverVersion: 0.6.0-dev +serverVersion: "[server-version]" sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts_info.snap b/rojo-test/serve-test-snapshots/serve_test__scripts_info.snap index f826d7e7..ffc35c89 100644 --- a/rojo-test/serve-test-snapshots/serve_test__scripts_info.snap +++ b/rojo-test/serve-test-snapshots/serve_test__scripts_info.snap @@ -5,5 +5,5 @@ expression: redactions.redacted_yaml(info) expectedPlaceIds: ~ protocolVersion: 3 rootInstanceId: id-2 -serverVersion: 0.6.0-dev +serverVersion: "[server-version]" sessionId: id-1 diff --git a/rojo-test/src/serve_util.rs b/rojo-test/src/serve_util.rs index d31a032d..918f5c32 100644 --- a/rojo-test/src/serve_util.rs +++ b/rojo-test/src/serve_util.rs @@ -41,6 +41,7 @@ pub fn run_serve_test(test_name: &str, callback: impl FnOnce(TestServeSession, R let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("serve-test-snapshots"); settings.set_snapshot_path(snapshot_path); settings.set_sort_maps(true); + settings.add_redaction(".serverVersion", "[server-version]"); settings.bind(move || callback(session, redactions)); } From 4a9c1d0d1ba05fe203f3be5616e8f1b22d6fe823 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 14 Feb 2020 18:15:18 -0800 Subject: [PATCH 0937/1504] two-way sync: allow changedProperties to be null to avoid array/object issues --- plugin/src/ApiContext.lua | 28 ++++++++++++++++++++++------ src/web/interface.rs | 2 ++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index c6e89a93..2f094558 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -158,19 +158,35 @@ end function ApiContext:write(patch) local url = ("%s/api/write"):format(self.__baseUrl) - local body = { - sessionId = self.__sessionId, - removed = patch.removed, - updated = patch.updated, - } + local updated = {} + for _, update in ipairs(patch.updated) do + local fixedUpdate = { + id = update.id, + changedName = update.changedName, + } + + if next(update.changedProperties) ~= nil then + fixedUpdate.changedProperties = update.changedProperties + end + + table.insert(updated, fixedUpdate) + end -- Only add the 'added' field if the table is non-empty, or else Roblox's -- JSON implementation will turn the table into an array instead of an -- object, causing API validation to fail. + local added if next(patch.added) ~= nil then - body.added = patch.added + added = patch.added end + local body = { + sessionId = self.__sessionId, + removed = patch.removed, + updated = updated, + added = added, + } + body = Http.jsonEncode(body) return Http.post(url, body) diff --git a/src/web/interface.rs b/src/web/interface.rs index dc315ca7..d2b5cd52 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -34,8 +34,10 @@ pub struct InstanceUpdate { pub id: RbxId, pub changed_name: Option, pub changed_class_name: Option, + // TODO: Transform from HashMap> to something else, since // null will get lost when decoding from JSON in some languages. + #[serde(default)] pub changed_properties: HashMap>, pub changed_metadata: Option, } From a3e0d42e86791340abefb3266b8f08ce0d62bc4d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 14 Feb 2020 18:24:03 -0800 Subject: [PATCH 0938/1504] two-way-sync: Handle deleting non-project node files. This is the tiniest step towards this feature and not even very useful, but an important proof of concept. --- src/change_processor.rs | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index 90278bd6..1ce146d7 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -1,4 +1,7 @@ -use std::sync::{Arc, Mutex}; +use std::{ + fs, + sync::{Arc, Mutex}, +}; use crossbeam_channel::{select, Receiver, RecvError, Sender}; use jod_thread::JoinHandle; @@ -174,11 +177,33 @@ impl JobThreadContext { fn handle_tree_event(&self, patch_set: PatchSet) { log::trace!("Applying PatchSet from client: {:#?}", patch_set); - // TODO: Calculate a corresponding VFS patch and apply that instead? - let applied_patch = { let mut tree = self.tree.lock().unwrap(); + for &id in &patch_set.removed_instances { + if let Some(instance) = tree.get_instance(id) { + if let Some(instigating_source) = &instance.metadata().instigating_source { + match instigating_source { + InstigatingSource::Path(path) => fs::remove_file(path).unwrap(), + InstigatingSource::ProjectNode(_, _, _) => { + log::warn!( + "Cannot remove instance {}, it's from a project file", + id + ); + } + } + } else { + // TODO + log::warn!( + "Cannot remove instance {}, it is not an instigating source.", + id + ); + } + } else { + log::warn!("Cannot remove instance {}, it does not exist.", id); + } + } + apply_patch_set(&mut tree, patch_set) }; From 5d9bc4473c442e641b99cf6813e435b5f790f276 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 14 Feb 2020 18:25:54 -0800 Subject: [PATCH 0939/1504] two-way-sync: Track Parent property for value objects --- plugin/src/InstanceMap.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 1396ed6c..59eccc80 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -133,6 +133,10 @@ function InstanceMap:__connectSignals(instance) instance:GetPropertyChangedSignal("Value"):Connect(function() self:__maybeFireInstanceChanged(instance, "Value") end), + + instance:GetPropertyChangedSignal("Parent"):Connect(function() + self:__maybeFireInstanceChanged(instance, "Parent") + end), } self.instancesToSignal[instance] = signals From 44041f33e36dfd0a01858fbfa0aa50ac7131140e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 14 Feb 2020 18:29:43 -0800 Subject: [PATCH 0940/1504] Start trying to sync parenting-to-nil (deleting) --- plugin/src/ServeSession.lua | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 41580f66..b13b351e 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -120,6 +120,8 @@ function ServeSession:__onInstanceChanged(instance, propertyName) return end + local remove = nil + local update = { id = instanceId, changedProperties = {}, @@ -127,6 +129,14 @@ function ServeSession:__onInstanceChanged(instance, propertyName) if propertyName == "Name" then update.changedName = instance.Name + elseif propertyName == "Parent" then + if instance.Parent == nil then + update = nil + remove = instanceId + else + Log.warn("Cannot sync non-nil Parent property changes yet") + return + end else local success, encoded = self.__reconciler:encodeApiValue(instance[propertyName]) @@ -139,7 +149,7 @@ function ServeSession:__onInstanceChanged(instance, propertyName) end local patch = { - removed = {}, + removed = {remove}, added = {}, updated = {update}, } From 8f215148555be4d2c1bff8893e2c6ebdce025565 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 18 Feb 2020 18:19:08 -0800 Subject: [PATCH 0941/1504] two-way-sync: Add super special case script syncing --- src/change_processor.rs | 53 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 52 insertions(+), 1 deletion(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index 1ce146d7..902a1c12 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -5,7 +5,7 @@ use std::{ use crossbeam_channel::{select, Receiver, RecvError, Sender}; use jod_thread::JoinHandle; -use rbx_dom_weak::RbxId; +use rbx_dom_weak::{RbxId, RbxValue}; use crate::{ message_queue::MessageQueue, @@ -204,6 +204,57 @@ impl JobThreadContext { } } + for update in &patch_set.updated_instances { + let id = update.id; + + if let Some(instance) = tree.get_instance(id) { + if update.changed_name.is_some() { + log::warn!("Cannot rename instances yet."); + } + + if update.changed_class_name.is_some() { + log::warn!("Cannot change ClassName yet."); + } + + if update.changed_metadata.is_some() { + log::warn!("Cannot change metadata yet."); + } + + for (key, changed_value) in &update.changed_properties { + if key == "Source" { + if let Some(instigating_source) = + &instance.metadata().instigating_source + { + match instigating_source { + InstigatingSource::Path(path) => { + if let Some(RbxValue::String { value }) = changed_value { + fs::write(path, value).unwrap(); + } else { + log::warn!("Cannot change Source to non-string value."); + } + } + InstigatingSource::ProjectNode(_, _, _) => { + log::warn!( + "Cannot remove instance {}, it's from a project file", + id + ); + } + } + } else { + log::warn!( + "Cannot update instance {}, it is not an instigating source.", + id + ); + } + } else { + log::warn!("Cannot change properties besides BaseScript.Source."); + } + } + } else { + log::warn!("Cannot update instance {}, it does not exist.", id); + } + } + apply_patch_set(&mut tree, patch_set) }; From 838e8f6bde2375631eafc7c851c5ed0523b14246 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 18 Feb 2020 22:30:12 -0800 Subject: [PATCH 0942/1504] VFS crate --- Cargo.lock | 20 ++++--- Cargo.toml | 2 + vfs/Cargo.toml | 10 ++++ vfs/src/lib.rs | 116 ++++++++++++++++++++++++++++++++++++++++ vfs/src/noop_backend.rs | 36 +++++++++++++ vfs/src/std_backend.rs | 37 +++++++++++++ 6 files changed, 214 insertions(+), 7 deletions(-) create mode 100644 vfs/Cargo.toml create mode 100644 vfs/src/lib.rs create mode 100644 vfs/src/noop_backend.rs create mode 100644 vfs/src/std_backend.rs diff --git a/Cargo.lock b/Cargo.lock index c59f3e99..d77b059b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -762,7 +762,7 @@ dependencies = [ [[package]] name = "inotify" -version = "0.6.1" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1037,15 +1037,14 @@ dependencies = [ [[package]] name = "notify" -version = "4.0.14" +version = "4.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "inotify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1672,7 +1671,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2359,6 +2358,13 @@ name = "version_check" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "vfs" +version = "0.1.0" +dependencies = [ + "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "walkdir" version = "2.2.9" @@ -2546,7 +2552,7 @@ dependencies = [ "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" "checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" -"checksum inotify 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40b54539f3910d6f84fbf9a643efd6e3aa6e4f001426c0329576128255994718" +"checksum inotify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24e40d6fd5d64e2082e0c796495c8ef5ad667a96d03e5aaa0becfd9d47bcbfb8" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" "checksum insta 0.12.0 (git+https://github.com/mitsuhiko/insta)" = "" "checksum insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d499dc062e841590a67230d853bce62d0abeb91304927871670b7c55c461349" @@ -2578,7 +2584,7 @@ dependencies = [ "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum notify 4.0.14 (registry+https://github.com/rust-lang/crates.io-index)" = "199628fc33b21bc767baa057490b00b382ecbae030803a7b36292422d15b778b" +"checksum notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "80ae4a7688d1fab81c5bf19c64fc8db920be8d519ce6336ed4e7efe024724dbd" "checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" "checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" diff --git a/Cargo.toml b/Cargo.toml index c01c5acc..c6b89947 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,12 +32,14 @@ members = [ "rojo-test", "rojo-insta-ext", "clibrojo", + "vfs", ] default-members = [ ".", "rojo-test", "rojo-insta-ext", + "vfs", ] [lib] diff --git a/vfs/Cargo.toml b/vfs/Cargo.toml new file mode 100644 index 00000000..b6eabf28 --- /dev/null +++ b/vfs/Cargo.toml @@ -0,0 +1,10 @@ +[package] +name = "vfs" +version = "0.1.0" +authors = ["Lucien Greathouse "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +notify = "4.0.15" diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs new file mode 100644 index 00000000..7246111f --- /dev/null +++ b/vfs/src/lib.rs @@ -0,0 +1,116 @@ +mod noop_backend; +mod std_backend; + +use std::io; +use std::path::{Path, PathBuf}; +use std::sync::{Arc, Mutex}; + +pub use noop_backend::NoopBackend; +pub use std_backend::StdBackend; + +pub trait VfsBackend { + fn read(&self, path: &Path) -> io::Result>; + fn write(&self, path: &Path, data: &[u8]) -> io::Result<()>; + fn read_dir(&self, path: &Path) -> io::Result; + fn metadata(&self, path: &Path) -> io::Result; +} + +pub struct DirEntry { + path: PathBuf, +} + +impl DirEntry { + pub fn path(&self) -> &Path { + &self.path + } +} + +pub struct ReadDir { + inner: Box>>, +} + +impl Iterator for ReadDir { + type Item = io::Result; + + fn next(&mut self) -> Option { + self.inner.next() + } +} + +pub struct Metadata { + is_file: bool, +} + +impl Metadata { + pub fn is_file(&self) -> bool { + self.is_file + } + + pub fn is_dir(&self) -> bool { + !self.is_file + } +} + +struct VfsLock { + data: (), + backend: Box, +} + +impl VfsLock { + pub fn read>(&mut self, path: P) -> io::Result>> { + let path = path.as_ref(); + let contents = self.backend.read(path)?; + Ok(Arc::new(contents)) + } + + pub fn write, C: AsRef<[u8]>>( + &mut self, + path: P, + contents: C, + ) -> io::Result<()> { + let path = path.as_ref(); + let contents = contents.as_ref(); + self.backend.write(path, contents) + } + + pub fn read_dir>(&mut self, path: P) -> io::Result { + let path = path.as_ref(); + self.backend.read_dir(path) + } +} + +pub struct Vfs { + inner: Mutex, +} + +impl Vfs { + pub fn new(backend: B) -> Self { + let lock = VfsLock { + data: (), + backend: Box::new(backend), + }; + + Self { + inner: Mutex::new(lock), + } + } + + pub fn read>(&self, path: P) -> io::Result>> { + let path = path.as_ref(); + let mut inner = self.inner.lock().unwrap(); + inner.read(path) + } + + pub fn write, C: AsRef<[u8]>>(&self, path: P, contents: C) -> io::Result<()> { + let path = path.as_ref(); + let contents = contents.as_ref(); + let mut inner = self.inner.lock().unwrap(); + inner.write(path, contents) + } + + pub fn read_dir>(&self, path: P) -> io::Result { + let path = path.as_ref(); + let mut inner = self.inner.lock().unwrap(); + inner.read_dir(path) + } +} diff --git a/vfs/src/noop_backend.rs b/vfs/src/noop_backend.rs new file mode 100644 index 00000000..95e66205 --- /dev/null +++ b/vfs/src/noop_backend.rs @@ -0,0 +1,36 @@ +use std::io; +use std::path::Path; + +use crate::{Metadata, ReadDir, VfsBackend}; + +pub struct NoopBackend; + +impl VfsBackend for NoopBackend { + fn read(&self, path: &Path) -> io::Result> { + Err(io::Error::new( + io::ErrorKind::Other, + "NoopBackend doesn't do anything", + )) + } + + fn write(&self, path: &Path, data: &[u8]) -> io::Result<()> { + Err(io::Error::new( + io::ErrorKind::Other, + "NoopBackend doesn't do anything", + )) + } + + fn read_dir(&self, path: &Path) -> io::Result { + Err(io::Error::new( + io::ErrorKind::Other, + "NoopBackend doesn't do anything", + )) + } + + fn metadata(&self, path: &Path) -> io::Result { + Err(io::Error::new( + io::ErrorKind::Other, + "NoopBackend doesn't do anything", + )) + } +} diff --git a/vfs/src/std_backend.rs b/vfs/src/std_backend.rs new file mode 100644 index 00000000..1e2d4f6d --- /dev/null +++ b/vfs/src/std_backend.rs @@ -0,0 +1,37 @@ +use std::fs; +use std::io; +use std::path::Path; + +use crate::{DirEntry, Metadata, ReadDir, VfsBackend}; + +pub struct StdBackend; + +impl VfsBackend for StdBackend { + fn read(&self, path: &Path) -> io::Result> { + fs::read(path) + } + + fn write(&self, path: &Path, data: &[u8]) -> io::Result<()> { + fs::write(path, data) + } + + fn read_dir(&self, path: &Path) -> io::Result { + let inner = fs::read_dir(path)?.map(|entry| { + Ok(DirEntry { + path: entry?.path(), + }) + }); + + Ok(ReadDir { + inner: Box::new(inner), + }) + } + + fn metadata(&self, path: &Path) -> io::Result { + let inner = fs::metadata(path)?; + + Ok(Metadata { + is_file: inner.is_file(), + }) + } +} From b4963f4ff7afaf9fb432a8ff7d2d8241ba6faae4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 18 Feb 2020 22:42:31 -0800 Subject: [PATCH 0943/1504] Watching --- vfs/src/lib.rs | 24 +++++++++++++++++------- vfs/src/noop_backend.rs | 29 +++++++++++++++++++++++++---- vfs/src/std_backend.rs | 41 ++++++++++++++++++++++++++++++++++++----- 3 files changed, 78 insertions(+), 16 deletions(-) diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index 7246111f..836e4443 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -8,11 +8,23 @@ use std::sync::{Arc, Mutex}; pub use noop_backend::NoopBackend; pub use std_backend::StdBackend; -pub trait VfsBackend { - fn read(&self, path: &Path) -> io::Result>; - fn write(&self, path: &Path, data: &[u8]) -> io::Result<()>; - fn read_dir(&self, path: &Path) -> io::Result; - fn metadata(&self, path: &Path) -> io::Result; +mod sealed { + use super::*; + + pub trait Sealed {} + + impl Sealed for NoopBackend {} + impl Sealed for StdBackend {} +} + +pub trait VfsBackend: sealed::Sealed { + fn read(&mut self, path: &Path) -> io::Result>; + fn write(&mut self, path: &Path, data: &[u8]) -> io::Result<()>; + fn read_dir(&mut self, path: &Path) -> io::Result; + fn metadata(&mut self, path: &Path) -> io::Result; + + fn watch(&mut self, path: &Path) -> io::Result<()>; + fn unwatch(&mut self, path: &Path) -> io::Result<()>; } pub struct DirEntry { @@ -52,7 +64,6 @@ impl Metadata { } struct VfsLock { - data: (), backend: Box, } @@ -86,7 +97,6 @@ pub struct Vfs { impl Vfs { pub fn new(backend: B) -> Self { let lock = VfsLock { - data: (), backend: Box::new(backend), }; diff --git a/vfs/src/noop_backend.rs b/vfs/src/noop_backend.rs index 95e66205..7b210f28 100644 --- a/vfs/src/noop_backend.rs +++ b/vfs/src/noop_backend.rs @@ -3,31 +3,52 @@ use std::path::Path; use crate::{Metadata, ReadDir, VfsBackend}; +#[non_exhaustive] pub struct NoopBackend; +impl NoopBackend { + pub fn new() -> Self { + Self + } +} + impl VfsBackend for NoopBackend { - fn read(&self, path: &Path) -> io::Result> { + fn read(&mut self, _path: &Path) -> io::Result> { Err(io::Error::new( io::ErrorKind::Other, "NoopBackend doesn't do anything", )) } - fn write(&self, path: &Path, data: &[u8]) -> io::Result<()> { + fn write(&mut self, _path: &Path, _data: &[u8]) -> io::Result<()> { Err(io::Error::new( io::ErrorKind::Other, "NoopBackend doesn't do anything", )) } - fn read_dir(&self, path: &Path) -> io::Result { + fn read_dir(&mut self, _path: &Path) -> io::Result { Err(io::Error::new( io::ErrorKind::Other, "NoopBackend doesn't do anything", )) } - fn metadata(&self, path: &Path) -> io::Result { + fn metadata(&mut self, _path: &Path) -> io::Result { + Err(io::Error::new( + io::ErrorKind::Other, + "NoopBackend doesn't do anything", + )) + } + + fn watch(&mut self, _path: &Path) -> io::Result<()> { + Err(io::Error::new( + io::ErrorKind::Other, + "NoopBackend doesn't do anything", + )) + } + + fn unwatch(&mut self, _path: &Path) -> io::Result<()> { Err(io::Error::new( io::ErrorKind::Other, "NoopBackend doesn't do anything", diff --git a/vfs/src/std_backend.rs b/vfs/src/std_backend.rs index 1e2d4f6d..940b7b8f 100644 --- a/vfs/src/std_backend.rs +++ b/vfs/src/std_backend.rs @@ -1,21 +1,40 @@ use std::fs; use std::io; use std::path::Path; +use std::sync::mpsc; +use std::time::Duration; + +use notify::{watcher, DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; use crate::{DirEntry, Metadata, ReadDir, VfsBackend}; -pub struct StdBackend; +pub struct StdBackend { + watcher: RecommendedWatcher, + watcher_receiver: mpsc::Receiver, +} + +impl StdBackend { + pub fn new() -> StdBackend { + let (tx, rx) = mpsc::channel(); + let watcher = watcher(tx, Duration::from_millis(50)).unwrap(); + + Self { + watcher, + watcher_receiver: rx, + } + } +} impl VfsBackend for StdBackend { - fn read(&self, path: &Path) -> io::Result> { + fn read(&mut self, path: &Path) -> io::Result> { fs::read(path) } - fn write(&self, path: &Path, data: &[u8]) -> io::Result<()> { + fn write(&mut self, path: &Path, data: &[u8]) -> io::Result<()> { fs::write(path, data) } - fn read_dir(&self, path: &Path) -> io::Result { + fn read_dir(&mut self, path: &Path) -> io::Result { let inner = fs::read_dir(path)?.map(|entry| { Ok(DirEntry { path: entry?.path(), @@ -27,11 +46,23 @@ impl VfsBackend for StdBackend { }) } - fn metadata(&self, path: &Path) -> io::Result { + fn metadata(&mut self, path: &Path) -> io::Result { let inner = fs::metadata(path)?; Ok(Metadata { is_file: inner.is_file(), }) } + + fn watch(&mut self, path: &Path) -> io::Result<()> { + self.watcher + .watch(path, RecursiveMode::NonRecursive) + .map_err(|inner| io::Error::new(io::ErrorKind::Other, inner)) + } + + fn unwatch(&mut self, path: &Path) -> io::Result<()> { + self.watcher + .unwatch(path) + .map_err(|inner| io::Error::new(io::ErrorKind::Other, inner)) + } } From 52e1dbd846f201f4729cb34aead4f28dbed3d516 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 18 Feb 2020 23:16:56 -0800 Subject: [PATCH 0944/1504] Flesh out crate --- Cargo.lock | 1 + vfs/Cargo.toml | 4 ++++ vfs/LICENSE.txt | 7 +++++++ vfs/README.md | 5 +++++ vfs/src/lib.rs | 36 ++++++++++++++++++++++++++++++++++++ vfs/src/noop_backend.rs | 7 ++++++- vfs/src/std_backend.rs | 40 ++++++++++++++++++++++++++++++++++++---- 7 files changed, 95 insertions(+), 5 deletions(-) create mode 100644 vfs/LICENSE.txt create mode 100644 vfs/README.md diff --git a/Cargo.lock b/Cargo.lock index d77b059b..a6266d51 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2362,6 +2362,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "vfs" version = "0.1.0" dependencies = [ + "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/vfs/Cargo.toml b/vfs/Cargo.toml index b6eabf28..38b7cbfd 100644 --- a/vfs/Cargo.toml +++ b/vfs/Cargo.toml @@ -3,8 +3,12 @@ name = "vfs" version = "0.1.0" authors = ["Lucien Greathouse "] edition = "2018" +readme = "README.md" +license = "MIT" +homepage = "https://github.com/rojo-rbx/rojo" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] notify = "4.0.15" +crossbeam-channel = "0.4.0" diff --git a/vfs/LICENSE.txt b/vfs/LICENSE.txt new file mode 100644 index 00000000..a4be86a1 --- /dev/null +++ b/vfs/LICENSE.txt @@ -0,0 +1,7 @@ +Copyright 2020 The Rojo Developers + +Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. \ No newline at end of file diff --git a/vfs/README.md b/vfs/README.md new file mode 100644 index 00000000..981daa26 --- /dev/null +++ b/vfs/README.md @@ -0,0 +1,5 @@ +# [vfs] +Name pending. Implementation of a virtual filesystem with a configurable backend and file watching. + +## License +[vfs] is available under the terms of the MIT license. See [LICENSE.txt](LICENSE.txt) or for more details. \ No newline at end of file diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index 836e4443..f53dd4d8 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -17,12 +17,16 @@ mod sealed { impl Sealed for StdBackend {} } +/// Backend that can be used to create a +/// +/// This trait is sealed and cannot not be implemented outside this crate. pub trait VfsBackend: sealed::Sealed { fn read(&mut self, path: &Path) -> io::Result>; fn write(&mut self, path: &Path, data: &[u8]) -> io::Result<()>; fn read_dir(&mut self, path: &Path) -> io::Result; fn metadata(&mut self, path: &Path) -> io::Result; + fn event_receiver(&mut self) -> crossbeam_channel::Receiver; fn watch(&mut self, path: &Path) -> io::Result<()>; fn unwatch(&mut self, path: &Path) -> io::Result<()>; } @@ -49,6 +53,7 @@ impl Iterator for ReadDir { } } +#[derive(Debug)] pub struct Metadata { is_file: bool, } @@ -63,6 +68,14 @@ impl Metadata { } } +#[derive(Debug)] +#[non_exhaustive] +pub enum VfsEvent { + Create(PathBuf), + Write(PathBuf), + Remove(PathBuf), +} + struct VfsLock { backend: Box, } @@ -90,11 +103,18 @@ impl VfsLock { } } +/// A virtual filesystem with a configurable backend. pub struct Vfs { inner: Mutex, } impl Vfs { + /// Creates a new `Vfs` with the default backend, `StdBackend`. + pub fn new_default() -> Self { + Self::new(StdBackend::new()) + } + + /// Creates a new `Vfs` with the given backend. pub fn new(backend: B) -> Self { let lock = VfsLock { backend: Box::new(backend), @@ -105,12 +125,23 @@ impl Vfs { } } + /// Read a file from the VFS, or the underlying backend if it isn't + /// resident. + /// + /// Roughly equivalent to [`std::fs::read`][std::fs::read]. + /// + /// [std::fs::read]: https://doc.rust-lang.org/stable/std/fs/fn.read.html pub fn read>(&self, path: P) -> io::Result>> { let path = path.as_ref(); let mut inner = self.inner.lock().unwrap(); inner.read(path) } + /// Write a file to the VFS and the underlying backend. + /// + /// Roughly equivalent to [`std::fs::write`][std::fs::write]. + /// + /// [std::fs::write]: https://doc.rust-lang.org/stable/std/fs/fn.write.html pub fn write, C: AsRef<[u8]>>(&self, path: P, contents: C) -> io::Result<()> { let path = path.as_ref(); let contents = contents.as_ref(); @@ -118,6 +149,11 @@ impl Vfs { inner.write(path, contents) } + /// Read all of the children of a directory. + /// + /// Roughly equivalent to [`std::fs::read_dir`][std::fs::read_dir]. + /// + /// [std::fs::read_dir]: https://doc.rust-lang.org/stable/std/fs/fn.read_dir.html pub fn read_dir>(&self, path: P) -> io::Result { let path = path.as_ref(); let mut inner = self.inner.lock().unwrap(); diff --git a/vfs/src/noop_backend.rs b/vfs/src/noop_backend.rs index 7b210f28..5d73bd1d 100644 --- a/vfs/src/noop_backend.rs +++ b/vfs/src/noop_backend.rs @@ -1,8 +1,9 @@ use std::io; use std::path::Path; -use crate::{Metadata, ReadDir, VfsBackend}; +use crate::{Metadata, ReadDir, VfsBackend, VfsEvent}; +/// `VfsBackend` that returns an error on every operation. #[non_exhaustive] pub struct NoopBackend; @@ -41,6 +42,10 @@ impl VfsBackend for NoopBackend { )) } + fn event_receiver(&mut self) -> crossbeam_channel::Receiver { + crossbeam_channel::never() + } + fn watch(&mut self, _path: &Path) -> io::Result<()> { Err(io::Error::new( io::ErrorKind::Other, diff --git a/vfs/src/std_backend.rs b/vfs/src/std_backend.rs index 940b7b8f..d42d8d6c 100644 --- a/vfs/src/std_backend.rs +++ b/vfs/src/std_backend.rs @@ -2,21 +2,49 @@ use std::fs; use std::io; use std::path::Path; use std::sync::mpsc; +use std::thread; use std::time::Duration; +use crossbeam_channel::Receiver; use notify::{watcher, DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; -use crate::{DirEntry, Metadata, ReadDir, VfsBackend}; +use crate::{DirEntry, Metadata, ReadDir, VfsBackend, VfsEvent}; +/// `VfsBackend` that uses `std::fs` and the `notify` crate. pub struct StdBackend { watcher: RecommendedWatcher, - watcher_receiver: mpsc::Receiver, + watcher_receiver: Receiver, } impl StdBackend { pub fn new() -> StdBackend { - let (tx, rx) = mpsc::channel(); - let watcher = watcher(tx, Duration::from_millis(50)).unwrap(); + let (notify_tx, notify_rx) = mpsc::channel(); + let watcher = watcher(notify_tx, Duration::from_millis(50)).unwrap(); + + let (tx, rx) = crossbeam_channel::unbounded(); + + thread::spawn(move || { + for event in notify_rx { + match event { + DebouncedEvent::Create(path) => { + tx.send(VfsEvent::Create(path))?; + } + DebouncedEvent::Write(path) => { + tx.send(VfsEvent::Write(path))?; + } + DebouncedEvent::Remove(path) => { + tx.send(VfsEvent::Remove(path))?; + } + DebouncedEvent::Rename(from, to) => { + tx.send(VfsEvent::Remove(from))?; + tx.send(VfsEvent::Create(to))?; + } + _ => {} + } + } + + Result::<(), crossbeam_channel::SendError>::Ok(()) + }); Self { watcher, @@ -54,6 +82,10 @@ impl VfsBackend for StdBackend { }) } + fn event_receiver(&mut self) -> crossbeam_channel::Receiver { + self.watcher_receiver.clone() + } + fn watch(&mut self, path: &Path) -> io::Result<()> { self.watcher .watch(path, RecursiveMode::NonRecursive) From 339e1060b7183cfa13ea886639069fbd2bd639ad Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 19 Feb 2020 09:17:21 -0800 Subject: [PATCH 0945/1504] Clean up Vfs methods that defer to VfsLock --- vfs/src/lib.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index f53dd4d8..19b76a6e 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -133,8 +133,7 @@ impl Vfs { /// [std::fs::read]: https://doc.rust-lang.org/stable/std/fs/fn.read.html pub fn read>(&self, path: P) -> io::Result>> { let path = path.as_ref(); - let mut inner = self.inner.lock().unwrap(); - inner.read(path) + self.inner.lock().unwrap().read(path) } /// Write a file to the VFS and the underlying backend. @@ -145,8 +144,7 @@ impl Vfs { pub fn write, C: AsRef<[u8]>>(&self, path: P, contents: C) -> io::Result<()> { let path = path.as_ref(); let contents = contents.as_ref(); - let mut inner = self.inner.lock().unwrap(); - inner.write(path, contents) + self.inner.lock().unwrap().write(path, contents) } /// Read all of the children of a directory. @@ -156,7 +154,6 @@ impl Vfs { /// [std::fs::read_dir]: https://doc.rust-lang.org/stable/std/fs/fn.read_dir.html pub fn read_dir>(&self, path: P) -> io::Result { let path = path.as_ref(); - let mut inner = self.inner.lock().unwrap(); - inner.read_dir(path) + self.inner.lock().unwrap().read_dir(path) } } From 89b5d9294c248f5b178fc81da6b89794c2205e91 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 19 Feb 2020 09:36:38 -0800 Subject: [PATCH 0946/1504] Event receiving/committing infrastructure --- vfs/src/lib.rs | 21 ++++++++++++++++++++- vfs/src/noop_backend.rs | 2 +- vfs/src/std_backend.rs | 2 +- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index 19b76a6e..c2f434e4 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -26,7 +26,7 @@ pub trait VfsBackend: sealed::Sealed { fn read_dir(&mut self, path: &Path) -> io::Result; fn metadata(&mut self, path: &Path) -> io::Result; - fn event_receiver(&mut self) -> crossbeam_channel::Receiver; + fn event_receiver(&self) -> crossbeam_channel::Receiver; fn watch(&mut self, path: &Path) -> io::Result<()>; fn unwatch(&mut self, path: &Path) -> io::Result<()>; } @@ -101,6 +101,15 @@ impl VfsLock { let path = path.as_ref(); self.backend.read_dir(path) } + + pub fn event_receiver(&self) -> crossbeam_channel::Receiver { + self.backend.event_receiver() + } + + pub fn commit_event(&mut self, _event: &VfsEvent) -> io::Result<()> { + // Because we hold no state, there's no cache to update here. + Ok(()) + } } /// A virtual filesystem with a configurable backend. @@ -156,4 +165,14 @@ impl Vfs { let path = path.as_ref(); self.inner.lock().unwrap().read_dir(path) } + + /// Retrieve a handle to the event receiver for this `Vfs`. + pub fn event_receiver(&self) -> crossbeam_channel::Receiver { + self.inner.lock().unwrap().event_receiver() + } + + /// Commit an event to this `Vfs`. + pub fn commit_event(&self, event: &VfsEvent) -> io::Result<()> { + self.inner.lock().unwrap().commit_event(event) + } } diff --git a/vfs/src/noop_backend.rs b/vfs/src/noop_backend.rs index 5d73bd1d..b28103ab 100644 --- a/vfs/src/noop_backend.rs +++ b/vfs/src/noop_backend.rs @@ -42,7 +42,7 @@ impl VfsBackend for NoopBackend { )) } - fn event_receiver(&mut self) -> crossbeam_channel::Receiver { + fn event_receiver(&self) -> crossbeam_channel::Receiver { crossbeam_channel::never() } diff --git a/vfs/src/std_backend.rs b/vfs/src/std_backend.rs index d42d8d6c..d0236c8c 100644 --- a/vfs/src/std_backend.rs +++ b/vfs/src/std_backend.rs @@ -82,7 +82,7 @@ impl VfsBackend for StdBackend { }) } - fn event_receiver(&mut self) -> crossbeam_channel::Receiver { + fn event_receiver(&self) -> crossbeam_channel::Receiver { self.watcher_receiver.clone() } From c7510e12c4db39f0bc90c336067d54d666f0b67c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 19 Feb 2020 09:39:49 -0800 Subject: [PATCH 0947/1504] Removal API --- vfs/src/lib.rs | 7 ++++++- vfs/src/noop_backend.rs | 14 ++++++++++++++ vfs/src/std_backend.rs | 8 ++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index c2f434e4..d9fe2f38 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -25,6 +25,8 @@ pub trait VfsBackend: sealed::Sealed { fn write(&mut self, path: &Path, data: &[u8]) -> io::Result<()>; fn read_dir(&mut self, path: &Path) -> io::Result; fn metadata(&mut self, path: &Path) -> io::Result; + fn remove_file(&mut self, path: &Path) -> io::Result<()>; + fn remove_dir_all(&mut self, path: &Path) -> io::Result<()>; fn event_receiver(&self) -> crossbeam_channel::Receiver; fn watch(&mut self, path: &Path) -> io::Result<()>; @@ -84,6 +86,7 @@ impl VfsLock { pub fn read>(&mut self, path: P) -> io::Result>> { let path = path.as_ref(); let contents = self.backend.read(path)?; + self.backend.watch(path)?; Ok(Arc::new(contents)) } @@ -99,7 +102,9 @@ impl VfsLock { pub fn read_dir>(&mut self, path: P) -> io::Result { let path = path.as_ref(); - self.backend.read_dir(path) + let dir = self.backend.read_dir(path)?; + self.backend.watch(path)?; + Ok(dir) } pub fn event_receiver(&self) -> crossbeam_channel::Receiver { diff --git a/vfs/src/noop_backend.rs b/vfs/src/noop_backend.rs index b28103ab..383119c5 100644 --- a/vfs/src/noop_backend.rs +++ b/vfs/src/noop_backend.rs @@ -35,6 +35,20 @@ impl VfsBackend for NoopBackend { )) } + fn remove_file(&mut self, _path: &Path) -> io::Result<()> { + Err(io::Error::new( + io::ErrorKind::Other, + "NoopBackend doesn't do anything", + )) + } + + fn remove_dir_all(&mut self, _path: &Path) -> io::Result<()> { + Err(io::Error::new( + io::ErrorKind::Other, + "NoopBackend doesn't do anything", + )) + } + fn metadata(&mut self, _path: &Path) -> io::Result { Err(io::Error::new( io::ErrorKind::Other, diff --git a/vfs/src/std_backend.rs b/vfs/src/std_backend.rs index d0236c8c..fa0857b8 100644 --- a/vfs/src/std_backend.rs +++ b/vfs/src/std_backend.rs @@ -74,6 +74,14 @@ impl VfsBackend for StdBackend { }) } + fn remove_file(&mut self, path: &Path) -> io::Result<()> { + fs::remove_file(path) + } + + fn remove_dir_all(&mut self, path: &Path) -> io::Result<()> { + fs::remove_dir_all(path) + } + fn metadata(&mut self, path: &Path) -> io::Result { let inner = fs::metadata(path)?; From 7ea9a1e3e811565289b51c424f8e4e49c7354db0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 19 Feb 2020 09:43:39 -0800 Subject: [PATCH 0948/1504] Expose metadata, remove_file, and remove_dir_all --- vfs/src/lib.rs | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index d9fe2f38..e8f2d088 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -107,6 +107,23 @@ impl VfsLock { Ok(dir) } + pub fn remove_file>(&mut self, path: P) -> io::Result<()> { + let path = path.as_ref(); + let _ = self.backend.unwatch(path); + self.backend.remove_file(path) + } + + pub fn remove_dir_all>(&mut self, path: P) -> io::Result<()> { + let path = path.as_ref(); + let _ = self.backend.unwatch(path); + self.backend.remove_dir_all(path) + } + + pub fn metadata>(&mut self, path: P) -> io::Result { + let path = path.as_ref(); + self.backend.metadata(path) + } + pub fn event_receiver(&self) -> crossbeam_channel::Receiver { self.backend.event_receiver() } @@ -171,6 +188,36 @@ impl Vfs { self.inner.lock().unwrap().read_dir(path) } + /// Remove a file. + /// + /// Roughly equivalent to [`std::fs::remove_file`][std::fs::remove_file]. + /// + /// [std::fs::remove_file]: https://doc.rust-lang.org/stable/std/fs/fn.remove_file.html + pub fn remove_file>(&mut self, path: P) -> io::Result<()> { + let path = path.as_ref(); + self.inner.lock().unwrap().remove_file(path) + } + + /// Remove a directory and all of its descendants. + /// + /// Roughly equivalent to [`std::fs::remove_dir_all`][std::fs::remove_dir_all]. + /// + /// [std::fs::remove_dir_all]: https://doc.rust-lang.org/stable/std/fs/fn.remove_dir_all.html + pub fn remove_dir_all>(&mut self, path: P) -> io::Result<()> { + let path = path.as_ref(); + self.inner.lock().unwrap().remove_dir_all(path) + } + + /// Query metadata about the given path. + /// + /// Roughly equivalent to [`std::fs::metadata`][std::fs::metadata]. + /// + /// [std::fs::metadata]: https://doc.rust-lang.org/stable/std/fs/fn.metadata.html + pub fn metadata>(&mut self, path: P) -> io::Result { + let path = path.as_ref(); + self.inner.lock().unwrap().metadata(path) + } + /// Retrieve a handle to the event receiver for this `Vfs`. pub fn event_receiver(&self) -> crossbeam_channel::Receiver { self.inner.lock().unwrap().event_receiver() From 4f46012c11ae5ed9f77b0e481e3da306c6ac66bf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 19 Feb 2020 09:49:18 -0800 Subject: [PATCH 0949/1504] Complete an unfinished --- vfs/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index e8f2d088..a7be30ee 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -17,7 +17,7 @@ mod sealed { impl Sealed for StdBackend {} } -/// Backend that can be used to create a +/// Backend that can be used to create a `Vfs`. /// /// This trait is sealed and cannot not be implemented outside this crate. pub trait VfsBackend: sealed::Sealed { From 57263905e76f994cc02afaa817815bce928be5a8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 19 Feb 2020 10:11:43 -0800 Subject: [PATCH 0950/1504] Add IoResultExt, fix mutability and Send-ness --- vfs/src/lib.rs | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index a7be30ee..c4423244 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -17,10 +17,29 @@ mod sealed { impl Sealed for StdBackend {} } +pub trait IoResultExt { + fn with_not_found(self) -> io::Result>; +} + +impl IoResultExt for io::Result { + fn with_not_found(self) -> io::Result> { + match self { + Ok(v) => Ok(Some(v)), + Err(err) => { + if err.kind() == io::ErrorKind::NotFound { + Ok(None) + } else { + Err(err) + } + } + } + } +} + /// Backend that can be used to create a `Vfs`. /// /// This trait is sealed and cannot not be implemented outside this crate. -pub trait VfsBackend: sealed::Sealed { +pub trait VfsBackend: sealed::Sealed + Send + 'static { fn read(&mut self, path: &Path) -> io::Result>; fn write(&mut self, path: &Path, data: &[u8]) -> io::Result<()>; fn read_dir(&mut self, path: &Path) -> io::Result; @@ -146,7 +165,7 @@ impl Vfs { } /// Creates a new `Vfs` with the given backend. - pub fn new(backend: B) -> Self { + pub fn new(backend: B) -> Self { let lock = VfsLock { backend: Box::new(backend), }; @@ -193,7 +212,7 @@ impl Vfs { /// Roughly equivalent to [`std::fs::remove_file`][std::fs::remove_file]. /// /// [std::fs::remove_file]: https://doc.rust-lang.org/stable/std/fs/fn.remove_file.html - pub fn remove_file>(&mut self, path: P) -> io::Result<()> { + pub fn remove_file>(&self, path: P) -> io::Result<()> { let path = path.as_ref(); self.inner.lock().unwrap().remove_file(path) } @@ -203,7 +222,7 @@ impl Vfs { /// Roughly equivalent to [`std::fs::remove_dir_all`][std::fs::remove_dir_all]. /// /// [std::fs::remove_dir_all]: https://doc.rust-lang.org/stable/std/fs/fn.remove_dir_all.html - pub fn remove_dir_all>(&mut self, path: P) -> io::Result<()> { + pub fn remove_dir_all>(&self, path: P) -> io::Result<()> { let path = path.as_ref(); self.inner.lock().unwrap().remove_dir_all(path) } @@ -213,7 +232,7 @@ impl Vfs { /// Roughly equivalent to [`std::fs::metadata`][std::fs::metadata]. /// /// [std::fs::metadata]: https://doc.rust-lang.org/stable/std/fs/fn.metadata.html - pub fn metadata>(&mut self, path: P) -> io::Result { + pub fn metadata>(&self, path: P) -> io::Result { let path = path.as_ref(); self.inner.lock().unwrap().metadata(path) } From 3a029caf2b189260afb1db794ce17fc9dc73b0f5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 19 Feb 2020 23:22:51 -0800 Subject: [PATCH 0951/1504] Bump MSRV to 1.40.0 --- .github/workflows/ci.yml | 2 +- README.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8c8b8660..6ad5b6e1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,7 +9,7 @@ jobs: strategy: matrix: - rust_version: [stable, "1.36.0"] + rust_version: [stable, "1.40.0"] steps: - uses: actions/checkout@v1 diff --git a/README.md b/README.md index cd71f8c7..bdbabc63 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions fo Pull requests are welcome! -Rojo supports Rust 1.36.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. +Rojo supports Rust 1.40.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. ## License Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file From 00a29bb6be6c5ad2c8aa469436471ff66de72c1b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 19 Feb 2020 23:32:46 -0800 Subject: [PATCH 0952/1504] Unwatch paths when they're reported as removed --- vfs/src/lib.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index c4423244..40b8979c 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -147,8 +147,14 @@ impl VfsLock { self.backend.event_receiver() } - pub fn commit_event(&mut self, _event: &VfsEvent) -> io::Result<()> { - // Because we hold no state, there's no cache to update here. + pub fn commit_event(&mut self, event: &VfsEvent) -> io::Result<()> { + match event { + VfsEvent::Remove(path) => { + let _ = self.backend.unwatch(&path); + } + _ => {} + } + Ok(()) } } From 6322c1f46de649da14d51486fee6656e761d5381 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 19 Feb 2020 23:35:45 -0800 Subject: [PATCH 0953/1504] vfs: Add stub MemoryBackend --- vfs/src/lib.rs | 3 ++ vfs/src/memory_backend.rs | 76 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 vfs/src/memory_backend.rs diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index 40b8979c..27a31a9d 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -1,3 +1,4 @@ +mod memory_backend; mod noop_backend; mod std_backend; @@ -5,6 +6,7 @@ use std::io; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex}; +pub use memory_backend::MemoryBackend; pub use noop_backend::NoopBackend; pub use std_backend::StdBackend; @@ -13,6 +15,7 @@ mod sealed { pub trait Sealed {} + impl Sealed for MemoryBackend {} impl Sealed for NoopBackend {} impl Sealed for StdBackend {} } diff --git a/vfs/src/memory_backend.rs b/vfs/src/memory_backend.rs new file mode 100644 index 00000000..d16cdd04 --- /dev/null +++ b/vfs/src/memory_backend.rs @@ -0,0 +1,76 @@ +use std::io; +use std::path::Path; + +use crate::{Metadata, ReadDir, VfsBackend, VfsEvent}; + +/// `VfsBackend` that reads from an in-memory filesystem. +#[non_exhaustive] +pub struct MemoryBackend; + +impl MemoryBackend { + pub fn new() -> Self { + Self + } +} + +impl VfsBackend for MemoryBackend { + fn read(&mut self, _path: &Path) -> io::Result> { + Err(io::Error::new( + io::ErrorKind::Other, + "MemoryBackend doesn't do anything", + )) + } + + fn write(&mut self, _path: &Path, _data: &[u8]) -> io::Result<()> { + Err(io::Error::new( + io::ErrorKind::Other, + "MemoryBackend doesn't do anything", + )) + } + + fn read_dir(&mut self, _path: &Path) -> io::Result { + Err(io::Error::new( + io::ErrorKind::Other, + "MemoryBackend doesn't do anything", + )) + } + + fn remove_file(&mut self, _path: &Path) -> io::Result<()> { + Err(io::Error::new( + io::ErrorKind::Other, + "MemoryBackend doesn't do anything", + )) + } + + fn remove_dir_all(&mut self, _path: &Path) -> io::Result<()> { + Err(io::Error::new( + io::ErrorKind::Other, + "MemoryBackend doesn't do anything", + )) + } + + fn metadata(&mut self, _path: &Path) -> io::Result { + Err(io::Error::new( + io::ErrorKind::Other, + "MemoryBackend doesn't do anything", + )) + } + + fn event_receiver(&self) -> crossbeam_channel::Receiver { + crossbeam_channel::never() + } + + fn watch(&mut self, _path: &Path) -> io::Result<()> { + Err(io::Error::new( + io::ErrorKind::Other, + "MemoryBackend doesn't do anything", + )) + } + + fn unwatch(&mut self, _path: &Path) -> io::Result<()> { + Err(io::Error::new( + io::ErrorKind::Other, + "MemoryBackend doesn't do anything", + )) + } +} From 1b24cd36e08e5f104a611025c9901094f8682e82 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 19 Feb 2020 23:58:09 -0800 Subject: [PATCH 0954/1504] vfs: Snapshots, roughly --- vfs/src/lib.rs | 2 ++ vfs/src/memory_backend.rs | 63 ++++++++++++++++++++++++++++++++++++--- vfs/src/snapshot.rs | 29 ++++++++++++++++++ 3 files changed, 90 insertions(+), 4 deletions(-) create mode 100644 vfs/src/snapshot.rs diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index 27a31a9d..8a59b7e0 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -1,5 +1,6 @@ mod memory_backend; mod noop_backend; +mod snapshot; mod std_backend; use std::io; @@ -8,6 +9,7 @@ use std::sync::{Arc, Mutex}; pub use memory_backend::MemoryBackend; pub use noop_backend::NoopBackend; +pub use snapshot::VfsSnapshot; pub use std_backend::StdBackend; mod sealed { diff --git a/vfs/src/memory_backend.rs b/vfs/src/memory_backend.rs index d16cdd04..4fe27269 100644 --- a/vfs/src/memory_backend.rs +++ b/vfs/src/memory_backend.rs @@ -1,16 +1,71 @@ +use std::collections::{BTreeSet, HashMap}; use std::io; -use std::path::Path; +use std::path::{Path, PathBuf}; -use crate::{Metadata, ReadDir, VfsBackend, VfsEvent}; +use crate::{Metadata, ReadDir, VfsBackend, VfsEvent, VfsSnapshot}; /// `VfsBackend` that reads from an in-memory filesystem. +#[derive(Debug)] #[non_exhaustive] -pub struct MemoryBackend; +pub struct MemoryBackend { + entries: HashMap, + orphans: BTreeSet, +} impl MemoryBackend { pub fn new() -> Self { - Self + Self { + entries: HashMap::new(), + orphans: BTreeSet::new(), + } } + + pub fn load_snapshot>(&mut self, path: P, snapshot: VfsSnapshot) { + let path = path.into(); + + if let Some(parent_path) = path.parent() { + if let Some(parent_entry) = self.entries.get_mut(parent_path) { + if let Entry::Dir { children } = parent_entry { + children.insert(path.clone()); + } else { + panic!( + "Tried to load snapshot as child of file, {}", + parent_path.display() + ); + } + } else { + self.orphans.insert(path.clone()); + } + } else { + self.orphans.insert(path.clone()); + } + + match snapshot { + VfsSnapshot::File { contents } => { + self.entries.insert(path, Entry::File { contents }); + } + VfsSnapshot::Dir { children } => { + self.entries.insert( + path.clone(), + Entry::Dir { + children: BTreeSet::new(), + }, + ); + + for (child_name, child) in children { + let full_path = path.join(child_name); + self.load_snapshot(full_path, child); + } + } + }; + } +} + +#[derive(Debug)] +enum Entry { + File { contents: Vec }, + + Dir { children: BTreeSet }, } impl VfsBackend for MemoryBackend { diff --git a/vfs/src/snapshot.rs b/vfs/src/snapshot.rs new file mode 100644 index 00000000..5ddb9363 --- /dev/null +++ b/vfs/src/snapshot.rs @@ -0,0 +1,29 @@ +use std::collections::BTreeMap; + +#[non_exhaustive] +pub enum VfsSnapshot { + File { + contents: Vec, + }, + + Dir { + children: BTreeMap, + }, +} + +impl VfsSnapshot { + pub fn file>>(contents: C) -> Self { + Self::File { + contents: contents.into(), + } + } + + pub fn dir, I: IntoIterator>(children: I) -> Self { + Self::Dir { + children: children + .into_iter() + .map(|(key, value)| (key.into(), value)) + .collect(), + } + } +} From fefc7a69cd0c5e08d67793d8c815848009a83f47 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 21 Feb 2020 23:34:56 -0800 Subject: [PATCH 0955/1504] vfs: Expand documentation --- vfs/src/lib.rs | 150 +++++++++++++++++++++++++++++++++----- vfs/src/memory_backend.rs | 4 +- 2 files changed, 135 insertions(+), 19 deletions(-) diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index 8a59b7e0..238c6d81 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -5,7 +5,7 @@ mod std_backend; use std::io; use std::path::{Path, PathBuf}; -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex, MutexGuard}; pub use memory_backend::MemoryBackend; pub use noop_backend::NoopBackend; @@ -15,6 +15,7 @@ pub use std_backend::StdBackend; mod sealed { use super::*; + /// Sealing trait for VfsBackend. pub trait Sealed {} impl Sealed for MemoryBackend {} @@ -22,6 +23,9 @@ mod sealed { impl Sealed for StdBackend {} } +/// Trait that transforms `io::Result` into `io::Result>`. +/// +/// `Ok(None)` takes the place of IO errors whose `io::ErrorKind` is `NotFound`. pub trait IoResultExt { fn with_not_found(self) -> io::Result>; } @@ -57,6 +61,9 @@ pub trait VfsBackend: sealed::Sealed + Send + 'static { fn unwatch(&mut self, path: &Path) -> io::Result<()>; } +/// Vfs equivalent to [`std::fs::DirEntry`][std::fs::DirEntry]. +/// +/// [std::fs::DirEntry]: https://doc.rust-lang.org/stable/std/fs/struct.DirEntry.html pub struct DirEntry { path: PathBuf, } @@ -67,6 +74,9 @@ impl DirEntry { } } +/// Vfs equivalent to [`std::fs::ReadDir`][std::fs::ReadDir]. +/// +/// [std::fs::ReadDir]: https://doc.rust-lang.org/stable/std/fs/struct.ReadDir.html pub struct ReadDir { inner: Box>>, } @@ -79,6 +89,9 @@ impl Iterator for ReadDir { } } +/// Vfs equivalent to [`std::fs::Metadata`][std::fs::Metadata]. +/// +/// [std::fs::Metadata]: https://doc.rust-lang.org/stable/std/fs/struct.Metadata.html #[derive(Debug)] pub struct Metadata { is_file: bool, @@ -102,57 +115,55 @@ pub enum VfsEvent { Remove(PathBuf), } -struct VfsLock { +/// Contains implementation details of the Vfs, wrapped by `Vfs` and `VfsLock`, +/// the public interfaces to this type. +struct VfsInner { backend: Box, } -impl VfsLock { - pub fn read>(&mut self, path: P) -> io::Result>> { +impl VfsInner { + fn read>(&mut self, path: P) -> io::Result>> { let path = path.as_ref(); let contents = self.backend.read(path)?; self.backend.watch(path)?; Ok(Arc::new(contents)) } - pub fn write, C: AsRef<[u8]>>( - &mut self, - path: P, - contents: C, - ) -> io::Result<()> { + fn write, C: AsRef<[u8]>>(&mut self, path: P, contents: C) -> io::Result<()> { let path = path.as_ref(); let contents = contents.as_ref(); self.backend.write(path, contents) } - pub fn read_dir>(&mut self, path: P) -> io::Result { + fn read_dir>(&mut self, path: P) -> io::Result { let path = path.as_ref(); let dir = self.backend.read_dir(path)?; self.backend.watch(path)?; Ok(dir) } - pub fn remove_file>(&mut self, path: P) -> io::Result<()> { + fn remove_file>(&mut self, path: P) -> io::Result<()> { let path = path.as_ref(); let _ = self.backend.unwatch(path); self.backend.remove_file(path) } - pub fn remove_dir_all>(&mut self, path: P) -> io::Result<()> { + fn remove_dir_all>(&mut self, path: P) -> io::Result<()> { let path = path.as_ref(); let _ = self.backend.unwatch(path); self.backend.remove_dir_all(path) } - pub fn metadata>(&mut self, path: P) -> io::Result { + fn metadata>(&mut self, path: P) -> io::Result { let path = path.as_ref(); self.backend.metadata(path) } - pub fn event_receiver(&self) -> crossbeam_channel::Receiver { + fn event_receiver(&self) -> crossbeam_channel::Receiver { self.backend.event_receiver() } - pub fn commit_event(&mut self, event: &VfsEvent) -> io::Result<()> { + fn commit_event(&mut self, event: &VfsEvent) -> io::Result<()> { match event { VfsEvent::Remove(path) => { let _ = self.backend.unwatch(&path); @@ -166,7 +177,7 @@ impl VfsLock { /// A virtual filesystem with a configurable backend. pub struct Vfs { - inner: Mutex, + inner: Mutex, } impl Vfs { @@ -177,7 +188,7 @@ impl Vfs { /// Creates a new `Vfs` with the given backend. pub fn new(backend: B) -> Self { - let lock = VfsLock { + let lock = VfsInner { backend: Box::new(backend), }; @@ -186,12 +197,19 @@ impl Vfs { } } + pub fn lock(&self) -> VfsLock<'_> { + VfsLock { + inner: self.inner.lock().unwrap(), + } + } + /// Read a file from the VFS, or the underlying backend if it isn't /// resident. /// /// Roughly equivalent to [`std::fs::read`][std::fs::read]. /// /// [std::fs::read]: https://doc.rust-lang.org/stable/std/fs/fn.read.html + #[inline] pub fn read>(&self, path: P) -> io::Result>> { let path = path.as_ref(); self.inner.lock().unwrap().read(path) @@ -202,6 +220,7 @@ impl Vfs { /// Roughly equivalent to [`std::fs::write`][std::fs::write]. /// /// [std::fs::write]: https://doc.rust-lang.org/stable/std/fs/fn.write.html + #[inline] pub fn write, C: AsRef<[u8]>>(&self, path: P, contents: C) -> io::Result<()> { let path = path.as_ref(); let contents = contents.as_ref(); @@ -213,6 +232,7 @@ impl Vfs { /// Roughly equivalent to [`std::fs::read_dir`][std::fs::read_dir]. /// /// [std::fs::read_dir]: https://doc.rust-lang.org/stable/std/fs/fn.read_dir.html + #[inline] pub fn read_dir>(&self, path: P) -> io::Result { let path = path.as_ref(); self.inner.lock().unwrap().read_dir(path) @@ -223,6 +243,7 @@ impl Vfs { /// Roughly equivalent to [`std::fs::remove_file`][std::fs::remove_file]. /// /// [std::fs::remove_file]: https://doc.rust-lang.org/stable/std/fs/fn.remove_file.html + #[inline] pub fn remove_file>(&self, path: P) -> io::Result<()> { let path = path.as_ref(); self.inner.lock().unwrap().remove_file(path) @@ -233,6 +254,7 @@ impl Vfs { /// Roughly equivalent to [`std::fs::remove_dir_all`][std::fs::remove_dir_all]. /// /// [std::fs::remove_dir_all]: https://doc.rust-lang.org/stable/std/fs/fn.remove_dir_all.html + #[inline] pub fn remove_dir_all>(&self, path: P) -> io::Result<()> { let path = path.as_ref(); self.inner.lock().unwrap().remove_dir_all(path) @@ -243,18 +265,112 @@ impl Vfs { /// Roughly equivalent to [`std::fs::metadata`][std::fs::metadata]. /// /// [std::fs::metadata]: https://doc.rust-lang.org/stable/std/fs/fn.metadata.html + #[inline] pub fn metadata>(&self, path: P) -> io::Result { let path = path.as_ref(); self.inner.lock().unwrap().metadata(path) } /// Retrieve a handle to the event receiver for this `Vfs`. + #[inline] pub fn event_receiver(&self) -> crossbeam_channel::Receiver { self.inner.lock().unwrap().event_receiver() } /// Commit an event to this `Vfs`. + #[inline] pub fn commit_event(&self, event: &VfsEvent) -> io::Result<()> { self.inner.lock().unwrap().commit_event(event) } } + +/// A locked handle to a `Vfs`, created by `Vfs::lock`. +pub struct VfsLock<'a> { + inner: MutexGuard<'a, VfsInner>, +} + +impl VfsLock<'_> { + /// Read a file from the VFS, or the underlying backend if it isn't + /// resident. + /// + /// Roughly equivalent to [`std::fs::read`][std::fs::read]. + /// + /// [std::fs::read]: https://doc.rust-lang.org/stable/std/fs/fn.read.html + #[inline] + pub fn read>(&mut self, path: P) -> io::Result>> { + let path = path.as_ref(); + self.inner.read(path) + } + + /// Write a file to the VFS and the underlying backend. + /// + /// Roughly equivalent to [`std::fs::write`][std::fs::write]. + /// + /// [std::fs::write]: https://doc.rust-lang.org/stable/std/fs/fn.write.html + #[inline] + pub fn write, C: AsRef<[u8]>>( + &mut self, + path: P, + contents: C, + ) -> io::Result<()> { + let path = path.as_ref(); + let contents = contents.as_ref(); + self.inner.write(path, contents) + } + + /// Read all of the children of a directory. + /// + /// Roughly equivalent to [`std::fs::read_dir`][std::fs::read_dir]. + /// + /// [std::fs::read_dir]: https://doc.rust-lang.org/stable/std/fs/fn.read_dir.html + #[inline] + pub fn read_dir>(&mut self, path: P) -> io::Result { + let path = path.as_ref(); + self.inner.read_dir(path) + } + + /// Remove a file. + /// + /// Roughly equivalent to [`std::fs::remove_file`][std::fs::remove_file]. + /// + /// [std::fs::remove_file]: https://doc.rust-lang.org/stable/std/fs/fn.remove_file.html + #[inline] + pub fn remove_file>(&mut self, path: P) -> io::Result<()> { + let path = path.as_ref(); + self.inner.remove_file(path) + } + + /// Remove a directory and all of its descendants. + /// + /// Roughly equivalent to [`std::fs::remove_dir_all`][std::fs::remove_dir_all]. + /// + /// [std::fs::remove_dir_all]: https://doc.rust-lang.org/stable/std/fs/fn.remove_dir_all.html + #[inline] + pub fn remove_dir_all>(&mut self, path: P) -> io::Result<()> { + let path = path.as_ref(); + self.inner.remove_dir_all(path) + } + + /// Query metadata about the given path. + /// + /// Roughly equivalent to [`std::fs::metadata`][std::fs::metadata]. + /// + /// [std::fs::metadata]: https://doc.rust-lang.org/stable/std/fs/fn.metadata.html + #[inline] + pub fn metadata>(&mut self, path: P) -> io::Result { + let path = path.as_ref(); + self.inner.metadata(path) + } + + /// Retrieve a handle to the event receiver for this `Vfs`. + #[inline] + pub fn event_receiver(&self) -> crossbeam_channel::Receiver { + self.inner.event_receiver() + } + + /// Commit an event to this `Vfs`. + #[inline] + pub fn commit_event(&mut self, event: &VfsEvent) -> io::Result<()> { + self.inner.commit_event(event) + } +} diff --git a/vfs/src/memory_backend.rs b/vfs/src/memory_backend.rs index 4fe27269..f1b66788 100644 --- a/vfs/src/memory_backend.rs +++ b/vfs/src/memory_backend.rs @@ -4,9 +4,9 @@ use std::path::{Path, PathBuf}; use crate::{Metadata, ReadDir, VfsBackend, VfsEvent, VfsSnapshot}; -/// `VfsBackend` that reads from an in-memory filesystem. +/// `VfsBackend` that reads from an in-memory filesystem, intended for setting +/// up testing scenarios quickly. #[derive(Debug)] -#[non_exhaustive] pub struct MemoryBackend { entries: HashMap, orphans: BTreeSet, From bb2dcbaea0745b93f838870465abb1db7db4c4bb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 21 Feb 2020 23:52:11 -0800 Subject: [PATCH 0956/1504] vfs: Flesh out MemoryBackend --- vfs/src/lib.rs | 6 +- vfs/src/memory_backend.rs | 153 ++++++++++++++++++++++++++------------ 2 files changed, 109 insertions(+), 50 deletions(-) diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index 238c6d81..6105a033 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -65,7 +65,7 @@ pub trait VfsBackend: sealed::Sealed + Send + 'static { /// /// [std::fs::DirEntry]: https://doc.rust-lang.org/stable/std/fs/struct.DirEntry.html pub struct DirEntry { - path: PathBuf, + pub(crate) path: PathBuf, } impl DirEntry { @@ -78,7 +78,7 @@ impl DirEntry { /// /// [std::fs::ReadDir]: https://doc.rust-lang.org/stable/std/fs/struct.ReadDir.html pub struct ReadDir { - inner: Box>>, + pub(crate) inner: Box>>, } impl Iterator for ReadDir { @@ -94,7 +94,7 @@ impl Iterator for ReadDir { /// [std::fs::Metadata]: https://doc.rust-lang.org/stable/std/fs/struct.Metadata.html #[derive(Debug)] pub struct Metadata { - is_file: bool, + pub(crate) is_file: bool, } impl Metadata { diff --git a/vfs/src/memory_backend.rs b/vfs/src/memory_backend.rs index f1b66788..b7c8ac13 100644 --- a/vfs/src/memory_backend.rs +++ b/vfs/src/memory_backend.rs @@ -1,8 +1,8 @@ -use std::collections::{BTreeSet, HashMap}; +use std::collections::{BTreeSet, HashMap, VecDeque}; use std::io; use std::path::{Path, PathBuf}; -use crate::{Metadata, ReadDir, VfsBackend, VfsEvent, VfsSnapshot}; +use crate::{DirEntry, Metadata, ReadDir, VfsBackend, VfsEvent, VfsSnapshot}; /// `VfsBackend` that reads from an in-memory filesystem, intended for setting /// up testing scenarios quickly. @@ -20,7 +20,11 @@ impl MemoryBackend { } } - pub fn load_snapshot>(&mut self, path: P, snapshot: VfsSnapshot) { + pub fn load_snapshot>( + &mut self, + path: P, + snapshot: VfsSnapshot, + ) -> io::Result<()> { let path = path.into(); if let Some(parent_path) = path.parent() { @@ -28,10 +32,7 @@ impl MemoryBackend { if let Entry::Dir { children } = parent_entry { children.insert(path.clone()); } else { - panic!( - "Tried to load snapshot as child of file, {}", - parent_path.display() - ); + return must_be_dir(parent_path); } } else { self.orphans.insert(path.clone()); @@ -54,10 +55,25 @@ impl MemoryBackend { for (child_name, child) in children { let full_path = path.join(child_name); - self.load_snapshot(full_path, child); + self.load_snapshot(full_path, child)?; } } - }; + } + + Ok(()) + } + + fn remove(&mut self, root_path: PathBuf) { + self.orphans.remove(&root_path); + + let mut to_remove = VecDeque::new(); + to_remove.push_back(root_path); + + while let Some(path) = to_remove.pop_front() { + if let Some(Entry::Dir { children }) = self.entries.remove(&path) { + to_remove.extend(children); + } + } } } @@ -69,46 +85,68 @@ enum Entry { } impl VfsBackend for MemoryBackend { - fn read(&mut self, _path: &Path) -> io::Result> { - Err(io::Error::new( - io::ErrorKind::Other, - "MemoryBackend doesn't do anything", - )) + fn read(&mut self, path: &Path) -> io::Result> { + match self.entries.get(path) { + Some(Entry::File { contents }) => Ok(contents.clone()), + Some(Entry::Dir { .. }) => must_be_file(path), + None => not_found(path), + } } - fn write(&mut self, _path: &Path, _data: &[u8]) -> io::Result<()> { - Err(io::Error::new( - io::ErrorKind::Other, - "MemoryBackend doesn't do anything", - )) + fn write(&mut self, path: &Path, data: &[u8]) -> io::Result<()> { + self.load_snapshot( + path, + VfsSnapshot::File { + contents: data.to_owned(), + }, + ) } - fn read_dir(&mut self, _path: &Path) -> io::Result { - Err(io::Error::new( - io::ErrorKind::Other, - "MemoryBackend doesn't do anything", - )) + fn read_dir(&mut self, path: &Path) -> io::Result { + match self.entries.get(path) { + Some(Entry::Dir { children }) => { + let iter = children + .clone() + .into_iter() + .map(|path| Ok(DirEntry { path })); + + Ok(ReadDir { + inner: Box::new(iter), + }) + } + Some(Entry::File { .. }) => must_be_dir(path), + None => not_found(path), + } } - fn remove_file(&mut self, _path: &Path) -> io::Result<()> { - Err(io::Error::new( - io::ErrorKind::Other, - "MemoryBackend doesn't do anything", - )) + fn remove_file(&mut self, path: &Path) -> io::Result<()> { + match self.entries.get(path) { + Some(Entry::File { .. }) => { + self.remove(path.to_owned()); + Ok(()) + } + Some(Entry::Dir { .. }) => must_be_file(path), + None => not_found(path), + } } - fn remove_dir_all(&mut self, _path: &Path) -> io::Result<()> { - Err(io::Error::new( - io::ErrorKind::Other, - "MemoryBackend doesn't do anything", - )) + fn remove_dir_all(&mut self, path: &Path) -> io::Result<()> { + match self.entries.get(path) { + Some(Entry::Dir { .. }) => { + self.remove(path.to_owned()); + Ok(()) + } + Some(Entry::File { .. }) => must_be_dir(path), + None => not_found(path), + } } - fn metadata(&mut self, _path: &Path) -> io::Result { - Err(io::Error::new( - io::ErrorKind::Other, - "MemoryBackend doesn't do anything", - )) + fn metadata(&mut self, path: &Path) -> io::Result { + match self.entries.get(path) { + Some(Entry::File { .. }) => Ok(Metadata { is_file: true }), + Some(Entry::Dir { .. }) => Ok(Metadata { is_file: false }), + None => not_found(path), + } } fn event_receiver(&self) -> crossbeam_channel::Receiver { @@ -116,16 +154,37 @@ impl VfsBackend for MemoryBackend { } fn watch(&mut self, _path: &Path) -> io::Result<()> { - Err(io::Error::new( - io::ErrorKind::Other, - "MemoryBackend doesn't do anything", - )) + Ok(()) } fn unwatch(&mut self, _path: &Path) -> io::Result<()> { - Err(io::Error::new( - io::ErrorKind::Other, - "MemoryBackend doesn't do anything", - )) + Ok(()) } } + +fn must_be_file(path: &Path) -> io::Result { + Err(io::Error::new( + io::ErrorKind::Other, + format!( + "path {} was a directory, but must be a file", + path.display() + ), + )) +} + +fn must_be_dir(path: &Path) -> io::Result { + Err(io::Error::new( + io::ErrorKind::Other, + format!( + "path {} was a file, but must be a directory", + path.display() + ), + )) +} + +fn not_found(path: &Path) -> io::Result { + Err(io::Error::new( + io::ErrorKind::NotFound, + format!("path {} not found", path.display()), + )) +} From e86e3316a946af4ef49e03d1fddb273461584c0c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 26 Feb 2020 17:56:33 -0800 Subject: [PATCH 0957/1504] Update changelog to include 0.5.x versions --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ab7b812a..743bdd1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,12 @@ * Added "error" state to show errors in a place that isn't the output panel. * Improved diagnostics for when the Rojo plugin cannot create an instance. +## [0.5.3](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.3) (October 15, 2019) +* Fixed an issue where Rojo would throw an error when encountering recently-added instance classes. + +## [0.5.2](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.2) (October 14, 2019) +* Fixed an issue where `LocalizationTable` instances would have their column order randomized. ([#173](https://github.com/rojo-rbx/rojo/issues/173)) + ## [0.5.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.1) (October 4, 2019) * Fixed an issue where Rojo would drop changes if they happened too quickly ([#252](https://github.com/rojo-rbx/rojo/issues/252)) * Improved diagnostics for when the Rojo plugin cannot create an instance. From cdfbebd637a9084e032489c8951efe9f12ec6dae Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 27 Feb 2020 10:29:41 -0800 Subject: [PATCH 0958/1504] Update changelog for 0.5.4 release --- CHANGELOG.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 743bdd1b..eed7c8cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ ## Unreleased Changes +## [0.5.4](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.4) (February 26, 2020) +This is a general maintenance release for the Rojo 0.5.x release series. + +* Updated reflection database and other dependencies. +* First stable release with binaries for macOS and Linux. + ## [0.6.0 Alpha 1](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.1) (January 22, 2020) ### General From cf5b72aa9aa93ea0350e23599cf33918243b8008 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 27 Feb 2020 22:57:06 -0800 Subject: [PATCH 0959/1504] Docs have moved to https://github.com/rojo-rbx/rojo.space --- docs/extra.css | 13 -- docs/guide/existing-game.md | 11 -- docs/guide/installation.md | 48 ------- docs/guide/migrating-to-epiphany.md | 63 --------- docs/guide/new-game.md | 90 ------------- docs/help.md | 7 - docs/images/connection-dialog.png | Bin 13716 -> 0 bytes docs/images/plugins-folder-in-studio.png | Bin 19363 -> 0 bytes docs/images/sync-example-files.gv | 17 --- docs/images/sync-example-files.svg | 38 ------ docs/images/sync-example-instances.gv | 15 --- docs/images/sync-example-instances.svg | 28 ---- docs/images/sync-example-json-model.gv | 17 --- docs/images/sync-example-json-model.svg | 38 ------ docs/index.md | 18 --- docs/internals/overview.md | 45 ------- docs/reference/full-vs-partial.md | 37 ------ docs/reference/project-format.md | 151 ---------------------- docs/reference/sync-details.md | 157 ----------------------- docs/requirements.txt | 3 - docs/rojo-alternatives.md | 23 ---- docs/why-rojo.md | 44 ------- mkdocs.yml | 37 ------ 23 files changed, 900 deletions(-) delete mode 100644 docs/extra.css delete mode 100644 docs/guide/existing-game.md delete mode 100644 docs/guide/installation.md delete mode 100644 docs/guide/migrating-to-epiphany.md delete mode 100644 docs/guide/new-game.md delete mode 100644 docs/help.md delete mode 100644 docs/images/connection-dialog.png delete mode 100644 docs/images/plugins-folder-in-studio.png delete mode 100644 docs/images/sync-example-files.gv delete mode 100644 docs/images/sync-example-files.svg delete mode 100644 docs/images/sync-example-instances.gv delete mode 100644 docs/images/sync-example-instances.svg delete mode 100644 docs/images/sync-example-json-model.gv delete mode 100644 docs/images/sync-example-json-model.svg delete mode 100644 docs/index.md delete mode 100644 docs/internals/overview.md delete mode 100644 docs/reference/full-vs-partial.md delete mode 100644 docs/reference/project-format.md delete mode 100644 docs/reference/sync-details.md delete mode 100644 docs/requirements.txt delete mode 100644 docs/rojo-alternatives.md delete mode 100644 docs/why-rojo.md delete mode 100644 mkdocs.yml diff --git a/docs/extra.css b/docs/extra.css deleted file mode 100644 index ed31fbc9..00000000 --- a/docs/extra.css +++ /dev/null @@ -1,13 +0,0 @@ -.md-typeset__table { - width: 100%; -} - -.feature-image img { - border: 1px solid rgba(0, 0, 0, 0.2); - box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2); -} - -.codehilite { - border: 1px solid rgba(0, 0, 0, 0.2); - box-shadow: 1px 1px 4px rgba(0, 0, 0, 0.2); -} \ No newline at end of file diff --git a/docs/guide/existing-game.md b/docs/guide/existing-game.md deleted file mode 100644 index 735b83ca..00000000 --- a/docs/guide/existing-game.md +++ /dev/null @@ -1,11 +0,0 @@ -**This page is under construction!** - -## Summary -* Tools to port existing games are in progress! - * [rbxlx-to-rojo](https://github.com/rojo-rbx/rbxlx-to-rojo) - * `rojo export` ([issue #208](https://github.com/rojo-rbx/rojo/issues/208)) -* Can port as much or as little of your game as you like - * Rojo can manage just a slice of your game! -* Some Roblox idioms aren't very well supported - * Redundant copies of scripts don't work well with files - * Having only a couple places with scripts simplifies your project dramatically! diff --git a/docs/guide/installation.md b/docs/guide/installation.md deleted file mode 100644 index 4b360327..00000000 --- a/docs/guide/installation.md +++ /dev/null @@ -1,48 +0,0 @@ -This is this installation guide for Rojo **0.5.x**. - -[TOC] - -## Overview -Rojo has two components: - -* The command line interface (CLI) -* The Roblox Studio plugin - -!!! info - It's important that your installed version of the plugin and CLI are compatible. - - The plugin will show errors in the Roblox Studio output window if there is a version mismatch. - -## Visual Studio Code Extension -If you use Visual Studio Code, you can install [the Rojo VS Code extension](https://marketplace.visualstudio.com/items?itemName=evaera.vscode-rojo), which will install both halves of Rojo for you. It even has a nifty UI to sync files and start/stop the Rojo server! - -## Installing the CLI - -### Installing from GitHub -If you're on Windows, there are pre-built binaries available from Rojo's [GitHub Releases page](https://github.com/LPGhatguy/rojo/releases). - -The Rojo CLI must be run from the command line, like Terminal.app on MacOS or `cmd.exe` on Windows. It's recommended that you put the Rojo CLI executable on your `PATH` to make this easier. - -### Installing from Cargo -If you have Rust installed, the easiest way to get Rojo is with Cargo! - -To install the latest 0.5.x release, use: - -```sh -cargo install rojo -``` - -If you're upgrading from a previous version of Rojo, you may need to pass `--force` to tell Cargo to overwrite your existing version. - -## Installing the Plugin - -### Installing from GitHub -The Rojo Roblox Studio plugin is available from Rojo's [GitHub Releases page](https://github.com/LPGhatguy/rojo/releases). - -Download the attached `rbxm` file and put it into your Roblox Studio plugins folder. You can find that folder by pressing **Plugins Folder** from your Plugins toolbar in Roblox Studio: - -!['Plugins Folder' button in Roblox Studio](../images/plugins-folder-in-studio.png) -{: align="center" } - -### Installing from Roblox.com -Visit [Rojo's Roblox.com Plugin page](https://www.roblox.com/library/1997686364) in Roblox Studio and press **Install**. \ No newline at end of file diff --git a/docs/guide/migrating-to-epiphany.md b/docs/guide/migrating-to-epiphany.md deleted file mode 100644 index 84709146..00000000 --- a/docs/guide/migrating-to-epiphany.md +++ /dev/null @@ -1,63 +0,0 @@ -Rojo underwent a large refactor during most of 2018 to enable a bunch of new features and lay groundwork for lots more in 2019. As such, Rojo **0.5.x** projects are not compatible with Rojo **0.4.x** projects. - -[TOC] - -## Supporting Both 0.4.x and 0.5.x -Rojo 0.5.x uses a different name for its project format. While 0.4.x used `rojo.json`, 0.5.x uses `default.project.json`, which allows them to coexist. - -If you aren't sure about upgrading or want to upgrade gradually, it's possible to keep both files in the same project without causing problems. - -## Upgrading Your Project File -Project files in 0.5.x are more explicit and flexible than they were in 0.4.x. Project files can now describe models and plugins in addition to places. - -This new project file format also guards against two of the biggest pitfalls when writing a config file: - -* Using a service as a partition target directly, which often wiped away extra instances -* Defining two partitions that overlapped, which made Rojo act unpredictably - -The biggest change is that the `partitions` field has been replaced with a new field, `tree`, that describes the entire hierarchy of your project from the top-down. - -A project for 0.4.x that syncs from the `src` directory into `ReplicatedStorage.Source` would look like this: - -```json -{ - "name": "Rojo 0.4.x Example", - "partitions": { - "path": "src", - "target": "ReplicatedStorage.Source" - } -} -``` - -In 0.5.x, the project format is more explicit: - -```json -{ - "name": "Rojo 0.5.x Example", - "tree": { - "$className": "DataModel", - "ReplicatedStorage": { - "$className": "ReplicatedStorage", - "Source": { - "$path": "src" - } - } - } -} -``` - -For each object in the tree, we define *metadata* and *children*. - -Metadata begins with a dollar sign (`$`), like `$className`. This is so that children and metadata can coexist without creating too many nested layers. - -All other values are considered children, where the key is the instance's name, and the value is an object, repeating the process. - -## Migrating Unknown Files -If you used Rojo to sync in files as `StringValue` objects, you'll need to make sure those files end with the `txt` extension to preserve this in Rojo 0.5.x. - -Unknown files are now ignored in Rojo instead of being converted to `StringValue` objects. - -## Migrating `init.model.json` files -In Rojo 0.4.x, it's possible to create a file named `init.model.json` that lets you describe a model that becomes the container for all of the other files in the folder, just like `init.lua`. - -In Rojo 0.5.x, this feature has been replaced with `init.meta.json` files. See [Sync Details](../../reference/sync-details) for more information about these new files. diff --git a/docs/guide/new-game.md b/docs/guide/new-game.md deleted file mode 100644 index ffbba4c8..00000000 --- a/docs/guide/new-game.md +++ /dev/null @@ -1,90 +0,0 @@ -[TOC] - -## Creating the Rojo Project -To use Rojo to build a game, you'll need to create a new project file, which tells Rojo how to turn your files into a Roblox place. - -First, create a new folder to contain the files for your game and open up a new terminal inside of it, like cmd.exe or Bash. - -It's convenient to make the folder from the command line: - -```sh -mkdir my-new-project -cd my-new-project -``` - -Inside the folder, initialize a new Rojo project: - -```sh -rojo init -``` - -Rojo will make a small project file in your directory, named `default.project.json`. It matches the "Baseplate" template from Roblox Studio, except that it'll take any files you put in a folder called `src` and put it into `ReplicatedStorage.Source`. - -Speaking of files, make sure to create a directory named `src` in this folder, or Rojo will be upset about missing files! - -```sh -mkdir src -``` - -Let's also add a Lua file, `hello.lua` to the `src` folder, so that we can make this project our own. - -```sh -echo 'return "Hello, Rojo!"' > src/hello.lua -``` - -## Building Your Place -Now that we have a project, one thing we can do is build a Roblox place file for our project. This is a great way to get started with a project quickly with no fuss. - -All we have to do is call `rojo build`: - -```sh -rojo build -o MyNewProject.rbxlx -``` - -If you open `MyNewProject.rbxlx` in Roblox Studio now, you should see a `Folder` named "Source" containing a `ModuleScript` under `ReplicatedStorage`. - -!!! info - To generate a binary place file instead, use `rbxl`. Note that support for binary model/place files (`rbxm` and `rbxl`) is very limited in Rojo presently. - -## Live-Syncing into Studio -Building a place file is great for starting to work on a game, but for active iteration, you'll want something faster. - -In Roblox Studio, make sure the Rojo plugin is installed. If you need it, check out [the installation guide](../installation) to learn how to install it. - -To expose your project to the plugin, you'll need to start a new **live sync session** from the command line: - -```sh -rojo serve -``` - -You should see output like this in your terminal: - -```sh -$ rojo serve -Rojo server listening on port 34872 -``` - -Switch into Roblox Studio and press the **Connect** button on the Rojo plugin toolbar. A dialog should appear: - -![Rojo plugin connection dialog](../images/connection-dialog.png) -{: class="feature-image" align="center" } - -If the port number doesn't match the output from the command line, change it, and then press **Connect**. - -If all went well, you should now be able to change files in the `src` directory and watch them sync into Roblox Studio in real time! - -## Uploading Your Place -Aimed at teams that want serious levels of automation, Rojo can upload places to Roblox.com automatically. - -You'll need an existing game on Roblox.com as well as the `.ROBLOSECURITY` cookie of an account that has write access to that game. - -!!! warning - It's recommended that you set up a Roblox account dedicated to deploying your game instead of your personal account in case your security cookie is compromised. - -Generating and publishing your game is as simple as: - -```sh -rojo upload --asset_id [PLACE ID] --cookie "[SECURITY COOKIE]" -``` - -An example project is available on GitHub that deploys to roblox.com from GitHub and Travis-CI automatically: [https://github.com/LPGhatguy/roads](https://github.com/LPGhatguy/roads) diff --git a/docs/help.md b/docs/help.md deleted file mode 100644 index 3bbf2ae9..00000000 --- a/docs/help.md +++ /dev/null @@ -1,7 +0,0 @@ -Rojo is a fairly complex tool to adopt, but there's a community willing to help! - -The [Roblox Open Source Community Discord](https://discord.gg/wH5ncNS) currently hosts a Rojo support channel, **#rojo**, that is a great place to get help as problems come up. - -If you find anything that looks like a bug or have ideas for how to improve Rojo, feel free to file an issue on [Rojo's GitHub issue tracker](https://github.com/rojo-rbx/rojo/issues). - -Rojo's primary maintainer is also available on Twitter, [@LPGhatguy](https://twitter.com/LPGhatguy). \ No newline at end of file diff --git a/docs/images/connection-dialog.png b/docs/images/connection-dialog.png deleted file mode 100644 index 5a3d5f29def79d087cc0d9d58e28e2f8d7f6eafd..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13716 zcmbWeWmp_Rx9^K+(ZZ0;YPL{P4YjU@5LB4g*sckN#qe_})f!l+$*Bfx!g-=L0+FP-^ym64zB)%T?9E z!qvmr*&IgJ+1%XT<)?$IfjY{6y3qXRs-&~Iv8$DXJ++#ZojD8_2d4mlgBQTTN6pCx z;QRvM<|bA)_yq&QvnDSkuI6cQnvLv>Z~ipca(_~MZ$OP2h%JGtpMftf{yE=r(BSL_ z|5^LYVQ{cG@R=QbJCGy6e8a>m1r5D5;hB5f!@)X5zjfcWikt``_sE z%i4Z=J=l$(oIHp+0`p>_2SFTrU-C!{JH%3s0ww6;Lm9j{b`FgjHA+8sAtr*jXV`2Y zHOj;<05-xV$q(cpYN7wXH!IXAhsVZuUQqIpQ%OqV>COh8HPWEuBOiLXl?pfqac(E` zt&S1mNY&8z9HLqHHUmW>iR(>LsHxEHGGRkiFP$3LTyFu@h4z*_O*;LjOZXhDz5f|j#bOND z>13v6kw^T7>j%+jZtcUZ6ICbI#@q5EEzQ@v*LB&ZK_#vxgac!@p{Fh6%zvYs&XQq; zv_4y+BP`zVs&ip;Mk|k7f`)fwP!Ny3)zfVL?eZcTU%PFC_nqVg>N=4WXm=ny7dpgV zbg2eAOyT~V;QzAUG1bDR!SKfDHeD=hD0D6q3U<0N{MMsD0tKAO@4vUKK&@suVyeyY_9&n)f;>jY zY#eZ$Z#^V_+%rbUGc^T$d?egyCv$S&%Y#>~&9g#V%eG~@9?5Zw3Ej@_E%i}}Gzw5V z&U-tc)+lTsDojj8}2M zJB&X?j|!YK4;%RtyrP$1CC9DERiuO+T{INB!Ig7v2GV-hQfnMp@{NSa04P5>vGfSz z7`s-3yuL={lzO`zJ3S0(;O3^aC+0nlXY5qck#eg$y8B05tN1kvmu=$n1-Zg_zZZhL zri!(HefMwbsmak&V$eUCDQr1+bL%gOTe{zd({;km8jT$nY!{)gIH)zXMuAekH-=F2 z&KQ~rA=mSSTh*Qiu}`VSNgH9U87}obI)UeZ+PEoM1stDK%>Q|elim(A(1vziGi_y* z`0m3pY^JUtuM4cde!#*X^vv2E>;!ek5akX&i?-N@_ z`Y@U8GVd?wcX_OEXI;oRw>c!*)8E3yB;h@_^A5nQiW!u zP~2mwmHRAMGtGs(SR=N*5e`*f@ipTyzNYP!(-#}iuH%%}fD3Iep>VaU15HwV#j94_DoEGX`;X(ITt&pp_S-7Sj2=ZDrKn^%wUXFU|C z;j3$Bqvp#fop%SEZaJJ^ z;oxm)XA+QW&2>6?UpCl1L-4QZJQ7&aKe2Hyxfz7dOMgDIG$wBfKE|b&a@n{6EtKBC zYjfyV?jPP};C}aNe_A^cQe2fMa8l%Yh7^r&8nXgh9jO??CXKBW+WtT?Ndg~5tG|?e zQJ@*z9D3a(dI`-yC@SJG?*$?>gDvW6%PLZGRKk;>uL%NOqW;TKybZ2?C%X~d%6>2F z>r1Q}^tk&9gDu_Nm(O)A*)QH7319q1tA_GxW8argU{nXHfJ2jr3Zvw)Ap~GTkuV2E^D#aW zK1jeiz>MLT>(4+fY-S;=2hjT-Y#R{Bi@M%zg z5$sG5B5yX^Rb;#$hd}mTO{LDZ9B06iM@&9{ zx3vPO`hv=vU8w#viQi2Vp!g&NoMZC=X;l{}!%bJ=CoKG%vc_^gTKAVO+CWD}NhoEh zYtu)m!ZEEodPz8Wx8o>?Tq}G8gf|3#+b&{QiJ9~U2`Xx6cgF34x5x!W>F`-~9fh8RJqV4}HTCu|60Z5oz08 zB~l^dqQ3=k`ydHB8BXTCIb!eh!75jH>8A9(36`07GgPy;u2?}IFPaVC;MsrR;C{Nj z4rEh!-3ngjgH9F+My8*nnCCv+9|s$s6Hwyv*$L@75lq8(zlU!Ky|Bw#Aa#Td*8dc+ zg9`@NB(I&_-B%va}@t#K-2x`<^_#I#h=V30aR#jEGt|Ls5 zZ8*0vB_BzIIlacrjo(Z19R?1;eN~tiyTRqa=cHa#K(5ZMTYB_6V0iC^uZ-OlrG&KO z_CRp|PELfg(zf@nuV2>;8Frc8PPb0Jn*wP9G#Zyz z+AVoq_~&EV>HQ=lc0)=F`3F>^#;nBjV@YkB3Sx%VWjqo$T&;%j5?|6Frv_1dT5by+PKVGf{u{!WSKd2D9o z>bX4+~^R@L3zAL=W{(Q=jqWzu04-EZ!qvP1ZxM@r;Wj_{lJg4A zBAi9`MgtAwR!w$M5xcj;qv3p~;Ga}5NsL%(c<1zJ9I|Hv`O$+EqLbN^YPGj~AGkiR z_?&#?^(Rc@`A&2{bPq-y?zb?q{juNOlqoDqZeCd`lgu)HD8gZ+EtPR5EZ3i9 zA6nEmL2FUDGV}puMK?QhY$CY(H$D&<3#!z6ENP1qh?){AW_7F?!PsIj3 zLD$qzBg^3Q*(eZpLVM+})BxpT-P=0;w6d0#I;tE46tS~3G?(K1xeD3G6aa@d_f1d6 zz!1PPcI)0z%#n|9YRsak8Ths>KQFZ}$%T&J+@z+BWb#G|iaxu~xmwZB205u$K|Lkzm7WNI&Xj(v{v$7}y(p|1lMp@T*AlSjm zTD&pd!Q9)w`G$qVN?U>d9FBeHM{x-?;O9y`)^)h5BeRV<7^yis*%i3}?lOp;sdDwt z45p-tz;9{tJ>Se5f`C~NccT|#ngmd$C_3n+&6mI2RwD+*>;cuAWqh(ps{M|AX#|KdRdL$Qf0Caj*Rx!q?WM&^d@A`vX8Ud$j)$}yW( z&c-)wTxW!Y7mm!0;c0@yJMFMFk4$v3ID?lS}OQC(a@vrlZ6^^V&D?j4$6sTfA6F)@Gr6)?O!!|9elf=m@p)jytX zcH+7dc29d*&Fpy}3LH4owMo!ysVfLBt-y8s8^w1I@sbB@!{dE$oC$KsJ?k|1mGWUk zN_jw|)i-KhQrnSWDvb3A=FaQ7yWrh1!57B|(^kaqw%%`GViK-QxNAzT2L9=#AqYqE zE@G&c?h!4-Bti&7@c*7??au%wJ7v$qX<=b!wL3yjKQY0%=vEa z*^#V@)b6&vX-@Pd3d@B~68x0?MYP(I3_oSF_fz6l8q3AkW8~#|qB;?MG8Ekl)<_id z`qO}6KD%WsOXXzFi?3hdsoh$s(>OUyb#=ekzOi6CTP8D$5Iymi{PaXtP?wz@yvAPh zi6`FajG)Hnl5MejYx8YyNH|03+==jeWr%Aei&^S~Yo5h;_+lHypXD=c?`GHB&yH`V9h?z|j zA79VYoOV2}Z_s@Bp|~7i^}%Oag_P*;=H&((*J2$1s7200XLM@&%wNok*s&V~eS7*w zuvhgm#=hbrg#`_RNc&_L078L@yd}}=Sv^$$G2uKFMzqt*qqwXcGl{8lxcC(LA^ zUOzkNY^#&qAl}gKb#Kg;d){ffjseQ$+xrCc<3#8$=4)5#_i7b<0KoD_7R=W}iSLl& zvhQ}RfW~FcM)e)+lLGbKoC`&)KJj8@Q}BR4oVZWVL(ftTta`*FOqZ;euG6sJHb2P~ z^oMlsXII(o|9$b(gM2sEKj0)@zXbp7J4t3tOJb|RcB#4MB#tDORY{nJyxx5=vi~`~ zi=TE(cB(;U$bb`$z?6u$kc2+|{5vYk zqrw9DzMEa!8;K9$WjeuoZwhl|kGY}=7sz9u9^$yQBIQ}~pawnYQ~wXL%?$j} zS7KLm#aYe`voF-)Js}ZxU}0NshFEjeNkh<@b9|70^pAcnFz^958j14ym;D0V&{AW( zlPTmHXY;?g6b{zv;Vo>j7?b^t7C@`vwOVJoYmSB>P1uFvi2-TT+Fl=2GUBEPfQU^` zD%KX%b}Wn*NgPc^=Y{KuGYZ1OB4*OI_wAmu{XpI--&_)eTy!`;c0~Vg0qlnM-~;D@ z8RN}{_Um!r$h!Xjmptakx>396((_9)&z?FqmomCA5!Q-B1^%#?h;jOvDFS5V_;$?nS!jP412UR%@=zX!(j$ zuRZT^x%HxZ2;;%$N&_iLN%+ho-jeP&tMgoFc}!fZ+r-yytTd!oG}^nCfBeVUiAhY7OVLV@7CVE$qU9R_WSk3DV>H z>#@%-s|(tyX^Cgs=jRi}qo?pDZ*HMgw_Mw}9TCMYKSk|h0` z^CBH_6Hm6ngiaUz>sP)Lq01?MTZ=otKvYB4s2mZe)lo#J7RBf`FWjfk`aRo|$I*3` z?UjhrVo;F(qv=INpKn>~+eIYU!9RwsUk&zT|AvSXogx#2f@Lq1ZrE<`Gv3n!-u%}3 zy2lCiO|siDv3lUR_Xi0IotGM^rXoCIYVr~2x^D}fE{3lZ!5ZCgPs4n`P(&1cWB5HH zA%h`)0E^nIZ116AGQsU&qUS9gLQ0mQ^y;zO*W)|%J2OMapHh%$doG{*0ZYMtR3x;V z?%fb3h0anYt+$Hr>#cb);sncg)#=Wfk{WCcM(nUi@#m(|A`X_C96h{N*kzp-_PQxg zC5X6G>Zc$UFRhEb(D>1X2Mj~!H8zUdmL4&ZFT3iv{_B5yEUNR2-&p@RP*s+!d>Q^ma*EvTaM zvrZQdRXF%e=U`a;$k8o$5o!G`TcngsNC>z#b&Jx#$o}j(-e-v8+FJ`kv~5DKDXm>@ z;LRJ06@9^5?9ZKd(No$D>|yEWIKAJXaN&k1J$s?jrv8?Fn}kOCsJI<8^@w{6_`N{L z{2z#~_kZu^YTbr`9R!HZg?ktKJiwRa497Ucg-jxV`;lE{r1eJQak`P2;*_^$40KGL zhfmA>p~a2P+DE_Vw)gBZp!D_c|NL%iSK_rqljORm%+Yzrb)+WWm_MBTQkYjfs@ZfO zyWny_3}5bT)Q1u6tJf%+8OWG7cHqRniSDsC&(G!7cN7B62kUaP?{wyW;pKa>$Nc(> zvJ5;I3!cCA?Z>;=r3s8c&$u36uxox0m{CEo%q%mP^V@JAc<$W^`-kUlZ)+{S|FOqD z5Q}T)R@CWn97KDQi1mEj@JU?#FpMH9V)CJFd<}*ikDn-FpMC!MRo|Gm18>9Z?}{_s z3ra-xs~vS=b7DDkqe*lYVrc!#T2sPZd#U-sDt8)qXNXlb}*- zgeO=Kh6)xgwkvk&fCR7ZXcPh+Czp+u@wk|iwo@8|lK%*=$UGa3C0M?H`Qr8qwdTOFTkelqQy^33REQJQ+-NBk z7Cs$oKv)P(rDw<{YeiJBy7Svqi(uLmJ(^ zPG`B$Vn)Z5@`S?x=AA9T-wvi@@!;EsYPu3z)6kBq=L+{tEx&VJJ1Q9;-1^{KbKz^u zspEmo(IwH$)Vxnl-A}iq?$-mX5|44=&Xh>>_F$e*Fu}{)7s*IZU}p|tC4;vb_gn)v zP@(g)h;NDTwNb}4SM7IgN0>KK>th<1;WU(cB*%n2(v0b-5!XEoH;e;VgM|UF_?Bnt zR#S~r6<;6J!uRDIc|YE#SIEYs>%UBATf5ysv$JR>>nX&yG0;W=^6=(E4 zk`n7H4rMGCuk+FO+|LF2saCCe3VTW22ENDR$s+QX5e#4F?eNMv!(MME9{g3X=EyF` z(dCGs^^1#dT(!ED>K#}TlACnYTaJFs=iv4uOiS^mI%_G*vp_O4lgWNr?8PS5I0tDh zl%%e!_b{|-gdMMYm179~vlKk&N6uxs*!%fC8Z`P&Hr8VZcH)^xe+~6m*NW+xzFqc! zUfyO+^eo@*R4hWD*gG8ghCF>}kZi^i&v7!126S@(y9>y<=KfC@=N2IWs95TCEj;y*h zM%F{|v@`=U4L4?JIrxAb4XP0pw!0?co*+%b z^yqrLrFCw&cgtyYG2&et3_yibFCmsHp(GE@!lJk7{^&?fmrJa;hI0}324DRzoh9X_MdaO|FKLM zZh!zeP478QQF0H`I{aH4Vej}Kjsg+U;OF@4?Y9>tWn&BY(f>cR6>bosz|b+iiv04t zfNEO||ITQT?YOHT`?WVgYk0oK|Cn`B~!L<3;3*Q z={4J(H{B1cQu<;Uy+h)!uwEs9yi&pcu3AR1{2%I?={DC<3~!&4{uM$FGmefb(4ush z%Zr$5CJVc}Vc*vLx=kWO&a@dK*xHWf`p)|Ig5>!PX{>ltcXI_AyewC%6?Dy6HLJGe zKhp4hCw^KG_A>@eSKGJIpup*^9>EAq9^Z~(#Ktx?9Ss!k)ejfXNH29tT&MrgRjmM< z?Jd}nXTtjh$(5nx@M#sR201YUq10NQ1eJJ zCD&);A~?Z%Cje@l0&RRAe7pae)ag_yj2dx~B1(YdOKJdK@0MCJd_N_Ag!va)bSCTsGdJ^14vpW7fGMi>If{D zr4pi;{|Jnas`!;YTv1u2gPF=48GS*;$8y@e3{HHC`eR~IvC@<7hJ!Hmk*EqYhLHHi z+s(!XD6Ot8uA*uj3F?;b-5&{tmq4Z;EWXox@?^$Ga}QK<5=ktb5yw|L6l89o;-$cWb^1WsNpjfX++395e@0UysQI|s~K_>>WLl#~Pr+sYk?AnuwOt%|&_EtXwfT-aD#c=D%YofvJz zwn~SXWALZ@_y`v&Wck~dQbTC?nF6Ii<@Gms6!I7uQ&WB5e8%m^^_tCcx9+|``TNoN z=m%Ql`vuE&Vr#M!89WIjHhgimZIaQa41hu2`K)>_omPMgP4ZVo2GzZz^{cgq67?#T z;*Z~-t?L|&U|f`7Up4Uw_);}*DMX~$&ZQmP=_4vaqm_{xLxic;I$8HuCmJ86d8^{! z&)4i_1-zY_1J>h8a|Zveh-?%wPFpHo{{XDto+Z?8B_@%z5U@S==_yx7eNerL)+}TQ zGb_9&`Hi+-cp(+%5s<3}n&jbqL_oIsl5u+f+V-WS*MBK((U6U>!yxrT&-OvF-JEDO zyFrt<2nXkB(V*&JyfguxNZQ!m^b2>ms5am%xg;1Yp?^$|vPFAP4fxr#G`y8aH{w^V z+cVc>mo4g(q?&_I$|whlhp-z1j&0 zKbI!!GB9-I;yb@S&$uH`Ktv8(_s~7MA?pJArp+0%MgZepo69yzZt>RrKMDbco1BBF z*@CL)`mC&w!0DAIz#6DxYWnFUDLF6MiAD}SWIsU=F6mhg2=s&#dE#s;AGxO-2HvmF z6Jp5Hl0ruk8!t^)gV9|P**9iEbUsx6a~hB#9JC@Q9Qd40KJ#IOwp5}5bc(=u$Dgak zs|{31gVJ~Y`)vs`B_^l0O-&ty-R2HIt*ffZZbpNh_!Mu1pRc4V|C;ges;QYn+oyhL zr@rj~H#w&i2*j~hOO8i;P&U4wiMHO)VKoYJhw9}h(}odVNJ~JM8RES+u>KXu{wby( zr2ja;!1%YQIkRuNY7JXOyVd#l`fnE=BAV{k^y2>ckR+W&!y!=tNFkgveb*!}W z&kHV6f~_;)02^USK))28{GmUoE#2XDMoW25ke2nOtiuadB(1$j92OS1O^=IONxBA` z4-=3k`iV*6qyYEx4mJwtWn~O;{Bgw$&}so(TkmdcvF;kc8qvBLzUbIP3PC79c1;6r zOhyK$Q&ObQ7h3?WKBj_kWI~ZbLh~=v@fdBIPc|1Q%KcFL4qsov;9B?QCL4X3u5Jcq zSr&;j$fT6G5YU8@v@&>oB z@|LMTN>r4qCh`Mm^2ee!e`w-NCBbd9qW=x0p{Qtc9Cd{K%wnf?gAUoZ5qLPb=`~;P ztqykC`)|__zNJ`(ZYdMZVfuZjJAX_k{r&9J-)|=vV|uXb{*M0U0sfii${DGK4JO&V z&yADoe4FXWxM7&qE)T}1fY^DxA67QD#$T6I60&WEnPoJuHef0dH&IE^Lur9_!7y<# zyvcuhmZ~aZ^dkLOV&hI>&F`s4dXRb1 zo3*1`EVn}G!a)+NXc<*VTF?q^z^ZlGx0{U}b8iS`PDL6V1o0_WENN-Y|4y19LfZwJ z_`<<2m%$ST#+#OwwPYxQtUjL|)1u@*yOv`L87P}cX{{rasYNxeT5uEnc2dw73V{aD zmt_H&BmbIASvQvOohmzs{VjrX#!2Y$7m6f+@t#aO3S^_i#x9hI&1ank{yG7Phw^b`;CPYVv55;L8ObzfiTq524|7 z-U#%#s&&2FzwvS2mI|AE<_fbroX(*^6X9LUO*&QH=Q!Pq@M#vaR(!2y<+>xqKQ1chVjm=ERW`-i}q{efQRB*g;Tv zX{*(kdv)KZ?{P#C(solA;@Cve9;|~uc{Fx*mtDQt;+d6)fc=s<9{lGTY^#g~II2Se+}X?FqB*na6g89(2~+bb zzw^5K%B1;*GkCa^;wYx-zMWt4xO?mQ%1qg-OQ-c4V%on%eaW1{TgvAkv-oeFea0O8 zJ3o3<4$mx^QG;4PwO3#|LMq}d1X(l`Amt%HBNd_^ptF~i!OcSJ>_V~P9 zmy+&7rDTT2MId>0>J=VTfwXCjfat}O-Th@J2EM}^-iE&`<(pStw?3G;k9+%9LA0$* zrCg*jAA9T?Y;N2s`FxGgf>7|$%(=SNPI5EMxQXATMn^)uRet!az2f4Rs*bjgb3)x> z={dLnj?j0BkS*Q5BDgPajCpI}L@#oP`OB1bGr9Jw?j5&7Q{_^BnS=YqqhE^><--mT zl#p=NA~a7(==0Bvv=wR1AS&>mL|r&pQsa11oP~T|F7)K{P_zAl+s(BDjyQD{#QNBO zjg}DQv75;i-8}G|`nSLY7gK(}Ex=TDoP=%#0rEwqODVO@+HR(1`Nk`>esW`@%#;pq zOR$~kol%m`%7dGW{;H{uG%a$Lpu_oI^V#j^G9_Mx3bB31ru=;|Tp&r=!N|`QWCu*y zi?Vi!meJL*B0_z6`iLT!MQv+kJ&&L4sDXx+#w3H~wi2MMoOVCc!43bUlI3JSklzdmGa2p+ zXOI4PXK%Pwb!0_-I@zjV9>*$oo22%$UZ?239YNqqZA&hh_wm?Tw+ID0dH=&l=XC1H zc=ja6P&mr-&gB$kn})?Gzf}_fb=#K3SKMvH>dgA*6|T@+TuW=~&(FSIw;ndw-%wtC zJ0*kD&2jYPihh`{6Gv+q*{gg50?kY~TRKxTwI^ms5Ye}w1 zFchl;G}>kFPqan}=clLkc4Sheoa3X}%vtm;TG7)1iTF;hl&9RB<7FqVxC8K3@5YEp z-6pCma3)Im91-9u`hF6icRG*@xE?-}V678ilPhR)qHbLsE=3tlGbH_6ncb?T&iBZH z;yrndAQwGIg?v_Lk^_e-;8@r;Eru8e;u9v-+4taLh8M_F8!@xiuZ@Ahpk`#fo2bZ|be*5tOWhOzsLp zG%3lRmU6ddW_*2tp|lA;rtg4;@zx)TzPN)JKwhe=gEsHLXPN7?XXox>7Yx`}Xi%w% zKua1jJYQN?&=7hA8q$A0zR@vW%a|Ati682nC)dcm-Q_8 zzP%^+D{X>Q5f)2D&6jE7*$AJ3UGb6mSp)2qK{k5*X5bn+U{b$9QDYtsu?8@*QzT@w*@8i)-v28|NP zx~Dhb@8^o#4bygy|C}MixQ*pyPv%4%;1i~?Zaf$I4V1EXsL3$eMmx!RyBV=POW zg>c>P`P6pLm#zHztk!feZhHEME0@(YeRHYme6{}a!a~}wUmPZXP?`_6-qXXmxjA!l z^WELu2>3|?z>U@rn`25f5cwoEqdsbQy?ObVH1thmO;r|sij{sRcZL_ z#f%`j!%sPV{fd_9v~41Ij(LFh>gnb6_wV02>1^kx8>`^Hjs1NhoT)eWz_X;>+#bsb z$``s?bF-=c4ClbwFRpqHwp-F%-1yW%kQ#aGA!0{#P1I<7EUwh3LfoOe+T-BEe7*J9 z86AeUz+92JOq}HA`3MmT$D^q>KYrln$ldTb>+h-5#~WAV8f3D)L?OtbYd*^dqQdz2 zlnku_yOI{aMb`W_jp;E$WQ}+;dF}c)G?a3ecL)F#Q6A}_A4L#yoDJw zBczua_@0Z8je9~xfa48z{5$z3Q$@%PRPN~(O44?DFdG}t56$%8&5VVkDpF<%+Kv8* zdoKPuy2hnw75dkhNIG14O@Quo0&5UcKFR0vhWTVV+}1R|_su6?zYic1Zj0Vi%`&yA zsVNS|G#(Zv28J-ZeWXrT{=3@K#zvk`5@fbbWT}$^l9H0(O>lU8E5F;3nxY~`N^&-k zx-=U=?YPk6-(yfC+ahOXVbMP!Ybu93)2&DmBSS};_uZBti)b$hxPNRdNt@6s(9dgW zZca0T5;!QKdF|p_g&84_)_gW)VL|7cP<#{FbBR}AM3y2i*d>#vpZ>9b7ykXUa^ zll6&Wm0lHScQP^qUY41OIdhg(BTjO!2<7V;8Nf+xqjeK#pN*R?qI|dw79voZ7SrPz zjH3wNHDYi;Pus-roi^eoZlnwjeR}dv%U!i+|MV$9nt+fn|08!oJ?pqLYBskK!C*Yq zU>4dv$t8+~MI~Z2vgyR>Y#^tfYlNq4$&3IM%H;9pYF=PXje{<{vYuXyLj(%o57WlE zYg;w1k$DWL4gGyk^ecy9=SE!FPhQ!NYMj$+U?iD%r|tnHs|DV>)YPveq*O%0uD?Es zOmEiI+qe?Oju+2sRUF5rFOEIOYf^}68>)_I4h5U$`vwPh{{EVv6%*WNOCqjET8li| z_z)Krg@%f1{7ry-K}%X1vGNlqC(d>ft1$WrayNX62@9HqwytipV?j3iWcGMM=w$CK z2@fg8o*h0DKHBKo;o)IfSy^9S-_PJX;)~Hkh4`a@4PgNRuakv3Es776x`^yBG*}8T zRsob@SX660{{FU1JMdx+)Ueq#6?BxLd3bIIPkzV;=|%M^rgh>$^ly}BkqEwl)U<5w z7oFPM-4E2a1)49GaYVAA7lkH14NJe%RiV4XV63jjyLsdm|3-SgYdL*4j1~G5Z+GLM z0|7v;TOQo@`(p>Ve%cDPnkfzq4==!$nVX&c!*f7>KMrCSTv=$a#8SnCM@2`sv9}M4 z>kUYdp}`LU%yTgK+%fG|w9Ju`st_|Z#GAvIL0aM}I$A1jaZ4s5QJe>+!xF5k#b75MAMD%9RyH$vG)QhCmo|mozaRR zQE_(z$5Z;V8XXeA?1xD1{>KEJdrG{KLW#g$3*O@|I_~m8t#U?d4+EnU3WYFifFO5z zHrFYf2Ar7y&{*K<0glI_fZmhON}8y@2pSF5;^Ly*2QpsUwN9@Fi?OJf7^!BLm8LS* zu_0B#mF(1Sx)AB9PyoO5tZwqo(@`rT)fV@Vd0Uexny@btY#P#GB2uIY!`#_2-K~t ztQ0ceBNYX}wKOj;;2))sCpP!#-RbgFcYC|{{&@DMKff#_?BCVj!%jLoJdrHl2O?$c zs_T3MA|75|3kwU0u%qMSO~gC|m)Z`=%>*{c+?jt5Lc7R0b@D$rNy#TnvJ)cWjmtuC zXs=SZ*alQeY`5r#4E-Oh?(;a1gDBPY{&NBH9T9)-QlSmupP~ZgPh4DF98t5@UudCK zx-Ii_bH-9MVGi6?+?L}zySshO2?IOvDRRG)lR?6xlyHHz@6oB<8qzA5?Sa4qUKn!d zd2M#u9xxwCX^Pesf+PDkHm2X^yxZ<}tfP~4ZbvNS>6qH`=-S41@4r8Nu;kH;*)PKp zuW4A%DJY18)&&IS<8C3xQ88NVl zF<-6K%URN&)2f`SzHIifUqBpSaTGPXx}} z+ZzX`Z#)1-5(&qDBRsGI0S;byE_zKxFitVt#AlVaCey^dAtAJ zcV@oayY5+wqD~$8$=>_f9;PTSiHd}e1O)|!DlH|Z3sx}7s(GU)D{?^XcO}~Aq3FJpi7jaD&6?-!m zcS9#rC`l(%Q#)r1dlx-5M93pD_|jq`s$cbvvfieu_O{#%`r4l_dpYMExTmCUS=r@N z;fMGn5ShUnYIaBG($vw?WFQXYqkKZ_Db6K@KCb+t>VS&>?gQyN6N6ZBH<9-!&HhMi z(@#&gS=^4_X3`^H4~8t@q9lorn3bHw>ybRBel%Ze%+t~$GIQUg0)9LwkYvu#_U>(% ztLpG8V@&z`P$Yx6`qAEG0py*}!^1+i$_vMC$J+aL@0Fn5 z#%_~;2N?iFAsKD5yY)-;K!0o=D(=~IJvc}3It;_cbj@#Ls*8d9S*X78+3ppx>KN zrq4W8J&U$9W~qwk<4l{N(1kmLDf7DxE9ybAS2CJLvw-ZdWq`~%ElMd{ejb8E=&1YQA@Z^^ocPvY^o#v5} z>DAP9dysej0YHZE5O(KmjHbTFVyMB<>nrj61&%`PRlaP?&sixPG{u$Um=^)oY1gu|}0Y9LeTDZ+J8 z>$Ev$ihCZ97~A_Juv>`UkA06Xv+tBH^DwtYB%#ax$1lVlUhiN zL5-1-pSfMBPMgP7exy6KBVCb(tGi!2LWOM6p4J#xtTpEB7`E7$LCK3HkN3O_sY>k= z_6GGht6ZlQOQITR6Ijz> zr**|})KLw*6_>_CH8B`#VLkq2I9jJsZb{xIy7(&|)*hDf7BZYRc2DXQvW}Nh@$4*I zPgmtSlO5rg>cLrk9Zu}WI1(Y#b|`DMvc`CH8ko`qrP<_a zcFdZ)J#@Y|2f{V=)a@Beoy~e~Zrt4HvQnf!nF7eNRrJu`v34&;X8<0!`xr_A5oI-9 z5{}3PKFZdRFr#djv!-ZC9Er63(*-f*roxP`y$x%DE zX`-fpNH_KB?DO3tOk;TPAA$xmo4}nzp30-%-PMJju>xVcq2#P|1Xc02Sj`?AE-sAm z@ThRR99H9@pWHsTM2^Xzn|u^q8dZunMK9@3tK&Gnj~&!QK?W~YeflpRlYc5M zQkIYs?(oYvUO`PuF+u_8+IIb1q#^5d^)kx%JSQ3R>~@Z?&7{RZ@ejF?t->n)-VC|D z_rt&E@U&V9{-1o)I8X=Xg1g8NzmX!6GqTLKqKROL6@6nY8>62rx1Q7Y6Ci*VDTGqC z{zf_lCq)EX{YBJDt`PCxIpp&cqBTfET>>DV?WN^b0$#^5RaEtx2niFpA~1N;(aX!r z_g4qQQVj5;D|`m(j&@CXtnwIZhEl+{-4S$^;1lBL{YHa@jOvbhYL=g4gM)vjiexmc zR;qN{qKWw6ZH}@{x4YrTRvFnJ@`@^&js$AA17mg=v>1nA$(Wg|eV`O&)k#Ay17F9N z(gcPucqkYTVq|wePeUWgtZNjz#ScnDsWI{5%%WO7-OZ(JU>~-+9yD4`7qd|_fP%^0 z4#23Ws}4P=tb+taVCDMVLtp!sL50rducsqi88?}+-=U#CKCAq%VI+WA@rMQA#zd0< z%9p2tQoGMUL%vlZLd6;aF1zJCQH0ELugkrF9L2iB!$XNE{J}%+GW{;!2pqw=%h zD{U11ExpLlTHUA_fSy7?PB6fa5*d!vcBWO~XZbflR+|VAkyecZwz;85P9y8PkC#ZE znQ++1lK33)-6ed#|Kyn%2CRRd<|^Dn4e>8RhhKER)-JIniI}zn#TOn8e80bph$}x^ z)K$i7&quNzT!mFUc*mTnYU5>SM@@0|{T=_WS_#Hlc?!LGGhk(%*07lfFj>z$Xm5f* z*_vEj)ez+SvROJxg~O!2!#vL|fvnX__F;(5zcZYTMHOf|ocv5z0Ta;gfsajg=NSk^ zOT_19v)E9^urEw=xwpM0@AEtp$efva|43cIb?D`OBYEIXtljCmd(=a<%3`Iw*4D>v z2mY*nN_sS#Zo7;uiS*WlpfwJy>`gGvCtXd%$@Mtl2d~Uqm))a0e3)r*rG-D*bnV-k z_--c}ktMb{aTGpCRBtk#!$REo^z<*!_z&y;fEAPTP|(d*&qC zhox1lBGc`GZwA9i#D#5uB`#}|P;Po9#oR`hAT<~_JVcn2V{ZXfyAMT~okiW+(M5)m z%(CxR?osE6Y@H&5)e!8M@OY3VqZ1Q|MsjXv79%w=kCdoTBp021 zhy`HL<|E|*Z*syG4~tOSlI|)vew?-1E;V8R5XHAFi-^{^ipsh&R5lsQ$%hxbJO-B&a)Ur;d94Q1Lj{le!Qr z7GBzI<+DekL=sU3{#GoP@mcZvr_CQ(2?^6xx_qUTiaLc9a|dzF+_@1(rD%*cE3K}> z$&7q%hcwxxyE{95-kDW1_ZQVN3Vt4Cdx2QDWhfg_E+3F`HM{=!CCm~A<%6AuIbzGs z4AtKH$TS^;CBEJ2+Z`$@01FG`5x=_c?u|;-m<^;BG{}6B(!{^sFR~@cTR4Xz?BuHx zP;pg57|T{1sG9cfGi^lwIRnVcwpwzT$5&%v)8gzdT8(48Tx4L_WB+W?c;R68eI{M% zoth>vCMV)nQy2t)bufpU!=aM%RuU;uld$b<`asv5?4lI$?MzPE?)ElWtyaAm>v4qg z0h_)qukZCz)JKx_k~*N57Vn7Sfo)xSpbM|IwO3Pk7;0vTV=UQ59c+TU;|2#o4JS6* z>PqjqqCp`5lV>b3w&vz!B|4k}==B8$?WcN$w3a2sbq22}gl?YOCfQ-|%xw^t2@@0(8n6AiMO$QJ>_nS@4 zC>5S+8MM?C_W=2d`^Cfs}6T(bcy8S|Y z`r(xi#7i@+4-Q)WQ7#(R#gr2~C*uyZM4u`&GmsE+j*UEMRE}m*GHJ;SE$1gAFqDW* zj*H}h9ufPDen6O}?B7ZEpGbDps&{3itVTD^m!l|Z?;6>>kO5i!3m3NTAe?d=@86Lm zAX98GQyGU64`n4d3FX)A$X#emZxL8ec(v8-X#eUB%N{%I(r(ldDI!Qc=dC`-@MY~f zOS5b96H0&@0a~P&%hQo)KUZ1oc+fEQZ+KP?!Ah^Dk5sD$rZfSL3kRdHLF|O#u^56Y zZ^NeP?BD_Ub!mB^-= z&L}TG+A@eXt;_%#XpGPCn$>&J|AVg2j~SscAFII_mZ7y5dzJq3qQmv|^``t}K>+%P zht33Creq(d>&LWlX3`p0`w3>Lw+A+iH_Na^>7?=G{(us`|B{<$)23ReC0- zs(dS-GWHGQ!BP&iQ6gTKA9*}G)U6_$eNkiqJUl!iNPM+rSB)Lig3pf|lhgX^U!#5m z>-L+rXa<#nVU@HXXcUAy>vp^>Z3Xn-;N1Of!i1dZtSJlI?sl zx;)|YVMbt%x5xgW2kh#ihiq~L+>;tQISeU?3X!?|X?(k@Jl~3F+GO(5Y(n$_eq^<% z^RDppOwGR2uhQYn3LE1O?3u3re~b({46&VmYY+fMt5>Lhlx>y45Hol+DUelwwFBj_ zoJz9V3CEbQ@6eSm%Nd+Lz`o*oNve4ll!=w(g@vc(g=@f$`w#X$0wW=OvM8;IAoM;RO3YV87LV;+@TDk zlop3k2*wi)PhKW@xs{~3JPtXDtRhsqo)NI_zZQNU#>!`dN&H>K)VQ33d&RsGh$6dV zNvhkB&tE@~15zN>xHhQ#m z%Gn+2mKav-a~upnA_3}G_#ms9N|g>X+aMF8&j#D7L4ffbA$=qcg#Vh+o(x(%ibH%= zlB=!D=={LW$H^NU-&PkW`FSbXI0I^aq>>?cC2IqEm;^k0sl*jnDpx+JQl$cT*lO#! z<19XR+m(BXJU`pTEixq04{#=vL&cIY89H)i)RJGQTe>YK+B@zy1D-j3UGHkB1?}fI z6za@M=kL$!-j1iBYv0GfkDi-=6bFW^7I%_G&^uLbzuXnri|;&rWW5^Kzxi+`)*;bC z-X!0X997rWxW`>OI(p+y_^HjO3lHcOZMj&CUR7O?(PaIu_eP(nt= z!?N?ZblwhWxLDe#2)1fsoMtS*9A*7jXJXU3ss+B=dsa=N61lQ3-~?Gw*G|` zM8NymD4aO#-=b9yri@AY8G^+Y;uf7zBR{NWv-xY|fr-4JPFEiw2{V>9)D; zj%6VuA*oktl8FHj!UjISc`s^MxV5{B;O$7Hf^5w`Ht2JxxTLnm3mhG)&WO^d7%qaB zr6_Y1?p|pjoy}qBIQbRtHQvQiZnJrMt|mJCQkUEQbv4cWJ~MmeVB}YJNWZI0FU47q z*6reIJu|rcy|8!2Os-%bjgoz1I6hfX--dR=`B+xflP&B)Soz}8&kxIsuIDiP zYYwBsbmM?4%A->}4-YoYLW84AH(jphe6|m=^5;GiCZRGw5>GZ( zH?^R!?Qb#r97Az(K_U(yCQW1n@*4(b6800}I_ks9%0ni1fqS>DUmBBH)CCc%VarYB z-c#x4b6?02Uf!*E@$%ZKS&s6e5;WdojZM4S4@jU&ffNraEBBv>m(@e~CR%s*RyV;r zE4<%9cuIa{6}&$tQ~G2 z<`$8bWFh$Fz>I)FLeo>$styFO(&EspwK!|wl~LM|17#r?ah|Z;l#6%{)8_mfr=E3^ zT!t;9WA*gtHQ7ZHBY)3^b@)yp%RbpX!{(#q#8+XEubuT)^+SQNx`YHHJxS-KO#)}r z02L-_g=frq#N45QRfn&=$uH+a0E%Cu_qBE0N=ZJ64_;Oyr_({J1b9fqpX)_2KH~99p*D-s<)?5yDs;R;W0S;a3LIDCV`yyW3tX!DtpRmii@Z(;4;_iO`5 zBIJ9K7UJcj!v54<9AG*QieR#Qy834GK6y5tYF$ZKaof!ZBLx7Xc1TiSzJL-|m+>R$ zD^EJRU_QKvkbWaVLGO-)y|Re~xE8 zEKyApD8KytdyQcCI@SYQyd7fC+qjIEOlnovHpQN3sV`QYurDY&<$``&p^`KbhRJ`; z?yzV!*V0=05dz@Tn)Qm-yx(|G21*L{XV=DjZS+1Sh>KT91t@sLy**ut$+DSm7u^JR z;BUKhS&pRZ8PBng9ffJoN#V8Lx;*%P2lAp?&fZmVa;>eIPu(~AoSSa0LImxaQm6eX zlhQ(rb2q9BXXqe-)#Sf+EuSBXFvYRGb0eI-b5*G3aB6uEp()As#MxK;WSr#4!&kaV zCgVOOMLta8q5zkK`$^L|G4b!NarbiTftdKt!ZcVYhwPxSz}pzgKtB@{b8CxFzqI>& zermNl#msTWssG!gU_gw%?(;xK(Zw1Ke}ssHrkI&AmTPU)-yP> zO$}s_**Sbj#T?@OuU=$!Y(=1XJ7$1E53x_g-4D37$Ku+zKEbr~^i2-~-~AY0ZoS{1 zx8JS|Oq2|tXsbonKdjeJZp0My5DSH|T}E~E4W2(9?MDZWAhaIY`C%Yf<7{-5qP~^% z2<08Wgr%ou2SMDz#zY+ih$}_Uz(C03WYXpPZ+a+P; z>pzP`^PIH#deQnjAZN+f>rYdCe!m^<+T6iLD=}`08>8-Ii}&u)_S#lTibA9qRkmlo zv{@;~DcxTk_PK=+!%PZv(P2(lnFoF&Bo>VGO^6>It~n$HxBFEbv8DQ&wy3qrKs6rK zDLd7)ZM!XXapT@gcgMXP2keR4%F@E1PECAWz4uzRy+%@LwN>65$lIs@m)OydUmQSg zAjgVfQ&C6d3g796?7N0NhpoNcNpzuzn6^d z`RI}R4_fybA1n8X;79g(JVBA3{z+Kr0Qci%tuIwcy%D%KM@vl^*lD}DGAT@TJoZvR zwqV6A5yw%EIqw$pAA?-?zHTmJ3%%WYciC~yD?`_Aw0>gMk1-#a~~^^t9oN;+TP02q!f5u;MguU`-QXd@gcBAiZ*^qY!Dy_K?;wFrohb) zg;EvzeQ`l~_Rg~8V11}W@j`cvB2(=l@ zP@K6}VD{#-Un&~y9~Qc2J)iBB@}RV$|7}`FVE@+`ek)G={!qmX;a=~y@^tCq`?jgO zSiv-T9Btfy$@S&K$mq7d>|=4RmfB0=LW^aDiPYvPdQ}1$>P!;E%1az3>%10|Kq2kn z)`ZXkTbVk#gxf?kJ}y6}ySIf5 zyU@sHh~X0r*xlON>(UT#+LEFje&e4xZ1s3kGnr^J6Sy^dUp2?C$R_ z9}Nj_5nYHe2oWTCP~ZB8a+L3)P|DOQJR3xIy89Rscv5^LS7DwsKSV!v{x$hJ`_bQ{d!_iJbi_x;KuFh)KnzB;qAlt%kI$&=u#V8}H{{^4+E3MQ1 zg~ez(hv{^{q>um45L|aLo0XPy`Z%eE;fbO^;zefdm;`(f!6k9q{oM_De^=!3Ee)^b zb_*}p)@R4I<)>zbpM&LkFkcQI4RqJa2((>Ug-Vj9ZN+Zl#>4fGo#5!HwLrvdW+Of5 zLN*VLb;JUmQnYCPRbVK&JP~$!K8M(L0140TxzmVx-|&A!bvQqbLu0gr*SZu@l>9pQ z7)k!}YlOvRr-h5l);OwS@fSZnq?yIEJ*4nK2pkV>{~(*C(w(q8v(d>c5zmM24inQ& z>W$-dRYqmi1{$8jSPZ9{-DIDB>F5KRZd2}Y*f9cRek5aSU2B(eVD?u?k?p#6cG@YikUTD>Uaf?DfArX~ z|Ehsx9#WT38ToELfZ81o^jMFfURRxrZ!NxG!&R5bTnB>?R^~cc>*SFH4aL)>ra{$q z20txjMHKrVWYOWCe0nUC-xd0EdX-{3o;CQLGm!a){n^N?N5v1=_7Ik?_S7~K1R!Z^ zPmA;lGe8`*n6KxO2yT*YnQ%P%%k+Gq2!P__rR_%g| z*za7|jqM4j`y4GwFP{JqE73C&FnO-vKGY0TnRyZpNa-U37lN_HXwGw+WE^W9MlPxK-o^^6GXuXG;FisRfQsv>}ljP@@6sO@G z5?vIpeSb!zWNnDvp~oBN2L;?sE$no`GrxxzAZvhNY`+m-56|WDfdjAngB$UZ_V;O> z(L^jIorDX1RGzfd8b_Wu(%1) zwHzupf3zGuU^jO8c(!%I***j^U#Y(teP>iDYxaQ# zB>31NG(d^2C;_p5F_;m=@LQ1sr9?+aM?S~EDOymLJ9E~lGP&Sm66-u-!W@UmC*`Sp z>|jAXUMN2pM|qU?jo(x|=yo+VzFV5lf@hAEqYSD_gxLN3wJdcv><{^)E%suoi?}OS zEHXJaxYtRBCxoGb_sI;jiB7YeZn0Sn#j^7=DMLZ_aLg?I$KG2OJvco=!lOz4*yCh~ zk7RYt@i(DaATg#scR1@4@>(0mi|uvtwQdCIsctaSA6^$r2)?Xd95x|ROl)TFI@A#J zpY*8f1`mOW47OtdGB(>CvTmEG#c?ydq+~;)ALAh&lMzbc2WP%#nFp*B72tjOvI0a) zl-cF_LmbFFeY8?m`FRW*JTCw6h=e9##Oz3ipN#@+)lj)>oYL1UD@$J?+Z0&AF&4e4 z!NNmWcWPo6<7N6JHkpLEI~RqZ1$BM>y!Q*2Jc3IM%^OFziT>V2X)BE}ZtjaomGS`# z{jyJXOSI3=;m{JM0XuK$z7RHjar4gZLeKLE(-?=cMy>WPU)=&Xm{Qi6rlru5-nHEy z*3kj=5!N&1+687rkCj?&f|Yg!%f}SiKgkHzAs+aw11?ZCM8vM_eG2NAPeUvrN~6he$5_Ueo$-HS~y#L zvF4+>jbCRv$xmE9eMV5153l?ztJBlf75?tV*P{#iIZd9ya?p=!0v#-B`9x(x|L{9h zrk0TZB{tIE`BnMf#z24bJbUVJdV&-E)4&Qbd9_}bxCcR-KGtr9sfC3d0kpKB%;8XY zF_zgAy@SFQ0P?KTn-Ve^spvX4e*vje|M@{rIz=2Q~t0 zHL#tFl~;1cm*cL1g6NOER3qF9qLa?8QHhR$BF;hLMdXpR0upUH_6L`|In51_4!)PpqfCm zWJ3P1p;t<)Tn2xU+rT%~B{VR!1^;_h31tPd(yNA)ZF}1lr3GD~WeRaKyZSDT> zc)Io^?>OfsXTh)O)o4j@L-^Alup}r5-s;OZ$-K#nbXZ(@HfUN`P`~j-f_S^>056}5 zJxKER;pT){ZBclKM{0#Drs|Fqt%V9y^+A~u9b2}$;1f0%6t149c2ZLsgCX3XSF#;D z377XGj9Sf>f6w`pnQ?{{rgx&?-sn53RX*rXy>6WAJv@Xkvi$aK90w}I{_%ZSTGNAg z|3}vuXT*ynpmy2$4*H=J-2g0Sls0p%t;wsn%^Y!e!X(ZEwd=IgZjJe+*`Az7q;o1h zME?x*?MC7(D(_gX;7zu5(UeTnoW~6+h*1x0jcSeYZaiX4Fv(=QJX64Dx2C30Jb;KG z(Y09P)uwTi+`>fboDXYv*J5RV={DCjG4rO~-+++o{!Co_fkAILw)4&i9*5P8{~H*) z&bu9mg*1SIfPJAMfcDh0&22=#`QP9#oyD(8`8I~Uc!O>xW1;H0H?zcq2eoh*Lfxrh zGT$~pDUleykmJBLuYl;VlCT6_5W9x8qnz50w{^h`+;P)S#9IABB+sWI`p@SnUC&q5 zkmLiv<-@$~R(-b}{tc$5_u zOLfXpt20LidfsCv=y#vqre~C{N=d+7*He+D+({2gx7zu0QT}}uj@3mCn)EZN%RU&eg z4sygf5!yWAu$mn$*SolXjr>Eh`gIs3&Nx>P)1DACHZ(LeKAz&40c!y(Hz*;1C=SHp zT!`ZO8`CTNOiY(O@&Qh&R~RCurU|W(0Fy}f8CLoczo96H&+3Rg(FUq(d(DLI_YkQW zm0!C{2_7Hgen9-WtJ|~9mwwblNVP$C!}R1^}%Zj1Wb+Fy#@lk!|}a|?pl z4?hRJCNkp%(c8lqN^d8`OYY@Y=523PLfu-d-^tH5$$GE6;59>R_y+3r<})gVYz8$h zGR2jbyHx)fUSp|$s$>H}==P`IW4|A%VpQM{NO1onw9xZej5xW0cy-rv-7r&vW46=X zcFM36$Z9@C91pKr{U}7}F;6NiLRAONwLF-R(`p9MaF2aPKC^{vgvOr+1t|)~y+{hw zT|D|Z=_=7ge)bzI)q)z(XAI0OESmA|he9cb|JRr7iwONk^2CsJ2%Uw+RjZe~Qp;v| z8A#{dneRWadW%*tMLBylLe$JeZ%M}XO0aN_^Z_4QX5i^>50dM4cT@SMIAAM^?V5ex zKne3DL3u5+Km;zQnJ)II>jH z?&qwAKBH4$LijM*YEbalItr?Q1Qf#FP?8DBlsYgll|h#b5hOqLS?PdMj`KY+#%8-V zHG1mZ^U-wUC1HoBFxdmvW>yG4eA%(jn#_bf&CTz-5Ig+(V(AR+a)LE~9N5at*xALT zyNg{JNG6Jo4RfQd0<70+N!T>UsNNz4$h4;ukDHt4GR7gO(?I z_MVjNBkh`&%^y6d8SbT8ZJi86A1X7$6%Sa9`=s)AZoLt{Vsy4yp>Df;p`z6J!t5u- zg#0NEJH#RRB%!neS~#{S4OK5ECFG?6(=Y*&X6-Jx{iEQANKH6v<<$6uLzUB%*$?Ib;I!{4Bj{;2~*r3zLBTk=v%wdS=>9rNUuo$8Sk0@2rTJ z3cxI!aWiEJcWGX`-+lap**26HD_-#KA^L<8h*tfswZ2ynu9p7rJN}fU1 z$@V_TPh_1El}hugx4XttZbf)l@A|^kV3*%$=F~EYcI%~Se45FFgHkE~#2Nek7UOG% ztK>~QmX{y$NgE<#RtPt9fB<{4k5#C3K4vop{M%?~dTKI|9zvw`cQ{mK?hv>3*+qwM zN7LP1GkUrj|KgD~Ta_B0`mRi@CpA+lOA&WbyLAVql|@IC_UyhlP^#3`1RgOg?R9y>?AB zNWRRl-u(&Y3;!F(l#_9%_r@x{Sls!!1(BqUfQ)xZrQ22_k|h8S+@`1vhk=KDqt~hc zOoKs74dgu*XODq{K-srLHP%IHTP^3G>zr7TZA01TTqDGprXt~f%O5IPJovLfb6_sz zEB{H(jqqYsuvReK;+9ApPife7fIfmc#YIi;tPOKorcL*vOF>nJoEi+upr1+`fcqBB2plGf33tw6;YY@!#-CZI0=%_>UmhnKn0sCv*k%S#r? zbyuwr8G0JSFP#gz;_!Np-S4VM=;d$U)Xw5Z4MY@Tf^@K5+^lG0FveBwGO(X^aQ?=; zpk$(T5s~*72W3W1RO3pS@p0a{uaiD|S?+9aRx{fU!vMMGj(E>>Ms(zeVF|vUYr{sq zXOra4-AK;O@B+J0rlRNxXS^+tNxUSHBqd|P2NMa0azrrn;HKzI3Lsl;6K*QMF<|c= z8rC@iv|VSQ44HRGjv`EdFXTmTAHC1doTWk$*`_z^v;C3~G};od&;iCp;y%VV@zfFQ z0sbZ~H>}@ZJqW+a`pm^X;h+B2{2@E*JXR~^0UxRzL&f0jc-8tu5<&>=GV9w`_hb4_^NNk%$sqM1x=R=Zb@7 zV!BFj`sPkgr`Qp!k5@&A;YV`VF8WQJB!sXnjwV=UG39bg`BV2(ZC5S|%)b^f-*JA# zce({gYe1ujjea`#xgSRC;;1m&pjsOvLvQ+CMSx`_6dZ~p3*C^fc+hPDxHCP*ev1iV zW$_D{){!{pew8Q>)hg$h7?RcmPV$Y>Jo*DY%{NV%ts2;qcJ(7yV2wJ$5a5#?0cYyg=5P=`PZ#kjsU2cF zR}34iiRAs4(Ebr$Ki2u~q8W9*+o@&Er0&)p!^_~EbdJ+}FO*T#Ll9nmAIHe6Yy<~FFduDCMs3E#n1 zNVudHPCOtfp&5`-pwdwfrC>-L%09}LV^mHHN01Rm*=amXsszFT*1DOd*Q-=S)N!!M z`I=xbtEd)Z{e?kj2A-qOP}poKAuTfu8t=;#C5cT47!@QM&!AOcN4xC~)OXT#JunXY z41H1s%H!s7llD_w>HD{jv(u(N41wjGCSulL6y6o%Ueu6CvFk2d z9RRJ`2w{XTa5VYK05cUxYT~YTL(c}D7@B&0l9OShtOw|E8>b=Ked;W-N)>ph&hJf;=!6IQDG23+acARDkopM~N(MH3OH z;5+QV_+JI!MVm6F(K1K3a(qYU425QzeP<<>*P5oc5ZFvni)qnCt@KJBU~2J(XZrG? z6_^}IoXDc2tljjrcUWcH>5}qyR3HwBI4X`CCu!|7XqCC0WdY4vhs?8fO;93c^%p)O zF9!mtca672FG_iATA`YH*q9@kw62KEuoZ*EOR^5OEOZBUP?WT)?^|^4TJ<23fF>>d z%CUXi#Y}UGLOIL$Tn*HRY1*Lq_LgOi=M-i%bT!8M)<1zCxr*#8_E4J}PSO!mJg9%d zzLL}*5E8?=`5~Lwk&J;cvSRx8-$c1`m<$t6^3r?`JF&R8$%yc0>R%n?1=KvzZB$8x zVFYA>NeMVsqdOYyLs0vaTOwZpA0$hD{$t=McP3@)&(saC_ovP9emB@I3#^kmmua9SSc&T}mb+ zR%CP#!|B%yKC*hAuNK3Yn$06vtNqq0?>O~r84~y=9R;hi0H)?rv)YR14+u$YC z-nIJyYlUkK-7VwzdzTVyhRIb$^N3O!P9##MLjLEUuhJhS{tKLRGbI0}c7`_;eSIwm z>8})Y$A%11vq`+^{t$YiyA^MFC%5yyz%>W=@Ss4sMhP~}d3wzFbSZ zkd%0{8uj1w--;5`W*&j`M4D4(3$3`w?n4`H!T24d- zieZj6?`x?SL>)l(oytCpjZeB#&Gd$*{K3Uu7WN5J`ZZ47+}gvSe9RT~Fu*sP$%Sw- ze~fXLRk7$UDjXRgcDtbU#C=}v%QhLM$TIMoQM-_~A3!1BQU;&q{GGk#0Y+XQ$*2;l35~?K2Y!{?Oi+T*|&?5Q2&LNtw z_XubDvz30RYelgCYT~|zjEmzq;+|TRgAsxFq4c#C#RQ2f$L_T950rE=u9vV&h{qm8 zy$(+|>6-K@38$j_tc-o`9Ayr&@_c}{Q&f4fSlIuMaXPtj)5<;%RKEwQ6Iq8b9S`~+ z&@hBy0y)r)6zbN~;F3RV#kB4xfuPMMP+IO33Yj%|XqByNjpjXLEtzB#ne7|Qiank= zYMW=$+eov{zG5=v{DjoR&Q*SMnCRjx{qb6UNr~c7>it@N85z*L>L0B=!ccsK{M=-P zXd#!@38_mAe=k`g@x%3faSvk1wYjuu+j-bWKE-+_&7Q^JSOC)${J;g~W-l*{8T4+bi)W0V*P$G~!CeXVM!g*1xCXkIM(PN#+&RKy;7A zjzrab|LTy)(32F*BB6s=FqUcYAs5u)7Rgj~4@4^Yzt)Rl zty1>;nhKj>YVu$gf_Eyo4cc{NQC@@cY+Gay>0*V{hsu6UkhOYRfu=9%p5bMGtwb1! z4S`6)!2iWaxr#43+p7La z3BKkBn)G={<)C!}cFKkAUTsn2O4_AZAF7`v$@I^?(40oGY_j3((BSaeODtTga#6GBMT_DzDR2Eq!sN9o8B@N zTvMJ#ZE_HTvohrmD2KZ_Z$?UY(q(l%nFesWX!mLsdL#UB4WJf5sM^j?cZ^fzSyB__ zcpK3=mYvQt=Sy#KAeCavN!##8t$CzAdm#Mbh>hGpPuwFT*e9vtlO~U4CHV0AUHu4i zTAYPNUUKPvsw=%r;MhD($rggf9P&MTPSKzNE9Ey^ZRHmddZwZ5d zucxpYg(~e7wMBW~oW>_Z;pq`BA5!0052jJXhjwaO=Og?0GCXa3h#_9+qgRf6Lq^0p z5`iaOiM@N8^>qveZCof+Ofdb;J8nj<-^wuVHmJ(i z2tOID#IjtWlLS$a`k+SH+IK%+igD6EHdJ&P1hhzMz^6)t0O+@h|M0SNAjRmw8(Ed@ z8wNCgoDVl0PNa6s1Zh?fYB7}H&d5=oy|)z{OaqgR7NqWn8A>!rj2OV#68)(grTWepKse{oNQne}#CG^4H7>T= z2^*fCx@RUmu1C+na<0wjCp+&<`UA9ml<5vHyV?{*N&)H&s~P<@!wX=9#mymUVJlGzNEvm<+;uHm>*pGE~1v!jm& zgO~`zPUTP5FgeJR#R}lGdr1r35Dd^PKdn8&S5fDcvp6oE9%{(Zn-*$O{ftayJP=WQ zqb=ELQ!j0p#SsIUGxRS3d-h@MNj-^@EjkS)2!b3+H$S%LZeGY@BNR{S0zIUd*yr-f z;*VRP_29JzYH|8vd*?lHs_hy#ON)A@Y&yz}Bvd?&&8k4Tz;~l8t4({loMfS(t%hj- z@Ro6O<*2?mx;FL)vFrB+@DNkJC#A(qV->c`QM0X^CG*1was_-bLR9R|8!tKw2~cgl zm}Fb)!FibsigGIqA_?%_T7b1Qja}p~DU+9_ViEeH@U(&TPK{o$HD zDppvBPJDaJCL!!syQTcG8xAla@QJ7 zSg(#$J7y?ppmD|-trvNgDDq|_YJED6fL3g%|L(gGo&JzHl3EejveDo| z|KG2F``Q%y+As*|jtzDB*D69fMWg~Wg%*J{kYHE_Z`;Vdei6g}tkA83C`SwV`5jUr zm^P?5@wKf4&J!~mu*Ht`dJCrJ%)Pr1? znvJeNAy5_#K?r2W=WI660r%Px3z@?A!WmvZ>W8y_k{5#$gqnB(uf~&QL63ctwB2u1 zrMBk5KJTxU4jS2-?6UA;075_F-bJ&0MEtK2OTiktu4)yB>c}M8xAzCtS&z3{WeSjv z$fv;&gqyDWdu#U<*Axbm{(P`@l*1BPMH7C%ZJa+p9xkRev;Xb>tVB9lkJ)A;d>q-k zyKC_BNV$us>5~t@qV;A>5Q+gURnAitFZh$?I@Fu16C6 z}Gbhan;6hV17v z%!9sOo7>P#S=~1{6-8hjkIBwHaHE~R_v?W=qNTQ|lSg#W+~ksyA>-s~?m~*TwJ#;b z>}y-n>qg(swAy$1DhNHvPVS7796tR1{ZljqooLbBV6AFHm(Tt1@f1qspdbXDK_ z`yVHMCKCj88V~$-Wv*V))p6Q7jWh0#AqpVkbK3f(N-*RT*rSr!{4%s=yF+^pvwR+CA!`uD=AiAkDnTUYV>)56ypUTAwga{lL^Kdb zBmajDH&p&V0Y(P7`Rk!0hQGY_eZ`;-hH>MCV`MDwhBoV`Y94t3%%7oBqob!30%jST5lC;=3CE7haC;FBwkv` zw7oSKobv2U2?D7#K@bEH3h}9RuU@?tKDKb}x^-JN7QMf7=eBKIi;9XiYA0t2GfEQfq=B z2qF|nty2i8H9-&r5elT%DTLITAP9m81ybu2LTXJA1VMxXsdWk=wI&FHAVR^S)&xNi z1VN-Brdm(fSUlcp6E_t5FB#n756 z$qiwoD6?d3VlBWBK(qL11a^(zTs*#r8w>B2wu#xqO}i#<_OwZxc0aJGL>Z!!Ht&95 z^DbrgGusWD$ZY})W8ov>y_9I(A?z^b1262f%@)($Ku3BOe9-(cx|1e)QO#O&;gT?f zi(q@k7VQ~RwCBE}J>!c?c#1M!#%u@u$|2lWR5H3~x3V!sC1^w#8btJ7i^(jb0DAE< zR$UYuXYt3(^)U>AkAl^OA

    QW@$>4R0TxXC@HH8V=2a{rD-KmYwYF{(^$)_0DdB@ zhAfPC!Fo4LHgbQ_o(I@ZTw-B-MJe0F4HshLF5M<*#!~dlButiM3;uykyC-kjosYog z64(Sb5PenXUNM^he|Sk40?JjSPvnL~W<~6$D5h+pwW)D(D%hN3K3RA(Ce56141ZG5 zp2?c!TceY=ln9%$rDWRH-P7^2sHC81H|)VJB{Q~^%-p(r*47dj0)<<4BL#+HFc#j* zY&y4TTlY-eQZluOH6pBVOUaxqyXR^)Q`F-2V9}mwnjy*(x9&kZ_z9b_b=xHLe+yRE9{gmpp$fD4XFoB($(uDZ+=IbebToq(Mim648RNntf#IUh+p7`W7jm7zp zKsTEtB%BL2v{p$q3m`?;X~UrF!jwGYr`dw&aTBWx6M8QMTSQs2n~U$?Ts*O;cmizm zF1G8b9fWUu`3{lRY&RAnjEOW?N~EYY>S|oSnHl=cHbl0=VyD~W*zWl&26I=1@hz1F zG(CnXsfOLp^wrG5pmYa#U)ts?dlBvHSxD5>8YU#ilq(@=hOn{nnxCu+Z+vqJBw1H$ zvGWQ;Q#Q38t%(-4Z+Riyja4^ZJ-~KxGyKuIkW%Vqq9daPVW^81L{nxv!3{zsOv)96 z3i`@^vZZCLE)}# zvluhsn=}l;rokAsa1{ZkJPYHmXjuRS^wwbFMU1#!xG2JKf%M@k!G=`x4N)^gt%Y&< zfljbn6@lqYp0WR87cQB}!)jla#?{);Y^IcKpVj1i&Xy8gt!HhqN`4VHtvnQ3S)r!Z zv$=_|6lrCeT0_X$5HvINl^J9}hyfIWn-B(z$RR4yl}+I?kLo-Zde0;uDOxQyX}aNs zjvAEHkc(z*Vhm%uB2F*-0OM3^RB>ptJw=Epe|=z>q1LbmnP6KkH(sKNaS20pq1G6q zrq(b|wVqkDrx3W5W)frtQq6x(FDjk}6KY+w`~L%p_xHOS_?R{T0000< KMNUMnLSTZPWX3rF diff --git a/docs/images/sync-example-files.gv b/docs/images/sync-example-files.gv deleted file mode 100644 index 1b1ac78c..00000000 --- a/docs/images/sync-example-files.gv +++ /dev/null @@ -1,17 +0,0 @@ -digraph "Sync Files" { - graph [ - ranksep = "0.7", - nodesep = "0.5", - ]; - node [ - fontname = "monospace", - shape = "record", - ]; - - my_model [label = "MyModel"] - init_server [label = "init.server.lua"] - foo [label = "foo.lua"] - - my_model -> init_server - my_model -> foo -} \ No newline at end of file diff --git a/docs/images/sync-example-files.svg b/docs/images/sync-example-files.svg deleted file mode 100644 index 64de9f10..00000000 --- a/docs/images/sync-example-files.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - -Sync Files - - -my_model - -MyModel - - -init_server - -init.server.lua - - -my_model->init_server - - - - -foo - -foo.lua - - -my_model->foo - - - - - diff --git a/docs/images/sync-example-instances.gv b/docs/images/sync-example-instances.gv deleted file mode 100644 index 4902a8b1..00000000 --- a/docs/images/sync-example-instances.gv +++ /dev/null @@ -1,15 +0,0 @@ -digraph "Sync Files" { - graph [ - ranksep = "0.7", - nodesep = "0.5", - ]; - node [ - fontname = "monospace", - shape = "record", - ]; - - my_model [label = "MyModel (Script)"] - foo [label = "foo (ModuleScript)"] - - my_model -> foo -} \ No newline at end of file diff --git a/docs/images/sync-example-instances.svg b/docs/images/sync-example-instances.svg deleted file mode 100644 index 24f4a52d..00000000 --- a/docs/images/sync-example-instances.svg +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - -Sync Files - - -my_model - -MyModel (Script) - - -foo - -foo (ModuleScript) - - -my_model->foo - - - - - diff --git a/docs/images/sync-example-json-model.gv b/docs/images/sync-example-json-model.gv deleted file mode 100644 index 376108d3..00000000 --- a/docs/images/sync-example-json-model.gv +++ /dev/null @@ -1,17 +0,0 @@ -digraph "Sync Files" { - graph [ - ranksep = "0.7", - nodesep = "0.5", - ]; - node [ - fontname = "monospace", - shape = "record", - ]; - - model [label = "My Cool Model (Folder)"] - root_part [label = "RootPart (Part)"] - send_money [label = "SendMoney (RemoteEvent)"] - - model -> root_part - model -> send_money -} \ No newline at end of file diff --git a/docs/images/sync-example-json-model.svg b/docs/images/sync-example-json-model.svg deleted file mode 100644 index 27dd3251..00000000 --- a/docs/images/sync-example-json-model.svg +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - -Sync Files - - -model - -My Cool Model (Folder) - - -root_part - -RootPart (Part) - - -model->root_part - - - - -send_money - -SendMoney (RemoteEvent) - - -model->send_money - - - - - diff --git a/docs/index.md b/docs/index.md deleted file mode 100644 index 19c949e0..00000000 --- a/docs/index.md +++ /dev/null @@ -1,18 +0,0 @@ -This is the documentation home for **the Rojo `master` branch**. - -!!! warning - Documentation here may not apply to the latest release of Rojo yet. - - For documentation for the latest stable release series, 0.5.x, go to: - - [https://rojo.space/docs/0.5.x](https://rojo.space/docs/0.5.x) - -Available versions of these docs: - -* [Latest version from `master` branch](https://rojo.space/docs/latest) -* [0.5.x](https://rojo.space/docs/0.5.x) -* [0.4.x](https://rojo.space/docs/0.4.x) - -**Rojo** is a tool designed to enable Roblox developers to use professional-grade software engineering tools. - -This documentation is a continual work in progress. If you find any issues, please file an issue on [Rojo's issue tracker](https://github.com/rojo-rbx/rojo/issues)! \ No newline at end of file diff --git a/docs/internals/overview.md b/docs/internals/overview.md deleted file mode 100644 index 186a5e02..00000000 --- a/docs/internals/overview.md +++ /dev/null @@ -1,45 +0,0 @@ -This document aims to give a general overview of how Rojo works. It's intended for people who want to contribute to the project as well as anyone who's just curious how the tool works! - -[TOC] - -## CLI - -### RbxTree -Rojo uses a library named [`rbx_tree`](https://github.com/LPGhatguy/rbx-tree) as its implementation of the Roblox DOM. It serves as a common format for serialization to all the formats Rojo supports! - -Rojo uses two related libraries to deserialize instances from Roblox's file formats, `rbx_xml` and `rbx_binary`. - -### In-Memory Filesystem (IMFS) -Relevant source files: - -* [`server/src/imfs.rs`](https://github.com/LPGhatguy/rojo/blob/master/server/src/imfs.rs) -* [`server/src/fs_watcher.rs`](https://github.com/LPGhatguy/rojo/blob/master/server/src/fs_watcher.rs) - -Rojo keeps an in-memory copy of all files that it needs reasons about. This enables taking fast, stateless, tear-tree snapshots of files to turn them into instances. - -Keeping an in-memory copy of file contents will also enable Rojo to debounce changes that are caused by Rojo itself. This'll happen when two-way sync finally happens. - -### Snapshot Reconciler -Relevant source files: - -* [`server/src/snapshot_reconciler.rs`](https://github.com/LPGhatguy/rojo/blob/master/server/src/snapshot_reconciler.rs) -* [`server/src/rbx_snapshot.rs`](https://github.com/LPGhatguy/rojo/blob/master/server/src/rbx_snapshot.rs) -* [`server/src/rbx_session.rs`](https://github.com/LPGhatguy/rojo/blob/master/server/src/rbx_session.rs) - -To simplify incremental updates of instances, Rojo generates lightweight snapshots describing how files map to instances. This means that Rojo can treat file change events similarly to damage painting as opposed to trying to surgically update the correct instances. - -This approach reduces the number of desynchronization bugs, reduces the complexity of important pieces of the codebase, and makes writing plugins a lot easier. - -### HTTP API -Relevant source files: - -* [`server/src/web.rs`](https://github.com/LPGhatguy/rojo/blob/master/server/src/web.rs) - -The Rojo live-sync server and Roblox Studio plugin communicate via HTTP. - -Requests sent from the plugin to the server are regular HTTP requests. - -Messages sent from the server to the plugin are delivered via HTTP long-polling. This is an approach that uses long-lived HTTP requests that restart on timeout. It's largely been replaced by WebSockets, but Roblox doesn't have support for them. - -## Roblox Studio Plugin -TODO \ No newline at end of file diff --git a/docs/reference/full-vs-partial.md b/docs/reference/full-vs-partial.md deleted file mode 100644 index 91003f0d..00000000 --- a/docs/reference/full-vs-partial.md +++ /dev/null @@ -1,37 +0,0 @@ -Rojo is designed to be adopted incrementally. How much of your project Rojo manages is up to you! - -There are two primary categories of ways to use Rojo: *Fully Managed*, where everything is managed by Rojo, and *Partially Managed*, where Rojo only manages a slice of your project. - -## Fully Managed -In a fully managed game project, Rojo controls every instance. A fully managed Rojo project can be built from scratch using `rojo build`. - -Fully managed projects are most practical for libraries, plugins, and simple games. - -Rojo's goal is to make it practical and easy for _every_ project to be fully managed, but we're not quite there yet! - -### Pros -* Fully reproducible builds from scratch -* Everything checked into version control - -### Cons -* Without two-way sync, models have to be saved manually - * This can be done with the 'Save to File...' menu in Roblox Studio - * This will be solved by Two-Way Sync ([issue #164](https://github.com/LPGhatguy/rojo/issues/164)) -* Rojo can't manage everything yet - * Refs are currently broken ([issue #142](https://github.com/LPGhatguy/rojo/issues/142)) - -## Partially Managed -In a partially managed project, Rojo only handles a slice of the game. This could be as small as a couple scripts, or as large as everything except `Workspace`! - -The rest of the place's content can be versioned using Team Create or checked into source control. - -Partially managed projects are most practical for complicated games, or games that are migrating to use Rojo. - -### Pros -* Easier to adopt gradually -* Integrates with Team Create - -### Cons -* Not everything is in version control, which makes merges tougher -* Rojo can't live-sync instances like Terrain, MeshPart, or CSG operations yet - * Will be fixed with plugin escalation ([issue #169](https://github.com/LPGhatguy/rojo/issues/169)) \ No newline at end of file diff --git a/docs/reference/project-format.md b/docs/reference/project-format.md deleted file mode 100644 index fa27c3c8..00000000 --- a/docs/reference/project-format.md +++ /dev/null @@ -1,151 +0,0 @@ -[TOC] - -## Project File -Rojo projects are JSON files that have the `.project.json` extension. They have the following fields: - -* `name`: A string indicating the name of the project. This name is used when building the project into a model or place file. - * **Required** -* `tree`: An [Instance Description](#instance-description) describing the root instance of the project. - * **Required** -* `servePort`: The port that `rojo serve` should listen on. Passing `--port` will override this setting. - * **Optional** - * Default is `34872` -* `servePlaceIds`: A list of place IDs that this project may be live-synced to. This feature can help prevent overwriting the wrong game with source from Rojo. - * **Optional** - * Default is `null` - -## Instance Description -Instance Descriptions correspond one-to-one with the actual Roblox Instances in the project. - -* `$className`: The ClassName of the Instance being described. - * **Optional if `$path` is specified.** -* `$path`: The path on the filesystem to pull files from into the project. - * **Optional if `$className` is specified.** - * Paths are relative to the folder containing the project file. -* `$properties`: Properties to apply to the instance. Values should be [Instance Property Values](#instance-property-value). - * **Optional** -* `$ignoreUnknownInstances`: Whether instances that Rojo doesn't know about should be deleted. - * **Optional** - * Default is `false` if `$path` is specified, otherwise `true`. - -All other fields in an Instance Description are turned into instances whose name is the key. These values should also be Instance Descriptions! - -Instance Descriptions are fairly verbose and strict. In the future, it'll be possible for Rojo to [infer class names for known services like `Workspace`](https://github.com/LPGhatguy/rojo/issues/179). - -## Instance Property Value -There are two kinds of property values on instances, **implicit** and **explicit**. - -In the vast majority of cases, you should be able to use **implicit** property values. To use them, just use a value that's the same shape as the type that the property has: - -```json -"MyPart": { - "$className": "Part", - "$properties": { - "Size": [3, 5, 3], - "Color": [0.5, 0, 0.5], - "Anchored": true, - "Material": "Granite" - } -} -``` - -`Vector3` and `Color3` properties can just be arrays of numbers, as can types like `Vector2`, `CFrame`, and more! - -Enums can be set to a string containing the enum variant. Rojo will raise an error if the string isn't a valid variant for the enum. - -There are some cases where this syntax for assigning properties _doesn't_ work. In these cases, Rojo requires you to use the **explicit** property syntax. - -Some reasons why you might need to use an **explicit** property: - -* Using exotic property types like `BinaryString` -* Using properties added to Roblox recently that Rojo doesn't know about yet - -The shape of explicit property values is defined by the [rbx-dom](https://github.com/LPGhatguy/rbx-dom) library, so it uses slightly different conventions than the rest of Rojo. - -Each value should be an object with the following required fields: - -* `Type`: The type of property to represent. - * [Supported types can be found here](https://github.com/LPGhatguy/rbx-tree#property-type-coverage). -* `Value`: The value of the property. - * The shape of this field depends on which property type is being used. `Vector3` and `Color3` values are both represented as a list of numbers, while `BinaryString` expects a base64-encoded string, for example. - -Here's the same object, but with explicit properties: - -```json -"MyPart": { - "$className": "Part", - "$properties": { - "Size": { - "Type": "Vector3", - "Value": [3, 5, 3] - }, - "Color": { - "Type": "Color3", - "Value": [0.5, 0, 0.5] - }, - "Anchored": { - "Type": "Bool", - "Value": true - }, - "Material": { - "Type": "Enum", - "Value": 832 - } - } -} -``` - -## Example Projects -This project bundles up everything in the `src` directory. It'd be suitable for making a plugin or model: - -```json -{ - "name": "AwesomeLibrary", - "tree": { - "$path": "src" - } -} -``` - -This project describes the layout you might use if you were making the next hit simulator game, *Sisyphus Simulator*: - -```json -{ - "name": "Sisyphus Simulator", - "tree": { - "$className": "DataModel", - - "HttpService": { - "$className": "HttpService", - "$properties": { - "HttpEnabled": true - } - }, - - "ReplicatedStorage": { - "$className": "ReplicatedStorage", - "$path": "src/ReplicatedStorage" - }, - - "StarterPlayer": { - "$className": "StarterPlayer", - - "StarterPlayerScripts": { - "$className": "StarterPlayerScripts", - "$path": "src/StarterPlayerScripts" - } - }, - - "Workspace": { - "$className": "Workspace", - "$properties": { - "Gravity": 67.3 - }, - - "Terrain": { - "$path": "Terrain.rbxm" - } - } - } -} -``` \ No newline at end of file diff --git a/docs/reference/sync-details.md b/docs/reference/sync-details.md deleted file mode 100644 index eeb88853..00000000 --- a/docs/reference/sync-details.md +++ /dev/null @@ -1,157 +0,0 @@ -This page aims to describe how Rojo turns files on the filesystem into Roblox objects. - -[TOC] - -## Overview -| File Name | Instance Type | -| -------------- | ------------------------- | -| any directory | `Folder` | -| `*.server.lua` | `Script` | -| `*.client.lua` | `LocalScript` | -| `*.lua` | `ModuleScript` | -| `*.csv` | `LocalizationTable` | -| `*.txt` | `StringValue` | -| `*.model.json` | Any | -| `*.rbxm` | Any | -| `*.rbxmx` | Any | -| `*.meta.json` | Modifies another instance | - -## Limitations -Not all property types can be synced by Rojo in real-time due to limitations of the Roblox Studio plugin API. In these cases, you can usually generate a place file and open it when you start working on a project. - -Some common cases you might hit are: - -* Binary data (Terrain, CSG, CollectionService tags) -* `MeshPart.MeshId` -* `HttpService.HttpEnabled` - -For a list of all property types that Rojo can reason about, both when live-syncing and when building place files, look at [rbx-dom's type coverage chart](https://github.com/rojo-rbx/rbx-dom#property-type-coverage). - -This limitation may be solved by [issue #205](https://github.com/rojo-rbx/rojo/issues/205) in the future. - -## Folders -Any directory on the filesystem will turn into a `Folder` instance unless it contains an 'init' script, described below. - -## Scripts -The default script type in Rojo projects is `ModuleScript`, since most scripts in well-structued Roblox projects will be modules. - -If a directory contains a file named `init.server.lua`, `init.client.lua`, or `init.lua`, that folder will be transformed into a `*Script` instance with the contents of the 'init' file. This can be used to create scripts inside of scripts. - -For example, these files: - -![Tree of files on disk](../images/sync-example-files.svg) -{: align="center" } - -Will turn into these instances in Roblox: - -![Tree of instances in Roblox](../images/sync-example-instances.svg) -{: align="center" } - -## Localization Tables -Any CSV files are transformed into `LocalizationTable` instances. Rojo expects these files to follow the same format that Roblox does when importing and exporting localization information. - -## Plain Text Files -Plain text files (`.txt`) files are transformed into `StringValue` instances. This is useful for bringing in text data that can be read by scripts at runtime. - -## JSON Models -Files ending in `.model.json` can be used to describe simple models. They're designed to be hand-written and are useful for instances like `RemoteEvent`. - -A JSON model describing a folder containing a `Part` and a `RemoteEvent` could be described as: - -```json -{ - "Name": "My Cool Model", - "ClassName": "Folder", - "Children": [ - { - "Name": "RootPart", - "ClassName": "Part", - "Properties": { - "Size": { - "Type": "Vector3", - "Value": [4, 4, 4] - } - } - }, - { - "Name": "SendMoney", - "ClassName": "RemoteEvent" - } - ] -} -``` - -It would turn into instances in this shape: - -![Tree of instances in Roblox](../images/sync-example-json-model.svg) -{: align="center" } - -!!! warning - Starting in Rojo 0.5.0 (stable), the `Name` field is no longer required. The name of the top-level instance in a JSON model is now based on its file name, and the `Name` field is now ignored. - - Rojo will emit a warning if the `Name` field is specified and does not match the file's name. - -## Binary and XML Models -Rojo supports both binary (`.rbxm`) and XML (`.rbxmx`) models generated by Roblox Studio or another tool. - -Support for the `rbxmx` is very good, while support for `rbxm` is still very early, buggy, and lacking features. - -For a rundown of supported types, check out [rbx-dom's type coverage chart](https://github.com/rojo-rbx/rbx-dom#property-type-coverage). - -## Meta Files -New in Rojo 0.5.0-alpha.12 are meta files, named `.meta.json`. - -Meta files allow attaching extra Rojo data to models defined in other formats, like Roblox's `rbxm` and `rbxmx` model formats, or even Lua scripts. - -This can be used to set Rojo-specific settings like `ignoreUnknownInstances`, or can be used to set properties like `Disabled` on a script. - -Meta files can contain: - -* `className`: Changes the `className` of a containing `Folder` into something else. - * Usable only in `init.meta.json` files -* `properties`: A map of properties to set on the instance, just like projects - * Usable on anything except `.rbxmx`, `.rbxm`, and `.model.json` files, which already have properties -* `ignoreUnknownInstances`: Works just like `$ignoreUnknownInstances` in project files - -### Meta Files to set Rojo metadata -Sometimes it's useful to apply properties like `ignoreUnknownInstances` on instances that are defined on the filesystem instead of within the project itself. - -If your project has `hello.txt` and there are instances underneath it that you want Rojo to ignore when live-syncing, you could create `hello.meta.json` with: - -```json -{ - "ignoreUnknownInstances": true -} -``` - -### Meta Files for Disabled Scripts -Meta files can be used to set properties on `Script` instances, like `Disabled`. - -If your project has `foo.server.lua` and you want to make sure it would be disabled, you could create a `foo.meta.json` next to it with: - -```json -{ - "properties": { - "Disabled": true - } -} -``` - -### Meta Files for Tools -If you wanted to represent a tool containing a script and a model for its handle, create a directory with an `init.meta.json` file in it: - -```json -{ - "className": "Tool", - "properties": { - "Grip": [ - 0, 0, 0, - 1, 0, 0, - 0, 1, 0, - 0, 0, 1 - ] - } -} -``` - -Instead of a `Folder` instance, you'll end up with a `Tool` instance with the `Grip` property set! \ No newline at end of file diff --git a/docs/requirements.txt b/docs/requirements.txt deleted file mode 100644 index 51b61b75..00000000 --- a/docs/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -mkdocs -mkdocs-material -pymdown-extensions \ No newline at end of file diff --git a/docs/rojo-alternatives.md b/docs/rojo-alternatives.md deleted file mode 100644 index 247dad7b..00000000 --- a/docs/rojo-alternatives.md +++ /dev/null @@ -1,23 +0,0 @@ -There are a number of existing plugins for Roblox that move code from the filesystem into Roblox. - -Besides Rojo, you might consider: - -* [rbxmk by Anaminus](https://github.com/anaminus/rbxmk) -* [Rofresh by Osyris](https://github.com/osyrisrblx/rofresh) -* [RbxRefresh by Osyris](https://github.com/osyrisrblx/RbxRefresh) -* [Studio Bridge by Vocksel](https://github.com/vocksel/studio-bridge) -* [Elixir by Vocksel](https://github.com/vocksel/elixir) -* [RbxSync by evaera](https://github.com/evaera/RbxSync) -* [CodeSync by MemoryPenguin](https://github.com/MemoryPenguin/CodeSync) -* [rbx-exteditor by MemoryPenguin](https://github.com/MemoryPenguin/rbx-exteditor) - -So why did I build Rojo? - -Each of these tools solves what is essentially the same problem from a few different angles. The goal of Rojo is to take all of the lessons and ideas learned from these projects and build a tool that can solve this problem for good. - -Additionally: - -* I think that this tool needs to be built in a compiled language without a runtime, for easy distribution and good performance. -* I think that the conventions promoted by other sync plugins (`.module.lua` for modules, as well a single sync point) are sub-optimal. -* I think that I have a good enough understanding of the problem to build something robust. -* I think that Rojo should be able to do more than just sync code. \ No newline at end of file diff --git a/docs/why-rojo.md b/docs/why-rojo.md deleted file mode 100644 index 279cb022..00000000 --- a/docs/why-rojo.md +++ /dev/null @@ -1,44 +0,0 @@ -Adding a tool like Rojo to your Roblox workflow can be daunting, but it comes with some key advantages. - -[TOC] - -## Rojo at RDC 2019 -Nathan Riemer (Kampfkarren) gave a talk at RDC 2019 talking about some of the benefits of using a tool like Rojo. - - - -## External Text Editors -Rojo opens the door to use the absolute best text editors in the world and their rich plugin ecosystems. - -Some very popular editors include [Visual Studio Code](https://code.visualstudio.com) and [Sublime Text](https://www.sublimetext.com). - -These advanced text editors have features like multi-cursor editing, go-to symbol, multi-file regex find and replace, bookmarks and much more. - -Many Rojo VS Code users also use extensions like: - -* [vscode-rbxlua](https://marketplace.visualstudio.com/items?itemName=AmaranthineCodices.vscode-rbxlua) -* [Roblox Lua Autocompletes](https://marketplace.visualstudio.com/items?itemName=Kampfkarren.roblox-lua-autofills) -* [TabNine](https://tabnine.com) - -## Version Control -By building your game (or just the scripts) as individual files on the filesystem, it becomes easy to start using professional-grade version control tools like [Git](https://git-scm.com) and [GitHub](https://github.com). - -Hundreds of thousands of companies and individual developers use Git to version their software projects. With Rojo, Roblox developers can take advantage of the best collaboration tool around. - -Using a repository hosting service like GitHub or GitLab brings powerful features to Roblox developers like code reviews and issue tracking that professional engineers can't live without. - -## TypeScript -TypeScript enables static type safety, which helps prevent typos and adds unparalleled autocompletion. It also brings features like arrow functions, object destructuring, functional programming methods, and more! - -With Rojo, you can use [roblox-ts](https://roblox-ts.github.io) to compile TypeScript to Lua and take advantage of a huge ecosystem of TypeScript tooling. - -It's also possible to use other languages that compile to Lua like [MoonScript](https://moonscript.org) and [Haxe](https://haxe.org). - -## Other Tools -There are decades of excellent tools available that operate on files. With Rojo, it's possible to take advantage of any of them! - -Popular tools include: - -* [luacheck](https://github.com/mpeterv/luacheck), a static analysis tool to help you write better Lua -* [ripgrep](https://github.com/BurntSushi/ripgrep), an extremely fast code search tool -* [Tokei](https://github.com/XAMPPRocky/tokei), a tool for statistics like lines of code diff --git a/mkdocs.yml b/mkdocs.yml deleted file mode 100644 index c5f86297..00000000 --- a/mkdocs.yml +++ /dev/null @@ -1,37 +0,0 @@ -site_name: Rojo Documentation -repo_name: rojo-rbx/rojo -repo_url: https://github.com/rojo-rbx/rojo - -theme: - name: material - palette: - primary: 'Red' - accent: 'Red' - -nav: - - Home: index.md - - Why Rojo?: why-rojo.md - - Get Help with Rojo: help.md - - Guide: - - Installation: guide/installation.md - - Creating a Game with Rojo: guide/new-game.md - - Porting an Existing Game to Rojo: guide/existing-game.md - - Migrating from 0.4.x to 0.5.x: guide/migrating-to-epiphany.md - - Reference: - - Fully vs Partially Managed Rojo: reference/full-vs-partial.md - - Project Format: reference/project-format.md - - Sync Details: reference/sync-details.md - - Rojo Alternatives: rojo-alternatives.md - - Rojo Internals: - - Internals Overview: internals/overview.md - -extra_css: - - extra.css - -markdown_extensions: - - attr_list - - admonition - - codehilite: - guess_lang: false - - toc: - permalink: true \ No newline at end of file From 07c6fd3711a95a1b93193a21e8172429d62b7526 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 4 Mar 2020 14:58:07 -0800 Subject: [PATCH 0960/1504] Update docs repo link --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index bdbabc63..24dd6f87 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ Soon, Rojo will be able to: * Import custom instances like MoonScript code ## [Documentation](https://rojo.space/docs) -If you find any mistakes, feel free to make changes in the [docs](https://github.com/rojo-rbx/rojo/tree/master/docs) folder of this repository and submit a pull request! +Documentation is hosted in the [rojo.space repository](https://github.com/rojo-rbx/rojo.space). ## Contributing Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions for helping work on Rojo! From d4a39674de126c399906ce92d375c84fec6f41b4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 6 Mar 2020 13:23:49 -0800 Subject: [PATCH 0961/1504] Fix 'rojo upload' behavior --- CHANGELOG.md | 4 +++- src/cli/mod.rs | 4 ---- src/cli/upload.rs | 13 +++++++++++-- 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eed7c8cd..d56c94e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog -## Unreleased Changes +## Unreleased Changes for 0.6.x +* Fixed `rojo upload` command always uploading models. +* Removed `--kind` parameter to `rojo upload`; Rojo now automatically uploads the correct kind of asset based on your project file. ## [0.5.4](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.4) (February 26, 2020) This is a general maintenance release for the Rojo 0.5.x release series. diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 20810002..a10039da 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -155,10 +155,6 @@ pub struct UploadCommand { #[structopt(default_value = "")] pub project: PathBuf, - /// The kind of asset to generate, 'place', or 'model'. Defaults to place. - #[structopt(long, default_value = "place")] - pub kind: UploadKind, - /// Authenication cookie to use. If not specified, Rojo will attempt to find one from the system automatically. #[structopt(long)] pub cookie: Option, diff --git a/src/cli/upload.rs b/src/cli/upload.rs index 42dca981..671c2b3c 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -43,14 +43,23 @@ fn upload_inner(options: UploadCommand) -> Result<(), Error> { let vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); let (_maybe_project, tree) = common_setup::start(&options.absolute_project(), &vfs); - let root_id = tree.get_root_id(); + + let inner_tree = tree.inner(); + let root_id = inner_tree.get_root_id(); + let root_instance = inner_tree.get_instance(root_id).unwrap(); + + let encode_ids = match root_instance.class_name.as_str() { + "DataModel" => root_instance.get_children_ids().to_vec(), + _ => vec![root_id], + }; let mut buffer = Vec::new(); log::trace!("Encoding XML model"); let config = rbx_xml::EncodeOptions::new() .property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown); - rbx_xml::to_writer(&mut buffer, tree.inner(), &[root_id], config).context(XmlModel)?; + + rbx_xml::to_writer(&mut buffer, tree.inner(), &encode_ids, config).context(XmlModel)?; let url = format!( "https://data.roblox.com/Data/Upload.ashx?assetid={}", From 4b0189dd5539776820adbc9f4b17cf01967e41b6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 6 Mar 2020 13:52:23 -0800 Subject: [PATCH 0962/1504] Upgrade to Insta 0.13.1 --- Cargo.lock | 26 +++---------------- Cargo.toml | 2 +- rojo-test/Cargo.toml | 5 +--- ...o_test__build_test__client_in_folder.snap} | 0 ...> rojo_test__build_test__client_init.snap} | 0 ...> rojo_test__build_test__csv_bug_145.snap} | 0 ...> rojo_test__build_test__csv_bug_147.snap} | 0 ...rojo_test__build_test__csv_in_folder.snap} | 0 ... rojo_test__build_test__deep_nesting.snap} | 0 ...ap => rojo_test__build_test__gitkeep.snap} | 0 ..._test__build_test__ignore_glob_inner.snap} | 0 ...test__build_test__ignore_glob_nested.snap} | 0 ...o_test__build_test__ignore_glob_spec.snap} | 0 ...st__build_test__init_meta_class_name.snap} | 0 ...st__build_test__init_meta_properties.snap} | 0 ...test__build_test__init_with_children.snap} | 0 ...st__build_test__json_model_in_folder.snap} | 0 ...__build_test__json_model_legacy_name.snap} | 0 ...o_test__build_test__module_in_folder.snap} | 0 ...> rojo_test__build_test__module_init.snap} | 0 ... => rojo_test__build_test__plain.txt.snap} | 0 ...rojo_test__build_test__plain_gitkeep.snap} | 0 ...ojo_test__build_test__rbxm_in_folder.snap} | 0 ...jo_test__build_test__rbxmx_in_folder.snap} | 0 ...jo_test__build_test__rbxmx_ref.rbxmx.snap} | 0 ...st__build_test__script_meta_disabled.snap} | 0 ...o_test__build_test__server_in_folder.snap} | 0 ...> rojo_test__build_test__server_init.snap} | 0 ...t.snap => rojo_test__build_test__txt.snap} | 0 ...rojo_test__build_test__txt_in_folder.snap} | 0 ...o_test__serve_test__add_folder_all-2.snap} | 0 ...ojo_test__serve_test__add_folder_all.snap} | 0 ...jo_test__serve_test__add_folder_info.snap} | 0 ...st__serve_test__add_folder_subscribe.snap} | 0 ...jo_test__serve_test__edit_init_all-2.snap} | 0 ...rojo_test__serve_test__edit_init_all.snap} | 0 ...ojo_test__serve_test__edit_init_info.snap} | 0 ...est__serve_test__edit_init_subscribe.snap} | 0 ... => rojo_test__serve_test__empty_all.snap} | 0 ...=> rojo_test__serve_test__empty_info.snap} | 0 ... rojo_test__serve_test__just_txt_all.snap} | 0 ...rojo_test__serve_test__just_txt_info.snap} | 0 ...rve_test__move_folder_of_stuff_all-2.snap} | 0 ...serve_test__move_folder_of_stuff_all.snap} | 0 ...erve_test__move_folder_of_stuff_info.snap} | 0 ...test__move_folder_of_stuff_subscribe.snap} | 0 ..._test__serve_test__remove_file_all-2.snap} | 0 ...jo_test__serve_test__remove_file_all.snap} | 0 ...o_test__serve_test__remove_file_info.snap} | 0 ...t__serve_test__remove_file_subscribe.snap} | 0 ...rojo_test__serve_test__scripts_all-2.snap} | 0 ...> rojo_test__serve_test__scripts_all.snap} | 0 ... rojo_test__serve_test__scripts_info.snap} | 0 ..._test__serve_test__scripts_subscribe.snap} | 0 ...apshot__tests__apply__add_property-2.snap} | 0 ...snapshot__tests__apply__add_property.snap} | 0 ...__apply__remove_property_after_patch.snap} | 0 ..._apply__remove_property_appied_patch.snap} | 0 ...ests__apply__remove_property_initial.snap} | 0 ...ts__apply__set_name_and_class_name-2.snap} | 0 ...ests__apply__set_name_and_class_name.snap} | 0 ..._snapshot__tests__compute__add_child.snap} | 0 ...apshot__tests__compute__remove_child.snap} | 0 ...hot__tests__compute__remove_property.snap} | 0 ...ts__compute__set_name_and_class_name.snap} | 0 ...apshot__tests__compute__set_property.snap} | 0 ..._middleware__csv__test__csv_from_vfs.snap} | 0 ...middleware__csv__test__csv_with_meta.snap} | 0 ..._middleware__dir__test__empty_folder.snap} | 0 ...dleware__dir__test__folder_in_folder.snap} | 0 ...re__json_model__test__model_from_vfs.snap} | 0 ...ddleware__lua__test__client_from_vfs.snap} | 0 ...are__lua__test__init_module_from_vfs.snap} | 0 ...ddleware__lua__test__module_from_vfs.snap} | 0 ...dleware__lua__test__module_with_meta.snap} | 0 ...ddleware__lua__test__script_disabled.snap} | 0 ...dleware__lua__test__script_with_meta.snap} | 0 ...ddleware__lua__test__server_from_vfs.snap} | 0 ...ject__test__project_from_direct_file.snap} | 0 ...__project__test__project_from_folder.snap} | 0 ...est__project_path_property_overrides.snap} | 0 ...project__test__project_with_children.snap} | 0 ...__test__project_with_path_to_project.snap} | 0 ...t_with_path_to_project_with_children.snap} | 0 ...ject__test__project_with_path_to_txt.snap} | 0 ...st__project_with_resolved_properties.snap} | 0 ...__project_with_unresolved_properties.snap} | 0 ...leware__txt__test__instance_from_vfs.snap} | 0 ...ession__change_file_in_project_after.snap} | 0 ...ssion__change_file_in_project_before.snap} | 0 ...ession__change_file_in_project_patch.snap} | 0 ...ve_session__change_script_meta_after.snap} | 0 ...e_session__change_script_meta_before.snap} | 0 ...ve_session__change_script_meta_patch.snap} | 0 ...serve_session__change_txt_file_after.snap} | 0 ...erve_session__change_txt_file_before.snap} | 0 ...serve_session__change_txt_file_patch.snap} | 0 ..._session__serve_session__just_folder.snap} | 0 ...__serve_session__project_with_folder.snap} | 0 ...ion__serve_session__script_with_meta.snap} | 0 100 files changed, 6 insertions(+), 27 deletions(-) rename rojo-test/build-test-snapshots/{build_test__client_in_folder.snap => rojo_test__build_test__client_in_folder.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__client_init.snap => rojo_test__build_test__client_init.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__csv_bug_145.snap => rojo_test__build_test__csv_bug_145.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__csv_bug_147.snap => rojo_test__build_test__csv_bug_147.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__csv_in_folder.snap => rojo_test__build_test__csv_in_folder.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__deep_nesting.snap => rojo_test__build_test__deep_nesting.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__gitkeep.snap => rojo_test__build_test__gitkeep.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__ignore_glob_inner.snap => rojo_test__build_test__ignore_glob_inner.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__ignore_glob_nested.snap => rojo_test__build_test__ignore_glob_nested.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__ignore_glob_spec.snap => rojo_test__build_test__ignore_glob_spec.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__init_meta_class_name.snap => rojo_test__build_test__init_meta_class_name.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__init_meta_properties.snap => rojo_test__build_test__init_meta_properties.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__init_with_children.snap => rojo_test__build_test__init_with_children.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__json_model_in_folder.snap => rojo_test__build_test__json_model_in_folder.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__json_model_legacy_name.snap => rojo_test__build_test__json_model_legacy_name.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__module_in_folder.snap => rojo_test__build_test__module_in_folder.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__module_init.snap => rojo_test__build_test__module_init.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__plain.txt.snap => rojo_test__build_test__plain.txt.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__plain_gitkeep.snap => rojo_test__build_test__plain_gitkeep.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__rbxm_in_folder.snap => rojo_test__build_test__rbxm_in_folder.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__rbxmx_in_folder.snap => rojo_test__build_test__rbxmx_in_folder.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__rbxmx_ref.rbxmx.snap => rojo_test__build_test__rbxmx_ref.rbxmx.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__script_meta_disabled.snap => rojo_test__build_test__script_meta_disabled.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__server_in_folder.snap => rojo_test__build_test__server_in_folder.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__server_init.snap => rojo_test__build_test__server_init.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__txt.snap => rojo_test__build_test__txt.snap} (100%) rename rojo-test/build-test-snapshots/{build_test__txt_in_folder.snap => rojo_test__build_test__txt_in_folder.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__add_folder_all-2.snap => rojo_test__serve_test__add_folder_all-2.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__add_folder_all.snap => rojo_test__serve_test__add_folder_all.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__add_folder_info.snap => rojo_test__serve_test__add_folder_info.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__add_folder_subscribe.snap => rojo_test__serve_test__add_folder_subscribe.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__edit_init_all-2.snap => rojo_test__serve_test__edit_init_all-2.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__edit_init_all.snap => rojo_test__serve_test__edit_init_all.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__edit_init_info.snap => rojo_test__serve_test__edit_init_info.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__edit_init_subscribe.snap => rojo_test__serve_test__edit_init_subscribe.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__empty_all.snap => rojo_test__serve_test__empty_all.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__empty_info.snap => rojo_test__serve_test__empty_info.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__just_txt_all.snap => rojo_test__serve_test__just_txt_all.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__just_txt_info.snap => rojo_test__serve_test__just_txt_info.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__move_folder_of_stuff_all-2.snap => rojo_test__serve_test__move_folder_of_stuff_all-2.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__move_folder_of_stuff_all.snap => rojo_test__serve_test__move_folder_of_stuff_all.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__move_folder_of_stuff_info.snap => rojo_test__serve_test__move_folder_of_stuff_info.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__move_folder_of_stuff_subscribe.snap => rojo_test__serve_test__move_folder_of_stuff_subscribe.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__remove_file_all-2.snap => rojo_test__serve_test__remove_file_all-2.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__remove_file_all.snap => rojo_test__serve_test__remove_file_all.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__remove_file_info.snap => rojo_test__serve_test__remove_file_info.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__remove_file_subscribe.snap => rojo_test__serve_test__remove_file_subscribe.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__scripts_all-2.snap => rojo_test__serve_test__scripts_all-2.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__scripts_all.snap => rojo_test__serve_test__scripts_all.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__scripts_info.snap => rojo_test__serve_test__scripts_info.snap} (100%) rename rojo-test/serve-test-snapshots/{serve_test__scripts_subscribe.snap => rojo_test__serve_test__scripts_subscribe.snap} (100%) rename src/snapshot/tests/snapshots/{apply__add_property-2.snap => librojo__snapshot__tests__apply__add_property-2.snap} (100%) rename src/snapshot/tests/snapshots/{apply__add_property.snap => librojo__snapshot__tests__apply__add_property.snap} (100%) rename src/snapshot/tests/snapshots/{apply__remove_property_after_patch.snap => librojo__snapshot__tests__apply__remove_property_after_patch.snap} (100%) rename src/snapshot/tests/snapshots/{apply__remove_property_appied_patch.snap => librojo__snapshot__tests__apply__remove_property_appied_patch.snap} (100%) rename src/snapshot/tests/snapshots/{apply__remove_property_initial.snap => librojo__snapshot__tests__apply__remove_property_initial.snap} (100%) rename src/snapshot/tests/snapshots/{apply__set_name_and_class_name-2.snap => librojo__snapshot__tests__apply__set_name_and_class_name-2.snap} (100%) rename src/snapshot/tests/snapshots/{apply__set_name_and_class_name.snap => librojo__snapshot__tests__apply__set_name_and_class_name.snap} (100%) rename src/snapshot/tests/snapshots/{compute__add_child.snap => librojo__snapshot__tests__compute__add_child.snap} (100%) rename src/snapshot/tests/snapshots/{compute__remove_child.snap => librojo__snapshot__tests__compute__remove_child.snap} (100%) rename src/snapshot/tests/snapshots/{compute__remove_property.snap => librojo__snapshot__tests__compute__remove_property.snap} (100%) rename src/snapshot/tests/snapshots/{compute__set_name_and_class_name.snap => librojo__snapshot__tests__compute__set_name_and_class_name.snap} (100%) rename src/snapshot/tests/snapshots/{compute__set_property.snap => librojo__snapshot__tests__compute__set_property.snap} (100%) rename src/snapshot_middleware/snapshots/{test__csv_from_vfs.snap => librojo__snapshot_middleware__csv__test__csv_from_vfs.snap} (100%) rename src/snapshot_middleware/snapshots/{test__csv_with_meta.snap => librojo__snapshot_middleware__csv__test__csv_with_meta.snap} (100%) rename src/snapshot_middleware/snapshots/{test__empty_folder.snap => librojo__snapshot_middleware__dir__test__empty_folder.snap} (100%) rename src/snapshot_middleware/snapshots/{test__folder_in_folder.snap => librojo__snapshot_middleware__dir__test__folder_in_folder.snap} (100%) rename src/snapshot_middleware/snapshots/{test__model_from_vfs.snap => librojo__snapshot_middleware__json_model__test__model_from_vfs.snap} (100%) rename src/snapshot_middleware/snapshots/{test__client_from_vfs.snap => librojo__snapshot_middleware__lua__test__client_from_vfs.snap} (100%) rename src/snapshot_middleware/snapshots/{test__init_module_from_vfs.snap => librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap} (100%) rename src/snapshot_middleware/snapshots/{test__module_from_vfs.snap => librojo__snapshot_middleware__lua__test__module_from_vfs.snap} (100%) rename src/snapshot_middleware/snapshots/{test__module_with_meta.snap => librojo__snapshot_middleware__lua__test__module_with_meta.snap} (100%) rename src/snapshot_middleware/snapshots/{test__script_disabled.snap => librojo__snapshot_middleware__lua__test__script_disabled.snap} (100%) rename src/snapshot_middleware/snapshots/{test__script_with_meta.snap => librojo__snapshot_middleware__lua__test__script_with_meta.snap} (100%) rename src/snapshot_middleware/snapshots/{test__server_from_vfs.snap => librojo__snapshot_middleware__lua__test__server_from_vfs.snap} (100%) rename src/snapshot_middleware/snapshots/{test__project_from_direct_file.snap => librojo__snapshot_middleware__project__test__project_from_direct_file.snap} (100%) rename src/snapshot_middleware/snapshots/{test__project_from_folder.snap => librojo__snapshot_middleware__project__test__project_from_folder.snap} (100%) rename src/snapshot_middleware/snapshots/{test__project_path_property_overrides.snap => librojo__snapshot_middleware__project__test__project_path_property_overrides.snap} (100%) rename src/snapshot_middleware/snapshots/{test__project_with_children.snap => librojo__snapshot_middleware__project__test__project_with_children.snap} (100%) rename src/snapshot_middleware/snapshots/{test__project_with_path_to_project.snap => librojo__snapshot_middleware__project__test__project_with_path_to_project.snap} (100%) rename src/snapshot_middleware/snapshots/{test__project_with_path_to_project_with_children.snap => librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap} (100%) rename src/snapshot_middleware/snapshots/{test__project_with_path_to_txt.snap => librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap} (100%) rename src/snapshot_middleware/snapshots/{test__project_with_resolved_properties.snap => librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap} (100%) rename src/snapshot_middleware/snapshots/{test__project_with_unresolved_properties.snap => librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap} (100%) rename src/snapshot_middleware/snapshots/{test__instance_from_vfs.snap => librojo__snapshot_middleware__txt__test__instance_from_vfs.snap} (100%) rename src/snapshots/{serve_session__change_file_in_project_after.snap => librojo__serve_session__serve_session__change_file_in_project_after.snap} (100%) rename src/snapshots/{serve_session__change_file_in_project_before.snap => librojo__serve_session__serve_session__change_file_in_project_before.snap} (100%) rename src/snapshots/{serve_session__change_file_in_project_patch.snap => librojo__serve_session__serve_session__change_file_in_project_patch.snap} (100%) rename src/snapshots/{serve_session__change_script_meta_after.snap => librojo__serve_session__serve_session__change_script_meta_after.snap} (100%) rename src/snapshots/{serve_session__change_script_meta_before.snap => librojo__serve_session__serve_session__change_script_meta_before.snap} (100%) rename src/snapshots/{serve_session__change_script_meta_patch.snap => librojo__serve_session__serve_session__change_script_meta_patch.snap} (100%) rename src/snapshots/{serve_session__change_txt_file_after.snap => librojo__serve_session__serve_session__change_txt_file_after.snap} (100%) rename src/snapshots/{serve_session__change_txt_file_before.snap => librojo__serve_session__serve_session__change_txt_file_before.snap} (100%) rename src/snapshots/{serve_session__change_txt_file_patch.snap => librojo__serve_session__serve_session__change_txt_file_patch.snap} (100%) rename src/snapshots/{serve_session__just_folder.snap => librojo__serve_session__serve_session__just_folder.snap} (100%) rename src/snapshots/{serve_session__project_with_folder.snap => librojo__serve_session__serve_session__project_with_folder.snap} (100%) rename src/snapshots/{serve_session__script_with_meta.snap => librojo__serve_session__serve_session__script_with_meta.snap} (100%) diff --git a/Cargo.lock b/Cargo.lock index a6266d51..4c5ff227 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -780,23 +780,7 @@ dependencies = [ [[package]] name = "insta" -version = "0.12.0" -source = "git+https://github.com/mitsuhiko/insta#8cc12dc009c86df0a4a45f45f26b305b6e7eab8f" -dependencies = [ - "console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", - "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "insta" -version = "0.12.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -807,7 +791,6 @@ dependencies = [ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1666,7 +1649,7 @@ dependencies = [ "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "insta 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1709,7 +1692,7 @@ name = "rojo-test" version = "0.1.0" dependencies = [ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "insta 0.12.0 (git+https://github.com/mitsuhiko/insta)", + "insta 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2555,8 +2538,7 @@ dependencies = [ "checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" "checksum inotify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24e40d6fd5d64e2082e0c796495c8ef5ad667a96d03e5aaa0becfd9d47bcbfb8" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" -"checksum insta 0.12.0 (git+https://github.com/mitsuhiko/insta)" = "" -"checksum insta 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0d499dc062e841590a67230d853bce62d0abeb91304927871670b7c55c461349" +"checksum insta 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8df742abee84dbf27d20869c9adf77b0d8f7ea3eead13c2c9e3998d136a97058" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" diff --git a/Cargo.toml b/Cargo.toml index c6b89947..5759aab6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,7 +89,7 @@ winreg = "0.6.2" rojo-insta-ext = { path = "rojo-insta-ext" } criterion = "0.3" -insta = { version = "0.12.0", features = ["redactions"] } +insta = { version = "0.13.1", features = ["redactions"] } lazy_static = "1.2" paste = "0.1" pretty_assertions = "0.6.1" diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index ddd275b2..d6417764 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -12,6 +12,7 @@ unstable_glob_ignore_paths = [] [dependencies] env_logger = "0.6.2" +insta = { version = "0.13.1", features = ["redactions"] } log = "0.4.8" paste = "0.1.5" rbx_dom_weak = "1.9.0" @@ -26,7 +27,3 @@ rojo-insta-ext = { path = "../rojo-insta-ext" } # We execute Rojo via std::process::Command, so depend on it so it's built! rojo = { path = ".." } - -[dependencies.insta] -git = "https://github.com/mitsuhiko/insta" -features = ["redactions"] diff --git a/rojo-test/build-test-snapshots/build_test__client_in_folder.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__client_in_folder.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__client_in_folder.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__client_in_folder.snap diff --git a/rojo-test/build-test-snapshots/build_test__client_init.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__client_init.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__client_init.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__client_init.snap diff --git a/rojo-test/build-test-snapshots/build_test__csv_bug_145.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__csv_bug_145.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__csv_bug_145.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__csv_bug_145.snap diff --git a/rojo-test/build-test-snapshots/build_test__csv_bug_147.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__csv_bug_147.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__csv_bug_147.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__csv_bug_147.snap diff --git a/rojo-test/build-test-snapshots/build_test__csv_in_folder.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__csv_in_folder.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__csv_in_folder.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__csv_in_folder.snap diff --git a/rojo-test/build-test-snapshots/build_test__deep_nesting.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__deep_nesting.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__deep_nesting.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__deep_nesting.snap diff --git a/rojo-test/build-test-snapshots/build_test__gitkeep.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__gitkeep.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__gitkeep.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__gitkeep.snap diff --git a/rojo-test/build-test-snapshots/build_test__ignore_glob_inner.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_inner.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__ignore_glob_inner.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_inner.snap diff --git a/rojo-test/build-test-snapshots/build_test__ignore_glob_nested.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_nested.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__ignore_glob_nested.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_nested.snap diff --git a/rojo-test/build-test-snapshots/build_test__ignore_glob_spec.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_spec.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__ignore_glob_spec.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_spec.snap diff --git a/rojo-test/build-test-snapshots/build_test__init_meta_class_name.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__init_meta_class_name.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__init_meta_class_name.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__init_meta_class_name.snap diff --git a/rojo-test/build-test-snapshots/build_test__init_meta_properties.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__init_meta_properties.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__init_meta_properties.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__init_meta_properties.snap diff --git a/rojo-test/build-test-snapshots/build_test__init_with_children.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__init_with_children.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__init_with_children.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__init_with_children.snap diff --git a/rojo-test/build-test-snapshots/build_test__json_model_in_folder.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__json_model_in_folder.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__json_model_in_folder.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__json_model_in_folder.snap diff --git a/rojo-test/build-test-snapshots/build_test__json_model_legacy_name.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__json_model_legacy_name.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__json_model_legacy_name.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__json_model_legacy_name.snap diff --git a/rojo-test/build-test-snapshots/build_test__module_in_folder.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__module_in_folder.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__module_in_folder.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__module_in_folder.snap diff --git a/rojo-test/build-test-snapshots/build_test__module_init.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__module_init.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__module_init.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__module_init.snap diff --git a/rojo-test/build-test-snapshots/build_test__plain.txt.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__plain.txt.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__plain.txt.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__plain.txt.snap diff --git a/rojo-test/build-test-snapshots/build_test__plain_gitkeep.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__plain_gitkeep.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__plain_gitkeep.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__plain_gitkeep.snap diff --git a/rojo-test/build-test-snapshots/build_test__rbxm_in_folder.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__rbxm_in_folder.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__rbxm_in_folder.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__rbxm_in_folder.snap diff --git a/rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_in_folder.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__rbxmx_in_folder.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_in_folder.snap diff --git a/rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_ref.rbxmx.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__rbxmx_ref.rbxmx.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_ref.rbxmx.snap diff --git a/rojo-test/build-test-snapshots/build_test__script_meta_disabled.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__script_meta_disabled.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__script_meta_disabled.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__script_meta_disabled.snap diff --git a/rojo-test/build-test-snapshots/build_test__server_in_folder.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__server_in_folder.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__server_in_folder.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__server_in_folder.snap diff --git a/rojo-test/build-test-snapshots/build_test__server_init.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__server_init.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__server_init.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__server_init.snap diff --git a/rojo-test/build-test-snapshots/build_test__txt.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__txt.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__txt.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__txt.snap diff --git a/rojo-test/build-test-snapshots/build_test__txt_in_folder.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__txt_in_folder.snap similarity index 100% rename from rojo-test/build-test-snapshots/build_test__txt_in_folder.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__txt_in_folder.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__add_folder_all-2.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_all-2.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__add_folder_all-2.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_all-2.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__add_folder_all.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_all.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__add_folder_all.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_all.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__add_folder_info.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_info.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__add_folder_info.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_info.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_subscribe.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__add_folder_subscribe.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_subscribe.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__edit_init_all-2.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_all-2.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__edit_init_all-2.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_all-2.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__edit_init_all.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_all.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__edit_init_all.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_all.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__edit_init_info.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_info.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__edit_init_info.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_info.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__edit_init_subscribe.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_subscribe.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__edit_init_subscribe.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_subscribe.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__empty_all.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__empty_all.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__empty_all.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__empty_all.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__empty_info.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__empty_info.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__empty_info.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__empty_info.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__just_txt_all.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__just_txt_all.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__just_txt_all.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__just_txt_all.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__just_txt_info.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__just_txt_info.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__just_txt_info.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__just_txt_info.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_all-2.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_all-2.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_all-2.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_all-2.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_all.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_all.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_all.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_all.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_info.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_info.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_info.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_info.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_subscribe.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_subscribe.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__move_folder_of_stuff_subscribe.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_subscribe.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__remove_file_all-2.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_all-2.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__remove_file_all-2.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_all-2.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__remove_file_all.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_all.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__remove_file_all.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_all.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__remove_file_info.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_info.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__remove_file_info.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_info.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__remove_file_subscribe.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_subscribe.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__remove_file_subscribe.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_subscribe.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts_all-2.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_all-2.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__scripts_all-2.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_all-2.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts_all.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_all.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__scripts_all.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_all.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts_info.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_info.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__scripts_info.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_info.snap diff --git a/rojo-test/serve-test-snapshots/serve_test__scripts_subscribe.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_subscribe.snap similarity index 100% rename from rojo-test/serve-test-snapshots/serve_test__scripts_subscribe.snap rename to rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_subscribe.snap diff --git a/src/snapshot/tests/snapshots/apply__add_property-2.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property-2.snap similarity index 100% rename from src/snapshot/tests/snapshots/apply__add_property-2.snap rename to src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property-2.snap diff --git a/src/snapshot/tests/snapshots/apply__add_property.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap similarity index 100% rename from src/snapshot/tests/snapshots/apply__add_property.snap rename to src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap diff --git a/src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap similarity index 100% rename from src/snapshot/tests/snapshots/apply__remove_property_after_patch.snap rename to src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap diff --git a/src/snapshot/tests/snapshots/apply__remove_property_appied_patch.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_appied_patch.snap similarity index 100% rename from src/snapshot/tests/snapshots/apply__remove_property_appied_patch.snap rename to src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_appied_patch.snap diff --git a/src/snapshot/tests/snapshots/apply__remove_property_initial.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap similarity index 100% rename from src/snapshot/tests/snapshots/apply__remove_property_initial.snap rename to src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap diff --git a/src/snapshot/tests/snapshots/apply__set_name_and_class_name-2.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name-2.snap similarity index 100% rename from src/snapshot/tests/snapshots/apply__set_name_and_class_name-2.snap rename to src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name-2.snap diff --git a/src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap similarity index 100% rename from src/snapshot/tests/snapshots/apply__set_name_and_class_name.snap rename to src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap diff --git a/src/snapshot/tests/snapshots/compute__add_child.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap similarity index 100% rename from src/snapshot/tests/snapshots/compute__add_child.snap rename to src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap diff --git a/src/snapshot/tests/snapshots/compute__remove_child.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__remove_child.snap similarity index 100% rename from src/snapshot/tests/snapshots/compute__remove_child.snap rename to src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__remove_child.snap diff --git a/src/snapshot/tests/snapshots/compute__remove_property.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__remove_property.snap similarity index 100% rename from src/snapshot/tests/snapshots/compute__remove_property.snap rename to src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__remove_property.snap diff --git a/src/snapshot/tests/snapshots/compute__set_name_and_class_name.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__set_name_and_class_name.snap similarity index 100% rename from src/snapshot/tests/snapshots/compute__set_name_and_class_name.snap rename to src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__set_name_and_class_name.snap diff --git a/src/snapshot/tests/snapshots/compute__set_property.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__set_property.snap similarity index 100% rename from src/snapshot/tests/snapshots/compute__set_property.snap rename to src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__set_property.snap diff --git a/src/snapshot_middleware/snapshots/test__csv_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__csv_from_vfs.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap diff --git a/src/snapshot_middleware/snapshots/test__csv_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__csv_with_meta.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap diff --git a/src/snapshot_middleware/snapshots/test__empty_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__empty_folder.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap diff --git a/src/snapshot_middleware/snapshots/test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__folder_in_folder.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap diff --git a/src/snapshot_middleware/snapshots/test__model_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__model_from_vfs.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap diff --git a/src/snapshot_middleware/snapshots/test__client_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__client_from_vfs.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__client_from_vfs.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__client_from_vfs.snap diff --git a/src/snapshot_middleware/snapshots/test__init_module_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__init_module_from_vfs.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap diff --git a/src/snapshot_middleware/snapshots/test__module_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_from_vfs.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__module_from_vfs.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_from_vfs.snap diff --git a/src/snapshot_middleware/snapshots/test__module_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_with_meta.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__module_with_meta.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_with_meta.snap diff --git a/src/snapshot_middleware/snapshots/test__script_disabled.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_disabled.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__script_disabled.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_disabled.snap diff --git a/src/snapshot_middleware/snapshots/test__script_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_with_meta.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__script_with_meta.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_with_meta.snap diff --git a/src/snapshot_middleware/snapshots/test__server_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__server_from_vfs.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__server_from_vfs.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__server_from_vfs.snap diff --git a/src/snapshot_middleware/snapshots/test__project_from_direct_file.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__project_from_direct_file.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap diff --git a/src/snapshot_middleware/snapshots/test__project_from_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_folder.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__project_from_folder.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_folder.snap diff --git a/src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__project_path_property_overrides.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap diff --git a/src/snapshot_middleware/snapshots/test__project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__project_with_children.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__project_with_path_to_project.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__project_with_path_to_project_with_children.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap diff --git a/src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__project_with_path_to_txt.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap diff --git a/src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__project_with_resolved_properties.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap diff --git a/src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__project_with_unresolved_properties.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap diff --git a/src/snapshot_middleware/snapshots/test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap similarity index 100% rename from src/snapshot_middleware/snapshots/test__instance_from_vfs.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap diff --git a/src/snapshots/serve_session__change_file_in_project_after.snap b/src/snapshots/librojo__serve_session__serve_session__change_file_in_project_after.snap similarity index 100% rename from src/snapshots/serve_session__change_file_in_project_after.snap rename to src/snapshots/librojo__serve_session__serve_session__change_file_in_project_after.snap diff --git a/src/snapshots/serve_session__change_file_in_project_before.snap b/src/snapshots/librojo__serve_session__serve_session__change_file_in_project_before.snap similarity index 100% rename from src/snapshots/serve_session__change_file_in_project_before.snap rename to src/snapshots/librojo__serve_session__serve_session__change_file_in_project_before.snap diff --git a/src/snapshots/serve_session__change_file_in_project_patch.snap b/src/snapshots/librojo__serve_session__serve_session__change_file_in_project_patch.snap similarity index 100% rename from src/snapshots/serve_session__change_file_in_project_patch.snap rename to src/snapshots/librojo__serve_session__serve_session__change_file_in_project_patch.snap diff --git a/src/snapshots/serve_session__change_script_meta_after.snap b/src/snapshots/librojo__serve_session__serve_session__change_script_meta_after.snap similarity index 100% rename from src/snapshots/serve_session__change_script_meta_after.snap rename to src/snapshots/librojo__serve_session__serve_session__change_script_meta_after.snap diff --git a/src/snapshots/serve_session__change_script_meta_before.snap b/src/snapshots/librojo__serve_session__serve_session__change_script_meta_before.snap similarity index 100% rename from src/snapshots/serve_session__change_script_meta_before.snap rename to src/snapshots/librojo__serve_session__serve_session__change_script_meta_before.snap diff --git a/src/snapshots/serve_session__change_script_meta_patch.snap b/src/snapshots/librojo__serve_session__serve_session__change_script_meta_patch.snap similarity index 100% rename from src/snapshots/serve_session__change_script_meta_patch.snap rename to src/snapshots/librojo__serve_session__serve_session__change_script_meta_patch.snap diff --git a/src/snapshots/serve_session__change_txt_file_after.snap b/src/snapshots/librojo__serve_session__serve_session__change_txt_file_after.snap similarity index 100% rename from src/snapshots/serve_session__change_txt_file_after.snap rename to src/snapshots/librojo__serve_session__serve_session__change_txt_file_after.snap diff --git a/src/snapshots/serve_session__change_txt_file_before.snap b/src/snapshots/librojo__serve_session__serve_session__change_txt_file_before.snap similarity index 100% rename from src/snapshots/serve_session__change_txt_file_before.snap rename to src/snapshots/librojo__serve_session__serve_session__change_txt_file_before.snap diff --git a/src/snapshots/serve_session__change_txt_file_patch.snap b/src/snapshots/librojo__serve_session__serve_session__change_txt_file_patch.snap similarity index 100% rename from src/snapshots/serve_session__change_txt_file_patch.snap rename to src/snapshots/librojo__serve_session__serve_session__change_txt_file_patch.snap diff --git a/src/snapshots/serve_session__just_folder.snap b/src/snapshots/librojo__serve_session__serve_session__just_folder.snap similarity index 100% rename from src/snapshots/serve_session__just_folder.snap rename to src/snapshots/librojo__serve_session__serve_session__just_folder.snap diff --git a/src/snapshots/serve_session__project_with_folder.snap b/src/snapshots/librojo__serve_session__serve_session__project_with_folder.snap similarity index 100% rename from src/snapshots/serve_session__project_with_folder.snap rename to src/snapshots/librojo__serve_session__serve_session__project_with_folder.snap diff --git a/src/snapshots/serve_session__script_with_meta.snap b/src/snapshots/librojo__serve_session__serve_session__script_with_meta.snap similarity index 100% rename from src/snapshots/serve_session__script_with_meta.snap rename to src/snapshots/librojo__serve_session__serve_session__script_with_meta.snap From 2e1c37ffff8591c6d6760d37dac7e7f601950280 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 6 Mar 2020 13:54:04 -0800 Subject: [PATCH 0963/1504] Update dependencies --- Cargo.lock | 1093 ++++++++++++++++++++++++++++------------------------ 1 file changed, 586 insertions(+), 507 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4c5ff227..491d9c39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -7,10 +7,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "aho-corasick" -version = "0.7.6" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -23,10 +23,11 @@ dependencies = [ [[package]] name = "atty" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -35,24 +36,29 @@ name = "autocfg" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "backtrace" -version = "0.3.40" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "backtrace-sys" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -60,7 +66,7 @@ name = "base64" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -80,7 +86,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -94,15 +100,20 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "bumpalo" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "byte-tools" version = "0.3.1" @@ -115,7 +126,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "byteorder" -version = "1.3.2" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -123,7 +134,7 @@ name = "bytes" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -141,11 +152,11 @@ name = "cargo_metadata" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -158,7 +169,7 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.48" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -172,7 +183,7 @@ version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -192,9 +203,9 @@ name = "clicolors-control" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -208,14 +219,14 @@ dependencies = [ [[package]] name = "console" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -235,12 +246,12 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "publicsuffix 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -248,16 +259,16 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.6.4" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "core-foundation-sys" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -270,31 +281,31 @@ dependencies = [ [[package]] name = "criterion" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion-plot 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "oorandom 11.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "plotters 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", - "tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "tinytemplate 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "criterion-plot" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -303,96 +314,83 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.4.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-deque" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-epoch" -version = "0.8.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-queue" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-queue" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "crossbeam-utils" -version = "0.6.6" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "crossbeam-utils" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "csv" -version = "1.1.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "csv-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "csv-core" -version = "0.1.6" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "ctor" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -415,7 +413,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "dtoa" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -430,7 +428,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "encoding_rs" -version = "0.8.21" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", @@ -441,11 +439,11 @@ name = "env_logger" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -453,39 +451,39 @@ name = "env_logger" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "error-chain" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", + "failure_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "failure_derive" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -500,7 +498,7 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -512,8 +510,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -548,7 +546,7 @@ name = "fsevent-sys" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -581,7 +579,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -594,12 +592,12 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -612,11 +610,11 @@ name = "globset" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -624,16 +622,16 @@ name = "h2" version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", + "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -646,10 +644,10 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.5" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -664,7 +662,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -688,7 +686,7 @@ name = "humantime" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -704,19 +702,19 @@ dependencies = [ "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -728,8 +726,8 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -739,7 +737,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -749,15 +747,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "indexmap" -version = "1.3.0" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -767,7 +765,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -775,7 +773,7 @@ name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -783,13 +781,13 @@ name = "insta" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "console 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -798,7 +796,7 @@ name = "iovec" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -811,7 +809,7 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -819,6 +817,14 @@ name = "jod-thread" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "js-sys" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "kernel32-sys" version = "0.2.2" @@ -840,7 +846,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "libc" -version = "0.2.66" +version = "0.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -850,10 +856,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "lock_api" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -869,7 +875,7 @@ name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -879,8 +885,8 @@ name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -905,11 +911,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "memchr" -version = "2.2.1" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", -] [[package]] name = "memoffset" @@ -921,21 +924,21 @@ dependencies = [ [[package]] name = "mime" -version = "0.3.14" +version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "mime_guess" -version = "2.0.1" +version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "miniz_oxide" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -951,7 +954,7 @@ dependencies = [ "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", @@ -976,7 +979,7 @@ version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -993,18 +996,18 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)", "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)", + "schannel 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1014,7 +1017,7 @@ version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1028,30 +1031,35 @@ dependencies = [ "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", "inotify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num-traits" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "num_cpus" -version = "1.11.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "oorandom" +version = "11.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "opaque-debug" version = "0.2.3" @@ -1059,15 +1067,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl" -version = "0.10.26" +version = "0.10.28" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1077,12 +1085,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "openssl-sys" -version = "0.9.53" +version = "0.9.54" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1100,7 +1108,7 @@ name = "parking_lot" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1112,7 +1120,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1121,22 +1129,22 @@ dependencies = [ [[package]] name = "paste" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "paste-impl 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "paste-impl" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1151,7 +1159,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "pest" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1162,30 +1170,30 @@ name = "pest_derive" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_generator 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "pest_generator" -version = "2.1.1" +version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "pest_meta 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "pest_meta" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1193,6 +1201,17 @@ name = "pkg-config" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "plotters" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "js-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "web-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ppv-lite86" version = "0.2.6" @@ -1204,19 +1223,33 @@ version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "ctor 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "proc-macro-error" -version = "0.2.6" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error-attr 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "proc-macro-error-attr" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1224,9 +1257,9 @@ name = "proc-macro-hack" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1244,7 +1277,7 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1255,11 +1288,11 @@ name = "publicsuffix" version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1272,7 +1305,7 @@ dependencies = [ [[package]] name = "quick-error" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1285,10 +1318,10 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1297,7 +1330,7 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1309,7 +1342,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1323,11 +1356,11 @@ dependencies = [ [[package]] name = "rand" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1369,7 +1402,7 @@ name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1401,7 +1434,7 @@ name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1413,21 +1446,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand_os" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand_pcg" version = "0.1.2" @@ -1445,34 +1469,26 @@ dependencies = [ "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rand_xoshiro" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rayon" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rayon-core" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1480,12 +1496,12 @@ name = "rbx_binary" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)", - "snafu 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.3.418 (registry+https://github.com/rust-lang/crates.io-index)", + "snafu 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1504,7 +1520,7 @@ dependencies = [ [[package]] name = "rbx_reflection" -version = "3.3.408" +version = "3.3.418" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1521,7 +1537,7 @@ dependencies = [ "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.3.418 (registry+https://github.com/rust-lang/crates.io-index)", "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1540,13 +1556,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "regex" -version = "1.3.1" +version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "regex-syntax 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", + "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1554,12 +1570,12 @@ name = "regex-automata" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "regex-syntax" -version = "0.6.12" +version = "0.6.16" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -1579,25 +1595,25 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.21 (registry+https://github.com/rust-lang/crates.io-index)", + "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)", "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", + "mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1631,19 +1647,19 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "rojo" version = "0.6.0-alpha.1" dependencies = [ - "criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "criterion 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1655,27 +1671,27 @@ dependencies = [ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)", + "rbx_reflection 3.3.418 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_xml 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "rlua 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", "rojo-insta-ext 0.1.0", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", - "snafu 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "snafu 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1694,16 +1710,16 @@ dependencies = [ "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "paste 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", "rojo 0.6.0-alpha.1", "rojo-insta-ext 0.1.0", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1726,15 +1742,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "same-file" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "schannel" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1743,26 +1759,27 @@ dependencies = [ [[package]] name = "scopeguard" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "security-framework" -version = "0.3.4" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "security-framework-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "security-framework-sys" -version = "0.3.3" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1792,17 +1809,17 @@ name = "serde_derive" version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "serde_json" -version = "1.0.44" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1812,9 +1829,9 @@ name = "serde_repr" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1822,8 +1839,8 @@ name = "serde_urlencoded" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1833,7 +1850,7 @@ name = "serde_yaml" version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1841,7 +1858,7 @@ dependencies = [ [[package]] name = "sha-1" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1857,12 +1874,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1880,26 +1897,26 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.0.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "snafu" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "snafu-derive 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "snafu-derive 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "snafu-derive" -version = "0.6.0" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -1925,43 +1942,54 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "structopt" -version = "0.3.5" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "structopt-derive" -version = "0.3.5" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "syn" -version = "1.0.11" +version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "syn-mid" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "synstructure" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1980,8 +2008,8 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1989,10 +2017,10 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.0.5" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2000,7 +2028,7 @@ name = "termios" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2013,7 +2041,7 @@ dependencies = [ [[package]] name = "thread_local" -version = "0.3.6" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2024,18 +2052,18 @@ name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tinytemplate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2046,19 +2074,19 @@ dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-uds 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2073,45 +2101,45 @@ dependencies = [ [[package]] name = "tokio-codec" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-current-thread" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-executor" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-fs" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-io" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2121,25 +2149,25 @@ dependencies = [ [[package]] name = "tokio-reactor" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-sync" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2148,73 +2176,73 @@ dependencies = [ [[package]] name = "tokio-tcp" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-threadpool" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-timer" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-udp" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "tokio-uds" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2258,10 +2286,10 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2296,7 +2324,7 @@ dependencies = [ [[package]] name = "url" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2317,7 +2345,7 @@ name = "uuid" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2331,11 +2359,6 @@ name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "version_check" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "version_check" version = "0.9.1" @@ -2345,18 +2368,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "vfs" version = "0.1.0" dependencies = [ - "crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] name = "walkdir" -version = "2.2.9" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -2371,9 +2394,67 @@ dependencies = [ [[package]] name = "wasi" -version = "0.7.0" +version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "wasm-bindgen" +version = "0.2.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bumpalo 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-macro-support 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.59" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-backend 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen-shared 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.59" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "web-sys" +version = "0.3.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "js-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "winapi" version = "0.2.8" @@ -2400,7 +2481,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "winapi-util" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2411,15 +2492,6 @@ name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "wincolor" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "winreg" version = "0.6.2" @@ -2452,60 +2524,60 @@ dependencies = [ [metadata] "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" -"checksum aho-corasick 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "58fb5e95d83b38284460a5fda7d6470aa0b8844d283a0b614b8535e880800d2d" +"checksum aho-corasick 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e63fd144e18ba274ae7095c0197a870a7b9468abc801dd62f190d80817d2ec" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" +"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" -"checksum backtrace 0.3.40 (registry+https://github.com/rust-lang/crates.io-index)" = "924c76597f0d9ca25d762c25a4d369d51267536465dc5064bdf0eb073ed477ea" -"checksum backtrace-sys 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "5d6575f128516de27e3ce99689419835fce9643a9b215a14d2b5b685be018491" +"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +"checksum backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8" +"checksum backtrace-sys 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "e17b52e737c40a7d75abca20b29a19a0eb7ba9fc72c5a72dd282a0a3c2c0dc35" "checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" "checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" "checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" "checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -"checksum bstr 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8d6c2c5b58ab920a4f5aeaaca34b4488074e8cc7596af94e6f8c6ff247c60245" +"checksum bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "502ae1441a0a5adb8fbd38a5955a6416b9493e92b465de5e4a9bde6a539c2c48" +"checksum bumpalo 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742" "checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" "checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" -"checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5" +"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" "checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" "checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" "checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" -"checksum cc 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "f52a465a666ca3d838ebbf08b241383421412fe7ebb463527bba275526d89f76" +"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" "checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum console 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f5d540c2d34ac9dd0deb5f3b5f54c36c79efa78f6b3ad19106a554d07a7b5d9f" +"checksum console 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "45e0f3986890b3acbc782009e2629dfe2baa430ac091519ce3be26164a2ae6c0" "checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" "checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" -"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d" -"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b" +"checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +"checksum core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" "checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" -"checksum criterion 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "938703e165481c8d612ea3479ac8342e5615185db37765162e762ec3523e2fc6" -"checksum criterion-plot 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eccdc6ce8bbe352ca89025bee672aa6d24f4eb8c53e3a8b5d1bc58011da072a2" -"checksum crossbeam-channel 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "acec9a3b0b3559f15aee4f90746c4e5e293b701c0f7d3925d24e01645267b68c" -"checksum crossbeam-deque 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3aa945d63861bfe624b55d153a39684da1e8c0bc8fba932f7ee3a3c16cea3ca" -"checksum crossbeam-epoch 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5064ebdbf05ce3cb95e45c8b086f72263f4166b29b97f6baff7ef7fe047b55ac" -"checksum crossbeam-queue 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7c979cd6cfe72335896575c6b5688da489e420d36a27a0b9eb0c73db574b4a4b" -"checksum crossbeam-queue 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dfd6515864a82d2f877b42813d4553292c6659498c9a2aa31bab5a15243c2700" -"checksum crossbeam-utils 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)" = "04973fa96e96579258a5091af6003abde64af786b860f18622b82e026cca60e6" -"checksum crossbeam-utils 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ce446db02cdc3165b94ae73111e570793400d0794e46125cc4056c81cbb039f4" -"checksum csv 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "37519ccdfd73a75821cac9319d4fce15a81b9fcf75f951df5b9988aa3a0af87d" -"checksum csv-core 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9b5cadb6b25c77aeff80ba701712494213f4a8418fcda2ee11b6560c3ad0bf4c" -"checksum ctor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8ce37ad4184ab2ce004c33bf6379185d3b1c95801cab51026bd271bf68eedc" +"checksum criterion 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1fc755679c12bda8e5523a71e4d654b6bf2e14bd838dfc48cde6559a05caf7d1" +"checksum criterion-plot 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a01e15e0ea58e8234f96146b1f91fa9d0e4dd7a38da93ff7a75d42c0b9d3a545" +"checksum crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" +"checksum crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +"checksum crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" +"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" +"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" +"checksum csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" +"checksum csv-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +"checksum ctor 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "47c5e5ac752e18207b12e16b10631ae5f7f68f8805f335f9b817ead83d9ffce1" "checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" "checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" "checksum doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97" -"checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" +"checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" -"checksum encoding_rs 0.8.21 (registry+https://github.com/rust-lang/crates.io-index)" = "f730a5068736d360795b76e8c53ef51d052a4090d281412da851f5fd6204f36d" +"checksum encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" "checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -"checksum error-chain 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3ab49e9dcb602294bc42f9a7dfc9bc6e936fca4418ea300dbfb84fe16de0b7d9" -"checksum failure 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f8273f13c977665c5db7eb2b99ae520952fe5ac831ae4cd09d80c4c7042b5ed9" -"checksum failure_derive 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0bc225b78e0391e4b8683440bf2e63c2deeeb2ce5189eab46e2b68c6d3725d08" +"checksum error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd" +"checksum failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" +"checksum failure_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" "checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" "checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" "checksum flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" @@ -2520,12 +2592,12 @@ dependencies = [ "checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" "checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" "checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum getrandom 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "e7db7ca94ed4cd01190ceee0d8a8052f08a247aa1b469a7f68c6a3b71afcf407" +"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" "checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" "checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" "checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" "checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7" +"checksum hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8" "checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" "checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" @@ -2535,20 +2607,21 @@ dependencies = [ "checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" "checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" "checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum indexmap 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712d7b3ea5827fcb9d4fda14bf4da5f136f0db2ae9c8f4bd4e2d1c6fde4e6db2" +"checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" "checksum inotify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24e40d6fd5d64e2082e0c796495c8ef5ad667a96d03e5aaa0becfd9d47bcbfb8" "checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" "checksum insta 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8df742abee84dbf27d20869c9adf77b0d8f7ea3eead13c2c9e3998d136a97058" "checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" "checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" -"checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f" +"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" "checksum jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f52a11f73b88fab829a0e4d9e13ea5982c7ac457c72eb3541d82a4afdfce4ff" +"checksum js-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1cb931d43e71f560c81badb0191596562bafad2be06a3f9025b845c847c60df5" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" +"checksum libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" -"checksum lock_api 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e57b3997725d2b60dbec1297f6c2e2957cc383db1cebd6be812163f969c7d586" +"checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" "checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" "checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" @@ -2556,51 +2629,54 @@ dependencies = [ "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" "checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" "checksum md5 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" -"checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" +"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" "checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" -"checksum mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "dd1d63acd1b78403cc0c325605908475dd9b9a3acbf65ed8bcab97e27014afcf" -"checksum mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a0ed03949aef72dbdf3116a383d7b38b4768e6f960528cd6a6044aa9ed68599" -"checksum miniz_oxide 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6f3f74f726ae935c3f514300cc6773a0c9492abc5e972d42ba0c0ebb88757625" +"checksum mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +"checksum mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +"checksum miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" "checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" "checksum mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" "checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" "checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e" +"checksum native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" "checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" "checksum notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "80ae4a7688d1fab81c5bf19c64fc8db920be8d519ce6336ed4e7efe024724dbd" -"checksum num-traits 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c81ffc11c212fa327657cb19dd85eb7419e163b5b076bede2bdb5c974c07e4" -"checksum num_cpus 1.11.1 (registry+https://github.com/rust-lang/crates.io-index)" = "76dac5ed2a876980778b8b85f75a71b6cbf0db0b1232ee12f826bccb00d09d72" +"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +"checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" +"checksum oorandom 11.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebcec7c9c2a95cacc7cd0ecb89d8a8454eca13906f6deb55258ffff0adeb9405" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum openssl 0.10.26 (registry+https://github.com/rust-lang/crates.io-index)" = "3a3cc5799d98e1088141b8e01ff760112bbd9f19d850c124500566ca6901a585" +"checksum openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)" = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.53 (registry+https://github.com/rust-lang/crates.io-index)" = "465d16ae7fc0e313318f7de5cecf57b2fbe7511fd213978b457e1c96ff46736f" +"checksum openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)" = "1024c0a59774200a555087a6da3f253a9095a5f344e353b212ac4c8b8e450986" "checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -"checksum paste 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "423a519e1c6e828f1e73b720f9d9ed2fa643dce8a7737fb43235ce0b41eeaa49" -"checksum paste-impl 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "4214c9e912ef61bf42b81ba9a47e8aad1b2ffaf739ab162bf96d1e011f54e6c5" +"checksum paste 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "63e1afe738d71b1ebab5f1207c055054015427dbfc7bbe9ee1266894156ec046" +"checksum paste-impl 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc4a7f6f743211c5aab239640a65091535d97d43d92a52bca435a640892bb" "checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" "checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -"checksum pest 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7e4fb201c5c22a55d8b24fef95f78be52738e5e1361129be1b5e862ecdb6894a" +"checksum pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" "checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" -"checksum pest_generator 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9fcf299b5712d06ee128a556c94709aaa04512c4dffb8ead07c5c998447fc0" -"checksum pest_meta 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "df43fd99896fd72c485fe47542c7b500e4ac1e8700bf995544d1317a60ded547" +"checksum pest_generator 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27e5277315f6b4f27e0e6744feb5d5ba1891e7164871033d3c8344c6783b349a" +"checksum pest_meta 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" "checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" +"checksum plotters 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "4e3bb8da247d27ae212529352020f3e5ee16e83c0c258061d27b08ab92675eeb" "checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" "checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" -"checksum proc-macro-error 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aeccfe4d5d8ea175d5f0e4a2ad0637e0f4121d63bd99d356fb1f39ab2e7c6097" +"checksum proc-macro-error 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a" +"checksum proc-macro-error-attr 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a" "checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" "checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "9c9e470a8dc4aeae2dee2f335e8f533e2d4b347e1434e5671afc49b054592f27" +"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" "checksum publicsuffix 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b" "checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" -"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" +"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" "checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -"checksum quote 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "053a8c8bcc71fcce321828dc897a98ab9760bef03a4fc36693c231e5b3216cfe" +"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" "checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" "checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3ae1b169243eaf61759b8475a998f0a385e42042370f3a7dbaf35246eacc8412" +"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" "checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" "checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" "checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" @@ -2611,21 +2687,19 @@ dependencies = [ "checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_os 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a788ae3edb696cfcba1c19bfd388cc4b8c21f8a408432b199c072825084da58a" "checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" "checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rand_xoshiro 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0e18c91676f670f6f0312764c759405f13afb98d5d73819840cf72a518487bff" -"checksum rayon 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43739f8831493b276363637423d3622d4bd6394ab6f0a9c4a552e208aeb7fddd" -"checksum rayon-core 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8bf17de6f23b05473c437eb958b9c850bfc8af0961fe17b4cc92d5a627b4791" +"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" +"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" "checksum rbx_binary 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b1c0c2b715bb763be1e27e5118e1f1ce0381f6c396a9cc8dd2c4b818cfa247d" "checksum rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "978b65ce742f3cb38c0b64ca48601a5590e6be9a14d12025b9cba2fe553b78c4" -"checksum rbx_reflection 3.3.408 (registry+https://github.com/rust-lang/crates.io-index)" = "a4c147f9006c1cfd3a1872d36e91d5fca88d4b94fafa5463f774a00f293b1277" +"checksum rbx_reflection 3.3.418 (registry+https://github.com/rust-lang/crates.io-index)" = "08c07c726f7d69ff7ba98a065f9b354edc90cfdaa9f7b973d5680920b972dc47" "checksum rbx_xml 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6431f38b84582ec4e4f40b525cdcc713d4a984dcc2e3eecd1a67ae4da1172fbd" "checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" "checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc220bd33bdce8f093101afe22a037b8eb0e5af33592e6a9caafff0d4cb81cbd" +"checksum regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" "checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" -"checksum regex-syntax 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "11a7e20d1cce64ef2fed88b66d347f88bd9babb82845b2b858f3edbf59a4f716" +"checksum regex-syntax 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "1132f845907680735a84409c3bebc64d1364a5683ffbce899550cd09d5eaefc1" "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" "checksum reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" "checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" @@ -2634,84 +2708,89 @@ dependencies = [ "checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" "checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" -"checksum same-file 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "585e8ddcedc187886a30fa705c47985c3fa88d06624095856b36ca0b82ff4421" -"checksum schannel 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "87f550b06b6cba9c8b8be3ee73f391990116bf527450d2556e9b9ce263b9a021" -"checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d" -"checksum security-framework 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8ef2429d7cefe5fd28bd1d2ed41c944547d4ff84776f5935b456da44593a16df" -"checksum security-framework-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e31493fc37615debb8c5090a7aeb4a9730bc61e77ab10b9af59f1a202284f895" +"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +"checksum schannel 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "507a9e6e8ffe0a4e0ebb9a10293e62fdf7657c06f1b8bb07a8fcf697d2abf295" +"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +"checksum security-framework 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "97bbedbe81904398b6ebb054b3e912f99d55807125790f3198ac990d98def5b0" +"checksum security-framework-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "06fd2f23e31ef68dd2328cc383bd493142e46107a3a0e24f7d734e3f3b80fe4c" "checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" "checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" "checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" "checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" -"checksum serde_json 1.0.44 (registry+https://github.com/rust-lang/crates.io-index)" = "48c575e0cc52bdd09b47f330f646cf59afc586e9c4e3ccd6fc1f625b8ea1dad7" +"checksum serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" "checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" "checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" "checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" -"checksum sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "23962131a91661d643c98940b20fcaffe62d776a823247be80a48fcb8b6fce68" +"checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" "checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" "checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" "checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" -"checksum smallvec 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ecf3b85f68e8abaa7555aa5abdb1153079387e60b718283d732f03897fcfc86" -"checksum snafu 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "41207ca11f96a62cd34e6b7fdf73d322b25ae3848eb9d38302169724bb32cf27" -"checksum snafu-derive 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5e338c8b0577457c9dda8e794b6ad7231c96e25b1b0dd5842d52249020c1c0" +"checksum smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" +"checksum snafu 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "546db9181bce2aa22ed883c33d65603b76335b4c2533a98289f54265043de7a1" +"checksum snafu-derive 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bdc75da2e0323f297402fd9c8fdba709bb04e4c627cbe31d19a2c91fc8d9f0e2" "checksum snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef82be0baf3ae45701ab992230f1f4889c15984736d87f37558aea3e4e321af" "checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "30b3a3e93f5ad553c38b3301c8a0a0cec829a36783f6a0c467fc4bf553a5f5bf" -"checksum structopt-derive 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ea692d40005b3ceba90a9fe7a78fa8d4b82b0ce627eebbffc329aab850f3410e" -"checksum syn 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dff0acdb207ae2fe6d5976617f887eb1e35a2ba52c13c7234c790960cdad9238" +"checksum structopt 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe43617218c0805c6eb37160119dc3c548110a67786da7218d1c6555212f073" +"checksum structopt-derive 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e79c80e0f4efd86ca960218d4e056249be189ff1c42824dcd9a7f51a56f0bd" +"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" +"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" "checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" "checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" "checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -"checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e" +"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" "checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum thread_local 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b53e329000edc2b34dbe8545fd20e55a333362d0a321909685a19bd28c3f1b" +"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tinytemplate 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4574b75faccaacddb9b284faecdf0b544b80b6b294f3d062d325c5726a209c20" +"checksum tinytemplate 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "57a3c6667d3e65eb1bc3aed6fd14011c6cbc3a0665218ab7f5daf040b9ec371a" "checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" -"checksum tokio-codec 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5c501eceaf96f0e1793cf26beb63da3d11c738c4a943fdf3746d81d64684c39f" -"checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443" -"checksum tokio-executor 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "ca6df436c42b0c3330a82d855d2ef017cd793090ad550a6bc2184f4b933532ab" -"checksum tokio-fs 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe6dc22b08d6993916647d108a1a7d15b9cd29c4f4496c62b92c45b5041b7af" -"checksum tokio-io 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5090db468dad16e1a7a54c8c67280c5e4b544f3d3e018f0b913b400261f85926" -"checksum tokio-reactor 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "6732fe6b53c8d11178dcb77ac6d9682af27fc6d4cb87789449152e5377377146" -"checksum tokio-sync 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "d06554cce1ae4a50f42fba8023918afa931413aded705b560e29600ccf7c6d76" -"checksum tokio-tcp 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1d14b10654be682ac43efee27401d792507e30fd8d26389e1da3b185de2e4119" -"checksum tokio-threadpool 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "f0c32ffea4827978e9aa392d2f743d973c1dfa3730a2ed3f22ce1e6984da848c" -"checksum tokio-timer 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "1739638e364e558128461fc1ad84d997702c8e31c2e6b18fb99842268199e827" -"checksum tokio-udp 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f02298505547f73e60f568359ef0d016d5acd6e830ab9bc7c4a5b3403440121b" -"checksum tokio-uds 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "037ffc3ba0e12a0ab4aca92e5234e0dedeb48fddf6ccd260f1f150a36a9f2445" +"checksum tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" +"checksum tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" +"checksum tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" +"checksum tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" +"checksum tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" +"checksum tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" +"checksum tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" +"checksum tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" +"checksum tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" +"checksum tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" +"checksum tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" +"checksum tokio-uds 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" "checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" "checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" "checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" "checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" "checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" "checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "b561e267b2326bb4cebfc0ef9e68355c7abe6c6f522aeac2f5bf95d56c59bdcf" +"checksum unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" "checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" "checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" "checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" "checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "75b414f6c464c879d7f9babf951f23bc3743fb7313c081b2e6ca719067ea9d61" +"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" "checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" "checksum uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" "checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" "checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" "checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" -"checksum walkdir 2.2.9 (registry+https://github.com/rust-lang/crates.io-index)" = "9658c94fa8b940eab2250bd5a457f9c48b748420d71293b165c8cdbe2f55f71e" +"checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" "checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" -"checksum wasi 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d" +"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" +"checksum wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "3557c397ab5a8e347d434782bcd31fc1483d927a6826804cec05cc792ee2519d" +"checksum wasm-bindgen-backend 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "e0da9c9a19850d3af6df1cb9574970b566d617ecfaf36eb0b706b6f3ef9bd2f8" +"checksum wasm-bindgen-macro 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "0f6fde1d36e75a714b5fe0cffbb78978f222ea6baebb726af13c78869fdb4205" +"checksum wasm-bindgen-macro-support 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "25bda4168030a6412ea8a047e27238cadf56f0e53516e1e83fec0a8b7c786f6d" +"checksum wasm-bindgen-shared 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "fc9f36ad51f25b0219a3d4d13b90eb44cd075dff8b6280cca015775d7acaddd8" +"checksum web-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)" = "721c6263e2c66fd44501cc5efbfa2b7dfa775d13e4ea38c46299646ed1f9c70a" "checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" "checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" "checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7168bab6e1daee33b4557efd0e95d5ca70a03706d39fa5f3fe7a236f584b03c9" +"checksum winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum wincolor 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "96f5016b18804d24db43cebf3c77269e7569b8954a8464501c216cc5e070eaa9" "checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" "checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" "checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" From 0187da5f24a2be8f86c1eb5a7ca87f7ac37bd302 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 6 Mar 2020 13:56:21 -0800 Subject: [PATCH 0964/1504] Release 0.6.0-alpha.2 --- CHANGELOG.md | 2 ++ Cargo.lock | 6 +++--- Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d56c94e8..89c91b71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes for 0.6.x + +## [0.6.0 Alpha 2](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.2) (March 6, 2020) * Fixed `rojo upload` command always uploading models. * Removed `--kind` parameter to `rojo upload`; Rojo now automatically uploads the correct kind of asset based on your project file. diff --git a/Cargo.lock b/Cargo.lock index 491d9c39..3ad24ba4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -195,7 +195,7 @@ dependencies = [ name = "clibrojo" version = "0.1.0" dependencies = [ - "rojo 0.6.0-alpha.1", + "rojo 0.6.0-alpha.2", ] [[package]] @@ -1655,7 +1655,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.6.0-alpha.1" +version = "0.6.0-alpha.2" dependencies = [ "criterion 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1713,7 +1713,7 @@ dependencies = [ "paste 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rojo 0.6.0-alpha.1", + "rojo 0.6.0-alpha.2", "rojo-insta-ext 0.1.0", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 5759aab6..20fe9229 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.6.0-alpha.1" +version = "0.6.0-alpha.2" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index f31b1df0..0c441833 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {0, 6, 0, "-alpha.1"}, + version = {0, 6, 0, "-alpha.2"}, expectedServerVersionString = "0.6.0 or newer", protocolVersion = 3, defaultHost = "localhost", From 199a39208c6fee1b135047ac92e14dca2cbf09d3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 8 Mar 2020 17:48:14 -0700 Subject: [PATCH 0965/1504] Implement 'rojo build --watch' (#284) * Refactor build command to reproduce model more easily * Spawn ServeSession for building --- Cargo.toml | 2 +- src/cli/build.rs | 47 ++++++++++++++++++++++++++++++++++++++--------- src/cli/mod.rs | 4 ++++ 3 files changed, 43 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 20fe9229..a85b486d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,6 +80,7 @@ serde_json = "1.0" snafu = "0.6.0" structopt = "0.3.5" termcolor = "1.0.5" +tokio = "0.1.22" uuid = { version = "0.8.1", features = ["v4", "serde"] } [target.'cfg(windows)'.dependencies] @@ -95,5 +96,4 @@ paste = "0.1" pretty_assertions = "0.6.1" serde_yaml = "0.8.9" tempfile = "3.0" -tokio = "0.1.22" walkdir = "2.1" diff --git a/src/cli/build.rs b/src/cli/build.rs index fff73fa4..d3d3f07c 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -4,11 +4,13 @@ use std::{ }; use snafu::{ResultExt, Snafu}; +use tokio::runtime::Runtime; use crate::{ cli::BuildCommand, - common_setup, project::ProjectError, + serve_session::ServeSession, + snapshot::RojoTree, vfs::{RealFetcher, Vfs, WatchMode}, }; @@ -71,18 +73,47 @@ pub fn build(options: BuildCommand) -> Result<(), BuildError> { } fn build_inner(options: BuildCommand) -> Result<(), Error> { - let output_kind = detect_output_kind(&options).ok_or(Error::UnknownOutputKind)?; + log::trace!("Constructing in-memory filesystem"); + let watch_mode = if options.watch { + WatchMode::Enabled + } else { + WatchMode::Disabled + }; + + let vfs = Vfs::new(RealFetcher::new(watch_mode)); + + let session = ServeSession::new(vfs, &options.absolute_project()); + let mut cursor = session.message_queue().cursor(); + + { + let tree = session.tree(); + write_model(&tree, &options)?; + } + + if options.watch { + let mut rt = Runtime::new().unwrap(); + + loop { + let receiver = session.message_queue().subscribe(cursor); + let (new_cursor, _patch_set) = rt.block_on(receiver).unwrap(); + cursor = new_cursor; + + let tree = session.tree(); + write_model(&tree, &options)?; + } + } + + Ok(()) +} + +fn write_model(tree: &RojoTree, options: &BuildCommand) -> Result<(), Error> { + let output_kind = detect_output_kind(&options).ok_or(Error::UnknownOutputKind)?; log::debug!("Hoping to generate file of type {:?}", output_kind); - log::trace!("Constructing in-memory filesystem"); - let vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); - - let (_maybe_project, tree) = common_setup::start(&options.absolute_project(), &vfs); let root_id = tree.get_root_id(); log::trace!("Opening output file for write"); - let file = File::create(&options.output).context(Io)?; let mut file = BufWriter::new(file); @@ -121,7 +152,5 @@ fn build_inner(options: BuildCommand) -> Result<(), Error> { file.flush().context(Io)?; - log::trace!("Done!"); - Ok(()) } diff --git a/src/cli/mod.rs b/src/cli/mod.rs index a10039da..d0048116 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -140,6 +140,10 @@ pub struct BuildCommand { /// Where to output the result. #[structopt(long, short)] pub output: PathBuf, + + /// Whether to automatically rebuild when any input files change. + #[structopt(long)] + pub watch: bool, } impl BuildCommand { From 04529de7b39a2ac9bde6012121beb93b93c31138 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 8 Mar 2020 17:48:50 -0700 Subject: [PATCH 0966/1504] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 89c91b71..ca455cbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes for 0.6.x +* Added `--watch` argument to `rojo build` ([#284](https://github.com/rojo-rbx/rojo/pull/284)) ## [0.6.0 Alpha 2](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.2) (March 6, 2020) * Fixed `rojo upload` command always uploading models. From 3107b1b21b22b66329f02bfc68eeac4f89a2d46c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 8 Mar 2020 18:32:42 -0700 Subject: [PATCH 0967/1504] Dynamic theming. Closes #241. Upgrades to Roact master and introduces dynamic theme switching. We branch on the theme name in order to try to use Rojo's brand colors instead of Studio's. I kind of winged it with these colors and we might want to choose slightly nicer dark theme colors in the future. I also took the opportunity to reorganize the color naming scheme since it didn't really work for dark theme. --- plugin/modules/roact | 2 +- plugin/src/Components/App.lua | 9 +- plugin/src/Components/ConnectPanel.lua | 220 +++++++++--------- plugin/src/Components/ConnectingPanel.lua | 37 +-- .../src/Components/ConnectionActivePanel.lua | 53 ++--- plugin/src/Components/ErrorPanel.lua | 89 +++---- plugin/src/Components/FormButton.lua | 74 +++--- plugin/src/Components/FormTextInput.lua | 80 +++---- plugin/src/Components/Panel.lua | 32 +-- plugin/src/Components/RojoFooter.lua | 85 +++---- plugin/src/Components/Theme.lua | 104 +++++++++ plugin/src/Theme.lua | 14 -- plugin/src/init.server.lua | 2 +- 13 files changed, 455 insertions(+), 346 deletions(-) create mode 100644 plugin/src/Components/Theme.lua delete mode 100644 plugin/src/Theme.lua diff --git a/plugin/modules/roact b/plugin/modules/roact index b1db3f82..f7d2f1ce 160000 --- a/plugin/modules/roact +++ b/plugin/modules/roact @@ -1 +1 @@ -Subproject commit b1db3f82a2510c4e5e5b2bdc2c47298ea02dabd8 +Subproject commit f7d2f1ce1dd69120f457c2f8032bb184eb8f0c29 diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 9fbb3c0a..3617b2fd 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -13,6 +13,7 @@ local Version = require(Plugin.Version) local preloadAssets = require(Plugin.preloadAssets) local strict = require(Plugin.strict) +local Theme = require(Plugin.Components.Theme) local ConnectPanel = require(Plugin.Components.ConnectPanel) local ConnectingPanel = require(Plugin.Components.ConnectingPanel) local ConnectionActivePanel = require(Plugin.Components.ConnectionActivePanel) @@ -199,9 +200,11 @@ function App:render() } end - return Roact.createElement(Roact.Portal, { - target = self.dockWidget, - }, children) + return Roact.createElement(Theme.StudioProvider, nil, { + UI = Roact.createElement(Roact.Portal, { + target = self.dockWidget, + }, children), + }) end function App:didMount() diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index 8dd092d1..7c89efe4 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -4,8 +4,8 @@ local Plugin = Rojo.Plugin local Roact = require(Rojo.Roact) local Config = require(Plugin.Config) -local Theme = require(Plugin.Theme) +local Theme = require(Plugin.Components.Theme) local Panel = require(Plugin.Components.Panel) local FitList = require(Plugin.Components.FitList) local FitText = require(Plugin.Components.FitText) @@ -26,136 +26,138 @@ end function ConnectPanel:render() local startSession = self.props.startSession - return e(Panel, nil, { - Layout = e("UIListLayout", { - SortOrder = Enum.SortOrder.LayoutOrder, - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - }), + return Theme.with(function(theme) + return e(Panel, nil, { + Layout = e("UIListLayout", { + SortOrder = Enum.SortOrder.LayoutOrder, + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + }), - Inputs = e(FitList, { - containerProps = { - BackgroundTransparency = 1, - LayoutOrder = 1, - }, - layoutProps = { - FillDirection = Enum.FillDirection.Horizontal, - Padding = UDim.new(0, 8), - }, - paddingProps = { - PaddingTop = UDim.new(0, 20), - PaddingBottom = UDim.new(0, 10), - PaddingLeft = UDim.new(0, 24), - PaddingRight = UDim.new(0, 24), - }, - }, { - Address = e(FitList, { + Inputs = e(FitList, { containerProps = { - LayoutOrder = 1, BackgroundTransparency = 1, + LayoutOrder = 1, }, layoutProps = { - Padding = UDim.new(0, 4), + FillDirection = Enum.FillDirection.Horizontal, + Padding = UDim.new(0, 8), + }, + paddingProps = { + PaddingTop = UDim.new(0, 20), + PaddingBottom = UDim.new(0, 10), + PaddingLeft = UDim.new(0, 24), + PaddingRight = UDim.new(0, 24), }, }, { - Label = e(FitText, { - Kind = "TextLabel", - LayoutOrder = 1, - BackgroundTransparency = 1, - TextXAlignment = Enum.TextXAlignment.Left, - Font = Theme.TitleFont, - TextSize = 20, - Text = "Address", - TextColor3 = Theme.PrimaryColor, + Address = e(FitList, { + containerProps = { + LayoutOrder = 1, + BackgroundTransparency = 1, + }, + layoutProps = { + Padding = UDim.new(0, 4), + }, + }, { + Label = e(FitText, { + Kind = "TextLabel", + LayoutOrder = 1, + BackgroundTransparency = 1, + TextXAlignment = Enum.TextXAlignment.Left, + Font = theme.TitleFont, + TextSize = 20, + Text = "Address", + TextColor3 = theme.Text1, + }), + + Input = e(FormTextInput, { + layoutOrder = 2, + width = UDim.new(0, 220), + value = self.state.address, + placeholderValue = Config.defaultHost, + onValueChange = function(newValue) + self:setState({ + address = newValue, + }) + end, + }), }), - Input = e(FormTextInput, { - layoutOrder = 2, - width = UDim.new(0, 220), - value = self.state.address, - placeholderValue = Config.defaultHost, - onValueChange = function(newValue) - self:setState({ - address = newValue, - }) - end, + Port = e(FitList, { + containerProps = { + LayoutOrder = 2, + BackgroundTransparency = 1, + }, + layoutProps = { + Padding = UDim.new(0, 4), + }, + }, { + Label = e(FitText, { + Kind = "TextLabel", + LayoutOrder = 1, + BackgroundTransparency = 1, + TextXAlignment = Enum.TextXAlignment.Left, + Font = theme.TitleFont, + TextSize = 20, + Text = "Port", + TextColor3 = theme.Text1, + }), + + Input = e(FormTextInput, { + layoutOrder = 2, + width = UDim.new(0, 80), + value = self.state.port, + placeholderValue = Config.defaultPort, + onValueChange = function(newValue) + self:setState({ + port = newValue, + }) + end, + }), }), }), - Port = e(FitList, { + Buttons = e(FitList, { + fitAxes = "Y", containerProps = { + BackgroundTransparency = 1, LayoutOrder = 2, - BackgroundTransparency = 1, + Size = UDim2.new(1, 0, 0, 0), }, layoutProps = { - Padding = UDim.new(0, 4), + FillDirection = Enum.FillDirection.Horizontal, + HorizontalAlignment = Enum.HorizontalAlignment.Right, + Padding = UDim.new(0, 8), + }, + paddingProps = { + PaddingTop = UDim.new(0, 0), + PaddingBottom = UDim.new(0, 20), + PaddingLeft = UDim.new(0, 24), + PaddingRight = UDim.new(0, 24), }, }, { - Label = e(FitText, { - Kind = "TextLabel", - LayoutOrder = 1, - BackgroundTransparency = 1, - TextXAlignment = Enum.TextXAlignment.Left, - Font = Theme.TitleFont, - TextSize = 20, - Text = "Port", - TextColor3 = Theme.PrimaryColor, - }), - - Input = e(FormTextInput, { + e(FormButton, { layoutOrder = 2, - width = UDim.new(0, 80), - value = self.state.port, - placeholderValue = Config.defaultPort, - onValueChange = function(newValue) - self:setState({ - port = newValue, - }) + text = "Connect", + onClick = function() + if startSession ~= nil then + local address = self.state.address + if address:len() == 0 then + address = Config.defaultHost + end + + local port = self.state.port + if port:len() == 0 then + port = Config.defaultPort + end + + startSession(address, port) + end end, }), }), - }), - - Buttons = e(FitList, { - fitAxes = "Y", - containerProps = { - BackgroundTransparency = 1, - LayoutOrder = 2, - Size = UDim2.new(1, 0, 0, 0), - }, - layoutProps = { - FillDirection = Enum.FillDirection.Horizontal, - HorizontalAlignment = Enum.HorizontalAlignment.Right, - Padding = UDim.new(0, 8), - }, - paddingProps = { - PaddingTop = UDim.new(0, 0), - PaddingBottom = UDim.new(0, 20), - PaddingLeft = UDim.new(0, 24), - PaddingRight = UDim.new(0, 24), - }, - }, { - e(FormButton, { - layoutOrder = 2, - text = "Connect", - onClick = function() - if startSession ~= nil then - local address = self.state.address - if address:len() == 0 then - address = Config.defaultHost - end - - local port = self.state.port - if port:len() == 0 then - port = Config.defaultPort - end - - startSession(address, port) - end - end, - }), - }), - }) + }) + end) end return ConnectPanel \ No newline at end of file diff --git a/plugin/src/Components/ConnectingPanel.lua b/plugin/src/Components/ConnectingPanel.lua index c28d6880..9dd0c126 100644 --- a/plugin/src/Components/ConnectingPanel.lua +++ b/plugin/src/Components/ConnectingPanel.lua @@ -2,8 +2,7 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) local Plugin = script:FindFirstAncestor("Plugin") -local Theme = require(Plugin.Theme) - +local Theme = require(Plugin.Components.Theme) local Panel = require(Plugin.Components.Panel) local FitText = require(Plugin.Components.FitText) @@ -12,23 +11,25 @@ local e = Roact.createElement local ConnectingPanel = Roact.Component:extend("ConnectingPanel") function ConnectingPanel:render() - return e(Panel, nil, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 8), - }), + return Theme.with(function(theme) + return e(Panel, nil, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 8), + }), - Text = e(FitText, { - Padding = Vector2.new(12, 6), - Font = Theme.ButtonFont, - TextSize = 18, - Text = "Connecting...", - TextColor3 = Theme.PrimaryColor, - BackgroundTransparency = 1, - }), - }) + Text = e(FitText, { + Padding = Vector2.new(12, 6), + Font = theme.ButtonFont, + TextSize = 18, + Text = "Connecting...", + TextColor3 = theme.Text1, + BackgroundTransparency = 1, + }), + }) + end) end return ConnectingPanel \ No newline at end of file diff --git a/plugin/src/Components/ConnectionActivePanel.lua b/plugin/src/Components/ConnectionActivePanel.lua index 47cb1aa5..437589a9 100644 --- a/plugin/src/Components/ConnectionActivePanel.lua +++ b/plugin/src/Components/ConnectionActivePanel.lua @@ -2,8 +2,7 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) local Plugin = script:FindFirstAncestor("Plugin") -local Theme = require(Plugin.Theme) - +local Theme = require(Plugin.Components.Theme) local Panel = require(Plugin.Components.Panel) local FitText = require(Plugin.Components.FitText) local FormButton = require(Plugin.Components.FormButton) @@ -15,32 +14,34 @@ local ConnectionActivePanel = Roact.Component:extend("ConnectionActivePanel") function ConnectionActivePanel:render() local stopSession = self.props.stopSession - return e(Panel, nil, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 8), - }), + return Theme.with(function(theme) + return e(Panel, nil, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 8), + }), - Text = e(FitText, { - Padding = Vector2.new(12, 6), - Font = Theme.ButtonFont, - TextSize = 18, - Text = "Connected to Live-Sync Server", - TextColor3 = Theme.PrimaryColor, - BackgroundTransparency = 1, - }), + Text = e(FitText, { + Padding = Vector2.new(12, 6), + Font = theme.ButtonFont, + TextSize = 18, + Text = "Connected to Live-Sync Server", + TextColor3 = theme.Text1, + BackgroundTransparency = 1, + }), - DisconnectButton = e(FormButton, { - layoutOrder = 2, - text = "Disconnect", - secondary = true, - onClick = function() - stopSession() - end, - }), - }) + DisconnectButton = e(FormButton, { + layoutOrder = 2, + text = "Disconnect", + secondary = true, + onClick = function() + stopSession() + end, + }), + }) + end) end return ConnectionActivePanel \ No newline at end of file diff --git a/plugin/src/Components/ErrorPanel.lua b/plugin/src/Components/ErrorPanel.lua index 97b16929..e541e0d8 100644 --- a/plugin/src/Components/ErrorPanel.lua +++ b/plugin/src/Components/ErrorPanel.lua @@ -2,8 +2,7 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) local Plugin = script:FindFirstAncestor("Plugin") -local Theme = require(Plugin.Theme) - +local Theme = require(Plugin.Components.Theme) local Panel = require(Plugin.Components.Panel) local FitText = require(Plugin.Components.FitText) local FitScrollingFrame = require(Plugin.Components.FitScrollingFrame) @@ -20,50 +19,52 @@ function ErrorPanel:render() local errorMessage = self.props.errorMessage local onDismiss = self.props.onDismiss - return e(Panel, nil, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 8), - }), - - ErrorContainer = e(FitScrollingFrame, { - containerProps = { - BackgroundTransparency = 1, - BorderSizePixel = 0, - Size = UDim2.new(1, -HOR_PADDING * 2, 1, -BUTTON_HEIGHT), - Position = UDim2.new(0, HOR_PADDING, 0, 0), - ScrollBarImageColor3 = Theme.PrimaryColor, - VerticalScrollBarInset = Enum.ScrollBarInset.ScrollBar, - ScrollingDirection = Enum.ScrollingDirection.Y, - }, - }, { - Text = e(FitText, { - Size = UDim2.new(1, 0, 0, 0), - - LayoutOrder = 1, - TextXAlignment = Enum.TextXAlignment.Left, - TextYAlignment = Enum.TextYAlignment.Top, - FitAxis = "Y", - Font = Theme.ButtonFont, - TextSize = 18, - Text = errorMessage, - TextWrap = true, - TextColor3 = Theme.PrimaryColor, - BackgroundTransparency = 1, + return Theme.with(function(theme) + return e(Panel, nil, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 8), }), - }), - DismissButton = e(FormButton, { - layoutOrder = 2, - text = "Dismiss", - secondary = true, - onClick = function() - onDismiss() - end, - }), - }) + ErrorContainer = e(FitScrollingFrame, { + containerProps = { + BackgroundTransparency = 1, + BorderSizePixel = 0, + Size = UDim2.new(1, -HOR_PADDING * 2, 1, -BUTTON_HEIGHT), + Position = UDim2.new(0, HOR_PADDING, 0, 0), + ScrollBarImageColor3 = theme.Text1, + VerticalScrollBarInset = Enum.ScrollBarInset.ScrollBar, + ScrollingDirection = Enum.ScrollingDirection.Y, + }, + }, { + Text = e(FitText, { + Size = UDim2.new(1, 0, 0, 0), + + LayoutOrder = 1, + TextXAlignment = Enum.TextXAlignment.Left, + TextYAlignment = Enum.TextYAlignment.Top, + FitAxis = "Y", + Font = theme.ButtonFont, + TextSize = 18, + Text = errorMessage, + TextWrap = true, + TextColor3 = theme.Text1, + BackgroundTransparency = 1, + }), + }), + + DismissButton = e(FormButton, { + layoutOrder = 2, + text = "Dismiss", + secondary = true, + onClick = function() + onDismiss() + end, + }), + }) + end) end return ErrorPanel \ No newline at end of file diff --git a/plugin/src/Components/FormButton.lua b/plugin/src/Components/FormButton.lua index 94ffba5e..7451395a 100644 --- a/plugin/src/Components/FormButton.lua +++ b/plugin/src/Components/FormButton.lua @@ -4,7 +4,7 @@ local Plugin = Rojo.Plugin local Roact = require(Rojo.Roact) local Assets = require(Plugin.Assets) -local Theme = require(Plugin.Theme) +local Theme = require(Plugin.Components.Theme) local FitList = require(Plugin.Components.FitList) local FitText = require(Plugin.Components.FitText) @@ -20,43 +20,45 @@ local function FormButton(props) local textColor local backgroundColor - if props.secondary then - textColor = Theme.AccentColor - backgroundColor = Theme.SecondaryColor - else - textColor = Theme.SecondaryColor - backgroundColor = Theme.AccentColor - end + return Theme.with(function(theme) + if props.secondary then + textColor = theme.Brand1 + backgroundColor = theme.Background2 + else + textColor = theme.TextOnAccent + backgroundColor = theme.Brand1 + end - return e(FitList, { - containerKind = "ImageButton", - containerProps = { - LayoutOrder = layoutOrder, - BackgroundTransparency = 1, - Image = RoundBox.asset, - ImageRectOffset = RoundBox.offset, - ImageRectSize = RoundBox.size, - SliceCenter = RoundBox.center, - ScaleType = Enum.ScaleType.Slice, - ImageColor3 = backgroundColor, + return e(FitList, { + containerKind = "ImageButton", + containerProps = { + LayoutOrder = layoutOrder, + BackgroundTransparency = 1, + Image = RoundBox.asset, + ImageRectOffset = RoundBox.offset, + ImageRectSize = RoundBox.size, + SliceCenter = RoundBox.center, + ScaleType = Enum.ScaleType.Slice, + ImageColor3 = backgroundColor, - [Roact.Event.Activated] = function() - if onClick ~= nil then - onClick() - end - end, - }, - }, { - Text = e(FitText, { - Kind = "TextLabel", - Text = text, - TextSize = 18, - TextColor3 = textColor, - Font = Theme.ButtonFont, - Padding = Vector2.new(16, 8), - BackgroundTransparency = 1, - }), - }) + [Roact.Event.Activated] = function() + if onClick ~= nil then + onClick() + end + end, + }, + }, { + Text = e(FitText, { + Kind = "TextLabel", + Text = text, + TextSize = 18, + TextColor3 = textColor, + Font = theme.ButtonFont, + Padding = Vector2.new(16, 8), + BackgroundTransparency = 1, + }), + }) + end) end return FormButton \ No newline at end of file diff --git a/plugin/src/Components/FormTextInput.lua b/plugin/src/Components/FormTextInput.lua index 22748c4b..f1f4625f 100644 --- a/plugin/src/Components/FormTextInput.lua +++ b/plugin/src/Components/FormTextInput.lua @@ -4,7 +4,7 @@ local Plugin = Rojo.Plugin local Roact = require(Rojo.Roact) local Assets = require(Plugin.Assets) -local Theme = require(Plugin.Theme) +local Theme = require(Plugin.Components.Theme) local e = Roact.createElement @@ -35,46 +35,48 @@ function FormTextInput:render() shownPlaceholder = placeholderValue end - return e("ImageLabel", { - LayoutOrder = layoutOrder, - Image = RoundBox.asset, - ImageRectOffset = RoundBox.offset, - ImageRectSize = RoundBox.size, - ScaleType = Enum.ScaleType.Slice, - SliceCenter = RoundBox.center, - ImageColor3 = Theme.SecondaryColor, - Size = UDim2.new(width.Scale, width.Offset, 0, TEXT_SIZE + PADDING * 2), - BackgroundTransparency = 1, - }, { - InputInner = e("TextBox", { + return Theme.with(function(theme) + return e("ImageLabel", { + LayoutOrder = layoutOrder, + Image = RoundBox.asset, + ImageRectOffset = RoundBox.offset, + ImageRectSize = RoundBox.size, + ScaleType = Enum.ScaleType.Slice, + SliceCenter = RoundBox.center, + ImageColor3 = theme.Background2, + Size = UDim2.new(width.Scale, width.Offset, 0, TEXT_SIZE + PADDING * 2), BackgroundTransparency = 1, - Size = UDim2.new(1, -PADDING * 2, 1, -PADDING * 2), - Position = UDim2.new(0.5, 0, 0.5, 0), - AnchorPoint = Vector2.new(0.5, 0.5), - Font = Theme.InputFont, - ClearTextOnFocus = false, - TextXAlignment = Enum.TextXAlignment.Center, - TextSize = TEXT_SIZE, - Text = value, - PlaceholderText = shownPlaceholder, - PlaceholderColor3 = Theme.LightTextColor, - TextColor3 = Theme.PrimaryColor, + }, { + InputInner = e("TextBox", { + BackgroundTransparency = 1, + Size = UDim2.new(1, -PADDING * 2, 1, -PADDING * 2), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + Font = theme.InputFont, + ClearTextOnFocus = false, + TextXAlignment = Enum.TextXAlignment.Center, + TextSize = TEXT_SIZE, + Text = value, + PlaceholderText = shownPlaceholder, + PlaceholderColor3 = theme.Text2, + TextColor3 = theme.Text1, - [Roact.Change.Text] = function(rbx) - onValueChange(rbx.Text) - end, - [Roact.Event.Focused] = function() - self:setState({ - focused = true, - }) - end, - [Roact.Event.FocusLost] = function() - self:setState({ - focused = false, - }) - end, - }), - }) + [Roact.Change.Text] = function(rbx) + onValueChange(rbx.Text) + end, + [Roact.Event.Focused] = function() + self:setState({ + focused = true, + }) + end, + [Roact.Event.FocusLost] = function() + self:setState({ + focused = false, + }) + end, + }), + }) + end) end return FormTextInput \ No newline at end of file diff --git a/plugin/src/Components/Panel.lua b/plugin/src/Components/Panel.lua index 5ae1e874..9a19ecfc 100644 --- a/plugin/src/Components/Panel.lua +++ b/plugin/src/Components/Panel.lua @@ -3,6 +3,7 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) local Plugin = script:FindFirstAncestor("Plugin") local RojoFooter = require(Plugin.Components.RojoFooter) +local Theme = require(Plugin.Components.Theme) local e = Roact.createElement @@ -13,22 +14,25 @@ function Panel:init() end function Panel:render() - return e("Frame", { - Size = UDim2.new(1, 0, 1, 0), - BackgroundTransparency = 1, - }, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - }), - - Body = e("Frame", { - Size = UDim2.new(0, 360, 1, -32), + return Theme.with(function(theme) + return e("Frame", { + Size = UDim2.new(1, 0, 1, 0), BackgroundTransparency = 1, - }, self.props[Roact.Children]), + }, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + }), - Footer = e(RojoFooter), - }) + Body = e("Frame", { + Size = UDim2.new(0, 360, 1, -32), + BackgroundColor3 = theme.Background1, + BorderSizePixel = 0, + }, self.props[Roact.Children]), + + Footer = e(RojoFooter), + }) + end) end return Panel \ No newline at end of file diff --git a/plugin/src/Components/RojoFooter.lua b/plugin/src/Components/RojoFooter.lua index babc1a78..3a32c610 100644 --- a/plugin/src/Components/RojoFooter.lua +++ b/plugin/src/Components/RojoFooter.lua @@ -6,7 +6,7 @@ local Roact = require(Rojo.Roact) local Config = require(Plugin.Config) local Version = require(Plugin.Version) local Assets = require(Plugin.Assets) -local Theme = require(Plugin.Theme) +local Theme = require(Plugin.Components.Theme) local e = Roact.createElement @@ -18,50 +18,53 @@ function RojoFooter:init() end function RojoFooter:render() - return e("Frame", { - LayoutOrder = 3, - Size = UDim2.new(1, 0, 0, 32), - BackgroundColor3 = Theme.SecondaryColor, - BorderSizePixel = 0, - }, { - Padding = e("UIPadding", { - PaddingTop = UDim.new(0, 4), - PaddingBottom = UDim.new(0, 4), - PaddingLeft = UDim.new(0, 8), - PaddingRight = UDim.new(0, 8), - }), - - LogoContainer = e("Frame", { - BackgroundTransparency = 1, - - Size = UDim2.new(0, 0, 0, 32), + return Theme.with(function(theme) + return e("Frame", { + LayoutOrder = 3, + Size = UDim2.new(1, 0, 0, 32), + BackgroundColor3 = theme.Background2, + BorderSizePixel = 0, + ZIndex = 2, }, { - Logo = e("ImageLabel", { - Image = Assets.Images.Logo, - Size = UDim2.new(0, 80, 0, 40), - ScaleType = Enum.ScaleType.Fit, - BackgroundTransparency = 1, - Position = UDim2.new(0, 0, 1, -10), - AnchorPoint = Vector2.new(0, 1), + Padding = e("UIPadding", { + PaddingTop = UDim.new(0, 4), + PaddingBottom = UDim.new(0, 4), + PaddingLeft = UDim.new(0, 8), + PaddingRight = UDim.new(0, 8), }), - }), - Version = e("TextLabel", { - Position = UDim2.new(1, 0, 0, 0), - Size = UDim2.new(0, 0, 1, 0), - AnchorPoint = Vector2.new(1, 0), - Font = Theme.TitleFont, - TextSize = 18, - Text = Version.display(Config.version), - TextXAlignment = Enum.TextXAlignment.Right, - TextColor3 = Theme.LightTextColor, - BackgroundTransparency = 1, + LogoContainer = e("Frame", { + BackgroundTransparency = 1, - [Roact.Change.AbsoluteSize] = function(rbx) - self.setFooterVersionSize(rbx.AbsoluteSize) - end, - }), - }) + Size = UDim2.new(0, 0, 0, 32), + }, { + Logo = e("ImageLabel", { + Image = Assets.Images.Logo, + Size = UDim2.new(0, 80, 0, 40), + ScaleType = Enum.ScaleType.Fit, + BackgroundTransparency = 1, + Position = UDim2.new(0, 0, 1, -10), + AnchorPoint = Vector2.new(0, 1), + }), + }), + + Version = e("TextLabel", { + Position = UDim2.new(1, 0, 0, 0), + Size = UDim2.new(0, 0, 1, 0), + AnchorPoint = Vector2.new(1, 0), + Font = theme.TitleFont, + TextSize = 18, + Text = Version.display(Config.version), + TextXAlignment = Enum.TextXAlignment.Right, + TextColor3 = theme.Text2, + BackgroundTransparency = 1, + + [Roact.Change.AbsoluteSize] = function(rbx) + self.setFooterVersionSize(rbx.AbsoluteSize) + end, + }), + }) + end) end return RojoFooter \ No newline at end of file diff --git a/plugin/src/Components/Theme.lua b/plugin/src/Components/Theme.lua new file mode 100644 index 00000000..ebd46015 --- /dev/null +++ b/plugin/src/Components/Theme.lua @@ -0,0 +1,104 @@ +--[[ + Theming system taking advantage of Roact's new context API. + + Doesn't use colors provided by Studio and instead just branches on theme + name. This isn't exactly best practice. +]] + +local Studio = settings():GetService("Studio") + +local Rojo = script:FindFirstAncestor("Rojo") + +local Roact = require(Rojo.Roact) +local Log = require(Rojo.Log) + +local strict = require(script.Parent.Parent.strict) + +local lightTheme = strict("Theme", { + ButtonFont = Enum.Font.GothamSemibold, + InputFont = Enum.Font.Code, + TitleFont = Enum.Font.GothamBold, + MainFont = Enum.Font.Gotham, + + Brand1 = Color3.fromRGB(225, 56, 53), + + Text1 = Color3.fromRGB(64, 64, 64), + Text2 = Color3.fromRGB(160, 160, 160), + TextOnAccent = Color3.fromRGB(235, 235, 235), + + Background1 = Color3.fromRGB(255, 255, 255), + Background2 = Color3.fromRGB(235, 235, 235), +}) + +local darkTheme = strict("Theme", { + ButtonFont = Enum.Font.GothamSemibold, + InputFont = Enum.Font.Code, + TitleFont = Enum.Font.GothamBold, + MainFont = Enum.Font.Gotham, + + Brand1 = Color3.fromRGB(225, 56, 53), + + Text1 = Color3.fromRGB(235, 235, 235), + Text2 = Color3.fromRGB(200, 200, 200), + TextOnAccent = Color3.fromRGB(235, 235, 235), + + Background1 = Color3.fromRGB(48, 48, 48), + Background2 = Color3.fromRGB(64, 64, 64), +}) + +local Context = Roact.createContext(lightTheme) + +local StudioProvider = Roact.Component:extend("StudioProvider") + +-- Pull the current theme from Roblox Studio and update state with it. +function StudioProvider:updateTheme() + local studioTheme = Studio.Theme + + if studioTheme.Name == "Light" then + self:setState({ + theme = lightTheme, + }) + elseif studioTheme.Name == "Dark" then + self:setState({ + theme = darkTheme, + }) + else + Log.warn("Unexpected theme '{}'' -- falling back to light theme!", studioTheme.Name) + + self:setState({ + theme = lightTheme, + }) + end +end + +function StudioProvider:init() + self:updateTheme() +end + +function StudioProvider:render() + return Roact.createElement(Context.Provider, { + value = self.state.theme, + }, self.props[Roact.Children]) +end + +function StudioProvider:didMount() + self.connection = Studio.ThemeChanged:Connect(function() + self:updateTheme() + end) +end + +function StudioProvider:willUnmount() + self.connection:Disconnect() +end + +local function with(callback) + return Roact.createElement(Context.Consumer, { + render = callback, + }) +end + +return { + StudioProvider = StudioProvider, + Consumer = Context.Consumer, + with = with, +} \ No newline at end of file diff --git a/plugin/src/Theme.lua b/plugin/src/Theme.lua deleted file mode 100644 index 0307c287..00000000 --- a/plugin/src/Theme.lua +++ /dev/null @@ -1,14 +0,0 @@ -local strict = require(script.Parent.strict) - -return strict("Theme", { - ButtonFont = Enum.Font.GothamSemibold, - InputFont = Enum.Font.Code, - TitleFont = Enum.Font.GothamBold, - MainFont = Enum.Font.Gotham, - - AccentColor = Color3.fromRGB(225, 56, 53), - AccentLightColor = Color3.fromRGB(255, 146, 145), - PrimaryColor = Color3.fromRGB(64, 64, 64), - SecondaryColor = Color3.fromRGB(235, 235, 235), - LightTextColor = Color3.fromRGB(160, 160, 160), -}) \ No newline at end of file diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index c249171b..2aaf4514 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -19,7 +19,7 @@ local app = Roact.createElement(App, { plugin = plugin, }) -local tree = Roact.mount(app, game:GetService("CoreGui"), "Rojo UI") +local tree = Roact.mount(app, nil, "Rojo UI") plugin.Unloading:Connect(function() Roact.unmount(tree) From a884f693ae29e64addbd9f17a3dd9d5b6ca76ade Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 8 Mar 2020 18:34:11 -0700 Subject: [PATCH 0968/1504] Update changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca455cbb..8419fdaa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,8 @@ # Rojo Changelog ## Unreleased Changes for 0.6.x -* Added `--watch` argument to `rojo build` ([#284](https://github.com/rojo-rbx/rojo/pull/284)) +* Added `--watch` argument to `rojo build`. ([#284](https://github.com/rojo-rbx/rojo/pull/284)) +* Added dark theme support to plugin. ([#241](https://github.com/rojo-rbx/rojo/issues/241)) ## [0.6.0 Alpha 2](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.2) (March 6, 2020) * Fixed `rojo upload` command always uploading models. From 477e0ada3250d95485d7f3c99bedc26ee2435ad8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Mar 2020 17:38:49 -0700 Subject: [PATCH 0969/1504] VFS in external crate (#297) * vroom * Port dir middleware * Filter rules * Directory metadata * Project support * Enable Lua support * StringValue support * CSV * rbxm, rbxmx, and rbxlx * JSON models * Clean up some warnings * Strip out PathMap * Unwatch paths when they're reported as removed * Fix 'rojo upload' behavior * Upgrade to Insta 0.13.1 * Update dependencies * Release 0.6.0-alpha.2 * Fix bad merge * Replace MemoryBackend with InMemoryFs * Sledgehammer tests into passing for now * Txt middleware * Update easy snapshot tests * Lua tests * Project middleware tests * Try to fix test failures by sorting * Port first set of serve session tests * Add InMemoryFs::raise_event * Finish porting serve session tests * Remove UI code for introspecting VFS for now * VFS docs --- Cargo.lock | 1 + Cargo.toml | 1 + src/change_processor.rs | 36 +- src/cli/build.rs | 15 +- src/cli/serve.rs | 10 +- src/cli/upload.rs | 10 +- src/common_setup.rs | 14 +- src/lib.rs | 2 - src/path_map.rs | 282 -------- src/serve_session.rs | 224 +++---- src/snapshot_middleware/csv.rs | 35 +- src/snapshot_middleware/dir.rs | 110 ++-- src/snapshot_middleware/error.rs | 10 +- src/snapshot_middleware/json_model.rs | 88 +-- src/snapshot_middleware/lua.rs | 257 ++++---- src/snapshot_middleware/middleware.rs | 20 +- src/snapshot_middleware/mod.rs | 50 +- src/snapshot_middleware/project.rs | 407 ++++++------ src/snapshot_middleware/rbxlx.rs | 27 +- src/snapshot_middleware/rbxm.rs | 50 +- src/snapshot_middleware/rbxmx.rs | 77 +-- src/snapshot_middleware/txt.rs | 112 +--- src/vfs/error.rs | 55 -- src/vfs/event.rs | 8 - src/vfs/fetcher.rs | 37 -- src/vfs/mod.rs | 24 - src/vfs/noop_fetcher.rs | 62 -- src/vfs/real_fetcher.rs | 225 ------- src/vfs/snapshot.rs | 42 -- src/vfs/test_fetcher.rs | 171 ----- src/vfs/vfs.rs | 614 ------------------ src/web/api.rs | 11 +- src/web/mod.rs | 22 +- src/web/ui.rs | 109 +--- .../{memory_backend.rs => in_memory_fs.rs} | 101 ++- vfs/src/lib.rs | 8 +- vfs/src/snapshot.rs | 15 + vfs/src/std_backend.rs | 13 +- 38 files changed, 846 insertions(+), 2509 deletions(-) delete mode 100644 src/path_map.rs delete mode 100644 src/vfs/error.rs delete mode 100644 src/vfs/event.rs delete mode 100644 src/vfs/fetcher.rs delete mode 100644 src/vfs/mod.rs delete mode 100644 src/vfs/noop_fetcher.rs delete mode 100644 src/vfs/real_fetcher.rs delete mode 100644 src/vfs/snapshot.rs delete mode 100644 src/vfs/test_fetcher.rs delete mode 100644 src/vfs/vfs.rs rename vfs/src/{memory_backend.rs => in_memory_fs.rs} (65%) diff --git a/Cargo.lock b/Cargo.lock index 3ad24ba4..42982f53 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1691,6 +1691,7 @@ dependencies = [ "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "vfs 0.1.0", "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/Cargo.toml b/Cargo.toml index a85b486d..6b9d9837 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -82,6 +82,7 @@ structopt = "0.3.5" termcolor = "1.0.5" tokio = "0.1.22" uuid = { version = "0.8.1", features = ["v4", "serde"] } +vfs = { path = "vfs" } [target.'cfg(windows)'.dependencies] winreg = "0.6.2" diff --git a/src/change_processor.rs b/src/change_processor.rs index 902a1c12..0351f48c 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -6,6 +6,7 @@ use std::{ use crossbeam_channel::{select, Receiver, RecvError, Sender}; use jod_thread::JoinHandle; use rbx_dom_weak::{RbxId, RbxValue}; +use vfs::{IoResultExt, Vfs, VfsEvent}; use crate::{ message_queue::MessageQueue, @@ -13,7 +14,6 @@ use crate::{ apply_patch_set, compute_patch_set, AppliedPatchSet, InstigatingSource, PatchSet, RojoTree, }, snapshot_middleware::{snapshot_from_vfs, snapshot_project_node}, - vfs::{FsResultExt, Vfs, VfsEvent, VfsFetcher}, }; /// Owns the connection between Rojo's VFS and its DOM by holding onto another @@ -43,14 +43,14 @@ pub struct ChangeProcessor { impl ChangeProcessor { /// Spin up the ChangeProcessor, connecting it to the given tree, VFS, and /// outbound message queue. - pub fn start( + pub fn start( tree: Arc>, - vfs: Arc>, + vfs: Arc, message_queue: Arc>, tree_mutation_receiver: Receiver, ) -> Self { let (shutdown_sender, shutdown_receiver) = crossbeam_channel::bounded(1); - let vfs_receiver = vfs.change_receiver(); + let vfs_receiver = vfs.event_receiver(); let task = JobThreadContext { tree, vfs, @@ -107,25 +107,25 @@ impl Drop for ChangeProcessor { } /// Contains all of the state needed to synchronize the DOM and VFS. -struct JobThreadContext { +struct JobThreadContext { /// A handle to the DOM we're managing. tree: Arc>, /// A handle to the VFS we're managing. - vfs: Arc>, + vfs: Arc, /// Whenever changes are applied to the DOM, we should push those changes /// into this message queue to inform any connected clients. message_queue: Arc>, } -impl JobThreadContext { +impl JobThreadContext { fn handle_vfs_event(&self, event: VfsEvent) { log::trace!("Vfs event: {:?}", event); // Update the VFS immediately with the event. self.vfs - .commit_change(&event) + .commit_event(&event) .expect("Error applying VFS change"); // For a given VFS event, we might have many changes to different parts @@ -135,7 +135,7 @@ impl JobThreadContext { let mut applied_patches = Vec::new(); match event { - VfsEvent::Created(path) | VfsEvent::Modified(path) | VfsEvent::Removed(path) => { + VfsEvent::Create(path) | VfsEvent::Write(path) | VfsEvent::Remove(path) => { // Find the nearest ancestor to this path that has // associated instances in the tree. This helps make sure // that we handle additions correctly, especially if we @@ -164,6 +164,7 @@ impl JobThreadContext { } } } + _ => log::warn!("Unhandled VFS event: {:?}", event), } applied_patches @@ -262,11 +263,7 @@ impl JobThreadContext { } } -fn compute_and_apply_changes( - tree: &mut RojoTree, - vfs: &Vfs, - id: RbxId, -) -> Option { +fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: RbxId) -> Option { let metadata = tree .get_metadata(id) .expect("metadata missing for instance present in tree"); @@ -288,19 +285,16 @@ fn compute_and_apply_changes( // file/folder in the first place. let applied_patch_set = match instigating_source { InstigatingSource::Path(path) => { - let maybe_entry = vfs - .get(path) - .with_not_found() - .expect("unexpected VFS error"); + let maybe_meta = vfs.metadata(path).with_not_found().unwrap(); - match maybe_entry { - Some(entry) => { + match maybe_meta { + Some(_meta) => { // Our instance was previously created from a path and // that path still exists. We can generate a snapshot // starting at that path and use it as the source for // our patch. - let snapshot = snapshot_from_vfs(&metadata.context, &vfs, &entry) + let snapshot = snapshot_from_vfs(&metadata.context, &vfs, &path) .expect("snapshot failed") .expect("snapshot did not return an instance"); diff --git a/src/cli/build.rs b/src/cli/build.rs index d3d3f07c..901bd3d6 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -5,13 +5,10 @@ use std::{ use snafu::{ResultExt, Snafu}; use tokio::runtime::Runtime; +use vfs::Vfs; use crate::{ - cli::BuildCommand, - project::ProjectError, - serve_session::ServeSession, - snapshot::RojoTree, - vfs::{RealFetcher, Vfs, WatchMode}, + cli::BuildCommand, project::ProjectError, serve_session::ServeSession, snapshot::RojoTree, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -75,13 +72,7 @@ pub fn build(options: BuildCommand) -> Result<(), BuildError> { fn build_inner(options: BuildCommand) -> Result<(), Error> { log::trace!("Constructing in-memory filesystem"); - let watch_mode = if options.watch { - WatchMode::Enabled - } else { - WatchMode::Disabled - }; - - let vfs = Vfs::new(RealFetcher::new(watch_mode)); + let vfs = Vfs::new_default(); let session = ServeSession::new(vfs, &options.absolute_project()); let mut cursor = session.message_queue().cursor(); diff --git a/src/cli/serve.rs b/src/cli/serve.rs index 789cb2f1..6a04338c 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -5,13 +5,9 @@ use std::{ use snafu::Snafu; use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; +use vfs::Vfs; -use crate::{ - cli::ServeCommand, - serve_session::ServeSession, - vfs::{RealFetcher, Vfs, WatchMode}, - web::LiveServer, -}; +use crate::{cli::ServeCommand, serve_session::ServeSession, web::LiveServer}; const DEFAULT_PORT: u16 = 34872; @@ -26,7 +22,7 @@ pub fn serve(options: ServeCommand) -> Result<(), ServeError> { } fn serve_inner(options: ServeCommand) -> Result<(), Error> { - let vfs = Vfs::new(RealFetcher::new(WatchMode::Enabled)); + let vfs = Vfs::new_default(); let session = Arc::new(ServeSession::new(vfs, &options.absolute_project())); diff --git a/src/cli/upload.rs b/src/cli/upload.rs index 671c2b3c..f6a7b31b 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -1,12 +1,8 @@ use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}; use snafu::{ResultExt, Snafu}; +use vfs::Vfs; -use crate::{ - auth_cookie::get_auth_cookie, - cli::UploadCommand, - common_setup, - vfs::{RealFetcher, Vfs, WatchMode}, -}; +use crate::{auth_cookie::get_auth_cookie, cli::UploadCommand, common_setup}; #[derive(Debug, Snafu)] pub struct UploadError(Error); @@ -40,7 +36,7 @@ fn upload_inner(options: UploadCommand) -> Result<(), Error> { .ok_or(Error::NeedAuthCookie)?; log::trace!("Constructing in-memory filesystem"); - let vfs = Vfs::new(RealFetcher::new(WatchMode::Disabled)); + let vfs = Vfs::new_default(); let (_maybe_project, tree) = common_setup::start(&options.absolute_project(), &vfs); diff --git a/src/common_setup.rs b/src/common_setup.rs index dff3f23d..4ae37d79 100644 --- a/src/common_setup.rs +++ b/src/common_setup.rs @@ -4,6 +4,7 @@ use std::path::Path; use rbx_dom_weak::RbxInstanceProperties; +use vfs::Vfs; use crate::{ project::Project, @@ -12,13 +13,9 @@ use crate::{ PathIgnoreRule, RojoTree, }, snapshot_middleware::snapshot_from_vfs, - vfs::{Vfs, VfsFetcher}, }; -pub fn start( - fuzzy_project_path: &Path, - vfs: &Vfs, -) -> (Option, RojoTree) { +pub fn start(fuzzy_project_path: &Path, vfs: &Vfs) -> (Option, RojoTree) { log::trace!("Loading project file from {}", fuzzy_project_path.display()); let maybe_project = Project::load_fuzzy(fuzzy_project_path).expect("TODO: Project load failed"); @@ -34,11 +31,6 @@ pub fn start( let root_id = tree.get_root_id(); - log::trace!("Reading project root"); - let entry = vfs - .get(fuzzy_project_path) - .expect("could not get project path"); - let mut instance_context = InstanceContext::default(); if let Some(project) = &maybe_project { @@ -51,7 +43,7 @@ pub fn start( } log::trace!("Generating snapshot of instances from VFS"); - let snapshot = snapshot_from_vfs(&instance_context, vfs, &entry) + let snapshot = snapshot_from_vfs(&instance_context, vfs, &fuzzy_project_path) .expect("snapshot failed") .expect("snapshot did not return an instance"); diff --git a/src/lib.rs b/src/lib.rs index 0a59c819..8f5fae27 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -13,14 +13,12 @@ mod common_setup; mod glob; mod message_queue; mod multimap; -mod path_map; mod path_serializer; mod project; mod serve_session; mod session_id; mod snapshot; mod snapshot_middleware; -mod vfs; mod web; pub use project::*; diff --git a/src/path_map.rs b/src/path_map.rs deleted file mode 100644 index 19201add..00000000 --- a/src/path_map.rs +++ /dev/null @@ -1,282 +0,0 @@ -use std::{ - collections::{BTreeSet, HashMap}, - path::{Path, PathBuf}, -}; - -use log::warn; -use serde::Serialize; - -#[derive(Debug, Serialize)] -struct PathMapNode { - value: T, - children: BTreeSet, -} - -/// A map from paths to another type, like instance IDs, with a bit of -/// additional data that enables removing a path and all of its child paths from -/// the tree more quickly. -#[derive(Debug, Serialize)] -pub struct PathMap { - nodes: HashMap>, - - /// Contains the set of all paths whose parent either does not exist, or is - /// not present in the PathMap. - /// - /// Note that these paths may have other _ancestors_ in the tree, but if an - /// orphan's parent path is ever inserted, it will stop being an orphan. It - /// will be... adopted! - orphan_paths: BTreeSet, -} - -impl Default for PathMap { - fn default() -> Self { - Self::new() - } -} - -impl PathMap { - pub fn new() -> PathMap { - PathMap { - nodes: HashMap::new(), - orphan_paths: BTreeSet::new(), - } - } - - pub fn get(&self, path: impl AsRef) -> Option<&T> { - self.nodes.get(path.as_ref()).map(|v| &v.value) - } - - pub fn get_mut(&mut self, path: impl AsRef) -> Option<&mut T> { - self.nodes.get_mut(path.as_ref()).map(|v| &mut v.value) - } - - pub fn children(&self, path: impl AsRef) -> Option> { - self.nodes - .get(path.as_ref()) - .map(|v| v.children.iter().map(AsRef::as_ref).collect()) - } - - pub fn contains_key(&self, path: impl AsRef) -> bool { - self.nodes.contains_key(path.as_ref()) - } - - pub fn insert(&mut self, path: impl Into, value: T) { - let path = path.into(); - - self.add_to_parent(path.clone()); - - // Collect any children that are currently marked as orphaned paths, but - // are actually children of this new node. - let mut children = BTreeSet::new(); - for orphan_path in &self.orphan_paths { - if orphan_path.parent() == Some(&path) { - children.insert(orphan_path.clone()); - } - } - - for child in &children { - self.orphan_paths.remove(child); - } - - self.nodes.insert(path, PathMapNode { value, children }); - } - - /// Remove the given path and all of its linked descendants, returning all - /// values stored in the map. - pub fn remove(&mut self, root_path: impl AsRef) -> Vec<(PathBuf, T)> { - let root_path = root_path.as_ref(); - - self.remove_from_parent(root_path); - - let (root_path, root_node) = match self.nodes.remove_entry(root_path) { - Some(node) => node, - None => return Vec::new(), - }; - - let mut removed_entries = vec![(root_path, root_node.value)]; - let mut to_visit: Vec = root_node.children.into_iter().collect(); - - while let Some(path) = to_visit.pop() { - match self.nodes.remove_entry(&path) { - Some((path, node)) => { - removed_entries.push((path, node.value)); - - for child in node.children.into_iter() { - to_visit.push(child); - } - } - None => { - warn!( - "Consistency issue; tried to remove {} but it was already removed", - path.display() - ); - } - } - } - - removed_entries - } - - pub fn orphans(&self) -> impl Iterator { - self.orphan_paths.iter().map(|item| item.as_ref()) - } - - /// Adds the path to its parent if it's present in the tree, or the set of - /// orphaned paths if it is not. - fn add_to_parent(&mut self, path: PathBuf) { - if let Some(parent_path) = path.parent() { - if let Some(parent) = self.nodes.get_mut(parent_path) { - parent.children.insert(path); - return; - } - } - - // In this branch, the path is orphaned because it either doesn't have a - // parent according to Path, or because its parent doesn't exist in the - // PathMap. - self.orphan_paths.insert(path); - } - - /// Removes the path from its parent, or from the orphaned paths set if it - /// has no parent. - fn remove_from_parent(&mut self, path: &Path) { - if let Some(parent_path) = path.parent() { - if let Some(parent) = self.nodes.get_mut(parent_path) { - parent.children.remove(path); - return; - } - } - - // In this branch, the path is orphaned because it either doesn't have a - // parent according to Path, or because its parent doesn't exist in the - // PathMap. - self.orphan_paths.remove(path); - } -} - -#[cfg(test)] -mod test { - use super::*; - - use maplit::btreeset; - - #[test] - fn smoke_test() { - let mut map = PathMap::new(); - - assert_eq!(map.get("/foo"), None); - map.insert("/foo", 5); - assert_eq!(map.get("/foo"), Some(&5)); - - map.insert("/foo/bar", 6); - assert_eq!(map.get("/foo"), Some(&5)); - assert_eq!(map.get("/foo/bar"), Some(&6)); - assert_eq!(map.children("/foo"), Some(vec![Path::new("/foo/bar")])); - } - - #[test] - fn orphans() { - let mut map = PathMap::new(); - - map.insert("/foo/bar", 5); - assert_eq!(map.orphan_paths, btreeset!["/foo/bar".into()]); - - map.insert("/foo", 6); - assert_eq!(map.orphan_paths, btreeset!["/foo".into()]); - } - - #[test] - fn remove_one() { - let mut map = PathMap::new(); - - map.insert("/foo", 6); - - assert_eq!(map.remove("/foo"), vec![(PathBuf::from("/foo"), 6),]); - - assert_eq!(map.get("/foo"), None); - } - - #[test] - fn remove_child() { - let mut map = PathMap::new(); - - map.insert("/foo", 6); - map.insert("/foo/bar", 12); - - assert_eq!( - map.remove("/foo"), - vec![(PathBuf::from("/foo"), 6), (PathBuf::from("/foo/bar"), 12),] - ); - - assert_eq!(map.get("/foo"), None); - assert_eq!(map.get("/foo/bar"), None); - } - - #[test] - fn remove_descendant() { - let mut map = PathMap::new(); - - map.insert("/foo", 6); - map.insert("/foo/bar", 12); - map.insert("/foo/bar/baz", 18); - - assert_eq!( - map.remove("/foo"), - vec![ - (PathBuf::from("/foo"), 6), - (PathBuf::from("/foo/bar"), 12), - (PathBuf::from("/foo/bar/baz"), 18), - ] - ); - - assert_eq!(map.get("/foo"), None); - assert_eq!(map.get("/foo/bar"), None); - assert_eq!(map.get("/foo/bar/baz"), None); - } - - #[test] - fn remove_not_orphan_descendants() { - let mut map = PathMap::new(); - - map.insert("/foo", 6); - map.insert("/foo/bar/baz", 12); - - assert_eq!(map.remove("/foo"), vec![(PathBuf::from("/foo"), 6),]); - - assert_eq!(map.get("/foo"), None); - assert_eq!(map.get("/foo/bar/baz"), Some(&12)); - } - - // Makes sure that regardless of addition order, paths are always sorted - // when asking for children. - #[test] - fn add_order_sorted() { - let mut map = PathMap::new(); - - map.insert("/foo", 5); - map.insert("/foo/b", 2); - map.insert("/foo/d", 0); - map.insert("/foo/c", 3); - - assert_eq!( - map.children("/foo"), - Some(vec![ - Path::new("/foo/b"), - Path::new("/foo/c"), - Path::new("/foo/d"), - ]) - ); - - map.insert("/foo/a", 1); - - assert_eq!( - map.children("/foo"), - Some(vec![ - Path::new("/foo/a"), - Path::new("/foo/b"), - Path::new("/foo/c"), - Path::new("/foo/d"), - ]) - ); - } -} diff --git a/src/serve_session.rs b/src/serve_session.rs index 34f49ffa..bcaf6c14 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -6,6 +6,7 @@ use std::{ }; use crossbeam_channel::Sender; +use vfs::Vfs; use crate::{ change_processor::ChangeProcessor, @@ -14,7 +15,6 @@ use crate::{ project::Project, session_id::SessionId, snapshot::{AppliedPatchSet, PatchSet, RojoTree}, - vfs::{Vfs, VfsFetcher}, }; /// Contains all of the state for a Rojo serve session. @@ -24,7 +24,7 @@ use crate::{ /// why Rojo couldn't expose an IPC or channels-based API for embedding in the /// future. `ServeSession` would be roughly the right interface to expose for /// those cases. -pub struct ServeSession { +pub struct ServeSession { /// The object responsible for listening to changes from the in-memory /// filesystem, applying them, updating the Roblox instance tree, and /// routing messages through the session's message queue to any connected @@ -68,7 +68,7 @@ pub struct ServeSession { /// /// The main use for accessing it from the session is for debugging issues /// with Rojo's live-sync protocol. - vfs: Arc>, + vfs: Arc, /// A queue of changes that have been applied to `tree` that affect clients. /// @@ -85,14 +85,14 @@ pub struct ServeSession { /// Methods that need thread-safety bounds on VfsFetcher are limited to this /// block to prevent needing to spread Send + Sync + 'static into everything /// that handles ServeSession. -impl ServeSession { +impl ServeSession { /// Start a new serve session from the given in-memory filesystem and start /// path. /// /// The project file is expected to be loaded out-of-band since it's /// currently loaded from the filesystem directly instead of through the /// in-memory filesystem layer. - pub fn new>(vfs: Vfs, start_path: P) -> Self { + pub fn new>(vfs: Vfs, start_path: P) -> Self { let start_path = start_path.as_ref(); log::trace!("Starting new ServeSession at path {}", start_path.display(),); @@ -131,7 +131,7 @@ impl ServeSession { } } -impl ServeSession { +impl ServeSession { pub fn tree_handle(&self) -> Arc> { Arc::clone(&self.tree) } @@ -144,7 +144,7 @@ impl ServeSession { self.tree_mutation_sender.clone() } - pub fn vfs(&self) -> &Vfs { + pub fn vfs(&self) -> &Vfs { &self.vfs } @@ -189,201 +189,201 @@ mod serve_session { use std::{path::PathBuf, time::Duration}; - use insta::assert_yaml_snapshot; use maplit::hashmap; use rojo_insta_ext::RedactionMap; use tokio::{runtime::Runtime, timer::Timeout}; + use vfs::{InMemoryFs, VfsEvent, VfsSnapshot}; - use crate::{ - tree_view::view_tree, - vfs::{NoopFetcher, TestFetcher, VfsDebug, VfsEvent, VfsSnapshot}, - }; + use crate::tree_view::view_tree; #[test] fn just_folder() { - let vfs = Vfs::new(NoopFetcher); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo", VfsSnapshot::empty_dir()) + .unwrap(); - vfs.debug_load_snapshot("/foo", VfsSnapshot::empty_dir()); + let vfs = Vfs::new(imfs); let session = ServeSession::new(vfs, "/foo"); let mut rm = RedactionMap::new(); - assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); + insta::assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); } #[test] fn project_with_folder() { - let vfs = Vfs::new(NoopFetcher); - - vfs.debug_load_snapshot( + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( "/foo", VfsSnapshot::dir(hashmap! { "default.project.json" => VfsSnapshot::file(r#" - { - "name": "HelloWorld", - "tree": { - "$path": "src" + { + "name": "HelloWorld", + "tree": { + "$path": "src" + } } - } - "#), + "#), "src" => VfsSnapshot::dir(hashmap! { "hello.txt" => VfsSnapshot::file("Hello, world!"), }), }), - ); + ) + .unwrap(); + + let vfs = Vfs::new(imfs); let session = ServeSession::new(vfs, "/foo"); let mut rm = RedactionMap::new(); - assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); + insta::assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); } #[test] fn script_with_meta() { - let vfs = Vfs::new(NoopFetcher); - - vfs.debug_load_snapshot( + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( "/root", VfsSnapshot::dir(hashmap! { "test.lua" => VfsSnapshot::file("This is a test."), "test.meta.json" => VfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#), }), - ); + ) + .unwrap(); + + let vfs = Vfs::new(imfs); let session = ServeSession::new(vfs, "/root"); let mut rm = RedactionMap::new(); - assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); - } - - #[test] - fn change_script_meta() { - let (state, fetcher) = TestFetcher::new(); - - state.load_snapshot( - "/root", - VfsSnapshot::dir(hashmap! { - "test.lua" => VfsSnapshot::file("This is a test."), - "test.meta.json" => VfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#), - }), - ); - - let vfs = Vfs::new(fetcher); - let session = ServeSession::new(vfs, "/root"); - - let mut redactions = RedactionMap::new(); - assert_yaml_snapshot!( - "change_script_meta_before", - view_tree(&session.tree(), &mut redactions) - ); - - state.load_snapshot( - "/root/test.meta.json", - VfsSnapshot::file(r#"{ "ignoreUnknownInstances": false }"#), - ); - - let receiver = Timeout::new( - session.message_queue().subscribe_any(), - Duration::from_millis(200), - ); - state.raise_event(VfsEvent::Modified(PathBuf::from("/root/test.meta.json"))); - - let mut rt = Runtime::new().unwrap(); - let changes = rt.block_on(receiver).unwrap(); - - assert_yaml_snapshot!( - "change_script_meta_patch", - redactions.redacted_yaml(changes) - ); - assert_yaml_snapshot!( - "change_script_meta_after", - view_tree(&session.tree(), &mut redactions) - ); + insta::assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); } #[test] fn change_txt_file() { - let (state, fetcher) = TestFetcher::new(); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo.txt", VfsSnapshot::file("Hello!")) + .unwrap(); - state.load_snapshot("/foo.txt", VfsSnapshot::file("Hello!")); + let vfs = Vfs::new(imfs.clone()); - let vfs = Vfs::new(fetcher); let session = ServeSession::new(vfs, "/foo.txt"); - let mut redactions = RedactionMap::new(); - assert_yaml_snapshot!( + let mut rm = RedactionMap::new(); + insta::assert_yaml_snapshot!( "change_txt_file_before", - view_tree(&session.tree(), &mut redactions) + view_tree(&session.tree(), &mut rm) ); - state.load_snapshot("/foo.txt", VfsSnapshot::file("World!")); + imfs.load_snapshot("/foo.txt", VfsSnapshot::file("World!")) + .unwrap(); let receiver = session.message_queue().subscribe_any(); - state.raise_event(VfsEvent::Modified(PathBuf::from("/foo.txt"))); + imfs.raise_event(VfsEvent::Write(PathBuf::from("/foo.txt"))); let receiver = Timeout::new(receiver, Duration::from_millis(200)); let mut rt = Runtime::new().unwrap(); let result = rt.block_on(receiver).unwrap(); - assert_yaml_snapshot!("change_txt_file_patch", redactions.redacted_yaml(result)); - assert_yaml_snapshot!( - "change_txt_file_after", - view_tree(&session.tree(), &mut redactions) + insta::assert_yaml_snapshot!("change_txt_file_patch", rm.redacted_yaml(result)); + insta::assert_yaml_snapshot!("change_txt_file_after", view_tree(&session.tree(), &mut rm)); + } + + #[test] + fn change_script_meta() { + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/root", + VfsSnapshot::dir(hashmap! { + "test.lua" => VfsSnapshot::file("This is a test."), + "test.meta.json" => VfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#), + }), + ) + .unwrap(); + + let vfs = Vfs::new(imfs.clone()); + + let session = ServeSession::new(vfs, "/root"); + + let mut rm = RedactionMap::new(); + insta::assert_yaml_snapshot!( + "change_script_meta_before", + view_tree(&session.tree(), &mut rm) + ); + + imfs.load_snapshot( + "/root/test.meta.json", + VfsSnapshot::file(r#"{ "ignoreUnknownInstances": false }"#), + ) + .unwrap(); + + let receiver = session.message_queue().subscribe_any(); + + imfs.raise_event(VfsEvent::Write(PathBuf::from("/root/test.meta.json"))); + + let receiver = Timeout::new(receiver, Duration::from_millis(200)); + + let mut rt = Runtime::new().unwrap(); + let result = rt.block_on(receiver).unwrap(); + + insta::assert_yaml_snapshot!("change_script_meta_patch", rm.redacted_yaml(result)); + insta::assert_yaml_snapshot!( + "change_script_meta_after", + view_tree(&session.tree(), &mut rm) ); } #[test] fn change_file_in_project() { - let (state, fetcher) = TestFetcher::new(); - - state.load_snapshot( + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( "/foo", VfsSnapshot::dir(hashmap! { "default.project.json" => VfsSnapshot::file(r#" - { - "name": "change_file_in_project", - "tree": { - "$className": "Folder", + { + "name": "change_file_in_project", + "tree": { + "$className": "Folder", - "Child": { - "$path": "file.txt" + "Child": { + "$path": "file.txt" + } } } - } - "#), + "#), "file.txt" => VfsSnapshot::file("initial content"), }), - ); + ) + .unwrap(); + + let vfs = Vfs::new(imfs.clone()); - let vfs = Vfs::new(fetcher); let session = ServeSession::new(vfs, "/foo"); - let mut redactions = RedactionMap::new(); - assert_yaml_snapshot!( + let mut rm = RedactionMap::new(); + insta::assert_yaml_snapshot!( "change_file_in_project_before", - view_tree(&session.tree(), &mut redactions) + view_tree(&session.tree(), &mut rm) ); - state.load_snapshot("/foo/file.txt", VfsSnapshot::file("Changed!")); + imfs.load_snapshot("/foo/file.txt", VfsSnapshot::file("Changed!")) + .unwrap(); let receiver = session.message_queue().subscribe_any(); - state.raise_event(VfsEvent::Modified(PathBuf::from("/foo/file.txt"))); + imfs.raise_event(VfsEvent::Write(PathBuf::from("/foo/file.txt"))); let receiver = Timeout::new(receiver, Duration::from_millis(200)); let mut rt = Runtime::new().unwrap(); let result = rt.block_on(receiver).unwrap(); - assert_yaml_snapshot!( - "change_file_in_project_patch", - redactions.redacted_yaml(result) - ); - assert_yaml_snapshot!( + insta::assert_yaml_snapshot!("change_file_in_project_patch", rm.redacted_yaml(result)); + insta::assert_yaml_snapshot!( "change_file_in_project_after", - view_tree(&session.tree(), &mut redactions) + view_tree(&session.tree(), &mut rm) ); } } diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 5ba626ee..93882e22 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -1,13 +1,11 @@ -use std::collections::BTreeMap; +use std::{collections::BTreeMap, path::Path}; use maplit::hashmap; use rbx_dom_weak::RbxValue; use serde::Serialize; +use vfs::{IoResultExt, Vfs}; -use crate::{ - snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, - vfs::{FsResultExt, Vfs, VfsEntry, VfsFetcher}, -}; +use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ meta_file::AdjacentMetadata, @@ -18,25 +16,21 @@ use super::{ pub struct SnapshotCsv; impl SnapshotMiddleware for SnapshotCsv { - fn from_vfs( - _context: &InstanceContext, - vfs: &Vfs, - entry: &VfsEntry, - ) -> SnapshotInstanceResult { - if entry.is_directory() { + fn from_vfs(_context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { + let meta = vfs.metadata(path)?; + + if meta.is_dir() { return Ok(None); } - let instance_name = match match_file_name(entry.path(), ".csv") { + let instance_name = match match_file_name(path, ".csv") { Some(name) => name, None => return Ok(None), }; - let meta_path = entry - .path() - .with_file_name(format!("{}.meta.json", instance_name)); + let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); - let table_contents = convert_localization_csv(&entry.contents(vfs)?); + let table_contents = convert_localization_csv(&vfs.read(path)?); let mut snapshot = InstanceSnapshot::new() .name(instance_name) @@ -48,12 +42,11 @@ impl SnapshotMiddleware for SnapshotCsv { }) .metadata( InstanceMetadata::new() - .instigating_source(entry.path()) - .relevant_paths(vec![entry.path().to_path_buf(), meta_path.clone()]), + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf(), meta_path.clone()]), ); - if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { - let meta_contents = meta_entry.contents(vfs)?; + if let Some(meta_contents) = vfs.read(meta_path).with_not_found()? { let mut metadata = AdjacentMetadata::from_slice(&meta_contents); metadata.apply_all(&mut snapshot); } @@ -138,7 +131,7 @@ fn convert_localization_csv(contents: &[u8]) -> String { serde_json::to_string(&entries).expect("Could not encode JSON for localization table") } -#[cfg(test)] +#[cfg(all(test, feature = "FIXME"))] mod test { use super::*; diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 67c781b2..22d1ed64 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -1,32 +1,27 @@ -use std::collections::HashMap; +use std::path::Path; -use rbx_dom_weak::{RbxId, RbxTree}; +use vfs::{DirEntry, IoResultExt, Vfs}; -use crate::{ - snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, - vfs::{DirectorySnapshot, FsResultExt, Vfs, VfsEntry, VfsFetcher, VfsSnapshot}, -}; +use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ error::SnapshotError, meta_file::DirectoryMetadata, - middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, - snapshot_from_instance, snapshot_from_vfs, + middleware::{SnapshotInstanceResult, SnapshotMiddleware}, + snapshot_from_vfs, }; pub struct SnapshotDir; impl SnapshotMiddleware for SnapshotDir { - fn from_vfs( - context: &InstanceContext, - vfs: &Vfs, - entry: &VfsEntry, - ) -> SnapshotInstanceResult { - if entry.is_file() { + fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { + let meta = vfs.metadata(path)?; + + if meta.is_file() { return Ok(None); } - let passes_filter_rules = |child: &VfsEntry| { + let passes_filter_rules = |child: &DirEntry| { context .path_ignore_rules .iter() @@ -35,31 +30,36 @@ impl SnapshotMiddleware for SnapshotDir { let mut snapshot_children = Vec::new(); - for child in entry.children(vfs)?.into_iter().filter(passes_filter_rules) { - if let Some(child_snapshot) = snapshot_from_vfs(context, vfs, &child)? { + for entry in vfs.read_dir(path)? { + let entry = entry?; + + if !passes_filter_rules(&entry) { + continue; + } + + if let Some(child_snapshot) = snapshot_from_vfs(context, vfs, entry.path())? { snapshot_children.push(child_snapshot); } } - let instance_name = entry - .path() + let instance_name = path .file_name() .expect("Could not extract file name") .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(entry.path()))? + .ok_or_else(|| SnapshotError::file_name_bad_unicode(path))? .to_string(); - let meta_path = entry.path().join("init.meta.json"); + let meta_path = path.join("init.meta.json"); let relevant_paths = vec![ - entry.path().to_path_buf(), + path.to_path_buf(), meta_path.clone(), // TODO: We shouldn't need to know about Lua existing in this // middleware. Should we figure out a way for that function to add // relevant paths to this middleware? - entry.path().join("init.lua"), - entry.path().join("init.server.lua"), - entry.path().join("init.client.lua"), + path.join("init.lua"), + path.join("init.server.lua"), + path.join("init.client.lua"), ]; let mut snapshot = InstanceSnapshot::new() @@ -68,81 +68,61 @@ impl SnapshotMiddleware for SnapshotDir { .children(snapshot_children) .metadata( InstanceMetadata::new() - .instigating_source(entry.path()) + .instigating_source(path) .relevant_paths(relevant_paths) .context(context), ); - if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { - let meta_contents = meta_entry.contents(vfs)?; + if let Some(meta_contents) = vfs.read(meta_path).with_not_found()? { let mut metadata = DirectoryMetadata::from_slice(&meta_contents); metadata.apply_all(&mut snapshot); } Ok(Some(snapshot)) } - - fn from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult { - let instance = tree.get_instance(id).unwrap(); - - if instance.class_name != "Folder" { - return None; - } - - let mut children = HashMap::new(); - - for child_id in instance.get_children_ids() { - if let Some((name, child)) = snapshot_from_instance(tree, *child_id) { - children.insert(name, child); - } - } - - let snapshot = VfsSnapshot::Directory(DirectorySnapshot { children }); - - Some((instance.name.clone(), snapshot)) - } } #[cfg(test)] mod test { use super::*; - use insta::assert_yaml_snapshot; use maplit::hashmap; - - use crate::vfs::{NoopFetcher, VfsDebug}; + use vfs::{InMemoryFs, VfsSnapshot}; #[test] fn empty_folder() { - let mut vfs = Vfs::new(NoopFetcher); - let dir = VfsSnapshot::dir::(HashMap::new()); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo", VfsSnapshot::empty_dir()) + .unwrap(); - vfs.debug_load_snapshot("/foo", dir); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotDir::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotDir::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) .unwrap() .unwrap(); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn folder_in_folder() { - let mut vfs = Vfs::new(NoopFetcher); - let dir = VfsSnapshot::dir(hashmap! { - "Child" => VfsSnapshot::dir::(HashMap::new()), - }); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo", + VfsSnapshot::dir(hashmap! { + "Child" => VfsSnapshot::empty_dir(), + }), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo", dir); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotDir::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotDir::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) .unwrap() .unwrap(); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } } diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs index b81f5b5f..94de47ea 100644 --- a/src/snapshot_middleware/error.rs +++ b/src/snapshot_middleware/error.rs @@ -1,7 +1,5 @@ use std::{error::Error, fmt, io, path::PathBuf}; -use crate::vfs::FsError; - #[derive(Debug)] pub struct SnapshotError { detail: SnapshotErrorDetail, @@ -73,11 +71,9 @@ impl fmt::Display for SnapshotError { } } -impl From for SnapshotError { - fn from(error: FsError) -> Self { - let (inner, path) = error.into_raw(); - - Self::new(inner.into(), Some(path)) +impl From for SnapshotError { + fn from(inner: io::Error) -> Self { + Self::new(inner.into(), Option::::None) } } diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index bff856ed..2f9ca5e8 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -1,13 +1,11 @@ -use std::{borrow::Cow, collections::HashMap}; +use std::{borrow::Cow, collections::HashMap, path::Path}; use rbx_dom_weak::UnresolvedRbxValue; use rbx_reflection::try_resolve_value; use serde::Deserialize; +use vfs::Vfs; -use crate::{ - snapshot::{InstanceContext, InstanceSnapshot}, - vfs::{Vfs, VfsEntry, VfsFetcher}, -}; +use crate::snapshot::{InstanceContext, InstanceSnapshot}; use super::{ middleware::{SnapshotInstanceResult, SnapshotMiddleware}, @@ -17,28 +15,26 @@ use super::{ pub struct SnapshotJsonModel; impl SnapshotMiddleware for SnapshotJsonModel { - fn from_vfs( - context: &InstanceContext, - vfs: &Vfs, - entry: &VfsEntry, - ) -> SnapshotInstanceResult { - if entry.is_directory() { + fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { + let meta = vfs.metadata(path)?; + + if meta.is_dir() { return Ok(None); } - let instance_name = match match_file_name(entry.path(), ".model.json") { + let instance_name = match match_file_name(path, ".model.json") { Some(name) => name, None => return Ok(None), }; let instance: JsonModel = - serde_json::from_slice(&entry.contents(vfs)?).expect("TODO: Handle serde_json errors"); + serde_json::from_slice(&vfs.read(path)?).expect("TODO: Handle serde_json errors"); if let Some(json_name) = &instance.name { if json_name != instance_name { log::warn!( "Name from JSON model did not match its file name: {}", - entry.path().display() + path.display() ); log::warn!( "In Rojo < alpha 14, this model is named \"{}\" (from its 'Name' property)", @@ -56,8 +52,8 @@ impl SnapshotMiddleware for SnapshotJsonModel { snapshot.metadata = snapshot .metadata - .instigating_source(entry.path()) - .relevant_paths(vec![entry.path().to_path_buf()]) + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf()]) .context(context); Ok(Some(snapshot)) @@ -137,39 +133,43 @@ impl JsonModelCore { mod test { use super::*; - use insta::assert_yaml_snapshot; - - use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot}; + use vfs::{InMemoryFs, VfsSnapshot}; #[test] fn model_from_vfs() { - let mut vfs = Vfs::new(NoopFetcher); - let file = VfsSnapshot::file( - r#" - { - "Name": "children", - "ClassName": "IntValue", - "Properties": { - "Value": 5 - }, - "Children": [ - { - "Name": "The Child", - "ClassName": "StringValue" - } - ] - } - "#, - ); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo.model.json", + VfsSnapshot::file( + r#" + { + "Name": "children", + "ClassName": "IntValue", + "Properties": { + "Value": 5 + }, + "Children": [ + { + "Name": "The Child", + "ClassName": "StringValue" + } + ] + } + "#, + ), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo.model.json", file); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo.model.json").unwrap(); - let instance_snapshot = - SnapshotJsonModel::from_vfs(&InstanceContext::default(), &mut vfs, &entry) - .unwrap() - .unwrap(); + let instance_snapshot = SnapshotJsonModel::from_vfs( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.model.json"), + ) + .unwrap() + .unwrap(); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } } diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index c8ac072d..fba6b04b 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -1,12 +1,10 @@ -use std::str; +use std::{path::Path, str}; use maplit::hashmap; use rbx_dom_weak::RbxValue; +use vfs::{IoResultExt, Vfs}; -use crate::{ - snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, - vfs::{FsResultExt, Vfs, VfsEntry, VfsFetcher}, -}; +use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ dir::SnapshotDir, @@ -18,12 +16,8 @@ use super::{ pub struct SnapshotLua; impl SnapshotMiddleware for SnapshotLua { - fn from_vfs( - context: &InstanceContext, - vfs: &Vfs, - entry: &VfsEntry, - ) -> SnapshotInstanceResult { - let file_name = entry.path().file_name().unwrap().to_string_lossy(); + fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { + let file_name = path.file_name().unwrap().to_string_lossy(); // These paths alter their parent instance, so we don't need to turn // them into a script instance here. @@ -32,18 +26,20 @@ impl SnapshotMiddleware for SnapshotLua { _ => {} } - if entry.is_file() { - snapshot_lua_file(context, vfs, entry) + let meta = vfs.metadata(path)?; + + if meta.is_file() { + snapshot_lua_file(context, vfs, path) } else { // At this point, our entry is definitely a directory! - if let Some(snapshot) = snapshot_init(context, vfs, entry, "init.lua")? { + if let Some(snapshot) = snapshot_init(context, vfs, path, "init.lua")? { // An `init.lua` file turns its parent into a ModuleScript Ok(Some(snapshot)) - } else if let Some(snapshot) = snapshot_init(context, vfs, entry, "init.server.lua")? { + } else if let Some(snapshot) = snapshot_init(context, vfs, path, "init.server.lua")? { // An `init.server.lua` file turns its parent into a Script Ok(Some(snapshot)) - } else if let Some(snapshot) = snapshot_init(context, vfs, entry, "init.client.lua")? { + } else if let Some(snapshot) = snapshot_init(context, vfs, path, "init.client.lua")? { // An `init.client.lua` file turns its parent into a LocalScript Ok(Some(snapshot)) } else { @@ -54,12 +50,8 @@ impl SnapshotMiddleware for SnapshotLua { } /// Core routine for turning Lua files into snapshots. -fn snapshot_lua_file( - context: &InstanceContext, - vfs: &Vfs, - entry: &VfsEntry, -) -> SnapshotInstanceResult { - let file_name = entry.path().file_name().unwrap().to_string_lossy(); +fn snapshot_lua_file(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { + let file_name = path.file_name().unwrap().to_string_lossy(); let (class_name, instance_name) = if let Some(name) = match_trailing(&file_name, ".server.lua") { @@ -72,15 +64,13 @@ fn snapshot_lua_file( return Ok(None); }; - let contents = entry.contents(vfs)?; + let contents = vfs.read(path)?; let contents_str = str::from_utf8(&contents) // TODO: Turn into error type .expect("File content was not valid UTF-8") .to_string(); - let meta_path = entry - .path() - .with_file_name(format!("{}.meta.json", instance_name)); + let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); let mut snapshot = InstanceSnapshot::new() .name(instance_name) @@ -92,13 +82,12 @@ fn snapshot_lua_file( }) .metadata( InstanceMetadata::new() - .instigating_source(entry.path()) - .relevant_paths(vec![entry.path().to_path_buf(), meta_path.clone()]) + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf(), meta_path.clone()]) .context(context), ); - if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { - let meta_contents = meta_entry.contents(vfs)?; + if let Some(meta_contents) = vfs.read(meta_path).with_not_found()? { let mut metadata = AdjacentMetadata::from_slice(&meta_contents); metadata.apply_all(&mut snapshot); } @@ -111,17 +100,17 @@ fn snapshot_lua_file( /// /// Scripts named `init.lua`, `init.server.lua`, or `init.client.lua` usurp /// their parents, which acts similarly to `__init__.py` from the Python world. -fn snapshot_init( +fn snapshot_init( context: &InstanceContext, - vfs: &Vfs, - folder_entry: &VfsEntry, + vfs: &Vfs, + folder_path: &Path, init_name: &str, ) -> SnapshotInstanceResult { - let init_path = folder_entry.path().join(init_name); + let init_path = folder_path.join(init_name); - if let Some(init_entry) = vfs.get(init_path).with_not_found()? { - if let Some(dir_snapshot) = SnapshotDir::from_vfs(context, vfs, folder_entry)? { - if let Some(mut init_snapshot) = snapshot_lua_file(context, vfs, &init_entry)? { + if vfs.metadata(&init_path).with_not_found()?.is_some() { + if let Some(dir_snapshot) = SnapshotDir::from_vfs(context, vfs, folder_path)? { + if let Some(mut init_snapshot) = snapshot_lua_file(context, vfs, &init_path)? { if dir_snapshot.class_name != "Folder" { panic!( "init.lua, init.server.lua, and init.client.lua can \ @@ -146,149 +135,171 @@ fn snapshot_init( mod test { use super::*; - use insta::{assert_yaml_snapshot, with_settings}; - - use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot}; + use vfs::{InMemoryFs, VfsSnapshot}; #[test] fn module_from_vfs() { - let mut vfs = Vfs::new(NoopFetcher); - let file = VfsSnapshot::file("Hello there!"); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo.lua", VfsSnapshot::file("Hello there!")) + .unwrap(); - vfs.debug_load_snapshot("/foo.lua", file); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo.lua")) .unwrap() .unwrap(); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn server_from_vfs() { - let mut vfs = Vfs::new(NoopFetcher); - let file = VfsSnapshot::file("Hello there!"); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo.server.lua", VfsSnapshot::file("Hello there!")) + .unwrap(); - vfs.debug_load_snapshot("/foo.server.lua", file); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo.server.lua").unwrap(); - let instance_snapshot = - SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) - .unwrap() - .unwrap(); + let instance_snapshot = SnapshotLua::from_vfs( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.server.lua"), + ) + .unwrap() + .unwrap(); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn client_from_vfs() { - let mut vfs = Vfs::new(NoopFetcher); - let file = VfsSnapshot::file("Hello there!"); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo.client.lua", VfsSnapshot::file("Hello there!")) + .unwrap(); - vfs.debug_load_snapshot("/foo.client.lua", file); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo.client.lua").unwrap(); - let instance_snapshot = - SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) - .unwrap() - .unwrap(); + let instance_snapshot = SnapshotLua::from_vfs( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.client.lua"), + ) + .unwrap() + .unwrap(); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn init_module_from_vfs() { - let mut vfs = Vfs::new(NoopFetcher); - let dir = VfsSnapshot::dir(hashmap! { - "init.lua" => VfsSnapshot::file("Hello!"), - }); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/root", + VfsSnapshot::dir(hashmap! { + "init.lua" => VfsSnapshot::file("Hello!"), + }), + ) + .unwrap(); - vfs.debug_load_snapshot("/root", dir); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/root").unwrap(); let instance_snapshot = - SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/root")) .unwrap() .unwrap(); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn module_with_meta() { - let mut vfs = Vfs::new(NoopFetcher); - let file = VfsSnapshot::file("Hello there!"); - let meta = VfsSnapshot::file( - r#" - { - "ignoreUnknownInstances": true - } - "#, - ); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo.lua", VfsSnapshot::file("Hello there!")) + .unwrap(); + imfs.load_snapshot( + "/foo.meta.json", + VfsSnapshot::file( + r#" + { + "ignoreUnknownInstances": true + } + "#, + ), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo.lua", file); - vfs.debug_load_snapshot("/foo.meta.json", meta); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo.lua").unwrap(); let instance_snapshot = - SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo.lua")) .unwrap() .unwrap(); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn script_with_meta() { - let mut vfs = Vfs::new(NoopFetcher); - let file = VfsSnapshot::file("Hello there!"); - let meta = VfsSnapshot::file( - r#" - { - "ignoreUnknownInstances": true - } - "#, - ); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo.server.lua", VfsSnapshot::file("Hello there!")) + .unwrap(); + imfs.load_snapshot( + "/foo.meta.json", + VfsSnapshot::file( + r#" + { + "ignoreUnknownInstances": true + } + "#, + ), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo.server.lua", file); - vfs.debug_load_snapshot("/foo.meta.json", meta); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo.server.lua").unwrap(); - let instance_snapshot = - SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) - .unwrap() - .unwrap(); + let instance_snapshot = SnapshotLua::from_vfs( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.server.lua"), + ) + .unwrap() + .unwrap(); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn script_disabled() { - let mut vfs = Vfs::new(NoopFetcher); - let file = VfsSnapshot::file("Hello there!"); - let meta = VfsSnapshot::file( - r#" - { - "properties": { - "Disabled": true - } - } - "#, - ); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/bar.server.lua", VfsSnapshot::file("Hello there!")) + .unwrap(); + imfs.load_snapshot( + "/bar.meta.json", + VfsSnapshot::file( + r#" + { + "properties": { + "Disabled": true + } + } + "#, + ), + ) + .unwrap(); - vfs.debug_load_snapshot("/bar.server.lua", file); - vfs.debug_load_snapshot("/bar.meta.json", meta); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/bar.server.lua").unwrap(); - let instance_snapshot = - SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, &entry) - .unwrap() - .unwrap(); + let instance_snapshot = SnapshotLua::from_vfs( + &InstanceContext::default(), + &mut vfs, + Path::new("/bar.server.lua"), + ) + .unwrap() + .unwrap(); - with_settings!({ sort_maps => true }, { - assert_yaml_snapshot!(instance_snapshot); + insta::with_settings!({ sort_maps => true }, { + insta::assert_yaml_snapshot!(instance_snapshot); }); } } diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index da0fbc44..baf28de2 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -1,23 +1,13 @@ -use rbx_dom_weak::{RbxId, RbxTree}; +use std::path::Path; -use crate::{ - snapshot::{InstanceContext, InstanceSnapshot}, - vfs::{Vfs, VfsEntry, VfsFetcher, VfsSnapshot}, -}; +use vfs::Vfs; + +use crate::snapshot::{InstanceContext, InstanceSnapshot}; use super::error::SnapshotError; pub type SnapshotInstanceResult = Result, SnapshotError>; -pub type SnapshotFileResult = Option<(String, VfsSnapshot)>; pub trait SnapshotMiddleware { - fn from_vfs( - context: &InstanceContext, - vfs: &Vfs, - entry: &VfsEntry, - ) -> SnapshotInstanceResult; - - fn from_instance(_tree: &RbxTree, _id: RbxId) -> SnapshotFileResult { - None - } + fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult; } diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index ea0030ed..24e3611e 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -15,46 +15,37 @@ mod rbxlx; mod rbxm; mod rbxmx; mod txt; -mod user_plugins; mod util; pub use self::error::*; -use rbx_dom_weak::{RbxId, RbxTree}; +use std::path::Path; +use vfs::Vfs; + +use self::middleware::{SnapshotInstanceResult, SnapshotMiddleware}; use self::{ - csv::SnapshotCsv, - dir::SnapshotDir, - json_model::SnapshotJsonModel, - lua::SnapshotLua, - middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, - project::SnapshotProject, - rbxlx::SnapshotRbxlx, - rbxm::SnapshotRbxm, - rbxmx::SnapshotRbxmx, + csv::SnapshotCsv, dir::SnapshotDir, json_model::SnapshotJsonModel, lua::SnapshotLua, + project::SnapshotProject, rbxlx::SnapshotRbxlx, rbxm::SnapshotRbxm, rbxmx::SnapshotRbxmx, txt::SnapshotTxt, - user_plugins::SnapshotUserPlugins, -}; -use crate::{ - snapshot::InstanceContext, - vfs::{Vfs, VfsEntry, VfsFetcher}, }; +use crate::snapshot::InstanceContext; pub use self::project::snapshot_project_node; macro_rules! middlewares { ( $($middleware: ident,)* ) => { - /// Generates a snapshot of instances from the given VfsEntry. - pub fn snapshot_from_vfs( + /// Generates a snapshot of instances from the given path. + pub fn snapshot_from_vfs( context: &InstanceContext, - vfs: &Vfs, - entry: &VfsEntry, + vfs: &Vfs, + path: &Path, ) -> SnapshotInstanceResult { $( - log::trace!("trying middleware {} on {}", stringify!($middleware), entry.path().display()); + log::trace!("trying middleware {} on {}", stringify!($middleware), path.display()); - if let Some(snapshot) = $middleware::from_vfs(context, vfs, entry)? { - log::trace!("middleware {} success on {}", stringify!($middleware), entry.path().display()); + if let Some(snapshot) = $middleware::from_vfs(context, vfs, path)? { + log::trace!("middleware {} success on {}", stringify!($middleware), path.display()); return Ok(Some(snapshot)); } )* @@ -62,24 +53,11 @@ macro_rules! middlewares { log::trace!("no middleware returned Ok(Some)"); Ok(None) } - - /// Generates an in-memory filesystem snapshot of the given Roblox - /// instance. - pub fn snapshot_from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult { - $( - if let Some(result) = $middleware::from_instance(tree, id) { - return Some(result); - } - )* - - None - } }; } middlewares! { SnapshotProject, - SnapshotUserPlugins, SnapshotJsonModel, SnapshotRbxlx, SnapshotRbxmx, diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 25282dc2..ad16aede 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -1,13 +1,13 @@ use std::{borrow::Cow, collections::HashMap, path::Path}; use rbx_reflection::try_resolve_value; +use vfs::{IoResultExt, Vfs}; use crate::{ project::{Project, ProjectNode}, snapshot::{ InstanceContext, InstanceMetadata, InstanceSnapshot, InstigatingSource, PathIgnoreRule, }, - vfs::{FsResultExt, Vfs, VfsEntry, VfsFetcher}, }; use super::{ @@ -22,30 +22,28 @@ use super::{ pub struct SnapshotProject; impl SnapshotMiddleware for SnapshotProject { - fn from_vfs( - context: &InstanceContext, - vfs: &Vfs, - entry: &VfsEntry, - ) -> SnapshotInstanceResult { - if entry.is_directory() { - let project_path = entry.path().join("default.project.json"); + fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { + let meta = vfs.metadata(path)?; - match vfs.get(project_path).with_not_found()? { + if meta.is_dir() { + let project_path = path.join("default.project.json"); + + match vfs.metadata(&project_path).with_not_found()? { // TODO: Do we need to muck with the relevant paths if we're a // project file within a folder? Should the folder path be the // relevant path instead of the project file path? - Some(entry) => return SnapshotProject::from_vfs(context, vfs, &entry), + Some(_meta) => return SnapshotProject::from_vfs(context, vfs, &project_path), None => return Ok(None), } } - if !entry.path().to_string_lossy().ends_with(".project.json") { + if !path.to_string_lossy().ends_with(".project.json") { // This isn't a project file, so it's not our job. return Ok(None); } - let project = Project::load_from_slice(&entry.contents(vfs)?, entry.path()) - .map_err(|err| SnapshotError::malformed_project(err, entry.path()))?; + let project = Project::load_from_slice(&vfs.read(path)?, path) + .map_err(|err| SnapshotError::malformed_project(err, path))?; let mut context = context.clone(); @@ -75,7 +73,7 @@ impl SnapshotMiddleware for SnapshotProject { // relevant path -> snapshot path mapping per instance, we pick the more // conservative approach of snapshotting the project file if any // relevant paths changed. - snapshot.metadata.instigating_source = Some(entry.path().to_path_buf().into()); + snapshot.metadata.instigating_source = Some(path.to_path_buf().into()); // Mark this snapshot (the root node of the project file) as being // related to the project file. @@ -83,21 +81,18 @@ impl SnapshotMiddleware for SnapshotProject { // We SHOULD NOT mark the project file as a relevant path for any // nodes that aren't roots. They'll be updated as part of the project // file being updated. - snapshot - .metadata - .relevant_paths - .push(entry.path().to_path_buf()); + snapshot.metadata.relevant_paths.push(path.to_path_buf()); Ok(Some(snapshot)) } } -pub fn snapshot_project_node( +pub fn snapshot_project_node( context: &InstanceContext, project_folder: &Path, instance_name: &str, node: &ProjectNode, - vfs: &Vfs, + vfs: &Vfs, ) -> SnapshotInstanceResult { let name = Cow::Owned(instance_name.to_owned()); let mut class_name = node @@ -117,9 +112,7 @@ pub fn snapshot_project_node( Cow::Borrowed(path) }; - let entry = vfs.get(path.as_path())?; - - if let Some(snapshot) = snapshot_from_vfs(context, vfs, &entry)? { + if let Some(snapshot) = snapshot_from_vfs(context, vfs, &path)? { // If a class name was already specified, then it'll override the // class name of this snapshot ONLY if it's a Folder. // @@ -217,259 +210,284 @@ pub fn snapshot_project_node( mod test { use super::*; - use insta::assert_yaml_snapshot; use maplit::hashmap; - - use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot}; + use vfs::{InMemoryFs, VfsSnapshot}; #[test] fn project_from_folder() { let _ = env_logger::try_init(); - let mut vfs = Vfs::new(NoopFetcher); - let dir = VfsSnapshot::dir(hashmap! { - "default.project.json" => VfsSnapshot::file(r#" - { - "name": "indirect-project", - "tree": { - "$className": "Folder" + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo", + VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" + { + "name": "indirect-project", + "tree": { + "$className": "Folder" + } } - } - "#), - }); + "#), + }), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo", dir); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) .expect("snapshot error") .expect("snapshot returned no instances"); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn project_from_direct_file() { let _ = env_logger::try_init(); - let mut vfs = Vfs::new(NoopFetcher); - let dir = VfsSnapshot::dir(hashmap! { - "hello.project.json" => VfsSnapshot::file(r#" - { - "name": "direct-project", - "tree": { - "$className": "Model" + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo", + VfsSnapshot::dir(hashmap! { + "hello.project.json" => VfsSnapshot::file(r#" + { + "name": "direct-project", + "tree": { + "$className": "Model" + } } - } - "#), - }); + "#), + }), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo", dir); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo/hello.project.json").unwrap(); - let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = SnapshotProject::from_vfs( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo/hello.project.json"), + ) + .expect("snapshot error") + .expect("snapshot returned no instances"); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn project_with_resolved_properties() { let _ = env_logger::try_init(); - let mut vfs = Vfs::new(NoopFetcher); - let dir = VfsSnapshot::dir(hashmap! { - "default.project.json" => VfsSnapshot::file(r#" - { - "name": "resolved-properties", - "tree": { - "$className": "StringValue", - "$properties": { - "Value": { - "Type": "String", - "Value": "Hello, world!" + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo", + VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" + { + "name": "resolved-properties", + "tree": { + "$className": "StringValue", + "$properties": { + "Value": { + "Type": "String", + "Value": "Hello, world!" + } } } } - } - "#), - }); + "#), + }), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo", dir); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) .expect("snapshot error") .expect("snapshot returned no instances"); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn project_with_unresolved_properties() { let _ = env_logger::try_init(); - let mut vfs = Vfs::new(NoopFetcher); - let dir = VfsSnapshot::dir(hashmap! { - "default.project.json" => VfsSnapshot::file(r#" - { - "name": "unresolved-properties", - "tree": { - "$className": "StringValue", - "$properties": { - "Value": "Hi!" + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo", + VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" + { + "name": "unresolved-properties", + "tree": { + "$className": "StringValue", + "$properties": { + "Value": "Hi!" + } } } - } - "#), - }); + "#), + }), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo", dir); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) .expect("snapshot error") .expect("snapshot returned no instances"); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn project_with_children() { let _ = env_logger::try_init(); - let mut vfs = Vfs::new(NoopFetcher); - let dir = VfsSnapshot::dir(hashmap! { - "default.project.json" => VfsSnapshot::file(r#" - { - "name": "children", - "tree": { - "$className": "Folder", + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo", + VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" + { + "name": "children", + "tree": { + "$className": "Folder", - "Child": { - "$className": "Model" + "Child": { + "$className": "Model" + } } } - } - "#), - }); + "#), + }), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo", dir); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) .expect("snapshot error") .expect("snapshot returned no instances"); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn project_with_path_to_txt() { let _ = env_logger::try_init(); - let mut vfs = Vfs::new(NoopFetcher); - let dir = VfsSnapshot::dir(hashmap! { - "default.project.json" => VfsSnapshot::file(r#" - { - "name": "path-project", - "tree": { - "$path": "other.txt" + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo", + VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" + { + "name": "path-project", + "tree": { + "$path": "other.txt" + } } - } - "#), - "other.txt" => VfsSnapshot::file("Hello, world!"), - }); + "#), + "other.txt" => VfsSnapshot::file("Hello, world!"), + }), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo", dir); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) .expect("snapshot error") .expect("snapshot returned no instances"); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn project_with_path_to_project() { let _ = env_logger::try_init(); - let mut vfs = Vfs::new(NoopFetcher); - let dir = VfsSnapshot::dir(hashmap! { - "default.project.json" => VfsSnapshot::file(r#" - { - "name": "path-project", - "tree": { - "$path": "other.project.json" + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo", + VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" + { + "name": "path-project", + "tree": { + "$path": "other.project.json" + } } - } - "#), - "other.project.json" => VfsSnapshot::file(r#" - { - "name": "other-project", - "tree": { - "$className": "Model" + "#), + "other.project.json" => VfsSnapshot::file(r#" + { + "name": "other-project", + "tree": { + "$className": "Model" + } } - } - "#), - }); + "#), + }), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo", dir); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) .expect("snapshot error") .expect("snapshot returned no instances"); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn project_with_path_to_project_with_children() { let _ = env_logger::try_init(); - let mut vfs = Vfs::new(NoopFetcher); - let dir = VfsSnapshot::dir(hashmap! { - "default.project.json" => VfsSnapshot::file(r#" - { - "name": "path-child-project", - "tree": { - "$path": "other.project.json" - } - } - "#), - "other.project.json" => VfsSnapshot::file(r#" - { - "name": "other-project", - "tree": { - "$className": "Folder", - - "SomeChild": { - "$className": "Model" + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo", + VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" + { + "name": "path-child-project", + "tree": { + "$path": "other.project.json" } } - } - "#), - }); + "#), + "other.project.json" => VfsSnapshot::file(r#" + { + "name": "other-project", + "tree": { + "$className": "Folder", - vfs.debug_load_snapshot("/foo", dir); + "SomeChild": { + "$className": "Model" + } + } + } + "#), + }), + ) + .unwrap(); + + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) .expect("snapshot error") .expect("snapshot returned no instances"); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } /// Ensures that if a property is defined both in the resulting instance @@ -479,40 +497,43 @@ mod test { fn project_path_property_overrides() { let _ = env_logger::try_init(); - let mut vfs = Vfs::new(NoopFetcher); - let dir = VfsSnapshot::dir(hashmap! { - "default.project.json" => VfsSnapshot::file(r#" - { - "name": "path-property-override", - "tree": { - "$path": "other.project.json", - "$properties": { - "Value": "Changed" + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo", + VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" + { + "name": "path-property-override", + "tree": { + "$path": "other.project.json", + "$properties": { + "Value": "Changed" + } } } - } - "#), - "other.project.json" => VfsSnapshot::file(r#" - { - "name": "other-project", - "tree": { - "$className": "StringValue", - "$properties": { - "Value": "Original" + "#), + "other.project.json" => VfsSnapshot::file(r#" + { + "name": "other-project", + "tree": { + "$className": "StringValue", + "$properties": { + "Value": "Original" + } } } - } - "#), - }); + "#), + }), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo", dir); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo").unwrap(); let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) .expect("snapshot error") .expect("snapshot returned no instances"); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } } diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index 0f7df5b1..16c7f4ea 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -1,7 +1,8 @@ -use crate::{ - snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, - vfs::{Vfs, VfsEntry, VfsFetcher}, -}; +use std::path::Path; + +use vfs::Vfs; + +use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ middleware::{SnapshotInstanceResult, SnapshotMiddleware}, @@ -11,16 +12,14 @@ use super::{ pub struct SnapshotRbxlx; impl SnapshotMiddleware for SnapshotRbxlx { - fn from_vfs( - context: &InstanceContext, - vfs: &Vfs, - entry: &VfsEntry, - ) -> SnapshotInstanceResult { - if entry.is_directory() { + fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { + let meta = vfs.metadata(path)?; + + if meta.is_dir() { return Ok(None); } - let instance_name = match match_file_name(entry.path(), ".rbxlx") { + let instance_name = match match_file_name(path, ".rbxlx") { Some(name) => name, None => return Ok(None), }; @@ -28,7 +27,7 @@ impl SnapshotMiddleware for SnapshotRbxlx { let options = rbx_xml::DecodeOptions::new() .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); - let temp_tree = rbx_xml::from_reader(entry.contents(vfs)?.as_slice(), options) + let temp_tree = rbx_xml::from_reader(vfs.read(path)?.as_slice(), options) .expect("TODO: Handle rbx_xml errors"); let root_id = temp_tree.get_root_id(); @@ -37,8 +36,8 @@ impl SnapshotMiddleware for SnapshotRbxlx { .name(instance_name) .metadata( InstanceMetadata::new() - .instigating_source(entry.path()) - .relevant_paths(vec![entry.path().to_path_buf()]) + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf()]) .context(context), ); diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 14f4c11c..f14afdfd 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -1,11 +1,9 @@ -use std::collections::HashMap; +use std::{collections::HashMap, path::Path}; use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; +use vfs::Vfs; -use crate::{ - snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, - vfs::{Vfs, VfsEntry, VfsFetcher}, -}; +use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ middleware::{SnapshotInstanceResult, SnapshotMiddleware}, @@ -15,16 +13,14 @@ use super::{ pub struct SnapshotRbxm; impl SnapshotMiddleware for SnapshotRbxm { - fn from_vfs( - context: &InstanceContext, - vfs: &Vfs, - entry: &VfsEntry, - ) -> SnapshotInstanceResult { - if entry.is_directory() { + fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { + let meta = vfs.metadata(path)?; + + if meta.is_dir() { return Ok(None); } - let instance_name = match match_file_name(entry.path(), ".rbxm") { + let instance_name = match match_file_name(path, ".rbxm") { Some(name) => name, None => return Ok(None), }; @@ -36,7 +32,7 @@ impl SnapshotMiddleware for SnapshotRbxm { }); let root_id = temp_tree.get_root_id(); - rbx_binary::decode(&mut temp_tree, root_id, entry.contents(vfs)?.as_slice()) + rbx_binary::decode(&mut temp_tree, root_id, vfs.read(path)?.as_slice()) .expect("TODO: Handle rbx_binary errors"); let root_instance = temp_tree.get_instance(root_id).unwrap(); @@ -47,8 +43,8 @@ impl SnapshotMiddleware for SnapshotRbxm { .name(instance_name) .metadata( InstanceMetadata::new() - .instigating_source(entry.path()) - .relevant_paths(vec![entry.path().to_path_buf()]) + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf()]) .context(context), ); @@ -63,20 +59,26 @@ impl SnapshotMiddleware for SnapshotRbxm { mod test { use super::*; - use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot}; + use vfs::{InMemoryFs, VfsSnapshot}; #[test] fn model_from_vfs() { - let mut vfs = Vfs::new(NoopFetcher); - let file = VfsSnapshot::file(include_bytes!("../../assets/test-folder.rbxm").to_vec()); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo.rbxm", + VfsSnapshot::file(include_bytes!("../../assets/test-folder.rbxm").to_vec()), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo.rbxm", file); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo.rbxm").unwrap(); - let instance_snapshot = - SnapshotRbxm::from_vfs(&InstanceContext::default(), &mut vfs, &entry) - .unwrap() - .unwrap(); + let instance_snapshot = SnapshotRbxm::from_vfs( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.rbxm"), + ) + .unwrap() + .unwrap(); assert_eq!(instance_snapshot.name, "foo"); assert_eq!(instance_snapshot.class_name, "Folder"); diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 91b9ef0c..c697336d 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -1,7 +1,8 @@ -use crate::{ - snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, - vfs::{Vfs, VfsEntry, VfsFetcher}, -}; +use std::path::Path; + +use vfs::Vfs; + +use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ middleware::{SnapshotInstanceResult, SnapshotMiddleware}, @@ -11,16 +12,14 @@ use super::{ pub struct SnapshotRbxmx; impl SnapshotMiddleware for SnapshotRbxmx { - fn from_vfs( - context: &InstanceContext, - vfs: &Vfs, - entry: &VfsEntry, - ) -> SnapshotInstanceResult { - if entry.is_directory() { + fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { + let meta = vfs.metadata(path)?; + + if meta.is_dir() { return Ok(None); } - let instance_name = match match_file_name(entry.path(), ".rbxmx") { + let instance_name = match match_file_name(path, ".rbxmx") { Some(name) => name, None => return Ok(None), }; @@ -28,7 +27,7 @@ impl SnapshotMiddleware for SnapshotRbxmx { let options = rbx_xml::DecodeOptions::new() .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); - let temp_tree = rbx_xml::from_reader(entry.contents(vfs)?.as_slice(), options) + let temp_tree = rbx_xml::from_reader(vfs.read(path)?.as_slice(), options) .expect("TODO: Handle rbx_xml errors"); let root_instance = temp_tree.get_instance(temp_tree.get_root_id()).unwrap(); @@ -39,8 +38,8 @@ impl SnapshotMiddleware for SnapshotRbxmx { .name(instance_name) .metadata( InstanceMetadata::new() - .instigating_source(entry.path()) - .relevant_paths(vec![entry.path().to_path_buf()]) + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf()]) .context(context), ); @@ -55,36 +54,40 @@ impl SnapshotMiddleware for SnapshotRbxmx { mod test { use super::*; - use std::collections::HashMap; - - use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot}; + use vfs::{InMemoryFs, VfsSnapshot}; #[test] - fn model_from_vfs() { - let mut vfs = Vfs::new(NoopFetcher); - let file = VfsSnapshot::file( - r#" - - - - THIS NAME IS IGNORED - - - - "#, - ); + fn plain_folder() { + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo.rbxmx", + VfsSnapshot::file( + r#" + + + + THIS NAME IS IGNORED + + + + "#, + ), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo.rbxmx", file); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo.rbxmx").unwrap(); - let instance_snapshot = - SnapshotRbxmx::from_vfs(&InstanceContext::default(), &mut vfs, &entry) - .unwrap() - .unwrap(); + let instance_snapshot = SnapshotRbxmx::from_vfs( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.rbxmx"), + ) + .unwrap() + .unwrap(); assert_eq!(instance_snapshot.name, "foo"); assert_eq!(instance_snapshot.class_name, "Folder"); - assert_eq!(instance_snapshot.properties, HashMap::new()); + assert_eq!(instance_snapshot.properties, Default::default()); assert_eq!(instance_snapshot.children, Vec::new()); } } diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index b0307da0..9ee73b0b 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -1,40 +1,36 @@ -use std::str; +use std::{path::Path, str}; use maplit::hashmap; -use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; +use rbx_dom_weak::RbxValue; +use vfs::{IoResultExt, Vfs}; -use crate::{ - snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, - vfs::{FileSnapshot, FsResultExt, Vfs, VfsEntry, VfsFetcher, VfsSnapshot}, -}; +use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ error::SnapshotError, meta_file::AdjacentMetadata, - middleware::{SnapshotFileResult, SnapshotInstanceResult, SnapshotMiddleware}, + middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; pub struct SnapshotTxt; impl SnapshotMiddleware for SnapshotTxt { - fn from_vfs( - context: &InstanceContext, - vfs: &Vfs, - entry: &VfsEntry, - ) -> SnapshotInstanceResult { - if entry.is_directory() { + fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { + let meta = vfs.metadata(path)?; + + if meta.is_dir() { return Ok(None); } - let instance_name = match match_file_name(entry.path(), ".txt") { + let instance_name = match match_file_name(path, ".txt") { Some(name) => name, None => return Ok(None), }; - let contents = entry.contents(vfs)?; + let contents = vfs.read(path)?; let contents_str = str::from_utf8(&contents) - .map_err(|err| SnapshotError::file_contents_bad_unicode(err, entry.path()))? + .map_err(|err| SnapshotError::file_contents_bad_unicode(err, path))? .to_string(); let properties = hashmap! { @@ -43,9 +39,7 @@ impl SnapshotMiddleware for SnapshotTxt { }, }; - let meta_path = entry - .path() - .with_file_name(format!("{}.meta.json", instance_name)); + let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); let mut snapshot = InstanceSnapshot::new() .name(instance_name) @@ -53,99 +47,39 @@ impl SnapshotMiddleware for SnapshotTxt { .properties(properties) .metadata( InstanceMetadata::new() - .instigating_source(entry.path()) - .relevant_paths(vec![entry.path().to_path_buf(), meta_path.clone()]) + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf(), meta_path.clone()]) .context(context), ); - if let Some(meta_entry) = vfs.get(meta_path).with_not_found()? { - let meta_contents = meta_entry.contents(vfs)?; + if let Some(meta_contents) = vfs.read(meta_path).with_not_found()? { let mut metadata = AdjacentMetadata::from_slice(&meta_contents); metadata.apply_all(&mut snapshot); } Ok(Some(snapshot)) } - - fn from_instance(tree: &RbxTree, id: RbxId) -> SnapshotFileResult { - let instance = tree.get_instance(id).unwrap(); - - if instance.class_name != "StringValue" { - return None; - } - - if !instance.get_children_ids().is_empty() { - return None; - } - - let value = match instance.properties.get("Value") { - Some(RbxValue::String { value }) => value.clone(), - Some(_) => panic!("wrong type ahh"), - None => String::new(), - }; - - let snapshot = VfsSnapshot::File(FileSnapshot { - contents: value.into_bytes(), - }); - - let mut file_name = instance.name.clone(); - file_name.push_str(".txt"); - - Some((file_name, snapshot)) - } } #[cfg(test)] mod test { use super::*; - use insta::assert_yaml_snapshot; - use maplit::hashmap; - use rbx_dom_weak::RbxInstanceProperties; - - use crate::vfs::{NoopFetcher, VfsDebug}; + use vfs::{InMemoryFs, VfsSnapshot}; #[test] fn instance_from_vfs() { - let mut vfs = Vfs::new(NoopFetcher); - let file = VfsSnapshot::file("Hello there!"); + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo.txt", VfsSnapshot::file("Hello there!")) + .unwrap(); - vfs.debug_load_snapshot("/foo.txt", file); + let mut vfs = Vfs::new(imfs.clone()); - let entry = vfs.get("/foo.txt").unwrap(); let instance_snapshot = - SnapshotTxt::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotTxt::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo.txt")) .unwrap() .unwrap(); - assert_yaml_snapshot!(instance_snapshot); - } - - #[test] - fn vfs_from_instance() { - let tree = RbxTree::new(string_value("Root", "Hello, world!")); - let root_id = tree.get_root_id(); - - let (_file_name, _file) = SnapshotTxt::from_instance(&tree, root_id).unwrap(); - } - - fn folder(name: impl Into) -> RbxInstanceProperties { - RbxInstanceProperties { - name: name.into(), - class_name: "Folder".to_owned(), - properties: Default::default(), - } - } - - fn string_value(name: impl Into, value: impl Into) -> RbxInstanceProperties { - RbxInstanceProperties { - name: name.into(), - class_name: "StringValue".to_owned(), - properties: hashmap! { - "Value".to_owned() => RbxValue::String { - value: value.into(), - }, - }, - } + insta::assert_yaml_snapshot!(instance_snapshot); } } diff --git a/src/vfs/error.rs b/src/vfs/error.rs deleted file mode 100644 index 54d4efb1..00000000 --- a/src/vfs/error.rs +++ /dev/null @@ -1,55 +0,0 @@ -use std::{error::Error, fmt, io, path::PathBuf}; - -pub type FsResult = Result; -pub use io::ErrorKind as FsErrorKind; - -pub trait FsResultExt { - fn with_not_found(self) -> Result, FsError>; -} - -impl FsResultExt for Result { - fn with_not_found(self) -> Result, FsError> { - match self { - Ok(value) => Ok(Some(value)), - Err(ref err) if err.kind() == FsErrorKind::NotFound => Ok(None), - Err(err) => Err(err), - } - } -} - -/// A wrapper around io::Error that also attaches the path associated with the -/// error. -#[derive(Debug)] -pub struct FsError { - source: io::Error, - path: PathBuf, -} - -impl FsError { - pub fn new>(source: io::Error, path: P) -> FsError { - FsError { - source, - path: path.into(), - } - } - - pub fn kind(&self) -> FsErrorKind { - self.source.kind() - } - - pub fn into_raw(self) -> (io::Error, PathBuf) { - (self.source, self.path) - } -} - -impl Error for FsError { - fn source(&self) -> Option<&(dyn Error + 'static)> { - Some(&self.source) - } -} - -impl fmt::Display for FsError { - fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { - write!(output, "{}: {}", self.path.display(), self.source) - } -} diff --git a/src/vfs/event.rs b/src/vfs/event.rs deleted file mode 100644 index 93c641ff..00000000 --- a/src/vfs/event.rs +++ /dev/null @@ -1,8 +0,0 @@ -use std::path::PathBuf; - -#[derive(Debug)] -pub enum VfsEvent { - Modified(PathBuf), - Created(PathBuf), - Removed(PathBuf), -} diff --git a/src/vfs/fetcher.rs b/src/vfs/fetcher.rs deleted file mode 100644 index 7d38e370..00000000 --- a/src/vfs/fetcher.rs +++ /dev/null @@ -1,37 +0,0 @@ -use std::{ - io, - path::{Path, PathBuf}, -}; - -use crossbeam_channel::Receiver; - -use super::event::VfsEvent; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum FileType { - File, - Directory, -} - -/// The generic interface that `Vfs` uses to lazily read files from the disk. -/// In tests, it's stubbed out to do different versions of absolutely nothing -/// depending on the test. -pub trait VfsFetcher { - fn file_type(&self, path: &Path) -> io::Result; - fn read_children(&self, path: &Path) -> io::Result>; - fn read_contents(&self, path: &Path) -> io::Result>; - - fn create_directory(&self, path: &Path) -> io::Result<()>; - fn write_file(&self, path: &Path, contents: &[u8]) -> io::Result<()>; - fn remove(&self, path: &Path) -> io::Result<()>; - - fn receiver(&self) -> Receiver; - - fn watch(&self, _path: &Path) {} - fn unwatch(&self, _path: &Path) {} - - /// A method intended for debugging what paths the fetcher is watching. - fn watched_paths(&self) -> Vec { - Vec::new() - } -} diff --git a/src/vfs/mod.rs b/src/vfs/mod.rs deleted file mode 100644 index 34a14a3d..00000000 --- a/src/vfs/mod.rs +++ /dev/null @@ -1,24 +0,0 @@ -mod error; -mod event; -mod fetcher; -mod noop_fetcher; -mod real_fetcher; -mod snapshot; - -// I don't think module inception is a real problem? -#[allow(clippy::module_inception)] -mod vfs; - -pub use error::*; -pub use event::*; -pub use fetcher::*; -pub use noop_fetcher::*; -pub use real_fetcher::*; -pub use snapshot::*; -pub use vfs::*; - -#[cfg(test)] -mod test_fetcher; - -#[cfg(test)] -pub use test_fetcher::*; diff --git a/src/vfs/noop_fetcher.rs b/src/vfs/noop_fetcher.rs deleted file mode 100644 index 58533a83..00000000 --- a/src/vfs/noop_fetcher.rs +++ /dev/null @@ -1,62 +0,0 @@ -//! Implements the VFS fetcher interface for a fake filesystem using Rust's -//! std::fs interface. - -// This interface is only used for testing, so it's okay if it isn't used. -#![allow(unused)] - -use std::{ - io, - path::{Path, PathBuf}, -}; - -use crossbeam_channel::Receiver; - -use super::{ - event::VfsEvent, - fetcher::{FileType, VfsFetcher}, -}; - -pub struct NoopFetcher; - -impl VfsFetcher for NoopFetcher { - fn file_type(&self, _path: &Path) -> io::Result { - Err(io::Error::new( - io::ErrorKind::NotFound, - "NoopFetcher always returns NotFound", - )) - } - - fn read_children(&self, _path: &Path) -> io::Result> { - Err(io::Error::new( - io::ErrorKind::NotFound, - "NoopFetcher always returns NotFound", - )) - } - - fn read_contents(&self, _path: &Path) -> io::Result> { - Err(io::Error::new( - io::ErrorKind::NotFound, - "NoopFetcher always returns NotFound", - )) - } - - fn create_directory(&self, _path: &Path) -> io::Result<()> { - Ok(()) - } - - fn write_file(&self, _path: &Path, _contents: &[u8]) -> io::Result<()> { - Ok(()) - } - - fn remove(&self, _path: &Path) -> io::Result<()> { - Ok(()) - } - - fn watch(&self, _path: &Path) {} - - fn unwatch(&self, _path: &Path) {} - - fn receiver(&self) -> Receiver { - crossbeam_channel::never() - } -} diff --git a/src/vfs/real_fetcher.rs b/src/vfs/real_fetcher.rs deleted file mode 100644 index 7add1022..00000000 --- a/src/vfs/real_fetcher.rs +++ /dev/null @@ -1,225 +0,0 @@ -//! Implements the VFS fetcher interface for the real filesystem using Rust's -//! std::fs interface and notify as the file watcher. - -use std::{ - collections::HashSet, - fs, io, - path::{Path, PathBuf}, - sync::{mpsc, Mutex}, - time::Duration, -}; - -use crossbeam_channel::{unbounded, Receiver, Sender}; -use jod_thread::JoinHandle; -use notify::{DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; - -use super::{ - event::VfsEvent, - fetcher::{FileType, VfsFetcher}, -}; - -/// Workaround to disable the file watcher for processes that don't need it, -/// since notify appears hang on to mpsc Sender objects too long, causing Rojo -/// to deadlock on drop. -/// -/// We can make constructing the watcher optional in order to hotfix rojo build. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum WatchMode { - Enabled, - Disabled, -} - -pub struct RealFetcher { - // Drop order is relevant here! - // - // `watcher` must be dropped before `_converter_thread` or else joining the - // thread will cause a deadlock. - watcher: Option>, - - /// Thread handle to convert notify's mpsc channel messages into - /// crossbeam_channel messages. - _converter_thread: JoinHandle<()>, - - /// The crossbeam receiver filled with events from the converter thread. - receiver: Receiver, - - /// All of the paths that the fetcher is watching, tracked here because - /// notify does not expose this information. - watched_paths: Mutex>, -} - -impl RealFetcher { - pub fn new(watch_mode: WatchMode) -> RealFetcher { - log::trace!("Starting RealFetcher with watch mode {:?}", watch_mode); - - let (notify_sender, notify_receiver) = mpsc::channel(); - let (sender, receiver) = unbounded(); - - let handle = jod_thread::Builder::new() - .name("notify message converter".to_owned()) - .spawn(move || { - log::trace!("RealFetcher converter thread started"); - converter_thread(notify_receiver, sender); - log::trace!("RealFetcher converter thread stopped"); - }) - .expect("Could not start message converter thread"); - - // TODO: Investigate why notify hangs onto notify_sender too long, - // causing our program to deadlock. Once this is fixed, watcher no - // longer needs to be optional, but is still maybe useful? - let watcher = match watch_mode { - WatchMode::Enabled => { - let watcher = notify::watcher(notify_sender, Duration::from_millis(300)) - .expect("Couldn't start 'notify' file watcher"); - - Some(Mutex::new(watcher)) - } - WatchMode::Disabled => None, - }; - - RealFetcher { - watcher, - _converter_thread: handle, - receiver, - watched_paths: Mutex::new(HashSet::new()), - } - } -} - -fn converter_thread(notify_receiver: mpsc::Receiver, sender: Sender) { - use DebouncedEvent::*; - - for event in notify_receiver { - log::trace!("Notify event: {:?}", event); - - match event { - Create(path) => sender.send(VfsEvent::Created(path)).unwrap(), - Write(path) => sender.send(VfsEvent::Modified(path)).unwrap(), - Remove(path) => sender.send(VfsEvent::Removed(path)).unwrap(), - Rename(from_path, to_path) => { - sender.send(VfsEvent::Created(from_path)).unwrap(); - sender.send(VfsEvent::Removed(to_path)).unwrap(); - } - Rescan => { - log::warn!("Unhandled filesystem rescan event."); - log::warn!( - "Please file an issue! Rojo may need to handle this case, but does not yet." - ); - } - Error(err, maybe_path) => { - log::warn!("Unhandled filesystem error: {}", err); - - match maybe_path { - Some(path) => log::warn!("On path {}", path.display()), - None => log::warn!("No path was associated with this error."), - } - - log::warn!( - "Rojo may need to handle this. If this happens again, please file an issue!" - ); - } - NoticeWrite(_) | NoticeRemove(_) | Chmod(_) => {} - } - } -} - -impl VfsFetcher for RealFetcher { - fn file_type(&self, path: &Path) -> io::Result { - let metadata = fs::metadata(path)?; - - if metadata.is_file() { - Ok(FileType::File) - } else { - Ok(FileType::Directory) - } - } - - fn read_children(&self, path: &Path) -> io::Result> { - log::trace!("Reading directory {}", path.display()); - - let mut result = Vec::new(); - - let iter = fs::read_dir(path)?; - - for entry in iter { - result.push(entry?.path()); - } - - Ok(result) - } - - fn read_contents(&self, path: &Path) -> io::Result> { - log::trace!("Reading file {}", path.display()); - - fs::read(path) - } - - fn create_directory(&self, path: &Path) -> io::Result<()> { - log::trace!("Creating directory {}", path.display()); - - fs::create_dir(path) - } - - fn write_file(&self, path: &Path, contents: &[u8]) -> io::Result<()> { - log::trace!("Writing path {}", path.display()); - - fs::write(path, contents) - } - - fn remove(&self, path: &Path) -> io::Result<()> { - log::trace!("Removing path {}", path.display()); - - let metadata = fs::metadata(path)?; - - if metadata.is_file() { - fs::remove_file(path) - } else { - fs::remove_dir_all(path) - } - } - - fn watch(&self, path: &Path) { - log::trace!("Watching path {}", path.display()); - - if let Some(watcher_handle) = &self.watcher { - let mut watcher = watcher_handle.lock().unwrap(); - - match watcher.watch(path, RecursiveMode::NonRecursive) { - Ok(_) => { - let mut watched_paths = self.watched_paths.lock().unwrap(); - watched_paths.insert(path.to_path_buf()); - } - Err(err) => { - log::warn!("Couldn't watch path {}: {:?}", path.display(), err); - } - } - } - } - - fn unwatch(&self, path: &Path) { - log::trace!("Stopped watching path {}", path.display()); - - if let Some(watcher_handle) = &self.watcher { - let mut watcher = watcher_handle.lock().unwrap(); - - // Remove the path from our watched paths regardless of the outcome - // of notify's unwatch to ensure we drop old paths in the event of a - // rename. - let mut watched_paths = self.watched_paths.lock().unwrap(); - watched_paths.remove(path); - - if let Err(err) = watcher.unwatch(path) { - log::warn!("Couldn't unwatch path {}: {:?}", path.display(), err); - } - } - } - - fn receiver(&self) -> Receiver { - self.receiver.clone() - } - - fn watched_paths(&self) -> Vec { - let watched_paths = self.watched_paths.lock().unwrap(); - watched_paths.iter().cloned().collect() - } -} diff --git a/src/vfs/snapshot.rs b/src/vfs/snapshot.rs deleted file mode 100644 index 34187232..00000000 --- a/src/vfs/snapshot.rs +++ /dev/null @@ -1,42 +0,0 @@ -// This file is non-critical and used for testing, so it's okay if it's unused. -#![allow(unused)] - -use std::collections::HashMap; - -#[derive(Debug, Clone)] -pub enum VfsSnapshot { - File(FileSnapshot), - Directory(DirectorySnapshot), -} - -impl VfsSnapshot { - /// Create a new file VfsSnapshot with the given contents. - pub fn file(contents: impl Into>) -> VfsSnapshot { - VfsSnapshot::File(FileSnapshot { - contents: contents.into(), - }) - } - - /// Create a new directory VfsSnapshot with the given children. - pub fn dir>(children: HashMap) -> VfsSnapshot { - let children = children.into_iter().map(|(k, v)| (k.into(), v)).collect(); - - VfsSnapshot::Directory(DirectorySnapshot { children }) - } - - pub fn empty_dir() -> VfsSnapshot { - VfsSnapshot::Directory(DirectorySnapshot { - children: Default::default(), - }) - } -} - -#[derive(Debug, Clone)] -pub struct FileSnapshot { - pub contents: Vec, -} - -#[derive(Debug, Clone)] -pub struct DirectorySnapshot { - pub children: HashMap, -} diff --git a/src/vfs/test_fetcher.rs b/src/vfs/test_fetcher.rs deleted file mode 100644 index e97f9334..00000000 --- a/src/vfs/test_fetcher.rs +++ /dev/null @@ -1,171 +0,0 @@ -//! Implements the VFS fetcher interface for a fake filesystem that can be -//! mutated and have changes signaled through it. -//! -//! This is useful for testing how things using Vfs react to changed events -//! without relying on the real filesystem implementation, which is very -//! platform-specific. - -// This interface is only used for testing, so it's okay if it isn't used. -#![allow(unused)] - -use std::{ - io, - path::{self, Path, PathBuf}, - sync::{Arc, Mutex}, -}; - -use crossbeam_channel::{unbounded, Receiver, Sender}; - -use crate::path_map::PathMap; - -use super::{ - event::VfsEvent, - fetcher::{FileType, VfsFetcher}, - snapshot::VfsSnapshot, -}; - -#[derive(Clone)] -pub struct TestFetcherState { - inner: Arc>, -} - -impl TestFetcherState { - pub fn load_snapshot>(&self, path: P, snapshot: VfsSnapshot) { - let mut inner = self.inner.lock().unwrap(); - inner.load_snapshot(path.as_ref().to_path_buf(), snapshot); - } - - pub fn remove>(&self, path: P) { - let mut inner = self.inner.lock().unwrap(); - inner.remove(path.as_ref()); - } - - pub fn raise_event(&self, event: VfsEvent) { - let mut inner = self.inner.lock().unwrap(); - inner.raise_event(event); - } -} - -pub enum TestFetcherEntry { - File(Vec), - Dir, -} - -struct TestFetcherStateInner { - entries: PathMap, - sender: Sender, -} - -impl TestFetcherStateInner { - fn new(sender: Sender) -> Self { - let mut entries = PathMap::new(); - entries.insert(Path::new("/"), TestFetcherEntry::Dir); - - Self { sender, entries } - } - - fn load_snapshot(&mut self, path: PathBuf, snapshot: VfsSnapshot) { - match snapshot { - VfsSnapshot::File(file) => { - self.entries - .insert(path, TestFetcherEntry::File(file.contents)); - } - VfsSnapshot::Directory(directory) => { - self.entries.insert(path.clone(), TestFetcherEntry::Dir); - - for (child_name, child) in directory.children.into_iter() { - self.load_snapshot(path.join(child_name), child); - } - } - } - } - - fn remove(&mut self, path: &Path) { - self.entries.remove(path); - } - - fn raise_event(&mut self, event: VfsEvent) { - self.sender.send(event).unwrap(); - } -} - -pub struct TestFetcher { - state: TestFetcherState, - receiver: Receiver, -} - -impl TestFetcher { - pub fn new() -> (TestFetcherState, Self) { - let (sender, receiver) = unbounded(); - - let state = TestFetcherState { - inner: Arc::new(Mutex::new(TestFetcherStateInner::new(sender))), - }; - - (state.clone(), Self { receiver, state }) - } -} - -impl VfsFetcher for TestFetcher { - fn file_type(&self, path: &Path) -> io::Result { - let inner = self.state.inner.lock().unwrap(); - - match inner.entries.get(path) { - Some(TestFetcherEntry::File(_)) => Ok(FileType::File), - Some(TestFetcherEntry::Dir) => Ok(FileType::Directory), - None => Err(io::Error::new(io::ErrorKind::NotFound, "Path not found")), - } - } - - fn read_children(&self, path: &Path) -> io::Result> { - let inner = self.state.inner.lock().unwrap(); - - Ok(inner - .entries - .children(path) - .ok_or_else(|| io::Error::new(io::ErrorKind::NotFound, "Path not found"))? - .into_iter() - .map(|path| path.to_path_buf()) - .collect()) - } - - fn read_contents(&self, path: &Path) -> io::Result> { - let inner = self.state.inner.lock().unwrap(); - - let node = inner.entries.get(path); - - match node { - Some(TestFetcherEntry::File(contents)) => Ok(contents.clone()), - Some(TestFetcherEntry::Dir) => Err(io::Error::new( - io::ErrorKind::Other, - "Cannot read contents of a directory", - )), - None => Err(io::Error::new(io::ErrorKind::NotFound, "Path not found")), - } - } - - fn create_directory(&self, _path: &Path) -> io::Result<()> { - Err(io::Error::new( - io::ErrorKind::Other, - "TestFetcher is not mutable yet", - )) - } - - fn write_file(&self, _path: &Path, _contents: &[u8]) -> io::Result<()> { - Err(io::Error::new( - io::ErrorKind::Other, - "TestFetcher is not mutable yet", - )) - } - - fn remove(&self, _path: &Path) -> io::Result<()> { - Err(io::Error::new( - io::ErrorKind::Other, - "TestFetcher is not mutable yet", - )) - } - - fn receiver(&self) -> Receiver { - self.receiver.clone() - } -} diff --git a/src/vfs/vfs.rs b/src/vfs/vfs.rs deleted file mode 100644 index 149834e0..00000000 --- a/src/vfs/vfs.rs +++ /dev/null @@ -1,614 +0,0 @@ -use std::{ - io, - path::{Path, PathBuf}, - sync::{Arc, Mutex}, -}; - -use crossbeam_channel::Receiver; - -use crate::path_map::PathMap; - -use super::{ - error::{FsError, FsResult}, - event::VfsEvent, - fetcher::{FileType, VfsFetcher}, - snapshot::VfsSnapshot, -}; - -/// An in-memory filesystem that can be incrementally populated and updated as -/// filesystem modification events occur. -/// -/// All operations on the `Vfs` are lazy and do I/O as late as they can to -/// avoid reading extraneous files or directories from the disk. This means that -/// they all take `self` mutably, and means that it isn't possible to hold -/// references to the internal state of the Vfs while traversing it! -/// -/// Most operations return `VfsEntry` objects to work around this, which is -/// effectively a index into the `Vfs`. -pub struct Vfs { - /// A hierarchical map from paths to items that have been read or partially - /// read into memory by the Vfs. - data: Mutex>, - - /// This Vfs's fetcher, which is used for all actual interactions with the - /// filesystem. It's referred to by the type parameter `F` all over, and is - /// generic in order to make it feasible to mock. - fetcher: F, -} - -impl Vfs { - pub fn new(fetcher: F) -> Self { - Self { - data: Mutex::new(PathMap::new()), - fetcher, - } - } - - pub fn change_receiver(&self) -> Receiver { - self.fetcher.receiver() - } - - pub fn commit_change(&self, event: &VfsEvent) -> FsResult<()> { - use VfsEvent::*; - - log::trace!("Committing Vfs change {:?}", event); - - let mut data = self.data.lock().unwrap(); - - match event { - Created(path) | Modified(path) => { - Self::raise_file_changed(&mut data, &self.fetcher, path)?; - } - Removed(path) => { - Self::raise_file_removed(&mut data, &self.fetcher, path)?; - } - } - - Ok(()) - } - - pub fn get(&self, path: impl AsRef) -> FsResult { - let mut data = self.data.lock().unwrap(); - Self::get_internal(&mut data, &self.fetcher, path) - } - - pub fn get_contents(&self, path: impl AsRef) -> FsResult>> { - let path = path.as_ref(); - - let mut data = self.data.lock().unwrap(); - Self::read_if_not_exists(&mut data, &self.fetcher, path)?; - - match data.get_mut(path).unwrap() { - VfsItem::File(file) => { - if file.contents.is_none() { - file.contents = Some( - self.fetcher - .read_contents(path) - .map(Arc::new) - .map_err(|err| FsError::new(err, path.to_path_buf()))?, - ); - } - - Ok(file.contents.clone().unwrap()) - } - VfsItem::Directory(_) => Err(FsError::new( - io::Error::new(io::ErrorKind::Other, "Can't read a directory"), - path.to_path_buf(), - )), - } - } - - pub fn get_children(&self, path: impl AsRef) -> FsResult> { - let path = path.as_ref(); - - let mut data = self.data.lock().unwrap(); - Self::read_if_not_exists(&mut data, &self.fetcher, path)?; - - match data.get_mut(path).unwrap() { - VfsItem::Directory(dir) => { - self.fetcher.watch(path); - - // If the directory hasn't been marked as enumerated yet, find - // all of its children and insert them into the VFS. - if !dir.children_enumerated { - dir.children_enumerated = true; - - let children = self - .fetcher - .read_children(path) - .map_err(|err| FsError::new(err, path.to_path_buf()))?; - - for path in children { - Self::get_internal(&mut data, &self.fetcher, path)?; - } - } - - data.children(path) - .unwrap() // TODO: Handle None here, which means the PathMap entry did not exist. - .into_iter() - .map(PathBuf::from) // Convert paths from &Path to PathBuf - .collect::>() // Collect all PathBufs, since self.get needs to borrow self mutably. - .into_iter() - .map(|path| Self::get_internal(&mut data, &self.fetcher, path)) - .collect::>>() - } - VfsItem::File(_) => Err(FsError::new( - io::Error::new(io::ErrorKind::Other, "Can't read a directory"), - path.to_path_buf(), - )), - } - } - - fn get_internal( - data: &mut PathMap, - fetcher: &F, - path: impl AsRef, - ) -> FsResult { - let path = path.as_ref(); - - Self::read_if_not_exists(data, fetcher, path)?; - - let item = data.get(path).unwrap(); - - let is_file = match item { - VfsItem::File(_) => true, - VfsItem::Directory(_) => false, - }; - - Ok(VfsEntry { - path: item.path().to_path_buf(), - is_file, - }) - } - - fn raise_file_changed( - data: &mut PathMap, - fetcher: &F, - path: impl AsRef, - ) -> FsResult<()> { - let path = path.as_ref(); - - if !Self::would_be_resident(&data, path) { - log::trace!( - "Path would not be resident, skipping change: {}", - path.display() - ); - - return Ok(()); - } - - let new_type = fetcher - .file_type(path) - .map_err(|err| FsError::new(err, path.to_path_buf()))?; - - match data.get_mut(path) { - Some(existing_item) => { - match (existing_item, &new_type) { - (VfsItem::File(existing_file), FileType::File) => { - // Invalidate the existing file contents. - // We can probably be smarter about this by reading the changed file. - existing_file.contents = None; - } - (VfsItem::Directory(_), FileType::Directory) => { - // No changes required, a directory updating doesn't mean anything to us. - fetcher.watch(path); - } - (VfsItem::File(_), FileType::Directory) => { - data.remove(path); - data.insert( - path.to_path_buf(), - VfsItem::new_from_type(FileType::Directory, path), - ); - fetcher.watch(path); - } - (VfsItem::Directory(_), FileType::File) => { - data.remove(path); - data.insert( - path.to_path_buf(), - VfsItem::new_from_type(FileType::File, path), - ); - fetcher.unwatch(path); - } - } - } - None => { - log::trace!("Inserting new path {}", path.display()); - data.insert(path.to_path_buf(), VfsItem::new_from_type(new_type, path)); - } - } - - Ok(()) - } - - fn raise_file_removed( - data: &mut PathMap, - fetcher: &F, - path: impl AsRef, - ) -> FsResult<()> { - let path = path.as_ref(); - - if !Self::would_be_resident(data, path) { - return Ok(()); - } - - data.remove(path); - fetcher.unwatch(path); - Ok(()) - } - - /// Attempts to read the path into the `Vfs` if it doesn't exist. - /// - /// This does not necessitate that file contents or directory children will - /// be read. Depending on the `VfsFetcher` implementation that the `Vfs` - /// is using, this call may read exactly only the given path and no more. - fn read_if_not_exists(data: &mut PathMap, fetcher: &F, path: &Path) -> FsResult<()> { - if !data.contains_key(path) { - let kind = fetcher - .file_type(path) - .map_err(|err| FsError::new(err, path.to_path_buf()))?; - - if kind == FileType::Directory { - fetcher.watch(path); - } - - data.insert(path.to_path_buf(), VfsItem::new_from_type(kind, path)); - } - - Ok(()) - } - - /// Tells whether the given path, if it were loaded, would be loaded if it - /// existed. - /// - /// Returns true if the path is loaded or if its parent is loaded, is a - /// directory, and is marked as having been enumerated before. - /// - /// This idea corresponds to whether a file change event should result in - /// tangible changes to the in-memory filesystem. If a path would be - /// resident, we need to read it, and if its contents were known before, we - /// need to update them. - fn would_be_resident(data: &PathMap, path: &Path) -> bool { - if data.contains_key(path) { - return true; - } - - if let Some(parent) = path.parent() { - if let Some(VfsItem::Directory(dir)) = data.get(parent) { - return dir.children_enumerated; - } - } - - false - } -} - -/// Contains extra methods that should only be used for debugging. They're -/// broken out into a separate trait to make it more explicit to depend on them. -pub trait VfsDebug { - fn debug_load_snapshot>(&self, path: P, snapshot: VfsSnapshot); - fn debug_is_file(&self, path: &Path) -> bool; - fn debug_contents(&self, path: &Path) -> Option>>; - fn debug_children(&self, path: &Path) -> Option<(bool, Vec)>; - fn debug_orphans(&self) -> Vec; - fn debug_watched_paths(&self) -> Vec; -} - -impl VfsDebug for Vfs { - fn debug_load_snapshot>(&self, path: P, snapshot: VfsSnapshot) { - fn load_snapshot>( - data: &mut PathMap, - path: P, - snapshot: VfsSnapshot, - ) { - let path = path.as_ref(); - - match snapshot { - VfsSnapshot::File(file) => { - data.insert( - path.to_path_buf(), - VfsItem::File(VfsFile { - path: path.to_path_buf(), - contents: Some(Arc::new(file.contents)), - }), - ); - } - VfsSnapshot::Directory(directory) => { - data.insert( - path.to_path_buf(), - VfsItem::Directory(VfsDirectory { - path: path.to_path_buf(), - children_enumerated: true, - }), - ); - - for (child_name, child) in directory.children.into_iter() { - load_snapshot(data, path.join(child_name), child); - } - } - } - } - - let mut data = self.data.lock().unwrap(); - load_snapshot(&mut data, path, snapshot) - } - - fn debug_is_file(&self, path: &Path) -> bool { - let data = self.data.lock().unwrap(); - match data.get(path) { - Some(VfsItem::File(_)) => true, - _ => false, - } - } - - fn debug_contents(&self, path: &Path) -> Option>> { - let data = self.data.lock().unwrap(); - match data.get(path) { - Some(VfsItem::File(file)) => file.contents.clone(), - _ => None, - } - } - - fn debug_children(&self, path: &Path) -> Option<(bool, Vec)> { - let data = self.data.lock().unwrap(); - match data.get(path) { - Some(VfsItem::Directory(dir)) => Some(( - dir.children_enumerated, - data.children(path) - .unwrap() - .iter() - .map(|path| path.to_path_buf()) - .collect(), - )), - _ => None, - } - } - - fn debug_orphans(&self) -> Vec { - let data = self.data.lock().unwrap(); - data.orphans().map(|path| path.to_path_buf()).collect() - } - - fn debug_watched_paths(&self) -> Vec { - self.fetcher.watched_paths() - } -} - -/// A reference to file or folder in an `Vfs`. Can only be produced by the -/// entry existing in the Vfs, but can later point to nothing if something -/// would invalidate that path. -/// -/// This struct does not borrow from the Vfs since every operation has the -/// possibility to mutate the underlying data structure and move memory around. -pub struct VfsEntry { - path: PathBuf, - is_file: bool, -} - -impl VfsEntry { - pub fn path(&self) -> &Path { - &self.path - } - - pub fn contents(&self, vfs: &Vfs) -> FsResult>> { - vfs.get_contents(&self.path) - } - - pub fn children(&self, vfs: &Vfs) -> FsResult> { - vfs.get_children(&self.path) - } - - pub fn is_file(&self) -> bool { - self.is_file - } - - pub fn is_directory(&self) -> bool { - !self.is_file - } -} - -/// Internal structure describing potentially partially-resident files and -/// folders in the `Vfs`. -#[derive(Debug)] -pub enum VfsItem { - File(VfsFile), - Directory(VfsDirectory), -} - -impl VfsItem { - fn path(&self) -> &Path { - match self { - VfsItem::File(file) => &file.path, - VfsItem::Directory(dir) => &dir.path, - } - } - - fn new_from_type(kind: FileType, path: impl Into) -> VfsItem { - match kind { - FileType::Directory => VfsItem::Directory(VfsDirectory { - path: path.into(), - children_enumerated: false, - }), - FileType::File => VfsItem::File(VfsFile { - path: path.into(), - contents: None, - }), - } - } -} - -#[derive(Debug)] -pub struct VfsFile { - pub(super) path: PathBuf, - pub(super) contents: Option>>, -} - -#[derive(Debug)] -pub struct VfsDirectory { - pub(super) path: PathBuf, - pub(super) children_enumerated: bool, -} - -#[cfg(test)] -mod test { - use super::*; - - use std::{cell::RefCell, rc::Rc}; - - use crossbeam_channel::Receiver; - use maplit::hashmap; - - use super::super::{error::FsErrorKind, event::VfsEvent, noop_fetcher::NoopFetcher}; - - #[test] - fn from_snapshot_file() { - let vfs = Vfs::new(NoopFetcher); - let file = VfsSnapshot::file("hello, world!"); - - vfs.debug_load_snapshot("/hello.txt", file); - - let contents = vfs.get_contents("/hello.txt").unwrap(); - assert_eq!(contents.as_slice(), b"hello, world!"); - } - - #[test] - fn from_snapshot_dir() { - let vfs = Vfs::new(NoopFetcher); - let dir = VfsSnapshot::dir(hashmap! { - "a.txt" => VfsSnapshot::file("contents of a.txt"), - "b.lua" => VfsSnapshot::file("contents of b.lua"), - }); - - vfs.debug_load_snapshot("/dir", dir); - - let children = vfs.get_children("/dir").unwrap(); - - let mut has_a = false; - let mut has_b = false; - - for child in children.into_iter() { - if child.path() == Path::new("/dir/a.txt") { - has_a = true; - } else if child.path() == Path::new("/dir/b.lua") { - has_b = true; - } else { - panic!("Unexpected child in /dir"); - } - } - - assert!(has_a, "/dir/a.txt was missing"); - assert!(has_b, "/dir/b.lua was missing"); - - let a_contents = vfs.get_contents("/dir/a.txt").unwrap(); - assert_eq!(a_contents.as_slice(), b"contents of a.txt"); - - let b_contents = vfs.get_contents("/dir/b.lua").unwrap(); - assert_eq!(b_contents.as_slice(), b"contents of b.lua"); - } - - #[test] - fn changed_event() { - #[derive(Default)] - struct MockState { - a_contents: &'static str, - } - - struct MockFetcher { - inner: Rc>, - } - - impl VfsFetcher for MockFetcher { - fn file_type(&self, path: &Path) -> io::Result { - if path == Path::new("/dir/a.txt") { - return Ok(FileType::File); - } - - unimplemented!(); - } - - fn read_contents(&self, path: &Path) -> io::Result> { - if path == Path::new("/dir/a.txt") { - let inner = self.inner.borrow(); - - return Ok(Vec::from(inner.a_contents)); - } - - unimplemented!(); - } - - fn read_children(&self, _path: &Path) -> io::Result> { - unimplemented!(); - } - - fn create_directory(&self, _path: &Path) -> io::Result<()> { - unimplemented!(); - } - - fn write_file(&self, _path: &Path, _contents: &[u8]) -> io::Result<()> { - unimplemented!(); - } - - fn remove(&self, _path: &Path) -> io::Result<()> { - unimplemented!(); - } - - fn receiver(&self) -> Receiver { - crossbeam_channel::never() - } - } - - let mock_state = Rc::new(RefCell::new(MockState { - a_contents: "Initial contents", - })); - - let mut vfs = Vfs::new(MockFetcher { - inner: mock_state.clone(), - }); - - let a = vfs.get("/dir/a.txt").expect("mock file did not exist"); - - let contents = a.contents(&mut vfs).expect("mock file contents error"); - - assert_eq!(contents.as_slice(), b"Initial contents"); - - { - let mut mock_state = mock_state.borrow_mut(); - mock_state.a_contents = "Changed contents"; - } - - vfs.commit_change(&VfsEvent::Modified(PathBuf::from("/dir/a.txt"))) - .expect("error processing file change"); - - let contents = a.contents(&mut vfs).expect("mock file contents error"); - - assert_eq!(contents.as_slice(), b"Changed contents"); - } - - #[test] - fn removed_event_existing() { - let mut vfs = Vfs::new(NoopFetcher); - - let file = VfsSnapshot::file("hello, world!"); - vfs.debug_load_snapshot("/hello.txt", file); - - let hello = vfs.get("/hello.txt").expect("couldn't get hello.txt"); - - let contents = hello - .contents(&mut vfs) - .expect("couldn't get hello.txt contents"); - - assert_eq!(contents.as_slice(), b"hello, world!"); - - vfs.commit_change(&VfsEvent::Removed(PathBuf::from("/hello.txt"))) - .expect("error processing file removal"); - - match vfs.get("hello.txt") { - Err(ref err) if err.kind() == FsErrorKind::NotFound => {} - Ok(_) => { - panic!("hello.txt was not removed from Vfs"); - } - Err(err) => { - panic!("Unexpected error: {:?}", err); - } - } - } -} diff --git a/src/web/api.rs b/src/web/api.rs index 0ddb21d6..9a341de7 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -11,7 +11,6 @@ use rbx_dom_weak::RbxId; use crate::{ serve_session::ServeSession, snapshot::{PatchSet, PatchUpdate}, - vfs::VfsFetcher, web::{ interface::{ ErrorResponse, Instance, InstanceMetadata as WebInstanceMetadata, InstanceUpdate, @@ -22,11 +21,11 @@ use crate::{ }, }; -pub struct ApiService { - serve_session: Arc>, +pub struct ApiService { + serve_session: Arc, } -impl Service for ApiService { +impl Service for ApiService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; @@ -53,8 +52,8 @@ impl Service for ApiService { } } -impl ApiService { - pub fn new(serve_session: Arc>) -> Self { +impl ApiService { + pub fn new(serve_session: Arc) -> Self { ApiService { serve_session } } diff --git a/src/web/mod.rs b/src/web/mod.rs index d6548ef7..e9a032bc 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -13,16 +13,16 @@ use futures::{ use hyper::{service::Service, Body, Request, Response, Server}; use log::trace; -use crate::{serve_session::ServeSession, vfs::VfsFetcher}; +use crate::serve_session::ServeSession; use self::{api::ApiService, ui::UiService}; -pub struct RootService { - api: ApiService, - ui: UiService, +pub struct RootService { + api: ApiService, + ui: UiService, } -impl Service for RootService { +impl Service for RootService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; @@ -39,8 +39,8 @@ impl Service for RootService { } } -impl RootService { - pub fn new(serve_session: Arc>) -> Self { +impl RootService { + pub fn new(serve_session: Arc) -> Self { RootService { api: ApiService::new(Arc::clone(&serve_session)), ui: UiService::new(Arc::clone(&serve_session)), @@ -48,12 +48,12 @@ impl RootService { } } -pub struct LiveServer { - serve_session: Arc>, +pub struct LiveServer { + serve_session: Arc, } -impl LiveServer { - pub fn new(serve_session: Arc>) -> Self { +impl LiveServer { + pub fn new(serve_session: Arc) -> Self { LiveServer { serve_session } } diff --git a/src/web/ui.rs b/src/web/ui.rs index 0f59b9e8..50fe1df4 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -1,6 +1,6 @@ //! Defines the HTTP-based UI. These endpoints generally return HTML and SVG. -use std::{borrow::Cow, path::Path, sync::Arc, time::Duration}; +use std::{borrow::Cow, sync::Arc, time::Duration}; use futures::{future, Future}; use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; @@ -11,7 +11,6 @@ use ritz::{html, Fragment, HtmlContent, HtmlSelfClosingTag}; use crate::{ serve_session::ServeSession, snapshot::RojoTree, - vfs::{Vfs, VfsDebug, VfsFetcher}, web::{ assets, interface::{ErrorResponse, SERVER_VERSION}, @@ -19,11 +18,11 @@ use crate::{ }, }; -pub struct UiService { - serve_session: Arc>, +pub struct UiService { + serve_session: Arc, } -impl Service for UiService { +impl Service for UiService { type ReqBody = Body; type ResBody = Body; type Error = hyper::Error; @@ -35,7 +34,6 @@ impl Service for UiService { (&Method::GET, "/logo.png") => self.handle_logo(), (&Method::GET, "/icon.png") => self.handle_icon(), (&Method::GET, "/show-instances") => self.handle_show_instances(), - (&Method::GET, "/show-vfs") => self.handle_show_vfs(), (_method, path) => { return json( ErrorResponse::not_found(format!("Route not found: {}", path)), @@ -48,8 +46,8 @@ impl Service for UiService { } } -impl UiService { - pub fn new(serve_session: Arc>) -> Self { +impl UiService { + pub fn new(serve_session: Arc) -> Self { UiService { serve_session } } @@ -71,7 +69,6 @@ impl UiService { let page = self.normal_page(html! {

    { Self::button("Rojo Documentation", "https://rojo.space/docs") } - { Self::button("View virtual filesystem state", "/show-vfs") } { Self::button("View instance tree state", "/show-instances") }
    }); @@ -96,100 +93,6 @@ impl UiService { .unwrap() } - fn handle_show_vfs(&self) -> Response { - let vfs = self.serve_session.vfs(); - - let orphans: Vec<_> = vfs - .debug_orphans() - .into_iter() - .map(|path| Self::render_vfs_path(&vfs, &path, true)) - .collect(); - - let watched_list: Vec<_> = vfs - .debug_watched_paths() - .into_iter() - .map(|path| { - html! { -
  • { format!("{}", path.display()) }
  • - } - }) - .collect(); - - let page = self.normal_page(html! { - <> -
    -

    "Known FS Items"

    -
    { Fragment::new(orphans) }
    -
    - -
    -

    "Watched Paths"

    -
      { Fragment::new(watched_list) }
    -
    - - }); - - Response::builder() - .header(header::CONTENT_TYPE, "text/html") - .body(Body::from(format!("{}", page))) - .unwrap() - } - - fn render_vfs_path(vfs: &Vfs, path: &Path, is_root: bool) -> HtmlContent<'static> { - let is_file = vfs.debug_is_file(path); - - let (note, children) = if is_file { - (HtmlContent::None, Vec::new()) - } else { - let (is_exhaustive, mut children) = vfs.debug_children(path).unwrap(); - - // Sort files above directories, then sort how Path does after that. - children.sort_unstable_by(|a, b| { - let a_is_file = vfs.debug_is_file(a); - let b_is_file = vfs.debug_is_file(b); - - b_is_file.cmp(&a_is_file).then_with(|| a.cmp(b)) - }); - - let children: Vec<_> = children - .into_iter() - .map(|child| Self::render_vfs_path(vfs, &child, false)) - .collect(); - - let note = if is_exhaustive { - HtmlContent::None - } else { - html!({ " (not enumerated)" }) - }; - - (note, children) - }; - - // For root entries, we want the full path to contextualize the path. - let mut name = if is_root { - path.to_str().unwrap().to_owned() - } else { - path.file_name().unwrap().to_str().unwrap().to_owned() - }; - - // Directories should end with `/` in the UI to mark them. - if !is_file && !name.ends_with('/') && !name.ends_with('\\') { - name.push('/'); - } - - html! { -
    -
    - { name } - { note } -
    -
    - { Fragment::new(children) } -
    -
    - } - } - fn instance(tree: &RojoTree, id: RbxId) -> HtmlContent<'_> { let instance = tree.get_instance(id).unwrap(); let children_list: Vec<_> = instance diff --git a/vfs/src/memory_backend.rs b/vfs/src/in_memory_fs.rs similarity index 65% rename from vfs/src/memory_backend.rs rename to vfs/src/in_memory_fs.rs index b7c8ac13..328fbffe 100644 --- a/vfs/src/memory_backend.rs +++ b/vfs/src/in_memory_fs.rs @@ -1,32 +1,77 @@ use std::collections::{BTreeSet, HashMap, VecDeque}; use std::io; use std::path::{Path, PathBuf}; +use std::sync::{Arc, Mutex}; + +use crossbeam_channel::{Receiver, Sender}; use crate::{DirEntry, Metadata, ReadDir, VfsBackend, VfsEvent, VfsSnapshot}; -/// `VfsBackend` that reads from an in-memory filesystem, intended for setting -/// up testing scenarios quickly. -#[derive(Debug)] -pub struct MemoryBackend { - entries: HashMap, - orphans: BTreeSet, +/// In-memory filesystem that can be used as a VFS backend. +/// +/// Internally reference counted to enable giving a copy to +/// [`Vfs`](struct.Vfs.html) and keeping the original to mutate the filesystem's +/// state with. +#[derive(Debug, Clone)] +pub struct InMemoryFs { + inner: Arc>, } -impl MemoryBackend { +impl InMemoryFs { + /// Create a new empty `InMemoryFs`. pub fn new() -> Self { Self { - entries: HashMap::new(), - orphans: BTreeSet::new(), + inner: Arc::new(Mutex::new(InMemoryFsInner::new())), } } + /// Load a [`VfsSnapshot`](enum.VfsSnapshot.html) into a subtree of the + /// in-memory filesystem. + /// + /// This function will return an error if the operations required to apply + /// the snapshot result in errors, like trying to create a file inside a + /// file. pub fn load_snapshot>( &mut self, path: P, snapshot: VfsSnapshot, ) -> io::Result<()> { - let path = path.into(); + let mut inner = self.inner.lock().unwrap(); + inner.load_snapshot(path.into(), snapshot) + } + /// Raises a filesystem change event. + /// + /// If this `InMemoryFs` is being used as the backend of a + /// [`Vfs`](struct.Vfs.html), then any listeners be notified of this event. + pub fn raise_event(&mut self, event: VfsEvent) { + let inner = self.inner.lock().unwrap(); + inner.event_sender.send(event).unwrap(); + } +} + +#[derive(Debug)] +struct InMemoryFsInner { + entries: HashMap, + orphans: BTreeSet, + + event_receiver: Receiver, + event_sender: Sender, +} + +impl InMemoryFsInner { + fn new() -> Self { + let (event_sender, event_receiver) = crossbeam_channel::unbounded(); + + Self { + entries: HashMap::new(), + orphans: BTreeSet::new(), + event_receiver, + event_sender, + } + } + + fn load_snapshot(&mut self, path: PathBuf, snapshot: VfsSnapshot) -> io::Result<()> { if let Some(parent_path) = path.parent() { if let Some(parent_entry) = self.entries.get_mut(parent_path) { if let Entry::Dir { children } = parent_entry { @@ -84,9 +129,11 @@ enum Entry { Dir { children: BTreeSet }, } -impl VfsBackend for MemoryBackend { +impl VfsBackend for InMemoryFs { fn read(&mut self, path: &Path) -> io::Result> { - match self.entries.get(path) { + let inner = self.inner.lock().unwrap(); + + match inner.entries.get(path) { Some(Entry::File { contents }) => Ok(contents.clone()), Some(Entry::Dir { .. }) => must_be_file(path), None => not_found(path), @@ -94,8 +141,10 @@ impl VfsBackend for MemoryBackend { } fn write(&mut self, path: &Path, data: &[u8]) -> io::Result<()> { - self.load_snapshot( - path, + let mut inner = self.inner.lock().unwrap(); + + inner.load_snapshot( + path.to_path_buf(), VfsSnapshot::File { contents: data.to_owned(), }, @@ -103,7 +152,9 @@ impl VfsBackend for MemoryBackend { } fn read_dir(&mut self, path: &Path) -> io::Result { - match self.entries.get(path) { + let inner = self.inner.lock().unwrap(); + + match inner.entries.get(path) { Some(Entry::Dir { children }) => { let iter = children .clone() @@ -120,9 +171,11 @@ impl VfsBackend for MemoryBackend { } fn remove_file(&mut self, path: &Path) -> io::Result<()> { - match self.entries.get(path) { + let mut inner = self.inner.lock().unwrap(); + + match inner.entries.get(path) { Some(Entry::File { .. }) => { - self.remove(path.to_owned()); + inner.remove(path.to_owned()); Ok(()) } Some(Entry::Dir { .. }) => must_be_file(path), @@ -131,9 +184,11 @@ impl VfsBackend for MemoryBackend { } fn remove_dir_all(&mut self, path: &Path) -> io::Result<()> { - match self.entries.get(path) { + let mut inner = self.inner.lock().unwrap(); + + match inner.entries.get(path) { Some(Entry::Dir { .. }) => { - self.remove(path.to_owned()); + inner.remove(path.to_owned()); Ok(()) } Some(Entry::File { .. }) => must_be_dir(path), @@ -142,7 +197,9 @@ impl VfsBackend for MemoryBackend { } fn metadata(&mut self, path: &Path) -> io::Result { - match self.entries.get(path) { + let inner = self.inner.lock().unwrap(); + + match inner.entries.get(path) { Some(Entry::File { .. }) => Ok(Metadata { is_file: true }), Some(Entry::Dir { .. }) => Ok(Metadata { is_file: false }), None => not_found(path), @@ -150,7 +207,9 @@ impl VfsBackend for MemoryBackend { } fn event_receiver(&self) -> crossbeam_channel::Receiver { - crossbeam_channel::never() + let inner = self.inner.lock().unwrap(); + + inner.event_receiver.clone() } fn watch(&mut self, _path: &Path) -> io::Result<()> { diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index 6105a033..8aede061 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -1,4 +1,4 @@ -mod memory_backend; +mod in_memory_fs; mod noop_backend; mod snapshot; mod std_backend; @@ -7,7 +7,7 @@ use std::io; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex, MutexGuard}; -pub use memory_backend::MemoryBackend; +pub use in_memory_fs::InMemoryFs; pub use noop_backend::NoopBackend; pub use snapshot::VfsSnapshot; pub use std_backend::StdBackend; @@ -18,9 +18,9 @@ mod sealed { /// Sealing trait for VfsBackend. pub trait Sealed {} - impl Sealed for MemoryBackend {} impl Sealed for NoopBackend {} impl Sealed for StdBackend {} + impl Sealed for InMemoryFs {} } /// Trait that transforms `io::Result` into `io::Result>`. @@ -107,6 +107,8 @@ impl Metadata { } } +/// Represents an event that a filesystem can raise that might need to be +/// handled. #[derive(Debug)] #[non_exhaustive] pub enum VfsEvent { diff --git a/vfs/src/snapshot.rs b/vfs/src/snapshot.rs index 5ddb9363..e6596bb2 100644 --- a/vfs/src/snapshot.rs +++ b/vfs/src/snapshot.rs @@ -1,5 +1,8 @@ use std::collections::BTreeMap; +/// A slice of a tree of files. Can be loaded into an +/// [`InMemoryFs`](struct.InMemoryFs.html). +#[derive(Debug)] #[non_exhaustive] pub enum VfsSnapshot { File { @@ -26,4 +29,16 @@ impl VfsSnapshot { .collect(), } } + + pub fn empty_file() -> Self { + Self::File { + contents: Vec::new(), + } + } + + pub fn empty_dir() -> Self { + Self::Dir { + children: BTreeMap::new(), + } + } } diff --git a/vfs/src/std_backend.rs b/vfs/src/std_backend.rs index fa0857b8..e023ec71 100644 --- a/vfs/src/std_backend.rs +++ b/vfs/src/std_backend.rs @@ -63,11 +63,14 @@ impl VfsBackend for StdBackend { } fn read_dir(&mut self, path: &Path) -> io::Result { - let inner = fs::read_dir(path)?.map(|entry| { - Ok(DirEntry { - path: entry?.path(), - }) - }); + let entries: Result, _> = fs::read_dir(path)?.collect(); + let mut entries = entries?; + + entries.sort_by_cached_key(|entry| entry.file_name()); + + let inner = entries + .into_iter() + .map(|entry| Ok(DirEntry { path: entry.path() })); Ok(ReadDir { inner: Box::new(inner), From f61f3671a662d5760f3f19c029929f48e511c678 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Mar 2020 17:57:57 -0700 Subject: [PATCH 0970/1504] Choose 'memofs' as the vfs name --- vfs/Cargo.toml | 2 +- vfs/README.md | 19 ++++++++++++++++--- vfs/README.tpl | 7 +++++++ vfs/src/lib.rs | 26 +++++++++++++++++++++++++- 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 vfs/README.tpl diff --git a/vfs/Cargo.toml b/vfs/Cargo.toml index 38b7cbfd..96be15c7 100644 --- a/vfs/Cargo.toml +++ b/vfs/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Lucien Greathouse "] edition = "2018" readme = "README.md" license = "MIT" -homepage = "https://github.com/rojo-rbx/rojo" +homepage = "https://github.com/rojo-rbx/rojo/tree/master/vfs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/vfs/README.md b/vfs/README.md index 981daa26..4659ce3d 100644 --- a/vfs/README.md +++ b/vfs/README.md @@ -1,5 +1,18 @@ -# [vfs] -Name pending. Implementation of a virtual filesystem with a configurable backend and file watching. +# vfs +Implementation of a virtual filesystem with a configurable backend and file watching. + +memofs is currently an unstable minimum viable library. Its primary consumer is [Rojo](https://github.com/rojo-rbx/rojo), a build system for Roblox. + +### Current Features +* API similar to `std::fs` +* Configurable backends + * `StdBackend`, which uses `std::fs` and the `notify` crate + * `NoopBackend`, which always throws errors + * `InMemoryFs`, a simple in-memory filesystem useful for testing + +### Future Features +* Hash-based hierarchical memoization keys (hence the name) +* Configurable caching (write-through, write-around, write-back) ## License -[vfs] is available under the terms of the MIT license. See [LICENSE.txt](LICENSE.txt) or for more details. \ No newline at end of file +memofs is available under the terms of the MIT license. See [LICENSE.txt](LICENSE.txt) or for more details. diff --git a/vfs/README.tpl b/vfs/README.tpl new file mode 100644 index 00000000..b8129a25 --- /dev/null +++ b/vfs/README.tpl @@ -0,0 +1,7 @@ +# {{crate}} +[![Crates.io](https://img.shields.io/crates/v/memofs.svg)](https://crates.io/crates/memofs) + +{{readme}} + +## License +memofs is available under the terms of the MIT license. See [LICENSE.txt](LICENSE.txt) or for more details. \ No newline at end of file diff --git a/vfs/src/lib.rs b/vfs/src/lib.rs index 8aede061..cbdc63da 100644 --- a/vfs/src/lib.rs +++ b/vfs/src/lib.rs @@ -1,3 +1,20 @@ +/*! +Implementation of a virtual filesystem with a configurable backend and file watching. + +memofs is currently an unstable minimum viable library. Its primary consumer is [Rojo](https://github.com/rojo-rbx/rojo), a build system for Roblox. + +## Current Features +* API similar to `std::fs` +* Configurable backends + * `StdBackend`, which uses `std::fs` and the `notify` crate + * `NoopBackend`, which always throws errors + * `InMemoryFs`, a simple in-memory filesystem useful for testing + +## Future Features +* Hash-based hierarchical memoization keys (hence the name) +* Configurable caching (write-through, write-around, write-back) +*/ + mod in_memory_fs; mod noop_backend; mod snapshot; @@ -178,6 +195,10 @@ impl VfsInner { } /// A virtual filesystem with a configurable backend. +/// +/// All operations on the Vfs take a lock on an internal backend. For performing +/// large batches of operations, it might be more performant to call `lock()` +/// and use [`VfsLock`](struct.VfsLock.html) instead. pub struct Vfs { inner: Mutex, } @@ -199,6 +220,7 @@ impl Vfs { } } + /// Manually lock the Vfs, useful for large batches of operations. pub fn lock(&self) -> VfsLock<'_> { VfsLock { inner: self.inner.lock().unwrap(), @@ -286,7 +308,9 @@ impl Vfs { } } -/// A locked handle to a `Vfs`, created by `Vfs::lock`. +/// A locked handle to a [`Vfs`](struct.Vfs.html), created by `Vfs::lock`. +/// +/// Implements roughly the same API as [`Vfs`](struct.Vfs.html). pub struct VfsLock<'a> { inner: MutexGuard<'a, VfsInner>, } From 5be4175ac3ddca71b88a93ca2a36dfdc566e0e3f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Mar 2020 18:05:31 -0700 Subject: [PATCH 0971/1504] Rename vfs -> memofs across the codebase --- Cargo.lock | 18 +++++++++--------- Cargo.toml | 6 +++--- {vfs => memofs}/Cargo.toml | 4 ++-- {vfs => memofs}/LICENSE.txt | 0 {vfs => memofs}/README.md | 0 {vfs => memofs}/README.tpl | 0 {vfs => memofs}/src/in_memory_fs.rs | 0 {vfs => memofs}/src/lib.rs | 6 ++++-- {vfs => memofs}/src/noop_backend.rs | 0 {vfs => memofs}/src/snapshot.rs | 0 {vfs => memofs}/src/std_backend.rs | 0 src/change_processor.rs | 2 +- src/cli/build.rs | 2 +- src/cli/serve.rs | 2 +- src/cli/upload.rs | 2 +- src/common_setup.rs | 2 +- src/serve_session.rs | 4 ++-- src/snapshot_middleware/csv.rs | 2 +- src/snapshot_middleware/dir.rs | 4 ++-- src/snapshot_middleware/json_model.rs | 4 ++-- src/snapshot_middleware/lua.rs | 4 ++-- src/snapshot_middleware/middleware.rs | 2 +- src/snapshot_middleware/mod.rs | 2 +- src/snapshot_middleware/project.rs | 4 ++-- src/snapshot_middleware/rbxlx.rs | 2 +- src/snapshot_middleware/rbxm.rs | 4 ++-- src/snapshot_middleware/rbxmx.rs | 4 ++-- src/snapshot_middleware/txt.rs | 4 ++-- 28 files changed, 43 insertions(+), 41 deletions(-) rename {vfs => memofs}/Cargo.toml (78%) rename {vfs => memofs}/LICENSE.txt (100%) rename {vfs => memofs}/README.md (100%) rename {vfs => memofs}/README.tpl (100%) rename {vfs => memofs}/src/in_memory_fs.rs (100%) rename {vfs => memofs}/src/lib.rs (99%) rename {vfs => memofs}/src/noop_backend.rs (100%) rename {vfs => memofs}/src/snapshot.rs (100%) rename {vfs => memofs}/src/std_backend.rs (100%) diff --git a/Cargo.lock b/Cargo.lock index 42982f53..9cf91fc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -922,6 +922,14 @@ dependencies = [ "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "memofs" +version = "0.1.0" +dependencies = [ + "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "mime" version = "0.3.16" @@ -1670,6 +1678,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", + "memofs 0.1.0", "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1691,7 +1700,6 @@ dependencies = [ "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "vfs 0.1.0", "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2365,14 +2373,6 @@ name = "version_check" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "vfs" -version = "0.1.0" -dependencies = [ - "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "walkdir" version = "2.3.1" diff --git a/Cargo.toml b/Cargo.toml index 6b9d9837..11c606fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,14 +32,14 @@ members = [ "rojo-test", "rojo-insta-ext", "clibrojo", - "vfs", + "memofs", ] default-members = [ ".", "rojo-test", "rojo-insta-ext", - "vfs", + "memofs", ] [lib] @@ -82,7 +82,7 @@ structopt = "0.3.5" termcolor = "1.0.5" tokio = "0.1.22" uuid = { version = "0.8.1", features = ["v4", "serde"] } -vfs = { path = "vfs" } +memofs = { path = "memofs" } [target.'cfg(windows)'.dependencies] winreg = "0.6.2" diff --git a/vfs/Cargo.toml b/memofs/Cargo.toml similarity index 78% rename from vfs/Cargo.toml rename to memofs/Cargo.toml index 96be15c7..09912fb4 100644 --- a/vfs/Cargo.toml +++ b/memofs/Cargo.toml @@ -1,11 +1,11 @@ [package] -name = "vfs" +name = "memofs" version = "0.1.0" authors = ["Lucien Greathouse "] edition = "2018" readme = "README.md" license = "MIT" -homepage = "https://github.com/rojo-rbx/rojo/tree/master/vfs" +homepage = "https://github.com/rojo-rbx/rojo/tree/master/memofs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/vfs/LICENSE.txt b/memofs/LICENSE.txt similarity index 100% rename from vfs/LICENSE.txt rename to memofs/LICENSE.txt diff --git a/vfs/README.md b/memofs/README.md similarity index 100% rename from vfs/README.md rename to memofs/README.md diff --git a/vfs/README.tpl b/memofs/README.tpl similarity index 100% rename from vfs/README.tpl rename to memofs/README.tpl diff --git a/vfs/src/in_memory_fs.rs b/memofs/src/in_memory_fs.rs similarity index 100% rename from vfs/src/in_memory_fs.rs rename to memofs/src/in_memory_fs.rs diff --git a/vfs/src/lib.rs b/memofs/src/lib.rs similarity index 99% rename from vfs/src/lib.rs rename to memofs/src/lib.rs index cbdc63da..a04bf71d 100644 --- a/vfs/src/lib.rs +++ b/memofs/src/lib.rs @@ -1,7 +1,9 @@ /*! -Implementation of a virtual filesystem with a configurable backend and file watching. +Implementation of a virtual filesystem with a configurable backend and file +watching. -memofs is currently an unstable minimum viable library. Its primary consumer is [Rojo](https://github.com/rojo-rbx/rojo), a build system for Roblox. +memofs is currently an unstable minimum viable library. Its primary consumer is +[Rojo](https://github.com/rojo-rbx/rojo), a build system for Roblox. ## Current Features * API similar to `std::fs` diff --git a/vfs/src/noop_backend.rs b/memofs/src/noop_backend.rs similarity index 100% rename from vfs/src/noop_backend.rs rename to memofs/src/noop_backend.rs diff --git a/vfs/src/snapshot.rs b/memofs/src/snapshot.rs similarity index 100% rename from vfs/src/snapshot.rs rename to memofs/src/snapshot.rs diff --git a/vfs/src/std_backend.rs b/memofs/src/std_backend.rs similarity index 100% rename from vfs/src/std_backend.rs rename to memofs/src/std_backend.rs diff --git a/src/change_processor.rs b/src/change_processor.rs index 0351f48c..50cdc949 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -5,8 +5,8 @@ use std::{ use crossbeam_channel::{select, Receiver, RecvError, Sender}; use jod_thread::JoinHandle; +use memofs::{IoResultExt, Vfs, VfsEvent}; use rbx_dom_weak::{RbxId, RbxValue}; -use vfs::{IoResultExt, Vfs, VfsEvent}; use crate::{ message_queue::MessageQueue, diff --git a/src/cli/build.rs b/src/cli/build.rs index 901bd3d6..11fc7bd7 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -3,9 +3,9 @@ use std::{ io::{self, BufWriter, Write}, }; +use memofs::Vfs; use snafu::{ResultExt, Snafu}; use tokio::runtime::Runtime; -use vfs::Vfs; use crate::{ cli::BuildCommand, project::ProjectError, serve_session::ServeSession, snapshot::RojoTree, diff --git a/src/cli/serve.rs b/src/cli/serve.rs index 6a04338c..429ce23b 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -3,9 +3,9 @@ use std::{ sync::Arc, }; +use memofs::Vfs; use snafu::Snafu; use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; -use vfs::Vfs; use crate::{cli::ServeCommand, serve_session::ServeSession, web::LiveServer}; diff --git a/src/cli/upload.rs b/src/cli/upload.rs index f6a7b31b..f6f847af 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -1,6 +1,6 @@ +use memofs::Vfs; use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}; use snafu::{ResultExt, Snafu}; -use vfs::Vfs; use crate::{auth_cookie::get_auth_cookie, cli::UploadCommand, common_setup}; diff --git a/src/common_setup.rs b/src/common_setup.rs index 4ae37d79..7de22c06 100644 --- a/src/common_setup.rs +++ b/src/common_setup.rs @@ -3,8 +3,8 @@ use std::path::Path; +use memofs::Vfs; use rbx_dom_weak::RbxInstanceProperties; -use vfs::Vfs; use crate::{ project::Project, diff --git a/src/serve_session.rs b/src/serve_session.rs index bcaf6c14..8d737733 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -6,7 +6,7 @@ use std::{ }; use crossbeam_channel::Sender; -use vfs::Vfs; +use memofs::Vfs; use crate::{ change_processor::ChangeProcessor, @@ -190,9 +190,9 @@ mod serve_session { use std::{path::PathBuf, time::Duration}; use maplit::hashmap; + use memofs::{InMemoryFs, VfsEvent, VfsSnapshot}; use rojo_insta_ext::RedactionMap; use tokio::{runtime::Runtime, timer::Timeout}; - use vfs::{InMemoryFs, VfsEvent, VfsSnapshot}; use crate::tree_view::view_tree; diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 93882e22..a819ba44 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -1,9 +1,9 @@ use std::{collections::BTreeMap, path::Path}; use maplit::hashmap; +use memofs::{IoResultExt, Vfs}; use rbx_dom_weak::RbxValue; use serde::Serialize; -use vfs::{IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 22d1ed64..9ff6d9a3 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -1,6 +1,6 @@ use std::path::Path; -use vfs::{DirEntry, IoResultExt, Vfs}; +use memofs::{DirEntry, IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; @@ -87,7 +87,7 @@ mod test { use super::*; use maplit::hashmap; - use vfs::{InMemoryFs, VfsSnapshot}; + use memofs::{InMemoryFs, VfsSnapshot}; #[test] fn empty_folder() { diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 2f9ca5e8..8633b818 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -1,9 +1,9 @@ use std::{borrow::Cow, collections::HashMap, path::Path}; +use memofs::Vfs; use rbx_dom_weak::UnresolvedRbxValue; use rbx_reflection::try_resolve_value; use serde::Deserialize; -use vfs::Vfs; use crate::snapshot::{InstanceContext, InstanceSnapshot}; @@ -133,7 +133,7 @@ impl JsonModelCore { mod test { use super::*; - use vfs::{InMemoryFs, VfsSnapshot}; + use memofs::{InMemoryFs, VfsSnapshot}; #[test] fn model_from_vfs() { diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index fba6b04b..decd6144 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -1,8 +1,8 @@ use std::{path::Path, str}; use maplit::hashmap; +use memofs::{IoResultExt, Vfs}; use rbx_dom_weak::RbxValue; -use vfs::{IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; @@ -135,7 +135,7 @@ fn snapshot_init( mod test { use super::*; - use vfs::{InMemoryFs, VfsSnapshot}; + use memofs::{InMemoryFs, VfsSnapshot}; #[test] fn module_from_vfs() { diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index baf28de2..18e79439 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -1,6 +1,6 @@ use std::path::Path; -use vfs::Vfs; +use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceSnapshot}; diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 24e3611e..77dca702 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -21,7 +21,7 @@ pub use self::error::*; use std::path::Path; -use vfs::Vfs; +use memofs::Vfs; use self::middleware::{SnapshotInstanceResult, SnapshotMiddleware}; use self::{ diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index ad16aede..e2d0c3a7 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -1,7 +1,7 @@ use std::{borrow::Cow, collections::HashMap, path::Path}; +use memofs::{IoResultExt, Vfs}; use rbx_reflection::try_resolve_value; -use vfs::{IoResultExt, Vfs}; use crate::{ project::{Project, ProjectNode}, @@ -211,7 +211,7 @@ mod test { use super::*; use maplit::hashmap; - use vfs::{InMemoryFs, VfsSnapshot}; + use memofs::{InMemoryFs, VfsSnapshot}; #[test] fn project_from_folder() { diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs index 16c7f4ea..94cc942d 100644 --- a/src/snapshot_middleware/rbxlx.rs +++ b/src/snapshot_middleware/rbxlx.rs @@ -1,6 +1,6 @@ use std::path::Path; -use vfs::Vfs; +use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index f14afdfd..319d316a 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, path::Path}; +use memofs::Vfs; use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; -use vfs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; @@ -59,7 +59,7 @@ impl SnapshotMiddleware for SnapshotRbxm { mod test { use super::*; - use vfs::{InMemoryFs, VfsSnapshot}; + use memofs::{InMemoryFs, VfsSnapshot}; #[test] fn model_from_vfs() { diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index c697336d..90193b62 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -1,6 +1,6 @@ use std::path::Path; -use vfs::Vfs; +use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; @@ -54,7 +54,7 @@ impl SnapshotMiddleware for SnapshotRbxmx { mod test { use super::*; - use vfs::{InMemoryFs, VfsSnapshot}; + use memofs::{InMemoryFs, VfsSnapshot}; #[test] fn plain_folder() { diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 9ee73b0b..41502d55 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -1,8 +1,8 @@ use std::{path::Path, str}; use maplit::hashmap; +use memofs::{IoResultExt, Vfs}; use rbx_dom_weak::RbxValue; -use vfs::{IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; @@ -65,7 +65,7 @@ impl SnapshotMiddleware for SnapshotTxt { mod test { use super::*; - use vfs::{InMemoryFs, VfsSnapshot}; + use memofs::{InMemoryFs, VfsSnapshot}; #[test] fn instance_from_vfs() { From 6191b6371d7d8e31d3101dc87090b2d81c854251 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Mar 2020 18:09:04 -0700 Subject: [PATCH 0972/1504] Update using cargo-readme --- memofs/README.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/memofs/README.md b/memofs/README.md index 4659ce3d..d04b8ff6 100644 --- a/memofs/README.md +++ b/memofs/README.md @@ -1,7 +1,11 @@ -# vfs -Implementation of a virtual filesystem with a configurable backend and file watching. +# memofs +[![Crates.io](https://img.shields.io/crates/v/memofs.svg)](https://crates.io/crates/memofs) -memofs is currently an unstable minimum viable library. Its primary consumer is [Rojo](https://github.com/rojo-rbx/rojo), a build system for Roblox. +Implementation of a virtual filesystem with a configurable backend and file +watching. + +memofs is currently an unstable minimum viable library. Its primary consumer is +[Rojo](https://github.com/rojo-rbx/rojo), a build system for Roblox. ### Current Features * API similar to `std::fs` From 10ba74c21e363fa4f11342beb55f8ea13b5bbc6c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Mar 2020 18:11:39 -0700 Subject: [PATCH 0973/1504] memofs: Add description --- memofs/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/memofs/Cargo.toml b/memofs/Cargo.toml index 09912fb4..a583486f 100644 --- a/memofs/Cargo.toml +++ b/memofs/Cargo.toml @@ -1,5 +1,6 @@ [package] name = "memofs" +description = "Virtual filesystem with configurable backends." version = "0.1.0" authors = ["Lucien Greathouse "] edition = "2018" From ca151b434e905dbeb0c4923935495f3f538bcc74 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Mar 2020 18:13:34 -0700 Subject: [PATCH 0974/1504] Update memofs dependency --- Cargo.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 11c606fa..e3da831a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -55,6 +55,8 @@ name = "build" harness = false [dependencies] +memofs = { version = "0.1.0", path = "memofs" } + crossbeam-channel = "0.4.0" csv = "1.1.1" env_logger = "0.7.1" @@ -82,7 +84,6 @@ structopt = "0.3.5" termcolor = "1.0.5" tokio = "0.1.22" uuid = { version = "0.8.1", features = ["v4", "serde"] } -memofs = { path = "memofs" } [target.'cfg(windows)'.dependencies] winreg = "0.6.2" From c4375074429cf9b0b1562026322fe0073c239176 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Mar 2020 18:15:06 -0700 Subject: [PATCH 0975/1504] Update changelogs --- CHANGELOG.md | 1 + memofs/CHANGELOG.md | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 memofs/CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 8419fdaa..82e495bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased Changes for 0.6.x * Added `--watch` argument to `rojo build`. ([#284](https://github.com/rojo-rbx/rojo/pull/284)) * Added dark theme support to plugin. ([#241](https://github.com/rojo-rbx/rojo/issues/241)) +* Simplified filesystem access code dramatically. ## [0.6.0 Alpha 2](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.2) (March 6, 2020) * Fixed `rojo upload` command always uploading models. diff --git a/memofs/CHANGELOG.md b/memofs/CHANGELOG.md new file mode 100644 index 00000000..a75397e1 --- /dev/null +++ b/memofs/CHANGELOG.md @@ -0,0 +1,6 @@ +# memofs Changelog + +## Unreleased Changes + +## 0.1.0 (2020-03-10) +* Initial release \ No newline at end of file From e8e3b7b98505dfd1ab3950053c1358a709f16a88 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Mar 2020 20:34:12 -0700 Subject: [PATCH 0976/1504] plugin: Fix dark theme when resized to be wide --- plugin/src/Components/Panel.lua | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugin/src/Components/Panel.lua b/plugin/src/Components/Panel.lua index 9a19ecfc..f1961702 100644 --- a/plugin/src/Components/Panel.lua +++ b/plugin/src/Components/Panel.lua @@ -17,7 +17,8 @@ function Panel:render() return Theme.with(function(theme) return e("Frame", { Size = UDim2.new(1, 0, 1, 0), - BackgroundTransparency = 1, + BackgroundColor3 = theme.Background1, + BorderSizePixel = 1, }, { Layout = Roact.createElement("UIListLayout", { HorizontalAlignment = Enum.HorizontalAlignment.Center, @@ -26,8 +27,7 @@ function Panel:render() Body = e("Frame", { Size = UDim2.new(0, 360, 1, -32), - BackgroundColor3 = theme.Background1, - BorderSizePixel = 0, + BackgroundTransparency = 1, }, self.props[Roact.Children]), Footer = e(RojoFooter), From fe0ca280a1d517ad04f910a5fd6cb355353931d4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 10 Mar 2020 23:52:55 -0700 Subject: [PATCH 0977/1504] Update disabled CSV middleware test --- src/snapshot_middleware/csv.rs | 50 +++++++++++++++++++--------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index a819ba44..f54e4a51 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -131,52 +131,58 @@ fn convert_localization_csv(contents: &[u8]) -> String { serde_json::to_string(&entries).expect("Could not encode JSON for localization table") } -#[cfg(all(test, feature = "FIXME"))] +#[cfg(test)] mod test { use super::*; - use crate::vfs::{NoopFetcher, VfsDebug, VfsSnapshot}; - use insta::assert_yaml_snapshot; + use memofs::{InMemoryFs, VfsSnapshot}; #[test] fn csv_from_vfs() { - let mut vfs = Vfs::new(NoopFetcher); - let file = VfsSnapshot::file( - r#" + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo.csv", + VfsSnapshot::file( + r#" Key,Source,Context,Example,es Ack,Ack!,,An exclamation of despair,¡Ay!"#, - ); + ), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo.csv", file); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo.csv").unwrap(); let instance_snapshot = - SnapshotCsv::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotCsv::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo.csv")) .unwrap() .unwrap(); - assert_yaml_snapshot!(instance_snapshot); + insta::assert_yaml_snapshot!(instance_snapshot); } #[test] fn csv_with_meta() { - let mut vfs = Vfs::new(NoopFetcher); - let file = VfsSnapshot::file( - r#" + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo.csv", + VfsSnapshot::file( + r#" Key,Source,Context,Example,es Ack,Ack!,,An exclamation of despair,¡Ay!"#, - ); - let meta = VfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#); + ), + ) + .unwrap(); + imfs.load_snapshot( + "/foo.meta.json", + VfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#), + ) + .unwrap(); - vfs.debug_load_snapshot("/foo.csv", file); - vfs.debug_load_snapshot("/foo.meta.json", meta); + let mut vfs = Vfs::new(imfs); - let entry = vfs.get("/foo.csv").unwrap(); let instance_snapshot = - SnapshotCsv::from_vfs(&InstanceContext::default(), &mut vfs, &entry) + SnapshotCsv::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo.csv")) .unwrap() .unwrap(); - - assert_yaml_snapshot!(instance_snapshot); } } From eb8964e1d18b187402bbaa57602c7c40f08f6f19 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 12 Mar 2020 15:42:56 -0700 Subject: [PATCH 0978/1504] Improve panic messaging and process behavior. - Replaced main() to use custom panic hook - Updated log formatting - Switched to panic=abort, since we don't need to unwind now. - Process will now abort if any thread panics. --- CHANGELOG.md | 4 ++ Cargo.lock | 1 + Cargo.toml | 7 +++ src/bin.rs | 120 ++++++++++++++++++++++++++++++--------------------- 4 files changed, 84 insertions(+), 48 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82e495bc..3a77d67b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,10 @@ * Added `--watch` argument to `rojo build`. ([#284](https://github.com/rojo-rbx/rojo/pull/284)) * Added dark theme support to plugin. ([#241](https://github.com/rojo-rbx/rojo/issues/241)) * Simplified filesystem access code dramatically. +* Improved error reporting and logging across the board. + * Log messages have a less noisy prefix. + * Any thread panicking now causes Rojo to abort instead of existing as a zombie. + * Errors now have a list of causes, helping make many errors more clear. ## [0.6.0 Alpha 2](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.2) (March 6, 2020) * Fixed `rojo upload` command always uploading models. diff --git a/Cargo.lock b/Cargo.lock index 9cf91fc1..133c55bb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1665,6 +1665,7 @@ dependencies = [ name = "rojo" version = "0.6.0-alpha.2" dependencies = [ + "backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", "criterion 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index e3da831a..36df1fbb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,6 +15,12 @@ exclude = [ "/test-projects/**", ] +[profile.dev] +panic = "abort" + +[profile.release] +panic = "abort" + [features] default = [] @@ -56,6 +62,7 @@ harness = false [dependencies] memofs = { version = "0.1.0", path = "memofs" } +backtrace = "0.3" crossbeam-channel = "0.4.0" csv = "1.1.1" diff --git a/src/bin.rs b/src/bin.rs index 1b745ded..3d3189e1 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -1,49 +1,10 @@ -use std::{error::Error, panic, process}; +use std::{env, error::Error, panic, process}; -use log::error; +use backtrace::Backtrace; use structopt::StructOpt; use librojo::cli::{self, Options, Subcommand}; -fn main() { - let options = Options::from_args(); - - { - let log_filter = match options.verbosity { - 0 => "warn", - 1 => "warn,librojo=info", - 2 => "warn,librojo=trace", - _ => "trace", - }; - - let log_env = env_logger::Env::default().default_filter_or(log_filter); - - env_logger::Builder::from_env(log_env) - .format_timestamp(None) - .init(); - } - - let panic_result = panic::catch_unwind(|| { - if let Err(err) = run(options.subcommand) { - log::error!("{}", err); - process::exit(1); - } - }); - - if let Err(error) = panic_result { - let message = match error.downcast_ref::<&str>() { - Some(message) => message.to_string(), - None => match error.downcast_ref::() { - Some(message) => message.clone(), - None => "".to_string(), - }, - }; - - show_crash_message(&message); - process::exit(1); - } -} - fn run(subcommand: Subcommand) -> Result<(), Box> { match subcommand { Subcommand::Init(init_options) => cli::init(init_options)?, @@ -55,11 +16,74 @@ fn run(subcommand: Subcommand) -> Result<(), Box> { Ok(()) } -fn show_crash_message(message: &str) { - error!("Rojo crashed!"); - error!("This is a bug in Rojo."); - error!(""); - error!("Please consider filing a bug: https://github.com/rojo-rbx/rojo/issues"); - error!(""); - error!("Details: {}", message); +fn main() { + panic::set_hook(Box::new(|panic_info| { + // PanicInfo's payload is usually a &'static str or String. + // See: https://doc.rust-lang.org/beta/std/panic/struct.PanicInfo.html#method.payload + let message = match panic_info.payload().downcast_ref::<&str>() { + Some(message) => message.to_string(), + None => match panic_info.payload().downcast_ref::() { + Some(message) => message.clone(), + None => "".to_string(), + }, + }; + + log::error!("Rojo crashed!"); + log::error!("This is probably a Rojo bug."); + log::error!(""); + log::error!("Please consider filing an issue: https://github.com/rojo-rbx/rojo/issues"); + log::error!(""); + log::error!("Details: {}", message); + + if let Some(location) = panic_info.location() { + log::error!("in file {} on line {}", location.file(), location.line()); + } + + // When using the backtrace crate, we need to check the RUST_BACKTRACE + // environment variable ourselves. Once we switch to the (currently + // unstable) std::backtrace module, we won't need to do this anymore. + let should_backtrace = env::var("RUST_BACKTRACE") + .map(|var| var == "1") + .unwrap_or(false); + + if should_backtrace { + eprintln!("{:?}", Backtrace::new()); + } else { + eprintln!( + "note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace." + ); + } + + process::exit(1); + })); + + let options = Options::from_args(); + + let log_filter = match options.verbosity { + 0 => "warn", + 1 => "warn,librojo=info", + 2 => "warn,librojo=trace", + _ => "trace", + }; + + let log_env = env_logger::Env::default().default_filter_or(log_filter); + + env_logger::Builder::from_env(log_env) + .format_module_path(false) + .format_timestamp(None) + // Indent following lines equal to the log level label, like `[ERROR] ` + .format_indent(Some(8)) + .init(); + + if let Err(err) = run(options.subcommand) { + log::error!("{}", err); + + let mut current_err: &dyn Error = &*err; + while let Some(source) = current_err.source() { + log::error!(" caused by {}", err); + current_err = &*source; + } + + process::exit(1); + } } From 2a31937b81c70f488183f75fa687954f6642f2e7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 12 Mar 2020 15:48:30 -0700 Subject: [PATCH 0979/1504] Use CARGO_PKG_REPOSITORY instead of hard-coded URL --- src/bin.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/bin.rs b/src/bin.rs index 3d3189e1..ff31802b 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -31,7 +31,10 @@ fn main() { log::error!("Rojo crashed!"); log::error!("This is probably a Rojo bug."); log::error!(""); - log::error!("Please consider filing an issue: https://github.com/rojo-rbx/rojo/issues"); + log::error!( + "Please consider filing an issue: {}/issues", + env!("CARGO_PKG_REPOSITORY") + ); log::error!(""); log::error!("Details: {}", message); From 255bf439d3c2d2e9e7cba251808a03c245ada2e6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 12 Mar 2020 16:02:19 -0700 Subject: [PATCH 0980/1504] Add 'rojo doc' command --- CHANGELOG.md | 1 + Cargo.lock | 10 ++++++++++ Cargo.toml | 3 ++- src/bin.rs | 1 + src/cli/doc.rs | 26 ++++++++++++++++++++++++++ src/cli/mod.rs | 5 +++++ 6 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 src/cli/doc.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 3a77d67b..35ff751c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased Changes for 0.6.x * Added `--watch` argument to `rojo build`. ([#284](https://github.com/rojo-rbx/rojo/pull/284)) * Added dark theme support to plugin. ([#241](https://github.com/rojo-rbx/rojo/issues/241)) +* Added the `rojo doc` command, which opens Rojo's documentation in your browser. * Simplified filesystem access code dramatically. * Improved error reporting and logging across the board. * Log messages have a less noisy prefix. diff --git a/Cargo.lock b/Cargo.lock index 133c55bb..18ede8d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1073,6 +1073,14 @@ name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "opener" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "openssl" version = "0.10.28" @@ -1681,6 +1689,7 @@ dependencies = [ "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", "memofs 0.1.0", "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "opener 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_binary 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2647,6 +2656,7 @@ dependencies = [ "checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" "checksum oorandom 11.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebcec7c9c2a95cacc7cd0ecb89d8a8454eca13906f6deb55258ffff0adeb9405" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" +"checksum opener 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13117407ca9d0caf3a0e74f97b490a7e64c0ae3aa90a8b7085544d0c37b6f3ae" "checksum openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)" = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" "checksum openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)" = "1024c0a59774200a555087a6da3f253a9095a5f344e353b212ac4c8b8e450986" diff --git a/Cargo.toml b/Cargo.toml index 36df1fbb..5e1fd971 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,8 +62,8 @@ harness = false [dependencies] memofs = { version = "0.1.0", path = "memofs" } -backtrace = "0.3" +backtrace = "0.3" crossbeam-channel = "0.4.0" csv = "1.1.1" env_logger = "0.7.1" @@ -76,6 +76,7 @@ lazy_static = "1.4.0" log = "0.4.8" maplit = "1.0.1" notify = "4.0.14" +opener = "0.4.1" rbx_binary = "0.5.0" rbx_dom_weak = "1.10.1" rbx_reflection = "3.3.408" diff --git a/src/bin.rs b/src/bin.rs index ff31802b..f32c7bff 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -11,6 +11,7 @@ fn run(subcommand: Subcommand) -> Result<(), Box> { Subcommand::Serve(serve_options) => cli::serve(serve_options)?, Subcommand::Build(build_options) => cli::build(build_options)?, Subcommand::Upload(upload_options) => cli::upload(upload_options)?, + Subcommand::Doc => cli::doc()?, } Ok(()) diff --git a/src/cli/doc.rs b/src/cli/doc.rs new file mode 100644 index 00000000..f10cc8f5 --- /dev/null +++ b/src/cli/doc.rs @@ -0,0 +1,26 @@ +use opener::{open, OpenError}; +use snafu::Snafu; + +#[derive(Debug, Snafu)] +pub struct DocError(Error); + +#[derive(Debug, Snafu)] +enum Error { + Open { source: OpenError }, +} + +impl From for Error { + fn from(source: OpenError) -> Self { + Error::Open { source } + } +} + +pub fn doc() -> Result<(), DocError> { + doc_inner()?; + Ok(()) +} + +fn doc_inner() -> Result<(), Error> { + open("https://rojo.space/docs")?; + Ok(()) +} diff --git a/src/cli/mod.rs b/src/cli/mod.rs index d0048116..40179a32 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,6 +1,7 @@ //! Defines Rojo's CLI through structopt types. mod build; +mod doc; mod init; mod serve; mod upload; @@ -17,6 +18,7 @@ use std::{ use structopt::StructOpt; pub use self::build::*; +pub use self::doc::*; pub use self::init::*; pub use self::serve::*; pub use self::upload::*; @@ -48,6 +50,9 @@ pub enum Subcommand { /// Generates a place or model file out of the project and uploads it to Roblox. Upload(UploadCommand), + + /// Open Rojo's documentation in your browser. + Doc, } /// Initializes a new Rojo project. From c1bf9d9dfcaae07fa5b3404de3af94eae09574a9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 12 Mar 2020 19:39:27 -0700 Subject: [PATCH 0981/1504] Update duplicate env_logger dep --- Cargo.lock | 15 +-------------- rojo-test/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 18ede8d7..e1d9dd82 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -434,18 +434,6 @@ dependencies = [ "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "env_logger" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "env_logger" version = "0.7.1" @@ -1726,7 +1714,7 @@ dependencies = [ name = "rojo-test" version = "0.1.0" dependencies = [ - "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "insta 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2584,7 +2572,6 @@ dependencies = [ "checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" "checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" "checksum encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" -"checksum env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" "checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" "checksum error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd" "checksum failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index d6417764..85dcb8cd 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -11,7 +11,7 @@ default = [] unstable_glob_ignore_paths = [] [dependencies] -env_logger = "0.6.2" +env_logger = "0.7.1" insta = { version = "0.13.1", features = ["redactions"] } log = "0.4.8" paste = "0.1.5" From f7c0f33eb5eca69fb7236611fb3f1c0ce4fdb6b7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Mar 2020 19:33:43 -0700 Subject: [PATCH 0982/1504] Add brand new rojo init command --- CHANGELOG.md | 1 + assets/default-model.lua | 5 ++ assets/model.project.json | 6 ++ assets/place.project.json | 77 +++++++++++++------- src/cli/init.rs | 147 ++++++++++++++++++++++++++++++++++++-- 5 files changed, 205 insertions(+), 31 deletions(-) create mode 100644 assets/default-model.lua create mode 100644 assets/model.project.json diff --git a/CHANGELOG.md b/CHANGELOG.md index 35ff751c..a01c48f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased Changes for 0.6.x * Added `--watch` argument to `rojo build`. ([#284](https://github.com/rojo-rbx/rojo/pull/284)) * Added dark theme support to plugin. ([#241](https://github.com/rojo-rbx/rojo/issues/241)) +* Added a revamped `rojo init` command, which will now create more complete projects. * Added the `rojo doc` command, which opens Rojo's documentation in your browser. * Simplified filesystem access code dramatically. * Improved error reporting and logging across the board. diff --git a/assets/default-model.lua b/assets/default-model.lua new file mode 100644 index 00000000..41faf217 --- /dev/null +++ b/assets/default-model.lua @@ -0,0 +1,5 @@ +return { + hello = function() + print("Hello world, from {project_name}!") + end, +} \ No newline at end of file diff --git a/assets/model.project.json b/assets/model.project.json new file mode 100644 index 00000000..e7bb5891 --- /dev/null +++ b/assets/model.project.json @@ -0,0 +1,6 @@ +{ + "name": "{project_name}", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/assets/place.project.json b/assets/place.project.json index 4cf32314..fc3f1ec3 100644 --- a/assets/place.project.json +++ b/assets/place.project.json @@ -1,39 +1,36 @@ { - "name": "[placeholder]", + "name": "{project_name}", "tree": { "$className": "DataModel", - "HttpService": { - "$className": "HttpService", - "$properties": { - "HttpEnabled": true - } - }, - "Lighting": { - "$className": "Lighting", - "$properties": { - "Ambient": [ - 0, - 0, - 0 - ], - "Brightness": 2, - "GlobalShadows": true, - "Outlines": false, - "Technology": "Voxel" - } - }, + "ReplicatedStorage": { "$className": "ReplicatedStorage", - "Source": { - "$path": "src" + + "Common": { + "$path": "src/common" } }, - "SoundService": { - "$className": "SoundService", - "$properties": { - "RespectFilteringEnabled": true + + "ServerScriptService": { + "$className": "ServerScriptService", + + "Server": { + "$path": "src/server" } }, + + "StarterPlayer": { + "$className": "StarterPlayer", + + "StarterPlayerScripts": { + "$className": "StarterPlayerScripts", + + "Client": { + "$path": "src/client" + } + } + }, + "Workspace": { "$className": "Workspace", "$properties": { @@ -61,6 +58,32 @@ ] } } + }, + "Lighting": { + "$className": "Lighting", + "$properties": { + "Ambient": [ + 0, + 0, + 0 + ], + "Brightness": 2, + "GlobalShadows": true, + "Outlines": false, + "Technology": "Voxel" + } + }, + "SoundService": { + "$className": "SoundService", + "$properties": { + "RespectFilteringEnabled": true + } + }, + "HttpService": { + "$className": "HttpService", + "$properties": { + "HttpEnabled": true + } } } } \ No newline at end of file diff --git a/src/cli/init.rs b/src/cli/init.rs index c27360b1..5fbbdafa 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -1,17 +1,156 @@ +use std::{ + fs::{self, OpenOptions}, + io::{self, Write}, + path::Path, +}; + use snafu::Snafu; -use crate::cli::InitCommand; +use crate::cli::{InitCommand, InitKind}; + +static DEFAULT_PLACE_PROJECT: &str = include_str!("../../assets/place.project.json"); + +static DEFAULT_MODEL_PROJECT: &str = include_str!("../../assets/model.project.json"); +static DEFAULT_MODEL_INIT: &str = include_str!("../../assets/default-model.lua"); #[derive(Debug, Snafu)] pub struct InitError(Error); #[derive(Debug, Snafu)] -enum Error {} +enum Error { + #[snafu(display("A project file named default.project.json already exists in this folder"))] + AlreadyExists, + + #[snafu(display("I/O error"))] + Io { source: io::Error }, +} + +impl From for Error { + fn from(source: io::Error) -> Self { + Self::Io { source } + } +} pub fn init(options: InitCommand) -> Result<(), InitError> { Ok(init_inner(options)?) } -fn init_inner(_options: InitCommand) -> Result<(), Error> { - unimplemented!("init command"); +fn init_inner(options: InitCommand) -> Result<(), Error> { + let base_path = options.absolute_path(); + let canonical = fs::canonicalize(&base_path)?; + let project_name = canonical + .file_name() + .and_then(|name| name.to_str()) + .unwrap_or("new-project"); + + let project_params = ProjectParams { + name: project_name.to_owned(), + }; + + match options.kind { + InitKind::Place => init_place(&base_path, project_params), + InitKind::Model => init_model(&base_path, project_params), + } +} + +fn init_place(base_path: &Path, project_params: ProjectParams) -> Result<(), Error> { + let project_file = project_params.render_template(DEFAULT_PLACE_PROJECT); + try_create_project(base_path, &project_file)?; + + let src = base_path.join("src"); + fs::create_dir_all(&src)?; + + let src_common = src.join("common"); + fs::create_dir_all(src.join(&src_common))?; + + let src_server = src.join("server"); + fs::create_dir_all(src.join(&src_server))?; + + let src_client = src.join("client"); + fs::create_dir_all(src.join(&src_client))?; + + write_if_not_exists( + &src_common.join("Hello.lua"), + "return function()\n\tprint(\"Hello, world!\")\nend", + )?; + + write_if_not_exists( + &src_server.join("init.server.lua"), + "print(\"Hello world, from server!\")", + )?; + + write_if_not_exists( + &src_client.join("init.client.lua"), + "print(\"Hello world, from client!\")", + )?; + + Ok(()) +} + +fn init_model(base_path: &Path, project_params: ProjectParams) -> Result<(), Error> { + let project_file = project_params.render_template(DEFAULT_MODEL_PROJECT); + try_create_project(base_path, &project_file)?; + + let src = base_path.join("src"); + fs::create_dir_all(&src)?; + + let init = project_params.render_template(DEFAULT_MODEL_INIT); + write_if_not_exists(&src.join("init.lua"), &init)?; + + Ok(()) +} + +/// Contains parameters used in templates to create a project. +struct ProjectParams { + name: String, +} + +impl ProjectParams { + /// Render a template by replacing variables with project parameters. + fn render_template(&self, template: &str) -> String { + template.replace("{project_name}", &self.name) + } +} + +/// Write a file if it does not exist yet, otherwise, leave it alone. +fn write_if_not_exists(path: &Path, contents: &str) -> Result<(), Error> { + let file_res = OpenOptions::new().write(true).create_new(true).open(path); + + let mut file = match file_res { + Ok(file) => file, + Err(err) => { + return match err.kind() { + io::ErrorKind::AlreadyExists => return Ok(()), + _ => Err(err.into()), + } + } + }; + + file.write_all(contents.as_bytes())?; + + Ok(()) +} + +/// Try to create a project file and fail if it already exists. +fn try_create_project(base_path: &Path, contents: &str) -> Result<(), Error> { + let project_path = base_path.join("default.project.json"); + + let file_res = OpenOptions::new() + .write(true) + .create_new(true) + .open(project_path); + + let mut file = match file_res { + Ok(file) => file, + Err(err) => { + return match err.kind() { + io::ErrorKind::AlreadyExists => Err(Error::AlreadyExists), + _ => Err(err.into()), + } + } + }; + + file.write_all(contents.as_bytes())?; + + Ok(()) } From fe874720aadda3bb43591d328a09fdffc396eccd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Mar 2020 20:00:48 -0700 Subject: [PATCH 0983/1504] Upgrade rojo init to create README.md and create Git repo --- assets/default-model-project/README.md | 9 ++ .../default.project.json} | 0 assets/default-model-project/gitignore.txt | 3 + .../src-init.lua} | 0 assets/default-place-project/README.md | 17 ++++ .../default.project.json} | 0 assets/default-place-project/gitignore.txt | 6 ++ src/cli/init.rs | 86 +++++++++++++++++-- 8 files changed, 114 insertions(+), 7 deletions(-) create mode 100644 assets/default-model-project/README.md rename assets/{model.project.json => default-model-project/default.project.json} (100%) create mode 100644 assets/default-model-project/gitignore.txt rename assets/{default-model.lua => default-model-project/src-init.lua} (100%) create mode 100644 assets/default-place-project/README.md rename assets/{place.project.json => default-place-project/default.project.json} (100%) create mode 100644 assets/default-place-project/gitignore.txt diff --git a/assets/default-model-project/README.md b/assets/default-model-project/README.md new file mode 100644 index 00000000..c5d511fe --- /dev/null +++ b/assets/default-model-project/README.md @@ -0,0 +1,9 @@ +# {project_name} +Generated by [Rojo](https://github.com/rojo-rbx/rojo) {rojo_version}. + +## Getting Started +To build this library or plugin, use: + +```bash +rojo build -o "{project_name}.rbxmx" +``` \ No newline at end of file diff --git a/assets/model.project.json b/assets/default-model-project/default.project.json similarity index 100% rename from assets/model.project.json rename to assets/default-model-project/default.project.json diff --git a/assets/default-model-project/gitignore.txt b/assets/default-model-project/gitignore.txt new file mode 100644 index 00000000..0dfcd838 --- /dev/null +++ b/assets/default-model-project/gitignore.txt @@ -0,0 +1,3 @@ +# Roblox Studio lock files +/*.rbxlx.lock +/*.rbxl.lock \ No newline at end of file diff --git a/assets/default-model.lua b/assets/default-model-project/src-init.lua similarity index 100% rename from assets/default-model.lua rename to assets/default-model-project/src-init.lua diff --git a/assets/default-place-project/README.md b/assets/default-place-project/README.md new file mode 100644 index 00000000..d2738511 --- /dev/null +++ b/assets/default-place-project/README.md @@ -0,0 +1,17 @@ +# {project_name} +Generated by [Rojo](https://github.com/rojo-rbx/rojo) {rojo_version}. + +## Getting Started +To build the place from scratch, use: + +```bash +rojo build -o Place.rbxlx +``` + +Next, open `Place.rbxlx` in Roblox Studio and start the Rojo server: + +```bash +rojo serve +``` + +For more help, check out [the Rojo documentation](https://rojo.space/docs). \ No newline at end of file diff --git a/assets/place.project.json b/assets/default-place-project/default.project.json similarity index 100% rename from assets/place.project.json rename to assets/default-place-project/default.project.json diff --git a/assets/default-place-project/gitignore.txt b/assets/default-place-project/gitignore.txt new file mode 100644 index 00000000..41d6a8ab --- /dev/null +++ b/assets/default-place-project/gitignore.txt @@ -0,0 +1,6 @@ +# Project place file +/{project_name}.rbxlx + +# Roblox Studio lock files +/*.rbxlx.lock +/*.rbxl.lock \ No newline at end of file diff --git a/src/cli/init.rs b/src/cli/init.rs index 5fbbdafa..064bf392 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -2,16 +2,23 @@ use std::{ fs::{self, OpenOptions}, io::{self, Write}, path::Path, + process::{Command, Stdio}, }; use snafu::Snafu; use crate::cli::{InitCommand, InitKind}; -static DEFAULT_PLACE_PROJECT: &str = include_str!("../../assets/place.project.json"); +static MODEL_PROJECT: &str = + include_str!("../../assets/default-model-project/default.project.json"); +static MODEL_README: &str = include_str!("../../assets/default-model-project/README.md"); +static MODEL_INIT: &str = include_str!("../../assets/default-model-project/src-init.lua"); +static MODEL_GIT_IGNORE: &str = include_str!("../../assets/default-model-project/gitignore.txt"); -static DEFAULT_MODEL_PROJECT: &str = include_str!("../../assets/model.project.json"); -static DEFAULT_MODEL_INIT: &str = include_str!("../../assets/default-model.lua"); +static PLACE_PROJECT: &str = + include_str!("../../assets/default-place-project/default.project.json"); +static PLACE_README: &str = include_str!("../../assets/default-place-project/README.md"); +static PLACE_GIT_IGNORE: &str = include_str!("../../assets/default-place-project/gitignore.txt"); #[derive(Debug, Snafu)] pub struct InitError(Error); @@ -21,6 +28,9 @@ enum Error { #[snafu(display("A project file named default.project.json already exists in this folder"))] AlreadyExists, + #[snafu(display("git init failed"))] + GitInit, + #[snafu(display("I/O error"))] Io { source: io::Error }, } @@ -37,6 +47,8 @@ pub fn init(options: InitCommand) -> Result<(), InitError> { fn init_inner(options: InitCommand) -> Result<(), Error> { let base_path = options.absolute_path(); + fs::create_dir_all(&base_path)?; + let canonical = fs::canonicalize(&base_path)?; let project_name = canonical .file_name() @@ -54,9 +66,14 @@ fn init_inner(options: InitCommand) -> Result<(), Error> { } fn init_place(base_path: &Path, project_params: ProjectParams) -> Result<(), Error> { - let project_file = project_params.render_template(DEFAULT_PLACE_PROJECT); + eprintln!("Creating new place project '{}'", project_params.name); + + let project_file = project_params.render_template(PLACE_PROJECT); try_create_project(base_path, &project_file)?; + let readme = project_params.render_template(PLACE_README); + write_if_not_exists(&base_path.join("README.md"), &readme)?; + let src = base_path.join("src"); fs::create_dir_all(&src)?; @@ -84,19 +101,34 @@ fn init_place(base_path: &Path, project_params: ProjectParams) -> Result<(), Err "print(\"Hello world, from client!\")", )?; + let git_ignore = project_params.render_template(PLACE_GIT_IGNORE); + try_git_init(base_path, &git_ignore)?; + + eprintln!("Created project successfully."); + Ok(()) } fn init_model(base_path: &Path, project_params: ProjectParams) -> Result<(), Error> { - let project_file = project_params.render_template(DEFAULT_MODEL_PROJECT); + eprintln!("Creating new model project '{}'", project_params.name); + + let project_file = project_params.render_template(MODEL_PROJECT); try_create_project(base_path, &project_file)?; + let readme = project_params.render_template(MODEL_README); + write_if_not_exists(&base_path.join("README.md"), &readme)?; + let src = base_path.join("src"); fs::create_dir_all(&src)?; - let init = project_params.render_template(DEFAULT_MODEL_INIT); + let init = project_params.render_template(MODEL_INIT); write_if_not_exists(&src.join("init.lua"), &init)?; + let git_ignore = project_params.render_template(MODEL_GIT_IGNORE); + try_git_init(base_path, &git_ignore)?; + + eprintln!("Created project successfully."); + Ok(()) } @@ -108,7 +140,47 @@ struct ProjectParams { impl ProjectParams { /// Render a template by replacing variables with project parameters. fn render_template(&self, template: &str) -> String { - template.replace("{project_name}", &self.name) + template + .replace("{project_name}", &self.name) + .replace("{rojo_version}", env!("CARGO_PKG_VERSION")) + } +} + +/// Attempt to initialize a Git repository if necessary, and create .gitignore. +fn try_git_init(path: &Path, git_ignore: &str) -> Result<(), Error> { + if should_git_init(path) { + log::debug!("Initializing Git repository..."); + + let status = Command::new("git").arg("init").current_dir(path).status()?; + + if !status.success() { + return Err(Error::GitInit); + } + } + + write_if_not_exists(&path.join(".gitignore"), git_ignore)?; + + Ok(()) +} + +/// Tells whether we should initialize a Git repository inside the given path. +/// +/// Will return false if the user doesn't have Git installed or if the path is +/// already inside a Git repository. +fn should_git_init(path: &Path) -> bool { + let result = Command::new("git") + .args(&["rev-parse", "--is-inside-work-tree"]) + .stdout(Stdio::null()) + .current_dir(path) + .status(); + + match result { + // If the command ran, but returned a non-zero exit code, we are not in + // a Git repo and we should initialize one. + Ok(status) => !status.success(), + + // If the command failed to run, we probably don't have Git installed. + Err(_) => false, } } From 9b4c89820d223e5ee98e3d1e4a036efde2cc0f4b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Mar 2020 20:10:31 -0700 Subject: [PATCH 0984/1504] Fix extra Git output in rojo init and update place template --- assets/default-place-project/README.md | 4 ++-- src/cli/init.rs | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/assets/default-place-project/README.md b/assets/default-place-project/README.md index d2738511..7908cf59 100644 --- a/assets/default-place-project/README.md +++ b/assets/default-place-project/README.md @@ -5,10 +5,10 @@ Generated by [Rojo](https://github.com/rojo-rbx/rojo) {rojo_version}. To build the place from scratch, use: ```bash -rojo build -o Place.rbxlx +rojo build -o "{project_name}.rbxlx" ``` -Next, open `Place.rbxlx` in Roblox Studio and start the Rojo server: +Next, open `{project_name}.rbxlx` in Roblox Studio and start the Rojo server: ```bash rojo serve diff --git a/src/cli/init.rs b/src/cli/init.rs index 064bf392..9e607a48 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -171,6 +171,7 @@ fn should_git_init(path: &Path) -> bool { let result = Command::new("git") .args(&["rev-parse", "--is-inside-work-tree"]) .stdout(Stdio::null()) + .stderr(Stdio::null()) .current_dir(path) .status(); From cfa7f03815b8275ce8fd6352047cea46d469f3d4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Mar 2020 20:11:08 -0700 Subject: [PATCH 0985/1504] Add help link to default model project --- assets/default-model-project/README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/assets/default-model-project/README.md b/assets/default-model-project/README.md index c5d511fe..30dfc436 100644 --- a/assets/default-model-project/README.md +++ b/assets/default-model-project/README.md @@ -6,4 +6,6 @@ To build this library or plugin, use: ```bash rojo build -o "{project_name}.rbxmx" -``` \ No newline at end of file +``` + +For more help, check out [the Rojo documentation](https://rojo.space/docs). \ No newline at end of file From 4119a510f53d9ef7a9d679334cd51b10e47fe68c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Mar 2020 20:12:42 -0700 Subject: [PATCH 0986/1504] Fix broken error source tracking --- src/bin.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bin.rs b/src/bin.rs index f32c7bff..5b7a846f 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -84,7 +84,7 @@ fn main() { let mut current_err: &dyn Error = &*err; while let Some(source) = current_err.source() { - log::error!(" caused by {}", err); + log::error!(" caused by {}", source); current_err = &*source; } From a95ffe1d31ef7a21a84a6c0805089ccecc8e4e5e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Mar 2020 20:24:14 -0700 Subject: [PATCH 0987/1504] Add snapshot error handling to ChangeProcessor --- src/change_processor.rs | 27 ++++++++++++++++++++------- src/error.rs | 18 ++++++++++++++++++ src/lib.rs | 1 + 3 files changed, 39 insertions(+), 7 deletions(-) create mode 100644 src/error.rs diff --git a/src/change_processor.rs b/src/change_processor.rs index 50cdc949..466ba0e6 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -9,6 +9,7 @@ use memofs::{IoResultExt, Vfs, VfsEvent}; use rbx_dom_weak::{RbxId, RbxValue}; use crate::{ + error::ErrorDisplay, message_queue::MessageQueue, snapshot::{ apply_patch_set, compute_patch_set, AppliedPatchSet, InstigatingSource, PatchSet, RojoTree, @@ -294,9 +295,15 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: RbxId) -> Optio // starting at that path and use it as the source for // our patch. - let snapshot = snapshot_from_vfs(&metadata.context, &vfs, &path) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); + let snapshot = match snapshot_from_vfs(&metadata.context, &vfs, &path) { + Ok(maybe_snapshot) => { + maybe_snapshot.expect("snapshot did not return an instance") + } + Err(err) => { + log::error!("Snapshot error: {}", ErrorDisplay(err)); + return None; + } + }; let patch_set = compute_patch_set(&snapshot, &tree, id); apply_patch_set(tree, patch_set) @@ -320,15 +327,21 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: RbxId) -> Optio // there might be information associated with our instance from // the project file, we snapshot the entire project node again. - let snapshot = snapshot_project_node( + let snapshot_result = snapshot_project_node( &metadata.context, &project_path, instance_name, project_node, &vfs, - ) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); + ); + + let snapshot = match snapshot_result { + Ok(maybe_snapshot) => maybe_snapshot.expect("snapshot did not return an instance"), + Err(err) => { + log::error!("Snapshot error: {}", ErrorDisplay(err)); + return None; + } + }; let patch_set = compute_patch_set(&snapshot, &tree, id); apply_patch_set(tree, patch_set) diff --git a/src/error.rs b/src/error.rs new file mode 100644 index 00000000..5c5a953e --- /dev/null +++ b/src/error.rs @@ -0,0 +1,18 @@ +use std::{error::Error, fmt}; + +/// Wrapper type to print errors with source-chasing. +pub struct ErrorDisplay(pub E); + +impl fmt::Display for ErrorDisplay { + fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { + writeln!(formatter, "{}", self.0)?; + + let mut current_err: &dyn Error = &self.0; + while let Some(source) = current_err.source() { + writeln!(formatter, " caused by {}", source)?; + current_err = &*source; + } + + Ok(()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 8f5fae27..fdfab494 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -10,6 +10,7 @@ mod tree_view; mod auth_cookie; mod change_processor; mod common_setup; +mod error; mod glob; mod message_queue; mod multimap; From b0fc9ee50786683b8687213becbdef758b66bc1b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Mar 2020 20:25:50 -0700 Subject: [PATCH 0988/1504] Rename 'src/common' in default place template to 'src/shared' --- src/cli/init.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cli/init.rs b/src/cli/init.rs index 9e607a48..27aab313 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -77,8 +77,8 @@ fn init_place(base_path: &Path, project_params: ProjectParams) -> Result<(), Err let src = base_path.join("src"); fs::create_dir_all(&src)?; - let src_common = src.join("common"); - fs::create_dir_all(src.join(&src_common))?; + let src_shared = src.join("shared"); + fs::create_dir_all(src.join(&src_shared))?; let src_server = src.join("server"); fs::create_dir_all(src.join(&src_server))?; @@ -87,7 +87,7 @@ fn init_place(base_path: &Path, project_params: ProjectParams) -> Result<(), Err fs::create_dir_all(src.join(&src_client))?; write_if_not_exists( - &src_common.join("Hello.lua"), + &src_shared.join("Hello.lua"), "return function()\n\tprint(\"Hello, world!\")\nend", )?; From 6de74b41b3b8fb51c06649a9a51dd653cb6c89e1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Mar 2020 20:31:31 -0700 Subject: [PATCH 0989/1504] Update snapshot error type and handle serde_json errors in JSON models --- src/snapshot_middleware/error.rs | 106 ++++++++++++-------------- src/snapshot_middleware/json_model.rs | 6 +- 2 files changed, 53 insertions(+), 59 deletions(-) diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs index 94de47ea..fc2ef0ed 100644 --- a/src/snapshot_middleware/error.rs +++ b/src/snapshot_middleware/error.rs @@ -1,5 +1,7 @@ use std::{error::Error, fmt, io, path::PathBuf}; +use snafu::Snafu; + #[derive(Debug)] pub struct SnapshotError { detail: SnapshotErrorDetail, @@ -8,49 +10,56 @@ pub struct SnapshotError { impl SnapshotError { pub fn new(detail: SnapshotErrorDetail, path: Option>) -> Self { - SnapshotError { + Self { detail, path: path.map(Into::into), } } - pub(crate) fn wrap(inner: impl Into, path: impl Into) -> Self { - SnapshotError { - detail: inner.into(), + pub(crate) fn wrap(source: impl Into, path: impl Into) -> Self { + Self { + detail: source.into(), path: Some(path.into()), } } - pub(crate) fn file_did_not_exist(path: impl Into) -> SnapshotError { - SnapshotError { + pub(crate) fn file_did_not_exist(path: impl Into) -> Self { + Self { detail: SnapshotErrorDetail::FileDidNotExist, path: Some(path.into()), } } - pub(crate) fn file_name_bad_unicode(path: impl Into) -> SnapshotError { - SnapshotError { + pub(crate) fn file_name_bad_unicode(path: impl Into) -> Self { + Self { detail: SnapshotErrorDetail::FileNameBadUnicode, path: Some(path.into()), } } pub(crate) fn file_contents_bad_unicode( - inner: std::str::Utf8Error, + source: std::str::Utf8Error, path: impl Into, - ) -> SnapshotError { - SnapshotError { - detail: SnapshotErrorDetail::FileContentsBadUnicode { inner }, + ) -> Self { + Self { + detail: SnapshotErrorDetail::FileContentsBadUnicode { source }, path: Some(path.into()), } } - pub(crate) fn malformed_project( - inner: serde_json::Error, + pub(crate) fn malformed_project(source: serde_json::Error, path: impl Into) -> Self { + Self { + detail: SnapshotErrorDetail::MalformedProject { source }, + path: Some(path.into()), + } + } + + pub(crate) fn malformed_model_json( + source: serde_json::Error, path: impl Into, - ) -> SnapshotError { - SnapshotError { - detail: SnapshotErrorDetail::MalformedProject { inner }, + ) -> Self { + Self { + detail: SnapshotErrorDetail::MalformedModelJson { source }, path: Some(path.into()), } } @@ -83,55 +92,38 @@ impl From for SnapshotError { } } -#[derive(Debug)] +#[derive(Debug, Snafu)] pub enum SnapshotErrorDetail { - IoError { inner: io::Error }, - Lua { inner: rlua::Error }, + #[snafu(display("I/O error"))] + IoError { source: io::Error }, + + #[snafu(display("Lua error"))] + Lua { source: rlua::Error }, + + #[snafu(display("file did not exist"))] FileDidNotExist, + + #[snafu(display("file name had malformed Unicode"))] FileNameBadUnicode, - FileContentsBadUnicode { inner: std::str::Utf8Error }, - MalformedProject { inner: serde_json::Error }, + + #[snafu(display("file had malformed Unicode contents"))] + FileContentsBadUnicode { source: std::str::Utf8Error }, + + #[snafu(display("malformed project file"))] + MalformedProject { source: serde_json::Error }, + + #[snafu(display("malformed .model.json file"))] + MalformedModelJson { source: serde_json::Error }, } impl From for SnapshotErrorDetail { - fn from(inner: io::Error) -> Self { - SnapshotErrorDetail::IoError { inner } + fn from(source: io::Error) -> Self { + SnapshotErrorDetail::IoError { source } } } impl From for SnapshotErrorDetail { - fn from(inner: rlua::Error) -> Self { - SnapshotErrorDetail::Lua { inner } - } -} - -impl SnapshotErrorDetail { - fn source(&self) -> Option<&(dyn Error + 'static)> { - use self::SnapshotErrorDetail::*; - - match self { - IoError { inner } => Some(inner), - Lua { inner } => Some(inner), - FileContentsBadUnicode { inner } => Some(inner), - MalformedProject { inner } => Some(inner), - _ => None, - } - } -} - -impl fmt::Display for SnapshotErrorDetail { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - use self::SnapshotErrorDetail::*; - - match self { - IoError { inner } => write!(formatter, "I/O error: {}", inner), - Lua { inner } => write!(formatter, "{}", inner), - FileDidNotExist => write!(formatter, "file did not exist"), - FileNameBadUnicode => write!(formatter, "file name had malformed Unicode"), - FileContentsBadUnicode { inner } => { - write!(formatter, "file had malformed unicode: {}", inner) - } - MalformedProject { inner } => write!(formatter, "{}", inner), - } + fn from(source: rlua::Error) -> Self { + SnapshotErrorDetail::Lua { source } } } diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 8633b818..f132fdf6 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -8,6 +8,7 @@ use serde::Deserialize; use crate::snapshot::{InstanceContext, InstanceSnapshot}; use super::{ + error::SnapshotError, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, }; @@ -27,8 +28,9 @@ impl SnapshotMiddleware for SnapshotJsonModel { None => return Ok(None), }; - let instance: JsonModel = - serde_json::from_slice(&vfs.read(path)?).expect("TODO: Handle serde_json errors"); + let contents = vfs.read(path)?; + let instance: JsonModel = serde_json::from_slice(&contents) + .map_err(|source| SnapshotError::malformed_model_json(source, path))?; if let Some(json_name) = &instance.name { if json_name != instance_name { From 1cbe272e1970c2a4866b2ed623d36f90d19bfe55 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Mar 2020 20:38:06 -0700 Subject: [PATCH 0990/1504] Fix malformed meta files causing panics. Fixes #280. --- src/snapshot_middleware/csv.rs | 4 ++-- src/snapshot_middleware/dir.rs | 4 ++-- src/snapshot_middleware/error.rs | 10 ++++++++++ src/snapshot_middleware/lua.rs | 4 ++-- src/snapshot_middleware/meta_file.rs | 14 +++++++------- src/snapshot_middleware/txt.rs | 4 ++-- 6 files changed, 25 insertions(+), 15 deletions(-) diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index f54e4a51..9dca4747 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -46,8 +46,8 @@ impl SnapshotMiddleware for SnapshotCsv { .relevant_paths(vec![path.to_path_buf(), meta_path.clone()]), ); - if let Some(meta_contents) = vfs.read(meta_path).with_not_found()? { - let mut metadata = AdjacentMetadata::from_slice(&meta_contents); + if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { + let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; metadata.apply_all(&mut snapshot); } diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 9ff6d9a3..8e9bb932 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -73,8 +73,8 @@ impl SnapshotMiddleware for SnapshotDir { .context(context), ); - if let Some(meta_contents) = vfs.read(meta_path).with_not_found()? { - let mut metadata = DirectoryMetadata::from_slice(&meta_contents); + if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { + let mut metadata = DirectoryMetadata::from_slice(&meta_contents, &meta_path)?; metadata.apply_all(&mut snapshot); } diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs index fc2ef0ed..1460936f 100644 --- a/src/snapshot_middleware/error.rs +++ b/src/snapshot_middleware/error.rs @@ -63,6 +63,13 @@ impl SnapshotError { path: Some(path.into()), } } + + pub(crate) fn malformed_meta_json(source: serde_json::Error, path: impl Into) -> Self { + Self { + detail: SnapshotErrorDetail::MalformedMetaJson { source }, + path: Some(path.into()), + } + } } impl Error for SnapshotError { @@ -114,6 +121,9 @@ pub enum SnapshotErrorDetail { #[snafu(display("malformed .model.json file"))] MalformedModelJson { source: serde_json::Error }, + + #[snafu(display("malformed .meta.json file"))] + MalformedMetaJson { source: serde_json::Error }, } impl From for SnapshotErrorDetail { diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index decd6144..abf98973 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -87,8 +87,8 @@ fn snapshot_lua_file(context: &InstanceContext, vfs: &Vfs, path: &Path) -> Snaps .context(context), ); - if let Some(meta_contents) = vfs.read(meta_path).with_not_found()? { - let mut metadata = AdjacentMetadata::from_slice(&meta_contents); + if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { + let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; metadata.apply_all(&mut snapshot); } diff --git a/src/snapshot_middleware/meta_file.rs b/src/snapshot_middleware/meta_file.rs index db8e1b40..57f1e318 100644 --- a/src/snapshot_middleware/meta_file.rs +++ b/src/snapshot_middleware/meta_file.rs @@ -1,4 +1,4 @@ -use std::{borrow::Cow, collections::HashMap}; +use std::{borrow::Cow, collections::HashMap, path::Path}; use rbx_dom_weak::UnresolvedRbxValue; use rbx_reflection::try_resolve_value; @@ -6,6 +6,8 @@ use serde::{Deserialize, Serialize}; use crate::snapshot::InstanceSnapshot; +use super::error::SnapshotError; + /// Represents metadata in a sibling file with the same basename. /// /// As an example, hello.meta.json next to hello.lua would allow assigning @@ -21,10 +23,9 @@ pub struct AdjacentMetadata { } impl AdjacentMetadata { - pub fn from_slice(slice: &[u8]) -> Self { + pub fn from_slice(slice: &[u8], path: &Path) -> Result { serde_json::from_slice(slice) - // TODO: Turn into error type - .expect(".meta.json file was malformed") + .map_err(|source| SnapshotError::malformed_meta_json(source, path)) } pub fn apply_ignore_unknown_instances(&mut self, snapshot: &mut InstanceSnapshot) { @@ -74,10 +75,9 @@ pub struct DirectoryMetadata { } impl DirectoryMetadata { - pub fn from_slice(slice: &[u8]) -> Self { + pub fn from_slice(slice: &[u8], path: &Path) -> Result { serde_json::from_slice(slice) - // TODO: Turn into error type - .expect("init.meta.json file was malformed") + .map_err(|source| SnapshotError::malformed_meta_json(source, path)) } pub fn apply_all(&mut self, snapshot: &mut InstanceSnapshot) { diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 41502d55..6e4fcc0c 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -52,8 +52,8 @@ impl SnapshotMiddleware for SnapshotTxt { .context(context), ); - if let Some(meta_contents) = vfs.read(meta_path).with_not_found()? { - let mut metadata = AdjacentMetadata::from_slice(&meta_contents); + if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { + let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; metadata.apply_all(&mut snapshot); } From 1a83789c01ff87b0be0f19bd80f0dd1ce011b14b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Mar 2020 20:50:03 -0700 Subject: [PATCH 0991/1504] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a01c48f5..6a24429e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Added dark theme support to plugin. ([#241](https://github.com/rojo-rbx/rojo/issues/241)) * Added a revamped `rojo init` command, which will now create more complete projects. * Added the `rojo doc` command, which opens Rojo's documentation in your browser. +* Fixed many crashes from malformed projects and filesystem edge cases in `rojo serve`. * Simplified filesystem access code dramatically. * Improved error reporting and logging across the board. * Log messages have a less noisy prefix. From bd13047b58029ee836d83137b4b5a9d5606862a5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 13 Mar 2020 23:50:54 -0700 Subject: [PATCH 0992/1504] Release 0.6.0-alpha.3 --- CHANGELOG.md | 2 ++ Cargo.lock | 6 +++--- Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6a24429e..02c2b78d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes for 0.6.x + +## [0.6.0 Alpha 3](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.3) (March 13, 2020) * Added `--watch` argument to `rojo build`. ([#284](https://github.com/rojo-rbx/rojo/pull/284)) * Added dark theme support to plugin. ([#241](https://github.com/rojo-rbx/rojo/issues/241)) * Added a revamped `rojo init` command, which will now create more complete projects. diff --git a/Cargo.lock b/Cargo.lock index e1d9dd82..fbae337a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -195,7 +195,7 @@ dependencies = [ name = "clibrojo" version = "0.1.0" dependencies = [ - "rojo 0.6.0-alpha.2", + "rojo 0.6.0-alpha.3", ] [[package]] @@ -1659,7 +1659,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.6.0-alpha.2" +version = "0.6.0-alpha.3" dependencies = [ "backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", "criterion 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1720,7 +1720,7 @@ dependencies = [ "paste 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rojo 0.6.0-alpha.2", + "rojo 0.6.0-alpha.3", "rojo-insta-ext 0.1.0", "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 5e1fd971..501e3b8b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.6.0-alpha.2" +version = "0.6.0-alpha.3" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 0c441833..7dc4d4e0 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {0, 6, 0, "-alpha.2"}, + version = {0, 6, 0, "-alpha.3"}, expectedServerVersionString = "0.6.0 or newer", protocolVersion = 3, defaultHost = "localhost", From dcc15e89117edd7db35d98d547cacca053bcb01d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 16 Mar 2020 20:20:12 -0700 Subject: [PATCH 0993/1504] Refactor upload to use ServeSession and drop common_setup --- src/cli/upload.rs | 6 ++--- src/common_setup.rs | 57 -------------------------------------------- src/lib.rs | 1 - src/serve_session.rs | 51 +++++++++++++++++++++++++++++++++------ 4 files changed, 47 insertions(+), 68 deletions(-) delete mode 100644 src/common_setup.rs diff --git a/src/cli/upload.rs b/src/cli/upload.rs index f6f847af..aed6ba30 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -2,7 +2,7 @@ use memofs::Vfs; use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}; use snafu::{ResultExt, Snafu}; -use crate::{auth_cookie::get_auth_cookie, cli::UploadCommand, common_setup}; +use crate::{auth_cookie::get_auth_cookie, cli::UploadCommand, serve_session::ServeSession}; #[derive(Debug, Snafu)] pub struct UploadError(Error); @@ -35,11 +35,11 @@ fn upload_inner(options: UploadCommand) -> Result<(), Error> { .or_else(get_auth_cookie) .ok_or(Error::NeedAuthCookie)?; - log::trace!("Constructing in-memory filesystem"); let vfs = Vfs::new_default(); - let (_maybe_project, tree) = common_setup::start(&options.absolute_project(), &vfs); + let session = ServeSession::new(vfs, &options.absolute_project()); + let tree = session.tree(); let inner_tree = tree.inner(); let root_id = inner_tree.get_root_id(); let root_instance = inner_tree.get_instance(root_id).unwrap(); diff --git a/src/common_setup.rs b/src/common_setup.rs deleted file mode 100644 index 7de22c06..00000000 --- a/src/common_setup.rs +++ /dev/null @@ -1,57 +0,0 @@ -//! Initialization routines that are used by more than one Rojo command or -//! utility. - -use std::path::Path; - -use memofs::Vfs; -use rbx_dom_weak::RbxInstanceProperties; - -use crate::{ - project::Project, - snapshot::{ - apply_patch_set, compute_patch_set, InstanceContext, InstancePropertiesWithMeta, - PathIgnoreRule, RojoTree, - }, - snapshot_middleware::snapshot_from_vfs, -}; - -pub fn start(fuzzy_project_path: &Path, vfs: &Vfs) -> (Option, RojoTree) { - log::trace!("Loading project file from {}", fuzzy_project_path.display()); - let maybe_project = Project::load_fuzzy(fuzzy_project_path).expect("TODO: Project load failed"); - - log::trace!("Constructing initial tree"); - let mut tree = RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "Folder".to_owned(), - properties: Default::default(), - }, - metadata: Default::default(), - }); - - let root_id = tree.get_root_id(); - - let mut instance_context = InstanceContext::default(); - - if let Some(project) = &maybe_project { - let rules = project.glob_ignore_paths.iter().map(|glob| PathIgnoreRule { - glob: glob.clone(), - base_path: project.folder_location().to_path_buf(), - }); - - instance_context.add_path_ignore_rules(rules); - } - - log::trace!("Generating snapshot of instances from VFS"); - let snapshot = snapshot_from_vfs(&instance_context, vfs, &fuzzy_project_path) - .expect("snapshot failed") - .expect("snapshot did not return an instance"); - - log::trace!("Computing patch set"); - let patch_set = compute_patch_set(&snapshot, &tree, root_id); - - log::trace!("Applying patch set"); - apply_patch_set(&mut tree, patch_set); - - (maybe_project, tree) -} diff --git a/src/lib.rs b/src/lib.rs index fdfab494..454449b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,6 @@ mod tree_view; mod auth_cookie; mod change_processor; -mod common_setup; mod error; mod glob; mod message_queue; diff --git a/src/serve_session.rs b/src/serve_session.rs index 8d737733..c72a2279 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -7,14 +7,18 @@ use std::{ use crossbeam_channel::Sender; use memofs::Vfs; +use rbx_dom_weak::RbxInstanceProperties; use crate::{ change_processor::ChangeProcessor, - common_setup, message_queue::MessageQueue, project::Project, session_id::SessionId, - snapshot::{AppliedPatchSet, PatchSet, RojoTree}, + snapshot::{ + apply_patch_set, compute_patch_set, AppliedPatchSet, InstanceContext, + InstancePropertiesWithMeta, PatchSet, PathIgnoreRule, RojoTree, + }, + snapshot_middleware::snapshot_from_vfs, }; /// Contains all of the state for a Rojo serve session. @@ -86,7 +90,7 @@ pub struct ServeSession { /// block to prevent needing to spread Send + Sync + 'static into everything /// that handles ServeSession. impl ServeSession { - /// Start a new serve session from the given in-memory filesystem and start + /// Start a new serve session from the given in-memory filesystem and start /// path. /// /// The project file is expected to be loaded out-of-band since it's @@ -94,12 +98,45 @@ impl ServeSession { /// in-memory filesystem layer. pub fn new>(vfs: Vfs, start_path: P) -> Self { let start_path = start_path.as_ref(); - - log::trace!("Starting new ServeSession at path {}", start_path.display(),); - let start_time = Instant::now(); - let (root_project, tree) = common_setup::start(start_path, &vfs); + log::trace!("Starting new ServeSession at path {}", start_path.display()); + + log::trace!("Loading project file from {}", start_path.display()); + let root_project = Project::load_fuzzy(start_path).expect("TODO: Project load failed"); + + let mut tree = RojoTree::new(InstancePropertiesWithMeta { + properties: RbxInstanceProperties { + name: "ROOT".to_owned(), + class_name: "Folder".to_owned(), + properties: Default::default(), + }, + metadata: Default::default(), + }); + + let root_id = tree.get_root_id(); + + let mut instance_context = InstanceContext::default(); + + if let Some(project) = &root_project { + let rules = project.glob_ignore_paths.iter().map(|glob| PathIgnoreRule { + glob: glob.clone(), + base_path: project.folder_location().to_path_buf(), + }); + + instance_context.add_path_ignore_rules(rules); + } + + log::trace!("Generating snapshot of instances from VFS"); + let snapshot = snapshot_from_vfs(&instance_context, &vfs, &start_path) + .expect("snapshot failed") + .expect("snapshot did not return an instance"); + + log::trace!("Computing initial patch set"); + let patch_set = compute_patch_set(&snapshot, &tree, root_id); + + log::trace!("Applying initial patch set"); + apply_patch_set(&mut tree, patch_set); let session_id = SessionId::new(); let message_queue = MessageQueue::new(); From 363f95ba1496e07174c425c19fb17c95023ac740 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 16 Mar 2020 20:35:58 -0700 Subject: [PATCH 0994/1504] memofs: Use fs_err instead of std::fs when possible --- Cargo.lock | 7 +++++++ memofs/Cargo.toml | 3 ++- memofs/src/std_backend.rs | 8 ++++---- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fbae337a..cc087913 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -520,6 +520,11 @@ name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "fs-err" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "fsevent" version = "0.4.0" @@ -915,6 +920,7 @@ name = "memofs" version = "0.1.0" dependencies = [ "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "fs-err 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2582,6 +2588,7 @@ dependencies = [ "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +"checksum fs-err 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c7c48ddea3998e5c287467a6b2ede62009788e98d0bf124bd94d8e05a38f3be" "checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" "checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" diff --git a/memofs/Cargo.toml b/memofs/Cargo.toml index a583486f..07fbec10 100644 --- a/memofs/Cargo.toml +++ b/memofs/Cargo.toml @@ -11,5 +11,6 @@ homepage = "https://github.com/rojo-rbx/rojo/tree/master/memofs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -notify = "4.0.15" crossbeam-channel = "0.4.0" +fs-err = "2.2.0" +notify = "4.0.15" diff --git a/memofs/src/std_backend.rs b/memofs/src/std_backend.rs index e023ec71..6b6efc79 100644 --- a/memofs/src/std_backend.rs +++ b/memofs/src/std_backend.rs @@ -55,15 +55,15 @@ impl StdBackend { impl VfsBackend for StdBackend { fn read(&mut self, path: &Path) -> io::Result> { - fs::read(path) + fs_err::read(path) } fn write(&mut self, path: &Path, data: &[u8]) -> io::Result<()> { - fs::write(path, data) + fs_err::write(path, data) } fn read_dir(&mut self, path: &Path) -> io::Result { - let entries: Result, _> = fs::read_dir(path)?.collect(); + let entries: Result, _> = fs_err::read_dir(path)?.collect(); let mut entries = entries?; entries.sort_by_cached_key(|entry| entry.file_name()); @@ -86,7 +86,7 @@ impl VfsBackend for StdBackend { } fn metadata(&mut self, path: &Path) -> io::Result { - let inner = fs::metadata(path)?; + let inner = fs_err::metadata(path)?; Ok(Metadata { is_file: inner.is_file(), From f69096dadb81f3a5129da5241d1edca99ada4367 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 16 Mar 2020 21:13:38 -0700 Subject: [PATCH 0995/1504] Use thiserror and anyhow for command-level error types --- Cargo.lock | 29 +++++++++++++++++++++++++ Cargo.toml | 3 +++ src/cli/build.rs | 54 ++++++++++------------------------------------- src/cli/doc.rs | 26 ++--------------------- src/cli/init.rs | 40 +++++++++++------------------------ src/cli/serve.rs | 14 ++---------- src/cli/upload.rs | 35 +++++++++--------------------- 7 files changed, 69 insertions(+), 132 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc087913..1e4dcb5a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -21,6 +21,11 @@ dependencies = [ "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "anyhow" +version = "1.0.27" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "atty" version = "0.2.14" @@ -1667,11 +1672,13 @@ dependencies = [ name = "rojo" version = "0.6.0-alpha.3" dependencies = [ + "anyhow 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", "backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", "criterion 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fs-err 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1702,6 +1709,7 @@ dependencies = [ "structopt 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2052,6 +2060,24 @@ dependencies = [ "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "thiserror" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "thiserror-impl 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "thread_local" version = "1.0.1" @@ -2531,6 +2557,7 @@ dependencies = [ "checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" "checksum aho-corasick 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e63fd144e18ba274ae7095c0197a870a7b9468abc801dd62f190d80817d2ec" "checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum anyhow 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "013a6e0a2cbe3d20f9c60b65458f7a7f7a5e636c5d0f45a5a6aee5d4b1f01785" "checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" "checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" "checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" @@ -2747,6 +2774,8 @@ dependencies = [ "checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" "checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum thiserror 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ee14bf8e6767ab4c687c9e8bc003879e042a96fd67a3ba5934eadb6536bef4db" +"checksum thiserror-impl 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a7b51e1fbc44b5a0840be594fbc0f960be09050f2617e61e6aa43bef97cd3ef4" "checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" "checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" "checksum tinytemplate 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "57a3c6667d3e65eb1bc3aed6fd14011c6cbc3a0665218ab7f5daf040b9ec371a" diff --git a/Cargo.toml b/Cargo.toml index 501e3b8b..ce3d70fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,10 +63,12 @@ harness = false [dependencies] memofs = { version = "0.1.0", path = "memofs" } +anyhow = "1.0.27" backtrace = "0.3" crossbeam-channel = "0.4.0" csv = "1.1.1" env_logger = "0.7.1" +fs-err = "2.2.0" futures = "0.1.29" globset = "0.4.4" humantime = "1.3.0" @@ -90,6 +92,7 @@ serde_json = "1.0" snafu = "0.6.0" structopt = "0.3.5" termcolor = "1.0.5" +thiserror = "1.0.11" tokio = "0.1.22" uuid = { version = "0.8.1", features = ["v4", "serde"] } diff --git a/src/cli/build.rs b/src/cli/build.rs index 11fc7bd7..fbbe4373 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -1,15 +1,13 @@ use std::{ fs::File, - io::{self, BufWriter, Write}, + io::{BufWriter, Write}, }; use memofs::Vfs; -use snafu::{ResultExt, Snafu}; +use thiserror::Error; use tokio::runtime::Runtime; -use crate::{ - cli::BuildCommand, project::ProjectError, serve_session::ServeSession, snapshot::RojoTree, -}; +use crate::{cli::BuildCommand, serve_session::ServeSession, snapshot::RojoTree}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] enum OutputKind { @@ -31,45 +29,17 @@ fn detect_output_kind(options: &BuildCommand) -> Option { } } -#[derive(Debug, Snafu)] -pub struct BuildError(Error); - -#[derive(Debug, Snafu)] +#[derive(Debug, Error)] enum Error { - #[snafu(display("Could not detect what kind of file to create"))] + #[error("Could not detect what kind of file to build. Expected output file to end in .rbxl, .rbxlx, .rbxm, or .rbxmx.")] UnknownOutputKind, - - #[snafu(display("{}", source))] - Io { source: io::Error }, - - #[snafu(display("{}", source))] - XmlModelEncode { source: rbx_xml::EncodeError }, - - #[snafu(display("Binary model error: {:?}", source))] - BinaryModelEncode { - #[snafu(source(false))] - source: rbx_binary::EncodeError, - }, - - #[snafu(display("{}", source))] - Project { source: ProjectError }, -} - -impl From for Error { - fn from(source: rbx_binary::EncodeError) -> Self { - Error::BinaryModelEncode { source } - } } fn xml_encode_config() -> rbx_xml::EncodeOptions { rbx_xml::EncodeOptions::new().property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown) } -pub fn build(options: BuildCommand) -> Result<(), BuildError> { - Ok(build_inner(options)?) -} - -fn build_inner(options: BuildCommand) -> Result<(), Error> { +pub fn build(options: BuildCommand) -> Result<(), anyhow::Error> { log::trace!("Constructing in-memory filesystem"); let vfs = Vfs::new_default(); @@ -98,14 +68,14 @@ fn build_inner(options: BuildCommand) -> Result<(), Error> { Ok(()) } -fn write_model(tree: &RojoTree, options: &BuildCommand) -> Result<(), Error> { +fn write_model(tree: &RojoTree, options: &BuildCommand) -> Result<(), anyhow::Error> { let output_kind = detect_output_kind(&options).ok_or(Error::UnknownOutputKind)?; log::debug!("Hoping to generate file of type {:?}", output_kind); let root_id = tree.get_root_id(); log::trace!("Opening output file for write"); - let file = File::create(&options.output).context(Io)?; + let file = File::create(&options.output)?; let mut file = BufWriter::new(file); match output_kind { @@ -113,8 +83,7 @@ fn write_model(tree: &RojoTree, options: &BuildCommand) -> Result<(), Error> { // Model files include the root instance of the tree and all its // descendants. - rbx_xml::to_writer(&mut file, tree.inner(), &[root_id], xml_encode_config()) - .context(XmlModelEncode)?; + rbx_xml::to_writer(&mut file, tree.inner(), &[root_id], xml_encode_config())?; } OutputKind::Rbxlx => { // Place files don't contain an entry for the DataModel, but our @@ -123,8 +92,7 @@ fn write_model(tree: &RojoTree, options: &BuildCommand) -> Result<(), Error> { let root_instance = tree.get_instance(root_id).unwrap(); let top_level_ids = root_instance.children(); - rbx_xml::to_writer(&mut file, tree.inner(), top_level_ids, xml_encode_config()) - .context(XmlModelEncode)?; + rbx_xml::to_writer(&mut file, tree.inner(), top_level_ids, xml_encode_config())?; } OutputKind::Rbxm => { rbx_binary::encode(tree.inner(), &[root_id], &mut file)?; @@ -141,7 +109,7 @@ fn write_model(tree: &RojoTree, options: &BuildCommand) -> Result<(), Error> { } } - file.flush().context(Io)?; + file.flush()?; Ok(()) } diff --git a/src/cli/doc.rs b/src/cli/doc.rs index f10cc8f5..3de2b052 100644 --- a/src/cli/doc.rs +++ b/src/cli/doc.rs @@ -1,26 +1,4 @@ -use opener::{open, OpenError}; -use snafu::Snafu; - -#[derive(Debug, Snafu)] -pub struct DocError(Error); - -#[derive(Debug, Snafu)] -enum Error { - Open { source: OpenError }, -} - -impl From for Error { - fn from(source: OpenError) -> Self { - Error::Open { source } - } -} - -pub fn doc() -> Result<(), DocError> { - doc_inner()?; - Ok(()) -} - -fn doc_inner() -> Result<(), Error> { - open("https://rojo.space/docs")?; +pub fn doc() -> Result<(), anyhow::Error> { + opener::open("https://rojo.space/docs")?; Ok(()) } diff --git a/src/cli/init.rs b/src/cli/init.rs index 27aab313..b5ff49dc 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -5,7 +5,7 @@ use std::{ process::{Command, Stdio}, }; -use snafu::Snafu; +use thiserror::Error; use crate::cli::{InitCommand, InitKind}; @@ -20,32 +20,16 @@ static PLACE_PROJECT: &str = static PLACE_README: &str = include_str!("../../assets/default-place-project/README.md"); static PLACE_GIT_IGNORE: &str = include_str!("../../assets/default-place-project/gitignore.txt"); -#[derive(Debug, Snafu)] -pub struct InitError(Error); - -#[derive(Debug, Snafu)] +#[derive(Debug, Error)] enum Error { - #[snafu(display("A project file named default.project.json already exists in this folder"))] + #[error("A project file named default.project.json already exists in this folder")] AlreadyExists, - #[snafu(display("git init failed"))] + #[error("git init failed")] GitInit, - - #[snafu(display("I/O error"))] - Io { source: io::Error }, } -impl From for Error { - fn from(source: io::Error) -> Self { - Self::Io { source } - } -} - -pub fn init(options: InitCommand) -> Result<(), InitError> { - Ok(init_inner(options)?) -} - -fn init_inner(options: InitCommand) -> Result<(), Error> { +pub fn init(options: InitCommand) -> Result<(), anyhow::Error> { let base_path = options.absolute_path(); fs::create_dir_all(&base_path)?; @@ -65,7 +49,7 @@ fn init_inner(options: InitCommand) -> Result<(), Error> { } } -fn init_place(base_path: &Path, project_params: ProjectParams) -> Result<(), Error> { +fn init_place(base_path: &Path, project_params: ProjectParams) -> Result<(), anyhow::Error> { eprintln!("Creating new place project '{}'", project_params.name); let project_file = project_params.render_template(PLACE_PROJECT); @@ -109,7 +93,7 @@ fn init_place(base_path: &Path, project_params: ProjectParams) -> Result<(), Err Ok(()) } -fn init_model(base_path: &Path, project_params: ProjectParams) -> Result<(), Error> { +fn init_model(base_path: &Path, project_params: ProjectParams) -> Result<(), anyhow::Error> { eprintln!("Creating new model project '{}'", project_params.name); let project_file = project_params.render_template(MODEL_PROJECT); @@ -147,14 +131,14 @@ impl ProjectParams { } /// Attempt to initialize a Git repository if necessary, and create .gitignore. -fn try_git_init(path: &Path, git_ignore: &str) -> Result<(), Error> { +fn try_git_init(path: &Path, git_ignore: &str) -> Result<(), anyhow::Error> { if should_git_init(path) { log::debug!("Initializing Git repository..."); let status = Command::new("git").arg("init").current_dir(path).status()?; if !status.success() { - return Err(Error::GitInit); + return Err(Error::GitInit.into()); } } @@ -186,7 +170,7 @@ fn should_git_init(path: &Path) -> bool { } /// Write a file if it does not exist yet, otherwise, leave it alone. -fn write_if_not_exists(path: &Path, contents: &str) -> Result<(), Error> { +fn write_if_not_exists(path: &Path, contents: &str) -> Result<(), anyhow::Error> { let file_res = OpenOptions::new().write(true).create_new(true).open(path); let mut file = match file_res { @@ -205,7 +189,7 @@ fn write_if_not_exists(path: &Path, contents: &str) -> Result<(), Error> { } /// Try to create a project file and fail if it already exists. -fn try_create_project(base_path: &Path, contents: &str) -> Result<(), Error> { +fn try_create_project(base_path: &Path, contents: &str) -> Result<(), anyhow::Error> { let project_path = base_path.join("default.project.json"); let file_res = OpenOptions::new() @@ -217,7 +201,7 @@ fn try_create_project(base_path: &Path, contents: &str) -> Result<(), Error> { Ok(file) => file, Err(err) => { return match err.kind() { - io::ErrorKind::AlreadyExists => Err(Error::AlreadyExists), + io::ErrorKind::AlreadyExists => Err(Error::AlreadyExists.into()), _ => Err(err.into()), } } diff --git a/src/cli/serve.rs b/src/cli/serve.rs index 429ce23b..b9ae48b5 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -3,25 +3,15 @@ use std::{ sync::Arc, }; +use anyhow::Result; use memofs::Vfs; -use snafu::Snafu; use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; use crate::{cli::ServeCommand, serve_session::ServeSession, web::LiveServer}; const DEFAULT_PORT: u16 = 34872; -#[derive(Debug, Snafu)] -pub struct ServeError(Error); - -#[derive(Debug, Snafu)] -enum Error {} - -pub fn serve(options: ServeCommand) -> Result<(), ServeError> { - Ok(serve_inner(options)?) -} - -fn serve_inner(options: ServeCommand) -> Result<(), Error> { +pub fn serve(options: ServeCommand) -> Result<()> { let vfs = Vfs::new_default(); let session = Arc::new(ServeSession::new(vfs, &options.absolute_project())); diff --git a/src/cli/upload.rs b/src/cli/upload.rs index aed6ba30..2a9b7f7a 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -1,34 +1,19 @@ use memofs::Vfs; use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}; -use snafu::{ResultExt, Snafu}; +use thiserror::Error; use crate::{auth_cookie::get_auth_cookie, cli::UploadCommand, serve_session::ServeSession}; -#[derive(Debug, Snafu)] -pub struct UploadError(Error); - -#[derive(Debug, Snafu)] +#[derive(Debug, Error)] enum Error { - #[snafu(display( - "Rojo could not find your Roblox auth cookie. Please pass one via --cookie.", - ))] + #[error("Rojo could not find your Roblox auth cookie. Please pass one via --cookie.")] NeedAuthCookie, - #[snafu(display("XML model file encode error: {}", source))] - XmlModel { source: rbx_xml::EncodeError }, - - #[snafu(display("HTTP error: {}", source))] - Http { source: reqwest::Error }, - - #[snafu(display("Roblox API error: {}", body))] + #[error("The Roblox API returned an unexpected error: {body}")] RobloxApi { body: String }, } -pub fn upload(options: UploadCommand) -> Result<(), UploadError> { - Ok(upload_inner(options)?) -} - -fn upload_inner(options: UploadCommand) -> Result<(), Error> { +pub fn upload(options: UploadCommand) -> Result<(), anyhow::Error> { let cookie = options .cookie .clone() @@ -55,7 +40,7 @@ fn upload_inner(options: UploadCommand) -> Result<(), Error> { let config = rbx_xml::EncodeOptions::new() .property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown); - rbx_xml::to_writer(&mut buffer, tree.inner(), &encode_ids, config).context(XmlModel)?; + rbx_xml::to_writer(&mut buffer, tree.inner(), &encode_ids, config)?; let url = format!( "https://data.roblox.com/Data/Upload.ashx?assetid={}", @@ -72,13 +57,13 @@ fn upload_inner(options: UploadCommand) -> Result<(), Error> { .header(CONTENT_TYPE, "application/xml") .header(ACCEPT, "application/json") .body(buffer) - .send() - .context(Http)?; + .send()?; if !response.status().is_success() { return Err(Error::RobloxApi { - body: response.text().context(Http)?, - }); + body: response.text()?, + } + .into()); } Ok(()) From c065ded440d0266bc27c2a3bf4b5df23dd1e92f4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 16 Mar 2020 21:35:46 -0700 Subject: [PATCH 0996/1504] Tidy up SnapshotError a lot --- src/snapshot_middleware/error.rs | 158 ++++++++++--------------------- 1 file changed, 49 insertions(+), 109 deletions(-) diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs index 1460936f..78aaaf95 100644 --- a/src/snapshot_middleware/error.rs +++ b/src/snapshot_middleware/error.rs @@ -1,56 +1,62 @@ -use std::{error::Error, fmt, io, path::PathBuf}; +use std::{io, path::PathBuf}; -use snafu::Snafu; +use thiserror::Error; -#[derive(Debug)] -pub struct SnapshotError { - detail: SnapshotErrorDetail, - path: Option, +#[derive(Debug, Error)] +pub enum SnapshotError { + #[error("file name had malformed Unicode")] + FileNameBadUnicode { path: PathBuf }, + + #[error("file had malformed Unicode contents")] + FileContentsBadUnicode { + source: std::str::Utf8Error, + path: PathBuf, + }, + + #[error("malformed project file")] + MalformedProject { + source: serde_json::Error, + path: PathBuf, + }, + + #[error("malformed .model.json file")] + MalformedModelJson { + source: serde_json::Error, + path: PathBuf, + }, + + #[error("malformed .meta.json file")] + MalformedMetaJson { + source: serde_json::Error, + path: PathBuf, + }, + + #[error(transparent)] + Io { + #[from] + source: io::Error, + }, } impl SnapshotError { - pub fn new(detail: SnapshotErrorDetail, path: Option>) -> Self { - Self { - detail, - path: path.map(Into::into), - } - } - - pub(crate) fn wrap(source: impl Into, path: impl Into) -> Self { - Self { - detail: source.into(), - path: Some(path.into()), - } - } - - pub(crate) fn file_did_not_exist(path: impl Into) -> Self { - Self { - detail: SnapshotErrorDetail::FileDidNotExist, - path: Some(path.into()), - } - } - pub(crate) fn file_name_bad_unicode(path: impl Into) -> Self { - Self { - detail: SnapshotErrorDetail::FileNameBadUnicode, - path: Some(path.into()), - } + Self::FileNameBadUnicode { path: path.into() } } pub(crate) fn file_contents_bad_unicode( source: std::str::Utf8Error, path: impl Into, ) -> Self { - Self { - detail: SnapshotErrorDetail::FileContentsBadUnicode { source }, - path: Some(path.into()), + Self::FileContentsBadUnicode { + source, + path: path.into(), } } pub(crate) fn malformed_project(source: serde_json::Error, path: impl Into) -> Self { - Self { - detail: SnapshotErrorDetail::MalformedProject { source }, - path: Some(path.into()), + Self::MalformedProject { + source, + path: path.into(), } } @@ -58,82 +64,16 @@ impl SnapshotError { source: serde_json::Error, path: impl Into, ) -> Self { - Self { - detail: SnapshotErrorDetail::MalformedModelJson { source }, - path: Some(path.into()), + Self::MalformedModelJson { + source, + path: path.into(), } } pub(crate) fn malformed_meta_json(source: serde_json::Error, path: impl Into) -> Self { - Self { - detail: SnapshotErrorDetail::MalformedMetaJson { source }, - path: Some(path.into()), + Self::MalformedMetaJson { + source, + path: path.into(), } } } - -impl Error for SnapshotError { - fn source(&self) -> Option<&(dyn Error + 'static)> { - self.detail.source() - } -} - -impl fmt::Display for SnapshotError { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - match &self.path { - Some(path) => write!(formatter, "{} in path {}", self.detail, path.display()), - None => write!(formatter, "{}", self.detail), - } - } -} - -impl From for SnapshotError { - fn from(inner: io::Error) -> Self { - Self::new(inner.into(), Option::::None) - } -} - -impl From for SnapshotError { - fn from(error: rlua::Error) -> Self { - Self::new(error.into(), Option::::None) - } -} - -#[derive(Debug, Snafu)] -pub enum SnapshotErrorDetail { - #[snafu(display("I/O error"))] - IoError { source: io::Error }, - - #[snafu(display("Lua error"))] - Lua { source: rlua::Error }, - - #[snafu(display("file did not exist"))] - FileDidNotExist, - - #[snafu(display("file name had malformed Unicode"))] - FileNameBadUnicode, - - #[snafu(display("file had malformed Unicode contents"))] - FileContentsBadUnicode { source: std::str::Utf8Error }, - - #[snafu(display("malformed project file"))] - MalformedProject { source: serde_json::Error }, - - #[snafu(display("malformed .model.json file"))] - MalformedModelJson { source: serde_json::Error }, - - #[snafu(display("malformed .meta.json file"))] - MalformedMetaJson { source: serde_json::Error }, -} - -impl From for SnapshotErrorDetail { - fn from(source: io::Error) -> Self { - SnapshotErrorDetail::IoError { source } - } -} - -impl From for SnapshotErrorDetail { - fn from(source: rlua::Error) -> Self { - SnapshotErrorDetail::Lua { source } - } -} From aa4039a2e76c594f0f02e332a25d9ad68b777d03 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 16 Mar 2020 23:37:00 -0700 Subject: [PATCH 0997/1504] bye snafu --- Cargo.lock | 1 - Cargo.toml | 1 - src/project.rs | 36 ++++++++++++++++++------------------ 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e4dcb5a..8dd984dc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1705,7 +1705,6 @@ dependencies = [ "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", - "snafu 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", "structopt 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index ce3d70fe..4555ef1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -89,7 +89,6 @@ ritz = "0.1.0" rlua = "0.17.0" serde = { version = "1.0", features = ["derive", "rc"] } serde_json = "1.0" -snafu = "0.6.0" structopt = "0.3.5" termcolor = "1.0.5" thiserror = "1.0.11" diff --git a/src/project.rs b/src/project.rs index f6cc92b5..bbdb5398 100644 --- a/src/project.rs +++ b/src/project.rs @@ -6,22 +6,26 @@ use std::{ use rbx_dom_weak::UnresolvedRbxValue; use serde::{Deserialize, Serialize}; -use snafu::{ResultExt, Snafu}; +use thiserror::Error; use crate::glob::Glob; static PROJECT_FILENAME: &str = "default.project.json"; /// Error type returned by any function that handles projects. -#[derive(Debug, Snafu)] -pub struct ProjectError(Error); +#[derive(Debug, Error)] +#[error(transparent)] +pub struct ProjectError(#[from] Error); -#[derive(Debug, Snafu)] +#[derive(Debug, Error)] enum Error { - /// A general IO error occurred. - Io { source: io::Error, path: PathBuf }, + #[error("Rojo project I/O error")] + Io { + #[from] + source: io::Error, + }, - /// An error with JSON parsing occurred. + #[error("Error parsing Rojo project")] Json { source: serde_json::Error, path: PathBuf, @@ -125,14 +129,14 @@ impl Project { } } - fn load_exact(project_file_location: &Path) -> Result { - let contents = fs::read_to_string(project_file_location).context(Io { - path: project_file_location, - })?; + fn load_exact(project_file_location: &Path) -> Result { + let contents = fs::read_to_string(project_file_location)?; - let mut project: Project = serde_json::from_str(&contents).context(Json { - path: project_file_location, - })?; + let mut project: Project = + serde_json::from_str(&contents).map_err(|source| Error::Json { + source, + path: project_file_location.to_owned(), + })?; project.file_location = project_file_location.to_path_buf(); project.check_compatibility(); @@ -140,10 +144,6 @@ impl Project { Ok(project) } - pub fn save(&self) -> Result<(), ProjectError> { - unimplemented!() - } - /// Checks if there are any compatibility issues with this project file and /// warns the user if there are any. fn check_compatibility(&self) { From 102c77b23e0ac8ff3e0e21279aecbc52c7203cfa Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Mar 2020 17:50:54 -0700 Subject: [PATCH 0998/1504] Implement /api/open/{id} to open a script by ID in your default editor --- src/web/api.rs | 83 +++++++++++++++++++++++++++++++++++++++++--- src/web/interface.rs | 7 ++++ 2 files changed, 86 insertions(+), 4 deletions(-) diff --git a/src/web/api.rs b/src/web/api.rs index 9a341de7..b1e683fa 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -1,7 +1,7 @@ //! Defines Rojo's HTTP API, all under /api. These endpoints generally return //! JSON. -use std::{collections::HashMap, sync::Arc}; +use std::{collections::HashMap, fs, path::PathBuf, sync::Arc}; use futures::{Future, Stream}; @@ -10,12 +10,12 @@ use rbx_dom_weak::RbxId; use crate::{ serve_session::ServeSession, - snapshot::{PatchSet, PatchUpdate}, + snapshot::{InstanceWithMeta, PatchSet, PatchUpdate}, web::{ interface::{ ErrorResponse, Instance, InstanceMetadata as WebInstanceMetadata, InstanceUpdate, - ReadResponse, ServerInfoResponse, SubscribeMessage, SubscribeResponse, WriteRequest, - WriteResponse, PROTOCOL_VERSION, SERVER_VERSION, + OpenResponse, ReadResponse, ServerInfoResponse, SubscribeMessage, SubscribeResponse, + WriteRequest, WriteResponse, PROTOCOL_VERSION, SERVER_VERSION, }, util::{json, json_ok}, }, @@ -39,6 +39,9 @@ impl Service for ApiService { (&Method::GET, path) if path.starts_with("/api/subscribe/") => { self.handle_api_subscribe(request) } + (&Method::POST, path) if path.starts_with("/api/open/") => { + self.handle_api_open(request) + } (&Method::POST, "/api/write") if cfg!(feature = "unstable_two_way_sync") => { self.handle_api_write(request) @@ -233,4 +236,76 @@ impl ApiService { instances, }) } + + /// Open a script with the given ID in the user's default text editor. + fn handle_api_open(&self, request: Request) -> ::Future { + let argument = &request.uri().path()["/api/open/".len()..]; + let requested_id = match RbxId::parse_str(argument) { + Some(id) => id, + None => { + return json( + ErrorResponse::bad_request("Invalid instance ID"), + StatusCode::BAD_REQUEST, + ); + } + }; + + let tree = self.serve_session.tree(); + + let instance = match tree.get_instance(requested_id) { + Some(instance) => instance, + None => { + return json( + ErrorResponse::bad_request("Instance not found"), + StatusCode::NOT_FOUND, + ); + } + }; + + let script_path = match pick_script_path(instance) { + Some(path) => path, + None => { + return json( + ErrorResponse::bad_request( + "No appropriate file could be found to open this script", + ), + StatusCode::NOT_FOUND, + ); + } + }; + + let _ = opener::open(script_path); + + json_ok(&OpenResponse { + session_id: self.serve_session.session_id(), + }) + } +} + +/// If this instance is represented by a script, try to find the correct .lua +/// file to open to edit it. +fn pick_script_path(instance: InstanceWithMeta<'_>) -> Option { + match instance.class_name() { + "Script" | "LocalScript" | "ModuleScript" => {} + _ => return None, + } + + // Pick the first listed relevant path that has an extension of .lua that + // exists. + instance + .metadata() + .relevant_paths + .iter() + .find(|path| { + // We should only ever open Lua files to be safe. + match path.extension().and_then(|ext| ext.to_str()) { + Some("lua") => {} + _ => return false, + } + + fs::metadata(path) + .map(|meta| meta.is_file()) + .unwrap_or(false) + }) + .map(|path| path.to_owned()) } diff --git a/src/web/interface.rs b/src/web/interface.rs index d2b5cd52..f66a3909 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -128,6 +128,13 @@ pub struct SubscribeResponse<'a> { pub messages: Vec>, } +/// Response body from /api/open/{id} +#[derive(Debug, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct OpenResponse { + pub session_id: SessionId, +} + /// General response type returned from all Rojo routes #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] From 91d45afd0ff1a072af7f90de1d48c283c224485c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Mar 2020 18:13:52 -0700 Subject: [PATCH 0999/1504] Add plugin feature 'UnstableOpenScriptsExternally' --- plugin/src/ApiContext.lua | 15 +++++++++++ plugin/src/DevSettings.lua | 12 +++++++++ plugin/src/ServeSession.lua | 52 +++++++++++++++++++++++++++++++++++++ 3 files changed, 79 insertions(+) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 2f094558..40af8058 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -233,4 +233,19 @@ function ApiContext:retrieveMessages() end) end +function ApiContext:open(id) + local url = ("%s/api/open/%s"):format(self.__baseUrl, id) + + return Http.post(url, "") + :andThen(rejectFailedRequests) + :andThen(Http.Response.json) + :andThen(function(body) + if body.sessionId ~= self.__sessionId then + return Promise.reject("Server changed ID") + end + + return nil + end) +end + return ApiContext \ No newline at end of file diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua index c859f8f0..43237cd4 100644 --- a/plugin/src/DevSettings.lua +++ b/plugin/src/DevSettings.lua @@ -33,6 +33,14 @@ local VALUES = { [Environment.Test] = false, }, }, + UnstableOpenScriptsExternally = { + type = "BoolValue", + values = { + [Environment.User] = false, + [Environment.Dev] = false, + [Environment.Test] = false, + }, + }, } local CONTAINER_NAME = "RojoDevSettings" .. Config.codename @@ -144,6 +152,10 @@ function DevSettings:twoWaySyncEnabled() return getValue("UnstableTwoWaySync") end +function DevSettings:alwaysOpenScriptsExternally() + return getValue("UnstableOpenScriptsExternally") +end + function _G.ROJO_DEV_CREATE() DevSettings:createDevSettings() end diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index b13b351e..36fb61b2 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -1,3 +1,5 @@ +local StudioService = game:GetService("StudioService") + local Log = require(script.Parent.Parent.Log) local Fmt = require(script.Parent.Parent.Fmt) local t = require(script.Parent.Parent.t) @@ -57,12 +59,26 @@ function ServeSession.new(options) local instanceMap = InstanceMap.new(onInstanceChanged) local reconciler = Reconciler.new(instanceMap) + local connections = {} + + local connection = StudioService + :GetPropertyChangedSignal("ActiveScript") + :Connect(function() + local activeScript = StudioService.ActiveScript + + if activeScript ~= nil then + self:__onActiveScriptChanged(activeScript) + end + end) + table.insert(connections, connection) + self = { __status = Status.NotStarted, __apiContext = options.apiContext, __reconciler = reconciler, __instanceMap = instanceMap, __statusChangedCallback = nil, + __connections = connections, } setmetatable(self, ServeSession) @@ -108,6 +124,37 @@ function ServeSession:stop() self:__stopInternal() end +function ServeSession:__onActiveScriptChanged(activeScript) + if not DevSettings:alwaysOpenScriptsExternally() then + Log.trace("Not opening script {} because feature not enabled.", activeScript) + + return + end + + if self.__status ~= Status.Connected then + Log.trace("Not opening script {} because session is not connected.", activeScript) + + return + end + + local scriptId = self.__instanceMap.fromInstances[activeScript] + if scriptId == nil then + Log.trace("Not opening script {} because it is not known by Rojo.", activeScript) + + return + end + + Log.debug("Trying to open script {} externally...", activeScript) + + -- Force-close the script inside Studio + local existingParent = activeScript.Parent + activeScript.Parent = nil + activeScript.Parent = existingParent + + -- Notify the Rojo server to open this script + self.__apiContext:open(scriptId) +end + function ServeSession:__onInstanceChanged(instance, propertyName) if not DevSettings:twoWaySyncEnabled() then return @@ -200,6 +247,11 @@ function ServeSession:__stopInternal(err) self:__setStatus(Status.Disconnected, err) self.__apiContext:disconnect() self.__instanceMap:stop() + + for _, connection in ipairs(self.__connections) do + connection:Disconnect() + end + self.__connections = {} end function ServeSession:__setStatus(status, detail) From 830c242751bb6577b49fcbc82903e2d95f4de635 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Mar 2020 22:25:04 -0700 Subject: [PATCH 1000/1504] plugin: Stop using codename in dev mode --- plugin/src/Components/App.lua | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 3617b2fd..78900ba3 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -74,10 +74,7 @@ function App:init() self.signals = {} self.serveSession = nil - - self.displayedVersion = DevSettings:isEnabled() - and Config.codename - or Version.display(Config.version) + self.displayedVersion = Version.display(Config.version) local toolbar = self.props.plugin:CreateToolbar("Rojo " .. self.displayedVersion) From d58e1f07922756502c1a6b2827a805d6e14b2c3b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Mar 2020 22:28:38 -0700 Subject: [PATCH 1001/1504] Add logging when running rojo build --- src/cli/build.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/cli/build.rs b/src/cli/build.rs index fbbe4373..13db6681 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -111,5 +111,12 @@ fn write_model(tree: &RojoTree, options: &BuildCommand) -> Result<(), anyhow::Er file.flush()?; + let filename = options + .output + .file_name() + .and_then(|name| name.to_str()) + .unwrap_or(""); + log::info!("Built project to {}", filename); + Ok(()) } From 8e81140effebe9ef44f1d37686370fe769ae29f6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Mar 2020 22:29:23 -0700 Subject: [PATCH 1002/1504] Increase verbosity of logging --- src/bin.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index 5b7a846f..2a1336d3 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -64,9 +64,9 @@ fn main() { let options = Options::from_args(); let log_filter = match options.verbosity { - 0 => "warn", - 1 => "warn,librojo=info", - 2 => "warn,librojo=trace", + 0 => "info", + 1 => "info,librojo=debug", + 2 => "info,librojo=trace", _ => "trace", }; From 76dea568c9d6f6c1616a4af94a0ace7b09efb370 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Mar 2020 22:30:00 -0700 Subject: [PATCH 1003/1504] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 02c2b78d..9880933e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes for 0.6.x +* Increased default logging verbosity in commands like `rojo build`. ## [0.6.0 Alpha 3](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.3) (March 13, 2020) * Added `--watch` argument to `rojo build`. ([#284](https://github.com/rojo-rbx/rojo/pull/284)) From c5ce15fe3415e248ee34b8715c5eb660d18e4574 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Mar 2020 22:38:53 -0700 Subject: [PATCH 1004/1504] plugin: Add dummy settings panel --- plugin/src/Components/App.lua | 27 +++++++++++--- plugin/src/Components/ConnectPanel.lua | 12 +++++++ plugin/src/Components/SettingsPanel.lua | 47 +++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 5 deletions(-) create mode 100644 plugin/src/Components/SettingsPanel.lua diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 78900ba3..bef4973e 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -13,11 +13,12 @@ local Version = require(Plugin.Version) local preloadAssets = require(Plugin.preloadAssets) local strict = require(Plugin.strict) -local Theme = require(Plugin.Components.Theme) local ConnectPanel = require(Plugin.Components.ConnectPanel) local ConnectingPanel = require(Plugin.Components.ConnectingPanel) local ConnectionActivePanel = require(Plugin.Components.ConnectionActivePanel) local ErrorPanel = require(Plugin.Components.ErrorPanel) +local SettingsPanel = require(Plugin.Components.SettingsPanel) +local Theme = require(Plugin.Components.Theme) local e = Roact.createElement @@ -62,6 +63,7 @@ local AppStatus = strict("AppStatus", { Connecting = "Connecting", Connected = "Connected", Error = "Error", + Settings = "Settings", }) local App = Roact.Component:extend("App") @@ -155,6 +157,11 @@ function App:render() startSession = function(address, port) self:startSession(address, port) end, + openSettings = function() + self:setState({ + appStatus = AppStatus.Settings, + }) + end, cancel = function() Log.trace("Canceling session configuration") @@ -166,7 +173,7 @@ function App:render() } elseif self.state.appStatus == AppStatus.Connecting then children = { - ConnectingPanel = Roact.createElement(ConnectingPanel), + ConnectingPanel = e(ConnectingPanel), } elseif self.state.appStatus == AppStatus.Connected then children = { @@ -184,9 +191,19 @@ function App:render() end, }), } + elseif self.state.appStatus == AppStatus.Settings then + children = { + e(SettingsPanel, { + back = function() + self:setState({ + appStatus = AppStatus.NotStarted, + }) + end, + }), + } elseif self.state.appStatus == AppStatus.Error then children = { - ErrorPanel = Roact.createElement(ErrorPanel, { + ErrorPanel = e(ErrorPanel, { errorMessage = self.state.errorMessage, onDismiss = function() self:setState({ @@ -197,8 +214,8 @@ function App:render() } end - return Roact.createElement(Theme.StudioProvider, nil, { - UI = Roact.createElement(Roact.Portal, { + return e(Theme.StudioProvider, nil, { + UI = e(Roact.Portal, { target = self.dockWidget, }, children), }) diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index 7c89efe4..8a3e3a99 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -25,6 +25,7 @@ end function ConnectPanel:render() local startSession = self.props.startSession + local openSettings = self.props.openSettings return Theme.with(function(theme) return e(Panel, nil, { @@ -136,6 +137,17 @@ function ConnectPanel:render() PaddingRight = UDim.new(0, 24), }, }, { + e(FormButton, { + layoutOrder = 1, + text = "Settings", + secondary = true, + onClick = function() + if openSettings ~= nil then + openSettings() + end + end, + }), + e(FormButton, { layoutOrder = 2, text = "Connect", diff --git a/plugin/src/Components/SettingsPanel.lua b/plugin/src/Components/SettingsPanel.lua new file mode 100644 index 00000000..3f026d87 --- /dev/null +++ b/plugin/src/Components/SettingsPanel.lua @@ -0,0 +1,47 @@ +local Roact = require(script:FindFirstAncestor("Rojo").Roact) + +local Plugin = script:FindFirstAncestor("Plugin") + +local Theme = require(Plugin.Components.Theme) +local Panel = require(Plugin.Components.Panel) +local FitText = require(Plugin.Components.FitText) +local FormButton = require(Plugin.Components.FormButton) + +local e = Roact.createElement + +local SettingsPanel = Roact.Component:extend("SettingsPanel") + +function SettingsPanel:render() + local back = self.props.back + + return Theme.with(function(theme) + return e(Panel, nil, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 8), + }), + + Text = e(FitText, { + Padding = Vector2.new(12, 6), + Font = theme.ButtonFont, + TextSize = 18, + Text = "This will be a settings panel.", + TextColor3 = theme.Text1, + BackgroundTransparency = 1, + }), + + DisconnectButton = e(FormButton, { + layoutOrder = 2, + text = "Okay", + secondary = true, + onClick = function() + back() + end, + }), + }) + end) +end + +return SettingsPanel \ No newline at end of file From 2cefd1bf2e9941c3eeb04a24fdf291c936f867ad Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Mar 2020 23:03:01 -0700 Subject: [PATCH 1005/1504] plugin: Add PluginSettings context item, render it in settings screen --- plugin/src/Components/App.lua | 9 +- plugin/src/Components/PluginSettings.lua | 119 +++++++++++++++++++++++ plugin/src/Components/SettingsPanel.lua | 55 ++++++----- plugin/src/init.server.lua | 12 ++- 4 files changed, 161 insertions(+), 34 deletions(-) create mode 100644 plugin/src/Components/PluginSettings.lua diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index bef4973e..2736d950 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -18,7 +18,6 @@ local ConnectingPanel = require(Plugin.Components.ConnectingPanel) local ConnectionActivePanel = require(Plugin.Components.ConnectionActivePanel) local ErrorPanel = require(Plugin.Components.ErrorPanel) local SettingsPanel = require(Plugin.Components.SettingsPanel) -local Theme = require(Plugin.Components.Theme) local e = Roact.createElement @@ -214,11 +213,9 @@ function App:render() } end - return e(Theme.StudioProvider, nil, { - UI = e(Roact.Portal, { - target = self.dockWidget, - }, children), - }) + return e(Roact.Portal, { + target = self.dockWidget, + }, children) end function App:didMount() diff --git a/plugin/src/Components/PluginSettings.lua b/plugin/src/Components/PluginSettings.lua new file mode 100644 index 00000000..df90b10c --- /dev/null +++ b/plugin/src/Components/PluginSettings.lua @@ -0,0 +1,119 @@ +--[[ + Persistent plugin settings that can be accessed via Roact context. +]] + +local Rojo = script:FindFirstAncestor("Rojo") + +local Roact = require(Rojo.Roact) + +local defaultSettings = { + openScriptsExternally = false, +} + +local Settings = {} +Settings.__index = Settings + +function Settings.fromPlugin(plugin) + local values = {} + + for name, defaultValue in pairs(defaultSettings) do + local savedValue = plugin:GetSetting("Rojo_" .. name) + + if savedValue == nil then + values[name] = defaultValue + else + values[name] = savedValue + end + end + + return setmetatable({ + __values = values, + __plugin = plugin, + __updateListeners = {}, + }, Settings) +end + +function Settings:get(name) + if defaultSettings[name] == nil then + error("Invalid setings name " .. tostring(name), 2) + end + + return self.__values[name] +end + +function Settings:set(name, value) + self.__plugin:SetSetting(name, value) + self.__values[name] = value + + for callback in pairs(self.__updateListeners) do + callback(name, value) + end +end + +function Settings:onUpdate(newCallback) + local newListeners = {} + for callback in pairs(self.__updateListeners) do + newListeners[callback] = true + end + + newListeners[newCallback] = true + self.__updateListeners = newListeners + + return function() + local newListeners = {} + for callback in pairs(self.__updateListeners) do + if callback ~= newCallback then + newListeners[callback] = true + end + end + + self.__updateListeners = newListeners + end +end + +local Context = Roact.createContext(nil) + +local StudioProvider = Roact.Component:extend("StudioProvider") + +function StudioProvider:init() + self.settings = Settings.fromPlugin(self.props.plugin) +end + +function StudioProvider:render() + return Roact.createElement(Context.Provider, { + value = self.settings, + }, self.props[Roact.Children]) +end + +local InternalConsumer = Roact.Component:extend("InternalConsumer") + +function InternalConsumer:render() + return self.props.render(self.props.settings) +end + +function InternalConsumer:didMount() + self.disconnect = self.props.settings:onUpdate(function() + -- Trigger a dummy state update to update the settings consumer. + self:setState({}) + end) +end + +function InternalConsumer:willUnmount() + self.disconnect() +end + +local function with(callback) + return Roact.createElement(Context.Consumer, { + render = function(settings) + return Roact.createElement(InternalConsumer, { + settings = settings, + render = callback, + }) + end, + }) +end + +return { + StudioProvider = StudioProvider, + with = with, +} \ No newline at end of file diff --git a/plugin/src/Components/SettingsPanel.lua b/plugin/src/Components/SettingsPanel.lua index 3f026d87..f11fff56 100644 --- a/plugin/src/Components/SettingsPanel.lua +++ b/plugin/src/Components/SettingsPanel.lua @@ -2,10 +2,11 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) local Plugin = script:FindFirstAncestor("Plugin") -local Theme = require(Plugin.Components.Theme) -local Panel = require(Plugin.Components.Panel) local FitText = require(Plugin.Components.FitText) local FormButton = require(Plugin.Components.FormButton) +local Panel = require(Plugin.Components.Panel) +local PluginSettings = require(Plugin.Components.PluginSettings) +local Theme = require(Plugin.Components.Theme) local e = Roact.createElement @@ -15,32 +16,34 @@ function SettingsPanel:render() local back = self.props.back return Theme.with(function(theme) - return e(Panel, nil, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 8), - }), + return PluginSettings.with(function(settings) + return e(Panel, nil, { + Layout = Roact.createElement("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 8), + }), - Text = e(FitText, { - Padding = Vector2.new(12, 6), - Font = theme.ButtonFont, - TextSize = 18, - Text = "This will be a settings panel.", - TextColor3 = theme.Text1, - BackgroundTransparency = 1, - }), + Text = e(FitText, { + Padding = Vector2.new(12, 6), + Font = theme.ButtonFont, + TextSize = 18, + Text = "openScriptsExternally: " .. tostring(settings:get("openScriptsExternally")), + TextColor3 = theme.Text1, + BackgroundTransparency = 1, + }), - DisconnectButton = e(FormButton, { - layoutOrder = 2, - text = "Okay", - secondary = true, - onClick = function() - back() - end, - }), - }) + DisconnectButton = e(FormButton, { + layoutOrder = 2, + text = "Okay", + secondary = true, + onClick = function() + back() + end, + }), + }) + end) end) end diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index 2aaf4514..ca8d000f 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -14,9 +14,17 @@ local Roact = require(script.Parent.Roact) local Config = require(script.Config) local App = require(script.Components.App) +local Theme = require(script.Components.Theme) +local PluginSettings = require(script.Components.PluginSettings) -local app = Roact.createElement(App, { - plugin = plugin, +local app = Roact.createElement(Theme.StudioProvider, nil, { + Roact.createElement(PluginSettings.StudioProvider, { + plugin = plugin, + }, { + RojoUI = Roact.createElement(App, { + plugin = plugin, + }), + }) }) local tree = Roact.mount(app, nil, "Rojo UI") From 4a4da4737dad22ef112213c1adaba3f932d16e32 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Mar 2020 23:03:59 -0700 Subject: [PATCH 1006/1504] Fix plugin settings persistent --- plugin/src/Components/PluginSettings.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/src/Components/PluginSettings.lua b/plugin/src/Components/PluginSettings.lua index df90b10c..260b2912 100644 --- a/plugin/src/Components/PluginSettings.lua +++ b/plugin/src/Components/PluginSettings.lua @@ -20,6 +20,7 @@ function Settings.fromPlugin(plugin) local savedValue = plugin:GetSetting("Rojo_" .. name) if savedValue == nil then + plugin:SetSetting("Rojo_" .. name, defaultValue) values[name] = defaultValue else values[name] = savedValue @@ -42,7 +43,7 @@ function Settings:get(name) end function Settings:set(name, value) - self.__plugin:SetSetting(name, value) + self.__plugin:SetSetting("Rojo_" .. name, value) self.__values[name] = value for callback in pairs(self.__updateListeners) do From a2356773dc3ad0de0a55766e7936d80f7364599f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Mar 2020 23:14:32 -0700 Subject: [PATCH 1007/1504] Add checkbox and fill out settings panel --- plugin/src/Components/Checkbox.lua | 39 ++++++++++++++++++++ plugin/src/Components/SettingsPanel.lua | 47 ++++++++++++++++++++----- 2 files changed, 78 insertions(+), 8 deletions(-) create mode 100644 plugin/src/Components/Checkbox.lua diff --git a/plugin/src/Components/Checkbox.lua b/plugin/src/Components/Checkbox.lua new file mode 100644 index 00000000..0969b8e4 --- /dev/null +++ b/plugin/src/Components/Checkbox.lua @@ -0,0 +1,39 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Theme = require(Plugin.Components.Theme) + +local e = Roact.createElement + +local function Checkbox(props) + local checked = props.checked + local layoutOrder = props.layoutOrder + local onChange = props.onChange + + return Theme.with(function(theme) + return e("ImageButton", { + LayoutOrder = layoutOrder, + Size = UDim2.new(0, 20, 0, 20), + BorderSizePixel = 2, + BorderColor3 = theme.Text2, + BackgroundColor3 = theme.Background2, + + [Roact.Event.Activated] = function() + onChange(not checked) + end, + }, { + Indicator = e("Frame", { + Size = UDim2.new(0, 18, 0, 18), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + BorderSizePixel = 0, + BackgroundColor3 = theme.Brand1, + BackgroundTransparency = checked and 0 or 1, + }) + }) + end) +end + +return Checkbox \ No newline at end of file diff --git a/plugin/src/Components/SettingsPanel.lua b/plugin/src/Components/SettingsPanel.lua index f11fff56..0bb99dc9 100644 --- a/plugin/src/Components/SettingsPanel.lua +++ b/plugin/src/Components/SettingsPanel.lua @@ -2,6 +2,8 @@ local Roact = require(script:FindFirstAncestor("Rojo").Roact) local Plugin = script:FindFirstAncestor("Plugin") +local Checkbox = require(Plugin.Components.Checkbox) +local FitList = require(Plugin.Components.FitList) local FitText = require(Plugin.Components.FitText) local FormButton = require(Plugin.Components.FormButton) local Panel = require(Plugin.Components.Panel) @@ -25,16 +27,45 @@ function SettingsPanel:render() Padding = UDim.new(0, 8), }), - Text = e(FitText, { - Padding = Vector2.new(12, 6), - Font = theme.ButtonFont, - TextSize = 18, - Text = "openScriptsExternally: " .. tostring(settings:get("openScriptsExternally")), - TextColor3 = theme.Text1, - BackgroundTransparency = 1, + Address = e(FitList, { + containerProps = { + LayoutOrder = 1, + BackgroundTransparency = 1, + }, + layoutProps = { + Padding = UDim.new(0, 4), + FillDirection = Enum.FillDirection.Horizontal, + HorizontalAlignment = Enum.HorizontalAlignment.Left, + VerticalAlignment = Enum.VerticalAlignment.Center, + }, + }, { + Label = e(FitText, { + Kind = "TextLabel", + LayoutOrder = 1, + BackgroundTransparency = 1, + TextXAlignment = Enum.TextXAlignment.Left, + Font = theme.MainFont, + TextSize = 16, + Text = "Open Scripts Externally", + TextColor3 = theme.Text1, + }), + + Padding = e("Frame", { + Size = UDim2.new(0, 8, 0, 0), + BackgroundTransparency = 1, + LayoutOrder = 2, + }), + + Input = e(Checkbox, { + layoutOrder = 3, + checked = settings:get("openScriptsExternally"), + onChange = function(newValue) + settings:set("openScriptsExternally", not settings:get("openScriptsExternally")) + end, + }), }), - DisconnectButton = e(FormButton, { + BackButton = e(FormButton, { layoutOrder = 2, text = "Okay", secondary = true, From 0e4f6dea2bf68fd151ab1ecdc52ddfcc86f4e3ac Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Mar 2020 23:20:05 -0700 Subject: [PATCH 1008/1504] plugin: Add setting for opening scripts externally --- plugin/src/Components/App.lua | 7 +- plugin/src/Components/ConnectPanel.lua | 241 +++++++++++++------------ plugin/src/DevSettings.lua | 12 -- plugin/src/ServeSession.lua | 4 +- 4 files changed, 131 insertions(+), 133 deletions(-) diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index 2736d950..c18abf40 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -107,12 +107,13 @@ function App:init() end) end -function App:startSession(address, port) +function App:startSession(address, port, sessionOptions) Log.trace("Starting new session") local baseUrl = ("http://%s:%s"):format(address, port) self.serveSession = ServeSession.new({ apiContext = ApiContext.new(baseUrl), + openScriptsExternally = sessionOptions.openScriptsExternally, }) self.serveSession:onStatusChanged(function(status, details) @@ -153,8 +154,8 @@ function App:render() if self.state.appStatus == AppStatus.NotStarted then children = { ConnectPanel = e(ConnectPanel, { - startSession = function(address, port) - self:startSession(address, port) + startSession = function(address, port, settings) + self:startSession(address, port, settings) end, openSettings = function() self:setState({ diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index 8a3e3a99..032d66a6 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -11,6 +11,7 @@ local FitList = require(Plugin.Components.FitList) local FitText = require(Plugin.Components.FitText) local FormButton = require(Plugin.Components.FormButton) local FormTextInput = require(Plugin.Components.FormTextInput) +local PluginSettings = require(Plugin.Components.PluginSettings) local e = Roact.createElement @@ -28,147 +29,153 @@ function ConnectPanel:render() local openSettings = self.props.openSettings return Theme.with(function(theme) - return e(Panel, nil, { - Layout = e("UIListLayout", { - SortOrder = Enum.SortOrder.LayoutOrder, - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - }), + return PluginSettings.with(function(settings) + return e(Panel, nil, { + Layout = e("UIListLayout", { + SortOrder = Enum.SortOrder.LayoutOrder, + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + }), - Inputs = e(FitList, { - containerProps = { - BackgroundTransparency = 1, - LayoutOrder = 1, - }, - layoutProps = { - FillDirection = Enum.FillDirection.Horizontal, - Padding = UDim.new(0, 8), - }, - paddingProps = { - PaddingTop = UDim.new(0, 20), - PaddingBottom = UDim.new(0, 10), - PaddingLeft = UDim.new(0, 24), - PaddingRight = UDim.new(0, 24), - }, - }, { - Address = e(FitList, { + Inputs = e(FitList, { containerProps = { - LayoutOrder = 1, BackgroundTransparency = 1, + LayoutOrder = 1, }, layoutProps = { - Padding = UDim.new(0, 4), + FillDirection = Enum.FillDirection.Horizontal, + Padding = UDim.new(0, 8), + }, + paddingProps = { + PaddingTop = UDim.new(0, 20), + PaddingBottom = UDim.new(0, 10), + PaddingLeft = UDim.new(0, 24), + PaddingRight = UDim.new(0, 24), }, }, { - Label = e(FitText, { - Kind = "TextLabel", - LayoutOrder = 1, - BackgroundTransparency = 1, - TextXAlignment = Enum.TextXAlignment.Left, - Font = theme.TitleFont, - TextSize = 20, - Text = "Address", - TextColor3 = theme.Text1, + Address = e(FitList, { + containerProps = { + LayoutOrder = 1, + BackgroundTransparency = 1, + }, + layoutProps = { + Padding = UDim.new(0, 4), + }, + }, { + Label = e(FitText, { + Kind = "TextLabel", + LayoutOrder = 1, + BackgroundTransparency = 1, + TextXAlignment = Enum.TextXAlignment.Left, + Font = theme.TitleFont, + TextSize = 20, + Text = "Address", + TextColor3 = theme.Text1, + }), + + Input = e(FormTextInput, { + layoutOrder = 2, + width = UDim.new(0, 220), + value = self.state.address, + placeholderValue = Config.defaultHost, + onValueChange = function(newValue) + self:setState({ + address = newValue, + }) + end, + }), }), - Input = e(FormTextInput, { - layoutOrder = 2, - width = UDim.new(0, 220), - value = self.state.address, - placeholderValue = Config.defaultHost, - onValueChange = function(newValue) - self:setState({ - address = newValue, - }) - end, + Port = e(FitList, { + containerProps = { + LayoutOrder = 2, + BackgroundTransparency = 1, + }, + layoutProps = { + Padding = UDim.new(0, 4), + }, + }, { + Label = e(FitText, { + Kind = "TextLabel", + LayoutOrder = 1, + BackgroundTransparency = 1, + TextXAlignment = Enum.TextXAlignment.Left, + Font = theme.TitleFont, + TextSize = 20, + Text = "Port", + TextColor3 = theme.Text1, + }), + + Input = e(FormTextInput, { + layoutOrder = 2, + width = UDim.new(0, 80), + value = self.state.port, + placeholderValue = Config.defaultPort, + onValueChange = function(newValue) + self:setState({ + port = newValue, + }) + end, + }), }), }), - Port = e(FitList, { + Buttons = e(FitList, { + fitAxes = "Y", containerProps = { + BackgroundTransparency = 1, LayoutOrder = 2, - BackgroundTransparency = 1, + Size = UDim2.new(1, 0, 0, 0), }, layoutProps = { - Padding = UDim.new(0, 4), + FillDirection = Enum.FillDirection.Horizontal, + HorizontalAlignment = Enum.HorizontalAlignment.Right, + Padding = UDim.new(0, 8), + }, + paddingProps = { + PaddingTop = UDim.new(0, 0), + PaddingBottom = UDim.new(0, 20), + PaddingLeft = UDim.new(0, 24), + PaddingRight = UDim.new(0, 24), }, }, { - Label = e(FitText, { - Kind = "TextLabel", - LayoutOrder = 1, - BackgroundTransparency = 1, - TextXAlignment = Enum.TextXAlignment.Left, - Font = theme.TitleFont, - TextSize = 20, - Text = "Port", - TextColor3 = theme.Text1, + e(FormButton, { + layoutOrder = 1, + text = "Settings", + secondary = true, + onClick = function() + if openSettings ~= nil then + openSettings() + end + end, }), - Input = e(FormTextInput, { + e(FormButton, { layoutOrder = 2, - width = UDim.new(0, 80), - value = self.state.port, - placeholderValue = Config.defaultPort, - onValueChange = function(newValue) - self:setState({ - port = newValue, - }) + text = "Connect", + onClick = function() + if startSession ~= nil then + local address = self.state.address + if address:len() == 0 then + address = Config.defaultHost + end + + local port = self.state.port + if port:len() == 0 then + port = Config.defaultPort + end + + local sessionOptions = { + openScriptsExternally = settings:get("openScriptsExternally"), + } + + startSession(address, port, sessionOptions) + end end, }), }), - }), - - Buttons = e(FitList, { - fitAxes = "Y", - containerProps = { - BackgroundTransparency = 1, - LayoutOrder = 2, - Size = UDim2.new(1, 0, 0, 0), - }, - layoutProps = { - FillDirection = Enum.FillDirection.Horizontal, - HorizontalAlignment = Enum.HorizontalAlignment.Right, - Padding = UDim.new(0, 8), - }, - paddingProps = { - PaddingTop = UDim.new(0, 0), - PaddingBottom = UDim.new(0, 20), - PaddingLeft = UDim.new(0, 24), - PaddingRight = UDim.new(0, 24), - }, - }, { - e(FormButton, { - layoutOrder = 1, - text = "Settings", - secondary = true, - onClick = function() - if openSettings ~= nil then - openSettings() - end - end, - }), - - e(FormButton, { - layoutOrder = 2, - text = "Connect", - onClick = function() - if startSession ~= nil then - local address = self.state.address - if address:len() == 0 then - address = Config.defaultHost - end - - local port = self.state.port - if port:len() == 0 then - port = Config.defaultPort - end - - startSession(address, port) - end - end, - }), - }), - }) + }) + end) end) end diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua index 43237cd4..c859f8f0 100644 --- a/plugin/src/DevSettings.lua +++ b/plugin/src/DevSettings.lua @@ -33,14 +33,6 @@ local VALUES = { [Environment.Test] = false, }, }, - UnstableOpenScriptsExternally = { - type = "BoolValue", - values = { - [Environment.User] = false, - [Environment.Dev] = false, - [Environment.Test] = false, - }, - }, } local CONTAINER_NAME = "RojoDevSettings" .. Config.codename @@ -152,10 +144,6 @@ function DevSettings:twoWaySyncEnabled() return getValue("UnstableTwoWaySync") end -function DevSettings:alwaysOpenScriptsExternally() - return getValue("UnstableOpenScriptsExternally") -end - function _G.ROJO_DEV_CREATE() DevSettings:createDevSettings() end diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 36fb61b2..c683a839 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -45,6 +45,7 @@ ServeSession.Status = Status local validateServeOptions = t.strictInterface({ apiContext = t.table, + openScriptsExternally = t.boolean, }) function ServeSession.new(options) @@ -75,6 +76,7 @@ function ServeSession.new(options) self = { __status = Status.NotStarted, __apiContext = options.apiContext, + __openScriptsExternally = options.openScriptsExternally, __reconciler = reconciler, __instanceMap = instanceMap, __statusChangedCallback = nil, @@ -125,7 +127,7 @@ function ServeSession:stop() end function ServeSession:__onActiveScriptChanged(activeScript) - if not DevSettings:alwaysOpenScriptsExternally() then + if not self.__openScriptsExternally then Log.trace("Not opening script {} because feature not enabled.", activeScript) return From 1601e6d26eb0d7182268dbebecf8cad5eb8f3462 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 17 Mar 2020 23:20:40 -0700 Subject: [PATCH 1009/1504] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9880933e..49b85b72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes for 0.6.x +* Added "Open Scripts Externally" feature. When enabled, opening a script in Studio will instead open it in your default text editor. * Increased default logging verbosity in commands like `rojo build`. ## [0.6.0 Alpha 3](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.3) (March 13, 2020) From 2a46df111092817d044f8929c407042d11e22fdb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Mar 2020 10:39:40 -0700 Subject: [PATCH 1010/1504] Expose two-way sync. - Convert plugin DevSettings flag to settings panel feature - Remove server feature, always enable write API --- Cargo.toml | 3 -- plugin/src/Components/App.lua | 1 + plugin/src/Components/ConnectPanel.lua | 1 + plugin/src/Components/PluginSettings.lua | 1 + plugin/src/Components/SettingsPanel.lua | 44 ++++++++++++++++++++++-- plugin/src/DevSettings.lua | 12 ------- plugin/src/ServeSession.lua | 4 ++- src/web/api.rs | 4 +-- 8 files changed, 48 insertions(+), 22 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4555ef1e..d4eae073 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,9 +27,6 @@ default = [] # Turn on support for specifying glob ignore path rules in the project format. unstable_glob_ignore_paths = [] -# Turn on the server half of Rojo's unstable two-way sync feature. -unstable_two_way_sync = [] - # Enable this feature to live-reload assets from the web UI. dev_live_assets = [] diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua index c18abf40..8a195235 100644 --- a/plugin/src/Components/App.lua +++ b/plugin/src/Components/App.lua @@ -114,6 +114,7 @@ function App:startSession(address, port, sessionOptions) self.serveSession = ServeSession.new({ apiContext = ApiContext.new(baseUrl), openScriptsExternally = sessionOptions.openScriptsExternally, + twoWaySync = sessionOptions.twoWaySync, }) self.serveSession:onStatusChanged(function(status, details) diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua index 032d66a6..bebd67a6 100644 --- a/plugin/src/Components/ConnectPanel.lua +++ b/plugin/src/Components/ConnectPanel.lua @@ -167,6 +167,7 @@ function ConnectPanel:render() local sessionOptions = { openScriptsExternally = settings:get("openScriptsExternally"), + twoWaySync = settings:get("twoWaySync"), } startSession(address, port, sessionOptions) diff --git a/plugin/src/Components/PluginSettings.lua b/plugin/src/Components/PluginSettings.lua index 260b2912..1c5b4e37 100644 --- a/plugin/src/Components/PluginSettings.lua +++ b/plugin/src/Components/PluginSettings.lua @@ -8,6 +8,7 @@ local Roact = require(Rojo.Roact) local defaultSettings = { openScriptsExternally = false, + twoWaySync = false, } local Settings = {} diff --git a/plugin/src/Components/SettingsPanel.lua b/plugin/src/Components/SettingsPanel.lua index 0bb99dc9..d385d05b 100644 --- a/plugin/src/Components/SettingsPanel.lua +++ b/plugin/src/Components/SettingsPanel.lua @@ -24,10 +24,10 @@ function SettingsPanel:render() HorizontalAlignment = Enum.HorizontalAlignment.Center, VerticalAlignment = Enum.VerticalAlignment.Center, SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 8), + Padding = UDim.new(0, 16), }), - Address = e(FitList, { + OpenScriptsExternally = e(FitList, { containerProps = { LayoutOrder = 1, BackgroundTransparency = 1, @@ -65,8 +65,46 @@ function SettingsPanel:render() }), }), + TwoWaySync = e(FitList, { + containerProps = { + LayoutOrder = 2, + BackgroundTransparency = 1, + }, + layoutProps = { + Padding = UDim.new(0, 4), + FillDirection = Enum.FillDirection.Horizontal, + HorizontalAlignment = Enum.HorizontalAlignment.Left, + VerticalAlignment = Enum.VerticalAlignment.Center, + }, + }, { + Label = e(FitText, { + Kind = "TextLabel", + LayoutOrder = 1, + BackgroundTransparency = 1, + TextXAlignment = Enum.TextXAlignment.Left, + Font = theme.MainFont, + TextSize = 16, + Text = "Two-Way Sync (Experimental!)", + TextColor3 = theme.Text1, + }), + + Padding = e("Frame", { + Size = UDim2.new(0, 8, 0, 0), + BackgroundTransparency = 1, + LayoutOrder = 2, + }), + + Input = e(Checkbox, { + layoutOrder = 3, + checked = settings:get("twoWaySync"), + onChange = function(newValue) + settings:set("twoWaySync", not settings:get("twoWaySync")) + end, + }), + }), + BackButton = e(FormButton, { - layoutOrder = 2, + layoutOrder = 4, text = "Okay", secondary = true, onClick = function() diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua index c859f8f0..f1458c00 100644 --- a/plugin/src/DevSettings.lua +++ b/plugin/src/DevSettings.lua @@ -25,14 +25,6 @@ local VALUES = { [Environment.Test] = true, }, }, - UnstableTwoWaySync = { - type = "BoolValue", - values = { - [Environment.User] = false, - [Environment.Dev] = false, - [Environment.Test] = false, - }, - }, } local CONTAINER_NAME = "RojoDevSettings" .. Config.codename @@ -140,10 +132,6 @@ function DevSettings:shouldTypecheck() return getValue("TypecheckingEnabled") end -function DevSettings:twoWaySyncEnabled() - return getValue("UnstableTwoWaySync") -end - function _G.ROJO_DEV_CREATE() DevSettings:createDevSettings() end diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index c683a839..bf6e9194 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -46,6 +46,7 @@ ServeSession.Status = Status local validateServeOptions = t.strictInterface({ apiContext = t.table, openScriptsExternally = t.boolean, + twoWaySync = t.boolean, }) function ServeSession.new(options) @@ -77,6 +78,7 @@ function ServeSession.new(options) __status = Status.NotStarted, __apiContext = options.apiContext, __openScriptsExternally = options.openScriptsExternally, + __twoWaySync = options.twoWaySync, __reconciler = reconciler, __instanceMap = instanceMap, __statusChangedCallback = nil, @@ -158,7 +160,7 @@ function ServeSession:__onActiveScriptChanged(activeScript) end function ServeSession:__onInstanceChanged(instance, propertyName) - if not DevSettings:twoWaySyncEnabled() then + if not self.__twoWaySync then return end diff --git a/src/web/api.rs b/src/web/api.rs index b1e683fa..580bd055 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -43,9 +43,7 @@ impl Service for ApiService { self.handle_api_open(request) } - (&Method::POST, "/api/write") if cfg!(feature = "unstable_two_way_sync") => { - self.handle_api_write(request) - } + (&Method::POST, "/api/write") => self.handle_api_write(request), (_method, path) => json( ErrorResponse::not_found(format!("Route not found: {}", path)), From e8d1faf4e2a545ab644cd5e895ef4e322b71c447 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Mar 2020 10:43:42 -0700 Subject: [PATCH 1011/1504] Update changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49b85b72..488fa5a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,9 @@ # Rojo Changelog ## Unreleased Changes for 0.6.x -* Added "Open Scripts Externally" feature. When enabled, opening a script in Studio will instead open it in your default text editor. +* Added basic settings panel to plugin, with two settings: + * "Open Scripts Externally": When enabled, opening a script in Studio will instead open it in your default text editor. + * "Two-Way Sync": When enabled, Rojo will attempt to save changes to your place back to the filesystem. **Very early feature, very broken, beware!** * Increased default logging verbosity in commands like `rojo build`. ## [0.6.0 Alpha 3](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.3) (March 13, 2020) From 85e098d5c81764609b1f1bc842399c10be70953b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Mar 2020 11:36:50 -0700 Subject: [PATCH 1012/1504] Update README --- README.md | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 24dd6f87..3c86d35b 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,8 @@ Latest server version - - Rojo 0.5.x Documentation + + Rojo 0.5.x Documentation

    @@ -34,11 +34,10 @@ Rojo enables: * Streaming `rbxmx` and `rbxm` models into your game in real time * Packaging and deploying your project to Roblox.com from the command line -Soon, Rojo will be able to: +In the future, Rojo will be able to: -* Automatically convert your existing game to work with Rojo * Sync instances from Roblox Studio to the filesystem -* Automatically manage your assets on Roblox.com, like images and sounds +* Automatically convert your existing game to work with Rojo * Import custom instances like MoonScript code ## [Documentation](https://rojo.space/docs) From 0b0fe01a7cb39c417d2f9277eab178f26a90832a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Mar 2020 11:40:12 -0700 Subject: [PATCH 1013/1504] Tidy up root repository files --- CONTRIBUTING.md | 7 +++---- design.gv | 30 ------------------------------ 2 files changed, 3 insertions(+), 34 deletions(-) delete mode 100644 design.gv diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index aff0c400..57c2b78c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -33,15 +33,13 @@ Please file issues and we'll try to help figure out what the best way forward is ## Pushing a Rojo Release The Rojo release process is pretty manual right now. If you need to do it, here's how: -1. Bump server version in [`server/Cargo.toml`](server/Cargo.toml) +1. Bump server version in [`Cargo.toml`](Cargo.toml) 2. Bump plugin version in [`plugin/src/Config.lua`](plugin/src/Config.lua) 3. Run `cargo test` to update `Cargo.lock` and double-check tests 4. Update [`CHANGELOG.md`](CHANGELOG.md) 5. Commit! * `git add . && git commit -m "Release vX.Y.Z"` 6. Tag the commit with the version from `Cargo.toml` prepended with a v, like `v0.4.13` -7. Build Windows release build of CLI - * `cargo build --release` 7. Publish the CLI * `cargo publish` 8. Build and upload the plugin @@ -52,4 +50,5 @@ The Rojo release process is pretty manual right now. If you need to do it, here' 10. Copy GitHub release content from previous release * Update the leading text with a summary about the release * Paste the changelog notes (as-is!) from [`CHANGELOG.md`](CHANGELOG.md) - * Write a small summary of each major feature \ No newline at end of file + * Write a small summary of each major feature + * Attach release artifacts from GitHub Actions for each platform \ No newline at end of file diff --git a/design.gv b/design.gv deleted file mode 100644 index f44e7db7..00000000 --- a/design.gv +++ /dev/null @@ -1,30 +0,0 @@ -digraph Rojo { - concentrate = true; - node [fontname = "sans-serif"]; - - plugin [label="Roblox Studio Plugin"] - session [label="Session"] - rbx_tree [label="Instance Tree"] - imfs [label="In-Memory Filesystem"] - fs_impl [label="Filesystem Implementation\n(stubbed in tests)"] - fs [label="Real Filesystem"] - snapshot_subsystem [label="Snapshot Subsystem\n(reconciler)"] - snapshot_generator [label="Snapshot Generator"] - user_middleware [label="User Middleware\n(MoonScript, etc.)"] - builtin_middleware [label="Built-in Middleware\n(.lua, .rbxm, etc.)"] - api [label="Web API"] - file_watcher [label="File Watcher"] - - session -> imfs - session -> rbx_tree - session -> snapshot_subsystem - session -> snapshot_generator - session -> file_watcher [dir="both"] - file_watcher -> imfs - snapshot_generator -> user_middleware - snapshot_generator -> builtin_middleware - plugin -> api [style="dotted"; dir="both"; minlen=2] - api -> session - imfs -> fs_impl - fs_impl -> fs -} \ No newline at end of file From 9f0a6101b89f15f97a6872e16c4e3bb768d162e4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Mar 2020 12:03:07 -0700 Subject: [PATCH 1014/1504] Add configurable color options --- src/bin.rs | 11 ++++---- src/cli/mod.rs | 66 +++++++++++++++++++++++++++++++++++++++++++++--- src/cli/serve.rs | 14 ++++++---- 3 files changed, 77 insertions(+), 14 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index 2a1336d3..3d1ac733 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -3,12 +3,12 @@ use std::{env, error::Error, panic, process}; use backtrace::Backtrace; use structopt::StructOpt; -use librojo::cli::{self, Options, Subcommand}; +use librojo::cli::{self, GlobalOptions, Options, Subcommand}; -fn run(subcommand: Subcommand) -> Result<(), Box> { +fn run(global: GlobalOptions, subcommand: Subcommand) -> Result<(), Box> { match subcommand { Subcommand::Init(init_options) => cli::init(init_options)?, - Subcommand::Serve(serve_options) => cli::serve(serve_options)?, + Subcommand::Serve(serve_options) => cli::serve(global, serve_options)?, Subcommand::Build(build_options) => cli::build(build_options)?, Subcommand::Upload(upload_options) => cli::upload(upload_options)?, Subcommand::Doc => cli::doc()?, @@ -63,7 +63,7 @@ fn main() { let options = Options::from_args(); - let log_filter = match options.verbosity { + let log_filter = match options.global.verbosity { 0 => "info", 1 => "info,librojo=debug", 2 => "info,librojo=trace", @@ -77,9 +77,10 @@ fn main() { .format_timestamp(None) // Indent following lines equal to the log level label, like `[ERROR] ` .format_indent(Some(8)) + .write_style(options.global.color.into()) .init(); - if let Err(err) = run(options.subcommand) { + if let Err(err) = run(options.global, options.subcommand) { log::error!("{}", err); let mut current_err: &dyn Error = &*err; diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 40179a32..1339527c 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -16,6 +16,7 @@ use std::{ }; use structopt::StructOpt; +use thiserror::Error; pub use self::build::*; pub use self::doc::*; @@ -27,16 +28,73 @@ pub use self::upload::*; #[derive(Debug, StructOpt)] #[structopt(name = "Rojo", about, author)] pub struct Options { - /// Sets verbosity level. Can be specified multiple times. - #[structopt(long = "verbose", short, global(true), parse(from_occurrences))] - pub verbosity: u8, + #[structopt(flatten)] + pub global: GlobalOptions, /// Subcommand to run in this invocation. #[structopt(subcommand)] pub subcommand: Subcommand, } -/// All of Rojo's subcommands. +#[derive(Debug, StructOpt)] +pub struct GlobalOptions { + /// Sets verbosity level. Can be specified multiple times. + #[structopt(long("verbose"), short, global(true), parse(from_occurrences))] + pub verbosity: u8, + + /// Set color behavior. Valid values are auto, always, and never. + #[structopt(long("color"), global(true), default_value("auto"))] + pub color: ColorChoice, +} + +#[derive(Debug, Clone, Copy)] +pub enum ColorChoice { + Auto, + Always, + Never, +} + +impl FromStr for ColorChoice { + type Err = ColorChoiceParseError; + + fn from_str(source: &str) -> Result { + match source { + "auto" => Ok(ColorChoice::Auto), + "always" => Ok(ColorChoice::Always), + "never" => Ok(ColorChoice::Never), + _ => Err(ColorChoiceParseError { + attempted: source.to_owned(), + }), + } + } +} + +impl From for termcolor::ColorChoice { + fn from(value: ColorChoice) -> Self { + match value { + ColorChoice::Auto => termcolor::ColorChoice::Auto, + ColorChoice::Always => termcolor::ColorChoice::Always, + ColorChoice::Never => termcolor::ColorChoice::Never, + } + } +} + +impl From for env_logger::WriteStyle { + fn from(value: ColorChoice) -> Self { + match value { + ColorChoice::Auto => env_logger::WriteStyle::Auto, + ColorChoice::Always => env_logger::WriteStyle::Always, + ColorChoice::Never => env_logger::WriteStyle::Never, + } + } +} + +#[derive(Debug, Error)] +#[error("Invalid color choice '{attempted}'. Valid values are: auto, always, never")] +pub struct ColorChoiceParseError { + attempted: String, +} + #[derive(Debug, StructOpt)] pub enum Subcommand { /// Creates a new Rojo project. diff --git a/src/cli/serve.rs b/src/cli/serve.rs index b9ae48b5..b4fbcd63 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -7,11 +7,15 @@ use anyhow::Result; use memofs::Vfs; use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; -use crate::{cli::ServeCommand, serve_session::ServeSession, web::LiveServer}; +use crate::{ + cli::{GlobalOptions, ServeCommand}, + serve_session::ServeSession, + web::LiveServer, +}; const DEFAULT_PORT: u16 = 34872; -pub fn serve(options: ServeCommand) -> Result<()> { +pub fn serve(global: GlobalOptions, options: ServeCommand) -> Result<()> { let vfs = Vfs::new_default(); let session = Arc::new(ServeSession::new(vfs, &options.absolute_project())); @@ -23,14 +27,14 @@ pub fn serve(options: ServeCommand) -> Result<()> { let server = LiveServer::new(session); - let _ = show_start_message(port); + let _ = show_start_message(port, global.color.into()); server.start(port); Ok(()) } -fn show_start_message(port: u16) -> io::Result<()> { - let writer = BufferWriter::stdout(ColorChoice::Auto); +fn show_start_message(port: u16, color: ColorChoice) -> io::Result<()> { + let writer = BufferWriter::stdout(color); let mut buffer = writer.buffer(); writeln!(&mut buffer, "Rojo server listening:")?; From f13940262e688cf69196851ac69ee2a06976d905 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Mar 2020 12:03:50 -0700 Subject: [PATCH 1015/1504] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 488fa5a0..560e93b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Added basic settings panel to plugin, with two settings: * "Open Scripts Externally": When enabled, opening a script in Studio will instead open it in your default text editor. * "Two-Way Sync": When enabled, Rojo will attempt to save changes to your place back to the filesystem. **Very early feature, very broken, beware!** +* Added `--color` option to force-enable or force-disable color in Rojo's output. * Increased default logging verbosity in commands like `rojo build`. ## [0.6.0 Alpha 3](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.3) (March 13, 2020) From c1286db9c128dbd98c4aa0e48508812cf8ffa2af Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Mar 2020 16:26:41 -0700 Subject: [PATCH 1016/1504] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 560e93b0..320d81f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * "Open Scripts Externally": When enabled, opening a script in Studio will instead open it in your default text editor. * "Two-Way Sync": When enabled, Rojo will attempt to save changes to your place back to the filesystem. **Very early feature, very broken, beware!** * Added `--color` option to force-enable or force-disable color in Rojo's output. +* The server half of **experimental** two-way sync is now enabled by default. * Increased default logging verbosity in commands like `rojo build`. ## [0.6.0 Alpha 3](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.3) (March 13, 2020) From 28ddf40344c12d9736780da29880f35d20fe27ea Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Mar 2020 18:06:58 -0700 Subject: [PATCH 1017/1504] memofs: Update fs-err and use it more --- Cargo.lock | 8 ++++---- memofs/Cargo.toml | 2 +- memofs/src/std_backend.rs | 4 ++-- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8dd984dc..102a5b89 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -527,7 +527,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "fs-err" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -925,7 +925,7 @@ name = "memofs" version = "0.1.0" dependencies = [ "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fs-err 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fs-err 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -1678,7 +1678,7 @@ dependencies = [ "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fs-err 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "fs-err 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2614,7 +2614,7 @@ dependencies = [ "checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" "checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" "checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum fs-err 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9c7c48ddea3998e5c287467a6b2ede62009788e98d0bf124bd94d8e05a38f3be" +"checksum fs-err 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c1a51f8b7158efbe531f7baa74e38e49fbc41239e5d66720bb37ed39c27c241a" "checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" "checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" "checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" diff --git a/memofs/Cargo.toml b/memofs/Cargo.toml index 07fbec10..aaae80fd 100644 --- a/memofs/Cargo.toml +++ b/memofs/Cargo.toml @@ -12,5 +12,5 @@ homepage = "https://github.com/rojo-rbx/rojo/tree/master/memofs" [dependencies] crossbeam-channel = "0.4.0" -fs-err = "2.2.0" +fs-err = "2.3.0" notify = "4.0.15" diff --git a/memofs/src/std_backend.rs b/memofs/src/std_backend.rs index 6b6efc79..ac9b45c4 100644 --- a/memofs/src/std_backend.rs +++ b/memofs/src/std_backend.rs @@ -78,11 +78,11 @@ impl VfsBackend for StdBackend { } fn remove_file(&mut self, path: &Path) -> io::Result<()> { - fs::remove_file(path) + fs_err::remove_file(path) } fn remove_dir_all(&mut self, path: &Path) -> io::Result<()> { - fs::remove_dir_all(path) + fs_err::remove_dir_all(path) } fn metadata(&mut self, path: &Path) -> io::Result { From 3b433e53be0d6bf8b01297708a763144c2cf4bad Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Mar 2020 18:35:44 -0700 Subject: [PATCH 1018/1504] Memofs v0.1.1 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- memofs/CHANGELOG.md | 3 +++ memofs/Cargo.toml | 2 +- memofs/src/std_backend.rs | 1 - 5 files changed, 7 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 102a5b89..1b7b6170 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -922,7 +922,7 @@ dependencies = [ [[package]] name = "memofs" -version = "0.1.0" +version = "0.1.1" dependencies = [ "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "fs-err 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1688,7 +1688,7 @@ dependencies = [ "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memofs 0.1.0", + "memofs 0.1.1", "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", "opener 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", "paste 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index d4eae073..b7d734d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -58,7 +58,7 @@ name = "build" harness = false [dependencies] -memofs = { version = "0.1.0", path = "memofs" } +memofs = { version = "0.1.1", path = "memofs" } anyhow = "1.0.27" backtrace = "0.3" diff --git a/memofs/CHANGELOG.md b/memofs/CHANGELOG.md index a75397e1..cd4647f2 100644 --- a/memofs/CHANGELOG.md +++ b/memofs/CHANGELOG.md @@ -2,5 +2,8 @@ ## Unreleased Changes +## 0.1.1 (2020-03-18) +* Improved error messages using the [fs-err](https://crates.io/crates/fs-err) crate. + ## 0.1.0 (2020-03-10) * Initial release \ No newline at end of file diff --git a/memofs/Cargo.toml b/memofs/Cargo.toml index aaae80fd..3843606a 100644 --- a/memofs/Cargo.toml +++ b/memofs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "memofs" description = "Virtual filesystem with configurable backends." -version = "0.1.0" +version = "0.1.1" authors = ["Lucien Greathouse "] edition = "2018" readme = "README.md" diff --git a/memofs/src/std_backend.rs b/memofs/src/std_backend.rs index ac9b45c4..7e616cbd 100644 --- a/memofs/src/std_backend.rs +++ b/memofs/src/std_backend.rs @@ -1,4 +1,3 @@ -use std::fs; use std::io; use std::path::Path; use std::sync::mpsc; From 5768d8e4a4f11f35b41b0db818642b99dd01df99 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Mar 2020 23:15:03 -0700 Subject: [PATCH 1019/1504] plugin: Miscellaneous cleanup --- plugin/src/InstanceMap.lua | 1 + plugin/src/PatchSet.lua | 25 +++++++++++++++++++++++++ plugin/src/Reconciler.lua | 18 +++--------------- plugin/src/ServeSession.lua | 1 - plugin/src/getCanonicalProperty.lua | 2 +- 5 files changed, 30 insertions(+), 17 deletions(-) create mode 100644 plugin/src/PatchSet.lua diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 59eccc80..25a25493 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -5,6 +5,7 @@ local Log = require(script.Parent.Parent.Log) keep track of every instance we know about. TODO: Track ancestry to catch when stuff moves? + TODO: Ability to pause change tracking for preventing feedback. ]] local InstanceMap = {} InstanceMap.__index = InstanceMap diff --git a/plugin/src/PatchSet.lua b/plugin/src/PatchSet.lua new file mode 100644 index 00000000..6d18b46d --- /dev/null +++ b/plugin/src/PatchSet.lua @@ -0,0 +1,25 @@ +--[[ + Methods to operate on either a patch created by the hydrate method, or a + patch returned from the API. +]] + +local t = require(script.Parent.Parent.t) + +local Types = require(script.Parent.Types) + +local PatchSet = {} + +PatchSet.validate = t.interface({ + removed = t.array(t.union(Types.RbxId, t.Instance)), + added = t.map(Types.RbxId, Types.ApiInstance), + updated = t.array(Types.ApiInstanceUpdate), +}) + +--[[ + Invert the given PatchSet using the given instance map. +]] +function PatchSet.invert(patchSet, instanceMap) + error("not yet implemented", 2) +end + +return PatchSet \ No newline at end of file diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua index 6050a401..ad395abf 100644 --- a/plugin/src/Reconciler.lua +++ b/plugin/src/Reconciler.lua @@ -5,24 +5,12 @@ local RbxDom = require(script.Parent.Parent.RbxDom) local t = require(script.Parent.Parent.t) -local Log = require(script.Parent.Parent.Log) local Types = require(script.Parent.Types) local invariant = require(script.Parent.invariant) local getCanonicalProperty = require(script.Parent.getCanonicalProperty) local setCanonicalProperty = require(script.Parent.setCanonicalProperty) - ---[[ - This interface represents either a patch created by the hydrate method, or a - patch returned from the API. - - This type should be a subset of Types.ApiInstanceUpdate. -]] -local IPatch = t.interface({ - removed = t.array(t.union(Types.RbxId, t.Instance)), - added = t.map(Types.RbxId, Types.ApiInstance), - updated = t.array(Types.ApiInstanceUpdate), -}) +local PatchSet = require(script.Parent.PatchSet) --[[ Attempt to safely set the parent of an instance. @@ -86,7 +74,7 @@ end editable by scripts. ]] local applyPatchSchema = Types.ifEnabled(t.tuple( - IPatch + PatchSet.validate )) function Reconciler:applyPatch(patch) assert(applyPatchSchema(patch)) @@ -287,7 +275,7 @@ local hydrateSchema = Types.ifEnabled(t.tuple( t.map(Types.RbxId, Types.VirtualInstance), Types.RbxId, t.Instance, - IPatch + PatchSet.validate )) function Reconciler:__hydrateInternal(apiInstances, id, instance, hydratePatch) assert(hydrateSchema(apiInstances, id, instance, hydratePatch)) diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index bf6e9194..e527cc6d 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -4,7 +4,6 @@ local Log = require(script.Parent.Parent.Log) local Fmt = require(script.Parent.Parent.Fmt) local t = require(script.Parent.Parent.t) -local DevSettings = require(script.Parent.DevSettings) local InstanceMap = require(script.Parent.InstanceMap) local Reconciler = require(script.Parent.Reconciler) local strict = require(script.Parent.strict) diff --git a/plugin/src/getCanonicalProperty.lua b/plugin/src/getCanonicalProperty.lua index 288d5989..f594722a 100644 --- a/plugin/src/getCanonicalProperty.lua +++ b/plugin/src/getCanonicalProperty.lua @@ -1,7 +1,7 @@ local RbxDom = require(script.Parent.Parent.RbxDom) --[[ - Attempts to set a property on the given instance. + Attempts to read a property from the given instance. ]] local function getCanonincalProperty(instance, propertyName) local descriptor = RbxDom.findCanonicalPropertyDescriptor(instance.ClassName, propertyName) From 9e9cf5dd1f40d2d2e630ca218413dbfbad5b324f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Mar 2020 23:27:30 -0700 Subject: [PATCH 1020/1504] plugin: Add support for pausing updates tracked by InstanceMap --- plugin/src/InstanceMap.lua | 50 +++++++++++++++++++++++++++++++++++--- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 25a25493..68f8c219 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -5,16 +5,28 @@ local Log = require(script.Parent.Parent.Log) keep track of every instance we know about. TODO: Track ancestry to catch when stuff moves? - TODO: Ability to pause change tracking for preventing feedback. ]] local InstanceMap = {} InstanceMap.__index = InstanceMap function InstanceMap.new(onInstanceChanged) local self = { + -- A map from IDs to instances. fromIds = {}, + + -- A map from instances to IDs. fromInstances = {}, + + -- A set of all instances that updates should be paused for. This set + -- should generally be empty, and will be filled by pauseInstance + -- temporarily. + pausedUpdateInstances = {}, + + -- A map from instances to a signal or list of signals connected to it. instancesToSignal = {}, + + -- Callback that's invoked whenever an instance is changed and it was + -- not paused. onInstanceChanged = onInstanceChanged, } @@ -119,6 +131,32 @@ function InstanceMap:destroyId(id) end end +--[[ + Pause updates for an instance momentarily and invoke a callback. + + If the callback throws an error, InstanceMap will still be kept in a + consistent state. +]] +function InstanceMap:pauseInstance(instance, callback) + local id = self.fromInstances[instance] + + -- If we don't know about this instance, ignore it and do not invoke the + -- callback. + if id == nil then + return + end + + self.pausedUpdateInstances[instance] = true + local success, result = xpcall(callback, debug.traceback) + self.pausedUpdateInstances[instance] = false + + if success then + return result + else + error(result, 2) + end +end + function InstanceMap:__connectSignals(instance) -- ValueBase instances have an overriden version of the Changed signal that -- only detects changes to their Value property. @@ -151,9 +189,15 @@ end function InstanceMap:__maybeFireInstanceChanged(instance, propertyName) Log.trace("{}.{} changed", instance:GetFullName(), propertyName) - if self.onInstanceChanged ~= nil then - self.onInstanceChanged(instance, propertyName) + if self.pausedUpdateInstances[instance] then + return end + + if self.onInstanceChanged == nil then + return + end + + self.onInstanceChanged(instance, propertyName) end function InstanceMap:__disconnectSignals(instance) From cf0ff60d31c64a639d832b6c1f0b5602ef255659 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 18 Mar 2020 23:31:22 -0700 Subject: [PATCH 1021/1504] plugin: Add simple signal implementation for future work --- plugin/src/createSignal.lua | 53 +++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 plugin/src/createSignal.lua diff --git a/plugin/src/createSignal.lua b/plugin/src/createSignal.lua new file mode 100644 index 00000000..965a452d --- /dev/null +++ b/plugin/src/createSignal.lua @@ -0,0 +1,53 @@ +--[[ + Create a new signal that can be connected to, disconnected from, and fired. + + Usage: + + local signal = createSignal() + local disconnect = signal:connect(function(...) + print("fired:", ...) + end) + + signal:fire("a", "b", "c") + disconnect() + + Avoids mutating listeners list directly to prevent iterator invalidation if + a listener is disconnected while the signal is firing. +]] +local function createSignal() + local listeners = {} + + local function connect(newListener) + local nextListeners = {} + for listener in pairs(listeners) do + nextListeners[listener] = true + end + + nextListeners[newListener] = true + listeners = nextListeners + + return function() + local nextListeners = {} + for listener in pairs(listeners) do + if listener ~= newListener then + nextListeners[listener] = true + end + end + + listeners = nextListeners + end + end + + local function fire(...) + for listener in pairs(listeners) do + listener(...) + end + end + + return { + connect = connect, + fire = fire, + } +end + +return createSignal \ No newline at end of file From 330c92c9a8b1cadd9f9ce625a8d2153b04a7f9f9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 21 Mar 2020 17:47:25 -0700 Subject: [PATCH 1022/1504] Refactor ChangeProcessor loop to get rid of panics --- src/change_processor.rs | 88 +++++++++++++++++++++++------------------ 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index 466ba0e6..e998793a 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -272,12 +272,11 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: RbxId) -> Optio let instigating_source = match &metadata.instigating_source { Some(path) => path, None => { - log::warn!( + log::error!( "Instance {} did not have an instigating source, but was considered for an update.", id ); - log::warn!("This is a Rojo bug. Please file an issue!"); - + log::error!("This is a bug. Please file an issue!"); return None; } }; @@ -285,43 +284,49 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: RbxId) -> Optio // How we process a file change event depends on what created this // file/folder in the first place. let applied_patch_set = match instigating_source { - InstigatingSource::Path(path) => { - let maybe_meta = vfs.metadata(path).with_not_found().unwrap(); + InstigatingSource::Path(path) => match vfs.metadata(path).with_not_found() { + Ok(Some(_)) => { + // Our instance was previously created from a path and that + // path still exists. We can generate a snapshot starting at + // that path and use it as the source for our patch. - match maybe_meta { - Some(_meta) => { - // Our instance was previously created from a path and - // that path still exists. We can generate a snapshot - // starting at that path and use it as the source for - // our patch. + let snapshot = match snapshot_from_vfs(&metadata.context, &vfs, &path) { + Ok(Some(snapshot)) => snapshot, + Ok(None) => { + log::error!( + "Snapshot did not return an instance from path {}", + path.display() + ); + log::error!("This may be a bug!"); + return None; + } + Err(err) => { + log::error!("Snapshot error: {}", ErrorDisplay(err)); + return None; + } + }; - let snapshot = match snapshot_from_vfs(&metadata.context, &vfs, &path) { - Ok(maybe_snapshot) => { - maybe_snapshot.expect("snapshot did not return an instance") - } - Err(err) => { - log::error!("Snapshot error: {}", ErrorDisplay(err)); - return None; - } - }; - - let patch_set = compute_patch_set(&snapshot, &tree, id); - apply_patch_set(tree, patch_set) - } - None => { - // Our instance was previously created from a path, but - // that path no longer exists. - // - // We associate deleting the instigating file for an - // instance with deleting that instance. - - let mut patch_set = PatchSet::new(); - patch_set.removed_instances.push(id); - - apply_patch_set(tree, patch_set) - } + let patch_set = compute_patch_set(&snapshot, &tree, id); + apply_patch_set(tree, patch_set) } - } + Ok(None) => { + // Our instance was previously created from a path, but that + // path no longer exists. + // + // We associate deleting the instigating file for an + // instance with deleting that instance. + + let mut patch_set = PatchSet::new(); + patch_set.removed_instances.push(id); + + apply_patch_set(tree, patch_set) + } + Err(err) => { + log::error!("Error processing filesystem change: {}", ErrorDisplay(err)); + return None; + } + }, + InstigatingSource::ProjectNode(project_path, instance_name, project_node) => { // This instance is the direct subject of a project node. Since // there might be information associated with our instance from @@ -336,9 +341,14 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: RbxId) -> Optio ); let snapshot = match snapshot_result { - Ok(maybe_snapshot) => maybe_snapshot.expect("snapshot did not return an instance"), + Ok(Some(snapshot)) => snapshot, + Ok(None) => { + log::error!("Snapshot did not return an instance from a project node."); + log::error!("This is a bug!"); + return None; + } Err(err) => { - log::error!("Snapshot error: {}", ErrorDisplay(err)); + log::error!("{}", ErrorDisplay(err)); return None; } }; From 69c0e8d70ea21d3d0ed89896ddb138c1a9b273ea Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 21 Mar 2020 17:49:56 -0700 Subject: [PATCH 1023/1504] Fix warnings --- src/bin.rs | 2 +- src/change_processor.rs | 9 --------- src/serve_session.rs | 1 + 3 files changed, 2 insertions(+), 10 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index 3d1ac733..403823c6 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -22,7 +22,7 @@ fn main() { // PanicInfo's payload is usually a &'static str or String. // See: https://doc.rust-lang.org/beta/std/panic/struct.PanicInfo.html#method.payload let message = match panic_info.payload().downcast_ref::<&str>() { - Some(message) => message.to_string(), + Some(&message) => message.to_string(), None => match panic_info.payload().downcast_ref::() { Some(message) => message.clone(), None => "".to_string(), diff --git a/src/change_processor.rs b/src/change_processor.rs index e998793a..15f264c8 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -63,15 +63,6 @@ impl ChangeProcessor { .spawn(move || { log::trace!("ChangeProcessor thread started"); - #[allow( - // Crossbeam's select macro generates code that Clippy doesn't like, - // and Clippy blames us for it. - clippy::drop_copy, - - // Crossbeam uses 0 as *const _ and Clippy doesn't like that either, - // but this isn't our fault. - clippy::zero_ptr, - )] loop { select! { recv(vfs_receiver) -> event => { diff --git a/src/serve_session.rs b/src/serve_session.rs index c72a2279..2423bf52 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -181,6 +181,7 @@ impl ServeSession { self.tree_mutation_sender.clone() } + #[allow(unused)] pub fn vfs(&self) -> &Vfs { &self.vfs } From 691a8fcdeb780b8a7981db5400ca36c3e7f291f1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 25 Mar 2020 16:15:21 -0700 Subject: [PATCH 1024/1504] Upgrade lockfile using latest rustc --- Cargo.lock | 2038 ++++++++++++++++++++++++++-------------------------- 1 file changed, 1018 insertions(+), 1020 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1b7b6170..fbcc2b87 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,2828 +4,2826 @@ name = "adler32" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" [[package]] name = "aho-corasick" version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5e63fd144e18ba274ae7095c0197a870a7b9468abc801dd62f190d80817d2ec" dependencies = [ - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "ansi_term" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8", ] [[package]] name = "anyhow" version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "013a6e0a2cbe3d20f9c60b65458f7a7f7a5e636c5d0f45a5a6aee5d4b1f01785" [[package]] name = "atty" version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", + "winapi 0.3.8", ] [[package]] name = "autocfg" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" [[package]] name = "autocfg" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "backtrace" version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8" dependencies = [ - "backtrace-sys 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace-sys", + "cfg-if", + "libc", + "rustc-demangle", ] [[package]] name = "backtrace-sys" version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e17b52e737c40a7d75abca20b29a19a0eb7ba9fc72c5a72dd282a0a3c2c0dc35" dependencies = [ - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", ] [[package]] name = "base64" version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", ] [[package]] name = "base64" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "block-buffer" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" dependencies = [ - "block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-padding", + "byte-tools", + "byteorder", + "generic-array", ] [[package]] name = "block-padding" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" dependencies = [ - "byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "byte-tools", ] [[package]] name = "bstr" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "502ae1441a0a5adb8fbd38a5955a6416b9493e92b465de5e4a9bde6a539c2c48" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "memchr", + "regex-automata", + "serde", ] [[package]] name = "bumpalo" version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742" [[package]] name = "byte-tools" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "bytecount" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" [[package]] name = "byteorder" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" [[package]] name = "bytes" version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "either", + "iovec", ] [[package]] name = "c2-chacha" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" dependencies = [ - "ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "ppv-lite86", ] [[package]] name = "cargo_metadata" version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" dependencies = [ - "error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain", + "semver", + "serde", + "serde_derive", + "serde_json", ] [[package]] name = "cast" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version", ] [[package]] name = "cc" version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" [[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] name = "clap" version = "2.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", + "atty", + "bitflags", + "strsim", + "textwrap", + "unicode-width", + "vec_map", ] [[package]] name = "clibrojo" version = "0.1.0" dependencies = [ - "rojo 0.6.0-alpha.3", + "rojo", ] [[package]] name = "clicolors-control" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" dependencies = [ - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "atty", + "lazy_static", + "libc", + "winapi 0.3.8", ] [[package]] name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", ] [[package]] name = "console" version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45e0f3986890b3acbc782009e2629dfe2baa430ac091519ce3be26164a2ae6c0" dependencies = [ - "clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "clicolors-control", + "encode_unicode", + "lazy_static", + "libc", + "regex", + "termios", + "winapi 0.3.8", ] [[package]] name = "cookie" version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" dependencies = [ - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "time", + "url 1.7.2", ] [[package]] name = "cookie_store" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" dependencies = [ - "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "publicsuffix 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cookie", + "failure", + "idna 0.1.5", + "log", + "publicsuffix", + "serde", + "serde_json", + "time", + "try_from", + "url 1.7.2", ] [[package]] name = "core-foundation" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" dependencies = [ - "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys", + "libc", ] [[package]] name = "core-foundation-sys" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" [[package]] name = "crc32fast" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "criterion" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fc755679c12bda8e5523a71e4d654b6bf2e14bd838dfc48cde6559a05caf7d1" dependencies = [ - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "criterion-plot 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "oorandom 11.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "plotters 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", - "tinytemplate 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "atty", + "cast", + "clap", + "criterion-plot", + "csv", + "itertools", + "lazy_static", + "num-traits", + "oorandom", + "plotters", + "rayon", + "regex", + "serde", + "serde_derive", + "serde_json", + "tinytemplate", + "walkdir", ] [[package]] name = "criterion-plot" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a01e15e0ea58e8234f96146b1f91fa9d0e4dd7a38da93ff7a75d42c0b9d3a545" dependencies = [ - "cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cast", + "itertools", ] [[package]] name = "crossbeam-channel" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" dependencies = [ - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils", + "maybe-uninit", ] [[package]] name = "crossbeam-deque" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" dependencies = [ - "crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-epoch", + "crossbeam-utils", + "maybe-uninit", ] [[package]] name = "crossbeam-epoch" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", + "cfg-if", + "crossbeam-utils", + "lazy_static", + "maybe-uninit", + "memoffset", + "scopeguard", ] [[package]] name = "crossbeam-queue" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crossbeam-utils", ] [[package]] name = "crossbeam-utils" version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", + "cfg-if", + "lazy_static", ] [[package]] name = "csv" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" dependencies = [ - "bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "csv-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "bstr", + "csv-core", + "itoa", + "ryu", + "serde", ] [[package]] name = "csv-core" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" dependencies = [ - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "memchr", ] [[package]] name = "ctor" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47c5e5ac752e18207b12e16b10631ae5f7f68f8805f335f9b817ead83d9ffce1" dependencies = [ - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3", + "syn", ] [[package]] name = "difference" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" [[package]] name = "digest" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ - "generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "generic-array", ] [[package]] name = "doc-comment" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97" [[package]] name = "dtoa" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" [[package]] name = "either" version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" [[package]] name = "encode_unicode" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "env_logger" version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" dependencies = [ - "atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty", + "humantime", + "log", + "regex", + "termcolor", ] [[package]] name = "error-chain" version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd" dependencies = [ - "backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", + "version_check", ] [[package]] name = "failure" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" dependencies = [ - "backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "failure_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "backtrace", + "failure_derive", ] [[package]] name = "failure_derive" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", + "synstructure", ] [[package]] name = "fake-simd" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "filetime" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "redox_syscall", + "winapi 0.3.8", ] [[package]] name = "flate2" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "crc32fast", + "libc", + "miniz_oxide", ] [[package]] name = "fnv" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" [[package]] name = "foreign-types" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "foreign-types-shared", ] [[package]] name = "foreign-types-shared" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "fs-err" version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1a51f8b7158efbe531f7baa74e38e49fbc41239e5d66720bb37ed39c27c241a" [[package]] name = "fsevent" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "fsevent-sys", ] [[package]] name = "fsevent-sys" version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" dependencies = [ - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "fuchsia-cprng" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" [[package]] name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "fuchsia-zircon-sys", ] [[package]] name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" [[package]] name = "futures-cpupool" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "futures", + "num_cpus", ] [[package]] name = "generic-array" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" dependencies = [ - "typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)", + "typenum", ] [[package]] name = "getrandom" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "wasi", ] [[package]] name = "glob" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" [[package]] name = "globset" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" dependencies = [ - "aho-corasick 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "bstr", + "fnv", + "log", + "regex", ] [[package]] name = "h2" version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "bytes", + "fnv", + "futures", + "http", + "indexmap", + "log", + "slab", + "string", + "tokio-io", ] [[package]] name = "heck" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" dependencies = [ - "unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-segmentation", ] [[package]] name = "hermit-abi" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8" dependencies = [ - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "htmlescape" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" [[package]] name = "http" version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "fnv", + "itoa", ] [[package]] name = "http-body" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "http", + "tokio-buf", ] [[package]] name = "httparse" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" [[package]] name = "humantime" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" dependencies = [ - "quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error", ] [[package]] name = "hyper" version = "0.12.35" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "futures-cpupool", + "h2", + "http", + "http-body", + "httparse", + "iovec", + "itoa", + "log", + "net2", + "rustc_version", + "time", + "tokio", + "tokio-buf", + "tokio-executor", + "tokio-io", + "tokio-reactor", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "want", ] [[package]] name = "hyper-tls" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "hyper", + "native-tls", + "tokio-io", ] [[package]] name = "idna" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "idna" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", + "unicode-bidi", + "unicode-normalization", ] [[package]] name = "indexmap" version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", ] [[package]] name = "inotify" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24e40d6fd5d64e2082e0c796495c8ef5ad667a96d03e5aaa0becfd9d47bcbfb8" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "inotify-sys", + "libc", ] [[package]] name = "inotify-sys" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" dependencies = [ - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "insta" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df742abee84dbf27d20869c9adf77b0d8f7ea3eead13c2c9e3998d136a97058" dependencies = [ - "console 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)", - "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", + "console", + "difference", + "lazy_static", + "pest", + "pest_derive", + "serde", + "serde_json", + "serde_yaml", ] [[package]] name = "iovec" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" dependencies = [ - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "itertools" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" dependencies = [ - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", + "either", ] [[package]] name = "itoa" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" [[package]] name = "jod-thread" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f52a11f73b88fab829a0e4d9e13ea5982c7ac457c72eb3541d82a4afdfce4ff" [[package]] name = "js-sys" version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1cb931d43e71f560c81badb0191596562bafad2be06a3f9025b845c847c60df5" dependencies = [ - "wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "wasm-bindgen", ] [[package]] name = "kernel32-sys" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8", + "winapi-build", ] [[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lazycell" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" version = "0.2.67" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" [[package]] name = "linked-hash-map" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" [[package]] name = "lock_api" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" dependencies = [ - "scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "scopeguard", ] [[package]] name = "log" version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "lz4" version = "1.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" dependencies = [ - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)", - "skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "lz4-sys", + "skeptic", ] [[package]] name = "lz4-sys" version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" dependencies = [ - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "cc", + "libc", ] [[package]] name = "maplit" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "matches" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" [[package]] name = "maybe-uninit" version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "md5" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] name = "memchr" version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" [[package]] name = "memoffset" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" dependencies = [ - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc_version", ] [[package]] name = "memofs" version = "0.1.1" dependencies = [ - "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "fs-err 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-channel", + "fs-err", + "notify", ] [[package]] name = "mime" version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mime_guess" version = "2.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" dependencies = [ - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "mime", + "unicase", ] [[package]] name = "miniz_oxide" version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" dependencies = [ - "adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "adler32", ] [[package]] name = "mio" version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", ] [[package]] name = "mio-extras" version = "2.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" dependencies = [ - "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "lazycell", + "log", + "mio", + "slab", ] [[package]] name = "mio-uds" version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" dependencies = [ - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", + "iovec", + "libc", + "mio", ] [[package]] name = "miow" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" dependencies = [ - "kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", ] [[package]] name = "native-tls" version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)", - "schannel 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", ] [[package]] name = "net2" version = "0.2.33" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "winapi 0.3.8", ] [[package]] name = "notify" version = "4.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80ae4a7688d1fab81c5bf19c64fc8db920be8d519ce6336ed4e7efe024724dbd" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "inotify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "filetime", + "fsevent", + "fsevent-sys", + "inotify", + "libc", + "mio", + "mio-extras", + "walkdir", + "winapi 0.3.8", ] [[package]] name = "num-traits" version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", ] [[package]] name = "num_cpus" version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" dependencies = [ - "hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "hermit-abi", + "libc", ] [[package]] name = "oorandom" version = "11.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebcec7c9c2a95cacc7cd0ecb89d8a8454eca13906f6deb55258ffff0adeb9405" [[package]] name = "opaque-debug" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" [[package]] name = "opener" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13117407ca9d0caf3a0e74f97b490a7e64c0ae3aa90a8b7085544d0c37b6f3ae" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8", ] [[package]] name = "openssl" version = "0.10.28" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "cfg-if", + "foreign-types", + "lazy_static", + "libc", + "openssl-sys", ] [[package]] name = "openssl-probe" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" version = "0.9.54" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1024c0a59774200a555087a6da3f253a9095a5f344e353b212ac4c8b8e450986" dependencies = [ - "autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)", - "vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 1.0.0", + "cc", + "libc", + "pkg-config", + "vcpkg", ] [[package]] name = "output_vt100" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8", ] [[package]] name = "parking_lot" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" dependencies = [ - "lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "lock_api", + "parking_lot_core", + "rustc_version", ] [[package]] name = "parking_lot_core" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "cloudabi", + "libc", + "redox_syscall", + "rustc_version", + "smallvec 0.6.13", + "winapi 0.3.8", ] [[package]] name = "paste" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e1afe738d71b1ebab5f1207c055054015427dbfc7bbe9ee1266894156ec046" dependencies = [ - "paste-impl 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", + "paste-impl", + "proc-macro-hack", ] [[package]] name = "paste-impl" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d4dc4a7f6f743211c5aab239640a65091535d97d43d92a52bca435a640892bb" dependencies = [ - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", ] [[package]] name = "percent-encoding" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" [[package]] name = "percent-encoding" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pest" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" dependencies = [ - "ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ucd-trie", ] [[package]] name = "pest_derive" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" dependencies = [ - "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_generator 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "pest", + "pest_generator", ] [[package]] name = "pest_generator" version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27e5277315f6b4f27e0e6744feb5d5ba1891e7164871033d3c8344c6783b349a" dependencies = [ - "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "pest_meta 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "pest", + "pest_meta", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", ] [[package]] name = "pest_meta" version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" dependencies = [ - "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)", + "maplit", + "pest", + "sha-1", ] [[package]] name = "pkg-config" version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" [[package]] name = "plotters" version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e3bb8da247d27ae212529352020f3e5ee16e83c0c258061d27b08ab92675eeb" dependencies = [ - "js-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "web-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys", + "num-traits", + "wasm-bindgen", + "web-sys", ] [[package]] name = "ppv-lite86" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" [[package]] name = "pretty_assertions" version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "ctor 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", - "output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ansi_term", + "ctor", + "difference", + "output_vt100", ] [[package]] name = "proc-macro-error" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a" dependencies = [ - "proc-macro-error-attr 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-error-attr", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", + "version_check", ] [[package]] name = "proc-macro-error-attr" version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", + "syn-mid", + "version_check", ] [[package]] name = "proc-macro-hack" version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", ] [[package]] name = "proc-macro-nested" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" [[package]] name = "proc-macro2" version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0", ] [[package]] name = "proc-macro2" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" dependencies = [ - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.2.0", ] [[package]] name = "publicsuffix" version = "1.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b" dependencies = [ - "error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain", + "idna 0.2.0", + "lazy_static", + "regex", + "url 2.1.1", ] [[package]] name = "pulldown-cmark" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", ] [[package]] name = "quick-error" version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" [[package]] name = "quote" version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", ] [[package]] name = "quote" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9", ] [[package]] name = "rand" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" dependencies = [ - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi 0.3.8", ] [[package]] name = "rand" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7", + "libc", + "rand_chacha 0.1.1", + "rand_core 0.4.2", + "rand_hc 0.1.0", + "rand_isaac", + "rand_jitter", + "rand_os", + "rand_pcg", + "rand_xorshift", + "winapi 0.3.8", ] [[package]] name = "rand" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", + "libc", + "rand_chacha 0.2.1", + "rand_core 0.5.1", + "rand_hc 0.2.0", ] [[package]] name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7", + "rand_core 0.3.1", ] [[package]] name = "rand_chacha" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" dependencies = [ - "c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "c2-chacha", + "rand_core 0.5.1", ] [[package]] name = "rand_core" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" dependencies = [ - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.4.2", ] [[package]] name = "rand_core" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" [[package]] name = "rand_core" version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)", + "getrandom", ] [[package]] name = "rand_hc" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.5.1", ] [[package]] name = "rand_isaac" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "rand_jitter" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" dependencies = [ - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "rand_core 0.4.2", + "winapi 0.3.8", ] [[package]] name = "rand_os" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" dependencies = [ - "cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cloudabi", + "fuchsia-cprng", + "libc", + "rand_core 0.4.2", + "rdrand", + "winapi 0.3.8", ] [[package]] name = "rand_pcg" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" dependencies = [ - "autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "autocfg 0.1.7", + "rand_core 0.4.2", ] [[package]] name = "rand_xorshift" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "rayon" version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" dependencies = [ - "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque", + "either", + "rayon-core", ] [[package]] name = "rayon-core" version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" dependencies = [ - "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "lazy_static", + "num_cpus", ] [[package]] name = "rbx_binary" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b1c0c2b715bb763be1e27e5118e1f1ce0381f6c396a9cc8dd2c4b818cfa247d" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.3.418 (registry+https://github.com/rust-lang/crates.io-index)", - "snafu 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", + "log", + "lz4", + "rbx_dom_weak", + "rbx_reflection", + "snafu", ] [[package]] name = "rbx_dom_weak" version = "1.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978b65ce742f3cb38c0b64ca48601a5590e6be9a14d12025b9cba2fe553b78c4" dependencies = [ - "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "md5 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0", + "lazy_static", + "md5", + "serde", + "serde_derive", + "serde_repr", + "uuid 0.8.1", ] [[package]] name = "rbx_reflection" version = "3.3.418" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08c07c726f7d69ff7ba98a065f9b354edc90cfdaa9f7b973d5680920b972dc47" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "lazy_static", + "rbx_dom_weak", + "serde", ] [[package]] name = "rbx_xml" version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6431f38b84582ec4e4f40b525cdcc713d4a984dcc2e3eecd1a67ae4da1172fbd" dependencies = [ - "base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.3.418 (registry+https://github.com/rust-lang/crates.io-index)", - "xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.11.0", + "log", + "rbx_dom_weak", + "rbx_reflection", + "xml-rs", ] [[package]] name = "rdrand" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" dependencies = [ - "rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_core 0.3.1", ] [[package]] name = "redox_syscall" version = "0.1.56" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" [[package]] name = "regex" version = "1.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" dependencies = [ - "aho-corasick 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)", - "memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "regex-syntax 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)", - "thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", ] [[package]] name = "regex-automata" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" dependencies = [ - "byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "byteorder", ] [[package]] name = "regex-syntax" version = "0.6.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1132f845907680735a84409c3bebc64d1364a5683ffbce899550cd09d5eaefc1" [[package]] name = "remove_dir_all" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8", ] [[package]] name = "reqwest" version = "0.9.24" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" dependencies = [ - "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)", - "flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)", - "time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)", - "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "base64 0.10.1", + "bytes", + "cookie", + "cookie_store", + "encoding_rs", + "flate2", + "futures", + "http", + "hyper", + "hyper-tls", + "log", + "mime", + "mime_guess", + "native-tls", + "serde", + "serde_json", + "serde_urlencoded", + "time", + "tokio", + "tokio-executor", + "tokio-io", + "tokio-threadpool", + "tokio-timer", + "url 1.7.2", + "uuid 0.7.4", + "winreg", ] [[package]] name = "ritz" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" dependencies = [ - "htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "htmlescape", + "proc-macro-hack", + "proc-macro-nested", + "ritz_impl", ] [[package]] name = "ritz_impl" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" dependencies = [ - "proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro-hack", + "proc-macro2 0.4.30", + "quote 0.6.13", + "snax", ] [[package]] name = "rlua" version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25fa5b2c667bae0b6218361e96d365e414fe4a0fa80f476b9631aa2dea2c6881" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "bstr", + "cc", + "libc", + "num-traits", ] [[package]] name = "rojo" version = "0.6.0-alpha.3" dependencies = [ - "anyhow 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)", - "backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)", - "criterion 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)", - "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fs-err 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", - "humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", - "insta 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "memofs 0.1.1", - "notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)", - "opener 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_binary 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_reflection 3.3.418 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_xml 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)", - "regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rlua 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)", - "rojo-insta-ext 0.1.0", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "thiserror 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)", - "uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "anyhow", + "backtrace", + "criterion", + "crossbeam-channel", + "csv", + "env_logger", + "fs-err", + "futures", + "globset", + "humantime", + "hyper", + "insta", + "jod-thread", + "lazy_static", + "log", + "maplit", + "memofs", + "notify", + "opener", + "paste", + "pretty_assertions", + "rbx_binary", + "rbx_dom_weak", + "rbx_reflection", + "rbx_xml", + "regex", + "reqwest", + "ritz", + "rlua", + "rojo-insta-ext", + "serde", + "serde_json", + "serde_yaml", + "structopt", + "tempfile", + "termcolor", + "thiserror", + "tokio", + "uuid 0.8.1", + "walkdir", + "winreg", ] [[package]] name = "rojo-insta-ext" version = "0.1.0" dependencies = [ - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", + "serde_yaml", ] [[package]] name = "rojo-test" version = "0.1.0" dependencies = [ - "env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", - "insta 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "paste 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)", - "reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)", - "rojo 0.6.0-alpha.3", - "rojo-insta-ext 0.1.0", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)", - "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "env_logger", + "insta", + "log", + "paste", + "rbx_dom_weak", + "reqwest", + "rojo", + "rojo-insta-ext", + "serde", + "serde_json", + "serde_yaml", + "tempfile", + "walkdir", ] [[package]] name = "rustc-demangle" version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" [[package]] name = "rustc_version" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" dependencies = [ - "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "semver", ] [[package]] name = "ryu" version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" [[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" dependencies = [ - "winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util", ] [[package]] name = "schannel" version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507a9e6e8ffe0a4e0ebb9a10293e62fdf7657c06f1b8bb07a8fcf697d2abf295" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", + "winapi 0.3.8", ] [[package]] name = "scopeguard" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "security-framework" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97bbedbe81904398b6ebb054b3e912f99d55807125790f3198ac990d98def5b0" dependencies = [ - "bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "security-framework-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags", + "core-foundation", + "core-foundation-sys", + "security-framework-sys", ] [[package]] name = "security-framework-sys" version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06fd2f23e31ef68dd2328cc383bd493142e46107a3a0e24f7d734e3f3b80fe4c" dependencies = [ - "core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "core-foundation-sys", + "libc", ] [[package]] name = "semver" version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ - "semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "semver-parser", + "serde", ] [[package]] name = "semver-parser" version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" dependencies = [ - "serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", ] [[package]] name = "serde_json" version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" dependencies = [ - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "itoa", + "ryu", + "serde", ] [[package]] name = "serde_repr" version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", ] [[package]] name = "serde_urlencoded" version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" dependencies = [ - "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa", + "itoa", + "serde", + "url 1.7.2", ] [[package]] name = "serde_yaml" version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" dependencies = [ - "dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "dtoa", + "linked-hash-map", + "serde", + "yaml-rust", ] [[package]] name = "sha-1" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" dependencies = [ - "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", + "block-buffer", + "digest", + "fake-simd", + "opaque-debug", ] [[package]] name = "skeptic" version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" dependencies = [ - "bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)", - "walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "bytecount", + "cargo_metadata", + "error-chain", + "glob", + "pulldown-cmark", + "serde_json", + "tempdir", + "walkdir", ] [[package]] name = "slab" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "smallvec" version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" dependencies = [ - "maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)", + "maybe-uninit", ] [[package]] name = "smallvec" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" [[package]] name = "snafu" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "546db9181bce2aa22ed883c33d65603b76335b4c2533a98289f54265043de7a1" dependencies = [ - "doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "snafu-derive 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", + "doc-comment", + "snafu-derive", ] [[package]] name = "snafu-derive" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdc75da2e0323f297402fd9c8fdba709bb04e4c627cbe31d19a2c91fc8d9f0e2" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", ] [[package]] name = "snax" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef82be0baf3ae45701ab992230f1f4889c15984736d87f37558aea3e4e321af" dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30", ] [[package]] name = "string" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", ] [[package]] name = "strsim" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fe43617218c0805c6eb37160119dc3c548110a67786da7218d1c6555212f073" dependencies = [ - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "clap", + "lazy_static", + "structopt-derive", ] [[package]] name = "structopt-derive" version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6e79c80e0f4efd86ca960218d4e056249be189ff1c42824dcd9a7f51a56f0bd" dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro-error 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "heck", + "proc-macro-error", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", ] [[package]] name = "syn" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9", + "quote 1.0.3", + "unicode-xid 0.2.0", ] [[package]] name = "syn-mid" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", ] [[package]] name = "synstructure" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", + "unicode-xid 0.2.0", ] [[package]] name = "tempdir" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" dependencies = [ - "rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.6", + "remove_dir_all", ] [[package]] name = "tempfile" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "libc", + "rand 0.7.3", + "redox_syscall", + "remove_dir_all", + "winapi 0.3.8", ] [[package]] name = "termcolor" version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" dependencies = [ - "winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-util", ] [[package]] name = "termios" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" dependencies = [ - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", ] [[package]] name = "textwrap" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" dependencies = [ - "unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width", ] [[package]] name = "thiserror" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee14bf8e6767ab4c687c9e8bc003879e042a96fd67a3ba5934eadb6536bef4db" dependencies = [ - "thiserror-impl 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", + "thiserror-impl", ] [[package]] name = "thiserror-impl" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7b51e1fbc44b5a0840be594fbc0f960be09050f2617e61e6aa43bef97cd3ef4" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", ] [[package]] name = "thread_local" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" dependencies = [ - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "lazy_static", ] [[package]] name = "time" version = "0.1.42" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" dependencies = [ - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "libc", + "redox_syscall", + "winapi 0.3.8", ] [[package]] name = "tinytemplate" version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57a3c6667d3e65eb1bc3aed6fd14011c6cbc3a0665218ab7f5daf040b9ec371a" dependencies = [ - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", - "serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)", + "serde", + "serde_json", ] [[package]] name = "tokio" version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-uds 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "mio", + "num_cpus", + "tokio-codec", + "tokio-current-thread", + "tokio-executor", + "tokio-fs", + "tokio-io", + "tokio-reactor", + "tokio-sync", + "tokio-tcp", + "tokio-threadpool", + "tokio-timer", + "tokio-udp", + "tokio-uds", ] [[package]] name = "tokio-buf" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "either", + "futures", ] [[package]] name = "tokio-codec" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "tokio-io", ] [[package]] name = "tokio-current-thread" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "futures", + "tokio-executor", ] [[package]] name = "tokio-executor" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" dependencies = [ - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils", + "futures", ] [[package]] name = "tokio-fs" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", + "futures", + "tokio-io", + "tokio-threadpool", ] [[package]] name = "tokio-io" version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "log", ] [[package]] name = "tokio-reactor" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" dependencies = [ - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils", + "futures", + "lazy_static", + "log", + "mio", + "num_cpus", + "parking_lot", + "slab", + "tokio-executor", + "tokio-io", + "tokio-sync", ] [[package]] name = "tokio-sync" version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" dependencies = [ - "fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "fnv", + "futures", ] [[package]] name = "tokio-tcp" version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "iovec", + "mio", + "tokio-io", + "tokio-reactor", ] [[package]] name = "tokio-threadpool" version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" dependencies = [ - "crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-deque", + "crossbeam-queue", + "crossbeam-utils", + "futures", + "lazy_static", + "log", + "num_cpus", + "slab", + "tokio-executor", ] [[package]] name = "tokio-timer" version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" dependencies = [ - "crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "crossbeam-utils", + "futures", + "slab", + "tokio-executor", ] [[package]] name = "tokio-udp" version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "log", + "mio", + "tokio-codec", + "tokio-io", + "tokio-reactor", ] [[package]] name = "tokio-uds" version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" dependencies = [ - "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)", - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)", - "mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)", - "tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)", + "bytes", + "futures", + "iovec", + "libc", + "log", + "mio", + "mio-uds", + "tokio-codec", + "tokio-io", + "tokio-reactor", ] [[package]] name = "try-lock" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" [[package]] name = "try_from" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", ] [[package]] name = "typenum" version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" [[package]] name = "ucd-trie" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" [[package]] name = "unicase" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" dependencies = [ - "version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "version_check", ] [[package]] name = "unicode-bidi" version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" dependencies = [ - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", + "matches", ] [[package]] name = "unicode-normalization" version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" dependencies = [ - "smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "smallvec 1.2.0", ] [[package]] name = "unicode-segmentation" version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" [[package]] name = "unicode-width" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" [[package]] name = "unicode-xid" version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" [[package]] name = "url" version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" dependencies = [ - "idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.1.5", + "matches", + "percent-encoding 1.0.1", ] [[package]] name = "url" version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" dependencies = [ - "idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", - "percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "idna 0.2.0", + "matches", + "percent-encoding 2.1.0", ] [[package]] name = "uuid" version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" dependencies = [ - "rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.6.5", ] [[package]] name = "uuid" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" dependencies = [ - "rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)", - "serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.7.3", + "serde", ] [[package]] name = "vcpkg" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" [[package]] name = "vec_map" version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" [[package]] name = "version_check" version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" [[package]] name = "walkdir" version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" dependencies = [ - "same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "same-file", + "winapi 0.3.8", + "winapi-util", ] [[package]] name = "want" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" dependencies = [ - "futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", + "futures", + "log", + "try-lock", ] [[package]] name = "wasi" version = "0.9.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasm-bindgen" version = "0.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3557c397ab5a8e347d434782bcd31fc1483d927a6826804cec05cc792ee2519d" dependencies = [ - "cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if", + "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" version = "0.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0da9c9a19850d3af6df1cb9574970b566d617ecfaf36eb0b706b6f3ef9bd2f8" dependencies = [ - "bumpalo 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "bumpalo", + "lazy_static", + "log", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" version = "0.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f6fde1d36e75a714b5fe0cffbb78978f222ea6baebb726af13c78869fdb4205" dependencies = [ - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-macro-support 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 1.0.3", + "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" version = "0.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25bda4168030a6412ea8a047e27238cadf56f0e53516e1e83fec0a8b7c786f6d" dependencies = [ - "proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-backend 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen-shared 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 1.0.9", + "quote 1.0.3", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" version = "0.2.59" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc9f36ad51f25b0219a3d4d13b90eb44cd075dff8b6280cca015775d7acaddd8" [[package]] name = "web-sys" version = "0.3.36" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721c6263e2c66fd44501cc5efbfa2b7dfa775d13e4ea38c46299646ed1f9c70a" dependencies = [ - "js-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)", - "wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)", + "js-sys", + "wasm-bindgen", ] [[package]] name = "winapi" version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi" version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" dependencies = [ - "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] name = "winapi-build" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8", ] [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "winreg" version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" dependencies = [ - "winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.8", ] [[package]] name = "ws2_32-sys" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" dependencies = [ - "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8", + "winapi-build", ] [[package]] name = "xml-rs" version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" [[package]] name = "yaml-rust" version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" dependencies = [ - "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)", + "linked-hash-map", ] - -[metadata] -"checksum adler32 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" -"checksum aho-corasick 0.7.9 (registry+https://github.com/rust-lang/crates.io-index)" = "d5e63fd144e18ba274ae7095c0197a870a7b9468abc801dd62f190d80817d2ec" -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum anyhow 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)" = "013a6e0a2cbe3d20f9c60b65458f7a7f7a5e636c5d0f45a5a6aee5d4b1f01785" -"checksum atty 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -"checksum autocfg 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" -"checksum autocfg 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" -"checksum backtrace 0.3.45 (registry+https://github.com/rust-lang/crates.io-index)" = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8" -"checksum backtrace-sys 0.1.33 (registry+https://github.com/rust-lang/crates.io-index)" = "e17b52e737c40a7d75abca20b29a19a0eb7ba9fc72c5a72dd282a0a3c2c0dc35" -"checksum base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -"checksum base64 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" -"checksum bitflags 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" -"checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" -"checksum block-padding 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -"checksum bstr 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "502ae1441a0a5adb8fbd38a5955a6416b9493e92b465de5e4a9bde6a539c2c48" -"checksum bumpalo 3.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742" -"checksum byte-tools 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -"checksum bytecount 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" -"checksum byteorder 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" -"checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -"checksum c2-chacha 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -"checksum cargo_metadata 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -"checksum cast 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b9434b9a5aa1450faa3f9cb14ea0e8c53bb5d2b3c1bfd1ab4fc03e9f33fbfb0" -"checksum cc 1.0.50 (registry+https://github.com/rust-lang/crates.io-index)" = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" -"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" -"checksum clicolors-control 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" -"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -"checksum console 0.9.2 (registry+https://github.com/rust-lang/crates.io-index)" = "45e0f3986890b3acbc782009e2629dfe2baa430ac091519ce3be26164a2ae6c0" -"checksum cookie 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" -"checksum cookie_store 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" -"checksum core-foundation 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" -"checksum core-foundation-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" -"checksum crc32fast 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" -"checksum criterion 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "1fc755679c12bda8e5523a71e4d654b6bf2e14bd838dfc48cde6559a05caf7d1" -"checksum criterion-plot 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a01e15e0ea58e8234f96146b1f91fa9d0e4dd7a38da93ff7a75d42c0b9d3a545" -"checksum crossbeam-channel 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" -"checksum crossbeam-deque 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" -"checksum crossbeam-epoch 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" -"checksum crossbeam-queue 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" -"checksum crossbeam-utils 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -"checksum csv 1.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" -"checksum csv-core 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" -"checksum ctor 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "47c5e5ac752e18207b12e16b10631ae5f7f68f8805f335f9b817ead83d9ffce1" -"checksum difference 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "524cbf6897b527295dff137cec09ecf3a05f4fddffd7dfcd1585403449e74198" -"checksum digest 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" -"checksum doc-comment 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97" -"checksum dtoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" -"checksum either 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" -"checksum encode_unicode 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" -"checksum encoding_rs 0.8.22 (registry+https://github.com/rust-lang/crates.io-index)" = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" -"checksum env_logger 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" -"checksum error-chain 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd" -"checksum failure 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" -"checksum failure_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" -"checksum fake-simd 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" -"checksum filetime 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" -"checksum flate2 1.0.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" -"checksum fnv 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" -"checksum foreign-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -"checksum foreign-types-shared 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" -"checksum fs-err 2.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c1a51f8b7158efbe531f7baa74e38e49fbc41239e5d66720bb37ed39c27c241a" -"checksum fsevent 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" -"checksum fsevent-sys 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" -"checksum fuchsia-cprng 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum futures 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" -"checksum futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -"checksum generic-array 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c68f0274ae0e023facc3c97b2e00f076be70e254bc851d972503b328db79b2ec" -"checksum getrandom 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" -"checksum glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" -"checksum globset 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" -"checksum h2 0.1.26 (registry+https://github.com/rust-lang/crates.io-index)" = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" -"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" -"checksum hermit-abi 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8" -"checksum htmlescape 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" -"checksum http 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" -"checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" -"checksum httparse 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" -"checksum humantime 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -"checksum hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)" = "9dbe6ed1438e1f8ad955a4701e9a944938e9519f6888d12d8558b645e247d5f6" -"checksum hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" -"checksum idna 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -"checksum idna 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" -"checksum indexmap 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" -"checksum inotify 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "24e40d6fd5d64e2082e0c796495c8ef5ad667a96d03e5aaa0becfd9d47bcbfb8" -"checksum inotify-sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" -"checksum insta 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8df742abee84dbf27d20869c9adf77b0d8f7ea3eead13c2c9e3998d136a97058" -"checksum iovec 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -"checksum itertools 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" -"checksum itoa 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)" = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" -"checksum jod-thread 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2f52a11f73b88fab829a0e4d9e13ea5982c7ac457c72eb3541d82a4afdfce4ff" -"checksum js-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1cb931d43e71f560c81badb0191596562bafad2be06a3f9025b845c847c60df5" -"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -"checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -"checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" -"checksum libc 0.2.67 (registry+https://github.com/rust-lang/crates.io-index)" = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" -"checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" -"checksum lock_api 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" -"checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" -"checksum lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)" = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" -"checksum lz4-sys 1.8.3 (registry+https://github.com/rust-lang/crates.io-index)" = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" -"checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" -"checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" -"checksum maybe-uninit 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" -"checksum md5 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" -"checksum memchr 2.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" -"checksum memoffset 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" -"checksum mime 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" -"checksum mime_guess 2.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" -"checksum miniz_oxide 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" -"checksum mio 0.6.21 (registry+https://github.com/rust-lang/crates.io-index)" = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" -"checksum mio-extras 2.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" -"checksum miow 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" -"checksum native-tls 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" -"checksum net2 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" -"checksum notify 4.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "80ae4a7688d1fab81c5bf19c64fc8db920be8d519ce6336ed4e7efe024724dbd" -"checksum num-traits 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" -"checksum num_cpus 1.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" -"checksum oorandom 11.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ebcec7c9c2a95cacc7cd0ecb89d8a8454eca13906f6deb55258ffff0adeb9405" -"checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" -"checksum opener 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "13117407ca9d0caf3a0e74f97b490a7e64c0ae3aa90a8b7085544d0c37b6f3ae" -"checksum openssl 0.10.28 (registry+https://github.com/rust-lang/crates.io-index)" = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" -"checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-sys 0.9.54 (registry+https://github.com/rust-lang/crates.io-index)" = "1024c0a59774200a555087a6da3f253a9095a5f344e353b212ac4c8b8e450986" -"checksum output_vt100 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" -"checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -"checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -"checksum paste 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "63e1afe738d71b1ebab5f1207c055054015427dbfc7bbe9ee1266894156ec046" -"checksum paste-impl 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc4a7f6f743211c5aab239640a65091535d97d43d92a52bca435a640892bb" -"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" -"checksum percent-encoding 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" -"checksum pest 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" -"checksum pest_derive 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" -"checksum pest_generator 2.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "27e5277315f6b4f27e0e6744feb5d5ba1891e7164871033d3c8344c6783b349a" -"checksum pest_meta 2.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" -"checksum pkg-config 0.3.17 (registry+https://github.com/rust-lang/crates.io-index)" = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" -"checksum plotters 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "4e3bb8da247d27ae212529352020f3e5ee16e83c0c258061d27b08ab92675eeb" -"checksum ppv-lite86 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" -"checksum pretty_assertions 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3f81e1644e1b54f5a68959a29aa86cde704219254669da328ecfdf6a1f09d427" -"checksum proc-macro-error 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a" -"checksum proc-macro-error-attr 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a" -"checksum proc-macro-hack 0.5.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" -"checksum proc-macro-nested 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum proc-macro2 1.0.9 (registry+https://github.com/rust-lang/crates.io-index)" = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" -"checksum publicsuffix 1.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b" -"checksum pulldown-cmark 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" -"checksum quick-error 1.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" -"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" -"checksum quote 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" -"checksum rand 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -"checksum rand 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -"checksum rand 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" -"checksum rand_chacha 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -"checksum rand_chacha 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" -"checksum rand_core 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -"checksum rand_core 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" -"checksum rand_core 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" -"checksum rand_hc 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -"checksum rand_hc 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -"checksum rand_isaac 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -"checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -"checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -"checksum rand_pcg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -"checksum rand_xorshift 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -"checksum rayon 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" -"checksum rayon-core 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" -"checksum rbx_binary 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5b1c0c2b715bb763be1e27e5118e1f1ce0381f6c396a9cc8dd2c4b818cfa247d" -"checksum rbx_dom_weak 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "978b65ce742f3cb38c0b64ca48601a5590e6be9a14d12025b9cba2fe553b78c4" -"checksum rbx_reflection 3.3.418 (registry+https://github.com/rust-lang/crates.io-index)" = "08c07c726f7d69ff7ba98a065f9b354edc90cfdaa9f7b973d5680920b972dc47" -"checksum rbx_xml 0.11.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6431f38b84582ec4e4f40b525cdcc713d4a984dcc2e3eecd1a67ae4da1172fbd" -"checksum rdrand 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -"checksum redox_syscall 0.1.56 (registry+https://github.com/rust-lang/crates.io-index)" = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" -"checksum regex 1.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" -"checksum regex-automata 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" -"checksum regex-syntax 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "1132f845907680735a84409c3bebc64d1364a5683ffbce899550cd09d5eaefc1" -"checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" -"checksum reqwest 0.9.24 (registry+https://github.com/rust-lang/crates.io-index)" = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" -"checksum ritz 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e7b52479a28408dacd24819d32f3562146b5f03eb0a06a8b2d7b11e34fbfe52d" -"checksum ritz_impl 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa7bba143ce94ca7e580094b8c4f6338b960b3bfa5ad7f479700e414b24d5d7b" -"checksum rlua 0.17.0 (registry+https://github.com/rust-lang/crates.io-index)" = "25fa5b2c667bae0b6218361e96d365e414fe4a0fa80f476b9631aa2dea2c6881" -"checksum rustc-demangle 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" -"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -"checksum ryu 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" -"checksum same-file 1.0.6 (registry+https://github.com/rust-lang/crates.io-index)" = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" -"checksum schannel 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "507a9e6e8ffe0a4e0ebb9a10293e62fdf7657c06f1b8bb07a8fcf697d2abf295" -"checksum scopeguard 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" -"checksum security-framework 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "97bbedbe81904398b6ebb054b3e912f99d55807125790f3198ac990d98def5b0" -"checksum security-framework-sys 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "06fd2f23e31ef68dd2328cc383bd493142e46107a3a0e24f7d734e3f3b80fe4c" -"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" -"checksum serde 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" -"checksum serde_derive 1.0.104 (registry+https://github.com/rust-lang/crates.io-index)" = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" -"checksum serde_json 1.0.48 (registry+https://github.com/rust-lang/crates.io-index)" = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" -"checksum serde_repr 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" -"checksum serde_urlencoded 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" -"checksum serde_yaml 0.8.11 (registry+https://github.com/rust-lang/crates.io-index)" = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" -"checksum sha-1 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" -"checksum skeptic 0.13.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" -"checksum slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" -"checksum smallvec 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" -"checksum smallvec 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" -"checksum snafu 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "546db9181bce2aa22ed883c33d65603b76335b4c2533a98289f54265043de7a1" -"checksum snafu-derive 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bdc75da2e0323f297402fd9c8fdba709bb04e4c627cbe31d19a2c91fc8d9f0e2" -"checksum snax 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7ef82be0baf3ae45701ab992230f1f4889c15984736d87f37558aea3e4e321af" -"checksum string 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "3fe43617218c0805c6eb37160119dc3c548110a67786da7218d1c6555212f073" -"checksum structopt-derive 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "c6e79c80e0f4efd86ca960218d4e056249be189ff1c42824dcd9a7f51a56f0bd" -"checksum syn 1.0.16 (registry+https://github.com/rust-lang/crates.io-index)" = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" -"checksum syn-mid 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" -"checksum synstructure 0.12.3 (registry+https://github.com/rust-lang/crates.io-index)" = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" -"checksum tempdir 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -"checksum tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" -"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" -"checksum termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum thiserror 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "ee14bf8e6767ab4c687c9e8bc003879e042a96fd67a3ba5934eadb6536bef4db" -"checksum thiserror-impl 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "a7b51e1fbc44b5a0840be594fbc0f960be09050f2617e61e6aa43bef97cd3ef4" -"checksum thread_local 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" -"checksum time 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" -"checksum tinytemplate 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "57a3c6667d3e65eb1bc3aed6fd14011c6cbc3a0665218ab7f5daf040b9ec371a" -"checksum tokio 0.1.22 (registry+https://github.com/rust-lang/crates.io-index)" = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" -"checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" -"checksum tokio-codec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" -"checksum tokio-current-thread 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" -"checksum tokio-executor 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" -"checksum tokio-fs 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" -"checksum tokio-io 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" -"checksum tokio-reactor 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" -"checksum tokio-sync 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" -"checksum tokio-tcp 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" -"checksum tokio-threadpool 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)" = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" -"checksum tokio-timer 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" -"checksum tokio-udp 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" -"checksum tokio-uds 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" -"checksum try-lock 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" -"checksum try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" -"checksum typenum 1.11.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" -"checksum ucd-trie 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" -"checksum unicase 2.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" -"checksum unicode-normalization 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" -"checksum unicode-segmentation 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" -"checksum unicode-width 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum unicode-xid 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" -"checksum url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -"checksum url 2.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" -"checksum uuid 0.7.4 (registry+https://github.com/rust-lang/crates.io-index)" = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" -"checksum uuid 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" -"checksum vcpkg 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" -"checksum version_check 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" -"checksum walkdir 2.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" -"checksum want 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" -"checksum wasi 0.9.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" -"checksum wasm-bindgen 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "3557c397ab5a8e347d434782bcd31fc1483d927a6826804cec05cc792ee2519d" -"checksum wasm-bindgen-backend 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "e0da9c9a19850d3af6df1cb9574970b566d617ecfaf36eb0b706b6f3ef9bd2f8" -"checksum wasm-bindgen-macro 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "0f6fde1d36e75a714b5fe0cffbb78978f222ea6baebb726af13c78869fdb4205" -"checksum wasm-bindgen-macro-support 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "25bda4168030a6412ea8a047e27238cadf56f0e53516e1e83fec0a8b7c786f6d" -"checksum wasm-bindgen-shared 0.2.59 (registry+https://github.com/rust-lang/crates.io-index)" = "fc9f36ad51f25b0219a3d4d13b90eb44cd075dff8b6280cca015775d7acaddd8" -"checksum web-sys 0.3.36 (registry+https://github.com/rust-lang/crates.io-index)" = "721c6263e2c66fd44501cc5efbfa2b7dfa775d13e4ea38c46299646ed1f9c70a" -"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" -"checksum winapi 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" -"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" -"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" -"checksum winapi-util 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80" -"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -"checksum winreg 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" -"checksum ws2_32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -"checksum xml-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" -"checksum yaml-rust 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" From f43777e37e71520e1cfba84c5aaed81bc3083e07 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 25 Mar 2020 17:01:28 -0700 Subject: [PATCH 1025/1504] Require a Rojo project again (#307) --- ... => rojo_test__build_test__rbxmx_ref.snap} | 0 .../deep_nesting/default.project.json | 6 + .../level-1/level-2/level-3/.gitkeep | 0 .../init_with_children/default.project.json | 6 + .../init_with_children/{ => src}/init.lua | 0 .../init_with_children/{ => src}/other.lua | 0 rojo-test/build-tests/plain.txt | 1 - .../rbxmx_ref/default.project.json | 6 + .../model.rbxmx} | 0 .../add_folder/default.project.json | 6 + .../add_folder/src}/.gitkeep | 0 .../edit_init/default.project.json | 6 + .../serve-tests/edit_init/{ => src}/init.lua | 0 rojo-test/serve-tests/just_txt.txt | 1 - .../serve-tests/move_folder_of_stuff/.gitkeep | 0 .../move_folder_of_stuff/default.project.json | 6 + .../src}/.gitkeep | 0 .../remove_file/default.project.json | 6 + .../remove_file/{ => src}/hello.txt | 0 .../serve-tests/scripts/default.project.json | 6 + .../scripts/{ => src}/bar.server.lua | 0 .../serve-tests/scripts/{ => src}/foo.lua | 0 rojo-test/src/build_test.rs | 12 +- rojo-test/src/serve_test.rs | 30 +-- src/serve_session.rs | 245 ++---------------- ...session__change_file_in_project_after.snap | 35 --- ...ession__change_file_in_project_before.snap | 35 --- ...session__change_file_in_project_patch.snap | 16 -- ...rve_session__change_script_meta_after.snap | 36 --- ...ve_session__change_script_meta_before.snap | 36 --- ...rve_session__change_script_meta_patch.snap | 20 -- ..._serve_session__change_txt_file_after.snap | 20 -- ...serve_session__change_txt_file_before.snap | 20 -- ..._serve_session__change_txt_file_patch.snap | 16 -- ...e_session__serve_session__just_folder.snap | 20 -- ...n__serve_session__project_with_folder.snap | 37 --- ...sion__serve_session__script_with_meta.snap | 36 --- src/web/ui.rs | 2 +- 38 files changed, 70 insertions(+), 596 deletions(-) rename rojo-test/build-test-snapshots/{rojo_test__build_test__rbxmx_ref.rbxmx.snap => rojo_test__build_test__rbxmx_ref.snap} (100%) create mode 100644 rojo-test/build-tests/deep_nesting/default.project.json rename rojo-test/build-tests/deep_nesting/{ => src}/level-1/level-2/level-3/.gitkeep (100%) create mode 100644 rojo-test/build-tests/init_with_children/default.project.json rename rojo-test/build-tests/init_with_children/{ => src}/init.lua (100%) rename rojo-test/build-tests/init_with_children/{ => src}/other.lua (100%) delete mode 100644 rojo-test/build-tests/plain.txt create mode 100644 rojo-test/build-tests/rbxmx_ref/default.project.json rename rojo-test/build-tests/{rbxmx_ref.rbxmx => rbxmx_ref/model.rbxmx} (100%) create mode 100644 rojo-test/serve-tests/add_folder/default.project.json rename rojo-test/{build-tests/plain_gitkeep => serve-tests/add_folder/src}/.gitkeep (100%) create mode 100644 rojo-test/serve-tests/edit_init/default.project.json rename rojo-test/serve-tests/edit_init/{ => src}/init.lua (100%) delete mode 100644 rojo-test/serve-tests/just_txt.txt delete mode 100644 rojo-test/serve-tests/move_folder_of_stuff/.gitkeep create mode 100644 rojo-test/serve-tests/move_folder_of_stuff/default.project.json rename rojo-test/serve-tests/{add_folder => move_folder_of_stuff/src}/.gitkeep (100%) create mode 100644 rojo-test/serve-tests/remove_file/default.project.json rename rojo-test/serve-tests/remove_file/{ => src}/hello.txt (100%) create mode 100644 rojo-test/serve-tests/scripts/default.project.json rename rojo-test/serve-tests/scripts/{ => src}/bar.server.lua (100%) rename rojo-test/serve-tests/scripts/{ => src}/foo.lua (100%) delete mode 100644 src/snapshots/librojo__serve_session__serve_session__change_file_in_project_after.snap delete mode 100644 src/snapshots/librojo__serve_session__serve_session__change_file_in_project_before.snap delete mode 100644 src/snapshots/librojo__serve_session__serve_session__change_file_in_project_patch.snap delete mode 100644 src/snapshots/librojo__serve_session__serve_session__change_script_meta_after.snap delete mode 100644 src/snapshots/librojo__serve_session__serve_session__change_script_meta_before.snap delete mode 100644 src/snapshots/librojo__serve_session__serve_session__change_script_meta_patch.snap delete mode 100644 src/snapshots/librojo__serve_session__serve_session__change_txt_file_after.snap delete mode 100644 src/snapshots/librojo__serve_session__serve_session__change_txt_file_before.snap delete mode 100644 src/snapshots/librojo__serve_session__serve_session__change_txt_file_patch.snap delete mode 100644 src/snapshots/librojo__serve_session__serve_session__just_folder.snap delete mode 100644 src/snapshots/librojo__serve_session__serve_session__project_with_folder.snap delete mode 100644 src/snapshots/librojo__serve_session__serve_session__script_with_meta.snap diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_ref.rbxmx.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_ref.snap similarity index 100% rename from rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_ref.rbxmx.snap rename to rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_ref.snap diff --git a/rojo-test/build-tests/deep_nesting/default.project.json b/rojo-test/build-tests/deep_nesting/default.project.json new file mode 100644 index 00000000..a4768233 --- /dev/null +++ b/rojo-test/build-tests/deep_nesting/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "deep_nesting", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/deep_nesting/level-1/level-2/level-3/.gitkeep b/rojo-test/build-tests/deep_nesting/src/level-1/level-2/level-3/.gitkeep similarity index 100% rename from rojo-test/build-tests/deep_nesting/level-1/level-2/level-3/.gitkeep rename to rojo-test/build-tests/deep_nesting/src/level-1/level-2/level-3/.gitkeep diff --git a/rojo-test/build-tests/init_with_children/default.project.json b/rojo-test/build-tests/init_with_children/default.project.json new file mode 100644 index 00000000..70d83a8b --- /dev/null +++ b/rojo-test/build-tests/init_with_children/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "init_with_children", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/init_with_children/init.lua b/rojo-test/build-tests/init_with_children/src/init.lua similarity index 100% rename from rojo-test/build-tests/init_with_children/init.lua rename to rojo-test/build-tests/init_with_children/src/init.lua diff --git a/rojo-test/build-tests/init_with_children/other.lua b/rojo-test/build-tests/init_with_children/src/other.lua similarity index 100% rename from rojo-test/build-tests/init_with_children/other.lua rename to rojo-test/build-tests/init_with_children/src/other.lua diff --git a/rojo-test/build-tests/plain.txt b/rojo-test/build-tests/plain.txt deleted file mode 100644 index 8948f215..00000000 --- a/rojo-test/build-tests/plain.txt +++ /dev/null @@ -1 +0,0 @@ -This is a bare text file with no project. \ No newline at end of file diff --git a/rojo-test/build-tests/rbxmx_ref/default.project.json b/rojo-test/build-tests/rbxmx_ref/default.project.json new file mode 100644 index 00000000..61c7d083 --- /dev/null +++ b/rojo-test/build-tests/rbxmx_ref/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "rbxmx_ref", + "tree": { + "$path": "model.rbxmx" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/rbxmx_ref.rbxmx b/rojo-test/build-tests/rbxmx_ref/model.rbxmx similarity index 100% rename from rojo-test/build-tests/rbxmx_ref.rbxmx rename to rojo-test/build-tests/rbxmx_ref/model.rbxmx diff --git a/rojo-test/serve-tests/add_folder/default.project.json b/rojo-test/serve-tests/add_folder/default.project.json new file mode 100644 index 00000000..6831b978 --- /dev/null +++ b/rojo-test/serve-tests/add_folder/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "add_folder", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/plain_gitkeep/.gitkeep b/rojo-test/serve-tests/add_folder/src/.gitkeep similarity index 100% rename from rojo-test/build-tests/plain_gitkeep/.gitkeep rename to rojo-test/serve-tests/add_folder/src/.gitkeep diff --git a/rojo-test/serve-tests/edit_init/default.project.json b/rojo-test/serve-tests/edit_init/default.project.json new file mode 100644 index 00000000..88d3bdc6 --- /dev/null +++ b/rojo-test/serve-tests/edit_init/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "edit_init", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/edit_init/init.lua b/rojo-test/serve-tests/edit_init/src/init.lua similarity index 100% rename from rojo-test/serve-tests/edit_init/init.lua rename to rojo-test/serve-tests/edit_init/src/init.lua diff --git a/rojo-test/serve-tests/just_txt.txt b/rojo-test/serve-tests/just_txt.txt deleted file mode 100644 index 5dd01c17..00000000 --- a/rojo-test/serve-tests/just_txt.txt +++ /dev/null @@ -1 +0,0 @@ -Hello, world! \ No newline at end of file diff --git a/rojo-test/serve-tests/move_folder_of_stuff/.gitkeep b/rojo-test/serve-tests/move_folder_of_stuff/.gitkeep deleted file mode 100644 index e69de29b..00000000 diff --git a/rojo-test/serve-tests/move_folder_of_stuff/default.project.json b/rojo-test/serve-tests/move_folder_of_stuff/default.project.json new file mode 100644 index 00000000..e4a6a2e9 --- /dev/null +++ b/rojo-test/serve-tests/move_folder_of_stuff/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "move_folder_of_stuff", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/add_folder/.gitkeep b/rojo-test/serve-tests/move_folder_of_stuff/src/.gitkeep similarity index 100% rename from rojo-test/serve-tests/add_folder/.gitkeep rename to rojo-test/serve-tests/move_folder_of_stuff/src/.gitkeep diff --git a/rojo-test/serve-tests/remove_file/default.project.json b/rojo-test/serve-tests/remove_file/default.project.json new file mode 100644 index 00000000..6055a0bf --- /dev/null +++ b/rojo-test/serve-tests/remove_file/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "remove_file", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/remove_file/hello.txt b/rojo-test/serve-tests/remove_file/src/hello.txt similarity index 100% rename from rojo-test/serve-tests/remove_file/hello.txt rename to rojo-test/serve-tests/remove_file/src/hello.txt diff --git a/rojo-test/serve-tests/scripts/default.project.json b/rojo-test/serve-tests/scripts/default.project.json new file mode 100644 index 00000000..52987f7d --- /dev/null +++ b/rojo-test/serve-tests/scripts/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "scripts", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/scripts/bar.server.lua b/rojo-test/serve-tests/scripts/src/bar.server.lua similarity index 100% rename from rojo-test/serve-tests/scripts/bar.server.lua rename to rojo-test/serve-tests/scripts/src/bar.server.lua diff --git a/rojo-test/serve-tests/scripts/foo.lua b/rojo-test/serve-tests/scripts/src/foo.lua similarity index 100% rename from rojo-test/serve-tests/scripts/foo.lua rename to rojo-test/serve-tests/scripts/src/foo.lua diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index a5d18467..c51cacf9 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -35,12 +35,12 @@ gen_build_tests! { json_model_legacy_name, module_in_folder, module_init, - plain_gitkeep, rbxm_in_folder, rbxmx_in_folder, script_meta_disabled, server_in_folder, server_init, + rbxmx_ref, txt, txt_in_folder, } @@ -52,16 +52,6 @@ gen_build_tests! { ignore_glob_spec, } -#[test] -fn build_plain_txt() { - run_build_test("plain.txt"); -} - -#[test] -fn build_rbxmx_ref() { - run_build_test("rbxmx_ref.rbxmx"); -} - fn run_build_test(test_name: &str) { let build_test_path = get_build_tests_path(); let working_dir = get_working_dir_path(); diff --git a/rojo-test/src/serve_test.rs b/rojo-test/src/serve_test.rs index 80ecae77..daac30e2 100644 --- a/rojo-test/src/serve_test.rs +++ b/rojo-test/src/serve_test.rs @@ -35,7 +35,7 @@ fn scripts() { read_response.intern_and_redact(&mut redactions, root_id) ); - fs::write(session.path().join("foo.lua"), "Updated foo!").unwrap(); + fs::write(session.path().join("src/foo.lua"), "Updated foo!").unwrap(); let subscribe_response = session.get_api_subscribe(0).unwrap(); assert_yaml_snapshot!( @@ -51,26 +51,6 @@ fn scripts() { }); } -#[test] -fn just_txt() { - run_serve_test("just_txt.txt", |session, mut redactions| { - let info = session.get_api_rojo().unwrap(); - let root_id = info.root_instance_id; - - assert_yaml_snapshot!("just_txt_info", redactions.redacted_yaml(info)); - - let read_response = session.get_api_read(root_id).unwrap(); - assert_yaml_snapshot!( - "just_txt_all", - read_response.intern_and_redact(&mut redactions, root_id) - ); - - fs::write(session.path(), "Changed content!").unwrap(); - - // TODO: Directly served files currently don't trigger changed events! - }); -} - #[test] fn add_folder() { run_serve_test("add_folder", |session, mut redactions| { @@ -85,7 +65,7 @@ fn add_folder() { read_response.intern_and_redact(&mut redactions, root_id) ); - fs::create_dir(session.path().join("my-new-folder")).unwrap(); + fs::create_dir(session.path().join("src/my-new-folder")).unwrap(); let subscribe_response = session.get_api_subscribe(0).unwrap(); assert_yaml_snapshot!( @@ -115,7 +95,7 @@ fn remove_file() { read_response.intern_and_redact(&mut redactions, root_id) ); - fs::remove_file(session.path().join("hello.txt")).unwrap(); + fs::remove_file(session.path().join("src/hello.txt")).unwrap(); let subscribe_response = session.get_api_subscribe(0).unwrap(); assert_yaml_snapshot!( @@ -145,7 +125,7 @@ fn edit_init() { read_response.intern_and_redact(&mut redactions, root_id) ); - fs::write(session.path().join("init.lua"), b"-- Edited contents").unwrap(); + fs::write(session.path().join("src/init.lua"), b"-- Edited contents").unwrap(); let subscribe_response = session.get_api_subscribe(0).unwrap(); assert_yaml_snapshot!( @@ -191,7 +171,7 @@ fn move_folder_of_stuff() { // We're hoping that this rename gets picked up as one event. This test // will fail otherwise. - fs::rename(stuff_path, session.path().join("new-stuff")).unwrap(); + fs::rename(stuff_path, session.path().join("src/new-stuff")).unwrap(); let subscribe_response = session.get_api_subscribe(0).unwrap(); assert_yaml_snapshot!( diff --git a/src/serve_session.rs b/src/serve_session.rs index 2423bf52..6263c2e0 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -47,15 +47,12 @@ pub struct ServeSession { /// diagnostics. start_time: Instant, - /// The root project for the serve session, if there was one defined. + /// The root project for the serve session. /// /// This will be defined if a folder with a `default.project.json` file was /// used for starting the serve session, or if the user specified a full /// path to a `.project.json` file. - /// - /// If `root_project` is None, values from the project should be treated as - /// their defaults. - root_project: Option, + root_project: Project, /// A randomly generated ID for this serve session. It's used to ensure that /// a client doesn't begin connecting to a different server part way through @@ -103,7 +100,9 @@ impl ServeSession { log::trace!("Starting new ServeSession at path {}", start_path.display()); log::trace!("Loading project file from {}", start_path.display()); - let root_project = Project::load_fuzzy(start_path).expect("TODO: Project load failed"); + let root_project = Project::load_fuzzy(start_path) + .expect("TODO: Project load failed") + .expect("TODO: No project was found."); let mut tree = RojoTree::new(InstancePropertiesWithMeta { properties: RbxInstanceProperties { @@ -118,14 +117,15 @@ impl ServeSession { let mut instance_context = InstanceContext::default(); - if let Some(project) = &root_project { - let rules = project.glob_ignore_paths.iter().map(|glob| PathIgnoreRule { + let rules = root_project + .glob_ignore_paths + .iter() + .map(|glob| PathIgnoreRule { glob: glob.clone(), - base_path: project.folder_location().to_path_buf(), + base_path: root_project.folder_location().to_path_buf(), }); - instance_context.add_path_ignore_rules(rules); - } + instance_context.add_path_ignore_rules(rules); log::trace!("Generating snapshot of instances from VFS"); let snapshot = snapshot_from_vfs(&instance_context, &vfs, &start_path) @@ -194,16 +194,12 @@ impl ServeSession { self.session_id } - pub fn project_name(&self) -> Option<&str> { - self.root_project - .as_ref() - .map(|project| project.name.as_str()) + pub fn project_name(&self) -> &str { + &self.root_project.name } pub fn project_port(&self) -> Option { - self.root_project - .as_ref() - .and_then(|project| project.serve_port) + self.root_project.serve_port } pub fn start_time(&self) -> Instant { @@ -211,217 +207,6 @@ impl ServeSession { } pub fn serve_place_ids(&self) -> Option<&HashSet> { - self.root_project - .as_ref() - .and_then(|project| project.serve_place_ids.as_ref()) - } -} - -/// This module is named to trick Insta into naming the resulting snapshots -/// correctly. -/// -/// See https://github.com/mitsuhiko/insta/issues/78 -#[cfg(test)] -mod serve_session { - use super::*; - - use std::{path::PathBuf, time::Duration}; - - use maplit::hashmap; - use memofs::{InMemoryFs, VfsEvent, VfsSnapshot}; - use rojo_insta_ext::RedactionMap; - use tokio::{runtime::Runtime, timer::Timeout}; - - use crate::tree_view::view_tree; - - #[test] - fn just_folder() { - let mut imfs = InMemoryFs::new(); - imfs.load_snapshot("/foo", VfsSnapshot::empty_dir()) - .unwrap(); - - let vfs = Vfs::new(imfs); - - let session = ServeSession::new(vfs, "/foo"); - - let mut rm = RedactionMap::new(); - insta::assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); - } - - #[test] - fn project_with_folder() { - let mut imfs = InMemoryFs::new(); - imfs.load_snapshot( - "/foo", - VfsSnapshot::dir(hashmap! { - "default.project.json" => VfsSnapshot::file(r#" - { - "name": "HelloWorld", - "tree": { - "$path": "src" - } - } - "#), - "src" => VfsSnapshot::dir(hashmap! { - "hello.txt" => VfsSnapshot::file("Hello, world!"), - }), - }), - ) - .unwrap(); - - let vfs = Vfs::new(imfs); - - let session = ServeSession::new(vfs, "/foo"); - - let mut rm = RedactionMap::new(); - insta::assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); - } - - #[test] - fn script_with_meta() { - let mut imfs = InMemoryFs::new(); - imfs.load_snapshot( - "/root", - VfsSnapshot::dir(hashmap! { - "test.lua" => VfsSnapshot::file("This is a test."), - "test.meta.json" => VfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#), - }), - ) - .unwrap(); - - let vfs = Vfs::new(imfs); - - let session = ServeSession::new(vfs, "/root"); - - let mut rm = RedactionMap::new(); - insta::assert_yaml_snapshot!(view_tree(&session.tree(), &mut rm)); - } - - #[test] - fn change_txt_file() { - let mut imfs = InMemoryFs::new(); - imfs.load_snapshot("/foo.txt", VfsSnapshot::file("Hello!")) - .unwrap(); - - let vfs = Vfs::new(imfs.clone()); - - let session = ServeSession::new(vfs, "/foo.txt"); - - let mut rm = RedactionMap::new(); - insta::assert_yaml_snapshot!( - "change_txt_file_before", - view_tree(&session.tree(), &mut rm) - ); - - imfs.load_snapshot("/foo.txt", VfsSnapshot::file("World!")) - .unwrap(); - - let receiver = session.message_queue().subscribe_any(); - - imfs.raise_event(VfsEvent::Write(PathBuf::from("/foo.txt"))); - - let receiver = Timeout::new(receiver, Duration::from_millis(200)); - - let mut rt = Runtime::new().unwrap(); - let result = rt.block_on(receiver).unwrap(); - - insta::assert_yaml_snapshot!("change_txt_file_patch", rm.redacted_yaml(result)); - insta::assert_yaml_snapshot!("change_txt_file_after", view_tree(&session.tree(), &mut rm)); - } - - #[test] - fn change_script_meta() { - let mut imfs = InMemoryFs::new(); - imfs.load_snapshot( - "/root", - VfsSnapshot::dir(hashmap! { - "test.lua" => VfsSnapshot::file("This is a test."), - "test.meta.json" => VfsSnapshot::file(r#"{ "ignoreUnknownInstances": true }"#), - }), - ) - .unwrap(); - - let vfs = Vfs::new(imfs.clone()); - - let session = ServeSession::new(vfs, "/root"); - - let mut rm = RedactionMap::new(); - insta::assert_yaml_snapshot!( - "change_script_meta_before", - view_tree(&session.tree(), &mut rm) - ); - - imfs.load_snapshot( - "/root/test.meta.json", - VfsSnapshot::file(r#"{ "ignoreUnknownInstances": false }"#), - ) - .unwrap(); - - let receiver = session.message_queue().subscribe_any(); - - imfs.raise_event(VfsEvent::Write(PathBuf::from("/root/test.meta.json"))); - - let receiver = Timeout::new(receiver, Duration::from_millis(200)); - - let mut rt = Runtime::new().unwrap(); - let result = rt.block_on(receiver).unwrap(); - - insta::assert_yaml_snapshot!("change_script_meta_patch", rm.redacted_yaml(result)); - insta::assert_yaml_snapshot!( - "change_script_meta_after", - view_tree(&session.tree(), &mut rm) - ); - } - - #[test] - fn change_file_in_project() { - let mut imfs = InMemoryFs::new(); - imfs.load_snapshot( - "/foo", - VfsSnapshot::dir(hashmap! { - "default.project.json" => VfsSnapshot::file(r#" - { - "name": "change_file_in_project", - "tree": { - "$className": "Folder", - - "Child": { - "$path": "file.txt" - } - } - } - "#), - "file.txt" => VfsSnapshot::file("initial content"), - }), - ) - .unwrap(); - - let vfs = Vfs::new(imfs.clone()); - - let session = ServeSession::new(vfs, "/foo"); - - let mut rm = RedactionMap::new(); - insta::assert_yaml_snapshot!( - "change_file_in_project_before", - view_tree(&session.tree(), &mut rm) - ); - - imfs.load_snapshot("/foo/file.txt", VfsSnapshot::file("Changed!")) - .unwrap(); - - let receiver = session.message_queue().subscribe_any(); - - imfs.raise_event(VfsEvent::Write(PathBuf::from("/foo/file.txt"))); - - let receiver = Timeout::new(receiver, Duration::from_millis(200)); - - let mut rt = Runtime::new().unwrap(); - let result = rt.block_on(receiver).unwrap(); - - insta::assert_yaml_snapshot!("change_file_in_project_patch", rm.redacted_yaml(result)); - insta::assert_yaml_snapshot!( - "change_file_in_project_after", - view_tree(&session.tree(), &mut rm) - ); + self.root_project.serve_place_ids.as_ref() } } diff --git a/src/snapshots/librojo__serve_session__serve_session__change_file_in_project_after.snap b/src/snapshots/librojo__serve_session__serve_session__change_file_in_project_after.snap deleted file mode 100644 index 29afd767..00000000 --- a/src/snapshots/librojo__serve_session__serve_session__change_file_in_project_after.snap +++ /dev/null @@ -1,35 +0,0 @@ ---- -source: src/serve_session.rs -expression: "view_tree(&session.tree(), &mut redactions)" ---- -id: id-1 -name: change_file_in_project -class_name: Folder -properties: {} -metadata: - ignore_unknown_instances: true - instigating_source: - Path: /foo/default.project.json - relevant_paths: - - /foo/default.project.json - context: {} -children: - - id: id-2 - name: Child - class_name: StringValue - properties: - Value: - Type: String - Value: Changed! - metadata: - ignore_unknown_instances: false - instigating_source: - ProjectNode: - - /foo - - Child - - $path: file.txt - relevant_paths: - - /foo/file.txt - - /foo/file.meta.json - context: {} - children: [] diff --git a/src/snapshots/librojo__serve_session__serve_session__change_file_in_project_before.snap b/src/snapshots/librojo__serve_session__serve_session__change_file_in_project_before.snap deleted file mode 100644 index 9b20d87f..00000000 --- a/src/snapshots/librojo__serve_session__serve_session__change_file_in_project_before.snap +++ /dev/null @@ -1,35 +0,0 @@ ---- -source: src/serve_session.rs -expression: "view_tree(&session.tree(), &mut redactions)" ---- -id: id-1 -name: change_file_in_project -class_name: Folder -properties: {} -metadata: - ignore_unknown_instances: true - instigating_source: - Path: /foo/default.project.json - relevant_paths: - - /foo/default.project.json - context: {} -children: - - id: id-2 - name: Child - class_name: StringValue - properties: - Value: - Type: String - Value: initial content - metadata: - ignore_unknown_instances: false - instigating_source: - ProjectNode: - - /foo - - Child - - $path: file.txt - relevant_paths: - - /foo/file.txt - - /foo/file.meta.json - context: {} - children: [] diff --git a/src/snapshots/librojo__serve_session__serve_session__change_file_in_project_patch.snap b/src/snapshots/librojo__serve_session__serve_session__change_file_in_project_patch.snap deleted file mode 100644 index 062181c5..00000000 --- a/src/snapshots/librojo__serve_session__serve_session__change_file_in_project_patch.snap +++ /dev/null @@ -1,16 +0,0 @@ ---- -source: src/serve_session.rs -expression: redactions.redacted_yaml(result) ---- -- 1 -- - removed: [] - added: [] - updated: - - id: id-2 - changed_name: ~ - changed_class_name: ~ - changed_properties: - Value: - Type: String - Value: Changed! - changed_metadata: ~ diff --git a/src/snapshots/librojo__serve_session__serve_session__change_script_meta_after.snap b/src/snapshots/librojo__serve_session__serve_session__change_script_meta_after.snap deleted file mode 100644 index c9cd47a1..00000000 --- a/src/snapshots/librojo__serve_session__serve_session__change_script_meta_after.snap +++ /dev/null @@ -1,36 +0,0 @@ ---- -source: src/serve_session.rs -expression: "view_tree(&session.tree(), &mut redactions)" ---- -id: id-1 -name: root -class_name: Folder -properties: {} -metadata: - ignore_unknown_instances: false - instigating_source: - Path: /root - relevant_paths: - - /root - - /root/init.meta.json - - /root/init.lua - - /root/init.server.lua - - /root/init.client.lua - context: {} -children: - - id: id-2 - name: test - class_name: ModuleScript - properties: - Source: - Type: String - Value: This is a test. - metadata: - ignore_unknown_instances: false - instigating_source: - Path: /root/test.lua - relevant_paths: - - /root/test.lua - - /root/test.meta.json - context: {} - children: [] diff --git a/src/snapshots/librojo__serve_session__serve_session__change_script_meta_before.snap b/src/snapshots/librojo__serve_session__serve_session__change_script_meta_before.snap deleted file mode 100644 index 21e575f1..00000000 --- a/src/snapshots/librojo__serve_session__serve_session__change_script_meta_before.snap +++ /dev/null @@ -1,36 +0,0 @@ ---- -source: src/serve_session.rs -expression: "view_tree(&session.tree(), &mut redactions)" ---- -id: id-1 -name: root -class_name: Folder -properties: {} -metadata: - ignore_unknown_instances: false - instigating_source: - Path: /root - relevant_paths: - - /root - - /root/init.meta.json - - /root/init.lua - - /root/init.server.lua - - /root/init.client.lua - context: {} -children: - - id: id-2 - name: test - class_name: ModuleScript - properties: - Source: - Type: String - Value: This is a test. - metadata: - ignore_unknown_instances: true - instigating_source: - Path: /root/test.lua - relevant_paths: - - /root/test.lua - - /root/test.meta.json - context: {} - children: [] diff --git a/src/snapshots/librojo__serve_session__serve_session__change_script_meta_patch.snap b/src/snapshots/librojo__serve_session__serve_session__change_script_meta_patch.snap deleted file mode 100644 index abc41b3a..00000000 --- a/src/snapshots/librojo__serve_session__serve_session__change_script_meta_patch.snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: src/serve_session.rs -expression: redactions.redacted_yaml(changes) ---- -- 1 -- - removed: [] - added: [] - updated: - - id: id-2 - changed_name: ~ - changed_class_name: ~ - changed_properties: {} - changed_metadata: - ignore_unknown_instances: false - instigating_source: - Path: /root/test.lua - relevant_paths: - - /root/test.lua - - /root/test.meta.json - context: {} diff --git a/src/snapshots/librojo__serve_session__serve_session__change_txt_file_after.snap b/src/snapshots/librojo__serve_session__serve_session__change_txt_file_after.snap deleted file mode 100644 index 4ff19d78..00000000 --- a/src/snapshots/librojo__serve_session__serve_session__change_txt_file_after.snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: src/serve_session.rs -expression: "view_tree(&session.tree(), &mut redactions)" ---- -id: id-1 -name: foo -class_name: StringValue -properties: - Value: - Type: String - Value: World! -metadata: - ignore_unknown_instances: false - instigating_source: - Path: /foo.txt - relevant_paths: - - /foo.txt - - /foo.meta.json - context: {} -children: [] diff --git a/src/snapshots/librojo__serve_session__serve_session__change_txt_file_before.snap b/src/snapshots/librojo__serve_session__serve_session__change_txt_file_before.snap deleted file mode 100644 index e3324a6a..00000000 --- a/src/snapshots/librojo__serve_session__serve_session__change_txt_file_before.snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: src/serve_session.rs -expression: "view_tree(&session.tree(), &mut redactions)" ---- -id: id-1 -name: foo -class_name: StringValue -properties: - Value: - Type: String - Value: Hello! -metadata: - ignore_unknown_instances: false - instigating_source: - Path: /foo.txt - relevant_paths: - - /foo.txt - - /foo.meta.json - context: {} -children: [] diff --git a/src/snapshots/librojo__serve_session__serve_session__change_txt_file_patch.snap b/src/snapshots/librojo__serve_session__serve_session__change_txt_file_patch.snap deleted file mode 100644 index 5e194e99..00000000 --- a/src/snapshots/librojo__serve_session__serve_session__change_txt_file_patch.snap +++ /dev/null @@ -1,16 +0,0 @@ ---- -source: src/serve_session.rs -expression: redactions.redacted_yaml(result) ---- -- 1 -- - removed: [] - added: [] - updated: - - id: id-1 - changed_name: ~ - changed_class_name: ~ - changed_properties: - Value: - Type: String - Value: World! - changed_metadata: ~ diff --git a/src/snapshots/librojo__serve_session__serve_session__just_folder.snap b/src/snapshots/librojo__serve_session__serve_session__just_folder.snap deleted file mode 100644 index 5851d3f2..00000000 --- a/src/snapshots/librojo__serve_session__serve_session__just_folder.snap +++ /dev/null @@ -1,20 +0,0 @@ ---- -source: src/serve_session.rs -expression: "view_tree(&session.tree(), &mut rm)" ---- -id: id-1 -name: foo -class_name: Folder -properties: {} -metadata: - ignore_unknown_instances: false - instigating_source: - Path: /foo - relevant_paths: - - /foo - - /foo/init.meta.json - - /foo/init.lua - - /foo/init.server.lua - - /foo/init.client.lua - context: {} -children: [] diff --git a/src/snapshots/librojo__serve_session__serve_session__project_with_folder.snap b/src/snapshots/librojo__serve_session__serve_session__project_with_folder.snap deleted file mode 100644 index c6a3a4b2..00000000 --- a/src/snapshots/librojo__serve_session__serve_session__project_with_folder.snap +++ /dev/null @@ -1,37 +0,0 @@ ---- -source: src/serve_session.rs -expression: "view_tree(&session.tree(), &mut rm)" ---- -id: id-1 -name: HelloWorld -class_name: Folder -properties: {} -metadata: - ignore_unknown_instances: false - instigating_source: - Path: /foo/default.project.json - relevant_paths: - - /foo/src - - /foo/src/init.meta.json - - /foo/src/init.lua - - /foo/src/init.server.lua - - /foo/src/init.client.lua - - /foo/default.project.json - context: {} -children: - - id: id-2 - name: hello - class_name: StringValue - properties: - Value: - Type: String - Value: "Hello, world!" - metadata: - ignore_unknown_instances: false - instigating_source: - Path: /foo/src/hello.txt - relevant_paths: - - /foo/src/hello.txt - - /foo/src/hello.meta.json - context: {} - children: [] diff --git a/src/snapshots/librojo__serve_session__serve_session__script_with_meta.snap b/src/snapshots/librojo__serve_session__serve_session__script_with_meta.snap deleted file mode 100644 index 6542fa39..00000000 --- a/src/snapshots/librojo__serve_session__serve_session__script_with_meta.snap +++ /dev/null @@ -1,36 +0,0 @@ ---- -source: src/serve_session.rs -expression: "view_tree(&session.tree(), &mut rm)" ---- -id: id-1 -name: root -class_name: Folder -properties: {} -metadata: - ignore_unknown_instances: false - instigating_source: - Path: /root - relevant_paths: - - /root - - /root/init.meta.json - - /root/init.lua - - /root/init.server.lua - - /root/init.client.lua - context: {} -children: - - id: id-2 - name: test - class_name: ModuleScript - properties: - Source: - Type: String - Value: This is a test. - metadata: - ignore_unknown_instances: true - instigating_source: - Path: /root/test.lua - relevant_paths: - - /root/test.lua - - /root/test.meta.json - context: {} - children: [] diff --git a/src/web/ui.rs b/src/web/ui.rs index 50fe1df4..a3705e06 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -233,7 +233,7 @@ impl UiService { } fn normal_page<'a>(&'a self, body: HtmlContent<'a>) -> HtmlContent<'a> { - let project_name = self.serve_session.project_name().unwrap_or(""); + let project_name = self.serve_session.project_name(); let uptime = { let elapsed = self.serve_session.start_time().elapsed(); From 8ebe7e332b11ef15ec9f9ce37fdf0af1b44a19f3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 25 Mar 2020 17:02:32 -0700 Subject: [PATCH 1026/1504] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 320d81f6..c5bfe708 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Added `--color` option to force-enable or force-disable color in Rojo's output. * The server half of **experimental** two-way sync is now enabled by default. * Increased default logging verbosity in commands like `rojo build`. +* Rojo now requires a project file again, just like 0.5.4. ## [0.6.0 Alpha 3](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.3) (March 13, 2020) * Added `--watch` argument to `rojo build`. ([#284](https://github.com/rojo-rbx/rojo/pull/284)) From 9c790eddd74a9c6e24e19295c29a7ef12c7d924c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 26 Mar 2020 12:06:16 -0700 Subject: [PATCH 1027/1504] Tidy up ServeSession now that trait bounds are gone --- src/serve_session.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/serve_session.rs b/src/serve_session.rs index 6263c2e0..cb0e81d7 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -83,9 +83,6 @@ pub struct ServeSession { tree_mutation_sender: Sender, } -/// Methods that need thread-safety bounds on VfsFetcher are limited to this -/// block to prevent needing to spread Send + Sync + 'static into everything -/// that handles ServeSession. impl ServeSession { /// Start a new serve session from the given in-memory filesystem and start /// path. @@ -166,9 +163,7 @@ impl ServeSession { vfs, } } -} -impl ServeSession { pub fn tree_handle(&self) -> Arc> { Arc::clone(&self.tree) } From 03c297190d19ffc16d0d656f2285c0491cb3a7ec Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 26 Mar 2020 12:07:44 -0700 Subject: [PATCH 1028/1504] Make ServeSession::new fallible --- src/cli/build.rs | 2 +- src/cli/serve.rs | 2 +- src/cli/upload.rs | 2 +- src/serve_session.rs | 10 +++++++--- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/cli/build.rs b/src/cli/build.rs index 13db6681..88760e2f 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -44,7 +44,7 @@ pub fn build(options: BuildCommand) -> Result<(), anyhow::Error> { let vfs = Vfs::new_default(); - let session = ServeSession::new(vfs, &options.absolute_project()); + let session = ServeSession::new(vfs, &options.absolute_project())?; let mut cursor = session.message_queue().cursor(); { diff --git a/src/cli/serve.rs b/src/cli/serve.rs index b4fbcd63..07ae85b3 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -18,7 +18,7 @@ const DEFAULT_PORT: u16 = 34872; pub fn serve(global: GlobalOptions, options: ServeCommand) -> Result<()> { let vfs = Vfs::new_default(); - let session = Arc::new(ServeSession::new(vfs, &options.absolute_project())); + let session = Arc::new(ServeSession::new(vfs, &options.absolute_project())?); let port = options .port diff --git a/src/cli/upload.rs b/src/cli/upload.rs index 2a9b7f7a..49e367d1 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -22,7 +22,7 @@ pub fn upload(options: UploadCommand) -> Result<(), anyhow::Error> { let vfs = Vfs::new_default(); - let session = ServeSession::new(vfs, &options.absolute_project()); + let session = ServeSession::new(vfs, &options.absolute_project())?; let tree = session.tree(); let inner_tree = tree.inner(); diff --git a/src/serve_session.rs b/src/serve_session.rs index cb0e81d7..db0935d4 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -8,6 +8,7 @@ use std::{ use crossbeam_channel::Sender; use memofs::Vfs; use rbx_dom_weak::RbxInstanceProperties; +use thiserror::Error; use crate::{ change_processor::ChangeProcessor, @@ -90,7 +91,7 @@ impl ServeSession { /// The project file is expected to be loaded out-of-band since it's /// currently loaded from the filesystem directly instead of through the /// in-memory filesystem layer. - pub fn new>(vfs: Vfs, start_path: P) -> Self { + pub fn new>(vfs: Vfs, start_path: P) -> Result { let start_path = start_path.as_ref(); let start_time = Instant::now(); @@ -152,7 +153,7 @@ impl ServeSession { tree_mutation_receiver, ); - Self { + Ok(Self { change_processor, start_time, session_id, @@ -161,7 +162,7 @@ impl ServeSession { message_queue, tree_mutation_sender, vfs, - } + }) } pub fn tree_handle(&self) -> Arc> { @@ -205,3 +206,6 @@ impl ServeSession { self.root_project.serve_place_ids.as_ref() } } + +#[derive(Debug, Error)] +pub enum ServeSessionError {} From 729a7f00534fc3739419862cb3594da3ec474a4b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 26 Mar 2020 12:16:55 -0700 Subject: [PATCH 1029/1504] Turn panics into errors in ServeSession --- src/project.rs | 4 ++-- src/serve_session.rs | 39 +++++++++++++++++++++++++--------- src/snapshot_middleware/mod.rs | 22 ++++++++++++------- 3 files changed, 45 insertions(+), 20 deletions(-) diff --git a/src/project.rs b/src/project.rs index bbdb5398..12134dc9 100644 --- a/src/project.rs +++ b/src/project.rs @@ -19,13 +19,13 @@ pub struct ProjectError(#[from] Error); #[derive(Debug, Error)] enum Error { - #[error("Rojo project I/O error")] + #[error(transparent)] Io { #[from] source: io::Error, }, - #[error("Error parsing Rojo project")] + #[error("Error parsing Rojo project in path {}", .path.display())] Json { source: serde_json::Error, path: PathBuf, diff --git a/src/serve_session.rs b/src/serve_session.rs index db0935d4..2c2813d3 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -1,6 +1,6 @@ use std::{ collections::HashSet, - path::Path, + path::{Path, PathBuf}, sync::{Arc, Mutex, MutexGuard}, time::Instant, }; @@ -13,13 +13,13 @@ use thiserror::Error; use crate::{ change_processor::ChangeProcessor, message_queue::MessageQueue, - project::Project, + project::{Project, ProjectError}, session_id::SessionId, snapshot::{ apply_patch_set, compute_patch_set, AppliedPatchSet, InstanceContext, InstancePropertiesWithMeta, PatchSet, PathIgnoreRule, RojoTree, }, - snapshot_middleware::snapshot_from_vfs, + snapshot_middleware::{snapshot_from_vfs, SnapshotError}, }; /// Contains all of the state for a Rojo serve session. @@ -97,10 +97,11 @@ impl ServeSession { log::trace!("Starting new ServeSession at path {}", start_path.display()); - log::trace!("Loading project file from {}", start_path.display()); - let root_project = Project::load_fuzzy(start_path) - .expect("TODO: Project load failed") - .expect("TODO: No project was found."); + log::debug!("Loading project file from {}", start_path.display()); + let root_project = + Project::load_fuzzy(start_path)?.ok_or_else(|| ServeSessionError::NoProjectFound { + path: start_path.to_owned(), + })?; let mut tree = RojoTree::new(InstancePropertiesWithMeta { properties: RbxInstanceProperties { @@ -126,8 +127,7 @@ impl ServeSession { instance_context.add_path_ignore_rules(rules); log::trace!("Generating snapshot of instances from VFS"); - let snapshot = snapshot_from_vfs(&instance_context, &vfs, &start_path) - .expect("snapshot failed") + let snapshot = snapshot_from_vfs(&instance_context, &vfs, &start_path)? .expect("snapshot did not return an instance"); log::trace!("Computing initial patch set"); @@ -208,4 +208,23 @@ impl ServeSession { } #[derive(Debug, Error)] -pub enum ServeSessionError {} +pub enum ServeSessionError { + #[error( + "Rojo requires a project file, but no project file was found in path {}\n\ + See https://rojo.space/docs/ for guides and documentation.", + .path.display() + )] + NoProjectFound { path: PathBuf }, + + #[error(transparent)] + Project { + #[from] + source: ProjectError, + }, + + #[error(transparent)] + Snapshot { + #[from] + source: SnapshotError, + }, +} diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 77dca702..dff62bc0 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -17,20 +17,26 @@ mod rbxmx; mod txt; mod util; -pub use self::error::*; - use std::path::Path; use memofs::Vfs; -use self::middleware::{SnapshotInstanceResult, SnapshotMiddleware}; -use self::{ - csv::SnapshotCsv, dir::SnapshotDir, json_model::SnapshotJsonModel, lua::SnapshotLua, - project::SnapshotProject, rbxlx::SnapshotRbxlx, rbxm::SnapshotRbxm, rbxmx::SnapshotRbxmx, - txt::SnapshotTxt, -}; use crate::snapshot::InstanceContext; +use self::{ + csv::SnapshotCsv, + dir::SnapshotDir, + json_model::SnapshotJsonModel, + lua::SnapshotLua, + middleware::{SnapshotInstanceResult, SnapshotMiddleware}, + project::SnapshotProject, + rbxlx::SnapshotRbxlx, + rbxm::SnapshotRbxm, + rbxmx::SnapshotRbxmx, + txt::SnapshotTxt, +}; + +pub use self::error::*; pub use self::project::snapshot_project_node; macro_rules! middlewares { From 62e51b7535579b48ee288de77f358ce1b1c3f95c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 27 Mar 2020 23:58:31 -0700 Subject: [PATCH 1030/1504] Upgrade to latest rbx-dom --- plugin/modules/rbx-dom | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index 5bca08fe..94116dcc 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit 5bca08fec3f5708a29811dceb11957b92eafe81f +Subproject commit 94116dcc11a1728e49dad1c779077cff526c2808 From 4bf73c7a8ac32c3c5221160e249a074a37da6634 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 28 Mar 2020 00:36:01 -0700 Subject: [PATCH 1031/1504] Implement support for turning .json files into Lua modules (#308) * Stub implementation * Flesh out feature and add tests. Other snapshots currently failing. * Blacklist .meta.json in JSON handler * Write to correct property (Source) instead of Value * Update changelog --- CHANGELOG.md | 1 + .../rojo_test__build_test__json_as_lua.snap | 23 ++ .../json_as_lua/default.project.json | 6 + .../json_as_lua/make-me-a-script.json | 12 + rojo-test/src/build_test.rs | 1 + src/lib.rs | 1 + src/lua_ast.rs | 279 ++++++++++++++++++ src/snapshot_middleware/error.rs | 21 +- src/snapshot_middleware/json.rs | 142 +++++++++ src/snapshot_middleware/mod.rs | 3 + ...leware__json__test__instance_from_vfs.snap | 20 ++ 11 files changed, 505 insertions(+), 4 deletions(-) create mode 100644 rojo-test/build-test-snapshots/rojo_test__build_test__json_as_lua.snap create mode 100644 rojo-test/build-tests/json_as_lua/default.project.json create mode 100644 rojo-test/build-tests/json_as_lua/make-me-a-script.json create mode 100644 src/lua_ast.rs create mode 100644 src/snapshot_middleware/json.rs create mode 100644 src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index c5bfe708..259f2d75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * "Open Scripts Externally": When enabled, opening a script in Studio will instead open it in your default text editor. * "Two-Way Sync": When enabled, Rojo will attempt to save changes to your place back to the filesystem. **Very early feature, very broken, beware!** * Added `--color` option to force-enable or force-disable color in Rojo's output. +* Added support for turning `.json` files into `ModuleScript` instances ([#308](https://github.com/rojo-rbx/rojo/pull/308)) * The server half of **experimental** two-way sync is now enabled by default. * Increased default logging verbosity in commands like `rojo build`. * Rojo now requires a project file again, just like 0.5.4. diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__json_as_lua.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__json_as_lua.snap new file mode 100644 index 00000000..8fcead0a --- /dev/null +++ b/rojo-test/build-test-snapshots/rojo_test__build_test__json_as_lua.snap @@ -0,0 +1,23 @@ +--- +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + json_as_lua + return { + ["1invalidident"] = "nice", + array = {1, 2, 3}, + ["false"] = false, + float = 1234.5452, + int = 1234, + null = nil, + object = { + hello = "world", + }, + ["true"] = true, +} + + + diff --git a/rojo-test/build-tests/json_as_lua/default.project.json b/rojo-test/build-tests/json_as_lua/default.project.json new file mode 100644 index 00000000..1e984c68 --- /dev/null +++ b/rojo-test/build-tests/json_as_lua/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "json_as_lua", + "tree": { + "$path": "make-me-a-script.json" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/json_as_lua/make-me-a-script.json b/rojo-test/build-tests/json_as_lua/make-me-a-script.json new file mode 100644 index 00000000..c252006c --- /dev/null +++ b/rojo-test/build-tests/json_as_lua/make-me-a-script.json @@ -0,0 +1,12 @@ +{ + "array": [1, 2, 3], + "object": { + "hello": "world" + }, + "true": true, + "false": false, + "null": null, + "int": 1234, + "float": 1234.5452, + "1invalidident": "nice" +} \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index c51cacf9..7939f206 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -31,6 +31,7 @@ gen_build_tests! { init_meta_class_name, init_meta_properties, init_with_children, + json_as_lua, json_model_in_folder, json_model_legacy_name, module_in_folder, diff --git a/src/lib.rs b/src/lib.rs index 454449b2..7e594414 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ mod auth_cookie; mod change_processor; mod error; mod glob; +mod lua_ast; mod message_queue; mod multimap; mod path_serializer; diff --git a/src/lua_ast.rs b/src/lua_ast.rs new file mode 100644 index 00000000..ace9b4d7 --- /dev/null +++ b/src/lua_ast.rs @@ -0,0 +1,279 @@ +//! Defines module for defining a small Lua AST for simple codegen. + +use std::{ + fmt::{self, Write}, + num::FpCategory, +}; + +/// Trait that helps turn a type into an equivalent Lua snippet. +/// +/// Designed to be similar to the `Display` trait from Rust's std. +trait FmtLua { + fn fmt_lua(&self, output: &mut LuaStream<'_>) -> fmt::Result; + + /// Used to override how this type will appear when used as a table key. + /// Some types, like strings, can have a shorter representation as a table + /// key than the default, safe approach. + fn fmt_table_key(&self, output: &mut LuaStream<'_>) -> fmt::Result { + write!(output, "[")?; + self.fmt_lua(output)?; + write!(output, "]") + } +} + +pub(crate) enum Statement { + Return(Expression), +} + +impl FmtLua for Statement { + fn fmt_lua(&self, output: &mut LuaStream<'_>) -> fmt::Result { + match self { + Self::Return(literal) => { + write!(output, "return ")?; + literal.fmt_lua(output) + } + } + } +} + +impl fmt::Display for Statement { + fn fmt(&self, output: &mut fmt::Formatter) -> fmt::Result { + let mut stream = LuaStream::new(output); + FmtLua::fmt_lua(self, &mut stream) + } +} + +pub(crate) enum Expression { + Nil, + Bool(bool), + Number(f64), + String(String), + Table(Table), + + /// Arrays are not technically distinct from other tables in Lua, but this + /// representation is more convenient. + Array(Vec), +} + +impl Expression { + pub fn table(entries: Vec<(Expression, Expression)>) -> Self { + Self::Table(Table { entries }) + } +} + +impl FmtLua for Expression { + fn fmt_lua(&self, output: &mut LuaStream<'_>) -> fmt::Result { + match self { + Self::Nil => write!(output, "nil"), + Self::Bool(inner) => inner.fmt_lua(output), + Self::Number(inner) => inner.fmt_lua(output), + Self::String(inner) => inner.fmt_lua(output), + Self::Table(inner) => inner.fmt_lua(output), + Self::Array(inner) => inner.fmt_lua(output), + } + } + + fn fmt_table_key(&self, output: &mut LuaStream<'_>) -> fmt::Result { + match self { + Self::Nil => panic!("nil cannot be a table key"), + Self::Bool(inner) => inner.fmt_table_key(output), + Self::Number(inner) => inner.fmt_table_key(output), + Self::String(inner) => inner.fmt_table_key(output), + Self::Table(inner) => inner.fmt_table_key(output), + Self::Array(inner) => inner.fmt_table_key(output), + } + } +} + +impl From for Expression { + fn from(value: String) -> Self { + Self::String(value) + } +} + +impl From<&'_ str> for Expression { + fn from(value: &str) -> Self { + Self::String(value.to_owned()) + } +} + +impl From for Expression { + fn from(value: Table) -> Self { + Self::Table(value) + } +} + +impl FmtLua for bool { + fn fmt_lua(&self, output: &mut LuaStream<'_>) -> fmt::Result { + write!(output, "{}", self) + } +} + +impl FmtLua for f64 { + fn fmt_lua(&self, output: &mut LuaStream<'_>) -> fmt::Result { + match self.classify() { + FpCategory::Nan => write!(output, "0/0"), + FpCategory::Infinite => { + if self.is_sign_positive() { + write!(output, "math.huge") + } else { + write!(output, "-math.huge") + } + } + _ => write!(output, "{}", self), + } + } +} + +impl FmtLua for String { + fn fmt_lua(&self, output: &mut LuaStream<'_>) -> fmt::Result { + write!(output, "\"{}\"", self) + } + + fn fmt_table_key(&self, output: &mut LuaStream<'_>) -> fmt::Result { + if is_valid_ident(self) { + write!(output, "{}", self) + } else { + write!(output, "[\"{}\"]", self) + } + } +} + +impl FmtLua for Vec { + fn fmt_lua(&self, output: &mut LuaStream<'_>) -> fmt::Result { + write!(output, "{{")?; + + for (index, value) in self.iter().enumerate() { + value.fmt_lua(output)?; + + if index < self.len() - 1 { + write!(output, ", ")?; + } + } + + write!(output, "}}") + } +} + +pub(crate) struct Table { + pub entries: Vec<(Expression, Expression)>, +} + +impl FmtLua for Table { + fn fmt_lua(&self, output: &mut LuaStream<'_>) -> fmt::Result { + writeln!(output, "{{")?; + output.indent(); + + for (key, value) in &self.entries { + key.fmt_table_key(output)?; + write!(output, " = ")?; + value.fmt_lua(output)?; + writeln!(output, ",")?; + } + + output.unindent(); + write!(output, "}}") + } +} + +fn is_valid_ident_char_start(value: char) -> bool { + value.is_ascii_alphabetic() || value == '_' +} + +fn is_valid_ident_char(value: char) -> bool { + value.is_ascii_alphanumeric() || value == '_' +} + +fn is_keyword(value: &str) -> bool { + match value { + "and" | "break" | "do" | "else" | "elseif" | "end" | "false" | "for" | "function" + | "if" | "in" | "local" | "nil" | "not" | "or" | "repeat" | "return" | "then" | "true" + | "until" | "while" => true, + _ => false, + } +} + +/// Tells whether the given string is a valid Lua identifier. +fn is_valid_ident(value: &str) -> bool { + if is_keyword(value) { + return false; + } + + let mut chars = value.chars(); + + match chars.next() { + Some(first) => { + if !is_valid_ident_char_start(first) { + return false; + } + } + None => return false, + } + + chars.all(is_valid_ident_char) +} + +/// Wraps a `fmt::Write` with additional tracking to do pretty-printing of Lua. +/// +/// Behaves similarly to `fmt::Formatter`. This trait's relationship to `LuaFmt` +/// is very similar to `Formatter`'s relationship to `Display`. +struct LuaStream<'a> { + indent_level: usize, + is_start_of_line: bool, + inner: &'a mut (dyn fmt::Write + 'a), +} + +impl fmt::Write for LuaStream<'_> { + /// Method to support the `write!` and `writeln!` macros. Instead of using a + /// trait directly, these macros just call `write_str` on their first + /// argument. + /// + /// This method is also available on `io::Write` and `fmt::Write`. + fn write_str(&mut self, value: &str) -> fmt::Result { + let mut is_first_line = true; + + for line in value.split('\n') { + if is_first_line { + is_first_line = false; + } else { + self.line()?; + } + + if !line.is_empty() { + if self.is_start_of_line { + self.is_start_of_line = false; + let indentation = "\t".repeat(self.indent_level); + self.inner.write_str(&indentation)?; + } + + self.inner.write_str(line)?; + } + } + + Ok(()) + } +} + +impl<'a> LuaStream<'a> { + fn new(inner: &'a mut (dyn fmt::Write + 'a)) -> Self { + LuaStream { + indent_level: 0, + is_start_of_line: true, + inner, + } + } + + fn indent(&mut self) { + self.indent_level += 1; + } + + fn unindent(&mut self) { + assert!(self.indent_level > 0); + self.indent_level -= 1; + } + + fn line(&mut self) -> fmt::Result { + self.is_start_of_line = true; + self.inner.write_str("\n") + } +} diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs index 78aaaf95..a686fcbc 100644 --- a/src/snapshot_middleware/error.rs +++ b/src/snapshot_middleware/error.rs @@ -7,30 +7,36 @@ pub enum SnapshotError { #[error("file name had malformed Unicode")] FileNameBadUnicode { path: PathBuf }, - #[error("file had malformed Unicode contents")] + #[error("file had malformed Unicode contents at path {}", .path.display())] FileContentsBadUnicode { source: std::str::Utf8Error, path: PathBuf, }, - #[error("malformed project file")] + #[error("malformed project file at path {}", .path.display())] MalformedProject { source: serde_json::Error, path: PathBuf, }, - #[error("malformed .model.json file")] + #[error("malformed .model.json file at path {}", .path.display())] MalformedModelJson { source: serde_json::Error, path: PathBuf, }, - #[error("malformed .meta.json file")] + #[error("malformed .meta.json file at path {}", .path.display())] MalformedMetaJson { source: serde_json::Error, path: PathBuf, }, + #[error("malformed JSON at path {}", .path.display())] + MalformedJson { + source: serde_json::Error, + path: PathBuf, + }, + #[error(transparent)] Io { #[from] @@ -76,4 +82,11 @@ impl SnapshotError { path: path.into(), } } + + pub(crate) fn malformed_json(source: serde_json::Error, path: impl Into) -> Self { + Self::MalformedJson { + source, + path: path.into(), + } + } } diff --git a/src/snapshot_middleware/json.rs b/src/snapshot_middleware/json.rs new file mode 100644 index 00000000..4b3508e3 --- /dev/null +++ b/src/snapshot_middleware/json.rs @@ -0,0 +1,142 @@ +use std::path::Path; + +use maplit::hashmap; +use memofs::{IoResultExt, Vfs}; +use rbx_dom_weak::RbxValue; + +use crate::{ + lua_ast::{Expression, Statement}, + snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, +}; + +use super::{ + error::SnapshotError, + meta_file::AdjacentMetadata, + middleware::{SnapshotInstanceResult, SnapshotMiddleware}, + util::match_file_name, +}; + +/// Catch-all middleware for snapshots on JSON files that aren't used for other +/// features, like Rojo projects, JSON models, or meta files. +pub struct SnapshotJson; + +impl SnapshotMiddleware for SnapshotJson { + fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { + let meta = vfs.metadata(path)?; + + if meta.is_dir() { + return Ok(None); + } + + // FIXME: This middleware should not need to know about the .meta.json + // middleware. Should there be a way to signal "I'm not returning an + // instance and no one should"? + if match_file_name(path, ".meta.json").is_some() { + return Ok(None); + } + + let instance_name = match match_file_name(path, ".json") { + Some(name) => name, + None => return Ok(None), + }; + + let contents = vfs.read(path)?; + + let value: serde_json::Value = serde_json::from_slice(&contents) + .map_err(|err| SnapshotError::malformed_json(err, path))?; + + let as_lua = json_to_lua(value).to_string(); + + let properties = hashmap! { + "Source".to_owned() => RbxValue::String { + value: as_lua, + }, + }; + + let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); + + let mut snapshot = InstanceSnapshot::new() + .name(instance_name) + .class_name("ModuleScript") + .properties(properties) + .metadata( + InstanceMetadata::new() + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf(), meta_path.clone()]) + .context(context), + ); + + if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { + let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; + metadata.apply_all(&mut snapshot); + } + + Ok(Some(snapshot)) + } +} + +fn json_to_lua(value: serde_json::Value) -> Statement { + Statement::Return(json_to_lua_value(value)) +} + +fn json_to_lua_value(value: serde_json::Value) -> Expression { + use serde_json::Value; + + match value { + Value::Null => Expression::Nil, + Value::Bool(value) => Expression::Bool(value), + Value::Number(value) => Expression::Number(value.as_f64().unwrap()), + Value::String(value) => Expression::String(value), + Value::Array(values) => { + Expression::Array(values.into_iter().map(json_to_lua_value).collect()) + } + Value::Object(values) => Expression::table( + values + .into_iter() + .map(|(key, value)| (key.into(), json_to_lua_value(value))) + .collect(), + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + use memofs::{InMemoryFs, VfsSnapshot}; + + #[test] + fn instance_from_vfs() { + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo.json", + VfsSnapshot::file( + r#"{ + "array": [1, 2, 3], + "object": { + "hello": "world" + }, + "true": true, + "false": false, + "null": null, + "int": 1234, + "float": 1234.5452, + "1invalidident": "nice" + }"#, + ), + ) + .unwrap(); + + let mut vfs = Vfs::new(imfs.clone()); + + let instance_snapshot = SnapshotJson::from_vfs( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.json"), + ) + .unwrap() + .unwrap(); + + insta::assert_yaml_snapshot!(instance_snapshot); + } +} diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index dff62bc0..561949c2 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -6,6 +6,7 @@ mod csv; mod dir; mod error; +mod json; mod json_model; mod lua; mod meta_file; @@ -26,6 +27,7 @@ use crate::snapshot::InstanceContext; use self::{ csv::SnapshotCsv, dir::SnapshotDir, + json::SnapshotJson, json_model::SnapshotJsonModel, lua::SnapshotLua, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, @@ -71,5 +73,6 @@ middlewares! { SnapshotLua, SnapshotCsv, SnapshotTxt, + SnapshotJson, SnapshotDir, } diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap new file mode 100644 index 00000000..59378750 --- /dev/null +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap @@ -0,0 +1,20 @@ +--- +source: src/snapshot_middleware/json.rs +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /foo.json + relevant_paths: + - /foo.json + - /foo.meta.json + context: {} +name: foo +class_name: ModuleScript +properties: + Source: + Type: String + Value: "return {\n\t[\"1invalidident\"] = \"nice\",\n\tarray = {1, 2, 3},\n\t[\"false\"] = false,\n\tfloat = 1234.5452,\n\tint = 1234,\n\tnull = nil,\n\tobject = {\n\t\thello = \"world\",\n\t},\n\t[\"true\"] = true,\n}" +children: [] From 5c85cd27c32cc9f7f00a0a98c7020ac8e947ab46 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 29 Mar 2020 12:21:55 -0700 Subject: [PATCH 1032/1504] Fix default place project. Closes #311. --- assets/default-place-project/default.project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/default-place-project/default.project.json b/assets/default-place-project/default.project.json index fc3f1ec3..85367e4c 100644 --- a/assets/default-place-project/default.project.json +++ b/assets/default-place-project/default.project.json @@ -7,7 +7,7 @@ "$className": "ReplicatedStorage", "Common": { - "$path": "src/common" + "$path": "src/shared" } }, From 9b459c20d6fd1a061fbfd2bb7078976de3cba8b2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 29 Mar 2020 13:17:06 -0700 Subject: [PATCH 1033/1504] Fix GHA only running on pushes to master --- .github/workflows/ci.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6ad5b6e1..536a7d9d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,6 +1,9 @@ name: CI -on: [push] +on: + pull_request: + push: + branches: ["*"] jobs: build: From 3cf82e112fe9379406fda2c8eff638b775c5f90c Mon Sep 17 00:00:00 2001 From: jeparlefrancais <35781636+jeparlefrancais@users.noreply.github.com> Date: Sun, 29 Mar 2020 16:41:54 -0400 Subject: [PATCH 1034/1504] Install plugin from CLI (#304) * add install command * cargo fmt * filter spec files * Update src/cli/plugin.rs Co-Authored-By: Lucien Greathouse * Update src/cli/plugin.rs Co-Authored-By: Lucien Greathouse * fix comments * encode plugin with rbx_binary * update build script * refactor pathbuf error into io error * fix rojo typo * remove snafu * Update `snapshot_from_fs_path` * Print `rerun-if-changed` even for directories, in order to run the build.rs script when files are added. * Switch `filter_map` loop to a regular for loop. I like the FP-style iterator stuff in Rust, but I think Result handling is easier in a normal loop. Also, I don't believe the result of read_dir implements `ExactSizedIterator`, so some of the wins of map+collect aren't there. * Replace Result::unwrap with ? in build.rs * Simplify error handling code in runtime * Checkout with submodules Co-authored-by: Lucien Greathouse --- .github/workflows/ci.yml | 2 + Cargo.lock | 289 +++++++++++++++++++++++++-------------- Cargo.toml | 9 ++ build.rs | 78 +++++++++++ memofs/Cargo.toml | 1 + memofs/src/snapshot.rs | 3 +- plugin/modules/rbx-dom | 2 +- src/bin.rs | 1 + src/cli/mod.rs | 23 ++++ src/cli/plugin.rs | 70 ++++++++++ 10 files changed, 373 insertions(+), 105 deletions(-) create mode 100644 build.rs create mode 100644 src/cli/plugin.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 536a7d9d..ffe614ea 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,8 @@ jobs: steps: - uses: actions/checkout@v1 + with: + submodules: true - name: Setup Rust toolchain run: rustup default ${{ matrix.rust_version }} diff --git a/Cargo.lock b/Cargo.lock index fbcc2b87..3926256a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -8,9 +8,9 @@ checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" [[package]] name = "aho-corasick" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5e63fd144e18ba274ae7095c0197a870a7b9468abc801dd62f190d80817d2ec" +checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" dependencies = [ "memchr", ] @@ -30,6 +30,18 @@ version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "013a6e0a2cbe3d20f9c60b65458f7a7f7a5e636c5d0f45a5a6aee5d4b1f01785" +[[package]] +name = "arrayref" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" + +[[package]] +name = "arrayvec" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" + [[package]] name = "atty" version = "0.2.14" @@ -55,9 +67,9 @@ checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" [[package]] name = "backtrace" -version = "0.3.45" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad235dabf00f36301792cfe82499880ba54c6486be094d1047b02bacb67c14e8" +checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" dependencies = [ "backtrace-sys", "cfg-if", @@ -67,9 +79,9 @@ dependencies = [ [[package]] name = "backtrace-sys" -version = "0.1.33" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17b52e737c40a7d75abca20b29a19a0eb7ba9fc72c5a72dd282a0a3c2c0dc35" +checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118" dependencies = [ "cc", "libc", @@ -90,12 +102,33 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +[[package]] +name = "bincode" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" +dependencies = [ + "byteorder", + "serde", +] + [[package]] name = "bitflags" version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +[[package]] +name = "blake2b_simd" +version = "0.5.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" +dependencies = [ + "arrayref", + "arrayvec", + "constant_time_eq", +] + [[package]] name = "block-buffer" version = "0.7.3" @@ -119,9 +152,9 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "502ae1441a0a5adb8fbd38a5955a6416b9493e92b465de5e4a9bde6a539c2c48" +checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" dependencies = [ "lazy_static", "memchr", @@ -131,9 +164,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f359dc14ff8911330a51ef78022d376f25ed00248912803b58f00cb1c27f742" +checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" [[package]] name = "byte-tools" @@ -164,15 +197,6 @@ dependencies = [ "iovec", ] -[[package]] -name = "c2-chacha" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214238caa1bf3a496ec3392968969cab8549f96ff30652c9e56885329315f6bb" -dependencies = [ - "ppv-lite86", -] - [[package]] name = "cargo_metadata" version = "0.6.4" @@ -265,6 +289,12 @@ dependencies = [ "winapi 0.3.8", ] +[[package]] +name = "constant_time_eq" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" + [[package]] name = "cookie" version = "0.12.0" @@ -458,10 +488,32 @@ dependencies = [ ] [[package]] -name = "doc-comment" -version = "0.3.1" +name = "dirs" +version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "923dea538cea0aa3025e8685b20d6ee21ef99c4f77e954a30febbaac5ec73a97" +checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" +dependencies = [ + "cfg-if", + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" +dependencies = [ + "cfg-if", + "libc", + "redox_users", + "winapi 0.3.8", +] + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "dtoa" @@ -555,9 +607,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bd6d6f4752952feb71363cffc9ebac9411b75b87c6ab6058c40c8900cf43c0f" +checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42" dependencies = [ "cfg-if", "crc32fast", @@ -677,9 +729,9 @@ checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" [[package]] name = "globset" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925aa2cac82d8834e2b2a4415b6f6879757fb5c0928fc445ae76461a12eed8f2" +checksum = "7ad1da430bd7281dde2576f44c84cc3f0f7b475e7202cd503042dff01a8c8120" dependencies = [ "aho-corasick", "bstr", @@ -904,15 +956,15 @@ checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" [[package]] name = "jod-thread" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f52a11f73b88fab829a0e4d9e13ea5982c7ac457c72eb3541d82a4afdfce4ff" +checksum = "4022656272c3e564a7cdebcaaba6518d844b0d0c1836597196efb5bfeb98bb49" [[package]] name = "js-sys" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cb931d43e71f560c81badb0191596562bafad2be06a3f9025b845c847c60df5" +checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" dependencies = [ "wasm-bindgen", ] @@ -941,9 +993,9 @@ checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" [[package]] name = "libc" -version = "0.2.67" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb147597cdf94ed43ab7a9038716637d2d1bf2bc571da995d0028dec06bd3018" +checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" [[package]] name = "linked-hash-map" @@ -1022,11 +1074,11 @@ checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" [[package]] name = "memoffset" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75189eb85871ea5c2e2c15abbdd541185f63b408415e5051f5cac122d8c774b9" +checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" dependencies = [ - "rustc_version", + "autocfg 1.0.0", ] [[package]] @@ -1036,6 +1088,7 @@ dependencies = [ "crossbeam-channel", "fs-err", "notify", + "serde", ] [[package]] @@ -1274,9 +1327,9 @@ dependencies = [ [[package]] name = "paste" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e1afe738d71b1ebab5f1207c055054015427dbfc7bbe9ee1266894156ec046" +checksum = "092d791bf7847f70bbd49085489fba25fc2c193571752bff9e36e74e72403932" dependencies = [ "paste-impl", "proc-macro-hack", @@ -1284,9 +1337,9 @@ dependencies = [ [[package]] name = "paste-impl" -version = "0.1.7" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d4dc4a7f6f743211c5aab239640a65091535d97d43d92a52bca435a640892bb" +checksum = "406c23fb4c45cc6f68a9bbabb8ec7bd6f8cfcbd17e9e8f72c2460282f8325729" dependencies = [ "proc-macro-hack", "proc-macro2 1.0.9", @@ -1327,9 +1380,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.1.2" +version = "2.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27e5277315f6b4f27e0e6744feb5d5ba1891e7164871033d3c8344c6783b349a" +checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", @@ -1387,9 +1440,9 @@ dependencies = [ [[package]] name = "proc-macro-error" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7959c6467d962050d639361f7703b2051c43036d03493c36f01d440fdd3138a" +checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" dependencies = [ "proc-macro-error-attr", "proc-macro2 1.0.9", @@ -1400,9 +1453,9 @@ dependencies = [ [[package]] name = "proc-macro-error-attr" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4002d9f55991d5e019fb940a90e1a95eb80c24e77cb2462dd4dc869604d543a" +checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" dependencies = [ "proc-macro2 1.0.9", "quote 1.0.3", @@ -1413,20 +1466,15 @@ dependencies = [ [[package]] name = "proc-macro-hack" -version = "0.5.11" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecd45702f76d6d3c75a80564378ae228a85f0b59d2f3ed43c91b4a69eb2ebfc5" -dependencies = [ - "proc-macro2 1.0.9", - "quote 1.0.3", - "syn", -] +checksum = "fcfdefadc3d57ca21cf17990a28ef4c0f7c61383a28cb7604cf4a18e6ede1420" [[package]] name = "proc-macro-nested" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "369a6ed065f249a159e06c45752c780bda2fb53c995718f9e484d08daa9eb42e" +checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" [[package]] name = "proc-macro2" @@ -1532,7 +1580,7 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ "getrandom", "libc", - "rand_chacha 0.2.1", + "rand_chacha 0.2.2", "rand_core 0.5.1", "rand_hc 0.2.0", ] @@ -1549,11 +1597,11 @@ dependencies = [ [[package]] name = "rand_chacha" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03a2a90da8c7523f554344f921aa97283eadf6ac484a6d2a7d0212fa7f8d6853" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ - "c2-chacha", + "ppv-lite86", "rand_core 0.5.1", ] @@ -1746,10 +1794,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" [[package]] -name = "regex" -version = "1.3.4" +name = "redox_users" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "322cf97724bea3ee221b78fe25ac9c46114ebb51747ad5babd51a2fc6a8235a8" +checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" +dependencies = [ + "getrandom", + "redox_syscall", + "rust-argon2", +] + +[[package]] +name = "regex" +version = "1.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" dependencies = [ "aho-corasick", "memchr", @@ -1759,18 +1818,18 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92b73c2a1770c255c240eaa4ee600df1704a38dc3feaa6e949e7fcd4f8dc09f9" +checksum = "ae1ded71d66a4a97f5e961fd0cb25a5f366a42a41570d16a763a69c092c26ae4" dependencies = [ "byteorder", ] [[package]] name = "regex-syntax" -version = "0.6.16" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1132f845907680735a84409c3bebc64d1364a5683ffbce899550cd09d5eaefc1" +checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" [[package]] name = "remove_dir_all" @@ -1852,12 +1911,23 @@ dependencies = [ "num-traits", ] +[[package]] +name = "roblox_install" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f80edbbbcd67bce7ddaf754d94276b30ae0a72eedfdf034c0c987f4a535e4a54" +dependencies = [ + "dirs", + "winreg", +] + [[package]] name = "rojo" version = "0.6.0-alpha.3" dependencies = [ "anyhow", "backtrace", + "bincode", "criterion", "crossbeam-channel", "csv", @@ -1885,6 +1955,7 @@ dependencies = [ "reqwest", "ritz", "rlua", + "roblox_install", "rojo-insta-ext", "serde", "serde_json", @@ -1926,6 +1997,18 @@ dependencies = [ "walkdir", ] +[[package]] +name = "rust-argon2" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" +dependencies = [ + "base64 0.11.0", + "blake2b_simd", + "constant_time_eq", + "crossbeam-utils", +] + [[package]] name = "rustc-demangle" version = "0.1.16" @@ -1943,9 +2026,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa8506c1de11c9c4e4c38863ccbe02a305c8188e85a05a784c9e11e1c3910c8" +checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" [[package]] name = "same-file" @@ -1958,9 +2041,9 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "507a9e6e8ffe0a4e0ebb9a10293e62fdf7657c06f1b8bb07a8fcf697d2abf295" +checksum = "039c25b130bd8c1321ee2d7de7fde2659fa9c2744e4bb29711cfc852ea53cd19" dependencies = [ "lazy_static", "winapi 0.3.8", @@ -2012,18 +2095,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.104" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "414115f25f818d7dfccec8ee535d76949ae78584fc4f79a6f45a904bf8ab4449" +checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.104" +version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128f9e303a5a29922045a830221b8f78ec74a5f544944f3d5984f8ec3895ef64" +checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" dependencies = [ "proc-macro2 1.0.9", "quote 1.0.3", @@ -2032,9 +2115,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.48" +version = "1.0.50" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9371ade75d4c2d6cb154141b9752cf3781ec9c05e0e5cf35060e1e70ee7b9c25" +checksum = "78a7a12c167809363ec3bd7329fc0a3369056996de43c4b37ef3cd54a6ce4867" dependencies = [ "itoa", "ryu", @@ -2127,9 +2210,9 @@ checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" [[package]] name = "snafu" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "546db9181bce2aa22ed883c33d65603b76335b4c2533a98289f54265043de7a1" +checksum = "48492e4f51c6e679217e80c11290edfdedf3133e358f4f432a6296f4c820f95b" dependencies = [ "doc-comment", "snafu-derive", @@ -2137,9 +2220,9 @@ dependencies = [ [[package]] name = "snafu-derive" -version = "0.6.2" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdc75da2e0323f297402fd9c8fdba709bb04e4c627cbe31d19a2c91fc8d9f0e2" +checksum = "b5d1c41856cbfa99befda5034c72539dd9d7dd6f3e61058bdb804ac40715bc2a" dependencies = [ "proc-macro2 1.0.9", "quote 1.0.3", @@ -2172,9 +2255,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fe43617218c0805c6eb37160119dc3c548110a67786da7218d1c6555212f073" +checksum = "c8faa2719539bbe9d77869bfb15d4ee769f99525e707931452c97b693b3f159d" dependencies = [ "clap", "lazy_static", @@ -2183,9 +2266,9 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6e79c80e0f4efd86ca960218d4e056249be189ff1c42824dcd9a7f51a56f0bd" +checksum = "3f88b8e18c69496aad6f9ddf4630dd7d585bcaf765786cb415b9aec2fe5a0430" dependencies = [ "heck", "proc-macro-error", @@ -2196,9 +2279,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "123bd9499cfb380418d509322d7a6d52e5315f064fe4b3ad18a53d6b92c07859" +checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" dependencies = [ "proc-macro2 1.0.9", "quote 1.0.3", @@ -2281,18 +2364,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee14bf8e6767ab4c687c9e8bc003879e042a96fd67a3ba5934eadb6536bef4db" +checksum = "f0570dc61221295909abdb95c739f2e74325e14293b2026b0a7e195091ec54ae" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7b51e1fbc44b5a0840be594fbc0f960be09050f2617e61e6aa43bef97cd3ef4" +checksum = "227362df41d566be41a28f64401e07a043157c21c14b9785a0d8e256f940a8fd" dependencies = [ "proc-macro2 1.0.9", "quote 1.0.3", @@ -2545,9 +2628,9 @@ checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" [[package]] name = "ucd-trie" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f00ed7be0c1ff1e24f46c3d2af4859f7e863672ba3a6e92e7cff702bf9f06c2" +checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" [[package]] name = "unicase" @@ -2689,9 +2772,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasm-bindgen" -version = "0.2.59" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3557c397ab5a8e347d434782bcd31fc1483d927a6826804cec05cc792ee2519d" +checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -2699,9 +2782,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.59" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0da9c9a19850d3af6df1cb9574970b566d617ecfaf36eb0b706b6f3ef9bd2f8" +checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" dependencies = [ "bumpalo", "lazy_static", @@ -2714,9 +2797,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.59" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f6fde1d36e75a714b5fe0cffbb78978f222ea6baebb726af13c78869fdb4205" +checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" dependencies = [ "quote 1.0.3", "wasm-bindgen-macro-support", @@ -2724,9 +2807,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.59" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25bda4168030a6412ea8a047e27238cadf56f0e53516e1e83fec0a8b7c786f6d" +checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" dependencies = [ "proc-macro2 1.0.9", "quote 1.0.3", @@ -2737,15 +2820,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.59" +version = "0.2.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc9f36ad51f25b0219a3d4d13b90eb44cd075dff8b6280cca015775d7acaddd8" +checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" [[package]] name = "web-sys" -version = "0.3.36" +version = "0.3.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "721c6263e2c66fd44501cc5efbfa2b7dfa775d13e4ea38c46299646ed1f9c70a" +checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index b7d734d4..875663bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -62,6 +62,7 @@ memofs = { version = "0.1.1", path = "memofs" } anyhow = "1.0.27" backtrace = "0.3" +bincode = "1.2.1" crossbeam-channel = "0.4.0" csv = "1.1.1" env_logger = "0.7.1" @@ -84,6 +85,7 @@ regex = "1.3.1" reqwest = "0.9.20" ritz = "0.1.0" rlua = "0.17.0" +roblox_install = "0.2.2" serde = { version = "1.0", features = ["derive", "rc"] } serde_json = "1.0" structopt = "0.3.5" @@ -95,6 +97,13 @@ uuid = { version = "0.8.1", features = ["v4", "serde"] } [target.'cfg(windows)'.dependencies] winreg = "0.6.2" +[build-dependencies] +memofs = { version = "0.1.0", path = "memofs" } + +anyhow = "1.0.27" +bincode = "1.2.1" +maplit = "1.0.1" + [dev-dependencies] rojo-insta-ext = { path = "rojo-insta-ext" } diff --git a/build.rs b/build.rs new file mode 100644 index 00000000..71f8d1fd --- /dev/null +++ b/build.rs @@ -0,0 +1,78 @@ +use std::{ + env, + fs::{self, File}, + io, + path::{Path, PathBuf}, +}; + +use maplit::hashmap; +use memofs::VfsSnapshot; + +fn snapshot_from_fs_path(path: &Path) -> io::Result { + println!("cargo:rerun-if-changed={}", path.display()); + + if path.is_dir() { + let mut children = Vec::new(); + + for entry in fs::read_dir(path)? { + let entry = entry?; + + let file_name = entry.file_name().to_str().unwrap().to_owned(); + + // We can skip any TestEZ test files since they aren't necessary for + // the plugin to run. + if file_name.ends_with(".spec.lua") { + continue; + } + + let child_snapshot = snapshot_from_fs_path(&entry.path())?; + children.push((file_name, child_snapshot)); + } + + Ok(VfsSnapshot::dir(children)) + } else { + let content = fs::read_to_string(path)?; + + Ok(VfsSnapshot::file(content)) + } +} + +fn main() -> Result<(), anyhow::Error> { + let out_dir = env::var_os("OUT_DIR").unwrap(); + + let root_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap(); + let plugin_root = PathBuf::from(root_dir).join("plugin"); + + let plugin_modules = plugin_root.join("modules"); + + let snapshot = VfsSnapshot::dir(hashmap! { + "default.project.json" => snapshot_from_fs_path(&plugin_root.join("default.project.json"))?, + "fmt" => snapshot_from_fs_path(&plugin_root.join("fmt"))?, + "http" => snapshot_from_fs_path(&plugin_root.join("http"))?, + "log" => snapshot_from_fs_path(&plugin_root.join("log"))?, + "src" => snapshot_from_fs_path(&plugin_root.join("src"))?, + "modules" => VfsSnapshot::dir(hashmap! { + "roact" => VfsSnapshot::dir(hashmap! { + "src" => snapshot_from_fs_path(&plugin_modules.join("roact").join("src"))? + }), + "promise" => VfsSnapshot::dir(hashmap! { + "lib" => snapshot_from_fs_path(&plugin_modules.join("promise").join("lib"))? + }), + "t" => VfsSnapshot::dir(hashmap! { + "lib" => snapshot_from_fs_path(&plugin_modules.join("t").join("lib"))? + }), + "rbx-dom" => VfsSnapshot::dir(hashmap! { + "rbx_dom_lua" => VfsSnapshot::dir(hashmap! { + "src" => snapshot_from_fs_path(&plugin_modules.join("rbx-dom").join("rbx_dom_lua").join("src"))? + }) + }), + }), + }); + + let out_path = Path::new(&out_dir).join("plugin.bincode"); + let out_file = File::create(&out_path)?; + + bincode::serialize_into(out_file, &snapshot)?; + + Ok(()) +} diff --git a/memofs/Cargo.toml b/memofs/Cargo.toml index 3843606a..0d0d4a39 100644 --- a/memofs/Cargo.toml +++ b/memofs/Cargo.toml @@ -14,3 +14,4 @@ homepage = "https://github.com/rojo-rbx/rojo/tree/master/memofs" crossbeam-channel = "0.4.0" fs-err = "2.3.0" notify = "4.0.15" +serde = { version = "1.0", features = ["derive"] } diff --git a/memofs/src/snapshot.rs b/memofs/src/snapshot.rs index e6596bb2..0df3d473 100644 --- a/memofs/src/snapshot.rs +++ b/memofs/src/snapshot.rs @@ -1,8 +1,9 @@ +use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; /// A slice of a tree of files. Can be loaded into an /// [`InMemoryFs`](struct.InMemoryFs.html). -#[derive(Debug)] +#[derive(Debug, Serialize, Deserialize)] #[non_exhaustive] pub enum VfsSnapshot { File { diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom index 94116dcc..5bca08fe 160000 --- a/plugin/modules/rbx-dom +++ b/plugin/modules/rbx-dom @@ -1 +1 @@ -Subproject commit 94116dcc11a1728e49dad1c779077cff526c2808 +Subproject commit 5bca08fec3f5708a29811dceb11957b92eafe81f diff --git a/src/bin.rs b/src/bin.rs index 403823c6..aa8c647b 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -12,6 +12,7 @@ fn run(global: GlobalOptions, subcommand: Subcommand) -> Result<(), Box cli::build(build_options)?, Subcommand::Upload(upload_options) => cli::upload(upload_options)?, Subcommand::Doc => cli::doc()?, + Subcommand::Plugin(plugin_options) => cli::plugin(plugin_options)?, } Ok(()) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 1339527c..5bd69a1d 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -3,6 +3,7 @@ mod build; mod doc; mod init; +mod plugin; mod serve; mod upload; @@ -21,6 +22,7 @@ use thiserror::Error; pub use self::build::*; pub use self::doc::*; pub use self::init::*; +pub use self::plugin::*; pub use self::serve::*; pub use self::upload::*; @@ -111,6 +113,9 @@ pub enum Subcommand { /// Open Rojo's documentation in your browser. Doc, + + /// Manages Rojo's Roblox Studio plugin. + Plugin(PluginCommand), } /// Initializes a new Rojo project. @@ -287,3 +292,21 @@ fn resolve_path(path: &Path) -> Cow<'_, Path> { Cow::Owned(env::current_dir().unwrap().join(path)) } } + +#[derive(Debug, StructOpt)] +pub enum PluginSubcommand { + /// Install the plugin in Roblox Studio's plugins folder. If the plugin is + /// already installed, installing it again will overwrite the current plugin + /// file. + Install, + + /// Removes the plugin if it is installed. + Uninstall, +} + +/// Install Rojo's plugin. +#[derive(Debug, StructOpt)] +pub struct PluginCommand { + #[structopt(subcommand)] + subcommand: PluginSubcommand, +} diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs new file mode 100644 index 00000000..8ddca54d --- /dev/null +++ b/src/cli/plugin.rs @@ -0,0 +1,70 @@ +use std::{ + fs::{self, File}, + io::BufWriter, +}; + +use anyhow::Result; +use memofs::{InMemoryFs, Vfs, VfsSnapshot}; +use roblox_install::RobloxStudio; + +use crate::{ + cli::{PluginCommand, PluginSubcommand}, + serve_session::ServeSession, +}; + +static PLUGIN_BINCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/plugin.bincode")); +static PLUGIN_FILE_NAME: &str = "RojoManagedPlugin.rbxm"; + +pub fn plugin(options: PluginCommand) -> Result<()> { + match options.subcommand { + PluginSubcommand::Install => install_plugin(), + PluginSubcommand::Uninstall => uninstall_plugin(), + } +} + +pub fn install_plugin() -> Result<()> { + let plugin_snapshot: VfsSnapshot = bincode::deserialize(PLUGIN_BINCODE) + .expect("Rojo's plugin was not properly packed into Rojo's binary"); + + let studio = RobloxStudio::locate()?; + + let plugins_folder_path = studio.plugins_path(); + + if !plugins_folder_path.exists() { + log::debug!("Creating Roblox Studio plugins folder"); + fs::create_dir(plugins_folder_path)?; + } + + let mut in_memory_fs = InMemoryFs::new(); + in_memory_fs.load_snapshot("plugin", plugin_snapshot)?; + + let vfs = Vfs::new(in_memory_fs); + let session = ServeSession::new(vfs, "plugin")?; + + let plugin_path = plugins_folder_path.join(PLUGIN_FILE_NAME); + log::debug!("Writing plugin to {}", plugin_path.display()); + + let mut file = BufWriter::new(File::create(plugin_path)?); + + let tree = session.tree(); + let root_id = tree.get_root_id(); + + rbx_binary::encode(tree.inner(), &[root_id], &mut file)?; + + Ok(()) +} + +fn uninstall_plugin() -> Result<()> { + let studio = RobloxStudio::locate()?; + + let plugin_path = studio.plugins_path().join(PLUGIN_FILE_NAME); + + if plugin_path.exists() { + log::debug!("Removing existing plugin from {}", plugin_path.display()); + fs::remove_file(plugin_path)?; + } else { + log::debug!("Plugin not installed at {}", plugin_path.display()); + } + + Ok(()) +} From 571ef3060a9511de162c575feddc156a29b0d55c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 29 Mar 2020 13:46:27 -0700 Subject: [PATCH 1035/1504] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 259f2d75..c86fac67 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ * "Two-Way Sync": When enabled, Rojo will attempt to save changes to your place back to the filesystem. **Very early feature, very broken, beware!** * Added `--color` option to force-enable or force-disable color in Rojo's output. * Added support for turning `.json` files into `ModuleScript` instances ([#308](https://github.com/rojo-rbx/rojo/pull/308)) +* Added `rojo plugin install` and `rojo plugin uninstall` to allow Rojo to manage its Roblox Studio plugin. ([#304](https://github.com/rojo-rbx/rojo/pull/304)) * The server half of **experimental** two-way sync is now enabled by default. * Increased default logging verbosity in commands like `rojo build`. * Rojo now requires a project file again, just like 0.5.4. From 6a1fffd1cecb4d22ea995fed9bab380ae49f33f7 Mon Sep 17 00:00:00 2001 From: jeparlefrancais <35781636+jeparlefrancais@users.noreply.github.com> Date: Sun, 29 Mar 2020 19:03:15 -0400 Subject: [PATCH 1036/1504] Infer class name (#210) * infer service names * Update project code and add support for StarterPlayer * Store parent_class in InstigatingSource * Update snapshots Co-authored-by: Lucien Greathouse --- ..._test__build_test__infer_service_name.snap | 28 +++++++++++++ ...est__build_test__infer_starter_player.snap | 26 ++++++++++++ .../infer_service_name/default.project.json | 16 ++++++++ .../build-tests/infer_service_name/main.lua | 1 + .../infer_starter_player/default.project.json | 11 +++++ .../build-tests/infer_starter_player/main.lua | 1 + rojo-test/src/build_test.rs | 4 +- src/change_processor.rs | 7 ++-- src/snapshot/metadata.rs | 8 ++-- src/snapshot_middleware/project.rs | 41 +++++++++++++++++-- ..._project__test__project_with_children.snap | 1 + ...ct_with_path_to_project_with_children.snap | 1 + 12 files changed, 134 insertions(+), 11 deletions(-) create mode 100644 rojo-test/build-test-snapshots/rojo_test__build_test__infer_service_name.snap create mode 100644 rojo-test/build-test-snapshots/rojo_test__build_test__infer_starter_player.snap create mode 100644 rojo-test/build-tests/infer_service_name/default.project.json create mode 100644 rojo-test/build-tests/infer_service_name/main.lua create mode 100644 rojo-test/build-tests/infer_starter_player/default.project.json create mode 100644 rojo-test/build-tests/infer_starter_player/main.lua diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__infer_service_name.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__infer_service_name.snap new file mode 100644 index 00000000..bda746ce --- /dev/null +++ b/rojo-test/build-test-snapshots/rojo_test__build_test__infer_service_name.snap @@ -0,0 +1,28 @@ +--- +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + infer-service-name + + + + HttpService + true + + + + + ReplicatedStorage + + + + Main + -- hello, from main + + + + + diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__infer_starter_player.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__infer_starter_player.snap new file mode 100644 index 00000000..13574f23 --- /dev/null +++ b/rojo-test/build-test-snapshots/rojo_test__build_test__infer_starter_player.snap @@ -0,0 +1,26 @@ +--- +source: rojo-test/src/build_test.rs +expression: contents +--- + + + + infer-service-name + + + + StarterPlayer + + + + StarterCharacterScripts + + + + + StarterPlayerScripts + + + + + diff --git a/rojo-test/build-tests/infer_service_name/default.project.json b/rojo-test/build-tests/infer_service_name/default.project.json new file mode 100644 index 00000000..36d8906c --- /dev/null +++ b/rojo-test/build-tests/infer_service_name/default.project.json @@ -0,0 +1,16 @@ +{ + "name": "infer-service-name", + "tree": { + "$className": "DataModel", + "ReplicatedStorage": { + "Main": { + "$path": "main.lua" + } + }, + "HttpService": { + "$properties": { + "HttpEnabled": true + } + } + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/infer_service_name/main.lua b/rojo-test/build-tests/infer_service_name/main.lua new file mode 100644 index 00000000..36c9d9bc --- /dev/null +++ b/rojo-test/build-tests/infer_service_name/main.lua @@ -0,0 +1 @@ +-- hello, from main \ No newline at end of file diff --git a/rojo-test/build-tests/infer_starter_player/default.project.json b/rojo-test/build-tests/infer_starter_player/default.project.json new file mode 100644 index 00000000..3e505e66 --- /dev/null +++ b/rojo-test/build-tests/infer_starter_player/default.project.json @@ -0,0 +1,11 @@ +{ + "name": "infer-service-name", + "tree": { + "$className": "DataModel", + + "StarterPlayer": { + "StarterPlayerScripts": {}, + "StarterCharacterScripts": {} + } + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/infer_starter_player/main.lua b/rojo-test/build-tests/infer_starter_player/main.lua new file mode 100644 index 00000000..36c9d9bc --- /dev/null +++ b/rojo-test/build-tests/infer_starter_player/main.lua @@ -0,0 +1 @@ +-- hello, from main \ No newline at end of file diff --git a/rojo-test/src/build_test.rs b/rojo-test/src/build_test.rs index 7939f206..f0d6424d 100644 --- a/rojo-test/src/build_test.rs +++ b/rojo-test/src/build_test.rs @@ -28,6 +28,8 @@ gen_build_tests! { csv_in_folder, deep_nesting, gitkeep, + infer_service_name, + infer_starter_player, init_meta_class_name, init_meta_properties, init_with_children, @@ -38,10 +40,10 @@ gen_build_tests! { module_init, rbxm_in_folder, rbxmx_in_folder, + rbxmx_ref, script_meta_disabled, server_in_folder, server_init, - rbxmx_ref, txt, txt_in_folder, } diff --git a/src/change_processor.rs b/src/change_processor.rs index 15f264c8..9e7797ee 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -178,7 +178,7 @@ impl JobThreadContext { if let Some(instigating_source) = &instance.metadata().instigating_source { match instigating_source { InstigatingSource::Path(path) => fs::remove_file(path).unwrap(), - InstigatingSource::ProjectNode(_, _, _) => { + InstigatingSource::ProjectNode(_, _, _, _) => { log::warn!( "Cannot remove instance {}, it's from a project file", id @@ -226,7 +226,7 @@ impl JobThreadContext { log::warn!("Cannot change Source to non-string value."); } } - InstigatingSource::ProjectNode(_, _, _) => { + InstigatingSource::ProjectNode(_, _, _, _) => { log::warn!( "Cannot remove instance {}, it's from a project file", id @@ -318,7 +318,7 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: RbxId) -> Optio } }, - InstigatingSource::ProjectNode(project_path, instance_name, project_node) => { + InstigatingSource::ProjectNode(project_path, instance_name, project_node, parent_class) => { // This instance is the direct subject of a project node. Since // there might be information associated with our instance from // the project file, we snapshot the entire project node again. @@ -329,6 +329,7 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: RbxId) -> Optio instance_name, project_node, &vfs, + parent_class.as_ref().map(|name| name.as_str()), ); let snapshot = match snapshot_result { diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index 983b426e..192a0001 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -163,6 +163,7 @@ pub enum InstigatingSource { #[serde(serialize_with = "path_serializer::serialize_absolute")] PathBuf, String, ProjectNode, + Option, ), } @@ -170,12 +171,13 @@ impl fmt::Debug for InstigatingSource { fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { match self { InstigatingSource::Path(path) => write!(formatter, "Path({})", path.display()), - InstigatingSource::ProjectNode(path, name, node) => write!( + InstigatingSource::ProjectNode(path, name, node, parent_class) => write!( formatter, - "ProjectNode({}: {:?}) from path {}", + "ProjectNode({}: {:?}) from path {} and parent class {:?}", name, node, - path.display() + path.display(), + parent_class, ), } } diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index e2d0c3a7..cefed521 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -1,7 +1,7 @@ use std::{borrow::Cow, collections::HashMap, path::Path}; use memofs::{IoResultExt, Vfs}; -use rbx_reflection::try_resolve_value; +use rbx_reflection::{get_class_descriptor, try_resolve_value}; use crate::{ project::{Project, ProjectNode}, @@ -62,6 +62,7 @@ impl SnapshotMiddleware for SnapshotProject { &project.name, &project.tree, vfs, + None, )? .unwrap(); @@ -93,6 +94,7 @@ pub fn snapshot_project_node( instance_name: &str, node: &ProjectNode, vfs: &Vfs, + parent_class: Option<&str>, ) -> SnapshotInstanceResult { let name = Cow::Owned(instance_name.to_owned()); let mut class_name = node @@ -158,13 +160,43 @@ pub fn snapshot_project_node( } let class_name = class_name + .or_else(|| { + // If className wasn't defined from another source, we may be able + // to infer one. + + let parent_class = parent_class?; + + if parent_class == "DataModel" { + // Members of DataModel with names that match known services are + // probably supposed to be those services. + + let descriptor = get_class_descriptor(&name)?; + + if descriptor.is_service() { + return Some(name.clone()); + } + } else if parent_class == "StarterPlayer" { + // StarterPlayer has two special members with their own classes. + + if name == "StarterPlayerScripts" || name == "StarterCharacterScripts" { + return Some(name.clone()); + } + } + + None + }) // TODO: Turn this into an error object. .expect("$className or $path must be specified"); for (child_name, child_project_node) in &node.children { - if let Some(child) = - snapshot_project_node(context, project_folder, child_name, child_project_node, vfs)? - { + if let Some(child) = snapshot_project_node( + context, + project_folder, + child_name, + child_project_node, + vfs, + Some(&class_name), + )? { children.push(child); } } @@ -194,6 +226,7 @@ pub fn snapshot_project_node( project_folder.to_path_buf(), instance_name.to_string(), node.clone(), + parent_class.map(|name| name.to_owned()), )); Ok(Some(InstanceSnapshot { diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap index ab659524..e5603c97 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap @@ -22,6 +22,7 @@ children: - /foo - Child - $className: Model + - Folder relevant_paths: [] context: {} name: Child diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap index ba3fb273..389d24e2 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap @@ -23,6 +23,7 @@ children: - /foo - SomeChild - $className: Model + - Folder relevant_paths: [] context: {} name: SomeChild From 5a5b1268d35eee4727d8a9145a1bce96e8b609a5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 29 Mar 2020 16:03:58 -0700 Subject: [PATCH 1037/1504] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c86fac67..490cffc4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Added `--color` option to force-enable or force-disable color in Rojo's output. * Added support for turning `.json` files into `ModuleScript` instances ([#308](https://github.com/rojo-rbx/rojo/pull/308)) * Added `rojo plugin install` and `rojo plugin uninstall` to allow Rojo to manage its Roblox Studio plugin. ([#304](https://github.com/rojo-rbx/rojo/pull/304)) +* Class names no longer need to be specified for Roblox services in Rojo projects. ([#210](https://github.com/rojo-rbx/rojo/pull/210)) * The server half of **experimental** two-way sync is now enabled by default. * Increased default logging verbosity in commands like `rojo build`. * Rojo now requires a project file again, just like 0.5.4. From 1214fc8b0db92a32e2808d6b613883c870d0f0ea Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 29 Mar 2020 16:17:09 -0700 Subject: [PATCH 1038/1504] Release 6.0.0-rc.1 This change also includes some minor packaging changes in order to make Cargo happy. --- .gitmodules | 5 +- CHANGELOG.md | 6 +- Cargo.lock | 4 +- Cargo.toml | 6 +- README.md | 2 +- build.rs | 12 +- memofs/Cargo.toml | 2 +- plugin/default.project.json | 6 +- plugin/modules/rbx-dom | 1 - plugin/rbx_dom_lua/.luacheckrc | 44 + plugin/rbx_dom_lua/README.md | 2 + plugin/rbx_dom_lua/default.project.json | 6 + plugin/rbx_dom_lua/src/EncodedValue.lua | 242 + plugin/rbx_dom_lua/src/EncodedValue.spec.lua | 127 + plugin/rbx_dom_lua/src/Error.lua | 28 + plugin/rbx_dom_lua/src/PropertyDescriptor.lua | 80 + .../src/ReflectionDatabase/classes.lua | 18757 ++++++++++++++++ .../src/ReflectionDatabase/init.lua | 3 + plugin/rbx_dom_lua/src/base64.lua | 139 + plugin/rbx_dom_lua/src/base64.spec.lua | 29 + plugin/rbx_dom_lua/src/customProperties.lua | 47 + plugin/rbx_dom_lua/src/init.lua | 67 + plugin/rbx_dom_lua/src/init.spec.lua | 7 + plugin/rbx_dom_lua/test-place.project.json | 35 + plugin/rbx_dom_lua/test.server.lua | 7 + plugin/src/Config.lua | 4 +- 26 files changed, 19642 insertions(+), 26 deletions(-) delete mode 160000 plugin/modules/rbx-dom create mode 100644 plugin/rbx_dom_lua/.luacheckrc create mode 100644 plugin/rbx_dom_lua/README.md create mode 100644 plugin/rbx_dom_lua/default.project.json create mode 100644 plugin/rbx_dom_lua/src/EncodedValue.lua create mode 100644 plugin/rbx_dom_lua/src/EncodedValue.spec.lua create mode 100644 plugin/rbx_dom_lua/src/Error.lua create mode 100644 plugin/rbx_dom_lua/src/PropertyDescriptor.lua create mode 100644 plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua create mode 100644 plugin/rbx_dom_lua/src/ReflectionDatabase/init.lua create mode 100644 plugin/rbx_dom_lua/src/base64.lua create mode 100644 plugin/rbx_dom_lua/src/base64.spec.lua create mode 100644 plugin/rbx_dom_lua/src/customProperties.lua create mode 100644 plugin/rbx_dom_lua/src/init.lua create mode 100644 plugin/rbx_dom_lua/src/init.spec.lua create mode 100644 plugin/rbx_dom_lua/test-place.project.json create mode 100644 plugin/rbx_dom_lua/test.server.lua diff --git a/.gitmodules b/.gitmodules index 1e86ae9d..90468044 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,7 +9,4 @@ url = https://github.com/LPGhatguy/roblox-lua-promise.git [submodule "plugin/modules/t"] path = plugin/modules/t - url = https://github.com/osyrisrblx/t.git -[submodule "plugin/modules/rbx-dom"] - path = plugin/modules/rbx-dom - url = http://github.com/rojo-rbx/rbx-dom \ No newline at end of file + url = https://github.com/osyrisrblx/t.git \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 490cffc4..b07f2d3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Rojo Changelog -## Unreleased Changes for 0.6.x +## Unreleased Changes + +## [6.0.0 Release Candidate 1](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.1) (March 29, 2020) +This release jumped from 0.6.0 to 6.0.0. Rojo has been in use in production for many users for quite a long times, and so 6.0 is a more accurate reflection of Rojo's version than a pre-1.0 version. + * Added basic settings panel to plugin, with two settings: * "Open Scripts Externally": When enabled, opening a script in Studio will instead open it in your default text editor. * "Two-Way Sync": When enabled, Rojo will attempt to save changes to your place back to the filesystem. **Very early feature, very broken, beware!** diff --git a/Cargo.lock b/Cargo.lock index 3926256a..73faed7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1083,7 +1083,7 @@ dependencies = [ [[package]] name = "memofs" -version = "0.1.1" +version = "0.1.2" dependencies = [ "crossbeam-channel", "fs-err", @@ -1923,7 +1923,7 @@ dependencies = [ [[package]] name = "rojo" -version = "0.6.0-alpha.3" +version = "6.0.0-rc.1" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 875663bf..818dd973 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "0.6.0-alpha.3" +version = "6.0.0-rc.1" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" @@ -11,7 +11,6 @@ readme = "README.md" edition = "2018" exclude = [ - "/plugin/**", "/test-projects/**", ] @@ -58,7 +57,7 @@ name = "build" harness = false [dependencies] -memofs = { version = "0.1.1", path = "memofs" } +memofs = { version = "0.1.2", path = "memofs" } anyhow = "1.0.27" backtrace = "0.3" @@ -102,6 +101,7 @@ memofs = { version = "0.1.0", path = "memofs" } anyhow = "1.0.27" bincode = "1.2.1" +fs-err = "2.3.0" maplit = "1.0.1" [dev-dependencies] diff --git a/README.md b/README.md index 3c86d35b..4ab247ec 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ Latest server version - Rojo 0.5.x Documentation + Rojo Documentation diff --git a/build.rs b/build.rs index 71f8d1fd..343c151a 100644 --- a/build.rs +++ b/build.rs @@ -1,10 +1,10 @@ use std::{ - env, - fs::{self, File}, - io, + env, io, path::{Path, PathBuf}, }; +use fs_err as fs; +use fs_err::File; use maplit::hashmap; use memofs::VfsSnapshot; @@ -50,6 +50,7 @@ fn main() -> Result<(), anyhow::Error> { "fmt" => snapshot_from_fs_path(&plugin_root.join("fmt"))?, "http" => snapshot_from_fs_path(&plugin_root.join("http"))?, "log" => snapshot_from_fs_path(&plugin_root.join("log"))?, + "rbx_dom_lua" => snapshot_from_fs_path(&plugin_root.join("rbx_dom_lua"))?, "src" => snapshot_from_fs_path(&plugin_root.join("src"))?, "modules" => VfsSnapshot::dir(hashmap! { "roact" => VfsSnapshot::dir(hashmap! { @@ -61,11 +62,6 @@ fn main() -> Result<(), anyhow::Error> { "t" => VfsSnapshot::dir(hashmap! { "lib" => snapshot_from_fs_path(&plugin_modules.join("t").join("lib"))? }), - "rbx-dom" => VfsSnapshot::dir(hashmap! { - "rbx_dom_lua" => VfsSnapshot::dir(hashmap! { - "src" => snapshot_from_fs_path(&plugin_modules.join("rbx-dom").join("rbx_dom_lua").join("src"))? - }) - }), }), }); diff --git a/memofs/Cargo.toml b/memofs/Cargo.toml index 0d0d4a39..3484c765 100644 --- a/memofs/Cargo.toml +++ b/memofs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "memofs" description = "Virtual filesystem with configurable backends." -version = "0.1.1" +version = "0.1.2" authors = ["Lucien Greathouse "] edition = "2018" readme = "README.md" diff --git a/plugin/default.project.json b/plugin/default.project.json index 36ee57f1..c1a85c9b 100644 --- a/plugin/default.project.json +++ b/plugin/default.project.json @@ -14,6 +14,9 @@ "Fmt": { "$path": "fmt" }, + "RbxDom": { + "$path": "rbx_dom_lua" + }, "Roact": { "$path": "modules/roact/src" }, @@ -22,9 +25,6 @@ }, "t": { "$path": "modules/t/lib" - }, - "RbxDom": { - "$path": "modules/rbx-dom/rbx_dom_lua/src" } } } \ No newline at end of file diff --git a/plugin/modules/rbx-dom b/plugin/modules/rbx-dom deleted file mode 160000 index 5bca08fe..00000000 --- a/plugin/modules/rbx-dom +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 5bca08fec3f5708a29811dceb11957b92eafe81f diff --git a/plugin/rbx_dom_lua/.luacheckrc b/plugin/rbx_dom_lua/.luacheckrc new file mode 100644 index 00000000..f1447162 --- /dev/null +++ b/plugin/rbx_dom_lua/.luacheckrc @@ -0,0 +1,44 @@ +stds.roblox = { + read_globals = { + game = { + other_fields = true, + }, + + -- Roblox globals + "script", + + -- Extra functions + "tick", "warn", + "wait", "typeof", + + -- Types + "CFrame", + "Color3", + "Enum", + "Instance", + "NumberRange", + "Rect", + "UDim", "UDim2", + "Vector2", "Vector3", + "Vector2int16", "Vector3int16", + } +} + +stds.testez = { + read_globals = { + "describe", + "it", "itFOCUS", "itSKIP", + "FOCUS", "SKIP", "HACK_NO_XPCALL", + "expect", + } +} + +ignore = { + "212", -- unused arguments +} + +std = "lua51+roblox" + +files["**/*.spec.lua"] = { + std = "+testez", +} \ No newline at end of file diff --git a/plugin/rbx_dom_lua/README.md b/plugin/rbx_dom_lua/README.md new file mode 100644 index 00000000..e2eec50c --- /dev/null +++ b/plugin/rbx_dom_lua/README.md @@ -0,0 +1,2 @@ +# rbx\_dom\_lua +Roblox Lua implementation of rbx-dom mechanisms, intended to work with rbx\_dom\_weak and friends. \ No newline at end of file diff --git a/plugin/rbx_dom_lua/default.project.json b/plugin/rbx_dom_lua/default.project.json new file mode 100644 index 00000000..2ecfe52b --- /dev/null +++ b/plugin/rbx_dom_lua/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "rbx_dom_lua", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/EncodedValue.lua b/plugin/rbx_dom_lua/src/EncodedValue.lua new file mode 100644 index 00000000..a36de63b --- /dev/null +++ b/plugin/rbx_dom_lua/src/EncodedValue.lua @@ -0,0 +1,242 @@ +local base64 = require(script.Parent.base64) + +local function identity(...) + return ... +end + +local function unpackDecoder(f) + return function(value) + return f(unpack(value)) + end +end + +local function serializeFloat(value) + -- TODO: Figure out a better way to serialize infinity and NaN, neither of + -- which fit into JSON. + if value == math.huge or value == -math.huge then + return 999999999 * math.sign(value) + end + + return value +end + +local encoders +encoders = { + Bool = identity, + Content = identity, + Float32 = serializeFloat, + Float64 = serializeFloat, + Int32 = identity, + Int64 = identity, + String = identity, + + BinaryString = base64.encode, + SharedString = base64.encode, + + BrickColor = function(value) + return value.Number + end, + + CFrame = function(value) + return {value:GetComponents()} + end, + Color3 = function(value) + return {value.r, value.g, value.b} + end, + NumberRange = function(value) + return {value.Min, value.Max} + end, + NumberSequence = function(value) + local keypoints = {} + + for index, keypoint in ipairs(value.Keypoints) do + keypoints[index] = { + Time = keypoint.Time, + Value = keypoint.Value, + Envelope = keypoint.Envelope, + } + end + + return { + Keypoints = keypoints, + } + end, + ColorSequence = function(value) + local keypoints = {} + + for index, keypoint in ipairs(value.Keypoints) do + keypoints[index] = { + Time = keypoint.Time, + Color = encoders.Color3(keypoint.Value), + } + end + + return { + Keypoints = keypoints, + } + end, + Rect = function(value) + return { + Min = {value.Min.X, value.Min.Y}, + Max = {value.Max.X, value.Max.Y}, + } + end, + UDim = function(value) + return {value.Scale, value.Offset} + end, + UDim2 = function(value) + return {value.X.Scale, value.X.Offset, value.Y.Scale, value.Y.Offset} + end, + Vector2 = function(value) + return { + serializeFloat(value.X), + serializeFloat(value.Y), + } + end, + Vector2int16 = function(value) + return {value.X, value.Y} + end, + Vector3 = function(value) + return { + serializeFloat(value.X), + serializeFloat(value.Y), + serializeFloat(value.Z), + } + end, + Vector3int16 = function(value) + return {value.X, value.Y, value.Z} + end, + + PhysicalProperties = function(value) + if value == nil then + return nil + else + return { + Density = value.Density, + Friction = value.Friction, + Elasticity = value.Elasticity, + FrictionWeight = value.FrictionWeight, + ElasticityWeight = value.ElasticityWeight, + } + end + end, + + Ref = function(value) + return nil + end, +} + +local decoders = { + Bool = identity, + Content = identity, + Enum = identity, + Float32 = identity, + Float64 = identity, + Int32 = identity, + Int64 = identity, + String = identity, + + BinaryString = base64.decode, + SharedString = base64.decode, + + BrickColor = BrickColor.new, + + CFrame = unpackDecoder(CFrame.new), + Color3 = unpackDecoder(Color3.new), + Color3uint8 = unpackDecoder(Color3.fromRGB), + NumberRange = unpackDecoder(NumberRange.new), + UDim = unpackDecoder(UDim.new), + UDim2 = unpackDecoder(UDim2.new), + Vector2 = unpackDecoder(Vector2.new), + Vector2int16 = unpackDecoder(Vector2int16.new), + Vector3 = unpackDecoder(Vector3.new), + Vector3int16 = unpackDecoder(Vector3int16.new), + + Rect = function(value) + return Rect.new(value.Min[1], value.Min[2], value.Max[1], value.Max[2]) + end, + + NumberSequence = function(value) + local keypoints = {} + + for index, keypoint in ipairs(value.Keypoints) do + keypoints[index] = NumberSequenceKeypoint.new( + keypoint.Time, + keypoint.Value, + keypoint.Envelope + ) + end + + return NumberSequence.new(keypoints) + end, + + ColorSequence = function(value) + local keypoints = {} + + for index, keypoint in ipairs(value.Keypoints) do + keypoints[index] = ColorSequenceKeypoint.new( + keypoint.Time, + Color3.new(unpack(keypoint.Color)) + ) + end + + return ColorSequence.new(keypoints) + end, + + PhysicalProperties = function(properties) + if properties == nil then + return nil + else + return PhysicalProperties.new( + properties.Density, + properties.Friction, + properties.Elasticity, + properties.FrictionWeight, + properties.ElasticityWeight + ) + end + end, + + Ref = function() + return nil + end, +} + +local EncodedValue = {} + +function EncodedValue.decode(encodedValue) + local decoder = decoders[encodedValue.Type] + if decoder ~= nil then + return true, decoder(encodedValue.Value) + end + + return false, "Couldn't decode value " .. tostring(encodedValue.Type) +end + +function EncodedValue.encode(rbxValue, propertyType) + assert(propertyType ~= nil, "Property type descriptor is required") + + if propertyType.type == "Data" then + local encoder = encoders[propertyType.name] + + if encoder == nil then + return false, ("Missing encoder for property type %q"):format(propertyType.name) + end + + if encoder ~= nil then + return true, { + Type = propertyType.name, + Value = encoder(rbxValue), + } + end + elseif propertyType.type == "Enum" then + return true, { + Type = "Enum", + Value = rbxValue.Value, + } + end + + return false, ("Unknown property descriptor type %q"):format(tostring(propertyType.type)) +end + +return EncodedValue \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/EncodedValue.spec.lua b/plugin/rbx_dom_lua/src/EncodedValue.spec.lua new file mode 100644 index 00000000..c58f801d --- /dev/null +++ b/plugin/rbx_dom_lua/src/EncodedValue.spec.lua @@ -0,0 +1,127 @@ +return function() + local RbxDom = require(script.Parent) + local EncodedValue = require(script.Parent.EncodedValue) + + it("should decode Rect values", function() + local input = { + Type = "Rect", + Value = { + Min = {1, 2}, + Max = {3, 4}, + }, + } + + local output = Rect.new(1, 2, 3, 4) + + local ok, decoded = EncodedValue.decode(input) + + assert(ok, decoded) + expect(decoded).to.equal(output) + end) + + it("should decode ColorSequence values", function() + local input = { + Type = "ColorSequence", + Value = { + Keypoints = { + { + Time = 0, + Color = { 0.12, 0.34, 0.56 }, + }, + + { + Time = 1, + Color = { 0.13, 0.33, 0.37 }, + }, + } + }, + } + + local output = ColorSequence.new({ + ColorSequenceKeypoint.new(0, Color3.new(0.12, 0.34, 0.56)), + ColorSequenceKeypoint.new(1, Color3.new(0.13, 0.33, 0.37)), + }) + + local ok, decoded = EncodedValue.decode(input) + assert(ok, decoded) + expect(decoded).to.equal(output) + end) + + it("should decode NumberSequence values", function() + local input = { + Type = "NumberSequence", + Value = { + Keypoints = { + { + Time = 0, + Value = 0.5, + Envelope = 0, + }, + + { + Time = 1, + Value = 0.5, + Envelope = 0, + }, + } + }, + } + + local output = NumberSequence.new({ + NumberSequenceKeypoint.new(0, 0.5, 0), + NumberSequenceKeypoint.new(1, 0.5, 0), + }) + + local ok, decoded = EncodedValue.decode(input) + assert(ok, decoded) + expect(decoded).to.equal(output) + end) + + it("should decode PhysicalProperties values", function() + local input = { + Type = "PhysicalProperties", + Value = { + Density = 0.1, + Friction = 0.2, + Elasticity = 0.3, + FrictionWeight = 0.4, + ElasticityWeight = 0.5, + }, + } + + local output = PhysicalProperties.new( + 0.1, + 0.2, + 0.3, + 0.4, + 0.5 + ) + + local ok, decoded = EncodedValue.decode(input) + assert(ok, decoded) + expect(decoded).to.equal(output) + end) + + -- This part of rbx_dom_lua needs some work still. + itSKIP("should encode Rect values", function() + local input = Rect.new(10, 20, 30, 40) + + local output = { + Type = "Rect", + Value = { + Min = {10, 20}, + Max = {30, 40}, + }, + } + + local descriptor = RbxDom.findCanonicalPropertyDescriptor("ImageLabel", "SliceCenter") + local ok, encoded = EncodedValue.encode(input, descriptor) + + assert(ok, encoded) + expect(encoded.Type).to.equal(output.Type) + expect(encoded.Value.Min[1]).to.equal(output.Value.Min[1]) + expect(encoded.Value.Min[2]).to.equal(output.Value.Min[2]) + expect(encoded.Value.Max[1]).to.equal(output.Value.Max[1]) + expect(encoded.Value.Max[2]).to.equal(output.Value.Max[2]) + end) +end \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/Error.lua b/plugin/rbx_dom_lua/src/Error.lua new file mode 100644 index 00000000..d4c8b1ca --- /dev/null +++ b/plugin/rbx_dom_lua/src/Error.lua @@ -0,0 +1,28 @@ +local Error = {} +Error.__index = Error + +Error.Kind = { + UnknownProperty = "UnknownProperty", + PropertyNotReadable = "PropertyNotReadable", + PropertyNotWritable = "PropertyNotWritable", + Roblox = "Roblox", +} + +setmetatable(Error.Kind, { + __index = function(_, key) + error(("%q is not a valid member of Error.Kind"):format(tostring(key)), 2) + end, +}) + +function Error.new(kind, extra) + return setmetatable({ + kind = kind, + extra = extra, + }, Error) +end + +function Error:__tostring() + return ("Error(%s: %s)"):format(self.kind, tostring(self.extra)) +end + +return Error \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/PropertyDescriptor.lua b/plugin/rbx_dom_lua/src/PropertyDescriptor.lua new file mode 100644 index 00000000..d7fc577a --- /dev/null +++ b/plugin/rbx_dom_lua/src/PropertyDescriptor.lua @@ -0,0 +1,80 @@ +local Error = require(script.Parent.Error) +local customProperties = require(script.Parent.customProperties) + +-- A wrapper around a property descriptor from the reflection database with some +-- extra convenience methods. +-- +-- The aim of this API is to facilitate looking up a property once, then reading +-- from it or writing to it multiple times. It's also useful when a consumer +-- wants to check additional constraints on the property before trying to use +-- it, like scriptability. +local PropertyDescriptor = {} +PropertyDescriptor.__index = PropertyDescriptor + +local function get(container, key) + return container[key] +end + +local function set(container, key, value) + container[key] = value +end + +function PropertyDescriptor.fromRaw(data, className, propertyName) + return setmetatable({ + scriptability = data.scriptability, + className = className, + name = propertyName, + }, PropertyDescriptor) +end + +function PropertyDescriptor:read(instance) + if self.scriptability == "ReadWrite" or self.scriptability == "Read" then + local success, value = xpcall(get, debug.traceback, instance, self.name) + + if success then + return success, value + else + return false, Error.new(Error.Kind.Roblox, value) + end + end + + if self.scriptability == "Custom" then + local interface = customProperties[self.className][self.name] + + return interface.read(instance, self.name) + end + + if self.scriptability == "None" or self.scriptability == "Write" then + local fullName = ("%s.%s"):format(instance.className, self.name) + + return false, Error.new(Error.Kind.PropertyNotReadable, fullName) + end + + error(("Internal error: unexpected value of 'scriptability': %s"):format(tostring(self.scriptability)), 2) +end + +function PropertyDescriptor:write(instance, value) + if self.scriptability == "ReadWrite" or self.scriptability == "Write" then + local success, err = xpcall(set, debug.traceback, instance, self.name, value) + + if success then + return success + else + return false, Error.new(Error.Kind.Roblox, err) + end + end + + if self.scriptability == "Custom" then + local interface = customProperties[self.className][self.name] + + return interface.write(instance, self.name, value) + end + + if self.scriptability == "None" or self.scriptability == "Read" then + local fullName = ("%s.%s"):format(instance.className, self.name) + + return false, Error.new(Error.Kind.PropertyNotWritable, fullName) + end +end + +return PropertyDescriptor \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua b/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua new file mode 100644 index 00000000..93949b42 --- /dev/null +++ b/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua @@ -0,0 +1,18757 @@ +-- This file is automatically @generated. +return { + ABTestService = { + name = "ABTestService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "ABTestService", + }, + }, + Accessory = { + name = "Accessory", + superclass = "Accoutrement", + properties = { + }, + defaults = { + AttachmentForward = Vector3.new(0, 0, -1), + AttachmentPoint = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + AttachmentPos = Vector3.new(0, 0, 0), + AttachmentRight = Vector3.new(1, 0, 0), + AttachmentUp = Vector3.new(0, 1, 0), + Name = "Accessory", + }, + }, + Accoutrement = { + name = "Accoutrement", + superclass = "Instance", + properties = { + AttachmentForward = { + name = "AttachmentForward", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + AttachmentPoint = { + name = "AttachmentPoint", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AttachmentPos = { + name = "AttachmentPos", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + AttachmentRight = { + name = "AttachmentRight", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + AttachmentUp = { + name = "AttachmentUp", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + AttachmentForward = Vector3.new(0, 0, -1), + AttachmentPoint = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + AttachmentPos = Vector3.new(0, 0, 0), + AttachmentRight = Vector3.new(1, 0, 0), + AttachmentUp = Vector3.new(0, 1, 0), + Name = "Accoutrement", + }, + }, + AdService = { + name = "AdService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "AdService", + }, + }, + AdvancedDragger = { + name = "AdvancedDragger", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "AdvancedDragger", + }, + }, + AlignOrientation = { + name = "AlignOrientation", + superclass = "Constraint", + properties = { + AlignType = { + name = "AlignType", + type = {type = "Enum", name = "AlignType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxAngularVelocity = { + name = "MaxAngularVelocity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxTorque = { + name = "MaxTorque", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PrimaryAxisOnly = { + name = "PrimaryAxisOnly", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ReactionTorqueEnabled = { + name = "ReactionTorqueEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Responsiveness = { + name = "Responsiveness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RigidityEnabled = { + name = "RigidityEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + AlignType = 0, + Attachment0 = nil, + Attachment1 = nil, + Color = BrickColor.new(23), + Enabled = true, + MaxAngularVelocity = 1000000000, + MaxTorque = 10000, + Name = "AlignOrientation", + PrimaryAxisOnly = false, + ReactionTorqueEnabled = false, + Responsiveness = 10, + RigidityEnabled = false, + Visible = false, + }, + }, + AlignPosition = { + name = "AlignPosition", + superclass = "Constraint", + properties = { + ApplyAtCenterOfMass = { + name = "ApplyAtCenterOfMass", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxForce = { + name = "MaxForce", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxVelocity = { + name = "MaxVelocity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ReactionForceEnabled = { + name = "ReactionForceEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Responsiveness = { + name = "Responsiveness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RigidityEnabled = { + name = "RigidityEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + ApplyAtCenterOfMass = false, + Attachment0 = nil, + Attachment1 = nil, + Color = BrickColor.new(194), + Enabled = true, + MaxForce = 10000, + MaxVelocity = 1000000000, + Name = "AlignPosition", + ReactionForceEnabled = false, + Responsiveness = 10, + RigidityEnabled = false, + Visible = false, + }, + }, + AnalysticsSettings = { + name = "AnalysticsSettings", + superclass = "GenericSettings", + properties = { + }, + defaults = { + }, + }, + AnalyticsService = { + name = "AnalyticsService", + superclass = "Instance", + properties = { + ApiKey = { + name = "ApiKey", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "AnalyticsService", + }, + }, + AngularVelocity = { + name = "AngularVelocity", + superclass = "Constraint", + properties = { + AngularVelocity = { + name = "AngularVelocity", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxTorque = { + name = "MaxTorque", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RelativeTo = { + name = "RelativeTo", + type = {type = "Enum", name = "ActuatorRelativeTo"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + AngularVelocity = Vector3.new(0, 0, 0), + Attachment0 = nil, + Attachment1 = nil, + Color = BrickColor.new(23), + Enabled = true, + MaxTorque = 0, + Name = "AngularVelocity", + RelativeTo = 2, + Visible = false, + }, + }, + Animation = { + name = "Animation", + superclass = "Instance", + properties = { + AnimationId = { + name = "AnimationId", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + AnimationId = "", + Name = "Animation", + }, + }, + AnimationController = { + name = "AnimationController", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "AnimationController", + }, + }, + AnimationTrack = { + name = "AnimationTrack", + superclass = "Instance", + properties = { + Animation = { + name = "Animation", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsPlaying = { + name = "IsPlaying", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Length = { + name = "Length", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Looped = { + name = "Looped", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Priority = { + name = "Priority", + type = {type = "Enum", name = "AnimationPriority"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Speed = { + name = "Speed", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TimePosition = { + name = "TimePosition", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + WeightCurrent = { + name = "WeightCurrent", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + WeightTarget = { + name = "WeightTarget", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + Animator = { + name = "Animator", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Animator", + }, + }, + AppStorageService = { + name = "AppStorageService", + superclass = "LocalStorageService", + properties = { + }, + defaults = { + }, + }, + ArcHandles = { + name = "ArcHandles", + superclass = "HandlesBase", + properties = { + Axes = { + name = "Axes", + type = {type = "Unimplemented", name = "Axes"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Adornee = nil, + Color = BrickColor.new(23), + Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + Name = "ArcHandles", + Transparency = 0, + Visible = true, + }, + }, + AssetService = { + name = "AssetService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "AssetService", + }, + }, + Attachment = { + name = "Attachment", + superclass = "Instance", + properties = { + Axis = { + name = "Axis", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + CFrame = { + name = "CFrame", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Orientation = { + name = "Orientation", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Position = { + name = "Position", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Rotation = { + name = "Rotation", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + SecondaryAxis = { + name = "SecondaryAxis", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Visible = { + name = "Visible", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WorldAxis = { + name = "WorldAxis", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + WorldCFrame = { + name = "WorldCFrame", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + WorldOrientation = { + name = "WorldOrientation", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + WorldPosition = { + name = "WorldPosition", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + WorldRotation = { + name = "WorldRotation", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + WorldSecondaryAxis = { + name = "WorldSecondaryAxis", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + Axis = Vector3.new(1, 0, 0), + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Name = "Attachment", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + SecondaryAxis = Vector3.new(0, 1, 0), + Visible = false, + WorldAxis = Vector3.new(1, 0, 0), + WorldCFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + WorldOrientation = Vector3.new(0, 0, 0), + WorldPosition = Vector3.new(0, 0, 0), + WorldSecondaryAxis = Vector3.new(0, 1, 0), + }, + }, + Backpack = { + name = "Backpack", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Backpack", + }, + }, + BackpackItem = { + name = "BackpackItem", + superclass = "Instance", + properties = { + TextureId = { + name = "TextureId", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + BadgeService = { + name = "BadgeService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "BadgeService", + }, + }, + BallSocketConstraint = { + name = "BallSocketConstraint", + superclass = "Constraint", + properties = { + LimitsEnabled = { + name = "LimitsEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Radius = { + name = "Radius", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Restitution = { + name = "Restitution", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TwistLimitsEnabled = { + name = "TwistLimitsEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TwistLowerAngle = { + name = "TwistLowerAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TwistUpperAngle = { + name = "TwistUpperAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UpperAngle = { + name = "UpperAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Attachment0 = nil, + Attachment1 = nil, + Color = BrickColor.new(1009), + Enabled = true, + LimitsEnabled = false, + Name = "BallSocketConstraint", + Radius = 0.15, + Restitution = 0, + TwistLimitsEnabled = false, + TwistLowerAngle = -45, + TwistUpperAngle = 45, + UpperAngle = 45, + Visible = false, + }, + }, + BasePart = { + name = "BasePart", + superclass = "PVInstance", + properties = { + Anchored = { + name = "Anchored", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BackParamA = { + name = "BackParamA", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BackParamB = { + name = "BackParamB", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BackSurface = { + name = "BackSurface", + type = {type = "Enum", name = "SurfaceType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BackSurfaceInput = { + name = "BackSurfaceInput", + type = {type = "Enum", name = "InputType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BottomParamA = { + name = "BottomParamA", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BottomParamB = { + name = "BottomParamB", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BottomSurface = { + name = "BottomSurface", + type = {type = "Enum", name = "SurfaceType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BottomSurfaceInput = { + name = "BottomSurfaceInput", + type = {type = "Enum", name = "InputType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BrickColor = { + name = "BrickColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = false, + canonicalName = "Color", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + CFrame = { + name = "CFrame", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CanCollide = { + name = "CanCollide", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CastShadow = { + name = "CastShadow", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CenterOfMass = { + name = "CenterOfMass", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + CollisionGroupId = { + name = "CollisionGroupId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CollisionGroups = { + name = "CollisionGroups", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Custom", + serializes = true, + }, + Color = { + name = "Color", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = "Color3uint8", + scriptability = "ReadWrite", + serializes = true, + }, + Color3uint8 = { + name = "Color3uint8", + type = {type = "Data", name = "Color3uint8"}, + isCanonical = false, + canonicalName = "Color", + serializedName = nil, + scriptability = "None", + serializes = false, + }, + CustomPhysicalProperties = { + name = "CustomPhysicalProperties", + type = {type = "Data", name = "PhysicalProperties"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Elasticity = { + name = "Elasticity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Friction = { + name = "Friction", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + FrontParamA = { + name = "FrontParamA", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FrontParamB = { + name = "FrontParamB", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FrontSurface = { + name = "FrontSurface", + type = {type = "Enum", name = "SurfaceType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FrontSurfaceInput = { + name = "FrontSurfaceInput", + type = {type = "Enum", name = "InputType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LeftParamA = { + name = "LeftParamA", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LeftParamB = { + name = "LeftParamB", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LeftSurface = { + name = "LeftSurface", + type = {type = "Enum", name = "SurfaceType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LeftSurfaceInput = { + name = "LeftSurfaceInput", + type = {type = "Enum", name = "InputType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LocalTransparencyModifier = { + name = "LocalTransparencyModifier", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Locked = { + name = "Locked", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Massless = { + name = "Massless", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Material = { + name = "Material", + type = {type = "Enum", name = "Material"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Orientation = { + name = "Orientation", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Position = { + name = "Position", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + ReceiveAge = { + name = "ReceiveAge", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Reflectance = { + name = "Reflectance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ResizeIncrement = { + name = "ResizeIncrement", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ResizeableFaces = { + name = "ResizeableFaces", + type = {type = "Unimplemented", name = "Faces"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + RightParamA = { + name = "RightParamA", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RightParamB = { + name = "RightParamB", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RightSurface = { + name = "RightSurface", + type = {type = "Enum", name = "SurfaceType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RightSurfaceInput = { + name = "RightSurfaceInput", + type = {type = "Enum", name = "InputType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RootPriority = { + name = "RootPriority", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RotVelocity = { + name = "RotVelocity", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Rotation = { + name = "Rotation", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Size = { + name = "Size", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = "size", + scriptability = "ReadWrite", + serializes = true, + }, + SpecificGravity = { + name = "SpecificGravity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TopParamA = { + name = "TopParamA", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TopParamB = { + name = "TopParamB", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TopSurface = { + name = "TopSurface", + type = {type = "Enum", name = "SurfaceType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TopSurfaceInput = { + name = "TopSurfaceInput", + type = {type = "Enum", name = "InputType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Transparency = { + name = "Transparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Velocity = { + name = "Velocity", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + brickColor = { + name = "brickColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = false, + canonicalName = "Color", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + size = { + name = "size", + type = {type = "Data", name = "Vector3"}, + isCanonical = false, + canonicalName = "Size", + serializedName = nil, + scriptability = "None", + serializes = false, + }, + }, + defaults = { + }, + }, + BasePlayerGui = { + name = "BasePlayerGui", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + BaseScript = { + name = "BaseScript", + superclass = "LuaSourceContainer", + properties = { + Disabled = { + name = "Disabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LinkedSource = { + name = "LinkedSource", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + Beam = { + name = "Beam", + superclass = "Instance", + properties = { + Attachment0 = { + name = "Attachment0", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Attachment1 = { + name = "Attachment1", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Color = { + name = "Color", + type = {type = "Data", name = "ColorSequence"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CurveSize0 = { + name = "CurveSize0", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CurveSize1 = { + name = "CurveSize1", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FaceCamera = { + name = "FaceCamera", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LightEmission = { + name = "LightEmission", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LightInfluence = { + name = "LightInfluence", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Segments = { + name = "Segments", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Texture = { + name = "Texture", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextureLength = { + name = "TextureLength", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextureMode = { + name = "TextureMode", + type = {type = "Enum", name = "TextureMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextureSpeed = { + name = "TextureSpeed", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Transparency = { + name = "Transparency", + type = {type = "Data", name = "NumberSequence"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Width0 = { + name = "Width0", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Width1 = { + name = "Width1", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ZOffset = { + name = "ZOffset", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Attachment0 = nil, + Attachment1 = nil, + Color = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.new(1, 1, 1)), ColorSequenceKeypoint.new(1, Color3.new(1, 1, 1))}), + CurveSize0 = 0, + CurveSize1 = 0, + Enabled = true, + FaceCamera = false, + LightEmission = 0, + LightInfluence = 0, + Name = "Beam", + Segments = 10, + Texture = "", + TextureLength = 1, + TextureMode = 0, + TextureSpeed = 1, + Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 0.5, 0), NumberSequenceKeypoint.new(1, 0.5, 0)}), + Width0 = 1, + Width1 = 1, + ZOffset = 0, + }, + }, + BevelMesh = { + name = "BevelMesh", + superclass = "DataModelMesh", + properties = { + }, + defaults = { + }, + }, + BillboardGui = { + name = "BillboardGui", + superclass = "LayerCollector", + properties = { + Active = { + name = "Active", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Adornee = { + name = "Adornee", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AlwaysOnTop = { + name = "AlwaysOnTop", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ClipsDescendants = { + name = "ClipsDescendants", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CurrentDistance = { + name = "CurrentDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + DistanceLowerLimit = { + name = "DistanceLowerLimit", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DistanceStep = { + name = "DistanceStep", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DistanceUpperLimit = { + name = "DistanceUpperLimit", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ExtentsOffset = { + name = "ExtentsOffset", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ExtentsOffsetWorldSpace = { + name = "ExtentsOffsetWorldSpace", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LightInfluence = { + name = "LightInfluence", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxDistance = { + name = "MaxDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PlayerToHideFrom = { + name = "PlayerToHideFrom", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Size = { + name = "Size", + type = {type = "Data", name = "UDim2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SizeOffset = { + name = "SizeOffset", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + StudsOffset = { + name = "StudsOffset", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + StudsOffsetWorldSpace = { + name = "StudsOffsetWorldSpace", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Active = false, + Adornee = nil, + AlwaysOnTop = false, + AutoLocalize = true, + ClipsDescendants = false, + DistanceLowerLimit = 0, + DistanceStep = 0, + DistanceUpperLimit = -1, + Enabled = true, + ExtentsOffset = Vector3.new(0, 0, 0), + ExtentsOffsetWorldSpace = Vector3.new(0, 0, 0), + LightInfluence = 0, + Localize = true, + MaxDistance = 1000000000, + Name = "BillboardGui", + PlayerToHideFrom = nil, + ResetOnSpawn = true, + RootLocalizationTable = nil, + Size = UDim2.new(0, 0, 0, 0), + SizeOffset = Vector2.new(0, 0), + StudsOffset = Vector3.new(0, 0, 0), + StudsOffsetWorldSpace = Vector3.new(0, 0, 0), + ZIndexBehavior = 0, + }, + }, + BinaryStringValue = { + name = "BinaryStringValue", + superclass = "ValueBase", + properties = { + }, + defaults = { + Name = "Value", + }, + }, + BindableEvent = { + name = "BindableEvent", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Event", + }, + }, + BindableFunction = { + name = "BindableFunction", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Function", + }, + }, + BlockMesh = { + name = "BlockMesh", + superclass = "BevelMesh", + properties = { + }, + defaults = { + Name = "Mesh", + Offset = Vector3.new(0, 0, 0), + Scale = Vector3.new(1, 1, 1), + VertexColor = Vector3.new(1, 1, 1), + }, + }, + BloomEffect = { + name = "BloomEffect", + superclass = "PostEffect", + properties = { + Intensity = { + name = "Intensity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Size = { + name = "Size", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Threshold = { + name = "Threshold", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Enabled = true, + Intensity = 0.4, + Name = "Bloom", + Size = 24, + Threshold = 0.95, + }, + }, + BlurEffect = { + name = "BlurEffect", + superclass = "PostEffect", + properties = { + Size = { + name = "Size", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Enabled = true, + Name = "Blur", + Size = 24, + }, + }, + BodyAngularVelocity = { + name = "BodyAngularVelocity", + superclass = "BodyMover", + properties = { + AngularVelocity = { + name = "AngularVelocity", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxTorque = { + name = "MaxTorque", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + P = { + name = "P", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + angularvelocity = { + name = "angularvelocity", + type = {type = "Data", name = "Vector3"}, + isCanonical = false, + canonicalName = "AngularVelocity", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + maxTorque = { + name = "maxTorque", + type = {type = "Data", name = "Vector3"}, + isCanonical = false, + canonicalName = "MaxTorque", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + AngularVelocity = Vector3.new(0, 2, 0), + MaxTorque = Vector3.new(4000, 4000, 4000), + Name = "BodyAngularVelocity", + P = 1250, + }, + }, + BodyColors = { + name = "BodyColors", + superclass = "CharacterAppearance", + properties = { + HeadColor = { + name = "HeadColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + HeadColor3 = { + name = "HeadColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LeftArmColor = { + name = "LeftArmColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + LeftArmColor3 = { + name = "LeftArmColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LeftLegColor = { + name = "LeftLegColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + LeftLegColor3 = { + name = "LeftLegColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RightArmColor = { + name = "RightArmColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + RightArmColor3 = { + name = "RightArmColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RightLegColor = { + name = "RightLegColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + RightLegColor3 = { + name = "RightLegColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TorsoColor = { + name = "TorsoColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + TorsoColor3 = { + name = "TorsoColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + HeadColor = BrickColor.new(226), + HeadColor3 = Color3.new(0.9921569, 0.9176471, 0.5529412), + LeftArmColor = BrickColor.new(226), + LeftArmColor3 = Color3.new(0.9921569, 0.9176471, 0.5529412), + LeftLegColor = BrickColor.new(23), + LeftLegColor3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + Name = "Body Colors", + RightArmColor = BrickColor.new(226), + RightArmColor3 = Color3.new(0.9921569, 0.9176471, 0.5529412), + RightLegColor = BrickColor.new(23), + RightLegColor3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + TorsoColor = BrickColor.new(28), + TorsoColor3 = Color3.new(0.15686275, 0.49803925, 0.2784314), + }, + }, + BodyForce = { + name = "BodyForce", + superclass = "BodyMover", + properties = { + Force = { + name = "Force", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + force = { + name = "force", + type = {type = "Data", name = "Vector3"}, + isCanonical = false, + canonicalName = "Force", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + Force = Vector3.new(0, 1, 0), + Name = "BodyForce", + }, + }, + BodyGyro = { + name = "BodyGyro", + superclass = "BodyMover", + properties = { + CFrame = { + name = "CFrame", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + D = { + name = "D", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxTorque = { + name = "MaxTorque", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + P = { + name = "P", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + cframe = { + name = "cframe", + type = {type = "Data", name = "CFrame"}, + isCanonical = false, + canonicalName = "CFrame", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + maxTorque = { + name = "maxTorque", + type = {type = "Data", name = "Vector3"}, + isCanonical = false, + canonicalName = "MaxTorque", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + D = 500, + MaxTorque = Vector3.new(400000, 0, 400000), + Name = "BodyGyro", + P = 3000, + }, + }, + BodyMover = { + name = "BodyMover", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + BodyPosition = { + name = "BodyPosition", + superclass = "BodyMover", + properties = { + D = { + name = "D", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxForce = { + name = "MaxForce", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + P = { + name = "P", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Position = { + name = "Position", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + maxForce = { + name = "maxForce", + type = {type = "Data", name = "Vector3"}, + isCanonical = false, + canonicalName = "MaxForce", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + position = { + name = "position", + type = {type = "Data", name = "Vector3"}, + isCanonical = false, + canonicalName = "Position", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + D = 1250, + MaxForce = Vector3.new(4000, 4000, 4000), + Name = "BodyPosition", + P = 10000, + Position = Vector3.new(0, 50, 0), + }, + }, + BodyThrust = { + name = "BodyThrust", + superclass = "BodyMover", + properties = { + Force = { + name = "Force", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Location = { + name = "Location", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + force = { + name = "force", + type = {type = "Data", name = "Vector3"}, + isCanonical = false, + canonicalName = "Force", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + location = { + name = "location", + type = {type = "Data", name = "Vector3"}, + isCanonical = false, + canonicalName = "Location", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + Force = Vector3.new(0, 1, 0), + Location = Vector3.new(0, 0, 0), + Name = "BodyThrust", + }, + }, + BodyVelocity = { + name = "BodyVelocity", + superclass = "BodyMover", + properties = { + MaxForce = { + name = "MaxForce", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + P = { + name = "P", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Velocity = { + name = "Velocity", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + maxForce = { + name = "maxForce", + type = {type = "Data", name = "Vector3"}, + isCanonical = false, + canonicalName = "MaxForce", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + velocity = { + name = "velocity", + type = {type = "Data", name = "Vector3"}, + isCanonical = false, + canonicalName = "Velocity", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + MaxForce = Vector3.new(4000, 4000, 4000), + Name = "BodyVelocity", + P = 1250, + Velocity = Vector3.new(0, 2, 0), + }, + }, + BoolValue = { + name = "BoolValue", + superclass = "ValueBase", + properties = { + Value = { + name = "Value", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Value", + Value = false, + }, + }, + BoxHandleAdornment = { + name = "BoxHandleAdornment", + superclass = "HandleAdornment", + properties = { + Size = { + name = "Size", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Adornee = nil, + AlwaysOnTop = false, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Color = BrickColor.new(23), + Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + Name = "BoxHandleAdornment", + Size = Vector3.new(1, 1, 1), + SizeRelativeOffset = Vector3.new(0, 0, 0), + Transparency = 0, + Visible = true, + ZIndex = -1, + }, + }, + BrickColorValue = { + name = "BrickColorValue", + superclass = "ValueBase", + properties = { + Value = { + name = "Value", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Value", + Value = BrickColor.new(194), + }, + }, + BrowserService = { + name = "BrowserService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + CFrameValue = { + name = "CFrameValue", + superclass = "ValueBase", + properties = { + Value = { + name = "Value", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Value", + Value = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + }, + }, + CSGDictionaryService = { + name = "CSGDictionaryService", + superclass = "FlyweightService", + properties = { + }, + defaults = { + }, + }, + CacheableContentProvider = { + name = "CacheableContentProvider", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + Camera = { + name = "Camera", + superclass = "Instance", + properties = { + CFrame = { + name = "CFrame", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CameraSubject = { + name = "CameraSubject", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CameraType = { + name = "CameraType", + type = {type = "Enum", name = "CameraType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CoordinateFrame = { + name = "CoordinateFrame", + type = {type = "Data", name = "CFrame"}, + isCanonical = false, + canonicalName = "CFrame", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + FieldOfView = { + name = "FieldOfView", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Focus = { + name = "Focus", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HeadLocked = { + name = "HeadLocked", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HeadScale = { + name = "HeadScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NearPlaneZ = { + name = "NearPlaneZ", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ViewportSize = { + name = "ViewportSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + focus = { + name = "focus", + type = {type = "Data", name = "CFrame"}, + isCanonical = false, + canonicalName = "Focus", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + CFrame = CFrame.new(0, 20, 20, 1, 0, 0, 0, 0.7071068, 0.7071068, 0, -0.7071068, 0.7071068), + CameraSubject = nil, + CameraType = 0, + FieldOfView = 70, + Focus = CFrame.new(0, 0, -5, 1, 0, 0, 0, 1, 0, 0, 0, 1), + HeadLocked = true, + HeadScale = 1, + Name = "Camera", + }, + }, + ChangeHistoryService = { + name = "ChangeHistoryService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "ChangeHistoryService", + }, + }, + CharacterAppearance = { + name = "CharacterAppearance", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + CharacterMesh = { + name = "CharacterMesh", + superclass = "CharacterAppearance", + properties = { + BaseTextureId = { + name = "BaseTextureId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BodyPart = { + name = "BodyPart", + type = {type = "Enum", name = "BodyPart"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MeshId = { + name = "MeshId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + OverlayTextureId = { + name = "OverlayTextureId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + BaseTextureId = 0, + BodyPart = 0, + MeshId = 0, + Name = "CharacterMesh", + OverlayTextureId = 0, + }, + }, + Chat = { + name = "Chat", + superclass = "Instance", + properties = { + BubbleChatEnabled = { + name = "BubbleChatEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LoadDefaultChat = { + name = "LoadDefaultChat", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = true, + }, + }, + defaults = { + BubbleChatEnabled = false, + LoadDefaultChat = true, + Name = "Chat", + }, + }, + ChorusSoundEffect = { + name = "ChorusSoundEffect", + superclass = "SoundEffect", + properties = { + Depth = { + name = "Depth", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Mix = { + name = "Mix", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Rate = { + name = "Rate", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Depth = 0.15, + Enabled = true, + Mix = 0.5, + Name = "ChorusSoundEffect", + Priority = 0, + Rate = 0.5, + }, + }, + ClickDetector = { + name = "ClickDetector", + superclass = "Instance", + properties = { + CursorIcon = { + name = "CursorIcon", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxActivationDistance = { + name = "MaxActivationDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + CursorIcon = "", + MaxActivationDistance = 32, + Name = "ClickDetector", + }, + }, + ClientReplicator = { + name = "ClientReplicator", + superclass = "NetworkReplicator", + properties = { + }, + defaults = { + }, + }, + Clothing = { + name = "Clothing", + superclass = "CharacterAppearance", + properties = { + Color3 = { + name = "Color3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + ClusterPacketCache = { + name = "ClusterPacketCache", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + CollectionService = { + name = "CollectionService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "CollectionService", + }, + }, + Color3Value = { + name = "Color3Value", + superclass = "ValueBase", + properties = { + Value = { + name = "Value", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Value", + Value = Color3.new(0, 0, 0), + }, + }, + ColorCorrectionEffect = { + name = "ColorCorrectionEffect", + superclass = "PostEffect", + properties = { + Brightness = { + name = "Brightness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Contrast = { + name = "Contrast", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Saturation = { + name = "Saturation", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TintColor = { + name = "TintColor", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Brightness = 0, + Contrast = 0, + Enabled = true, + Name = "ColorCorrection", + Saturation = 0, + TintColor = Color3.new(1, 1, 1), + }, + }, + CompressorSoundEffect = { + name = "CompressorSoundEffect", + superclass = "SoundEffect", + properties = { + Attack = { + name = "Attack", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GainMakeup = { + name = "GainMakeup", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Ratio = { + name = "Ratio", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Release = { + name = "Release", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SideChain = { + name = "SideChain", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Threshold = { + name = "Threshold", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Attack = 0.1, + Enabled = true, + GainMakeup = 0, + Name = "CompressorSoundEffect", + Priority = 0, + Ratio = 40, + Release = 0.1, + SideChain = nil, + Threshold = -40, + }, + }, + ConeHandleAdornment = { + name = "ConeHandleAdornment", + superclass = "HandleAdornment", + properties = { + Height = { + name = "Height", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Radius = { + name = "Radius", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Adornee = nil, + AlwaysOnTop = false, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Color = BrickColor.new(23), + Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + Height = 2, + Name = "ConeHandleAdornment", + Radius = 0.5, + SizeRelativeOffset = Vector3.new(0, 0, 0), + Transparency = 0, + Visible = true, + ZIndex = -1, + }, + }, + Configuration = { + name = "Configuration", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Configuration", + }, + }, + Constraint = { + name = "Constraint", + superclass = "Instance", + properties = { + Active = { + name = "Active", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Attachment0 = { + name = "Attachment0", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Attachment1 = { + name = "Attachment1", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Color = { + name = "Color", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Visible = { + name = "Visible", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + ContentProvider = { + name = "ContentProvider", + superclass = "Instance", + properties = { + BaseUrl = { + name = "BaseUrl", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + RequestQueueSize = { + name = "RequestQueueSize", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + Name = "ContentProvider", + }, + }, + ContextActionService = { + name = "ContextActionService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "ContextActionService", + }, + }, + Controller = { + name = "Controller", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + ControllerService = { + name = "ControllerService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + CookiesService = { + name = "CookiesService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "CookiesService", + }, + }, + CoreGui = { + name = "CoreGui", + superclass = "BasePlayerGui", + properties = { + SelectionImageObject = { + name = "SelectionImageObject", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Version = { + name = "Version", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + Name = "CoreGui", + SelectionImageObject = nil, + }, + }, + CorePackages = { + name = "CorePackages", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "CorePackages", + }, + }, + CoreScript = { + name = "CoreScript", + superclass = "BaseScript", + properties = { + }, + defaults = { + }, + }, + CoreScriptSyncService = { + name = "CoreScriptSyncService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + CornerWedgePart = { + name = "CornerWedgePart", + superclass = "BasePart", + properties = { + }, + defaults = { + Anchored = false, + BackParamA = -0.5, + BackParamB = 0.5, + BackSurface = 0, + BackSurfaceInput = 0, + BottomParamA = -0.5, + BottomParamB = 0.5, + BottomSurface = 0, + BottomSurfaceInput = 0, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CanCollide = true, + CastShadow = true, + CollisionGroupId = 0, + Color = Color3.new(0.6392157, 0.63529414, 0.64705884), + CustomPhysicalProperties = nil, + Elasticity = 0.5, + Friction = 0.3, + FrontParamA = -0.5, + FrontParamB = 0.5, + FrontSurface = 0, + FrontSurfaceInput = 0, + LeftParamA = -0.5, + LeftParamB = 0.5, + LeftSurface = 0, + LeftSurfaceInput = 0, + LocalTransparencyModifier = 0, + Locked = false, + Massless = false, + Material = 256, + Name = "CornerWedge", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Reflectance = 0, + RightParamA = -0.5, + RightParamB = 0.5, + RightSurface = 0, + RightSurfaceInput = 0, + RootPriority = 0, + RotVelocity = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + Size = Vector3.new(2, 2, 2), + TopParamA = -0.5, + TopParamB = 0.5, + TopSurface = 0, + TopSurfaceInput = 0, + Transparency = 0, + Velocity = Vector3.new(0, 0, 0), + }, + }, + CustomEvent = { + name = "CustomEvent", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "CustomEvent", + }, + }, + CustomEventReceiver = { + name = "CustomEventReceiver", + superclass = "Instance", + properties = { + Source = { + name = "Source", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "CustomEventReceiver", + Source = nil, + }, + }, + CylinderHandleAdornment = { + name = "CylinderHandleAdornment", + superclass = "HandleAdornment", + properties = { + Height = { + name = "Height", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Radius = { + name = "Radius", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Adornee = nil, + AlwaysOnTop = false, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Color = BrickColor.new(23), + Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + Height = 1, + Name = "CylinderHandleAdornment", + Radius = 1, + SizeRelativeOffset = Vector3.new(0, 0, 0), + Transparency = 0, + Visible = true, + ZIndex = -1, + }, + }, + CylinderMesh = { + name = "CylinderMesh", + superclass = "BevelMesh", + properties = { + }, + defaults = { + Name = "Mesh", + Offset = Vector3.new(0, 0, 0), + Scale = Vector3.new(1, 1, 1), + VertexColor = Vector3.new(1, 1, 1), + }, + }, + CylindricalConstraint = { + name = "CylindricalConstraint", + superclass = "SlidingBallConstraint", + properties = { + AngularActuatorType = { + name = "AngularActuatorType", + type = {type = "Enum", name = "ActuatorType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AngularLimitsEnabled = { + name = "AngularLimitsEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AngularRestitution = { + name = "AngularRestitution", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AngularSpeed = { + name = "AngularSpeed", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AngularVelocity = { + name = "AngularVelocity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CurrentAngle = { + name = "CurrentAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + InclinationAngle = { + name = "InclinationAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LowerAngle = { + name = "LowerAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MotorMaxAngularAcceleration = { + name = "MotorMaxAngularAcceleration", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MotorMaxTorque = { + name = "MotorMaxTorque", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RotationAxisVisible = { + name = "RotationAxisVisible", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ServoMaxTorque = { + name = "ServoMaxTorque", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TargetAngle = { + name = "TargetAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UpperAngle = { + name = "UpperAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WorldRotationAxis = { + name = "WorldRotationAxis", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + ActuatorType = 0, + AngularActuatorType = 0, + AngularLimitsEnabled = false, + AngularRestitution = 0, + AngularSpeed = 0, + AngularVelocity = 0, + Attachment0 = nil, + Attachment1 = nil, + Color = BrickColor.new(1009), + Enabled = true, + InclinationAngle = 0, + LimitsEnabled = false, + LowerAngle = -45, + LowerLimit = 0, + MotorMaxAcceleration = 1000000000, + MotorMaxAngularAcceleration = 1000000000, + MotorMaxForce = 0, + MotorMaxTorque = 0, + Name = "CylindricalConstraint", + Restitution = 0, + RotationAxisVisible = false, + ServoMaxForce = 0, + ServoMaxTorque = 0, + Size = 0.15, + Speed = 0, + TargetAngle = 0, + TargetPosition = 0, + UpperAngle = 45, + UpperLimit = 5, + Velocity = 0, + Visible = false, + }, + }, + DataModel = { + name = "DataModel", + superclass = "ServiceProvider", + properties = { + CreatorId = { + name = "CreatorId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + CreatorType = { + name = "CreatorType", + type = {type = "Enum", name = "CreatorType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + GameId = { + name = "GameId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + GearGenreSetting = { + name = "GearGenreSetting", + type = {type = "Enum", name = "GearGenreSetting"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Genre = { + name = "Genre", + type = {type = "Enum", name = "Genre"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsSFFlagsLoaded = { + name = "IsSFFlagsLoaded", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + JobId = { + name = "JobId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + PlaceId = { + name = "PlaceId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + PlaceVersion = { + name = "PlaceVersion", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + PrivateServerId = { + name = "PrivateServerId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + PrivateServerOwnerId = { + name = "PrivateServerOwnerId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + VIPServerId = { + name = "VIPServerId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + VIPServerOwnerId = { + name = "VIPServerOwnerId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Workspace = { + name = "Workspace", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + lighting = { + name = "lighting", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + workspace = { + name = "workspace", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + DataModelMesh = { + name = "DataModelMesh", + superclass = "Instance", + properties = { + Offset = { + name = "Offset", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Scale = { + name = "Scale", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + VertexColor = { + name = "VertexColor", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + DataModelSession = { + name = "DataModelSession", + superclass = "Instance", + properties = { + CurrentDataModelType = { + name = "CurrentDataModelType", + type = {type = "Enum", name = "StudioDataModelType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + SessionId = { + name = "SessionId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + DataStorePages = { + name = "DataStorePages", + superclass = "Pages", + properties = { + }, + defaults = { + }, + }, + DataStoreService = { + name = "DataStoreService", + superclass = "Instance", + properties = { + AutomaticRetry = { + name = "AutomaticRetry", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LegacyNamingScheme = { + name = "LegacyNamingScheme", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "DataStoreService", + }, + }, + Debris = { + name = "Debris", + superclass = "Instance", + properties = { + MaxItems = { + name = "MaxItems", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = true, + }, + }, + defaults = { + MaxItems = 1000, + Name = "Debris", + }, + }, + DebugSettings = { + name = "DebugSettings", + superclass = "Instance", + properties = { + DataModel = { + name = "DataModel", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ErrorReporting = { + name = "ErrorReporting", + type = {type = "Enum", name = "ErrorReporting"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GfxCard = { + name = "GfxCard", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + InstanceCount = { + name = "InstanceCount", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsFmodProfilingEnabled = { + name = "IsFmodProfilingEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsScriptStackTracingEnabled = { + name = "IsScriptStackTracingEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + JobCount = { + name = "JobCount", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + OsIs64Bit = { + name = "OsIs64Bit", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + OsPlatform = { + name = "OsPlatform", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + OsPlatformId = { + name = "OsPlatformId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + OsVer = { + name = "OsVer", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + PlayerCount = { + name = "PlayerCount", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ReportSoundWarnings = { + name = "ReportSoundWarnings", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RobloxProductName = { + name = "RobloxProductName", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + RobloxVersion = { + name = "RobloxVersion", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + SIMD = { + name = "SIMD", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + SystemProductName = { + name = "SystemProductName", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TickCountPreciseOverride = { + name = "TickCountPreciseOverride", + type = {type = "Enum", name = "TickCountSampleMethod"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + VideoMemory = { + name = "VideoMemory", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + DebuggerBreakpoint = { + name = "DebuggerBreakpoint", + superclass = "Instance", + properties = { + Condition = { + name = "Condition", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsEnabled = { + name = "IsEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Line = { + name = "Line", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + DebuggerManager = { + name = "DebuggerManager", + superclass = "Instance", + properties = { + DebuggingEnabled = { + name = "DebuggingEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + DebuggerWatch = { + name = "DebuggerWatch", + superclass = "Instance", + properties = { + Expression = { + name = "Expression", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + Decal = { + name = "Decal", + superclass = "FaceInstance", + properties = { + Color3 = { + name = "Color3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LocalTransparencyModifier = { + name = "LocalTransparencyModifier", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Shiny = { + name = "Shiny", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Specular = { + name = "Specular", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Texture = { + name = "Texture", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Transparency = { + name = "Transparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Color3 = Color3.new(1, 1, 1), + Face = 5, + LocalTransparencyModifier = 0, + Name = "Decal", + Shiny = 20, + Specular = 0, + Texture = "", + Transparency = 0, + }, + }, + Dialog = { + name = "Dialog", + superclass = "Instance", + properties = { + BehaviorType = { + name = "BehaviorType", + type = {type = "Enum", name = "DialogBehaviorType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ConversationDistance = { + name = "ConversationDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GoodbyeChoiceActive = { + name = "GoodbyeChoiceActive", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GoodbyeDialog = { + name = "GoodbyeDialog", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + InUse = { + name = "InUse", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + InitialPrompt = { + name = "InitialPrompt", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Purpose = { + name = "Purpose", + type = {type = "Enum", name = "DialogPurpose"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Tone = { + name = "Tone", + type = {type = "Enum", name = "DialogTone"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TriggerDistance = { + name = "TriggerDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TriggerOffset = { + name = "TriggerOffset", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + BehaviorType = 0, + ConversationDistance = 25, + GoodbyeChoiceActive = true, + GoodbyeDialog = "", + InUse = false, + InitialPrompt = "", + Name = "Dialog", + Purpose = 1, + Tone = 0, + TriggerDistance = 0, + TriggerOffset = Vector3.new(0, 0, 0), + }, + }, + DialogChoice = { + name = "DialogChoice", + superclass = "Instance", + properties = { + GoodbyeChoiceActive = { + name = "GoodbyeChoiceActive", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GoodbyeDialog = { + name = "GoodbyeDialog", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ResponseDialog = { + name = "ResponseDialog", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UserDialog = { + name = "UserDialog", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + GoodbyeChoiceActive = true, + GoodbyeDialog = "", + Name = "DialogChoice", + ResponseDialog = "", + UserDialog = "", + }, + }, + DistortionSoundEffect = { + name = "DistortionSoundEffect", + superclass = "SoundEffect", + properties = { + Level = { + name = "Level", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Enabled = true, + Level = 0.75, + Name = "DistortionSoundEffect", + Priority = 0, + }, + }, + DockWidgetPluginGui = { + name = "DockWidgetPluginGui", + superclass = "PluginGui", + properties = { + HostWidgetWasRestored = { + name = "HostWidgetWasRestored", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + DoubleConstrainedValue = { + name = "DoubleConstrainedValue", + superclass = "ValueBase", + properties = { + ConstrainedValue = { + name = "ConstrainedValue", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + MaxValue = { + name = "MaxValue", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MinValue = { + name = "MinValue", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Value = { + name = "Value", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + ConstrainedValue = 0, + MaxValue = 1, + MinValue = 0, + Name = "Value", + Value = 0, + }, + }, + DraftsService = { + name = "DraftsService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "DraftsService", + }, + }, + Dragger = { + name = "Dragger", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Dragger", + }, + }, + DynamicRotate = { + name = "DynamicRotate", + superclass = "JointInstance", + properties = { + BaseAngle = { + name = "BaseAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + EchoSoundEffect = { + name = "EchoSoundEffect", + superclass = "SoundEffect", + properties = { + Delay = { + name = "Delay", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DryLevel = { + name = "DryLevel", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Feedback = { + name = "Feedback", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WetLevel = { + name = "WetLevel", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Delay = 1, + DryLevel = 0, + Enabled = true, + Feedback = 0.5, + Name = "EchoSoundEffect", + Priority = 0, + WetLevel = 0, + }, + }, + EmotesPages = { + name = "EmotesPages", + superclass = "InventoryPages", + properties = { + }, + defaults = { + }, + }, + EqualizerSoundEffect = { + name = "EqualizerSoundEffect", + superclass = "SoundEffect", + properties = { + HighGain = { + name = "HighGain", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LowGain = { + name = "LowGain", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MidGain = { + name = "MidGain", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Enabled = true, + HighGain = 0, + LowGain = -20, + MidGain = -10, + Name = "EqualizerSoundEffect", + Priority = 0, + }, + }, + Explosion = { + name = "Explosion", + superclass = "Instance", + properties = { + BlastPressure = { + name = "BlastPressure", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BlastRadius = { + name = "BlastRadius", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DestroyJointRadiusPercent = { + name = "DestroyJointRadiusPercent", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ExplosionType = { + name = "ExplosionType", + type = {type = "Enum", name = "ExplosionType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Position = { + name = "Position", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Visible = { + name = "Visible", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + BlastPressure = 500000, + BlastRadius = 4, + DestroyJointRadiusPercent = 1, + ExplosionType = 1, + Name = "Explosion", + Position = Vector3.new(0, 0, 0), + Visible = true, + }, + }, + FaceInstance = { + name = "FaceInstance", + superclass = "Instance", + properties = { + Face = { + name = "Face", + type = {type = "Enum", name = "NormalId"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + Feature = { + name = "Feature", + superclass = "Instance", + properties = { + FaceId = { + name = "FaceId", + type = {type = "Enum", name = "NormalId"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + InOut = { + name = "InOut", + type = {type = "Enum", name = "InOut"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LeftRight = { + name = "LeftRight", + type = {type = "Enum", name = "LeftRight"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TopBottom = { + name = "TopBottom", + type = {type = "Enum", name = "TopBottom"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + File = { + name = "File", + superclass = "Instance", + properties = { + FileName = { + name = "FileName", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + FileSize = { + name = "FileSize", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Size = { + name = "Size", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + FileMesh = { + name = "FileMesh", + superclass = "DataModelMesh", + properties = { + MeshId = { + name = "MeshId", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextureId = { + name = "TextureId", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + MeshId = "", + Name = "Mesh", + Offset = Vector3.new(0, 0, 0), + Scale = Vector3.new(1, 1, 1), + TextureId = "", + VertexColor = Vector3.new(1, 1, 1), + }, + }, + Fire = { + name = "Fire", + superclass = "Instance", + properties = { + Color = { + name = "Color", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Heat = { + name = "Heat", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = "heat_xml", + scriptability = "ReadWrite", + serializes = true, + }, + SecondaryColor = { + name = "SecondaryColor", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Size = { + name = "Size", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = "size_xml", + scriptability = "ReadWrite", + serializes = true, + }, + heat_xml = { + name = "heat_xml", + type = {type = "Data", name = "Float32"}, + isCanonical = false, + canonicalName = "Heat", + serializedName = nil, + scriptability = "None", + serializes = false, + }, + size = { + name = "size", + type = {type = "Data", name = "Float32"}, + isCanonical = false, + canonicalName = "Size", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + size_xml = { + name = "size_xml", + type = {type = "Data", name = "Float32"}, + isCanonical = false, + canonicalName = "Size", + serializedName = nil, + scriptability = "None", + serializes = false, + }, + }, + defaults = { + Color = Color3.new(0.92549026, 0.54509807, 0.27450982), + Enabled = true, + Heat = 9, + Name = "Fire", + SecondaryColor = Color3.new(0.54509807, 0.3137255, 0.21568629), + Size = 5, + }, + }, + Flag = { + name = "Flag", + superclass = "Tool", + properties = { + TeamColor = { + name = "TeamColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + CanBeDropped = true, + Enabled = true, + Grip = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + GripForward = Vector3.new(0, 0, -1), + GripPos = Vector3.new(0, 0, 0), + GripRight = Vector3.new(1, 0, 0), + GripUp = Vector3.new(0, 1, 0), + ManualActivationOnly = false, + Name = "Flag", + RequiresHandle = true, + TeamColor = BrickColor.new(194), + TextureId = "", + ToolTip = "", + }, + }, + FlagStand = { + name = "FlagStand", + superclass = "Part", + properties = { + TeamColor = { + name = "TeamColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Anchored = false, + BackParamA = -0.5, + BackParamB = 0.5, + BackSurface = 0, + BackSurfaceInput = 0, + BottomParamA = -0.5, + BottomParamB = 0.5, + BottomSurface = 4, + BottomSurfaceInput = 0, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CanCollide = true, + CastShadow = true, + CollisionGroupId = 0, + Color = Color3.new(0.6392157, 0.63529414, 0.64705884), + CustomPhysicalProperties = nil, + Elasticity = 0.5, + FormFactor = 1, + Friction = 0.3, + FrontParamA = -0.5, + FrontParamB = 0.5, + FrontSurface = 0, + FrontSurfaceInput = 0, + LeftParamA = -0.5, + LeftParamB = 0.5, + LeftSurface = 0, + LeftSurfaceInput = 0, + LocalTransparencyModifier = 0, + Locked = false, + Massless = false, + Material = 256, + Name = "FlagStand", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Reflectance = 0, + RightParamA = -0.5, + RightParamB = 0.5, + RightSurface = 0, + RightSurfaceInput = 0, + RootPriority = 0, + RotVelocity = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + Shape = 1, + Size = Vector3.new(4, 1.2, 2), + TeamColor = BrickColor.new(194), + TopParamA = -0.5, + TopParamB = 0.5, + TopSurface = 3, + TopSurfaceInput = 0, + Transparency = 0, + Velocity = Vector3.new(0, 0, 0), + }, + }, + FlagStandService = { + name = "FlagStandService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + FlangeSoundEffect = { + name = "FlangeSoundEffect", + superclass = "SoundEffect", + properties = { + Depth = { + name = "Depth", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Mix = { + name = "Mix", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Rate = { + name = "Rate", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Depth = 0.45, + Enabled = true, + Mix = 0.85, + Name = "FlangeSoundEffect", + Priority = 0, + Rate = 5, + }, + }, + FloorWire = { + name = "FloorWire", + superclass = "GuiBase3d", + properties = { + CycleOffset = { + name = "CycleOffset", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + From = { + name = "From", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + StudsBetweenTextures = { + name = "StudsBetweenTextures", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Texture = { + name = "Texture", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextureSize = { + name = "TextureSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + To = { + name = "To", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Velocity = { + name = "Velocity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WireRadius = { + name = "WireRadius", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Color = BrickColor.new(23), + Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + CycleOffset = 0, + From = nil, + Name = "FloorWire", + StudsBetweenTextures = 4, + Texture = "", + TextureSize = Vector2.new(1, 1), + To = nil, + Transparency = 0, + Velocity = 2, + Visible = true, + WireRadius = 0.0625, + }, + }, + FlyweightService = { + name = "FlyweightService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + Folder = { + name = "Folder", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Folder", + }, + }, + ForceField = { + name = "ForceField", + superclass = "Instance", + properties = { + Visible = { + name = "Visible", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "ForceField", + Visible = true, + }, + }, + FormFactorPart = { + name = "FormFactorPart", + superclass = "BasePart", + properties = { + FormFactor = { + name = "FormFactor", + type = {type = "Enum", name = "FormFactor"}, + isCanonical = true, + canonicalName = nil, + serializedName = "formFactorRaw", + scriptability = "ReadWrite", + serializes = true, + }, + formFactor = { + name = "formFactor", + type = {type = "Enum", name = "FormFactor"}, + isCanonical = false, + canonicalName = "FormFactor", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + formFactorRaw = { + name = "formFactorRaw", + type = {type = "Enum", name = "FormFactor"}, + isCanonical = false, + canonicalName = "FormFactor", + serializedName = nil, + scriptability = "None", + serializes = false, + }, + }, + defaults = { + }, + }, + Frame = { + name = "Frame", + superclass = "GuiObject", + properties = { + Style = { + name = "Style", + type = {type = "Enum", name = "FrameStyle"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Active = false, + AnchorPoint = Vector2.new(0, 0), + AutoLocalize = true, + BackgroundColor = BrickColor.new(194), + BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), + BackgroundTransparency = 0, + BorderColor = BrickColor.new(26), + BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), + BorderMode = 0, + BorderSizePixel = 1, + ClipsDescendants = false, + Draggable = false, + LayoutOrder = 0, + Localize = true, + Name = "Frame", + NextSelectionDown = nil, + NextSelectionLeft = nil, + NextSelectionRight = nil, + NextSelectionUp = nil, + Position = UDim2.new(0, 0, 0, 0), + RootLocalizationTable = nil, + Rotation = 0, + Selectable = false, + SelectionImageObject = nil, + Size = UDim2.new(0, 0, 0, 0), + SizeConstraint = 0, + Style = 0, + Transparency = 0, + Visible = true, + ZIndex = 1, + }, + }, + FriendPages = { + name = "FriendPages", + superclass = "Pages", + properties = { + }, + defaults = { + }, + }, + FriendService = { + name = "FriendService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "FriendService", + }, + }, + FunctionalTest = { + name = "FunctionalTest", + superclass = "Instance", + properties = { + Description = { + name = "Description", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Description = "?", + Name = "Instance", + }, + }, + GamePassService = { + name = "GamePassService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "GamePassService", + }, + }, + GameSettings = { + name = "GameSettings", + superclass = "Instance", + properties = { + AdditionalCoreIncludeDirs = { + name = "AdditionalCoreIncludeDirs", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BubbleChatLifetime = { + name = "BubbleChatLifetime", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BubbleChatMaxBubbles = { + name = "BubbleChatMaxBubbles", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ChatHistory = { + name = "ChatHistory", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ChatScrollLength = { + name = "ChatScrollLength", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CollisionSoundEnabled = { + name = "CollisionSoundEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + CollisionSoundVolume = { + name = "CollisionSoundVolume", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + HardwareMouse = { + name = "HardwareMouse", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxCollisionSounds = { + name = "MaxCollisionSounds", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + OverrideStarterScript = { + name = "OverrideStarterScript", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ReportAbuseChatHistory = { + name = "ReportAbuseChatHistory", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SoftwareSound = { + name = "SoftwareSound", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + VideoCaptureEnabled = { + name = "VideoCaptureEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + VideoQuality = { + name = "VideoQuality", + type = {type = "Enum", name = "VideoQualitySettings"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + GamepadService = { + name = "GamepadService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "GamepadService", + }, + }, + GenericSettings = { + name = "GenericSettings", + superclass = "ServiceProvider", + properties = { + }, + defaults = { + }, + }, + Geometry = { + name = "Geometry", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Geometry", + }, + }, + GlobalDataStore = { + name = "GlobalDataStore", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + GlobalSettings = { + name = "GlobalSettings", + superclass = "GenericSettings", + properties = { + }, + defaults = { + }, + }, + Glue = { + name = "Glue", + superclass = "JointInstance", + properties = { + F0 = { + name = "F0", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + F1 = { + name = "F1", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + F2 = { + name = "F2", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + F3 = { + name = "F3", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + F0 = Vector3.new(0, 0, 0), + F1 = Vector3.new(0, 0, 0), + F2 = Vector3.new(0, 0, 0), + F3 = Vector3.new(0, 0, 0), + Name = "Glue", + Part0 = nil, + Part1 = nil, + }, + }, + GoogleAnalyticsConfiguration = { + name = "GoogleAnalyticsConfiguration", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + GroupService = { + name = "GroupService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "GroupService", + }, + }, + GuiBase = { + name = "GuiBase", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + GuiBase2d = { + name = "GuiBase2d", + superclass = "GuiBase", + properties = { + AbsolutePosition = { + name = "AbsolutePosition", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + AbsoluteRotation = { + name = "AbsoluteRotation", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + AbsoluteSize = { + name = "AbsoluteSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + AutoLocalize = { + name = "AutoLocalize", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Localize = { + name = "Localize", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + RootLocalizationTable = { + name = "RootLocalizationTable", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + GuiBase3d = { + name = "GuiBase3d", + superclass = "GuiBase", + properties = { + Color = { + name = "Color", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Color3 = { + name = "Color3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Transparency = { + name = "Transparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Visible = { + name = "Visible", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + GuiButton = { + name = "GuiButton", + superclass = "GuiObject", + properties = { + AutoButtonColor = { + name = "AutoButtonColor", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Modal = { + name = "Modal", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Selected = { + name = "Selected", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Style = { + name = "Style", + type = {type = "Enum", name = "ButtonStyle"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + GuiLabel = { + name = "GuiLabel", + superclass = "GuiObject", + properties = { + }, + defaults = { + }, + }, + GuiMain = { + name = "GuiMain", + superclass = "ScreenGui", + properties = { + }, + defaults = { + AutoLocalize = true, + DisplayOrder = 0, + Enabled = true, + IgnoreGuiInset = false, + Localize = true, + Name = "GuiMain", + OnTopOfCoreBlur = false, + ResetOnSpawn = true, + RootLocalizationTable = nil, + ZIndexBehavior = 0, + }, + }, + GuiObject = { + name = "GuiObject", + superclass = "GuiBase2d", + properties = { + Active = { + name = "Active", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AnchorPoint = { + name = "AnchorPoint", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BackgroundColor = { + name = "BackgroundColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + BackgroundColor3 = { + name = "BackgroundColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BackgroundTransparency = { + name = "BackgroundTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BorderColor = { + name = "BorderColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + BorderColor3 = { + name = "BorderColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BorderMode = { + name = "BorderMode", + type = {type = "Enum", name = "BorderMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BorderSizePixel = { + name = "BorderSizePixel", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ClipsDescendants = { + name = "ClipsDescendants", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Draggable = { + name = "Draggable", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LayoutOrder = { + name = "LayoutOrder", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NextSelectionDown = { + name = "NextSelectionDown", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NextSelectionLeft = { + name = "NextSelectionLeft", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NextSelectionRight = { + name = "NextSelectionRight", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NextSelectionUp = { + name = "NextSelectionUp", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Position = { + name = "Position", + type = {type = "Data", name = "UDim2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Rotation = { + name = "Rotation", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Selectable = { + name = "Selectable", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SelectionImageObject = { + name = "SelectionImageObject", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Size = { + name = "Size", + type = {type = "Data", name = "UDim2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SizeConstraint = { + name = "SizeConstraint", + type = {type = "Enum", name = "SizeConstraint"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Transparency = { + name = "Transparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Visible = { + name = "Visible", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ZIndex = { + name = "ZIndex", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + GuiService = { + name = "GuiService", + superclass = "Instance", + properties = { + AutoSelectGuiEnabled = { + name = "AutoSelectGuiEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CoreEffectFolder = { + name = "CoreEffectFolder", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + CoreGuiFolder = { + name = "CoreGuiFolder", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + CoreGuiNavigationEnabled = { + name = "CoreGuiNavigationEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GuiNavigationEnabled = { + name = "GuiNavigationEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsModalDialog = { + name = "IsModalDialog", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsWindows = { + name = "IsWindows", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + MenuIsOpen = { + name = "MenuIsOpen", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + SelectedCoreObject = { + name = "SelectedCoreObject", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + SelectedObject = { + name = "SelectedObject", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + AutoSelectGuiEnabled = true, + CoreEffectFolder = nil, + CoreGuiFolder = nil, + CoreGuiNavigationEnabled = true, + GuiNavigationEnabled = true, + Name = "GuiService", + SelectedCoreObject = nil, + SelectedObject = nil, + }, + }, + GuidRegistryService = { + name = "GuidRegistryService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + HandleAdornment = { + name = "HandleAdornment", + superclass = "PVAdornment", + properties = { + AlwaysOnTop = { + name = "AlwaysOnTop", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CFrame = { + name = "CFrame", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SizeRelativeOffset = { + name = "SizeRelativeOffset", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ZIndex = { + name = "ZIndex", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + Handles = { + name = "Handles", + superclass = "HandlesBase", + properties = { + Faces = { + name = "Faces", + type = {type = "Unimplemented", name = "Faces"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Style = { + name = "Style", + type = {type = "Enum", name = "HandlesStyle"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Adornee = nil, + Color = BrickColor.new(23), + Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + Name = "Handles", + Style = 0, + Transparency = 0, + Visible = true, + }, + }, + HandlesBase = { + name = "HandlesBase", + superclass = "PartAdornment", + properties = { + }, + defaults = { + }, + }, + HapticService = { + name = "HapticService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "HapticService", + }, + }, + Hat = { + name = "Hat", + superclass = "Accoutrement", + properties = { + }, + defaults = { + AttachmentForward = Vector3.new(0, 0, -1), + AttachmentPoint = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + AttachmentPos = Vector3.new(0, 0, 0), + AttachmentRight = Vector3.new(1, 0, 0), + AttachmentUp = Vector3.new(0, 1, 0), + Name = "Hat", + }, + }, + HingeConstraint = { + name = "HingeConstraint", + superclass = "Constraint", + properties = { + ActuatorType = { + name = "ActuatorType", + type = {type = "Enum", name = "ActuatorType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AngularSpeed = { + name = "AngularSpeed", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AngularVelocity = { + name = "AngularVelocity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CurrentAngle = { + name = "CurrentAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + LimitsEnabled = { + name = "LimitsEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LowerAngle = { + name = "LowerAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MotorMaxAcceleration = { + name = "MotorMaxAcceleration", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MotorMaxTorque = { + name = "MotorMaxTorque", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Radius = { + name = "Radius", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Restitution = { + name = "Restitution", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ServoMaxTorque = { + name = "ServoMaxTorque", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TargetAngle = { + name = "TargetAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UpperAngle = { + name = "UpperAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + ActuatorType = 0, + AngularSpeed = 0, + AngularVelocity = 0, + Attachment0 = nil, + Attachment1 = nil, + Color = BrickColor.new(1009), + Enabled = true, + LimitsEnabled = false, + LowerAngle = -45, + MotorMaxAcceleration = 1000000000, + MotorMaxTorque = 0, + Name = "HingeConstraint", + Radius = 0.15, + Restitution = 0, + ServoMaxTorque = 0, + TargetAngle = 0, + UpperAngle = 45, + Visible = false, + }, + }, + Hint = { + name = "Hint", + superclass = "Message", + properties = { + }, + defaults = { + Name = "Message", + Text = "", + }, + }, + Hole = { + name = "Hole", + superclass = "Feature", + properties = { + }, + defaults = { + FaceId = 0, + InOut = 2, + LeftRight = 1, + Name = "Hole", + TopBottom = 1, + }, + }, + Hopper = { + name = "Hopper", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + HopperBin = { + name = "HopperBin", + superclass = "BackpackItem", + properties = { + Active = { + name = "Active", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BinType = { + name = "BinType", + type = {type = "Enum", name = "BinType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Active = false, + BinType = 0, + Name = "HopperBin", + TextureId = "", + }, + }, + HttpRbxApiService = { + name = "HttpRbxApiService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "HttpRbxApiService", + }, + }, + HttpRequest = { + name = "HttpRequest", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + HttpService = { + name = "HttpService", + superclass = "Instance", + properties = { + HttpEnabled = { + name = "HttpEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "HttpService", + }, + }, + Humanoid = { + name = "Humanoid", + superclass = "Instance", + properties = { + AutoJumpEnabled = { + name = "AutoJumpEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AutoRotate = { + name = "AutoRotate", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AutomaticScalingEnabled = { + name = "AutomaticScalingEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BreakJointsOnDeath = { + name = "BreakJointsOnDeath", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CameraOffset = { + name = "CameraOffset", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + CollisionType = { + name = "CollisionType", + type = {type = "Enum", name = "HumanoidCollisionType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DisplayDistanceType = { + name = "DisplayDistanceType", + type = {type = "Enum", name = "HumanoidDisplayDistanceType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FloorMaterial = { + name = "FloorMaterial", + type = {type = "Enum", name = "Material"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Health = { + name = "Health", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + HealthDisplayDistance = { + name = "HealthDisplayDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HealthDisplayType = { + name = "HealthDisplayType", + type = {type = "Enum", name = "HumanoidHealthDisplayType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HipHeight = { + name = "HipHeight", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Jump = { + name = "Jump", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + JumpHeight = { + name = "JumpHeight", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + JumpPower = { + name = "JumpPower", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LeftLeg = { + name = "LeftLeg", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + MaxHealth = { + name = "MaxHealth", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxSlopeAngle = { + name = "MaxSlopeAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MoveDirection = { + name = "MoveDirection", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + NameDisplayDistance = { + name = "NameDisplayDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NameOcclusion = { + name = "NameOcclusion", + type = {type = "Enum", name = "NameOcclusion"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PlatformStand = { + name = "PlatformStand", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + RigType = { + name = "RigType", + type = {type = "Enum", name = "HumanoidRigType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RightLeg = { + name = "RightLeg", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + RootPart = { + name = "RootPart", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + SeatPart = { + name = "SeatPart", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Sit = { + name = "Sit", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + TargetPoint = { + name = "TargetPoint", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Torso = { + name = "Torso", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + UseJumpPower = { + name = "UseJumpPower", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WalkSpeed = { + name = "WalkSpeed", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WalkToPart = { + name = "WalkToPart", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + WalkToPoint = { + name = "WalkToPoint", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + maxHealth = { + name = "maxHealth", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + AutoJumpEnabled = true, + AutoRotate = true, + AutomaticScalingEnabled = true, + BreakJointsOnDeath = true, + CameraOffset = Vector3.new(0, 0, 0), + CollisionType = 0, + DisplayDistanceType = 0, + Health = 100, + HealthDisplayDistance = 100, + HealthDisplayType = 0, + HipHeight = 0, + Jump = false, + JumpHeight = 7.2, + JumpPower = 50, + LeftLeg = nil, + MaxHealth = 100, + MaxSlopeAngle = 89, + Name = "Humanoid", + NameDisplayDistance = 100, + NameOcclusion = 2, + PlatformStand = false, + RigType = 0, + RightLeg = nil, + Sit = false, + TargetPoint = Vector3.new(0, 0, 0), + Torso = nil, + UseJumpPower = true, + WalkSpeed = 16, + WalkToPart = nil, + WalkToPoint = Vector3.new(0, 0, 0), + maxHealth = 100, + }, + }, + HumanoidController = { + name = "HumanoidController", + superclass = "Controller", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + HumanoidDescription = { + name = "HumanoidDescription", + superclass = "Instance", + properties = { + BackAccessory = { + name = "BackAccessory", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + BodyTypeScale = { + name = "BodyTypeScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ClimbAnimation = { + name = "ClimbAnimation", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DepthScale = { + name = "DepthScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Face = { + name = "Face", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FaceAccessory = { + name = "FaceAccessory", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FallAnimation = { + name = "FallAnimation", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FrontAccessory = { + name = "FrontAccessory", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GraphicTShirt = { + name = "GraphicTShirt", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HairAccessory = { + name = "HairAccessory", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HatAccessory = { + name = "HatAccessory", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Head = { + name = "Head", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HeadColor = { + name = "HeadColor", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HeadScale = { + name = "HeadScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HeightScale = { + name = "HeightScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IdleAnimation = { + name = "IdleAnimation", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + JumpAnimation = { + name = "JumpAnimation", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LeftArm = { + name = "LeftArm", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LeftArmColor = { + name = "LeftArmColor", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LeftLeg = { + name = "LeftLeg", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LeftLegColor = { + name = "LeftLegColor", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NeckAccessory = { + name = "NeckAccessory", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NumberEmotesLoaded = { + name = "NumberEmotesLoaded", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Pants = { + name = "Pants", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ProportionScale = { + name = "ProportionScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RightArm = { + name = "RightArm", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RightArmColor = { + name = "RightArmColor", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RightLeg = { + name = "RightLeg", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RightLegColor = { + name = "RightLegColor", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RunAnimation = { + name = "RunAnimation", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Shirt = { + name = "Shirt", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ShouldersAccessory = { + name = "ShouldersAccessory", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SwimAnimation = { + name = "SwimAnimation", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Torso = { + name = "Torso", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TorsoColor = { + name = "TorsoColor", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WaistAccessory = { + name = "WaistAccessory", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WalkAnimation = { + name = "WalkAnimation", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WidthScale = { + name = "WidthScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + BackAccessory = "", + BodyTypeScale = 0.3, + ClimbAnimation = 0, + DepthScale = 1, + Face = 0, + FaceAccessory = "", + FallAnimation = 0, + FrontAccessory = "", + GraphicTShirt = 0, + HairAccessory = "", + HatAccessory = "", + Head = 0, + HeadColor = Color3.new(0, 0, 0), + HeadScale = 1, + HeightScale = 1, + IdleAnimation = 0, + JumpAnimation = 0, + LeftArm = 0, + LeftArmColor = Color3.new(0, 0, 0), + LeftLeg = 0, + LeftLegColor = Color3.new(0, 0, 0), + Name = "HumanoidDescription", + NeckAccessory = "", + NumberEmotesLoaded = -1, + Pants = 0, + ProportionScale = 1, + RightArm = 0, + RightArmColor = Color3.new(0, 0, 0), + RightLeg = 0, + RightLegColor = Color3.new(0, 0, 0), + RunAnimation = 0, + Shirt = 0, + ShouldersAccessory = "", + SwimAnimation = 0, + Torso = 0, + TorsoColor = Color3.new(0, 0, 0), + WaistAccessory = "", + WalkAnimation = 0, + WidthScale = 1, + }, + }, + ImageButton = { + name = "ImageButton", + superclass = "GuiButton", + properties = { + HoverImage = { + name = "HoverImage", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Image = { + name = "Image", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ImageColor3 = { + name = "ImageColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ImageRectOffset = { + name = "ImageRectOffset", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ImageRectSize = { + name = "ImageRectSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ImageTransparency = { + name = "ImageTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsLoaded = { + name = "IsLoaded", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + PressedImage = { + name = "PressedImage", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ScaleType = { + name = "ScaleType", + type = {type = "Enum", name = "ScaleType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SliceCenter = { + name = "SliceCenter", + type = {type = "Data", name = "Rect"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SliceScale = { + name = "SliceScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TileSize = { + name = "TileSize", + type = {type = "Data", name = "UDim2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Active = true, + AnchorPoint = Vector2.new(0, 0), + AutoButtonColor = true, + AutoLocalize = true, + BackgroundColor = BrickColor.new(194), + BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), + BackgroundTransparency = 0, + BorderColor = BrickColor.new(26), + BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), + BorderMode = 0, + BorderSizePixel = 1, + ClipsDescendants = false, + Draggable = false, + HoverImage = "", + Image = "", + ImageColor3 = Color3.new(1, 1, 1), + ImageRectOffset = Vector2.new(0, 0), + ImageRectSize = Vector2.new(0, 0), + ImageTransparency = 0, + LayoutOrder = 0, + Localize = true, + Modal = false, + Name = "ImageButton", + NextSelectionDown = nil, + NextSelectionLeft = nil, + NextSelectionRight = nil, + NextSelectionUp = nil, + Position = UDim2.new(0, 0, 0, 0), + PressedImage = "", + RootLocalizationTable = nil, + Rotation = 0, + ScaleType = 0, + Selectable = true, + Selected = false, + SelectionImageObject = nil, + Size = UDim2.new(0, 0, 0, 0), + SizeConstraint = 0, + SliceCenter = Rect.new(0, 0, 0, 0), + SliceScale = 1, + Style = 0, + TileSize = UDim2.new(1, 0, 1, 0), + Transparency = 0, + Visible = true, + ZIndex = 1, + }, + }, + ImageHandleAdornment = { + name = "ImageHandleAdornment", + superclass = "HandleAdornment", + properties = { + Image = { + name = "Image", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Size = { + name = "Size", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Adornee = nil, + AlwaysOnTop = false, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Color = BrickColor.new(1), + Color3 = Color3.new(0.9490197, 0.95294124, 0.95294124), + Image = "rbxasset://textures/SurfacesDefault.png", + Name = "ImageHandleAdornment", + Size = Vector2.new(1, 1), + SizeRelativeOffset = Vector3.new(0, 0, 0), + Transparency = 0, + Visible = true, + ZIndex = -1, + }, + }, + ImageLabel = { + name = "ImageLabel", + superclass = "GuiLabel", + properties = { + Image = { + name = "Image", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ImageColor3 = { + name = "ImageColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ImageRectOffset = { + name = "ImageRectOffset", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ImageRectSize = { + name = "ImageRectSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ImageTransparency = { + name = "ImageTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsLoaded = { + name = "IsLoaded", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ScaleType = { + name = "ScaleType", + type = {type = "Enum", name = "ScaleType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SliceCenter = { + name = "SliceCenter", + type = {type = "Data", name = "Rect"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SliceScale = { + name = "SliceScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TileSize = { + name = "TileSize", + type = {type = "Data", name = "UDim2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Active = false, + AnchorPoint = Vector2.new(0, 0), + AutoLocalize = true, + BackgroundColor = BrickColor.new(194), + BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), + BackgroundTransparency = 0, + BorderColor = BrickColor.new(26), + BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), + BorderMode = 0, + BorderSizePixel = 1, + ClipsDescendants = false, + Draggable = false, + Image = "", + ImageColor3 = Color3.new(1, 1, 1), + ImageRectOffset = Vector2.new(0, 0), + ImageRectSize = Vector2.new(0, 0), + ImageTransparency = 0, + LayoutOrder = 0, + Localize = true, + Name = "ImageLabel", + NextSelectionDown = nil, + NextSelectionLeft = nil, + NextSelectionRight = nil, + NextSelectionUp = nil, + Position = UDim2.new(0, 0, 0, 0), + RootLocalizationTable = nil, + Rotation = 0, + ScaleType = 0, + Selectable = false, + SelectionImageObject = nil, + Size = UDim2.new(0, 0, 0, 0), + SizeConstraint = 0, + SliceCenter = Rect.new(0, 0, 0, 0), + SliceScale = 1, + TileSize = UDim2.new(1, 0, 1, 0), + Transparency = 0, + Visible = true, + ZIndex = 1, + }, + }, + InputObject = { + name = "InputObject", + superclass = "Instance", + properties = { + Delta = { + name = "Delta", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + KeyCode = { + name = "KeyCode", + type = {type = "Enum", name = "KeyCode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Position = { + name = "Position", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + UserInputState = { + name = "UserInputState", + type = {type = "Enum", name = "UserInputState"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + UserInputType = { + name = "UserInputType", + type = {type = "Enum", name = "UserInputType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + }, + }, + InsertService = { + name = "InsertService", + superclass = "Instance", + properties = { + AllowClientInsertModels = { + name = "AllowClientInsertModels", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + AllowInsertFreeModels = { + name = "AllowInsertFreeModels", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + AllowInsertFreeModels = false, + Name = "InsertService", + }, + }, + Instance = { + name = "Instance", + superclass = nil, + properties = { + Archivable = { + name = "Archivable", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = "archivable", + scriptability = "ReadWrite", + serializes = true, + }, + ClassName = { + name = "ClassName", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + DataCost = { + name = "DataCost", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Name = { + name = "Name", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Parent = { + name = "Parent", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + RobloxLocked = { + name = "RobloxLocked", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Tags = { + name = "Tags", + type = {type = "Data", name = "BinaryString"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Custom", + serializes = true, + }, + archivable = { + name = "archivable", + type = {type = "Data", name = "Bool"}, + isCanonical = false, + canonicalName = "Archivable", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + className = { + name = "className", + type = {type = "Data", name = "String"}, + isCanonical = false, + canonicalName = "ClassName", + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + IntConstrainedValue = { + name = "IntConstrainedValue", + superclass = "ValueBase", + properties = { + ConstrainedValue = { + name = "ConstrainedValue", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + MaxValue = { + name = "MaxValue", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MinValue = { + name = "MinValue", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Value = { + name = "Value", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + ConstrainedValue = 0, + MaxValue = 10, + MinValue = 0, + Name = "Value", + Value = 0, + }, + }, + IntValue = { + name = "IntValue", + superclass = "ValueBase", + properties = { + Value = { + name = "Value", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Value", + Value = 0, + }, + }, + InventoryPages = { + name = "InventoryPages", + superclass = "Pages", + properties = { + }, + defaults = { + }, + }, + JointInstance = { + name = "JointInstance", + superclass = "Instance", + properties = { + Active = { + name = "Active", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + C0 = { + name = "C0", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + C1 = { + name = "C1", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Part0 = { + name = "Part0", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Part1 = { + name = "Part1", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + part1 = { + name = "part1", + type = {type = "Data", name = "Ref"}, + isCanonical = false, + canonicalName = "Part1", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + }, + }, + JointsService = { + name = "JointsService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "JointsService", + }, + }, + KeyboardService = { + name = "KeyboardService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + Keyframe = { + name = "Keyframe", + superclass = "Instance", + properties = { + Time = { + name = "Time", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Keyframe", + Time = 0, + }, + }, + KeyframeMarker = { + name = "KeyframeMarker", + superclass = "Instance", + properties = { + Value = { + name = "Value", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "KeyframeMarker", + Value = "", + }, + }, + KeyframeSequence = { + name = "KeyframeSequence", + superclass = "Instance", + properties = { + AuthoredHipHeight = { + name = "AuthoredHipHeight", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Loop = { + name = "Loop", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Priority = { + name = "Priority", + type = {type = "Enum", name = "AnimationPriority"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + AuthoredHipHeight = 2, + Loop = true, + Name = "KeyframeSequence", + Priority = 2, + }, + }, + KeyframeSequenceProvider = { + name = "KeyframeSequenceProvider", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + LayerCollector = { + name = "LayerCollector", + superclass = "GuiBase2d", + properties = { + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ResetOnSpawn = { + name = "ResetOnSpawn", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ZIndexBehavior = { + name = "ZIndexBehavior", + type = {type = "Enum", name = "ZIndexBehavior"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + Light = { + name = "Light", + superclass = "Instance", + properties = { + Brightness = { + name = "Brightness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Color = { + name = "Color", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Shadows = { + name = "Shadows", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + Lighting = { + name = "Lighting", + superclass = "Instance", + properties = { + Ambient = { + name = "Ambient", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Brightness = { + name = "Brightness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ClockTime = { + name = "ClockTime", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + ColorShift_Bottom = { + name = "ColorShift_Bottom", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ColorShift_Top = { + name = "ColorShift_Top", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ExposureCompensation = { + name = "ExposureCompensation", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FogColor = { + name = "FogColor", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FogEnd = { + name = "FogEnd", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FogStart = { + name = "FogStart", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GeographicLatitude = { + name = "GeographicLatitude", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GlobalShadows = { + name = "GlobalShadows", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LegacyOutlines = { + name = "LegacyOutlines", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + OutdoorAmbient = { + name = "OutdoorAmbient", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Outlines = { + name = "Outlines", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ShadowColor = { + name = "ShadowColor", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + ShadowSoftness = { + name = "ShadowSoftness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Technology = { + name = "Technology", + type = {type = "Enum", name = "Technology"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + TimeOfDay = { + name = "TimeOfDay", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Ambient = Color3.new(0.5, 0.5, 0.5), + Brightness = 1, + ClockTime = 14, + ColorShift_Bottom = Color3.new(0, 0, 0), + ColorShift_Top = Color3.new(0, 0, 0), + ExposureCompensation = 0, + FogColor = Color3.new(0.75, 0.75, 0.75), + FogEnd = 100000, + FogStart = 0, + GeographicLatitude = 41.7333, + GlobalShadows = false, + Name = "Lighting", + OutdoorAmbient = Color3.new(0.5, 0.5, 0.5), + Outlines = true, + ShadowColor = Color3.new(0.7, 0.7, 0.72), + ShadowSoftness = 0.5, + TimeOfDay = "14:00:00", + }, + }, + LineForce = { + name = "LineForce", + superclass = "Constraint", + properties = { + ApplyAtCenterOfMass = { + name = "ApplyAtCenterOfMass", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + InverseSquareLaw = { + name = "InverseSquareLaw", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Magnitude = { + name = "Magnitude", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxForce = { + name = "MaxForce", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ReactionForceEnabled = { + name = "ReactionForceEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + ApplyAtCenterOfMass = false, + Attachment0 = nil, + Attachment1 = nil, + Color = BrickColor.new(23), + Enabled = true, + InverseSquareLaw = false, + Magnitude = 1000, + MaxForce = 1000000000, + Name = "LineForce", + ReactionForceEnabled = false, + Visible = false, + }, + }, + LineHandleAdornment = { + name = "LineHandleAdornment", + superclass = "HandleAdornment", + properties = { + Length = { + name = "Length", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Thickness = { + name = "Thickness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Adornee = nil, + AlwaysOnTop = false, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Color = BrickColor.new(23), + Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + Length = 5, + Name = "LineHandleAdornment", + SizeRelativeOffset = Vector3.new(0, 0, 0), + Thickness = 1, + Transparency = 0, + Visible = true, + ZIndex = -1, + }, + }, + LocalScript = { + name = "LocalScript", + superclass = "Script", + properties = { + }, + defaults = { + Disabled = false, + LinkedSource = "", + Name = "LocalScript", + Source = "", + }, + }, + LocalStorageService = { + name = "LocalStorageService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + LocalizationService = { + name = "LocalizationService", + superclass = "Instance", + properties = { + ForcePlayModeGameLocaleId = { + name = "ForcePlayModeGameLocaleId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + ForcePlayModeRobloxLocaleId = { + name = "ForcePlayModeRobloxLocaleId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + IsTextScraperRunning = { + name = "IsTextScraperRunning", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + RobloxForcePlayModeGameLocaleId = { + name = "RobloxForcePlayModeGameLocaleId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + RobloxForcePlayModeRobloxLocaleId = { + name = "RobloxForcePlayModeRobloxLocaleId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + RobloxLocaleId = { + name = "RobloxLocaleId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + SystemLocaleId = { + name = "SystemLocaleId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + IsTextScraperRunning = false, + Name = "LocalizationService", + RobloxForcePlayModeGameLocaleId = "", + RobloxForcePlayModeRobloxLocaleId = "en-us", + }, + }, + LocalizationTable = { + name = "LocalizationTable", + superclass = "Instance", + properties = { + Contents = { + name = "Contents", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Custom", + serializes = true, + }, + DevelopmentLanguage = { + name = "DevelopmentLanguage", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Root = { + name = "Root", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + SourceLocaleId = { + name = "SourceLocaleId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + DevelopmentLanguage = "en-us", + Name = "LocalizationTable", + Root = nil, + SourceLocaleId = "en-us", + }, + }, + LogService = { + name = "LogService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "LogService", + }, + }, + LoginService = { + name = "LoginService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + LuaSettings = { + name = "LuaSettings", + superclass = "Instance", + properties = { + AreScriptStartsReported = { + name = "AreScriptStartsReported", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DefaultWaitTime = { + name = "DefaultWaitTime", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GcFrequency = { + name = "GcFrequency", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GcLimit = { + name = "GcLimit", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GcPause = { + name = "GcPause", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GcStepMul = { + name = "GcStepMul", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WaitingThreadsBudget = { + name = "WaitingThreadsBudget", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + LuaSourceContainer = { + name = "LuaSourceContainer", + superclass = "Instance", + properties = { + CurrentEditor = { + name = "CurrentEditor", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = false, + }, + }, + defaults = { + }, + }, + LuaWebService = { + name = "LuaWebService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + MDIInstance = { + name = "MDIInstance", + superclass = "Instance", + properties = { + FocusedDataModelSession = { + name = "FocusedDataModelSession", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + FocusedDataModelSessionId = { + name = "FocusedDataModelSessionId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + ManualGlue = { + name = "ManualGlue", + superclass = "ManualSurfaceJointInstance", + properties = { + }, + defaults = { + C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Name = "ManualGlue", + Part0 = nil, + Part1 = nil, + }, + }, + ManualSurfaceJointInstance = { + name = "ManualSurfaceJointInstance", + superclass = "JointInstance", + properties = { + }, + defaults = { + }, + }, + ManualWeld = { + name = "ManualWeld", + superclass = "ManualSurfaceJointInstance", + properties = { + }, + defaults = { + C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Name = "ManualWeld", + Part0 = nil, + Part1 = nil, + }, + }, + MarketplaceService = { + name = "MarketplaceService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "MarketplaceService", + }, + }, + MemStorageConnection = { + name = "MemStorageConnection", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + MemStorageService = { + name = "MemStorageService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "MemStorageService", + }, + }, + MeshContentProvider = { + name = "MeshContentProvider", + superclass = "CacheableContentProvider", + properties = { + }, + defaults = { + Name = "MeshContentProvider", + }, + }, + MeshPart = { + name = "MeshPart", + superclass = "TriangleMeshPart", + properties = { + MeshID = { + name = "MeshID", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + MeshId = { + name = "MeshId", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = true, + }, + RenderFidelity = { + name = "RenderFidelity", + type = {type = "Enum", name = "RenderFidelity"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextureID = { + name = "TextureID", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Anchored = false, + BackParamA = -0.5, + BackParamB = 0.5, + BackSurface = 0, + BackSurfaceInput = 0, + BottomParamA = -0.5, + BottomParamB = 0.5, + BottomSurface = 0, + BottomSurfaceInput = 0, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CanCollide = true, + CastShadow = true, + CollisionFidelity = 0, + CollisionGroupId = 0, + Color = Color3.new(0.6392157, 0.63529414, 0.64705884), + CustomPhysicalProperties = nil, + Elasticity = 0.5, + Friction = 0.3, + FrontParamA = -0.5, + FrontParamB = 0.5, + FrontSurface = 0, + FrontSurfaceInput = 0, + LeftParamA = -0.5, + LeftParamB = 0.5, + LeftSurface = 0, + LeftSurfaceInput = 0, + LocalTransparencyModifier = 0, + Locked = false, + Massless = false, + Material = 256, + MeshId = "", + Name = "MeshPart", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Reflectance = 0, + RenderFidelity = 1, + RightParamA = -0.5, + RightParamB = 0.5, + RightSurface = 0, + RightSurfaceInput = 0, + RootPriority = 0, + RotVelocity = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + Size = Vector3.new(4, 1.2, 2), + TextureID = "", + TopParamA = -0.5, + TopParamB = 0.5, + TopSurface = 0, + TopSurfaceInput = 0, + Transparency = 0, + Velocity = Vector3.new(0, 0, 0), + }, + }, + Message = { + name = "Message", + superclass = "Instance", + properties = { + Text = { + name = "Text", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Message", + Text = "", + }, + }, + MessagingService = { + name = "MessagingService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "MessagingService", + }, + }, + Model = { + name = "Model", + superclass = "PVInstance", + properties = { + PrimaryPart = { + name = "PrimaryPart", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Model", + PrimaryPart = nil, + }, + }, + ModuleScript = { + name = "ModuleScript", + superclass = "LuaSourceContainer", + properties = { + LinkedSource = { + name = "LinkedSource", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Source = { + name = "Source", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + LinkedSource = "", + Name = "ModuleScript", + Source = "", + }, + }, + Motor = { + name = "Motor", + superclass = "JointInstance", + properties = { + CurrentAngle = { + name = "CurrentAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + DesiredAngle = { + name = "DesiredAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxVelocity = { + name = "MaxVelocity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CurrentAngle = 0, + DesiredAngle = 0, + MaxVelocity = 0, + Name = "Motor", + Part0 = nil, + Part1 = nil, + }, + }, + Motor6D = { + name = "Motor6D", + superclass = "Motor", + properties = { + Transform = { + name = "Transform", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CurrentAngle = 0, + DesiredAngle = 0, + MaxVelocity = 0, + Name = "Motor6D", + Part0 = nil, + Part1 = nil, + Transform = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + }, + }, + MotorFeature = { + name = "MotorFeature", + superclass = "Feature", + properties = { + }, + defaults = { + FaceId = 0, + InOut = 2, + LeftRight = 1, + Name = "MotorFeature", + TopBottom = 1, + }, + }, + Mouse = { + name = "Mouse", + superclass = "Instance", + properties = { + Hit = { + name = "Hit", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Icon = { + name = "Icon", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Origin = { + name = "Origin", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Target = { + name = "Target", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TargetFilter = { + name = "TargetFilter", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TargetSurface = { + name = "TargetSurface", + type = {type = "Enum", name = "NormalId"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + UnitRay = { + name = "UnitRay", + type = {type = "Unimplemented", name = "Ray"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ViewSizeX = { + name = "ViewSizeX", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ViewSizeY = { + name = "ViewSizeY", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + X = { + name = "X", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Y = { + name = "Y", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + hit = { + name = "hit", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + target = { + name = "target", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + MouseService = { + name = "MouseService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + NegateOperation = { + name = "NegateOperation", + superclass = "PartOperation", + properties = { + }, + defaults = { + Anchored = true, + BackParamA = -0.5, + BackParamB = 0.5, + BackSurface = 0, + BackSurfaceInput = 0, + BottomParamA = -0.5, + BottomParamB = 0.5, + BottomSurface = 0, + BottomSurfaceInput = 0, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CanCollide = false, + CastShadow = true, + CollisionFidelity = 0, + CollisionGroupId = 0, + Color = Color3.new(1, 1, 1), + CustomPhysicalProperties = nil, + Elasticity = 0.5, + Friction = 0.3, + FrontParamA = -0.5, + FrontParamB = 0.5, + FrontSurface = 0, + FrontSurfaceInput = 0, + LeftParamA = -0.5, + LeftParamB = 0.5, + LeftSurface = 0, + LeftSurfaceInput = 0, + LocalTransparencyModifier = 0, + Locked = false, + Massless = false, + Material = 256, + Name = "NegativePart", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Reflectance = 0, + RenderFidelity = 1, + RightParamA = -0.5, + RightParamB = 0.5, + RightSurface = 0, + RightSurfaceInput = 0, + RootPriority = 0, + RotVelocity = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + Size = Vector3.new(4, 1.2, 2), + TopParamA = -0.5, + TopParamB = 0.5, + TopSurface = 0, + TopSurfaceInput = 0, + Transparency = 0.1, + UsePartColor = false, + Velocity = Vector3.new(0, 0, 0), + }, + }, + NetworkClient = { + name = "NetworkClient", + superclass = "NetworkPeer", + properties = { + Ticket = { + name = "Ticket", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + NetworkMarker = { + name = "NetworkMarker", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + NetworkPeer = { + name = "NetworkPeer", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + NetworkReplicator = { + name = "NetworkReplicator", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + NetworkServer = { + name = "NetworkServer", + superclass = "NetworkPeer", + properties = { + Port = { + name = "Port", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + NetworkSettings = { + name = "NetworkSettings", + superclass = "Instance", + properties = { + ArePhysicsRejectionsReported = { + name = "ArePhysicsRejectionsReported", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ClientPhysicsSendRate = { + name = "ClientPhysicsSendRate", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DataGCRate = { + name = "DataGCRate", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DataMtuAdjust = { + name = "DataMtuAdjust", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DataSendPriority = { + name = "DataSendPriority", + type = {type = "Enum", name = "PacketPriority"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + DataSendRate = { + name = "DataSendRate", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ExtraMemoryUsed = { + name = "ExtraMemoryUsed", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + FreeMemoryMBytes = { + name = "FreeMemoryMBytes", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IncommingReplicationLag = { + name = "IncommingReplicationLag", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsQueueErrorComputed = { + name = "IsQueueErrorComputed", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NetworkOwnerRate = { + name = "NetworkOwnerRate", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PhysicsMtuAdjust = { + name = "PhysicsMtuAdjust", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PhysicsSendPriority = { + name = "PhysicsSendPriority", + type = {type = "Enum", name = "PacketPriority"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + PhysicsSendRate = { + name = "PhysicsSendRate", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PreferredClientPort = { + name = "PreferredClientPort", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PrintBits = { + name = "PrintBits", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PrintEvents = { + name = "PrintEvents", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PrintFilters = { + name = "PrintFilters", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PrintInstances = { + name = "PrintInstances", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PrintJoinSizeBreakdown = { + name = "PrintJoinSizeBreakdown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PrintPhysicsErrors = { + name = "PrintPhysicsErrors", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PrintProperties = { + name = "PrintProperties", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PrintSplitMessage = { + name = "PrintSplitMessage", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PrintStreamInstanceQuota = { + name = "PrintStreamInstanceQuota", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PrintTouches = { + name = "PrintTouches", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ProxyEnabled = { + name = "ProxyEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ProxyURL = { + name = "ProxyURL", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ReceiveRate = { + name = "ReceiveRate", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RenderStreamedRegions = { + name = "RenderStreamedRegions", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ShowActiveAnimationAsset = { + name = "ShowActiveAnimationAsset", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TouchSendRate = { + name = "TouchSendRate", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TrackDataTypes = { + name = "TrackDataTypes", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TrackPhysicsDetails = { + name = "TrackPhysicsDetails", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UsePhysicsPacketCache = { + name = "UsePhysicsPacketCache", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + NoCollisionConstraint = { + name = "NoCollisionConstraint", + superclass = "Instance", + properties = { + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Part0 = { + name = "Part0", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Part1 = { + name = "Part1", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Enabled = true, + Name = "NoCollisionConstraint", + Part0 = nil, + Part1 = nil, + }, + }, + NonReplicatedCSGDictionaryService = { + name = "NonReplicatedCSGDictionaryService", + superclass = "FlyweightService", + properties = { + }, + defaults = { + }, + }, + NotificationService = { + name = "NotificationService", + superclass = "Instance", + properties = { + IsLuaBottomBarEnabled = { + name = "IsLuaBottomBarEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsLuaBottomBarWithText = { + name = "IsLuaBottomBarWithText", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsLuaChatEnabled = { + name = "IsLuaChatEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsLuaGameDetailsEnabled = { + name = "IsLuaGameDetailsEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsLuaHomeWithAvatarEnabled = { + name = "IsLuaHomeWithAvatarEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + SelectedTheme = { + name = "SelectedTheme", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + Name = "NotificationService", + SelectedTheme = "", + }, + }, + NumberValue = { + name = "NumberValue", + superclass = "ValueBase", + properties = { + Value = { + name = "Value", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Value", + Value = 0, + }, + }, + ObjectValue = { + name = "ObjectValue", + superclass = "ValueBase", + properties = { + Value = { + name = "Value", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Value", + Value = nil, + }, + }, + OrderedDataStore = { + name = "OrderedDataStore", + superclass = "GlobalDataStore", + properties = { + }, + defaults = { + }, + }, + PVAdornment = { + name = "PVAdornment", + superclass = "GuiBase3d", + properties = { + Adornee = { + name = "Adornee", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + PVInstance = { + name = "PVInstance", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + PackageLink = { + name = "PackageLink", + superclass = "Instance", + properties = { + AutoUpdate = { + name = "AutoUpdate", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + PackageId = { + name = "PackageId", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Status = { + name = "Status", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + VersionNumber = { + name = "VersionNumber", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + }, + }, + PackageService = { + name = "PackageService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + Pages = { + name = "Pages", + superclass = "Instance", + properties = { + IsFinished = { + name = "IsFinished", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + Pants = { + name = "Pants", + superclass = "Clothing", + properties = { + PantsTemplate = { + name = "PantsTemplate", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Color3 = Color3.new(1, 1, 1), + Name = "Clothing", + PantsTemplate = "", + }, + }, + ParabolaAdornment = { + name = "ParabolaAdornment", + superclass = "PVAdornment", + properties = { + A = { + name = "A", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + B = { + name = "B", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + C = { + name = "C", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Range = { + name = "Range", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Thickness = { + name = "Thickness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + A = 1, + Adornee = nil, + B = 0, + C = 0, + Color = BrickColor.new(1), + Color3 = Color3.new(0.9490197, 0.95294124, 0.95294124), + Name = "ParabolaAdornment", + Range = 1, + Thickness = 1, + Transparency = 0, + Visible = true, + }, + }, + Part = { + name = "Part", + superclass = "FormFactorPart", + properties = { + Shape = { + name = "Shape", + type = {type = "Enum", name = "PartType"}, + isCanonical = true, + canonicalName = nil, + serializedName = "shape", + scriptability = "ReadWrite", + serializes = true, + }, + shape = { + name = "shape", + type = {type = "Enum", name = "PartType"}, + isCanonical = false, + canonicalName = "Shape", + serializedName = nil, + scriptability = "None", + serializes = false, + }, + }, + defaults = { + Anchored = false, + BackParamA = -0.5, + BackParamB = 0.5, + BackSurface = 0, + BackSurfaceInput = 0, + BottomParamA = -0.5, + BottomParamB = 0.5, + BottomSurface = 4, + BottomSurfaceInput = 0, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CanCollide = true, + CastShadow = true, + CollisionGroupId = 0, + Color = Color3.new(0.6392157, 0.63529414, 0.64705884), + CustomPhysicalProperties = nil, + Elasticity = 0.5, + FormFactor = 1, + Friction = 0.3, + FrontParamA = -0.5, + FrontParamB = 0.5, + FrontSurface = 0, + FrontSurfaceInput = 0, + LeftParamA = -0.5, + LeftParamB = 0.5, + LeftSurface = 0, + LeftSurfaceInput = 0, + LocalTransparencyModifier = 0, + Locked = false, + Massless = false, + Material = 256, + Name = "Part", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Reflectance = 0, + RightParamA = -0.5, + RightParamB = 0.5, + RightSurface = 0, + RightSurfaceInput = 0, + RootPriority = 0, + RotVelocity = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + Shape = 1, + Size = Vector3.new(4, 1.2, 2), + TopParamA = -0.5, + TopParamB = 0.5, + TopSurface = 3, + TopSurfaceInput = 0, + Transparency = 0, + Velocity = Vector3.new(0, 0, 0), + }, + }, + PartAdornment = { + name = "PartAdornment", + superclass = "GuiBase3d", + properties = { + Adornee = { + name = "Adornee", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + PartOperation = { + name = "PartOperation", + superclass = "TriangleMeshPart", + properties = { + RenderFidelity = { + name = "RenderFidelity", + type = {type = "Enum", name = "RenderFidelity"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TriangleCount = { + name = "TriangleCount", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + UsePartColor = { + name = "UsePartColor", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Anchored = false, + BackParamA = -0.5, + BackParamB = 0.5, + BackSurface = 0, + BackSurfaceInput = 0, + BottomParamA = -0.5, + BottomParamB = 0.5, + BottomSurface = 0, + BottomSurfaceInput = 0, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CanCollide = true, + CastShadow = true, + CollisionFidelity = 0, + CollisionGroupId = 0, + Color = Color3.new(1, 1, 1), + CustomPhysicalProperties = nil, + Elasticity = 0.5, + Friction = 0.3, + FrontParamA = -0.5, + FrontParamB = 0.5, + FrontSurface = 0, + FrontSurfaceInput = 0, + LeftParamA = -0.5, + LeftParamB = 0.5, + LeftSurface = 0, + LeftSurfaceInput = 0, + LocalTransparencyModifier = 0, + Locked = false, + Massless = false, + Material = 256, + Name = "PartOperation", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Reflectance = 0, + RenderFidelity = 1, + RightParamA = -0.5, + RightParamB = 0.5, + RightSurface = 0, + RightSurfaceInput = 0, + RootPriority = 0, + RotVelocity = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + Size = Vector3.new(4, 1.2, 2), + TopParamA = -0.5, + TopParamB = 0.5, + TopSurface = 0, + TopSurfaceInput = 0, + Transparency = 0, + UsePartColor = false, + Velocity = Vector3.new(0, 0, 0), + }, + }, + PartOperationAsset = { + name = "PartOperationAsset", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + ParticleEmitter = { + name = "ParticleEmitter", + superclass = "Instance", + properties = { + Acceleration = { + name = "Acceleration", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Color = { + name = "Color", + type = {type = "Data", name = "ColorSequence"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Drag = { + name = "Drag", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + EmissionDirection = { + name = "EmissionDirection", + type = {type = "Enum", name = "NormalId"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Lifetime = { + name = "Lifetime", + type = {type = "Data", name = "NumberRange"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LightEmission = { + name = "LightEmission", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LightInfluence = { + name = "LightInfluence", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LockedToPart = { + name = "LockedToPart", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Rate = { + name = "Rate", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RotSpeed = { + name = "RotSpeed", + type = {type = "Data", name = "NumberRange"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Rotation = { + name = "Rotation", + type = {type = "Data", name = "NumberRange"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Size = { + name = "Size", + type = {type = "Data", name = "NumberSequence"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Speed = { + name = "Speed", + type = {type = "Data", name = "NumberRange"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SpreadAngle = { + name = "SpreadAngle", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Texture = { + name = "Texture", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Transparency = { + name = "Transparency", + type = {type = "Data", name = "NumberSequence"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + VelocityInheritance = { + name = "VelocityInheritance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + VelocitySpread = { + name = "VelocitySpread", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + ZOffset = { + name = "ZOffset", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Acceleration = Vector3.new(0, 0, 0), + Color = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.new(1, 1, 1)), ColorSequenceKeypoint.new(1, Color3.new(1, 1, 1))}), + Drag = 0, + EmissionDirection = 1, + Enabled = true, + Lifetime = NumberRange.new(5, 10), + LightEmission = 0, + LightInfluence = 0, + LockedToPart = false, + Name = "ParticleEmitter", + Rate = 20, + RotSpeed = NumberRange.new(0, 0), + Rotation = NumberRange.new(0, 0), + Size = NumberSequence.new({NumberSequenceKeypoint.new(0, 1, 0), NumberSequenceKeypoint.new(1, 1, 0)}), + Speed = NumberRange.new(5, 5), + SpreadAngle = Vector2.new(0, 0), + Texture = "rbxasset://textures/particles/sparkles_main.dds", + Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 0, 0), NumberSequenceKeypoint.new(1, 0, 0)}), + VelocityInheritance = 0, + VelocitySpread = 0, + ZOffset = 0, + }, + }, + Path = { + name = "Path", + superclass = "Instance", + properties = { + Status = { + name = "Status", + type = {type = "Enum", name = "PathStatus"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + PathfindingService = { + name = "PathfindingService", + superclass = "Instance", + properties = { + EmptyCutoff = { + name = "EmptyCutoff", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + EmptyCutoff = 0, + Name = "Instance", + }, + }, + PhysicsPacketCache = { + name = "PhysicsPacketCache", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + PhysicsService = { + name = "PhysicsService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "PhysicsService", + }, + }, + PhysicsSettings = { + name = "PhysicsSettings", + superclass = "Instance", + properties = { + AllowSleep = { + name = "AllowSleep", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AreAnchorsShown = { + name = "AreAnchorsShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AreAssembliesShown = { + name = "AreAssembliesShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AreAwakePartsHighlighted = { + name = "AreAwakePartsHighlighted", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AreBodyTypesShown = { + name = "AreBodyTypesShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AreContactIslandsShown = { + name = "AreContactIslandsShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AreContactPointsShown = { + name = "AreContactPointsShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AreJointCoordinatesShown = { + name = "AreJointCoordinatesShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AreMechanismsShown = { + name = "AreMechanismsShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AreModelCoordsShown = { + name = "AreModelCoordsShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AreOwnersShown = { + name = "AreOwnersShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ArePartCoordsShown = { + name = "ArePartCoordsShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AreRegionsShown = { + name = "AreRegionsShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AreUnalignedPartsShown = { + name = "AreUnalignedPartsShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AreWorldCoordsShown = { + name = "AreWorldCoordsShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DisableCSGv2 = { + name = "DisableCSGv2", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsReceiveAgeShown = { + name = "IsReceiveAgeShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsTreeShown = { + name = "IsTreeShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PhysicsEnvironmentalThrottle = { + name = "PhysicsEnvironmentalThrottle", + type = {type = "Enum", name = "EnviromentalPhysicsThrottle"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ShowDecompositionGeometry = { + name = "ShowDecompositionGeometry", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ThrottleAdjustTime = { + name = "ThrottleAdjustTime", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UseCSGv2 = { + name = "UseCSGv2", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + PitchShiftSoundEffect = { + name = "PitchShiftSoundEffect", + superclass = "SoundEffect", + properties = { + Octave = { + name = "Octave", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Enabled = true, + Name = "PitchShiftSoundEffect", + Octave = 1.25, + Priority = 0, + }, + }, + Platform = { + name = "Platform", + superclass = "Part", + properties = { + }, + defaults = { + }, + }, + Player = { + name = "Player", + superclass = "Instance", + properties = { + AccountAge = { + name = "AccountAge", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + AppearanceDidLoad = { + name = "AppearanceDidLoad", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + AutoJumpEnabled = { + name = "AutoJumpEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CameraMaxZoomDistance = { + name = "CameraMaxZoomDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CameraMinZoomDistance = { + name = "CameraMinZoomDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CameraMode = { + name = "CameraMode", + type = {type = "Enum", name = "CameraMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CanLoadCharacterAppearance = { + name = "CanLoadCharacterAppearance", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Character = { + name = "Character", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CharacterAppearance = { + name = "CharacterAppearance", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CharacterAppearanceId = { + name = "CharacterAppearanceId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ChatMode = { + name = "ChatMode", + type = {type = "Enum", name = "ChatMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + DataComplexity = { + name = "DataComplexity", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + DataComplexityLimit = { + name = "DataComplexityLimit", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + DataReady = { + name = "DataReady", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + DevCameraOcclusionMode = { + name = "DevCameraOcclusionMode", + type = {type = "Enum", name = "DevCameraOcclusionMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DevComputerCameraMode = { + name = "DevComputerCameraMode", + type = {type = "Enum", name = "DevComputerCameraMovementMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DevComputerMovementMode = { + name = "DevComputerMovementMode", + type = {type = "Enum", name = "DevComputerMovementMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DevEnableMouseLock = { + name = "DevEnableMouseLock", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DevTouchCameraMode = { + name = "DevTouchCameraMode", + type = {type = "Enum", name = "DevTouchCameraMovementMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DevTouchMovementMode = { + name = "DevTouchMovementMode", + type = {type = "Enum", name = "DevTouchMovementMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DisplayName = { + name = "DisplayName", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + FollowUserId = { + name = "FollowUserId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + GameplayPaused = { + name = "GameplayPaused", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Guest = { + name = "Guest", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + HealthDisplayDistance = { + name = "HealthDisplayDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LocaleId = { + name = "LocaleId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + MaximumSimulationRadius = { + name = "MaximumSimulationRadius", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + MembershipType = { + name = "MembershipType", + type = {type = "Enum", name = "MembershipType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + NameDisplayDistance = { + name = "NameDisplayDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Neutral = { + name = "Neutral", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + OsPlatform = { + name = "OsPlatform", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + ReplicationFocus = { + name = "ReplicationFocus", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RespawnLocation = { + name = "RespawnLocation", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SimulationRadius = { + name = "SimulationRadius", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Team = { + name = "Team", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TeamColor = { + name = "TeamColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Teleported = { + name = "Teleported", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TeleportedIn = { + name = "TeleportedIn", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UserId = { + name = "UserId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + VRDevice = { + name = "VRDevice", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + userId = { + name = "userId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + }, + }, + PlayerGui = { + name = "PlayerGui", + superclass = "BasePlayerGui", + properties = { + CurrentScreenOrientation = { + name = "CurrentScreenOrientation", + type = {type = "Enum", name = "ScreenOrientation"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ScreenOrientation = { + name = "ScreenOrientation", + type = {type = "Enum", name = "ScreenOrientation"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SelectionImageObject = { + name = "SelectionImageObject", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + PlayerMouse = { + name = "PlayerMouse", + superclass = "Mouse", + properties = { + }, + defaults = { + }, + }, + PlayerScripts = { + name = "PlayerScripts", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + Players = { + name = "Players", + superclass = "Instance", + properties = { + BubbleChat = { + name = "BubbleChat", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + CharacterAutoLoads = { + name = "CharacterAutoLoads", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ClassicChat = { + name = "ClassicChat", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + LocalPlayer = { + name = "LocalPlayer", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + MaxPlayers = { + name = "MaxPlayers", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = "MaxPlayersInternal", + scriptability = "Read", + serializes = true, + }, + MaxPlayersInternal = { + name = "MaxPlayersInternal", + type = {type = "Data", name = "Int32"}, + isCanonical = false, + canonicalName = "MaxPlayers", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + NumPlayers = { + name = "NumPlayers", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + PreferredPlayers = { + name = "PreferredPlayers", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = "PreferredPlayersInternal", + scriptability = "Read", + serializes = true, + }, + PreferredPlayersInternal = { + name = "PreferredPlayersInternal", + type = {type = "Data", name = "Int32"}, + isCanonical = false, + canonicalName = "PreferredPlayers", + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + RespawnTime = { + name = "RespawnTime", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + localPlayer = { + name = "localPlayer", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + numPlayers = { + name = "numPlayers", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + CharacterAutoLoads = true, + Name = "Players", + RespawnTime = 5, + }, + }, + Plugin = { + name = "Plugin", + superclass = "Instance", + properties = { + CollisionEnabled = { + name = "CollisionEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + GridSize = { + name = "GridSize", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + HostDataModelType = { + name = "HostDataModelType", + type = {type = "Enum", name = "StudioDataModelType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + HostDataModelTypeIsCurrent = { + name = "HostDataModelTypeIsCurrent", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + MDIInstance = { + name = "MDIInstance", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + UsesAssetInsertionDrag = { + name = "UsesAssetInsertionDrag", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + }, + }, + PluginAction = { + name = "PluginAction", + superclass = "Instance", + properties = { + ActionId = { + name = "ActionId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + AllowBinding = { + name = "AllowBinding", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Checked = { + name = "Checked", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + DefaultShortcut = { + name = "DefaultShortcut", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + StatusTip = { + name = "StatusTip", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Text = { + name = "Text", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + Checked = true, + DefaultShortcut = "", + Enabled = false, + Name = "Instance", + }, + }, + PluginDragEvent = { + name = "PluginDragEvent", + superclass = "Instance", + properties = { + Data = { + name = "Data", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + MimeType = { + name = "MimeType", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Position = { + name = "Position", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Sender = { + name = "Sender", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + PluginGui = { + name = "PluginGui", + superclass = "LayerCollector", + properties = { + Title = { + name = "Title", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + PluginGuiService = { + name = "PluginGuiService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "PluginGuiService", + }, + }, + PluginManager = { + name = "PluginManager", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + PluginMenu = { + name = "PluginMenu", + superclass = "Instance", + properties = { + Icon = { + name = "Icon", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Title = { + name = "Title", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + }, + }, + PluginMouse = { + name = "PluginMouse", + superclass = "Mouse", + properties = { + }, + defaults = { + }, + }, + PluginToolbar = { + name = "PluginToolbar", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + PluginToolbarButton = { + name = "PluginToolbarButton", + superclass = "Instance", + properties = { + ClickableWhenViewportHidden = { + name = "ClickableWhenViewportHidden", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Icon = { + name = "Icon", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + }, + }, + PointLight = { + name = "PointLight", + superclass = "Light", + properties = { + Range = { + name = "Range", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Brightness = 1, + Color = Color3.new(1, 1, 1), + Enabled = true, + Name = "PointLight", + Range = 8, + Shadows = false, + }, + }, + PointsService = { + name = "PointsService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "PointsService", + }, + }, + PolicyService = { + name = "PolicyService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "PolicyService", + }, + }, + Pose = { + name = "Pose", + superclass = "Instance", + properties = { + CFrame = { + name = "CFrame", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + EasingDirection = { + name = "EasingDirection", + type = {type = "Enum", name = "PoseEasingDirection"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + EasingStyle = { + name = "EasingStyle", + type = {type = "Enum", name = "PoseEasingStyle"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaskWeight = { + name = "MaskWeight", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Weight = { + name = "Weight", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + EasingDirection = 0, + EasingStyle = 0, + MaskWeight = 0, + Name = "Pose", + Weight = 1, + }, + }, + PostEffect = { + name = "PostEffect", + superclass = "Instance", + properties = { + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + PrismaticConstraint = { + name = "PrismaticConstraint", + superclass = "SlidingBallConstraint", + properties = { + }, + defaults = { + ActuatorType = 0, + Attachment0 = nil, + Attachment1 = nil, + Color = BrickColor.new(1009), + Enabled = true, + LimitsEnabled = false, + LowerLimit = 0, + MotorMaxAcceleration = 1000000000, + MotorMaxForce = 0, + Name = "PrismaticConstraint", + Restitution = 0, + ServoMaxForce = 0, + Size = 0.15, + Speed = 0, + TargetPosition = 0, + UpperLimit = 5, + Velocity = 0, + Visible = false, + }, + }, + QWidgetPluginGui = { + name = "QWidgetPluginGui", + superclass = "PluginGui", + properties = { + }, + defaults = { + }, + }, + RayValue = { + name = "RayValue", + superclass = "ValueBase", + properties = { + Value = { + name = "Value", + type = {type = "Unimplemented", name = "Ray"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Value", + }, + }, + RbxAnalyticsService = { + name = "RbxAnalyticsService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "RbxAnalyticsService", + }, + }, + ReflectionMetadata = { + name = "ReflectionMetadata", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + ReflectionMetadataCallbacks = { + name = "ReflectionMetadataCallbacks", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + ReflectionMetadataClass = { + name = "ReflectionMetadataClass", + superclass = "ReflectionMetadataItem", + properties = { + ExplorerImageIndex = { + name = "ExplorerImageIndex", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ExplorerOrder = { + name = "ExplorerOrder", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Insertable = { + name = "Insertable", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PreferredParent = { + name = "PreferredParent", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Browsable = true, + ClassCategory = "", + ClientOnly = false, + Constraint = "", + Deprecated = false, + EditingDisabled = false, + ExplorerImageIndex = 0, + ExplorerOrder = 2147483647, + Insertable = true, + IsBackend = false, + Name = "Instance", + PreferredParent = "", + ScriptContext = "", + ServerOnly = false, + UIMaximum = 0, + UIMinimum = 0, + UINumTicks = 0, + summary = "", + }, + }, + ReflectionMetadataClasses = { + name = "ReflectionMetadataClasses", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + ReflectionMetadataEnum = { + name = "ReflectionMetadataEnum", + superclass = "ReflectionMetadataItem", + properties = { + }, + defaults = { + Browsable = true, + ClassCategory = "", + ClientOnly = false, + Constraint = "", + Deprecated = false, + EditingDisabled = false, + IsBackend = false, + Name = "Instance", + ScriptContext = "", + ServerOnly = false, + UIMaximum = 0, + UIMinimum = 0, + UINumTicks = 0, + summary = "", + }, + }, + ReflectionMetadataEnumItem = { + name = "ReflectionMetadataEnumItem", + superclass = "ReflectionMetadataItem", + properties = { + }, + defaults = { + Browsable = true, + ClassCategory = "", + ClientOnly = false, + Constraint = "", + Deprecated = false, + EditingDisabled = false, + IsBackend = false, + Name = "Instance", + ScriptContext = "", + ServerOnly = false, + UIMaximum = 0, + UIMinimum = 0, + UINumTicks = 0, + summary = "", + }, + }, + ReflectionMetadataEnums = { + name = "ReflectionMetadataEnums", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + ReflectionMetadataEvents = { + name = "ReflectionMetadataEvents", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + ReflectionMetadataFunctions = { + name = "ReflectionMetadataFunctions", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + ReflectionMetadataItem = { + name = "ReflectionMetadataItem", + superclass = "Instance", + properties = { + Browsable = { + name = "Browsable", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ClassCategory = { + name = "ClassCategory", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ClientOnly = { + name = "ClientOnly", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Constraint = { + name = "Constraint", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Deprecated = { + name = "Deprecated", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + EditingDisabled = { + name = "EditingDisabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsBackend = { + name = "IsBackend", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ScriptContext = { + name = "ScriptContext", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ServerOnly = { + name = "ServerOnly", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UIMaximum = { + name = "UIMaximum", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UIMinimum = { + name = "UIMinimum", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UINumTicks = { + name = "UINumTicks", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + summary = { + name = "summary", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + ReflectionMetadataMember = { + name = "ReflectionMetadataMember", + superclass = "ReflectionMetadataItem", + properties = { + }, + defaults = { + Browsable = true, + ClassCategory = "", + ClientOnly = false, + Constraint = "", + Deprecated = false, + EditingDisabled = false, + IsBackend = false, + Name = "Instance", + ScriptContext = "", + ServerOnly = false, + UIMaximum = 0, + UIMinimum = 0, + UINumTicks = 0, + summary = "", + }, + }, + ReflectionMetadataProperties = { + name = "ReflectionMetadataProperties", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + ReflectionMetadataYieldFunctions = { + name = "ReflectionMetadataYieldFunctions", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + RemoteEvent = { + name = "RemoteEvent", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "RemoteEvent", + }, + }, + RemoteFunction = { + name = "RemoteFunction", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "RemoteFunction", + }, + }, + RenderSettings = { + name = "RenderSettings", + superclass = "Instance", + properties = { + AutoFRMLevel = { + name = "AutoFRMLevel", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + EagerBulkExecution = { + name = "EagerBulkExecution", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + EditQualityLevel = { + name = "EditQualityLevel", + type = {type = "Enum", name = "QualityLevel"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + EnableFRM = { + name = "EnableFRM", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + ExportMergeByMaterial = { + name = "ExportMergeByMaterial", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FrameRateManager = { + name = "FrameRateManager", + type = {type = "Enum", name = "FramerateManagerMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GraphicsMode = { + name = "GraphicsMode", + type = {type = "Enum", name = "GraphicsMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MeshCacheSize = { + name = "MeshCacheSize", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + QualityLevel = { + name = "QualityLevel", + type = {type = "Enum", name = "QualityLevel"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ReloadAssets = { + name = "ReloadAssets", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RenderCSGTrianglesDebug = { + name = "RenderCSGTrianglesDebug", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ShowBoundingBoxes = { + name = "ShowBoundingBoxes", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + RenderingTest = { + name = "RenderingTest", + superclass = "Instance", + properties = { + CFrame = { + name = "CFrame", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ComparisonDiffThreshold = { + name = "ComparisonDiffThreshold", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ComparisonMethod = { + name = "ComparisonMethod", + type = {type = "Enum", name = "RenderingTestComparisonMethod"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ComparisonPsnrThreshold = { + name = "ComparisonPsnrThreshold", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Description = { + name = "Description", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FieldOfView = { + name = "FieldOfView", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Orientation = { + name = "Orientation", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Position = { + name = "Position", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + QualityLevel = { + name = "QualityLevel", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ShouldSkip = { + name = "ShouldSkip", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Ticket = { + name = "Ticket", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + ComparisonDiffThreshold = 10, + ComparisonMethod = 0, + ComparisonPsnrThreshold = 50, + Description = "", + FieldOfView = 70, + Name = "RenderingTest", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + QualityLevel = 21, + ShouldSkip = false, + Ticket = "", + }, + }, + ReplicatedFirst = { + name = "ReplicatedFirst", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "ReplicatedFirst", + }, + }, + ReplicatedStorage = { + name = "ReplicatedStorage", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "ReplicatedStorage", + }, + }, + ReverbSoundEffect = { + name = "ReverbSoundEffect", + superclass = "SoundEffect", + properties = { + DecayTime = { + name = "DecayTime", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Density = { + name = "Density", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Diffusion = { + name = "Diffusion", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DryLevel = { + name = "DryLevel", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WetLevel = { + name = "WetLevel", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + DecayTime = 1.5, + Density = 1, + Diffusion = 1, + DryLevel = -6, + Enabled = true, + Name = "ReverbSoundEffect", + Priority = 0, + WetLevel = 0, + }, + }, + RobloxPluginGuiService = { + name = "RobloxPluginGuiService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "RobloxPluginGuiService", + }, + }, + RobloxReplicatedStorage = { + name = "RobloxReplicatedStorage", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "RobloxReplicatedStorage", + }, + }, + RocketPropulsion = { + name = "RocketPropulsion", + superclass = "BodyMover", + properties = { + CartoonFactor = { + name = "CartoonFactor", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxSpeed = { + name = "MaxSpeed", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxThrust = { + name = "MaxThrust", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxTorque = { + name = "MaxTorque", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Target = { + name = "Target", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TargetOffset = { + name = "TargetOffset", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TargetRadius = { + name = "TargetRadius", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ThrustD = { + name = "ThrustD", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ThrustP = { + name = "ThrustP", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TurnD = { + name = "TurnD", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TurnP = { + name = "TurnP", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + CartoonFactor = 0.7, + MaxSpeed = 30, + MaxThrust = 4000, + MaxTorque = Vector3.new(400000, 400000, 0), + Name = "RocketPropulsion", + Target = nil, + TargetOffset = Vector3.new(0, 0, 0), + TargetRadius = 4, + ThrustD = 0.001, + ThrustP = 5, + TurnD = 500, + TurnP = 3000, + }, + }, + RodConstraint = { + name = "RodConstraint", + superclass = "Constraint", + properties = { + CurrentDistance = { + name = "CurrentDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Length = { + name = "Length", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Thickness = { + name = "Thickness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Attachment0 = nil, + Attachment1 = nil, + Color = BrickColor.new(26), + Enabled = true, + Length = 5, + Name = "RodConstraint", + Thickness = 0.1, + Visible = false, + }, + }, + RopeConstraint = { + name = "RopeConstraint", + superclass = "Constraint", + properties = { + CurrentDistance = { + name = "CurrentDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Length = { + name = "Length", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Restitution = { + name = "Restitution", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Thickness = { + name = "Thickness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Attachment0 = nil, + Attachment1 = nil, + Color = BrickColor.new(25), + Enabled = true, + Length = 5, + Name = "RopeConstraint", + Restitution = 0, + Thickness = 0.1, + Visible = false, + }, + }, + Rotate = { + name = "Rotate", + superclass = "JointInstance", + properties = { + }, + defaults = { + C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Name = "Rotate", + Part0 = nil, + Part1 = nil, + }, + }, + RotateP = { + name = "RotateP", + superclass = "DynamicRotate", + properties = { + }, + defaults = { + BaseAngle = 0, + C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Name = "RotateP", + Part0 = nil, + Part1 = nil, + }, + }, + RotateV = { + name = "RotateV", + superclass = "DynamicRotate", + properties = { + }, + defaults = { + BaseAngle = 0, + C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Name = "RotateV", + Part0 = nil, + Part1 = nil, + }, + }, + RunService = { + name = "RunService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Run Service", + }, + }, + RunningAverageItemDouble = { + name = "RunningAverageItemDouble", + superclass = "StatsItem", + properties = { + }, + defaults = { + }, + }, + RunningAverageItemInt = { + name = "RunningAverageItemInt", + superclass = "StatsItem", + properties = { + }, + defaults = { + }, + }, + RunningAverageTimeIntervalItem = { + name = "RunningAverageTimeIntervalItem", + superclass = "StatsItem", + properties = { + }, + defaults = { + }, + }, + RuntimeScriptService = { + name = "RuntimeScriptService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + ScreenGui = { + name = "ScreenGui", + superclass = "LayerCollector", + properties = { + DisplayOrder = { + name = "DisplayOrder", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IgnoreGuiInset = { + name = "IgnoreGuiInset", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + OnTopOfCoreBlur = { + name = "OnTopOfCoreBlur", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + AutoLocalize = true, + DisplayOrder = 0, + Enabled = true, + IgnoreGuiInset = false, + Localize = true, + Name = "ScreenGui", + OnTopOfCoreBlur = false, + ResetOnSpawn = true, + RootLocalizationTable = nil, + ZIndexBehavior = 0, + }, + }, + Script = { + name = "Script", + superclass = "BaseScript", + properties = { + Source = { + name = "Source", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Disabled = false, + LinkedSource = "", + Name = "Script", + Source = "", + }, + }, + ScriptContext = { + name = "ScriptContext", + superclass = "Instance", + properties = { + ScriptsDisabled = { + name = "ScriptsDisabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + Name = "Script Context", + }, + }, + ScriptDebugger = { + name = "ScriptDebugger", + superclass = "Instance", + properties = { + CurrentLine = { + name = "CurrentLine", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsDebugging = { + name = "IsDebugging", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsPaused = { + name = "IsPaused", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Script = { + name = "Script", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + ScriptService = { + name = "ScriptService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + ScrollingFrame = { + name = "ScrollingFrame", + superclass = "GuiObject", + properties = { + AbsoluteWindowSize = { + name = "AbsoluteWindowSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + BottomImage = { + name = "BottomImage", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CanvasPosition = { + name = "CanvasPosition", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CanvasSize = { + name = "CanvasSize", + type = {type = "Data", name = "UDim2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ElasticBehavior = { + name = "ElasticBehavior", + type = {type = "Enum", name = "ElasticBehavior"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HorizontalScrollBarInset = { + name = "HorizontalScrollBarInset", + type = {type = "Enum", name = "ScrollBarInset"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MidImage = { + name = "MidImage", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ScrollBarImageColor3 = { + name = "ScrollBarImageColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ScrollBarImageTransparency = { + name = "ScrollBarImageTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ScrollBarThickness = { + name = "ScrollBarThickness", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ScrollingDirection = { + name = "ScrollingDirection", + type = {type = "Enum", name = "ScrollingDirection"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ScrollingEnabled = { + name = "ScrollingEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TopImage = { + name = "TopImage", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + VerticalScrollBarInset = { + name = "VerticalScrollBarInset", + type = {type = "Enum", name = "ScrollBarInset"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + VerticalScrollBarPosition = { + name = "VerticalScrollBarPosition", + type = {type = "Enum", name = "VerticalScrollBarPosition"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Active = false, + AnchorPoint = Vector2.new(0, 0), + AutoLocalize = true, + BackgroundColor = BrickColor.new(194), + BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), + BackgroundTransparency = 0, + BorderColor = BrickColor.new(26), + BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), + BorderMode = 0, + BorderSizePixel = 1, + BottomImage = "rbxasset://textures/ui/Scroll/scroll-bottom.png", + CanvasPosition = Vector2.new(0, 0), + CanvasSize = UDim2.new(0, 0, 2, 0), + ClipsDescendants = true, + Draggable = false, + ElasticBehavior = 0, + HorizontalScrollBarInset = 0, + LayoutOrder = 0, + Localize = true, + MidImage = "rbxasset://textures/ui/Scroll/scroll-middle.png", + Name = "ScrollingFrame", + NextSelectionDown = nil, + NextSelectionLeft = nil, + NextSelectionRight = nil, + NextSelectionUp = nil, + Position = UDim2.new(0, 0, 0, 0), + RootLocalizationTable = nil, + Rotation = 0, + ScrollBarImageColor3 = Color3.new(1, 1, 1), + ScrollBarImageTransparency = 0, + ScrollBarThickness = 12, + ScrollingDirection = 4, + ScrollingEnabled = true, + Selectable = true, + SelectionImageObject = nil, + Size = UDim2.new(0, 0, 0, 0), + SizeConstraint = 0, + TopImage = "rbxasset://textures/ui/Scroll/scroll-top.png", + Transparency = 0, + VerticalScrollBarInset = 0, + VerticalScrollBarPosition = 0, + Visible = true, + ZIndex = 1, + }, + }, + Seat = { + name = "Seat", + superclass = "Part", + properties = { + Disabled = { + name = "Disabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Occupant = { + name = "Occupant", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + Anchored = false, + BackParamA = -0.5, + BackParamB = 0.5, + BackSurface = 0, + BackSurfaceInput = 0, + BottomParamA = -0.5, + BottomParamB = 0.5, + BottomSurface = 4, + BottomSurfaceInput = 0, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CanCollide = true, + CastShadow = true, + CollisionGroupId = 0, + Color = Color3.new(0.6392157, 0.63529414, 0.64705884), + CustomPhysicalProperties = nil, + Disabled = false, + Elasticity = 0.5, + FormFactor = 1, + Friction = 0.3, + FrontParamA = -0.5, + FrontParamB = 0.5, + FrontSurface = 0, + FrontSurfaceInput = 0, + LeftParamA = -0.5, + LeftParamB = 0.5, + LeftSurface = 0, + LeftSurfaceInput = 0, + LocalTransparencyModifier = 0, + Locked = false, + Massless = false, + Material = 256, + Name = "Seat", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Reflectance = 0, + RightParamA = -0.5, + RightParamB = 0.5, + RightSurface = 0, + RightSurfaceInput = 0, + RootPriority = 0, + RotVelocity = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + Shape = 1, + Size = Vector3.new(4, 1.2, 2), + TopParamA = -0.5, + TopParamB = 0.5, + TopSurface = 3, + TopSurfaceInput = 0, + Transparency = 0, + Velocity = Vector3.new(0, 0, 0), + }, + }, + Selection = { + name = "Selection", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Selection", + }, + }, + SelectionBox = { + name = "SelectionBox", + superclass = "PVAdornment", + properties = { + LineThickness = { + name = "LineThickness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SurfaceColor = { + name = "SurfaceColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + SurfaceColor3 = { + name = "SurfaceColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SurfaceTransparency = { + name = "SurfaceTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Adornee = nil, + Color = BrickColor.new(23), + Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + LineThickness = 0.15, + Name = "SelectionBox", + SurfaceColor = BrickColor.new(23), + SurfaceColor3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + SurfaceTransparency = 1, + Transparency = 0, + Visible = true, + }, + }, + SelectionLasso = { + name = "SelectionLasso", + superclass = "GuiBase3d", + properties = { + Humanoid = { + name = "Humanoid", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + SelectionPartLasso = { + name = "SelectionPartLasso", + superclass = "SelectionLasso", + properties = { + Part = { + name = "Part", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Color = BrickColor.new(23), + Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + Humanoid = nil, + Name = "SelectionPartLasso", + Part = nil, + Transparency = 0, + Visible = true, + }, + }, + SelectionPointLasso = { + name = "SelectionPointLasso", + superclass = "SelectionLasso", + properties = { + Point = { + name = "Point", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Color = BrickColor.new(23), + Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + Humanoid = nil, + Name = "SelectionPointLasso", + Point = Vector3.new(0, 0, 0), + Transparency = 0, + Visible = true, + }, + }, + SelectionSphere = { + name = "SelectionSphere", + superclass = "PVAdornment", + properties = { + SurfaceColor = { + name = "SurfaceColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + SurfaceColor3 = { + name = "SurfaceColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SurfaceTransparency = { + name = "SurfaceTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Adornee = nil, + Color = BrickColor.new(23), + Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + Name = "SelectionSphere", + SurfaceColor = BrickColor.new(23), + SurfaceColor3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + SurfaceTransparency = 1, + Transparency = 0, + Visible = true, + }, + }, + ServerReplicator = { + name = "ServerReplicator", + superclass = "NetworkReplicator", + properties = { + }, + defaults = { + }, + }, + ServerScriptService = { + name = "ServerScriptService", + superclass = "Instance", + properties = { + LoadStringEnabled = { + name = "LoadStringEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + }, + defaults = { + Name = "ServerScriptService", + }, + }, + ServerStorage = { + name = "ServerStorage", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "ServerStorage", + }, + }, + ServiceProvider = { + name = "ServiceProvider", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + Shirt = { + name = "Shirt", + superclass = "Clothing", + properties = { + ShirtTemplate = { + name = "ShirtTemplate", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Color3 = Color3.new(1, 1, 1), + Name = "Clothing", + ShirtTemplate = "", + }, + }, + ShirtGraphic = { + name = "ShirtGraphic", + superclass = "CharacterAppearance", + properties = { + Color3 = { + name = "Color3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Graphic = { + name = "Graphic", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Color3 = Color3.new(1, 1, 1), + Graphic = "", + Name = "Shirt Graphic", + }, + }, + SkateboardController = { + name = "SkateboardController", + superclass = "Controller", + properties = { + Steer = { + name = "Steer", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Throttle = { + name = "Throttle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + Name = "SkateboardController", + }, + }, + SkateboardPlatform = { + name = "SkateboardPlatform", + superclass = "Part", + properties = { + Controller = { + name = "Controller", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ControllingHumanoid = { + name = "ControllingHumanoid", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Steer = { + name = "Steer", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + StickyWheels = { + name = "StickyWheels", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Throttle = { + name = "Throttle", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Anchored = false, + BackParamA = -0.5, + BackParamB = 0.5, + BackSurface = 0, + BackSurfaceInput = 0, + BottomParamA = -0.5, + BottomParamB = 0.5, + BottomSurface = 4, + BottomSurfaceInput = 0, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CanCollide = true, + CastShadow = true, + CollisionGroupId = 0, + Color = Color3.new(0.6392157, 0.63529414, 0.64705884), + CustomPhysicalProperties = nil, + Elasticity = 0.5, + FormFactor = 1, + Friction = 0.3, + FrontParamA = -0.5, + FrontParamB = 0.5, + FrontSurface = 0, + FrontSurfaceInput = 0, + LeftParamA = -0.5, + LeftParamB = 0.5, + LeftSurface = 0, + LeftSurfaceInput = 0, + LocalTransparencyModifier = 0, + Locked = false, + Massless = false, + Material = 256, + Name = "SkateboardPlatform", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Reflectance = 0, + RightParamA = -0.5, + RightParamB = 0.5, + RightSurface = 0, + RightSurfaceInput = 0, + RootPriority = 0, + RotVelocity = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + Shape = 1, + Size = Vector3.new(4, 1.2, 2), + Steer = 0, + StickyWheels = true, + Throttle = 0, + TopParamA = -0.5, + TopParamB = 0.5, + TopSurface = 3, + TopSurfaceInput = 0, + Transparency = 0, + Velocity = Vector3.new(0, 0, 0), + }, + }, + Skin = { + name = "Skin", + superclass = "CharacterAppearance", + properties = { + SkinColor = { + name = "SkinColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Skin", + SkinColor = BrickColor.new(226), + }, + }, + Sky = { + name = "Sky", + superclass = "Instance", + properties = { + CelestialBodiesShown = { + name = "CelestialBodiesShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MoonAngularSize = { + name = "MoonAngularSize", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MoonTextureId = { + name = "MoonTextureId", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SkyboxBk = { + name = "SkyboxBk", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SkyboxDn = { + name = "SkyboxDn", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SkyboxFt = { + name = "SkyboxFt", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SkyboxLf = { + name = "SkyboxLf", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SkyboxRt = { + name = "SkyboxRt", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SkyboxUp = { + name = "SkyboxUp", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + StarCount = { + name = "StarCount", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SunAngularSize = { + name = "SunAngularSize", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SunTextureId = { + name = "SunTextureId", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + CelestialBodiesShown = true, + MoonAngularSize = 11, + MoonTextureId = "rbxasset://sky/moon.jpg", + Name = "Sky", + SkyboxBk = "rbxasset://textures/sky/sky512_bk.tex", + SkyboxDn = "rbxasset://textures/sky/sky512_dn.tex", + SkyboxFt = "rbxasset://textures/sky/sky512_ft.tex", + SkyboxLf = "rbxasset://textures/sky/sky512_lf.tex", + SkyboxRt = "rbxasset://textures/sky/sky512_rt.tex", + SkyboxUp = "rbxasset://textures/sky/sky512_up.tex", + StarCount = 3000, + SunAngularSize = 21, + SunTextureId = "rbxasset://sky/sun.jpg", + }, + }, + SlidingBallConstraint = { + name = "SlidingBallConstraint", + superclass = "Constraint", + properties = { + ActuatorType = { + name = "ActuatorType", + type = {type = "Enum", name = "ActuatorType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CurrentPosition = { + name = "CurrentPosition", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + LimitsEnabled = { + name = "LimitsEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LowerLimit = { + name = "LowerLimit", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MotorMaxAcceleration = { + name = "MotorMaxAcceleration", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MotorMaxForce = { + name = "MotorMaxForce", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Restitution = { + name = "Restitution", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ServoMaxForce = { + name = "ServoMaxForce", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Size = { + name = "Size", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Speed = { + name = "Speed", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TargetPosition = { + name = "TargetPosition", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UpperLimit = { + name = "UpperLimit", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Velocity = { + name = "Velocity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + Smoke = { + name = "Smoke", + superclass = "Instance", + properties = { + Color = { + name = "Color", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Opacity = { + name = "Opacity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = "opacity_xml", + scriptability = "ReadWrite", + serializes = true, + }, + RiseVelocity = { + name = "RiseVelocity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = "riseVelocity_xml", + scriptability = "ReadWrite", + serializes = true, + }, + Size = { + name = "Size", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = "size_xml", + scriptability = "ReadWrite", + serializes = true, + }, + opacity_xml = { + name = "opacity_xml", + type = {type = "Data", name = "Float32"}, + isCanonical = false, + canonicalName = "Opacity", + serializedName = nil, + scriptability = "None", + serializes = false, + }, + riseVelocity_xml = { + name = "riseVelocity_xml", + type = {type = "Data", name = "Float32"}, + isCanonical = false, + canonicalName = "RiseVelocity", + serializedName = nil, + scriptability = "None", + serializes = false, + }, + size_xml = { + name = "size_xml", + type = {type = "Data", name = "Float32"}, + isCanonical = false, + canonicalName = "Size", + serializedName = nil, + scriptability = "None", + serializes = false, + }, + }, + defaults = { + Color = Color3.new(1, 1, 1), + Enabled = true, + Name = "Smoke", + Opacity = 0.5, + RiseVelocity = 1, + Size = 1, + }, + }, + Snap = { + name = "Snap", + superclass = "JointInstance", + properties = { + }, + defaults = { + C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Name = "Snap", + Part0 = nil, + Part1 = nil, + }, + }, + SocialService = { + name = "SocialService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "SocialService", + }, + }, + SolidModelContentProvider = { + name = "SolidModelContentProvider", + superclass = "CacheableContentProvider", + properties = { + }, + defaults = { + Name = "SolidModelContentProvider", + }, + }, + Sound = { + name = "Sound", + superclass = "Instance", + properties = { + EmitterSize = { + name = "EmitterSize", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsLoaded = { + name = "IsLoaded", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsPaused = { + name = "IsPaused", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsPlaying = { + name = "IsPlaying", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Looped = { + name = "Looped", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxDistance = { + name = "MaxDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = "xmlRead_MaxDistance_3", + scriptability = "ReadWrite", + serializes = true, + }, + MinDistance = { + name = "MinDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Pitch = { + name = "Pitch", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + PlayOnRemove = { + name = "PlayOnRemove", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PlaybackLoudness = { + name = "PlaybackLoudness", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + PlaybackSpeed = { + name = "PlaybackSpeed", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Playing = { + name = "Playing", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RollOffMode = { + name = "RollOffMode", + type = {type = "Enum", name = "RollOffMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SoundGroup = { + name = "SoundGroup", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SoundId = { + name = "SoundId", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TimeLength = { + name = "TimeLength", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TimePosition = { + name = "TimePosition", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Volume = { + name = "Volume", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + isPlaying = { + name = "isPlaying", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + xmlRead_MaxDistance_3 = { + name = "xmlRead_MaxDistance_3", + type = {type = "Data", name = "Float32"}, + isCanonical = false, + canonicalName = "MaxDistance", + serializedName = nil, + scriptability = "None", + serializes = false, + }, + }, + defaults = { + EmitterSize = 10, + Looped = false, + MaxDistance = 10000, + MinDistance = 10, + Name = "Sound", + Pitch = 1, + PlayOnRemove = false, + PlaybackSpeed = 1, + Playing = false, + RollOffMode = 0, + SoundGroup = nil, + SoundId = "", + TimePosition = 0, + Volume = 0.5, + }, + }, + SoundEffect = { + name = "SoundEffect", + superclass = "Instance", + properties = { + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Priority = { + name = "Priority", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + SoundGroup = { + name = "SoundGroup", + superclass = "Instance", + properties = { + Volume = { + name = "Volume", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "SoundGroup", + Volume = 0.5, + }, + }, + SoundService = { + name = "SoundService", + superclass = "Instance", + properties = { + AmbientReverb = { + name = "AmbientReverb", + type = {type = "Enum", name = "ReverbType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DistanceFactor = { + name = "DistanceFactor", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DopplerScale = { + name = "DopplerScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RespectFilteringEnabled = { + name = "RespectFilteringEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RolloffScale = { + name = "RolloffScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + AmbientReverb = 0, + DistanceFactor = 3.33, + DopplerScale = 1, + Name = "SoundService", + RespectFilteringEnabled = false, + RolloffScale = 1, + }, + }, + Sparkles = { + name = "Sparkles", + superclass = "Instance", + properties = { + Color = { + name = "Color", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SparkleColor = { + name = "SparkleColor", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Color = Color3.new(1, 1.0000001, 1), + Enabled = true, + Name = "Sparkles", + SparkleColor = Color3.new(0.5647059, 0.09803923, 1), + }, + }, + SpawnLocation = { + name = "SpawnLocation", + superclass = "Part", + properties = { + AllowTeamChangeOnTouch = { + name = "AllowTeamChangeOnTouch", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Duration = { + name = "Duration", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Neutral = { + name = "Neutral", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TeamColor = { + name = "TeamColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + AllowTeamChangeOnTouch = false, + Anchored = false, + BackParamA = -0.5, + BackParamB = 0.5, + BackSurface = 0, + BackSurfaceInput = 0, + BottomParamA = -0.5, + BottomParamB = 0.5, + BottomSurface = 4, + BottomSurfaceInput = 0, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CanCollide = true, + CastShadow = true, + CollisionGroupId = 0, + Color = Color3.new(0.6392157, 0.63529414, 0.64705884), + CustomPhysicalProperties = nil, + Duration = 10, + Elasticity = 0.5, + Enabled = true, + FormFactor = 1, + Friction = 0.3, + FrontParamA = -0.5, + FrontParamB = 0.5, + FrontSurface = 0, + FrontSurfaceInput = 0, + LeftParamA = -0.5, + LeftParamB = 0.5, + LeftSurface = 0, + LeftSurfaceInput = 0, + LocalTransparencyModifier = 0, + Locked = false, + Massless = false, + Material = 256, + Name = "SpawnLocation", + Neutral = true, + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Reflectance = 0, + RightParamA = -0.5, + RightParamB = 0.5, + RightSurface = 0, + RightSurfaceInput = 0, + RootPriority = 0, + RotVelocity = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + Shape = 1, + Size = Vector3.new(4, 1.2, 2), + TeamColor = BrickColor.new(194), + TopParamA = -0.5, + TopParamB = 0.5, + TopSurface = 3, + TopSurfaceInput = 0, + Transparency = 0, + Velocity = Vector3.new(0, 0, 0), + }, + }, + SpawnerService = { + name = "SpawnerService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + SpecialMesh = { + name = "SpecialMesh", + superclass = "FileMesh", + properties = { + MeshType = { + name = "MeshType", + type = {type = "Enum", name = "MeshType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + MeshId = "", + MeshType = 0, + Name = "Mesh", + Offset = Vector3.new(0, 0, 0), + Scale = Vector3.new(1, 1, 1), + TextureId = "", + VertexColor = Vector3.new(1, 1, 1), + }, + }, + SphereHandleAdornment = { + name = "SphereHandleAdornment", + superclass = "HandleAdornment", + properties = { + Radius = { + name = "Radius", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Adornee = nil, + AlwaysOnTop = false, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Color = BrickColor.new(23), + Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + Name = "SphereHandleAdornment", + Radius = 1, + SizeRelativeOffset = Vector3.new(0, 0, 0), + Transparency = 0, + Visible = true, + ZIndex = -1, + }, + }, + SpotLight = { + name = "SpotLight", + superclass = "Light", + properties = { + Angle = { + name = "Angle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Face = { + name = "Face", + type = {type = "Enum", name = "NormalId"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Range = { + name = "Range", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Angle = 90, + Brightness = 1, + Color = Color3.new(1, 1, 1), + Enabled = true, + Face = 5, + Name = "SpotLight", + Range = 16, + Shadows = false, + }, + }, + SpringConstraint = { + name = "SpringConstraint", + superclass = "Constraint", + properties = { + Coils = { + name = "Coils", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CurrentLength = { + name = "CurrentLength", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Damping = { + name = "Damping", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FreeLength = { + name = "FreeLength", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LimitsEnabled = { + name = "LimitsEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxForce = { + name = "MaxForce", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxLength = { + name = "MaxLength", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MinLength = { + name = "MinLength", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Radius = { + name = "Radius", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Stiffness = { + name = "Stiffness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Thickness = { + name = "Thickness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Attachment0 = nil, + Attachment1 = nil, + Coils = 3, + Color = BrickColor.new(200), + Damping = 0, + Enabled = true, + FreeLength = 1, + LimitsEnabled = false, + MaxForce = 1000000000, + MaxLength = 5, + MinLength = 0, + Name = "SpringConstraint", + Radius = 0.4, + Stiffness = 0, + Thickness = 0.1, + Visible = false, + }, + }, + StandalonePluginScripts = { + name = "StandalonePluginScripts", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "StandalonePluginScripts", + }, + }, + StandardPages = { + name = "StandardPages", + superclass = "Pages", + properties = { + }, + defaults = { + }, + }, + StarterCharacterScripts = { + name = "StarterCharacterScripts", + superclass = "StarterPlayerScripts", + properties = { + }, + defaults = { + }, + }, + StarterGear = { + name = "StarterGear", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "StarterGear", + }, + }, + StarterGui = { + name = "StarterGui", + superclass = "BasePlayerGui", + properties = { + ProcessUserInput = { + name = "ProcessUserInput", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + ResetPlayerGuiOnSpawn = { + name = "ResetPlayerGuiOnSpawn", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ScreenOrientation = { + name = "ScreenOrientation", + type = {type = "Enum", name = "ScreenOrientation"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ShowDevelopmentGui = { + name = "ShowDevelopmentGui", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "StarterGui", + ProcessUserInput = true, + ResetPlayerGuiOnSpawn = true, + ScreenOrientation = 2, + ShowDevelopmentGui = true, + }, + }, + StarterPack = { + name = "StarterPack", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "StarterPack", + }, + }, + StarterPlayer = { + name = "StarterPlayer", + superclass = "Instance", + properties = { + AllowCustomAnimations = { + name = "AllowCustomAnimations", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AutoJumpEnabled = { + name = "AutoJumpEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CameraMaxZoomDistance = { + name = "CameraMaxZoomDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CameraMinZoomDistance = { + name = "CameraMinZoomDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CameraMode = { + name = "CameraMode", + type = {type = "Enum", name = "CameraMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CharacterJumpHeight = { + name = "CharacterJumpHeight", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CharacterJumpPower = { + name = "CharacterJumpPower", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CharacterMaxSlopeAngle = { + name = "CharacterMaxSlopeAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CharacterUseJumpPower = { + name = "CharacterUseJumpPower", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CharacterWalkSpeed = { + name = "CharacterWalkSpeed", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DevCameraOcclusionMode = { + name = "DevCameraOcclusionMode", + type = {type = "Enum", name = "DevCameraOcclusionMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DevComputerCameraMovementMode = { + name = "DevComputerCameraMovementMode", + type = {type = "Enum", name = "DevComputerCameraMovementMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DevComputerMovementMode = { + name = "DevComputerMovementMode", + type = {type = "Enum", name = "DevComputerMovementMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DevTouchCameraMovementMode = { + name = "DevTouchCameraMovementMode", + type = {type = "Enum", name = "DevTouchCameraMovementMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DevTouchMovementMode = { + name = "DevTouchMovementMode", + type = {type = "Enum", name = "DevTouchMovementMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + EnableMouseLockOption = { + name = "EnableMouseLockOption", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsAssetIDFace = { + name = "GameSettingsAssetIDFace", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsAssetIDHead = { + name = "GameSettingsAssetIDHead", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsAssetIDLeftArm = { + name = "GameSettingsAssetIDLeftArm", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsAssetIDLeftLeg = { + name = "GameSettingsAssetIDLeftLeg", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsAssetIDPants = { + name = "GameSettingsAssetIDPants", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsAssetIDRightArm = { + name = "GameSettingsAssetIDRightArm", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsAssetIDRightLeg = { + name = "GameSettingsAssetIDRightLeg", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsAssetIDShirt = { + name = "GameSettingsAssetIDShirt", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsAssetIDTeeShirt = { + name = "GameSettingsAssetIDTeeShirt", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsAssetIDTorso = { + name = "GameSettingsAssetIDTorso", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsAvatar = { + name = "GameSettingsAvatar", + type = {type = "Enum", name = "GameAvatarType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsR15Collision = { + name = "GameSettingsR15Collision", + type = {type = "Enum", name = "R15CollisionType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsScaleRangeBodyType = { + name = "GameSettingsScaleRangeBodyType", + type = {type = "Data", name = "NumberRange"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsScaleRangeHead = { + name = "GameSettingsScaleRangeHead", + type = {type = "Data", name = "NumberRange"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsScaleRangeHeight = { + name = "GameSettingsScaleRangeHeight", + type = {type = "Data", name = "NumberRange"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsScaleRangeProportion = { + name = "GameSettingsScaleRangeProportion", + type = {type = "Data", name = "NumberRange"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GameSettingsScaleRangeWidth = { + name = "GameSettingsScaleRangeWidth", + type = {type = "Data", name = "NumberRange"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HealthDisplayDistance = { + name = "HealthDisplayDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LoadCharacterAppearance = { + name = "LoadCharacterAppearance", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NameDisplayDistance = { + name = "NameDisplayDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UserEmotesEnabled = { + name = "UserEmotesEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + AllowCustomAnimations = true, + AutoJumpEnabled = true, + CameraMaxZoomDistance = 400, + CameraMinZoomDistance = 0.5, + CameraMode = 0, + CharacterJumpHeight = 7.2, + CharacterJumpPower = 50, + CharacterMaxSlopeAngle = 89, + CharacterUseJumpPower = true, + CharacterWalkSpeed = 16, + DevCameraOcclusionMode = 0, + DevComputerCameraMovementMode = 0, + DevComputerMovementMode = 0, + DevTouchCameraMovementMode = 0, + DevTouchMovementMode = 0, + EnableMouseLockOption = true, + GameSettingsAssetIDFace = 0, + GameSettingsAssetIDHead = 0, + GameSettingsAssetIDLeftArm = 0, + GameSettingsAssetIDLeftLeg = 0, + GameSettingsAssetIDPants = 0, + GameSettingsAssetIDRightArm = 0, + GameSettingsAssetIDRightLeg = 0, + GameSettingsAssetIDShirt = 0, + GameSettingsAssetIDTeeShirt = 0, + GameSettingsAssetIDTorso = 0, + GameSettingsAvatar = 1, + GameSettingsR15Collision = 0, + GameSettingsScaleRangeBodyType = NumberRange.new(0, 1), + GameSettingsScaleRangeHead = NumberRange.new(0.95, 1), + GameSettingsScaleRangeHeight = NumberRange.new(0.9, 1.05), + GameSettingsScaleRangeProportion = NumberRange.new(0, 1), + GameSettingsScaleRangeWidth = NumberRange.new(0.7, 1), + HealthDisplayDistance = 100, + LoadCharacterAppearance = true, + Name = "StarterPlayer", + NameDisplayDistance = 100, + UserEmotesEnabled = true, + }, + }, + StarterPlayerScripts = { + name = "StarterPlayerScripts", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + Stats = { + name = "Stats", + superclass = "Instance", + properties = { + ContactsCount = { + name = "ContactsCount", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + DataReceiveKbps = { + name = "DataReceiveKbps", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + DataSendKbps = { + name = "DataSendKbps", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + HeartbeatTimeMs = { + name = "HeartbeatTimeMs", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + InstanceCount = { + name = "InstanceCount", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + MovingPrimitivesCount = { + name = "MovingPrimitivesCount", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + PhysicsReceiveKbps = { + name = "PhysicsReceiveKbps", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + PhysicsSendKbps = { + name = "PhysicsSendKbps", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + PhysicsStepTimeMs = { + name = "PhysicsStepTimeMs", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + PrimitivesCount = { + name = "PrimitivesCount", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + Name = "Stats", + }, + }, + StatsItem = { + name = "StatsItem", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + Status = { + name = "Status", + superclass = "Model", + properties = { + }, + defaults = { + }, + }, + StopWatchReporter = { + name = "StopWatchReporter", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + StringValue = { + name = "StringValue", + superclass = "ValueBase", + properties = { + Value = { + name = "Value", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Value", + Value = "", + }, + }, + Studio = { + name = "Studio", + superclass = "Instance", + properties = { + DefaultScriptFileDir = { + name = "DefaultScriptFileDir", + type = {type = "Unimplemented", name = "QDir"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DeprecatedObjectsShown = { + name = "DeprecatedObjectsShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Font = { + name = "Font", + type = {type = "Unimplemented", name = "QFont"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Language = { + name = "Language", + type = {type = "Enum", name = "LanguagePreference"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LuaDebuggerEnabled = { + name = "LuaDebuggerEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LuaDebuggerEnabledAtStartup = { + name = "LuaDebuggerEnabledAtStartup", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + OverrideCoreScripts = { + name = "OverrideCoreScripts", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + OverrideCoreScriptsDir = { + name = "OverrideCoreScriptsDir", + type = {type = "Unimplemented", name = "QDir"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PermissionLevelShown = { + name = "PermissionLevelShown", + type = {type = "Enum", name = "PermissionLevelShown"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PluginsDir = { + name = "PluginsDir", + type = {type = "Unimplemented", name = "QDir"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RecentSavesDir = { + name = "RecentSavesDir", + type = {type = "Unimplemented", name = "QDir"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RuntimeUndoBehavior = { + name = "RuntimeUndoBehavior", + type = {type = "Enum", name = "RuntimeUndoBehavior"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ScriptTimeoutLength = { + name = "ScriptTimeoutLength", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Theme = { + name = "Theme", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + }, + }, + StudioData = { + name = "StudioData", + superclass = "Instance", + properties = { + SrcPlaceId = { + name = "SrcPlaceId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SrcUniverseId = { + name = "SrcUniverseId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + StudioService = { + name = "StudioService", + superclass = "Instance", + properties = { + ActiveScript = { + name = "ActiveScript", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + GridSize = { + name = "GridSize", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + InstalledPluginData = { + name = "InstalledPluginData", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + RotateIncrement = { + name = "RotateIncrement", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + StudioLocaleId = { + name = "StudioLocaleId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + UseLocalSpace = { + name = "UseLocalSpace", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + Name = "StudioService", + UseLocalSpace = true, + }, + }, + StudioTheme = { + name = "StudioTheme", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + SunRaysEffect = { + name = "SunRaysEffect", + superclass = "PostEffect", + properties = { + Intensity = { + name = "Intensity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Spread = { + name = "Spread", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Enabled = true, + Intensity = 0.25, + Name = "SunRays", + Spread = 1, + }, + }, + SurfaceGui = { + name = "SurfaceGui", + superclass = "LayerCollector", + properties = { + Active = { + name = "Active", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Adornee = { + name = "Adornee", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AlwaysOnTop = { + name = "AlwaysOnTop", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CanvasSize = { + name = "CanvasSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ClipsDescendants = { + name = "ClipsDescendants", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Face = { + name = "Face", + type = {type = "Enum", name = "NormalId"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LightInfluence = { + name = "LightInfluence", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PixelsPerStud = { + name = "PixelsPerStud", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SizingMode = { + name = "SizingMode", + type = {type = "Enum", name = "SurfaceGuiSizingMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ToolPunchThroughDistance = { + name = "ToolPunchThroughDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ZOffset = { + name = "ZOffset", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Active = true, + Adornee = nil, + AlwaysOnTop = false, + AutoLocalize = true, + CanvasSize = Vector2.new(800, 600), + ClipsDescendants = false, + Enabled = true, + Face = 5, + LightInfluence = 0, + Localize = true, + Name = "SurfaceGui", + PixelsPerStud = 50, + ResetOnSpawn = true, + RootLocalizationTable = nil, + SizingMode = 0, + ToolPunchThroughDistance = 0, + ZIndexBehavior = 0, + ZOffset = 0, + }, + }, + SurfaceLight = { + name = "SurfaceLight", + superclass = "Light", + properties = { + Angle = { + name = "Angle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Face = { + name = "Face", + type = {type = "Enum", name = "NormalId"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Range = { + name = "Range", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Angle = 90, + Brightness = 1, + Color = Color3.new(1, 1, 1), + Enabled = true, + Face = 5, + Name = "SurfaceLight", + Range = 16, + Shadows = false, + }, + }, + SurfaceSelection = { + name = "SurfaceSelection", + superclass = "PartAdornment", + properties = { + TargetSurface = { + name = "TargetSurface", + type = {type = "Enum", name = "NormalId"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Adornee = nil, + Color = BrickColor.new(23), + Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), + Name = "SurfaceSelection", + TargetSurface = 0, + Transparency = 0, + Visible = true, + }, + }, + TaskScheduler = { + name = "TaskScheduler", + superclass = "Instance", + properties = { + SchedulerDutyCycle = { + name = "SchedulerDutyCycle", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + SchedulerRate = { + name = "SchedulerRate", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ThreadPoolConfig = { + name = "ThreadPoolConfig", + type = {type = "Enum", name = "ThreadPoolConfig"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ThreadPoolSize = { + name = "ThreadPoolSize", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + Team = { + name = "Team", + superclass = "Instance", + properties = { + AutoAssignable = { + name = "AutoAssignable", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AutoColorCharacters = { + name = "AutoColorCharacters", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Score = { + name = "Score", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + TeamColor = { + name = "TeamColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + AutoAssignable = true, + AutoColorCharacters = true, + Name = "Team", + Score = 0, + TeamColor = BrickColor.new(1), + }, + }, + Teams = { + name = "Teams", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Teams", + }, + }, + TeleportService = { + name = "TeleportService", + superclass = "Instance", + properties = { + CustomizedTeleportUI = { + name = "CustomizedTeleportUI", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + CustomizedTeleportUI = false, + Name = "Teleport Service", + }, + }, + Terrain = { + name = "Terrain", + superclass = "BasePart", + properties = { + IsSmooth = { + name = "IsSmooth", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + MaterialColors = { + name = "MaterialColors", + type = {type = "Data", name = "BinaryString"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + MaxExtents = { + name = "MaxExtents", + type = {type = "Unimplemented", name = "Region3int16"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + WaterColor = { + name = "WaterColor", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WaterReflectance = { + name = "WaterReflectance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WaterTransparency = { + name = "WaterTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WaterWaveSize = { + name = "WaterWaveSize", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WaterWaveSpeed = { + name = "WaterWaveSpeed", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + TerrainRegion = { + name = "TerrainRegion", + superclass = "Instance", + properties = { + IsSmooth = { + name = "IsSmooth", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + SizeInCells = { + name = "SizeInCells", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + Name = "TerrainRegion", + }, + }, + TestService = { + name = "TestService", + superclass = "Instance", + properties = { + AutoRuns = { + name = "AutoRuns", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Description = { + name = "Description", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ErrorCount = { + name = "ErrorCount", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ExecuteWithStudioRun = { + name = "ExecuteWithStudioRun", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Is30FpsThrottleEnabled = { + name = "Is30FpsThrottleEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsPhysicsEnvironmentalThrottled = { + name = "IsPhysicsEnvironmentalThrottled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsSleepAllowed = { + name = "IsSleepAllowed", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NumberOfPlayers = { + name = "NumberOfPlayers", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SimulateSecondsLag = { + name = "SimulateSecondsLag", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TestCount = { + name = "TestCount", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Timeout = { + name = "Timeout", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WarnCount = { + name = "WarnCount", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + AutoRuns = true, + Description = "", + ExecuteWithStudioRun = false, + Is30FpsThrottleEnabled = true, + IsPhysicsEnvironmentalThrottled = true, + IsSleepAllowed = true, + Name = "TestService", + NumberOfPlayers = 0, + SimulateSecondsLag = 0, + Timeout = 10, + }, + }, + TextBox = { + name = "TextBox", + superclass = "GuiObject", + properties = { + ClearTextOnFocus = { + name = "ClearTextOnFocus", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CursorPosition = { + name = "CursorPosition", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + EnableRealtimeFilteringHints = { + name = "EnableRealtimeFilteringHints", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Font = { + name = "Font", + type = {type = "Enum", name = "Font"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FontSize = { + name = "FontSize", + type = {type = "Enum", name = "FontSize"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + LineHeight = { + name = "LineHeight", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ManualFocusRelease = { + name = "ManualFocusRelease", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + MultiLine = { + name = "MultiLine", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + OverlayNativeInput = { + name = "OverlayNativeInput", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + PlaceholderColor3 = { + name = "PlaceholderColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PlaceholderText = { + name = "PlaceholderText", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ReturnKeyType = { + name = "ReturnKeyType", + type = {type = "Enum", name = "ReturnKeyType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + SelectionStart = { + name = "SelectionStart", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + ShowNativeInput = { + name = "ShowNativeInput", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Text = { + name = "Text", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextBounds = { + name = "TextBounds", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TextColor = { + name = "TextColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + TextColor3 = { + name = "TextColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextEditable = { + name = "TextEditable", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextFits = { + name = "TextFits", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TextInputType = { + name = "TextInputType", + type = {type = "Enum", name = "TextInputType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + TextScaled = { + name = "TextScaled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextSize = { + name = "TextSize", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextStrokeColor3 = { + name = "TextStrokeColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextStrokeTransparency = { + name = "TextStrokeTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextTransparency = { + name = "TextTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextTruncate = { + name = "TextTruncate", + type = {type = "Enum", name = "TextTruncate"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextWrap = { + name = "TextWrap", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + TextWrapped = { + name = "TextWrapped", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextXAlignment = { + name = "TextXAlignment", + type = {type = "Enum", name = "TextXAlignment"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextYAlignment = { + name = "TextYAlignment", + type = {type = "Enum", name = "TextYAlignment"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Active = true, + AnchorPoint = Vector2.new(0, 0), + AutoLocalize = true, + BackgroundColor = BrickColor.new(194), + BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), + BackgroundTransparency = 0, + BorderColor = BrickColor.new(26), + BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), + BorderMode = 0, + BorderSizePixel = 1, + ClearTextOnFocus = true, + ClipsDescendants = false, + CursorPosition = 1, + Draggable = false, + EnableRealtimeFilteringHints = false, + Font = 0, + FontSize = 0, + LayoutOrder = 0, + LineHeight = 1, + Localize = true, + ManualFocusRelease = false, + MultiLine = false, + Name = "TextBox", + NextSelectionDown = nil, + NextSelectionLeft = nil, + NextSelectionRight = nil, + NextSelectionUp = nil, + OverlayNativeInput = false, + PlaceholderColor3 = Color3.new(0.7, 0.7, 0.7), + PlaceholderText = "", + Position = UDim2.new(0, 0, 0, 0), + ReturnKeyType = 0, + RootLocalizationTable = nil, + Rotation = 0, + Selectable = true, + SelectionImageObject = nil, + SelectionStart = -1, + ShowNativeInput = true, + Size = UDim2.new(0, 0, 0, 0), + SizeConstraint = 0, + Text = "TextBox", + TextColor = BrickColor.new(26), + TextColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), + TextEditable = true, + TextInputType = 0, + TextScaled = false, + TextSize = 8, + TextStrokeColor3 = Color3.new(0, 0, 0), + TextStrokeTransparency = 1, + TextTransparency = 0, + TextTruncate = 0, + TextWrap = false, + TextWrapped = false, + TextXAlignment = 2, + TextYAlignment = 1, + Transparency = 0, + Visible = true, + ZIndex = 1, + }, + }, + TextButton = { + name = "TextButton", + superclass = "GuiButton", + properties = { + Font = { + name = "Font", + type = {type = "Enum", name = "Font"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FontSize = { + name = "FontSize", + type = {type = "Enum", name = "FontSize"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + LineHeight = { + name = "LineHeight", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LocalizedText = { + name = "LocalizedText", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Text = { + name = "Text", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextBounds = { + name = "TextBounds", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TextColor = { + name = "TextColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + TextColor3 = { + name = "TextColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextFits = { + name = "TextFits", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TextScaled = { + name = "TextScaled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextSize = { + name = "TextSize", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextStrokeColor3 = { + name = "TextStrokeColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextStrokeTransparency = { + name = "TextStrokeTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextTransparency = { + name = "TextTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextTruncate = { + name = "TextTruncate", + type = {type = "Enum", name = "TextTruncate"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextWrap = { + name = "TextWrap", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + TextWrapped = { + name = "TextWrapped", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextXAlignment = { + name = "TextXAlignment", + type = {type = "Enum", name = "TextXAlignment"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextYAlignment = { + name = "TextYAlignment", + type = {type = "Enum", name = "TextYAlignment"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Active = true, + AnchorPoint = Vector2.new(0, 0), + AutoButtonColor = true, + AutoLocalize = true, + BackgroundColor = BrickColor.new(194), + BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), + BackgroundTransparency = 0, + BorderColor = BrickColor.new(26), + BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), + BorderMode = 0, + BorderSizePixel = 1, + ClipsDescendants = false, + Draggable = false, + Font = 0, + FontSize = 0, + LayoutOrder = 0, + LineHeight = 1, + Localize = true, + Modal = false, + Name = "TextButton", + NextSelectionDown = nil, + NextSelectionLeft = nil, + NextSelectionRight = nil, + NextSelectionUp = nil, + Position = UDim2.new(0, 0, 0, 0), + RootLocalizationTable = nil, + Rotation = 0, + Selectable = true, + Selected = false, + SelectionImageObject = nil, + Size = UDim2.new(0, 0, 0, 0), + SizeConstraint = 0, + Style = 0, + Text = "Button", + TextColor = BrickColor.new(26), + TextColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), + TextScaled = false, + TextSize = 8, + TextStrokeColor3 = Color3.new(0, 0, 0), + TextStrokeTransparency = 1, + TextTransparency = 0, + TextTruncate = 0, + TextWrap = false, + TextWrapped = false, + TextXAlignment = 2, + TextYAlignment = 1, + Transparency = 0, + Visible = true, + ZIndex = 1, + }, + }, + TextFilterResult = { + name = "TextFilterResult", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + TextLabel = { + name = "TextLabel", + superclass = "GuiLabel", + properties = { + Font = { + name = "Font", + type = {type = "Enum", name = "Font"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FontSize = { + name = "FontSize", + type = {type = "Enum", name = "FontSize"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + LineHeight = { + name = "LineHeight", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LocalizedText = { + name = "LocalizedText", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Text = { + name = "Text", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextBounds = { + name = "TextBounds", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TextColor = { + name = "TextColor", + type = {type = "Data", name = "BrickColor"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + TextColor3 = { + name = "TextColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextFits = { + name = "TextFits", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TextScaled = { + name = "TextScaled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextSize = { + name = "TextSize", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextStrokeColor3 = { + name = "TextStrokeColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextStrokeTransparency = { + name = "TextStrokeTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextTransparency = { + name = "TextTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextTruncate = { + name = "TextTruncate", + type = {type = "Enum", name = "TextTruncate"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextWrap = { + name = "TextWrap", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + TextWrapped = { + name = "TextWrapped", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextXAlignment = { + name = "TextXAlignment", + type = {type = "Enum", name = "TextXAlignment"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextYAlignment = { + name = "TextYAlignment", + type = {type = "Enum", name = "TextYAlignment"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Active = false, + AnchorPoint = Vector2.new(0, 0), + AutoLocalize = true, + BackgroundColor = BrickColor.new(194), + BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), + BackgroundTransparency = 0, + BorderColor = BrickColor.new(26), + BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), + BorderMode = 0, + BorderSizePixel = 1, + ClipsDescendants = false, + Draggable = false, + Font = 0, + FontSize = 0, + LayoutOrder = 0, + LineHeight = 1, + Localize = true, + Name = "TextLabel", + NextSelectionDown = nil, + NextSelectionLeft = nil, + NextSelectionRight = nil, + NextSelectionUp = nil, + Position = UDim2.new(0, 0, 0, 0), + RootLocalizationTable = nil, + Rotation = 0, + Selectable = false, + SelectionImageObject = nil, + Size = UDim2.new(0, 0, 0, 0), + SizeConstraint = 0, + Text = "Label", + TextColor = BrickColor.new(26), + TextColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), + TextScaled = false, + TextSize = 8, + TextStrokeColor3 = Color3.new(0, 0, 0), + TextStrokeTransparency = 1, + TextTransparency = 0, + TextTruncate = 0, + TextWrap = false, + TextWrapped = false, + TextXAlignment = 2, + TextYAlignment = 1, + Transparency = 0, + Visible = true, + ZIndex = 1, + }, + }, + TextService = { + name = "TextService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "TextService", + }, + }, + Texture = { + name = "Texture", + superclass = "Decal", + properties = { + OffsetStudsU = { + name = "OffsetStudsU", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + OffsetStudsV = { + name = "OffsetStudsV", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + StudsPerTileU = { + name = "StudsPerTileU", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + StudsPerTileV = { + name = "StudsPerTileV", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Color3 = Color3.new(1, 1, 1), + Face = 5, + LocalTransparencyModifier = 0, + Name = "Texture", + OffsetStudsU = 0, + OffsetStudsV = 0, + Shiny = 20, + Specular = 0, + StudsPerTileU = 2, + StudsPerTileV = 2, + Texture = "", + Transparency = 0, + }, + }, + ThirdPartyUserService = { + name = "ThirdPartyUserService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + TimerService = { + name = "TimerService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + Tool = { + name = "Tool", + superclass = "BackpackItem", + properties = { + CanBeDropped = { + name = "CanBeDropped", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Grip = { + name = "Grip", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GripForward = { + name = "GripForward", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + GripPos = { + name = "GripPos", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + GripRight = { + name = "GripRight", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + GripUp = { + name = "GripUp", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + ManualActivationOnly = { + name = "ManualActivationOnly", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RequiresHandle = { + name = "RequiresHandle", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ToolTip = { + name = "ToolTip", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + CanBeDropped = true, + Enabled = true, + Grip = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + GripForward = Vector3.new(0, 0, -1), + GripPos = Vector3.new(0, 0, 0), + GripRight = Vector3.new(1, 0, 0), + GripUp = Vector3.new(0, 1, 0), + ManualActivationOnly = false, + Name = "Tool", + RequiresHandle = true, + TextureId = "", + ToolTip = "", + }, + }, + Torque = { + name = "Torque", + superclass = "Constraint", + properties = { + RelativeTo = { + name = "RelativeTo", + type = {type = "Enum", name = "ActuatorRelativeTo"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Torque = { + name = "Torque", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Attachment0 = nil, + Attachment1 = nil, + Color = BrickColor.new(23), + Enabled = true, + Name = "Torque", + RelativeTo = 0, + Torque = Vector3.new(0, 0, 0), + Visible = false, + }, + }, + TotalCountTimeIntervalItem = { + name = "TotalCountTimeIntervalItem", + superclass = "StatsItem", + properties = { + }, + defaults = { + }, + }, + TouchInputService = { + name = "TouchInputService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "TouchInputService", + }, + }, + TouchTransmitter = { + name = "TouchTransmitter", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + Trail = { + name = "Trail", + superclass = "Instance", + properties = { + Attachment0 = { + name = "Attachment0", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Attachment1 = { + name = "Attachment1", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Color = { + name = "Color", + type = {type = "Data", name = "ColorSequence"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FaceCamera = { + name = "FaceCamera", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Lifetime = { + name = "Lifetime", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LightEmission = { + name = "LightEmission", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LightInfluence = { + name = "LightInfluence", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxLength = { + name = "MaxLength", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MinLength = { + name = "MinLength", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Texture = { + name = "Texture", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextureLength = { + name = "TextureLength", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TextureMode = { + name = "TextureMode", + type = {type = "Enum", name = "TextureMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Transparency = { + name = "Transparency", + type = {type = "Data", name = "NumberSequence"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + WidthScale = { + name = "WidthScale", + type = {type = "Data", name = "NumberSequence"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Attachment0 = nil, + Attachment1 = nil, + Color = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.new(1, 1, 1)), ColorSequenceKeypoint.new(1, Color3.new(1, 1, 1))}), + Enabled = true, + FaceCamera = false, + Lifetime = 2, + LightEmission = 0, + LightInfluence = 0, + MaxLength = 0, + MinLength = 0.1, + Name = "Trail", + Texture = "", + TextureLength = 1, + TextureMode = 0, + Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 0.5, 0), NumberSequenceKeypoint.new(1, 0.5, 0)}), + WidthScale = NumberSequence.new({NumberSequenceKeypoint.new(0, 1, 0), NumberSequenceKeypoint.new(1, 1, 0)}), + }, + }, + Translator = { + name = "Translator", + superclass = "Instance", + properties = { + LocaleId = { + name = "LocaleId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + TremoloSoundEffect = { + name = "TremoloSoundEffect", + superclass = "SoundEffect", + properties = { + Depth = { + name = "Depth", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Duty = { + name = "Duty", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Frequency = { + name = "Frequency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Depth = 1, + Duty = 0.5, + Enabled = true, + Frequency = 5, + Name = "TremoloSoundEffect", + Priority = 0, + }, + }, + TriangleMeshPart = { + name = "TriangleMeshPart", + superclass = "BasePart", + properties = { + CollisionFidelity = { + name = "CollisionFidelity", + type = {type = "Enum", name = "CollisionFidelity"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + }, + }, + TrussPart = { + name = "TrussPart", + superclass = "BasePart", + properties = { + Style = { + name = "Style", + type = {type = "Enum", name = "Style"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + Anchored = false, + BackParamA = -0.5, + BackParamB = 0.5, + BackSurface = 5, + BackSurfaceInput = 0, + BottomParamA = -0.5, + BottomParamB = 0.5, + BottomSurface = 5, + BottomSurfaceInput = 0, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CanCollide = true, + CastShadow = true, + CollisionGroupId = 0, + Color = Color3.new(0.6392157, 0.63529414, 0.64705884), + CustomPhysicalProperties = nil, + Elasticity = 0.5, + Friction = 0.3, + FrontParamA = -0.5, + FrontParamB = 0.5, + FrontSurface = 5, + FrontSurfaceInput = 0, + LeftParamA = -0.5, + LeftParamB = 0.5, + LeftSurface = 5, + LeftSurfaceInput = 0, + LocalTransparencyModifier = 0, + Locked = false, + Massless = false, + Material = 256, + Name = "Truss", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Reflectance = 0, + RightParamA = -0.5, + RightParamB = 0.5, + RightSurface = 5, + RightSurfaceInput = 0, + RootPriority = 0, + RotVelocity = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + Size = Vector3.new(2, 2, 2), + Style = 0, + TopParamA = -0.5, + TopParamB = 0.5, + TopSurface = 5, + TopSurfaceInput = 0, + Transparency = 0, + Velocity = Vector3.new(0, 0, 0), + }, + }, + Tween = { + name = "Tween", + superclass = "TweenBase", + properties = { + Instance = { + name = "Instance", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TweenInfo = { + name = "TweenInfo", + type = {type = "Unimplemented", name = "TweenInfo"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + Name = "Tween", + }, + }, + TweenBase = { + name = "TweenBase", + superclass = "Instance", + properties = { + PlaybackState = { + name = "PlaybackState", + type = {type = "Enum", name = "PlaybackState"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + TweenService = { + name = "TweenService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "TweenService", + }, + }, + UGCValidationService = { + name = "UGCValidationService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "UGCValidationService", + }, + }, + UIAspectRatioConstraint = { + name = "UIAspectRatioConstraint", + superclass = "UIConstraint", + properties = { + AspectRatio = { + name = "AspectRatio", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + AspectType = { + name = "AspectType", + type = {type = "Enum", name = "AspectType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DominantAxis = { + name = "DominantAxis", + type = {type = "Enum", name = "DominantAxis"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + AspectRatio = 1, + AspectType = 0, + DominantAxis = 0, + Name = "UIAspectRatioConstraint", + }, + }, + UIBase = { + name = "UIBase", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + UIComponent = { + name = "UIComponent", + superclass = "UIBase", + properties = { + }, + defaults = { + }, + }, + UIConstraint = { + name = "UIConstraint", + superclass = "UIComponent", + properties = { + }, + defaults = { + }, + }, + UIGridLayout = { + name = "UIGridLayout", + superclass = "UIGridStyleLayout", + properties = { + AbsoluteCellCount = { + name = "AbsoluteCellCount", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + AbsoluteCellSize = { + name = "AbsoluteCellSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + CellPadding = { + name = "CellPadding", + type = {type = "Data", name = "UDim2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CellSize = { + name = "CellSize", + type = {type = "Data", name = "UDim2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FillDirectionMaxCells = { + name = "FillDirectionMaxCells", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + StartCorner = { + name = "StartCorner", + type = {type = "Enum", name = "StartCorner"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + CellPadding = UDim2.new(0, 5, 0, 5), + CellSize = UDim2.new(0, 100, 0, 100), + FillDirection = 0, + FillDirectionMaxCells = 0, + HorizontalAlignment = 1, + Name = "UIGridLayout", + SortOrder = 0, + StartCorner = 0, + VerticalAlignment = 1, + }, + }, + UIGridStyleLayout = { + name = "UIGridStyleLayout", + superclass = "UILayout", + properties = { + AbsoluteContentSize = { + name = "AbsoluteContentSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + FillDirection = { + name = "FillDirection", + type = {type = "Enum", name = "FillDirection"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HorizontalAlignment = { + name = "HorizontalAlignment", + type = {type = "Enum", name = "HorizontalAlignment"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SortOrder = { + name = "SortOrder", + type = {type = "Enum", name = "SortOrder"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + VerticalAlignment = { + name = "VerticalAlignment", + type = {type = "Enum", name = "VerticalAlignment"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + UIInlineLayout = { + name = "UIInlineLayout", + superclass = "UIGridStyleLayout", + properties = { + InlineAlignment = { + name = "InlineAlignment", + type = {type = "Enum", name = "InlineAlignment"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + InlinePadding = { + name = "InlinePadding", + type = {type = "Data", name = "UDim2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + FillDirection = 0, + HorizontalAlignment = 1, + InlineAlignment = 1, + InlinePadding = UDim2.new(0, 0, 0, 0), + Name = "UIInlineLayout", + SortOrder = 0, + VerticalAlignment = 1, + }, + }, + UILayout = { + name = "UILayout", + superclass = "UIComponent", + properties = { + }, + defaults = { + }, + }, + UIListLayout = { + name = "UIListLayout", + superclass = "UIGridStyleLayout", + properties = { + Padding = { + name = "Padding", + type = {type = "Data", name = "UDim"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + FillDirection = 1, + HorizontalAlignment = 1, + Name = "UIListLayout", + Padding = UDim.new(0, 0), + SortOrder = 0, + VerticalAlignment = 1, + }, + }, + UIPadding = { + name = "UIPadding", + superclass = "UIComponent", + properties = { + PaddingBottom = { + name = "PaddingBottom", + type = {type = "Data", name = "UDim"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PaddingLeft = { + name = "PaddingLeft", + type = {type = "Data", name = "UDim"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PaddingRight = { + name = "PaddingRight", + type = {type = "Data", name = "UDim"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + PaddingTop = { + name = "PaddingTop", + type = {type = "Data", name = "UDim"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "UIPadding", + PaddingBottom = UDim.new(0, 0), + PaddingLeft = UDim.new(0, 0), + PaddingRight = UDim.new(0, 0), + PaddingTop = UDim.new(0, 0), + }, + }, + UIPageLayout = { + name = "UIPageLayout", + superclass = "UIGridStyleLayout", + properties = { + Animated = { + name = "Animated", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Circular = { + name = "Circular", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CurrentPage = { + name = "CurrentPage", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + EasingDirection = { + name = "EasingDirection", + type = {type = "Enum", name = "EasingDirection"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + EasingStyle = { + name = "EasingStyle", + type = {type = "Enum", name = "EasingStyle"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GamepadInputEnabled = { + name = "GamepadInputEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Padding = { + name = "Padding", + type = {type = "Data", name = "UDim"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ScrollWheelInputEnabled = { + name = "ScrollWheelInputEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TouchInputEnabled = { + name = "TouchInputEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TweenTime = { + name = "TweenTime", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Animated = true, + Circular = false, + EasingDirection = 1, + EasingStyle = 2, + FillDirection = 0, + GamepadInputEnabled = true, + HorizontalAlignment = 1, + Name = "UIPageLayout", + Padding = UDim.new(0, 0), + ScrollWheelInputEnabled = true, + SortOrder = 0, + TouchInputEnabled = true, + TweenTime = 1, + VerticalAlignment = 1, + }, + }, + UIScale = { + name = "UIScale", + superclass = "UIComponent", + properties = { + Scale = { + name = "Scale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "UIScale", + Scale = 1, + }, + }, + UISizeConstraint = { + name = "UISizeConstraint", + superclass = "UIConstraint", + properties = { + MaxSize = { + name = "MaxSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MinSize = { + name = "MinSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + MaxSize = Vector2.new(1000000000, 1000000000), + MinSize = Vector2.new(0, 0), + Name = "UISizeConstraint", + }, + }, + UITableLayout = { + name = "UITableLayout", + superclass = "UIGridStyleLayout", + properties = { + FillEmptySpaceColumns = { + name = "FillEmptySpaceColumns", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FillEmptySpaceRows = { + name = "FillEmptySpaceRows", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MajorAxis = { + name = "MajorAxis", + type = {type = "Enum", name = "TableMajorAxis"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Padding = { + name = "Padding", + type = {type = "Data", name = "UDim2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + FillDirection = 1, + FillEmptySpaceColumns = false, + FillEmptySpaceRows = false, + HorizontalAlignment = 1, + MajorAxis = 0, + Name = "UITableLayout", + Padding = UDim2.new(0, 0, 0, 0), + SortOrder = 0, + VerticalAlignment = 1, + }, + }, + UITextSizeConstraint = { + name = "UITextSizeConstraint", + superclass = "UIConstraint", + properties = { + MaxTextSize = { + name = "MaxTextSize", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MinTextSize = { + name = "MinTextSize", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + MaxTextSize = 100, + MinTextSize = 1, + Name = "UITextSizeConstraint", + }, + }, + UnionOperation = { + name = "UnionOperation", + superclass = "PartOperation", + properties = { + }, + defaults = { + Anchored = false, + BackParamA = -0.5, + BackParamB = 0.5, + BackSurface = 0, + BackSurfaceInput = 0, + BottomParamA = -0.5, + BottomParamB = 0.5, + BottomSurface = 0, + BottomSurfaceInput = 0, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CanCollide = true, + CastShadow = true, + CollisionFidelity = 0, + CollisionGroupId = 0, + Color = Color3.new(1, 1, 1), + CustomPhysicalProperties = nil, + Elasticity = 0.5, + Friction = 0.3, + FrontParamA = -0.5, + FrontParamB = 0.5, + FrontSurface = 0, + FrontSurfaceInput = 0, + LeftParamA = -0.5, + LeftParamB = 0.5, + LeftSurface = 0, + LeftSurfaceInput = 0, + LocalTransparencyModifier = 0, + Locked = false, + Massless = false, + Material = 256, + Name = "Union", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Reflectance = 0, + RenderFidelity = 1, + RightParamA = -0.5, + RightParamB = 0.5, + RightSurface = 0, + RightSurfaceInput = 0, + RootPriority = 0, + RotVelocity = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + Size = Vector3.new(4, 1.2, 2), + TopParamA = -0.5, + TopParamB = 0.5, + TopSurface = 0, + TopSurfaceInput = 0, + Transparency = 0, + UsePartColor = false, + Velocity = Vector3.new(0, 0, 0), + }, + }, + UserGameSettings = { + name = "UserGameSettings", + superclass = "Instance", + properties = { + AllTutorialsDisabled = { + name = "AllTutorialsDisabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CameraMode = { + name = "CameraMode", + type = {type = "Enum", name = "CustomCameraMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CameraYInverted = { + name = "CameraYInverted", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ChatVisible = { + name = "ChatVisible", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ComputerCameraMovementMode = { + name = "ComputerCameraMovementMode", + type = {type = "Enum", name = "ComputerCameraMovementMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ComputerMovementMode = { + name = "ComputerMovementMode", + type = {type = "Enum", name = "ComputerMovementMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ControlMode = { + name = "ControlMode", + type = {type = "Enum", name = "ControlMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Fullscreen = { + name = "Fullscreen", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GamepadCameraSensitivity = { + name = "GamepadCameraSensitivity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HasEverUsedVR = { + name = "HasEverUsedVR", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsUsingCameraYInverted = { + name = "IsUsingCameraYInverted", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsUsingGamepadCameraSensitivity = { + name = "IsUsingGamepadCameraSensitivity", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + MasterVolume = { + name = "MasterVolume", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MicroProfilerWebServerEnabled = { + name = "MicroProfilerWebServerEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MicroProfilerWebServerIP = { + name = "MicroProfilerWebServerIP", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + MicroProfilerWebServerPort = { + name = "MicroProfilerWebServerPort", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + MouseSensitivity = { + name = "MouseSensitivity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MouseSensitivityFirstPerson = { + name = "MouseSensitivityFirstPerson", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MouseSensitivityThirdPerson = { + name = "MouseSensitivityThirdPerson", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + OnScreenProfilerEnabled = { + name = "OnScreenProfilerEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + OnboardingsCompleted = { + name = "OnboardingsCompleted", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + PerformanceStatsVisible = { + name = "PerformanceStatsVisible", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RCCProfilerRecordFrameRate = { + name = "RCCProfilerRecordFrameRate", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RCCProfilerRecordTimeFrame = { + name = "RCCProfilerRecordTimeFrame", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RotationType = { + name = "RotationType", + type = {type = "Enum", name = "RotationType"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + SavedQualityLevel = { + name = "SavedQualityLevel", + type = {type = "Enum", name = "SavedQualitySetting"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + StartMaximized = { + name = "StartMaximized", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + StartScreenPosition = { + name = "StartScreenPosition", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + StartScreenSize = { + name = "StartScreenSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + TouchCameraMovementMode = { + name = "TouchCameraMovementMode", + type = {type = "Enum", name = "TouchCameraMovementMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TouchMovementMode = { + name = "TouchMovementMode", + type = {type = "Enum", name = "TouchMovementMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UsedCoreGuiIsVisibleToggle = { + name = "UsedCoreGuiIsVisibleToggle", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UsedCustomGuiIsVisibleToggle = { + name = "UsedCustomGuiIsVisibleToggle", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UsedHideHudShortcut = { + name = "UsedHideHudShortcut", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + VREnabled = { + name = "VREnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + VRRotationIntensity = { + name = "VRRotationIntensity", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, + UserInputService = { + name = "UserInputService", + superclass = "Instance", + properties = { + AccelerometerEnabled = { + name = "AccelerometerEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + BottomBarSize = { + name = "BottomBarSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + GamepadEnabled = { + name = "GamepadEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + GazeSelectionEnabled = { + name = "GazeSelectionEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + GyroscopeEnabled = { + name = "GyroscopeEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + KeyboardEnabled = { + name = "KeyboardEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + LegacyInputEventsEnabled = { + name = "LegacyInputEventsEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ModalEnabled = { + name = "ModalEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + MouseBehavior = { + name = "MouseBehavior", + type = {type = "Enum", name = "MouseBehavior"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MouseDeltaSensitivity = { + name = "MouseDeltaSensitivity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + MouseEnabled = { + name = "MouseEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + MouseIconEnabled = { + name = "MouseIconEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NavBarSize = { + name = "NavBarSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + OnScreenKeyboardAnimationDuration = { + name = "OnScreenKeyboardAnimationDuration", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + OnScreenKeyboardPosition = { + name = "OnScreenKeyboardPosition", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + OnScreenKeyboardSize = { + name = "OnScreenKeyboardSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + OnScreenKeyboardVisible = { + name = "OnScreenKeyboardVisible", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + OverrideMouseIconBehavior = { + name = "OverrideMouseIconBehavior", + type = {type = "Enum", name = "OverrideMouseIconBehavior"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + RightBarSize = { + name = "RightBarSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + StatusBarSize = { + name = "StatusBarSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TouchEnabled = { + name = "TouchEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + UserHeadCFrame = { + name = "UserHeadCFrame", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + VREnabled = { + name = "VREnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + GazeSelectionEnabled = true, + LegacyInputEventsEnabled = true, + ModalEnabled = false, + MouseBehavior = 0, + MouseDeltaSensitivity = 1, + MouseIconEnabled = true, + Name = "Instance", + OverrideMouseIconBehavior = 0, + }, + }, + UserSettings = { + name = "UserSettings", + superclass = "GenericSettings", + properties = { + }, + defaults = { + }, + }, + UserStorageService = { + name = "UserStorageService", + superclass = "LocalStorageService", + properties = { + }, + defaults = { + }, + }, + VRService = { + name = "VRService", + superclass = "Instance", + properties = { + GuiInputUserCFrame = { + name = "GuiInputUserCFrame", + type = {type = "Enum", name = "UserCFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + VRDeviceName = { + name = "VRDeviceName", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + VREnabled = { + name = "VREnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + GuiInputUserCFrame = 0, + Name = "VRService", + }, + }, + ValueBase = { + name = "ValueBase", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + Vector3Value = { + name = "Vector3Value", + superclass = "ValueBase", + properties = { + Value = { + name = "Value", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Value", + Value = Vector3.new(0, 0, 0), + }, + }, + VectorForce = { + name = "VectorForce", + superclass = "Constraint", + properties = { + ApplyAtCenterOfMass = { + name = "ApplyAtCenterOfMass", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Force = { + name = "Force", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RelativeTo = { + name = "RelativeTo", + type = {type = "Enum", name = "ActuatorRelativeTo"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + ApplyAtCenterOfMass = false, + Attachment0 = nil, + Attachment1 = nil, + Color = BrickColor.new(23), + Enabled = true, + Force = Vector3.new(1000, 0, 0), + Name = "VectorForce", + RelativeTo = 0, + Visible = false, + }, + }, + VehicleController = { + name = "VehicleController", + superclass = "Controller", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + VehicleSeat = { + name = "VehicleSeat", + superclass = "BasePart", + properties = { + AreHingesDetected = { + name = "AreHingesDetected", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Disabled = { + name = "Disabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HeadsUpDisplay = { + name = "HeadsUpDisplay", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxSpeed = { + name = "MaxSpeed", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Occupant = { + name = "Occupant", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Steer = { + name = "Steer", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + SteerFloat = { + name = "SteerFloat", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Throttle = { + name = "Throttle", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ThrottleFloat = { + name = "ThrottleFloat", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Torque = { + name = "Torque", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TurnSpeed = { + name = "TurnSpeed", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Anchored = false, + BackParamA = -0.5, + BackParamB = 0.5, + BackSurface = 0, + BackSurfaceInput = 0, + BottomParamA = -0.5, + BottomParamB = 0.5, + BottomSurface = 4, + BottomSurfaceInput = 0, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CanCollide = true, + CastShadow = true, + CollisionGroupId = 0, + Color = Color3.new(0.6392157, 0.63529414, 0.64705884), + CustomPhysicalProperties = nil, + Disabled = false, + Elasticity = 0.5, + Friction = 0.3, + FrontParamA = -0.5, + FrontParamB = 0.5, + FrontSurface = 0, + FrontSurfaceInput = 0, + HeadsUpDisplay = true, + LeftParamA = -0.5, + LeftParamB = 0.5, + LeftSurface = 0, + LeftSurfaceInput = 0, + LocalTransparencyModifier = 0, + Locked = false, + Massless = false, + Material = 256, + MaxSpeed = 25, + Name = "VehicleSeat", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Reflectance = 0, + RightParamA = -0.5, + RightParamB = 0.5, + RightSurface = 0, + RightSurfaceInput = 0, + RootPriority = 0, + RotVelocity = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + Size = Vector3.new(4, 1.2, 2), + Steer = 0, + SteerFloat = 0, + Throttle = 0, + ThrottleFloat = 0, + TopParamA = -0.5, + TopParamB = 0.5, + TopSurface = 3, + TopSurfaceInput = 0, + Torque = 10, + Transparency = 0, + TurnSpeed = 1, + Velocity = Vector3.new(0, 0, 0), + }, + }, + VelocityMotor = { + name = "VelocityMotor", + superclass = "JointInstance", + properties = { + CurrentAngle = { + name = "CurrentAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DesiredAngle = { + name = "DesiredAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Hole = { + name = "Hole", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxVelocity = { + name = "MaxVelocity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CurrentAngle = 0, + DesiredAngle = 0, + Hole = nil, + MaxVelocity = 0, + Name = "VelocityMotor", + Part0 = nil, + Part1 = nil, + }, + }, + VersionControlService = { + name = "VersionControlService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + ViewportFrame = { + name = "ViewportFrame", + superclass = "GuiObject", + properties = { + Ambient = { + name = "Ambient", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CurrentCamera = { + name = "CurrentCamera", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + ImageColor3 = { + name = "ImageColor3", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ImageTransparency = { + name = "ImageTransparency", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LightColor = { + name = "LightColor", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LightDirection = { + name = "LightDirection", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Active = false, + Ambient = Color3.new(0.78431374, 0.78431374, 0.78431374), + AnchorPoint = Vector2.new(0, 0), + AutoLocalize = true, + BackgroundColor = BrickColor.new(194), + BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), + BackgroundTransparency = 0, + BorderColor = BrickColor.new(26), + BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), + BorderMode = 0, + BorderSizePixel = 1, + ClipsDescendants = false, + CurrentCamera = nil, + Draggable = false, + ImageColor3 = Color3.new(1, 1, 1), + ImageTransparency = 0, + LayoutOrder = 0, + LightColor = Color3.new(0.54901963, 0.54901963, 0.54901963), + LightDirection = Vector3.new(-1, -1, -1), + Localize = true, + Name = "ViewportFrame", + NextSelectionDown = nil, + NextSelectionLeft = nil, + NextSelectionRight = nil, + NextSelectionUp = nil, + Position = UDim2.new(0, 0, 0, 0), + RootLocalizationTable = nil, + Rotation = 0, + Selectable = false, + SelectionImageObject = nil, + Size = UDim2.new(0, 0, 0, 0), + SizeConstraint = 0, + Transparency = 0, + Visible = true, + ZIndex = 1, + }, + }, + VirtualInputManager = { + name = "VirtualInputManager", + superclass = "Instance", + properties = { + AdditionalLuaState = { + name = "AdditionalLuaState", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + AdditionalLuaState = "", + Name = "VirtualInputManager", + }, + }, + VirtualUser = { + name = "VirtualUser", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Instance", + }, + }, + Visit = { + name = "Visit", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "Visit", + }, + }, + WedgePart = { + name = "WedgePart", + superclass = "FormFactorPart", + properties = { + }, + defaults = { + Anchored = false, + BackParamA = -0.5, + BackParamB = 0.5, + BackSurface = 0, + BackSurfaceInput = 0, + BottomParamA = -0.5, + BottomParamB = 0.5, + BottomSurface = 4, + BottomSurfaceInput = 0, + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CanCollide = true, + CastShadow = true, + CollisionGroupId = 0, + Color = Color3.new(0.6392157, 0.63529414, 0.64705884), + CustomPhysicalProperties = nil, + Elasticity = 0.5, + FormFactor = 1, + Friction = 0.3, + FrontParamA = -0.5, + FrontParamB = 0.5, + FrontSurface = 0, + FrontSurfaceInput = 0, + LeftParamA = -0.5, + LeftParamB = 0.5, + LeftSurface = 0, + LeftSurfaceInput = 0, + LocalTransparencyModifier = 0, + Locked = false, + Massless = false, + Material = 256, + Name = "Wedge", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Reflectance = 0, + RightParamA = -0.5, + RightParamB = 0.5, + RightSurface = 0, + RightSurfaceInput = 0, + RootPriority = 0, + RotVelocity = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + Size = Vector3.new(4, 1.2, 2), + TopParamA = -0.5, + TopParamB = 0.5, + TopSurface = 0, + TopSurfaceInput = 0, + Transparency = 0, + Velocity = Vector3.new(0, 0, 0), + }, + }, + Weld = { + name = "Weld", + superclass = "JointInstance", + properties = { + }, + defaults = { + C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Name = "Weld", + Part0 = nil, + Part1 = nil, + }, + }, + WeldConstraint = { + name = "WeldConstraint", + superclass = "Instance", + properties = { + Active = { + name = "Active", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Part0 = { + name = "Part0", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + Part1 = { + name = "Part1", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + Enabled = true, + Name = "WeldConstraint", + Part0 = nil, + Part1 = nil, + }, + }, + Workspace = { + name = "Workspace", + superclass = "Model", + properties = { + AllowThirdPartySales = { + name = "AllowThirdPartySales", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CollisionGroups = { + name = "CollisionGroups", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Custom", + serializes = true, + }, + CurrentCamera = { + name = "CurrentCamera", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + DistributedGameTime = { + name = "DistributedGameTime", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FallenPartsDestroyHeight = { + name = "FallenPartsDestroyHeight", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FilteringEnabled = { + name = "FilteringEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Gravity = { + name = "Gravity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + StreamingEnabled = { + name = "StreamingEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + StreamingMinRadius = { + name = "StreamingMinRadius", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + StreamingPauseMode = { + name = "StreamingPauseMode", + type = {type = "Enum", name = "StreamingPauseMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + StreamingTargetRadius = { + name = "StreamingTargetRadius", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + TemporaryLegacyPhysicsSolverOverride = { + name = "TemporaryLegacyPhysicsSolverOverride", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = false, + }, + Terrain = { + name = "Terrain", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + AllowThirdPartySales = false, + CurrentCamera = nil, + DistributedGameTime = 0, + FallenPartsDestroyHeight = -500, + FilteringEnabled = false, + Gravity = 196.2, + Name = "Workspace", + PrimaryPart = nil, + StreamingEnabled = false, + }, + }, +} diff --git a/plugin/rbx_dom_lua/src/ReflectionDatabase/init.lua b/plugin/rbx_dom_lua/src/ReflectionDatabase/init.lua new file mode 100644 index 00000000..bf1096e6 --- /dev/null +++ b/plugin/rbx_dom_lua/src/ReflectionDatabase/init.lua @@ -0,0 +1,3 @@ +return { + classes = require(script.classes) +} \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/base64.lua b/plugin/rbx_dom_lua/src/base64.lua new file mode 100644 index 00000000..33011306 --- /dev/null +++ b/plugin/rbx_dom_lua/src/base64.lua @@ -0,0 +1,139 @@ +-- Thanks to Tiffany352 for this base64 implementation! + +local floor = math.floor +local char = string.char + +local function encodeBase64(str) + local out = {} + local nOut = 0 + local alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + local strLen = #str + + -- 3 octets become 4 hextets + for i = 1, strLen - 2, 3 do + local b1, b2, b3 = str:byte(i, i + 3) + local word = b3 + b2 * 256 + b1 * 256 * 256 + + local h4 = word % 64 + 1 + word = floor(word / 64) + local h3 = word % 64 + 1 + word = floor(word / 64) + local h2 = word % 64 + 1 + word = floor(word / 64) + local h1 = word % 64 + 1 + + out[nOut + 1] = alphabet:sub(h1, h1) + out[nOut + 2] = alphabet:sub(h2, h2) + out[nOut + 3] = alphabet:sub(h3, h3) + out[nOut + 4] = alphabet:sub(h4, h4) + nOut = nOut + 4 + end + + local remainder = strLen % 3 + + if remainder == 2 then + -- 16 input bits -> 3 hextets (2 full, 1 partial) + local b1, b2 = str:byte(-2, -1) + -- partial is 4 bits long, leaving 2 bits of zero padding -> + -- offset = 4 + local word = b2 * 4 + b1 * 4 * 256 + + local h3 = word % 64 + 1 + word = floor(word / 64) + local h2 = word % 64 + 1 + word = floor(word / 64) + local h1 = word % 64 + 1 + + out[nOut + 1] = alphabet:sub(h1, h1) + out[nOut + 2] = alphabet:sub(h2, h2) + out[nOut + 3] = alphabet:sub(h3, h3) + out[nOut + 4] = "=" + elseif remainder == 1 then + -- 8 input bits -> 2 hextets (2 full, 1 partial) + local b1 = str:byte(-1, -1) + -- partial is 2 bits long, leaving 4 bits of zero padding -> + -- offset = 16 + local word = b1 * 16 + + local h2 = word % 64 + 1 + word = floor(word / 64) + local h1 = word % 64 + 1 + + out[nOut + 1] = alphabet:sub(h1, h1) + out[nOut + 2] = alphabet:sub(h2, h2) + out[nOut + 3] = "=" + out[nOut + 4] = "=" + end + -- if the remainder is 0, then no work is needed + + return table.concat(out, "") +end + +local function decodeBase64(str) + local out = {} + local nOut = 0 + local alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + local strLen = #str + local acc = 0 + local nAcc = 0 + + local alphabetLut = {} + for i = 1, #alphabet do + alphabetLut[alphabet:sub(i, i)] = i - 1 + end + + -- 4 hextets become 3 octets + for i = 1, strLen do + local ch = str:sub(i, i) + local byte = alphabetLut[ch] + if byte then + acc = acc * 64 + byte + nAcc = nAcc + 1 + end + + if nAcc == 4 then + local b3 = acc % 256 + acc = floor(acc / 256) + local b2 = acc % 256 + acc = floor(acc / 256) + local b1 = acc % 256 + + out[nOut + 1] = char(b1) + out[nOut + 2] = char(b2) + out[nOut + 3] = char(b3) + nOut = nOut + 3 + nAcc = 0 + acc = 0 + end + end + + if nAcc == 3 then + -- 3 hextets -> 16 bit output + acc = acc * 64 + acc = floor(acc / 256) + local b2 = acc % 256 + acc = floor(acc / 256) + local b1 = acc % 256 + + out[nOut + 1] = char(b1) + out[nOut + 2] = char(b2) + elseif nAcc == 2 then + -- 2 hextets -> 8 bit output + acc = acc * 64 + acc = floor(acc / 256) + acc = acc * 64 + acc = floor(acc / 256) + local b1 = acc % 256 + + out[nOut + 1] = char(b1) + elseif nAcc == 1 then + error("Base64 has invalid length") + end + + return table.concat(out, "") +end + +return { + decode = decodeBase64, + encode = encodeBase64, +} \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/base64.spec.lua b/plugin/rbx_dom_lua/src/base64.spec.lua new file mode 100644 index 00000000..5f2a5f4a --- /dev/null +++ b/plugin/rbx_dom_lua/src/base64.spec.lua @@ -0,0 +1,29 @@ +return function() + local base64 = require(script.Parent.base64) + + it("should encode and decode", function() + local function try(str, expected) + local encoded = base64.encode(str) + expect(encoded).to.equal(expected) + expect(base64.decode(encoded)).to.equal(str) + end + + try("Man", "TWFu") + try("Ma", "TWE=") + try("M", "TQ==") + try("ManM", "TWFuTQ==") + try( + [[Man is distinguished, not only by his reason, but by this ]].. + [[singular passion from other animals, which is a lust of the ]].. + [[mind, that by a perseverance of delight in the continued and ]].. + [[indefatigable generation of knowledge, exceeds the short ]].. + [[vehemence of any carnal pleasure.]], + [[TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sI]].. + [[GJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYW]].. + [[xzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJ]].. + [[zZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRl]].. + [[ZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZ]].. + [[SBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=]] + ) + end) +end \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/customProperties.lua b/plugin/rbx_dom_lua/src/customProperties.lua new file mode 100644 index 00000000..aa03310d --- /dev/null +++ b/plugin/rbx_dom_lua/src/customProperties.lua @@ -0,0 +1,47 @@ +local CollectionService = game:GetService("CollectionService") + +-- Defines how to read and write properties that aren't directly scriptable. +-- +-- The reflection database refers to these as having scriptability = "Custom" +return { + Instance = { + Tags = { + read = function(instance, key) + local tagList = CollectionService:GetTags(instance) + + return true, table.concat(tagList, "\0") + end, + write = function(instance, key, value) + local existingTags = CollectionService:GetTags(instance) + + local unseenTags = {} + for _, tag in ipairs(existingTags) do + unseenTags[tag] = true + end + + local tagList = string.split(value, "\0") + for _, tag in ipairs(tagList) do + unseenTags[tag] = nil + CollectionService:AddTag(instance, tag) + end + + for tag in pairs(unseenTags) do + CollectionService:RemoveTag(instance, tag) + end + + return true + end, + }, + }, + LocalizationTable = { + Contents = { + read = function(instance, key) + return true, instance:GetContents() + end, + write = function(instance, key, value) + instance:SetContents(value) + return true + end, + }, + }, +} \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/init.lua b/plugin/rbx_dom_lua/src/init.lua new file mode 100644 index 00000000..3c1149d6 --- /dev/null +++ b/plugin/rbx_dom_lua/src/init.lua @@ -0,0 +1,67 @@ +local ReflectionDatabase = require(script.ReflectionDatabase) +local Error = require(script.Error) +local PropertyDescriptor = require(script.PropertyDescriptor) + +local function findCanonicalPropertyDescriptor(className, propertyName) + local currentClassName = className + + repeat + local currentClass = ReflectionDatabase.classes[currentClassName] + + if currentClass == nil then + return currentClass + end + + local propertyData = currentClass.properties[propertyName] + if propertyData ~= nil then + if propertyData.isCanonical then + return PropertyDescriptor.fromRaw(propertyData, currentClassName, propertyName) + end + + if propertyData.canonicalName ~= nil then + return PropertyDescriptor.fromRaw( + currentClass.properties[propertyData.canonicalName], + currentClassName, + propertyData.canonicalName) + end + + return nil + end + + currentClassName = currentClass.superclass + until currentClassName == nil + + return nil +end + +local function readProperty(instance, propertyName) + local descriptor = findCanonicalPropertyDescriptor(instance.ClassName, propertyName) + + if descriptor == nil then + local fullName = ("%s.%s"):format(instance.className, propertyName) + + return false, Error.new(Error.Kind.UnknownProperty, fullName) + end + + return descriptor:read(instance) +end + +local function writeProperty(instance, propertyName, value) + local descriptor = findCanonicalPropertyDescriptor(instance.ClassName, propertyName) + + if descriptor == nil then + local fullName = ("%s.%s"):format(instance.className, propertyName) + + return false, Error.new(Error.Kind.UnknownProperty, fullName) + end + + return descriptor:write(instance, value) +end + +return { + readProperty = readProperty, + writeProperty = writeProperty, + findCanonicalPropertyDescriptor = findCanonicalPropertyDescriptor, + Error = Error, + EncodedValue = require(script.EncodedValue), +} \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/init.spec.lua b/plugin/rbx_dom_lua/src/init.spec.lua new file mode 100644 index 00000000..4cafe5ae --- /dev/null +++ b/plugin/rbx_dom_lua/src/init.spec.lua @@ -0,0 +1,7 @@ +return function() + local RbxDom = require(script.Parent) + + it("should load", function() + expect(RbxDom).to.be.ok() + end) +end \ No newline at end of file diff --git a/plugin/rbx_dom_lua/test-place.project.json b/plugin/rbx_dom_lua/test-place.project.json new file mode 100644 index 00000000..f852b2b4 --- /dev/null +++ b/plugin/rbx_dom_lua/test-place.project.json @@ -0,0 +1,35 @@ +{ + "name": "rbx_dom_lua test place", + "tree": { + "$className": "DataModel", + "ReplicatedStorage": { + "$className": "ReplicatedStorage", + + "RbxDom": { + "$path": "src" + }, + "TestEZ": { + "$path": "modules/testez/lib" + } + }, + "ServerScriptService": { + "$className": "ServerScriptService", + + "Run Tests": { + "$path": "test.server.lua" + } + }, + "Players": { + "$className": "Players", + "$properties": { + "CharacterAutoLoads": false + } + }, + "HttpService": { + "$className": "HttpService", + "$properties": { + "HttpEnabled": true + } + } + } +} \ No newline at end of file diff --git a/plugin/rbx_dom_lua/test.server.lua b/plugin/rbx_dom_lua/test.server.lua new file mode 100644 index 00000000..841c63c1 --- /dev/null +++ b/plugin/rbx_dom_lua/test.server.lua @@ -0,0 +1,7 @@ +local ReplicatedStorage = game:GetService("ReplicatedStorage") + +local LIB_ROOT = ReplicatedStorage.RbxDom + +local TestEZ = require(ReplicatedStorage.TestEZ) + +TestEZ.TestBootstrap:run({LIB_ROOT}) \ No newline at end of file diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 7dc4d4e0..fbdca8a3 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,8 +5,8 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {0, 6, 0, "-alpha.3"}, - expectedServerVersionString = "0.6.0 or newer", + version = {6, 0, 0, "-rc.1"}, + expectedServerVersionString = "6.0 or newer", protocolVersion = 3, defaultHost = "localhost", defaultPort = 34872, From def99a9e4dd4115097aa8db90bfd70711a634ebe Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 29 Mar 2020 17:09:52 -0700 Subject: [PATCH 1039/1504] Update release job to fix 6.0.0 release --- .github/workflows/release.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 779566c5..bf43ed0f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,6 +10,8 @@ jobs: steps: - uses: actions/checkout@v1 + with: + submodules: true - name: Build release binary run: cargo build --verbose --locked --release @@ -25,6 +27,8 @@ jobs: steps: - uses: actions/checkout@v1 + with: + submodules: true - name: Install Rust run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y @@ -47,6 +51,8 @@ jobs: steps: - uses: actions/checkout@v1 + with: + submodules: true - name: Build run: cargo build --locked --verbose --release From 30a01381be0ab4529cd4a087f7a205edb005b29f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 30 Mar 2020 11:12:20 -0700 Subject: [PATCH 1040/1504] Fix malformed CSV files causing crashes; fixes #310 --- CHANGELOG.md | 1 + src/snapshot_middleware/csv.rs | 18 +++++++++++------- src/snapshot_middleware/error.rs | 10 ++++++++++ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b07f2d3e..894a250a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Fixed crash when malformed CSV files are put into a project. ([#310](https://github.com/rojo-rbx/rojo/issues/310)) ## [6.0.0 Release Candidate 1](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.1) (March 29, 2020) This release jumped from 0.6.0 to 6.0.0. Rojo has been in use in production for many users for quite a long times, and so 6.0 is a more accurate reflection of Rojo's version than a pre-1.0 version. diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 9dca4747..72075a3e 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -8,6 +8,7 @@ use serde::Serialize; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ + error::SnapshotError, meta_file::AdjacentMetadata, middleware::{SnapshotInstanceResult, SnapshotMiddleware}, util::match_file_name, @@ -29,8 +30,10 @@ impl SnapshotMiddleware for SnapshotCsv { }; let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); + let contents = vfs.read(path)?; - let table_contents = convert_localization_csv(&vfs.read(path)?); + let table_contents = convert_localization_csv(&contents) + .map_err(|source| SnapshotError::malformed_l10n_csv(source, path))?; let mut snapshot = InstanceSnapshot::new() .name(instance_name) @@ -87,17 +90,15 @@ struct LocalizationEntry<'a> { /// https://github.com/BurntSushi/rust-csv/issues/151 /// /// This function operates in one step in order to minimize data-copying. -fn convert_localization_csv(contents: &[u8]) -> String { +fn convert_localization_csv(contents: &[u8]) -> Result { let mut reader = csv::Reader::from_reader(contents); - let headers = reader.headers().expect("TODO: Handle csv errors").clone(); + let headers = reader.headers()?.clone(); let mut records = Vec::new(); for record in reader.into_records() { - let record = record.expect("TODO: Handle csv errors"); - - records.push(record); + records.push(record?); } let mut entries = Vec::new(); @@ -128,7 +129,10 @@ fn convert_localization_csv(contents: &[u8]) -> String { entries.push(entry); } - serde_json::to_string(&entries).expect("Could not encode JSON for localization table") + let encoded = + serde_json::to_string(&entries).expect("Could not encode JSON for localization table"); + + Ok(encoded) } #[cfg(test)] diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs index a686fcbc..a1c1665d 100644 --- a/src/snapshot_middleware/error.rs +++ b/src/snapshot_middleware/error.rs @@ -37,6 +37,9 @@ pub enum SnapshotError { path: PathBuf, }, + #[error("malformed CSV localization data at path {}", .path.display())] + MalformedLocalizationCsv { source: csv::Error, path: PathBuf }, + #[error(transparent)] Io { #[from] @@ -89,4 +92,11 @@ impl SnapshotError { path: path.into(), } } + + pub(crate) fn malformed_l10n_csv(source: csv::Error, path: impl Into) -> Self { + Self::MalformedLocalizationCsv { + source, + path: path.into(), + } + } } From a4d4beeb97775633f3ce6d42dbde24a0d4275213 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 30 Mar 2020 11:34:41 -0700 Subject: [PATCH 1041/1504] Update default place template --- CHANGELOG.md | 1 + .../default-place-project/default.project.json | 17 ----------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 894a250a..34ba10c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased Changes * Fixed crash when malformed CSV files are put into a project. ([#310](https://github.com/rojo-rbx/rojo/issues/310)) +* Updated default place template to take advantage of [#210](https://github.com/rojo-rbx/rojo/pull/210). ## [6.0.0 Release Candidate 1](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.1) (March 29, 2020) This release jumped from 0.6.0 to 6.0.0. Rojo has been in use in production for many users for quite a long times, and so 6.0 is a more accurate reflection of Rojo's version than a pre-1.0 version. diff --git a/assets/default-place-project/default.project.json b/assets/default-place-project/default.project.json index 85367e4c..6b25eb9b 100644 --- a/assets/default-place-project/default.project.json +++ b/assets/default-place-project/default.project.json @@ -4,27 +4,19 @@ "$className": "DataModel", "ReplicatedStorage": { - "$className": "ReplicatedStorage", - "Common": { "$path": "src/shared" } }, "ServerScriptService": { - "$className": "ServerScriptService", - "Server": { "$path": "src/server" } }, "StarterPlayer": { - "$className": "StarterPlayer", - "StarterPlayerScripts": { - "$className": "StarterPlayerScripts", - "Client": { "$path": "src/client" } @@ -32,7 +24,6 @@ }, "Workspace": { - "$className": "Workspace", "$properties": { "FilteringEnabled": true }, @@ -60,7 +51,6 @@ } }, "Lighting": { - "$className": "Lighting", "$properties": { "Ambient": [ 0, @@ -74,16 +64,9 @@ } }, "SoundService": { - "$className": "SoundService", "$properties": { "RespectFilteringEnabled": true } - }, - "HttpService": { - "$className": "HttpService", - "$properties": { - "HttpEnabled": true - } } } } \ No newline at end of file From 5364c9c1bc61d0fa90c7af2e7c9479a3918dbb72 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 16 Apr 2020 12:00:02 -0700 Subject: [PATCH 1042/1504] Fix Lua string escaping. Closes #314. --- CHANGELOG.md | 1 + src/lua_ast.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 50 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 34ba10c6..4bd0ed2c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased Changes * Fixed crash when malformed CSV files are put into a project. ([#310](https://github.com/rojo-rbx/rojo/issues/310)) +* Fixed incorrect string escaping when producing Lua code from JSON files. ([#314](https://github.com/rojo-rbx/rojo/issues/314)) * Updated default place template to take advantage of [#210](https://github.com/rojo-rbx/rojo/pull/210). ## [6.0.0 Release Candidate 1](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.1) (March 29, 2020) diff --git a/src/lua_ast.rs b/src/lua_ast.rs index ace9b4d7..b29370b4 100644 --- a/src/lua_ast.rs +++ b/src/lua_ast.rs @@ -21,6 +21,18 @@ trait FmtLua { } } +struct DisplayLua(T); + +impl fmt::Display for DisplayLua +where + T: FmtLua, +{ + fn fmt(&self, output: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut stream = LuaStream::new(output); + self.0.fmt_lua(&mut stream) + } +} + pub(crate) enum Statement { Return(Expression), } @@ -125,16 +137,37 @@ impl FmtLua for f64 { } } +/// Wrapper struct to display the wrapped string using Lua's string escaping +/// rules. +struct LuaEscape<'a>(&'a str); + +impl fmt::Display for LuaEscape<'_> { + fn fmt(&self, output: &mut fmt::Formatter<'_>) -> fmt::Result { + for c in self.0.chars() { + match c { + '"' => output.write_str("\\\"")?, + '\r' => output.write_str("\\r")?, + '\n' => output.write_str("\\n")?, + '\t' => output.write_str("\\t")?, + '\\' => output.write_str("\\\\")?, + _ => output.write_char(c)?, + } + } + + Ok(()) + } +} + impl FmtLua for String { fn fmt_lua(&self, output: &mut LuaStream<'_>) -> fmt::Result { - write!(output, "\"{}\"", self) + write!(output, "\"{}\"", LuaEscape(self)) } fn fmt_table_key(&self, output: &mut LuaStream<'_>) -> fmt::Result { if is_valid_ident(self) { write!(output, "{}", self) } else { - write!(output, "[\"{}\"]", self) + write!(output, "[\"{}\"]", LuaEscape(self)) } } } @@ -277,3 +310,17 @@ impl<'a> LuaStream<'a> { self.inner.write_str("\n") } } + +#[cfg(test)] +mod test { + use super::*; + + /// Regression test for https://github.com/rojo-rbx/rojo/issues/314 + #[test] + fn bug_314() { + let my_value = "\"\r\n\t\\".to_owned(); + let displayed = format!("{}", DisplayLua(my_value)); + + assert_eq!(displayed, "\"\\\"\\r\\n\\t\\\\\""); + } +} From 56bf6d282bbf382dd6577e5db79643b8e70c1387 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 2 May 2020 21:39:13 -0700 Subject: [PATCH 1043/1504] Stop building Rojo in rojo-test, since it doesn't work as intended --- perf-test.sh | 10 ++++++++++ rojo-test/Cargo.toml | 3 --- 2 files changed, 10 insertions(+), 3 deletions(-) create mode 100644 perf-test.sh diff --git a/perf-test.sh b/perf-test.sh new file mode 100644 index 00000000..1dcd00e2 --- /dev/null +++ b/perf-test.sh @@ -0,0 +1,10 @@ +#!/bin/sh +set -e + +cargo build --release + +echo "Known good:" +time rojo build ../uiblox/test-place.project.json -o UIBlox.rbxlx + +echo "Current:" +time ./target/release/rojo build ../uiblox/test-place.project.json -o UIBlox.rbxlx \ No newline at end of file diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index 85dcb8cd..e73f2445 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -24,6 +24,3 @@ tempfile = "3.1.0" walkdir = "2.2.9" rojo-insta-ext = { path = "../rojo-insta-ext" } - -# We execute Rojo via std::process::Command, so depend on it so it's built! -rojo = { path = ".." } From 9481fdd38dac2454e006aa6eb2f13bd992864d56 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 2 May 2020 21:47:36 -0700 Subject: [PATCH 1044/1504] Add missing Cargo.lock change --- Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 73faed7a..430df8b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1988,7 +1988,6 @@ dependencies = [ "paste", "rbx_dom_weak", "reqwest", - "rojo", "rojo-insta-ext", "serde", "serde_json", From ca5b8ab3098372f72129c24082dba2341d6e3f31 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 20 May 2020 11:56:34 -0700 Subject: [PATCH 1045/1504] Restore improperly tested dependency on rojo from rojo-test --- Cargo.lock | 1 + rojo-test/Cargo.toml | 1 + 2 files changed, 2 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 430df8b1..73faed7a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1988,6 +1988,7 @@ dependencies = [ "paste", "rbx_dom_weak", "reqwest", + "rojo", "rojo-insta-ext", "serde", "serde_json", diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml index e73f2445..39d91393 100644 --- a/rojo-test/Cargo.toml +++ b/rojo-test/Cargo.toml @@ -23,4 +23,5 @@ serde_yaml = "0.8.9" tempfile = "3.1.0" walkdir = "2.2.9" +rojo = { path = ".." } rojo-insta-ext = { path = "../rojo-insta-ext" } From 5ccd02939b6ff3af87691a3edc43149859fc918d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 20 May 2020 15:30:05 -0700 Subject: [PATCH 1046/1504] Replace rojo-test with regular tests folder again (#323) * Replace rojo-test with regular tests folder again * Bump MSRV to 1.43.1 --- .github/workflows/ci.yml | 2 +- Cargo.lock | 19 ------------- Cargo.toml | 2 -- README.md | 2 +- rojo-test/Cargo.toml | 27 ------------------- rojo-test/README.md | 8 ------ ..._end__tests__build__client_in_folder.snap} | 2 +- ...nd_to_end__tests__build__client_init.snap} | 2 +- ...nd_to_end__tests__build__csv_bug_145.snap} | 2 +- ...nd_to_end__tests__build__csv_bug_147.snap} | 2 +- ..._to_end__tests__build__csv_in_folder.snap} | 2 +- ...d_to_end__tests__build__deep_nesting.snap} | 2 +- ...=> end_to_end__tests__build__gitkeep.snap} | 2 +- ...end__tests__build__ignore_glob_inner.snap} | 2 +- ...nd__tests__build__ignore_glob_nested.snap} | 2 +- ..._end__tests__build__ignore_glob_spec.snap} | 2 +- ...nd__tests__build__infer_service_name.snap} | 2 +- ...__tests__build__infer_starter_player.snap} | 2 +- ...__tests__build__init_meta_class_name.snap} | 2 +- ...__tests__build__init_meta_properties.snap} | 2 +- ...nd__tests__build__init_with_children.snap} | 2 +- ...nd_to_end__tests__build__json_as_lua.snap} | 2 +- ...__tests__build__json_model_in_folder.snap} | 2 +- ...tests__build__json_model_legacy_name.snap} | 2 +- ..._end__tests__build__module_in_folder.snap} | 2 +- ...nd_to_end__tests__build__module_init.snap} | 2 +- ...to_end__tests__build__rbxm_in_folder.snap} | 2 +- ...o_end__tests__build__rbxmx_in_folder.snap} | 2 +- ... end_to_end__tests__build__rbxmx_ref.snap} | 2 +- ...__tests__build__script_meta_disabled.snap} | 2 +- ..._end__tests__build__server_in_folder.snap} | 2 +- ...nd_to_end__tests__build__server_init.snap} | 2 +- ...nap => end_to_end__tests__build__txt.snap} | 2 +- ..._to_end__tests__build__txt_in_folder.snap} | 2 +- .../rojo_test__build_test__plain.txt.snap | 12 --------- .../rojo_test__build_test__plain_gitkeep.snap | 11 -------- ..._end__tests__serve__add_folder_all-2.snap} | 2 +- ...to_end__tests__serve__add_folder_all.snap} | 2 +- ...o_end__tests__serve__add_folder_info.snap} | 2 +- ...__tests__serve__add_folder_subscribe.snap} | 2 +- ...o_end__tests__serve__edit_init_all-2.snap} | 2 +- ..._to_end__tests__serve__edit_init_all.snap} | 2 +- ...to_end__tests__serve__edit_init_info.snap} | 2 +- ...d__tests__serve__edit_init_subscribe.snap} | 2 +- ... end_to_end__tests__serve__empty_all.snap} | 2 +- ...end_to_end__tests__serve__empty_info.snap} | 2 +- ...s__serve__move_folder_of_stuff_all-2.snap} | 2 +- ...sts__serve__move_folder_of_stuff_all.snap} | 2 +- ...ts__serve__move_folder_of_stuff_info.snap} | 2 +- ...erve__move_folder_of_stuff_subscribe.snap} | 2 +- ...end__tests__serve__remove_file_all-2.snap} | 2 +- ...o_end__tests__serve__remove_file_all.snap} | 2 +- ...o_end__tests__serve__remove_file_info.snap | 9 +++++++ ..._tests__serve__remove_file_subscribe.snap} | 2 +- ..._to_end__tests__serve__scripts_all-2.snap} | 2 +- ...nd_to_end__tests__serve__scripts_all.snap} | 2 +- ...nd_to_end__tests__serve__scripts_info.snap | 9 +++++++ ...end__tests__serve__scripts_subscribe.snap} | 2 +- .../rojo_test__serve_test__just_txt_all.snap | 19 ------------- ...serve_test__move_folder_of_stuff_info.snap | 9 ------- ...jo_test__serve_test__remove_file_info.snap | 9 ------- .../rojo_test__serve_test__scripts_info.snap | 9 ------- rojo-test/src/lib.rs | 7 ----- tests/end_to_end.rs | 2 ++ .../src => tests/rojo_test}/internable.rs | 0 .../src/util.rs => tests/rojo_test/io_util.rs | 23 +++------------- tests/rojo_test/mod.rs | 3 +++ .../src => tests/rojo_test}/serve_util.rs | 16 ++++++----- .../src/build_test.rs => tests/tests/build.rs | 15 ++++++----- tests/tests/mod.rs | 2 ++ .../src/serve_test.rs => tests/tests/serve.rs | 2 +- 71 files changed, 96 insertions(+), 217 deletions(-) delete mode 100644 rojo-test/Cargo.toml delete mode 100644 rojo-test/README.md rename rojo-test/build-test-snapshots/{rojo_test__build_test__client_in_folder.snap => end_to_end__tests__build__client_in_folder.snap} (91%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__client_init.snap => end_to_end__tests__build__client_init.snap} (88%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__csv_bug_145.snap => end_to_end__tests__build__csv_bug_145.snap} (92%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__csv_bug_147.snap => end_to_end__tests__build__csv_bug_147.snap} (96%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__csv_in_folder.snap => end_to_end__tests__build__csv_in_folder.snap} (92%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__deep_nesting.snap => end_to_end__tests__build__deep_nesting.snap} (94%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__gitkeep.snap => end_to_end__tests__build__gitkeep.snap} (83%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__ignore_glob_inner.snap => end_to_end__tests__build__ignore_glob_inner.snap} (96%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__ignore_glob_nested.snap => end_to_end__tests__build__ignore_glob_nested.snap} (91%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__ignore_glob_spec.snap => end_to_end__tests__build__ignore_glob_spec.snap} (92%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__infer_service_name.snap => end_to_end__tests__build__infer_service_name.snap} (95%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__infer_starter_player.snap => end_to_end__tests__build__infer_starter_player.snap} (95%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__init_meta_class_name.snap => end_to_end__tests__build__init_meta_class_name.snap} (84%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__init_meta_properties.snap => end_to_end__tests__build__init_meta_properties.snap} (87%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__init_with_children.snap => end_to_end__tests__build__init_with_children.snap} (92%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__json_as_lua.snap => end_to_end__tests__build__json_as_lua.snap} (91%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__json_model_in_folder.snap => end_to_end__tests__build__json_model_in_folder.snap} (93%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__json_model_legacy_name.snap => end_to_end__tests__build__json_model_legacy_name.snap} (90%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__module_in_folder.snap => end_to_end__tests__build__module_in_folder.snap} (91%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__module_init.snap => end_to_end__tests__build__module_init.snap} (87%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__rbxm_in_folder.snap => end_to_end__tests__build__rbxm_in_folder.snap} (89%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__rbxmx_in_folder.snap => end_to_end__tests__build__rbxmx_in_folder.snap} (96%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__rbxmx_ref.snap => end_to_end__tests__build__rbxmx_ref.snap} (95%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__script_meta_disabled.snap => end_to_end__tests__build__script_meta_disabled.snap} (92%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__server_in_folder.snap => end_to_end__tests__build__server_in_folder.snap} (91%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__server_init.snap => end_to_end__tests__build__server_init.snap} (87%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__txt.snap => end_to_end__tests__build__txt.snap} (87%) rename rojo-test/build-test-snapshots/{rojo_test__build_test__txt_in_folder.snap => end_to_end__tests__build__txt_in_folder.snap} (91%) delete mode 100644 rojo-test/build-test-snapshots/rojo_test__build_test__plain.txt.snap delete mode 100644 rojo-test/build-test-snapshots/rojo_test__build_test__plain_gitkeep.snap rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__add_folder_all-2.snap => end_to_end__tests__serve__add_folder_all-2.snap} (92%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__add_folder_all.snap => end_to_end__tests__serve__add_folder_all.snap} (88%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__just_txt_info.snap => end_to_end__tests__serve__add_folder_info.snap} (81%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__add_folder_subscribe.snap => end_to_end__tests__serve__add_folder_subscribe.snap} (91%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__edit_init_all-2.snap => end_to_end__tests__serve__edit_init_all-2.snap} (90%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__edit_init_all.snap => end_to_end__tests__serve__edit_init_all.snap} (90%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__add_folder_info.snap => end_to_end__tests__serve__edit_init_info.snap} (81%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__edit_init_subscribe.snap => end_to_end__tests__serve__edit_init_subscribe.snap} (91%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__empty_all.snap => end_to_end__tests__serve__empty_all.snap} (88%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__empty_info.snap => end_to_end__tests__serve__empty_info.snap} (81%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__move_folder_of_stuff_all-2.snap => end_to_end__tests__serve__move_folder_of_stuff_all-2.snap} (98%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__move_folder_of_stuff_all.snap => end_to_end__tests__serve__move_folder_of_stuff_all.snap} (89%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__edit_init_info.snap => end_to_end__tests__serve__move_folder_of_stuff_info.snap} (81%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__move_folder_of_stuff_subscribe.snap => end_to_end__tests__serve__move_folder_of_stuff_subscribe.snap} (98%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__remove_file_all-2.snap => end_to_end__tests__serve__remove_file_all-2.snap} (88%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__remove_file_all.snap => end_to_end__tests__serve__remove_file_all.snap} (93%) create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_info.snap rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__remove_file_subscribe.snap => end_to_end__tests__serve__remove_file_subscribe.snap} (83%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__scripts_all-2.snap => end_to_end__tests__serve__scripts_all-2.snap} (95%) rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__scripts_all.snap => end_to_end__tests__serve__scripts_all.snap} (95%) create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_info.snap rename rojo-test/serve-test-snapshots/{rojo_test__serve_test__scripts_subscribe.snap => end_to_end__tests__serve__scripts_subscribe.snap} (90%) delete mode 100644 rojo-test/serve-test-snapshots/rojo_test__serve_test__just_txt_all.snap delete mode 100644 rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_info.snap delete mode 100644 rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_info.snap delete mode 100644 rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_info.snap delete mode 100644 rojo-test/src/lib.rs create mode 100644 tests/end_to_end.rs rename {rojo-test/src => tests/rojo_test}/internable.rs (100%) rename rojo-test/src/util.rs => tests/rojo_test/io_util.rs (70%) create mode 100644 tests/rojo_test/mod.rs rename {rojo-test/src => tests/rojo_test}/serve_util.rs (93%) rename rojo-test/src/build_test.rs => tests/tests/build.rs (84%) create mode 100644 tests/tests/mod.rs rename rojo-test/src/serve_test.rs => tests/tests/serve.rs (98%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ffe614ea..62179d8b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,7 +12,7 @@ jobs: strategy: matrix: - rust_version: [stable, "1.40.0"] + rust_version: [stable, "1.43.1"] steps: - uses: actions/checkout@v1 diff --git a/Cargo.lock b/Cargo.lock index 73faed7a..21ddc3c4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1978,25 +1978,6 @@ dependencies = [ "serde_yaml", ] -[[package]] -name = "rojo-test" -version = "0.1.0" -dependencies = [ - "env_logger", - "insta", - "log", - "paste", - "rbx_dom_weak", - "reqwest", - "rojo", - "rojo-insta-ext", - "serde", - "serde_json", - "serde_yaml", - "tempfile", - "walkdir", -] - [[package]] name = "rust-argon2" version = "0.7.0" diff --git a/Cargo.toml b/Cargo.toml index 818dd973..772560fe 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -31,7 +31,6 @@ dev_live_assets = [] [workspace] members = [ - "rojo-test", "rojo-insta-ext", "clibrojo", "memofs", @@ -39,7 +38,6 @@ members = [ default-members = [ ".", - "rojo-test", "rojo-insta-ext", "memofs", ] diff --git a/README.md b/README.md index 4ab247ec..edf89258 100644 --- a/README.md +++ b/README.md @@ -48,7 +48,7 @@ Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions fo Pull requests are welcome! -Rojo supports Rust 1.40.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. +Rojo supports Rust 1.43.1 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. ## License Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file diff --git a/rojo-test/Cargo.toml b/rojo-test/Cargo.toml deleted file mode 100644 index 39d91393..00000000 --- a/rojo-test/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "rojo-test" -version = "0.1.0" -authors = ["Lucien Greathouse "] -edition = "2018" -publish = false - -[features] -default = [] - -unstable_glob_ignore_paths = [] - -[dependencies] -env_logger = "0.7.1" -insta = { version = "0.13.1", features = ["redactions"] } -log = "0.4.8" -paste = "0.1.5" -rbx_dom_weak = "1.9.0" -reqwest = "0.9.20" -serde = "1.0.99" -serde_json = "1.0.40" -serde_yaml = "0.8.9" -tempfile = "3.1.0" -walkdir = "2.2.9" - -rojo = { path = ".." } -rojo-insta-ext = { path = "../rojo-insta-ext" } diff --git a/rojo-test/README.md b/rojo-test/README.md deleted file mode 100644 index 166044a1..00000000 --- a/rojo-test/README.md +++ /dev/null @@ -1,8 +0,0 @@ -# rojo-test -This project does end-to-end testing of Rojo by executing it and checking what side-effects it has. - -rojo-test is meant to be run as a test with: - -```bash -cargo test -``` \ No newline at end of file diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__client_in_folder.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__client_in_folder.snap similarity index 91% rename from rojo-test/build-test-snapshots/rojo_test__build_test__client_in_folder.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__client_in_folder.snap index 27695545..3953fcb6 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__client_in_folder.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__client_in_folder.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__client_init.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__client_init.snap similarity index 88% rename from rojo-test/build-test-snapshots/rojo_test__build_test__client_init.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__client_init.snap index eacede5a..f3391ebe 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__client_init.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__client_init.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__csv_bug_145.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_145.snap similarity index 92% rename from rojo-test/build-test-snapshots/rojo_test__build_test__csv_bug_145.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_145.snap index 48146d39..ab7470b3 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__csv_bug_145.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_145.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__csv_bug_147.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_147.snap similarity index 96% rename from rojo-test/build-test-snapshots/rojo_test__build_test__csv_bug_147.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_147.snap index defea874..d16de20f 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__csv_bug_147.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_147.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__csv_in_folder.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_in_folder.snap similarity index 92% rename from rojo-test/build-test-snapshots/rojo_test__build_test__csv_in_folder.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__csv_in_folder.snap index 3917a988..d60fca02 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__csv_in_folder.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_in_folder.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__deep_nesting.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__deep_nesting.snap similarity index 94% rename from rojo-test/build-test-snapshots/rojo_test__build_test__deep_nesting.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__deep_nesting.snap index 9e4dc471..18e0bab6 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__deep_nesting.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__deep_nesting.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__gitkeep.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__gitkeep.snap similarity index 83% rename from rojo-test/build-test-snapshots/rojo_test__build_test__gitkeep.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__gitkeep.snap index fe025fc9..003a210d 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__gitkeep.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__gitkeep.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_inner.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__ignore_glob_inner.snap similarity index 96% rename from rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_inner.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__ignore_glob_inner.snap index 9ff1bdec..338493fd 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_inner.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__ignore_glob_inner.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_nested.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__ignore_glob_nested.snap similarity index 91% rename from rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_nested.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__ignore_glob_nested.snap index aab8afaf..7d6b063d 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_nested.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__ignore_glob_nested.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_spec.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__ignore_glob_spec.snap similarity index 92% rename from rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_spec.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__ignore_glob_spec.snap index 7fc338f9..4d427f15 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__ignore_glob_spec.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__ignore_glob_spec.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__infer_service_name.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__infer_service_name.snap similarity index 95% rename from rojo-test/build-test-snapshots/rojo_test__build_test__infer_service_name.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__infer_service_name.snap index bda746ce..98b92a46 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__infer_service_name.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__infer_service_name.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__infer_starter_player.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__infer_starter_player.snap similarity index 95% rename from rojo-test/build-test-snapshots/rojo_test__build_test__infer_starter_player.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__infer_starter_player.snap index 13574f23..6e9e5fc0 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__infer_starter_player.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__infer_starter_player.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__init_meta_class_name.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__init_meta_class_name.snap similarity index 84% rename from rojo-test/build-test-snapshots/rojo_test__build_test__init_meta_class_name.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__init_meta_class_name.snap index 8a5f8a06..889fca12 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__init_meta_class_name.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__init_meta_class_name.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__init_meta_properties.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__init_meta_properties.snap similarity index 87% rename from rojo-test/build-test-snapshots/rojo_test__build_test__init_meta_properties.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__init_meta_properties.snap index 5d24b949..0613bbe8 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__init_meta_properties.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__init_meta_properties.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__init_with_children.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__init_with_children.snap similarity index 92% rename from rojo-test/build-test-snapshots/rojo_test__build_test__init_with_children.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__init_with_children.snap index 98f2f030..09346fe4 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__init_with_children.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__init_with_children.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__json_as_lua.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__json_as_lua.snap similarity index 91% rename from rojo-test/build-test-snapshots/rojo_test__build_test__json_as_lua.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__json_as_lua.snap index 8fcead0a..9ce0846c 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__json_as_lua.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__json_as_lua.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__json_model_in_folder.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__json_model_in_folder.snap similarity index 93% rename from rojo-test/build-test-snapshots/rojo_test__build_test__json_model_in_folder.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__json_model_in_folder.snap index 67013a05..cf1dba88 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__json_model_in_folder.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__json_model_in_folder.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__json_model_legacy_name.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__json_model_legacy_name.snap similarity index 90% rename from rojo-test/build-test-snapshots/rojo_test__build_test__json_model_legacy_name.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__json_model_legacy_name.snap index 0a0b7fba..ba8299cf 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__json_model_legacy_name.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__json_model_legacy_name.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__module_in_folder.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__module_in_folder.snap similarity index 91% rename from rojo-test/build-test-snapshots/rojo_test__build_test__module_in_folder.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__module_in_folder.snap index 6a73f1fd..91a79007 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__module_in_folder.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__module_in_folder.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__module_init.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__module_init.snap similarity index 87% rename from rojo-test/build-test-snapshots/rojo_test__build_test__module_init.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__module_init.snap index e6cd09e3..52737a9e 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__module_init.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__module_init.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__rbxm_in_folder.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxm_in_folder.snap similarity index 89% rename from rojo-test/build-test-snapshots/rojo_test__build_test__rbxm_in_folder.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__rbxm_in_folder.snap index f67a3d9e..81296c91 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__rbxm_in_folder.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxm_in_folder.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_in_folder.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_in_folder.snap similarity index 96% rename from rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_in_folder.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_in_folder.snap index 21a7a396..92cab199 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_in_folder.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_in_folder.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_ref.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_ref.snap similarity index 95% rename from rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_ref.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_ref.snap index 26ada371..1f1e21a2 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__rbxmx_ref.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_ref.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__script_meta_disabled.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__script_meta_disabled.snap similarity index 92% rename from rojo-test/build-test-snapshots/rojo_test__build_test__script_meta_disabled.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__script_meta_disabled.snap index 45f01e48..0876056e 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__script_meta_disabled.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__script_meta_disabled.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__server_in_folder.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__server_in_folder.snap similarity index 91% rename from rojo-test/build-test-snapshots/rojo_test__build_test__server_in_folder.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__server_in_folder.snap index 006917b2..282889d0 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__server_in_folder.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__server_in_folder.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__server_init.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__server_init.snap similarity index 87% rename from rojo-test/build-test-snapshots/rojo_test__build_test__server_init.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__server_init.snap index 9aa4fa5e..070b7012 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__server_init.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__server_init.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__txt.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__txt.snap similarity index 87% rename from rojo-test/build-test-snapshots/rojo_test__build_test__txt.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__txt.snap index 004b83c1..85159a12 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__txt.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__txt.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__txt_in_folder.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__txt_in_folder.snap similarity index 91% rename from rojo-test/build-test-snapshots/rojo_test__build_test__txt_in_folder.snap rename to rojo-test/build-test-snapshots/end_to_end__tests__build__txt_in_folder.snap index cc6ba42d..ca297d2a 100644 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__txt_in_folder.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__txt_in_folder.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/build_test.rs +source: tests/tests/build.rs expression: contents --- diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__plain.txt.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__plain.txt.snap deleted file mode 100644 index bd9ec616..00000000 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__plain.txt.snap +++ /dev/null @@ -1,12 +0,0 @@ ---- -source: rojo-test/src/build_test.rs -expression: contents ---- - - - - plain - This is a bare text file with no project. - - - diff --git a/rojo-test/build-test-snapshots/rojo_test__build_test__plain_gitkeep.snap b/rojo-test/build-test-snapshots/rojo_test__build_test__plain_gitkeep.snap deleted file mode 100644 index ccf37852..00000000 --- a/rojo-test/build-test-snapshots/rojo_test__build_test__plain_gitkeep.snap +++ /dev/null @@ -1,11 +0,0 @@ ---- -source: rojo-test/src/build_test.rs -expression: contents ---- - - - - plain_gitkeep - - - diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all-2.snap similarity index 92% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_all-2.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all-2.snap index 379aa949..29d3b553 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_all-2.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all-2.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all.snap similarity index 88% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_all.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all.snap index 53d11e9b..fc902c99 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_all.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__just_txt_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_info.snap similarity index 81% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__just_txt_info.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_info.snap index ffc35c89..62f5dc4b 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__just_txt_info.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_info.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: redactions.redacted_yaml(info) --- expectedPlaceIds: ~ diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_subscribe.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_subscribe.snap similarity index 91% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_subscribe.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_subscribe.snap index 49d489dc..09d4512c 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_subscribe.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_subscribe.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "subscribe_response.intern_and_redact(&mut redactions, ())" --- messageCursor: 1 diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all-2.snap similarity index 90% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_all-2.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all-2.snap index d11fbb4b..688f72d6 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_all-2.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all-2.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all.snap similarity index 90% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_all.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all.snap index 9596f3a8..a484d8e2 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_all.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_info.snap similarity index 81% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_info.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_info.snap index ffc35c89..62f5dc4b 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__add_folder_info.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_info.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: redactions.redacted_yaml(info) --- expectedPlaceIds: ~ diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_subscribe.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_subscribe.snap similarity index 91% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_subscribe.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_subscribe.snap index ef6a4fc8..bb3f9990 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_subscribe.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_subscribe.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "subscribe_response.intern_and_redact(&mut redactions, ())" --- messageCursor: 1 diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__empty_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_all.snap similarity index 88% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__empty_all.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_all.snap index 7aca5205..188f854f 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__empty_all.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_all.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__empty_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_info.snap similarity index 81% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__empty_info.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_info.snap index ffc35c89..62f5dc4b 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__empty_info.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_info.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: redactions.redacted_yaml(info) --- expectedPlaceIds: ~ diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all-2.snap similarity index 98% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_all-2.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all-2.snap index d73ce024..96e5126e 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_all-2.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all-2.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all.snap similarity index 89% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_all.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all.snap index 2f0cfd81..1f189d00 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_all.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_info.snap similarity index 81% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_info.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_info.snap index ffc35c89..62f5dc4b 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__edit_init_info.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_info.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: redactions.redacted_yaml(info) --- expectedPlaceIds: ~ diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_subscribe.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_subscribe.snap similarity index 98% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_subscribe.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_subscribe.snap index fa026ed2..9f544c5c 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_subscribe.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_subscribe.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "subscribe_response.intern_and_redact(&mut redactions, ())" --- messageCursor: 1 diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all-2.snap similarity index 88% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_all-2.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all-2.snap index ce9ed750..b3c0a7fd 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_all-2.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all-2.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all.snap similarity index 93% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_all.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all.snap index e133c4ea..8534c320 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_all.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_info.snap new file mode 100644 index 00000000..62f5dc4b --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_info.snap @@ -0,0 +1,9 @@ +--- +source: tests/tests/serve.rs +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +protocolVersion: 3 +rootInstanceId: id-2 +serverVersion: "[server-version]" +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_subscribe.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_subscribe.snap similarity index 83% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_subscribe.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_subscribe.snap index e4f34a28..e70d17f9 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_subscribe.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_subscribe.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "subscribe_response.intern_and_redact(&mut redactions, ())" --- messageCursor: 1 diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all-2.snap similarity index 95% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_all-2.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all-2.snap index edc0daef..7571797f 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_all-2.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all-2.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all.snap similarity index 95% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_all.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all.snap index 64542c22..6f67d05c 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_all.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "read_response.intern_and_redact(&mut redactions, root_id)" --- instances: diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_info.snap new file mode 100644 index 00000000..62f5dc4b --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_info.snap @@ -0,0 +1,9 @@ +--- +source: tests/tests/serve.rs +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +protocolVersion: 3 +rootInstanceId: id-2 +serverVersion: "[server-version]" +sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_subscribe.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_subscribe.snap similarity index 90% rename from rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_subscribe.snap rename to rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_subscribe.snap index 7d52bc4d..4b373663 100644 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_subscribe.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_subscribe.snap @@ -1,5 +1,5 @@ --- -source: rojo-test/src/serve_test.rs +source: tests/tests/serve.rs expression: "subscribe_response.intern_and_redact(&mut redactions, ())" --- messageCursor: 1 diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__just_txt_all.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__just_txt_all.snap deleted file mode 100644 index e67add37..00000000 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__just_txt_all.snap +++ /dev/null @@ -1,19 +0,0 @@ ---- -source: rojo-test/src/serve_test.rs -expression: "read_response.intern_and_redact(&mut redactions, root_id)" ---- -instances: - id-2: - Children: [] - ClassName: StringValue - Id: id-2 - Metadata: - ignoreUnknownInstances: false - Name: just_txt - Parent: ~ - Properties: - Value: - Type: String - Value: "Hello, world!" -messageCursor: 0 -sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_info.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_info.snap deleted file mode 100644 index ffc35c89..00000000 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__move_folder_of_stuff_info.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: rojo-test/src/serve_test.rs -expression: redactions.redacted_yaml(info) ---- -expectedPlaceIds: ~ -protocolVersion: 3 -rootInstanceId: id-2 -serverVersion: "[server-version]" -sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_info.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_info.snap deleted file mode 100644 index ffc35c89..00000000 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__remove_file_info.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: rojo-test/src/serve_test.rs -expression: redactions.redacted_yaml(info) ---- -expectedPlaceIds: ~ -protocolVersion: 3 -rootInstanceId: id-2 -serverVersion: "[server-version]" -sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_info.snap b/rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_info.snap deleted file mode 100644 index ffc35c89..00000000 --- a/rojo-test/serve-test-snapshots/rojo_test__serve_test__scripts_info.snap +++ /dev/null @@ -1,9 +0,0 @@ ---- -source: rojo-test/src/serve_test.rs -expression: redactions.redacted_yaml(info) ---- -expectedPlaceIds: ~ -protocolVersion: 3 -rootInstanceId: id-2 -serverVersion: "[server-version]" -sessionId: id-1 diff --git a/rojo-test/src/lib.rs b/rojo-test/src/lib.rs deleted file mode 100644 index cd4e7461..00000000 --- a/rojo-test/src/lib.rs +++ /dev/null @@ -1,7 +0,0 @@ -#![cfg(test)] - -mod build_test; -mod internable; -mod serve_test; -mod serve_util; -mod util; diff --git a/tests/end_to_end.rs b/tests/end_to_end.rs new file mode 100644 index 00000000..3e191799 --- /dev/null +++ b/tests/end_to_end.rs @@ -0,0 +1,2 @@ +mod rojo_test; +mod tests; diff --git a/rojo-test/src/internable.rs b/tests/rojo_test/internable.rs similarity index 100% rename from rojo-test/src/internable.rs rename to tests/rojo_test/internable.rs diff --git a/rojo-test/src/util.rs b/tests/rojo_test/io_util.rs similarity index 70% rename from rojo-test/src/util.rs rename to tests/rojo_test/io_util.rs index e0b59f87..b060be65 100644 --- a/rojo-test/src/util.rs +++ b/tests/rojo_test/io_util.rs @@ -6,16 +6,9 @@ use std::{ use walkdir::WalkDir; -pub fn get_rojo_path() -> PathBuf { - let working_dir = get_working_dir_path(); - - let mut exe_path = working_dir.join("target/debug/rojo"); - if cfg!(windows) { - exe_path.set_extension("exe"); - } - - exe_path -} +pub static ROJO_PATH: &str = env!("CARGO_BIN_EXE_rojo"); +pub static BUILD_TESTS_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/rojo-test/build-tests"); +pub static SERVE_TESTS_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/rojo-test/serve-tests"); pub fn get_working_dir_path() -> PathBuf { let mut manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); @@ -26,16 +19,6 @@ pub fn get_working_dir_path() -> PathBuf { manifest_dir } -pub fn get_build_tests_path() -> PathBuf { - let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); - manifest_dir.join("build-tests") -} - -pub fn get_serve_tests_path() -> PathBuf { - let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); - manifest_dir.join("serve-tests") -} - /// Recursively walk a directory and copy each item to the equivalent location /// in another directory. Equivalent to `cp -r src/* dst` pub fn copy_recursive(from: &Path, to: &Path) -> io::Result<()> { diff --git a/tests/rojo_test/mod.rs b/tests/rojo_test/mod.rs new file mode 100644 index 00000000..fd0cda3a --- /dev/null +++ b/tests/rojo_test/mod.rs @@ -0,0 +1,3 @@ +pub mod internable; +pub mod io_util; +pub mod serve_util; diff --git a/rojo-test/src/serve_util.rs b/tests/rojo_test/serve_util.rs similarity index 93% rename from rojo-test/src/serve_util.rs rename to tests/rojo_test/serve_util.rs index 918f5c32..d38eb2c7 100644 --- a/rojo-test/src/serve_util.rs +++ b/tests/rojo_test/serve_util.rs @@ -14,8 +14,8 @@ use tempfile::{tempdir, TempDir}; use librojo::web_api::{ReadResponse, ServerInfoResponse, SubscribeResponse}; use rojo_insta_ext::RedactionMap; -use crate::util::{ - copy_recursive, get_rojo_path, get_serve_tests_path, get_working_dir_path, KillOnDrop, +use crate::rojo_test::io_util::{ + copy_recursive, get_working_dir_path, KillOnDrop, ROJO_PATH, SERVE_TESTS_PATH, }; /// Convenience method to run a `rojo serve` test. @@ -38,7 +38,11 @@ pub fn run_serve_test(test_name: &str, callback: impl FnOnce(TestServeSession, R let mut settings = insta::Settings::new(); - let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("serve-test-snapshots"); + let snapshot_path = Path::new(SERVE_TESTS_PATH) + .parent() + .unwrap() + .join("serve-test-snapshots"); + settings.set_snapshot_path(snapshot_path); settings.set_sort_maps(true); settings.add_redaction(".serverVersion", "[server-version]"); @@ -58,11 +62,9 @@ pub struct TestServeSession { impl TestServeSession { pub fn new(name: &str) -> Self { - let serve_test_path = get_serve_tests_path(); let working_dir = get_working_dir_path(); - let exe_path = get_rojo_path(); - let source_path = serve_test_path.join(name); + let source_path = Path::new(SERVE_TESTS_PATH).join(name); let dir = tempdir().expect("Couldn't create temporary directory"); let project_path = dir.path().join(name); @@ -80,7 +82,7 @@ impl TestServeSession { let port = get_port_number(); let port_string = port.to_string(); - let rojo_process = Command::new(exe_path) + let rojo_process = Command::new(ROJO_PATH) .args(&[ "serve", project_path.to_str().unwrap(), diff --git a/rojo-test/src/build_test.rs b/tests/tests/build.rs similarity index 84% rename from rojo-test/src/build_test.rs rename to tests/tests/build.rs index f0d6424d..2f5fc76a 100644 --- a/rojo-test/src/build_test.rs +++ b/tests/tests/build.rs @@ -3,7 +3,7 @@ use std::{fs, path::Path, process::Command}; use insta::assert_snapshot; use tempfile::tempdir; -use crate::util::{get_build_tests_path, get_rojo_path, get_working_dir_path}; +use crate::rojo_test::io_util::{get_working_dir_path, BUILD_TESTS_PATH, ROJO_PATH}; macro_rules! gen_build_tests { ( $($test_name: ident,)* ) => { @@ -56,17 +56,14 @@ gen_build_tests! { } fn run_build_test(test_name: &str) { - let build_test_path = get_build_tests_path(); let working_dir = get_working_dir_path(); - let input_path = build_test_path.join(test_name); + let input_path = Path::new(BUILD_TESTS_PATH).join(test_name); let output_dir = tempdir().expect("couldn't create temporary directory"); let output_path = output_dir.path().join(format!("{}.rbxmx", test_name)); - let exe_path = get_rojo_path(); - - let status = Command::new(exe_path) + let status = Command::new(ROJO_PATH) .args(&[ "build", input_path.to_str().unwrap(), @@ -84,7 +81,11 @@ fn run_build_test(test_name: &str) { let mut settings = insta::Settings::new(); - let snapshot_path = Path::new(env!("CARGO_MANIFEST_DIR")).join("build-test-snapshots"); + let snapshot_path = Path::new(BUILD_TESTS_PATH) + .parent() + .unwrap() + .join("build-test-snapshots"); + settings.set_snapshot_path(snapshot_path); settings.bind(|| { diff --git a/tests/tests/mod.rs b/tests/tests/mod.rs new file mode 100644 index 00000000..a348e228 --- /dev/null +++ b/tests/tests/mod.rs @@ -0,0 +1,2 @@ +mod build; +mod serve; diff --git a/rojo-test/src/serve_test.rs b/tests/tests/serve.rs similarity index 98% rename from rojo-test/src/serve_test.rs rename to tests/tests/serve.rs index daac30e2..61912275 100644 --- a/rojo-test/src/serve_test.rs +++ b/tests/tests/serve.rs @@ -3,7 +3,7 @@ use std::fs; use insta::assert_yaml_snapshot; use tempfile::tempdir; -use crate::{internable::InternAndRedact, serve_util::run_serve_test}; +use crate::rojo_test::{internable::InternAndRedact, serve_util::run_serve_test}; #[test] fn empty() { From bdd1afea5779da69931e43359e62095d8864d6f6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 20 May 2020 15:30:44 -0700 Subject: [PATCH 1047/1504] Run CI on master and PRs to master only --- .github/workflows/ci.yml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 62179d8b..004858c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,9 +1,13 @@ name: CI on: - pull_request: push: - branches: ["*"] + branches: + - master + + pull_request: + branches: + - master jobs: build: From 486b067567f3771910b6e08100e17dc830ba1005 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 17 Jun 2020 13:47:09 -0700 Subject: [PATCH 1048/1504] Flatten snapshot middleware to be much simpler (#324) * First take at flattening middleware for simpler code and better perf * Undo debug prints * Fix using wrong path in snapshot_from_vfs * Disable some broken tests * Re-enable (mistakenly?) disabled CSV test * Fix some tests * Update project file tests * Fix benchmark --- benches/build.rs | 1 + src/snapshot_middleware/csv.rs | 97 ++++---- src/snapshot_middleware/dir.rs | 124 +++++----- src/snapshot_middleware/json.rs | 89 +++---- src/snapshot_middleware/json_model.rs | 94 +++----- src/snapshot_middleware/lua.rs | 97 +++----- src/snapshot_middleware/middleware.rs | 10 +- src/snapshot_middleware/mod.rs | 117 +++++---- src/snapshot_middleware/project.rs | 226 +++++++++--------- src/snapshot_middleware/rbxlx.rs | 46 ---- src/snapshot_middleware/rbxm.rs | 74 +++--- src/snapshot_middleware/rbxmx.rs | 66 +++-- ..._project__test__project_with_children.snap | 6 +- ...ct_with_path_to_project_with_children.snap | 2 +- ...est__project_with_resolved_properties.snap | 4 +- ...t__project_with_unresolved_properties.snap | 4 +- src/snapshot_middleware/txt.rs | 89 ++++--- src/snapshot_middleware/user_plugins.rs | 56 ----- 18 files changed, 489 insertions(+), 713 deletions(-) delete mode 100644 src/snapshot_middleware/rbxlx.rs delete mode 100644 src/snapshot_middleware/user_plugins.rs diff --git a/benches/build.rs b/benches/build.rs index 802f43a3..0b1e8934 100644 --- a/benches/build.rs +++ b/benches/build.rs @@ -35,6 +35,7 @@ fn place_setup>(input_path: P) -> (TempDir, BuildCommand) { let options = BuildCommand { project: input, + watch: false, output, }; diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 72075a3e..fcd358f6 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -8,54 +8,41 @@ use serde::Serialize; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ - error::SnapshotError, - meta_file::AdjacentMetadata, - middleware::{SnapshotInstanceResult, SnapshotMiddleware}, - util::match_file_name, + error::SnapshotError, meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult, }; -pub struct SnapshotCsv; +pub fn snapshot_csv( + _context: &InstanceContext, + vfs: &Vfs, + path: &Path, + instance_name: &str, +) -> SnapshotInstanceResult { + let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); + let contents = vfs.read(path)?; -impl SnapshotMiddleware for SnapshotCsv { - fn from_vfs(_context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { - let meta = vfs.metadata(path)?; + let table_contents = convert_localization_csv(&contents) + .map_err(|source| SnapshotError::malformed_l10n_csv(source, path))?; - if meta.is_dir() { - return Ok(None); - } + let mut snapshot = InstanceSnapshot::new() + .name(instance_name) + .class_name("LocalizationTable") + .properties(hashmap! { + "Contents".to_owned() => RbxValue::String { + value: table_contents, + }, + }) + .metadata( + InstanceMetadata::new() + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf(), meta_path.clone()]), + ); - let instance_name = match match_file_name(path, ".csv") { - Some(name) => name, - None => return Ok(None), - }; - - let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); - let contents = vfs.read(path)?; - - let table_contents = convert_localization_csv(&contents) - .map_err(|source| SnapshotError::malformed_l10n_csv(source, path))?; - - let mut snapshot = InstanceSnapshot::new() - .name(instance_name) - .class_name("LocalizationTable") - .properties(hashmap! { - "Contents".to_owned() => RbxValue::String { - value: table_contents, - }, - }) - .metadata( - InstanceMetadata::new() - .instigating_source(path) - .relevant_paths(vec![path.to_path_buf(), meta_path.clone()]), - ); - - if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { - let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; - metadata.apply_all(&mut snapshot); - } - - Ok(Some(snapshot)) + if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { + let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; + metadata.apply_all(&mut snapshot); } + + Ok(Some(snapshot)) } /// Struct that holds any valid row from a Roblox CSV translation table. @@ -156,10 +143,14 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, let mut vfs = Vfs::new(imfs); - let instance_snapshot = - SnapshotCsv::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo.csv")) - .unwrap() - .unwrap(); + let instance_snapshot = snapshot_csv( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.csv"), + "foo", + ) + .unwrap() + .unwrap(); insta::assert_yaml_snapshot!(instance_snapshot); } @@ -184,9 +175,15 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, let mut vfs = Vfs::new(imfs); - let instance_snapshot = - SnapshotCsv::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo.csv")) - .unwrap() - .unwrap(); + let instance_snapshot = snapshot_csv( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.csv"), + "foo", + ) + .unwrap() + .unwrap(); + + insta::assert_yaml_snapshot!(instance_snapshot); } } diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 8e9bb932..359856d0 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -5,81 +5,69 @@ use memofs::{DirEntry, IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ - error::SnapshotError, - meta_file::DirectoryMetadata, - middleware::{SnapshotInstanceResult, SnapshotMiddleware}, + error::SnapshotError, meta_file::DirectoryMetadata, middleware::SnapshotInstanceResult, snapshot_from_vfs, }; -pub struct SnapshotDir; +pub fn snapshot_dir(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { + let passes_filter_rules = |child: &DirEntry| { + context + .path_ignore_rules + .iter() + .all(|rule| rule.passes(child.path())) + }; -impl SnapshotMiddleware for SnapshotDir { - fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { - let meta = vfs.metadata(path)?; + let mut snapshot_children = Vec::new(); - if meta.is_file() { - return Ok(None); + for entry in vfs.read_dir(path)? { + let entry = entry?; + + if !passes_filter_rules(&entry) { + continue; } - let passes_filter_rules = |child: &DirEntry| { - context - .path_ignore_rules - .iter() - .all(|rule| rule.passes(child.path())) - }; - - let mut snapshot_children = Vec::new(); - - for entry in vfs.read_dir(path)? { - let entry = entry?; - - if !passes_filter_rules(&entry) { - continue; - } - - if let Some(child_snapshot) = snapshot_from_vfs(context, vfs, entry.path())? { - snapshot_children.push(child_snapshot); - } + if let Some(child_snapshot) = snapshot_from_vfs(context, vfs, entry.path())? { + snapshot_children.push(child_snapshot); } - - let instance_name = path - .file_name() - .expect("Could not extract file name") - .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(path))? - .to_string(); - - let meta_path = path.join("init.meta.json"); - - let relevant_paths = vec![ - path.to_path_buf(), - meta_path.clone(), - // TODO: We shouldn't need to know about Lua existing in this - // middleware. Should we figure out a way for that function to add - // relevant paths to this middleware? - path.join("init.lua"), - path.join("init.server.lua"), - path.join("init.client.lua"), - ]; - - let mut snapshot = InstanceSnapshot::new() - .name(instance_name) - .class_name("Folder") - .children(snapshot_children) - .metadata( - InstanceMetadata::new() - .instigating_source(path) - .relevant_paths(relevant_paths) - .context(context), - ); - - if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { - let mut metadata = DirectoryMetadata::from_slice(&meta_contents, &meta_path)?; - metadata.apply_all(&mut snapshot); - } - - Ok(Some(snapshot)) } + + let instance_name = path + .file_name() + .expect("Could not extract file name") + .to_str() + .ok_or_else(|| SnapshotError::file_name_bad_unicode(path))? + .to_string(); + + let meta_path = path.join("init.meta.json"); + + let relevant_paths = vec![ + path.to_path_buf(), + meta_path.clone(), + // TODO: We shouldn't need to know about Lua existing in this + // middleware. Should we figure out a way for that function to add + // relevant paths to this middleware? + path.join("init.lua"), + path.join("init.server.lua"), + path.join("init.client.lua"), + ]; + + let mut snapshot = InstanceSnapshot::new() + .name(instance_name) + .class_name("Folder") + .children(snapshot_children) + .metadata( + InstanceMetadata::new() + .instigating_source(path) + .relevant_paths(relevant_paths) + .context(context), + ); + + if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { + let mut metadata = DirectoryMetadata::from_slice(&meta_contents, &meta_path)?; + metadata.apply_all(&mut snapshot); + } + + Ok(Some(snapshot)) } #[cfg(test)] @@ -98,7 +86,7 @@ mod test { let mut vfs = Vfs::new(imfs); let instance_snapshot = - SnapshotDir::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) + snapshot_dir(&InstanceContext::default(), &mut vfs, Path::new("/foo")) .unwrap() .unwrap(); @@ -119,7 +107,7 @@ mod test { let mut vfs = Vfs::new(imfs); let instance_snapshot = - SnapshotDir::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) + snapshot_dir(&InstanceContext::default(), &mut vfs, Path::new("/foo")) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/json.rs b/src/snapshot_middleware/json.rs index 4b3508e3..15efe21b 100644 --- a/src/snapshot_middleware/json.rs +++ b/src/snapshot_middleware/json.rs @@ -10,69 +10,47 @@ use crate::{ }; use super::{ - error::SnapshotError, - meta_file::AdjacentMetadata, - middleware::{SnapshotInstanceResult, SnapshotMiddleware}, - util::match_file_name, + error::SnapshotError, meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult, }; -/// Catch-all middleware for snapshots on JSON files that aren't used for other -/// features, like Rojo projects, JSON models, or meta files. -pub struct SnapshotJson; +pub fn snapshot_json( + context: &InstanceContext, + vfs: &Vfs, + path: &Path, + instance_name: &str, +) -> SnapshotInstanceResult { + let contents = vfs.read(path)?; -impl SnapshotMiddleware for SnapshotJson { - fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { - let meta = vfs.metadata(path)?; + let value: serde_json::Value = serde_json::from_slice(&contents) + .map_err(|err| SnapshotError::malformed_json(err, path))?; - if meta.is_dir() { - return Ok(None); - } + let as_lua = json_to_lua(value).to_string(); - // FIXME: This middleware should not need to know about the .meta.json - // middleware. Should there be a way to signal "I'm not returning an - // instance and no one should"? - if match_file_name(path, ".meta.json").is_some() { - return Ok(None); - } + let properties = hashmap! { + "Source".to_owned() => RbxValue::String { + value: as_lua, + }, + }; - let instance_name = match match_file_name(path, ".json") { - Some(name) => name, - None => return Ok(None), - }; + let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); - let contents = vfs.read(path)?; + let mut snapshot = InstanceSnapshot::new() + .name(instance_name) + .class_name("ModuleScript") + .properties(properties) + .metadata( + InstanceMetadata::new() + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf(), meta_path.clone()]) + .context(context), + ); - let value: serde_json::Value = serde_json::from_slice(&contents) - .map_err(|err| SnapshotError::malformed_json(err, path))?; - - let as_lua = json_to_lua(value).to_string(); - - let properties = hashmap! { - "Source".to_owned() => RbxValue::String { - value: as_lua, - }, - }; - - let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); - - let mut snapshot = InstanceSnapshot::new() - .name(instance_name) - .class_name("ModuleScript") - .properties(properties) - .metadata( - InstanceMetadata::new() - .instigating_source(path) - .relevant_paths(vec![path.to_path_buf(), meta_path.clone()]) - .context(context), - ); - - if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { - let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; - metadata.apply_all(&mut snapshot); - } - - Ok(Some(snapshot)) + if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { + let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; + metadata.apply_all(&mut snapshot); } + + Ok(Some(snapshot)) } fn json_to_lua(value: serde_json::Value) -> Statement { @@ -129,10 +107,11 @@ mod test { let mut vfs = Vfs::new(imfs.clone()); - let instance_snapshot = SnapshotJson::from_vfs( + let instance_snapshot = snapshot_json( &InstanceContext::default(), &mut vfs, Path::new("/foo.json"), + "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index f132fdf6..74ed97fd 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -7,68 +7,45 @@ use serde::Deserialize; use crate::snapshot::{InstanceContext, InstanceSnapshot}; -use super::{ - error::SnapshotError, - middleware::{SnapshotInstanceResult, SnapshotMiddleware}, - util::match_file_name, -}; +use super::{error::SnapshotError, middleware::SnapshotInstanceResult}; -pub struct SnapshotJsonModel; +pub fn snapshot_json_model( + context: &InstanceContext, + vfs: &Vfs, + path: &Path, + instance_name: &str, +) -> SnapshotInstanceResult { + let contents = vfs.read(path)?; + let instance: JsonModel = serde_json::from_slice(&contents) + .map_err(|source| SnapshotError::malformed_model_json(source, path))?; -impl SnapshotMiddleware for SnapshotJsonModel { - fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { - let meta = vfs.metadata(path)?; - - if meta.is_dir() { - return Ok(None); + if let Some(json_name) = &instance.name { + if json_name != instance_name { + log::warn!( + "Name from JSON model did not match its file name: {}", + path.display() + ); + log::warn!( + "In Rojo < alpha 14, this model is named \"{}\" (from its 'Name' property)", + json_name + ); + log::warn!( + "In Rojo >= alpha 14, this model is named \"{}\" (from its file name)", + instance_name + ); + log::warn!("'Name' for the top-level instance in a JSON model is now optional and will be ignored."); } - - let instance_name = match match_file_name(path, ".model.json") { - Some(name) => name, - None => return Ok(None), - }; - - let contents = vfs.read(path)?; - let instance: JsonModel = serde_json::from_slice(&contents) - .map_err(|source| SnapshotError::malformed_model_json(source, path))?; - - if let Some(json_name) = &instance.name { - if json_name != instance_name { - log::warn!( - "Name from JSON model did not match its file name: {}", - path.display() - ); - log::warn!( - "In Rojo < alpha 14, this model is named \"{}\" (from its 'Name' property)", - json_name - ); - log::warn!( - "In Rojo >= alpha 14, this model is named \"{}\" (from its file name)", - instance_name - ); - log::warn!("'Name' for the top-level instance in a JSON model is now optional and will be ignored."); - } - } - - let mut snapshot = instance.core.into_snapshot(instance_name.to_owned()); - - snapshot.metadata = snapshot - .metadata - .instigating_source(path) - .relevant_paths(vec![path.to_path_buf()]) - .context(context); - - Ok(Some(snapshot)) } -} -fn match_trailing<'a>(input: &'a str, trailer: &str) -> Option<&'a str> { - if input.ends_with(trailer) { - let end = input.len().saturating_sub(trailer.len()); - Some(&input[..end]) - } else { - None - } + let mut snapshot = instance.core.into_snapshot(instance_name.to_owned()); + + snapshot.metadata = snapshot + .metadata + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf()]) + .context(context); + + Ok(Some(snapshot)) } #[derive(Debug, Deserialize)] @@ -164,10 +141,11 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = SnapshotJsonModel::from_vfs( + let instance_snapshot = snapshot_json_model( &InstanceContext::default(), &mut vfs, Path::new("/foo.model.json"), + "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index abf98973..668f57a7 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -7,50 +7,12 @@ use rbx_dom_weak::RbxValue; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ - dir::SnapshotDir, - meta_file::AdjacentMetadata, - middleware::{SnapshotInstanceResult, SnapshotMiddleware}, + dir::snapshot_dir, meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult, util::match_trailing, }; -pub struct SnapshotLua; - -impl SnapshotMiddleware for SnapshotLua { - fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { - let file_name = path.file_name().unwrap().to_string_lossy(); - - // These paths alter their parent instance, so we don't need to turn - // them into a script instance here. - match &*file_name { - "init.lua" | "init.server.lua" | "init.client.lua" => return Ok(None), - _ => {} - } - - let meta = vfs.metadata(path)?; - - if meta.is_file() { - snapshot_lua_file(context, vfs, path) - } else { - // At this point, our entry is definitely a directory! - - if let Some(snapshot) = snapshot_init(context, vfs, path, "init.lua")? { - // An `init.lua` file turns its parent into a ModuleScript - Ok(Some(snapshot)) - } else if let Some(snapshot) = snapshot_init(context, vfs, path, "init.server.lua")? { - // An `init.server.lua` file turns its parent into a Script - Ok(Some(snapshot)) - } else if let Some(snapshot) = snapshot_init(context, vfs, path, "init.client.lua")? { - // An `init.client.lua` file turns its parent into a LocalScript - Ok(Some(snapshot)) - } else { - Ok(None) - } - } - } -} - /// Core routine for turning Lua files into snapshots. -fn snapshot_lua_file(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { +pub fn snapshot_lua(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { let file_name = path.file_name().unwrap().to_string_lossy(); let (class_name, instance_name) = if let Some(name) = match_trailing(&file_name, ".server.lua") @@ -100,35 +62,29 @@ fn snapshot_lua_file(context: &InstanceContext, vfs: &Vfs, path: &Path) -> Snaps /// /// Scripts named `init.lua`, `init.server.lua`, or `init.client.lua` usurp /// their parents, which acts similarly to `__init__.py` from the Python world. -fn snapshot_init( +pub fn snapshot_lua_init( context: &InstanceContext, vfs: &Vfs, - folder_path: &Path, - init_name: &str, + init_path: &Path, ) -> SnapshotInstanceResult { - let init_path = folder_path.join(init_name); + let folder_path = init_path.parent().unwrap(); + let dir_snapshot = snapshot_dir(context, vfs, folder_path)?.unwrap(); - if vfs.metadata(&init_path).with_not_found()?.is_some() { - if let Some(dir_snapshot) = SnapshotDir::from_vfs(context, vfs, folder_path)? { - if let Some(mut init_snapshot) = snapshot_lua_file(context, vfs, &init_path)? { - if dir_snapshot.class_name != "Folder" { - panic!( - "init.lua, init.server.lua, and init.client.lua can \ - only be used if the instance produced by the parent \ - directory would be a Folder." - ); - } - - init_snapshot.name = dir_snapshot.name; - init_snapshot.children = dir_snapshot.children; - init_snapshot.metadata = dir_snapshot.metadata; - - return Ok(Some(init_snapshot)); - } - } + if dir_snapshot.class_name != "Folder" { + panic!( + "init.lua, init.server.lua, and init.client.lua can \ + only be used if the instance produced by the parent \ + directory would be a Folder." + ); } - Ok(None) + let mut init_snapshot = snapshot_lua(context, vfs, init_path)?.unwrap(); + + init_snapshot.name = dir_snapshot.name; + init_snapshot.children = dir_snapshot.children; + init_snapshot.metadata = dir_snapshot.metadata; + + Ok(Some(init_snapshot)) } #[cfg(test)] @@ -146,7 +102,7 @@ mod test { let mut vfs = Vfs::new(imfs); let instance_snapshot = - SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo.lua")) + snapshot_lua(&InstanceContext::default(), &mut vfs, Path::new("/foo.lua")) .unwrap() .unwrap(); @@ -161,7 +117,7 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = SnapshotLua::from_vfs( + let instance_snapshot = snapshot_lua( &InstanceContext::default(), &mut vfs, Path::new("/foo.server.lua"), @@ -180,7 +136,7 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = SnapshotLua::from_vfs( + let instance_snapshot = snapshot_lua( &InstanceContext::default(), &mut vfs, Path::new("/foo.client.lua"), @@ -191,6 +147,7 @@ mod test { insta::assert_yaml_snapshot!(instance_snapshot); } + #[ignore = "init.lua functionality has moved to the root snapshot function"] #[test] fn init_module_from_vfs() { let mut imfs = InMemoryFs::new(); @@ -205,7 +162,7 @@ mod test { let mut vfs = Vfs::new(imfs); let instance_snapshot = - SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/root")) + snapshot_lua(&InstanceContext::default(), &mut vfs, Path::new("/root")) .unwrap() .unwrap(); @@ -232,7 +189,7 @@ mod test { let mut vfs = Vfs::new(imfs); let instance_snapshot = - SnapshotLua::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo.lua")) + snapshot_lua(&InstanceContext::default(), &mut vfs, Path::new("/foo.lua")) .unwrap() .unwrap(); @@ -258,7 +215,7 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = SnapshotLua::from_vfs( + let instance_snapshot = snapshot_lua( &InstanceContext::default(), &mut vfs, Path::new("/foo.server.lua"), @@ -290,7 +247,7 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = SnapshotLua::from_vfs( + let instance_snapshot = snapshot_lua( &InstanceContext::default(), &mut vfs, Path::new("/bar.server.lua"), diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index 18e79439..b05f0b9e 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -1,13 +1,5 @@ -use std::path::Path; - -use memofs::Vfs; - -use crate::snapshot::{InstanceContext, InstanceSnapshot}; +use crate::snapshot::InstanceSnapshot; use super::error::SnapshotError; pub type SnapshotInstanceResult = Result, SnapshotError>; - -pub trait SnapshotMiddleware { - fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult; -} diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 561949c2..9563d8b6 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -12,7 +12,6 @@ mod lua; mod meta_file; mod middleware; mod project; -mod rbxlx; mod rbxm; mod rbxmx; mod txt; @@ -20,59 +19,87 @@ mod util; use std::path::Path; -use memofs::Vfs; +use memofs::{IoResultExt, Vfs}; use crate::snapshot::InstanceContext; use self::{ - csv::SnapshotCsv, - dir::SnapshotDir, - json::SnapshotJson, - json_model::SnapshotJsonModel, - lua::SnapshotLua, - middleware::{SnapshotInstanceResult, SnapshotMiddleware}, - project::SnapshotProject, - rbxlx::SnapshotRbxlx, - rbxm::SnapshotRbxm, - rbxmx::SnapshotRbxmx, - txt::SnapshotTxt, + csv::snapshot_csv, + dir::snapshot_dir, + json::snapshot_json, + json_model::snapshot_json_model, + lua::{snapshot_lua, snapshot_lua_init}, + middleware::SnapshotInstanceResult, + project::snapshot_project, + rbxm::snapshot_rbxm, + rbxmx::snapshot_rbxmx, + txt::snapshot_txt, + util::match_file_name, }; pub use self::error::*; pub use self::project::snapshot_project_node; -macro_rules! middlewares { - ( $($middleware: ident,)* ) => { - /// Generates a snapshot of instances from the given path. - pub fn snapshot_from_vfs( - context: &InstanceContext, - vfs: &Vfs, - path: &Path, - ) -> SnapshotInstanceResult { - $( - log::trace!("trying middleware {} on {}", stringify!($middleware), path.display()); - - if let Some(snapshot) = $middleware::from_vfs(context, vfs, path)? { - log::trace!("middleware {} success on {}", stringify!($middleware), path.display()); - return Ok(Some(snapshot)); - } - )* - - log::trace!("no middleware returned Ok(Some)"); - Ok(None) - } +pub fn snapshot_from_vfs( + context: &InstanceContext, + vfs: &Vfs, + path: &Path, +) -> SnapshotInstanceResult { + let meta = match vfs.metadata(path).with_not_found()? { + Some(meta) => meta, + None => return Ok(None), }; -} -middlewares! { - SnapshotProject, - SnapshotJsonModel, - SnapshotRbxlx, - SnapshotRbxmx, - SnapshotRbxm, - SnapshotLua, - SnapshotCsv, - SnapshotTxt, - SnapshotJson, - SnapshotDir, + if meta.is_dir() { + let project_path = path.join("default.project.json"); + if vfs.metadata(&project_path).with_not_found()?.is_some() { + return snapshot_project(context, vfs, &project_path); + } + + let init_path = path.join("init.lua"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return snapshot_lua_init(context, vfs, &init_path); + } + + let init_path = path.join("init.server.lua"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return snapshot_lua_init(context, vfs, &init_path); + } + + let init_path = path.join("init.client.lua"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return snapshot_lua_init(context, vfs, &init_path); + } + + snapshot_dir(context, vfs, path) + } else { + if let Some(name) = match_file_name(path, ".lua") { + match name { + // init scripts are handled elsewhere and should not turn into + // their own children. + "init" | "init.client" | "init.server" => return Ok(None), + + _ => return snapshot_lua(context, vfs, path), + } + } else if let Some(_name) = match_file_name(path, ".project.json") { + return snapshot_project(context, vfs, path); + } else if let Some(name) = match_file_name(path, ".model.json") { + return snapshot_json_model(context, vfs, path, name); + } else if let Some(_name) = match_file_name(path, ".meta.json") { + // .meta.json files do not turn into their own instances. + return Ok(None); + } else if let Some(name) = match_file_name(path, ".json") { + return snapshot_json(context, vfs, path, name); + } else if let Some(name) = match_file_name(path, ".csv") { + return snapshot_csv(context, vfs, path, name); + } else if let Some(name) = match_file_name(path, ".txt") { + return snapshot_txt(context, vfs, path, name); + } else if let Some(name) = match_file_name(path, ".rbxmx") { + return snapshot_rbxmx(context, vfs, path, name); + } else if let Some(name) = match_file_name(path, ".rbxm") { + return snapshot_rbxm(context, vfs, path, name); + } + + Ok(None) + } } diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index cefed521..94414bd5 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -1,6 +1,6 @@ use std::{borrow::Cow, collections::HashMap, path::Path}; -use memofs::{IoResultExt, Vfs}; +use memofs::Vfs; use rbx_reflection::{get_class_descriptor, try_resolve_value}; use crate::{ @@ -10,92 +10,61 @@ use crate::{ }, }; -use super::{ - error::SnapshotError, - middleware::{SnapshotInstanceResult, SnapshotMiddleware}, - snapshot_from_vfs, -}; +use super::{error::SnapshotError, middleware::SnapshotInstanceResult, snapshot_from_vfs}; -/// Handles snapshots for: -/// * Files ending in `.project.json` -/// * Folders containing a file named `default.project.json` -pub struct SnapshotProject; +pub fn snapshot_project( + context: &InstanceContext, + vfs: &Vfs, + path: &Path, +) -> SnapshotInstanceResult { + let project = Project::load_from_slice(&vfs.read(path)?, path) + .map_err(|err| SnapshotError::malformed_project(err, path))?; -impl SnapshotMiddleware for SnapshotProject { - fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { - let meta = vfs.metadata(path)?; + let mut context = context.clone(); - if meta.is_dir() { - let project_path = path.join("default.project.json"); + let rules = project.glob_ignore_paths.iter().map(|glob| PathIgnoreRule { + glob: glob.clone(), + base_path: project.folder_location().to_path_buf(), + }); - match vfs.metadata(&project_path).with_not_found()? { - // TODO: Do we need to muck with the relevant paths if we're a - // project file within a folder? Should the folder path be the - // relevant path instead of the project file path? - Some(_meta) => return SnapshotProject::from_vfs(context, vfs, &project_path), - None => return Ok(None), - } - } + context.add_path_ignore_rules(rules); - if !path.to_string_lossy().ends_with(".project.json") { - // This isn't a project file, so it's not our job. - return Ok(None); - } + // TODO: If this project node is a path to an instance that Rojo doesn't + // understand, this may panic! + let mut snapshot = + snapshot_project_node(&context, path, &project.name, &project.tree, vfs, None)?.unwrap(); - let project = Project::load_from_slice(&vfs.read(path)?, path) - .map_err(|err| SnapshotError::malformed_project(err, path))?; + // Setting the instigating source to the project file path is a little + // coarse. + // + // Ideally, we'd only snapshot the project file if the project file + // actually changed. Because Rojo only has the concept of one + // relevant path -> snapshot path mapping per instance, we pick the more + // conservative approach of snapshotting the project file if any + // relevant paths changed. + snapshot.metadata.instigating_source = Some(path.to_path_buf().into()); - let mut context = context.clone(); + // Mark this snapshot (the root node of the project file) as being + // related to the project file. + // + // We SHOULD NOT mark the project file as a relevant path for any + // nodes that aren't roots. They'll be updated as part of the project + // file being updated. + snapshot.metadata.relevant_paths.push(path.to_path_buf()); - let rules = project.glob_ignore_paths.iter().map(|glob| PathIgnoreRule { - glob: glob.clone(), - base_path: project.folder_location().to_path_buf(), - }); - - context.add_path_ignore_rules(rules); - - // Snapshotting a project should always return an instance, so this - // unwrap is safe. - let mut snapshot = snapshot_project_node( - &context, - project.folder_location(), - &project.name, - &project.tree, - vfs, - None, - )? - .unwrap(); - - // Setting the instigating source to the project file path is a little - // coarse. - // - // Ideally, we'd only snapshot the project file if the project file - // actually changed. Because Rojo only has the concept of one - // relevant path -> snapshot path mapping per instance, we pick the more - // conservative approach of snapshotting the project file if any - // relevant paths changed. - snapshot.metadata.instigating_source = Some(path.to_path_buf().into()); - - // Mark this snapshot (the root node of the project file) as being - // related to the project file. - // - // We SHOULD NOT mark the project file as a relevant path for any - // nodes that aren't roots. They'll be updated as part of the project - // file being updated. - snapshot.metadata.relevant_paths.push(path.to_path_buf()); - - Ok(Some(snapshot)) - } + Ok(Some(snapshot)) } pub fn snapshot_project_node( context: &InstanceContext, - project_folder: &Path, + project_path: &Path, instance_name: &str, node: &ProjectNode, vfs: &Vfs, parent_class: Option<&str>, ) -> SnapshotInstanceResult { + let project_folder = project_path.parent().unwrap(); + let name = Cow::Owned(instance_name.to_owned()); let mut class_name = node .class_name @@ -191,7 +160,7 @@ pub fn snapshot_project_node( for (child_name, child_project_node) in &node.children { if let Some(child) = snapshot_project_node( context, - project_folder, + project_path, child_name, child_project_node, vfs, @@ -223,7 +192,7 @@ pub fn snapshot_project_node( } metadata.instigating_source = Some(InstigatingSource::ProjectNode( - project_folder.to_path_buf(), + project_path.to_path_buf(), instance_name.to_string(), node.clone(), parent_class.map(|name| name.to_owned()), @@ -239,6 +208,7 @@ pub fn snapshot_project_node( })) } +// #[cfg(feature = "broken-tests")] #[cfg(test)] mod test { use super::*; @@ -246,6 +216,7 @@ mod test { use maplit::hashmap; use memofs::{InMemoryFs, VfsSnapshot}; + #[ignore = "Functionality moved to root snapshot middleware"] #[test] fn project_from_folder() { let _ = env_logger::try_init(); @@ -269,7 +240,7 @@ mod test { let mut vfs = Vfs::new(imfs); let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) + snapshot_project(&InstanceContext::default(), &mut vfs, Path::new("/foo")) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -298,7 +269,7 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = SnapshotProject::from_vfs( + let instance_snapshot = snapshot_project( &InstanceContext::default(), &mut vfs, Path::new("/foo/hello.project.json"), @@ -315,9 +286,9 @@ mod test { let mut imfs = InMemoryFs::new(); imfs.load_snapshot( - "/foo", - VfsSnapshot::dir(hashmap! { - "default.project.json" => VfsSnapshot::file(r#" + "/foo.project.json", + VfsSnapshot::file( + r#" { "name": "resolved-properties", "tree": { @@ -330,17 +301,20 @@ mod test { } } } - "#), - }), + "#, + ), ) .unwrap(); let mut vfs = Vfs::new(imfs); - let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = snapshot_project( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.project.json"), + ) + .expect("snapshot error") + .expect("snapshot returned no instances"); insta::assert_yaml_snapshot!(instance_snapshot); } @@ -351,9 +325,9 @@ mod test { let mut imfs = InMemoryFs::new(); imfs.load_snapshot( - "/foo", - VfsSnapshot::dir(hashmap! { - "default.project.json" => VfsSnapshot::file(r#" + "/foo.project.json", + VfsSnapshot::file( + r#" { "name": "unresolved-properties", "tree": { @@ -363,17 +337,20 @@ mod test { } } } - "#), - }), + "#, + ), ) .unwrap(); let mut vfs = Vfs::new(imfs); - let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = snapshot_project( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.project.json"), + ) + .expect("snapshot error") + .expect("snapshot returned no instances"); insta::assert_yaml_snapshot!(instance_snapshot); } @@ -384,9 +361,9 @@ mod test { let mut imfs = InMemoryFs::new(); imfs.load_snapshot( - "/foo", - VfsSnapshot::dir(hashmap! { - "default.project.json" => VfsSnapshot::file(r#" + "/foo.project.json", + VfsSnapshot::file( + r#" { "name": "children", "tree": { @@ -397,17 +374,20 @@ mod test { } } } - "#), - }), + "#, + ), ) .unwrap(); let mut vfs = Vfs::new(imfs); - let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = snapshot_project( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.project.json"), + ) + .expect("snapshot error") + .expect("snapshot returned no instances"); insta::assert_yaml_snapshot!(instance_snapshot); } @@ -435,10 +415,13 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = snapshot_project( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo/default.project.json"), + ) + .expect("snapshot error") + .expect("snapshot returned no instances"); insta::assert_yaml_snapshot!(instance_snapshot); } @@ -473,10 +456,13 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = snapshot_project( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo/default.project.json"), + ) + .expect("snapshot error") + .expect("snapshot returned no instances"); insta::assert_yaml_snapshot!(instance_snapshot); } @@ -515,10 +501,13 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = snapshot_project( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo/default.project.json"), + ) + .expect("snapshot error") + .expect("snapshot returned no instances"); insta::assert_yaml_snapshot!(instance_snapshot); } @@ -562,10 +551,13 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = - SnapshotProject::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo")) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = snapshot_project( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo/default.project.json"), + ) + .expect("snapshot error") + .expect("snapshot returned no instances"); insta::assert_yaml_snapshot!(instance_snapshot); } diff --git a/src/snapshot_middleware/rbxlx.rs b/src/snapshot_middleware/rbxlx.rs deleted file mode 100644 index 94cc942d..00000000 --- a/src/snapshot_middleware/rbxlx.rs +++ /dev/null @@ -1,46 +0,0 @@ -use std::path::Path; - -use memofs::Vfs; - -use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; - -use super::{ - middleware::{SnapshotInstanceResult, SnapshotMiddleware}, - util::match_file_name, -}; - -pub struct SnapshotRbxlx; - -impl SnapshotMiddleware for SnapshotRbxlx { - fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { - let meta = vfs.metadata(path)?; - - if meta.is_dir() { - return Ok(None); - } - - let instance_name = match match_file_name(path, ".rbxlx") { - Some(name) => name, - None => return Ok(None), - }; - - let options = rbx_xml::DecodeOptions::new() - .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); - - let temp_tree = rbx_xml::from_reader(vfs.read(path)?.as_slice(), options) - .expect("TODO: Handle rbx_xml errors"); - - let root_id = temp_tree.get_root_id(); - - let snapshot = InstanceSnapshot::from_tree(&temp_tree, root_id) - .name(instance_name) - .metadata( - InstanceMetadata::new() - .instigating_source(path) - .relevant_paths(vec![path.to_path_buf()]) - .context(context), - ); - - Ok(Some(snapshot)) - } -} diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 319d316a..5c7624ba 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -5,53 +5,40 @@ use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{ - middleware::{SnapshotInstanceResult, SnapshotMiddleware}, - util::match_file_name, -}; +use super::middleware::SnapshotInstanceResult; -pub struct SnapshotRbxm; +pub fn snapshot_rbxm( + context: &InstanceContext, + vfs: &Vfs, + path: &Path, + instance_name: &str, +) -> SnapshotInstanceResult { + let mut temp_tree = RbxTree::new(RbxInstanceProperties { + name: "DataModel".to_owned(), + class_name: "DataModel".to_owned(), + properties: HashMap::new(), + }); -impl SnapshotMiddleware for SnapshotRbxm { - fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { - let meta = vfs.metadata(path)?; + let root_id = temp_tree.get_root_id(); + rbx_binary::decode(&mut temp_tree, root_id, vfs.read(path)?.as_slice()) + .expect("TODO: Handle rbx_binary errors"); - if meta.is_dir() { - return Ok(None); - } + let root_instance = temp_tree.get_instance(root_id).unwrap(); + let children = root_instance.get_children_ids(); - let instance_name = match match_file_name(path, ".rbxm") { - Some(name) => name, - None => return Ok(None), - }; + if children.len() == 1 { + let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) + .name(instance_name) + .metadata( + InstanceMetadata::new() + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf()]) + .context(context), + ); - let mut temp_tree = RbxTree::new(RbxInstanceProperties { - name: "DataModel".to_owned(), - class_name: "DataModel".to_owned(), - properties: HashMap::new(), - }); - - let root_id = temp_tree.get_root_id(); - rbx_binary::decode(&mut temp_tree, root_id, vfs.read(path)?.as_slice()) - .expect("TODO: Handle rbx_binary errors"); - - let root_instance = temp_tree.get_instance(root_id).unwrap(); - let children = root_instance.get_children_ids(); - - if children.len() == 1 { - let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) - .name(instance_name) - .metadata( - InstanceMetadata::new() - .instigating_source(path) - .relevant_paths(vec![path.to_path_buf()]) - .context(context), - ); - - Ok(Some(snapshot)) - } else { - panic!("Rojo doesn't have support for model files with zero or more than one top-level instances yet."); - } + Ok(Some(snapshot)) + } else { + panic!("Rojo doesn't have support for model files with zero or more than one top-level instances yet."); } } @@ -72,10 +59,11 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = SnapshotRbxm::from_vfs( + let instance_snapshot = snapshot_rbxm( &InstanceContext::default(), &mut vfs, Path::new("/foo.rbxm"), + "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 90193b62..b8012101 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -4,49 +4,36 @@ use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{ - middleware::{SnapshotInstanceResult, SnapshotMiddleware}, - util::match_file_name, -}; +use super::middleware::SnapshotInstanceResult; -pub struct SnapshotRbxmx; +pub fn snapshot_rbxmx( + context: &InstanceContext, + vfs: &Vfs, + path: &Path, + instance_name: &str, +) -> SnapshotInstanceResult { + let options = rbx_xml::DecodeOptions::new() + .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); -impl SnapshotMiddleware for SnapshotRbxmx { - fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { - let meta = vfs.metadata(path)?; + let temp_tree = rbx_xml::from_reader(vfs.read(path)?.as_slice(), options) + .expect("TODO: Handle rbx_xml errors"); - if meta.is_dir() { - return Ok(None); - } + let root_instance = temp_tree.get_instance(temp_tree.get_root_id()).unwrap(); + let children = root_instance.get_children_ids(); - let instance_name = match match_file_name(path, ".rbxmx") { - Some(name) => name, - None => return Ok(None), - }; + if children.len() == 1 { + let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) + .name(instance_name) + .metadata( + InstanceMetadata::new() + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf()]) + .context(context), + ); - let options = rbx_xml::DecodeOptions::new() - .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); - - let temp_tree = rbx_xml::from_reader(vfs.read(path)?.as_slice(), options) - .expect("TODO: Handle rbx_xml errors"); - - let root_instance = temp_tree.get_instance(temp_tree.get_root_id()).unwrap(); - let children = root_instance.get_children_ids(); - - if children.len() == 1 { - let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) - .name(instance_name) - .metadata( - InstanceMetadata::new() - .instigating_source(path) - .relevant_paths(vec![path.to_path_buf()]) - .context(context), - ); - - Ok(Some(snapshot)) - } else { - panic!("Rojo doesn't have support for model files with zero or more than one top-level instances yet."); - } + Ok(Some(snapshot)) + } else { + panic!("Rojo doesn't have support for model files with zero or more than one top-level instances yet."); } } @@ -77,10 +64,11 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = SnapshotRbxmx::from_vfs( + let instance_snapshot = snapshot_rbxmx( &InstanceContext::default(), &mut vfs, Path::new("/foo.rbxmx"), + "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap index e5603c97..ccf6b535 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap @@ -6,9 +6,9 @@ snapshot_id: ~ metadata: ignore_unknown_instances: true instigating_source: - Path: /foo/default.project.json + Path: /foo.project.json relevant_paths: - - /foo/default.project.json + - /foo.project.json context: {} name: children class_name: Folder @@ -19,7 +19,7 @@ children: ignore_unknown_instances: true instigating_source: ProjectNode: - - /foo + - /foo.project.json - Child - $className: Model - Folder diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap index 389d24e2..c71b4d2d 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap @@ -20,7 +20,7 @@ children: ignore_unknown_instances: true instigating_source: ProjectNode: - - /foo + - /foo/other.project.json - SomeChild - $className: Model - Folder diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap index cb6025f7..21159485 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap @@ -6,9 +6,9 @@ snapshot_id: ~ metadata: ignore_unknown_instances: true instigating_source: - Path: /foo/default.project.json + Path: /foo.project.json relevant_paths: - - /foo/default.project.json + - /foo.project.json context: {} name: resolved-properties class_name: StringValue diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap index a8a0e6df..d3cbb593 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap @@ -6,9 +6,9 @@ snapshot_id: ~ metadata: ignore_unknown_instances: true instigating_source: - Path: /foo/default.project.json + Path: /foo.project.json relevant_paths: - - /foo/default.project.json + - /foo.project.json context: {} name: unresolved-properties class_name: StringValue diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 6e4fcc0c..edf1fbf5 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -7,58 +7,45 @@ use rbx_dom_weak::RbxValue; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ - error::SnapshotError, - meta_file::AdjacentMetadata, - middleware::{SnapshotInstanceResult, SnapshotMiddleware}, - util::match_file_name, + error::SnapshotError, meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult, }; -pub struct SnapshotTxt; +pub fn snapshot_txt( + context: &InstanceContext, + vfs: &Vfs, + path: &Path, + instance_name: &str, +) -> SnapshotInstanceResult { + let contents = vfs.read(path)?; + let contents_str = str::from_utf8(&contents) + .map_err(|err| SnapshotError::file_contents_bad_unicode(err, path))? + .to_string(); -impl SnapshotMiddleware for SnapshotTxt { - fn from_vfs(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { - let meta = vfs.metadata(path)?; + let properties = hashmap! { + "Value".to_owned() => RbxValue::String { + value: contents_str, + }, + }; - if meta.is_dir() { - return Ok(None); - } + let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); - let instance_name = match match_file_name(path, ".txt") { - Some(name) => name, - None => return Ok(None), - }; + let mut snapshot = InstanceSnapshot::new() + .name(instance_name) + .class_name("StringValue") + .properties(properties) + .metadata( + InstanceMetadata::new() + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf(), meta_path.clone()]) + .context(context), + ); - let contents = vfs.read(path)?; - let contents_str = str::from_utf8(&contents) - .map_err(|err| SnapshotError::file_contents_bad_unicode(err, path))? - .to_string(); - - let properties = hashmap! { - "Value".to_owned() => RbxValue::String { - value: contents_str, - }, - }; - - let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); - - let mut snapshot = InstanceSnapshot::new() - .name(instance_name) - .class_name("StringValue") - .properties(properties) - .metadata( - InstanceMetadata::new() - .instigating_source(path) - .relevant_paths(vec![path.to_path_buf(), meta_path.clone()]) - .context(context), - ); - - if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { - let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; - metadata.apply_all(&mut snapshot); - } - - Ok(Some(snapshot)) + if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { + let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; + metadata.apply_all(&mut snapshot); } + + Ok(Some(snapshot)) } #[cfg(test)] @@ -75,10 +62,14 @@ mod test { let mut vfs = Vfs::new(imfs.clone()); - let instance_snapshot = - SnapshotTxt::from_vfs(&InstanceContext::default(), &mut vfs, Path::new("/foo.txt")) - .unwrap() - .unwrap(); + let instance_snapshot = snapshot_txt( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.txt"), + "foo", + ) + .unwrap() + .unwrap(); insta::assert_yaml_snapshot!(instance_snapshot); } diff --git a/src/snapshot_middleware/user_plugins.rs b/src/snapshot_middleware/user_plugins.rs deleted file mode 100644 index c28a7a76..00000000 --- a/src/snapshot_middleware/user_plugins.rs +++ /dev/null @@ -1,56 +0,0 @@ -use crate::{ - snapshot::InstanceContext, - vfs::{Vfs, VfsEntry, VfsFetcher}, -}; - -use super::middleware::{SnapshotInstanceResult, SnapshotMiddleware}; - -/// Handles snapshotting of any file that a user plugin wants to handle. -/// -/// User plugins are specified in the project file, but there are never user -/// plugins specified unless a Cargo feature is enabled, `user-plugins`. -/// Additionally, extra data needs to be set up inside the snapshot context -/// which is not currently wired up. -pub struct SnapshotUserPlugins; - -impl SnapshotMiddleware for SnapshotUserPlugins { - fn from_vfs( - _context: &InstanceContext, - _vfs: &Vfs, - _entry: &VfsEntry, - ) -> SnapshotInstanceResult { - // TODO: Invoke plugin here and get result out. - - // The current plan for plugins here is to make them work - // like Redux/Rodux middleware. A plugin will be a function - // that accepts the next middleware in the chain as a - // function and the snapshot subject (the VFS entry). - // - // Plugins can (but don't have to) invoke the next snapshot - // function and may or may not mutate the result. The hope - // is that this model enables the most flexibility possible - // for plugins to modify existing Rojo output, as well as - // generate new outputs. - // - // Open questions: - // * How will middleware be ordered? Does putting user - // middleware always at the beginning or always at the end - // of the chain reduce the scope of what that middleware - // can do? - // - // * Will plugins hurt Rojo's ability to parallelize - // snapshotting in the future? - // - // * Do the mutable handles to the Vfs and the snapshot - // context prevent plugins from invoking other plugins - // indirectly? - // - // * Will there be problems using a single Lua state because - // of re-entrancy? - // - // * Can the Lua <-> Rojo bindings used for middleware be - // reused for or from another project like Remodel? - - Ok(None) - } -} From fc27b2911e217435ddd94ba5e54a8bfa03cb8bf9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 17 Jun 2020 14:06:44 -0700 Subject: [PATCH 1049/1504] Allow turning off file watching in memofs. Also preemptively bumping version to 0.1.3 so I don't forget on next release --- Cargo.lock | 2 +- Cargo.toml | 2 +- memofs/CHANGELOG.md | 4 ++++ memofs/Cargo.toml | 2 +- memofs/src/lib.rs | 33 +++++++++++++++++++++++++++++++-- 5 files changed, 38 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 21ddc3c4..bdc90964 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1083,7 +1083,7 @@ dependencies = [ [[package]] name = "memofs" -version = "0.1.2" +version = "0.1.3" dependencies = [ "crossbeam-channel", "fs-err", diff --git a/Cargo.toml b/Cargo.toml index 772560fe..96723065 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -95,7 +95,7 @@ uuid = { version = "0.8.1", features = ["v4", "serde"] } winreg = "0.6.2" [build-dependencies] -memofs = { version = "0.1.0", path = "memofs" } +memofs = { version = "0.1.3", path = "memofs" } anyhow = "1.0.27" bincode = "1.2.1" diff --git a/memofs/CHANGELOG.md b/memofs/CHANGELOG.md index cd4647f2..78dd22aa 100644 --- a/memofs/CHANGELOG.md +++ b/memofs/CHANGELOG.md @@ -1,6 +1,10 @@ # memofs Changelog ## Unreleased Changes +* Added `set_watch_enabled` to `Vfs` and `VfsLock` to allow turning off file watching. + +## 0.1.2 (2020-03-29) +* `VfsSnapshot` now implements Serde's `Serialize` and `Deserialize` traits. ## 0.1.1 (2020-03-18) * Improved error messages using the [fs-err](https://crates.io/crates/fs-err) crate. diff --git a/memofs/Cargo.toml b/memofs/Cargo.toml index 3484c765..12c67caa 100644 --- a/memofs/Cargo.toml +++ b/memofs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "memofs" description = "Virtual filesystem with configurable backends." -version = "0.1.2" +version = "0.1.3" authors = ["Lucien Greathouse "] edition = "2018" readme = "README.md" diff --git a/memofs/src/lib.rs b/memofs/src/lib.rs index a04bf71d..f6a17ef6 100644 --- a/memofs/src/lib.rs +++ b/memofs/src/lib.rs @@ -140,13 +140,18 @@ pub enum VfsEvent { /// the public interfaces to this type. struct VfsInner { backend: Box, + watch_enabled: bool, } impl VfsInner { fn read>(&mut self, path: P) -> io::Result>> { let path = path.as_ref(); let contents = self.backend.read(path)?; - self.backend.watch(path)?; + + if self.watch_enabled { + self.backend.watch(path)?; + } + Ok(Arc::new(contents)) } @@ -159,7 +164,11 @@ impl VfsInner { fn read_dir>(&mut self, path: P) -> io::Result { let path = path.as_ref(); let dir = self.backend.read_dir(path)?; - self.backend.watch(path)?; + + if self.watch_enabled { + self.backend.watch(path)?; + } + Ok(dir) } @@ -215,6 +224,7 @@ impl Vfs { pub fn new(backend: B) -> Self { let lock = VfsInner { backend: Box::new(backend), + watch_enabled: true, }; Self { @@ -229,6 +239,16 @@ impl Vfs { } } + /// Turns automatic file watching on or off. Enabled by default. + /// + /// Turning off file watching may be useful for single-use cases, especially + /// on platforms like macOS where registering file watches has significant + /// performance cost. + pub fn set_watch_enabled(&self, enabled: bool) { + let mut inner = self.inner.lock().unwrap(); + inner.watch_enabled = enabled; + } + /// Read a file from the VFS, or the underlying backend if it isn't /// resident. /// @@ -318,6 +338,15 @@ pub struct VfsLock<'a> { } impl VfsLock<'_> { + /// Turns automatic file watching on or off. Enabled by default. + /// + /// Turning off file watching may be useful for single-use cases, especially + /// on platforms like macOS where registering file watches has significant + /// performance cost. + pub fn set_watch_enabled(&mut self, enabled: bool) { + self.inner.watch_enabled = enabled; + } + /// Read a file from the VFS, or the underlying backend if it isn't /// resident. /// From 782b054b1ae712c7d3ceccbdd3ae4e70ef01c690 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 17 Jun 2020 14:11:48 -0700 Subject: [PATCH 1050/1504] Pass build watch argument into Vfs --- src/cli/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cli/build.rs b/src/cli/build.rs index 88760e2f..4cfe9f77 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -43,6 +43,7 @@ pub fn build(options: BuildCommand) -> Result<(), anyhow::Error> { log::trace!("Constructing in-memory filesystem"); let vfs = Vfs::new_default(); + vfs.set_watch_enabled(options.watch); let session = ServeSession::new(vfs, &options.absolute_project())?; let mut cursor = session.message_queue().cursor(); From a3edb93273fcee5c3e882893a7d8d75d1204359c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 17 Jun 2020 14:38:39 -0700 Subject: [PATCH 1051/1504] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4bd0ed2c..a445f299 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased Changes * Fixed crash when malformed CSV files are put into a project. ([#310](https://github.com/rojo-rbx/rojo/issues/310)) * Fixed incorrect string escaping when producing Lua code from JSON files. ([#314](https://github.com/rojo-rbx/rojo/issues/314)) +* Fixed performance issues introduced in Rojo 6.0.0-rc.1. ([#317](https://github.com/rojo-rbx/rojo/issues/317)) * Updated default place template to take advantage of [#210](https://github.com/rojo-rbx/rojo/pull/210). ## [6.0.0 Release Candidate 1](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.1) (March 29, 2020) From 940aff7ef423f239546b17dc3f45cb83a8d8fa87 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 17 Jun 2020 14:42:46 -0700 Subject: [PATCH 1052/1504] Enable globIgnorePaths by default --- .github/workflows/ci.yml | 8 +------- CHANGELOG.md | 2 ++ Cargo.toml | 3 --- src/project.rs | 1 - tests/tests/build.rs | 10 +++------- 5 files changed, 6 insertions(+), 18 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 004858c7..02a6af3e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,10 +36,4 @@ jobs: run: | cargo fmt -- --check cargo clippy - if: matrix.rust_version == 'stable' - - - name: Build (All Features) - run: cargo build --locked --verbose --all-features - - - name: Run tests (All Features) - run: cargo test --locked --verbose --all-features \ No newline at end of file + if: matrix.rust_version == 'stable' \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a445f299..f31ae289 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ * Fixed incorrect string escaping when producing Lua code from JSON files. ([#314](https://github.com/rojo-rbx/rojo/issues/314)) * Fixed performance issues introduced in Rojo 6.0.0-rc.1. ([#317](https://github.com/rojo-rbx/rojo/issues/317)) * Updated default place template to take advantage of [#210](https://github.com/rojo-rbx/rojo/pull/210). +* Enabled glob ignore patterns by default and removed the `unstable_glob_ignore` feature. + * `globIgnorePaths` can be set on a project to a list of globs to ignore. ## [6.0.0 Release Candidate 1](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.1) (March 29, 2020) This release jumped from 0.6.0 to 6.0.0. Rojo has been in use in production for many users for quite a long times, and so 6.0 is a more accurate reflection of Rojo's version than a pre-1.0 version. diff --git a/Cargo.toml b/Cargo.toml index 96723065..57a08e35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,9 +23,6 @@ panic = "abort" [features] default = [] -# Turn on support for specifying glob ignore path rules in the project format. -unstable_glob_ignore_paths = [] - # Enable this feature to live-reload assets from the web UI. dev_live_assets = [] diff --git a/src/project.rs b/src/project.rs index 12134dc9..4d29c72a 100644 --- a/src/project.rs +++ b/src/project.rs @@ -61,7 +61,6 @@ pub struct Project { /// A list of globs, relative to the folder the project file is in, that /// match files that should be excluded if Rojo encounters them. #[serde(default, skip_serializing_if = "Vec::is_empty")] - #[cfg_attr(not(feature = "unstable_glob_ignore_paths"), serde(skip))] pub glob_ignore_paths: Vec, /// The path to the file that this project came from. Relative paths in the diff --git a/tests/tests/build.rs b/tests/tests/build.rs index 2f5fc76a..3cb286eb 100644 --- a/tests/tests/build.rs +++ b/tests/tests/build.rs @@ -28,6 +28,9 @@ gen_build_tests! { csv_in_folder, deep_nesting, gitkeep, + ignore_glob_inner, + ignore_glob_nested, + ignore_glob_spec, infer_service_name, infer_starter_player, init_meta_class_name, @@ -48,13 +51,6 @@ gen_build_tests! { txt_in_folder, } -#[cfg(feature = "unstable_glob_ignore_paths")] -gen_build_tests! { - ignore_glob_inner, - ignore_glob_nested, - ignore_glob_spec, -} - fn run_build_test(test_name: &str) { let working_dir = get_working_dir_path(); From 4cbb3874a4dc7332736cb66aa1e6d6aa02e75735 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 17 Jun 2020 14:56:09 -0700 Subject: [PATCH 1053/1504] Use anyhow error reporting instead of custom --- src/bin.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/bin.rs b/src/bin.rs index aa8c647b..ca4b878d 100644 --- a/src/bin.rs +++ b/src/bin.rs @@ -1,11 +1,11 @@ -use std::{env, error::Error, panic, process}; +use std::{env, panic, process}; use backtrace::Backtrace; use structopt::StructOpt; use librojo::cli::{self, GlobalOptions, Options, Subcommand}; -fn run(global: GlobalOptions, subcommand: Subcommand) -> Result<(), Box> { +fn run(global: GlobalOptions, subcommand: Subcommand) -> anyhow::Result<()> { match subcommand { Subcommand::Init(init_options) => cli::init(init_options)?, Subcommand::Serve(serve_options) => cli::serve(global, serve_options)?, @@ -82,14 +82,7 @@ fn main() { .init(); if let Err(err) = run(options.global, options.subcommand) { - log::error!("{}", err); - - let mut current_err: &dyn Error = &*err; - while let Some(source) = current_err.source() { - log::error!(" caused by {}", source); - current_err = &*source; - } - + log::error!("{:?}", err); process::exit(1); } } From 9453588ab17a914f9432d88a8a113443da032c8d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 17 Jun 2020 22:54:13 -0700 Subject: [PATCH 1054/1504] Load built-in plugin from absolute path to make errors more apparent --- src/cli/plugin.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs index 8ddca54d..d3c31c7c 100644 --- a/src/cli/plugin.rs +++ b/src/cli/plugin.rs @@ -36,10 +36,10 @@ pub fn install_plugin() -> Result<()> { } let mut in_memory_fs = InMemoryFs::new(); - in_memory_fs.load_snapshot("plugin", plugin_snapshot)?; + in_memory_fs.load_snapshot("/plugin", plugin_snapshot)?; let vfs = Vfs::new(in_memory_fs); - let session = ServeSession::new(vfs, "plugin")?; + let session = ServeSession::new(vfs, "/plugin")?; let plugin_path = plugins_folder_path.join(PLUGIN_FILE_NAME); log::debug!("Writing plugin to {}", plugin_path.display()); From badb5c3636266bcf0304c74afa89faf22f21e188 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 17 Jun 2020 22:54:35 -0700 Subject: [PATCH 1055/1504] Stop redundantly adding ignore paths when starting ServeSession --- src/serve_session.rs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/src/serve_session.rs b/src/serve_session.rs index 2c2813d3..1164dc5a 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -17,7 +17,7 @@ use crate::{ session_id::SessionId, snapshot::{ apply_patch_set, compute_patch_set, AppliedPatchSet, InstanceContext, - InstancePropertiesWithMeta, PatchSet, PathIgnoreRule, RojoTree, + InstancePropertiesWithMeta, PatchSet, RojoTree, }, snapshot_middleware::{snapshot_from_vfs, SnapshotError}, }; @@ -114,17 +114,7 @@ impl ServeSession { let root_id = tree.get_root_id(); - let mut instance_context = InstanceContext::default(); - - let rules = root_project - .glob_ignore_paths - .iter() - .map(|glob| PathIgnoreRule { - glob: glob.clone(), - base_path: root_project.folder_location().to_path_buf(), - }); - - instance_context.add_path_ignore_rules(rules); + let instance_context = InstanceContext::default(); log::trace!("Generating snapshot of instances from VFS"); let snapshot = snapshot_from_vfs(&instance_context, &vfs, &start_path)? From da05078ff3b5b616eb07957ed26c4d5539e28270 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 17 Jun 2020 23:13:29 -0700 Subject: [PATCH 1056/1504] Load project file from VFS instead of through fs. Fixes #320. Previously, the root project file was loaded via methods on Project (which do not know about the VFS) instead of through the VFS like all other disk access. This meant that Rojo was unable to build its own plugin because there is no project file on the real disk, only in the VFS. --- src/project.rs | 9 +++++++-- src/serve_session.rs | 31 ++++++++++++++++++++++++++----- src/snapshot_middleware/error.rs | 9 ++++----- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/project.rs b/src/project.rs index 4d29c72a..16c3a7cf 100644 --- a/src/project.rs +++ b/src/project.rs @@ -111,8 +111,13 @@ impl Project { pub fn load_from_slice( contents: &[u8], project_file_location: &Path, - ) -> Result { - let mut project: Self = serde_json::from_slice(&contents)?; + ) -> Result { + let mut project: Self = + serde_json::from_slice(&contents).map_err(|source| Error::Json { + source, + path: project_file_location.to_owned(), + })?; + project.file_location = project_file_location.to_path_buf(); project.check_compatibility(); Ok(project) diff --git a/src/serve_session.rs b/src/serve_session.rs index 1164dc5a..d43d4981 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -1,11 +1,14 @@ use std::{ + borrow::Cow, collections::HashSet, + io, path::{Path, PathBuf}, sync::{Arc, Mutex, MutexGuard}, time::Instant, }; use crossbeam_channel::Sender; +use memofs::IoResultExt; use memofs::Vfs; use rbx_dom_weak::RbxInstanceProperties; use thiserror::Error; @@ -97,11 +100,23 @@ impl ServeSession { log::trace!("Starting new ServeSession at path {}", start_path.display()); - log::debug!("Loading project file from {}", start_path.display()); - let root_project = - Project::load_fuzzy(start_path)?.ok_or_else(|| ServeSessionError::NoProjectFound { - path: start_path.to_owned(), - })?; + let project_path; + if Project::is_project_file(start_path) { + project_path = Cow::Borrowed(start_path); + } else { + project_path = Cow::Owned(start_path.join("default.project.json")); + } + + log::debug!("Loading project file from {}", project_path.display()); + + let root_project = match vfs.read(&project_path).with_not_found()? { + Some(contents) => Project::load_from_slice(&contents, &project_path)?, + None => { + return Err(ServeSessionError::NoProjectFound { + path: project_path.to_path_buf(), + }); + } + }; let mut tree = RojoTree::new(InstancePropertiesWithMeta { properties: RbxInstanceProperties { @@ -206,6 +221,12 @@ pub enum ServeSessionError { )] NoProjectFound { path: PathBuf }, + #[error(transparent)] + Io { + #[from] + source: io::Error, + }, + #[error(transparent)] Project { #[from] diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs index a1c1665d..7e0e3847 100644 --- a/src/snapshot_middleware/error.rs +++ b/src/snapshot_middleware/error.rs @@ -2,6 +2,8 @@ use std::{io, path::PathBuf}; use thiserror::Error; +use crate::project::ProjectError; + #[derive(Debug, Error)] pub enum SnapshotError { #[error("file name had malformed Unicode")] @@ -14,10 +16,7 @@ pub enum SnapshotError { }, #[error("malformed project file at path {}", .path.display())] - MalformedProject { - source: serde_json::Error, - path: PathBuf, - }, + MalformedProject { source: ProjectError, path: PathBuf }, #[error("malformed .model.json file at path {}", .path.display())] MalformedModelJson { @@ -62,7 +61,7 @@ impl SnapshotError { } } - pub(crate) fn malformed_project(source: serde_json::Error, path: impl Into) -> Self { + pub(crate) fn malformed_project(source: ProjectError, path: impl Into) -> Self { Self::MalformedProject { source, path: path.into(), From 65898125d04714980f8f9b54f66735bdad2dc207 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 17 Jun 2020 23:14:24 -0700 Subject: [PATCH 1057/1504] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f31ae289..8adeaf35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Fixed crash when malformed CSV files are put into a project. ([#310](https://github.com/rojo-rbx/rojo/issues/310)) * Fixed incorrect string escaping when producing Lua code from JSON files. ([#314](https://github.com/rojo-rbx/rojo/issues/314)) * Fixed performance issues introduced in Rojo 6.0.0-rc.1. ([#317](https://github.com/rojo-rbx/rojo/issues/317)) +* Fixed `rojo plugin install` subcommand failing for everyone except Rojo developers. ([#320](https://github.com/rojo-rbx/rojo/issues/320)) * Updated default place template to take advantage of [#210](https://github.com/rojo-rbx/rojo/pull/210). * Enabled glob ignore patterns by default and removed the `unstable_glob_ignore` feature. * `globIgnorePaths` can be set on a project to a list of globs to ignore. From 61c7ef3cb0a7c9ce2eef78b1dc76472ca00822a8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Jun 2020 21:50:14 -0700 Subject: [PATCH 1058/1504] plugin: lazily access settings() to help with testing --- plugin/src/Components/Theme.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/Components/Theme.lua b/plugin/src/Components/Theme.lua index ebd46015..7cee972d 100644 --- a/plugin/src/Components/Theme.lua +++ b/plugin/src/Components/Theme.lua @@ -5,8 +5,6 @@ name. This isn't exactly best practice. ]] -local Studio = settings():GetService("Studio") - local Rojo = script:FindFirstAncestor("Rojo") local Roact = require(Rojo.Roact) @@ -82,6 +80,8 @@ function StudioProvider:render() end function StudioProvider:didMount() + local Studio = settings():GetService("Studio") + self.connection = Studio.ThemeChanged:Connect(function() self:updateTheme() end) From 0c41e9c10b347228914af6dd2f660ecbc9120bd3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Jun 2020 21:50:25 -0700 Subject: [PATCH 1059/1504] Depend on latest Rojo release from Rojo --- foreman.toml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 foreman.toml diff --git a/foreman.toml b/foreman.toml new file mode 100644 index 00000000..fe2956e1 --- /dev/null +++ b/foreman.toml @@ -0,0 +1,2 @@ +[tools] +rojo = { source = "rojo-rbx/rojo", version = "6.0.0-rc.1" } From 95648361be0d1043ac27d16f79b96da05937712f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Jun 2020 21:51:26 -0700 Subject: [PATCH 1060/1504] Recreate test place, just running in Studio --- plugin/test-place.project.json | 28 ++++++++++++++++++++++++++++ plugin/testez.project.json | 6 ------ 2 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 plugin/test-place.project.json delete mode 100644 plugin/testez.project.json diff --git a/plugin/test-place.project.json b/plugin/test-place.project.json new file mode 100644 index 00000000..8e3a7b35 --- /dev/null +++ b/plugin/test-place.project.json @@ -0,0 +1,28 @@ +{ + "name": "Rojo Test Place", + "tree": { + "$className": "DataModel", + + "ReplicatedStorage": { + "Rojo": { + "$path": "default.project.json" + }, + + "TestEZ": { + "$path": "modules/testez/lib" + } + }, + + "ServerScriptService": { + "RunTests": { + "$path": "testBootstrap.server.lua" + } + }, + + "StarterPlayer": { + "$properties": { + "CharacterAutoLoads": false + } + } + } +} \ No newline at end of file diff --git a/plugin/testez.project.json b/plugin/testez.project.json deleted file mode 100644 index 8b209162..00000000 --- a/plugin/testez.project.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "TestEZ", - "tree": { - "$path": "modules/testez/lib" - } -} \ No newline at end of file From a4616cda7d64dc950fbc8e8af913c4bc18bc5691 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Jun 2020 22:16:35 -0700 Subject: [PATCH 1061/1504] Fix test place's CharacterAutoLoads value --- plugin/test-place.project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/test-place.project.json b/plugin/test-place.project.json index 8e3a7b35..32901b26 100644 --- a/plugin/test-place.project.json +++ b/plugin/test-place.project.json @@ -19,7 +19,7 @@ } }, - "StarterPlayer": { + "Players": { "$properties": { "CharacterAutoLoads": false } From 79ae4c52cd4f94445d35ee2065166e6974c929ed Mon Sep 17 00:00:00 2001 From: cliffchapmanrbx <47404136+cliffchapmanrbx@users.noreply.github.com> Date: Mon, 22 Jun 2020 14:11:53 -0700 Subject: [PATCH 1062/1504] Enable CLA bot (#333) --- .github/workflows/clabot.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 .github/workflows/clabot.yml diff --git a/.github/workflows/clabot.yml b/.github/workflows/clabot.yml new file mode 100644 index 00000000..cc8327dd --- /dev/null +++ b/.github/workflows/clabot.yml @@ -0,0 +1,21 @@ +name: "CLA Signature Bot" +on: + issue_comment: + types: [created] + pull_request: + types: [opened,closed,synchronize] + +jobs: + clabot: + runs-on: ubuntu-latest + steps: + - name: "CLA Signature Bot" + uses: roblox/cla-signature-bot@v2.0.1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + whitelist: "LPGhatguy,ZoteTheMighty,cliffchapmanrbx,MagiMaster,MisterUncloaked,amatosov-rbx" + use-remote-repo: true + remote-repo-name: "roblox/cla-bot-store" + remote-repo-pat: ${{ secrets.CLA_REMOTE_REPO_PAT }} + url-to-cladocument: "https://roblox.github.io/cla-bot-store/" From 6b82cead9c19abee0b7972ba1621fde3b80ea652 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 22 Jun 2020 14:13:01 -0700 Subject: [PATCH 1063/1504] Move from rojo-rbx org to Roblox org --- CHANGELOG.md | 184 ++++++++++++------------- CONTRIBUTING.md | 4 +- Cargo.toml | 2 +- README.md | 8 +- assets/default-model-project/README.md | 2 +- assets/default-place-project/README.md | 2 +- foreman.toml | 2 +- memofs/Cargo.toml | 2 +- memofs/README.md | 4 +- memofs/src/lib.rs | 2 +- plugin/src/ApiContext.lua | 2 +- plugin/src/invariant.lua | 2 +- src/lua_ast.rs | 2 +- 13 files changed, 110 insertions(+), 108 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8adeaf35..4c177fae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,31 +1,31 @@ # Rojo Changelog ## Unreleased Changes -* Fixed crash when malformed CSV files are put into a project. ([#310](https://github.com/rojo-rbx/rojo/issues/310)) -* Fixed incorrect string escaping when producing Lua code from JSON files. ([#314](https://github.com/rojo-rbx/rojo/issues/314)) -* Fixed performance issues introduced in Rojo 6.0.0-rc.1. ([#317](https://github.com/rojo-rbx/rojo/issues/317)) -* Fixed `rojo plugin install` subcommand failing for everyone except Rojo developers. ([#320](https://github.com/rojo-rbx/rojo/issues/320)) -* Updated default place template to take advantage of [#210](https://github.com/rojo-rbx/rojo/pull/210). +* Fixed crash when malformed CSV files are put into a project. ([#310](https://github.com/Roblox/rojo/issues/310)) +* Fixed incorrect string escaping when producing Lua code from JSON files. ([#314](https://github.com/Roblox/rojo/issues/314)) +* Fixed performance issues introduced in Rojo 6.0.0-rc.1. ([#317](https://github.com/Roblox/rojo/issues/317)) +* Fixed `rojo plugin install` subcommand failing for everyone except Rojo developers. ([#320](https://github.com/Roblox/rojo/issues/320)) +* Updated default place template to take advantage of [#210](https://github.com/Roblox/rojo/pull/210). * Enabled glob ignore patterns by default and removed the `unstable_glob_ignore` feature. * `globIgnorePaths` can be set on a project to a list of globs to ignore. -## [6.0.0 Release Candidate 1](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.1) (March 29, 2020) +## [6.0.0 Release Candidate 1](https://github.com/Roblox/rojo/releases/tag/v6.0.0-rc.1) (March 29, 2020) This release jumped from 0.6.0 to 6.0.0. Rojo has been in use in production for many users for quite a long times, and so 6.0 is a more accurate reflection of Rojo's version than a pre-1.0 version. * Added basic settings panel to plugin, with two settings: * "Open Scripts Externally": When enabled, opening a script in Studio will instead open it in your default text editor. * "Two-Way Sync": When enabled, Rojo will attempt to save changes to your place back to the filesystem. **Very early feature, very broken, beware!** * Added `--color` option to force-enable or force-disable color in Rojo's output. -* Added support for turning `.json` files into `ModuleScript` instances ([#308](https://github.com/rojo-rbx/rojo/pull/308)) -* Added `rojo plugin install` and `rojo plugin uninstall` to allow Rojo to manage its Roblox Studio plugin. ([#304](https://github.com/rojo-rbx/rojo/pull/304)) -* Class names no longer need to be specified for Roblox services in Rojo projects. ([#210](https://github.com/rojo-rbx/rojo/pull/210)) +* Added support for turning `.json` files into `ModuleScript` instances ([#308](https://github.com/Roblox/rojo/pull/308)) +* Added `rojo plugin install` and `rojo plugin uninstall` to allow Rojo to manage its Roblox Studio plugin. ([#304](https://github.com/Roblox/rojo/pull/304)) +* Class names no longer need to be specified for Roblox services in Rojo projects. ([#210](https://github.com/Roblox/rojo/pull/210)) * The server half of **experimental** two-way sync is now enabled by default. * Increased default logging verbosity in commands like `rojo build`. * Rojo now requires a project file again, just like 0.5.4. -## [0.6.0 Alpha 3](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.3) (March 13, 2020) -* Added `--watch` argument to `rojo build`. ([#284](https://github.com/rojo-rbx/rojo/pull/284)) -* Added dark theme support to plugin. ([#241](https://github.com/rojo-rbx/rojo/issues/241)) +## [0.6.0 Alpha 3](https://github.com/Roblox/rojo/releases/tag/v0.6.0-alpha.3) (March 13, 2020) +* Added `--watch` argument to `rojo build`. ([#284](https://github.com/Roblox/rojo/pull/284)) +* Added dark theme support to plugin. ([#241](https://github.com/Roblox/rojo/issues/241)) * Added a revamped `rojo init` command, which will now create more complete projects. * Added the `rojo doc` command, which opens Rojo's documentation in your browser. * Fixed many crashes from malformed projects and filesystem edge cases in `rojo serve`. @@ -35,22 +35,22 @@ This release jumped from 0.6.0 to 6.0.0. Rojo has been in use in production for * Any thread panicking now causes Rojo to abort instead of existing as a zombie. * Errors now have a list of causes, helping make many errors more clear. -## [0.6.0 Alpha 2](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.2) (March 6, 2020) +## [0.6.0 Alpha 2](https://github.com/Roblox/rojo/releases/tag/v0.6.0-alpha.2) (March 6, 2020) * Fixed `rojo upload` command always uploading models. * Removed `--kind` parameter to `rojo upload`; Rojo now automatically uploads the correct kind of asset based on your project file. -## [0.5.4](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.4) (February 26, 2020) +## [0.5.4](https://github.com/Roblox/rojo/releases/tag/v0.5.4) (February 26, 2020) This is a general maintenance release for the Rojo 0.5.x release series. * Updated reflection database and other dependencies. * First stable release with binaries for macOS and Linux. -## [0.6.0 Alpha 1](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.1) (January 22, 2020) +## [0.6.0 Alpha 1](https://github.com/Roblox/rojo/releases/tag/v0.6.0-alpha.1) (January 22, 2020) ### General -* Added support for nested project files. ([#95](https://github.com/rojo-rbx/rojo/issues/95)) -* Added project file hot-reloading. ([#10](https://github.com/rojo-rbx/rojo/issues/10)]) -* Fixed Rojo dropping Ref properties ([#142](https://github.com/rojo-rbx/rojo/issues/142)) +* Added support for nested project files. ([#95](https://github.com/Roblox/rojo/issues/95)) +* Added project file hot-reloading. ([#10](https://github.com/Roblox/rojo/issues/10)]) +* Fixed Rojo dropping Ref properties ([#142](https://github.com/Roblox/rojo/issues/142)) * This means that properties like `PrimaryPart` now work! * Improved live sync protocol to reduce round-trips and improve syncing consistency. * Improved support for binary model files and places. @@ -69,52 +69,52 @@ This is a general maintenance release for the Rojo 0.5.x release series. * Added "error" state to show errors in a place that isn't the output panel. * Improved diagnostics for when the Rojo plugin cannot create an instance. -## [0.5.3](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.3) (October 15, 2019) +## [0.5.3](https://github.com/Roblox/rojo/releases/tag/v0.5.3) (October 15, 2019) * Fixed an issue where Rojo would throw an error when encountering recently-added instance classes. -## [0.5.2](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.2) (October 14, 2019) -* Fixed an issue where `LocalizationTable` instances would have their column order randomized. ([#173](https://github.com/rojo-rbx/rojo/issues/173)) +## [0.5.2](https://github.com/Roblox/rojo/releases/tag/v0.5.2) (October 14, 2019) +* Fixed an issue where `LocalizationTable` instances would have their column order randomized. ([#173](https://github.com/Roblox/rojo/issues/173)) -## [0.5.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.1) (October 4, 2019) -* Fixed an issue where Rojo would drop changes if they happened too quickly ([#252](https://github.com/rojo-rbx/rojo/issues/252)) +## [0.5.1](https://github.com/Roblox/rojo/releases/tag/v0.5.1) (October 4, 2019) +* Fixed an issue where Rojo would drop changes if they happened too quickly ([#252](https://github.com/Roblox/rojo/issues/252)) * Improved diagnostics for when the Rojo plugin cannot create an instance. * Updated dependencies * This brings Rojo's reflection database from client release 395 to client release 404. -## [0.5.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0) (August 27, 2019) +## [0.5.0](https://github.com/Roblox/rojo/releases/tag/v0.5.0) (August 27, 2019) * Changed `.model.json` naming, which may require projects to migrate ambiguous cases: * The file name now takes precedence over the `Name` field in the model, like Rojo 0.4.x. * The `Name` field of the top-level instance is now optional. It's recommended that you remove it from your models. * Rojo will emit a warning when `Name` is specified and does not match the name from the file. -* Fixed `Rect` values being set to `0, 0, 0, 0` when synced with the Rojo plugin. ([#201](https://github.com/rojo-rbx/rojo/issues/201)) +* Fixed `Rect` values being set to `0, 0, 0, 0` when synced with the Rojo plugin. ([#201](https://github.com/Roblox/rojo/issues/201)) * Fixed live-syncing of `PhysicalProperties`, `NumberSequence`, and `ColorSequence` values -## [0.5.0 Alpha 13](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.13) (August 2, 2019) +## [0.5.0 Alpha 13](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.13) (August 2, 2019) * Bumped minimum Rust version to 1.34.0. -* Fixed default port documentation in `rojo serve --help` ([#219](https://github.com/rojo-rbx/rojo/issues/219)) +* Fixed default port documentation in `rojo serve --help` ([#219](https://github.com/Roblox/rojo/issues/219)) * Fixed BrickColor support by upgrading Roblox-related dependencies -## [0.5.0 Alpha 12](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.12) (July 2, 2019) +## [0.5.0 Alpha 12](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.12) (July 2, 2019) * Added `.meta.json` files - * `init.meta.json` files replace `init.model.json` files from Rojo 0.4.x ([#183](https://github.com/rojo-rbx/rojo/pull/183)) - * Other `.meta.json` files allow attaching extra data to other files ([#189](https://github.com/rojo-rbx/rojo/pull/189)) + * `init.meta.json` files replace `init.model.json` files from Rojo 0.4.x ([#183](https://github.com/Roblox/rojo/pull/183)) + * Other `.meta.json` files allow attaching extra data to other files ([#189](https://github.com/Roblox/rojo/pull/189)) * Added support for infinite and NaN values in types like `Vector2` when building models and places. * These types aren't supported for live-syncing yet due to limitations around JSON encoding. * Added support for using `SharedString` values when building XML models and places. * Added support for live-syncing `CollectionService` tags. * Added a warning when building binary place files, since they're still experimental and have bugs. * Added a warning when trying to use Rojo 0.5.x with a Rojo 0.4.x-only project. -* Added a warning when a Rojo project contains keys that start with `$`, which are reserved names. ([#191](https://github.com/rojo-rbx/rojo/issues/191)) +* Added a warning when a Rojo project contains keys that start with `$`, which are reserved names. ([#191](https://github.com/Roblox/rojo/issues/191)) * Rojo now throws an error if unknown keys are found most files. * Added an icon to the plugin's toolbar button * Changed the plugin to use a docking widget for all UI. * Changed the plugin to ignore unknown properties when live-syncing. - * Rojo's approach to this problem might change later, like with a strict model mode ([#190](https://github.com/rojo-rbx/rojo/issues/190)) or another approach. + * Rojo's approach to this problem might change later, like with a strict model mode ([#190](https://github.com/Roblox/rojo/issues/190)) or another approach. * Upgraded to reflection database from client release 388. * Updated Rojo's branding to shift the color palette to make it work better on dark backgrounds -## [0.5.0 Alpha 11](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) -* Added support for implicit property values in JSON model files ([#154](https://github.com/rojo-rbx/rojo/pull/154)) +## [0.5.0 Alpha 11](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) +* Added support for implicit property values in JSON model files ([#154](https://github.com/Roblox/rojo/pull/154)) * `Content` propertyes can now be specified in projects and model files as regular string literals. * Added support for `BrickColor` properties. * Added support for properties added in client release 384, like `Lighting.Technology` being set to `"ShadowMap"`. @@ -125,16 +125,16 @@ This is a general maintenance release for the Rojo 0.5.x release series. * Plugin should now be able to live-sync more properties, and ignore ones it can't, like `Lighting.Technology`. ## 0.5.0 Alpha 10 -* This release was a dud due to [issue #176](https://github.com/rojo-rbx/rojo/issues/176) and was rolled back. +* This release was a dud due to [issue #176](https://github.com/Roblox/rojo/issues/176) and was rolled back. -## [0.5.0 Alpha 9](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.9) (April 4, 2019) +## [0.5.0 Alpha 9](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.9) (April 4, 2019) * Changed `rojo build` to use buffered I/O, which can make it up to 2x faster in some cases. * Building [*Road Not Taken*](https://github.com/rojo-rbx/roads) to an `rbxlx` file dropped from 150ms to 70ms on my machine -* Fixed `LocalizationTable` instances being made from `csv` files incorrectly interpreting empty rows and columns. ([#149](https://github.com/rojo-rbx/rojo/pull/149)) -* Fixed CSV files with entries that parse as numbers causing Rojo to panic. ([#152](https://github.com/rojo-rbx/rojo/pull/152)) +* Fixed `LocalizationTable` instances being made from `csv` files incorrectly interpreting empty rows and columns. ([#149](https://github.com/Roblox/rojo/pull/149)) +* Fixed CSV files with entries that parse as numbers causing Rojo to panic. ([#152](https://github.com/Roblox/rojo/pull/152)) * Improved error messages when malformed CSV files are found in a Rojo project. -## [0.5.0 Alpha 8](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.8) (March 29, 2019) +## [0.5.0 Alpha 8](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.8) (March 29, 2019) * Added support for a bunch of new types when dealing with XML model/place files: * `ColorSequence` * `Float64` @@ -145,13 +145,13 @@ This is a general maintenance release for the Rojo 0.5.x release series. * `Ray` * `Rect` * `Ref` -* Improved server instance ordering behavior when files are added during a live session ([#135](https://github.com/rojo-rbx/rojo/pull/135)) +* Improved server instance ordering behavior when files are added during a live session ([#135](https://github.com/Roblox/rojo/pull/135)) * Fixed error being thrown when trying to unload the Rojo plugin. -* Added partial fix for [issue #141](https://github.com/rojo-rbx/rojo/issues/141) for `Lighting.Technology`, which should restore live sync functionality for the default project file. +* Added partial fix for [issue #141](https://github.com/Roblox/rojo/issues/141) for `Lighting.Technology`, which should restore live sync functionality for the default project file. -## [0.5.0 Alpha 6](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.6) (March 19, 2019) +## [0.5.0 Alpha 6](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.6) (March 19, 2019) * Fixed `rojo init` giving unexpected results by upgrading to `rbx_dom_weak` 1.1.0 -* Fixed live server not responding when the Rojo plugin is connected ([#133](https://github.com/rojo-rbx/rojo/issues/133)) +* Fixed live server not responding when the Rojo plugin is connected ([#133](https://github.com/Roblox/rojo/issues/133)) * Updated default place file: * Improved default properties to be closer to Studio's built-in 'Baseplate' template * Added a baseplate to the project file (Thanks, [@AmaranthineCodices](https://github.com/AmaranthineCodices/)!) @@ -159,40 +159,40 @@ This is a general maintenance release for the Rojo 0.5.x release series. * Fixed some cases where the Rojo plugin would leave around objects that it knows should be deleted * Updated plugin to correctly listen to `Plugin.Unloading` when installing or uninstalling new plugins -## [0.5.0 Alpha 5](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.5) (March 1, 2019) +## [0.5.0 Alpha 5](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.5) (March 1, 2019) * Upgraded core dependencies, which improves compatibility for lots of instance types * Upgraded from `rbx_tree` 0.2.0 to `rbx_dom_weak` 1.0.0 * Upgraded from `rbx_xml` 0.2.0 to `rbx_xml` 0.4.0 * Upgraded from `rbx_binary` 0.2.0 to `rbx_binary` 0.4.0 * Added support for non-primitive types in the Rojo plugin. * Types like `Color3` and `CFrame` can now be updated live! -* Fixed plugin assets flashing in on first load ([#121](https://github.com/rojo-rbx/rojo/issues/121)) +* Fixed plugin assets flashing in on first load ([#121](https://github.com/Roblox/rojo/issues/121)) * Changed Rojo's HTTP server from Rouille to Hyper, which reduced the release size by around a megabyte. -* Added property type inference to projects, which makes specifying services a lot easier ([#130](https://github.com/rojo-rbx/rojo/pull/130)) +* Added property type inference to projects, which makes specifying services a lot easier ([#130](https://github.com/Roblox/rojo/pull/130)) * Made error messages from invalid and missing files more user-friendly -## [0.5.0 Alpha 4](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.4) (February 8, 2019) -* Added support for nested partitions ([#102](https://github.com/rojo-rbx/rojo/issues/102)) -* Added support for 'transmuting' partitions ([#112](https://github.com/rojo-rbx/rojo/issues/112)) -* Added support for aliasing filesystem paths ([#105](https://github.com/rojo-rbx/rojo/issues/105)) -* Changed Windows builds to statically link the CRT ([#89](https://github.com/rojo-rbx/rojo/issues/89)) +## [0.5.0 Alpha 4](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.4) (February 8, 2019) +* Added support for nested partitions ([#102](https://github.com/Roblox/rojo/issues/102)) +* Added support for 'transmuting' partitions ([#112](https://github.com/Roblox/rojo/issues/112)) +* Added support for aliasing filesystem paths ([#105](https://github.com/Roblox/rojo/issues/105)) +* Changed Windows builds to statically link the CRT ([#89](https://github.com/Roblox/rojo/issues/89)) -## [0.5.0 Alpha 3](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.3) (February 1, 2019) -* Changed default project file name from `roblox-project.json` to `default.project.json` ([#120](https://github.com/rojo-rbx/rojo/pull/120)) +## [0.5.0 Alpha 3](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.3) (February 1, 2019) +* Changed default project file name from `roblox-project.json` to `default.project.json` ([#120](https://github.com/Roblox/rojo/pull/120)) * The old file name will still be supported until 0.5.0 is fully released. * Added warning when loading project files that don't end in `.project.json` * This new extension enables Rojo to distinguish project files from random JSON files, which is necessary to support nested projects. * Added new (empty) diagnostic page served from the server * Added better error messages for when a file is missing that's referenced by a Rojo project * Added support for visualization endpoints returning GraphViz source when Dot is not available -* Fixed an in-memory filesystem regression introduced recently ([#119](https://github.com/rojo-rbx/rojo/pull/119)) +* Fixed an in-memory filesystem regression introduced recently ([#119](https://github.com/Roblox/rojo/pull/119)) -## [0.5.0 Alpha 2](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.2) (January 28, 2019) +## [0.5.0 Alpha 2](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.2) (January 28, 2019) * Added support for `.model.json` files, compatible with 0.4.x * Fixed in-memory filesystem not handling out-of-order filesystem change events -* Fixed long-polling error caused by a promise mixup ([#110](https://github.com/rojo-rbx/rojo/issues/110)) +* Fixed long-polling error caused by a promise mixup ([#110](https://github.com/Roblox/rojo/issues/110)) -## [0.5.0 Alpha 1](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.1) (January 25, 2019) +## [0.5.0 Alpha 1](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.1) (January 25, 2019) * Changed plugin UI to be way prettier * Thanks to [Reselim](https://github.com/Reselim) for the design! * Changed plugin error messages to be a little more useful @@ -200,7 +200,7 @@ This is a general maintenance release for the Rojo 0.5.x release series. * Fixed bug where bad server responses could cause the plugin to be in a bad state * Upgraded to rbx\_tree, rbx\_xml, and rbx\_binary 0.2.0, which dramatically expands the kinds of properties that Rojo can handle, especially in XML. -## [0.5.0 Alpha 0](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.0) (January 14, 2019) +## [0.5.0 Alpha 0](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.0) (January 14, 2019) * "Epiphany" rewrite, in progress since the beginning of time * New live sync protocol * Uses HTTP long polling to reduce request count and improve responsiveness @@ -225,105 +225,105 @@ This is a general maintenance release for the Rojo 0.5.x release series. * Multiple places can be specified, like when building a multi-place game * Added support for specifying properties on services in project files -## [0.4.13](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.13) (November 12, 2018) +## [0.4.13](https://github.com/Roblox/rojo/releases/tag/v0.4.13) (November 12, 2018) * When `rojo.json` points to a file or directory that does not exist, Rojo now issues a warning instead of throwing an error and exiting -## [0.4.12](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.12) (June 21, 2018) -* Fixed obscure assertion failure when renaming or deleting files ([#78](https://github.com/rojo-rbx/rojo/issues/78)) -* Added a `PluginAction` for the sync in command, which should help with some automation scripts ([#80](https://github.com/rojo-rbx/rojo/pull/80)) +## [0.4.12](https://github.com/Roblox/rojo/releases/tag/v0.4.12) (June 21, 2018) +* Fixed obscure assertion failure when renaming or deleting files ([#78](https://github.com/Roblox/rojo/issues/78)) +* Added a `PluginAction` for the sync in command, which should help with some automation scripts ([#80](https://github.com/Roblox/rojo/pull/80)) -## [0.4.11](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.11) (June 10, 2018) +## [0.4.11](https://github.com/Roblox/rojo/releases/tag/v0.4.11) (June 10, 2018) * Defensively insert existing instances into RouteMap; should fix most duplication cases when syncing into existing trees. * Fixed incorrect synchronization from `Plugin:_pull` that would cause polling to create issues * Fixed incorrect file routes being assigned to `init.lua` and `init.model.json` files * Untangled route handling-internals slightly -## [0.4.10](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.10) (June 2, 2018) -* Added support for `init.model.json` files, which enable versioning `Tool` instances (among other things) with Rojo. ([#66](https://github.com/rojo-rbx/rojo/issues/66)) +## [0.4.10](https://github.com/Roblox/rojo/releases/tag/v0.4.10) (June 2, 2018) +* Added support for `init.model.json` files, which enable versioning `Tool` instances (among other things) with Rojo. ([#66](https://github.com/Roblox/rojo/issues/66)) * Fixed obscure error when syncing into an invalid service. * Fixed multiple sync processes occurring when a server ID mismatch is detected. -## [0.4.9](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.9) (May 26, 2018) -* Fixed warning when renaming or removing files that would sometimes corrupt the instance cache ([#72](https://github.com/rojo-rbx/rojo/pull/72)) +## [0.4.9](https://github.com/Roblox/rojo/releases/tag/v0.4.9) (May 26, 2018) +* Fixed warning when renaming or removing files that would sometimes corrupt the instance cache ([#72](https://github.com/Roblox/rojo/pull/72)) * JSON models are no longer as strict -- `Children` and `Properties` are now optional. -## [0.4.8](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.8) (May 26, 2018) +## [0.4.8](https://github.com/Roblox/rojo/releases/tag/v0.4.8) (May 26, 2018) * Hotfix to prevent errors from being thrown when objects managed by Rojo are deleted -## [0.4.7](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.7) (May 25, 2018) -* Added icons to the Rojo plugin, made by [@Vorlias](https://github.com/Vorlias)! ([#70](https://github.com/rojo-rbx/rojo/pull/70)) -* Server will now issue a warning if no partitions are specified in `rojo serve` ([#40](https://github.com/rojo-rbx/rojo/issues/40)) +## [0.4.7](https://github.com/Roblox/rojo/releases/tag/v0.4.7) (May 25, 2018) +* Added icons to the Rojo plugin, made by [@Vorlias](https://github.com/Vorlias)! ([#70](https://github.com/Roblox/rojo/pull/70)) +* Server will now issue a warning if no partitions are specified in `rojo serve` ([#40](https://github.com/Roblox/rojo/issues/40)) -## [0.4.6](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.6) (May 21, 2018) -* Rojo handles being restarted by Roblox Studio more gracefully ([#67](https://github.com/rojo-rbx/rojo/issues/67)) +## [0.4.6](https://github.com/Roblox/rojo/releases/tag/v0.4.6) (May 21, 2018) +* Rojo handles being restarted by Roblox Studio more gracefully ([#67](https://github.com/Roblox/rojo/issues/67)) * Folders should no longer get collapsed when syncing occurs. * **Significant** robustness improvements with regards to caching. * **This should catch all existing script duplication bugs.** * If there are any bugs with script duplication or caching in the future, restarting the Rojo server process will fix them for that session. * Fixed message in plugin not being prefixed with `Rojo: `. -## [0.4.5](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.5) (May 1, 2018) +## [0.4.5](https://github.com/Roblox/rojo/releases/tag/v0.4.5) (May 1, 2018) * Rojo messages are now prefixed with `Rojo: ` to make them stand out in the output more. * Fixed server to notice file changes *much* more quickly. (200ms vs 1000ms) * Server now lists name of project when starting up. -* Rojo now throws an error if no project file is found. ([#63](https://github.com/rojo-rbx/rojo/issues/63)) -* Fixed multiple sync operations occuring at the same time. ([#61](https://github.com/rojo-rbx/rojo/issues/61)) -* Partitions targeting files directly now work as expected. ([#57](https://github.com/rojo-rbx/rojo/issues/57)) +* Rojo now throws an error if no project file is found. ([#63](https://github.com/Roblox/rojo/issues/63)) +* Fixed multiple sync operations occuring at the same time. ([#61](https://github.com/Roblox/rojo/issues/61)) +* Partitions targeting files directly now work as expected. ([#57](https://github.com/Roblox/rojo/issues/57)) -## [0.4.4](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.4) (April 7, 2018) +## [0.4.4](https://github.com/Roblox/rojo/releases/tag/v0.4.4) (April 7, 2018) * Fix small regression introduced in 0.4.3 -## [0.4.3](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.3) (April 7, 2018) -* Plugin now automatically selects `HttpService` if it determines that HTTP isn't enabled ([#58](https://github.com/rojo-rbx/rojo/pull/58)) +## [0.4.3](https://github.com/Roblox/rojo/releases/tag/v0.4.3) (April 7, 2018) +* Plugin now automatically selects `HttpService` if it determines that HTTP isn't enabled ([#58](https://github.com/Roblox/rojo/pull/58)) * Plugin now has much more robust handling and will wipe all state when the server changes. * This should fix issues that would otherwise be solved by restarting Roblox Studio. -## [0.4.2](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.2) (April 4, 2018) +## [0.4.2](https://github.com/Roblox/rojo/releases/tag/v0.4.2) (April 4, 2018) * Fixed final case of duplicated instance insertion, caused by reconciled instances not being inserted into `RouteMap`. * The reconciler is still not a perfect solution, especially if script instances get moved around without being destroyed. I don't think this can be fixed before a big refactor. -## [0.4.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.1) (April 1, 2018) +## [0.4.1](https://github.com/Roblox/rojo/releases/tag/v0.4.1) (April 1, 2018) * Merged plugin repository into main Rojo repository for easier tracking. * Improved `RouteMap` object tracking; this should fix some cases of duplicated instances being synced into the tree. -## [0.4.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.0) (March 27, 2018) +## [0.4.0](https://github.com/Roblox/rojo/releases/tag/v0.4.0) (March 27, 2018) * Protocol version 1, which shifts more responsibility onto the server * This is a **major breaking** change! * The server now has a content of 'filter plugins', which transform data at various stages in the pipeline * The server now exposes Roblox instance objects instead of file contents, which lines up with how `rojo pack` will work, and paves the way for more robust syncing. * Added `*.model.json` files, which let you embed small Roblox objects into your Rojo tree. -* Improved error messages in some cases ([#46](https://github.com/rojo-rbx/rojo/issues/46)) +* Improved error messages in some cases ([#46](https://github.com/Roblox/rojo/issues/46)) -## [0.3.2](https://github.com/rojo-rbx/rojo/releases/tag/v0.3.2) (December 20, 2017) +## [0.3.2](https://github.com/Roblox/rojo/releases/tag/v0.3.2) (December 20, 2017) * Fixed `rojo serve` failing to correctly construct an absolute root path when passed as an argument * Fixed intense CPU usage when running `rojo serve` -## [0.3.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.3.1) (December 14, 2017) +## [0.3.1](https://github.com/Roblox/rojo/releases/tag/v0.3.1) (December 14, 2017) * Improved error reporting when invalid JSON is found in a `rojo.json` project * These messages are passed on from Serde -## [0.3.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.3.0) (December 12, 2017) +## [0.3.0](https://github.com/Roblox/rojo/releases/tag/v0.3.0) (December 12, 2017) * Factored out the plugin into a separate repository * Fixed server when using a file as a partition * Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory! * Started running automatic tests on Travis CI (#9) -## [0.2.3](https://github.com/rojo-rbx/rojo/releases/tag/v0.2.3) (December 4, 2017) +## [0.2.3](https://github.com/Roblox/rojo/releases/tag/v0.2.3) (December 4, 2017) * Plugin only release * Tightened `init` file rules to only match script files * Previously, Rojo would sometimes pick up the wrong file when syncing -## [0.2.2](https://github.com/rojo-rbx/rojo/releases/tag/v0.2.2) (December 1, 2017) +## [0.2.2](https://github.com/Roblox/rojo/releases/tag/v0.2.2) (December 1, 2017) * Plugin only release * Fixed broken reconciliation behavior with `init` files -## [0.2.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.2.1) (December 1, 2017) +## [0.2.1](https://github.com/Roblox/rojo/releases/tag/v0.2.1) (December 1, 2017) * Plugin only release * Changes default port to 8000 -## [0.2.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.2.0) (December 1, 2017) +## [0.2.0](https://github.com/Roblox/rojo/releases/tag/v0.2.0) (December 1, 2017) * Support for `init.lua` like rbxfs and rbxpacker * More robust syncing with a new reconciler -## [0.1.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.1.0) (November 29, 2017) +## [0.1.0](https://github.com/Roblox/rojo/releases/tag/v0.1.0) (November 29, 2017) * Initial release, functionally very similar to [rbxfs](https://github.com/rojo-rbx/rbxfs) \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 57c2b78c..54b5c5a0 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,7 +3,7 @@ Rojo is a big project and can always use more help! This guide covers all reposi Some of the repositories covered are: -* https://github.com/rojo-rbx/rojo +* https://github.com/Roblox/rojo * https://github.com/rojo-rbx/rbx-dom * https://github.com/rojo-rbx/vscode-rojo * https://github.com/rojo-rbx/rbxlx-to-rojo @@ -14,7 +14,7 @@ Code contributions are welcome for features and bugs that have been reported in You'll want these tools to work on Rojo: * Latest stable Rust compiler -* Latest stable [Rojo](https://github.com/rojo-rbx/rojo) +* Latest stable [Rojo](https://github.com/Roblox/rojo) * Latest stable [Remodel](https://github.com/rojo-rbx/remodel) * Latest stable [run-in-roblox](https://github.com/rojo-rbx/run-in-roblox) diff --git a/Cargo.toml b/Cargo.toml index 57a08e35..b3992e28 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ description = "Enables professional-grade development tools for Roblox developer license = "MPL-2.0" homepage = "https://rojo.space" documentation = "https://rojo.space/docs" -repository = "https://github.com/rojo-rbx/rojo" +repository = "https://github.com/Roblox/rojo" readme = "README.md" edition = "2018" diff --git a/README.md b/README.md index edf89258..258c70fa 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@
     
    - - Actions status + + Actions status Latest server version @@ -20,6 +20,8 @@
    +**Heads up! This repository was recently migrated from [the rojo-rbx org](https://github.com/rojo-rbx) to [the Roblox org](https://github.com/Roblox). Not much else has changed.** + **Rojo** is a tool designed to enable Roblox developers to use professional-grade software engineering tools. With Rojo, it's possible to use industry-leading tools like **Visual Studio Code** and **Git**. @@ -41,7 +43,7 @@ In the future, Rojo will be able to: * Import custom instances like MoonScript code ## [Documentation](https://rojo.space/docs) -Documentation is hosted in the [rojo.space repository](https://github.com/rojo-rbx/rojo.space). +Documentation is hosted in the [rojo.space repository](https://github.com/Roblox/rojo.space). ## Contributing Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions for helping work on Rojo! diff --git a/assets/default-model-project/README.md b/assets/default-model-project/README.md index 30dfc436..617d7093 100644 --- a/assets/default-model-project/README.md +++ b/assets/default-model-project/README.md @@ -1,5 +1,5 @@ # {project_name} -Generated by [Rojo](https://github.com/rojo-rbx/rojo) {rojo_version}. +Generated by [Rojo](https://github.com/Roblox/rojo) {rojo_version}. ## Getting Started To build this library or plugin, use: diff --git a/assets/default-place-project/README.md b/assets/default-place-project/README.md index 7908cf59..f519d472 100644 --- a/assets/default-place-project/README.md +++ b/assets/default-place-project/README.md @@ -1,5 +1,5 @@ # {project_name} -Generated by [Rojo](https://github.com/rojo-rbx/rojo) {rojo_version}. +Generated by [Rojo](https://github.com/Roblox/rojo) {rojo_version}. ## Getting Started To build the place from scratch, use: diff --git a/foreman.toml b/foreman.toml index fe2956e1..7df5a1a3 100644 --- a/foreman.toml +++ b/foreman.toml @@ -1,2 +1,2 @@ [tools] -rojo = { source = "rojo-rbx/rojo", version = "6.0.0-rc.1" } +rojo = { source = "Roblox/rojo", version = "6.0.0-rc.1" } diff --git a/memofs/Cargo.toml b/memofs/Cargo.toml index 12c67caa..f31553cb 100644 --- a/memofs/Cargo.toml +++ b/memofs/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Lucien Greathouse "] edition = "2018" readme = "README.md" license = "MIT" -homepage = "https://github.com/rojo-rbx/rojo/tree/master/memofs" +homepage = "https://github.com/Roblox/rojo/tree/master/memofs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/memofs/README.md b/memofs/README.md index d04b8ff6..c0f5740f 100644 --- a/memofs/README.md +++ b/memofs/README.md @@ -5,7 +5,7 @@ Implementation of a virtual filesystem with a configurable backend and file watching. memofs is currently an unstable minimum viable library. Its primary consumer is -[Rojo](https://github.com/rojo-rbx/rojo), a build system for Roblox. +[Rojo](https://github.com/Roblox/rojo), a build system for Roblox. ### Current Features * API similar to `std::fs` @@ -19,4 +19,4 @@ memofs is currently an unstable minimum viable library. Its primary consumer is * Configurable caching (write-through, write-around, write-back) ## License -memofs is available under the terms of the MIT license. See [LICENSE.txt](LICENSE.txt) or for more details. +memofs is available under the terms of the MIT license. See [LICENSE.txt](LICENSE.txt) or for more details. \ No newline at end of file diff --git a/memofs/src/lib.rs b/memofs/src/lib.rs index f6a17ef6..c8f543a6 100644 --- a/memofs/src/lib.rs +++ b/memofs/src/lib.rs @@ -3,7 +3,7 @@ Implementation of a virtual filesystem with a configurable backend and file watching. memofs is currently an unstable minimum viable library. Its primary consumer is -[Rojo](https://github.com/rojo-rbx/rojo), a build system for Roblox. +[Rojo](https://github.com/Roblox/rojo), a build system for Roblox. ## Current Features * API similar to `std::fs` diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 40af8058..57e65db8 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -34,7 +34,7 @@ local function rejectWrongProtocolVersion(infoResponseBody) "\nMake sure you have matching versions of both the Rojo plugin and server!" .. "\n\nYour client is version %s, with protocol version %s. It expects server version %s." .. "\nYour server is version %s, with protocol version %s." .. - "\n\nGo to https://github.com/rojo-rbx/rojo for more details." + "\n\nGo to https://github.com/Roblox/rojo for more details." ):format( Version.display(Config.version), Config.protocolVersion, Config.expectedServerVersionString, diff --git a/plugin/src/invariant.lua b/plugin/src/invariant.lua index 7cb813b4..09c6d2e0 100644 --- a/plugin/src/invariant.lua +++ b/plugin/src/invariant.lua @@ -18,7 +18,7 @@ else "Rojo detected an invariant violation within itself:\n" .. "%s\n\n" .. "This is a bug in Rojo. Please file an issue:\n" .. - "https://github.com/rojo-rbx/rojo/issues", + "https://github.com/Roblox/rojo/issues", message ) diff --git a/src/lua_ast.rs b/src/lua_ast.rs index b29370b4..fac62c2e 100644 --- a/src/lua_ast.rs +++ b/src/lua_ast.rs @@ -315,7 +315,7 @@ impl<'a> LuaStream<'a> { mod test { use super::*; - /// Regression test for https://github.com/rojo-rbx/rojo/issues/314 + /// Regression test for https://github.com/Roblox/rojo/issues/314 #[test] fn bug_314() { let my_value = "\"\r\n\t\\".to_owned(); From 3b257ea87a2235bc77fd3135a0f302dc7bf8bbc4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 23 Jun 2020 11:55:46 -0700 Subject: [PATCH 1064/1504] Update repo references after Roblox move --- CHANGELOG.md | 4 ++-- CONTRIBUTING.md | 11 +++++------ src/snapshot_middleware/rbxm.rs | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c177fae..e92148ce 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -129,7 +129,7 @@ This is a general maintenance release for the Rojo 0.5.x release series. ## [0.5.0 Alpha 9](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.9) (April 4, 2019) * Changed `rojo build` to use buffered I/O, which can make it up to 2x faster in some cases. - * Building [*Road Not Taken*](https://github.com/rojo-rbx/roads) to an `rbxlx` file dropped from 150ms to 70ms on my machine + * Building [*Road Not Taken*](https://github.com/LPGhatguy/roads) to an `rbxlx` file dropped from 150ms to 70ms on my machine * Fixed `LocalizationTable` instances being made from `csv` files incorrectly interpreting empty rows and columns. ([#149](https://github.com/Roblox/rojo/pull/149)) * Fixed CSV files with entries that parse as numbers causing Rojo to panic. ([#152](https://github.com/Roblox/rojo/pull/152)) * Improved error messages when malformed CSV files are found in a Rojo project. @@ -326,4 +326,4 @@ This is a general maintenance release for the Rojo 0.5.x release series. * More robust syncing with a new reconciler ## [0.1.0](https://github.com/Roblox/rojo/releases/tag/v0.1.0) (November 29, 2017) -* Initial release, functionally very similar to [rbxfs](https://github.com/rojo-rbx/rbxfs) \ No newline at end of file +* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 54b5c5a0..0ab92137 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,12 +1,12 @@ # Contributing to the Rojo Project -Rojo is a big project and can always use more help! This guide covers all repositories underneath the [rojo-rbx organization on GitHub](https://github.com/rojo-rbx). +Rojo is a big project and can always use more help! Some of the repositories covered are: * https://github.com/Roblox/rojo -* https://github.com/rojo-rbx/rbx-dom -* https://github.com/rojo-rbx/vscode-rojo -* https://github.com/rojo-rbx/rbxlx-to-rojo +* https://github.com/Roblox/rbx-dom +* https://github.com/Roblox/vscode-rojo +* https://github.com/Roblox/rbxlx-to-rojo ## Code Code contributions are welcome for features and bugs that have been reported in the project's bug tracker. We want to make sure that no one wastes their time, so be sure to talk with maintainers about what changes would be accepted before doing any work! @@ -15,8 +15,7 @@ You'll want these tools to work on Rojo: * Latest stable Rust compiler * Latest stable [Rojo](https://github.com/Roblox/rojo) -* Latest stable [Remodel](https://github.com/rojo-rbx/remodel) -* Latest stable [run-in-roblox](https://github.com/rojo-rbx/run-in-roblox) +* [Foreman](https://github.com/Roblox/foreman) ## Documentation Documentation impacts way more people than the individual lines of code we write. diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 5c7624ba..db4d6667 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -76,6 +76,6 @@ mod test { // distinguish between String and BinaryString. The sample model was // created by Roblox Studio and has an empty BinaryString "Tags" // property that currently deserializes incorrectly. - // See: https://github.com/rojo-rbx/rbx-dom/issues/49 + // See: https://github.com/Roblox/rbx-dom/issues/49 } } From ec5b3f80efcc2a2d289d2037be3d34816229db4e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 3 Jul 2020 12:21:49 -0700 Subject: [PATCH 1065/1504] Fix theme component error regression --- plugin/src/Components/Theme.lua | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/plugin/src/Components/Theme.lua b/plugin/src/Components/Theme.lua index 7cee972d..c8ee810d 100644 --- a/plugin/src/Components/Theme.lua +++ b/plugin/src/Components/Theme.lua @@ -5,6 +5,17 @@ name. This isn't exactly best practice. ]] +-- Studio does not exist outside Roblox Studio, so we'll lazily initialize it +-- when possible. +local _Studio +local function getStudio() + if _Studio == nil then + _Studio = settings():GetService("Studio") + end + + return _Studio +end + local Rojo = script:FindFirstAncestor("Rojo") local Roact = require(Rojo.Roact) @@ -50,7 +61,7 @@ local StudioProvider = Roact.Component:extend("StudioProvider") -- Pull the current theme from Roblox Studio and update state with it. function StudioProvider:updateTheme() - local studioTheme = Studio.Theme + local studioTheme = getStudio().Theme if studioTheme.Name == "Light" then self:setState({ @@ -80,9 +91,7 @@ function StudioProvider:render() end function StudioProvider:didMount() - local Studio = settings():GetService("Studio") - - self.connection = Studio.ThemeChanged:Connect(function() + self.connection = getStudio().ThemeChanged:Connect(function() self:updateTheme() end) end From 45a20a1633b1abf29bca5aad2b83d94c53f9be02 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 9 Sep 2020 17:31:34 -0700 Subject: [PATCH 1066/1504] Remove outdated notices --- .github/workflows/clabot.yml | 21 --- CHANGELOG.md | 184 ++++++++++++------------- CONTRIBUTING.md | 10 +- Cargo.toml | 2 +- README.md | 8 +- assets/default-model-project/README.md | 2 +- assets/default-place-project/README.md | 2 +- foreman.toml | 2 +- memofs/Cargo.toml | 2 +- memofs/README.md | 2 +- memofs/src/lib.rs | 2 +- plugin/src/ApiContext.lua | 2 +- plugin/src/invariant.lua | 2 +- src/lua_ast.rs | 2 +- 14 files changed, 110 insertions(+), 133 deletions(-) delete mode 100644 .github/workflows/clabot.yml diff --git a/.github/workflows/clabot.yml b/.github/workflows/clabot.yml deleted file mode 100644 index cc8327dd..00000000 --- a/.github/workflows/clabot.yml +++ /dev/null @@ -1,21 +0,0 @@ -name: "CLA Signature Bot" -on: - issue_comment: - types: [created] - pull_request: - types: [opened,closed,synchronize] - -jobs: - clabot: - runs-on: ubuntu-latest - steps: - - name: "CLA Signature Bot" - uses: roblox/cla-signature-bot@v2.0.1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - whitelist: "LPGhatguy,ZoteTheMighty,cliffchapmanrbx,MagiMaster,MisterUncloaked,amatosov-rbx" - use-remote-repo: true - remote-repo-name: "roblox/cla-bot-store" - remote-repo-pat: ${{ secrets.CLA_REMOTE_REPO_PAT }} - url-to-cladocument: "https://roblox.github.io/cla-bot-store/" diff --git a/CHANGELOG.md b/CHANGELOG.md index e92148ce..fb7a3fd9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,31 +1,31 @@ # Rojo Changelog ## Unreleased Changes -* Fixed crash when malformed CSV files are put into a project. ([#310](https://github.com/Roblox/rojo/issues/310)) -* Fixed incorrect string escaping when producing Lua code from JSON files. ([#314](https://github.com/Roblox/rojo/issues/314)) -* Fixed performance issues introduced in Rojo 6.0.0-rc.1. ([#317](https://github.com/Roblox/rojo/issues/317)) -* Fixed `rojo plugin install` subcommand failing for everyone except Rojo developers. ([#320](https://github.com/Roblox/rojo/issues/320)) -* Updated default place template to take advantage of [#210](https://github.com/Roblox/rojo/pull/210). +* Fixed crash when malformed CSV files are put into a project. ([#310](https://github.com/rojo-rbx/rojo/issues/310)) +* Fixed incorrect string escaping when producing Lua code from JSON files. ([#314](https://github.com/rojo-rbx/rojo/issues/314)) +* Fixed performance issues introduced in Rojo 6.0.0-rc.1. ([#317](https://github.com/rojo-rbx/rojo/issues/317)) +* Fixed `rojo plugin install` subcommand failing for everyone except Rojo developers. ([#320](https://github.com/rojo-rbx/rojo/issues/320)) +* Updated default place template to take advantage of [#210](https://github.com/rojo-rbx/rojo/pull/210). * Enabled glob ignore patterns by default and removed the `unstable_glob_ignore` feature. * `globIgnorePaths` can be set on a project to a list of globs to ignore. -## [6.0.0 Release Candidate 1](https://github.com/Roblox/rojo/releases/tag/v6.0.0-rc.1) (March 29, 2020) +## [6.0.0 Release Candidate 1](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.1) (March 29, 2020) This release jumped from 0.6.0 to 6.0.0. Rojo has been in use in production for many users for quite a long times, and so 6.0 is a more accurate reflection of Rojo's version than a pre-1.0 version. * Added basic settings panel to plugin, with two settings: * "Open Scripts Externally": When enabled, opening a script in Studio will instead open it in your default text editor. * "Two-Way Sync": When enabled, Rojo will attempt to save changes to your place back to the filesystem. **Very early feature, very broken, beware!** * Added `--color` option to force-enable or force-disable color in Rojo's output. -* Added support for turning `.json` files into `ModuleScript` instances ([#308](https://github.com/Roblox/rojo/pull/308)) -* Added `rojo plugin install` and `rojo plugin uninstall` to allow Rojo to manage its Roblox Studio plugin. ([#304](https://github.com/Roblox/rojo/pull/304)) -* Class names no longer need to be specified for Roblox services in Rojo projects. ([#210](https://github.com/Roblox/rojo/pull/210)) +* Added support for turning `.json` files into `ModuleScript` instances ([#308](https://github.com/rojo-rbx/rojo/pull/308)) +* Added `rojo plugin install` and `rojo plugin uninstall` to allow Rojo to manage its Roblox Studio plugin. ([#304](https://github.com/rojo-rbx/rojo/pull/304)) +* Class names no longer need to be specified for Roblox services in Rojo projects. ([#210](https://github.com/rojo-rbx/rojo/pull/210)) * The server half of **experimental** two-way sync is now enabled by default. * Increased default logging verbosity in commands like `rojo build`. * Rojo now requires a project file again, just like 0.5.4. -## [0.6.0 Alpha 3](https://github.com/Roblox/rojo/releases/tag/v0.6.0-alpha.3) (March 13, 2020) -* Added `--watch` argument to `rojo build`. ([#284](https://github.com/Roblox/rojo/pull/284)) -* Added dark theme support to plugin. ([#241](https://github.com/Roblox/rojo/issues/241)) +## [0.6.0 Alpha 3](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.3) (March 13, 2020) +* Added `--watch` argument to `rojo build`. ([#284](https://github.com/rojo-rbx/rojo/pull/284)) +* Added dark theme support to plugin. ([#241](https://github.com/rojo-rbx/rojo/issues/241)) * Added a revamped `rojo init` command, which will now create more complete projects. * Added the `rojo doc` command, which opens Rojo's documentation in your browser. * Fixed many crashes from malformed projects and filesystem edge cases in `rojo serve`. @@ -35,22 +35,22 @@ This release jumped from 0.6.0 to 6.0.0. Rojo has been in use in production for * Any thread panicking now causes Rojo to abort instead of existing as a zombie. * Errors now have a list of causes, helping make many errors more clear. -## [0.6.0 Alpha 2](https://github.com/Roblox/rojo/releases/tag/v0.6.0-alpha.2) (March 6, 2020) +## [0.6.0 Alpha 2](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.2) (March 6, 2020) * Fixed `rojo upload` command always uploading models. * Removed `--kind` parameter to `rojo upload`; Rojo now automatically uploads the correct kind of asset based on your project file. -## [0.5.4](https://github.com/Roblox/rojo/releases/tag/v0.5.4) (February 26, 2020) +## [0.5.4](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.4) (February 26, 2020) This is a general maintenance release for the Rojo 0.5.x release series. * Updated reflection database and other dependencies. * First stable release with binaries for macOS and Linux. -## [0.6.0 Alpha 1](https://github.com/Roblox/rojo/releases/tag/v0.6.0-alpha.1) (January 22, 2020) +## [0.6.0 Alpha 1](https://github.com/rojo-rbx/rojo/releases/tag/v0.6.0-alpha.1) (January 22, 2020) ### General -* Added support for nested project files. ([#95](https://github.com/Roblox/rojo/issues/95)) -* Added project file hot-reloading. ([#10](https://github.com/Roblox/rojo/issues/10)]) -* Fixed Rojo dropping Ref properties ([#142](https://github.com/Roblox/rojo/issues/142)) +* Added support for nested project files. ([#95](https://github.com/rojo-rbx/rojo/issues/95)) +* Added project file hot-reloading. ([#10](https://github.com/rojo-rbx/rojo/issues/10)]) +* Fixed Rojo dropping Ref properties ([#142](https://github.com/rojo-rbx/rojo/issues/142)) * This means that properties like `PrimaryPart` now work! * Improved live sync protocol to reduce round-trips and improve syncing consistency. * Improved support for binary model files and places. @@ -69,52 +69,52 @@ This is a general maintenance release for the Rojo 0.5.x release series. * Added "error" state to show errors in a place that isn't the output panel. * Improved diagnostics for when the Rojo plugin cannot create an instance. -## [0.5.3](https://github.com/Roblox/rojo/releases/tag/v0.5.3) (October 15, 2019) +## [0.5.3](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.3) (October 15, 2019) * Fixed an issue where Rojo would throw an error when encountering recently-added instance classes. -## [0.5.2](https://github.com/Roblox/rojo/releases/tag/v0.5.2) (October 14, 2019) -* Fixed an issue where `LocalizationTable` instances would have their column order randomized. ([#173](https://github.com/Roblox/rojo/issues/173)) +## [0.5.2](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.2) (October 14, 2019) +* Fixed an issue where `LocalizationTable` instances would have their column order randomized. ([#173](https://github.com/rojo-rbx/rojo/issues/173)) -## [0.5.1](https://github.com/Roblox/rojo/releases/tag/v0.5.1) (October 4, 2019) -* Fixed an issue where Rojo would drop changes if they happened too quickly ([#252](https://github.com/Roblox/rojo/issues/252)) +## [0.5.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.1) (October 4, 2019) +* Fixed an issue where Rojo would drop changes if they happened too quickly ([#252](https://github.com/rojo-rbx/rojo/issues/252)) * Improved diagnostics for when the Rojo plugin cannot create an instance. * Updated dependencies * This brings Rojo's reflection database from client release 395 to client release 404. -## [0.5.0](https://github.com/Roblox/rojo/releases/tag/v0.5.0) (August 27, 2019) +## [0.5.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0) (August 27, 2019) * Changed `.model.json` naming, which may require projects to migrate ambiguous cases: * The file name now takes precedence over the `Name` field in the model, like Rojo 0.4.x. * The `Name` field of the top-level instance is now optional. It's recommended that you remove it from your models. * Rojo will emit a warning when `Name` is specified and does not match the name from the file. -* Fixed `Rect` values being set to `0, 0, 0, 0` when synced with the Rojo plugin. ([#201](https://github.com/Roblox/rojo/issues/201)) +* Fixed `Rect` values being set to `0, 0, 0, 0` when synced with the Rojo plugin. ([#201](https://github.com/rojo-rbx/rojo/issues/201)) * Fixed live-syncing of `PhysicalProperties`, `NumberSequence`, and `ColorSequence` values -## [0.5.0 Alpha 13](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.13) (August 2, 2019) +## [0.5.0 Alpha 13](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.13) (August 2, 2019) * Bumped minimum Rust version to 1.34.0. -* Fixed default port documentation in `rojo serve --help` ([#219](https://github.com/Roblox/rojo/issues/219)) +* Fixed default port documentation in `rojo serve --help` ([#219](https://github.com/rojo-rbx/rojo/issues/219)) * Fixed BrickColor support by upgrading Roblox-related dependencies -## [0.5.0 Alpha 12](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.12) (July 2, 2019) +## [0.5.0 Alpha 12](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.12) (July 2, 2019) * Added `.meta.json` files - * `init.meta.json` files replace `init.model.json` files from Rojo 0.4.x ([#183](https://github.com/Roblox/rojo/pull/183)) - * Other `.meta.json` files allow attaching extra data to other files ([#189](https://github.com/Roblox/rojo/pull/189)) + * `init.meta.json` files replace `init.model.json` files from Rojo 0.4.x ([#183](https://github.com/rojo-rbx/rojo/pull/183)) + * Other `.meta.json` files allow attaching extra data to other files ([#189](https://github.com/rojo-rbx/rojo/pull/189)) * Added support for infinite and NaN values in types like `Vector2` when building models and places. * These types aren't supported for live-syncing yet due to limitations around JSON encoding. * Added support for using `SharedString` values when building XML models and places. * Added support for live-syncing `CollectionService` tags. * Added a warning when building binary place files, since they're still experimental and have bugs. * Added a warning when trying to use Rojo 0.5.x with a Rojo 0.4.x-only project. -* Added a warning when a Rojo project contains keys that start with `$`, which are reserved names. ([#191](https://github.com/Roblox/rojo/issues/191)) +* Added a warning when a Rojo project contains keys that start with `$`, which are reserved names. ([#191](https://github.com/rojo-rbx/rojo/issues/191)) * Rojo now throws an error if unknown keys are found most files. * Added an icon to the plugin's toolbar button * Changed the plugin to use a docking widget for all UI. * Changed the plugin to ignore unknown properties when live-syncing. - * Rojo's approach to this problem might change later, like with a strict model mode ([#190](https://github.com/Roblox/rojo/issues/190)) or another approach. + * Rojo's approach to this problem might change later, like with a strict model mode ([#190](https://github.com/rojo-rbx/rojo/issues/190)) or another approach. * Upgraded to reflection database from client release 388. * Updated Rojo's branding to shift the color palette to make it work better on dark backgrounds -## [0.5.0 Alpha 11](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) -* Added support for implicit property values in JSON model files ([#154](https://github.com/Roblox/rojo/pull/154)) +## [0.5.0 Alpha 11](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.11) (May 29, 2019) +* Added support for implicit property values in JSON model files ([#154](https://github.com/rojo-rbx/rojo/pull/154)) * `Content` propertyes can now be specified in projects and model files as regular string literals. * Added support for `BrickColor` properties. * Added support for properties added in client release 384, like `Lighting.Technology` being set to `"ShadowMap"`. @@ -125,16 +125,16 @@ This is a general maintenance release for the Rojo 0.5.x release series. * Plugin should now be able to live-sync more properties, and ignore ones it can't, like `Lighting.Technology`. ## 0.5.0 Alpha 10 -* This release was a dud due to [issue #176](https://github.com/Roblox/rojo/issues/176) and was rolled back. +* This release was a dud due to [issue #176](https://github.com/rojo-rbx/rojo/issues/176) and was rolled back. -## [0.5.0 Alpha 9](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.9) (April 4, 2019) +## [0.5.0 Alpha 9](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.9) (April 4, 2019) * Changed `rojo build` to use buffered I/O, which can make it up to 2x faster in some cases. * Building [*Road Not Taken*](https://github.com/LPGhatguy/roads) to an `rbxlx` file dropped from 150ms to 70ms on my machine -* Fixed `LocalizationTable` instances being made from `csv` files incorrectly interpreting empty rows and columns. ([#149](https://github.com/Roblox/rojo/pull/149)) -* Fixed CSV files with entries that parse as numbers causing Rojo to panic. ([#152](https://github.com/Roblox/rojo/pull/152)) +* Fixed `LocalizationTable` instances being made from `csv` files incorrectly interpreting empty rows and columns. ([#149](https://github.com/rojo-rbx/rojo/pull/149)) +* Fixed CSV files with entries that parse as numbers causing Rojo to panic. ([#152](https://github.com/rojo-rbx/rojo/pull/152)) * Improved error messages when malformed CSV files are found in a Rojo project. -## [0.5.0 Alpha 8](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.8) (March 29, 2019) +## [0.5.0 Alpha 8](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.8) (March 29, 2019) * Added support for a bunch of new types when dealing with XML model/place files: * `ColorSequence` * `Float64` @@ -145,13 +145,13 @@ This is a general maintenance release for the Rojo 0.5.x release series. * `Ray` * `Rect` * `Ref` -* Improved server instance ordering behavior when files are added during a live session ([#135](https://github.com/Roblox/rojo/pull/135)) +* Improved server instance ordering behavior when files are added during a live session ([#135](https://github.com/rojo-rbx/rojo/pull/135)) * Fixed error being thrown when trying to unload the Rojo plugin. -* Added partial fix for [issue #141](https://github.com/Roblox/rojo/issues/141) for `Lighting.Technology`, which should restore live sync functionality for the default project file. +* Added partial fix for [issue #141](https://github.com/rojo-rbx/rojo/issues/141) for `Lighting.Technology`, which should restore live sync functionality for the default project file. -## [0.5.0 Alpha 6](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.6) (March 19, 2019) +## [0.5.0 Alpha 6](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.6) (March 19, 2019) * Fixed `rojo init` giving unexpected results by upgrading to `rbx_dom_weak` 1.1.0 -* Fixed live server not responding when the Rojo plugin is connected ([#133](https://github.com/Roblox/rojo/issues/133)) +* Fixed live server not responding when the Rojo plugin is connected ([#133](https://github.com/rojo-rbx/rojo/issues/133)) * Updated default place file: * Improved default properties to be closer to Studio's built-in 'Baseplate' template * Added a baseplate to the project file (Thanks, [@AmaranthineCodices](https://github.com/AmaranthineCodices/)!) @@ -159,40 +159,40 @@ This is a general maintenance release for the Rojo 0.5.x release series. * Fixed some cases where the Rojo plugin would leave around objects that it knows should be deleted * Updated plugin to correctly listen to `Plugin.Unloading` when installing or uninstalling new plugins -## [0.5.0 Alpha 5](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.5) (March 1, 2019) +## [0.5.0 Alpha 5](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.5) (March 1, 2019) * Upgraded core dependencies, which improves compatibility for lots of instance types * Upgraded from `rbx_tree` 0.2.0 to `rbx_dom_weak` 1.0.0 * Upgraded from `rbx_xml` 0.2.0 to `rbx_xml` 0.4.0 * Upgraded from `rbx_binary` 0.2.0 to `rbx_binary` 0.4.0 * Added support for non-primitive types in the Rojo plugin. * Types like `Color3` and `CFrame` can now be updated live! -* Fixed plugin assets flashing in on first load ([#121](https://github.com/Roblox/rojo/issues/121)) +* Fixed plugin assets flashing in on first load ([#121](https://github.com/rojo-rbx/rojo/issues/121)) * Changed Rojo's HTTP server from Rouille to Hyper, which reduced the release size by around a megabyte. -* Added property type inference to projects, which makes specifying services a lot easier ([#130](https://github.com/Roblox/rojo/pull/130)) +* Added property type inference to projects, which makes specifying services a lot easier ([#130](https://github.com/rojo-rbx/rojo/pull/130)) * Made error messages from invalid and missing files more user-friendly -## [0.5.0 Alpha 4](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.4) (February 8, 2019) -* Added support for nested partitions ([#102](https://github.com/Roblox/rojo/issues/102)) -* Added support for 'transmuting' partitions ([#112](https://github.com/Roblox/rojo/issues/112)) -* Added support for aliasing filesystem paths ([#105](https://github.com/Roblox/rojo/issues/105)) -* Changed Windows builds to statically link the CRT ([#89](https://github.com/Roblox/rojo/issues/89)) +## [0.5.0 Alpha 4](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.4) (February 8, 2019) +* Added support for nested partitions ([#102](https://github.com/rojo-rbx/rojo/issues/102)) +* Added support for 'transmuting' partitions ([#112](https://github.com/rojo-rbx/rojo/issues/112)) +* Added support for aliasing filesystem paths ([#105](https://github.com/rojo-rbx/rojo/issues/105)) +* Changed Windows builds to statically link the CRT ([#89](https://github.com/rojo-rbx/rojo/issues/89)) -## [0.5.0 Alpha 3](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.3) (February 1, 2019) -* Changed default project file name from `roblox-project.json` to `default.project.json` ([#120](https://github.com/Roblox/rojo/pull/120)) +## [0.5.0 Alpha 3](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.3) (February 1, 2019) +* Changed default project file name from `roblox-project.json` to `default.project.json` ([#120](https://github.com/rojo-rbx/rojo/pull/120)) * The old file name will still be supported until 0.5.0 is fully released. * Added warning when loading project files that don't end in `.project.json` * This new extension enables Rojo to distinguish project files from random JSON files, which is necessary to support nested projects. * Added new (empty) diagnostic page served from the server * Added better error messages for when a file is missing that's referenced by a Rojo project * Added support for visualization endpoints returning GraphViz source when Dot is not available -* Fixed an in-memory filesystem regression introduced recently ([#119](https://github.com/Roblox/rojo/pull/119)) +* Fixed an in-memory filesystem regression introduced recently ([#119](https://github.com/rojo-rbx/rojo/pull/119)) -## [0.5.0 Alpha 2](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.2) (January 28, 2019) +## [0.5.0 Alpha 2](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.2) (January 28, 2019) * Added support for `.model.json` files, compatible with 0.4.x * Fixed in-memory filesystem not handling out-of-order filesystem change events -* Fixed long-polling error caused by a promise mixup ([#110](https://github.com/Roblox/rojo/issues/110)) +* Fixed long-polling error caused by a promise mixup ([#110](https://github.com/rojo-rbx/rojo/issues/110)) -## [0.5.0 Alpha 1](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.1) (January 25, 2019) +## [0.5.0 Alpha 1](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.1) (January 25, 2019) * Changed plugin UI to be way prettier * Thanks to [Reselim](https://github.com/Reselim) for the design! * Changed plugin error messages to be a little more useful @@ -200,7 +200,7 @@ This is a general maintenance release for the Rojo 0.5.x release series. * Fixed bug where bad server responses could cause the plugin to be in a bad state * Upgraded to rbx\_tree, rbx\_xml, and rbx\_binary 0.2.0, which dramatically expands the kinds of properties that Rojo can handle, especially in XML. -## [0.5.0 Alpha 0](https://github.com/Roblox/rojo/releases/tag/v0.5.0-alpha.0) (January 14, 2019) +## [0.5.0 Alpha 0](https://github.com/rojo-rbx/rojo/releases/tag/v0.5.0-alpha.0) (January 14, 2019) * "Epiphany" rewrite, in progress since the beginning of time * New live sync protocol * Uses HTTP long polling to reduce request count and improve responsiveness @@ -225,105 +225,105 @@ This is a general maintenance release for the Rojo 0.5.x release series. * Multiple places can be specified, like when building a multi-place game * Added support for specifying properties on services in project files -## [0.4.13](https://github.com/Roblox/rojo/releases/tag/v0.4.13) (November 12, 2018) +## [0.4.13](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.13) (November 12, 2018) * When `rojo.json` points to a file or directory that does not exist, Rojo now issues a warning instead of throwing an error and exiting -## [0.4.12](https://github.com/Roblox/rojo/releases/tag/v0.4.12) (June 21, 2018) -* Fixed obscure assertion failure when renaming or deleting files ([#78](https://github.com/Roblox/rojo/issues/78)) -* Added a `PluginAction` for the sync in command, which should help with some automation scripts ([#80](https://github.com/Roblox/rojo/pull/80)) +## [0.4.12](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.12) (June 21, 2018) +* Fixed obscure assertion failure when renaming or deleting files ([#78](https://github.com/rojo-rbx/rojo/issues/78)) +* Added a `PluginAction` for the sync in command, which should help with some automation scripts ([#80](https://github.com/rojo-rbx/rojo/pull/80)) -## [0.4.11](https://github.com/Roblox/rojo/releases/tag/v0.4.11) (June 10, 2018) +## [0.4.11](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.11) (June 10, 2018) * Defensively insert existing instances into RouteMap; should fix most duplication cases when syncing into existing trees. * Fixed incorrect synchronization from `Plugin:_pull` that would cause polling to create issues * Fixed incorrect file routes being assigned to `init.lua` and `init.model.json` files * Untangled route handling-internals slightly -## [0.4.10](https://github.com/Roblox/rojo/releases/tag/v0.4.10) (June 2, 2018) -* Added support for `init.model.json` files, which enable versioning `Tool` instances (among other things) with Rojo. ([#66](https://github.com/Roblox/rojo/issues/66)) +## [0.4.10](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.10) (June 2, 2018) +* Added support for `init.model.json` files, which enable versioning `Tool` instances (among other things) with Rojo. ([#66](https://github.com/rojo-rbx/rojo/issues/66)) * Fixed obscure error when syncing into an invalid service. * Fixed multiple sync processes occurring when a server ID mismatch is detected. -## [0.4.9](https://github.com/Roblox/rojo/releases/tag/v0.4.9) (May 26, 2018) -* Fixed warning when renaming or removing files that would sometimes corrupt the instance cache ([#72](https://github.com/Roblox/rojo/pull/72)) +## [0.4.9](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.9) (May 26, 2018) +* Fixed warning when renaming or removing files that would sometimes corrupt the instance cache ([#72](https://github.com/rojo-rbx/rojo/pull/72)) * JSON models are no longer as strict -- `Children` and `Properties` are now optional. -## [0.4.8](https://github.com/Roblox/rojo/releases/tag/v0.4.8) (May 26, 2018) +## [0.4.8](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.8) (May 26, 2018) * Hotfix to prevent errors from being thrown when objects managed by Rojo are deleted -## [0.4.7](https://github.com/Roblox/rojo/releases/tag/v0.4.7) (May 25, 2018) -* Added icons to the Rojo plugin, made by [@Vorlias](https://github.com/Vorlias)! ([#70](https://github.com/Roblox/rojo/pull/70)) -* Server will now issue a warning if no partitions are specified in `rojo serve` ([#40](https://github.com/Roblox/rojo/issues/40)) +## [0.4.7](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.7) (May 25, 2018) +* Added icons to the Rojo plugin, made by [@Vorlias](https://github.com/Vorlias)! ([#70](https://github.com/rojo-rbx/rojo/pull/70)) +* Server will now issue a warning if no partitions are specified in `rojo serve` ([#40](https://github.com/rojo-rbx/rojo/issues/40)) -## [0.4.6](https://github.com/Roblox/rojo/releases/tag/v0.4.6) (May 21, 2018) -* Rojo handles being restarted by Roblox Studio more gracefully ([#67](https://github.com/Roblox/rojo/issues/67)) +## [0.4.6](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.6) (May 21, 2018) +* Rojo handles being restarted by Roblox Studio more gracefully ([#67](https://github.com/rojo-rbx/rojo/issues/67)) * Folders should no longer get collapsed when syncing occurs. * **Significant** robustness improvements with regards to caching. * **This should catch all existing script duplication bugs.** * If there are any bugs with script duplication or caching in the future, restarting the Rojo server process will fix them for that session. * Fixed message in plugin not being prefixed with `Rojo: `. -## [0.4.5](https://github.com/Roblox/rojo/releases/tag/v0.4.5) (May 1, 2018) +## [0.4.5](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.5) (May 1, 2018) * Rojo messages are now prefixed with `Rojo: ` to make them stand out in the output more. * Fixed server to notice file changes *much* more quickly. (200ms vs 1000ms) * Server now lists name of project when starting up. -* Rojo now throws an error if no project file is found. ([#63](https://github.com/Roblox/rojo/issues/63)) -* Fixed multiple sync operations occuring at the same time. ([#61](https://github.com/Roblox/rojo/issues/61)) -* Partitions targeting files directly now work as expected. ([#57](https://github.com/Roblox/rojo/issues/57)) +* Rojo now throws an error if no project file is found. ([#63](https://github.com/rojo-rbx/rojo/issues/63)) +* Fixed multiple sync operations occuring at the same time. ([#61](https://github.com/rojo-rbx/rojo/issues/61)) +* Partitions targeting files directly now work as expected. ([#57](https://github.com/rojo-rbx/rojo/issues/57)) -## [0.4.4](https://github.com/Roblox/rojo/releases/tag/v0.4.4) (April 7, 2018) +## [0.4.4](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.4) (April 7, 2018) * Fix small regression introduced in 0.4.3 -## [0.4.3](https://github.com/Roblox/rojo/releases/tag/v0.4.3) (April 7, 2018) -* Plugin now automatically selects `HttpService` if it determines that HTTP isn't enabled ([#58](https://github.com/Roblox/rojo/pull/58)) +## [0.4.3](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.3) (April 7, 2018) +* Plugin now automatically selects `HttpService` if it determines that HTTP isn't enabled ([#58](https://github.com/rojo-rbx/rojo/pull/58)) * Plugin now has much more robust handling and will wipe all state when the server changes. * This should fix issues that would otherwise be solved by restarting Roblox Studio. -## [0.4.2](https://github.com/Roblox/rojo/releases/tag/v0.4.2) (April 4, 2018) +## [0.4.2](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.2) (April 4, 2018) * Fixed final case of duplicated instance insertion, caused by reconciled instances not being inserted into `RouteMap`. * The reconciler is still not a perfect solution, especially if script instances get moved around without being destroyed. I don't think this can be fixed before a big refactor. -## [0.4.1](https://github.com/Roblox/rojo/releases/tag/v0.4.1) (April 1, 2018) +## [0.4.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.1) (April 1, 2018) * Merged plugin repository into main Rojo repository for easier tracking. * Improved `RouteMap` object tracking; this should fix some cases of duplicated instances being synced into the tree. -## [0.4.0](https://github.com/Roblox/rojo/releases/tag/v0.4.0) (March 27, 2018) +## [0.4.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.4.0) (March 27, 2018) * Protocol version 1, which shifts more responsibility onto the server * This is a **major breaking** change! * The server now has a content of 'filter plugins', which transform data at various stages in the pipeline * The server now exposes Roblox instance objects instead of file contents, which lines up with how `rojo pack` will work, and paves the way for more robust syncing. * Added `*.model.json` files, which let you embed small Roblox objects into your Rojo tree. -* Improved error messages in some cases ([#46](https://github.com/Roblox/rojo/issues/46)) +* Improved error messages in some cases ([#46](https://github.com/rojo-rbx/rojo/issues/46)) -## [0.3.2](https://github.com/Roblox/rojo/releases/tag/v0.3.2) (December 20, 2017) +## [0.3.2](https://github.com/rojo-rbx/rojo/releases/tag/v0.3.2) (December 20, 2017) * Fixed `rojo serve` failing to correctly construct an absolute root path when passed as an argument * Fixed intense CPU usage when running `rojo serve` -## [0.3.1](https://github.com/Roblox/rojo/releases/tag/v0.3.1) (December 14, 2017) +## [0.3.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.3.1) (December 14, 2017) * Improved error reporting when invalid JSON is found in a `rojo.json` project * These messages are passed on from Serde -## [0.3.0](https://github.com/Roblox/rojo/releases/tag/v0.3.0) (December 12, 2017) +## [0.3.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.3.0) (December 12, 2017) * Factored out the plugin into a separate repository * Fixed server when using a file as a partition * Previously, trailing slashes were put on the end of a partition even if the read request was an empty string. This broke file reading on Windows when a partition pointed to a file instead of a directory! * Started running automatic tests on Travis CI (#9) -## [0.2.3](https://github.com/Roblox/rojo/releases/tag/v0.2.3) (December 4, 2017) +## [0.2.3](https://github.com/rojo-rbx/rojo/releases/tag/v0.2.3) (December 4, 2017) * Plugin only release * Tightened `init` file rules to only match script files * Previously, Rojo would sometimes pick up the wrong file when syncing -## [0.2.2](https://github.com/Roblox/rojo/releases/tag/v0.2.2) (December 1, 2017) +## [0.2.2](https://github.com/rojo-rbx/rojo/releases/tag/v0.2.2) (December 1, 2017) * Plugin only release * Fixed broken reconciliation behavior with `init` files -## [0.2.1](https://github.com/Roblox/rojo/releases/tag/v0.2.1) (December 1, 2017) +## [0.2.1](https://github.com/rojo-rbx/rojo/releases/tag/v0.2.1) (December 1, 2017) * Plugin only release * Changes default port to 8000 -## [0.2.0](https://github.com/Roblox/rojo/releases/tag/v0.2.0) (December 1, 2017) +## [0.2.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.2.0) (December 1, 2017) * Support for `init.lua` like rbxfs and rbxpacker * More robust syncing with a new reconciler -## [0.1.0](https://github.com/Roblox/rojo/releases/tag/v0.1.0) (November 29, 2017) +## [0.1.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.1.0) (November 29, 2017) * Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0ab92137..9eccac56 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,10 +3,10 @@ Rojo is a big project and can always use more help! Some of the repositories covered are: -* https://github.com/Roblox/rojo -* https://github.com/Roblox/rbx-dom -* https://github.com/Roblox/vscode-rojo -* https://github.com/Roblox/rbxlx-to-rojo +* https://github.com/rojo-rbx/rojo +* https://github.com/rojo-rbx/rbx-dom +* https://github.com/rojo-rbx/vscode-rojo +* https://github.com/rojo-rbx/rbxlx-to-rojo ## Code Code contributions are welcome for features and bugs that have been reported in the project's bug tracker. We want to make sure that no one wastes their time, so be sure to talk with maintainers about what changes would be accepted before doing any work! @@ -14,7 +14,7 @@ Code contributions are welcome for features and bugs that have been reported in You'll want these tools to work on Rojo: * Latest stable Rust compiler -* Latest stable [Rojo](https://github.com/Roblox/rojo) +* Latest stable [Rojo](https://github.com/rojo-rbx/rojo) * [Foreman](https://github.com/Roblox/foreman) ## Documentation diff --git a/Cargo.toml b/Cargo.toml index b3992e28..57a08e35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ description = "Enables professional-grade development tools for Roblox developer license = "MPL-2.0" homepage = "https://rojo.space" documentation = "https://rojo.space/docs" -repository = "https://github.com/Roblox/rojo" +repository = "https://github.com/rojo-rbx/rojo" readme = "README.md" edition = "2018" diff --git a/README.md b/README.md index 258c70fa..edf89258 100644 --- a/README.md +++ b/README.md @@ -7,8 +7,8 @@
     
    - - Actions status + + Actions status Latest server version @@ -20,8 +20,6 @@
    -**Heads up! This repository was recently migrated from [the rojo-rbx org](https://github.com/rojo-rbx) to [the Roblox org](https://github.com/Roblox). Not much else has changed.** - **Rojo** is a tool designed to enable Roblox developers to use professional-grade software engineering tools. With Rojo, it's possible to use industry-leading tools like **Visual Studio Code** and **Git**. @@ -43,7 +41,7 @@ In the future, Rojo will be able to: * Import custom instances like MoonScript code ## [Documentation](https://rojo.space/docs) -Documentation is hosted in the [rojo.space repository](https://github.com/Roblox/rojo.space). +Documentation is hosted in the [rojo.space repository](https://github.com/rojo-rbx/rojo.space). ## Contributing Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions for helping work on Rojo! diff --git a/assets/default-model-project/README.md b/assets/default-model-project/README.md index 617d7093..30dfc436 100644 --- a/assets/default-model-project/README.md +++ b/assets/default-model-project/README.md @@ -1,5 +1,5 @@ # {project_name} -Generated by [Rojo](https://github.com/Roblox/rojo) {rojo_version}. +Generated by [Rojo](https://github.com/rojo-rbx/rojo) {rojo_version}. ## Getting Started To build this library or plugin, use: diff --git a/assets/default-place-project/README.md b/assets/default-place-project/README.md index f519d472..7908cf59 100644 --- a/assets/default-place-project/README.md +++ b/assets/default-place-project/README.md @@ -1,5 +1,5 @@ # {project_name} -Generated by [Rojo](https://github.com/Roblox/rojo) {rojo_version}. +Generated by [Rojo](https://github.com/rojo-rbx/rojo) {rojo_version}. ## Getting Started To build the place from scratch, use: diff --git a/foreman.toml b/foreman.toml index 7df5a1a3..fe2956e1 100644 --- a/foreman.toml +++ b/foreman.toml @@ -1,2 +1,2 @@ [tools] -rojo = { source = "Roblox/rojo", version = "6.0.0-rc.1" } +rojo = { source = "rojo-rbx/rojo", version = "6.0.0-rc.1" } diff --git a/memofs/Cargo.toml b/memofs/Cargo.toml index f31553cb..12c67caa 100644 --- a/memofs/Cargo.toml +++ b/memofs/Cargo.toml @@ -6,7 +6,7 @@ authors = ["Lucien Greathouse "] edition = "2018" readme = "README.md" license = "MIT" -homepage = "https://github.com/Roblox/rojo/tree/master/memofs" +homepage = "https://github.com/rojo-rbx/rojo/tree/master/memofs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html diff --git a/memofs/README.md b/memofs/README.md index c0f5740f..056832cd 100644 --- a/memofs/README.md +++ b/memofs/README.md @@ -5,7 +5,7 @@ Implementation of a virtual filesystem with a configurable backend and file watching. memofs is currently an unstable minimum viable library. Its primary consumer is -[Rojo](https://github.com/Roblox/rojo), a build system for Roblox. +[Rojo](https://github.com/rojo-rbx/rojo), a build system for Roblox. ### Current Features * API similar to `std::fs` diff --git a/memofs/src/lib.rs b/memofs/src/lib.rs index c8f543a6..f6a17ef6 100644 --- a/memofs/src/lib.rs +++ b/memofs/src/lib.rs @@ -3,7 +3,7 @@ Implementation of a virtual filesystem with a configurable backend and file watching. memofs is currently an unstable minimum viable library. Its primary consumer is -[Rojo](https://github.com/Roblox/rojo), a build system for Roblox. +[Rojo](https://github.com/rojo-rbx/rojo), a build system for Roblox. ## Current Features * API similar to `std::fs` diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 57e65db8..40af8058 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -34,7 +34,7 @@ local function rejectWrongProtocolVersion(infoResponseBody) "\nMake sure you have matching versions of both the Rojo plugin and server!" .. "\n\nYour client is version %s, with protocol version %s. It expects server version %s." .. "\nYour server is version %s, with protocol version %s." .. - "\n\nGo to https://github.com/Roblox/rojo for more details." + "\n\nGo to https://github.com/rojo-rbx/rojo for more details." ):format( Version.display(Config.version), Config.protocolVersion, Config.expectedServerVersionString, diff --git a/plugin/src/invariant.lua b/plugin/src/invariant.lua index 09c6d2e0..7cb813b4 100644 --- a/plugin/src/invariant.lua +++ b/plugin/src/invariant.lua @@ -18,7 +18,7 @@ else "Rojo detected an invariant violation within itself:\n" .. "%s\n\n" .. "This is a bug in Rojo. Please file an issue:\n" .. - "https://github.com/Roblox/rojo/issues", + "https://github.com/rojo-rbx/rojo/issues", message ) diff --git a/src/lua_ast.rs b/src/lua_ast.rs index fac62c2e..b29370b4 100644 --- a/src/lua_ast.rs +++ b/src/lua_ast.rs @@ -315,7 +315,7 @@ impl<'a> LuaStream<'a> { mod test { use super::*; - /// Regression test for https://github.com/Roblox/rojo/issues/314 + /// Regression test for https://github.com/rojo-rbx/rojo/issues/314 #[test] fn bug_314() { let my_value = "\"\r\n\t\\".to_owned(); From 7cd9bd383e131094beb7a19306bf05cd84decd8c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 29 Oct 2020 10:35:55 -0700 Subject: [PATCH 1067/1504] Update to latest reflection database --- plugin/rbx_dom_lua/README.md | 4 +- .../src/ReflectionDatabase/classes.lua | 2162 ++++++++++++----- 2 files changed, 1496 insertions(+), 670 deletions(-) diff --git a/plugin/rbx_dom_lua/README.md b/plugin/rbx_dom_lua/README.md index e2eec50c..437e37c1 100644 --- a/plugin/rbx_dom_lua/README.md +++ b/plugin/rbx_dom_lua/README.md @@ -1,2 +1,2 @@ -# rbx\_dom\_lua -Roblox Lua implementation of rbx-dom mechanisms, intended to work with rbx\_dom\_weak and friends. \ No newline at end of file +# rbx_dom_lua +Roblox Lua implementation of rbx-dom mechanisms, intended to work with rbx_dom_weak and friends. \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua b/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua index 93949b42..c53b075f 100644 --- a/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua +++ b/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua @@ -6,7 +6,6 @@ return { properties = { }, defaults = { - Name = "ABTestService", }, }, Accessory = { @@ -306,6 +305,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + ReactionTorqueEnabled = { + name = "ReactionTorqueEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, RelativeTo = { name = "RelativeTo", type = {type = "Enum", name = "ActuatorRelativeTo"}, @@ -324,6 +332,7 @@ return { Enabled = true, MaxTorque = 0, Name = "AngularVelocity", + ReactionTorqueEnabled = false, RelativeTo = 2, Visible = false, }, @@ -485,6 +494,22 @@ return { Visible = true, }, }, + AssetCounterService = { + name = "AssetCounterService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, + AssetManagerService = { + name = "AssetManagerService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, AssetService = { name = "AssetService", superclass = "Instance", @@ -494,6 +519,75 @@ return { Name = "AssetService", }, }, + Atmosphere = { + name = "Atmosphere", + superclass = "Instance", + properties = { + Color = { + name = "Color", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Decay = { + name = "Decay", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Density = { + name = "Density", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Glare = { + name = "Glare", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Haze = { + name = "Haze", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Offset = { + name = "Offset", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Color = Color3.new(0.7843, 0.6667, 0.4235), + Decay = Color3.new(0.3608, 0.2353, 0.0549), + Density = 0.395, + Glare = 0, + Haze = 0, + Name = "Atmosphere", + Offset = 0, + }, + }, Attachment = { name = "Attachment", superclass = "Instance", @@ -632,6 +726,15 @@ return { WorldSecondaryAxis = Vector3.new(0, 1, 0), }, }, + AvatarEditorService = { + name = "AvatarEditorService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "AvatarEditorService", + }, + }, Backpack = { name = "Backpack", superclass = "Instance", @@ -680,6 +783,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + MaxFrictionTorque = { + name = "MaxFrictionTorque", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, Radius = { name = "Radius", type = {type = "Data", name = "Float32"}, @@ -741,6 +853,7 @@ return { Color = BrickColor.new(1009), Enabled = true, LimitsEnabled = false, + MaxFrictionTorque = 0, Name = "BallSocketConstraint", Radius = 0.15, Restitution = 0, @@ -1034,6 +1147,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + Mass = { + name = "Mass", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, Massless = { name = "Massless", type = {type = "Data", name = "Bool"}, @@ -2237,6 +2359,55 @@ return { Velocity = Vector3.new(0, 2, 0), }, }, + Bone = { + name = "Bone", + superclass = "Attachment", + properties = { + Transform = { + name = "Transform", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + TransformedCFrame = { + name = "TransformedCFrame", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TransformedWorldCFrame = { + name = "TransformedWorldCFrame", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + Axis = Vector3.new(1, 0, 0), + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Name = "Bone", + Orientation = Vector3.new(0, 0, 0), + Position = Vector3.new(0, 0, 0), + Rotation = Vector3.new(0, 0, 0), + SecondaryAxis = Vector3.new(0, 1, 0), + Transform = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Visible = false, + WorldAxis = Vector3.new(1, 0, 0), + WorldCFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + WorldOrientation = Vector3.new(0, 0, 0), + WorldPosition = Vector3.new(0, 0, 0), + WorldSecondaryAxis = Vector3.new(0, 1, 0), + }, + }, BoolValue = { name = "BoolValue", superclass = "ValueBase", @@ -2271,6 +2442,7 @@ return { }, }, defaults = { + AdornCullingMode = 0, Adornee = nil, AlwaysOnTop = false, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), @@ -2308,6 +2480,15 @@ return { superclass = "Instance", properties = { }, + defaults = { + Name = "Instance", + }, + }, + BulkImportService = { + name = "BulkImportService", + superclass = "Instance", + properties = { + }, defaults = { }, }, @@ -2386,6 +2567,15 @@ return { scriptability = "ReadWrite", serializes = false, }, + DiagonalFieldOfView = { + name = "DiagonalFieldOfView", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, FieldOfView = { name = "FieldOfView", type = {type = "Data", name = "Float32"}, @@ -2395,6 +2585,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + FieldOfViewMode = { + name = "FieldOfViewMode", + type = {type = "Enum", name = "FieldOfViewMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, Focus = { name = "Focus", type = {type = "Data", name = "CFrame"}, @@ -2422,6 +2621,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + MaxAxisFieldOfView = { + name = "MaxAxisFieldOfView", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, NearPlaneZ = { name = "NearPlaneZ", type = {type = "Data", name = "Float32"}, @@ -2454,13 +2662,24 @@ return { CFrame = CFrame.new(0, 20, 20, 1, 0, 0, 0, 0.7071068, 0.7071068, 0, -0.7071068, 0.7071068), CameraSubject = nil, CameraType = 0, + DiagonalFieldOfView = 0, FieldOfView = 70, + FieldOfViewMode = 0, Focus = CFrame.new(0, 0, -5, 1, 0, 0, 0, 1, 0, 0, 0, 1), HeadLocked = true, HeadScale = 1, + MaxAxisFieldOfView = 0, Name = "Camera", }, }, + CatalogPages = { + name = "CatalogPages", + superclass = "Pages", + properties = { + }, + defaults = { + }, + }, ChangeHistoryService = { name = "ChangeHistoryService", superclass = "Instance", @@ -2832,6 +3051,7 @@ return { }, }, defaults = { + AdornCullingMode = 0, Adornee = nil, AlwaysOnTop = false, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), @@ -3004,7 +3224,6 @@ return { }, defaults = { Name = "CoreGui", - SelectionImageObject = nil, }, }, CorePackages = { @@ -3013,7 +3232,6 @@ return { properties = { }, defaults = { - Name = "CorePackages", }, }, CoreScript = { @@ -3119,6 +3337,15 @@ return { name = "CylinderHandleAdornment", superclass = "HandleAdornment", properties = { + Angle = { + name = "Angle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, Height = { name = "Height", type = {type = "Data", name = "Float32"}, @@ -3128,6 +3355,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + InnerRadius = { + name = "InnerRadius", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, Radius = { name = "Radius", type = {type = "Data", name = "Float32"}, @@ -3139,12 +3375,15 @@ return { }, }, defaults = { + AdornCullingMode = 0, Adornee = nil, AlwaysOnTop = false, + Angle = 360, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), Color = BrickColor.new(23), Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), Height = 1, + InnerRadius = 0, Name = "CylinderHandleAdornment", Radius = 1, SizeRelativeOffset = Vector3.new(0, 0, 0), @@ -3619,24 +3858,6 @@ return { scriptability = "Read", serializes = false, }, - ErrorReporting = { - name = "ErrorReporting", - type = {type = "Enum", name = "ErrorReporting"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GfxCard = { - name = "GfxCard", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, InstanceCount = { name = "InstanceCount", type = {type = "Data", name = "Int32"}, @@ -3646,15 +3867,6 @@ return { scriptability = "Read", serializes = false, }, - IsFmodProfilingEnabled = { - name = "IsFmodProfilingEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, IsScriptStackTracingEnabled = { name = "IsScriptStackTracingEnabled", type = {type = "Data", name = "Bool"}, @@ -3673,42 +3885,6 @@ return { scriptability = "Read", serializes = false, }, - OsIs64Bit = { - name = "OsIs64Bit", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - OsPlatform = { - name = "OsPlatform", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - OsPlatformId = { - name = "OsPlatformId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - OsVer = { - name = "OsVer", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, PlayerCount = { name = "PlayerCount", type = {type = "Data", name = "Int32"}, @@ -3727,15 +3903,6 @@ return { scriptability = "ReadWrite", serializes = true, }, - RobloxProductName = { - name = "RobloxProductName", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, RobloxVersion = { name = "RobloxVersion", type = {type = "Data", name = "String"}, @@ -3745,24 +3912,6 @@ return { scriptability = "Read", serializes = false, }, - SIMD = { - name = "SIMD", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - SystemProductName = { - name = "SystemProductName", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, TickCountPreciseOverride = { name = "TickCountPreciseOverride", type = {type = "Enum", name = "TickCountSampleMethod"}, @@ -3772,15 +3921,6 @@ return { scriptability = "ReadWrite", serializes = true, }, - VideoMemory = { - name = "VideoMemory", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, }, defaults = { }, @@ -3816,6 +3956,15 @@ return { scriptability = "Read", serializes = false, }, + isContextDependentBreakpoint = { + name = "isContextDependentBreakpoint", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, }, defaults = { }, @@ -3924,6 +4073,56 @@ return { Transparency = 0, }, }, + DepthOfFieldEffect = { + name = "DepthOfFieldEffect", + superclass = "PostEffect", + properties = { + FarIntensity = { + name = "FarIntensity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + FocusDistance = { + name = "FocusDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + InFocusRadius = { + name = "InFocusRadius", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NearIntensity = { + name = "NearIntensity", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Enabled = true, + FarIntensity = 0.75, + FocusDistance = 0.05, + InFocusRadius = 10, + Name = "DepthOfField", + NearIntensity = 0.75, + }, + }, Dialog = { name = "Dialog", superclass = "Instance", @@ -4304,6 +4503,14 @@ return { Priority = 0, }, }, + EventIngestService = { + name = "EventIngestService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, Explosion = { name = "Explosion", superclass = "Instance", @@ -4915,6 +5122,7 @@ return { Active = false, AnchorPoint = Vector2.new(0, 0), AutoLocalize = true, + AutomaticSize = 0, BackgroundColor = BrickColor.new(194), BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), BackgroundTransparency = 0, @@ -5002,78 +5210,6 @@ return { scriptability = "ReadWrite", serializes = true, }, - BubbleChatLifetime = { - name = "BubbleChatLifetime", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BubbleChatMaxBubbles = { - name = "BubbleChatMaxBubbles", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ChatHistory = { - name = "ChatHistory", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ChatScrollLength = { - name = "ChatScrollLength", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CollisionSoundEnabled = { - name = "CollisionSoundEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - CollisionSoundVolume = { - name = "CollisionSoundVolume", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - HardwareMouse = { - name = "HardwareMouse", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxCollisionSounds = { - name = "MaxCollisionSounds", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, OverrideStarterScript = { name = "OverrideStarterScript", type = {type = "Data", name = "String"}, @@ -5083,24 +5219,6 @@ return { scriptability = "ReadWrite", serializes = true, }, - ReportAbuseChatHistory = { - name = "ReportAbuseChatHistory", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SoftwareSound = { - name = "SoftwareSound", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, VideoCaptureEnabled = { name = "VideoCaptureEnabled", type = {type = "Data", name = "Bool"}, @@ -5110,14 +5228,14 @@ return { scriptability = "ReadWrite", serializes = true, }, - VideoQuality = { - name = "VideoQuality", - type = {type = "Enum", name = "VideoQualitySettings"}, + VideoRecording = { + name = "VideoRecording", + type = {type = "Data", name = "Bool"}, isCanonical = true, canonicalName = nil, serializedName = nil, scriptability = "ReadWrite", - serializes = true, + serializes = false, }, }, defaults = { @@ -5127,6 +5245,15 @@ return { name = "GamepadService", superclass = "Instance", properties = { + GamepadCursorEnabled = { + name = "GamepadCursorEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, }, defaults = { Name = "GamepadService", @@ -5209,6 +5336,7 @@ return { defaults = { C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Enabled = true, F0 = Vector3.new(0, 0, 0), F1 = Vector3.new(0, 0, 0), F2 = Vector3.new(0, 0, 0), @@ -5283,6 +5411,24 @@ return { scriptability = "ReadWrite", serializes = true, }, + ClippedRect = { + name = "ClippedRect", + type = {type = "Data", name = "Rect"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + IsNotOccluded = { + name = "IsNotOccluded", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, Localize = { name = "Localize", type = {type = "Data", name = "Bool"}, @@ -5292,6 +5438,15 @@ return { scriptability = "ReadWrite", serializes = false, }, + RawRect2D = { + name = "RawRect2D", + type = {type = "Data", name = "Rect"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, RootLocalizationTable = { name = "RootLocalizationTable", type = {type = "Data", name = "Ref"}, @@ -5301,6 +5456,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + TotalGroupScale = { + name = "TotalGroupScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, }, defaults = { }, @@ -5413,7 +5577,6 @@ return { IgnoreGuiInset = false, Localize = true, Name = "GuiMain", - OnTopOfCoreBlur = false, ResetOnSpawn = true, RootLocalizationTable = nil, ZIndexBehavior = 0, @@ -5441,6 +5604,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + AutomaticSize = { + name = "AutomaticSize", + type = {type = "Enum", name = "AutomaticSize"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, BackgroundColor = { name = "BackgroundColor", type = {type = "Data", name = "BrickColor"}, @@ -5749,12 +5921,9 @@ return { }, defaults = { AutoSelectGuiEnabled = true, - CoreEffectFolder = nil, - CoreGuiFolder = nil, CoreGuiNavigationEnabled = true, GuiNavigationEnabled = true, Name = "GuiService", - SelectedCoreObject = nil, SelectedObject = nil, }, }, @@ -5770,6 +5939,15 @@ return { name = "HandleAdornment", superclass = "PVAdornment", properties = { + AdornCullingMode = { + name = "AdornCullingMode", + type = {type = "Enum", name = "AdornCullingMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, AlwaysOnTop = { name = "AlwaysOnTop", type = {type = "Data", name = "Bool"}, @@ -6180,6 +6358,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + DisplayName = { + name = "DisplayName", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, FloorMaterial = { name = "FloorMaterial", type = {type = "Enum", name = "Material"}, @@ -6315,6 +6502,15 @@ return { scriptability = "ReadWrite", serializes = false, }, + RequiresNeck = { + name = "RequiresNeck", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, RigType = { name = "RigType", type = {type = "Enum", name = "HumanoidRigType"}, @@ -6432,6 +6628,7 @@ return { CameraOffset = Vector3.new(0, 0, 0), CollisionType = 0, DisplayDistanceType = 0, + DisplayName = "", Health = 100, HealthDisplayDistance = 100, HealthDisplayType = 0, @@ -6446,6 +6643,7 @@ return { NameDisplayDistance = 100, NameOcclusion = 2, PlatformStand = false, + RequiresNeck = true, RigType = 0, RightLeg = nil, Sit = false, @@ -6838,7 +7036,6 @@ return { LeftLegColor = Color3.new(0, 0, 0), Name = "HumanoidDescription", NeckAccessory = "", - NumberEmotesLoaded = -1, Pants = 0, ProportionScale = 1, RightArm = 0, @@ -6856,6 +7053,14 @@ return { WidthScale = 1, }, }, + ILegacyStudioBridge = { + name = "ILegacyStudioBridge", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, ImageButton = { name = "ImageButton", superclass = "GuiButton", @@ -6974,6 +7179,7 @@ return { AnchorPoint = Vector2.new(0, 0), AutoButtonColor = true, AutoLocalize = true, + AutomaticSize = 0, BackgroundColor = BrickColor.new(194), BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), BackgroundTransparency = 0, @@ -7040,6 +7246,7 @@ return { }, }, defaults = { + AdornCullingMode = 0, Adornee = nil, AlwaysOnTop = false, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), @@ -7153,6 +7360,7 @@ return { Active = false, AnchorPoint = Vector2.new(0, 0), AutoLocalize = true, + AutomaticSize = 0, BackgroundColor = BrickColor.new(194), BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), BackgroundTransparency = 0, @@ -7329,6 +7537,15 @@ return { scriptability = "ReadWrite", serializes = false, }, + SourceAssetId = { + name = "SourceAssetId", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, Tags = { name = "Tags", type = {type = "Data", name = "BinaryString"}, @@ -7360,6 +7577,23 @@ return { defaults = { }, }, + InstanceAdornment = { + name = "InstanceAdornment", + superclass = "GuiBase3d", + properties = { + Adornee = { + name = "Adornee", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + }, + }, IntConstrainedValue = { name = "IntConstrainedValue", superclass = "ValueBase", @@ -7428,6 +7662,14 @@ return { Value = 0, }, }, + InternalContainer = { + name = "InternalContainer", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, InventoryPages = { name = "InventoryPages", superclass = "Pages", @@ -7467,6 +7709,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, Part0 = { name = "Part0", type = {type = "Data", name = "Ref"}, @@ -7602,6 +7853,15 @@ return { Name = "Instance", }, }, + LanguageService = { + name = "LanguageService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "LanguageService", + }, + }, LayerCollector = { name = "LayerCollector", superclass = "GuiBase2d", @@ -7637,6 +7897,14 @@ return { defaults = { }, }, + LegacyStudioBridge = { + name = "LegacyStudioBridge", + superclass = "ILegacyStudioBridge", + properties = { + }, + defaults = { + }, + }, Light = { name = "Light", superclass = "Instance", @@ -7730,6 +7998,24 @@ return { scriptability = "ReadWrite", serializes = true, }, + EnvironmentDiffuseScale = { + name = "EnvironmentDiffuseScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + EnvironmentSpecularScale = { + name = "EnvironmentSpecularScale", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, ExposureCompensation = { name = "ExposureCompensation", type = {type = "Data", name = "Float32"}, @@ -7784,15 +8070,6 @@ return { scriptability = "ReadWrite", serializes = true, }, - LegacyOutlines = { - name = "LegacyOutlines", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, OutdoorAmbient = { name = "OutdoorAmbient", type = {type = "Data", name = "Color3"}, @@ -7854,6 +8131,8 @@ return { ClockTime = 14, ColorShift_Bottom = Color3.new(0, 0, 0), ColorShift_Top = Color3.new(0, 0, 0), + EnvironmentDiffuseScale = 0, + EnvironmentSpecularScale = 0, ExposureCompensation = 0, FogColor = Color3.new(0.75, 0.75, 0.75), FogEnd = 100000, @@ -7956,6 +8235,7 @@ return { }, }, defaults = { + AdornCullingMode = 0, Adornee = nil, AlwaysOnTop = false, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), @@ -8059,10 +8339,7 @@ return { }, }, defaults = { - IsTextScraperRunning = false, Name = "LocalizationService", - RobloxForcePlayModeGameLocaleId = "", - RobloxForcePlayModeRobloxLocaleId = "en-us", }, }, LocalizationTable = { @@ -8134,69 +8411,6 @@ return { name = "LuaSettings", superclass = "Instance", properties = { - AreScriptStartsReported = { - name = "AreScriptStartsReported", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DefaultWaitTime = { - name = "DefaultWaitTime", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GcFrequency = { - name = "GcFrequency", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GcLimit = { - name = "GcLimit", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GcPause = { - name = "GcPause", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GcStepMul = { - name = "GcStepMul", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WaitingThreadsBudget = { - name = "WaitingThreadsBudget", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, }, defaults = { }, @@ -8214,6 +8428,15 @@ return { scriptability = "None", serializes = false, }, + IsDifferentFromFileSystem = { + name = "IsDifferentFromFileSystem", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = false, + }, }, defaults = { }, @@ -8227,32 +8450,6 @@ return { Name = "Instance", }, }, - MDIInstance = { - name = "MDIInstance", - superclass = "Instance", - properties = { - FocusedDataModelSession = { - name = "FocusedDataModelSession", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - FocusedDataModelSessionId = { - name = "FocusedDataModelSessionId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, ManualGlue = { name = "ManualGlue", superclass = "ManualSurfaceJointInstance", @@ -8261,6 +8458,7 @@ return { defaults = { C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Enabled = true, Name = "ManualGlue", Part0 = nil, Part1 = nil, @@ -8282,6 +8480,7 @@ return { defaults = { C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Enabled = true, Name = "ManualWeld", Part0 = nil, Part1 = nil, @@ -8326,6 +8525,42 @@ return { name = "MeshPart", superclass = "TriangleMeshPart", properties = { + DoubleSided = { + name = "DoubleSided", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HasJointOffset = { + name = "HasJointOffset", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = true, + }, + HasSkinnedMesh = { + name = "HasSkinnedMesh", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = true, + }, + JointOffset = { + name = "JointOffset", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = true, + }, MeshID = { name = "MeshID", type = {type = "Data", name = "Content"}, @@ -8344,6 +8579,15 @@ return { scriptability = "Read", serializes = true, }, + MeshSize = { + name = "MeshSize", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, RenderFidelity = { name = "RenderFidelity", type = {type = "Enum", name = "RenderFidelity"}, @@ -8376,16 +8620,20 @@ return { CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, CastShadow = true, - CollisionFidelity = 0, + CollisionFidelity = 2, CollisionGroupId = 0, Color = Color3.new(0.6392157, 0.63529414, 0.64705884), CustomPhysicalProperties = nil, + DoubleSided = false, Elasticity = 0.5, Friction = 0.3, FrontParamA = -0.5, FrontParamB = 0.5, FrontSurface = 0, FrontSurfaceInput = 0, + HasJointOffset = false, + HasSkinnedMesh = false, + JointOffset = Vector3.new(0, 0, 0), LeftParamA = -0.5, LeftParamB = 0.5, LeftSurface = 0, @@ -8449,6 +8697,15 @@ return { name = "Model", superclass = "PVInstance", properties = { + LevelOfDetail = { + name = "LevelOfDetail", + type = {type = "Enum", name = "ModelLevelOfDetail"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, PrimaryPart = { name = "PrimaryPart", type = {type = "Data", name = "Ref"}, @@ -8460,6 +8717,7 @@ return { }, }, defaults = { + LevelOfDetail = 0, Name = "Model", PrimaryPart = nil, }, @@ -8530,6 +8788,7 @@ return { C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CurrentAngle = 0, DesiredAngle = 0, + Enabled = true, MaxVelocity = 0, Name = "Motor", Part0 = nil, @@ -8540,6 +8799,24 @@ return { name = "Motor6D", superclass = "Motor", properties = { + ChildName = { + name = "ChildName", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = false, + }, + ParentName = { + name = "ParentName", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = false, + }, Transform = { name = "Transform", type = {type = "Data", name = "CFrame"}, @@ -8555,6 +8832,7 @@ return { C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CurrentAngle = 0, DesiredAngle = 0, + Enabled = true, MaxVelocity = 0, Name = "Motor6D", Part0 = nil, @@ -8709,6 +8987,23 @@ return { Name = "Instance", }, }, + MultipleDocumentInterfaceInstance = { + name = "MultipleDocumentInterfaceInstance", + superclass = "Instance", + properties = { + FocusedDataModelSession = { + name = "FocusedDataModelSession", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, NegateOperation = { name = "NegateOperation", superclass = "PartOperation", @@ -8727,7 +9022,7 @@ return { CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = false, CastShadow = true, - CollisionFidelity = 0, + CollisionFidelity = 2, CollisionGroupId = 0, Color = Color3.new(1, 1, 1), CustomPhysicalProperties = nil, @@ -8758,6 +9053,7 @@ return { RotVelocity = Vector3.new(0, 0, 0), Rotation = Vector3.new(0, 0, 0), Size = Vector3.new(4, 1.2, 2), + SmoothingAngle = 0, TopParamA = -0.5, TopParamB = 0.5, TopSurface = 0, @@ -8771,15 +9067,6 @@ return { name = "NetworkClient", superclass = "NetworkPeer", properties = { - Ticket = { - name = "Ticket", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, }, defaults = { }, @@ -8812,15 +9099,6 @@ return { name = "NetworkServer", superclass = "NetworkPeer", properties = { - Port = { - name = "Port", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, }, defaults = { }, @@ -8829,60 +9107,6 @@ return { name = "NetworkSettings", superclass = "Instance", properties = { - ArePhysicsRejectionsReported = { - name = "ArePhysicsRejectionsReported", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ClientPhysicsSendRate = { - name = "ClientPhysicsSendRate", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DataGCRate = { - name = "DataGCRate", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DataMtuAdjust = { - name = "DataMtuAdjust", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DataSendPriority = { - name = "DataSendPriority", - type = {type = "Enum", name = "PacketPriority"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - DataSendRate = { - name = "DataSendRate", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, ExtraMemoryUsed = { name = "ExtraMemoryUsed", type = {type = "Data", name = "Int32"}, @@ -8901,8 +9125,26 @@ return { scriptability = "Read", serializes = false, }, - IncommingReplicationLag = { - name = "IncommingReplicationLag", + HttpProxyEnabled = { + name = "HttpProxyEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HttpProxyURL = { + name = "HttpProxyURL", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IncomingReplicationLag = { + name = "IncomingReplicationLag", type = {type = "Data", name = "Float64"}, isCanonical = true, canonicalName = nil, @@ -8910,96 +9152,6 @@ return { scriptability = "ReadWrite", serializes = true, }, - IsQueueErrorComputed = { - name = "IsQueueErrorComputed", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - NetworkOwnerRate = { - name = "NetworkOwnerRate", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PhysicsMtuAdjust = { - name = "PhysicsMtuAdjust", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PhysicsSendPriority = { - name = "PhysicsSendPriority", - type = {type = "Enum", name = "PacketPriority"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - PhysicsSendRate = { - name = "PhysicsSendRate", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PreferredClientPort = { - name = "PreferredClientPort", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PrintBits = { - name = "PrintBits", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PrintEvents = { - name = "PrintEvents", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PrintFilters = { - name = "PrintFilters", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PrintInstances = { - name = "PrintInstances", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, PrintJoinSizeBreakdown = { name = "PrintJoinSizeBreakdown", type = {type = "Data", name = "Bool"}, @@ -9018,24 +9170,6 @@ return { scriptability = "ReadWrite", serializes = true, }, - PrintProperties = { - name = "PrintProperties", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PrintSplitMessage = { - name = "PrintSplitMessage", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, PrintStreamInstanceQuota = { name = "PrintStreamInstanceQuota", type = {type = "Data", name = "Bool"}, @@ -9045,42 +9179,6 @@ return { scriptability = "ReadWrite", serializes = true, }, - PrintTouches = { - name = "PrintTouches", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ProxyEnabled = { - name = "ProxyEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ProxyURL = { - name = "ProxyURL", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ReceiveRate = { - name = "ReceiveRate", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, RenderStreamedRegions = { name = "RenderStreamedRegions", type = {type = "Data", name = "Bool"}, @@ -9099,15 +9197,6 @@ return { scriptability = "ReadWrite", serializes = true, }, - TouchSendRate = { - name = "TouchSendRate", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, TrackDataTypes = { name = "TrackDataTypes", type = {type = "Data", name = "Bool"}, @@ -9126,15 +9215,6 @@ return { scriptability = "ReadWrite", serializes = true, }, - UsePhysicsPacketCache = { - name = "UsePhysicsPacketCache", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, }, defaults = { }, @@ -9190,24 +9270,6 @@ return { name = "NotificationService", superclass = "Instance", properties = { - IsLuaBottomBarEnabled = { - name = "IsLuaBottomBarEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - IsLuaBottomBarWithText = { - name = "IsLuaBottomBarWithText", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, IsLuaChatEnabled = { name = "IsLuaChatEnabled", type = {type = "Data", name = "Bool"}, @@ -9226,15 +9288,6 @@ return { scriptability = "Read", serializes = false, }, - IsLuaHomeWithAvatarEnabled = { - name = "IsLuaHomeWithAvatarEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, SelectedTheme = { name = "SelectedTheme", type = {type = "Data", name = "String"}, @@ -9247,7 +9300,6 @@ return { }, defaults = { Name = "NotificationService", - SelectedTheme = "", }, }, NumberValue = { @@ -9296,6 +9348,14 @@ return { defaults = { }, }, + OutfitPages = { + name = "OutfitPages", + superclass = "Pages", + properties = { + }, + defaults = { + }, + }, PVAdornment = { name = "PVAdornment", superclass = "GuiBase3d", @@ -9462,17 +9522,6 @@ return { }, }, defaults = { - A = 1, - Adornee = nil, - B = 0, - C = 0, - Color = BrickColor.new(1), - Color3 = Color3.new(0.9490197, 0.95294124, 0.95294124), - Name = "ParabolaAdornment", - Range = 1, - Thickness = 1, - Transparency = 0, - Visible = true, }, }, Part = { @@ -9580,6 +9629,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + SmoothingAngle = { + name = "SmoothingAngle", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, TriangleCount = { name = "TriangleCount", type = {type = "Data", name = "Int32"}, @@ -9612,7 +9670,7 @@ return { CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, CastShadow = true, - CollisionFidelity = 0, + CollisionFidelity = 2, CollisionGroupId = 0, Color = Color3.new(1, 1, 1), CustomPhysicalProperties = nil, @@ -9643,6 +9701,7 @@ return { RotVelocity = Vector3.new(0, 0, 0), Rotation = Vector3.new(0, 0, 0), Size = Vector3.new(4, 1.2, 2), + SmoothingAngle = 0, TopParamA = -0.5, TopParamB = 0.5, TopSurface = 0, @@ -9906,12 +9965,13 @@ return { Name = "Instance", }, }, - PhysicsPacketCache = { - name = "PhysicsPacketCache", + PermissionsService = { + name = "PermissionsService", superclass = "Instance", properties = { }, defaults = { + Name = "PermissionsService", }, }, PhysicsService = { @@ -10044,6 +10104,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + AreTerrainReplicationRegionsShown = { + name = "AreTerrainReplicationRegionsShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, AreUnalignedPartsShown = { name = "AreUnalignedPartsShown", type = {type = "Data", name = "Bool"}, @@ -10071,6 +10140,24 @@ return { scriptability = "ReadWrite", serializes = true, }, + ForceCSGv2 = { + name = "ForceCSGv2", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + IsInterpolationThrottleShown = { + name = "IsInterpolationThrottleShown", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, IsReceiveAgeShown = { name = "IsReceiveAgeShown", type = {type = "Data", name = "Bool"}, @@ -10441,6 +10528,15 @@ return { scriptability = "ReadWrite", serializes = false, }, + PlatformName = { + name = "PlatformName", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, ReplicationFocus = { name = "ReplicationFocus", type = {type = "Data", name = "Ref"}, @@ -10535,6 +10631,32 @@ return { defaults = { }, }, + PlayerEmulatorService = { + name = "PlayerEmulatorService", + superclass = "Instance", + properties = { + PlayerEmulationEnabled = { + name = "PlayerEmulationEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + StudioEmulatedCountryRegionCode = { + name = "StudioEmulatedCountryRegionCode", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + }, + }, PlayerGui = { name = "PlayerGui", superclass = "BasePlayerGui", @@ -10745,8 +10867,8 @@ return { scriptability = "Read", serializes = false, }, - MDIInstance = { - name = "MDIInstance", + MultipleDocumentInterfaceInstance = { + name = "MultipleDocumentInterfaceInstance", type = {type = "Data", name = "Ref"}, isCanonical = true, canonicalName = nil, @@ -10836,12 +10958,17 @@ return { }, }, defaults = { - Checked = true, - DefaultShortcut = "", - Enabled = false, Name = "Instance", }, }, + PluginDebugService = { + name = "PluginDebugService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, PluginDragEvent = { name = "PluginDragEvent", superclass = "Instance", @@ -10920,6 +11047,14 @@ return { defaults = { }, }, + PluginManagerInterface = { + name = "PluginManagerInterface", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, PluginMenu = { name = "PluginMenu", superclass = "Instance", @@ -11033,6 +11168,24 @@ return { name = "PolicyService", superclass = "Instance", properties = { + IsLuobuServer = { + name = "IsLuobuServer", + type = {type = "Enum", name = "TriStateBoolean"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + LuobuWhitelisted = { + name = "LuobuWhitelisted", + type = {type = "Enum", name = "TriStateBoolean"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, }, defaults = { Name = "PolicyService", @@ -11140,6 +11293,164 @@ return { Visible = false, }, }, + ProximityPrompt = { + name = "ProximityPrompt", + superclass = "Instance", + properties = { + ActionText = { + name = "ActionText", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ClickablePrompt = { + name = "ClickablePrompt", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Exclusivity = { + name = "Exclusivity", + type = {type = "Enum", name = "ProximityPromptExclusivity"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + GamepadKeyCode = { + name = "GamepadKeyCode", + type = {type = "Enum", name = "KeyCode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + HoldDuration = { + name = "HoldDuration", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + KeyboardKeyCode = { + name = "KeyboardKeyCode", + type = {type = "Enum", name = "KeyCode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxActivationDistance = { + name = "MaxActivationDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ObjectText = { + name = "ObjectText", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RequiresLineOfSight = { + name = "RequiresLineOfSight", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Style = { + name = "Style", + type = {type = "Enum", name = "ProximityPromptStyle"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + UIOffset = { + name = "UIOffset", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + ActionText = "Interact", + ClickablePrompt = true, + Enabled = true, + Exclusivity = 0, + GamepadKeyCode = 1000, + HoldDuration = 0, + KeyboardKeyCode = 101, + MaxActivationDistance = 10, + Name = "ProximityPrompt", + ObjectText = "", + RequiresLineOfSight = true, + Style = 0, + UIOffset = Vector2.new(0, 0), + }, + }, + ProximityPromptService = { + name = "ProximityPromptService", + superclass = "Instance", + properties = { + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MaxPromptsVisible = { + name = "MaxPromptsVisible", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Enabled = true, + MaxPromptsVisible = 16, + Name = "ProximityPromptService", + }, + }, QWidgetPluginGui = { name = "QWidgetPluginGui", superclass = "PluginGui", @@ -11172,7 +11483,6 @@ return { properties = { }, defaults = { - Name = "RbxAnalyticsService", }, }, ReflectionMetadata = { @@ -11594,6 +11904,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + MeshPartDetailLevel = { + name = "MeshPartDetailLevel", + type = {type = "Enum", name = "MeshPartDetailLevel"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, QualityLevel = { name = "QualityLevel", type = {type = "Enum", name = "QualityLevel"}, @@ -11762,6 +12081,15 @@ return { Name = "ReplicatedFirst", }, }, + ReplicatedScriptService = { + name = "ReplicatedScriptService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "ReplicatedScriptService", + }, + }, ReplicatedStorage = { name = "ReplicatedStorage", superclass = "Instance", @@ -11838,7 +12166,6 @@ return { properties = { }, defaults = { - Name = "RobloxPluginGuiService", }, }, RobloxReplicatedStorage = { @@ -11847,7 +12174,6 @@ return { properties = { }, defaults = { - Name = "RobloxReplicatedStorage", }, }, RocketPropulsion = { @@ -12073,6 +12399,7 @@ return { defaults = { C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Enabled = true, Name = "Rotate", Part0 = nil, Part1 = nil, @@ -12087,6 +12414,7 @@ return { BaseAngle = 0, C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Enabled = true, Name = "RotateP", Part0 = nil, Part1 = nil, @@ -12101,6 +12429,7 @@ return { BaseAngle = 0, C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Enabled = true, Name = "RotateV", Part0 = nil, Part1 = nil, @@ -12145,7 +12474,6 @@ return { properties = { }, defaults = { - Name = "Instance", }, }, ScreenGui = { @@ -12187,7 +12515,6 @@ return { IgnoreGuiInset = false, Localize = true, Name = "ScreenGui", - OnTopOfCoreBlur = false, ResetOnSpawn = true, RootLocalizationTable = nil, ZIndexBehavior = 0, @@ -12289,6 +12616,15 @@ return { name = "ScrollingFrame", superclass = "GuiObject", properties = { + AbsoluteCanvasSize = { + name = "AbsoluteCanvasSize", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, AbsoluteWindowSize = { name = "AbsoluteWindowSize", type = {type = "Data", name = "Vector2"}, @@ -12298,6 +12634,15 @@ return { scriptability = "Read", serializes = false, }, + AutomaticCanvasSize = { + name = "AutomaticCanvasSize", + type = {type = "Enum", name = "AutomaticSize"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, BottomImage = { name = "BottomImage", type = {type = "Data", name = "Content"}, @@ -12334,6 +12679,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + HorizontalBarRect = { + name = "HorizontalBarRect", + type = {type = "Data", name = "Rect"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, HorizontalScrollBarInset = { name = "HorizontalScrollBarInset", type = {type = "Enum", name = "ScrollBarInset"}, @@ -12343,6 +12697,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + MaxCanvasPosition = { + name = "MaxCanvasPosition", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, MidImage = { name = "MidImage", type = {type = "Data", name = "Content"}, @@ -12406,6 +12769,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + VerticalBarRect = { + name = "VerticalBarRect", + type = {type = "Data", name = "Rect"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, VerticalScrollBarInset = { name = "VerticalScrollBarInset", type = {type = "Enum", name = "ScrollBarInset"}, @@ -12429,6 +12801,8 @@ return { Active = false, AnchorPoint = Vector2.new(0, 0), AutoLocalize = true, + AutomaticCanvasSize = 0, + AutomaticSize = 0, BackgroundColor = BrickColor.new(194), BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), BackgroundTransparency = 0, @@ -12551,6 +12925,15 @@ return { name = "Selection", superclass = "Instance", properties = { + ActiveInstance = { + name = "ActiveInstance", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, }, defaults = { Name = "Selection", @@ -12558,7 +12941,7 @@ return { }, SelectionBox = { name = "SelectionBox", - superclass = "PVAdornment", + superclass = "InstanceAdornment", properties = { LineThickness = { name = "LineThickness", @@ -12762,6 +13145,14 @@ return { defaults = { }, }, + SessionService = { + name = "SessionService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, Shirt = { name = "Shirt", superclass = "Clothing", @@ -13310,6 +13701,7 @@ return { defaults = { C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Enabled = true, Name = "Snap", Part0 = nil, Part1 = nil, @@ -13832,6 +14224,7 @@ return { }, }, defaults = { + AdornCullingMode = 0, Adornee = nil, AlwaysOnTop = false, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), @@ -14113,7 +14506,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "Read", serializes = true, }, AutoJumpEnabled = { @@ -14458,23 +14851,6 @@ return { DevTouchCameraMovementMode = 0, DevTouchMovementMode = 0, EnableMouseLockOption = true, - GameSettingsAssetIDFace = 0, - GameSettingsAssetIDHead = 0, - GameSettingsAssetIDLeftArm = 0, - GameSettingsAssetIDLeftLeg = 0, - GameSettingsAssetIDPants = 0, - GameSettingsAssetIDRightArm = 0, - GameSettingsAssetIDRightLeg = 0, - GameSettingsAssetIDShirt = 0, - GameSettingsAssetIDTeeShirt = 0, - GameSettingsAssetIDTorso = 0, - GameSettingsAvatar = 1, - GameSettingsR15Collision = 0, - GameSettingsScaleRangeBodyType = NumberRange.new(0, 1), - GameSettingsScaleRangeHead = NumberRange.new(0.95, 1), - GameSettingsScaleRangeHeight = NumberRange.new(0.9, 1.05), - GameSettingsScaleRangeProportion = NumberRange.new(0, 1), - GameSettingsScaleRangeWidth = NumberRange.new(0.7, 1), HealthDisplayDistance = 100, LoadCharacterAppearance = true, Name = "StarterPlayer", @@ -14636,6 +15012,15 @@ return { name = "Studio", superclass = "Instance", properties = { + CommandBarLocalState = { + name = "CommandBarLocalState", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, DefaultScriptFileDir = { name = "DefaultScriptFileDir", type = {type = "Unimplemented", name = "QDir"}, @@ -14672,6 +15057,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + LocalAssetsFolder = { + name = "LocalAssetsFolder", + type = {type = "Unimplemented", name = "QDir"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, LuaDebuggerEnabled = { name = "LuaDebuggerEnabled", type = {type = "Data", name = "Bool"}, @@ -14717,6 +15111,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + PluginDebuggingEnabled = { + name = "PluginDebuggingEnabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, PluginsDir = { name = "PluginsDir", type = {type = "Unimplemented", name = "QDir"}, @@ -14726,9 +15129,9 @@ return { scriptability = "ReadWrite", serializes = true, }, - RecentSavesDir = { - name = "RecentSavesDir", - type = {type = "Unimplemented", name = "QDir"}, + Rulers = { + name = "Rulers", + type = {type = "Data", name = "String"}, isCanonical = true, canonicalName = nil, serializedName = nil, @@ -14770,6 +15173,33 @@ return { name = "StudioData", superclass = "Instance", properties = { + EnableScriptCollabByDefaultOnLoad = { + name = "EnableScriptCollabByDefaultOnLoad", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + EnableScriptCollabOnLoad = { + name = "EnableScriptCollabOnLoad", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + EnableScriptCollabVersionHistoryOnLoad = { + name = "EnableScriptCollabVersionHistoryOnLoad", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, SrcPlaceId = { name = "SrcPlaceId", type = {type = "Data", name = "Int32"}, @@ -14805,6 +15235,33 @@ return { scriptability = "Read", serializes = false, }, + AlignDraggedObjects = { + name = "AlignDraggedObjects", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + DraggerSolveConstraints = { + name = "DraggerSolveConstraints", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + DrawConstraintsOnTop = { + name = "DrawConstraintsOnTop", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, GridSize = { name = "GridSize", type = {type = "Data", name = "Float32"}, @@ -14814,6 +15271,15 @@ return { scriptability = "Read", serializes = false, }, + HoverInstance = { + name = "HoverInstance", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, InstalledPluginData = { name = "InstalledPluginData", type = {type = "Data", name = "String"}, @@ -14832,6 +15298,24 @@ return { scriptability = "Read", serializes = false, }, + ShowActiveInstanceHighlight = { + name = "ShowActiveInstanceHighlight", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + ShowConstraintDetails = { + name = "ShowConstraintDetails", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, StudioLocaleId = { name = "StudioLocaleId", type = {type = "Data", name = "String"}, @@ -14894,6 +15378,69 @@ return { Spread = 1, }, }, + SurfaceAppearance = { + name = "SurfaceAppearance", + superclass = "Instance", + properties = { + AlphaMode = { + name = "AlphaMode", + type = {type = "Enum", name = "AlphaMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ColorMap = { + name = "ColorMap", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MetalnessMap = { + name = "MetalnessMap", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + NormalMap = { + name = "NormalMap", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + RoughnessMap = { + name = "RoughnessMap", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + TexturePack = { + name = "TexturePack", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "SurfaceAppearance", + }, + }, SurfaceGui = { name = "SurfaceGui", superclass = "LayerCollector", @@ -15152,6 +15699,15 @@ return { scriptability = "ReadWrite", serializes = false, }, + ChildOrder = { + name = "ChildOrder", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, Score = { name = "Score", type = {type = "Data", name = "Int32"}, @@ -15211,6 +15767,15 @@ return { name = "Terrain", superclass = "BasePart", properties = { + Decoration = { + name = "Decoration", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, IsSmooth = { name = "IsSmooth", type = {type = "Data", name = "Bool"}, @@ -15552,6 +16117,15 @@ return { scriptability = "ReadWrite", serializes = false, }, + RichText = { + name = "RichText", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, SelectionStart = { name = "SelectionStart", type = {type = "Data", name = "Int32"}, @@ -15728,6 +16302,7 @@ return { Active = true, AnchorPoint = Vector2.new(0, 0), AutoLocalize = true, + AutomaticSize = 0, BackgroundColor = BrickColor.new(194), BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), BackgroundTransparency = 0, @@ -15739,24 +16314,21 @@ return { ClipsDescendants = false, CursorPosition = 1, Draggable = false, - EnableRealtimeFilteringHints = false, Font = 0, FontSize = 0, LayoutOrder = 0, LineHeight = 1, Localize = true, - ManualFocusRelease = false, MultiLine = false, Name = "TextBox", NextSelectionDown = nil, NextSelectionLeft = nil, NextSelectionRight = nil, NextSelectionUp = nil, - OverlayNativeInput = false, PlaceholderColor3 = Color3.new(0.7, 0.7, 0.7), PlaceholderText = "", Position = UDim2.new(0, 0, 0, 0), - ReturnKeyType = 0, + RichText = false, RootLocalizationTable = nil, Rotation = 0, Selectable = true, @@ -15769,7 +16341,6 @@ return { TextColor = BrickColor.new(26), TextColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), TextEditable = true, - TextInputType = 0, TextScaled = false, TextSize = 8, TextStrokeColor3 = Color3.new(0, 0, 0), @@ -15825,6 +16396,15 @@ return { scriptability = "Read", serializes = false, }, + RichText = { + name = "RichText", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, Text = { name = "Text", type = {type = "Data", name = "String"}, @@ -15966,6 +16546,7 @@ return { AnchorPoint = Vector2.new(0, 0), AutoButtonColor = true, AutoLocalize = true, + AutomaticSize = 0, BackgroundColor = BrickColor.new(194), BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), BackgroundTransparency = 0, @@ -15987,6 +16568,7 @@ return { NextSelectionRight = nil, NextSelectionUp = nil, Position = UDim2.new(0, 0, 0, 0), + RichText = false, RootLocalizationTable = nil, Rotation = 0, Selectable = true, @@ -16061,6 +16643,15 @@ return { scriptability = "Read", serializes = false, }, + RichText = { + name = "RichText", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, Text = { name = "Text", type = {type = "Data", name = "String"}, @@ -16201,6 +16792,7 @@ return { Active = false, AnchorPoint = Vector2.new(0, 0), AutoLocalize = true, + AutomaticSize = 0, BackgroundColor = BrickColor.new(194), BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), BackgroundTransparency = 0, @@ -16221,6 +16813,7 @@ return { NextSelectionRight = nil, NextSelectionUp = nil, Position = UDim2.new(0, 0, 0, 0), + RichText = false, RootLocalizationTable = nil, Rotation = 0, Selectable = false, @@ -16496,6 +17089,14 @@ return { defaults = { }, }, + TracerService = { + name = "TracerService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, Trail = { name = "Trail", superclass = "Instance", @@ -16920,6 +17521,84 @@ return { defaults = { }, }, + UICorner = { + name = "UICorner", + superclass = "UIComponent", + properties = { + CornerRadius = { + name = "CornerRadius", + type = {type = "Data", name = "UDim"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + CornerRadius = UDim.new(0, 8), + Name = "UICorner", + }, + }, + UIGradient = { + name = "UIGradient", + superclass = "UIComponent", + properties = { + Color = { + name = "Color", + type = {type = "Data", name = "ColorSequence"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Offset = { + name = "Offset", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Rotation = { + name = "Rotation", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Transparency = { + name = "Transparency", + type = {type = "Data", name = "NumberSequence"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Color = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.new(1, 1, 1)), ColorSequenceKeypoint.new(1, Color3.new(1, 1, 1))}), + Enabled = true, + Name = "UIGradient", + Offset = Vector2.new(0, 0), + Rotation = 0, + Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 0, 0), NumberSequenceKeypoint.new(1, 0, 0)}), + }, + }, UIGridLayout = { name = "UIGridLayout", superclass = "UIGridStyleLayout", @@ -17044,39 +17723,6 @@ return { defaults = { }, }, - UIInlineLayout = { - name = "UIInlineLayout", - superclass = "UIGridStyleLayout", - properties = { - InlineAlignment = { - name = "InlineAlignment", - type = {type = "Enum", name = "InlineAlignment"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - InlinePadding = { - name = "InlinePadding", - type = {type = "Data", name = "UDim2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - FillDirection = 0, - HorizontalAlignment = 1, - InlineAlignment = 1, - InlinePadding = UDim2.new(0, 0, 0, 0), - Name = "UIInlineLayout", - SortOrder = 0, - VerticalAlignment = 1, - }, - }, UILayout = { name = "UILayout", superclass = "UIComponent", @@ -17417,7 +18063,7 @@ return { CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, CastShadow = true, - CollisionFidelity = 0, + CollisionFidelity = 2, CollisionGroupId = 0, Color = Color3.new(1, 1, 1), CustomPhysicalProperties = nil, @@ -17448,6 +18094,7 @@ return { RotVelocity = Vector3.new(0, 0, 0), Rotation = Vector3.new(0, 0, 0), Size = Vector3.new(4, 1.2, 2), + SmoothingAngle = 0, TopParamA = -0.5, TopParamB = 0.5, TopSurface = 0, @@ -17457,6 +18104,14 @@ return { Velocity = Vector3.new(0, 0, 0), }, }, + UnvalidatedAssetService = { + name = "UnvalidatedAssetService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, UserGameSettings = { name = "UserGameSettings", superclass = "Instance", @@ -17542,6 +18197,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + GraphicsQualityLevel = { + name = "GraphicsQualityLevel", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, HasEverUsedVR = { name = "HasEverUsedVR", type = {type = "Data", name = "Bool"}, @@ -18002,14 +18666,20 @@ return { }, }, defaults = { - GazeSelectionEnabled = true, - LegacyInputEventsEnabled = true, ModalEnabled = false, MouseBehavior = 0, MouseDeltaSensitivity = 1, MouseIconEnabled = true, Name = "Instance", - OverrideMouseIconBehavior = 0, + }, + }, + UserService = { + name = "UserService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "UserService", }, }, UserSettings = { @@ -18354,6 +19024,7 @@ return { C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CurrentAngle = 0, DesiredAngle = 0, + Enabled = true, Hole = nil, MaxVelocity = 0, Name = "VelocityMotor", @@ -18369,6 +19040,121 @@ return { defaults = { }, }, + VideoFrame = { + name = "VideoFrame", + superclass = "GuiObject", + properties = { + IsLoaded = { + name = "IsLoaded", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + Looped = { + name = "Looped", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Playing = { + name = "Playing", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Resolution = { + name = "Resolution", + type = {type = "Data", name = "Vector2"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TimeLength = { + name = "TimeLength", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + TimePosition = { + name = "TimePosition", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Video = { + name = "Video", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Volume = { + name = "Volume", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Active = false, + AnchorPoint = Vector2.new(0, 0), + AutoLocalize = true, + AutomaticSize = 0, + BackgroundColor = BrickColor.new(194), + BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), + BackgroundTransparency = 0, + BorderColor = BrickColor.new(26), + BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), + BorderMode = 0, + BorderSizePixel = 1, + ClipsDescendants = false, + Draggable = false, + LayoutOrder = 0, + Localize = true, + Looped = false, + Name = "VideoFrame", + NextSelectionDown = nil, + NextSelectionLeft = nil, + NextSelectionRight = nil, + NextSelectionUp = nil, + Playing = false, + Position = UDim2.new(0, 0, 0, 0), + RootLocalizationTable = nil, + Rotation = 0, + Selectable = false, + SelectionImageObject = nil, + Size = UDim2.new(0, 0, 0, 0), + SizeConstraint = 0, + TimePosition = 0, + Transparency = 0, + Video = "", + Visible = true, + Volume = 1, + ZIndex = 1, + }, + }, ViewportFrame = { name = "ViewportFrame", superclass = "GuiObject", @@ -18433,6 +19219,7 @@ return { Ambient = Color3.new(0.78431374, 0.78431374, 0.78431374), AnchorPoint = Vector2.new(0, 0), AutoLocalize = true, + AutomaticSize = 0, BackgroundColor = BrickColor.new(194), BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), BackgroundTransparency = 0, @@ -18481,7 +19268,6 @@ return { }, }, defaults = { - AdditionalLuaState = "", Name = "VirtualInputManager", }, }, @@ -18567,6 +19353,7 @@ return { defaults = { C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Enabled = true, Name = "Weld", Part0 = nil, Part1 = nil, @@ -18622,7 +19409,7 @@ return { }, Workspace = { name = "Workspace", - superclass = "Model", + superclass = "WorldRoot", properties = { AllowThirdPartySales = { name = "AllowThirdPartySales", @@ -18639,7 +19426,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "Custom", + scriptability = "None", serializes = true, }, CurrentCamera = { @@ -18687,6 +19474,33 @@ return { scriptability = "ReadWrite", serializes = true, }, + InterpolationThrottling = { + name = "InterpolationThrottling", + type = {type = "Enum", name = "InterpolationThrottlingMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + MeshPartHeads = { + name = "MeshPartHeads", + type = {type = "Enum", name = "MeshPartHeads"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + PhysicsSimulationRate = { + name = "PhysicsSimulationRate", + type = {type = "Enum", name = "PhysicsSimulationRate"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, StreamingEnabled = { name = "StreamingEnabled", type = {type = "Data", name = "Bool"}, @@ -18723,15 +19537,6 @@ return { scriptability = "None", serializes = true, }, - TemporaryLegacyPhysicsSolverOverride = { - name = "TemporaryLegacyPhysicsSolverOverride", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, Terrain = { name = "Terrain", type = {type = "Data", name = "Ref"}, @@ -18749,9 +19554,30 @@ return { FallenPartsDestroyHeight = -500, FilteringEnabled = false, Gravity = 196.2, + InterpolationThrottling = 0, + LevelOfDetail = 0, Name = "Workspace", PrimaryPart = nil, StreamingEnabled = false, }, }, + WorldModel = { + name = "WorldModel", + superclass = "WorldRoot", + properties = { + }, + defaults = { + LevelOfDetail = 0, + Name = "WorldModel", + PrimaryPart = nil, + }, + }, + WorldRoot = { + name = "WorldRoot", + superclass = "Model", + properties = { + }, + defaults = { + }, + }, } From 50f0a2bd2eb1bb7962b131ef08fa70b94f389225 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 29 Oct 2020 10:36:20 -0700 Subject: [PATCH 1068/1504] Update CLI dependencies --- Cargo.lock | 911 +++++++++++++++++++++++++++-------------------------- 1 file changed, 465 insertions(+), 446 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bdc90964..c6eb1462 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,16 +1,25 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] -name = "adler32" -version = "1.0.4" +name = "addr2line" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d2e7343e7fc9de883d1b0341e0b13970f764c14101234857d2ddafa1cb1cac2" +checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" [[package]] name = "aho-corasick" -version = "0.7.10" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8716408b8bc624ed7f65d223ddb9ac2d044c0547b6fa4b0d554f3a9540496ada" +checksum = "b476ce7103678b0c6d3d395dbbae31d48ff910bd28be979ba5d48c6351131d0d" dependencies = [ "memchr", ] @@ -21,14 +30,14 @@ version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "anyhow" -version = "1.0.27" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "013a6e0a2cbe3d20f9c60b65458f7a7f7a5e636c5d0f45a5a6aee5d4b1f01785" +checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c" [[package]] name = "arrayref" @@ -38,9 +47,9 @@ checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cff77d8686867eceff3105329d4698d96c2391c176d5d03adc90c7389162b5b8" +checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "atty" @@ -50,7 +59,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi", "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -61,32 +70,24 @@ checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" [[package]] name = "autocfg" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.46" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1e692897359247cc6bb902933361652380af0f1b7651ae5c5013407f30e109e" +checksum = "707b586e0e2f247cbde68cdd2c3ce69ea7b7be43e1c5b426e37c9319c4b9838e" dependencies = [ - "backtrace-sys", - "cfg-if", + "addr2line", + "cfg-if 1.0.0", "libc", + "miniz_oxide", + "object", "rustc-demangle", ] -[[package]] -name = "backtrace-sys" -version = "0.1.35" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8aba10a69c8e8d7622c5710229485ec32e9d55fdad160ea559c086fdcd118" -dependencies = [ - "cc", - "libc", -] - [[package]] name = "base64" version = "0.10.1" @@ -103,10 +104,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" [[package]] -name = "bincode" -version = "1.2.1" +name = "base64" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5753e2a71534719bf3f4e57006c3a4f0d2c672a4b676eec84161f763eca87dbf" +checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" + +[[package]] +name = "bincode" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f30d3a39baa26f9651f17b375061f3233dde33424a8b72b0dbe93a68a0bc896d" dependencies = [ "byteorder", "serde", @@ -152,9 +159,9 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2889e6d50f394968c8bf4240dc3f2a7eb4680844d27308f798229ac9d4725f41" +checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf" dependencies = [ "lazy_static", "memchr", @@ -164,9 +171,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.2.1" +version = "3.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12ae9db68ad7fac5fe51304d20f016c911539251075a214f8e663babefa35187" +checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" [[package]] name = "byte-tools" @@ -174,12 +181,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" -[[package]] -name = "bytecount" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b92204551573580e078dc80017f36a213eb77a0450e4ddd8cfa0f3f2d1f0178f" - [[package]] name = "byteorder" version = "1.3.4" @@ -197,19 +198,6 @@ dependencies = [ "iovec", ] -[[package]] -name = "cargo_metadata" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5d1b4d380e1bab994591a24c2bdd1b054f64b60bef483a8c598c7c345bc3bbe" -dependencies = [ - "error-chain", - "semver", - "serde", - "serde_derive", - "serde_json", -] - [[package]] name = "cast" version = "0.2.3" @@ -221,9 +209,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.50" +version = "1.0.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95e28fa049fda1c330bcf9d723be7663a899c4679724b34c81e9f5a326aab8cd" +checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d" [[package]] name = "cfg-if" @@ -232,10 +220,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" [[package]] -name = "clap" -version = "2.33.0" +name = "cfg-if" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "clap" +version = "2.33.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" dependencies = [ "ansi_term", "atty", @@ -262,7 +256,7 @@ dependencies = [ "atty", "lazy_static", "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -286,9 +280,15 @@ dependencies = [ "libc", "regex", "termios", - "winapi 0.3.8", + "winapi 0.3.9", ] +[[package]] +name = "const_fn" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce90df4c658c62f12d78f7508cf92f9173e5184a539c10bfe54a3107b3ffd0f2" + [[package]] name = "constant_time_eq" version = "0.1.5" @@ -341,18 +341,18 @@ checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" [[package]] name = "crc32fast" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" +checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] name = "criterion" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fc755679c12bda8e5523a71e4d654b6bf2e14bd838dfc48cde6559a05caf7d1" +checksum = "70daa7ceec6cf143990669a04c7df13391d55fb27bd4079d252fca774ba244d8" dependencies = [ "atty", "cast", @@ -367,6 +367,7 @@ dependencies = [ "rayon", "regex", "serde", + "serde_cbor", "serde_derive", "serde_json", "tinytemplate", @@ -375,9 +376,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a01e15e0ea58e8234f96146b1f91fa9d0e4dd7a38da93ff7a75d42c0b9d3a545" +checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d" dependencies = [ "cast", "itertools", @@ -385,34 +386,55 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cced8691919c02aac3cb0a1bc2e9b73d89e832bf9a06fc579d4e71b68a2da061" +checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87" dependencies = [ - "crossbeam-utils", + "crossbeam-utils 0.7.2", "maybe-uninit", ] +[[package]] +name = "crossbeam-channel" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-utils 0.8.0", +] + [[package]] name = "crossbeam-deque" version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" dependencies = [ - "crossbeam-epoch", - "crossbeam-utils", + "crossbeam-epoch 0.8.2", + "crossbeam-utils 0.7.2", "maybe-uninit", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +dependencies = [ + "cfg-if 1.0.0", + "crossbeam-epoch 0.9.0", + "crossbeam-utils 0.8.0", +] + [[package]] name = "crossbeam-epoch" version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ - "autocfg 1.0.0", - "cfg-if", - "crossbeam-utils", + "autocfg 1.0.1", + "cfg-if 0.1.10", + "crossbeam-utils 0.7.2", "lazy_static", "maybe-uninit", "memoffset", @@ -420,13 +442,28 @@ dependencies = [ ] [[package]] -name = "crossbeam-queue" -version = "0.2.1" +name = "crossbeam-epoch" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c695eeca1e7173472a32221542ae469b3e9aac3a4fc81f7696bcad82029493db" +checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f" dependencies = [ - "cfg-if", - "crossbeam-utils", + "cfg-if 1.0.0", + "const_fn", + "crossbeam-utils 0.8.0", + "lazy_static", + "memoffset", + "scopeguard", +] + +[[package]] +name = "crossbeam-queue" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" +dependencies = [ + "cfg-if 0.1.10", + "crossbeam-utils 0.7.2", + "maybe-uninit", ] [[package]] @@ -435,8 +472,20 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg 1.0.0", - "cfg-if", + "autocfg 1.0.1", + "cfg-if 0.1.10", + "lazy_static", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5" +dependencies = [ + "autocfg 1.0.1", + "cfg-if 1.0.0", + "const_fn", "lazy_static", ] @@ -464,11 +513,11 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.13" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47c5e5ac752e18207b12e16b10631ae5f7f68f8805f335f9b817ead83d9ffce1" +checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484" dependencies = [ - "quote 1.0.3", + "quote 1.0.7", "syn", ] @@ -493,20 +542,19 @@ version = "2.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "dirs-sys", ] [[package]] name = "dirs-sys" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afa0b23de8fd801745c471deffa6e12d248f962c9fd4b4c33787b055599bde7b" +checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a" dependencies = [ - "cfg-if", "libc", "redox_users", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -517,15 +565,15 @@ checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" [[package]] name = "dtoa" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4358a9e11b9a09cf52383b451b49a169e8d797b68aa02301ff586d70d9661ea3" +checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" [[package]] name = "either" -version = "1.5.3" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "encode_unicode" @@ -535,11 +583,11 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.22" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd8d03faa7fe0c1431609dfad7bbe827af30f82e1e2ae6f7ee4fca6bd764bc28" +checksum = "a51b8cf747471cb9499b6d59e59b0444f4c90eba8968c4e44874e92b5b64ace2" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] [[package]] @@ -557,19 +605,18 @@ dependencies = [ [[package]] name = "error-chain" -version = "0.12.2" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d371106cc88ffdfb1eabd7111e432da544f16f3e2d7bf1dfe8bf575f1df045cd" +checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc" dependencies = [ - "backtrace", "version_check", ] [[package]] name = "failure" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8529c2421efa3066a5cbd8063d2244603824daccb6936b079010bb2aa89464b" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" dependencies = [ "backtrace", "failure_derive", @@ -577,12 +624,12 @@ dependencies = [ [[package]] name = "failure_derive" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "030a733c8287d6213886dd487564ff5c8f6aae10278b3588ed177f9d18f8d231" +checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.9", - "quote 1.0.3", + "proc-macro2 1.0.24", + "quote 1.0.7", "syn", "synstructure", ] @@ -595,23 +642,23 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "filetime" -version = "0.2.8" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff6d4dab0aa0c8e6346d46052e93b13a16cf847b54ed357087c35011048cc7d" +checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "redox_syscall", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "flate2" -version = "1.0.14" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cfff41391129e0a856d6d822600b8d71179d46879e310417eb9c762eb178b42" +checksum = "da80be589a72651dcda34d8b35bcdc9b7254ad06325611074d9cc0fbb19f60ee" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "crc32fast", "libc", "miniz_oxide", @@ -619,9 +666,9 @@ dependencies = [ [[package]] name = "fnv" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fad85553e09a6f881f739c29f0b00b0f01357c743266d478b68951ce23285f3" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "foreign-types" @@ -640,9 +687,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "fs-err" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1a51f8b7158efbe531f7baa74e38e49fbc41239e5d66720bb37ed39c27c241a" +checksum = "bcd1163ae48bda72a20ae26d66a04d3094135cadab911cff418ae5e33f253431" [[package]] name = "fsevent" @@ -687,9 +734,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" -version = "0.1.29" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b980f2816d6ee8673b6517b52cb0e808a180efc92e5c19d02cdda79066703ef" +checksum = "4c7e4c2612746b0df8fed4ce0c69156021b704c9aefa360311c04e6e9e002eed" [[package]] name = "futures-cpupool" @@ -712,26 +759,26 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.14" +version = "0.1.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7abc8dd8451921606d809ba32e95b6111925cd2906060d2dcc29c070220503eb" +checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", - "wasi", + "wasi 0.9.0+wasi-snapshot-preview1", ] [[package]] -name = "glob" -version = "0.2.11" +name = "gimli" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" +checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" [[package]] name = "globset" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ad1da430bd7281dde2576f44c84cc3f0f7b475e7202cd503042dff01a8c8120" +checksum = "c152169ef1e421390738366d2f796655fec62621dabbd0fd476f905934061e4a" dependencies = [ "aho-corasick", "bstr", @@ -758,6 +805,18 @@ dependencies = [ "tokio-io", ] +[[package]] +name = "half" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" + +[[package]] +name = "hashbrown" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" + [[package]] name = "heck" version = "0.3.1" @@ -769,9 +828,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.1.8" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1010591b26bbfe835e9faeabeb11866061cc7dcebffd56ad7d0942d0e61aefd8" +checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" dependencies = [ "libc", ] @@ -887,18 +946,19 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.3.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "076f042c5b7b98f31d205f1249267e12a6518c1481e9dae9764af19b707d2292" +checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", + "hashbrown", ] [[package]] name = "inotify" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e40d6fd5d64e2082e0c796495c8ef5ad667a96d03e5aaa0becfd9d47bcbfb8" +checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" dependencies = [ "bitflags", "inotify-sys", @@ -941,30 +1001,30 @@ dependencies = [ [[package]] name = "itertools" -version = "0.8.2" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f56a2d0bc861f9165be4eb3442afd3c236d8a98afd426f65d92324ae1091a484" +checksum = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b" dependencies = [ "either", ] [[package]] name = "itoa" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8b7a7c0c47db5545ed3fef7468ee7bb5b74691498139e4b3f6a20685dc6dd8e" +checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] name = "jod-thread" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4022656272c3e564a7cdebcaaba6518d844b0d0c1836597196efb5bfeb98bb49" +checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] name = "js-sys" -version = "0.3.37" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a27d435371a2fa5b6d2b028a74bbdb1234f308da363226a2854ca3ff8ba7055" +checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" dependencies = [ "wasm-bindgen", ] @@ -987,56 +1047,55 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "lazycell" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.68" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" +checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" [[package]] name = "linked-hash-map" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" +checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" [[package]] name = "lock_api" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79b2de95ecb4691949fea4716ca53cdbcfccb2c612e19644a8bad05edcf9f47b" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" dependencies = [ "scopeguard", ] [[package]] name = "log" -version = "0.4.8" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7" +checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] [[package]] name = "lz4" -version = "1.23.1" +version = "1.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43c94a9f09a60017f373020cc93d4291db4cd92b0db64ff25927f27d09dc23d5" +checksum = "aac20ed6991e01bf6a2e68cc73df2b389707403662a8ba89f68511fb340f724c" dependencies = [ "libc", "lz4-sys", - "skeptic", ] [[package]] name = "lz4-sys" -version = "1.8.3" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20ab022822e9331c58d373acdd6b98085bace058ac6837b8266f213a2fccdafe" +checksum = "dca79aa95d8b3226213ad454d328369853be3a1382d89532a854f4d69640acae" dependencies = [ "cc", "libc", @@ -1068,24 +1127,24 @@ checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" [[package]] name = "memchr" -version = "2.3.3" +version = "2.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3728d817d99e5ac407411fa471ff9800a778d88a24685968b36824eaf4bee400" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" [[package]] name = "memoffset" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4fc2c02a7e374099d4ee95a193111f72d2110197fe200272371758f6c3643d8" +checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", ] [[package]] name = "memofs" version = "0.1.3" dependencies = [ - "crossbeam-channel", + "crossbeam-channel 0.4.4", "fs-err", "notify", "serde", @@ -1109,20 +1168,21 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.3.6" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa679ff6578b1cddee93d7e82e263b94a575e0bfced07284eb0c037c1d2416a5" +checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d" dependencies = [ - "adler32", + "adler", + "autocfg 1.0.1", ] [[package]] name = "mio" -version = "0.6.21" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302dec22bcf6bae6dfb69c647187f4b4d0fb6f535521f7bc022430ce8e12008f" +checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "fuchsia-zircon", "fuchsia-zircon-sys", "iovec", @@ -1149,9 +1209,9 @@ dependencies = [ [[package]] name = "mio-uds" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125" +checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" dependencies = [ "iovec", "libc", @@ -1190,13 +1250,13 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.33" +version = "0.2.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42550d9fb7b6684a6d404d9fa7250c2eb2646df731d1c06afc06dcee9e1bcf88" +checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1214,33 +1274,39 @@ dependencies = [ "mio", "mio-extras", "walkdir", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "num-traits" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", ] [[package]] name = "num_cpus" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46203554f085ff89c235cd12f7075f3233af9b11ed7c9e16dfe2560d03313ce6" +checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" dependencies = [ "hermit-abi", "libc", ] [[package]] -name = "oorandom" -version = "11.1.0" +name = "object" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebcec7c9c2a95cacc7cd0ecb89d8a8454eca13906f6deb55258ffff0adeb9405" +checksum = "37fd5004feb2ce328a52b0b3d01dbf4ffff72583493900ed15f22d4111c51693" + +[[package]] +name = "oorandom" +version = "11.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a170cebd8021a008ea92e4db85a72f80b35df514ec664b296fdcbb654eac0b2c" [[package]] name = "opaque-debug" @@ -1254,17 +1320,17 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "13117407ca9d0caf3a0e74f97b490a7e64c0ae3aa90a8b7085544d0c37b6f3ae" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] name = "openssl" -version = "0.10.28" +version = "0.10.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "973293749822d7dd6370d6da1e523b0d1db19f06c459134c658b2a4261378b52" +checksum = "8d575eff3665419f9b83678ff2815858ad9d11567e082f5ac1814baba4e2bcb4" dependencies = [ "bitflags", - "cfg-if", + "cfg-if 0.1.10", "foreign-types", "lazy_static", "libc", @@ -1279,11 +1345,11 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" -version = "0.9.54" +version = "0.9.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1024c0a59774200a555087a6da3f253a9095a5f344e353b212ac4c8b8e450986" +checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de" dependencies = [ - "autocfg 1.0.0", + "autocfg 1.0.1", "cc", "libc", "pkg-config", @@ -1296,7 +1362,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1316,20 +1382,20 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "cloudabi", "libc", "redox_syscall", "rustc_version", - "smallvec 0.6.13", - "winapi 0.3.8", + "smallvec", + "winapi 0.3.9", ] [[package]] name = "paste" -version = "0.1.9" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "092d791bf7847f70bbd49085489fba25fc2c193571752bff9e36e74e72403932" +checksum = "45ca20c77d80be666aef2b45486da86238fabe33e38306bd3118fe4af33fa880" dependencies = [ "paste-impl", "proc-macro-hack", @@ -1337,14 +1403,11 @@ dependencies = [ [[package]] name = "paste-impl" -version = "0.1.9" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "406c23fb4c45cc6f68a9bbabb8ec7bd6f8cfcbd17e9e8f72c2460282f8325729" +checksum = "d95a7db200b97ef370c8e6de0088252f7e0dfff7d047a28528e47456c0fc98b6" dependencies = [ "proc-macro-hack", - "proc-macro2 1.0.9", - "quote 1.0.3", - "syn", ] [[package]] @@ -1386,8 +1449,8 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.9", - "quote 1.0.3", + "proc-macro2 1.0.24", + "quote 1.0.7", "syn", ] @@ -1404,15 +1467,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.17" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" +checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" [[package]] name = "plotters" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e3bb8da247d27ae212529352020f3e5ee16e83c0c258061d27b08ab92675eeb" +checksum = "0d1685fbe7beba33de0330629da9d955ac75bd54f33d7b79f9a895590124f6bb" dependencies = [ "js-sys", "num-traits", @@ -1422,9 +1485,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.6" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74490b50b9fbe561ac330df47c08f3f33073d2d00c150f719147d7c54522fa1b" +checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" [[package]] name = "pretty_assertions" @@ -1440,41 +1503,39 @@ dependencies = [ [[package]] name = "proc-macro-error" -version = "0.4.12" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18f33027081eba0a6d8aba6d1b1c3a3be58cbb12106341c2d5759fcd9b5277e7" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.9", - "quote 1.0.3", + "proc-macro2 1.0.24", + "quote 1.0.7", "syn", "version_check", ] [[package]] name = "proc-macro-error-attr" -version = "0.4.12" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a5b4b77fdb63c1eca72173d68d24501c54ab1269409f6b672c85deb18af69de" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.9", - "quote 1.0.3", - "syn", - "syn-mid", + "proc-macro2 1.0.24", + "quote 1.0.7", "version_check", ] [[package]] name = "proc-macro-hack" -version = "0.5.14" +version = "0.5.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcfdefadc3d57ca21cf17990a28ef4c0f7c61383a28cb7604cf4a18e6ede1420" +checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro-nested" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e946095f9d3ed29ec38de908c22f95d9ac008e424c7bcae54c75a79c527c694" +checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a" [[package]] name = "proc-macro2" @@ -1487,11 +1548,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.9" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c09721c6781493a2a492a96b5a5bf19b65917fe6728884e7c44dd0c60ca3435" +checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" dependencies = [ - "unicode-xid 0.2.0", + "unicode-xid 0.2.1", ] [[package]] @@ -1507,15 +1568,6 @@ dependencies = [ "url 2.1.1", ] -[[package]] -name = "pulldown-cmark" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eef52fac62d0ea7b9b4dc7da092aa64ea7ec3d90af6679422d3d7e0e14b6ee15" -dependencies = [ - "bitflags", -] - [[package]] name = "quick-error" version = "1.2.3" @@ -1533,24 +1585,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.3" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bdc6c187c65bca4260c9011c9e3132efe4909da44726bad24cf7572ae338d7f" +checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" dependencies = [ - "proc-macro2 1.0.9", -] - -[[package]] -name = "rand" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" -dependencies = [ - "fuchsia-cprng", - "libc", - "rand_core 0.3.1", - "rdrand", - "winapi 0.3.8", + "proc-macro2 1.0.24", ] [[package]] @@ -1569,7 +1608,7 @@ dependencies = [ "rand_os", "rand_pcg", "rand_xorshift", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1664,7 +1703,7 @@ checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" dependencies = [ "libc", "rand_core 0.4.2", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1678,7 +1717,7 @@ dependencies = [ "libc", "rand_core 0.4.2", "rdrand", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1702,24 +1741,25 @@ dependencies = [ [[package]] name = "rayon" -version = "1.3.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db6ce3297f9c85e16621bb8cca38a06779ffc31bb8184e1be4bed2be4678a098" +checksum = "8b0d8e0819fadc20c74ea8373106ead0600e3a67ef1fe8da56e39b9ae7275674" dependencies = [ - "crossbeam-deque", + "autocfg 1.0.1", + "crossbeam-deque 0.8.0", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08a89b46efaf957e52b18062fb2f4660f8b8a4dde1807ca002690868ef2c85a9" +checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" dependencies = [ - "crossbeam-deque", - "crossbeam-queue", - "crossbeam-utils", + "crossbeam-channel 0.5.0", + "crossbeam-deque 0.8.0", + "crossbeam-utils 0.8.0", "lazy_static", "num_cpus", ] @@ -1755,9 +1795,9 @@ dependencies = [ [[package]] name = "rbx_reflection" -version = "3.3.418" +version = "3.3.454" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c07c726f7d69ff7ba98a065f9b354edc90cfdaa9f7b973d5680920b972dc47" +checksum = "e9ccdde2a675eb13a8ecfe1f60879bf11ab29e9a671459d833929298873eedc4" dependencies = [ "bitflags", "lazy_static", @@ -1789,15 +1829,15 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.56" +version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_users" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09b23093265f8d200fa7b4c2c76297f47e681c655f6f1285a8780d6a022f7431" +checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" dependencies = [ "getrandom", "redox_syscall", @@ -1806,9 +1846,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.3.6" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f6946991529684867e47d86474e3a6d0c0ab9b82d5821e314b1ede31fa3a4b3" +checksum = "8963b85b8ce3074fecffde43b4b0dded83ce2f367dc8d363afc56679f3ee820b" dependencies = [ "aho-corasick", "memchr", @@ -1827,17 +1867,17 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.17" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fe5bd57d1d7414c6b5ed48563a2c855d995ff777729dcd91c369ec7fea395ae" +checksum = "8cab7a364d15cde1e505267766a2d3c4e22a843e1a601f0fa7564c0f82ced11c" [[package]] name = "remove_dir_all" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e" +checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -1929,7 +1969,7 @@ dependencies = [ "backtrace", "bincode", "criterion", - "crossbeam-channel", + "crossbeam-channel 0.4.4", "csv", "env_logger", "fs-err", @@ -1980,21 +2020,21 @@ dependencies = [ [[package]] name = "rust-argon2" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bc8af4bda8e1ff4932523b94d3dd20ee30a87232323eda55903ffd71d2fb017" +checksum = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19" dependencies = [ - "base64 0.11.0", + "base64 0.12.3", "blake2b_simd", "constant_time_eq", - "crossbeam-utils", + "crossbeam-utils 0.7.2", ] [[package]] name = "rustc-demangle" -version = "0.1.16" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c691c0e608126e00913e33f0ccf3727d5fc84573623b8d65b2df340b5201783" +checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" [[package]] name = "rustc_version" @@ -2007,9 +2047,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "535622e6be132bccd223f4bb2b8ac8d53cda3c7a6394944d3b2b33fb974f9d76" +checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" [[package]] name = "same-file" @@ -2022,12 +2062,12 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039c25b130bd8c1321ee2d7de7fde2659fa9c2744e4bb29711cfc852ea53cd19" +checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" dependencies = [ "lazy_static", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2038,21 +2078,22 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "security-framework" -version = "0.4.1" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97bbedbe81904398b6ebb054b3e912f99d55807125790f3198ac990d98def5b0" +checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" dependencies = [ "bitflags", "core-foundation", "core-foundation-sys", + "libc", "security-framework-sys", ] [[package]] name = "security-framework-sys" -version = "0.4.1" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06fd2f23e31ef68dd2328cc383bd493142e46107a3a0e24f7d734e3f3b80fe4c" +checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" dependencies = [ "core-foundation-sys", "libc", @@ -2065,7 +2106,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" dependencies = [ "semver-parser", - "serde", ] [[package]] @@ -2076,29 +2116,39 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.105" +version = "1.0.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e707fbbf255b8fc8c3b99abb91e7257a622caeb20a9818cbadbeeede4e0932ff" +checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a" dependencies = [ "serde_derive", ] [[package]] -name = "serde_derive" -version = "1.0.105" +name = "serde_cbor" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5d00fc561ba2724df6758a17de23df5914f20e41cb00f94d5b7ae42fffaff8" +checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" dependencies = [ - "proc-macro2 1.0.9", - "quote 1.0.3", + "half", + "serde", +] + +[[package]] +name = "serde_derive" +version = "1.0.117" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" +dependencies = [ + "proc-macro2 1.0.24", + "quote 1.0.7", "syn", ] [[package]] name = "serde_json" -version = "1.0.50" +version = "1.0.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78a7a12c167809363ec3bd7329fc0a3369056996de43c4b37ef3cd54a6ce4867" +checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95" dependencies = [ "itoa", "ryu", @@ -2107,12 +2157,12 @@ dependencies = [ [[package]] name = "serde_repr" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd02c7587ec314570041b2754829f84d873ced14a96d1fd1823531e11db40573" +checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" dependencies = [ - "proc-macro2 1.0.9", - "quote 1.0.3", + "proc-macro2 1.0.24", + "quote 1.0.7", "syn", ] @@ -2130,9 +2180,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.8.11" +version = "0.8.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "691b17f19fc1ec9d94ec0b5864859290dff279dbd7b03f017afda54eb36c3c35" +checksum = "ae3e2dd40a7cdc18ca80db804b7f461a39bb721160a85c9a1fa30134bf3c02a5" dependencies = [ "dtoa", "linked-hash-map", @@ -2152,22 +2202,6 @@ dependencies = [ "opaque-debug", ] -[[package]] -name = "skeptic" -version = "0.13.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6fb8ed853fdc19ce09752d63f3a2e5b5158aeb261520cd75eb618bd60305165" -dependencies = [ - "bytecount", - "cargo_metadata", - "error-chain", - "glob", - "pulldown-cmark", - "serde_json", - "tempdir", - "walkdir", -] - [[package]] name = "slab" version = "0.4.2" @@ -2183,17 +2217,11 @@ dependencies = [ "maybe-uninit", ] -[[package]] -name = "smallvec" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c2fb2ec9bcd216a5b0d0ccf31ab17b5ed1d627960edff65bbe95d3ce221cefc" - [[package]] name = "snafu" -version = "0.6.3" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48492e4f51c6e679217e80c11290edfdedf3133e358f4f432a6296f4c820f95b" +checksum = "9c4e6046e4691afe918fd1b603fd6e515bcda5388a1092a9edbada307d159f09" dependencies = [ "doc-comment", "snafu-derive", @@ -2201,12 +2229,12 @@ dependencies = [ [[package]] name = "snafu-derive" -version = "0.6.3" +version = "0.6.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5d1c41856cbfa99befda5034c72539dd9d7dd6f3e61058bdb804ac40715bc2a" +checksum = "7073448732a89f2f3e6581989106067f403d378faeafb4a50812eb814170d3e5" dependencies = [ - "proc-macro2 1.0.9", - "quote 1.0.3", + "proc-macro2 1.0.24", + "quote 1.0.7", "syn", ] @@ -2236,9 +2264,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.12" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8faa2719539bbe9d77869bfb15d4ee769f99525e707931452c97b693b3f159d" +checksum = "126d630294ec449fae0b16f964e35bf3c74f940da9dca17ee9b905f7b3112eb8" dependencies = [ "clap", "lazy_static", @@ -2247,59 +2275,38 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.5" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f88b8e18c69496aad6f9ddf4630dd7d585bcaf765786cb415b9aec2fe5a0430" +checksum = "65e51c492f9e23a220534971ff5afc14037289de430e3c83f9daf6a1b6ae91e8" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.9", - "quote 1.0.3", + "proc-macro2 1.0.24", + "quote 1.0.7", "syn", ] [[package]] name = "syn" -version = "1.0.17" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0df0eb663f387145cab623dea85b09c2c5b4b0aef44e945d928e682fce71bb03" +checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac" dependencies = [ - "proc-macro2 1.0.9", - "quote 1.0.3", - "unicode-xid 0.2.0", -] - -[[package]] -name = "syn-mid" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7be3539f6c128a931cf19dcee741c1af532c7fd387baa739c03dd2e96479338a" -dependencies = [ - "proc-macro2 1.0.9", - "quote 1.0.3", - "syn", + "proc-macro2 1.0.24", + "quote 1.0.7", + "unicode-xid 0.2.1", ] [[package]] name = "synstructure" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67656ea1dc1b41b1451851562ea232ec2e5a80242139f7e679ceccfb5d61f545" +checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ - "proc-macro2 1.0.9", - "quote 1.0.3", + "proc-macro2 1.0.24", + "quote 1.0.7", "syn", - "unicode-xid 0.2.0", -] - -[[package]] -name = "tempdir" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15f2b5fb00ccdf689e0149d1b1b3c03fead81c2b37735d812fa8bddbbf41b6d8" -dependencies = [ - "rand 0.4.6", - "remove_dir_all", + "unicode-xid 0.2.1", ] [[package]] @@ -2308,12 +2315,12 @@ version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "libc", "rand 0.7.3", "redox_syscall", "remove_dir_all", - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2327,9 +2334,9 @@ dependencies = [ [[package]] name = "termios" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b620c5ea021d75a735c943269bb07d30c9b77d6ac6b236bc8b5c496ef05625" +checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" dependencies = [ "libc", ] @@ -2345,21 +2352,21 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.14" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0570dc61221295909abdb95c739f2e74325e14293b2026b0a7e195091ec54ae" +checksum = "318234ffa22e0920fe9a40d7b8369b5f649d490980cf7aadcf1eb91594869b42" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.14" +version = "1.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "227362df41d566be41a28f64401e07a043157c21c14b9785a0d8e256f940a8fd" +checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab" dependencies = [ - "proc-macro2 1.0.9", - "quote 1.0.3", + "proc-macro2 1.0.24", + "quote 1.0.7", "syn", ] @@ -2374,25 +2381,31 @@ dependencies = [ [[package]] name = "time" -version = "0.1.42" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", - "redox_syscall", - "winapi 0.3.8", + "wasi 0.10.0+wasi-snapshot-preview1", + "winapi 0.3.9", ] [[package]] name = "tinytemplate" -version = "1.0.3" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57a3c6667d3e65eb1bc3aed6fd14011c6cbc3a0665218ab7f5daf040b9ec371a" +checksum = "6d3dc76004a03cec1c5932bca4cdc2e39aaa798e3f82363dd94f9adf6098c12f" dependencies = [ "serde", "serde_json", ] +[[package]] +name = "tinyvec" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" + [[package]] name = "tokio" version = "0.1.22" @@ -2455,7 +2468,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" dependencies = [ - "crossbeam-utils", + "crossbeam-utils 0.7.2", "futures", ] @@ -2487,7 +2500,7 @@ version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" dependencies = [ - "crossbeam-utils", + "crossbeam-utils 0.7.2", "futures", "lazy_static", "log", @@ -2530,9 +2543,9 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" dependencies = [ - "crossbeam-deque", + "crossbeam-deque 0.7.3", "crossbeam-queue", - "crossbeam-utils", + "crossbeam-utils 0.7.2", "futures", "lazy_static", "log", @@ -2547,7 +2560,7 @@ version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" dependencies = [ - "crossbeam-utils", + "crossbeam-utils 0.7.2", "futures", "slab", "tokio-executor", @@ -2570,9 +2583,9 @@ dependencies = [ [[package]] name = "tokio-uds" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5076db410d6fdc6523df7595447629099a1fdc47b3d9f896220780fa48faf798" +checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" dependencies = [ "bytes", "futures", @@ -2588,9 +2601,9 @@ dependencies = [ [[package]] name = "try-lock" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e604eb7b43c06650e854be16a2a03155743d3752dd1c943f6829e26b7a36e382" +checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" [[package]] name = "try_from" @@ -2598,14 +2611,14 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", ] [[package]] name = "typenum" -version = "1.11.2" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2783fe2d6b8c1101136184eb41be8b1ad379e4657050b8aaff0c79ee7575f9" +checksum = "373c8a200f9e67a0c95e62a4f52fbf80c23b4381c05a17845531982fa99e6b33" [[package]] name = "ucd-trie" @@ -2633,11 +2646,11 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5479532badd04e128284890390c1e876ef7a993d0570b3597ae43dfa1d59afa4" +checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" dependencies = [ - "smallvec 1.2.0", + "tinyvec", ] [[package]] @@ -2648,9 +2661,9 @@ checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" [[package]] name = "unicode-width" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "caaa9d531767d1ff2150b9332433f32a24622147e5ebb1f26409d5da67afd479" +checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" [[package]] name = "unicode-xid" @@ -2660,9 +2673,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "826e7639553986605ec5979c7dd957c7895e93eabed50ab2ffa7f6128a75097c" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" [[package]] name = "url" @@ -2707,21 +2720,21 @@ dependencies = [ [[package]] name = "vcpkg" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fc439f2794e98976c88a2a2dafce96b930fe8010b0a256b3c2199a773933168" +checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" [[package]] name = "vec_map" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "078775d0255232fb988e6fccf26ddc9d1ac274299aaedcedce21c6f72cc533ce" +checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed" [[package]] name = "walkdir" @@ -2730,7 +2743,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "777182bc735b6424e1a57516d35ed72cb8019d85c8c9bf536dccb3445c1a2f7d" dependencies = [ "same-file", - "winapi 0.3.8", + "winapi 0.3.9", "winapi-util", ] @@ -2752,48 +2765,54 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] -name = "wasm-bindgen" -version = "0.2.60" +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cc57ce05287f8376e998cbddfb4c8cb43b84a7ec55cf4551d7c00eef317a47f" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "wasm-bindgen" +version = "0.2.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" dependencies = [ - "cfg-if", + "cfg-if 0.1.10", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.60" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d967d37bf6c16cca2973ca3af071d0a2523392e4a594548155d89a678f4237cd" +checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.9", - "quote 1.0.3", + "proc-macro2 1.0.24", + "quote 1.0.7", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.60" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd151b63e1ea881bb742cd20e1d6127cef28399558f3b5d415289bc41eee3a4" +checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" dependencies = [ - "quote 1.0.3", + "quote 1.0.7", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.60" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d68a5b36eef1be7868f668632863292e37739656a80fc4b9acec7b0bd35a4931" +checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" dependencies = [ - "proc-macro2 1.0.9", - "quote 1.0.3", + "proc-macro2 1.0.24", + "quote 1.0.7", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -2801,15 +2820,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.60" +version = "0.2.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "daf76fe7d25ac79748a37538b7daeed1c7a6867c92d3245c12c6222e4a20d639" +checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" [[package]] name = "web-sys" -version = "0.3.37" +version = "0.3.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d6f51648d8c56c366144378a33290049eafdd784071077f6fe37dae64c1c4cb" +checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" dependencies = [ "js-sys", "wasm-bindgen", @@ -2823,9 +2842,9 @@ checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" [[package]] name = "winapi" -version = "0.3.8" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ "winapi-i686-pc-windows-gnu", "winapi-x86_64-pc-windows-gnu", @@ -2845,11 +2864,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ccfbf554c6ad11084fb7517daca16cfdcaccbdadba4fc336f032a8b12c2ad80" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2864,7 +2883,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" dependencies = [ - "winapi 0.3.8", + "winapi 0.3.9", ] [[package]] @@ -2879,15 +2898,15 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.0" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "541b12c998c5b56aa2b4e6f18f03664eef9a4fd0a246a55594efae6cc2d964b5" +checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" [[package]] name = "yaml-rust" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65923dd1784f44da1d2c3dbbc5e822045628c590ba72123e1c73d3c230c4434d" +checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d" dependencies = [ "linked-hash-map", ] From f66860bdfe1b6a5f0174465c0a6c964b56e304cb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 11 Nov 2020 16:30:23 -0800 Subject: [PATCH 1069/1504] Break apart plugin reconciler (#332) * Start splitting apart reconciler, with tests * Reify children in reify * Baseline hydrate implementation * Remove debug print * Scaffold out diff implementation, just supporting name changes * invariant -> error in decodeValue * Flesh out diff and add getProperty * Clear out top-level reconciler interface, start updating code that touches it * Address review feedback * Add (experimental) Selene configuration * Add emptiness checks to PatchSet, remove unimplement invert method * Improve descendant destruction behavior in InstanceMap * Track instanceId on all reify errors * Base implementation of applyPatch, returning partial patches on failure * Change reify to accept InstanceMap and insert instances into it * Start testing applyPatch for removals * Add test for applyPatch adding instances successfully and not * Add , which is just error with formatting * Correctly use new diff and applyPatch APIs * Improve applyPatch logging and fix field name typo * Better debug output when reify fails * Print out unapplied patch in debug mode * Don't write properties if their values are not different. This was exposed trying to sync the Rojo plugin, which has a gigantic ModuleScript in it with the reflection database. This workaround was present in some form in many versions of Rojo, and I guess we still need it. This time, I actually documented why it's here so that I don't forget for the umpteenth time... * Add placeholder test that needs to happen still * Introduce easier plugin testing, write applyPatch properties test * Delete legacy get/setCanonicalProperty files * Fix trying to remove numbers instead of instances * Change applyPatch to return partial patches instead of binary success * Work towards being able to decode and apply refs * Add helpers for PatchSet assertions * Apply refs in reify, test all cases * Improve diagnostics when patches fail to apply * Stop logging when destroying untracked instances, it's ok * Remove read before setting property in applyPatch * Fix diff thinking all properties are changed --- .gitignore | 8 +- .luacheckrc | 2 +- foreman.toml | 1 + plugin/log/init.lua | 4 + ...tstrap.server.lua => run-tests.server.lua} | 0 plugin/src/InstanceMap.lua | 38 +- plugin/src/PatchSet.lua | 165 +++++++- plugin/src/Reconciler.lua | 389 ------------------ plugin/src/Reconciler/Error.lua | 37 ++ plugin/src/Reconciler/applyPatch.lua | 131 ++++++ plugin/src/Reconciler/applyPatch.spec.lua | 159 +++++++ plugin/src/Reconciler/decodeValue.lua | 35 ++ plugin/src/Reconciler/diff.lua | 148 +++++++ plugin/src/Reconciler/diff.spec.lua | 292 +++++++++++++ .../getProperty.lua} | 31 +- plugin/src/Reconciler/hydrate.lua | 50 +++ plugin/src/Reconciler/hydrate.spec.lua | 129 ++++++ plugin/src/Reconciler/init.lua | 34 ++ plugin/src/Reconciler/reify.lua | 152 +++++++ plugin/src/Reconciler/reify.spec.lua | 352 ++++++++++++++++ plugin/src/Reconciler/setProperty.lua | 48 +++ plugin/src/ServeSession.lua | 32 +- plugin/src/setCanonicalProperty.lua | 37 -- plugin/test | 4 + plugin/test-place.project.json | 2 +- selene.toml | 4 + 26 files changed, 1818 insertions(+), 466 deletions(-) rename plugin/{testBootstrap.server.lua => run-tests.server.lua} (100%) delete mode 100644 plugin/src/Reconciler.lua create mode 100644 plugin/src/Reconciler/Error.lua create mode 100644 plugin/src/Reconciler/applyPatch.lua create mode 100644 plugin/src/Reconciler/applyPatch.spec.lua create mode 100644 plugin/src/Reconciler/decodeValue.lua create mode 100644 plugin/src/Reconciler/diff.lua create mode 100644 plugin/src/Reconciler/diff.spec.lua rename plugin/src/{getCanonicalProperty.lua => Reconciler/getProperty.lua} (55%) create mode 100644 plugin/src/Reconciler/hydrate.lua create mode 100644 plugin/src/Reconciler/hydrate.spec.lua create mode 100644 plugin/src/Reconciler/init.lua create mode 100644 plugin/src/Reconciler/reify.lua create mode 100644 plugin/src/Reconciler/reify.spec.lua create mode 100644 plugin/src/Reconciler/setProperty.lua delete mode 100644 plugin/src/setCanonicalProperty.lua create mode 100644 plugin/test create mode 100644 selene.toml diff --git a/.gitignore b/.gitignore index 3b6e942e..b12513e1 100644 --- a/.gitignore +++ b/.gitignore @@ -10,9 +10,15 @@ /*.rbxl /*.rbxlx +# Test places for the Roblox Studio Plugin +/plugin/*.rbxlx + # Roblox Studio holds 'lock' files on places *.rbxl.lock *.rbxlx.lock # Snapshot files from the 'insta' Rust crate -**/*.snap.new \ No newline at end of file +**/*.snap.new + +# Selene generates a roblox.toml file that should not be checked in. +/roblox.toml \ No newline at end of file diff --git a/.luacheckrc b/.luacheckrc index b523c1b5..bb55667f 100644 --- a/.luacheckrc +++ b/.luacheckrc @@ -33,7 +33,7 @@ stds.plugin = { stds.testez = { read_globals = { "describe", - "it", "itFOCUS", "itSKIP", + "it", "itFOCUS", "itSKIP", "itFIXME", "FOCUS", "SKIP", "HACK_NO_XPCALL", "expect", } diff --git a/foreman.toml b/foreman.toml index fe2956e1..53464e41 100644 --- a/foreman.toml +++ b/foreman.toml @@ -1,2 +1,3 @@ [tools] rojo = { source = "rojo-rbx/rojo", version = "6.0.0-rc.1" } +run-in-roblox = { source = "rojo-rbx/run-in-roblox", version = "0.3.0" } diff --git a/plugin/log/init.lua b/plugin/log/init.lua index dae88594..97fa7e46 100644 --- a/plugin/log/init.lua +++ b/plugin/log/init.lua @@ -53,4 +53,8 @@ function Log.warn(template, ...) end end +function Log.error(template, ...) + error(Fmt.fmt(template, ...)) +end + return Log \ No newline at end of file diff --git a/plugin/testBootstrap.server.lua b/plugin/run-tests.server.lua similarity index 100% rename from plugin/testBootstrap.server.lua rename to plugin/run-tests.server.lua diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 68f8c219..fe2b3eac 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -33,6 +33,16 @@ function InstanceMap.new(onInstanceChanged) return setmetatable(self, InstanceMap) end +function InstanceMap:size() + local size = 0 + + for _ in pairs(self.fromIds) do + size = size + 1 + end + + return size +end + --[[ Disconnect all connections and release all instance references. ]] @@ -81,8 +91,6 @@ function InstanceMap:removeId(id) self:__disconnectSignals(instance) self.fromIds[id] = nil self.fromInstances[instance] = nil - else - Log.warn("Attempted to remove nonexistant ID {}", id) end end @@ -93,8 +101,6 @@ function InstanceMap:removeInstance(instance) if id ~= nil then self.fromInstances[instance] = nil self.fromIds[id] = nil - else - Log.warn("Attempted to remove nonexistant instance {}", instance) end end @@ -102,10 +108,14 @@ function InstanceMap:destroyInstance(instance) local id = self.fromInstances[instance] if id ~= nil then - self:destroyId(id) - else - Log.warn("Attempted to destroy untracked instance {}", instance) + self:removeId(id) end + + for _, descendantInstance in ipairs(instance:GetDescendants()) do + self:removeInstance(descendantInstance) + end + + instance:Destroy() end function InstanceMap:destroyId(id) @@ -113,21 +123,11 @@ function InstanceMap:destroyId(id) self:removeId(id) if instance ~= nil then - local descendantsToDestroy = {} - - for otherInstance in pairs(self.fromInstances) do - if otherInstance:IsDescendantOf(instance) then - table.insert(descendantsToDestroy, otherInstance) - end - end - - for _, otherInstance in ipairs(descendantsToDestroy) do - self:removeInstance(otherInstance) + for _, descendantInstance in ipairs(instance:GetDescendants()) do + self:removeInstance(descendantInstance) end instance:Destroy() - else - Log.warn("Attempted to destroy nonexistant ID {}", id) end end diff --git a/plugin/src/PatchSet.lua b/plugin/src/PatchSet.lua index 6d18b46d..d8fde747 100644 --- a/plugin/src/PatchSet.lua +++ b/plugin/src/PatchSet.lua @@ -16,10 +16,169 @@ PatchSet.validate = t.interface({ }) --[[ - Invert the given PatchSet using the given instance map. + Create a new, empty PatchSet. ]] -function PatchSet.invert(patchSet, instanceMap) - error("not yet implemented", 2) +function PatchSet.newEmpty() + return { + removed = {}, + added = {}, + updated = {}, + } +end + +--[[ + Tells whether the given PatchSet is empty. +]] +function PatchSet.isEmpty(patchSet) + return next(patchSet.removed) == nil and + next(patchSet.added) == nil and + next(patchSet.updated) == nil +end + +--[[ + Tells whether the given PatchSet has any remove operations. +]] +function PatchSet.hasRemoves(patchSet) + return next(patchSet.removed) ~= nil +end + +--[[ + Tells whether the given PatchSet has any add operations. +]] +function PatchSet.hasAdditions(patchSet) + return next(patchSet.added) ~= nil +end + +--[[ + Tells whether the given PatchSet has any update operations. +]] +function PatchSet.hasUpdates(patchSet) + return next(patchSet.updated) ~= nil +end + +--[[ + Merge multiple PatchSet objects into the given PatchSet. +]] +function PatchSet.assign(target, ...) + for i = 1, select("#", ...) do + local sourcePatch = select(i, ...) + + for _, removed in ipairs(sourcePatch.removed) do + table.insert(target.removed, removed) + end + + for id, added in pairs(sourcePatch.added) do + target.added[id] = added + end + + for _, update in ipairs(sourcePatch.updated) do + table.insert(target.updated, update) + end + end + + return target +end + +--[[ + Create a list of human-readable statements summarizing the contents of this + patch, intended to be displayed to users. +]] +function PatchSet.humanSummary(instanceMap, patchSet) + local statements = {} + + for _, idOrInstance in ipairs(patchSet.removed) do + local instance, id + + if type(idOrInstance) == "string" then + id = idOrInstance + instance = instanceMap.fromIds[id] + else + instance = idOrInstance + id = instanceMap.fromInstances[instance] + end + + if instance ~= nil then + table.insert(statements, string.format("- Delete instance %s", instance:GetFullName())) + else + table.insert(statements, string.format("- Delete instance with ID %s", id)) + end + end + + local additionsMentioned = {} + + local function addAllDescendents(virtualInstance) + additionsMentioned[virtualInstance.Id] = true + + for _, childId in ipairs(virtualInstance.Children) do + addAllDescendents(patchSet.added[childId]) + end + end + + for id, addition in pairs(patchSet.added) do + if additionsMentioned[id] then + continue + end + + local virtualInstance = addition + while true do + if virtualInstance.Parent == nil then + break + end + + local virtualParent = patchSet.added[virtualInstance.Parent] + if virtualParent == nil then + break + end + + virtualInstance = virtualParent + end + + local parentDisplayName = "nil (how strange!)" + if virtualInstance.Parent ~= nil then + local parent = instanceMap.fromIds[virtualInstance.Parent] + if parent ~= nil then + parentDisplayName = parent:GetFullName() + end + end + + table.insert(statements, string.format( + "- Add instance %q (ClassName %q) to %s", + virtualInstance.Name, virtualInstance.ClassName, parentDisplayName)) + end + + for _, update in ipairs(patchSet.updated) do + local updatedProperties = {} + + if update.changedMetadata ~= nil then + table.insert(updatedProperties, "Rojo's Metadata") + end + + if update.changedName ~= nil then + table.insert(updatedProperties, "Name") + end + + if update.changedClassName ~= nil then + table.insert(updatedProperties, "ClassName") + end + + for name in pairs(update.changedProperties) do + table.insert(updatedProperties, name) + end + + local instance = instanceMap.fromIds[update.id] + local displayName + if instance ~= nil then + displayName = instance:GetFullName() + else + displayName = "[unknown instance]" + end + + table.insert(statements, string.format( + "- Update properties on %s: %s", + displayName, table.concat(updatedProperties, ","))) + end + + return table.concat(statements, "\n") end return PatchSet \ No newline at end of file diff --git a/plugin/src/Reconciler.lua b/plugin/src/Reconciler.lua deleted file mode 100644 index ad395abf..00000000 --- a/plugin/src/Reconciler.lua +++ /dev/null @@ -1,389 +0,0 @@ ---[[ - This module defines the meat of the Rojo plugin and how it manages tracking - and mutating the Roblox DOM. -]] - -local RbxDom = require(script.Parent.Parent.RbxDom) -local t = require(script.Parent.Parent.t) - -local Types = require(script.Parent.Types) -local invariant = require(script.Parent.invariant) -local getCanonicalProperty = require(script.Parent.getCanonicalProperty) -local setCanonicalProperty = require(script.Parent.setCanonicalProperty) -local PatchSet = require(script.Parent.PatchSet) - ---[[ - Attempt to safely set the parent of an instance. - - This function will always succeed, even if the actual set failed. This is - important for some types like services that will throw even if their current - parent is already set to the requested parent. - - TODO: See if we can eliminate this by being more nuanced with property - assignment? -]] -local function safeSetParent(instance, newParent) - pcall(function() - instance.Parent = newParent - end) -end - ---[[ - Similar to setting Parent, some instances really don't like being renamed. - - TODO: Should we be throwing away these results or can we be more careful? -]] -local function safeSetName(instance, name) - pcall(function() - instance.Name = name - end) -end - -local Reconciler = {} -Reconciler.__index = Reconciler - -function Reconciler.new(instanceMap) - local self = { - -- Tracks all of the instances known by the reconciler by ID. - __instanceMap = instanceMap, - } - - return setmetatable(self, Reconciler) -end - ---[[ - See Reconciler:__hydrateInternal(). -]] -function Reconciler:hydrate(apiInstances, id, instance) - local hydratePatch = { - removed = {}, - added = {}, - updated = {}, - } - - self:__hydrateInternal(apiInstances, id, instance, hydratePatch) - - return hydratePatch -end - ---[[ - Applies a patch to the Roblox DOM using the reconciler's internal state. - - TODO: This function might only apply some of the patch in the future and - require content negotiation with the Rojo server to handle types that aren't - editable by scripts. -]] -local applyPatchSchema = Types.ifEnabled(t.tuple( - PatchSet.validate -)) -function Reconciler:applyPatch(patch) - assert(applyPatchSchema(patch)) - - for _, removedIdOrInstance in ipairs(patch.removed) do - local removedInstance - - if Types.RbxId(removedIdOrInstance) then - -- If this value is an ID, it's assumed to be an instance that the - -- Rojo server knows about. - removedInstance = self.__instanceMap.fromIds[removedIdOrInstance] - self.__instanceMap:removeId(removedIdOrInstance) - end - - -- If this entry was an ID that we didn't know about, removedInstance - -- will be nil, which we guard against in case of minor tree desync. - if removedInstance ~= nil then - -- Ensure that if any descendants are tracked by Rojo, that we - -- properly un-track them. - for _, descendantInstance in ipairs(removedInstance:GetDescendants()) do - self.__instanceMap:removeInstance(descendantInstance) - end - - removedInstance:Destroy() - end - end - - -- TODO: This loop assumes that apiInstance.ParentId is never nil. The Rojo - -- plugin can't create a new top-level DataModel anyways, so this should - -- only be violated in cases that are already erroneous. - for id, apiInstance in pairs(patch.added) do - if self.__instanceMap.fromIds[id] == nil then - -- Find the first ancestor of this instance that is marked for an - -- addition. - -- - -- This helps us make sure we only reify each instance once, and we - -- start from the top. - while patch.added[apiInstance.Parent] ~= nil do - id = apiInstance.Parent - apiInstance = patch.added[id] - end - - local parentInstance = self.__instanceMap.fromIds[apiInstance.Parent] - - if parentInstance == nil then - invariant( - "Cannot add an instance from a patch that has no parent.\nInstance {} with parent {}.\nState: {:#?}", - id, - apiInstance.Parent, - self.__instanceMap - ) - end - - self:__reifyInstance(patch.added, id, parentInstance) - end - end - - for _, update in ipairs(patch.updated) do - local instance = self.__instanceMap.fromIds[update.id] - - if instance == nil then - invariant( - "Cannot update an instance that does not exist in the reconciler's state.\nInstance {}\nState: {:#?}", - update.id, - self.__instanceMap - ) - end - - if update.changedClassName ~= nil then - error("TODO: Support changing class name by destroying + recreating instance.") - end - - if update.changedName ~= nil then - instance.Name = update.changedName - end - - if update.changedMetadata ~= nil then - print("TODO: Support changing metadata, if necessary.") - end - - if update.changedProperties ~= nil then - for propertyName, propertyValue in pairs(update.changedProperties) do - -- TODO: Gracefully handle this error instead? - assert(setCanonicalProperty(instance, propertyName, self:__decodeApiValue(propertyValue))) - end - end - end -end - ---[[ - Transforms a value into one that can be sent over the network back to the - Rojo server. - - This operation can fail, and so it returns bool, value. -]] -function Reconciler:encodeApiValue(value) - if typeof(value) == "string" then - return true, { - Type = "String", - Value = value, - } - end - - return false -end - ---[[ - Transforms a value encoded by rbx_dom_weak on the server side into a value - usable by Rojo's reconciler, potentially using RbxDom. -]] -function Reconciler:__decodeApiValue(apiValue) - assert(Types.ApiValue(apiValue)) - - -- Refs are represented as IDs in the same space that Rojo's protocol uses. - if apiValue.Type == "Ref" then - -- TODO: This ref could be pointing at an instance we haven't created - -- yet! - - return self.__instanceMap.fromIds[apiValue.Value] - end - - local success, decodedValue = RbxDom.EncodedValue.decode(apiValue) - - if not success then - error(decodedValue, 2) - end - - return decodedValue -end - ---[[ - Constructs an instance from an ApiInstance without any of its children. -]] -local reifySingleInstanceSchema = Types.ifEnabled(t.tuple( - Types.ApiInstance -)) -function Reconciler:__reifySingleInstance(apiInstance) - assert(reifySingleInstanceSchema(apiInstance)) - - -- Instance.new can fail if we're passing in something that can't be - -- created, like a service, something enabled with a feature flag, or - -- something that requires higher security than we have. - local ok, instance = pcall(Instance.new, apiInstance.ClassName) - if not ok then - return false, instance - end - - -- TODO: When can setting Name fail here? - safeSetName(instance, apiInstance.Name) - - for key, value in pairs(apiInstance.Properties) do - setCanonicalProperty(instance, key, self:__decodeApiValue(value)) - end - - return true, instance -end - ---[[ - Construct an instance and all of its descendants, parent it to the given - instance, and insert it into the reconciler's internal state. -]] -local reifyInstanceSchema = Types.ifEnabled(t.tuple( - t.map(Types.RbxId, Types.VirtualInstance), - Types.RbxId, - t.Instance -)) -function Reconciler:__reifyInstance(apiInstances, id, parentInstance) - assert(reifyInstanceSchema(apiInstances, id, parentInstance)) - - local apiInstance = apiInstances[id] - local ok, instance = self:__reifySingleInstance(apiInstance) - - -- TODO: Propagate this error upward to handle it elsewhere? - if not ok then - error(("Couldn't create an instance of type %q, a child of %s"):format( - apiInstance.ClassName, - parentInstance:GetFullName() - )) - end - - self.__instanceMap:insert(id, instance) - - for _, childId in ipairs(apiInstance.Children) do - self:__reifyInstance(apiInstances, childId, instance) - end - - safeSetParent(instance, parentInstance) - - return instance -end - ---[[ - Populates the reconciler's internal state, maps IDs to instances that the - Rojo plugin knows about, and generates a patch that would update the Roblox - tree to match Rojo's view of the tree. -]] -local hydrateSchema = Types.ifEnabled(t.tuple( - t.map(Types.RbxId, Types.VirtualInstance), - Types.RbxId, - t.Instance, - PatchSet.validate -)) -function Reconciler:__hydrateInternal(apiInstances, id, instance, hydratePatch) - assert(hydrateSchema(apiInstances, id, instance, hydratePatch)) - - self.__instanceMap:insert(id, instance) - - local apiInstance = apiInstances[id] - - local function markIdAdded(id) - local apiInstance = apiInstances[id] - hydratePatch.added[id] = apiInstance - - for _, childId in ipairs(apiInstance.Children) do - markIdAdded(childId) - end - end - - local changedName = nil - local changedProperties = {} - - if apiInstance.Name ~= instance.Name then - changedName = apiInstance.Name - end - - for propertyName, virtualValue in pairs(apiInstance.Properties) do - local success, existingValue = getCanonicalProperty(instance, propertyName) - - if success then - local decodedValue = self:__decodeApiValue(virtualValue) - - if existingValue ~= decodedValue then - changedProperties[propertyName] = virtualValue - end - end - end - - -- If any properties differed from the virtual instance we read, add it to - -- the hydrate patch so that we can catch up. - if changedName ~= nil or next(changedProperties) ~= nil then - table.insert(hydratePatch.updated, { - id = id, - changedName = changedName, - changedClassName = nil, - changedProperties = changedProperties, - changedMetadata = nil, - }) - end - - local existingChildren = instance:GetChildren() - - -- For each existing child, we'll track whether it's been paired with an - -- instance that the Rojo server knows about. - local isExistingChildVisited = {} - for i = 1, #existingChildren do - isExistingChildVisited[i] = false - end - - for _, childId in ipairs(apiInstance.Children) do - local apiChild = apiInstances[childId] - - local childInstance - - for childIndex, instance in ipairs(existingChildren) do - if not isExistingChildVisited[childIndex] then - -- We guard accessing Name and ClassName in order to avoid - -- tripping over children of DataModel that Rojo won't have - -- permissions to access at all. - local ok, name, className = pcall(function() - return instance.Name, instance.ClassName - end) - - -- This rule is very conservative and could be loosened in the - -- future, or more heuristics could be introduced. - if ok and name == apiChild.Name and className == apiChild.ClassName then - childInstance = instance - isExistingChildVisited[childIndex] = true - break - end - end - end - - if childInstance ~= nil then - -- We found an instance that matches the instance from the API, yay! - self:__hydrateInternal(apiInstances, childId, childInstance, hydratePatch) - else - markIdAdded(childId) - end - end - - -- Any unvisited children at this point aren't known by Rojo and we can - -- destroy them unless the user has explicitly asked us to preserve children - -- of this instance. - local shouldClearUnknown = self:__shouldClearUnknownChildren(apiInstance) - if shouldClearUnknown then - for childIndex, visited in ipairs(isExistingChildVisited) do - if not visited then - table.insert(hydratePatch.removed, existingChildren[childIndex]) - end - end - end -end - -function Reconciler:__shouldClearUnknownChildren(apiInstance) - if apiInstance.Metadata ~= nil then - return not apiInstance.Metadata.ignoreUnknownInstances - else - return true - end -end - -return Reconciler \ No newline at end of file diff --git a/plugin/src/Reconciler/Error.lua b/plugin/src/Reconciler/Error.lua new file mode 100644 index 00000000..5833420a --- /dev/null +++ b/plugin/src/Reconciler/Error.lua @@ -0,0 +1,37 @@ +--[[ + Defines the errors that can be returned by the reconciler. +]] + +local Fmt = require(script.Parent.Parent.Parent.Fmt) + +local Error = {} + +local function makeVariant(name) + Error[name] = setmetatable({}, { + __tostring = function() + return "Error." .. name + end, + }) +end + +makeVariant("CannotCreateInstance") +makeVariant("CannotDecodeValue") +makeVariant("LackingPropertyPermissions") +makeVariant("OtherPropertyError") +makeVariant("RefDidNotExist") +makeVariant("UnknownProperty") +makeVariant("UnreadableProperty") +makeVariant("UnwritableProperty") + +function Error.new(kind, details) + return setmetatable({ + kind = kind, + details = details, + }, Error) +end + +function Error:__tostring() + return Fmt.fmt("Error({}): {:#?}", self.kind, self.details) +end + +return Error \ No newline at end of file diff --git a/plugin/src/Reconciler/applyPatch.lua b/plugin/src/Reconciler/applyPatch.lua new file mode 100644 index 00000000..dafaa352 --- /dev/null +++ b/plugin/src/Reconciler/applyPatch.lua @@ -0,0 +1,131 @@ +--[[ + Apply a patch to the DOM. Returns any portions of the patch that weren't + possible to apply. + + Patches can come from the server or be generated by the client. +]] + +local Log = require(script.Parent.Parent.Parent.Log) + +local PatchSet = require(script.Parent.Parent.PatchSet) +local Types = require(script.Parent.Parent.Types) +local invariant = require(script.Parent.Parent.invariant) + +local decodeValue = require(script.Parent.decodeValue) +local getProperty = require(script.Parent.getProperty) +local reify = require(script.Parent.reify) +local setProperty = require(script.Parent.setProperty) + +local function applyPatch(instanceMap, patch) + -- Tracks any portions of the patch that could not be applied to the DOM. + local unappliedPatch = PatchSet.newEmpty() + + for _, removedIdOrInstance in ipairs(patch.removed) do + if Types.RbxId(removedIdOrInstance) then + instanceMap:destroyId(removedIdOrInstance) + else + instanceMap:destroyInstance(removedIdOrInstance) + end + end + + for id, virtualInstance in pairs(patch.added) do + if instanceMap.fromIds[id] ~= nil then + -- This instance already exists. We might've already added it in a + -- previous iteration of this loop, or maybe this patch was not + -- supposed to list this instance. + -- + -- It's probably fine, right? + continue + end + + -- Find the first ancestor of this instance that is marked for an + -- addition. + -- + -- This helps us make sure we only reify each instance once, and we + -- start from the top. + while patch.added[virtualInstance.Parent] ~= nil do + id = virtualInstance.Parent + virtualInstance = patch.added[id] + end + + local parentInstance = instanceMap.fromIds[virtualInstance.Parent] + + if parentInstance == nil then + -- This would be peculiar. If you create an instance with no + -- parent, were you supposed to create it at all? + invariant( + "Cannot add an instance from a patch that has no parent.\nInstance {} with parent {}.\nState: {:#?}", + id, + virtualInstance.Parent, + instanceMap + ) + end + + local failedToReify = reify(instanceMap, patch.added, id, parentInstance) + + if not PatchSet.isEmpty(failedToReify) then + Log.debug("Failed to reify as part of applying a patch: {}", failedToReify) + PatchSet.assign(unappliedPatch, failedToReify) + end + end + + for _, update in ipairs(patch.updated) do + local instance = instanceMap.fromIds[update.id] + + if instance == nil then + -- We can't update an instance that doesn't exist. + -- TODO: Should this be an invariant? + continue + end + + -- Track any part of this update that could not be applied. + local unappliedUpdate = { + id = update.id, + changedProperties = {}, + } + local partiallyApplied = false + + if update.changedClassName ~= nil then + -- TODO: Support changing class name by destroying + recreating. + unappliedUpdate.changedClassName = update.changedClassName + partiallyApplied = true + end + + if update.changedName ~= nil then + instance.Name = update.changedName + end + + if update.changedMetadata ~= nil then + -- TODO: Support changing metadata. This will become necessary when + -- Rojo persistently tracks metadata for each instance in order to + -- remove extra instances. + unappliedUpdate.changedMetadata = update.changedMetadata + partiallyApplied = true + end + + if update.changedProperties ~= nil then + for propertyName, propertyValue in pairs(update.changedProperties) do + local ok, decodedValue = decodeValue(propertyValue, instanceMap) + if not ok then + unappliedUpdate.changedProperties[propertyName] = propertyValue + partiallyApplied = true + continue + end + + local ok = setProperty(instance, propertyName, decodedValue) + if not ok then + unappliedUpdate.changedProperties[propertyName] = propertyValue + partiallyApplied = true + end + end + end + + if partiallyApplied then + table.insert(unappliedPatch.updated, unappliedUpdate) + end + end + + return unappliedPatch +end + +return applyPatch \ No newline at end of file diff --git a/plugin/src/Reconciler/applyPatch.spec.lua b/plugin/src/Reconciler/applyPatch.spec.lua new file mode 100644 index 00000000..5308079d --- /dev/null +++ b/plugin/src/Reconciler/applyPatch.spec.lua @@ -0,0 +1,159 @@ +return function() + local applyPatch = require(script.Parent.applyPatch) + + local InstanceMap = require(script.Parent.Parent.InstanceMap) + local PatchSet = require(script.Parent.Parent.PatchSet) + + local dummy = Instance.new("Folder") + local function wasDestroyed(instance) + -- If an instance was destroyed, its parent property is locked. + local ok = pcall(function() + local oldParent = instance.Parent + instance.Parent = dummy + instance.Parent = oldParent + end) + + return not ok + end + + it("should return an empty patch if given an empty patch", function() + local patch = applyPatch(InstanceMap.new(), PatchSet.newEmpty()) + assert(PatchSet.isEmpty(patch), "expected remaining patch to be empty") + end) + + it("should destroy instances listed for remove", function() + local root = Instance.new("Folder") + + local child = Instance.new("Folder") + child.Name = "Child" + child.Parent = root + + local instanceMap = InstanceMap.new() + instanceMap:insert("ROOT", root) + instanceMap:insert("CHILD", child) + + local patch = PatchSet.newEmpty() + table.insert(patch.removed, child) + + local unapplied = applyPatch(instanceMap, patch) + assert(PatchSet.isEmpty(unapplied), "expected remaining patch to be empty") + + assert(not wasDestroyed(root), "expected root to be left alone") + assert(wasDestroyed(child), "expected child to be destroyed") + + instanceMap:stop() + end) + + it("should destroy IDs listed for remove", function() + local root = Instance.new("Folder") + + local child = Instance.new("Folder") + child.Name = "Child" + child.Parent = root + + local instanceMap = InstanceMap.new() + instanceMap:insert("ROOT", root) + instanceMap:insert("CHILD", child) + + local patch = PatchSet.newEmpty() + table.insert(patch.removed, "CHILD") + + local unapplied = applyPatch(instanceMap, patch) + assert(PatchSet.isEmpty(unapplied), "expected remaining patch to be empty") + expect(instanceMap:size()).to.equal(1) + + assert(not wasDestroyed(root), "expected root to be left alone") + assert(wasDestroyed(child), "expected child to be destroyed") + + instanceMap:stop() + end) + + it("should add instances to the DOM", function() + -- Many of the details of this functionality are instead covered by + -- tests on reify, not here. + + local root = Instance.new("Folder") + + local instanceMap = InstanceMap.new() + instanceMap:insert("ROOT", root) + + local patch = PatchSet.newEmpty() + patch.added["CHILD"] = { + Id = "CHILD", + ClassName = "Model", + Name = "Child", + Parent = "ROOT", + Children = {"GRANDCHILD"}, + Properties = {}, + } + + patch.added["GRANDCHILD"] = { + Id = "GRANDCHILD", + ClassName = "Part", + Name = "Grandchild", + Parent = "CHILD", + Children = {}, + Properties = {}, + } + + local unapplied = applyPatch(instanceMap, patch) + assert(PatchSet.isEmpty(unapplied), "expected remaining patch to be empty") + expect(instanceMap:size()).to.equal(3) + + local child = root:FindFirstChild("Child") + expect(child).to.be.ok() + expect(child.ClassName).to.equal("Model") + expect(child).to.equal(instanceMap.fromIds["CHILD"]) + + local grandchild = child:FindFirstChild("Grandchild") + expect(grandchild).to.be.ok() + expect(grandchild.ClassName).to.equal("Part") + expect(grandchild).to.equal(instanceMap.fromIds["GRANDCHILD"]) + end) + + it("should return unapplied additions when instances cannot be created", function() + local root = Instance.new("Folder") + + local instanceMap = InstanceMap.new() + instanceMap:insert("ROOT", root) + + local patch = PatchSet.newEmpty() + patch.added["OOPSIE"] = { + Id = "OOPSIE", + -- Hopefully Roblox never makes an instance with this ClassName. + ClassName = "UH OH", + Name = "FUBAR", + Parent = "ROOT", + Children = {}, + Properties = {}, + } + + local unapplied = applyPatch(instanceMap, patch) + expect(unapplied.added["OOPSIE"]).to.equal(patch.added["OOPSIE"]) + expect(instanceMap:size()).to.equal(1) + expect(#root:GetChildren()).to.equal(0) + end) + + it("should apply property changes to instances", function() + local value = Instance.new("StringValue") + value.Value = "HELLO" + + local instanceMap = InstanceMap.new() + instanceMap:insert("VALUE", value) + + local patch = PatchSet.newEmpty() + table.insert(patch.updated, { + id = "VALUE", + changedProperties = { + Value = { + Type = "String", + Value = "WORLD", + }, + }, + }) + + local unapplied = applyPatch(instanceMap, patch) + assert(PatchSet.isEmpty(unapplied), "expected remaining patch to be empty") + expect(value.Value).to.equal("WORLD") + end) +end \ No newline at end of file diff --git a/plugin/src/Reconciler/decodeValue.lua b/plugin/src/Reconciler/decodeValue.lua new file mode 100644 index 00000000..3dfd321c --- /dev/null +++ b/plugin/src/Reconciler/decodeValue.lua @@ -0,0 +1,35 @@ +--[[ + Transforms a value encoded by rbx_dom_weak on the server side into a value + usable by Rojo's reconciler, potentially using RbxDom. +]] + +local RbxDom = require(script.Parent.Parent.Parent.RbxDom) +local Error = require(script.Parent.Error) + +local function decodeValue(virtualValue, instanceMap) + -- Refs are represented as IDs in the same space that Rojo's protocol uses. + if virtualValue.Type == "Ref" then + local instance = instanceMap.fromIds[virtualValue.Value] + + if instance ~= nil then + return true, instance + else + return false, Error.new(Error.RefDidNotExist, { + virtualValue = virtualValue, + }) + end + end + + local ok, decodedValue = RbxDom.EncodedValue.decode(virtualValue) + + if not ok then + return false, Error.new(Error.CannotDecodeValue, { + virtualValue = virtualValue, + innerError = decodedValue, + }) + end + + return true, decodedValue +end + +return decodeValue \ No newline at end of file diff --git a/plugin/src/Reconciler/diff.lua b/plugin/src/Reconciler/diff.lua new file mode 100644 index 00000000..67c8c161 --- /dev/null +++ b/plugin/src/Reconciler/diff.lua @@ -0,0 +1,148 @@ +--[[ + Defines the process for diffing a virtual DOM and the real DOM to compute a + patch that can be later applied. +]] + +local Log = require(script.Parent.Parent.Parent.Log) +local invariant = require(script.Parent.Parent.invariant) +local getProperty = require(script.Parent.getProperty) +local Error = require(script.Parent.Error) +local decodeValue = require(script.Parent.decodeValue) + +local function isEmpty(table) + return next(table) == nil +end + +local function shouldDeleteUnknownInstances(virtualInstance) + if virtualInstance.Metadata ~= nil then + return not virtualInstance.Metadata.ignoreUnknownInstances + else + return true + end +end + +local function diff(instanceMap, virtualInstances, rootId) + local patch = { + removed = {}, + added = {}, + updated = {}, + } + + -- Add a virtual instance and all of its descendants to the patch, marked as + -- being added. + local function markIdAdded(id) + local virtualInstance = virtualInstances[id] + patch.added[id] = virtualInstance + + for _, childId in ipairs(virtualInstance.Children) do + markIdAdded(childId) + end + end + + -- Internal recursive kernel for diffing an instance with the given ID. + local function diffInternal(id) + local virtualInstance = virtualInstances[id] + local instance = instanceMap.fromIds[id] + + if virtualInstance == nil then + invariant("Cannot diff an instance not present in virtualInstances\nID: {}", id) + end + + if instance == nil then + invariant("Cannot diff an instance not present in InstanceMap\nID: {}", id) + end + + if virtualInstance.ClassName ~= instance.ClassName then + error("unimplemented: support changing ClassName") + end + + local changedName = nil + if virtualInstance.Name ~= instance.Name then + changedName = virtualInstance.Name + end + + local changedProperties = {} + for propertyName, virtualValue in pairs(virtualInstance.Properties) do + local ok, existingValueOrErr = getProperty(instance, propertyName) + + if ok then + local existingValue = existingValueOrErr + local ok, decodedValue = decodeValue(virtualValue, instanceMap) + + if ok then + if existingValue ~= decodedValue then + changedProperties[propertyName] = virtualValue + end + else + Log.warn("Failed to decode property of type {}", virtualValue.Type) + end + else + local err = existingValueOrErr + + if err.kind == Error.UnknownProperty then + Log.trace("Skipping unknown property {}.{}", err.details.className, err.details.propertyName) + elseif err.kind == Error.UnreadableProperty then + Log.trace("Skipping unreadable property {}.{}", err.details.className, err.details.propertyName) + else + return false, err + end + end + end + + if changedName ~= nil or not isEmpty(changedProperties) then + table.insert(patch.updated, { + id = id, + changedName = changedName, + changedClassName = nil, + changedProperties = changedProperties, + changedMetadata = nil, + }) + end + + -- Traverse the list of children in the DOM. Any instance that has no + -- corresponding virtual instance should be removed. Any instance that + -- does have a corresponding virtual instance is recursively diffed. + for _, childInstance in ipairs(instance:GetChildren()) do + local childId = instanceMap.fromInstances[childInstance] + + if childId == nil then + -- This is an existing instance not present in the virtual DOM. + -- We can mark it for deletion unless the user has asked us not + -- to delete unknown stuff. + if shouldDeleteUnknownInstances(virtualInstance) then + table.insert(patch.removed, childInstance) + end + else + local ok, err = diffInternal(childId) + + if not ok then + return false, err + end + end + end + + -- Traverse the list of children in the virtual DOM. Any virtual + -- instance that has no corresponding real instance should be created. + for _, childId in ipairs(virtualInstance.Children) do + local childInstance = instanceMap.fromIds[childId] + + if childInstance == nil then + -- This instance is present in the virtual DOM, but doesn't + -- exist in the real DOM. + markIdAdded(childId) + end + end + + return true + end + + local ok, err = diffInternal(rootId) + + if not ok then + return false, err + end + + return true, patch +end + +return diff \ No newline at end of file diff --git a/plugin/src/Reconciler/diff.spec.lua b/plugin/src/Reconciler/diff.spec.lua new file mode 100644 index 00000000..47709554 --- /dev/null +++ b/plugin/src/Reconciler/diff.spec.lua @@ -0,0 +1,292 @@ +return function() + local Log = require(script.Parent.Parent.Parent.Log) + + local InstanceMap = require(script.Parent.Parent.InstanceMap) + local PatchSet = require(script.Parent.Parent.PatchSet) + + local diff = require(script.Parent.diff) + + local function isEmpty(table) + return next(table) == nil, "Table was not empty" + end + + local function size(dict) + local len = 0 + + for _ in pairs(dict) do + len = len + 1 + end + + return len + end + + it("should generate an empty patch for empty instances", function() + local knownInstances = InstanceMap.new() + local virtualInstances = { + ROOT = { + ClassName = "Folder", + Name = "Some Name", + Properties = {}, + Children = {}, + }, + } + + local rootInstance = Instance.new("Folder") + rootInstance.Name = "Some Name" + knownInstances:insert("ROOT", rootInstance) + + local ok, patch = diff(knownInstances, virtualInstances, "ROOT") + + assert(ok, tostring(patch)) + + assert(isEmpty(patch.removed)) + assert(isEmpty(patch.added)) + assert(isEmpty(patch.updated)) + end) + + it("should generate a patch with a changed name", function() + local knownInstances = InstanceMap.new() + local virtualInstances = { + ROOT = { + ClassName = "Folder", + Name = "Some Name", + Properties = {}, + Children = {}, + }, + } + + local rootInstance = Instance.new("Folder") + knownInstances:insert("ROOT", rootInstance) + + local ok, patch = diff(knownInstances, virtualInstances, "ROOT") + + assert(ok, tostring(patch)) + + assert(isEmpty(patch.removed)) + assert(isEmpty(patch.added)) + expect(#patch.updated).to.equal(1) + + local update = patch.updated[1] + expect(update.id).to.equal("ROOT") + expect(update.changedName).to.equal("Some Name") + assert(isEmpty(update.changedProperties)) + end) + + it("should generate a patch with a changed property", function() + local knownInstances = InstanceMap.new() + local virtualInstances = { + ROOT = { + ClassName = "StringValue", + Name = "Value", + Properties = { + Value = { + Type = "String", + Value = "Hello, world!", + }, + }, + Children = {}, + }, + } + + local rootInstance = Instance.new("StringValue") + rootInstance.Value = "Initial Value" + knownInstances:insert("ROOT", rootInstance) + + local ok, patch = diff(knownInstances, virtualInstances, "ROOT") + + assert(ok, tostring(patch)) + + assert(isEmpty(patch.removed)) + assert(isEmpty(patch.added)) + expect(#patch.updated).to.equal(1) + + local update = patch.updated[1] + expect(update.id).to.equal("ROOT") + expect(update.changedName).to.equal(nil) + expect(size(update.changedProperties)).to.equal(1) + + local patchProperty = update.changedProperties["Value"] + expect(patchProperty).to.be.a("table") + expect(patchProperty.Type).to.equal("String") + expect(patchProperty.Value).to.equal("Hello, world!") + end) + + it("should generate an empty patch if no properties changed", function() + local knownInstances = InstanceMap.new() + local virtualInstances = { + ROOT = { + ClassName = "StringValue", + Name = "Value", + Properties = { + Value = { + Type = "String", + Value = "Hello, world!", + }, + }, + Children = {}, + }, + } + + local rootInstance = Instance.new("StringValue") + rootInstance.Value = "Hello, world!" + knownInstances:insert("ROOT", rootInstance) + + local ok, patch = diff(knownInstances, virtualInstances, "ROOT") + + assert(ok, tostring(patch)) + assert(PatchSet.isEmpty(patch), "expected empty patch") + end) + + it("should ignore unknown properties", function() + local knownInstances = InstanceMap.new() + local virtualInstances = { + ROOT = { + ClassName = "Folder", + Name = "Folder", + Properties = { + FAKE_PROPERTY = { + Type = "String", + Value = "Hello, world!", + }, + }, + Children = {}, + }, + } + + local rootInstance = Instance.new("Folder") + knownInstances:insert("ROOT", rootInstance) + + local ok, patch = diff(knownInstances, virtualInstances, "ROOT") + + assert(ok, tostring(patch)) + + assert(isEmpty(patch.removed)) + assert(isEmpty(patch.added)) + assert(isEmpty(patch.updated)) + end) + + --[[ + Because rbx_dom_lua resolves non-canonical properties to their canonical + variants, this test does not work as intended. + + Instead, heat_xml is diffed with Heat, the canonical property variant, + and a patch trying to assign to heat_xml is generated. This is + incorrect, but will require more invasive changes to fix later. + ]] + itFIXME("should ignore unreadable properties", function() + local knownInstances = InstanceMap.new() + local virtualInstances = { + ROOT = { + ClassName = "Fire", + Name = "Fire", + Properties = { + -- heat_xml is a serialization-only property that is not + -- exposed to Lua. + heat_xml = { + Type = "Float32", + Value = 5, + }, + }, + Children = {}, + }, + } + + local rootInstance = Instance.new("Fire") + knownInstances:insert("ROOT", rootInstance) + + local ok, patch = diff(knownInstances, virtualInstances, "ROOT") + + Log.warn("{:#?}", patch) + + assert(ok, tostring(patch)) + + assert(isEmpty(patch.removed)) + assert(isEmpty(patch.added)) + assert(isEmpty(patch.updated)) + end) + + it("should generate a patch removing unknown children by default", function() + local knownInstances = InstanceMap.new() + local virtualInstances = { + ROOT = { + ClassName = "Folder", + Name = "Folder", + Properties = {}, + Children = {}, + }, + } + + local rootInstance = Instance.new("Folder") + local unknownChild = Instance.new("Folder") + unknownChild.Parent = rootInstance + knownInstances:insert("ROOT", rootInstance) + + local ok, patch = diff(knownInstances, virtualInstances, "ROOT") + + assert(ok, tostring(patch)) + + assert(isEmpty(patch.added)) + assert(isEmpty(patch.updated)) + expect(#patch.removed).to.equal(1) + expect(patch.removed[1]).to.equal(unknownChild) + end) + + it("should generate an empty patch if unknown children should be ignored", function() + local knownInstances = InstanceMap.new() + local virtualInstances = { + ROOT = { + ClassName = "Folder", + Name = "Folder", + Properties = {}, + Children = {}, + Metadata = { + ignoreUnknownInstances = true, + }, + }, + } + + local rootInstance = Instance.new("Folder") + local unknownChild = Instance.new("Folder") + unknownChild.Parent = rootInstance + knownInstances:insert("ROOT", rootInstance) + + local ok, patch = diff(knownInstances, virtualInstances, "ROOT") + + assert(ok, tostring(patch)) + + assert(isEmpty(patch.added)) + assert(isEmpty(patch.updated)) + assert(isEmpty(patch.removed)) + end) + + it("should generate a patch with an added child", function() + local knownInstances = InstanceMap.new() + local virtualInstances = { + ROOT = { + ClassName = "Folder", + Name = "Folder", + Properties = {}, + Children = {"CHILD"}, + }, + + CHILD = { + ClassName = "Folder", + Name = "Child", + Properties = {}, + Children = {}, + }, + } + + local rootInstance = Instance.new("Folder") + knownInstances:insert("ROOT", rootInstance) + + local ok, patch = diff(knownInstances, virtualInstances, "ROOT") + + assert(ok, tostring(patch)) + + assert(isEmpty(patch.updated)) + assert(isEmpty(patch.removed)) + expect(size(patch.added)).to.equal(1) + expect(patch.added["CHILD"]).to.equal(virtualInstances["CHILD"]) + end) +end \ No newline at end of file diff --git a/plugin/src/getCanonicalProperty.lua b/plugin/src/Reconciler/getProperty.lua similarity index 55% rename from plugin/src/getCanonicalProperty.lua rename to plugin/src/Reconciler/getProperty.lua index f594722a..bc67525c 100644 --- a/plugin/src/getCanonicalProperty.lua +++ b/plugin/src/Reconciler/getProperty.lua @@ -1,9 +1,11 @@ -local RbxDom = require(script.Parent.Parent.RbxDom) - --[[ Attempts to read a property from the given instance. ]] -local function getCanonincalProperty(instance, propertyName) + +local RbxDom = require(script.Parent.Parent.Parent.RbxDom) +local Error = require(script.Parent.Error) + +local function getProperty(instance, propertyName) local descriptor = RbxDom.findCanonicalPropertyDescriptor(instance.ClassName, propertyName) -- We can skip unknown properties; they're not likely reflected to Lua. @@ -11,11 +13,17 @@ local function getCanonincalProperty(instance, propertyName) -- A good example of a property like this is `Model.ModelInPrimary`, which -- is serialized but not reflected to Lua. if descriptor == nil then - return false, "unknown property" + return false, Error.new(Error.UnknownProperty, { + className = instance.ClassName, + propertyName = propertyName, + }) end if descriptor.scriptability == "None" or descriptor.scriptability == "Write" then - return false, "unreadable property" + return false, Error.new(Error.UnreadableProperty, { + className = instance.ClassName, + propertyName = propertyName, + }) end local success, valueOrErr = descriptor:read(instance) @@ -26,14 +34,19 @@ local function getCanonincalProperty(instance, propertyName) -- If we don't have permission to read a property, we can chalk that up -- to our database being out of date and the engine being right. if err.kind == RbxDom.Error.Kind.Roblox and err.extra:find("lacking permission") then - return false, "permission error" + return false, Error.new(Error.LackingPropertyPermissions, { + className = instance.ClassName, + propertyName = propertyName, + }) end - local message = ("Invalid property %s.%s: %s"):format(descriptor.className, descriptor.name, tostring(err)) - error(message, 2) + return false, Error.new(Error.OtherPropertyError, { + className = instance.ClassName, + propertyName = propertyName, + }) end return true, valueOrErr end -return getCanonincalProperty \ No newline at end of file +return getProperty \ No newline at end of file diff --git a/plugin/src/Reconciler/hydrate.lua b/plugin/src/Reconciler/hydrate.lua new file mode 100644 index 00000000..4d677f57 --- /dev/null +++ b/plugin/src/Reconciler/hydrate.lua @@ -0,0 +1,50 @@ +--[[ + Defines the process of "hydration" -- matching up a virtual DOM with + concrete instances and assigning them IDs. +]] + +local invariant = require(script.Parent.Parent.invariant) + +local function hydrate(instanceMap, virtualInstances, rootId, rootInstance) + local virtualInstance = virtualInstances[rootId] + + if virtualInstance == nil then + invariant("Cannot hydrate an instance not present in virtualInstances\nID: {}", rootId) + end + + instanceMap:insert(rootId, rootInstance) + + local existingChildren = rootInstance:GetChildren() + + -- For each existing child, we'll track whether it's been paired with an + -- instance that the Rojo server knows about. + local isExistingChildVisited = {} + for i = 1, #existingChildren do + isExistingChildVisited[i] = false + end + + for _, childId in ipairs(virtualInstance.Children) do + local virtualChild = virtualInstances[childId] + + for childIndex, childInstance in ipairs(existingChildren) do + if not isExistingChildVisited[childIndex] then + -- We guard accessing Name and ClassName in order to avoid + -- tripping over children of DataModel that Rojo won't have + -- permissions to access at all. + local ok, name, className = pcall(function() + return childInstance.Name, childInstance.ClassName + end) + + -- This rule is very conservative and could be loosened in the + -- future, or more heuristics could be introduced. + if ok and name == virtualChild.Name and className == virtualChild.ClassName then + isExistingChildVisited[childIndex] = true + hydrate(instanceMap, virtualInstances, childId, childInstance) + break + end + end + end + end +end + +return hydrate \ No newline at end of file diff --git a/plugin/src/Reconciler/hydrate.spec.lua b/plugin/src/Reconciler/hydrate.spec.lua new file mode 100644 index 00000000..b9ff796b --- /dev/null +++ b/plugin/src/Reconciler/hydrate.spec.lua @@ -0,0 +1,129 @@ +return function() + local hydrate = require(script.Parent.hydrate) + + local InstanceMap = require(script.Parent.Parent.InstanceMap) + + it("should match the root instance no matter what", function() + local knownInstances = InstanceMap.new() + local virtualInstances = { + ROOT = { + ClassName = "Model", + Name = "Foo", + Properties = {}, + Children = {}, + }, + } + + local rootInstance = Instance.new("Folder") + + hydrate(knownInstances, virtualInstances, "ROOT", rootInstance) + + expect(knownInstances:size()).to.equal(1) + expect(knownInstances.fromIds["ROOT"]).to.equal(rootInstance) + end) + + it("should not match children with mismatched ClassName", function() + local knownInstances = InstanceMap.new() + local virtualInstances = { + ROOT = { + ClassName = "Folder", + Name = "Root", + Properties = {}, + Children = {}, + }, + + CHILD = { + ClassName = "Folder", + Name = "Child", + Properties = {}, + Children = {}, + }, + } + + local rootInstance = Instance.new("Folder") + + -- ClassName of this instance is intentionally different + local child = Instance.new("Model") + child.Name = "Child" + child.Parent = rootInstance + + hydrate(knownInstances, virtualInstances, "ROOT", rootInstance) + + expect(knownInstances:size()).to.equal(1) + expect(knownInstances.fromIds["ROOT"]).to.equal(rootInstance) + end) + + it("should not match children with mismatched Name", function() + local knownInstances = InstanceMap.new() + local virtualInstances = { + ROOT = { + ClassName = "Folder", + Name = "Root", + Properties = {}, + Children = {}, + }, + + CHILD = { + ClassName = "Folder", + Name = "Child", + Properties = {}, + Children = {}, + }, + } + + local rootInstance = Instance.new("Folder") + + -- Name of this instance is intentionally different + local child = Instance.new("Folder") + child.Name = "Not Child" + child.Parent = rootInstance + + hydrate(knownInstances, virtualInstances, "ROOT", rootInstance) + + expect(knownInstances:size()).to.equal(1) + expect(knownInstances.fromIds["ROOT"]).to.equal(rootInstance) + end) + + it("should pair instances with matching Name and ClassName", function() + local knownInstances = InstanceMap.new() + local virtualInstances = { + ROOT = { + ClassName = "Folder", + Name = "Root", + Properties = {}, + Children = {"CHILD1", "CHILD2"}, + }, + + CHILD1 = { + ClassName = "Folder", + Name = "Child 1", + Properties = {}, + Children = {}, + }, + + CHILD2 = { + ClassName = "Model", + Name = "Child 2", + Properties = {}, + Children = {}, + }, + } + + local rootInstance = Instance.new("Folder") + + local child1 = Instance.new("Folder") + child1.Name = "Child 1" + child1.Parent = rootInstance + + local child2 = Instance.new("Model") + child2.Name = "Child 2" + child2.Parent = rootInstance + + hydrate(knownInstances, virtualInstances, "ROOT", rootInstance) + + expect(knownInstances:size()).to.equal(3) + expect(knownInstances.fromIds["ROOT"]).to.equal(rootInstance) + expect(knownInstances.fromIds["CHILD1"]).to.equal(child1) + expect(knownInstances.fromIds["CHILD2"]).to.equal(child2) + end) +end \ No newline at end of file diff --git a/plugin/src/Reconciler/init.lua b/plugin/src/Reconciler/init.lua new file mode 100644 index 00000000..1db295a4 --- /dev/null +++ b/plugin/src/Reconciler/init.lua @@ -0,0 +1,34 @@ +--[[ + This module defines the meat of the Rojo plugin and how it manages tracking + and mutating the Roblox DOM. +]] + +local applyPatch = require(script.applyPatch) +local hydrate = require(script.hydrate) +local diff = require(script.diff) + +local Reconciler = {} +Reconciler.__index = Reconciler + +function Reconciler.new(instanceMap) + local self = { + -- Tracks all of the instances known by the reconciler by ID. + __instanceMap = instanceMap, + } + + return setmetatable(self, Reconciler) +end + +function Reconciler:applyPatch(patch) + return applyPatch(self.__instanceMap, patch) +end + +function Reconciler:hydrate(virtualInstances, rootId, rootInstance) + return hydrate(self.__instanceMap, virtualInstances, rootId, rootInstance) +end + +function Reconciler:diff(virtualInstances, rootId) + return diff(self.__instanceMap, virtualInstances, rootId) +end + +return Reconciler \ No newline at end of file diff --git a/plugin/src/Reconciler/reify.lua b/plugin/src/Reconciler/reify.lua new file mode 100644 index 00000000..8fbee41b --- /dev/null +++ b/plugin/src/Reconciler/reify.lua @@ -0,0 +1,152 @@ +--[[ + "Reifies" a virtual DOM, constructing a real DOM with the same shape. +]] + +local invariant = require(script.Parent.Parent.invariant) +local PatchSet = require(script.Parent.Parent.PatchSet) +local setProperty = require(script.Parent.setProperty) +local decodeValue = require(script.Parent.decodeValue) + +local reifyInner, applyDeferredRefs + +local function reify(instanceMap, virtualInstances, rootId, parentInstance) + -- Create an empty patch that will be populated with any parts of this reify + -- that could not happen, like instances that couldn't be created and + -- properties that could not be assigned. + local unappliedPatch = PatchSet.newEmpty() + + -- Contains a list of all of the ref properties that we'll need to assign + -- after all instances are created. We apply refs in a second pass, after + -- we create as many instances as we can, so that we ensure that referents + -- can be mapped to instances correctly. + local deferredRefs = {} + + reifyInner(instanceMap, virtualInstances, rootId, parentInstance, unappliedPatch, deferredRefs) + applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch) + + return unappliedPatch +end + +--[[ + Add the given ID and all of its descendants in virtualInstances to the given + PatchSet, marked for addition. +]] +local function addAllToPatch(patchSet, virtualInstances, id) + local virtualInstance = virtualInstances[id] + patchSet.added[id] = virtualInstance + + for _, childId in ipairs(virtualInstance.Children) do + addAllToPatch(patchSet, virtualInstances, childId) + end +end + +--[[ + Inner function that defines the core routine. +]] +function reifyInner(instanceMap, virtualInstances, id, parentInstance, unappliedPatch, deferredRefs) + local virtualInstance = virtualInstances[id] + + if virtualInstance == nil then + invariant("Cannot reify an instance not present in virtualInstances\nID: {}", id) + end + + -- Instance.new can fail if we're passing in something that can't be + -- created, like a service, something enabled with a feature flag, or + -- something that requires higher security than we have. + local ok, instance = pcall(Instance.new, virtualInstance.ClassName) + + if not ok then + addAllToPatch(unappliedPatch, virtualInstances, id) + return + end + + -- TODO: Can this fail? Previous versions of Rojo guarded against this, but + -- the reason why was uncertain. + instance.Name = virtualInstance.Name + + -- Track all of the properties that we've failed to assign to this instance. + local unappliedProperties = {} + + for propertyName, virtualValue in pairs(virtualInstance.Properties) do + -- Because refs may refer to instances that we haven't constructed yet, + -- we defer applying any ref properties until all instances are created. + if virtualValue.Type == "Ref" then + table.insert(deferredRefs, { + id = id, + instance = instance, + propertyName = propertyName, + virtualValue = virtualValue, + }) + continue + end + + local ok, value = decodeValue(virtualValue, instanceMap) + if not ok then + unappliedProperties[propertyName] = virtualValue + continue + end + + local ok = setProperty(instance, propertyName, value) + if not ok then + unappliedProperties[propertyName] = virtualValue + end + end + + -- If there were any properties that we failed to assign, push this into our + -- unapplied patch as an update that would need to be applied. + if next(unappliedProperties) ~= nil then + table.insert(unappliedPatch.updated, { + id = id, + changedProperties = unappliedProperties, + }) + end + + for _, childId in ipairs(virtualInstance.Children) do + reifyInner(instanceMap, virtualInstances, childId, instance, unappliedPatch, deferredRefs) + end + + instance.Parent = parentInstance + instanceMap:insert(id, instance) +end + +function applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch) + local function markFailed(id, propertyName, virtualValue) + -- If there is already an updated entry in the unapplied patch for this + -- ref, use the existing one. This could match other parts of the + -- instance that failed to be created, or even just other refs that + -- failed to apply. + -- + -- This is important for instances like selectable GUI objects, which + -- have many similar referent properties. + for _, existingUpdate in ipairs(unappliedPatch.updated) do + if existingUpdate.id == id then + existingUpdate.changedProperties[propertyName] = virtualValue + return + end + end + + -- We didn't find an existing entry that matched, so push a new entry + -- into our unapplied patch. + table.insert(unappliedPatch.updated, { + id = id, + changedProperties = { + [propertyName] = virtualValue, + }, + }) + end + + for _, entry in ipairs(deferredRefs) do + local targetInstance = instanceMap.fromIds[entry.virtualValue.Value] + if targetInstance == nil then + markFailed(entry.id, entry.propertyName, entry.virtualValue) + continue + end + + local ok = setProperty(entry.instance, entry.propertyName, targetInstance) + if not ok then + markFailed(entry.id, entry.propertyName, entry.virtualValue) + end + end +end + +return reify \ No newline at end of file diff --git a/plugin/src/Reconciler/reify.spec.lua b/plugin/src/Reconciler/reify.spec.lua new file mode 100644 index 00000000..74335ec5 --- /dev/null +++ b/plugin/src/Reconciler/reify.spec.lua @@ -0,0 +1,352 @@ +return function() + local reify = require(script.Parent.reify) + + local PatchSet = require(script.Parent.Parent.PatchSet) + local InstanceMap = require(script.Parent.Parent.InstanceMap) + local Error = require(script.Parent.Error) + + local function isEmpty(table) + return next(table) == nil, "Table was not empty" + end + + local function size(dict) + local len = 0 + + for _ in pairs(dict) do + len = len + 1 + end + + return len + end + + it("should throw when given a bogus ID", function() + expect(function() + reify(InstanceMap.new(), {}, "Hi, mom!", game) + end).to.throw() + end) + + it("should return an error when given bogus class names", function() + local virtualInstances = { + ROOT = { + ClassName = "Balogna", + Name = "Food", + Properties = {}, + Children = {}, + }, + } + + local instanceMap = InstanceMap.new() + local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT", nil) + + assert(instanceMap:size() == 0, "expected instanceMap to be empty") + + expect(size(unappliedPatch.added)).to.equal(1) + expect(unappliedPatch.added["ROOT"]).to.equal(virtualInstances["ROOT"]) + + assert(isEmpty(unappliedPatch.removed), "expected no removes") + assert(isEmpty(unappliedPatch.updated), "expected no updates") + end) + + it("should assign name and properties", function() + local virtualInstances = { + ROOT = { + ClassName = "StringValue", + Name = "Spaghetti", + Properties = { + Value = { + Type = "String", + Value = "Hello, world!", + }, + }, + Children = {}, + }, + } + + local instanceMap = InstanceMap.new() + local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT") + + assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty") + + local instance = instanceMap.fromIds["ROOT"] + expect(instance.ClassName).to.equal("StringValue") + expect(instance.Name).to.equal("Spaghetti") + expect(instance.Value).to.equal("Hello, world!") + + expect(instanceMap:size()).to.equal(1) + end) + + it("should construct children", function() + local virtualInstances = { + ROOT = { + ClassName = "Folder", + Name = "Parent", + Properties = {}, + Children = {"CHILD"}, + }, + + CHILD = { + ClassName = "Folder", + Name = "Child", + Properties = {}, + Children = {}, + }, + } + + local instanceMap = InstanceMap.new() + local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT") + + assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty") + + local instance = instanceMap.fromIds["ROOT"] + expect(instance.ClassName).to.equal("Folder") + expect(instance.Name).to.equal("Parent") + + local child = instance.Child + expect(child.ClassName).to.equal("Folder") + + expect(instanceMap:size()).to.equal(2) + end) + + it("should still construct parents if children fail", function() + local virtualInstances = { + ROOT = { + ClassName = "Folder", + Name = "Parent", + Properties = {}, + Children = {"CHILD"}, + }, + + CHILD = { + ClassName = "this ain't an Instance", + Name = "Child", + Properties = {}, + Children = {}, + }, + } + + local instanceMap = InstanceMap.new() + local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT") + + expect(size(unappliedPatch.added)).to.equal(1) + expect(unappliedPatch.added["CHILD"]).to.equal(virtualInstances["CHILD"]) + assert(isEmpty(unappliedPatch.updated), "expected no updates") + assert(isEmpty(unappliedPatch.removed), "expected no removes") + + local instance = instanceMap.fromIds["ROOT"] + expect(instance.ClassName).to.equal("Folder") + expect(instance.Name).to.equal("Parent") + + expect(#instance:GetChildren()).to.equal(0) + expect(instanceMap:size()).to.equal(1) + end) + + it("should fail gracefully when setting erroneous properties", function() + local virtualInstances = { + ROOT = { + ClassName = "StringValue", + Name = "Root", + Properties = { + Value = { + Type = "Vector3", + Value = {1, 2, 3}, + }, + }, + Children = {}, + }, + } + + local instanceMap = InstanceMap.new() + local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT") + + local instance = instanceMap.fromIds["ROOT"] + expect(instance.ClassName).to.equal("StringValue") + expect(instance.Name).to.equal("Root") + + assert(isEmpty(unappliedPatch.added), "expected no additions") + expect(#unappliedPatch.updated).to.equal(1) + assert(isEmpty(unappliedPatch.removed), "expected no removes") + + local update = unappliedPatch.updated[1] + expect(update.id).to.equal("ROOT") + expect(size(update.changedProperties)).to.equal(1) + + local property = update.changedProperties["Value"] + expect(property).to.equal(virtualInstances["ROOT"].Properties.Value) + end) + + -- This is the simplest ref case: ensure that setting a ref property that + -- points to an instance that was previously created as part of the same + -- reify operation works. + it("should apply properties containing refs to ancestors", function() + local virtualInstances = { + ROOT = { + ClassName = "Folder", + Name = "Root", + Properties = {}, + Children = {"CHILD"}, + }, + + CHILD = { + ClassName = "ObjectValue", + Name = "Child", + Properties = { + Value = { + Type = "Ref", + Value = "ROOT", + }, + }, + Children = {}, + }, + } + + local instanceMap = InstanceMap.new() + local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT") + + assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty") + + local root = instanceMap.fromIds["ROOT"] + local child = instanceMap.fromIds["CHILD"] + expect(child.Value).to.equal(root) + end) + + -- This is another simple case: apply a ref property that points to an + -- existing instance. In this test, that instance was created before the + -- reify operation started and is present in instanceMap. + it("should apply properties containing refs to previously-existing instances", function() + local virtualInstances = { + ROOT = { + ClassName = "ObjectValue", + Name = "Root", + Properties = { + Value = { + Type = "Ref", + Value = "EXISTING", + }, + }, + Children = {}, + }, + } + + local instanceMap = InstanceMap.new() + + local existing = Instance.new("Folder") + existing.Name = "Existing" + instanceMap:insert("EXISTING", existing) + + local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT") + + assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty") + + local root = instanceMap.fromIds["ROOT"] + expect(root.Value).to.equal(existing) + end) + + -- This is a tricky ref case: CHILD_A points to CHILD_B, but is constructed + -- first. Deferred ref application is required to implement this case + -- correctly. + it("should apply properties containing refs to later siblings correctly", function() + local virtualInstances = { + ROOT = { + ClassName = "Folder", + Name = "Root", + Properties = {}, + Children = {"CHILD_A", "CHILD_B"}, + }, + + CHILD_A = { + ClassName = "ObjectValue", + Name = "Child A", + Properties = { + Value = { + Type = "Ref", + Value = "Child B", + }, + }, + Children = {}, + }, + + CHILD_B = { + ClassName = "Folder", + Name = "Child B", + Properties = {}, + Children = {}, + }, + } + + local instanceMap = InstanceMap.new() + local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT") + + assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty") + + local childA = instanceMap.fromIds["CHILD_A"] + local childB = instanceMap.fromIds["CHILD_B"] + expect(childA.Value).to.equal(childB) + end) + + -- This is the classic case that calls for deferred ref application. In this + -- test, the root instance has a ref property that refers to its child. The + -- root is definitely constructed first. + -- + -- This is distinct from the sibling case in that the child will be + -- constructed as part of a recursive call before the parent has totally + -- finished. Given deferred refs, this should not fail, but it is a good + -- case to test. + it("should apply properties containing refs to later siblings correctly", function() + local virtualInstances = { + ROOT = { + ClassName = "ObjectValue", + Name = "Root", + Properties = { + Value = { + Type = "Ref", + Value = "CHILD", + }, + }, + Children = {"CHILD"}, + }, + + CHILD = { + ClassName = "Folder", + Name = "Child", + Properties = {}, + Children = {}, + }, + } + + local instanceMap = InstanceMap.new() + local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT") + + assert(PatchSet.isEmpty(unappliedPatch), "expected remaining patch to be empty") + + local root = instanceMap.fromIds["ROOT"] + local child = instanceMap.fromIds["CHILD"] + expect(root.Value).to.equal(child) + end) + + it("should return a partial patch when applying invalid refs", function() + local virtualInstances = { + ROOT = { + ClassName = "ObjectValue", + Name = "Root", + Properties = { + Value = { + Type = "Ref", + Value = "SORRY", + }, + }, + Children = {}, + }, + } + + local instanceMap = InstanceMap.new() + local unappliedPatch = reify(instanceMap, virtualInstances, "ROOT") + + assert(not PatchSet.hasRemoves(unappliedPatch), "expected no removes") + assert(not PatchSet.hasAdditions(unappliedPatch), "expected no additions") + expect(#unappliedPatch.updated).to.equal(1) + + local update = unappliedPatch.updated[1] + expect(update.id).to.equal("ROOT") + expect(update.changedProperties.Value).to.equal(virtualInstances["ROOT"].Properties.Value) + end) +end \ No newline at end of file diff --git a/plugin/src/Reconciler/setProperty.lua b/plugin/src/Reconciler/setProperty.lua new file mode 100644 index 00000000..316f920e --- /dev/null +++ b/plugin/src/Reconciler/setProperty.lua @@ -0,0 +1,48 @@ +--[[ + Attempts to set a property on the given instance. +]] + +local RbxDom = require(script.Parent.Parent.Parent.RbxDom) +local Log = require(script.Parent.Parent.Parent.Log) +local Error = require(script.Parent.Error) + +local function setProperty(instance, propertyName, value) + local descriptor = RbxDom.findCanonicalPropertyDescriptor(instance.ClassName, propertyName) + + -- We can skip unknown properties; they're not likely reflected to Lua. + -- + -- A good example of a property like this is `Model.ModelInPrimary`, which + -- is serialized but not reflected to Lua. + if descriptor == nil then + Log.trace("Skipping unknown property {}.{}", instance.ClassName, propertyName) + + return true + end + + if descriptor.scriptability == "None" or descriptor.scriptability == "Read" then + return false, Error.new(Error.UnwritableProperty, { + className = instance.ClassName, + propertyName = propertyName, + }) + end + + local ok, err = descriptor:write(instance, value) + + if not ok then + if err.kind == RbxDom.Error.Kind.Roblox and err.extra:find("lacking permission") then + return false, Error.new(Error.LackingPropertyPermissions, { + className = instance.ClassName, + propertyName = propertyName, + }) + end + + return false, Error.new(Error.OtherPropertyError, { + className = instance.ClassName, + propertyName = propertyName, + }) + end + + return true +end + +return setProperty \ No newline at end of file diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index e527cc6d..4bbe726c 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -5,6 +5,7 @@ local Fmt = require(script.Parent.Parent.Fmt) local t = require(script.Parent.Parent.t) local InstanceMap = require(script.Parent.InstanceMap) +local PatchSet = require(script.Parent.PatchSet) local Reconciler = require(script.Parent.Reconciler) local strict = require(script.Parent.strict) @@ -214,22 +215,36 @@ function ServeSession:__initialSync(rootInstanceId) -- the tree defined in this response. self.__apiContext:setMessageCursor(readResponseBody.messageCursor) - Log.trace("Computing changes that plugin needs to make to catch up to server...") + -- For any instances that line up with the Rojo server's view, start + -- tracking them in the reconciler. + Log.trace("Matching existing Roblox instances to Rojo IDs") + self.__reconciler:hydrate(readResponseBody.instances, rootInstanceId, game) -- Calculate the initial patch to apply to the DataModel to catch us -- up to what Rojo thinks the place should look like. - local hydratePatch = self.__reconciler:hydrate( + Log.trace("Computing changes that plugin needs to make to catch up to server...") + local success, catchUpPatch = self.__reconciler:diff( readResponseBody.instances, rootInstanceId, game ) - Log.trace("Computed hydration patch: {:#?}", debugPatch(hydratePatch)) + if not success then + Log.error("Could not compute a diff to catch up to the Rojo server: {:#?}", catchUpPatch) + end + + Log.trace("Computed hydration patch: {:#?}", debugPatch(catchUpPatch)) -- TODO: Prompt user to notify them of this patch, since it's - -- effectively a conflict between the Rojo server and the client. + -- effectively a conflict between the Rojo server and the client. In + -- the future, we'll ask which changes the user wants to keep. - self.__reconciler:applyPatch(hydratePatch) + local unappliedPatch = self.__reconciler:applyPatch(catchUpPatch) + + if not PatchSet.isEmpty(unappliedPatch) then + Log.warn("Could not apply all changes requested by the Rojo server:\n{}", + PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) + end end) end @@ -237,7 +252,12 @@ function ServeSession:__mainSyncLoop() return self.__apiContext:retrieveMessages() :andThen(function(messages) for _, message in ipairs(messages) do - self.__reconciler:applyPatch(message) + local unappliedPatch = self.__reconciler:applyPatch(message) + + if not PatchSet.isEmpty(unappliedPatch) then + Log.warn("Could not apply all changes requested by the Rojo server:\n{}", + PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) + end end if self.__status ~= Status.Disconnected then diff --git a/plugin/src/setCanonicalProperty.lua b/plugin/src/setCanonicalProperty.lua deleted file mode 100644 index 9554d020..00000000 --- a/plugin/src/setCanonicalProperty.lua +++ /dev/null @@ -1,37 +0,0 @@ -local RbxDom = require(script.Parent.Parent.RbxDom) - ---[[ - Attempts to set a property on the given instance. -]] -local function setCanonicalProperty(instance, propertyName, value) - local descriptor = RbxDom.findCanonicalPropertyDescriptor(instance.ClassName, propertyName) - - -- We can skip unknown properties; they're not likely reflected to Lua. - -- - -- A good example of a property like this is `Model.ModelInPrimary`, which - -- is serialized but not reflected to Lua. - if descriptor == nil then - return false, "unknown property" - end - - if descriptor.scriptability == "None" or descriptor.scriptability == "Read" then - return false, "unwritable property" - end - - local success, err = descriptor:write(instance, value) - - if not success then - -- If we don't have permission to write a property, we just silently - -- ignore it. - if err.kind == RbxDom.Error.Kind.Roblox and err.extra:find("lacking permission") then - return false, "permission error" - end - - local message = ("Invalid property %s.%s: %s"):format(descriptor.className, descriptor.name, tostring(err)) - error(message, 2) - end - - return true -end - -return setCanonicalProperty \ No newline at end of file diff --git a/plugin/test b/plugin/test new file mode 100644 index 00000000..caeb8874 --- /dev/null +++ b/plugin/test @@ -0,0 +1,4 @@ +#!/bin/sh + +rojo build test-place.project.json -o TestPlace.rbxlx +run-in-roblox --script run-tests.server.lua --place TestPlace.rbxlx \ No newline at end of file diff --git a/plugin/test-place.project.json b/plugin/test-place.project.json index 32901b26..7bc42eb6 100644 --- a/plugin/test-place.project.json +++ b/plugin/test-place.project.json @@ -15,7 +15,7 @@ "ServerScriptService": { "RunTests": { - "$path": "testBootstrap.server.lua" + "$path": "run-tests.server.lua" } }, diff --git a/selene.toml b/selene.toml new file mode 100644 index 00000000..e73e3567 --- /dev/null +++ b/selene.toml @@ -0,0 +1,4 @@ +std = "roblox" + +[config] +unused_variable = { allow_unused_self = true } From e5041d80ef9d0bb55cbb5e05c7a2cddddbd5718c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 11 Nov 2020 17:11:34 -0800 Subject: [PATCH 1070/1504] plugin: Fix warning in applyPatch.lua --- plugin/src/Reconciler/applyPatch.lua | 1 - 1 file changed, 1 deletion(-) diff --git a/plugin/src/Reconciler/applyPatch.lua b/plugin/src/Reconciler/applyPatch.lua index dafaa352..f806013c 100644 --- a/plugin/src/Reconciler/applyPatch.lua +++ b/plugin/src/Reconciler/applyPatch.lua @@ -12,7 +12,6 @@ local Types = require(script.Parent.Parent.Types) local invariant = require(script.Parent.Parent.invariant) local decodeValue = require(script.Parent.decodeValue) -local getProperty = require(script.Parent.getProperty) local reify = require(script.Parent.reify) local setProperty = require(script.Parent.setProperty) From 2136da15d6d304a76eef33e9db8d84ad974409a9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 16 Nov 2020 11:44:39 -0800 Subject: [PATCH 1071/1504] plugin: Ensure InstanceMap deletes existing entries before inserting --- plugin/src/InstanceMap.lua | 3 +++ 1 file changed, 3 insertions(+) diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index fe2b3eac..7196d915 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -79,6 +79,9 @@ function InstanceMap:__fmtDebug(output) end function InstanceMap:insert(id, instance) + self:removeId(id) + self:removeInstance(instance) + self.fromIds[id] = instance self.fromInstances[instance] = id self:__connectSignals(instance) From 039d92ce78cf0f927508e7619978554797099474 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 16 Nov 2020 11:44:56 -0800 Subject: [PATCH 1072/1504] plugin: Support ClassName changes in applyPatch --- plugin/src/Reconciler/applyPatch.lua | 78 +++++++++++++++++++++-- plugin/src/Reconciler/applyPatch.spec.lua | 39 ++++++++++++ 2 files changed, 113 insertions(+), 4 deletions(-) diff --git a/plugin/src/Reconciler/applyPatch.lua b/plugin/src/Reconciler/applyPatch.lua index f806013c..352ed48f 100644 --- a/plugin/src/Reconciler/applyPatch.lua +++ b/plugin/src/Reconciler/applyPatch.lua @@ -73,7 +73,7 @@ local function applyPatch(instanceMap, patch) if instance == nil then -- We can't update an instance that doesn't exist. - -- TODO: Should this be an invariant? + table.insert(unappliedPatch.updated, update) continue end @@ -84,10 +84,80 @@ local function applyPatch(instanceMap, patch) } local partiallyApplied = false + -- If the instance's className changed, we have a bumpy ride ahead while + -- we recreate this instance and move all of its children into the new + -- copy atomically...ish. if update.changedClassName ~= nil then - -- TODO: Support changing class name by destroying + recreating. - unappliedUpdate.changedClassName = update.changedClassName - partiallyApplied = true + -- If the instance's name also changed, we'll do it here, since this + -- branch will skip the rest of the loop iteration. + local newName = update.changedName or instance.Name + + -- TODO: When changing between instances that have similar sets of + -- properties, like between an ImageLabel and an ImageButton, we + -- should preserve all of the properties that are shared between the + -- two classes unless they're changed as part of this patch. This is + -- similar to how "class changer" Studio plugins work. + -- + -- For now, we'll only apply properties that are mentioned in this + -- update. Patches with changedClassName set only occur in specific + -- circumstances, usually between Folder and ModuleScript instances. + -- While this may result in some issues, like not preserving the + -- "Archived" property, a robust solution is sufficiently + -- complicated that we're pushing it off for now. + local newProperties = update.changedProperties + + -- If the instance's ClassName changed, we'll kick into reify to + -- create this instance. We'll handle moving all of children between + -- the instances after the new one is created. + local mockVirtualInstance = { + Id = update.id, + Name = newName, + ClassName = update.changedClassName, + Properties = newProperties, + Children = {}, + } + + local mockAdded = { + [update.id] = mockVirtualInstance, + } + + local failedToReify = reify(instanceMap, mockAdded, update.id, instance.Parent) + + local newInstance = instanceMap.fromIds[update.id] + + -- Some parts of reify may have failed, but this is not necessarily + -- critical. If the instance wasn't recreated or has the wrong Name, + -- we'll consider our attempt a failure. + if instance == newInstance or newInstance.Name ~= newName then + table.insert(unappliedPatch.updated, update) + continue + end + + -- Here are the non-critical failures. We know that the instance + -- succeeded in creating and that assigning Name did not fail, but + -- other property assignments might've. + if not PatchSet.isEmpty(failedToReify) then + PatchSet.assign(unappliedPatch, failedToReify) + end + + -- Watch out, this is the scary part! Move all of the children of + -- instance into newInstance. + -- + -- TODO: If this fails part way through, should we move everything + -- back? For now, we assume that moving things will not fail. + for _, child in ipairs(instance:GetChildren()) do + child.Parent = newInstance + end + + -- See you later, original instance. + -- + -- TODO: Can this fail? Some kinds of instance may not appreciate + -- being destroyed, like services. + instance:Destroy() + + -- This completes your rebuilding a plane mid-flight safety + -- instruction. Please sit back, relax, and enjoy your flight. + continue end if update.changedName ~= nil then diff --git a/plugin/src/Reconciler/applyPatch.spec.lua b/plugin/src/Reconciler/applyPatch.spec.lua index 5308079d..28e2a41e 100644 --- a/plugin/src/Reconciler/applyPatch.spec.lua +++ b/plugin/src/Reconciler/applyPatch.spec.lua @@ -156,4 +156,43 @@ return function() assert(PatchSet.isEmpty(unapplied), "expected remaining patch to be empty") expect(value.Value).to.equal("WORLD") end) + + it("should recreate instances when changedClassName is set, preserving children", function() + local root = Instance.new("Folder") + root.Name = "Initial Root Name" + + local child = Instance.new("Folder") + child.Name = "Child" + child.Parent = root + + local instanceMap = InstanceMap.new() + instanceMap:insert("ROOT", root) + instanceMap:insert("CHILD", child) + + local patch = PatchSet.newEmpty() + table.insert(patch.updated, { + id = "ROOT", + changedName = "Updated Root Name", + changedClassName = "StringValue", + changedProperties = { + Value = { + Type = "String", + Value = "I am Root", + }, + }, + }) + + local unapplied = applyPatch(instanceMap, patch) + assert(PatchSet.isEmpty(unapplied), "expected remaining patch to be empty") + + local newRoot = instanceMap.fromIds["ROOT"] + assert(newRoot ~= root, "expected instance to be recreated") + expect(newRoot.ClassName).to.equal("StringValue") + expect(newRoot.Name).to.equal("Updated Root Name") + expect(newRoot.Value).to.equal("I am Root") + + local newChild = newRoot:FindFirstChild("Child") + assert(newChild ~= nil, "expected child to be present") + assert(newChild == child, "expected child to be preserved") + end) end \ No newline at end of file From 046dc0d5983dac233db4cb8e59162b1906cba75c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 16 Nov 2020 11:49:30 -0800 Subject: [PATCH 1073/1504] plugin: Fix grammar in comments a bit :) --- plugin/src/Reconciler/applyPatch.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/Reconciler/applyPatch.lua b/plugin/src/Reconciler/applyPatch.lua index 352ed48f..a061bea7 100644 --- a/plugin/src/Reconciler/applyPatch.lua +++ b/plugin/src/Reconciler/applyPatch.lua @@ -86,7 +86,7 @@ local function applyPatch(instanceMap, patch) -- If the instance's className changed, we have a bumpy ride ahead while -- we recreate this instance and move all of its children into the new - -- copy atomically...ish. + -- version atomically...ish. if update.changedClassName ~= nil then -- If the instance's name also changed, we'll do it here, since this -- branch will skip the rest of the loop iteration. @@ -135,7 +135,7 @@ local function applyPatch(instanceMap, patch) -- Here are the non-critical failures. We know that the instance -- succeeded in creating and that assigning Name did not fail, but - -- other property assignments might've. + -- other property assignments might've failed. if not PatchSet.isEmpty(failedToReify) then PatchSet.assign(unappliedPatch, failedToReify) end From 836b18e68a2f45af85cf74d5d125839e02b75f73 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Nov 2020 10:25:25 -0800 Subject: [PATCH 1074/1504] Release 6.0.0-rc.2 --- CHANGELOG.md | 4 ++ Cargo.lock | 154 ++++++++++++++++++++++++------------------ Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 4 files changed, 93 insertions(+), 69 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fb7a3fd9..7bf71906 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes + +## [6.0.0 Release Candidate 2](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.1) (November 19, 2020) * Fixed crash when malformed CSV files are put into a project. ([#310](https://github.com/rojo-rbx/rojo/issues/310)) * Fixed incorrect string escaping when producing Lua code from JSON files. ([#314](https://github.com/rojo-rbx/rojo/issues/314)) * Fixed performance issues introduced in Rojo 6.0.0-rc.1. ([#317](https://github.com/rojo-rbx/rojo/issues/317)) @@ -8,6 +10,8 @@ * Updated default place template to take advantage of [#210](https://github.com/rojo-rbx/rojo/pull/210). * Enabled glob ignore patterns by default and removed the `unstable_glob_ignore` feature. * `globIgnorePaths` can be set on a project to a list of globs to ignore. +* The Rojo plugin now completes as much as it can from a patch without disconnecting. Warnings are shown in the console. +* Fixed 6.0.0-rc.1 regression causing instances that changed ClassName to instead... not change ClassName. ## [6.0.0 Release Candidate 1](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.1) (March 29, 2020) This release jumped from 0.6.0 to 6.0.0. Rojo has been in use in production for many users for quite a long times, and so 6.0 is a more accurate reflection of Rojo's version than a pre-1.0 version. diff --git a/Cargo.lock b/Cargo.lock index c6eb1462..c29ac6fa 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,9 +2,9 @@ # It is not intended for manual editing. [[package]] name = "addr2line" -version = "0.13.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b6a2d3371669ab3ca9797670853d61402b03d0b4b9ebf33d677dfa720203072" +checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423" dependencies = [ "gimli", ] @@ -17,9 +17,9 @@ checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e" [[package]] name = "aho-corasick" -version = "0.7.14" +version = "0.7.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b476ce7103678b0c6d3d395dbbae31d48ff910bd28be979ba5d48c6351131d0d" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" dependencies = [ "memchr", ] @@ -35,9 +35,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c" +checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7" [[package]] name = "arrayref" @@ -76,9 +76,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.53" +version = "0.3.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707b586e0e2f247cbde68cdd2c3ce69ea7b7be43e1c5b426e37c9319c4b9838e" +checksum = "2baad346b2d4e94a24347adeee9c7a93f412ee94b9cc26e5b59dea23848e9f28" dependencies = [ "addr2line", "cfg-if 1.0.0", @@ -127,9 +127,9 @@ checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" [[package]] name = "blake2b_simd" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8fb2d74254a3a0b5cac33ac9f8ed0e44aa50378d9dbb2e5d83bd21ed1dc2c8a" +checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587" dependencies = [ "arrayref", "arrayvec", @@ -209,9 +209,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.61" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed67cbde08356238e75fc4656be4749481eeffb09e19f320a25237d5221c985d" +checksum = "ad9c6140b5a2c7db40ea56eb1821245e5362b44385c05b76288b1a599934ac87" [[package]] name = "cfg-if" @@ -285,9 +285,9 @@ dependencies = [ [[package]] name = "const_fn" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce90df4c658c62f12d78f7508cf92f9173e5184a539c10bfe54a3107b3ffd0f2" +checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab" [[package]] name = "constant_time_eq" @@ -325,9 +325,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.7.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57d24c7a13c43e870e37c1556b74555437870a04514f7685f5b354e090567171" +checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" dependencies = [ "core-foundation-sys", "libc", @@ -335,9 +335,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.7.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3a71ab494c0b5b860bdc8407ae08978052417070c2ced38573a9157ad75b8ac" +checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" [[package]] name = "crc32fast" @@ -491,9 +491,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.1.3" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00affe7f6ab566df61b4be3ce8cf16bc2576bca0963ceb0955e45d514bf9a279" +checksum = "fc4666154fd004af3fd6f1da2e81a96fd5a81927fe8ddb6ecc79e2aa6e138b54" dependencies = [ "bstr", "csv-core", @@ -583,11 +583,11 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.24" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a51b8cf747471cb9499b6d59e59b0444f4c90eba8968c4e44874e92b5b64ace2" +checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] @@ -642,11 +642,11 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "filetime" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed85775dcc68644b5c950ac06a2b23768d3bc9390464151aaf27136998dcf9e" +checksum = "0c122a393ea57648015bf06fbd3d372378992e86b9ff5a7a497b076a28c79efe" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", "redox_syscall", "winapi 0.3.9", @@ -654,11 +654,11 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.18" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da80be589a72651dcda34d8b35bcdc9b7254ad06325611074d9cc0fbb19f60ee" +checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "crc32fast", "libc", "miniz_oxide", @@ -685,6 +685,16 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" +[[package]] +name = "form_urlencoded" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ece68d15c92e84fa4f19d3780f1294e5ca82a78a6d515f1efaabcc144688be00" +dependencies = [ + "matches", + "percent-encoding 2.1.0", +] + [[package]] name = "fs-err" version = "2.5.0" @@ -770,9 +780,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" +checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" [[package]] name = "globset" @@ -967,9 +977,9 @@ dependencies = [ [[package]] name = "inotify-sys" -version = "0.1.3" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e74a1aa87c59aeff6ef2cc2fa62d41bc43f54952f55652656b18a02fd5e356c0" +checksum = "c4563555856585ab3180a5bf0b2f9f8d301a728462afffc8195b3f5394229c55" dependencies = [ "libc", ] @@ -1232,9 +1242,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b0d88c06fe90d5ee94048ba40409ef1d9315d86f6f38c2efdaad4fb50c58b2d" +checksum = "6fcc7939b5edc4e4f86b1b4a04bb1498afaaf871b1a6691838ed06fcb48d3a3f" dependencies = [ "lazy_static", "libc", @@ -1279,9 +1289,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" dependencies = [ "autocfg 1.0.1", ] @@ -1298,9 +1308,9 @@ dependencies = [ [[package]] name = "object" -version = "0.21.1" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37fd5004feb2ce328a52b0b3d01dbf4ffff72583493900ed15f22d4111c51693" +checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" [[package]] name = "oorandom" @@ -1485,9 +1495,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c36fa947111f5c62a733b652544dd0016a43ce89619538a8ef92724a6f501a20" +checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" [[package]] name = "pretty_assertions" @@ -1565,7 +1575,7 @@ dependencies = [ "idna 0.2.0", "lazy_static", "regex", - "url 2.1.1", + "url 2.2.0", ] [[package]] @@ -1846,9 +1856,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8963b85b8ce3074fecffde43b4b0dded83ce2f367dc8d363afc56679f3ee820b" +checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" dependencies = [ "aho-corasick", "memchr", @@ -1867,9 +1877,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.20" +version = "0.6.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cab7a364d15cde1e505267766a2d3c4e22a843e1a601f0fa7564c0f82ced11c" +checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" [[package]] name = "remove_dir_all" @@ -1963,7 +1973,7 @@ dependencies = [ [[package]] name = "rojo" -version = "6.0.0-rc.1" +version = "6.0.0-rc.2" dependencies = [ "anyhow", "backtrace", @@ -2078,9 +2088,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "security-framework" -version = "0.4.4" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64808902d7d99f78eaddd2b4e2509713babc3dc3c85ad6f4c447680f3c01e535" +checksum = "c1759c2e3c8580017a484a7ac56d3abc5a6c1feadf88db2f3633f12ae4268c69" dependencies = [ "bitflags", "core-foundation", @@ -2091,9 +2101,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "0.4.3" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17bf11d99252f512695eb468de5516e5cf75455521e69dfe343f3b74e4748405" +checksum = "f99b9d5e26d2a71633cc4f2ebae7cc9f874044e0c351a27e17892d76dce5678b" dependencies = [ "core-foundation-sys", "libc", @@ -2180,9 +2190,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.8.13" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae3e2dd40a7cdc18ca80db804b7f461a39bb721160a85c9a1fa30134bf3c02a5" +checksum = "f7baae0a99f1a324984bcdc5f0718384c1f69775f1c7eec8b859b71b443e3fd7" dependencies = [ "dtoa", "linked-hash-map", @@ -2325,9 +2335,9 @@ dependencies = [ [[package]] name = "termcolor" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" dependencies = [ "winapi-util", ] @@ -2352,18 +2362,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "318234ffa22e0920fe9a40d7b8369b5f649d490980cf7aadcf1eb91594869b42" +checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.21" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cae2447b6282786c3493999f40a9be2a6ad20cb8bd268b0a0dbf5a065535c0ab" +checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", @@ -2402,9 +2412,18 @@ dependencies = [ [[package]] name = "tinyvec" -version = "0.3.4" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "238ce071d267c5710f9d31451efec16c5ee22de34df17cc05e56cbc92e967117" +checksum = "b78a366903f506d2ad52ca8dc552102ffdd3e937ba8a227f024dc1d1eae28575" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" @@ -2646,18 +2665,18 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.13" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb19cf769fa8c6a80a162df694621ebeb4dafb606470b2b2fce0be40a98a977" +checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606" dependencies = [ "tinyvec", ] [[package]] name = "unicode-segmentation" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e83e153d1053cbb5a118eeff7fd5be06ed99153f00dbcd8ae310c5fb2b22edc0" +checksum = "db8716a166f290ff49dabc18b44aa407cb7c6dbe1aa0971b44b8a24b0ca35aae" [[package]] name = "unicode-width" @@ -2690,10 +2709,11 @@ dependencies = [ [[package]] name = "url" -version = "2.1.1" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "829d4a8476c35c9bf0bbce5a3b23f4106f79728039b726d292bb93bc106787cb" +checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e" dependencies = [ + "form_urlencoded", "idna 0.2.0", "matches", "percent-encoding 2.1.0", diff --git a/Cargo.toml b/Cargo.toml index 57a08e35..9b737bdb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "6.0.0-rc.1" +version = "6.0.0-rc.2" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index fbdca8a3..b33f34ab 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {6, 0, 0, "-rc.1"}, + version = {6, 0, 0, "-rc.2"}, expectedServerVersionString = "6.0 or newer", protocolVersion = 3, defaultHost = "localhost", From 19a955a3272c528710e80354f0eb8ed895e85a5c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Nov 2020 10:26:37 -0800 Subject: [PATCH 1075/1504] Release memofs 0.1.3 --- memofs/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/memofs/CHANGELOG.md b/memofs/CHANGELOG.md index 78dd22aa..6a6aecde 100644 --- a/memofs/CHANGELOG.md +++ b/memofs/CHANGELOG.md @@ -1,6 +1,8 @@ # memofs Changelog ## Unreleased Changes + +## 0.1.3 (2020-11-19) * Added `set_watch_enabled` to `Vfs` and `VfsLock` to allow turning off file watching. ## 0.1.2 (2020-03-29) From 35efb464e54f3efae99a62e9490b93684e584891 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Nov 2020 10:33:09 -0800 Subject: [PATCH 1076/1504] Fix incorrect tag in CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bf71906..daa7f341 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased Changes -## [6.0.0 Release Candidate 2](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.1) (November 19, 2020) +## [6.0.0 Release Candidate 2](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.2) (November 19, 2020) * Fixed crash when malformed CSV files are put into a project. ([#310](https://github.com/rojo-rbx/rojo/issues/310)) * Fixed incorrect string escaping when producing Lua code from JSON files. ([#314](https://github.com/rojo-rbx/rojo/issues/314)) * Fixed performance issues introduced in Rojo 6.0.0-rc.1. ([#317](https://github.com/rojo-rbx/rojo/issues/317)) From 3b800d1cd78ad84a4b069bf689984bf47817126e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Nov 2020 11:06:03 -0800 Subject: [PATCH 1077/1504] Patch ReflectionDatabase to turn off SourceAssetId --- plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua b/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua index c53b075f..3c1275b7 100644 --- a/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua +++ b/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua @@ -7543,7 +7543,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, Tags = { @@ -19580,4 +19580,4 @@ return { defaults = { }, }, -} +} \ No newline at end of file From 0401c3ac0ec46d82361614d806549a1bb951193b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Nov 2020 11:20:30 -0800 Subject: [PATCH 1078/1504] Mark HttpEnabled as not scriptable as well --- plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua b/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua index 3c1275b7..b3b90619 100644 --- a/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua +++ b/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua @@ -6283,7 +6283,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, }, From 1c0dc6007174fa7f482f015abba5fee9b5f0476e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Nov 2020 11:31:46 -0800 Subject: [PATCH 1079/1504] Update CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index daa7f341..96f5ca95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Fixed the Rojo plugin attempted to write the non-scriptable properties `Instance.SourceAssetId` and `HttpServer.HttpEnabled`. ## [6.0.0 Release Candidate 2](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.2) (November 19, 2020) * Fixed crash when malformed CSV files are put into a project. ([#310](https://github.com/rojo-rbx/rojo/issues/310)) From dcb30351c5ae7e3152a9f85402da2c876def26bc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Nov 2020 11:44:53 -0800 Subject: [PATCH 1080/1504] Fix null referent handling --- CHANGELOG.md | 1 + plugin/src/Reconciler/decodeValue.lua | 4 ++++ plugin/src/Reconciler/reify.lua | 12 +++++++++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 96f5ca95..a4fb3062 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased Changes * Fixed the Rojo plugin attempted to write the non-scriptable properties `Instance.SourceAssetId` and `HttpServer.HttpEnabled`. +* Fixed the Rojo plugin's handling of null referents. ## [6.0.0 Release Candidate 2](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.2) (November 19, 2020) * Fixed crash when malformed CSV files are put into a project. ([#310](https://github.com/rojo-rbx/rojo/issues/310)) diff --git a/plugin/src/Reconciler/decodeValue.lua b/plugin/src/Reconciler/decodeValue.lua index 3dfd321c..5962d210 100644 --- a/plugin/src/Reconciler/decodeValue.lua +++ b/plugin/src/Reconciler/decodeValue.lua @@ -9,6 +9,10 @@ local Error = require(script.Parent.Error) local function decodeValue(virtualValue, instanceMap) -- Refs are represented as IDs in the same space that Rojo's protocol uses. if virtualValue.Type == "Ref" then + if virtualValue.Value == nil then + return true, nil + end + local instance = instanceMap.fromIds[virtualValue.Value] if instance ~= nil then diff --git a/plugin/src/Reconciler/reify.lua b/plugin/src/Reconciler/reify.lua index 8fbee41b..b0c8aa0b 100644 --- a/plugin/src/Reconciler/reify.lua +++ b/plugin/src/Reconciler/reify.lua @@ -136,15 +136,21 @@ function applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch) end for _, entry in ipairs(deferredRefs) do - local targetInstance = instanceMap.fromIds[entry.virtualValue.Value] + local virtualValue = entry.virtualValue + + if virtualValue.Value == nil then + continue + end + + local targetInstance = instanceMap.fromIds[virtualValue.Value] if targetInstance == nil then - markFailed(entry.id, entry.propertyName, entry.virtualValue) + markFailed(entry.id, entry.propertyName, virtualValue) continue end local ok = setProperty(entry.instance, entry.propertyName, targetInstance) if not ok then - markFailed(entry.id, entry.propertyName, entry.virtualValue) + markFailed(entry.id, entry.propertyName, virtualValue) end end end From a1f7cdc2b63e1db5999287d12ebb19ef334405e5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Nov 2020 11:47:07 -0800 Subject: [PATCH 1081/1504] Release 6.0.0-rc.3 --- CHANGELOG.md | 2 ++ Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4fb3062..79a8e4ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes + +## [6.0.0 Release Candidate 3](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.3) (November 19, 2020) * Fixed the Rojo plugin attempted to write the non-scriptable properties `Instance.SourceAssetId` and `HttpServer.HttpEnabled`. * Fixed the Rojo plugin's handling of null referents. diff --git a/Cargo.toml b/Cargo.toml index 9b737bdb..5ac7f359 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "6.0.0-rc.2" +version = "6.0.0-rc.3" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index b33f34ab..27e6ed9e 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {6, 0, 0, "-rc.2"}, + version = {6, 0, 0, "-rc.3"}, expectedServerVersionString = "6.0 or newer", protocolVersion = 3, defaultHost = "localhost", From 23b8308282d47f888b1f241dd12db01b7bbc5b46 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 19 Nov 2020 11:50:06 -0800 Subject: [PATCH 1082/1504] Fix lockfile not being updated for 6.0.0-rc.3 --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index c29ac6fa..cf8be64a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1973,7 +1973,7 @@ dependencies = [ [[package]] name = "rojo" -version = "6.0.0-rc.2" +version = "6.0.0-rc.3" dependencies = [ "anyhow", "backtrace", From 98238e4516a555e98c7770a97527c94aa7c40ea0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Dec 2020 10:12:51 -0800 Subject: [PATCH 1083/1504] Fix longstanding message_queue warning --- src/message_queue.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/message_queue.rs b/src/message_queue.rs index 2f20dcab..8542c671 100644 --- a/src/message_queue.rs +++ b/src/message_queue.rs @@ -1,7 +1,4 @@ -use std::{ - mem, - sync::{Mutex, RwLock}, -}; +use std::sync::{Mutex, RwLock}; use futures::sync::oneshot; @@ -58,7 +55,7 @@ impl MessageQueue { // Without this annotation, Rust gets confused since the first argument // is a MutexGuard, but the second is a Vec. - mem::replace::>(&mut message_listeners, remaining_listeners); + *message_listeners = remaining_listeners; } /// Subscribe to any messages occurring after the given message cursor. From 5bb3dc258a725eaf4f8f4ef9e4c83a0fb2e12498 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Dec 2020 10:17:52 -0800 Subject: [PATCH 1084/1504] Add projectName to serve output --- .../end_to_end__tests__serve__add_folder_info.snap | 1 + .../end_to_end__tests__serve__edit_init_info.snap | 1 + .../end_to_end__tests__serve__empty_info.snap | 1 + .../end_to_end__tests__serve__move_folder_of_stuff_info.snap | 1 + .../end_to_end__tests__serve__remove_file_info.snap | 1 + .../end_to_end__tests__serve__scripts_info.snap | 1 + src/web/api.rs | 1 + src/web/interface.rs | 1 + 8 files changed, 8 insertions(+) diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_info.snap index 62f5dc4b..738c0fd0 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_info.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_info.snap @@ -3,6 +3,7 @@ source: tests/tests/serve.rs expression: redactions.redacted_yaml(info) --- expectedPlaceIds: ~ +projectName: add_folder protocolVersion: 3 rootInstanceId: id-2 serverVersion: "[server-version]" diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_info.snap index 62f5dc4b..b9c43c7a 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_info.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_info.snap @@ -3,6 +3,7 @@ source: tests/tests/serve.rs expression: redactions.redacted_yaml(info) --- expectedPlaceIds: ~ +projectName: edit_init protocolVersion: 3 rootInstanceId: id-2 serverVersion: "[server-version]" diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_info.snap index 62f5dc4b..7b4e3904 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_info.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_info.snap @@ -3,6 +3,7 @@ source: tests/tests/serve.rs expression: redactions.redacted_yaml(info) --- expectedPlaceIds: ~ +projectName: empty protocolVersion: 3 rootInstanceId: id-2 serverVersion: "[server-version]" diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_info.snap index 62f5dc4b..e3a59e17 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_info.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_info.snap @@ -3,6 +3,7 @@ source: tests/tests/serve.rs expression: redactions.redacted_yaml(info) --- expectedPlaceIds: ~ +projectName: move_folder_of_stuff protocolVersion: 3 rootInstanceId: id-2 serverVersion: "[server-version]" diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_info.snap index 62f5dc4b..bbc8301f 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_info.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_info.snap @@ -3,6 +3,7 @@ source: tests/tests/serve.rs expression: redactions.redacted_yaml(info) --- expectedPlaceIds: ~ +projectName: remove_file protocolVersion: 3 rootInstanceId: id-2 serverVersion: "[server-version]" diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_info.snap index 62f5dc4b..0b801363 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_info.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_info.snap @@ -3,6 +3,7 @@ source: tests/tests/serve.rs expression: redactions.redacted_yaml(info) --- expectedPlaceIds: ~ +projectName: scripts protocolVersion: 3 rootInstanceId: id-2 serverVersion: "[server-version]" diff --git a/src/web/api.rs b/src/web/api.rs index 580bd055..d041b9c1 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -67,6 +67,7 @@ impl ApiService { server_version: SERVER_VERSION.to_owned(), protocol_version: PROTOCOL_VERSION, session_id: self.serve_session.session_id(), + project_name: self.serve_session.project_name().to_owned(), expected_place_ids: self.serve_session.serve_place_ids().cloned(), root_instance_id, }) diff --git a/src/web/interface.rs b/src/web/interface.rs index f66a3909..be37f1e0 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -89,6 +89,7 @@ pub struct ServerInfoResponse { pub session_id: SessionId, pub server_version: String, pub protocol_version: u64, + pub project_name: String, pub expected_place_ids: Option>, pub root_instance_id: RbxId, } From ff43ffce0711f1efb0965ef918b5f74ab972f901 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Dec 2020 10:22:40 -0800 Subject: [PATCH 1085/1504] Update to insta 1.3.0 --- Cargo.lock | 33 +++++++++++++++------------------ Cargo.toml | 2 +- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cf8be64a..4a27fa83 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -247,18 +247,6 @@ dependencies = [ "rojo", ] -[[package]] -name = "clicolors-control" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90082ee5dcdd64dc4e9e0d37fbf3ee325419e39c0092191e0393df65518f741e" -dependencies = [ - "atty", - "lazy_static", - "libc", - "winapi 0.3.9", -] - [[package]] name = "cloudabi" version = "0.0.3" @@ -270,15 +258,14 @@ dependencies = [ [[package]] name = "console" -version = "0.9.2" +version = "0.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e0f3986890b3acbc782009e2629dfe2baa430ac091519ce3be26164a2ae6c0" +checksum = "c0b1aacfaffdbff75be81c15a399b4bedf78aaefe840e8af1d299ac2ade885d2" dependencies = [ - "clicolors-control", "encode_unicode", "lazy_static", "libc", - "regex", + "terminal_size", "termios", "winapi 0.3.9", ] @@ -986,9 +973,9 @@ dependencies = [ [[package]] name = "insta" -version = "0.13.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8df742abee84dbf27d20869c9adf77b0d8f7ea3eead13c2c9e3998d136a97058" +checksum = "863bf97e7130bf788f29a99bc4073735af6b8ecc3da6a39c23b3a688d2d3109a" dependencies = [ "console", "difference", @@ -2342,6 +2329,16 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "terminal_size" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bd2d183bd3fac5f5fe38ddbeb4dc9aec4a39a9d7d59e7491d900302da01cbe1" +dependencies = [ + "libc", + "winapi 0.3.9", +] + [[package]] name = "termios" version = "0.3.3" diff --git a/Cargo.toml b/Cargo.toml index 5ac7f359..09411ee1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -103,7 +103,7 @@ maplit = "1.0.1" rojo-insta-ext = { path = "rojo-insta-ext" } criterion = "0.3" -insta = { version = "0.13.1", features = ["redactions"] } +insta = { version = "1.3.0", features = ["redactions"] } lazy_static = "1.2" paste = "0.1" pretty_assertions = "0.6.1" From a937fc38db536b07e7de7c07ee722d52098f51d6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Dec 2020 10:22:45 -0800 Subject: [PATCH 1086/1504] Update Changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 79a8e4ca..8861f68f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,10 @@ # Rojo Changelog ## Unreleased Changes +* Added `projectName` to `/api/rojo` output. ## [6.0.0 Release Candidate 3](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.3) (November 19, 2020) -* Fixed the Rojo plugin attempted to write the non-scriptable properties `Instance.SourceAssetId` and `HttpServer.HttpEnabled`. +* Fixed the Rojo plugin attempting to write the non-scriptable properties `Instance.SourceAssetId` and `HttpServer.HttpEnabled`. * Fixed the Rojo plugin's handling of null referents. ## [6.0.0 Release Candidate 2](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.2) (November 19, 2020) From cae4c466697c6ea773d3d24efcfe8e49568ee7da Mon Sep 17 00:00:00 2001 From: Reselim Date: Mon, 14 Dec 2020 14:07:39 -0500 Subject: [PATCH 1087/1504] New UI (#367) * Add Flipper * Remove old UI * Add boilerplate UI * Change plugin version * Merge upstream * Bunch of new UI changes Too lazy to list them all in individual commits * Touch ripple for buttons and a few other things * Make the close button on the PluginGui work * Set button state to guiEnabled * Implement Connecting, NotConnected; add Header; don't update plugin button on render * Replace mapLerpColor with mapLerp * Update blendAlpha to be 0 without any values * Add ActionFillTransparency to Theme.Button * Suffix all Theme entries * Update Flipper * Add disconnect button * Remove cancel button * Add settings page * Add scrollbar and dark theme support to settings * Include settings in startSession * Set context default value to nil I always thought this was the name, lol... * Add Error page * Fix preloadAssets * Fix preloadAssets import * Update checkbox colors a little * Add setting descriptions * Fix scrolling frame in settings panel * Remove .vscode * Rename Throbber to Spinner * Update merge * Move Spinner images to assets * Change casing of directories * Remove old directories * Add comments to getDerivedStateFromProps * Account for offset in host TextBox size * Turn width variables into constants * Attempt to fix the comments * Add a missing comma in Settings * Remove a double space * Remove Dummy object * Move most of the Studio logic out of render * Don't truncate port input * Replace merge with Dictionary.merge * Replace "Got it!" with "Okay" * Add projectName to setStatus call * Add Flipper to build.rs --- .gitmodules | 5 +- build.rs | 3 + foreman.toml | 2 +- plugin/default.project.json | 3 + plugin/modules/flipper | 1 + .../src/App/Components/BorderedContainer.lua | 41 +++ plugin/src/App/Components/Checkbox.lua | 96 +++++++ plugin/src/App/Components/Header.lua | 55 ++++ plugin/src/App/Components/IconButton.lua | 79 ++++++ plugin/src/App/Components/ScrollingFrame.lua | 42 +++ plugin/src/App/Components/SlicedImage.lua | 29 +++ plugin/src/App/Components/Spinner.lua | 66 +++++ .../Components/Studio/StudioPluginContext.lua | 7 + .../App/Components/Studio/StudioPluginGui.lua | 84 ++++++ .../Components/Studio/StudioToggleButton.lua | 66 +++++ .../App/Components/Studio/StudioToolbar.lua | 45 ++++ .../Studio/StudioToolbarContext.lua | 7 + plugin/src/App/Components/TextButton.lua | 137 ++++++++++ plugin/src/App/Components/TouchRipple.lua | 145 +++++++++++ plugin/src/App/Page.lua | 70 +++++ .../{Components => App}/PluginSettings.lua | 0 plugin/src/App/StatusPages/Connected.lua | 125 +++++++++ plugin/src/App/StatusPages/Connecting.lua | 20 ++ plugin/src/App/StatusPages/Error.lua | 153 +++++++++++ plugin/src/App/StatusPages/NotConnected.lua | 154 +++++++++++ plugin/src/App/StatusPages/Settings.lua | 230 +++++++++++++++++ plugin/src/App/StatusPages/init.lua | 7 + plugin/src/App/Theme.lua | 239 +++++++++++++++++ plugin/src/App/bindingUtil.lua | 58 +++++ plugin/src/App/init.lua | 226 ++++++++++++++++ plugin/src/Assets.lua | 43 +++- plugin/src/Components/App.lua | 241 ------------------ plugin/src/Components/Checkbox.lua | 39 --- plugin/src/Components/ConnectPanel.lua | 183 ------------- plugin/src/Components/ConnectingPanel.lua | 35 --- .../src/Components/ConnectionActivePanel.lua | 47 ---- plugin/src/Components/ErrorPanel.lua | 70 ----- plugin/src/Components/FitList.lua | 63 ----- plugin/src/Components/FitScrollingFrame.lua | 33 --- plugin/src/Components/FitText.lua | 88 ------- plugin/src/Components/FormButton.lua | 64 ----- plugin/src/Components/FormTextInput.lua | 82 ------ plugin/src/Components/Panel.lua | 38 --- plugin/src/Components/RojoFooter.lua | 70 ----- plugin/src/Components/SettingsPanel.lua | 119 --------- plugin/src/Components/Theme.lua | 113 -------- plugin/src/ServeSession.lua | 2 +- plugin/src/init.server.lua | 15 +- plugin/src/preloadAssets.lua | 29 ++- 49 files changed, 2249 insertions(+), 1320 deletions(-) create mode 160000 plugin/modules/flipper create mode 100644 plugin/src/App/Components/BorderedContainer.lua create mode 100644 plugin/src/App/Components/Checkbox.lua create mode 100644 plugin/src/App/Components/Header.lua create mode 100644 plugin/src/App/Components/IconButton.lua create mode 100644 plugin/src/App/Components/ScrollingFrame.lua create mode 100644 plugin/src/App/Components/SlicedImage.lua create mode 100644 plugin/src/App/Components/Spinner.lua create mode 100644 plugin/src/App/Components/Studio/StudioPluginContext.lua create mode 100644 plugin/src/App/Components/Studio/StudioPluginGui.lua create mode 100644 plugin/src/App/Components/Studio/StudioToggleButton.lua create mode 100644 plugin/src/App/Components/Studio/StudioToolbar.lua create mode 100644 plugin/src/App/Components/Studio/StudioToolbarContext.lua create mode 100644 plugin/src/App/Components/TextButton.lua create mode 100644 plugin/src/App/Components/TouchRipple.lua create mode 100644 plugin/src/App/Page.lua rename plugin/src/{Components => App}/PluginSettings.lua (100%) create mode 100644 plugin/src/App/StatusPages/Connected.lua create mode 100644 plugin/src/App/StatusPages/Connecting.lua create mode 100644 plugin/src/App/StatusPages/Error.lua create mode 100644 plugin/src/App/StatusPages/NotConnected.lua create mode 100644 plugin/src/App/StatusPages/Settings.lua create mode 100644 plugin/src/App/StatusPages/init.lua create mode 100644 plugin/src/App/Theme.lua create mode 100644 plugin/src/App/bindingUtil.lua create mode 100644 plugin/src/App/init.lua delete mode 100644 plugin/src/Components/App.lua delete mode 100644 plugin/src/Components/Checkbox.lua delete mode 100644 plugin/src/Components/ConnectPanel.lua delete mode 100644 plugin/src/Components/ConnectingPanel.lua delete mode 100644 plugin/src/Components/ConnectionActivePanel.lua delete mode 100644 plugin/src/Components/ErrorPanel.lua delete mode 100644 plugin/src/Components/FitList.lua delete mode 100644 plugin/src/Components/FitScrollingFrame.lua delete mode 100644 plugin/src/Components/FitText.lua delete mode 100644 plugin/src/Components/FormButton.lua delete mode 100644 plugin/src/Components/FormTextInput.lua delete mode 100644 plugin/src/Components/Panel.lua delete mode 100644 plugin/src/Components/RojoFooter.lua delete mode 100644 plugin/src/Components/SettingsPanel.lua delete mode 100644 plugin/src/Components/Theme.lua diff --git a/.gitmodules b/.gitmodules index 90468044..98b1cb5e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -9,4 +9,7 @@ url = https://github.com/LPGhatguy/roblox-lua-promise.git [submodule "plugin/modules/t"] path = plugin/modules/t - url = https://github.com/osyrisrblx/t.git \ No newline at end of file + url = https://github.com/osyrisrblx/t.git +[submodule "plugin/modules/flipper"] + path = plugin/modules/flipper + url = https://github.com/Reselim/Flipper diff --git a/build.rs b/build.rs index 343c151a..fe2a840a 100644 --- a/build.rs +++ b/build.rs @@ -62,6 +62,9 @@ fn main() -> Result<(), anyhow::Error> { "t" => VfsSnapshot::dir(hashmap! { "lib" => snapshot_from_fs_path(&plugin_modules.join("t").join("lib"))? }), + "flipper" => VfsSnapshot::dir(hashmap! { + "src" => snapshot_from_fs_path(&plugin_modules.join("flipper").join("src"))? + }), }), }); diff --git a/foreman.toml b/foreman.toml index 53464e41..7fb33cb9 100644 --- a/foreman.toml +++ b/foreman.toml @@ -1,3 +1,3 @@ [tools] -rojo = { source = "rojo-rbx/rojo", version = "6.0.0-rc.1" } +rojo = { source = "rojo-rbx/rojo", version = "6.0.0-rc.3" } run-in-roblox = { source = "rojo-rbx/run-in-roblox", version = "0.3.0" } diff --git a/plugin/default.project.json b/plugin/default.project.json index c1a85c9b..bdaadab3 100644 --- a/plugin/default.project.json +++ b/plugin/default.project.json @@ -25,6 +25,9 @@ }, "t": { "$path": "modules/t/lib" + }, + "Flipper": { + "$path": "modules/flipper/src" } } } \ No newline at end of file diff --git a/plugin/modules/flipper b/plugin/modules/flipper new file mode 160000 index 00000000..4cf7a03c --- /dev/null +++ b/plugin/modules/flipper @@ -0,0 +1 @@ +Subproject commit 4cf7a03cb6776ec0af41b6a50988aa70e5c9cc3c diff --git a/plugin/src/App/Components/BorderedContainer.lua b/plugin/src/App/Components/BorderedContainer.lua new file mode 100644 index 00000000..78ceb426 --- /dev/null +++ b/plugin/src/App/Components/BorderedContainer.lua @@ -0,0 +1,41 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Theme = require(Plugin.App.Theme) +local Assets = require(Plugin.Assets) + +local SlicedImage = require(script.Parent.SlicedImage) + +local e = Roact.createElement + +local function BorderedContainer(props) + return Theme.with(function(theme) + return e(SlicedImage, { + slice = Assets.Slices.RoundedBackground, + color = theme.BorderedContainer.BackgroundColor, + transparency = props.transparency, + + size = props.size, + position = props.position, + anchorPoint = props.anchorPoint, + layoutOrder = props.layoutOrder, + }, { + Content = e("Frame", { + Size = UDim2.new(1, 0, 1, 0), + BackgroundTransparency = 1, + }, props[Roact.Children]), + + Border = e(SlicedImage, { + slice = Assets.Slices.RoundedBorder, + color = theme.BorderedContainer.BorderColor, + transparency = props.transparency, + + size = UDim2.new(1, 0, 1, 0), + }), + }) + end) +end + +return BorderedContainer \ No newline at end of file diff --git a/plugin/src/App/Components/Checkbox.lua b/plugin/src/App/Components/Checkbox.lua new file mode 100644 index 00000000..21c2c544 --- /dev/null +++ b/plugin/src/App/Components/Checkbox.lua @@ -0,0 +1,96 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) +local Flipper = require(Rojo.Flipper) + +local Assets = require(Plugin.Assets) +local Theme = require(Plugin.App.Theme) +local bindingUtil = require(Plugin.App.bindingUtil) + +local SlicedImage = require(script.Parent.SlicedImage) + +local e = Roact.createElement + +local Checkbox = Roact.Component:extend("Checkbox") + +function Checkbox:init() + self.motor = Flipper.SingleMotor.new(self.props.active and 1 or 0) + self.binding = bindingUtil.fromMotor(self.motor) +end + +function Checkbox:didUpdate(lastProps) + if lastProps.active ~= self.props.active then + self.motor:setGoal( + Flipper.Spring.new(self.props.active and 1 or 0, { + frequency = 6, + dampingRatio = 1.1, + }) + ) + end +end + +function Checkbox:render() + return Theme.with(function(theme) + theme = theme.Checkbox + + local activeTransparency = Roact.joinBindings({ + self.binding:map(function(value) + return 1 - value + end), + self.props.transparency, + }):map(bindingUtil.blendAlpha) + + return e("ImageButton", { + Size = UDim2.new(0, 28, 0, 28), + Position = self.props.position, + AnchorPoint = self.props.anchorPoint, + LayoutOrder = self.props.layoutOrder, + ZIndex = self.props.zIndex, + BackgroundTransparency = 1, + + [Roact.Event.Activated] = self.props.onClick, + }, { + Active = e(SlicedImage, { + slice = Assets.Slices.RoundedBackground, + color = theme.Active.BackgroundColor, + transparency = activeTransparency, + size = UDim2.new(1, 0, 1, 0), + zIndex = 2, + }, { + Icon = e("ImageLabel", { + Image = Assets.Images.Checkbox.Active, + ImageColor3 = theme.Active.IconColor, + ImageTransparency = activeTransparency, + + Size = UDim2.new(0, 16, 0, 16), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + + BackgroundTransparency = 1, + }), + }), + + Inactive = e(SlicedImage, { + slice = Assets.Slices.RoundedBorder, + color = theme.Inactive.BorderColor, + transparency = self.props.transparency, + size = UDim2.new(1, 0, 1, 0), + }, { + Icon = e("ImageLabel", { + Image = Assets.Images.Checkbox.Inactive, + ImageColor3 = theme.Inactive.IconColor, + ImageTransparency = self.props.transparency, + + Size = UDim2.new(0, 16, 0, 16), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + + BackgroundTransparency = 1, + }), + }), + }) + end) +end + +return Checkbox \ No newline at end of file diff --git a/plugin/src/App/Components/Header.lua b/plugin/src/App/Components/Header.lua new file mode 100644 index 00000000..fdc5e5d1 --- /dev/null +++ b/plugin/src/App/Components/Header.lua @@ -0,0 +1,55 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Theme = require(Plugin.App.Theme) +local Assets = require(Plugin.Assets) +local Config = require(Plugin.Config) +local Version = require(Plugin.Version) + +local e = Roact.createElement + +local function Header(props) + return Theme.with(function(theme) + return e("Frame", { + Size = UDim2.new(1, 0, 0, 32), + LayoutOrder = props.layoutOrder, + BackgroundTransparency = 1, + }, { + Logo = e("ImageLabel", { + Image = Assets.Images.Logo, + ImageColor3 = theme.Header.LogoColor, + ImageTransparency = props.transparency, + + Size = UDim2.new(0, 60, 0, 27), + + LayoutOrder = 1, + BackgroundTransparency = 1, + }), + + Version = e("TextLabel", { + Text = Version.display(Config.version), + Font = Enum.Font.Gotham, + TextSize = 14, + TextColor3 = theme.Header.VersionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = props.transparency, + + Size = UDim2.new(1, 0, 0, 14), + + LayoutOrder = 2, + BackgroundTransparency = 1, + }), + + Layout = e("UIListLayout", { + VerticalAlignment = Enum.VerticalAlignment.Center, + FillDirection = Enum.FillDirection.Horizontal, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 15), + }), + }) + end) +end + +return Header \ No newline at end of file diff --git a/plugin/src/App/Components/IconButton.lua b/plugin/src/App/Components/IconButton.lua new file mode 100644 index 00000000..388a1fe0 --- /dev/null +++ b/plugin/src/App/Components/IconButton.lua @@ -0,0 +1,79 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) +local Flipper = require(Rojo.Flipper) + +local Assets = require(Plugin.Assets) +local bindingUtil = require(Plugin.App.bindingUtil) + +local HOVER_SPRING_PROPS = { + frequency = 5, + dampingRatio = 1.1, +} + +local e = Roact.createElement + +local IconButton = Roact.Component:extend("IconButton") + +function IconButton:init() + self.motor = Flipper.SingleMotor.new(0) + self.binding = bindingUtil.fromMotor(self.motor) +end + +function IconButton:render() + local iconSize = self.props.iconSize + + return e("ImageButton", { + Size = UDim2.new(0, iconSize * 1.5, 0, iconSize * 1.5), + Position = self.props.position, + AnchorPoint = self.props.anchorPoint, + + LayoutOrder = self.props.layoutOrder, + ZIndex = self.props.zIndex, + BackgroundTransparency = 1, + + [Roact.Event.Activated] = self.props.onClick, + + [Roact.Event.MouseEnter] = function() + self.motor:setGoal( + Flipper.Spring.new(1, HOVER_SPRING_PROPS) + ) + end, + + [Roact.Event.MouseLeave] = function() + self.motor:setGoal( + Flipper.Spring.new(0, HOVER_SPRING_PROPS) + ) + end, + }, { + Icon = e("ImageLabel", { + Image = self.props.icon, + ImageColor3 = self.props.color, + ImageTransparency = self.props.transparency, + + Size = UDim2.new(0, iconSize, 0, iconSize), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + + BackgroundTransparency = 1, + }), + + HoverCircle = e("ImageLabel", { + Image = Assets.Images.Circles[128], + ImageColor3 = self.props.color, + ImageTransparency = Roact.joinBindings({ + hover = self.binding, + transparency = self.props.transparency, + }):map(function(values) + return bindingUtil.blendAlpha({ 0.85, 1 - values.hover, values.transparency }) + end), + + Size = UDim2.new(1, 0, 1, 0), + + BackgroundTransparency = 1, + }), + }) +end + +return IconButton \ No newline at end of file diff --git a/plugin/src/App/Components/ScrollingFrame.lua b/plugin/src/App/Components/ScrollingFrame.lua new file mode 100644 index 00000000..87d10226 --- /dev/null +++ b/plugin/src/App/Components/ScrollingFrame.lua @@ -0,0 +1,42 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Assets = require(Plugin.Assets) +local Theme = require(Plugin.App.Theme) +local bindingUtil = require(Plugin.App.bindingUtil) + +local e = Roact.createElement + +local function ScrollingFrame(props) + return Theme.with(function(theme) + return e("ScrollingFrame", { + ScrollBarThickness = 9, + ScrollBarImageColor3 = theme.ScrollBarColor, + ScrollBarImageTransparency = props.transparency:map(function(value) + return bindingUtil.blendAlpha({ 0.65, value }) + end), + TopImage = Assets.Images.ScrollBar.Top, + MidImage = Assets.Images.ScrollBar.Middle, + BottomImage = Assets.Images.ScrollBar.Bottom, + + ElasticBehavior = Enum.ElasticBehavior.Always, + ScrollingDirection = Enum.ScrollingDirection.Y, + + Size = props.size, + Position = props.position, + AnchorPoint = props.anchorPoint, + CanvasSize = props.contentSize:map(function(value) + return UDim2.new(0, 0, 0, value.Y) + end), + + BorderSizePixel = 0, + BackgroundTransparency = 1, + + [Roact.Change.AbsoluteSize] = props[Roact.Change.AbsoluteSize] + }, props[Roact.Children]) + end) +end + +return ScrollingFrame \ No newline at end of file diff --git a/plugin/src/App/Components/SlicedImage.lua b/plugin/src/App/Components/SlicedImage.lua new file mode 100644 index 00000000..8c03c877 --- /dev/null +++ b/plugin/src/App/Components/SlicedImage.lua @@ -0,0 +1,29 @@ +local Rojo = script:FindFirstAncestor("Rojo") + +local Roact = require(Rojo.Roact) + +local e = Roact.createElement + +local function SlicedImage(props) + local slice = props.slice + + return e("ImageLabel", { + Image = slice.Image, + ImageColor3 = props.color, + ImageTransparency = props.transparency, + + ScaleType = Enum.ScaleType.Slice, + SliceCenter = slice.Center, + SliceScale = slice.Scale, + + Size = props.size, + Position = props.position, + AnchorPoint = props.anchorPoint, + + ZIndex = props.zIndex, + LayoutOrder = props.layoutOrder, + BackgroundTransparency = 1, + }, props[Roact.Children]) +end + +return SlicedImage \ No newline at end of file diff --git a/plugin/src/App/Components/Spinner.lua b/plugin/src/App/Components/Spinner.lua new file mode 100644 index 00000000..562bd679 --- /dev/null +++ b/plugin/src/App/Components/Spinner.lua @@ -0,0 +1,66 @@ +local RunService = game:GetService("RunService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Theme = require(Plugin.App.Theme) +local Assets = require(Plugin.Assets) + +local ROTATIONS_PER_SECOND = 1.75 + +local e = Roact.createElement + +local Spinner = Roact.PureComponent:extend("Spinner") + +function Spinner:init() + self.rotation, self.setRotation = Roact.createBinding(0) +end + +function Spinner:render() + return Theme.with(function(theme) + return e("ImageLabel", { + Image = Assets.Images.Spinner.Background, + ImageColor3 = theme.Spinner.BackgroundColor, + ImageTransparency = self.props.transparency, + + Size = UDim2.new(0, 24, 0, 24), + Position = self.props.position, + AnchorPoint = self.props.anchorPoint, + + LayoutOrder = self.props.layoutOrder, + BackgroundTransparency = 1, + }, { + Foreground = e("ImageLabel", { + Image = Assets.Images.Spinner.Foreground, + ImageColor3 = theme.Spinner.ForegroundColor, + ImageTransparency = self.props.transparency, + + Size = UDim2.new(1, 0, 1, 0), + Rotation = self.rotation:map(function(value) + return value * 360 + end), + + BackgroundTransparency = 1, + }), + }) + end) +end + +function Spinner:didMount() + self.stepper = RunService.RenderStepped:Connect(function(deltaTime) + local rotation = self.rotation:getValue() + + rotation = rotation + deltaTime * ROTATIONS_PER_SECOND + rotation = rotation % 1 + + self.setRotation(rotation) + end) +end + +function Spinner:willUnmount() + self.stepper:Disconnect() +end + +return Spinner \ No newline at end of file diff --git a/plugin/src/App/Components/Studio/StudioPluginContext.lua b/plugin/src/App/Components/Studio/StudioPluginContext.lua new file mode 100644 index 00000000..978f628f --- /dev/null +++ b/plugin/src/App/Components/Studio/StudioPluginContext.lua @@ -0,0 +1,7 @@ +local Rojo = script:FindFirstAncestor("Rojo") + +local Roact = require(Rojo.Roact) + +local StudioPluginContext = Roact.createContext(nil) + +return StudioPluginContext \ No newline at end of file diff --git a/plugin/src/App/Components/Studio/StudioPluginGui.lua b/plugin/src/App/Components/Studio/StudioPluginGui.lua new file mode 100644 index 00000000..6bd37511 --- /dev/null +++ b/plugin/src/App/Components/Studio/StudioPluginGui.lua @@ -0,0 +1,84 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Dictionary = require(Plugin.Dictionary) + +local StudioPluginContext = require(script.Parent.StudioPluginContext) + +local e = Roact.createElement + +local StudioPluginGui = Roact.PureComponent:extend("StudioPluginGui") + +StudioPluginGui.defaultProps = { + initDockState = Enum.InitialDockState.Right, + active = false, + overridePreviousState = false, + floatingSize = Vector2.new(0, 0), + minimumSize = Vector2.new(0, 0), + zIndexBehavior = Enum.ZIndexBehavior.Sibling, +} + +function StudioPluginGui:init() + local floatingSize = self.props.floatingSize + local minimumSize = self.props.minimumSize + + local dockWidgetPluginGuiInfo = DockWidgetPluginGuiInfo.new( + self.props.initDockState, + self.props.active, + self.props.overridePreviousState, + floatingSize.X, floatingSize.Y, + minimumSize.X, minimumSize.Y + ) + + local pluginGui = self.props.plugin:CreateDockWidgetPluginGui(self.props.id, dockWidgetPluginGuiInfo) + + pluginGui.Name = self.props.id + pluginGui.Title = self.props.title + pluginGui.ZIndexBehavior = self.props.zIndexBehavior + + if self.props.onInitialState then + self.props.onInitialState(pluginGui.Enabled) + end + + pluginGui:BindToClose(function() + if self.props.onClose then + self.props.onClose() + else + pluginGui.Enabled = false + end + end) + + self.pluginGui = pluginGui +end + +function StudioPluginGui:render() + return e(Roact.Portal, { + target = self.pluginGui, + }, self.props[Roact.Children]) +end + +function StudioPluginGui:didUpdate(lastProps) + if self.props.active ~= lastProps.active then + -- This is intentionally in didUpdate to make sure the initial active state + -- (if the PluginGui is open initially) is preserved. + self.pluginGui.Enabled = self.props.active + end +end + +function StudioPluginGui:willUnmount() + self.pluginGui:Destroy() +end + +local function StudioPluginGuiWrapper(props) + return e(StudioPluginContext.Consumer, { + render = function(plugin) + return e(StudioPluginGui, Dictionary.merge(props, { + plugin = plugin, + })) + end, + }) +end + +return StudioPluginGuiWrapper \ No newline at end of file diff --git a/plugin/src/App/Components/Studio/StudioToggleButton.lua b/plugin/src/App/Components/Studio/StudioToggleButton.lua new file mode 100644 index 00000000..1970ff92 --- /dev/null +++ b/plugin/src/App/Components/Studio/StudioToggleButton.lua @@ -0,0 +1,66 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Dictionary = require(Plugin.Dictionary) + +local StudioToolbarContext = require(script.Parent.StudioToolbarContext) + +local e = Roact.createElement + +local StudioToggleButton = Roact.Component:extend("StudioToggleButton") + +StudioToggleButton.defaultProps = { + enabled = true, + active = false, +} + +function StudioToggleButton:init() + local button = self.props.toolbar:CreateButton( + self.props.name, + self.props.tooltip, + self.props.icon, + self.props.text + ) + + button.Click:Connect(function() + if self.props.onClick then + self.props.onClick() + end + end) + + button.ClickableWhenViewportHidden = true + + self.button = button +end + +function StudioToggleButton:render() + return nil +end + +function StudioToggleButton:didUpdate(lastProps) + if self.props.enabled ~= lastProps.enabled then + self.button.Enabled = self.props.enabled + end + + if self.props.active ~= lastProps.active then + self.button:SetActive(self.props.active) + end +end + +function StudioToggleButton:willUnmount() + self.button:Destroy() +end + +local function StudioToggleButtonWrapper(props) + return e(StudioToolbarContext.Consumer, { + render = function(toolbar) + return e(StudioToggleButton, Dictionary.merge(props, { + toolbar = toolbar, + })) + end, + }) +end + +return StudioToggleButtonWrapper \ No newline at end of file diff --git a/plugin/src/App/Components/Studio/StudioToolbar.lua b/plugin/src/App/Components/Studio/StudioToolbar.lua new file mode 100644 index 00000000..c03b20c0 --- /dev/null +++ b/plugin/src/App/Components/Studio/StudioToolbar.lua @@ -0,0 +1,45 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Dictionary = require(Plugin.Dictionary) + +local StudioToolbarContext = require(script.Parent.StudioToolbarContext) +local StudioPluginContext = require(script.Parent.StudioPluginContext) + +local e = Roact.createElement + +local StudioToolbar = Roact.Component:extend("StudioToolbar") + +function StudioToolbar:init() + self.toolbar = self.props.plugin:CreateToolbar(self.props.name) +end + +function StudioToolbar:render() + return e(StudioToolbarContext.Provider, { + value = self.toolbar, + }, self.props[Roact.Children]) +end + +function StudioToolbar:didUpdate(lastProps) + if self.props.name ~= lastProps.name then + self.toolbar.Name = self.props.name + end +end + +function StudioToolbar:willUnmount() + self.toolbar:Destroy() +end + +local function StudioToolbarWrapper(props) + return e(StudioPluginContext.Consumer, { + render = function(plugin) + return e(StudioToolbar, Dictionary.merge(props, { + plugin = plugin, + })) + end, + }) +end + +return StudioToolbarWrapper \ No newline at end of file diff --git a/plugin/src/App/Components/Studio/StudioToolbarContext.lua b/plugin/src/App/Components/Studio/StudioToolbarContext.lua new file mode 100644 index 00000000..925b7e0c --- /dev/null +++ b/plugin/src/App/Components/Studio/StudioToolbarContext.lua @@ -0,0 +1,7 @@ +local Rojo = script:FindFirstAncestor("Rojo") + +local Roact = require(Rojo.Roact) + +local StudioToolbarContext = Roact.createContext(nil) + +return StudioToolbarContext \ No newline at end of file diff --git a/plugin/src/App/Components/TextButton.lua b/plugin/src/App/Components/TextButton.lua new file mode 100644 index 00000000..e4e97e71 --- /dev/null +++ b/plugin/src/App/Components/TextButton.lua @@ -0,0 +1,137 @@ +local TextService = game:GetService("TextService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) +local Flipper = require(Rojo.Flipper) + +local Theme = require(Plugin.App.Theme) +local Assets = require(Plugin.Assets) +local bindingUtil = require(Plugin.App.bindingUtil) + +local SlicedImage = require(script.Parent.SlicedImage) +local TouchRipple = require(script.Parent.TouchRipple) + +local SPRING_PROPS = { + frequency = 5, + dampingRatio = 1, +} + +local e = Roact.createElement + +local TextButton = Roact.Component:extend("TextButton") + +function TextButton:init() + self.motor = Flipper.GroupMotor.new({ + hover = 0, + enabled = self.props.enabled and 1 or 0, + }) + self.binding = bindingUtil.fromMotor(self.motor) +end + +function TextButton:didUpdate(lastProps) + if lastProps.enabled ~= self.props.enabled then + self.motor:setGoal({ + enabled = Flipper.Spring.new(self.props.enabled and 1 or 0), + }) + end +end + +function TextButton:render() + return Theme.with(function(theme) + local textSize = TextService:GetTextSize( + self.props.text, 18, Enum.Font.GothamSemibold, + Vector2.new(math.huge, math.huge) + ) + + local style = self.props.style + + theme = theme.Button[style] + + local bindingHover = bindingUtil.deriveProperty(self.binding, "hover") + local bindingEnabled = bindingUtil.deriveProperty(self.binding, "enabled") + + return e("ImageButton", { + Size = UDim2.new(0, 15 + textSize.X + 15, 0, 34), + Position = self.props.position, + AnchorPoint = self.props.anchorPoint, + + LayoutOrder = self.props.layoutOrder, + BackgroundTransparency = 1, + + [Roact.Event.Activated] = self.props.onClick, + + [Roact.Event.MouseEnter] = function() + self.motor:setGoal({ + hover = Flipper.Spring.new(1, SPRING_PROPS), + }) + end, + + [Roact.Event.MouseLeave] = function() + self.motor:setGoal({ + hover = Flipper.Spring.new(0, SPRING_PROPS), + }) + end, + }, { + TouchRipple = e(TouchRipple, { + color = theme.ActionFillColor, + transparency = self.props.transparency:map(function(value) + return bindingUtil.blendAlpha({ theme.ActionFillTransparency, value }) + end), + zIndex = 2, + }), + + Text = e("TextLabel", { + Text = self.props.text, + Font = Enum.Font.GothamSemibold, + TextSize = 18, + TextColor3 = bindingUtil.mapLerp(bindingEnabled, theme.Enabled.TextColor, theme.Disabled.TextColor), + TextTransparency = self.props.transparency, + + Size = UDim2.new(1, 0, 1, 0), + + BackgroundTransparency = 1, + }), + + Border = style == "Bordered" and e(SlicedImage, { + slice = Assets.Slices.RoundedBorder, + color = bindingUtil.mapLerp(bindingEnabled, theme.Enabled.BorderColor, theme.Disabled.BorderColor), + transparency = self.props.transparency, + + size = UDim2.new(1, 0, 1, 0), + + zIndex = 0, + }), + + HoverOverlay = e(SlicedImage, { + slice = Assets.Slices.RoundedBackground, + color = theme.ActionFillColor, + transparency = Roact.joinBindings({ + hover = bindingHover:map(function(value) + return 1 - value + end), + transparency = self.props.transparency, + }):map(function(values) + return bindingUtil.blendAlpha({ theme.ActionFillTransparency, values.hover, values.transparency }) + end), + + size = UDim2.new(1, 0, 1, 0), + + zIndex = -1, + }), + + Background = style == "Solid" and e(SlicedImage, { + slice = Assets.Slices.RoundedBackground, + color = bindingUtil.mapLerp(bindingEnabled, theme.Enabled.BackgroundColor, theme.Disabled.BackgroundColor), + transparency = self.props.transparency, + + size = UDim2.new(1, 0, 1, 0), + + zIndex = -2, + }), + }) + end) +end + +return TextButton \ No newline at end of file diff --git a/plugin/src/App/Components/TouchRipple.lua b/plugin/src/App/Components/TouchRipple.lua new file mode 100644 index 00000000..955d0716 --- /dev/null +++ b/plugin/src/App/Components/TouchRipple.lua @@ -0,0 +1,145 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) +local Flipper = require(Rojo.Flipper) + +local Assets = require(Plugin.Assets) +local bindingUtil = require(Plugin.App.bindingUtil) + +local EXPAND_SPRING = { + frequency = 7, + dampingRatio = 2, +} + +local TouchRipple = Roact.Component:extend("TouchRipple") + +function TouchRipple:init() + self.ref = Roact.createRef() + + self.motor = Flipper.GroupMotor.new({ + scale = 0, + opacity = 0, + }) + self.binding = bindingUtil.fromMotor(self.motor) + + self.position, self.setPosition = Roact.createBinding( + Vector2.new(0, 0) + ) +end + +function TouchRipple:reset() + self.motor:setGoal({ + scale = Flipper.Instant.new(0), + opacity = Flipper.Instant.new(0), + }) + + -- Forces motor to update + self.motor:step(0) +end + +function TouchRipple:calculateRadius(position) + local container = self.ref.current + + if container then + local corner = Vector2.new( + math.floor((1 - position.X) + 0.5), + math.floor((1 - position.Y) + 0.5) + ) + + local size = container.AbsoluteSize + local ratio = size / math.min(size.X, size.Y) + + return ((corner * ratio) - (position * ratio)).Magnitude + else + return 0 + end +end + +function TouchRipple:render() + local scale = bindingUtil.deriveProperty(self.binding, "scale") + local transparency = bindingUtil.deriveProperty(self.binding, "opacity"):map(function(value) + return 1 - value + end) + + transparency = Roact.joinBindings({ + transparency, + self.props.transparency, + }):map(bindingUtil.blendAlpha) + + return Roact.createElement("Frame", { + ClipsDescendants = true, + Size = UDim2.new(1, 0, 1, 0), + ZIndex = self.props.zIndex, + BackgroundTransparency = 1, + + [Roact.Ref] = self.ref, + + [Roact.Event.InputBegan] = function(object, input) + if input.UserInputType == Enum.UserInputType.MouseButton1 then + self:reset() + + local position = Vector2.new(input.Position.X, input.Position.Y) + local relativePosition = (position - object.AbsolutePosition) / object.AbsoluteSize + + self.setPosition(relativePosition) + + self.motor:setGoal({ + scale = Flipper.Spring.new(1, EXPAND_SPRING), + opacity = Flipper.Spring.new(1, EXPAND_SPRING), + }) + + input:GetPropertyChangedSignal("UserInputState"):Connect(function() + local userInputState = input.UserInputState + + if + userInputState == Enum.UserInputState.Cancel + or userInputState == Enum.UserInputState.End + then + self.motor:setGoal({ + opacity = Flipper.Spring.new(0, { + frequency = 5, + dampingRatio = 1, + }), + }) + end + end) + end + end, + }, { + Circle = Roact.createElement("ImageLabel", { + Image = Assets.Images.Circles[500], + ImageColor3 = self.props.color, + ImageTransparency = transparency, + + Size = Roact.joinBindings({ + scale = scale, + position = self.position, + }):map(function(values) + local targetSize = self:calculateRadius(values.position) * 2 + local currentSize = targetSize * values.scale + + local container = self.ref.current + + if container then + local containerSize = container.AbsoluteSize + local containerAspect = containerSize.X / containerSize.Y + + return UDim2.new( + currentSize / math.max(containerAspect, 1), 0, + currentSize * math.min(containerAspect, 1), 0 + ) + end + end), + + Position = self.position:map(function(value) + return UDim2.new(value.X, 0, value.Y, 0) + end), + AnchorPoint = Vector2.new(0.5, 0.5), + + BackgroundTransparency = 1, + }), + }) +end + +return TouchRipple \ No newline at end of file diff --git a/plugin/src/App/Page.lua b/plugin/src/App/Page.lua new file mode 100644 index 00000000..99b5a942 --- /dev/null +++ b/plugin/src/App/Page.lua @@ -0,0 +1,70 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) +local Flipper = require(Rojo.Flipper) + +local Dictionary = require(Plugin.Dictionary) + +local bindingUtil = require(script.Parent.bindingUtil) + +local e = Roact.createElement + +local Page = Roact.Component:extend("Page") + +function Page:init() + self:setState({ + rendered = self.props.active + }) + + self.motor = Flipper.SingleMotor.new(self.props.active and 1 or 0) + self.binding = bindingUtil.fromMotor(self.motor) + + self.motor:onStep(function(value) + local rendered = value > 0 + + self:setState(function(state) + if state.rendered ~= rendered then + return { + rendered = rendered, + } + end + end) + end) +end + +function Page:render() + if not self.state.rendered then + return nil + end + + local transparency = self.binding:map(function(value) + return 1 - value + end) + + return e("Frame", { + Position = transparency:map(function(value) + value = self.props.active and value or -value + return UDim2.new(0, value * 30, 0, 0) + end), + Size = UDim2.new(1, 0, 1, 0), + BackgroundTransparency = 1, + }, { + Component = e(self.props.component, Dictionary.merge(self.props, { + transparency = transparency, + })) + }) +end + +function Page:didUpdate(lastProps) + if self.props.active ~= lastProps.active then + self.motor:setGoal( + Flipper.Spring.new(self.props.active and 1 or 0, { + frequency = 6, + dampingRatio = 1, + }) + ) + end +end + +return Page \ No newline at end of file diff --git a/plugin/src/Components/PluginSettings.lua b/plugin/src/App/PluginSettings.lua similarity index 100% rename from plugin/src/Components/PluginSettings.lua rename to plugin/src/App/PluginSettings.lua diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua new file mode 100644 index 00000000..5793c6ba --- /dev/null +++ b/plugin/src/App/StatusPages/Connected.lua @@ -0,0 +1,125 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Theme = require(Plugin.App.Theme) +local Assets = require(Plugin.Assets) + +local Header = require(Plugin.App.Components.Header) +local IconButton = require(Plugin.App.Components.IconButton) +local BorderedContainer = require(Plugin.App.Components.BorderedContainer) + +local e = Roact.createElement + +local function ConnectionDetails(props) + return Theme.with(function(theme) + return e(BorderedContainer, { + transparency = props.transparency, + size = UDim2.new(1, 0, 0, 70), + layoutOrder = props.layoutOrder, + }, { + TextContainer = e("Frame", { + Size = UDim2.new(1, 0, 1, 0), + BackgroundTransparency = 1 + }, { + ProjectName = e("TextLabel", { + Text = props.projectName, + Font = Enum.Font.GothamBold, + TextSize = 20, + TextColor3 = theme.ConnectionDetails.ProjectNameColor, + TextTransparency = props.transparency, + TextXAlignment = Enum.TextXAlignment.Left, + + Size = UDim2.new(1, 0, 0, 20), + + LayoutOrder = 1, + BackgroundTransparency = 1, + }), + + Address = e("TextLabel", { + Text = props.address, + Font = Enum.Font.Code, + TextSize = 15, + TextColor3 = theme.ConnectionDetails.AddressColor, + TextTransparency = props.transparency, + TextXAlignment = Enum.TextXAlignment.Left, + + Size = UDim2.new(1, 0, 0, 15), + + LayoutOrder = 2, + BackgroundTransparency = 1, + }), + + Layout = e("UIListLayout", { + VerticalAlignment = Enum.VerticalAlignment.Center, + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 6), + }), + }), + + Disconnect = e(IconButton, { + icon = Assets.Images.Icons.Close, + iconSize = 24, + color = theme.ConnectionDetails.DisconnectColor, + transparency = props.transparency, + + position = UDim2.new(1, 0, 0.5, 0), + anchorPoint = Vector2.new(1, 0.5), + + onClick = props.onDisconnect, + }), + + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 17), + PaddingRight = UDim.new(0, 15), + }), + }) + end) +end + +local ConnectedPage = Roact.Component:extend("ConnectedPage") + +function ConnectedPage:render() + return Roact.createFragment({ + Header = e(Header, { + transparency = self.props.transparency, + layoutOrder = 1, + }), + + ConnectionDetails = e(ConnectionDetails, { + projectName = self.state.projectName, + address = self.state.address, + transparency = self.props.transparency, + layoutOrder = 2, + + onDisconnect = self.props.onDisconnect, + }), + + Layout = e("UIListLayout", { + VerticalAlignment = Enum.VerticalAlignment.Center, + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 10), + }), + + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 20), + PaddingRight = UDim.new(0, 20), + }), + }) +end + +function ConnectedPage.getDerivedStateFromProps(props) + -- If projectName or address ever get removed from props, make sure we still have + -- the properties! The component still needs to have its data for it to be properly + -- animated out without the labels changing. + + return { + projectName = props.projectName, + address = props.address, + } +end + +return ConnectedPage \ No newline at end of file diff --git a/plugin/src/App/StatusPages/Connecting.lua b/plugin/src/App/StatusPages/Connecting.lua new file mode 100644 index 00000000..e45c3c53 --- /dev/null +++ b/plugin/src/App/StatusPages/Connecting.lua @@ -0,0 +1,20 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Spinner = require(Plugin.App.Components.Spinner) + +local e = Roact.createElement + +local ConnectingPage = Roact.Component:extend("ConnectingPage") + +function ConnectingPage:render() + return e(Spinner, { + position = UDim2.new(0.5, 0, 0.5, 0), + anchorPoint = Vector2.new(0.5, 0.5), + transparency = self.props.transparency, + }) +end + +return ConnectingPage \ No newline at end of file diff --git a/plugin/src/App/StatusPages/Error.lua b/plugin/src/App/StatusPages/Error.lua new file mode 100644 index 00000000..01ad1091 --- /dev/null +++ b/plugin/src/App/StatusPages/Error.lua @@ -0,0 +1,153 @@ +local TextService = game:GetService("TextService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Theme = require(Plugin.App.Theme) + +local TextButton = require(Plugin.App.Components.TextButton) +local BorderedContainer = require(Plugin.App.Components.BorderedContainer) +local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) + +local e = Roact.createElement + +local ERROR_PADDING = Vector2.new(13, 10) + +local Error = Roact.Component:extend("Error") + +function Error:init() + self.contentSize, self.setContentSize = Roact.createBinding(Vector2.new(0, 0)) +end + +function Error:render() + return e(BorderedContainer, { + size = Roact.joinBindings({ + containerSize = self.props.containerSize, + contentSize = self.contentSize, + }):map(function(values) + local maximumSize = values.containerSize + maximumSize -= Vector2.new(14, 14) * 2 -- Page padding + maximumSize -= Vector2.new(0, 34 + 10) -- Buttons and spacing + + local outerSize = values.contentSize + ERROR_PADDING * 2 + + return UDim2.new(1, 0, 0, math.min(outerSize.Y, maximumSize.Y)) + end), + transparency = self.props.transparency, + }, { + ScrollingFrame = e(ScrollingFrame, { + size = UDim2.new(1, 0, 1, 0), + contentSize = self.contentSize:map(function(value) + return value + ERROR_PADDING * 2 + end), + transparency = self.props.transparency, + + [Roact.Change.AbsoluteSize] = function(object) + local containerSize = object.AbsoluteSize - ERROR_PADDING * 2 + + local textBounds = TextService:GetTextSize( + self.props.errorMessage, 16, Enum.Font.Code, + Vector2.new(containerSize.X, math.huge) + ) + + self.setContentSize(Vector2.new(containerSize.X, textBounds.Y)) + end, + }, { + ErrorMessage = Theme.with(function(theme) + return e("TextLabel", { + Text = self.props.errorMessage, + Font = Enum.Font.Code, + TextSize = 16, + TextColor3 = theme.ErrorColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextYAlignment = Enum.TextYAlignment.Top, + TextTransparency = self.props.transparency, + TextWrapped = true, + + Size = UDim2.new(1, 0, 1, 0), + + BackgroundTransparency = 1, + }) + end), + + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, ERROR_PADDING.X), + PaddingRight = UDim.new(0, ERROR_PADDING.X), + PaddingTop = UDim.new(0, ERROR_PADDING.Y), + PaddingBottom = UDim.new(0, ERROR_PADDING.Y), + }), + }), + }) +end + +local ErrorPage = Roact.Component:extend("ErrorPage") + +function ErrorPage:init() + self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0)) +end + +function ErrorPage:render() + return Roact.createElement("Frame", { + Size = UDim2.new(1, 0, 1, 0), + BackgroundTransparency = 1, + + [Roact.Change.AbsoluteSize] = function(object) + self.setContainerSize(object.AbsoluteSize) + end, + }, { + Error = e(Error, { + errorMessage = self.state.errorMessage, + containerSize = self.containerSize, + transparency = self.props.transparency, + layoutOrder = 1, + }), + + Buttons = e("Frame", { + Size = UDim2.new(1, 0, 0, 35), + LayoutOrder = 2, + BackgroundTransparency = 1, + }, { + Close = e(TextButton, { + text = "Okay", + style = "Bordered", + transparency = self.props.transparency, + layoutOrder = 1, + onClick = self.props.onClose, + }), + + Layout = e("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Right, + FillDirection = Enum.FillDirection.Horizontal, + SortOrder = Enum.SortOrder.LayoutOrder, + }), + }), + + Layout = e("UIListLayout", { + VerticalAlignment = Enum.VerticalAlignment.Center, + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 10), + }), + + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 14), + PaddingRight = UDim.new(0, 14), + PaddingTop = UDim.new(0, 14), + PaddingBottom = UDim.new(0, 14), + }), + }) +end + +function ErrorPage.getDerivedStateFromProps(props) + -- If errorMessage ever gets removed from props, make sure we still have the + -- property! The component still needs to have its data for it to be properly + -- animated out without the labels changing. + + return { + errorMessage = props.errorMessage, + } +end + +return ErrorPage \ No newline at end of file diff --git a/plugin/src/App/StatusPages/NotConnected.lua b/plugin/src/App/StatusPages/NotConnected.lua new file mode 100644 index 00000000..10988424 --- /dev/null +++ b/plugin/src/App/StatusPages/NotConnected.lua @@ -0,0 +1,154 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Config = require(Plugin.Config) + +local Theme = require(Plugin.App.Theme) +local BorderedContainer = require(Plugin.App.Components.BorderedContainer) +local TextButton = require(Plugin.App.Components.TextButton) +local Header = require(Plugin.App.Components.Header) + +local PORT_WIDTH = 74 +local DIVIDER_WIDTH = 1 +local HOST_OFFSET = 12 + +local e = Roact.createElement + +local function AddressEntry(props) + return Theme.with(function(theme) + return e(BorderedContainer, { + transparency = props.transparency, + size = UDim2.new(1, 0, 0, 36), + layoutOrder = props.layoutOrder, + }, { + Host = e("TextBox", { + Text = "", + Font = Enum.Font.Code, + TextSize = 18, + TextColor3 = theme.AddressEntry.TextColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = props.transparency, + PlaceholderText = Config.defaultHost, + PlaceholderColor3 = theme.AddressEntry.PlaceholderColor, + + Size = UDim2.new(1, -(HOST_OFFSET + DIVIDER_WIDTH + PORT_WIDTH), 1, 0), + Position = UDim2.new(0, HOST_OFFSET, 0, 0), + + ClipsDescendants = true, + BackgroundTransparency = 1, + + [Roact.Ref] = props.hostRef, + }), + + Port = e("TextBox", { + Text = "", + Font = Enum.Font.Code, + TextSize = 18, + TextColor3 = theme.AddressEntry.TextColor, + TextTransparency = props.transparency, + PlaceholderText = Config.defaultPort, + PlaceholderColor3 = theme.AddressEntry.PlaceholderColor, + + Size = UDim2.new(0, PORT_WIDTH, 1, 0), + Position = UDim2.new(1, 0, 0, 0), + AnchorPoint = Vector2.new(1, 0), + + ClipsDescendants = true, + BackgroundTransparency = 1, + + [Roact.Ref] = props.portRef, + + [Roact.Change.Text] = function(object) + local text = object.Text + text = text:gsub("%D", "") + object.Text = text + end, + }, { + Divider = e("Frame", { + BackgroundColor3 = theme.BorderedContainer.BorderColor, + BackgroundTransparency = props.transparency, + Size = UDim2.new(0, DIVIDER_WIDTH, 1, 0), + AnchorPoint = Vector2.new(1, 0), + BorderSizePixel = 0, + }), + }), + }) + end) +end + +local NotConnectedPage = Roact.Component:extend("NotConnectedPage") + +function NotConnectedPage:init() + self.hostRef = Roact.createRef() + self.portRef = Roact.createRef() +end + +function NotConnectedPage:render() + return Roact.createFragment({ + Header = e(Header, { + transparency = self.props.transparency, + layoutOrder = 1, + }), + + AddressEntry = e(AddressEntry, { + hostRef = self.hostRef, + portRef = self.portRef, + transparency = self.props.transparency, + layoutOrder = 2, + }), + + Buttons = e("Frame", { + Size = UDim2.new(1, 0, 0, 34), + LayoutOrder = 3, + BackgroundTransparency = 1, + }, { + Settings = e(TextButton, { + text = "Settings", + style = "Bordered", + transparency = self.props.transparency, + layoutOrder = 1, + onClick = self.props.onNavigateSettings, + }), + + Connect = e(TextButton, { + text = "Connect", + style = "Solid", + transparency = self.props.transparency, + layoutOrder = 2, + onClick = function() + local hostText = self.hostRef.current.Text + local portText = self.portRef.current.Text + + self.props.onConnect( + #hostText > 0 and hostText or Config.defaultHost, + #portText > 0 and portText or Config.defaultPort + ) + end, + }), + + Layout = e("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Right, + FillDirection = Enum.FillDirection.Horizontal, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 10), + }), + }), + + Layout = e("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 10), + }), + + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 20), + PaddingRight = UDim.new(0, 20), + }), + }) +end + +return NotConnectedPage \ No newline at end of file diff --git a/plugin/src/App/StatusPages/Settings.lua b/plugin/src/App/StatusPages/Settings.lua new file mode 100644 index 00000000..1b933252 --- /dev/null +++ b/plugin/src/App/StatusPages/Settings.lua @@ -0,0 +1,230 @@ +local TextService = game:GetService("TextService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Assets = require(Plugin.Assets) +local Theme = require(Plugin.App.Theme) +local PluginSettings = require(Plugin.App.PluginSettings) + +local Checkbox = require(Plugin.App.Components.Checkbox) +local IconButton = require(Plugin.App.Components.IconButton) +local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) + +local e = Roact.createElement + +local DIVIDER_FADE_SIZE = 0.1 + +local function getTextBounds(text, textSize, font, lineHeight, bounds) + local textBounds = TextService:GetTextSize(text, textSize, font, bounds) + + local lineCount = textBounds.Y / textSize + local lineHeightAbsolute = textSize * lineHeight + + return Vector2.new(textBounds.X, lineHeightAbsolute * lineCount - (lineHeightAbsolute - textSize)) +end + +local function Navbar(props) + return Theme.with(function(theme) + theme = theme.Settings.Navbar + + return e("Frame", { + Size = UDim2.new(1, 0, 0, 46), + LayoutOrder = props.layoutOrder, + BackgroundTransparency = 1, + }, { + Back = e(IconButton, { + icon = Assets.Images.Icons.Back, + iconSize = 24, + color = theme.BackButtonColor, + transparency = props.transparency, + + position = UDim2.new(0, 0, 0.5, 0), + anchorPoint = Vector2.new(0, 0.5), + + onClick = props.onBack, + }), + + Text = e("TextLabel", { + Text = "Settings", + Font = Enum.Font.Gotham, + TextSize = 18, + TextColor3 = theme.TextColor, + TextTransparency = props.transparency, + + Size = UDim2.new(1, 0, 1, 0), + + BackgroundTransparency = 1, + }) + }) + end) +end + +local Setting = Roact.Component:extend("Setting") + +function Setting:init() + self.contentSize, self.setContentSize = Roact.createBinding(Vector2.new(0, 0)) + self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0)) +end + +function Setting:render() + return Theme.with(function(theme) + theme = theme.Settings + + return PluginSettings.with(function(settings) + return e("Frame", { + Size = self.contentSize:map(function(value) + return UDim2.new(1, 0, 0, 20 + value.Y + 20) + end), + LayoutOrder = self.props.layoutOrder, + BackgroundTransparency = 1, + + [Roact.Change.AbsoluteSize] = function(object) + self.setContainerSize(object.AbsoluteSize) + end, + }, { + Checkbox = e(Checkbox, { + active = settings:get(self.props.id), + transparency = self.props.transparency, + position = UDim2.new(1, 0, 0.5, 0), + anchorPoint = Vector2.new(1, 0.5), + onClick = function() + local currentValue = settings:get(self.props.id) + settings:set(self.props.id, not currentValue) + end, + }), + + Text = e("Frame", { + Size = UDim2.new(1, 0, 1, 0), + BackgroundTransparency = 1, + }, { + Name = e("TextLabel", { + Text = self.props.name, + Font = Enum.Font.GothamBold, + TextSize = 17, + TextColor3 = theme.Setting.NameColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = self.props.transparency, + + Size = UDim2.new(1, 0, 0, 17), + + LayoutOrder = 1, + BackgroundTransparency = 1, + }), + + Description = e("TextLabel", { + Text = self.props.description, + Font = Enum.Font.Gotham, + LineHeight = 1.2, + TextSize = 14, + TextColor3 = theme.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = self.props.transparency, + TextWrapped = true, + + Size = self.containerSize:map(function(value) + local textBounds = getTextBounds( + self.props.description, 14, Enum.Font.Gotham, 1.2, + Vector2.new(value.X - 50, math.huge) + ) + return UDim2.new(1, -50, 0, textBounds.Y) + end), + + LayoutOrder = 2, + BackgroundTransparency = 1, + }), + + Layout = e("UIListLayout", { + VerticalAlignment = Enum.VerticalAlignment.Center, + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 6), + + [Roact.Change.AbsoluteContentSize] = function(object) + self.setContentSize(object.AbsoluteContentSize) + end, + }), + + Padding = e("UIPadding", { + PaddingTop = UDim.new(0, 20), + PaddingBottom = UDim.new(0, 20), + }), + }), + + Divider = e("Frame", { + BackgroundColor3 = theme.DividerColor, + BackgroundTransparency = self.props.transparency, + Size = UDim2.new(1, 0, 0, 1), + BorderSizePixel = 0, + }, { + Gradient = e("UIGradient", { + Transparency = NumberSequence.new({ + NumberSequenceKeypoint.new(0, 1), + NumberSequenceKeypoint.new(DIVIDER_FADE_SIZE, 0), + NumberSequenceKeypoint.new(1 - DIVIDER_FADE_SIZE, 0), + NumberSequenceKeypoint.new(1, 1), + }), + }), + }), + }) + end) + end) +end + +local SettingsPage = Roact.Component:extend("SettingsPage") + +function SettingsPage:init() + self.contentSize, self.setContentSize = Roact.createBinding(Vector2.new(0, 0)) +end + +function SettingsPage:render() + return Theme.with(function(theme) + theme = theme.Settings + + return e(ScrollingFrame, { + size = UDim2.new(1, 0, 1, 0), + contentSize = self.contentSize, + transparency = self.props.transparency, + }, { + Navbar = e(Navbar, { + onBack = self.props.onBack, + transparency = self.props.transparency, + layoutOrder = 0, + }), + + OpenScriptsExternally = e(Setting, { + id = "openScriptsExternally", + name = "Open Scripts Externally", + description = "Attempt to open scripts in an external editor", + transparency = self.props.transparency, + layoutOrder = 1, + }), + + TwoWaySync = e(Setting, { + id = "twoWaySync", + name = "Two-Way Sync", + description = "Editing files in Studio will sync them into the filesystem", + transparency = self.props.transparency, + layoutOrder = 2, + }), + + Layout = e("UIListLayout", { + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + + [Roact.Change.AbsoluteContentSize] = function(object) + self.setContentSize(object.AbsoluteContentSize) + end, + }), + + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 20), + PaddingRight = UDim.new(0, 20), + }), + }) + end) +end + +return SettingsPage \ No newline at end of file diff --git a/plugin/src/App/StatusPages/init.lua b/plugin/src/App/StatusPages/init.lua new file mode 100644 index 00000000..03d64e45 --- /dev/null +++ b/plugin/src/App/StatusPages/init.lua @@ -0,0 +1,7 @@ +return { + NotConnected = require(script.NotConnected), + Settings = require(script.Settings), + Connecting = require(script.Connecting), + Connected = require(script.Connected), + Error = require(script.Error), +} \ No newline at end of file diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua new file mode 100644 index 00000000..2829cf4e --- /dev/null +++ b/plugin/src/App/Theme.lua @@ -0,0 +1,239 @@ +--[[ + Theming system taking advantage of Roact's new context API. + Doesn't use colors provided by Studio and instead just branches on theme + name. This isn't exactly best practice. +]] + +-- Studio does not exist outside Roblox Studio, so we'll lazily initialize it +-- when possible. +local _Studio +local function getStudio() + if _Studio == nil then + _Studio = settings():GetService("Studio") + end + + return _Studio +end + +local Rojo = script:FindFirstAncestor("Rojo") + +local Roact = require(Rojo.Roact) +local Log = require(Rojo.Log) + +local strict = require(script.Parent.Parent.strict) + +-- Copying hex colors back and forth from design programs is faster +local function hexColor(decimal) + local red = bit32.band(bit32.rshift(decimal, 16), 2^8 - 1) + local green = bit32.band(bit32.rshift(decimal, 8), 2^8 - 1) + local blue = bit32.band(decimal, 2^8 - 1) + + return Color3.fromRGB(red, green, blue) +end + +local BRAND_COLOR = hexColor(0xE13835) + +local lightTheme = strict("LightTheme", { + BackgroundColor = hexColor(0xF0F0F0), + Button = { + Solid = { + ActionFillColor = hexColor(0xFFFFFF), + ActionFillTransparency = 0.8, + Enabled = { + TextColor = hexColor(0xFFFFFF), + BackgroundColor = BRAND_COLOR, + }, + Disabled = { + TextColor = hexColor(0xFFFFFF), + BackgroundColor = BRAND_COLOR, + }, + }, + Bordered = { + ActionFillColor = hexColor(0x000000), + ActionFillTransparency = 0.9, + Enabled = { + TextColor = hexColor(0x393939), + BorderColor = hexColor(0xACACAC), + }, + Disabled = { + TextColor = hexColor(0x393939), + BorderColor = hexColor(0xACACAC), + }, + }, + }, + Checkbox = { + Active = { + IconColor = hexColor(0xFFFFFF), + BackgroundColor = BRAND_COLOR, + }, + Inactive = { + IconColor = hexColor(0xCACACA), + BorderColor = hexColor(0xAFAFAF), + }, + }, + AddressEntry = { + TextColor = hexColor(0x000000), + PlaceholderColor = hexColor(0x8C8C8C) + }, + BorderedContainer = { + BorderColor = hexColor(0xCBCBCB), + BackgroundColor = hexColor(0xE0E0E0), + }, + Spinner = { + ForegroundColor = BRAND_COLOR, + BackgroundColor = hexColor(0xE0E0E0), + }, + ConnectionDetails = { + ProjectNameColor = hexColor(0x00000), + AddressColor = hexColor(0x00000), + DisconnectColor = BRAND_COLOR, + }, + Settings = { + DividerColor = hexColor(0xCBCBCB), + Navbar = { + BackButtonColor = hexColor(0x000000), + TextColor = hexColor(0x000000), + }, + Setting = { + NameColor = hexColor(0x000000), + DescriptionColor = hexColor(0x5F5F5F), + }, + }, + Header = { + LogoColor = BRAND_COLOR, + VersionColor = hexColor(0x727272), + }, + ErrorColor = hexColor(0x000000), + ScrollBarColor = hexColor(0x000000), +}) + +local darkTheme = strict("DarkTheme", { + BackgroundColor = hexColor(0x272727), + Button = { + Solid = { + ActionFillColor = hexColor(0xFFFFFF), + ActionFillTransparency = 0.8, + Enabled = { + TextColor = hexColor(0xFFFFFF), + BackgroundColor = BRAND_COLOR, + }, + Disabled = { + TextColor = hexColor(0xFFFFFF), + BackgroundColor = BRAND_COLOR, + }, + }, + Bordered = { + ActionFillColor = hexColor(0xFFFFFF), + ActionFillTransparency = 0.9, + Enabled = { + TextColor = hexColor(0xDBDBDB), + BorderColor = hexColor(0x535353), + }, + Disabled = { + TextColor = hexColor(0xDBDBDB), + BorderColor = hexColor(0x535353), + }, + }, + }, + Checkbox = { + Active = { + IconColor = hexColor(0xFFFFFF), + BackgroundColor = BRAND_COLOR, + }, + Inactive = { + IconColor = hexColor(0x484848), + BorderColor = hexColor(0x5A5A5A), + }, + }, + AddressEntry = { + TextColor = hexColor(0xFFFFFF), + PlaceholderColor = hexColor(0x717171) + }, + BorderedContainer = { + BorderColor = hexColor(0x535353), + BackgroundColor = hexColor(0x323232), + }, + Spinner = { + ForegroundColor = BRAND_COLOR, + BackgroundColor = hexColor(0x323232), + }, + ConnectionDetails = { + ProjectNameColor = hexColor(0xFFFFFF), + AddressColor = hexColor(0xFFFFFF), + DisconnectColor = hexColor(0xFFFFFF), + }, + Settings = { + DividerColor = hexColor(0x535353), + Navbar = { + BackButtonColor = hexColor(0xFFFFFF), + TextColor = hexColor(0xFFFFFF), + }, + Setting = { + NameColor = hexColor(0xFFFFFF), + DescriptionColor = hexColor(0xD3D3D3), + }, + }, + Header = { + LogoColor = hexColor(0xFFFFFF), + VersionColor = hexColor(0xD3D3D3) + }, + ErrorColor = hexColor(0xFFFFFF), + ScrollBarColor = hexColor(0xFFFFFF), +}) + +local Context = Roact.createContext(lightTheme) + +local StudioProvider = Roact.Component:extend("StudioProvider") + +-- Pull the current theme from Roblox Studio and update state with it. +function StudioProvider:updateTheme() + local studioTheme = getStudio().Theme + + if studioTheme.Name == "Light" then + self:setState({ + theme = lightTheme, + }) + elseif studioTheme.Name == "Dark" then + self:setState({ + theme = darkTheme, + }) + else + Log.warn("Unexpected theme '{}'' -- falling back to light theme!", studioTheme.Name) + + self:setState({ + theme = lightTheme, + }) + end +end + +function StudioProvider:init() + self:updateTheme() +end + +function StudioProvider:render() + return Roact.createElement(Context.Provider, { + value = self.state.theme, + }, self.props[Roact.Children]) +end + +function StudioProvider:didMount() + self.connection = getStudio().ThemeChanged:Connect(function() + self:updateTheme() + end) +end + +function StudioProvider:willUnmount() + self.connection:Disconnect() +end + +local function with(callback) + return Roact.createElement(Context.Consumer, { + render = callback, + }) +end + +return { + StudioProvider = StudioProvider, + Consumer = Context.Consumer, + with = with, +} \ No newline at end of file diff --git a/plugin/src/App/bindingUtil.lua b/plugin/src/App/bindingUtil.lua new file mode 100644 index 00000000..daabd711 --- /dev/null +++ b/plugin/src/App/bindingUtil.lua @@ -0,0 +1,58 @@ +local Rojo = script:FindFirstAncestor("Rojo") + +local Roact = require(Rojo.Roact) +local Log = require(Rojo.Log) + +local LERP_DATA_TYPES = { + Color3 = true, + UDim = true, + UDim2 = true, + Vector2 = true, + Vector3 = true, +} + +local function fromMotor(motor) + local motorBinding, setMotorBinding = Roact.createBinding(motor:getValue()) + motor:onStep(setMotorBinding) + return motorBinding +end + +local function mapLerp(binding, value1, value2) + local valueType = typeof(value1) + if valueType ~= typeof(value2) then + Log.error("Type mismatch between values ({}, {}})", valueType, typeof(value2)) + end + + return binding:map(function(position) + if valueType == "number" then + return value1 - (value2 - value1) * position + elseif LERP_DATA_TYPES[valueType] then + return value1:lerp(value2, position) + else + Log.error("Unable to interpolate type {}", valueType) + end + end) +end + +local function deriveProperty(binding, propertyName) + return binding:map(function(values) + return values[propertyName] + end) +end + +local function blendAlpha(alphaValues) + local alpha = 0 + + for _, value in pairs(alphaValues) do + alpha = alpha + (1 - alpha) * value + end + + return alpha +end + +return { + fromMotor = fromMotor, + mapLerp = mapLerp, + deriveProperty = deriveProperty, + blendAlpha = blendAlpha, +} \ No newline at end of file diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua new file mode 100644 index 00000000..b4d01f5b --- /dev/null +++ b/plugin/src/App/init.lua @@ -0,0 +1,226 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) +local Log = require(Rojo.Log) + +local Assets = require(Plugin.Assets) +local Version = require(Plugin.Version) +local Config = require(Plugin.Config) +local strict = require(Plugin.strict) +local Dictionary = require(Plugin.Dictionary) +local ServeSession = require(Plugin.ServeSession) +local ApiContext = require(Plugin.ApiContext) +local preloadAssets = require(Plugin.preloadAssets) +local Theme = require(script.Theme) +local PluginSettings = require(script.PluginSettings) + +local Page = require(script.Page) +local StudioToolbar = require(script.Components.Studio.StudioToolbar) +local StudioToggleButton = require(script.Components.Studio.StudioToggleButton) +local StudioPluginGui = require(script.Components.Studio.StudioPluginGui) +local StudioPluginContext = require(script.Components.Studio.StudioPluginContext) +local StatusPages = require(script.StatusPages) + +local AppStatus = strict("AppStatus", { + NotConnected = "NotConnected", + Settings = "Settings", + Connecting = "Connecting", + Connected = "Connected", + Error = "Error", +}) + +local e = Roact.createElement + +local App = Roact.Component:extend("App") + +function App:init() + preloadAssets() + + self:setState({ + appStatus = AppStatus.NotConnected, + guiEnabled = false, + }) +end + +function App:startSession(host, port, sessionOptions) + local baseUrl = ("http://%s:%s"):format(host, port) + local apiContext = ApiContext.new(baseUrl) + + local serveSession = ServeSession.new({ + apiContext = apiContext, + openScriptsExternally = sessionOptions.openScriptsExternally, + twoWaySync = sessionOptions.twoWaySync, + }) + + serveSession:onStatusChanged(function(status, details) + if status == ServeSession.Status.Connecting then + self:setState({ + appStatus = AppStatus.Connecting, + }) + elseif status == ServeSession.Status.Connected then + local address = ("%s:%s"):format(host, port) + self:setState({ + appStatus = AppStatus.Connected, + projectName = details, + address = address, + }) + elseif status == ServeSession.Status.Disconnected then + self.serveSession = nil + + -- Details being present indicates that this + -- disconnection was from an error. + if details ~= nil then + Log.warn("Disconnected from an error: {}", details) + + self:setState({ + appStatus = AppStatus.Error, + errorMessage = tostring(details), + }) + else + self:setState({ + appStatus = AppStatus.NotConnected, + }) + end + end + end) + + serveSession:start() + + self.serveSession = serveSession +end + +function App:render() + local pluginName = "Rojo " .. Version.display(Config.version) + + local function createPageElement(appStatus, additionalProps) + additionalProps = additionalProps or {} + + local props = Dictionary.merge(additionalProps, { + component = StatusPages[appStatus], + active = self.state.appStatus == appStatus, + }) + + return e(Page, props) + end + + return e(StudioPluginContext.Provider, { + value = self.props.plugin, + }, { + e(Theme.StudioProvider, nil, { + e(PluginSettings.StudioProvider, { + plugin = self.props.plugin, + }, { + gui = e(StudioPluginGui, { + id = pluginName, + title = pluginName, + active = self.state.guiEnabled, + + initDockState = Enum.InitialDockState.Right, + initEnabled = false, + overridePreviousState = false, + floatingSize = Vector2.new(300, 200), + minimumSize = Vector2.new(300, 200), + + zIndexBehavior = Enum.ZIndexBehavior.Sibling, + + onInitialState = function(initialState) + self:setState({ + guiEnabled = initialState, + }) + end, + + onClose = function() + self:setState({ + guiEnabled = false, + }) + end, + }, { + NotConnectedPage = PluginSettings.with(function(settings) + return createPageElement(AppStatus.NotConnected, { + onConnect = function(host, port) + self:startSession(host, port, { + openScriptsExternally = settings:get("openScriptsExternally"), + twoWaySync = settings:get("twoWaySync"), + }) + end, + + onNavigateSettings = function() + self:setState({ + appStatus = AppStatus.Settings, + }) + end, + }) + end), + + Connecting = createPageElement(AppStatus.Connecting), + + Connected = createPageElement(AppStatus.Connected, { + projectName = self.state.projectName, + address = self.state.address, + + onDisconnect = function() + Log.trace("Disconnecting session") + + self.serveSession:stop() + self.serveSession = nil + self:setState({ + appStatus = AppStatus.NotConnected, + }) + + Log.trace("Session terminated by user") + end, + }), + + Settings = createPageElement(AppStatus.Settings, { + onBack = function() + self:setState({ + appStatus = AppStatus.NotConnected, + }) + end, + }), + + Error = createPageElement(AppStatus.Error, { + errorMessage = self.state.errorMessage, + + onClose = function() + self:setState({ + appStatus = AppStatus.NotConnected, + }) + end, + }), + + Background = Theme.with(function(theme) + return e("Frame", { + Size = UDim2.new(1, 0, 1, 0), + BackgroundColor3 = theme.BackgroundColor, + ZIndex = 0, + BorderSizePixel = 0, + }) + end), + }), + + toolbar = e(StudioToolbar, { + name = pluginName, + }, { + button = e(StudioToggleButton, { + name = "Rojo", + tooltip = "Show or hide the Rojo panel", + icon = Assets.Images.PluginButton, + active = self.state.guiEnabled, + enabled = true, + onClick = function() + self:setState(function(state) + return { + guiEnabled = not state.guiEnabled, + } + end) + end, + }) + }), + }), + }), + }) +end + +return App \ No newline at end of file diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index 86b8500c..beb4bad5 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -3,16 +3,45 @@ local strict = require(script.Parent.strict) local Assets = { Sprites = {}, Slices = { - RoundBox = { - asset = "rbxassetid://2773204550", - offset = Vector2.new(0, 0), - size = Vector2.new(32, 32), - center = Rect.new(4, 4, 4, 4), + RoundedBackground = { + Image = "rbxassetid://5981360418", + Center = Rect.new(10, 10, 10, 10), + Scale = 0.5, + }, + + RoundedBorder = { + Image = "rbxassetid://5981360137", + Center = Rect.new(10, 10, 10, 10), + Scale = 0.5, }, }, Images = { - Logo = "rbxassetid://3405346157", - Icon = "rbxassetid://3405341609", + Logo = "rbxassetid://5990772764", + PluginButton = "rbxassetid://3405341609", + Icons = { + Close = "rbxassetid://6012985953", + Back = "rbxassetid://6017213752", + }, + Checkbox = { + Active = "rbxassetid://6016251644", + Inactive = "rbxassetid://6016251963", + }, + Spinner = { + Foreground = "rbxassetid://3222731032", + Background = "rbxassetid://3222730627", + }, + ScrollBar = { + Top = "rbxassetid://6017290134", + Middle = "rbxassetid://6017289904", + Bottom = "rbxassetid://6017289712", + }, + Circles = { + [16] = "rbxassetid://3056541177", + [32] = "rbxassetid://3088713341", + [64] = "rbxassetid://4918677124", + [128] = "rbxassetid://2600845734", + [500] = "rbxassetid://2609138523" + }, }, StartSession = "", SessionActive = "", diff --git a/plugin/src/Components/App.lua b/plugin/src/Components/App.lua deleted file mode 100644 index 8a195235..00000000 --- a/plugin/src/Components/App.lua +++ /dev/null @@ -1,241 +0,0 @@ -local Rojo = script:FindFirstAncestor("Rojo") -local Plugin = Rojo.Plugin - -local Roact = require(Rojo.Roact) -local Log = require(Rojo.Log) - -local ApiContext = require(Plugin.ApiContext) -local Assets = require(Plugin.Assets) -local Config = require(Plugin.Config) -local DevSettings = require(Plugin.DevSettings) -local ServeSession = require(Plugin.ServeSession) -local Version = require(Plugin.Version) -local preloadAssets = require(Plugin.preloadAssets) -local strict = require(Plugin.strict) - -local ConnectPanel = require(Plugin.Components.ConnectPanel) -local ConnectingPanel = require(Plugin.Components.ConnectingPanel) -local ConnectionActivePanel = require(Plugin.Components.ConnectionActivePanel) -local ErrorPanel = require(Plugin.Components.ErrorPanel) -local SettingsPanel = require(Plugin.Components.SettingsPanel) - -local e = Roact.createElement - -local function showUpgradeMessage(lastVersion) - local message = ( - "Rojo detected an upgrade from version %s to version %s." .. - "\nMake sure you have also upgraded your server!" .. - "\n\nRojo plugin version %s is intended for use with server version %s." - ):format( - Version.display(lastVersion), Version.display(Config.version), - Version.display(Config.version), Config.expectedServerVersionString - ) - - Log.info(message) -end - ---[[ - Check if the user is using a newer version of Rojo than last time. If they - are, show them a reminder to make sure they check their server version. -]] -local function checkUpgrade(plugin) - -- When developing Rojo, there's no use in doing version checks - if DevSettings:isEnabled() then - return - end - - local lastVersion = plugin:GetSetting("LastRojoVersion") - - if lastVersion then - local wasUpgraded = Version.compare(Config.version, lastVersion) == 1 - - if wasUpgraded then - showUpgradeMessage(lastVersion) - end - end - - plugin:SetSetting("LastRojoVersion", Config.version) -end - -local AppStatus = strict("AppStatus", { - NotStarted = "NotStarted", - Connecting = "Connecting", - Connected = "Connected", - Error = "Error", - Settings = "Settings", -}) - -local App = Roact.Component:extend("App") - -function App:init() - self:setState({ - appStatus = AppStatus.NotStarted, - errorMessage = nil, - }) - - self.signals = {} - self.serveSession = nil - self.displayedVersion = Version.display(Config.version) - - local toolbar = self.props.plugin:CreateToolbar("Rojo " .. self.displayedVersion) - - self.toggleButton = toolbar:CreateButton( - "Rojo", - "Show or hide the Rojo panel", - Assets.Images.Icon) - self.toggleButton.ClickableWhenViewportHidden = true - self.toggleButton.Click:Connect(function() - self.dockWidget.Enabled = not self.dockWidget.Enabled - end) - - local widgetInfo = DockWidgetPluginGuiInfo.new( - Enum.InitialDockState.Right, - false, -- Initially enabled state - false, -- Whether to override the widget's previous state - 360, 190, -- Floating size - 360, 190 -- Minimum size - ) - - self.dockWidget = self.props.plugin:CreateDockWidgetPluginGui("Rojo-" .. self.displayedVersion, widgetInfo) - self.dockWidget.Name = "Rojo " .. self.displayedVersion - self.dockWidget.Title = "Rojo " .. self.displayedVersion - self.dockWidget.AutoLocalize = false - self.dockWidget.ZIndexBehavior = Enum.ZIndexBehavior.Sibling - - self.signals.dockWidgetEnabled = self.dockWidget:GetPropertyChangedSignal("Enabled"):Connect(function() - self.toggleButton:SetActive(self.dockWidget.Enabled) - end) -end - -function App:startSession(address, port, sessionOptions) - Log.trace("Starting new session") - - local baseUrl = ("http://%s:%s"):format(address, port) - self.serveSession = ServeSession.new({ - apiContext = ApiContext.new(baseUrl), - openScriptsExternally = sessionOptions.openScriptsExternally, - twoWaySync = sessionOptions.twoWaySync, - }) - - self.serveSession:onStatusChanged(function(status, details) - if status == ServeSession.Status.Connecting then - self:setState({ - appStatus = AppStatus.Connecting, - }) - elseif status == ServeSession.Status.Connected then - self:setState({ - appStatus = AppStatus.Connected, - }) - elseif status == ServeSession.Status.Disconnected then - self.serveSession = nil - - -- Details being present indicates that this - -- disconnection was from an error. - if details ~= nil then - Log.warn("Disconnected from an error: {}", details) - - self:setState({ - appStatus = AppStatus.Error, - errorMessage = tostring(details), - }) - else - self:setState({ - appStatus = AppStatus.NotStarted, - }) - end - end - end) - - self.serveSession:start() -end - -function App:render() - local children - - if self.state.appStatus == AppStatus.NotStarted then - children = { - ConnectPanel = e(ConnectPanel, { - startSession = function(address, port, settings) - self:startSession(address, port, settings) - end, - openSettings = function() - self:setState({ - appStatus = AppStatus.Settings, - }) - end, - cancel = function() - Log.trace("Canceling session configuration") - - self:setState({ - appStatus = AppStatus.NotStarted, - }) - end, - }), - } - elseif self.state.appStatus == AppStatus.Connecting then - children = { - ConnectingPanel = e(ConnectingPanel), - } - elseif self.state.appStatus == AppStatus.Connected then - children = { - ConnectionActivePanel = e(ConnectionActivePanel, { - stopSession = function() - Log.trace("Disconnecting session") - - self.serveSession:stop() - self.serveSession = nil - self:setState({ - appStatus = AppStatus.NotStarted, - }) - - Log.trace("Session terminated by user") - end, - }), - } - elseif self.state.appStatus == AppStatus.Settings then - children = { - e(SettingsPanel, { - back = function() - self:setState({ - appStatus = AppStatus.NotStarted, - }) - end, - }), - } - elseif self.state.appStatus == AppStatus.Error then - children = { - ErrorPanel = e(ErrorPanel, { - errorMessage = self.state.errorMessage, - onDismiss = function() - self:setState({ - appStatus = AppStatus.NotStarted, - }) - end, - }), - } - end - - return e(Roact.Portal, { - target = self.dockWidget, - }, children) -end - -function App:didMount() - Log.trace("Rojo {} initializing", self.displayedVersion) - - checkUpgrade(self.props.plugin) - preloadAssets() -end - -function App:willUnmount() - if self.serveSession ~= nil then - self.serveSession:stop() - self.serveSession = nil - end - - for _, signal in pairs(self.signals) do - signal:Disconnect() - end -end - -return App \ No newline at end of file diff --git a/plugin/src/Components/Checkbox.lua b/plugin/src/Components/Checkbox.lua deleted file mode 100644 index 0969b8e4..00000000 --- a/plugin/src/Components/Checkbox.lua +++ /dev/null @@ -1,39 +0,0 @@ -local Rojo = script:FindFirstAncestor("Rojo") -local Plugin = Rojo.Plugin - -local Roact = require(Rojo.Roact) - -local Theme = require(Plugin.Components.Theme) - -local e = Roact.createElement - -local function Checkbox(props) - local checked = props.checked - local layoutOrder = props.layoutOrder - local onChange = props.onChange - - return Theme.with(function(theme) - return e("ImageButton", { - LayoutOrder = layoutOrder, - Size = UDim2.new(0, 20, 0, 20), - BorderSizePixel = 2, - BorderColor3 = theme.Text2, - BackgroundColor3 = theme.Background2, - - [Roact.Event.Activated] = function() - onChange(not checked) - end, - }, { - Indicator = e("Frame", { - Size = UDim2.new(0, 18, 0, 18), - Position = UDim2.new(0.5, 0, 0.5, 0), - AnchorPoint = Vector2.new(0.5, 0.5), - BorderSizePixel = 0, - BackgroundColor3 = theme.Brand1, - BackgroundTransparency = checked and 0 or 1, - }) - }) - end) -end - -return Checkbox \ No newline at end of file diff --git a/plugin/src/Components/ConnectPanel.lua b/plugin/src/Components/ConnectPanel.lua deleted file mode 100644 index bebd67a6..00000000 --- a/plugin/src/Components/ConnectPanel.lua +++ /dev/null @@ -1,183 +0,0 @@ -local Rojo = script:FindFirstAncestor("Rojo") -local Plugin = Rojo.Plugin - -local Roact = require(Rojo.Roact) - -local Config = require(Plugin.Config) - -local Theme = require(Plugin.Components.Theme) -local Panel = require(Plugin.Components.Panel) -local FitList = require(Plugin.Components.FitList) -local FitText = require(Plugin.Components.FitText) -local FormButton = require(Plugin.Components.FormButton) -local FormTextInput = require(Plugin.Components.FormTextInput) -local PluginSettings = require(Plugin.Components.PluginSettings) - -local e = Roact.createElement - -local ConnectPanel = Roact.Component:extend("ConnectPanel") - -function ConnectPanel:init() - self:setState({ - address = "", - port = "", - }) -end - -function ConnectPanel:render() - local startSession = self.props.startSession - local openSettings = self.props.openSettings - - return Theme.with(function(theme) - return PluginSettings.with(function(settings) - return e(Panel, nil, { - Layout = e("UIListLayout", { - SortOrder = Enum.SortOrder.LayoutOrder, - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - }), - - Inputs = e(FitList, { - containerProps = { - BackgroundTransparency = 1, - LayoutOrder = 1, - }, - layoutProps = { - FillDirection = Enum.FillDirection.Horizontal, - Padding = UDim.new(0, 8), - }, - paddingProps = { - PaddingTop = UDim.new(0, 20), - PaddingBottom = UDim.new(0, 10), - PaddingLeft = UDim.new(0, 24), - PaddingRight = UDim.new(0, 24), - }, - }, { - Address = e(FitList, { - containerProps = { - LayoutOrder = 1, - BackgroundTransparency = 1, - }, - layoutProps = { - Padding = UDim.new(0, 4), - }, - }, { - Label = e(FitText, { - Kind = "TextLabel", - LayoutOrder = 1, - BackgroundTransparency = 1, - TextXAlignment = Enum.TextXAlignment.Left, - Font = theme.TitleFont, - TextSize = 20, - Text = "Address", - TextColor3 = theme.Text1, - }), - - Input = e(FormTextInput, { - layoutOrder = 2, - width = UDim.new(0, 220), - value = self.state.address, - placeholderValue = Config.defaultHost, - onValueChange = function(newValue) - self:setState({ - address = newValue, - }) - end, - }), - }), - - Port = e(FitList, { - containerProps = { - LayoutOrder = 2, - BackgroundTransparency = 1, - }, - layoutProps = { - Padding = UDim.new(0, 4), - }, - }, { - Label = e(FitText, { - Kind = "TextLabel", - LayoutOrder = 1, - BackgroundTransparency = 1, - TextXAlignment = Enum.TextXAlignment.Left, - Font = theme.TitleFont, - TextSize = 20, - Text = "Port", - TextColor3 = theme.Text1, - }), - - Input = e(FormTextInput, { - layoutOrder = 2, - width = UDim.new(0, 80), - value = self.state.port, - placeholderValue = Config.defaultPort, - onValueChange = function(newValue) - self:setState({ - port = newValue, - }) - end, - }), - }), - }), - - Buttons = e(FitList, { - fitAxes = "Y", - containerProps = { - BackgroundTransparency = 1, - LayoutOrder = 2, - Size = UDim2.new(1, 0, 0, 0), - }, - layoutProps = { - FillDirection = Enum.FillDirection.Horizontal, - HorizontalAlignment = Enum.HorizontalAlignment.Right, - Padding = UDim.new(0, 8), - }, - paddingProps = { - PaddingTop = UDim.new(0, 0), - PaddingBottom = UDim.new(0, 20), - PaddingLeft = UDim.new(0, 24), - PaddingRight = UDim.new(0, 24), - }, - }, { - e(FormButton, { - layoutOrder = 1, - text = "Settings", - secondary = true, - onClick = function() - if openSettings ~= nil then - openSettings() - end - end, - }), - - e(FormButton, { - layoutOrder = 2, - text = "Connect", - onClick = function() - if startSession ~= nil then - local address = self.state.address - if address:len() == 0 then - address = Config.defaultHost - end - - local port = self.state.port - if port:len() == 0 then - port = Config.defaultPort - end - - local sessionOptions = { - openScriptsExternally = settings:get("openScriptsExternally"), - twoWaySync = settings:get("twoWaySync"), - } - - startSession(address, port, sessionOptions) - end - end, - }), - }), - }) - end) - end) -end - -return ConnectPanel \ No newline at end of file diff --git a/plugin/src/Components/ConnectingPanel.lua b/plugin/src/Components/ConnectingPanel.lua deleted file mode 100644 index 9dd0c126..00000000 --- a/plugin/src/Components/ConnectingPanel.lua +++ /dev/null @@ -1,35 +0,0 @@ -local Roact = require(script:FindFirstAncestor("Rojo").Roact) - -local Plugin = script:FindFirstAncestor("Plugin") - -local Theme = require(Plugin.Components.Theme) -local Panel = require(Plugin.Components.Panel) -local FitText = require(Plugin.Components.FitText) - -local e = Roact.createElement - -local ConnectingPanel = Roact.Component:extend("ConnectingPanel") - -function ConnectingPanel:render() - return Theme.with(function(theme) - return e(Panel, nil, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 8), - }), - - Text = e(FitText, { - Padding = Vector2.new(12, 6), - Font = theme.ButtonFont, - TextSize = 18, - Text = "Connecting...", - TextColor3 = theme.Text1, - BackgroundTransparency = 1, - }), - }) - end) -end - -return ConnectingPanel \ No newline at end of file diff --git a/plugin/src/Components/ConnectionActivePanel.lua b/plugin/src/Components/ConnectionActivePanel.lua deleted file mode 100644 index 437589a9..00000000 --- a/plugin/src/Components/ConnectionActivePanel.lua +++ /dev/null @@ -1,47 +0,0 @@ -local Roact = require(script:FindFirstAncestor("Rojo").Roact) - -local Plugin = script:FindFirstAncestor("Plugin") - -local Theme = require(Plugin.Components.Theme) -local Panel = require(Plugin.Components.Panel) -local FitText = require(Plugin.Components.FitText) -local FormButton = require(Plugin.Components.FormButton) - -local e = Roact.createElement - -local ConnectionActivePanel = Roact.Component:extend("ConnectionActivePanel") - -function ConnectionActivePanel:render() - local stopSession = self.props.stopSession - - return Theme.with(function(theme) - return e(Panel, nil, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 8), - }), - - Text = e(FitText, { - Padding = Vector2.new(12, 6), - Font = theme.ButtonFont, - TextSize = 18, - Text = "Connected to Live-Sync Server", - TextColor3 = theme.Text1, - BackgroundTransparency = 1, - }), - - DisconnectButton = e(FormButton, { - layoutOrder = 2, - text = "Disconnect", - secondary = true, - onClick = function() - stopSession() - end, - }), - }) - end) -end - -return ConnectionActivePanel \ No newline at end of file diff --git a/plugin/src/Components/ErrorPanel.lua b/plugin/src/Components/ErrorPanel.lua deleted file mode 100644 index e541e0d8..00000000 --- a/plugin/src/Components/ErrorPanel.lua +++ /dev/null @@ -1,70 +0,0 @@ -local Roact = require(script:FindFirstAncestor("Rojo").Roact) - -local Plugin = script:FindFirstAncestor("Plugin") - -local Theme = require(Plugin.Components.Theme) -local Panel = require(Plugin.Components.Panel) -local FitText = require(Plugin.Components.FitText) -local FitScrollingFrame = require(Plugin.Components.FitScrollingFrame) -local FormButton = require(Plugin.Components.FormButton) - -local e = Roact.createElement - -local BUTTON_HEIGHT = 60 -local HOR_PADDING = 8 - -local ErrorPanel = Roact.Component:extend("ErrorPanel") - -function ErrorPanel:render() - local errorMessage = self.props.errorMessage - local onDismiss = self.props.onDismiss - - return Theme.with(function(theme) - return e(Panel, nil, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 8), - }), - - ErrorContainer = e(FitScrollingFrame, { - containerProps = { - BackgroundTransparency = 1, - BorderSizePixel = 0, - Size = UDim2.new(1, -HOR_PADDING * 2, 1, -BUTTON_HEIGHT), - Position = UDim2.new(0, HOR_PADDING, 0, 0), - ScrollBarImageColor3 = theme.Text1, - VerticalScrollBarInset = Enum.ScrollBarInset.ScrollBar, - ScrollingDirection = Enum.ScrollingDirection.Y, - }, - }, { - Text = e(FitText, { - Size = UDim2.new(1, 0, 0, 0), - - LayoutOrder = 1, - TextXAlignment = Enum.TextXAlignment.Left, - TextYAlignment = Enum.TextYAlignment.Top, - FitAxis = "Y", - Font = theme.ButtonFont, - TextSize = 18, - Text = errorMessage, - TextWrap = true, - TextColor3 = theme.Text1, - BackgroundTransparency = 1, - }), - }), - - DismissButton = e(FormButton, { - layoutOrder = 2, - text = "Dismiss", - secondary = true, - onClick = function() - onDismiss() - end, - }), - }) - end) -end - -return ErrorPanel \ No newline at end of file diff --git a/plugin/src/Components/FitList.lua b/plugin/src/Components/FitList.lua deleted file mode 100644 index e86e185a..00000000 --- a/plugin/src/Components/FitList.lua +++ /dev/null @@ -1,63 +0,0 @@ -local Roact = require(script:FindFirstAncestor("Rojo").Roact) - -local Dictionary = require(script.Parent.Parent.Dictionary) - -local e = Roact.createElement - -local FitList = Roact.Component:extend("FitList") - -function FitList:init() - self.sizeBinding, self.setSize = Roact.createBinding(UDim2.new()) -end - -function FitList:render() - local containerKind = self.props.containerKind or "Frame" - local fitAxes = self.props.fitAxes or "XY" - local containerProps = self.props.containerProps - local layoutProps = self.props.layoutProps - local paddingProps = self.props.paddingProps - - local padding - if paddingProps ~= nil then - padding = e("UIPadding", paddingProps) - end - - local children = Dictionary.merge(self.props[Roact.Children], { - ["$Layout"] = e("UIListLayout", Dictionary.merge({ - SortOrder = Enum.SortOrder.LayoutOrder, - [Roact.Change.AbsoluteContentSize] = function(instance) - local contentSize = instance.AbsoluteContentSize - - if paddingProps ~= nil then - contentSize = contentSize + Vector2.new( - paddingProps.PaddingLeft.Offset + paddingProps.PaddingRight.Offset, - paddingProps.PaddingTop.Offset + paddingProps.PaddingBottom.Offset) - end - - local combinedSize - - if fitAxes == "X" then - combinedSize = UDim2.new(0, contentSize.X, containerProps.Size.Y.Scale, containerProps.Size.Y.Offset) - elseif fitAxes == "Y" then - combinedSize = UDim2.new(containerProps.Size.X.Scale, containerProps.Size.X.Offset, 0, contentSize.Y) - elseif fitAxes == "XY" then - combinedSize = UDim2.new(0, contentSize.X, 0, contentSize.Y) - else - error("Invalid fitAxes value") - end - - self.setSize(combinedSize) - end, - }, layoutProps)), - - ["$Padding"] = padding, - }) - - local fullContainerProps = Dictionary.merge(containerProps, { - Size = self.sizeBinding, - }) - - return e(containerKind, fullContainerProps, children) -end - -return FitList \ No newline at end of file diff --git a/plugin/src/Components/FitScrollingFrame.lua b/plugin/src/Components/FitScrollingFrame.lua deleted file mode 100644 index ede927fd..00000000 --- a/plugin/src/Components/FitScrollingFrame.lua +++ /dev/null @@ -1,33 +0,0 @@ -local Roact = require(script:FindFirstAncestor("Rojo").Roact) - -local Dictionary = require(script.Parent.Parent.Dictionary) - -local e = Roact.createElement - -local FitScrollingFrame = Roact.Component:extend("FitScrollingFrame") - -function FitScrollingFrame:init() - self.sizeBinding, self.setSize = Roact.createBinding(UDim2.new()) -end - -function FitScrollingFrame:render() - local containerProps = self.props.containerProps - local layoutProps = self.props.layoutProps - - local children = Dictionary.merge(self.props[Roact.Children], { - ["$Layout"] = e("UIListLayout", Dictionary.merge({ - SortOrder = Enum.SortOrder.LayoutOrder, - [Roact.Change.AbsoluteContentSize] = function(instance) - self.setSize(UDim2.new(0, 0, 0, instance.AbsoluteContentSize.Y)) - end, - }, layoutProps)), - }) - - local fullContainerProps = Dictionary.merge(containerProps, { - CanvasSize = self.sizeBinding, - }) - - return e("ScrollingFrame", fullContainerProps, children) -end - -return FitScrollingFrame \ No newline at end of file diff --git a/plugin/src/Components/FitText.lua b/plugin/src/Components/FitText.lua deleted file mode 100644 index 1c036ba9..00000000 --- a/plugin/src/Components/FitText.lua +++ /dev/null @@ -1,88 +0,0 @@ -local TextService = game:GetService("TextService") - -local Roact = require(script:FindFirstAncestor("Rojo").Roact) - -local Dictionary = require(script.Parent.Parent.Dictionary) - -local e = Roact.createElement - -local FitText = Roact.Component:extend("FitText") - -function FitText:init() - self.ref = Roact.createRef() - self.sizeBinding, self.setSize = Roact.createBinding(UDim2.new()) -end - -function FitText:render() - local kind = self.props.Kind or "TextLabel" - - local containerProps = Dictionary.merge(self.props, { - FitAxis = Dictionary.None, - Kind = Dictionary.None, - Padding = Dictionary.None, - MinSize = Dictionary.None, - Size = self.sizeBinding, - [Roact.Ref] = self.ref, - [Roact.Change.AbsoluteSize] = function() - self:updateTextMeasurements() - end - }) - - return e(kind, containerProps) -end - -function FitText:didMount() - self:updateTextMeasurements() -end - -function FitText:didUpdate() - self:updateTextMeasurements() -end - -function FitText:updateTextMeasurements() - local minSize = self.props.MinSize or Vector2.new(0, 0) - local padding = self.props.Padding or Vector2.new(0, 0) - local fitAxis = self.props.FitAxis or "XY" - local baseSize = self.props.Size - - local text = self.props.Text or "" - local font = self.props.Font or Enum.Font.Legacy - local textSize = self.props.TextSize or 12 - - local containerSize = self.ref.current.AbsoluteSize - - local textBounds - - if fitAxis == "XY" then - textBounds = Vector2.new(9e6, 9e6) - elseif fitAxis == "X" then - textBounds = Vector2.new(9e6, containerSize.Y - padding.Y * 2) - elseif fitAxis == "Y" then - textBounds = Vector2.new(containerSize.X - padding.X * 2, 9e6) - end - - local measuredText = TextService:GetTextSize(text, textSize, font, textBounds) - - local computedX = math.max(minSize.X, padding.X * 2 + measuredText.X) - local computedY = math.max(minSize.Y, padding.Y * 2 + measuredText.Y) - - local totalSize - - if fitAxis == "XY" then - totalSize = UDim2.new( - 0, computedX, - 0, computedY) - elseif fitAxis == "X" then - totalSize = UDim2.new( - 0, computedX, - baseSize.Y.Scale, baseSize.Y.Offset) - elseif fitAxis == "Y" then - totalSize = UDim2.new( - baseSize.X.Scale, baseSize.X.Offset, - 0, computedY) - end - - self.setSize(totalSize) -end - -return FitText \ No newline at end of file diff --git a/plugin/src/Components/FormButton.lua b/plugin/src/Components/FormButton.lua deleted file mode 100644 index 7451395a..00000000 --- a/plugin/src/Components/FormButton.lua +++ /dev/null @@ -1,64 +0,0 @@ -local Rojo = script:FindFirstAncestor("Rojo") -local Plugin = Rojo.Plugin - -local Roact = require(Rojo.Roact) - -local Assets = require(Plugin.Assets) -local Theme = require(Plugin.Components.Theme) -local FitList = require(Plugin.Components.FitList) -local FitText = require(Plugin.Components.FitText) - -local e = Roact.createElement - -local RoundBox = Assets.Slices.RoundBox - -local function FormButton(props) - local text = props.text - local layoutOrder = props.layoutOrder - local onClick = props.onClick - - local textColor - local backgroundColor - - return Theme.with(function(theme) - if props.secondary then - textColor = theme.Brand1 - backgroundColor = theme.Background2 - else - textColor = theme.TextOnAccent - backgroundColor = theme.Brand1 - end - - return e(FitList, { - containerKind = "ImageButton", - containerProps = { - LayoutOrder = layoutOrder, - BackgroundTransparency = 1, - Image = RoundBox.asset, - ImageRectOffset = RoundBox.offset, - ImageRectSize = RoundBox.size, - SliceCenter = RoundBox.center, - ScaleType = Enum.ScaleType.Slice, - ImageColor3 = backgroundColor, - - [Roact.Event.Activated] = function() - if onClick ~= nil then - onClick() - end - end, - }, - }, { - Text = e(FitText, { - Kind = "TextLabel", - Text = text, - TextSize = 18, - TextColor3 = textColor, - Font = theme.ButtonFont, - Padding = Vector2.new(16, 8), - BackgroundTransparency = 1, - }), - }) - end) -end - -return FormButton \ No newline at end of file diff --git a/plugin/src/Components/FormTextInput.lua b/plugin/src/Components/FormTextInput.lua deleted file mode 100644 index f1f4625f..00000000 --- a/plugin/src/Components/FormTextInput.lua +++ /dev/null @@ -1,82 +0,0 @@ -local Rojo = script:FindFirstAncestor("Rojo") -local Plugin = Rojo.Plugin - -local Roact = require(Rojo.Roact) - -local Assets = require(Plugin.Assets) -local Theme = require(Plugin.Components.Theme) - -local e = Roact.createElement - -local RoundBox = Assets.Slices.RoundBox - -local TEXT_SIZE = 22 -local PADDING = 8 - -local FormTextInput = Roact.Component:extend("FormTextInput") - -function FormTextInput:init() - self:setState({ - focused = false, - }) -end - -function FormTextInput:render() - local value = self.props.value - local placeholderValue = self.props.placeholderValue - local onValueChange = self.props.onValueChange - local layoutOrder = self.props.layoutOrder - local width = self.props.width - - local shownPlaceholder - if self.state.focused then - shownPlaceholder = "" - else - shownPlaceholder = placeholderValue - end - - return Theme.with(function(theme) - return e("ImageLabel", { - LayoutOrder = layoutOrder, - Image = RoundBox.asset, - ImageRectOffset = RoundBox.offset, - ImageRectSize = RoundBox.size, - ScaleType = Enum.ScaleType.Slice, - SliceCenter = RoundBox.center, - ImageColor3 = theme.Background2, - Size = UDim2.new(width.Scale, width.Offset, 0, TEXT_SIZE + PADDING * 2), - BackgroundTransparency = 1, - }, { - InputInner = e("TextBox", { - BackgroundTransparency = 1, - Size = UDim2.new(1, -PADDING * 2, 1, -PADDING * 2), - Position = UDim2.new(0.5, 0, 0.5, 0), - AnchorPoint = Vector2.new(0.5, 0.5), - Font = theme.InputFont, - ClearTextOnFocus = false, - TextXAlignment = Enum.TextXAlignment.Center, - TextSize = TEXT_SIZE, - Text = value, - PlaceholderText = shownPlaceholder, - PlaceholderColor3 = theme.Text2, - TextColor3 = theme.Text1, - - [Roact.Change.Text] = function(rbx) - onValueChange(rbx.Text) - end, - [Roact.Event.Focused] = function() - self:setState({ - focused = true, - }) - end, - [Roact.Event.FocusLost] = function() - self:setState({ - focused = false, - }) - end, - }), - }) - end) -end - -return FormTextInput \ No newline at end of file diff --git a/plugin/src/Components/Panel.lua b/plugin/src/Components/Panel.lua deleted file mode 100644 index f1961702..00000000 --- a/plugin/src/Components/Panel.lua +++ /dev/null @@ -1,38 +0,0 @@ -local Roact = require(script:FindFirstAncestor("Rojo").Roact) - -local Plugin = script:FindFirstAncestor("Plugin") - -local RojoFooter = require(Plugin.Components.RojoFooter) -local Theme = require(Plugin.Components.Theme) - -local e = Roact.createElement - -local Panel = Roact.Component:extend("Panel") - -function Panel:init() - self.footerSize, self.setFooterSize = Roact.createBinding(Vector2.new()) -end - -function Panel:render() - return Theme.with(function(theme) - return e("Frame", { - Size = UDim2.new(1, 0, 1, 0), - BackgroundColor3 = theme.Background1, - BorderSizePixel = 1, - }, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - }), - - Body = e("Frame", { - Size = UDim2.new(0, 360, 1, -32), - BackgroundTransparency = 1, - }, self.props[Roact.Children]), - - Footer = e(RojoFooter), - }) - end) -end - -return Panel \ No newline at end of file diff --git a/plugin/src/Components/RojoFooter.lua b/plugin/src/Components/RojoFooter.lua deleted file mode 100644 index 3a32c610..00000000 --- a/plugin/src/Components/RojoFooter.lua +++ /dev/null @@ -1,70 +0,0 @@ -local Rojo = script:FindFirstAncestor("Rojo") -local Plugin = Rojo.Plugin - -local Roact = require(Rojo.Roact) - -local Config = require(Plugin.Config) -local Version = require(Plugin.Version) -local Assets = require(Plugin.Assets) -local Theme = require(Plugin.Components.Theme) - -local e = Roact.createElement - -local RojoFooter = Roact.Component:extend("RojoFooter") - -function RojoFooter:init() - self.footerSize, self.setFooterSize = Roact.createBinding(Vector2.new()) - self.footerVersionSize, self.setFooterVersionSize = Roact.createBinding(Vector2.new()) -end - -function RojoFooter:render() - return Theme.with(function(theme) - return e("Frame", { - LayoutOrder = 3, - Size = UDim2.new(1, 0, 0, 32), - BackgroundColor3 = theme.Background2, - BorderSizePixel = 0, - ZIndex = 2, - }, { - Padding = e("UIPadding", { - PaddingTop = UDim.new(0, 4), - PaddingBottom = UDim.new(0, 4), - PaddingLeft = UDim.new(0, 8), - PaddingRight = UDim.new(0, 8), - }), - - LogoContainer = e("Frame", { - BackgroundTransparency = 1, - - Size = UDim2.new(0, 0, 0, 32), - }, { - Logo = e("ImageLabel", { - Image = Assets.Images.Logo, - Size = UDim2.new(0, 80, 0, 40), - ScaleType = Enum.ScaleType.Fit, - BackgroundTransparency = 1, - Position = UDim2.new(0, 0, 1, -10), - AnchorPoint = Vector2.new(0, 1), - }), - }), - - Version = e("TextLabel", { - Position = UDim2.new(1, 0, 0, 0), - Size = UDim2.new(0, 0, 1, 0), - AnchorPoint = Vector2.new(1, 0), - Font = theme.TitleFont, - TextSize = 18, - Text = Version.display(Config.version), - TextXAlignment = Enum.TextXAlignment.Right, - TextColor3 = theme.Text2, - BackgroundTransparency = 1, - - [Roact.Change.AbsoluteSize] = function(rbx) - self.setFooterVersionSize(rbx.AbsoluteSize) - end, - }), - }) - end) -end - -return RojoFooter \ No newline at end of file diff --git a/plugin/src/Components/SettingsPanel.lua b/plugin/src/Components/SettingsPanel.lua deleted file mode 100644 index d385d05b..00000000 --- a/plugin/src/Components/SettingsPanel.lua +++ /dev/null @@ -1,119 +0,0 @@ -local Roact = require(script:FindFirstAncestor("Rojo").Roact) - -local Plugin = script:FindFirstAncestor("Plugin") - -local Checkbox = require(Plugin.Components.Checkbox) -local FitList = require(Plugin.Components.FitList) -local FitText = require(Plugin.Components.FitText) -local FormButton = require(Plugin.Components.FormButton) -local Panel = require(Plugin.Components.Panel) -local PluginSettings = require(Plugin.Components.PluginSettings) -local Theme = require(Plugin.Components.Theme) - -local e = Roact.createElement - -local SettingsPanel = Roact.Component:extend("SettingsPanel") - -function SettingsPanel:render() - local back = self.props.back - - return Theme.with(function(theme) - return PluginSettings.with(function(settings) - return e(Panel, nil, { - Layout = Roact.createElement("UIListLayout", { - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 16), - }), - - OpenScriptsExternally = e(FitList, { - containerProps = { - LayoutOrder = 1, - BackgroundTransparency = 1, - }, - layoutProps = { - Padding = UDim.new(0, 4), - FillDirection = Enum.FillDirection.Horizontal, - HorizontalAlignment = Enum.HorizontalAlignment.Left, - VerticalAlignment = Enum.VerticalAlignment.Center, - }, - }, { - Label = e(FitText, { - Kind = "TextLabel", - LayoutOrder = 1, - BackgroundTransparency = 1, - TextXAlignment = Enum.TextXAlignment.Left, - Font = theme.MainFont, - TextSize = 16, - Text = "Open Scripts Externally", - TextColor3 = theme.Text1, - }), - - Padding = e("Frame", { - Size = UDim2.new(0, 8, 0, 0), - BackgroundTransparency = 1, - LayoutOrder = 2, - }), - - Input = e(Checkbox, { - layoutOrder = 3, - checked = settings:get("openScriptsExternally"), - onChange = function(newValue) - settings:set("openScriptsExternally", not settings:get("openScriptsExternally")) - end, - }), - }), - - TwoWaySync = e(FitList, { - containerProps = { - LayoutOrder = 2, - BackgroundTransparency = 1, - }, - layoutProps = { - Padding = UDim.new(0, 4), - FillDirection = Enum.FillDirection.Horizontal, - HorizontalAlignment = Enum.HorizontalAlignment.Left, - VerticalAlignment = Enum.VerticalAlignment.Center, - }, - }, { - Label = e(FitText, { - Kind = "TextLabel", - LayoutOrder = 1, - BackgroundTransparency = 1, - TextXAlignment = Enum.TextXAlignment.Left, - Font = theme.MainFont, - TextSize = 16, - Text = "Two-Way Sync (Experimental!)", - TextColor3 = theme.Text1, - }), - - Padding = e("Frame", { - Size = UDim2.new(0, 8, 0, 0), - BackgroundTransparency = 1, - LayoutOrder = 2, - }), - - Input = e(Checkbox, { - layoutOrder = 3, - checked = settings:get("twoWaySync"), - onChange = function(newValue) - settings:set("twoWaySync", not settings:get("twoWaySync")) - end, - }), - }), - - BackButton = e(FormButton, { - layoutOrder = 4, - text = "Okay", - secondary = true, - onClick = function() - back() - end, - }), - }) - end) - end) -end - -return SettingsPanel \ No newline at end of file diff --git a/plugin/src/Components/Theme.lua b/plugin/src/Components/Theme.lua deleted file mode 100644 index c8ee810d..00000000 --- a/plugin/src/Components/Theme.lua +++ /dev/null @@ -1,113 +0,0 @@ ---[[ - Theming system taking advantage of Roact's new context API. - - Doesn't use colors provided by Studio and instead just branches on theme - name. This isn't exactly best practice. -]] - --- Studio does not exist outside Roblox Studio, so we'll lazily initialize it --- when possible. -local _Studio -local function getStudio() - if _Studio == nil then - _Studio = settings():GetService("Studio") - end - - return _Studio -end - -local Rojo = script:FindFirstAncestor("Rojo") - -local Roact = require(Rojo.Roact) -local Log = require(Rojo.Log) - -local strict = require(script.Parent.Parent.strict) - -local lightTheme = strict("Theme", { - ButtonFont = Enum.Font.GothamSemibold, - InputFont = Enum.Font.Code, - TitleFont = Enum.Font.GothamBold, - MainFont = Enum.Font.Gotham, - - Brand1 = Color3.fromRGB(225, 56, 53), - - Text1 = Color3.fromRGB(64, 64, 64), - Text2 = Color3.fromRGB(160, 160, 160), - TextOnAccent = Color3.fromRGB(235, 235, 235), - - Background1 = Color3.fromRGB(255, 255, 255), - Background2 = Color3.fromRGB(235, 235, 235), -}) - -local darkTheme = strict("Theme", { - ButtonFont = Enum.Font.GothamSemibold, - InputFont = Enum.Font.Code, - TitleFont = Enum.Font.GothamBold, - MainFont = Enum.Font.Gotham, - - Brand1 = Color3.fromRGB(225, 56, 53), - - Text1 = Color3.fromRGB(235, 235, 235), - Text2 = Color3.fromRGB(200, 200, 200), - TextOnAccent = Color3.fromRGB(235, 235, 235), - - Background1 = Color3.fromRGB(48, 48, 48), - Background2 = Color3.fromRGB(64, 64, 64), -}) - -local Context = Roact.createContext(lightTheme) - -local StudioProvider = Roact.Component:extend("StudioProvider") - --- Pull the current theme from Roblox Studio and update state with it. -function StudioProvider:updateTheme() - local studioTheme = getStudio().Theme - - if studioTheme.Name == "Light" then - self:setState({ - theme = lightTheme, - }) - elseif studioTheme.Name == "Dark" then - self:setState({ - theme = darkTheme, - }) - else - Log.warn("Unexpected theme '{}'' -- falling back to light theme!", studioTheme.Name) - - self:setState({ - theme = lightTheme, - }) - end -end - -function StudioProvider:init() - self:updateTheme() -end - -function StudioProvider:render() - return Roact.createElement(Context.Provider, { - value = self.state.theme, - }, self.props[Roact.Children]) -end - -function StudioProvider:didMount() - self.connection = getStudio().ThemeChanged:Connect(function() - self:updateTheme() - end) -end - -function StudioProvider:willUnmount() - self.connection:Disconnect() -end - -local function with(callback) - return Roact.createElement(Context.Consumer, { - render = callback, - }) -end - -return { - StudioProvider = StudioProvider, - Consumer = Context.Consumer, - with = with, -} \ No newline at end of file diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 4bbe726c..9e06065f 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -110,7 +110,7 @@ function ServeSession:start() self.__apiContext:connect() :andThen(function(serverInfo) - self:__setStatus(Status.Connected) + self:__setStatus(Status.Connected, serverInfo.projectName) local rootInstanceId = serverInfo.rootInstanceId diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index ca8d000f..79e2b51a 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -13,20 +13,11 @@ end) local Roact = require(script.Parent.Roact) local Config = require(script.Config) -local App = require(script.Components.App) -local Theme = require(script.Components.Theme) -local PluginSettings = require(script.Components.PluginSettings) +local App = require(script.App) -local app = Roact.createElement(Theme.StudioProvider, nil, { - Roact.createElement(PluginSettings.StudioProvider, { - plugin = plugin, - }, { - RojoUI = Roact.createElement(App, { - plugin = plugin, - }), - }) +local app = Roact.createElement(App, { + plugin = plugin }) - local tree = Roact.mount(app, nil, "Rojo UI") plugin.Unloading:Connect(function() diff --git a/plugin/src/preloadAssets.lua b/plugin/src/preloadAssets.lua index c23d2dd1..edbc37d7 100644 --- a/plugin/src/preloadAssets.lua +++ b/plugin/src/preloadAssets.lua @@ -4,20 +4,23 @@ local Log = require(script.Parent.Parent.Log) local Assets = require(script.Parent.Assets) +local gatherAssetUrlsRecursive +function gatherAssetUrlsRecursive(currentTable, currentUrls) + currentUrls = currentUrls or {} + + for _, value in pairs(currentTable) do + if typeof(value) == "string" then + table.insert(currentUrls, value) + elseif typeof(value) == "table" then + gatherAssetUrlsRecursive(value) + end + end + + return currentUrls +end + local function preloadAssets() - local contentUrls = {} - - for _, sprite in pairs(Assets.Sprites) do - table.insert(contentUrls, sprite.asset) - end - - for _, slice in pairs(Assets.Slices) do - table.insert(contentUrls, slice.asset) - end - - for _, url in pairs(Assets.Images) do - table.insert(contentUrls, url) - end + local contentUrls = gatherAssetUrlsRecursive(Assets) Log.trace("Preloading assets: {:?}", contentUrls) From f9110097524e7b8111e3373a4133a9a3538ec812 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Dec 2020 11:13:36 -0800 Subject: [PATCH 1088/1504] Remove clibrojo, as it's broken --- Cargo.lock | 7 ------- Cargo.toml | 7 ------- clibrojo/Cargo.toml | 13 ------------- clibrojo/README.md | 19 ------------------- clibrojo/src/lib.rs | 14 -------------- 5 files changed, 60 deletions(-) delete mode 100644 clibrojo/Cargo.toml delete mode 100644 clibrojo/README.md delete mode 100644 clibrojo/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index 4a27fa83..4a95ba9f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -240,13 +240,6 @@ dependencies = [ "vec_map", ] -[[package]] -name = "clibrojo" -version = "0.1.0" -dependencies = [ - "rojo", -] - [[package]] name = "cloudabi" version = "0.0.3" diff --git a/Cargo.toml b/Cargo.toml index 09411ee1..d04e4d9b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,13 +28,6 @@ dev_live_assets = [] [workspace] members = [ - "rojo-insta-ext", - "clibrojo", - "memofs", -] - -default-members = [ - ".", "rojo-insta-ext", "memofs", ] diff --git a/clibrojo/Cargo.toml b/clibrojo/Cargo.toml deleted file mode 100644 index 19420607..00000000 --- a/clibrojo/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "clibrojo" -version = "0.1.0" -authors = ["Lucien Greathouse "] -edition = "2018" - -[lib] -crate-type = ["cdylib"] - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -rojo = { path = ".." } diff --git a/clibrojo/README.md b/clibrojo/README.md deleted file mode 100644 index d8821ed9..00000000 --- a/clibrojo/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Rojo as a C Library -This is an experiment to expose a C API for Rojo that would be suitable for embedding it into an existing C/C++ application. - -I'm hoping to expand it to drop the HTTP layer and communicate through a channel, which could make it feasible to embed into an existing Roblox IDE with minimal changes or additional code. - -## Building -This project is currently not built by default and could break/disappear at any time. - -```bash -cargo build -p clibrojo -``` - -On Windows, Cargo will generate a `clibrojo.dll` and associated `.lib` file. Link these into your project. - -To generate the associated C header file to include in the project, use [cbindgen](https://github.com/eqrion/cbindgen): - -```bash -cbindgen --crate clibrojo --output include/rojo.h -``` \ No newline at end of file diff --git a/clibrojo/src/lib.rs b/clibrojo/src/lib.rs deleted file mode 100644 index 0c3dbbf7..00000000 --- a/clibrojo/src/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -use std::{ffi::CStr, os::raw::c_char, path::PathBuf}; - -use librojo::commands::{serve, ServeOptions}; - -#[no_mangle] -pub extern "C" fn rojo_serve(path: *const c_char) { - let path = unsafe { PathBuf::from(CStr::from_ptr(path).to_str().unwrap()) }; - - serve(&ServeOptions { - fuzzy_project_path: path, - port: None, - }) - .unwrap(); -} From dd667cce0b5bb0bee319b7775837515f7ee9a668 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Dec 2020 11:20:07 -0800 Subject: [PATCH 1089/1504] Add images from plugin rewrite --- assets/images/back.png | Bin 0 -> 229 bytes assets/images/back.svg | 5 +++++ assets/images/checkbox-off.png | Bin 0 -> 269 bytes assets/images/checkbox-off.svg | 15 +++++++++++++++ assets/images/checkbox-on.png | Bin 0 -> 249 bytes assets/images/checkbox-on.svg | 12 ++++++++++++ assets/images/circle-128.png | Bin 0 -> 1502 bytes assets/images/circle-16.png | Bin 0 -> 196 bytes assets/images/circle-32.png | Bin 0 -> 317 bytes assets/images/circle-500.png | Bin 0 -> 7471 bytes assets/images/circle-64.png | Bin 0 -> 613 bytes assets/images/close.png | Bin 0 -> 295 bytes assets/images/close.svg | 15 +++++++++++++++ assets/images/header-logo.png | Bin 0 -> 3061 bytes assets/images/header-logo.svg | 21 +++++++++++++++++++++ assets/images/rounded-background.png | Bin 0 -> 228 bytes assets/images/rounded-border.png | Bin 0 -> 315 bytes assets/images/scrollbar-bottom.png | Bin 0 -> 105 bytes assets/images/scrollbar-bottom.svg | 17 +++++++++++++++++ assets/images/scrollbar-middle.png | Bin 0 -> 75 bytes assets/images/scrollbar-middle.svg | 12 ++++++++++++ assets/images/scrollbar-top.png | Bin 0 -> 132 bytes assets/images/scrollbar-top.svg | 10 ++++++++++ assets/images/spinner-background.png | Bin 0 -> 684 bytes assets/images/spinner-background.svg | 8 ++++++++ assets/images/spinner-foreground.png | Bin 0 -> 340 bytes assets/images/spinner-foreground.svg | 8 ++++++++ 27 files changed, 123 insertions(+) create mode 100644 assets/images/back.png create mode 100644 assets/images/back.svg create mode 100644 assets/images/checkbox-off.png create mode 100644 assets/images/checkbox-off.svg create mode 100644 assets/images/checkbox-on.png create mode 100644 assets/images/checkbox-on.svg create mode 100644 assets/images/circle-128.png create mode 100644 assets/images/circle-16.png create mode 100644 assets/images/circle-32.png create mode 100644 assets/images/circle-500.png create mode 100644 assets/images/circle-64.png create mode 100644 assets/images/close.png create mode 100644 assets/images/close.svg create mode 100644 assets/images/header-logo.png create mode 100644 assets/images/header-logo.svg create mode 100644 assets/images/rounded-background.png create mode 100644 assets/images/rounded-border.png create mode 100644 assets/images/scrollbar-bottom.png create mode 100644 assets/images/scrollbar-bottom.svg create mode 100644 assets/images/scrollbar-middle.png create mode 100644 assets/images/scrollbar-middle.svg create mode 100644 assets/images/scrollbar-top.png create mode 100644 assets/images/scrollbar-top.svg create mode 100644 assets/images/spinner-background.png create mode 100644 assets/images/spinner-background.svg create mode 100644 assets/images/spinner-foreground.png create mode 100644 assets/images/spinner-foreground.svg diff --git a/assets/images/back.png b/assets/images/back.png new file mode 100644 index 0000000000000000000000000000000000000000..907e793f87058e5a55b6908ff933be6b08343f5c GIT binary patch literal 229 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUtHJ&bxAr-gY-rUXGV8G*gk>^-S z$eS|^Y%b2uf=M~gUnwr#@BV1=jI^}eXIEJS92gi`R`5ie+j@>`$D{Jy>vPQx7~lKn z;&RlVnWOhRTg&lkrl3cA88Sc0HC*`-=uq{CV}Z+`aEF;c^c#Xc?rkXgXxp&;M@P2A z1WA2{M`BJkM>?)+JaTTk;iX_!-0{}rkwddZkP_e5j*VPN8(JlFmD+Z9eBAZ#0*68a d1Jjjw_PI%K*WEZ)X$o{VgQu&X%Q~loCICS(T^axY literal 0 HcmV?d00001 diff --git a/assets/images/back.svg b/assets/images/back.svg new file mode 100644 index 00000000..427aff3c --- /dev/null +++ b/assets/images/back.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/assets/images/checkbox-off.png b/assets/images/checkbox-off.png new file mode 100644 index 0000000000000000000000000000000000000000..55e53d187d9a69e33d5e247ebc6fd5fa618d9500 GIT binary patch literal 269 zcmV+o0rLKdP)>Hzf8YqCA#Mfv`FJR+q^NRRI&cgX9z$4<0{3KxId((<|B0oJrnK&>jf+l^HUV!Ex z1(4I2h7lr6XH$?Pv+#(kbUmFnn5w`WHxUu-%ABa2Hm7Z5VKEghZE39& + + + + + + + + + + + + + + diff --git a/assets/images/checkbox-on.png b/assets/images/checkbox-on.png new file mode 100644 index 0000000000000000000000000000000000000000..bc0e8a0b66cabff09498cf2a58b7f8756d2bbadb GIT binary patch literal 249 zcmVH`!BF?g;KwMwwzrB29|XoA;TF;$`&PMHNY zi7q&G8093o;hbq`;sfFyRy%W8t!McX_^-eTqD|PFCS7~s00000NkvXXu0mjf0{UU0 literal 0 HcmV?d00001 diff --git a/assets/images/checkbox-on.svg b/assets/images/checkbox-on.svg new file mode 100644 index 00000000..24ae73d9 --- /dev/null +++ b/assets/images/checkbox-on.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/images/circle-128.png b/assets/images/circle-128.png new file mode 100644 index 0000000000000000000000000000000000000000..aca1b0e12f802f6529e6159d77851b3f399e0e12 GIT binary patch literal 1502 zcmV<41tI#0P)keJzB6<0J>O6I8U*(EJ0G5z`{zu_7*h&R)1*1lYtlODBWaKH ziF88xM!Fzfi!S76C-OUc@;B@98gufR!Fd(Jhj>JKMS4g2i*#nP<4oRz-)l+U8v)2! zWztL18mUFPF~xBs$FL^HR7L=@(NFR<{GQY`?$VWGtjRGW028W8dPDkR{G%hsUPS=X z>p5xLgu}LcCIn!FUXXT8xbSD2M*#Y@KsqpbIFQe*J^-_Fzpa&qc%Uu-4@tj~E)8H0 zR>cz)0pN3B8+GraUBvZ4o^SR*hE~CF>f%*U0eC7ys2~}K;#m*@;4$-a)HF5c;+?kv zn8H`S71qT|uL8i6BAck4H9nY(CYrLEp4~&utkWb_To1qu=`(7T8Asx=lL2^UZfC$i zwsgd6rvfm8;^!WMC$0pbB414)|I zdfow8g6Gb$m{$OJk^*DvAATMDP7F!xyzwRIhBm_zVhpVv@3alAI#eh0IyfW zGA@5OPI@Xx8h}-J>K!Y#0>D@OSiS2Xmr3plk_6x*y!4jFqycyd54~q$k^mgQKkwNe zHvli-UHG?!!ve4i--2N$Z2+Fbv*7qSO#rsxS8!}44L}uM1xqza0N%i-VEKJi0JyW& z7x)w`9n;gjtTzC2@F;j{!vgRg{shk-_XU8L7kA-L@N`XVDLKadb+Rxh0Bi6?4Q~ep zpaoyl@ON(jcu)Tgd{M)-)ci*PUcnP}EX4!x4t}U(BOU;3_Rz;+JOF3#Lmj740H)!E zS{`HkUpF-lz-#!RmSt@C)J+{5KXlXJ0HDc}UYZ<$Pw+u4Ee^m5d{9f91Mm$#sO2jM z-~v9VrON@hf)8rBLI4l|oC36;0&o$i{2~yyfy!?KF%YDe7KVa#)5K(uZW@>l)=eD? zLUgl?C1JX$VNs}V9%EU!UVbbK$Howy+}Rj{tzr7Ovo#ExL-lcIb11fl>!NRaI2uIg zqOU;&TEysLV2cVUhZ=ajbdx77V`{JUUh_V?R2UwE+LT zXQGEkW8;Y5O#JwG)-34~UV6u+)NbMcuvX!xcdR6-ZPEZdB(>qGHyo25*bD$}3;p3g zsa45#0I-qN59(=Znl=FZwSr9~?sAy)tAE@8u%436;k9#oPjc07BLJ)=`0X5vKs{x4bK-yPS_pmUdHXsxW}E#%`CfejK7$kZd?d}-H9f?fZ~3) z-1PXmz=B`PF}#&yD*NWAj{)e_Bbjg5kRjC53=4iL@3A4{^cCOz3n2i5G%cr$Wpg_t z$zu&XpWc#D$glEseI@G3&)V`kP5GO;yhcr4GdQpQ2dYy}1X+(`>;M1&07*qoM6N<$ Eg6tT<%>V!Z literal 0 HcmV?d00001 diff --git a/assets/images/circle-16.png b/assets/images/circle-16.png new file mode 100644 index 0000000000000000000000000000000000000000..a87ce0ed93cc6a9f9e1928615ea6fceed536830c GIT binary patch literal 196 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`-JULvAr-gQ2H)mwP~gdtX#0AE zwM4zQZ;AAablsDtjx`GosD5|M6#7dDfNuf(5W=q^JQ10delL0|h8Lqtlw-Id87*0b zv}ABodbBNXLTvewjY)!P%^q7?vr9CmQ|)=GwWIWvOwDYs&!v7#*R)`76k&61X2R^&bWzfTq!=cla@!2q z8HTotCbyZ;$bG9B-tIL9%`p7lM7l@2!=yU|?tJ!$oui$12~ z>*s>k<{z!kNeeTY_N-Ga$1|3?gkufb>rJh<*NrMB9EXkySyKhq`+iY%e&krN&DyN) z=eh&@2BwluBhSp6M`swYmR2!ich*fDJ2M)~g!4F;wWc9yZA8eUd!3nuKcbPeU+WAK zVz@0#Y5=~hb%lX74&*hUbNi$3rs+InyUONCYrh?jcMemf>GOYo<5Jepw7-^Tjg3|M zi{*l(AF@ikz?CM+Yxj@G8#`89!pC7kr(+fdO*>gH$;hLS_DWYhvq`%{+sb8Ee`UkM zg>=gfKJ|XoSf*YQ>7X`dB7QOM+6+7Y%>b!*BvOdpbt>!zO6_d=xQm0PFr7Qcj7$6Y zYtsT%oSx1}oWa8#@+L}{J4o|xYmcW-Ot&=4bu;lV2Yw`)_&JTcb!S&q4~mcOcgtUT zZA@C=hn|meq1@>ErMAP-);sutgI~O*VbcTT7>C7j2_JR>(zG5YChA_>u1U}|NVaLAgp=TBj`jqYd&s&$0rrb3F@c8prerA zbZ4ef_UfDAEBnjL6Pz8)qps>DJ@Fnz3RAc{64l%G6cxm~-m-Lep>+Ig-m1QqH5xK* z=G9(v@$UEo!-wp$V)S-2M)sgjRR^ZC>L;R!y{BmPdwf?gbYpDX9J6!{m0!afAuWy@ zD!AC-xw9qkRl=1L3Yz6HXL`Yi>mK1is*w=IN+%C+K>!|!^{H5sc(M-!~7hkoi^DKwdFTsw=-+)P8ZP z%ZX^R^$@-MTL-D4)9OrF1z+L!$VycHpNR?F&;^Cf%iMx+OM@hRJu1I(@FH1byMEW@ z`GC3Kf*?N^hi%x-;Z1E{kCRoR%2E01dl|=1Wm(JId^OeXc@|0Un=kxJuJdL_p-pK&;<@}T`ce0Iw{36 zscoGBP*17RExT9_NV^?+h{_y>1!7iSSWF9${@t6GIE@IQ-;p6*?L>wXcC}NPUV)I= z9~wW>e&OFiZ|ZyDiQTIi?qHZSX%~O%oS7p*eJ~f3i>_uzI-OYrwlHwUqv<=(i1rT?m?lo~#aFwP3){b=@ zMnFA0hO3RLY4V~3hwj*rM>CnA1R0C z|8yK04uZT_u|gurzWZ0UHl9DzD~(|6ul=3zk|ulNTmUcc8G`Zk(ay}c zXG;FPQk_)mS77~j3^~gNMN!KUlHL}E5c&^M&y&f%&>n6lGXUfgrj?qHanz-D40 zZ>2-Zh7`q{5L`jketFxoc6DLPzPPcfW|Kfl|1XoJ+xvgb0m>=KywkCWv=<)Bp!U3~ z)ZWOp-W6>(t|>0LJe&{D^RnPy>hqTeJ!6V$4;JJxcR{X!I-fAg>Q>dEWud1 zDsrq4jC^aOx&gE_L^}{OR+5UunVQ-1>;yAuz(H#vPX@rPzZ2`pP_koC=)INDvf z1N&}G?##^ty)0j7wtbbEg4ZfJ-*c|Gf;~hk)yW=M09koat49%xfdUm;N2uJHW?LO| z6zu;azOe`f^nEOi=)Wfu^y^vS+G!2*wVfZ$!3Ofqep>pr$AI zbAiL`T{3f;wpS^rWOsDlWR5KD0|T7ltq6v}bpF3Jjj2)>@}{3&3FY?mp&ZA^GT~a? z{!k=0mua%1LP-0V*My?<|2i3v;WJnXX56PT2M`Rh^}f1yyJSiZrn;2t3q+Ab#+Dbq zhSad9^U9Wf0m}6*lzyG~TM7f&z>958^F)e3PTc!%iHTtE^sT2~9}FBe6?o1#13Gsa zk+u*0BfJ>WC7ym2g^$=P574BmGxmUPl-%J(9Bn;$nkB{72{II{aW(K;3A=(HvGEVA z^H#c~AVyM#Xg`8sRiHj_CR>WFyE9=~Phf(fF=U*Ijf0?(u3_ep6$HTnZ<%@tt(&i-Gc=fIb2{EQliHc0NnBSjwzRB8R8QYGVa z?~2OU%Oukw9f17oiAWP@1a2LRlLmV}-fi-vv>H^-Yy}9aAEnjot!wCWQ=sQHRgYpDzR~7BlIY@Q{TS+#t z;Xzf3b?jRHjMSNXhC_i+eD=)JFpLHJpPwE&2F2JV0`=(RU_@Fd&(Z?iH%uNrAFC$_ z!*RfYVblAe&|7>PsDJ&<+eFYnHU-A#J^kgyBV=P>Of9)ioZF-d2Fv5s8U>Y|W77qj z*nSn3PuLmLSQzbm;0MXudx8^jzbPZqiY7KYb&Q1KD6C}#sqk9i9yL)iSqsc8miozy zy-6VwoM-b5+9od^B5Q)?myL%F1!xk+&I(*0RwTNs`a^0LqQJhVk!46xJu}SC6m0)c zN;8ZJgFNjG!S>!ebTv^fQ?etE3A$&W{)f{Oy&&z1#j%$Dn@fF0gNR2#r|1 zGcx@Q*P0~__C{d1w{4IjAz21^wPP=t2n3f_o9yMlz1$|*5J(p*3)m{Ul69|JgHe#; zQ?^p(xkd>-NDE#Gg^K@L0_*@SEf-4dvpE=5u7p75+O}1;AnC)c;b&=vf;SuufID^6 zQC>X3*$Hr;ucWJpI-|c^Bm<}A+0Kxm1yopcwNy#PT|p^3Ben=e=^v(1j=%DolVu5H zoI`3H3n4xkqX5#r6@;paj5%sR^m#l~MKrC=LWcq9MiC9)6bfO`!2qf>hf6raDnlUn zz+>nMjAc5>>;}IjlLbWbXc#Rz~O416FCj0|IUt)@Kh0Y|5MD9Y@NyAwo z#0oK6fb`-&aY#{WwGL3|OQj!$meKBD`(wOrFqBxe8}z*_e1{ZORBOSgVy{0m)|d`_ z<%7J++4IjOC|LIdbk!v#*bzJ?_PvwydBkQtPXWG$81F}HQ)(QH@{c@XTOGFokMqWE zHnJ-MM#mIEGF2xv=`C^1Bt{lAB)z0reYF^o1i2q9?x{ zkr!`{fn_Ndbct(H(?5WQ=YQp(T3^^mIaM1^KVsK5909&D{YidMaFsIX8ypv_h@?mp z8@QX<_Y5IE9`gfmy)bl~n0{+filA+@tCAg3fB=zyCsmtG zazJlz&l7gg2H?Rd;G9IezXH`dAn7RXFfqMJ(rn}|BCS*cVh<75;yF?vbICT9BJCu! ztU#?ZHZ+P5Vkt?-O^zxeoehoO4Fs)d$q33%*z4I6B{9YTHX3einTrr(CE9os6;Yf7 z3{|tGN_G?Hg6DwmbH-SLR-Gd7t>3K`EKT6gia!o2Z*+M%sCAQ*aH&PKn7%RA*y0m7 zw=()G;+{#=yWoMkB!;Kw|F6COGXrtdMjL$IAc5op=oFoDG3(a{ZHt0LO?WV=rV*Paps@16SLkhNu0MjsA1 zk#_AsLvt>21hd#(Xs8h_+2dFpdGS@ro(V4f-`x(|*icV5RnaDi1K6C6plF?y?6Et% z$NF%nZUM+h_qnebNL)LEBLgxMSY!B$ux~_%z&;k^ZYT(lNbCN?C)GB5QWyTHTqXbi zUH2~Rx~FE|jfn4~e6Sxyu*0v})x8P}fvnJ4K<{PNX%$fIMgyt&aa&13|7aXA6jqU8r2a!@IU2PG`L2$XQ{Ci_8Je;t99Fk!PaV1?Zy$LnS(CJF9EP}J)4$e=o_|k};;F7_7vK+zL zV?MrkGz;ZJdxP8b!fANeBPjI*G!g6rwqIMIqoKr&WE%`4eWm06aDHB~ot=ayf|y2t zv}CL)LTt2wqF|IvD&nXDk#_Q&Gea*)D@>ZOHVJ)+RyGzSR+|FB8w?H&$+?po+W_02 zHPJnbrc|sB+DJS3h@+dub|m-|k(?cpQv?&3KBNh7k(jwbvKp?PRc!?XueT~sj$c<5 zotoYX?4La@COVX=w-l=Yh^$FFy%GrN$7~!~Q`eXH5eTs|M-$MezFg812+{|3$0&i2 z{l~JtjLgF4M{Z@6BS?Camov$Irz-N`XaV}?*UqZ&ksZhaU@x!6W9i!?d3)YPmK6N2 z89rMnc|reddf`&0X#Yr&NKPo4kOIp5(zvAajR^5E$r;SewNb%|cz-+M_QI$5GEcGE zn^JKSqJbBG8_fqQrBc~S+0D=ZaB>g5rV;oS4yhOSEQ3Nsk$;E6LFl(pMm!o458Xf&s|s&mWI!qIKx*VHY~d!BJaB8MQX3hn zL=~%G+svg2K^JUNBlZ)?{8-jj5c(;YF*O1oxev6P>}5J#!x?qHC_+M2RxsF4XDcKV@iFv!!#Liy6D0Sv~swLce`s5C2_V2Aw zYOCTycJG6Pr3-LXcWmnKFN41D&e_GomEYpe^kiS++7dI4r9rp?-|){pK-lvPSek?@ zv;<#<4HM;PX2u2>zmX~= z1@ALszAVuJ*K#fc_+B&p@Z=y|m-T8d59)xvVS5@CDcWvLOW3&+Eaurv*(Xo4Y*caW zhgW0>_eG(aP1G8qgCYMOTzGe_TBPQpwA>v|jR9YCt(us44!jhBL$;vrwa?UW0c=gu z))7nmW`fj8D@g|_;_}fe@E_a8ximD2($p+Na6XaWbcm9=J5k4WRv(CF2AIKzp>{un zeIzYSa(OT<)AckEJRxN*se-h+-Kp8AdFNZ#?PB3u#%Uj3w|=>fr=cMC&C(8F|NL=% zy3sSXf6cRg0Ff#^XWIPa?HTUNyYY$y6Z}3if6B6zyte589wd28<>nloeRBt1$Zac1 z1QQ|dUD0tIMeE0b2&GN?JW{zwjzZF%4|EPLX#-_}7q>Nc^s2X>Aa~D_4t%A0v?b(Y zF3Jb}o6n|wNAj)8w!lS#NUJGZnh87wf)hv_D=B9$7Zs3fXU`Mbn#@_NoTQUOuze8o^pcI! zX|YAZu^~})7LjabS~o(LJ5xxp`x4wA8*41cHP2}oQeAE~wRBM1+1z-C$v4PV@#FjA)je!}M2Iy{` z*il^x(*o8;FzFyyVhNKDm(u+p<##hM>9CvdhbQ%W77k_^_9kj)!z_dJ!XfVVGzkeY z)#4`ywaVqvQ1dB0jkr}W&614tFrj4=sus6=BO!f7vt+p^p1LCQD{-_}!%tXf<78U4 zW4iP#f)Q_8{LRgpFc%zzJ$n;1pV(t4$AH!GaaGOT0Td;@Nt9Y+y_8od-J;9Y5Rvw8 zP%Yg@GyHQ+rq>5u1Vgc4o3Pv*CS>w?JDz$Xan*bw)3aOmMS2-pXw9Iorwh%shl&CS zY3l7%Ka8GW5R=Z`k5T>CqUT&;g)S23VQrI;PnG|wlvUNTnkDR=`AV+jgtk9a4^ijNC5BO~tmCuJ zC3F6e^)!#G!Pc^eZtoyX7h+5PsOd28t_p&xaUnBUQV7g%fhNA!f_e~fbg&R+#Ebx9 zsge0^oQBGOdS7!OVlR-P>#+7wVa9Bc)$}3g-c~1P6Be~YAqZyJ?jC!krUv>xm}3JA z1`r`jIaWa}GD>~Dnpn4j4~P&OFP!)1e#7NT>BX;pWRK8KPuY=wTI=&~qcB^P~q+#qT4 ze0kujplx#pQVAwFOV-^d<5j5qwY?)z^`i=#=;0x}D+h=s(yd(HFw=5j^F2Z=_R8PK zV7}NpAtIt-;D?*9eE2i_4yw@m_Gw+Wi#j58`g;ub)p!{y-^`(LjltZND8GGo*X4{Z z^Ose}AV1$xW!hT>X}-~gY}#XX*|67*i%<9{^)r>RSXnP~B^CMs9hiG{3$+|8QRzYZ zIO6b^gcafH!iw$861Ur&fm%&K9vqr&>H_mLGR6x`SA5^IAJX~pH+f}IcfUcWjD+FwQRM? zs-oyQn8gl_`i+~ipo;svbg`{d9qyvBGkaC9u0!F9$3Pyd=VGEOlCEGDpLx-cf0L&0 zg`dRDaND5GJ&W$l9dG%WuLhIpf-@0lUT6Z$x-UG6QO|dIesAb2;=#he?|D!3lJw`c z-Rsqk(KfxutM8K+Dm0rGZ=pIP>Byp2IvqO81@rZ<)37Y9@zoos{POe-uw%ev7&q(ImE=LR!!XUIfG@!-UY$-tOlx`JH^E>Pqb&NmjOH+a*s76G2Ei zGbYiO`{l#e54UZTWG$#V^Ih2!jH%8{l-lIa=Gr&3t+>VBFH6!*(hvUk6Gl!)C$ooH ztIe9;j++rS_xE7h!sb`6!wtL@Z(S@`Z_yeInoC+R{8nG#P_%rHx)**!%EpFptC&2} zO7gZZNg1QIm~jTz3vTknV?6McmKJ>vzpCYPKnl0^W$SkAjRncG(@n4Ji~IOR?K`Ii zXGWXl9PTY&rtXI2Upuc~G)Qo@ST%bvLa#ZWGJ(On{`Z^D>~|hru(0f@)B5D%9HTFu zvcA{x71f}%6Sl$S=_f;DpKBNQ@Ttr%qPmn_EY`T85KX&s41W4a%1!bde#xw3T73AL z#&Iy{$J;KP2+QeT6SP-HO04N9P{#&GoL>u^&muXxFF~Kq59RdF^<$0ICK`&Oi?73v zM9z_c-0w_X9W~geIf1WQBS*%w;b)P=v7G)>k)aQK#vATOj$MNl@7$SdbI?xkvskrx zU+b3sBh5G?Mo4W*6B}q__YpWQOp^2xTvJ+;z*Oz_Q*6m5_P0JJOv*W9* z!Q1NtR=kXUo^VV&wouFy3t5)7>u7s((tYl_wAb0;=I3aUCj1ZzJY0{s)S$xu{C@-a BnJfSR literal 0 HcmV?d00001 diff --git a/assets/images/circle-64.png b/assets/images/circle-64.png new file mode 100644 index 0000000000000000000000000000000000000000..7660412efab8de201bafd243e6bcbc00dc9a0b13 GIT binary patch literal 613 zcmV-r0-F7aP)6Hp01e#0(1eo5HGpG4OPW9z=tAvOP$pGsXh`#CRvJr|MS{Vv zwP%0nZ;&7BPhxg=cBTZNl(21bhdd@v$qVw9d?26L2mWor*NpidJL&Ny_23G*PhOMH zxL@kt6+f$@JAg8INZuhi?f4yKod7(LyW}sVr%!(8LzVz6a*OODJGndtD{TNZ@*DJ# z8cQ`T01fgt^phG>J!t?v@(=XYnPWrj093G$d`^X*$(KnIfxU0a%(Xa^hSpSz!RQP+T>y0Z`M%M}Yyj!KpC_ zpo`+m`3pcf6g8-f&PZd9azCZxaegJEM09GCV8_`nN zdEO(~3P1;P)m8w;f&q+5oHUTCi2|??3}CJRYy|_@C;$h+0QL&NNicw;0bu?DCJ35o zQ2atj{8Cu_W=Q;YSbRdnq{Lv7q9!eF4n|;(#?0ZUcRcPE_~Wl0kBcvmFeNfDMN+0r zu4uEu-G!2-RMs~&E_3+tu@y^u5b~5dn;^z=`Cv>qYaZ|%B-}Dnhv1eO&s7L+n)0t0 zo5;Rxu89oV=7Isz;caG`TUrMhH%?w^ogHwtCCN9|7l=IK{{miEol z|FzGz$s?Yh=j07}Pd>8u{M($b8Sy=dx6l6qAQMDe9>r!k00000NkvXXu0mjf%{vZl literal 0 HcmV?d00001 diff --git a/assets/images/close.png b/assets/images/close.png new file mode 100644 index 0000000000000000000000000000000000000000..881647b4d78e071ab66fbdc3c1a6e1eaddc23c4d GIT binary patch literal 295 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezpUtcb+beAr-gY&WPnYqQKKqd+E;3 zz1KHAf9beM>`nKVnyiV`fcIM z;i3N8)xV*(*~-o`)nU(+ouxYS7-r9N*FQ3~LbrMk-v#DE^?R}jSASPDRS3PWYYA#@ z(B{aTGkeecK*@#)oCVXZE-0Vy{gb1ZE%;6MrP94cLfaj7bZ*}yv{>NsBi+3L`YoLm z*~aR;&;RZaUsV6XZ6V`=et|ElZFO!7xh1zuZ7?hTP$u=ynfd?Hmj71{Zx2nn`5?nZ qm#ueg)!r33x + + + + + + + + + + + + + + diff --git a/assets/images/header-logo.png b/assets/images/header-logo.png new file mode 100644 index 0000000000000000000000000000000000000000..56d9cb52197bf7632c1c2328ed7f75832ba681d1 GIT binary patch literal 3061 zcmV5nPi{KsYAi zYwHMSrieN91h*xuvLI>~O!t0Ef)5cMO%ZeI2u_DbY%;65_O4=T>l0cMZX)z0j3%u2 zalY2zx+#KUCODHYNkhU1gdBLz-w+Ncq&E(6VM$2MBZ|Gfx<5xy0g>X5c0nU|w>keGQ`fZNSO9(&3XB)z``1^%~Y{JEa%K-U(7s5}_*JVDq zn$VfhlQ4uZhA@LrLfB3yHie$12O(GBtAsz}f$t?8M_7}ARe3@~%s(t2_?ZSv&^ba< zvs!b z1hyS{Z?g%*uU^BMCo?5o4DBE9o+utm0mLwF0J571c^i(GW)jhex%vv;DC5 z==zc2+ArZh#Nm-YtdU$ZL!5U$wg+9?N%$isM%}8ADsM3iEYG5keC+SK_HxKR&PQl) zLSvprd;3p}$b{$0C)8CT&b!N?0ept~g`G-TE z?^&UYBtx*}N-X+ApX2L8l#t@YZe`qWS}cyPaT7e!u-64CSG5s)`emOU3Gq-1V8Z9J z^R|KPHWv5M9qN%Q!8yvp%$`&&WNF zP^O1NsCEzfxHK+;i!~&vHz#lEz7R3#mlh`V28bXZDkib5BAo`|EI44DAYDG?NbnTp zUV0j0=D!kV5e~9_x+9)X!oq5L%HXT$=d3sgZfH=5db5GZV!C}HR2C`bpJCzD?LiU1 zYMg%nr1!A6$t+l)(ePv|5X0J%+f=bg+YExxFvPPfSd2a%;o;d9*ZV%ijQS8g%HrCC zAJh=F1H`sr&eu*r*Y-frw++dTfD}&-?T`J-=0@{i<`)sR;z7BjBgZKB^tk4jR*1#F zKv|Rbta?C2vlUW0!l^p~%NUCn{egzCuaRDx2Pa~nAx8F0Y9q%a#2bitJ*DV&3k%>u zmhQd+OHhGT)x@%o?#cL7X%cSx+e@fkV67y4+slaUzE zg+C|oP+K|-N}9c8nE6Gl&wD_yZGWF&B2Hyvf5I^-;H ztJewR-QuYAr`g_^z-%f)QeYf2p8`(B2uO*pVMsp0p?Sadx{sk)}nC__87P3;Joh;m2jmaCdiZd`Co><7$ z95)KZ18VuwAcry6!X#OW$Yi@q{2PYgu|6WjoiT~y{b5dzvg@sabx3nu34-|vt?=MH zM`=t53s8xKfLEB1&{(>4h^={BEZl0muT{o8FOFnG4OWU{DtqY@1HlWC#8wjtjYaaB z@dEt)KE)eup6623q_H(aheEl?aTxwocO_m5Y(aU|r zkrA+Xi;&Lrj<+ef$x`%o0V`8C4ubDBc+Rz#$3hBgg6C_$IC3GlYpG84HOqC|#I zozzxk+iaf^>%UuzUxZm~s+jMX}Um4bYIa%TVoC2P@mu z$|6YjE zb3mf5mEd7r65@J|g#Qce3q$nL8gcJT&6ovZ(gJ@49;SNVq0Nif2Sd`!bddP z0be2V_oDfKp4D7@lf{fmhq|>7cwTWF1i}cvvXe|E>U(=>kqH0m0)G?sKhe}k=wBgO zYVp9;7uMFIf+S4akH{s~y6A+)P507lF7fOvCfTWNC)6L)!@Hhkl8#_?9L0Gv5wjlC zOvElpJcv=6aoSX%Bou$-E9OH;6a6|w9JNgm=9l~;CAfp;;(IM?h;*y@kdH`GEX;2* zv}Yt&3Vq40w@>$pKoB@bNl&hF*b6gQah&i8B@e;t&W@8wP8L|y$d)Yo@b;csbY!UIp7>?^afIZZ8V&5qKTRUBey?F+_<8F@m;iL$z z1&>rdu=g>jya+FnKpL + + + + + + + + + + + + + + + + + + + + diff --git a/assets/images/rounded-background.png b/assets/images/rounded-background.png new file mode 100644 index 0000000000000000000000000000000000000000..dc3f4e3c6d0fd25cdd91cac99e45186d1f537a37 GIT binary patch literal 228 zcmV literal 0 HcmV?d00001 diff --git a/assets/images/rounded-border.png b/assets/images/rounded-border.png new file mode 100644 index 0000000000000000000000000000000000000000..b2db5945e88b77ea2a4824575d6ff1f92596fdd5 GIT binary patch literal 315 zcmV-B0mS}^P)G`PYP8r{In_5HA$mh!ar}Ij9huk@F-P)UE^@w)=%h z9qrI$M91>$rC@>G^pYDwOC&pKVFVM_v+fHq!xgoo))IIz)3Y={Fk?L}1#F + + + + + + + + + + + + + + + + diff --git a/assets/images/scrollbar-middle.png b/assets/images/scrollbar-middle.png new file mode 100644 index 0000000000000000000000000000000000000000..d9f60ac620768c32414d8ed972707dd120f37759 GIT binary patch literal 75 zcmeAS@N?(olHy`uVBq!ia0vp^oIuRT!3HFG4z<(*DIrf6$B>F!$v^)8w`UefW=^nV Y2!1R7aLe}t6+l@APgg&ebxsLQ09IlY4gdfE literal 0 HcmV?d00001 diff --git a/assets/images/scrollbar-middle.svg b/assets/images/scrollbar-middle.svg new file mode 100644 index 00000000..61bec546 --- /dev/null +++ b/assets/images/scrollbar-middle.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/assets/images/scrollbar-top.png b/assets/images/scrollbar-top.png new file mode 100644 index 0000000000000000000000000000000000000000..3932e11cf050a0248d21089fe07f279301251224 GIT binary patch literal 132 zcmeAS@N?(olHy`uVBq!ia0vp^LO{&N!3HFiZux8nQr?~}jv*Ddl7IaFZ_jLMaQKAD z39$}y#*fAt_gF-gPcFz(`1f62_z&wNtt8$}hZ8wAC2l(+vE`+G;)aP5&GQ5kFBm8B gD2eq*xh!&INT24ZyWS`HH_%uHPgg&ebxsLQ04W440{{R3 literal 0 HcmV?d00001 diff --git a/assets/images/scrollbar-top.svg b/assets/images/scrollbar-top.svg new file mode 100644 index 00000000..4f979515 --- /dev/null +++ b/assets/images/scrollbar-top.svg @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/assets/images/spinner-background.png b/assets/images/spinner-background.png new file mode 100644 index 0000000000000000000000000000000000000000..37b5a8898244ada062dbce59ba6d2df9aec9ad74 GIT binary patch literal 684 zcmV;d0#p5oP){RPVIidy29PHl6K)BQgjd3p@C8iq>=ExAqfP9w<1{W2nuH$V zM@E+)v~8fT#0V4!mxQG>CksLseOn{o5Y7m5X-{T^HpVhaph9?)$%!{s*%X1AB%p2&>~Qm+avX;1Zpv6eoT0Rz3%|Gcs7o)5;ZP?ipHLwK+!7Wo2ug7 z4-E@dRuOO_S{vW&3)aSA;!7ew098 zR}ogdu#P}Cg7U%=u9-Sq1PPRwzD?io%&%Js&URY(4xrz#$y~akMdeq&3C>n-tP6{mcj#Sb~P-5vyj?M?EOB7tXxZbN~L!6vy&k-)t|w@-nz$0l)8B%u0`mpefq^IItM zA93c*Xyy;H%)1g_Ya`#a%I??gaTLYTG
    }|Pq|AI!@26E}%nq(Cq*b`eho)81 zOl%DzjN3AqTAagTIGU#N+;nPDAc3lr+;wq!a!y#+R&v)wdi@{0r$Y_ zRfBbxJsNOpbuW8(ZBJ#wmp#I++Z=fzo)@Qj!M2w%K+$B0-$VR&gLjQwxA_AYdhzn- Sw&h{~0000 + + + + + + + diff --git a/assets/images/spinner-foreground.png b/assets/images/spinner-foreground.png new file mode 100644 index 0000000000000000000000000000000000000000..6814b5f2b32d25e43d4e88d460cfef1042580d0c GIT binary patch literal 340 zcmeAS@N?(olHy`uVBq!ia0vp^1|ZDA1|-9oezr3(FiLy6IEGZ*dVAfL>yU#$+e6ir zJP{GguNXfOt77C{Tg0HdHC$wGtNq+ZtXsB=y6`8gchq?-Uf{rTv$uZcRLP3l2b_&& zyBsZCvoEIQTSn`#75!Qo-#cHgmS>oER`P71tY{9)o%5VqC#GvRJZo@za*Jz0r1JeV zhP%B7(j1J$L$*pf1fLbU;KFR;INSW4%LLH}8<{ literal 0 HcmV?d00001 diff --git a/assets/images/spinner-foreground.svg b/assets/images/spinner-foreground.svg new file mode 100644 index 00000000..d7cbfaaa --- /dev/null +++ b/assets/images/spinner-foreground.svg @@ -0,0 +1,8 @@ + + + + + + + + From 503e687c55162ed3a57a6fe875fff8e155a322f4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Dec 2020 11:20:28 -0800 Subject: [PATCH 1090/1504] Fix repository link --- src/cli/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/build.rs b/src/cli/build.rs index 4cfe9f77..cab366ab 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -101,7 +101,7 @@ fn write_model(tree: &RojoTree, options: &BuildCommand) -> Result<(), anyhow::Er OutputKind::Rbxl => { log::warn!("Support for building binary places (rbxl) is still experimental."); log::warn!("Using the XML place format (rbxlx) is recommended instead."); - log::warn!("For more info, see https://github.com/LPGhatguy/rojo/issues/180"); + log::warn!("For more info, see https://github.com/rojo-rbx/rojo/issues/180"); let root_instance = tree.get_instance(root_id).unwrap(); let top_level_ids = root_instance.children(); From da8ed6ddf93b934161d8ea3682d6c0ab934befe9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Dec 2020 11:22:43 -0800 Subject: [PATCH 1091/1504] Update Changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8861f68f..f3dc802b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Added brand new Rojo UI ([#367](https://github.com/rojo-rbx/rojo/pull/367)) * Added `projectName` to `/api/rojo` output. ## [6.0.0 Release Candidate 3](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.3) (November 19, 2020) From 71e4dfeb14999339046c71e22ad1bf9dae149fe4 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Dec 2020 12:59:53 -0800 Subject: [PATCH 1092/1504] Change logo to be brand color on dark theme --- plugin/src/App/Theme.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index 2829cf4e..d6d688b3 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -174,7 +174,7 @@ local darkTheme = strict("DarkTheme", { }, }, Header = { - LogoColor = hexColor(0xFFFFFF), + LogoColor = BRAND_COLOR, VersionColor = hexColor(0xD3D3D3) }, ErrorColor = hexColor(0xFFFFFF), From faf86d006ad95273c3bf2c72148a7ca942bd6455 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Dec 2020 13:16:34 -0800 Subject: [PATCH 1093/1504] Remove outdated warning from Rojo 0.5.0 alpha 14 --- src/snapshot_middleware/json_model.rs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 74ed97fd..c978f57a 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -19,24 +19,6 @@ pub fn snapshot_json_model( let instance: JsonModel = serde_json::from_slice(&contents) .map_err(|source| SnapshotError::malformed_model_json(source, path))?; - if let Some(json_name) = &instance.name { - if json_name != instance_name { - log::warn!( - "Name from JSON model did not match its file name: {}", - path.display() - ); - log::warn!( - "In Rojo < alpha 14, this model is named \"{}\" (from its 'Name' property)", - json_name - ); - log::warn!( - "In Rojo >= alpha 14, this model is named \"{}\" (from its file name)", - instance_name - ); - log::warn!("'Name' for the top-level instance in a JSON model is now optional and will be ignored."); - } - } - let mut snapshot = instance.core.into_snapshot(instance_name.to_owned()); snapshot.metadata = snapshot From eddbe7d0cfca14c58548e20ad7232a513d98c83d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 14 Dec 2020 14:04:06 -0800 Subject: [PATCH 1094/1504] Release 6.0.0-rc.4 --- CHANGELOG.md | 2 + Cargo.lock | 170 ++++++++++++++++++++++-------------------- Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 4 files changed, 93 insertions(+), 83 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f3dc802b..8853f79e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes + +## [6.0.0 Release Candidate 4](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.4) (December 14, 2020) * Added brand new Rojo UI ([#367](https://github.com/rojo-rbx/rojo/pull/367)) * Added `projectName` to `/api/rojo` output. diff --git a/Cargo.lock b/Cargo.lock index 4a95ba9f..d8712b16 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -35,9 +35,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf8dcb5b4bbaa28653b647d8c77bd4ed40183b48882e130c1f1ffb73de069fd7" +checksum = "2c0df63cb2955042487fad3aefd2c6e3ae7389ac5dc1beb28921de0b69f779d4" [[package]] name = "arrayref" @@ -76,9 +76,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.54" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2baad346b2d4e94a24347adeee9c7a93f412ee94b9cc26e5b59dea23848e9f28" +checksum = "ef5140344c85b01f9bbb4d4b7288a8aa4b3287ccef913a14bcc78a1063623598" dependencies = [ "addr2line", "cfg-if 1.0.0", @@ -105,9 +105,9 @@ checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" [[package]] name = "base64" -version = "0.12.3" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3441f0f7b02788e948e47f457ca01f1d7e6d92c693bc132c22b087d3141c03ff" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bincode" @@ -209,9 +209,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.63" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad9c6140b5a2c7db40ea56eb1821245e5362b44385c05b76288b1a599934ac87" +checksum = "4c0496836a84f8d0495758516b8621a622beb77c0fed418570e50764093ced48" [[package]] name = "cfg-if" @@ -265,9 +265,9 @@ dependencies = [ [[package]] name = "const_fn" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c478836e029dcef17fb47c89023448c64f781a046e0300e257ad8225ae59afab" +checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826" [[package]] name = "constant_time_eq" @@ -381,7 +381,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.0", + "crossbeam-utils 0.8.1", ] [[package]] @@ -402,8 +402,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" dependencies = [ "cfg-if 1.0.0", - "crossbeam-epoch 0.9.0", - "crossbeam-utils 0.8.0", + "crossbeam-epoch 0.9.1", + "crossbeam-utils 0.8.1", ] [[package]] @@ -417,21 +417,21 @@ dependencies = [ "crossbeam-utils 0.7.2", "lazy_static", "maybe-uninit", - "memoffset", + "memoffset 0.5.6", "scopeguard", ] [[package]] name = "crossbeam-epoch" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0f606a85340376eef0d6d8fec399e6d4a544d648386c6645eb6d0653b27d9f" +checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d" dependencies = [ "cfg-if 1.0.0", "const_fn", - "crossbeam-utils 0.8.0", + "crossbeam-utils 0.8.1", "lazy_static", - "memoffset", + "memoffset 0.6.1", "scopeguard", ] @@ -459,21 +459,20 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec91540d98355f690a86367e566ecad2e9e579f230230eb7c21398372be73ea5" +checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d" dependencies = [ "autocfg 1.0.1", "cfg-if 1.0.0", - "const_fn", "lazy_static", ] [[package]] name = "csv" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4666154fd004af3fd6f1da2e81a96fd5a81927fe8ddb6ecc79e2aa6e138b54" +checksum = "f9d58633299b24b515ac72a3f869f8b91306a3cec616a602843a383acd6f9e97" dependencies = [ "bstr", "csv-core", @@ -1012,9 +1011,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] name = "js-sys" -version = "0.3.45" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" +checksum = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175" dependencies = [ "wasm-bindgen", ] @@ -1043,9 +1042,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d58d1b70b004888f764dfbf6a26a3b0342a1632d33968e4a179d8011c760614" +checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" [[package]] name = "linked-hash-map" @@ -1130,6 +1129,15 @@ dependencies = [ "autocfg 1.0.1", ] +[[package]] +name = "memoffset" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" +dependencies = [ + "autocfg 1.0.1", +] + [[package]] name = "memofs" version = "0.1.3" @@ -1168,9 +1176,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.6.22" +version = "0.6.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fce347092656428bc8eaf6201042cb551b8d67855af7374542a92a0fbfcac430" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" dependencies = [ "cfg-if 0.1.10", "fuchsia-zircon", @@ -1210,9 +1218,9 @@ dependencies = [ [[package]] name = "miow" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c1f2f3b1cf331de6896aabf6e9d55dca90356cc9960cca7eaaf408a355ae919" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" dependencies = [ "kernel32-sys", "net2", @@ -1240,9 +1248,9 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.35" +version = "0.2.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ebc3ec692ed7c9a255596c67808dee269f64655d8baf7b4f0638e51ba1d6853" +checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" dependencies = [ "cfg-if 0.1.10", "libc", @@ -1294,9 +1302,9 @@ checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" [[package]] name = "oorandom" -version = "11.1.2" +version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a170cebd8021a008ea92e4db85a72f80b35df514ec664b296fdcbb654eac0b2c" +checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" [[package]] name = "opaque-debug" @@ -1315,12 +1323,12 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.30" +version = "0.10.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d575eff3665419f9b83678ff2815858ad9d11567e082f5ac1814baba4e2bcb4" +checksum = "8d008f51b1acffa0d3450a68606e6a51c123012edaacb0f4e1426bd978869187" dependencies = [ "bitflags", - "cfg-if 0.1.10", + "cfg-if 1.0.0", "foreign-types", "lazy_static", "libc", @@ -1335,9 +1343,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" -version = "0.9.58" +version = "0.9.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a842db4709b604f0fe5d1170ae3565899be2ad3d9cbc72dedc789ac0511f78de" +checksum = "de52d8eabd217311538a39bba130d7dea1f1e118010fee7a033d966845e7d5fe" dependencies = [ "autocfg 1.0.1", "cc", @@ -1749,7 +1757,7 @@ checksum = "9ab346ac5921dc62ffa9f89b7a773907511cdfa5490c572ae9be1be33e8afa4a" dependencies = [ "crossbeam-channel 0.5.0", "crossbeam-deque 0.8.0", - "crossbeam-utils 0.8.0", + "crossbeam-utils 0.8.1", "lazy_static", "num_cpus", ] @@ -1953,7 +1961,7 @@ dependencies = [ [[package]] name = "rojo" -version = "6.0.0-rc.3" +version = "6.0.0-rc.4" dependencies = [ "anyhow", "backtrace", @@ -2010,14 +2018,14 @@ dependencies = [ [[package]] name = "rust-argon2" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9dab61250775933275e84053ac235621dfb739556d5c54a2f2e9313b7cf43a19" +checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb" dependencies = [ - "base64 0.12.3", + "base64 0.13.0", "blake2b_simd", "constant_time_eq", - "crossbeam-utils 0.7.2", + "crossbeam-utils 0.8.1", ] [[package]] @@ -2106,9 +2114,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.117" +version = "1.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b88fa983de7720629c9387e9f517353ed404164b1e482c970a90c1a4aaf7dc1a" +checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" dependencies = [ "serde_derive", ] @@ -2125,9 +2133,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.117" +version = "1.0.118" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbd1ae72adb44aab48f325a02444a5fc079349a8d804c1fc922aed3f7454c74e" +checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", @@ -2136,9 +2144,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.59" +version = "1.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcac07dbffa1c65e7f816ab9eba78eb142c6d44410f4eeba1e26e4f5dfa56b95" +checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779" dependencies = [ "itoa", "ryu", @@ -2209,9 +2217,9 @@ dependencies = [ [[package]] name = "snafu" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c4e6046e4691afe918fd1b603fd6e515bcda5388a1092a9edbada307d159f09" +checksum = "eab12d3c261b2308b0d80c26fffb58d17eba81a4be97890101f416b478c79ca7" dependencies = [ "doc-comment", "snafu-derive", @@ -2219,9 +2227,9 @@ dependencies = [ [[package]] name = "snafu-derive" -version = "0.6.9" +version = "0.6.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7073448732a89f2f3e6581989106067f403d378faeafb4a50812eb814170d3e5" +checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", @@ -2254,9 +2262,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.20" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "126d630294ec449fae0b16f964e35bf3c74f940da9dca17ee9b905f7b3112eb8" +checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c" dependencies = [ "clap", "lazy_static", @@ -2265,9 +2273,9 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65e51c492f9e23a220534971ff5afc14037289de430e3c83f9daf6a1b6ae91e8" +checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90" dependencies = [ "heck", "proc-macro-error", @@ -2278,9 +2286,9 @@ dependencies = [ [[package]] name = "syn" -version = "1.0.48" +version = "1.0.54" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc371affeffc477f42a221a1e4297aedcea33d47d19b61455588bd9d8f6b19ac" +checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", @@ -2402,9 +2410,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b78a366903f506d2ad52ca8dc552102ffdd3e937ba8a227f024dc1d1eae28575" +checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f" dependencies = [ "tinyvec_macros", ] @@ -2664,9 +2672,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.7.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db8716a166f290ff49dabc18b44aa407cb7c6dbe1aa0971b44b8a24b0ca35aae" +checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796" [[package]] name = "unicode-width" @@ -2730,9 +2738,9 @@ dependencies = [ [[package]] name = "vcpkg" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6454029bf181f092ad1b853286f23e2c507d8e8194d01d92da4a55c274a5508c" +checksum = "b00bca6106a5e23f3eee943593759b7fcddb00554332e856d990c893966879fb" [[package]] name = "vec_map" @@ -2782,19 +2790,19 @@ checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" +checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" +checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62" dependencies = [ "bumpalo", "lazy_static", @@ -2807,9 +2815,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" +checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084" dependencies = [ "quote 1.0.7", "wasm-bindgen-macro-support", @@ -2817,9 +2825,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" +checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549" dependencies = [ "proc-macro2 1.0.24", "quote 1.0.7", @@ -2830,15 +2838,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.68" +version = "0.2.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" +checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158" [[package]] name = "web-sys" -version = "0.3.45" +version = "0.3.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bf6ef87ad7ae8008e15a355ce696bed26012b7caa21605188cfd8214ab51e2d" +checksum = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3" dependencies = [ "js-sys", "wasm-bindgen", diff --git a/Cargo.toml b/Cargo.toml index d04e4d9b..75f12da1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "6.0.0-rc.3" +version = "6.0.0-rc.4" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 27e6ed9e..18d5d2a3 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {6, 0, 0, "-rc.3"}, + version = {6, 0, 0, "-rc.4"}, expectedServerVersionString = "6.0 or newer", protocolVersion = 3, defaultHost = "localhost", From f3745c68d2f8124efe05cdb05a2205bc7d87b224 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 18 Dec 2020 11:39:41 -0800 Subject: [PATCH 1095/1504] Turn rbxm/rbxmx errors into error variants --- src/snapshot_middleware/error.rs | 29 +++++++++++++++++++++++++++++ src/snapshot_middleware/rbxm.rs | 4 ++-- src/snapshot_middleware/rbxmx.rs | 4 ++-- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs index 7e0e3847..145c44ec 100644 --- a/src/snapshot_middleware/error.rs +++ b/src/snapshot_middleware/error.rs @@ -18,6 +18,18 @@ pub enum SnapshotError { #[error("malformed project file at path {}", .path.display())] MalformedProject { source: ProjectError, path: PathBuf }, + #[error("malformed .rbxm file at path {}", .path.display())] + MalformedRbxm { + source: rbx_binary::DecodeError, + path: PathBuf, + }, + + #[error("malformed .rbxmx file at path {}", .path.display())] + MalformedRbxmx { + source: rbx_xml::DecodeError, + path: PathBuf, + }, + #[error("malformed .model.json file at path {}", .path.display())] MalformedModelJson { source: serde_json::Error, @@ -68,6 +80,23 @@ impl SnapshotError { } } + pub(crate) fn malformed_rbxm( + source: rbx_binary::DecodeError, + path: impl Into, + ) -> Self { + Self::MalformedRbxm { + source, + path: path.into(), + } + } + + pub(crate) fn malformed_rbxmx(source: rbx_xml::DecodeError, path: impl Into) -> Self { + Self::MalformedRbxmx { + source, + path: path.into(), + } + } + pub(crate) fn malformed_model_json( source: serde_json::Error, path: impl Into, diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index db4d6667..9d2dc4b6 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -5,7 +5,7 @@ use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::middleware::SnapshotInstanceResult; +use super::{middleware::SnapshotInstanceResult, SnapshotError}; pub fn snapshot_rbxm( context: &InstanceContext, @@ -21,7 +21,7 @@ pub fn snapshot_rbxm( let root_id = temp_tree.get_root_id(); rbx_binary::decode(&mut temp_tree, root_id, vfs.read(path)?.as_slice()) - .expect("TODO: Handle rbx_binary errors"); + .map_err(|err| SnapshotError::malformed_rbxm(err, path))?; let root_instance = temp_tree.get_instance(root_id).unwrap(); let children = root_instance.get_children_ids(); diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index b8012101..753bdc7d 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -4,7 +4,7 @@ use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::middleware::SnapshotInstanceResult; +use super::{middleware::SnapshotInstanceResult, SnapshotError}; pub fn snapshot_rbxmx( context: &InstanceContext, @@ -16,7 +16,7 @@ pub fn snapshot_rbxmx( .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); let temp_tree = rbx_xml::from_reader(vfs.read(path)?.as_slice(), options) - .expect("TODO: Handle rbx_xml errors"); + .map_err(|err| SnapshotError::malformed_rbxmx(err, path))?; let root_instance = temp_tree.get_instance(temp_tree.get_root_id()).unwrap(); let children = root_instance.get_children_ids(); From 3b149cc875df3b3caca3267d2f8b519e800cbbc1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 18 Dec 2020 12:16:05 -0800 Subject: [PATCH 1096/1504] Drop SnapshotError in favor of anyhow::Error --- src/change_processor.rs | 4 +- src/serve_session.rs | 6 +- src/snapshot_middleware/csv.rs | 13 ++- src/snapshot_middleware/dir.rs | 7 +- src/snapshot_middleware/error.rs | 130 -------------------------- src/snapshot_middleware/json.rs | 7 +- src/snapshot_middleware/json_model.rs | 5 +- src/snapshot_middleware/lua.rs | 16 ++-- src/snapshot_middleware/meta_file.rs | 23 +++-- src/snapshot_middleware/middleware.rs | 4 +- src/snapshot_middleware/mod.rs | 2 - src/snapshot_middleware/project.rs | 5 +- src/snapshot_middleware/rbxm.rs | 11 ++- src/snapshot_middleware/rbxmx.rs | 11 ++- src/snapshot_middleware/txt.rs | 9 +- 15 files changed, 70 insertions(+), 183 deletions(-) delete mode 100644 src/snapshot_middleware/error.rs diff --git a/src/change_processor.rs b/src/change_processor.rs index 9e7797ee..a6ebdb03 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -292,7 +292,7 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: RbxId) -> Optio return None; } Err(err) => { - log::error!("Snapshot error: {}", ErrorDisplay(err)); + log::error!("Snapshot error: {:?}", err); return None; } }; @@ -340,7 +340,7 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: RbxId) -> Optio return None; } Err(err) => { - log::error!("{}", ErrorDisplay(err)); + log::error!("{:?}", err); return None; } }; diff --git a/src/serve_session.rs b/src/serve_session.rs index d43d4981..ee6020a6 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -22,7 +22,7 @@ use crate::{ apply_patch_set, compute_patch_set, AppliedPatchSet, InstanceContext, InstancePropertiesWithMeta, PatchSet, RojoTree, }, - snapshot_middleware::{snapshot_from_vfs, SnapshotError}, + snapshot_middleware::snapshot_from_vfs, }; /// Contains all of the state for a Rojo serve session. @@ -234,8 +234,8 @@ pub enum ServeSessionError { }, #[error(transparent)] - Snapshot { + Other { #[from] - source: SnapshotError, + source: anyhow::Error, }, } diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index fcd358f6..fd39b04e 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -1,5 +1,6 @@ use std::{collections::BTreeMap, path::Path}; +use anyhow::Context; use maplit::hashmap; use memofs::{IoResultExt, Vfs}; use rbx_dom_weak::RbxValue; @@ -7,9 +8,7 @@ use serde::Serialize; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{ - error::SnapshotError, meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult, -}; +use super::{meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult}; pub fn snapshot_csv( _context: &InstanceContext, @@ -20,8 +19,12 @@ pub fn snapshot_csv( let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); let contents = vfs.read(path)?; - let table_contents = convert_localization_csv(&contents) - .map_err(|source| SnapshotError::malformed_l10n_csv(source, path))?; + let table_contents = convert_localization_csv(&contents).with_context(|| { + format!( + "File was not a valid LocalizationTable CSV file: {}", + path.display() + ) + })?; let mut snapshot = InstanceSnapshot::new() .name(instance_name) diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 359856d0..84c7d64a 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -4,10 +4,7 @@ use memofs::{DirEntry, IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{ - error::SnapshotError, meta_file::DirectoryMetadata, middleware::SnapshotInstanceResult, - snapshot_from_vfs, -}; +use super::{meta_file::DirectoryMetadata, middleware::SnapshotInstanceResult, snapshot_from_vfs}; pub fn snapshot_dir(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { let passes_filter_rules = |child: &DirEntry| { @@ -35,7 +32,7 @@ pub fn snapshot_dir(context: &InstanceContext, vfs: &Vfs, path: &Path) -> Snapsh .file_name() .expect("Could not extract file name") .to_str() - .ok_or_else(|| SnapshotError::file_name_bad_unicode(path))? + .ok_or_else(|| anyhow::anyhow!("File name was not valid UTF-8: {}", path.display()))? .to_string(); let meta_path = path.join("init.meta.json"); diff --git a/src/snapshot_middleware/error.rs b/src/snapshot_middleware/error.rs deleted file mode 100644 index 145c44ec..00000000 --- a/src/snapshot_middleware/error.rs +++ /dev/null @@ -1,130 +0,0 @@ -use std::{io, path::PathBuf}; - -use thiserror::Error; - -use crate::project::ProjectError; - -#[derive(Debug, Error)] -pub enum SnapshotError { - #[error("file name had malformed Unicode")] - FileNameBadUnicode { path: PathBuf }, - - #[error("file had malformed Unicode contents at path {}", .path.display())] - FileContentsBadUnicode { - source: std::str::Utf8Error, - path: PathBuf, - }, - - #[error("malformed project file at path {}", .path.display())] - MalformedProject { source: ProjectError, path: PathBuf }, - - #[error("malformed .rbxm file at path {}", .path.display())] - MalformedRbxm { - source: rbx_binary::DecodeError, - path: PathBuf, - }, - - #[error("malformed .rbxmx file at path {}", .path.display())] - MalformedRbxmx { - source: rbx_xml::DecodeError, - path: PathBuf, - }, - - #[error("malformed .model.json file at path {}", .path.display())] - MalformedModelJson { - source: serde_json::Error, - path: PathBuf, - }, - - #[error("malformed .meta.json file at path {}", .path.display())] - MalformedMetaJson { - source: serde_json::Error, - path: PathBuf, - }, - - #[error("malformed JSON at path {}", .path.display())] - MalformedJson { - source: serde_json::Error, - path: PathBuf, - }, - - #[error("malformed CSV localization data at path {}", .path.display())] - MalformedLocalizationCsv { source: csv::Error, path: PathBuf }, - - #[error(transparent)] - Io { - #[from] - source: io::Error, - }, -} - -impl SnapshotError { - pub(crate) fn file_name_bad_unicode(path: impl Into) -> Self { - Self::FileNameBadUnicode { path: path.into() } - } - - pub(crate) fn file_contents_bad_unicode( - source: std::str::Utf8Error, - path: impl Into, - ) -> Self { - Self::FileContentsBadUnicode { - source, - path: path.into(), - } - } - - pub(crate) fn malformed_project(source: ProjectError, path: impl Into) -> Self { - Self::MalformedProject { - source, - path: path.into(), - } - } - - pub(crate) fn malformed_rbxm( - source: rbx_binary::DecodeError, - path: impl Into, - ) -> Self { - Self::MalformedRbxm { - source, - path: path.into(), - } - } - - pub(crate) fn malformed_rbxmx(source: rbx_xml::DecodeError, path: impl Into) -> Self { - Self::MalformedRbxmx { - source, - path: path.into(), - } - } - - pub(crate) fn malformed_model_json( - source: serde_json::Error, - path: impl Into, - ) -> Self { - Self::MalformedModelJson { - source, - path: path.into(), - } - } - - pub(crate) fn malformed_meta_json(source: serde_json::Error, path: impl Into) -> Self { - Self::MalformedMetaJson { - source, - path: path.into(), - } - } - - pub(crate) fn malformed_json(source: serde_json::Error, path: impl Into) -> Self { - Self::MalformedJson { - source, - path: path.into(), - } - } - - pub(crate) fn malformed_l10n_csv(source: csv::Error, path: impl Into) -> Self { - Self::MalformedLocalizationCsv { - source, - path: path.into(), - } - } -} diff --git a/src/snapshot_middleware/json.rs b/src/snapshot_middleware/json.rs index 15efe21b..959b3cb3 100644 --- a/src/snapshot_middleware/json.rs +++ b/src/snapshot_middleware/json.rs @@ -1,5 +1,6 @@ use std::path::Path; +use anyhow::Context; use maplit::hashmap; use memofs::{IoResultExt, Vfs}; use rbx_dom_weak::RbxValue; @@ -9,9 +10,7 @@ use crate::{ snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, }; -use super::{ - error::SnapshotError, meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult, -}; +use super::{meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult}; pub fn snapshot_json( context: &InstanceContext, @@ -22,7 +21,7 @@ pub fn snapshot_json( let contents = vfs.read(path)?; let value: serde_json::Value = serde_json::from_slice(&contents) - .map_err(|err| SnapshotError::malformed_json(err, path))?; + .with_context(|| format!("File contains malformed JSON: {}", path.display()))?; let as_lua = json_to_lua(value).to_string(); diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index c978f57a..b0dd361c 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -1,5 +1,6 @@ use std::{borrow::Cow, collections::HashMap, path::Path}; +use anyhow::Context; use memofs::Vfs; use rbx_dom_weak::UnresolvedRbxValue; use rbx_reflection::try_resolve_value; @@ -7,7 +8,7 @@ use serde::Deserialize; use crate::snapshot::{InstanceContext, InstanceSnapshot}; -use super::{error::SnapshotError, middleware::SnapshotInstanceResult}; +use super::middleware::SnapshotInstanceResult; pub fn snapshot_json_model( context: &InstanceContext, @@ -17,7 +18,7 @@ pub fn snapshot_json_model( ) -> SnapshotInstanceResult { let contents = vfs.read(path)?; let instance: JsonModel = serde_json::from_slice(&contents) - .map_err(|source| SnapshotError::malformed_model_json(source, path))?; + .with_context(|| format!("File is not a valid JSON model: {}", path.display()))?; let mut snapshot = instance.core.into_snapshot(instance_name.to_owned()); diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 668f57a7..bfea5324 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -1,5 +1,6 @@ use std::{path::Path, str}; +use anyhow::Context; use maplit::hashmap; use memofs::{IoResultExt, Vfs}; use rbx_dom_weak::RbxValue; @@ -28,9 +29,8 @@ pub fn snapshot_lua(context: &InstanceContext, vfs: &Vfs, path: &Path) -> Snapsh let contents = vfs.read(path)?; let contents_str = str::from_utf8(&contents) - // TODO: Turn into error type - .expect("File content was not valid UTF-8") - .to_string(); + .with_context(|| format!("File was not valid UTF-8: {}", path.display()))? + .to_owned(); let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); @@ -71,10 +71,14 @@ pub fn snapshot_lua_init( let dir_snapshot = snapshot_dir(context, vfs, folder_path)?.unwrap(); if dir_snapshot.class_name != "Folder" { - panic!( + anyhow::bail!( "init.lua, init.server.lua, and init.client.lua can \ - only be used if the instance produced by the parent \ - directory would be a Folder." + only be used if the instance produced by the containing \ + directory would be a Folder.\n\n\ + + The directory {} turned into an instance of class {}.", + folder_path.display(), + dir_snapshot.class_name ); } diff --git a/src/snapshot_middleware/meta_file.rs b/src/snapshot_middleware/meta_file.rs index 57f1e318..618f72c6 100644 --- a/src/snapshot_middleware/meta_file.rs +++ b/src/snapshot_middleware/meta_file.rs @@ -1,13 +1,12 @@ use std::{borrow::Cow, collections::HashMap, path::Path}; +use anyhow::Context; use rbx_dom_weak::UnresolvedRbxValue; use rbx_reflection::try_resolve_value; use serde::{Deserialize, Serialize}; use crate::snapshot::InstanceSnapshot; -use super::error::SnapshotError; - /// Represents metadata in a sibling file with the same basename. /// /// As an example, hello.meta.json next to hello.lua would allow assigning @@ -23,9 +22,13 @@ pub struct AdjacentMetadata { } impl AdjacentMetadata { - pub fn from_slice(slice: &[u8], path: &Path) -> Result { - serde_json::from_slice(slice) - .map_err(|source| SnapshotError::malformed_meta_json(source, path)) + pub fn from_slice(slice: &[u8], path: &Path) -> anyhow::Result { + serde_json::from_slice(slice).with_context(|| { + format!( + "File contained malformed .meta.json data: {}", + path.display() + ) + }) } pub fn apply_ignore_unknown_instances(&mut self, snapshot: &mut InstanceSnapshot) { @@ -75,9 +78,13 @@ pub struct DirectoryMetadata { } impl DirectoryMetadata { - pub fn from_slice(slice: &[u8], path: &Path) -> Result { - serde_json::from_slice(slice) - .map_err(|source| SnapshotError::malformed_meta_json(source, path)) + pub fn from_slice(slice: &[u8], path: &Path) -> anyhow::Result { + serde_json::from_slice(slice).with_context(|| { + format!( + "File contained malformed init.meta.json data: {}", + path.display() + ) + }) } pub fn apply_all(&mut self, snapshot: &mut InstanceSnapshot) { diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs index b05f0b9e..f576ede8 100644 --- a/src/snapshot_middleware/middleware.rs +++ b/src/snapshot_middleware/middleware.rs @@ -1,5 +1,3 @@ use crate::snapshot::InstanceSnapshot; -use super::error::SnapshotError; - -pub type SnapshotInstanceResult = Result, SnapshotError>; +pub type SnapshotInstanceResult = anyhow::Result>; diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 9563d8b6..bf9f4e8c 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -5,7 +5,6 @@ mod csv; mod dir; -mod error; mod json; mod json_model; mod lua; @@ -37,7 +36,6 @@ use self::{ util::match_file_name, }; -pub use self::error::*; pub use self::project::snapshot_project_node; pub fn snapshot_from_vfs( diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 94414bd5..c644c396 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -1,5 +1,6 @@ use std::{borrow::Cow, collections::HashMap, path::Path}; +use anyhow::Context; use memofs::Vfs; use rbx_reflection::{get_class_descriptor, try_resolve_value}; @@ -10,7 +11,7 @@ use crate::{ }, }; -use super::{error::SnapshotError, middleware::SnapshotInstanceResult, snapshot_from_vfs}; +use super::{middleware::SnapshotInstanceResult, snapshot_from_vfs}; pub fn snapshot_project( context: &InstanceContext, @@ -18,7 +19,7 @@ pub fn snapshot_project( path: &Path, ) -> SnapshotInstanceResult { let project = Project::load_from_slice(&vfs.read(path)?, path) - .map_err(|err| SnapshotError::malformed_project(err, path))?; + .with_context(|| format!("File was not a valid Rojo project: {}", path.display()))?; let mut context = context.clone(); diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 9d2dc4b6..68080b1d 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -1,11 +1,12 @@ use std::{collections::HashMap, path::Path}; +use anyhow::Context; use memofs::Vfs; use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{middleware::SnapshotInstanceResult, SnapshotError}; +use super::middleware::SnapshotInstanceResult; pub fn snapshot_rbxm( context: &InstanceContext, @@ -21,7 +22,7 @@ pub fn snapshot_rbxm( let root_id = temp_tree.get_root_id(); rbx_binary::decode(&mut temp_tree, root_id, vfs.read(path)?.as_slice()) - .map_err(|err| SnapshotError::malformed_rbxm(err, path))?; + .with_context(|| format!("Malformed rbxm file: {}", path.display()))?; let root_instance = temp_tree.get_instance(root_id).unwrap(); let children = root_instance.get_children_ids(); @@ -38,7 +39,11 @@ pub fn snapshot_rbxm( Ok(Some(snapshot)) } else { - panic!("Rojo doesn't have support for model files with zero or more than one top-level instances yet."); + anyhow::bail!( + "Rojo doesn't have support for model files with zero or more than one top-level instances yet.\n\n \ + Check the model file at path {}", + path.display() + ); } } diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 753bdc7d..e24a6f58 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -1,10 +1,11 @@ use std::path::Path; +use anyhow::Context; use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{middleware::SnapshotInstanceResult, SnapshotError}; +use super::middleware::SnapshotInstanceResult; pub fn snapshot_rbxmx( context: &InstanceContext, @@ -16,7 +17,7 @@ pub fn snapshot_rbxmx( .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); let temp_tree = rbx_xml::from_reader(vfs.read(path)?.as_slice(), options) - .map_err(|err| SnapshotError::malformed_rbxmx(err, path))?; + .with_context(|| format!("Malformed rbxm file: {}", path.display()))?; let root_instance = temp_tree.get_instance(temp_tree.get_root_id()).unwrap(); let children = root_instance.get_children_ids(); @@ -33,7 +34,11 @@ pub fn snapshot_rbxmx( Ok(Some(snapshot)) } else { - panic!("Rojo doesn't have support for model files with zero or more than one top-level instances yet."); + anyhow::bail!( + "Rojo doesn't have support for model files with zero or more than one top-level instances yet.\n\n \ + Check the model file at path {}", + path.display() + ); } } diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index edf1fbf5..4e408475 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -1,14 +1,13 @@ use std::{path::Path, str}; +use anyhow::Context; use maplit::hashmap; use memofs::{IoResultExt, Vfs}; use rbx_dom_weak::RbxValue; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{ - error::SnapshotError, meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult, -}; +use super::{meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult}; pub fn snapshot_txt( context: &InstanceContext, @@ -18,8 +17,8 @@ pub fn snapshot_txt( ) -> SnapshotInstanceResult { let contents = vfs.read(path)?; let contents_str = str::from_utf8(&contents) - .map_err(|err| SnapshotError::file_contents_bad_unicode(err, path))? - .to_string(); + .with_context(|| format!("File was not valid UTF-8: {}", path.display()))? + .to_owned(); let properties = hashmap! { "Value".to_owned() => RbxValue::String { From 02dbd4ba7565f9bc92fec36c1a3e6f4f265e46dc Mon Sep 17 00:00:00 2001 From: tacheometry <39647014+tacheometry@users.noreply.github.com> Date: Wed, 6 Jan 2021 22:49:05 +0200 Subject: [PATCH 1097/1504] fix hyphen (#378) This uses an em dash instead of double lines (--) --- plugin/http/Error.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/http/Error.lua b/plugin/http/Error.lua index 271a8ab7..ed85fc67 100644 --- a/plugin/http/Error.lua +++ b/plugin/http/Error.lua @@ -8,7 +8,7 @@ Error.Kind = { }, ConnectFailed = { message = "Couldn't connect to the Rojo server.\n" .. - "Make sure the server is running -- use 'rojo serve' to run it!", + "Make sure the server is running — use 'rojo serve' to run it!", }, Timeout = { message = "HTTP request timed out.", @@ -63,4 +63,4 @@ function Error.fromRobloxErrorString(message) return Error.new(Error.Kind.Unknown, message) end -return Error \ No newline at end of file +return Error From bb7bd2e27eabe97ea4e59bd10b0bb7b188dd6e99 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 13 Jan 2021 23:31:57 -0700 Subject: [PATCH 1098/1504] plugin: Update reflection database --- .../src/ReflectionDatabase/classes.lua | 717 +++++++++++++++--- 1 file changed, 624 insertions(+), 93 deletions(-) diff --git a/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua b/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua index b3b90619..f420140a 100644 --- a/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua +++ b/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua @@ -81,6 +81,17 @@ return { Name = "Accoutrement", }, }, + Actor = { + name = "Actor", + superclass = "Model", + properties = { + }, + defaults = { + LevelOfDetail = 0, + Name = "Actor", + PrimaryPart = nil, + }, + }, AdService = { name = "AdService", superclass = "Instance", @@ -275,7 +286,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, }, @@ -471,6 +482,14 @@ return { defaults = { }, }, + AppUpdateService = { + name = "AppUpdateService", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, ArcHandles = { name = "ArcHandles", superclass = "HandlesBase", @@ -502,6 +521,14 @@ return { defaults = { }, }, + AssetDeliveryProxy = { + name = "AssetDeliveryProxy", + superclass = "Instance", + properties = { + }, + defaults = { + }, + }, AssetManagerService = { name = "AssetManagerService", superclass = "Instance", @@ -877,6 +904,51 @@ return { scriptability = "ReadWrite", serializes = true, }, + AssemblyAngularVelocity = { + name = "AssemblyAngularVelocity", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + AssemblyCenterOfMass = { + name = "AssemblyCenterOfMass", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + AssemblyLinearVelocity = { + name = "AssemblyLinearVelocity", + type = {type = "Data", name = "Vector3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + AssemblyMass = { + name = "AssemblyMass", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + AssemblyRootPart = { + name = "AssemblyRootPart", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, BackParamA = { name = "BackParamA", type = {type = "Data", name = "Float32"}, @@ -976,6 +1048,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + CanTouch = { + name = "CanTouch", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, CastShadow = { name = "CastShadow", type = {type = "Data", name = "Bool"}, @@ -1419,6 +1500,59 @@ return { defaults = { }, }, + BaseWrap = { + name = "BaseWrap", + superclass = "Instance", + properties = { + CageMeshId = { + name = "CageMeshId", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CageOrigin = { + name = "CageOrigin", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + CageOriginWorld = { + name = "CageOriginWorld", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ImportOrigin = { + name = "ImportOrigin", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ImportOriginWorld = { + name = "ImportOriginWorld", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, Beam = { name = "Beam", superclass = "Instance", @@ -2662,13 +2796,13 @@ return { CFrame = CFrame.new(0, 20, 20, 1, 0, 0, 0, 0.7071068, 0.7071068, 0, -0.7071068, 0.7071068), CameraSubject = nil, CameraType = 0, - DiagonalFieldOfView = 0, + DiagonalFieldOfView = 88.87653, FieldOfView = 70, FieldOfViewMode = 0, Focus = CFrame.new(0, 0, -5, 1, 0, 0, 0, 1, 0, 0, 0, 1), HeadLocked = true, HeadScale = 1, - MaxAxisFieldOfView = 0, + MaxAxisFieldOfView = 70, Name = "Camera", }, }, @@ -2870,6 +3004,35 @@ return { defaults = { }, }, + Clouds = { + name = "Clouds", + superclass = "Instance", + properties = { + Cover = { + name = "Cover", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Density = { + name = "Density", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Cover = 0.5, + Density = 0.7, + Name = "Clouds", + }, + }, ClusterPacketCache = { name = "ClusterPacketCache", superclass = "Instance", @@ -3209,7 +3372,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, Version = { @@ -3257,6 +3420,8 @@ return { }, defaults = { Anchored = false, + AssemblyAngularVelocity = Vector3.new(0, 0, 0), + AssemblyLinearVelocity = Vector3.new(0, 0, 0), BackParamA = -0.5, BackParamB = 0.5, BackSurface = 0, @@ -3267,6 +3432,7 @@ return { BottomSurfaceInput = 0, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, + CanTouch = true, CastShadow = true, CollisionGroupId = 0, Color = Color3.new(0.6392157, 0.63529414, 0.64705884), @@ -3809,7 +3975,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, LegacyNamingScheme = { @@ -3818,7 +3984,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, }, @@ -3996,7 +4162,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, }, @@ -4840,6 +5006,8 @@ return { }, defaults = { Anchored = false, + AssemblyAngularVelocity = Vector3.new(0, 0, 0), + AssemblyLinearVelocity = Vector3.new(0, 0, 0), BackParamA = -0.5, BackParamB = 0.5, BackSurface = 0, @@ -4850,6 +5018,7 @@ return { BottomSurfaceInput = 0, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, + CanTouch = true, CastShadow = true, CollisionGroupId = 0, Color = Color3.new(0.6392157, 0.63529414, 0.64705884), @@ -5251,7 +5420,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, }, @@ -5843,7 +6012,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, CoreGuiFolder = { @@ -5852,7 +6021,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, CoreGuiNavigationEnabled = { @@ -5906,7 +6075,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, SelectedObject = { @@ -6052,6 +6221,15 @@ return { Name = "Hat", }, }, + HeightmapImporterService = { + name = "HeightmapImporterService", + superclass = "Instance", + properties = { + }, + defaults = { + Name = "HeightmapImporterService", + }, + }, HingeConstraint = { name = "HingeConstraint", superclass = "Constraint", @@ -6873,7 +7051,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, Pants = { @@ -8280,7 +8458,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, ForcePlayModeRobloxLocaleId = { @@ -8289,7 +8467,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, IsTextScraperRunning = { @@ -8298,7 +8476,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, RobloxForcePlayModeGameLocaleId = { @@ -8307,7 +8485,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, RobloxForcePlayModeRobloxLocaleId = { @@ -8316,7 +8494,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, RobloxLocaleId = { @@ -8609,6 +8787,8 @@ return { }, defaults = { Anchored = false, + AssemblyAngularVelocity = Vector3.new(0, 0, 0), + AssemblyLinearVelocity = Vector3.new(0, 0, 0), BackParamA = -0.5, BackParamB = 0.5, BackSurface = 0, @@ -8619,6 +8799,7 @@ return { BottomSurfaceInput = 0, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, + CanTouch = true, CastShadow = true, CollisionFidelity = 2, CollisionGroupId = 0, @@ -9011,6 +9192,8 @@ return { }, defaults = { Anchored = true, + AssemblyAngularVelocity = Vector3.new(0, 0, 0), + AssemblyLinearVelocity = Vector3.new(0, 0, 0), BackParamA = -0.5, BackParamB = 0.5, BackSurface = 0, @@ -9021,6 +9204,7 @@ return { BottomSurfaceInput = 0, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = false, + CanTouch = true, CastShadow = true, CollisionFidelity = 2, CollisionGroupId = 0, @@ -9294,7 +9478,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, }, @@ -9302,6 +9486,28 @@ return { Name = "NotificationService", }, }, + NumberPose = { + name = "NumberPose", + superclass = "PoseBase", + properties = { + Value = { + name = "Value", + type = {type = "Data", name = "Float64"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + EasingDirection = 0, + EasingStyle = 0, + Name = "Pose", + Value = 0, + Weight = 1, + }, + }, NumberValue = { name = "NumberValue", superclass = "ValueBase", @@ -9549,6 +9755,8 @@ return { }, defaults = { Anchored = false, + AssemblyAngularVelocity = Vector3.new(0, 0, 0), + AssemblyLinearVelocity = Vector3.new(0, 0, 0), BackParamA = -0.5, BackParamB = 0.5, BackSurface = 0, @@ -9559,6 +9767,7 @@ return { BottomSurfaceInput = 0, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, + CanTouch = true, CastShadow = true, CollisionGroupId = 0, Color = Color3.new(0.6392157, 0.63529414, 0.64705884), @@ -9659,6 +9868,8 @@ return { }, defaults = { Anchored = false, + AssemblyAngularVelocity = Vector3.new(0, 0, 0), + AssemblyLinearVelocity = Vector3.new(0, 0, 0), BackParamA = -0.5, BackParamB = 0.5, BackSurface = 0, @@ -9669,6 +9880,7 @@ return { BottomSurfaceInput = 0, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, + CanTouch = true, CastShadow = true, CollisionFidelity = 2, CollisionGroupId = 0, @@ -10635,22 +10847,58 @@ return { name = "PlayerEmulatorService", superclass = "Instance", properties = { + EmulatedCountryCode = { + name = "EmulatedCountryCode", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, + EmulatedGameLocale = { + name = "EmulatedGameLocale", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, PlayerEmulationEnabled = { name = "PlayerEmulationEnabled", type = {type = "Data", name = "Bool"}, isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", + serializes = true, + }, + PlayerEmulationEnabled_deprecated = { + name = "PlayerEmulationEnabled_deprecated", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", serializes = false, }, + SerializedEmulatedPolicyInfo = { + name = "SerializedEmulatedPolicyInfo", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, StudioEmulatedCountryRegionCode = { name = "StudioEmulatedCountryRegionCode", type = {type = "Data", name = "String"}, isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, }, @@ -10917,7 +11165,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, DefaultShortcut = { @@ -10926,7 +11174,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, Enabled = { @@ -10935,7 +11183,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, StatusTip = { @@ -11174,7 +11422,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, LuobuWhitelisted = { @@ -11183,7 +11431,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, }, @@ -11193,7 +11441,7 @@ return { }, Pose = { name = "Pose", - superclass = "Instance", + superclass = "PoseBase", properties = { CFrame = { name = "CFrame", @@ -11204,6 +11452,29 @@ return { scriptability = "ReadWrite", serializes = true, }, + MaskWeight = { + name = "MaskWeight", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + }, + defaults = { + CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + EasingDirection = 0, + EasingStyle = 0, + MaskWeight = 0, + Name = "Pose", + Weight = 1, + }, + }, + PoseBase = { + name = "PoseBase", + superclass = "Instance", + properties = { EasingDirection = { name = "EasingDirection", type = {type = "Enum", name = "PoseEasingDirection"}, @@ -11222,15 +11493,6 @@ return { scriptability = "ReadWrite", serializes = true, }, - MaskWeight = { - name = "MaskWeight", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, Weight = { name = "Weight", type = {type = "Data", name = "Float32"}, @@ -11242,12 +11504,6 @@ return { }, }, defaults = { - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - EasingDirection = 0, - EasingStyle = 0, - MaskWeight = 0, - Name = "Pose", - Weight = 1, }, }, PostEffect = { @@ -11306,6 +11562,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + AutoLocalize = { + name = "AutoLocalize", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, ClickablePrompt = { name = "ClickablePrompt", type = {type = "Data", name = "Bool"}, @@ -11387,6 +11652,15 @@ return { scriptability = "ReadWrite", serializes = true, }, + RootLocalizationTable = { + name = "RootLocalizationTable", + type = {type = "Data", name = "Ref"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, Style = { name = "Style", type = {type = "Enum", name = "ProximityPromptStyle"}, @@ -11408,6 +11682,7 @@ return { }, defaults = { ActionText = "Interact", + AutoLocalize = true, ClickablePrompt = true, Enabled = true, Exclusivity = 0, @@ -11418,6 +11693,7 @@ return { Name = "ProximityPrompt", ObjectText = "", RequiresLineOfSight = true, + RootLocalizationTable = nil, Style = 0, UIOffset = Vector2.new(0, 0), }, @@ -12504,7 +12780,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, }, @@ -12551,7 +12827,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, }, @@ -12870,6 +13146,8 @@ return { }, defaults = { Anchored = false, + AssemblyAngularVelocity = Vector3.new(0, 0, 0), + AssemblyLinearVelocity = Vector3.new(0, 0, 0), BackParamA = -0.5, BackParamB = 0.5, BackSurface = 0, @@ -12880,6 +13158,7 @@ return { BottomSurfaceInput = 0, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, + CanTouch = true, CastShadow = true, CollisionGroupId = 0, Color = Color3.new(0.6392157, 0.63529414, 0.64705884), @@ -13281,6 +13560,8 @@ return { }, defaults = { Anchored = false, + AssemblyAngularVelocity = Vector3.new(0, 0, 0), + AssemblyLinearVelocity = Vector3.new(0, 0, 0), BackParamA = -0.5, BackParamB = 0.5, BackSurface = 0, @@ -13291,6 +13572,7 @@ return { BottomSurfaceInput = 0, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, + CanTouch = true, CastShadow = true, CollisionGroupId = 0, Color = Color3.new(0.6392157, 0.63529414, 0.64705884), @@ -13837,6 +14119,24 @@ return { scriptability = "ReadWrite", serializes = true, }, + RollOffMaxDistance = { + name = "RollOffMaxDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, + RollOffMinDistance = { + name = "RollOffMinDistance", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = false, + }, RollOffMode = { name = "RollOffMode", type = {type = "Enum", name = "RollOffMode"}, @@ -13920,6 +14220,8 @@ return { PlayOnRemove = false, PlaybackSpeed = 1, Playing = false, + RollOffMaxDistance = 10000, + RollOffMinDistance = 10, RollOffMode = 0, SoundGroup = nil, SoundId = "", @@ -14123,6 +14425,8 @@ return { defaults = { AllowTeamChangeOnTouch = false, Anchored = false, + AssemblyAngularVelocity = Vector3.new(0, 0, 0), + AssemblyLinearVelocity = Vector3.new(0, 0, 0), BackParamA = -0.5, BackParamB = 0.5, BackSurface = 0, @@ -14133,6 +14437,7 @@ return { BottomSurfaceInput = 0, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, + CanTouch = true, CastShadow = true, CollisionGroupId = 0, Color = Color3.new(0.6392157, 0.63529414, 0.64705884), @@ -14650,7 +14955,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsAssetIDHead = { @@ -14659,7 +14964,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsAssetIDLeftArm = { @@ -14668,7 +14973,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsAssetIDLeftLeg = { @@ -14677,7 +14982,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsAssetIDPants = { @@ -14686,7 +14991,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsAssetIDRightArm = { @@ -14695,7 +15000,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsAssetIDRightLeg = { @@ -14704,7 +15009,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsAssetIDShirt = { @@ -14713,7 +15018,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsAssetIDTeeShirt = { @@ -14722,7 +15027,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsAssetIDTorso = { @@ -14731,7 +15036,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsAvatar = { @@ -14740,7 +15045,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsR15Collision = { @@ -14749,7 +15054,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsScaleRangeBodyType = { @@ -14758,7 +15063,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsScaleRangeHead = { @@ -14767,7 +15072,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsScaleRangeHeight = { @@ -14776,7 +15081,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsScaleRangeProportion = { @@ -14785,7 +15090,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, GameSettingsScaleRangeWidth = { @@ -14794,7 +15099,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, HealthDisplayDistance = { @@ -15179,7 +15484,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, EnableScriptCollabOnLoad = { @@ -15188,16 +15493,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - EnableScriptCollabVersionHistoryOnLoad = { - name = "EnableScriptCollabVersionHistoryOnLoad", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, SrcPlaceId = { @@ -15206,7 +15502,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, SrcUniverseId = { @@ -15215,7 +15511,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, }, @@ -15277,7 +15573,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, InstalledPluginData = { @@ -15304,7 +15600,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, ShowConstraintDetails = { @@ -15388,7 +15684,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, ColorMap = { @@ -15397,7 +15693,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, MetalnessMap = { @@ -15406,7 +15702,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, NormalMap = { @@ -15415,7 +15711,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, RoughnessMap = { @@ -15424,7 +15720,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, TexturePack = { @@ -15433,7 +15729,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, }, @@ -15705,7 +16001,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, Score = { @@ -15744,6 +16040,71 @@ return { Name = "Teams", }, }, + TeleportAsyncResult = { + name = "TeleportAsyncResult", + superclass = "Instance", + properties = { + PrivateServerId = { + name = "PrivateServerId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ReservedServerAccessCode = { + name = "ReservedServerAccessCode", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + }, + defaults = { + }, + }, + TeleportOptions = { + name = "TeleportOptions", + superclass = "Instance", + properties = { + ReservedServerAccessCode = { + name = "ReservedServerAccessCode", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ServerInstanceId = { + name = "ServerInstanceId", + type = {type = "Data", name = "String"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ShouldReserveServer = { + name = "ShouldReserveServer", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + Name = "Instance", + ReservedServerAccessCode = "", + ServerInstanceId = "", + ShouldReserveServer = false, + }, + }, TeleportService = { name = "TeleportService", superclass = "Instance", @@ -16033,7 +16394,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, Font = { @@ -16069,7 +16430,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, MultiLine = { @@ -16087,7 +16448,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, PlaceholderColor3 = { @@ -16114,7 +16475,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, RichText = { @@ -16204,7 +16565,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, TextScaled = { @@ -17347,6 +17708,8 @@ return { }, defaults = { Anchored = false, + AssemblyAngularVelocity = Vector3.new(0, 0, 0), + AssemblyLinearVelocity = Vector3.new(0, 0, 0), BackParamA = -0.5, BackParamB = 0.5, BackSurface = 5, @@ -17357,6 +17720,7 @@ return { BottomSurfaceInput = 0, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, + CanTouch = true, CastShadow = true, CollisionGroupId = 0, Color = Color3.new(0.6392157, 0.63529414, 0.64705884), @@ -18052,6 +18416,8 @@ return { }, defaults = { Anchored = false, + AssemblyAngularVelocity = Vector3.new(0, 0, 0), + AssemblyLinearVelocity = Vector3.new(0, 0, 0), BackParamA = -0.5, BackParamB = 0.5, BackSurface = 0, @@ -18062,6 +18428,7 @@ return { BottomSurfaceInput = 0, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, + CanTouch = true, CastShadow = true, CollisionFidelity = 2, CollisionGroupId = 0, @@ -18490,7 +18857,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, GyroscopeEnabled = { @@ -18517,7 +18884,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = true, }, ModalEnabled = { @@ -18616,7 +18983,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, RightBarSize = { @@ -18921,6 +19288,8 @@ return { }, defaults = { Anchored = false, + AssemblyAngularVelocity = Vector3.new(0, 0, 0), + AssemblyLinearVelocity = Vector3.new(0, 0, 0), BackParamA = -0.5, BackParamB = 0.5, BackSurface = 0, @@ -18931,6 +19300,7 @@ return { BottomSurfaceInput = 0, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, + CanTouch = true, CastShadow = true, CollisionGroupId = 0, Color = Color3.new(0.6392157, 0.63529414, 0.64705884), @@ -19263,7 +19633,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, }, @@ -19296,6 +19666,8 @@ return { }, defaults = { Anchored = false, + AssemblyAngularVelocity = Vector3.new(0, 0, 0), + AssemblyLinearVelocity = Vector3.new(0, 0, 0), BackParamA = -0.5, BackParamB = 0.5, BackSurface = 0, @@ -19306,6 +19678,7 @@ return { BottomSurfaceInput = 0, CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), CanCollide = true, + CanTouch = true, CastShadow = true, CollisionGroupId = 0, Color = Color3.new(0.6392157, 0.63529414, 0.64705884), @@ -19498,7 +19871,7 @@ return { isCanonical = true, canonicalName = nil, serializedName = nil, - scriptability = "ReadWrite", + scriptability = "None", serializes = false, }, StreamingEnabled = { @@ -19546,6 +19919,15 @@ return { scriptability = "Read", serializes = false, }, + TouchesUseCollisionGroups = { + name = "TouchesUseCollisionGroups", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = true, + }, }, defaults = { AllowThirdPartySales = false, @@ -19580,4 +19962,153 @@ return { defaults = { }, }, -} \ No newline at end of file + WrapLayer = { + name = "WrapLayer", + superclass = "BaseWrap", + properties = { + BindOffset = { + name = "BindOffset", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Color = { + name = "Color", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = false, + }, + DebugMode = { + name = "DebugMode", + type = {type = "Enum", name = "WrapLayerDebugMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = false, + }, + Enabled = { + name = "Enabled", + type = {type = "Data", name = "Bool"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Order = { + name = "Order", + type = {type = "Data", name = "Int32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + Puffiness = { + name = "Puffiness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ReferenceMeshId = { + name = "ReferenceMeshId", + type = {type = "Data", name = "Content"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ReferenceOrigin = { + name = "ReferenceOrigin", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + ReferenceOriginWorld = { + name = "ReferenceOriginWorld", + type = {type = "Data", name = "CFrame"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "Read", + serializes = false, + }, + ShrinkFactor = { + name = "ShrinkFactor", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + BindOffset = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + CageMeshId = "", + CageOrigin = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Enabled = true, + ImportOrigin = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Name = "WrapLayer", + Order = 1, + Puffiness = 1, + ReferenceMeshId = "", + ReferenceOrigin = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + ShrinkFactor = 0, + }, + }, + WrapTarget = { + name = "WrapTarget", + superclass = "BaseWrap", + properties = { + Color = { + name = "Color", + type = {type = "Data", name = "Color3"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = false, + }, + DebugMode = { + name = "DebugMode", + type = {type = "Enum", name = "WrapTargetDebugMode"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "None", + serializes = false, + }, + Stiffness = { + name = "Stiffness", + type = {type = "Data", name = "Float32"}, + isCanonical = true, + canonicalName = nil, + serializedName = nil, + scriptability = "ReadWrite", + serializes = true, + }, + }, + defaults = { + CageMeshId = "", + CageOrigin = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + ImportOrigin = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), + Name = "WrapTarget", + Stiffness = 0.9, + }, + }, +} From 040b9c14526995040fa1ede92edbd05af90bfbed Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 14 Jan 2021 11:55:24 -0700 Subject: [PATCH 1099/1504] Delete accidentally committed test bash script --- perf-test.sh | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 perf-test.sh diff --git a/perf-test.sh b/perf-test.sh deleted file mode 100644 index 1dcd00e2..00000000 --- a/perf-test.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -set -e - -cargo build --release - -echo "Known good:" -time rojo build ../uiblox/test-place.project.json -o UIBlox.rbxlx - -echo "Current:" -time ./target/release/rojo build ../uiblox/test-place.project.json -o UIBlox.rbxlx \ No newline at end of file From 5989ab3b8571701a1e19dd8706cdb7279b0b5a8f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 16 Jan 2021 15:34:59 -0700 Subject: [PATCH 1100/1504] Add project to test that plugin skips unwritable properties --- test-projects/script-unwritable/README.md | 2 ++ .../script-unwritable/default.project.json | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 test-projects/script-unwritable/README.md create mode 100644 test-projects/script-unwritable/default.project.json diff --git a/test-projects/script-unwritable/README.md b/test-projects/script-unwritable/README.md new file mode 100644 index 00000000..1a256f2b --- /dev/null +++ b/test-projects/script-unwritable/README.md @@ -0,0 +1,2 @@ +# script-unwritable +This project is used to test that Rojo successfully builds places with properties that are unwritable to scripts, but are ignored when the same project is used for live sync. \ No newline at end of file diff --git a/test-projects/script-unwritable/default.project.json b/test-projects/script-unwritable/default.project.json new file mode 100644 index 00000000..e64bfddd --- /dev/null +++ b/test-projects/script-unwritable/default.project.json @@ -0,0 +1,18 @@ +{ + "name": "script-unwritable", + "tree": { + "$className": "DataModel", + + "HttpService": { + "$properties": { + "HttpEnabled": true + } + }, + + "StarterPlayer": { + "$properties": { + "GameSettingsAvatar": "R15" + } + } + } +} \ No newline at end of file From cc4f4df4f95b57fa0633fe2fb881059e64dba288 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 16 Jan 2021 18:26:30 -0700 Subject: [PATCH 1101/1504] Support changing ClassName in Reconciler.diff --- plugin/src/Reconciler/diff.lua | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugin/src/Reconciler/diff.lua b/plugin/src/Reconciler/diff.lua index 67c8c161..d146b308 100644 --- a/plugin/src/Reconciler/diff.lua +++ b/plugin/src/Reconciler/diff.lua @@ -52,8 +52,9 @@ local function diff(instanceMap, virtualInstances, rootId) invariant("Cannot diff an instance not present in InstanceMap\nID: {}", id) end + local changedClassName = nil if virtualInstance.ClassName ~= instance.ClassName then - error("unimplemented: support changing ClassName") + changedClassName = virtualInstance.ClassName end local changedName = nil @@ -89,11 +90,11 @@ local function diff(instanceMap, virtualInstances, rootId) end end - if changedName ~= nil or not isEmpty(changedProperties) then + if changedName ~= nil or changedClassName ~= nil or not isEmpty(changedProperties) then table.insert(patch.updated, { id = id, changedName = changedName, - changedClassName = nil, + changedClassName = changedClassName, changedProperties = changedProperties, changedMetadata = nil, }) From 27af0c841bb5f14b889a4e8a386dfef4943fc475 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 16 Jan 2021 18:35:27 -0700 Subject: [PATCH 1102/1504] Release 6.0.0 --- CHANGELOG.md | 5 +++++ Cargo.lock | 2 +- Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 4 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8853f79e..59b8b038 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ ## Unreleased Changes +## [6.0.0](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0) (January 16, 2021) +* Improved server error messages + * The server will now keep running in more error cases +* Fixed Rojo being unable to diff ClassName changes + ## [6.0.0 Release Candidate 4](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0-rc.4) (December 14, 2020) * Added brand new Rojo UI ([#367](https://github.com/rojo-rbx/rojo/pull/367)) * Added `projectName` to `/api/rojo` output. diff --git a/Cargo.lock b/Cargo.lock index d8712b16..d763496d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1961,7 +1961,7 @@ dependencies = [ [[package]] name = "rojo" -version = "6.0.0-rc.4" +version = "6.0.0" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 75f12da1..3ec448f9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "6.0.0-rc.4" +version = "6.0.0" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 18d5d2a3..f12eec2e 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {6, 0, 0, "-rc.4"}, + version = {6, 0, 0}, expectedServerVersionString = "6.0 or newer", protocolVersion = 3, defaultHost = "localhost", From 4992c36f086853f4d690d2207783b7d4f4e9d99d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 18 Jan 2021 14:54:12 -0700 Subject: [PATCH 1103/1504] Delete ErrorDisplay, use anyhow instead! --- src/change_processor.rs | 3 +-- src/error.rs | 18 ------------------ src/lib.rs | 1 - 3 files changed, 1 insertion(+), 21 deletions(-) delete mode 100644 src/error.rs diff --git a/src/change_processor.rs b/src/change_processor.rs index a6ebdb03..449fe911 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -9,7 +9,6 @@ use memofs::{IoResultExt, Vfs, VfsEvent}; use rbx_dom_weak::{RbxId, RbxValue}; use crate::{ - error::ErrorDisplay, message_queue::MessageQueue, snapshot::{ apply_patch_set, compute_patch_set, AppliedPatchSet, InstigatingSource, PatchSet, RojoTree, @@ -313,7 +312,7 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: RbxId) -> Optio apply_patch_set(tree, patch_set) } Err(err) => { - log::error!("Error processing filesystem change: {}", ErrorDisplay(err)); + log::error!("Error processing filesystem change: {:?}", err); return None; } }, diff --git a/src/error.rs b/src/error.rs deleted file mode 100644 index 5c5a953e..00000000 --- a/src/error.rs +++ /dev/null @@ -1,18 +0,0 @@ -use std::{error::Error, fmt}; - -/// Wrapper type to print errors with source-chasing. -pub struct ErrorDisplay(pub E); - -impl fmt::Display for ErrorDisplay { - fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - writeln!(formatter, "{}", self.0)?; - - let mut current_err: &dyn Error = &self.0; - while let Some(source) = current_err.source() { - writeln!(formatter, " caused by {}", source)?; - current_err = &*source; - } - - Ok(()) - } -} diff --git a/src/lib.rs b/src/lib.rs index 7e594414..361c92e4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -9,7 +9,6 @@ mod tree_view; mod auth_cookie; mod change_processor; -mod error; mod glob; mod lua_ast; mod message_queue; From 804fd3de8e32c87e0c8a73d5db70360ae216a11b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 22 Jan 2021 13:41:55 -0700 Subject: [PATCH 1104/1504] Remove Requester header to handle API change --- CHANGELOG.md | 1 + src/cli/upload.rs | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 59b8b038..f1a5b4ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Fixed `rojo upload` requests being rejected by Roblox ## [6.0.0](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0) (January 16, 2021) * Improved server error messages diff --git a/src/cli/upload.rs b/src/cli/upload.rs index 49e367d1..20d2d28f 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -53,13 +53,16 @@ pub fn upload(options: UploadCommand) -> Result<(), anyhow::Error> { .post(&url) .header(COOKIE, format!(".ROBLOSECURITY={}", &cookie)) .header(USER_AGENT, "Roblox/WinInet") - .header("Requester", "Client") .header(CONTENT_TYPE, "application/xml") .header(ACCEPT, "application/json") .body(buffer) .send()?; - if !response.status().is_success() { + let status = response.status(); + + if !status.is_success() { + log::error!("Error uploading, status: {}", status); + return Err(Error::RobloxApi { body: response.text()?, } From 7888a704e17c5d6de17ce95bc85d1376954830b6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 22 Jan 2021 13:47:39 -0700 Subject: [PATCH 1105/1504] Release 6.0.1 --- CHANGELOG.md | 2 ++ Cargo.lock | 2 +- Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f1a5b4ff..81801bf4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes + +## [6.0.1](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.1) (January 22, 2021) * Fixed `rojo upload` requests being rejected by Roblox ## [6.0.0](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.0) (January 16, 2021) diff --git a/Cargo.lock b/Cargo.lock index d763496d..1b1733e2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1961,7 +1961,7 @@ dependencies = [ [[package]] name = "rojo" -version = "6.0.0" +version = "6.0.1" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 3ec448f9..1ed13047 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "6.0.0" +version = "6.0.1" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index f12eec2e..e3c1df95 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {6, 0, 0}, + version = {6, 0, 1}, expectedServerVersionString = "6.0 or newer", protocolVersion = 3, defaultHost = "localhost", From 0e89b91c38e71f49004e801abb3bf310582c3b37 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 9 Feb 2021 11:36:59 -0500 Subject: [PATCH 1106/1504] Implement CSRF challenge support in upload --- CHANGELOG.md | 1 + src/cli/upload.rs | 45 +++++++++++++++++++++++++++++++-------------- 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 81801bf4..e88506d3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Fixed `rojo upload` to handle CSRF challenges. ## [6.0.1](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.1) (January 22, 2021) * Fixed `rojo upload` requests being rejected by Roblox diff --git a/src/cli/upload.rs b/src/cli/upload.rs index 20d2d28f..e6969c22 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -1,5 +1,8 @@ use memofs::Vfs; -use reqwest::header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}; +use reqwest::{ + header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}, + StatusCode, +}; use thiserror::Error; use crate::{auth_cookie::get_auth_cookie, cli::UploadCommand, serve_session::ServeSession}; @@ -41,28 +44,42 @@ pub fn upload(options: UploadCommand) -> Result<(), anyhow::Error> { .property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown); rbx_xml::to_writer(&mut buffer, tree.inner(), &encode_ids, config)?; + do_upload(buffer, options.asset_id, &cookie) +} +fn do_upload(buffer: Vec, asset_id: u64, cookie: &str) -> anyhow::Result<()> { let url = format!( "https://data.roblox.com/Data/Upload.ashx?assetid={}", - options.asset_id + asset_id ); - log::trace!("POSTing to {}", url); let client = reqwest::Client::new(); - let mut response = client - .post(&url) - .header(COOKIE, format!(".ROBLOSECURITY={}", &cookie)) - .header(USER_AGENT, "Roblox/WinInet") - .header(CONTENT_TYPE, "application/xml") - .header(ACCEPT, "application/json") - .body(buffer) - .send()?; + + let build_request = move || { + client + .post(&url) + .header(COOKIE, format!(".ROBLOSECURITY={}", cookie)) + .header(USER_AGENT, "Roblox/WinInet") + .header(CONTENT_TYPE, "application/xml") + .header(ACCEPT, "application/json") + .body(buffer.clone()) + }; + + log::debug!("Uploading to Roblox..."); + let mut response = build_request().send()?; + + // Starting in Feburary, 2021, the upload endpoint performs CSRF challenges. + // If we receive an HTTP 403 with a X-CSRF-Token reply, we should retry the + // request, echoing the value of that header. + if response.status() == StatusCode::FORBIDDEN { + if let Some(csrf_token) = response.headers().get("X-CSRF-Token") { + log::debug!("Received CSRF challenge, retrying with token..."); + response = build_request().header("X-CSRF-Token", csrf_token).send()?; + } + } let status = response.status(); - if !status.is_success() { - log::error!("Error uploading, status: {}", status); - return Err(Error::RobloxApi { body: response.text()?, } From b84aab0960ff270a1e15cd0e6418042a6b486f6c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 9 Feb 2021 11:45:58 -0500 Subject: [PATCH 1107/1504] Release v6.0.2 --- CHANGELOG.md | 2 ++ Cargo.lock | 2 +- Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e88506d3..2a71ccc2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes + +## [6.0.2](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.2) (February 9, 2021) * Fixed `rojo upload` to handle CSRF challenges. ## [6.0.1](https://github.com/rojo-rbx/rojo/releases/tag/v6.0.1) (January 22, 2021) diff --git a/Cargo.lock b/Cargo.lock index 1b1733e2..b78491c5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1961,7 +1961,7 @@ dependencies = [ [[package]] name = "rojo" -version = "6.0.1" +version = "6.0.2" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 1ed13047..fb1eeafc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "6.0.1" +version = "6.0.2" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index e3c1df95..e681dca8 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {6, 0, 1}, + version = {6, 0, 2}, expectedServerVersionString = "6.0 or newer", protocolVersion = 3, defaultHost = "localhost", From 59ef5f05ea87a5c21dce2070cfa265a5c4c7cbfb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 18 Feb 2021 20:56:09 -0500 Subject: [PATCH 1108/1504] Upgrade to rbx_dom_weak 2.0 (#377) * Mostly mechanical port bits * Almost there * It builds again! * Turn on all the code again * Tests compiling but not passing * Stub work for value resolution * Implement resolution minus enums and derived properties * Implement property descriptor resolution * Update referent snapshots * Update unions test project Using a place file instead of a model yields better error messages in Roblox Studio. * Add easy shortcut to testing with local rbx-dom * Update rbx-dom * Add enum resolution * Update init.meta.json to use UnresolvedValue * Expand value resolution support, add test * Filter SharedString values from web API * Add 'property' builder method to InstanceSnapshot * Change InstanceSnapshot/InstanceBuilder boundary * Fix remove_file crash * rustfmt * Update to latest rbx_dom_lua * Update dependencies, including rbx_dom_weak * Update to latest rbx-dom * Update dependencies * Update rbx-dom, fixing more bugs * Remove experimental warning on binary place builds * Remove unused imports --- Cargo.lock | 578 +- Cargo.toml | 17 +- plugin/rbx_dom_lua/run-tests.lua | 1 + plugin/rbx_dom_lua/src/EncodedValue.lua | 167 +- plugin/rbx_dom_lua/src/EncodedValue.spec.lua | 162 +- plugin/rbx_dom_lua/src/PropertyDescriptor.lua | 2 +- .../src/ReflectionDatabase/classes.lua | 20114 ------- .../src/ReflectionDatabase/init.lua | 3 - plugin/rbx_dom_lua/src/allValues.json | 338 + plugin/rbx_dom_lua/src/database.json | 43997 ++++++++++++++++ plugin/rbx_dom_lua/src/init.lua | 18 +- plugin/rbx_dom_lua/test | 4 + plugin/rbx_dom_lua/test-place.project.json | 2 +- plugin/rbx_dom_lua/test.server.lua | 7 - ...d__tests__build__json_model_in_folder.snap | 2 +- ..._end__tests__build__unresolved_values.snap | 55 + .../unresolved_values/default.project.json | 43 + ...o_end__tests__serve__add_folder_all-2.snap | 2 +- ..._to_end__tests__serve__add_folder_all.snap | 2 +- ...to_end__tests__serve__edit_init_all-2.snap | 2 +- ...d_to_end__tests__serve__edit_init_all.snap | 2 +- .../end_to_end__tests__serve__empty_all.snap | 2 +- ...ts__serve__move_folder_of_stuff_all-2.snap | 2 +- ...ests__serve__move_folder_of_stuff_all.snap | 2 +- ..._end__tests__serve__remove_file_all-2.snap | 2 +- ...to_end__tests__serve__remove_file_all.snap | 2 +- ...d_to_end__tests__serve__scripts_all-2.snap | 2 +- ...end_to_end__tests__serve__scripts_all.snap | 2 +- src/change_processor.rs | 20 +- src/cli/build.rs | 10 +- src/cli/plugin.rs | 2 +- src/cli/upload.rs | 9 +- src/lib.rs | 1 + src/project.rs | 5 +- src/resolution.rs | 159 + src/serve_session.rs | 14 +- src/snapshot/instance_snapshot.rs | 42 +- src/snapshot/patch.rs | 22 +- src/snapshot/patch_apply.rs | 135 +- src/snapshot/patch_compute.rs | 67 +- src/snapshot/tests/apply.rs | 25 +- src/snapshot/tests/compute.rs | 29 +- src/snapshot/tree.rs | 193 +- src/snapshot_middleware/csv.rs | 9 +- src/snapshot_middleware/dir.rs | 4 +- src/snapshot_middleware/json.rs | 9 +- src/snapshot_middleware/json_model.rs | 42 +- src/snapshot_middleware/lua.rs | 9 +- src/snapshot_middleware/meta_file.rs | 90 +- src/snapshot_middleware/project.rs | 21 +- src/snapshot_middleware/rbxm.rs | 16 +- src/snapshot_middleware/rbxmx.rs | 4 +- ...are__json_model__test__model_from_vfs.snap | 2 +- src/snapshot_middleware/txt.rs | 9 +- src/tree_view.rs | 8 +- src/web/api.rs | 16 +- src/web/interface.rs | 41 +- src/web/ui.rs | 18 +- test-projects/enums/default.project.json | 12 + test-projects/unions/default.project.json | 8 +- tests/rojo_test/internable.rs | 18 +- tests/rojo_test/serve_util.rs | 4 +- tests/tests/build.rs | 1 + 63 files changed, 45602 insertions(+), 21004 deletions(-) create mode 100644 plugin/rbx_dom_lua/run-tests.lua delete mode 100644 plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua delete mode 100644 plugin/rbx_dom_lua/src/ReflectionDatabase/init.lua create mode 100644 plugin/rbx_dom_lua/src/allValues.json create mode 100644 plugin/rbx_dom_lua/src/database.json create mode 100644 plugin/rbx_dom_lua/test delete mode 100644 plugin/rbx_dom_lua/test.server.lua create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__unresolved_values.snap create mode 100644 rojo-test/build-tests/unresolved_values/default.project.json create mode 100644 src/resolution.rs create mode 100644 test-projects/enums/default.project.json diff --git a/Cargo.lock b/Cargo.lock index b78491c5..78daf125 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,9 +2,9 @@ # It is not intended for manual editing. [[package]] name = "addr2line" -version = "0.14.0" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c0929d69e78dd9bf5408269919fcbcaeb2e35e5d43e5815517cdc6a8e11a423" +checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" dependencies = [ "gimli", ] @@ -35,9 +35,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.35" +version = "1.0.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c0df63cb2955042487fad3aefd2c6e3ae7389ac5dc1beb28921de0b69f779d4" +checksum = "afddf7f520a80dbf76e6f50a35bca42a2331ef227a28b3b6dc5c2e2338d114b1" [[package]] name = "arrayref" @@ -76,9 +76,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.55" +version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5140344c85b01f9bbb4d4b7288a8aa4b3287ccef913a14bcc78a1063623598" +checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc" dependencies = [ "addr2line", "cfg-if 1.0.0", @@ -136,6 +136,21 @@ dependencies = [ "constant_time_eq", ] +[[package]] +name = "blake3" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46080006c1505f12f64dd2a09264b343381ed3190fa02c8005d5d662ac571c63" +dependencies = [ + "arrayref", + "arrayvec", + "cc", + "cfg-if 0.1.10", + "constant_time_eq", + "crypto-mac", + "digest", +] + [[package]] name = "block-buffer" version = "0.7.3" @@ -159,9 +174,9 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf" +checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d" dependencies = [ "lazy_static", "memchr", @@ -171,9 +186,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.4.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" +checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9" [[package]] name = "byte-tools" @@ -183,9 +198,9 @@ checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" [[package]] name = "byteorder" -version = "1.3.4" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08c48aae112d48ed9f069b33538ea9e3e90aa263cfa3d1c24309612b1f7472de" +checksum = "ae44d1a3d5a19df61dd0c8beb138458ac2a53a7ac09eba97d55592540004306b" [[package]] name = "bytes" @@ -251,23 +266,22 @@ dependencies = [ [[package]] name = "console" -version = "0.12.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0b1aacfaffdbff75be81c15a399b4bedf78aaefe840e8af1d299ac2ade885d2" +checksum = "7cc80946b3480f421c2f17ed1cb841753a371c7c5104f51d507e13f532c856aa" dependencies = [ "encode_unicode", "lazy_static", "libc", "terminal_size", - "termios", "winapi 0.3.9", ] [[package]] name = "const_fn" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd51eab21ab4fd6a3bf889e2d0958c0a6e3a61ad04260325e919e652a2a62826" +checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6" [[package]] name = "constant_time_eq" @@ -330,16 +344,16 @@ dependencies = [ [[package]] name = "criterion" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70daa7ceec6cf143990669a04c7df13391d55fb27bd4079d252fca774ba244d8" +checksum = "ab327ed7354547cc2ef43cbe20ef68b988e70b4b593cbd66a2a61733123a3d23" dependencies = [ "atty", "cast", "clap", "criterion-plot", "csv", - "itertools", + "itertools 0.10.0", "lazy_static", "num-traits", "oorandom", @@ -361,7 +375,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e022feadec601fba1649cfa83586381a4ad31c6bf3a9ab7d408118b05dd9889d" dependencies = [ "cast", - "itertools", + "itertools 0.9.0", ] [[package]] @@ -468,6 +482,16 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "crypto-mac" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +dependencies = [ + "generic-array", + "subtle", +] + [[package]] name = "csv" version = "1.1.5" @@ -492,11 +516,11 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.16" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fbaabec2c953050352311293be5c6aba8e141ba19d6811862b232d6fd020484" +checksum = "e8f45d9ad417bcef4817d614a501ab55cdd96a6fdb24f49aab89a54acfd66b19" dependencies = [ - "quote 1.0.7", + "quote 1.0.9", "syn", ] @@ -536,17 +560,11 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "doc-comment" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" - [[package]] name = "dtoa" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134951f4028bdadb9b84baf4232681efbf277da25144b9b0ad65df75946c422b" +checksum = "88d7ed2934d741c6b37e33e3832298e8850b53fd2d2bea03873375596c7cea4e" [[package]] name = "either" @@ -562,9 +580,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.26" +version = "0.8.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "801bbab217d7f79c0062f4f7205b5d4427c6d1a7bd7aafdd1475f7c59d62b283" +checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" dependencies = [ "cfg-if 1.0.0", ] @@ -608,7 +626,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", + "quote 1.0.9", "syn", "synstructure", ] @@ -621,21 +639,21 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "filetime" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c122a393ea57648015bf06fbd3d372378992e86b9ff5a7a497b076a28c79efe" +checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall", + "redox_syscall 0.2.5", "winapi 0.3.9", ] [[package]] name = "flate2" -version = "1.0.19" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7411863d55df97a419aa64cb4d2f167103ea9d767e2c54a1868b7ac3f6b47129" +checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" dependencies = [ "cfg-if 1.0.0", "crc32fast", @@ -748,15 +766,26 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc587bc0ec293155d5bfa6b9891ec18a1e330c234f896ea47fbada4cadbe47e6" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", "wasi 0.9.0+wasi-snapshot-preview1", ] +[[package]] +name = "getrandom" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "wasi 0.10.2+wasi-snapshot-preview1", +] + [[package]] name = "gimli" version = "0.23.0" @@ -796,9 +825,9 @@ dependencies = [ [[package]] name = "half" -version = "1.6.0" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d36fab90f82edc3c747f9d438e06cf0a491055896f2a279638bb5beed6c40177" +checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3" [[package]] name = "hashbrown" @@ -808,18 +837,18 @@ checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" [[package]] name = "heck" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" +checksum = "87cbf45460356b7deeb5e3415b5563308c0a9b057c85e12b06ad551f98d0a6ac" dependencies = [ "unicode-segmentation", ] [[package]] name = "hermit-abi" -version = "0.1.17" +version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" +checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c" dependencies = [ "libc", ] @@ -855,9 +884,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.3.4" +version = "1.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd179ae861f0c2e53da70d892f5f3029f9594be0c41dc5269cd371691b1dc2f9" +checksum = "615caabe2c3160b313d52ccc905335f4ed5f10881dd63dc5699d47e90be85691" [[package]] name = "humantime" @@ -924,9 +953,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02e2673c30ee86b5b96a9cb52ad15718aa1f966f5ab9ad54a8b95d5ca33120a9" +checksum = "de910d521f7cc3135c4de8db1cb910e0b5ed1dc6f57c381cd07e8e661ce10094" dependencies = [ "matches", "unicode-bidi", @@ -935,9 +964,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55e2e4c765aa53a0424761bf9f41aa7a6ac1efa87238f59560640e27fca028f2" +checksum = "4fb1fa934250de4de8aef298d81c729a7d33d8c239daa3a7575e6b92bfc7313b" dependencies = [ "autocfg 1.0.1", "hashbrown", @@ -956,27 +985,28 @@ dependencies = [ [[package]] name = "inotify-sys" -version = "0.1.4" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4563555856585ab3180a5bf0b2f9f8d301a728462afffc8195b3f5394229c55" +checksum = "e05c02b5e89bff3b946cedeca278abc628fe811e604f027c45a8aa3cf793d0eb" dependencies = [ "libc", ] [[package]] name = "insta" -version = "1.3.0" +version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "863bf97e7130bf788f29a99bc4073735af6b8ecc3da6a39c23b3a688d2d3109a" +checksum = "fd354a2c8c8083d58414597a4ecada1984f9b82ea7e87eeabddc869eaf120992" dependencies = [ "console", - "difference", "lazy_static", "pest", "pest_derive", "serde", "serde_json", "serde_yaml", + "similar", + "uuid 0.8.2", ] [[package]] @@ -998,10 +1028,19 @@ dependencies = [ ] [[package]] -name = "itoa" -version = "0.4.6" +name = "itertools" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" +checksum = "37d572918e350e82412fe766d24b15e6682fb2ed2bbe018280caa810397cb319" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" [[package]] name = "jod-thread" @@ -1011,9 +1050,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] name = "js-sys" -version = "0.3.46" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf3d7383929f7c9c7c2d0fa596f325832df98c3704f2c60553080f7127a58175" +checksum = "5cfb73131c35423a367daf8cbd24100af0d077668c8c2943f0e7dd775fef0f65" dependencies = [ "wasm-bindgen", ] @@ -1042,15 +1081,15 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.81" +version = "0.2.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1482821306169ec4d07f6aca392a4681f66c75c9918aa49641a2595db64053cb" +checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c" [[package]] name = "linked-hash-map" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dd5a6d5999d9907cda8ed67bbd137d3af8085216c2ac62de5be860bd41f304a" +checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" [[package]] name = "lock_api" @@ -1063,11 +1102,11 @@ dependencies = [ [[package]] name = "log" -version = "0.4.11" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", ] [[package]] @@ -1108,12 +1147,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" -[[package]] -name = "md5" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "490cc448043f947bae3cbee9c203358d62dbee0db12107a74be5c30ccfd09771" - [[package]] name = "memchr" version = "2.3.4" @@ -1230,9 +1263,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fcc7939b5edc4e4f86b1b4a04bb1498afaaf871b1a6691838ed06fcb48d3a3f" +checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" dependencies = [ "lazy_static", "libc", @@ -1296,9 +1329,15 @@ dependencies = [ [[package]] name = "object" -version = "0.22.0" +version = "0.23.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d3b63360ec3cb337817c2dbd47ab4a0f170d285d8e5a2064600f3def1402397" +checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" + +[[package]] +name = "once_cell" +version = "1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0" [[package]] name = "oorandom" @@ -1323,9 +1362,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.31" +version = "0.10.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d008f51b1acffa0d3450a68606e6a51c123012edaacb0f4e1426bd978869187" +checksum = "038d43985d1ddca7a9900630d8cd031b56e4794eecc2e9ea39dd17aa04399a70" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -1343,9 +1382,9 @@ checksum = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" [[package]] name = "openssl-sys" -version = "0.9.59" +version = "0.9.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de52d8eabd217311538a39bba130d7dea1f1e118010fee7a033d966845e7d5fe" +checksum = "921fc71883267538946025deffb622905ecad223c28efbfdef9bb59a0175f3e6" dependencies = [ "autocfg 1.0.1", "cc", @@ -1383,7 +1422,7 @@ dependencies = [ "cfg-if 0.1.10", "cloudabi", "libc", - "redox_syscall", + "redox_syscall 0.1.57", "rustc_version", "smallvec", "winapi 0.3.9", @@ -1448,7 +1487,7 @@ dependencies = [ "pest", "pest_meta", "proc-macro2 1.0.24", - "quote 1.0.7", + "quote 1.0.9", "syn", ] @@ -1471,16 +1510,32 @@ checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" [[package]] name = "plotters" -version = "0.2.15" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d1685fbe7beba33de0330629da9d955ac75bd54f33d7b79f9a895590124f6bb" +checksum = "45ca0ae5f169d0917a7c7f5a9c1a3d3d9598f18f529dd2b8373ed988efea307a" dependencies = [ - "js-sys", "num-traits", + "plotters-backend", + "plotters-svg", "wasm-bindgen", "web-sys", ] +[[package]] +name = "plotters-backend" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07fffcddc1cb3a1de753caa4e4df03b79922ba43cf882acc1bdd7e8df9f4590" + +[[package]] +name = "plotters-svg" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b38a02e23bd9604b842a812063aec4ef702b57989c37b655254bb61c471ad211" +dependencies = [ + "plotters-backend", +] + [[package]] name = "ppv-lite86" version = "0.2.10" @@ -1507,7 +1562,7 @@ checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", "proc-macro2 1.0.24", - "quote 1.0.7", + "quote 1.0.9", "syn", "version_check", ] @@ -1519,7 +1574,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", + "quote 1.0.9", "version_check", ] @@ -1531,9 +1586,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" [[package]] name = "proc-macro-nested" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eba180dafb9038b050a4c280019bbedf9f2467b61e5d892dcad585bb57aadc5a" +checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086" [[package]] name = "proc-macro2" @@ -1560,7 +1615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3bbaa49075179162b49acac1c6aa45fb4dafb5f13cf6794276d77bc7fd95757b" dependencies = [ "error-chain", - "idna 0.2.0", + "idna 0.2.1", "lazy_static", "regex", "url 2.2.0", @@ -1583,9 +1638,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ "proc-macro2 1.0.24", ] @@ -1615,13 +1670,25 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ - "getrandom", + "getrandom 0.1.16", "libc", "rand_chacha 0.2.2", "rand_core 0.5.1", "rand_hc 0.2.0", ] +[[package]] +name = "rand" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e" +dependencies = [ + "libc", + "rand_chacha 0.3.0", + "rand_core 0.6.2", + "rand_hc 0.3.0", +] + [[package]] name = "rand_chacha" version = "0.1.1" @@ -1642,6 +1709,16 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_chacha" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d" +dependencies = [ + "ppv-lite86", + "rand_core 0.6.2", +] + [[package]] name = "rand_core" version = "0.3.1" @@ -1663,7 +1740,16 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" dependencies = [ - "getrandom", + "getrandom 0.1.16", +] + +[[package]] +name = "rand_core" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7" +dependencies = [ + "getrandom 0.2.2", ] [[package]] @@ -1684,6 +1770,15 @@ dependencies = [ "rand_core 0.5.1", ] +[[package]] +name = "rand_hc" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73" +dependencies = [ + "rand_core 0.6.2", +] + [[package]] name = "rand_isaac" version = "0.1.1" @@ -1764,55 +1859,69 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b1c0c2b715bb763be1e27e5118e1f1ce0381f6c396a9cc8dd2c4b818cfa247d" +version = "0.6.0-dev" +source = "git+https://github.com/rojo-rbx/rbx-dom?branch=master#e75caa3cb0d283add38457ec2a20ed3fa3fef711" dependencies = [ - "byteorder", "log", "lz4", "rbx_dom_weak", "rbx_reflection", - "snafu", + "rbx_reflection_database", + "thiserror", ] [[package]] name = "rbx_dom_weak" -version = "1.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978b65ce742f3cb38c0b64ca48601a5590e6be9a14d12025b9cba2fe553b78c4" +version = "2.0.0-dev" +source = "git+https://github.com/rojo-rbx/rbx-dom?branch=master#e75caa3cb0d283add38457ec2a20ed3fa3fef711" dependencies = [ - "base64 0.11.0", - "lazy_static", - "md5", + "rbx_types", "serde", - "serde_derive", - "serde_repr", - "uuid 0.8.1", ] [[package]] name = "rbx_reflection" -version = "3.3.454" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9ccdde2a675eb13a8ecfe1f60879bf11ab29e9a671459d833929298873eedc4" +version = "4.0.0-dev" +source = "git+https://github.com/rojo-rbx/rbx-dom?branch=master#e75caa3cb0d283add38457ec2a20ed3fa3fef711" +dependencies = [ + "rbx_types", + "serde", +] + +[[package]] +name = "rbx_reflection_database" +version = "0.1.0" +source = "git+https://github.com/rojo-rbx/rbx-dom?branch=master#e75caa3cb0d283add38457ec2a20ed3fa3fef711" dependencies = [ - "bitflags", "lazy_static", - "rbx_dom_weak", + "rbx_reflection", + "rmp-serde", + "serde", +] + +[[package]] +name = "rbx_types" +version = "0.2.0" +source = "git+https://github.com/rojo-rbx/rbx-dom?branch=master#e75caa3cb0d283add38457ec2a20ed3fa3fef711" +dependencies = [ + "base64 0.11.0", + "bitflags", + "blake3", + "lazy_static", + "rand 0.7.3", "serde", ] [[package]] name = "rbx_xml" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6431f38b84582ec4e4f40b525cdcc713d4a984dcc2e3eecd1a67ae4da1172fbd" +version = "0.12.0-dev" +source = "git+https://github.com/rojo-rbx/rbx-dom?branch=master#e75caa3cb0d283add38457ec2a20ed3fa3fef711" dependencies = [ "base64 0.11.0", "log", "rbx_dom_weak", "rbx_reflection", + "rbx_reflection_database", "xml-rs", ] @@ -1831,22 +1940,31 @@ version = "0.1.57" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" +[[package]] +name = "redox_syscall" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9" +dependencies = [ + "bitflags", +] + [[package]] name = "redox_users" version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d" dependencies = [ - "getrandom", - "redox_syscall", + "getrandom 0.1.16", + "redox_syscall 0.1.57", "rust-argon2", ] [[package]] name = "regex" -version = "1.4.2" +version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" +checksum = "d9251239e129e16308e70d853559389de218ac275b515068abc96829d05b948a" dependencies = [ "aho-corasick", "memchr", @@ -1865,9 +1983,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.21" +version = "0.6.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" +checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581" [[package]] name = "remove_dir_all" @@ -1949,6 +2067,27 @@ dependencies = [ "num-traits", ] +[[package]] +name = "rmp" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f55e5fa1446c4d5dd1f5daeed2a4fe193071771a2636274d0d7a3b082aa7ad6" +dependencies = [ + "byteorder", + "num-traits", +] + +[[package]] +name = "rmp-serde" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ce7d70c926fe472aed493b902010bccc17fa9f7284145cb8772fd22fdb052d8" +dependencies = [ + "byteorder", + "rmp", + "serde", +] + [[package]] name = "roblox_install" version = "0.2.2" @@ -1988,6 +2127,7 @@ dependencies = [ "rbx_binary", "rbx_dom_weak", "rbx_reflection", + "rbx_reflection_database", "rbx_xml", "regex", "reqwest", @@ -2003,7 +2143,7 @@ dependencies = [ "termcolor", "thiserror", "tokio", - "uuid 0.8.1", + "uuid 0.8.2", "walkdir", "winreg", ] @@ -2114,9 +2254,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.118" +version = "1.0.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06c64263859d87aa2eb554587e2d23183398d617427327cf2b3d0ed8c69e4800" +checksum = "92d5161132722baa40d802cc70b15262b98258453e85e5d1d365c757c73869ae" dependencies = [ "serde_derive", ] @@ -2133,37 +2273,26 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.118" +version = "1.0.123" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c84d3526699cd55261af4b941e4e725444df67aa4f9e6a3564f18030d12672df" +checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", + "quote 1.0.9", "syn", ] [[package]] name = "serde_json" -version = "1.0.60" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1500e84d27fe482ed1dc791a56eddc2f230046a040fa908c08bda1d9fb615779" +checksum = "ea1c6153794552ea7cf7cf63b1231a25de00ec90db326ba6264440fa08e31486" dependencies = [ "itoa", "ryu", "serde", ] -[[package]] -name = "serde_repr" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc6b7951b17b051f3210b063f12cc17320e2fe30ae05b0fe2a3abb068551c76" -dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn", -] - [[package]] name = "serde_urlencoded" version = "0.5.5" @@ -2178,9 +2307,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.8.14" +version = "0.8.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7baae0a99f1a324984bcdc5f0718384c1f69775f1c7eec8b859b71b443e3fd7" +checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23" dependencies = [ "dtoa", "linked-hash-map", @@ -2200,6 +2329,12 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "similar" +version = "1.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a04629d2e8ecdcf30e0188e3699ed6d50d5750d0219db146a790065fe92a897" + [[package]] name = "slab" version = "0.4.2" @@ -2208,34 +2343,13 @@ checksum = "c111b5bd5695e56cffe5129854aa230b39c93a305372fdbb2668ca2394eea9f8" [[package]] name = "smallvec" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7b0758c52e15a8b5e3691eae6cc559f08eee9406e548a4477ba4e67770a82b6" +checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" dependencies = [ "maybe-uninit", ] -[[package]] -name = "snafu" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab12d3c261b2308b0d80c26fffb58d17eba81a4be97890101f416b478c79ca7" -dependencies = [ - "doc-comment", - "snafu-derive", -] - -[[package]] -name = "snafu-derive" -version = "0.6.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1508efa03c362e23817f96cde18abed596a25219a8b2c66e8db33c03543d315b" -dependencies = [ - "proc-macro2 1.0.24", - "quote 1.0.7", - "syn", -] - [[package]] name = "snax" version = "0.2.0" @@ -2280,18 +2394,24 @@ dependencies = [ "heck", "proc-macro-error", "proc-macro2 1.0.24", - "quote 1.0.7", + "quote 1.0.9", "syn", ] [[package]] -name = "syn" -version = "1.0.54" +name = "subtle" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a2af957a63d6bd42255c359c93d9bfdb97076bd3b820897ce55ffbfbf107f44" +checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" + +[[package]] +name = "syn" +version = "1.0.60" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", + "quote 1.0.9", "unicode-xid 0.2.1", ] @@ -2302,21 +2422,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b834f2d66f734cb897113e34aaff2f1ab4719ca946f9a7358dba8f8064148701" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", + "quote 1.0.9", "syn", "unicode-xid 0.2.1", ] [[package]] name = "tempfile" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6e24d9338a0a5be79593e2fa15a648add6138caa803e2d5bc782c371732ca9" +checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ - "cfg-if 0.1.10", + "cfg-if 1.0.0", "libc", - "rand 0.7.3", - "redox_syscall", + "rand 0.8.3", + "redox_syscall 0.2.5", "remove_dir_all", "winapi 0.3.9", ] @@ -2332,23 +2452,14 @@ dependencies = [ [[package]] name = "terminal_size" -version = "0.1.15" +version = "0.1.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bd2d183bd3fac5f5fe38ddbeb4dc9aec4a39a9d7d59e7491d900302da01cbe1" +checksum = "86ca8ced750734db02076f44132d802af0b33b09942331f4459dde8636fd2406" dependencies = [ "libc", "winapi 0.3.9", ] -[[package]] -name = "termios" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "411c5bf740737c7918b8b1fe232dca4dc9f8e754b8ad5e20966814001ed0ac6b" -dependencies = [ - "libc", -] - [[package]] name = "textwrap" version = "0.11.0" @@ -2360,49 +2471,48 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e9ae34b84616eedaaf1e9dd6026dbe00dcafa92aa0c8077cb69df1fcfe5e53e" +checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba20f23e85b10754cd195504aebf6a27e2e6cbe28c17778a0c930724628dd56" +checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", + "quote 1.0.9", "syn", ] [[package]] name = "thread_local" -version = "1.0.1" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +checksum = "8018d24e04c95ac8790716a5987d0fec4f8b27249ffa0f7d33f1369bdfb88cbd" dependencies = [ - "lazy_static", + "once_cell", ] [[package]] name = "time" -version = "0.1.44" +version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" dependencies = [ "libc", - "wasi 0.10.0+wasi-snapshot-preview1", "winapi 0.3.9", ] [[package]] name = "tinytemplate" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d3dc76004a03cec1c5932bca4cdc2e39aaa798e3f82363dd94f9adf6098c12f" +checksum = "a2ada8616fad06a2d0c455adc530de4ef57605a8120cc65da9653e0e9623ca74" dependencies = [ "serde", "serde_json", @@ -2410,9 +2520,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf8dbc19eb42fba10e8feaaec282fb50e2c14b2726d6301dbfeed0f73306a6f" +checksum = "317cca572a0e89c3ce0ca1f1bdc9369547fe318a683418e42ac8f59d14701023" dependencies = [ "tinyvec_macros", ] @@ -2663,9 +2773,9 @@ dependencies = [ [[package]] name = "unicode-normalization" -version = "0.1.16" +version = "0.1.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a13e63ab62dbe32aeee58d1c5408d35c36c392bba5d9d3142287219721afe606" +checksum = "07fbfce1c8a97d547e8b5334978438d9d6ec8c20e38f56d4a4374d181493eaef" dependencies = [ "tinyvec", ] @@ -2712,7 +2822,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e" dependencies = [ "form_urlencoded", - "idna 0.2.0", + "idna 0.2.1", "matches", "percent-encoding 2.1.0", ] @@ -2728,11 +2838,11 @@ dependencies = [ [[package]] name = "uuid" -version = "0.8.1" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fde2f6a4bea1d6e007c4ad38c6839fa71cbb63b6dbf5b595aa38dc9b1093c11" +checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "rand 0.7.3", + "getrandom 0.2.2", "serde", ] @@ -2784,15 +2894,15 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.69" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3cd364751395ca0f68cafb17666eee36b63077fb5ecd972bbcd74c90c4bf736e" +checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -2800,37 +2910,37 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.69" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1114f89ab1f4106e5b55e688b828c0ab0ea593a1ea7c094b141b14cbaaec2d62" +checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7" dependencies = [ "bumpalo", "lazy_static", "log", "proc-macro2 1.0.24", - "quote 1.0.7", + "quote 1.0.9", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.69" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6ac8995ead1f084a8dea1e65f194d0973800c7f571f6edd70adf06ecf77084" +checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c" dependencies = [ - "quote 1.0.7", + "quote 1.0.9", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.69" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5a48c72f299d80557c7c62e37e7225369ecc0c963964059509fbafe917c7549" +checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385" dependencies = [ "proc-macro2 1.0.24", - "quote 1.0.7", + "quote 1.0.9", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -2838,15 +2948,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.69" +version = "0.2.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e7811dd7f9398f14cc76efd356f98f03aa30419dea46aa810d71e819fc97158" +checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64" [[package]] name = "web-sys" -version = "0.3.46" +version = "0.3.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222b1ef9334f92a21d3fb53dc3fd80f30836959a90f9274a626d7e06315ba3c3" +checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3" dependencies = [ "js-sys", "wasm-bindgen", @@ -2922,9 +3032,9 @@ checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" [[package]] name = "yaml-rust" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39f0c922f1a334134dc2f7a8b67dc5d25f0735263feec974345ff706bcf20b0d" +checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] diff --git a/Cargo.toml b/Cargo.toml index fb1eeafc..af95a22b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -47,6 +47,19 @@ harness = false [dependencies] memofs = { version = "0.1.2", path = "memofs" } +# These dependencies can be uncommented when working on rbx-dom simultaneously +# rbx_binary = { path = "../rbx-dom/rbx_binary" } +# rbx_dom_weak = { path = "../rbx-dom/rbx_dom_weak" } +# rbx_reflection = { path = "../rbx-dom/rbx_reflection" } +# rbx_reflection_database = { path = "../rbx-dom/rbx_reflection_database" } +# rbx_xml = { path = "../rbx-dom/rbx_xml" } + +rbx_binary = { git = "https://github.com/rojo-rbx/rbx-dom", branch = "master" } +rbx_dom_weak = { git = "https://github.com/rojo-rbx/rbx-dom", branch = "master" } +rbx_reflection = { git = "https://github.com/rojo-rbx/rbx-dom", branch = "master" } +rbx_reflection_database = { git = "https://github.com/rojo-rbx/rbx-dom", branch = "master" } +rbx_xml = { git = "https://github.com/rojo-rbx/rbx-dom", branch = "master" } + anyhow = "1.0.27" backtrace = "0.3" bincode = "1.2.1" @@ -64,10 +77,6 @@ log = "0.4.8" maplit = "1.0.1" notify = "4.0.14" opener = "0.4.1" -rbx_binary = "0.5.0" -rbx_dom_weak = "1.10.1" -rbx_reflection = "3.3.408" -rbx_xml = "0.11.3" regex = "1.3.1" reqwest = "0.9.20" ritz = "0.1.0" diff --git a/plugin/rbx_dom_lua/run-tests.lua b/plugin/rbx_dom_lua/run-tests.lua new file mode 100644 index 00000000..c61bdc85 --- /dev/null +++ b/plugin/rbx_dom_lua/run-tests.lua @@ -0,0 +1 @@ +require(game.ReplicatedStorage.TestEZ).TestBootstrap:run({game.ReplicatedStorage.RbxDom}) \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/EncodedValue.lua b/plugin/rbx_dom_lua/src/EncodedValue.lua index a36de63b..61dc4ae4 100644 --- a/plugin/rbx_dom_lua/src/EncodedValue.lua +++ b/plugin/rbx_dom_lua/src/EncodedValue.lua @@ -20,6 +20,9 @@ local function serializeFloat(value) return value end +local ALL_AXES = {"X", "Y", "Z"} +local ALL_FACES = {"Right", "Top", "Back", "Left", "Bottom", "Front"} + local encoders encoders = { Bool = identity, @@ -33,12 +36,56 @@ encoders = { BinaryString = base64.encode, SharedString = base64.encode, + Axes = function(value) + local output = {} + + for _, axis in ipairs(ALL_AXES) do + if value[axis] then + table.insert(output, axis) + end + end + + return output + end, + + Faces = function(value) + local output = {} + + for _, face in ipairs(ALL_FACES) do + if value[face] then + table.insert(output, face) + end + end + + return output + end, + + Enum = function(value) + if typeof(value) == "number" then + return value + else + return value.Value + end + end, + BrickColor = function(value) return value.Number end, CFrame = function(value) - return {value:GetComponents()} + local x, y, z, + r00, r01, r02, + r10, r11, r12, + r20, r21, r22 = value:GetComponents() + + return { + Position = {x, y, z}, + Orientation = { + {r00, r10, r20}, + {r01, r11, r21}, + {r02, r12, r22}, + }, + } end, Color3 = function(value) return {value.r, value.g, value.b} @@ -77,15 +124,18 @@ encoders = { end, Rect = function(value) return { - Min = {value.Min.X, value.Min.Y}, - Max = {value.Max.X, value.Max.Y}, + encoders.Vector2(value.Min), + encoders.Vector2(value.Max), } end, UDim = function(value) return {value.Scale, value.Offset} end, UDim2 = function(value) - return {value.X.Scale, value.X.Offset, value.Y.Scale, value.Y.Offset} + return { + encoders.UDim(value.X), + encoders.UDim(value.Y), + } end, Vector2 = function(value) return { @@ -121,12 +171,35 @@ encoders = { end end, + Ray = function(value) + return { + Origin = encoders.Vector3(value.Origin), + Direction = encoders.Vector3(value.Direction), + } + end, + Ref = function(value) return nil end, + + Region3int16 = function(value) + return { + encoders.Vector3int16(value.Min), + encoders.Vector3int16(value.Max), + } + end, + + Color3uint8 = function(value) + return { + math.round(value.R * 255), + math.round(value.G * 255), + math.round(value.B * 255), + } + end, } -local decoders = { +local decoders +decoders = { Bool = identity, Content = identity, Enum = identity, @@ -141,19 +214,63 @@ local decoders = { BrickColor = BrickColor.new, - CFrame = unpackDecoder(CFrame.new), Color3 = unpackDecoder(Color3.new), Color3uint8 = unpackDecoder(Color3.fromRGB), NumberRange = unpackDecoder(NumberRange.new), UDim = unpackDecoder(UDim.new), - UDim2 = unpackDecoder(UDim2.new), Vector2 = unpackDecoder(Vector2.new), Vector2int16 = unpackDecoder(Vector2int16.new), Vector3 = unpackDecoder(Vector3.new), Vector3int16 = unpackDecoder(Vector3int16.new), + UDim2 = function(value) + return UDim2.new( + value[1][1], + value[1][2], + value[2][1], + value[2][2] + ) + end, + + Axes = function(value) + local axes = {} + for index, axisName in ipairs(value) do + axes[index] = Enum.Axis[axisName] + end + + return Axes.new(unpack(axes)) + end, + + Faces = function(value) + local normalIds = {} + for index, faceName in ipairs(value) do + normalIds[index] = Enum.NormalId[faceName] + end + + return Faces.new(unpack(normalIds)) + end, + + CFrame = function(value) + return CFrame.fromMatrix( + decoders.Vector3(value.Position), + decoders.Vector3(value.Orientation[1]), + decoders.Vector3(value.Orientation[2]), + decoders.Vector3(value.Orientation[3]) + ) + end, + Rect = function(value) - return Rect.new(value.Min[1], value.Min[2], value.Max[1], value.Max[2]) + return Rect.new( + decoders.Vector2(value[1]), + decoders.Vector2(value[2]) + ) + end, + + Ray = function(value) + return Ray.new( + decoders.Vector3(value.Origin), + decoders.Vector3(value.Direction) + ) end, NumberSequence = function(value) @@ -200,6 +317,13 @@ local decoders = { Ref = function() return nil end, + + Region3int16 = function(value) + return Region3int16.new( + decoders.Vector3int16(value[1]), + decoders.Vector3int16(value[2]) + ) + end, } local EncodedValue = {} @@ -216,27 +340,16 @@ end function EncodedValue.encode(rbxValue, propertyType) assert(propertyType ~= nil, "Property type descriptor is required") - if propertyType.type == "Data" then - local encoder = encoders[propertyType.name] + local encoder = encoders[propertyType] - if encoder == nil then - return false, ("Missing encoder for property type %q"):format(propertyType.name) - end - - if encoder ~= nil then - return true, { - Type = propertyType.name, - Value = encoder(rbxValue), - } - end - elseif propertyType.type == "Enum" then - return true, { - Type = "Enum", - Value = rbxValue.Value, - } + if encoder == nil then + return false, ("Missing encoder for property type %q"):format(propertyType) end - return false, ("Unknown property descriptor type %q"):format(tostring(propertyType.type)) + return true, { + Type = propertyType, + Value = encoder(rbxValue), + } end -return EncodedValue \ No newline at end of file +return EncodedValue diff --git a/plugin/rbx_dom_lua/src/EncodedValue.spec.lua b/plugin/rbx_dom_lua/src/EncodedValue.spec.lua index c58f801d..4590773b 100644 --- a/plugin/rbx_dom_lua/src/EncodedValue.spec.lua +++ b/plugin/rbx_dom_lua/src/EncodedValue.spec.lua @@ -1,127 +1,63 @@ return function() + local HttpService = game:GetService("HttpService") + local RbxDom = require(script.Parent) local EncodedValue = require(script.Parent.EncodedValue) + local allValues = require(script.Parent.allValues) - it("should decode Rect values", function() - local input = { - Type = "Rect", - Value = { - Min = {1, 2}, - Max = {3, 4}, - }, - } + local function deepEq(a, b) + if typeof(a) ~= typeof(b) then + return false + end - local output = Rect.new(1, 2, 3, 4) + local ty = typeof(a) - local ok, decoded = EncodedValue.decode(input) + if ty == "table" then + local visited = {} + + for key, valueA in pairs(a) do + visited[key] = true + + if not deepEq(valueA, b[key]) then + return false + end + end - assert(ok, decoded) - expect(decoded).to.equal(output) - end) + for key, valueB in pairs(b) do + if visited[key] then + continue + end - it("should decode ColorSequence values", function() - local input = { - Type = "ColorSequence", - Value = { - Keypoints = { - { - Time = 0, - Color = { 0.12, 0.34, 0.56 }, - }, + if not deepEq(valueB, a[key]) then + return false + end + end - { - Time = 1, - Color = { 0.13, 0.33, 0.37 }, - }, - } - }, - } + return true + else + return a == b + end + end - local output = ColorSequence.new({ - ColorSequenceKeypoint.new(0, Color3.new(0.12, 0.34, 0.56)), - ColorSequenceKeypoint.new(1, Color3.new(0.13, 0.33, 0.37)), - }) + for testName, testEntry in pairs(allValues) do + it("round trip " .. testName, function() + local ok, decoded = EncodedValue.decode(testEntry.value) + assert(ok, decoded) - local ok, decoded = EncodedValue.decode(input) - assert(ok, decoded) - expect(decoded).to.equal(output) - end) + local ok, encoded = EncodedValue.encode(decoded, testEntry.ty) + assert(ok, encoded) - it("should decode NumberSequence values", function() - local input = { - Type = "NumberSequence", - Value = { - Keypoints = { - { - Time = 0, - Value = 0.5, - Envelope = 0, - }, + if not deepEq(encoded, testEntry.value) then + local expected = HttpService:JSONEncode(testEntry.value) + local actual = HttpService:JSONEncode(encoded) - { - Time = 1, - Value = 0.5, - Envelope = 0, - }, - } - }, - } + local message = string.format( + "Round-trip results did not match.\nExpected:\n%s\nActual:\n%s", + expected, actual + ) - local output = NumberSequence.new({ - NumberSequenceKeypoint.new(0, 0.5, 0), - NumberSequenceKeypoint.new(1, 0.5, 0), - }) - - local ok, decoded = EncodedValue.decode(input) - assert(ok, decoded) - expect(decoded).to.equal(output) - end) - - it("should decode PhysicalProperties values", function() - local input = { - Type = "PhysicalProperties", - Value = { - Density = 0.1, - Friction = 0.2, - Elasticity = 0.3, - FrictionWeight = 0.4, - ElasticityWeight = 0.5, - }, - } - - local output = PhysicalProperties.new( - 0.1, - 0.2, - 0.3, - 0.4, - 0.5 - ) - - local ok, decoded = EncodedValue.decode(input) - assert(ok, decoded) - expect(decoded).to.equal(output) - end) - - -- This part of rbx_dom_lua needs some work still. - itSKIP("should encode Rect values", function() - local input = Rect.new(10, 20, 30, 40) - - local output = { - Type = "Rect", - Value = { - Min = {10, 20}, - Max = {30, 40}, - }, - } - - local descriptor = RbxDom.findCanonicalPropertyDescriptor("ImageLabel", "SliceCenter") - local ok, encoded = EncodedValue.encode(input, descriptor) - - assert(ok, encoded) - expect(encoded.Type).to.equal(output.Type) - expect(encoded.Value.Min[1]).to.equal(output.Value.Min[1]) - expect(encoded.Value.Min[2]).to.equal(output.Value.Min[2]) - expect(encoded.Value.Max[1]).to.equal(output.Value.Max[1]) - expect(encoded.Value.Max[2]).to.equal(output.Value.Max[2]) - end) -end \ No newline at end of file + error(message) + end + end) + end +end diff --git a/plugin/rbx_dom_lua/src/PropertyDescriptor.lua b/plugin/rbx_dom_lua/src/PropertyDescriptor.lua index d7fc577a..dcb53632 100644 --- a/plugin/rbx_dom_lua/src/PropertyDescriptor.lua +++ b/plugin/rbx_dom_lua/src/PropertyDescriptor.lua @@ -21,7 +21,7 @@ end function PropertyDescriptor.fromRaw(data, className, propertyName) return setmetatable({ - scriptability = data.scriptability, + scriptability = data.Scriptability, className = className, name = propertyName, }, PropertyDescriptor) diff --git a/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua b/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua deleted file mode 100644 index f420140a..00000000 --- a/plugin/rbx_dom_lua/src/ReflectionDatabase/classes.lua +++ /dev/null @@ -1,20114 +0,0 @@ --- This file is automatically @generated. -return { - ABTestService = { - name = "ABTestService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - Accessory = { - name = "Accessory", - superclass = "Accoutrement", - properties = { - }, - defaults = { - AttachmentForward = Vector3.new(0, 0, -1), - AttachmentPoint = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - AttachmentPos = Vector3.new(0, 0, 0), - AttachmentRight = Vector3.new(1, 0, 0), - AttachmentUp = Vector3.new(0, 1, 0), - Name = "Accessory", - }, - }, - Accoutrement = { - name = "Accoutrement", - superclass = "Instance", - properties = { - AttachmentForward = { - name = "AttachmentForward", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - AttachmentPoint = { - name = "AttachmentPoint", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AttachmentPos = { - name = "AttachmentPos", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - AttachmentRight = { - name = "AttachmentRight", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - AttachmentUp = { - name = "AttachmentUp", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - AttachmentForward = Vector3.new(0, 0, -1), - AttachmentPoint = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - AttachmentPos = Vector3.new(0, 0, 0), - AttachmentRight = Vector3.new(1, 0, 0), - AttachmentUp = Vector3.new(0, 1, 0), - Name = "Accoutrement", - }, - }, - Actor = { - name = "Actor", - superclass = "Model", - properties = { - }, - defaults = { - LevelOfDetail = 0, - Name = "Actor", - PrimaryPart = nil, - }, - }, - AdService = { - name = "AdService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "AdService", - }, - }, - AdvancedDragger = { - name = "AdvancedDragger", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "AdvancedDragger", - }, - }, - AlignOrientation = { - name = "AlignOrientation", - superclass = "Constraint", - properties = { - AlignType = { - name = "AlignType", - type = {type = "Enum", name = "AlignType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxAngularVelocity = { - name = "MaxAngularVelocity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxTorque = { - name = "MaxTorque", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PrimaryAxisOnly = { - name = "PrimaryAxisOnly", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ReactionTorqueEnabled = { - name = "ReactionTorqueEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Responsiveness = { - name = "Responsiveness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RigidityEnabled = { - name = "RigidityEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AlignType = 0, - Attachment0 = nil, - Attachment1 = nil, - Color = BrickColor.new(23), - Enabled = true, - MaxAngularVelocity = 1000000000, - MaxTorque = 10000, - Name = "AlignOrientation", - PrimaryAxisOnly = false, - ReactionTorqueEnabled = false, - Responsiveness = 10, - RigidityEnabled = false, - Visible = false, - }, - }, - AlignPosition = { - name = "AlignPosition", - superclass = "Constraint", - properties = { - ApplyAtCenterOfMass = { - name = "ApplyAtCenterOfMass", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxForce = { - name = "MaxForce", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxVelocity = { - name = "MaxVelocity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ReactionForceEnabled = { - name = "ReactionForceEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Responsiveness = { - name = "Responsiveness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RigidityEnabled = { - name = "RigidityEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - ApplyAtCenterOfMass = false, - Attachment0 = nil, - Attachment1 = nil, - Color = BrickColor.new(194), - Enabled = true, - MaxForce = 10000, - MaxVelocity = 1000000000, - Name = "AlignPosition", - ReactionForceEnabled = false, - Responsiveness = 10, - RigidityEnabled = false, - Visible = false, - }, - }, - AnalysticsSettings = { - name = "AnalysticsSettings", - superclass = "GenericSettings", - properties = { - }, - defaults = { - }, - }, - AnalyticsService = { - name = "AnalyticsService", - superclass = "Instance", - properties = { - ApiKey = { - name = "ApiKey", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - }, - defaults = { - Name = "AnalyticsService", - }, - }, - AngularVelocity = { - name = "AngularVelocity", - superclass = "Constraint", - properties = { - AngularVelocity = { - name = "AngularVelocity", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxTorque = { - name = "MaxTorque", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ReactionTorqueEnabled = { - name = "ReactionTorqueEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RelativeTo = { - name = "RelativeTo", - type = {type = "Enum", name = "ActuatorRelativeTo"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AngularVelocity = Vector3.new(0, 0, 0), - Attachment0 = nil, - Attachment1 = nil, - Color = BrickColor.new(23), - Enabled = true, - MaxTorque = 0, - Name = "AngularVelocity", - ReactionTorqueEnabled = false, - RelativeTo = 2, - Visible = false, - }, - }, - Animation = { - name = "Animation", - superclass = "Instance", - properties = { - AnimationId = { - name = "AnimationId", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AnimationId = "", - Name = "Animation", - }, - }, - AnimationController = { - name = "AnimationController", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "AnimationController", - }, - }, - AnimationTrack = { - name = "AnimationTrack", - superclass = "Instance", - properties = { - Animation = { - name = "Animation", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - IsPlaying = { - name = "IsPlaying", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Length = { - name = "Length", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Looped = { - name = "Looped", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Priority = { - name = "Priority", - type = {type = "Enum", name = "AnimationPriority"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Speed = { - name = "Speed", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TimePosition = { - name = "TimePosition", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - WeightCurrent = { - name = "WeightCurrent", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - WeightTarget = { - name = "WeightTarget", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - Animator = { - name = "Animator", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Animator", - }, - }, - AppStorageService = { - name = "AppStorageService", - superclass = "LocalStorageService", - properties = { - }, - defaults = { - }, - }, - AppUpdateService = { - name = "AppUpdateService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - ArcHandles = { - name = "ArcHandles", - superclass = "HandlesBase", - properties = { - Axes = { - name = "Axes", - type = {type = "Unimplemented", name = "Axes"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Adornee = nil, - Color = BrickColor.new(23), - Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - Name = "ArcHandles", - Transparency = 0, - Visible = true, - }, - }, - AssetCounterService = { - name = "AssetCounterService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - AssetDeliveryProxy = { - name = "AssetDeliveryProxy", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - AssetManagerService = { - name = "AssetManagerService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - AssetService = { - name = "AssetService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "AssetService", - }, - }, - Atmosphere = { - name = "Atmosphere", - superclass = "Instance", - properties = { - Color = { - name = "Color", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Decay = { - name = "Decay", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Density = { - name = "Density", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Glare = { - name = "Glare", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Haze = { - name = "Haze", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Offset = { - name = "Offset", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Color = Color3.new(0.7843, 0.6667, 0.4235), - Decay = Color3.new(0.3608, 0.2353, 0.0549), - Density = 0.395, - Glare = 0, - Haze = 0, - Name = "Atmosphere", - Offset = 0, - }, - }, - Attachment = { - name = "Attachment", - superclass = "Instance", - properties = { - Axis = { - name = "Axis", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - CFrame = { - name = "CFrame", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Orientation = { - name = "Orientation", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Position = { - name = "Position", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Rotation = { - name = "Rotation", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - SecondaryAxis = { - name = "SecondaryAxis", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Visible = { - name = "Visible", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WorldAxis = { - name = "WorldAxis", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - WorldCFrame = { - name = "WorldCFrame", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - WorldOrientation = { - name = "WorldOrientation", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - WorldPosition = { - name = "WorldPosition", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - WorldRotation = { - name = "WorldRotation", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - WorldSecondaryAxis = { - name = "WorldSecondaryAxis", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - Axis = Vector3.new(1, 0, 0), - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Name = "Attachment", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - SecondaryAxis = Vector3.new(0, 1, 0), - Visible = false, - WorldAxis = Vector3.new(1, 0, 0), - WorldCFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - WorldOrientation = Vector3.new(0, 0, 0), - WorldPosition = Vector3.new(0, 0, 0), - WorldSecondaryAxis = Vector3.new(0, 1, 0), - }, - }, - AvatarEditorService = { - name = "AvatarEditorService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "AvatarEditorService", - }, - }, - Backpack = { - name = "Backpack", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Backpack", - }, - }, - BackpackItem = { - name = "BackpackItem", - superclass = "Instance", - properties = { - TextureId = { - name = "TextureId", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - BadgeService = { - name = "BadgeService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "BadgeService", - }, - }, - BallSocketConstraint = { - name = "BallSocketConstraint", - superclass = "Constraint", - properties = { - LimitsEnabled = { - name = "LimitsEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxFrictionTorque = { - name = "MaxFrictionTorque", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Radius = { - name = "Radius", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Restitution = { - name = "Restitution", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TwistLimitsEnabled = { - name = "TwistLimitsEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TwistLowerAngle = { - name = "TwistLowerAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TwistUpperAngle = { - name = "TwistUpperAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UpperAngle = { - name = "UpperAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Attachment0 = nil, - Attachment1 = nil, - Color = BrickColor.new(1009), - Enabled = true, - LimitsEnabled = false, - MaxFrictionTorque = 0, - Name = "BallSocketConstraint", - Radius = 0.15, - Restitution = 0, - TwistLimitsEnabled = false, - TwistLowerAngle = -45, - TwistUpperAngle = 45, - UpperAngle = 45, - Visible = false, - }, - }, - BasePart = { - name = "BasePart", - superclass = "PVInstance", - properties = { - Anchored = { - name = "Anchored", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AssemblyAngularVelocity = { - name = "AssemblyAngularVelocity", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - AssemblyCenterOfMass = { - name = "AssemblyCenterOfMass", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - AssemblyLinearVelocity = { - name = "AssemblyLinearVelocity", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - AssemblyMass = { - name = "AssemblyMass", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - AssemblyRootPart = { - name = "AssemblyRootPart", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - BackParamA = { - name = "BackParamA", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BackParamB = { - name = "BackParamB", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BackSurface = { - name = "BackSurface", - type = {type = "Enum", name = "SurfaceType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BackSurfaceInput = { - name = "BackSurfaceInput", - type = {type = "Enum", name = "InputType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BottomParamA = { - name = "BottomParamA", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BottomParamB = { - name = "BottomParamB", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BottomSurface = { - name = "BottomSurface", - type = {type = "Enum", name = "SurfaceType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BottomSurfaceInput = { - name = "BottomSurfaceInput", - type = {type = "Enum", name = "InputType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BrickColor = { - name = "BrickColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = false, - canonicalName = "Color", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - CFrame = { - name = "CFrame", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CanCollide = { - name = "CanCollide", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CanTouch = { - name = "CanTouch", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CastShadow = { - name = "CastShadow", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CenterOfMass = { - name = "CenterOfMass", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - CollisionGroupId = { - name = "CollisionGroupId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CollisionGroups = { - name = "CollisionGroups", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Custom", - serializes = true, - }, - Color = { - name = "Color", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = "Color3uint8", - scriptability = "ReadWrite", - serializes = true, - }, - Color3uint8 = { - name = "Color3uint8", - type = {type = "Data", name = "Color3uint8"}, - isCanonical = false, - canonicalName = "Color", - serializedName = nil, - scriptability = "None", - serializes = false, - }, - CustomPhysicalProperties = { - name = "CustomPhysicalProperties", - type = {type = "Data", name = "PhysicalProperties"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Elasticity = { - name = "Elasticity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Friction = { - name = "Friction", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - FrontParamA = { - name = "FrontParamA", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FrontParamB = { - name = "FrontParamB", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FrontSurface = { - name = "FrontSurface", - type = {type = "Enum", name = "SurfaceType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FrontSurfaceInput = { - name = "FrontSurfaceInput", - type = {type = "Enum", name = "InputType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LeftParamA = { - name = "LeftParamA", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LeftParamB = { - name = "LeftParamB", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LeftSurface = { - name = "LeftSurface", - type = {type = "Enum", name = "SurfaceType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LeftSurfaceInput = { - name = "LeftSurfaceInput", - type = {type = "Enum", name = "InputType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LocalTransparencyModifier = { - name = "LocalTransparencyModifier", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Locked = { - name = "Locked", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Mass = { - name = "Mass", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Massless = { - name = "Massless", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Material = { - name = "Material", - type = {type = "Enum", name = "Material"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Orientation = { - name = "Orientation", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Position = { - name = "Position", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - ReceiveAge = { - name = "ReceiveAge", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Reflectance = { - name = "Reflectance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ResizeIncrement = { - name = "ResizeIncrement", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ResizeableFaces = { - name = "ResizeableFaces", - type = {type = "Unimplemented", name = "Faces"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - RightParamA = { - name = "RightParamA", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RightParamB = { - name = "RightParamB", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RightSurface = { - name = "RightSurface", - type = {type = "Enum", name = "SurfaceType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RightSurfaceInput = { - name = "RightSurfaceInput", - type = {type = "Enum", name = "InputType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RootPriority = { - name = "RootPriority", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RotVelocity = { - name = "RotVelocity", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Rotation = { - name = "Rotation", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Size = { - name = "Size", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = "size", - scriptability = "ReadWrite", - serializes = true, - }, - SpecificGravity = { - name = "SpecificGravity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TopParamA = { - name = "TopParamA", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TopParamB = { - name = "TopParamB", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TopSurface = { - name = "TopSurface", - type = {type = "Enum", name = "SurfaceType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TopSurfaceInput = { - name = "TopSurfaceInput", - type = {type = "Enum", name = "InputType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Transparency = { - name = "Transparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Velocity = { - name = "Velocity", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - brickColor = { - name = "brickColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = false, - canonicalName = "Color", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - size = { - name = "size", - type = {type = "Data", name = "Vector3"}, - isCanonical = false, - canonicalName = "Size", - serializedName = nil, - scriptability = "None", - serializes = false, - }, - }, - defaults = { - }, - }, - BasePlayerGui = { - name = "BasePlayerGui", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - BaseScript = { - name = "BaseScript", - superclass = "LuaSourceContainer", - properties = { - Disabled = { - name = "Disabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LinkedSource = { - name = "LinkedSource", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - BaseWrap = { - name = "BaseWrap", - superclass = "Instance", - properties = { - CageMeshId = { - name = "CageMeshId", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CageOrigin = { - name = "CageOrigin", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CageOriginWorld = { - name = "CageOriginWorld", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ImportOrigin = { - name = "ImportOrigin", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ImportOriginWorld = { - name = "ImportOriginWorld", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - Beam = { - name = "Beam", - superclass = "Instance", - properties = { - Attachment0 = { - name = "Attachment0", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Attachment1 = { - name = "Attachment1", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Color = { - name = "Color", - type = {type = "Data", name = "ColorSequence"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CurveSize0 = { - name = "CurveSize0", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CurveSize1 = { - name = "CurveSize1", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FaceCamera = { - name = "FaceCamera", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LightEmission = { - name = "LightEmission", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LightInfluence = { - name = "LightInfluence", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Segments = { - name = "Segments", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Texture = { - name = "Texture", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextureLength = { - name = "TextureLength", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextureMode = { - name = "TextureMode", - type = {type = "Enum", name = "TextureMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextureSpeed = { - name = "TextureSpeed", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Transparency = { - name = "Transparency", - type = {type = "Data", name = "NumberSequence"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Width0 = { - name = "Width0", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Width1 = { - name = "Width1", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ZOffset = { - name = "ZOffset", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Attachment0 = nil, - Attachment1 = nil, - Color = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.new(1, 1, 1)), ColorSequenceKeypoint.new(1, Color3.new(1, 1, 1))}), - CurveSize0 = 0, - CurveSize1 = 0, - Enabled = true, - FaceCamera = false, - LightEmission = 0, - LightInfluence = 0, - Name = "Beam", - Segments = 10, - Texture = "", - TextureLength = 1, - TextureMode = 0, - TextureSpeed = 1, - Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 0.5, 0), NumberSequenceKeypoint.new(1, 0.5, 0)}), - Width0 = 1, - Width1 = 1, - ZOffset = 0, - }, - }, - BevelMesh = { - name = "BevelMesh", - superclass = "DataModelMesh", - properties = { - }, - defaults = { - }, - }, - BillboardGui = { - name = "BillboardGui", - superclass = "LayerCollector", - properties = { - Active = { - name = "Active", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Adornee = { - name = "Adornee", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AlwaysOnTop = { - name = "AlwaysOnTop", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ClipsDescendants = { - name = "ClipsDescendants", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CurrentDistance = { - name = "CurrentDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - DistanceLowerLimit = { - name = "DistanceLowerLimit", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DistanceStep = { - name = "DistanceStep", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DistanceUpperLimit = { - name = "DistanceUpperLimit", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ExtentsOffset = { - name = "ExtentsOffset", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ExtentsOffsetWorldSpace = { - name = "ExtentsOffsetWorldSpace", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LightInfluence = { - name = "LightInfluence", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxDistance = { - name = "MaxDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PlayerToHideFrom = { - name = "PlayerToHideFrom", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Size = { - name = "Size", - type = {type = "Data", name = "UDim2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SizeOffset = { - name = "SizeOffset", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - StudsOffset = { - name = "StudsOffset", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - StudsOffsetWorldSpace = { - name = "StudsOffsetWorldSpace", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Active = false, - Adornee = nil, - AlwaysOnTop = false, - AutoLocalize = true, - ClipsDescendants = false, - DistanceLowerLimit = 0, - DistanceStep = 0, - DistanceUpperLimit = -1, - Enabled = true, - ExtentsOffset = Vector3.new(0, 0, 0), - ExtentsOffsetWorldSpace = Vector3.new(0, 0, 0), - LightInfluence = 0, - Localize = true, - MaxDistance = 1000000000, - Name = "BillboardGui", - PlayerToHideFrom = nil, - ResetOnSpawn = true, - RootLocalizationTable = nil, - Size = UDim2.new(0, 0, 0, 0), - SizeOffset = Vector2.new(0, 0), - StudsOffset = Vector3.new(0, 0, 0), - StudsOffsetWorldSpace = Vector3.new(0, 0, 0), - ZIndexBehavior = 0, - }, - }, - BinaryStringValue = { - name = "BinaryStringValue", - superclass = "ValueBase", - properties = { - }, - defaults = { - Name = "Value", - }, - }, - BindableEvent = { - name = "BindableEvent", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Event", - }, - }, - BindableFunction = { - name = "BindableFunction", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Function", - }, - }, - BlockMesh = { - name = "BlockMesh", - superclass = "BevelMesh", - properties = { - }, - defaults = { - Name = "Mesh", - Offset = Vector3.new(0, 0, 0), - Scale = Vector3.new(1, 1, 1), - VertexColor = Vector3.new(1, 1, 1), - }, - }, - BloomEffect = { - name = "BloomEffect", - superclass = "PostEffect", - properties = { - Intensity = { - name = "Intensity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Size = { - name = "Size", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Threshold = { - name = "Threshold", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Enabled = true, - Intensity = 0.4, - Name = "Bloom", - Size = 24, - Threshold = 0.95, - }, - }, - BlurEffect = { - name = "BlurEffect", - superclass = "PostEffect", - properties = { - Size = { - name = "Size", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Enabled = true, - Name = "Blur", - Size = 24, - }, - }, - BodyAngularVelocity = { - name = "BodyAngularVelocity", - superclass = "BodyMover", - properties = { - AngularVelocity = { - name = "AngularVelocity", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxTorque = { - name = "MaxTorque", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - P = { - name = "P", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - angularvelocity = { - name = "angularvelocity", - type = {type = "Data", name = "Vector3"}, - isCanonical = false, - canonicalName = "AngularVelocity", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - maxTorque = { - name = "maxTorque", - type = {type = "Data", name = "Vector3"}, - isCanonical = false, - canonicalName = "MaxTorque", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - AngularVelocity = Vector3.new(0, 2, 0), - MaxTorque = Vector3.new(4000, 4000, 4000), - Name = "BodyAngularVelocity", - P = 1250, - }, - }, - BodyColors = { - name = "BodyColors", - superclass = "CharacterAppearance", - properties = { - HeadColor = { - name = "HeadColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - HeadColor3 = { - name = "HeadColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LeftArmColor = { - name = "LeftArmColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - LeftArmColor3 = { - name = "LeftArmColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LeftLegColor = { - name = "LeftLegColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - LeftLegColor3 = { - name = "LeftLegColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RightArmColor = { - name = "RightArmColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - RightArmColor3 = { - name = "RightArmColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RightLegColor = { - name = "RightLegColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - RightLegColor3 = { - name = "RightLegColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TorsoColor = { - name = "TorsoColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - TorsoColor3 = { - name = "TorsoColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - HeadColor = BrickColor.new(226), - HeadColor3 = Color3.new(0.9921569, 0.9176471, 0.5529412), - LeftArmColor = BrickColor.new(226), - LeftArmColor3 = Color3.new(0.9921569, 0.9176471, 0.5529412), - LeftLegColor = BrickColor.new(23), - LeftLegColor3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - Name = "Body Colors", - RightArmColor = BrickColor.new(226), - RightArmColor3 = Color3.new(0.9921569, 0.9176471, 0.5529412), - RightLegColor = BrickColor.new(23), - RightLegColor3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - TorsoColor = BrickColor.new(28), - TorsoColor3 = Color3.new(0.15686275, 0.49803925, 0.2784314), - }, - }, - BodyForce = { - name = "BodyForce", - superclass = "BodyMover", - properties = { - Force = { - name = "Force", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - force = { - name = "force", - type = {type = "Data", name = "Vector3"}, - isCanonical = false, - canonicalName = "Force", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - Force = Vector3.new(0, 1, 0), - Name = "BodyForce", - }, - }, - BodyGyro = { - name = "BodyGyro", - superclass = "BodyMover", - properties = { - CFrame = { - name = "CFrame", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - D = { - name = "D", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxTorque = { - name = "MaxTorque", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - P = { - name = "P", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - cframe = { - name = "cframe", - type = {type = "Data", name = "CFrame"}, - isCanonical = false, - canonicalName = "CFrame", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - maxTorque = { - name = "maxTorque", - type = {type = "Data", name = "Vector3"}, - isCanonical = false, - canonicalName = "MaxTorque", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - D = 500, - MaxTorque = Vector3.new(400000, 0, 400000), - Name = "BodyGyro", - P = 3000, - }, - }, - BodyMover = { - name = "BodyMover", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - BodyPosition = { - name = "BodyPosition", - superclass = "BodyMover", - properties = { - D = { - name = "D", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxForce = { - name = "MaxForce", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - P = { - name = "P", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Position = { - name = "Position", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - maxForce = { - name = "maxForce", - type = {type = "Data", name = "Vector3"}, - isCanonical = false, - canonicalName = "MaxForce", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - position = { - name = "position", - type = {type = "Data", name = "Vector3"}, - isCanonical = false, - canonicalName = "Position", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - D = 1250, - MaxForce = Vector3.new(4000, 4000, 4000), - Name = "BodyPosition", - P = 10000, - Position = Vector3.new(0, 50, 0), - }, - }, - BodyThrust = { - name = "BodyThrust", - superclass = "BodyMover", - properties = { - Force = { - name = "Force", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Location = { - name = "Location", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - force = { - name = "force", - type = {type = "Data", name = "Vector3"}, - isCanonical = false, - canonicalName = "Force", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - location = { - name = "location", - type = {type = "Data", name = "Vector3"}, - isCanonical = false, - canonicalName = "Location", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - Force = Vector3.new(0, 1, 0), - Location = Vector3.new(0, 0, 0), - Name = "BodyThrust", - }, - }, - BodyVelocity = { - name = "BodyVelocity", - superclass = "BodyMover", - properties = { - MaxForce = { - name = "MaxForce", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - P = { - name = "P", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Velocity = { - name = "Velocity", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - maxForce = { - name = "maxForce", - type = {type = "Data", name = "Vector3"}, - isCanonical = false, - canonicalName = "MaxForce", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - velocity = { - name = "velocity", - type = {type = "Data", name = "Vector3"}, - isCanonical = false, - canonicalName = "Velocity", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - MaxForce = Vector3.new(4000, 4000, 4000), - Name = "BodyVelocity", - P = 1250, - Velocity = Vector3.new(0, 2, 0), - }, - }, - Bone = { - name = "Bone", - superclass = "Attachment", - properties = { - Transform = { - name = "Transform", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - TransformedCFrame = { - name = "TransformedCFrame", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TransformedWorldCFrame = { - name = "TransformedWorldCFrame", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - Axis = Vector3.new(1, 0, 0), - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Name = "Bone", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - SecondaryAxis = Vector3.new(0, 1, 0), - Transform = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Visible = false, - WorldAxis = Vector3.new(1, 0, 0), - WorldCFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - WorldOrientation = Vector3.new(0, 0, 0), - WorldPosition = Vector3.new(0, 0, 0), - WorldSecondaryAxis = Vector3.new(0, 1, 0), - }, - }, - BoolValue = { - name = "BoolValue", - superclass = "ValueBase", - properties = { - Value = { - name = "Value", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Value", - Value = false, - }, - }, - BoxHandleAdornment = { - name = "BoxHandleAdornment", - superclass = "HandleAdornment", - properties = { - Size = { - name = "Size", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AdornCullingMode = 0, - Adornee = nil, - AlwaysOnTop = false, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Color = BrickColor.new(23), - Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - Name = "BoxHandleAdornment", - Size = Vector3.new(1, 1, 1), - SizeRelativeOffset = Vector3.new(0, 0, 0), - Transparency = 0, - Visible = true, - ZIndex = -1, - }, - }, - BrickColorValue = { - name = "BrickColorValue", - superclass = "ValueBase", - properties = { - Value = { - name = "Value", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Value", - Value = BrickColor.new(194), - }, - }, - BrowserService = { - name = "BrowserService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - BulkImportService = { - name = "BulkImportService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - CFrameValue = { - name = "CFrameValue", - superclass = "ValueBase", - properties = { - Value = { - name = "Value", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Value", - Value = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - }, - }, - CSGDictionaryService = { - name = "CSGDictionaryService", - superclass = "FlyweightService", - properties = { - }, - defaults = { - }, - }, - CacheableContentProvider = { - name = "CacheableContentProvider", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - Camera = { - name = "Camera", - superclass = "Instance", - properties = { - CFrame = { - name = "CFrame", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CameraSubject = { - name = "CameraSubject", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CameraType = { - name = "CameraType", - type = {type = "Enum", name = "CameraType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CoordinateFrame = { - name = "CoordinateFrame", - type = {type = "Data", name = "CFrame"}, - isCanonical = false, - canonicalName = "CFrame", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - DiagonalFieldOfView = { - name = "DiagonalFieldOfView", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - FieldOfView = { - name = "FieldOfView", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FieldOfViewMode = { - name = "FieldOfViewMode", - type = {type = "Enum", name = "FieldOfViewMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Focus = { - name = "Focus", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HeadLocked = { - name = "HeadLocked", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HeadScale = { - name = "HeadScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxAxisFieldOfView = { - name = "MaxAxisFieldOfView", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - NearPlaneZ = { - name = "NearPlaneZ", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ViewportSize = { - name = "ViewportSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - focus = { - name = "focus", - type = {type = "Data", name = "CFrame"}, - isCanonical = false, - canonicalName = "Focus", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - CFrame = CFrame.new(0, 20, 20, 1, 0, 0, 0, 0.7071068, 0.7071068, 0, -0.7071068, 0.7071068), - CameraSubject = nil, - CameraType = 0, - DiagonalFieldOfView = 88.87653, - FieldOfView = 70, - FieldOfViewMode = 0, - Focus = CFrame.new(0, 0, -5, 1, 0, 0, 0, 1, 0, 0, 0, 1), - HeadLocked = true, - HeadScale = 1, - MaxAxisFieldOfView = 70, - Name = "Camera", - }, - }, - CatalogPages = { - name = "CatalogPages", - superclass = "Pages", - properties = { - }, - defaults = { - }, - }, - ChangeHistoryService = { - name = "ChangeHistoryService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "ChangeHistoryService", - }, - }, - CharacterAppearance = { - name = "CharacterAppearance", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - CharacterMesh = { - name = "CharacterMesh", - superclass = "CharacterAppearance", - properties = { - BaseTextureId = { - name = "BaseTextureId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BodyPart = { - name = "BodyPart", - type = {type = "Enum", name = "BodyPart"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MeshId = { - name = "MeshId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - OverlayTextureId = { - name = "OverlayTextureId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - BaseTextureId = 0, - BodyPart = 0, - MeshId = 0, - Name = "CharacterMesh", - OverlayTextureId = 0, - }, - }, - Chat = { - name = "Chat", - superclass = "Instance", - properties = { - BubbleChatEnabled = { - name = "BubbleChatEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LoadDefaultChat = { - name = "LoadDefaultChat", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = true, - }, - }, - defaults = { - BubbleChatEnabled = false, - LoadDefaultChat = true, - Name = "Chat", - }, - }, - ChorusSoundEffect = { - name = "ChorusSoundEffect", - superclass = "SoundEffect", - properties = { - Depth = { - name = "Depth", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Mix = { - name = "Mix", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Rate = { - name = "Rate", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Depth = 0.15, - Enabled = true, - Mix = 0.5, - Name = "ChorusSoundEffect", - Priority = 0, - Rate = 0.5, - }, - }, - ClickDetector = { - name = "ClickDetector", - superclass = "Instance", - properties = { - CursorIcon = { - name = "CursorIcon", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxActivationDistance = { - name = "MaxActivationDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - CursorIcon = "", - MaxActivationDistance = 32, - Name = "ClickDetector", - }, - }, - ClientReplicator = { - name = "ClientReplicator", - superclass = "NetworkReplicator", - properties = { - }, - defaults = { - }, - }, - Clothing = { - name = "Clothing", - superclass = "CharacterAppearance", - properties = { - Color3 = { - name = "Color3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - Clouds = { - name = "Clouds", - superclass = "Instance", - properties = { - Cover = { - name = "Cover", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Density = { - name = "Density", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Cover = 0.5, - Density = 0.7, - Name = "Clouds", - }, - }, - ClusterPacketCache = { - name = "ClusterPacketCache", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - CollectionService = { - name = "CollectionService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "CollectionService", - }, - }, - Color3Value = { - name = "Color3Value", - superclass = "ValueBase", - properties = { - Value = { - name = "Value", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Value", - Value = Color3.new(0, 0, 0), - }, - }, - ColorCorrectionEffect = { - name = "ColorCorrectionEffect", - superclass = "PostEffect", - properties = { - Brightness = { - name = "Brightness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Contrast = { - name = "Contrast", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Saturation = { - name = "Saturation", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TintColor = { - name = "TintColor", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Brightness = 0, - Contrast = 0, - Enabled = true, - Name = "ColorCorrection", - Saturation = 0, - TintColor = Color3.new(1, 1, 1), - }, - }, - CompressorSoundEffect = { - name = "CompressorSoundEffect", - superclass = "SoundEffect", - properties = { - Attack = { - name = "Attack", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GainMakeup = { - name = "GainMakeup", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Ratio = { - name = "Ratio", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Release = { - name = "Release", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SideChain = { - name = "SideChain", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Threshold = { - name = "Threshold", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Attack = 0.1, - Enabled = true, - GainMakeup = 0, - Name = "CompressorSoundEffect", - Priority = 0, - Ratio = 40, - Release = 0.1, - SideChain = nil, - Threshold = -40, - }, - }, - ConeHandleAdornment = { - name = "ConeHandleAdornment", - superclass = "HandleAdornment", - properties = { - Height = { - name = "Height", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Radius = { - name = "Radius", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AdornCullingMode = 0, - Adornee = nil, - AlwaysOnTop = false, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Color = BrickColor.new(23), - Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - Height = 2, - Name = "ConeHandleAdornment", - Radius = 0.5, - SizeRelativeOffset = Vector3.new(0, 0, 0), - Transparency = 0, - Visible = true, - ZIndex = -1, - }, - }, - Configuration = { - name = "Configuration", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Configuration", - }, - }, - Constraint = { - name = "Constraint", - superclass = "Instance", - properties = { - Active = { - name = "Active", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Attachment0 = { - name = "Attachment0", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Attachment1 = { - name = "Attachment1", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Color = { - name = "Color", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Visible = { - name = "Visible", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - ContentProvider = { - name = "ContentProvider", - superclass = "Instance", - properties = { - BaseUrl = { - name = "BaseUrl", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - RequestQueueSize = { - name = "RequestQueueSize", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - Name = "ContentProvider", - }, - }, - ContextActionService = { - name = "ContextActionService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "ContextActionService", - }, - }, - Controller = { - name = "Controller", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - ControllerService = { - name = "ControllerService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - CookiesService = { - name = "CookiesService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "CookiesService", - }, - }, - CoreGui = { - name = "CoreGui", - superclass = "BasePlayerGui", - properties = { - SelectionImageObject = { - name = "SelectionImageObject", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - Version = { - name = "Version", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - Name = "CoreGui", - }, - }, - CorePackages = { - name = "CorePackages", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - CoreScript = { - name = "CoreScript", - superclass = "BaseScript", - properties = { - }, - defaults = { - }, - }, - CoreScriptSyncService = { - name = "CoreScriptSyncService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - CornerWedgePart = { - name = "CornerWedgePart", - superclass = "BasePart", - properties = { - }, - defaults = { - Anchored = false, - AssemblyAngularVelocity = Vector3.new(0, 0, 0), - AssemblyLinearVelocity = Vector3.new(0, 0, 0), - BackParamA = -0.5, - BackParamB = 0.5, - BackSurface = 0, - BackSurfaceInput = 0, - BottomParamA = -0.5, - BottomParamB = 0.5, - BottomSurface = 0, - BottomSurfaceInput = 0, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CanCollide = true, - CanTouch = true, - CastShadow = true, - CollisionGroupId = 0, - Color = Color3.new(0.6392157, 0.63529414, 0.64705884), - CustomPhysicalProperties = nil, - Elasticity = 0.5, - Friction = 0.3, - FrontParamA = -0.5, - FrontParamB = 0.5, - FrontSurface = 0, - FrontSurfaceInput = 0, - LeftParamA = -0.5, - LeftParamB = 0.5, - LeftSurface = 0, - LeftSurfaceInput = 0, - LocalTransparencyModifier = 0, - Locked = false, - Massless = false, - Material = 256, - Name = "CornerWedge", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Reflectance = 0, - RightParamA = -0.5, - RightParamB = 0.5, - RightSurface = 0, - RightSurfaceInput = 0, - RootPriority = 0, - RotVelocity = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - Size = Vector3.new(2, 2, 2), - TopParamA = -0.5, - TopParamB = 0.5, - TopSurface = 0, - TopSurfaceInput = 0, - Transparency = 0, - Velocity = Vector3.new(0, 0, 0), - }, - }, - CustomEvent = { - name = "CustomEvent", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "CustomEvent", - }, - }, - CustomEventReceiver = { - name = "CustomEventReceiver", - superclass = "Instance", - properties = { - Source = { - name = "Source", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "CustomEventReceiver", - Source = nil, - }, - }, - CylinderHandleAdornment = { - name = "CylinderHandleAdornment", - superclass = "HandleAdornment", - properties = { - Angle = { - name = "Angle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Height = { - name = "Height", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - InnerRadius = { - name = "InnerRadius", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Radius = { - name = "Radius", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AdornCullingMode = 0, - Adornee = nil, - AlwaysOnTop = false, - Angle = 360, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Color = BrickColor.new(23), - Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - Height = 1, - InnerRadius = 0, - Name = "CylinderHandleAdornment", - Radius = 1, - SizeRelativeOffset = Vector3.new(0, 0, 0), - Transparency = 0, - Visible = true, - ZIndex = -1, - }, - }, - CylinderMesh = { - name = "CylinderMesh", - superclass = "BevelMesh", - properties = { - }, - defaults = { - Name = "Mesh", - Offset = Vector3.new(0, 0, 0), - Scale = Vector3.new(1, 1, 1), - VertexColor = Vector3.new(1, 1, 1), - }, - }, - CylindricalConstraint = { - name = "CylindricalConstraint", - superclass = "SlidingBallConstraint", - properties = { - AngularActuatorType = { - name = "AngularActuatorType", - type = {type = "Enum", name = "ActuatorType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AngularLimitsEnabled = { - name = "AngularLimitsEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AngularRestitution = { - name = "AngularRestitution", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AngularSpeed = { - name = "AngularSpeed", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AngularVelocity = { - name = "AngularVelocity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CurrentAngle = { - name = "CurrentAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - InclinationAngle = { - name = "InclinationAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LowerAngle = { - name = "LowerAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MotorMaxAngularAcceleration = { - name = "MotorMaxAngularAcceleration", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MotorMaxTorque = { - name = "MotorMaxTorque", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RotationAxisVisible = { - name = "RotationAxisVisible", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ServoMaxTorque = { - name = "ServoMaxTorque", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TargetAngle = { - name = "TargetAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UpperAngle = { - name = "UpperAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WorldRotationAxis = { - name = "WorldRotationAxis", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - ActuatorType = 0, - AngularActuatorType = 0, - AngularLimitsEnabled = false, - AngularRestitution = 0, - AngularSpeed = 0, - AngularVelocity = 0, - Attachment0 = nil, - Attachment1 = nil, - Color = BrickColor.new(1009), - Enabled = true, - InclinationAngle = 0, - LimitsEnabled = false, - LowerAngle = -45, - LowerLimit = 0, - MotorMaxAcceleration = 1000000000, - MotorMaxAngularAcceleration = 1000000000, - MotorMaxForce = 0, - MotorMaxTorque = 0, - Name = "CylindricalConstraint", - Restitution = 0, - RotationAxisVisible = false, - ServoMaxForce = 0, - ServoMaxTorque = 0, - Size = 0.15, - Speed = 0, - TargetAngle = 0, - TargetPosition = 0, - UpperAngle = 45, - UpperLimit = 5, - Velocity = 0, - Visible = false, - }, - }, - DataModel = { - name = "DataModel", - superclass = "ServiceProvider", - properties = { - CreatorId = { - name = "CreatorId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - CreatorType = { - name = "CreatorType", - type = {type = "Enum", name = "CreatorType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - GameId = { - name = "GameId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - GearGenreSetting = { - name = "GearGenreSetting", - type = {type = "Enum", name = "GearGenreSetting"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Genre = { - name = "Genre", - type = {type = "Enum", name = "Genre"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - IsSFFlagsLoaded = { - name = "IsSFFlagsLoaded", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - JobId = { - name = "JobId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - PlaceId = { - name = "PlaceId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - PlaceVersion = { - name = "PlaceVersion", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - PrivateServerId = { - name = "PrivateServerId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - PrivateServerOwnerId = { - name = "PrivateServerOwnerId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - VIPServerId = { - name = "VIPServerId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - VIPServerOwnerId = { - name = "VIPServerOwnerId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Workspace = { - name = "Workspace", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - lighting = { - name = "lighting", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - workspace = { - name = "workspace", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - DataModelMesh = { - name = "DataModelMesh", - superclass = "Instance", - properties = { - Offset = { - name = "Offset", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Scale = { - name = "Scale", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - VertexColor = { - name = "VertexColor", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - DataModelSession = { - name = "DataModelSession", - superclass = "Instance", - properties = { - CurrentDataModelType = { - name = "CurrentDataModelType", - type = {type = "Enum", name = "StudioDataModelType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - SessionId = { - name = "SessionId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - DataStorePages = { - name = "DataStorePages", - superclass = "Pages", - properties = { - }, - defaults = { - }, - }, - DataStoreService = { - name = "DataStoreService", - superclass = "Instance", - properties = { - AutomaticRetry = { - name = "AutomaticRetry", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - LegacyNamingScheme = { - name = "LegacyNamingScheme", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - }, - defaults = { - Name = "DataStoreService", - }, - }, - Debris = { - name = "Debris", - superclass = "Instance", - properties = { - MaxItems = { - name = "MaxItems", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = true, - }, - }, - defaults = { - MaxItems = 1000, - Name = "Debris", - }, - }, - DebugSettings = { - name = "DebugSettings", - superclass = "Instance", - properties = { - DataModel = { - name = "DataModel", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - InstanceCount = { - name = "InstanceCount", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - IsScriptStackTracingEnabled = { - name = "IsScriptStackTracingEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - JobCount = { - name = "JobCount", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - PlayerCount = { - name = "PlayerCount", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ReportSoundWarnings = { - name = "ReportSoundWarnings", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RobloxVersion = { - name = "RobloxVersion", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TickCountPreciseOverride = { - name = "TickCountPreciseOverride", - type = {type = "Enum", name = "TickCountSampleMethod"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - DebuggerBreakpoint = { - name = "DebuggerBreakpoint", - superclass = "Instance", - properties = { - Condition = { - name = "Condition", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IsEnabled = { - name = "IsEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Line = { - name = "Line", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - isContextDependentBreakpoint = { - name = "isContextDependentBreakpoint", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - DebuggerManager = { - name = "DebuggerManager", - superclass = "Instance", - properties = { - DebuggingEnabled = { - name = "DebuggingEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - DebuggerWatch = { - name = "DebuggerWatch", - superclass = "Instance", - properties = { - Expression = { - name = "Expression", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - }, - defaults = { - }, - }, - Decal = { - name = "Decal", - superclass = "FaceInstance", - properties = { - Color3 = { - name = "Color3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LocalTransparencyModifier = { - name = "LocalTransparencyModifier", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Shiny = { - name = "Shiny", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Specular = { - name = "Specular", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Texture = { - name = "Texture", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Transparency = { - name = "Transparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Color3 = Color3.new(1, 1, 1), - Face = 5, - LocalTransparencyModifier = 0, - Name = "Decal", - Shiny = 20, - Specular = 0, - Texture = "", - Transparency = 0, - }, - }, - DepthOfFieldEffect = { - name = "DepthOfFieldEffect", - superclass = "PostEffect", - properties = { - FarIntensity = { - name = "FarIntensity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FocusDistance = { - name = "FocusDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - InFocusRadius = { - name = "InFocusRadius", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - NearIntensity = { - name = "NearIntensity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Enabled = true, - FarIntensity = 0.75, - FocusDistance = 0.05, - InFocusRadius = 10, - Name = "DepthOfField", - NearIntensity = 0.75, - }, - }, - Dialog = { - name = "Dialog", - superclass = "Instance", - properties = { - BehaviorType = { - name = "BehaviorType", - type = {type = "Enum", name = "DialogBehaviorType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ConversationDistance = { - name = "ConversationDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GoodbyeChoiceActive = { - name = "GoodbyeChoiceActive", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GoodbyeDialog = { - name = "GoodbyeDialog", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - InUse = { - name = "InUse", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - InitialPrompt = { - name = "InitialPrompt", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Purpose = { - name = "Purpose", - type = {type = "Enum", name = "DialogPurpose"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Tone = { - name = "Tone", - type = {type = "Enum", name = "DialogTone"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TriggerDistance = { - name = "TriggerDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TriggerOffset = { - name = "TriggerOffset", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - BehaviorType = 0, - ConversationDistance = 25, - GoodbyeChoiceActive = true, - GoodbyeDialog = "", - InUse = false, - InitialPrompt = "", - Name = "Dialog", - Purpose = 1, - Tone = 0, - TriggerDistance = 0, - TriggerOffset = Vector3.new(0, 0, 0), - }, - }, - DialogChoice = { - name = "DialogChoice", - superclass = "Instance", - properties = { - GoodbyeChoiceActive = { - name = "GoodbyeChoiceActive", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GoodbyeDialog = { - name = "GoodbyeDialog", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ResponseDialog = { - name = "ResponseDialog", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UserDialog = { - name = "UserDialog", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - GoodbyeChoiceActive = true, - GoodbyeDialog = "", - Name = "DialogChoice", - ResponseDialog = "", - UserDialog = "", - }, - }, - DistortionSoundEffect = { - name = "DistortionSoundEffect", - superclass = "SoundEffect", - properties = { - Level = { - name = "Level", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Enabled = true, - Level = 0.75, - Name = "DistortionSoundEffect", - Priority = 0, - }, - }, - DockWidgetPluginGui = { - name = "DockWidgetPluginGui", - superclass = "PluginGui", - properties = { - HostWidgetWasRestored = { - name = "HostWidgetWasRestored", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - DoubleConstrainedValue = { - name = "DoubleConstrainedValue", - superclass = "ValueBase", - properties = { - ConstrainedValue = { - name = "ConstrainedValue", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - MaxValue = { - name = "MaxValue", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MinValue = { - name = "MinValue", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Value = { - name = "Value", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - ConstrainedValue = 0, - MaxValue = 1, - MinValue = 0, - Name = "Value", - Value = 0, - }, - }, - DraftsService = { - name = "DraftsService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "DraftsService", - }, - }, - Dragger = { - name = "Dragger", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Dragger", - }, - }, - DynamicRotate = { - name = "DynamicRotate", - superclass = "JointInstance", - properties = { - BaseAngle = { - name = "BaseAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - EchoSoundEffect = { - name = "EchoSoundEffect", - superclass = "SoundEffect", - properties = { - Delay = { - name = "Delay", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DryLevel = { - name = "DryLevel", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Feedback = { - name = "Feedback", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WetLevel = { - name = "WetLevel", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Delay = 1, - DryLevel = 0, - Enabled = true, - Feedback = 0.5, - Name = "EchoSoundEffect", - Priority = 0, - WetLevel = 0, - }, - }, - EmotesPages = { - name = "EmotesPages", - superclass = "InventoryPages", - properties = { - }, - defaults = { - }, - }, - EqualizerSoundEffect = { - name = "EqualizerSoundEffect", - superclass = "SoundEffect", - properties = { - HighGain = { - name = "HighGain", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LowGain = { - name = "LowGain", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MidGain = { - name = "MidGain", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Enabled = true, - HighGain = 0, - LowGain = -20, - MidGain = -10, - Name = "EqualizerSoundEffect", - Priority = 0, - }, - }, - EventIngestService = { - name = "EventIngestService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - Explosion = { - name = "Explosion", - superclass = "Instance", - properties = { - BlastPressure = { - name = "BlastPressure", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BlastRadius = { - name = "BlastRadius", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DestroyJointRadiusPercent = { - name = "DestroyJointRadiusPercent", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ExplosionType = { - name = "ExplosionType", - type = {type = "Enum", name = "ExplosionType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Position = { - name = "Position", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Visible = { - name = "Visible", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - BlastPressure = 500000, - BlastRadius = 4, - DestroyJointRadiusPercent = 1, - ExplosionType = 1, - Name = "Explosion", - Position = Vector3.new(0, 0, 0), - Visible = true, - }, - }, - FaceInstance = { - name = "FaceInstance", - superclass = "Instance", - properties = { - Face = { - name = "Face", - type = {type = "Enum", name = "NormalId"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - Feature = { - name = "Feature", - superclass = "Instance", - properties = { - FaceId = { - name = "FaceId", - type = {type = "Enum", name = "NormalId"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - InOut = { - name = "InOut", - type = {type = "Enum", name = "InOut"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LeftRight = { - name = "LeftRight", - type = {type = "Enum", name = "LeftRight"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TopBottom = { - name = "TopBottom", - type = {type = "Enum", name = "TopBottom"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - File = { - name = "File", - superclass = "Instance", - properties = { - FileName = { - name = "FileName", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - FileSize = { - name = "FileSize", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Size = { - name = "Size", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - FileMesh = { - name = "FileMesh", - superclass = "DataModelMesh", - properties = { - MeshId = { - name = "MeshId", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextureId = { - name = "TextureId", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - MeshId = "", - Name = "Mesh", - Offset = Vector3.new(0, 0, 0), - Scale = Vector3.new(1, 1, 1), - TextureId = "", - VertexColor = Vector3.new(1, 1, 1), - }, - }, - Fire = { - name = "Fire", - superclass = "Instance", - properties = { - Color = { - name = "Color", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Heat = { - name = "Heat", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = "heat_xml", - scriptability = "ReadWrite", - serializes = true, - }, - SecondaryColor = { - name = "SecondaryColor", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Size = { - name = "Size", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = "size_xml", - scriptability = "ReadWrite", - serializes = true, - }, - heat_xml = { - name = "heat_xml", - type = {type = "Data", name = "Float32"}, - isCanonical = false, - canonicalName = "Heat", - serializedName = nil, - scriptability = "None", - serializes = false, - }, - size = { - name = "size", - type = {type = "Data", name = "Float32"}, - isCanonical = false, - canonicalName = "Size", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - size_xml = { - name = "size_xml", - type = {type = "Data", name = "Float32"}, - isCanonical = false, - canonicalName = "Size", - serializedName = nil, - scriptability = "None", - serializes = false, - }, - }, - defaults = { - Color = Color3.new(0.92549026, 0.54509807, 0.27450982), - Enabled = true, - Heat = 9, - Name = "Fire", - SecondaryColor = Color3.new(0.54509807, 0.3137255, 0.21568629), - Size = 5, - }, - }, - Flag = { - name = "Flag", - superclass = "Tool", - properties = { - TeamColor = { - name = "TeamColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - CanBeDropped = true, - Enabled = true, - Grip = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - GripForward = Vector3.new(0, 0, -1), - GripPos = Vector3.new(0, 0, 0), - GripRight = Vector3.new(1, 0, 0), - GripUp = Vector3.new(0, 1, 0), - ManualActivationOnly = false, - Name = "Flag", - RequiresHandle = true, - TeamColor = BrickColor.new(194), - TextureId = "", - ToolTip = "", - }, - }, - FlagStand = { - name = "FlagStand", - superclass = "Part", - properties = { - TeamColor = { - name = "TeamColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Anchored = false, - AssemblyAngularVelocity = Vector3.new(0, 0, 0), - AssemblyLinearVelocity = Vector3.new(0, 0, 0), - BackParamA = -0.5, - BackParamB = 0.5, - BackSurface = 0, - BackSurfaceInput = 0, - BottomParamA = -0.5, - BottomParamB = 0.5, - BottomSurface = 4, - BottomSurfaceInput = 0, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CanCollide = true, - CanTouch = true, - CastShadow = true, - CollisionGroupId = 0, - Color = Color3.new(0.6392157, 0.63529414, 0.64705884), - CustomPhysicalProperties = nil, - Elasticity = 0.5, - FormFactor = 1, - Friction = 0.3, - FrontParamA = -0.5, - FrontParamB = 0.5, - FrontSurface = 0, - FrontSurfaceInput = 0, - LeftParamA = -0.5, - LeftParamB = 0.5, - LeftSurface = 0, - LeftSurfaceInput = 0, - LocalTransparencyModifier = 0, - Locked = false, - Massless = false, - Material = 256, - Name = "FlagStand", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Reflectance = 0, - RightParamA = -0.5, - RightParamB = 0.5, - RightSurface = 0, - RightSurfaceInput = 0, - RootPriority = 0, - RotVelocity = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - Shape = 1, - Size = Vector3.new(4, 1.2, 2), - TeamColor = BrickColor.new(194), - TopParamA = -0.5, - TopParamB = 0.5, - TopSurface = 3, - TopSurfaceInput = 0, - Transparency = 0, - Velocity = Vector3.new(0, 0, 0), - }, - }, - FlagStandService = { - name = "FlagStandService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - FlangeSoundEffect = { - name = "FlangeSoundEffect", - superclass = "SoundEffect", - properties = { - Depth = { - name = "Depth", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Mix = { - name = "Mix", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Rate = { - name = "Rate", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Depth = 0.45, - Enabled = true, - Mix = 0.85, - Name = "FlangeSoundEffect", - Priority = 0, - Rate = 5, - }, - }, - FloorWire = { - name = "FloorWire", - superclass = "GuiBase3d", - properties = { - CycleOffset = { - name = "CycleOffset", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - From = { - name = "From", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - StudsBetweenTextures = { - name = "StudsBetweenTextures", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Texture = { - name = "Texture", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextureSize = { - name = "TextureSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - To = { - name = "To", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Velocity = { - name = "Velocity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WireRadius = { - name = "WireRadius", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Color = BrickColor.new(23), - Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - CycleOffset = 0, - From = nil, - Name = "FloorWire", - StudsBetweenTextures = 4, - Texture = "", - TextureSize = Vector2.new(1, 1), - To = nil, - Transparency = 0, - Velocity = 2, - Visible = true, - WireRadius = 0.0625, - }, - }, - FlyweightService = { - name = "FlyweightService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - Folder = { - name = "Folder", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Folder", - }, - }, - ForceField = { - name = "ForceField", - superclass = "Instance", - properties = { - Visible = { - name = "Visible", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "ForceField", - Visible = true, - }, - }, - FormFactorPart = { - name = "FormFactorPart", - superclass = "BasePart", - properties = { - FormFactor = { - name = "FormFactor", - type = {type = "Enum", name = "FormFactor"}, - isCanonical = true, - canonicalName = nil, - serializedName = "formFactorRaw", - scriptability = "ReadWrite", - serializes = true, - }, - formFactor = { - name = "formFactor", - type = {type = "Enum", name = "FormFactor"}, - isCanonical = false, - canonicalName = "FormFactor", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - formFactorRaw = { - name = "formFactorRaw", - type = {type = "Enum", name = "FormFactor"}, - isCanonical = false, - canonicalName = "FormFactor", - serializedName = nil, - scriptability = "None", - serializes = false, - }, - }, - defaults = { - }, - }, - Frame = { - name = "Frame", - superclass = "GuiObject", - properties = { - Style = { - name = "Style", - type = {type = "Enum", name = "FrameStyle"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Active = false, - AnchorPoint = Vector2.new(0, 0), - AutoLocalize = true, - AutomaticSize = 0, - BackgroundColor = BrickColor.new(194), - BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), - BackgroundTransparency = 0, - BorderColor = BrickColor.new(26), - BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), - BorderMode = 0, - BorderSizePixel = 1, - ClipsDescendants = false, - Draggable = false, - LayoutOrder = 0, - Localize = true, - Name = "Frame", - NextSelectionDown = nil, - NextSelectionLeft = nil, - NextSelectionRight = nil, - NextSelectionUp = nil, - Position = UDim2.new(0, 0, 0, 0), - RootLocalizationTable = nil, - Rotation = 0, - Selectable = false, - SelectionImageObject = nil, - Size = UDim2.new(0, 0, 0, 0), - SizeConstraint = 0, - Style = 0, - Transparency = 0, - Visible = true, - ZIndex = 1, - }, - }, - FriendPages = { - name = "FriendPages", - superclass = "Pages", - properties = { - }, - defaults = { - }, - }, - FriendService = { - name = "FriendService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "FriendService", - }, - }, - FunctionalTest = { - name = "FunctionalTest", - superclass = "Instance", - properties = { - Description = { - name = "Description", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Description = "?", - Name = "Instance", - }, - }, - GamePassService = { - name = "GamePassService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "GamePassService", - }, - }, - GameSettings = { - name = "GameSettings", - superclass = "Instance", - properties = { - AdditionalCoreIncludeDirs = { - name = "AdditionalCoreIncludeDirs", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - OverrideStarterScript = { - name = "OverrideStarterScript", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - VideoCaptureEnabled = { - name = "VideoCaptureEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - VideoRecording = { - name = "VideoRecording", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - }, - }, - GamepadService = { - name = "GamepadService", - superclass = "Instance", - properties = { - GamepadCursorEnabled = { - name = "GamepadCursorEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - }, - defaults = { - Name = "GamepadService", - }, - }, - GenericSettings = { - name = "GenericSettings", - superclass = "ServiceProvider", - properties = { - }, - defaults = { - }, - }, - Geometry = { - name = "Geometry", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Geometry", - }, - }, - GlobalDataStore = { - name = "GlobalDataStore", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - GlobalSettings = { - name = "GlobalSettings", - superclass = "GenericSettings", - properties = { - }, - defaults = { - }, - }, - Glue = { - name = "Glue", - superclass = "JointInstance", - properties = { - F0 = { - name = "F0", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - F1 = { - name = "F1", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - F2 = { - name = "F2", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - F3 = { - name = "F3", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Enabled = true, - F0 = Vector3.new(0, 0, 0), - F1 = Vector3.new(0, 0, 0), - F2 = Vector3.new(0, 0, 0), - F3 = Vector3.new(0, 0, 0), - Name = "Glue", - Part0 = nil, - Part1 = nil, - }, - }, - GoogleAnalyticsConfiguration = { - name = "GoogleAnalyticsConfiguration", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - GroupService = { - name = "GroupService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "GroupService", - }, - }, - GuiBase = { - name = "GuiBase", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - GuiBase2d = { - name = "GuiBase2d", - superclass = "GuiBase", - properties = { - AbsolutePosition = { - name = "AbsolutePosition", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - AbsoluteRotation = { - name = "AbsoluteRotation", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - AbsoluteSize = { - name = "AbsoluteSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - AutoLocalize = { - name = "AutoLocalize", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ClippedRect = { - name = "ClippedRect", - type = {type = "Data", name = "Rect"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - IsNotOccluded = { - name = "IsNotOccluded", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Localize = { - name = "Localize", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - RawRect2D = { - name = "RawRect2D", - type = {type = "Data", name = "Rect"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - RootLocalizationTable = { - name = "RootLocalizationTable", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TotalGroupScale = { - name = "TotalGroupScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - GuiBase3d = { - name = "GuiBase3d", - superclass = "GuiBase", - properties = { - Color = { - name = "Color", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Color3 = { - name = "Color3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Transparency = { - name = "Transparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Visible = { - name = "Visible", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - GuiButton = { - name = "GuiButton", - superclass = "GuiObject", - properties = { - AutoButtonColor = { - name = "AutoButtonColor", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Modal = { - name = "Modal", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Selected = { - name = "Selected", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Style = { - name = "Style", - type = {type = "Enum", name = "ButtonStyle"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - GuiLabel = { - name = "GuiLabel", - superclass = "GuiObject", - properties = { - }, - defaults = { - }, - }, - GuiMain = { - name = "GuiMain", - superclass = "ScreenGui", - properties = { - }, - defaults = { - AutoLocalize = true, - DisplayOrder = 0, - Enabled = true, - IgnoreGuiInset = false, - Localize = true, - Name = "GuiMain", - ResetOnSpawn = true, - RootLocalizationTable = nil, - ZIndexBehavior = 0, - }, - }, - GuiObject = { - name = "GuiObject", - superclass = "GuiBase2d", - properties = { - Active = { - name = "Active", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AnchorPoint = { - name = "AnchorPoint", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AutomaticSize = { - name = "AutomaticSize", - type = {type = "Enum", name = "AutomaticSize"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BackgroundColor = { - name = "BackgroundColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - BackgroundColor3 = { - name = "BackgroundColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BackgroundTransparency = { - name = "BackgroundTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BorderColor = { - name = "BorderColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - BorderColor3 = { - name = "BorderColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BorderMode = { - name = "BorderMode", - type = {type = "Enum", name = "BorderMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BorderSizePixel = { - name = "BorderSizePixel", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ClipsDescendants = { - name = "ClipsDescendants", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Draggable = { - name = "Draggable", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LayoutOrder = { - name = "LayoutOrder", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - NextSelectionDown = { - name = "NextSelectionDown", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - NextSelectionLeft = { - name = "NextSelectionLeft", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - NextSelectionRight = { - name = "NextSelectionRight", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - NextSelectionUp = { - name = "NextSelectionUp", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Position = { - name = "Position", - type = {type = "Data", name = "UDim2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Rotation = { - name = "Rotation", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Selectable = { - name = "Selectable", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SelectionImageObject = { - name = "SelectionImageObject", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Size = { - name = "Size", - type = {type = "Data", name = "UDim2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SizeConstraint = { - name = "SizeConstraint", - type = {type = "Enum", name = "SizeConstraint"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Transparency = { - name = "Transparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Visible = { - name = "Visible", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ZIndex = { - name = "ZIndex", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - GuiService = { - name = "GuiService", - superclass = "Instance", - properties = { - AutoSelectGuiEnabled = { - name = "AutoSelectGuiEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CoreEffectFolder = { - name = "CoreEffectFolder", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - CoreGuiFolder = { - name = "CoreGuiFolder", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - CoreGuiNavigationEnabled = { - name = "CoreGuiNavigationEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GuiNavigationEnabled = { - name = "GuiNavigationEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IsModalDialog = { - name = "IsModalDialog", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - IsWindows = { - name = "IsWindows", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - MenuIsOpen = { - name = "MenuIsOpen", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - SelectedCoreObject = { - name = "SelectedCoreObject", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - SelectedObject = { - name = "SelectedObject", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AutoSelectGuiEnabled = true, - CoreGuiNavigationEnabled = true, - GuiNavigationEnabled = true, - Name = "GuiService", - SelectedObject = nil, - }, - }, - GuidRegistryService = { - name = "GuidRegistryService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - HandleAdornment = { - name = "HandleAdornment", - superclass = "PVAdornment", - properties = { - AdornCullingMode = { - name = "AdornCullingMode", - type = {type = "Enum", name = "AdornCullingMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AlwaysOnTop = { - name = "AlwaysOnTop", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CFrame = { - name = "CFrame", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SizeRelativeOffset = { - name = "SizeRelativeOffset", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ZIndex = { - name = "ZIndex", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - Handles = { - name = "Handles", - superclass = "HandlesBase", - properties = { - Faces = { - name = "Faces", - type = {type = "Unimplemented", name = "Faces"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Style = { - name = "Style", - type = {type = "Enum", name = "HandlesStyle"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Adornee = nil, - Color = BrickColor.new(23), - Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - Name = "Handles", - Style = 0, - Transparency = 0, - Visible = true, - }, - }, - HandlesBase = { - name = "HandlesBase", - superclass = "PartAdornment", - properties = { - }, - defaults = { - }, - }, - HapticService = { - name = "HapticService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "HapticService", - }, - }, - Hat = { - name = "Hat", - superclass = "Accoutrement", - properties = { - }, - defaults = { - AttachmentForward = Vector3.new(0, 0, -1), - AttachmentPoint = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - AttachmentPos = Vector3.new(0, 0, 0), - AttachmentRight = Vector3.new(1, 0, 0), - AttachmentUp = Vector3.new(0, 1, 0), - Name = "Hat", - }, - }, - HeightmapImporterService = { - name = "HeightmapImporterService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "HeightmapImporterService", - }, - }, - HingeConstraint = { - name = "HingeConstraint", - superclass = "Constraint", - properties = { - ActuatorType = { - name = "ActuatorType", - type = {type = "Enum", name = "ActuatorType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AngularSpeed = { - name = "AngularSpeed", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AngularVelocity = { - name = "AngularVelocity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CurrentAngle = { - name = "CurrentAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - LimitsEnabled = { - name = "LimitsEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LowerAngle = { - name = "LowerAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MotorMaxAcceleration = { - name = "MotorMaxAcceleration", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MotorMaxTorque = { - name = "MotorMaxTorque", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Radius = { - name = "Radius", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Restitution = { - name = "Restitution", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ServoMaxTorque = { - name = "ServoMaxTorque", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TargetAngle = { - name = "TargetAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UpperAngle = { - name = "UpperAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - ActuatorType = 0, - AngularSpeed = 0, - AngularVelocity = 0, - Attachment0 = nil, - Attachment1 = nil, - Color = BrickColor.new(1009), - Enabled = true, - LimitsEnabled = false, - LowerAngle = -45, - MotorMaxAcceleration = 1000000000, - MotorMaxTorque = 0, - Name = "HingeConstraint", - Radius = 0.15, - Restitution = 0, - ServoMaxTorque = 0, - TargetAngle = 0, - UpperAngle = 45, - Visible = false, - }, - }, - Hint = { - name = "Hint", - superclass = "Message", - properties = { - }, - defaults = { - Name = "Message", - Text = "", - }, - }, - Hole = { - name = "Hole", - superclass = "Feature", - properties = { - }, - defaults = { - FaceId = 0, - InOut = 2, - LeftRight = 1, - Name = "Hole", - TopBottom = 1, - }, - }, - Hopper = { - name = "Hopper", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - HopperBin = { - name = "HopperBin", - superclass = "BackpackItem", - properties = { - Active = { - name = "Active", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BinType = { - name = "BinType", - type = {type = "Enum", name = "BinType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Active = false, - BinType = 0, - Name = "HopperBin", - TextureId = "", - }, - }, - HttpRbxApiService = { - name = "HttpRbxApiService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "HttpRbxApiService", - }, - }, - HttpRequest = { - name = "HttpRequest", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - HttpService = { - name = "HttpService", - superclass = "Instance", - properties = { - HttpEnabled = { - name = "HttpEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - }, - defaults = { - Name = "HttpService", - }, - }, - Humanoid = { - name = "Humanoid", - superclass = "Instance", - properties = { - AutoJumpEnabled = { - name = "AutoJumpEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AutoRotate = { - name = "AutoRotate", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AutomaticScalingEnabled = { - name = "AutomaticScalingEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BreakJointsOnDeath = { - name = "BreakJointsOnDeath", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CameraOffset = { - name = "CameraOffset", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - CollisionType = { - name = "CollisionType", - type = {type = "Enum", name = "HumanoidCollisionType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DisplayDistanceType = { - name = "DisplayDistanceType", - type = {type = "Enum", name = "HumanoidDisplayDistanceType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DisplayName = { - name = "DisplayName", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FloorMaterial = { - name = "FloorMaterial", - type = {type = "Enum", name = "Material"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Health = { - name = "Health", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - HealthDisplayDistance = { - name = "HealthDisplayDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HealthDisplayType = { - name = "HealthDisplayType", - type = {type = "Enum", name = "HumanoidHealthDisplayType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HipHeight = { - name = "HipHeight", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Jump = { - name = "Jump", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - JumpHeight = { - name = "JumpHeight", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - JumpPower = { - name = "JumpPower", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LeftLeg = { - name = "LeftLeg", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - MaxHealth = { - name = "MaxHealth", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxSlopeAngle = { - name = "MaxSlopeAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MoveDirection = { - name = "MoveDirection", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - NameDisplayDistance = { - name = "NameDisplayDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - NameOcclusion = { - name = "NameOcclusion", - type = {type = "Enum", name = "NameOcclusion"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PlatformStand = { - name = "PlatformStand", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - RequiresNeck = { - name = "RequiresNeck", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RigType = { - name = "RigType", - type = {type = "Enum", name = "HumanoidRigType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RightLeg = { - name = "RightLeg", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - RootPart = { - name = "RootPart", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - SeatPart = { - name = "SeatPart", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Sit = { - name = "Sit", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - TargetPoint = { - name = "TargetPoint", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Torso = { - name = "Torso", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - UseJumpPower = { - name = "UseJumpPower", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WalkSpeed = { - name = "WalkSpeed", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WalkToPart = { - name = "WalkToPart", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - WalkToPoint = { - name = "WalkToPoint", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - maxHealth = { - name = "maxHealth", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - AutoJumpEnabled = true, - AutoRotate = true, - AutomaticScalingEnabled = true, - BreakJointsOnDeath = true, - CameraOffset = Vector3.new(0, 0, 0), - CollisionType = 0, - DisplayDistanceType = 0, - DisplayName = "", - Health = 100, - HealthDisplayDistance = 100, - HealthDisplayType = 0, - HipHeight = 0, - Jump = false, - JumpHeight = 7.2, - JumpPower = 50, - LeftLeg = nil, - MaxHealth = 100, - MaxSlopeAngle = 89, - Name = "Humanoid", - NameDisplayDistance = 100, - NameOcclusion = 2, - PlatformStand = false, - RequiresNeck = true, - RigType = 0, - RightLeg = nil, - Sit = false, - TargetPoint = Vector3.new(0, 0, 0), - Torso = nil, - UseJumpPower = true, - WalkSpeed = 16, - WalkToPart = nil, - WalkToPoint = Vector3.new(0, 0, 0), - maxHealth = 100, - }, - }, - HumanoidController = { - name = "HumanoidController", - superclass = "Controller", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - HumanoidDescription = { - name = "HumanoidDescription", - superclass = "Instance", - properties = { - BackAccessory = { - name = "BackAccessory", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BodyTypeScale = { - name = "BodyTypeScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ClimbAnimation = { - name = "ClimbAnimation", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DepthScale = { - name = "DepthScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Face = { - name = "Face", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FaceAccessory = { - name = "FaceAccessory", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FallAnimation = { - name = "FallAnimation", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FrontAccessory = { - name = "FrontAccessory", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GraphicTShirt = { - name = "GraphicTShirt", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HairAccessory = { - name = "HairAccessory", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HatAccessory = { - name = "HatAccessory", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Head = { - name = "Head", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HeadColor = { - name = "HeadColor", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HeadScale = { - name = "HeadScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HeightScale = { - name = "HeightScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IdleAnimation = { - name = "IdleAnimation", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - JumpAnimation = { - name = "JumpAnimation", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LeftArm = { - name = "LeftArm", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LeftArmColor = { - name = "LeftArmColor", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LeftLeg = { - name = "LeftLeg", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LeftLegColor = { - name = "LeftLegColor", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - NeckAccessory = { - name = "NeckAccessory", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - NumberEmotesLoaded = { - name = "NumberEmotesLoaded", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - Pants = { - name = "Pants", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ProportionScale = { - name = "ProportionScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RightArm = { - name = "RightArm", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RightArmColor = { - name = "RightArmColor", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RightLeg = { - name = "RightLeg", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RightLegColor = { - name = "RightLegColor", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RunAnimation = { - name = "RunAnimation", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Shirt = { - name = "Shirt", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ShouldersAccessory = { - name = "ShouldersAccessory", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SwimAnimation = { - name = "SwimAnimation", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Torso = { - name = "Torso", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TorsoColor = { - name = "TorsoColor", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WaistAccessory = { - name = "WaistAccessory", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WalkAnimation = { - name = "WalkAnimation", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WidthScale = { - name = "WidthScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - BackAccessory = "", - BodyTypeScale = 0.3, - ClimbAnimation = 0, - DepthScale = 1, - Face = 0, - FaceAccessory = "", - FallAnimation = 0, - FrontAccessory = "", - GraphicTShirt = 0, - HairAccessory = "", - HatAccessory = "", - Head = 0, - HeadColor = Color3.new(0, 0, 0), - HeadScale = 1, - HeightScale = 1, - IdleAnimation = 0, - JumpAnimation = 0, - LeftArm = 0, - LeftArmColor = Color3.new(0, 0, 0), - LeftLeg = 0, - LeftLegColor = Color3.new(0, 0, 0), - Name = "HumanoidDescription", - NeckAccessory = "", - Pants = 0, - ProportionScale = 1, - RightArm = 0, - RightArmColor = Color3.new(0, 0, 0), - RightLeg = 0, - RightLegColor = Color3.new(0, 0, 0), - RunAnimation = 0, - Shirt = 0, - ShouldersAccessory = "", - SwimAnimation = 0, - Torso = 0, - TorsoColor = Color3.new(0, 0, 0), - WaistAccessory = "", - WalkAnimation = 0, - WidthScale = 1, - }, - }, - ILegacyStudioBridge = { - name = "ILegacyStudioBridge", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - ImageButton = { - name = "ImageButton", - superclass = "GuiButton", - properties = { - HoverImage = { - name = "HoverImage", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Image = { - name = "Image", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ImageColor3 = { - name = "ImageColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ImageRectOffset = { - name = "ImageRectOffset", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ImageRectSize = { - name = "ImageRectSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ImageTransparency = { - name = "ImageTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IsLoaded = { - name = "IsLoaded", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - PressedImage = { - name = "PressedImage", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ScaleType = { - name = "ScaleType", - type = {type = "Enum", name = "ScaleType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SliceCenter = { - name = "SliceCenter", - type = {type = "Data", name = "Rect"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SliceScale = { - name = "SliceScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TileSize = { - name = "TileSize", - type = {type = "Data", name = "UDim2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Active = true, - AnchorPoint = Vector2.new(0, 0), - AutoButtonColor = true, - AutoLocalize = true, - AutomaticSize = 0, - BackgroundColor = BrickColor.new(194), - BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), - BackgroundTransparency = 0, - BorderColor = BrickColor.new(26), - BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), - BorderMode = 0, - BorderSizePixel = 1, - ClipsDescendants = false, - Draggable = false, - HoverImage = "", - Image = "", - ImageColor3 = Color3.new(1, 1, 1), - ImageRectOffset = Vector2.new(0, 0), - ImageRectSize = Vector2.new(0, 0), - ImageTransparency = 0, - LayoutOrder = 0, - Localize = true, - Modal = false, - Name = "ImageButton", - NextSelectionDown = nil, - NextSelectionLeft = nil, - NextSelectionRight = nil, - NextSelectionUp = nil, - Position = UDim2.new(0, 0, 0, 0), - PressedImage = "", - RootLocalizationTable = nil, - Rotation = 0, - ScaleType = 0, - Selectable = true, - Selected = false, - SelectionImageObject = nil, - Size = UDim2.new(0, 0, 0, 0), - SizeConstraint = 0, - SliceCenter = Rect.new(0, 0, 0, 0), - SliceScale = 1, - Style = 0, - TileSize = UDim2.new(1, 0, 1, 0), - Transparency = 0, - Visible = true, - ZIndex = 1, - }, - }, - ImageHandleAdornment = { - name = "ImageHandleAdornment", - superclass = "HandleAdornment", - properties = { - Image = { - name = "Image", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Size = { - name = "Size", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AdornCullingMode = 0, - Adornee = nil, - AlwaysOnTop = false, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Color = BrickColor.new(1), - Color3 = Color3.new(0.9490197, 0.95294124, 0.95294124), - Image = "rbxasset://textures/SurfacesDefault.png", - Name = "ImageHandleAdornment", - Size = Vector2.new(1, 1), - SizeRelativeOffset = Vector3.new(0, 0, 0), - Transparency = 0, - Visible = true, - ZIndex = -1, - }, - }, - ImageLabel = { - name = "ImageLabel", - superclass = "GuiLabel", - properties = { - Image = { - name = "Image", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ImageColor3 = { - name = "ImageColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ImageRectOffset = { - name = "ImageRectOffset", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ImageRectSize = { - name = "ImageRectSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ImageTransparency = { - name = "ImageTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IsLoaded = { - name = "IsLoaded", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ScaleType = { - name = "ScaleType", - type = {type = "Enum", name = "ScaleType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SliceCenter = { - name = "SliceCenter", - type = {type = "Data", name = "Rect"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SliceScale = { - name = "SliceScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TileSize = { - name = "TileSize", - type = {type = "Data", name = "UDim2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Active = false, - AnchorPoint = Vector2.new(0, 0), - AutoLocalize = true, - AutomaticSize = 0, - BackgroundColor = BrickColor.new(194), - BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), - BackgroundTransparency = 0, - BorderColor = BrickColor.new(26), - BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), - BorderMode = 0, - BorderSizePixel = 1, - ClipsDescendants = false, - Draggable = false, - Image = "", - ImageColor3 = Color3.new(1, 1, 1), - ImageRectOffset = Vector2.new(0, 0), - ImageRectSize = Vector2.new(0, 0), - ImageTransparency = 0, - LayoutOrder = 0, - Localize = true, - Name = "ImageLabel", - NextSelectionDown = nil, - NextSelectionLeft = nil, - NextSelectionRight = nil, - NextSelectionUp = nil, - Position = UDim2.new(0, 0, 0, 0), - RootLocalizationTable = nil, - Rotation = 0, - ScaleType = 0, - Selectable = false, - SelectionImageObject = nil, - Size = UDim2.new(0, 0, 0, 0), - SizeConstraint = 0, - SliceCenter = Rect.new(0, 0, 0, 0), - SliceScale = 1, - TileSize = UDim2.new(1, 0, 1, 0), - Transparency = 0, - Visible = true, - ZIndex = 1, - }, - }, - InputObject = { - name = "InputObject", - superclass = "Instance", - properties = { - Delta = { - name = "Delta", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - KeyCode = { - name = "KeyCode", - type = {type = "Enum", name = "KeyCode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Position = { - name = "Position", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - UserInputState = { - name = "UserInputState", - type = {type = "Enum", name = "UserInputState"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - UserInputType = { - name = "UserInputType", - type = {type = "Enum", name = "UserInputType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - }, - }, - InsertService = { - name = "InsertService", - superclass = "Instance", - properties = { - AllowClientInsertModels = { - name = "AllowClientInsertModels", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - AllowInsertFreeModels = { - name = "AllowInsertFreeModels", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AllowInsertFreeModels = false, - Name = "InsertService", - }, - }, - Instance = { - name = "Instance", - superclass = nil, - properties = { - Archivable = { - name = "Archivable", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = "archivable", - scriptability = "ReadWrite", - serializes = true, - }, - ClassName = { - name = "ClassName", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - DataCost = { - name = "DataCost", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Name = { - name = "Name", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Parent = { - name = "Parent", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - RobloxLocked = { - name = "RobloxLocked", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - SourceAssetId = { - name = "SourceAssetId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - Tags = { - name = "Tags", - type = {type = "Data", name = "BinaryString"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Custom", - serializes = true, - }, - archivable = { - name = "archivable", - type = {type = "Data", name = "Bool"}, - isCanonical = false, - canonicalName = "Archivable", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - className = { - name = "className", - type = {type = "Data", name = "String"}, - isCanonical = false, - canonicalName = "ClassName", - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - InstanceAdornment = { - name = "InstanceAdornment", - superclass = "GuiBase3d", - properties = { - Adornee = { - name = "Adornee", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - IntConstrainedValue = { - name = "IntConstrainedValue", - superclass = "ValueBase", - properties = { - ConstrainedValue = { - name = "ConstrainedValue", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - MaxValue = { - name = "MaxValue", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MinValue = { - name = "MinValue", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Value = { - name = "Value", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - ConstrainedValue = 0, - MaxValue = 10, - MinValue = 0, - Name = "Value", - Value = 0, - }, - }, - IntValue = { - name = "IntValue", - superclass = "ValueBase", - properties = { - Value = { - name = "Value", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Value", - Value = 0, - }, - }, - InternalContainer = { - name = "InternalContainer", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - InventoryPages = { - name = "InventoryPages", - superclass = "Pages", - properties = { - }, - defaults = { - }, - }, - JointInstance = { - name = "JointInstance", - superclass = "Instance", - properties = { - Active = { - name = "Active", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - C0 = { - name = "C0", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - C1 = { - name = "C1", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Part0 = { - name = "Part0", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Part1 = { - name = "Part1", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - part1 = { - name = "part1", - type = {type = "Data", name = "Ref"}, - isCanonical = false, - canonicalName = "Part1", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - }, - }, - JointsService = { - name = "JointsService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "JointsService", - }, - }, - KeyboardService = { - name = "KeyboardService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - Keyframe = { - name = "Keyframe", - superclass = "Instance", - properties = { - Time = { - name = "Time", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Keyframe", - Time = 0, - }, - }, - KeyframeMarker = { - name = "KeyframeMarker", - superclass = "Instance", - properties = { - Value = { - name = "Value", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "KeyframeMarker", - Value = "", - }, - }, - KeyframeSequence = { - name = "KeyframeSequence", - superclass = "Instance", - properties = { - AuthoredHipHeight = { - name = "AuthoredHipHeight", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Loop = { - name = "Loop", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Priority = { - name = "Priority", - type = {type = "Enum", name = "AnimationPriority"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AuthoredHipHeight = 2, - Loop = true, - Name = "KeyframeSequence", - Priority = 2, - }, - }, - KeyframeSequenceProvider = { - name = "KeyframeSequenceProvider", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - LanguageService = { - name = "LanguageService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "LanguageService", - }, - }, - LayerCollector = { - name = "LayerCollector", - superclass = "GuiBase2d", - properties = { - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ResetOnSpawn = { - name = "ResetOnSpawn", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ZIndexBehavior = { - name = "ZIndexBehavior", - type = {type = "Enum", name = "ZIndexBehavior"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - LegacyStudioBridge = { - name = "LegacyStudioBridge", - superclass = "ILegacyStudioBridge", - properties = { - }, - defaults = { - }, - }, - Light = { - name = "Light", - superclass = "Instance", - properties = { - Brightness = { - name = "Brightness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Color = { - name = "Color", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Shadows = { - name = "Shadows", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - Lighting = { - name = "Lighting", - superclass = "Instance", - properties = { - Ambient = { - name = "Ambient", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Brightness = { - name = "Brightness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ClockTime = { - name = "ClockTime", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - ColorShift_Bottom = { - name = "ColorShift_Bottom", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ColorShift_Top = { - name = "ColorShift_Top", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - EnvironmentDiffuseScale = { - name = "EnvironmentDiffuseScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - EnvironmentSpecularScale = { - name = "EnvironmentSpecularScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ExposureCompensation = { - name = "ExposureCompensation", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FogColor = { - name = "FogColor", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FogEnd = { - name = "FogEnd", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FogStart = { - name = "FogStart", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GeographicLatitude = { - name = "GeographicLatitude", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GlobalShadows = { - name = "GlobalShadows", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - OutdoorAmbient = { - name = "OutdoorAmbient", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Outlines = { - name = "Outlines", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ShadowColor = { - name = "ShadowColor", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - ShadowSoftness = { - name = "ShadowSoftness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Technology = { - name = "Technology", - type = {type = "Enum", name = "Technology"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - TimeOfDay = { - name = "TimeOfDay", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Ambient = Color3.new(0.5, 0.5, 0.5), - Brightness = 1, - ClockTime = 14, - ColorShift_Bottom = Color3.new(0, 0, 0), - ColorShift_Top = Color3.new(0, 0, 0), - EnvironmentDiffuseScale = 0, - EnvironmentSpecularScale = 0, - ExposureCompensation = 0, - FogColor = Color3.new(0.75, 0.75, 0.75), - FogEnd = 100000, - FogStart = 0, - GeographicLatitude = 41.7333, - GlobalShadows = false, - Name = "Lighting", - OutdoorAmbient = Color3.new(0.5, 0.5, 0.5), - Outlines = true, - ShadowColor = Color3.new(0.7, 0.7, 0.72), - ShadowSoftness = 0.5, - TimeOfDay = "14:00:00", - }, - }, - LineForce = { - name = "LineForce", - superclass = "Constraint", - properties = { - ApplyAtCenterOfMass = { - name = "ApplyAtCenterOfMass", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - InverseSquareLaw = { - name = "InverseSquareLaw", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Magnitude = { - name = "Magnitude", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxForce = { - name = "MaxForce", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ReactionForceEnabled = { - name = "ReactionForceEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - ApplyAtCenterOfMass = false, - Attachment0 = nil, - Attachment1 = nil, - Color = BrickColor.new(23), - Enabled = true, - InverseSquareLaw = false, - Magnitude = 1000, - MaxForce = 1000000000, - Name = "LineForce", - ReactionForceEnabled = false, - Visible = false, - }, - }, - LineHandleAdornment = { - name = "LineHandleAdornment", - superclass = "HandleAdornment", - properties = { - Length = { - name = "Length", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Thickness = { - name = "Thickness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AdornCullingMode = 0, - Adornee = nil, - AlwaysOnTop = false, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Color = BrickColor.new(23), - Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - Length = 5, - Name = "LineHandleAdornment", - SizeRelativeOffset = Vector3.new(0, 0, 0), - Thickness = 1, - Transparency = 0, - Visible = true, - ZIndex = -1, - }, - }, - LocalScript = { - name = "LocalScript", - superclass = "Script", - properties = { - }, - defaults = { - Disabled = false, - LinkedSource = "", - Name = "LocalScript", - Source = "", - }, - }, - LocalStorageService = { - name = "LocalStorageService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - LocalizationService = { - name = "LocalizationService", - superclass = "Instance", - properties = { - ForcePlayModeGameLocaleId = { - name = "ForcePlayModeGameLocaleId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - ForcePlayModeRobloxLocaleId = { - name = "ForcePlayModeRobloxLocaleId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - IsTextScraperRunning = { - name = "IsTextScraperRunning", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - RobloxForcePlayModeGameLocaleId = { - name = "RobloxForcePlayModeGameLocaleId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - RobloxForcePlayModeRobloxLocaleId = { - name = "RobloxForcePlayModeRobloxLocaleId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - RobloxLocaleId = { - name = "RobloxLocaleId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - SystemLocaleId = { - name = "SystemLocaleId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - Name = "LocalizationService", - }, - }, - LocalizationTable = { - name = "LocalizationTable", - superclass = "Instance", - properties = { - Contents = { - name = "Contents", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Custom", - serializes = true, - }, - DevelopmentLanguage = { - name = "DevelopmentLanguage", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Root = { - name = "Root", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - SourceLocaleId = { - name = "SourceLocaleId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - DevelopmentLanguage = "en-us", - Name = "LocalizationTable", - Root = nil, - SourceLocaleId = "en-us", - }, - }, - LogService = { - name = "LogService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "LogService", - }, - }, - LoginService = { - name = "LoginService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - LuaSettings = { - name = "LuaSettings", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - LuaSourceContainer = { - name = "LuaSourceContainer", - superclass = "Instance", - properties = { - CurrentEditor = { - name = "CurrentEditor", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - IsDifferentFromFileSystem = { - name = "IsDifferentFromFileSystem", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - }, - defaults = { - }, - }, - LuaWebService = { - name = "LuaWebService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - ManualGlue = { - name = "ManualGlue", - superclass = "ManualSurfaceJointInstance", - properties = { - }, - defaults = { - C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Enabled = true, - Name = "ManualGlue", - Part0 = nil, - Part1 = nil, - }, - }, - ManualSurfaceJointInstance = { - name = "ManualSurfaceJointInstance", - superclass = "JointInstance", - properties = { - }, - defaults = { - }, - }, - ManualWeld = { - name = "ManualWeld", - superclass = "ManualSurfaceJointInstance", - properties = { - }, - defaults = { - C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Enabled = true, - Name = "ManualWeld", - Part0 = nil, - Part1 = nil, - }, - }, - MarketplaceService = { - name = "MarketplaceService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "MarketplaceService", - }, - }, - MemStorageConnection = { - name = "MemStorageConnection", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - MemStorageService = { - name = "MemStorageService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "MemStorageService", - }, - }, - MeshContentProvider = { - name = "MeshContentProvider", - superclass = "CacheableContentProvider", - properties = { - }, - defaults = { - Name = "MeshContentProvider", - }, - }, - MeshPart = { - name = "MeshPart", - superclass = "TriangleMeshPart", - properties = { - DoubleSided = { - name = "DoubleSided", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HasJointOffset = { - name = "HasJointOffset", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = true, - }, - HasSkinnedMesh = { - name = "HasSkinnedMesh", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = true, - }, - JointOffset = { - name = "JointOffset", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = true, - }, - MeshID = { - name = "MeshID", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - MeshId = { - name = "MeshId", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = true, - }, - MeshSize = { - name = "MeshSize", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - RenderFidelity = { - name = "RenderFidelity", - type = {type = "Enum", name = "RenderFidelity"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextureID = { - name = "TextureID", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Anchored = false, - AssemblyAngularVelocity = Vector3.new(0, 0, 0), - AssemblyLinearVelocity = Vector3.new(0, 0, 0), - BackParamA = -0.5, - BackParamB = 0.5, - BackSurface = 0, - BackSurfaceInput = 0, - BottomParamA = -0.5, - BottomParamB = 0.5, - BottomSurface = 0, - BottomSurfaceInput = 0, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CanCollide = true, - CanTouch = true, - CastShadow = true, - CollisionFidelity = 2, - CollisionGroupId = 0, - Color = Color3.new(0.6392157, 0.63529414, 0.64705884), - CustomPhysicalProperties = nil, - DoubleSided = false, - Elasticity = 0.5, - Friction = 0.3, - FrontParamA = -0.5, - FrontParamB = 0.5, - FrontSurface = 0, - FrontSurfaceInput = 0, - HasJointOffset = false, - HasSkinnedMesh = false, - JointOffset = Vector3.new(0, 0, 0), - LeftParamA = -0.5, - LeftParamB = 0.5, - LeftSurface = 0, - LeftSurfaceInput = 0, - LocalTransparencyModifier = 0, - Locked = false, - Massless = false, - Material = 256, - MeshId = "", - Name = "MeshPart", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Reflectance = 0, - RenderFidelity = 1, - RightParamA = -0.5, - RightParamB = 0.5, - RightSurface = 0, - RightSurfaceInput = 0, - RootPriority = 0, - RotVelocity = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - Size = Vector3.new(4, 1.2, 2), - TextureID = "", - TopParamA = -0.5, - TopParamB = 0.5, - TopSurface = 0, - TopSurfaceInput = 0, - Transparency = 0, - Velocity = Vector3.new(0, 0, 0), - }, - }, - Message = { - name = "Message", - superclass = "Instance", - properties = { - Text = { - name = "Text", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Message", - Text = "", - }, - }, - MessagingService = { - name = "MessagingService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "MessagingService", - }, - }, - Model = { - name = "Model", - superclass = "PVInstance", - properties = { - LevelOfDetail = { - name = "LevelOfDetail", - type = {type = "Enum", name = "ModelLevelOfDetail"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PrimaryPart = { - name = "PrimaryPart", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - LevelOfDetail = 0, - Name = "Model", - PrimaryPart = nil, - }, - }, - ModuleScript = { - name = "ModuleScript", - superclass = "LuaSourceContainer", - properties = { - LinkedSource = { - name = "LinkedSource", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Source = { - name = "Source", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - LinkedSource = "", - Name = "ModuleScript", - Source = "", - }, - }, - Motor = { - name = "Motor", - superclass = "JointInstance", - properties = { - CurrentAngle = { - name = "CurrentAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - DesiredAngle = { - name = "DesiredAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxVelocity = { - name = "MaxVelocity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CurrentAngle = 0, - DesiredAngle = 0, - Enabled = true, - MaxVelocity = 0, - Name = "Motor", - Part0 = nil, - Part1 = nil, - }, - }, - Motor6D = { - name = "Motor6D", - superclass = "Motor", - properties = { - ChildName = { - name = "ChildName", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - ParentName = { - name = "ParentName", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - Transform = { - name = "Transform", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CurrentAngle = 0, - DesiredAngle = 0, - Enabled = true, - MaxVelocity = 0, - Name = "Motor6D", - Part0 = nil, - Part1 = nil, - Transform = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - }, - }, - MotorFeature = { - name = "MotorFeature", - superclass = "Feature", - properties = { - }, - defaults = { - FaceId = 0, - InOut = 2, - LeftRight = 1, - Name = "MotorFeature", - TopBottom = 1, - }, - }, - Mouse = { - name = "Mouse", - superclass = "Instance", - properties = { - Hit = { - name = "Hit", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Icon = { - name = "Icon", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Origin = { - name = "Origin", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Target = { - name = "Target", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TargetFilter = { - name = "TargetFilter", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TargetSurface = { - name = "TargetSurface", - type = {type = "Enum", name = "NormalId"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - UnitRay = { - name = "UnitRay", - type = {type = "Unimplemented", name = "Ray"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ViewSizeX = { - name = "ViewSizeX", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ViewSizeY = { - name = "ViewSizeY", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - X = { - name = "X", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Y = { - name = "Y", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - hit = { - name = "hit", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - target = { - name = "target", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - MouseService = { - name = "MouseService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - MultipleDocumentInterfaceInstance = { - name = "MultipleDocumentInterfaceInstance", - superclass = "Instance", - properties = { - FocusedDataModelSession = { - name = "FocusedDataModelSession", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - NegateOperation = { - name = "NegateOperation", - superclass = "PartOperation", - properties = { - }, - defaults = { - Anchored = true, - AssemblyAngularVelocity = Vector3.new(0, 0, 0), - AssemblyLinearVelocity = Vector3.new(0, 0, 0), - BackParamA = -0.5, - BackParamB = 0.5, - BackSurface = 0, - BackSurfaceInput = 0, - BottomParamA = -0.5, - BottomParamB = 0.5, - BottomSurface = 0, - BottomSurfaceInput = 0, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CanCollide = false, - CanTouch = true, - CastShadow = true, - CollisionFidelity = 2, - CollisionGroupId = 0, - Color = Color3.new(1, 1, 1), - CustomPhysicalProperties = nil, - Elasticity = 0.5, - Friction = 0.3, - FrontParamA = -0.5, - FrontParamB = 0.5, - FrontSurface = 0, - FrontSurfaceInput = 0, - LeftParamA = -0.5, - LeftParamB = 0.5, - LeftSurface = 0, - LeftSurfaceInput = 0, - LocalTransparencyModifier = 0, - Locked = false, - Massless = false, - Material = 256, - Name = "NegativePart", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Reflectance = 0, - RenderFidelity = 1, - RightParamA = -0.5, - RightParamB = 0.5, - RightSurface = 0, - RightSurfaceInput = 0, - RootPriority = 0, - RotVelocity = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - Size = Vector3.new(4, 1.2, 2), - SmoothingAngle = 0, - TopParamA = -0.5, - TopParamB = 0.5, - TopSurface = 0, - TopSurfaceInput = 0, - Transparency = 0.1, - UsePartColor = false, - Velocity = Vector3.new(0, 0, 0), - }, - }, - NetworkClient = { - name = "NetworkClient", - superclass = "NetworkPeer", - properties = { - }, - defaults = { - }, - }, - NetworkMarker = { - name = "NetworkMarker", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - NetworkPeer = { - name = "NetworkPeer", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - NetworkReplicator = { - name = "NetworkReplicator", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - NetworkServer = { - name = "NetworkServer", - superclass = "NetworkPeer", - properties = { - }, - defaults = { - }, - }, - NetworkSettings = { - name = "NetworkSettings", - superclass = "Instance", - properties = { - ExtraMemoryUsed = { - name = "ExtraMemoryUsed", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - FreeMemoryMBytes = { - name = "FreeMemoryMBytes", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - HttpProxyEnabled = { - name = "HttpProxyEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HttpProxyURL = { - name = "HttpProxyURL", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IncomingReplicationLag = { - name = "IncomingReplicationLag", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PrintJoinSizeBreakdown = { - name = "PrintJoinSizeBreakdown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PrintPhysicsErrors = { - name = "PrintPhysicsErrors", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PrintStreamInstanceQuota = { - name = "PrintStreamInstanceQuota", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RenderStreamedRegions = { - name = "RenderStreamedRegions", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ShowActiveAnimationAsset = { - name = "ShowActiveAnimationAsset", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TrackDataTypes = { - name = "TrackDataTypes", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TrackPhysicsDetails = { - name = "TrackPhysicsDetails", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - NoCollisionConstraint = { - name = "NoCollisionConstraint", - superclass = "Instance", - properties = { - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Part0 = { - name = "Part0", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Part1 = { - name = "Part1", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Enabled = true, - Name = "NoCollisionConstraint", - Part0 = nil, - Part1 = nil, - }, - }, - NonReplicatedCSGDictionaryService = { - name = "NonReplicatedCSGDictionaryService", - superclass = "FlyweightService", - properties = { - }, - defaults = { - }, - }, - NotificationService = { - name = "NotificationService", - superclass = "Instance", - properties = { - IsLuaChatEnabled = { - name = "IsLuaChatEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - IsLuaGameDetailsEnabled = { - name = "IsLuaGameDetailsEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - SelectedTheme = { - name = "SelectedTheme", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - }, - defaults = { - Name = "NotificationService", - }, - }, - NumberPose = { - name = "NumberPose", - superclass = "PoseBase", - properties = { - Value = { - name = "Value", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - EasingDirection = 0, - EasingStyle = 0, - Name = "Pose", - Value = 0, - Weight = 1, - }, - }, - NumberValue = { - name = "NumberValue", - superclass = "ValueBase", - properties = { - Value = { - name = "Value", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Value", - Value = 0, - }, - }, - ObjectValue = { - name = "ObjectValue", - superclass = "ValueBase", - properties = { - Value = { - name = "Value", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Value", - Value = nil, - }, - }, - OrderedDataStore = { - name = "OrderedDataStore", - superclass = "GlobalDataStore", - properties = { - }, - defaults = { - }, - }, - OutfitPages = { - name = "OutfitPages", - superclass = "Pages", - properties = { - }, - defaults = { - }, - }, - PVAdornment = { - name = "PVAdornment", - superclass = "GuiBase3d", - properties = { - Adornee = { - name = "Adornee", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - PVInstance = { - name = "PVInstance", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - PackageLink = { - name = "PackageLink", - superclass = "Instance", - properties = { - AutoUpdate = { - name = "AutoUpdate", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - PackageId = { - name = "PackageId", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Status = { - name = "Status", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - VersionNumber = { - name = "VersionNumber", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - }, - }, - PackageService = { - name = "PackageService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - Pages = { - name = "Pages", - superclass = "Instance", - properties = { - IsFinished = { - name = "IsFinished", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - Pants = { - name = "Pants", - superclass = "Clothing", - properties = { - PantsTemplate = { - name = "PantsTemplate", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Color3 = Color3.new(1, 1, 1), - Name = "Clothing", - PantsTemplate = "", - }, - }, - ParabolaAdornment = { - name = "ParabolaAdornment", - superclass = "PVAdornment", - properties = { - A = { - name = "A", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - B = { - name = "B", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - C = { - name = "C", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Range = { - name = "Range", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Thickness = { - name = "Thickness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - }, - }, - Part = { - name = "Part", - superclass = "FormFactorPart", - properties = { - Shape = { - name = "Shape", - type = {type = "Enum", name = "PartType"}, - isCanonical = true, - canonicalName = nil, - serializedName = "shape", - scriptability = "ReadWrite", - serializes = true, - }, - shape = { - name = "shape", - type = {type = "Enum", name = "PartType"}, - isCanonical = false, - canonicalName = "Shape", - serializedName = nil, - scriptability = "None", - serializes = false, - }, - }, - defaults = { - Anchored = false, - AssemblyAngularVelocity = Vector3.new(0, 0, 0), - AssemblyLinearVelocity = Vector3.new(0, 0, 0), - BackParamA = -0.5, - BackParamB = 0.5, - BackSurface = 0, - BackSurfaceInput = 0, - BottomParamA = -0.5, - BottomParamB = 0.5, - BottomSurface = 4, - BottomSurfaceInput = 0, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CanCollide = true, - CanTouch = true, - CastShadow = true, - CollisionGroupId = 0, - Color = Color3.new(0.6392157, 0.63529414, 0.64705884), - CustomPhysicalProperties = nil, - Elasticity = 0.5, - FormFactor = 1, - Friction = 0.3, - FrontParamA = -0.5, - FrontParamB = 0.5, - FrontSurface = 0, - FrontSurfaceInput = 0, - LeftParamA = -0.5, - LeftParamB = 0.5, - LeftSurface = 0, - LeftSurfaceInput = 0, - LocalTransparencyModifier = 0, - Locked = false, - Massless = false, - Material = 256, - Name = "Part", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Reflectance = 0, - RightParamA = -0.5, - RightParamB = 0.5, - RightSurface = 0, - RightSurfaceInput = 0, - RootPriority = 0, - RotVelocity = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - Shape = 1, - Size = Vector3.new(4, 1.2, 2), - TopParamA = -0.5, - TopParamB = 0.5, - TopSurface = 3, - TopSurfaceInput = 0, - Transparency = 0, - Velocity = Vector3.new(0, 0, 0), - }, - }, - PartAdornment = { - name = "PartAdornment", - superclass = "GuiBase3d", - properties = { - Adornee = { - name = "Adornee", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - PartOperation = { - name = "PartOperation", - superclass = "TriangleMeshPart", - properties = { - RenderFidelity = { - name = "RenderFidelity", - type = {type = "Enum", name = "RenderFidelity"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SmoothingAngle = { - name = "SmoothingAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TriangleCount = { - name = "TriangleCount", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - UsePartColor = { - name = "UsePartColor", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Anchored = false, - AssemblyAngularVelocity = Vector3.new(0, 0, 0), - AssemblyLinearVelocity = Vector3.new(0, 0, 0), - BackParamA = -0.5, - BackParamB = 0.5, - BackSurface = 0, - BackSurfaceInput = 0, - BottomParamA = -0.5, - BottomParamB = 0.5, - BottomSurface = 0, - BottomSurfaceInput = 0, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CanCollide = true, - CanTouch = true, - CastShadow = true, - CollisionFidelity = 2, - CollisionGroupId = 0, - Color = Color3.new(1, 1, 1), - CustomPhysicalProperties = nil, - Elasticity = 0.5, - Friction = 0.3, - FrontParamA = -0.5, - FrontParamB = 0.5, - FrontSurface = 0, - FrontSurfaceInput = 0, - LeftParamA = -0.5, - LeftParamB = 0.5, - LeftSurface = 0, - LeftSurfaceInput = 0, - LocalTransparencyModifier = 0, - Locked = false, - Massless = false, - Material = 256, - Name = "PartOperation", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Reflectance = 0, - RenderFidelity = 1, - RightParamA = -0.5, - RightParamB = 0.5, - RightSurface = 0, - RightSurfaceInput = 0, - RootPriority = 0, - RotVelocity = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - Size = Vector3.new(4, 1.2, 2), - SmoothingAngle = 0, - TopParamA = -0.5, - TopParamB = 0.5, - TopSurface = 0, - TopSurfaceInput = 0, - Transparency = 0, - UsePartColor = false, - Velocity = Vector3.new(0, 0, 0), - }, - }, - PartOperationAsset = { - name = "PartOperationAsset", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - ParticleEmitter = { - name = "ParticleEmitter", - superclass = "Instance", - properties = { - Acceleration = { - name = "Acceleration", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Color = { - name = "Color", - type = {type = "Data", name = "ColorSequence"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Drag = { - name = "Drag", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - EmissionDirection = { - name = "EmissionDirection", - type = {type = "Enum", name = "NormalId"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Lifetime = { - name = "Lifetime", - type = {type = "Data", name = "NumberRange"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LightEmission = { - name = "LightEmission", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LightInfluence = { - name = "LightInfluence", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LockedToPart = { - name = "LockedToPart", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Rate = { - name = "Rate", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RotSpeed = { - name = "RotSpeed", - type = {type = "Data", name = "NumberRange"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Rotation = { - name = "Rotation", - type = {type = "Data", name = "NumberRange"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Size = { - name = "Size", - type = {type = "Data", name = "NumberSequence"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Speed = { - name = "Speed", - type = {type = "Data", name = "NumberRange"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SpreadAngle = { - name = "SpreadAngle", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Texture = { - name = "Texture", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Transparency = { - name = "Transparency", - type = {type = "Data", name = "NumberSequence"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - VelocityInheritance = { - name = "VelocityInheritance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - VelocitySpread = { - name = "VelocitySpread", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - ZOffset = { - name = "ZOffset", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Acceleration = Vector3.new(0, 0, 0), - Color = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.new(1, 1, 1)), ColorSequenceKeypoint.new(1, Color3.new(1, 1, 1))}), - Drag = 0, - EmissionDirection = 1, - Enabled = true, - Lifetime = NumberRange.new(5, 10), - LightEmission = 0, - LightInfluence = 0, - LockedToPart = false, - Name = "ParticleEmitter", - Rate = 20, - RotSpeed = NumberRange.new(0, 0), - Rotation = NumberRange.new(0, 0), - Size = NumberSequence.new({NumberSequenceKeypoint.new(0, 1, 0), NumberSequenceKeypoint.new(1, 1, 0)}), - Speed = NumberRange.new(5, 5), - SpreadAngle = Vector2.new(0, 0), - Texture = "rbxasset://textures/particles/sparkles_main.dds", - Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 0, 0), NumberSequenceKeypoint.new(1, 0, 0)}), - VelocityInheritance = 0, - VelocitySpread = 0, - ZOffset = 0, - }, - }, - Path = { - name = "Path", - superclass = "Instance", - properties = { - Status = { - name = "Status", - type = {type = "Enum", name = "PathStatus"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - PathfindingService = { - name = "PathfindingService", - superclass = "Instance", - properties = { - EmptyCutoff = { - name = "EmptyCutoff", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - EmptyCutoff = 0, - Name = "Instance", - }, - }, - PermissionsService = { - name = "PermissionsService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "PermissionsService", - }, - }, - PhysicsService = { - name = "PhysicsService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "PhysicsService", - }, - }, - PhysicsSettings = { - name = "PhysicsSettings", - superclass = "Instance", - properties = { - AllowSleep = { - name = "AllowSleep", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreAnchorsShown = { - name = "AreAnchorsShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreAssembliesShown = { - name = "AreAssembliesShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreAwakePartsHighlighted = { - name = "AreAwakePartsHighlighted", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreBodyTypesShown = { - name = "AreBodyTypesShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreContactIslandsShown = { - name = "AreContactIslandsShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreContactPointsShown = { - name = "AreContactPointsShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreJointCoordinatesShown = { - name = "AreJointCoordinatesShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreMechanismsShown = { - name = "AreMechanismsShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreModelCoordsShown = { - name = "AreModelCoordsShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreOwnersShown = { - name = "AreOwnersShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ArePartCoordsShown = { - name = "ArePartCoordsShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreRegionsShown = { - name = "AreRegionsShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreTerrainReplicationRegionsShown = { - name = "AreTerrainReplicationRegionsShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreUnalignedPartsShown = { - name = "AreUnalignedPartsShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AreWorldCoordsShown = { - name = "AreWorldCoordsShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DisableCSGv2 = { - name = "DisableCSGv2", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ForceCSGv2 = { - name = "ForceCSGv2", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IsInterpolationThrottleShown = { - name = "IsInterpolationThrottleShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IsReceiveAgeShown = { - name = "IsReceiveAgeShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IsTreeShown = { - name = "IsTreeShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PhysicsEnvironmentalThrottle = { - name = "PhysicsEnvironmentalThrottle", - type = {type = "Enum", name = "EnviromentalPhysicsThrottle"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ShowDecompositionGeometry = { - name = "ShowDecompositionGeometry", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ThrottleAdjustTime = { - name = "ThrottleAdjustTime", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UseCSGv2 = { - name = "UseCSGv2", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - PitchShiftSoundEffect = { - name = "PitchShiftSoundEffect", - superclass = "SoundEffect", - properties = { - Octave = { - name = "Octave", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Enabled = true, - Name = "PitchShiftSoundEffect", - Octave = 1.25, - Priority = 0, - }, - }, - Platform = { - name = "Platform", - superclass = "Part", - properties = { - }, - defaults = { - }, - }, - Player = { - name = "Player", - superclass = "Instance", - properties = { - AccountAge = { - name = "AccountAge", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - AppearanceDidLoad = { - name = "AppearanceDidLoad", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - AutoJumpEnabled = { - name = "AutoJumpEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CameraMaxZoomDistance = { - name = "CameraMaxZoomDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CameraMinZoomDistance = { - name = "CameraMinZoomDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CameraMode = { - name = "CameraMode", - type = {type = "Enum", name = "CameraMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CanLoadCharacterAppearance = { - name = "CanLoadCharacterAppearance", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Character = { - name = "Character", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CharacterAppearance = { - name = "CharacterAppearance", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CharacterAppearanceId = { - name = "CharacterAppearanceId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ChatMode = { - name = "ChatMode", - type = {type = "Enum", name = "ChatMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - DataComplexity = { - name = "DataComplexity", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - DataComplexityLimit = { - name = "DataComplexityLimit", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - DataReady = { - name = "DataReady", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - DevCameraOcclusionMode = { - name = "DevCameraOcclusionMode", - type = {type = "Enum", name = "DevCameraOcclusionMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DevComputerCameraMode = { - name = "DevComputerCameraMode", - type = {type = "Enum", name = "DevComputerCameraMovementMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DevComputerMovementMode = { - name = "DevComputerMovementMode", - type = {type = "Enum", name = "DevComputerMovementMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DevEnableMouseLock = { - name = "DevEnableMouseLock", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DevTouchCameraMode = { - name = "DevTouchCameraMode", - type = {type = "Enum", name = "DevTouchCameraMovementMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DevTouchMovementMode = { - name = "DevTouchMovementMode", - type = {type = "Enum", name = "DevTouchMovementMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DisplayName = { - name = "DisplayName", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - FollowUserId = { - name = "FollowUserId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - GameplayPaused = { - name = "GameplayPaused", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Guest = { - name = "Guest", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - HealthDisplayDistance = { - name = "HealthDisplayDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LocaleId = { - name = "LocaleId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - MaximumSimulationRadius = { - name = "MaximumSimulationRadius", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - MembershipType = { - name = "MembershipType", - type = {type = "Enum", name = "MembershipType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - NameDisplayDistance = { - name = "NameDisplayDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Neutral = { - name = "Neutral", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - OsPlatform = { - name = "OsPlatform", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - PlatformName = { - name = "PlatformName", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - ReplicationFocus = { - name = "ReplicationFocus", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RespawnLocation = { - name = "RespawnLocation", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SimulationRadius = { - name = "SimulationRadius", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Team = { - name = "Team", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TeamColor = { - name = "TeamColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Teleported = { - name = "Teleported", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TeleportedIn = { - name = "TeleportedIn", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UserId = { - name = "UserId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - VRDevice = { - name = "VRDevice", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - userId = { - name = "userId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - }, - }, - PlayerEmulatorService = { - name = "PlayerEmulatorService", - superclass = "Instance", - properties = { - EmulatedCountryCode = { - name = "EmulatedCountryCode", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - EmulatedGameLocale = { - name = "EmulatedGameLocale", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - PlayerEmulationEnabled = { - name = "PlayerEmulationEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - PlayerEmulationEnabled_deprecated = { - name = "PlayerEmulationEnabled_deprecated", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - SerializedEmulatedPolicyInfo = { - name = "SerializedEmulatedPolicyInfo", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - StudioEmulatedCountryRegionCode = { - name = "StudioEmulatedCountryRegionCode", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - }, - defaults = { - }, - }, - PlayerGui = { - name = "PlayerGui", - superclass = "BasePlayerGui", - properties = { - CurrentScreenOrientation = { - name = "CurrentScreenOrientation", - type = {type = "Enum", name = "ScreenOrientation"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ScreenOrientation = { - name = "ScreenOrientation", - type = {type = "Enum", name = "ScreenOrientation"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SelectionImageObject = { - name = "SelectionImageObject", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - PlayerMouse = { - name = "PlayerMouse", - superclass = "Mouse", - properties = { - }, - defaults = { - }, - }, - PlayerScripts = { - name = "PlayerScripts", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - Players = { - name = "Players", - superclass = "Instance", - properties = { - BubbleChat = { - name = "BubbleChat", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - CharacterAutoLoads = { - name = "CharacterAutoLoads", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ClassicChat = { - name = "ClassicChat", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - LocalPlayer = { - name = "LocalPlayer", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - MaxPlayers = { - name = "MaxPlayers", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = "MaxPlayersInternal", - scriptability = "Read", - serializes = true, - }, - MaxPlayersInternal = { - name = "MaxPlayersInternal", - type = {type = "Data", name = "Int32"}, - isCanonical = false, - canonicalName = "MaxPlayers", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - NumPlayers = { - name = "NumPlayers", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - PreferredPlayers = { - name = "PreferredPlayers", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = "PreferredPlayersInternal", - scriptability = "Read", - serializes = true, - }, - PreferredPlayersInternal = { - name = "PreferredPlayersInternal", - type = {type = "Data", name = "Int32"}, - isCanonical = false, - canonicalName = "PreferredPlayers", - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - RespawnTime = { - name = "RespawnTime", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - localPlayer = { - name = "localPlayer", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - numPlayers = { - name = "numPlayers", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - CharacterAutoLoads = true, - Name = "Players", - RespawnTime = 5, - }, - }, - Plugin = { - name = "Plugin", - superclass = "Instance", - properties = { - CollisionEnabled = { - name = "CollisionEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - GridSize = { - name = "GridSize", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - HostDataModelType = { - name = "HostDataModelType", - type = {type = "Enum", name = "StudioDataModelType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - HostDataModelTypeIsCurrent = { - name = "HostDataModelTypeIsCurrent", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - MultipleDocumentInterfaceInstance = { - name = "MultipleDocumentInterfaceInstance", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - UsesAssetInsertionDrag = { - name = "UsesAssetInsertionDrag", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - }, - }, - PluginAction = { - name = "PluginAction", - superclass = "Instance", - properties = { - ActionId = { - name = "ActionId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - AllowBinding = { - name = "AllowBinding", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Checked = { - name = "Checked", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - DefaultShortcut = { - name = "DefaultShortcut", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - StatusTip = { - name = "StatusTip", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Text = { - name = "Text", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - Name = "Instance", - }, - }, - PluginDebugService = { - name = "PluginDebugService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - PluginDragEvent = { - name = "PluginDragEvent", - superclass = "Instance", - properties = { - Data = { - name = "Data", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - MimeType = { - name = "MimeType", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Position = { - name = "Position", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Sender = { - name = "Sender", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - PluginGui = { - name = "PluginGui", - superclass = "LayerCollector", - properties = { - Title = { - name = "Title", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - PluginGuiService = { - name = "PluginGuiService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "PluginGuiService", - }, - }, - PluginManager = { - name = "PluginManager", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - PluginManagerInterface = { - name = "PluginManagerInterface", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - PluginMenu = { - name = "PluginMenu", - superclass = "Instance", - properties = { - Icon = { - name = "Icon", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Title = { - name = "Title", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - }, - }, - PluginMouse = { - name = "PluginMouse", - superclass = "Mouse", - properties = { - }, - defaults = { - }, - }, - PluginToolbar = { - name = "PluginToolbar", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - PluginToolbarButton = { - name = "PluginToolbarButton", - superclass = "Instance", - properties = { - ClickableWhenViewportHidden = { - name = "ClickableWhenViewportHidden", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Icon = { - name = "Icon", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - }, - }, - PointLight = { - name = "PointLight", - superclass = "Light", - properties = { - Range = { - name = "Range", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Brightness = 1, - Color = Color3.new(1, 1, 1), - Enabled = true, - Name = "PointLight", - Range = 8, - Shadows = false, - }, - }, - PointsService = { - name = "PointsService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "PointsService", - }, - }, - PolicyService = { - name = "PolicyService", - superclass = "Instance", - properties = { - IsLuobuServer = { - name = "IsLuobuServer", - type = {type = "Enum", name = "TriStateBoolean"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - LuobuWhitelisted = { - name = "LuobuWhitelisted", - type = {type = "Enum", name = "TriStateBoolean"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - }, - defaults = { - Name = "PolicyService", - }, - }, - Pose = { - name = "Pose", - superclass = "PoseBase", - properties = { - CFrame = { - name = "CFrame", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaskWeight = { - name = "MaskWeight", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - EasingDirection = 0, - EasingStyle = 0, - MaskWeight = 0, - Name = "Pose", - Weight = 1, - }, - }, - PoseBase = { - name = "PoseBase", - superclass = "Instance", - properties = { - EasingDirection = { - name = "EasingDirection", - type = {type = "Enum", name = "PoseEasingDirection"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - EasingStyle = { - name = "EasingStyle", - type = {type = "Enum", name = "PoseEasingStyle"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Weight = { - name = "Weight", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - PostEffect = { - name = "PostEffect", - superclass = "Instance", - properties = { - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - PrismaticConstraint = { - name = "PrismaticConstraint", - superclass = "SlidingBallConstraint", - properties = { - }, - defaults = { - ActuatorType = 0, - Attachment0 = nil, - Attachment1 = nil, - Color = BrickColor.new(1009), - Enabled = true, - LimitsEnabled = false, - LowerLimit = 0, - MotorMaxAcceleration = 1000000000, - MotorMaxForce = 0, - Name = "PrismaticConstraint", - Restitution = 0, - ServoMaxForce = 0, - Size = 0.15, - Speed = 0, - TargetPosition = 0, - UpperLimit = 5, - Velocity = 0, - Visible = false, - }, - }, - ProximityPrompt = { - name = "ProximityPrompt", - superclass = "Instance", - properties = { - ActionText = { - name = "ActionText", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AutoLocalize = { - name = "AutoLocalize", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ClickablePrompt = { - name = "ClickablePrompt", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Exclusivity = { - name = "Exclusivity", - type = {type = "Enum", name = "ProximityPromptExclusivity"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GamepadKeyCode = { - name = "GamepadKeyCode", - type = {type = "Enum", name = "KeyCode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HoldDuration = { - name = "HoldDuration", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - KeyboardKeyCode = { - name = "KeyboardKeyCode", - type = {type = "Enum", name = "KeyCode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxActivationDistance = { - name = "MaxActivationDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ObjectText = { - name = "ObjectText", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RequiresLineOfSight = { - name = "RequiresLineOfSight", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RootLocalizationTable = { - name = "RootLocalizationTable", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Style = { - name = "Style", - type = {type = "Enum", name = "ProximityPromptStyle"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UIOffset = { - name = "UIOffset", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - ActionText = "Interact", - AutoLocalize = true, - ClickablePrompt = true, - Enabled = true, - Exclusivity = 0, - GamepadKeyCode = 1000, - HoldDuration = 0, - KeyboardKeyCode = 101, - MaxActivationDistance = 10, - Name = "ProximityPrompt", - ObjectText = "", - RequiresLineOfSight = true, - RootLocalizationTable = nil, - Style = 0, - UIOffset = Vector2.new(0, 0), - }, - }, - ProximityPromptService = { - name = "ProximityPromptService", - superclass = "Instance", - properties = { - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxPromptsVisible = { - name = "MaxPromptsVisible", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Enabled = true, - MaxPromptsVisible = 16, - Name = "ProximityPromptService", - }, - }, - QWidgetPluginGui = { - name = "QWidgetPluginGui", - superclass = "PluginGui", - properties = { - }, - defaults = { - }, - }, - RayValue = { - name = "RayValue", - superclass = "ValueBase", - properties = { - Value = { - name = "Value", - type = {type = "Unimplemented", name = "Ray"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Value", - }, - }, - RbxAnalyticsService = { - name = "RbxAnalyticsService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - ReflectionMetadata = { - name = "ReflectionMetadata", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - ReflectionMetadataCallbacks = { - name = "ReflectionMetadataCallbacks", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - ReflectionMetadataClass = { - name = "ReflectionMetadataClass", - superclass = "ReflectionMetadataItem", - properties = { - ExplorerImageIndex = { - name = "ExplorerImageIndex", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ExplorerOrder = { - name = "ExplorerOrder", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Insertable = { - name = "Insertable", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PreferredParent = { - name = "PreferredParent", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Browsable = true, - ClassCategory = "", - ClientOnly = false, - Constraint = "", - Deprecated = false, - EditingDisabled = false, - ExplorerImageIndex = 0, - ExplorerOrder = 2147483647, - Insertable = true, - IsBackend = false, - Name = "Instance", - PreferredParent = "", - ScriptContext = "", - ServerOnly = false, - UIMaximum = 0, - UIMinimum = 0, - UINumTicks = 0, - summary = "", - }, - }, - ReflectionMetadataClasses = { - name = "ReflectionMetadataClasses", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - ReflectionMetadataEnum = { - name = "ReflectionMetadataEnum", - superclass = "ReflectionMetadataItem", - properties = { - }, - defaults = { - Browsable = true, - ClassCategory = "", - ClientOnly = false, - Constraint = "", - Deprecated = false, - EditingDisabled = false, - IsBackend = false, - Name = "Instance", - ScriptContext = "", - ServerOnly = false, - UIMaximum = 0, - UIMinimum = 0, - UINumTicks = 0, - summary = "", - }, - }, - ReflectionMetadataEnumItem = { - name = "ReflectionMetadataEnumItem", - superclass = "ReflectionMetadataItem", - properties = { - }, - defaults = { - Browsable = true, - ClassCategory = "", - ClientOnly = false, - Constraint = "", - Deprecated = false, - EditingDisabled = false, - IsBackend = false, - Name = "Instance", - ScriptContext = "", - ServerOnly = false, - UIMaximum = 0, - UIMinimum = 0, - UINumTicks = 0, - summary = "", - }, - }, - ReflectionMetadataEnums = { - name = "ReflectionMetadataEnums", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - ReflectionMetadataEvents = { - name = "ReflectionMetadataEvents", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - ReflectionMetadataFunctions = { - name = "ReflectionMetadataFunctions", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - ReflectionMetadataItem = { - name = "ReflectionMetadataItem", - superclass = "Instance", - properties = { - Browsable = { - name = "Browsable", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ClassCategory = { - name = "ClassCategory", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ClientOnly = { - name = "ClientOnly", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Constraint = { - name = "Constraint", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Deprecated = { - name = "Deprecated", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - EditingDisabled = { - name = "EditingDisabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IsBackend = { - name = "IsBackend", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ScriptContext = { - name = "ScriptContext", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ServerOnly = { - name = "ServerOnly", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UIMaximum = { - name = "UIMaximum", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UIMinimum = { - name = "UIMinimum", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UINumTicks = { - name = "UINumTicks", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - summary = { - name = "summary", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - ReflectionMetadataMember = { - name = "ReflectionMetadataMember", - superclass = "ReflectionMetadataItem", - properties = { - }, - defaults = { - Browsable = true, - ClassCategory = "", - ClientOnly = false, - Constraint = "", - Deprecated = false, - EditingDisabled = false, - IsBackend = false, - Name = "Instance", - ScriptContext = "", - ServerOnly = false, - UIMaximum = 0, - UIMinimum = 0, - UINumTicks = 0, - summary = "", - }, - }, - ReflectionMetadataProperties = { - name = "ReflectionMetadataProperties", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - ReflectionMetadataYieldFunctions = { - name = "ReflectionMetadataYieldFunctions", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - RemoteEvent = { - name = "RemoteEvent", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "RemoteEvent", - }, - }, - RemoteFunction = { - name = "RemoteFunction", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "RemoteFunction", - }, - }, - RenderSettings = { - name = "RenderSettings", - superclass = "Instance", - properties = { - AutoFRMLevel = { - name = "AutoFRMLevel", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - EagerBulkExecution = { - name = "EagerBulkExecution", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - EditQualityLevel = { - name = "EditQualityLevel", - type = {type = "Enum", name = "QualityLevel"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - EnableFRM = { - name = "EnableFRM", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - ExportMergeByMaterial = { - name = "ExportMergeByMaterial", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FrameRateManager = { - name = "FrameRateManager", - type = {type = "Enum", name = "FramerateManagerMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GraphicsMode = { - name = "GraphicsMode", - type = {type = "Enum", name = "GraphicsMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MeshCacheSize = { - name = "MeshCacheSize", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MeshPartDetailLevel = { - name = "MeshPartDetailLevel", - type = {type = "Enum", name = "MeshPartDetailLevel"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - QualityLevel = { - name = "QualityLevel", - type = {type = "Enum", name = "QualityLevel"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ReloadAssets = { - name = "ReloadAssets", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RenderCSGTrianglesDebug = { - name = "RenderCSGTrianglesDebug", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ShowBoundingBoxes = { - name = "ShowBoundingBoxes", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - RenderingTest = { - name = "RenderingTest", - superclass = "Instance", - properties = { - CFrame = { - name = "CFrame", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ComparisonDiffThreshold = { - name = "ComparisonDiffThreshold", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ComparisonMethod = { - name = "ComparisonMethod", - type = {type = "Enum", name = "RenderingTestComparisonMethod"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ComparisonPsnrThreshold = { - name = "ComparisonPsnrThreshold", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Description = { - name = "Description", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FieldOfView = { - name = "FieldOfView", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Orientation = { - name = "Orientation", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Position = { - name = "Position", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - QualityLevel = { - name = "QualityLevel", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ShouldSkip = { - name = "ShouldSkip", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Ticket = { - name = "Ticket", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - ComparisonDiffThreshold = 10, - ComparisonMethod = 0, - ComparisonPsnrThreshold = 50, - Description = "", - FieldOfView = 70, - Name = "RenderingTest", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - QualityLevel = 21, - ShouldSkip = false, - Ticket = "", - }, - }, - ReplicatedFirst = { - name = "ReplicatedFirst", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "ReplicatedFirst", - }, - }, - ReplicatedScriptService = { - name = "ReplicatedScriptService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "ReplicatedScriptService", - }, - }, - ReplicatedStorage = { - name = "ReplicatedStorage", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "ReplicatedStorage", - }, - }, - ReverbSoundEffect = { - name = "ReverbSoundEffect", - superclass = "SoundEffect", - properties = { - DecayTime = { - name = "DecayTime", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Density = { - name = "Density", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Diffusion = { - name = "Diffusion", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DryLevel = { - name = "DryLevel", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WetLevel = { - name = "WetLevel", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - DecayTime = 1.5, - Density = 1, - Diffusion = 1, - DryLevel = -6, - Enabled = true, - Name = "ReverbSoundEffect", - Priority = 0, - WetLevel = 0, - }, - }, - RobloxPluginGuiService = { - name = "RobloxPluginGuiService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - RobloxReplicatedStorage = { - name = "RobloxReplicatedStorage", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - RocketPropulsion = { - name = "RocketPropulsion", - superclass = "BodyMover", - properties = { - CartoonFactor = { - name = "CartoonFactor", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxSpeed = { - name = "MaxSpeed", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxThrust = { - name = "MaxThrust", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxTorque = { - name = "MaxTorque", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Target = { - name = "Target", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TargetOffset = { - name = "TargetOffset", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TargetRadius = { - name = "TargetRadius", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ThrustD = { - name = "ThrustD", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ThrustP = { - name = "ThrustP", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TurnD = { - name = "TurnD", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TurnP = { - name = "TurnP", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - CartoonFactor = 0.7, - MaxSpeed = 30, - MaxThrust = 4000, - MaxTorque = Vector3.new(400000, 400000, 0), - Name = "RocketPropulsion", - Target = nil, - TargetOffset = Vector3.new(0, 0, 0), - TargetRadius = 4, - ThrustD = 0.001, - ThrustP = 5, - TurnD = 500, - TurnP = 3000, - }, - }, - RodConstraint = { - name = "RodConstraint", - superclass = "Constraint", - properties = { - CurrentDistance = { - name = "CurrentDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Length = { - name = "Length", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Thickness = { - name = "Thickness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Attachment0 = nil, - Attachment1 = nil, - Color = BrickColor.new(26), - Enabled = true, - Length = 5, - Name = "RodConstraint", - Thickness = 0.1, - Visible = false, - }, - }, - RopeConstraint = { - name = "RopeConstraint", - superclass = "Constraint", - properties = { - CurrentDistance = { - name = "CurrentDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Length = { - name = "Length", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Restitution = { - name = "Restitution", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Thickness = { - name = "Thickness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Attachment0 = nil, - Attachment1 = nil, - Color = BrickColor.new(25), - Enabled = true, - Length = 5, - Name = "RopeConstraint", - Restitution = 0, - Thickness = 0.1, - Visible = false, - }, - }, - Rotate = { - name = "Rotate", - superclass = "JointInstance", - properties = { - }, - defaults = { - C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Enabled = true, - Name = "Rotate", - Part0 = nil, - Part1 = nil, - }, - }, - RotateP = { - name = "RotateP", - superclass = "DynamicRotate", - properties = { - }, - defaults = { - BaseAngle = 0, - C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Enabled = true, - Name = "RotateP", - Part0 = nil, - Part1 = nil, - }, - }, - RotateV = { - name = "RotateV", - superclass = "DynamicRotate", - properties = { - }, - defaults = { - BaseAngle = 0, - C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Enabled = true, - Name = "RotateV", - Part0 = nil, - Part1 = nil, - }, - }, - RunService = { - name = "RunService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Run Service", - }, - }, - RunningAverageItemDouble = { - name = "RunningAverageItemDouble", - superclass = "StatsItem", - properties = { - }, - defaults = { - }, - }, - RunningAverageItemInt = { - name = "RunningAverageItemInt", - superclass = "StatsItem", - properties = { - }, - defaults = { - }, - }, - RunningAverageTimeIntervalItem = { - name = "RunningAverageTimeIntervalItem", - superclass = "StatsItem", - properties = { - }, - defaults = { - }, - }, - RuntimeScriptService = { - name = "RuntimeScriptService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - ScreenGui = { - name = "ScreenGui", - superclass = "LayerCollector", - properties = { - DisplayOrder = { - name = "DisplayOrder", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IgnoreGuiInset = { - name = "IgnoreGuiInset", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - OnTopOfCoreBlur = { - name = "OnTopOfCoreBlur", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - }, - defaults = { - AutoLocalize = true, - DisplayOrder = 0, - Enabled = true, - IgnoreGuiInset = false, - Localize = true, - Name = "ScreenGui", - ResetOnSpawn = true, - RootLocalizationTable = nil, - ZIndexBehavior = 0, - }, - }, - Script = { - name = "Script", - superclass = "BaseScript", - properties = { - Source = { - name = "Source", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Disabled = false, - LinkedSource = "", - Name = "Script", - Source = "", - }, - }, - ScriptContext = { - name = "ScriptContext", - superclass = "Instance", - properties = { - ScriptsDisabled = { - name = "ScriptsDisabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - }, - defaults = { - Name = "Script Context", - }, - }, - ScriptDebugger = { - name = "ScriptDebugger", - superclass = "Instance", - properties = { - CurrentLine = { - name = "CurrentLine", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - IsDebugging = { - name = "IsDebugging", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - IsPaused = { - name = "IsPaused", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Script = { - name = "Script", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - ScriptService = { - name = "ScriptService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - ScrollingFrame = { - name = "ScrollingFrame", - superclass = "GuiObject", - properties = { - AbsoluteCanvasSize = { - name = "AbsoluteCanvasSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - AbsoluteWindowSize = { - name = "AbsoluteWindowSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - AutomaticCanvasSize = { - name = "AutomaticCanvasSize", - type = {type = "Enum", name = "AutomaticSize"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - BottomImage = { - name = "BottomImage", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CanvasPosition = { - name = "CanvasPosition", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CanvasSize = { - name = "CanvasSize", - type = {type = "Data", name = "UDim2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ElasticBehavior = { - name = "ElasticBehavior", - type = {type = "Enum", name = "ElasticBehavior"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HorizontalBarRect = { - name = "HorizontalBarRect", - type = {type = "Data", name = "Rect"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - HorizontalScrollBarInset = { - name = "HorizontalScrollBarInset", - type = {type = "Enum", name = "ScrollBarInset"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxCanvasPosition = { - name = "MaxCanvasPosition", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - MidImage = { - name = "MidImage", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ScrollBarImageColor3 = { - name = "ScrollBarImageColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ScrollBarImageTransparency = { - name = "ScrollBarImageTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ScrollBarThickness = { - name = "ScrollBarThickness", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ScrollingDirection = { - name = "ScrollingDirection", - type = {type = "Enum", name = "ScrollingDirection"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ScrollingEnabled = { - name = "ScrollingEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TopImage = { - name = "TopImage", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - VerticalBarRect = { - name = "VerticalBarRect", - type = {type = "Data", name = "Rect"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - VerticalScrollBarInset = { - name = "VerticalScrollBarInset", - type = {type = "Enum", name = "ScrollBarInset"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - VerticalScrollBarPosition = { - name = "VerticalScrollBarPosition", - type = {type = "Enum", name = "VerticalScrollBarPosition"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Active = false, - AnchorPoint = Vector2.new(0, 0), - AutoLocalize = true, - AutomaticCanvasSize = 0, - AutomaticSize = 0, - BackgroundColor = BrickColor.new(194), - BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), - BackgroundTransparency = 0, - BorderColor = BrickColor.new(26), - BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), - BorderMode = 0, - BorderSizePixel = 1, - BottomImage = "rbxasset://textures/ui/Scroll/scroll-bottom.png", - CanvasPosition = Vector2.new(0, 0), - CanvasSize = UDim2.new(0, 0, 2, 0), - ClipsDescendants = true, - Draggable = false, - ElasticBehavior = 0, - HorizontalScrollBarInset = 0, - LayoutOrder = 0, - Localize = true, - MidImage = "rbxasset://textures/ui/Scroll/scroll-middle.png", - Name = "ScrollingFrame", - NextSelectionDown = nil, - NextSelectionLeft = nil, - NextSelectionRight = nil, - NextSelectionUp = nil, - Position = UDim2.new(0, 0, 0, 0), - RootLocalizationTable = nil, - Rotation = 0, - ScrollBarImageColor3 = Color3.new(1, 1, 1), - ScrollBarImageTransparency = 0, - ScrollBarThickness = 12, - ScrollingDirection = 4, - ScrollingEnabled = true, - Selectable = true, - SelectionImageObject = nil, - Size = UDim2.new(0, 0, 0, 0), - SizeConstraint = 0, - TopImage = "rbxasset://textures/ui/Scroll/scroll-top.png", - Transparency = 0, - VerticalScrollBarInset = 0, - VerticalScrollBarPosition = 0, - Visible = true, - ZIndex = 1, - }, - }, - Seat = { - name = "Seat", - superclass = "Part", - properties = { - Disabled = { - name = "Disabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Occupant = { - name = "Occupant", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - Anchored = false, - AssemblyAngularVelocity = Vector3.new(0, 0, 0), - AssemblyLinearVelocity = Vector3.new(0, 0, 0), - BackParamA = -0.5, - BackParamB = 0.5, - BackSurface = 0, - BackSurfaceInput = 0, - BottomParamA = -0.5, - BottomParamB = 0.5, - BottomSurface = 4, - BottomSurfaceInput = 0, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CanCollide = true, - CanTouch = true, - CastShadow = true, - CollisionGroupId = 0, - Color = Color3.new(0.6392157, 0.63529414, 0.64705884), - CustomPhysicalProperties = nil, - Disabled = false, - Elasticity = 0.5, - FormFactor = 1, - Friction = 0.3, - FrontParamA = -0.5, - FrontParamB = 0.5, - FrontSurface = 0, - FrontSurfaceInput = 0, - LeftParamA = -0.5, - LeftParamB = 0.5, - LeftSurface = 0, - LeftSurfaceInput = 0, - LocalTransparencyModifier = 0, - Locked = false, - Massless = false, - Material = 256, - Name = "Seat", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Reflectance = 0, - RightParamA = -0.5, - RightParamB = 0.5, - RightSurface = 0, - RightSurfaceInput = 0, - RootPriority = 0, - RotVelocity = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - Shape = 1, - Size = Vector3.new(4, 1.2, 2), - TopParamA = -0.5, - TopParamB = 0.5, - TopSurface = 3, - TopSurfaceInput = 0, - Transparency = 0, - Velocity = Vector3.new(0, 0, 0), - }, - }, - Selection = { - name = "Selection", - superclass = "Instance", - properties = { - ActiveInstance = { - name = "ActiveInstance", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - Name = "Selection", - }, - }, - SelectionBox = { - name = "SelectionBox", - superclass = "InstanceAdornment", - properties = { - LineThickness = { - name = "LineThickness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SurfaceColor = { - name = "SurfaceColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - SurfaceColor3 = { - name = "SurfaceColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SurfaceTransparency = { - name = "SurfaceTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Adornee = nil, - Color = BrickColor.new(23), - Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - LineThickness = 0.15, - Name = "SelectionBox", - SurfaceColor = BrickColor.new(23), - SurfaceColor3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - SurfaceTransparency = 1, - Transparency = 0, - Visible = true, - }, - }, - SelectionLasso = { - name = "SelectionLasso", - superclass = "GuiBase3d", - properties = { - Humanoid = { - name = "Humanoid", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - SelectionPartLasso = { - name = "SelectionPartLasso", - superclass = "SelectionLasso", - properties = { - Part = { - name = "Part", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Color = BrickColor.new(23), - Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - Humanoid = nil, - Name = "SelectionPartLasso", - Part = nil, - Transparency = 0, - Visible = true, - }, - }, - SelectionPointLasso = { - name = "SelectionPointLasso", - superclass = "SelectionLasso", - properties = { - Point = { - name = "Point", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Color = BrickColor.new(23), - Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - Humanoid = nil, - Name = "SelectionPointLasso", - Point = Vector3.new(0, 0, 0), - Transparency = 0, - Visible = true, - }, - }, - SelectionSphere = { - name = "SelectionSphere", - superclass = "PVAdornment", - properties = { - SurfaceColor = { - name = "SurfaceColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - SurfaceColor3 = { - name = "SurfaceColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SurfaceTransparency = { - name = "SurfaceTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Adornee = nil, - Color = BrickColor.new(23), - Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - Name = "SelectionSphere", - SurfaceColor = BrickColor.new(23), - SurfaceColor3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - SurfaceTransparency = 1, - Transparency = 0, - Visible = true, - }, - }, - ServerReplicator = { - name = "ServerReplicator", - superclass = "NetworkReplicator", - properties = { - }, - defaults = { - }, - }, - ServerScriptService = { - name = "ServerScriptService", - superclass = "Instance", - properties = { - LoadStringEnabled = { - name = "LoadStringEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - }, - defaults = { - Name = "ServerScriptService", - }, - }, - ServerStorage = { - name = "ServerStorage", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "ServerStorage", - }, - }, - ServiceProvider = { - name = "ServiceProvider", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - SessionService = { - name = "SessionService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - Shirt = { - name = "Shirt", - superclass = "Clothing", - properties = { - ShirtTemplate = { - name = "ShirtTemplate", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Color3 = Color3.new(1, 1, 1), - Name = "Clothing", - ShirtTemplate = "", - }, - }, - ShirtGraphic = { - name = "ShirtGraphic", - superclass = "CharacterAppearance", - properties = { - Color3 = { - name = "Color3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Graphic = { - name = "Graphic", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Color3 = Color3.new(1, 1, 1), - Graphic = "", - Name = "Shirt Graphic", - }, - }, - SkateboardController = { - name = "SkateboardController", - superclass = "Controller", - properties = { - Steer = { - name = "Steer", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Throttle = { - name = "Throttle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - Name = "SkateboardController", - }, - }, - SkateboardPlatform = { - name = "SkateboardPlatform", - superclass = "Part", - properties = { - Controller = { - name = "Controller", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ControllingHumanoid = { - name = "ControllingHumanoid", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Steer = { - name = "Steer", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - StickyWheels = { - name = "StickyWheels", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Throttle = { - name = "Throttle", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Anchored = false, - AssemblyAngularVelocity = Vector3.new(0, 0, 0), - AssemblyLinearVelocity = Vector3.new(0, 0, 0), - BackParamA = -0.5, - BackParamB = 0.5, - BackSurface = 0, - BackSurfaceInput = 0, - BottomParamA = -0.5, - BottomParamB = 0.5, - BottomSurface = 4, - BottomSurfaceInput = 0, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CanCollide = true, - CanTouch = true, - CastShadow = true, - CollisionGroupId = 0, - Color = Color3.new(0.6392157, 0.63529414, 0.64705884), - CustomPhysicalProperties = nil, - Elasticity = 0.5, - FormFactor = 1, - Friction = 0.3, - FrontParamA = -0.5, - FrontParamB = 0.5, - FrontSurface = 0, - FrontSurfaceInput = 0, - LeftParamA = -0.5, - LeftParamB = 0.5, - LeftSurface = 0, - LeftSurfaceInput = 0, - LocalTransparencyModifier = 0, - Locked = false, - Massless = false, - Material = 256, - Name = "SkateboardPlatform", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Reflectance = 0, - RightParamA = -0.5, - RightParamB = 0.5, - RightSurface = 0, - RightSurfaceInput = 0, - RootPriority = 0, - RotVelocity = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - Shape = 1, - Size = Vector3.new(4, 1.2, 2), - Steer = 0, - StickyWheels = true, - Throttle = 0, - TopParamA = -0.5, - TopParamB = 0.5, - TopSurface = 3, - TopSurfaceInput = 0, - Transparency = 0, - Velocity = Vector3.new(0, 0, 0), - }, - }, - Skin = { - name = "Skin", - superclass = "CharacterAppearance", - properties = { - SkinColor = { - name = "SkinColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Skin", - SkinColor = BrickColor.new(226), - }, - }, - Sky = { - name = "Sky", - superclass = "Instance", - properties = { - CelestialBodiesShown = { - name = "CelestialBodiesShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MoonAngularSize = { - name = "MoonAngularSize", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MoonTextureId = { - name = "MoonTextureId", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SkyboxBk = { - name = "SkyboxBk", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SkyboxDn = { - name = "SkyboxDn", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SkyboxFt = { - name = "SkyboxFt", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SkyboxLf = { - name = "SkyboxLf", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SkyboxRt = { - name = "SkyboxRt", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SkyboxUp = { - name = "SkyboxUp", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - StarCount = { - name = "StarCount", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SunAngularSize = { - name = "SunAngularSize", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SunTextureId = { - name = "SunTextureId", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - CelestialBodiesShown = true, - MoonAngularSize = 11, - MoonTextureId = "rbxasset://sky/moon.jpg", - Name = "Sky", - SkyboxBk = "rbxasset://textures/sky/sky512_bk.tex", - SkyboxDn = "rbxasset://textures/sky/sky512_dn.tex", - SkyboxFt = "rbxasset://textures/sky/sky512_ft.tex", - SkyboxLf = "rbxasset://textures/sky/sky512_lf.tex", - SkyboxRt = "rbxasset://textures/sky/sky512_rt.tex", - SkyboxUp = "rbxasset://textures/sky/sky512_up.tex", - StarCount = 3000, - SunAngularSize = 21, - SunTextureId = "rbxasset://sky/sun.jpg", - }, - }, - SlidingBallConstraint = { - name = "SlidingBallConstraint", - superclass = "Constraint", - properties = { - ActuatorType = { - name = "ActuatorType", - type = {type = "Enum", name = "ActuatorType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CurrentPosition = { - name = "CurrentPosition", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - LimitsEnabled = { - name = "LimitsEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LowerLimit = { - name = "LowerLimit", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MotorMaxAcceleration = { - name = "MotorMaxAcceleration", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MotorMaxForce = { - name = "MotorMaxForce", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Restitution = { - name = "Restitution", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ServoMaxForce = { - name = "ServoMaxForce", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Size = { - name = "Size", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Speed = { - name = "Speed", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TargetPosition = { - name = "TargetPosition", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UpperLimit = { - name = "UpperLimit", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Velocity = { - name = "Velocity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - Smoke = { - name = "Smoke", - superclass = "Instance", - properties = { - Color = { - name = "Color", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Opacity = { - name = "Opacity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = "opacity_xml", - scriptability = "ReadWrite", - serializes = true, - }, - RiseVelocity = { - name = "RiseVelocity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = "riseVelocity_xml", - scriptability = "ReadWrite", - serializes = true, - }, - Size = { - name = "Size", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = "size_xml", - scriptability = "ReadWrite", - serializes = true, - }, - opacity_xml = { - name = "opacity_xml", - type = {type = "Data", name = "Float32"}, - isCanonical = false, - canonicalName = "Opacity", - serializedName = nil, - scriptability = "None", - serializes = false, - }, - riseVelocity_xml = { - name = "riseVelocity_xml", - type = {type = "Data", name = "Float32"}, - isCanonical = false, - canonicalName = "RiseVelocity", - serializedName = nil, - scriptability = "None", - serializes = false, - }, - size_xml = { - name = "size_xml", - type = {type = "Data", name = "Float32"}, - isCanonical = false, - canonicalName = "Size", - serializedName = nil, - scriptability = "None", - serializes = false, - }, - }, - defaults = { - Color = Color3.new(1, 1, 1), - Enabled = true, - Name = "Smoke", - Opacity = 0.5, - RiseVelocity = 1, - Size = 1, - }, - }, - Snap = { - name = "Snap", - superclass = "JointInstance", - properties = { - }, - defaults = { - C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Enabled = true, - Name = "Snap", - Part0 = nil, - Part1 = nil, - }, - }, - SocialService = { - name = "SocialService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "SocialService", - }, - }, - SolidModelContentProvider = { - name = "SolidModelContentProvider", - superclass = "CacheableContentProvider", - properties = { - }, - defaults = { - Name = "SolidModelContentProvider", - }, - }, - Sound = { - name = "Sound", - superclass = "Instance", - properties = { - EmitterSize = { - name = "EmitterSize", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IsLoaded = { - name = "IsLoaded", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - IsPaused = { - name = "IsPaused", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - IsPlaying = { - name = "IsPlaying", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Looped = { - name = "Looped", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxDistance = { - name = "MaxDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = "xmlRead_MaxDistance_3", - scriptability = "ReadWrite", - serializes = true, - }, - MinDistance = { - name = "MinDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Pitch = { - name = "Pitch", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - PlayOnRemove = { - name = "PlayOnRemove", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PlaybackLoudness = { - name = "PlaybackLoudness", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - PlaybackSpeed = { - name = "PlaybackSpeed", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Playing = { - name = "Playing", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RollOffMaxDistance = { - name = "RollOffMaxDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - RollOffMinDistance = { - name = "RollOffMinDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - RollOffMode = { - name = "RollOffMode", - type = {type = "Enum", name = "RollOffMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SoundGroup = { - name = "SoundGroup", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SoundId = { - name = "SoundId", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TimeLength = { - name = "TimeLength", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TimePosition = { - name = "TimePosition", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Volume = { - name = "Volume", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - isPlaying = { - name = "isPlaying", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - xmlRead_MaxDistance_3 = { - name = "xmlRead_MaxDistance_3", - type = {type = "Data", name = "Float32"}, - isCanonical = false, - canonicalName = "MaxDistance", - serializedName = nil, - scriptability = "None", - serializes = false, - }, - }, - defaults = { - EmitterSize = 10, - Looped = false, - MaxDistance = 10000, - MinDistance = 10, - Name = "Sound", - Pitch = 1, - PlayOnRemove = false, - PlaybackSpeed = 1, - Playing = false, - RollOffMaxDistance = 10000, - RollOffMinDistance = 10, - RollOffMode = 0, - SoundGroup = nil, - SoundId = "", - TimePosition = 0, - Volume = 0.5, - }, - }, - SoundEffect = { - name = "SoundEffect", - superclass = "Instance", - properties = { - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Priority = { - name = "Priority", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - SoundGroup = { - name = "SoundGroup", - superclass = "Instance", - properties = { - Volume = { - name = "Volume", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "SoundGroup", - Volume = 0.5, - }, - }, - SoundService = { - name = "SoundService", - superclass = "Instance", - properties = { - AmbientReverb = { - name = "AmbientReverb", - type = {type = "Enum", name = "ReverbType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DistanceFactor = { - name = "DistanceFactor", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DopplerScale = { - name = "DopplerScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RespectFilteringEnabled = { - name = "RespectFilteringEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RolloffScale = { - name = "RolloffScale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AmbientReverb = 0, - DistanceFactor = 3.33, - DopplerScale = 1, - Name = "SoundService", - RespectFilteringEnabled = false, - RolloffScale = 1, - }, - }, - Sparkles = { - name = "Sparkles", - superclass = "Instance", - properties = { - Color = { - name = "Color", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SparkleColor = { - name = "SparkleColor", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Color = Color3.new(1, 1.0000001, 1), - Enabled = true, - Name = "Sparkles", - SparkleColor = Color3.new(0.5647059, 0.09803923, 1), - }, - }, - SpawnLocation = { - name = "SpawnLocation", - superclass = "Part", - properties = { - AllowTeamChangeOnTouch = { - name = "AllowTeamChangeOnTouch", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Duration = { - name = "Duration", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Neutral = { - name = "Neutral", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TeamColor = { - name = "TeamColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AllowTeamChangeOnTouch = false, - Anchored = false, - AssemblyAngularVelocity = Vector3.new(0, 0, 0), - AssemblyLinearVelocity = Vector3.new(0, 0, 0), - BackParamA = -0.5, - BackParamB = 0.5, - BackSurface = 0, - BackSurfaceInput = 0, - BottomParamA = -0.5, - BottomParamB = 0.5, - BottomSurface = 4, - BottomSurfaceInput = 0, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CanCollide = true, - CanTouch = true, - CastShadow = true, - CollisionGroupId = 0, - Color = Color3.new(0.6392157, 0.63529414, 0.64705884), - CustomPhysicalProperties = nil, - Duration = 10, - Elasticity = 0.5, - Enabled = true, - FormFactor = 1, - Friction = 0.3, - FrontParamA = -0.5, - FrontParamB = 0.5, - FrontSurface = 0, - FrontSurfaceInput = 0, - LeftParamA = -0.5, - LeftParamB = 0.5, - LeftSurface = 0, - LeftSurfaceInput = 0, - LocalTransparencyModifier = 0, - Locked = false, - Massless = false, - Material = 256, - Name = "SpawnLocation", - Neutral = true, - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Reflectance = 0, - RightParamA = -0.5, - RightParamB = 0.5, - RightSurface = 0, - RightSurfaceInput = 0, - RootPriority = 0, - RotVelocity = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - Shape = 1, - Size = Vector3.new(4, 1.2, 2), - TeamColor = BrickColor.new(194), - TopParamA = -0.5, - TopParamB = 0.5, - TopSurface = 3, - TopSurfaceInput = 0, - Transparency = 0, - Velocity = Vector3.new(0, 0, 0), - }, - }, - SpawnerService = { - name = "SpawnerService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - SpecialMesh = { - name = "SpecialMesh", - superclass = "FileMesh", - properties = { - MeshType = { - name = "MeshType", - type = {type = "Enum", name = "MeshType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - MeshId = "", - MeshType = 0, - Name = "Mesh", - Offset = Vector3.new(0, 0, 0), - Scale = Vector3.new(1, 1, 1), - TextureId = "", - VertexColor = Vector3.new(1, 1, 1), - }, - }, - SphereHandleAdornment = { - name = "SphereHandleAdornment", - superclass = "HandleAdornment", - properties = { - Radius = { - name = "Radius", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AdornCullingMode = 0, - Adornee = nil, - AlwaysOnTop = false, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Color = BrickColor.new(23), - Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - Name = "SphereHandleAdornment", - Radius = 1, - SizeRelativeOffset = Vector3.new(0, 0, 0), - Transparency = 0, - Visible = true, - ZIndex = -1, - }, - }, - SpotLight = { - name = "SpotLight", - superclass = "Light", - properties = { - Angle = { - name = "Angle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Face = { - name = "Face", - type = {type = "Enum", name = "NormalId"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Range = { - name = "Range", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Angle = 90, - Brightness = 1, - Color = Color3.new(1, 1, 1), - Enabled = true, - Face = 5, - Name = "SpotLight", - Range = 16, - Shadows = false, - }, - }, - SpringConstraint = { - name = "SpringConstraint", - superclass = "Constraint", - properties = { - Coils = { - name = "Coils", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CurrentLength = { - name = "CurrentLength", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Damping = { - name = "Damping", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FreeLength = { - name = "FreeLength", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LimitsEnabled = { - name = "LimitsEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxForce = { - name = "MaxForce", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxLength = { - name = "MaxLength", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MinLength = { - name = "MinLength", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Radius = { - name = "Radius", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Stiffness = { - name = "Stiffness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Thickness = { - name = "Thickness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Attachment0 = nil, - Attachment1 = nil, - Coils = 3, - Color = BrickColor.new(200), - Damping = 0, - Enabled = true, - FreeLength = 1, - LimitsEnabled = false, - MaxForce = 1000000000, - MaxLength = 5, - MinLength = 0, - Name = "SpringConstraint", - Radius = 0.4, - Stiffness = 0, - Thickness = 0.1, - Visible = false, - }, - }, - StandalonePluginScripts = { - name = "StandalonePluginScripts", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "StandalonePluginScripts", - }, - }, - StandardPages = { - name = "StandardPages", - superclass = "Pages", - properties = { - }, - defaults = { - }, - }, - StarterCharacterScripts = { - name = "StarterCharacterScripts", - superclass = "StarterPlayerScripts", - properties = { - }, - defaults = { - }, - }, - StarterGear = { - name = "StarterGear", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "StarterGear", - }, - }, - StarterGui = { - name = "StarterGui", - superclass = "BasePlayerGui", - properties = { - ProcessUserInput = { - name = "ProcessUserInput", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - ResetPlayerGuiOnSpawn = { - name = "ResetPlayerGuiOnSpawn", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ScreenOrientation = { - name = "ScreenOrientation", - type = {type = "Enum", name = "ScreenOrientation"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ShowDevelopmentGui = { - name = "ShowDevelopmentGui", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "StarterGui", - ProcessUserInput = true, - ResetPlayerGuiOnSpawn = true, - ScreenOrientation = 2, - ShowDevelopmentGui = true, - }, - }, - StarterPack = { - name = "StarterPack", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "StarterPack", - }, - }, - StarterPlayer = { - name = "StarterPlayer", - superclass = "Instance", - properties = { - AllowCustomAnimations = { - name = "AllowCustomAnimations", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = true, - }, - AutoJumpEnabled = { - name = "AutoJumpEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CameraMaxZoomDistance = { - name = "CameraMaxZoomDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CameraMinZoomDistance = { - name = "CameraMinZoomDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CameraMode = { - name = "CameraMode", - type = {type = "Enum", name = "CameraMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CharacterJumpHeight = { - name = "CharacterJumpHeight", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CharacterJumpPower = { - name = "CharacterJumpPower", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CharacterMaxSlopeAngle = { - name = "CharacterMaxSlopeAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CharacterUseJumpPower = { - name = "CharacterUseJumpPower", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CharacterWalkSpeed = { - name = "CharacterWalkSpeed", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DevCameraOcclusionMode = { - name = "DevCameraOcclusionMode", - type = {type = "Enum", name = "DevCameraOcclusionMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DevComputerCameraMovementMode = { - name = "DevComputerCameraMovementMode", - type = {type = "Enum", name = "DevComputerCameraMovementMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DevComputerMovementMode = { - name = "DevComputerMovementMode", - type = {type = "Enum", name = "DevComputerMovementMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DevTouchCameraMovementMode = { - name = "DevTouchCameraMovementMode", - type = {type = "Enum", name = "DevTouchCameraMovementMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DevTouchMovementMode = { - name = "DevTouchMovementMode", - type = {type = "Enum", name = "DevTouchMovementMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - EnableMouseLockOption = { - name = "EnableMouseLockOption", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GameSettingsAssetIDFace = { - name = "GameSettingsAssetIDFace", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsAssetIDHead = { - name = "GameSettingsAssetIDHead", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsAssetIDLeftArm = { - name = "GameSettingsAssetIDLeftArm", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsAssetIDLeftLeg = { - name = "GameSettingsAssetIDLeftLeg", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsAssetIDPants = { - name = "GameSettingsAssetIDPants", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsAssetIDRightArm = { - name = "GameSettingsAssetIDRightArm", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsAssetIDRightLeg = { - name = "GameSettingsAssetIDRightLeg", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsAssetIDShirt = { - name = "GameSettingsAssetIDShirt", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsAssetIDTeeShirt = { - name = "GameSettingsAssetIDTeeShirt", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsAssetIDTorso = { - name = "GameSettingsAssetIDTorso", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsAvatar = { - name = "GameSettingsAvatar", - type = {type = "Enum", name = "GameAvatarType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsR15Collision = { - name = "GameSettingsR15Collision", - type = {type = "Enum", name = "R15CollisionType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsScaleRangeBodyType = { - name = "GameSettingsScaleRangeBodyType", - type = {type = "Data", name = "NumberRange"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsScaleRangeHead = { - name = "GameSettingsScaleRangeHead", - type = {type = "Data", name = "NumberRange"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsScaleRangeHeight = { - name = "GameSettingsScaleRangeHeight", - type = {type = "Data", name = "NumberRange"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsScaleRangeProportion = { - name = "GameSettingsScaleRangeProportion", - type = {type = "Data", name = "NumberRange"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - GameSettingsScaleRangeWidth = { - name = "GameSettingsScaleRangeWidth", - type = {type = "Data", name = "NumberRange"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - HealthDisplayDistance = { - name = "HealthDisplayDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LoadCharacterAppearance = { - name = "LoadCharacterAppearance", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - NameDisplayDistance = { - name = "NameDisplayDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UserEmotesEnabled = { - name = "UserEmotesEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AllowCustomAnimations = true, - AutoJumpEnabled = true, - CameraMaxZoomDistance = 400, - CameraMinZoomDistance = 0.5, - CameraMode = 0, - CharacterJumpHeight = 7.2, - CharacterJumpPower = 50, - CharacterMaxSlopeAngle = 89, - CharacterUseJumpPower = true, - CharacterWalkSpeed = 16, - DevCameraOcclusionMode = 0, - DevComputerCameraMovementMode = 0, - DevComputerMovementMode = 0, - DevTouchCameraMovementMode = 0, - DevTouchMovementMode = 0, - EnableMouseLockOption = true, - HealthDisplayDistance = 100, - LoadCharacterAppearance = true, - Name = "StarterPlayer", - NameDisplayDistance = 100, - UserEmotesEnabled = true, - }, - }, - StarterPlayerScripts = { - name = "StarterPlayerScripts", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - Stats = { - name = "Stats", - superclass = "Instance", - properties = { - ContactsCount = { - name = "ContactsCount", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - DataReceiveKbps = { - name = "DataReceiveKbps", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - DataSendKbps = { - name = "DataSendKbps", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - HeartbeatTimeMs = { - name = "HeartbeatTimeMs", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - InstanceCount = { - name = "InstanceCount", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - MovingPrimitivesCount = { - name = "MovingPrimitivesCount", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - PhysicsReceiveKbps = { - name = "PhysicsReceiveKbps", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - PhysicsSendKbps = { - name = "PhysicsSendKbps", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - PhysicsStepTimeMs = { - name = "PhysicsStepTimeMs", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - PrimitivesCount = { - name = "PrimitivesCount", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - Name = "Stats", - }, - }, - StatsItem = { - name = "StatsItem", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - Status = { - name = "Status", - superclass = "Model", - properties = { - }, - defaults = { - }, - }, - StopWatchReporter = { - name = "StopWatchReporter", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - StringValue = { - name = "StringValue", - superclass = "ValueBase", - properties = { - Value = { - name = "Value", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Value", - Value = "", - }, - }, - Studio = { - name = "Studio", - superclass = "Instance", - properties = { - CommandBarLocalState = { - name = "CommandBarLocalState", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DefaultScriptFileDir = { - name = "DefaultScriptFileDir", - type = {type = "Unimplemented", name = "QDir"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DeprecatedObjectsShown = { - name = "DeprecatedObjectsShown", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Font = { - name = "Font", - type = {type = "Unimplemented", name = "QFont"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Language = { - name = "Language", - type = {type = "Enum", name = "LanguagePreference"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LocalAssetsFolder = { - name = "LocalAssetsFolder", - type = {type = "Unimplemented", name = "QDir"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LuaDebuggerEnabled = { - name = "LuaDebuggerEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LuaDebuggerEnabledAtStartup = { - name = "LuaDebuggerEnabledAtStartup", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - OverrideCoreScripts = { - name = "OverrideCoreScripts", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - OverrideCoreScriptsDir = { - name = "OverrideCoreScriptsDir", - type = {type = "Unimplemented", name = "QDir"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PermissionLevelShown = { - name = "PermissionLevelShown", - type = {type = "Enum", name = "PermissionLevelShown"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PluginDebuggingEnabled = { - name = "PluginDebuggingEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PluginsDir = { - name = "PluginsDir", - type = {type = "Unimplemented", name = "QDir"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Rulers = { - name = "Rulers", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RuntimeUndoBehavior = { - name = "RuntimeUndoBehavior", - type = {type = "Enum", name = "RuntimeUndoBehavior"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ScriptTimeoutLength = { - name = "ScriptTimeoutLength", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Theme = { - name = "Theme", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - }, - }, - StudioData = { - name = "StudioData", - superclass = "Instance", - properties = { - EnableScriptCollabByDefaultOnLoad = { - name = "EnableScriptCollabByDefaultOnLoad", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - EnableScriptCollabOnLoad = { - name = "EnableScriptCollabOnLoad", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - SrcPlaceId = { - name = "SrcPlaceId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - SrcUniverseId = { - name = "SrcUniverseId", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - }, - defaults = { - }, - }, - StudioService = { - name = "StudioService", - superclass = "Instance", - properties = { - ActiveScript = { - name = "ActiveScript", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - AlignDraggedObjects = { - name = "AlignDraggedObjects", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - DraggerSolveConstraints = { - name = "DraggerSolveConstraints", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - DrawConstraintsOnTop = { - name = "DrawConstraintsOnTop", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - GridSize = { - name = "GridSize", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - HoverInstance = { - name = "HoverInstance", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - InstalledPluginData = { - name = "InstalledPluginData", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - RotateIncrement = { - name = "RotateIncrement", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ShowActiveInstanceHighlight = { - name = "ShowActiveInstanceHighlight", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - ShowConstraintDetails = { - name = "ShowConstraintDetails", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - StudioLocaleId = { - name = "StudioLocaleId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - UseLocalSpace = { - name = "UseLocalSpace", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - Name = "StudioService", - UseLocalSpace = true, - }, - }, - StudioTheme = { - name = "StudioTheme", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - SunRaysEffect = { - name = "SunRaysEffect", - superclass = "PostEffect", - properties = { - Intensity = { - name = "Intensity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Spread = { - name = "Spread", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Enabled = true, - Intensity = 0.25, - Name = "SunRays", - Spread = 1, - }, - }, - SurfaceAppearance = { - name = "SurfaceAppearance", - superclass = "Instance", - properties = { - AlphaMode = { - name = "AlphaMode", - type = {type = "Enum", name = "AlphaMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - ColorMap = { - name = "ColorMap", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - MetalnessMap = { - name = "MetalnessMap", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - NormalMap = { - name = "NormalMap", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - RoughnessMap = { - name = "RoughnessMap", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - TexturePack = { - name = "TexturePack", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - }, - defaults = { - Name = "SurfaceAppearance", - }, - }, - SurfaceGui = { - name = "SurfaceGui", - superclass = "LayerCollector", - properties = { - Active = { - name = "Active", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Adornee = { - name = "Adornee", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AlwaysOnTop = { - name = "AlwaysOnTop", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CanvasSize = { - name = "CanvasSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ClipsDescendants = { - name = "ClipsDescendants", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Face = { - name = "Face", - type = {type = "Enum", name = "NormalId"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LightInfluence = { - name = "LightInfluence", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PixelsPerStud = { - name = "PixelsPerStud", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SizingMode = { - name = "SizingMode", - type = {type = "Enum", name = "SurfaceGuiSizingMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ToolPunchThroughDistance = { - name = "ToolPunchThroughDistance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ZOffset = { - name = "ZOffset", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Active = true, - Adornee = nil, - AlwaysOnTop = false, - AutoLocalize = true, - CanvasSize = Vector2.new(800, 600), - ClipsDescendants = false, - Enabled = true, - Face = 5, - LightInfluence = 0, - Localize = true, - Name = "SurfaceGui", - PixelsPerStud = 50, - ResetOnSpawn = true, - RootLocalizationTable = nil, - SizingMode = 0, - ToolPunchThroughDistance = 0, - ZIndexBehavior = 0, - ZOffset = 0, - }, - }, - SurfaceLight = { - name = "SurfaceLight", - superclass = "Light", - properties = { - Angle = { - name = "Angle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Face = { - name = "Face", - type = {type = "Enum", name = "NormalId"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Range = { - name = "Range", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Angle = 90, - Brightness = 1, - Color = Color3.new(1, 1, 1), - Enabled = true, - Face = 5, - Name = "SurfaceLight", - Range = 16, - Shadows = false, - }, - }, - SurfaceSelection = { - name = "SurfaceSelection", - superclass = "PartAdornment", - properties = { - TargetSurface = { - name = "TargetSurface", - type = {type = "Enum", name = "NormalId"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Adornee = nil, - Color = BrickColor.new(23), - Color3 = Color3.new(0.050980397, 0.41176474, 0.6745098), - Name = "SurfaceSelection", - TargetSurface = 0, - Transparency = 0, - Visible = true, - }, - }, - TaskScheduler = { - name = "TaskScheduler", - superclass = "Instance", - properties = { - SchedulerDutyCycle = { - name = "SchedulerDutyCycle", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - SchedulerRate = { - name = "SchedulerRate", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ThreadPoolConfig = { - name = "ThreadPoolConfig", - type = {type = "Enum", name = "ThreadPoolConfig"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ThreadPoolSize = { - name = "ThreadPoolSize", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - Team = { - name = "Team", - superclass = "Instance", - properties = { - AutoAssignable = { - name = "AutoAssignable", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AutoColorCharacters = { - name = "AutoColorCharacters", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - ChildOrder = { - name = "ChildOrder", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - Score = { - name = "Score", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - TeamColor = { - name = "TeamColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AutoAssignable = true, - AutoColorCharacters = true, - Name = "Team", - Score = 0, - TeamColor = BrickColor.new(1), - }, - }, - Teams = { - name = "Teams", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Teams", - }, - }, - TeleportAsyncResult = { - name = "TeleportAsyncResult", - superclass = "Instance", - properties = { - PrivateServerId = { - name = "PrivateServerId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ReservedServerAccessCode = { - name = "ReservedServerAccessCode", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - TeleportOptions = { - name = "TeleportOptions", - superclass = "Instance", - properties = { - ReservedServerAccessCode = { - name = "ReservedServerAccessCode", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ServerInstanceId = { - name = "ServerInstanceId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ShouldReserveServer = { - name = "ShouldReserveServer", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Instance", - ReservedServerAccessCode = "", - ServerInstanceId = "", - ShouldReserveServer = false, - }, - }, - TeleportService = { - name = "TeleportService", - superclass = "Instance", - properties = { - CustomizedTeleportUI = { - name = "CustomizedTeleportUI", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - CustomizedTeleportUI = false, - Name = "Teleport Service", - }, - }, - Terrain = { - name = "Terrain", - superclass = "BasePart", - properties = { - Decoration = { - name = "Decoration", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - IsSmooth = { - name = "IsSmooth", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - MaterialColors = { - name = "MaterialColors", - type = {type = "Data", name = "BinaryString"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - MaxExtents = { - name = "MaxExtents", - type = {type = "Unimplemented", name = "Region3int16"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - WaterColor = { - name = "WaterColor", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WaterReflectance = { - name = "WaterReflectance", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WaterTransparency = { - name = "WaterTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WaterWaveSize = { - name = "WaterWaveSize", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WaterWaveSpeed = { - name = "WaterWaveSpeed", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - TerrainRegion = { - name = "TerrainRegion", - superclass = "Instance", - properties = { - IsSmooth = { - name = "IsSmooth", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - SizeInCells = { - name = "SizeInCells", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - Name = "TerrainRegion", - }, - }, - TestService = { - name = "TestService", - superclass = "Instance", - properties = { - AutoRuns = { - name = "AutoRuns", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Description = { - name = "Description", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ErrorCount = { - name = "ErrorCount", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ExecuteWithStudioRun = { - name = "ExecuteWithStudioRun", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Is30FpsThrottleEnabled = { - name = "Is30FpsThrottleEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IsPhysicsEnvironmentalThrottled = { - name = "IsPhysicsEnvironmentalThrottled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IsSleepAllowed = { - name = "IsSleepAllowed", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - NumberOfPlayers = { - name = "NumberOfPlayers", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SimulateSecondsLag = { - name = "SimulateSecondsLag", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TestCount = { - name = "TestCount", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Timeout = { - name = "Timeout", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WarnCount = { - name = "WarnCount", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - AutoRuns = true, - Description = "", - ExecuteWithStudioRun = false, - Is30FpsThrottleEnabled = true, - IsPhysicsEnvironmentalThrottled = true, - IsSleepAllowed = true, - Name = "TestService", - NumberOfPlayers = 0, - SimulateSecondsLag = 0, - Timeout = 10, - }, - }, - TextBox = { - name = "TextBox", - superclass = "GuiObject", - properties = { - ClearTextOnFocus = { - name = "ClearTextOnFocus", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CursorPosition = { - name = "CursorPosition", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - EnableRealtimeFilteringHints = { - name = "EnableRealtimeFilteringHints", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - Font = { - name = "Font", - type = {type = "Enum", name = "Font"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FontSize = { - name = "FontSize", - type = {type = "Enum", name = "FontSize"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - LineHeight = { - name = "LineHeight", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ManualFocusRelease = { - name = "ManualFocusRelease", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - MultiLine = { - name = "MultiLine", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - OverlayNativeInput = { - name = "OverlayNativeInput", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - PlaceholderColor3 = { - name = "PlaceholderColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PlaceholderText = { - name = "PlaceholderText", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ReturnKeyType = { - name = "ReturnKeyType", - type = {type = "Enum", name = "ReturnKeyType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - RichText = { - name = "RichText", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SelectionStart = { - name = "SelectionStart", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - ShowNativeInput = { - name = "ShowNativeInput", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Text = { - name = "Text", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextBounds = { - name = "TextBounds", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TextColor = { - name = "TextColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - TextColor3 = { - name = "TextColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextEditable = { - name = "TextEditable", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextFits = { - name = "TextFits", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TextInputType = { - name = "TextInputType", - type = {type = "Enum", name = "TextInputType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - TextScaled = { - name = "TextScaled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextSize = { - name = "TextSize", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextStrokeColor3 = { - name = "TextStrokeColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextStrokeTransparency = { - name = "TextStrokeTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextTransparency = { - name = "TextTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextTruncate = { - name = "TextTruncate", - type = {type = "Enum", name = "TextTruncate"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextWrap = { - name = "TextWrap", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - TextWrapped = { - name = "TextWrapped", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextXAlignment = { - name = "TextXAlignment", - type = {type = "Enum", name = "TextXAlignment"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextYAlignment = { - name = "TextYAlignment", - type = {type = "Enum", name = "TextYAlignment"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Active = true, - AnchorPoint = Vector2.new(0, 0), - AutoLocalize = true, - AutomaticSize = 0, - BackgroundColor = BrickColor.new(194), - BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), - BackgroundTransparency = 0, - BorderColor = BrickColor.new(26), - BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), - BorderMode = 0, - BorderSizePixel = 1, - ClearTextOnFocus = true, - ClipsDescendants = false, - CursorPosition = 1, - Draggable = false, - Font = 0, - FontSize = 0, - LayoutOrder = 0, - LineHeight = 1, - Localize = true, - MultiLine = false, - Name = "TextBox", - NextSelectionDown = nil, - NextSelectionLeft = nil, - NextSelectionRight = nil, - NextSelectionUp = nil, - PlaceholderColor3 = Color3.new(0.7, 0.7, 0.7), - PlaceholderText = "", - Position = UDim2.new(0, 0, 0, 0), - RichText = false, - RootLocalizationTable = nil, - Rotation = 0, - Selectable = true, - SelectionImageObject = nil, - SelectionStart = -1, - ShowNativeInput = true, - Size = UDim2.new(0, 0, 0, 0), - SizeConstraint = 0, - Text = "TextBox", - TextColor = BrickColor.new(26), - TextColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), - TextEditable = true, - TextScaled = false, - TextSize = 8, - TextStrokeColor3 = Color3.new(0, 0, 0), - TextStrokeTransparency = 1, - TextTransparency = 0, - TextTruncate = 0, - TextWrap = false, - TextWrapped = false, - TextXAlignment = 2, - TextYAlignment = 1, - Transparency = 0, - Visible = true, - ZIndex = 1, - }, - }, - TextButton = { - name = "TextButton", - superclass = "GuiButton", - properties = { - Font = { - name = "Font", - type = {type = "Enum", name = "Font"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FontSize = { - name = "FontSize", - type = {type = "Enum", name = "FontSize"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - LineHeight = { - name = "LineHeight", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LocalizedText = { - name = "LocalizedText", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - RichText = { - name = "RichText", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Text = { - name = "Text", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextBounds = { - name = "TextBounds", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TextColor = { - name = "TextColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - TextColor3 = { - name = "TextColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextFits = { - name = "TextFits", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TextScaled = { - name = "TextScaled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextSize = { - name = "TextSize", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextStrokeColor3 = { - name = "TextStrokeColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextStrokeTransparency = { - name = "TextStrokeTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextTransparency = { - name = "TextTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextTruncate = { - name = "TextTruncate", - type = {type = "Enum", name = "TextTruncate"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextWrap = { - name = "TextWrap", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - TextWrapped = { - name = "TextWrapped", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextXAlignment = { - name = "TextXAlignment", - type = {type = "Enum", name = "TextXAlignment"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextYAlignment = { - name = "TextYAlignment", - type = {type = "Enum", name = "TextYAlignment"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Active = true, - AnchorPoint = Vector2.new(0, 0), - AutoButtonColor = true, - AutoLocalize = true, - AutomaticSize = 0, - BackgroundColor = BrickColor.new(194), - BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), - BackgroundTransparency = 0, - BorderColor = BrickColor.new(26), - BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), - BorderMode = 0, - BorderSizePixel = 1, - ClipsDescendants = false, - Draggable = false, - Font = 0, - FontSize = 0, - LayoutOrder = 0, - LineHeight = 1, - Localize = true, - Modal = false, - Name = "TextButton", - NextSelectionDown = nil, - NextSelectionLeft = nil, - NextSelectionRight = nil, - NextSelectionUp = nil, - Position = UDim2.new(0, 0, 0, 0), - RichText = false, - RootLocalizationTable = nil, - Rotation = 0, - Selectable = true, - Selected = false, - SelectionImageObject = nil, - Size = UDim2.new(0, 0, 0, 0), - SizeConstraint = 0, - Style = 0, - Text = "Button", - TextColor = BrickColor.new(26), - TextColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), - TextScaled = false, - TextSize = 8, - TextStrokeColor3 = Color3.new(0, 0, 0), - TextStrokeTransparency = 1, - TextTransparency = 0, - TextTruncate = 0, - TextWrap = false, - TextWrapped = false, - TextXAlignment = 2, - TextYAlignment = 1, - Transparency = 0, - Visible = true, - ZIndex = 1, - }, - }, - TextFilterResult = { - name = "TextFilterResult", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - TextLabel = { - name = "TextLabel", - superclass = "GuiLabel", - properties = { - Font = { - name = "Font", - type = {type = "Enum", name = "Font"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FontSize = { - name = "FontSize", - type = {type = "Enum", name = "FontSize"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - LineHeight = { - name = "LineHeight", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LocalizedText = { - name = "LocalizedText", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - RichText = { - name = "RichText", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Text = { - name = "Text", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextBounds = { - name = "TextBounds", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TextColor = { - name = "TextColor", - type = {type = "Data", name = "BrickColor"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - TextColor3 = { - name = "TextColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextFits = { - name = "TextFits", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TextScaled = { - name = "TextScaled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextSize = { - name = "TextSize", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextStrokeColor3 = { - name = "TextStrokeColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextStrokeTransparency = { - name = "TextStrokeTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextTransparency = { - name = "TextTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextTruncate = { - name = "TextTruncate", - type = {type = "Enum", name = "TextTruncate"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextWrap = { - name = "TextWrap", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - TextWrapped = { - name = "TextWrapped", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextXAlignment = { - name = "TextXAlignment", - type = {type = "Enum", name = "TextXAlignment"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextYAlignment = { - name = "TextYAlignment", - type = {type = "Enum", name = "TextYAlignment"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Active = false, - AnchorPoint = Vector2.new(0, 0), - AutoLocalize = true, - AutomaticSize = 0, - BackgroundColor = BrickColor.new(194), - BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), - BackgroundTransparency = 0, - BorderColor = BrickColor.new(26), - BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), - BorderMode = 0, - BorderSizePixel = 1, - ClipsDescendants = false, - Draggable = false, - Font = 0, - FontSize = 0, - LayoutOrder = 0, - LineHeight = 1, - Localize = true, - Name = "TextLabel", - NextSelectionDown = nil, - NextSelectionLeft = nil, - NextSelectionRight = nil, - NextSelectionUp = nil, - Position = UDim2.new(0, 0, 0, 0), - RichText = false, - RootLocalizationTable = nil, - Rotation = 0, - Selectable = false, - SelectionImageObject = nil, - Size = UDim2.new(0, 0, 0, 0), - SizeConstraint = 0, - Text = "Label", - TextColor = BrickColor.new(26), - TextColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), - TextScaled = false, - TextSize = 8, - TextStrokeColor3 = Color3.new(0, 0, 0), - TextStrokeTransparency = 1, - TextTransparency = 0, - TextTruncate = 0, - TextWrap = false, - TextWrapped = false, - TextXAlignment = 2, - TextYAlignment = 1, - Transparency = 0, - Visible = true, - ZIndex = 1, - }, - }, - TextService = { - name = "TextService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "TextService", - }, - }, - Texture = { - name = "Texture", - superclass = "Decal", - properties = { - OffsetStudsU = { - name = "OffsetStudsU", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - OffsetStudsV = { - name = "OffsetStudsV", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - StudsPerTileU = { - name = "StudsPerTileU", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - StudsPerTileV = { - name = "StudsPerTileV", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Color3 = Color3.new(1, 1, 1), - Face = 5, - LocalTransparencyModifier = 0, - Name = "Texture", - OffsetStudsU = 0, - OffsetStudsV = 0, - Shiny = 20, - Specular = 0, - StudsPerTileU = 2, - StudsPerTileV = 2, - Texture = "", - Transparency = 0, - }, - }, - ThirdPartyUserService = { - name = "ThirdPartyUserService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - TimerService = { - name = "TimerService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - Tool = { - name = "Tool", - superclass = "BackpackItem", - properties = { - CanBeDropped = { - name = "CanBeDropped", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Grip = { - name = "Grip", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GripForward = { - name = "GripForward", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - GripPos = { - name = "GripPos", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - GripRight = { - name = "GripRight", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - GripUp = { - name = "GripUp", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - ManualActivationOnly = { - name = "ManualActivationOnly", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RequiresHandle = { - name = "RequiresHandle", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ToolTip = { - name = "ToolTip", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - CanBeDropped = true, - Enabled = true, - Grip = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - GripForward = Vector3.new(0, 0, -1), - GripPos = Vector3.new(0, 0, 0), - GripRight = Vector3.new(1, 0, 0), - GripUp = Vector3.new(0, 1, 0), - ManualActivationOnly = false, - Name = "Tool", - RequiresHandle = true, - TextureId = "", - ToolTip = "", - }, - }, - Torque = { - name = "Torque", - superclass = "Constraint", - properties = { - RelativeTo = { - name = "RelativeTo", - type = {type = "Enum", name = "ActuatorRelativeTo"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Torque = { - name = "Torque", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Attachment0 = nil, - Attachment1 = nil, - Color = BrickColor.new(23), - Enabled = true, - Name = "Torque", - RelativeTo = 0, - Torque = Vector3.new(0, 0, 0), - Visible = false, - }, - }, - TotalCountTimeIntervalItem = { - name = "TotalCountTimeIntervalItem", - superclass = "StatsItem", - properties = { - }, - defaults = { - }, - }, - TouchInputService = { - name = "TouchInputService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "TouchInputService", - }, - }, - TouchTransmitter = { - name = "TouchTransmitter", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - TracerService = { - name = "TracerService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - Trail = { - name = "Trail", - superclass = "Instance", - properties = { - Attachment0 = { - name = "Attachment0", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Attachment1 = { - name = "Attachment1", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Color = { - name = "Color", - type = {type = "Data", name = "ColorSequence"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FaceCamera = { - name = "FaceCamera", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Lifetime = { - name = "Lifetime", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LightEmission = { - name = "LightEmission", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LightInfluence = { - name = "LightInfluence", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxLength = { - name = "MaxLength", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MinLength = { - name = "MinLength", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Texture = { - name = "Texture", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextureLength = { - name = "TextureLength", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TextureMode = { - name = "TextureMode", - type = {type = "Enum", name = "TextureMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Transparency = { - name = "Transparency", - type = {type = "Data", name = "NumberSequence"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - WidthScale = { - name = "WidthScale", - type = {type = "Data", name = "NumberSequence"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Attachment0 = nil, - Attachment1 = nil, - Color = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.new(1, 1, 1)), ColorSequenceKeypoint.new(1, Color3.new(1, 1, 1))}), - Enabled = true, - FaceCamera = false, - Lifetime = 2, - LightEmission = 0, - LightInfluence = 0, - MaxLength = 0, - MinLength = 0.1, - Name = "Trail", - Texture = "", - TextureLength = 1, - TextureMode = 0, - Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 0.5, 0), NumberSequenceKeypoint.new(1, 0.5, 0)}), - WidthScale = NumberSequence.new({NumberSequenceKeypoint.new(0, 1, 0), NumberSequenceKeypoint.new(1, 1, 0)}), - }, - }, - Translator = { - name = "Translator", - superclass = "Instance", - properties = { - LocaleId = { - name = "LocaleId", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - TremoloSoundEffect = { - name = "TremoloSoundEffect", - superclass = "SoundEffect", - properties = { - Depth = { - name = "Depth", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Duty = { - name = "Duty", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Frequency = { - name = "Frequency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Depth = 1, - Duty = 0.5, - Enabled = true, - Frequency = 5, - Name = "TremoloSoundEffect", - Priority = 0, - }, - }, - TriangleMeshPart = { - name = "TriangleMeshPart", - superclass = "BasePart", - properties = { - CollisionFidelity = { - name = "CollisionFidelity", - type = {type = "Enum", name = "CollisionFidelity"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - }, - }, - TrussPart = { - name = "TrussPart", - superclass = "BasePart", - properties = { - Style = { - name = "Style", - type = {type = "Enum", name = "Style"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - Anchored = false, - AssemblyAngularVelocity = Vector3.new(0, 0, 0), - AssemblyLinearVelocity = Vector3.new(0, 0, 0), - BackParamA = -0.5, - BackParamB = 0.5, - BackSurface = 5, - BackSurfaceInput = 0, - BottomParamA = -0.5, - BottomParamB = 0.5, - BottomSurface = 5, - BottomSurfaceInput = 0, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CanCollide = true, - CanTouch = true, - CastShadow = true, - CollisionGroupId = 0, - Color = Color3.new(0.6392157, 0.63529414, 0.64705884), - CustomPhysicalProperties = nil, - Elasticity = 0.5, - Friction = 0.3, - FrontParamA = -0.5, - FrontParamB = 0.5, - FrontSurface = 5, - FrontSurfaceInput = 0, - LeftParamA = -0.5, - LeftParamB = 0.5, - LeftSurface = 5, - LeftSurfaceInput = 0, - LocalTransparencyModifier = 0, - Locked = false, - Massless = false, - Material = 256, - Name = "Truss", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Reflectance = 0, - RightParamA = -0.5, - RightParamB = 0.5, - RightSurface = 5, - RightSurfaceInput = 0, - RootPriority = 0, - RotVelocity = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - Size = Vector3.new(2, 2, 2), - Style = 0, - TopParamA = -0.5, - TopParamB = 0.5, - TopSurface = 5, - TopSurfaceInput = 0, - Transparency = 0, - Velocity = Vector3.new(0, 0, 0), - }, - }, - Tween = { - name = "Tween", - superclass = "TweenBase", - properties = { - Instance = { - name = "Instance", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TweenInfo = { - name = "TweenInfo", - type = {type = "Unimplemented", name = "TweenInfo"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - Name = "Tween", - }, - }, - TweenBase = { - name = "TweenBase", - superclass = "Instance", - properties = { - PlaybackState = { - name = "PlaybackState", - type = {type = "Enum", name = "PlaybackState"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - }, - }, - TweenService = { - name = "TweenService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "TweenService", - }, - }, - UGCValidationService = { - name = "UGCValidationService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "UGCValidationService", - }, - }, - UIAspectRatioConstraint = { - name = "UIAspectRatioConstraint", - superclass = "UIConstraint", - properties = { - AspectRatio = { - name = "AspectRatio", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - AspectType = { - name = "AspectType", - type = {type = "Enum", name = "AspectType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DominantAxis = { - name = "DominantAxis", - type = {type = "Enum", name = "DominantAxis"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - AspectRatio = 1, - AspectType = 0, - DominantAxis = 0, - Name = "UIAspectRatioConstraint", - }, - }, - UIBase = { - name = "UIBase", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - UIComponent = { - name = "UIComponent", - superclass = "UIBase", - properties = { - }, - defaults = { - }, - }, - UIConstraint = { - name = "UIConstraint", - superclass = "UIComponent", - properties = { - }, - defaults = { - }, - }, - UICorner = { - name = "UICorner", - superclass = "UIComponent", - properties = { - CornerRadius = { - name = "CornerRadius", - type = {type = "Data", name = "UDim"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - CornerRadius = UDim.new(0, 8), - Name = "UICorner", - }, - }, - UIGradient = { - name = "UIGradient", - superclass = "UIComponent", - properties = { - Color = { - name = "Color", - type = {type = "Data", name = "ColorSequence"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Offset = { - name = "Offset", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Rotation = { - name = "Rotation", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Transparency = { - name = "Transparency", - type = {type = "Data", name = "NumberSequence"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Color = ColorSequence.new({ColorSequenceKeypoint.new(0, Color3.new(1, 1, 1)), ColorSequenceKeypoint.new(1, Color3.new(1, 1, 1))}), - Enabled = true, - Name = "UIGradient", - Offset = Vector2.new(0, 0), - Rotation = 0, - Transparency = NumberSequence.new({NumberSequenceKeypoint.new(0, 0, 0), NumberSequenceKeypoint.new(1, 0, 0)}), - }, - }, - UIGridLayout = { - name = "UIGridLayout", - superclass = "UIGridStyleLayout", - properties = { - AbsoluteCellCount = { - name = "AbsoluteCellCount", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - AbsoluteCellSize = { - name = "AbsoluteCellSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - CellPadding = { - name = "CellPadding", - type = {type = "Data", name = "UDim2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CellSize = { - name = "CellSize", - type = {type = "Data", name = "UDim2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FillDirectionMaxCells = { - name = "FillDirectionMaxCells", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - StartCorner = { - name = "StartCorner", - type = {type = "Enum", name = "StartCorner"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - CellPadding = UDim2.new(0, 5, 0, 5), - CellSize = UDim2.new(0, 100, 0, 100), - FillDirection = 0, - FillDirectionMaxCells = 0, - HorizontalAlignment = 1, - Name = "UIGridLayout", - SortOrder = 0, - StartCorner = 0, - VerticalAlignment = 1, - }, - }, - UIGridStyleLayout = { - name = "UIGridStyleLayout", - superclass = "UILayout", - properties = { - AbsoluteContentSize = { - name = "AbsoluteContentSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - FillDirection = { - name = "FillDirection", - type = {type = "Enum", name = "FillDirection"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HorizontalAlignment = { - name = "HorizontalAlignment", - type = {type = "Enum", name = "HorizontalAlignment"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SortOrder = { - name = "SortOrder", - type = {type = "Enum", name = "SortOrder"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - VerticalAlignment = { - name = "VerticalAlignment", - type = {type = "Enum", name = "VerticalAlignment"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - UILayout = { - name = "UILayout", - superclass = "UIComponent", - properties = { - }, - defaults = { - }, - }, - UIListLayout = { - name = "UIListLayout", - superclass = "UIGridStyleLayout", - properties = { - Padding = { - name = "Padding", - type = {type = "Data", name = "UDim"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - FillDirection = 1, - HorizontalAlignment = 1, - Name = "UIListLayout", - Padding = UDim.new(0, 0), - SortOrder = 0, - VerticalAlignment = 1, - }, - }, - UIPadding = { - name = "UIPadding", - superclass = "UIComponent", - properties = { - PaddingBottom = { - name = "PaddingBottom", - type = {type = "Data", name = "UDim"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PaddingLeft = { - name = "PaddingLeft", - type = {type = "Data", name = "UDim"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PaddingRight = { - name = "PaddingRight", - type = {type = "Data", name = "UDim"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - PaddingTop = { - name = "PaddingTop", - type = {type = "Data", name = "UDim"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "UIPadding", - PaddingBottom = UDim.new(0, 0), - PaddingLeft = UDim.new(0, 0), - PaddingRight = UDim.new(0, 0), - PaddingTop = UDim.new(0, 0), - }, - }, - UIPageLayout = { - name = "UIPageLayout", - superclass = "UIGridStyleLayout", - properties = { - Animated = { - name = "Animated", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Circular = { - name = "Circular", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CurrentPage = { - name = "CurrentPage", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - EasingDirection = { - name = "EasingDirection", - type = {type = "Enum", name = "EasingDirection"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - EasingStyle = { - name = "EasingStyle", - type = {type = "Enum", name = "EasingStyle"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GamepadInputEnabled = { - name = "GamepadInputEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Padding = { - name = "Padding", - type = {type = "Data", name = "UDim"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ScrollWheelInputEnabled = { - name = "ScrollWheelInputEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TouchInputEnabled = { - name = "TouchInputEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TweenTime = { - name = "TweenTime", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Animated = true, - Circular = false, - EasingDirection = 1, - EasingStyle = 2, - FillDirection = 0, - GamepadInputEnabled = true, - HorizontalAlignment = 1, - Name = "UIPageLayout", - Padding = UDim.new(0, 0), - ScrollWheelInputEnabled = true, - SortOrder = 0, - TouchInputEnabled = true, - TweenTime = 1, - VerticalAlignment = 1, - }, - }, - UIScale = { - name = "UIScale", - superclass = "UIComponent", - properties = { - Scale = { - name = "Scale", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "UIScale", - Scale = 1, - }, - }, - UISizeConstraint = { - name = "UISizeConstraint", - superclass = "UIConstraint", - properties = { - MaxSize = { - name = "MaxSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MinSize = { - name = "MinSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - MaxSize = Vector2.new(1000000000, 1000000000), - MinSize = Vector2.new(0, 0), - Name = "UISizeConstraint", - }, - }, - UITableLayout = { - name = "UITableLayout", - superclass = "UIGridStyleLayout", - properties = { - FillEmptySpaceColumns = { - name = "FillEmptySpaceColumns", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FillEmptySpaceRows = { - name = "FillEmptySpaceRows", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MajorAxis = { - name = "MajorAxis", - type = {type = "Enum", name = "TableMajorAxis"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Padding = { - name = "Padding", - type = {type = "Data", name = "UDim2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - FillDirection = 1, - FillEmptySpaceColumns = false, - FillEmptySpaceRows = false, - HorizontalAlignment = 1, - MajorAxis = 0, - Name = "UITableLayout", - Padding = UDim2.new(0, 0, 0, 0), - SortOrder = 0, - VerticalAlignment = 1, - }, - }, - UITextSizeConstraint = { - name = "UITextSizeConstraint", - superclass = "UIConstraint", - properties = { - MaxTextSize = { - name = "MaxTextSize", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MinTextSize = { - name = "MinTextSize", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - MaxTextSize = 100, - MinTextSize = 1, - Name = "UITextSizeConstraint", - }, - }, - UnionOperation = { - name = "UnionOperation", - superclass = "PartOperation", - properties = { - }, - defaults = { - Anchored = false, - AssemblyAngularVelocity = Vector3.new(0, 0, 0), - AssemblyLinearVelocity = Vector3.new(0, 0, 0), - BackParamA = -0.5, - BackParamB = 0.5, - BackSurface = 0, - BackSurfaceInput = 0, - BottomParamA = -0.5, - BottomParamB = 0.5, - BottomSurface = 0, - BottomSurfaceInput = 0, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CanCollide = true, - CanTouch = true, - CastShadow = true, - CollisionFidelity = 2, - CollisionGroupId = 0, - Color = Color3.new(1, 1, 1), - CustomPhysicalProperties = nil, - Elasticity = 0.5, - Friction = 0.3, - FrontParamA = -0.5, - FrontParamB = 0.5, - FrontSurface = 0, - FrontSurfaceInput = 0, - LeftParamA = -0.5, - LeftParamB = 0.5, - LeftSurface = 0, - LeftSurfaceInput = 0, - LocalTransparencyModifier = 0, - Locked = false, - Massless = false, - Material = 256, - Name = "Union", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Reflectance = 0, - RenderFidelity = 1, - RightParamA = -0.5, - RightParamB = 0.5, - RightSurface = 0, - RightSurfaceInput = 0, - RootPriority = 0, - RotVelocity = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - Size = Vector3.new(4, 1.2, 2), - SmoothingAngle = 0, - TopParamA = -0.5, - TopParamB = 0.5, - TopSurface = 0, - TopSurfaceInput = 0, - Transparency = 0, - UsePartColor = false, - Velocity = Vector3.new(0, 0, 0), - }, - }, - UnvalidatedAssetService = { - name = "UnvalidatedAssetService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - UserGameSettings = { - name = "UserGameSettings", - superclass = "Instance", - properties = { - AllTutorialsDisabled = { - name = "AllTutorialsDisabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CameraMode = { - name = "CameraMode", - type = {type = "Enum", name = "CustomCameraMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CameraYInverted = { - name = "CameraYInverted", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ChatVisible = { - name = "ChatVisible", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ComputerCameraMovementMode = { - name = "ComputerCameraMovementMode", - type = {type = "Enum", name = "ComputerCameraMovementMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ComputerMovementMode = { - name = "ComputerMovementMode", - type = {type = "Enum", name = "ComputerMovementMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ControlMode = { - name = "ControlMode", - type = {type = "Enum", name = "ControlMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Fullscreen = { - name = "Fullscreen", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GamepadCameraSensitivity = { - name = "GamepadCameraSensitivity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - GraphicsQualityLevel = { - name = "GraphicsQualityLevel", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HasEverUsedVR = { - name = "HasEverUsedVR", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - IsUsingCameraYInverted = { - name = "IsUsingCameraYInverted", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - IsUsingGamepadCameraSensitivity = { - name = "IsUsingGamepadCameraSensitivity", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - MasterVolume = { - name = "MasterVolume", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MicroProfilerWebServerEnabled = { - name = "MicroProfilerWebServerEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MicroProfilerWebServerIP = { - name = "MicroProfilerWebServerIP", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - MicroProfilerWebServerPort = { - name = "MicroProfilerWebServerPort", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - MouseSensitivity = { - name = "MouseSensitivity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MouseSensitivityFirstPerson = { - name = "MouseSensitivityFirstPerson", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MouseSensitivityThirdPerson = { - name = "MouseSensitivityThirdPerson", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - OnScreenProfilerEnabled = { - name = "OnScreenProfilerEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - OnboardingsCompleted = { - name = "OnboardingsCompleted", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - PerformanceStatsVisible = { - name = "PerformanceStatsVisible", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RCCProfilerRecordFrameRate = { - name = "RCCProfilerRecordFrameRate", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RCCProfilerRecordTimeFrame = { - name = "RCCProfilerRecordTimeFrame", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RotationType = { - name = "RotationType", - type = {type = "Enum", name = "RotationType"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - SavedQualityLevel = { - name = "SavedQualityLevel", - type = {type = "Enum", name = "SavedQualitySetting"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - StartMaximized = { - name = "StartMaximized", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - StartScreenPosition = { - name = "StartScreenPosition", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - StartScreenSize = { - name = "StartScreenSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - TouchCameraMovementMode = { - name = "TouchCameraMovementMode", - type = {type = "Enum", name = "TouchCameraMovementMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TouchMovementMode = { - name = "TouchMovementMode", - type = {type = "Enum", name = "TouchMovementMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UsedCoreGuiIsVisibleToggle = { - name = "UsedCoreGuiIsVisibleToggle", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UsedCustomGuiIsVisibleToggle = { - name = "UsedCustomGuiIsVisibleToggle", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - UsedHideHudShortcut = { - name = "UsedHideHudShortcut", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - VREnabled = { - name = "VREnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - VRRotationIntensity = { - name = "VRRotationIntensity", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - }, - }, - UserInputService = { - name = "UserInputService", - superclass = "Instance", - properties = { - AccelerometerEnabled = { - name = "AccelerometerEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - BottomBarSize = { - name = "BottomBarSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - GamepadEnabled = { - name = "GamepadEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - GazeSelectionEnabled = { - name = "GazeSelectionEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - GyroscopeEnabled = { - name = "GyroscopeEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - KeyboardEnabled = { - name = "KeyboardEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - LegacyInputEventsEnabled = { - name = "LegacyInputEventsEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - ModalEnabled = { - name = "ModalEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - MouseBehavior = { - name = "MouseBehavior", - type = {type = "Enum", name = "MouseBehavior"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MouseDeltaSensitivity = { - name = "MouseDeltaSensitivity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - MouseEnabled = { - name = "MouseEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - MouseIconEnabled = { - name = "MouseIconEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - NavBarSize = { - name = "NavBarSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - OnScreenKeyboardAnimationDuration = { - name = "OnScreenKeyboardAnimationDuration", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - OnScreenKeyboardPosition = { - name = "OnScreenKeyboardPosition", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - OnScreenKeyboardSize = { - name = "OnScreenKeyboardSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - OnScreenKeyboardVisible = { - name = "OnScreenKeyboardVisible", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - OverrideMouseIconBehavior = { - name = "OverrideMouseIconBehavior", - type = {type = "Enum", name = "OverrideMouseIconBehavior"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - RightBarSize = { - name = "RightBarSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - StatusBarSize = { - name = "StatusBarSize", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TouchEnabled = { - name = "TouchEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - UserHeadCFrame = { - name = "UserHeadCFrame", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - VREnabled = { - name = "VREnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - ModalEnabled = false, - MouseBehavior = 0, - MouseDeltaSensitivity = 1, - MouseIconEnabled = true, - Name = "Instance", - }, - }, - UserService = { - name = "UserService", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "UserService", - }, - }, - UserSettings = { - name = "UserSettings", - superclass = "GenericSettings", - properties = { - }, - defaults = { - }, - }, - UserStorageService = { - name = "UserStorageService", - superclass = "LocalStorageService", - properties = { - }, - defaults = { - }, - }, - VRService = { - name = "VRService", - superclass = "Instance", - properties = { - GuiInputUserCFrame = { - name = "GuiInputUserCFrame", - type = {type = "Enum", name = "UserCFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - VRDeviceName = { - name = "VRDeviceName", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - VREnabled = { - name = "VREnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - }, - defaults = { - GuiInputUserCFrame = 0, - Name = "VRService", - }, - }, - ValueBase = { - name = "ValueBase", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - Vector3Value = { - name = "Vector3Value", - superclass = "ValueBase", - properties = { - Value = { - name = "Value", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Name = "Value", - Value = Vector3.new(0, 0, 0), - }, - }, - VectorForce = { - name = "VectorForce", - superclass = "Constraint", - properties = { - ApplyAtCenterOfMass = { - name = "ApplyAtCenterOfMass", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Force = { - name = "Force", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - RelativeTo = { - name = "RelativeTo", - type = {type = "Enum", name = "ActuatorRelativeTo"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - ApplyAtCenterOfMass = false, - Attachment0 = nil, - Attachment1 = nil, - Color = BrickColor.new(23), - Enabled = true, - Force = Vector3.new(1000, 0, 0), - Name = "VectorForce", - RelativeTo = 0, - Visible = false, - }, - }, - VehicleController = { - name = "VehicleController", - superclass = "Controller", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - VehicleSeat = { - name = "VehicleSeat", - superclass = "BasePart", - properties = { - AreHingesDetected = { - name = "AreHingesDetected", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Disabled = { - name = "Disabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - HeadsUpDisplay = { - name = "HeadsUpDisplay", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxSpeed = { - name = "MaxSpeed", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Occupant = { - name = "Occupant", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Steer = { - name = "Steer", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - SteerFloat = { - name = "SteerFloat", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Throttle = { - name = "Throttle", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ThrottleFloat = { - name = "ThrottleFloat", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Torque = { - name = "Torque", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - TurnSpeed = { - name = "TurnSpeed", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Anchored = false, - AssemblyAngularVelocity = Vector3.new(0, 0, 0), - AssemblyLinearVelocity = Vector3.new(0, 0, 0), - BackParamA = -0.5, - BackParamB = 0.5, - BackSurface = 0, - BackSurfaceInput = 0, - BottomParamA = -0.5, - BottomParamB = 0.5, - BottomSurface = 4, - BottomSurfaceInput = 0, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CanCollide = true, - CanTouch = true, - CastShadow = true, - CollisionGroupId = 0, - Color = Color3.new(0.6392157, 0.63529414, 0.64705884), - CustomPhysicalProperties = nil, - Disabled = false, - Elasticity = 0.5, - Friction = 0.3, - FrontParamA = -0.5, - FrontParamB = 0.5, - FrontSurface = 0, - FrontSurfaceInput = 0, - HeadsUpDisplay = true, - LeftParamA = -0.5, - LeftParamB = 0.5, - LeftSurface = 0, - LeftSurfaceInput = 0, - LocalTransparencyModifier = 0, - Locked = false, - Massless = false, - Material = 256, - MaxSpeed = 25, - Name = "VehicleSeat", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Reflectance = 0, - RightParamA = -0.5, - RightParamB = 0.5, - RightSurface = 0, - RightSurfaceInput = 0, - RootPriority = 0, - RotVelocity = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - Size = Vector3.new(4, 1.2, 2), - Steer = 0, - SteerFloat = 0, - Throttle = 0, - ThrottleFloat = 0, - TopParamA = -0.5, - TopParamB = 0.5, - TopSurface = 3, - TopSurfaceInput = 0, - Torque = 10, - Transparency = 0, - TurnSpeed = 1, - Velocity = Vector3.new(0, 0, 0), - }, - }, - VelocityMotor = { - name = "VelocityMotor", - superclass = "JointInstance", - properties = { - CurrentAngle = { - name = "CurrentAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DesiredAngle = { - name = "DesiredAngle", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Hole = { - name = "Hole", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MaxVelocity = { - name = "MaxVelocity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CurrentAngle = 0, - DesiredAngle = 0, - Enabled = true, - Hole = nil, - MaxVelocity = 0, - Name = "VelocityMotor", - Part0 = nil, - Part1 = nil, - }, - }, - VersionControlService = { - name = "VersionControlService", - superclass = "Instance", - properties = { - }, - defaults = { - }, - }, - VideoFrame = { - name = "VideoFrame", - superclass = "GuiObject", - properties = { - IsLoaded = { - name = "IsLoaded", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Looped = { - name = "Looped", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Playing = { - name = "Playing", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Resolution = { - name = "Resolution", - type = {type = "Data", name = "Vector2"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TimeLength = { - name = "TimeLength", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TimePosition = { - name = "TimePosition", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Video = { - name = "Video", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Volume = { - name = "Volume", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Active = false, - AnchorPoint = Vector2.new(0, 0), - AutoLocalize = true, - AutomaticSize = 0, - BackgroundColor = BrickColor.new(194), - BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), - BackgroundTransparency = 0, - BorderColor = BrickColor.new(26), - BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), - BorderMode = 0, - BorderSizePixel = 1, - ClipsDescendants = false, - Draggable = false, - LayoutOrder = 0, - Localize = true, - Looped = false, - Name = "VideoFrame", - NextSelectionDown = nil, - NextSelectionLeft = nil, - NextSelectionRight = nil, - NextSelectionUp = nil, - Playing = false, - Position = UDim2.new(0, 0, 0, 0), - RootLocalizationTable = nil, - Rotation = 0, - Selectable = false, - SelectionImageObject = nil, - Size = UDim2.new(0, 0, 0, 0), - SizeConstraint = 0, - TimePosition = 0, - Transparency = 0, - Video = "", - Visible = true, - Volume = 1, - ZIndex = 1, - }, - }, - ViewportFrame = { - name = "ViewportFrame", - superclass = "GuiObject", - properties = { - Ambient = { - name = "Ambient", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CurrentCamera = { - name = "CurrentCamera", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - ImageColor3 = { - name = "ImageColor3", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ImageTransparency = { - name = "ImageTransparency", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LightColor = { - name = "LightColor", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - LightDirection = { - name = "LightDirection", - type = {type = "Data", name = "Vector3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - Active = false, - Ambient = Color3.new(0.78431374, 0.78431374, 0.78431374), - AnchorPoint = Vector2.new(0, 0), - AutoLocalize = true, - AutomaticSize = 0, - BackgroundColor = BrickColor.new(194), - BackgroundColor3 = Color3.new(0.6392157, 0.63529414, 0.64705884), - BackgroundTransparency = 0, - BorderColor = BrickColor.new(26), - BorderColor3 = Color3.new(0.10588236, 0.16470589, 0.20784315), - BorderMode = 0, - BorderSizePixel = 1, - ClipsDescendants = false, - CurrentCamera = nil, - Draggable = false, - ImageColor3 = Color3.new(1, 1, 1), - ImageTransparency = 0, - LayoutOrder = 0, - LightColor = Color3.new(0.54901963, 0.54901963, 0.54901963), - LightDirection = Vector3.new(-1, -1, -1), - Localize = true, - Name = "ViewportFrame", - NextSelectionDown = nil, - NextSelectionLeft = nil, - NextSelectionRight = nil, - NextSelectionUp = nil, - Position = UDim2.new(0, 0, 0, 0), - RootLocalizationTable = nil, - Rotation = 0, - Selectable = false, - SelectionImageObject = nil, - Size = UDim2.new(0, 0, 0, 0), - SizeConstraint = 0, - Transparency = 0, - Visible = true, - ZIndex = 1, - }, - }, - VirtualInputManager = { - name = "VirtualInputManager", - superclass = "Instance", - properties = { - AdditionalLuaState = { - name = "AdditionalLuaState", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - }, - defaults = { - Name = "VirtualInputManager", - }, - }, - VirtualUser = { - name = "VirtualUser", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Instance", - }, - }, - Visit = { - name = "Visit", - superclass = "Instance", - properties = { - }, - defaults = { - Name = "Visit", - }, - }, - WedgePart = { - name = "WedgePart", - superclass = "FormFactorPart", - properties = { - }, - defaults = { - Anchored = false, - AssemblyAngularVelocity = Vector3.new(0, 0, 0), - AssemblyLinearVelocity = Vector3.new(0, 0, 0), - BackParamA = -0.5, - BackParamB = 0.5, - BackSurface = 0, - BackSurfaceInput = 0, - BottomParamA = -0.5, - BottomParamB = 0.5, - BottomSurface = 4, - BottomSurfaceInput = 0, - CFrame = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CanCollide = true, - CanTouch = true, - CastShadow = true, - CollisionGroupId = 0, - Color = Color3.new(0.6392157, 0.63529414, 0.64705884), - CustomPhysicalProperties = nil, - Elasticity = 0.5, - FormFactor = 1, - Friction = 0.3, - FrontParamA = -0.5, - FrontParamB = 0.5, - FrontSurface = 0, - FrontSurfaceInput = 0, - LeftParamA = -0.5, - LeftParamB = 0.5, - LeftSurface = 0, - LeftSurfaceInput = 0, - LocalTransparencyModifier = 0, - Locked = false, - Massless = false, - Material = 256, - Name = "Wedge", - Orientation = Vector3.new(0, 0, 0), - Position = Vector3.new(0, 0, 0), - Reflectance = 0, - RightParamA = -0.5, - RightParamB = 0.5, - RightSurface = 0, - RightSurfaceInput = 0, - RootPriority = 0, - RotVelocity = Vector3.new(0, 0, 0), - Rotation = Vector3.new(0, 0, 0), - Size = Vector3.new(4, 1.2, 2), - TopParamA = -0.5, - TopParamB = 0.5, - TopSurface = 0, - TopSurfaceInput = 0, - Transparency = 0, - Velocity = Vector3.new(0, 0, 0), - }, - }, - Weld = { - name = "Weld", - superclass = "JointInstance", - properties = { - }, - defaults = { - C0 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - C1 = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Enabled = true, - Name = "Weld", - Part0 = nil, - Part1 = nil, - }, - }, - WeldConstraint = { - name = "WeldConstraint", - superclass = "Instance", - properties = { - Active = { - name = "Active", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Part0 = { - name = "Part0", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - Part1 = { - name = "Part1", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = false, - }, - }, - defaults = { - Enabled = true, - Name = "WeldConstraint", - Part0 = nil, - Part1 = nil, - }, - }, - Workspace = { - name = "Workspace", - superclass = "WorldRoot", - properties = { - AllowThirdPartySales = { - name = "AllowThirdPartySales", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - CollisionGroups = { - name = "CollisionGroups", - type = {type = "Data", name = "String"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - CurrentCamera = { - name = "CurrentCamera", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - DistributedGameTime = { - name = "DistributedGameTime", - type = {type = "Data", name = "Float64"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FallenPartsDestroyHeight = { - name = "FallenPartsDestroyHeight", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - FilteringEnabled = { - name = "FilteringEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Gravity = { - name = "Gravity", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - InterpolationThrottling = { - name = "InterpolationThrottling", - type = {type = "Enum", name = "InterpolationThrottlingMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - MeshPartHeads = { - name = "MeshPartHeads", - type = {type = "Enum", name = "MeshPartHeads"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - PhysicsSimulationRate = { - name = "PhysicsSimulationRate", - type = {type = "Enum", name = "PhysicsSimulationRate"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - StreamingEnabled = { - name = "StreamingEnabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - StreamingMinRadius = { - name = "StreamingMinRadius", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - StreamingPauseMode = { - name = "StreamingPauseMode", - type = {type = "Enum", name = "StreamingPauseMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - StreamingTargetRadius = { - name = "StreamingTargetRadius", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - Terrain = { - name = "Terrain", - type = {type = "Data", name = "Ref"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - TouchesUseCollisionGroups = { - name = "TouchesUseCollisionGroups", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = true, - }, - }, - defaults = { - AllowThirdPartySales = false, - CurrentCamera = nil, - DistributedGameTime = 0, - FallenPartsDestroyHeight = -500, - FilteringEnabled = false, - Gravity = 196.2, - InterpolationThrottling = 0, - LevelOfDetail = 0, - Name = "Workspace", - PrimaryPart = nil, - StreamingEnabled = false, - }, - }, - WorldModel = { - name = "WorldModel", - superclass = "WorldRoot", - properties = { - }, - defaults = { - LevelOfDetail = 0, - Name = "WorldModel", - PrimaryPart = nil, - }, - }, - WorldRoot = { - name = "WorldRoot", - superclass = "Model", - properties = { - }, - defaults = { - }, - }, - WrapLayer = { - name = "WrapLayer", - superclass = "BaseWrap", - properties = { - BindOffset = { - name = "BindOffset", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Color = { - name = "Color", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - DebugMode = { - name = "DebugMode", - type = {type = "Enum", name = "WrapLayerDebugMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - Enabled = { - name = "Enabled", - type = {type = "Data", name = "Bool"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Order = { - name = "Order", - type = {type = "Data", name = "Int32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - Puffiness = { - name = "Puffiness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ReferenceMeshId = { - name = "ReferenceMeshId", - type = {type = "Data", name = "Content"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ReferenceOrigin = { - name = "ReferenceOrigin", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - ReferenceOriginWorld = { - name = "ReferenceOriginWorld", - type = {type = "Data", name = "CFrame"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "Read", - serializes = false, - }, - ShrinkFactor = { - name = "ShrinkFactor", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - BindOffset = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - CageMeshId = "", - CageOrigin = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Enabled = true, - ImportOrigin = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Name = "WrapLayer", - Order = 1, - Puffiness = 1, - ReferenceMeshId = "", - ReferenceOrigin = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - ShrinkFactor = 0, - }, - }, - WrapTarget = { - name = "WrapTarget", - superclass = "BaseWrap", - properties = { - Color = { - name = "Color", - type = {type = "Data", name = "Color3"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - DebugMode = { - name = "DebugMode", - type = {type = "Enum", name = "WrapTargetDebugMode"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "None", - serializes = false, - }, - Stiffness = { - name = "Stiffness", - type = {type = "Data", name = "Float32"}, - isCanonical = true, - canonicalName = nil, - serializedName = nil, - scriptability = "ReadWrite", - serializes = true, - }, - }, - defaults = { - CageMeshId = "", - CageOrigin = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - ImportOrigin = CFrame.new(0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1), - Name = "WrapTarget", - Stiffness = 0.9, - }, - }, -} diff --git a/plugin/rbx_dom_lua/src/ReflectionDatabase/init.lua b/plugin/rbx_dom_lua/src/ReflectionDatabase/init.lua deleted file mode 100644 index bf1096e6..00000000 --- a/plugin/rbx_dom_lua/src/ReflectionDatabase/init.lua +++ /dev/null @@ -1,3 +0,0 @@ -return { - classes = require(script.classes) -} \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/allValues.json b/plugin/rbx_dom_lua/src/allValues.json new file mode 100644 index 00000000..b0d131d9 --- /dev/null +++ b/plugin/rbx_dom_lua/src/allValues.json @@ -0,0 +1,338 @@ +{ + "Color3uint8": { + "value": { + "Type": "Color3uint8", + "Value": [ + 0, + 128, + 255 + ] + }, + "ty": "Color3uint8" + }, + "Bool": { + "value": { + "Type": "Bool", + "Value": true + }, + "ty": "Bool" + }, + "BinaryString": { + "value": { + "Type": "BinaryString", + "Value": "SGVsbG8h" + }, + "ty": "BinaryString" + }, + "BrickColor": { + "value": { + "Type": "BrickColor", + "Value": 1004 + }, + "ty": "BrickColor" + }, + "Vector3": { + "value": { + "Type": "Vector3", + "Value": [ + -300.0, + 0.0, + 1500.0 + ] + }, + "ty": "Vector3" + }, + "String": { + "value": { + "Type": "String", + "Value": "Hello, world!" + }, + "ty": "String" + }, + "NumberRange": { + "value": { + "Type": "NumberRange", + "Value": [ + -36.0, + 94.0 + ] + }, + "ty": "NumberRange" + }, + "Int64": { + "value": { + "Type": "Int64", + "Value": 23491023 + }, + "ty": "Int64" + }, + "Vector3int16": { + "value": { + "Type": "Vector3int16", + "Value": [ + 60, + 37, + -450 + ] + }, + "ty": "Vector3int16" + }, + "Float32": { + "value": { + "Type": "Float32", + "Value": 15.0 + }, + "ty": "Float32" + }, + "NumberSequence": { + "value": { + "Type": "NumberSequence", + "Value": { + "Keypoints": [ + { + "Time": 0.0, + "Value": 5.0, + "Envelope": 2.0 + }, + { + "Time": 1.0, + "Value": 22.0, + "Envelope": 0.0 + } + ] + } + }, + "ty": "NumberSequence" + }, + "ColorSequence": { + "value": { + "Type": "ColorSequence", + "Value": { + "Keypoints": [ + { + "Time": 0.0, + "Color": [ + 1.0, + 1.0, + 0.5 + ] + }, + { + "Time": 1.0, + "Color": [ + 0.0, + 0.0, + 0.0 + ] + } + ] + } + }, + "ty": "ColorSequence" + }, + "Ray": { + "value": { + "Type": "Ray", + "Value": { + "Origin": [ + 1.0, + 2.0, + 3.0 + ], + "Direction": [ + 4.0, + 5.0, + 6.0 + ] + } + }, + "ty": "Ray" + }, + "Int32": { + "value": { + "Type": "Int32", + "Value": 6014 + }, + "ty": "Int32" + }, + "Axes": { + "value": { + "Type": "Axes", + "Value": [ + "X", + "Y", + "Z" + ] + }, + "ty": "Axes" + }, + "Enum": { + "value": { + "Type": "Enum", + "Value": 1234 + }, + "ty": "Enum" + }, + "Faces": { + "value": { + "Type": "Faces", + "Value": [ + "Right", + "Top", + "Back", + "Left", + "Bottom", + "Front" + ] + }, + "ty": "Faces" + }, + "UDim": { + "value": { + "Type": "UDim", + "Value": [ + 1.0, + 32 + ] + }, + "ty": "UDim" + }, + "Vector2": { + "value": { + "Type": "Vector2", + "Value": [ + -50.0, + 50.0 + ] + }, + "ty": "Vector2" + }, + "Color3": { + "value": { + "Type": "Color3", + "Value": [ + 1.0, + 2.0, + 3.0 + ] + }, + "ty": "Color3" + }, + "Float64": { + "value": { + "Type": "Float64", + "Value": 15123.0 + }, + "ty": "Float64" + }, + "UDim2": { + "value": { + "Type": "UDim2", + "Value": [ + [ + -1.0, + 100 + ], + [ + 1.0, + -100 + ] + ] + }, + "ty": "UDim2" + }, + "Region3int16": { + "value": { + "Type": "Region3int16", + "Value": [ + [ + -10, + -5, + 0 + ], + [ + 5, + 10, + 15 + ] + ] + }, + "ty": "Region3int16" + }, + "CFrame": { + "value": { + "Type": "CFrame", + "Value": { + "Position": [ + 1.0, + 2.0, + 3.0 + ], + "Orientation": [ + [ + 4.0, + 5.0, + 6.0 + ], + [ + 7.0, + 8.0, + 9.0 + ], + [ + 10.0, + 11.0, + 12.0 + ] + ] + } + }, + "ty": "CFrame" + }, + "Content": { + "value": { + "Type": "Content", + "Value": "rbxassetid://12345" + }, + "ty": "Content" + }, + "PhysicalProperties": { + "value": { + "Type": "PhysicalProperties", + "Value": { + "Density": 0.5, + "Friction": 1.0, + "Elasticity": 0.0, + "FrictionWeight": 50.0, + "ElasticityWeight": 25.0 + } + }, + "ty": "PhysicalProperties" + }, + "Rect": { + "value": { + "Type": "Rect", + "Value": [ + [ + 0.0, + 5.0 + ], + [ + 10.0, + 15.0 + ] + ] + }, + "ty": "Rect" + }, + "Vector2int16": { + "value": { + "Type": "Vector2int16", + "Value": [ + -300, + 300 + ] + }, + "ty": "Vector2int16" + } +} diff --git a/plugin/rbx_dom_lua/src/database.json b/plugin/rbx_dom_lua/src/database.json new file mode 100644 index 00000000..08a31239 --- /dev/null +++ b/plugin/rbx_dom_lua/src/database.json @@ -0,0 +1,43997 @@ +{ + "Version": [ + 0, + 465, + 0, + 417678 + ], + "Classes": { + "ABTestService": { + "Name": "ABTestService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Accessory": { + "Name": "Accessory", + "Tags": [], + "Superclass": "Accoutrement", + "Properties": {}, + "DefaultProperties": { + "AttachmentPoint": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Accoutrement": { + "Name": "Accoutrement", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "AttachmentForward": { + "Name": "AttachmentForward", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AttachmentPoint": { + "Name": "AttachmentPoint", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AttachmentPos": { + "Name": "AttachmentPos", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AttachmentRight": { + "Name": "AttachmentRight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AttachmentUp": { + "Name": "AttachmentUp", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttachmentPoint": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Actor": { + "Name": "Actor", + "Tags": [], + "Superclass": "Model", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "LevelOfDetail": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "AdService": { + "Name": "AdService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "AdvancedDragger": { + "Name": "AdvancedDragger", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "AlignOrientation": { + "Name": "AlignOrientation", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "AlignType": { + "Name": "AlignType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AlignType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxAngularVelocity": { + "Name": "MaxAngularVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxTorque": { + "Name": "MaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PrimaryAxisOnly": { + "Name": "PrimaryAxisOnly", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReactionTorqueEnabled": { + "Name": "ReactionTorqueEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Responsiveness": { + "Name": "Responsiveness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RigidityEnabled": { + "Name": "RigidityEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AlignType": { + "Type": "Enum", + "Value": 0 + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Int32", + "Value": 23 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "MaxAngularVelocity": { + "Type": "Float32", + "Value": null + }, + "MaxTorque": { + "Type": "Float32", + "Value": 10000.0 + }, + "PrimaryAxisOnly": { + "Type": "Bool", + "Value": false + }, + "ReactionTorqueEnabled": { + "Type": "Bool", + "Value": false + }, + "Responsiveness": { + "Type": "Float32", + "Value": 10.0 + }, + "RigidityEnabled": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "AlignPosition": { + "Name": "AlignPosition", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "ApplyAtCenterOfMass": { + "Name": "ApplyAtCenterOfMass", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxForce": { + "Name": "MaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxVelocity": { + "Name": "MaxVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReactionForceEnabled": { + "Name": "ReactionForceEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Responsiveness": { + "Name": "Responsiveness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RigidityEnabled": { + "Name": "RigidityEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "ApplyAtCenterOfMass": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Int32", + "Value": 194 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "MaxForce": { + "Type": "Float32", + "Value": 10000.0 + }, + "MaxVelocity": { + "Type": "Float32", + "Value": null + }, + "ReactionForceEnabled": { + "Type": "Bool", + "Value": false + }, + "Responsiveness": { + "Type": "Float32", + "Value": 10.0 + }, + "RigidityEnabled": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "AnalysticsSettings": { + "Name": "AnalysticsSettings", + "Tags": [ + "NotCreatable" + ], + "Superclass": "GenericSettings", + "Properties": {}, + "DefaultProperties": {} + }, + "AnalyticsService": { + "Name": "AnalyticsService", + "Tags": [ + "Service" + ], + "Superclass": "Instance", + "Properties": { + "ApiKey": { + "Name": "ApiKey", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Deprecated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "ApiKey": { + "Type": "String", + "Value": "" + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "AngularVelocity": { + "Name": "AngularVelocity", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "AngularVelocity": { + "Name": "AngularVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxTorque": { + "Name": "MaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReactionTorqueEnabled": { + "Name": "ReactionTorqueEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RelativeTo": { + "Name": "RelativeTo", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ActuatorRelativeTo" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AngularVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Int32", + "Value": 23 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "MaxTorque": { + "Type": "Float32", + "Value": 0.0 + }, + "ReactionTorqueEnabled": { + "Type": "Bool", + "Value": false + }, + "RelativeTo": { + "Type": "Enum", + "Value": 2 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "Animation": { + "Name": "Animation", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "AnimationId": { + "Name": "AnimationId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AnimationId": { + "Type": "Content", + "Value": "" + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "AnimationController": { + "Name": "AnimationController", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "AnimationTrack": { + "Name": "AnimationTrack", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Animation": { + "Name": "Animation", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPlaying": { + "Name": "IsPlaying", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Length": { + "Name": "Length", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Looped": { + "Name": "Looped", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Priority": { + "Name": "Priority", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AnimationPriority" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Speed": { + "Name": "Speed", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TimePosition": { + "Name": "TimePosition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WeightCurrent": { + "Name": "WeightCurrent", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WeightTarget": { + "Name": "WeightTarget", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "Animator": { + "Name": "Animator", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "AppStorageService": { + "Name": "AppStorageService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "LocalStorageService", + "Properties": {}, + "DefaultProperties": {} + }, + "AppUpdateService": { + "Name": "AppUpdateService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "ArcHandles": { + "Name": "ArcHandles", + "Tags": [], + "Superclass": "HandlesBase", + "Properties": { + "Axes": { + "Name": "Axes", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Axes" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Axes": { + "Type": "Axes", + "Value": [ + "X", + "Y", + "Z" + ] + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + } + } + }, + "AssetCounterService": { + "Name": "AssetCounterService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "AssetDeliveryProxy": { + "Name": "AssetDeliveryProxy", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "AssetManagerService": { + "Name": "AssetManagerService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "AssetService": { + "Name": "AssetService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Atmosphere": { + "Name": "Atmosphere", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Decay": { + "Name": "Decay", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Density": { + "Name": "Density", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Glare": { + "Name": "Glare", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Haze": { + "Name": "Haze", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Offset": { + "Name": "Offset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Color3", + "Value": [ + 0.7843, + 0.6667, + 0.4235 + ] + }, + "Decay": { + "Type": "Color3", + "Value": [ + 0.3608, + 0.2353, + 0.0549 + ] + }, + "Density": { + "Type": "Float32", + "Value": 0.395 + }, + "Glare": { + "Type": "Float32", + "Value": 0.0 + }, + "Haze": { + "Type": "Float32", + "Value": 0.0 + }, + "Offset": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Attachment": { + "Name": "Attachment", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Axis": { + "Name": "Axis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CFrame": { + "Name": "CFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Orientation": { + "Name": "Orientation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Position": { + "Name": "Position", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Rotation": { + "Name": "Rotation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SecondaryAxis": { + "Name": "SecondaryAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Visible": { + "Name": "Visible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WorldAxis": { + "Name": "WorldAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WorldCFrame": { + "Name": "WorldCFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WorldOrientation": { + "Name": "WorldOrientation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WorldPosition": { + "Name": "WorldPosition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WorldRotation": { + "Name": "WorldRotation", + "Scriptability": "Read", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WorldSecondaryAxis": { + "Name": "WorldSecondaryAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "AvatarEditorService": { + "Name": "AvatarEditorService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Backpack": { + "Name": "Backpack", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "BackpackItem": { + "Name": "BackpackItem", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "TextureId": { + "Name": "TextureId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "BadgeService": { + "Name": "BadgeService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "BallSocketConstraint": { + "Name": "BallSocketConstraint", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "LimitsEnabled": { + "Name": "LimitsEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxFrictionTorque": { + "Name": "MaxFrictionTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Radius": { + "Name": "Radius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Restitution": { + "Name": "Restitution", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TwistLimitsEnabled": { + "Name": "TwistLimitsEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TwistLowerAngle": { + "Name": "TwistLowerAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TwistUpperAngle": { + "Name": "TwistUpperAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UpperAngle": { + "Name": "UpperAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Int32", + "Value": 1009 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "LimitsEnabled": { + "Type": "Bool", + "Value": false + }, + "Radius": { + "Type": "Float32", + "Value": 0.15 + }, + "Restitution": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TwistLimitsEnabled": { + "Type": "Bool", + "Value": false + }, + "TwistLowerAngle": { + "Type": "Float32", + "Value": -45.0 + }, + "TwistUpperAngle": { + "Type": "Float32", + "Value": 45.0 + }, + "UpperAngle": { + "Type": "Float32", + "Value": 45.0 + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "BasePart": { + "Name": "BasePart", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "PVInstance", + "Properties": { + "Anchored": { + "Name": "Anchored", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AssemblyAngularVelocity": { + "Name": "AssemblyAngularVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AssemblyCenterOfMass": { + "Name": "AssemblyCenterOfMass", + "Scriptability": "Read", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AssemblyLinearVelocity": { + "Name": "AssemblyLinearVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AssemblyMass": { + "Name": "AssemblyMass", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AssemblyRootPart": { + "Name": "AssemblyRootPart", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "BackParamA": { + "Name": "BackParamA", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BackParamB": { + "Name": "BackParamB", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BackSurface": { + "Name": "BackSurface", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SurfaceType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BackSurfaceInput": { + "Name": "BackSurfaceInput", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "InputType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BottomParamA": { + "Name": "BottomParamA", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BottomParamB": { + "Name": "BottomParamB", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BottomSurface": { + "Name": "BottomSurface", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SurfaceType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BottomSurfaceInput": { + "Name": "BottomSurfaceInput", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "InputType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BrickColor": { + "Name": "BrickColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "Color" + } + } + }, + "CFrame": { + "Name": "CFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CanCollide": { + "Name": "CanCollide", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CanTouch": { + "Name": "CanTouch", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CastShadow": { + "Name": "CastShadow", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CenterOfMass": { + "Name": "CenterOfMass", + "Scriptability": "Read", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CollisionGroupId": { + "Name": "CollisionGroupId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CollisionGroups": { + "Name": "CollisionGroups", + "Scriptability": "Custom", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "Color3uint8" + } + } + } + }, + "Color3uint8": { + "Name": "Color3uint8", + "Scriptability": "None", + "DataType": { + "Value": "Color3uint8" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "Color" + } + } + }, + "CustomPhysicalProperties": { + "Name": "CustomPhysicalProperties", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "PhysicalProperties" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Elasticity": { + "Name": "Elasticity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Friction": { + "Name": "Friction", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FrontParamA": { + "Name": "FrontParamA", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FrontParamB": { + "Name": "FrontParamB", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FrontSurface": { + "Name": "FrontSurface", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SurfaceType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FrontSurfaceInput": { + "Name": "FrontSurfaceInput", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "InputType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeftParamA": { + "Name": "LeftParamA", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeftParamB": { + "Name": "LeftParamB", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeftSurface": { + "Name": "LeftSurface", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SurfaceType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeftSurfaceInput": { + "Name": "LeftSurfaceInput", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "InputType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LocalTransparencyModifier": { + "Name": "LocalTransparencyModifier", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Locked": { + "Name": "Locked", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Mass": { + "Name": "Mass", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Massless": { + "Name": "Massless", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Material": { + "Name": "Material", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "Material" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Orientation": { + "Name": "Orientation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Position": { + "Name": "Position", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ReceiveAge": { + "Name": "ReceiveAge", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Reflectance": { + "Name": "Reflectance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ResizeIncrement": { + "Name": "ResizeIncrement", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ResizeableFaces": { + "Name": "ResizeableFaces", + "Scriptability": "Read", + "DataType": { + "Value": "Faces" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightParamA": { + "Name": "RightParamA", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RightParamB": { + "Name": "RightParamB", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RightSurface": { + "Name": "RightSurface", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SurfaceType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RightSurfaceInput": { + "Name": "RightSurfaceInput", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "InputType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RootPriority": { + "Name": "RootPriority", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RotVelocity": { + "Name": "RotVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Rotation": { + "Name": "Rotation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "size" + } + } + } + }, + "SpecificGravity": { + "Name": "SpecificGravity", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TopParamA": { + "Name": "TopParamA", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TopParamB": { + "Name": "TopParamB", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TopSurface": { + "Name": "TopSurface", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SurfaceType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TopSurfaceInput": { + "Name": "TopSurfaceInput", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "InputType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Transparency": { + "Name": "Transparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Velocity": { + "Name": "Velocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "brickColor": { + "Name": "brickColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "Color" + } + } + }, + "size": { + "Name": "size", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "Size" + } + } + } + }, + "DefaultProperties": {} + }, + "BasePlayerGui": { + "Name": "BasePlayerGui", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "BaseScript": { + "Name": "BaseScript", + "Tags": [ + "NotCreatable" + ], + "Superclass": "LuaSourceContainer", + "Properties": { + "Disabled": { + "Name": "Disabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LinkedSource": { + "Name": "LinkedSource", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "BaseWrap": { + "Name": "BaseWrap", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "CageMeshId": { + "Name": "CageMeshId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CageOrigin": { + "Name": "CageOrigin", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CageOriginWorld": { + "Name": "CageOriginWorld", + "Scriptability": "Read", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ImportOrigin": { + "Name": "ImportOrigin", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImportOriginWorld": { + "Name": "ImportOriginWorld", + "Scriptability": "Read", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "Beam": { + "Name": "Beam", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Attachment0": { + "Name": "Attachment0", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Attachment1": { + "Name": "Attachment1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "ColorSequence" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CurveSize0": { + "Name": "CurveSize0", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CurveSize1": { + "Name": "CurveSize1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FaceCamera": { + "Name": "FaceCamera", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LightEmission": { + "Name": "LightEmission", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LightInfluence": { + "Name": "LightInfluence", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Segments": { + "Name": "Segments", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Texture": { + "Name": "Texture", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextureLength": { + "Name": "TextureLength", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextureMode": { + "Name": "TextureMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextureMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextureSpeed": { + "Name": "TextureSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Transparency": { + "Name": "Transparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberSequence" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Width0": { + "Name": "Width0", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Width1": { + "Name": "Width1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ZOffset": { + "Name": "ZOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "ColorSequence", + "Value": { + "Keypoints": [ + { + "Time": 0.0, + "Color": [ + 1.0, + 1.0, + 1.0 + ] + }, + { + "Time": 1.0, + "Color": [ + 1.0, + 1.0, + 1.0 + ] + } + ] + } + }, + "CurveSize0": { + "Type": "Float32", + "Value": 0.0 + }, + "CurveSize1": { + "Type": "Float32", + "Value": 0.0 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "FaceCamera": { + "Type": "Bool", + "Value": false + }, + "LightEmission": { + "Type": "Float32", + "Value": 0.0 + }, + "LightInfluence": { + "Type": "Float32", + "Value": 0.0 + }, + "Segments": { + "Type": "Int32", + "Value": 10 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Texture": { + "Type": "Content", + "Value": "" + }, + "TextureLength": { + "Type": "Float32", + "Value": 1.0 + }, + "TextureMode": { + "Type": "Enum", + "Value": 0 + }, + "TextureSpeed": { + "Type": "Float32", + "Value": 1.0 + }, + "Transparency": { + "Type": "NumberSequence", + "Value": { + "Keypoints": [ + { + "Time": 0.0, + "Value": 0.5, + "Envelope": 0.0 + }, + { + "Time": 1.0, + "Value": 0.5, + "Envelope": 0.0 + } + ] + } + }, + "Width0": { + "Type": "Float32", + "Value": 1.0 + }, + "Width1": { + "Type": "Float32", + "Value": 1.0 + }, + "ZOffset": { + "Type": "Float32", + "Value": 0.0 + } + } + }, + "BevelMesh": { + "Name": "BevelMesh", + "Tags": [ + "Deprecated", + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "DataModelMesh", + "Properties": {}, + "DefaultProperties": {} + }, + "BillboardGui": { + "Name": "BillboardGui", + "Tags": [], + "Superclass": "LayerCollector", + "Properties": { + "Active": { + "Name": "Active", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Adornee": { + "Name": "Adornee", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AlwaysOnTop": { + "Name": "AlwaysOnTop", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClipsDescendants": { + "Name": "ClipsDescendants", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CurrentDistance": { + "Name": "CurrentDistance", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DistanceLowerLimit": { + "Name": "DistanceLowerLimit", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DistanceStep": { + "Name": "DistanceStep", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DistanceUpperLimit": { + "Name": "DistanceUpperLimit", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ExtentsOffset": { + "Name": "ExtentsOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ExtentsOffsetWorldSpace": { + "Name": "ExtentsOffsetWorldSpace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LightInfluence": { + "Name": "LightInfluence", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxDistance": { + "Name": "MaxDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlayerToHideFrom": { + "Name": "PlayerToHideFrom", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SizeOffset": { + "Name": "SizeOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StudsOffset": { + "Name": "StudsOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StudsOffsetWorldSpace": { + "Name": "StudsOffsetWorldSpace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Type": "Bool", + "Value": false + }, + "AlwaysOnTop": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "ClipsDescendants": { + "Type": "Bool", + "Value": false + }, + "DistanceLowerLimit": { + "Type": "Float32", + "Value": 0.0 + }, + "DistanceStep": { + "Type": "Float32", + "Value": 0.0 + }, + "DistanceUpperLimit": { + "Type": "Float32", + "Value": -1.0 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "ExtentsOffset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "ExtentsOffsetWorldSpace": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "LightInfluence": { + "Type": "Float32", + "Value": 0.0 + }, + "MaxDistance": { + "Type": "Float32", + "Value": null + }, + "ResetOnSpawn": { + "Type": "Bool", + "Value": true + }, + "Size": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SizeOffset": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "StudsOffset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "StudsOffsetWorldSpace": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "ZIndexBehavior": { + "Type": "Enum", + "Value": 0 + } + } + }, + "BinaryStringValue": { + "Name": "BinaryStringValue", + "Tags": [], + "Superclass": "ValueBase", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "BindableEvent": { + "Name": "BindableEvent", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "BindableFunction": { + "Name": "BindableFunction", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "BlockMesh": { + "Name": "BlockMesh", + "Tags": [], + "Superclass": "BevelMesh", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Offset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Scale": { + "Type": "Vector3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "VertexColor": { + "Type": "Vector3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + } + } + }, + "BloomEffect": { + "Name": "BloomEffect", + "Tags": [], + "Superclass": "PostEffect", + "Properties": { + "Intensity": { + "Name": "Intensity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Threshold": { + "Name": "Threshold", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Intensity": { + "Type": "Float32", + "Value": 0.4 + }, + "Size": { + "Type": "Float32", + "Value": 24.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Threshold": { + "Type": "Float32", + "Value": 0.95 + } + } + }, + "BlurEffect": { + "Name": "BlurEffect", + "Tags": [], + "Superclass": "PostEffect", + "Properties": { + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Size": { + "Type": "Float32", + "Value": 24.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "BodyAngularVelocity": { + "Name": "BodyAngularVelocity", + "Tags": [], + "Superclass": "BodyMover", + "Properties": { + "AngularVelocity": { + "Name": "AngularVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxTorque": { + "Name": "MaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "P": { + "Name": "P", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "angularvelocity": { + "Name": "angularvelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "AngularVelocity" + } + } + }, + "maxTorque": { + "Name": "maxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "MaxTorque" + } + } + } + }, + "DefaultProperties": { + "AngularVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 2.0, + 0.0 + ] + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "MaxTorque": { + "Type": "Vector3", + "Value": [ + 4000.0, + 4000.0, + 4000.0 + ] + }, + "P": { + "Type": "Float32", + "Value": 1250.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "BodyColors": { + "Name": "BodyColors", + "Tags": [], + "Superclass": "CharacterAppearance", + "Properties": { + "HeadColor": { + "Name": "HeadColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "HeadColor3": { + "Name": "HeadColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeftArmColor": { + "Name": "LeftArmColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftArmColor3": { + "Name": "LeftArmColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeftLegColor": { + "Name": "LeftLegColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftLegColor3": { + "Name": "LeftLegColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RightArmColor": { + "Name": "RightArmColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightArmColor3": { + "Name": "RightArmColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RightLegColor": { + "Name": "RightLegColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightLegColor3": { + "Name": "RightLegColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TorsoColor": { + "Name": "TorsoColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TorsoColor3": { + "Name": "TorsoColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "HeadColor3": { + "Type": "Color3", + "Value": [ + 0.9921569, + 0.9176471, + 0.5529412 + ] + }, + "LeftArmColor3": { + "Type": "Color3", + "Value": [ + 0.9921569, + 0.9176471, + 0.5529412 + ] + }, + "LeftLegColor3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "RightArmColor3": { + "Type": "Color3", + "Value": [ + 0.9921569, + 0.9176471, + 0.5529412 + ] + }, + "RightLegColor3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TorsoColor3": { + "Type": "Color3", + "Value": [ + 0.15686275, + 0.49803925, + 0.2784314 + ] + } + } + }, + "BodyForce": { + "Name": "BodyForce", + "Tags": [], + "Superclass": "BodyMover", + "Properties": { + "Force": { + "Name": "Force", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "force": { + "Name": "force", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "Force" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Force": { + "Type": "Vector3", + "Value": [ + 0.0, + 1.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "BodyGyro": { + "Name": "BodyGyro", + "Tags": [], + "Superclass": "BodyMover", + "Properties": { + "CFrame": { + "Name": "CFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "D": { + "Name": "D", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxTorque": { + "Name": "MaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "P": { + "Name": "P", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "cframe": { + "Name": "cframe", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "CFrame" + } + } + }, + "maxTorque": { + "Name": "maxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "MaxTorque" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "D": { + "Type": "Float32", + "Value": 500.0 + }, + "MaxTorque": { + "Type": "Vector3", + "Value": [ + 400000.0, + 0.0, + 400000.0 + ] + }, + "P": { + "Type": "Float32", + "Value": 3000.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "BodyMover": { + "Name": "BodyMover", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "BodyPosition": { + "Name": "BodyPosition", + "Tags": [], + "Superclass": "BodyMover", + "Properties": { + "D": { + "Name": "D", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxForce": { + "Name": "MaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "P": { + "Name": "P", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Position": { + "Name": "Position", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "maxForce": { + "Name": "maxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "MaxForce" + } + } + }, + "position": { + "Name": "position", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "Position" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "D": { + "Type": "Float32", + "Value": 1250.0 + }, + "MaxForce": { + "Type": "Vector3", + "Value": [ + 4000.0, + 4000.0, + 4000.0 + ] + }, + "P": { + "Type": "Float32", + "Value": 10000.0 + }, + "Position": { + "Type": "Vector3", + "Value": [ + 0.0, + 50.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "BodyThrust": { + "Name": "BodyThrust", + "Tags": [], + "Superclass": "BodyMover", + "Properties": { + "Force": { + "Name": "Force", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Location": { + "Name": "Location", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "force": { + "Name": "force", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "Force" + } + } + }, + "location": { + "Name": "location", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "Location" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Force": { + "Type": "Vector3", + "Value": [ + 0.0, + 1.0, + 0.0 + ] + }, + "Location": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "BodyVelocity": { + "Name": "BodyVelocity", + "Tags": [], + "Superclass": "BodyMover", + "Properties": { + "MaxForce": { + "Name": "MaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "P": { + "Name": "P", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Velocity": { + "Name": "Velocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "maxForce": { + "Name": "maxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "MaxForce" + } + } + }, + "velocity": { + "Name": "velocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "Velocity" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "MaxForce": { + "Type": "Vector3", + "Value": [ + 4000.0, + 4000.0, + 4000.0 + ] + }, + "P": { + "Type": "Float32", + "Value": 1250.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 2.0, + 0.0 + ] + } + } + }, + "Bone": { + "Name": "Bone", + "Tags": [], + "Superclass": "Attachment", + "Properties": { + "Transform": { + "Name": "Transform", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TransformedCFrame": { + "Name": "TransformedCFrame", + "Scriptability": "Read", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TransformedWorldCFrame": { + "Name": "TransformedWorldCFrame", + "Scriptability": "Read", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "BoolValue": { + "Name": "BoolValue", + "Tags": [], + "Superclass": "ValueBase", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Value": { + "Type": "Bool", + "Value": false + } + } + }, + "BoxHandleAdornment": { + "Name": "BoxHandleAdornment", + "Tags": [], + "Superclass": "HandleAdornment", + "Properties": { + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AdornCullingMode": { + "Type": "Enum", + "Value": 0 + }, + "AlwaysOnTop": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "Size": { + "Type": "Vector3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "SizeRelativeOffset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": -1 + } + } + }, + "BrickColorValue": { + "Name": "BrickColorValue", + "Tags": [], + "Superclass": "ValueBase", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Value": { + "Type": "Int32", + "Value": 194 + } + } + }, + "BrowserService": { + "Name": "BrowserService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "BulkImportService": { + "Name": "BulkImportService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "CFrameValue": { + "Name": "CFrameValue", + "Tags": [], + "Superclass": "ValueBase", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Value": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + } + } + }, + "CSGDictionaryService": { + "Name": "CSGDictionaryService", + "Tags": [ + "Service" + ], + "Superclass": "FlyweightService", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "CacheableContentProvider": { + "Name": "CacheableContentProvider", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Camera": { + "Name": "Camera", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "CFrame": { + "Name": "CFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraSubject": { + "Name": "CameraSubject", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraType": { + "Name": "CameraType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "CameraType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CoordinateFrame": { + "Name": "CoordinateFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "CFrame" + } + } + }, + "DiagonalFieldOfView": { + "Name": "DiagonalFieldOfView", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FieldOfView": { + "Name": "FieldOfView", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FieldOfViewMode": { + "Name": "FieldOfViewMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "FieldOfViewMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Focus": { + "Name": "Focus", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HeadLocked": { + "Name": "HeadLocked", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HeadScale": { + "Name": "HeadScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxAxisFieldOfView": { + "Name": "MaxAxisFieldOfView", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "NearPlaneZ": { + "Name": "NearPlaneZ", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ViewportSize": { + "Name": "ViewportSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "focus": { + "Name": "focus", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "Focus" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 20.0, + 20.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + -0.0 + ], + [ + -0.0, + 0.7071068, + 0.7071068 + ], + [ + 0.0, + -0.7071068, + 0.7071068 + ] + ] + } + }, + "CameraType": { + "Type": "Enum", + "Value": 0 + }, + "FieldOfView": { + "Type": "Float32", + "Value": 70.0 + }, + "FieldOfViewMode": { + "Type": "Enum", + "Value": 0 + }, + "Focus": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + -5.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "HeadLocked": { + "Type": "Bool", + "Value": true + }, + "HeadScale": { + "Type": "Float32", + "Value": 1.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "CatalogPages": { + "Name": "CatalogPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, + "ChangeHistoryService": { + "Name": "ChangeHistoryService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "CharacterAppearance": { + "Name": "CharacterAppearance", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "CharacterMesh": { + "Name": "CharacterMesh", + "Tags": [], + "Superclass": "CharacterAppearance", + "Properties": { + "BaseTextureId": { + "Name": "BaseTextureId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BodyPart": { + "Name": "BodyPart", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "BodyPart" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MeshId": { + "Name": "MeshId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OverlayTextureId": { + "Name": "OverlayTextureId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BaseTextureId": { + "Type": "Int64", + "Value": 0 + }, + "BodyPart": { + "Type": "Enum", + "Value": 0 + }, + "MeshId": { + "Type": "Int64", + "Value": 0 + }, + "OverlayTextureId": { + "Type": "Int64", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Chat": { + "Name": "Chat", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "BubbleChatEnabled": { + "Name": "BubbleChatEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LoadDefaultChat": { + "Name": "LoadDefaultChat", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BubbleChatEnabled": { + "Type": "Bool", + "Value": false + }, + "LoadDefaultChat": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ChorusSoundEffect": { + "Name": "ChorusSoundEffect", + "Tags": [], + "Superclass": "SoundEffect", + "Properties": { + "Depth": { + "Name": "Depth", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Mix": { + "Name": "Mix", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Rate": { + "Name": "Rate", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Depth": { + "Type": "Float32", + "Value": 0.15 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Mix": { + "Type": "Float32", + "Value": 0.5 + }, + "Priority": { + "Type": "Int32", + "Value": 0 + }, + "Rate": { + "Type": "Float32", + "Value": 0.5 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ClickDetector": { + "Name": "ClickDetector", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "CursorIcon": { + "Name": "CursorIcon", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxActivationDistance": { + "Name": "MaxActivationDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CursorIcon": { + "Type": "Content", + "Value": "" + }, + "MaxActivationDistance": { + "Type": "Float32", + "Value": 32.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ClientReplicator": { + "Name": "ClientReplicator", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "NetworkReplicator", + "Properties": {}, + "DefaultProperties": {} + }, + "Clothing": { + "Name": "Clothing", + "Tags": [ + "NotCreatable" + ], + "Superclass": "CharacterAppearance", + "Properties": { + "Color3": { + "Name": "Color3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "Clouds": { + "Name": "Clouds", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Cover": { + "Name": "Cover", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Density": { + "Name": "Density", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Cover": { + "Type": "Float32", + "Value": 0.5 + }, + "Density": { + "Type": "Float32", + "Value": 0.7 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ClusterPacketCache": { + "Name": "ClusterPacketCache", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "CollectionService": { + "Name": "CollectionService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Color3Value": { + "Name": "Color3Value", + "Tags": [], + "Superclass": "ValueBase", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Value": { + "Type": "Color3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "ColorCorrectionEffect": { + "Name": "ColorCorrectionEffect", + "Tags": [], + "Superclass": "PostEffect", + "Properties": { + "Brightness": { + "Name": "Brightness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Contrast": { + "Name": "Contrast", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Saturation": { + "Name": "Saturation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TintColor": { + "Name": "TintColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Brightness": { + "Type": "Float32", + "Value": 0.0 + }, + "Contrast": { + "Type": "Float32", + "Value": 0.0 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Saturation": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TintColor": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + } + } + }, + "CompressorSoundEffect": { + "Name": "CompressorSoundEffect", + "Tags": [], + "Superclass": "SoundEffect", + "Properties": { + "Attack": { + "Name": "Attack", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GainMakeup": { + "Name": "GainMakeup", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Ratio": { + "Name": "Ratio", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Release": { + "Name": "Release", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SideChain": { + "Name": "SideChain", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Threshold": { + "Name": "Threshold", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attack": { + "Type": "Float32", + "Value": 0.1 + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "GainMakeup": { + "Type": "Float32", + "Value": 0.0 + }, + "Priority": { + "Type": "Int32", + "Value": 0 + }, + "Ratio": { + "Type": "Float32", + "Value": 40.0 + }, + "Release": { + "Type": "Float32", + "Value": 0.1 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Threshold": { + "Type": "Float32", + "Value": -40.0 + } + } + }, + "ConeHandleAdornment": { + "Name": "ConeHandleAdornment", + "Tags": [], + "Superclass": "HandleAdornment", + "Properties": { + "Height": { + "Name": "Height", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Radius": { + "Name": "Radius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AdornCullingMode": { + "Type": "Enum", + "Value": 0 + }, + "AlwaysOnTop": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "Height": { + "Type": "Float32", + "Value": 2.0 + }, + "Radius": { + "Type": "Float32", + "Value": 0.5 + }, + "SizeRelativeOffset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": -1 + } + } + }, + "Configuration": { + "Name": "Configuration", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Constraint": { + "Name": "Constraint", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Active": { + "Name": "Active", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Attachment0": { + "Name": "Attachment0", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Attachment1": { + "Name": "Attachment1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Visible": { + "Name": "Visible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "ContentProvider": { + "Name": "ContentProvider", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "BaseUrl": { + "Name": "BaseUrl", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RequestQueueSize": { + "Name": "RequestQueueSize", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "ContextActionService": { + "Name": "ContextActionService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Controller": { + "Name": "Controller", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "ControllerService": { + "Name": "ControllerService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "CookiesService": { + "Name": "CookiesService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "CoreGui": { + "Name": "CoreGui", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "BasePlayerGui", + "Properties": { + "SelectionImageObject": { + "Name": "SelectionImageObject", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Version": { + "Name": "Version", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "CorePackages": { + "Name": "CorePackages", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "CoreScript": { + "Name": "CoreScript", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "BaseScript", + "Properties": {}, + "DefaultProperties": {} + }, + "CoreScriptSyncService": { + "Name": "CoreScriptSyncService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "CornerWedgePart": { + "Name": "CornerWedgePart", + "Tags": [], + "Superclass": "BasePart", + "Properties": {}, + "DefaultProperties": { + "Anchored": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 0 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 163, + 162, + 165 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Size": { + "Type": "Vector3", + "Value": [ + 2.0, + 2.0, + 2.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 0 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "CustomEvent": { + "Name": "CustomEvent", + "Tags": [ + "Deprecated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "CustomEventReceiver": { + "Name": "CustomEventReceiver", + "Tags": [ + "Deprecated" + ], + "Superclass": "Instance", + "Properties": { + "Source": { + "Name": "Source", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "CylinderHandleAdornment": { + "Name": "CylinderHandleAdornment", + "Tags": [], + "Superclass": "HandleAdornment", + "Properties": { + "Angle": { + "Name": "Angle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Height": { + "Name": "Height", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InnerRadius": { + "Name": "InnerRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Radius": { + "Name": "Radius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AdornCullingMode": { + "Type": "Enum", + "Value": 0 + }, + "AlwaysOnTop": { + "Type": "Bool", + "Value": false + }, + "Angle": { + "Type": "Float32", + "Value": 360.0 + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "Height": { + "Type": "Float32", + "Value": 1.0 + }, + "InnerRadius": { + "Type": "Float32", + "Value": 0.0 + }, + "Radius": { + "Type": "Float32", + "Value": 1.0 + }, + "SizeRelativeOffset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": -1 + } + } + }, + "CylinderMesh": { + "Name": "CylinderMesh", + "Tags": [ + "Deprecated" + ], + "Superclass": "BevelMesh", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Offset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Scale": { + "Type": "Vector3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "VertexColor": { + "Type": "Vector3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + } + } + }, + "CylindricalConstraint": { + "Name": "CylindricalConstraint", + "Tags": [], + "Superclass": "SlidingBallConstraint", + "Properties": { + "AngularActuatorType": { + "Name": "AngularActuatorType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ActuatorType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AngularLimitsEnabled": { + "Name": "AngularLimitsEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AngularRestitution": { + "Name": "AngularRestitution", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AngularSpeed": { + "Name": "AngularSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AngularVelocity": { + "Name": "AngularVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CurrentAngle": { + "Name": "CurrentAngle", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "InclinationAngle": { + "Name": "InclinationAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LowerAngle": { + "Name": "LowerAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MotorMaxAngularAcceleration": { + "Name": "MotorMaxAngularAcceleration", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MotorMaxTorque": { + "Name": "MotorMaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RotationAxisVisible": { + "Name": "RotationAxisVisible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ServoMaxTorque": { + "Name": "ServoMaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TargetAngle": { + "Name": "TargetAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UpperAngle": { + "Name": "UpperAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WorldRotationAxis": { + "Name": "WorldRotationAxis", + "Scriptability": "Read", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "ActuatorType": { + "Type": "Enum", + "Value": 0 + }, + "AngularActuatorType": { + "Type": "Enum", + "Value": 0 + }, + "AngularLimitsEnabled": { + "Type": "Bool", + "Value": false + }, + "AngularRestitution": { + "Type": "Float32", + "Value": 0.0 + }, + "AngularSpeed": { + "Type": "Float32", + "Value": 0.0 + }, + "AngularVelocity": { + "Type": "Float32", + "Value": 0.0 + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Int32", + "Value": 1009 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "InclinationAngle": { + "Type": "Float32", + "Value": 0.0 + }, + "LimitsEnabled": { + "Type": "Bool", + "Value": false + }, + "LowerAngle": { + "Type": "Float32", + "Value": -45.0 + }, + "LowerLimit": { + "Type": "Float32", + "Value": 0.0 + }, + "MotorMaxAcceleration": { + "Type": "Float32", + "Value": null + }, + "MotorMaxAngularAcceleration": { + "Type": "Float32", + "Value": null + }, + "MotorMaxForce": { + "Type": "Float32", + "Value": 0.0 + }, + "MotorMaxTorque": { + "Type": "Float32", + "Value": 0.0 + }, + "Restitution": { + "Type": "Float32", + "Value": 0.0 + }, + "RotationAxisVisible": { + "Type": "Bool", + "Value": false + }, + "ServoMaxForce": { + "Type": "Float32", + "Value": 0.0 + }, + "ServoMaxTorque": { + "Type": "Float32", + "Value": 0.0 + }, + "Size": { + "Type": "Float32", + "Value": 0.15 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Speed": { + "Type": "Float32", + "Value": 0.0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TargetAngle": { + "Type": "Float32", + "Value": 0.0 + }, + "TargetPosition": { + "Type": "Float32", + "Value": 0.0 + }, + "UpperAngle": { + "Type": "Float32", + "Value": 45.0 + }, + "UpperLimit": { + "Type": "Float32", + "Value": 5.0 + }, + "Velocity": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "DataModel": { + "Name": "DataModel", + "Tags": [ + "NotCreatable" + ], + "Superclass": "ServiceProvider", + "Properties": { + "CreatorId": { + "Name": "CreatorId", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CreatorType": { + "Name": "CreatorType", + "Scriptability": "Read", + "DataType": { + "Enum": "CreatorType" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GameId": { + "Name": "GameId", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GearGenreSetting": { + "Name": "GearGenreSetting", + "Scriptability": "Read", + "DataType": { + "Enum": "GearGenreSetting" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Genre": { + "Name": "Genre", + "Scriptability": "Read", + "DataType": { + "Enum": "Genre" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsSFFlagsLoaded": { + "Name": "IsSFFlagsLoaded", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "JobId": { + "Name": "JobId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlaceId": { + "Name": "PlaceId", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlaceVersion": { + "Name": "PlaceVersion", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PrivateServerId": { + "Name": "PrivateServerId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PrivateServerOwnerId": { + "Name": "PrivateServerOwnerId", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "VIPServerId": { + "Name": "VIPServerId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "VIPServerOwnerId": { + "Name": "VIPServerOwnerId", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Workspace": { + "Name": "Workspace", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "lighting": { + "Name": "lighting", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "workspace": { + "Name": "workspace", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "DataModelMesh": { + "Name": "DataModelMesh", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Offset": { + "Name": "Offset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Scale": { + "Name": "Scale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VertexColor": { + "Name": "VertexColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "DataModelSession": { + "Name": "DataModelSession", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "CurrentDataModelType": { + "Name": "CurrentDataModelType", + "Scriptability": "Read", + "DataType": { + "Enum": "StudioDataModelType" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SessionId": { + "Name": "SessionId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "DataStore": { + "Name": "DataStore", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "GlobalDataStore", + "Properties": {}, + "DefaultProperties": {} + }, + "DataStoreEnumerationPages": { + "Name": "DataStoreEnumerationPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, + "DataStoreIncrementOptions": { + "Name": "DataStoreIncrementOptions", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "DataStoreInfo": { + "Name": "DataStoreInfo", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "CreatedTime": { + "Name": "CreatedTime", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DataStoreName": { + "Name": "DataStoreName", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UpdatedTime": { + "Name": "UpdatedTime", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "DataStoreKeyInfo": { + "Name": "DataStoreKeyInfo", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "KeyName": { + "Name": "KeyName", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "DataStoreKeyPages": { + "Name": "DataStoreKeyPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, + "DataStoreKeyVersionInfo": { + "Name": "DataStoreKeyVersionInfo", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "CreatedTime": { + "Name": "CreatedTime", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UpdatedTime": { + "Name": "UpdatedTime", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Version": { + "Name": "Version", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "DataStorePages": { + "Name": "DataStorePages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, + "DataStoreService": { + "Name": "DataStoreService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "AutomaticRetry": { + "Name": "AutomaticRetry", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LegacyNamingScheme": { + "Name": "LegacyNamingScheme", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutomaticRetry": { + "Type": "Bool", + "Value": true + }, + "LegacyNamingScheme": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "DataStoreSetOptions": { + "Name": "DataStoreSetOptions", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "DataStoreVersionPages": { + "Name": "DataStoreVersionPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, + "Debris": { + "Name": "Debris", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "MaxItems": { + "Name": "MaxItems", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Deprecated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "MaxItems": { + "Type": "Int32", + "Value": 1000 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "DebugSettings": { + "Name": "DebugSettings", + "Tags": [ + "NotBrowsable", + "NotCreatable", + "Settings" + ], + "Superclass": "Instance", + "Properties": { + "DataModel": { + "Name": "DataModel", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "InstanceCount": { + "Name": "InstanceCount", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsScriptStackTracingEnabled": { + "Name": "IsScriptStackTracingEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "JobCount": { + "Name": "JobCount", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlayerCount": { + "Name": "PlayerCount", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ReportSoundWarnings": { + "Name": "ReportSoundWarnings", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RobloxVersion": { + "Name": "RobloxVersion", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TickCountPreciseOverride": { + "Name": "TickCountPreciseOverride", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TickCountSampleMethod" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "DebuggerBreakpoint": { + "Name": "DebuggerBreakpoint", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Condition": { + "Name": "Condition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsEnabled": { + "Name": "IsEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Line": { + "Name": "Line", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "isContextDependentBreakpoint": { + "Name": "isContextDependentBreakpoint", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "DebuggerManager": { + "Name": "DebuggerManager", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "DebuggingEnabled": { + "Name": "DebuggingEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "DebuggerWatch": { + "Name": "DebuggerWatch", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Expression": { + "Name": "Expression", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "Decal": { + "Name": "Decal", + "Tags": [], + "Superclass": "FaceInstance", + "Properties": { + "Color3": { + "Name": "Color3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LocalTransparencyModifier": { + "Name": "LocalTransparencyModifier", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Shiny": { + "Name": "Shiny", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Specular": { + "Name": "Specular", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Texture": { + "Name": "Texture", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Transparency": { + "Name": "Transparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color3": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "Face": { + "Type": "Enum", + "Value": 5 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Texture": { + "Type": "Content", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + } + } + }, + "DepthOfFieldEffect": { + "Name": "DepthOfFieldEffect", + "Tags": [], + "Superclass": "PostEffect", + "Properties": { + "FarIntensity": { + "Name": "FarIntensity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FocusDistance": { + "Name": "FocusDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InFocusRadius": { + "Name": "InFocusRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NearIntensity": { + "Name": "NearIntensity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "FarIntensity": { + "Type": "Float32", + "Value": 0.75 + }, + "FocusDistance": { + "Type": "Float32", + "Value": 0.05 + }, + "InFocusRadius": { + "Type": "Float32", + "Value": 10.0 + }, + "NearIntensity": { + "Type": "Float32", + "Value": 0.75 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Dialog": { + "Name": "Dialog", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "BehaviorType": { + "Name": "BehaviorType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DialogBehaviorType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ConversationDistance": { + "Name": "ConversationDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GoodbyeChoiceActive": { + "Name": "GoodbyeChoiceActive", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GoodbyeDialog": { + "Name": "GoodbyeDialog", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InUse": { + "Name": "InUse", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "InitialPrompt": { + "Name": "InitialPrompt", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Purpose": { + "Name": "Purpose", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DialogPurpose" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Tone": { + "Name": "Tone", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DialogTone" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TriggerDistance": { + "Name": "TriggerDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TriggerOffset": { + "Name": "TriggerOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BehaviorType": { + "Type": "Enum", + "Value": 0 + }, + "ConversationDistance": { + "Type": "Float32", + "Value": 25.0 + }, + "GoodbyeChoiceActive": { + "Type": "Bool", + "Value": true + }, + "GoodbyeDialog": { + "Type": "String", + "Value": "" + }, + "InitialPrompt": { + "Type": "String", + "Value": "" + }, + "Purpose": { + "Type": "Enum", + "Value": 1 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Tone": { + "Type": "Enum", + "Value": 0 + }, + "TriggerDistance": { + "Type": "Float32", + "Value": 0.0 + }, + "TriggerOffset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "DialogChoice": { + "Name": "DialogChoice", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "GoodbyeChoiceActive": { + "Name": "GoodbyeChoiceActive", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GoodbyeDialog": { + "Name": "GoodbyeDialog", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ResponseDialog": { + "Name": "ResponseDialog", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UserDialog": { + "Name": "UserDialog", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "GoodbyeChoiceActive": { + "Type": "Bool", + "Value": true + }, + "GoodbyeDialog": { + "Type": "String", + "Value": "" + }, + "ResponseDialog": { + "Type": "String", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "UserDialog": { + "Type": "String", + "Value": "" + } + } + }, + "DistortionSoundEffect": { + "Name": "DistortionSoundEffect", + "Tags": [], + "Superclass": "SoundEffect", + "Properties": { + "Level": { + "Name": "Level", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Level": { + "Type": "Float32", + "Value": 0.75 + }, + "Priority": { + "Type": "Int32", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "DockWidgetPluginGui": { + "Name": "DockWidgetPluginGui", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "PluginGui", + "Properties": { + "HostWidgetWasRestored": { + "Name": "HostWidgetWasRestored", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "DoubleConstrainedValue": { + "Name": "DoubleConstrainedValue", + "Tags": [ + "Deprecated" + ], + "Superclass": "ValueBase", + "Properties": { + "ConstrainedValue": { + "Name": "ConstrainedValue", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MaxValue": { + "Name": "MaxValue", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MinValue": { + "Name": "MinValue", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "MaxValue": { + "Type": "Float64", + "Value": 1.0 + }, + "MinValue": { + "Type": "Float64", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "DraftsService": { + "Name": "DraftsService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Dragger": { + "Name": "Dragger", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "DynamicRotate": { + "Name": "DynamicRotate", + "Tags": [ + "NotCreatable" + ], + "Superclass": "JointInstance", + "Properties": { + "BaseAngle": { + "Name": "BaseAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "EchoSoundEffect": { + "Name": "EchoSoundEffect", + "Tags": [], + "Superclass": "SoundEffect", + "Properties": { + "Delay": { + "Name": "Delay", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DryLevel": { + "Name": "DryLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Feedback": { + "Name": "Feedback", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WetLevel": { + "Name": "WetLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Delay": { + "Type": "Float32", + "Value": 1.0 + }, + "DryLevel": { + "Type": "Float32", + "Value": 0.0 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Feedback": { + "Type": "Float32", + "Value": 0.5 + }, + "Priority": { + "Type": "Int32", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "WetLevel": { + "Type": "Float32", + "Value": 0.0 + } + } + }, + "EmotesPages": { + "Name": "EmotesPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "InventoryPages", + "Properties": {}, + "DefaultProperties": {} + }, + "EqualizerSoundEffect": { + "Name": "EqualizerSoundEffect", + "Tags": [], + "Superclass": "SoundEffect", + "Properties": { + "HighGain": { + "Name": "HighGain", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LowGain": { + "Name": "LowGain", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MidGain": { + "Name": "MidGain", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "HighGain": { + "Type": "Float32", + "Value": 0.0 + }, + "LowGain": { + "Type": "Float32", + "Value": -20.0 + }, + "MidGain": { + "Type": "Float32", + "Value": -10.0 + }, + "Priority": { + "Type": "Int32", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "EventIngestService": { + "Name": "EventIngestService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Explosion": { + "Name": "Explosion", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "BlastPressure": { + "Name": "BlastPressure", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BlastRadius": { + "Name": "BlastRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DestroyJointRadiusPercent": { + "Name": "DestroyJointRadiusPercent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ExplosionType": { + "Name": "ExplosionType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ExplosionType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Position": { + "Name": "Position", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Visible": { + "Name": "Visible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BlastPressure": { + "Type": "Float32", + "Value": 500000.0 + }, + "BlastRadius": { + "Type": "Float32", + "Value": 4.0 + }, + "DestroyJointRadiusPercent": { + "Type": "Float32", + "Value": 1.0 + }, + "ExplosionType": { + "Type": "Enum", + "Value": 1 + }, + "Position": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Visible": { + "Type": "Bool", + "Value": true + } + } + }, + "FaceInstance": { + "Name": "FaceInstance", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Face": { + "Name": "Face", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "NormalId" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "Feature": { + "Name": "Feature", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "FaceId": { + "Name": "FaceId", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "NormalId" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InOut": { + "Name": "InOut", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "InOut" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeftRight": { + "Name": "LeftRight", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "LeftRight" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TopBottom": { + "Name": "TopBottom", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TopBottom" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "File": { + "Name": "File", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "FileName": { + "Name": "FileName", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FileSize": { + "Name": "FileSize", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Size": { + "Name": "Size", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "FileMesh": { + "Name": "FileMesh", + "Tags": [], + "Superclass": "DataModelMesh", + "Properties": { + "MeshId": { + "Name": "MeshId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextureId": { + "Name": "TextureId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "MeshId": { + "Type": "Content", + "Value": "" + }, + "Offset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Scale": { + "Type": "Vector3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TextureId": { + "Type": "Content", + "Value": "" + }, + "VertexColor": { + "Type": "Vector3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + } + } + }, + "Fire": { + "Name": "Fire", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Heat": { + "Name": "Heat", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "heat_xml" + } + } + } + }, + "SecondaryColor": { + "Name": "SecondaryColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "size_xml" + } + } + } + }, + "heat_xml": { + "Name": "heat_xml", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "Heat" + } + } + }, + "size": { + "Name": "size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "Size" + } + } + }, + "size_xml": { + "Name": "size_xml", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "Size" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Color3", + "Value": [ + 0.92549026, + 0.54509807, + 0.27450982 + ] + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Heat": { + "Type": "Float32", + "Value": 9.0 + }, + "SecondaryColor": { + "Type": "Color3", + "Value": [ + 0.54509807, + 0.3137255, + 0.21568629 + ] + }, + "Size": { + "Type": "Float32", + "Value": 5.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Flag": { + "Name": "Flag", + "Tags": [ + "Deprecated" + ], + "Superclass": "Tool", + "Properties": { + "TeamColor": { + "Name": "TeamColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CanBeDropped": { + "Type": "Bool", + "Value": true + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Grip": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ManualActivationOnly": { + "Type": "Bool", + "Value": false + }, + "RequiresHandle": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TeamColor": { + "Type": "Int32", + "Value": 194 + }, + "TextureId": { + "Type": "Content", + "Value": "" + }, + "ToolTip": { + "Type": "String", + "Value": "" + } + } + }, + "FlagStand": { + "Name": "FlagStand", + "Tags": [ + "Deprecated" + ], + "Superclass": "Part", + "Properties": { + "TeamColor": { + "Name": "TeamColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Anchored": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 4 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 163, + 162, + 165 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "FormFactor": { + "Type": "Enum", + "Value": 1 + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Shape": { + "Type": "Enum", + "Value": 1 + }, + "Size": { + "Type": "Vector3", + "Value": [ + 4.0, + 1.2, + 2.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TeamColor": { + "Type": "Int32", + "Value": 194 + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 3 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "FlagStandService": { + "Name": "FlagStandService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "FlangeSoundEffect": { + "Name": "FlangeSoundEffect", + "Tags": [], + "Superclass": "SoundEffect", + "Properties": { + "Depth": { + "Name": "Depth", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Mix": { + "Name": "Mix", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Rate": { + "Name": "Rate", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Depth": { + "Type": "Float32", + "Value": 0.45 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Mix": { + "Type": "Float32", + "Value": 0.85 + }, + "Priority": { + "Type": "Int32", + "Value": 0 + }, + "Rate": { + "Type": "Float32", + "Value": 5.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "FloorWire": { + "Name": "FloorWire", + "Tags": [ + "Deprecated" + ], + "Superclass": "GuiBase3d", + "Properties": { + "CycleOffset": { + "Name": "CycleOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "From": { + "Name": "From", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StudsBetweenTextures": { + "Name": "StudsBetweenTextures", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Texture": { + "Name": "Texture", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextureSize": { + "Name": "TextureSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "To": { + "Name": "To", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Velocity": { + "Name": "Velocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WireRadius": { + "Name": "WireRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "CycleOffset": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "StudsBetweenTextures": { + "Type": "Float32", + "Value": 4.0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Texture": { + "Type": "Content", + "Value": "" + }, + "TextureSize": { + "Type": "Vector2", + "Value": [ + 1.0, + 1.0 + ] + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Velocity": { + "Type": "Float32", + "Value": 2.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "WireRadius": { + "Type": "Float32", + "Value": 0.0625 + } + } + }, + "FlyweightService": { + "Name": "FlyweightService", + "Tags": [ + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Folder": { + "Name": "Folder", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ForceField": { + "Name": "ForceField", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Visible": { + "Name": "Visible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Visible": { + "Type": "Bool", + "Value": true + } + } + }, + "FormFactorPart": { + "Name": "FormFactorPart", + "Tags": [ + "NotCreatable" + ], + "Superclass": "BasePart", + "Properties": { + "FormFactor": { + "Name": "FormFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "FormFactor" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "formFactorRaw" + } + } + } + }, + "formFactor": { + "Name": "formFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "FormFactor" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "FormFactor" + } + } + }, + "formFactorRaw": { + "Name": "formFactorRaw", + "Scriptability": "None", + "DataType": { + "Enum": "FormFactor" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "FormFactor" + } + } + } + }, + "DefaultProperties": {} + }, + "Frame": { + "Name": "Frame", + "Tags": [], + "Superclass": "GuiObject", + "Properties": { + "Style": { + "Name": "Style", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "FrameStyle" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Type": "Bool", + "Value": false + }, + "AnchorPoint": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "AutomaticSize": { + "Type": "Enum", + "Value": 0 + }, + "BackgroundColor3": { + "Type": "Color3", + "Value": [ + 0.6392157, + 0.63529414, + 0.64705884 + ] + }, + "BackgroundTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "BorderColor3": { + "Type": "Color3", + "Value": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "BorderMode": { + "Type": "Enum", + "Value": 0 + }, + "BorderSizePixel": { + "Type": "Int32", + "Value": 1 + }, + "ClipsDescendants": { + "Type": "Bool", + "Value": false + }, + "Draggable": { + "Type": "Bool", + "Value": false + }, + "LayoutOrder": { + "Type": "Int32", + "Value": 0 + }, + "Position": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "Rotation": { + "Type": "Float32", + "Value": 0.0 + }, + "Selectable": { + "Type": "Bool", + "Value": false + }, + "Size": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SizeConstraint": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Style": { + "Type": "Enum", + "Value": 0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": 1 + } + } + }, + "FriendPages": { + "Name": "FriendPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, + "FriendService": { + "Name": "FriendService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "FunctionalTest": { + "Name": "FunctionalTest", + "Tags": [ + "Deprecated" + ], + "Superclass": "Instance", + "Properties": { + "Description": { + "Name": "Description", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Description": { + "Type": "String", + "Value": "?" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "GamePassService": { + "Name": "GamePassService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "GameSettings": { + "Name": "GameSettings", + "Tags": [ + "NotBrowsable", + "NotCreatable", + "Settings" + ], + "Superclass": "Instance", + "Properties": { + "AdditionalCoreIncludeDirs": { + "Name": "AdditionalCoreIncludeDirs", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OverrideStarterScript": { + "Name": "OverrideStarterScript", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VideoCaptureEnabled": { + "Name": "VideoCaptureEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VideoRecording": { + "Name": "VideoRecording", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "GamepadService": { + "Name": "GamepadService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "GamepadCursorEnabled": { + "Name": "GamepadCursorEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "GenericSettings": { + "Name": "GenericSettings", + "Tags": [ + "NotCreatable" + ], + "Superclass": "ServiceProvider", + "Properties": {}, + "DefaultProperties": {} + }, + "Geometry": { + "Name": "Geometry", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "GetDataStoreOptions": { + "Name": "GetDataStoreOptions", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "AllScopes": { + "Name": "AllScopes", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "GlobalDataStore": { + "Name": "GlobalDataStore", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "GlobalSettings": { + "Name": "GlobalSettings", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "GenericSettings", + "Properties": {}, + "DefaultProperties": {} + }, + "Glue": { + "Name": "Glue", + "Tags": [ + "Deprecated" + ], + "Superclass": "JointInstance", + "Properties": { + "F0": { + "Name": "F0", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "F1": { + "Name": "F1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "F2": { + "Name": "F2", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "F3": { + "Name": "F3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "C0": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "C1": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "F0": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "F1": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "F2": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "F3": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "GoogleAnalyticsConfiguration": { + "Name": "GoogleAnalyticsConfiguration", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "GroupService": { + "Name": "GroupService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "GuiBase": { + "Name": "GuiBase", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "GuiBase2d": { + "Name": "GuiBase2d", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "GuiBase", + "Properties": { + "AbsolutePosition": { + "Name": "AbsolutePosition", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AbsoluteRotation": { + "Name": "AbsoluteRotation", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AbsoluteSize": { + "Name": "AbsoluteSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AutoLocalize": { + "Name": "AutoLocalize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClippedRect": { + "Name": "ClippedRect", + "Scriptability": "Read", + "DataType": { + "Value": "Rect" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsNotOccluded": { + "Name": "IsNotOccluded", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Localize": { + "Name": "Localize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RawRect2D": { + "Name": "RawRect2D", + "Scriptability": "Read", + "DataType": { + "Value": "Rect" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RootLocalizationTable": { + "Name": "RootLocalizationTable", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TotalGroupScale": { + "Name": "TotalGroupScale", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "GuiBase3d": { + "Name": "GuiBase3d", + "Tags": [ + "NotCreatable" + ], + "Superclass": "GuiBase", + "Properties": { + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Color3": { + "Name": "Color3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Transparency": { + "Name": "Transparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Visible": { + "Name": "Visible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "GuiButton": { + "Name": "GuiButton", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "GuiObject", + "Properties": { + "AutoButtonColor": { + "Name": "AutoButtonColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Modal": { + "Name": "Modal", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Selected": { + "Name": "Selected", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Style": { + "Name": "Style", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ButtonStyle" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "GuiLabel": { + "Name": "GuiLabel", + "Tags": [ + "NotCreatable" + ], + "Superclass": "GuiObject", + "Properties": {}, + "DefaultProperties": {} + }, + "GuiMain": { + "Name": "GuiMain", + "Tags": [ + "Deprecated" + ], + "Superclass": "ScreenGui", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "DisplayOrder": { + "Type": "Int32", + "Value": 0 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "IgnoreGuiInset": { + "Type": "Bool", + "Value": false + }, + "ResetOnSpawn": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "ZIndexBehavior": { + "Type": "Enum", + "Value": 0 + } + } + }, + "GuiObject": { + "Name": "GuiObject", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "GuiBase2d", + "Properties": { + "Active": { + "Name": "Active", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AnchorPoint": { + "Name": "AnchorPoint", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AutomaticSize": { + "Name": "AutomaticSize", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AutomaticSize" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BackgroundColor": { + "Name": "BackgroundColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "BackgroundColor3": { + "Name": "BackgroundColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BackgroundTransparency": { + "Name": "BackgroundTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BorderColor": { + "Name": "BorderColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "BorderColor3": { + "Name": "BorderColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BorderMode": { + "Name": "BorderMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "BorderMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BorderSizePixel": { + "Name": "BorderSizePixel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClipsDescendants": { + "Name": "ClipsDescendants", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Draggable": { + "Name": "Draggable", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LayoutOrder": { + "Name": "LayoutOrder", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NextSelectionDown": { + "Name": "NextSelectionDown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NextSelectionLeft": { + "Name": "NextSelectionLeft", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NextSelectionRight": { + "Name": "NextSelectionRight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NextSelectionUp": { + "Name": "NextSelectionUp", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Position": { + "Name": "Position", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Rotation": { + "Name": "Rotation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Selectable": { + "Name": "Selectable", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SelectionImageObject": { + "Name": "SelectionImageObject", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SizeConstraint": { + "Name": "SizeConstraint", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SizeConstraint" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Transparency": { + "Name": "Transparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Visible": { + "Name": "Visible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ZIndex": { + "Name": "ZIndex", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "GuiService": { + "Name": "GuiService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "AutoSelectGuiEnabled": { + "Name": "AutoSelectGuiEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CoreEffectFolder": { + "Name": "CoreEffectFolder", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CoreGuiFolder": { + "Name": "CoreGuiFolder", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CoreGuiNavigationEnabled": { + "Name": "CoreGuiNavigationEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GuiNavigationEnabled": { + "Name": "GuiNavigationEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsModalDialog": { + "Name": "IsModalDialog", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsWindows": { + "Name": "IsWindows", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MenuIsOpen": { + "Name": "MenuIsOpen", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SelectedCoreObject": { + "Name": "SelectedCoreObject", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SelectedObject": { + "Name": "SelectedObject", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "GuidRegistryService": { + "Name": "GuidRegistryService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "HandleAdornment": { + "Name": "HandleAdornment", + "Tags": [ + "NotCreatable" + ], + "Superclass": "PVAdornment", + "Properties": { + "AdornCullingMode": { + "Name": "AdornCullingMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AdornCullingMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AlwaysOnTop": { + "Name": "AlwaysOnTop", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CFrame": { + "Name": "CFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SizeRelativeOffset": { + "Name": "SizeRelativeOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ZIndex": { + "Name": "ZIndex", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "Handles": { + "Name": "Handles", + "Tags": [], + "Superclass": "HandlesBase", + "Properties": { + "Faces": { + "Name": "Faces", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Faces" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Style": { + "Name": "Style", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "HandlesStyle" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "Faces": { + "Type": "Faces", + "Value": [ + "Right", + "Top", + "Back", + "Left", + "Bottom", + "Front" + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Style": { + "Type": "Enum", + "Value": 0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + } + } + }, + "HandlesBase": { + "Name": "HandlesBase", + "Tags": [ + "NotCreatable" + ], + "Superclass": "PartAdornment", + "Properties": {}, + "DefaultProperties": {} + }, + "HapticService": { + "Name": "HapticService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Hat": { + "Name": "Hat", + "Tags": [ + "Deprecated" + ], + "Superclass": "Accoutrement", + "Properties": {}, + "DefaultProperties": { + "AttachmentPoint": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "HeightmapImporterService": { + "Name": "HeightmapImporterService", + "Tags": [ + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "HingeConstraint": { + "Name": "HingeConstraint", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "ActuatorType": { + "Name": "ActuatorType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ActuatorType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AngularSpeed": { + "Name": "AngularSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AngularVelocity": { + "Name": "AngularVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CurrentAngle": { + "Name": "CurrentAngle", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LimitsEnabled": { + "Name": "LimitsEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LowerAngle": { + "Name": "LowerAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MotorMaxAcceleration": { + "Name": "MotorMaxAcceleration", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MotorMaxTorque": { + "Name": "MotorMaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Radius": { + "Name": "Radius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Restitution": { + "Name": "Restitution", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ServoMaxTorque": { + "Name": "ServoMaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TargetAngle": { + "Name": "TargetAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UpperAngle": { + "Name": "UpperAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "ActuatorType": { + "Type": "Enum", + "Value": 0 + }, + "AngularSpeed": { + "Type": "Float32", + "Value": 0.0 + }, + "AngularVelocity": { + "Type": "Float32", + "Value": 0.0 + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Int32", + "Value": 1009 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "LimitsEnabled": { + "Type": "Bool", + "Value": false + }, + "LowerAngle": { + "Type": "Float32", + "Value": -45.0 + }, + "MotorMaxAcceleration": { + "Type": "Float32", + "Value": null + }, + "MotorMaxTorque": { + "Type": "Float32", + "Value": 0.0 + }, + "Radius": { + "Type": "Float32", + "Value": 0.15 + }, + "Restitution": { + "Type": "Float32", + "Value": 0.0 + }, + "ServoMaxTorque": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TargetAngle": { + "Type": "Float32", + "Value": 0.0 + }, + "UpperAngle": { + "Type": "Float32", + "Value": 45.0 + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "Hint": { + "Name": "Hint", + "Tags": [ + "Deprecated" + ], + "Superclass": "Message", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Text": { + "Type": "String", + "Value": "" + } + } + }, + "Hole": { + "Name": "Hole", + "Tags": [ + "Deprecated" + ], + "Superclass": "Feature", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "FaceId": { + "Type": "Enum", + "Value": 0 + }, + "InOut": { + "Type": "Enum", + "Value": 2 + }, + "LeftRight": { + "Type": "Enum", + "Value": 1 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TopBottom": { + "Type": "Enum", + "Value": 1 + } + } + }, + "Hopper": { + "Name": "Hopper", + "Tags": [ + "Deprecated", + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "HopperBin": { + "Name": "HopperBin", + "Tags": [ + "Deprecated" + ], + "Superclass": "BackpackItem", + "Properties": { + "Active": { + "Name": "Active", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BinType": { + "Name": "BinType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "BinType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BinType": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TextureId": { + "Type": "Content", + "Value": "" + } + } + }, + "HttpRbxApiService": { + "Name": "HttpRbxApiService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "HttpRequest": { + "Name": "HttpRequest", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "HttpService": { + "Name": "HttpService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "HttpEnabled": { + "Name": "HttpEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "HttpEnabled": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Humanoid": { + "Name": "Humanoid", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "AutoJumpEnabled": { + "Name": "AutoJumpEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AutoRotate": { + "Name": "AutoRotate", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AutomaticScalingEnabled": { + "Name": "AutomaticScalingEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BreakJointsOnDeath": { + "Name": "BreakJointsOnDeath", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraOffset": { + "Name": "CameraOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CollisionType": { + "Name": "CollisionType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "HumanoidCollisionType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DisplayDistanceType": { + "Name": "DisplayDistanceType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "HumanoidDisplayDistanceType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DisplayName": { + "Name": "DisplayName", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FloorMaterial": { + "Name": "FloorMaterial", + "Scriptability": "Read", + "DataType": { + "Enum": "Material" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Health": { + "Name": "Health", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "HealthDisplayDistance": { + "Name": "HealthDisplayDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HealthDisplayType": { + "Name": "HealthDisplayType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "HumanoidHealthDisplayType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HipHeight": { + "Name": "HipHeight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Jump": { + "Name": "Jump", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "JumpHeight": { + "Name": "JumpHeight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "JumpPower": { + "Name": "JumpPower", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeftLeg": { + "Name": "LeftLeg", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MaxHealth": { + "Name": "MaxHealth", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxSlopeAngle": { + "Name": "MaxSlopeAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MoveDirection": { + "Name": "MoveDirection", + "Scriptability": "Read", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "NameDisplayDistance": { + "Name": "NameDisplayDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NameOcclusion": { + "Name": "NameOcclusion", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "NameOcclusion" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlatformStand": { + "Name": "PlatformStand", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RequiresNeck": { + "Name": "RequiresNeck", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RigType": { + "Name": "RigType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "HumanoidRigType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RightLeg": { + "Name": "RightLeg", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RootPart": { + "Name": "RootPart", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SeatPart": { + "Name": "SeatPart", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Sit": { + "Name": "Sit", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TargetPoint": { + "Name": "TargetPoint", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Torso": { + "Name": "Torso", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UseJumpPower": { + "Name": "UseJumpPower", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WalkSpeed": { + "Name": "WalkSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WalkToPart": { + "Name": "WalkToPart", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WalkToPoint": { + "Name": "WalkToPoint", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "maxHealth": { + "Name": "maxHealth", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoJumpEnabled": { + "Type": "Bool", + "Value": true + }, + "AutoRotate": { + "Type": "Bool", + "Value": true + }, + "AutomaticScalingEnabled": { + "Type": "Bool", + "Value": true + }, + "BreakJointsOnDeath": { + "Type": "Bool", + "Value": true + }, + "CollisionType": { + "Type": "Enum", + "Value": 0 + }, + "DisplayDistanceType": { + "Type": "Enum", + "Value": 0 + }, + "DisplayName": { + "Type": "String", + "Value": "" + }, + "HealthDisplayDistance": { + "Type": "Float32", + "Value": 100.0 + }, + "HealthDisplayType": { + "Type": "Enum", + "Value": 0 + }, + "HipHeight": { + "Type": "Float32", + "Value": 0.0 + }, + "JumpHeight": { + "Type": "Float32", + "Value": 7.2 + }, + "JumpPower": { + "Type": "Float32", + "Value": 50.0 + }, + "MaxHealth": { + "Type": "Float32", + "Value": 100.0 + }, + "MaxSlopeAngle": { + "Type": "Float32", + "Value": 89.0 + }, + "NameDisplayDistance": { + "Type": "Float32", + "Value": 100.0 + }, + "NameOcclusion": { + "Type": "Enum", + "Value": 2 + }, + "RequiresNeck": { + "Type": "Bool", + "Value": true + }, + "RigType": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "UseJumpPower": { + "Type": "Bool", + "Value": true + }, + "WalkSpeed": { + "Type": "Float32", + "Value": 16.0 + } + } + }, + "HumanoidController": { + "Name": "HumanoidController", + "Tags": [], + "Superclass": "Controller", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "HumanoidDescription": { + "Name": "HumanoidDescription", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "BackAccessory": { + "Name": "BackAccessory", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BodyTypeScale": { + "Name": "BodyTypeScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClimbAnimation": { + "Name": "ClimbAnimation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DepthScale": { + "Name": "DepthScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Face": { + "Name": "Face", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FaceAccessory": { + "Name": "FaceAccessory", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FallAnimation": { + "Name": "FallAnimation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FrontAccessory": { + "Name": "FrontAccessory", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GraphicTShirt": { + "Name": "GraphicTShirt", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HairAccessory": { + "Name": "HairAccessory", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HatAccessory": { + "Name": "HatAccessory", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Head": { + "Name": "Head", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HeadColor": { + "Name": "HeadColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HeadScale": { + "Name": "HeadScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HeightScale": { + "Name": "HeightScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IdleAnimation": { + "Name": "IdleAnimation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "JumpAnimation": { + "Name": "JumpAnimation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeftArm": { + "Name": "LeftArm", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeftArmColor": { + "Name": "LeftArmColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeftLeg": { + "Name": "LeftLeg", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeftLegColor": { + "Name": "LeftLegColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NeckAccessory": { + "Name": "NeckAccessory", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NumberEmotesLoaded": { + "Name": "NumberEmotesLoaded", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Pants": { + "Name": "Pants", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ProportionScale": { + "Name": "ProportionScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RightArm": { + "Name": "RightArm", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RightArmColor": { + "Name": "RightArmColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RightLeg": { + "Name": "RightLeg", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RightLegColor": { + "Name": "RightLegColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RunAnimation": { + "Name": "RunAnimation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Shirt": { + "Name": "Shirt", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShouldersAccessory": { + "Name": "ShouldersAccessory", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SwimAnimation": { + "Name": "SwimAnimation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Torso": { + "Name": "Torso", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TorsoColor": { + "Name": "TorsoColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WaistAccessory": { + "Name": "WaistAccessory", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WalkAnimation": { + "Name": "WalkAnimation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WidthScale": { + "Name": "WidthScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackAccessory": { + "Type": "String", + "Value": "" + }, + "BodyTypeScale": { + "Type": "Float32", + "Value": 0.3 + }, + "ClimbAnimation": { + "Type": "Int64", + "Value": 0 + }, + "DepthScale": { + "Type": "Float32", + "Value": 1.0 + }, + "Face": { + "Type": "Int64", + "Value": 0 + }, + "FaceAccessory": { + "Type": "String", + "Value": "" + }, + "FallAnimation": { + "Type": "Int64", + "Value": 0 + }, + "FrontAccessory": { + "Type": "String", + "Value": "" + }, + "GraphicTShirt": { + "Type": "Int64", + "Value": 0 + }, + "HairAccessory": { + "Type": "String", + "Value": "" + }, + "HatAccessory": { + "Type": "String", + "Value": "" + }, + "Head": { + "Type": "Int64", + "Value": 0 + }, + "HeadColor": { + "Type": "Color3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "HeadScale": { + "Type": "Float32", + "Value": 1.0 + }, + "HeightScale": { + "Type": "Float32", + "Value": 1.0 + }, + "IdleAnimation": { + "Type": "Int64", + "Value": 0 + }, + "JumpAnimation": { + "Type": "Int64", + "Value": 0 + }, + "LeftArm": { + "Type": "Int64", + "Value": 0 + }, + "LeftArmColor": { + "Type": "Color3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "LeftLeg": { + "Type": "Int64", + "Value": 0 + }, + "LeftLegColor": { + "Type": "Color3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "NeckAccessory": { + "Type": "String", + "Value": "" + }, + "Pants": { + "Type": "Int64", + "Value": 0 + }, + "ProportionScale": { + "Type": "Float32", + "Value": 1.0 + }, + "RightArm": { + "Type": "Int64", + "Value": 0 + }, + "RightArmColor": { + "Type": "Color3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "RightLeg": { + "Type": "Int64", + "Value": 0 + }, + "RightLegColor": { + "Type": "Color3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "RunAnimation": { + "Type": "Int64", + "Value": 0 + }, + "Shirt": { + "Type": "Int64", + "Value": 0 + }, + "ShouldersAccessory": { + "Type": "String", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "SwimAnimation": { + "Type": "Int64", + "Value": 0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Torso": { + "Type": "Int64", + "Value": 0 + }, + "TorsoColor": { + "Type": "Color3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "WaistAccessory": { + "Type": "String", + "Value": "" + }, + "WalkAnimation": { + "Type": "Int64", + "Value": 0 + }, + "WidthScale": { + "Type": "Float32", + "Value": 1.0 + } + } + }, + "ILegacyStudioBridge": { + "Name": "ILegacyStudioBridge", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "IXPService": { + "Name": "IXPService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "ImageButton": { + "Name": "ImageButton", + "Tags": [], + "Superclass": "GuiButton", + "Properties": { + "HoverImage": { + "Name": "HoverImage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Image": { + "Name": "Image", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImageColor3": { + "Name": "ImageColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImageRectOffset": { + "Name": "ImageRectOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImageRectSize": { + "Name": "ImageRectSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImageTransparency": { + "Name": "ImageTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsLoaded": { + "Name": "IsLoaded", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PressedImage": { + "Name": "PressedImage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ScaleType": { + "Name": "ScaleType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ScaleType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SliceCenter": { + "Name": "SliceCenter", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Rect" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SliceScale": { + "Name": "SliceScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TileSize": { + "Name": "TileSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Type": "Bool", + "Value": true + }, + "AnchorPoint": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoButtonColor": { + "Type": "Bool", + "Value": true + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "AutomaticSize": { + "Type": "Enum", + "Value": 0 + }, + "BackgroundColor3": { + "Type": "Color3", + "Value": [ + 0.6392157, + 0.63529414, + 0.64705884 + ] + }, + "BackgroundTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "BorderColor3": { + "Type": "Color3", + "Value": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "BorderMode": { + "Type": "Enum", + "Value": 0 + }, + "BorderSizePixel": { + "Type": "Int32", + "Value": 1 + }, + "ClipsDescendants": { + "Type": "Bool", + "Value": false + }, + "Draggable": { + "Type": "Bool", + "Value": false + }, + "HoverImage": { + "Type": "Content", + "Value": "" + }, + "Image": { + "Type": "Content", + "Value": "" + }, + "ImageColor3": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "ImageRectOffset": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "ImageRectSize": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "ImageTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "LayoutOrder": { + "Type": "Int32", + "Value": 0 + }, + "Modal": { + "Type": "Bool", + "Value": false + }, + "Position": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "PressedImage": { + "Type": "Content", + "Value": "" + }, + "Rotation": { + "Type": "Float32", + "Value": 0.0 + }, + "ScaleType": { + "Type": "Enum", + "Value": 0 + }, + "Selectable": { + "Type": "Bool", + "Value": true + }, + "Selected": { + "Type": "Bool", + "Value": false + }, + "Size": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SizeConstraint": { + "Type": "Enum", + "Value": 0 + }, + "SliceCenter": { + "Type": "Rect", + "Value": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 0.0 + ] + ] + }, + "SliceScale": { + "Type": "Float32", + "Value": 1.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Style": { + "Type": "Enum", + "Value": 0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TileSize": { + "Type": "UDim2", + "Value": [ + [ + 1.0, + 0 + ], + [ + 1.0, + 0 + ] + ] + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": 1 + } + } + }, + "ImageHandleAdornment": { + "Name": "ImageHandleAdornment", + "Tags": [], + "Superclass": "HandleAdornment", + "Properties": { + "Image": { + "Name": "Image", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AdornCullingMode": { + "Type": "Enum", + "Value": 0 + }, + "AlwaysOnTop": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.9490197, + 0.95294124, + 0.95294124 + ] + }, + "Image": { + "Type": "Content", + "Value": "rbxasset://textures/SurfacesDefault.png" + }, + "Size": { + "Type": "Vector2", + "Value": [ + 1.0, + 1.0 + ] + }, + "SizeRelativeOffset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": -1 + } + } + }, + "ImageLabel": { + "Name": "ImageLabel", + "Tags": [], + "Superclass": "GuiLabel", + "Properties": { + "Image": { + "Name": "Image", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImageColor3": { + "Name": "ImageColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImageRectOffset": { + "Name": "ImageRectOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImageRectSize": { + "Name": "ImageRectSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImageTransparency": { + "Name": "ImageTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsLoaded": { + "Name": "IsLoaded", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ScaleType": { + "Name": "ScaleType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ScaleType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SliceCenter": { + "Name": "SliceCenter", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Rect" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SliceScale": { + "Name": "SliceScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TileSize": { + "Name": "TileSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Type": "Bool", + "Value": false + }, + "AnchorPoint": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "AutomaticSize": { + "Type": "Enum", + "Value": 0 + }, + "BackgroundColor3": { + "Type": "Color3", + "Value": [ + 0.6392157, + 0.63529414, + 0.64705884 + ] + }, + "BackgroundTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "BorderColor3": { + "Type": "Color3", + "Value": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "BorderMode": { + "Type": "Enum", + "Value": 0 + }, + "BorderSizePixel": { + "Type": "Int32", + "Value": 1 + }, + "ClipsDescendants": { + "Type": "Bool", + "Value": false + }, + "Draggable": { + "Type": "Bool", + "Value": false + }, + "Image": { + "Type": "Content", + "Value": "" + }, + "ImageColor3": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "ImageRectOffset": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "ImageRectSize": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "ImageTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "LayoutOrder": { + "Type": "Int32", + "Value": 0 + }, + "Position": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "Rotation": { + "Type": "Float32", + "Value": 0.0 + }, + "ScaleType": { + "Type": "Enum", + "Value": 0 + }, + "Selectable": { + "Type": "Bool", + "Value": false + }, + "Size": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SizeConstraint": { + "Type": "Enum", + "Value": 0 + }, + "SliceCenter": { + "Type": "Rect", + "Value": [ + [ + 0.0, + 0.0 + ], + [ + 0.0, + 0.0 + ] + ] + }, + "SliceScale": { + "Type": "Float32", + "Value": 1.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TileSize": { + "Type": "UDim2", + "Value": [ + [ + 1.0, + 0 + ], + [ + 1.0, + 0 + ] + ] + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": 1 + } + } + }, + "InputObject": { + "Name": "InputObject", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Delta": { + "Name": "Delta", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "KeyCode": { + "Name": "KeyCode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "KeyCode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Position": { + "Name": "Position", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UserInputState": { + "Name": "UserInputState", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "UserInputState" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UserInputType": { + "Name": "UserInputType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "UserInputType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "InsertService": { + "Name": "InsertService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "AllowClientInsertModels": { + "Name": "AllowClientInsertModels", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AllowInsertFreeModels": { + "Name": "AllowInsertFreeModels", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotBrowsable", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AllowClientInsertModels": { + "Type": "Bool", + "Value": false + }, + "AllowInsertFreeModels": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Instance": { + "Name": "Instance", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": null, + "Properties": { + "Archivable": { + "Name": "Archivable", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "archivable" + } + } + } + }, + "Attributes": { + "Name": "Attributes", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "AttributesSerialize" + } + } + } + }, + "AttributesSerialize": { + "Name": "AttributesSerialize", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClassName": { + "Name": "ClassName", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DataCost": { + "Name": "DataCost", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Name": { + "Name": "Name", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Parent": { + "Name": "Parent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RobloxLocked": { + "Name": "RobloxLocked", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SourceAssetId": { + "Name": "SourceAssetId", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Tags": { + "Name": "Tags", + "Scriptability": "Custom", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "archivable": { + "Name": "archivable", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "Archivable" + } + } + }, + "className": { + "Name": "className", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Alias": { + "AliasFor": "ClassName" + } + } + } + }, + "DefaultProperties": {} + }, + "InstanceAdornment": { + "Name": "InstanceAdornment", + "Tags": [ + "NotCreatable" + ], + "Superclass": "GuiBase3d", + "Properties": { + "Adornee": { + "Name": "Adornee", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "IntConstrainedValue": { + "Name": "IntConstrainedValue", + "Tags": [ + "Deprecated" + ], + "Superclass": "ValueBase", + "Properties": { + "ConstrainedValue": { + "Name": "ConstrainedValue", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MaxValue": { + "Name": "MaxValue", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MinValue": { + "Name": "MinValue", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "MaxValue": { + "Type": "Int64", + "Value": 10 + }, + "MinValue": { + "Type": "Int64", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "IntValue": { + "Name": "IntValue", + "Tags": [], + "Superclass": "ValueBase", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Value": { + "Type": "Int64", + "Value": 0 + } + } + }, + "InternalContainer": { + "Name": "InternalContainer", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "InventoryPages": { + "Name": "InventoryPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, + "JointInstance": { + "Name": "JointInstance", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Active": { + "Name": "Active", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "C0": { + "Name": "C0", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "C1": { + "Name": "C1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Part0": { + "Name": "Part0", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Part1": { + "Name": "Part1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "part1": { + "Name": "part1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "Part1" + } + } + } + }, + "DefaultProperties": {} + }, + "JointsService": { + "Name": "JointsService", + "Tags": [ + "Deprecated", + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "KeyboardService": { + "Name": "KeyboardService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Keyframe": { + "Name": "Keyframe", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Time": { + "Name": "Time", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Time": { + "Type": "Float32", + "Value": 0.0 + } + } + }, + "KeyframeMarker": { + "Name": "KeyframeMarker", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Value": { + "Type": "String", + "Value": "" + } + } + }, + "KeyframeSequence": { + "Name": "KeyframeSequence", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "AuthoredHipHeight": { + "Name": "AuthoredHipHeight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Loop": { + "Name": "Loop", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Priority": { + "Name": "Priority", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AnimationPriority" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AuthoredHipHeight": { + "Type": "Float32", + "Value": 2.0 + }, + "Loop": { + "Type": "Bool", + "Value": true + }, + "Priority": { + "Type": "Enum", + "Value": 2 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "KeyframeSequenceProvider": { + "Name": "KeyframeSequenceProvider", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "LanguageService": { + "Name": "LanguageService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "LayerCollector": { + "Name": "LayerCollector", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "GuiBase2d", + "Properties": { + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ResetOnSpawn": { + "Name": "ResetOnSpawn", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ZIndexBehavior": { + "Name": "ZIndexBehavior", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ZIndexBehavior" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "LegacyStudioBridge": { + "Name": "LegacyStudioBridge", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "ILegacyStudioBridge", + "Properties": {}, + "DefaultProperties": {} + }, + "Light": { + "Name": "Light", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Brightness": { + "Name": "Brightness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Shadows": { + "Name": "Shadows", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "Lighting": { + "Name": "Lighting", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "Ambient": { + "Name": "Ambient", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Brightness": { + "Name": "Brightness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClockTime": { + "Name": "ClockTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ColorShift_Bottom": { + "Name": "ColorShift_Bottom", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ColorShift_Top": { + "Name": "ColorShift_Top", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnvironmentDiffuseScale": { + "Name": "EnvironmentDiffuseScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnvironmentSpecularScale": { + "Name": "EnvironmentSpecularScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ExposureCompensation": { + "Name": "ExposureCompensation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FogColor": { + "Name": "FogColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FogEnd": { + "Name": "FogEnd", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FogStart": { + "Name": "FogStart", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GeographicLatitude": { + "Name": "GeographicLatitude", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GlobalShadows": { + "Name": "GlobalShadows", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OutdoorAmbient": { + "Name": "OutdoorAmbient", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Outlines": { + "Name": "Outlines", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShadowColor": { + "Name": "ShadowColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ShadowSoftness": { + "Name": "ShadowSoftness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Technology": { + "Name": "Technology", + "Scriptability": "None", + "DataType": { + "Enum": "Technology" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TimeOfDay": { + "Name": "TimeOfDay", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Ambient": { + "Type": "Color3", + "Value": [ + 0.5, + 0.5, + 0.5 + ] + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Brightness": { + "Type": "Float32", + "Value": 1.0 + }, + "ColorShift_Bottom": { + "Type": "Color3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "ColorShift_Top": { + "Type": "Color3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "EnvironmentDiffuseScale": { + "Type": "Float32", + "Value": 0.0 + }, + "EnvironmentSpecularScale": { + "Type": "Float32", + "Value": 0.0 + }, + "ExposureCompensation": { + "Type": "Float32", + "Value": 0.0 + }, + "FogColor": { + "Type": "Color3", + "Value": [ + 0.75, + 0.75, + 0.75 + ] + }, + "FogEnd": { + "Type": "Float32", + "Value": 100000.0 + }, + "FogStart": { + "Type": "Float32", + "Value": 0.0 + }, + "GeographicLatitude": { + "Type": "Float32", + "Value": 41.7333 + }, + "GlobalShadows": { + "Type": "Bool", + "Value": false + }, + "OutdoorAmbient": { + "Type": "Color3", + "Value": [ + 0.5, + 0.5, + 0.5 + ] + }, + "Outlines": { + "Type": "Bool", + "Value": true + }, + "ShadowSoftness": { + "Type": "Float32", + "Value": 0.5 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Technology": { + "Type": "Enum", + "Value": 2 + }, + "TimeOfDay": { + "Type": "String", + "Value": "14:00:00" + } + } + }, + "LineForce": { + "Name": "LineForce", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "ApplyAtCenterOfMass": { + "Name": "ApplyAtCenterOfMass", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InverseSquareLaw": { + "Name": "InverseSquareLaw", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Magnitude": { + "Name": "Magnitude", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxForce": { + "Name": "MaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReactionForceEnabled": { + "Name": "ReactionForceEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "ApplyAtCenterOfMass": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Int32", + "Value": 23 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "InverseSquareLaw": { + "Type": "Bool", + "Value": false + }, + "Magnitude": { + "Type": "Float32", + "Value": 1000.0 + }, + "MaxForce": { + "Type": "Float32", + "Value": null + }, + "ReactionForceEnabled": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "LineHandleAdornment": { + "Name": "LineHandleAdornment", + "Tags": [], + "Superclass": "HandleAdornment", + "Properties": { + "Length": { + "Name": "Length", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Thickness": { + "Name": "Thickness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AdornCullingMode": { + "Type": "Enum", + "Value": 0 + }, + "AlwaysOnTop": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "Length": { + "Type": "Float32", + "Value": 5.0 + }, + "SizeRelativeOffset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Thickness": { + "Type": "Float32", + "Value": 1.0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": -1 + } + } + }, + "LocalScript": { + "Name": "LocalScript", + "Tags": [], + "Superclass": "Script", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Disabled": { + "Type": "Bool", + "Value": false + }, + "LinkedSource": { + "Type": "Content", + "Value": "" + }, + "Source": { + "Type": "String", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "LocalStorageService": { + "Name": "LocalStorageService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "LocalizationService": { + "Name": "LocalizationService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "ForcePlayModeGameLocaleId": { + "Name": "ForcePlayModeGameLocaleId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ForcePlayModeRobloxLocaleId": { + "Name": "ForcePlayModeRobloxLocaleId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsTextScraperRunning": { + "Name": "IsTextScraperRunning", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RobloxForcePlayModeGameLocaleId": { + "Name": "RobloxForcePlayModeGameLocaleId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RobloxForcePlayModeRobloxLocaleId": { + "Name": "RobloxForcePlayModeRobloxLocaleId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RobloxLocaleId": { + "Name": "RobloxLocaleId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SystemLocaleId": { + "Name": "SystemLocaleId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "LocalizationTable": { + "Name": "LocalizationTable", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Contents": { + "Name": "Contents", + "Scriptability": "Custom", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DevelopmentLanguage": { + "Name": "DevelopmentLanguage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Root": { + "Name": "Root", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SourceLocaleId": { + "Name": "SourceLocaleId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Contents": { + "Type": "String", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "SourceLocaleId": { + "Type": "String", + "Value": "en-us" + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "LogService": { + "Name": "LogService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "LoginService": { + "Name": "LoginService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "LuaSettings": { + "Name": "LuaSettings", + "Tags": [ + "NotCreatable", + "Settings" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "LuaSourceContainer": { + "Name": "LuaSourceContainer", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "CurrentEditor": { + "Name": "CurrentEditor", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsDifferentFromFileSystem": { + "Name": "IsDifferentFromFileSystem", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "LuaWebService": { + "Name": "LuaWebService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ManualGlue": { + "Name": "ManualGlue", + "Tags": [], + "Superclass": "ManualSurfaceJointInstance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "C0": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "C1": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ManualSurfaceJointInstance": { + "Name": "ManualSurfaceJointInstance", + "Tags": [ + "NotCreatable" + ], + "Superclass": "JointInstance", + "Properties": {}, + "DefaultProperties": {} + }, + "ManualWeld": { + "Name": "ManualWeld", + "Tags": [], + "Superclass": "ManualSurfaceJointInstance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "C0": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "C1": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "MarketplaceService": { + "Name": "MarketplaceService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "MemStorageConnection": { + "Name": "MemStorageConnection", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "MemStorageService": { + "Name": "MemStorageService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "MeshContentProvider": { + "Name": "MeshContentProvider", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "CacheableContentProvider", + "Properties": {}, + "DefaultProperties": {} + }, + "MeshPart": { + "Name": "MeshPart", + "Tags": [], + "Superclass": "TriangleMeshPart", + "Properties": { + "DoubleSided": { + "Name": "DoubleSided", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HasJointOffset": { + "Name": "HasJointOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HasSkinnedMesh": { + "Name": "HasSkinnedMesh", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "JointOffset": { + "Name": "JointOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MeshID": { + "Name": "MeshID", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Deprecated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MeshId": { + "Name": "MeshId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MeshSize": { + "Name": "MeshSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RenderFidelity": { + "Name": "RenderFidelity", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RenderFidelity" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextureID": { + "Name": "TextureID", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Anchored": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 0 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 163, + 162, + 165 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "DoubleSided": { + "Type": "Bool", + "Value": false + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "HasJointOffset": { + "Type": "Bool", + "Value": false + }, + "HasSkinnedMesh": { + "Type": "Bool", + "Value": false + }, + "JointOffset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "MeshID": { + "Type": "Content", + "Value": "" + }, + "MeshId": { + "Type": "Content", + "Value": "" + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RenderFidelity": { + "Type": "Enum", + "Value": 1 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Size": { + "Type": "Vector3", + "Value": [ + 4.0, + 1.2, + 2.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TextureID": { + "Type": "Content", + "Value": "" + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 0 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "Message": { + "Name": "Message", + "Tags": [ + "Deprecated" + ], + "Superclass": "Instance", + "Properties": { + "Text": { + "Name": "Text", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Text": { + "Type": "String", + "Value": "" + } + } + }, + "MessagingService": { + "Name": "MessagingService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Model": { + "Name": "Model", + "Tags": [], + "Superclass": "PVInstance", + "Properties": { + "LevelOfDetail": { + "Name": "LevelOfDetail", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ModelLevelOfDetail" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PrimaryPart": { + "Name": "PrimaryPart", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "LevelOfDetail": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ModuleScript": { + "Name": "ModuleScript", + "Tags": [], + "Superclass": "LuaSourceContainer", + "Properties": { + "LinkedSource": { + "Name": "LinkedSource", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Source": { + "Name": "Source", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "LinkedSource": { + "Type": "Content", + "Value": "" + }, + "Source": { + "Type": "String", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Motor": { + "Name": "Motor", + "Tags": [], + "Superclass": "JointInstance", + "Properties": { + "CurrentAngle": { + "Name": "CurrentAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DesiredAngle": { + "Name": "DesiredAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxVelocity": { + "Name": "MaxVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "C0": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "C1": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "DesiredAngle": { + "Type": "Float32", + "Value": 0.0 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "MaxVelocity": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Motor6D": { + "Name": "Motor6D", + "Tags": [], + "Superclass": "Motor", + "Properties": { + "ChildName": { + "Name": "ChildName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "NotScriptable", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ParentName": { + "Name": "ParentName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "NotScriptable", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Transform": { + "Name": "Transform", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "C0": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "C1": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "DesiredAngle": { + "Type": "Float32", + "Value": 0.0 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "MaxVelocity": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "MotorFeature": { + "Name": "MotorFeature", + "Tags": [ + "Deprecated" + ], + "Superclass": "Feature", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "FaceId": { + "Type": "Enum", + "Value": 0 + }, + "InOut": { + "Type": "Enum", + "Value": 2 + }, + "LeftRight": { + "Type": "Enum", + "Value": 1 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TopBottom": { + "Type": "Enum", + "Value": 1 + } + } + }, + "Mouse": { + "Name": "Mouse", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Hit": { + "Name": "Hit", + "Scriptability": "Read", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Icon": { + "Name": "Icon", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Origin": { + "Name": "Origin", + "Scriptability": "Read", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Target": { + "Name": "Target", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TargetFilter": { + "Name": "TargetFilter", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TargetSurface": { + "Name": "TargetSurface", + "Scriptability": "Read", + "DataType": { + "Enum": "NormalId" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UnitRay": { + "Name": "UnitRay", + "Scriptability": "Read", + "DataType": { + "Value": "Ray" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ViewSizeX": { + "Name": "ViewSizeX", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ViewSizeY": { + "Name": "ViewSizeY", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "X": { + "Name": "X", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Y": { + "Name": "Y", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "hit": { + "Name": "hit", + "Scriptability": "Read", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "target": { + "Name": "target", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "MouseService": { + "Name": "MouseService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "MultipleDocumentInterfaceInstance": { + "Name": "MultipleDocumentInterfaceInstance", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "FocusedDataModelSession": { + "Name": "FocusedDataModelSession", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "NegateOperation": { + "Name": "NegateOperation", + "Tags": [], + "Superclass": "PartOperation", + "Properties": {}, + "DefaultProperties": { + "Anchored": { + "Type": "Bool", + "Value": true + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 0 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": false + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 255, + 255, + 255 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RenderFidelity": { + "Type": "Enum", + "Value": 1 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Size": { + "Type": "Vector3", + "Value": [ + 4.0, + 1.2, + 2.0 + ] + }, + "SmoothingAngle": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 0 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.1 + }, + "UsePartColor": { + "Type": "Bool", + "Value": false + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "NetworkClient": { + "Name": "NetworkClient", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "NetworkPeer", + "Properties": {}, + "DefaultProperties": {} + }, + "NetworkMarker": { + "Name": "NetworkMarker", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "NetworkPeer": { + "Name": "NetworkPeer", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "NetworkReplicator": { + "Name": "NetworkReplicator", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "NetworkServer": { + "Name": "NetworkServer", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "NetworkPeer", + "Properties": {}, + "DefaultProperties": {} + }, + "NetworkSettings": { + "Name": "NetworkSettings", + "Tags": [ + "NotBrowsable", + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "ExtraMemoryUsed": { + "Name": "ExtraMemoryUsed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FreeMemoryMBytes": { + "Name": "FreeMemoryMBytes", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "HttpProxyEnabled": { + "Name": "HttpProxyEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HttpProxyURL": { + "Name": "HttpProxyURL", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IncomingReplicationLag": { + "Name": "IncomingReplicationLag", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PrintJoinSizeBreakdown": { + "Name": "PrintJoinSizeBreakdown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PrintPhysicsErrors": { + "Name": "PrintPhysicsErrors", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PrintStreamInstanceQuota": { + "Name": "PrintStreamInstanceQuota", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RandomizeJoinInstanceOrder": { + "Name": "RandomizeJoinInstanceOrder", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RenderStreamedRegions": { + "Name": "RenderStreamedRegions", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShowActiveAnimationAsset": { + "Name": "ShowActiveAnimationAsset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TrackDataTypes": { + "Name": "TrackDataTypes", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TrackPhysicsDetails": { + "Name": "TrackPhysicsDetails", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "NoCollisionConstraint": { + "Name": "NoCollisionConstraint", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Part0": { + "Name": "Part0", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Part1": { + "Name": "Part1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "NonReplicatedCSGDictionaryService": { + "Name": "NonReplicatedCSGDictionaryService", + "Tags": [ + "Service" + ], + "Superclass": "FlyweightService", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "NotificationService": { + "Name": "NotificationService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "IsLuaChatEnabled": { + "Name": "IsLuaChatEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsLuaGameDetailsEnabled": { + "Name": "IsLuaGameDetailsEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SelectedTheme": { + "Name": "SelectedTheme", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "NumberPose": { + "Name": "NumberPose", + "Tags": [], + "Superclass": "PoseBase", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "EasingDirection": { + "Type": "Enum", + "Value": 0 + }, + "EasingStyle": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Value": { + "Type": "Float64", + "Value": 0.0 + }, + "Weight": { + "Type": "Float32", + "Value": 1.0 + } + } + }, + "NumberValue": { + "Name": "NumberValue", + "Tags": [], + "Superclass": "ValueBase", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Value": { + "Type": "Float64", + "Value": 0.0 + } + } + }, + "ObjectValue": { + "Name": "ObjectValue", + "Tags": [], + "Superclass": "ValueBase", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ObjectVersionInfo": { + "Name": "ObjectVersionInfo", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "CreatedTime": { + "Name": "CreatedTime", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsDeleted": { + "Name": "IsDeleted", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Version": { + "Name": "Version", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "OrderedDataStore": { + "Name": "OrderedDataStore", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "GlobalDataStore", + "Properties": {}, + "DefaultProperties": {} + }, + "OutfitPages": { + "Name": "OutfitPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, + "PVAdornment": { + "Name": "PVAdornment", + "Tags": [ + "NotCreatable" + ], + "Superclass": "GuiBase3d", + "Properties": { + "Adornee": { + "Name": "Adornee", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "PVInstance": { + "Name": "PVInstance", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "PackageLink": { + "Name": "PackageLink", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "AutoUpdate": { + "Name": "AutoUpdate", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PackageId": { + "Name": "PackageId", + "Scriptability": "Read", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Status": { + "Name": "Status", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "VersionNumber": { + "Name": "VersionNumber", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "PackageService": { + "Name": "PackageService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Pages": { + "Name": "Pages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "IsFinished": { + "Name": "IsFinished", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "Pants": { + "Name": "Pants", + "Tags": [], + "Superclass": "Clothing", + "Properties": { + "PantsTemplate": { + "Name": "PantsTemplate", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color3": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "PantsTemplate": { + "Type": "Content", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ParabolaAdornment": { + "Name": "ParabolaAdornment", + "Tags": [], + "Superclass": "PVAdornment", + "Properties": { + "A": { + "Name": "A", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "B": { + "Name": "B", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "C": { + "Name": "C", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Range": { + "Name": "Range", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Thickness": { + "Name": "Thickness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.9490197, + 0.95294124, + 0.95294124 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + } + } + }, + "Part": { + "Name": "Part", + "Tags": [], + "Superclass": "FormFactorPart", + "Properties": { + "Shape": { + "Name": "Shape", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "PartType" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "shape" + } + } + } + }, + "shape": { + "Name": "shape", + "Scriptability": "None", + "DataType": { + "Enum": "PartType" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "Shape" + } + } + } + }, + "DefaultProperties": { + "Anchored": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 4 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 163, + 162, + 165 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "FormFactor": { + "Type": "Enum", + "Value": 1 + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Shape": { + "Type": "Enum", + "Value": 1 + }, + "Size": { + "Type": "Vector3", + "Value": [ + 4.0, + 1.2, + 2.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 3 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "PartAdornment": { + "Name": "PartAdornment", + "Tags": [ + "NotCreatable" + ], + "Superclass": "GuiBase3d", + "Properties": { + "Adornee": { + "Name": "Adornee", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "PartOperation": { + "Name": "PartOperation", + "Tags": [], + "Superclass": "TriangleMeshPart", + "Properties": { + "RenderFidelity": { + "Name": "RenderFidelity", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RenderFidelity" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SmoothingAngle": { + "Name": "SmoothingAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TriangleCount": { + "Name": "TriangleCount", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UsePartColor": { + "Name": "UsePartColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Anchored": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 0 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 255, + 255, + 255 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RenderFidelity": { + "Type": "Enum", + "Value": 1 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Size": { + "Type": "Vector3", + "Value": [ + 4.0, + 1.2, + 2.0 + ] + }, + "SmoothingAngle": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 0 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "UsePartColor": { + "Type": "Bool", + "Value": false + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "PartOperationAsset": { + "Name": "PartOperationAsset", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ParticleEmitter": { + "Name": "ParticleEmitter", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Acceleration": { + "Name": "Acceleration", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "ColorSequence" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Drag": { + "Name": "Drag", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EmissionDirection": { + "Name": "EmissionDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "NormalId" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Lifetime": { + "Name": "Lifetime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LightEmission": { + "Name": "LightEmission", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LightInfluence": { + "Name": "LightInfluence", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LockedToPart": { + "Name": "LockedToPart", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Orientation": { + "Name": "Orientation", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ParticleOrientation" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Rate": { + "Name": "Rate", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RotSpeed": { + "Name": "RotSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Rotation": { + "Name": "Rotation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberSequence" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Speed": { + "Name": "Speed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SpreadAngle": { + "Name": "SpreadAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Texture": { + "Name": "Texture", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TimeScale": { + "Name": "TimeScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Transparency": { + "Name": "Transparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberSequence" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VelocityInheritance": { + "Name": "VelocityInheritance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VelocitySpread": { + "Name": "VelocitySpread", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ZOffset": { + "Name": "ZOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Acceleration": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "ColorSequence", + "Value": { + "Keypoints": [ + { + "Time": 0.0, + "Color": [ + 1.0, + 1.0, + 1.0 + ] + }, + { + "Time": 1.0, + "Color": [ + 1.0, + 1.0, + 1.0 + ] + } + ] + } + }, + "Drag": { + "Type": "Float32", + "Value": 0.0 + }, + "EmissionDirection": { + "Type": "Enum", + "Value": 1 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Lifetime": { + "Type": "NumberRange", + "Value": [ + 5.0, + 10.0 + ] + }, + "LightEmission": { + "Type": "Float32", + "Value": 0.0 + }, + "LightInfluence": { + "Type": "Float32", + "Value": 0.0 + }, + "LockedToPart": { + "Type": "Bool", + "Value": false + }, + "Orientation": { + "Type": "Enum", + "Value": 0 + }, + "Rate": { + "Type": "Float32", + "Value": 20.0 + }, + "RotSpeed": { + "Type": "NumberRange", + "Value": [ + 0.0, + 0.0 + ] + }, + "Rotation": { + "Type": "NumberRange", + "Value": [ + 0.0, + 0.0 + ] + }, + "Size": { + "Type": "NumberSequence", + "Value": { + "Keypoints": [ + { + "Time": 0.0, + "Value": 1.0, + "Envelope": 0.0 + }, + { + "Time": 1.0, + "Value": 1.0, + "Envelope": 0.0 + } + ] + } + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Speed": { + "Type": "NumberRange", + "Value": [ + 5.0, + 5.0 + ] + }, + "SpreadAngle": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Texture": { + "Type": "Content", + "Value": "rbxasset://textures/particles/sparkles_main.dds" + }, + "TimeScale": { + "Type": "Float32", + "Value": 1.0 + }, + "Transparency": { + "Type": "NumberSequence", + "Value": { + "Keypoints": [ + { + "Time": 0.0, + "Value": 0.0, + "Envelope": 0.0 + }, + { + "Time": 1.0, + "Value": 0.0, + "Envelope": 0.0 + } + ] + } + }, + "VelocityInheritance": { + "Type": "Float32", + "Value": 0.0 + }, + "ZOffset": { + "Type": "Float32", + "Value": 0.0 + } + } + }, + "Path": { + "Name": "Path", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Status": { + "Name": "Status", + "Scriptability": "Read", + "DataType": { + "Enum": "PathStatus" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "PathfindingService": { + "Name": "PathfindingService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "EmptyCutoff": { + "Name": "EmptyCutoff", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "PermissionsService": { + "Name": "PermissionsService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "PhysicsService": { + "Name": "PhysicsService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "PhysicsSettings": { + "Name": "PhysicsSettings", + "Tags": [ + "NotCreatable", + "Settings" + ], + "Superclass": "Instance", + "Properties": { + "AllowSleep": { + "Name": "AllowSleep", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreAnchorsShown": { + "Name": "AreAnchorsShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreAssembliesShown": { + "Name": "AreAssembliesShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreAwakePartsHighlighted": { + "Name": "AreAwakePartsHighlighted", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreBodyTypesShown": { + "Name": "AreBodyTypesShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreContactIslandsShown": { + "Name": "AreContactIslandsShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreContactPointsShown": { + "Name": "AreContactPointsShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreJointCoordinatesShown": { + "Name": "AreJointCoordinatesShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreMechanismsShown": { + "Name": "AreMechanismsShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreModelCoordsShown": { + "Name": "AreModelCoordsShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreOwnersShown": { + "Name": "AreOwnersShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ArePartCoordsShown": { + "Name": "ArePartCoordsShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreRegionsShown": { + "Name": "AreRegionsShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreTerrainReplicationRegionsShown": { + "Name": "AreTerrainReplicationRegionsShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreTimestepsShown": { + "Name": "AreTimestepsShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreUnalignedPartsShown": { + "Name": "AreUnalignedPartsShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreWorldCoordsShown": { + "Name": "AreWorldCoordsShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DisableCSGv2": { + "Name": "DisableCSGv2", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ForceCSGv2": { + "Name": "ForceCSGv2", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsInterpolationThrottleShown": { + "Name": "IsInterpolationThrottleShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsReceiveAgeShown": { + "Name": "IsReceiveAgeShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsTreeShown": { + "Name": "IsTreeShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PhysicsEnvironmentalThrottle": { + "Name": "PhysicsEnvironmentalThrottle", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "EnviromentalPhysicsThrottle" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShowDecompositionGeometry": { + "Name": "ShowDecompositionGeometry", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ThrottleAdjustTime": { + "Name": "ThrottleAdjustTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UseCSGv2": { + "Name": "UseCSGv2", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "PitchShiftSoundEffect": { + "Name": "PitchShiftSoundEffect", + "Tags": [], + "Superclass": "SoundEffect", + "Properties": { + "Octave": { + "Name": "Octave", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Octave": { + "Type": "Float32", + "Value": 1.25 + }, + "Priority": { + "Type": "Int32", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Platform": { + "Name": "Platform", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Part", + "Properties": {}, + "DefaultProperties": {} + }, + "Player": { + "Name": "Player", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "AccountAge": { + "Name": "AccountAge", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AppearanceDidLoad": { + "Name": "AppearanceDidLoad", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AutoJumpEnabled": { + "Name": "AutoJumpEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraMaxZoomDistance": { + "Name": "CameraMaxZoomDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraMinZoomDistance": { + "Name": "CameraMinZoomDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraMode": { + "Name": "CameraMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "CameraMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CanLoadCharacterAppearance": { + "Name": "CanLoadCharacterAppearance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Character": { + "Name": "Character", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CharacterAppearance": { + "Name": "CharacterAppearance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Deprecated", + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CharacterAppearanceId": { + "Name": "CharacterAppearanceId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ChatMode": { + "Name": "ChatMode", + "Scriptability": "Read", + "DataType": { + "Enum": "ChatMode" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DataComplexity": { + "Name": "DataComplexity", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DataComplexityLimit": { + "Name": "DataComplexityLimit", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DataReady": { + "Name": "DataReady", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DevCameraOcclusionMode": { + "Name": "DevCameraOcclusionMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DevCameraOcclusionMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DevComputerCameraMode": { + "Name": "DevComputerCameraMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DevComputerCameraMovementMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DevComputerMovementMode": { + "Name": "DevComputerMovementMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DevComputerMovementMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DevEnableMouseLock": { + "Name": "DevEnableMouseLock", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DevTouchCameraMode": { + "Name": "DevTouchCameraMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DevTouchCameraMovementMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DevTouchMovementMode": { + "Name": "DevTouchMovementMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DevTouchMovementMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DisplayName": { + "Name": "DisplayName", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FollowUserId": { + "Name": "FollowUserId", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GameplayPaused": { + "Name": "GameplayPaused", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Guest": { + "Name": "Guest", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "HealthDisplayDistance": { + "Name": "HealthDisplayDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LocaleId": { + "Name": "LocaleId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MaximumSimulationRadius": { + "Name": "MaximumSimulationRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MembershipType": { + "Name": "MembershipType", + "Scriptability": "Read", + "DataType": { + "Enum": "MembershipType" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "NameDisplayDistance": { + "Name": "NameDisplayDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Neutral": { + "Name": "Neutral", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OsPlatform": { + "Name": "OsPlatform", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlatformName": { + "Name": "PlatformName", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ReplicationFocus": { + "Name": "ReplicationFocus", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RespawnLocation": { + "Name": "RespawnLocation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SimulationRadius": { + "Name": "SimulationRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Team": { + "Name": "Team", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TeamColor": { + "Name": "TeamColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Teleported": { + "Name": "Teleported", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TeleportedIn": { + "Name": "TeleportedIn", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UserId": { + "Name": "UserId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "VRDevice": { + "Name": "VRDevice", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "userId": { + "Name": "userId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Deprecated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "PlayerEmulatorService": { + "Name": "PlayerEmulatorService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "EmulatedCountryCode": { + "Name": "EmulatedCountryCode", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EmulatedGameLocale": { + "Name": "EmulatedGameLocale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlayerEmulationEnabled": { + "Name": "PlayerEmulationEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlayerEmulationEnabled_deprecated": { + "Name": "PlayerEmulationEnabled_deprecated", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SerializedEmulatedPolicyInfo": { + "Name": "SerializedEmulatedPolicyInfo", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StudioEmulatedCountryRegionCode": { + "Name": "StudioEmulatedCountryRegionCode", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "EmulatedCountryCode": { + "Type": "String", + "Value": "" + }, + "EmulatedGameLocale": { + "Type": "String", + "Value": "" + }, + "PlayerEmulationEnabled": { + "Type": "Bool", + "Value": false + }, + "SerializedEmulatedPolicyInfo": { + "Type": "String", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "PlayerGui": { + "Name": "PlayerGui", + "Tags": [ + "NotCreatable", + "PlayerReplicated" + ], + "Superclass": "BasePlayerGui", + "Properties": { + "CurrentScreenOrientation": { + "Name": "CurrentScreenOrientation", + "Scriptability": "Read", + "DataType": { + "Enum": "ScreenOrientation" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ScreenOrientation": { + "Name": "ScreenOrientation", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ScreenOrientation" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SelectionImageObject": { + "Name": "SelectionImageObject", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "PlayerMouse": { + "Name": "PlayerMouse", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Mouse", + "Properties": {}, + "DefaultProperties": {} + }, + "PlayerScripts": { + "Name": "PlayerScripts", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Players": { + "Name": "Players", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "BubbleChat": { + "Name": "BubbleChat", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CharacterAutoLoads": { + "Name": "CharacterAutoLoads", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClassicChat": { + "Name": "ClassicChat", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LocalPlayer": { + "Name": "LocalPlayer", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MaxPlayers": { + "Name": "MaxPlayers", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "MaxPlayersInternal" + } + } + } + }, + "MaxPlayersInternal": { + "Name": "MaxPlayersInternal", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "MaxPlayers" + } + } + }, + "NumPlayers": { + "Name": "NumPlayers", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PreferredPlayers": { + "Name": "PreferredPlayers", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "PreferredPlayersInternal" + } + } + } + }, + "PreferredPlayersInternal": { + "Name": "PreferredPlayersInternal", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "PreferredPlayers" + } + } + }, + "RespawnTime": { + "Name": "RespawnTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "localPlayer": { + "Name": "localPlayer", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "numPlayers": { + "Name": "numPlayers", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CharacterAutoLoads": { + "Type": "Bool", + "Value": true + }, + "MaxPlayers": { + "Type": "Int32", + "Value": 12 + }, + "PreferredPlayers": { + "Type": "Int32", + "Value": 0 + }, + "RespawnTime": { + "Type": "Float32", + "Value": 5.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Plugin": { + "Name": "Plugin", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "CollisionEnabled": { + "Name": "CollisionEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GridSize": { + "Name": "GridSize", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "HostDataModelType": { + "Name": "HostDataModelType", + "Scriptability": "Read", + "DataType": { + "Enum": "StudioDataModelType" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "HostDataModelTypeIsCurrent": { + "Name": "HostDataModelTypeIsCurrent", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MultipleDocumentInterfaceInstance": { + "Name": "MultipleDocumentInterfaceInstance", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UsesAssetInsertionDrag": { + "Name": "UsesAssetInsertionDrag", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "PluginAction": { + "Name": "PluginAction", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "ActionId": { + "Name": "ActionId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AllowBinding": { + "Name": "AllowBinding", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Checked": { + "Name": "Checked", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DefaultShortcut": { + "Name": "DefaultShortcut", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "StatusTip": { + "Name": "StatusTip", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Text": { + "Name": "Text", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "PluginDebugService": { + "Name": "PluginDebugService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "PluginDragEvent": { + "Name": "PluginDragEvent", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Data": { + "Name": "Data", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MimeType": { + "Name": "MimeType", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Position": { + "Name": "Position", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Sender": { + "Name": "Sender", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "PluginGui": { + "Name": "PluginGui", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "LayerCollector", + "Properties": { + "Title": { + "Name": "Title", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "PluginGuiService": { + "Name": "PluginGuiService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "PluginManager": { + "Name": "PluginManager", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "PluginManagerInterface": { + "Name": "PluginManagerInterface", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "PluginMenu": { + "Name": "PluginMenu", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Icon": { + "Name": "Icon", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Title": { + "Name": "Title", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "PluginMouse": { + "Name": "PluginMouse", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Mouse", + "Properties": {}, + "DefaultProperties": {} + }, + "PluginToolbar": { + "Name": "PluginToolbar", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "PluginToolbarButton": { + "Name": "PluginToolbarButton", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "ClickableWhenViewportHidden": { + "Name": "ClickableWhenViewportHidden", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Icon": { + "Name": "Icon", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "PointLight": { + "Name": "PointLight", + "Tags": [], + "Superclass": "Light", + "Properties": { + "Range": { + "Name": "Range", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Brightness": { + "Type": "Float32", + "Value": 1.0 + }, + "Color": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Range": { + "Type": "Float32", + "Value": 8.0 + }, + "Shadows": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "PointsService": { + "Name": "PointsService", + "Tags": [ + "Deprecated", + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "PolicyService": { + "Name": "PolicyService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "IsLuobuServer": { + "Name": "IsLuobuServer", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TriStateBoolean" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LuobuWhitelisted": { + "Name": "LuobuWhitelisted", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TriStateBoolean" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "Pose": { + "Name": "Pose", + "Tags": [], + "Superclass": "PoseBase", + "Properties": { + "CFrame": { + "Name": "CFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaskWeight": { + "Name": "MaskWeight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "EasingDirection": { + "Type": "Enum", + "Value": 0 + }, + "EasingStyle": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Weight": { + "Type": "Float32", + "Value": 1.0 + } + } + }, + "PoseBase": { + "Name": "PoseBase", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "EasingDirection": { + "Name": "EasingDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "PoseEasingDirection" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EasingStyle": { + "Name": "EasingStyle", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "PoseEasingStyle" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Weight": { + "Name": "Weight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "PostEffect": { + "Name": "PostEffect", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "PrismaticConstraint": { + "Name": "PrismaticConstraint", + "Tags": [], + "Superclass": "SlidingBallConstraint", + "Properties": {}, + "DefaultProperties": { + "ActuatorType": { + "Type": "Enum", + "Value": 0 + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Int32", + "Value": 1009 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "LimitsEnabled": { + "Type": "Bool", + "Value": false + }, + "LowerLimit": { + "Type": "Float32", + "Value": 0.0 + }, + "MotorMaxAcceleration": { + "Type": "Float32", + "Value": null + }, + "MotorMaxForce": { + "Type": "Float32", + "Value": 0.0 + }, + "Restitution": { + "Type": "Float32", + "Value": 0.0 + }, + "ServoMaxForce": { + "Type": "Float32", + "Value": 0.0 + }, + "Size": { + "Type": "Float32", + "Value": 0.15 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Speed": { + "Type": "Float32", + "Value": 0.0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TargetPosition": { + "Type": "Float32", + "Value": 0.0 + }, + "UpperLimit": { + "Type": "Float32", + "Value": 5.0 + }, + "Velocity": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "ProximityPrompt": { + "Name": "ProximityPrompt", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "ActionText": { + "Name": "ActionText", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AutoLocalize": { + "Name": "AutoLocalize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClickablePrompt": { + "Name": "ClickablePrompt", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Exclusivity": { + "Name": "Exclusivity", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ProximityPromptExclusivity" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GamepadKeyCode": { + "Name": "GamepadKeyCode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "KeyCode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HoldDuration": { + "Name": "HoldDuration", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "KeyboardKeyCode": { + "Name": "KeyboardKeyCode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "KeyCode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxActivationDistance": { + "Name": "MaxActivationDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ObjectText": { + "Name": "ObjectText", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RequiresLineOfSight": { + "Name": "RequiresLineOfSight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RootLocalizationTable": { + "Name": "RootLocalizationTable", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Style": { + "Name": "Style", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ProximityPromptStyle" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UIOffset": { + "Name": "UIOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "ActionText": { + "Type": "String", + "Value": "Interact" + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "ClickablePrompt": { + "Type": "Bool", + "Value": true + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Exclusivity": { + "Type": "Enum", + "Value": 0 + }, + "GamepadKeyCode": { + "Type": "Enum", + "Value": 1000 + }, + "HoldDuration": { + "Type": "Float32", + "Value": 0.0 + }, + "KeyboardKeyCode": { + "Type": "Enum", + "Value": 101 + }, + "MaxActivationDistance": { + "Type": "Float32", + "Value": 10.0 + }, + "ObjectText": { + "Type": "String", + "Value": "" + }, + "RequiresLineOfSight": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Style": { + "Type": "Enum", + "Value": 0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "UIOffset": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + } + } + }, + "ProximityPromptService": { + "Name": "ProximityPromptService", + "Tags": [ + "NotBrowsable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxPromptsVisible": { + "Name": "MaxPromptsVisible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "MaxPromptsVisible": { + "Type": "Int32", + "Value": 16 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "QWidgetPluginGui": { + "Name": "QWidgetPluginGui", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "PluginGui", + "Properties": {}, + "DefaultProperties": {} + }, + "RayValue": { + "Name": "RayValue", + "Tags": [], + "Superclass": "ValueBase", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ray" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Value": { + "Type": "Ray", + "Value": { + "Origin": [ + 0.0, + 0.0, + 0.0 + ], + "Direction": [ + 0.0, + 0.0, + 0.0 + ] + } + } + } + }, + "RbxAnalyticsService": { + "Name": "RbxAnalyticsService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "ReflectionMetadata": { + "Name": "ReflectionMetadata", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ReflectionMetadataCallbacks": { + "Name": "ReflectionMetadataCallbacks", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ReflectionMetadataClass": { + "Name": "ReflectionMetadataClass", + "Tags": [], + "Superclass": "ReflectionMetadataItem", + "Properties": { + "ExplorerImageIndex": { + "Name": "ExplorerImageIndex", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ExplorerOrder": { + "Name": "ExplorerOrder", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Insertable": { + "Name": "Insertable", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PreferredParent": { + "Name": "PreferredParent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Browsable": { + "Type": "Bool", + "Value": true + }, + "ClassCategory": { + "Type": "String", + "Value": "" + }, + "ClientOnly": { + "Type": "Bool", + "Value": false + }, + "Constraint": { + "Type": "String", + "Value": "" + }, + "Deprecated": { + "Type": "Bool", + "Value": false + }, + "EditingDisabled": { + "Type": "Bool", + "Value": false + }, + "ExplorerImageIndex": { + "Type": "Int32", + "Value": 0 + }, + "ExplorerOrder": { + "Type": "Int32", + "Value": 2147483647 + }, + "Insertable": { + "Type": "Bool", + "Value": true + }, + "IsBackend": { + "Type": "Bool", + "Value": false + }, + "PreferredParent": { + "Type": "String", + "Value": "" + }, + "PropertyOrder": { + "Type": "Int32", + "Value": 5000 + }, + "ScriptContext": { + "Type": "String", + "Value": "" + }, + "ServerOnly": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "UIMaximum": { + "Type": "Float64", + "Value": 0.0 + }, + "UIMinimum": { + "Type": "Float64", + "Value": 0.0 + }, + "UINumTicks": { + "Type": "Float64", + "Value": 0.0 + }, + "summary": { + "Type": "String", + "Value": "" + } + } + }, + "ReflectionMetadataClasses": { + "Name": "ReflectionMetadataClasses", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ReflectionMetadataEnum": { + "Name": "ReflectionMetadataEnum", + "Tags": [], + "Superclass": "ReflectionMetadataItem", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Browsable": { + "Type": "Bool", + "Value": true + }, + "ClassCategory": { + "Type": "String", + "Value": "" + }, + "ClientOnly": { + "Type": "Bool", + "Value": false + }, + "Constraint": { + "Type": "String", + "Value": "" + }, + "Deprecated": { + "Type": "Bool", + "Value": false + }, + "EditingDisabled": { + "Type": "Bool", + "Value": false + }, + "IsBackend": { + "Type": "Bool", + "Value": false + }, + "PropertyOrder": { + "Type": "Int32", + "Value": 5000 + }, + "ScriptContext": { + "Type": "String", + "Value": "" + }, + "ServerOnly": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "UIMaximum": { + "Type": "Float64", + "Value": 0.0 + }, + "UIMinimum": { + "Type": "Float64", + "Value": 0.0 + }, + "UINumTicks": { + "Type": "Float64", + "Value": 0.0 + }, + "summary": { + "Type": "String", + "Value": "" + } + } + }, + "ReflectionMetadataEnumItem": { + "Name": "ReflectionMetadataEnumItem", + "Tags": [], + "Superclass": "ReflectionMetadataItem", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Browsable": { + "Type": "Bool", + "Value": true + }, + "ClassCategory": { + "Type": "String", + "Value": "" + }, + "ClientOnly": { + "Type": "Bool", + "Value": false + }, + "Constraint": { + "Type": "String", + "Value": "" + }, + "Deprecated": { + "Type": "Bool", + "Value": false + }, + "EditingDisabled": { + "Type": "Bool", + "Value": false + }, + "IsBackend": { + "Type": "Bool", + "Value": false + }, + "PropertyOrder": { + "Type": "Int32", + "Value": 5000 + }, + "ScriptContext": { + "Type": "String", + "Value": "" + }, + "ServerOnly": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "UIMaximum": { + "Type": "Float64", + "Value": 0.0 + }, + "UIMinimum": { + "Type": "Float64", + "Value": 0.0 + }, + "UINumTicks": { + "Type": "Float64", + "Value": 0.0 + }, + "summary": { + "Type": "String", + "Value": "" + } + } + }, + "ReflectionMetadataEnums": { + "Name": "ReflectionMetadataEnums", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ReflectionMetadataEvents": { + "Name": "ReflectionMetadataEvents", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ReflectionMetadataFunctions": { + "Name": "ReflectionMetadataFunctions", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ReflectionMetadataItem": { + "Name": "ReflectionMetadataItem", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Browsable": { + "Name": "Browsable", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClassCategory": { + "Name": "ClassCategory", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClientOnly": { + "Name": "ClientOnly", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Constraint": { + "Name": "Constraint", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Deprecated": { + "Name": "Deprecated", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EditingDisabled": { + "Name": "EditingDisabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsBackend": { + "Name": "IsBackend", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PropertyOrder": { + "Name": "PropertyOrder", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ScriptContext": { + "Name": "ScriptContext", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ServerOnly": { + "Name": "ServerOnly", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UIMaximum": { + "Name": "UIMaximum", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UIMinimum": { + "Name": "UIMinimum", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UINumTicks": { + "Name": "UINumTicks", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "summary": { + "Name": "summary", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "ReflectionMetadataMember": { + "Name": "ReflectionMetadataMember", + "Tags": [], + "Superclass": "ReflectionMetadataItem", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Browsable": { + "Type": "Bool", + "Value": true + }, + "ClassCategory": { + "Type": "String", + "Value": "" + }, + "ClientOnly": { + "Type": "Bool", + "Value": false + }, + "Constraint": { + "Type": "String", + "Value": "" + }, + "Deprecated": { + "Type": "Bool", + "Value": false + }, + "EditingDisabled": { + "Type": "Bool", + "Value": false + }, + "IsBackend": { + "Type": "Bool", + "Value": false + }, + "PropertyOrder": { + "Type": "Int32", + "Value": 5000 + }, + "ScriptContext": { + "Type": "String", + "Value": "" + }, + "ServerOnly": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "UIMaximum": { + "Type": "Float64", + "Value": 0.0 + }, + "UIMinimum": { + "Type": "Float64", + "Value": 0.0 + }, + "UINumTicks": { + "Type": "Float64", + "Value": 0.0 + }, + "summary": { + "Type": "String", + "Value": "" + } + } + }, + "ReflectionMetadataProperties": { + "Name": "ReflectionMetadataProperties", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ReflectionMetadataYieldFunctions": { + "Name": "ReflectionMetadataYieldFunctions", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "RemoteEvent": { + "Name": "RemoteEvent", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "RemoteFunction": { + "Name": "RemoteFunction", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "RenderSettings": { + "Name": "RenderSettings", + "Tags": [ + "NotBrowsable", + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "AutoFRMLevel": { + "Name": "AutoFRMLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EagerBulkExecution": { + "Name": "EagerBulkExecution", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EditQualityLevel": { + "Name": "EditQualityLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "QualityLevel" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableFRM": { + "Name": "EnableFRM", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ExportMergeByMaterial": { + "Name": "ExportMergeByMaterial", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FrameRateManager": { + "Name": "FrameRateManager", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "FramerateManagerMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GraphicsMode": { + "Name": "GraphicsMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "GraphicsMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MeshCacheSize": { + "Name": "MeshCacheSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MeshPartDetailLevel": { + "Name": "MeshPartDetailLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "MeshPartDetailLevel" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "QualityLevel": { + "Name": "QualityLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "QualityLevel" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReloadAssets": { + "Name": "ReloadAssets", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RenderCSGTrianglesDebug": { + "Name": "RenderCSGTrianglesDebug", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShowBoundingBoxes": { + "Name": "ShowBoundingBoxes", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "RenderingTest": { + "Name": "RenderingTest", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "CFrame": { + "Name": "CFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ComparisonDiffThreshold": { + "Name": "ComparisonDiffThreshold", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ComparisonMethod": { + "Name": "ComparisonMethod", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RenderingTestComparisonMethod" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ComparisonPsnrThreshold": { + "Name": "ComparisonPsnrThreshold", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Description": { + "Name": "Description", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FieldOfView": { + "Name": "FieldOfView", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Orientation": { + "Name": "Orientation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Position": { + "Name": "Position", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "QualityLevel": { + "Name": "QualityLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShouldSkip": { + "Name": "ShouldSkip", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Ticket": { + "Name": "Ticket", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ComparisonDiffThreshold": { + "Type": "Int32", + "Value": 10 + }, + "ComparisonMethod": { + "Type": "Enum", + "Value": 0 + }, + "ComparisonPsnrThreshold": { + "Type": "Float32", + "Value": 50.0 + }, + "Description": { + "Type": "String", + "Value": "" + }, + "FieldOfView": { + "Type": "Float32", + "Value": 70.0 + }, + "QualityLevel": { + "Type": "Int32", + "Value": 21 + }, + "ShouldSkip": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Ticket": { + "Type": "String", + "Value": "" + } + } + }, + "ReplicatedFirst": { + "Name": "ReplicatedFirst", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ReplicatedScriptService": { + "Name": "ReplicatedScriptService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ReplicatedStorage": { + "Name": "ReplicatedStorage", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ReverbSoundEffect": { + "Name": "ReverbSoundEffect", + "Tags": [], + "Superclass": "SoundEffect", + "Properties": { + "DecayTime": { + "Name": "DecayTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Density": { + "Name": "Density", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Diffusion": { + "Name": "Diffusion", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DryLevel": { + "Name": "DryLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WetLevel": { + "Name": "WetLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "DecayTime": { + "Type": "Float32", + "Value": 1.5 + }, + "Density": { + "Type": "Float32", + "Value": 1.0 + }, + "Diffusion": { + "Type": "Float32", + "Value": 1.0 + }, + "DryLevel": { + "Type": "Float32", + "Value": -6.0 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Priority": { + "Type": "Int32", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "WetLevel": { + "Type": "Float32", + "Value": 0.0 + } + } + }, + "RobloxPluginGuiService": { + "Name": "RobloxPluginGuiService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "RobloxReplicatedStorage": { + "Name": "RobloxReplicatedStorage", + "Tags": [ + "NotBrowsable", + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "RocketPropulsion": { + "Name": "RocketPropulsion", + "Tags": [], + "Superclass": "BodyMover", + "Properties": { + "CartoonFactor": { + "Name": "CartoonFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxSpeed": { + "Name": "MaxSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxThrust": { + "Name": "MaxThrust", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxTorque": { + "Name": "MaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Target": { + "Name": "Target", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TargetOffset": { + "Name": "TargetOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TargetRadius": { + "Name": "TargetRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ThrustD": { + "Name": "ThrustD", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ThrustP": { + "Name": "ThrustP", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TurnD": { + "Name": "TurnD", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TurnP": { + "Name": "TurnP", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CartoonFactor": { + "Type": "Float32", + "Value": 0.7 + }, + "MaxSpeed": { + "Type": "Float32", + "Value": 30.0 + }, + "MaxThrust": { + "Type": "Float32", + "Value": 4000.0 + }, + "MaxTorque": { + "Type": "Vector3", + "Value": [ + 400000.0, + 400000.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TargetOffset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "TargetRadius": { + "Type": "Float32", + "Value": 4.0 + }, + "ThrustD": { + "Type": "Float32", + "Value": 0.001 + }, + "ThrustP": { + "Type": "Float32", + "Value": 5.0 + }, + "TurnD": { + "Type": "Float32", + "Value": 500.0 + }, + "TurnP": { + "Type": "Float32", + "Value": 3000.0 + } + } + }, + "RodConstraint": { + "Name": "RodConstraint", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "CurrentDistance": { + "Name": "CurrentDistance", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Length": { + "Name": "Length", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Thickness": { + "Name": "Thickness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Int32", + "Value": 26 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Length": { + "Type": "Float32", + "Value": 5.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Thickness": { + "Type": "Float32", + "Value": 0.1 + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "RopeConstraint": { + "Name": "RopeConstraint", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "CurrentDistance": { + "Name": "CurrentDistance", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Length": { + "Name": "Length", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Restitution": { + "Name": "Restitution", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Thickness": { + "Name": "Thickness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Int32", + "Value": 25 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Length": { + "Type": "Float32", + "Value": 5.0 + }, + "Restitution": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Thickness": { + "Type": "Float32", + "Value": 0.1 + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "Rotate": { + "Name": "Rotate", + "Tags": [], + "Superclass": "JointInstance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "C0": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "C1": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "RotateP": { + "Name": "RotateP", + "Tags": [], + "Superclass": "DynamicRotate", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BaseAngle": { + "Type": "Float32", + "Value": 0.0 + }, + "C0": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "C1": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "RotateV": { + "Name": "RotateV", + "Tags": [], + "Superclass": "DynamicRotate", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BaseAngle": { + "Type": "Float32", + "Value": 0.0 + }, + "C0": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "C1": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "RunService": { + "Name": "RunService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "RunningAverageItemDouble": { + "Name": "RunningAverageItemDouble", + "Tags": [ + "NotCreatable" + ], + "Superclass": "StatsItem", + "Properties": {}, + "DefaultProperties": {} + }, + "RunningAverageItemInt": { + "Name": "RunningAverageItemInt", + "Tags": [ + "NotCreatable" + ], + "Superclass": "StatsItem", + "Properties": {}, + "DefaultProperties": {} + }, + "RunningAverageTimeIntervalItem": { + "Name": "RunningAverageTimeIntervalItem", + "Tags": [ + "NotCreatable" + ], + "Superclass": "StatsItem", + "Properties": {}, + "DefaultProperties": {} + }, + "RuntimeScriptService": { + "Name": "RuntimeScriptService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "ScreenGui": { + "Name": "ScreenGui", + "Tags": [], + "Superclass": "LayerCollector", + "Properties": { + "DisplayOrder": { + "Name": "DisplayOrder", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IgnoreGuiInset": { + "Name": "IgnoreGuiInset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OnTopOfCoreBlur": { + "Name": "OnTopOfCoreBlur", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "DisplayOrder": { + "Type": "Int32", + "Value": 0 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "IgnoreGuiInset": { + "Type": "Bool", + "Value": false + }, + "ResetOnSpawn": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "ZIndexBehavior": { + "Type": "Enum", + "Value": 0 + } + } + }, + "Script": { + "Name": "Script", + "Tags": [], + "Superclass": "BaseScript", + "Properties": { + "Source": { + "Name": "Source", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Disabled": { + "Type": "Bool", + "Value": false + }, + "LinkedSource": { + "Type": "Content", + "Value": "" + }, + "Source": { + "Type": "String", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ScriptContext": { + "Name": "ScriptContext", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "ScriptsDisabled": { + "Name": "ScriptsDisabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "ScriptDebugger": { + "Name": "ScriptDebugger", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "CurrentLine": { + "Name": "CurrentLine", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsDebugging": { + "Name": "IsDebugging", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPaused": { + "Name": "IsPaused", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Script": { + "Name": "Script", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "ScriptService": { + "Name": "ScriptService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ScrollingFrame": { + "Name": "ScrollingFrame", + "Tags": [], + "Superclass": "GuiObject", + "Properties": { + "AbsoluteCanvasSize": { + "Name": "AbsoluteCanvasSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AbsoluteWindowSize": { + "Name": "AbsoluteWindowSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AutomaticCanvasSize": { + "Name": "AutomaticCanvasSize", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AutomaticSize" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BottomImage": { + "Name": "BottomImage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CanvasPosition": { + "Name": "CanvasPosition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CanvasSize": { + "Name": "CanvasSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ElasticBehavior": { + "Name": "ElasticBehavior", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ElasticBehavior" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HorizontalBarRect": { + "Name": "HorizontalBarRect", + "Scriptability": "Read", + "DataType": { + "Value": "Rect" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "HorizontalScrollBarInset": { + "Name": "HorizontalScrollBarInset", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ScrollBarInset" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxCanvasPosition": { + "Name": "MaxCanvasPosition", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MidImage": { + "Name": "MidImage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ScrollBarImageColor3": { + "Name": "ScrollBarImageColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ScrollBarImageTransparency": { + "Name": "ScrollBarImageTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ScrollBarThickness": { + "Name": "ScrollBarThickness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ScrollingDirection": { + "Name": "ScrollingDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ScrollingDirection" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ScrollingEnabled": { + "Name": "ScrollingEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TopImage": { + "Name": "TopImage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VerticalBarRect": { + "Name": "VerticalBarRect", + "Scriptability": "Read", + "DataType": { + "Value": "Rect" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "VerticalScrollBarInset": { + "Name": "VerticalScrollBarInset", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ScrollBarInset" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VerticalScrollBarPosition": { + "Name": "VerticalScrollBarPosition", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "VerticalScrollBarPosition" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Type": "Bool", + "Value": false + }, + "AnchorPoint": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "AutomaticCanvasSize": { + "Type": "Enum", + "Value": 0 + }, + "AutomaticSize": { + "Type": "Enum", + "Value": 0 + }, + "BackgroundColor3": { + "Type": "Color3", + "Value": [ + 0.6392157, + 0.63529414, + 0.64705884 + ] + }, + "BackgroundTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "BorderColor3": { + "Type": "Color3", + "Value": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "BorderMode": { + "Type": "Enum", + "Value": 0 + }, + "BorderSizePixel": { + "Type": "Int32", + "Value": 1 + }, + "BottomImage": { + "Type": "Content", + "Value": "rbxasset://textures/ui/Scroll/scroll-bottom.png" + }, + "CanvasPosition": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "CanvasSize": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 2.0, + 0 + ] + ] + }, + "ClipsDescendants": { + "Type": "Bool", + "Value": true + }, + "Draggable": { + "Type": "Bool", + "Value": false + }, + "ElasticBehavior": { + "Type": "Enum", + "Value": 0 + }, + "HorizontalScrollBarInset": { + "Type": "Enum", + "Value": 0 + }, + "LayoutOrder": { + "Type": "Int32", + "Value": 0 + }, + "MidImage": { + "Type": "Content", + "Value": "rbxasset://textures/ui/Scroll/scroll-middle.png" + }, + "Position": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "Rotation": { + "Type": "Float32", + "Value": 0.0 + }, + "ScrollBarImageColor3": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "ScrollBarImageTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "ScrollBarThickness": { + "Type": "Int32", + "Value": 12 + }, + "ScrollingDirection": { + "Type": "Enum", + "Value": 4 + }, + "ScrollingEnabled": { + "Type": "Bool", + "Value": true + }, + "Selectable": { + "Type": "Bool", + "Value": true + }, + "Size": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SizeConstraint": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TopImage": { + "Type": "Content", + "Value": "rbxasset://textures/ui/Scroll/scroll-top.png" + }, + "VerticalScrollBarInset": { + "Type": "Enum", + "Value": 0 + }, + "VerticalScrollBarPosition": { + "Type": "Enum", + "Value": 0 + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": 1 + } + } + }, + "Seat": { + "Name": "Seat", + "Tags": [], + "Superclass": "Part", + "Properties": { + "Disabled": { + "Name": "Disabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Occupant": { + "Name": "Occupant", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Anchored": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 4 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 163, + 162, + 165 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "Disabled": { + "Type": "Bool", + "Value": false + }, + "FormFactor": { + "Type": "Enum", + "Value": 1 + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Shape": { + "Type": "Enum", + "Value": 1 + }, + "Size": { + "Type": "Vector3", + "Value": [ + 4.0, + 1.2, + 2.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 3 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "Selection": { + "Name": "Selection", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "ActiveInstance": { + "Name": "ActiveInstance", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "SelectionBox": { + "Name": "SelectionBox", + "Tags": [], + "Superclass": "InstanceAdornment", + "Properties": { + "LineThickness": { + "Name": "LineThickness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SurfaceColor": { + "Name": "SurfaceColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SurfaceColor3": { + "Name": "SurfaceColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SurfaceTransparency": { + "Name": "SurfaceTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "LineThickness": { + "Type": "Float32", + "Value": 0.15 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "SurfaceColor3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "SurfaceTransparency": { + "Type": "Float32", + "Value": 1.0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + } + } + }, + "SelectionLasso": { + "Name": "SelectionLasso", + "Tags": [ + "NotCreatable" + ], + "Superclass": "GuiBase3d", + "Properties": { + "Humanoid": { + "Name": "Humanoid", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "SelectionPartLasso": { + "Name": "SelectionPartLasso", + "Tags": [ + "Deprecated" + ], + "Superclass": "SelectionLasso", + "Properties": { + "Part": { + "Name": "Part", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + } + } + }, + "SelectionPointLasso": { + "Name": "SelectionPointLasso", + "Tags": [ + "Deprecated" + ], + "Superclass": "SelectionLasso", + "Properties": { + "Point": { + "Name": "Point", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "Point": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + } + } + }, + "SelectionSphere": { + "Name": "SelectionSphere", + "Tags": [], + "Superclass": "PVAdornment", + "Properties": { + "SurfaceColor": { + "Name": "SurfaceColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SurfaceColor3": { + "Name": "SurfaceColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SurfaceTransparency": { + "Name": "SurfaceTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "SurfaceColor3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "SurfaceTransparency": { + "Type": "Float32", + "Value": 1.0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + } + } + }, + "ServerReplicator": { + "Name": "ServerReplicator", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "NetworkReplicator", + "Properties": {}, + "DefaultProperties": {} + }, + "ServerScriptService": { + "Name": "ServerScriptService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "LoadStringEnabled": { + "Name": "LoadStringEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "LoadStringEnabled": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ServerStorage": { + "Name": "ServerStorage", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ServiceProvider": { + "Name": "ServiceProvider", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "SessionService": { + "Name": "SessionService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Shirt": { + "Name": "Shirt", + "Tags": [], + "Superclass": "Clothing", + "Properties": { + "ShirtTemplate": { + "Name": "ShirtTemplate", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color3": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "ShirtTemplate": { + "Type": "Content", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ShirtGraphic": { + "Name": "ShirtGraphic", + "Tags": [], + "Superclass": "CharacterAppearance", + "Properties": { + "Color3": { + "Name": "Color3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Graphic": { + "Name": "Graphic", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color3": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "Graphic": { + "Type": "Content", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "SkateboardController": { + "Name": "SkateboardController", + "Tags": [], + "Superclass": "Controller", + "Properties": { + "Steer": { + "Name": "Steer", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Throttle": { + "Name": "Throttle", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "SkateboardPlatform": { + "Name": "SkateboardPlatform", + "Tags": [ + "Deprecated" + ], + "Superclass": "Part", + "Properties": { + "Controller": { + "Name": "Controller", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ControllingHumanoid": { + "Name": "ControllingHumanoid", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Steer": { + "Name": "Steer", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StickyWheels": { + "Name": "StickyWheels", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Throttle": { + "Name": "Throttle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Anchored": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 4 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 163, + 162, + 165 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "FormFactor": { + "Type": "Enum", + "Value": 1 + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Shape": { + "Type": "Enum", + "Value": 1 + }, + "Size": { + "Type": "Vector3", + "Value": [ + 4.0, + 1.2, + 2.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Steer": { + "Type": "Int32", + "Value": 0 + }, + "StickyWheels": { + "Type": "Bool", + "Value": true + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Throttle": { + "Type": "Int32", + "Value": 0 + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 3 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "Skin": { + "Name": "Skin", + "Tags": [ + "Deprecated" + ], + "Superclass": "CharacterAppearance", + "Properties": { + "SkinColor": { + "Name": "SkinColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SkinColor": { + "Type": "Int32", + "Value": 226 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Sky": { + "Name": "Sky", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "CelestialBodiesShown": { + "Name": "CelestialBodiesShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MoonAngularSize": { + "Name": "MoonAngularSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MoonTextureId": { + "Name": "MoonTextureId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SkyboxBk": { + "Name": "SkyboxBk", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SkyboxDn": { + "Name": "SkyboxDn", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SkyboxFt": { + "Name": "SkyboxFt", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SkyboxLf": { + "Name": "SkyboxLf", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SkyboxRt": { + "Name": "SkyboxRt", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SkyboxUp": { + "Name": "SkyboxUp", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StarCount": { + "Name": "StarCount", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SunAngularSize": { + "Name": "SunAngularSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SunTextureId": { + "Name": "SunTextureId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CelestialBodiesShown": { + "Type": "Bool", + "Value": true + }, + "MoonAngularSize": { + "Type": "Float32", + "Value": 11.0 + }, + "MoonTextureId": { + "Type": "Content", + "Value": "rbxasset://sky/moon.jpg" + }, + "SkyboxBk": { + "Type": "Content", + "Value": "rbxasset://textures/sky/sky512_bk.tex" + }, + "SkyboxDn": { + "Type": "Content", + "Value": "rbxasset://textures/sky/sky512_dn.tex" + }, + "SkyboxFt": { + "Type": "Content", + "Value": "rbxasset://textures/sky/sky512_ft.tex" + }, + "SkyboxLf": { + "Type": "Content", + "Value": "rbxasset://textures/sky/sky512_lf.tex" + }, + "SkyboxRt": { + "Type": "Content", + "Value": "rbxasset://textures/sky/sky512_rt.tex" + }, + "SkyboxUp": { + "Type": "Content", + "Value": "rbxasset://textures/sky/sky512_up.tex" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "StarCount": { + "Type": "Int32", + "Value": 3000 + }, + "SunAngularSize": { + "Type": "Float32", + "Value": 21.0 + }, + "SunTextureId": { + "Type": "Content", + "Value": "rbxasset://sky/sun.jpg" + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "SlidingBallConstraint": { + "Name": "SlidingBallConstraint", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Constraint", + "Properties": { + "ActuatorType": { + "Name": "ActuatorType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ActuatorType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CurrentPosition": { + "Name": "CurrentPosition", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LimitsEnabled": { + "Name": "LimitsEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LowerLimit": { + "Name": "LowerLimit", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MotorMaxAcceleration": { + "Name": "MotorMaxAcceleration", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MotorMaxForce": { + "Name": "MotorMaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Restitution": { + "Name": "Restitution", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ServoMaxForce": { + "Name": "ServoMaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Speed": { + "Name": "Speed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TargetPosition": { + "Name": "TargetPosition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UpperLimit": { + "Name": "UpperLimit", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Velocity": { + "Name": "Velocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "Smoke": { + "Name": "Smoke", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Opacity": { + "Name": "Opacity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "opacity_xml" + } + } + } + }, + "RiseVelocity": { + "Name": "RiseVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "riseVelocity_xml" + } + } + } + }, + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "size_xml" + } + } + } + }, + "opacity_xml": { + "Name": "opacity_xml", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "Opacity" + } + } + }, + "riseVelocity_xml": { + "Name": "riseVelocity_xml", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "RiseVelocity" + } + } + }, + "size_xml": { + "Name": "size_xml", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "Size" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Opacity": { + "Type": "Float32", + "Value": 0.5 + }, + "RiseVelocity": { + "Type": "Float32", + "Value": 1.0 + }, + "Size": { + "Type": "Float32", + "Value": 1.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Snap": { + "Name": "Snap", + "Tags": [], + "Superclass": "JointInstance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "C0": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "C1": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "SocialService": { + "Name": "SocialService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "SolidModelContentProvider": { + "Name": "SolidModelContentProvider", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "CacheableContentProvider", + "Properties": {}, + "DefaultProperties": {} + }, + "Sound": { + "Name": "Sound", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "EmitterSize": { + "Name": "EmitterSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsLoaded": { + "Name": "IsLoaded", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPaused": { + "Name": "IsPaused", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPlaying": { + "Name": "IsPlaying", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Looped": { + "Name": "Looped", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxDistance": { + "Name": "MaxDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "xmlRead_MaxDistance_3" + } + } + } + }, + "MinDistance": { + "Name": "MinDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Pitch": { + "Name": "Pitch", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Deprecated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlayOnRemove": { + "Name": "PlayOnRemove", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlaybackLoudness": { + "Name": "PlaybackLoudness", + "Scriptability": "Read", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlaybackSpeed": { + "Name": "PlaybackSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Playing": { + "Name": "Playing", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RollOffMaxDistance": { + "Name": "RollOffMaxDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RollOffMinDistance": { + "Name": "RollOffMinDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RollOffMode": { + "Name": "RollOffMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RollOffMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SoundGroup": { + "Name": "SoundGroup", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SoundId": { + "Name": "SoundId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TimeLength": { + "Name": "TimeLength", + "Scriptability": "Read", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TimePosition": { + "Name": "TimePosition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Volume": { + "Name": "Volume", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "isPlaying": { + "Name": "isPlaying", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "xmlRead_MaxDistance_3": { + "Name": "xmlRead_MaxDistance_3", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "MaxDistance" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "EmitterSize": { + "Type": "Float32", + "Value": 10.0 + }, + "Looped": { + "Type": "Bool", + "Value": false + }, + "MaxDistance": { + "Type": "Float32", + "Value": 10000.0 + }, + "PlayOnRemove": { + "Type": "Bool", + "Value": false + }, + "PlaybackSpeed": { + "Type": "Float32", + "Value": 1.0 + }, + "Playing": { + "Type": "Bool", + "Value": false + }, + "RollOffMode": { + "Type": "Enum", + "Value": 0 + }, + "SoundId": { + "Type": "Content", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TimePosition": { + "Type": "Float64", + "Value": 0.0 + }, + "Volume": { + "Type": "Float32", + "Value": 0.5 + } + } + }, + "SoundEffect": { + "Name": "SoundEffect", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Priority": { + "Name": "Priority", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "SoundGroup": { + "Name": "SoundGroup", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Volume": { + "Name": "Volume", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Volume": { + "Type": "Float32", + "Value": 0.5 + } + } + }, + "SoundService": { + "Name": "SoundService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "AmbientReverb": { + "Name": "AmbientReverb", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ReverbType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DistanceFactor": { + "Name": "DistanceFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DopplerScale": { + "Name": "DopplerScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RespectFilteringEnabled": { + "Name": "RespectFilteringEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RolloffScale": { + "Name": "RolloffScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AmbientReverb": { + "Type": "Enum", + "Value": 0 + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "DistanceFactor": { + "Type": "Float32", + "Value": 3.33 + }, + "DopplerScale": { + "Type": "Float32", + "Value": 1.0 + }, + "RespectFilteringEnabled": { + "Type": "Bool", + "Value": false + }, + "RolloffScale": { + "Type": "Float32", + "Value": 1.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Sparkles": { + "Name": "Sparkles", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SparkleColor": { + "Name": "SparkleColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "SparkleColor": { + "Type": "Color3", + "Value": [ + 0.5647059, + 0.098039225, + 1.0 + ] + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "SpawnLocation": { + "Name": "SpawnLocation", + "Tags": [], + "Superclass": "Part", + "Properties": { + "AllowTeamChangeOnTouch": { + "Name": "AllowTeamChangeOnTouch", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Duration": { + "Name": "Duration", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Neutral": { + "Name": "Neutral", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TeamColor": { + "Name": "TeamColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AllowTeamChangeOnTouch": { + "Type": "Bool", + "Value": false + }, + "Anchored": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 4 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 163, + 162, + 165 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "Duration": { + "Type": "Int32", + "Value": 10 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "FormFactor": { + "Type": "Enum", + "Value": 1 + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "Neutral": { + "Type": "Bool", + "Value": true + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Shape": { + "Type": "Enum", + "Value": 1 + }, + "Size": { + "Type": "Vector3", + "Value": [ + 4.0, + 1.2, + 2.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TeamColor": { + "Type": "Int32", + "Value": 194 + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 3 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "SpawnerService": { + "Name": "SpawnerService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "SpecialMesh": { + "Name": "SpecialMesh", + "Tags": [], + "Superclass": "FileMesh", + "Properties": { + "MeshType": { + "Name": "MeshType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "MeshType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "MeshId": { + "Type": "Content", + "Value": "" + }, + "MeshType": { + "Type": "Enum", + "Value": 0 + }, + "Offset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Scale": { + "Type": "Vector3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TextureId": { + "Type": "Content", + "Value": "" + }, + "VertexColor": { + "Type": "Vector3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + } + } + }, + "SphereHandleAdornment": { + "Name": "SphereHandleAdornment", + "Tags": [], + "Superclass": "HandleAdornment", + "Properties": { + "Radius": { + "Name": "Radius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AdornCullingMode": { + "Type": "Enum", + "Value": 0 + }, + "AlwaysOnTop": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "Radius": { + "Type": "Float32", + "Value": 1.0 + }, + "SizeRelativeOffset": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": -1 + } + } + }, + "SpotLight": { + "Name": "SpotLight", + "Tags": [], + "Superclass": "Light", + "Properties": { + "Angle": { + "Name": "Angle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Face": { + "Name": "Face", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "NormalId" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Range": { + "Name": "Range", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Angle": { + "Type": "Float32", + "Value": 90.0 + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Brightness": { + "Type": "Float32", + "Value": 1.0 + }, + "Color": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Face": { + "Type": "Enum", + "Value": 5 + }, + "Range": { + "Type": "Float32", + "Value": 16.0 + }, + "Shadows": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "SpringConstraint": { + "Name": "SpringConstraint", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "Coils": { + "Name": "Coils", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CurrentLength": { + "Name": "CurrentLength", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Damping": { + "Name": "Damping", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FreeLength": { + "Name": "FreeLength", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LimitsEnabled": { + "Name": "LimitsEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxForce": { + "Name": "MaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxLength": { + "Name": "MaxLength", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MinLength": { + "Name": "MinLength", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Radius": { + "Name": "Radius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Stiffness": { + "Name": "Stiffness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Thickness": { + "Name": "Thickness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Coils": { + "Type": "Float32", + "Value": 3.0 + }, + "Color": { + "Type": "Int32", + "Value": 200 + }, + "Damping": { + "Type": "Float32", + "Value": 0.0 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "FreeLength": { + "Type": "Float32", + "Value": 1.0 + }, + "LimitsEnabled": { + "Type": "Bool", + "Value": false + }, + "MaxForce": { + "Type": "Float32", + "Value": null + }, + "MaxLength": { + "Type": "Float32", + "Value": 5.0 + }, + "MinLength": { + "Type": "Float32", + "Value": 0.0 + }, + "Radius": { + "Type": "Float32", + "Value": 0.4 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Stiffness": { + "Type": "Float32", + "Value": 0.0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Thickness": { + "Type": "Float32", + "Value": 0.1 + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "StandalonePluginScripts": { + "Name": "StandalonePluginScripts", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "StandardPages": { + "Name": "StandardPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, + "StarterCharacterScripts": { + "Name": "StarterCharacterScripts", + "Tags": [ + "NotCreatable" + ], + "Superclass": "StarterPlayerScripts", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "StarterGear": { + "Name": "StarterGear", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "StarterGui": { + "Name": "StarterGui", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "BasePlayerGui", + "Properties": { + "ProcessUserInput": { + "Name": "ProcessUserInput", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ResetPlayerGuiOnSpawn": { + "Name": "ResetPlayerGuiOnSpawn", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ScreenOrientation": { + "Name": "ScreenOrientation", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ScreenOrientation" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShowDevelopmentGui": { + "Name": "ShowDevelopmentGui", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "ResetPlayerGuiOnSpawn": { + "Type": "Bool", + "Value": true + }, + "ScreenOrientation": { + "Type": "Enum", + "Value": 2 + }, + "ShowDevelopmentGui": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "StarterPack": { + "Name": "StarterPack", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "StarterPlayer": { + "Name": "StarterPlayer", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "AllowCustomAnimations": { + "Name": "AllowCustomAnimations", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AutoJumpEnabled": { + "Name": "AutoJumpEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraMaxZoomDistance": { + "Name": "CameraMaxZoomDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraMinZoomDistance": { + "Name": "CameraMinZoomDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraMode": { + "Name": "CameraMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "CameraMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CharacterJumpHeight": { + "Name": "CharacterJumpHeight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CharacterJumpPower": { + "Name": "CharacterJumpPower", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CharacterMaxSlopeAngle": { + "Name": "CharacterMaxSlopeAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CharacterUseJumpPower": { + "Name": "CharacterUseJumpPower", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CharacterWalkSpeed": { + "Name": "CharacterWalkSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DevCameraOcclusionMode": { + "Name": "DevCameraOcclusionMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DevCameraOcclusionMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DevComputerCameraMovementMode": { + "Name": "DevComputerCameraMovementMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DevComputerCameraMovementMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DevComputerMovementMode": { + "Name": "DevComputerMovementMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DevComputerMovementMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DevTouchCameraMovementMode": { + "Name": "DevTouchCameraMovementMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DevTouchCameraMovementMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DevTouchMovementMode": { + "Name": "DevTouchMovementMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DevTouchMovementMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableMouseLockOption": { + "Name": "EnableMouseLockOption", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsAssetIDFace": { + "Name": "GameSettingsAssetIDFace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsAssetIDHead": { + "Name": "GameSettingsAssetIDHead", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsAssetIDLeftArm": { + "Name": "GameSettingsAssetIDLeftArm", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsAssetIDLeftLeg": { + "Name": "GameSettingsAssetIDLeftLeg", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsAssetIDPants": { + "Name": "GameSettingsAssetIDPants", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsAssetIDRightArm": { + "Name": "GameSettingsAssetIDRightArm", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsAssetIDRightLeg": { + "Name": "GameSettingsAssetIDRightLeg", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsAssetIDShirt": { + "Name": "GameSettingsAssetIDShirt", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsAssetIDTeeShirt": { + "Name": "GameSettingsAssetIDTeeShirt", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsAssetIDTorso": { + "Name": "GameSettingsAssetIDTorso", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsAvatar": { + "Name": "GameSettingsAvatar", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "GameAvatarType" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsR15Collision": { + "Name": "GameSettingsR15Collision", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "R15CollisionType" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsScaleRangeBodyType": { + "Name": "GameSettingsScaleRangeBodyType", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsScaleRangeHead": { + "Name": "GameSettingsScaleRangeHead", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsScaleRangeHeight": { + "Name": "GameSettingsScaleRangeHeight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsScaleRangeProportion": { + "Name": "GameSettingsScaleRangeProportion", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GameSettingsScaleRangeWidth": { + "Name": "GameSettingsScaleRangeWidth", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HealthDisplayDistance": { + "Name": "HealthDisplayDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LoadCharacterAppearance": { + "Name": "LoadCharacterAppearance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NameDisplayDistance": { + "Name": "NameDisplayDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UserEmotesEnabled": { + "Name": "UserEmotesEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AllowCustomAnimations": { + "Type": "Bool", + "Value": true + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoJumpEnabled": { + "Type": "Bool", + "Value": true + }, + "CameraMaxZoomDistance": { + "Type": "Float32", + "Value": 400.0 + }, + "CameraMinZoomDistance": { + "Type": "Float32", + "Value": 0.5 + }, + "CameraMode": { + "Type": "Enum", + "Value": 0 + }, + "CharacterJumpHeight": { + "Type": "Float32", + "Value": 7.2 + }, + "CharacterJumpPower": { + "Type": "Float32", + "Value": 50.0 + }, + "CharacterMaxSlopeAngle": { + "Type": "Float32", + "Value": 89.0 + }, + "CharacterUseJumpPower": { + "Type": "Bool", + "Value": true + }, + "CharacterWalkSpeed": { + "Type": "Float32", + "Value": 16.0 + }, + "DevCameraOcclusionMode": { + "Type": "Enum", + "Value": 0 + }, + "DevComputerCameraMovementMode": { + "Type": "Enum", + "Value": 0 + }, + "DevComputerMovementMode": { + "Type": "Enum", + "Value": 0 + }, + "DevTouchCameraMovementMode": { + "Type": "Enum", + "Value": 0 + }, + "DevTouchMovementMode": { + "Type": "Enum", + "Value": 0 + }, + "EnableMouseLockOption": { + "Type": "Bool", + "Value": true + }, + "GameSettingsAssetIDFace": { + "Type": "Int64", + "Value": 0 + }, + "GameSettingsAssetIDHead": { + "Type": "Int64", + "Value": 0 + }, + "GameSettingsAssetIDLeftArm": { + "Type": "Int64", + "Value": 0 + }, + "GameSettingsAssetIDLeftLeg": { + "Type": "Int64", + "Value": 0 + }, + "GameSettingsAssetIDPants": { + "Type": "Int64", + "Value": 0 + }, + "GameSettingsAssetIDRightArm": { + "Type": "Int64", + "Value": 0 + }, + "GameSettingsAssetIDRightLeg": { + "Type": "Int64", + "Value": 0 + }, + "GameSettingsAssetIDShirt": { + "Type": "Int64", + "Value": 0 + }, + "GameSettingsAssetIDTeeShirt": { + "Type": "Int64", + "Value": 0 + }, + "GameSettingsAssetIDTorso": { + "Type": "Int64", + "Value": 0 + }, + "GameSettingsAvatar": { + "Type": "Enum", + "Value": 1 + }, + "GameSettingsR15Collision": { + "Type": "Enum", + "Value": 0 + }, + "GameSettingsScaleRangeBodyType": { + "Type": "NumberRange", + "Value": [ + 0.0, + 1.0 + ] + }, + "GameSettingsScaleRangeHead": { + "Type": "NumberRange", + "Value": [ + 0.95, + 1.0 + ] + }, + "GameSettingsScaleRangeHeight": { + "Type": "NumberRange", + "Value": [ + 0.9, + 1.05 + ] + }, + "GameSettingsScaleRangeProportion": { + "Type": "NumberRange", + "Value": [ + 0.0, + 1.0 + ] + }, + "GameSettingsScaleRangeWidth": { + "Type": "NumberRange", + "Value": [ + 0.7, + 1.0 + ] + }, + "HealthDisplayDistance": { + "Type": "Float32", + "Value": 100.0 + }, + "LoadCharacterAppearance": { + "Type": "Bool", + "Value": true + }, + "NameDisplayDistance": { + "Type": "Float32", + "Value": 100.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "UserEmotesEnabled": { + "Type": "Bool", + "Value": true + } + } + }, + "StarterPlayerScripts": { + "Name": "StarterPlayerScripts", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Stats": { + "Name": "Stats", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "ContactsCount": { + "Name": "ContactsCount", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DataReceiveKbps": { + "Name": "DataReceiveKbps", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DataSendKbps": { + "Name": "DataSendKbps", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "HeartbeatTimeMs": { + "Name": "HeartbeatTimeMs", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "InstanceCount": { + "Name": "InstanceCount", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MovingPrimitivesCount": { + "Name": "MovingPrimitivesCount", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PhysicsReceiveKbps": { + "Name": "PhysicsReceiveKbps", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PhysicsSendKbps": { + "Name": "PhysicsSendKbps", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PhysicsStepTimeMs": { + "Name": "PhysicsStepTimeMs", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PrimitivesCount": { + "Name": "PrimitivesCount", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "StatsItem": { + "Name": "StatsItem", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Status": { + "Name": "Status", + "Tags": [ + "Deprecated", + "NotCreatable" + ], + "Superclass": "Model", + "Properties": {}, + "DefaultProperties": {} + }, + "StopWatchReporter": { + "Name": "StopWatchReporter", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "StringValue": { + "Name": "StringValue", + "Tags": [], + "Superclass": "ValueBase", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Value": { + "Type": "String", + "Value": "" + } + } + }, + "Studio": { + "Name": "Studio", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "\"TODO\" Color": { + "Name": "\"TODO\" Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "\"function\" Color": { + "Name": "\"function\" Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "\"local\" Color": { + "Name": "\"local\" Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "\"nil\" Color": { + "Name": "\"nil\" Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "\"self\" Color": { + "Name": "\"self\" Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Active Color": { + "Name": "Active Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Active Hover Over Color": { + "Name": "Active Hover Over Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Always Save Script Changes": { + "Name": "Always Save Script Changes", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Animate Hover Over": { + "Name": "Animate Hover Over", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Auto Clean Empty Line": { + "Name": "Auto Clean Empty Line", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Auto Closing Brackets": { + "Name": "Auto Closing Brackets", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Auto Closing Quotes": { + "Name": "Auto Closing Quotes", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Auto Indent Rule": { + "Name": "Auto Indent Rule", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AutoIndentRule" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Auto-Recovery Enabled": { + "Name": "Auto-Recovery Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Auto-Recovery Interval (Minutes)": { + "Name": "Auto-Recovery Interval (Minutes)", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Background Color": { + "Name": "Background Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Basic Objects Display Mode": { + "Name": "Basic Objects Display Mode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ListDisplayMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Bool Color": { + "Name": "Bool Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Bracket Color": { + "Name": "Bracket Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Built-in Function Color": { + "Name": "Built-in Function Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Camera Mouse Wheel Speed": { + "Name": "Camera Mouse Wheel Speed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Camera Shift Speed": { + "Name": "Camera Shift Speed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Camera Speed": { + "Name": "Camera Speed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Camera Zoom to Mouse Position": { + "Name": "Camera Zoom to Mouse Position", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Clear Output On Start": { + "Name": "Clear Output On Start", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CommandBarLocalState": { + "Name": "CommandBarLocalState", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Comment Color": { + "Name": "Comment Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Current Line Highlight Color": { + "Name": "Current Line Highlight Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Debugger Current Line Color": { + "Name": "Debugger Current Line Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Debugger Error Line Color": { + "Name": "Debugger Error Line Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DeprecatedObjectsShown": { + "Name": "DeprecatedObjectsShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Disable Accurate Play Solo": { + "Name": "Disable Accurate Play Solo", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DisplayLanguage": { + "Name": "DisplayLanguage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Drag Multiple Parts As Single Part": { + "Name": "Drag Multiple Parts As Single Part", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enable Autocomplete": { + "Name": "Enable Autocomplete", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enable CoreScript Debugger": { + "Name": "Enable CoreScript Debugger", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enable Http Sandboxing": { + "Name": "Enable Http Sandboxing", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enable Internal Beta Features": { + "Name": "Enable Internal Beta Features", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enable Internal Features": { + "Name": "Enable Internal Features", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enable Temporary Tabs": { + "Name": "Enable Temporary Tabs", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enable Temporary Tabs In Explorer": { + "Name": "Enable Temporary Tabs In Explorer", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Error Color": { + "Name": "Error Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Find Selection Background Color": { + "Name": "Find Selection Background Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Format On Paste": { + "Name": "Format On Paste", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Format On Type": { + "Name": "Format On Type", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Function Name Color": { + "Name": "Function Name Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Highlight Current Line": { + "Name": "Highlight Current Line", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Highlight Occurances": { + "Name": "Highlight Occurances", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Hover Animate Speed": { + "Name": "Hover Animate Speed", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "HoverAnimateSpeed" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Hover Over Color": { + "Name": "Hover Over Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Indent Using Spaces": { + "Name": "Indent Using Spaces", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Keyword Color": { + "Name": "Keyword Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Language": { + "Name": "Language", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "LanguagePreference" + }, + "Tags": [ + "Deprecated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Line Thickness": { + "Name": "Line Thickness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LuaDebuggerEnabled": { + "Name": "LuaDebuggerEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LuaDebuggerEnabledAtStartup": { + "Name": "LuaDebuggerEnabledAtStartup", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Luau Keyword Color": { + "Name": "Luau Keyword Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Matching Word Background Color": { + "Name": "Matching Word Background Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Maximum Output Lines": { + "Name": "Maximum Output Lines", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Method Color": { + "Name": "Method Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Number Color": { + "Name": "Number Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Only Play Audio from Window in Focus": { + "Name": "Only Play Audio from Window in Focus", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Operator Color": { + "Name": "Operator Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Output Layout Mode": { + "Name": "Output Layout Mode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "OutputLayoutMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OverrideCoreScripts": { + "Name": "OverrideCoreScripts", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PermissionLevelShown": { + "Name": "PermissionLevelShown", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "PermissionLevelShown" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PluginDebuggingEnabled": { + "Name": "PluginDebuggingEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Property Color": { + "Name": "Property Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Render Throttle Percentage": { + "Name": "Render Throttle Percentage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Respect Studio shortcuts when game has focus": { + "Name": "Respect Studio shortcuts when game has focus", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Ruler Color": { + "Name": "Ruler Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Rulers": { + "Name": "Rulers", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RuntimeUndoBehavior": { + "Name": "RuntimeUndoBehavior", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RuntimeUndoBehavior" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Script Editor Color Preset": { + "Name": "Script Editor Color Preset", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "StudioScriptEditorColorPresets" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ScriptTimeoutLength": { + "Name": "ScriptTimeoutLength", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Scroll Past Last Line": { + "Name": "Scroll Past Last Line", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Search Content For Core Scripts": { + "Name": "Search Content For Core Scripts", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Select Color": { + "Name": "Select Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Select/Hover Color": { + "Name": "Select/Hover Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Selection Background Color": { + "Name": "Selection Background Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Selection Color": { + "Name": "Selection Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Server Audio Behavior": { + "Name": "Server Audio Behavior", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ServerAudioBehavior" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show Core GUI in Explorer while Playing": { + "Name": "Show Core GUI in Explorer while Playing", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show CorePackages": { + "Name": "Show CorePackages", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show Diagnostics Bar": { + "Name": "Show Diagnostics Bar", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show FileSyncService": { + "Name": "Show FileSyncService", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show Hidden Objects in Explorer": { + "Name": "Show Hidden Objects in Explorer", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show Hover Over": { + "Name": "Show Hover Over", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show Navigation Mesh": { + "Name": "Show Navigation Mesh", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show Plugin GUI Service in Explorer": { + "Name": "Show Plugin GUI Service in Explorer", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show QT warnings in output": { + "Name": "Show QT warnings in output", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show Whitespace": { + "Name": "Show Whitespace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show plus button on hover in Explorer": { + "Name": "Show plus button on hover in Explorer", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Skip Closing Brackets and Quotes": { + "Name": "Skip Closing Brackets and Quotes", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "String Color": { + "Name": "String Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Tab Width": { + "Name": "Tab Width", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Text Color": { + "Name": "Text Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Text Wrapping": { + "Name": "Text Wrapping", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Theme": { + "Name": "Theme", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UI Theme": { + "Name": "UI Theme", + "Scriptability": "Read", + "DataType": { + "Enum": "UITheme" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Warning Color": { + "Name": "Warning Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Whitespace Color": { + "Name": "Whitespace Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "StudioData": { + "Name": "StudioData", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "EnableScriptCollabByDefaultOnLoad": { + "Name": "EnableScriptCollabByDefaultOnLoad", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableScriptCollabOnLoad": { + "Name": "EnableScriptCollabOnLoad", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SrcPlaceId": { + "Name": "SrcPlaceId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SrcUniverseId": { + "Name": "SrcUniverseId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "EnableScriptCollabByDefaultOnLoad": { + "Type": "Bool", + "Value": false + }, + "EnableScriptCollabOnLoad": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "SrcPlaceId": { + "Type": "Int64", + "Value": 0 + }, + "SrcUniverseId": { + "Type": "Int64", + "Value": 0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "StudioService": { + "Name": "StudioService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "ActiveScript": { + "Name": "ActiveScript", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AlignDraggedObjects": { + "Name": "AlignDraggedObjects", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DraggerSolveConstraints": { + "Name": "DraggerSolveConstraints", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DrawConstraintsOnTop": { + "Name": "DrawConstraintsOnTop", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GridSize": { + "Name": "GridSize", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "HoverInstance": { + "Name": "HoverInstance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "InstalledPluginData": { + "Name": "InstalledPluginData", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RotateIncrement": { + "Name": "RotateIncrement", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ShowActiveInstanceHighlight": { + "Name": "ShowActiveInstanceHighlight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ShowConstraintDetails": { + "Name": "ShowConstraintDetails", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "StudioLocaleId": { + "Name": "StudioLocaleId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UseLocalSpace": { + "Name": "UseLocalSpace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "StudioTheme": { + "Name": "StudioTheme", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "SunRaysEffect": { + "Name": "SunRaysEffect", + "Tags": [], + "Superclass": "PostEffect", + "Properties": { + "Intensity": { + "Name": "Intensity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Spread": { + "Name": "Spread", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Intensity": { + "Type": "Float32", + "Value": 0.25 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Spread": { + "Type": "Float32", + "Value": 1.0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "SurfaceAppearance": { + "Name": "SurfaceAppearance", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "AlphaMode": { + "Name": "AlphaMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AlphaMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ColorMap": { + "Name": "ColorMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MetalnessMap": { + "Name": "MetalnessMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NormalMap": { + "Name": "NormalMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RoughnessMap": { + "Name": "RoughnessMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TexturePack": { + "Name": "TexturePack", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AlphaMode": { + "Type": "Enum", + "Value": 0 + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "ColorMap": { + "Type": "Content", + "Value": "" + }, + "MetalnessMap": { + "Type": "Content", + "Value": "" + }, + "NormalMap": { + "Type": "Content", + "Value": "" + }, + "RoughnessMap": { + "Type": "Content", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TexturePack": { + "Type": "Content", + "Value": "" + } + } + }, + "SurfaceGui": { + "Name": "SurfaceGui", + "Tags": [], + "Superclass": "LayerCollector", + "Properties": { + "Active": { + "Name": "Active", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Adornee": { + "Name": "Adornee", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AlwaysOnTop": { + "Name": "AlwaysOnTop", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CanvasSize": { + "Name": "CanvasSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClipsDescendants": { + "Name": "ClipsDescendants", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Face": { + "Name": "Face", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "NormalId" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LightInfluence": { + "Name": "LightInfluence", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PixelsPerStud": { + "Name": "PixelsPerStud", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SizingMode": { + "Name": "SizingMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SurfaceGuiSizingMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ToolPunchThroughDistance": { + "Name": "ToolPunchThroughDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ZOffset": { + "Name": "ZOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Type": "Bool", + "Value": true + }, + "AlwaysOnTop": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "CanvasSize": { + "Type": "Vector2", + "Value": [ + 800.0, + 600.0 + ] + }, + "ClipsDescendants": { + "Type": "Bool", + "Value": false + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Face": { + "Type": "Enum", + "Value": 5 + }, + "LightInfluence": { + "Type": "Float32", + "Value": 0.0 + }, + "PixelsPerStud": { + "Type": "Float32", + "Value": 50.0 + }, + "ResetOnSpawn": { + "Type": "Bool", + "Value": true + }, + "SizingMode": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "ToolPunchThroughDistance": { + "Type": "Float32", + "Value": 0.0 + }, + "ZIndexBehavior": { + "Type": "Enum", + "Value": 0 + }, + "ZOffset": { + "Type": "Float32", + "Value": 0.0 + } + } + }, + "SurfaceLight": { + "Name": "SurfaceLight", + "Tags": [], + "Superclass": "Light", + "Properties": { + "Angle": { + "Name": "Angle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Face": { + "Name": "Face", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "NormalId" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Range": { + "Name": "Range", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Angle": { + "Type": "Float32", + "Value": 90.0 + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Brightness": { + "Type": "Float32", + "Value": 1.0 + }, + "Color": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Face": { + "Type": "Enum", + "Value": 5 + }, + "Range": { + "Type": "Float32", + "Value": 16.0 + }, + "Shadows": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "SurfaceSelection": { + "Name": "SurfaceSelection", + "Tags": [], + "Superclass": "PartAdornment", + "Properties": { + "TargetSurface": { + "Name": "TargetSurface", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "NormalId" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color3": { + "Type": "Color3", + "Value": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TargetSurface": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Visible": { + "Type": "Bool", + "Value": true + } + } + }, + "TaskScheduler": { + "Name": "TaskScheduler", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "SchedulerDutyCycle": { + "Name": "SchedulerDutyCycle", + "Scriptability": "Read", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SchedulerRate": { + "Name": "SchedulerRate", + "Scriptability": "Read", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ThreadPoolConfig": { + "Name": "ThreadPoolConfig", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ThreadPoolConfig" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ThreadPoolSize": { + "Name": "ThreadPoolSize", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "Team": { + "Name": "Team", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "AutoAssignable": { + "Name": "AutoAssignable", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AutoColorCharacters": { + "Name": "AutoColorCharacters", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ChildOrder": { + "Name": "ChildOrder", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Score": { + "Name": "Score", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TeamColor": { + "Name": "TeamColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoAssignable": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TeamColor": { + "Type": "Int32", + "Value": 1 + } + } + }, + "Teams": { + "Name": "Teams", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "TeleportAsyncResult": { + "Name": "TeleportAsyncResult", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "PrivateServerId": { + "Name": "PrivateServerId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ReservedServerAccessCode": { + "Name": "ReservedServerAccessCode", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "TeleportOptions": { + "Name": "TeleportOptions", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "ReservedServerAccessCode": { + "Name": "ReservedServerAccessCode", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ServerInstanceId": { + "Name": "ServerInstanceId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShouldReserveServer": { + "Name": "ShouldReserveServer", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "ReservedServerAccessCode": { + "Type": "String", + "Value": "" + }, + "ServerInstanceId": { + "Type": "String", + "Value": "" + }, + "ShouldReserveServer": { + "Type": "Bool", + "Value": false + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "TeleportService": { + "Name": "TeleportService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "CustomizedTeleportUI": { + "Name": "CustomizedTeleportUI", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Terrain": { + "Name": "Terrain", + "Tags": [ + "NotCreatable" + ], + "Superclass": "BasePart", + "Properties": { + "Decoration": { + "Name": "Decoration", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsSmooth": { + "Name": "IsSmooth", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MaterialColors": { + "Name": "MaterialColors", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxExtents": { + "Name": "MaxExtents", + "Scriptability": "Read", + "DataType": { + "Value": "Region3int16" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WaterColor": { + "Name": "WaterColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WaterReflectance": { + "Name": "WaterReflectance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WaterTransparency": { + "Name": "WaterTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WaterWaveSize": { + "Name": "WaterWaveSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WaterWaveSpeed": { + "Name": "WaterWaveSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Anchored": { + "Type": "Bool", + "Value": true + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 4 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 163, + 162, + 165 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "Decoration": { + "Type": "Bool", + "Value": false + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": true + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "MaterialColors": { + "Type": "BinaryString", + "Value": "AAAAAAAAan8/P39rf2Y/ilY+j35fi21PZmxvZbDqw8faiVpHOi4kHh4lZlw76JxKc3trhHtagcLgc4RKxr21zq2UlJSM" + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Size": { + "Type": "Vector3", + "Value": [ + 2044.0, + 252.0, + 2044.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 3 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "WaterColor": { + "Type": "Color3", + "Value": [ + 0.05, + 0.33, + 0.36 + ] + }, + "WaterReflectance": { + "Type": "Float32", + "Value": 1.0 + }, + "WaterTransparency": { + "Type": "Float32", + "Value": 0.3 + }, + "WaterWaveSize": { + "Type": "Float32", + "Value": 0.15 + }, + "WaterWaveSpeed": { + "Type": "Float32", + "Value": 10.0 + } + } + }, + "TerrainRegion": { + "Name": "TerrainRegion", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "IsSmooth": { + "Name": "IsSmooth", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SizeInCells": { + "Name": "SizeInCells", + "Scriptability": "Read", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "TestService": { + "Name": "TestService", + "Tags": [ + "Service" + ], + "Superclass": "Instance", + "Properties": { + "AutoRuns": { + "Name": "AutoRuns", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Description": { + "Name": "Description", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ErrorCount": { + "Name": "ErrorCount", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ExecuteWithStudioRun": { + "Name": "ExecuteWithStudioRun", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Is30FpsThrottleEnabled": { + "Name": "Is30FpsThrottleEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsPhysicsEnvironmentalThrottled": { + "Name": "IsPhysicsEnvironmentalThrottled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsSleepAllowed": { + "Name": "IsSleepAllowed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NumberOfPlayers": { + "Name": "NumberOfPlayers", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SimulateSecondsLag": { + "Name": "SimulateSecondsLag", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TestCount": { + "Name": "TestCount", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Timeout": { + "Name": "Timeout", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WarnCount": { + "Name": "WarnCount", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoRuns": { + "Type": "Bool", + "Value": true + }, + "Description": { + "Type": "String", + "Value": "" + }, + "ExecuteWithStudioRun": { + "Type": "Bool", + "Value": false + }, + "Is30FpsThrottleEnabled": { + "Type": "Bool", + "Value": true + }, + "IsPhysicsEnvironmentalThrottled": { + "Type": "Bool", + "Value": true + }, + "IsSleepAllowed": { + "Type": "Bool", + "Value": true + }, + "NumberOfPlayers": { + "Type": "Int32", + "Value": 0 + }, + "SimulateSecondsLag": { + "Type": "Float64", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Timeout": { + "Type": "Float64", + "Value": 10.0 + } + } + }, + "TextBox": { + "Name": "TextBox", + "Tags": [], + "Superclass": "GuiObject", + "Properties": { + "ClearTextOnFocus": { + "Name": "ClearTextOnFocus", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Content": { + "Name": "Content", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CursorPosition": { + "Name": "CursorPosition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EnableRealtimeFilteringHints": { + "Name": "EnableRealtimeFilteringHints", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Font": { + "Name": "Font", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "Font" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FontSize": { + "Name": "FontSize", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "FontSize" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LineHeight": { + "Name": "LineHeight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ManualFocusRelease": { + "Name": "ManualFocusRelease", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MultiLine": { + "Name": "MultiLine", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OverlayNativeInput": { + "Name": "OverlayNativeInput", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlaceholderColor3": { + "Name": "PlaceholderColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlaceholderText": { + "Name": "PlaceholderText", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReturnKeyType": { + "Name": "ReturnKeyType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ReturnKeyType" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RichText": { + "Name": "RichText", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SelectionStart": { + "Name": "SelectionStart", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ShowNativeInput": { + "Name": "ShowNativeInput", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Text": { + "Name": "Text", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextBounds": { + "Name": "TextBounds", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextColor": { + "Name": "TextColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextColor3": { + "Name": "TextColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextEditable": { + "Name": "TextEditable", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextFits": { + "Name": "TextFits", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextInputType": { + "Name": "TextInputType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextInputType" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextScaled": { + "Name": "TextScaled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextSize": { + "Name": "TextSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextStrokeColor3": { + "Name": "TextStrokeColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextStrokeTransparency": { + "Name": "TextStrokeTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextTransparency": { + "Name": "TextTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextTruncate": { + "Name": "TextTruncate", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextTruncate" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextWrap": { + "Name": "TextWrap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextWrapped": { + "Name": "TextWrapped", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextXAlignment": { + "Name": "TextXAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextXAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextYAlignment": { + "Name": "TextYAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextYAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Type": "Bool", + "Value": true + }, + "AnchorPoint": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "AutomaticSize": { + "Type": "Enum", + "Value": 0 + }, + "BackgroundColor3": { + "Type": "Color3", + "Value": [ + 0.6392157, + 0.63529414, + 0.64705884 + ] + }, + "BackgroundTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "BorderColor3": { + "Type": "Color3", + "Value": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "BorderMode": { + "Type": "Enum", + "Value": 0 + }, + "BorderSizePixel": { + "Type": "Int32", + "Value": 1 + }, + "ClearTextOnFocus": { + "Type": "Bool", + "Value": true + }, + "ClipsDescendants": { + "Type": "Bool", + "Value": false + }, + "Draggable": { + "Type": "Bool", + "Value": false + }, + "Font": { + "Type": "Enum", + "Value": 0 + }, + "LayoutOrder": { + "Type": "Int32", + "Value": 0 + }, + "LineHeight": { + "Type": "Float32", + "Value": 1.0 + }, + "MultiLine": { + "Type": "Bool", + "Value": false + }, + "PlaceholderColor3": { + "Type": "Color3", + "Value": [ + 0.7, + 0.7, + 0.7 + ] + }, + "PlaceholderText": { + "Type": "String", + "Value": "" + }, + "Position": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "RichText": { + "Type": "Bool", + "Value": false + }, + "Rotation": { + "Type": "Float32", + "Value": 0.0 + }, + "Selectable": { + "Type": "Bool", + "Value": true + }, + "ShowNativeInput": { + "Type": "Bool", + "Value": true + }, + "Size": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SizeConstraint": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Text": { + "Type": "String", + "Value": "TextBox" + }, + "TextColor3": { + "Type": "Color3", + "Value": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "TextEditable": { + "Type": "Bool", + "Value": true + }, + "TextScaled": { + "Type": "Bool", + "Value": false + }, + "TextSize": { + "Type": "Float32", + "Value": 8.0 + }, + "TextStrokeColor3": { + "Type": "Color3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "TextStrokeTransparency": { + "Type": "Float32", + "Value": 1.0 + }, + "TextTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "TextTruncate": { + "Type": "Enum", + "Value": 0 + }, + "TextWrapped": { + "Type": "Bool", + "Value": false + }, + "TextXAlignment": { + "Type": "Enum", + "Value": 2 + }, + "TextYAlignment": { + "Type": "Enum", + "Value": 1 + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": 1 + } + } + }, + "TextButton": { + "Name": "TextButton", + "Tags": [], + "Superclass": "GuiButton", + "Properties": { + "Content": { + "Name": "Content", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Font": { + "Name": "Font", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "Font" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FontSize": { + "Name": "FontSize", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "FontSize" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LineHeight": { + "Name": "LineHeight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LocalizedText": { + "Name": "LocalizedText", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RichText": { + "Name": "RichText", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Text": { + "Name": "Text", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextBounds": { + "Name": "TextBounds", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextColor": { + "Name": "TextColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextColor3": { + "Name": "TextColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextFits": { + "Name": "TextFits", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextScaled": { + "Name": "TextScaled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextSize": { + "Name": "TextSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextStrokeColor3": { + "Name": "TextStrokeColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextStrokeTransparency": { + "Name": "TextStrokeTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextTransparency": { + "Name": "TextTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextTruncate": { + "Name": "TextTruncate", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextTruncate" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextWrap": { + "Name": "TextWrap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextWrapped": { + "Name": "TextWrapped", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextXAlignment": { + "Name": "TextXAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextXAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextYAlignment": { + "Name": "TextYAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextYAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Type": "Bool", + "Value": true + }, + "AnchorPoint": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoButtonColor": { + "Type": "Bool", + "Value": true + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "AutomaticSize": { + "Type": "Enum", + "Value": 0 + }, + "BackgroundColor3": { + "Type": "Color3", + "Value": [ + 0.6392157, + 0.63529414, + 0.64705884 + ] + }, + "BackgroundTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "BorderColor3": { + "Type": "Color3", + "Value": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "BorderMode": { + "Type": "Enum", + "Value": 0 + }, + "BorderSizePixel": { + "Type": "Int32", + "Value": 1 + }, + "ClipsDescendants": { + "Type": "Bool", + "Value": false + }, + "Draggable": { + "Type": "Bool", + "Value": false + }, + "Font": { + "Type": "Enum", + "Value": 0 + }, + "LayoutOrder": { + "Type": "Int32", + "Value": 0 + }, + "LineHeight": { + "Type": "Float32", + "Value": 1.0 + }, + "Modal": { + "Type": "Bool", + "Value": false + }, + "Position": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "RichText": { + "Type": "Bool", + "Value": false + }, + "Rotation": { + "Type": "Float32", + "Value": 0.0 + }, + "Selectable": { + "Type": "Bool", + "Value": true + }, + "Selected": { + "Type": "Bool", + "Value": false + }, + "Size": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SizeConstraint": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Style": { + "Type": "Enum", + "Value": 0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Text": { + "Type": "String", + "Value": "Button" + }, + "TextColor3": { + "Type": "Color3", + "Value": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "TextScaled": { + "Type": "Bool", + "Value": false + }, + "TextSize": { + "Type": "Float32", + "Value": 8.0 + }, + "TextStrokeColor3": { + "Type": "Color3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "TextStrokeTransparency": { + "Type": "Float32", + "Value": 1.0 + }, + "TextTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "TextTruncate": { + "Type": "Enum", + "Value": 0 + }, + "TextWrapped": { + "Type": "Bool", + "Value": false + }, + "TextXAlignment": { + "Type": "Enum", + "Value": 2 + }, + "TextYAlignment": { + "Type": "Enum", + "Value": 1 + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": 1 + } + } + }, + "TextFilterResult": { + "Name": "TextFilterResult", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "TextLabel": { + "Name": "TextLabel", + "Tags": [], + "Superclass": "GuiLabel", + "Properties": { + "Content": { + "Name": "Content", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Font": { + "Name": "Font", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "Font" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FontSize": { + "Name": "FontSize", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "FontSize" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LineHeight": { + "Name": "LineHeight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LocalizedText": { + "Name": "LocalizedText", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RichText": { + "Name": "RichText", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Text": { + "Name": "Text", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextBounds": { + "Name": "TextBounds", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextColor": { + "Name": "TextColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "BrickColor" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextColor3": { + "Name": "TextColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextFits": { + "Name": "TextFits", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextScaled": { + "Name": "TextScaled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextSize": { + "Name": "TextSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextStrokeColor3": { + "Name": "TextStrokeColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextStrokeTransparency": { + "Name": "TextStrokeTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextTransparency": { + "Name": "TextTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextTruncate": { + "Name": "TextTruncate", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextTruncate" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextWrap": { + "Name": "TextWrap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextWrapped": { + "Name": "TextWrapped", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextXAlignment": { + "Name": "TextXAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextXAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextYAlignment": { + "Name": "TextYAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextYAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Type": "Bool", + "Value": false + }, + "AnchorPoint": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "AutomaticSize": { + "Type": "Enum", + "Value": 0 + }, + "BackgroundColor3": { + "Type": "Color3", + "Value": [ + 0.6392157, + 0.63529414, + 0.64705884 + ] + }, + "BackgroundTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "BorderColor3": { + "Type": "Color3", + "Value": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "BorderMode": { + "Type": "Enum", + "Value": 0 + }, + "BorderSizePixel": { + "Type": "Int32", + "Value": 1 + }, + "ClipsDescendants": { + "Type": "Bool", + "Value": false + }, + "Draggable": { + "Type": "Bool", + "Value": false + }, + "Font": { + "Type": "Enum", + "Value": 0 + }, + "LayoutOrder": { + "Type": "Int32", + "Value": 0 + }, + "LineHeight": { + "Type": "Float32", + "Value": 1.0 + }, + "Position": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "RichText": { + "Type": "Bool", + "Value": false + }, + "Rotation": { + "Type": "Float32", + "Value": 0.0 + }, + "Selectable": { + "Type": "Bool", + "Value": false + }, + "Size": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SizeConstraint": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Text": { + "Type": "String", + "Value": "Label" + }, + "TextColor3": { + "Type": "Color3", + "Value": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "TextScaled": { + "Type": "Bool", + "Value": false + }, + "TextSize": { + "Type": "Float32", + "Value": 8.0 + }, + "TextStrokeColor3": { + "Type": "Color3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "TextStrokeTransparency": { + "Type": "Float32", + "Value": 1.0 + }, + "TextTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "TextTruncate": { + "Type": "Enum", + "Value": 0 + }, + "TextWrapped": { + "Type": "Bool", + "Value": false + }, + "TextXAlignment": { + "Type": "Enum", + "Value": 2 + }, + "TextYAlignment": { + "Type": "Enum", + "Value": 1 + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": 1 + } + } + }, + "TextService": { + "Name": "TextService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Texture": { + "Name": "Texture", + "Tags": [], + "Superclass": "Decal", + "Properties": { + "OffsetStudsU": { + "Name": "OffsetStudsU", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OffsetStudsV": { + "Name": "OffsetStudsV", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StudsPerTileU": { + "Name": "StudsPerTileU", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StudsPerTileV": { + "Name": "StudsPerTileV", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color3": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "Face": { + "Type": "Enum", + "Value": 5 + }, + "OffsetStudsU": { + "Type": "Float32", + "Value": 0.0 + }, + "OffsetStudsV": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "StudsPerTileU": { + "Type": "Float32", + "Value": 2.0 + }, + "StudsPerTileV": { + "Type": "Float32", + "Value": 2.0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Texture": { + "Type": "Content", + "Value": "" + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + } + } + }, + "ThirdPartyUserService": { + "Name": "ThirdPartyUserService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "TimerService": { + "Name": "TimerService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Tool": { + "Name": "Tool", + "Tags": [], + "Superclass": "BackpackItem", + "Properties": { + "CanBeDropped": { + "Name": "CanBeDropped", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Grip": { + "Name": "Grip", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GripForward": { + "Name": "GripForward", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GripPos": { + "Name": "GripPos", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GripRight": { + "Name": "GripRight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GripUp": { + "Name": "GripUp", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ManualActivationOnly": { + "Name": "ManualActivationOnly", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RequiresHandle": { + "Name": "RequiresHandle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ToolTip": { + "Name": "ToolTip", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CanBeDropped": { + "Type": "Bool", + "Value": true + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Grip": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ManualActivationOnly": { + "Type": "Bool", + "Value": false + }, + "RequiresHandle": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TextureId": { + "Type": "Content", + "Value": "" + }, + "ToolTip": { + "Type": "String", + "Value": "" + } + } + }, + "Torque": { + "Name": "Torque", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "RelativeTo": { + "Name": "RelativeTo", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ActuatorRelativeTo" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Torque": { + "Name": "Torque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Int32", + "Value": 23 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "RelativeTo": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Torque": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "TotalCountTimeIntervalItem": { + "Name": "TotalCountTimeIntervalItem", + "Tags": [ + "NotCreatable" + ], + "Superclass": "StatsItem", + "Properties": {}, + "DefaultProperties": {} + }, + "TouchInputService": { + "Name": "TouchInputService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "TouchTransmitter": { + "Name": "TouchTransmitter", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "TracerService": { + "Name": "TracerService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Trail": { + "Name": "Trail", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Attachment0": { + "Name": "Attachment0", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Attachment1": { + "Name": "Attachment1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "ColorSequence" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FaceCamera": { + "Name": "FaceCamera", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Lifetime": { + "Name": "Lifetime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LightEmission": { + "Name": "LightEmission", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LightInfluence": { + "Name": "LightInfluence", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxLength": { + "Name": "MaxLength", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MinLength": { + "Name": "MinLength", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Texture": { + "Name": "Texture", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextureLength": { + "Name": "TextureLength", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextureMode": { + "Name": "TextureMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextureMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Transparency": { + "Name": "Transparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberSequence" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WidthScale": { + "Name": "WidthScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberSequence" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "ColorSequence", + "Value": { + "Keypoints": [ + { + "Time": 0.0, + "Color": [ + 1.0, + 1.0, + 1.0 + ] + }, + { + "Time": 1.0, + "Color": [ + 1.0, + 1.0, + 1.0 + ] + } + ] + } + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "FaceCamera": { + "Type": "Bool", + "Value": false + }, + "Lifetime": { + "Type": "Float32", + "Value": 2.0 + }, + "LightEmission": { + "Type": "Float32", + "Value": 0.0 + }, + "LightInfluence": { + "Type": "Float32", + "Value": 0.0 + }, + "MaxLength": { + "Type": "Float32", + "Value": 0.0 + }, + "MinLength": { + "Type": "Float32", + "Value": 0.1 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Texture": { + "Type": "Content", + "Value": "" + }, + "TextureLength": { + "Type": "Float32", + "Value": 1.0 + }, + "TextureMode": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "NumberSequence", + "Value": { + "Keypoints": [ + { + "Time": 0.0, + "Value": 0.5, + "Envelope": 0.0 + }, + { + "Time": 1.0, + "Value": 0.5, + "Envelope": 0.0 + } + ] + } + }, + "WidthScale": { + "Type": "NumberSequence", + "Value": { + "Keypoints": [ + { + "Time": 0.0, + "Value": 1.0, + "Envelope": 0.0 + }, + { + "Time": 1.0, + "Value": 1.0, + "Envelope": 0.0 + } + ] + } + } + } + }, + "Translator": { + "Name": "Translator", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "LocaleId": { + "Name": "LocaleId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "TremoloSoundEffect": { + "Name": "TremoloSoundEffect", + "Tags": [], + "Superclass": "SoundEffect", + "Properties": { + "Depth": { + "Name": "Depth", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Duty": { + "Name": "Duty", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Frequency": { + "Name": "Frequency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Depth": { + "Type": "Float32", + "Value": 1.0 + }, + "Duty": { + "Type": "Float32", + "Value": 0.5 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Frequency": { + "Type": "Float32", + "Value": 5.0 + }, + "Priority": { + "Type": "Int32", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "TriangleMeshPart": { + "Name": "TriangleMeshPart", + "Tags": [ + "NotCreatable" + ], + "Superclass": "BasePart", + "Properties": { + "CollisionFidelity": { + "Name": "CollisionFidelity", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "CollisionFidelity" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "TrussPart": { + "Name": "TrussPart", + "Tags": [], + "Superclass": "BasePart", + "Properties": { + "Style": { + "Name": "Style", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "Style" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Anchored": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 5 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 5 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 163, + 162, + 165 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 5 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 5 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 5 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Size": { + "Type": "Vector3", + "Value": [ + 2.0, + 2.0, + 2.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 5 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "Tween": { + "Name": "Tween", + "Tags": [], + "Superclass": "TweenBase", + "Properties": { + "Instance": { + "Name": "Instance", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "TweenBase": { + "Name": "TweenBase", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "PlaybackState": { + "Name": "PlaybackState", + "Scriptability": "Read", + "DataType": { + "Enum": "PlaybackState" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "TweenService": { + "Name": "TweenService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "UGCValidationService": { + "Name": "UGCValidationService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "UIAspectRatioConstraint": { + "Name": "UIAspectRatioConstraint", + "Tags": [], + "Superclass": "UIConstraint", + "Properties": { + "AspectRatio": { + "Name": "AspectRatio", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AspectType": { + "Name": "AspectType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AspectType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DominantAxis": { + "Name": "DominantAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DominantAxis" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AspectRatio": { + "Type": "Float32", + "Value": 1.0 + }, + "AspectType": { + "Type": "Enum", + "Value": 0 + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "DominantAxis": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "UIBase": { + "Name": "UIBase", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "UIComponent": { + "Name": "UIComponent", + "Tags": [ + "NotCreatable" + ], + "Superclass": "UIBase", + "Properties": {}, + "DefaultProperties": {} + }, + "UIConstraint": { + "Name": "UIConstraint", + "Tags": [ + "NotCreatable" + ], + "Superclass": "UIComponent", + "Properties": {}, + "DefaultProperties": {} + }, + "UICorner": { + "Name": "UICorner", + "Tags": [], + "Superclass": "UIComponent", + "Properties": { + "CornerRadius": { + "Name": "CornerRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CornerRadius": { + "Type": "UDim", + "Value": [ + 0.0, + 8 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "UIGradient": { + "Name": "UIGradient", + "Tags": [], + "Superclass": "UIComponent", + "Properties": { + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "ColorSequence" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Offset": { + "Name": "Offset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Rotation": { + "Name": "Rotation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Transparency": { + "Name": "Transparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberSequence" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "ColorSequence", + "Value": { + "Keypoints": [ + { + "Time": 0.0, + "Color": [ + 1.0, + 1.0, + 1.0 + ] + }, + { + "Time": 1.0, + "Color": [ + 1.0, + 1.0, + 1.0 + ] + } + ] + } + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Offset": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "Rotation": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Transparency": { + "Type": "NumberSequence", + "Value": { + "Keypoints": [ + { + "Time": 0.0, + "Value": 0.0, + "Envelope": 0.0 + }, + { + "Time": 1.0, + "Value": 0.0, + "Envelope": 0.0 + } + ] + } + } + } + }, + "UIGridLayout": { + "Name": "UIGridLayout", + "Tags": [], + "Superclass": "UIGridStyleLayout", + "Properties": { + "AbsoluteCellCount": { + "Name": "AbsoluteCellCount", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AbsoluteCellSize": { + "Name": "AbsoluteCellSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CellPadding": { + "Name": "CellPadding", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CellSize": { + "Name": "CellSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FillDirectionMaxCells": { + "Name": "FillDirectionMaxCells", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StartCorner": { + "Name": "StartCorner", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "StartCorner" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CellPadding": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 5 + ], + [ + 0.0, + 5 + ] + ] + }, + "CellSize": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 100 + ], + [ + 0.0, + 100 + ] + ] + }, + "FillDirection": { + "Type": "Enum", + "Value": 0 + }, + "FillDirectionMaxCells": { + "Type": "Int32", + "Value": 0 + }, + "HorizontalAlignment": { + "Type": "Enum", + "Value": 1 + }, + "SortOrder": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "StartCorner": { + "Type": "Enum", + "Value": 0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "VerticalAlignment": { + "Type": "Enum", + "Value": 1 + } + } + }, + "UIGridStyleLayout": { + "Name": "UIGridStyleLayout", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "UILayout", + "Properties": { + "AbsoluteContentSize": { + "Name": "AbsoluteContentSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FillDirection": { + "Name": "FillDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "FillDirection" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HorizontalAlignment": { + "Name": "HorizontalAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "HorizontalAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SortOrder": { + "Name": "SortOrder", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SortOrder" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VerticalAlignment": { + "Name": "VerticalAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "VerticalAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "UILayout": { + "Name": "UILayout", + "Tags": [ + "NotCreatable" + ], + "Superclass": "UIComponent", + "Properties": {}, + "DefaultProperties": {} + }, + "UIListLayout": { + "Name": "UIListLayout", + "Tags": [], + "Superclass": "UIGridStyleLayout", + "Properties": { + "Padding": { + "Name": "Padding", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "FillDirection": { + "Type": "Enum", + "Value": 1 + }, + "HorizontalAlignment": { + "Type": "Enum", + "Value": 1 + }, + "Padding": { + "Type": "UDim", + "Value": [ + 0.0, + 0 + ] + }, + "SortOrder": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "VerticalAlignment": { + "Type": "Enum", + "Value": 1 + } + } + }, + "UIPadding": { + "Name": "UIPadding", + "Tags": [], + "Superclass": "UIComponent", + "Properties": { + "PaddingBottom": { + "Name": "PaddingBottom", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PaddingLeft": { + "Name": "PaddingLeft", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PaddingRight": { + "Name": "PaddingRight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PaddingTop": { + "Name": "PaddingTop", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "PaddingBottom": { + "Type": "UDim", + "Value": [ + 0.0, + 0 + ] + }, + "PaddingLeft": { + "Type": "UDim", + "Value": [ + 0.0, + 0 + ] + }, + "PaddingRight": { + "Type": "UDim", + "Value": [ + 0.0, + 0 + ] + }, + "PaddingTop": { + "Type": "UDim", + "Value": [ + 0.0, + 0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "UIPageLayout": { + "Name": "UIPageLayout", + "Tags": [], + "Superclass": "UIGridStyleLayout", + "Properties": { + "Animated": { + "Name": "Animated", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Circular": { + "Name": "Circular", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CurrentPage": { + "Name": "CurrentPage", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EasingDirection": { + "Name": "EasingDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "EasingDirection" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EasingStyle": { + "Name": "EasingStyle", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "EasingStyle" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GamepadInputEnabled": { + "Name": "GamepadInputEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Padding": { + "Name": "Padding", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ScrollWheelInputEnabled": { + "Name": "ScrollWheelInputEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TouchInputEnabled": { + "Name": "TouchInputEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TweenTime": { + "Name": "TweenTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Animated": { + "Type": "Bool", + "Value": true + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Circular": { + "Type": "Bool", + "Value": false + }, + "EasingDirection": { + "Type": "Enum", + "Value": 1 + }, + "EasingStyle": { + "Type": "Enum", + "Value": 2 + }, + "FillDirection": { + "Type": "Enum", + "Value": 0 + }, + "GamepadInputEnabled": { + "Type": "Bool", + "Value": true + }, + "HorizontalAlignment": { + "Type": "Enum", + "Value": 1 + }, + "Padding": { + "Type": "UDim", + "Value": [ + 0.0, + 0 + ] + }, + "ScrollWheelInputEnabled": { + "Type": "Bool", + "Value": true + }, + "SortOrder": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TouchInputEnabled": { + "Type": "Bool", + "Value": true + }, + "TweenTime": { + "Type": "Float32", + "Value": 1.0 + }, + "VerticalAlignment": { + "Type": "Enum", + "Value": 1 + } + } + }, + "UIScale": { + "Name": "UIScale", + "Tags": [], + "Superclass": "UIComponent", + "Properties": { + "Scale": { + "Name": "Scale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Scale": { + "Type": "Float32", + "Value": 1.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "UISizeConstraint": { + "Name": "UISizeConstraint", + "Tags": [], + "Superclass": "UIConstraint", + "Properties": { + "MaxSize": { + "Name": "MaxSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MinSize": { + "Name": "MinSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "MaxSize": { + "Type": "Vector2", + "Value": [ + null, + null + ] + }, + "MinSize": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "UITableLayout": { + "Name": "UITableLayout", + "Tags": [], + "Superclass": "UIGridStyleLayout", + "Properties": { + "FillEmptySpaceColumns": { + "Name": "FillEmptySpaceColumns", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FillEmptySpaceRows": { + "Name": "FillEmptySpaceRows", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MajorAxis": { + "Name": "MajorAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TableMajorAxis" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Padding": { + "Name": "Padding", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "FillDirection": { + "Type": "Enum", + "Value": 1 + }, + "FillEmptySpaceColumns": { + "Type": "Bool", + "Value": false + }, + "FillEmptySpaceRows": { + "Type": "Bool", + "Value": false + }, + "HorizontalAlignment": { + "Type": "Enum", + "Value": 1 + }, + "MajorAxis": { + "Type": "Enum", + "Value": 0 + }, + "Padding": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SortOrder": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "VerticalAlignment": { + "Type": "Enum", + "Value": 1 + } + } + }, + "UITextSizeConstraint": { + "Name": "UITextSizeConstraint", + "Tags": [], + "Superclass": "UIConstraint", + "Properties": { + "MaxTextSize": { + "Name": "MaxTextSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MinTextSize": { + "Name": "MinTextSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "MaxTextSize": { + "Type": "Int32", + "Value": 100 + }, + "MinTextSize": { + "Type": "Int32", + "Value": 1 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "UnionOperation": { + "Name": "UnionOperation", + "Tags": [], + "Superclass": "PartOperation", + "Properties": {}, + "DefaultProperties": { + "Anchored": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 0 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 255, + 255, + 255 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RenderFidelity": { + "Type": "Enum", + "Value": 1 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Size": { + "Type": "Vector3", + "Value": [ + 4.0, + 1.2, + 2.0 + ] + }, + "SmoothingAngle": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 0 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "UsePartColor": { + "Type": "Bool", + "Value": false + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "UniversalConstraint": { + "Name": "UniversalConstraint", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "LimitsEnabled": { + "Name": "LimitsEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxAngle": { + "Name": "MaxAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Radius": { + "Name": "Radius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Restitution": { + "Name": "Restitution", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Int32", + "Value": 1009 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "LimitsEnabled": { + "Type": "Bool", + "Value": false + }, + "MaxAngle": { + "Type": "Float32", + "Value": 45.0 + }, + "Radius": { + "Type": "Float32", + "Value": 0.2 + }, + "Restitution": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "UnvalidatedAssetService": { + "Name": "UnvalidatedAssetService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "UserGameSettings": { + "Name": "UserGameSettings", + "Tags": [ + "NotCreatable", + "UserSettings" + ], + "Superclass": "Instance", + "Properties": { + "AllTutorialsDisabled": { + "Name": "AllTutorialsDisabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraMode": { + "Name": "CameraMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "CustomCameraMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraYInverted": { + "Name": "CameraYInverted", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ChatVisible": { + "Name": "ChatVisible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ComputerCameraMovementMode": { + "Name": "ComputerCameraMovementMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ComputerCameraMovementMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ComputerMovementMode": { + "Name": "ComputerMovementMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ComputerMovementMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ControlMode": { + "Name": "ControlMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ControlMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Fullscreen": { + "Name": "Fullscreen", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GamepadCameraSensitivity": { + "Name": "GamepadCameraSensitivity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GraphicsQualityLevel": { + "Name": "GraphicsQualityLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HasEverUsedVR": { + "Name": "HasEverUsedVR", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsUsingCameraYInverted": { + "Name": "IsUsingCameraYInverted", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsUsingGamepadCameraSensitivity": { + "Name": "IsUsingGamepadCameraSensitivity", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MasterVolume": { + "Name": "MasterVolume", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MicroProfilerWebServerEnabled": { + "Name": "MicroProfilerWebServerEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MicroProfilerWebServerIP": { + "Name": "MicroProfilerWebServerIP", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MicroProfilerWebServerPort": { + "Name": "MicroProfilerWebServerPort", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseSensitivity": { + "Name": "MouseSensitivity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MouseSensitivityFirstPerson": { + "Name": "MouseSensitivityFirstPerson", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MouseSensitivityThirdPerson": { + "Name": "MouseSensitivityThirdPerson", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OnScreenProfilerEnabled": { + "Name": "OnScreenProfilerEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OnboardingsCompleted": { + "Name": "OnboardingsCompleted", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PerformanceStatsVisible": { + "Name": "PerformanceStatsVisible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RCCProfilerRecordFrameRate": { + "Name": "RCCProfilerRecordFrameRate", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RCCProfilerRecordTimeFrame": { + "Name": "RCCProfilerRecordTimeFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RotationType": { + "Name": "RotationType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RotationType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SavedQualityLevel": { + "Name": "SavedQualityLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SavedQualitySetting" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StartMaximized": { + "Name": "StartMaximized", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StartScreenPosition": { + "Name": "StartScreenPosition", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StartScreenSize": { + "Name": "StartScreenSize", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TouchCameraMovementMode": { + "Name": "TouchCameraMovementMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TouchCameraMovementMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TouchMovementMode": { + "Name": "TouchMovementMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TouchMovementMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UsedCoreGuiIsVisibleToggle": { + "Name": "UsedCoreGuiIsVisibleToggle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UsedCustomGuiIsVisibleToggle": { + "Name": "UsedCustomGuiIsVisibleToggle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UsedHideHudShortcut": { + "Name": "UsedHideHudShortcut", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VREnabled": { + "Name": "VREnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VRRotationIntensity": { + "Name": "VRRotationIntensity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "UserInputService": { + "Name": "UserInputService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "AccelerometerEnabled": { + "Name": "AccelerometerEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "BottomBarSize": { + "Name": "BottomBarSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GamepadEnabled": { + "Name": "GamepadEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GazeSelectionEnabled": { + "Name": "GazeSelectionEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GyroscopeEnabled": { + "Name": "GyroscopeEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "KeyboardEnabled": { + "Name": "KeyboardEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LegacyInputEventsEnabled": { + "Name": "LegacyInputEventsEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ModalEnabled": { + "Name": "ModalEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseBehavior": { + "Name": "MouseBehavior", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "MouseBehavior" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MouseDeltaSensitivity": { + "Name": "MouseDeltaSensitivity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseEnabled": { + "Name": "MouseEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseIconEnabled": { + "Name": "MouseIconEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NavBarSize": { + "Name": "NavBarSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "OnScreenKeyboardAnimationDuration": { + "Name": "OnScreenKeyboardAnimationDuration", + "Scriptability": "Read", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "OnScreenKeyboardPosition": { + "Name": "OnScreenKeyboardPosition", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "OnScreenKeyboardSize": { + "Name": "OnScreenKeyboardSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "OnScreenKeyboardVisible": { + "Name": "OnScreenKeyboardVisible", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "OverrideMouseIconBehavior": { + "Name": "OverrideMouseIconBehavior", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "OverrideMouseIconBehavior" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightBarSize": { + "Name": "RightBarSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "StatusBarSize": { + "Name": "StatusBarSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TouchEnabled": { + "Name": "TouchEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UserHeadCFrame": { + "Name": "UserHeadCFrame", + "Scriptability": "Read", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "VREnabled": { + "Name": "VREnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "UserService": { + "Name": "UserService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "UserSettings": { + "Name": "UserSettings", + "Tags": [ + "NotCreatable" + ], + "Superclass": "GenericSettings", + "Properties": {}, + "DefaultProperties": {} + }, + "UserStorageService": { + "Name": "UserStorageService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "LocalStorageService", + "Properties": {}, + "DefaultProperties": {} + }, + "VRService": { + "Name": "VRService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "GuiInputUserCFrame": { + "Name": "GuiInputUserCFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "UserCFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "VRDeviceName": { + "Name": "VRDeviceName", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "VREnabled": { + "Name": "VREnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "ValueBase": { + "Name": "ValueBase", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Vector3Value": { + "Name": "Vector3Value", + "Tags": [], + "Superclass": "ValueBase", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Value": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "VectorForce": { + "Name": "VectorForce", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "ApplyAtCenterOfMass": { + "Name": "ApplyAtCenterOfMass", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Force": { + "Name": "Force", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RelativeTo": { + "Name": "RelativeTo", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ActuatorRelativeTo" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "ApplyAtCenterOfMass": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Color": { + "Type": "Int32", + "Value": 23 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "Force": { + "Type": "Vector3", + "Value": [ + 1000.0, + 0.0, + 0.0 + ] + }, + "RelativeTo": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Visible": { + "Type": "Bool", + "Value": false + } + } + }, + "VehicleController": { + "Name": "VehicleController", + "Tags": [], + "Superclass": "Controller", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "VehicleSeat": { + "Name": "VehicleSeat", + "Tags": [], + "Superclass": "BasePart", + "Properties": { + "AreHingesDetected": { + "Name": "AreHingesDetected", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Disabled": { + "Name": "Disabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HeadsUpDisplay": { + "Name": "HeadsUpDisplay", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxSpeed": { + "Name": "MaxSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Occupant": { + "Name": "Occupant", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Steer": { + "Name": "Steer", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SteerFloat": { + "Name": "SteerFloat", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Throttle": { + "Name": "Throttle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ThrottleFloat": { + "Name": "ThrottleFloat", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Torque": { + "Name": "Torque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TurnSpeed": { + "Name": "TurnSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Anchored": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 4 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 163, + 162, + 165 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "Disabled": { + "Type": "Bool", + "Value": false + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "HeadsUpDisplay": { + "Type": "Bool", + "Value": true + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "MaxSpeed": { + "Type": "Float32", + "Value": 25.0 + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Size": { + "Type": "Vector3", + "Value": [ + 4.0, + 1.2, + 2.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Steer": { + "Type": "Int32", + "Value": 0 + }, + "SteerFloat": { + "Type": "Float32", + "Value": 0.0 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Throttle": { + "Type": "Int32", + "Value": 0 + }, + "ThrottleFloat": { + "Type": "Float32", + "Value": 0.0 + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 3 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Torque": { + "Type": "Float32", + "Value": 10.0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "TurnSpeed": { + "Type": "Float32", + "Value": 1.0 + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "VelocityMotor": { + "Name": "VelocityMotor", + "Tags": [], + "Superclass": "JointInstance", + "Properties": { + "CurrentAngle": { + "Name": "CurrentAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DesiredAngle": { + "Name": "DesiredAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Hole": { + "Name": "Hole", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxVelocity": { + "Name": "MaxVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "C0": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "C1": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CurrentAngle": { + "Type": "Float32", + "Value": 0.0 + }, + "DesiredAngle": { + "Type": "Float32", + "Value": 0.0 + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "MaxVelocity": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "VersionControlService": { + "Name": "VersionControlService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "VideoFrame": { + "Name": "VideoFrame", + "Tags": [], + "Superclass": "GuiObject", + "Properties": { + "IsLoaded": { + "Name": "IsLoaded", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Looped": { + "Name": "Looped", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Playing": { + "Name": "Playing", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Resolution": { + "Name": "Resolution", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TimeLength": { + "Name": "TimeLength", + "Scriptability": "Read", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TimePosition": { + "Name": "TimePosition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Video": { + "Name": "Video", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Volume": { + "Name": "Volume", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Type": "Bool", + "Value": false + }, + "AnchorPoint": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "AutomaticSize": { + "Type": "Enum", + "Value": 0 + }, + "BackgroundColor3": { + "Type": "Color3", + "Value": [ + 0.6392157, + 0.63529414, + 0.64705884 + ] + }, + "BackgroundTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "BorderColor3": { + "Type": "Color3", + "Value": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "BorderMode": { + "Type": "Enum", + "Value": 0 + }, + "BorderSizePixel": { + "Type": "Int32", + "Value": 1 + }, + "ClipsDescendants": { + "Type": "Bool", + "Value": false + }, + "Draggable": { + "Type": "Bool", + "Value": false + }, + "LayoutOrder": { + "Type": "Int32", + "Value": 0 + }, + "Looped": { + "Type": "Bool", + "Value": false + }, + "Playing": { + "Type": "Bool", + "Value": false + }, + "Position": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "Rotation": { + "Type": "Float32", + "Value": 0.0 + }, + "Selectable": { + "Type": "Bool", + "Value": false + }, + "Size": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SizeConstraint": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TimePosition": { + "Type": "Float64", + "Value": 0.0 + }, + "Video": { + "Type": "Content", + "Value": "" + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "Volume": { + "Type": "Float32", + "Value": 1.0 + }, + "ZIndex": { + "Type": "Int32", + "Value": 1 + } + } + }, + "ViewportFrame": { + "Name": "ViewportFrame", + "Tags": [], + "Superclass": "GuiObject", + "Properties": { + "Ambient": { + "Name": "Ambient", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CurrentCamera": { + "Name": "CurrentCamera", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ImageColor3": { + "Name": "ImageColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImageTransparency": { + "Name": "ImageTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LightColor": { + "Name": "LightColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LightDirection": { + "Name": "LightDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Type": "Bool", + "Value": false + }, + "Ambient": { + "Type": "Color3", + "Value": [ + 0.78431374, + 0.78431374, + 0.78431374 + ] + }, + "AnchorPoint": { + "Type": "Vector2", + "Value": [ + 0.0, + 0.0 + ] + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "AutoLocalize": { + "Type": "Bool", + "Value": true + }, + "AutomaticSize": { + "Type": "Enum", + "Value": 0 + }, + "BackgroundColor3": { + "Type": "Color3", + "Value": [ + 0.6392157, + 0.63529414, + 0.64705884 + ] + }, + "BackgroundTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "BorderColor3": { + "Type": "Color3", + "Value": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "BorderMode": { + "Type": "Enum", + "Value": 0 + }, + "BorderSizePixel": { + "Type": "Int32", + "Value": 1 + }, + "ClipsDescendants": { + "Type": "Bool", + "Value": false + }, + "Draggable": { + "Type": "Bool", + "Value": false + }, + "ImageColor3": { + "Type": "Color3", + "Value": [ + 1.0, + 1.0, + 1.0 + ] + }, + "ImageTransparency": { + "Type": "Float32", + "Value": 0.0 + }, + "LayoutOrder": { + "Type": "Int32", + "Value": 0 + }, + "LightColor": { + "Type": "Color3", + "Value": [ + 0.54901963, + 0.54901963, + 0.54901963 + ] + }, + "LightDirection": { + "Type": "Vector3", + "Value": [ + -1.0, + -1.0, + -1.0 + ] + }, + "Position": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "Rotation": { + "Type": "Float32", + "Value": 0.0 + }, + "Selectable": { + "Type": "Bool", + "Value": false + }, + "Size": { + "Type": "UDim2", + "Value": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SizeConstraint": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "Visible": { + "Type": "Bool", + "Value": true + }, + "ZIndex": { + "Type": "Int32", + "Value": 1 + } + } + }, + "VirtualInputManager": { + "Name": "VirtualInputManager", + "Tags": [ + "Service" + ], + "Superclass": "Instance", + "Properties": { + "AdditionalLuaState": { + "Name": "AdditionalLuaState", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "VirtualUser": { + "Name": "VirtualUser", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Visit": { + "Name": "Visit", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "WedgePart": { + "Name": "WedgePart", + "Tags": [], + "Superclass": "FormFactorPart", + "Properties": {}, + "DefaultProperties": { + "Anchored": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BackParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BackParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BackSurface": { + "Type": "Enum", + "Value": 0 + }, + "BackSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "BottomParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "BottomParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "BottomSurface": { + "Type": "Enum", + "Value": 4 + }, + "BottomSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "CFrame": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Type": "Bool", + "Value": true + }, + "CanTouch": { + "Type": "Bool", + "Value": true + }, + "CastShadow": { + "Type": "Bool", + "Value": true + }, + "CollisionGroupId": { + "Type": "Int32", + "Value": 0 + }, + "Color": { + "Type": "Color3uint8", + "Value": [ + 163, + 162, + 165 + ] + }, + "CustomPhysicalProperties": { + "Type": "PhysicalProperties", + "Value": "Default" + }, + "FormFactor": { + "Type": "Enum", + "Value": 1 + }, + "FrontParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "FrontParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "FrontSurface": { + "Type": "Enum", + "Value": 0 + }, + "FrontSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "LeftParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "LeftParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "LeftSurface": { + "Type": "Enum", + "Value": 0 + }, + "LeftSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Locked": { + "Type": "Bool", + "Value": false + }, + "Massless": { + "Type": "Bool", + "Value": false + }, + "Material": { + "Type": "Enum", + "Value": 256 + }, + "Reflectance": { + "Type": "Float32", + "Value": 0.0 + }, + "RightParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "RightParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "RightSurface": { + "Type": "Enum", + "Value": 0 + }, + "RightSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "RootPriority": { + "Type": "Int32", + "Value": 0 + }, + "RotVelocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Size": { + "Type": "Vector3", + "Value": [ + 4.0, + 1.2, + 2.0 + ] + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TopParamA": { + "Type": "Float32", + "Value": -0.5 + }, + "TopParamB": { + "Type": "Float32", + "Value": 0.5 + }, + "TopSurface": { + "Type": "Enum", + "Value": 0 + }, + "TopSurfaceInput": { + "Type": "Enum", + "Value": 0 + }, + "Transparency": { + "Type": "Float32", + "Value": 0.0 + }, + "Velocity": { + "Type": "Vector3", + "Value": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "Weld": { + "Name": "Weld", + "Tags": [], + "Superclass": "JointInstance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "C0": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "C1": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "WeldConstraint": { + "Name": "WeldConstraint", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Active": { + "Name": "Active", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Part0": { + "Name": "Part0", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Part1": { + "Name": "Part1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "Workspace": { + "Name": "Workspace", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "WorldRoot", + "Properties": { + "AllowThirdPartySales": { + "Name": "AllowThirdPartySales", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CollisionGroups": { + "Name": "CollisionGroups", + "Scriptability": "Custom", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CurrentCamera": { + "Name": "CurrentCamera", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DistributedGameTime": { + "Name": "DistributedGameTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FallenPartsDestroyHeight": { + "Name": "FallenPartsDestroyHeight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FilteringEnabled": { + "Name": "FilteringEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Gravity": { + "Name": "Gravity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InterpolationThrottling": { + "Name": "InterpolationThrottling", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "InterpolationThrottlingMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MeshPartHeads": { + "Name": "MeshPartHeads", + "Scriptability": "None", + "DataType": { + "Enum": "MeshPartHeads" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PhysicsSimulationRate": { + "Name": "PhysicsSimulationRate", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "PhysicsSimulationRate" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PhysicsSteppingMethod": { + "Name": "PhysicsSteppingMethod", + "Scriptability": "None", + "DataType": { + "Enum": "PhysicsSteppingMethod" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StreamingEnabled": { + "Name": "StreamingEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StreamingMinRadius": { + "Name": "StreamingMinRadius", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StreamingPauseMode": { + "Name": "StreamingPauseMode", + "Scriptability": "None", + "DataType": { + "Enum": "StreamingPauseMode" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StreamingTargetRadius": { + "Name": "StreamingTargetRadius", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Terrain": { + "Name": "Terrain", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TouchesUseCollisionGroups": { + "Name": "TouchesUseCollisionGroups", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AllowThirdPartySales": { + "Type": "Bool", + "Value": false + }, + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CollisionGroups": { + "Type": "String", + "Value": "Default^0^1" + }, + "DistributedGameTime": { + "Type": "Float64", + "Value": 0.0 + }, + "FallenPartsDestroyHeight": { + "Type": "Float32", + "Value": -500.0 + }, + "FilteringEnabled": { + "Type": "Bool", + "Value": false + }, + "Gravity": { + "Type": "Float32", + "Value": 196.2 + }, + "InterpolationThrottling": { + "Type": "Enum", + "Value": 0 + }, + "LevelOfDetail": { + "Type": "Enum", + "Value": 0 + }, + "MeshPartHeads": { + "Type": "Enum", + "Value": 0 + }, + "PhysicsSteppingMethod": { + "Type": "Enum", + "Value": 0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "StreamingEnabled": { + "Type": "Bool", + "Value": false + }, + "StreamingMinRadius": { + "Type": "Int32", + "Value": 64 + }, + "StreamingPauseMode": { + "Type": "Enum", + "Value": 0 + }, + "StreamingTargetRadius": { + "Type": "Int32", + "Value": 1024 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + }, + "TouchesUseCollisionGroups": { + "Type": "Bool", + "Value": false + } + } + }, + "WorldModel": { + "Name": "WorldModel", + "Tags": [], + "Superclass": "WorldRoot", + "Properties": {}, + "DefaultProperties": {} + }, + "WorldRoot": { + "Name": "WorldRoot", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Model", + "Properties": {}, + "DefaultProperties": {} + }, + "WrapLayer": { + "Name": "WrapLayer", + "Tags": [], + "Superclass": "BaseWrap", + "Properties": { + "BindOffset": { + "Name": "BindOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Color": { + "Name": "Color", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DebugMode": { + "Name": "DebugMode", + "Scriptability": "None", + "DataType": { + "Enum": "WrapLayerDebugMode" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Order": { + "Name": "Order", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Puffiness": { + "Name": "Puffiness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReferenceMeshId": { + "Name": "ReferenceMeshId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReferenceOrigin": { + "Name": "ReferenceOrigin", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReferenceOriginWorld": { + "Name": "ReferenceOriginWorld", + "Scriptability": "Read", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ShrinkFactor": { + "Name": "ShrinkFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "BindOffset": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CageMeshId": { + "Type": "Content", + "Value": "" + }, + "CageOrigin": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Enabled": { + "Type": "Bool", + "Value": true + }, + "ImportOrigin": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Order": { + "Type": "Int32", + "Value": 1 + }, + "Puffiness": { + "Type": "Float32", + "Value": 1.0 + }, + "ReferenceMeshId": { + "Type": "Content", + "Value": "" + }, + "ReferenceOrigin": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ShrinkFactor": { + "Type": "Float32", + "Value": 0.0 + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + }, + "WrapTarget": { + "Name": "WrapTarget", + "Tags": [], + "Superclass": "BaseWrap", + "Properties": { + "Color": { + "Name": "Color", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DebugMode": { + "Name": "DebugMode", + "Scriptability": "None", + "DataType": { + "Enum": "WrapTargetDebugMode" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Stiffness": { + "Name": "Stiffness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "Type": "BinaryString", + "Value": "" + }, + "CageMeshId": { + "Type": "Content", + "Value": "" + }, + "CageOrigin": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ImportOrigin": { + "Type": "CFrame", + "Value": { + "Position": [ + 0.0, + 0.0, + 0.0 + ], + "Orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "SourceAssetId": { + "Type": "Int64", + "Value": -1 + }, + "Stiffness": { + "Type": "Float32", + "Value": 0.9 + }, + "Tags": { + "Type": "BinaryString", + "Value": "" + } + } + } + }, + "Enums": { + "ABTestLoadingStatus": { + "name": "ABTestLoadingStatus", + "items": { + "Error": 3, + "Initialized": 2, + "None": 0, + "Pending": 1, + "ShutOff": 5, + "TimedOut": 4 + } + }, + "ActionType": { + "name": "ActionType", + "items": { + "Draw": 3, + "Lose": 2, + "Nothing": 0, + "Pause": 1, + "Win": 4 + } + }, + "ActuatorRelativeTo": { + "name": "ActuatorRelativeTo", + "items": { + "Attachment0": 0, + "Attachment1": 1, + "World": 2 + } + }, + "ActuatorType": { + "name": "ActuatorType", + "items": { + "Motor": 1, + "None": 0, + "Servo": 2 + } + }, + "AdornCullingMode": { + "name": "AdornCullingMode", + "items": { + "Automatic": 0, + "Never": 1 + } + }, + "AlignType": { + "name": "AlignType", + "items": { + "Parallel": 0, + "Perpendicular": 1 + } + }, + "AlphaMode": { + "name": "AlphaMode", + "items": { + "Overlay": 0, + "Transparency": 1 + } + }, + "AnalyticsEconomyAction": { + "name": "AnalyticsEconomyAction", + "items": { + "Acquire": 1, + "Default": 0, + "Spend": 2 + } + }, + "AnalyticsLogLevel": { + "name": "AnalyticsLogLevel", + "items": { + "Debug": 1, + "Error": 4, + "Fatal": 5, + "Information": 2, + "Trace": 0, + "Warning": 3 + } + }, + "AnalyticsProgressionStatus": { + "name": "AnalyticsProgressionStatus", + "items": { + "Abandon": 3, + "Begin": 1, + "Complete": 2, + "Default": 0, + "Fail": 4 + } + }, + "AnimationPriority": { + "name": "AnimationPriority", + "items": { + "Action": 2, + "Core": 1000, + "Idle": 0, + "Movement": 1 + } + }, + "AppShellActionType": { + "name": "AppShellActionType", + "items": { + "AvatarEditorPageLoaded": 10, + "GamePageLoaded": 8, + "HomePageLoaded": 9, + "None": 0, + "OpenApp": 1, + "ReadConversation": 5, + "TapAvatarTab": 4, + "TapChatTab": 2, + "TapConversationEntry": 3, + "TapGamePageTab": 6, + "TapHomePageTab": 7 + } + }, + "AppShellFeature": { + "name": "AppShellFeature", + "items": { + "AvatarEditor": 2, + "Chat": 1, + "GamePage": 3, + "HomePage": 4, + "Landing": 6, + "More": 5, + "None": 0 + } + }, + "AppUpdateStatus": { + "name": "AppUpdateStatus", + "items": { + "Available": 4, + "Failed": 2, + "NotAvailable": 3, + "NotSupported": 1, + "Unknown": 0 + } + }, + "AspectType": { + "name": "AspectType", + "items": { + "FitWithinMaxSize": 0, + "ScaleWithParentSize": 1 + } + }, + "AssetFetchStatus": { + "name": "AssetFetchStatus", + "items": { + "Failure": 1, + "Success": 0 + } + }, + "AssetType": { + "name": "AssetType", + "items": { + "Animation": 24, + "Audio": 3, + "BackAccessory": 46, + "Badge": 21, + "ClimbAnimation": 48, + "DeathAnimation": 49, + "Decal": 13, + "EarAccessory": 57, + "EmoteAnimation": 61, + "EyeAccessory": 58, + "Face": 18, + "FaceAccessory": 42, + "FallAnimation": 50, + "FrontAccessory": 45, + "GamePass": 34, + "Gear": 19, + "HairAccessory": 41, + "Hat": 8, + "Head": 17, + "IdleAnimation": 51, + "Image": 1, + "JumpAnimation": 52, + "LeftArm": 29, + "LeftLeg": 30, + "Lua": 5, + "Mesh": 4, + "MeshPart": 40, + "Model": 10, + "NeckAccessory": 43, + "Package": 32, + "Pants": 12, + "Place": 9, + "Plugin": 38, + "PoseAnimation": 56, + "RightArm": 28, + "RightLeg": 31, + "RunAnimation": 53, + "Shirt": 11, + "ShoulderAccessory": 44, + "SwimAnimation": 54, + "TeeShirt": 2, + "Torso": 27, + "Video": 62, + "WaistAccessory": 47, + "WalkAnimation": 55 + } + }, + "AssetTypeVerification": { + "name": "AssetTypeVerification", + "items": { + "Always": 3, + "ClientOnly": 2, + "Default": 1 + } + }, + "AutoIndentRule": { + "name": "AutoIndentRule", + "items": { + "Absolute": 1, + "Off": 0, + "Relative": 2 + } + }, + "AutomaticSize": { + "name": "AutomaticSize", + "items": { + "None": 0, + "X": 1, + "XY": 3, + "Y": 2 + } + }, + "AvatarAssetType": { + "name": "AvatarAssetType", + "items": { + "BackAccessory": 46, + "ClimbAnimation": 48, + "EmoteAnimation": 61, + "Face": 18, + "FaceAccessory": 42, + "FallAnimation": 50, + "FrontAccessory": 45, + "Gear": 19, + "HairAccessory": 41, + "Hat": 8, + "Head": 17, + "IdleAnimation": 51, + "JumpAnimation": 52, + "LeftArm": 29, + "LeftLeg": 30, + "NeckAccessory": 43, + "Pants": 12, + "RightArm": 28, + "RightLeg": 31, + "RunAnimation": 53, + "Shirt": 11, + "ShoulderAccessory": 44, + "SwimAnimation": 54, + "TShirt": 2, + "Torso": 27, + "WaistAccessory": 47, + "WalkAnimation": 55 + } + }, + "AvatarContextMenuOption": { + "name": "AvatarContextMenuOption", + "items": { + "Chat": 1, + "Emote": 2, + "Friend": 0, + "InspectMenu": 3 + } + }, + "AvatarItemType": { + "name": "AvatarItemType", + "items": { + "Asset": 1, + "Bundle": 2 + } + }, + "AvatarJointPositionType": { + "name": "AvatarJointPositionType", + "items": { + "ArtistIntent": 1, + "Fixed": 0 + } + }, + "AvatarPromptResult": { + "name": "AvatarPromptResult", + "items": { + "Failed": 3, + "PermissionDenied": 2, + "Success": 1 + } + }, + "Axis": { + "name": "Axis", + "items": { + "X": 0, + "Y": 1, + "Z": 2 + } + }, + "BinType": { + "name": "BinType", + "items": { + "Clone": 3, + "GameTool": 1, + "Grab": 2, + "Hammer": 4, + "Script": 0 + } + }, + "BodyPart": { + "name": "BodyPart", + "items": { + "Head": 0, + "LeftArm": 2, + "LeftLeg": 4, + "RightArm": 3, + "RightLeg": 5, + "Torso": 1 + } + }, + "BodyPartR15": { + "name": "BodyPartR15", + "items": { + "Head": 0, + "LeftFoot": 3, + "LeftHand": 9, + "LeftLowerArm": 10, + "LeftLowerLeg": 4, + "LeftUpperArm": 11, + "LeftUpperLeg": 5, + "LowerTorso": 2, + "RightFoot": 6, + "RightHand": 12, + "RightLowerArm": 13, + "RightLowerLeg": 7, + "RightUpperArm": 14, + "RightUpperLeg": 8, + "RootPart": 15, + "Unknown": 17, + "UpperTorso": 1 + } + }, + "BorderMode": { + "name": "BorderMode", + "items": { + "Inset": 2, + "Middle": 1, + "Outline": 0 + } + }, + "BreakReason": { + "name": "BreakReason", + "items": { + "Error": 1, + "Other": 0, + "SpecialBreakpoint": 2, + "UserBreakpoint": 3 + } + }, + "BulkMoveMode": { + "name": "BulkMoveMode", + "items": { + "FireAllEvents": 0, + "FireCFrameChanged": 1 + } + }, + "BundleType": { + "name": "BundleType", + "items": { + "Animations": 2, + "BodyParts": 1 + } + }, + "Button": { + "name": "Button", + "items": { + "Dismount": 8, + "Jump": 32 + } + }, + "ButtonStyle": { + "name": "ButtonStyle", + "items": { + "Custom": 0, + "RobloxButton": 2, + "RobloxButtonDefault": 1, + "RobloxRoundButton": 3, + "RobloxRoundDefaultButton": 4, + "RobloxRoundDropdownButton": 5 + } + }, + "CameraMode": { + "name": "CameraMode", + "items": { + "Classic": 0, + "LockFirstPerson": 1 + } + }, + "CameraPanMode": { + "name": "CameraPanMode", + "items": { + "Classic": 0, + "EdgeBump": 1 + } + }, + "CameraType": { + "name": "CameraType", + "items": { + "Attach": 1, + "Custom": 5, + "Fixed": 0, + "Follow": 4, + "Orbital": 7, + "Scriptable": 6, + "Track": 3, + "Watch": 2 + } + }, + "CatalogCategoryFilter": { + "name": "CatalogCategoryFilter", + "items": { + "Collectibles": 3, + "CommunityCreations": 4, + "Featured": 2, + "None": 1, + "Premium": 5 + } + }, + "CatalogSortType": { + "name": "CatalogSortType", + "items": { + "MostFavorited": 5, + "PriceHighToLow": 2, + "PriceLowToHigh": 3, + "RecentlyUpdated": 4, + "Relevance": 1 + } + }, + "CellBlock": { + "name": "CellBlock", + "items": { + "CornerWedge": 2, + "HorizontalWedge": 4, + "InverseCornerWedge": 3, + "Solid": 0, + "VerticalWedge": 1 + } + }, + "CellMaterial": { + "name": "CellMaterial", + "items": { + "Aluminum": 7, + "Asphalt": 5, + "BluePlastic": 16, + "Brick": 3, + "Cement": 14, + "CinderBlock": 12, + "Empty": 0, + "Gold": 8, + "Granite": 4, + "Grass": 1, + "Gravel": 11, + "Iron": 6, + "MossyStone": 13, + "RedPlastic": 15, + "Sand": 2, + "Water": 17, + "WoodLog": 10, + "WoodPlank": 9 + } + }, + "CellOrientation": { + "name": "CellOrientation", + "items": { + "NegX": 3, + "NegZ": 0, + "X": 1, + "Z": 2 + } + }, + "CenterDialogType": { + "name": "CenterDialogType", + "items": { + "ModalDialog": 3, + "PlayerInitiatedDialog": 2, + "QuitDialog": 4, + "UnsolicitedDialog": 1 + } + }, + "ChatCallbackType": { + "name": "ChatCallbackType", + "items": { + "OnClientFormattingMessage": 3, + "OnClientSendingMessage": 2, + "OnCreatingChatWindow": 1, + "OnServerReceivingMessage": 17 + } + }, + "ChatColor": { + "name": "ChatColor", + "items": { + "Blue": 0, + "Green": 1, + "Red": 2, + "White": 3 + } + }, + "ChatMode": { + "name": "ChatMode", + "items": { + "Menu": 0, + "TextAndMenu": 1 + } + }, + "ChatPrivacyMode": { + "name": "ChatPrivacyMode", + "items": { + "AllUsers": 0, + "Friends": 2, + "NoOne": 1 + } + }, + "ChatStyle": { + "name": "ChatStyle", + "items": { + "Bubble": 1, + "Classic": 0, + "ClassicAndBubble": 2 + } + }, + "CollisionFidelity": { + "name": "CollisionFidelity", + "items": { + "Box": 2, + "Default": 0, + "Hull": 1, + "PreciseConvexDecomposition": 3 + } + }, + "ComputerCameraMovementMode": { + "name": "ComputerCameraMovementMode", + "items": { + "CameraToggle": 4, + "Classic": 1, + "Default": 0, + "Follow": 2, + "Orbital": 3 + } + }, + "ComputerMovementMode": { + "name": "ComputerMovementMode", + "items": { + "ClickToMove": 2, + "Default": 0, + "KeyboardMouse": 1 + } + }, + "ConnectionError": { + "name": "ConnectionError", + "items": { + "DisconnectBadhash": 257, + "DisconnectBlockedIP": 282, + "DisconnectBySecurityPolicy": 281, + "DisconnectCloudEditKick": 270, + "DisconnectConnectionLost": 277, + "DisconnectDevMaintenance": 274, + "DisconnectDuplicatePlayer": 264, + "DisconnectDuplicateTicket": 265, + "DisconnectErrors": 256, + "DisconnectEvicted": 273, + "DisconnectHashTimeout": 269, + "DisconnectIdle": 278, + "DisconnectIllegalTeleport": 263, + "DisconnectLuaKick": 267, + "DisconnectNewSecurityKeyMismatch": 272, + "DisconnectOnRemoteSysStats": 268, + "DisconnectPlayerless": 271, + "DisconnectProtocolMismatch": 259, + "DisconnectRaknetErrors": 279, + "DisconnectReceivePacketError": 260, + "DisconnectReceivePacketStreamError": 261, + "DisconnectRejoin": 276, + "DisconnectRobloxMaintenance": 275, + "DisconnectSecurityKeyMismatch": 258, + "DisconnectSendPacketError": 262, + "DisconnectTimeout": 266, + "DisconnectWrongVersion": 280, + "OK": 0, + "PlacelaunchCustomMessage": 610, + "PlacelaunchDisabled": 515, + "PlacelaunchError": 516, + "PlacelaunchErrors": 512, + "PlacelaunchFlooded": 525, + "PlacelaunchGameEnded": 517, + "PlacelaunchGameFull": 518, + "PlacelaunchHashException": 527, + "PlacelaunchHashExpired": 526, + "PlacelaunchHttpError": 529, + "PlacelaunchOtherError": 611, + "PlacelaunchPartyCannotFit": 528, + "PlacelaunchRestricted": 523, + "PlacelaunchUnauthorized": 524, + "PlacelaunchUserLeft": 522, + "TeleportErrors": 768, + "TeleportFailure": 769, + "TeleportFlooded": 774, + "TeleportGameEnded": 771, + "TeleportGameFull": 772, + "TeleportGameNotFound": 770, + "TeleportIsTeleporting": 775, + "TeleportUnauthorized": 773 + } + }, + "ConnectionState": { + "name": "ConnectionState", + "items": { + "Connected": 0, + "Disconnected": 1 + } + }, + "ContextActionPriority": { + "name": "ContextActionPriority", + "items": { + "Default": 2000, + "High": 3000, + "Low": 1000, + "Medium": 2000 + } + }, + "ContextActionResult": { + "name": "ContextActionResult", + "items": { + "Pass": 1, + "Sink": 0 + } + }, + "ControlMode": { + "name": "ControlMode", + "items": { + "Classic": 0, + "MouseLockSwitch": 1 + } + }, + "CoreGuiType": { + "name": "CoreGuiType", + "items": { + "All": 4, + "Backpack": 2, + "Chat": 3, + "EmotesMenu": 5, + "Health": 1, + "PlayerList": 0 + } + }, + "CreatorType": { + "name": "CreatorType", + "items": { + "Group": 1, + "User": 0 + } + }, + "CurrencyType": { + "name": "CurrencyType", + "items": { + "Default": 0, + "Robux": 1, + "Tix": 2 + } + }, + "CustomCameraMode": { + "name": "CustomCameraMode", + "items": { + "Classic": 1, + "Default": 0, + "Follow": 2 + } + }, + "DataStoreRequestType": { + "name": "DataStoreRequestType", + "items": { + "GetAsync": 0, + "GetSortedAsync": 3, + "OnUpdate": 5, + "SetIncrementAsync": 1, + "SetIncrementSortedAsync": 4, + "UpdateAsync": 2 + } + }, + "DevCameraOcclusionMode": { + "name": "DevCameraOcclusionMode", + "items": { + "Invisicam": 1, + "Zoom": 0 + } + }, + "DevComputerCameraMovementMode": { + "name": "DevComputerCameraMovementMode", + "items": { + "CameraToggle": 4, + "Classic": 1, + "Follow": 2, + "Orbital": 3, + "UserChoice": 0 + } + }, + "DevComputerMovementMode": { + "name": "DevComputerMovementMode", + "items": { + "ClickToMove": 2, + "KeyboardMouse": 1, + "Scriptable": 3, + "UserChoice": 0 + } + }, + "DevTouchCameraMovementMode": { + "name": "DevTouchCameraMovementMode", + "items": { + "Classic": 1, + "Follow": 2, + "Orbital": 3, + "UserChoice": 0 + } + }, + "DevTouchMovementMode": { + "name": "DevTouchMovementMode", + "items": { + "ClickToMove": 4, + "DPad": 2, + "DynamicThumbstick": 6, + "Scriptable": 5, + "Thumbpad": 3, + "Thumbstick": 1, + "UserChoice": 0 + } + }, + "DeveloperMemoryTag": { + "name": "DeveloperMemoryTag", + "items": { + "Animation": 21, + "GraphicsMeshParts": 9, + "GraphicsParticles": 10, + "GraphicsParts": 11, + "GraphicsSolidModels": 8, + "GraphicsSpatialHash": 12, + "GraphicsTerrain": 13, + "GraphicsTexture": 14, + "GraphicsTextureCharacter": 15, + "Gui": 20, + "HttpCache": 1, + "Instances": 2, + "Internal": 0, + "LuaHeap": 4, + "Navigation": 22, + "PhysicsCollision": 6, + "PhysicsParts": 7, + "Script": 5, + "Signals": 3, + "Sounds": 16, + "StreamingSounds": 17, + "TerrainVoxels": 18 + } + }, + "DeviceType": { + "name": "DeviceType", + "items": { + "Desktop": 1, + "Phone": 3, + "Tablet": 2, + "Unknown": 0 + } + }, + "DialogBehaviorType": { + "name": "DialogBehaviorType", + "items": { + "MultiplePlayers": 1, + "SinglePlayer": 0 + } + }, + "DialogPurpose": { + "name": "DialogPurpose", + "items": { + "Help": 1, + "Quest": 0, + "Shop": 2 + } + }, + "DialogTone": { + "name": "DialogTone", + "items": { + "Enemy": 2, + "Friendly": 1, + "Neutral": 0 + } + }, + "DominantAxis": { + "name": "DominantAxis", + "items": { + "Height": 1, + "Width": 0 + } + }, + "DraftStatusCode": { + "name": "DraftStatusCode", + "items": { + "DraftCommitted": 3, + "DraftOutdated": 1, + "OK": 0, + "ScriptRemoved": 2 + } + }, + "EasingDirection": { + "name": "EasingDirection", + "items": { + "In": 0, + "InOut": 2, + "Out": 1 + } + }, + "EasingStyle": { + "name": "EasingStyle", + "items": { + "Back": 2, + "Bounce": 6, + "Circular": 9, + "Cubic": 10, + "Elastic": 7, + "Exponential": 8, + "Linear": 0, + "Quad": 3, + "Quart": 4, + "Quint": 5, + "Sine": 1 + } + }, + "ElasticBehavior": { + "name": "ElasticBehavior", + "items": { + "Always": 1, + "Never": 2, + "WhenScrollable": 0 + } + }, + "EnviromentalPhysicsThrottle": { + "name": "EnviromentalPhysicsThrottle", + "items": { + "Always": 2, + "DefaultAuto": 0, + "Disabled": 1, + "Skip16": 6, + "Skip2": 3, + "Skip4": 4, + "Skip8": 5 + } + }, + "ExplosionType": { + "name": "ExplosionType", + "items": { + "Craters": 1, + "NoCraters": 0 + } + }, + "FieldOfViewMode": { + "name": "FieldOfViewMode", + "items": { + "Diagonal": 1, + "MaxAxis": 2, + "Vertical": 0 + } + }, + "FillDirection": { + "name": "FillDirection", + "items": { + "Horizontal": 0, + "Vertical": 1 + } + }, + "FilterResult": { + "name": "FilterResult", + "items": { + "Accepted": 0, + "Rejected": 1 + } + }, + "Font": { + "name": "Font", + "items": { + "AmaticSC": 21, + "Antique": 15, + "Arcade": 13, + "Arial": 1, + "ArialBold": 2, + "Bangers": 22, + "Bodoni": 7, + "Cartoon": 9, + "Code": 10, + "Creepster": 23, + "DenkOne": 24, + "Fantasy": 14, + "Fondamento": 25, + "FredokaOne": 26, + "Garamond": 8, + "Gotham": 17, + "GothamBlack": 20, + "GothamBold": 19, + "GothamSemibold": 18, + "GrenzeGotisch": 27, + "Highway": 11, + "IndieFlower": 28, + "JosefinSans": 29, + "Jura": 30, + "Kalam": 31, + "Legacy": 0, + "LuckiestGuy": 32, + "Merriweather": 33, + "Michroma": 34, + "Nunito": 35, + "Oswald": 36, + "PatrickHand": 37, + "PermanentMarker": 38, + "Roboto": 39, + "RobotoCondensed": 40, + "RobotoMono": 41, + "Sarpanch": 42, + "SciFi": 12, + "SourceSans": 3, + "SourceSansBold": 4, + "SourceSansItalic": 6, + "SourceSansLight": 5, + "SourceSansSemibold": 16, + "SpecialElite": 43, + "TitilliumWeb": 44, + "Ubuntu": 45 + } + }, + "FontSize": { + "name": "FontSize", + "items": { + "Size10": 2, + "Size11": 3, + "Size12": 4, + "Size14": 5, + "Size18": 6, + "Size24": 7, + "Size28": 10, + "Size32": 11, + "Size36": 8, + "Size42": 12, + "Size48": 9, + "Size60": 13, + "Size8": 0, + "Size9": 1, + "Size96": 14 + } + }, + "FormFactor": { + "name": "FormFactor", + "items": { + "Brick": 1, + "Custom": 3, + "Plate": 2, + "Symmetric": 0 + } + }, + "FrameStyle": { + "name": "FrameStyle", + "items": { + "ChatBlue": 1, + "ChatGreen": 4, + "ChatRed": 5, + "Custom": 0, + "DropShadow": 6, + "RobloxRound": 3, + "RobloxSquare": 2 + } + }, + "FramerateManagerMode": { + "name": "FramerateManagerMode", + "items": { + "Automatic": 0, + "Off": 2, + "On": 1 + } + }, + "FriendRequestEvent": { + "name": "FriendRequestEvent", + "items": { + "Accept": 2, + "Deny": 3, + "Issue": 0, + "Revoke": 1 + } + }, + "FriendStatus": { + "name": "FriendStatus", + "items": { + "Friend": 2, + "FriendRequestReceived": 4, + "FriendRequestSent": 3, + "NotFriend": 1, + "Unknown": 0 + } + }, + "FunctionalTestResult": { + "name": "FunctionalTestResult", + "items": { + "Error": 2, + "Passed": 0, + "Warning": 1 + } + }, + "GameAvatarType": { + "name": "GameAvatarType", + "items": { + "PlayerChoice": 2, + "R15": 1, + "R6": 0 + } + }, + "GearGenreSetting": { + "name": "GearGenreSetting", + "items": { + "AllGenres": 0, + "MatchingGenreOnly": 1 + } + }, + "GearType": { + "name": "GearType", + "items": { + "BuildingTools": 7, + "Explosives": 2, + "MeleeWeapons": 0, + "MusicalInstruments": 5, + "NavigationEnhancers": 4, + "PowerUps": 3, + "RangedWeapons": 1, + "SocialItems": 6, + "Transport": 8 + } + }, + "Genre": { + "name": "Genre", + "items": { + "Adventure": 7, + "All": 0, + "Fantasy": 2, + "Funny": 9, + "Ninja": 4, + "Pirate": 6, + "Scary": 5, + "SciFi": 3, + "SkatePark": 12, + "Sports": 8, + "TownAndCity": 1, + "Tutorial": 13, + "War": 11, + "WildWest": 10 + } + }, + "GraphicsMode": { + "name": "GraphicsMode", + "items": { + "Automatic": 1, + "Direct3D11": 2, + "Direct3D9": 3, + "Metal": 5, + "NoGraphics": 7, + "OpenGL": 4, + "Vulkan": 6 + } + }, + "HandlesStyle": { + "name": "HandlesStyle", + "items": { + "Movement": 1, + "Resize": 0 + } + }, + "HorizontalAlignment": { + "name": "HorizontalAlignment", + "items": { + "Center": 0, + "Left": 1, + "Right": 2 + } + }, + "HoverAnimateSpeed": { + "name": "HoverAnimateSpeed", + "items": { + "Fast": 3, + "Medium": 2, + "Slow": 1, + "VeryFast": 4, + "VerySlow": 0 + } + }, + "HttpCachePolicy": { + "name": "HttpCachePolicy", + "items": { + "DataOnly": 2, + "Default": 3, + "Full": 1, + "InternalRedirectRefresh": 4, + "None": 0 + } + }, + "HttpContentType": { + "name": "HttpContentType", + "items": { + "ApplicationJson": 0, + "ApplicationUrlEncoded": 2, + "ApplicationXml": 1, + "TextPlain": 3, + "TextXml": 4 + } + }, + "HttpError": { + "name": "HttpError", + "items": { + "Aborted": 9, + "ConnectFail": 3, + "DnsResolve": 2, + "InvalidRedirect": 7, + "InvalidUrl": 1, + "NetFail": 8, + "OK": 0, + "OutOfMemory": 4, + "SslConnectFail": 10, + "SslVerificationFail": 11, + "TimedOut": 5, + "TooManyRedirects": 6, + "Unknown": 12 + } + }, + "HttpRequestType": { + "name": "HttpRequestType", + "items": { + "Analytics": 23, + "Avatar": 16, + "Chat": 15, + "Default": 0, + "Localization": 25, + "MarketplaceService": 2, + "Players": 7 + } + }, + "HumanoidCollisionType": { + "name": "HumanoidCollisionType", + "items": { + "InnerBox": 1, + "OuterBox": 0 + } + }, + "HumanoidDisplayDistanceType": { + "name": "HumanoidDisplayDistanceType", + "items": { + "None": 2, + "Subject": 1, + "Viewer": 0 + } + }, + "HumanoidHealthDisplayType": { + "name": "HumanoidHealthDisplayType", + "items": { + "AlwaysOff": 2, + "AlwaysOn": 1, + "DisplayWhenDamaged": 0 + } + }, + "HumanoidRigType": { + "name": "HumanoidRigType", + "items": { + "R15": 1, + "R6": 0 + } + }, + "HumanoidStateType": { + "name": "HumanoidStateType", + "items": { + "Climbing": 12, + "Dead": 15, + "FallingDown": 0, + "Flying": 6, + "Freefall": 5, + "GettingUp": 2, + "Jumping": 3, + "Landed": 7, + "None": 18, + "Physics": 16, + "PlatformStanding": 14, + "Ragdoll": 1, + "Running": 8, + "RunningNoPhysics": 10, + "Seated": 13, + "StrafingNoPhysics": 11, + "Swimming": 4 + } + }, + "IKCollisionsMode": { + "name": "IKCollisionsMode", + "items": { + "IncludeContactedMechanisms": 2, + "NoCollisions": 0, + "OtherMechanismsAnchored": 1 + } + }, + "IXPLoadingStatus": { + "name": "IXPLoadingStatus", + "items": { + "ErrorConnection": 5, + "ErrorInvalidUser": 4, + "ErrorJsonParse": 6, + "ErrorTimedOut": 7, + "Initialized": 2, + "None": 0, + "Pending": 1, + "ShutOff": 3 + } + }, + "InOut": { + "name": "InOut", + "items": { + "Center": 2, + "Edge": 0, + "Inset": 1 + } + }, + "InfoType": { + "name": "InfoType", + "items": { + "Asset": 0, + "Bundle": 4, + "GamePass": 2, + "Product": 1, + "Subscription": 3 + } + }, + "InitialDockState": { + "name": "InitialDockState", + "items": { + "Bottom": 1, + "Float": 4, + "Left": 2, + "Right": 3, + "Top": 0 + } + }, + "InputType": { + "name": "InputType", + "items": { + "Constant": 12, + "NoInput": 0, + "Sin": 13 + } + }, + "InterpolationThrottlingMode": { + "name": "InterpolationThrottlingMode", + "items": { + "Default": 0, + "Disabled": 1, + "Enabled": 2 + } + }, + "JointCreationMode": { + "name": "JointCreationMode", + "items": { + "All": 0, + "None": 2, + "Surface": 1 + } + }, + "KeyCode": { + "name": "KeyCode", + "items": { + "A": 97, + "Ampersand": 38, + "Asterisk": 42, + "At": 64, + "B": 98, + "BackSlash": 92, + "Backquote": 96, + "Backspace": 8, + "Break": 318, + "ButtonA": 1002, + "ButtonB": 1003, + "ButtonL1": 1005, + "ButtonL2": 1007, + "ButtonL3": 1009, + "ButtonR1": 1004, + "ButtonR2": 1006, + "ButtonR3": 1008, + "ButtonSelect": 1011, + "ButtonStart": 1010, + "ButtonX": 1000, + "ButtonY": 1001, + "C": 99, + "CapsLock": 301, + "Caret": 94, + "Clear": 12, + "Colon": 58, + "Comma": 44, + "Compose": 314, + "D": 100, + "DPadDown": 1015, + "DPadLeft": 1012, + "DPadRight": 1013, + "DPadUp": 1014, + "Delete": 127, + "Dollar": 36, + "Down": 274, + "E": 101, + "Eight": 56, + "End": 279, + "Equals": 61, + "Escape": 27, + "Euro": 321, + "F": 102, + "F1": 282, + "F10": 291, + "F11": 292, + "F12": 293, + "F13": 294, + "F14": 295, + "F15": 296, + "F2": 283, + "F3": 284, + "F4": 285, + "F5": 286, + "F6": 287, + "F7": 288, + "F8": 289, + "F9": 290, + "Five": 53, + "Four": 52, + "G": 103, + "GreaterThan": 62, + "H": 104, + "Hash": 35, + "Help": 315, + "Home": 278, + "I": 105, + "Insert": 277, + "J": 106, + "K": 107, + "KeypadDivide": 267, + "KeypadEight": 264, + "KeypadEnter": 271, + "KeypadEquals": 272, + "KeypadFive": 261, + "KeypadFour": 260, + "KeypadMinus": 269, + "KeypadMultiply": 268, + "KeypadNine": 265, + "KeypadOne": 257, + "KeypadPeriod": 266, + "KeypadPlus": 270, + "KeypadSeven": 263, + "KeypadSix": 262, + "KeypadThree": 259, + "KeypadTwo": 258, + "KeypadZero": 256, + "L": 108, + "Left": 276, + "LeftAlt": 308, + "LeftBracket": 91, + "LeftControl": 306, + "LeftCurly": 123, + "LeftMeta": 310, + "LeftParenthesis": 40, + "LeftShift": 304, + "LeftSuper": 311, + "LessThan": 60, + "M": 109, + "Menu": 319, + "Minus": 45, + "Mode": 313, + "N": 110, + "Nine": 57, + "NumLock": 300, + "O": 111, + "One": 49, + "P": 112, + "PageDown": 281, + "PageUp": 280, + "Pause": 19, + "Percent": 37, + "Period": 46, + "Pipe": 124, + "Plus": 43, + "Power": 320, + "Print": 316, + "Q": 113, + "Question": 63, + "Quote": 39, + "QuotedDouble": 34, + "R": 114, + "Return": 13, + "Right": 275, + "RightAlt": 307, + "RightBracket": 93, + "RightControl": 305, + "RightCurly": 125, + "RightMeta": 309, + "RightParenthesis": 41, + "RightShift": 303, + "RightSuper": 312, + "S": 115, + "ScrollLock": 302, + "Semicolon": 59, + "Seven": 55, + "Six": 54, + "Slash": 47, + "Space": 32, + "SysReq": 317, + "T": 116, + "Tab": 9, + "Three": 51, + "Thumbstick1": 1016, + "Thumbstick2": 1017, + "Tilde": 126, + "Two": 50, + "U": 117, + "Underscore": 95, + "Undo": 322, + "Unknown": 0, + "Up": 273, + "V": 118, + "W": 119, + "World0": 160, + "World1": 161, + "World10": 170, + "World11": 171, + "World12": 172, + "World13": 173, + "World14": 174, + "World15": 175, + "World16": 176, + "World17": 177, + "World18": 178, + "World19": 179, + "World2": 162, + "World20": 180, + "World21": 181, + "World22": 182, + "World23": 183, + "World24": 184, + "World25": 185, + "World26": 186, + "World27": 187, + "World28": 188, + "World29": 189, + "World3": 163, + "World30": 190, + "World31": 191, + "World32": 192, + "World33": 193, + "World34": 194, + "World35": 195, + "World36": 196, + "World37": 197, + "World38": 198, + "World39": 199, + "World4": 164, + "World40": 200, + "World41": 201, + "World42": 202, + "World43": 203, + "World44": 204, + "World45": 205, + "World46": 206, + "World47": 207, + "World48": 208, + "World49": 209, + "World5": 165, + "World50": 210, + "World51": 211, + "World52": 212, + "World53": 213, + "World54": 214, + "World55": 215, + "World56": 216, + "World57": 217, + "World58": 218, + "World59": 219, + "World6": 166, + "World60": 220, + "World61": 221, + "World62": 222, + "World63": 223, + "World64": 224, + "World65": 225, + "World66": 226, + "World67": 227, + "World68": 228, + "World69": 229, + "World7": 167, + "World70": 230, + "World71": 231, + "World72": 232, + "World73": 233, + "World74": 234, + "World75": 235, + "World76": 236, + "World77": 237, + "World78": 238, + "World79": 239, + "World8": 168, + "World80": 240, + "World81": 241, + "World82": 242, + "World83": 243, + "World84": 244, + "World85": 245, + "World86": 246, + "World87": 247, + "World88": 248, + "World89": 249, + "World9": 169, + "World90": 250, + "World91": 251, + "World92": 252, + "World93": 253, + "World94": 254, + "World95": 255, + "X": 120, + "Y": 121, + "Z": 122, + "Zero": 48 + } + }, + "KeywordFilterType": { + "name": "KeywordFilterType", + "items": { + "Exclude": 1, + "Include": 0 + } + }, + "Language": { + "name": "Language", + "items": { + "Default": 0 + } + }, + "LanguagePreference": { + "name": "LanguagePreference", + "items": { + "English": 1, + "Korean": 3, + "SimplifiedChinese": 2, + "SystemDefault": 0 + } + }, + "LeftRight": { + "name": "LeftRight", + "items": { + "Center": 1, + "Left": 0, + "Right": 2 + } + }, + "LevelOfDetailSetting": { + "name": "LevelOfDetailSetting", + "items": { + "High": 2, + "Low": 0, + "Medium": 1 + } + }, + "Limb": { + "name": "Limb", + "items": { + "Head": 0, + "LeftArm": 2, + "LeftLeg": 4, + "RightArm": 3, + "RightLeg": 5, + "Torso": 1, + "Unknown": 6 + } + }, + "ListDisplayMode": { + "name": "ListDisplayMode", + "items": { + "Horizontal": 0, + "Vertical": 1 + } + }, + "ListenerType": { + "name": "ListenerType", + "items": { + "CFrame": 1, + "Camera": 0, + "ObjectCFrame": 3, + "ObjectPosition": 2 + } + }, + "Material": { + "name": "Material", + "items": { + "Air": 1792, + "Asphalt": 1376, + "Basalt": 788, + "Brick": 848, + "Cobblestone": 880, + "Concrete": 816, + "CorrodedMetal": 1040, + "CrackedLava": 804, + "DiamondPlate": 1056, + "Fabric": 1312, + "Foil": 1072, + "ForceField": 1584, + "Glacier": 1552, + "Glass": 1568, + "Granite": 832, + "Grass": 1280, + "Ground": 1360, + "Ice": 1536, + "LeafyGrass": 1284, + "Limestone": 820, + "Marble": 784, + "Metal": 1088, + "Mud": 1344, + "Neon": 288, + "Pavement": 836, + "Pebble": 864, + "Plastic": 256, + "Rock": 896, + "Salt": 1392, + "Sand": 1296, + "Sandstone": 912, + "Slate": 800, + "SmoothPlastic": 272, + "Snow": 1328, + "Water": 2048, + "Wood": 512, + "WoodPlanks": 528 + } + }, + "MembershipType": { + "name": "MembershipType", + "items": { + "BuildersClub": 1, + "None": 0, + "OutrageousBuildersClub": 3, + "Premium": 4, + "TurboBuildersClub": 2 + } + }, + "MeshPartDetailLevel": { + "name": "MeshPartDetailLevel", + "items": { + "DistanceBased": 0, + "Level01": 1, + "Level02": 2, + "Level03": 3, + "Level04": 4 + } + }, + "MeshPartHeads": { + "name": "MeshPartHeads", + "items": { + "Default": 0, + "Disabled": 1, + "Enabled": 2 + } + }, + "MeshType": { + "name": "MeshType", + "items": { + "Brick": 6, + "CornerWedge": 11, + "Cylinder": 4, + "FileMesh": 5, + "Head": 0, + "ParallelRamp": 9, + "Prism": 7, + "Pyramid": 8, + "RightAngleRamp": 10, + "Sphere": 3, + "Torso": 1, + "Wedge": 2 + } + }, + "MessageType": { + "name": "MessageType", + "items": { + "MessageError": 3, + "MessageInfo": 1, + "MessageOutput": 0, + "MessageWarning": 2 + } + }, + "ModelLevelOfDetail": { + "name": "ModelLevelOfDetail", + "items": { + "Automatic": 0, + "Disabled": 2, + "StreamingMesh": 1 + } + }, + "ModifierKey": { + "name": "ModifierKey", + "items": { + "Alt": 2, + "Ctrl": 1, + "Meta": 3, + "Shift": 0 + } + }, + "MouseBehavior": { + "name": "MouseBehavior", + "items": { + "Default": 0, + "LockCenter": 1, + "LockCurrentPosition": 2 + } + }, + "MoveState": { + "name": "MoveState", + "items": { + "AirFree": 4, + "Coasting": 1, + "Pushing": 2, + "Stopped": 0, + "Stopping": 3 + } + }, + "NameOcclusion": { + "name": "NameOcclusion", + "items": { + "EnemyOcclusion": 1, + "NoOcclusion": 0, + "OccludeAll": 2 + } + }, + "NetworkOwnership": { + "name": "NetworkOwnership", + "items": { + "Automatic": 0, + "Manual": 1, + "OnContact": 2 + } + }, + "NormalId": { + "name": "NormalId", + "items": { + "Back": 2, + "Bottom": 4, + "Front": 5, + "Left": 3, + "Right": 0, + "Top": 1 + } + }, + "OutputLayoutMode": { + "name": "OutputLayoutMode", + "items": { + "Horizontal": 0, + "Vertical": 1 + } + }, + "OverrideMouseIconBehavior": { + "name": "OverrideMouseIconBehavior", + "items": { + "ForceHide": 2, + "ForceShow": 1, + "None": 0 + } + }, + "PacketPriority": { + "name": "PacketPriority", + "items": { + "HIGH_PRIORITY": 1, + "IMMEDIATE_PRIORITY": 0, + "LOW_PRIORITY": 3, + "MEDIUM_PRIORITY": 2 + } + }, + "PartType": { + "name": "PartType", + "items": { + "Ball": 0, + "Block": 1, + "Cylinder": 2 + } + }, + "ParticleOrientation": { + "name": "ParticleOrientation", + "items": { + "FacingCamera": 0, + "FacingCameraWorldUp": 1, + "VelocityParallel": 2, + "VelocityPerpendicular": 3 + } + }, + "PathStatus": { + "name": "PathStatus", + "items": { + "ClosestNoPath": 1, + "ClosestOutOfRange": 2, + "FailFinishNotEmpty": 4, + "FailStartNotEmpty": 3, + "NoPath": 5, + "Success": 0 + } + }, + "PathWaypointAction": { + "name": "PathWaypointAction", + "items": { + "Jump": 1, + "Walk": 0 + } + }, + "PermissionLevelShown": { + "name": "PermissionLevelShown", + "items": { + "Game": 0, + "Roblox": 4, + "RobloxGame": 1, + "RobloxScript": 2, + "Studio": 3 + } + }, + "PhysicsSimulationRate": { + "name": "PhysicsSimulationRate", + "items": { + "Fixed120Hz": 1, + "Fixed240Hz": 0, + "Fixed60Hz": 2 + } + }, + "PhysicsSteppingMethod": { + "name": "PhysicsSteppingMethod", + "items": { + "Adaptive": 2, + "Default": 0, + "Fixed": 1 + } + }, + "Platform": { + "name": "Platform", + "items": { + "Android": 3, + "AndroidTV": 11, + "BeOS": 17, + "Chromecast": 12, + "DOS": 16, + "IOS": 2, + "Linux": 13, + "NX": 9, + "None": 19, + "OSX": 1, + "Ouya": 10, + "PS3": 6, + "PS4": 5, + "SteamOS": 14, + "UWP": 18, + "WebOS": 15, + "WiiU": 8, + "Windows": 0, + "XBox360": 7, + "XBoxOne": 4 + } + }, + "PlaybackState": { + "name": "PlaybackState", + "items": { + "Begin": 0, + "Cancelled": 5, + "Completed": 4, + "Delayed": 1, + "Paused": 3, + "Playing": 2 + } + }, + "PlayerActions": { + "name": "PlayerActions", + "items": { + "CharacterBackward": 1, + "CharacterForward": 0, + "CharacterJump": 4, + "CharacterLeft": 2, + "CharacterRight": 3 + } + }, + "PlayerChatType": { + "name": "PlayerChatType", + "items": { + "All": 0, + "Team": 1, + "Whisper": 2 + } + }, + "PoseEasingDirection": { + "name": "PoseEasingDirection", + "items": { + "In": 0, + "InOut": 2, + "Out": 1 + } + }, + "PoseEasingStyle": { + "name": "PoseEasingStyle", + "items": { + "Bounce": 4, + "Constant": 1, + "Cubic": 3, + "Elastic": 2, + "Linear": 0 + } + }, + "PrivilegeType": { + "name": "PrivilegeType", + "items": { + "Admin": 240, + "Banned": 0, + "Member": 128, + "Owner": 255, + "Visitor": 10 + } + }, + "ProductPurchaseDecision": { + "name": "ProductPurchaseDecision", + "items": { + "NotProcessedYet": 0, + "PurchaseGranted": 1 + } + }, + "ProximityPromptExclusivity": { + "name": "ProximityPromptExclusivity", + "items": { + "AlwaysShow": 2, + "OneGlobally": 1, + "OnePerButton": 0 + } + }, + "ProximityPromptInputType": { + "name": "ProximityPromptInputType", + "items": { + "Gamepad": 1, + "Keyboard": 0, + "Touch": 2 + } + }, + "ProximityPromptStyle": { + "name": "ProximityPromptStyle", + "items": { + "Custom": 1, + "Default": 0 + } + }, + "QualityLevel": { + "name": "QualityLevel", + "items": { + "Automatic": 0, + "Level01": 1, + "Level02": 2, + "Level03": 3, + "Level04": 4, + "Level05": 5, + "Level06": 6, + "Level07": 7, + "Level08": 8, + "Level09": 9, + "Level10": 10, + "Level11": 11, + "Level12": 12, + "Level13": 13, + "Level14": 14, + "Level15": 15, + "Level16": 16, + "Level17": 17, + "Level18": 18, + "Level19": 19, + "Level20": 20, + "Level21": 21 + } + }, + "R15CollisionType": { + "name": "R15CollisionType", + "items": { + "InnerBox": 1, + "OuterBox": 0 + } + }, + "RaycastFilterType": { + "name": "RaycastFilterType", + "items": { + "Blacklist": 0, + "Whitelist": 1 + } + }, + "RenderFidelity": { + "name": "RenderFidelity", + "items": { + "Automatic": 0, + "Performance": 2, + "Precise": 1 + } + }, + "RenderPriority": { + "name": "RenderPriority", + "items": { + "Camera": 200, + "Character": 300, + "First": 0, + "Input": 100, + "Last": 2000 + } + }, + "RenderingTestComparisonMethod": { + "name": "RenderingTestComparisonMethod", + "items": { + "diff": 1, + "psnr": 0 + } + }, + "ReturnKeyType": { + "name": "ReturnKeyType", + "items": { + "Default": 0, + "Done": 1, + "Go": 2, + "Next": 3, + "Search": 4, + "Send": 5 + } + }, + "ReverbType": { + "name": "ReverbType", + "items": { + "Alley": 15, + "Arena": 10, + "Auditorium": 7, + "Bathroom": 4, + "CarpettedHallway": 12, + "Cave": 9, + "City": 17, + "ConcertHall": 8, + "Forest": 16, + "GenericReverb": 1, + "Hallway": 13, + "Hangar": 11, + "LivingRoom": 5, + "Mountains": 18, + "NoReverb": 0, + "PaddedCell": 2, + "ParkingLot": 21, + "Plain": 20, + "Quarry": 19, + "Room": 3, + "SewerPipe": 22, + "StoneCorridor": 14, + "StoneRoom": 6, + "UnderWater": 23 + } + }, + "RibbonTool": { + "name": "RibbonTool", + "items": { + "ColorPicker": 5, + "Group": 7, + "MaterialPicker": 6, + "Move": 3, + "None": 9, + "Rotate": 2, + "Scale": 1, + "Select": 0, + "Transform": 4, + "Ungroup": 8 + } + }, + "RollOffMode": { + "name": "RollOffMode", + "items": { + "Inverse": 0, + "InverseTapered": 3, + "Linear": 1, + "LinearSquare": 2 + } + }, + "RotationType": { + "name": "RotationType", + "items": { + "CameraRelative": 1, + "MovementRelative": 0 + } + }, + "RuntimeUndoBehavior": { + "name": "RuntimeUndoBehavior", + "items": { + "Aggregate": 0, + "Hybrid": 2, + "Snapshot": 1 + } + }, + "SaveFilter": { + "name": "SaveFilter", + "items": { + "SaveAll": 2, + "SaveGame": 1, + "SaveWorld": 0 + } + }, + "SavedQualitySetting": { + "name": "SavedQualitySetting", + "items": { + "Automatic": 0, + "QualityLevel1": 1, + "QualityLevel10": 10, + "QualityLevel2": 2, + "QualityLevel3": 3, + "QualityLevel4": 4, + "QualityLevel5": 5, + "QualityLevel6": 6, + "QualityLevel7": 7, + "QualityLevel8": 8, + "QualityLevel9": 9 + } + }, + "ScaleType": { + "name": "ScaleType", + "items": { + "Crop": 4, + "Fit": 3, + "Slice": 1, + "Stretch": 0, + "Tile": 2 + } + }, + "ScreenOrientation": { + "name": "ScreenOrientation", + "items": { + "LandscapeLeft": 0, + "LandscapeRight": 1, + "LandscapeSensor": 2, + "Portrait": 3, + "Sensor": 4 + } + }, + "ScrollBarInset": { + "name": "ScrollBarInset", + "items": { + "Always": 2, + "None": 0, + "ScrollBar": 1 + } + }, + "ScrollingDirection": { + "name": "ScrollingDirection", + "items": { + "X": 1, + "XY": 4, + "Y": 2 + } + }, + "ServerAudioBehavior": { + "name": "ServerAudioBehavior", + "items": { + "Enabled": 0, + "Muted": 1, + "OnlineGame": 2 + } + }, + "SizeConstraint": { + "name": "SizeConstraint", + "items": { + "RelativeXX": 1, + "RelativeXY": 0, + "RelativeYY": 2 + } + }, + "SortDirection": { + "name": "SortDirection", + "items": { + "Ascending": 0, + "Descending": 1 + } + }, + "SortOrder": { + "name": "SortOrder", + "items": { + "Custom": 1, + "LayoutOrder": 2, + "Name": 0 + } + }, + "SoundType": { + "name": "SoundType", + "items": { + "Boing": 1, + "Bomb": 2, + "Break": 3, + "Click": 4, + "Clock": 5, + "NoSound": 0, + "Page": 7, + "Ping": 8, + "Slingshot": 6, + "Snap": 9, + "Splat": 10, + "Step": 11, + "StepOn": 12, + "Swoosh": 13, + "Victory": 14 + } + }, + "SpecialKey": { + "name": "SpecialKey", + "items": { + "ChatHotkey": 5, + "End": 2, + "Home": 1, + "Insert": 0, + "PageDown": 4, + "PageUp": 3 + } + }, + "StartCorner": { + "name": "StartCorner", + "items": { + "BottomLeft": 2, + "BottomRight": 3, + "TopLeft": 0, + "TopRight": 1 + } + }, + "Status": { + "name": "Status", + "items": { + "Confusion": 1, + "Poison": 0 + } + }, + "StreamingPauseMode": { + "name": "StreamingPauseMode", + "items": { + "ClientPhysicsPause": 2, + "Default": 0, + "Disabled": 1 + } + }, + "StudioDataModelType": { + "name": "StudioDataModelType", + "items": { + "Edit": 0, + "None": 6, + "PlayClient": 2, + "PlayServer": 3, + "RobloxPlugin": 4, + "UserPlugin": 5 + } + }, + "StudioScriptEditorColorCategories": { + "name": "StudioScriptEditorColorCategories", + "items": { + "ActiveLine": 25, + "Background": 17, + "Bool": 10, + "Bracket": 29, + "Builtin": 6, + "Comment": 4, + "DebuggerCurrentLine": 26, + "DebuggerErrorLine": 27, + "Default": 0, + "Error": 23, + "FindSelectionBackground": 20, + "Function": 11, + "FunctionName": 15, + "Keyword": 5, + "Local": 12, + "LuauKeyword": 14, + "MatchingWordBackground": 21, + "Method": 7, + "Nil": 9, + "Number": 2, + "Operator": 1, + "Property": 8, + "Ruler": 28, + "SelectionBackground": 19, + "SelectionText": 18, + "Self": 13, + "String": 3, + "TODO": 16, + "Warning": 22, + "Whitespace": 24 + } + }, + "StudioScriptEditorColorPresets": { + "name": "StudioScriptEditorColorPresets", + "items": { + "Custom": 3, + "Extra1": 1, + "Extra2": 2, + "RobloxDefault": 0 + } + }, + "StudioStyleGuideColor": { + "name": "StudioStyleGuideColor", + "items": { + "AttributeCog": 109, + "Border": 25, + "BrightText": 33, + "Button": 11, + "ButtonBorder": 81, + "ButtonText": 82, + "CategoryItem": 18, + "ChatIncomingBgColor": 75, + "ChatIncomingTextColor": 76, + "ChatModeratedMessageColor": 79, + "ChatOutgoingBgColor": 77, + "ChatOutgoingTextColor": 78, + "CheckedFieldBackground": 84, + "CheckedFieldBorder": 85, + "CheckedFieldIndicator": 86, + "ColorPickerFrame": 23, + "CurrentMarker": 24, + "Dark": 28, + "DebuggerCurrentLine": 57, + "DebuggerErrorLine": 58, + "DialogButton": 90, + "DialogButtonBorder": 92, + "DialogButtonText": 91, + "DialogMainButton": 93, + "DialogMainButtonText": 94, + "DiffFilePathBackground": 73, + "DiffFilePathBorder": 74, + "DiffFilePathText": 59, + "DiffLineNum": 68, + "DiffLineNumAdditionBackground": 71, + "DiffLineNumDeletionBackground": 72, + "DiffLineNumNoChangeBackground": 70, + "DiffLineNumSeparatorBackground": 69, + "DiffTextAddition": 62, + "DiffTextAdditionBackground": 66, + "DiffTextDeletion": 63, + "DiffTextDeletionBackground": 67, + "DiffTextHunkInfo": 60, + "DiffTextNoChange": 61, + "DiffTextNoChangeBackground": 65, + "DiffTextSeparatorBackground": 64, + "DimmedText": 34, + "Dropdown": 2, + "EmulatorBar": 21, + "EmulatorDropDown": 22, + "ErrorText": 37, + "GameSettingsTableItem": 19, + "GameSettingsTooltip": 20, + "HeaderSection": 87, + "InfoBarWarningBackground": 95, + "InfoBarWarningText": 96, + "InfoText": 38, + "InputFieldBackground": 15, + "InputFieldBorder": 83, + "Item": 16, + "Light": 27, + "LinkText": 35, + "MainBackground": 0, + "MainButton": 12, + "MainText": 30, + "Mid": 29, + "Midlight": 88, + "Notification": 4, + "RibbonButton": 13, + "RibbonTab": 9, + "RibbonTabTopBar": 10, + "ScriptBackground": 41, + "ScriptBool": 101, + "ScriptBracket": 108, + "ScriptBuiltInFunction": 52, + "ScriptComment": 50, + "ScriptEditorCurrentLine": 97, + "ScriptError": 54, + "ScriptFindSelectionBackground": 45, + "ScriptFunction": 102, + "ScriptFunctionName": 106, + "ScriptKeyword": 51, + "ScriptLocal": 103, + "ScriptLuauKeyword": 105, + "ScriptMatchingWordSelectionBackground": 46, + "ScriptMethod": 98, + "ScriptNil": 100, + "ScriptNumber": 48, + "ScriptOperator": 47, + "ScriptProperty": 99, + "ScriptRuler": 56, + "ScriptSelectionBackground": 44, + "ScriptSelectionText": 43, + "ScriptSelf": 104, + "ScriptSideWidget": 40, + "ScriptString": 49, + "ScriptText": 42, + "ScriptTodo": 107, + "ScriptWarning": 53, + "ScriptWhitespace": 55, + "ScrollBar": 5, + "ScrollBarBackground": 6, + "SensitiveText": 39, + "Separator": 80, + "Shadow": 26, + "StatusBar": 89, + "SubText": 31, + "Tab": 8, + "TabBar": 7, + "TableItem": 17, + "Titlebar": 1, + "TitlebarText": 32, + "Tooltip": 3, + "ViewPortBackground": 14, + "WarningText": 36 + } + }, + "StudioStyleGuideModifier": { + "name": "StudioStyleGuideModifier", + "items": { + "Default": 0, + "Disabled": 3, + "Hover": 4, + "Pressed": 2, + "Selected": 1 + } + }, + "Style": { + "name": "Style", + "items": { + "AlternatingSupports": 0, + "BridgeStyleSupports": 1, + "NoSupports": 2 + } + }, + "SurfaceConstraint": { + "name": "SurfaceConstraint", + "items": { + "Hinge": 1, + "Motor": 3, + "None": 0, + "SteppingMotor": 2 + } + }, + "SurfaceGuiSizingMode": { + "name": "SurfaceGuiSizingMode", + "items": { + "FixedSize": 0, + "PixelsPerStud": 1 + } + }, + "SurfaceType": { + "name": "SurfaceType", + "items": { + "Glue": 1, + "Hinge": 6, + "Inlet": 4, + "Motor": 7, + "Smooth": 0, + "SmoothNoOutlines": 10, + "SteppingMotor": 8, + "Studs": 3, + "Universal": 5, + "Weld": 2 + } + }, + "SwipeDirection": { + "name": "SwipeDirection", + "items": { + "Down": 3, + "Left": 1, + "None": 4, + "Right": 0, + "Up": 2 + } + }, + "TableMajorAxis": { + "name": "TableMajorAxis", + "items": { + "ColumnMajor": 1, + "RowMajor": 0 + } + }, + "Technology": { + "name": "Technology", + "items": { + "Compatibility": 2, + "Future": 4, + "Legacy": 0, + "ShadowMap": 3, + "Voxel": 1 + } + }, + "TeleportMethod": { + "name": "TeleportMethod", + "items": { + "TeleportPartyAsync": 3, + "TeleportToPlaceInstance": 1, + "TeleportToPrivateServer": 2, + "TeleportToSpawnByName": 0, + "TeleportUnknown": 4 + } + }, + "TeleportResult": { + "name": "TeleportResult", + "items": { + "Failure": 1, + "Flooded": 6, + "GameEnded": 3, + "GameFull": 4, + "GameNotFound": 2, + "IsTeleporting": 7, + "Success": 0, + "Unauthorized": 5 + } + }, + "TeleportState": { + "name": "TeleportState", + "items": { + "Failed": 3, + "InProgress": 4, + "RequestedFromServer": 0, + "Started": 1, + "WaitingForServer": 2 + } + }, + "TeleportType": { + "name": "TeleportType", + "items": { + "ToInstance": 1, + "ToPlace": 0, + "ToReservedServer": 2 + } + }, + "TextFilterContext": { + "name": "TextFilterContext", + "items": { + "PrivateChat": 2, + "PublicChat": 1 + } + }, + "TextInputType": { + "name": "TextInputType", + "items": { + "Default": 0, + "Email": 3, + "NoSuggestions": 1, + "Number": 2, + "Password": 5, + "PasswordShown": 6, + "Phone": 4, + "Username": 7 + } + }, + "TextTruncate": { + "name": "TextTruncate", + "items": { + "AtEnd": 1, + "None": 0 + } + }, + "TextXAlignment": { + "name": "TextXAlignment", + "items": { + "Center": 2, + "Left": 0, + "Right": 1 + } + }, + "TextYAlignment": { + "name": "TextYAlignment", + "items": { + "Bottom": 2, + "Center": 1, + "Top": 0 + } + }, + "TextureMode": { + "name": "TextureMode", + "items": { + "Static": 2, + "Stretch": 0, + "Wrap": 1 + } + }, + "TextureQueryType": { + "name": "TextureQueryType", + "items": { + "Humanoid": 2, + "HumanoidOrphaned": 3, + "NonHumanoid": 0, + "NonHumanoidOrphaned": 1 + } + }, + "ThreadPoolConfig": { + "name": "ThreadPoolConfig", + "items": { + "Auto": 0, + "PerCore1": 101, + "PerCore2": 102, + "PerCore3": 103, + "PerCore4": 104, + "Threads1": 1, + "Threads16": 16, + "Threads2": 2, + "Threads3": 3, + "Threads4": 4, + "Threads8": 8 + } + }, + "ThrottlingPriority": { + "name": "ThrottlingPriority", + "items": { + "Default": 0, + "ElevatedOnServer": 1, + "Extreme": 2 + } + }, + "ThumbnailSize": { + "name": "ThumbnailSize", + "items": { + "Size100x100": 4, + "Size150x150": 5, + "Size180x180": 1, + "Size352x352": 6, + "Size420x420": 2, + "Size48x48": 0, + "Size60x60": 3 + } + }, + "ThumbnailType": { + "name": "ThumbnailType", + "items": { + "AvatarBust": 1, + "AvatarThumbnail": 2, + "HeadShot": 0 + } + }, + "TickCountSampleMethod": { + "name": "TickCountSampleMethod", + "items": { + "Benchmark": 1, + "Fast": 0, + "Precise": 2 + } + }, + "TopBottom": { + "name": "TopBottom", + "items": { + "Bottom": 2, + "Center": 1, + "Top": 0 + } + }, + "TouchCameraMovementMode": { + "name": "TouchCameraMovementMode", + "items": { + "Classic": 1, + "Default": 0, + "Follow": 2, + "Orbital": 3 + } + }, + "TouchMovementMode": { + "name": "TouchMovementMode", + "items": { + "ClickToMove": 4, + "DPad": 2, + "Default": 0, + "DynamicThumbstick": 5, + "Thumbpad": 3, + "Thumbstick": 1 + } + }, + "TriStateBoolean": { + "name": "TriStateBoolean", + "items": { + "False": 2, + "True": 1, + "Unknown": 0 + } + }, + "TweenStatus": { + "name": "TweenStatus", + "items": { + "Canceled": 0, + "Completed": 1 + } + }, + "UITheme": { + "name": "UITheme", + "items": { + "Dark": 1, + "Light": 0 + } + }, + "UiMessageType": { + "name": "UiMessageType", + "items": { + "UiMessageError": 0, + "UiMessageInfo": 1 + } + }, + "UserCFrame": { + "name": "UserCFrame", + "items": { + "Head": 0, + "LeftHand": 1, + "RightHand": 2 + } + }, + "UserInputState": { + "name": "UserInputState", + "items": { + "Begin": 0, + "Cancel": 3, + "Change": 1, + "End": 2, + "None": 4 + } + }, + "UserInputType": { + "name": "UserInputType", + "items": { + "Accelerometer": 10, + "Focus": 9, + "Gamepad1": 12, + "Gamepad2": 13, + "Gamepad3": 14, + "Gamepad4": 15, + "Gamepad5": 16, + "Gamepad6": 17, + "Gamepad7": 18, + "Gamepad8": 19, + "Gyro": 11, + "InputMethod": 21, + "Keyboard": 8, + "MouseButton1": 0, + "MouseButton2": 1, + "MouseButton3": 2, + "MouseMovement": 4, + "MouseWheel": 3, + "None": 22, + "TextInput": 20, + "Touch": 7 + } + }, + "VRTouchpad": { + "name": "VRTouchpad", + "items": { + "Left": 0, + "Right": 1 + } + }, + "VRTouchpadMode": { + "name": "VRTouchpadMode", + "items": { + "ABXY": 2, + "Touch": 0, + "VirtualThumbstick": 1 + } + }, + "VerticalAlignment": { + "name": "VerticalAlignment", + "items": { + "Bottom": 2, + "Center": 0, + "Top": 1 + } + }, + "VerticalScrollBarPosition": { + "name": "VerticalScrollBarPosition", + "items": { + "Left": 1, + "Right": 0 + } + }, + "VibrationMotor": { + "name": "VibrationMotor", + "items": { + "Large": 0, + "LeftHand": 4, + "LeftTrigger": 2, + "RightHand": 5, + "RightTrigger": 3, + "Small": 1 + } + }, + "VirtualInputMode": { + "name": "VirtualInputMode", + "items": { + "None": 0, + "Playing": 2, + "Recording": 1 + } + }, + "WaterDirection": { + "name": "WaterDirection", + "items": { + "NegX": 0, + "NegY": 2, + "NegZ": 4, + "X": 1, + "Y": 3, + "Z": 5 + } + }, + "WaterForce": { + "name": "WaterForce", + "items": { + "Max": 4, + "Medium": 2, + "None": 0, + "Small": 1, + "Strong": 3 + } + }, + "WrapLayerDebugMode": { + "name": "WrapLayerDebugMode", + "items": { + "BoundCage": 1, + "BoundCageAndLinks": 3, + "LayerCage": 2, + "None": 0, + "Reference": 4 + } + }, + "WrapTargetDebugMode": { + "name": "WrapTargetDebugMode", + "items": { + "None": 0, + "TargetCage": 1 + } + }, + "ZIndexBehavior": { + "name": "ZIndexBehavior", + "items": { + "Global": 0, + "Sibling": 1 + } + } + } +} \ No newline at end of file diff --git a/plugin/rbx_dom_lua/src/init.lua b/plugin/rbx_dom_lua/src/init.lua index 3c1149d6..a9386d4d 100644 --- a/plugin/rbx_dom_lua/src/init.lua +++ b/plugin/rbx_dom_lua/src/init.lua @@ -1,4 +1,4 @@ -local ReflectionDatabase = require(script.ReflectionDatabase) +local database = require(script.database) local Error = require(script.Error) local PropertyDescriptor = require(script.PropertyDescriptor) @@ -6,29 +6,31 @@ local function findCanonicalPropertyDescriptor(className, propertyName) local currentClassName = className repeat - local currentClass = ReflectionDatabase.classes[currentClassName] + local currentClass = database.Classes[currentClassName] if currentClass == nil then return currentClass end - local propertyData = currentClass.properties[propertyName] + local propertyData = currentClass.Properties[propertyName] if propertyData ~= nil then - if propertyData.isCanonical then + local canonicalData = propertyData.Kind.Canonical + if canonicalData ~= nil then return PropertyDescriptor.fromRaw(propertyData, currentClassName, propertyName) end - if propertyData.canonicalName ~= nil then + local aliasData = propertyData.Kind.Alias + if aliasData ~= nil then return PropertyDescriptor.fromRaw( - currentClass.properties[propertyData.canonicalName], + currentClass.properties[aliasData.AliasFor], currentClassName, - propertyData.canonicalName) + aliasData.AliasFor) end return nil end - currentClassName = currentClass.superclass + currentClassName = currentClass.Superclass until currentClassName == nil return nil diff --git a/plugin/rbx_dom_lua/test b/plugin/rbx_dom_lua/test new file mode 100644 index 00000000..9ac1092f --- /dev/null +++ b/plugin/rbx_dom_lua/test @@ -0,0 +1,4 @@ +#!/bin/sh + +rojo build test-place.project.json -o TestPlace.rbxlx +run-in-roblox --script run-tests.lua --place TestPlace.rbxlx \ No newline at end of file diff --git a/plugin/rbx_dom_lua/test-place.project.json b/plugin/rbx_dom_lua/test-place.project.json index f852b2b4..3cd48403 100644 --- a/plugin/rbx_dom_lua/test-place.project.json +++ b/plugin/rbx_dom_lua/test-place.project.json @@ -16,7 +16,7 @@ "$className": "ServerScriptService", "Run Tests": { - "$path": "test.server.lua" + "$path": "run-tests.lua" } }, "Players": { diff --git a/plugin/rbx_dom_lua/test.server.lua b/plugin/rbx_dom_lua/test.server.lua deleted file mode 100644 index 841c63c1..00000000 --- a/plugin/rbx_dom_lua/test.server.lua +++ /dev/null @@ -1,7 +0,0 @@ -local ReplicatedStorage = game:GetService("ReplicatedStorage") - -local LIB_ROOT = ReplicatedStorage.RbxDom - -local TestEZ = require(ReplicatedStorage.TestEZ) - -TestEZ.TestBootstrap:run({LIB_ROOT}) \ No newline at end of file diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__json_model_in_folder.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__json_model_in_folder.snap index cf1dba88..db195dd9 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__json_model_in_folder.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__json_model_in_folder.snap @@ -10,7 +10,7 @@ expression: contents simple-model - 5 + 5 diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__unresolved_values.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__unresolved_values.snap new file mode 100644 index 00000000..ecec4172 --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__unresolved_values.snap @@ -0,0 +1,55 @@ +--- +source: tests/tests/build.rs +expression: contents +--- + + + + unresolved-values + + + + Lighting + + 1 + 0 + 0 + + 1 + + + + + Workspace + + + + Bool + true + + + + + Color + + 0.5 + 0.25 + 0 + + + + + + Float + 123.5 + + + + + Int + 65 + + + + + diff --git a/rojo-test/build-tests/unresolved_values/default.project.json b/rojo-test/build-tests/unresolved_values/default.project.json new file mode 100644 index 00000000..d5f5d534 --- /dev/null +++ b/rojo-test/build-tests/unresolved_values/default.project.json @@ -0,0 +1,43 @@ +{ + "name": "unresolved-values", + "tree": { + "$className": "DataModel", + + "Lighting": { + "$properties": { + "Technology": "Voxel", + "Ambient": [1, 0, 0] + } + }, + + "Workspace": { + "Color": { + "$className": "Part", + "$properties": { + "Color": [0.5, 0.25, 0] + } + }, + + "Bool": { + "$className": "BoolValue", + "$properties": { + "Value": true + } + }, + + "Int": { + "$className": "IntValue", + "$properties": { + "Value": 65 + } + }, + + "Float": { + "$className": "NumberValue", + "$properties": { + "Value": 123.5 + } + } + } + } +} \ No newline at end of file diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all-2.snap index 29d3b553..2053b9c7 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all-2.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all-2.snap @@ -11,7 +11,7 @@ instances: Metadata: ignoreUnknownInstances: false Name: add_folder - Parent: ~ + Parent: "00000000000000000000000000000000" Properties: {} id-3: Children: [] diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all.snap index fc902c99..3cffd761 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_folder_all.snap @@ -10,7 +10,7 @@ instances: Metadata: ignoreUnknownInstances: false Name: add_folder - Parent: ~ + Parent: "00000000000000000000000000000000" Properties: {} messageCursor: 0 sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all-2.snap index 688f72d6..7218c9bf 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all-2.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all-2.snap @@ -10,7 +10,7 @@ instances: Metadata: ignoreUnknownInstances: false Name: edit_init - Parent: ~ + Parent: "00000000000000000000000000000000" Properties: Source: Type: String diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all.snap index a484d8e2..d0b1b97a 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__edit_init_all.snap @@ -10,7 +10,7 @@ instances: Metadata: ignoreUnknownInstances: false Name: edit_init - Parent: ~ + Parent: "00000000000000000000000000000000" Properties: Source: Type: String diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_all.snap index 188f854f..71fded9e 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_all.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__empty_all.snap @@ -10,7 +10,7 @@ instances: Metadata: ignoreUnknownInstances: true Name: empty - Parent: ~ + Parent: "00000000000000000000000000000000" Properties: {} messageCursor: 0 sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all-2.snap index 96e5126e..c9b36434 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all-2.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all-2.snap @@ -59,7 +59,7 @@ instances: Metadata: ignoreUnknownInstances: false Name: move_folder_of_stuff - Parent: ~ + Parent: "00000000000000000000000000000000" Properties: {} id-3: Children: diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all.snap index 1f189d00..08cc4e31 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__move_folder_of_stuff_all.snap @@ -10,7 +10,7 @@ instances: Metadata: ignoreUnknownInstances: false Name: move_folder_of_stuff - Parent: ~ + Parent: "00000000000000000000000000000000" Properties: {} messageCursor: 0 sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all-2.snap index b3c0a7fd..7d0b25bb 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all-2.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all-2.snap @@ -10,7 +10,7 @@ instances: Metadata: ignoreUnknownInstances: false Name: remove_file - Parent: ~ + Parent: "00000000000000000000000000000000" Properties: {} messageCursor: 1 sessionId: id-1 diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all.snap index 8534c320..855c79ec 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__remove_file_all.snap @@ -11,7 +11,7 @@ instances: Metadata: ignoreUnknownInstances: false Name: remove_file - Parent: ~ + Parent: "00000000000000000000000000000000" Properties: {} id-3: Children: [] diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all-2.snap index 7571797f..72ab9efc 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all-2.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all-2.snap @@ -12,7 +12,7 @@ instances: Metadata: ignoreUnknownInstances: false Name: scripts - Parent: ~ + Parent: "00000000000000000000000000000000" Properties: {} id-3: Children: [] diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all.snap index 6f67d05c..1748f264 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all.snap @@ -12,7 +12,7 @@ instances: Metadata: ignoreUnknownInstances: false Name: scripts - Parent: ~ + Parent: "00000000000000000000000000000000" Properties: {} id-3: Children: [] diff --git a/src/change_processor.rs b/src/change_processor.rs index 449fe911..a964c6ad 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -6,7 +6,7 @@ use std::{ use crossbeam_channel::{select, Receiver, RecvError, Sender}; use jod_thread::JoinHandle; use memofs::{IoResultExt, Vfs, VfsEvent}; -use rbx_dom_weak::{RbxId, RbxValue}; +use rbx_dom_weak::types::{Ref, Variant}; use crate::{ message_queue::MessageQueue, @@ -179,7 +179,7 @@ impl JobThreadContext { InstigatingSource::Path(path) => fs::remove_file(path).unwrap(), InstigatingSource::ProjectNode(_, _, _, _) => { log::warn!( - "Cannot remove instance {}, it's from a project file", + "Cannot remove instance {:?}, it's from a project file", id ); } @@ -187,12 +187,12 @@ impl JobThreadContext { } else { // TODO log::warn!( - "Cannot remove instance {}, it is not an instigating source.", + "Cannot remove instance {:?}, it is not an instigating source.", id ); } } else { - log::warn!("Cannot remove instance {}, it does not exist.", id); + log::warn!("Cannot remove instance {:?}, it does not exist.", id); } } @@ -219,7 +219,7 @@ impl JobThreadContext { { match instigating_source { InstigatingSource::Path(path) => { - if let Some(RbxValue::String { value }) = changed_value { + if let Some(Variant::String(value)) = changed_value { fs::write(path, value).unwrap(); } else { log::warn!("Cannot change Source to non-string value."); @@ -227,14 +227,14 @@ impl JobThreadContext { } InstigatingSource::ProjectNode(_, _, _, _) => { log::warn!( - "Cannot remove instance {}, it's from a project file", + "Cannot remove instance {:?}, it's from a project file", id ); } } } else { log::warn!( - "Cannot update instance {}, it is not an instigating source.", + "Cannot update instance {:?}, it is not an instigating source.", id ); } @@ -243,7 +243,7 @@ impl JobThreadContext { } } } else { - log::warn!("Cannot update instance {}, it does not exist.", id); + log::warn!("Cannot update instance {:?}, it does not exist.", id); } } @@ -254,7 +254,7 @@ impl JobThreadContext { } } -fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: RbxId) -> Option { +fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: Ref) -> Option { let metadata = tree .get_metadata(id) .expect("metadata missing for instance present in tree"); @@ -263,7 +263,7 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: RbxId) -> Optio Some(path) => path, None => { log::error!( - "Instance {} did not have an instigating source, but was considered for an update.", + "Instance {:?} did not have an instigating source, but was considered for an update.", id ); log::error!("This is a bug. Please file an issue!"); diff --git a/src/cli/build.rs b/src/cli/build.rs index cab366ab..f1cc6d1e 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -88,7 +88,7 @@ fn write_model(tree: &RojoTree, options: &BuildCommand) -> Result<(), anyhow::Er } OutputKind::Rbxlx => { // Place files don't contain an entry for the DataModel, but our - // RbxTree representation does. + // WeakDom representation does. let root_instance = tree.get_instance(root_id).unwrap(); let top_level_ids = root_instance.children(); @@ -96,17 +96,13 @@ fn write_model(tree: &RojoTree, options: &BuildCommand) -> Result<(), anyhow::Er rbx_xml::to_writer(&mut file, tree.inner(), top_level_ids, xml_encode_config())?; } OutputKind::Rbxm => { - rbx_binary::encode(tree.inner(), &[root_id], &mut file)?; + rbx_binary::to_writer_default(&mut file, tree.inner(), &[root_id])?; } OutputKind::Rbxl => { - log::warn!("Support for building binary places (rbxl) is still experimental."); - log::warn!("Using the XML place format (rbxlx) is recommended instead."); - log::warn!("For more info, see https://github.com/rojo-rbx/rojo/issues/180"); - let root_instance = tree.get_instance(root_id).unwrap(); let top_level_ids = root_instance.children(); - rbx_binary::encode(tree.inner(), top_level_ids, &mut file)?; + rbx_binary::to_writer_default(&mut file, tree.inner(), top_level_ids)?; } } diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs index d3c31c7c..376d69db 100644 --- a/src/cli/plugin.rs +++ b/src/cli/plugin.rs @@ -49,7 +49,7 @@ pub fn install_plugin() -> Result<()> { let tree = session.tree(); let root_id = tree.get_root_id(); - rbx_binary::encode(tree.inner(), &[root_id], &mut file)?; + rbx_binary::to_writer_default(&mut file, tree.inner(), &[root_id])?; Ok(()) } diff --git a/src/cli/upload.rs b/src/cli/upload.rs index e6969c22..89ece43c 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -29,12 +29,11 @@ pub fn upload(options: UploadCommand) -> Result<(), anyhow::Error> { let tree = session.tree(); let inner_tree = tree.inner(); - let root_id = inner_tree.get_root_id(); - let root_instance = inner_tree.get_instance(root_id).unwrap(); + let root = inner_tree.root(); - let encode_ids = match root_instance.class_name.as_str() { - "DataModel" => root_instance.get_children_ids().to_vec(), - _ => vec![root_id], + let encode_ids = match root.class.as_str() { + "DataModel" => root.children().to_vec(), + _ => vec![root.referent()], }; let mut buffer = Vec::new(); diff --git a/src/lib.rs b/src/lib.rs index 361c92e4..51195b6c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ mod message_queue; mod multimap; mod path_serializer; mod project; +mod resolution; mod serve_session; mod session_id; mod snapshot; diff --git a/src/project.rs b/src/project.rs index 16c3a7cf..438f3210 100644 --- a/src/project.rs +++ b/src/project.rs @@ -4,11 +4,10 @@ use std::{ path::{Path, PathBuf}, }; -use rbx_dom_weak::UnresolvedRbxValue; use serde::{Deserialize, Serialize}; use thiserror::Error; -use crate::glob::Glob; +use crate::{glob::Glob, resolution::UnresolvedValue}; static PROJECT_FILENAME: &str = "default.project.json"; @@ -183,7 +182,7 @@ pub struct ProjectNode { default, skip_serializing_if = "HashMap::is_empty" )] - pub properties: HashMap, + pub properties: HashMap, /// Defines the behavior when Rojo encounters unknown instances in Roblox /// Studio during live sync. `$ignoreUnknownInstances` should be considered diff --git a/src/resolution.rs b/src/resolution.rs new file mode 100644 index 00000000..5c38e5f6 --- /dev/null +++ b/src/resolution.rs @@ -0,0 +1,159 @@ +use anyhow::format_err; +use rbx_dom_weak::types::{ + Color3, Color3uint8, Content, Enum, Variant, VariantType, Vector2, Vector3, +}; +use rbx_reflection::{DataType, PropertyDescriptor}; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum UnresolvedValue { + FullyQualified(Variant), + Ambiguous(AmbiguousValue), +} + +impl UnresolvedValue { + pub fn resolve(self, class_name: &str, prop_name: &str) -> anyhow::Result { + match self { + UnresolvedValue::FullyQualified(full) => Ok(full), + UnresolvedValue::Ambiguous(partial) => partial.resolve(class_name, prop_name), + } + } +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum AmbiguousValue { + Bool(bool), + String(String), + Number(f64), + Array2([f64; 2]), + Array3([f64; 3]), + Array4([f64; 4]), + Array16([f64; 16]), +} + +impl AmbiguousValue { + pub fn resolve(self, class_name: &str, prop_name: &str) -> anyhow::Result { + let property = find_descriptor(class_name, prop_name) + .ok_or_else(|| format_err!("Unknown property {}.{}", class_name, prop_name))?; + + match &property.data_type { + DataType::Enum(enum_name) => { + let database = rbx_reflection_database::get(); + + let enum_descriptor = database.enums.get(enum_name).ok_or_else(|| { + format_err!("Unknown enum {}. This is a Rojo bug!", enum_name) + })?; + + let error = |what: &str| { + let sample_values = enum_descriptor + .items + .keys() + .take(3) + .map(|name| format!(r#""{}""#, name)) + .collect::>() + .join(", "); + + format_err!( + "Invalid value for property {}.{}. Got {} but \ + expected a member of the {} enum such as {}", + class_name, + prop_name, + what, + enum_name, + sample_values + ) + }; + + let value = match self { + AmbiguousValue::String(value) => value, + unresolved => return Err(error(unresolved.describe())), + }; + + let resolved = enum_descriptor + .items + .get(value.as_str()) + .ok_or_else(|| error(value.as_str()))?; + + Ok(Enum::from_u32(*resolved).into()) + } + DataType::Value(variant_ty) => match (variant_ty, self) { + (VariantType::Bool, AmbiguousValue::Bool(value)) => Ok(value.into()), + + (VariantType::Float32, AmbiguousValue::Number(value)) => Ok((value as f32).into()), + (VariantType::Float64, AmbiguousValue::Number(value)) => Ok(value.into()), + (VariantType::Int32, AmbiguousValue::Number(value)) => Ok((value as i32).into()), + (VariantType::Int64, AmbiguousValue::Number(value)) => Ok((value as i64).into()), + + (VariantType::String, AmbiguousValue::String(value)) => Ok(value.into()), + (VariantType::Content, AmbiguousValue::String(value)) => { + Ok(Content::from(value).into()) + } + + (VariantType::Vector2, AmbiguousValue::Array2(value)) => { + Ok(Vector2::new(value[0] as f32, value[1] as f32).into()) + } + + (VariantType::Vector3, AmbiguousValue::Array3(value)) => { + Ok(Vector3::new(value[0] as f32, value[1] as f32, value[2] as f32).into()) + } + + (VariantType::Color3, AmbiguousValue::Array3(value)) => { + Ok(Color3::new(value[0] as f32, value[1] as f32, value[2] as f32).into()) + } + (VariantType::Color3uint8, AmbiguousValue::Array3(value)) => { + let value = Color3uint8::new( + (value[0] / 255.0) as u8, + (value[1] / 255.0) as u8, + (value[2] / 255.0) as u8, + ); + + Ok(value.into()) + } + + (_, unresolved) => Err(format_err!( + "Wrong type of value for property {}.{}. Expected {:?}, got {}", + class_name, + prop_name, + variant_ty, + unresolved.describe(), + )), + }, + _ => Err(format_err!( + "Unknown data type for property {}.{}", + class_name, + prop_name + )), + } + } + + fn describe(&self) -> &'static str { + match self { + AmbiguousValue::Bool(_) => "a bool", + AmbiguousValue::String(_) => "a string", + AmbiguousValue::Number(_) => "a number", + AmbiguousValue::Array2(_) => "an array of two numbers", + AmbiguousValue::Array3(_) => "an array of three numbers", + AmbiguousValue::Array4(_) => "an array of four numbers", + AmbiguousValue::Array16(_) => "an array of 16 numbers", + } + } +} + +fn find_descriptor( + class_name: &str, + prop_name: &str, +) -> Option<&'static PropertyDescriptor<'static>> { + let database = rbx_reflection_database::get(); + let mut current_class_name = class_name; + + loop { + let class = database.classes.get(current_class_name)?; + if let Some(descriptor) = class.properties.get(prop_name) { + return Some(descriptor); + } + + current_class_name = class.superclass.as_deref()?; + } +} diff --git a/src/serve_session.rs b/src/serve_session.rs index ee6020a6..aec152d0 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -10,7 +10,6 @@ use std::{ use crossbeam_channel::Sender; use memofs::IoResultExt; use memofs::Vfs; -use rbx_dom_weak::RbxInstanceProperties; use thiserror::Error; use crate::{ @@ -19,8 +18,8 @@ use crate::{ project::{Project, ProjectError}, session_id::SessionId, snapshot::{ - apply_patch_set, compute_patch_set, AppliedPatchSet, InstanceContext, - InstancePropertiesWithMeta, PatchSet, RojoTree, + apply_patch_set, compute_patch_set, AppliedPatchSet, InstanceContext, InstanceSnapshot, + PatchSet, RojoTree, }, snapshot_middleware::snapshot_from_vfs, }; @@ -118,14 +117,7 @@ impl ServeSession { } }; - let mut tree = RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "Folder".to_owned(), - properties: Default::default(), - }, - metadata: Default::default(), - }); + let mut tree = RojoTree::new(InstanceSnapshot::new()); let root_id = tree.get_root_id(); diff --git a/src/snapshot/instance_snapshot.rs b/src/snapshot/instance_snapshot.rs index aae249a8..050dc067 100644 --- a/src/snapshot/instance_snapshot.rs +++ b/src/snapshot/instance_snapshot.rs @@ -2,7 +2,10 @@ use std::{borrow::Cow, collections::HashMap}; -use rbx_dom_weak::{RbxId, RbxTree, RbxValue}; +use rbx_dom_weak::{ + types::{Ref, Variant}, + WeakDom, +}; use serde::{Deserialize, Serialize}; use super::InstanceMetadata; @@ -11,11 +14,12 @@ use super::InstanceMetadata; /// // Possible future improvements: // - Use refcounted/interned strings -// - Replace use of RbxValue with a sum of RbxValue + borrowed value +// - Replace use of Variant with a sum of Variant + borrowed value #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct InstanceSnapshot { + // FIXME: Don't use Option anymore! /// A temporary ID applied to the snapshot that's used for Ref properties. - pub snapshot_id: Option, + pub snapshot_id: Option, /// Rojo-specific metadata associated with the instance. pub metadata: InstanceMetadata, @@ -27,7 +31,7 @@ pub struct InstanceSnapshot { pub class_name: Cow<'static, str>, /// All other properties of the instance, weakly-typed. - pub properties: HashMap, + pub properties: HashMap, /// The children of the instance represented as more snapshots. /// @@ -61,7 +65,16 @@ impl InstanceSnapshot { } } - pub fn properties(self, properties: impl Into>) -> Self { + pub fn property(mut self, key: K, value: V) -> Self + where + K: Into, + V: Into, + { + self.properties.insert(key.into(), value.into()); + self + } + + pub fn properties(self, properties: impl Into>) -> Self { Self { properties: properties.into(), ..self @@ -75,6 +88,13 @@ impl InstanceSnapshot { } } + pub fn snapshot_id(self, snapshot_id: Option) -> Self { + Self { + snapshot_id, + ..self + } + } + pub fn metadata(self, metadata: impl Into) -> Self { Self { metadata: metadata.into(), @@ -82,15 +102,13 @@ impl InstanceSnapshot { } } - pub fn from_tree(tree: &RbxTree, id: RbxId) -> Self { - let instance = tree - .get_instance(id) - .expect("instance did not exist in tree"); + pub fn from_tree(tree: &WeakDom, id: Ref) -> Self { + let instance = tree.get_by_ref(id).expect("instance did not exist in tree"); let children = instance - .get_children_ids() + .children() .iter() - .cloned() + .copied() .map(|id| Self::from_tree(tree, id)) .collect(); @@ -98,7 +116,7 @@ impl InstanceSnapshot { snapshot_id: Some(id), metadata: InstanceMetadata::default(), name: Cow::Owned(instance.name.clone()), - class_name: Cow::Owned(instance.class_name.clone()), + class_name: Cow::Owned(instance.class.clone()), properties: instance.properties.clone(), children, } diff --git a/src/snapshot/patch.rs b/src/snapshot/patch.rs index 6fa1eb29..1d320a2c 100644 --- a/src/snapshot/patch.rs +++ b/src/snapshot/patch.rs @@ -2,19 +2,19 @@ use std::collections::HashMap; -use rbx_dom_weak::{RbxId, RbxValue}; +use rbx_dom_weak::types::{Ref, Variant}; use serde::{Deserialize, Serialize}; use super::{InstanceMetadata, InstanceSnapshot}; -/// A set of different kinds of patches that can be applied to an RbxTree. +/// A set of different kinds of patches that can be applied to an WeakDom. /// /// These patches shouldn't be persisted: there's no mechanism in place to make /// sure that another patch wasn't applied before this one that could cause a /// conflict! #[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)] pub struct PatchSet { - pub removed_instances: Vec, + pub removed_instances: Vec, pub added_instances: Vec, pub updated_instances: Vec, } @@ -32,20 +32,20 @@ impl<'a> PatchSet { /// A patch containing an instance that was added to the tree. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct PatchAdd { - pub parent_id: RbxId, + pub parent_id: Ref, pub instance: InstanceSnapshot, } /// A patch indicating that properties of an instance changed. #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct PatchUpdate { - pub id: RbxId, + pub id: Ref, pub changed_name: Option, pub changed_class_name: Option, /// Contains all changed properties. If a property is assigned to `None`, /// then that property has been removed. - pub changed_properties: HashMap>, + pub changed_properties: HashMap>, /// Changed Rojo-specific metadata, if any of it changed. pub changed_metadata: Option, @@ -63,8 +63,8 @@ pub struct PatchUpdate { // current values in all fields. #[derive(Debug, Clone, Default, Serialize, Deserialize)] pub struct AppliedPatchSet { - pub removed: Vec, - pub added: Vec, + pub removed: Vec, + pub added: Vec, pub updated: Vec, } @@ -80,17 +80,17 @@ impl AppliedPatchSet { #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AppliedPatchUpdate { - pub id: RbxId, + pub id: Ref, // TODO: Store previous values in order to detect application conflicts pub changed_name: Option, pub changed_class_name: Option, - pub changed_properties: HashMap>, + pub changed_properties: HashMap>, pub changed_metadata: Option, } impl AppliedPatchUpdate { - pub fn new(id: RbxId) -> Self { + pub fn new(id: Ref) -> Self { Self { id, changed_name: None, diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index ea28f302..4e40061c 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -2,11 +2,11 @@ use std::collections::HashMap; -use rbx_dom_weak::{RbxId, RbxInstanceProperties, RbxValue}; +use rbx_dom_weak::types::{Ref, Variant}; use super::{ patch::{AppliedPatchSet, AppliedPatchUpdate, PatchSet, PatchUpdate}, - InstancePropertiesWithMeta, InstanceSnapshot, RojoTree, + InstanceSnapshot, RojoTree, }; /// Consumes the input `PatchSet`, applying all of its prescribed changes to the @@ -37,7 +37,7 @@ pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) -> AppliedPatch struct PatchApplyContext { /// A map from transient snapshot IDs (generated by snapshot middleware) to /// instance IDs in the actual tree. These are both the same data type so - /// that they fit into the same `RbxValue::Ref` type. + /// that they fit into the same `Variant::Ref` type. /// /// At this point in the patch process, IDs in instance properties have been /// partially translated from 'snapshot space' into 'tree space' by the @@ -53,7 +53,7 @@ struct PatchApplyContext { /// #2 should not occur in well-formed projects, but is indistinguishable /// from #1 right now. It could happen if two model files try to reference /// eachother. - snapshot_id_to_instance_id: HashMap, + snapshot_id_to_instance_id: HashMap, /// The properties of instances added by the current `PatchSet`. /// @@ -68,7 +68,7 @@ struct PatchApplyContext { /// /// This doesn't affect updated instances, since they're always applied /// after we've added all the instances from the patch. - added_instance_properties: HashMap>, + added_instance_properties: HashMap>, /// The current applied patch result, describing changes made to the tree. applied_patch_set: AppliedPatchSet, @@ -93,11 +93,10 @@ fn finalize_patch_application(context: PatchApplyContext, tree: &mut RojoTree) - .expect("Invalid instance ID in deferred property map"); for (key, mut property_value) in properties { - if let RbxValue::Ref { value: Some(id) } = property_value { - if let Some(&instance_id) = context.snapshot_id_to_instance_id.get(&id) { - property_value = RbxValue::Ref { - value: Some(instance_id), - }; + if let Variant::Ref(referent) = property_value { + if let Some(&instance_referent) = context.snapshot_id_to_instance_id.get(&referent) + { + property_value = Variant::Ref(instance_referent); } } @@ -108,50 +107,40 @@ fn finalize_patch_application(context: PatchApplyContext, tree: &mut RojoTree) - context.applied_patch_set } -fn apply_remove_instance(context: &mut PatchApplyContext, tree: &mut RojoTree, removed_id: RbxId) { - match tree.remove_instance(removed_id) { - Some(_) => context.applied_patch_set.removed.push(removed_id), - None => { - log::warn!( - "Patch misapplication: Tried to remove instance {} but it did not exist.", - removed_id - ); - } - } +fn apply_remove_instance(context: &mut PatchApplyContext, tree: &mut RojoTree, removed_id: Ref) { + tree.remove(removed_id); + context.applied_patch_set.removed.push(removed_id); } fn apply_add_child( context: &mut PatchApplyContext, tree: &mut RojoTree, - parent_id: RbxId, + parent_id: Ref, snapshot: InstanceSnapshot, ) { - let properties = InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: snapshot.name.into_owned(), - class_name: snapshot.class_name.into_owned(), + let snapshot_id = snapshot.snapshot_id; + let properties = snapshot.properties; + let children = snapshot.children; - // Property assignment is deferred until after we know about all - // instances in this patch. See `PatchApplyContext` for details. - properties: HashMap::new(), - }, - metadata: snapshot.metadata, - }; - - let id = tree.insert_instance(properties, parent_id); + // Property application is deferred until after all children + // are constructed. This helps apply referents correctly. + let remaining_snapshot = InstanceSnapshot::new() + .name(snapshot.name) + .class_name(snapshot.class_name) + .metadata(snapshot.metadata) + .snapshot_id(snapshot.snapshot_id); + let id = tree.insert_instance(parent_id, remaining_snapshot); context.applied_patch_set.added.push(id); - context - .added_instance_properties - .insert(id, snapshot.properties); + context.added_instance_properties.insert(id, properties); - if let Some(snapshot_id) = snapshot.snapshot_id { + if let Some(snapshot_id) = snapshot_id { context.snapshot_id_to_instance_id.insert(snapshot_id, id); } - for child_snapshot in snapshot.children { - apply_add_child(context, tree, id, child_snapshot); + for child in children { + apply_add_child(context, tree, id, child); } } @@ -167,7 +156,7 @@ fn apply_update_child(context: &mut PatchApplyContext, tree: &mut RojoTree, patc Some(instance) => instance, None => { log::warn!( - "Patch misapplication: Instance {}, referred to by update patch, did not exist.", + "Patch misapplication: Instance {:?}, referred to by update patch, did not exist.", patch.id ); return; @@ -189,23 +178,24 @@ fn apply_update_child(context: &mut PatchApplyContext, tree: &mut RojoTree, patc // Ref values need to be potentially rewritten from snapshot IDs to // instance IDs if they referred to an instance that was created as // part of this patch. - Some(RbxValue::Ref { value: Some(id) }) => { + Some(Variant::Ref(referent)) => { + if referent.is_none() { + continue; + } + // If our ID is not found in this map, then it either refers to // an existing instance NOT added by this patch, or there was an // error. See `PatchApplyContext::snapshot_id_to_instance_id` // for more info. - let new_id = context + let new_referent = context .snapshot_id_to_instance_id - .get(&id) + .get(&referent) .copied() - .unwrap_or(id); + .unwrap_or(referent); - instance.properties_mut().insert( - key.clone(), - RbxValue::Ref { - value: Some(new_id), - }, - ); + instance + .properties_mut() + .insert(key.clone(), Variant::Ref(new_referent)); } Some(ref value) => { instance.properties_mut().insert(key.clone(), value.clone()); @@ -225,10 +215,10 @@ fn apply_update_child(context: &mut PatchApplyContext, tree: &mut RojoTree, patc mod test { use super::*; - use std::{borrow::Cow, collections::HashMap}; + use std::borrow::Cow; use maplit::hashmap; - use rbx_dom_weak::RbxValue; + use rbx_dom_weak::types::Variant; use super::super::PatchAdd; @@ -236,14 +226,7 @@ mod test { fn add_from_empty() { let _ = env_logger::try_init(); - let mut tree = RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "Folder".to_owned(), - class_name: "Folder".to_owned(), - properties: HashMap::new(), - }, - metadata: Default::default(), - }); + let mut tree = RojoTree::new(InstanceSnapshot::new()); let root_id = tree.get_root_id(); @@ -253,7 +236,7 @@ mod test { name: Cow::Borrowed("Foo"), class_name: Cow::Borrowed("Bar"), properties: hashmap! { - "Baz".to_owned() => RbxValue::Int32 { value: 5 }, + "Baz".to_owned() => Variant::Int32(5), }, children: Vec::new(), }; @@ -282,18 +265,14 @@ mod test { fn update_existing() { let _ = env_logger::try_init(); - let mut tree = RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "OldName".to_owned(), - class_name: "OldClassName".to_owned(), - properties: hashmap! { - "Foo".to_owned() => RbxValue::Int32 { value: 7 }, - "Bar".to_owned() => RbxValue::Int32 { value: 3 }, - "Unchanged".to_owned() => RbxValue::Int32 { value: -5 }, - }, - }, - metadata: Default::default(), - }); + let mut tree = RojoTree::new( + InstanceSnapshot::new() + .class_name("OldClassName") + .name("OldName") + .property("Foo", 7i32) + .property("Bar", 3i32) + .property("Unchanged", -5i32), + ); let root_id = tree.get_root_id(); @@ -303,13 +282,13 @@ mod test { changed_class_name: Some("NewClassName".to_owned()), changed_properties: hashmap! { // The value of Foo has changed - "Foo".to_owned() => Some(RbxValue::Int32 { value: 8 }), + "Foo".to_owned() => Some(Variant::Int32(8)), // Bar has been deleted "Bar".to_owned() => None, // Baz has been added - "Baz".to_owned() => Some(RbxValue::Int32 { value: 10 }), + "Baz".to_owned() => Some(Variant::Int32(10)), }, changed_metadata: None, }; @@ -322,9 +301,9 @@ mod test { apply_patch_set(&mut tree, patch_set); let expected_properties = hashmap! { - "Foo".to_owned() => RbxValue::Int32 { value: 8 }, - "Baz".to_owned() => RbxValue::Int32 { value: 10 }, - "Unchanged".to_owned() => RbxValue::Int32 { value: -5 }, + "Foo".to_owned() => Variant::Int32(8), + "Baz".to_owned() => Variant::Int32(10), + "Unchanged".to_owned() => Variant::Int32(-5), }; let root_instance = tree.get_instance(root_id).unwrap(); diff --git a/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs index 96418d02..39974caf 100644 --- a/src/snapshot/patch_compute.rs +++ b/src/snapshot/patch_compute.rs @@ -3,14 +3,14 @@ use std::collections::{HashMap, HashSet}; -use rbx_dom_weak::{RbxId, RbxValue}; +use rbx_dom_weak::types::{Ref, Variant}; use super::{ patch::{PatchAdd, PatchSet, PatchUpdate}, InstanceSnapshot, InstanceWithMeta, RojoTree, }; -pub fn compute_patch_set(snapshot: &InstanceSnapshot, tree: &RojoTree, id: RbxId) -> PatchSet { +pub fn compute_patch_set(snapshot: &InstanceSnapshot, tree: &RojoTree, id: Ref) -> PatchSet { let mut patch_set = PatchSet::new(); let mut context = ComputePatchContext::default(); @@ -26,17 +26,15 @@ pub fn compute_patch_set(snapshot: &InstanceSnapshot, tree: &RojoTree, id: RbxId #[derive(Default)] struct ComputePatchContext { - snapshot_id_to_instance_id: HashMap, + snapshot_id_to_instance_id: HashMap, } fn rewrite_refs_in_updates(context: &ComputePatchContext, updates: &mut [PatchUpdate]) { for update in updates { for property_value in update.changed_properties.values_mut() { - if let Some(RbxValue::Ref { value: Some(id) }) = property_value { - if let Some(&instance_id) = context.snapshot_id_to_instance_id.get(id) { - *property_value = Some(RbxValue::Ref { - value: Some(instance_id), - }); + if let Some(Variant::Ref(referent)) = property_value { + if let Some(&instance_ref) = context.snapshot_id_to_instance_id.get(referent) { + *property_value = Some(Variant::Ref(instance_ref)); } } } @@ -51,11 +49,9 @@ fn rewrite_refs_in_additions(context: &ComputePatchContext, additions: &mut [Pat fn rewrite_refs_in_snapshot(context: &ComputePatchContext, snapshot: &mut InstanceSnapshot) { for property_value in snapshot.properties.values_mut() { - if let RbxValue::Ref { value: Some(id) } = property_value { - if let Some(&instance_id) = context.snapshot_id_to_instance_id.get(id) { - *property_value = RbxValue::Ref { - value: Some(instance_id), - }; + if let Variant::Ref(referent) = property_value { + if let Some(&instance_referent) = context.snapshot_id_to_instance_id.get(referent) { + *property_value = Variant::Ref(instance_referent); } } } @@ -69,7 +65,7 @@ fn compute_patch_set_internal( context: &mut ComputePatchContext, snapshot: &InstanceSnapshot, tree: &RojoTree, - id: RbxId, + id: Ref, patch_set: &mut PatchSet, ) { if let Some(snapshot_id) = snapshot.snapshot_id { @@ -154,7 +150,7 @@ fn compute_children_patches( context: &mut ComputePatchContext, snapshot: &InstanceSnapshot, tree: &RojoTree, - id: RbxId, + id: Ref, patch_set: &mut PatchSet, ) { let instance = tree @@ -224,9 +220,6 @@ mod test { use std::borrow::Cow; use maplit::hashmap; - use rbx_dom_weak::RbxInstanceProperties; - - use super::super::InstancePropertiesWithMeta; /// This test makes sure that rewriting refs in instance update patches to /// instances that already exists works. We should be able to correlate the @@ -234,26 +227,17 @@ mod test { /// value before returning from compute_patch_set. #[test] fn rewrite_ref_existing_instance_update() { - let tree = RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "foo".to_owned(), - class_name: "foo".to_owned(), - properties: HashMap::new(), - }, - metadata: Default::default(), - }); + let tree = RojoTree::new(InstanceSnapshot::new().name("foo").class_name("foo")); let root_id = tree.get_root_id(); // This snapshot should be identical to the existing tree except for the // addition of a prop named Self, which is a self-referential Ref. - let snapshot_id = RbxId::new(); + let snapshot_id = Ref::new(); let snapshot = InstanceSnapshot { snapshot_id: Some(snapshot_id), properties: hashmap! { - "Self".to_owned() => RbxValue::Ref { - value: Some(snapshot_id), - } + "Self".to_owned() => Variant::Ref(snapshot_id), }, metadata: Default::default(), @@ -270,9 +254,7 @@ mod test { changed_name: None, changed_class_name: None, changed_properties: hashmap! { - "Self".to_owned() => Some(RbxValue::Ref { - value: Some(root_id), - }), + "Self".to_owned() => Some(Variant::Ref(root_id)), }, changed_metadata: None, }], @@ -288,26 +270,17 @@ mod test { /// one. #[test] fn rewrite_ref_existing_instance_addition() { - let tree = RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "foo".to_owned(), - class_name: "foo".to_owned(), - properties: HashMap::new(), - }, - metadata: Default::default(), - }); + let tree = RojoTree::new(InstanceSnapshot::new().name("foo").class_name("foo")); let root_id = tree.get_root_id(); // This patch describes the existing instance with a new child added. - let snapshot_id = RbxId::new(); + let snapshot_id = Ref::new(); let snapshot = InstanceSnapshot { snapshot_id: Some(snapshot_id), children: vec![InstanceSnapshot { properties: hashmap! { - "Self".to_owned() => RbxValue::Ref { - value: Some(snapshot_id), - }, + "Self".to_owned() => Variant::Ref(snapshot_id), }, snapshot_id: None, @@ -332,9 +305,7 @@ mod test { snapshot_id: None, metadata: Default::default(), properties: hashmap! { - "Self".to_owned() => RbxValue::Ref { - value: Some(root_id), - }, + "Self".to_owned() => Variant::Ref(root_id), }, name: Cow::Borrowed("child"), class_name: Cow::Borrowed("child"), diff --git a/src/snapshot/tests/apply.rs b/src/snapshot/tests/apply.rs index d9bb0753..96a365ac 100644 --- a/src/snapshot/tests/apply.rs +++ b/src/snapshot/tests/apply.rs @@ -1,11 +1,10 @@ use insta::assert_yaml_snapshot; use maplit::hashmap; -use rbx_dom_weak::{RbxInstanceProperties, RbxValue}; use rojo_insta_ext::RedactionMap; use crate::{ - snapshot::{apply_patch_set, InstancePropertiesWithMeta, PatchSet, PatchUpdate, RojoTree}, + snapshot::{apply_patch_set, InstanceSnapshot, PatchSet, PatchUpdate, RojoTree}, tree_view::{intern_tree, view_tree}, }; @@ -49,9 +48,7 @@ fn add_property() { changed_name: None, changed_class_name: None, changed_properties: hashmap! { - "Foo".to_owned() => Some(RbxValue::String { - value: "Value of Foo".to_owned(), - }), + "Foo".to_owned() => Some("Value of Foo".into()), }, changed_metadata: None, }], @@ -78,12 +75,9 @@ fn remove_property() { let root_id = tree.get_root_id(); let mut root_instance = tree.get_instance_mut(root_id).unwrap(); - root_instance.properties_mut().insert( - "Foo".to_owned(), - RbxValue::String { - value: "Should be removed".to_owned(), - }, - ); + root_instance + .properties_mut() + .insert("Foo".to_owned(), "Should be removed".into()); } let tree_view = view_tree(&tree, &mut redactions); @@ -112,12 +106,5 @@ fn remove_property() { } fn empty_tree() -> RojoTree { - RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "ROOT".to_owned(), - properties: Default::default(), - }, - metadata: Default::default(), - }) + RojoTree::new(InstanceSnapshot::new().name("ROOT").class_name("ROOT")) } diff --git a/src/snapshot/tests/compute.rs b/src/snapshot/tests/compute.rs index 8564ea34..c62978c9 100644 --- a/src/snapshot/tests/compute.rs +++ b/src/snapshot/tests/compute.rs @@ -2,11 +2,10 @@ use std::borrow::Cow; use insta::assert_yaml_snapshot; use maplit::hashmap; -use rbx_dom_weak::{RbxInstanceProperties, RbxValue}; use rojo_insta_ext::RedactionMap; -use crate::snapshot::{compute_patch_set, InstancePropertiesWithMeta, InstanceSnapshot, RojoTree}; +use crate::snapshot::{compute_patch_set, InstanceSnapshot, RojoTree}; #[test] fn set_name_and_class_name() { @@ -43,9 +42,7 @@ fn set_property() { name: Cow::Borrowed("ROOT"), class_name: Cow::Borrowed("ROOT"), properties: hashmap! { - "PropertyName".to_owned() => RbxValue::String { - value: "Hello, world!".to_owned(), - }, + "PropertyName".to_owned() => "Hello, world!".into(), }, children: Vec::new(), }; @@ -68,9 +65,7 @@ fn remove_property() { let mut root_instance = tree.get_instance_mut(root_id).unwrap(); root_instance.properties_mut().insert( "Foo".to_owned(), - RbxValue::String { - value: "This should be removed by the patch.".to_owned(), - }, + "This should be removed by the patch.".into(), ); } @@ -128,15 +123,8 @@ fn remove_child() { { let root_id = tree.get_root_id(); let new_id = tree.insert_instance( - InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "Should not appear in snapshot".to_owned(), - class_name: "Folder".to_owned(), - properties: Default::default(), - }, - metadata: Default::default(), - }, root_id, + InstanceSnapshot::new().name("Should not appear in snapshot"), ); redactions.intern(new_id); @@ -158,12 +146,5 @@ fn remove_child() { } fn empty_tree() -> RojoTree { - RojoTree::new(InstancePropertiesWithMeta { - properties: RbxInstanceProperties { - name: "ROOT".to_owned(), - class_name: "ROOT".to_owned(), - properties: Default::default(), - }, - metadata: Default::default(), - }) + RojoTree::new(InstanceSnapshot::new().name("ROOT").class_name("ROOT")) } diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index baafe32a..b0f12b69 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -1,26 +1,29 @@ use std::{ - collections::HashMap, + collections::{HashMap, VecDeque}, path::{Path, PathBuf}, }; -use rbx_dom_weak::{Descendants, RbxId, RbxInstance, RbxInstanceProperties, RbxTree, RbxValue}; +use rbx_dom_weak::{ + types::{Ref, Variant}, + Instance, InstanceBuilder, WeakDom, +}; use crate::multimap::MultiMap; -use super::InstanceMetadata; +use super::{InstanceMetadata, InstanceSnapshot}; -/// An expanded variant of rbx_dom_weak's `RbxTree` that tracks additional +/// An expanded variant of rbx_dom_weak's `WeakDom` that tracks additional /// metadata per instance that's Rojo-specific. /// /// This tree is also optimized for doing fast incremental updates and patches. #[derive(Debug)] pub struct RojoTree { /// Contains the instances without their Rojo-specific metadata. - inner: RbxTree, + inner: WeakDom, /// Metadata associated with each instance that is kept up-to-date with the /// set of actual instances. - metadata_map: HashMap, + metadata_map: HashMap, /// A multimap from source paths to all of the root instances that were /// constructed from that path. @@ -29,31 +32,42 @@ pub struct RojoTree { /// value portion of the map is also a set in order to support the same path /// appearing multiple times in the same Rojo project. This is sometimes /// called "path aliasing" in various Rojo documentation. - path_to_ids: MultiMap, + path_to_ids: MultiMap, } impl RojoTree { - pub fn new(root: InstancePropertiesWithMeta) -> RojoTree { + pub fn new(snapshot: InstanceSnapshot) -> RojoTree { + let root_builder = InstanceBuilder::new(snapshot.class_name.to_owned()) + .with_name(snapshot.name.to_owned()) + .with_properties(snapshot.properties); + let mut tree = RojoTree { - inner: RbxTree::new(root.properties), + inner: WeakDom::new(root_builder), metadata_map: HashMap::new(), path_to_ids: MultiMap::new(), }; - tree.insert_metadata(tree.inner.get_root_id(), root.metadata); + let root_ref = tree.inner.root_ref(); + + tree.insert_metadata(root_ref, snapshot.metadata); + + for child in snapshot.children { + tree.insert_instance(root_ref, child); + } + tree } - pub fn inner(&self) -> &RbxTree { + pub fn inner(&self) -> &WeakDom { &self.inner } - pub fn get_root_id(&self) -> RbxId { - self.inner.get_root_id() + pub fn get_root_id(&self) -> Ref { + self.inner.root_ref() } - pub fn get_instance(&self, id: RbxId) -> Option { - if let Some(instance) = self.inner.get_instance(id) { + pub fn get_instance(&self, id: Ref) -> Option { + if let Some(instance) = self.inner.get_by_ref(id) { let metadata = self.metadata_map.get(&id).unwrap(); Some(InstanceWithMeta { instance, metadata }) @@ -62,8 +76,8 @@ impl RojoTree { } } - pub fn get_instance_mut(&mut self, id: RbxId) -> Option { - if let Some(instance) = self.inner.get_instance_mut(id) { + pub fn get_instance_mut(&mut self, id: Ref) -> Option { + if let Some(instance) = self.inner.get_by_ref_mut(id) { let metadata = self.metadata_map.get_mut(&id).unwrap(); Some(InstanceWithMetaMut { instance, metadata }) @@ -72,38 +86,38 @@ impl RojoTree { } } - pub fn insert_instance( - &mut self, - properties: InstancePropertiesWithMeta, - parent_id: RbxId, - ) -> RbxId { - let id = self.inner.insert_instance(properties.properties, parent_id); - self.insert_metadata(id, properties.metadata); - id + pub fn insert_instance(&mut self, parent_ref: Ref, snapshot: InstanceSnapshot) -> Ref { + let builder = InstanceBuilder::new(snapshot.class_name.to_owned()) + .with_name(snapshot.name.to_owned()) + .with_properties(snapshot.properties); + + let referent = self.inner.insert(parent_ref, builder); + self.insert_metadata(referent, snapshot.metadata); + + for child in snapshot.children { + self.insert_instance(referent, child); + } + + referent } - pub fn remove_instance(&mut self, id: RbxId) -> Option { - if let Some(inner) = self.inner.remove_instance(id) { - let mut metadata_map = HashMap::new(); - let mut path_to_ids = MultiMap::new(); + pub fn remove(&mut self, id: Ref) { + let mut to_move = VecDeque::new(); + to_move.push_back(id); - self.move_metadata(id, &mut metadata_map, &mut path_to_ids); - for instance in inner.descendants(id) { - self.move_metadata(instance.get_id(), &mut metadata_map, &mut path_to_ids); + while let Some(id) = to_move.pop_front() { + self.remove_metadata(id); + + if let Some(instance) = self.inner.get_by_ref(id) { + to_move.extend(instance.children().iter().copied()); } - - Some(RojoTree { - inner, - metadata_map, - path_to_ids, - }) - } else { - None } + + self.inner.destroy(id); } /// Replaces the metadata associated with the given instance ID. - pub fn update_metadata(&mut self, id: RbxId, metadata: InstanceMetadata) { + pub fn update_metadata(&mut self, id: Ref, metadata: InstanceMetadata) { use std::collections::hash_map::Entry; match self.metadata_map.entry(id) { @@ -131,22 +145,22 @@ impl RojoTree { } } - pub fn descendants(&self, id: RbxId) -> RojoDescendants<'_> { - RojoDescendants { - inner: self.inner.descendants(id), - tree: self, - } + pub fn descendants(&self, id: Ref) -> RojoDescendants<'_> { + let mut queue = VecDeque::new(); + queue.push_back(id); + + RojoDescendants { queue, tree: self } } - pub fn get_ids_at_path(&self, path: &Path) -> &[RbxId] { + pub fn get_ids_at_path(&self, path: &Path) -> &[Ref] { self.path_to_ids.get(path) } - pub fn get_metadata(&self, id: RbxId) -> Option<&InstanceMetadata> { + pub fn get_metadata(&self, id: Ref) -> Option<&InstanceMetadata> { self.metadata_map.get(&id) } - fn insert_metadata(&mut self, id: RbxId, metadata: InstanceMetadata) { + fn insert_metadata(&mut self, id: Ref, metadata: InstanceMetadata) { for path in &metadata.relevant_paths { self.path_to_ids.insert(path.clone(), id); } @@ -156,25 +170,17 @@ impl RojoTree { /// Moves the Rojo metadata from the instance with the given ID from this /// tree into some loose maps. - fn move_metadata( - &mut self, - id: RbxId, - metadata_map: &mut HashMap, - path_to_ids: &mut MultiMap, - ) { + fn remove_metadata(&mut self, id: Ref) { let metadata = self.metadata_map.remove(&id).unwrap(); for path in &metadata.relevant_paths { self.path_to_ids.remove(path, id); - path_to_ids.insert(path.clone(), id); } - - metadata_map.insert(id, metadata); } } pub struct RojoDescendants<'a> { - inner: Descendants<'a>, + queue: VecDeque, tree: &'a RojoTree, } @@ -182,50 +188,43 @@ impl<'a> Iterator for RojoDescendants<'a> { type Item = InstanceWithMeta<'a>; fn next(&mut self) -> Option { - let instance = self.inner.next()?; + let id = self.queue.pop_front()?; + + let instance = self + .tree + .inner + .get_by_ref(id) + .expect("Instance did not exist"); + let metadata = self .tree - .get_metadata(instance.get_id()) + .get_metadata(instance.referent()) .expect("Metadata did not exist for instance"); + self.queue.extend(instance.children().iter().copied()); + Some(InstanceWithMeta { instance, metadata }) } } -/// RojoTree's equivalent of `RbxInstanceProperties`. -#[derive(Debug, Clone)] -pub struct InstancePropertiesWithMeta { - pub properties: RbxInstanceProperties, - pub metadata: InstanceMetadata, -} - -impl InstancePropertiesWithMeta { - pub fn new(properties: RbxInstanceProperties, metadata: InstanceMetadata) -> Self { - InstancePropertiesWithMeta { - properties, - metadata, - } - } -} - -/// RojoTree's equivalent of `&'a RbxInstance`. +/// RojoTree's equivalent of `&'a Instance`. /// /// This has to be a value type for RojoTree because the instance and metadata /// are stored in different places. The mutable equivalent is /// `InstanceWithMetaMut`. #[derive(Debug, Clone, Copy)] pub struct InstanceWithMeta<'a> { - instance: &'a RbxInstance, + instance: &'a Instance, metadata: &'a InstanceMetadata, } impl<'a> InstanceWithMeta<'a> { - pub fn id(&self) -> RbxId { - self.instance.get_id() + pub fn id(&self) -> Ref { + self.instance.referent() } - pub fn parent(&self) -> Option { - self.instance.get_parent_id() + pub fn parent(&self) -> Ref { + self.instance.parent() } pub fn name(&self) -> &'a str { @@ -233,15 +232,15 @@ impl<'a> InstanceWithMeta<'a> { } pub fn class_name(&self) -> &'a str { - &self.instance.class_name + &self.instance.class } - pub fn properties(&self) -> &'a HashMap { + pub fn properties(&self) -> &'a HashMap { &self.instance.properties } - pub fn children(&self) -> &'a [RbxId] { - self.instance.get_children_ids() + pub fn children(&self) -> &'a [Ref] { + self.instance.children() } pub fn metadata(&self) -> &'a InstanceMetadata { @@ -249,20 +248,20 @@ impl<'a> InstanceWithMeta<'a> { } } -/// RojoTree's equivalent of `&'a mut RbxInstance`. +/// RojoTree's equivalent of `&'a mut Instance`. /// /// This has to be a value type for RojoTree because the instance and metadata /// are stored in different places. The immutable equivalent is /// `InstanceWithMeta`. #[derive(Debug)] pub struct InstanceWithMetaMut<'a> { - instance: &'a mut RbxInstance, + instance: &'a mut Instance, metadata: &'a mut InstanceMetadata, } impl InstanceWithMetaMut<'_> { - pub fn id(&self) -> RbxId { - self.instance.get_id() + pub fn id(&self) -> Ref { + self.instance.referent() } pub fn name(&self) -> &str { @@ -274,23 +273,23 @@ impl InstanceWithMetaMut<'_> { } pub fn class_name(&self) -> &str { - &self.instance.class_name + &self.instance.class } pub fn class_name_mut(&mut self) -> &mut String { - &mut self.instance.class_name + &mut self.instance.class } - pub fn properties(&self) -> &HashMap { + pub fn properties(&self) -> &HashMap { &self.instance.properties } - pub fn properties_mut(&mut self) -> &mut HashMap { + pub fn properties_mut(&mut self) -> &mut HashMap { &mut self.instance.properties } - pub fn children(&self) -> &[RbxId] { - self.instance.get_children_ids() + pub fn children(&self) -> &[Ref] { + self.instance.children() } pub fn metadata(&self) -> &InstanceMetadata { diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index fd39b04e..1734fc07 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -3,7 +3,6 @@ use std::{collections::BTreeMap, path::Path}; use anyhow::Context; use maplit::hashmap; use memofs::{IoResultExt, Vfs}; -use rbx_dom_weak::RbxValue; use serde::Serialize; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; @@ -30,9 +29,7 @@ pub fn snapshot_csv( .name(instance_name) .class_name("LocalizationTable") .properties(hashmap! { - "Contents".to_owned() => RbxValue::String { - value: table_contents, - }, + "Contents".to_owned() => table_contents.into(), }) .metadata( InstanceMetadata::new() @@ -41,8 +38,8 @@ pub fn snapshot_csv( ); if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { - let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; - metadata.apply_all(&mut snapshot); + let mut metadata = AdjacentMetadata::from_slice(&meta_contents, meta_path)?; + metadata.apply_all(&mut snapshot)?; } Ok(Some(snapshot)) diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 84c7d64a..e4b47ffc 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -60,8 +60,8 @@ pub fn snapshot_dir(context: &InstanceContext, vfs: &Vfs, path: &Path) -> Snapsh ); if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { - let mut metadata = DirectoryMetadata::from_slice(&meta_contents, &meta_path)?; - metadata.apply_all(&mut snapshot); + let mut metadata = DirectoryMetadata::from_slice(&meta_contents, meta_path)?; + metadata.apply_all(&mut snapshot)?; } Ok(Some(snapshot)) diff --git a/src/snapshot_middleware/json.rs b/src/snapshot_middleware/json.rs index 959b3cb3..2e5c53fc 100644 --- a/src/snapshot_middleware/json.rs +++ b/src/snapshot_middleware/json.rs @@ -3,7 +3,6 @@ use std::path::Path; use anyhow::Context; use maplit::hashmap; use memofs::{IoResultExt, Vfs}; -use rbx_dom_weak::RbxValue; use crate::{ lua_ast::{Expression, Statement}, @@ -26,9 +25,7 @@ pub fn snapshot_json( let as_lua = json_to_lua(value).to_string(); let properties = hashmap! { - "Source".to_owned() => RbxValue::String { - value: as_lua, - }, + "Source".to_owned() => as_lua.into(), }; let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); @@ -45,8 +42,8 @@ pub fn snapshot_json( ); if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { - let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; - metadata.apply_all(&mut snapshot); + let mut metadata = AdjacentMetadata::from_slice(&meta_contents, meta_path)?; + metadata.apply_all(&mut snapshot)?; } Ok(Some(snapshot)) diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index b0dd361c..b14b66b4 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -2,11 +2,12 @@ use std::{borrow::Cow, collections::HashMap, path::Path}; use anyhow::Context; use memofs::Vfs; -use rbx_dom_weak::UnresolvedRbxValue; -use rbx_reflection::try_resolve_value; use serde::Deserialize; -use crate::snapshot::{InstanceContext, InstanceSnapshot}; +use crate::{ + resolution::UnresolvedValue, + snapshot::{InstanceContext, InstanceSnapshot}, +}; use super::middleware::SnapshotInstanceResult; @@ -20,7 +21,10 @@ pub fn snapshot_json_model( let instance: JsonModel = serde_json::from_slice(&contents) .with_context(|| format!("File is not a valid JSON model: {}", path.display()))?; - let mut snapshot = instance.core.into_snapshot(instance_name.to_owned()); + let mut snapshot = instance + .core + .into_snapshot(instance_name.to_owned()) + .with_context(|| format!("Could not load JSON model: {}", path.display()))?; snapshot.metadata = snapshot .metadata @@ -58,36 +62,32 @@ struct JsonModelCore { children: Vec, #[serde(default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")] - properties: HashMap, + properties: HashMap, } impl JsonModelCore { - fn into_snapshot(self, name: String) -> InstanceSnapshot { + fn into_snapshot(self, name: String) -> anyhow::Result { let class_name = self.class_name; - let children = self - .children - .into_iter() - .map(|child| child.core.into_snapshot(child.name)) - .collect(); + let mut children = Vec::with_capacity(self.children.len()); + for child in self.children { + children.push(child.core.into_snapshot(child.name)?); + } - let properties = self - .properties - .into_iter() - .map(|(key, value)| { - try_resolve_value(&class_name, &key, &value).map(|resolved| (key, resolved)) - }) - .collect::, _>>() - .expect("TODO: Handle rbx_reflection errors"); + let mut properties = HashMap::with_capacity(self.properties.len()); + for (key, unresolved) in self.properties { + let value = unresolved.resolve(&class_name, &key)?; + properties.insert(key, value); + } - InstanceSnapshot { + Ok(InstanceSnapshot { snapshot_id: None, metadata: Default::default(), name: Cow::Owned(name), class_name: Cow::Owned(class_name), properties, children, - } + }) } } diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index bfea5324..cc443084 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -3,7 +3,6 @@ use std::{path::Path, str}; use anyhow::Context; use maplit::hashmap; use memofs::{IoResultExt, Vfs}; -use rbx_dom_weak::RbxValue; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; @@ -38,9 +37,7 @@ pub fn snapshot_lua(context: &InstanceContext, vfs: &Vfs, path: &Path) -> Snapsh .name(instance_name) .class_name(class_name) .properties(hashmap! { - "Source".to_owned() => RbxValue::String { - value: contents_str, - }, + "Source".to_owned() => contents_str.into(), }) .metadata( InstanceMetadata::new() @@ -50,8 +47,8 @@ pub fn snapshot_lua(context: &InstanceContext, vfs: &Vfs, path: &Path) -> Snapsh ); if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { - let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; - metadata.apply_all(&mut snapshot); + let mut metadata = AdjacentMetadata::from_slice(&meta_contents, meta_path)?; + metadata.apply_all(&mut snapshot)?; } Ok(Some(snapshot)) diff --git a/src/snapshot_middleware/meta_file.rs b/src/snapshot_middleware/meta_file.rs index 618f72c6..2715dbbe 100644 --- a/src/snapshot_middleware/meta_file.rs +++ b/src/snapshot_middleware/meta_file.rs @@ -1,11 +1,9 @@ -use std::{borrow::Cow, collections::HashMap, path::Path}; +use std::{borrow::Cow, collections::HashMap, path::PathBuf}; -use anyhow::Context; -use rbx_dom_weak::UnresolvedRbxValue; -use rbx_reflection::try_resolve_value; +use anyhow::{format_err, Context}; use serde::{Deserialize, Serialize}; -use crate::snapshot::InstanceSnapshot; +use crate::{resolution::UnresolvedValue, snapshot::InstanceSnapshot}; /// Represents metadata in a sibling file with the same basename. /// @@ -18,17 +16,23 @@ pub struct AdjacentMetadata { pub ignore_unknown_instances: Option, #[serde(default, skip_serializing_if = "HashMap::is_empty")] - pub properties: HashMap, + pub properties: HashMap, + + #[serde(skip)] + pub path: PathBuf, } impl AdjacentMetadata { - pub fn from_slice(slice: &[u8], path: &Path) -> anyhow::Result { - serde_json::from_slice(slice).with_context(|| { + pub fn from_slice(slice: &[u8], path: PathBuf) -> anyhow::Result { + let mut meta: Self = serde_json::from_slice(slice).with_context(|| { format!( "File contained malformed .meta.json data: {}", path.display() ) - }) + })?; + + meta.path = path; + Ok(meta) } pub fn apply_ignore_unknown_instances(&mut self, snapshot: &mut InstanceSnapshot) { @@ -37,23 +41,24 @@ impl AdjacentMetadata { } } - pub fn apply_properties(&mut self, snapshot: &mut InstanceSnapshot) { - let class_name = &snapshot.class_name; + pub fn apply_properties(&mut self, snapshot: &mut InstanceSnapshot) -> anyhow::Result<()> { + let path = &self.path; - let source_properties = self.properties.drain().map(|(key, value)| { - try_resolve_value(class_name, &key, &value) - .map(|resolved| (key, resolved)) - .expect("TODO: Handle rbx_reflection errors") - }); + for (key, unresolved) in self.properties.drain() { + let value = unresolved + .resolve(&snapshot.class_name, &key) + .with_context(|| format!("error applying meta file {}", path.display()))?; - for (key, value) in source_properties { snapshot.properties.insert(key, value); } + + Ok(()) } - pub fn apply_all(&mut self, snapshot: &mut InstanceSnapshot) { + pub fn apply_all(&mut self, snapshot: &mut InstanceSnapshot) -> anyhow::Result<()> { self.apply_ignore_unknown_instances(snapshot); - self.apply_properties(snapshot); + self.apply_properties(snapshot)?; + Ok(()) } // TODO: Add method to allow selectively applying parts of metadata and @@ -71,37 +76,50 @@ pub struct DirectoryMetadata { pub ignore_unknown_instances: Option, #[serde(default, skip_serializing_if = "HashMap::is_empty")] - pub properties: HashMap, + pub properties: HashMap, #[serde(skip_serializing_if = "Option::is_none")] pub class_name: Option, + + #[serde(skip)] + pub path: PathBuf, } impl DirectoryMetadata { - pub fn from_slice(slice: &[u8], path: &Path) -> anyhow::Result { - serde_json::from_slice(slice).with_context(|| { + pub fn from_slice(slice: &[u8], path: PathBuf) -> anyhow::Result { + let mut meta: Self = serde_json::from_slice(slice).with_context(|| { format!( "File contained malformed init.meta.json data: {}", path.display() ) - }) + })?; + + meta.path = path; + Ok(meta) } - pub fn apply_all(&mut self, snapshot: &mut InstanceSnapshot) { + pub fn apply_all(&mut self, snapshot: &mut InstanceSnapshot) -> anyhow::Result<()> { self.apply_ignore_unknown_instances(snapshot); - self.apply_class_name(snapshot); - self.apply_properties(snapshot); + self.apply_class_name(snapshot)?; + self.apply_properties(snapshot)?; + + Ok(()) } - fn apply_class_name(&mut self, snapshot: &mut InstanceSnapshot) { + fn apply_class_name(&mut self, snapshot: &mut InstanceSnapshot) -> anyhow::Result<()> { if let Some(class_name) = self.class_name.take() { if snapshot.class_name != "Folder" { // TODO: Turn into error type - panic!("className in init.meta.json can only be specified if the affected directory would turn into a Folder instance."); + return Err(format_err!( + "className in init.meta.json can only be specified if the \ + affected directory would turn into a Folder instance." + )); } snapshot.class_name = Cow::Owned(class_name); } + + Ok(()) } fn apply_ignore_unknown_instances(&mut self, snapshot: &mut InstanceSnapshot) { @@ -110,17 +128,17 @@ impl DirectoryMetadata { } } - fn apply_properties(&mut self, snapshot: &mut InstanceSnapshot) { - let class_name = &snapshot.class_name; + fn apply_properties(&mut self, snapshot: &mut InstanceSnapshot) -> anyhow::Result<()> { + let path = &self.path; - let source_properties = self.properties.drain().map(|(key, value)| { - try_resolve_value(class_name, &key, &value) - .map(|resolved| (key, resolved)) - .expect("TODO: Handle rbx_reflection errors") - }); + for (key, unresolved) in self.properties.drain() { + let value = unresolved + .resolve(&snapshot.class_name, &key) + .with_context(|| format!("error applying meta file {}", path.display()))?; - for (key, value) in source_properties { snapshot.properties.insert(key, value); } + + Ok(()) } } diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index c644c396..1c88e4b9 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, collections::HashMap, path::Path}; use anyhow::Context; use memofs::Vfs; -use rbx_reflection::{get_class_descriptor, try_resolve_value}; +use rbx_reflection::ClassTag; use crate::{ project::{Project, ProjectNode}, @@ -140,9 +140,9 @@ pub fn snapshot_project_node( // Members of DataModel with names that match known services are // probably supposed to be those services. - let descriptor = get_class_descriptor(&name)?; + let descriptor = rbx_reflection_database::get().classes.get(&name)?; - if descriptor.is_service() { + if descriptor.tags.contains(&ClassTag::Service) { return Some(name.clone()); } } else if parent_class == "StarterPlayer" { @@ -171,11 +171,18 @@ pub fn snapshot_project_node( } } - for (key, value) in &node.properties { - let resolved_value = try_resolve_value(&class_name, key, value) - .expect("TODO: Properly handle value resolution errors"); + for (key, unresolved) in &node.properties { + let value = unresolved + .clone() + .resolve(&class_name, key) + .with_context(|| { + format!( + "Unresolvable property in project at path {}", + project_path.display() + ) + })?; - properties.insert(key.clone(), resolved_value); + properties.insert(key.clone(), value); } // If the user specified $ignoreUnknownInstances, overwrite the existing diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 68080b1d..6e632328 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -1,8 +1,7 @@ -use std::{collections::HashMap, path::Path}; +use std::path::Path; use anyhow::Context; use memofs::Vfs; -use rbx_dom_weak::{RbxInstanceProperties, RbxTree}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; @@ -14,18 +13,11 @@ pub fn snapshot_rbxm( path: &Path, instance_name: &str, ) -> SnapshotInstanceResult { - let mut temp_tree = RbxTree::new(RbxInstanceProperties { - name: "DataModel".to_owned(), - class_name: "DataModel".to_owned(), - properties: HashMap::new(), - }); - - let root_id = temp_tree.get_root_id(); - rbx_binary::decode(&mut temp_tree, root_id, vfs.read(path)?.as_slice()) + let temp_tree = rbx_binary::from_reader_default(vfs.read(path)?.as_slice()) .with_context(|| format!("Malformed rbxm file: {}", path.display()))?; - let root_instance = temp_tree.get_instance(root_id).unwrap(); - let children = root_instance.get_children_ids(); + let root_instance = temp_tree.root(); + let children = root_instance.children(); if children.len() == 1 { let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index e24a6f58..37ffbe78 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -19,8 +19,8 @@ pub fn snapshot_rbxmx( let temp_tree = rbx_xml::from_reader(vfs.read(path)?.as_slice(), options) .with_context(|| format!("Malformed rbxm file: {}", path.display()))?; - let root_instance = temp_tree.get_instance(temp_tree.get_root_id()).unwrap(); - let children = root_instance.get_children_ids(); + let root_instance = temp_tree.root(); + let children = root_instance.children(); if children.len() == 1 { let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap index 427f2ab9..a00fa612 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap @@ -14,7 +14,7 @@ name: foo class_name: IntValue properties: Value: - Type: Int32 + Type: Int64 Value: 5 children: - snapshot_id: ~ diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 4e408475..4cbf0c3d 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -3,7 +3,6 @@ use std::{path::Path, str}; use anyhow::Context; use maplit::hashmap; use memofs::{IoResultExt, Vfs}; -use rbx_dom_weak::RbxValue; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; @@ -21,9 +20,7 @@ pub fn snapshot_txt( .to_owned(); let properties = hashmap! { - "Value".to_owned() => RbxValue::String { - value: contents_str, - }, + "Value".to_owned() => contents_str.into(), }; let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); @@ -40,8 +37,8 @@ pub fn snapshot_txt( ); if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { - let mut metadata = AdjacentMetadata::from_slice(&meta_contents, &meta_path)?; - metadata.apply_all(&mut snapshot); + let mut metadata = AdjacentMetadata::from_slice(&meta_contents, meta_path)?; + metadata.apply_all(&mut snapshot)?; } Ok(Some(snapshot)) diff --git a/src/tree_view.rs b/src/tree_view.rs index a55e7e92..db0624d4 100644 --- a/src/tree_view.rs +++ b/src/tree_view.rs @@ -1,6 +1,6 @@ use std::collections::HashMap; -use rbx_dom_weak::{RbxId, RbxValue}; +use rbx_dom_weak::types::{Ref, Variant}; use rojo_insta_ext::RedactionMap; use serde::Serialize; @@ -29,15 +29,15 @@ pub fn intern_tree(tree: &RojoTree, redactions: &mut RedactionMap) { /// Copy of data from RojoTree in the right shape to have useful snapshots. #[derive(Debug, Serialize)] struct InstanceView { - id: RbxId, + id: Ref, name: String, class_name: String, - properties: HashMap, + properties: HashMap, metadata: InstanceMetadata, children: Vec, } -fn extract_instance_view(tree: &RojoTree, id: RbxId) -> InstanceView { +fn extract_instance_view(tree: &RojoTree, id: Ref) -> InstanceView { let instance = tree.get_instance(id).unwrap(); InstanceView { diff --git a/src/web/api.rs b/src/web/api.rs index d041b9c1..6a41f2e5 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -1,12 +1,12 @@ //! Defines Rojo's HTTP API, all under /api. These endpoints generally return //! JSON. -use std::{collections::HashMap, fs, path::PathBuf, sync::Arc}; +use std::{collections::HashMap, fs, path::PathBuf, str::FromStr, sync::Arc}; use futures::{Future, Stream}; use hyper::{service::Service, Body, Method, Request, StatusCode}; -use rbx_dom_weak::RbxId; +use rbx_dom_weak::types::Ref; use crate::{ serve_session::ServeSession, @@ -200,11 +200,11 @@ impl ApiService { fn handle_api_read(&self, request: Request) -> ::Future { let argument = &request.uri().path()["/api/read/".len()..]; - let requested_ids: Option> = argument.split(',').map(RbxId::parse_str).collect(); + let requested_ids: Result, _> = argument.split(',').map(Ref::from_str).collect(); let requested_ids = match requested_ids { - Some(ids) => ids, - None => { + Ok(ids) => ids, + Err(_) => { return json( ErrorResponse::bad_request("Malformed ID list"), StatusCode::BAD_REQUEST, @@ -239,9 +239,9 @@ impl ApiService { /// Open a script with the given ID in the user's default text editor. fn handle_api_open(&self, request: Request) -> ::Future { let argument = &request.uri().path()["/api/open/".len()..]; - let requested_id = match RbxId::parse_str(argument) { - Some(id) => id, - None => { + let requested_id = match Ref::from_str(argument) { + Ok(id) => id, + Err(_) => { return json( ErrorResponse::bad_request("Invalid instance ID"), StatusCode::BAD_REQUEST, diff --git a/src/web/interface.rs b/src/web/interface.rs index be37f1e0..9a0c2206 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -5,7 +5,7 @@ use std::{ collections::{HashMap, HashSet}, }; -use rbx_dom_weak::{RbxId, RbxValue}; +use rbx_dom_weak::types::{Ref, Variant}; use serde::{Deserialize, Serialize}; use crate::{ @@ -23,22 +23,22 @@ pub const PROTOCOL_VERSION: u64 = 3; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct SubscribeMessage<'a> { - pub removed: Vec, - pub added: HashMap>, + pub removed: Vec, + pub added: HashMap>, pub updated: Vec, } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct InstanceUpdate { - pub id: RbxId, + pub id: Ref, pub changed_name: Option, pub changed_class_name: Option, // TODO: Transform from HashMap> to something else, since // null will get lost when decoding from JSON in some languages. #[serde(default)] - pub changed_properties: HashMap>, + pub changed_properties: HashMap>, pub changed_metadata: Option, } @@ -59,23 +59,36 @@ impl InstanceMetadata { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "PascalCase")] pub struct Instance<'a> { - pub id: RbxId, - pub parent: Option, + pub id: Ref, + pub parent: Ref, pub name: Cow<'a, str>, pub class_name: Cow<'a, str>, - pub properties: Cow<'a, HashMap>, - pub children: Cow<'a, [RbxId]>, + pub properties: HashMap>, + pub children: Cow<'a, [Ref]>, pub metadata: Option, } impl<'a> Instance<'a> { pub(crate) fn from_rojo_instance(source: InstanceWithMeta<'_>) -> Instance<'_> { + let properties = source + .properties() + .iter() + .filter_map(|(key, value)| { + // SharedString values can't be serialized via Serde + if matches!(value, Variant::SharedString(_)) { + return None; + } + + Some((key.clone(), Cow::Borrowed(value))) + }) + .collect(); + Instance { id: source.id(), parent: source.parent(), name: Cow::Borrowed(source.name()), class_name: Cow::Borrowed(source.class_name()), - properties: Cow::Borrowed(source.properties()), + properties, children: Cow::Borrowed(source.children()), metadata: Some(InstanceMetadata::from_rojo_metadata(source.metadata())), } @@ -91,7 +104,7 @@ pub struct ServerInfoResponse { pub protocol_version: u64, pub project_name: String, pub expected_place_ids: Option>, - pub root_instance_id: RbxId, + pub root_instance_id: Ref, } /// Response body from /api/read/{id} @@ -100,17 +113,17 @@ pub struct ServerInfoResponse { pub struct ReadResponse<'a> { pub session_id: SessionId, pub message_cursor: u32, - pub instances: HashMap>, + pub instances: HashMap>, } #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct WriteRequest { pub session_id: SessionId, - pub removed: Vec, + pub removed: Vec, #[serde(default)] - pub added: HashMap, + pub added: HashMap, pub updated: Vec, } diff --git a/src/web/ui.rs b/src/web/ui.rs index a3705e06..7cc58d77 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -5,7 +5,7 @@ use std::{borrow::Cow, sync::Arc, time::Duration}; use futures::{future, Future}; use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; use maplit::hashmap; -use rbx_dom_weak::{RbxId, RbxValue}; +use rbx_dom_weak::types::{Ref, Variant}; use ritz::{html, Fragment, HtmlContent, HtmlSelfClosingTag}; use crate::{ @@ -93,7 +93,7 @@ impl UiService { .unwrap() } - fn instance(tree: &RojoTree, id: RbxId) -> HtmlContent<'_> { + fn instance(tree: &RojoTree, id: Ref) -> HtmlContent<'_> { let instance = tree.get_instance(id).unwrap(); let children_list: Vec<_> = instance .children() @@ -126,7 +126,7 @@ impl UiService { .map(|(key, value)| { html! {
    - { key.clone() } ": " { format!("{:?}", value.get_type()) } + { key.clone() } ": " { format!("{:?}", value.ty()) }
    } }) @@ -198,7 +198,7 @@ impl UiService { html! {
    -
     
    - - Actions status - - - Latest server version - - - Rojo Documentation - + Actions status + Latest server version + Rojo Documentation

    @@ -48,7 +40,7 @@ Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions fo Pull requests are welcome! -Rojo supports Rust 1.43.1 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. +Rojo supports Rust 1.46.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. ## License Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file diff --git a/src/cli/build.rs b/src/cli/build.rs index 18798037..38273f82 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -50,7 +50,7 @@ impl BuildCommand { write_model(&session, &self.output, output_kind)?; if self.watch { - let mut rt = Runtime::new().unwrap(); + let rt = Runtime::new().unwrap(); loop { let receiver = session.message_queue().subscribe(cursor); diff --git a/src/message_queue.rs b/src/message_queue.rs index 13c18ce4..cbac1862 100644 --- a/src/message_queue.rs +++ b/src/message_queue.rs @@ -1,6 +1,6 @@ use std::sync::{Mutex, RwLock}; -use futures::sync::oneshot; +use futures::channel::oneshot; /// A message queue with persistent history that can be subscribed to. /// diff --git a/src/web/api.rs b/src/web/api.rs index 4038943a..97624c7e 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -3,9 +3,7 @@ use std::{collections::HashMap, fs, path::PathBuf, str::FromStr, sync::Arc}; -use futures::{Future, Stream}; - -use hyper::{service::Service, Body, Method, Request, StatusCode}; +use hyper::{body, Body, Method, Request, Response, StatusCode}; use rbx_dom_weak::types::Ref; use crate::{ @@ -21,36 +19,32 @@ use crate::{ }, }; -pub struct ApiService { - serve_session: Arc, +pub async fn call(serve_session: Arc, request: Request) -> Response { + let service = ApiService::new(serve_session); + + match (request.method(), request.uri().path()) { + (&Method::GET, "/api/rojo") => service.handle_api_rojo().await, + (&Method::GET, path) if path.starts_with("/api/read/") => { + service.handle_api_read(request).await + } + (&Method::GET, path) if path.starts_with("/api/subscribe/") => { + service.handle_api_subscribe(request).await + } + (&Method::POST, path) if path.starts_with("/api/open/") => { + service.handle_api_open(request).await + } + + (&Method::POST, "/api/write") => service.handle_api_write(request).await, + + (_method, path) => json( + ErrorResponse::not_found(format!("Route not found: {}", path)), + StatusCode::NOT_FOUND, + ), + } } -impl Service for ApiService { - type ReqBody = Body; - type ResBody = Body; - type Error = hyper::Error; - type Future = - Box, Error = Self::Error> + Send>; - - fn call(&mut self, request: hyper::Request) -> Self::Future { - match (request.method(), request.uri().path()) { - (&Method::GET, "/api/rojo") => self.handle_api_rojo(), - (&Method::GET, path) if path.starts_with("/api/read/") => self.handle_api_read(request), - (&Method::GET, path) if path.starts_with("/api/subscribe/") => { - self.handle_api_subscribe(request) - } - (&Method::POST, path) if path.starts_with("/api/open/") => { - self.handle_api_open(request) - } - - (&Method::POST, "/api/write") => self.handle_api_write(request), - - (_method, path) => json( - ErrorResponse::not_found(format!("Route not found: {}", path)), - StatusCode::NOT_FOUND, - ), - } - } +pub struct ApiService { + serve_session: Arc, } impl ApiService { @@ -59,7 +53,7 @@ impl ApiService { } /// Get a summary of information about the server - fn handle_api_rojo(&self) -> ::Future { + async fn handle_api_rojo(&self) -> Response { let tree = self.serve_session.tree(); let root_instance_id = tree.get_root_id(); @@ -77,7 +71,7 @@ impl ApiService { /// Retrieve any messages past the given cursor index, and if /// there weren't any, subscribe to receive any new messages. - fn handle_api_subscribe(&self, request: Request) -> ::Future { + async fn handle_api_subscribe(&self, request: Request) -> Response { let argument = &request.uri().path()["/api/subscribe/".len()..]; let input_cursor: u32 = match argument.parse() { Ok(v) => v, @@ -91,11 +85,15 @@ impl ApiService { let session_id = self.serve_session.session_id(); - let receiver = self.serve_session.message_queue().subscribe(input_cursor); + let result = self + .serve_session + .message_queue() + .subscribe(input_cursor) + .await; let tree_handle = self.serve_session.tree_handle(); - Box::new(receiver.then(move |result| match result { + match result { Ok((message_cursor, messages)) => { let tree = tree_handle.lock().unwrap(); @@ -151,56 +149,56 @@ impl ApiService { ErrorResponse::internal_error("Message queue disconnected sender"), StatusCode::INTERNAL_SERVER_ERROR, ), - })) + } } - fn handle_api_write(&self, request: Request) -> ::Future { + async fn handle_api_write(&self, request: Request) -> Response { let session_id = self.serve_session.session_id(); let tree_mutation_sender = self.serve_session.tree_mutation_sender(); - Box::new(request.into_body().concat2().and_then(move |body| { - let request: WriteRequest = match serde_json::from_slice(&body) { - Ok(request) => request, - Err(err) => { - return json( - ErrorResponse::bad_request(format!("Invalid body: {}", err)), - StatusCode::BAD_REQUEST, - ); - } - }; + let body = body::to_bytes(request.into_body()).await.unwrap(); - if request.session_id != session_id { + let request: WriteRequest = match serde_json::from_slice(&body) { + Ok(request) => request, + Err(err) => { return json( - ErrorResponse::bad_request("Wrong session ID"), + ErrorResponse::bad_request(format!("Invalid body: {}", err)), StatusCode::BAD_REQUEST, ); } + }; - let updated_instances = request - .updated - .into_iter() - .map(|update| PatchUpdate { - id: update.id, - changed_class_name: update.changed_class_name, - changed_name: update.changed_name, - changed_properties: update.changed_properties, - changed_metadata: None, - }) - .collect(); + if request.session_id != session_id { + return json( + ErrorResponse::bad_request("Wrong session ID"), + StatusCode::BAD_REQUEST, + ); + } - tree_mutation_sender - .send(PatchSet { - removed_instances: Vec::new(), - added_instances: Vec::new(), - updated_instances, - }) - .unwrap(); + let updated_instances = request + .updated + .into_iter() + .map(|update| PatchUpdate { + id: update.id, + changed_class_name: update.changed_class_name, + changed_name: update.changed_name, + changed_properties: update.changed_properties, + changed_metadata: None, + }) + .collect(); - json_ok(&WriteResponse { session_id }) - })) + tree_mutation_sender + .send(PatchSet { + removed_instances: Vec::new(), + added_instances: Vec::new(), + updated_instances, + }) + .unwrap(); + + json_ok(&WriteResponse { session_id }) } - fn handle_api_read(&self, request: Request) -> ::Future { + async fn handle_api_read(&self, request: Request) -> Response { let argument = &request.uri().path()["/api/read/".len()..]; let requested_ids: Result, _> = argument.split(',').map(Ref::from_str).collect(); @@ -239,7 +237,7 @@ impl ApiService { } /// Open a script with the given ID in the user's default text editor. - fn handle_api_open(&self, request: Request) -> ::Future { + async fn handle_api_open(&self, request: Request) -> Response { let argument = &request.uri().path()["/api/open/".len()..]; let requested_id = match Ref::from_str(argument) { Ok(id) => id, diff --git a/src/web/mod.rs b/src/web/mod.rs index 5b3109f8..d6df4b15 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -8,50 +8,19 @@ pub mod interface; mod ui; mod util; -use std::{net::SocketAddr, sync::Arc}; +use std::convert::Infallible; +use std::net::SocketAddr; +use std::sync::Arc; -use futures::{ - future::{self, FutureResult}, - Future, +use hyper::{ + server::Server, + service::{make_service_fn, service_fn}, + Body, Request, }; -use hyper::{service::Service, Body, Request, Response, Server}; -use log::trace; +use tokio::runtime::Runtime; use crate::serve_session::ServeSession; -use self::{api::ApiService, ui::UiService}; - -pub struct RootService { - api: ApiService, - ui: UiService, -} - -impl Service for RootService { - type ReqBody = Body; - type ResBody = Body; - type Error = hyper::Error; - type Future = Box, Error = Self::Error> + Send>; - - fn call(&mut self, request: Request) -> Self::Future { - trace!("{} {}", request.method(), request.uri().path()); - - if request.uri().path().starts_with("/api") { - self.api.call(request) - } else { - self.ui.call(request) - } - } -} - -impl RootService { - pub fn new(serve_session: Arc) -> Self { - RootService { - api: ApiService::new(Arc::clone(&serve_session)), - ui: UiService::new(Arc::clone(&serve_session)), - } - } -} - pub struct LiveServer { serve_session: Arc, } @@ -62,14 +31,31 @@ impl LiveServer { } pub fn start(self, address: SocketAddr) { - let server = Server::bind(&address) - .serve(move || { - let service: FutureResult<_, hyper::Error> = - future::ok(RootService::new(Arc::clone(&self.serve_session))); - service - }) - .map_err(|e| eprintln!("Server error: {}", e)); + let serve_session = Arc::clone(&self.serve_session); - hyper::rt::run(server); + let make_service = make_service_fn(move |_conn| { + let serve_session = Arc::clone(&serve_session); + + async { + let service = move |req: Request| { + let serve_session = Arc::clone(&serve_session); + + async move { + if req.uri().path().starts_with("/api") { + Ok::<_, Infallible>(api::call(serve_session, req).await) + } else { + Ok::<_, Infallible>(ui::call(serve_session, req).await) + } + } + }; + + Ok::<_, Infallible>(service_fn(service)) + } + }); + + let rt = Runtime::new().unwrap(); + let _guard = rt.enter(); + let server = Server::bind(&address).serve(make_service); + rt.block_on(server).unwrap(); } } diff --git a/src/web/ui.rs b/src/web/ui.rs index 6ace230c..0199d58d 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -6,8 +6,7 @@ use std::{borrow::Cow, sync::Arc, time::Duration}; -use futures::{future, Future}; -use hyper::{header, service::Service, Body, Method, Request, Response, StatusCode}; +use hyper::{header, Body, Method, Request, Response, StatusCode}; use maplit::hashmap; use rbx_dom_weak::types::{Ref, Variant}; use ritz::{html, Fragment, HtmlContent, HtmlSelfClosingTag}; @@ -22,32 +21,23 @@ use crate::{ }, }; -pub struct UiService { - serve_session: Arc, +pub async fn call(serve_session: Arc, request: Request) -> Response { + let service = UiService::new(serve_session); + + match (request.method(), request.uri().path()) { + (&Method::GET, "/") => service.handle_home(), + (&Method::GET, "/logo.png") => service.handle_logo(), + (&Method::GET, "/icon.png") => service.handle_icon(), + (&Method::GET, "/show-instances") => service.handle_show_instances(), + (_method, path) => json( + ErrorResponse::not_found(format!("Route not found: {}", path)), + StatusCode::NOT_FOUND, + ), + } } -impl Service for UiService { - type ReqBody = Body; - type ResBody = Body; - type Error = hyper::Error; - type Future = Box, Error = Self::Error> + Send>; - - fn call(&mut self, request: Request) -> Self::Future { - let response = match (request.method(), request.uri().path()) { - (&Method::GET, "/") => self.handle_home(), - (&Method::GET, "/logo.png") => self.handle_logo(), - (&Method::GET, "/icon.png") => self.handle_icon(), - (&Method::GET, "/show-instances") => self.handle_show_instances(), - (_method, path) => { - return json( - ErrorResponse::not_found(format!("Route not found: {}", path)), - StatusCode::NOT_FOUND, - ) - } - }; - - Box::new(future::ok(response)) - } +pub struct UiService { + serve_session: Arc, } impl UiService { diff --git a/src/web/util.rs b/src/web/util.rs index 26ddec61..2b6882e5 100644 --- a/src/web/util.rs +++ b/src/web/util.rs @@ -1,23 +1,11 @@ -use futures::{future, Future}; use hyper::{header::CONTENT_TYPE, Body, Response, StatusCode}; use serde::Serialize; -/// Respond to a request with JSON and the given status code. -pub fn json( - value: T, - code: StatusCode, -) -> Box, Error = hyper::Error> + Send> { - Box::new(future::ok(response_json(value, code))) -} - -/// Respond to a request with a 200 OK response containing JSON. -pub fn json_ok( - value: T, -) -> Box, Error = hyper::Error> + Send> { +pub fn json_ok(value: T) -> Response { json(value, StatusCode::OK) } -fn response_json(value: T, code: StatusCode) -> Response { +pub fn json(value: T, code: StatusCode) -> Response { let serialized = match serde_json::to_string(&value) { Ok(v) => v, Err(err) => { From e1f9eaefa940dbcc706803ef8b5e0231bd390b4d Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Thu, 5 Aug 2021 00:03:13 -0700 Subject: [PATCH 1157/1504] Fix Ref reification (#462) * Update ApiValue type to use new value format * Use new value format for Ref reification --- plugin/src/Reconciler/reify.lua | 14 +++++++------- plugin/src/Types.lua | 7 ++----- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/plugin/src/Reconciler/reify.lua b/plugin/src/Reconciler/reify.lua index b0c8aa0b..3c396573 100644 --- a/plugin/src/Reconciler/reify.lua +++ b/plugin/src/Reconciler/reify.lua @@ -70,7 +70,7 @@ function reifyInner(instanceMap, virtualInstances, id, parentInstance, unapplied for propertyName, virtualValue in pairs(virtualInstance.Properties) do -- Because refs may refer to instances that we haven't constructed yet, -- we defer applying any ref properties until all instances are created. - if virtualValue.Type == "Ref" then + if next(virtualValue) == "Ref" then table.insert(deferredRefs, { id = id, instance = instance, @@ -136,23 +136,23 @@ function applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch) end for _, entry in ipairs(deferredRefs) do - local virtualValue = entry.virtualValue + local _, refId = next(entry.virtualValue) - if virtualValue.Value == nil then + if refId == nil then continue end - local targetInstance = instanceMap.fromIds[virtualValue.Value] + local targetInstance = instanceMap.fromIds[refId] if targetInstance == nil then - markFailed(entry.id, entry.propertyName, virtualValue) + markFailed(entry.id, entry.propertyName, entry.virtualValue) continue end local ok = setProperty(entry.instance, entry.propertyName, targetInstance) if not ok then - markFailed(entry.id, entry.propertyName, virtualValue) + markFailed(entry.id, entry.propertyName, entry.virtualValue) end end end -return reify \ No newline at end of file +return reify diff --git a/plugin/src/Types.lua b/plugin/src/Types.lua index dac5f06c..ebd8efe1 100644 --- a/plugin/src/Types.lua +++ b/plugin/src/Types.lua @@ -5,10 +5,7 @@ local strict = require(script.Parent.strict) local RbxId = t.string -local ApiValue = t.interface({ - Type = t.string, - Value = t.optional(t.any), -}) +local ApiValue = t.keys(t.string) local ApiInstanceMetadata = t.interface({ ignoreUnknownInstances = t.optional(t.boolean), @@ -96,4 +93,4 @@ return strict("Types", { VirtualInstance = ApiInstance, VirtualMetadata = ApiInstanceMetadata, VirtualValue = ApiValue, -}) \ No newline at end of file +}) From 6cc2e919c0b597540d314824e88c823355184f61 Mon Sep 17 00:00:00 2001 From: Ayuka Date: Mon, 9 Aug 2021 13:14:59 -0500 Subject: [PATCH 1158/1504] Update nil Ref check and property decode warning to new Rojo protocol (#466) * Skip empty Refs in new Rojo protocol * Update warning message for new Rojo protocol --- plugin/src/Reconciler/decodeValue.lua | 2 +- plugin/src/Reconciler/diff.lua | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/plugin/src/Reconciler/decodeValue.lua b/plugin/src/Reconciler/decodeValue.lua index 321aae92..0fe7bf59 100644 --- a/plugin/src/Reconciler/decodeValue.lua +++ b/plugin/src/Reconciler/decodeValue.lua @@ -11,7 +11,7 @@ local function decodeValue(encodedValue, instanceMap) -- Refs are represented as IDs in the same space that Rojo's protocol uses. if ty == "Ref" then - if value == nil then + if value == "00000000000000000000000000000000" then return true, nil end diff --git a/plugin/src/Reconciler/diff.lua b/plugin/src/Reconciler/diff.lua index d146b308..14e04fb8 100644 --- a/plugin/src/Reconciler/diff.lua +++ b/plugin/src/Reconciler/diff.lua @@ -75,7 +75,9 @@ local function diff(instanceMap, virtualInstances, rootId) changedProperties[propertyName] = virtualValue end else - Log.warn("Failed to decode property of type {}", virtualValue.Type) + -- virtualValue can be empty in certain cases, and this may print out nil to the user. + local propertyType = next(virtualValue) + Log.warn("Failed to decode property of type {}", propertyType) end else local err = existingValueOrErr From f0526d17de6cf757a1a96875c9daaa56592f68eb Mon Sep 17 00:00:00 2001 From: James Onnen Date: Mon, 23 Aug 2021 12:21:01 -0700 Subject: [PATCH 1159/1504] Support long file paths on Windows (past 256 limit) (#464) * Support long file paths on Windows (past 256 limit) This issue can occur when using symlinks deep in rojo such that very long paths can occur, among other scenarios. Note while the original fix comes from here: https://gal.hagever.com/posts/windows-long-paths-in-rust/ The manifest had to be modified from this source: https://stackoverflow.com/questions/59816045/windows-10-1903-longpathaware-not-working * Move manifests, tidy code a little Co-authored-by: Lucien Greathouse --- Cargo.lock | 34 ++++++++++++++++++++++++++++++++++ Cargo.toml | 2 ++ build.rs | 4 ++++ build/windows/rojo-manifest.rc | 2 ++ build/windows/rojo.manifest | 8 ++++++++ 5 files changed, 50 insertions(+) create mode 100644 build/windows/rojo-manifest.rc create mode 100644 build/windows/rojo.manifest diff --git a/Cargo.lock b/Cargo.lock index 5ed75c8a..19036d5c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "addr2line" version = "0.16.0" @@ -552,6 +554,17 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "embed-resource" +version = "1.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45de30eb317b4cd3882ee16623cb3004e5fb99a8f4cd40097cadf61efbc54adc" +dependencies = [ + "cc", + "vswhom", + "winreg 0.9.0", +] + [[package]] name = "encode_unicode" version = "0.3.6" @@ -2228,6 +2241,7 @@ dependencies = [ "criterion", "crossbeam-channel", "csv", + "embed-resource", "env_logger", "fs-err", "futures 0.3.16", @@ -2968,6 +2982,26 @@ version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +[[package]] +name = "vswhom" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be979b7f07507105799e854203b470ff7c78a1639e330a58f183b5fea574608b" +dependencies = [ + "libc", + "vswhom-sys", +] + +[[package]] +name = "vswhom-sys" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc2f5402d3d0e79a069714f7b48e3ecc60be7775a2c049cb839457457a239532" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "walkdir" version = "2.3.2" diff --git a/Cargo.toml b/Cargo.toml index 2efbe847..56db2f75 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ documentation = "https://rojo.space/docs" repository = "https://github.com/rojo-rbx/rojo" readme = "README.md" edition = "2018" +build = "build.rs" exclude = [ "/test-projects/**", @@ -96,6 +97,7 @@ winreg = "0.9.0" [build-dependencies] memofs = { version = "0.1.3", path = "memofs" } +embed-resource = "1.6" anyhow = "1.0.27" bincode = "1.2.1" fs-err = "2.3.0" diff --git a/build.rs b/build.rs index fe2a840a..5ac7672b 100644 --- a/build.rs +++ b/build.rs @@ -73,5 +73,9 @@ fn main() -> Result<(), anyhow::Error> { bincode::serialize_into(out_file, &snapshot)?; + println!("cargo:rerun-if-changed=build/windows/rojo-manifest.rc"); + println!("cargo:rerun-if-changed=build/windows/rojo.manifest"); + embed_resource::compile("build/windows/rojo-manifest.rc"); + Ok(()) } diff --git a/build/windows/rojo-manifest.rc b/build/windows/rojo-manifest.rc new file mode 100644 index 00000000..2e362020 --- /dev/null +++ b/build/windows/rojo-manifest.rc @@ -0,0 +1,2 @@ +#define RT_MANIFEST 24 +1 RT_MANIFEST "rojo.manifest" \ No newline at end of file diff --git a/build/windows/rojo.manifest b/build/windows/rojo.manifest new file mode 100644 index 00000000..62ed2721 --- /dev/null +++ b/build/windows/rojo.manifest @@ -0,0 +1,8 @@ + + + + + true + + + \ No newline at end of file From c7390254536187003f0950c44d3c36658a53b37b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 23 Aug 2021 15:23:19 -0400 Subject: [PATCH 1160/1504] Update changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d5f528cc..8ab94d26 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,9 @@ The shorthand property format that most users use is not impacted. For reference * Added the `fmt-project` subcommand for formatting Rojo project files. * Improved error output for many subcommands. * Updated to stable versions of rbx-dom libraries. +* Fixed long path issues on Windows. ([#464][#464]) + +[#464]: https://github.com/rojo-rbx/rojo/pull/464 ## [7.0.0-alpha.4][7.0.0-alpha.4] (May 5, 2021) * Added the `gameId` and `placeId` optional properties to project files. From 16aa354d3695bc8fff9941e92a890e61109c1075 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 23 Aug 2021 15:45:04 -0400 Subject: [PATCH 1161/1504] Update dependencies and fix Lua ref tests --- Cargo.lock | 173 ++- plugin/rbx_dom_lua/database.json | 2112 +++++++++++++++++++++++--- plugin/rbx_dom_lua/init.lua | 4 +- plugin/src/Reconciler/reify.spec.lua | 12 +- 4 files changed, 2027 insertions(+), 274 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 19036d5c..9993a34e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,9 +46,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.42" +version = "1.0.43" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486" +checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf" [[package]] name = "arrayref" @@ -126,9 +126,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "1.2.1" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "blake3" @@ -384,9 +384,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f02af974daeee82218205558e51ec8768b48cf524bd01d550abe5573a608285" +checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed" dependencies = [ "crossbeam-epoch 0.8.2", "crossbeam-utils 0.7.2", @@ -395,9 +395,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.0" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9" +checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch 0.9.5", @@ -623,13 +623,13 @@ checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] name = "filetime" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d34cfa13a63ae058bfa601fe9e313bbdb3746427c1459185464ce0fcf62e1e8" +checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.2.9", + "redox_syscall 0.2.10", "winapi 0.3.9", ] @@ -973,9 +973,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60daa14be0e0786db0f03a9e57cb404c9d756eed2b6c62b9ea98ec5743ec75a9" +checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5" dependencies = [ "bytes 1.0.1", "http 0.2.4", @@ -984,9 +984,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.4.1" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3a87b616e37e93c22fb19bcd386f02f3af5ea98a25670ad0fce773de23c5e68" +checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" [[package]] name = "httpdate" @@ -1041,13 +1041,13 @@ dependencies = [ "futures-core", "futures-util", "http 0.2.4", - "http-body 0.4.2", + "http-body 0.4.3", "httparse", "httpdate", "itoa", "pin-project-lite", "socket2", - "tokio 1.9.0", + "tokio 1.10.0", "tower-service", "tracing", "want 0.3.0", @@ -1120,9 +1120,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1b21a2971cea49ca4613c0e9fe8225ecaf5de64090fddc6002284726e9244" +checksum = "58019516c1403ac45b106c9fc4e8fcbd77a78e98b014c619d1506338902ccfa4" dependencies = [ "console", "lazy_static", @@ -1155,9 +1155,9 @@ dependencies = [ [[package]] name = "itoa" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" [[package]] name = "jod-thread" @@ -1167,9 +1167,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] name = "js-sys" -version = "0.3.51" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bdfbace3a0e81a4253f73b49e960b053e396a11012cbd49b9b74d6a2b67062" +checksum = "e4bf49d50e2961077d9c99f4b7997d770a1114f087c3c2e0069b36c13fc2979d" dependencies = [ "wasm-bindgen", ] @@ -1198,9 +1198,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.98" +version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790" +checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5" [[package]] name = "linked-hash-map" @@ -1254,9 +1254,9 @@ checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" [[package]] name = "matches" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08" +checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" [[package]] name = "maybe-uninit" @@ -1266,9 +1266,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16bd47d9e329435e309c58469fe0791c2d0d1ba96ec0954152a5ae2b04387dc" +checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" [[package]] name = "memoffset" @@ -1391,9 +1391,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8d96b2e1c8da3957d58100b09f102c6d9cfdfced01b7ec5a8974044bb09dbd4" +checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" dependencies = [ "lazy_static", "libc", @@ -1466,9 +1466,9 @@ dependencies = [ [[package]] name = "object" -version = "0.26.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c55827317fb4c08822499848a14237d2874d6f139828893017237e7ab93eb386" +checksum = "ee2766204889d09937d00bfbb7fec56bb2a199e2ade963cab19185d8a6104c7c" dependencies = [ "memchr", ] @@ -1503,9 +1503,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.35" +version = "0.10.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "549430950c79ae24e6d02e0b7404534ecf311d94cc9f861e9e4020187d13d885" +checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -1523,9 +1523,9 @@ checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" [[package]] name = "openssl-sys" -version = "0.9.65" +version = "0.9.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a7907e3bfa08bb85105209cdfcb6c63d109f8f6c1ed6ca318fff5c1853fbc1d" +checksum = "1996d2d305e561b70d1ee0c53f1542833f4e1ac6ce9a6708b6ff2738ca67dc82" dependencies = [ "autocfg 1.0.1", "cc", @@ -1970,7 +1970,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" dependencies = [ "autocfg 1.0.1", - "crossbeam-deque 0.8.0", + "crossbeam-deque 0.8.1", "either", "rayon-core", ] @@ -1982,7 +1982,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" dependencies = [ "crossbeam-channel", - "crossbeam-deque 0.8.0", + "crossbeam-deque 0.8.1", "crossbeam-utils 0.8.5", "lazy_static", "num_cpus", @@ -2079,9 +2079,9 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab49abadf3f9e1c4bc499e8845e152ad87d2ad2d30371841171169e9d75feee" +checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" dependencies = [ "bitflags", ] @@ -2093,7 +2093,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" dependencies = [ "getrandom 0.2.3", - "redox_syscall 0.2.9", + "redox_syscall 0.2.10", ] [[package]] @@ -2276,7 +2276,7 @@ dependencies = [ "tempfile", "termcolor", "thiserror", - "tokio 1.9.0", + "tokio 1.10.0", "uuid 0.8.2", "walkdir", "winreg 0.9.0", @@ -2311,7 +2311,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.3", + "semver 1.0.4", ] [[package]] @@ -2379,9 +2379,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f3aac57ee7f3272d8395c6e4f502f434f0e289fcd62876f70daa008c20dcabe" +checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" [[package]] name = "semver-parser" @@ -2391,18 +2391,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.126" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03" +checksum = "1056a0db1978e9dbf0f6e4fca677f6f9143dc1c19de346f22cac23e422196834" dependencies = [ "serde_derive", ] [[package]] name = "serde_cbor" -version = "0.11.1" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e18acfa2f90e8b735b2836ab8d538de304cbb6729a7360729ea5a895d15a622" +checksum = "2bef2ebfde456fb76bbcf9f59315333decc4fda0b2b44b420243c11e0f5ec1f5" dependencies = [ "half", "serde", @@ -2410,9 +2410,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.126" +version = "1.0.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43" +checksum = "13af2fbb8b60a8950d6c72a56d2095c28870367cc8e10c55e9745bac4995a2c4" dependencies = [ "proc-macro2 1.0.28", "quote 1.0.9", @@ -2421,9 +2421,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.64" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79" +checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127" dependencies = [ "itoa", "ryu", @@ -2444,12 +2444,12 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.8.17" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15654ed4ab61726bf918a39cb8d98a2e2995b002387807fa6ba58fdf7f59bb23" +checksum = "6375dbd828ed6964c3748e4ef6d18e7a175d408ffe184bca01698d0c73f915a9" dependencies = [ "dtoa", - "linked-hash-map", + "indexmap", "serde", "yaml-rust", ] @@ -2474,9 +2474,9 @@ checksum = "1ad1d488a557b235fc46dae55512ffbfc429d2482b08b4d9435ab07384ca8aec" [[package]] name = "slab" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527" +checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" [[package]] name = "smallvec" @@ -2498,9 +2498,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e3dfc207c526015c632472a77be09cf1b6e46866581aecae5cc38fb4235dea2" +checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad" dependencies = [ "libc", "winapi 0.3.9", @@ -2553,9 +2553,9 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "syn" -version = "1.0.74" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c" +checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7" dependencies = [ "proc-macro2 1.0.28", "quote 1.0.9", @@ -2583,7 +2583,7 @@ dependencies = [ "cfg-if 1.0.0", "libc", "rand 0.8.4", - "redox_syscall 0.2.9", + "redox_syscall 0.2.10", "remove_dir_all", "winapi 0.3.9", ] @@ -2692,9 +2692,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b7b349f11a7047e6d1276853e612d152f5e8a352c61917887cc2169e2366b4c" +checksum = "01cf844b23c6131f624accf65ce0e4e9956a8bb329400ea5bcc26ae3a5c20b0b" dependencies = [ "autocfg 1.0.1", "libc", @@ -2795,7 +2795,7 @@ version = "0.1.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" dependencies = [ - "crossbeam-deque 0.7.3", + "crossbeam-deque 0.7.4", "crossbeam-queue", "crossbeam-utils 0.7.2", "futures 0.1.31", @@ -2837,9 +2837,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.18" +version = "0.1.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9ff14f98b1a4b289c6248a023c1c2fa1491062964e9fed67ab29c4e4da4a052" +checksum = "2ca517f43f0fb96e0c3072ed5c275fe5eece87e8cb52f4a77b69226d3b1c9df8" dependencies = [ "lazy_static", ] @@ -2882,12 +2882,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeb8be209bb1c96b7c177c7420d26e04eccacb0eeae6b980e35fcb74678107e0" -dependencies = [ - "matches", -] +checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085" [[package]] name = "unicode-normalization" @@ -3048,9 +3045,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.74" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54ee1d4ed486f78874278e63e4069fc1ab9f6a18ca492076ffb90c5eb2997fd" +checksum = "8ce9b1b516211d33767048e5d47fa2a381ed8b76fc48d2ce4aa39877f9f183e0" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -3058,9 +3055,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.74" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b33f6a0694ccfea53d94db8b2ed1c3a8a4c86dd936b13b9f0a15ec4a451b900" +checksum = "cfe8dc78e2326ba5f845f4b5bf548401604fa20b1dd1d365fb73b6c1d6364041" dependencies = [ "bumpalo", "lazy_static", @@ -3073,9 +3070,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.74" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "088169ca61430fe1e58b8096c24975251700e7b1f6fd91cc9d59b04fb9b18bd4" +checksum = "44468aa53335841d9d6b6c023eaab07c0cd4bddbcfdee3e2bb1e8d2cb8069fef" dependencies = [ "quote 1.0.9", "wasm-bindgen-macro-support", @@ -3083,9 +3080,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.74" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be2241542ff3d9f241f5e2cb6dd09b37efe786df8851c54957683a49f0987a97" +checksum = "0195807922713af1e67dc66132c7328206ed9766af3858164fb583eedc25fbad" dependencies = [ "proc-macro2 1.0.28", "quote 1.0.9", @@ -3096,15 +3093,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.74" +version = "0.2.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7cff876b8f18eed75a66cf49b65e7f967cb354a7aa16003fb55dbfd25b44b4f" +checksum = "acdb075a845574a1fa5f09fd77e43f7747599301ea3417a9fbffdeedfc1f4a29" [[package]] name = "web-sys" -version = "0.3.51" +version = "0.3.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e828417b379f3df7111d3a2a9e5753706cae29c41f7c4029ee9fd77f3e09e582" +checksum = "224b2f6b67919060055ef1a67807367c2066ed520c3862cc013d26cf893a783c" dependencies = [ "js-sys", "wasm-bindgen", @@ -3183,9 +3180,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b07db065a5cf61a7e4ba64f29e67db906fb1787316516c4e6e5ff0fea1efcd8a" +checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" [[package]] name = "yaml-rust" diff --git a/plugin/rbx_dom_lua/database.json b/plugin/rbx_dom_lua/database.json index d9e263d7..a6ee7adc 100644 --- a/plugin/rbx_dom_lua/database.json +++ b/plugin/rbx_dom_lua/database.json @@ -1,9 +1,9 @@ { "Version": [ 0, - 484, + 489, 0, - 425477 + 4890336 ], "Classes": { "ABTestService": { @@ -21,8 +21,25 @@ "Name": "Accessory", "Tags": [], "Superclass": "Accoutrement", - "Properties": {}, + "Properties": { + "AccessoryType": { + "Name": "AccessoryType", + "Scriptability": "Read", + "DataType": { + "Enum": "AccessoryType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { + "AccessoryType": { + "Enum": 0 + }, "AttachmentPoint": { "CFrame": { "position": [ @@ -928,6 +945,40 @@ "Properties": {}, "DefaultProperties": {} }, + "AssetImportItemSettings": { + "Name": "AssetImportItemSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "ShouldImport": { + "Name": "ShouldImport", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "AssetImportMeshSettings": { + "Name": "AssetImportMeshSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "AssetImportItemSettings", + "Properties": {}, + "DefaultProperties": {} + }, "AssetImportService": { "Name": "AssetImportService", "Tags": [ @@ -939,6 +990,43 @@ "Properties": {}, "DefaultProperties": {} }, + "AssetImportSettings": { + "Name": "AssetImportSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Hierarchy": { + "Name": "Hierarchy", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "AssetImportTextureSettings": { + "Name": "AssetImportTextureSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "AssetImportItemSettings", + "Properties": {}, + "DefaultProperties": {} + }, "AssetManagerService": { "Name": "AssetManagerService", "Tags": [ @@ -4391,6 +4479,23 @@ "Tags": [], "Superclass": "Attachment", "Properties": { + "IsCFrameDriven": { + "Name": "IsCFrameDriven", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Transform": { "Name": "Transform", "Scriptability": "ReadWrite", @@ -4607,6 +4712,102 @@ } } }, + "Breakpoint": { + "Name": "Breakpoint", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Condition": { + "Name": "Condition", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Line": { + "Name": "Line", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Script": { + "Name": "Script", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Valid": { + "Name": "Valid", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "BrickColorValue": { "Name": "BrickColorValue", "Tags": [], @@ -5372,6 +5573,19 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Cover": { "Name": "Cover", "Scriptability": "ReadWrite", @@ -5397,18 +5611,41 @@ "Serialization": "Serializes" } } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { "AttributesSerialize": { "BinaryString": "" }, + "Color": { + "Color3": [ + 1.0, + 1.0, + 1.0 + ] + }, "Cover": { "Float32": 0.5 }, "Density": { "Float32": 0.7 }, + "Enabled": { + "Bool": true + }, "SourceAssetId": { "Int64": -1 }, @@ -5691,6 +5928,22 @@ } } }, + "Permission": { + "Name": "Permission", + "Scriptability": "None", + "DataType": { + "Enum": "CommandPermission" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "StatusTip": { "Name": "StatusTip", "Scriptability": "None", @@ -7380,16 +7633,6 @@ "Properties": {}, "DefaultProperties": {} }, - "DataStoreEnumerationPages": { - "Name": "DataStoreEnumerationPages", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "Pages", - "Properties": {}, - "DefaultProperties": {} - }, "DataStoreIncrementOptions": { "Name": "DataStoreIncrementOptions", "Tags": [ @@ -7458,8 +7701,8 @@ }, "DefaultProperties": {} }, - "DataStoreKeyInfo": { - "Name": "DataStoreKeyInfo", + "DataStoreKey": { + "Name": "DataStoreKey", "Tags": [ "NotCreatable", "NotReplicated" @@ -7485,18 +7728,8 @@ }, "DefaultProperties": {} }, - "DataStoreKeyPages": { - "Name": "DataStoreKeyPages", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "Pages", - "Properties": {}, - "DefaultProperties": {} - }, - "DataStoreKeyVersionInfo": { - "Name": "DataStoreKeyVersionInfo", + "DataStoreKeyInfo": { + "Name": "DataStoreKeyInfo", "Tags": [ "NotCreatable", "NotReplicated" @@ -7554,6 +7787,108 @@ }, "DefaultProperties": {} }, + "DataStoreKeyPages": { + "Name": "DataStoreKeyPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, + "DataStoreListingPages": { + "Name": "DataStoreListingPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, + "DataStoreObjectVersionInfo": { + "Name": "DataStoreObjectVersionInfo", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "CreatedTime": { + "Name": "CreatedTime", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsDeleted": { + "Name": "IsDeleted", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Version": { + "Name": "Version", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "DataStoreOptions": { + "Name": "DataStoreOptions", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "AllScopes": { + "Name": "AllScopes", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "DataStorePages": { "Name": "DataStorePages", "Tags": [ @@ -7832,6 +8167,19 @@ } } }, + "ContinueExecution": { + "Name": "ContinueExecution", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "IsEnabled": { "Name": "IsEnabled", "Scriptability": "ReadWrite", @@ -7861,6 +8209,19 @@ } } }, + "LogExpression": { + "Name": "LogExpression", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "isContextDependentBreakpoint": { "Name": "isContextDependentBreakpoint", "Scriptability": "ReadWrite", @@ -7877,6 +8238,79 @@ }, "DefaultProperties": {} }, + "DebuggerConnection": { + "Name": "DebuggerConnection", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Id": { + "Name": "Id", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPaused": { + "Name": "IsPaused", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "DebuggerConnectionManager": { + "Name": "DebuggerConnectionManager", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "Timeout": { + "Name": "Timeout", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "DebuggerManager": { "Name": "DebuggerManager", "Tags": [ @@ -9165,6 +9599,865 @@ } } }, + "Expression": { + "Name": "Expression", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Expression": { + "Name": "Expression", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "Expression": { + "String": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, + "FaceControls": { + "Name": "FaceControls", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "ChinRaiser": { + "Name": "ChinRaiser", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ChinRaiserUpperLip": { + "Name": "ChinRaiserUpperLip", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Corrugator": { + "Name": "Corrugator", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EyesLookDown": { + "Name": "EyesLookDown", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EyesLookLeft": { + "Name": "EyesLookLeft", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EyesLookRight": { + "Name": "EyesLookRight", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EyesLookUp": { + "Name": "EyesLookUp", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FlatPucker": { + "Name": "FlatPucker", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Funneler": { + "Name": "Funneler", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "JawDrop": { + "Name": "JawDrop", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "JawLeft": { + "Name": "JawLeft", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "JawRight": { + "Name": "JawRight", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftBrowLowerer": { + "Name": "LeftBrowLowerer", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftCheekPuff": { + "Name": "LeftCheekPuff", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftCheekRaiser": { + "Name": "LeftCheekRaiser", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftDimpler": { + "Name": "LeftDimpler", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftEyeClosed": { + "Name": "LeftEyeClosed", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftEyeUpperLidRaiser": { + "Name": "LeftEyeUpperLidRaiser", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftInnerBrowRaiser": { + "Name": "LeftInnerBrowRaiser", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftLipCornerDown": { + "Name": "LeftLipCornerDown", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftLipCornerPuller": { + "Name": "LeftLipCornerPuller", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftLipStretcher": { + "Name": "LeftLipStretcher", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftLowerLipDepressor": { + "Name": "LeftLowerLipDepressor", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftNoseWrinkler": { + "Name": "LeftNoseWrinkler", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftOuterBrowRaiser": { + "Name": "LeftOuterBrowRaiser", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeftUpperLipRaiser": { + "Name": "LeftUpperLipRaiser", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LipPresser": { + "Name": "LipPresser", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LipsTogether": { + "Name": "LipsTogether", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LowerLipSuck": { + "Name": "LowerLipSuck", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouthLeft": { + "Name": "MouthLeft", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouthRight": { + "Name": "MouthRight", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Pucker": { + "Name": "Pucker", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightBrowLowerer": { + "Name": "RightBrowLowerer", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightCheekPuff": { + "Name": "RightCheekPuff", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightCheekRaiser": { + "Name": "RightCheekRaiser", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightDimpler": { + "Name": "RightDimpler", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightEyeClosed": { + "Name": "RightEyeClosed", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightEyeUpperLidRaiser": { + "Name": "RightEyeUpperLidRaiser", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightInnerBrowRaiser": { + "Name": "RightInnerBrowRaiser", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightLipCornerDown": { + "Name": "RightLipCornerDown", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightLipCornerPuller": { + "Name": "RightLipCornerPuller", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightLipStretcher": { + "Name": "RightLipStretcher", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightLowerLipDepressor": { + "Name": "RightLowerLipDepressor", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightNoseWrinkler": { + "Name": "RightNoseWrinkler", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightOuterBrowRaiser": { + "Name": "RightOuterBrowRaiser", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RightUpperLipRaiser": { + "Name": "RightUpperLipRaiser", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TongueDown": { + "Name": "TongueDown", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TongueOut": { + "Name": "TongueOut", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TongueUp": { + "Name": "TongueUp", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UpperLipSuck": { + "Name": "UpperLipSuck", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "FaceInstance": { "Name": "FaceInstance", "Tags": [ @@ -10541,29 +11834,6 @@ } } }, - "GetDataStoreOptions": { - "Name": "GetDataStoreOptions", - "Tags": [ - "NotReplicated" - ], - "Superclass": "Instance", - "Properties": { - "AllScopes": { - "Name": "AllScopes", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": {} - }, "GlobalDataStore": { "Name": "GlobalDataStore", "Tags": [ @@ -15483,6 +16753,22 @@ } } }, + "TempUseNewSkyRemovalBehaviour": { + "Name": "TempUseNewSkyRemovalBehaviour", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "TimeOfDay": { "Name": "TimeOfDay", "Scriptability": "ReadWrite", @@ -18155,65 +19441,6 @@ } } }, - "ObjectVersionInfo": { - "Name": "ObjectVersionInfo", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "Instance", - "Properties": { - "CreatedTime": { - "Name": "CreatedTime", - "Scriptability": "Read", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "IsDeleted": { - "Name": "IsDeleted", - "Scriptability": "Read", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Version": { - "Name": "Version", - "Scriptability": "Read", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": {} - }, "OrderedDataStore": { "Name": "OrderedDataStore", "Tags": [ @@ -19691,6 +20918,40 @@ }, "DefaultProperties": {} }, + "PathfindingModifier": { + "Name": "PathfindingModifier", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "ModifierId": { + "Name": "ModifierId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "ModifierId": { + "String": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "PathfindingService": { "Name": "PathfindingService", "Tags": [ @@ -19719,6 +20980,158 @@ }, "DefaultProperties": {} }, + "PausedState": { + "Name": "PausedState", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "IsValid": { + "Name": "IsValid", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Reason": { + "Name": "Reason", + "Scriptability": "None", + "DataType": { + "Enum": "DebuggerPauseReason" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ThreadCount": { + "Name": "ThreadCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "PausedStateBreakpoint": { + "Name": "PausedStateBreakpoint", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "PausedState", + "Properties": { + "Breakpoint": { + "Name": "Breakpoint", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "BreakpointThread": { + "Name": "BreakpointThread", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "PausedStateException": { + "Name": "PausedStateException", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "PausedState", + "Properties": { + "ExceptionText": { + "Name": "ExceptionText", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ExceptionThread": { + "Name": "ExceptionThread", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "PermissionsService": { "Name": "PermissionsService", "Tags": [ @@ -22525,6 +23938,9 @@ "EditingDisabled": { "Bool": false }, + "EditorType": { + "String": "" + }, "ExplorerImageIndex": { "Int32": 0 }, @@ -22566,9 +23982,6 @@ }, "UINumTicks": { "Float64": 0.0 - }, - "summary": { - "String": "" } } }, @@ -22616,6 +24029,9 @@ "EditingDisabled": { "Bool": false }, + "EditorType": { + "String": "" + }, "FFlag": { "String": "" }, @@ -22645,9 +24061,6 @@ }, "UINumTicks": { "Float64": 0.0 - }, - "summary": { - "String": "" } } }, @@ -22678,6 +24091,9 @@ "EditingDisabled": { "Bool": false }, + "EditorType": { + "String": "" + }, "FFlag": { "String": "" }, @@ -22707,9 +24123,6 @@ }, "UINumTicks": { "Float64": 0.0 - }, - "summary": { - "String": "" } } }, @@ -22849,6 +24262,19 @@ } } }, + "EditorType": { + "Name": "EditorType", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "FFlag": { "Name": "FFlag", "Scriptability": "ReadWrite", @@ -22952,19 +24378,6 @@ "Serialization": "Serializes" } } - }, - "summary": { - "Name": "summary", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "String" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } } }, "DefaultProperties": {} @@ -22996,6 +24409,9 @@ "EditingDisabled": { "Bool": false }, + "EditorType": { + "String": "" + }, "FFlag": { "String": "" }, @@ -23025,9 +24441,6 @@ }, "UINumTicks": { "Float64": 0.0 - }, - "summary": { - "String": "" } } }, @@ -23065,6 +24478,17 @@ } } }, + "RemoteDebuggerServer": { + "Name": "RemoteDebuggerServer", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "RemoteEvent": { "Name": "RemoteEvent", "Tags": [], @@ -24065,6 +25489,71 @@ "Serialization": "Serializes" } } + }, + "WinchEnabled": { + "Name": "WinchEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WinchForce": { + "Name": "WinchForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WinchResponsiveness": { + "Name": "WinchResponsiveness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WinchSpeed": { + "Name": "WinchSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WinchTarget": { + "Name": "WinchTarget", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -24094,6 +25583,21 @@ }, "Visible": { "Bool": false + }, + "WinchEnabled": { + "Bool": false + }, + "WinchForce": { + "Float32": 10000.0 + }, + "WinchResponsiveness": { + "Float32": 45.0 + }, + "WinchSpeed": { + "Float32": 2.0 + }, + "WinchTarget": { + "Float32": 5.0 } } }, @@ -24603,6 +26107,36 @@ }, "DefaultProperties": {} }, + "ScriptRef": { + "Name": "ScriptRef", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "ScriptRefId": { + "Name": "ScriptRefId", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "ScriptRef", + "Properties": {}, + "DefaultProperties": {} + }, + "ScriptRefPath": { + "Name": "ScriptRefPath", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "ScriptRef", + "Properties": {}, + "DefaultProperties": {} + }, "ScriptService": { "Name": "ScriptService", "Tags": [ @@ -25338,6 +26872,22 @@ "Serialization": "DoesNotSerialize" } } + }, + "SelectionThickness": { + "Name": "SelectionThickness", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -29912,6 +31462,19 @@ } } }, + "DEPRECATED_DisableAccuratePlaySolo": { + "Name": "DEPRECATED_DisableAccuratePlaySolo", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Debugger Current Line Color": { "Name": "Debugger Current Line Color", "Scriptability": "ReadWrite", @@ -29955,19 +31518,6 @@ } } }, - "Disable Accurate Play Solo": { - "Name": "Disable Accurate Play Solo", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "DisplayLanguage": { "Name": "DisplayLanguage", "Scriptability": "None", @@ -30059,8 +31609,8 @@ } } }, - "Enable Linting": { - "Name": "Enable Linting", + "Enable Script Analysis": { + "Name": "Enable Script Analysis", "Scriptability": "None", "DataType": { "Value": "Bool" @@ -30665,6 +32215,22 @@ } } }, + "ScriptEditorMenuBorderColor": { + "Name": "ScriptEditorMenuBorderColor", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ScriptEditorShouldShowPluginMethods": { "Name": "ScriptEditorShouldShowPluginMethods", "Scriptability": "None", @@ -30821,6 +32387,19 @@ } } }, + "Selection Highlight Thickness": { + "Name": "Selection Highlight Thickness", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Server Audio Behavior": { "Name": "Server Audio Behavior", "Scriptability": "ReadWrite", @@ -30912,6 +32491,32 @@ } } }, + "Show Light Guides": { + "Name": "Show Light Guides", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show Navigation Areas": { + "Name": "Show Navigation Areas", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Show Navigation Mesh": { "Name": "Show Navigation Mesh", "Scriptability": "ReadWrite", @@ -34624,6 +36229,34 @@ "Properties": {}, "DefaultProperties": {} }, + "ThreadState": { + "Name": "ThreadState", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "ThreadId": { + "Name": "ThreadId", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "TimerService": { "Name": "TimerService", "Tags": [ @@ -34971,6 +36604,22 @@ "DataType": { "Value": "Bool" }, + "Tags": [ + "Deprecated", + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LimitsEnabled": { + "Name": "LimitsEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, "Tags": [], "Kind": { "Canonical": { @@ -35063,6 +36712,9 @@ "LimitEnabled": { "Bool": false }, + "LimitsEnabled": { + "Bool": false + }, "MaxAngle": { "Float32": 45.0 }, @@ -39944,6 +41596,19 @@ } } }, + "Part0Internal": { + "Name": "Part0Internal", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "Part0" + } + } + }, "Part1": { "Name": "Part1", "Scriptability": "ReadWrite", @@ -39958,6 +41623,19 @@ "Serialization": "DoesNotSerialize" } } + }, + "Part1Internal": { + "Name": "Part1Internal", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Alias": { + "AliasFor": "Part1" + } + } } }, "DefaultProperties": { @@ -40122,6 +41800,21 @@ } } }, + "HumanoidOnlySetCollisionsOnStateChange": { + "Name": "HumanoidOnlySetCollisionsOnStateChange", + "Scriptability": "None", + "DataType": { + "Enum": "HumanoidOnlySetCollisionsOnStateChange" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "InterpolationThrottling": { "Name": "InterpolationThrottling", "Scriptability": "ReadWrite", @@ -40314,6 +42007,9 @@ "Gravity": { "Float32": 196.2 }, + "HumanoidOnlySetCollisionsOnStateChange": { + "Enum": 0 + }, "InterpolationThrottling": { "Enum": 0 }, @@ -40784,23 +42480,24 @@ "AccessoryType": { "name": "AccessoryType", "items": { - "Back": 6, - "DressSkirt": 16, - "Face": 2, - "Front": 5, - "Hair": 1, - "Hat": 0, - "Jacket": 11, - "LeftShoe": 14, - "Neck": 3, - "Pants": 10, - "RightShoe": 15, - "Shirt": 9, - "Shorts": 13, - "Shoulder": 4, - "Sweater": 12, - "TeeShirt": 8, - "Waist": 7 + "Back": 7, + "DressSkirt": 17, + "Face": 3, + "Front": 6, + "Hair": 2, + "Hat": 1, + "Jacket": 12, + "LeftShoe": 15, + "Neck": 4, + "Pants": 11, + "RightShoe": 16, + "Shirt": 10, + "Shorts": 14, + "Shoulder": 5, + "Sweater": 13, + "TShirt": 9, + "Unknown": 0, + "Waist": 8 } }, "ActionType": { @@ -40998,8 +42695,8 @@ "ShoulderAccessory": 44, "SweaterAccessory": 68, "SwimAnimation": 54, - "TeeShirt": 2, - "TeeShirtAccessory": 64, + "TShirt": 2, + "TShirtAccessory": 64, "Torso": 27, "Video": 62, "WaistAccessory": 47, @@ -41066,7 +42763,7 @@ "SweaterAccessory": 68, "SwimAnimation": 54, "TShirt": 2, - "TeeShirtAccessory": 64, + "TShirtAccessory": 64, "Torso": 27, "WaistAccessory": 47, "WalkAnimation": 55 @@ -41088,13 +42785,6 @@ "Bundle": 2 } }, - "AvatarJointPositionType": { - "name": "AvatarJointPositionType", - "items": { - "ArtistIntent": 1, - "Fixed": 0 - } - }, "AvatarPromptResult": { "name": "AvatarPromptResult", "items": { @@ -41171,6 +42861,14 @@ "UserBreakpoint": 3 } }, + "BreakpointRemoveReason": { + "name": "BreakpointRemoveReason", + "items": { + "Requested": 0, + "ScriptChanged": 1, + "ScriptRemoved": 2 + } + }, "BulkMoveMode": { "name": "BulkMoveMode", "items": { @@ -41367,6 +43065,13 @@ "PreciseConvexDecomposition": 3 } }, + "CommandPermission": { + "name": "CommandPermission", + "items": { + "LocalUser": 1, + "Plugin": 0 + } + }, "ComputerCameraMovementMode": { "name": "ComputerCameraMovementMode", "items": { @@ -41391,6 +43096,7 @@ "DisconnectBadhash": 257, "DisconnectBlockedIP": 282, "DisconnectBySecurityPolicy": 281, + "DisconnectClientFailure": 284, "DisconnectCloudEditKick": 270, "DisconnectConnectionLost": 277, "DisconnectDevMaintenance": 274, @@ -41524,6 +43230,50 @@ "UpdateAsync": 2 } }, + "DebuggerEndReason": { + "name": "DebuggerEndReason", + "items": { + "ClientRequest": 0, + "ConfigurationFailed": 6, + "Disconnected": 3, + "InvalidHost": 2, + "RpcError": 7, + "ServerProtocolMismatch": 5, + "ServerShutdown": 4, + "Timeout": 1 + } + }, + "DebuggerFrameType": { + "name": "DebuggerFrameType", + "items": { + "C": 0, + "Lua": 1 + } + }, + "DebuggerPauseReason": { + "name": "DebuggerPauseReason", + "items": { + "Breakpoint": 2, + "Entrypoint": 5, + "Exception": 3, + "Requested": 1, + "SingleStep": 4, + "Unknown": 0 + } + }, + "DebuggerStatus": { + "name": "DebuggerStatus", + "items": { + "ConnectionLost": 2, + "InternalError": 4, + "InvalidArgument": 7, + "InvalidResponse": 3, + "InvalidState": 5, + "RpcError": 6, + "Success": 0, + "Timeout": 1 + } + }, "DevCameraOcclusionMode": { "name": "DevCameraOcclusionMode", "items": { @@ -42018,6 +43768,14 @@ "DisplayWhenDamaged": 0 } }, + "HumanoidOnlySetCollisionsOnStateChange": { + "name": "HumanoidOnlySetCollisionsOnStateChange", + "items": { + "Default": 0, + "Disabled": 1, + "Enabled": 2 + } + }, "HumanoidRigType": { "name": "HumanoidRigType", "items": { @@ -43181,6 +44939,7 @@ "LuauKeyword": 14, "MatchingWordBackground": 21, "MenuBackground": 33, + "MenuBorder": 37, "MenuPrimaryText": 30, "MenuScrollbarBackground": 35, "MenuScrollbarHandle": 36, @@ -43765,6 +45524,7 @@ "BoundCageAndLinks": 3, "LayerCage": 2, "None": 0, + "OuterCage": 6, "Rbf": 5, "Reference": 4 } diff --git a/plugin/rbx_dom_lua/init.lua b/plugin/rbx_dom_lua/init.lua index a9386d4d..4230a0a1 100644 --- a/plugin/rbx_dom_lua/init.lua +++ b/plugin/rbx_dom_lua/init.lua @@ -22,7 +22,7 @@ local function findCanonicalPropertyDescriptor(className, propertyName) local aliasData = propertyData.Kind.Alias if aliasData ~= nil then return PropertyDescriptor.fromRaw( - currentClass.properties[aliasData.AliasFor], + currentClass.Properties[aliasData.AliasFor], currentClassName, aliasData.AliasFor) end @@ -66,4 +66,4 @@ return { findCanonicalPropertyDescriptor = findCanonicalPropertyDescriptor, Error = Error, EncodedValue = require(script.EncodedValue), -} \ No newline at end of file +} diff --git a/plugin/src/Reconciler/reify.spec.lua b/plugin/src/Reconciler/reify.spec.lua index 9097da5d..607811d6 100644 --- a/plugin/src/Reconciler/reify.spec.lua +++ b/plugin/src/Reconciler/reify.spec.lua @@ -190,8 +190,7 @@ return function() Name = "Child", Properties = { Value = { - Type = "Ref", - Value = "ROOT", + Ref = "ROOT", }, }, Children = {}, @@ -218,8 +217,7 @@ return function() Name = "Root", Properties = { Value = { - Type = "Ref", - Value = "EXISTING", + Ref = "EXISTING", }, }, Children = {}, @@ -257,8 +255,7 @@ return function() Name = "Child A", Properties = { Value = { - Type = "Ref", - Value = "Child B", + Ref = "Child B", }, }, Children = {}, @@ -297,8 +294,7 @@ return function() Name = "Root", Properties = { Value = { - Type = "Ref", - Value = "CHILD", + Ref = "CHILD", }, }, Children = {"CHILD"}, From 43715143e4e02b56f9d77a77ee75fa31c54367eb Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 23 Aug 2021 15:50:28 -0400 Subject: [PATCH 1162/1504] Release v7.0.0-rc.1 --- CHANGELOG.md | 12 ++++++++++-- Cargo.lock | 2 +- Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ab94d26..e63577ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes + +## [7.0.0-rc.1][7.0.0-rc.1] (August 23, 2021) In Rojo 6 and previous Rojo 7 alphas, an explicit Vector3 property would be written like this: ```json @@ -39,13 +41,19 @@ The shorthand property format that most users use is not impacted. For reference } ``` -* Major breaking change: changed explicit property syntax; shorthand syntax is unchanged. +* Major breaking change: changed property syntax for project files; shorthand syntax is unchanged. * Added the `fmt-project` subcommand for formatting Rojo project files. * Improved error output for many subcommands. * Updated to stable versions of rbx-dom libraries. -* Fixed long path issues on Windows. ([#464][#464]) +* Updated async infrastructure, which should fix a handful of bugs. ([#459][#459]) +* Fixed syncing refs in the Roblox Studio plugin ([#462][#462], [#466][#466]) +* Added support for long paths on Windows. ([#464][#464]) +[#459]: https://github.com/rojo-rbx/rojo/pull/459 +[#462]: https://github.com/rojo-rbx/rojo/pull/462 [#464]: https://github.com/rojo-rbx/rojo/pull/464 +[#466]: https://github.com/rojo-rbx/rojo/pull/466 +[7.0.0-rc.1]: https://github.com/rojo-rbx/rojo/releases/tag/v7.0.0-rc.1 ## [7.0.0-alpha.4][7.0.0-alpha.4] (May 5, 2021) * Added the `gameId` and `placeId` optional properties to project files. diff --git a/Cargo.lock b/Cargo.lock index 9993a34e..9050fe95 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2233,7 +2233,7 @@ dependencies = [ [[package]] name = "rojo" -version = "7.0.0-alpha.4" +version = "7.0.0-rc.1" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 56db2f75..c552f8b7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "7.0.0-alpha.4" +version = "7.0.0-rc.1" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 4f9649b4..1e613426 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {7, 0, 0, "-alpha.4"}, + version = {7, 0, 0, "-rc.1"}, expectedServerVersionString = "7.0 or newer", protocolVersion = 4, defaultHost = "localhost", From af4a3ca0af7ac758ed69688a2978062a80075d9a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 23 Aug 2021 16:00:51 -0400 Subject: [PATCH 1163/1504] Update memofs to 0.2.0 --- Cargo.lock | 2 +- Cargo.toml | 4 ++-- memofs/CHANGELOG.md | 3 +++ memofs/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9050fe95..81d24349 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1290,7 +1290,7 @@ dependencies = [ [[package]] name = "memofs" -version = "0.1.3" +version = "0.2.0" dependencies = [ "crossbeam-channel", "fs-err", diff --git a/Cargo.toml b/Cargo.toml index c552f8b7..cd760b45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ name = "build" harness = false [dependencies] -memofs = { version = "0.1.2", path = "memofs" } +memofs = { version = "0.2.0", path = "memofs" } # These dependencies can be uncommented when working on rbx-dom simultaneously # rbx_binary = { path = "../rbx-dom/rbx_binary" } @@ -95,7 +95,7 @@ uuid = { version = "0.8.1", features = ["v4", "serde"] } winreg = "0.9.0" [build-dependencies] -memofs = { version = "0.1.3", path = "memofs" } +memofs = { version = "0.2.0", path = "memofs" } embed-resource = "1.6" anyhow = "1.0.27" diff --git a/memofs/CHANGELOG.md b/memofs/CHANGELOG.md index 6a6aecde..b49b2f0f 100644 --- a/memofs/CHANGELOG.md +++ b/memofs/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased Changes +## 0.2.0 (2021-08-23) +* Updated to `crossbeam-channel` 0.5.1. + ## 0.1.3 (2020-11-19) * Added `set_watch_enabled` to `Vfs` and `VfsLock` to allow turning off file watching. diff --git a/memofs/Cargo.toml b/memofs/Cargo.toml index 9dac4351..5cf5a733 100644 --- a/memofs/Cargo.toml +++ b/memofs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "memofs" description = "Virtual filesystem with configurable backends." -version = "0.1.3" +version = "0.2.0" authors = ["Lucien Greathouse "] edition = "2018" readme = "README.md" From 9f06cbf3a020ca34e1034916fc1de6bcfc0ab772 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 23 Aug 2021 16:11:03 -0400 Subject: [PATCH 1164/1504] Update contributing guide --- CONTRIBUTING.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index de61ecf1..99abebfb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,16 +34,17 @@ The Rojo release process is pretty manual right now. If you need to do it, here' 1. Bump server version in [`Cargo.toml`](Cargo.toml) 2. Bump plugin version in [`plugin/src/Config.lua`](plugin/src/Config.lua) -3. Run `cargo test` to update `Cargo.lock` and double-check tests +3. Run `cargo test` to update `Cargo.lock` and run tests 4. Update [`CHANGELOG.md`](CHANGELOG.md) 5. Commit! * `git add . && git commit -m "Release vX.Y.Z"` -6. Tag the commit with the version from `Cargo.toml` prepended with a v, like `v0.4.13` +6. Tag the commit + * `git tag vX.Y.Z` 7. Publish the CLI * `cargo publish` 8. Publish the Plugin - * `rojo publish plugin --asset_id 6415005344` - * `rojo build plugin -o Rojo.rbxm` + * `cargo run -- upload plugin --asset_id 6415005344` + * `cargo run -- build plugin --output Rojo.rbxm` 9. Push commits and tags * `git push && git push --tags` 10. Copy GitHub release content from previous release From d484098781faaa35a7c8bcd6c2eafbaf5eb3fab5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 24 Aug 2021 17:15:47 -0400 Subject: [PATCH 1165/1504] Get rid of confusing 'SnapshotInstanceResult' type alias --- src/snapshot_middleware/csv.rs | 4 ++-- src/snapshot_middleware/dir.rs | 8 ++++++-- src/snapshot_middleware/json.rs | 4 ++-- src/snapshot_middleware/json_model.rs | 4 +--- src/snapshot_middleware/lua.rs | 13 +++++++------ src/snapshot_middleware/middleware.rs | 3 --- src/snapshot_middleware/mod.rs | 6 ++---- src/snapshot_middleware/project.rs | 6 +++--- src/snapshot_middleware/rbxm.rs | 4 +--- src/snapshot_middleware/rbxmx.rs | 4 +--- src/snapshot_middleware/txt.rs | 4 ++-- 11 files changed, 27 insertions(+), 33 deletions(-) delete mode 100644 src/snapshot_middleware/middleware.rs diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 1734fc07..b505e793 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -7,14 +7,14 @@ use serde::Serialize; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult}; +use super::meta_file::AdjacentMetadata; pub fn snapshot_csv( _context: &InstanceContext, vfs: &Vfs, path: &Path, instance_name: &str, -) -> SnapshotInstanceResult { +) -> anyhow::Result> { let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); let contents = vfs.read(path)?; diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index e4b47ffc..bad35c81 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -4,9 +4,13 @@ use memofs::{DirEntry, IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{meta_file::DirectoryMetadata, middleware::SnapshotInstanceResult, snapshot_from_vfs}; +use super::{meta_file::DirectoryMetadata, snapshot_from_vfs}; -pub fn snapshot_dir(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { +pub fn snapshot_dir( + context: &InstanceContext, + vfs: &Vfs, + path: &Path, +) -> anyhow::Result> { let passes_filter_rules = |child: &DirEntry| { context .path_ignore_rules diff --git a/src/snapshot_middleware/json.rs b/src/snapshot_middleware/json.rs index 2e5c53fc..7530812d 100644 --- a/src/snapshot_middleware/json.rs +++ b/src/snapshot_middleware/json.rs @@ -9,14 +9,14 @@ use crate::{ snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, }; -use super::{meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult}; +use super::meta_file::AdjacentMetadata; pub fn snapshot_json( context: &InstanceContext, vfs: &Vfs, path: &Path, instance_name: &str, -) -> SnapshotInstanceResult { +) -> anyhow::Result> { let contents = vfs.read(path)?; let value: serde_json::Value = serde_json::from_slice(&contents) diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 653cc86d..89b274d4 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -9,14 +9,12 @@ use crate::{ snapshot::{InstanceContext, InstanceSnapshot}, }; -use super::middleware::SnapshotInstanceResult; - pub fn snapshot_json_model( context: &InstanceContext, vfs: &Vfs, path: &Path, instance_name: &str, -) -> SnapshotInstanceResult { +) -> anyhow::Result> { let contents = vfs.read(path)?; let contents_str = str::from_utf8(&contents) .with_context(|| format!("File was not valid UTF-8: {}", path.display()))?; diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index cc443084..d11e72c6 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -6,13 +6,14 @@ use memofs::{IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{ - dir::snapshot_dir, meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult, - util::match_trailing, -}; +use super::{dir::snapshot_dir, meta_file::AdjacentMetadata, util::match_trailing}; /// Core routine for turning Lua files into snapshots. -pub fn snapshot_lua(context: &InstanceContext, vfs: &Vfs, path: &Path) -> SnapshotInstanceResult { +pub fn snapshot_lua( + context: &InstanceContext, + vfs: &Vfs, + path: &Path, +) -> anyhow::Result> { let file_name = path.file_name().unwrap().to_string_lossy(); let (class_name, instance_name) = if let Some(name) = match_trailing(&file_name, ".server.lua") @@ -63,7 +64,7 @@ pub fn snapshot_lua_init( context: &InstanceContext, vfs: &Vfs, init_path: &Path, -) -> SnapshotInstanceResult { +) -> anyhow::Result> { let folder_path = init_path.parent().unwrap(); let dir_snapshot = snapshot_dir(context, vfs, folder_path)?.unwrap(); diff --git a/src/snapshot_middleware/middleware.rs b/src/snapshot_middleware/middleware.rs deleted file mode 100644 index f576ede8..00000000 --- a/src/snapshot_middleware/middleware.rs +++ /dev/null @@ -1,3 +0,0 @@ -use crate::snapshot::InstanceSnapshot; - -pub type SnapshotInstanceResult = anyhow::Result>; diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index b6bbb432..9ce40c95 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -11,7 +11,6 @@ mod json; mod json_model; mod lua; mod meta_file; -mod middleware; mod project; mod rbxm; mod rbxmx; @@ -22,7 +21,7 @@ use std::path::Path; use memofs::{IoResultExt, Vfs}; -use crate::snapshot::InstanceContext; +use crate::snapshot::{InstanceContext, InstanceSnapshot}; use self::{ csv::snapshot_csv, @@ -30,7 +29,6 @@ use self::{ json::snapshot_json, json_model::snapshot_json_model, lua::{snapshot_lua, snapshot_lua_init}, - middleware::SnapshotInstanceResult, project::snapshot_project, rbxm::snapshot_rbxm, rbxmx::snapshot_rbxmx, @@ -46,7 +44,7 @@ pub fn snapshot_from_vfs( context: &InstanceContext, vfs: &Vfs, path: &Path, -) -> SnapshotInstanceResult { +) -> anyhow::Result> { let meta = match vfs.metadata(path).with_not_found()? { Some(meta) => meta, None => return Ok(None), diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 2ee55bc2..673def0f 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -11,13 +11,13 @@ use crate::{ }, }; -use super::{middleware::SnapshotInstanceResult, snapshot_from_vfs}; +use super::snapshot_from_vfs; pub fn snapshot_project( context: &InstanceContext, vfs: &Vfs, path: &Path, -) -> SnapshotInstanceResult { +) -> anyhow::Result> { let project = Project::load_from_slice(&vfs.read(path)?, path) .with_context(|| format!("File was not a valid Rojo project: {}", path.display()))?; @@ -63,7 +63,7 @@ pub fn snapshot_project_node( node: &ProjectNode, vfs: &Vfs, parent_class: Option<&str>, -) -> SnapshotInstanceResult { +) -> anyhow::Result> { let project_folder = project_path.parent().unwrap(); let class_name_from_project = node diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 868f863e..8ec551d2 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -5,14 +5,12 @@ use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::middleware::SnapshotInstanceResult; - pub fn snapshot_rbxm( context: &InstanceContext, vfs: &Vfs, path: &Path, instance_name: &str, -) -> SnapshotInstanceResult { +) -> anyhow::Result> { let temp_tree = rbx_binary::from_reader(vfs.read(path)?.as_slice()) .with_context(|| format!("Malformed rbxm file: {}", path.display()))?; diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index d89ad87d..c37d3ddf 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -5,14 +5,12 @@ use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::middleware::SnapshotInstanceResult; - pub fn snapshot_rbxmx( context: &InstanceContext, vfs: &Vfs, path: &Path, instance_name: &str, -) -> SnapshotInstanceResult { +) -> anyhow::Result> { let options = rbx_xml::DecodeOptions::new() .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 4cbf0c3d..fbc42dd6 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -6,14 +6,14 @@ use memofs::{IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{meta_file::AdjacentMetadata, middleware::SnapshotInstanceResult}; +use super::meta_file::AdjacentMetadata; pub fn snapshot_txt( context: &InstanceContext, vfs: &Vfs, path: &Path, instance_name: &str, -) -> SnapshotInstanceResult { +) -> anyhow::Result> { let contents = vfs.read(path)?; let contents_str = str::from_utf8(&contents) .with_context(|| format!("File was not valid UTF-8: {}", path.display()))? From 8954def25cf653e90558cd45792f581ed3b99da0 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 24 Aug 2021 17:59:53 -0400 Subject: [PATCH 1166/1504] Move responsibility for extracting names from paths lower --- src/snapshot_middleware/csv.rs | 33 ++++++++++--------------- src/snapshot_middleware/json.rs | 9 +++---- src/snapshot_middleware/json_model.rs | 8 +++--- src/snapshot_middleware/mod.rs | 32 ++++++++++++------------ src/snapshot_middleware/rbxm.rs | 8 +++--- src/snapshot_middleware/rbxmx.rs | 8 +++--- src/snapshot_middleware/txt.rs | 21 +++++++--------- src/snapshot_middleware/util.rs | 35 ++++++++++++++++++++++----- 8 files changed, 86 insertions(+), 68 deletions(-) diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index b505e793..a8f27180 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -7,15 +7,16 @@ use serde::Serialize; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::meta_file::AdjacentMetadata; +use super::{meta_file::AdjacentMetadata, util::PathExt}; pub fn snapshot_csv( _context: &InstanceContext, vfs: &Vfs, path: &Path, - instance_name: &str, ) -> anyhow::Result> { - let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); + let name = path.file_name_trim_end(".csv")?; + + let meta_path = path.with_file_name(format!("{}.meta.json", name)); let contents = vfs.read(path)?; let table_contents = convert_localization_csv(&contents).with_context(|| { @@ -26,7 +27,7 @@ pub fn snapshot_csv( })?; let mut snapshot = InstanceSnapshot::new() - .name(instance_name) + .name(name) .class_name("LocalizationTable") .properties(hashmap! { "Contents".to_owned() => table_contents.into(), @@ -143,14 +144,10 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, let mut vfs = Vfs::new(imfs); - let instance_snapshot = snapshot_csv( - &InstanceContext::default(), - &mut vfs, - Path::new("/foo.csv"), - "foo", - ) - .unwrap() - .unwrap(); + let instance_snapshot = + snapshot_csv(&InstanceContext::default(), &mut vfs, Path::new("/foo.csv")) + .unwrap() + .unwrap(); insta::assert_yaml_snapshot!(instance_snapshot); } @@ -175,14 +172,10 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, let mut vfs = Vfs::new(imfs); - let instance_snapshot = snapshot_csv( - &InstanceContext::default(), - &mut vfs, - Path::new("/foo.csv"), - "foo", - ) - .unwrap() - .unwrap(); + let instance_snapshot = + snapshot_csv(&InstanceContext::default(), &mut vfs, Path::new("/foo.csv")) + .unwrap() + .unwrap(); insta::assert_yaml_snapshot!(instance_snapshot); } diff --git a/src/snapshot_middleware/json.rs b/src/snapshot_middleware/json.rs index 7530812d..8c7f369e 100644 --- a/src/snapshot_middleware/json.rs +++ b/src/snapshot_middleware/json.rs @@ -9,14 +9,14 @@ use crate::{ snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, }; -use super::meta_file::AdjacentMetadata; +use super::{meta_file::AdjacentMetadata, util::PathExt}; pub fn snapshot_json( context: &InstanceContext, vfs: &Vfs, path: &Path, - instance_name: &str, ) -> anyhow::Result> { + let name = path.file_name_trim_end(".json")?; let contents = vfs.read(path)?; let value: serde_json::Value = serde_json::from_slice(&contents) @@ -28,10 +28,10 @@ pub fn snapshot_json( "Source".to_owned() => as_lua.into(), }; - let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); + let meta_path = path.with_file_name(format!("{}.meta.json", name)); let mut snapshot = InstanceSnapshot::new() - .name(instance_name) + .name(name) .class_name("ModuleScript") .properties(properties) .metadata( @@ -107,7 +107,6 @@ mod test { &InstanceContext::default(), &mut vfs, Path::new("/foo.json"), - "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 89b274d4..52071031 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -9,12 +9,15 @@ use crate::{ snapshot::{InstanceContext, InstanceSnapshot}, }; +use super::util::PathExt; + pub fn snapshot_json_model( context: &InstanceContext, vfs: &Vfs, path: &Path, - instance_name: &str, ) -> anyhow::Result> { + let name = path.file_name_trim_end(".model.json")?; + let contents = vfs.read(path)?; let contents_str = str::from_utf8(&contents) .with_context(|| format!("File was not valid UTF-8: {}", path.display()))?; @@ -28,7 +31,7 @@ pub fn snapshot_json_model( let mut snapshot = instance .core - .into_snapshot(instance_name.to_owned()) + .into_snapshot(name.to_owned()) .with_context(|| format!("Could not load JSON model: {}", path.display()))?; snapshot.metadata = snapshot @@ -133,7 +136,6 @@ mod test { &InstanceContext::default(), &mut vfs, Path::new("/foo.model.json"), - "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 9ce40c95..36729f8f 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -33,7 +33,7 @@ use self::{ rbxm::snapshot_rbxm, rbxmx::snapshot_rbxmx, txt::snapshot_txt, - util::match_file_name, + util::PathExt, }; pub use self::project::snapshot_project_node; @@ -73,7 +73,7 @@ pub fn snapshot_from_vfs( snapshot_dir(context, vfs, path) } else { - if let Some(name) = match_file_name(path, ".lua") { + if let Ok(name) = path.file_name_trim_end(".lua") { match name { // init scripts are handled elsewhere and should not turn into // their own children. @@ -81,23 +81,23 @@ pub fn snapshot_from_vfs( _ => return snapshot_lua(context, vfs, path), } - } else if let Some(_name) = match_file_name(path, ".project.json") { + } else if path.file_name_ends_with(".project.json") { return snapshot_project(context, vfs, path); - } else if let Some(name) = match_file_name(path, ".model.json") { - return snapshot_json_model(context, vfs, path, name); - } else if let Some(_name) = match_file_name(path, ".meta.json") { + } else if path.file_name_ends_with(".model.json") { + return snapshot_json_model(context, vfs, path); + } else if path.file_name_ends_with(".meta.json") { // .meta.json files do not turn into their own instances. return Ok(None); - } else if let Some(name) = match_file_name(path, ".json") { - return snapshot_json(context, vfs, path, name); - } else if let Some(name) = match_file_name(path, ".csv") { - return snapshot_csv(context, vfs, path, name); - } else if let Some(name) = match_file_name(path, ".txt") { - return snapshot_txt(context, vfs, path, name); - } else if let Some(name) = match_file_name(path, ".rbxmx") { - return snapshot_rbxmx(context, vfs, path, name); - } else if let Some(name) = match_file_name(path, ".rbxm") { - return snapshot_rbxm(context, vfs, path, name); + } else if path.file_name_ends_with(".json") { + return snapshot_json(context, vfs, path); + } else if path.file_name_ends_with(".csv") { + return snapshot_csv(context, vfs, path); + } else if path.file_name_ends_with(".txt") { + return snapshot_txt(context, vfs, path); + } else if path.file_name_ends_with(".rbxmx") { + return snapshot_rbxmx(context, vfs, path); + } else if path.file_name_ends_with(".rbxm") { + return snapshot_rbxm(context, vfs, path); } Ok(None) diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 8ec551d2..b1d61313 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -5,12 +5,15 @@ use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; +use super::util::PathExt; + pub fn snapshot_rbxm( context: &InstanceContext, vfs: &Vfs, path: &Path, - instance_name: &str, ) -> anyhow::Result> { + let name = path.file_name_trim_end(".rbxm")?; + let temp_tree = rbx_binary::from_reader(vfs.read(path)?.as_slice()) .with_context(|| format!("Malformed rbxm file: {}", path.display()))?; @@ -19,7 +22,7 @@ pub fn snapshot_rbxm( if children.len() == 1 { let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) - .name(instance_name) + .name(name) .metadata( InstanceMetadata::new() .instigating_source(path) @@ -58,7 +61,6 @@ mod test { &InstanceContext::default(), &mut vfs, Path::new("/foo.rbxm"), - "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index c37d3ddf..3cdd52e4 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -5,12 +5,15 @@ use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; +use super::util::PathExt; + pub fn snapshot_rbxmx( context: &InstanceContext, vfs: &Vfs, path: &Path, - instance_name: &str, ) -> anyhow::Result> { + let name = path.file_name_trim_end(".rbxmx")?; + let options = rbx_xml::DecodeOptions::new() .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); @@ -22,7 +25,7 @@ pub fn snapshot_rbxmx( if children.len() == 1 { let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) - .name(instance_name) + .name(name) .metadata( InstanceMetadata::new() .instigating_source(path) @@ -71,7 +74,6 @@ mod test { &InstanceContext::default(), &mut vfs, Path::new("/foo.rbxmx"), - "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index fbc42dd6..13d5b990 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -6,14 +6,15 @@ use memofs::{IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::meta_file::AdjacentMetadata; +use super::{meta_file::AdjacentMetadata, util::PathExt}; pub fn snapshot_txt( context: &InstanceContext, vfs: &Vfs, path: &Path, - instance_name: &str, ) -> anyhow::Result> { + let name = path.file_name_trim_end(".txt")?; + let contents = vfs.read(path)?; let contents_str = str::from_utf8(&contents) .with_context(|| format!("File was not valid UTF-8: {}", path.display()))? @@ -23,10 +24,10 @@ pub fn snapshot_txt( "Value".to_owned() => contents_str.into(), }; - let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); + let meta_path = path.with_file_name(format!("{}.meta.json", name)); let mut snapshot = InstanceSnapshot::new() - .name(instance_name) + .name(name) .class_name("StringValue") .properties(properties) .metadata( @@ -58,14 +59,10 @@ mod test { let mut vfs = Vfs::new(imfs.clone()); - let instance_snapshot = snapshot_txt( - &InstanceContext::default(), - &mut vfs, - Path::new("/foo.txt"), - "foo", - ) - .unwrap() - .unwrap(); + let instance_snapshot = + snapshot_txt(&InstanceContext::default(), &mut vfs, Path::new("/foo.txt")) + .unwrap() + .unwrap(); insta::assert_yaml_snapshot!(instance_snapshot); } diff --git a/src/snapshot_middleware/util.rs b/src/snapshot_middleware/util.rs index 153c31c2..517cd606 100644 --- a/src/snapshot_middleware/util.rs +++ b/src/snapshot_middleware/util.rs @@ -1,5 +1,7 @@ use std::path::Path; +use anyhow::Context; + /// If the given string ends up with the given suffix, returns the portion of /// the string before the suffix. pub fn match_trailing<'a>(input: &'a str, suffix: &str) -> Option<&'a str> { @@ -11,10 +13,31 @@ pub fn match_trailing<'a>(input: &'a str, suffix: &str) -> Option<&'a str> { } } -/// If the given path has a file name, and that file name ends with the given -/// suffix, returns the portion of the file name before the given suffix. -pub fn match_file_name<'a>(path: &'a Path, suffix: &str) -> Option<&'a str> { - let file_name = path.file_name()?.to_str()?; - - match_trailing(&file_name, suffix) +pub trait PathExt { + fn file_name_ends_with(&self, suffix: &str) -> bool; + fn file_name_trim_end<'a>(&'a self, suffix: &str) -> anyhow::Result<&'a str>; +} + +impl

    PathExt for P +where + P: AsRef, +{ + fn file_name_ends_with(&self, suffix: &str) -> bool { + self.as_ref() + .file_name() + .and_then(|name| name.to_str()) + .map(|name| name.ends_with(suffix)) + .unwrap_or(false) + } + + fn file_name_trim_end<'a>(&'a self, suffix: &str) -> anyhow::Result<&'a str> { + let path = self.as_ref(); + let file_name = path + .file_name() + .and_then(|name| name.to_str()) + .with_context(|| format!("Path did not have a file name: {}", path.display()))?; + + match_trailing(&file_name, suffix) + .with_context(|| format!("Path did not end in {}: {}", suffix, path.display())) + } } From cc071a6415ed98033b63c268cda35509b2a88f92 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 14 Sep 2021 20:42:38 -0400 Subject: [PATCH 1167/1504] Move entrypoint from src/bin.rs to src/main.rs --- Cargo.toml | 4 ---- src/{bin.rs => main.rs} | 0 2 files changed, 4 deletions(-) rename src/{bin.rs => main.rs} (100%) diff --git a/Cargo.toml b/Cargo.toml index cd760b45..dee8b31e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,10 +37,6 @@ members = [ name = "librojo" path = "src/lib.rs" -[[bin]] -name = "rojo" -path = "src/bin.rs" - [[bench]] name = "build" harness = false diff --git a/src/bin.rs b/src/main.rs similarity index 100% rename from src/bin.rs rename to src/main.rs From 8d29b4315570f66d04236cd660c23ab79e927eac Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 11 Oct 2021 17:40:14 -0400 Subject: [PATCH 1168/1504] Upgrade dependencies --- Cargo.lock | 328 +++++++++--------- Cargo.toml | 76 ++-- ...to_end__tests__build__rbxmx_in_folder.snap | 7 +- .../end_to_end__tests__build__rbxmx_ref.snap | 10 +- 4 files changed, 214 insertions(+), 207 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 81d24349..1e0ffe49 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,9 +46,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.43" +version = "1.0.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28ae2b3dec75a406790005a200b1bd89785afc02517a00ca99ecfe093ee9e6cf" +checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" [[package]] name = "arrayref" @@ -168,9 +168,9 @@ dependencies = [ [[package]] name = "bstr" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" dependencies = [ "lazy_static", "memchr", @@ -180,9 +180,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.7.0" +version = "3.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c59e7af012c713f529e7a3ee57ce9b31ddd858d4b512923602f74608b009631" +checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538" [[package]] name = "byte-tools" @@ -209,9 +209,9 @@ dependencies = [ [[package]] name = "bytes" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040" +checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" [[package]] name = "cast" @@ -224,9 +224,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.69" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2" +checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" [[package]] name = "cfg-if" @@ -498,11 +498,11 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e98e2ad1a782e33928b96fc3948e7c355e5af34ba4de7670fe8bac2a3b2006d" +checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" dependencies = [ - "quote 1.0.9", + "quote 1.0.10", "syn", ] @@ -556,13 +556,13 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "embed-resource" -version = "1.6.3" +version = "1.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45de30eb317b4cd3882ee16623cb3004e5fb99a8f4cd40097cadf61efbc54adc" +checksum = "254a67531cc22d81bf92a24358a1dfa3d3b30f8d326fed8c5780eb6f2e5c784f" dependencies = [ "cc", "vswhom", - "winreg 0.9.0", + "winreg 0.10.1", ] [[package]] @@ -609,8 +609,8 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.28", - "quote 1.0.9", + "proc-macro2 1.0.29", + "quote 1.0.10", "syn", "synstructure", ] @@ -635,9 +635,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0" +checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" dependencies = [ "cfg-if 1.0.0", "crc32fast", @@ -731,9 +731,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1adc00f486adfc9ce99f77d717836f0c5aa84965eb0b4f051f4e83f7cab53f8b" +checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" dependencies = [ "futures-channel", "futures-core", @@ -746,9 +746,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74ed2411805f6e4e3d9bc904c95d5d423b89b3b25dc0250aa74729de20629ff9" +checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" dependencies = [ "futures-core", "futures-sink", @@ -756,9 +756,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af51b1b4a7fdff033703db39de8802c673eb91855f2e0d47dcf3bf2c0ef01f99" +checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" [[package]] name = "futures-cpupool" @@ -772,9 +772,9 @@ dependencies = [ [[package]] name = "futures-executor" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d0d535a57b87e1ae31437b892713aee90cd2d7b0ee48727cd11fc72ef54761c" +checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" dependencies = [ "futures-core", "futures-task", @@ -783,40 +783,40 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b0e06c393068f3a6ef246c75cdca793d6a46347e75286933e5e75fd2fd11582" +checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" [[package]] name = "futures-macro" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54913bae956fb8df7f4dc6fc90362aa72e69148e3f39041fbe8742d21e0ac57" +checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" dependencies = [ "autocfg 1.0.1", "proc-macro-hack", - "proc-macro2 1.0.28", - "quote 1.0.9", + "proc-macro2 1.0.29", + "quote 1.0.10", "syn", ] [[package]] name = "futures-sink" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f30aaa67363d119812743aa5f33c201a7a66329f97d1a887022971feea4b53" +checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" [[package]] name = "futures-task" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbe54a98670017f3be909561f6ad13e810d9a51f3f061b902062ca3da80799f2" +checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" [[package]] name = "futures-util" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67eb846bfd58e44a8481a00049e82c43e0ccb5d61f8dc071057cb19249dd4d78" +checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" dependencies = [ "autocfg 1.0.1", "futures-channel", @@ -950,11 +950,11 @@ dependencies = [ [[package]] name = "http" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "527e8c9ac747e28542699a951517aa9a6945af506cd1f2e1b53a576c17b6cc11" +checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "fnv", "itoa", ] @@ -977,8 +977,8 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5" dependencies = [ - "bytes 1.0.1", - "http 0.2.4", + "bytes 1.1.0", + "http 0.2.5", "pin-project-lite", ] @@ -1032,22 +1032,22 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.11" +version = "0.14.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b61cf2d1aebcf6e6352c97b81dc2244ca29194be1b276f5d8ad5c6330fffb11" +checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593" dependencies = [ - "bytes 1.0.1", + "bytes 1.1.0", "futures-channel", "futures-core", "futures-util", - "http 0.2.4", + "http 0.2.5", "http-body 0.4.3", "httparse", "httpdate", "itoa", "pin-project-lite", "socket2", - "tokio 1.10.0", + "tokio 1.12.0", "tower-service", "tracing", "want 0.3.0", @@ -1120,9 +1120,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58019516c1403ac45b106c9fc4e8fcbd77a78e98b014c619d1506338902ccfa4" +checksum = "15226a375927344c78d39dc6b49e2d5562a5b0705e26a589093c6792e52eed8e" dependencies = [ "console", "lazy_static", @@ -1167,9 +1167,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] name = "js-sys" -version = "0.3.53" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4bf49d50e2961077d9c99f4b7997d770a1114f087c3c2e0069b36c13fc2979d" +checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" dependencies = [ "wasm-bindgen", ] @@ -1198,9 +1198,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.100" +version = "0.2.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5" +checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" [[package]] name = "linked-hash-map" @@ -1466,9 +1466,9 @@ dependencies = [ [[package]] name = "object" -version = "0.26.1" +version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee2766204889d09937d00bfbb7fec56bb2a199e2ade963cab19185d8a6104c7c" +checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" dependencies = [ "memchr", ] @@ -1523,9 +1523,9 @@ checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" [[package]] name = "openssl-sys" -version = "0.9.66" +version = "0.9.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1996d2d305e561b70d1ee0c53f1542833f4e1ac6ce9a6708b6ff2738ca67dc82" +checksum = "69df2d8dfc6ce3aaf44b40dec6f487d5a886516cf6879c49e98e0710f310a058" dependencies = [ "autocfg 1.0.1", "cc", @@ -1614,8 +1614,8 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.28", - "quote 1.0.9", + "proc-macro2 1.0.29", + "quote 1.0.10", "syn", ] @@ -1644,9 +1644,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.19" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c" +checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb" [[package]] name = "plotters" @@ -1701,8 +1701,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.28", - "quote 1.0.9", + "proc-macro2 1.0.29", + "quote 1.0.10", "syn", "version_check", ] @@ -1713,8 +1713,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.28", - "quote 1.0.9", + "proc-macro2 1.0.29", + "quote 1.0.10", "version_check", ] @@ -1741,9 +1741,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.28" +version = "1.0.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" +checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" dependencies = [ "unicode-xid 0.2.2", ] @@ -1769,11 +1769,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ - "proc-macro2 1.0.28", + "proc-macro2 1.0.29", ] [[package]] @@ -1990,9 +1990,9 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "0.6.2" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ef5d412170f7cd73437fbc51bd0c2d976a19226b1ca4e0dd4654b9de456ce69" +checksum = "68f424adb7a0a24ab4bd153be141035f1404ae40affed902fd2721b42cca7f86" dependencies = [ "log", "lz4", @@ -2004,9 +2004,9 @@ dependencies = [ [[package]] name = "rbx_dom_weak" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d65a8c420268f17400dd7b1edb259086fe5922b794c1d78027ca605afe38c1e5" +checksum = "6f7f524fb18f30d7065c82c4e87f747705679329810207e96169c6d4ec922d1f" dependencies = [ "rbx_types", "serde", @@ -2014,9 +2014,9 @@ dependencies = [ [[package]] name = "rbx_reflection" -version = "4.1.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5348f0072bca81d514808002a6464cb842128b48c36e2e8b07cd6d490eb12c82" +checksum = "a8915748c8a3b2a92540e4e35e99ebd548df2d62b0a6cf38ae5d0081f0e611d5" dependencies = [ "rbx_types", "serde", @@ -2024,9 +2024,9 @@ dependencies = [ [[package]] name = "rbx_reflection_database" -version = "0.2.1+roblox-484" +version = "0.2.2+roblox-498" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82fd952a01a86f1e6e182e1bc5f31bead251b37c4200f3ac3ff0d5e0a49d5d7" +checksum = "e4e459dc87be8464122ad3bb722a562ddae8e811bb4a6b7809eaa1fac220cf30" dependencies = [ "lazy_static", "rbx_reflection", @@ -2036,9 +2036,9 @@ dependencies = [ [[package]] name = "rbx_types" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42ae2a0d18070ac3139c6a3b7228fe3342559b9520f4da2faa13e2eefb2d59" +checksum = "d637383aa560cb675b7ea7a7778b945dab065ccc7c158f77b5455e27efadc6df" dependencies = [ "base64 0.11.0", "bitflags", @@ -2046,13 +2046,14 @@ dependencies = [ "lazy_static", "rand 0.7.3", "serde", + "thiserror", ] [[package]] name = "rbx_xml" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88c71b41834dbf565b040399b011b1d6b006df78692fa3469d5defa985be9cbc" +checksum = "67387cd246cdec9251dd2451672541499ae6ce0a47c768b3ea9ee0a1becda9dd" dependencies = [ "base64 0.11.0", "log", @@ -2188,9 +2189,9 @@ dependencies = [ [[package]] name = "rlua" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25fa5b2c667bae0b6218361e96d365e414fe4a0fa80f476b9631aa2dea2c6881" +checksum = "93397b9792dc237cab7554ab4c4128b8aa5fc9ec25892cfd82c92286055313d0" dependencies = [ "bitflags", "bstr", @@ -2244,10 +2245,10 @@ dependencies = [ "embed-resource", "env_logger", "fs-err", - "futures 0.3.16", + "futures 0.3.17", "globset", "humantime", - "hyper 0.14.11", + "hyper 0.14.13", "insta", "jod-thread", "lazy_static", @@ -2276,7 +2277,7 @@ dependencies = [ "tempfile", "termcolor", "thiserror", - "tokio 1.10.0", + "tokio 1.12.0", "uuid 0.8.2", "walkdir", "winreg 0.9.0", @@ -2292,9 +2293,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dead70b0b5e03e9c814bcb6b01e03e68f7c57a80aa48c72ec92152ab3e818d49" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" [[package]] name = "rustc_version" @@ -2347,9 +2348,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "security-framework" -version = "2.3.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a2ac85147a3a11d77ecf1bc7166ec0b92febfa4461c37944e180f319ece467" +checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" dependencies = [ "bitflags", "core-foundation", @@ -2360,9 +2361,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.3.0" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e4effb91b4b8b6fb7732e670b6cee160278ff8e6bf485c7805d9e319d76e284" +checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" dependencies = [ "core-foundation-sys", "libc", @@ -2391,9 +2392,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.128" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1056a0db1978e9dbf0f6e4fca677f6f9143dc1c19de346f22cac23e422196834" +checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" dependencies = [ "serde_derive", ] @@ -2410,20 +2411,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.128" +version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13af2fbb8b60a8950d6c72a56d2095c28870367cc8e10c55e9745bac4995a2c4" +checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" dependencies = [ - "proc-macro2 1.0.28", - "quote 1.0.9", + "proc-macro2 1.0.29", + "quote 1.0.10", "syn", ] [[package]] name = "serde_json" -version = "1.0.66" +version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "336b10da19a12ad094b59d870ebde26a45402e5b470add4b5fd03c5048a32127" +checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" dependencies = [ "itoa", "ryu", @@ -2444,9 +2445,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.8.19" +version = "0.8.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6375dbd828ed6964c3748e4ef6d18e7a175d408ffe184bca01698d0c73f915a9" +checksum = "d8c608a35705a5d3cdc9fbe403147647ff34b921f8e833e49306df898f9b20af" dependencies = [ "dtoa", "indexmap", @@ -2498,9 +2499,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "765f090f0e423d2b55843402a07915add955e7d60657db13707a159727326cad" +checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" dependencies = [ "libc", "winapi 0.3.9", @@ -2523,9 +2524,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.22" +version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69b041cdcb67226aca307e6e7be44c8806423d83e018bd662360a93dabce4d71" +checksum = "bf9d950ef167e25e0bdb073cf1d68e9ad2795ac826f2f3f59647817cf23c0bfa" dependencies = [ "clap", "lazy_static", @@ -2534,14 +2535,14 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.15" +version = "0.4.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7813934aecf5f51a54775e00068c237de98489463968231a51746bbbc03f9c10" +checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.28", - "quote 1.0.9", + "proc-macro2 1.0.29", + "quote 1.0.10", "syn", ] @@ -2553,23 +2554,23 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "syn" -version = "1.0.75" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7" +checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" dependencies = [ - "proc-macro2 1.0.28", - "quote 1.0.9", + "proc-macro2 1.0.29", + "quote 1.0.10", "unicode-xid 0.2.2", ] [[package]] name = "synstructure" -version = "0.12.5" +version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "474aaa926faa1603c40b7885a9eaea29b444d1cb2850cb7c0e37bb1a4182f4fa" +checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.28", - "quote 1.0.9", + "proc-macro2 1.0.29", + "quote 1.0.10", "syn", "unicode-xid 0.2.2", ] @@ -2618,21 +2619,21 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.26" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2" +checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.26" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745" +checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ - "proc-macro2 1.0.28", - "quote 1.0.9", + "proc-macro2 1.0.29", + "quote 1.0.10", "syn", ] @@ -2658,9 +2659,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.3.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338" +checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7" dependencies = [ "tinyvec_macros", ] @@ -2692,9 +2693,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.10.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cf844b23c6131f624accf65ce0e4e9956a8bb329400ea5bcc26ae3a5c20b0b" +checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc" dependencies = [ "autocfg 1.0.1", "libc", @@ -2826,9 +2827,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.26" +version = "0.1.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09adeb8c97449311ccd28a427f96fb563e7fd31aabf994189879d9da2394b89d" +checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -2837,9 +2838,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.19" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ca517f43f0fb96e0c3072ed5c275fe5eece87e8cb52f4a77b69226d3b1c9df8" +checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" dependencies = [ "lazy_static", ] @@ -2861,9 +2862,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.13.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879f6906492a7cd215bfa4cf595b600146ccfac0c79bcbd1f3000162af5e8b06" +checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" [[package]] name = "ucd-trie" @@ -2882,9 +2883,9 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085" +checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" [[package]] name = "unicode-normalization" @@ -2903,9 +2904,9 @@ checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" [[package]] name = "unicode-width" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" [[package]] name = "unicode-xid" @@ -3045,9 +3046,9 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasm-bindgen" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce9b1b516211d33767048e5d47fa2a381ed8b76fc48d2ce4aa39877f9f183e0" +checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -3055,37 +3056,37 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe8dc78e2326ba5f845f4b5bf548401604fa20b1dd1d365fb73b6c1d6364041" +checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.28", - "quote 1.0.9", + "proc-macro2 1.0.29", + "quote 1.0.10", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44468aa53335841d9d6b6c023eaab07c0cd4bddbcfdee3e2bb1e8d2cb8069fef" +checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" dependencies = [ - "quote 1.0.9", + "quote 1.0.10", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0195807922713af1e67dc66132c7328206ed9766af3858164fb583eedc25fbad" +checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" dependencies = [ - "proc-macro2 1.0.28", - "quote 1.0.9", + "proc-macro2 1.0.29", + "quote 1.0.10", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -3093,15 +3094,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.76" +version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acdb075a845574a1fa5f09fd77e43f7747599301ea3417a9fbffdeedfc1f4a29" +checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" [[package]] name = "web-sys" -version = "0.3.53" +version = "0.3.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "224b2f6b67919060055ef1a67807367c2066ed520c3862cc013d26cf893a783c" +checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" dependencies = [ "js-sys", "wasm-bindgen", @@ -3168,6 +3169,15 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "winreg" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +dependencies = [ + "winapi 0.3.9", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" diff --git a/Cargo.toml b/Cargo.toml index dee8b31e..4cea6450 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,41 +51,41 @@ memofs = { version = "0.2.0", path = "memofs" } # rbx_reflection_database = { path = "../rbx-dom/rbx_reflection_database" } # rbx_xml = { path = "../rbx-dom/rbx_xml" } -rbx_binary = "0.6.1" -rbx_dom_weak = "2.1.0" -rbx_reflection = "4.1.0" -rbx_reflection_database = "0.2.1" -rbx_xml = "0.12.1" +rbx_binary = "0.6.4" +rbx_dom_weak = "2.3.0" +rbx_reflection = "4.2.0" +rbx_reflection_database = "0.2.2" +rbx_xml = "0.12.3" -anyhow = "1.0.27" -backtrace = "0.3" -bincode = "1.2.1" +anyhow = "1.0.44" +backtrace = "0.3.61" +bincode = "1.3.3" crossbeam-channel = "0.5.1" -csv = "1.1.1" +csv = "1.1.6" env_logger = "0.9.0" -fs-err = "2.2.0" -futures = "0.3.16" -globset = "0.4.4" +fs-err = "2.6.0" +futures = "0.3.17" +globset = "0.4.8" humantime = "2.1.0" -hyper = { version = "0.14.11", features = ["server", "tcp", "http1"] } -jod-thread = "0.1.0" +hyper = { version = "0.14.13", features = ["server", "tcp", "http1"] } +jod-thread = "0.1.2" lazy_static = "1.4.0" -log = "0.4.8" -maplit = "1.0.1" -notify = "4.0.14" +log = "0.4.14" +maplit = "1.0.2" +notify = "4.0.17" opener = "0.5.0" -regex = "1.3.1" -reqwest = "0.9.20" +regex = "1.5.4" +reqwest = "0.9.24" ritz = "0.1.0" -rlua = "0.17.0" +rlua = "0.17.1" roblox_install = "1.0.0" -serde = { version = "1.0", features = ["derive", "rc"] } -serde_json = "1.0" -structopt = "0.3.5" -termcolor = "1.0.5" -thiserror = "1.0.11" -tokio = { version = "1.9.0", features = ["rt", "rt-multi-thread"] } -uuid = { version = "0.8.1", features = ["v4", "serde"] } +serde = { version = "1.0.130", features = ["derive", "rc"] } +serde_json = "1.0.68" +structopt = "0.3.23" +termcolor = "1.1.2" +thiserror = "1.0.30" +tokio = { version = "1.12.0", features = ["rt", "rt-multi-thread"] } +uuid = { version = "0.8.2", features = ["v4", "serde"] } [target.'cfg(windows)'.dependencies] winreg = "0.9.0" @@ -93,20 +93,20 @@ winreg = "0.9.0" [build-dependencies] memofs = { version = "0.2.0", path = "memofs" } -embed-resource = "1.6" -anyhow = "1.0.27" -bincode = "1.2.1" -fs-err = "2.3.0" -maplit = "1.0.1" +embed-resource = "1.6.4" +anyhow = "1.0.44" +bincode = "1.3.3" +fs-err = "2.6.0" +maplit = "1.0.2" [dev-dependencies] rojo-insta-ext = { path = "rojo-insta-ext" } -criterion = "0.3" -insta = { version = "1.3.0", features = ["redactions"] } -lazy_static = "1.2" +criterion = "0.3.5" +insta = { version = "1.8.0", features = ["redactions"] } +lazy_static = "1.4.0" paste = "1.0.5" pretty_assertions = "0.7.2" -serde_yaml = "0.8.9" -tempfile = "3.0" -walkdir = "2.1" +serde_yaml = "0.8.21" +tempfile = "3.2.0" +walkdir = "2.3.2" diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_in_folder.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_in_folder.snap index 92cab199..db602853 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_in_folder.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_in_folder.snap @@ -1,6 +1,7 @@ --- source: tests/tests/build.rs expression: contents + --- @@ -25,14 +26,12 @@ expression: contents 1 null - - + Cool StringValue - - + Did you know that BaseValue.Changed is different than Instance.Changed? diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_ref.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_ref.snap index 1f1e21a2..621961f8 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_ref.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__rbxmx_ref.snap @@ -1,27 +1,25 @@ --- source: tests/tests/build.rs expression: contents + --- rbxmx_ref - - + Target - - + Pointed to by ObjectValue Pointer - - + 1 From 5d88bdb25673da00b11e3f418bfea7228c7ea211 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 15 Oct 2021 13:24:40 -0400 Subject: [PATCH 1169/1504] Upgrade dependencies in lockfile --- Cargo.lock | 61 +++++++++++++++++++++++++++--------------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1e0ffe49..40aa9ae9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -313,9 +313,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" +checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" dependencies = [ "core-foundation-sys", "libc", @@ -323,9 +323,9 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" +checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "crc32fast" @@ -609,7 +609,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.29", + "proc-macro2 1.0.30", "quote 1.0.10", "syn", "synstructure", @@ -795,7 +795,7 @@ checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" dependencies = [ "autocfg 1.0.1", "proc-macro-hack", - "proc-macro2 1.0.29", + "proc-macro2 1.0.30", "quote 1.0.10", "syn", ] @@ -861,7 +861,7 @@ checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi 0.10.0+wasi-snapshot-preview1", ] [[package]] @@ -903,9 +903,9 @@ dependencies = [ [[package]] name = "half" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62aca2aba2d62b4a7f5b33f3712cb1b0692779a56fb510499d5c0aa594daeaf3" +checksum = "ac5956d4e63858efaec57e0d6c1c2f6a41e1487f830314a324ccd7e2223a7ca0" [[package]] name = "hashbrown" @@ -1614,7 +1614,7 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.29", + "proc-macro2 1.0.30", "quote 1.0.10", "syn", ] @@ -1678,9 +1678,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.10" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" +checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741" [[package]] name = "pretty_assertions" @@ -1701,7 +1701,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.29", + "proc-macro2 1.0.30", "quote 1.0.10", "syn", "version_check", @@ -1713,7 +1713,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.29", + "proc-macro2 1.0.30", "quote 1.0.10", "version_check", ] @@ -1741,9 +1741,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.29" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" +checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70" dependencies = [ "unicode-xid 0.2.2", ] @@ -1773,7 +1773,7 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ - "proc-macro2 1.0.29", + "proc-macro2 1.0.30", ] [[package]] @@ -2415,7 +2415,7 @@ version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" dependencies = [ - "proc-macro2 1.0.29", + "proc-macro2 1.0.30", "quote 1.0.10", "syn", ] @@ -2475,9 +2475,9 @@ checksum = "1ad1d488a557b235fc46dae55512ffbfc429d2482b08b4d9435ab07384ca8aec" [[package]] name = "slab" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" +checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" [[package]] name = "smallvec" @@ -2541,7 +2541,7 @@ checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.29", + "proc-macro2 1.0.30", "quote 1.0.10", "syn", ] @@ -2558,7 +2558,7 @@ version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" dependencies = [ - "proc-macro2 1.0.29", + "proc-macro2 1.0.30", "quote 1.0.10", "unicode-xid 0.2.2", ] @@ -2569,7 +2569,7 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.29", + "proc-macro2 1.0.30", "quote 1.0.10", "syn", "unicode-xid 0.2.2", @@ -2632,18 +2632,19 @@ version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ - "proc-macro2 1.0.29", + "proc-macro2 1.0.30", "quote 1.0.10", "syn", ] [[package]] name = "time" -version = "0.1.43" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" dependencies = [ "libc", + "wasi 0.10.0+wasi-snapshot-preview1", "winapi 0.3.9", ] @@ -3040,9 +3041,9 @@ checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" [[package]] name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" +version = "0.10.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] name = "wasm-bindgen" @@ -3063,7 +3064,7 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.29", + "proc-macro2 1.0.30", "quote 1.0.10", "syn", "wasm-bindgen-shared", @@ -3085,7 +3086,7 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" dependencies = [ - "proc-macro2 1.0.29", + "proc-macro2 1.0.30", "quote 1.0.10", "syn", "wasm-bindgen-backend", From 277ddfa9bedf992dd40e2e3d5d253280c98a8330 Mon Sep 17 00:00:00 2001 From: Wiktor Rudnicki <46418816+Rudy-Dev@users.noreply.github.com> Date: Fri, 15 Oct 2021 19:27:47 +0200 Subject: [PATCH 1170/1504] Themes colors modification (#482) * Modified colors of themes Colors match Roblox Studio theme. * Change cases of colors Colors' hexes have correct cases now. --- plugin/src/App/Theme.lua | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index d6d688b3..32578d3e 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -34,7 +34,7 @@ end local BRAND_COLOR = hexColor(0xE13835) local lightTheme = strict("LightTheme", { - BackgroundColor = hexColor(0xF0F0F0), + BackgroundColor = hexColor(0xFFFFFF), Button = { Solid = { ActionFillColor = hexColor(0xFFFFFF), @@ -67,7 +67,7 @@ local lightTheme = strict("LightTheme", { BackgroundColor = BRAND_COLOR, }, Inactive = { - IconColor = hexColor(0xCACACA), + IconColor = hexColor(0xEEEEEE), BorderColor = hexColor(0xAFAFAF), }, }, @@ -77,11 +77,11 @@ local lightTheme = strict("LightTheme", { }, BorderedContainer = { BorderColor = hexColor(0xCBCBCB), - BackgroundColor = hexColor(0xE0E0E0), + BackgroundColor = hexColor(0xEEEEEE), }, Spinner = { ForegroundColor = BRAND_COLOR, - BackgroundColor = hexColor(0xE0E0E0), + BackgroundColor = hexColor(0xEEEEEE), }, ConnectionDetails = { ProjectNameColor = hexColor(0x00000), @@ -108,7 +108,7 @@ local lightTheme = strict("LightTheme", { }) local darkTheme = strict("DarkTheme", { - BackgroundColor = hexColor(0x272727), + BackgroundColor = hexColor(0x2E2E2E), Button = { Solid = { ActionFillColor = hexColor(0xFFFFFF), @@ -147,15 +147,15 @@ local darkTheme = strict("DarkTheme", { }, AddressEntry = { TextColor = hexColor(0xFFFFFF), - PlaceholderColor = hexColor(0x717171) + PlaceholderColor = hexColor(0x8B8B8B) }, BorderedContainer = { BorderColor = hexColor(0x535353), - BackgroundColor = hexColor(0x323232), + BackgroundColor = hexColor(0x2B2B2B), }, Spinner = { ForegroundColor = BRAND_COLOR, - BackgroundColor = hexColor(0x323232), + BackgroundColor = hexColor(0x2B2B2B), }, ConnectionDetails = { ProjectNameColor = hexColor(0xFFFFFF), @@ -236,4 +236,4 @@ return { StudioProvider = StudioProvider, Consumer = Context.Consumer, with = with, -} \ No newline at end of file +} From 9d0b3132619d1fc8a361746c75e7e8c6df39119b Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Mon, 18 Oct 2021 15:18:51 -0700 Subject: [PATCH 1171/1504] Add ChangeBatcher to plugin for two-way sync (#478) * Implement ChangeBatcher * Use ChangeBatcher for two-way sync * Pause updates during patch application * I can English good * Break after encountering a nil Parent change This prevents __flush from erroring out when an instance's Parent is changed to nil and it has other property changes in the same batch. * Update rbx_dom_lua * Don't connect changed listeners in a running game #468 made me realize how bad of an idea this is in general... * Update TestEZ and fix sibling Ref reification test * Add ChangeBatcher tests * Test instance unpausing by breaking functionality out to __cycle * Break up the module a bit and improve tests * Shuffle requires around and edit comment * Break out more stuff, rename createChangePatch -> createPatchSet * Make ChangeBatcher responsible for unpausing all paused instances This somewhat improves the situation (of course, it would preferrable to not have to hack around this problem with Source at all). It also sets us up nicely if we come across any other properties that do anything similar. * Remove old reference to pausedBatchInstances * Use RenderStepped instead of Heartbeat and trash multi-frame pauses I probably should have done this in the first place... ChangeBatcher still needs to unpause instances, but we don't need to hold pauses for any longer than one cycle. * Remove useless branch * if not next(x) -> if next(x) == nil * Add InstanceMap:unpauseAllInstances, use it in ChangeBatcher * Move IsRunning check to InstanceMap:__maybeFireInstanceChanged --- plugin/modules/testez | 2 +- plugin/rbx_dom_lua/PropertyDescriptor.lua | 16 ++- plugin/src/ChangeBatcher/createPatchSet.lua | 40 +++++++ .../src/ChangeBatcher/createPatchSet.spec.lua | 74 +++++++++++++ .../src/ChangeBatcher/encodePatchUpdate.lua | 39 +++++++ .../ChangeBatcher/encodePatchUpdate.spec.lua | 62 +++++++++++ plugin/src/ChangeBatcher/encodeProperty.lua | 21 ++++ plugin/src/ChangeBatcher/init.lua | 81 ++++++++++++++ plugin/src/ChangeBatcher/init.spec.lua | 101 ++++++++++++++++++ plugin/src/InstanceMap.lua | 40 ++++--- plugin/src/Reconciler/applyPatch.lua | 6 +- plugin/src/Reconciler/reify.spec.lua | 6 +- plugin/src/ServeSession.lua | 65 +++-------- plugin/test-place.project.json | 4 +- 14 files changed, 483 insertions(+), 74 deletions(-) create mode 100644 plugin/src/ChangeBatcher/createPatchSet.lua create mode 100644 plugin/src/ChangeBatcher/createPatchSet.spec.lua create mode 100644 plugin/src/ChangeBatcher/encodePatchUpdate.lua create mode 100644 plugin/src/ChangeBatcher/encodePatchUpdate.spec.lua create mode 100644 plugin/src/ChangeBatcher/encodeProperty.lua create mode 100644 plugin/src/ChangeBatcher/init.lua create mode 100644 plugin/src/ChangeBatcher/init.spec.lua diff --git a/plugin/modules/testez b/plugin/modules/testez index 6e9157db..25d957d4 160000 --- a/plugin/modules/testez +++ b/plugin/modules/testez @@ -1 +1 @@ -Subproject commit 6e9157db3c1a8b1558c54c50065e3562cab362e1 +Subproject commit 25d957d4d5c4c02a52843ef43e72f21f973c2908 diff --git a/plugin/rbx_dom_lua/PropertyDescriptor.lua b/plugin/rbx_dom_lua/PropertyDescriptor.lua index dcb53632..3d4c2bd5 100644 --- a/plugin/rbx_dom_lua/PropertyDescriptor.lua +++ b/plugin/rbx_dom_lua/PropertyDescriptor.lua @@ -20,7 +20,21 @@ local function set(container, key, value) end function PropertyDescriptor.fromRaw(data, className, propertyName) + local key, value = next(data.DataType) + return setmetatable({ + -- The meanings of the key and value in DataType differ when the type of + -- the property is Enum. When the property is of type Enum, the key is + -- the name of the type: + -- + -- { Enum = "" } + -- + -- When the property is not of type Enum, the value is the name of the + -- type: + -- + -- { Value = "" } + dataType = key == "Enum" and key or value, + scriptability = data.Scriptability, className = className, name = propertyName, @@ -77,4 +91,4 @@ function PropertyDescriptor:write(instance, value) end end -return PropertyDescriptor \ No newline at end of file +return PropertyDescriptor diff --git a/plugin/src/ChangeBatcher/createPatchSet.lua b/plugin/src/ChangeBatcher/createPatchSet.lua new file mode 100644 index 00000000..e4c0fc0a --- /dev/null +++ b/plugin/src/ChangeBatcher/createPatchSet.lua @@ -0,0 +1,40 @@ +--[[ + Take an InstanceMap and a dictionary mapping instances to sets of property + names. Populate a patch with the encoded values of all the given properties + on all the given instances (or, if any changes set Parent to nil, removals + of instances) and return the patch. +]] + +local Log = require(script.Parent.Parent.Parent.Log) + +local PatchSet = require(script.Parent.Parent.PatchSet) + +local encodePatchUpdate = require(script.Parent.encodePatchUpdate) + +return function(instanceMap, propertyChanges) + local patch = PatchSet.newEmpty() + + for instance, properties in pairs(propertyChanges) do + local instanceId = instanceMap.fromInstances[instance] + + if instanceId == nil then + Log.warn("Ignoring change for instance {:?} as it is unknown to Rojo", instance) + continue + end + + if properties.Parent then + if instance.Parent == nil then + table.insert(patch.removed, instanceId) + else + Log.warn("Cannot sync non-nil Parent property changes yet") + end + else + local update = encodePatchUpdate(instance, instanceId, properties) + table.insert(patch.updated, update) + end + + propertyChanges[instance] = nil + end + + return patch +end diff --git a/plugin/src/ChangeBatcher/createPatchSet.spec.lua b/plugin/src/ChangeBatcher/createPatchSet.spec.lua new file mode 100644 index 00000000..55528df6 --- /dev/null +++ b/plugin/src/ChangeBatcher/createPatchSet.spec.lua @@ -0,0 +1,74 @@ +return function() + local PatchSet = require(script.Parent.Parent.PatchSet) + local InstanceMap = require(script.Parent.Parent.InstanceMap) + + local createPatchSet = require(script.Parent.createPatchSet) + + it("should return a patch", function() + local patch = createPatchSet(InstanceMap.new(), {}) + + assert(PatchSet.validate(patch)) + end) + + it("should contain updates for every instance with property changes", function() + local instanceMap = InstanceMap.new() + + local part1 = Instance.new("Part") + instanceMap:insert("PART_1", part1) + + local part2 = Instance.new("Part") + instanceMap:insert("PART_2", part2) + + local changes = { + [part1] = { + Position = true, + Size = true, + Color = true, + }, + [part2] = { + CFrame = true, + Velocity = true, + Transparency = true, + }, + } + + local patch = createPatchSet(instanceMap, changes) + + expect(#patch.updated).to.equal(2) + end) + + it("should not contain any updates for removed instances", function() + local instanceMap = InstanceMap.new() + + local part1 = Instance.new("Part") + instanceMap:insert("PART_1", part1) + + local changes = { + [part1] = { + Parent = true, + Position = true, + Size = true, + }, + } + + local patch = createPatchSet(instanceMap, changes) + + expect(#patch.removed).to.equal(1) + expect(#patch.updated).to.equal(0) + end) + + it("should remove instances from the property change table", function() + local instanceMap = InstanceMap.new() + + local part1 = Instance.new("Part") + instanceMap:insert("PART_1", part1) + + local changes = { + [part1] = {}, + } + + createPatchSet(instanceMap, changes) + + expect(next(changes)).to.equal(nil) + end) +end diff --git a/plugin/src/ChangeBatcher/encodePatchUpdate.lua b/plugin/src/ChangeBatcher/encodePatchUpdate.lua new file mode 100644 index 00000000..a3af8069 --- /dev/null +++ b/plugin/src/ChangeBatcher/encodePatchUpdate.lua @@ -0,0 +1,39 @@ +local Log = require(script.Parent.Parent.Parent.Log) +local RbxDom = require(script.Parent.Parent.Parent.RbxDom) + +local encodeProperty = require(script.Parent.encodeProperty) + +return function(instance, instanceId, properties) + local update = { + id = instanceId, + changedProperties = {}, + } + + for propertyName in pairs(properties) do + if propertyName == "Name" then + update.changedName = instance.Name + else + local descriptor = RbxDom.findCanonicalPropertyDescriptor(instance.ClassName, propertyName) + + if not descriptor then + Log.debug("Could not sync back property {:?}.{}", instance, propertyName) + continue + end + + local encodeSuccess, encodeResult = encodeProperty(instance, propertyName, descriptor) + + if not encodeSuccess then + Log.debug("Could not sync back property {:?}.{}: {}", instance, propertyName, encodeResult) + continue + end + + update.changedProperties[propertyName] = encodeResult + end + end + + if next(update.changedProperties) == nil and update.changedName == nil then + return nil + end + + return update +end diff --git a/plugin/src/ChangeBatcher/encodePatchUpdate.spec.lua b/plugin/src/ChangeBatcher/encodePatchUpdate.spec.lua new file mode 100644 index 00000000..9945ae34 --- /dev/null +++ b/plugin/src/ChangeBatcher/encodePatchUpdate.spec.lua @@ -0,0 +1,62 @@ +return function() + local encodePatchUpdate = require(script.Parent.encodePatchUpdate) + + it("should return an update when there are property changes", function() + local part = Instance.new("Part") + local properties = { + CFrame = true, + Color = true, + } + local update = encodePatchUpdate(part, "PART", properties) + + expect(update.id).to.equal("PART") + expect(update.changedProperties.CFrame).to.be.ok() + expect(update.changedProperties.Color).to.be.ok() + end) + + it("should return nil when there are no property changes", function() + local part = Instance.new("Part") + local properties = { + NonExistentProperty = true, + } + local update = encodePatchUpdate(part, "PART", properties) + + expect(update).to.equal(nil) + end) + + it("should set changedName in the update when the instance's Name changes", function() + local part = Instance.new("Part") + local properties = { + Name = true, + } + + part.Name = "We'reGettingToTheCoolPart" + + local update = encodePatchUpdate(part, "PART", properties) + + expect(update.changedName).to.equal("We'reGettingToTheCoolPart") + end) + + it("should correctly encode property values", function() + local part = Instance.new("Part") + local properties = { + Position = true, + Color = true, + } + + part.Position = Vector3.new(0, 100, 0) + part.Color = Color3.new(0.8, 0.2, 0.9) + + local update = encodePatchUpdate(part, "PART", properties) + local position = update.changedProperties.Position + local color = update.changedProperties.Color + + expect(position.Vector3[1]).to.equal(0) + expect(position.Vector3[2]).to.equal(100) + expect(position.Vector3[3]).to.equal(0) + + expect(color.Color3[1]).to.be.near(0.8, 0.01) + expect(color.Color3[2]).to.be.near(0.2, 0.01) + expect(color.Color3[3]).to.be.near(0.9, 0.01) + end) +end diff --git a/plugin/src/ChangeBatcher/encodeProperty.lua b/plugin/src/ChangeBatcher/encodeProperty.lua new file mode 100644 index 00000000..e6ad95a2 --- /dev/null +++ b/plugin/src/ChangeBatcher/encodeProperty.lua @@ -0,0 +1,21 @@ +local Log = require(script.Parent.Parent.Parent.Log) +local RbxDom = require(script.Parent.Parent.Parent.RbxDom) + +return function(instance, propertyName, propertyDescriptor) + local readSuccess, readResult = propertyDescriptor:read(instance) + + if not readSuccess then + Log.warn("Could not sync back property {:?}.{}: {}", instance, propertyName, readResult) + return false, nil + end + + local dataType = propertyDescriptor.dataType + local encodeSuccess, encodeResult = RbxDom.EncodedValue.encode(readResult, dataType) + + if not encodeSuccess then + Log.warn("Could not sync back property {:?}.{}: {}", instance, propertyName, encodeResult) + return false, nil + end + + return true, encodeResult +end diff --git a/plugin/src/ChangeBatcher/init.lua b/plugin/src/ChangeBatcher/init.lua new file mode 100644 index 00000000..5d320ce2 --- /dev/null +++ b/plugin/src/ChangeBatcher/init.lua @@ -0,0 +1,81 @@ +--[[ + The ChangeBatcher is responsible for collecting and dispatching changes made + to tracked instances during two-way sync. +]] + +local RunService = game:GetService("RunService") + +local PatchSet = require(script.Parent.PatchSet) + +local createPatchSet = require(script.createPatchSet) + +local ChangeBatcher = {} +ChangeBatcher.__index = ChangeBatcher + +local BATCH_INTERVAL = 0.2 + +function ChangeBatcher.new(instanceMap, onChangesFlushed) + local self + + local renderSteppedConnection = RunService.RenderStepped:Connect(function(dt) + self:__cycle(dt) + end) + + self = setmetatable({ + __accumulator = 0, + __renderSteppedConnection = renderSteppedConnection, + __instanceMap = instanceMap, + __onChangesFlushed = onChangesFlushed, + __pendingPropertyChanges = {}, + }, ChangeBatcher) + + return self +end + +function ChangeBatcher:stop() + self.__renderSteppedConnection:Disconnect() + self.__pendingPropertyChanges = {} +end + +function ChangeBatcher:add(instance, propertyName) + local properties = self.__pendingPropertyChanges[instance] + + if not properties then + properties = {} + self.__pendingPropertyChanges[instance] = properties + end + + properties[propertyName] = true +end + +function ChangeBatcher:__cycle(dt) + self.__accumulator += dt + + if self.__accumulator >= BATCH_INTERVAL then + self.__accumulator -= BATCH_INTERVAL + + local patch = self:__flush() + + if patch then + self.__onChangesFlushed(patch) + end + end + + self.__instanceMap:unpauseAllInstances() +end + +function ChangeBatcher:__flush() + if next(self.__pendingPropertyChanges) == nil then + return nil + end + + local patch = createPatchSet(self.__instanceMap, self.__pendingPropertyChanges) + + if PatchSet.isEmpty(patch) then + return nil + end + + return patch +end + +return ChangeBatcher diff --git a/plugin/src/ChangeBatcher/init.spec.lua b/plugin/src/ChangeBatcher/init.spec.lua new file mode 100644 index 00000000..21173233 --- /dev/null +++ b/plugin/src/ChangeBatcher/init.spec.lua @@ -0,0 +1,101 @@ +return function() + local ChangeBatcher = require(script.Parent) + local InstanceMap = require(script.Parent.Parent.InstanceMap) + local PatchSet = require(script.Parent.Parent.PatchSet) + + local noop = function() end + + describe("new", function() + it("should create a new ChangeBatcher", function() + local instanceMap = InstanceMap.new() + local changeBatcher = ChangeBatcher.new(instanceMap, noop) + + expect(changeBatcher.__pendingPropertyChanges).to.be.a("table") + expect(next(changeBatcher.__pendingPropertyChanges)).to.equal(nil) + expect(changeBatcher.__onChangesFlushed).to.equal(noop) + expect(changeBatcher.__instanceMap).to.equal(instanceMap) + expect(typeof(changeBatcher.__renderSteppedConnection)).to.equal("RBXScriptConnection") + end) + end) + + describe("stop", function() + it("should disconnect the RenderStepped connection", function() + local changeBatcher = ChangeBatcher.new(InstanceMap.new(), noop) + + changeBatcher:stop() + + expect(changeBatcher.__renderSteppedConnection.Connected).to.equal(false) + end) + end) + + describe("add", function() + it("should add property changes to be considered for the current batch", function() + local instanceMap = InstanceMap.new() + local changeBatcher = ChangeBatcher.new(instanceMap, noop) + local part = Instance.new("Part") + + instanceMap:insert("PART", part) + changeBatcher:add(part, "Name") + + local properties = changeBatcher.__pendingPropertyChanges[part] + + expect(properties).to.be.a("table") + expect(properties.Name).to.be.ok() + + changeBatcher:add(part, "Position") + expect(properties.Position).to.be.ok() + end) + end) + + describe("__cycle", function() + it("should immediately unpause any paused instances after each cycle", function() + local instanceMap = InstanceMap.new() + local changeBatcher = ChangeBatcher.new(instanceMap, noop) + local part = Instance.new("Part") + + instanceMap.pausedUpdateInstances[part] = true + + changeBatcher:__cycle(0) + + expect(instanceMap.pausedUpdateInstances[part]).to.equal(nil) + end) + end) + + describe("__flush", function() + it("should return nil when there are no changes to process", function() + local changeBatcher = ChangeBatcher.new(InstanceMap.new(), noop) + expect(changeBatcher:__flush()).to.equal(nil) + end) + + it("should return a patch when there are changes to process and the resulting patch is non-empty", function() + local instanceMap = InstanceMap.new() + local changeBatcher = ChangeBatcher.new(instanceMap, noop) + local part = Instance.new("Part") + + instanceMap:insert("PART", part) + + changeBatcher.__pendingPropertyChanges[part] = { + Position = true, + Name = true, + } + + local patch = changeBatcher:__flush() + + assert(PatchSet.validate(patch)) + end) + + it("should return nil when there are changes to process and the resulting patch is empty", function() + local instanceMap = InstanceMap.new() + local changeBatcher = ChangeBatcher.new(instanceMap, noop) + local part = Instance.new("Part") + + instanceMap:insert("PART", part) + + changeBatcher.__pendingPropertyChanges[part] = { + NonExistentProperty = true, + } + + expect(changeBatcher:__flush()).to.equal(nil) + end) + end) +end diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 7196d915..2d9cbffb 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -1,3 +1,5 @@ +local RunService = game:GetService("RunService") + local Log = require(script.Parent.Parent.Log) --[[ @@ -135,29 +137,31 @@ function InstanceMap:destroyId(id) end --[[ - Pause updates for an instance momentarily and invoke a callback. - - If the callback throws an error, InstanceMap will still be kept in a - consistent state. + Pause updates for an instance. ]] -function InstanceMap:pauseInstance(instance, callback) +function InstanceMap:pauseInstance(instance) local id = self.fromInstances[instance] - -- If we don't know about this instance, ignore it and do not invoke the - -- callback. + -- If we don't know about this instance, ignore it. if id == nil then return end self.pausedUpdateInstances[instance] = true - local success, result = xpcall(callback, debug.traceback) - self.pausedUpdateInstances[instance] = false +end - if success then - return result - else - error(result, 2) - end +--[[ + Unpause updates for an instance. +]] +function InstanceMap:unpauseInstance(instance) + self.pausedUpdateInstances[instance] = nil +end + +--[[ + Unpause updates for all instances. +]] +function InstanceMap:unpauseAllInstances() + table.clear(self.pausedUpdateInstances) end function InstanceMap:__connectSignals(instance) @@ -200,6 +204,12 @@ function InstanceMap:__maybeFireInstanceChanged(instance, propertyName) return end + if RunService:IsRunning() then + -- We probably don't want to pick up property changes to save to the + -- filesystem in a running game. + return + end + self.onInstanceChanged(instance, propertyName) end @@ -222,4 +232,4 @@ function InstanceMap:__disconnectSignals(instance) end end -return InstanceMap \ No newline at end of file +return InstanceMap diff --git a/plugin/src/Reconciler/applyPatch.lua b/plugin/src/Reconciler/applyPatch.lua index a061bea7..345a3bf7 100644 --- a/plugin/src/Reconciler/applyPatch.lua +++ b/plugin/src/Reconciler/applyPatch.lua @@ -77,6 +77,10 @@ local function applyPatch(instanceMap, patch) continue end + -- Pause updates on this instance to avoid picking up our changes when + -- two-way sync is enabled. + instanceMap:pauseInstance(instance) + -- Track any part of this update that could not be applied. local unappliedUpdate = { id = update.id, @@ -197,4 +201,4 @@ local function applyPatch(instanceMap, patch) return unappliedPatch end -return applyPatch \ No newline at end of file +return applyPatch diff --git a/plugin/src/Reconciler/reify.spec.lua b/plugin/src/Reconciler/reify.spec.lua index 607811d6..a13b204a 100644 --- a/plugin/src/Reconciler/reify.spec.lua +++ b/plugin/src/Reconciler/reify.spec.lua @@ -255,7 +255,7 @@ return function() Name = "Child A", Properties = { Value = { - Ref = "Child B", + Ref = "CHILD_B", }, }, Children = {}, @@ -287,7 +287,7 @@ return function() -- constructed as part of a recursive call before the parent has totally -- finished. Given deferred refs, this should not fail, but it is a good -- case to test. - it("should apply properties containing refs to later siblings correctly", function() + it("should apply properties containing refs to later children correctly", function() local virtualInstances = { ROOT = { ClassName = "ObjectValue", @@ -344,4 +344,4 @@ return function() expect(update.id).to.equal("ROOT") expect(update.changedProperties.Value).to.equal(virtualInstances["ROOT"].Properties.Value) end) -end \ No newline at end of file +end diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index b40d8e81..d0bff1f3 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -5,6 +5,7 @@ local Log = require(script.Parent.Parent.Log) local Fmt = require(script.Parent.Parent.Fmt) local t = require(script.Parent.Parent.t) +local ChangeBatcher = require(script.Parent.ChangeBatcher) local InstanceMap = require(script.Parent.InstanceMap) local PatchSet = require(script.Parent.PatchSet) local Reconciler = require(script.Parent.Reconciler) @@ -56,10 +57,19 @@ function ServeSession.new(options) -- Declare self ahead of time to capture it in a closure local self local function onInstanceChanged(instance, propertyName) - self:__onInstanceChanged(instance, propertyName) + if not self.__twoWaySync then + return + end + + self.__changeBatcher:add(instance, propertyName) + end + + local function onChangesFlushed(patch) + self.__apiContext:write(patch) end local instanceMap = InstanceMap.new(onInstanceChanged) + local changeBatcher = ChangeBatcher.new(instanceMap, onChangesFlushed) local reconciler = Reconciler.new(instanceMap) local connections = {} @@ -82,6 +92,7 @@ function ServeSession.new(options) __twoWaySync = options.twoWaySync, __reconciler = reconciler, __instanceMap = instanceMap, + __changeBatcher = changeBatcher, __statusChangedCallback = nil, __connections = connections, } @@ -179,55 +190,6 @@ function ServeSession:__onActiveScriptChanged(activeScript) self.__apiContext:open(scriptId) end -function ServeSession:__onInstanceChanged(instance, propertyName) - if not self.__twoWaySync then - return - end - - local instanceId = self.__instanceMap.fromInstances[instance] - - if instanceId == nil then - Log.warn("Ignoring change for instance {:?} as it is unknown to Rojo", instance) - return - end - - local remove = nil - - local update = { - id = instanceId, - changedProperties = {}, - } - - if propertyName == "Name" then - update.changedName = instance.Name - elseif propertyName == "Parent" then - if instance.Parent == nil then - update = nil - remove = instanceId - else - Log.warn("Cannot sync non-nil Parent property changes yet") - return - end - else - local success, encoded = self.__reconciler:encodeApiValue(instance[propertyName]) - - if not success then - Log.warn("Could not sync back property {:?}.{}", instance, propertyName) - return - end - - update.changedProperties[propertyName] = encoded - end - - local patch = { - removed = {remove}, - added = {}, - updated = {update}, - } - - self.__apiContext:write(patch) -end - function ServeSession:__initialSync(rootInstanceId) return self.__apiContext:read({ rootInstanceId }) :andThen(function(readResponseBody) @@ -290,6 +252,7 @@ function ServeSession:__stopInternal(err) self:__setStatus(Status.Disconnected, err) self.__apiContext:disconnect() self.__instanceMap:stop() + self.__changeBatcher:stop() for _, connection in ipairs(self.__connections) do connection:Disconnect() @@ -305,4 +268,4 @@ function ServeSession:__setStatus(status, detail) end end -return ServeSession \ No newline at end of file +return ServeSession diff --git a/plugin/test-place.project.json b/plugin/test-place.project.json index 7bc42eb6..b75fcaae 100644 --- a/plugin/test-place.project.json +++ b/plugin/test-place.project.json @@ -9,7 +9,7 @@ }, "TestEZ": { - "$path": "modules/testez/lib" + "$path": "modules/testez" } }, @@ -25,4 +25,4 @@ } } } -} \ No newline at end of file +} From 96112fe1183406e8f9fb0d5d900cccf242a06520 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Tue, 19 Oct 2021 13:46:31 -0700 Subject: [PATCH 1172/1504] Add ambiguous value resolution StringArray -> Tags (#484) * Add ambiguous value resolution StringArray -> Tags * Remove funny autocompleted reference --- src/resolution.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/resolution.rs b/src/resolution.rs index 94b481b4..a1e1e0ee 100644 --- a/src/resolution.rs +++ b/src/resolution.rs @@ -1,7 +1,7 @@ use std::borrow::Borrow; use anyhow::format_err; -use rbx_dom_weak::types::{Color3, Content, Enum, Variant, VariantType, Vector2, Vector3}; +use rbx_dom_weak::types::{Color3, Content, Enum, Tags, Variant, VariantType, Vector2, Vector3}; use rbx_reflection::{DataType, PropertyDescriptor}; use serde::{Deserialize, Serialize}; @@ -32,6 +32,7 @@ impl UnresolvedValue { pub enum AmbiguousValue { Bool(bool), String(String), + StringArray(Vec), Number(f64), Array2([f64; 2]), Array3([f64; 3]), @@ -93,6 +94,9 @@ impl AmbiguousValue { (VariantType::Int64, AmbiguousValue::Number(value)) => Ok((value as i64).into()), (VariantType::String, AmbiguousValue::String(value)) => Ok(value.into()), + (VariantType::Tags, AmbiguousValue::StringArray(value)) => { + Ok(Tags::from(value).into()) + } (VariantType::Content, AmbiguousValue::String(value)) => { Ok(Content::from(value).into()) } @@ -129,6 +133,7 @@ impl AmbiguousValue { match self { AmbiguousValue::Bool(_) => "a bool", AmbiguousValue::String(_) => "a string", + AmbiguousValue::StringArray(_) => "an array of strings", AmbiguousValue::Number(_) => "a number", AmbiguousValue::Array2(_) => "an array of two numbers", AmbiguousValue::Array3(_) => "an array of three numbers", From 07abfbde43914b9c4600539aed72eebfb8065220 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Oct 2021 17:04:34 -0400 Subject: [PATCH 1173/1504] Release Rojo 7.0.0-rc.2 --- CHANGELOG.md | 22 ++++++++++++++++++---- Cargo.lock | 2 +- Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e63577ed..359e87b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,21 @@ ## Unreleased Changes -## [7.0.0-rc.1][7.0.0-rc.1] (August 23, 2021) +## [7.0.0-rc.2] - October 19, 2021 +This is the last release candidate for Rojo 7. In an effort to get Rojo 7 out the door, we'll be freezing features from here on out, something we should've done a couple months ago. + +Expect to see Rojo 7 stable soon! + +* Added support for writing `Tags` in project files, model files, and meta files. ([#484]) +* Adjusted Studio plugin colors to match Roblox Studio palette. ([#482]) +* Improved experimental two-way sync feature by batching changes. ([#478]) + +[#482]: https://github.com/rojo-rbx/rojo/pull/482 +[#484]: https://github.com/rojo-rbx/rojo/pull/484 +[#478]: https://github.com/rojo-rbx/rojo/pull/478 +[7.0.0-rc.2]: https://github.com/rojo-rbx/rojo/releases/tag/v7.0.0-rc.2 + +## [7.0.0-rc.1] - August 23, 2021 In Rojo 6 and previous Rojo 7 alphas, an explicit Vector3 property would be written like this: ```json @@ -45,9 +59,9 @@ The shorthand property format that most users use is not impacted. For reference * Added the `fmt-project` subcommand for formatting Rojo project files. * Improved error output for many subcommands. * Updated to stable versions of rbx-dom libraries. -* Updated async infrastructure, which should fix a handful of bugs. ([#459][#459]) -* Fixed syncing refs in the Roblox Studio plugin ([#462][#462], [#466][#466]) -* Added support for long paths on Windows. ([#464][#464]) +* Updated async infrastructure, which should fix a handful of bugs. ([#459]) +* Fixed syncing refs in the Roblox Studio plugin ([#462], [#466]) +* Added support for long paths on Windows. ([#464]) [#459]: https://github.com/rojo-rbx/rojo/pull/459 [#462]: https://github.com/rojo-rbx/rojo/pull/462 diff --git a/Cargo.lock b/Cargo.lock index 40aa9ae9..c077ec9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2234,7 +2234,7 @@ dependencies = [ [[package]] name = "rojo" -version = "7.0.0-rc.1" +version = "7.0.0-rc.2" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 4cea6450..45a40943 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "7.0.0-rc.1" +version = "7.0.0-rc.2" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 1e613426..8e606272 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {7, 0, 0, "-rc.1"}, + version = {7, 0, 0, "-rc.2"}, expectedServerVersionString = "7.0 or newer", protocolVersion = 4, defaultHost = "localhost", From 75542dacb3c38658a171caa11f56883f089ad5a8 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Oct 2021 17:12:28 -0400 Subject: [PATCH 1174/1504] Release Rojo 7.0.0-rc.3 --- CHANGELOG.md | 7 +- Cargo.lock | 2 +- Cargo.toml | 2 +- plugin/rbx_dom_lua/EncodedValue.lua | 5 + plugin/rbx_dom_lua/allValues.json | 10 + plugin/rbx_dom_lua/customProperties.lua | 13 +- plugin/rbx_dom_lua/database.json | 3214 +++++++++++++++++++---- plugin/src/Config.lua | 2 +- 8 files changed, 2747 insertions(+), 508 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 359e87b3..449b507a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ ## Unreleased Changes -## [7.0.0-rc.2] - October 19, 2021 +## [7.0.0-rc.3] - October 19, 2021 This is the last release candidate for Rojo 7. In an effort to get Rojo 7 out the door, we'll be freezing features from here on out, something we should've done a couple months ago. Expect to see Rojo 7 stable soon! @@ -14,7 +14,10 @@ Expect to see Rojo 7 stable soon! [#482]: https://github.com/rojo-rbx/rojo/pull/482 [#484]: https://github.com/rojo-rbx/rojo/pull/484 [#478]: https://github.com/rojo-rbx/rojo/pull/478 -[7.0.0-rc.2]: https://github.com/rojo-rbx/rojo/releases/tag/v7.0.0-rc.2 +[7.0.0-rc.3]: https://github.com/rojo-rbx/rojo/releases/tag/v7.0.0-rc.3 + +## 7.0.0-rc.2 - October 19, 2021 +(Botched release due to Git mishap, oops!) ## [7.0.0-rc.1] - August 23, 2021 In Rojo 6 and previous Rojo 7 alphas, an explicit Vector3 property would be written like this: diff --git a/Cargo.lock b/Cargo.lock index c077ec9b..ee1fae56 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2234,7 +2234,7 @@ dependencies = [ [[package]] name = "rojo" -version = "7.0.0-rc.2" +version = "7.0.0-rc.3" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 45a40943..917ce77c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "7.0.0-rc.2" +version = "7.0.0-rc.3" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/rbx_dom_lua/EncodedValue.lua b/plugin/rbx_dom_lua/EncodedValue.lua index 37cfad6c..3c495888 100644 --- a/plugin/rbx_dom_lua/EncodedValue.lua +++ b/plugin/rbx_dom_lua/EncodedValue.lua @@ -388,6 +388,11 @@ types = { end, }, + Tags = { + fromPod = identity, + toPod = identity, + }, + Vector2 = { fromPod = unpackDecoder(Vector2.new), diff --git a/plugin/rbx_dom_lua/allValues.json b/plugin/rbx_dom_lua/allValues.json index c577f8f7..a03cf57b 100644 --- a/plugin/rbx_dom_lua/allValues.json +++ b/plugin/rbx_dom_lua/allValues.json @@ -251,6 +251,16 @@ }, "ty": "String" }, + "Tags": { + "value": { + "Tags": [ + "foo", + "con'fusion?!", + "bar" + ] + }, + "ty": "Tags" + }, "UDim": { "value": { "UDim": [ diff --git a/plugin/rbx_dom_lua/customProperties.lua b/plugin/rbx_dom_lua/customProperties.lua index aa03310d..7b3dccba 100644 --- a/plugin/rbx_dom_lua/customProperties.lua +++ b/plugin/rbx_dom_lua/customProperties.lua @@ -6,12 +6,10 @@ local CollectionService = game:GetService("CollectionService") return { Instance = { Tags = { - read = function(instance, key) - local tagList = CollectionService:GetTags(instance) - - return true, table.concat(tagList, "\0") + read = function(instance) + return true, CollectionService:GetTags(instance) end, - write = function(instance, key, value) + write = function(instance, _, value) local existingTags = CollectionService:GetTags(instance) local unseenTags = {} @@ -19,8 +17,7 @@ return { unseenTags[tag] = true end - local tagList = string.split(value, "\0") - for _, tag in ipairs(tagList) do + for _, tag in ipairs(value) do unseenTags[tag] = nil CollectionService:AddTag(instance, tag) end @@ -44,4 +41,4 @@ return { end, }, }, -} \ No newline at end of file +} diff --git a/plugin/rbx_dom_lua/database.json b/plugin/rbx_dom_lua/database.json index a6ee7adc..4fd4d431 100644 --- a/plugin/rbx_dom_lua/database.json +++ b/plugin/rbx_dom_lua/database.json @@ -1,9 +1,9 @@ { "Version": [ 0, - 489, + 498, 0, - 4890336 + 4980398 ], "Classes": { "ABTestService": { @@ -249,6 +249,19 @@ } } }, + "CFrame": { + "Name": "CFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MaxAngularVelocity": { "Name": "MaxAngularVelocity", "Scriptability": "ReadWrite", @@ -275,6 +288,32 @@ } } }, + "Mode": { + "Name": "Mode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "OrientationAlignmentMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PrimaryAxis": { + "Name": "PrimaryAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PrimaryAxisOnly": { "Name": "PrimaryAxisOnly", "Scriptability": "ReadWrite", @@ -326,6 +365,19 @@ "Serialization": "Serializes" } } + }, + "SecondaryAxis": { + "Name": "SecondaryAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -335,6 +387,32 @@ "AttributesSerialize": { "BinaryString": "" }, + "CFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, "Color": { "Int32": 23 }, @@ -347,6 +425,16 @@ "MaxTorque": { "Float32": 10000.0 }, + "Mode": { + "Enum": 1 + }, + "PrimaryAxis": { + "Vector3": [ + 1.0, + 0.0, + 0.0 + ] + }, "PrimaryAxisOnly": { "Bool": false }, @@ -359,6 +447,13 @@ "RigidityEnabled": { "Bool": false }, + "SecondaryAxis": { + "Vector3": [ + 0.0, + 1.0, + 0.0 + ] + }, "SourceAssetId": { "Int64": -1 }, @@ -414,6 +509,32 @@ } } }, + "Mode": { + "Name": "Mode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "PositionAlignmentMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Position": { + "Name": "Position", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ReactionForceEnabled": { "Name": "ReactionForceEnabled", "Scriptability": "ReadWrite", @@ -473,6 +594,16 @@ "MaxVelocity": { "Float32": null }, + "Mode": { + "Enum": 1 + }, + "Position": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, "ReactionForceEnabled": { "Bool": false }, @@ -669,6 +800,42 @@ } } }, + "AnimationClip": { + "Name": "AnimationClip", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Loop": { + "Name": "Loop", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Priority": { + "Name": "Priority", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AnimationPriority" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "AnimationController": { "Name": "AnimationController", "Tags": [], @@ -686,6 +853,23 @@ } } }, + "AnimationRigData": { + "Name": "AnimationRigData", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "AnimationTrack": { "Name": "AnimationTrack", "Tags": [ @@ -945,40 +1129,6 @@ "Properties": {}, "DefaultProperties": {} }, - "AssetImportItemSettings": { - "Name": "AssetImportItemSettings", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "Instance", - "Properties": { - "ShouldImport": { - "Name": "ShouldImport", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": {} - }, - "AssetImportMeshSettings": { - "Name": "AssetImportMeshSettings", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "AssetImportItemSettings", - "Properties": {}, - "DefaultProperties": {} - }, "AssetImportService": { "Name": "AssetImportService", "Tags": [ @@ -990,43 +1140,6 @@ "Properties": {}, "DefaultProperties": {} }, - "AssetImportSettings": { - "Name": "AssetImportSettings", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "Instance", - "Properties": { - "Hierarchy": { - "Name": "Hierarchy", - "Scriptability": "Read", - "DataType": { - "Value": "Ref" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": {} - }, - "AssetImportTextureSettings": { - "Name": "AssetImportTextureSettings", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "AssetImportItemSettings", - "Properties": {}, - "DefaultProperties": {} - }, "AssetManagerService": { "Name": "AssetManagerService", "Tags": [ @@ -2260,6 +2373,19 @@ } } }, + "MaterialVariant": { + "Name": "MaterialVariant", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Orientation": { "Name": "Orientation", "Scriptability": "ReadWrite", @@ -2783,6 +2909,19 @@ } } }, + "Brightness": { + "Name": "Brightness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Color": { "Name": "Color", "Scriptability": "ReadWrite", @@ -2996,6 +3135,9 @@ "AttributesSerialize": { "BinaryString": "" }, + "Brightness": { + "Float32": 1.0 + }, "Color": { "ColorSequence": { "keypoints": [ @@ -4715,7 +4857,6 @@ "Breakpoint": { "Name": "Breakpoint", "Tags": [ - "NotCreatable", "NotReplicated" ], "Superclass": "Instance", @@ -4724,12 +4865,11 @@ "Name": "Condition", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "Hidden", - "NotReplicated", - "ReadOnly" + "NotReplicated" ], "Kind": { "Canonical": { @@ -4743,6 +4883,22 @@ "DataType": { "Value": "Bool" }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Id": { + "Name": "Id", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, "Tags": [ "Hidden", "NotReplicated", @@ -4771,11 +4927,27 @@ } } }, + "LogMessage": { + "Name": "LogMessage", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Script": { "Name": "Script", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "Hidden", @@ -4788,8 +4960,8 @@ } } }, - "Valid": { - "Name": "Valid", + "Verified": { + "Name": "Verified", "Scriptability": "None", "DataType": { "Value": "Bool" @@ -4921,6 +5093,16 @@ } } }, + "CSGCacheService": { + "Name": "CSGCacheService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "CSGDictionaryService": { "Name": "CSGDictionaryService", "Tags": [ @@ -5248,6 +5430,146 @@ } } }, + "CanvasGroup": { + "Name": "CanvasGroup", + "Tags": [], + "Superclass": "GuiObject", + "Properties": { + "GroupColor": { + "Name": "GroupColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Transparency": { + "Name": "Transparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Bool": false + }, + "AnchorPoint": { + "Vector2": [ + 0.0, + 0.0 + ] + }, + "AttributesSerialize": { + "BinaryString": "" + }, + "AutoLocalize": { + "Bool": true + }, + "AutomaticSize": { + "Enum": 0 + }, + "BackgroundColor3": { + "Color3": [ + 0.6392157, + 0.63529414, + 0.64705884 + ] + }, + "BackgroundTransparency": { + "Float32": 0.0 + }, + "BorderColor3": { + "Color3": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "BorderMode": { + "Enum": 0 + }, + "BorderSizePixel": { + "Int32": 1 + }, + "ClipsDescendants": { + "Bool": false + }, + "Draggable": { + "Bool": false + }, + "GroupColor": { + "Color3": [ + 1.0, + 1.0, + 1.0 + ] + }, + "LayoutOrder": { + "Int32": 0 + }, + "Position": { + "UDim2": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "Rotation": { + "Float32": 0.0 + }, + "Selectable": { + "Bool": false + }, + "Size": { + "UDim2": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SizeConstraint": { + "Enum": 0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "Transparency": { + "Float32": 0.0 + }, + "Visible": { + "Bool": true + }, + "ZIndex": { + "Int32": 1 + } + } + }, "CatalogPages": { "Name": "CatalogPages", "Tags": [ @@ -5268,6 +5590,48 @@ "Properties": {}, "DefaultProperties": {} }, + "ChannelSelectorSoundEffect": { + "Name": "ChannelSelectorSoundEffect", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "CustomDspSoundEffect", + "Properties": { + "Channel": { + "Name": "Channel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "Channel": { + "Int32": 1 + }, + "Enabled": { + "Bool": true + }, + "Priority": { + "Int32": 0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "CharacterAppearance": { "Name": "CharacterAppearance", "Tags": [ @@ -5857,6 +6221,22 @@ "DataType": { "Value": "String" }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DisplayName": { + "Name": "DisplayName", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, "Tags": [ "NotReplicated" ], @@ -5881,22 +6261,6 @@ } } }, - "Group": { - "Name": "Group", - "Scriptability": "Read", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "Icon": { "Name": "Icon", "Scriptability": "None", @@ -5958,22 +6322,6 @@ "Serialization": "DoesNotSerialize" } } - }, - "Text": { - "Name": "Text", - "Scriptability": "Read", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } } }, "DefaultProperties": {} @@ -6704,6 +7052,38 @@ } } }, + "CurveAnimation": { + "Name": "CurveAnimation", + "Tags": [], + "Superclass": "AnimationClip", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "Loop": { + "Bool": true + }, + "Priority": { + "Enum": 2 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, + "CustomDspSoundEffect": { + "Name": "CustomDspSoundEffect", + "Tags": [ + "NotCreatable" + ], + "Superclass": "SoundEffect", + "Properties": {}, + "DefaultProperties": {} + }, "CustomEvent": { "Name": "CustomEvent", "Tags": [ @@ -8246,6 +8626,40 @@ ], "Superclass": "Instance", "Properties": { + "ErrorMessage": { + "Name": "ErrorMessage", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "HasError": { + "Name": "HasError", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Id": { "Name": "Id", "Scriptability": "None", @@ -8311,6 +8725,102 @@ }, "DefaultProperties": {} }, + "DebuggerLuaResponse": { + "Name": "DebuggerLuaResponse", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "IsError": { + "Name": "IsError", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsSuccess": { + "Name": "IsSuccess", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Message": { + "Name": "Message", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RequestId": { + "Name": "RequestId", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Status": { + "Name": "Status", + "Scriptability": "None", + "DataType": { + "Enum": "DebuggerStatus" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "DebuggerManager": { "Name": "DebuggerManager", "Tags": [ @@ -8339,6 +8849,119 @@ }, "DefaultProperties": {} }, + "DebuggerVariable": { + "Name": "DebuggerVariable", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Name": { + "Name": "Name", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Populated": { + "Name": "Populated", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Type": { + "Name": "Type", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Value": { + "Name": "Value", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "VariableId": { + "Name": "VariableId", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "VariablesCount": { + "Name": "VariablesCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "DebuggerWatch": { "Name": "DebuggerWatch", "Tags": [], @@ -9471,6 +10094,40 @@ } } }, + "EulerRotationCurve": { + "Name": "EulerRotationCurve", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "RotationOrder": { + "Name": "RotationOrder", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RotationOrder" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "RotationOrder": { + "Enum": 0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "EventIngestService": { "Name": "EventIngestService", "Tags": [ @@ -9599,45 +10256,6 @@ } } }, - "Expression": { - "Name": "Expression", - "Tags": [ - "NotReplicated" - ], - "Superclass": "Instance", - "Properties": { - "Expression": { - "Name": "Expression", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "AttributesSerialize": { - "BinaryString": "" - }, - "Expression": { - "String": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, "FaceControls": { "Name": "FaceControls", "Tags": [ @@ -9647,13 +10265,12 @@ "Properties": { "ChinRaiser": { "Name": "ChinRaiser", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9663,13 +10280,12 @@ }, "ChinRaiserUpperLip": { "Name": "ChinRaiserUpperLip", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9679,13 +10295,12 @@ }, "Corrugator": { "Name": "Corrugator", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9695,13 +10310,12 @@ }, "EyesLookDown": { "Name": "EyesLookDown", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9711,13 +10325,12 @@ }, "EyesLookLeft": { "Name": "EyesLookLeft", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9727,13 +10340,12 @@ }, "EyesLookRight": { "Name": "EyesLookRight", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9743,13 +10355,12 @@ }, "EyesLookUp": { "Name": "EyesLookUp", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9759,13 +10370,12 @@ }, "FlatPucker": { "Name": "FlatPucker", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9775,13 +10385,12 @@ }, "Funneler": { "Name": "Funneler", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9791,13 +10400,12 @@ }, "JawDrop": { "Name": "JawDrop", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9807,13 +10415,12 @@ }, "JawLeft": { "Name": "JawLeft", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9823,13 +10430,12 @@ }, "JawRight": { "Name": "JawRight", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9839,13 +10445,12 @@ }, "LeftBrowLowerer": { "Name": "LeftBrowLowerer", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9855,13 +10460,12 @@ }, "LeftCheekPuff": { "Name": "LeftCheekPuff", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9871,13 +10475,12 @@ }, "LeftCheekRaiser": { "Name": "LeftCheekRaiser", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9887,13 +10490,12 @@ }, "LeftDimpler": { "Name": "LeftDimpler", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9903,13 +10505,12 @@ }, "LeftEyeClosed": { "Name": "LeftEyeClosed", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9919,13 +10520,12 @@ }, "LeftEyeUpperLidRaiser": { "Name": "LeftEyeUpperLidRaiser", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9935,13 +10535,12 @@ }, "LeftInnerBrowRaiser": { "Name": "LeftInnerBrowRaiser", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9951,13 +10550,12 @@ }, "LeftLipCornerDown": { "Name": "LeftLipCornerDown", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9967,13 +10565,12 @@ }, "LeftLipCornerPuller": { "Name": "LeftLipCornerPuller", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9983,13 +10580,12 @@ }, "LeftLipStretcher": { "Name": "LeftLipStretcher", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -9999,13 +10595,12 @@ }, "LeftLowerLipDepressor": { "Name": "LeftLowerLipDepressor", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10015,13 +10610,12 @@ }, "LeftNoseWrinkler": { "Name": "LeftNoseWrinkler", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10031,13 +10625,12 @@ }, "LeftOuterBrowRaiser": { "Name": "LeftOuterBrowRaiser", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10047,13 +10640,12 @@ }, "LeftUpperLipRaiser": { "Name": "LeftUpperLipRaiser", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10063,13 +10655,12 @@ }, "LipPresser": { "Name": "LipPresser", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10079,13 +10670,12 @@ }, "LipsTogether": { "Name": "LipsTogether", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10095,13 +10685,12 @@ }, "LowerLipSuck": { "Name": "LowerLipSuck", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10111,13 +10700,12 @@ }, "MouthLeft": { "Name": "MouthLeft", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10127,13 +10715,12 @@ }, "MouthRight": { "Name": "MouthRight", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10143,13 +10730,12 @@ }, "Pucker": { "Name": "Pucker", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10159,13 +10745,12 @@ }, "RightBrowLowerer": { "Name": "RightBrowLowerer", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10175,13 +10760,12 @@ }, "RightCheekPuff": { "Name": "RightCheekPuff", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10191,13 +10775,12 @@ }, "RightCheekRaiser": { "Name": "RightCheekRaiser", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10207,13 +10790,12 @@ }, "RightDimpler": { "Name": "RightDimpler", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10223,13 +10805,12 @@ }, "RightEyeClosed": { "Name": "RightEyeClosed", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10239,13 +10820,12 @@ }, "RightEyeUpperLidRaiser": { "Name": "RightEyeUpperLidRaiser", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10255,13 +10835,12 @@ }, "RightInnerBrowRaiser": { "Name": "RightInnerBrowRaiser", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10271,13 +10850,12 @@ }, "RightLipCornerDown": { "Name": "RightLipCornerDown", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10287,13 +10865,12 @@ }, "RightLipCornerPuller": { "Name": "RightLipCornerPuller", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10303,13 +10880,12 @@ }, "RightLipStretcher": { "Name": "RightLipStretcher", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10319,13 +10895,12 @@ }, "RightLowerLipDepressor": { "Name": "RightLowerLipDepressor", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10335,13 +10910,12 @@ }, "RightNoseWrinkler": { "Name": "RightNoseWrinkler", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10351,13 +10925,12 @@ }, "RightOuterBrowRaiser": { "Name": "RightOuterBrowRaiser", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10367,13 +10940,12 @@ }, "RightUpperLipRaiser": { "Name": "RightUpperLipRaiser", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10383,13 +10955,12 @@ }, "TongueDown": { "Name": "TongueDown", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10399,13 +10970,12 @@ }, "TongueOut": { "Name": "TongueOut", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10415,13 +10985,12 @@ }, "TongueUp": { "Name": "TongueUp", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10431,13 +11000,12 @@ }, "UpperLipSuck": { "Name": "UpperLipSuck", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" }, "Tags": [ - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -10552,42 +11120,6 @@ ], "Superclass": "Instance", "Properties": { - "FileName": { - "Name": "FileName", - "Scriptability": "Read", - "DataType": { - "Value": "String" - }, - "Tags": [ - "Deprecated", - "Hidden", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "FileSize": { - "Name": "FileSize", - "Scriptability": "Read", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Deprecated", - "Hidden", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "Size": { "Name": "Size", "Scriptability": "Read", @@ -11230,6 +11762,40 @@ } } }, + "FloatCurve": { + "Name": "FloatCurve", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Length": { + "Name": "Length", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "FloorWire": { "Name": "FloorWire", "Tags": [ @@ -12904,6 +13470,19 @@ "Serialization": "Serializes" } } + }, + "TouchControlsEnabled": { + "Name": "TouchControlsEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": {} @@ -13640,7 +14219,9 @@ "DataType": { "Enum": "HumanoidCollisionType" }, - "Tags": [], + "Tags": [ + "Deprecated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -14677,7 +15258,7 @@ }, "DefaultProperties": { "AccessoryBlob": { - "String": "" + "String": "[]" }, "AttributesSerialize": { "BinaryString": "" @@ -14851,6 +15432,23 @@ "Tags": [], "Superclass": "GuiButton", "Properties": { + "ContentImageSize": { + "Name": "ContentImageSize", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "HoverImage": { "Name": "HoverImage", "Scriptability": "ReadWrite", @@ -14958,6 +15556,19 @@ } } }, + "ResampleMode": { + "Name": "ResampleMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ResamplerMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ScaleType": { "Name": "ScaleType", "Scriptability": "ReadWrite", @@ -15111,6 +15722,9 @@ "PressedImage": { "Content": "" }, + "ResampleMode": { + "Enum": 0 + }, "Rotation": { "Float32": 0.0 }, @@ -15295,6 +15909,23 @@ "Tags": [], "Superclass": "GuiLabel", "Properties": { + "ContentImageSize": { + "Name": "ContentImageSize", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Image": { "Name": "Image", "Scriptability": "ReadWrite", @@ -15376,6 +16007,19 @@ } } }, + "ResampleMode": { + "Name": "ResampleMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ResamplerMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ScaleType": { "Name": "ScaleType", "Scriptability": "ReadWrite", @@ -15517,6 +16161,9 @@ ] ] }, + "ResampleMode": { + "Enum": 0 + }, "Rotation": { "Float32": 0.0 }, @@ -15582,6 +16229,306 @@ } } }, + "ImporterBaseSettings": { + "Name": "ImporterBaseSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Id": { + "Name": "Id", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ImportName": { + "Name": "ImportName", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShouldImport": { + "Name": "ShouldImport", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "ImporterGroupSettings": { + "Name": "ImporterGroupSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "ImporterBaseSettings", + "Properties": { + "ImportAsModelAsset": { + "Name": "ImportAsModelAsset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "ImporterJointSettings": { + "Name": "ImporterJointSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "ImporterBaseSettings", + "Properties": {}, + "DefaultProperties": {} + }, + "ImporterMeshSettings": { + "Name": "ImporterMeshSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "ImporterBaseSettings", + "Properties": { + "Dimensions": { + "Name": "Dimensions", + "Scriptability": "Read", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DoubleSided": { + "Name": "DoubleSided", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IgnoreVertexColors": { + "Name": "IgnoreVertexColors", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PolygonCount": { + "Name": "PolygonCount", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "ImporterRootSettings": { + "Name": "ImporterRootSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "ImporterBaseSettings", + "Properties": { + "FileDimensions": { + "Name": "FileDimensions", + "Scriptability": "Read", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ImportAsModelAsset": { + "Name": "ImportAsModelAsset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InvertNegativeFaces": { + "Name": "InvertNegativeFaces", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MergeMeshes": { + "Name": "MergeMeshes", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PolygonCount": { + "Name": "PolygonCount", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ScaleUnit": { + "Name": "ScaleUnit", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "MeshScaleUnit" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WorldForward": { + "Name": "WorldForward", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "NormalId" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WorldUp": { + "Name": "WorldUp", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "NormalId" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ZeroOrigin": { + "Name": "ZeroOrigin", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "ImporterTextureSettings": { + "Name": "ImporterTextureSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "ImporterBaseSettings", + "Properties": {}, + "DefaultProperties": {} + }, "IncrementalPatchBuilder": { "Name": "IncrementalPatchBuilder", "Tags": [ @@ -15875,7 +16822,7 @@ "Name": "Tags", "Scriptability": "Custom", "DataType": { - "Value": "BinaryString" + "Value": "Tags" }, "Tags": [], "Kind": { @@ -16282,7 +17229,7 @@ "KeyframeSequence": { "Name": "KeyframeSequence", "Tags": [], - "Superclass": "Instance", + "Superclass": "AnimationClip", "Properties": { "AuthoredHipHeight": { "Name": "AuthoredHipHeight", @@ -16298,32 +17245,6 @@ "Serialization": "Serializes" } } - }, - "Loop": { - "Name": "Loop", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Priority": { - "Name": "Priority", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "AnimationPriority" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } } }, "DefaultProperties": { @@ -17078,6 +17999,196 @@ } } }, + "LinearVelocity": { + "Name": "LinearVelocity", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "LineDirection": { + "Name": "LineDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LineVelocity": { + "Name": "LineVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxForce": { + "Name": "MaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlaneVelocity": { + "Name": "PlaneVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PrimaryTangentAxis": { + "Name": "PrimaryTangentAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RelativeTo": { + "Name": "RelativeTo", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ActuatorRelativeTo" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SecondaryTangentAxis": { + "Name": "SecondaryTangentAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VectorVelocity": { + "Name": "VectorVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VelocityConstraintMode": { + "Name": "VelocityConstraintMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "VelocityConstraintMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "Color": { + "Int32": 26 + }, + "Enabled": { + "Bool": true + }, + "LineDirection": { + "Vector3": [ + 1.0, + 0.0, + 0.0 + ] + }, + "LineVelocity": { + "Float32": -0.0 + }, + "MaxForce": { + "Float32": 1000.0 + }, + "PlaneVelocity": { + "Vector2": [ + 0.0, + 0.0 + ] + }, + "PrimaryTangentAxis": { + "Vector3": [ + 1.0, + 0.0, + 0.0 + ] + }, + "RelativeTo": { + "Enum": 2 + }, + "SecondaryTangentAxis": { + "Vector3": [ + 0.0, + 1.0, + 0.0 + ] + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "VectorVelocity": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "VelocityConstraintMode": { + "Enum": 2 + }, + "Visible": { + "Bool": false + } + } + }, "LocalScript": { "Name": "LocalScript", "Tags": [], @@ -17571,6 +18682,391 @@ "Properties": {}, "DefaultProperties": {} }, + "MaterialService": { + "Name": "MaterialService", + "Tags": [ + "NotBrowsable", + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "Brick": { + "Name": "Brick", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Cobblestone": { + "Name": "Cobblestone", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Concrete": { + "Name": "Concrete", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CorrodedMetal": { + "Name": "CorrodedMetal", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DiamondPlate": { + "Name": "DiamondPlate", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Fabric": { + "Name": "Fabric", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Foil": { + "Name": "Foil", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Granite": { + "Name": "Granite", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Grass": { + "Name": "Grass", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Ice": { + "Name": "Ice", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Marble": { + "Name": "Marble", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Metal": { + "Name": "Metal", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Pebble": { + "Name": "Pebble", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Plastic": { + "Name": "Plastic", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Sand": { + "Name": "Sand", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Slate": { + "Name": "Slate", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SmoothPlastic": { + "Name": "SmoothPlastic", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Wood": { + "Name": "Wood", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WoodPlanks": { + "Name": "WoodPlanks", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, + "MaterialVariant": { + "Name": "MaterialVariant", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "BaseMaterial": { + "Name": "BaseMaterial", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "Material" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ColorMap": { + "Name": "ColorMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MetalnessMap": { + "Name": "MetalnessMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NormalMap": { + "Name": "NormalMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RoughnessMap": { + "Name": "RoughnessMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StudsPerTile": { + "Name": "StudsPerTile", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "BaseMaterial": { + "Enum": 256 + }, + "ColorMap": { + "Content": "" + }, + "MetalnessMap": { + "Content": "" + }, + "NormalMap": { + "Content": "" + }, + "RoughnessMap": { + "Content": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "StudsPerTile": { + "Float32": 10.0 + }, + "Tags": { + "BinaryString": "" + } + } + }, "MemStorageConnection": { "Name": "MemStorageConnection", "Tags": [ @@ -18046,6 +19542,27 @@ } } }, + "MessageBusConnection": { + "Name": "MessageBusConnection", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "MessageBusService": { + "Name": "MessageBusService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "MessagingService": { "Name": "MessagingService", "Tags": [ @@ -19195,6 +20712,25 @@ }, "DefaultProperties": {} }, + "NewVoiceChatService": { + "Name": "NewVoiceChatService", + "Tags": [ + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "NoCollisionConstraint": { "Name": "NoCollisionConstraint", "Tags": [], @@ -20475,6 +22011,19 @@ } } }, + "Brightness": { + "Name": "Brightness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Color": { "Name": "Color", "Scriptability": "ReadWrite", @@ -20631,6 +22180,58 @@ } } }, + "Shape": { + "Name": "Shape", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ParticleEmitterShape" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShapeInOut": { + "Name": "ShapeInOut", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ParticleEmitterShapeInOut" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShapePartial": { + "Name": "ShapePartial", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShapeStyle": { + "Name": "ShapeStyle", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ParticleEmitterShapeStyle" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Size": { "Name": "Size", "Scriptability": "ReadWrite", @@ -20670,6 +22271,19 @@ } } }, + "Squash": { + "Name": "Squash", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberSequence" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Texture": { "Name": "Texture", "Scriptability": "ReadWrite", @@ -20763,6 +22377,9 @@ "AttributesSerialize": { "BinaryString": "" }, + "Brightness": { + "Float32": 1.0 + }, "Color": { "ColorSequence": { "keypoints": [ @@ -20827,6 +22444,18 @@ 0.0 ] }, + "Shape": { + "Enum": 0 + }, + "ShapeInOut": { + "Enum": 0 + }, + "ShapePartial": { + "Float32": 1.0 + }, + "ShapeStyle": { + "Enum": 0 + }, "Size": { "NumberSequence": { "keypoints": [ @@ -20858,6 +22487,22 @@ 0.0 ] }, + "Squash": { + "NumberSequence": { + "keypoints": [ + { + "time": 0.0, + "value": 0.0, + "envelope": 0.0 + }, + { + "time": 1.0, + "value": 0.0, + "envelope": 0.0 + } + ] + } + }, "Tags": { "BinaryString": "" }, @@ -20918,6 +22563,66 @@ }, "DefaultProperties": {} }, + "PathfindingLink": { + "Name": "PathfindingLink", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Attachment0": { + "Name": "Attachment0", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Attachment1": { + "Name": "Attachment1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsBidirectional": { + "Name": "IsBidirectional", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "IsBidirectional": { + "Bool": true + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "PathfindingModifier": { "Name": "PathfindingModifier", "Tags": [], @@ -20935,6 +22640,19 @@ "Serialization": "Serializes" } } + }, + "PassThrough": { + "Name": "PassThrough", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -20944,6 +22662,9 @@ "ModifierId": { "String": "" }, + "PassThrough": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -20988,8 +22709,8 @@ ], "Superclass": "Instance", "Properties": { - "IsValid": { - "Name": "IsValid", + "AllThreadsPaused": { + "Name": "AllThreadsPaused", "Scriptability": "None", "DataType": { "Value": "Bool" @@ -21022,8 +22743,8 @@ } } }, - "ThreadCount": { - "Name": "ThreadCount", + "ThreadId": { + "Name": "ThreadId", "Scriptability": "None", "DataType": { "Value": "Int32" @@ -21066,23 +22787,6 @@ "Serialization": "DoesNotSerialize" } } - }, - "BreakpointThread": { - "Name": "BreakpointThread", - "Scriptability": "None", - "DataType": { - "Value": "Ref" - }, - "Tags": [ - "Hidden", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } } }, "DefaultProperties": {} @@ -21111,23 +22815,6 @@ "Serialization": "DoesNotSerialize" } } - }, - "ExceptionThread": { - "Name": "ExceptionThread", - "Scriptability": "None", - "DataType": { - "Value": "Ref" - }, - "Tags": [ - "Hidden", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } } }, "DefaultProperties": {} @@ -22200,11 +23887,11 @@ ], "Superclass": "Instance", "Properties": { - "DEPRECATED_SerializedEmulatedPolicyInfo": { - "Name": "DEPRECATED_SerializedEmulatedPolicyInfo", + "CustomPoliciesEnabled": { + "Name": "CustomPoliciesEnabled", "Scriptability": "None", "DataType": { - "Value": "String" + "Value": "Bool" }, "Tags": [ "Hidden" @@ -22260,22 +23947,6 @@ } } }, - "PlayerEmulationEnabled_deprecated": { - "Name": "PlayerEmulationEnabled_deprecated", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "SerializedEmulatedPolicyInfo": { "Name": "SerializedEmulatedPolicyInfo", "Scriptability": "None", @@ -22290,30 +23961,14 @@ "Serialization": "Serializes" } } - }, - "StudioEmulatedCountryRegionCode": { - "Name": "StudioEmulatedCountryRegionCode", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } } }, "DefaultProperties": { "AttributesSerialize": { "BinaryString": "" }, - "DEPRECATED_SerializedEmulatedPolicyInfo": { - "String": "" + "CustomPoliciesEnabled": { + "Bool": false }, "EmulatedCountryCode": { "String": "" @@ -23453,6 +25108,16 @@ } } }, + "ProcessInstancePhysicsService": { + "Name": "ProcessInstancePhysicsService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ProximityPrompt": { "Name": "ProximityPrompt", "Tags": [], @@ -25823,6 +27488,40 @@ } } }, + "RotationCurve": { + "Name": "RotationCurve", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Length": { + "Name": "Length", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "RunService": { "Name": "RunService", "Tags": [ @@ -26107,36 +27806,6 @@ }, "DefaultProperties": {} }, - "ScriptRef": { - "Name": "ScriptRef", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "ScriptRefId": { - "Name": "ScriptRefId", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "ScriptRef", - "Properties": {}, - "DefaultProperties": {} - }, - "ScriptRefPath": { - "Name": "ScriptRefPath", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "ScriptRef", - "Properties": {}, - "DefaultProperties": {} - }, "ScriptService": { "Name": "ScriptService", "Tags": [ @@ -26164,12 +27833,11 @@ "Properties": { "AbsoluteCanvasSize": { "Name": "AbsoluteCanvasSize", - "Scriptability": "None", + "Scriptability": "Read", "DataType": { "Value": "Vector2" }, "Tags": [ - "Hidden", "NotReplicated", "ReadOnly" ], @@ -28435,6 +30103,23 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "ChannelCount": { + "Name": "ChannelCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotBrowsable", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "EmitterSize": { "Name": "EmitterSize", "Scriptability": "ReadWrite", @@ -29356,6 +31041,23 @@ ], "Superclass": "Instance", "Properties": { + "ChannelCount": { + "Name": "ChannelCount", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotBrowsable", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PlaybackLoudness": { "Name": "PlaybackLoudness", "Scriptability": "Read", @@ -29908,6 +31610,170 @@ } } }, + "StackFrame": { + "Name": "StackFrame", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "FrameId": { + "Name": "FrameId", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FrameName": { + "Name": "FrameName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FrameType": { + "Name": "FrameType", + "Scriptability": "None", + "DataType": { + "Enum": "DebuggerFrameType" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Globals": { + "Name": "Globals", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Line": { + "Name": "Line", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Locals": { + "Name": "Locals", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Populated": { + "Name": "Populated", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Script": { + "Name": "Script", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Upvalues": { + "Name": "Upvalues", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "StandalonePluginScripts": { "Name": "StandalonePluginScripts", "Tags": [], @@ -31462,19 +33328,6 @@ } } }, - "DEPRECATED_DisableAccuratePlaySolo": { - "Name": "DEPRECATED_DisableAccuratePlaySolo", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "Debugger Current Line Color": { "Name": "Debugger Current Line Color", "Scriptability": "ReadWrite", @@ -31674,6 +33527,22 @@ } } }, + "EnableOnTypeAutocomplete": { + "Name": "EnableOnTypeAutocomplete", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Error Color": { "Name": "Error Color", "Scriptability": "ReadWrite", @@ -32243,7 +34112,7 @@ ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } }, @@ -32413,6 +34282,19 @@ } } }, + "Set Pivot of Imported Parts": { + "Name": "Set Pivot of Imported Parts", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Show Core GUI in Explorer while Playing": { "Name": "Show Core GUI in Explorer while Playing", "Scriptability": "ReadWrite", @@ -32751,6 +34633,21 @@ } } }, + "EnableTeamCreateStreamingOnLoad": { + "Name": "EnableTeamCreateStreamingOnLoad", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "SrcPlaceId": { "Name": "SrcPlaceId", "Scriptability": "None", @@ -32791,6 +34688,9 @@ "EnableScriptCollabByDefaultOnLoad": { "Bool": false }, + "EnableTeamCreateStreamingOnLoad": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -35646,6 +37546,44 @@ } } }, + "TextChannel": { + "Name": "TextChannel", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, + "TextChatService": { + "Name": "TextChatService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "TextFilterResult": { "Name": "TextFilterResult", "Tags": [ @@ -36117,6 +38055,23 @@ "Properties": {}, "DefaultProperties": {} }, + "TextSource": { + "Name": "TextSource", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "Texture": { "Name": "Texture", "Tags": [], @@ -36237,6 +38192,40 @@ ], "Superclass": "Instance", "Properties": { + "FrameCount": { + "Name": "FrameCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Populated": { + "Name": "Populated", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ThreadId": { "Name": "ThreadId", "Scriptability": "None", @@ -36253,6 +38242,23 @@ "Serialization": "DoesNotSerialize" } } + }, + "ThreadName": { + "Name": "ThreadName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": {} @@ -36822,6 +38828,19 @@ } } }, + "Brightness": { + "Name": "Brightness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Color": { "Name": "Color", "Scriptability": "ReadWrite", @@ -36996,6 +39015,9 @@ "AttributesSerialize": { "BinaryString": "" }, + "Brightness": { + "Float32": 1.0 + }, "Color": { "ColorSequence": { "keypoints": [ @@ -39710,7 +41732,9 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Deprecated" + ], "Kind": { "Canonical": { "Serialization": "DoesNotSerialize" @@ -40063,6 +42087,23 @@ "Properties": {}, "DefaultProperties": {} }, + "Vector3Curve": { + "Name": "Vector3Curve", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "Vector3Value": { "Name": "Vector3Value", "Tags": [], @@ -41235,6 +43276,45 @@ "Properties": {}, "DefaultProperties": {} }, + "VoiceChatService": { + "Name": "VoiceChatService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "VoiceChatState": { + "Name": "VoiceChatState", + "Scriptability": "None", + "DataType": { + "Enum": "VoiceChatState" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "VoiceSource": { "Name": "VoiceSource", "Tags": [ @@ -41874,6 +43954,19 @@ } } }, + "Retargeting": { + "Name": "Retargeting", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AnimatorRetargetingMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "SignalBehavior": { "Name": "SignalBehavior", "Scriptability": "None", @@ -41889,6 +43982,21 @@ } } }, + "StreamOutBehavior": { + "Name": "StreamOutBehavior", + "Scriptability": "None", + "DataType": { + "Enum": "StreamOutBehavior" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "StreamingEnabled": { "Name": "StreamingEnabled", "Scriptability": "ReadWrite", @@ -42022,12 +44130,18 @@ "PhysicsSteppingMethod": { "Enum": 0 }, + "Retargeting": { + "Enum": 0 + }, "SignalBehavior": { "Enum": 0 }, "SourceAssetId": { "Int64": -1 }, + "StreamOutBehavior": { + "Enum": 0 + }, "StreamingEnabled": { "Bool": false }, @@ -42585,6 +44699,14 @@ "Movement": 1 } }, + "AnimatorRetargetingMode": { + "name": "AnimatorRetargetingMode", + "items": { + "Default": 0, + "Disabled": 1, + "Enabled": 2 + } + }, "AppShellActionType": { "name": "AppShellActionType", "items": { @@ -43663,7 +45785,6 @@ "items": { "Automatic": 1, "Direct3D11": 2, - "Direct3D9": 3, "Metal": 5, "NoGraphics": 7, "OpenGL": 4, @@ -44137,6 +46258,14 @@ "Zero": 48 } }, + "KeyInterpolationMode": { + "name": "KeyInterpolationMode", + "items": { + "Constant": 0, + "Cubic": 2, + "Linear": 1 + } + }, "KeywordFilterType": { "name": "KeywordFilterType", "items": { @@ -44280,6 +46409,17 @@ "Enabled": 2 } }, + "MeshScaleUnit": { + "name": "MeshScaleUnit", + "items": { + "CM": 2, + "Foot": 4, + "Inch": 5, + "MM": 3, + "Meter": 1, + "Stud": 0 + } + }, "MeshType": { "name": "MeshType", "items": { @@ -44376,6 +46516,13 @@ "Top": 1 } }, + "OrientationAlignmentMode": { + "name": "OrientationAlignmentMode", + "items": { + "OneAttachment": 0, + "TwoAttachment": 1 + } + }, "OutfitSource": { "name": "OutfitSource", "items": { @@ -44427,6 +46574,30 @@ "Cylinder": 2 } }, + "ParticleEmitterShape": { + "name": "ParticleEmitterShape", + "items": { + "Box": 0, + "Cylinder": 2, + "Disc": 3, + "Sphere": 1 + } + }, + "ParticleEmitterShapeInOut": { + "name": "ParticleEmitterShapeInOut", + "items": { + "InAndOut": 2, + "Inward": 1, + "Outward": 0 + } + }, + "ParticleEmitterShapeStyle": { + "name": "ParticleEmitterShapeStyle", + "items": { + "Surface": 1, + "Volume": 0 + } + }, "ParticleOrientation": { "name": "ParticleOrientation", "items": { @@ -44552,6 +46723,13 @@ "Linear": 0 } }, + "PositionAlignmentMode": { + "name": "PositionAlignmentMode", + "items": { + "OneAttachment": 0, + "TwoAttachment": 1 + } + }, "PrivilegeType": { "name": "PrivilegeType", "items": { @@ -44666,6 +46844,13 @@ "psnr": 0 } }, + "ResamplerMode": { + "name": "ResamplerMode", + "items": { + "Default": 0, + "Pixelated": 1 + } + }, "ReturnKeyType": { "name": "ReturnKeyType", "items": { @@ -44730,6 +46915,17 @@ "LinearSquare": 2 } }, + "RotationOrder": { + "name": "RotationOrder", + "items": { + "XYZ": 0, + "XZY": 1, + "YXZ": 3, + "YZX": 2, + "ZXY": 4, + "ZYX": 5 + } + }, "RotationType": { "name": "RotationType", "items": { @@ -44891,6 +47087,14 @@ "Poison": 0 } }, + "StreamOutBehavior": { + "name": "StreamOutBehavior", + "items": { + "Default": 0, + "LowMemory": 1, + "Opportunistic": 2 + } + }, "StreamingPauseMode": { "name": "StreamingPauseMode", "items": { @@ -44911,11 +47115,11 @@ "name": "StudioDataModelType", "items": { "Edit": 0, - "None": 6, - "PlayClient": 2, - "PlayServer": 3, - "RobloxPlugin": 4, - "UserPlugin": 5 + "None": 5, + "PlayClient": 1, + "PlayServer": 2, + "RobloxPlugin": 3, + "UserPlugin": 4 } }, "StudioScriptEditorColorCategories": { @@ -45454,6 +47658,14 @@ "VirtualThumbstick": 1 } }, + "VelocityConstraintMode": { + "name": "VelocityConstraintMode", + "items": { + "Line": 0, + "Plane": 1, + "Vector": 2 + } + }, "VerticalAlignment": { "name": "VerticalAlignment", "items": { @@ -45496,6 +47708,18 @@ "Recording": 1 } }, + "VoiceChatState": { + "name": "VoiceChatState", + "items": { + "Ended": 5, + "Failed": 6, + "Idle": 0, + "Joined": 3, + "Joining": 1, + "JoiningRetry": 2, + "Leaving": 4 + } + }, "WaterDirection": { "name": "WaterDirection", "items": { diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 8e606272..cdd9e2a3 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {7, 0, 0, "-rc.2"}, + version = {7, 0, 0, "-rc.3"}, expectedServerVersionString = "7.0 or newer", protocolVersion = 4, defaultHost = "localhost", From e136529ff07fe03f35d03b59bad44028099d16cd Mon Sep 17 00:00:00 2001 From: Umbreon Date: Thu, 28 Oct 2021 06:09:20 +0100 Subject: [PATCH 1175/1504] Add a check to getProperty for unknown properties. (#493) --- plugin/src/Reconciler/getProperty.lua | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/plugin/src/Reconciler/getProperty.lua b/plugin/src/Reconciler/getProperty.lua index bc67525c..cd5c11f3 100644 --- a/plugin/src/Reconciler/getProperty.lua +++ b/plugin/src/Reconciler/getProperty.lua @@ -40,6 +40,13 @@ local function getProperty(instance, propertyName) }) end + if err.kind == RbxDom.Error.Kind.Roblox and err.extra:find("is not a valid member of") then + return false, Error.new(Error.UnknownProperty, { + className = instance.ClassName, + propertyName = propertyName, + }) + end + return false, Error.new(Error.OtherPropertyError, { className = instance.ClassName, propertyName = propertyName, From 173dc12cb38adc50993c54790ab927c8bbc074f2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Nov 2021 17:05:45 -0500 Subject: [PATCH 1176/1504] Improve warning and debug output in plugin --- plugin/src/Reconciler/applyPatch.lua | 2 +- plugin/src/Reconciler/diff.lua | 8 ++++++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/plugin/src/Reconciler/applyPatch.lua b/plugin/src/Reconciler/applyPatch.lua index 345a3bf7..4ecf3e1f 100644 --- a/plugin/src/Reconciler/applyPatch.lua +++ b/plugin/src/Reconciler/applyPatch.lua @@ -63,7 +63,7 @@ local function applyPatch(instanceMap, patch) local failedToReify = reify(instanceMap, patch.added, id, parentInstance) if not PatchSet.isEmpty(failedToReify) then - Log.debug("Failed to reify as part of applying a patch: {}", failedToReify) + Log.debug("Failed to reify as part of applying a patch: {:#?}", failedToReify) PatchSet.assign(unappliedPatch, failedToReify) end end diff --git a/plugin/src/Reconciler/diff.lua b/plugin/src/Reconciler/diff.lua index 14e04fb8..e4cb7d88 100644 --- a/plugin/src/Reconciler/diff.lua +++ b/plugin/src/Reconciler/diff.lua @@ -75,9 +75,13 @@ local function diff(instanceMap, virtualInstances, rootId) changedProperties[propertyName] = virtualValue end else - -- virtualValue can be empty in certain cases, and this may print out nil to the user. local propertyType = next(virtualValue) - Log.warn("Failed to decode property of type {}", propertyType) + Log.warn( + "Failed to decode property {}.{}. Encoded property was: {:#?}", + virtualInstance.ClassName, + propertyName, + virtualValue + ) end else local err = existingValueOrErr From 8b54bf0ba1f95cc9106b56ae767bb346d3431b4c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Nov 2021 17:15:58 -0500 Subject: [PATCH 1177/1504] Improve error when file is not found --- src/snapshot_middleware/project.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 673def0f..6c855eb8 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -80,13 +80,13 @@ pub fn snapshot_project_node( if let Some(path) = &node.path { // If the path specified in the project is relative, we assume it's // relative to the folder that the project is in, project_folder. - let path = if path.is_relative() { + let full_path = if path.is_relative() { Cow::Owned(project_folder.join(path)) } else { Cow::Borrowed(path) }; - if let Some(snapshot) = snapshot_from_vfs(context, vfs, &path)? { + if let Some(snapshot) = snapshot_from_vfs(context, vfs, &full_path)? { class_name_from_path = Some(snapshot.class_name); // Properties from the snapshot are pulled in unchanged, and @@ -107,9 +107,14 @@ pub fn snapshot_project_node( // on. metadata = snapshot.metadata; } else { - // TODO: Should this issue an error instead? - log::warn!( - "$path referred to a path that could not be turned into an instance by Rojo" + anyhow::bail!( + "Rojo project referred to a file using $path that could not be turned into a Roblox Instance by Rojo.\n\ + Check that the file exists and is a file type known by Rojo.\n\ + \n\ + Project path: {}\n\ + File $path: {}", + project_path.display(), + path.display(), ); } } From 5fa63733fd58d2b7a388001ddaf2c8d085afcc2f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Nov 2021 17:38:36 -0500 Subject: [PATCH 1178/1504] Factor out property filtering code to simplify web server --- src/snapshot_middleware/lua.rs | 4 +- src/web/api.rs | 45 ++------------------ src/web/interface.rs | 75 +++++++++++++++++++++++++++++----- 3 files changed, 71 insertions(+), 53 deletions(-) diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index d11e72c6..02bbc51d 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -72,8 +72,8 @@ pub fn snapshot_lua_init( anyhow::bail!( "init.lua, init.server.lua, and init.client.lua can \ only be used if the instance produced by the containing \ - directory would be a Folder.\n\n\ - + directory would be a Folder.\n\ + \n\ The directory {} turned into an instance of class {}.", folder_path.display(), dir_snapshot.class_name diff --git a/src/web/api.rs b/src/web/api.rs index 97624c7e..93b1ccb0 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -11,9 +11,9 @@ use crate::{ snapshot::{InstanceWithMeta, PatchSet, PatchUpdate}, web::{ interface::{ - ErrorResponse, Instance, InstanceMetadata as WebInstanceMetadata, InstanceUpdate, - OpenResponse, ReadResponse, ServerInfoResponse, SubscribeMessage, SubscribeResponse, - WriteRequest, WriteResponse, PROTOCOL_VERSION, SERVER_VERSION, + ErrorResponse, Instance, OpenResponse, ReadResponse, ServerInfoResponse, + SubscribeMessage, SubscribeResponse, WriteRequest, WriteResponse, PROTOCOL_VERSION, + SERVER_VERSION, }, util::{json, json_ok}, }, @@ -99,44 +99,7 @@ impl ApiService { let api_messages = messages .into_iter() - .map(|message| { - let removed = message.removed; - - let mut added = HashMap::new(); - for id in message.added { - let instance = tree.get_instance(id).unwrap(); - added.insert(id, Instance::from_rojo_instance(instance)); - - for instance in tree.descendants(id) { - added.insert(instance.id(), Instance::from_rojo_instance(instance)); - } - } - - let updated = message - .updated - .into_iter() - .map(|update| { - let changed_metadata = update - .changed_metadata - .as_ref() - .map(WebInstanceMetadata::from_rojo_metadata); - - InstanceUpdate { - id: update.id, - changed_name: update.changed_name, - changed_class_name: update.changed_class_name, - changed_properties: update.changed_properties, - changed_metadata, - } - }) - .collect(); - - SubscribeMessage { - removed, - added, - updated, - } - }) + .map(|patch| SubscribeMessage::from_patch_update(&tree, patch)) .collect(); json_ok(SubscribeResponse { diff --git a/src/web/interface.rs b/src/web/interface.rs index f5bda237..28005057 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -7,12 +7,14 @@ use std::{ collections::{HashMap, HashSet}, }; -use rbx_dom_weak::types::{Ref, Variant}; +use rbx_dom_weak::types::{Ref, Variant, VariantType}; use serde::{Deserialize, Serialize}; use crate::{ session_id::SessionId, - snapshot::{InstanceMetadata as RojoInstanceMetadata, InstanceWithMeta}, + snapshot::{ + AppliedPatchSet, InstanceMetadata as RojoInstanceMetadata, InstanceWithMeta, RojoTree, + }, }; /// Server version to report over the API, not exposed outside this crate. @@ -30,6 +32,53 @@ pub struct SubscribeMessage<'a> { pub updated: Vec, } +impl<'a> SubscribeMessage<'a> { + pub(crate) fn from_patch_update(tree: &'a RojoTree, patch: AppliedPatchSet) -> Self { + let removed = patch.removed; + + let mut added = HashMap::new(); + for id in patch.added { + let instance = tree.get_instance(id).unwrap(); + added.insert(id, Instance::from_rojo_instance(instance)); + + for instance in tree.descendants(id) { + added.insert(instance.id(), Instance::from_rojo_instance(instance)); + } + } + + let updated = patch + .updated + .into_iter() + .map(|update| { + let changed_metadata = update + .changed_metadata + .as_ref() + .map(InstanceMetadata::from_rojo_metadata); + + let changed_properties = update + .changed_properties + .into_iter() + .filter(|(_key, value)| property_filter(value.as_ref())) + .collect(); + + InstanceUpdate { + id: update.id, + changed_name: update.changed_name, + changed_class_name: update.changed_class_name, + changed_properties, + changed_metadata, + } + }) + .collect(); + + Self { + removed, + added, + updated, + } + } +} + #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct InstanceUpdate { @@ -75,14 +124,8 @@ impl<'a> Instance<'a> { let properties = source .properties() .iter() - .filter_map(|(key, value)| { - // SharedString values can't be serialized via Serde - if matches!(value, Variant::SharedString(_)) { - return None; - } - - Some((key.clone(), Cow::Borrowed(value))) - }) + .filter(|(_key, value)| property_filter(Some(value))) + .map(|(key, value)| (key.clone(), Cow::Borrowed(value))) .collect(); Instance { @@ -97,6 +140,18 @@ impl<'a> Instance<'a> { } } +fn property_filter(value: Option<&Variant>) -> bool { + let ty = value.map(|value| value.ty()); + + // Lua can't do anything with SharedString values. They also can't be + // serialized directly by Serde! + if ty == Some(VariantType::SharedString) { + return false; + } + + return true; +} + /// Response body from /api/rojo #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] From da25c80d0b083ac78839d6a0dbe7135bb03711e5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Nov 2021 17:50:40 -0500 Subject: [PATCH 1179/1504] Add support for CFrame shorthand. Fixes #430. --- ...o_end__tests__build__unresolved_values.snap | 14 ++++++++++++++ .../unresolved_values/default.project.json | 8 +++++++- src/resolution.rs | 18 +++++++++++++++++- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__unresolved_values.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__unresolved_values.snap index 073b3074..8b9eac0e 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__unresolved_values.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__unresolved_values.snap @@ -32,6 +32,20 @@ expression: contents Color + + 1 + 2 + 3 + 0 + 1 + 0 + 0 + 0 + 1 + 1 + 0 + 0 + 8404992 diff --git a/rojo-test/build-tests/unresolved_values/default.project.json b/rojo-test/build-tests/unresolved_values/default.project.json index d5f5d534..aecca203 100644 --- a/rojo-test/build-tests/unresolved_values/default.project.json +++ b/rojo-test/build-tests/unresolved_values/default.project.json @@ -14,7 +14,13 @@ "Color": { "$className": "Part", "$properties": { - "Color": [0.5, 0.25, 0] + "Color": [0.5, 0.25, 0], + "CFrame": [ + 1, 2, 3, + 0, 1, 0, + 0, 0, 1, + 1, 0, 0 + ] } }, diff --git a/src/resolution.rs b/src/resolution.rs index a1e1e0ee..8f25d992 100644 --- a/src/resolution.rs +++ b/src/resolution.rs @@ -1,7 +1,9 @@ use std::borrow::Borrow; use anyhow::format_err; -use rbx_dom_weak::types::{Color3, Content, Enum, Tags, Variant, VariantType, Vector2, Vector3}; +use rbx_dom_weak::types::{ + CFrame, Color3, Content, Enum, Matrix3, Tags, Variant, VariantType, Vector2, Vector3, +}; use rbx_reflection::{DataType, PropertyDescriptor}; use serde::{Deserialize, Serialize}; @@ -37,6 +39,7 @@ pub enum AmbiguousValue { Array2([f64; 2]), Array3([f64; 3]), Array4([f64; 4]), + Array12([f64; 12]), } impl AmbiguousValue { @@ -113,6 +116,18 @@ impl AmbiguousValue { Ok(Color3::new(value[0] as f32, value[1] as f32, value[2] as f32).into()) } + (VariantType::CFrame, AmbiguousValue::Array12(value)) => { + let value = value.map(|v| v as f32); + let pos = Vector3::new(value[0], value[1], value[2]); + let orientation = Matrix3::new( + Vector3::new(value[3], value[4], value[5]), + Vector3::new(value[6], value[7], value[8]), + Vector3::new(value[9], value[10], value[11]), + ); + + Ok(CFrame::new(pos, orientation).into()) + } + (_, unresolved) => Err(format_err!( "Wrong type of value for property {}.{}. Expected {:?}, got {}", class_name, @@ -138,6 +153,7 @@ impl AmbiguousValue { AmbiguousValue::Array2(_) => "an array of two numbers", AmbiguousValue::Array3(_) => "an array of three numbers", AmbiguousValue::Array4(_) => "an array of four numbers", + AmbiguousValue::Array12(_) => "an array of twelve numbers", } } } From 9904d94e4c3787e54f4b323c957ffef0906968dc Mon Sep 17 00:00:00 2001 From: Umbreon Date: Sat, 20 Nov 2021 22:51:38 +0000 Subject: [PATCH 1180/1504] Remember sync connection settings. (#500) --- plugin/src/App/StatusPages/NotConnected.lua | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/plugin/src/App/StatusPages/NotConnected.lua b/plugin/src/App/StatusPages/NotConnected.lua index 10988424..083f22c2 100644 --- a/plugin/src/App/StatusPages/NotConnected.lua +++ b/plugin/src/App/StatusPages/NotConnected.lua @@ -14,6 +14,8 @@ local PORT_WIDTH = 74 local DIVIDER_WIDTH = 1 local HOST_OFFSET = 12 +local lastHost, lastPort + local e = Roact.createElement local function AddressEntry(props) @@ -24,7 +26,7 @@ local function AddressEntry(props) layoutOrder = props.layoutOrder, }, { Host = e("TextBox", { - Text = "", + Text = lastHost or "", Font = Enum.Font.Code, TextSize = 18, TextColor3 = theme.AddressEntry.TextColor, @@ -43,7 +45,7 @@ local function AddressEntry(props) }), Port = e("TextBox", { - Text = "", + Text = lastPort or "", Font = Enum.Font.Code, TextSize = 18, TextColor3 = theme.AddressEntry.TextColor, @@ -121,6 +123,9 @@ function NotConnectedPage:render() local hostText = self.hostRef.current.Text local portText = self.portRef.current.Text + lastHost = hostText + lastPort = portText + self.props.onConnect( #hostText > 0 and hostText or Config.defaultHost, #portText > 0 and portText or Config.defaultPort From 8461339e9a9d3b00fa37307acc7a503ba70a52b4 Mon Sep 17 00:00:00 2001 From: Blake Mealey Date: Sat, 20 Nov 2021 14:53:22 -0800 Subject: [PATCH 1181/1504] Add note for git submodules (#495) --- CONTRIBUTING.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 99abebfb..75fa762d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -29,6 +29,11 @@ Sometimes there's something that Rojo doesn't do that it probably should. Please file issues and we'll try to help figure out what the best way forward is. +## Local Development Gotchas + +If your build fails with "Error: failed to open file `D:\code\rojo\plugin\modules\roact\src`" you need to update your Git submodules. +Run the command and try building again: `git submodule update --init --recursive`. + ## Pushing a Rojo Release The Rojo release process is pretty manual right now. If you need to do it, here's how: @@ -51,4 +56,4 @@ The Rojo release process is pretty manual right now. If you need to do it, here' * Update the leading text with a summary about the release * Paste the changelog notes (as-is!) from [`CHANGELOG.md`](CHANGELOG.md) * Write a small summary of each major feature - * Attach release artifacts from GitHub Actions for each platform \ No newline at end of file + * Attach release artifacts from GitHub Actions for each platform From 1d9845a6cb9da17df1933dd0f1991f9c1892b7bc Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Nov 2021 18:06:12 -0500 Subject: [PATCH 1182/1504] Update dependencies --- Cargo.lock | 148 ++--- plugin/rbx_dom_lua/database.json | 903 ++++++++++++++++++++++++++++--- 2 files changed, 908 insertions(+), 143 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ee1fae56..a9088c14 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.16.0" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e61f2b7f93d2c7d2b08263acaa4a363b3e276806c68af6134c44f523bf1aacd" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" dependencies = [ "gimli", ] @@ -46,9 +46,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.44" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" +checksum = "38d9ff5d688f1c13395289f67db01d4826b46dd694e7580accdc3e8430f2d98e" [[package]] name = "arrayref" @@ -87,9 +87,9 @@ checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" [[package]] name = "backtrace" -version = "0.3.61" +version = "0.3.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7a905d892734eea339e896738c14b9afce22b5318f64b951e70bf3844419b01" +checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" dependencies = [ "addr2line", "cc", @@ -180,9 +180,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.7.1" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538" +checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" [[package]] name = "byte-tools" @@ -224,9 +224,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" +checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" [[package]] name = "cfg-if" @@ -556,9 +556,9 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "embed-resource" -version = "1.6.4" +version = "1.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "254a67531cc22d81bf92a24358a1dfa3d3b30f8d326fed8c5780eb6f2e5c784f" +checksum = "85505eb239fc952b300f29f0556d2d884082a83566768d980278d8faf38c780d" dependencies = [ "cc", "vswhom", @@ -573,9 +573,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.28" +version = "0.8.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" +checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" dependencies = [ "cfg-if 1.0.0", ] @@ -609,7 +609,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.30", + "proc-macro2 1.0.32", "quote 1.0.10", "syn", "synstructure", @@ -795,7 +795,7 @@ checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" dependencies = [ "autocfg 1.0.1", "proc-macro-hack", - "proc-macro2 1.0.30", + "proc-macro2 1.0.32", "quote 1.0.10", "syn", ] @@ -866,9 +866,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.25.0" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0a01e0497841a3b2db4f8afa483cce65f7e96a3498bd6c541734792aeac8fe7" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" [[package]] name = "globset" @@ -903,9 +903,9 @@ dependencies = [ [[package]] name = "half" -version = "1.8.0" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac5956d4e63858efaec57e0d6c1c2f6a41e1487f830314a324ccd7e2223a7ca0" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hashbrown" @@ -973,9 +973,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5" +checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" dependencies = [ "bytes 1.1.0", "http 0.2.5", @@ -990,9 +990,9 @@ checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" [[package]] name = "httpdate" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "humantime" @@ -1032,22 +1032,22 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.13" +version = "0.14.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593" +checksum = "436ec0091e4f20e655156a30a0df3770fe2900aa301e548e08446ec794b6953c" dependencies = [ "bytes 1.1.0", "futures-channel", "futures-core", "futures-util", "http 0.2.5", - "http-body 0.4.3", + "http-body 0.4.4", "httparse", "httpdate", "itoa", "pin-project-lite", "socket2", - "tokio 1.12.0", + "tokio 1.14.0", "tower-service", "tracing", "want 0.3.0", @@ -1198,9 +1198,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.103" +version = "0.2.108" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" +checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" [[package]] name = "linked-hash-map" @@ -1345,9 +1345,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.13" +version = "0.7.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" +checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" dependencies = [ "libc", "log", @@ -1466,9 +1466,9 @@ dependencies = [ [[package]] name = "object" -version = "0.26.2" +version = "0.27.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39f37e50073ccad23b6d09bcb5b263f4e76d3bb6038e4a3c08e52162ffa8abc2" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" dependencies = [ "memchr", ] @@ -1503,9 +1503,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.36" +version = "0.10.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a" +checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -1523,9 +1523,9 @@ checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" [[package]] name = "openssl-sys" -version = "0.9.67" +version = "0.9.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69df2d8dfc6ce3aaf44b40dec6f487d5a886516cf6879c49e98e0710f310a058" +checksum = "7df13d165e607909b363a4757a6f133f8a818a74e9d3a98d09c6128e15fa4c73" dependencies = [ "autocfg 1.0.1", "cc", @@ -1571,9 +1571,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf547ad0c65e31259204bd90935776d1c693cec2f4ff7abb7a1bbbd40dfe58" +checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" [[package]] name = "percent-encoding" @@ -1614,7 +1614,7 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.30", + "proc-macro2 1.0.32", "quote 1.0.10", "syn", ] @@ -1644,9 +1644,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.20" +version = "0.3.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb" +checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" [[package]] name = "plotters" @@ -1678,9 +1678,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3ca011bd0129ff4ae15cd04c4eef202cadf6c51c21e47aba319b4e0501db741" +checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" [[package]] name = "pretty_assertions" @@ -1701,7 +1701,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.30", + "proc-macro2 1.0.32", "quote 1.0.10", "syn", "version_check", @@ -1713,7 +1713,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.30", + "proc-macro2 1.0.32", "quote 1.0.10", "version_check", ] @@ -1741,9 +1741,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.30" +version = "1.0.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edc3358ebc67bc8b7fa0c007f945b0b18226f78437d61bec735a9eb96b61ee70" +checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" dependencies = [ "unicode-xid 0.2.2", ] @@ -1773,7 +1773,7 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" dependencies = [ - "proc-macro2 1.0.30", + "proc-macro2 1.0.32", ] [[package]] @@ -2024,9 +2024,9 @@ dependencies = [ [[package]] name = "rbx_reflection_database" -version = "0.2.2+roblox-498" +version = "0.2.3+roblox-503" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e459dc87be8464122ad3bb722a562ddae8e811bb4a6b7809eaa1fac220cf30" +checksum = "13f720dca247c34e34f73f155bb46e7aa532f1755d5ee8ef77c76a161c7e18d8" dependencies = [ "lazy_static", "rbx_reflection", @@ -2248,7 +2248,7 @@ dependencies = [ "futures 0.3.17", "globset", "humantime", - "hyper 0.14.13", + "hyper 0.14.15", "insta", "jod-thread", "lazy_static", @@ -2277,7 +2277,7 @@ dependencies = [ "tempfile", "termcolor", "thiserror", - "tokio 1.12.0", + "tokio 1.14.0", "uuid 0.8.2", "walkdir", "winreg 0.9.0", @@ -2415,16 +2415,16 @@ version = "1.0.130" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" dependencies = [ - "proc-macro2 1.0.30", + "proc-macro2 1.0.32", "quote 1.0.10", "syn", ] [[package]] name = "serde_json" -version = "1.0.68" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" +checksum = "063bf466a64011ac24040a49009724ee60a57da1b437617ceb32e53ad61bfb19" dependencies = [ "itoa", "ryu", @@ -2524,9 +2524,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.23" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf9d950ef167e25e0bdb073cf1d68e9ad2795ac826f2f3f59647817cf23c0bfa" +checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" dependencies = [ "clap", "lazy_static", @@ -2535,13 +2535,13 @@ dependencies = [ [[package]] name = "structopt-derive" -version = "0.4.16" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "134d838a2c9943ac3125cf6df165eda53493451b719f3255b2a26b85f772d0ba" +checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.30", + "proc-macro2 1.0.32", "quote 1.0.10", "syn", ] @@ -2554,11 +2554,11 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "syn" -version = "1.0.80" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d010a1623fbd906d51d650a9916aaefc05ffa0e4053ff7fe601167f3e715d194" +checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" dependencies = [ - "proc-macro2 1.0.30", + "proc-macro2 1.0.32", "quote 1.0.10", "unicode-xid 0.2.2", ] @@ -2569,7 +2569,7 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.30", + "proc-macro2 1.0.32", "quote 1.0.10", "syn", "unicode-xid 0.2.2", @@ -2632,7 +2632,7 @@ version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" dependencies = [ - "proc-macro2 1.0.30", + "proc-macro2 1.0.32", "quote 1.0.10", "syn", ] @@ -2660,9 +2660,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7" +checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" dependencies = [ "tinyvec_macros", ] @@ -2694,13 +2694,13 @@ dependencies = [ [[package]] name = "tokio" -version = "1.12.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc" +checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" dependencies = [ "autocfg 1.0.1", "libc", - "mio 0.7.13", + "mio 0.7.14", "num_cpus", "pin-project-lite", "winapi 0.3.9", @@ -3064,7 +3064,7 @@ dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.30", + "proc-macro2 1.0.32", "quote 1.0.10", "syn", "wasm-bindgen-shared", @@ -3086,7 +3086,7 @@ version = "0.2.78" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" dependencies = [ - "proc-macro2 1.0.30", + "proc-macro2 1.0.32", "quote 1.0.10", "syn", "wasm-bindgen-backend", diff --git a/plugin/rbx_dom_lua/database.json b/plugin/rbx_dom_lua/database.json index 4fd4d431..d15b16e9 100644 --- a/plugin/rbx_dom_lua/database.json +++ b/plugin/rbx_dom_lua/database.json @@ -1,9 +1,9 @@ { "Version": [ 0, - 498, + 503, 0, - 4980398 + 5030338 ], "Classes": { "ABTestService": { @@ -836,6 +836,17 @@ }, "DefaultProperties": {} }, + "AnimationClipProvider": { + "Name": "AnimationClipProvider", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "AnimationController": { "Name": "AnimationController", "Tags": [], @@ -2373,19 +2384,6 @@ } } }, - "MaterialVariant": { - "Name": "MaterialVariant", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "Orientation": { "Name": "Orientation", "Scriptability": "ReadWrite", @@ -4877,6 +4875,22 @@ } } }, + "ContinueExecution": { + "Name": "ContinueExecution", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Enabled": { "Name": "Enabled", "Scriptability": "None", @@ -4980,6 +4994,17 @@ }, "DefaultProperties": {} }, + "BreakpointManager": { + "Name": "BreakpointManager", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "BrickColorValue": { "Name": "BrickColorValue", "Tags": [], @@ -6576,6 +6601,16 @@ } } }, + "ConfigureServerService": { + "Name": "ConfigureServerService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Constraint": { "Name": "Constraint", "Tags": [ @@ -7959,6 +7994,17 @@ }, "DefaultProperties": {} }, + "DataModelPatchService": { + "Name": "DataModelPatchService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "DataModelSession": { "Name": "DataModelSession", "Tags": [ @@ -8849,6 +8895,17 @@ }, "DefaultProperties": {} }, + "DebuggerUIService": { + "Name": "DebuggerUIService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "DebuggerVariable": { "Name": "DebuggerVariable", "Tags": [ @@ -13717,6 +13774,128 @@ "Properties": {}, "DefaultProperties": {} }, + "Highlight": { + "Name": "Highlight", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "DepthMode": { + "Name": "DepthMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "HighlightDepthMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FillColor": { + "Name": "FillColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FillTransparency": { + "Name": "FillTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OutlineColor": { + "Name": "OutlineColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OutlineTransparency": { + "Name": "OutlineTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "DepthMode": { + "Enum": 0 + }, + "Enabled": { + "Bool": true + }, + "FillColor": { + "Color3": [ + 1.0, + 0.0, + 0.0 + ] + }, + "FillTransparency": { + "Float32": 0.5 + }, + "OutlineColor": { + "Color3": [ + 1.0, + 1.0, + 1.0 + ] + }, + "OutlineTransparency": { + "Float32": 0.0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "HingeConstraint": { "Name": "HingeConstraint", "Tags": [], @@ -16290,6 +16469,19 @@ ], "Superclass": "ImporterBaseSettings", "Properties": { + "Anchored": { + "Name": "Anchored", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ImportAsModelAsset": { "Name": "ImportAsModelAsset", "Scriptability": "ReadWrite", @@ -16302,6 +16494,19 @@ "Serialization": "Serializes" } } + }, + "InsertInWorkspace": { + "Name": "InsertInWorkspace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": {} @@ -16324,6 +16529,19 @@ ], "Superclass": "ImporterBaseSettings", "Properties": { + "Anchored": { + "Name": "Anchored", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Dimensions": { "Name": "Dimensions", "Scriptability": "Read", @@ -16393,6 +16611,19 @@ ], "Superclass": "ImporterBaseSettings", "Properties": { + "Anchored": { + "Name": "Anchored", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "FileDimensions": { "Name": "FileDimensions", "Scriptability": "Read", @@ -16422,6 +16653,19 @@ } } }, + "InsertInWorkspace": { + "Name": "InsertInWorkspace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "InvertNegativeFaces": { "Name": "InvertNegativeFaces", "Scriptability": "ReadWrite", @@ -16464,6 +16708,19 @@ } } }, + "RigType": { + "Name": "RigType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RigType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ScaleUnit": { "Name": "ScaleUnit", "Scriptability": "ReadWrite", @@ -16502,19 +16759,6 @@ "Serialization": "Serializes" } } - }, - "ZeroOrigin": { - "Name": "ZeroOrigin", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } } }, "DefaultProperties": {} @@ -16526,7 +16770,24 @@ "NotReplicated" ], "Superclass": "ImporterBaseSettings", - "Properties": {}, + "Properties": { + "FilePath": { + "Name": "FilePath", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, "DefaultProperties": {} }, "IncrementalPatchBuilder": { @@ -18443,6 +18704,53 @@ } } }, + "LodDataEntity": { + "Name": "LodDataEntity", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "EntityLodEnabled": { + "Name": "EntityLodEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "LodDataService": { + "Name": "LodDataService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "LogService": { "Name": "LogService", "Tags": [ @@ -18519,6 +18827,17 @@ } } }, + "LuauScriptAnalyzerService": { + "Name": "LuauScriptAnalyzerService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ManualGlue": { "Name": "ManualGlue", "Tags": [], @@ -19574,6 +19893,180 @@ "Properties": {}, "DefaultProperties": {} }, + "MetaBreakpoint": { + "Name": "MetaBreakpoint", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Condition": { + "Name": "Condition", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ContinueExecution": { + "Name": "ContinueExecution", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Id": { + "Name": "Id", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsLogpoint": { + "Name": "IsLogpoint", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Line": { + "Name": "Line", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LogMessage": { + "Name": "LogMessage", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Script": { + "Name": "Script", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Valid": { + "Name": "Valid", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "MetaBreakpointContext": { + "Name": "MetaBreakpointContext", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Model": { "Name": "Model", "Tags": [], @@ -20712,25 +21205,6 @@ }, "DefaultProperties": {} }, - "NewVoiceChatService": { - "Name": "NewVoiceChatService", - "Tags": [ - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "AttributesSerialize": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, "NoCollisionConstraint": { "Name": "NoCollisionConstraint", "Tags": [], @@ -21245,6 +21719,17 @@ "Properties": {}, "DefaultProperties": {} }, + "PackageUIService": { + "Name": "PackageUIService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Pages": { "Name": "Pages", "Tags": [ @@ -23251,6 +23736,32 @@ } } }, + "Plane": { + "Name": "Plane", + "Tags": [], + "Superclass": "Constraint", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "Color": { + "Int32": 194 + }, + "Enabled": { + "Bool": true + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "Visible": { + "Bool": false + } + } + }, "Platform": { "Name": "Platform", "Tags": [ @@ -25116,7 +25627,17 @@ ], "Superclass": "Instance", "Properties": {}, - "DefaultProperties": {} + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } }, "ProximityPrompt": { "Name": "ProximityPrompt", @@ -27705,6 +28226,17 @@ } } }, + "ScriptChangeService": { + "Name": "ScriptChangeService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ScriptContext": { "Name": "ScriptContext", "Tags": [ @@ -28027,6 +28559,22 @@ } } }, + "ScrollVelocity": { + "Name": "ScrollVelocity", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ScrollingDirection": { "Name": "ScrollingDirection", "Scriptability": "ReadWrite", @@ -32478,18 +33026,19 @@ } } }, - "LoadCharacterLayeredClothing": { - "Name": "LoadCharacterLayeredClothing", + "LoadCharacterLayeredClothing ": { + "Name": "LoadCharacterLayeredClothing ", "Scriptability": "None", "DataType": { "Enum": "LoadCharacterLayeredClothing" }, "Tags": [ + "NotReplicated", "NotScriptable" ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -32644,9 +33193,6 @@ "LoadCharacterAppearance": { "Bool": true }, - "LoadCharacterLayeredClothing": { - "Enum": 0 - }, "NameDisplayDistance": { "Float32": 100.0 }, @@ -33475,6 +34021,19 @@ } } }, + "Enable Scrollbar Markers": { + "Name": "Enable Scrollbar Markers", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Enable Signature Help": { "Name": "Enable Signature Help", "Scriptability": "None", @@ -34610,6 +35169,17 @@ }, "DefaultProperties": {} }, + "StudioAssetService": { + "Name": "StudioAssetService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "StudioData": { "Name": "StudioData", "Tags": [ @@ -34716,6 +35286,17 @@ "Properties": {}, "DefaultProperties": {} }, + "StudioScriptDebugEventListener": { + "Name": "StudioScriptDebugEventListener", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "StudioService": { "Name": "StudioService", "Tags": [ @@ -35802,6 +36383,28 @@ } } }, + "TemporaryCageMeshProvider": { + "Name": "TemporaryCageMeshProvider", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "TemporaryScriptService": { + "Name": "TemporaryScriptService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Terrain": { "Name": "Terrain", "Tags": [ @@ -36463,6 +37066,22 @@ } } }, + "ContentText": { + "Name": "ContentText", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "CursorPosition": { "Name": "CursorPosition", "Scriptability": "ReadWrite", @@ -37089,6 +37708,22 @@ "Tags": [], "Superclass": "GuiButton", "Properties": { + "ContentText": { + "Name": "ContentText", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Font": { "Name": "Font", "Scriptability": "ReadWrite", @@ -37599,6 +38234,22 @@ "Tags": [], "Superclass": "GuiLabel", "Properties": { + "ContentText": { + "Name": "ContentText", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Font": { "Name": "Font", "Scriptability": "ReadWrite", @@ -38057,20 +38708,42 @@ }, "TextSource": { "Name": "TextSource", - "Tags": [], + "Tags": [ + "NotCreatable" + ], "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "AttributesSerialize": { - "BinaryString": "" + "Properties": { + "CanSend": { + "Name": "CanSend", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" + "UserId": { + "Name": "UserId", + "Scriptability": "Read", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } - } + }, + "DefaultProperties": {} }, "Texture": { "Name": "Texture", @@ -38494,6 +39167,17 @@ } } }, + "ToolboxService": { + "Name": "ToolboxService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Torque": { "Name": "Torque", "Tags": [], @@ -42032,6 +42716,23 @@ } } }, + "VRDeviceAvailable": { + "Name": "VRDeviceAvailable", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "VRDeviceName": { "Name": "VRDeviceName", "Scriptability": "None", @@ -43276,8 +43977,25 @@ "Properties": {}, "DefaultProperties": {} }, - "VoiceChatService": { - "Name": "VoiceChatService", + "VoiceChannel": { + "Name": "VoiceChannel", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, + "VoiceChatInternal": { + "Name": "VoiceChatInternal", "Tags": [ "NotCreatable", "Service" @@ -43286,7 +44004,7 @@ "Properties": { "VoiceChatState": { "Name": "VoiceChatState", - "Scriptability": "None", + "Scriptability": "Read", "DataType": { "Enum": "VoiceChatState" }, @@ -43315,6 +44033,26 @@ } } }, + "VoiceChatService": { + "Name": "VoiceChatService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "VoiceSource": { "Name": "VoiceSource", "Tags": [ @@ -45798,6 +46536,13 @@ "Resize": 0 } }, + "HighlightDepthMode": { + "name": "HighlightDepthMode", + "items": { + "AlwaysOnTop": 0, + "Default": 1 + } + }, "HorizontalAlignment": { "name": "HorizontalAlignment", "items": { @@ -46906,6 +47651,16 @@ "Ungroup": 8 } }, + "RigType": { + "name": "RigType", + "items": { + "Custom": 3, + "None": 4, + "R15": 0, + "Rthro": 1, + "RthroNarrow": 2 + } + }, "RollOffMode": { "name": "RollOffMode", "items": { @@ -47429,6 +48184,16 @@ "Template": 2 } }, + "TextChatMessageStatus": { + "name": "TextChatMessageStatus", + "items": { + "Floodchecked": 3, + "InvalidPrivacySettings": 4, + "InvalidTextChannelPermissions": 5, + "Success": 1, + "TextFilterFailed": 2 + } + }, "TextFilterContext": { "name": "TextFilterContext", "items": { From 689625764767f841edeb0c0351a385dc71211695 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Nov 2021 18:07:24 -0500 Subject: [PATCH 1183/1504] Bump MSRV to 1.55.0 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 942cc7f3..93048409 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - rust_version: [stable, "1.46.0"] + rust_version: [stable, "1.55.0"] steps: - uses: actions/checkout@v1 From adc733d25cd7d915df23526fd6dd8c1f1a63ec6c Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Nov 2021 18:14:17 -0500 Subject: [PATCH 1184/1504] Update changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 449b507a..84b94068 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ # Rojo Changelog ## Unreleased Changes +* Fixed Rojo's interactions with properties enabled by FFlags that are not yet enabled. ([#493]) +* Improved output in Roblox Studio plugin when bad property data is encountered. +* Reintroduced support for CFrame shorthand syntax in Rojo project and `.meta.json` files, matching Rojo 6. ([#430]) +* Connection settings are now remembered when reconnecting in Roblox Studio. ([#500]) +* Updated reflection database to Roblox v503. + +[#430]: https://github.com/rojo-rbx/rojo/issues/430 +[#493]: https://github.com/rojo-rbx/rojo/pull/493 +[#500]: https://github.com/rojo-rbx/rojo/pull/500 ## [7.0.0-rc.3] - October 19, 2021 This is the last release candidate for Rojo 7. In an effort to get Rojo 7 out the door, we'll be freezing features from here on out, something we should've done a couple months ago. From 9b22545842e1a7f636de617159953e6214718543 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 22 Nov 2021 13:22:16 -0500 Subject: [PATCH 1185/1504] Add tests for current file naming with regards to project name field --- ...ests__build__project_composed_default.snap | 17 ++++++++++++++ ...__tests__build__project_composed_file.snap | 22 +++++++++++++++++++ ..._end__tests__build__project_root_name.snap | 12 ++++++++++ .../default.project.json | 9 ++++++++ .../folder/default.project.json | 6 +++++ .../default.project.json | 9 ++++++++ .../folder/child-filename.project.json | 6 +++++ .../project_root_name/default.project.json | 6 +++++ tests/tests/build.rs | 3 +++ 9 files changed, 90 insertions(+) create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__project_composed_default.snap create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__project_composed_file.snap create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__project_root_name.snap create mode 100644 rojo-test/build-tests/project_composed_default/default.project.json create mode 100644 rojo-test/build-tests/project_composed_default/folder/default.project.json create mode 100644 rojo-test/build-tests/project_composed_file/default.project.json create mode 100644 rojo-test/build-tests/project_composed_file/folder/child-filename.project.json create mode 100644 rojo-test/build-tests/project_root_name/default.project.json diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__project_composed_default.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__project_composed_default.snap new file mode 100644 index 00000000..6445e820 --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__project_composed_default.snap @@ -0,0 +1,17 @@ +--- +source: tests/tests/build.rs +expression: contents + +--- + + + + root + + + + folder + + + + diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__project_composed_file.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__project_composed_file.snap new file mode 100644 index 00000000..287268ed --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__project_composed_file.snap @@ -0,0 +1,22 @@ +--- +source: tests/tests/build.rs +expression: contents + +--- + + + + root + + + + folder + + + + child-projectname + + + + + diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__project_root_name.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__project_root_name.snap new file mode 100644 index 00000000..2dd39b54 --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__project_root_name.snap @@ -0,0 +1,12 @@ +--- +source: tests/tests/build.rs +expression: contents + +--- + + + + root + + + diff --git a/rojo-test/build-tests/project_composed_default/default.project.json b/rojo-test/build-tests/project_composed_default/default.project.json new file mode 100644 index 00000000..c38c6b60 --- /dev/null +++ b/rojo-test/build-tests/project_composed_default/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "root", + "tree": { + "$className": "Folder", + "folder": { + "$path": "folder" + } + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/project_composed_default/folder/default.project.json b/rojo-test/build-tests/project_composed_default/folder/default.project.json new file mode 100644 index 00000000..0b282813 --- /dev/null +++ b/rojo-test/build-tests/project_composed_default/folder/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "child-projectname", + "tree": { + "$className": "Folder" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/project_composed_file/default.project.json b/rojo-test/build-tests/project_composed_file/default.project.json new file mode 100644 index 00000000..c38c6b60 --- /dev/null +++ b/rojo-test/build-tests/project_composed_file/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "root", + "tree": { + "$className": "Folder", + "folder": { + "$path": "folder" + } + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/project_composed_file/folder/child-filename.project.json b/rojo-test/build-tests/project_composed_file/folder/child-filename.project.json new file mode 100644 index 00000000..0b282813 --- /dev/null +++ b/rojo-test/build-tests/project_composed_file/folder/child-filename.project.json @@ -0,0 +1,6 @@ +{ + "name": "child-projectname", + "tree": { + "$className": "Folder" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/project_root_name/default.project.json b/rojo-test/build-tests/project_root_name/default.project.json new file mode 100644 index 00000000..d7171c6a --- /dev/null +++ b/rojo-test/build-tests/project_root_name/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "root", + "tree": { + "$className": "Folder" + } +} \ No newline at end of file diff --git a/tests/tests/build.rs b/tests/tests/build.rs index 23b066b9..33829683 100644 --- a/tests/tests/build.rs +++ b/tests/tests/build.rs @@ -41,6 +41,9 @@ gen_build_tests! { json_model_legacy_name, module_in_folder, module_init, + project_composed_default, + project_composed_file, + project_root_name, rbxm_in_folder, rbxmx_in_folder, rbxmx_ref, From e8afa03f7bcbce6c004b50db0b35e05b11911499 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 22 Nov 2021 13:59:12 -0500 Subject: [PATCH 1186/1504] Fix most test output (but not termcolor) --- tests/rojo_test/io_util.rs | 15 ++++++++++++++- tests/tests/build.rs | 9 ++++++--- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/tests/rojo_test/io_util.rs b/tests/rojo_test/io_util.rs index 4c33706b..ce940f4a 100644 --- a/tests/rojo_test/io_util.rs +++ b/tests/rojo_test/io_util.rs @@ -1,5 +1,6 @@ use std::{ - fs, io, + fs, + io::{self, Read}, path::{Path, PathBuf}, process::Child, }; @@ -50,5 +51,17 @@ pub struct KillOnDrop(pub Child); impl Drop for KillOnDrop { fn drop(&mut self) { let _ = self.0.kill(); + + if let Some(mut stdout) = self.0.stdout.take() { + let mut output = Vec::new(); + let _ = stdout.read_to_end(&mut output); + print!("{}", String::from_utf8_lossy(&output)); + } + + if let Some(mut stderr) = self.0.stderr.take() { + let mut output = Vec::new(); + let _ = stderr.read_to_end(&mut output); + eprint!("{}", String::from_utf8_lossy(&output)); + } } } diff --git a/tests/tests/build.rs b/tests/tests/build.rs index 33829683..aaf666e6 100644 --- a/tests/tests/build.rs +++ b/tests/tests/build.rs @@ -63,7 +63,7 @@ fn run_build_test(test_name: &str) { let output_dir = tempdir().expect("couldn't create temporary directory"); let output_path = output_dir.path().join(format!("{}.rbxmx", test_name)); - let status = Command::new(ROJO_PATH) + let output = Command::new(ROJO_PATH) .args(&[ "build", input_path.to_str().unwrap(), @@ -72,10 +72,13 @@ fn run_build_test(test_name: &str) { ]) .env("RUST_LOG", "error") .current_dir(working_dir) - .status() + .output() .expect("Couldn't start Rojo"); - assert!(status.success(), "Rojo did not exit successfully"); + print!("{}", String::from_utf8_lossy(&output.stdout)); + eprint!("{}", String::from_utf8_lossy(&output.stderr)); + + assert!(output.status.success(), "Rojo did not exit successfully"); let contents = fs::read_to_string(&output_path).expect("Couldn't read output file"); From 1c319f2fa8667a3879a73792bd1ee99eab4eedd1 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 26 Nov 2021 16:36:55 -0500 Subject: [PATCH 1187/1504] Promote weldconstraint test project to a build test --- ..._to_end__tests__build__weldconstraint.snap | 230 ++++++++++++++++++ .../weldconstraint/default.project.json | 6 + .../weldconstraint/two-parts-welded.rbxmx | 0 .../weldconstraint/default.project.json | 12 - tests/tests/build.rs | 1 + 5 files changed, 237 insertions(+), 12 deletions(-) create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__weldconstraint.snap create mode 100644 rojo-test/build-tests/weldconstraint/default.project.json rename {test-projects => rojo-test/build-tests}/weldconstraint/two-parts-welded.rbxmx (100%) delete mode 100644 test-projects/weldconstraint/default.project.json diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__weldconstraint.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__weldconstraint.snap new file mode 100644 index 00000000..7a87112a --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__weldconstraint.snap @@ -0,0 +1,230 @@ +--- +source: tests/tests/build.rs +expression: contents + +--- + + + + weldconstraint + + + -1 + + + + + A + false + + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -14 + 0.5 + -5 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + true + true + 0 + 10724005 + + false + + 1 + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + + 4 + 1 + 2 + + -1 + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + + + WeldConstraint + + + + 7 + 0.000001013279 + -3 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + 1 + 3 + -1 + 3 + + + + + + + B + false + + + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + + -7 + 0.500001 + -8 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + true + true + true + true + 0 + 10724005 + + false + + 1 + -0.5 + 0.5 + 0 + 0 + -0.5 + 0.5 + 0 + 0 + false + false + 256 + + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 1 + + 0 + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + 1 + + 4 + 1 + 2 + + -1 + + -0.5 + 0.5 + 0 + 0 + 0 + + 0 + 0 + 0 + + + + + diff --git a/rojo-test/build-tests/weldconstraint/default.project.json b/rojo-test/build-tests/weldconstraint/default.project.json new file mode 100644 index 00000000..2a61046c --- /dev/null +++ b/rojo-test/build-tests/weldconstraint/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "weldconstraint", + "tree": { + "$path": "two-parts-welded.rbxmx" + } +} \ No newline at end of file diff --git a/test-projects/weldconstraint/two-parts-welded.rbxmx b/rojo-test/build-tests/weldconstraint/two-parts-welded.rbxmx similarity index 100% rename from test-projects/weldconstraint/two-parts-welded.rbxmx rename to rojo-test/build-tests/weldconstraint/two-parts-welded.rbxmx diff --git a/test-projects/weldconstraint/default.project.json b/test-projects/weldconstraint/default.project.json deleted file mode 100644 index e666911b..00000000 --- a/test-projects/weldconstraint/default.project.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "name": "weldconstraint", - "tree": { - "$className": "DataModel", - - "Workspace": { - "Parts": { - "$path": "two-parts-welded.rbxmx" - } - } - } -} \ No newline at end of file diff --git a/tests/tests/build.rs b/tests/tests/build.rs index aaf666e6..748121fc 100644 --- a/tests/tests/build.rs +++ b/tests/tests/build.rs @@ -53,6 +53,7 @@ gen_build_tests! { txt, txt_in_folder, unresolved_values, + weldconstraint, } fn run_build_test(test_name: &str) { From af077c796cb028f9e42731e2d8a43445318a9ca3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 26 Nov 2021 17:28:13 -0500 Subject: [PATCH 1188/1504] Update dependencies --- Cargo.lock | 63 +++++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a9088c14..afe7a2b8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -46,9 +46,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d9ff5d688f1c13395289f67db01d4826b46dd694e7580accdc3e8430f2d98e" +checksum = "62e1f47f7dc0422027a4e370dd4548d4d66b26782e513e98dca1e689e058a80e" [[package]] name = "arrayref" @@ -329,9 +329,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "crc32fast" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a" +checksum = "3825b1e8580894917dc4468cb634a1b4e9745fddc854edad72d9c04644c0319f" dependencies = [ "cfg-if 1.0.0", ] @@ -731,9 +731,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" +checksum = "8cd0210d8c325c245ff06fd95a3b13689a1a276ac8cfa8e8720cb840bfb84b9e" dependencies = [ "futures-channel", "futures-core", @@ -746,9 +746,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" +checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27" dependencies = [ "futures-core", "futures-sink", @@ -756,9 +756,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" +checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445" [[package]] name = "futures-cpupool" @@ -772,9 +772,9 @@ dependencies = [ [[package]] name = "futures-executor" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45025be030969d763025784f7f355043dc6bc74093e4ecc5000ca4dc50d8745c" +checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97" dependencies = [ "futures-core", "futures-task", @@ -783,18 +783,16 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" +checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11" [[package]] name = "futures-macro" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18e4a4b95cea4b4ccbcf1c5675ca7c4ee4e9e75eb79944d07defde18068f79bb" +checksum = "a89f17b21645bc4ed773c69af9c9a0effd4a3f1a3876eadd453469f8854e7fdd" dependencies = [ - "autocfg 1.0.1", - "proc-macro-hack", "proc-macro2 1.0.32", "quote 1.0.10", "syn", @@ -802,23 +800,22 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" +checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af" [[package]] name = "futures-task" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" +checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12" [[package]] name = "futures-util" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" +checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e" dependencies = [ - "autocfg 1.0.1", "futures-channel", "futures-core", "futures-io", @@ -828,8 +825,6 @@ dependencies = [ "memchr", "pin-project-lite", "pin-utils", - "proc-macro-hack", - "proc-macro-nested", "slab", ] @@ -2024,9 +2019,9 @@ dependencies = [ [[package]] name = "rbx_reflection_database" -version = "0.2.3+roblox-503" +version = "0.2.4+roblox-504" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13f720dca247c34e34f73f155bb46e7aa532f1755d5ee8ef77c76a161c7e18d8" +checksum = "b41e8da85aa697cd04cef48e6dd7d96992786d2e322bafe1d3cc93045f4de1e1" dependencies = [ "lazy_static", "rbx_reflection", @@ -2245,7 +2240,7 @@ dependencies = [ "embed-resource", "env_logger", "fs-err", - "futures 0.3.17", + "futures 0.3.18", "globset", "humantime", "hyper 0.14.15", @@ -2422,9 +2417,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.71" +version = "1.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "063bf466a64011ac24040a49009724ee60a57da1b437617ceb32e53ad61bfb19" +checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" dependencies = [ "itoa", "ryu", @@ -2554,9 +2549,9 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "syn" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2afee18b8beb5a596ecb4a2dce128c719b4ba399d34126b9e4396e3f9860966" +checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" dependencies = [ "proc-macro2 1.0.32", "quote 1.0.10", From f389a4a1dbaf1a352333ecb78c56c21ed9e5e805 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 26 Nov 2021 17:31:12 -0500 Subject: [PATCH 1189/1504] Update rbx_dom_lua --- plugin/rbx_dom_lua/database.json | 477 +++++++++++++++++++++++-------- 1 file changed, 363 insertions(+), 114 deletions(-) diff --git a/plugin/rbx_dom_lua/database.json b/plugin/rbx_dom_lua/database.json index d15b16e9..37183baf 100644 --- a/plugin/rbx_dom_lua/database.json +++ b/plugin/rbx_dom_lua/database.json @@ -1,9 +1,9 @@ { "Version": [ 0, - 503, + 504, 0, - 5030338 + 5040410 ], "Classes": { "ABTestService": { @@ -12405,6 +12405,7 @@ "Name": "GamepadService", "Tags": [ "NotCreatable", + "NotReplicated", "Service" ], "Superclass": "Instance", @@ -18991,6 +18992,40 @@ } } }, + "MarkerCurve": { + "Name": "MarkerCurve", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Length": { + "Name": "Length", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "MarketplaceService": { "Name": "MarketplaceService", "Tags": [ @@ -19012,11 +19047,13 @@ "Properties": { "Brick": { "Name": "Brick", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19025,11 +19062,13 @@ }, "Cobblestone": { "Name": "Cobblestone", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19038,11 +19077,13 @@ }, "Concrete": { "Name": "Concrete", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19051,11 +19092,13 @@ }, "CorrodedMetal": { "Name": "CorrodedMetal", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19064,11 +19107,13 @@ }, "DiamondPlate": { "Name": "DiamondPlate", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19077,11 +19122,13 @@ }, "Fabric": { "Name": "Fabric", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19090,11 +19137,13 @@ }, "Foil": { "Name": "Foil", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19103,11 +19152,13 @@ }, "Granite": { "Name": "Granite", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19116,11 +19167,13 @@ }, "Grass": { "Name": "Grass", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19129,11 +19182,13 @@ }, "Ice": { "Name": "Ice", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19142,11 +19197,13 @@ }, "Marble": { "Name": "Marble", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19155,11 +19212,13 @@ }, "Metal": { "Name": "Metal", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19168,11 +19227,13 @@ }, "Pebble": { "Name": "Pebble", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19181,11 +19242,13 @@ }, "Plastic": { "Name": "Plastic", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19194,11 +19257,13 @@ }, "Sand": { "Name": "Sand", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19207,11 +19272,13 @@ }, "Slate": { "Name": "Slate", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19220,11 +19287,13 @@ }, "SmoothPlastic": { "Name": "SmoothPlastic", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19233,11 +19302,13 @@ }, "Wood": { "Name": "Wood", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -19246,11 +19317,13 @@ }, "WoodPlanks": { "Name": "WoodPlanks", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -20036,23 +20109,6 @@ "Serialization": "DoesNotSerialize" } } - }, - "Valid": { - "Name": "Valid", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } } }, "DefaultProperties": {} @@ -23091,6 +23147,19 @@ "Serialization": "Serializes" } } + }, + "ModifierId": { + "Name": "ModifierId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -23100,6 +23169,9 @@ "IsBidirectional": { "Bool": true }, + "ModifierId": { + "String": "" + }, "SourceAssetId": { "Int64": -1 }, @@ -27272,6 +27344,107 @@ } } }, + "RigidConstraint": { + "Name": "RigidConstraint", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Constraint", + "Properties": { + "Broken": { + "Name": "Broken", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DestructionEnabled": { + "Name": "DestructionEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DestructionForce": { + "Name": "DestructionForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DestructionTorque": { + "Name": "DestructionTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AttributesSerialize": { + "BinaryString": "" + }, + "Broken": { + "Bool": false + }, + "Color": { + "Int32": 194 + }, + "DestructionEnabled": { + "Bool": false + }, + "DestructionForce": { + "Float32": null + }, + "DestructionTorque": { + "Float32": null + }, + "Enabled": { + "Bool": true + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "Visible": { + "Bool": false + } + } + }, "RobloxPluginGuiService": { "Name": "RobloxPluginGuiService", "Tags": [ @@ -28338,6 +28511,17 @@ }, "DefaultProperties": {} }, + "ScriptRegistrationService": { + "Name": "ScriptRegistrationService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ScriptService": { "Name": "ScriptService", "Tags": [ @@ -33930,6 +34114,22 @@ } } }, + "Doc View Code Background Color": { + "Name": "Doc View Code Background Color", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Drag Multiple Parts As Single Part": { "Name": "Drag Multiple Parts As Single Part", "Scriptability": "ReadWrite", @@ -33956,6 +34156,19 @@ } } }, + "Enable Autocomplete Doc View": { + "Name": "Enable Autocomplete Doc View", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Enable CoreScript Debugger": { "Name": "Enable CoreScript Debugger", "Scriptability": "ReadWrite", @@ -34047,6 +34260,19 @@ } } }, + "Enable Signature Help Doc View": { + "Name": "Enable Signature Help Doc View", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Enable Temporary Tabs": { "Name": "Enable Temporary Tabs", "Scriptability": "ReadWrite", @@ -43465,7 +43691,23 @@ "Service" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "ScriptCollabEnabled": { + "Name": "ScriptCollabEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, "DefaultProperties": {} }, "VideoFrame": { @@ -44036,6 +44278,7 @@ "VoiceChatService": { "Name": "VoiceChatService", "Tags": [ + "Deprecated", "NotCreatable", "Service" ], @@ -44410,7 +44653,9 @@ ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": { + "SerializesAs": "Part0Internal" + } } } }, @@ -44438,7 +44683,9 @@ ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": { + "SerializesAs": "Part1Internal" + } } } }, @@ -44521,7 +44768,7 @@ }, "CollisionGroups": { "Name": "CollisionGroups", - "Scriptability": "Custom", + "Scriptability": "None", "DataType": { "Value": "String" }, @@ -47889,6 +48136,7 @@ "DebuggerCurrentLine": 26, "DebuggerErrorLine": 27, "Default": 0, + "DocViewCodeBackground": 38, "Error": 23, "FindSelectionBackground": 20, "Function": 11, @@ -47932,48 +48180,49 @@ "StudioStyleGuideColor": { "name": "StudioStyleGuideColor", "items": { - "AttributeCog": 115, + "AttributeCog": 116, "Border": 31, "BrightText": 39, "Button": 17, - "ButtonBorder": 87, - "ButtonText": 88, + "ButtonBorder": 88, + "ButtonText": 89, "CategoryItem": 24, - "ChatIncomingBgColor": 81, - "ChatIncomingTextColor": 82, - "ChatModeratedMessageColor": 85, - "ChatOutgoingBgColor": 83, - "ChatOutgoingTextColor": 84, - "CheckedFieldBackground": 90, - "CheckedFieldBorder": 91, - "CheckedFieldIndicator": 92, + "ChatIncomingBgColor": 82, + "ChatIncomingTextColor": 83, + "ChatModeratedMessageColor": 86, + "ChatOutgoingBgColor": 84, + "ChatOutgoingTextColor": 85, + "CheckedFieldBackground": 91, + "CheckedFieldBorder": 92, + "CheckedFieldIndicator": 93, "ColorPickerFrame": 29, "CurrentMarker": 30, "Dark": 34, - "DebuggerCurrentLine": 63, - "DebuggerErrorLine": 64, - "DialogButton": 96, - "DialogButtonBorder": 98, - "DialogButtonText": 97, - "DialogMainButton": 99, - "DialogMainButtonText": 100, - "DiffFilePathBackground": 79, - "DiffFilePathBorder": 80, - "DiffFilePathText": 65, - "DiffLineNum": 74, - "DiffLineNumAdditionBackground": 77, - "DiffLineNumDeletionBackground": 78, - "DiffLineNumNoChangeBackground": 76, - "DiffLineNumSeparatorBackground": 75, - "DiffTextAddition": 68, - "DiffTextAdditionBackground": 72, - "DiffTextDeletion": 69, - "DiffTextDeletionBackground": 73, - "DiffTextHunkInfo": 66, - "DiffTextNoChange": 67, - "DiffTextNoChangeBackground": 71, - "DiffTextSeparatorBackground": 70, + "DebuggerCurrentLine": 64, + "DebuggerErrorLine": 65, + "DialogButton": 97, + "DialogButtonBorder": 99, + "DialogButtonText": 98, + "DialogMainButton": 100, + "DialogMainButtonText": 101, + "DiffFilePathBackground": 80, + "DiffFilePathBorder": 81, + "DiffFilePathText": 66, + "DiffLineNum": 75, + "DiffLineNumAdditionBackground": 78, + "DiffLineNumDeletionBackground": 79, + "DiffLineNumNoChangeBackground": 77, + "DiffLineNumSeparatorBackground": 76, + "DiffTextAddition": 69, + "DiffTextAdditionBackground": 73, + "DiffTextDeletion": 70, + "DiffTextDeletionBackground": 74, + "DiffTextHunkInfo": 67, + "DiffTextNoChange": 68, + "DiffTextNoChangeBackground": 72, + "DiffTextSeparatorBackground": 71, "DimmedText": 40, + "DocViewCodeBackground": 63, "Dropdown": 2, "EmulatorBar": 27, "EmulatorDropDown": 28, @@ -47986,12 +48235,12 @@ "FilterButtonHover": 10, "GameSettingsTableItem": 25, "GameSettingsTooltip": 26, - "HeaderSection": 93, - "InfoBarWarningBackground": 101, - "InfoBarWarningText": 102, + "HeaderSection": 94, + "InfoBarWarningBackground": 102, + "InfoBarWarningText": 103, "InfoText": 44, "InputFieldBackground": 21, - "InputFieldBorder": 89, + "InputFieldBorder": 90, "Item": 22, "Light": 33, "LinkText": 41, @@ -47999,46 +48248,46 @@ "MainButton": 18, "MainText": 36, "Mid": 35, - "Midlight": 94, + "Midlight": 95, "Notification": 4, "RibbonButton": 19, "RibbonTab": 15, "RibbonTabTopBar": 16, "ScriptBackground": 47, - "ScriptBool": 107, - "ScriptBracket": 114, + "ScriptBool": 108, + "ScriptBracket": 115, "ScriptBuiltInFunction": 58, "ScriptComment": 56, - "ScriptEditorCurrentLine": 103, + "ScriptEditorCurrentLine": 104, "ScriptError": 60, "ScriptFindSelectionBackground": 51, - "ScriptFunction": 108, - "ScriptFunctionName": 112, + "ScriptFunction": 109, + "ScriptFunctionName": 113, "ScriptKeyword": 57, - "ScriptLocal": 109, - "ScriptLuauKeyword": 111, + "ScriptLocal": 110, + "ScriptLuauKeyword": 112, "ScriptMatchingWordSelectionBackground": 52, - "ScriptMethod": 104, - "ScriptNil": 106, + "ScriptMethod": 105, + "ScriptNil": 107, "ScriptNumber": 54, "ScriptOperator": 53, - "ScriptProperty": 105, + "ScriptProperty": 106, "ScriptRuler": 62, "ScriptSelectionBackground": 50, "ScriptSelectionText": 49, - "ScriptSelf": 110, + "ScriptSelf": 111, "ScriptSideWidget": 46, "ScriptString": 55, "ScriptText": 48, - "ScriptTodo": 113, + "ScriptTodo": 114, "ScriptWarning": 59, "ScriptWhitespace": 61, "ScrollBar": 5, "ScrollBarBackground": 6, "SensitiveText": 45, - "Separator": 86, + "Separator": 87, "Shadow": 32, - "StatusBar": 95, + "StatusBar": 96, "SubText": 37, "Tab": 8, "TabBar": 7, From 07637dfe96f52a2c2f2dd3630601b0137aeada42 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 10 Dec 2021 19:37:39 -0500 Subject: [PATCH 1190/1504] Release v7.0.0 --- CHANGELOG.md | 3 +++ Cargo.lock | 2 +- Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 84b94068..d6329f32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes + +## [7.0.0] - December 10, 2021 * Fixed Rojo's interactions with properties enabled by FFlags that are not yet enabled. ([#493]) * Improved output in Roblox Studio plugin when bad property data is encountered. * Reintroduced support for CFrame shorthand syntax in Rojo project and `.meta.json` files, matching Rojo 6. ([#430]) @@ -10,6 +12,7 @@ [#430]: https://github.com/rojo-rbx/rojo/issues/430 [#493]: https://github.com/rojo-rbx/rojo/pull/493 [#500]: https://github.com/rojo-rbx/rojo/pull/500 +[7.0.0]: https://github.com/rojo-rbx/rojo/releases/tag/v7.0.0 ## [7.0.0-rc.3] - October 19, 2021 This is the last release candidate for Rojo 7. In an effort to get Rojo 7 out the door, we'll be freezing features from here on out, something we should've done a couple months ago. diff --git a/Cargo.lock b/Cargo.lock index afe7a2b8..29a247a3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2229,7 +2229,7 @@ dependencies = [ [[package]] name = "rojo" -version = "7.0.0-rc.3" +version = "7.0.0" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 917ce77c..c76131ff 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "7.0.0-rc.3" +version = "7.0.0" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index cdd9e2a3..02d0b83d 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {7, 0, 0, "-rc.3"}, + version = {7, 0, 0}, expectedServerVersionString = "7.0 or newer", protocolVersion = 4, defaultHost = "localhost", From 12370846b4748a8b734644d94c6ccea23cbc0815 Mon Sep 17 00:00:00 2001 From: Ashton Miller <30465911+VernandoGames@users.noreply.github.com> Date: Tue, 19 Apr 2022 15:02:40 -0500 Subject: [PATCH 1191/1504] Support the new Open Cloud API (#504) * Add support for the new Open Cloud API * Cleanup Open Cloud variables * Avoid cloning buffer for do_upload_open_cloud * Satisfy cargo fmt * Actually correct cargo fmt Apparently my earlier fix did not fix everything. * Update CHANGELOG.md * Update CHANGELOG.md Forgot to add the link to issue #486 in the previous commit :/ * Cleanup & improve code for open cloud api * Commit to force GH Actions to run (?) Co-authored-by: Lucien Greathouse --- CHANGELOG.md | 4 ++- src/cli/upload.rs | 78 ++++++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 76 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d6329f32..3b51a413 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Added support for the new Open Cloud API when uploading. ([#486]) ## [7.0.0] - December 10, 2021 * Fixed Rojo's interactions with properties enabled by FFlags that are not yet enabled. ([#493]) @@ -9,6 +10,7 @@ * Connection settings are now remembered when reconnecting in Roblox Studio. ([#500]) * Updated reflection database to Roblox v503. +[#486]: https://github.com/rojo-rbx/rojo/issues/486 [#430]: https://github.com/rojo-rbx/rojo/issues/430 [#493]: https://github.com/rojo-rbx/rojo/pull/493 [#500]: https://github.com/rojo-rbx/rojo/pull/500 @@ -475,4 +477,4 @@ This is a general maintenance release for the Rojo 0.5.x release series. * More robust syncing with a new reconciler ## [0.1.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.1.0) (November 29, 2017) -* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) \ No newline at end of file +* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) diff --git a/src/cli/upload.rs b/src/cli/upload.rs index 8c862618..2006ac66 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -24,6 +24,14 @@ pub struct UploadCommand { #[structopt(long)] pub cookie: Option, + /// API key obtained from create.roblox.com/credentials. Rojo will use the Open Cloud API when this is provided. Only supports uploading to a place. + #[structopt(long = "api_key")] + pub api_key: Option, + + /// The Universe ID of the given place. Required when using the Open Cloud API. + #[structopt(long = "universe_id")] + pub universe_id: Option, + /// Asset ID to upload to. #[structopt(long = "asset_id")] pub asset_id: u64, @@ -33,10 +41,6 @@ impl UploadCommand { pub fn run(self) -> Result<(), anyhow::Error> { let project_path = resolve_path(&self.project); - let cookie = self.cookie.or_else(get_auth_cookie).context( - "Rojo could not find your Roblox auth cookie. Please pass one via --cookie.", - )?; - let vfs = Vfs::new_default(); let session = ServeSession::new(vfs, project_path)?; @@ -54,7 +58,36 @@ impl UploadCommand { log::trace!("Encoding binary model"); rbx_binary::to_writer(&mut buffer, tree.inner(), &encode_ids)?; - do_upload(buffer, self.asset_id, &cookie) + + match (self.cookie, self.api_key, self.universe_id) { + (cookie, None, universe) => { + // using legacy. notify if universe is provided. + if universe.is_some() { + log::warn!( + "--universe_id was provided but is ignored when using legacy upload" + ); + } + + let cookie = cookie.or_else(get_auth_cookie).context( + "Rojo could not find your Roblox auth cookie. Please pass one via --cookie.", + )?; + do_upload(buffer, self.asset_id, &cookie) + } + + (cookie, Some(api_key), Some(universe_id)) => { + // using open cloud. notify if cookie is provided. + if cookie.is_some() { + log::warn!("--cookie was provided but is ignored when using Open Cloud API"); + } + + do_upload_open_cloud(buffer, universe_id, self.asset_id, &api_key) + } + + (_, Some(_), None) => { + // API key is provided, universe id is not. + bail!("--universe_id must be provided to use the Open Cloud API"); + } + } } } @@ -125,3 +158,38 @@ fn do_upload(buffer: Vec, asset_id: u64, cookie: &str) -> anyhow::Result<()> Ok(()) } + +/// Implementation of do_upload that supports the new open cloud api. +/// see https://developer.roblox.com/en-us/articles/open-cloud +fn do_upload_open_cloud( + buffer: Vec, + universe_id: u64, + asset_id: u64, + api_key: &str, +) -> anyhow::Result<()> { + let url = format!( + "https://apis.roblox.com/universes/v1/{}/places/{}/versions?versionType=Published", + universe_id, asset_id + ); + + let client = reqwest::Client::new(); + + log::debug!("Uploading to Roblox..."); + let mut response = client + .post(&url) + .header("x-api-key", api_key) + .header(CONTENT_TYPE, "application/xml") + .header(ACCEPT, "application/json") + .body(buffer) + .send()?; + + let status = response.status(); + if !status.is_success() { + bail!( + "The Roblox API returned an unexpected error: {}", + response.text()? + ); + } + + Ok(()) +} From 49f8845105925c29590c4883fa293d4f735716dd Mon Sep 17 00:00:00 2001 From: Ashton Miller <30465911+VernandoGames@users.noreply.github.com> Date: Tue, 19 Apr 2022 15:54:03 -0500 Subject: [PATCH 1192/1504] Add ability to specify address in default.project.json (#507) * Allow for setting the default port in project json set as ```json "serveAddress": "0.0.0.0" ``` * Update CHANGELOG.md * cargo fmt Co-authored-by: Lucien Greathouse --- CHANGELOG.md | 5 ++++- src/cli/serve.rs | 5 ++++- src/project.rs | 6 ++++++ src/serve_session.rs | 5 +++++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b51a413..4f7993cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,12 @@ # Rojo Changelog ## Unreleased Changes +* Added support for specifying an address to be used by default in the .project.json file ([#447]) * Added support for the new Open Cloud API when uploading. ([#486]) +[#447]: https://github.com/rojo-rbx/rojo/issues/447 +[#486]: https://github.com/rojo-rbx/rojo/issues/486 + ## [7.0.0] - December 10, 2021 * Fixed Rojo's interactions with properties enabled by FFlags that are not yet enabled. ([#493]) * Improved output in Roblox Studio plugin when bad property data is encountered. @@ -10,7 +14,6 @@ * Connection settings are now remembered when reconnecting in Roblox Studio. ([#500]) * Updated reflection database to Roblox v503. -[#486]: https://github.com/rojo-rbx/rojo/issues/486 [#430]: https://github.com/rojo-rbx/rojo/issues/430 [#493]: https://github.com/rojo-rbx/rojo/pull/493 [#500]: https://github.com/rojo-rbx/rojo/pull/500 diff --git a/src/cli/serve.rs b/src/cli/serve.rs index abd3dd8e..56b46121 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -41,7 +41,10 @@ impl ServeCommand { let session = Arc::new(ServeSession::new(vfs, &project_path)?); - let ip = self.address.unwrap_or(DEFAULT_BIND_ADDRESS.into()); + let ip = self + .address + .or_else(|| session.serve_address()) + .unwrap_or(DEFAULT_BIND_ADDRESS.into()); let port = self .port diff --git a/src/project.rs b/src/project.rs index 088e6d97..d9edc820 100644 --- a/src/project.rs +++ b/src/project.rs @@ -1,6 +1,7 @@ use std::{ collections::{BTreeMap, HashMap, HashSet}, fs, io, + net::IpAddr, path::{Path, PathBuf}, }; @@ -67,6 +68,11 @@ pub struct Project { #[serde(skip_serializing_if = "Option::is_none")] pub game_id: Option, + /// If specified, this address will be used in place of the default address + /// As long as --address is unprovided. + #[serde(skip_serializing_if = "Option::is_none")] + pub serve_address: Option, + /// A list of globs, relative to the folder the project file is in, that /// match files that should be excluded if Rojo encounters them. #[serde(default, skip_serializing_if = "Vec::is_empty")] diff --git a/src/serve_session.rs b/src/serve_session.rs index 13b8037c..2643cffd 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -2,6 +2,7 @@ use std::{ borrow::Cow, collections::HashSet, io, + net::IpAddr, path::{Path, PathBuf}, sync::{Arc, Mutex, MutexGuard}, time::Instant, @@ -212,6 +213,10 @@ impl ServeSession { pub fn serve_place_ids(&self) -> Option<&HashSet> { self.root_project.serve_place_ids.as_ref() } + + pub fn serve_address(&self) -> Option { + self.root_project.serve_address + } } #[derive(Debug, Error)] From 256aba4bc1e7a0dd635e6a02aa70972c7b8e4048 Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Tue, 19 Apr 2022 23:45:29 +0200 Subject: [PATCH 1193/1504] Implement sourcemap CLI command (#530) * Initial implementation of sourcemap CLI command * Update src/cli/sourcemap.rs Co-authored-by: JohnnyMorganz * Update src/cli/sourcemap.rs Co-authored-by: JohnnyMorganz * Tidy up sourcemap command * Update CHANGELOG Co-authored-by: JohnnyMorganz Co-authored-by: Lucien Greathouse --- CHANGELOG.md | 4 +- src/cli/mod.rs | 4 ++ src/cli/sourcemap.rs | 139 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 146 insertions(+), 1 deletion(-) create mode 100644 src/cli/sourcemap.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 4f7993cc..c6952480 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,9 +3,11 @@ ## Unreleased Changes * Added support for specifying an address to be used by default in the .project.json file ([#447]) * Added support for the new Open Cloud API when uploading. ([#486]) +* Added `sourcemap` command for generating sourcemaps to feed into other tools. ([#530]) [#447]: https://github.com/rojo-rbx/rojo/issues/447 [#486]: https://github.com/rojo-rbx/rojo/issues/486 +[#530]: https://github.com/rojo-rbx/rojo/pull/530 ## [7.0.0] - December 10, 2021 * Fixed Rojo's interactions with properties enabled by FFlags that are not yet enabled. ([#493]) @@ -480,4 +482,4 @@ This is a general maintenance release for the Rojo 0.5.x release series. * More robust syncing with a new reconciler ## [0.1.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.1.0) (November 29, 2017) -* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) +* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) \ No newline at end of file diff --git a/src/cli/mod.rs b/src/cli/mod.rs index cace812c..2d498b4a 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -6,6 +6,7 @@ mod fmt_project; mod init; mod plugin; mod serve; +mod sourcemap; mod upload; use std::{borrow::Cow, env, path::Path, str::FromStr}; @@ -19,6 +20,7 @@ pub use self::fmt_project::FmtProjectCommand; pub use self::init::{InitCommand, InitKind}; pub use self::plugin::{PluginCommand, PluginSubcommand}; pub use self::serve::ServeCommand; +pub use self::sourcemap::SourcemapCommand; pub use self::upload::UploadCommand; /// Command line options that Rojo accepts, defined using the structopt crate. @@ -40,6 +42,7 @@ impl Options { Subcommand::Serve(subcommand) => subcommand.run(self.global), Subcommand::Build(subcommand) => subcommand.run(), Subcommand::Upload(subcommand) => subcommand.run(), + Subcommand::Sourcemap(subcommand) => subcommand.run(), Subcommand::FmtProject(subcommand) => subcommand.run(), Subcommand::Doc(subcommand) => subcommand.run(), Subcommand::Plugin(subcommand) => subcommand.run(), @@ -112,6 +115,7 @@ pub enum Subcommand { Serve(ServeCommand), Build(BuildCommand), Upload(UploadCommand), + Sourcemap(SourcemapCommand), FmtProject(FmtProjectCommand), Doc(DocCommand), Plugin(PluginCommand), diff --git a/src/cli/sourcemap.rs b/src/cli/sourcemap.rs new file mode 100644 index 00000000..66341dc8 --- /dev/null +++ b/src/cli/sourcemap.rs @@ -0,0 +1,139 @@ +use std::{ + io::{BufWriter, Write}, + path::{Path, PathBuf}, +}; + +use fs_err::File; +use memofs::Vfs; +use rbx_dom_weak::types::Ref; +use serde::Serialize; +use structopt::StructOpt; + +use crate::{ + serve_session::ServeSession, + snapshot::{InstanceWithMeta, RojoTree}, +}; + +use super::resolve_path; + +const PATH_STRIP_FAILED_ERR: &str = "Failed to create relative paths for project file!"; + +/// Representation of a node in the generated sourcemap tree. +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct SourcemapNode { + name: String, + class_name: String, + + #[serde(skip_serializing_if = "Vec::is_empty")] + file_paths: Vec, + + #[serde(skip_serializing_if = "Vec::is_empty")] + children: Vec, +} + +/// Generates a sourcemap file from the Rojo project. +#[derive(Debug, StructOpt)] +pub struct SourcemapCommand { + /// Path to the project to use for the sourcemap. Defaults to the current + /// directory. + #[structopt(default_value = "")] + pub project: PathBuf, + + /// Where to output the sourcemap. Omit this to use stdout instead of + /// writing to a file. + /// + /// Should end in .json. + #[structopt(long, short)] + pub output: Option, + + /// If non-script files should be included or not. Defaults to false. + #[structopt(long)] + pub include_non_scripts: bool, +} + +impl SourcemapCommand { + pub fn run(self) -> anyhow::Result<()> { + let project_path = resolve_path(&self.project); + + let mut project_dir = project_path.to_path_buf(); + project_dir.pop(); + + log::trace!("Constructing in-memory filesystem"); + let vfs = Vfs::new_default(); + + let session = ServeSession::new(vfs, &project_path)?; + let tree = session.tree(); + + let filter = if self.include_non_scripts { + filter_nothing + } else { + filter_non_scripts + }; + + let root_node = recurse_create_node(&tree, tree.get_root_id(), &project_dir, filter); + + if let Some(output_path) = self.output { + let mut file = BufWriter::new(File::create(&output_path)?); + serde_json::to_writer(&mut file, &root_node)?; + file.flush()?; + + println!("Created sourcemap at {}", output_path.display()); + } else { + let output = serde_json::to_string(&root_node)?; + println!("{}", output); + } + + Ok(()) + } +} + +fn filter_nothing(_instance: &InstanceWithMeta) -> bool { + true +} + +fn filter_non_scripts(instance: &InstanceWithMeta) -> bool { + match instance.class_name() { + "Script" | "LocalScript" | "ModuleScript" => true, + _ => false, + } +} + +fn recurse_create_node( + tree: &RojoTree, + referent: Ref, + project_dir: &Path, + filter: fn(&InstanceWithMeta) -> bool, +) -> Option { + let instance = tree.get_instance(referent).expect("instance did not exist"); + + let mut children = Vec::new(); + for &child_id in instance.children() { + if let Some(child_node) = recurse_create_node(tree, child_id, &project_dir, filter) { + children.push(child_node); + } + } + + // If this object has no children and doesn't pass the filter, it doesn't + // contain any information we're looking for. + if children.is_empty() && !filter(&instance) { + return None; + } + + let file_paths = instance + .metadata() + .relevant_paths + .iter() + // Not all paths listed as relevant are guaranteed to exist. + .filter(|path| path.is_file()) + .map(|path| path.strip_prefix(project_dir).expect(PATH_STRIP_FAILED_ERR)) + .map(|path| path.to_path_buf()) + .collect(); + + Some(SourcemapNode { + name: instance.name().to_string(), + class_name: instance.class_name().to_string(), + file_paths, + children, + }) +} From 654690d73ebb82d82a83d24ab33724c0ba5b1da9 Mon Sep 17 00:00:00 2001 From: Micah <48431591+nezuo@users.noreply.github.com> Date: Tue, 19 Apr 2022 14:45:55 -0700 Subject: [PATCH 1194/1504] Add testez std (#535) --- selene.toml | 2 +- testez.toml | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 testez.toml diff --git a/selene.toml b/selene.toml index e73e3567..16c0939f 100644 --- a/selene.toml +++ b/selene.toml @@ -1,4 +1,4 @@ -std = "roblox" +std = "roblox+testez" [config] unused_variable = { allow_unused_self = true } diff --git a/testez.toml b/testez.toml new file mode 100644 index 00000000..c2c5a984 --- /dev/null +++ b/testez.toml @@ -0,0 +1,66 @@ +[[afterAll.args]] +type = "function" + +[[afterEach.args]] +type = "function" + +[[beforeAll.args]] +type = "function" + +[[beforeEach.args]] +type = "function" + +[[describe.args]] +type = "string" + +[[describe.args]] +type = "function" + +[[describeFOCUS.args]] +type = "string" + +[[describeFOCUS.args]] +type = "function" + +[[describeSKIP.args]] +type = "string" + +[[describeSKIP.args]] +type = "function" + +[[expect.args]] +type = "any" + +[[FIXME.args]] +type = "string" +required = false + +[FOCUS] +args = [] + +[[it.args]] +type = "string" + +[[it.args]] +type = "function" + +[[itFIXME.args]] +type = "string" + +[[itFIXME.args]] +type = "function" + +[[itFOCUS.args]] +type = "string" + +[[itFOCUS.args]] +type = "function" + +[[itSKIP.args]] +type = "string" + +[[itSKIP.args]] +type = "function" + +[SKIP] +args = [] From fe81e5592568d4482bb435defc1575f121c12e28 Mon Sep 17 00:00:00 2001 From: James Onnen Date: Tue, 19 Apr 2022 15:43:47 -0700 Subject: [PATCH 1195/1504] Add support for optional paths (#472) * Add PathNode with optional fields to project. This allows a path to be defined either as `"$path": "src"` or `"$path": { "optional": "src" }` * Make $path truly optional * Prevent rojo from erroring if no project node is resolved * Use match instead of if-statement * Add end-to-end tests (credit to MobiusCraftFlip for initial scenario) * Pass option with ref inside instead of reference to option * Empty commit to restart GitHub Actions * Simplify build test * Minimize serve test: it fails * Simplify serve test even more * Ignore failing serve test Co-authored-by: Lucien Greathouse --- .../end_to_end__tests__build__optional.snap | 24 +++ .../build-tests/optional/default.project.json | 15 ++ rojo-test/build-tests/optional/foo.txt | 1 + ...nd__tests__serve__add_optional_folder.snap | 14 ++ ...sts__serve__add_optional_folder_all-2.snap | 62 ++++++++ ...tests__serve__add_optional_folder_all.snap | 40 +++++ ..._serve__add_optional_folder_subscribe.snap | 36 +++++ .../add_optional_folder/default.project.json | 9 ++ src/change_processor.rs | 21 +-- src/project.rs | 140 +++++++++++++++++- src/serve_session.rs | 5 +- src/snapshot/patch_compute.rs | 29 ++-- src/snapshot/tests/compute.rs | 10 +- src/snapshot_middleware/project.rs | 94 ++++++------ tests/tests/build.rs | 1 + tests/tests/serve.rs | 31 ++++ 16 files changed, 450 insertions(+), 82 deletions(-) create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__optional.snap create mode 100644 rojo-test/build-tests/optional/default.project.json create mode 100644 rojo-test/build-tests/optional/foo.txt create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder_all-2.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder_all.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder_subscribe.snap create mode 100644 rojo-test/serve-tests/add_optional_folder/default.project.json diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__optional.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__optional.snap new file mode 100644 index 00000000..63f0494f --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__optional.snap @@ -0,0 +1,24 @@ +--- +source: tests/tests/build.rs +expression: contents + +--- + + + + optional + + + + foo-optional + Hello, from foo.txt! + + + + + foo-required + Hello, from foo.txt! + + + + diff --git a/rojo-test/build-tests/optional/default.project.json b/rojo-test/build-tests/optional/default.project.json new file mode 100644 index 00000000..9e9091f4 --- /dev/null +++ b/rojo-test/build-tests/optional/default.project.json @@ -0,0 +1,15 @@ +{ + "name": "optional", + "tree": { + "$className": "Folder", + "foo-required": { + "$path": "foo.txt" + }, + "foo-optional":{ + "$path": { "optional": "foo.txt" } + }, + "bar-optional":{ + "$path": { "optional": "bar.txt" } + } + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/optional/foo.txt b/rojo-test/build-tests/optional/foo.txt new file mode 100644 index 00000000..ca77661c --- /dev/null +++ b/rojo-test/build-tests/optional/foo.txt @@ -0,0 +1 @@ +Hello, from foo.txt! \ No newline at end of file diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder.snap new file mode 100644 index 00000000..42a31374 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder.snap @@ -0,0 +1,14 @@ +--- +source: tests/tests/serve.rs +expression: redactions.redacted_yaml(info) + +--- +expectedPlaceIds: ~ +gameId: ~ +placeId: ~ +projectName: optional +protocolVersion: 4 +rootInstanceId: id-2 +serverVersion: "[server-version]" +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder_all-2.snap new file mode 100644 index 00000000..22432adf --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder_all-2.snap @@ -0,0 +1,62 @@ +--- +source: tests/tests/serve.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" + +--- +instances: + id-2: + Children: + - id-3 + ClassName: Folder + Id: id-2 + Metadata: + ignoreUnknownInstances: true + Name: optional + Parent: "00000000000000000000000000000000" + Properties: {} + id-3: + Children: + - id-4 + - id-5 + ClassName: Folder + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: src + Parent: id-2 + Properties: {} + id-4: + Children: [] + ClassName: StringValue + Id: id-4 + Metadata: + ignoreUnknownInstances: false + Name: foo + Parent: id-3 + Properties: + Value: + String: "Hello, from foo.txt!" + id-5: + Children: + - id-6 + ClassName: Folder + Id: id-5 + Metadata: + ignoreUnknownInstances: false + Name: node_modules + Parent: id-3 + Properties: {} + id-6: + Children: [] + ClassName: StringValue + Id: id-6 + Metadata: + ignoreUnknownInstances: false + Name: bar + Parent: id-5 + Properties: + Value: + String: Hello from bar.txt +messageCursor: 2 +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder_all.snap new file mode 100644 index 00000000..af3714ec --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder_all.snap @@ -0,0 +1,40 @@ +--- +source: tests/tests/serve.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" + +--- +instances: + id-2: + Children: + - id-3 + ClassName: Folder + Id: id-2 + Metadata: + ignoreUnknownInstances: true + Name: optional + Parent: "00000000000000000000000000000000" + Properties: {} + id-3: + Children: + - id-4 + ClassName: Folder + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: src + Parent: id-2 + Properties: {} + id-4: + Children: [] + ClassName: StringValue + Id: id-4 + Metadata: + ignoreUnknownInstances: false + Name: foo + Parent: id-3 + Properties: + Value: + String: "Hello, from foo.txt!" +messageCursor: 0 +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder_subscribe.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder_subscribe.snap new file mode 100644 index 00000000..492302c8 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__add_optional_folder_subscribe.snap @@ -0,0 +1,36 @@ +--- +source: tests/tests/serve.rs +expression: "subscribe_response.intern_and_redact(&mut redactions, ())" + +--- +messageCursor: 2 +messages: + - added: + id-5: + Children: + - id-6 + ClassName: Folder + Id: id-5 + Metadata: + ignoreUnknownInstances: false + Name: node_modules + Parent: id-3 + Properties: {} + id-6: + Children: [] + ClassName: StringValue + Id: id-6 + Metadata: + ignoreUnknownInstances: false + Name: bar + Parent: id-5 + Properties: + Value: + String: Hello from bar.txt + removed: [] + updated: [] + - added: {} + removed: [] + updated: [] +sessionId: id-1 + diff --git a/rojo-test/serve-tests/add_optional_folder/default.project.json b/rojo-test/serve-tests/add_optional_folder/default.project.json new file mode 100644 index 00000000..d582e8e5 --- /dev/null +++ b/rojo-test/serve-tests/add_optional_folder/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "optional", + "tree": { + "$className": "Folder", + "create-later": { + "$path": { "optional": "create-later" } + } + } +} \ No newline at end of file diff --git a/src/change_processor.rs b/src/change_processor.rs index b7ad8b20..7082a687 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -284,22 +284,14 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: Ref) -> Option< // that path and use it as the source for our patch. let snapshot = match snapshot_from_vfs(&metadata.context, &vfs, &path) { - Ok(Some(snapshot)) => snapshot, - Ok(None) => { - log::error!( - "Snapshot did not return an instance from path {}", - path.display() - ); - log::error!("This may be a bug!"); - return None; - } + Ok(snapshot) => snapshot, Err(err) => { log::error!("Snapshot error: {:?}", err); return None; } }; - let patch_set = compute_patch_set(&snapshot, &tree, id); + let patch_set = compute_patch_set(snapshot.as_ref(), &tree, id); apply_patch_set(tree, patch_set) } Ok(None) => { @@ -335,19 +327,14 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: Ref) -> Option< ); let snapshot = match snapshot_result { - Ok(Some(snapshot)) => snapshot, - Ok(None) => { - log::error!("Snapshot did not return an instance from a project node."); - log::error!("This is a bug!"); - return None; - } + Ok(snapshot) => snapshot, Err(err) => { log::error!("{:?}", err); return None; } }; - let patch_set = compute_patch_set(&snapshot, &tree, id); + let patch_set = compute_patch_set(snapshot.as_ref(), &tree, id); apply_patch_set(tree, patch_set) } }; diff --git a/src/project.rs b/src/project.rs index d9edc820..53d52808 100644 --- a/src/project.rs +++ b/src/project.rs @@ -174,6 +174,35 @@ impl Project { } } +#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] +pub struct OptionalPathNode { + #[serde(serialize_with = "crate::path_serializer::serialize_absolute")] + pub optional: PathBuf, +} + +impl OptionalPathNode { + pub fn new(optional: PathBuf) -> Self { + OptionalPathNode { optional } + } +} + +/// Describes a path that is either optional or required +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(untagged)] +pub enum PathNode { + Required(#[serde(serialize_with = "crate::path_serializer::serialize_absolute")] PathBuf), + Optional(OptionalPathNode), +} + +impl PathNode { + pub fn path(&self) -> &Path { + match self { + PathNode::Required(pathbuf) => &pathbuf, + PathNode::Optional(OptionalPathNode { optional }) => &optional, + } + } +} + /// Describes an instance and its descendants in a project. #[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)] pub struct ProjectNode { @@ -224,12 +253,8 @@ pub struct ProjectNode { /// path can point to any file type supported by Rojo, including Lua files /// (`.lua`), Roblox models (`.rbxm`, `.rbxmx`), and localization table /// spreadsheets (`.csv`). - #[serde( - rename = "$path", - serialize_with = "crate::path_serializer::serialize_option_absolute", - skip_serializing_if = "Option::is_none" - )] - pub path: Option, + #[serde(rename = "$path", skip_serializing_if = "Option::is_none")] + pub path: Option, } impl ProjectNode { @@ -249,3 +274,106 @@ impl ProjectNode { } } } + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn path_node_required() { + let path_node: PathNode = serde_json::from_str(r#""src""#).unwrap(); + assert_eq!(path_node, PathNode::Required(PathBuf::from("src"))); + } + + #[test] + fn path_node_optional() { + let path_node: PathNode = serde_json::from_str(r#"{ "optional": "src" }"#).unwrap(); + assert_eq!( + path_node, + PathNode::Optional(OptionalPathNode::new(PathBuf::from("src"))) + ); + } + + #[test] + fn project_node_required() { + let project_node: ProjectNode = serde_json::from_str( + r#"{ + "$path": "src" + }"#, + ) + .unwrap(); + + assert_eq!( + project_node.path, + Some(PathNode::Required(PathBuf::from("src"))) + ); + } + + #[test] + fn project_node_optional() { + let project_node: ProjectNode = serde_json::from_str( + r#"{ + "$path": { "optional": "src" } + }"#, + ) + .unwrap(); + + assert_eq!( + project_node.path, + Some(PathNode::Optional(OptionalPathNode::new(PathBuf::from( + "src" + )))) + ); + } + + #[test] + fn project_node_none() { + let project_node: ProjectNode = serde_json::from_str( + r#"{ + "$className": "Folder" + }"#, + ) + .unwrap(); + + assert_eq!(project_node.path, None); + } + + #[test] + fn project_node_optional_serialize_absolute() { + let project_node: ProjectNode = serde_json::from_str( + r#"{ + "$path": { "optional": "..\\src" } + }"#, + ) + .unwrap(); + + let serialized = serde_json::to_string(&project_node).unwrap(); + assert_eq!(serialized, r#"{"$path":{"optional":"../src"}}"#); + } + + #[test] + fn project_node_optional_serialize_absolute_no_change() { + let project_node: ProjectNode = serde_json::from_str( + r#"{ + "$path": { "optional": "../src" } + }"#, + ) + .unwrap(); + + let serialized = serde_json::to_string(&project_node).unwrap(); + assert_eq!(serialized, r#"{"$path":{"optional":"../src"}}"#); + } + + #[test] + fn project_node_optional_serialize_optional() { + let project_node: ProjectNode = serde_json::from_str( + r#"{ + "$path": "..\\src" + }"#, + ) + .unwrap(); + + let serialized = serde_json::to_string(&project_node).unwrap(); + assert_eq!(serialized, r#"{"$path":"../src"}"#); + } +} diff --git a/src/serve_session.rs b/src/serve_session.rs index 2643cffd..2cf1dc1c 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -127,11 +127,10 @@ impl ServeSession { let instance_context = InstanceContext::default(); log::trace!("Generating snapshot of instances from VFS"); - let snapshot = snapshot_from_vfs(&instance_context, &vfs, &start_path)? - .expect("snapshot did not return an instance"); + let snapshot = snapshot_from_vfs(&instance_context, &vfs, &start_path)?; log::trace!("Computing initial patch set"); - let patch_set = compute_patch_set(&snapshot, &tree, root_id); + let patch_set = compute_patch_set(snapshot.as_ref(), &tree, root_id); log::trace!("Applying initial patch set"); apply_patch_set(&mut tree, patch_set); diff --git a/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs index 39974caf..76f0b26c 100644 --- a/src/snapshot/patch_compute.rs +++ b/src/snapshot/patch_compute.rs @@ -10,16 +10,27 @@ use super::{ InstanceSnapshot, InstanceWithMeta, RojoTree, }; -pub fn compute_patch_set(snapshot: &InstanceSnapshot, tree: &RojoTree, id: Ref) -> PatchSet { +pub fn compute_patch_set( + snapshot: Option<&InstanceSnapshot>, + tree: &RojoTree, + id: Ref, +) -> PatchSet { let mut patch_set = PatchSet::new(); - let mut context = ComputePatchContext::default(); - compute_patch_set_internal(&mut context, snapshot, tree, id, &mut patch_set); + if let Some(snapshot) = snapshot { + let mut context = ComputePatchContext::default(); - // Rewrite Ref properties to refer to instance IDs instead of snapshot IDs - // for all of the IDs that we know about so far. - rewrite_refs_in_updates(&context, &mut patch_set.updated_instances); - rewrite_refs_in_additions(&context, &mut patch_set.added_instances); + compute_patch_set_internal(&mut context, snapshot, tree, id, &mut patch_set); + + // Rewrite Ref properties to refer to instance IDs instead of snapshot IDs + // for all of the IDs that we know about so far. + rewrite_refs_in_updates(&context, &mut patch_set.updated_instances); + rewrite_refs_in_additions(&context, &mut patch_set.added_instances); + } else { + if id != tree.get_root_id() { + patch_set.removed_instances.push(id); + } + } patch_set } @@ -246,7 +257,7 @@ mod test { children: Vec::new(), }; - let patch_set = compute_patch_set(&snapshot, &tree, root_id); + let patch_set = compute_patch_set(Some(&snapshot), &tree, root_id); let expected_patch_set = PatchSet { updated_instances: vec![PatchUpdate { @@ -296,7 +307,7 @@ mod test { class_name: Cow::Borrowed("foo"), }; - let patch_set = compute_patch_set(&snapshot, &tree, root_id); + let patch_set = compute_patch_set(Some(&snapshot), &tree, root_id); let expected_patch_set = PatchSet { added_instances: vec![PatchAdd { diff --git a/src/snapshot/tests/compute.rs b/src/snapshot/tests/compute.rs index c62978c9..7b15d378 100644 --- a/src/snapshot/tests/compute.rs +++ b/src/snapshot/tests/compute.rs @@ -23,7 +23,7 @@ fn set_name_and_class_name() { children: Vec::new(), }; - let patch_set = compute_patch_set(&snapshot, &tree, tree.get_root_id()); + let patch_set = compute_patch_set(Some(&snapshot), &tree, tree.get_root_id()); let patch_value = redactions.redacted_yaml(patch_set); assert_yaml_snapshot!(patch_value); @@ -47,7 +47,7 @@ fn set_property() { children: Vec::new(), }; - let patch_set = compute_patch_set(&snapshot, &tree, tree.get_root_id()); + let patch_set = compute_patch_set(Some(&snapshot), &tree, tree.get_root_id()); let patch_value = redactions.redacted_yaml(patch_set); assert_yaml_snapshot!(patch_value); @@ -78,7 +78,7 @@ fn remove_property() { children: Vec::new(), }; - let patch_set = compute_patch_set(&snapshot, &tree, tree.get_root_id()); + let patch_set = compute_patch_set(Some(&snapshot), &tree, tree.get_root_id()); let patch_value = redactions.redacted_yaml(patch_set); assert_yaml_snapshot!(patch_value); @@ -107,7 +107,7 @@ fn add_child() { }], }; - let patch_set = compute_patch_set(&snapshot, &tree, tree.get_root_id()); + let patch_set = compute_patch_set(Some(&snapshot), &tree, tree.get_root_id()); let patch_value = redactions.redacted_yaml(patch_set); assert_yaml_snapshot!(patch_value); @@ -139,7 +139,7 @@ fn remove_child() { children: Vec::new(), }; - let patch_set = compute_patch_set(&snapshot, &tree, tree.get_root_id()); + let patch_set = compute_patch_set(Some(&snapshot), &tree, tree.get_root_id()); let patch_value = redactions.redacted_yaml(patch_set); assert_yaml_snapshot!(patch_value); diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 6c855eb8..5650c99a 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -5,7 +5,7 @@ use memofs::Vfs; use rbx_reflection::ClassTag; use crate::{ - project::{Project, ProjectNode}, + project::{PathNode, Project, ProjectNode}, snapshot::{ InstanceContext, InstanceMetadata, InstanceSnapshot, InstigatingSource, PathIgnoreRule, }, @@ -30,30 +30,31 @@ pub fn snapshot_project( context.add_path_ignore_rules(rules); - // TODO: If this project node is a path to an instance that Rojo doesn't - // understand, this may panic! - let mut snapshot = - snapshot_project_node(&context, path, &project.name, &project.tree, vfs, None)?.unwrap(); + match snapshot_project_node(&context, path, &project.name, &project.tree, vfs, None)? { + Some(found_snapshot) => { + let mut snapshot = found_snapshot; + // Setting the instigating source to the project file path is a little + // coarse. + // + // Ideally, we'd only snapshot the project file if the project file + // actually changed. Because Rojo only has the concept of one + // relevant path -> snapshot path mapping per instance, we pick the more + // conservative approach of snapshotting the project file if any + // relevant paths changed. + snapshot.metadata.instigating_source = Some(path.to_path_buf().into()); - // Setting the instigating source to the project file path is a little - // coarse. - // - // Ideally, we'd only snapshot the project file if the project file - // actually changed. Because Rojo only has the concept of one - // relevant path -> snapshot path mapping per instance, we pick the more - // conservative approach of snapshotting the project file if any - // relevant paths changed. - snapshot.metadata.instigating_source = Some(path.to_path_buf().into()); + // Mark this snapshot (the root node of the project file) as being + // related to the project file. + // + // We SHOULD NOT mark the project file as a relevant path for any + // nodes that aren't roots. They'll be updated as part of the project + // file being updated. + snapshot.metadata.relevant_paths.push(path.to_path_buf()); - // Mark this snapshot (the root node of the project file) as being - // related to the project file. - // - // We SHOULD NOT mark the project file as a relevant path for any - // nodes that aren't roots. They'll be updated as part of the project - // file being updated. - snapshot.metadata.relevant_paths.push(path.to_path_buf()); - - Ok(Some(snapshot)) + Ok(Some(snapshot)) + } + None => Ok(None), + } } pub fn snapshot_project_node( @@ -77,7 +78,9 @@ pub fn snapshot_project_node( let mut children = Vec::new(); let mut metadata = InstanceMetadata::default(); - if let Some(path) = &node.path { + if let Some(path_node) = &node.path { + let path = path_node.path(); + // If the path specified in the project is relative, we assume it's // relative to the folder that the project is in, project_folder. let full_path = if path.is_relative() { @@ -106,16 +109,6 @@ pub fn snapshot_project_node( // Take the snapshot's metadata as-is, which will be mutated later // on. metadata = snapshot.metadata; - } else { - anyhow::bail!( - "Rojo project referred to a file using $path that could not be turned into a Roblox Instance by Rojo.\n\ - Check that the file exists and is a file type known by Rojo.\n\ - \n\ - Project path: {}\n\ - File $path: {}", - project_path.display(), - path.display(), - ); } } @@ -125,20 +118,21 @@ pub fn snapshot_project_node( class_name_from_project, class_name_from_path, class_name_from_inference, + &node.path, ) { // These are the easy, happy paths! - (Some(project), None, None) => project, - (None, Some(path), None) => path, - (None, None, Some(inference)) => inference, + (Some(project), None, None, _) => project, + (None, Some(path), None, _) => path, + (None, None, Some(inference), _) => inference, // If the user specifies a class name, but there's an inferred class // name, we prefer the name listed explicitly by the user. - (Some(project), None, Some(_)) => project, + (Some(project), None, Some(_), _) => project, // If the user has a $path pointing to a folder and we're able to infer // a class name, let's use the inferred name. If the path we're pointing // to isn't a folder, though, that's a user error. - (None, Some(path), Some(inference)) => { + (None, Some(path), Some(inference), _) => { if path == "Folder" { inference } else { @@ -146,7 +140,7 @@ pub fn snapshot_project_node( } } - (Some(project), Some(path), _) => { + (Some(project), Some(path), _, _) => { if path == "Folder" { project } else { @@ -160,12 +154,28 @@ pub fn snapshot_project_node( project, path, project_path.display(), - node.path.as_ref().unwrap().display() + node.path.as_ref().unwrap().path().display() ); } } - (None, None, None) => { + (None, None, None, Some(PathNode::Optional(_))) => { + return Ok(None); + } + + (_, None, _, Some(PathNode::Required(path))) => { + anyhow::bail!( + "Rojo project referred to a file using $path that could not be turned into a Roblox Instance by Rojo.\n\ + Check that the file exists and is a file type known by Rojo.\n\ + \n\ + Project path: {}\n\ + File $path: {}", + project_path.display(), + path.display(), + ); + } + + (None, None, None, None) => { bail!( "Instance \"{}\" is missing some required information.\n\ One of the following must be true:\n\ diff --git a/tests/tests/build.rs b/tests/tests/build.rs index 748121fc..fc3b55fe 100644 --- a/tests/tests/build.rs +++ b/tests/tests/build.rs @@ -53,6 +53,7 @@ gen_build_tests! { txt, txt_in_folder, unresolved_values, + optional, weldconstraint, } diff --git a/tests/tests/serve.rs b/tests/tests/serve.rs index 4eb1ebe5..9cca9fac 100644 --- a/tests/tests/serve.rs +++ b/tests/tests/serve.rs @@ -220,3 +220,34 @@ fn empty_json_model() { ); }); } + +#[test] +#[ignore = "Rojo does not watch missing, optional files for changes."] +fn add_optional_folder() { + run_serve_test("add_optional_folder", |session, mut redactions| { + let info = session.get_api_rojo().unwrap(); + let root_id = info.root_instance_id; + + assert_yaml_snapshot!("add_optional_folder", redactions.redacted_yaml(info)); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "add_optional_folder_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); + + fs::create_dir(session.path().join("create-later")).unwrap(); + + let subscribe_response = session.get_api_subscribe(0).unwrap(); + assert_yaml_snapshot!( + "add_optional_folder_subscribe", + subscribe_response.intern_and_redact(&mut redactions, ()) + ); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "add_optional_folder_all-2", + read_response.intern_and_redact(&mut redactions, root_id) + ); + }); +} From 5d5536a95eb823b96e6aff5895c4f847eb27e0c7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Tue, 19 Apr 2022 18:45:09 -0400 Subject: [PATCH 1196/1504] Update CHANGELOG --- CHANGELOG.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c6952480..0013faeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,14 @@ # Rojo Changelog ## Unreleased Changes -* Added support for specifying an address to be used by default in the .project.json file ([#447]) -* Added support for the new Open Cloud API when uploading. ([#486]) +* Added support for specifying an address to be used by default in project files. ([#507]) +* Added support for optional paths in project files. ([#472]) +* Added support for the new Open Cloud API when uploading. ([#504]) * Added `sourcemap` command for generating sourcemaps to feed into other tools. ([#530]) -[#447]: https://github.com/rojo-rbx/rojo/issues/447 -[#486]: https://github.com/rojo-rbx/rojo/issues/486 +[#472]: https://github.com/rojo-rbx/rojo/pull/472 +[#504]: https://github.com/rojo-rbx/rojo/pull/504 +[#507]: https://github.com/rojo-rbx/rojo/pull/507 [#530]: https://github.com/rojo-rbx/rojo/pull/530 ## [7.0.0] - December 10, 2021 From 10abc2254ac50ccbdb2024a8da68921f2b735dbb Mon Sep 17 00:00:00 2001 From: boatbomber Date: Mon, 2 May 2022 14:28:18 -0700 Subject: [PATCH 1197/1504] Add changing toolbar icon to indicate state (#538) * Add changing toolbar icon * Return to default icon after closing error * Update changelog * Add assets * Improved link icon * Upload new icons Co-authored-by: Lucien Greathouse --- CHANGELOG.md | 6 ++++-- assets/icon-link-32.png | Bin 0 -> 1378 bytes assets/icon-warn-32.png | Bin 0 -> 1264 bytes .../App/Components/Studio/StudioToggleButton.lua | 6 +++++- plugin/src/App/init.lua | 10 ++++++++-- plugin/src/Assets.lua | 2 ++ 6 files changed, 19 insertions(+), 5 deletions(-) create mode 100644 assets/icon-link-32.png create mode 100644 assets/icon-warn-32.png diff --git a/CHANGELOG.md b/CHANGELOG.md index 0013faeb..204cea8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,13 @@ * Added support for optional paths in project files. ([#472]) * Added support for the new Open Cloud API when uploading. ([#504]) * Added `sourcemap` command for generating sourcemaps to feed into other tools. ([#530]) +* Added changing toolbar icon to indicate state ([#538]) [#472]: https://github.com/rojo-rbx/rojo/pull/472 [#504]: https://github.com/rojo-rbx/rojo/pull/504 [#507]: https://github.com/rojo-rbx/rojo/pull/507 [#530]: https://github.com/rojo-rbx/rojo/pull/530 +[#538]: https://github.com/rojo-rbx/rojo/pull/538 ## [7.0.0] - December 10, 2021 * Fixed Rojo's interactions with properties enabled by FFlags that are not yet enabled. ([#493]) @@ -96,7 +98,7 @@ The shorthand property format that most users use is not impacted. For reference ## [7.0.0-alpha.4][7.0.0-alpha.4] (May 5, 2021) * Added the `gameId` and `placeId` optional properties to project files. * When connecting from the Rojo Roblox Studio plugin, Rojo will set the game and place ID of the current place to these values, if set. - * This is equivalent to running `game:SetUniverseId(...)` and `game:SetPlaceId(...)` from the command bar in Studio. + * This is equivalent to running `game:SetUniverseId(...)` and `game:SetPlaceId(...)` from the command bar in Studio. * Added "EXPERIMENTAL!" label to two-way sync toggle in Rojo's Roblox Studio plugin. * Fixed `Name` and `Parent` properties being allowed in Rojo projects. ([#413][pr-413]) * Fixed "Open Scripts Externally" feature crashing Studio. ([#369][issue-369]) @@ -484,4 +486,4 @@ This is a general maintenance release for the Rojo 0.5.x release series. * More robust syncing with a new reconciler ## [0.1.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.1.0) (November 29, 2017) -* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) \ No newline at end of file +* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) diff --git a/assets/icon-link-32.png b/assets/icon-link-32.png new file mode 100644 index 0000000000000000000000000000000000000000..a69bbf997402843bb4ae8847b9015906723f4787 GIT binary patch literal 1378 zcmV-o1)chdP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGjU;qFQU;%n~MU4Oe1oufqK~z{rwO4IS zTU8i71EhQ?<5L8SWpfS&Srs#rEzwLgGBbaOiXq16HjF0zFfjG6=$MIrRN(IxH#g%4 znTu@3DHyX&7hR&;@ETw^5jx5?1Pbi}TPGEt=WtGUZ+qK-)}DS7v71vpgjwhjJ#^=i?LmIJZM!E;OyCi-yGjZ!qZT@=bT{xir?U6+K;$zm->= z>72(xAT&445OI$Chovw9ECxWqvHscFU)543;`*#x9@O)AZ%>%R!)K{!Tv!Z-z?(<&S0w`t(?t=)f44+Jj^{Ou-l{4Ni4xFpCRZh5tALDc217YP0&>L2^tq0i2)HGcGS;@)SP`*)TIeSH$ z_reZ!n-zw53}Xve0S_uxOEGs**zt#&kc%|qpSQ)=~&zUBVqOl}zkSFv8x0N4C(H@ z-~{+6SSF=HJOZ+Zbc6ZeHYooHS8Ecok({V<|EZP|%z@VjhqkF@Y#5>*?2|GZgbmQWoM7B}WmjWgXDM>c5@ZMDp@nM` z*kVV(SD|<($TK06t`KYj6NAa8Pc!CCNP~I6-}LE-_glPSh;^VBoL8IyqjD+|vI^+_ zZ`_qVQUd7K8wqYu+#|Yu(}(H`^0v?;mQ%1H(lKrX)4&sOJu4zHc;44AD27U_(&KkAiUol2fHBNEJxAKvYL*FEu4nPN~2uQhO;7a!eFJ zIUrRE3B5F^R85sO61gNuRN~N<4G~b%7-N0{$Y5hTI2f(9J;Wo1jSV(MeW%$sv+sTL z=9~B4D3FG9mdzyFh$Qnke$Y7MpjPX!-G+pp$ z<4v7jdyV9^*GNOdly|ahYlTqmb~0nG9Fl2>!auFI&H0s&+jDsAjxOgw>~Hjy(HjMMHTL) z1)$!bZ=}=i!0H9ZA5)0Dh1Jyi!!**VF+}>Gwz9 z`rR^?wYqpySGHQMr=15yG0^Vze39sQBmo%!`s1IsBmqwpRd|&W0CM-^;r?isaG6%( zcwlv{uXpL?)qRfl8vrHou?4_20ImZ`C{MM^(H*Z&rP7n4)U&kQRr$w6&VJ4%0i^)G zrksZXT#*D+9~gm_xlPmJ$=o`?_MohoWC% z?E9J|fKLd3KL4q$$OIWTp5~w^1^}QUi?#iBs{BuR4xn~_20(EFy#zobQ|l!Gb#FDCq?x#JqUa6{Y|K_U zN9Mft8mWypb>fIbxtn};3(q5e;6548L?TbmPD~b$#C1VY47m9Gt}$EXoL#5=;79<- z!=LE7U4H)JJn58fudMazR4V;YdFk&R=E9p~jd@}UB`l>2Kmh<_w#qr3N~H&Yi_^1psgzTPk#n~3rcRwor6*vL6{Q2k zuG7|z*(&GCSk{`(e+3LvG*n*tm?r3CwauR>n;!aQl!`cvoRjW~NE6fU_Ou+-8!B*w z(qS&_xs;dNCU11x-JX_YZ${No0vHVjM}G2ce4o!~%q5wbrDXRVmckyMVJtI|*OQ^x z-nYY%0(kQ_h;2UD@DGiL!lMo&=M2YU!KLWVeB80bGa8F~dwUlDm$dPw&dF+ Date: Mon, 2 May 2022 14:49:31 -0700 Subject: [PATCH 1198/1504] PluginActions for connecting/disconnecting a session (#537) * Create plugin action component * Add plugin action for session start/end * Add output for connection status change * Move host & port refs to App level so keybind can access them * Use passed function directly * Improve the action text clarity * Add actions for single action * Add to changelog * Explicitly return nil Co-authored-by: Lucien Greathouse * Change log level to info * Refactor startSession to contain the logic * Formatting Co-authored-by: Lucien Greathouse --- CHANGELOG.md | 2 + .../Components/Studio/StudioPluginAction.lua | 40 ++++++ plugin/src/App/StatusPages/NotConnected.lua | 24 +--- plugin/src/App/init.lua | 132 ++++++++++++++---- 4 files changed, 152 insertions(+), 46 deletions(-) create mode 100644 plugin/src/App/Components/Studio/StudioPluginAction.lua diff --git a/CHANGELOG.md b/CHANGELOG.md index 204cea8d..83c1ebeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,14 @@ * Added support for optional paths in project files. ([#472]) * Added support for the new Open Cloud API when uploading. ([#504]) * Added `sourcemap` command for generating sourcemaps to feed into other tools. ([#530]) +* Added PluginActions for connecting/disconnecting a session ([#537]) * Added changing toolbar icon to indicate state ([#538]) [#472]: https://github.com/rojo-rbx/rojo/pull/472 [#504]: https://github.com/rojo-rbx/rojo/pull/504 [#507]: https://github.com/rojo-rbx/rojo/pull/507 [#530]: https://github.com/rojo-rbx/rojo/pull/530 +[#537]: https://github.com/rojo-rbx/rojo/pull/537 [#538]: https://github.com/rojo-rbx/rojo/pull/538 ## [7.0.0] - December 10, 2021 diff --git a/plugin/src/App/Components/Studio/StudioPluginAction.lua b/plugin/src/App/Components/Studio/StudioPluginAction.lua new file mode 100644 index 00000000..458bd4fc --- /dev/null +++ b/plugin/src/App/Components/Studio/StudioPluginAction.lua @@ -0,0 +1,40 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Dictionary = require(Plugin.Dictionary) + +local StudioPluginContext = require(script.Parent.StudioPluginContext) + +local e = Roact.createElement + +local StudioPluginAction = Roact.Component:extend("StudioPluginAction") + +function StudioPluginAction:init() + self.pluginAction = self.props.plugin:CreatePluginAction( + self.props.name, self.props.title, self.props.description, self.props.icon, self.props.bindable + ) + + self.pluginAction.Triggered:Connect(self.props.onTriggered) +end + +function StudioPluginAction:render() + return nil +end + +function StudioPluginAction:willUnmount() + self.pluginAction:Destroy() +end + +local function StudioPluginActionWrapper(props) + return e(StudioPluginContext.Consumer, { + render = function(plugin) + return e(StudioPluginAction, Dictionary.merge(props, { + plugin = plugin, + })) + end, + }) +end + +return StudioPluginActionWrapper diff --git a/plugin/src/App/StatusPages/NotConnected.lua b/plugin/src/App/StatusPages/NotConnected.lua index 083f22c2..fb9434fc 100644 --- a/plugin/src/App/StatusPages/NotConnected.lua +++ b/plugin/src/App/StatusPages/NotConnected.lua @@ -82,11 +82,6 @@ end local NotConnectedPage = Roact.Component:extend("NotConnectedPage") -function NotConnectedPage:init() - self.hostRef = Roact.createRef() - self.portRef = Roact.createRef() -end - function NotConnectedPage:render() return Roact.createFragment({ Header = e(Header, { @@ -95,8 +90,8 @@ function NotConnectedPage:render() }), AddressEntry = e(AddressEntry, { - hostRef = self.hostRef, - portRef = self.portRef, + hostRef = self.props.hostRef, + portRef = self.props.portRef, transparency = self.props.transparency, layoutOrder = 2, }), @@ -119,18 +114,7 @@ function NotConnectedPage:render() style = "Solid", transparency = self.props.transparency, layoutOrder = 2, - onClick = function() - local hostText = self.hostRef.current.Text - local portText = self.portRef.current.Text - - lastHost = hostText - lastPort = portText - - self.props.onConnect( - #hostText > 0 and hostText or Config.defaultHost, - #portText > 0 and portText or Config.defaultPort - ) - end, + onClick = self.props.onConnect, }), Layout = e("UIListLayout", { @@ -156,4 +140,4 @@ function NotConnectedPage:render() }) end -return NotConnectedPage \ No newline at end of file +return NotConnectedPage diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 78c94015..e6dd50c7 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -16,6 +16,7 @@ local Theme = require(script.Theme) local PluginSettings = require(script.PluginSettings) local Page = require(script.Page) +local StudioPluginAction = require(script.Components.Studio.StudioPluginAction) local StudioToolbar = require(script.Components.Studio.StudioToolbar) local StudioToggleButton = require(script.Components.Studio.StudioToggleButton) local StudioPluginGui = require(script.Components.Studio.StudioPluginGui) @@ -37,6 +38,9 @@ local App = Roact.Component:extend("App") function App:init() preloadAssets() + self.hostRef = Roact.createRef() + self.portRef = Roact.createRef() + self:setState({ appStatus = AppStatus.NotConnected, guiEnabled = false, @@ -44,7 +48,17 @@ function App:init() }) end -function App:startSession(host, port, sessionOptions) +function App:startSession() + local hostText = self.hostRef.current.Text + local portText = self.portRef.current.Text + + local host = if #hostText > 0 then hostText else Config.defaultHost + local port = if #portText > 0 then portText else Config.defaultPort + local sessionOptions = { + openScriptsExternally = self.props.settings:get("openScriptsExternally"), + twoWaySync = self.props.settings:get("twoWaySync"), + } + local baseUrl = ("http://%s:%s"):format(host, port) local apiContext = ApiContext.new(baseUrl) @@ -68,6 +82,8 @@ function App:startSession(host, port, sessionOptions) address = address, toolbarIcon = Assets.Images.PluginButtonConnected, }) + + Log.info("Connected to session '{}' at {}", details, address) elseif status == ServeSession.Status.Disconnected then self.serveSession = nil @@ -86,6 +102,8 @@ function App:startSession(host, port, sessionOptions) appStatus = AppStatus.NotConnected, toolbarIcon = Assets.Images.PluginButton, }) + + Log.info("Disconnected session") end end end) @@ -95,6 +113,22 @@ function App:startSession(host, port, sessionOptions) self.serveSession = serveSession end +function App:endSession() + if self.serveSession == nil then + return + end + + Log.trace("Disconnecting session") + + self.serveSession:stop() + self.serveSession = nil + self:setState({ + appStatus = AppStatus.NotConnected, + }) + + Log.trace("Session terminated by user") +end + function App:render() local pluginName = "Rojo " .. Version.display(Config.version) @@ -141,22 +175,20 @@ function App:render() }) end, }, { - NotConnectedPage = PluginSettings.with(function(settings) - return createPageElement(AppStatus.NotConnected, { - onConnect = function(host, port) - self:startSession(host, port, { - openScriptsExternally = settings:get("openScriptsExternally"), - twoWaySync = settings:get("twoWaySync"), - }) - end, + NotConnectedPage = createPageElement(AppStatus.NotConnected, { + hostRef = self.hostRef, + portRef = self.portRef, - onNavigateSettings = function() - self:setState({ - appStatus = AppStatus.Settings, - }) - end, - }) - end), + onConnect = function() + self:startSession() + end, + + onNavigateSettings = function() + self:setState({ + appStatus = AppStatus.Settings, + }) + end, + }), Connecting = createPageElement(AppStatus.Connecting), @@ -165,15 +197,7 @@ function App:render() address = self.state.address, onDisconnect = function() - Log.trace("Disconnecting session") - - self.serveSession:stop() - self.serveSession = nil - self:setState({ - appStatus = AppStatus.NotConnected, - }) - - Log.trace("Session terminated by user") + self:endSession() end, }), @@ -206,6 +230,51 @@ function App:render() end), }), + toggleAction = e(StudioPluginAction, { + name = "RojoConnection", + title = "Rojo: Connect/Disconnect", + description = "Toggles the server for a Rojo sync session", + icon = Assets.Images.PluginButton, + bindable = true, + onTriggered = function() + if self.serveSession then + self:endSession() + else + self:startSession() + end + end, + }), + + connectAction = e(StudioPluginAction, { + name = "RojoConnect", + title = "Rojo: Connect", + description = "Connects the server for a Rojo sync session", + icon = Assets.Images.PluginButton, + bindable = true, + onTriggered = function() + if self.serveSession then + return + end + + self:startSession() + end, + }), + + disconnectAction = e(StudioPluginAction, { + name = "RojoDisconnect", + title = "Rojo: Disconnect", + description = "Disconnects the server for a Rojo sync session", + icon = Assets.Images.PluginButton, + bindable = true, + onTriggered = function() + if not self.serveSession then + return + end + + self:endSession() + end, + }), + toolbar = e(StudioToolbar, { name = pluginName, }, { @@ -229,4 +298,15 @@ function App:render() }) end -return App +return function(props) + return e(PluginSettings.StudioProvider, { + plugin = props.plugin, + }, { + App = PluginSettings.with(function(settings) + local settingsProps = Dictionary.merge(props, { + settings = settings, + }) + return e(App, settingsProps) + end), + }) +end \ No newline at end of file From f1d0f1c1c92e12f509d75f4fe2b102fa5b040bf5 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sun, 22 May 2022 15:47:11 -0700 Subject: [PATCH 1199/1504] Bugfix: PluginAction spam causing errors (#541) * Use session's state instead of existence to determine action * Retain host/port text * Use bindings instead of text/ref tunneling Co-authored-by: Lucien Greathouse --- plugin/src/App/StatusPages/NotConnected.lua | 28 ++++++++----- plugin/src/App/init.lua | 45 ++++++++++++--------- plugin/src/ServeSession.lua | 4 ++ 3 files changed, 47 insertions(+), 30 deletions(-) diff --git a/plugin/src/App/StatusPages/NotConnected.lua b/plugin/src/App/StatusPages/NotConnected.lua index fb9434fc..7cc7abfc 100644 --- a/plugin/src/App/StatusPages/NotConnected.lua +++ b/plugin/src/App/StatusPages/NotConnected.lua @@ -14,8 +14,6 @@ local PORT_WIDTH = 74 local DIVIDER_WIDTH = 1 local HOST_OFFSET = 12 -local lastHost, lastPort - local e = Roact.createElement local function AddressEntry(props) @@ -26,7 +24,7 @@ local function AddressEntry(props) layoutOrder = props.layoutOrder, }, { Host = e("TextBox", { - Text = lastHost or "", + Text = props.host or "", Font = Enum.Font.Code, TextSize = 18, TextColor3 = theme.AddressEntry.TextColor, @@ -34,6 +32,7 @@ local function AddressEntry(props) TextTransparency = props.transparency, PlaceholderText = Config.defaultHost, PlaceholderColor3 = theme.AddressEntry.PlaceholderColor, + ClearTextOnFocus = false, Size = UDim2.new(1, -(HOST_OFFSET + DIVIDER_WIDTH + PORT_WIDTH), 1, 0), Position = UDim2.new(0, HOST_OFFSET, 0, 0), @@ -41,17 +40,22 @@ local function AddressEntry(props) ClipsDescendants = true, BackgroundTransparency = 1, - [Roact.Ref] = props.hostRef, + [Roact.Change.Text] = function(object) + if props.onHostChange ~= nil then + props.onHostChange(object.Text) + end + end }), Port = e("TextBox", { - Text = lastPort or "", + Text = props.port or "", Font = Enum.Font.Code, TextSize = 18, TextColor3 = theme.AddressEntry.TextColor, TextTransparency = props.transparency, PlaceholderText = Config.defaultPort, PlaceholderColor3 = theme.AddressEntry.PlaceholderColor, + ClearTextOnFocus = false, Size = UDim2.new(0, PORT_WIDTH, 1, 0), Position = UDim2.new(1, 0, 0, 0), @@ -60,12 +64,14 @@ local function AddressEntry(props) ClipsDescendants = true, BackgroundTransparency = 1, - [Roact.Ref] = props.portRef, - [Roact.Change.Text] = function(object) local text = object.Text text = text:gsub("%D", "") object.Text = text + + if props.onPortChange ~= nil then + props.onPortChange(text) + end end, }, { Divider = e("Frame", { @@ -90,8 +96,10 @@ function NotConnectedPage:render() }), AddressEntry = e(AddressEntry, { - hostRef = self.props.hostRef, - portRef = self.props.portRef, + host = self.props.host, + port = self.props.port, + onHostChange = self.props.onHostChange, + onPortChange = self.props.onPortChange, transparency = self.props.transparency, layoutOrder = 2, }), @@ -140,4 +148,4 @@ function NotConnectedPage:render() }) end -return NotConnectedPage +return NotConnectedPage \ No newline at end of file diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index e6dd50c7..a6669f81 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -38,8 +38,8 @@ local App = Roact.Component:extend("App") function App:init() preloadAssets() - self.hostRef = Roact.createRef() - self.portRef = Roact.createRef() + self.host, self.setHost = Roact.createBinding("") + self.port, self.setPort = Roact.createBinding("") self:setState({ appStatus = AppStatus.NotConnected, @@ -48,12 +48,19 @@ function App:init() }) end -function App:startSession() - local hostText = self.hostRef.current.Text - local portText = self.portRef.current.Text +function App:getHostAndPort() + local host = self.host:getValue() + local port = self.port:getValue() + + local host = if #host > 0 then host else Config.defaultHost + local port = if #port > 0 then port else Config.defaultPort + + return host, port +end + +function App:startSession() + local host, port = self:getHostAndPort() - local host = if #hostText > 0 then hostText else Config.defaultHost - local port = if #portText > 0 then portText else Config.defaultPort local sessionOptions = { openScriptsExternally = self.props.settings:get("openScriptsExternally"), twoWaySync = self.props.settings:get("twoWaySync"), @@ -176,8 +183,10 @@ function App:render() end, }, { NotConnectedPage = createPageElement(AppStatus.NotConnected, { - hostRef = self.hostRef, - portRef = self.portRef, + host = self.host, + onHostChange = self.setHost, + port = self.port, + onPortChange = self.setPort, onConnect = function() self:startSession() @@ -237,10 +246,10 @@ function App:render() icon = Assets.Images.PluginButton, bindable = true, onTriggered = function() - if self.serveSession then - self:endSession() - else + if self.serveSession == nil or self.serveSession:getStatus() == ServeSession.Status.NotStarted then self:startSession() + elseif self.serveSession ~= nil and self.serveSession:getStatus() == ServeSession.Status.Connected then + self:endSession() end end, }), @@ -252,11 +261,9 @@ function App:render() icon = Assets.Images.PluginButton, bindable = true, onTriggered = function() - if self.serveSession then - return + if self.serveSession == nil or self.serveSession:getStatus() == ServeSession.Status.NotStarted then + self:startSession() end - - self:startSession() end, }), @@ -267,11 +274,9 @@ function App:render() icon = Assets.Images.PluginButton, bindable = true, onTriggered = function() - if not self.serveSession then - return + if self.serveSession ~= nil and self.serveSession:getStatus() == ServeSession.Status.Connected then + self:endSession() end - - self:endSession() end, }), diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index d0bff1f3..f9a3bd9b 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -113,6 +113,10 @@ function ServeSession:__fmtDebug(output) output:write("}") end +function ServeSession:getStatus() + return self.__status +end + function ServeSession:onStatusChanged(callback) self.__statusChangedCallback = callback end From a5a69fd9fc045d0299758fafd489c9b63541b08e Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 22 May 2022 18:53:45 -0400 Subject: [PATCH 1200/1504] Release v7.1.0 --- CHANGELOG.md | 5 +- Cargo.lock | 758 ++++++++++++++++++++++-------------------- Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 4 files changed, 404 insertions(+), 363 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 83c1ebeb..aff40072 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes + +## [7.1.0] - May 22, 2022 * Added support for specifying an address to be used by default in project files. ([#507]) * Added support for optional paths in project files. ([#472]) * Added support for the new Open Cloud API when uploading. ([#504]) @@ -14,6 +16,7 @@ [#530]: https://github.com/rojo-rbx/rojo/pull/530 [#537]: https://github.com/rojo-rbx/rojo/pull/537 [#538]: https://github.com/rojo-rbx/rojo/pull/538 +[7.1.0]: https://github.com/rojo-rbx/rojo/releases/tag/v7.1.0 ## [7.0.0] - December 10, 2021 * Fixed Rojo's interactions with properties enabled by FFlags that are not yet enabled. ([#493]) @@ -488,4 +491,4 @@ This is a general maintenance release for the Rojo 0.5.x release series. * More robust syncing with a new reconciler ## [0.1.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.1.0) (November 29, 2017) -* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) +* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 29a247a3..b9f64099 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,15 +26,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "ansi_term" version = "0.12.1" @@ -46,9 +37,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.48" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62e1f47f7dc0422027a4e370dd4548d4d66b26782e513e98dca1e689e058a80e" +checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" [[package]] name = "arrayref" @@ -75,21 +66,24 @@ dependencies = [ [[package]] name = "autocfg" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d49d90015b3c36167a20fe2810c5cd875ad504b39cff3d4eae7977e6b7c1cb2" +checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" +dependencies = [ + "autocfg 1.1.0", +] [[package]] name = "autocfg" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.63" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" +checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" dependencies = [ "addr2line", "cc", @@ -180,9 +174,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.8.0" +version = "3.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" +checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" [[package]] name = "byte-tools" @@ -224,9 +218,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a9137b95ea06864e018375b72adfb7db6e6f68cfc8df5a04d00288050485ee" +checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" [[package]] name = "cfg-if" @@ -242,11 +236,11 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "clap" -version = "2.33.3" +version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37e58ac78573c40708d45522f0d80fa2f01cc4f9b4e2bf749807255454312002" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "ansi_term 0.11.0", + "ansi_term", "atty", "bitflags", "strsim", @@ -266,13 +260,13 @@ dependencies = [ [[package]] name = "console" -version = "0.14.1" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3993e6445baa160675931ec041a5e03ca84b9c6e32a056150d3aa2bdda0a1f45" +checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" dependencies = [ "encode_unicode", - "lazy_static", "libc", + "once_cell", "terminal_size", "winapi 0.3.9", ] @@ -313,9 +307,9 @@ dependencies = [ [[package]] name = "core-foundation" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3" +checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" dependencies = [ "core-foundation-sys", "libc", @@ -329,9 +323,9 @@ checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" [[package]] name = "crc32fast" -version = "1.2.2" +version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3825b1e8580894917dc4468cb634a1b4e9745fddc854edad72d9c04644c0319f" +checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" dependencies = [ "cfg-if 1.0.0", ] @@ -374,12 +368,12 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.1" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ed27e177f16d65f0f0c22a213e17c696ace5dd64b14258b52f9417ccb52db4" +checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.8", ] [[package]] @@ -400,8 +394,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if 1.0.0", - "crossbeam-epoch 0.9.5", - "crossbeam-utils 0.8.5", + "crossbeam-epoch 0.9.8", + "crossbeam-utils 0.8.8", ] [[package]] @@ -410,7 +404,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "cfg-if 0.1.10", "crossbeam-utils 0.7.2", "lazy_static", @@ -421,14 +415,15 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.5" +version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec02e091aa634e2c3ada4a392989e7c3116673ef0ac5b72232439094d73b7fd" +checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" dependencies = [ + "autocfg 1.1.0", "cfg-if 1.0.0", - "crossbeam-utils 0.8.5", + "crossbeam-utils 0.8.8", "lazy_static", - "memoffset 0.6.4", + "memoffset 0.6.5", "scopeguard", ] @@ -449,16 +444,16 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "cfg-if 0.1.10", "lazy_static", ] [[package]] name = "crossbeam-utils" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" +checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" dependencies = [ "cfg-if 1.0.0", "lazy_static", @@ -482,7 +477,7 @@ checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" dependencies = [ "bstr", "csv-core", - "itoa", + "itoa 0.4.8", "ryu", "serde", ] @@ -498,11 +493,11 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccc0a48a9b826acdf4028595adc9db92caea352f7af011a3034acd172a52a0aa" +checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" dependencies = [ - "quote 1.0.10", + "quote 1.0.18", "syn", ] @@ -533,9 +528,9 @@ dependencies = [ [[package]] name = "dirs-sys" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03d86534ed367a67548dc68113a0f5db55432fdfbb6e6f9d77704397d95d5780" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", @@ -556,11 +551,13 @@ checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" [[package]] name = "embed-resource" -version = "1.6.5" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85505eb239fc952b300f29f0556d2d884082a83566768d980278d8faf38c780d" +checksum = "ecc24ff8d764818e9ab17963b0593c535f077a513f565e75e4352d758bc4d8c0" dependencies = [ "cc", + "rustc_version 0.4.0", + "toml", "vswhom", "winreg 0.10.1", ] @@ -573,9 +570,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.29" +version = "0.8.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" +checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" dependencies = [ "cfg-if 1.0.0", ] @@ -609,8 +606,8 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.39", + "quote 1.0.18", "syn", "synstructure", ] @@ -622,22 +619,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" [[package]] -name = "filetime" -version = "0.2.15" +name = "fastrand" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "975ccf83d8d9d0d84682850a38c8169027be83368805971cc4f238c2b245bc98" +checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +dependencies = [ + "instant", +] + +[[package]] +name = "filetime" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.2.10", + "redox_syscall 0.2.13", "winapi 0.3.9", ] [[package]] name = "flate2" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e6988e897c1c9c485f43b47a529cef42fde0547f9d8d41a7062518f1d8fc53f" +checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" dependencies = [ "cfg-if 1.0.0", "crc32fast", @@ -678,9 +684,9 @@ dependencies = [ [[package]] name = "fs-err" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ebd3504ad6116843b8375ad70df74e7bfe83cac77a1f3fe73200c844d43bfe0" +checksum = "5bd79fa345a495d3ae89fb7165fec01c0e72f41821d642dda363a1e97975652e" [[package]] name = "fsevent" @@ -731,9 +737,9 @@ checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" [[package]] name = "futures" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd0210d8c325c245ff06fd95a3b13689a1a276ac8cfa8e8720cb840bfb84b9e" +checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" dependencies = [ "futures-channel", "futures-core", @@ -746,9 +752,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27" +checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" dependencies = [ "futures-core", "futures-sink", @@ -756,9 +762,9 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445" +checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" [[package]] name = "futures-cpupool" @@ -772,9 +778,9 @@ dependencies = [ [[package]] name = "futures-executor" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b808bf53348a36cab739d7e04755909b9fcaaa69b7d7e588b37b6ec62704c97" +checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" dependencies = [ "futures-core", "futures-task", @@ -783,38 +789,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11" +checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" [[package]] name = "futures-macro" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89f17b21645bc4ed773c69af9c9a0effd4a3f1a3876eadd453469f8854e7fdd" +checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.39", + "quote 1.0.18", "syn", ] [[package]] name = "futures-sink" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af" +checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" [[package]] name = "futures-task" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12" +checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" [[package]] name = "futures-util" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e" +checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" dependencies = [ "futures-channel", "futures-core", @@ -850,9 +856,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" +checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if 1.0.0", "libc", @@ -940,18 +946,18 @@ checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" dependencies = [ "bytes 0.4.12", "fnv", - "itoa", + "itoa 0.4.8", ] [[package]] name = "http" -version = "0.2.5" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" +checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" dependencies = [ "bytes 1.1.0", "fnv", - "itoa", + "itoa 1.0.2", ] [[package]] @@ -968,20 +974,20 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ff4f84919677303da5f147645dbea6b1881f368d03ac84e1dc09031ebd7b2c6" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ "bytes 1.1.0", - "http 0.2.5", + "http 0.2.7", "pin-project-lite", ] [[package]] name = "httparse" -version = "1.5.1" +version = "1.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" +checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" [[package]] name = "httpdate" @@ -1009,7 +1015,7 @@ dependencies = [ "http-body 0.1.0", "httparse", "iovec", - "itoa", + "itoa 0.4.8", "log", "net2", "rustc_version 0.2.3", @@ -1027,22 +1033,22 @@ dependencies = [ [[package]] name = "hyper" -version = "0.14.15" +version = "0.14.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436ec0091e4f20e655156a30a0df3770fe2900aa301e548e08446ec794b6953c" +checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" dependencies = [ "bytes 1.1.0", "futures-channel", "futures-core", "futures-util", - "http 0.2.5", - "http-body 0.4.4", + "http 0.2.7", + "http-body 0.4.5", "httparse", "httpdate", - "itoa", + "itoa 1.0.2", "pin-project-lite", "socket2", - "tokio 1.14.0", + "tokio 1.18.2", "tower-service", "tracing", "want 0.3.0", @@ -1085,11 +1091,11 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" +checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "hashbrown", ] @@ -1115,19 +1121,27 @@ dependencies = [ [[package]] name = "insta" -version = "1.8.0" +version = "1.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15226a375927344c78d39dc6b49e2d5562a5b0705e26a589093c6792e52eed8e" +checksum = "689960f187c43c01650c805fb6bc6f55ab944499d86d4ffe9474ad78991d8e94" dependencies = [ "console", - "lazy_static", + "once_cell", "pest", "pest_derive", "serde", "serde_json", "serde_yaml", "similar", - "uuid 0.8.2", +] + +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if 1.0.0", ] [[package]] @@ -1141,9 +1155,9 @@ dependencies = [ [[package]] name = "itertools" -version = "0.10.1" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69ddb889f9d0d08a67338271fa9b62996bc788c7796a5c18cf057420aaed5eaf" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" dependencies = [ "either", ] @@ -1154,6 +1168,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" + [[package]] name = "jod-thread" version = "0.1.2" @@ -1162,9 +1182,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] name = "js-sys" -version = "0.3.55" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" dependencies = [ "wasm-bindgen", ] @@ -1193,9 +1213,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.108" +version = "0.2.126" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8521a1b57e76b1ec69af7599e75e38e7b7fad6610f037db8c79b127201b5d119" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] name = "linked-hash-map" @@ -1214,18 +1234,18 @@ dependencies = [ [[package]] name = "log" -version = "0.4.14" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "lz4" -version = "1.23.2" +version = "1.23.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aac20ed6991e01bf6a2e68cc73df2b389707403662a8ba89f68511fb340f724c" +checksum = "4edcb94251b1c375c459e5abe9fb0168c1c826c3370172684844f8f3f8d1a885" dependencies = [ "libc", "lz4-sys", @@ -1233,9 +1253,9 @@ dependencies = [ [[package]] name = "lz4-sys" -version = "1.9.2" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dca79aa95d8b3226213ad454d328369853be3a1382d89532a854f4d69640acae" +checksum = "d7be8908e2ed6f31c02db8a9fa962f03e36c53fbfde437363eae3306b85d7e17" dependencies = [ "cc", "libc", @@ -1261,9 +1281,9 @@ checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" [[package]] name = "memchr" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" @@ -1271,16 +1291,16 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", ] [[package]] name = "memoffset" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59accc507f1338036a0477ef61afdae33cde60840f4dfe481319ce3ad116ddf9" +checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", ] [[package]] @@ -1301,9 +1321,9 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mime_guess" -version = "2.0.3" +version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" dependencies = [ "mime", "unicase", @@ -1311,12 +1331,11 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.4.4" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" dependencies = [ "adler", - "autocfg 1.0.1", ] [[package]] @@ -1332,7 +1351,7 @@ dependencies = [ "kernel32-sys", "libc", "log", - "miow 0.2.2", + "miow", "net2", "slab", "winapi 0.2.8", @@ -1340,15 +1359,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.7.14" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8067b404fe97c70829f082dec8bcf4f71225d7eaea1d8645349cb76fa06205cc" +checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" dependencies = [ "libc", "log", - "miow 0.3.7", - "ntapi", - "winapi 0.3.9", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys", ] [[package]] @@ -1375,20 +1393,11 @@ dependencies = [ "ws2_32-sys", ] -[[package]] -name = "miow" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "native-tls" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" +checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" dependencies = [ "lazy_static", "libc", @@ -1431,29 +1440,20 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "ntapi" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "num-traits" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", ] [[package]] name = "num_cpus" -version = "1.13.0" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" +checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" dependencies = [ "hermit-abi", "libc", @@ -1461,18 +1461,18 @@ dependencies = [ [[package]] name = "object" -version = "0.27.1" +version = "0.28.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.8.0" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "7b10983b38c53aebdf33f542c6275b0f58a238129d00c4ae0e6fb59738d783ca" [[package]] name = "oorandom" @@ -1498,31 +1498,43 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.38" +version = "0.10.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c7ae222234c30df141154f159066c5093ff73b63204dcda7121eb082fc56a95" +checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" dependencies = [ "bitflags", "cfg-if 1.0.0", "foreign-types", "libc", "once_cell", + "openssl-macros", "openssl-sys", ] [[package]] -name = "openssl-probe" -version = "0.1.4" +name = "openssl-macros" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" +checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +dependencies = [ + "proc-macro2 1.0.39", + "quote 1.0.18", + "syn", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.71" +version = "0.9.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df13d165e607909b363a4757a6f133f8a818a74e9d3a98d09c6128e15fa4c73" +checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "cc", "libc", "pkg-config", @@ -1531,9 +1543,9 @@ dependencies = [ [[package]] name = "output_vt100" -version = "0.1.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53cdc5b785b7a58c5aad8216b3dfa114df64b0b06ae6e1501cef91df2fbdf8f9" +checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" dependencies = [ "winapi 0.3.9", ] @@ -1566,9 +1578,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0744126afe1a6dd7f394cb50a716dbe086cb06e255e53d8d0185d82828358fb5" +checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" [[package]] name = "percent-encoding" @@ -1609,8 +1621,8 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.39", + "quote 1.0.18", "syn", ] @@ -1627,9 +1639,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -1639,9 +1651,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.22" +version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" +checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" [[package]] name = "plotters" @@ -1673,9 +1685,9 @@ dependencies = [ [[package]] name = "ppv-lite86" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed0cfbc8191465bed66e1718596ee0b0b35d5ee1f41c5df2189d0fe8bde535ba" +checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "pretty_assertions" @@ -1683,7 +1695,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1cab0e7c02cf376875e9335e0ba1da535775beb5450d21e1dffca068818ed98b" dependencies = [ - "ansi_term 0.12.1", + "ansi_term", "ctor", "diff", "output_vt100", @@ -1696,8 +1708,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.39", + "quote 1.0.18", "syn", "version_check", ] @@ -1708,8 +1720,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.39", + "quote 1.0.18", "version_check", ] @@ -1736,11 +1748,11 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.32" +version = "1.0.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba508cc11742c0dc5c1659771673afbab7a0efab23aa17e854cbab0837ed0b43" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" dependencies = [ - "unicode-xid 0.2.2", + "unicode-ident", ] [[package]] @@ -1764,11 +1776,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.10" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38bc8cc6a5f2e3655e0899c1b848643b2562f853f114bfec7be120678e3ace05" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" dependencies = [ - "proc-macro2 1.0.32", + "proc-macro2 1.0.39", ] [[package]] @@ -1777,7 +1789,7 @@ version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" dependencies = [ - "autocfg 0.1.7", + "autocfg 0.1.8", "libc", "rand_chacha 0.1.1", "rand_core 0.4.2", @@ -1803,25 +1815,13 @@ dependencies = [ "rand_hc 0.2.0", ] -[[package]] -name = "rand" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" -dependencies = [ - "libc", - "rand_chacha 0.3.1", - "rand_core 0.6.3", - "rand_hc 0.3.1", -] - [[package]] name = "rand_chacha" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" dependencies = [ - "autocfg 0.1.7", + "autocfg 0.1.8", "rand_core 0.3.1", ] @@ -1835,16 +1835,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core 0.6.3", -] - [[package]] name = "rand_core" version = "0.3.1" @@ -1869,15 +1859,6 @@ dependencies = [ "getrandom 0.1.16", ] -[[package]] -name = "rand_core" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" -dependencies = [ - "getrandom 0.2.3", -] - [[package]] name = "rand_hc" version = "0.1.0" @@ -1896,15 +1877,6 @@ dependencies = [ "rand_core 0.5.1", ] -[[package]] -name = "rand_hc" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" -dependencies = [ - "rand_core 0.6.3", -] - [[package]] name = "rand_isaac" version = "0.1.1" @@ -1945,7 +1917,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" dependencies = [ - "autocfg 0.1.7", + "autocfg 0.1.8", "rand_core 0.4.2", ] @@ -1960,11 +1932,11 @@ dependencies = [ [[package]] name = "rayon" -version = "1.5.1" +version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06aca804d41dbc8ba42dfd964f0d01334eceb64314b9ecf7c5fad5188a06d90" +checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" dependencies = [ - "autocfg 1.0.1", + "autocfg 1.1.0", "crossbeam-deque 0.8.1", "either", "rayon-core", @@ -1972,14 +1944,13 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.9.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d78120e2c850279833f1dd3582f730c4ab53ed95aeaaaa862a2a5c71b1656d8e" +checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ "crossbeam-channel", "crossbeam-deque 0.8.1", - "crossbeam-utils 0.8.5", - "lazy_static", + "crossbeam-utils 0.8.8", "num_cpus", ] @@ -2075,28 +2046,29 @@ checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" [[package]] name = "redox_syscall" -version = "0.2.10" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" +checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" dependencies = [ "bitflags", ] [[package]] name = "redox_users" -version = "0.4.0" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64" +checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.3", - "redox_syscall 0.2.10", + "getrandom 0.2.6", + "redox_syscall 0.2.13", + "thiserror", ] [[package]] name = "regex" -version = "1.5.4" +version = "1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d07a8629359eb56f1e2fb1652bb04212c072a87ba68546a04065d525673ac461" +checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" dependencies = [ "aho-corasick", "memchr", @@ -2111,9 +2083,9 @@ checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" [[package]] name = "regex-syntax" -version = "0.6.25" +version = "0.6.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" +checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" [[package]] name = "remove_dir_all" @@ -2197,12 +2169,13 @@ dependencies = [ [[package]] name = "rmp" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f55e5fa1446c4d5dd1f5daeed2a4fe193071771a2636274d0d7a3b082aa7ad6" +checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f" dependencies = [ "byteorder", "num-traits", + "paste", ] [[package]] @@ -2229,7 +2202,7 @@ dependencies = [ [[package]] name = "rojo" -version = "7.0.0" +version = "7.1.0" dependencies = [ "anyhow", "backtrace", @@ -2240,10 +2213,10 @@ dependencies = [ "embed-resource", "env_logger", "fs-err", - "futures 0.3.18", + "futures 0.3.21", "globset", "humantime", - "hyper 0.14.15", + "hyper 0.14.18", "insta", "jod-thread", "lazy_static", @@ -2272,7 +2245,7 @@ dependencies = [ "tempfile", "termcolor", "thiserror", - "tokio 1.14.0", + "tokio 1.18.2", "uuid 0.8.2", "walkdir", "winreg 0.9.0", @@ -2307,14 +2280,14 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.4", + "semver 1.0.9", ] [[package]] name = "ryu" -version = "1.0.5" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" +checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" [[package]] name = "same-file" @@ -2327,12 +2300,12 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" +checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "winapi 0.3.9", + "windows-sys", ] [[package]] @@ -2343,9 +2316,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "security-framework" -version = "2.4.2" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" +checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" dependencies = [ "bitflags", "core-foundation", @@ -2356,9 +2329,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.4.2" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" +checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" dependencies = [ "core-foundation-sys", "libc", @@ -2375,9 +2348,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.4" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "568a8e6258aa33c13358f81fd834adb854c6f7c9468520910a9b1e8fac068012" +checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" [[package]] name = "semver-parser" @@ -2387,9 +2360,9 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.130" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" dependencies = [ "serde_derive", ] @@ -2406,22 +2379,22 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.39", + "quote 1.0.18", "syn", ] [[package]] name = "serde_json" -version = "1.0.72" +version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" +checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" dependencies = [ - "itoa", + "itoa 1.0.2", "ryu", "serde", ] @@ -2433,19 +2406,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" dependencies = [ "dtoa", - "itoa", + "itoa 0.4.8", "serde", "url 1.7.2", ] [[package]] name = "serde_yaml" -version = "0.8.21" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8c608a35705a5d3cdc9fbe403147647ff34b921f8e833e49306df898f9b20af" +checksum = "707d15895415db6628332b737c838b88c598522e4dc70647e59b72312924aebc" dependencies = [ - "dtoa", "indexmap", + "ryu", "serde", "yaml-rust", ] @@ -2464,15 +2437,15 @@ dependencies = [ [[package]] name = "similar" -version = "1.3.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad1d488a557b235fc46dae55512ffbfc429d2482b08b4d9435ab07384ca8aec" +checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3" [[package]] name = "slab" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9def91fd1e018fe007022791f865d0ccc9b3a0d5001e01aabb8b40e46000afb5" +checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" [[package]] name = "smallvec" @@ -2494,9 +2467,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.2" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" +checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" dependencies = [ "libc", "winapi 0.3.9", @@ -2519,9 +2492,9 @@ checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" [[package]] name = "structopt" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40b9788f4202aa75c240ecc9c15c65185e6a39ccdeb0fd5d008b98825464c87c" +checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" dependencies = [ "clap", "lazy_static", @@ -2536,8 +2509,8 @@ checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.39", + "quote 1.0.18", "syn", ] @@ -2549,13 +2522,13 @@ checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" [[package]] name = "syn" -version = "1.0.82" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8daf5dd0bb60cbd4137b1b587d2fc0ae729bc07cf01cd70b36a1ed5ade3b9d59" +checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", - "unicode-xid 0.2.2", + "proc-macro2 1.0.39", + "quote 1.0.18", + "unicode-ident", ] [[package]] @@ -2564,31 +2537,31 @@ version = "0.12.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.39", + "quote 1.0.18", "syn", - "unicode-xid 0.2.2", + "unicode-xid 0.2.3", ] [[package]] name = "tempfile" -version = "3.2.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" +checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" dependencies = [ "cfg-if 1.0.0", + "fastrand", "libc", - "rand 0.8.4", - "redox_syscall 0.2.10", + "redox_syscall 0.2.13", "remove_dir_all", "winapi 0.3.9", ] [[package]] name = "termcolor" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" dependencies = [ "winapi-util", ] @@ -2614,21 +2587,21 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417" +checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.30" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b" +checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.39", + "quote 1.0.18", "syn", ] @@ -2655,9 +2628,9 @@ dependencies = [ [[package]] name = "tinyvec" -version = "1.5.1" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c1c1d5a42b6245520c249549ec267180beaffcc0615401ac8e31853d4b6d8d2" +checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" dependencies = [ "tinyvec_macros", ] @@ -2689,15 +2662,16 @@ dependencies = [ [[package]] name = "tokio" -version = "1.14.0" +version = "1.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" +checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395" dependencies = [ - "autocfg 1.0.1", "libc", - "mio 0.7.14", + "mio 0.8.3", "num_cpus", + "once_cell", "pin-project-lite", + "socket2", "winapi 0.3.9", ] @@ -2815,6 +2789,15 @@ dependencies = [ "tokio-executor", ] +[[package]] +name = "toml" +version = "0.5.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +dependencies = [ + "serde", +] + [[package]] name = "tower-service" version = "0.3.1" @@ -2823,9 +2806,9 @@ checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" [[package]] name = "tracing" -version = "0.1.29" +version = "0.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "375a639232caf30edfc78e8d89b2d4c375515393e7af7e16f01cd96917fb2105" +checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -2834,9 +2817,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.21" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f4ed65637b8390770814083d20756f87bfa2c21bf2f110babdc5438351746e4" +checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" dependencies = [ "lazy_static", ] @@ -2858,9 +2841,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" +checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" [[package]] name = "ucd-trie" @@ -2879,9 +2862,15 @@ dependencies = [ [[package]] name = "unicode-bidi" -version = "0.3.7" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a01404663e3db436ed2746d9fefef640d868edae3cceb81c3b8d5732fda678f" +checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" + +[[package]] +name = "unicode-ident" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" [[package]] name = "unicode-normalization" @@ -2894,9 +2883,9 @@ dependencies = [ [[package]] name = "unicode-segmentation" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b" +checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" [[package]] name = "unicode-width" @@ -2912,9 +2901,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "unicode-xid" -version = "0.2.2" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" +checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" [[package]] name = "url" @@ -2954,7 +2943,7 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" dependencies = [ - "getrandom 0.2.3", + "getrandom 0.2.6", "serde", ] @@ -2972,9 +2961,9 @@ checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" [[package]] name = "version_check" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" +checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "vswhom" @@ -2988,9 +2977,9 @@ dependencies = [ [[package]] name = "vswhom-sys" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc2f5402d3d0e79a069714f7b48e3ecc60be7775a2c049cb839457457a239532" +checksum = "22025f6d8eb903ebf920ea6933b70b1e495be37e2cb4099e62c80454aaf57c39" dependencies = [ "cc", "libc", @@ -3041,10 +3030,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] -name = "wasm-bindgen" -version = "0.2.78" +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.80" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -3052,37 +3047,37 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.78" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.39", + "quote 1.0.18", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.78" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" dependencies = [ - "quote 1.0.10", + "quote 1.0.18", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.78" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" dependencies = [ - "proc-macro2 1.0.32", - "quote 1.0.10", + "proc-macro2 1.0.39", + "quote 1.0.18", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -3090,15 +3085,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.78" +version = "0.2.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" +checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" [[package]] name = "web-sys" -version = "0.3.55" +version = "0.3.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" +checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" dependencies = [ "js-sys", "wasm-bindgen", @@ -3147,6 +3142,49 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows-sys" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +dependencies = [ + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" + +[[package]] +name = "windows_i686_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" + +[[package]] +name = "windows_i686_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.36.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" + [[package]] name = "winreg" version = "0.6.2" diff --git a/Cargo.toml b/Cargo.toml index c76131ff..b7f27f54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "7.0.0" +version = "7.1.0" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 02d0b83d..2544b457 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {7, 0, 0}, + version = {7, 1, 0}, expectedServerVersionString = "7.0 or newer", protocolVersion = 4, defaultHost = "localhost", From ea58999a2ad88bf966f272c79f37c6b3cb0a2a3d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 22 May 2022 19:12:33 -0400 Subject: [PATCH 1201/1504] Update to pretty_assertions 1.2.1 --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b9f64099..7fe8ef55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1691,9 +1691,9 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "pretty_assertions" -version = "0.7.2" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cab0e7c02cf376875e9335e0ba1da535775beb5450d21e1dffca068818ed98b" +checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563" dependencies = [ "ansi_term", "ctor", diff --git a/Cargo.toml b/Cargo.toml index b7f27f54..9ae95aae 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -106,7 +106,7 @@ criterion = "0.3.5" insta = { version = "1.8.0", features = ["redactions"] } lazy_static = "1.4.0" paste = "1.0.5" -pretty_assertions = "0.7.2" +pretty_assertions = "1.2.1" serde_yaml = "0.8.21" tempfile = "3.2.0" walkdir = "2.3.2" From 57005c4fd534abc4703aafd72d71f1a9bab23d5b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 22 May 2022 19:13:11 -0400 Subject: [PATCH 1202/1504] Update uuid and winreg --- Cargo.lock | 17 ++++------------- Cargo.toml | 4 ++-- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7fe8ef55..58ff4143 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2246,9 +2246,9 @@ dependencies = [ "termcolor", "thiserror", "tokio 1.18.2", - "uuid 0.8.2", + "uuid 1.0.0", "walkdir", - "winreg 0.9.0", + "winreg 0.10.1", ] [[package]] @@ -2939,9 +2939,9 @@ dependencies = [ [[package]] name = "uuid" -version = "0.8.2" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5cf98d8186244414c848017f0e2676b3fcb46807f6668a97dfe67359a3c4b7" +checksum = "8cfcd319456c4d6ea10087ed423473267e1a071f3bc0aa89f80d60997843c6f0" dependencies = [ "getrandom 0.2.6", "serde", @@ -3194,15 +3194,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "winreg" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16cdb3898397cf7f624c294948669beafaeebc5577d5ec53d0afb76633593597" -dependencies = [ - "winapi 0.3.9", -] - [[package]] name = "winreg" version = "0.10.1" diff --git a/Cargo.toml b/Cargo.toml index 9ae95aae..702d3a26 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -85,10 +85,10 @@ structopt = "0.3.23" termcolor = "1.1.2" thiserror = "1.0.30" tokio = { version = "1.12.0", features = ["rt", "rt-multi-thread"] } -uuid = { version = "0.8.2", features = ["v4", "serde"] } +uuid = { version = "1.0.0", features = ["v4", "serde"] } [target.'cfg(windows)'.dependencies] -winreg = "0.9.0" +winreg = "0.10.1" [build-dependencies] memofs = { version = "0.2.0", path = "memofs" } From eaac53908750c07ca48368cbb347dd4397746865 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 22 May 2022 19:16:43 -0400 Subject: [PATCH 1203/1504] Update to reqwest 0.11.10 --- Cargo.lock | 909 ++++++---------------------------- Cargo.toml | 2 +- src/cli/upload.rs | 6 +- tests/rojo_test/serve_util.rs | 6 +- 4 files changed, 145 insertions(+), 778 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 58ff4143..ad5f7ae6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -64,15 +64,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "autocfg" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0dde43e75fd43e8a1bf86103336bc699aa8d17ad1be60c76c0bdfd4828e19b78" -dependencies = [ - "autocfg 1.1.0", -] - [[package]] name = "autocfg" version = "1.1.0" @@ -94,21 +85,18 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b25d992356d2eb0ed82172f5248873db5560c4721f564b13cb5193bda5e668e" -dependencies = [ - "byteorder", -] - [[package]] name = "base64" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + [[package]] name = "bincode" version = "1.3.3" @@ -190,17 +178,6 @@ version = "1.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -dependencies = [ - "byteorder", - "either", - "iovec", -] - [[package]] name = "bytes" version = "1.1.0" @@ -213,7 +190,7 @@ version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" dependencies = [ - "rustc_version 0.4.0", + "rustc_version", ] [[package]] @@ -249,15 +226,6 @@ dependencies = [ "vec_map", ] -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags", -] - [[package]] name = "console" version = "0.15.0" @@ -277,34 +245,6 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" -[[package]] -name = "cookie" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "888604f00b3db336d2af898ec3c1d5d0ddf5e6d462220f2ededc33a87ac4bbd5" -dependencies = [ - "time", - "url 1.7.2", -] - -[[package]] -name = "cookie_store" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46750b3f362965f197996c4448e4a0935e791bf7d6631bfce9ee0af3d24c919c" -dependencies = [ - "cookie", - "failure", - "idna 0.1.5", - "log", - "publicsuffix", - "serde", - "serde_json", - "time", - "try_from", - "url 1.7.2", -] - [[package]] name = "core-foundation" version = "0.9.3" @@ -321,15 +261,6 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" -[[package]] -name = "crc32fast" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" -dependencies = [ - "cfg-if 1.0.0", -] - [[package]] name = "criterion" version = "0.3.5" @@ -373,18 +304,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" dependencies = [ "cfg-if 1.0.0", - "crossbeam-utils 0.8.8", -] - -[[package]] -name = "crossbeam-deque" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed" -dependencies = [ - "crossbeam-epoch 0.8.2", - "crossbeam-utils 0.7.2", - "maybe-uninit", + "crossbeam-utils", ] [[package]] @@ -394,23 +314,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" dependencies = [ "cfg-if 1.0.0", - "crossbeam-epoch 0.9.8", - "crossbeam-utils 0.8.8", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" -dependencies = [ - "autocfg 1.1.0", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "lazy_static", - "maybe-uninit", - "memoffset 0.5.6", - "scopeguard", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] @@ -419,36 +324,14 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" dependencies = [ - "autocfg 1.1.0", + "autocfg", "cfg-if 1.0.0", - "crossbeam-utils 0.8.8", + "crossbeam-utils", "lazy_static", - "memoffset 0.6.5", + "memoffset", "scopeguard", ] -[[package]] -name = "crossbeam-queue" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" -dependencies = [ - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "maybe-uninit", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg 1.1.0", - "cfg-if 0.1.10", - "lazy_static", -] - [[package]] name = "crossbeam-utils" version = "0.8.8" @@ -537,12 +420,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "dtoa" -version = "0.4.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0" - [[package]] name = "either" version = "1.6.1" @@ -556,7 +433,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ecc24ff8d764818e9ab17963b0593c535f077a513f565e75e4352d758bc4d8c0" dependencies = [ "cc", - "rustc_version 0.4.0", + "rustc_version", "toml", "vswhom", "winreg 0.10.1", @@ -590,28 +467,6 @@ dependencies = [ "termcolor", ] -[[package]] -name = "failure" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" -dependencies = [ - "backtrace", - "failure_derive", -] - -[[package]] -name = "failure_derive" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa4da3c766cd7a0db8242e326e9e4e081edd567072893ed320008189715366a4" -dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn", - "synstructure", -] - [[package]] name = "fake-simd" version = "0.1.2" @@ -635,22 +490,10 @@ checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.2.13", + "redox_syscall", "winapi 0.3.9", ] -[[package]] -name = "flate2" -version = "1.0.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39522e96686d38f4bc984b9198e3a0613264abaebaff2c5c918bfa6b6da09af" -dependencies = [ - "cfg-if 1.0.0", - "crc32fast", - "libc", - "miniz_oxide", -] - [[package]] name = "fnv" version = "1.0.7" @@ -679,7 +522,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" dependencies = [ "matches", - "percent-encoding 2.1.0", + "percent-encoding", ] [[package]] @@ -707,12 +550,6 @@ dependencies = [ "libc", ] -[[package]] -name = "fuchsia-cprng" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" - [[package]] name = "fuchsia-zircon" version = "0.3.3" @@ -729,12 +566,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -[[package]] -name = "futures" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" - [[package]] name = "futures" version = "0.3.21" @@ -766,16 +597,6 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" -[[package]] -name = "futures-cpupool" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab90cde24b3319636588d0c35fe03b1333857621051837ed769faefb4c2162e4" -dependencies = [ - "futures 0.1.31", - "num_cpus", -] - [[package]] name = "futures-executor" version = "0.3.21" @@ -886,20 +707,21 @@ dependencies = [ [[package]] name = "h2" -version = "0.1.26" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5b34c246847f938a410a03c5458c7fee2274436675e76d8b903c08efc29c462" +checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" dependencies = [ - "byteorder", - "bytes 0.4.12", + "bytes", "fnv", - "futures 0.1.31", - "http 0.1.21", + "futures-core", + "futures-sink", + "futures-util", + "http", "indexmap", - "log", "slab", - "string", - "tokio-io", + "tokio", + "tokio-util", + "tracing", ] [[package]] @@ -938,48 +760,25 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" -[[package]] -name = "http" -version = "0.1.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6ccf5ede3a895d8856620237b2f02972c1bbc78d2965ad7fe8838d4a0ed41f0" -dependencies = [ - "bytes 0.4.12", - "fnv", - "itoa 0.4.8", -] - [[package]] name = "http" version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" dependencies = [ - "bytes 1.1.0", + "bytes", "fnv", "itoa 1.0.2", ] -[[package]] -name = "http-body" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "http 0.1.21", - "tokio-buf", -] - [[package]] name = "http-body" version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" dependencies = [ - "bytes 1.1.0", - "http 0.2.7", + "bytes", + "http", "pin-project-lite", ] @@ -1001,81 +800,41 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" -[[package]] -name = "hyper" -version = "0.12.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c843caf6296fc1f93444735205af9ed4e109a539005abb2564ae1d6fad34c52" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "futures-cpupool", - "h2", - "http 0.1.21", - "http-body 0.1.0", - "httparse", - "iovec", - "itoa 0.4.8", - "log", - "net2", - "rustc_version 0.2.3", - "time", - "tokio 0.1.22", - "tokio-buf", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", - "want 0.2.0", -] - [[package]] name = "hyper" version = "0.14.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" dependencies = [ - "bytes 1.1.0", + "bytes", "futures-channel", "futures-core", "futures-util", - "http 0.2.7", - "http-body 0.4.5", + "h2", + "http", + "http-body", "httparse", "httpdate", "itoa 1.0.2", "pin-project-lite", "socket2", - "tokio 1.18.2", + "tokio", "tower-service", "tracing", - "want 0.3.0", + "want", ] [[package]] name = "hyper-tls" -version = "0.3.2" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a800d6aa50af4b5850b2b0f659625ce9504df908e9733b635720483be26174f" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "hyper 0.12.36", + "bytes", + "hyper", "native-tls", - "tokio-io", -] - -[[package]] -name = "idna" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38f09e0f0b1fb55fdee1f17470ad800da77af5186a1a76c026b679358b7e844e" -dependencies = [ - "matches", - "unicode-bidi", - "unicode-normalization", + "tokio", + "tokio-native-tls", ] [[package]] @@ -1095,7 +854,7 @@ version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" dependencies = [ - "autocfg 1.1.0", + "autocfg", "hashbrown", ] @@ -1153,6 +912,12 @@ dependencies = [ "libc", ] +[[package]] +name = "ipnet" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" + [[package]] name = "itertools" version = "0.10.3" @@ -1223,15 +988,6 @@ version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" -[[package]] -name = "lock_api" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" -dependencies = [ - "scopeguard", -] - [[package]] name = "log" version = "0.4.17" @@ -1273,34 +1029,19 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "memchr" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" -[[package]] -name = "memoffset" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" -dependencies = [ - "autocfg 1.1.0", -] - [[package]] name = "memoffset" version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" dependencies = [ - "autocfg 1.1.0", + "autocfg", ] [[package]] @@ -1319,16 +1060,6 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" -[[package]] -name = "mime_guess" -version = "2.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" -dependencies = [ - "mime", - "unicase", -] - [[package]] name = "miniz_oxide" version = "0.5.1" @@ -1446,7 +1177,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" dependencies = [ - "autocfg 1.1.0", + "autocfg", ] [[package]] @@ -1534,7 +1265,7 @@ version = "0.9.73" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0" dependencies = [ - "autocfg 1.1.0", + "autocfg", "cc", "libc", "pkg-config", @@ -1550,44 +1281,12 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "parking_lot" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" -dependencies = [ - "lock_api", - "parking_lot_core", - "rustc_version 0.2.3", -] - -[[package]] -name = "parking_lot_core" -version = "0.6.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" -dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc", - "redox_syscall 0.1.57", - "rustc_version 0.2.3", - "smallvec", - "winapi 0.3.9", -] - [[package]] name = "paste" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" -[[package]] -name = "percent-encoding" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" - [[package]] name = "percent-encoding" version = "2.1.0" @@ -1743,7 +1442,7 @@ version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" dependencies = [ - "unicode-xid 0.1.0", + "unicode-xid", ] [[package]] @@ -1755,16 +1454,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "publicsuffix" -version = "1.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95b4ce31ff0a27d93c8de1849cf58162283752f065a90d508f1105fa6c9a213f" -dependencies = [ - "idna 0.2.3", - "url 2.2.2", -] - [[package]] name = "quote" version = "0.6.13" @@ -1783,25 +1472,6 @@ dependencies = [ "proc-macro2 1.0.39", ] -[[package]] -name = "rand" -version = "0.6.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d71dacdc3c88c1fde3885a3be3fbab9f35724e6ce99467f7d9c5026132184ca" -dependencies = [ - "autocfg 0.1.8", - "libc", - "rand_chacha 0.1.1", - "rand_core 0.4.2", - "rand_hc 0.1.0", - "rand_isaac", - "rand_jitter", - "rand_os", - "rand_pcg", - "rand_xorshift", - "winapi 0.3.9", -] - [[package]] name = "rand" version = "0.7.3" @@ -1810,19 +1480,9 @@ checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" dependencies = [ "getrandom 0.1.16", "libc", - "rand_chacha 0.2.2", - "rand_core 0.5.1", - "rand_hc 0.2.0", -] - -[[package]] -name = "rand_chacha" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556d3a1ca6600bfcbab7c7c91ccb085ac7fbbcd70e008a98742e7847f4f7bcef" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.3.1", + "rand_chacha", + "rand_core", + "rand_hc", ] [[package]] @@ -1832,24 +1492,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" dependencies = [ "ppv-lite86", - "rand_core 0.5.1", + "rand_core", ] -[[package]] -name = "rand_core" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" -dependencies = [ - "rand_core 0.4.2", -] - -[[package]] -name = "rand_core" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" - [[package]] name = "rand_core" version = "0.5.1" @@ -1859,75 +1504,13 @@ dependencies = [ "getrandom 0.1.16", ] -[[package]] -name = "rand_hc" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b40677c7be09ae76218dc623efbf7b18e34bced3f38883af07bb75630a21bc4" -dependencies = [ - "rand_core 0.3.1", -] - [[package]] name = "rand_hc" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "rand_core 0.5.1", -] - -[[package]] -name = "rand_isaac" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ded997c9d5f13925be2a6fd7e66bf1872597f759fd9dd93513dd7e92e5a5ee08" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "rand_jitter" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b" -dependencies = [ - "libc", - "rand_core 0.4.2", - "winapi 0.3.9", -] - -[[package]] -name = "rand_os" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071" -dependencies = [ - "cloudabi", - "fuchsia-cprng", - "libc", - "rand_core 0.4.2", - "rdrand", - "winapi 0.3.9", -] - -[[package]] -name = "rand_pcg" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abf9b09b01790cfe0364f52bf32995ea3c39f4d2dd011eac241d2914146d0b44" -dependencies = [ - "autocfg 0.1.8", - "rand_core 0.4.2", -] - -[[package]] -name = "rand_xorshift" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbf7e9e623549b0e21f6e97cf8ecf247c1a8fd2e8a992ae265314300b2455d5c" -dependencies = [ - "rand_core 0.3.1", + "rand_core", ] [[package]] @@ -1936,8 +1519,8 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" dependencies = [ - "autocfg 1.1.0", - "crossbeam-deque 0.8.1", + "autocfg", + "crossbeam-deque", "either", "rayon-core", ] @@ -1949,8 +1532,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" dependencies = [ "crossbeam-channel", - "crossbeam-deque 0.8.1", - "crossbeam-utils 0.8.8", + "crossbeam-deque", + "crossbeam-utils", "num_cpus", ] @@ -2010,7 +1593,7 @@ dependencies = [ "bitflags", "blake3", "lazy_static", - "rand 0.7.3", + "rand", "serde", "thiserror", ] @@ -2029,21 +1612,6 @@ dependencies = [ "xml-rs", ] -[[package]] -name = "rdrand" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" -dependencies = [ - "rand_core 0.3.1", -] - -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - [[package]] name = "redox_syscall" version = "0.2.13" @@ -2060,7 +1628,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom 0.2.6", - "redox_syscall 0.2.13", + "redox_syscall", "thiserror", ] @@ -2098,36 +1666,38 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.9.24" +version = "0.11.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f88643aea3c1343c804950d7bf983bd2067f5ab59db6d613a08e05572f2714ab" +checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" dependencies = [ - "base64 0.10.1", - "bytes 0.4.12", - "cookie", - "cookie_store", + "base64 0.13.0", + "bytes", "encoding_rs", - "flate2", - "futures 0.1.31", - "http 0.1.21", - "hyper 0.12.36", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", "hyper-tls", + "ipnet", + "js-sys", + "lazy_static", "log", "mime", - "mime_guess", "native-tls", + "percent-encoding", + "pin-project-lite", "serde", "serde_json", "serde_urlencoded", - "time", - "tokio 0.1.22", - "tokio-executor", - "tokio-io", - "tokio-threadpool", - "tokio-timer", - "url 1.7.2", - "uuid 0.7.4", - "winreg 0.6.2", + "tokio", + "tokio-native-tls", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "winreg 0.10.1", ] [[package]] @@ -2213,10 +1783,10 @@ dependencies = [ "embed-resource", "env_logger", "fs-err", - "futures 0.3.21", + "futures", "globset", "humantime", - "hyper 0.14.18", + "hyper", "insta", "jod-thread", "lazy_static", @@ -2245,8 +1815,8 @@ dependencies = [ "tempfile", "termcolor", "thiserror", - "tokio 1.18.2", - "uuid 1.0.0", + "tokio", + "uuid", "walkdir", "winreg 0.10.1", ] @@ -2265,22 +1835,13 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - [[package]] name = "rustc_version" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" dependencies = [ - "semver 1.0.9", + "semver", ] [[package]] @@ -2337,27 +1898,12 @@ dependencies = [ "libc", ] -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - [[package]] name = "semver" version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "serde" version = "1.0.137" @@ -2401,14 +1947,14 @@ dependencies = [ [[package]] name = "serde_urlencoded" -version = "0.5.5" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "642dd69105886af2efd227f75a520ec9b44a820d65bc133a9131f7d229fd165a" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ - "dtoa", - "itoa 0.4.8", + "form_urlencoded", + "itoa 1.0.2", + "ryu", "serde", - "url 1.7.2", ] [[package]] @@ -2447,15 +1993,6 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" -[[package]] -name = "smallvec" -version = "0.6.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" -dependencies = [ - "maybe-uninit", -] - [[package]] name = "snax" version = "0.2.0" @@ -2475,15 +2012,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "string" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d24114bfcceb867ca7f71a0d3fe45d45619ec47a6fbfa98cb14e14250bfa5d6d" -dependencies = [ - "bytes 0.4.12", -] - [[package]] name = "strsim" version = "0.8.0" @@ -2531,18 +2059,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "synstructure" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f36bdaa60a83aca3921b5259d5400cbf5e90fc51931376a9bd4a0eb79aa7210f" -dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn", - "unicode-xid 0.2.3", -] - [[package]] name = "tempfile" version = "3.3.0" @@ -2552,7 +2068,7 @@ dependencies = [ "cfg-if 1.0.0", "fastrand", "libc", - "redox_syscall 0.2.13", + "redox_syscall", "remove_dir_all", "winapi 0.3.9", ] @@ -2605,17 +2121,6 @@ dependencies = [ "syn", ] -[[package]] -name = "time" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" -dependencies = [ - "libc", - "wasi 0.10.0+wasi-snapshot-preview1", - "winapi 0.3.9", -] - [[package]] name = "tinytemplate" version = "1.2.1" @@ -2641,32 +2146,15 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" -[[package]] -name = "tokio" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "mio 0.6.23", - "num_cpus", - "tokio-current-thread", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", -] - [[package]] name = "tokio" version = "1.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395" dependencies = [ + "bytes", "libc", + "memchr", "mio 0.8.3", "num_cpus", "once_cell", @@ -2676,117 +2164,27 @@ dependencies = [ ] [[package]] -name = "tokio-buf" -version = "0.1.1" +name = "tokio-native-tls" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46" +checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" dependencies = [ - "bytes 0.4.12", - "either", - "futures 0.1.31", + "native-tls", + "tokio", ] [[package]] -name = "tokio-current-thread" -version = "0.1.7" +name = "tokio-util" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" +checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" dependencies = [ - "futures 0.1.31", - "tokio-executor", -] - -[[package]] -name = "tokio-executor" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.31", -] - -[[package]] -name = "tokio-io" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "log", -] - -[[package]] -name = "tokio-reactor" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.31", - "lazy_static", - "log", - "mio 0.6.23", - "num_cpus", - "parking_lot", - "slab", - "tokio-executor", - "tokio-io", - "tokio-sync", -] - -[[package]] -name = "tokio-sync" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" -dependencies = [ - "fnv", - "futures 0.1.31", -] - -[[package]] -name = "tokio-tcp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "iovec", - "mio 0.6.23", - "tokio-io", - "tokio-reactor", -] - -[[package]] -name = "tokio-threadpool" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" -dependencies = [ - "crossbeam-deque 0.7.4", - "crossbeam-queue", - "crossbeam-utils 0.7.2", - "futures 0.1.31", - "lazy_static", - "log", - "num_cpus", - "slab", - "tokio-executor", -] - -[[package]] -name = "tokio-timer" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.31", - "slab", - "tokio-executor", + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", ] [[package]] @@ -2812,9 +2210,21 @@ checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +dependencies = [ + "proc-macro2 1.0.39", + "quote 1.0.18", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.26" @@ -2830,15 +2240,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" -[[package]] -name = "try_from" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "283d3b89e1368717881a9d51dad843cc435380d8109c9e47d38780a324698d8b" -dependencies = [ - "cfg-if 0.1.10", -] - [[package]] name = "typenum" version = "1.15.0" @@ -2851,15 +2252,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" -[[package]] -name = "unicase" -version = "2.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" -dependencies = [ - "version_check", -] - [[package]] name = "unicode-bidi" version = "0.3.8" @@ -2899,23 +2291,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -[[package]] -name = "unicode-xid" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e51f3646910546462e67d5f7599b9e4fb8acdd304b087a6494730f9eebf04" - -[[package]] -name = "url" -version = "1.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd4e7c0d531266369519a4aa4f399d748bd37043b00bde1e4ff1f60a120b355a" -dependencies = [ - "idna 0.1.5", - "matches", - "percent-encoding 1.0.1", -] - [[package]] name = "url" version = "2.2.2" @@ -2923,18 +2298,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" dependencies = [ "form_urlencoded", - "idna 0.2.3", + "idna", "matches", - "percent-encoding 2.1.0", -] - -[[package]] -name = "uuid" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90dbc611eb48397705a6b0f6e917da23ae517e4d127123d2cf7674206627d32a" -dependencies = [ - "rand 0.6.5", + "percent-encoding", ] [[package]] @@ -2996,17 +2362,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "want" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6395efa4784b027708f7451087e647ec73cc74f5d9bc2e418404248d679a230" -dependencies = [ - "futures 0.1.31", - "log", - "try-lock", -] - [[package]] name = "want" version = "0.3.0" @@ -3060,6 +2415,18 @@ dependencies = [ "wasm-bindgen-shared", ] +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +dependencies = [ + "cfg-if 1.0.0", + "js-sys", + "wasm-bindgen", + "web-sys", +] + [[package]] name = "wasm-bindgen-macro" version = "0.2.80" diff --git a/Cargo.toml b/Cargo.toml index 702d3a26..27755e82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,7 +75,7 @@ maplit = "1.0.2" notify = "4.0.17" opener = "0.5.0" regex = "1.5.4" -reqwest = "0.9.24" +reqwest = { version = "0.11.10", features = ["blocking", "json"] } ritz = "0.1.0" rlua = "0.17.1" roblox_install = "1.0.0" diff --git a/src/cli/upload.rs b/src/cli/upload.rs index 2006ac66..2f4d2d63 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -123,7 +123,7 @@ fn do_upload(buffer: Vec, asset_id: u64, cookie: &str) -> anyhow::Result<()> asset_id ); - let client = reqwest::Client::new(); + let client = reqwest::blocking::Client::new(); let build_request = move || { client @@ -172,10 +172,10 @@ fn do_upload_open_cloud( universe_id, asset_id ); - let client = reqwest::Client::new(); + let client = reqwest::blocking::Client::new(); log::debug!("Uploading to Roblox..."); - let mut response = client + let response = client .post(&url) .header("x-api-key", api_key) .header(CONTENT_TYPE, "application/xml") diff --git a/tests/rojo_test/serve_util.rs b/tests/rojo_test/serve_util.rs index 981bb00b..d8253612 100644 --- a/tests/rojo_test/serve_util.rs +++ b/tests/rojo_test/serve_util.rs @@ -141,14 +141,14 @@ impl TestServeSession { pub fn get_api_rojo(&self) -> Result { let url = format!("http://localhost:{}/api/rojo", self.port); - let body = reqwest::get(&url)?.text()?; + let body = reqwest::blocking::get(&url)?.text()?; Ok(serde_json::from_str(&body).expect("Server returned malformed response")) } pub fn get_api_read(&self, id: Ref) -> Result { let url = format!("http://localhost:{}/api/read/{}", self.port, id); - let body = reqwest::get(&url)?.text()?; + let body = reqwest::blocking::get(&url)?.text()?; Ok(serde_json::from_str(&body).expect("Server returned malformed response")) } @@ -159,7 +159,7 @@ impl TestServeSession { ) -> Result, reqwest::Error> { let url = format!("http://localhost:{}/api/subscribe/{}", self.port, cursor); - reqwest::get(&url)?.json() + reqwest::blocking::get(&url)?.json() } } From 18e53f06fe5336b3b4c4091b996c474e6a2f8f00 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 22 May 2022 19:20:41 -0400 Subject: [PATCH 1204/1504] Remove unused dependencies and dead code warnings --- Cargo.lock | 15 --------------- Cargo.toml | 3 --- src/message_queue.rs | 1 + src/path_serializer.rs | 14 -------------- 4 files changed, 1 insertion(+), 32 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ad5f7ae6..69586d8d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1724,19 +1724,6 @@ dependencies = [ "snax", ] -[[package]] -name = "rlua" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93397b9792dc237cab7554ab4c4128b8aa5fc9ec25892cfd82c92286055313d0" -dependencies = [ - "bitflags", - "bstr", - "cc", - "libc", - "num-traits", -] - [[package]] name = "rmp" version = "0.8.11" @@ -1802,10 +1789,8 @@ dependencies = [ "rbx_reflection", "rbx_reflection_database", "rbx_xml", - "regex", "reqwest", "ritz", - "rlua", "roblox_install", "rojo-insta-ext", "serde", diff --git a/Cargo.toml b/Cargo.toml index 27755e82..5543208a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,15 +69,12 @@ globset = "0.4.8" humantime = "2.1.0" hyper = { version = "0.14.13", features = ["server", "tcp", "http1"] } jod-thread = "0.1.2" -lazy_static = "1.4.0" log = "0.4.14" maplit = "1.0.2" notify = "4.0.17" opener = "0.5.0" -regex = "1.5.4" reqwest = { version = "0.11.10", features = ["blocking", "json"] } ritz = "0.1.0" -rlua = "0.17.1" roblox_install = "1.0.0" serde = { version = "1.0.130", features = ["derive", "rc"] } serde_json = "1.0.68" diff --git a/src/message_queue.rs b/src/message_queue.rs index cbac1862..56482ea1 100644 --- a/src/message_queue.rs +++ b/src/message_queue.rs @@ -64,6 +64,7 @@ impl MessageQueue { /// This method is only useful in tests. Non-test code should use subscribe /// instead. #[cfg(test)] + #[allow(unused)] pub fn subscribe_any(&self) -> oneshot::Receiver<(u32, Vec)> { let cursor = { let messages = self.messages.read().unwrap(); diff --git a/src/path_serializer.rs b/src/path_serializer.rs index 18a61707..74eb9534 100644 --- a/src/path_serializer.rs +++ b/src/path_serializer.rs @@ -36,17 +36,3 @@ where seq.end() } - -pub fn serialize_option_absolute( - maybe_path: &Option, - serializer: S, -) -> Result -where - S: Serializer, - T: AsRef, -{ - match maybe_path { - Some(path) => serialize_absolute(path, serializer), - None => serializer.serialize_none(), - } -} From 3cef2fe9aa45a8dcf02303c59c5e920f6543ea13 Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Mon, 23 May 2022 21:19:30 +0200 Subject: [PATCH 1205/1504] Fix sourcemap command not stripping paths correctly (#544) * Fix sourcemap command not stripping paths correctly * Use ServeSession to get the proper root dir to strip for sourcemap --- src/cli/sourcemap.rs | 5 +---- src/serve_session.rs | 4 ++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cli/sourcemap.rs b/src/cli/sourcemap.rs index 66341dc8..8cda48ff 100644 --- a/src/cli/sourcemap.rs +++ b/src/cli/sourcemap.rs @@ -56,9 +56,6 @@ impl SourcemapCommand { pub fn run(self) -> anyhow::Result<()> { let project_path = resolve_path(&self.project); - let mut project_dir = project_path.to_path_buf(); - project_dir.pop(); - log::trace!("Constructing in-memory filesystem"); let vfs = Vfs::new_default(); @@ -71,7 +68,7 @@ impl SourcemapCommand { filter_non_scripts }; - let root_node = recurse_create_node(&tree, tree.get_root_id(), &project_dir, filter); + let root_node = recurse_create_node(&tree, tree.get_root_id(), session.root_dir(), filter); if let Some(output_path) = self.output { let mut file = BufWriter::new(File::create(&output_path)?); diff --git a/src/serve_session.rs b/src/serve_session.rs index 2cf1dc1c..a4eced44 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -216,6 +216,10 @@ impl ServeSession { pub fn serve_address(&self) -> Option { self.root_project.serve_address } + + pub fn root_dir(&self) -> &Path { + self.root_project.folder_location() + } } #[derive(Debug, Error)] From 0a412ade8883232148760a517a7a794d9f148272 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 25 May 2022 15:48:10 -0700 Subject: [PATCH 1206/1504] Remove duplicate PluginSettings.StudioProvider (#545) --- plugin/src/App/init.lua | 258 ++++++++++++++++++++-------------------- 1 file changed, 127 insertions(+), 131 deletions(-) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index a6669f81..ed9b4443 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -154,150 +154,146 @@ function App:render() value = self.props.plugin, }, { e(Theme.StudioProvider, nil, { - e(PluginSettings.StudioProvider, { - plugin = self.props.plugin, + gui = e(StudioPluginGui, { + id = pluginName, + title = pluginName, + active = self.state.guiEnabled, + + initDockState = Enum.InitialDockState.Right, + initEnabled = false, + overridePreviousState = false, + floatingSize = Vector2.new(300, 200), + minimumSize = Vector2.new(300, 200), + + zIndexBehavior = Enum.ZIndexBehavior.Sibling, + + onInitialState = function(initialState) + self:setState({ + guiEnabled = initialState, + }) + end, + + onClose = function() + self:setState({ + guiEnabled = false, + }) + end, }, { - gui = e(StudioPluginGui, { - id = pluginName, - title = pluginName, - active = self.state.guiEnabled, + NotConnectedPage = createPageElement(AppStatus.NotConnected, { + host = self.host, + onHostChange = self.setHost, + port = self.port, + onPortChange = self.setPort, - initDockState = Enum.InitialDockState.Right, - initEnabled = false, - overridePreviousState = false, - floatingSize = Vector2.new(300, 200), - minimumSize = Vector2.new(300, 200), + onConnect = function() + self:startSession() + end, - zIndexBehavior = Enum.ZIndexBehavior.Sibling, - - onInitialState = function(initialState) + onNavigateSettings = function() self:setState({ - guiEnabled = initialState, + appStatus = AppStatus.Settings, }) end, + }), + + Connecting = createPageElement(AppStatus.Connecting), + + Connected = createPageElement(AppStatus.Connected, { + projectName = self.state.projectName, + address = self.state.address, + + onDisconnect = function() + self:endSession() + end, + }), + + Settings = createPageElement(AppStatus.Settings, { + onBack = function() + self:setState({ + appStatus = AppStatus.NotConnected, + }) + end, + }), + + Error = createPageElement(AppStatus.Error, { + errorMessage = self.state.errorMessage, onClose = function() self:setState({ - guiEnabled = false, + appStatus = AppStatus.NotConnected, + toolbarIcon = Assets.Images.PluginButton, }) end, - }, { - NotConnectedPage = createPageElement(AppStatus.NotConnected, { - host = self.host, - onHostChange = self.setHost, - port = self.port, - onPortChange = self.setPort, - - onConnect = function() - self:startSession() - end, - - onNavigateSettings = function() - self:setState({ - appStatus = AppStatus.Settings, - }) - end, - }), - - Connecting = createPageElement(AppStatus.Connecting), - - Connected = createPageElement(AppStatus.Connected, { - projectName = self.state.projectName, - address = self.state.address, - - onDisconnect = function() - self:endSession() - end, - }), - - Settings = createPageElement(AppStatus.Settings, { - onBack = function() - self:setState({ - appStatus = AppStatus.NotConnected, - }) - end, - }), - - Error = createPageElement(AppStatus.Error, { - errorMessage = self.state.errorMessage, - - onClose = function() - self:setState({ - appStatus = AppStatus.NotConnected, - toolbarIcon = Assets.Images.PluginButton, - }) - end, - }), - - Background = Theme.with(function(theme) - return e("Frame", { - Size = UDim2.new(1, 0, 1, 0), - BackgroundColor3 = theme.BackgroundColor, - ZIndex = 0, - BorderSizePixel = 0, - }) - end), }), - toggleAction = e(StudioPluginAction, { - name = "RojoConnection", - title = "Rojo: Connect/Disconnect", - description = "Toggles the server for a Rojo sync session", - icon = Assets.Images.PluginButton, - bindable = true, - onTriggered = function() - if self.serveSession == nil or self.serveSession:getStatus() == ServeSession.Status.NotStarted then - self:startSession() - elseif self.serveSession ~= nil and self.serveSession:getStatus() == ServeSession.Status.Connected then - self:endSession() - end - end, - }), - - connectAction = e(StudioPluginAction, { - name = "RojoConnect", - title = "Rojo: Connect", - description = "Connects the server for a Rojo sync session", - icon = Assets.Images.PluginButton, - bindable = true, - onTriggered = function() - if self.serveSession == nil or self.serveSession:getStatus() == ServeSession.Status.NotStarted then - self:startSession() - end - end, - }), - - disconnectAction = e(StudioPluginAction, { - name = "RojoDisconnect", - title = "Rojo: Disconnect", - description = "Disconnects the server for a Rojo sync session", - icon = Assets.Images.PluginButton, - bindable = true, - onTriggered = function() - if self.serveSession ~= nil and self.serveSession:getStatus() == ServeSession.Status.Connected then - self:endSession() - end - end, - }), - - toolbar = e(StudioToolbar, { - name = pluginName, - }, { - button = e(StudioToggleButton, { - name = "Rojo", - tooltip = "Show or hide the Rojo panel", - icon = self.state.toolbarIcon, - active = self.state.guiEnabled, - enabled = true, - onClick = function() - self:setState(function(state) - return { - guiEnabled = not state.guiEnabled, - } - end) - end, + Background = Theme.with(function(theme) + return e("Frame", { + Size = UDim2.new(1, 0, 1, 0), + BackgroundColor3 = theme.BackgroundColor, + ZIndex = 0, + BorderSizePixel = 0, }) - }), + end), + }), + + toggleAction = e(StudioPluginAction, { + name = "RojoConnection", + title = "Rojo: Connect/Disconnect", + description = "Toggles the server for a Rojo sync session", + icon = Assets.Images.PluginButton, + bindable = true, + onTriggered = function() + if self.serveSession == nil or self.serveSession:getStatus() == ServeSession.Status.NotStarted then + self:startSession() + elseif self.serveSession ~= nil and self.serveSession:getStatus() == ServeSession.Status.Connected then + self:endSession() + end + end, + }), + + connectAction = e(StudioPluginAction, { + name = "RojoConnect", + title = "Rojo: Connect", + description = "Connects the server for a Rojo sync session", + icon = Assets.Images.PluginButton, + bindable = true, + onTriggered = function() + if self.serveSession == nil or self.serveSession:getStatus() == ServeSession.Status.NotStarted then + self:startSession() + end + end, + }), + + disconnectAction = e(StudioPluginAction, { + name = "RojoDisconnect", + title = "Rojo: Disconnect", + description = "Disconnects the server for a Rojo sync session", + icon = Assets.Images.PluginButton, + bindable = true, + onTriggered = function() + if self.serveSession ~= nil and self.serveSession:getStatus() == ServeSession.Status.Connected then + self:endSession() + end + end, + }), + + toolbar = e(StudioToolbar, { + name = pluginName, + }, { + button = e(StudioToggleButton, { + name = "Rojo", + tooltip = "Show or hide the Rojo panel", + icon = self.state.toolbarIcon, + active = self.state.guiEnabled, + enabled = true, + onClick = function() + self:setState(function(state) + return { + guiEnabled = not state.guiEnabled, + } + end) + end, + }) }), }), }) @@ -314,4 +310,4 @@ return function(props) return e(App, settingsProps) end), }) -end \ No newline at end of file +end From 1f1193e857814182f35ca86e06827ae687a52fe5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 25 May 2022 18:48:57 -0400 Subject: [PATCH 1207/1504] Remove unused lazy_static --- Cargo.lock | 1 - Cargo.toml | 1 - 2 files changed, 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 69586d8d..a7eb79cb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1776,7 +1776,6 @@ dependencies = [ "hyper", "insta", "jod-thread", - "lazy_static", "log", "maplit", "memofs", diff --git a/Cargo.toml b/Cargo.toml index 5543208a..5c970cf9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -101,7 +101,6 @@ rojo-insta-ext = { path = "rojo-insta-ext" } criterion = "0.3.5" insta = { version = "1.8.0", features = ["redactions"] } -lazy_static = "1.4.0" paste = "1.0.5" pretty_assertions = "1.2.1" serde_yaml = "0.8.21" From 192fd7d4ddca2d17b6b660e574c5827bb29da1ea Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 25 May 2022 18:53:08 -0400 Subject: [PATCH 1208/1504] New and improved CI pipeline --- .github/workflows/ci.yml | 46 +++++++++++++++++++++++++++------------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 93048409..30110fa3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,37 +3,53 @@ name: CI on: push: branches: - - master + - main pull_request: branches: - - master + - main jobs: build: - + name: Build and Test runs-on: ubuntu-latest strategy: matrix: - rust_version: [stable, "1.55.0"] + rust_version: [stable, 1.55.0] steps: - - uses: actions/checkout@v1 - with: - submodules: true + - uses: actions/checkout@v3 - - name: Setup Rust toolchain - run: rustup default ${{ matrix.rust_version }} + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: ${{ matrix.rust_version }} + override: true + profile: minimal - name: Build run: cargo build --locked --verbose - - name: Run tests + - name: Test run: cargo test --locked --verbose - - name: Rustfmt and Clippy - run: | - cargo fmt -- --check - cargo clippy - if: matrix.rust_version == 'stable' \ No newline at end of file + lint: + name: Rustfmt and Clippy + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + override: true + components: rustfmt, clippy + + - name: Rustfmt + run: cargo fmt -- --check + + - name: Clippy + run: cargo clippy \ No newline at end of file From e169d7be68a1bd9706d3facb9bb7e87b380d542a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 25 May 2022 22:26:22 -0400 Subject: [PATCH 1209/1504] New release workflow (#547) * Port release workflow from Aftman to test * Checkout submodules in plugin build step * ...and build with submodules for other builds too * Fix ci.yml; we use master branch still * CI with submodules too --- .github/workflows/ci.yml | 8 +- .github/workflows/release.yml | 199 ++++++++++++++++++++++++---------- 2 files changed, 149 insertions(+), 58 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 30110fa3..a589a7e7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,11 +3,11 @@ name: CI on: push: branches: - - main + - master pull_request: branches: - - main + - master jobs: build: @@ -20,6 +20,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: true - name: Install Rust uses: actions-rs/toolchain@v1 @@ -40,6 +42,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: true - name: Install Rust uses: actions-rs/toolchain@v1 diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index bf43ed0f..05ec5bd4 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -2,65 +2,152 @@ name: Release on: push: - tags: ["*"] + tags: ["v*"] jobs: - windows: - runs-on: windows-latest - - steps: - - uses: actions/checkout@v1 - with: - submodules: true - - - name: Build release binary - run: cargo build --verbose --locked --release - - - name: Upload artifacts - uses: actions/upload-artifact@v1 - with: - name: rojo-win64 - path: target/release/rojo.exe - - macos: - runs-on: macos-latest - - steps: - - uses: actions/checkout@v1 - with: - submodules: true - - - name: Install Rust - run: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y - - - name: Build release binary - run: | - source $HOME/.cargo/env - cargo build --verbose --locked --release - env: - OPENSSL_STATIC: 1 - - - name: Upload artifacts - uses: actions/upload-artifact@v1 - with: - name: rojo-macos - path: target/release/rojo - - linux: + create-release: + name: Create Release runs-on: ubuntu-latest - + outputs: + upload_url: ${{ steps.create_release.outputs.upload_url }} steps: - - uses: actions/checkout@v1 - with: - submodules: true + - name: Create Release + id: create_release + uses: actions/create-release@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag_name: ${{ github.ref }} + release_name: ${{ github.ref }} + draft: true + prerelease: false - - name: Build - run: cargo build --locked --verbose --release - env: - OPENSSL_STATIC: 1 + build-plugin: + needs: ["create-release"] + name: Build Roblox Studio Plugin + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + with: + submodules: true - - name: Upload artifacts - uses: actions/upload-artifact@v1 - with: - name: rojo-linux - path: target/release/rojo \ No newline at end of file + - name: Setup Foreman + uses: Roblox/setup-foreman@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Build Plugin + run: rojo build plugin --output Rojo.rbxm + + - name: Upload Plugin to Release + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ needs.create-release.outputs.upload_url }} + asset_path: Rojo.rbxm + asset_name: Rojo.rbxm + asset_content_type: application/octet-stream + + - name: Upload Plugin to Artifacts + uses: actions/upload-artifact@v3 + with: + name: Rojo.rbxm + path: Rojo.rbxm + + build: + needs: ["create-release"] + strategy: + fail-fast: false + matrix: + # https://doc.rust-lang.org/rustc/platform-support.html + # + # FIXME: After the Rojo VS Code extension updates, add architecture + # names to each of these releases. We'll rename win64 to windows and add + # -x86_64 to each release. + include: + - host: linux + os: ubuntu-latest + target: x86_64-unknown-linux-gnu + label: linux + + - host: windows + os: windows-latest + target: x86_64-pc-windows-msvc + label: win64 + + - host: macos + os: macos-latest + target: x86_64-apple-darwin + label: macos + + - host: macos + os: macos-latest + target: aarch64-apple-darwin + label: macos-aarch64 + + name: Build (${{ matrix.target }}) + runs-on: ${{ matrix.os }} + env: + BIN: rojo + steps: + - uses: actions/checkout@v3 + with: + submodules: true + + - name: Get Version from Tag + shell: bash + # https://github.community/t/how-to-get-just-the-tag-name/16241/7#M1027 + run: | + echo "PROJECT_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV + echo "Version is: ${{ env.PROJECT_VERSION }}" + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: stable + target: ${{ matrix.target }} + override: true + profile: minimal + + - name: Build Release + run: cargo build --release --locked --verbose + env: + # Build into a known directory so we can find our build artifact more + # easily. + CARGO_TARGET_DIR: output + + # On platforms that use OpenSSL, ensure it is statically linked to + # make binaries more portable. + OPENSSL_STATIC: 1 + + - name: Create Release Archive + shell: bash + run: | + mkdir staging + + if [ "${{ matrix.host }}" = "windows" ]; then + cp "output/release/$BIN.exe" staging/ + cd staging + 7z a ../release.zip * + else + cp "output/release/$BIN" staging/ + cd staging + zip ../release.zip * + fi + + - name: Upload Archive to Release + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ needs.create-release.outputs.upload_url }} + asset_path: release.zip + asset_name: ${{ env.BIN }}-${{ env.PROJECT_VERSION }}-${{ matrix.label }}.zip + asset_content_type: application/octet-stream + + - name: Upload Archive to Artifacts + uses: actions/upload-artifact@v3 + with: + name: ${{ env.BIN }}-${{ env.PROJECT_VERSION }}-${{ matrix.label }}.zip + path: release.zip \ No newline at end of file From 6c6d6c9c8dec79000208e63658192181ecf3dacd Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 26 May 2022 02:28:57 -0400 Subject: [PATCH 1210/1504] Add .github/FUNDING.yml --- .github/FUNDING.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 00000000..a2b06a67 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +patreon: lpghatguy \ No newline at end of file From b9ed68fa9eca2b348cfe9ae521b6ebe2c61c0d5a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 26 May 2022 02:53:20 -0400 Subject: [PATCH 1211/1504] Release v7.1.1 --- CHANGELOG.md | 8 ++++++++ CONTRIBUTING.md | 4 +--- Cargo.lock | 2 +- Cargo.toml | 2 +- plugin/src/Config.lua | 2 +- 5 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index aff40072..852e32b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## Unreleased Changes +## [7.1.1] - May 26, 2022 +* Fixed sourcemap command not stripping paths correctly ([#544]) +* Fixed Studio plugin settings not saving correctly. + +[#544]: https://github.com/rojo-rbx/rojo/pull/544 +[#545]: https://github.com/rojo-rbx/rojo/pull/545 +[7.1.1]: https://github.com/rojo-rbx/rojo/releases/tag/v7.1.1 + ## [7.1.0] - May 22, 2022 * Added support for specifying an address to be used by default in project files. ([#507]) * Added support for optional paths in project files. ([#472]) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 75fa762d..8f3efd19 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -49,11 +49,9 @@ The Rojo release process is pretty manual right now. If you need to do it, here' * `cargo publish` 8. Publish the Plugin * `cargo run -- upload plugin --asset_id 6415005344` - * `cargo run -- build plugin --output Rojo.rbxm` 9. Push commits and tags * `git push && git push --tags` 10. Copy GitHub release content from previous release * Update the leading text with a summary about the release * Paste the changelog notes (as-is!) from [`CHANGELOG.md`](CHANGELOG.md) - * Write a small summary of each major feature - * Attach release artifacts from GitHub Actions for each platform + * Write a small summary of each major feature \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index a7eb79cb..fe8466ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1759,7 +1759,7 @@ dependencies = [ [[package]] name = "rojo" -version = "7.1.0" +version = "7.1.1" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 5c970cf9..958396a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "7.1.0" +version = "7.1.1" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 2544b457..4e77df61 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {7, 1, 0}, + version = {7, 1, 1}, expectedServerVersionString = "7.0 or newer", protocolVersion = 4, defaultHost = "localhost", From 79c02f2457c0927a08c93584abb29c5fdefeee77 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 26 May 2022 04:13:50 -0400 Subject: [PATCH 1212/1504] Delete old bin folder and update foreman.toml --- bin/dev-plugin.sh | 5 ----- bin/install-dev-plugin.sh | 13 ------------- bin/install-release-plugin.sh | 5 ----- bin/mark-plugin-as-dev.lua | 12 ------------ bin/put-plugin-in-test-place.lua | 8 -------- bin/run-all-tests.sh | 6 ------ bin/run-cli-tests.sh | 9 --------- bin/run-plugin-tests.sh | 16 ---------------- foreman.toml | 3 ++- 9 files changed, 2 insertions(+), 75 deletions(-) delete mode 100755 bin/dev-plugin.sh delete mode 100755 bin/install-dev-plugin.sh delete mode 100755 bin/install-release-plugin.sh delete mode 100644 bin/mark-plugin-as-dev.lua delete mode 100644 bin/put-plugin-in-test-place.lua delete mode 100755 bin/run-all-tests.sh delete mode 100755 bin/run-cli-tests.sh delete mode 100755 bin/run-plugin-tests.sh diff --git a/bin/dev-plugin.sh b/bin/dev-plugin.sh deleted file mode 100755 index 0b786218..00000000 --- a/bin/dev-plugin.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -set -e - -watchexec -c -w plugin "sh -c './bin/install-dev-plugin.sh'" \ No newline at end of file diff --git a/bin/install-dev-plugin.sh b/bin/install-dev-plugin.sh deleted file mode 100755 index d8a8376c..00000000 --- a/bin/install-dev-plugin.sh +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh - -set -e - -DIR="$( mktemp -d )" -PLUGIN_FILE="$DIR/Rojo.rbxm" -TESTEZ_FILE="$DIR/TestEZ.rbxm" - -rojo build plugin -o "$PLUGIN_FILE" -rojo build plugin/testez.project.json -o "$TESTEZ_FILE" -remodel bin/mark-plugin-as-dev.lua "$PLUGIN_FILE" "$TESTEZ_FILE" 2>/dev/null - -cp "$PLUGIN_FILE" "$LOCALAPPDATA/Roblox/Plugins/Rojo.rbxm" \ No newline at end of file diff --git a/bin/install-release-plugin.sh b/bin/install-release-plugin.sh deleted file mode 100755 index f670c18c..00000000 --- a/bin/install-release-plugin.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/bin/sh - -set -e - -rojo build plugin -o "$LOCALAPPDATA/Roblox/Plugins/Rojo.rbxm" \ No newline at end of file diff --git a/bin/mark-plugin-as-dev.lua b/bin/mark-plugin-as-dev.lua deleted file mode 100644 index 49fe902a..00000000 --- a/bin/mark-plugin-as-dev.lua +++ /dev/null @@ -1,12 +0,0 @@ -local pluginPath, testezPath = ... - -local plugin = remodel.readModelFile(pluginPath)[1] -local testez = remodel.readModelFile(testezPath)[1] - -local marker = Instance.new("Folder") -marker.Name = "ROJO_DEV_BUILD" -marker.Parent = plugin - -testez.Parent = plugin - -remodel.writeModelFile(plugin, pluginPath) \ No newline at end of file diff --git a/bin/put-plugin-in-test-place.lua b/bin/put-plugin-in-test-place.lua deleted file mode 100644 index f651c1bf..00000000 --- a/bin/put-plugin-in-test-place.lua +++ /dev/null @@ -1,8 +0,0 @@ -local pluginPath, placePath = ... - -local plugin = remodel.readModelFile(pluginPath)[1] -local place = remodel.readPlaceFile(placePath) - -plugin.Parent = place:GetService("ReplicatedStorage") - -remodel.writePlaceFile(place, placePath) \ No newline at end of file diff --git a/bin/run-all-tests.sh b/bin/run-all-tests.sh deleted file mode 100755 index e17aafa4..00000000 --- a/bin/run-all-tests.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -set -e - -./bin/run-cli-tests.sh -./bin/run-plugin-tests.sh \ No newline at end of file diff --git a/bin/run-cli-tests.sh b/bin/run-cli-tests.sh deleted file mode 100755 index 8f1b49a2..00000000 --- a/bin/run-cli-tests.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -set -e - -cargo test --all --locked -cargo fmt -- --check - -touch src/lib.rs # Nudge Rust source to make Clippy actually check things -cargo clippy \ No newline at end of file diff --git a/bin/run-plugin-tests.sh b/bin/run-plugin-tests.sh deleted file mode 100755 index 1da9bb47..00000000 --- a/bin/run-plugin-tests.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/sh - -set -e - -DIR="$( mktemp -d )" -PLUGIN_FILE="$DIR/Rojo.rbxmx" -PLACE_FILE="$DIR/RojoTestPlace.rbxlx" - -rojo build plugin -o "$PLUGIN_FILE" -rojo build plugin/place.project.json -o "$PLACE_FILE" - -remodel bin/put-plugin-in-test-place.lua "$PLUGIN_FILE" "$PLACE_FILE" - -run-in-roblox -s plugin/testBootstrap.server.lua "$PLACE_FILE" - -luacheck plugin/src plugin/log plugin/http \ No newline at end of file diff --git a/foreman.toml b/foreman.toml index d6e1b51f..c1275b8d 100644 --- a/foreman.toml +++ b/foreman.toml @@ -1,3 +1,4 @@ [tools] -rojo = { source = "rojo-rbx/rojo", version = "6.1.0" } +rojo = { source = "rojo-rbx/rojo", version = "7.1.1" } run-in-roblox = { source = "rojo-rbx/run-in-roblox", version = "0.3.0" } +selene = { source = "Kampfkarren/selene", version = "0.17.0" } From c7aeffe5868dc6756278db2bc966f15070f67658 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 26 May 2022 04:19:51 -0400 Subject: [PATCH 1213/1504] Switch from structopt to clap --- CHANGELOG.md | 1 + Cargo.lock | 106 ++++++++++++++++++++++------------------- Cargo.toml | 2 +- src/cli/build.rs | 10 ++-- src/cli/doc.rs | 4 +- src/cli/fmt_project.rs | 6 +-- src/cli/init.rs | 8 ++-- src/cli/mod.rs | 22 ++++----- src/cli/plugin.rs | 8 ++-- src/cli/serve.rs | 10 ++-- src/cli/sourcemap.rs | 10 ++-- src/cli/upload.rs | 14 +++--- src/main.rs | 4 +- 13 files changed, 107 insertions(+), 98 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 852e32b8..3894731d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Switched from structopt to clap for command line argument parsing. ## [7.1.1] - May 26, 2022 * Fixed sourcemap command not stripping paths correctly ([#544]) diff --git a/Cargo.lock b/Cargo.lock index fe8466ae..326db2ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -217,13 +217,48 @@ version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "ansi_term", + "bitflags", + "textwrap 0.11.0", + "unicode-width", +] + +[[package]] +name = "clap" +version = "3.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" +dependencies = [ "atty", "bitflags", + "clap_derive", + "clap_lex", + "indexmap", + "lazy_static", "strsim", - "textwrap", - "unicode-width", - "vec_map", + "termcolor", + "textwrap 0.15.0", +] + +[[package]] +name = "clap_derive" +version = "3.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c" +dependencies = [ + "heck", + "proc-macro-error", + "proc-macro2 1.0.39", + "quote 1.0.18", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +dependencies = [ + "os_str_bytes", ] [[package]] @@ -269,7 +304,7 @@ checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" dependencies = [ "atty", "cast", - "clap", + "clap 2.34.0", "criterion-plot", "csv", "itertools", @@ -738,12 +773,9 @@ checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" [[package]] name = "heck" -version = "0.3.3" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] +checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" [[package]] name = "hermit-abi" @@ -1272,6 +1304,12 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "os_str_bytes" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" + [[package]] name = "output_vt100" version = "0.1.3" @@ -1764,6 +1802,7 @@ dependencies = [ "anyhow", "backtrace", "bincode", + "clap 3.1.18", "criterion", "crossbeam-channel", "csv", @@ -1795,7 +1834,6 @@ dependencies = [ "serde", "serde_json", "serde_yaml", - "structopt", "tempfile", "termcolor", "thiserror", @@ -1998,33 +2036,9 @@ dependencies = [ [[package]] name = "strsim" -version = "0.8.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" - -[[package]] -name = "structopt" -version = "0.3.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c6b5c64445ba8094a6ab0c3cd2ad323e07171012d9c98b0b15651daf1787a10" -dependencies = [ - "clap", - "lazy_static", - "structopt-derive", -] - -[[package]] -name = "structopt-derive" -version = "0.4.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcb5ae327f9cc13b68763b5749770cb9e048a99bd9dfdfa58d0cf05d5f64afe0" -dependencies = [ - "heck", - "proc-macro-error", - "proc-macro2 1.0.39", - "quote 1.0.18", - "syn", -] +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "subtle" @@ -2085,6 +2099,12 @@ dependencies = [ "unicode-width", ] +[[package]] +name = "textwrap" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" + [[package]] name = "thiserror" version = "1.0.31" @@ -2257,12 +2277,6 @@ dependencies = [ "tinyvec", ] -[[package]] -name = "unicode-segmentation" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99" - [[package]] name = "unicode-width" version = "0.1.9" @@ -2303,12 +2317,6 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" -[[package]] -name = "vec_map" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" - [[package]] name = "version_check" version = "0.9.4" diff --git a/Cargo.toml b/Cargo.toml index 958396a4..cc2828ad 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -78,11 +78,11 @@ ritz = "0.1.0" roblox_install = "1.0.0" serde = { version = "1.0.130", features = ["derive", "rc"] } serde_json = "1.0.68" -structopt = "0.3.23" termcolor = "1.1.2" thiserror = "1.0.30" tokio = { version = "1.12.0", features = ["rt", "rt-multi-thread"] } uuid = { version = "1.0.0", features = ["v4", "serde"] } +clap = { version = "3.1.18", features = ["derive"] } [target.'cfg(windows)'.dependencies] winreg = "0.10.1" diff --git a/src/cli/build.rs b/src/cli/build.rs index 38273f82..081aef3a 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -4,9 +4,9 @@ use std::{ }; use anyhow::Context; +use clap::Parser; use fs_err::File; use memofs::Vfs; -use structopt::StructOpt; use tokio::runtime::Runtime; use crate::serve_session::ServeSession; @@ -17,20 +17,20 @@ const UNKNOWN_OUTPUT_KIND_ERR: &str = "Could not detect what kind of file to bui Expected output file to end in .rbxl, .rbxlx, .rbxm, or .rbxmx."; /// Generates a model or place file from the Rojo project. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct BuildCommand { /// Path to the project to serve. Defaults to the current directory. - #[structopt(default_value = "")] + #[clap(default_value = "")] pub project: PathBuf, /// Where to output the result. /// /// Should end in .rbxm, .rbxl, .rbxmx, or .rbxlx. - #[structopt(long, short)] + #[clap(long, short)] pub output: PathBuf, /// Whether to automatically rebuild when any input files change. - #[structopt(long)] + #[clap(long)] pub watch: bool, } diff --git a/src/cli/doc.rs b/src/cli/doc.rs index 9a344997..61a8d416 100644 --- a/src/cli/doc.rs +++ b/src/cli/doc.rs @@ -1,7 +1,7 @@ -use structopt::StructOpt; +use clap::Parser; /// Open Rojo's documentation in your browser. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct DocCommand {} impl DocCommand { diff --git a/src/cli/fmt_project.rs b/src/cli/fmt_project.rs index e227fa44..9351d635 100644 --- a/src/cli/fmt_project.rs +++ b/src/cli/fmt_project.rs @@ -1,15 +1,15 @@ use std::path::PathBuf; use anyhow::Context; -use structopt::StructOpt; +use clap::Parser; use crate::project::Project; /// Reformat a Rojo project using the standard JSON formatting rules. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct FmtProjectCommand { /// Path to the project to format. Defaults to the current directory. - #[structopt(default_value = "")] + #[clap(default_value = "")] pub project: PathBuf, } diff --git a/src/cli/init.rs b/src/cli/init.rs index 3117b61f..795ec04d 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -4,9 +4,9 @@ use std::process::{Command, Stdio}; use std::str::FromStr; use anyhow::{bail, format_err}; +use clap::Parser; use fs_err as fs; use fs_err::OpenOptions; -use structopt::StructOpt; use super::resolve_path; @@ -22,14 +22,14 @@ static PLACE_README: &str = include_str!("../../assets/default-place-project/REA static PLACE_GIT_IGNORE: &str = include_str!("../../assets/default-place-project/gitignore.txt"); /// Initializes a new Rojo project. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct InitCommand { /// Path to the place to create the project. Defaults to the current directory. - #[structopt(default_value = "")] + #[clap(default_value = "")] pub path: PathBuf, /// The kind of project to create, 'place' or 'model'. Defaults to place. - #[structopt(long, default_value = "place")] + #[clap(long, default_value = "place")] pub kind: InitKind, } diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 2d498b4a..36b32940 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -1,4 +1,4 @@ -//! Defines Rojo's CLI through structopt types. +//! Defines Rojo's CLI through clap types. mod build; mod doc; @@ -11,7 +11,7 @@ mod upload; use std::{borrow::Cow, env, path::Path, str::FromStr}; -use structopt::StructOpt; +use clap::Parser; use thiserror::Error; pub use self::build::BuildCommand; @@ -23,15 +23,15 @@ pub use self::serve::ServeCommand; pub use self::sourcemap::SourcemapCommand; pub use self::upload::UploadCommand; -/// Command line options that Rojo accepts, defined using the structopt crate. -#[derive(Debug, StructOpt)] -#[structopt(name = "Rojo", about, author)] +/// Command line options that Rojo accepts, defined using the clap crate. +#[derive(Debug, Parser)] +#[clap(name = "Rojo", version, about, author)] pub struct Options { - #[structopt(flatten)] + #[clap(flatten)] pub global: GlobalOptions, /// Subcommand to run in this invocation. - #[structopt(subcommand)] + #[clap(subcommand)] pub subcommand: Subcommand, } @@ -50,14 +50,14 @@ impl Options { } } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct GlobalOptions { /// Sets verbosity level. Can be specified multiple times. - #[structopt(long("verbose"), short, global(true), parse(from_occurrences))] + #[clap(long("verbose"), short, global(true), parse(from_occurrences))] pub verbosity: u8, /// Set color behavior. Valid values are auto, always, and never. - #[structopt(long("color"), global(true), default_value("auto"))] + #[clap(long("color"), global(true), default_value("auto"))] pub color: ColorChoice, } @@ -109,7 +109,7 @@ pub struct ColorChoiceParseError { attempted: String, } -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum Subcommand { Init(InitCommand), Serve(ServeCommand), diff --git a/src/cli/plugin.rs b/src/cli/plugin.rs index 5ab98e07..aa8773b3 100644 --- a/src/cli/plugin.rs +++ b/src/cli/plugin.rs @@ -3,9 +3,9 @@ use std::{ io::BufWriter, }; +use clap::Parser; use memofs::{InMemoryFs, Vfs, VfsSnapshot}; use roblox_install::RobloxStudio; -use structopt::StructOpt; use crate::serve_session::ServeSession; @@ -13,14 +13,14 @@ static PLUGIN_BINCODE: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/plugin. static PLUGIN_FILE_NAME: &str = "RojoManagedPlugin.rbxm"; /// Install Rojo's plugin. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct PluginCommand { - #[structopt(subcommand)] + #[clap(subcommand)] subcommand: PluginSubcommand, } /// Manages Rojo's Roblox Studio plugin. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub enum PluginSubcommand { /// Install the plugin in Roblox Studio's plugins folder. If the plugin is /// already installed, installing it again will overwrite the current plugin diff --git a/src/cli/serve.rs b/src/cli/serve.rs index 56b46121..9d2aa343 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -5,8 +5,8 @@ use std::{ sync::Arc, }; +use clap::Parser; use memofs::Vfs; -use structopt::StructOpt; use termcolor::{BufferWriter, Color, ColorChoice, ColorSpec, WriteColor}; use crate::{serve_session::ServeSession, web::LiveServer}; @@ -17,19 +17,19 @@ const DEFAULT_BIND_ADDRESS: Ipv4Addr = Ipv4Addr::new(127, 0, 0, 1); const DEFAULT_PORT: u16 = 34872; /// Expose a Rojo project to the Rojo Studio plugin. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct ServeCommand { /// Path to the project to serve. Defaults to the current directory. - #[structopt(default_value = "")] + #[clap(default_value = "")] pub project: PathBuf, /// The IP address to listen on. Defaults to `127.0.0.1`. - #[structopt(long)] + #[clap(long)] pub address: Option, /// The port to listen on. Defaults to the project's preference, or `34872` if /// it has none. - #[structopt(long)] + #[clap(long)] pub port: Option, } diff --git a/src/cli/sourcemap.rs b/src/cli/sourcemap.rs index 8cda48ff..9d761e71 100644 --- a/src/cli/sourcemap.rs +++ b/src/cli/sourcemap.rs @@ -3,11 +3,11 @@ use std::{ path::{Path, PathBuf}, }; +use clap::Parser; use fs_err::File; use memofs::Vfs; use rbx_dom_weak::types::Ref; use serde::Serialize; -use structopt::StructOpt; use crate::{ serve_session::ServeSession, @@ -33,22 +33,22 @@ struct SourcemapNode { } /// Generates a sourcemap file from the Rojo project. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct SourcemapCommand { /// Path to the project to use for the sourcemap. Defaults to the current /// directory. - #[structopt(default_value = "")] + #[clap(default_value = "")] pub project: PathBuf, /// Where to output the sourcemap. Omit this to use stdout instead of /// writing to a file. /// /// Should end in .json. - #[structopt(long, short)] + #[clap(long, short)] pub output: Option, /// If non-script files should be included or not. Defaults to false. - #[structopt(long)] + #[clap(long)] pub include_non_scripts: bool, } diff --git a/src/cli/upload.rs b/src/cli/upload.rs index 2f4d2d63..d8404099 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -2,38 +2,38 @@ use std::path::PathBuf; use std::str::FromStr; use anyhow::{bail, format_err, Context}; +use clap::Parser; use memofs::Vfs; use reqwest::{ header::{ACCEPT, CONTENT_TYPE, COOKIE, USER_AGENT}, StatusCode, }; -use structopt::StructOpt; use crate::{auth_cookie::get_auth_cookie, serve_session::ServeSession}; use super::resolve_path; /// Builds the project and uploads it to Roblox. -#[derive(Debug, StructOpt)] +#[derive(Debug, Parser)] pub struct UploadCommand { /// Path to the project to upload. Defaults to the current directory. - #[structopt(default_value = "")] + #[clap(default_value = "")] pub project: PathBuf, /// Authenication cookie to use. If not specified, Rojo will attempt to find one from the system automatically. - #[structopt(long)] + #[clap(long)] pub cookie: Option, /// API key obtained from create.roblox.com/credentials. Rojo will use the Open Cloud API when this is provided. Only supports uploading to a place. - #[structopt(long = "api_key")] + #[clap(long = "api_key")] pub api_key: Option, /// The Universe ID of the given place. Required when using the Open Cloud API. - #[structopt(long = "universe_id")] + #[clap(long = "universe_id")] pub universe_id: Option, /// Asset ID to upload to. - #[structopt(long = "asset_id")] + #[clap(long = "asset_id")] pub asset_id: u64, } diff --git a/src/main.rs b/src/main.rs index 34d89d8a..10920bd3 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,7 @@ use std::{env, panic, process}; use backtrace::Backtrace; -use structopt::StructOpt; +use clap::Parser; use librojo::cli::Options; @@ -49,7 +49,7 @@ fn main() { process::exit(1); })); - let options = Options::from_args(); + let options = Options::parse(); let log_filter = match options.global.verbosity { 0 => "info", From 79b57b3359c2be182a7ed8f2ac3518b9a855b26d Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 26 May 2022 04:23:44 -0400 Subject: [PATCH 1214/1504] Move memofs and rojo-insta-ext into crates folder --- Cargo.toml | 11 ++++------- {memofs => crates/memofs}/CHANGELOG.md | 0 {memofs => crates/memofs}/Cargo.toml | 0 {memofs => crates/memofs}/LICENSE.txt | 0 {memofs => crates/memofs}/README.md | 0 {memofs => crates/memofs}/README.tpl | 0 {memofs => crates/memofs}/src/in_memory_fs.rs | 0 {memofs => crates/memofs}/src/lib.rs | 0 {memofs => crates/memofs}/src/noop_backend.rs | 0 {memofs => crates/memofs}/src/snapshot.rs | 0 {memofs => crates/memofs}/src/std_backend.rs | 0 {rojo-insta-ext => crates/rojo-insta-ext}/Cargo.toml | 0 {rojo-insta-ext => crates/rojo-insta-ext}/README.md | 0 {rojo-insta-ext => crates/rojo-insta-ext}/src/lib.rs | 0 .../rojo-insta-ext}/src/redaction_map.rs | 0 15 files changed, 4 insertions(+), 7 deletions(-) rename {memofs => crates/memofs}/CHANGELOG.md (100%) rename {memofs => crates/memofs}/Cargo.toml (100%) rename {memofs => crates/memofs}/LICENSE.txt (100%) rename {memofs => crates/memofs}/README.md (100%) rename {memofs => crates/memofs}/README.tpl (100%) rename {memofs => crates/memofs}/src/in_memory_fs.rs (100%) rename {memofs => crates/memofs}/src/lib.rs (100%) rename {memofs => crates/memofs}/src/noop_backend.rs (100%) rename {memofs => crates/memofs}/src/snapshot.rs (100%) rename {memofs => crates/memofs}/src/std_backend.rs (100%) rename {rojo-insta-ext => crates/rojo-insta-ext}/Cargo.toml (100%) rename {rojo-insta-ext => crates/rojo-insta-ext}/README.md (100%) rename {rojo-insta-ext => crates/rojo-insta-ext}/src/lib.rs (100%) rename {rojo-insta-ext => crates/rojo-insta-ext}/src/redaction_map.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index cc2828ad..14b8a9ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,10 +28,7 @@ default = [] dev_live_assets = [] [workspace] -members = [ - "rojo-insta-ext", - "memofs", -] +members = ["crates/*"] [lib] name = "librojo" @@ -42,7 +39,7 @@ name = "build" harness = false [dependencies] -memofs = { version = "0.2.0", path = "memofs" } +memofs = { version = "0.2.0", path = "crates/memofs" } # These dependencies can be uncommented when working on rbx-dom simultaneously # rbx_binary = { path = "../rbx-dom/rbx_binary" } @@ -88,7 +85,7 @@ clap = { version = "3.1.18", features = ["derive"] } winreg = "0.10.1" [build-dependencies] -memofs = { version = "0.2.0", path = "memofs" } +memofs = { version = "0.2.0", path = "crates/memofs" } embed-resource = "1.6.4" anyhow = "1.0.44" @@ -97,7 +94,7 @@ fs-err = "2.6.0" maplit = "1.0.2" [dev-dependencies] -rojo-insta-ext = { path = "rojo-insta-ext" } +rojo-insta-ext = { path = "crates/rojo-insta-ext" } criterion = "0.3.5" insta = { version = "1.8.0", features = ["redactions"] } diff --git a/memofs/CHANGELOG.md b/crates/memofs/CHANGELOG.md similarity index 100% rename from memofs/CHANGELOG.md rename to crates/memofs/CHANGELOG.md diff --git a/memofs/Cargo.toml b/crates/memofs/Cargo.toml similarity index 100% rename from memofs/Cargo.toml rename to crates/memofs/Cargo.toml diff --git a/memofs/LICENSE.txt b/crates/memofs/LICENSE.txt similarity index 100% rename from memofs/LICENSE.txt rename to crates/memofs/LICENSE.txt diff --git a/memofs/README.md b/crates/memofs/README.md similarity index 100% rename from memofs/README.md rename to crates/memofs/README.md diff --git a/memofs/README.tpl b/crates/memofs/README.tpl similarity index 100% rename from memofs/README.tpl rename to crates/memofs/README.tpl diff --git a/memofs/src/in_memory_fs.rs b/crates/memofs/src/in_memory_fs.rs similarity index 100% rename from memofs/src/in_memory_fs.rs rename to crates/memofs/src/in_memory_fs.rs diff --git a/memofs/src/lib.rs b/crates/memofs/src/lib.rs similarity index 100% rename from memofs/src/lib.rs rename to crates/memofs/src/lib.rs diff --git a/memofs/src/noop_backend.rs b/crates/memofs/src/noop_backend.rs similarity index 100% rename from memofs/src/noop_backend.rs rename to crates/memofs/src/noop_backend.rs diff --git a/memofs/src/snapshot.rs b/crates/memofs/src/snapshot.rs similarity index 100% rename from memofs/src/snapshot.rs rename to crates/memofs/src/snapshot.rs diff --git a/memofs/src/std_backend.rs b/crates/memofs/src/std_backend.rs similarity index 100% rename from memofs/src/std_backend.rs rename to crates/memofs/src/std_backend.rs diff --git a/rojo-insta-ext/Cargo.toml b/crates/rojo-insta-ext/Cargo.toml similarity index 100% rename from rojo-insta-ext/Cargo.toml rename to crates/rojo-insta-ext/Cargo.toml diff --git a/rojo-insta-ext/README.md b/crates/rojo-insta-ext/README.md similarity index 100% rename from rojo-insta-ext/README.md rename to crates/rojo-insta-ext/README.md diff --git a/rojo-insta-ext/src/lib.rs b/crates/rojo-insta-ext/src/lib.rs similarity index 100% rename from rojo-insta-ext/src/lib.rs rename to crates/rojo-insta-ext/src/lib.rs diff --git a/rojo-insta-ext/src/redaction_map.rs b/crates/rojo-insta-ext/src/redaction_map.rs similarity index 100% rename from rojo-insta-ext/src/redaction_map.rs rename to crates/rojo-insta-ext/src/redaction_map.rs From 7aa7a35aa55029225853f66376e8d0804513cdb7 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 27 May 2022 03:08:54 -0400 Subject: [PATCH 1215/1504] Add profiling info and optional profiling with Tracy --- Cargo.lock | 152 +++++++++++++++++++++++++++++++++ Cargo.toml | 4 + src/cli/build.rs | 1 + src/main.rs | 3 + src/snapshot/patch_apply.rs | 1 + src/snapshot/patch_compute.rs | 1 + src/snapshot_middleware/mod.rs | 1 + 7 files changed, 163 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index 326db2ba..5b2a42df 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -690,6 +690,19 @@ dependencies = [ "slab", ] +[[package]] +name = "generator" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1d9279ca822891c1a4dae06d185612cf8fc6acfe5dff37781b41297811b12ee" +dependencies = [ + "cc", + "libc", + "log", + "rustversion", + "winapi 0.3.9", +] + [[package]] name = "generic-array" version = "0.12.4" @@ -1029,6 +1042,19 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "loom" +version = "0.5.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +dependencies = [ + "cfg-if 1.0.0", + "generator", + "scoped-tls", + "tracing", + "tracing-subscriber", +] + [[package]] name = "lz4" version = "1.23.3" @@ -1055,6 +1081,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" +[[package]] +name = "matchers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +dependencies = [ + "regex-automata", +] + [[package]] name = "matches" version = "0.1.9" @@ -1492,6 +1527,26 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "profiling" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f61dcf0b917cd75d4521d7343d1ffff3d1583054133c9b5cbea3375c703c40d" +dependencies = [ + "profiling-procmacros", + "tracy-client", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "98eee3c112f2a6f784b6713fe1d7fb7d6506e066121c0a49371fdb976f72bae5" +dependencies = [ + "quote 1.0.18", + "syn", +] + [[package]] name = "quote" version = "0.6.13" @@ -1686,6 +1741,9 @@ name = "regex-automata" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +dependencies = [ + "regex-syntax", +] [[package]] name = "regex-syntax" @@ -1822,6 +1880,7 @@ dependencies = [ "opener", "paste", "pretty_assertions", + "profiling", "rbx_binary", "rbx_dom_weak", "rbx_reflection", @@ -1838,6 +1897,7 @@ dependencies = [ "termcolor", "thiserror", "tokio", + "tracy-client", "uuid", "walkdir", "winreg 0.10.1", @@ -1866,6 +1926,12 @@ dependencies = [ "semver", ] +[[package]] +name = "rustversion" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" + [[package]] name = "ryu" version = "1.0.10" @@ -1891,6 +1957,12 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "scoped-tls" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" + [[package]] name = "scopeguard" version = "1.1.0" @@ -2003,6 +2075,15 @@ dependencies = [ "opaque-debug", ] +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + [[package]] name = "similar" version = "2.1.0" @@ -2015,6 +2096,12 @@ version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +[[package]] +name = "smallvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" + [[package]] name = "snax" version = "0.2.0" @@ -2125,6 +2212,15 @@ dependencies = [ "syn", ] +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + [[package]] name = "tinytemplate" version = "1.2.1" @@ -2236,6 +2332,56 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" dependencies = [ "lazy_static", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" +dependencies = [ + "ansi_term", + "lazy_static", + "matchers", + "regex", + "sharded-slab", + "smallvec", + "thread_local", + "tracing", + "tracing-core", + "tracing-log", +] + +[[package]] +name = "tracy-client" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ebfe7a24c18b5ba86d8920c124b41b942352f863fbe0c84d3d63428fa1860f" +dependencies = [ + "loom", + "once_cell", + "tracy-client-sys", +] + +[[package]] +name = "tracy-client-sys" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9012b9dfeccaff16e93f5a8b02336125113a80a769902e679d334cbdd4d83f3b" +dependencies = [ + "cc", ] [[package]] @@ -2311,6 +2457,12 @@ dependencies = [ "serde", ] +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/Cargo.toml b/Cargo.toml index 14b8a9ef..9e5c3deb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -27,6 +27,8 @@ default = [] # Enable this feature to live-reload assets from the web UI. dev_live_assets = [] +profile-with-tracy = ["profiling/profile-with-tracy", "tracy-client"] + [workspace] members = ["crates/*"] @@ -80,6 +82,8 @@ thiserror = "1.0.30" tokio = { version = "1.12.0", features = ["rt", "rt-multi-thread"] } uuid = { version = "1.0.0", features = ["v4", "serde"] } clap = { version = "3.1.18", features = ["derive"] } +profiling = "1.0.6" +tracy-client = { version = "0.13.2", optional = true } [target.'cfg(windows)'.dependencies] winreg = "0.10.1" diff --git a/src/cli/build.rs b/src/cli/build.rs index 081aef3a..24f83546 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -97,6 +97,7 @@ fn xml_encode_config() -> rbx_xml::EncodeOptions { rbx_xml::EncodeOptions::new().property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown) } +#[profiling::function] fn write_model( session: &ServeSession, output: &Path, diff --git a/src/main.rs b/src/main.rs index 10920bd3..5bb9bc6c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,9 @@ use clap::Parser; use librojo::cli::Options; fn main() { + #[cfg(feature = "profile-with-tracy")] + tracy_client::Client::start(); + panic::set_hook(Box::new(|panic_info| { // PanicInfo's payload is usually a &'static str or String. // See: https://doc.rust-lang.org/beta/std/panic/struct.PanicInfo.html#method.payload diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index 4e40061c..f87660ba 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -12,6 +12,7 @@ use super::{ /// Consumes the input `PatchSet`, applying all of its prescribed changes to the /// tree and returns an `AppliedPatchSet`, which can be used to keep another /// tree in sync with Rojo's. +#[profiling::function] pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) -> AppliedPatchSet { let mut context = PatchApplyContext::default(); diff --git a/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs index 76f0b26c..c778f1fa 100644 --- a/src/snapshot/patch_compute.rs +++ b/src/snapshot/patch_compute.rs @@ -10,6 +10,7 @@ use super::{ InstanceSnapshot, InstanceWithMeta, RojoTree, }; +#[profiling::function] pub fn compute_patch_set( snapshot: Option<&InstanceSnapshot>, tree: &RojoTree, diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 36729f8f..a8b348ee 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -40,6 +40,7 @@ pub use self::project::snapshot_project_node; /// The main entrypoint to the snapshot function. This function can be pointed /// at any path and will return something if Rojo knows how to deal with it. +#[profiling::function] pub fn snapshot_from_vfs( context: &InstanceContext, vfs: &Vfs, From 824cdc5dcd3ec124ff332143c01ba1d461f5f9b3 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 27 May 2022 18:12:56 -0400 Subject: [PATCH 1216/1504] Annotate snapshot_rbxm for profiling --- src/snapshot/instance_snapshot.rs | 1 + src/snapshot_middleware/rbxm.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/snapshot/instance_snapshot.rs b/src/snapshot/instance_snapshot.rs index 050dc067..77e9f3c6 100644 --- a/src/snapshot/instance_snapshot.rs +++ b/src/snapshot/instance_snapshot.rs @@ -102,6 +102,7 @@ impl InstanceSnapshot { } } + #[profiling::function] pub fn from_tree(tree: &WeakDom, id: Ref) -> Self { let instance = tree.get_by_ref(id).expect("instance did not exist in tree"); diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index b1d61313..c94d4ef4 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -7,6 +7,7 @@ use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::util::PathExt; +#[profiling::function] pub fn snapshot_rbxm( context: &InstanceContext, vfs: &Vfs, From 10341e3776be26f0f7ad24e3d4ed30bee1ce2b03 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 5 Jun 2022 17:47:31 -0400 Subject: [PATCH 1217/1504] Major Performance Improvements (#548) * Use WeakDom::into_raw for faster snapshot generation from models * Make compute_patch_set take snapshots by value * Stop deferring property application in apply_patch_set * Use InstanceBuilder::empty to avoid extra name allocations * Git dependencies, skip dropping ServeSession * Use std::mem::forget instead of ManuallyDrop * Switch to latest rbx-dom crates.io dependencies * Update other dependencies --- Cargo.lock | 161 +++++++++++++++--------------- Cargo.toml | 2 +- src/change_processor.rs | 4 +- src/cli/build.rs | 5 + src/serve_session.rs | 2 +- src/snapshot/instance_snapshot.rs | 22 ++-- src/snapshot/patch_apply.rs | 82 +++++++-------- src/snapshot/patch_compute.rs | 47 +++++---- src/snapshot/tests/compute.rs | 10 +- src/snapshot/tree.rs | 5 +- src/snapshot_middleware/rbxm.rs | 3 +- src/snapshot_middleware/rbxmx.rs | 3 +- 12 files changed, 180 insertions(+), 166 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b2a42df..45e9c897 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,9 +49,9 @@ checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" [[package]] name = "arrayvec" -version = "0.5.2" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" +checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" [[package]] name = "atty" @@ -114,17 +114,16 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "blake3" -version = "0.1.5" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46080006c1505f12f64dd2a09264b343381ed3190fa02c8005d5d662ac571c63" +checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" dependencies = [ "arrayref", "arrayvec", "cc", - "cfg-if 0.1.10", + "cfg-if 1.0.0", "constant_time_eq", - "crypto-mac", - "digest", + "digest 0.10.3", ] [[package]] @@ -136,7 +135,16 @@ dependencies = [ "block-padding", "byte-tools", "byteorder", - "generic-array", + "generic-array 0.12.4", +] + +[[package]] +name = "block-buffer" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" +dependencies = [ + "generic-array 0.14.5", ] [[package]] @@ -162,9 +170,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.9.1" +version = "3.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a45a46ab1f2412e53d3a0ade76ffad2025804294569aae387231a0cd6e0899" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" [[package]] name = "byte-tools" @@ -378,13 +386,13 @@ dependencies = [ ] [[package]] -name = "crypto-mac" -version = "0.7.0" +name = "crypto-common" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4434400df11d95d556bac068ddfedd482915eb18fe8bea89bc80b6e4b1c179e5" +checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" dependencies = [ - "generic-array", - "subtle", + "generic-array 0.14.5", + "typenum", ] [[package]] @@ -431,7 +439,18 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" dependencies = [ - "generic-array", + "generic-array 0.12.4", +] + +[[package]] +name = "digest" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" +dependencies = [ + "block-buffer 0.10.2", + "crypto-common", + "subtle", ] [[package]] @@ -713,14 +732,13 @@ dependencies = [ ] [[package]] -name = "getrandom" -version = "0.1.16" +name = "generic-array" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" dependencies = [ - "cfg-if 1.0.0", - "libc", - "wasi 0.9.0+wasi-snapshot-preview1", + "typenum", + "version_check", ] [[package]] @@ -731,7 +749,7 @@ checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.10.0+wasi-snapshot-preview1", + "wasi 0.10.2+wasi-snapshot-preview1", ] [[package]] @@ -847,9 +865,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.18" +version = "0.14.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b26ae0a80afebe130861d90abf98e3814a4f28a4c6ffeb5ab8ebb2be311e0ef2" +checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f" dependencies = [ "bytes", "futures-channel", @@ -895,9 +913,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.8.1" +version = "1.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f647032dfaa1f8b6dc29bd3edb7bbef4861b8b8007ebb118d6db284fd59f6ee" +checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" dependencies = [ "autocfg", "hashbrown", @@ -925,9 +943,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.14.0" +version = "1.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "689960f187c43c01650c805fb6bc6f55ab944499d86d4ffe9474ad78991d8e94" +checksum = "bcc3e639bcba360d9237acabd22014c16f3df772db463b7446cd81b070714767" dependencies = [ "console", "once_cell", @@ -1129,9 +1147,9 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "miniz_oxide" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b29bd4bc3f33391105ebee3589c19197c4271e3e5a9ec9bfe8127eeff8f082" +checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" dependencies = [ "adler", ] @@ -1268,9 +1286,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b10983b38c53aebdf33f542c6275b0f58a238129d00c4ae0e6fb59738d783ca" +checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" [[package]] name = "oorandom" @@ -1328,9 +1346,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.73" +version = "0.9.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d5fd19fb3e0a8191c1e34935718976a3e70c112ab9a24af6d7cadccd9d90bc0" +checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" dependencies = [ "autocfg", "cc", @@ -1567,22 +1585,20 @@ dependencies = [ [[package]] name = "rand" -version = "0.7.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ - "getrandom 0.1.16", "libc", "rand_chacha", "rand_core", - "rand_hc", ] [[package]] name = "rand_chacha" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", "rand_core", @@ -1590,20 +1606,11 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.5.1" +version = "0.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" dependencies = [ - "getrandom 0.1.16", -] - -[[package]] -name = "rand_hc" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" -dependencies = [ - "rand_core", + "getrandom", ] [[package]] @@ -1646,9 +1653,9 @@ dependencies = [ [[package]] name = "rbx_dom_weak" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f7f524fb18f30d7065c82c4e87f747705679329810207e96169c6d4ec922d1f" +checksum = "b7cc2238fd858d706f4f5c6a0f9af3cd4a10f3f8dc8b6534e683f8543af26f33" dependencies = [ "rbx_types", "serde", @@ -1678,11 +1685,11 @@ dependencies = [ [[package]] name = "rbx_types" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d637383aa560cb675b7ea7a7778b945dab065ccc7c158f77b5455e27efadc6df" +checksum = "cbfc0ca9c674968170d4fbbd95dc692d0b3f9405b4830babc76107dc00a66380" dependencies = [ - "base64 0.11.0", + "base64 0.13.0", "bitflags", "blake3", "lazy_static", @@ -1720,7 +1727,7 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ - "getrandom 0.2.6", + "getrandom", "redox_syscall", "thiserror", ] @@ -2069,8 +2076,8 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" dependencies = [ - "block-buffer", - "digest", + "block-buffer 0.7.3", + "digest 0.8.1", "fake-simd", "opaque-debug", ] @@ -2129,15 +2136,15 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "subtle" -version = "1.0.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d67a5a62ba6e01cb2192ff309324cb4875d0c451d55fe2319433abe7a05a8ee" +checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.95" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" +checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" dependencies = [ "proc-macro2 1.0.39", "quote 1.0.18", @@ -2248,9 +2255,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.18.2" +version = "1.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4903bf0427cf68dddd5aa6a93220756f8be0c34fcfa9f5e6191e103e15a31395" +checksum = "95eec79ea28c00a365f539f1961e9278fbcaf81c0ff6aaf0e93c181352446948" dependencies = [ "bytes", "libc", @@ -2275,9 +2282,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f988a1a1adc2fb21f9c12aa96441da33a1728193ae0b95d2be22dbd17fcb4e5c" +checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" dependencies = [ "bytes", "futures-core", @@ -2449,11 +2456,11 @@ dependencies = [ [[package]] name = "uuid" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cfcd319456c4d6ea10087ed423473267e1a071f3bc0aa89f80d60997843c6f0" +checksum = "c6d5d669b51467dcf7b2f1a796ce0f955f05f01cafda6c19d6e95f730df29238" dependencies = [ - "getrandom 0.2.6", + "getrandom", "serde", ] @@ -2518,15 +2525,9 @@ dependencies = [ [[package]] name = "wasi" -version = "0.9.0+wasi-snapshot-preview1" +version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" - -[[package]] -name = "wasi" -version = "0.10.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" +checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" [[package]] name = "wasi" diff --git a/Cargo.toml b/Cargo.toml index 9e5c3deb..83749b32 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,7 +51,7 @@ memofs = { version = "0.2.0", path = "crates/memofs" } # rbx_xml = { path = "../rbx-dom/rbx_xml" } rbx_binary = "0.6.4" -rbx_dom_weak = "2.3.0" +rbx_dom_weak = "2.4.0" rbx_reflection = "4.2.0" rbx_reflection_database = "0.2.2" rbx_xml = "0.12.3" diff --git a/src/change_processor.rs b/src/change_processor.rs index 7082a687..dce1cd8d 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -291,7 +291,7 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: Ref) -> Option< } }; - let patch_set = compute_patch_set(snapshot.as_ref(), &tree, id); + let patch_set = compute_patch_set(snapshot, &tree, id); apply_patch_set(tree, patch_set) } Ok(None) => { @@ -334,7 +334,7 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: Ref) -> Option< } }; - let patch_set = compute_patch_set(snapshot.as_ref(), &tree, id); + let patch_set = compute_patch_set(snapshot, &tree, id); apply_patch_set(tree, patch_set) } }; diff --git a/src/cli/build.rs b/src/cli/build.rs index 24f83546..d6c3f349 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -1,5 +1,6 @@ use std::{ io::{BufWriter, Write}, + mem::forget, path::{Path, PathBuf}, }; @@ -61,6 +62,10 @@ impl BuildCommand { } } + // Avoid dropping ServeSession: it's potentially VERY expensive to drop + // and we're about to exit anyways. + forget(session); + Ok(()) } } diff --git a/src/serve_session.rs b/src/serve_session.rs index a4eced44..96a68ac9 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -130,7 +130,7 @@ impl ServeSession { let snapshot = snapshot_from_vfs(&instance_context, &vfs, &start_path)?; log::trace!("Computing initial patch set"); - let patch_set = compute_patch_set(snapshot.as_ref(), &tree, root_id); + let patch_set = compute_patch_set(snapshot, &tree, root_id); log::trace!("Applying initial patch set"); apply_patch_set(&mut tree, patch_set); diff --git a/src/snapshot/instance_snapshot.rs b/src/snapshot/instance_snapshot.rs index 77e9f3c6..36c51821 100644 --- a/src/snapshot/instance_snapshot.rs +++ b/src/snapshot/instance_snapshot.rs @@ -4,7 +4,7 @@ use std::{borrow::Cow, collections::HashMap}; use rbx_dom_weak::{ types::{Ref, Variant}, - WeakDom, + Instance, WeakDom, }; use serde::{Deserialize, Serialize}; @@ -103,22 +103,28 @@ impl InstanceSnapshot { } #[profiling::function] - pub fn from_tree(tree: &WeakDom, id: Ref) -> Self { - let instance = tree.get_by_ref(id).expect("instance did not exist in tree"); + pub fn from_tree(tree: WeakDom, id: Ref) -> Self { + let (_, mut raw_tree) = tree.into_raw(); + Self::from_raw_tree(&mut raw_tree, id) + } + + fn from_raw_tree(raw_tree: &mut HashMap, id: Ref) -> Self { + let instance = raw_tree + .remove(&id) + .expect("instance did not exist in tree"); let children = instance .children() .iter() - .copied() - .map(|id| Self::from_tree(tree, id)) + .map(|&id| Self::from_raw_tree(raw_tree, id)) .collect(); Self { snapshot_id: Some(id), metadata: InstanceMetadata::default(), - name: Cow::Owned(instance.name.clone()), - class_name: Cow::Owned(instance.class.clone()), - properties: instance.properties.clone(), + name: Cow::Owned(instance.name), + class_name: Cow::Owned(instance.class), + properties: instance.properties, children, } } diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index f87660ba..439452d8 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -1,6 +1,9 @@ //! Defines the algorithm for applying generated patches. -use std::collections::HashMap; +use std::{ + collections::{HashMap, HashSet}, + mem::take, +}; use rbx_dom_weak::types::{Ref, Variant}; @@ -16,18 +19,27 @@ use super::{ pub fn apply_patch_set(tree: &mut RojoTree, patch_set: PatchSet) -> AppliedPatchSet { let mut context = PatchApplyContext::default(); - for removed_id in patch_set.removed_instances { - apply_remove_instance(&mut context, tree, removed_id); + { + profiling::scope!("removals"); + for removed_id in patch_set.removed_instances { + apply_remove_instance(&mut context, tree, removed_id); + } } - for add_patch in patch_set.added_instances { - apply_add_child(&mut context, tree, add_patch.parent_id, add_patch.instance); + { + profiling::scope!("additions"); + for add_patch in patch_set.added_instances { + apply_add_child(&mut context, tree, add_patch.parent_id, add_patch.instance); + } } - // Updates need to be applied after additions, which reduces the complexity - // of updates significantly. - for update_patch in patch_set.updated_instances { - apply_update_child(&mut context, tree, update_patch); + { + profiling::scope!("updates"); + // Updates need to be applied after additions, which reduces the complexity + // of updates significantly. + for update_patch in patch_set.updated_instances { + apply_update_child(&mut context, tree, update_patch); + } } finalize_patch_application(context, tree) @@ -56,20 +68,9 @@ struct PatchApplyContext { /// eachother. snapshot_id_to_instance_id: HashMap, - /// The properties of instances added by the current `PatchSet`. - /// - /// Instances added to the tree can refer to eachother via Ref properties, - /// but we need to make sure they're correctly transformed from snapshot - /// space into tree space (via `snapshot_id_to_instance_id`). - /// - /// It's not possible to do that transformation for refs that refer to added - /// instances until all the instances have actually been inserted into the - /// tree. For simplicity, we defer application of _all_ properties on added - /// instances instead of just Refs. - /// - /// This doesn't affect updated instances, since they're always applied - /// after we've added all the instances from the patch. - added_instance_properties: HashMap>, + /// Tracks all of the instances added by this patch that have refs that need + /// to be rewritten. + has_refs_to_rewrite: HashSet, /// The current applied patch result, describing changes made to the tree. applied_patch_set: AppliedPatchSet, @@ -85,23 +86,22 @@ struct PatchApplyContext { /// The remaining Ref properties need to be handled during patch application, /// where we build up a map of snapshot IDs to instance IDs as they're created, /// then apply properties all at once at the end. +#[profiling::function] fn finalize_patch_application(context: PatchApplyContext, tree: &mut RojoTree) -> AppliedPatchSet { - for (id, properties) in context.added_instance_properties { + for id in context.has_refs_to_rewrite { // This should always succeed since instances marked as added in our // patch should be added without fail. let mut instance = tree .get_instance_mut(id) .expect("Invalid instance ID in deferred property map"); - for (key, mut property_value) in properties { - if let Variant::Ref(referent) = property_value { + for value in instance.properties_mut().values_mut() { + if let Variant::Ref(referent) = value { if let Some(&instance_referent) = context.snapshot_id_to_instance_id.get(&referent) { - property_value = Variant::Ref(instance_referent); + *value = Variant::Ref(instance_referent); } } - - instance.properties_mut().insert(key, property_value); } } @@ -117,24 +117,24 @@ fn apply_add_child( context: &mut PatchApplyContext, tree: &mut RojoTree, parent_id: Ref, - snapshot: InstanceSnapshot, + mut snapshot: InstanceSnapshot, ) { let snapshot_id = snapshot.snapshot_id; - let properties = snapshot.properties; - let children = snapshot.children; + let children = take(&mut snapshot.children); - // Property application is deferred until after all children - // are constructed. This helps apply referents correctly. - let remaining_snapshot = InstanceSnapshot::new() - .name(snapshot.name) - .class_name(snapshot.class_name) - .metadata(snapshot.metadata) - .snapshot_id(snapshot.snapshot_id); + // If an object we're adding has a non-null referent, we'll note this + // instance down as needing to be revisited later. + let has_refs = snapshot.properties.values().any(|value| match value { + Variant::Ref(value) => value.is_some(), + _ => false, + }); - let id = tree.insert_instance(parent_id, remaining_snapshot); + let id = tree.insert_instance(parent_id, snapshot); context.applied_patch_set.added.push(id); - context.added_instance_properties.insert(id, properties); + if has_refs { + context.has_refs_to_rewrite.insert(id); + } if let Some(snapshot_id) = snapshot_id { context.snapshot_id_to_instance_id.insert(snapshot_id, id); diff --git a/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs index c778f1fa..23e2f302 100644 --- a/src/snapshot/patch_compute.rs +++ b/src/snapshot/patch_compute.rs @@ -1,7 +1,10 @@ //! Defines the algorithm for computing a roughly-minimal patch set given an //! existing instance tree and an instance snapshot. -use std::collections::{HashMap, HashSet}; +use std::{ + collections::{HashMap, HashSet}, + mem::take, +}; use rbx_dom_weak::types::{Ref, Variant}; @@ -11,11 +14,7 @@ use super::{ }; #[profiling::function] -pub fn compute_patch_set( - snapshot: Option<&InstanceSnapshot>, - tree: &RojoTree, - id: Ref, -) -> PatchSet { +pub fn compute_patch_set(snapshot: Option, tree: &RojoTree, id: Ref) -> PatchSet { let mut patch_set = PatchSet::new(); if let Some(snapshot) = snapshot { @@ -75,7 +74,7 @@ fn rewrite_refs_in_snapshot(context: &ComputePatchContext, snapshot: &mut Instan fn compute_patch_set_internal( context: &mut ComputePatchContext, - snapshot: &InstanceSnapshot, + mut snapshot: InstanceSnapshot, tree: &RojoTree, id: Ref, patch_set: &mut PatchSet, @@ -88,12 +87,12 @@ fn compute_patch_set_internal( .get_instance(id) .expect("Instance did not exist in tree"); - compute_property_patches(snapshot, &instance, patch_set); - compute_children_patches(context, snapshot, tree, id, patch_set); + compute_property_patches(&mut snapshot, &instance, patch_set); + compute_children_patches(context, &mut snapshot, tree, id, patch_set); } fn compute_property_patches( - snapshot: &InstanceSnapshot, + snapshot: &mut InstanceSnapshot, instance: &InstanceWithMeta, patch_set: &mut PatchSet, ) { @@ -103,32 +102,32 @@ fn compute_property_patches( let changed_name = if snapshot.name == instance.name() { None } else { - Some(snapshot.name.clone().into_owned()) + Some(take(&mut snapshot.name).into_owned()) }; let changed_class_name = if snapshot.class_name == instance.class_name() { None } else { - Some(snapshot.class_name.clone().into_owned()) + Some(take(&mut snapshot.class_name).into_owned()) }; let changed_metadata = if &snapshot.metadata == instance.metadata() { None } else { - Some(snapshot.metadata.clone()) + Some(take(&mut snapshot.metadata)) }; - for (name, snapshot_value) in &snapshot.properties { - visited_properties.insert(name.as_str()); + for (name, snapshot_value) in take(&mut snapshot.properties) { + visited_properties.insert(name.clone()); - match instance.properties().get(name) { + match instance.properties().get(&name) { Some(instance_value) => { - if snapshot_value != instance_value { - changed_properties.insert(name.clone(), Some(snapshot_value.clone())); + if &snapshot_value != instance_value { + changed_properties.insert(name, Some(snapshot_value)); } } None => { - changed_properties.insert(name.clone(), Some(snapshot_value.clone())); + changed_properties.insert(name, Some(snapshot_value)); } } } @@ -160,7 +159,7 @@ fn compute_property_patches( fn compute_children_patches( context: &mut ComputePatchContext, - snapshot: &InstanceSnapshot, + snapshot: &mut InstanceSnapshot, tree: &RojoTree, id: Ref, patch_set: &mut PatchSet, @@ -173,7 +172,7 @@ fn compute_children_patches( let mut paired_instances = vec![false; instance_children.len()]; - for snapshot_child in snapshot.children.iter() { + for snapshot_child in take(&mut snapshot.children) { let matching_instance = instance_children .iter() @@ -210,7 +209,7 @@ fn compute_children_patches( None => { patch_set.added_instances.push(PatchAdd { parent_id: id, - instance: snapshot_child.clone(), + instance: snapshot_child, }); } } @@ -258,7 +257,7 @@ mod test { children: Vec::new(), }; - let patch_set = compute_patch_set(Some(&snapshot), &tree, root_id); + let patch_set = compute_patch_set(Some(snapshot), &tree, root_id); let expected_patch_set = PatchSet { updated_instances: vec![PatchUpdate { @@ -308,7 +307,7 @@ mod test { class_name: Cow::Borrowed("foo"), }; - let patch_set = compute_patch_set(Some(&snapshot), &tree, root_id); + let patch_set = compute_patch_set(Some(snapshot), &tree, root_id); let expected_patch_set = PatchSet { added_instances: vec![PatchAdd { diff --git a/src/snapshot/tests/compute.rs b/src/snapshot/tests/compute.rs index 7b15d378..309d73b6 100644 --- a/src/snapshot/tests/compute.rs +++ b/src/snapshot/tests/compute.rs @@ -23,7 +23,7 @@ fn set_name_and_class_name() { children: Vec::new(), }; - let patch_set = compute_patch_set(Some(&snapshot), &tree, tree.get_root_id()); + let patch_set = compute_patch_set(Some(snapshot), &tree, tree.get_root_id()); let patch_value = redactions.redacted_yaml(patch_set); assert_yaml_snapshot!(patch_value); @@ -47,7 +47,7 @@ fn set_property() { children: Vec::new(), }; - let patch_set = compute_patch_set(Some(&snapshot), &tree, tree.get_root_id()); + let patch_set = compute_patch_set(Some(snapshot), &tree, tree.get_root_id()); let patch_value = redactions.redacted_yaml(patch_set); assert_yaml_snapshot!(patch_value); @@ -78,7 +78,7 @@ fn remove_property() { children: Vec::new(), }; - let patch_set = compute_patch_set(Some(&snapshot), &tree, tree.get_root_id()); + let patch_set = compute_patch_set(Some(snapshot), &tree, tree.get_root_id()); let patch_value = redactions.redacted_yaml(patch_set); assert_yaml_snapshot!(patch_value); @@ -107,7 +107,7 @@ fn add_child() { }], }; - let patch_set = compute_patch_set(Some(&snapshot), &tree, tree.get_root_id()); + let patch_set = compute_patch_set(Some(snapshot), &tree, tree.get_root_id()); let patch_value = redactions.redacted_yaml(patch_set); assert_yaml_snapshot!(patch_value); @@ -139,7 +139,7 @@ fn remove_child() { children: Vec::new(), }; - let patch_set = compute_patch_set(Some(&snapshot), &tree, tree.get_root_id()); + let patch_set = compute_patch_set(Some(snapshot), &tree, tree.get_root_id()); let patch_value = redactions.redacted_yaml(patch_set); assert_yaml_snapshot!(patch_value); diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index b0f12b69..e342e186 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -87,8 +87,9 @@ impl RojoTree { } pub fn insert_instance(&mut self, parent_ref: Ref, snapshot: InstanceSnapshot) -> Ref { - let builder = InstanceBuilder::new(snapshot.class_name.to_owned()) - .with_name(snapshot.name.to_owned()) + let builder = InstanceBuilder::empty() + .with_class(snapshot.class_name.into_owned()) + .with_name(snapshot.name.into_owned()) .with_properties(snapshot.properties); let referent = self.inner.insert(parent_ref, builder); diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index c94d4ef4..969f022d 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -22,7 +22,8 @@ pub fn snapshot_rbxm( let children = root_instance.children(); if children.len() == 1 { - let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) + let child = children[0]; + let snapshot = InstanceSnapshot::from_tree(temp_tree, child) .name(name) .metadata( InstanceMetadata::new() diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 3cdd52e4..4f128ff6 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -24,7 +24,8 @@ pub fn snapshot_rbxmx( let children = root_instance.children(); if children.len() == 1 { - let snapshot = InstanceSnapshot::from_tree(&temp_tree, children[0]) + let child = children[0]; + let snapshot = InstanceSnapshot::from_tree(temp_tree, child) .name(name) .metadata( InstanceMetadata::new() From c06463b61d781e7b5179d9a38c7a6ed04585d5f2 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 5 Jun 2022 17:48:17 -0400 Subject: [PATCH 1218/1504] Update CHANGELOG --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3894731d..23494c95 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ ## Unreleased Changes * Switched from structopt to clap for command line argument parsing. +* Significantly improved performance of building and serving. ([#548]) + +[#548]: https://github.com/rojo-rbx/rojo/pull/548 ## [7.1.1] - May 26, 2022 * Fixed sourcemap command not stripping paths correctly ([#544]) From e5dbee107330e234444e8ba2d789649745a28581 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Thu, 9 Jun 2022 21:42:37 -0400 Subject: [PATCH 1219/1504] Defer application of `init.meta.json` until after init Lua files. (#549) Fixes #546. --- .../end_to_end__tests__build__issue_546.snap | 14 +++++++ rojo-test/build-tests/issue_546/README.md | 2 + .../issue_546/default.project.json | 6 +++ .../issue_546/hello/init.client.lua | 1 + .../issue_546/hello/init.meta.json | 5 +++ src/snapshot_middleware/dir.rs | 41 ++++++++++++++++--- src/snapshot_middleware/lua.rs | 12 +++++- tests/tests/build.rs | 3 +- 8 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__issue_546.snap create mode 100644 rojo-test/build-tests/issue_546/README.md create mode 100644 rojo-test/build-tests/issue_546/default.project.json create mode 100644 rojo-test/build-tests/issue_546/hello/init.client.lua create mode 100644 rojo-test/build-tests/issue_546/hello/init.meta.json diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__issue_546.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__issue_546.snap new file mode 100644 index 00000000..3107344a --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__issue_546.snap @@ -0,0 +1,14 @@ +--- +source: tests/tests/build.rs +assertion_line: 98 +expression: contents +--- + + + + issue_546 + true + print("Hello, world!") + + + diff --git a/rojo-test/build-tests/issue_546/README.md b/rojo-test/build-tests/issue_546/README.md new file mode 100644 index 00000000..7ccd95fa --- /dev/null +++ b/rojo-test/build-tests/issue_546/README.md @@ -0,0 +1,2 @@ +# Issue #546 (https://github.com/rojo-rbx/rojo/issues/546) +Regression from Rojo 6.2.0 to Rojo 7.0.0. Meta files named as init.meta.json should apply after init.client.lua and other init files. \ No newline at end of file diff --git a/rojo-test/build-tests/issue_546/default.project.json b/rojo-test/build-tests/issue_546/default.project.json new file mode 100644 index 00000000..65c91a52 --- /dev/null +++ b/rojo-test/build-tests/issue_546/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "issue_546", + "tree": { + "$path": "hello" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/issue_546/hello/init.client.lua b/rojo-test/build-tests/issue_546/hello/init.client.lua new file mode 100644 index 00000000..1385fe3e --- /dev/null +++ b/rojo-test/build-tests/issue_546/hello/init.client.lua @@ -0,0 +1 @@ +print("Hello, world!") \ No newline at end of file diff --git a/rojo-test/build-tests/issue_546/hello/init.meta.json b/rojo-test/build-tests/issue_546/hello/init.meta.json new file mode 100644 index 00000000..54f46925 --- /dev/null +++ b/rojo-test/build-tests/issue_546/hello/init.meta.json @@ -0,0 +1,5 @@ +{ + "properties": { + "Disabled": true + } +} \ No newline at end of file diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index bad35c81..404b794d 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -10,6 +10,40 @@ pub fn snapshot_dir( context: &InstanceContext, vfs: &Vfs, path: &Path, +) -> anyhow::Result> { + let mut snapshot = match snapshot_dir_no_meta(context, vfs, path)? { + Some(snapshot) => snapshot, + None => return Ok(None), + }; + + if let Some(mut meta) = dir_meta(vfs, path)? { + meta.apply_all(&mut snapshot)?; + } + + Ok(Some(snapshot)) +} + +/// Retrieves the meta file that should be applied for this directory, if it +/// exists. +pub fn dir_meta(vfs: &Vfs, path: &Path) -> anyhow::Result> { + let meta_path = path.join("init.meta.json"); + + if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { + let metadata = DirectoryMetadata::from_slice(&meta_contents, meta_path)?; + Ok(Some(metadata)) + } else { + Ok(None) + } +} + +/// Snapshot a directory without applying meta files; useful for if the +/// directory's ClassName will change before metadata should be applied. For +/// example, this can happen if the directory contains an `init.client.lua` +/// file. +pub fn snapshot_dir_no_meta( + context: &InstanceContext, + vfs: &Vfs, + path: &Path, ) -> anyhow::Result> { let passes_filter_rules = |child: &DirEntry| { context @@ -52,7 +86,7 @@ pub fn snapshot_dir( path.join("init.client.lua"), ]; - let mut snapshot = InstanceSnapshot::new() + let snapshot = InstanceSnapshot::new() .name(instance_name) .class_name("Folder") .children(snapshot_children) @@ -63,11 +97,6 @@ pub fn snapshot_dir( .context(context), ); - if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { - let mut metadata = DirectoryMetadata::from_slice(&meta_contents, meta_path)?; - metadata.apply_all(&mut snapshot)?; - } - Ok(Some(snapshot)) } diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 02bbc51d..1b911762 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -6,7 +6,11 @@ use memofs::{IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{dir::snapshot_dir, meta_file::AdjacentMetadata, util::match_trailing}; +use super::{ + dir::{dir_meta, snapshot_dir_no_meta}, + meta_file::AdjacentMetadata, + util::match_trailing, +}; /// Core routine for turning Lua files into snapshots. pub fn snapshot_lua( @@ -66,7 +70,7 @@ pub fn snapshot_lua_init( init_path: &Path, ) -> anyhow::Result> { let folder_path = init_path.parent().unwrap(); - let dir_snapshot = snapshot_dir(context, vfs, folder_path)?.unwrap(); + let dir_snapshot = snapshot_dir_no_meta(context, vfs, folder_path)?.unwrap(); if dir_snapshot.class_name != "Folder" { anyhow::bail!( @@ -86,6 +90,10 @@ pub fn snapshot_lua_init( init_snapshot.children = dir_snapshot.children; init_snapshot.metadata = dir_snapshot.metadata; + if let Some(mut meta) = dir_meta(vfs, folder_path)? { + meta.apply_all(&mut init_snapshot)?; + } + Ok(Some(init_snapshot)) } diff --git a/tests/tests/build.rs b/tests/tests/build.rs index fc3b55fe..fc917d04 100644 --- a/tests/tests/build.rs +++ b/tests/tests/build.rs @@ -36,11 +36,13 @@ gen_build_tests! { init_meta_class_name, init_meta_properties, init_with_children, + issue_546, json_as_lua, json_model_in_folder, json_model_legacy_name, module_in_folder, module_init, + optional, project_composed_default, project_composed_file, project_root_name, @@ -53,7 +55,6 @@ gen_build_tests! { txt, txt_in_folder, unresolved_values, - optional, weldconstraint, } From 2e7c4b6dff7efe8a5ba794cfca467ee7cdcc6bdf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 10 Jun 2022 01:55:16 -0400 Subject: [PATCH 1220/1504] Update Changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 23494c95..797d1ccc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,10 @@ ## Unreleased Changes * Switched from structopt to clap for command line argument parsing. * Significantly improved performance of building and serving. ([#548]) +* Fixed `init.meta.json` when used with `init.lua` and related files. ([#549]) [#548]: https://github.com/rojo-rbx/rojo/pull/548 +[#549]: https://github.com/rojo-rbx/rojo/pull/549 ## [7.1.1] - May 26, 2022 * Fixed sourcemap command not stripping paths correctly ([#544]) From 2624ea7d2a3a9e3d724aae5c33d5c663ac970b10 Mon Sep 17 00:00:00 2001 From: Micah <48431591+nezuo@users.noreply.github.com> Date: Sat, 11 Jun 2022 23:57:40 -0700 Subject: [PATCH 1221/1504] Remove .luacheckrc (#551) --- .luacheckrc | 58 ----------------------------------------------------- 1 file changed, 58 deletions(-) delete mode 100644 .luacheckrc diff --git a/.luacheckrc b/.luacheckrc deleted file mode 100644 index bb55667f..00000000 --- a/.luacheckrc +++ /dev/null @@ -1,58 +0,0 @@ -stds.roblox = { - read_globals = { - game = { - other_fields = true, - }, - - -- Roblox globals - "script", - - -- Extra functions - "tick", "warn", "spawn", - "wait", "settings", "typeof", - - -- Types - "Vector2", "Vector3", - "Vector2int16", "Vector3int16", - "Color3", - "UDim", "UDim2", - "Rect", - "CFrame", - "Enum", - "Instance", - "DockWidgetPluginGuiInfo", - } -} - -stds.plugin = { - read_globals = { - "plugin", - } -} - -stds.testez = { - read_globals = { - "describe", - "it", "itFOCUS", "itSKIP", "itFIXME", - "FOCUS", "SKIP", "HACK_NO_XPCALL", - "expect", - } -} - -ignore = { - "212", -- unused arguments - "421", -- shadowing local variable - "422", -- shadowing argument - "431", -- shadowing upvalue - "432", -- shadowing upvalue argument -} - -std = "lua51+roblox" - -files["**/*.server.lua"] = { - std = "+plugin", -} - -files["**/*.spec.lua"] = { - std = "+testez", -} \ No newline at end of file From cf76982cfafb6919caf4bc96ca5db3f05d7297d9 Mon Sep 17 00:00:00 2001 From: Micah <48431591+nezuo@users.noreply.github.com> Date: Sun, 12 Jun 2022 00:41:49 -0700 Subject: [PATCH 1222/1504] Update selene (#550) * Update selene * Update foreman.toml Co-authored-by: Sasial <44125644+sasial-dev@users.noreply.github.com> Co-authored-by: Sasial <44125644+sasial-dev@users.noreply.github.com> Co-authored-by: Lucien Greathouse --- .gitignore | 3 --- foreman.toml | 2 +- testez.toml | 66 ---------------------------------------------------- testez.yml | 53 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 54 insertions(+), 70 deletions(-) delete mode 100644 testez.toml create mode 100644 testez.yml diff --git a/.gitignore b/.gitignore index b12513e1..88cdf551 100644 --- a/.gitignore +++ b/.gitignore @@ -19,6 +19,3 @@ # Snapshot files from the 'insta' Rust crate **/*.snap.new - -# Selene generates a roblox.toml file that should not be checked in. -/roblox.toml \ No newline at end of file diff --git a/foreman.toml b/foreman.toml index c1275b8d..20ce14cb 100644 --- a/foreman.toml +++ b/foreman.toml @@ -1,4 +1,4 @@ [tools] rojo = { source = "rojo-rbx/rojo", version = "7.1.1" } run-in-roblox = { source = "rojo-rbx/run-in-roblox", version = "0.3.0" } -selene = { source = "Kampfkarren/selene", version = "0.17.0" } +selene = { source = "Kampfkarren/selene", version = "0.18.2" } diff --git a/testez.toml b/testez.toml deleted file mode 100644 index c2c5a984..00000000 --- a/testez.toml +++ /dev/null @@ -1,66 +0,0 @@ -[[afterAll.args]] -type = "function" - -[[afterEach.args]] -type = "function" - -[[beforeAll.args]] -type = "function" - -[[beforeEach.args]] -type = "function" - -[[describe.args]] -type = "string" - -[[describe.args]] -type = "function" - -[[describeFOCUS.args]] -type = "string" - -[[describeFOCUS.args]] -type = "function" - -[[describeSKIP.args]] -type = "string" - -[[describeSKIP.args]] -type = "function" - -[[expect.args]] -type = "any" - -[[FIXME.args]] -type = "string" -required = false - -[FOCUS] -args = [] - -[[it.args]] -type = "string" - -[[it.args]] -type = "function" - -[[itFIXME.args]] -type = "string" - -[[itFIXME.args]] -type = "function" - -[[itFOCUS.args]] -type = "string" - -[[itFOCUS.args]] -type = "function" - -[[itSKIP.args]] -type = "string" - -[[itSKIP.args]] -type = "function" - -[SKIP] -args = [] diff --git a/testez.yml b/testez.yml new file mode 100644 index 00000000..08be74e1 --- /dev/null +++ b/testez.yml @@ -0,0 +1,53 @@ +--- +globals: + FIXME: + args: + - required: false + type: string + FOCUS: + args: [] + SKIP: + args: [] + afterAll: + args: + - type: function + afterEach: + args: + - type: function + beforeAll: + args: + - type: function + beforeEach: + args: + - type: function + describe: + args: + - type: string + - type: function + describeFOCUS: + args: + - type: string + - type: function + describeSKIP: + args: + - type: string + - type: function + expect: + args: + - type: any + it: + args: + - type: string + - type: function + itFIXME: + args: + - type: string + - type: function + itFOCUS: + args: + - type: string + - type: function + itSKIP: + args: + - type: string + - type: function From cd5d6fd15cc6225ced392528cbf67395298aa47b Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sun, 12 Jun 2022 04:32:26 -0400 Subject: [PATCH 1223/1504] Add test project for tags --- test-projects/tags/default.project.json | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 test-projects/tags/default.project.json diff --git a/test-projects/tags/default.project.json b/test-projects/tags/default.project.json new file mode 100644 index 00000000..51abe57c --- /dev/null +++ b/test-projects/tags/default.project.json @@ -0,0 +1,14 @@ +{ + "name": "tags", + "tree": { + "$className": "DataModel", + "Workspace": { + "Folder": { + "$className": "Folder", + "$properties": { + "Tags": ["Hello", "World"] + } + } + } + } +} \ No newline at end of file From 2e672badf2f602ebbbf492e300d93f42979b5305 Mon Sep 17 00:00:00 2001 From: Michael Schmatz Date: Wed, 22 Jun 2022 01:46:34 -0700 Subject: [PATCH 1224/1504] Update rbx_binary to 0.6.5 (#558) --- Cargo.lock | 5 +++-- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 45e9c897..b42d64ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1639,12 +1639,13 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68f424adb7a0a24ab4bd153be141035f1404ae40affed902fd2721b42cca7f86" +checksum = "28fe644ede286801c9bd59527b332d69449c6e9eaefa2277a0e776252097bc90" dependencies = [ "log", "lz4", + "profiling", "rbx_dom_weak", "rbx_reflection", "rbx_reflection_database", diff --git a/Cargo.toml b/Cargo.toml index 83749b32..25eedb6b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,7 +50,7 @@ memofs = { version = "0.2.0", path = "crates/memofs" } # rbx_reflection_database = { path = "../rbx-dom/rbx_reflection_database" } # rbx_xml = { path = "../rbx-dom/rbx_xml" } -rbx_binary = "0.6.4" +rbx_binary = "0.6.5" rbx_dom_weak = "2.4.0" rbx_reflection = "4.2.0" rbx_reflection_database = "0.2.2" From f9b7774286c6578e1e610c60c8e9353a0d28474e Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Sun, 26 Jun 2022 20:22:16 +0100 Subject: [PATCH 1225/1504] Change linux release runner to use `ubuntu-18.04` (#561) ubuntu-latest uses Ubuntu 20.04, this causes issues with glibc as older versions of ubuntu/other distros use an older version. This is fixed by building the release binary on `ubuntu-18.04`, which uses a version of glibc more widely available. Ref: https://github.com/JohnnyMorganz/StyLua/pull/444 https://github.com/JohnnyMorganz/StyLua/pull/445 --- .github/workflows/release.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 05ec5bd4..216d8cad 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -67,7 +67,7 @@ jobs: # -x86_64 to each release. include: - host: linux - os: ubuntu-latest + os: ubuntu-18.04 target: x86_64-unknown-linux-gnu label: linux @@ -150,4 +150,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: ${{ env.BIN }}-${{ env.PROJECT_VERSION }}-${{ matrix.label }}.zip - path: release.zip \ No newline at end of file + path: release.zip From 0d1bc0d7fe6c29ee478cc806b3336f05b5cf2023 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 29 Jun 2022 17:58:57 -0400 Subject: [PATCH 1226/1504] Update dependencies --- Cargo.lock | 277 +++++++++++++++++++++++++---------------------------- 1 file changed, 133 insertions(+), 144 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b42d64ab..22b557a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -37,9 +37,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.57" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f9b8508dccb7687a1d6c4ce66b2b0ecef467c94667de27d8d7fe1f8d2a9cdc" +checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" [[package]] name = "arrayref" @@ -85,12 +85,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" - [[package]] name = "base64" version = "0.13.0" @@ -232,16 +226,16 @@ dependencies = [ [[package]] name = "clap" -version = "3.1.18" +version = "3.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2dbdf4bdacb33466e854ce889eee8dfd5729abf7ccd7664d0a2d60cd384440b" +checksum = "5b7b16274bb247b45177db843202209b12191b631a14a9d06e41b3777d6ecf14" dependencies = [ "atty", "bitflags", "clap_derive", "clap_lex", "indexmap", - "lazy_static", + "once_cell", "strsim", "termcolor", "textwrap 0.15.0", @@ -249,22 +243,22 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.1.18" +version = "3.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25320346e922cffe59c0bbc5410c8d8784509efb321488971081313cb1e1a33c" +checksum = "759bf187376e1afa7b85b959e6a664a3e7a95203415dba952ad19139e798f902" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", "syn", ] [[package]] name = "clap_lex" -version = "0.2.0" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37c35f1112dad5e6e0b1adaff798507497a18fceeb30cceb3bae7d1427b9213" +checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5" dependencies = [ "os_str_bytes", ] @@ -342,9 +336,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaa7bd5fb665c6864b5f963dd9097905c54125909c7aa94c9e18507cdbe6c53" +checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -363,26 +357,26 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.8" +version = "0.9.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1145cf131a2c6ba0615079ab6a638f7e1973ac9c2634fcbeaaad6114246efe8c" +checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", - "lazy_static", "memoffset", + "once_cell", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.8" +version = "0.8.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf124c720b7686e3c2663cf54062ab0f68a88af2fb6a030e87e30bf721fcb38" +checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" dependencies = [ "cfg-if 1.0.0", - "lazy_static", + "once_cell", ] [[package]] @@ -423,15 +417,15 @@ version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" dependencies = [ - "quote 1.0.18", + "quote 1.0.20", "syn", ] [[package]] name = "diff" -version = "0.1.12" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "digest" @@ -476,9 +470,9 @@ dependencies = [ [[package]] name = "either" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" [[package]] name = "embed-resource" @@ -674,8 +668,8 @@ version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", "syn", ] @@ -743,13 +737,13 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9be70c98951c83b8d2f8f60d7065fa6d5146873094452a1008da8c2f1e4205ad" +checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" dependencies = [ "cfg-if 1.0.0", "libc", - "wasi 0.10.2+wasi-snapshot-preview1", + "wasi", ] [[package]] @@ -760,9 +754,9 @@ checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" [[package]] name = "globset" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd" +checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" dependencies = [ "aho-corasick", "bstr", @@ -798,9 +792,9 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hashbrown" -version = "0.11.2" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" [[package]] name = "heck" @@ -825,9 +819,9 @@ checksum = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" [[package]] name = "http" -version = "0.2.7" +version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff8670570af52249509a86f5e3e18a08c60b177071826898fde8997cf5f6bfbb" +checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", @@ -913,9 +907,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "1.8.2" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6012d540c5baa3589337a98ce73408de9b5a25ec9fc2c6fd6be8f0d39e0ca5a" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" dependencies = [ "autocfg", "hashbrown", @@ -943,9 +937,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.14.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcc3e639bcba360d9237acabd22014c16f3df772db463b7446cd81b070714767" +checksum = "4126dd76ebfe2561486a1bd6738a33d2029ffb068a99ac446b7f8c77b2e58dbc" dependencies = [ "console", "once_cell", @@ -1010,9 +1004,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] name = "js-sys" -version = "0.3.57" +version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "671a26f820db17c2a2750743f1dd03bafd15b98c9f30c7c2628c024c05d73397" +checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" dependencies = [ "wasm-bindgen", ] @@ -1047,9 +1041,9 @@ checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" [[package]] name = "linked-hash-map" -version = "0.5.4" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3" +checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "log" @@ -1175,13 +1169,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ "libc", "log", - "wasi 0.11.0+wasi-snapshot-preview1", + "wasi", "windows-sys", ] @@ -1333,8 +1327,8 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", "syn", ] @@ -1411,8 +1405,8 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", "syn", ] @@ -1498,8 +1492,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", "syn", "version_check", ] @@ -1510,8 +1504,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", "version_check", ] @@ -1538,9 +1532,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" dependencies = [ "unicode-ident", ] @@ -1561,7 +1555,7 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98eee3c112f2a6f784b6713fe1d7fb7d6506e066121c0a49371fdb976f72bae5" dependencies = [ - "quote 1.0.18", + "quote 1.0.20", "syn", ] @@ -1576,11 +1570,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" dependencies = [ - "proc-macro2 1.0.39", + "proc-macro2 1.0.40", ] [[package]] @@ -1639,9 +1633,9 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28fe644ede286801c9bd59527b332d69449c6e9eaefa2277a0e776252097bc90" +checksum = "842a9253d37ca9df932108806a0f6c97195f2411bf05671e88744be622548807" dependencies = [ "log", "lz4", @@ -1674,9 +1668,9 @@ dependencies = [ [[package]] name = "rbx_reflection_database" -version = "0.2.4+roblox-504" +version = "0.2.5+roblox-530" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41e8da85aa697cd04cef48e6dd7d96992786d2e322bafe1d3cc93045f4de1e1" +checksum = "3e790ac1c92dee33669e7e12414caf75eb5cfce6fb5c54998eb9001d204fbab1" dependencies = [ "lazy_static", "rbx_reflection", @@ -1686,11 +1680,11 @@ dependencies = [ [[package]] name = "rbx_types" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cbfc0ca9c674968170d4fbbd95dc692d0b3f9405b4830babc76107dc00a66380" +checksum = "a773e53402f2ae7537bbec77badb7e3ff3e6ddac5ee9c2df7edf0a60edf5c9d8" dependencies = [ - "base64 0.13.0", + "base64", "bitflags", "blake3", "lazy_static", @@ -1701,11 +1695,11 @@ dependencies = [ [[package]] name = "rbx_xml" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67387cd246cdec9251dd2451672541499ae6ce0a47c768b3ea9ee0a1becda9dd" +checksum = "2559683f2f9205d442bd9083d7557be58b6cdcd0e5cc22600a6546a08e6d54f0" dependencies = [ - "base64 0.11.0", + "base64", "log", "rbx_dom_weak", "rbx_reflection", @@ -1770,11 +1764,11 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.10" +version = "0.11.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a1f7aa4f35e5e8b4160449f51afc758f0ce6454315a9fa7d0d113e958c41eb" +checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" dependencies = [ - "base64 0.13.0", + "base64", "bytes", "encoding_rs", "futures-core", @@ -1797,6 +1791,7 @@ dependencies = [ "serde_urlencoded", "tokio", "tokio-native-tls", + "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", @@ -1868,7 +1863,7 @@ dependencies = [ "anyhow", "backtrace", "bincode", - "clap 3.1.18", + "clap 3.2.7", "criterion", "crossbeam-channel", "csv", @@ -1936,9 +1931,9 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f" +checksum = "a0a5f7c728f5d284929a1cccb5bc19884422bfe6ef4d6c409da2c41838983fcf" [[package]] name = "ryu" @@ -2002,9 +1997,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd" +checksum = "3d92beeab217753479be2f74e54187a6aed4c125ff0703a866c3147a02f0c6dd" [[package]] name = "serde" @@ -2031,16 +2026,16 @@ version = "1.0.137" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", "syn", ] [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" dependencies = [ "itoa 1.0.2", "ryu", @@ -2106,9 +2101,9 @@ checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" [[package]] name = "smallvec" -version = "1.8.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2" [[package]] name = "snax" @@ -2143,12 +2138,12 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.96" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" +checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", "unicode-ident", ] @@ -2215,8 +2210,8 @@ version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", "syn", ] @@ -2256,14 +2251,14 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.19.1" +version = "1.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95eec79ea28c00a365f539f1961e9278fbcaf81c0ff6aaf0e93c181352446948" +checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" dependencies = [ "bytes", "libc", "memchr", - "mio 0.8.3", + "mio 0.8.4", "num_cpus", "once_cell", "pin-project-lite", @@ -2306,15 +2301,15 @@ dependencies = [ [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.34" +version = "0.1.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" +checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -2328,18 +2323,18 @@ version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", "syn", ] [[package]] name = "tracing-core" -version = "0.1.26" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" +checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" dependencies = [ - "lazy_static", + "once_cell", "valuable", ] @@ -2356,13 +2351,13 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.11" +version = "0.3.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" +checksum = "cfbbce75cad20b56f4f4200e413b894c990c7bbd7e47245ff5cbc2b82511e4da" dependencies = [ "ansi_term", - "lazy_static", "matchers", + "once_cell", "regex", "sharded-slab", "smallvec", @@ -2385,9 +2380,9 @@ dependencies = [ [[package]] name = "tracy-client-sys" -version = "0.17.0" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9012b9dfeccaff16e93f5a8b02336125113a80a769902e679d334cbdd4d83f3b" +checksum = "178d021455e83078bb38c00b70046b95117ef0a0312cbef925f426d833d11c79" dependencies = [ "cc", ] @@ -2418,15 +2413,15 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" +checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "81dee68f85cab8cf68dec42158baf3a79a1cdc065a8b103025965d6ccb7f6cbd" dependencies = [ "tinyvec", ] @@ -2457,9 +2452,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6d5d669b51467dcf7b2f1a796ce0f955f05f01cafda6c19d6e95f730df29238" +checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" dependencies = [ "getrandom", "serde", @@ -2524,12 +2519,6 @@ dependencies = [ "try-lock", ] -[[package]] -name = "wasi" -version = "0.10.2+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" - [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" @@ -2538,9 +2527,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27370197c907c55e3f1a9fbe26f44e937fe6451368324e009cba39e139dc08ad" +checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -2548,24 +2537,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e04185bfa3a779273da532f5025e33398409573f348985af9a1cbf3774d3f4" +checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" dependencies = [ "bumpalo", "lazy_static", "log", - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.30" +version = "0.4.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f741de44b75e14c35df886aff5f1eb73aa114fa5d4d00dcd37b5e01259bf3b2" +checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -2575,22 +2564,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17cae7ff784d7e83a2fe7611cfe766ecf034111b49deb850a3dc7699c08251f5" +checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" dependencies = [ - "quote 1.0.18", + "quote 1.0.20", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99ec0dc7a4756fffc231aab1b9f2f578d23cd391390ab27f952ae0c9b3ece20b" +checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" dependencies = [ - "proc-macro2 1.0.39", - "quote 1.0.18", + "proc-macro2 1.0.40", + "quote 1.0.20", "syn", "wasm-bindgen-backend", "wasm-bindgen-shared", @@ -2598,15 +2587,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.80" +version = "0.2.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d554b7f530dee5964d9a9468d95c1f8b8acae4f282807e7d27d4b03099a46744" +checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" [[package]] name = "web-sys" -version = "0.3.57" +version = "0.3.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b17e741662c70c8bd24ac5c5b18de314a2c26c32bf8346ee1e6f53de919c283" +checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" dependencies = [ "js-sys", "wasm-bindgen", From 8ea41480b723312df90fecdb32c28323207af8e6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 29 Jun 2022 18:41:37 -0400 Subject: [PATCH 1227/1504] Bump MSRV (#564) * Bump MSRV * Fix updated snapshot --- .github/workflows/ci.yml | 2 +- README.md | 2 +- .../end_to_end__tests__build__weldconstraint.snap | 14 +++++--------- 3 files changed, 7 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a589a7e7..ab5ffe20 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - rust_version: [stable, 1.55.0] + rust_version: [stable, 1.57.0] steps: - uses: actions/checkout@v3 diff --git a/README.md b/README.md index ce0d5c30..414ddd74 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions fo Pull requests are welcome! -Rojo supports Rust 1.46.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. +Rojo supports Rust 1.57.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. ## License Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__weldconstraint.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__weldconstraint.snap index 7a87112a..e3b95447 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__weldconstraint.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__weldconstraint.snap @@ -1,14 +1,13 @@ --- source: tests/tests/build.rs +assertion_line: 98 expression: contents - --- weldconstraint - - + -1 @@ -16,8 +15,7 @@ expression: contents A false - - + -0.5 0.5 0 @@ -108,8 +106,7 @@ expression: contents WeldConstraint - - + 7 0.000001013279 @@ -136,8 +133,7 @@ expression: contents B false - - + -0.5 0.5 0 From acf74563714d016cb753e436bcd2dd3325d88c0c Mon Sep 17 00:00:00 2001 From: Samuel P <60328723+imacodr@users.noreply.github.com> Date: Wed, 29 Jun 2022 16:53:10 -0600 Subject: [PATCH 1228/1504] Accept .luau files (#552) * accept .luau files * Accept .luau in snapshot creation * Update versioning and snapshots. * fix versioning * Run rustfmt * Reduce repetition in extension detection * Tidy build script change Co-authored-by: Lucien Greathouse --- build.rs | 2 +- src/snapshot_middleware/dir.rs | 3 +++ src/snapshot_middleware/lua.rs | 6 ++++++ src/snapshot_middleware/mod.rs | 21 ++++++++++++++++++- ...t_middleware__dir__test__empty_folder.snap | 4 ++++ ...ddleware__dir__test__folder_in_folder.snap | 7 +++++++ src/web/api.rs | 7 ++++--- 7 files changed, 45 insertions(+), 5 deletions(-) diff --git a/build.rs b/build.rs index 5ac7672b..0cbd190f 100644 --- a/build.rs +++ b/build.rs @@ -21,7 +21,7 @@ fn snapshot_from_fs_path(path: &Path) -> io::Result { // We can skip any TestEZ test files since they aren't necessary for // the plugin to run. - if file_name.ends_with(".spec.lua") { + if file_name.ends_with(".spec.lua") || file_name.ends_with(".spec.luau") { continue; } diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 404b794d..46fff335 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -82,8 +82,11 @@ pub fn snapshot_dir_no_meta( // middleware. Should we figure out a way for that function to add // relevant paths to this middleware? path.join("init.lua"), + path.join("init.luau"), path.join("init.server.lua"), + path.join("init.server.luau"), path.join("init.client.lua"), + path.join("init.client.luau"), ]; let snapshot = InstanceSnapshot::new() diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 1b911762..ba221626 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -27,6 +27,12 @@ pub fn snapshot_lua( ("LocalScript", name) } else if let Some(name) = match_trailing(&file_name, ".lua") { ("ModuleScript", name) + } else if let Some(name) = match_trailing(&file_name, ".server.luau") { + ("Script", name) + } else if let Some(name) = match_trailing(&file_name, ".client.luau") { + ("LocalScript", name) + } else if let Some(name) = match_trailing(&file_name, ".luau") { + ("ModuleScript", name) } else { return Ok(None); }; diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index a8b348ee..8d27d5bc 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -57,16 +57,31 @@ pub fn snapshot_from_vfs( return snapshot_project(context, vfs, &project_path); } + let init_path = path.join("init.luau"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return snapshot_lua_init(context, vfs, &init_path); + } + let init_path = path.join("init.lua"); if vfs.metadata(&init_path).with_not_found()?.is_some() { return snapshot_lua_init(context, vfs, &init_path); } + let init_path = path.join("init.server.luau"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return snapshot_lua_init(context, vfs, &init_path); + } + let init_path = path.join("init.server.lua"); if vfs.metadata(&init_path).with_not_found()?.is_some() { return snapshot_lua_init(context, vfs, &init_path); } + let init_path = path.join("init.client.luau"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return snapshot_lua_init(context, vfs, &init_path); + } + let init_path = path.join("init.client.lua"); if vfs.metadata(&init_path).with_not_found()?.is_some() { return snapshot_lua_init(context, vfs, &init_path); @@ -74,7 +89,11 @@ pub fn snapshot_from_vfs( snapshot_dir(context, vfs, path) } else { - if let Ok(name) = path.file_name_trim_end(".lua") { + let script_name = path + .file_name_trim_end(".lua") + .or_else(|_| path.file_name_trim_end(".luau")); + + if let Ok(name) = script_name { match name { // init scripts are handled elsewhere and should not turn into // their own children. diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap index f24a53a8..246f9de7 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap @@ -11,10 +11,14 @@ metadata: - /foo - /foo/init.meta.json - /foo/init.lua + - /foo/init.luau - /foo/init.server.lua + - /foo/init.server.luau - /foo/init.client.lua + - /foo/init.client.luau context: {} name: foo class_name: Folder properties: {} children: [] + diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap index e9bd5b92..cd437643 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap @@ -11,8 +11,11 @@ metadata: - /foo - /foo/init.meta.json - /foo/init.lua + - /foo/init.luau - /foo/init.server.lua + - /foo/init.server.luau - /foo/init.client.lua + - /foo/init.client.luau context: {} name: foo class_name: Folder @@ -27,10 +30,14 @@ children: - /foo/Child - /foo/Child/init.meta.json - /foo/Child/init.lua + - /foo/Child/init.luau - /foo/Child/init.server.lua + - /foo/Child/init.server.luau - /foo/Child/init.client.lua + - /foo/Child/init.client.luau context: {} name: Child class_name: Folder properties: {} children: [] + diff --git a/src/web/api.rs b/src/web/api.rs index 93b1ccb0..8f500116 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -244,7 +244,7 @@ impl ApiService { } } -/// If this instance is represented by a script, try to find the correct .lua +/// If this instance is represented by a script, try to find the correct .lua or .luau /// file to open to edit it. fn pick_script_path(instance: InstanceWithMeta<'_>) -> Option { match instance.class_name() { @@ -252,16 +252,17 @@ fn pick_script_path(instance: InstanceWithMeta<'_>) -> Option { _ => return None, } - // Pick the first listed relevant path that has an extension of .lua that + // Pick the first listed relevant path that has an extension of .lua or .luau that // exists. instance .metadata() .relevant_paths .iter() .find(|path| { - // We should only ever open Lua files to be safe. + // We should only ever open Lua or Luau files to be safe. match path.extension().and_then(|ext| ext.to_str()) { Some("lua") => {} + Some("luau") => {} _ => return false, } From eccb95690cbfb001ce567113cc811655a4108b09 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 29 Jun 2022 18:53:34 -0400 Subject: [PATCH 1229/1504] Live sync Attributes (#553) * Add test project for tags * Update rbx_dom_lua and add attributes project * Add Attributes shorthand; not working * Update dependencies * Update rbx_reflection_database * Update rbx_types and commit attributes snapshot --- plugin/rbx_dom_lua/EncodedValue.lua | 54 +- plugin/rbx_dom_lua/allValues.json | 69 + plugin/rbx_dom_lua/customProperties.lua | 20 + plugin/rbx_dom_lua/database.json | 3844 +++++++++++++---- .../end_to_end__tests__build__attributes.snap | 24 + ..._to_end__tests__build__weldconstraint.snap | 2 +- .../attributes/default.project.json | 36 + src/resolution.rs | 7 +- test-projects/attributes/default.project.json | 16 + tests/tests/build.rs | 1 + 10 files changed, 3344 insertions(+), 729 deletions(-) create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__attributes.snap create mode 100644 rojo-test/build-tests/attributes/default.project.json create mode 100644 test-projects/attributes/default.project.json diff --git a/plugin/rbx_dom_lua/EncodedValue.lua b/plugin/rbx_dom_lua/EncodedValue.lua index 3c495888..d910c297 100644 --- a/plugin/rbx_dom_lua/EncodedValue.lua +++ b/plugin/rbx_dom_lua/EncodedValue.lua @@ -23,8 +23,45 @@ end local ALL_AXES = {"X", "Y", "Z"} local ALL_FACES = {"Right", "Top", "Back", "Left", "Bottom", "Front"} +local EncodedValue = {} + local types types = { + Attributes = { + fromPod = function(pod) + local output = {} + + for key, value in pairs(pod) do + local ok, result = EncodedValue.decode(value) + + if ok then + output[key] = result + else + local warning = ("Could not decode attribute value of type %q: %s"):format(typeof(value), tostring(result)) + warn(warning) + end + end + + return output + end, + toPod = function(roblox) + local output = {} + + for key, value in pairs(roblox) do + local ok, result = EncodedValue.encodeNaive(value) + + if ok then + output[key] = result + else + local warning = ("Could not encode attribute value of type %q: %s"):format(typeof(value), tostring(result)) + warn(warning) + end + end + + return output + end, + }, + Axes = { fromPod = function(pod) local axes = {} @@ -433,8 +470,6 @@ types = { }, } -local EncodedValue = {} - function EncodedValue.decode(encodedValue) local ty, value = next(encodedValue) @@ -459,4 +494,19 @@ function EncodedValue.encode(rbxValue, propertyType) } end +local propertyTypeRenames = { + number = "Float64", + boolean = "Bool", + string = "String", +} + +function EncodedValue.encodeNaive(rbxValue) + local propertyType = typeof(rbxValue) + if propertyTypeRenames[propertyType] ~= nil then + propertyType = propertyTypeRenames[propertyType] + end + + return EncodedValue.encode(rbxValue, propertyType) +end + return EncodedValue diff --git a/plugin/rbx_dom_lua/allValues.json b/plugin/rbx_dom_lua/allValues.json index a03cf57b..ca62e541 100644 --- a/plugin/rbx_dom_lua/allValues.json +++ b/plugin/rbx_dom_lua/allValues.json @@ -1,4 +1,73 @@ { + "Attributes": { + "value": { + "Attributes": { + "TestBool": { + "Bool": true + }, + "TestBrickColor": { + "BrickColor": 24 + }, + "TestColor3": { + "Color3": [ + 1.0, + 0.5, + 0.0 + ] + }, + "TestNumber": { + "Float64": 1337.0 + }, + "TestRect": { + "Rect": [ + [ + 1.0, + 2.0 + ], + [ + 3.0, + 4.0 + ] + ] + }, + "TestString": { + "String": "Test" + }, + "TestUDim": { + "UDim": [ + 1.0, + 2 + ] + }, + "TestUDim2": { + "UDim2": [ + [ + 1.0, + 2 + ], + [ + 3.0, + 4 + ] + ] + }, + "TestVector2": { + "Vector2": [ + 1.0, + 2.0 + ] + }, + "TestVector3": { + "Vector3": [ + 1.0, + 2.0, + 3.0 + ] + } + } + }, + "ty": "Attributes" + }, "Axes": { "value": { "Axes": [ diff --git a/plugin/rbx_dom_lua/customProperties.lua b/plugin/rbx_dom_lua/customProperties.lua index 7b3dccba..6a2b64eb 100644 --- a/plugin/rbx_dom_lua/customProperties.lua +++ b/plugin/rbx_dom_lua/customProperties.lua @@ -5,6 +5,26 @@ local CollectionService = game:GetService("CollectionService") -- The reflection database refers to these as having scriptability = "Custom" return { Instance = { + Attributes = { + read = function(instance) + return true, instance:GetAttributes() + end, + write = function(instance, _, value) + local existing = instance:GetAttributes() + + for key, attr in pairs(value) do + instance:SetAttribute(key, attr) + end + + for key in pairs(existing) do + if value[key] == nil then + instance:SetAttribute(key, nil) + end + end + + return true + end, + }, Tags = { read = function(instance) return true, CollectionService:GetTags(instance) diff --git a/plugin/rbx_dom_lua/database.json b/plugin/rbx_dom_lua/database.json index 37183baf..610afbd1 100644 --- a/plugin/rbx_dom_lua/database.json +++ b/plugin/rbx_dom_lua/database.json @@ -1,9 +1,9 @@ { "Version": [ 0, - 504, + 530, 0, - 5040410 + 5300290 ], "Classes": { "ABTestService": { @@ -66,7 +66,7 @@ ] } }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -183,7 +183,7 @@ ] } }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -200,7 +200,7 @@ "Superclass": "Model", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "LevelOfDetail": { @@ -384,7 +384,7 @@ "AlignType": { "Enum": 0 }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CFrame": { @@ -579,7 +579,7 @@ "ApplyAtCenterOfMass": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -660,7 +660,7 @@ "ApiKey": { "String": "" }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -737,7 +737,7 @@ 0.0 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -789,7 +789,7 @@ "AnimationId": { "Content": "" }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -853,7 +853,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -864,13 +864,16 @@ } } }, - "AnimationRigData": { - "Name": "AnimationRigData", - "Tags": [], + "AnimationFromVideoCreatorService": { + "Name": "AnimationFromVideoCreatorService", + "Tags": [ + "NotCreatable", + "Service" + ], "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -881,6 +884,112 @@ } } }, + "AnimationFromVideoCreatorStudioService": { + "Name": "AnimationFromVideoCreatorStudioService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "AnimationRigData": { + "Name": "AnimationRigData", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, + "AnimationStreamTrack": { + "Name": "AnimationStreamTrack", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "IsPlaying": { + "Name": "IsPlaying", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Priority": { + "Name": "Priority", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AnimationPriority" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WeightCurrent": { + "Name": "WeightCurrent", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WeightTarget": { + "Name": "WeightTarget", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "AnimationTrack": { "Name": "AnimationTrack", "Tags": [ @@ -1034,7 +1143,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -1087,7 +1196,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Axes": { @@ -1171,7 +1280,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -1267,7 +1376,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -1507,7 +1616,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CFrame": { @@ -1575,7 +1684,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -1730,7 +1839,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -2384,6 +2493,21 @@ } } }, + "MaterialVariant": { + "Name": "MaterialVariant", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Orientation": { "Name": "Orientation", "Scriptability": "ReadWrite", @@ -2844,6 +2968,21 @@ } } }, + "HSRAssetId": { + "Name": "HSRAssetId", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ImportOrigin": { "Name": "ImportOrigin", "Scriptability": "ReadWrite", @@ -3130,7 +3269,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Brightness": { @@ -3485,7 +3624,7 @@ "AlwaysOnTop": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoLocalize": { @@ -3532,6 +3671,21 @@ "ResetOnSpawn": { "Bool": true }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, "Size": { "UDim2": [ [ @@ -3581,7 +3735,7 @@ "Superclass": "ValueBase", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -3598,7 +3752,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -3615,7 +3769,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -3632,7 +3786,7 @@ "Superclass": "BevelMesh", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Offset": { @@ -3710,7 +3864,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Enabled": { @@ -3753,7 +3907,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Enabled": { @@ -3772,7 +3926,9 @@ }, "BodyAngularVelocity": { "Name": "BodyAngularVelocity", - "Tags": [], + "Tags": [ + "Deprecated" + ], "Superclass": "BodyMover", "Properties": { "AngularVelocity": { @@ -3855,7 +4011,7 @@ 0.0 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "MaxTorque": { @@ -4039,7 +4195,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "HeadColor3": { @@ -4094,7 +4250,9 @@ }, "BodyForce": { "Name": "BodyForce", - "Tags": [], + "Tags": [ + "Deprecated" + ], "Superclass": "BodyMover", "Properties": { "Force": { @@ -4128,7 +4286,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Force": { @@ -4148,7 +4306,9 @@ }, "BodyGyro": { "Name": "BodyGyro", - "Tags": [], + "Tags": [ + "Deprecated" + ], "Superclass": "BodyMover", "Properties": { "CFrame": { @@ -4237,7 +4397,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CFrame": { @@ -4290,6 +4450,7 @@ "BodyMover": { "Name": "BodyMover", "Tags": [ + "Deprecated", "NotCreatable" ], "Superclass": "Instance", @@ -4298,7 +4459,9 @@ }, "BodyPosition": { "Name": "BodyPosition", - "Tags": [], + "Tags": [ + "Deprecated" + ], "Superclass": "BodyMover", "Properties": { "D": { @@ -4387,7 +4550,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "D": { @@ -4420,7 +4583,9 @@ }, "BodyThrust": { "Name": "BodyThrust", - "Tags": [], + "Tags": [ + "Deprecated" + ], "Superclass": "BodyMover", "Properties": { "Force": { @@ -4483,7 +4648,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Force": { @@ -4510,7 +4675,9 @@ }, "BodyVelocity": { "Name": "BodyVelocity", - "Tags": [], + "Tags": [ + "Deprecated" + ], "Superclass": "BodyMover", "Properties": { "MaxForce": { @@ -4586,7 +4753,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "MaxForce": { @@ -4685,7 +4852,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CFrame": { @@ -4745,7 +4912,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -4785,7 +4952,7 @@ "AlwaysOnTop": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CFrame": { @@ -4957,6 +5124,23 @@ } } }, + "MetaBreakpointId": { + "Name": "MetaBreakpointId", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Script": { "Name": "Script", "Scriptability": "None", @@ -5025,7 +5209,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -5081,7 +5265,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -5118,16 +5302,6 @@ } } }, - "CSGCacheService": { - "Name": "CSGCacheService", - "Tags": [ - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, "CSGDictionaryService": { "Name": "CSGDictionaryService", "Tags": [ @@ -5136,7 +5310,7 @@ "Superclass": "FlyweightService", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -5377,7 +5551,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CFrame": { @@ -5457,11 +5631,13 @@ }, "CanvasGroup": { "Name": "CanvasGroup", - "Tags": [], + "Tags": [ + "NotBrowsable" + ], "Superclass": "GuiObject", "Properties": { - "GroupColor": { - "Name": "GroupColor", + "GroupColor3": { + "Name": "GroupColor3", "Scriptability": "ReadWrite", "DataType": { "Value": "Color3" @@ -5473,8 +5649,8 @@ } } }, - "Transparency": { - "Name": "Transparency", + "GroupTransparency": { + "Name": "GroupTransparency", "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" @@ -5497,7 +5673,7 @@ 0.0 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoLocalize": { @@ -5535,13 +5711,16 @@ "Draggable": { "Bool": false }, - "GroupColor": { + "GroupColor3": { "Color3": [ 1.0, 1.0, 1.0 ] }, + "GroupTransparency": { + "Float32": 0.0 + }, "LayoutOrder": { "Int32": 0 }, @@ -5563,6 +5742,24 @@ "Selectable": { "Bool": false }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, + "SelectionOrder": { + "Int32": 0 + }, "Size": { "UDim2": [ [ @@ -5584,9 +5781,6 @@ "Tags": { "BinaryString": "" }, - "Transparency": { - "Float32": 0.0 - }, "Visible": { "Bool": true }, @@ -5637,7 +5831,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Channel": { @@ -5725,7 +5919,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BaseTextureId": { @@ -5785,7 +5979,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BubbleChatEnabled": { @@ -5802,6 +5996,93 @@ } } }, + "ChatInputBarConfiguration": { + "Name": "ChatInputBarConfiguration", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "TextChatConfigurations", + "Properties": { + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TargetTextChannel": { + "Name": "TargetTextChannel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "Enabled": { + "Bool": true + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, + "ChatWindowConfiguration": { + "Name": "ChatWindowConfiguration", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "TextChatConfigurations", + "Properties": { + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "Enabled": { + "Bool": true + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "ChorusSoundEffect": { "Name": "ChorusSoundEffect", "Tags": [], @@ -5848,7 +6129,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Depth": { @@ -5907,7 +6188,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CursorIcon": { @@ -6016,7 +6297,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -6063,7 +6344,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -6094,7 +6375,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -6171,7 +6452,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Brightness": { @@ -6450,7 +6731,7 @@ "Attack": { "Float32": 0.1 }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Enabled": { @@ -6518,7 +6799,7 @@ "AlwaysOnTop": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CFrame": { @@ -6590,7 +6871,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -6755,7 +7036,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -6795,7 +7076,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -6888,7 +7169,7 @@ "Anchored": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -7087,13 +7368,24 @@ } } }, + "CrossDMScriptChangeListener": { + "Name": "CrossDMScriptChangeListener", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "CurveAnimation": { "Name": "CurveAnimation", "Tags": [], "Superclass": "AnimationClip", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Loop": { @@ -7127,7 +7419,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -7160,7 +7452,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -7239,7 +7531,7 @@ "Angle": { "Float32": 360.0 }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CFrame": { @@ -7316,7 +7608,7 @@ "Superclass": "BevelMesh", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Offset": { @@ -7590,7 +7882,7 @@ "AngularVelocity": { "Float32": 0.0 }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -8367,7 +8659,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutomaticRetry": { @@ -8428,7 +8720,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "MaxItems": { @@ -8573,6 +8865,17 @@ }, "DefaultProperties": {} }, + "DebuggablePluginWatcher": { + "Name": "DebuggablePluginWatcher", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "DebuggerBreakpoint": { "Name": "DebuggerBreakpoint", "Tags": [ @@ -9147,7 +9450,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color3": { @@ -9236,7 +9539,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Enabled": { @@ -9399,7 +9702,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BehaviorType": { @@ -9500,7 +9803,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "GoodbyeChoiceActive": { @@ -9543,7 +9846,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Enabled": { @@ -9656,7 +9959,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "MaxValue": { @@ -10040,7 +10343,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Delay": { @@ -10125,7 +10428,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Enabled": { @@ -10171,7 +10474,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "RotationOrder": { @@ -10265,6 +10568,19 @@ } } }, + "TimeScale": { + "Name": "TimeScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Visible": { "Name": "Visible", "Scriptability": "ReadWrite", @@ -10280,7 +10596,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BlastPressure": { @@ -10308,11 +10624,74 @@ "Tags": { "BinaryString": "" }, + "TimeScale": { + "Float32": 1.0 + }, "Visible": { "Bool": true } } }, + "FaceAnimatorService": { + "Name": "FaceAnimatorService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "AudioAnimationEnabled": { + "Name": "AudioAnimationEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FlipHeadOrientation": { + "Name": "FlipHeadOrientation", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "VideoAnimationEnabled": { + "Name": "VideoAnimationEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "FaceControls": { "Name": "FaceControls", "Tags": [ @@ -11072,7 +11451,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -11107,6 +11486,42 @@ }, "DefaultProperties": {} }, + "FacialAnimationStreamingService": { + "Name": "FacialAnimationStreamingService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "Enabled": { + "Name": "Enabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "Feature": { "Name": "Feature", "Tags": [ @@ -11230,7 +11645,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "MeshId": { @@ -11346,6 +11761,19 @@ } } }, + "TimeScale": { + "Name": "TimeScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "heat_xml": { "Name": "heat_xml", "Scriptability": "None", @@ -11390,7 +11818,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -11421,6 +11849,9 @@ }, "Tags": { "BinaryString": "" + }, + "TimeScale": { + "Float32": 1.0 } } }, @@ -11446,7 +11877,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CanBeDropped": { @@ -11529,7 +11960,7 @@ "Anchored": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -11793,7 +12224,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Depth": { @@ -11842,7 +12273,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -11966,7 +12397,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color3": { @@ -12019,7 +12450,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -12036,7 +12467,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -12067,7 +12498,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -12168,7 +12599,7 @@ 0.0 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoLocalize": { @@ -12227,6 +12658,24 @@ "Selectable": { "Bool": false }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, + "SelectionOrder": { + "Int32": 0 + }, "Size": { "UDim2": [ [ @@ -12301,7 +12750,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Description": { @@ -12324,7 +12773,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -12344,32 +12793,6 @@ ], "Superclass": "Instance", "Properties": { - "AdditionalCoreIncludeDirs": { - "Name": "AdditionalCoreIncludeDirs", - "Scriptability": "Read", - "DataType": { - "Value": "String" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "OverrideStarterScript": { - "Name": "OverrideStarterScript", - "Scriptability": "Read", - "DataType": { - "Value": "String" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "VideoCaptureEnabled": { "Name": "VideoCaptureEnabled", "Scriptability": "ReadWrite", @@ -12412,17 +12835,14 @@ "Properties": { "GamepadCursorEnabled": { "Name": "GamepadCursorEnabled", - "Scriptability": "None", + "Scriptability": "Read", "DataType": { "Value": "Bool" }, - "Tags": [ - "Hidden", - "NotReplicated" - ], + "Tags": [], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } } @@ -12447,7 +12867,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -12458,6 +12878,55 @@ } } }, + "GetTextBoundsParams": { + "Name": "GetTextBoundsParams", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Text": { + "Name": "Text", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Width": { + "Name": "Width", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "GlobalDataStore": { "Name": "GlobalDataStore", "Tags": [ @@ -12539,7 +13008,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "C0": { @@ -12813,6 +13282,71 @@ } } }, + "SelectionBehaviorDown": { + "Name": "SelectionBehaviorDown", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SelectionBehavior" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SelectionBehaviorLeft": { + "Name": "SelectionBehaviorLeft", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SelectionBehavior" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SelectionBehaviorRight": { + "Name": "SelectionBehaviorRight", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SelectionBehavior" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SelectionBehaviorUp": { + "Name": "SelectionBehaviorUp", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SelectionBehavior" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SelectionGroup": { + "Name": "SelectionGroup", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TotalGroupScale": { "Name": "TotalGroupScale", "Scriptability": "None", @@ -12979,7 +13513,7 @@ "Superclass": "ScreenGui", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoLocalize": { @@ -12997,6 +13531,21 @@ "ResetOnSpawn": { "Bool": true }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -13299,6 +13848,19 @@ } } }, + "SelectionOrder": { + "Name": "SelectionOrder", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Size": { "Name": "Size", "Scriptability": "ReadWrite", @@ -13555,6 +14117,17 @@ "Properties": {}, "DefaultProperties": {} }, + "HSRDataContentProvider": { + "Name": "HSRDataContentProvider", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "CacheableContentProvider", + "Properties": {}, + "DefaultProperties": {} + }, "HandleAdornment": { "Name": "HandleAdornment", "Tags": [ @@ -13663,7 +14236,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color3": { @@ -13754,7 +14327,7 @@ ] } }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -13775,11 +14348,41 @@ "Properties": {}, "DefaultProperties": {} }, + "HiddenSurfaceRemovalAsset": { + "Name": "HiddenSurfaceRemovalAsset", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "Highlight": { "Name": "Highlight", "Tags": [], "Superclass": "Instance", "Properties": { + "Adornee": { + "Name": "Adornee", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DepthMode": { "Name": "DepthMode", "Scriptability": "ReadWrite", @@ -13860,7 +14463,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "DepthMode": { @@ -14101,7 +14704,7 @@ "AngularVelocity": { "Float32": 0.0 }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -14156,7 +14759,7 @@ "Superclass": "Message", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -14178,7 +14781,7 @@ "Superclass": "Feature", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "FaceId": { @@ -14250,7 +14853,7 @@ "Active": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BinType": { @@ -14309,7 +14912,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "HttpEnabled": { @@ -14831,7 +15434,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoJumpEnabled": { @@ -14908,7 +15511,7 @@ "Superclass": "Controller", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -15440,7 +16043,7 @@ "AccessoryBlob": { "String": "[]" }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackAccessory": { @@ -15812,7 +16415,7 @@ 0.0 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoButtonColor": { @@ -15917,6 +16520,24 @@ "Selected": { "Bool": false }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, + "SelectionOrder": { + "Int32": 0 + }, "Size": { "UDim2": [ [ @@ -16015,7 +16636,7 @@ "AlwaysOnTop": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CFrame": { @@ -16263,7 +16884,7 @@ 0.0 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoLocalize": { @@ -16353,6 +16974,24 @@ "Selectable": { "Bool": false }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, + "SelectionOrder": { + "Int32": 0 + }, "Size": { "UDim2": [ [ @@ -16409,6 +17048,16 @@ } } }, + "ImporterAnimationSettings": { + "Name": "ImporterAnimationSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "ImporterBaseSettings", + "Properties": {}, + "DefaultProperties": {} + }, "ImporterBaseSettings": { "Name": "ImporterBaseSettings", "Tags": [ @@ -16522,6 +17171,97 @@ "Properties": {}, "DefaultProperties": {} }, + "ImporterMaterialSettings": { + "Name": "ImporterMaterialSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "ImporterBaseSettings", + "Properties": { + "DiffuseFilePath": { + "Name": "DiffuseFilePath", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPbr": { + "Name": "IsPbr", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MetalnessFilePath": { + "Name": "MetalnessFilePath", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "NormalFilePath": { + "Name": "NormalFilePath", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RoughnessFilePath": { + "Name": "RoughnessFilePath", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "ImporterMeshSettings": { "Name": "ImporterMeshSettings", "Tags": [ @@ -16543,6 +17283,64 @@ } } }, + "CageManifold": { + "Name": "CageManifold", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CageManifoldPreview": { + "Name": "CageManifoldPreview", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CageNoOverlappingVertices": { + "Name": "CageNoOverlappingVertices", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CageNoOverlappingVerticesPreview": { + "Name": "CageNoOverlappingVerticesPreview", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Dimensions": { "Name": "Dimensions", "Scriptability": "Read", @@ -16667,6 +17465,19 @@ } } }, + "InsertWithScenePosition": { + "Name": "InsertWithScenePosition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "InvertNegativeFaces": { "Name": "InvertNegativeFaces", "Scriptability": "ReadWrite", @@ -16735,6 +17546,19 @@ } } }, + "UseSceneOriginAsPivot": { + "Name": "UseSceneOriginAsPivot", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "WorldForward": { "Name": "WorldForward", "Scriptability": "ReadWrite", @@ -16764,33 +17588,6 @@ }, "DefaultProperties": {} }, - "ImporterTextureSettings": { - "Name": "ImporterTextureSettings", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "ImporterBaseSettings", - "Properties": { - "FilePath": { - "Name": "FilePath", - "Scriptability": "Read", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": {} - }, "IncrementalPatchBuilder": { "Name": "IncrementalPatchBuilder", "Tags": [ @@ -16925,7 +17722,7 @@ "AllowInsertFreeModels": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -16961,9 +17758,9 @@ }, "Attributes": { "Name": "Attributes", - "Scriptability": "None", + "Scriptability": "Custom", "DataType": { - "Value": "BinaryString" + "Value": "Attributes" }, "Tags": [], "Kind": { @@ -16982,8 +17779,8 @@ }, "Tags": [], "Kind": { - "Canonical": { - "Serialization": "Serializes" + "Alias": { + "AliasFor": "Attributes" } } }, @@ -17219,7 +18016,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "MaxValue": { @@ -17256,7 +18053,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -17270,17 +18067,6 @@ } } }, - "InternalContainer": { - "Name": "InternalContainer", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, "InventoryPages": { "Name": "InventoryPages", "Tags": [ @@ -17440,7 +18226,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -17474,7 +18260,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -17510,7 +18296,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AuthoredHipHeight": { @@ -17541,6 +18327,17 @@ "Properties": {}, "DefaultProperties": {} }, + "LSPFileSyncService": { + "Name": "LSPFileSyncService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "LanguageService": { "Name": "LanguageService", "Tags": [ @@ -17551,7 +18348,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -17974,7 +18771,7 @@ 0.5 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Brightness": { @@ -18124,7 +18921,7 @@ "ApplyAtCenterOfMass": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -18195,7 +18992,7 @@ "AlwaysOnTop": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CFrame": { @@ -18385,7 +19182,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -18451,13 +19248,23 @@ } } }, + "LocalDebuggerConnection": { + "Name": "LocalDebuggerConnection", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "DebuggerConnection", + "Properties": {}, + "DefaultProperties": {} + }, "LocalScript": { "Name": "LocalScript", "Tags": [], "Superclass": "Script", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Disabled": { @@ -18610,7 +19417,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -18688,7 +19495,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Contents": { @@ -18741,7 +19548,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -18817,7 +19624,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -18841,11 +19648,13 @@ }, "ManualGlue": { "Name": "ManualGlue", - "Tags": [], + "Tags": [ + "Deprecated" + ], "Superclass": "ManualSurfaceJointInstance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "C0": { @@ -18914,6 +19723,7 @@ "ManualSurfaceJointInstance": { "Name": "ManualSurfaceJointInstance", "Tags": [ + "Deprecated", "NotCreatable" ], "Superclass": "JointInstance", @@ -18922,11 +19732,13 @@ }, "ManualWeld": { "Name": "ManualWeld", - "Tags": [], + "Tags": [ + "Deprecated" + ], "Superclass": "ManualSurfaceJointInstance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "C0": { @@ -19015,7 +19827,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -19045,11 +19857,11 @@ ], "Superclass": "Instance", "Properties": { - "Brick": { - "Name": "Brick", + "AsphaltName": { + "Name": "AsphaltName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19060,11 +19872,11 @@ } } }, - "Cobblestone": { - "Name": "Cobblestone", + "BasaltName": { + "Name": "BasaltName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19075,11 +19887,11 @@ } } }, - "Concrete": { - "Name": "Concrete", + "BrickName": { + "Name": "BrickName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19090,11 +19902,11 @@ } } }, - "CorrodedMetal": { - "Name": "CorrodedMetal", + "CobblestoneName": { + "Name": "CobblestoneName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19105,11 +19917,11 @@ } } }, - "DiamondPlate": { - "Name": "DiamondPlate", + "ConcreteName": { + "Name": "ConcreteName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19120,11 +19932,11 @@ } } }, - "Fabric": { - "Name": "Fabric", + "CorrodedMetalName": { + "Name": "CorrodedMetalName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19135,11 +19947,11 @@ } } }, - "Foil": { - "Name": "Foil", + "CrackedLavaName": { + "Name": "CrackedLavaName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19150,11 +19962,11 @@ } } }, - "Granite": { - "Name": "Granite", + "DiamondPlateName": { + "Name": "DiamondPlateName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19165,11 +19977,11 @@ } } }, - "Grass": { - "Name": "Grass", + "FabricName": { + "Name": "FabricName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19180,11 +19992,11 @@ } } }, - "Ice": { - "Name": "Ice", + "FoilName": { + "Name": "FoilName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19195,11 +20007,11 @@ } } }, - "Marble": { - "Name": "Marble", + "GlacierName": { + "Name": "GlacierName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19210,11 +20022,11 @@ } } }, - "Metal": { - "Name": "Metal", + "GraniteName": { + "Name": "GraniteName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19225,11 +20037,11 @@ } } }, - "Pebble": { - "Name": "Pebble", + "GrassName": { + "Name": "GrassName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19240,11 +20052,11 @@ } } }, - "Plastic": { - "Name": "Plastic", + "GroundName": { + "Name": "GroundName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19255,11 +20067,11 @@ } } }, - "Sand": { - "Name": "Sand", + "IceName": { + "Name": "IceName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19270,11 +20082,11 @@ } } }, - "Slate": { - "Name": "Slate", + "LeafyGrassName": { + "Name": "LeafyGrassName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19285,11 +20097,11 @@ } } }, - "SmoothPlastic": { - "Name": "SmoothPlastic", + "LimestoneName": { + "Name": "LimestoneName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19300,11 +20112,11 @@ } } }, - "Wood": { - "Name": "Wood", + "MarbleName": { + "Name": "MarbleName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19315,11 +20127,11 @@ } } }, - "WoodPlanks": { - "Name": "WoodPlanks", + "MetalName": { + "Name": "MetalName", "Scriptability": "None", "DataType": { - "Value": "Ref" + "Value": "String" }, "Tags": [ "NotScriptable" @@ -19329,17 +20141,340 @@ "Serialization": "Serializes" } } + }, + "MudName": { + "Name": "MudName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PavementName": { + "Name": "PavementName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PebbleName": { + "Name": "PebbleName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlasticName": { + "Name": "PlasticName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RockName": { + "Name": "RockName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SaltName": { + "Name": "SaltName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SandName": { + "Name": "SandName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SandstoneName": { + "Name": "SandstoneName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SlateName": { + "Name": "SlateName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SmoothPlasticName": { + "Name": "SmoothPlasticName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SnowName": { + "Name": "SnowName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Use2022Materials": { + "Name": "Use2022Materials", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WoodName": { + "Name": "WoodName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WoodPlanksName": { + "Name": "WoodPlanksName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "hasPropertyWarningInStudio": { + "Name": "hasPropertyWarningInStudio", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { - "AttributesSerialize": { + "AsphaltName": { + "String": "" + }, + "Attributes": { "BinaryString": "" }, + "BasaltName": { + "String": "" + }, + "BrickName": { + "String": "" + }, + "CobblestoneName": { + "String": "" + }, + "ConcreteName": { + "String": "" + }, + "CorrodedMetalName": { + "String": "" + }, + "CrackedLavaName": { + "String": "" + }, + "DiamondPlateName": { + "String": "" + }, + "FabricName": { + "String": "" + }, + "FoilName": { + "String": "" + }, + "GlacierName": { + "String": "" + }, + "GraniteName": { + "String": "" + }, + "GrassName": { + "String": "" + }, + "GroundName": { + "String": "" + }, + "IceName": { + "String": "" + }, + "LeafyGrassName": { + "String": "" + }, + "LimestoneName": { + "String": "" + }, + "MarbleName": { + "String": "" + }, + "MetalName": { + "String": "" + }, + "MudName": { + "String": "" + }, + "PavementName": { + "String": "" + }, + "PebbleName": { + "String": "" + }, + "PlasticName": { + "String": "" + }, + "RockName": { + "String": "" + }, + "SaltName": { + "String": "" + }, + "SandName": { + "String": "" + }, + "SandstoneName": { + "String": "" + }, + "SlateName": { + "String": "" + }, + "SmoothPlasticName": { + "String": "" + }, + "SnowName": { + "String": "" + }, "SourceAssetId": { "Int64": -1 }, "Tags": { "BinaryString": "" + }, + "WoodName": { + "String": "" + }, + "WoodPlanksName": { + "String": "" } } }, @@ -19376,6 +20511,19 @@ } } }, + "MaterialPattern": { + "Name": "MaterialPattern", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "MaterialPattern" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MetalnessMap": { "Name": "MetalnessMap", "Scriptability": "ReadWrite", @@ -19430,7 +20578,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BaseMaterial": { @@ -19439,6 +20587,9 @@ "ColorMap": { "Content": "" }, + "MaterialPattern": { + "Enum": 0 + }, "MetalnessMap": { "Content": "" }, @@ -19498,7 +20649,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -19671,7 +20822,7 @@ "Anchored": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -19920,7 +21071,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -19982,12 +21133,11 @@ }, "Tags": [ "Hidden", - "NotReplicated", - "ReadOnly" + "NotReplicated" ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } }, @@ -19999,12 +21149,11 @@ }, "Tags": [ "Hidden", - "NotReplicated", - "ReadOnly" + "NotReplicated" ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } }, @@ -20016,12 +21165,11 @@ }, "Tags": [ "Hidden", - "NotReplicated", - "ReadOnly" + "NotReplicated" ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } }, @@ -20067,12 +21215,11 @@ }, "Tags": [ "Hidden", - "NotReplicated", - "ReadOnly" + "NotReplicated" ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } }, @@ -20084,12 +21231,11 @@ }, "Tags": [ "Hidden", - "NotReplicated", - "ReadOnly" + "NotReplicated" ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } }, @@ -20101,17 +21247,44 @@ }, "Tags": [ "Hidden", - "NotReplicated", - "ReadOnly" + "NotReplicated" ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } } }, - "DefaultProperties": {} + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "Condition": { + "String": "" + }, + "ContinueExecution": { + "Bool": false + }, + "Enabled": { + "Bool": true + }, + "Line": { + "Int32": 0 + }, + "LogMessage": { + "String": "" + }, + "Script": { + "String": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } }, "MetaBreakpointContext": { "Name": "MetaBreakpointContext", @@ -20121,7 +21294,17 @@ ], "Superclass": "Instance", "Properties": {}, - "DefaultProperties": {} + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } }, "Model": { "Name": "Model", @@ -20203,7 +21386,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "LevelOfDetail": { @@ -20250,7 +21433,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "LinkedSource": { @@ -20315,7 +21498,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "C0": { @@ -20444,7 +21627,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "C0": { @@ -20524,7 +21707,7 @@ "Superclass": "Feature", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "FaceId": { @@ -20813,7 +21996,7 @@ "AssetId": { "Content": "" }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -21231,32 +22414,6 @@ "Serialization": "Serializes" } } - }, - "TrackDataTypes": { - "Name": "TrackDataTypes", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "TrackPhysicsDetails": { - "Name": "TrackPhysicsDetails", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } } }, "DefaultProperties": {} @@ -21307,7 +22464,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Enabled": { @@ -21329,7 +22486,7 @@ "Superclass": "FlyweightService", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -21419,7 +22576,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "EasingDirection": { @@ -21462,7 +22619,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -21496,7 +22653,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -21833,7 +22990,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color3": { @@ -21936,7 +23093,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color3": { @@ -22000,7 +23157,7 @@ "Anchored": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -22309,7 +23466,7 @@ "AssetId": { "Content": "" }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -22523,7 +23680,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -22617,6 +23774,71 @@ } } }, + "FlipbookFramerate": { + "Name": "FlipbookFramerate", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FlipbookIncompatible": { + "Name": "FlipbookIncompatible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FlipbookLayout": { + "Name": "FlipbookLayout", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ParticleFlipbookLayout" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FlipbookMode": { + "Name": "FlipbookMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ParticleFlipbookMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FlipbookStartRandom": { + "Name": "FlipbookStartRandom", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Lifetime": { "Name": "Lifetime", "Scriptability": "ReadWrite", @@ -22915,7 +24137,7 @@ 0.0 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Brightness": { @@ -22952,6 +24174,24 @@ "Enabled": { "Bool": true }, + "FlipbookFramerate": { + "NumberRange": [ + 1.0, + 1.0 + ] + }, + "FlipbookIncompatible": { + "String": "Particle texture must be 1024 by 1024 to use flipbooks." + }, + "FlipbookLayout": { + "Enum": 0 + }, + "FlipbookMode": { + "Enum": 0 + }, + "FlipbookStartRandom": { + "Bool": false + }, "Lifetime": { "NumberRange": [ 5.0, @@ -23106,7 +24346,9 @@ }, "PathfindingLink": { "Name": "PathfindingLink", - "Tags": [], + "Tags": [ + "NotBrowsable" + ], "Superclass": "Instance", "Properties": { "Attachment0": { @@ -23148,8 +24390,8 @@ } } }, - "ModifierId": { - "Name": "ModifierId", + "Label": { + "Name": "Label", "Scriptability": "ReadWrite", "DataType": { "Value": "String" @@ -23163,13 +24405,13 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "IsBidirectional": { "Bool": true }, - "ModifierId": { + "Label": { "String": "" }, "SourceAssetId": { @@ -23185,8 +24427,8 @@ "Tags": [], "Superclass": "Instance", "Properties": { - "ModifierId": { - "Name": "ModifierId", + "Label": { + "Name": "Label", "Scriptability": "ReadWrite", "DataType": { "Value": "String" @@ -23213,10 +24455,10 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, - "ModifierId": { + "Label": { "String": "" }, "PassThrough": { @@ -23385,7 +24627,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -23405,7 +24647,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -23788,7 +25030,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Enabled": { @@ -23810,11 +25052,39 @@ }, "Plane": { "Name": "Plane", + "Tags": [ + "Deprecated" + ], + "Superclass": "PlaneConstraint", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "Color": { + "Int32": 194 + }, + "Enabled": { + "Bool": true + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "Visible": { + "Bool": false + } + } + }, + "PlaneConstraint": { + "Name": "PlaneConstraint", "Tags": [], "Superclass": "Constraint", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -24547,7 +25817,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CustomPoliciesEnabled": { @@ -24850,7 +26120,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CharacterAutoLoads": { @@ -25389,7 +26659,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Brightness": { @@ -25508,7 +26778,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CFrame": { @@ -25635,7 +26905,7 @@ "ActuatorType": { "Enum": 0 }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -25700,7 +26970,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -25903,7 +27173,7 @@ "ActionText": { "String": "Interact" }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoLocalize": { @@ -25989,7 +27259,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Enabled": { @@ -26047,7 +27317,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -26088,7 +27358,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -26105,7 +27375,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -26175,7 +27445,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Browsable": { @@ -26226,6 +27496,9 @@ "ServerOnly": { "Bool": false }, + "SliderScaling": { + "String": "" + }, "SourceAssetId": { "Int64": -1 }, @@ -26249,7 +27522,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -26266,7 +27539,7 @@ "Superclass": "ReflectionMetadataItem", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Browsable": { @@ -26305,6 +27578,9 @@ "ServerOnly": { "Bool": false }, + "SliderScaling": { + "String": "" + }, "SourceAssetId": { "Int64": -1 }, @@ -26328,7 +27604,7 @@ "Superclass": "ReflectionMetadataItem", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Browsable": { @@ -26367,6 +27643,9 @@ "ServerOnly": { "Bool": false }, + "SliderScaling": { + "String": "" + }, "SourceAssetId": { "Int64": -1 }, @@ -26390,7 +27669,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -26407,7 +27686,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -26424,7 +27703,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -26598,6 +27877,19 @@ } } }, + "SliderScaling": { + "Name": "SliderScaling", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "UIMaximum": { "Name": "UIMaximum", "Scriptability": "ReadWrite", @@ -26646,7 +27938,7 @@ "Superclass": "ReflectionMetadataItem", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Browsable": { @@ -26685,6 +27977,9 @@ "ServerOnly": { "Bool": false }, + "SliderScaling": { + "String": "" + }, "SourceAssetId": { "Int64": -1 }, @@ -26708,7 +28003,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -26725,7 +28020,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -26753,7 +28048,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -26770,7 +28065,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -27119,7 +28414,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CFrame": { @@ -27189,27 +28484,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "ReplicatedScriptService": { - "Name": "ReplicatedScriptService", - "Tags": [ - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -27229,7 +28504,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -27312,7 +28587,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "DecayTime": { @@ -27346,23 +28621,23 @@ }, "RigidConstraint": { "Name": "RigidConstraint", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "Constraint", "Properties": { "Broken": { "Name": "Broken", - "Scriptability": "ReadWrite", + "Scriptability": "Read", "DataType": { "Value": "Bool" }, "Tags": [ - "NotBrowsable" + "NotBrowsable", + "NotReplicated", + "ReadOnly" ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -27413,12 +28688,9 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, - "Broken": { - "Bool": false - }, "Color": { "Int32": 194 }, @@ -27469,7 +28741,9 @@ }, "RocketPropulsion": { "Name": "RocketPropulsion", - "Tags": [], + "Tags": [ + "Deprecated" + ], "Superclass": "BodyMover", "Properties": { "CartoonFactor": { @@ -27617,7 +28891,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CartoonFactor": { @@ -27754,7 +29028,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -27916,7 +29190,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -27962,11 +29236,13 @@ }, "Rotate": { "Name": "Rotate", - "Tags": [], + "Tags": [ + "Deprecated" + ], "Superclass": "JointInstance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "C0": { @@ -28034,11 +29310,13 @@ }, "RotateP": { "Name": "RotateP", - "Tags": [], + "Tags": [ + "Deprecated" + ], "Superclass": "DynamicRotate", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BaseAngle": { @@ -28109,11 +29387,13 @@ }, "RotateV": { "Name": "RotateV", - "Tags": [], + "Tags": [ + "Deprecated" + ], "Superclass": "DynamicRotate", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BaseAngle": { @@ -28205,7 +29485,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -28216,6 +29496,17 @@ } } }, + "RtMessagingService": { + "Name": "RtMessagingService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "RunService": { "Name": "RunService", "Tags": [ @@ -28330,7 +29621,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoLocalize": { @@ -28348,6 +29639,21 @@ "ResetOnSpawn": { "Bool": true }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -28379,7 +29685,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Disabled": { @@ -28410,6 +29716,28 @@ "Properties": {}, "DefaultProperties": {} }, + "ScriptCloneWatcher": { + "Name": "ScriptCloneWatcher", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "ScriptCloneWatcherHelper": { + "Name": "ScriptCloneWatcherHelper", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ScriptContext": { "Name": "ScriptContext", "Tags": [ @@ -28511,6 +29839,27 @@ }, "DefaultProperties": {} }, + "ScriptDocument": { + "Name": "ScriptDocument", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "ScriptEditorService": { + "Name": "ScriptEditorService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ScriptRegistrationService": { "Name": "ScriptRegistrationService", "Tags": [ @@ -28531,7 +29880,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -28852,7 +30201,7 @@ 0.0 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoLocalize": { @@ -28963,6 +30312,24 @@ "Selectable": { "Bool": true }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": true + }, + "SelectionOrder": { + "Int32": 0 + }, "Size": { "UDim2": [ [ @@ -29040,7 +30407,7 @@ "Anchored": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -29291,7 +30658,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -29365,7 +30732,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color3": { @@ -29447,7 +30814,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color3": { @@ -29493,7 +30860,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color3": { @@ -29574,7 +30941,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color3": { @@ -29645,7 +31012,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "LoadStringEnabled": { @@ -29669,7 +31036,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -29720,7 +31087,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color3": { @@ -29774,7 +31141,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color3": { @@ -29834,7 +31201,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -29928,7 +31295,7 @@ "Anchored": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -30164,7 +31531,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SkinColor": { @@ -30341,7 +31708,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CelestialBodiesShown": { @@ -30665,6 +32032,19 @@ } } }, + "TimeScale": { + "Name": "TimeScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "opacity_xml": { "Name": "opacity_xml", "Scriptability": "None", @@ -30706,7 +32086,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -30733,16 +32113,21 @@ }, "Tags": { "BinaryString": "" + }, + "TimeScale": { + "Float32": 1.0 } } }, "Snap": { "Name": "Snap", - "Tags": [], + "Tags": [ + "Deprecated" + ], "Superclass": "JointInstance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "C0": { @@ -30808,6 +32193,17 @@ } } }, + "SnippetService": { + "Name": "SnippetService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "SocialService": { "Name": "SocialService", "Tags": [ @@ -31134,6 +32530,22 @@ } } }, + "UsageContextPermission": { + "Name": "UsageContextPermission", + "Scriptability": "None", + "DataType": { + "Enum": "UsageContext" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Volume": { "Name": "Volume", "Scriptability": "ReadWrite", @@ -31179,7 +32591,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "EmitterSize": { @@ -31276,7 +32688,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -31368,7 +32780,7 @@ "AmbientReverb": { "Enum": 0 }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "DistanceFactor": { @@ -31437,10 +32849,23 @@ "Serialization": "Serializes" } } + }, + "TimeScale": { + "Name": "TimeScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Enabled": { @@ -31458,6 +32883,9 @@ }, "Tags": { "BinaryString": "" + }, + "TimeScale": { + "Float32": 1.0 } } }, @@ -31539,7 +32967,7 @@ "Anchored": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -31890,7 +33318,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "RollOffMode": { @@ -31927,7 +33355,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "MeshId": { @@ -31994,7 +33422,7 @@ "AlwaysOnTop": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CFrame": { @@ -32106,7 +33534,7 @@ "Angle": { "Float32": 90.0 }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Brightness": { @@ -32292,7 +33720,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Coils": { @@ -32512,7 +33940,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -32541,7 +33969,7 @@ "Superclass": "StarterPlayerScripts", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -32558,7 +33986,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -32651,7 +34079,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "ResetPlayerGuiOnSpawn": { @@ -32683,7 +34111,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -33257,7 +34685,7 @@ "AllowCustomAnimations": { "Bool": true }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoJumpEnabled": { @@ -33399,7 +34827,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -33649,7 +35077,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -34550,6 +35978,19 @@ } } }, + "Main Volume": { + "Name": "Main Volume", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Matching Word Background Color": { "Name": "Matching Word Background Color", "Scriptability": "ReadWrite", @@ -34664,19 +36105,6 @@ } } }, - "OverrideCoreScripts": { - "Name": "OverrideCoreScripts", - "Scriptability": "Read", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "PermissionLevelShown": { "Name": "PermissionLevelShown", "Scriptability": "ReadWrite", @@ -35171,8 +36599,8 @@ } } }, - "Show Navigation Areas": { - "Name": "Show Navigation Areas", + "Show Navigation Labels": { + "Name": "Show Navigation Labels", "Scriptability": "None", "DataType": { "Value": "Bool" @@ -35197,6 +36625,19 @@ } } }, + "Show Pathfinding Links": { + "Name": "Show Pathfinding Links", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Show Plugin GUI Service in Explorer": { "Name": "Show Plugin GUI Service in Explorer", "Scriptability": "ReadWrite", @@ -35362,6 +36803,19 @@ } } }, + "Use Bounding Box Move Handles": { + "Name": "Use Bounding Box Move Handles", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Warning Color": { "Name": "Warning Color", "Scriptability": "ReadWrite", @@ -35429,21 +36883,6 @@ } } }, - "EnableTeamCreateStreamingOnLoad": { - "Name": "EnableTeamCreateStreamingOnLoad", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "SrcPlaceId": { "Name": "SrcPlaceId", "Scriptability": "None", @@ -35478,15 +36917,12 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "EnableScriptCollabByDefaultOnLoad": { "Bool": false }, - "EnableTeamCreateStreamingOnLoad": { - "Bool": false - }, "SourceAssetId": { "Int64": -1 }, @@ -35512,6 +36948,28 @@ "Properties": {}, "DefaultProperties": {} }, + "StudioHighDpiService": { + "Name": "StudioHighDpiService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "StudioPublishService": { + "Name": "StudioPublishService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "StudioScriptDebugEventListener": { "Name": "StudioScriptDebugEventListener", "Tags": [ @@ -35788,7 +37246,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Enabled": { @@ -35815,7 +37273,7 @@ "Properties": { "AlphaMode": { "Name": "AlphaMode", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Enum": "AlphaMode" }, @@ -35828,7 +37286,7 @@ }, "ColorMap": { "Name": "ColorMap", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Content" }, @@ -35841,7 +37299,7 @@ }, "MetalnessMap": { "Name": "MetalnessMap", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Content" }, @@ -35854,7 +37312,7 @@ }, "NormalMap": { "Name": "NormalMap", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Content" }, @@ -35867,7 +37325,7 @@ }, "RoughnessMap": { "Name": "RoughnessMap", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Content" }, @@ -35884,9 +37342,7 @@ "DataType": { "Value": "Content" }, - "Tags": [ - "Hidden" - ], + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -35898,7 +37354,7 @@ "AlphaMode": { "Enum": 0 }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "ColorMap": { @@ -36093,7 +37549,7 @@ "AlwaysOnTop": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoLocalize": { @@ -36126,6 +37582,21 @@ "ResetOnSpawn": { "Bool": true }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, "SizingMode": { "Enum": 0 }, @@ -36195,7 +37666,7 @@ "Angle": { "Float32": 90.0 }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Brightness": { @@ -36248,7 +37719,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color3": { @@ -36427,7 +37898,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoAssignable": { @@ -36453,7 +37924,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -36552,7 +38023,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "ReservedServerAccessCode": { @@ -36598,7 +38069,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -36787,7 +38258,7 @@ "Anchored": { "Bool": true }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -37011,6 +38482,138 @@ } } }, + "TerrainDetail": { + "Name": "TerrainDetail", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "ColorMap": { + "Name": "ColorMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Face": { + "Name": "Face", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TerrainFace" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaterialPattern": { + "Name": "MaterialPattern", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "MaterialPattern" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MetalnessMap": { + "Name": "MetalnessMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NormalMap": { + "Name": "NormalMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RoughnessMap": { + "Name": "RoughnessMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StudsPerTile": { + "Name": "StudsPerTile", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "ColorMap": { + "Content": "" + }, + "Face": { + "Enum": 1 + }, + "MaterialPattern": { + "Enum": 0 + }, + "MetalnessMap": { + "Content": "" + }, + "NormalMap": { + "Content": "" + }, + "RoughnessMap": { + "Content": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "StudsPerTile": { + "Float32": 10.0 + }, + "Tags": { + "BinaryString": "" + } + } + }, "TerrainRegion": { "Name": "TerrainRegion", "Tags": [], @@ -37051,7 +38654,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -37236,7 +38839,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoRuns": { @@ -37766,7 +39369,7 @@ 0.0 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoLocalize": { @@ -37853,6 +39456,24 @@ "Selectable": { "Bool": true }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, + "SelectionOrder": { + "Int32": 0 + }, "ShowNativeInput": { "Bool": true }, @@ -37929,6 +39550,16 @@ } } }, + "TextBoxService": { + "Name": "TextBoxService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "TextButton": { "Name": "TextButton", "Tags": [], @@ -38254,7 +39885,7 @@ 0.0 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoButtonColor": { @@ -38334,6 +39965,24 @@ "Selected": { "Bool": false }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, + "SelectionOrder": { + "Int32": 0 + }, "Size": { "UDim2": [ [ @@ -38409,11 +40058,236 @@ }, "TextChannel": { "Name": "TextChannel", - "Tags": [], + "Tags": [ + "NotBrowsable" + ], "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, + "TextChatCommand": { + "Name": "TextChatCommand", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PrimaryAlias": { + "Name": "PrimaryAlias", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SecondaryAlias": { + "Name": "SecondaryAlias", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "Enabled": { + "Bool": true + }, + "PrimaryAlias": { + "String": "" + }, + "SecondaryAlias": { + "String": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, + "TextChatConfigurations": { + "Name": "TextChatConfigurations", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "TextChatMessage": { + "Name": "TextChatMessage", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "MessageId": { + "Name": "MessageId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Metadata": { + "Name": "Metadata", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PrefixText": { + "Name": "PrefixText", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Status": { + "Name": "Status", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextChatMessageStatus" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Text": { + "Name": "Text", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextChannel": { + "Name": "TextChannel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextSource": { + "Name": "TextSource", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "TextChatMessageProperties": { + "Name": "TextChatMessageProperties", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "PrefixText": { + "Name": "PrefixText", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Text": { + "Name": "Text", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -38427,16 +40301,65 @@ "TextChatService": { "Name": "TextChatService", "Tags": [ + "NotBrowsable", "NotCreatable", - "NotReplicated", "Service" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "ChatVersion": { + "Name": "ChatVersion", + "Scriptability": "Read", + "DataType": { + "Enum": "ChatVersion" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CreateDefaultCommands": { + "Name": "CreateDefaultCommands", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CreateDefaultTextChannels": { + "Name": "CreateDefaultTextChannels", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, + "ChatVersion": { + "Enum": 0 + }, + "CreateDefaultCommands": { + "Bool": true + }, + "CreateDefaultTextChannels": { + "Bool": true + }, "SourceAssetId": { "Int64": -1 }, @@ -38780,7 +40703,7 @@ 0.0 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoLocalize": { @@ -38851,6 +40774,24 @@ "Selectable": { "Bool": false }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, + "SelectionOrder": { + "Int32": 0 + }, "Size": { "UDim2": [ [ @@ -38935,6 +40876,7 @@ "TextSource": { "Name": "TextSource", "Tags": [ + "NotBrowsable", "NotCreatable" ], "Superclass": "Instance", @@ -39030,7 +40972,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color3": { @@ -39171,7 +41113,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -39338,7 +41280,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CanBeDropped": { @@ -39437,7 +41379,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -39610,7 +41552,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Coils": { @@ -39675,7 +41617,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -39707,6 +41649,15 @@ "Properties": {}, "DefaultProperties": {} }, + "TrackerStreamAnimation": { + "Name": "TrackerStreamAnimation", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Trail": { "Name": "Trail", "Tags": [], @@ -39922,7 +41873,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Brightness": { @@ -40093,7 +42044,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Depth": { @@ -40169,7 +42120,7 @@ "Anchored": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -40391,7 +42342,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -40438,7 +42389,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -40512,7 +42463,7 @@ "AspectType": { "Enum": 0 }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "DominantAxis": { @@ -40573,7 +42524,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CornerRadius": { @@ -40662,7 +42613,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -40814,7 +42765,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CellPadding": { @@ -40975,7 +42926,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "FillDirection": { @@ -41063,7 +43014,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "PaddingBottom": { @@ -41241,7 +43192,7 @@ "Animated": { "Bool": true }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Circular": { @@ -41311,7 +43262,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Scale": { @@ -41358,7 +43309,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "MaxSize": { @@ -41469,7 +43420,7 @@ "ApplyStrokeMode": { "Enum": 0 }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -41558,7 +43509,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "FillDirection": { @@ -41635,7 +43586,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "MaxTextSize": { @@ -41664,7 +43615,7 @@ "AssetId": { "Content": "" }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -41931,7 +43882,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -41972,7 +43923,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -42085,6 +44036,22 @@ } } }, + "DefaultCameraID": { + "Name": "DefaultCameraID", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Fullscreen": { "Name": "Fullscreen", "Scriptability": "None", @@ -42173,7 +44140,7 @@ }, "MasterVolume": { "Name": "MasterVolume", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Float32" }, @@ -42511,6 +44478,19 @@ "Serialization": "Serializes" } } + }, + "VignetteEnabled": { + "Name": "VignetteEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": {} @@ -42929,6 +44909,23 @@ ], "Superclass": "Instance", "Properties": { + "DidPointerHit": { + "Name": "DidPointerHit", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "GuiInputUserCFrame": { "Name": "GuiInputUserCFrame", "Scriptability": "ReadWrite", @@ -42942,6 +44939,23 @@ } } }, + "PointerHitCFrame": { + "Name": "PointerHitCFrame", + "Scriptability": "None", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "VRDeviceAvailable": { "Name": "VRDeviceAvailable", "Scriptability": "None", @@ -42994,7 +45008,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -43020,7 +45034,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -43051,7 +45065,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -43118,7 +45132,7 @@ "ApplyAtCenterOfMass": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "Color": { @@ -43154,7 +45168,7 @@ "Superclass": "Controller", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -43324,7 +45338,7 @@ "Anchored": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -43609,7 +45623,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "C0": { @@ -43710,6 +45724,59 @@ }, "DefaultProperties": {} }, + "VideoCaptureService": { + "Name": "VideoCaptureService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "Active": { + "Name": "Active", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CameraID": { + "Name": "CameraID", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "VideoFrame": { "Name": "VideoFrame", "Tags": [], @@ -43843,7 +45910,7 @@ 0.0 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoLocalize": { @@ -43908,6 +45975,24 @@ "Selectable": { "Bool": false }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, + "SelectionOrder": { + "Int32": 0 + }, "Size": { "UDim2": [ [ @@ -44049,7 +46134,7 @@ 0.0 ] }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "AutoLocalize": { @@ -44132,6 +46217,24 @@ "Selectable": { "Bool": false }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, + "SelectionOrder": { + "Int32": 0 + }, "Size": { "UDim2": [ [ @@ -44186,7 +46289,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -44208,6 +46311,16 @@ "Properties": {}, "DefaultProperties": {} }, + "VisibilityService": { + "Name": "VisibilityService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Visit": { "Name": "Visit", "Tags": [ @@ -44225,7 +46338,7 @@ "Superclass": "Instance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -44239,6 +46352,7 @@ "VoiceChatInternal": { "Name": "VoiceChatInternal", "Tags": [ + "NotBrowsable", "NotCreatable", "Service" ], @@ -44264,7 +46378,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -44278,16 +46392,62 @@ "VoiceChatService": { "Name": "VoiceChatService", "Tags": [ - "Deprecated", "NotCreatable", "Service" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "EnableDefaultVoice": { + "Name": "EnableDefaultVoice", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VoiceChatEnabledForPlaceOnRcc": { + "Name": "VoiceChatEnabledForPlaceOnRcc", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "VoiceChatEnabledForUniverseOnRcc": { + "Name": "VoiceChatEnabledForUniverseOnRcc", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, + "EnableDefaultVoice": { + "Bool": true + }, "SourceAssetId": { "Int64": -1 }, @@ -44321,7 +46481,17 @@ } } }, - "DefaultProperties": {} + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } }, "WedgePart": { "Name": "WedgePart", @@ -44332,7 +46502,7 @@ "Anchored": { "Bool": false }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "BackParamA": { @@ -44540,7 +46710,7 @@ "Superclass": "JointInstance", "Properties": {}, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "C0": { @@ -44704,7 +46874,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "SourceAssetId": { @@ -44852,6 +47022,19 @@ } } }, + "GlobalWind": { + "Name": "GlobalWind", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Gravity": { "Name": "Gravity", "Scriptability": "ReadWrite", @@ -44908,6 +47091,21 @@ } } }, + "PhysicsInertiaAndVolumeFix": { + "Name": "PhysicsInertiaAndVolumeFix", + "Scriptability": "None", + "DataType": { + "Enum": "PhysicsInertiaAndVolumeFix" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PhysicsSimulationRate": { "Name": "PhysicsSimulationRate", "Scriptability": "ReadWrite", @@ -44939,6 +47137,21 @@ } } }, + "ReplicateInstanceDestroySetting": { + "Name": "ReplicateInstanceDestroySetting", + "Scriptability": "None", + "DataType": { + "Enum": "ReplicateInstanceDestroySetting" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Retargeting": { "Name": "Retargeting", "Scriptability": "ReadWrite", @@ -45079,7 +47292,7 @@ "AnimationWeightedBlendFix": { "Enum": 0 }, - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "ClientAnimatorThrottling": { @@ -45097,6 +47310,13 @@ "FallenPartsDestroyHeight": { "Float32": -500.0 }, + "GlobalWind": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, "Gravity": { "Float32": 196.2 }, @@ -45112,9 +47332,15 @@ "MeshPartHeadsAndAccessories": { "Enum": 0 }, + "PhysicsInertiaAndVolumeFix": { + "Enum": 0 + }, "PhysicsSteppingMethod": { "Enum": 0 }, + "ReplicateInstanceDestroySetting": { + "Enum": 0 + }, "Retargeting": { "Enum": 0 }, @@ -45168,6 +47394,19 @@ "Tags": [], "Superclass": "BaseWrap", "Properties": { + "AutoSkin": { + "Name": "AutoSkin", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "WrapLayerAutoSkin" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "BindOffset": { "Name": "BindOffset", "Scriptability": "ReadWrite", @@ -45309,9 +47548,12 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, + "AutoSkin": { + "Enum": 0 + }, "BindOffset": { "CFrame": { "position": [ @@ -45370,6 +47612,9 @@ "Enabled": { "Bool": true }, + "HSRAssetId": { + "Content": "" + }, "ImportOrigin": { "CFrame": { "position": [ @@ -45494,7 +47739,7 @@ } }, "DefaultProperties": { - "AttributesSerialize": { + "Attributes": { "BinaryString": "" }, "CageMeshId": { @@ -45526,6 +47771,9 @@ ] } }, + "HSRAssetId": { + "Content": "" + }, "ImportOrigin": { "CFrame": { "position": [ @@ -45581,6 +47829,8 @@ "items": { "Back": 7, "DressSkirt": 17, + "Eyebrow": 18, + "Eyelash": 19, "Face": 3, "Front": 6, "Hair": 2, @@ -45679,6 +47929,9 @@ "name": "AnimationPriority", "items": { "Action": 2, + "Action2": 3, + "Action3": 4, + "Action4": 5, "Core": 1000, "Idle": 0, "Movement": 1 @@ -45765,6 +48018,8 @@ "EarAccessory": 57, "EmoteAnimation": 61, "EyeAccessory": 58, + "EyebrowAccessory": 76, + "EyelashAccessory": 77, "Face": 18, "FaceAccessory": 42, "FallAnimation": 50, @@ -45842,6 +48097,8 @@ "ClimbAnimation": 48, "DressSkirtAccessory": 72, "EmoteAnimation": 61, + "EyebrowAccessory": 76, + "EyelashAccessory": 77, "Face": 18, "FaceAccessory": 42, "FallAnimation": 50, @@ -45987,7 +48244,8 @@ "name": "BundleType", "items": { "Animations": 2, - "BodyParts": 1 + "BodyParts": 1, + "Shoes": 3 } }, "Button": { @@ -46155,6 +48413,13 @@ "ClassicAndBubble": 2 } }, + "ChatVersion": { + "name": "ChatVersion", + "items": { + "LegacyChatService": 0, + "TextChatService": 1 + } + }, "ClientAnimatorThrottlingMode": { "name": "ClientAnimatorThrottlingMode", "items": { @@ -46204,6 +48469,7 @@ "DisconnectBlockedIP": 282, "DisconnectBySecurityPolicy": 281, "DisconnectClientFailure": 284, + "DisconnectClientRequest": 285, "DisconnectCloudEditKick": 270, "DisconnectConnectionLost": 277, "DisconnectDevMaintenance": 274, @@ -46215,8 +48481,11 @@ "DisconnectIdle": 278, "DisconnectIllegalTeleport": 263, "DisconnectLuaKick": 267, + "DisconnectModeratedGame": 287, "DisconnectNewSecurityKeyMismatch": 272, "DisconnectOnRemoteSysStats": 268, + "DisconnectOutOfMemory": 286, + "DisconnectOutOfMemoryExitContinue": 288, "DisconnectPlayerless": 271, "DisconnectProtocolMismatch": 259, "DisconnectRaknetErrors": 279, @@ -46350,6 +48619,14 @@ "Timeout": 1 } }, + "DebuggerExceptionBreakMode": { + "name": "DebuggerExceptionBreakMode", + "items": { + "Always": 2, + "Never": 0, + "Unhandled": 1 + } + }, "DebuggerFrameType": { "name": "DebuggerFrameType", "items": { @@ -46371,6 +48648,7 @@ "DebuggerStatus": { "name": "DebuggerStatus", "items": { + "ConnectionClosed": 8, "ConnectionLost": 2, "InternalError": 4, "InvalidArgument": 7, @@ -46431,28 +48709,29 @@ "DeveloperMemoryTag": { "name": "DeveloperMemoryTag", "items": { - "Animation": 21, - "GraphicsMeshParts": 9, - "GraphicsParticles": 10, - "GraphicsParts": 11, + "Animation": 22, + "GeometryCSG": 24, + "GraphicsMeshParts": 10, + "GraphicsParticles": 11, + "GraphicsParts": 12, "GraphicsSolidModels": 8, - "GraphicsSpatialHash": 12, - "GraphicsTerrain": 13, - "GraphicsTexture": 14, - "GraphicsTextureCharacter": 15, - "Gui": 20, + "GraphicsSpatialHash": 13, + "GraphicsTerrain": 14, + "GraphicsTexture": 15, + "GraphicsTextureCharacter": 16, + "Gui": 21, "HttpCache": 1, "Instances": 2, "Internal": 0, "LuaHeap": 4, - "Navigation": 22, + "Navigation": 23, "PhysicsCollision": 6, "PhysicsParts": 7, "Script": 5, "Signals": 3, - "Sounds": 16, - "StreamingSounds": 17, - "TerrainVoxels": 18 + "Sounds": 17, + "StreamingSounds": 18, + "TerrainVoxels": 19 } }, "DeviceType": { @@ -46611,7 +48890,7 @@ "Gotham": 17, "GothamBlack": 20, "GothamBold": 19, - "GothamSemibold": 18, + "GothamMedium": 18, "GrenzeGotisch": 27, "Highway": 11, "IndieFlower": 28, @@ -46638,7 +48917,8 @@ "SourceSansSemibold": 16, "SpecialElite": 43, "TitilliumWeb": 44, - "Ubuntu": 45 + "Ubuntu": 45, + "Unknown": 100 } }, "FontSize": { @@ -46661,6 +48941,27 @@ "Size96": 14 } }, + "FontStyle": { + "name": "FontStyle", + "items": { + "Italic": 1, + "Normal": 0 + } + }, + "FontWeight": { + "name": "FontWeight", + "items": { + "Bold": 700, + "ExtraBold": 800, + "ExtraLight": 200, + "Heavy": 900, + "Light": 300, + "Medium": 500, + "Regular": 400, + "SemiBold": 600, + "Thin": 100 + } + }, "FormFactor": { "name": "FormFactor", "items": { @@ -46787,7 +49088,7 @@ "name": "HighlightDepthMode", "items": { "AlwaysOnTop": 0, - "Default": 1 + "Occluded": 1 } }, "HorizontalAlignment": { @@ -47265,6 +49566,38 @@ "Include": 0 } }, + "LSPMethodType": { + "name": "LSPMethodType", + "items": { + "CancelRequest": 3, + "Completion": 15, + "Declaration": 16, + "DocumentSymbols": 17, + "Initialize": 1, + "Initialized": 2, + "Roblox_findColor3": 27, + "Roblox_findExecutablePosition": 26, + "Roblox_patchSnippetData": 28, + "Roblox_registerSyntaxCategories": 22, + "Roblox_signalQuiescence": 23, + "Roblox_suggestExtraSelections": 25, + "Roblox_syntaxHighlight": 24, + "ShutdownRequest": 14, + "TextDocument_didChange": 5, + "TextDocument_didClose": 6, + "TextDocument_didOpen": 4, + "TextDocument_foldingRange": 7, + "TextDocument_formatting": 9, + "TextDocument_hover": 11, + "TextDocument_onTypeFormatting": 8, + "TextDocument_publishDiagnostics": 19, + "TextDocument_rangeFormatting": 10, + "TextDocument_signatureHelp": 12, + "Window_showMessage": 20, + "Window_showMessageRequest": 21, + "Workspace_DidChangeConfiguration": 13 + } + }, "Language": { "name": "Language", "items": { @@ -47373,6 +49706,13 @@ "WoodPlanks": 528 } }, + "MaterialPattern": { + "name": "MaterialPattern", + "items": { + "Organic": 1, + "Regular": 0 + } + }, "MembershipType": { "name": "MembershipType", "items": { @@ -47549,15 +49889,6 @@ "UseView": 3 } }, - "PacketPriority": { - "name": "PacketPriority", - "items": { - "HIGH_PRIORITY": 1, - "IMMEDIATE_PRIORITY": 0, - "LOW_PRIORITY": 3, - "MEDIUM_PRIORITY": 2 - } - }, "PartType": { "name": "PartType", "items": { @@ -47590,6 +49921,24 @@ "Volume": 0 } }, + "ParticleFlipbookLayout": { + "name": "ParticleFlipbookLayout", + "items": { + "EightByEight": 3, + "FourByFour": 2, + "None": 0, + "TwoByTwo": 1 + } + }, + "ParticleFlipbookMode": { + "name": "ParticleFlipbookMode", + "items": { + "Loop": 0, + "OneShot": 1, + "PingPong": 2, + "Random": 3 + } + }, "ParticleOrientation": { "name": "ParticleOrientation", "items": { @@ -47613,6 +49962,7 @@ "PathWaypointAction": { "name": "PathWaypointAction", "items": { + "Custom": 2, "Jump": 1, "Walk": 0 } @@ -47627,6 +49977,14 @@ "Studio": 3 } }, + "PhysicsInertiaAndVolumeFix": { + "name": "PhysicsInertiaAndVolumeFix", + "items": { + "Default": 0, + "Disabled": 1, + "Enabled": 2 + } + }, "PhysicsSimulationRate": { "name": "PhysicsSimulationRate", "items": { @@ -47747,6 +50105,14 @@ "PurchaseGranted": 1 } }, + "PropertyStatus": { + "name": "PropertyStatus", + "items": { + "Error": 2, + "Ok": 0, + "Warning": 1 + } + }, "ProximityPromptExclusivity": { "name": "ProximityPromptExclusivity", "items": { @@ -47836,6 +50202,14 @@ "psnr": 0 } }, + "ReplicateInstanceDestroySetting": { + "name": "ReplicateInstanceDestroySetting", + "items": { + "Default": 0, + "Disabled": 1, + "Enabled": 2 + } + }, "ResamplerMode": { "name": "ResamplerMode", "items": { @@ -48003,6 +50377,13 @@ "Y": 2 } }, + "SelectionBehavior": { + "name": "SelectionBehavior", + "items": { + "Escape": 0, + "Stop": 1 + } + }, "ServerAudioBehavior": { "name": "ServerAudioBehavior", "items": { @@ -48014,6 +50395,7 @@ "SignalBehavior": { "name": "SignalBehavior", "items": { + "AncestryDeferred": 3, "Default": 0, "Deferred": 2, "Immediate": 1 @@ -48042,26 +50424,6 @@ "Name": 0 } }, - "SoundType": { - "name": "SoundType", - "items": { - "Boing": 1, - "Bomb": 2, - "Break": 3, - "Click": 4, - "Clock": 5, - "NoSound": 0, - "Page": 7, - "Ping": 8, - "Slingshot": 6, - "Snap": 9, - "Splat": 10, - "Step": 11, - "StepOn": 12, - "Swoosh": 13, - "Victory": 14 - } - }, "SpecialKey": { "name": "SpecialKey", "items": { @@ -48117,11 +50479,10 @@ "name": "StudioDataModelType", "items": { "Edit": 0, - "None": 5, + "None": 4, "PlayClient": 1, "PlayServer": 2, - "RobloxPlugin": 3, - "UserPlugin": 4 + "Standalone": 3 } }, "StudioScriptEditorColorCategories": { @@ -48180,53 +50541,54 @@ "StudioStyleGuideColor": { "name": "StudioStyleGuideColor", "items": { - "AttributeCog": 116, + "AttributeCog": 117, "Border": 31, - "BrightText": 39, + "BrightText": 40, "Button": 17, - "ButtonBorder": 88, - "ButtonText": 89, + "ButtonBorder": 89, + "ButtonText": 90, "CategoryItem": 24, - "ChatIncomingBgColor": 82, - "ChatIncomingTextColor": 83, - "ChatModeratedMessageColor": 86, - "ChatOutgoingBgColor": 84, - "ChatOutgoingTextColor": 85, - "CheckedFieldBackground": 91, - "CheckedFieldBorder": 92, - "CheckedFieldIndicator": 93, + "ChatIncomingBgColor": 83, + "ChatIncomingTextColor": 84, + "ChatModeratedMessageColor": 87, + "ChatOutgoingBgColor": 85, + "ChatOutgoingTextColor": 86, + "CheckedFieldBackground": 92, + "CheckedFieldBorder": 93, + "CheckedFieldIndicator": 94, "ColorPickerFrame": 29, "CurrentMarker": 30, - "Dark": 34, - "DebuggerCurrentLine": 64, - "DebuggerErrorLine": 65, - "DialogButton": 97, - "DialogButtonBorder": 99, - "DialogButtonText": 98, - "DialogMainButton": 100, - "DialogMainButtonText": 101, - "DiffFilePathBackground": 80, - "DiffFilePathBorder": 81, - "DiffFilePathText": 66, - "DiffLineNum": 75, - "DiffLineNumAdditionBackground": 78, - "DiffLineNumDeletionBackground": 79, - "DiffLineNumNoChangeBackground": 77, - "DiffLineNumSeparatorBackground": 76, - "DiffTextAddition": 69, - "DiffTextAdditionBackground": 73, - "DiffTextDeletion": 70, - "DiffTextDeletionBackground": 74, - "DiffTextHunkInfo": 67, - "DiffTextNoChange": 68, - "DiffTextNoChangeBackground": 72, - "DiffTextSeparatorBackground": 71, - "DimmedText": 40, - "DocViewCodeBackground": 63, + "Dark": 35, + "DebuggerCurrentLine": 65, + "DebuggerErrorLine": 66, + "DialogButton": 98, + "DialogButtonBorder": 100, + "DialogButtonText": 99, + "DialogMainButton": 101, + "DialogMainButtonText": 102, + "DiffFilePathBackground": 81, + "DiffFilePathBorder": 82, + "DiffFilePathText": 67, + "DiffLineNum": 76, + "DiffLineNumAdditionBackground": 79, + "DiffLineNumDeletionBackground": 80, + "DiffLineNumNoChangeBackground": 78, + "DiffLineNumSeparatorBackground": 77, + "DiffTextAddition": 70, + "DiffTextAdditionBackground": 74, + "DiffTextDeletion": 71, + "DiffTextDeletionBackground": 75, + "DiffTextHunkInfo": 68, + "DiffTextNoChange": 69, + "DiffTextNoChangeBackground": 73, + "DiffTextSeparatorBackground": 72, + "DimmedText": 41, + "DocViewCodeBackground": 64, + "DropShadow": 32, "Dropdown": 2, "EmulatorBar": 27, "EmulatorDropDown": 28, - "ErrorText": 43, + "ErrorText": 44, "FilterButtonAccent": 12, "FilterButtonBorder": 13, "FilterButtonBorderAlt": 14, @@ -48235,68 +50597,68 @@ "FilterButtonHover": 10, "GameSettingsTableItem": 25, "GameSettingsTooltip": 26, - "HeaderSection": 94, - "InfoBarWarningBackground": 102, - "InfoBarWarningText": 103, - "InfoText": 44, + "HeaderSection": 95, + "InfoBarWarningBackground": 103, + "InfoBarWarningText": 104, + "InfoText": 45, "InputFieldBackground": 21, - "InputFieldBorder": 90, + "InputFieldBorder": 91, "Item": 22, - "Light": 33, - "LinkText": 41, + "Light": 34, + "LinkText": 42, "MainBackground": 0, "MainButton": 18, - "MainText": 36, - "Mid": 35, - "Midlight": 95, + "MainText": 37, + "Mid": 36, + "Midlight": 96, "Notification": 4, "RibbonButton": 19, "RibbonTab": 15, "RibbonTabTopBar": 16, - "ScriptBackground": 47, - "ScriptBool": 108, - "ScriptBracket": 115, - "ScriptBuiltInFunction": 58, - "ScriptComment": 56, - "ScriptEditorCurrentLine": 104, - "ScriptError": 60, - "ScriptFindSelectionBackground": 51, - "ScriptFunction": 109, - "ScriptFunctionName": 113, - "ScriptKeyword": 57, - "ScriptLocal": 110, - "ScriptLuauKeyword": 112, - "ScriptMatchingWordSelectionBackground": 52, - "ScriptMethod": 105, - "ScriptNil": 107, - "ScriptNumber": 54, - "ScriptOperator": 53, - "ScriptProperty": 106, - "ScriptRuler": 62, - "ScriptSelectionBackground": 50, - "ScriptSelectionText": 49, - "ScriptSelf": 111, - "ScriptSideWidget": 46, - "ScriptString": 55, - "ScriptText": 48, - "ScriptTodo": 114, - "ScriptWarning": 59, - "ScriptWhitespace": 61, + "ScriptBackground": 48, + "ScriptBool": 109, + "ScriptBracket": 116, + "ScriptBuiltInFunction": 59, + "ScriptComment": 57, + "ScriptEditorCurrentLine": 105, + "ScriptError": 61, + "ScriptFindSelectionBackground": 52, + "ScriptFunction": 110, + "ScriptFunctionName": 114, + "ScriptKeyword": 58, + "ScriptLocal": 111, + "ScriptLuauKeyword": 113, + "ScriptMatchingWordSelectionBackground": 53, + "ScriptMethod": 106, + "ScriptNil": 108, + "ScriptNumber": 55, + "ScriptOperator": 54, + "ScriptProperty": 107, + "ScriptRuler": 63, + "ScriptSelectionBackground": 51, + "ScriptSelectionText": 50, + "ScriptSelf": 112, + "ScriptSideWidget": 47, + "ScriptString": 56, + "ScriptText": 49, + "ScriptTodo": 115, + "ScriptWarning": 60, + "ScriptWhitespace": 62, "ScrollBar": 5, "ScrollBarBackground": 6, - "SensitiveText": 45, - "Separator": 87, - "Shadow": 32, - "StatusBar": 96, - "SubText": 37, + "SensitiveText": 46, + "Separator": 88, + "Shadow": 33, + "StatusBar": 97, + "SubText": 38, "Tab": 8, "TabBar": 7, "TableItem": 23, "Titlebar": 1, - "TitlebarText": 38, + "TitlebarText": 39, "Tooltip": 3, "ViewPortBackground": 20, - "WarningText": 42 + "WarningText": 43 } }, "StudioStyleGuideModifier": { @@ -48433,14 +50795,25 @@ "Template": 2 } }, + "TerrainFace": { + "name": "TerrainFace", + "items": { + "Bottom": 2, + "Side": 1, + "Top": 0 + } + }, "TextChatMessageStatus": { "name": "TextChatMessageStatus", "items": { - "Floodchecked": 3, - "InvalidPrivacySettings": 4, - "InvalidTextChannelPermissions": 5, - "Success": 1, - "TextFilterFailed": 2 + "Floodchecked": 5, + "InvalidPrivacySettings": 6, + "InvalidTextChannelPermissions": 7, + "MessageTooLong": 8, + "Sending": 3, + "Success": 2, + "TextFilterFailed": 4, + "Unknown": 1 } }, "TextFilterContext": { @@ -48613,6 +50986,13 @@ "UiMessageInfo": 1 } }, + "UsageContext": { + "name": "UsageContext", + "items": { + "Default": 0, + "Preview": 1 + } + }, "UserCFrame": { "name": "UserCFrame", "items": { @@ -48755,22 +51135,36 @@ "Strong": 3 } }, + "WrapLayerAutoSkin": { + "name": "WrapLayerAutoSkin", + "items": { + "Disabled": 0, + "EnabledOverride": 2, + "EnabledPreserve": 1 + } + }, "WrapLayerDebugMode": { "name": "WrapLayerDebugMode", "items": { "BoundCage": 1, "BoundCageAndLinks": 3, + "HSRInner": 10, + "HSRInnerReverse": 11, + "HSROuter": 9, + "HSROuterDetail": 8, "LayerCage": 2, "None": 0, "OuterCage": 6, "Rbf": 5, - "Reference": 4 + "Reference": 4, + "ReferenceMeshAfterMorph": 7 } }, "WrapTargetDebugMode": { "name": "WrapTargetDebugMode", "items": { "None": 0, + "OuterCageDetail": 8, "Rbf": 7, "TargetCageCompressed": 2, "TargetCageInterface": 3, diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__attributes.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__attributes.snap new file mode 100644 index 00000000..d78f8101 --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__attributes.snap @@ -0,0 +1,24 @@ +--- +source: tests/tests/build.rs +assertion_line: 99 +expression: contents +--- + + + + attributes + + + + Explicit + AgAAAAUAAABIZWxsbwIFAAAAV29ybGQGAAAAVmVjdG9yEQAAgD8AAABAAABAQA== + + + + + ImplicitAttributes + AgAAAAMAAABIZXkCBwAAAEdyYW5kbWEGAAAAVmVjdG9yEQAAgEAAAKBAAADAQA== + + + + diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__weldconstraint.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__weldconstraint.snap index e3b95447..37819274 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__weldconstraint.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__weldconstraint.snap @@ -1,6 +1,6 @@ --- source: tests/tests/build.rs -assertion_line: 98 +assertion_line: 99 expression: contents --- diff --git a/rojo-test/build-tests/attributes/default.project.json b/rojo-test/build-tests/attributes/default.project.json new file mode 100644 index 00000000..44be8f16 --- /dev/null +++ b/rojo-test/build-tests/attributes/default.project.json @@ -0,0 +1,36 @@ +{ + "name": "attributes", + "tree": { + "$className": "Folder", + + "Explicit": { + "$className": "Folder", + "$properties": { + "Attributes": { + "Attributes": { + "Hello": { + "String": "World" + }, + "Vector": { + "Vector3": [1, 2, 3] + } + } + } + } + }, + + "ImplicitAttributes": { + "$className": "Folder", + "$properties": { + "Attributes": { + "Hey": { + "String": "Grandma" + }, + "Vector": { + "Vector3": [4, 5, 6] + } + } + } + } + } +} \ No newline at end of file diff --git a/src/resolution.rs b/src/resolution.rs index 8f25d992..547e1729 100644 --- a/src/resolution.rs +++ b/src/resolution.rs @@ -2,7 +2,8 @@ use std::borrow::Borrow; use anyhow::format_err; use rbx_dom_weak::types::{ - CFrame, Color3, Content, Enum, Matrix3, Tags, Variant, VariantType, Vector2, Vector3, + Attributes, CFrame, Color3, Content, Enum, Matrix3, Tags, Variant, VariantType, Vector2, + Vector3, }; use rbx_reflection::{DataType, PropertyDescriptor}; use serde::{Deserialize, Serialize}; @@ -40,6 +41,7 @@ pub enum AmbiguousValue { Array3([f64; 3]), Array4([f64; 4]), Array12([f64; 12]), + Attributes(Attributes), } impl AmbiguousValue { @@ -128,6 +130,8 @@ impl AmbiguousValue { Ok(CFrame::new(pos, orientation).into()) } + (VariantType::Attributes, AmbiguousValue::Attributes(value)) => Ok(value.into()), + (_, unresolved) => Err(format_err!( "Wrong type of value for property {}.{}. Expected {:?}, got {}", class_name, @@ -154,6 +158,7 @@ impl AmbiguousValue { AmbiguousValue::Array3(_) => "an array of three numbers", AmbiguousValue::Array4(_) => "an array of four numbers", AmbiguousValue::Array12(_) => "an array of twelve numbers", + AmbiguousValue::Attributes(_) => "an object containing attributes", } } } diff --git a/test-projects/attributes/default.project.json b/test-projects/attributes/default.project.json new file mode 100644 index 00000000..78be72c2 --- /dev/null +++ b/test-projects/attributes/default.project.json @@ -0,0 +1,16 @@ +{ + "name": "attributes", + "tree": { + "$className": "DataModel", + "Workspace": { + "Folder": { + "$className": "Folder", + "$properties": { + "Attributes": { + "Hello": { "Vector3": [1, 2, 3] } + } + } + } + } + } +} \ No newline at end of file diff --git a/tests/tests/build.rs b/tests/tests/build.rs index fc917d04..1776fe7d 100644 --- a/tests/tests/build.rs +++ b/tests/tests/build.rs @@ -21,6 +21,7 @@ macro_rules! gen_build_tests { } gen_build_tests! { + attributes, client_in_folder, client_init, csv_bug_145, From 04fa5e2719375e789e6ef1984eece96c30a68d66 Mon Sep 17 00:00:00 2001 From: Watermelon <34957838+WatermelonArray@users.noreply.github.com> Date: Thu, 30 Jun 2022 00:04:28 +0100 Subject: [PATCH 1230/1504] Added address reference to CLI output (#556) * Added address reference to CLI output * Stored loopback check address as a variable * Changed other loopback references to the new variable * Fixed mistake on address_string variable * Merge write calls Co-authored-by: Lucien Greathouse --- src/cli/serve.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/cli/serve.rs b/src/cli/serve.rs index 9d2aa343..0e35785e 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -67,15 +67,17 @@ fn show_start_message(bind_address: IpAddr, port: u16, color: ColorChoice) -> io let writer = BufferWriter::stdout(color); let mut buffer = writer.buffer(); + let address_string = if bind_address.is_loopback() { + "localhost".to_owned() + } else { + bind_address.to_string() + }; + writeln!(&mut buffer, "Rojo server listening:")?; write!(&mut buffer, " Address: ")?; buffer.set_color(&green)?; - if bind_address.is_loopback() { - writeln!(&mut buffer, "localhost")?; - } else { - writeln!(&mut buffer, "{}", bind_address)?; - } + writeln!(&mut buffer, "{}", address_string)?; buffer.set_color(&ColorSpec::new())?; write!(&mut buffer, " Port: ")?; @@ -88,7 +90,7 @@ fn show_start_message(bind_address: IpAddr, port: u16, color: ColorChoice) -> io write!(&mut buffer, "Visit ")?; buffer.set_color(&green)?; - write!(&mut buffer, "http://localhost:{}/", port)?; + write!(&mut buffer, "http://{}:{}/", address_string, port)?; buffer.set_color(&ColorSpec::new())?; writeln!(&mut buffer, " in your browser for more information.")?; From f1cdf2fe79fbabde73f5c106777861c5a23f6ef5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 29 Jun 2022 19:05:04 -0400 Subject: [PATCH 1231/1504] Update CHANGELOG --- CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 797d1ccc..141167d7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,22 @@ # Rojo Changelog ## Unreleased Changes +* Added support for `.luau` files. ([#552]) +* Added support for live syncing Attributes and Tags. ([#553]) * Switched from structopt to clap for command line argument parsing. * Significantly improved performance of building and serving. ([#548]) +* Increased minimum supported Rust version to 1.57.0. ([#564]) * Fixed `init.meta.json` when used with `init.lua` and related files. ([#549]) +* Fixed incorrect output when serving from a non-default address or port ([#556]) +* Fixed Linux binaries not running on systems with older glibc. ([#561]) [#548]: https://github.com/rojo-rbx/rojo/pull/548 [#549]: https://github.com/rojo-rbx/rojo/pull/549 +[#552]: https://github.com/rojo-rbx/rojo/pull/552 +[#553]: https://github.com/rojo-rbx/rojo/pull/553 +[#556]: https://github.com/rojo-rbx/rojo/pull/556 +[#561]: https://github.com/rojo-rbx/rojo/pull/561 +[#564]: https://github.com/rojo-rbx/rojo/pull/564 ## [7.1.1] - May 26, 2022 * Fixed sourcemap command not stripping paths correctly ([#544]) From ca0759a011a189fb87c2315df0bf17d892bc7c38 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 29 Jun 2022 16:06:13 -0700 Subject: [PATCH 1232/1504] Add notification popups (#540) * Add notifications prototype * Add timeout * Improve function name * Faster timeouts and fully clickable * Update remove padding from old X button * Only auto-dismiss when viewport is open * Start auto dismiss once viewed * Avoid redundantly displaying widget text as notifs * Add sound effect * Add setting for notifications * Remove duplicate PluginSettings.StudioProvider * Use short pop sound effect * Fix broken audio, thanks Roblox * Use e instead of createElement --- assets/NotificationPop.mp3 | Bin 0 -> 2481 bytes plugin/src/App/Notifications.lua | 198 ++++++++++++++++++++++++ plugin/src/App/PluginSettings.lua | 3 +- plugin/src/App/StatusPages/Settings.lua | 12 +- plugin/src/App/Theme.lua | 8 + plugin/src/App/init.lua | 51 +++++- plugin/src/Assets.lua | 5 +- plugin/src/init.server.lua | 4 +- plugin/src/playSound.lua | 22 +++ 9 files changed, 293 insertions(+), 10 deletions(-) create mode 100644 assets/NotificationPop.mp3 create mode 100644 plugin/src/App/Notifications.lua create mode 100644 plugin/src/playSound.lua diff --git a/assets/NotificationPop.mp3 b/assets/NotificationPop.mp3 new file mode 100644 index 0000000000000000000000000000000000000000..5ecc19755051029143af50bb8a62f96a44f163c9 GIT binary patch literal 2481 zcmeHI3saNF8r~2>fCNYYHQ`diZ9ob&1m#XixJv`15HKKAFo;Aj0SRrSSUw;SOaTQ! zAW#Lh<)%1R7>TG{0wNV!QV_%=78Mn&w$M`xF~HZ)PTM(Wj=!LDo|$Lf+sy8}&%U#} zGr$E6-ry59E6^FSID~OY+%!tW$2?&cdncQQB=iu53xvEB9ydwI6Y$v#rXP|rLKu|I z=O3no39^N$lyCtrYhM;SHZT$?U=Y%%G#Wb~(*Hk0|A=rT)I!JgPxCW?)wdpPbX@>=G)t699+jX3cJ1X8_MH-)1^nom4B@@J|KkK0E|2_QEj0=4Pq^ zaii1+hBrW|x3{+lQ9*;cw6y#a+)v6wRDGKFs|Y}Ev|)yy-*!1M9RMoZnyP86A)b3k zxM_6%hdNusqouZ^iQ{G&x`ruK?Icby6H*BoUE-$*2FdO0ke!$Jv)p+i zyPaYQndZQ~t5t4h|E^Ry$_W|x7Jn|_YQk@?WmE}GA`L2DQXK!}M*Whn2MA@aTB`mhLt1q{p z9lxj(z^k*q8_%@&AV)Gxi}f7{*rd+^Ts&zxC7zaxGj(d>;nyJ@g|0n^EWzkf>ASii zT#+Q-&Okr5smSDX$R6AJ?N+*lF&%C#&lRbG=fp4*^*v%oI3VM9VeMIkxrO)o#wo~RM6Io#DvP zqcn528xe6rS;E4`2Sd@r(zyGz_O#*heMDn!P1Sb>KTl5UU9~v}yZUYF<^-@>IQRn6_b~Nk zp3CHYw{`!kDt&L%^%536U@GxU_DKH&Mx`D0ml6d5|Cuo(V{3|z6Ek#+UO3sbo=6j& z-&>a}i&Cb9rOudqFEf(FzqVj_zIYxctOyi-RV<09zQgbgof>gUi##6u@h8cfU$@pb z&|AZ7%nu~w)Wh(4Uf?wHG|6g}e1Vk~fUsy*42IR|M*D~2zYxp75Azlytml zgSC~}PThdmUfdD=xq0k0Tf#gmWaPkxJ<7MZgIEF;TG?)u&e)t@Z3@2CPqsA2cXwmZ z2|1y#<)F6;WBJFt!9ah+%ePAm-W}@y($|BIvXZl*D)UXRd)IEHC%ETdIx5B99%gR7 z{?YY4@D7^iWp?R_?eMGJ(SQF>(f`Mv3c%{*!3Ahb*D-&Uyb2li?S&A~{0FP^JKln! AKL7v# literal 0 HcmV?d00001 diff --git a/plugin/src/App/Notifications.lua b/plugin/src/App/Notifications.lua new file mode 100644 index 00000000..7da591cc --- /dev/null +++ b/plugin/src/App/Notifications.lua @@ -0,0 +1,198 @@ +local TextService = game:GetService("TextService") +local StudioService = game:GetService("StudioService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) +local Flipper = require(Rojo.Flipper) + +local bindingUtil = require(script.Parent.bindingUtil) + +local Theme = require(Plugin.App.Theme) +local Assets = require(Plugin.Assets) +local playSound = require(Plugin.playSound) + +local BorderedContainer = require(Plugin.App.Components.BorderedContainer) + +local baseClock = DateTime.now().UnixTimestampMillis + +local e = Roact.createElement + +local Notification = Roact.Component:extend("Notification") + +function Notification:init() + self.motor = Flipper.SingleMotor.new(0) + self.binding = bindingUtil.fromMotor(self.motor) + + self.lifetime = self.props.timeout + + self.motor:onStep(function(value) + if value <= 0 then + if self.props.onClose then + self.props.onClose() + end + end + end) +end + +function Notification:dismiss() + self.motor:setGoal( + Flipper.Spring.new(0, { + frequency = 5, + dampingRatio = 1, + }) + ) +end + +function Notification:didMount() + self.motor:setGoal( + Flipper.Spring.new(1, { + frequency = 3, + dampingRatio = 1, + }) + ) + + playSound(Assets.Sounds.Notification) + + self.timeout = task.spawn(function() + local clock = os.clock() + local seen = false + while task.wait(1/10) do + local now = os.clock() + local dt = now - clock + clock = now + + if not seen then + seen = StudioService.ActiveScript == nil + end + + if not seen then + -- Don't run down timer before being viewed + continue + end + + self.lifetime -= dt + if self.lifetime <= 0 then + self:dismiss() + break + end + end + end) +end + +function Notification:willUnmount() + task.cancel(self.timeout) +end + +function Notification:render() + local time = DateTime.fromUnixTimestampMillis(self.props.timestamp) + + local textBounds = TextService:GetTextSize( + self.props.text, + 15, + Enum.Font.GothamSemibold, + Vector2.new(350, 700) + ) + + local transparency = self.binding:map(function(value) + return 1 - value + end) + + local size = self.binding:map(function(value) + return UDim2.fromOffset( + (35+40+textBounds.X)*value, + math.max(14+20+textBounds.Y, 32+20) + ) + end) + + return Theme.with(function(theme) + return e("TextButton", { + BackgroundTransparency = 1, + Size = size, + LayoutOrder = self.props.layoutOrder, + Text = "", + ClipsDescendants = true, + + [Roact.Event.Activated] = function() + self:dismiss() + end, + }, { + e(BorderedContainer, { + transparency = transparency, + size = UDim2.new(1, 0, 1, 0), + }, { + TextContainer = e("Frame", { + Size = UDim2.new(0, 35+textBounds.X, 1, -20), + Position = UDim2.new(0, 0, 0, 10), + BackgroundTransparency = 1 + }, { + Logo = e("ImageLabel", { + ImageTransparency = transparency, + Image = Assets.Images.PluginButton, + BackgroundTransparency = 1, + Size = UDim2.new(0, 32, 0, 32), + Position = UDim2.new(0, 0, 0.5, 0), + AnchorPoint = Vector2.new(0, 0.5), + }), + Info = e("TextLabel", { + Text = self.props.text, + Font = Enum.Font.GothamSemibold, + TextSize = 15, + TextColor3 = theme.Notification.InfoColor, + TextTransparency = transparency, + TextXAlignment = Enum.TextXAlignment.Left, + TextWrapped = true, + + Size = UDim2.new(0, textBounds.X, 0, textBounds.Y), + Position = UDim2.fromOffset(35, 0), + + LayoutOrder = 1, + BackgroundTransparency = 1, + }), + Time = e("TextLabel", { + Text = time:FormatLocalTime("LTS", "en-us"), + Font = Enum.Font.Code, + TextSize = 12, + TextColor3 = theme.Notification.InfoColor, + TextTransparency = transparency, + TextXAlignment = Enum.TextXAlignment.Left, + + Size = UDim2.new(1, -35, 0, 14), + Position = UDim2.new(0, 35, 1, -14), + + LayoutOrder = 1, + BackgroundTransparency = 1, + }), + }), + + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 17), + PaddingRight = UDim.new(0, 15), + }), + }) + }) + end) +end + +local Notifications = Roact.Component:extend("Notifications") + +function Notifications:render() + local notifs = {} + + for index, notif in ipairs(self.props.notifications) do + notifs[notif] = e(Notification, { + text = notif.text, + timestamp = notif.timestamp, + timeout = notif.timeout, + layoutOrder = (notif.timestamp - baseClock), + onClose = function() + self.props.onClose(index) + end, + }) + end + + return Roact.createFragment(notifs) +end + +return Notifications diff --git a/plugin/src/App/PluginSettings.lua b/plugin/src/App/PluginSettings.lua index 1c5b4e37..72a5e6c1 100644 --- a/plugin/src/App/PluginSettings.lua +++ b/plugin/src/App/PluginSettings.lua @@ -9,6 +9,7 @@ local Roact = require(Rojo.Roact) local defaultSettings = { openScriptsExternally = false, twoWaySync = false, + showNotifications = true, } local Settings = {} @@ -118,4 +119,4 @@ end return { StudioProvider = StudioProvider, with = with, -} \ No newline at end of file +} diff --git a/plugin/src/App/StatusPages/Settings.lua b/plugin/src/App/StatusPages/Settings.lua index f78efbff..54b1e252 100644 --- a/plugin/src/App/StatusPages/Settings.lua +++ b/plugin/src/App/StatusPages/Settings.lua @@ -202,12 +202,20 @@ function SettingsPage:render() layoutOrder = 1, }), + ShowNotifications = e(Setting, { + id = "showNotifications", + name = "Show Notifications", + description = "Popup notifications in viewport", + transparency = self.props.transparency, + layoutOrder = 2, + }), + TwoWaySync = e(Setting, { id = "twoWaySync", name = "Two-Way Sync", description = "EXPERIMENTAL! Editing files in Studio will sync them into the filesystem", transparency = self.props.transparency, - layoutOrder = 2, + layoutOrder = 3, }), Layout = e("UIListLayout", { @@ -227,4 +235,4 @@ function SettingsPage:render() end) end -return SettingsPage \ No newline at end of file +return SettingsPage diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index 32578d3e..d27a2ecb 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -103,6 +103,10 @@ local lightTheme = strict("LightTheme", { LogoColor = BRAND_COLOR, VersionColor = hexColor(0x727272), }, + Notification = { + InfoColor = hexColor(0x00000), + CloseColor = BRAND_COLOR, + }, ErrorColor = hexColor(0x000000), ScrollBarColor = hexColor(0x000000), }) @@ -177,6 +181,10 @@ local darkTheme = strict("DarkTheme", { LogoColor = BRAND_COLOR, VersionColor = hexColor(0xD3D3D3) }, + Notification = { + InfoColor = hexColor(0xFFFFFF), + CloseColor = hexColor(0xFFFFFF), + }, ErrorColor = hexColor(0xFFFFFF), ScrollBarColor = hexColor(0xFFFFFF), }) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index ed9b4443..1058954a 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -16,6 +16,7 @@ local Theme = require(script.Theme) local PluginSettings = require(script.PluginSettings) local Page = require(script.Page) +local Notifications = require(script.Notifications) local StudioPluginAction = require(script.Components.Studio.StudioPluginAction) local StudioToolbar = require(script.Components.Studio.StudioToolbar) local StudioToggleButton = require(script.Components.Studio.StudioToggleButton) @@ -44,10 +45,37 @@ function App:init() self:setState({ appStatus = AppStatus.NotConnected, guiEnabled = false, + notifications = {}, toolbarIcon = Assets.Images.PluginButton, }) end +function App:addNotification(text: string, timeout: number?) + if not self.props.settings:get("showNotifications") then + return + end + + local notifications = table.clone(self.state.notifications) + table.insert(notifications, { + text = text, + timestamp = DateTime.now().UnixTimestampMillis, + timeout = timeout or 3, + }) + + self:setState({ + notifications = notifications, + }) +end + +function App:closeNotification(index: number) + local notifications = table.clone(self.state.notifications) + table.remove(notifications, index) + + self:setState({ + notifications = notifications, + }) +end + function App:getHostAndPort() local host = self.host:getValue() local port = self.port:getValue() @@ -81,6 +109,7 @@ function App:startSession() appStatus = AppStatus.Connecting, toolbarIcon = Assets.Images.PluginButton, }) + self:addNotification("Connecting to session...") elseif status == ServeSession.Status.Connected then local address = ("%s:%s"):format(host, port) self:setState({ @@ -89,8 +118,7 @@ function App:startSession() address = address, toolbarIcon = Assets.Images.PluginButtonConnected, }) - - Log.info("Connected to session '{}' at {}", details, address) + self:addNotification(string.format("Connected to session '%s' at %s.", details, address), 5) elseif status == ServeSession.Status.Disconnected then self.serveSession = nil @@ -104,13 +132,13 @@ function App:startSession() errorMessage = tostring(details), toolbarIcon = Assets.Images.PluginButtonWarning, }) + self:addNotification(tostring(details), 10) else self:setState({ appStatus = AppStatus.NotConnected, toolbarIcon = Assets.Images.PluginButton, }) - - Log.info("Disconnected session") + self:addNotification("Disconnected from session.") end end end) @@ -236,6 +264,21 @@ function App:render() end), }), + RojoNotifications = e("ScreenGui", {}, { + layout = e("UIListLayout", { + SortOrder = Enum.SortOrder.LayoutOrder, + HorizontalAlignment = Enum.HorizontalAlignment.Right, + VerticalAlignment = Enum.VerticalAlignment.Bottom, + Padding = UDim.new(0, 5), + }), + notifs = e(Notifications, { + notifications = self.state.notifications, + onClose = function(index) + self:closeNotification(index) + end, + }), + }), + toggleAction = e(StudioPluginAction, { name = "RojoConnection", title = "Rojo: Connect/Disconnect", diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index 29e61d11..02fc2c7b 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -45,6 +45,9 @@ local Assets = { [500] = "rbxassetid://2609138523" }, }, + Sounds = { + Notification = "rbxassetid://9716079936", + }, StartSession = "", SessionActive = "", Configure = "", @@ -62,4 +65,4 @@ end guardForTypos("Assets", Assets) -return Assets \ No newline at end of file +return Assets diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index 79e2b51a..43c271c1 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -18,7 +18,7 @@ local App = require(script.App) local app = Roact.createElement(App, { plugin = plugin }) -local tree = Roact.mount(app, nil, "Rojo UI") +local tree = Roact.mount(app, game:GetService("CoreGui"), "Rojo UI") plugin.Unloading:Connect(function() Roact.unmount(tree) @@ -28,4 +28,4 @@ if Config.isDevBuild then local TestEZ = require(script.Parent.TestEZ) require(script.runTests)(TestEZ) -end \ No newline at end of file +end diff --git a/plugin/src/playSound.lua b/plugin/src/playSound.lua new file mode 100644 index 00000000..4e452313 --- /dev/null +++ b/plugin/src/playSound.lua @@ -0,0 +1,22 @@ +-- Roblox decided that sounds only play in Edit mode when parented to a plugin widget, for some reason +local plugin = plugin or script:FindFirstAncestorWhichIsA("Plugin") +local widget = plugin:CreateDockWidgetPluginGui("Rojo_soundPlayer", DockWidgetPluginGuiInfo.new( + Enum.InitialDockState.Float, + false, true, + 10, 10, + 10, 10 +)) +widget.Name = "Rojo_soundPlayer" +widget.Title = "Rojo Sound Player" + +return function(soundId) + local sound = Instance.new("Sound") + sound.SoundId = soundId + sound.Parent = widget + + sound.Ended:Connect(function() + sound:Destroy() + end) + + sound:Play() +end From 966478b1318005b95ce763f82ae04820d8b74722 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 29 Jun 2022 19:07:17 -0400 Subject: [PATCH 1233/1504] Update Changelog --- CHANGELOG.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 141167d7..ecc46bbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,13 +3,15 @@ ## Unreleased Changes * Added support for `.luau` files. ([#552]) * Added support for live syncing Attributes and Tags. ([#553]) -* Switched from structopt to clap for command line argument parsing. -* Significantly improved performance of building and serving. ([#548]) -* Increased minimum supported Rust version to 1.57.0. ([#564]) +* Added notification popups in the Roblox Studio plugin. ([#540]) * Fixed `init.meta.json` when used with `init.lua` and related files. ([#549]) * Fixed incorrect output when serving from a non-default address or port ([#556]) * Fixed Linux binaries not running on systems with older glibc. ([#561]) +* Switched from structopt to clap for command line argument parsing. +* Significantly improved performance of building and serving. ([#548]) +* Increased minimum supported Rust version to 1.57.0. ([#564]) +[#540]: https://github.com/rojo-rbx/rojo/pull/540 [#548]: https://github.com/rojo-rbx/rojo/pull/548 [#549]: https://github.com/rojo-rbx/rojo/pull/549 [#552]: https://github.com/rojo-rbx/rojo/pull/552 From f649c180cf68cce4aa917126ecdf35aede852716 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 29 Jun 2022 19:14:35 -0500 Subject: [PATCH 1234/1504] Disambiguate camelCase and PascalCase in *.meta.json and *.model.json (#563) * Disambiguate camelCase and PascalCase. *.meta.json forces camelCase while *.model.json forces PascalCase. This commit reinforces camelCase as the preference for both, but allows for PascalCase in both as well. * Made requested changes, breaking due to serde bug. * Make work with existing Serde stuff * Work around MSRV Co-authored-by: Lucien Greathouse --- Cargo.toml | 2 +- src/snapshot_middleware/json_model.rs | 102 +++++++++++++----- ...on_model__test__model_from_vfs_legacy.snap | 29 +++++ 3 files changed, 103 insertions(+), 30 deletions(-) create mode 100644 src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap diff --git a/Cargo.toml b/Cargo.toml index 25eedb6b..34bfe1e5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ homepage = "https://rojo.space" documentation = "https://rojo.space/docs" repository = "https://github.com/rojo-rbx/rojo" readme = "README.md" -edition = "2018" +edition = "2021" build = "build.rs" exclude = [ diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 52071031..c29388c1 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -26,12 +26,25 @@ pub fn snapshot_json_model( return Ok(None); } - let instance: JsonModel = serde_json::from_str(contents_str) + let mut instance: JsonModel = serde_json::from_str(contents_str) .with_context(|| format!("File is not a valid JSON model: {}", path.display()))?; + if let Some(top_level_name) = &instance.name { + let new_name = format!("{}.model.json", top_level_name); + + log::warn!( + "Model at path {} had a top-level Name field. \ + This field has been ignored since Rojo 6.0.\n\ + Consider removing this field and renaming the file to {}.", + new_name, + path.display() + ); + } + + instance.name = Some(name.to_owned()); + let mut snapshot = instance - .core - .into_snapshot(name.to_owned()) + .into_snapshot() .with_context(|| format!("Could not load JSON model: {}", path.display()))?; snapshot.metadata = snapshot @@ -44,42 +57,37 @@ pub fn snapshot_json_model( } #[derive(Debug, Deserialize)] -#[serde(rename_all = "PascalCase")] +#[serde(rename_all = "camelCase")] struct JsonModel { + #[serde(alias = "Name")] name: Option, - #[serde(flatten)] - core: JsonModelCore, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "PascalCase")] -struct JsonModelInstance { - name: String, - - #[serde(flatten)] - core: JsonModelCore, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "PascalCase")] -struct JsonModelCore { + #[serde(alias = "ClassName")] class_name: String, - #[serde(default = "Vec::new", skip_serializing_if = "Vec::is_empty")] - children: Vec, + #[serde( + alias = "Children", + default = "Vec::new", + skip_serializing_if = "Vec::is_empty" + )] + children: Vec, - #[serde(default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")] + #[serde( + alias = "Properties", + default = "HashMap::new", + skip_serializing_if = "HashMap::is_empty" + )] properties: HashMap, } -impl JsonModelCore { - fn into_snapshot(self, name: String) -> anyhow::Result { +impl JsonModel { + fn into_snapshot(self) -> anyhow::Result { + let name = self.name.unwrap_or_else(|| self.class_name.clone()); let class_name = self.class_name; let mut children = Vec::with_capacity(self.children.len()); for child in self.children { - children.push(child.core.into_snapshot(child.name)?); + children.push(child.into_snapshot()?); } let mut properties = HashMap::with_capacity(self.properties.len()); @@ -113,7 +121,43 @@ mod test { VfsSnapshot::file( r#" { - "Name": "children", + "className": "IntValue", + "properties": { + "Value": 5 + }, + "children": [ + { + "name": "The Child", + "className": "StringValue" + } + ] + } + "#, + ), + ) + .unwrap(); + + let vfs = Vfs::new(imfs); + + let instance_snapshot = snapshot_json_model( + &InstanceContext::default(), + &vfs, + Path::new("/foo.model.json"), + ) + .unwrap() + .unwrap(); + + insta::assert_yaml_snapshot!(instance_snapshot); + } + + #[test] + fn model_from_vfs_legacy() { + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo.model.json", + VfsSnapshot::file( + r#" + { "ClassName": "IntValue", "Properties": { "Value": 5 @@ -130,11 +174,11 @@ mod test { ) .unwrap(); - let mut vfs = Vfs::new(imfs); + let vfs = Vfs::new(imfs); let instance_snapshot = snapshot_json_model( &InstanceContext::default(), - &mut vfs, + &vfs, Path::new("/foo.model.json"), ) .unwrap() diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap new file mode 100644 index 00000000..a58fdb0f --- /dev/null +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap @@ -0,0 +1,29 @@ +--- +source: src/snapshot_middleware/json_model.rs +assertion_line: 186 +expression: instance_snapshot +--- +snapshot_id: ~ +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /foo.model.json + relevant_paths: + - /foo.model.json + context: {} +name: foo +class_name: IntValue +properties: + Value: + Int64: 5 +children: + - snapshot_id: ~ + metadata: + ignore_unknown_instances: false + relevant_paths: [] + context: {} + name: The Child + class_name: StringValue + properties: {} + children: [] + From 58098e96d4892e899f35e91dd46c8512faaba4b5 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 29 Jun 2022 20:15:24 -0400 Subject: [PATCH 1235/1504] Update Changelog --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ecc46bbf..4d958eef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Fixed `init.meta.json` when used with `init.lua` and related files. ([#549]) * Fixed incorrect output when serving from a non-default address or port ([#556]) * Fixed Linux binaries not running on systems with older glibc. ([#561]) +* Added `camelCase` casing for JSON models, deprecating `PascalCase` names. ([#563]) * Switched from structopt to clap for command line argument parsing. * Significantly improved performance of building and serving. ([#548]) * Increased minimum supported Rust version to 1.57.0. ([#564]) @@ -18,6 +19,7 @@ [#553]: https://github.com/rojo-rbx/rojo/pull/553 [#556]: https://github.com/rojo-rbx/rojo/pull/556 [#561]: https://github.com/rojo-rbx/rojo/pull/561 +[#563]: https://github.com/rojo-rbx/rojo/pull/563 [#564]: https://github.com/rojo-rbx/rojo/pull/564 ## [7.1.1] - May 26, 2022 From 0987b44e23aa233f596b65a1ac4bc337e292831f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 29 Jun 2022 20:34:06 -0400 Subject: [PATCH 1236/1504] Release v7.2.0 --- CHANGELOG.md | 3 +++ Cargo.lock | 2 +- Cargo.toml | 3 ++- plugin/src/Config.lua | 2 +- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d958eef..0084b2e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes + +## [7.2.0] - June 29, 2022 * Added support for `.luau` files. ([#552]) * Added support for live syncing Attributes and Tags. ([#553]) * Added notification popups in the Roblox Studio plugin. ([#540]) @@ -21,6 +23,7 @@ [#561]: https://github.com/rojo-rbx/rojo/pull/561 [#563]: https://github.com/rojo-rbx/rojo/pull/563 [#564]: https://github.com/rojo-rbx/rojo/pull/564 +[7.2.0]: https://github.com/rojo-rbx/rojo/releases/tag/v7.2.0 ## [7.1.1] - May 26, 2022 * Fixed sourcemap command not stripping paths correctly ([#544]) diff --git a/Cargo.lock b/Cargo.lock index 22b557a0..be02c842 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1858,7 +1858,7 @@ dependencies = [ [[package]] name = "rojo" -version = "7.1.1" +version = "7.2.0" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 34bfe1e5..4834506a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "rojo" -version = "7.1.1" +version = "7.2.0" +rust-version = "1.57.0" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 4e77df61..be288916 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {7, 1, 1}, + version = {7, 2, 0}, expectedServerVersionString = "7.0 or newer", protocolVersion = 4, defaultHost = "localhost", From 54398d4c4b5c178ef5de8612563361c3731f8c45 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 2 Jul 2022 02:12:58 -0700 Subject: [PATCH 1237/1504] Add setting to toggle sound effects (#568) * Use soundPlayer object with setting * Style changes --- plugin/src/App/Notifications.lua | 4 ++-- plugin/src/App/PluginSettings.lua | 1 + plugin/src/App/StatusPages/Settings.lua | 10 +++++++++- plugin/src/App/init.lua | 7 +++++-- plugin/src/{playSound.lua => soundPlayer.lua} | 17 +++++++++++++++-- 5 files changed, 32 insertions(+), 7 deletions(-) rename plugin/src/{playSound.lua => soundPlayer.lua} (54%) diff --git a/plugin/src/App/Notifications.lua b/plugin/src/App/Notifications.lua index 7da591cc..97be8b45 100644 --- a/plugin/src/App/Notifications.lua +++ b/plugin/src/App/Notifications.lua @@ -11,7 +11,6 @@ local bindingUtil = require(script.Parent.bindingUtil) local Theme = require(Plugin.App.Theme) local Assets = require(Plugin.Assets) -local playSound = require(Plugin.playSound) local BorderedContainer = require(Plugin.App.Components.BorderedContainer) @@ -53,7 +52,7 @@ function Notification:didMount() }) ) - playSound(Assets.Sounds.Notification) + self.props.soundPlayer:play(Assets.Sounds.Notification) self.timeout = task.spawn(function() local clock = os.clock() @@ -182,6 +181,7 @@ function Notifications:render() for index, notif in ipairs(self.props.notifications) do notifs[notif] = e(Notification, { + soundPlayer = self.props.soundPlayer, text = notif.text, timestamp = notif.timestamp, timeout = notif.timeout, diff --git a/plugin/src/App/PluginSettings.lua b/plugin/src/App/PluginSettings.lua index 72a5e6c1..366eb87a 100644 --- a/plugin/src/App/PluginSettings.lua +++ b/plugin/src/App/PluginSettings.lua @@ -10,6 +10,7 @@ local defaultSettings = { openScriptsExternally = false, twoWaySync = false, showNotifications = true, + playSounds = true, } local Settings = {} diff --git a/plugin/src/App/StatusPages/Settings.lua b/plugin/src/App/StatusPages/Settings.lua index 54b1e252..77074b67 100644 --- a/plugin/src/App/StatusPages/Settings.lua +++ b/plugin/src/App/StatusPages/Settings.lua @@ -210,12 +210,20 @@ function SettingsPage:render() layoutOrder = 2, }), + PlaySounds = e(Setting, { + id = "playSounds", + name = "Play Sounds", + description = "Toggle sound effects", + transparency = self.props.transparency, + layoutOrder = 3, + }), + TwoWaySync = e(Setting, { id = "twoWaySync", name = "Two-Way Sync", description = "EXPERIMENTAL! Editing files in Studio will sync them into the filesystem", transparency = self.props.transparency, - layoutOrder = 3, + layoutOrder = 4, }), Layout = e("UIListLayout", { diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 1058954a..9b4b60fb 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -12,6 +12,7 @@ local Dictionary = require(Plugin.Dictionary) local ServeSession = require(Plugin.ServeSession) local ApiContext = require(Plugin.ApiContext) local preloadAssets = require(Plugin.preloadAssets) +local soundPlayer = require(Plugin.soundPlayer) local Theme = require(script.Theme) local PluginSettings = require(script.PluginSettings) @@ -272,6 +273,7 @@ function App:render() Padding = UDim.new(0, 5), }), notifs = e(Notifications, { + soundPlayer = self.props.soundPlayer, notifications = self.state.notifications, onClose = function(index) self:closeNotification(index) @@ -347,10 +349,11 @@ return function(props) plugin = props.plugin, }, { App = PluginSettings.with(function(settings) - local settingsProps = Dictionary.merge(props, { + local mergedProps = Dictionary.merge(props, { settings = settings, + soundPlayer = soundPlayer.new(settings), }) - return e(App, settingsProps) + return e(App, mergedProps) end), }) end diff --git a/plugin/src/playSound.lua b/plugin/src/soundPlayer.lua similarity index 54% rename from plugin/src/playSound.lua rename to plugin/src/soundPlayer.lua index 4e452313..a58e8364 100644 --- a/plugin/src/playSound.lua +++ b/plugin/src/soundPlayer.lua @@ -1,4 +1,4 @@ --- Roblox decided that sounds only play in Edit mode when parented to a plugin widget, for some reason +-- Sounds only play in Edit mode when parented to a plugin widget, for some reason local plugin = plugin or script:FindFirstAncestorWhichIsA("Plugin") local widget = plugin:CreateDockWidgetPluginGui("Rojo_soundPlayer", DockWidgetPluginGuiInfo.new( Enum.InitialDockState.Float, @@ -9,7 +9,18 @@ local widget = plugin:CreateDockWidgetPluginGui("Rojo_soundPlayer", DockWidgetPl widget.Name = "Rojo_soundPlayer" widget.Title = "Rojo Sound Player" -return function(soundId) +local SoundPlayer = {} +SoundPlayer.__index = SoundPlayer + +function SoundPlayer.new(settings) + return setmetatable({ + settings = settings, + }, SoundPlayer) +end + +function SoundPlayer:play(soundId) + if self.settings and self.settings:get("playSounds") == false then return end + local sound = Instance.new("Sound") sound.SoundId = soundId sound.Parent = widget @@ -20,3 +31,5 @@ return function(soundId) sound:Play() end + +return SoundPlayer From 535e4d42bb10aff3916441971dc6cb124d2d6c29 Mon Sep 17 00:00:00 2001 From: Samuel P <60328723+imacodr@users.noreply.github.com> Date: Sat, 2 Jul 2022 17:33:24 -0600 Subject: [PATCH 1238/1504] Change Notification sound to generic sound (#566) * Change Notification sound to generic sound The notification sound causes the game to summon an error due to no experience permissions with no way to grant permission. This is due to the new audio policy update. * Update Notification sound --- plugin/src/Assets.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index 02fc2c7b..df259c07 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -46,7 +46,7 @@ local Assets = { }, }, Sounds = { - Notification = "rbxassetid://9716079936", + Notification = "rbxassetid://203785492", }, StartSession = "", SessionActive = "", From e482aba030aa1661bc3bd0d80dab85df6fca2fcf Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Fri, 8 Jul 2022 20:22:16 -0400 Subject: [PATCH 1239/1504] Release v7.2.1 --- CHANGELOG.md | 8 ++++++++ Cargo.lock | 2 +- Cargo.toml | 2 +- plugin/src/Config.lua | 4 ++-- 4 files changed, 12 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0084b2e1..21bee906 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## Unreleased Changes +## [7.2.1] - July 8, 2022 +* Fixed notification sound by changing it to a generic sound. ([#566]) +* Added setting to turn off sound effects. ([#568]) + +[#566]: https://github.com/rojo-rbx/rojo/pull/566 +[#568]: https://github.com/rojo-rbx/rojo/pull/568 +[7.2.0]: https://github.com/rojo-rbx/rojo/releases/tag/v7.2.0 + ## [7.2.0] - June 29, 2022 * Added support for `.luau` files. ([#552]) * Added support for live syncing Attributes and Tags. ([#553]) diff --git a/Cargo.lock b/Cargo.lock index be02c842..5bed38c0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1858,7 +1858,7 @@ dependencies = [ [[package]] name = "rojo" -version = "7.2.0" +version = "7.2.1" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 4834506a..008501d4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "7.2.0" +version = "7.2.1" rust-version = "1.57.0" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index be288916..3b85c3ee 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,8 +5,8 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {7, 2, 0}, - expectedServerVersionString = "7.0 or newer", + version = {7, 2, 1}, + expectedServerVersionString = "7.2 or newer", protocolVersion = 4, defaultHost = "localhost", defaultPort = 34872, From 5bf1f868863adac49a16ad32748a61d324ace592 Mon Sep 17 00:00:00 2001 From: wackbyte Date: Mon, 11 Jul 2022 00:44:47 -0400 Subject: [PATCH 1240/1504] Fix link to v7.2.1 in the changelog (#578) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 21bee906..56999e1b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ [#566]: https://github.com/rojo-rbx/rojo/pull/566 [#568]: https://github.com/rojo-rbx/rojo/pull/568 -[7.2.0]: https://github.com/rojo-rbx/rojo/releases/tag/v7.2.0 +[7.2.1]: https://github.com/rojo-rbx/rojo/releases/tag/v7.2.1 ## [7.2.0] - June 29, 2022 * Added support for `.luau` files. ([#552]) From 178cdc9dfa42519b102108553d23ae302bf4a1d0 Mon Sep 17 00:00:00 2001 From: wackbyte Date: Sun, 17 Jul 2022 18:50:12 -0400 Subject: [PATCH 1241/1504] Update benches so they compile (#582) --- benches/build.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/benches/build.rs b/benches/build.rs index 0b1e8934..456a5339 100644 --- a/benches/build.rs +++ b/benches/build.rs @@ -3,7 +3,7 @@ use std::path::Path; use criterion::{criterion_group, criterion_main, BatchSize, Criterion}; use tempfile::{tempdir, TempDir}; -use librojo::cli::{build, BuildCommand}; +use librojo::cli::BuildCommand; pub fn benchmark_small_place(c: &mut Criterion) { bench_build_place(c, "Small Place", "test-projects/benchmark_small_place") @@ -20,7 +20,7 @@ fn bench_build_place(c: &mut Criterion, name: &str, path: &str) { group.bench_function("build", |b| { b.iter_batched( || place_setup(path), - |(_dir, options)| build(options).unwrap(), + |(_dir, options)| options.run().unwrap(), BatchSize::SmallInput, ) }); From 6ae0bf366a901789b3dfb093dd3a4c72928092d7 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Mon, 18 Jul 2022 16:36:38 -0700 Subject: [PATCH 1242/1504] Use singleton settings outside the Roact tree (#576) * Use singleton settings outside the Roact tree * Cleanup listener on unmount * Refactor setting page components * Fix willUnmount being added to the wrong table * Remove bindings in favor of state --- plugin/src/App/PluginSettings.lua | 123 --------- plugin/src/App/StatusPages/Settings.lua | 246 ------------------ .../src/App/StatusPages/Settings/Setting.lua | 149 +++++++++++ plugin/src/App/StatusPages/Settings/init.lua | 121 +++++++++ plugin/src/App/init.lua | 22 +- plugin/src/Settings.lua | 78 ++++++ 6 files changed, 356 insertions(+), 383 deletions(-) delete mode 100644 plugin/src/App/PluginSettings.lua delete mode 100644 plugin/src/App/StatusPages/Settings.lua create mode 100644 plugin/src/App/StatusPages/Settings/Setting.lua create mode 100644 plugin/src/App/StatusPages/Settings/init.lua create mode 100644 plugin/src/Settings.lua diff --git a/plugin/src/App/PluginSettings.lua b/plugin/src/App/PluginSettings.lua deleted file mode 100644 index 366eb87a..00000000 --- a/plugin/src/App/PluginSettings.lua +++ /dev/null @@ -1,123 +0,0 @@ ---[[ - Persistent plugin settings that can be accessed via Roact context. -]] - -local Rojo = script:FindFirstAncestor("Rojo") - -local Roact = require(Rojo.Roact) - -local defaultSettings = { - openScriptsExternally = false, - twoWaySync = false, - showNotifications = true, - playSounds = true, -} - -local Settings = {} -Settings.__index = Settings - -function Settings.fromPlugin(plugin) - local values = {} - - for name, defaultValue in pairs(defaultSettings) do - local savedValue = plugin:GetSetting("Rojo_" .. name) - - if savedValue == nil then - plugin:SetSetting("Rojo_" .. name, defaultValue) - values[name] = defaultValue - else - values[name] = savedValue - end - end - - return setmetatable({ - __values = values, - __plugin = plugin, - __updateListeners = {}, - }, Settings) -end - -function Settings:get(name) - if defaultSettings[name] == nil then - error("Invalid setings name " .. tostring(name), 2) - end - - return self.__values[name] -end - -function Settings:set(name, value) - self.__plugin:SetSetting("Rojo_" .. name, value) - self.__values[name] = value - - for callback in pairs(self.__updateListeners) do - callback(name, value) - end -end - -function Settings:onUpdate(newCallback) - local newListeners = {} - for callback in pairs(self.__updateListeners) do - newListeners[callback] = true - end - - newListeners[newCallback] = true - self.__updateListeners = newListeners - - return function() - local newListeners = {} - for callback in pairs(self.__updateListeners) do - if callback ~= newCallback then - newListeners[callback] = true - end - end - - self.__updateListeners = newListeners - end -end - -local Context = Roact.createContext(nil) - -local StudioProvider = Roact.Component:extend("StudioProvider") - -function StudioProvider:init() - self.settings = Settings.fromPlugin(self.props.plugin) -end - -function StudioProvider:render() - return Roact.createElement(Context.Provider, { - value = self.settings, - }, self.props[Roact.Children]) -end - -local InternalConsumer = Roact.Component:extend("InternalConsumer") - -function InternalConsumer:render() - return self.props.render(self.props.settings) -end - -function InternalConsumer:didMount() - self.disconnect = self.props.settings:onUpdate(function() - -- Trigger a dummy state update to update the settings consumer. - self:setState({}) - end) -end - -function InternalConsumer:willUnmount() - self.disconnect() -end - -local function with(callback) - return Roact.createElement(Context.Consumer, { - render = function(settings) - return Roact.createElement(InternalConsumer, { - settings = settings, - render = callback, - }) - end, - }) -end - -return { - StudioProvider = StudioProvider, - with = with, -} diff --git a/plugin/src/App/StatusPages/Settings.lua b/plugin/src/App/StatusPages/Settings.lua deleted file mode 100644 index 77074b67..00000000 --- a/plugin/src/App/StatusPages/Settings.lua +++ /dev/null @@ -1,246 +0,0 @@ -local TextService = game:GetService("TextService") - -local Rojo = script:FindFirstAncestor("Rojo") -local Plugin = Rojo.Plugin - -local Roact = require(Rojo.Roact) - -local Assets = require(Plugin.Assets) -local Theme = require(Plugin.App.Theme) -local PluginSettings = require(Plugin.App.PluginSettings) - -local Checkbox = require(Plugin.App.Components.Checkbox) -local IconButton = require(Plugin.App.Components.IconButton) -local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) - -local e = Roact.createElement - -local DIVIDER_FADE_SIZE = 0.1 - -local function getTextBounds(text, textSize, font, lineHeight, bounds) - local textBounds = TextService:GetTextSize(text, textSize, font, bounds) - - local lineCount = textBounds.Y / textSize - local lineHeightAbsolute = textSize * lineHeight - - return Vector2.new(textBounds.X, lineHeightAbsolute * lineCount - (lineHeightAbsolute - textSize)) -end - -local function Navbar(props) - return Theme.with(function(theme) - theme = theme.Settings.Navbar - - return e("Frame", { - Size = UDim2.new(1, 0, 0, 46), - LayoutOrder = props.layoutOrder, - BackgroundTransparency = 1, - }, { - Back = e(IconButton, { - icon = Assets.Images.Icons.Back, - iconSize = 24, - color = theme.BackButtonColor, - transparency = props.transparency, - - position = UDim2.new(0, 0, 0.5, 0), - anchorPoint = Vector2.new(0, 0.5), - - onClick = props.onBack, - }), - - Text = e("TextLabel", { - Text = "Settings", - Font = Enum.Font.Gotham, - TextSize = 18, - TextColor3 = theme.TextColor, - TextTransparency = props.transparency, - - Size = UDim2.new(1, 0, 1, 0), - - BackgroundTransparency = 1, - }) - }) - end) -end - -local Setting = Roact.Component:extend("Setting") - -function Setting:init() - self.contentSize, self.setContentSize = Roact.createBinding(Vector2.new(0, 0)) - self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0)) -end - -function Setting:render() - return Theme.with(function(theme) - theme = theme.Settings - - return PluginSettings.with(function(settings) - return e("Frame", { - Size = self.contentSize:map(function(value) - return UDim2.new(1, 0, 0, 20 + value.Y + 20) - end), - LayoutOrder = self.props.layoutOrder, - BackgroundTransparency = 1, - - [Roact.Change.AbsoluteSize] = function(object) - self.setContainerSize(object.AbsoluteSize) - end, - }, { - Checkbox = e(Checkbox, { - active = settings:get(self.props.id), - transparency = self.props.transparency, - position = UDim2.new(1, 0, 0.5, 0), - anchorPoint = Vector2.new(1, 0.5), - onClick = function() - local currentValue = settings:get(self.props.id) - settings:set(self.props.id, not currentValue) - end, - }), - - Text = e("Frame", { - Size = UDim2.new(1, 0, 1, 0), - BackgroundTransparency = 1, - }, { - Name = e("TextLabel", { - Text = self.props.name, - Font = Enum.Font.GothamBold, - TextSize = 17, - TextColor3 = theme.Setting.NameColor, - TextXAlignment = Enum.TextXAlignment.Left, - TextTransparency = self.props.transparency, - - Size = UDim2.new(1, 0, 0, 17), - - LayoutOrder = 1, - BackgroundTransparency = 1, - }), - - Description = e("TextLabel", { - Text = self.props.description, - Font = Enum.Font.Gotham, - LineHeight = 1.2, - TextSize = 14, - TextColor3 = theme.Setting.DescriptionColor, - TextXAlignment = Enum.TextXAlignment.Left, - TextTransparency = self.props.transparency, - TextWrapped = true, - - Size = self.containerSize:map(function(value) - local textBounds = getTextBounds( - self.props.description, 14, Enum.Font.Gotham, 1.2, - Vector2.new(value.X - 50, math.huge) - ) - return UDim2.new(1, -50, 0, textBounds.Y) - end), - - LayoutOrder = 2, - BackgroundTransparency = 1, - }), - - Layout = e("UIListLayout", { - VerticalAlignment = Enum.VerticalAlignment.Center, - FillDirection = Enum.FillDirection.Vertical, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 6), - - [Roact.Change.AbsoluteContentSize] = function(object) - self.setContentSize(object.AbsoluteContentSize) - end, - }), - - Padding = e("UIPadding", { - PaddingTop = UDim.new(0, 20), - PaddingBottom = UDim.new(0, 20), - }), - }), - - Divider = e("Frame", { - BackgroundColor3 = theme.DividerColor, - BackgroundTransparency = self.props.transparency, - Size = UDim2.new(1, 0, 0, 1), - BorderSizePixel = 0, - }, { - Gradient = e("UIGradient", { - Transparency = NumberSequence.new({ - NumberSequenceKeypoint.new(0, 1), - NumberSequenceKeypoint.new(DIVIDER_FADE_SIZE, 0), - NumberSequenceKeypoint.new(1 - DIVIDER_FADE_SIZE, 0), - NumberSequenceKeypoint.new(1, 1), - }), - }), - }), - }) - end) - end) -end - -local SettingsPage = Roact.Component:extend("SettingsPage") - -function SettingsPage:init() - self.contentSize, self.setContentSize = Roact.createBinding(Vector2.new(0, 0)) -end - -function SettingsPage:render() - return Theme.with(function(theme) - theme = theme.Settings - - return e(ScrollingFrame, { - size = UDim2.new(1, 0, 1, 0), - contentSize = self.contentSize, - transparency = self.props.transparency, - }, { - Navbar = e(Navbar, { - onBack = self.props.onBack, - transparency = self.props.transparency, - layoutOrder = 0, - }), - - OpenScriptsExternally = e(Setting, { - id = "openScriptsExternally", - name = "Open Scripts Externally", - description = "Attempt to open scripts in an external editor", - transparency = self.props.transparency, - layoutOrder = 1, - }), - - ShowNotifications = e(Setting, { - id = "showNotifications", - name = "Show Notifications", - description = "Popup notifications in viewport", - transparency = self.props.transparency, - layoutOrder = 2, - }), - - PlaySounds = e(Setting, { - id = "playSounds", - name = "Play Sounds", - description = "Toggle sound effects", - transparency = self.props.transparency, - layoutOrder = 3, - }), - - TwoWaySync = e(Setting, { - id = "twoWaySync", - name = "Two-Way Sync", - description = "EXPERIMENTAL! Editing files in Studio will sync them into the filesystem", - transparency = self.props.transparency, - layoutOrder = 4, - }), - - Layout = e("UIListLayout", { - FillDirection = Enum.FillDirection.Vertical, - SortOrder = Enum.SortOrder.LayoutOrder, - - [Roact.Change.AbsoluteContentSize] = function(object) - self.setContentSize(object.AbsoluteContentSize) - end, - }), - - Padding = e("UIPadding", { - PaddingLeft = UDim.new(0, 20), - PaddingRight = UDim.new(0, 20), - }), - }) - end) -end - -return SettingsPage diff --git a/plugin/src/App/StatusPages/Settings/Setting.lua b/plugin/src/App/StatusPages/Settings/Setting.lua new file mode 100644 index 00000000..89fc8ad5 --- /dev/null +++ b/plugin/src/App/StatusPages/Settings/Setting.lua @@ -0,0 +1,149 @@ +local TextService = game:GetService("TextService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Settings = require(Plugin.Settings) +local Theme = require(Plugin.App.Theme) + +local Checkbox = require(Plugin.App.Components.Checkbox) + +local e = Roact.createElement + +local DIVIDER_FADE_SIZE = 0.1 + +local function getTextBounds(text, textSize, font, lineHeight, bounds) + local textBounds = TextService:GetTextSize(text, textSize, font, bounds) + + local lineCount = textBounds.Y / textSize + local lineHeightAbsolute = textSize * lineHeight + + return Vector2.new(textBounds.X, lineHeightAbsolute * lineCount - (lineHeightAbsolute - textSize)) +end + +local Setting = Roact.Component:extend("Setting") + +function Setting:init() + self.contentSize, self.setContentSize = Roact.createBinding(Vector2.new(0, 0)) + self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0)) + + self:setState({ + setting = Settings:get(self.props.id), + }) + + self.changedCleanup = Settings:onChanged(self.props.id, function(value) + self:setState({ + setting = value, + }) + end) +end + +function Setting:willUnmount() + self.changedCleanup() +end + +function Setting:render() + return Theme.with(function(theme) + theme = theme.Settings + + return e("Frame", { + Size = self.contentSize:map(function(value) + return UDim2.new(1, 0, 0, 20 + value.Y + 20) + end), + LayoutOrder = self.props.layoutOrder, + BackgroundTransparency = 1, + + [Roact.Change.AbsoluteSize] = function(object) + self.setContainerSize(object.AbsoluteSize) + end, + }, { + Checkbox = e(Checkbox, { + active = self.state.setting, + transparency = self.props.transparency, + position = UDim2.new(1, 0, 0.5, 0), + anchorPoint = Vector2.new(1, 0.5), + onClick = function() + local currentValue = Settings:get(self.props.id) + Settings:set(self.props.id, not currentValue) + end, + }), + + Text = e("Frame", { + Size = UDim2.new(1, 0, 1, 0), + BackgroundTransparency = 1, + }, { + Name = e("TextLabel", { + Text = self.props.name, + Font = Enum.Font.GothamBold, + TextSize = 17, + TextColor3 = theme.Setting.NameColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = self.props.transparency, + + Size = UDim2.new(1, 0, 0, 17), + + LayoutOrder = 1, + BackgroundTransparency = 1, + }), + + Description = e("TextLabel", { + Text = self.props.description, + Font = Enum.Font.Gotham, + LineHeight = 1.2, + TextSize = 14, + TextColor3 = theme.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = self.props.transparency, + TextWrapped = true, + + Size = self.containerSize:map(function(value) + local textBounds = getTextBounds( + self.props.description, 14, Enum.Font.Gotham, 1.2, + Vector2.new(value.X - 50, math.huge) + ) + return UDim2.new(1, -50, 0, textBounds.Y) + end), + + LayoutOrder = 2, + BackgroundTransparency = 1, + }), + + Layout = e("UIListLayout", { + VerticalAlignment = Enum.VerticalAlignment.Center, + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 6), + + [Roact.Change.AbsoluteContentSize] = function(object) + self.setContentSize(object.AbsoluteContentSize) + end, + }), + + Padding = e("UIPadding", { + PaddingTop = UDim.new(0, 20), + PaddingBottom = UDim.new(0, 20), + }), + }), + + Divider = e("Frame", { + BackgroundColor3 = theme.DividerColor, + BackgroundTransparency = self.props.transparency, + Size = UDim2.new(1, 0, 0, 1), + BorderSizePixel = 0, + }, { + Gradient = e("UIGradient", { + Transparency = NumberSequence.new({ + NumberSequenceKeypoint.new(0, 1), + NumberSequenceKeypoint.new(DIVIDER_FADE_SIZE, 0), + NumberSequenceKeypoint.new(1 - DIVIDER_FADE_SIZE, 0), + NumberSequenceKeypoint.new(1, 1), + }), + }), + }), + }) + end) +end + +return Setting diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua new file mode 100644 index 00000000..4ffe226e --- /dev/null +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -0,0 +1,121 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin + +local Roact = require(Rojo.Roact) + +local Assets = require(Plugin.Assets) +local Theme = require(Plugin.App.Theme) + +local IconButton = require(Plugin.App.Components.IconButton) +local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) +local Setting = require(script.Setting) + +local e = Roact.createElement + +local function Navbar(props) + return Theme.with(function(theme) + theme = theme.Settings.Navbar + + return e("Frame", { + Size = UDim2.new(1, 0, 0, 46), + LayoutOrder = props.layoutOrder, + BackgroundTransparency = 1, + }, { + Back = e(IconButton, { + icon = Assets.Images.Icons.Back, + iconSize = 24, + color = theme.BackButtonColor, + transparency = props.transparency, + + position = UDim2.new(0, 0, 0.5, 0), + anchorPoint = Vector2.new(0, 0.5), + + onClick = props.onBack, + }), + + Text = e("TextLabel", { + Text = "Settings", + Font = Enum.Font.Gotham, + TextSize = 18, + TextColor3 = theme.TextColor, + TextTransparency = props.transparency, + + Size = UDim2.new(1, 0, 1, 0), + + BackgroundTransparency = 1, + }) + }) + end) +end + +local SettingsPage = Roact.Component:extend("SettingsPage") + +function SettingsPage:init() + self.contentSize, self.setContentSize = Roact.createBinding(Vector2.new(0, 0)) +end + +function SettingsPage:render() + return Theme.with(function(theme) + theme = theme.Settings + + return e(ScrollingFrame, { + size = UDim2.new(1, 0, 1, 0), + contentSize = self.contentSize, + transparency = self.props.transparency, + }, { + Navbar = e(Navbar, { + onBack = self.props.onBack, + transparency = self.props.transparency, + layoutOrder = 0, + }), + + OpenScriptsExternally = e(Setting, { + id = "openScriptsExternally", + name = "Open Scripts Externally", + description = "Attempt to open scripts in an external editor", + transparency = self.props.transparency, + layoutOrder = 1, + }), + + ShowNotifications = e(Setting, { + id = "showNotifications", + name = "Show Notifications", + description = "Popup notifications in viewport", + transparency = self.props.transparency, + layoutOrder = 2, + }), + + PlaySounds = e(Setting, { + id = "playSounds", + name = "Play Sounds", + description = "Toggle sound effects", + transparency = self.props.transparency, + layoutOrder = 3, + }), + + TwoWaySync = e(Setting, { + id = "twoWaySync", + name = "Two-Way Sync", + description = "EXPERIMENTAL! Editing files in Studio will sync them into the filesystem", + transparency = self.props.transparency, + layoutOrder = 4, + }), + + Layout = e("UIListLayout", { + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + + [Roact.Change.AbsoluteContentSize] = function(object) + self.setContentSize(object.AbsoluteContentSize) + end, + }), + + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 20), + PaddingRight = UDim.new(0, 20), + }), + }) + end) +end + +return SettingsPage diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 9b4b60fb..9693220b 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -7,6 +7,7 @@ local Log = require(Rojo.Log) local Assets = require(Plugin.Assets) local Version = require(Plugin.Version) local Config = require(Plugin.Config) +local Settings = require(Plugin.Settings) local strict = require(Plugin.strict) local Dictionary = require(Plugin.Dictionary) local ServeSession = require(Plugin.ServeSession) @@ -14,7 +15,6 @@ local ApiContext = require(Plugin.ApiContext) local preloadAssets = require(Plugin.preloadAssets) local soundPlayer = require(Plugin.soundPlayer) local Theme = require(script.Theme) -local PluginSettings = require(script.PluginSettings) local Page = require(script.Page) local Notifications = require(script.Notifications) @@ -52,7 +52,7 @@ function App:init() end function App:addNotification(text: string, timeout: number?) - if not self.props.settings:get("showNotifications") then + if not Settings:get("showNotifications") then return end @@ -91,8 +91,8 @@ function App:startSession() local host, port = self:getHostAndPort() local sessionOptions = { - openScriptsExternally = self.props.settings:get("openScriptsExternally"), - twoWaySync = self.props.settings:get("twoWaySync"), + openScriptsExternally = Settings:get("openScriptsExternally"), + twoWaySync = Settings:get("twoWaySync"), } local baseUrl = ("http://%s:%s"):format(host, port) @@ -345,15 +345,9 @@ function App:render() end return function(props) - return e(PluginSettings.StudioProvider, { - plugin = props.plugin, - }, { - App = PluginSettings.with(function(settings) - local mergedProps = Dictionary.merge(props, { - settings = settings, - soundPlayer = soundPlayer.new(settings), - }) - return e(App, mergedProps) - end), + local mergedProps = Dictionary.merge(props, { + soundPlayer = soundPlayer.new(Settings), }) + + return e(App, mergedProps) end diff --git a/plugin/src/Settings.lua b/plugin/src/Settings.lua new file mode 100644 index 00000000..6513d41c --- /dev/null +++ b/plugin/src/Settings.lua @@ -0,0 +1,78 @@ +--[[ + Persistent plugin settings. +]] + +local plugin = plugin or script:FindFirstAncestorWhichIsA("Plugin") +local Rojo = script:FindFirstAncestor("Rojo") + +local Log = require(Rojo.Log) + +local defaultSettings = { + openScriptsExternally = false, + twoWaySync = false, + showNotifications = true, + playSounds = true, +} + +local Settings = {} + +Settings._values = table.clone(defaultSettings) +Settings._updateListeners = {} + +if plugin then + for name, defaultValue in pairs(Settings._values) do + local savedValue = plugin:GetSetting("Rojo_" .. name) + + if savedValue == nil then + -- plugin:SetSetting hits disc instead of memory, so it can be slow. Spawn so we don't hang. + task.spawn(plugin.SetSetting, plugin, "Rojo_" .. name, defaultValue) + Settings._values[name] = defaultValue + else + Settings._values[name] = savedValue + end + end + Log.trace("Loaded settings from plugin store") +end + +function Settings:get(name) + if defaultSettings[name] == nil then + error("Invalid setings name " .. tostring(name), 2) + end + + return self._values[name] +end + +function Settings:set(name, value) + self._values[name] = value + + if plugin then + -- plugin:SetSetting hits disc instead of memory, so it can be slow. Spawn so we don't hang. + task.spawn(plugin.SetSetting, plugin, "Rojo_" .. name, value) + end + + if self._updateListeners[name] then + for callback in pairs(self._updateListeners[name]) do + task.spawn(callback, value) + end + end + + Log.trace(string.format("Set setting '%s' to '%s'", name, tostring(value))) +end + +function Settings:onChanged(name, callback) + local listeners = self._updateListeners[name] + if listeners == nil then + listeners = {} + self._updateListeners[name] = listeners + end + listeners[callback] = true + + Log.trace(string.format("Added listener for setting '%s' changes", name)) + + return function() + listeners[callback] = nil + Log.trace(string.format("Removed listener for setting '%s' changes", name)) + end +end + +return Settings From 411d1a89c14899f48103f8db3ac48dae458d8411 Mon Sep 17 00:00:00 2001 From: wackbyte Date: Mon, 18 Jul 2022 19:47:30 -0400 Subject: [PATCH 1243/1504] Really default to the current directory in 'rojo fmt-project' (#581) Co-authored-by: Lucien Greathouse --- src/cli/fmt_project.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/cli/fmt_project.rs b/src/cli/fmt_project.rs index 9351d635..48a52bd6 100644 --- a/src/cli/fmt_project.rs +++ b/src/cli/fmt_project.rs @@ -5,6 +5,8 @@ use clap::Parser; use crate::project::Project; +use super::resolve_path; + /// Reformat a Rojo project using the standard JSON formatting rules. #[derive(Debug, Parser)] pub struct FmtProjectCommand { @@ -15,7 +17,8 @@ pub struct FmtProjectCommand { impl FmtProjectCommand { pub fn run(self) -> anyhow::Result<()> { - let project = Project::load_fuzzy(&self.project)? + let base_path = resolve_path(&self.project); + let project = Project::load_fuzzy(&base_path)? .context("A project file is required to run 'rojo fmt-project'")?; let serialized = serde_json::to_string_pretty(&project) From 62eb4f026f7a81967b7a0cf89747fb2ace686c59 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 23 Jul 2022 09:24:16 -0700 Subject: [PATCH 1244/1504] Fix errors after session already ended (#587) --- plugin/src/ServeSession.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index f9a3bd9b..ec6de75e 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -137,7 +137,9 @@ function ServeSession:start() end) end) :catch(function(err) - self:__stopInternal(err) + if self.__status ~= Status.Disconnected then + self:__stopInternal(err) + end end) end From 5cb4cc0d1d92ff360e145e2d3eccf8ccc8ed8d79 Mon Sep 17 00:00:00 2001 From: Boegie19 <34578426+Boegie19@users.noreply.github.com> Date: Sat, 30 Jul 2022 03:45:19 +0200 Subject: [PATCH 1245/1504] feature init csv (#594) * init csv feature + test * fmt fixes --- ..._tests__build__init_csv_with_children.snap | 19 ++++++++ .../default.project.json | 6 +++ .../init_csv_with_children/src/init.csv | 2 + .../init_csv_with_children/src/other.csv | 2 + src/snapshot_middleware/csv.rs | 43 ++++++++++++++++++- src/snapshot_middleware/mod.rs | 19 ++++++-- tests/tests/build.rs | 1 + 7 files changed, 88 insertions(+), 4 deletions(-) create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__init_csv_with_children.snap create mode 100644 rojo-test/build-tests/init_csv_with_children/default.project.json create mode 100644 rojo-test/build-tests/init_csv_with_children/src/init.csv create mode 100644 rojo-test/build-tests/init_csv_with_children/src/other.csv diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__init_csv_with_children.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__init_csv_with_children.snap new file mode 100644 index 00000000..c089ebb2 --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__init_csv_with_children.snap @@ -0,0 +1,19 @@ +--- +source: tests/tests/build.rs +assertion_line: 100 +expression: contents +--- + + + + init_csv_with_children + [{"key":"init.csv","values":{}}] + + + + other + [{"key":"other.csv","values":{}}] + + + + diff --git a/rojo-test/build-tests/init_csv_with_children/default.project.json b/rojo-test/build-tests/init_csv_with_children/default.project.json new file mode 100644 index 00000000..9b77db50 --- /dev/null +++ b/rojo-test/build-tests/init_csv_with_children/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "init_csv_with_children", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/init_csv_with_children/src/init.csv b/rojo-test/build-tests/init_csv_with_children/src/init.csv new file mode 100644 index 00000000..a6bc3e7c --- /dev/null +++ b/rojo-test/build-tests/init_csv_with_children/src/init.csv @@ -0,0 +1,2 @@ +Key +init.csv \ No newline at end of file diff --git a/rojo-test/build-tests/init_csv_with_children/src/other.csv b/rojo-test/build-tests/init_csv_with_children/src/other.csv new file mode 100644 index 00000000..0fc62b49 --- /dev/null +++ b/rojo-test/build-tests/init_csv_with_children/src/other.csv @@ -0,0 +1,2 @@ +Key +other.csv \ No newline at end of file diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index a8f27180..708f1bb8 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -7,7 +7,11 @@ use serde::Serialize; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{meta_file::AdjacentMetadata, util::PathExt}; +use super::{ + dir::{dir_meta, snapshot_dir_no_meta}, + meta_file::AdjacentMetadata, + util::PathExt, +}; pub fn snapshot_csv( _context: &InstanceContext, @@ -46,6 +50,43 @@ pub fn snapshot_csv( Ok(Some(snapshot)) } +/// Attempts to snapshot an 'init' csv contained inside of a folder with +/// the given name. +/// +/// csv named `init.csv` +/// their parents, which acts similarly to `__init__.py` from the Python world. +pub fn snapshot_csv_init( + context: &InstanceContext, + vfs: &Vfs, + init_path: &Path, +) -> anyhow::Result> { + let folder_path = init_path.parent().unwrap(); + let dir_snapshot = snapshot_dir_no_meta(context, vfs, folder_path)?.unwrap(); + + if dir_snapshot.class_name != "Folder" { + anyhow::bail!( + "init.csv can only be used if the instance produced by \ + the containing directory would be a Folder.\n\ + \n\ + The directory {} turned into an instance of class {}.", + folder_path.display(), + dir_snapshot.class_name + ); + } + + let mut init_snapshot = snapshot_csv(context, vfs, init_path)?.unwrap(); + + init_snapshot.name = dir_snapshot.name; + init_snapshot.children = dir_snapshot.children; + init_snapshot.metadata = dir_snapshot.metadata; + + if let Some(mut meta) = dir_meta(vfs, folder_path)? { + meta.apply_all(&mut init_snapshot)?; + } + + Ok(Some(init_snapshot)) +} + /// Struct that holds any valid row from a Roblox CSV translation table. /// /// We manually deserialize into this table from CSV, but let serde_json handle diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 8d27d5bc..3d5de76b 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -24,7 +24,7 @@ use memofs::{IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceSnapshot}; use self::{ - csv::snapshot_csv, + csv::{snapshot_csv, snapshot_csv_init}, dir::snapshot_dir, json::snapshot_json, json_model::snapshot_json_model, @@ -87,12 +87,19 @@ pub fn snapshot_from_vfs( return snapshot_lua_init(context, vfs, &init_path); } + let init_path = path.join("init.csv"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return snapshot_csv_init(context, vfs, &init_path); + } + snapshot_dir(context, vfs, path) } else { let script_name = path .file_name_trim_end(".lua") .or_else(|_| path.file_name_trim_end(".luau")); + let csv_name = path.file_name_trim_end(".csv"); + if let Ok(name) = script_name { match name { // init scripts are handled elsewhere and should not turn into @@ -110,8 +117,14 @@ pub fn snapshot_from_vfs( return Ok(None); } else if path.file_name_ends_with(".json") { return snapshot_json(context, vfs, path); - } else if path.file_name_ends_with(".csv") { - return snapshot_csv(context, vfs, path); + } else if let Ok(name) = csv_name { + match name { + // init csv are handled elsewhere and should not turn into + // their own children. + "init" => return Ok(None), + + _ => return snapshot_csv(context, vfs, path), + } } else if path.file_name_ends_with(".txt") { return snapshot_txt(context, vfs, path); } else if path.file_name_ends_with(".rbxmx") { diff --git a/tests/tests/build.rs b/tests/tests/build.rs index 1776fe7d..4907449d 100644 --- a/tests/tests/build.rs +++ b/tests/tests/build.rs @@ -21,6 +21,7 @@ macro_rules! gen_build_tests { } gen_build_tests! { + init_csv_with_children, attributes, client_in_folder, client_init, From 2a6a8b42a6b010ce23dc84096d07646f7ac492a4 Mon Sep 17 00:00:00 2001 From: JohnnyMorganz Date: Mon, 1 Aug 2022 09:07:07 +0100 Subject: [PATCH 1246/1504] Add `--watch` to sourcemap generation (#602) * Implement watch argument * Add forget call * Clippy fixes * Update changelog --- CHANGELOG.md | 3 ++ src/cli/sourcemap.rs | 65 ++++++++++++++++++++++++++++++++++---------- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56999e1b..566c4af3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Rojo Changelog ## Unreleased Changes +* Added `--watch` flag to `rojo sourcemap` ([#602]) + +[#602]: https://github.com/rojo-rbx/rojo/pull/602 ## [7.2.1] - July 8, 2022 * Fixed notification sound by changing it to a generic sound. ([#566]) diff --git a/src/cli/sourcemap.rs b/src/cli/sourcemap.rs index 9d761e71..353c6020 100644 --- a/src/cli/sourcemap.rs +++ b/src/cli/sourcemap.rs @@ -1,5 +1,6 @@ use std::{ io::{BufWriter, Write}, + mem::forget, path::{Path, PathBuf}, }; @@ -8,6 +9,7 @@ use fs_err::File; use memofs::Vfs; use rbx_dom_weak::types::Ref; use serde::Serialize; +use tokio::runtime::Runtime; use crate::{ serve_session::ServeSession, @@ -50,6 +52,10 @@ pub struct SourcemapCommand { /// If non-script files should be included or not. Defaults to false. #[clap(long)] pub include_non_scripts: bool, + + /// Whether to automatically recreate a snapshot when any input files change. + #[clap(long)] + pub watch: bool, } impl SourcemapCommand { @@ -58,9 +64,10 @@ impl SourcemapCommand { log::trace!("Constructing in-memory filesystem"); let vfs = Vfs::new_default(); + vfs.set_watch_enabled(self.watch); let session = ServeSession::new(vfs, &project_path)?; - let tree = session.tree(); + let mut cursor = session.message_queue().cursor(); let filter = if self.include_non_scripts { filter_nothing @@ -68,19 +75,24 @@ impl SourcemapCommand { filter_non_scripts }; - let root_node = recurse_create_node(&tree, tree.get_root_id(), session.root_dir(), filter); + write_sourcemap(&session, self.output.as_deref(), filter)?; - if let Some(output_path) = self.output { - let mut file = BufWriter::new(File::create(&output_path)?); - serde_json::to_writer(&mut file, &root_node)?; - file.flush()?; + if self.watch { + let rt = Runtime::new().unwrap(); - println!("Created sourcemap at {}", output_path.display()); - } else { - let output = serde_json::to_string(&root_node)?; - println!("{}", output); + loop { + let receiver = session.message_queue().subscribe(cursor); + let (new_cursor, _patch_set) = rt.block_on(receiver).unwrap(); + cursor = new_cursor; + + write_sourcemap(&session, self.output.as_deref(), filter)?; + } } + // Avoid dropping ServeSession: it's potentially VERY expensive to drop + // and we're about to exit anyways. + forget(session); + Ok(()) } } @@ -90,10 +102,10 @@ fn filter_nothing(_instance: &InstanceWithMeta) -> bool { } fn filter_non_scripts(instance: &InstanceWithMeta) -> bool { - match instance.class_name() { - "Script" | "LocalScript" | "ModuleScript" => true, - _ => false, - } + matches!( + instance.class_name(), + "Script" | "LocalScript" | "ModuleScript" + ) } fn recurse_create_node( @@ -106,7 +118,7 @@ fn recurse_create_node( let mut children = Vec::new(); for &child_id in instance.children() { - if let Some(child_node) = recurse_create_node(tree, child_id, &project_dir, filter) { + if let Some(child_node) = recurse_create_node(tree, child_id, project_dir, filter) { children.push(child_node); } } @@ -134,3 +146,26 @@ fn recurse_create_node( children, }) } + +fn write_sourcemap( + session: &ServeSession, + output: Option<&Path>, + filter: fn(&InstanceWithMeta) -> bool, +) -> anyhow::Result<()> { + let tree = session.tree(); + + let root_node = recurse_create_node(&tree, tree.get_root_id(), session.root_dir(), filter); + + if let Some(output_path) = output { + let mut file = BufWriter::new(File::create(&output_path)?); + serde_json::to_writer(&mut file, &root_node)?; + file.flush()?; + + println!("Created sourcemap at {}", output_path.display()); + } else { + let output = serde_json::to_string(&root_node)?; + println!("{}", output); + } + + Ok(()) +} From 565c12405eb8fb5a9d33515562fe35cdcd37b748 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 3 Aug 2022 17:19:23 -0400 Subject: [PATCH 1247/1504] Skip empty AppliedPatchSets for sending changes. --- src/change_processor.rs | 8 ++++++-- src/snapshot/patch.rs | 6 +++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index dce1cd8d..ac9cb869 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -154,7 +154,9 @@ impl JobThreadContext { for id in affected_ids { if let Some(patch) = compute_and_apply_changes(&mut tree, &self.vfs, id) { - applied_patches.push(patch); + if !patch.is_empty() { + applied_patches.push(patch); + } } } } @@ -253,7 +255,9 @@ impl JobThreadContext { apply_patch_set(&mut tree, patch_set) }; - self.message_queue.push_messages(&[applied_patch]); + if !applied_patch.is_empty() { + self.message_queue.push_messages(&[applied_patch]); + } } } diff --git a/src/snapshot/patch.rs b/src/snapshot/patch.rs index 1d320a2c..4413db59 100644 --- a/src/snapshot/patch.rs +++ b/src/snapshot/patch.rs @@ -19,7 +19,7 @@ pub struct PatchSet { pub updated_instances: Vec, } -impl<'a> PatchSet { +impl PatchSet { pub fn new() -> Self { PatchSet { removed_instances: Vec::new(), @@ -76,6 +76,10 @@ impl AppliedPatchSet { updated: Vec::new(), } } + + pub fn is_empty(&self) -> bool { + self.removed.is_empty() && self.added.is_empty() && self.updated.is_empty() + } } #[derive(Debug, Clone, Serialize, Deserialize)] From e864cf0c7df50bceb491ad7f3fcb1ea381201749 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 3 Aug 2022 15:36:58 -0700 Subject: [PATCH 1248/1504] Switch git submodules to Wally packages (#584) * Switch git submodules to Wally packages * Update build snapshot * Add wally to foreman and use latest versions * Install packages in CI runners * Fix indents * Install packages in the correct directory * Install packages in correct dir of release action too * Remove submodules from ci checkout * Remove submodules from release checkout * Update selene with latest fix * Fix whitespace Co-authored-by: Lucien Greathouse --- .github/workflows/ci.yml | 28 ++++++++-- .github/workflows/release.yml | 10 ++-- .gitignore | 3 + .gitmodules | 15 ----- build.rs | 17 +----- foreman.toml | 5 +- plugin/default.project.json | 56 ++++++++----------- plugin/modules/flipper | 1 - plugin/modules/promise | 1 - plugin/modules/roact | 1 - plugin/modules/t | 1 - plugin/modules/testez | 1 - plugin/run-tests.server.lua | 4 +- plugin/src/ApiContext.lua | 11 ++-- .../src/App/Components/BorderedContainer.lua | 5 +- plugin/src/App/Components/Checkbox.lua | 7 ++- plugin/src/App/Components/Header.lua | 5 +- plugin/src/App/Components/IconButton.lua | 7 ++- plugin/src/App/Components/ScrollingFrame.lua | 5 +- plugin/src/App/Components/SlicedImage.lua | 5 +- plugin/src/App/Components/Spinner.lua | 5 +- .../Components/Studio/StudioPluginAction.lua | 3 +- .../Components/Studio/StudioPluginContext.lua | 5 +- .../App/Components/Studio/StudioPluginGui.lua | 5 +- .../Components/Studio/StudioToggleButton.lua | 3 +- .../App/Components/Studio/StudioToolbar.lua | 5 +- .../Studio/StudioToolbarContext.lua | 5 +- plugin/src/App/Components/TextButton.lua | 7 ++- plugin/src/App/Components/TouchRipple.lua | 7 ++- plugin/src/App/Notifications.lua | 5 +- plugin/src/App/Page.lua | 7 ++- plugin/src/App/StatusPages/Connected.lua | 5 +- plugin/src/App/StatusPages/Connecting.lua | 5 +- plugin/src/App/StatusPages/Error.lua | 5 +- plugin/src/App/StatusPages/NotConnected.lua | 5 +- .../src/App/StatusPages/Settings/Setting.lua | 3 +- plugin/src/App/StatusPages/Settings/init.lua | 3 +- plugin/src/App/Theme.lua | 5 +- plugin/src/App/bindingUtil.lua | 7 ++- plugin/src/App/init.lua | 5 +- plugin/src/ChangeBatcher/createPatchSet.lua | 3 +- .../src/ChangeBatcher/encodePatchUpdate.lua | 5 +- plugin/src/ChangeBatcher/encodeProperty.lua | 5 +- plugin/src/InstanceMap.lua | 3 +- plugin/src/PatchSet.lua | 5 +- plugin/src/Reconciler/Error.lua | 5 +- plugin/src/Reconciler/applyPatch.lua | 3 +- plugin/src/Reconciler/decodeValue.lua | 5 +- plugin/src/Reconciler/diff.lua | 6 +- plugin/src/Reconciler/diff.spec.lua | 5 +- plugin/src/Reconciler/getProperty.lua | 5 +- plugin/src/Reconciler/setProperty.lua | 7 ++- plugin/src/ServeSession.lua | 7 ++- plugin/src/Settings.lua | 3 +- plugin/src/Types.lua | 4 +- plugin/src/init.server.lua | 13 +++-- plugin/src/invariant.lua | 6 +- plugin/src/preloadAssets.lua | 5 +- plugin/src/runTests.lua | 5 +- plugin/src/soundPlayer.lua | 19 ++++--- plugin/test-place.project.json | 4 +- plugin/wally.lock | 33 +++++++++++ plugin/wally.toml | 17 ++++++ 63 files changed, 271 insertions(+), 190 deletions(-) delete mode 100644 .gitmodules delete mode 160000 plugin/modules/flipper delete mode 160000 plugin/modules/promise delete mode 160000 plugin/modules/roact delete mode 160000 plugin/modules/t delete mode 160000 plugin/modules/testez create mode 100644 plugin/wally.lock create mode 100644 plugin/wally.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ab5ffe20..6f4b3c56 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,8 +20,6 @@ jobs: steps: - uses: actions/checkout@v3 - with: - submodules: true - name: Install Rust uses: actions-rs/toolchain@v1 @@ -30,6 +28,17 @@ jobs: override: true profile: minimal + - name: Setup Foreman + uses: Roblox/setup-foreman@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install packages + run: | + cd plugin + wally install + cd .. + - name: Build run: cargo build --locked --verbose @@ -42,8 +51,6 @@ jobs: steps: - uses: actions/checkout@v3 - with: - submodules: true - name: Install Rust uses: actions-rs/toolchain@v1 @@ -52,8 +59,19 @@ jobs: override: true components: rustfmt, clippy + - name: Setup Foreman + uses: Roblox/setup-foreman@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install packages + run: | + cd plugin + wally install + cd .. + - name: Rustfmt run: cargo fmt -- --check - name: Clippy - run: cargo clippy \ No newline at end of file + run: cargo clippy diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 216d8cad..251b3140 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,14 +28,18 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - with: - submodules: true - name: Setup Foreman uses: Roblox/setup-foreman@v1 with: token: ${{ secrets.GITHUB_TOKEN }} + - name: Install packages + run: | + cd plugin + wally install + cd .. + - name: Build Plugin run: rojo build plugin --output Rojo.rbxm @@ -92,8 +96,6 @@ jobs: BIN: rojo steps: - uses: actions/checkout@v3 - with: - submodules: true - name: Get Version from Tag shell: bash diff --git a/.gitignore b/.gitignore index 88cdf551..2c910135 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,9 @@ # Test places for the Roblox Studio Plugin /plugin/*.rbxlx +# Packages for the Roblox Studio Plugin +/plugin/*Packages + # Roblox Studio holds 'lock' files on places *.rbxl.lock *.rbxlx.lock diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 98b1cb5e..00000000 --- a/.gitmodules +++ /dev/null @@ -1,15 +0,0 @@ -[submodule "plugin/modules/roact"] - path = plugin/modules/roact - url = https://github.com/Roblox/roact.git -[submodule "plugin/modules/testez"] - path = plugin/modules/testez - url = https://github.com/Roblox/testez.git -[submodule "plugin/modules/promise"] - path = plugin/modules/promise - url = https://github.com/LPGhatguy/roblox-lua-promise.git -[submodule "plugin/modules/t"] - path = plugin/modules/t - url = https://github.com/osyrisrblx/t.git -[submodule "plugin/modules/flipper"] - path = plugin/modules/flipper - url = https://github.com/Reselim/Flipper diff --git a/build.rs b/build.rs index 0cbd190f..1cff84c5 100644 --- a/build.rs +++ b/build.rs @@ -43,8 +43,6 @@ fn main() -> Result<(), anyhow::Error> { let root_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap(); let plugin_root = PathBuf::from(root_dir).join("plugin"); - let plugin_modules = plugin_root.join("modules"); - let snapshot = VfsSnapshot::dir(hashmap! { "default.project.json" => snapshot_from_fs_path(&plugin_root.join("default.project.json"))?, "fmt" => snapshot_from_fs_path(&plugin_root.join("fmt"))?, @@ -52,20 +50,7 @@ fn main() -> Result<(), anyhow::Error> { "log" => snapshot_from_fs_path(&plugin_root.join("log"))?, "rbx_dom_lua" => snapshot_from_fs_path(&plugin_root.join("rbx_dom_lua"))?, "src" => snapshot_from_fs_path(&plugin_root.join("src"))?, - "modules" => VfsSnapshot::dir(hashmap! { - "roact" => VfsSnapshot::dir(hashmap! { - "src" => snapshot_from_fs_path(&plugin_modules.join("roact").join("src"))? - }), - "promise" => VfsSnapshot::dir(hashmap! { - "lib" => snapshot_from_fs_path(&plugin_modules.join("promise").join("lib"))? - }), - "t" => VfsSnapshot::dir(hashmap! { - "lib" => snapshot_from_fs_path(&plugin_modules.join("t").join("lib"))? - }), - "flipper" => VfsSnapshot::dir(hashmap! { - "src" => snapshot_from_fs_path(&plugin_modules.join("flipper").join("src"))? - }), - }), + "Packages" => snapshot_from_fs_path(&plugin_root.join("Packages"))?, }); let out_path = Path::new(&out_dir).join("plugin.bincode"); diff --git a/foreman.toml b/foreman.toml index 20ce14cb..4b8546aa 100644 --- a/foreman.toml +++ b/foreman.toml @@ -1,4 +1,5 @@ [tools] -rojo = { source = "rojo-rbx/rojo", version = "7.1.1" } +rojo = { source = "rojo-rbx/rojo", version = "7.2.1" } run-in-roblox = { source = "rojo-rbx/run-in-roblox", version = "0.3.0" } -selene = { source = "Kampfkarren/selene", version = "0.18.2" } +selene = { source = "Kampfkarren/selene", version = "0.20.0" } +wally = { source = "UpliftGames/wally", version = "0.3.1"} diff --git a/plugin/default.project.json b/plugin/default.project.json index bdaadab3..09234438 100644 --- a/plugin/default.project.json +++ b/plugin/default.project.json @@ -1,33 +1,25 @@ { - "name": "Rojo", - "tree": { - "$className": "Folder", - "Plugin": { - "$path": "src" - }, - "Log": { - "$path": "log" - }, - "Http": { - "$path": "http" - }, - "Fmt": { - "$path": "fmt" - }, - "RbxDom": { - "$path": "rbx_dom_lua" - }, - "Roact": { - "$path": "modules/roact/src" - }, - "Promise": { - "$path": "modules/promise/lib" - }, - "t": { - "$path": "modules/t/lib" - }, - "Flipper": { - "$path": "modules/flipper/src" - } - } -} \ No newline at end of file + "name": "Rojo", + "tree": { + "$className": "Folder", + "Plugin": { + "$path": "src" + }, + "Packages": { + "$path": "Packages", + + "Log": { + "$path": "log" + }, + "Http": { + "$path": "http" + }, + "Fmt": { + "$path": "fmt" + }, + "RbxDom": { + "$path": "rbx_dom_lua" + } + } + } +} diff --git a/plugin/modules/flipper b/plugin/modules/flipper deleted file mode 160000 index 4cf7a03c..00000000 --- a/plugin/modules/flipper +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4cf7a03cb6776ec0af41b6a50988aa70e5c9cc3c diff --git a/plugin/modules/promise b/plugin/modules/promise deleted file mode 160000 index 7fb09d10..00000000 --- a/plugin/modules/promise +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 7fb09d103f4a680cbd61d5348ec9c5d50244a8e0 diff --git a/plugin/modules/roact b/plugin/modules/roact deleted file mode 160000 index f7d2f1ce..00000000 --- a/plugin/modules/roact +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f7d2f1ce1dd69120f457c2f8032bb184eb8f0c29 diff --git a/plugin/modules/t b/plugin/modules/t deleted file mode 160000 index f643b506..00000000 --- a/plugin/modules/t +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f643b50682c24ec8d6ac3e11f41ee8cbbb2bcecb diff --git a/plugin/modules/testez b/plugin/modules/testez deleted file mode 160000 index 25d957d4..00000000 --- a/plugin/modules/testez +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 25d957d4d5c4c02a52843ef43e72f21f973c2908 diff --git a/plugin/run-tests.server.lua b/plugin/run-tests.server.lua index a9ebcdf6..7637d12f 100644 --- a/plugin/run-tests.server.lua +++ b/plugin/run-tests.server.lua @@ -1,6 +1,6 @@ local ReplicatedStorage = game:GetService("ReplicatedStorage") -local TestEZ = require(ReplicatedStorage.TestEZ) +local TestEZ = require(ReplicatedStorage.Packages.TestEZ) local Rojo = ReplicatedStorage.Rojo @@ -16,4 +16,4 @@ require(Rojo.Plugin.runTests)(TestEZ) if setDevSettings then DevSettings:resetValues() -end \ No newline at end of file +end diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 40af8058..78f54fed 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -1,6 +1,7 @@ -local Http = require(script.Parent.Parent.Http) -local Log = require(script.Parent.Parent.Log) -local Promise = require(script.Parent.Parent.Promise) +local Packages = script.Parent.Parent.Packages +local Http = require(Packages.Http) +local Log = require(Packages.Log) +local Promise = require(Packages.Promise) local Config = require(script.Parent.Config) local Types = require(script.Parent.Types) @@ -85,7 +86,7 @@ local ApiContext = {} ApiContext.__index = ApiContext function ApiContext.new(baseUrl) - assert(type(baseUrl) == "string") + assert(type(baseUrl) == "string", "baseUrl must be a string") local self = { __baseUrl = baseUrl, @@ -248,4 +249,4 @@ function ApiContext:open(id) end) end -return ApiContext \ No newline at end of file +return ApiContext diff --git a/plugin/src/App/Components/BorderedContainer.lua b/plugin/src/App/Components/BorderedContainer.lua index 78ceb426..73fd2bf1 100644 --- a/plugin/src/App/Components/BorderedContainer.lua +++ b/plugin/src/App/Components/BorderedContainer.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Theme = require(Plugin.App.Theme) local Assets = require(Plugin.Assets) @@ -38,4 +39,4 @@ local function BorderedContainer(props) end) end -return BorderedContainer \ No newline at end of file +return BorderedContainer diff --git a/plugin/src/App/Components/Checkbox.lua b/plugin/src/App/Components/Checkbox.lua index 21c2c544..631164ee 100644 --- a/plugin/src/App/Components/Checkbox.lua +++ b/plugin/src/App/Components/Checkbox.lua @@ -1,8 +1,9 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) -local Flipper = require(Rojo.Flipper) +local Roact = require(Packages.Roact) +local Flipper = require(Packages.Flipper) local Assets = require(Plugin.Assets) local Theme = require(Plugin.App.Theme) @@ -93,4 +94,4 @@ function Checkbox:render() end) end -return Checkbox \ No newline at end of file +return Checkbox diff --git a/plugin/src/App/Components/Header.lua b/plugin/src/App/Components/Header.lua index fdc5e5d1..ca6acecf 100644 --- a/plugin/src/App/Components/Header.lua +++ b/plugin/src/App/Components/Header.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Theme = require(Plugin.App.Theme) local Assets = require(Plugin.Assets) @@ -52,4 +53,4 @@ local function Header(props) end) end -return Header \ No newline at end of file +return Header diff --git a/plugin/src/App/Components/IconButton.lua b/plugin/src/App/Components/IconButton.lua index 388a1fe0..18e914a6 100644 --- a/plugin/src/App/Components/IconButton.lua +++ b/plugin/src/App/Components/IconButton.lua @@ -1,8 +1,9 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) -local Flipper = require(Rojo.Flipper) +local Roact = require(Packages.Roact) +local Flipper = require(Packages.Flipper) local Assets = require(Plugin.Assets) local bindingUtil = require(Plugin.App.bindingUtil) @@ -76,4 +77,4 @@ function IconButton:render() }) end -return IconButton \ No newline at end of file +return IconButton diff --git a/plugin/src/App/Components/ScrollingFrame.lua b/plugin/src/App/Components/ScrollingFrame.lua index 87d10226..2231aacb 100644 --- a/plugin/src/App/Components/ScrollingFrame.lua +++ b/plugin/src/App/Components/ScrollingFrame.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Assets = require(Plugin.Assets) local Theme = require(Plugin.App.Theme) @@ -39,4 +40,4 @@ local function ScrollingFrame(props) end) end -return ScrollingFrame \ No newline at end of file +return ScrollingFrame diff --git a/plugin/src/App/Components/SlicedImage.lua b/plugin/src/App/Components/SlicedImage.lua index 8c03c877..40279cc8 100644 --- a/plugin/src/App/Components/SlicedImage.lua +++ b/plugin/src/App/Components/SlicedImage.lua @@ -1,6 +1,7 @@ local Rojo = script:FindFirstAncestor("Rojo") +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local e = Roact.createElement @@ -26,4 +27,4 @@ local function SlicedImage(props) }, props[Roact.Children]) end -return SlicedImage \ No newline at end of file +return SlicedImage diff --git a/plugin/src/App/Components/Spinner.lua b/plugin/src/App/Components/Spinner.lua index 562bd679..f09ea776 100644 --- a/plugin/src/App/Components/Spinner.lua +++ b/plugin/src/App/Components/Spinner.lua @@ -2,8 +2,9 @@ local RunService = game:GetService("RunService") local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Theme = require(Plugin.App.Theme) local Assets = require(Plugin.Assets) @@ -63,4 +64,4 @@ function Spinner:willUnmount() self.stepper:Disconnect() end -return Spinner \ No newline at end of file +return Spinner diff --git a/plugin/src/App/Components/Studio/StudioPluginAction.lua b/plugin/src/App/Components/Studio/StudioPluginAction.lua index 458bd4fc..3738d779 100644 --- a/plugin/src/App/Components/Studio/StudioPluginAction.lua +++ b/plugin/src/App/Components/Studio/StudioPluginAction.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Dictionary = require(Plugin.Dictionary) diff --git a/plugin/src/App/Components/Studio/StudioPluginContext.lua b/plugin/src/App/Components/Studio/StudioPluginContext.lua index 978f628f..a04f59d8 100644 --- a/plugin/src/App/Components/Studio/StudioPluginContext.lua +++ b/plugin/src/App/Components/Studio/StudioPluginContext.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local StudioPluginContext = Roact.createContext(nil) -return StudioPluginContext \ No newline at end of file +return StudioPluginContext diff --git a/plugin/src/App/Components/Studio/StudioPluginGui.lua b/plugin/src/App/Components/Studio/StudioPluginGui.lua index 6bd37511..e078572b 100644 --- a/plugin/src/App/Components/Studio/StudioPluginGui.lua +++ b/plugin/src/App/Components/Studio/StudioPluginGui.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Dictionary = require(Plugin.Dictionary) @@ -81,4 +82,4 @@ local function StudioPluginGuiWrapper(props) }) end -return StudioPluginGuiWrapper \ No newline at end of file +return StudioPluginGuiWrapper diff --git a/plugin/src/App/Components/Studio/StudioToggleButton.lua b/plugin/src/App/Components/Studio/StudioToggleButton.lua index 1adde586..8c7ed59e 100644 --- a/plugin/src/App/Components/Studio/StudioToggleButton.lua +++ b/plugin/src/App/Components/Studio/StudioToggleButton.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Dictionary = require(Plugin.Dictionary) diff --git a/plugin/src/App/Components/Studio/StudioToolbar.lua b/plugin/src/App/Components/Studio/StudioToolbar.lua index c03b20c0..34fd7aa0 100644 --- a/plugin/src/App/Components/Studio/StudioToolbar.lua +++ b/plugin/src/App/Components/Studio/StudioToolbar.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Dictionary = require(Plugin.Dictionary) @@ -42,4 +43,4 @@ local function StudioToolbarWrapper(props) }) end -return StudioToolbarWrapper \ No newline at end of file +return StudioToolbarWrapper diff --git a/plugin/src/App/Components/Studio/StudioToolbarContext.lua b/plugin/src/App/Components/Studio/StudioToolbarContext.lua index 925b7e0c..4dcba1dd 100644 --- a/plugin/src/App/Components/Studio/StudioToolbarContext.lua +++ b/plugin/src/App/Components/Studio/StudioToolbarContext.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local StudioToolbarContext = Roact.createContext(nil) -return StudioToolbarContext \ No newline at end of file +return StudioToolbarContext diff --git a/plugin/src/App/Components/TextButton.lua b/plugin/src/App/Components/TextButton.lua index e4e97e71..d33ddf9f 100644 --- a/plugin/src/App/Components/TextButton.lua +++ b/plugin/src/App/Components/TextButton.lua @@ -2,9 +2,10 @@ local TextService = game:GetService("TextService") local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) -local Flipper = require(Rojo.Flipper) +local Roact = require(Packages.Roact) +local Flipper = require(Packages.Flipper) local Theme = require(Plugin.App.Theme) local Assets = require(Plugin.Assets) @@ -134,4 +135,4 @@ function TextButton:render() end) end -return TextButton \ No newline at end of file +return TextButton diff --git a/plugin/src/App/Components/TouchRipple.lua b/plugin/src/App/Components/TouchRipple.lua index 955d0716..24ded570 100644 --- a/plugin/src/App/Components/TouchRipple.lua +++ b/plugin/src/App/Components/TouchRipple.lua @@ -1,8 +1,9 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) -local Flipper = require(Rojo.Flipper) +local Roact = require(Packages.Roact) +local Flipper = require(Packages.Flipper) local Assets = require(Plugin.Assets) local bindingUtil = require(Plugin.App.bindingUtil) @@ -142,4 +143,4 @@ function TouchRipple:render() }) end -return TouchRipple \ No newline at end of file +return TouchRipple diff --git a/plugin/src/App/Notifications.lua b/plugin/src/App/Notifications.lua index 97be8b45..5e1b0882 100644 --- a/plugin/src/App/Notifications.lua +++ b/plugin/src/App/Notifications.lua @@ -3,9 +3,10 @@ local StudioService = game:GetService("StudioService") local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) -local Flipper = require(Rojo.Flipper) +local Roact = require(Packages.Roact) +local Flipper = require(Packages.Flipper) local bindingUtil = require(script.Parent.bindingUtil) diff --git a/plugin/src/App/Page.lua b/plugin/src/App/Page.lua index 99b5a942..61387e21 100644 --- a/plugin/src/App/Page.lua +++ b/plugin/src/App/Page.lua @@ -1,8 +1,9 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) -local Flipper = require(Rojo.Flipper) +local Roact = require(Packages.Roact) +local Flipper = require(Packages.Flipper) local Dictionary = require(Plugin.Dictionary) @@ -67,4 +68,4 @@ function Page:didUpdate(lastProps) end end -return Page \ No newline at end of file +return Page diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index 5793c6ba..58884128 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Theme = require(Plugin.App.Theme) local Assets = require(Plugin.Assets) @@ -122,4 +123,4 @@ function ConnectedPage.getDerivedStateFromProps(props) } end -return ConnectedPage \ No newline at end of file +return ConnectedPage diff --git a/plugin/src/App/StatusPages/Connecting.lua b/plugin/src/App/StatusPages/Connecting.lua index e45c3c53..b32b37bd 100644 --- a/plugin/src/App/StatusPages/Connecting.lua +++ b/plugin/src/App/StatusPages/Connecting.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Spinner = require(Plugin.App.Components.Spinner) @@ -17,4 +18,4 @@ function ConnectingPage:render() }) end -return ConnectingPage \ No newline at end of file +return ConnectingPage diff --git a/plugin/src/App/StatusPages/Error.lua b/plugin/src/App/StatusPages/Error.lua index 01ad1091..15fe5446 100644 --- a/plugin/src/App/StatusPages/Error.lua +++ b/plugin/src/App/StatusPages/Error.lua @@ -2,8 +2,9 @@ local TextService = game:GetService("TextService") local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Theme = require(Plugin.App.Theme) @@ -150,4 +151,4 @@ function ErrorPage.getDerivedStateFromProps(props) } end -return ErrorPage \ No newline at end of file +return ErrorPage diff --git a/plugin/src/App/StatusPages/NotConnected.lua b/plugin/src/App/StatusPages/NotConnected.lua index 7cc7abfc..08684b55 100644 --- a/plugin/src/App/StatusPages/NotConnected.lua +++ b/plugin/src/App/StatusPages/NotConnected.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Config = require(Plugin.Config) @@ -148,4 +149,4 @@ function NotConnectedPage:render() }) end -return NotConnectedPage \ No newline at end of file +return NotConnectedPage diff --git a/plugin/src/App/StatusPages/Settings/Setting.lua b/plugin/src/App/StatusPages/Settings/Setting.lua index 89fc8ad5..da6bf50a 100644 --- a/plugin/src/App/StatusPages/Settings/Setting.lua +++ b/plugin/src/App/StatusPages/Settings/Setting.lua @@ -2,8 +2,9 @@ local TextService = game:GetService("TextService") local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Settings = require(Plugin.Settings) local Theme = require(Plugin.App.Theme) diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua index 4ffe226e..69fc16f9 100644 --- a/plugin/src/App/StatusPages/Settings/init.lua +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) +local Roact = require(Packages.Roact) local Assets = require(Plugin.Assets) local Theme = require(Plugin.App.Theme) diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index d27a2ecb..1ba2c35c 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -16,9 +16,10 @@ local function getStudio() end local Rojo = script:FindFirstAncestor("Rojo") +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) -local Log = require(Rojo.Log) +local Roact = require(Packages.Roact) +local Log = require(Packages.Log) local strict = require(script.Parent.Parent.strict) diff --git a/plugin/src/App/bindingUtil.lua b/plugin/src/App/bindingUtil.lua index daabd711..3797871e 100644 --- a/plugin/src/App/bindingUtil.lua +++ b/plugin/src/App/bindingUtil.lua @@ -1,7 +1,8 @@ local Rojo = script:FindFirstAncestor("Rojo") +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) -local Log = require(Rojo.Log) +local Roact = require(Packages.Roact) +local Log = require(Packages.Log) local LERP_DATA_TYPES = { Color3 = true, @@ -55,4 +56,4 @@ return { mapLerp = mapLerp, deriveProperty = deriveProperty, blendAlpha = blendAlpha, -} \ No newline at end of file +} diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 9693220b..b477dd36 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -1,8 +1,9 @@ local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin +local Packages = Rojo.Packages -local Roact = require(Rojo.Roact) -local Log = require(Rojo.Log) +local Roact = require(Packages.Roact) +local Log = require(Packages.Log) local Assets = require(Plugin.Assets) local Version = require(Plugin.Version) diff --git a/plugin/src/ChangeBatcher/createPatchSet.lua b/plugin/src/ChangeBatcher/createPatchSet.lua index e4c0fc0a..d418bb4d 100644 --- a/plugin/src/ChangeBatcher/createPatchSet.lua +++ b/plugin/src/ChangeBatcher/createPatchSet.lua @@ -5,7 +5,8 @@ of instances) and return the patch. ]] -local Log = require(script.Parent.Parent.Parent.Log) +local Packages = script.Parent.Parent.Parent.Packages +local Log = require(Packages.Log) local PatchSet = require(script.Parent.Parent.PatchSet) diff --git a/plugin/src/ChangeBatcher/encodePatchUpdate.lua b/plugin/src/ChangeBatcher/encodePatchUpdate.lua index a3af8069..36888a88 100644 --- a/plugin/src/ChangeBatcher/encodePatchUpdate.lua +++ b/plugin/src/ChangeBatcher/encodePatchUpdate.lua @@ -1,5 +1,6 @@ -local Log = require(script.Parent.Parent.Parent.Log) -local RbxDom = require(script.Parent.Parent.Parent.RbxDom) +local Packages = script.Parent.Parent.Parent.Packages +local Log = require(Packages.Log) +local RbxDom = require(Packages.RbxDom) local encodeProperty = require(script.Parent.encodeProperty) diff --git a/plugin/src/ChangeBatcher/encodeProperty.lua b/plugin/src/ChangeBatcher/encodeProperty.lua index e6ad95a2..52710e16 100644 --- a/plugin/src/ChangeBatcher/encodeProperty.lua +++ b/plugin/src/ChangeBatcher/encodeProperty.lua @@ -1,5 +1,6 @@ -local Log = require(script.Parent.Parent.Parent.Log) -local RbxDom = require(script.Parent.Parent.Parent.RbxDom) +local Packages = script.Parent.Parent.Parent.Packages +local Log = require(Packages.Log) +local RbxDom = require(Packages.RbxDom) return function(instance, propertyName, propertyDescriptor) local readSuccess, readResult = propertyDescriptor:read(instance) diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 2d9cbffb..5621e9be 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -1,6 +1,7 @@ local RunService = game:GetService("RunService") -local Log = require(script.Parent.Parent.Log) +local Packages = script.Parent.Parent.Packages +local Log = require(Packages.Log) --[[ A bidirectional map between instance IDs and Roblox instances. It lets us diff --git a/plugin/src/PatchSet.lua b/plugin/src/PatchSet.lua index d8fde747..fac6f945 100644 --- a/plugin/src/PatchSet.lua +++ b/plugin/src/PatchSet.lua @@ -3,7 +3,8 @@ patch returned from the API. ]] -local t = require(script.Parent.Parent.t) +local Packages = script.Parent.Parent.Packages +local t = require(Packages.t) local Types = require(script.Parent.Types) @@ -181,4 +182,4 @@ function PatchSet.humanSummary(instanceMap, patchSet) return table.concat(statements, "\n") end -return PatchSet \ No newline at end of file +return PatchSet diff --git a/plugin/src/Reconciler/Error.lua b/plugin/src/Reconciler/Error.lua index 5833420a..1e65c854 100644 --- a/plugin/src/Reconciler/Error.lua +++ b/plugin/src/Reconciler/Error.lua @@ -2,7 +2,8 @@ Defines the errors that can be returned by the reconciler. ]] -local Fmt = require(script.Parent.Parent.Parent.Fmt) +local Packages = script.Parent.Parent.Parent.Packages +local Fmt = require(Packages.Fmt) local Error = {} @@ -34,4 +35,4 @@ function Error:__tostring() return Fmt.fmt("Error({}): {:#?}", self.kind, self.details) end -return Error \ No newline at end of file +return Error diff --git a/plugin/src/Reconciler/applyPatch.lua b/plugin/src/Reconciler/applyPatch.lua index 4ecf3e1f..a625ebe9 100644 --- a/plugin/src/Reconciler/applyPatch.lua +++ b/plugin/src/Reconciler/applyPatch.lua @@ -5,7 +5,8 @@ Patches can come from the server or be generated by the client. ]] -local Log = require(script.Parent.Parent.Parent.Log) +local Packages = script.Parent.Parent.Parent.Packages +local Log = require(Packages.Log) local PatchSet = require(script.Parent.Parent.PatchSet) local Types = require(script.Parent.Parent.Types) diff --git a/plugin/src/Reconciler/decodeValue.lua b/plugin/src/Reconciler/decodeValue.lua index 0fe7bf59..64c33ace 100644 --- a/plugin/src/Reconciler/decodeValue.lua +++ b/plugin/src/Reconciler/decodeValue.lua @@ -3,7 +3,8 @@ usable by Rojo's reconciler, potentially using RbxDom. ]] -local RbxDom = require(script.Parent.Parent.Parent.RbxDom) +local Packages = script.Parent.Parent.Parent.Packages +local RbxDom = require(Packages.RbxDom) local Error = require(script.Parent.Error) local function decodeValue(encodedValue, instanceMap) @@ -38,4 +39,4 @@ local function decodeValue(encodedValue, instanceMap) return true, decodedValue end -return decodeValue \ No newline at end of file +return decodeValue diff --git a/plugin/src/Reconciler/diff.lua b/plugin/src/Reconciler/diff.lua index e4cb7d88..995d06d8 100644 --- a/plugin/src/Reconciler/diff.lua +++ b/plugin/src/Reconciler/diff.lua @@ -3,7 +3,9 @@ patch that can be later applied. ]] -local Log = require(script.Parent.Parent.Parent.Log) +local Packages = script.Parent.Parent.Parent.Packages +local Log = require(Packages.Log) + local invariant = require(script.Parent.Parent.invariant) local getProperty = require(script.Parent.getProperty) local Error = require(script.Parent.Error) @@ -152,4 +154,4 @@ local function diff(instanceMap, virtualInstances, rootId) return true, patch end -return diff \ No newline at end of file +return diff diff --git a/plugin/src/Reconciler/diff.spec.lua b/plugin/src/Reconciler/diff.spec.lua index 7618eea9..cc596eaa 100644 --- a/plugin/src/Reconciler/diff.spec.lua +++ b/plugin/src/Reconciler/diff.spec.lua @@ -1,5 +1,6 @@ return function() - local Log = require(script.Parent.Parent.Parent.Log) + local Packages = script.Parent.Parent.Parent.Packages + local Log = require(Packages.Log) local InstanceMap = require(script.Parent.Parent.InstanceMap) local PatchSet = require(script.Parent.Parent.PatchSet) @@ -286,4 +287,4 @@ return function() expect(size(patch.added)).to.equal(1) expect(patch.added["CHILD"]).to.equal(virtualInstances["CHILD"]) end) -end \ No newline at end of file +end diff --git a/plugin/src/Reconciler/getProperty.lua b/plugin/src/Reconciler/getProperty.lua index cd5c11f3..cd70fa24 100644 --- a/plugin/src/Reconciler/getProperty.lua +++ b/plugin/src/Reconciler/getProperty.lua @@ -2,7 +2,8 @@ Attempts to read a property from the given instance. ]] -local RbxDom = require(script.Parent.Parent.Parent.RbxDom) +local Packages = script.Parent.Parent.Parent.Packages +local RbxDom = require(Packages.RbxDom) local Error = require(script.Parent.Error) local function getProperty(instance, propertyName) @@ -56,4 +57,4 @@ local function getProperty(instance, propertyName) return true, valueOrErr end -return getProperty \ No newline at end of file +return getProperty diff --git a/plugin/src/Reconciler/setProperty.lua b/plugin/src/Reconciler/setProperty.lua index 316f920e..211a1491 100644 --- a/plugin/src/Reconciler/setProperty.lua +++ b/plugin/src/Reconciler/setProperty.lua @@ -2,8 +2,9 @@ Attempts to set a property on the given instance. ]] -local RbxDom = require(script.Parent.Parent.Parent.RbxDom) -local Log = require(script.Parent.Parent.Parent.Log) +local Packages = script.Parent.Parent.Parent.Packages +local Log = require(Packages.Log) +local RbxDom = require(Packages.RbxDom) local Error = require(script.Parent.Error) local function setProperty(instance, propertyName, value) @@ -45,4 +46,4 @@ local function setProperty(instance, propertyName, value) return true end -return setProperty \ No newline at end of file +return setProperty diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index ec6de75e..5ea3b11f 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -1,9 +1,10 @@ local StudioService = game:GetService("StudioService") local RunService = game:GetService("RunService") -local Log = require(script.Parent.Parent.Log) -local Fmt = require(script.Parent.Parent.Fmt) -local t = require(script.Parent.Parent.t) +local Packages = script.Parent.Parent.Packages +local Log = require(Packages.Log) +local Fmt = require(Packages.Fmt) +local t = require(Packages.t) local ChangeBatcher = require(script.Parent.ChangeBatcher) local InstanceMap = require(script.Parent.InstanceMap) diff --git a/plugin/src/Settings.lua b/plugin/src/Settings.lua index 6513d41c..206ed3e7 100644 --- a/plugin/src/Settings.lua +++ b/plugin/src/Settings.lua @@ -4,8 +4,9 @@ local plugin = plugin or script:FindFirstAncestorWhichIsA("Plugin") local Rojo = script:FindFirstAncestor("Rojo") +local Packages = Rojo.Packages -local Log = require(Rojo.Log) +local Log = require(Packages.Log) local defaultSettings = { openScriptsExternally = false, diff --git a/plugin/src/Types.lua b/plugin/src/Types.lua index ebd8efe1..ee66d520 100644 --- a/plugin/src/Types.lua +++ b/plugin/src/Types.lua @@ -1,5 +1,5 @@ -local t = require(script.Parent.Parent.t) - +local Packages = script.Parent.Parent.Packages +local t = require(Packages.t) local DevSettings = require(script.Parent.DevSettings) local strict = require(script.Parent.strict) diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index 43c271c1..564ebbd7 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -2,19 +2,20 @@ if not plugin then return end -local Log = require(script.Parent.Log) +local Rojo = script:FindFirstAncestor("Rojo") +local Packages = Rojo.Packages + +local Log = require(Packages.Log) +local Roact = require(Packages.Roact) local DevSettings = require(script.DevSettings) +local Config = require(script.Config) +local App = require(script.App) Log.setLogLevelThunk(function() return DevSettings:getLogLevel() end) -local Roact = require(script.Parent.Roact) - -local Config = require(script.Config) -local App = require(script.App) - local app = Roact.createElement(App, { plugin = plugin }) diff --git a/plugin/src/invariant.lua b/plugin/src/invariant.lua index 7cb813b4..37f4d756 100644 --- a/plugin/src/invariant.lua +++ b/plugin/src/invariant.lua @@ -1,4 +1,6 @@ -local Fmt = require(script.Parent.Parent.Fmt) + +local Packages = script.Parent.Parent.Packages +local Fmt = require(Packages.Fmt) local Config = require(script.Parent.Config) @@ -26,4 +28,4 @@ else end end -return invariant \ No newline at end of file +return invariant diff --git a/plugin/src/preloadAssets.lua b/plugin/src/preloadAssets.lua index edbc37d7..c37ca032 100644 --- a/plugin/src/preloadAssets.lua +++ b/plugin/src/preloadAssets.lua @@ -1,6 +1,7 @@ local ContentProvider = game:GetService("ContentProvider") -local Log = require(script.Parent.Parent.Log) +local Packages = script.Parent.Parent.Packages +local Log = require(Packages.Log) local Assets = require(script.Parent.Assets) @@ -29,4 +30,4 @@ local function preloadAssets() end)() end -return preloadAssets \ No newline at end of file +return preloadAssets diff --git a/plugin/src/runTests.lua b/plugin/src/runTests.lua index ea6172c2..b2c7e231 100644 --- a/plugin/src/runTests.lua +++ b/plugin/src/runTests.lua @@ -1,5 +1,6 @@ return function(TestEZ) local Rojo = script.Parent.Parent + local Packages = Rojo.Packages - TestEZ.TestBootstrap:run({ Rojo.Plugin, Rojo.Http, Rojo.Log }) -end \ No newline at end of file + TestEZ.TestBootstrap:run({ Rojo.Plugin, Packages.Http, Packages.Log, Packages.RbxDom }) +end diff --git a/plugin/src/soundPlayer.lua b/plugin/src/soundPlayer.lua index a58e8364..c1d018c2 100644 --- a/plugin/src/soundPlayer.lua +++ b/plugin/src/soundPlayer.lua @@ -1,13 +1,16 @@ -- Sounds only play in Edit mode when parented to a plugin widget, for some reason local plugin = plugin or script:FindFirstAncestorWhichIsA("Plugin") -local widget = plugin:CreateDockWidgetPluginGui("Rojo_soundPlayer", DockWidgetPluginGuiInfo.new( - Enum.InitialDockState.Float, - false, true, - 10, 10, - 10, 10 -)) -widget.Name = "Rojo_soundPlayer" -widget.Title = "Rojo Sound Player" +local widget = nil +if plugin then + widget = plugin:CreateDockWidgetPluginGui("Rojo_soundPlayer", DockWidgetPluginGuiInfo.new( + Enum.InitialDockState.Float, + false, true, + 10, 10, + 10, 10 + )) + widget.Name = "Rojo_soundPlayer" + widget.Title = "Rojo Sound Player" +end local SoundPlayer = {} SoundPlayer.__index = SoundPlayer diff --git a/plugin/test-place.project.json b/plugin/test-place.project.json index b75fcaae..9ac37f8b 100644 --- a/plugin/test-place.project.json +++ b/plugin/test-place.project.json @@ -8,8 +8,8 @@ "$path": "default.project.json" }, - "TestEZ": { - "$path": "modules/testez" + "Packages": { + "$path": "DevPackages" } }, diff --git a/plugin/wally.lock b/plugin/wally.lock new file mode 100644 index 00000000..e5c3f47c --- /dev/null +++ b/plugin/wally.lock @@ -0,0 +1,33 @@ +# This file is automatically @generated by Wally. +# It is not intended for manual editing. +registry = "test" + +[[package]] +name = "evaera/promise" +version = "4.0.0" +dependencies = [] + +[[package]] +name = "osyrisrblx/t" +version = "3.0.0" +dependencies = [] + +[[package]] +name = "reselim/flipper" +version = "2.0.0" +dependencies = [] + +[[package]] +name = "roblox/roact" +version = "1.4.4" +dependencies = [] + +[[package]] +name = "roblox/testez" +version = "0.4.1" +dependencies = [] + +[[package]] +name = "rojo-rbx/rojo" +version = "7.2.1" +dependencies = [["Flipper", "reselim/flipper@2.0.0"], ["Promise", "evaera/promise@4.0.0"], ["Roact", "roblox/roact@1.4.4"], ["t", "osyrisrblx/t@3.0.0"]] diff --git a/plugin/wally.toml b/plugin/wally.toml new file mode 100644 index 00000000..31ef5662 --- /dev/null +++ b/plugin/wally.toml @@ -0,0 +1,17 @@ +[package] +name = "rojo-rbx/rojo" +description = "Rojo enables Roblox developers to use professional-grade software engineering tools" +version = "7.2.1" +license = "MPL-2.0" +authors = ["LPGhatguy (https://lpg.space/)"] +registry = "https://github.com/upliftgames/wally-index" +realm = "shared" + +[dependencies] +Flipper = "reselim/flipper@2.0.0" +Promise = "evaera/promise@4.0.0" +Roact = "roblox/roact@1.4.4" +t = "osyrisrblx/t@3.0.0" + +[dev-dependencies] +TestEZ = "roblox/testez@0.4.1" From eb5c897ac01e9af07553112c9aea034d6718f4c1 Mon Sep 17 00:00:00 2001 From: Boegie19 <34578426+Boegie19@users.noreply.github.com> Date: Thu, 4 Aug 2022 00:38:08 +0200 Subject: [PATCH 1249/1504] fix relevant_paths not being set for init.csv (#599) * fix relevant_paths not being set for init.csv * fix failing tests Co-authored-by: Lucien Greathouse --- src/snapshot_middleware/dir.rs | 1 + .../librojo__snapshot_middleware__dir__test__empty_folder.snap | 2 ++ ...rojo__snapshot_middleware__dir__test__folder_in_folder.snap | 3 +++ 3 files changed, 6 insertions(+) diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index 46fff335..ba63301c 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -87,6 +87,7 @@ pub fn snapshot_dir_no_meta( path.join("init.server.luau"), path.join("init.client.lua"), path.join("init.client.luau"), + path.join("init.csv"), ]; let snapshot = InstanceSnapshot::new() diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap index 246f9de7..948dda0b 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap @@ -1,5 +1,6 @@ --- source: src/snapshot_middleware/dir.rs +assertion_line: 127 expression: instance_snapshot --- snapshot_id: ~ @@ -16,6 +17,7 @@ metadata: - /foo/init.server.luau - /foo/init.client.lua - /foo/init.client.luau + - /foo/init.csv context: {} name: foo class_name: Folder diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap index cd437643..cf07b0ed 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap @@ -1,5 +1,6 @@ --- source: src/snapshot_middleware/dir.rs +assertion_line: 148 expression: instance_snapshot --- snapshot_id: ~ @@ -16,6 +17,7 @@ metadata: - /foo/init.server.luau - /foo/init.client.lua - /foo/init.client.luau + - /foo/init.csv context: {} name: foo class_name: Folder @@ -35,6 +37,7 @@ children: - /foo/Child/init.server.luau - /foo/Child/init.client.lua - /foo/Child/init.client.luau + - /foo/Child/init.csv context: {} name: Child class_name: Folder From e110f3726a99c9ec44d711e9eecc5f8411c4260f Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 3 Aug 2022 15:58:28 -0700 Subject: [PATCH 1250/1504] Real-time status about sync details (#569) * Rough prototype of patch info display * Remove extra newline * Switch to binding * Update slower for older timestamps * Batch patches within a second of each other * Fix indentation * Less wasteful refresh hz * More apt variable name Co-authored-by: Lucien Greathouse --- plugin/src/App/StatusPages/Connected.lua | 92 ++++++++++++++++++------ plugin/src/App/init.lua | 43 +++++++++++ plugin/src/ServeSession.lua | 13 ++++ 3 files changed, 125 insertions(+), 23 deletions(-) diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index 58884128..810ce095 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -13,6 +13,26 @@ local BorderedContainer = require(Plugin.App.Components.BorderedContainer) local e = Roact.createElement +local AGE_UNITS = { {31556909, "year"}, {2629743, "month"}, {604800, "week"}, {86400, "day"}, {3600, "hour"}, {60, "minute"}, } +function timeSinceText(elapsed: number): string + if elapsed < 3 then + return "just now" + end + + local ageText = string.format("%d seconds ago", elapsed) + + for _,UnitData in ipairs(AGE_UNITS) do + local UnitSeconds, UnitName = UnitData[1], UnitData[2] + if elapsed > UnitSeconds then + local c = math.floor(elapsed/UnitSeconds) + ageText = string.format("%d %s%s ago", c, UnitName, c>1 and "s" or "") + break + end + end + + return ageText +end + local function ConnectionDetails(props) return Theme.with(function(theme) return e(BorderedContainer, { @@ -83,33 +103,59 @@ end local ConnectedPage = Roact.Component:extend("ConnectedPage") function ConnectedPage:render() - return Roact.createFragment({ - Header = e(Header, { - transparency = self.props.transparency, - layoutOrder = 1, - }), + return Theme.with(function(theme) + return Roact.createFragment({ + Header = e(Header, { + transparency = self.props.transparency, + layoutOrder = 1, + }), - ConnectionDetails = e(ConnectionDetails, { - projectName = self.state.projectName, - address = self.state.address, - transparency = self.props.transparency, - layoutOrder = 2, + ConnectionDetails = e(ConnectionDetails, { + projectName = self.state.projectName, + address = self.state.address, + transparency = self.props.transparency, + layoutOrder = 2, - onDisconnect = self.props.onDisconnect, - }), + onDisconnect = self.props.onDisconnect, + }), - Layout = e("UIListLayout", { - VerticalAlignment = Enum.VerticalAlignment.Center, - FillDirection = Enum.FillDirection.Vertical, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 10), - }), + Info = e("TextLabel", { + Text = self.props.patchInfo:map(function(info) + return string.format( + "Synced %d change%s %s", + info.changes, + info.changes == 1 and "" or "s", + timeSinceText(os.time() - info.timestamp) + ) + end), + Font = Enum.Font.Gotham, + TextSize = 14, + TextWrapped = true, + RichText = true, + TextColor3 = theme.Header.VersionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextYAlignment = Enum.TextYAlignment.Top, + TextTransparency = self.props.transparency, - Padding = e("UIPadding", { - PaddingLeft = UDim.new(0, 20), - PaddingRight = UDim.new(0, 20), - }), - }) + Size = UDim2.new(1, 0, 0, 28), + + LayoutOrder = 3, + BackgroundTransparency = 1, + }), + + Layout = e("UIListLayout", { + VerticalAlignment = Enum.VerticalAlignment.Center, + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 10), + }), + + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 20), + PaddingRight = UDim.new(0, 20), + }), + }) + end) end function ConnectedPage.getDerivedStateFromProps(props) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index b477dd36..70ece3df 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -43,6 +43,10 @@ function App:init() self.host, self.setHost = Roact.createBinding("") self.port, self.setPort = Roact.createBinding("") + self.patchInfo, self.setPatchInfo = Roact.createBinding({ + changes = 0, + timestamp = os.time(), + }) self:setState({ appStatus = AppStatus.NotConnected, @@ -105,6 +109,34 @@ function App:startSession() twoWaySync = sessionOptions.twoWaySync, }) + serveSession:onPatchApplied(function(patch, unapplied) + local now = os.time() + local changes = 0 + + for _, set in patch do + for _ in set do + changes += 1 + end + end + for _, set in unapplied do + for _ in set do + changes -= 1 + end + end + + if changes == 0 then return end + + local old = self.patchInfo:getValue() + if now - old.timestamp < 2 then + changes += old.changes + end + + self.setPatchInfo({ + changes = changes, + timestamp = now, + }) + end) + serveSession:onStatusChanged(function(status, details) if status == ServeSession.Status.Connecting then self:setState({ @@ -148,6 +180,16 @@ function App:startSession() serveSession:start() self.serveSession = serveSession + + task.defer(function() + while self.serveSession == serveSession do + -- Trigger rerender to update timestamp text + local patchInfo = table.clone(self.patchInfo:getValue()) + self.setPatchInfo(patchInfo) + local elapsed = os.time() - patchInfo.timestamp + task.wait(elapsed < 60 and 1 or elapsed/5) + end + end) end function App:endSession() @@ -231,6 +273,7 @@ function App:render() Connected = createPageElement(AppStatus.Connected, { projectName = self.state.projectName, address = self.state.address, + patchInfo = self.patchInfo, onDisconnect = function() self:endSession() diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 5ea3b11f..90860ff7 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -95,6 +95,7 @@ function ServeSession.new(options) __instanceMap = instanceMap, __changeBatcher = changeBatcher, __statusChangedCallback = nil, + __patchAppliedCallback = nil, __connections = connections, } @@ -122,6 +123,10 @@ function ServeSession:onStatusChanged(callback) self.__statusChangedCallback = callback end +function ServeSession:onPatchApplied(callback) + self.__patchAppliedCallback = callback +end + function ServeSession:start() self:__setStatus(Status.Connecting) @@ -234,6 +239,10 @@ function ServeSession:__initialSync(rootInstanceId) Log.warn("Could not apply all changes requested by the Rojo server:\n{}", PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) end + + if self.__patchAppliedCallback then + pcall(self.__patchAppliedCallback, catchUpPatch, unappliedPatch) + end end) end @@ -247,6 +256,10 @@ function ServeSession:__mainSyncLoop() Log.warn("Could not apply all changes requested by the Rojo server:\n{}", PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) end + + if self.__patchAppliedCallback then + pcall(self.__patchAppliedCallback, message, unappliedPatch) + end end if self.__status ~= Status.Disconnected then From 41d7aaf3237618d41cb753c674908b0a7a4163a5 Mon Sep 17 00:00:00 2001 From: James Onnen Date: Wed, 3 Aug 2022 16:01:07 -0700 Subject: [PATCH 1251/1504] Add uipadding to notifications (#589) --- plugin/src/App/init.lua | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 70ece3df..5de9ffdd 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -316,6 +316,12 @@ function App:render() VerticalAlignment = Enum.VerticalAlignment.Bottom, Padding = UDim.new(0, 5), }), + padding = e("UIPadding", { + PaddingTop = UDim.new(0, 5); + PaddingBottom = UDim.new(0, 5); + PaddingLeft = UDim.new(0, 5); + PaddingRight = UDim.new(0, 5); + }), notifs = e(Notifications, { soundPlayer = self.props.soundPlayer, notifications = self.state.notifications, From 3e83f92532246c011e743e1d6f708837b36b042f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Wed, 3 Aug 2022 19:39:14 -0400 Subject: [PATCH 1252/1504] Update MSRV to 1.58.1 for format string capturing --- .github/workflows/ci.yml | 2 +- Cargo.toml | 2 +- README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 6f4b3c56..cd36ef74 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - rust_version: [stable, 1.57.0] + rust_version: [stable, 1.58.1] steps: - uses: actions/checkout@v3 diff --git a/Cargo.toml b/Cargo.toml index 008501d4..a5261e37 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rojo" version = "7.2.1" -rust-version = "1.57.0" +rust-version = "1.58.1" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" diff --git a/README.md b/README.md index 414ddd74..fb318f3f 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions fo Pull requests are welcome! -Rojo supports Rust 1.57.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. +Rojo supports Rust 1.58.1 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. ## License Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file From d196c5091cb5df6a83bef74b668a0f6dcfe35000 Mon Sep 17 00:00:00 2001 From: Max Date: Wed, 3 Aug 2022 19:07:06 -0500 Subject: [PATCH 1253/1504] Simplify usage of attributes. (#574) * Support implicit values for primitive attributes This commit adds support for strings, numbers, and booleans to be implicitly typed in attribute maps, reducing the redundancy of needing to specify their types. I also quietly adjusted one of the tests to use a more stable class/property pair. Since SourceAssetId is locked to Roblox, it could potentially disappear at any time. * Apply formatting. * Address feedback * Backwards compatible format usage. * Axe UnresolvedValueMap in favor of $attributes Attributes can be defined directly on instances, with support for unambiguous types. * Adjust test. * to_string() -> into() * Made attribute test more concise. * small cleanup * Update src/resolution.rs * Update src/resolution.rs * Update src/resolution.rs * Update src/resolution.rs Co-authored-by: Lucien Greathouse --- .../end_to_end__tests__build__attributes.snap | 17 +++- .../attributes/default.project.json | 80 ++++++++++++++++++- src/project.rs | 7 ++ src/resolution.rs | 36 ++++++++- src/snapshot_middleware/json_model.rs | 15 ++++ src/snapshot_middleware/meta_file.rs | 17 ++++ src/snapshot_middleware/project.rs | 18 +++++ 7 files changed, 184 insertions(+), 6 deletions(-) diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__attributes.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__attributes.snap index d78f8101..04296e4e 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__attributes.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__attributes.snap @@ -1,6 +1,5 @@ --- source: tests/tests/build.rs -assertion_line: 99 expression: contents --- @@ -11,12 +10,24 @@ expression: contents Explicit - AgAAAAUAAABIZWxsbwIFAAAAV29ybGQGAAAAVmVjdG9yEQAAgD8AAABAAABAQA== + DQAAAAQAAABCb29sAwEKAAAAQnJpY2tDb2xvcg4BAAAABgAAAENvbG9yMw8AAAAAAAAAAAAAAAANAAAAQ29sb3JTZXF1ZW5jZRkCAAAAAAAAAAAAAAAAAIA/AACAPwAAgD8AAAAAAACAPwAAgD8AAIA/AACAPwcAAABGbG9hdDMyBQAAAAAHAAAARmxvYXQ2NAYAAAAAAAAAAAsAAABOdW1iZXJSYW5nZRsAAAAAAAAAAA4AAABOdW1iZXJTZXF1ZW5jZRcCAAAAAAAAAAAAAAAAAAAAAAAAAAAAgD8AAAAABAAAAFJlY3QcAAAAAAAAAAAAAAAAAAAAAAQAAABVRGltCQAAAAAAAAAABQAAAFVEaW0yCgAAAAAAAAAAAAAAAAAAAAAHAAAAVmVjdG9yMhAAAAAAAAAAAAcAAABWZWN0b3IzEQAAAAAAAAAAAAAAAA== - ImplicitAttributes + Implicit + AwAAAAQAAABCb29sAwEGAAAATnVtYmVyBgAAAAAAAOA/BgAAAFN0cmluZwIEAAAAVGVzdA== + + + + + LegacyExplicit + AgAAAAUAAABIZWxsbwIFAAAAV29ybGQGAAAAVmVjdG9yEQAAgD8AAABAAABAQA== + + + + + LegacyImplicit AgAAAAMAAABIZXkCBwAAAEdyYW5kbWEGAAAAVmVjdG9yEQAAgEAAAKBAAADAQA== diff --git a/rojo-test/build-tests/attributes/default.project.json b/rojo-test/build-tests/attributes/default.project.json index 44be8f16..b9bb2d95 100644 --- a/rojo-test/build-tests/attributes/default.project.json +++ b/rojo-test/build-tests/attributes/default.project.json @@ -3,7 +3,85 @@ "tree": { "$className": "Folder", + "Implicit": { + "$className": "Folder", + "$attributes": { + "Bool": true, + "Number": 0.5, + "String": "Test" + } + }, + "Explicit": { + "$className": "Folder", + "$attributes": { + "Bool": { + "Bool": true + }, + "Float32": { + "Float32": 0 + }, + "Float64": { + "Float64": 0 + }, + "UDim": { + "UDim": [0, 0] + }, + "UDim2": { + "UDim2": [[0, 0], [0, 0]] + }, + "BrickColor": { + "BrickColor": 1 + }, + "Color3": { + "Color3": [0, 0, 0] + }, + "Vector2": { + "Vector2": [0, 0] + }, + "Vector3": { + "Vector3": [0, 0, 0] + }, + "NumberSequence": { + "NumberSequence": { + "keypoints": [ + { + "time": 0, + "value": 0, + "envelope": 0 + }, + { + "time": 1, + "value": 0, + "envelope": 0 + } + ] + } + }, + "ColorSequence": { + "ColorSequence": { + "keypoints": [ + { + "time": 0, + "color": [1, 1, 1] + }, + { + "time": 1, + "color": [1, 1, 1] + } + ] + } + }, + "NumberRange": { + "NumberRange": [0, 0] + }, + "Rect": { + "Rect": [[0, 0], [0, 0]] + } + } + }, + + "LegacyExplicit": { "$className": "Folder", "$properties": { "Attributes": { @@ -19,7 +97,7 @@ } }, - "ImplicitAttributes": { + "LegacyImplicit": { "$className": "Folder", "$properties": { "Attributes": { diff --git a/src/project.rs b/src/project.rs index 53d52808..330cbd23 100644 --- a/src/project.rs +++ b/src/project.rs @@ -229,6 +229,13 @@ pub struct ProjectNode { )] pub properties: HashMap, + #[serde( + rename = "$attributes", + default, + skip_serializing_if = "HashMap::is_empty" + )] + pub attributes: HashMap, + /// Defines the behavior when Rojo encounters unknown instances in Roblox /// Studio during live sync. `$ignoreUnknownInstances` should be considered /// a large hammer and used with care. diff --git a/src/resolution.rs b/src/resolution.rs index 547e1729..56889145 100644 --- a/src/resolution.rs +++ b/src/resolution.rs @@ -1,6 +1,6 @@ use std::borrow::Borrow; -use anyhow::format_err; +use anyhow::{bail, format_err}; use rbx_dom_weak::types::{ Attributes, CFrame, Color3, Content, Enum, Matrix3, Tags, Variant, VariantType, Vector2, Vector3, @@ -28,6 +28,13 @@ impl UnresolvedValue { UnresolvedValue::Ambiguous(partial) => partial.resolve(class_name, prop_name), } } + + pub fn resolve_unambiguous(self) -> anyhow::Result { + match self { + UnresolvedValue::FullyQualified(full) => Ok(full), + UnresolvedValue::Ambiguous(partial) => partial.resolve_unambiguous(), + } + } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -148,6 +155,16 @@ impl AmbiguousValue { } } + pub fn resolve_unambiguous(self) -> anyhow::Result { + match self { + AmbiguousValue::Bool(value) => Ok(value.into()), + AmbiguousValue::Number(value) => Ok(value.into()), + AmbiguousValue::String(value) => Ok(value.into()), + + other => bail!("Cannot unambiguously resolve the value {other:?}"), + } + } + fn describe(&self) -> &'static str { match self { AmbiguousValue::Bool(_) => "a bool", @@ -218,12 +235,20 @@ mod test { unresolved.resolve(class, prop).unwrap() } + fn resolve_unambiguous(json_value: &str) -> Variant { + let unresolved: UnresolvedValue = serde_json::from_str(json_value).unwrap(); + unresolved.resolve_unambiguous().unwrap() + } + #[test] fn bools() { assert_eq!(resolve("BoolValue", "Value", "false"), Variant::Bool(false)); // Script.Disabled is inherited from BaseScript assert_eq!(resolve("Script", "Disabled", "true"), Variant::Bool(true)); + + assert_eq!(resolve_unambiguous("false"), Variant::Bool(false)); + assert_eq!(resolve_unambiguous("true"), Variant::Bool(true)); } #[test] @@ -247,6 +272,11 @@ mod test { // resolve("Folder", "Tags", "\"a\\u0000b\\u0000c\""), // Variant::BinaryString(b"a\0b\0c".to_vec().into()), // ); + + assert_eq!( + resolve_unambiguous("\"Hello world!\""), + Variant::String("Hello world!".into()), + ); } #[test] @@ -257,12 +287,14 @@ mod test { ); assert_eq!( - resolve("Folder", "SourceAssetId", "532413"), + resolve("IntValue", "Value", "532413"), Variant::Int64(532413), ); assert_eq!(resolve("Part", "Transparency", "1"), Variant::Float32(1.0)); assert_eq!(resolve("NumberValue", "Value", "1"), Variant::Float64(1.0)); + + assert_eq!(resolve_unambiguous("12.5"), Variant::Float64(12.5)); } #[test] diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index c29388c1..0f1388e4 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -2,6 +2,7 @@ use std::{borrow::Cow, collections::HashMap, path::Path, str}; use anyhow::Context; use memofs::Vfs; +use rbx_dom_weak::types::Attributes; use serde::Deserialize; use crate::{ @@ -78,6 +79,9 @@ struct JsonModel { skip_serializing_if = "HashMap::is_empty" )] properties: HashMap, + + #[serde(default = "HashMap::new", skip_serializing_if = "HashMap::is_empty")] + attributes: HashMap, } impl JsonModel { @@ -96,6 +100,17 @@ impl JsonModel { properties.insert(key, value); } + if !self.attributes.is_empty() { + let mut attributes = Attributes::new(); + + for (key, unresolved) in self.attributes { + let value = unresolved.resolve_unambiguous()?; + attributes.insert(key, value); + } + + properties.insert("Attributes".into(), attributes.into()); + } + Ok(InstanceSnapshot { snapshot_id: None, metadata: Default::default(), diff --git a/src/snapshot_middleware/meta_file.rs b/src/snapshot_middleware/meta_file.rs index 2715dbbe..abf53fba 100644 --- a/src/snapshot_middleware/meta_file.rs +++ b/src/snapshot_middleware/meta_file.rs @@ -1,6 +1,7 @@ use std::{borrow::Cow, collections::HashMap, path::PathBuf}; use anyhow::{format_err, Context}; +use rbx_dom_weak::types::Attributes; use serde::{Deserialize, Serialize}; use crate::{resolution::UnresolvedValue, snapshot::InstanceSnapshot}; @@ -78,6 +79,9 @@ pub struct DirectoryMetadata { #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub properties: HashMap, + #[serde(default, skip_serializing_if = "HashMap::is_empty")] + pub attributes: HashMap, + #[serde(skip_serializing_if = "Option::is_none")] pub class_name: Option, @@ -139,6 +143,19 @@ impl DirectoryMetadata { snapshot.properties.insert(key, value); } + if !self.attributes.is_empty() { + let mut attributes = Attributes::new(); + + for (key, unresolved) in self.attributes.drain() { + let value = unresolved.resolve_unambiguous()?; + attributes.insert(key, value); + } + + snapshot + .properties + .insert("Attributes".into(), attributes.into()); + } + Ok(()) } } diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 5650c99a..f8fa7920 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -2,6 +2,7 @@ use std::{borrow::Cow, collections::HashMap, path::Path}; use anyhow::{bail, Context}; use memofs::Vfs; +use rbx_dom_weak::types::Attributes; use rbx_reflection::ClassTag; use crate::{ @@ -231,6 +232,23 @@ pub fn snapshot_project_node( properties.insert(key.clone(), value); } + if !node.attributes.is_empty() { + let mut attributes = Attributes::new(); + + for (key, unresolved) in &node.attributes { + let value = unresolved.clone().resolve_unambiguous().with_context(|| { + format!( + "Unresolvable attribute in project at path {}", + project_path.display() + ) + })?; + + attributes.insert(key.clone(), value); + } + + properties.insert("Attributes".into(), attributes.into()); + } + // If the user specified $ignoreUnknownInstances, overwrite the existing // value. // From e34d2339ad4084b266b8b91dd653599edf3a9784 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 8 Aug 2022 00:14:32 -0400 Subject: [PATCH 1254/1504] Vendor OpenSSL via native-tls-vendored reqwest feature --- Cargo.lock | 10 ++++++++++ Cargo.toml | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 5bed38c0..82e9bb8c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1338,6 +1338,15 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" +[[package]] +name = "openssl-src" +version = "111.22.0+1.1.1q" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f31f0d509d1c1ae9cada2f9539ff8f37933831fd5098879e482aa687d659853" +dependencies = [ + "cc", +] + [[package]] name = "openssl-sys" version = "0.9.74" @@ -1347,6 +1356,7 @@ dependencies = [ "autocfg", "cc", "libc", + "openssl-src", "pkg-config", "vcpkg", ] diff --git a/Cargo.toml b/Cargo.toml index a5261e37..0aa671c2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -73,7 +73,7 @@ log = "0.4.14" maplit = "1.0.2" notify = "4.0.17" opener = "0.5.0" -reqwest = { version = "0.11.10", features = ["blocking", "json"] } +reqwest = { version = "0.11.10", features = ["blocking", "json", "native-tls-vendored"] } ritz = "0.1.0" roblox_install = "1.0.0" serde = { version = "1.0.130", features = ["derive", "rc"] } From d64db329dd9a7cff67cb693fe185a8cb70c26326 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Mon, 8 Aug 2022 00:28:52 -0400 Subject: [PATCH 1255/1504] Fix release workflow to use Wally --- .github/workflows/release.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 251b3140..666cede1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -112,6 +112,17 @@ jobs: override: true profile: minimal + - name: Setup Foreman + uses: Roblox/setup-foreman@v1 + with: + token: ${{ secrets.GITHUB_TOKEN }} + + - name: Install packages + run: | + cd plugin + wally install + cd .. + - name: Build Release run: cargo build --release --locked --verbose env: @@ -152,4 +163,4 @@ jobs: uses: actions/upload-artifact@v3 with: name: ${{ env.BIN }}-${{ env.PROJECT_VERSION }}-${{ matrix.label }}.zip - path: release.zip + path: release.zip \ No newline at end of file From faf767179936b3f1227af6452c67b4150f17e118 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Mon, 8 Aug 2022 00:58:32 -0700 Subject: [PATCH 1256/1504] Make error messages copyable (#614) * Make error copyable * Allow partial copying or double click full copy --- plugin/src/App/StatusPages/Error.lua | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/plugin/src/App/StatusPages/Error.lua b/plugin/src/App/StatusPages/Error.lua index 15fe5446..8af669c6 100644 --- a/plugin/src/App/StatusPages/Error.lua +++ b/plugin/src/App/StatusPages/Error.lua @@ -57,8 +57,16 @@ function Error:render() end, }, { ErrorMessage = Theme.with(function(theme) - return e("TextLabel", { + return e("TextBox", { + [Roact.Event.InputBegan] = function(rbx, input) + if input.UserInputType ~= Enum.UserInputType.MouseButton1 then return end + rbx.SelectionStart = 0 + rbx.CursorPosition = #rbx.Text+1 + end, + + Text = self.props.errorMessage, + TextEditable = false, Font = Enum.Font.Code, TextSize = 16, TextColor3 = theme.ErrorColor, @@ -66,10 +74,9 @@ function Error:render() TextYAlignment = Enum.TextYAlignment.Top, TextTransparency = self.props.transparency, TextWrapped = true, - - Size = UDim2.new(1, 0, 1, 0), - + ClearTextOnFocus = false, BackgroundTransparency = 1, + Size = UDim2.new(1, 0, 1, 0), }) end), From 05adb82ddabd6f9600273e13c3a128b1d489d3a9 Mon Sep 17 00:00:00 2001 From: Barocena <34089907+Barocena@users.noreply.github.com> Date: Mon, 8 Aug 2022 10:59:52 +0300 Subject: [PATCH 1257/1504] Renamed Common to Shared (#611) --- assets/default-place-project/default.project.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/default-place-project/default.project.json b/assets/default-place-project/default.project.json index 6b25eb9b..b6e6410a 100644 --- a/assets/default-place-project/default.project.json +++ b/assets/default-place-project/default.project.json @@ -4,7 +4,7 @@ "$className": "DataModel", "ReplicatedStorage": { - "Common": { + "Shared": { "$path": "src/shared" } }, From 4cb49c78259d3009d150dffef69fefbfedd0f55c Mon Sep 17 00:00:00 2001 From: boatbomber Date: Mon, 8 Aug 2022 01:08:55 -0700 Subject: [PATCH 1258/1504] Add sync locking for Team Create (#590) * Add sync locking * Steal lock from users who left without releasing * Do not remove lock as unknown instance * Don't delete non Archivable instance --- plugin/src/App/init.lua | 62 ++++++++++++++++++++++++++++++++++ plugin/src/Reconciler/diff.lua | 6 ++++ 2 files changed, 68 insertions(+) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 5de9ffdd..d239c52c 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -1,3 +1,6 @@ +local Players = game:GetService("Players") +local ServerStorage = game:GetService("ServerStorage") + local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin local Packages = Rojo.Packages @@ -92,7 +95,65 @@ function App:getHostAndPort() return host, port end +function App:claimSyncLock() + if #Players:GetPlayers() == 0 then + Log.trace("Skipping sync lock because this isn't in Team Create") + return true + end + + local lock = ServerStorage:FindFirstChild("__Rojo_SessionLock") + if not lock then + lock = Instance.new("ObjectValue") + lock.Name = "__Rojo_SessionLock" + lock.Archivable = false + lock.Value = Players.LocalPlayer + lock.Parent = ServerStorage + Log.trace("Created and claimed sync lock") + return true + end + + if lock.Value and lock.Value ~= Players.LocalPlayer and lock.Value.Parent then + Log.trace("Found existing sync lock owned by {}", lock.Value) + return false, lock.Value + end + + lock.Value = Players.LocalPlayer + Log.trace("Claimed existing sync lock") + return true +end + +function App:releaseSyncLock() + local lock = ServerStorage:FindFirstChild("__Rojo_SessionLock") + if not lock then + Log.trace("No sync lock found, assumed released") + return + end + + if lock.Value == Players.LocalPlayer then + lock.Value = nil + Log.trace("Released sync lock") + return + end + + Log.trace("Could not relase sync lock because it is owned by {}", lock.Value) +end + function App:startSession() + local claimedLock, priorOwner = self:claimSyncLock() + if not claimedLock then + local msg = string.format("Could not sync because user '%s' is already syncing", tostring(priorOwner)) + + Log.warn(msg) + self:addNotification(msg, 10) + self:setState({ + appStatus = AppStatus.Error, + errorMessage = msg, + toolbarIcon = Assets.Images.PluginButtonWarning, + }) + + return + end + local host, port = self:getHostAndPort() local sessionOptions = { @@ -155,6 +216,7 @@ function App:startSession() self:addNotification(string.format("Connected to session '%s' at %s.", details, address), 5) elseif status == ServeSession.Status.Disconnected then self.serveSession = nil + self:releaseSyncLock() -- Details being present indicates that this -- disconnection was from an error. diff --git a/plugin/src/Reconciler/diff.lua b/plugin/src/Reconciler/diff.lua index 995d06d8..97819e32 100644 --- a/plugin/src/Reconciler/diff.lua +++ b/plugin/src/Reconciler/diff.lua @@ -115,6 +115,12 @@ local function diff(instanceMap, virtualInstances, rootId) local childId = instanceMap.fromInstances[childInstance] if childId == nil then + if childInstance.Archivable == false then + -- We don't remove instances that aren't going to be saved anyway, + -- such as the Rojo session lock value. + continue + end + -- This is an existing instance not present in the virtual DOM. -- We can mark it for deletion unless the user has asked us not -- to delete unknown stuff. From 142705f386f27767334421415c5da5787fe393e6 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 10 Aug 2022 12:57:24 -0700 Subject: [PATCH 1259/1504] Fix security permission error (#619) --- plugin/src/Reconciler/diff.lua | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugin/src/Reconciler/diff.lua b/plugin/src/Reconciler/diff.lua index 97819e32..ef729700 100644 --- a/plugin/src/Reconciler/diff.lua +++ b/plugin/src/Reconciler/diff.lua @@ -115,9 +115,13 @@ local function diff(instanceMap, virtualInstances, rootId) local childId = instanceMap.fromInstances[childInstance] if childId == nil then - if childInstance.Archivable == false then + -- pcall to avoid security permission errors + local success, skip = pcall(function() -- We don't remove instances that aren't going to be saved anyway, -- such as the Rojo session lock value. + return childInstance.Archivable == false + end) + if success and skip then continue end From e0198e626b9840b7d3a004c9887a7849004fe5d6 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Aug 2022 21:34:25 -0400 Subject: [PATCH 1260/1504] Build Linux release on Ubuntu 20.04, use fixed artifact names --- .github/workflows/release.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 666cede1..96a32d6b 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -65,25 +65,21 @@ jobs: fail-fast: false matrix: # https://doc.rust-lang.org/rustc/platform-support.html - # - # FIXME: After the Rojo VS Code extension updates, add architecture - # names to each of these releases. We'll rename win64 to windows and add - # -x86_64 to each release. include: - host: linux - os: ubuntu-18.04 + os: ubuntu-20.04 target: x86_64-unknown-linux-gnu - label: linux + label: linux-x86_64 - host: windows os: windows-latest target: x86_64-pc-windows-msvc - label: win64 + label: windows-x86_64 - host: macos os: macos-latest target: x86_64-apple-darwin - label: macos + label: macos-x86_64 - host: macos os: macos-latest From 7a3ba7721f1fa2e6417861dd6ba563b04281d4f9 Mon Sep 17 00:00:00 2001 From: Boegie19 <34578426+Boegie19@users.noreply.github.com> Date: Sun, 21 Aug 2022 04:15:01 +0200 Subject: [PATCH 1261/1504] fix release action with aftman (#627) * fix release action with aftman * Fixes using bash not powershell * removed comment --- .github/workflows/release.yml | 7 +++++-- aftman.toml | 2 ++ 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 aftman.toml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 96a32d6b..5686867c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -108,16 +108,19 @@ jobs: override: true profile: minimal - - name: Setup Foreman - uses: Roblox/setup-foreman@v1 + - name: Setup Aftman + uses: Bok-nick/setup-aftman@v0.1.0 with: token: ${{ secrets.GITHUB_TOKEN }} + trust-check: false + version: 'v0.2.6' - name: Install packages run: | cd plugin wally install cd .. + shell: bash - name: Build Release run: cargo build --release --locked --verbose diff --git a/aftman.toml b/aftman.toml new file mode 100644 index 00000000..57f7a940 --- /dev/null +++ b/aftman.toml @@ -0,0 +1,2 @@ +[tools] +wally = "UpliftGames/wally@0.3.1" \ No newline at end of file From 46ad337fa5d55c2aa574e40a0a9f424f13913b02 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Aug 2022 22:20:51 -0400 Subject: [PATCH 1262/1504] Switch all workflows to Aftman --- .github/workflows/ci.yml | 14 +++++++++----- .github/workflows/release.yml | 6 ++++-- aftman.toml | 5 ++++- foreman.toml | 5 ----- 4 files changed, 17 insertions(+), 13 deletions(-) delete mode 100644 foreman.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd36ef74..1286f7a4 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,10 +28,12 @@ jobs: override: true profile: minimal - - name: Setup Foreman - uses: Roblox/setup-foreman@v1 + - name: Setup Aftman + uses: Bok-nick/setup-aftman@v0.1.0 with: token: ${{ secrets.GITHUB_TOKEN }} + trust-check: false + version: 'v0.2.6' - name: Install packages run: | @@ -59,10 +61,12 @@ jobs: override: true components: rustfmt, clippy - - name: Setup Foreman - uses: Roblox/setup-foreman@v1 + - name: Setup Aftman + uses: Bok-nick/setup-aftman@v0.1.0 with: token: ${{ secrets.GITHUB_TOKEN }} + trust-check: false + version: 'v0.2.6' - name: Install packages run: | @@ -74,4 +78,4 @@ jobs: run: cargo fmt -- --check - name: Clippy - run: cargo clippy + run: cargo clippy \ No newline at end of file diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5686867c..752fbcfc 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,10 +29,12 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Setup Foreman - uses: Roblox/setup-foreman@v1 + - name: Setup Aftman + uses: Bok-nick/setup-aftman@v0.1.0 with: token: ${{ secrets.GITHUB_TOKEN }} + trust-check: false + version: 'v0.2.6' - name: Install packages run: | diff --git a/aftman.toml b/aftman.toml index 57f7a940..058140ef 100644 --- a/aftman.toml +++ b/aftman.toml @@ -1,2 +1,5 @@ [tools] -wally = "UpliftGames/wally@0.3.1" \ No newline at end of file +wally = "UpliftGames/wally@0.3.1" +rojo = "rojo-rbx/rojo@7.2.1" +selene = "Kampfkarren/selene@0.20.0" +run-in-roblox = "rojo-rbx/run-in-roblox@0.3.0" diff --git a/foreman.toml b/foreman.toml deleted file mode 100644 index 4b8546aa..00000000 --- a/foreman.toml +++ /dev/null @@ -1,5 +0,0 @@ -[tools] -rojo = { source = "rojo-rbx/rojo", version = "7.2.1" } -run-in-roblox = { source = "rojo-rbx/run-in-roblox", version = "0.3.0" } -selene = { source = "Kampfkarren/selene", version = "0.20.0" } -wally = { source = "UpliftGames/wally", version = "0.3.1"} From 72d62220e83229b910af69338ac74d6854e47bc9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Aug 2022 22:22:11 -0400 Subject: [PATCH 1263/1504] Fix referring to open source maintainer as a chicken --- .github/workflows/ci.yml | 4 ++-- .github/workflows/release.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1286f7a4..adad0143 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,7 +29,7 @@ jobs: profile: minimal - name: Setup Aftman - uses: Bok-nick/setup-aftman@v0.1.0 + uses: ok-nick/setup-aftman@v0.1.0 with: token: ${{ secrets.GITHUB_TOKEN }} trust-check: false @@ -62,7 +62,7 @@ jobs: components: rustfmt, clippy - name: Setup Aftman - uses: Bok-nick/setup-aftman@v0.1.0 + uses: ok-nick/setup-aftman@v0.1.0 with: token: ${{ secrets.GITHUB_TOKEN }} trust-check: false diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 752fbcfc..ea4b0051 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -30,7 +30,7 @@ jobs: - uses: actions/checkout@v3 - name: Setup Aftman - uses: Bok-nick/setup-aftman@v0.1.0 + uses: ok-nick/setup-aftman@v0.1.0 with: token: ${{ secrets.GITHUB_TOKEN }} trust-check: false @@ -111,7 +111,7 @@ jobs: profile: minimal - name: Setup Aftman - uses: Bok-nick/setup-aftman@v0.1.0 + uses: ok-nick/setup-aftman@v0.1.0 with: token: ${{ secrets.GITHUB_TOKEN }} trust-check: false From 98765088877986e013ca863ef350ec477c7dd870 Mon Sep 17 00:00:00 2001 From: Boegie19 <34578426+Boegie19@users.noreply.github.com> Date: Sun, 21 Aug 2022 04:32:58 +0200 Subject: [PATCH 1264/1504] added attributes to AdjacentMetadata (#624) * added attributes to AdjacentMetadata * ran fmt --- src/snapshot_middleware/meta_file.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/snapshot_middleware/meta_file.rs b/src/snapshot_middleware/meta_file.rs index abf53fba..72930e49 100644 --- a/src/snapshot_middleware/meta_file.rs +++ b/src/snapshot_middleware/meta_file.rs @@ -19,6 +19,9 @@ pub struct AdjacentMetadata { #[serde(default, skip_serializing_if = "HashMap::is_empty")] pub properties: HashMap, + #[serde(default, skip_serializing_if = "HashMap::is_empty")] + pub attributes: HashMap, + #[serde(skip)] pub path: PathBuf, } @@ -53,6 +56,19 @@ impl AdjacentMetadata { snapshot.properties.insert(key, value); } + if !self.attributes.is_empty() { + let mut attributes = Attributes::new(); + + for (key, unresolved) in self.attributes.drain() { + let value = unresolved.resolve_unambiguous()?; + attributes.insert(key, value); + } + + snapshot + .properties + .insert("Attributes".into(), attributes.into()); + } + Ok(()) } From 17de912608a8d728e1879bf8ef6229e296ae1a1d Mon Sep 17 00:00:00 2001 From: Boegie19 <34578426+Boegie19@users.noreply.github.com> Date: Sun, 21 Aug 2022 04:33:19 +0200 Subject: [PATCH 1265/1504] fix_vfs_double_update (#616) --- src/change_processor.rs | 90 ++++++++++++++++++++++++----------------- 1 file changed, 52 insertions(+), 38 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index ac9cb869..f3902067 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -1,5 +1,6 @@ use std::{ fs, + path::PathBuf, sync::{Arc, Mutex}, }; @@ -124,46 +125,20 @@ impl JobThreadContext { // For a given VFS event, we might have many changes to different parts // of the tree. Calculate and apply all of these changes. - let applied_patches = { - let mut tree = self.tree.lock().unwrap(); - let mut applied_patches = Vec::new(); - - match event { - VfsEvent::Create(path) | VfsEvent::Write(path) | VfsEvent::Remove(path) => { - // Find the nearest ancestor to this path that has - // associated instances in the tree. This helps make sure - // that we handle additions correctly, especially if we - // receive events for descendants of a large tree being - // created all at once. - let mut current_path = path.as_path(); - let affected_ids = loop { - let ids = tree.get_ids_at_path(¤t_path); - - log::trace!("Path {} affects IDs {:?}", current_path.display(), ids); - - if !ids.is_empty() { - break ids.to_vec(); - } - - log::trace!("Trying parent path..."); - match current_path.parent() { - Some(parent) => current_path = parent, - None => break Vec::new(), - } - }; - - for id in affected_ids { - if let Some(patch) = compute_and_apply_changes(&mut tree, &self.vfs, id) { - if !patch.is_empty() { - applied_patches.push(patch); - } - } - } + let applied_patches = match event { + VfsEvent::Write(path) => { + if path.is_dir() { + return; } - _ => log::warn!("Unhandled VFS event: {:?}", event), + on_vfs_event(path, &self.tree, &self.vfs) + } + VfsEvent::Create(path) | VfsEvent::Remove(path) => { + on_vfs_event(path, &self.tree, &self.vfs) + } + _ => { + log::warn!("Unhandled VFS event: {:?}", event); + Vec::new() } - - applied_patches }; // Notify anyone listening to the message queue about the changes we @@ -261,6 +236,45 @@ impl JobThreadContext { } } +// Find the nearest ancestor to this path that has +// associated instances in the tree. This helps make sure +// that we handle additions correctly, especially if we +// receive events for descendants of a large tree being +// created all at once. +fn on_vfs_event( + path: PathBuf, + tree: &Arc>, + vfs: &Arc, +) -> Vec { + let mut tree = tree.lock().unwrap(); + let mut applied_patches = Vec::new(); + + let mut current_path = path.as_path(); + let affected_ids = loop { + let ids = tree.get_ids_at_path(¤t_path); + + log::trace!("Path {} affects IDs {:?}", current_path.display(), ids); + + if !ids.is_empty() { + break ids.to_vec(); + } + + log::trace!("Trying parent path..."); + match current_path.parent() { + Some(parent) => current_path = parent, + None => break Vec::new(), + } + }; + + for id in affected_ids { + if let Some(patch) = compute_and_apply_changes(&mut tree, &vfs, id) { + if !patch.is_empty() { + applied_patches.push(patch); + } + } + } + applied_patches +} fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: Ref) -> Option { let metadata = tree .get_metadata(id) From cdc972a5ce33545b424d25a7a7b89c7b161611c8 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 20 Aug 2022 19:39:34 -0700 Subject: [PATCH 1266/1504] Migrate DevSettings to PluginSettings for much better config flow (#572) * Add the devsetting config options into settings * Create dropdown component and add setting controls * Static dropdwon width and spin arrow * Improve dropdown option contrast and border * Forgot to make the settings page respect the static spacing, oops * Smaller arrow * Vert padding * Reset option for settings * Hide reset button when on default * Respect the logLevel setting * Portal settings out to external typechecking module * Implement new configs using the new singleton Settings * Remove DevSettings * Update test runner to use new settings * More helpful test failure output * Support non-plugin environment * Migrate dropdown to new packages system * Clean up components a tad --- plugin/run-tests.server.lua | 14 +- plugin/src/App/Components/Dropdown.lua | 169 ++++++++++++++++++ plugin/src/App/Components/IconButton.lua | 1 + .../src/App/StatusPages/Settings/Setting.lua | 52 ++++-- plugin/src/App/StatusPages/Settings/init.lua | 36 ++++ plugin/src/App/Theme.lua | 22 +++ plugin/src/Assets.lua | 4 + plugin/src/DevSettings.lua | 139 -------------- plugin/src/Settings.lua | 24 +++ plugin/src/Types.lua | 4 +- plugin/src/init.server.lua | 4 +- plugin/src/init.spec.lua | 7 +- 12 files changed, 309 insertions(+), 167 deletions(-) create mode 100644 plugin/src/App/Components/Dropdown.lua delete mode 100644 plugin/src/DevSettings.lua diff --git a/plugin/run-tests.server.lua b/plugin/run-tests.server.lua index 7637d12f..1e2130f5 100644 --- a/plugin/run-tests.server.lua +++ b/plugin/run-tests.server.lua @@ -4,16 +4,8 @@ local TestEZ = require(ReplicatedStorage.Packages.TestEZ) local Rojo = ReplicatedStorage.Rojo -local DevSettings = require(Rojo.Plugin.DevSettings) - -local setDevSettings = not DevSettings:hasChangedValues() - -if setDevSettings then - DevSettings:createTestSettings() -end +local Settings = require(Rojo.Plugin.Settings) +Settings:set("logLevel", "Trace") +Settings:set("typecheckingEnabled", true) require(Rojo.Plugin.runTests)(TestEZ) - -if setDevSettings then - DevSettings:resetValues() -end diff --git a/plugin/src/App/Components/Dropdown.lua b/plugin/src/App/Components/Dropdown.lua new file mode 100644 index 00000000..ef9a4211 --- /dev/null +++ b/plugin/src/App/Components/Dropdown.lua @@ -0,0 +1,169 @@ +local TextService = game:GetService("TextService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) +local Flipper = require(Packages.Flipper) + +local Assets = require(Plugin.Assets) +local Theme = require(Plugin.App.Theme) +local bindingUtil = require(Plugin.App.bindingUtil) + +local SlicedImage = require(script.Parent.SlicedImage) +local ScrollingFrame = require(script.Parent.ScrollingFrame) + +local e = Roact.createElement + +local Dropdown = Roact.Component:extend("Dropdown") + +function Dropdown:init() + self.openMotor = Flipper.SingleMotor.new(0) + self.openBinding = bindingUtil.fromMotor(self.openMotor) + + self.contentSize, self.setContentSize = Roact.createBinding(Vector2.new(0, 0)) + + self:setState({ + open = false, + }) +end + +function Dropdown:didUpdate() + self.openMotor:setGoal( + Flipper.Spring.new(self.state.open and 1 or 0, { + frequency = 6, + dampingRatio = 1.1, + }) + ) +end + +function Dropdown:render() + return Theme.with(function(theme) + theme = theme.Dropdown + + local optionButtons = {} + local width = -1 + for i, option in self.props.options do + local text = tostring(option or "") + local textSize = TextService:GetTextSize( + text, 15, Enum.Font.GothamMedium, + Vector2.new(math.huge, 20) + ) + if textSize.X > width then + width = textSize.X + end + + optionButtons[text] = e("TextButton", { + Text = text, + LayoutOrder = i, + Size = UDim2.new(1, 0, 0, 24), + BackgroundColor3 = theme.BackgroundColor, + TextTransparency = self.props.transparency, + BackgroundTransparency = self.props.transparency, + BorderSizePixel = 0, + TextColor3 = theme.TextColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextSize = 15, + Font = Enum.Font.GothamMedium, + + [Roact.Event.Activated] = function() + self:setState({ + open = false, + }) + self.props.onClick(option) + end, + }, { + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 6), + }), + }) + end + + return e("ImageButton", { + Size = UDim2.new(0, width+50, 0, 28), + Position = self.props.position, + AnchorPoint = self.props.anchorPoint, + LayoutOrder = self.props.layoutOrder, + ZIndex = self.props.zIndex, + BackgroundTransparency = 1, + + [Roact.Event.Activated] = function() + self:setState({ + open = not self.state.open, + }) + end, + }, { + Border = e(SlicedImage, { + slice = Assets.Slices.RoundedBorder, + color = theme.BorderColor, + transparency = self.props.transparency, + size = UDim2.new(1, 0, 1, 0), + }, { + DropArrow = e("ImageLabel", { + Image = Assets.Images.Dropdown.Arrow, + ImageColor3 = self.openBinding:map(function(a) + return theme.Closed.IconColor:Lerp(theme.Open.IconColor, a) + end), + ImageTransparency = self.props.transparency, + + Size = UDim2.new(0, 18, 0, 18), + Position = UDim2.new(1, -6, 0.5, 0), + AnchorPoint = Vector2.new(1, 0.5), + Rotation = self.openBinding:map(function(a) + return a * 180 + end), + + BackgroundTransparency = 1, + }), + Active = e("TextLabel", { + Size = UDim2.new(1, -30, 1, 0), + Position = UDim2.new(0, 6, 0, 0), + BackgroundTransparency = 1, + Text = self.props.active, + Font = Enum.Font.GothamMedium, + TextSize = 15, + TextColor3 = theme.TextColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = self.props.transparency, + }), + }), + Options = if self.state.open then e(SlicedImage, { + slice = Assets.Slices.RoundedBackground, + color = theme.BackgroundColor, + position = UDim2.new(1, 0, 1, 3), + size = self.openBinding:map(function(a) + return UDim2.new(1, 0, a*math.min(3, #self.props.options), 0) + end), + anchorPoint = Vector2.new(1, 0), + }, { + Border = e(SlicedImage, { + slice = Assets.Slices.RoundedBorder, + color = theme.BorderColor, + transparency = self.props.transparency, + size = UDim2.new(1, 0, 1, 0), + }), + ScrollingFrame = e(ScrollingFrame, { + size = UDim2.new(1, -4, 1, -4), + position = UDim2.new(0, 2, 0, 2), + transparency = self.props.transparency, + contentSize = self.contentSize, + }, { + Layout = e("UIListLayout", { + VerticalAlignment = Enum.VerticalAlignment.Top, + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 0), + + [Roact.Change.AbsoluteContentSize] = function(object) + self.setContentSize(object.AbsoluteContentSize) + end, + }), + Roact.createFragment(optionButtons), + }), + }) else nil, + }) + end) +end + +return Dropdown diff --git a/plugin/src/App/Components/IconButton.lua b/plugin/src/App/Components/IconButton.lua index 18e914a6..169e3867 100644 --- a/plugin/src/App/Components/IconButton.lua +++ b/plugin/src/App/Components/IconButton.lua @@ -30,6 +30,7 @@ function IconButton:render() Position = self.props.position, AnchorPoint = self.props.anchorPoint, + Visible = self.props.visible, LayoutOrder = self.props.layoutOrder, ZIndex = self.props.zIndex, BackgroundTransparency = 1, diff --git a/plugin/src/App/StatusPages/Settings/Setting.lua b/plugin/src/App/StatusPages/Settings/Setting.lua index da6bf50a..8bf688f6 100644 --- a/plugin/src/App/StatusPages/Settings/Setting.lua +++ b/plugin/src/App/StatusPages/Settings/Setting.lua @@ -7,9 +7,12 @@ local Packages = Rojo.Packages local Roact = require(Packages.Roact) local Settings = require(Plugin.Settings) +local Assets = require(Plugin.Assets) local Theme = require(Plugin.App.Theme) local Checkbox = require(Plugin.App.Components.Checkbox) +local Dropdown = require(Plugin.App.Components.Dropdown) +local IconButton = require(Plugin.App.Components.IconButton) local e = Roact.createElement @@ -54,22 +57,48 @@ function Setting:render() return UDim2.new(1, 0, 0, 20 + value.Y + 20) end), LayoutOrder = self.props.layoutOrder, + ZIndex = -self.props.layoutOrder, BackgroundTransparency = 1, [Roact.Change.AbsoluteSize] = function(object) self.setContainerSize(object.AbsoluteSize) end, }, { - Checkbox = e(Checkbox, { - active = self.state.setting, + Input = if self.props.options ~= nil then + e(Dropdown, { + options = self.props.options, + active = self.state.setting, + transparency = self.props.transparency, + position = UDim2.new(1, 0, 0.5, 0), + anchorPoint = Vector2.new(1, 0.5), + onClick = function(option) + Settings:set(self.props.id, option) + end, + }) + else + e(Checkbox, { + active = self.state.setting, + transparency = self.props.transparency, + position = UDim2.new(1, 0, 0.5, 0), + anchorPoint = Vector2.new(1, 0.5), + onClick = function() + local currentValue = Settings:get(self.props.id) + Settings:set(self.props.id, not currentValue) + end, + }), + + Reset = if self.props.onReset then e(IconButton, { + icon = Assets.Images.Icons.Reset, + iconSize = 24, + color = theme.BackButtonColor, transparency = self.props.transparency, - position = UDim2.new(1, 0, 0.5, 0), - anchorPoint = Vector2.new(1, 0.5), - onClick = function() - local currentValue = Settings:get(self.props.id) - Settings:set(self.props.id, not currentValue) - end, - }), + visible = self.props.showReset, + + position = UDim2.new(1, -32 - (self.props.options ~= nil and 120 or 40), 0.5, 0), + anchorPoint = Vector2.new(0, 0.5), + + onClick = self.props.onReset, + }) else nil, Text = e("Frame", { Size = UDim2.new(1, 0, 1, 0), @@ -100,11 +129,12 @@ function Setting:render() TextWrapped = true, Size = self.containerSize:map(function(value) + local offset = (self.props.onReset and 34 or 0) + (self.props.options ~= nil and 120 or 40) local textBounds = getTextBounds( self.props.description, 14, Enum.Font.Gotham, 1.2, - Vector2.new(value.X - 50, math.huge) + Vector2.new(value.X - offset, math.huge) ) - return UDim2.new(1, -50, 0, textBounds.Y) + return UDim2.new(1, -offset, 0, textBounds.Y) end), LayoutOrder = 2, diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua index 69fc16f9..3b4b339e 100644 --- a/plugin/src/App/StatusPages/Settings/init.lua +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -3,8 +3,10 @@ local Plugin = Rojo.Plugin local Packages = Rojo.Packages local Roact = require(Packages.Roact) +local Log = require(Packages.Log) local Assets = require(Plugin.Assets) +local Settings = require(Plugin.Settings) local Theme = require(Plugin.App.Theme) local IconButton = require(Plugin.App.Components.IconButton) @@ -13,6 +15,16 @@ local Setting = require(script.Setting) local e = Roact.createElement +local function invertTbl(tbl) + local new = {} + for key, value in tbl do + new[value] = key + end + return new +end + +local invertedLevels = invertTbl(Log.Level) + local function Navbar(props) return Theme.with(function(theme) theme = theme.Settings.Navbar @@ -102,6 +114,30 @@ function SettingsPage:render() layoutOrder = 4, }), + LogLevel = e(Setting, { + id = "logLevel", + name = "Log Level", + description = "Plugin output verbosity level", + transparency = self.props.transparency, + layoutOrder = 5, + + options = invertedLevels, + showReset = Settings:getBinding("logLevel"):map(function(value) + return value ~= "Info" + end), + onReset = function() + Settings:set("logLevel", "Info") + end, + }), + + TypecheckingEnabled = e(Setting, { + id = "typecheckingEnabled", + name = "Typechecking", + description = "Toggle typechecking on the API surface", + transparency = self.props.transparency, + layoutOrder = 6, + }), + Layout = e("UIListLayout", { FillDirection = Enum.FillDirection.Vertical, SortOrder = Enum.SortOrder.LayoutOrder, diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index 1ba2c35c..a6572484 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -72,6 +72,17 @@ local lightTheme = strict("LightTheme", { BorderColor = hexColor(0xAFAFAF), }, }, + Dropdown = { + TextColor = hexColor(0x00000), + BorderColor = hexColor(0xAFAFAF), + BackgroundColor = hexColor(0xEEEEEE), + Open = { + IconColor = BRAND_COLOR, + }, + Closed = { + IconColor = hexColor(0xEEEEEE), + }, + }, AddressEntry = { TextColor = hexColor(0x000000), PlaceholderColor = hexColor(0x8C8C8C) @@ -150,6 +161,17 @@ local darkTheme = strict("DarkTheme", { BorderColor = hexColor(0x5A5A5A), }, }, + Dropdown = { + TextColor = hexColor(0xFFFFFF), + BorderColor = hexColor(0x5A5A5A), + BackgroundColor = hexColor(0x2B2B2B), + Open = { + IconColor = BRAND_COLOR, + }, + Closed = { + IconColor = hexColor(0x484848), + }, + }, AddressEntry = { TextColor = hexColor(0xFFFFFF), PlaceholderColor = hexColor(0x8B8B8B) diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index df259c07..08f86b3b 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -23,11 +23,15 @@ local Assets = { Icons = { Close = "rbxassetid://6012985953", Back = "rbxassetid://6017213752", + Reset = "rbxassetid://10142422327", }, Checkbox = { Active = "rbxassetid://6016251644", Inactive = "rbxassetid://6016251963", }, + Dropdown = { + Arrow = "rbxassetid://10131770538", + }, Spinner = { Foreground = "rbxassetid://3222731032", Background = "rbxassetid://3222730627", diff --git a/plugin/src/DevSettings.lua b/plugin/src/DevSettings.lua deleted file mode 100644 index f1458c00..00000000 --- a/plugin/src/DevSettings.lua +++ /dev/null @@ -1,139 +0,0 @@ -local Config = require(script.Parent.Config) - -local Environment = { - User = "User", - Dev = "Dev", - Test = "Test", -} - -local DEFAULT_ENVIRONMENT = Config.isDevBuild and Environment.Dev or Environment.User - -local VALUES = { - LogLevel = { - type = "IntValue", - values = { - [Environment.User] = 2, - [Environment.Dev] = 4, - [Environment.Test] = 4, - }, - }, - TypecheckingEnabled = { - type = "BoolValue", - values = { - [Environment.User] = false, - [Environment.Dev] = true, - [Environment.Test] = true, - }, - }, -} - -local CONTAINER_NAME = "RojoDevSettings" .. Config.codename - -local function getValueContainer() - return game:FindFirstChild(CONTAINER_NAME) -end - -local valueContainer = getValueContainer() - -game.ChildAdded:Connect(function(child) - local success, name = pcall(function() - return child.Name - end) - - if success and name == CONTAINER_NAME then - valueContainer = child - end -end) - -local function getStoredValue(name) - if valueContainer == nil then - return nil - end - - local valueObject = valueContainer:FindFirstChild(name) - - if valueObject == nil then - return nil - end - - return valueObject.Value -end - -local function setStoredValue(name, kind, value) - local object = valueContainer:FindFirstChild(name) - - if object == nil then - object = Instance.new(kind) - object.Name = name - object.Parent = valueContainer - end - - object.Value = value -end - -local function createAllValues(environment) - assert(Environment[environment] ~= nil, "Invalid environment") - - valueContainer = getValueContainer() - - if valueContainer == nil then - valueContainer = Instance.new("Folder") - valueContainer.Name = CONTAINER_NAME - valueContainer.Parent = game - end - - for name, value in pairs(VALUES) do - setStoredValue(name, value.type, value.values[environment]) - end -end - -local function getValue(name) - assert(VALUES[name] ~= nil, "Invalid DevSettings name") - - local stored = getStoredValue(name) - - if stored ~= nil then - return stored - end - - return VALUES[name].values[DEFAULT_ENVIRONMENT] -end - -local DevSettings = {} - -function DevSettings:createDevSettings() - createAllValues(Environment.Dev) -end - -function DevSettings:createTestSettings() - createAllValues(Environment.Test) -end - -function DevSettings:hasChangedValues() - return valueContainer ~= nil -end - -function DevSettings:resetValues() - if valueContainer then - valueContainer:Destroy() - valueContainer = nil - end -end - -function DevSettings:isEnabled() - return valueContainer ~= nil -end - -function DevSettings:getLogLevel() - return getValue("LogLevel") -end - -function DevSettings:shouldTypecheck() - return getValue("TypecheckingEnabled") -end - -function _G.ROJO_DEV_CREATE() - DevSettings:createDevSettings() -end - -return DevSettings \ No newline at end of file diff --git a/plugin/src/Settings.lua b/plugin/src/Settings.lua index 206ed3e7..7bb592bf 100644 --- a/plugin/src/Settings.lua +++ b/plugin/src/Settings.lua @@ -7,18 +7,22 @@ local Rojo = script:FindFirstAncestor("Rojo") local Packages = Rojo.Packages local Log = require(Packages.Log) +local Roact = require(Packages.Roact) local defaultSettings = { openScriptsExternally = false, twoWaySync = false, showNotifications = true, playSounds = true, + typecheckingEnabled = false, + logLevel = "Info", } local Settings = {} Settings._values = table.clone(defaultSettings) Settings._updateListeners = {} +Settings._bindings = {} if plugin then for name, defaultValue in pairs(Settings._values) do @@ -45,6 +49,9 @@ end function Settings:set(name, value) self._values[name] = value + if self._bindings[name] then + self._bindings[name].set(value) + end if plugin then -- plugin:SetSetting hits disc instead of memory, so it can be slow. Spawn so we don't hang. @@ -76,4 +83,21 @@ function Settings:onChanged(name, callback) end end +function Settings:getBinding(name) + local cached = self._bindings[name] + if cached then + return cached.bind + end + + local bind, set = Roact.createBinding(self._values[name]) + self._bindings[name] = { + bind = bind, + set = set, + } + + Log.trace(string.format("Created binding for setting '%s'", name)) + + return bind +end + return Settings diff --git a/plugin/src/Types.lua b/plugin/src/Types.lua index ee66d520..221ddcb1 100644 --- a/plugin/src/Types.lua +++ b/plugin/src/Types.lua @@ -1,6 +1,6 @@ local Packages = script.Parent.Parent.Packages local t = require(Packages.t) -local DevSettings = require(script.Parent.DevSettings) +local Settings = require(script.Parent.Settings) local strict = require(script.Parent.strict) local RbxId = t.string @@ -66,7 +66,7 @@ local ApiError = t.interface({ local function ifEnabled(innerCheck) return function(...) - if DevSettings:shouldTypecheck() then + if Settings:get("typecheckingEnabled") then return innerCheck(...) else return true diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index 564ebbd7..da7a38ce 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -8,12 +8,12 @@ local Packages = Rojo.Packages local Log = require(Packages.Log) local Roact = require(Packages.Roact) -local DevSettings = require(script.DevSettings) +local Settings = require(script.Settings) local Config = require(script.Config) local App = require(script.App) Log.setLogLevelThunk(function() - return DevSettings:getLogLevel() + return Log.Level[Settings:get("logLevel")] or Log.Level.Info end) local app = Roact.createElement(App, { diff --git a/plugin/src/init.spec.lua b/plugin/src/init.spec.lua index ad474338..4cf8947c 100644 --- a/plugin/src/init.spec.lua +++ b/plugin/src/init.spec.lua @@ -2,7 +2,10 @@ return function() it("should load all submodules", function() local function loadRecursive(container) if container:IsA("ModuleScript") and not container.Name:find("%.spec$") then - require(container) + local success, err = pcall(require, container) + if not success then + error(string.format("Failed to load '%s': %s", container.Name, err)) + end end for _, child in ipairs(container:GetChildren()) do @@ -12,4 +15,4 @@ return function() loadRecursive(script.Parent) end) -end \ No newline at end of file +end From c7c0903804a97942d3e092d3a744a13404366913 Mon Sep 17 00:00:00 2001 From: Qualadore <93345551+Qualadore@users.noreply.github.com> Date: Sat, 20 Aug 2022 18:40:52 -0800 Subject: [PATCH 1267/1504] Reduce minimum plugin size (#606) * Reduce minimum plugin size * Resize to 300x120 Co-authored-by: Qualadore --- plugin/src/App/init.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index d239c52c..707127d1 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -297,7 +297,7 @@ function App:render() initEnabled = false, overridePreviousState = false, floatingSize = Vector2.new(300, 200), - minimumSize = Vector2.new(300, 200), + minimumSize = Vector2.new(300, 120), zIndexBehavior = Enum.ZIndexBehavior.Sibling, From 6ec411a618042f3f2beb8695a9dc6b2f082485a9 Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 20 Aug 2022 23:42:05 -0400 Subject: [PATCH 1268/1504] Add Patreon badge to README --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index fb318f3f..f87b5057 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Actions status Latest server version Rojo Documentation + Patreon


    From 003abe86bbb8a461f2cd7604dd9e8f6efaddad70 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Thu, 22 Sep 2022 20:03:09 -0700 Subject: [PATCH 1269/1504] Save host and port by placeId (#613) * Save host and port by placeId * Bump to 5 months before clearing * Fix indentation --- plugin/src/App/init.lua | 47 +++++++++++++++++++++++++++++++++++++++-- plugin/src/Config.lua | 4 ++-- plugin/src/Settings.lua | 1 + 3 files changed, 48 insertions(+), 4 deletions(-) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 707127d1..9f7e2ecf 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -44,8 +44,10 @@ local App = Roact.Component:extend("App") function App:init() preloadAssets() - self.host, self.setHost = Roact.createBinding("") - self.port, self.setPort = Roact.createBinding("") + local priorHost, priorPort = self:getPriorEndpoint() + self.host, self.setHost = Roact.createBinding(priorHost or "") + self.port, self.setPort = Roact.createBinding(priorPort or "") + self.patchInfo, self.setPatchInfo = Roact.createBinding({ changes = 0, timestamp = os.time(), @@ -85,6 +87,45 @@ function App:closeNotification(index: number) }) end +function App:getPriorEndpoint() + local priorEndpoints = Settings:get("priorEndpoints") + if not priorEndpoints then return end + + local place = priorEndpoints[tostring(game.PlaceId)] + if not place then return end + + return place.host, place.port +end + +function App:setPriorEndpoint(host: string, port: string) + local priorEndpoints = Settings:get("priorEndpoints") + if not priorEndpoints then + priorEndpoints = {} + end + + -- Clear any stale saves to avoid disc bloat + for placeId, endpoint in priorEndpoints do + if os.time() - endpoint.timestamp > 12_960_000 then + priorEndpoints[placeId] = nil + Log.trace("Cleared stale saved endpoint for {}", placeId) + end + end + + if host == Config.defaultHost and port == Config.defaultPort then + -- Don't save default + priorEndpoints[tostring(game.PlaceId)] = nil + else + priorEndpoints[tostring(game.PlaceId)] = { + host = host ~= Config.defaultHost and host or nil, + port = port ~= Config.defaultPort and port or nil, + timestamp = os.time(), + } + Log.trace("Saved last used endpoint for {}", game.PlaceId) + end + + Settings:set("priorEndpoints", priorEndpoints) +end + function App:getHostAndPort() local host = self.host:getValue() local port = self.port:getValue() @@ -200,6 +241,8 @@ function App:startSession() serveSession:onStatusChanged(function(status, details) if status == ServeSession.Status.Connecting then + self:setPriorEndpoint(host, port) + self:setState({ appStatus = AppStatus.Connecting, toolbarIcon = Assets.Images.PluginButton, diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 3b85c3ee..8aae470d 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -9,5 +9,5 @@ return strict("Config", { expectedServerVersionString = "7.2 or newer", protocolVersion = 4, defaultHost = "localhost", - defaultPort = 34872, -}) \ No newline at end of file + defaultPort = "34872", +}) diff --git a/plugin/src/Settings.lua b/plugin/src/Settings.lua index 7bb592bf..0f23c86b 100644 --- a/plugin/src/Settings.lua +++ b/plugin/src/Settings.lua @@ -16,6 +16,7 @@ local defaultSettings = { playSounds = true, typecheckingEnabled = false, logLevel = "Info", + priorEndpoints = {}, } local Settings = {} From 96cb1ee3fdaa58e2dc98fbdafdc868ff75fbe1d7 Mon Sep 17 00:00:00 2001 From: fox <83943819+fewkz@users.noreply.github.com> Date: Fri, 30 Sep 2022 17:59:09 -0400 Subject: [PATCH 1270/1504] Support explicitly specifying http or https protocol in plugin (#642) * Support explicitly specifying http or https protocol in plugin * Fix incorrect format string Port is not a number --- plugin/src/App/init.lua | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 9f7e2ecf..93186077 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -202,7 +202,9 @@ function App:startSession() twoWaySync = Settings:get("twoWaySync"), } - local baseUrl = ("http://%s:%s"):format(host, port) + local baseUrl = if string.find(host, "^https?://") + then string.format("%s:%s", host, port) + else string.format("http://%s:%s", host, port) local apiContext = ApiContext.new(baseUrl) local serveSession = ServeSession.new({ From b88d34c639b7d7bdd4171b7846a64c2b13f0c2d5 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Fri, 7 Oct 2022 19:31:14 -0400 Subject: [PATCH 1271/1504] Add tooltips to buttons (#637) * Add tooltips * Fix whitespace * Avoid overloaded word canvas * Clean render function * Switch folder to fragment --- .../src/App/Components/BorderedContainer.lua | 1 + plugin/src/App/Components/Checkbox.lua | 5 + plugin/src/App/Components/IconButton.lua | 2 + plugin/src/App/Components/TextButton.lua | 2 + plugin/src/App/Components/Tooltip.lua | 226 ++++++++++++++++++ plugin/src/App/StatusPages/Connected.lua | 5 + plugin/src/App/StatusPages/Error.lua | 5 + plugin/src/App/StatusPages/NotConnected.lua | 9 + plugin/src/App/StatusPages/Settings/init.lua | 5 + plugin/src/App/init.lua | 183 +++++++------- 10 files changed, 354 insertions(+), 89 deletions(-) create mode 100644 plugin/src/App/Components/Tooltip.lua diff --git a/plugin/src/App/Components/BorderedContainer.lua b/plugin/src/App/Components/BorderedContainer.lua index 73fd2bf1..401d5676 100644 --- a/plugin/src/App/Components/BorderedContainer.lua +++ b/plugin/src/App/Components/BorderedContainer.lua @@ -26,6 +26,7 @@ local function BorderedContainer(props) Content = e("Frame", { Size = UDim2.new(1, 0, 1, 0), BackgroundTransparency = 1, + ZIndex = 2, }, props[Roact.Children]), Border = e(SlicedImage, { diff --git a/plugin/src/App/Components/Checkbox.lua b/plugin/src/App/Components/Checkbox.lua index 631164ee..21ec56b3 100644 --- a/plugin/src/App/Components/Checkbox.lua +++ b/plugin/src/App/Components/Checkbox.lua @@ -10,6 +10,7 @@ local Theme = require(Plugin.App.Theme) local bindingUtil = require(Plugin.App.bindingUtil) local SlicedImage = require(script.Parent.SlicedImage) +local Tooltip = require(script.Parent.Tooltip) local e = Roact.createElement @@ -52,6 +53,10 @@ function Checkbox:render() [Roact.Event.Activated] = self.props.onClick, }, { + StateTip = e(Tooltip.Trigger, { + text = if self.props.active then "Enabled" else "Disabled", + }), + Active = e(SlicedImage, { slice = Assets.Slices.RoundedBackground, color = theme.Active.BackgroundColor, diff --git a/plugin/src/App/Components/IconButton.lua b/plugin/src/App/Components/IconButton.lua index 169e3867..130f76e4 100644 --- a/plugin/src/App/Components/IconButton.lua +++ b/plugin/src/App/Components/IconButton.lua @@ -75,6 +75,8 @@ function IconButton:render() BackgroundTransparency = 1, }), + + Children = Roact.createFragment(self.props[Roact.Children]), }) end diff --git a/plugin/src/App/Components/TextButton.lua b/plugin/src/App/Components/TextButton.lua index d33ddf9f..5551f64c 100644 --- a/plugin/src/App/Components/TextButton.lua +++ b/plugin/src/App/Components/TextButton.lua @@ -131,6 +131,8 @@ function TextButton:render() zIndex = -2, }), + + Children = Roact.createFragment(self.props[Roact.Children]), }) end) end diff --git a/plugin/src/App/Components/Tooltip.lua b/plugin/src/App/Components/Tooltip.lua new file mode 100644 index 00000000..e30a3603 --- /dev/null +++ b/plugin/src/App/Components/Tooltip.lua @@ -0,0 +1,226 @@ +local TextService = game:GetService("TextService") +local HttpService = game:GetService("HttpService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) +local Theme = require(Plugin.App.Theme) + +local BorderedContainer = require(Plugin.App.Components.BorderedContainer) + +local e = Roact.createElement + +local DELAY = 0.75 -- How long to hover before a popup is shown (seconds) +local TEXT_PADDING = Vector2.new(8 * 2, 6 * 2) -- Padding for the popup text containers +local TAIL_SIZE = 16 -- Size of the triangle tail piece +local X_OFFSET = 30 -- How far right (from left) the tail will be (assuming enough space) +local Y_OVERLAP = 10 -- Let the triangle tail piece overlap the target a bit to help "connect" it + +local TooltipContext = Roact.createContext({}) + +local function Popup(props) + local textSize = TextService:GetTextSize( + props.Text, 16, Enum.Font.GothamMedium, Vector2.new(math.min(props.parentSize.X, 160), math.huge) + ) + TEXT_PADDING + + local trigger = props.Trigger:getValue() + + local spaceBelow = props.parentSize.Y - (trigger.AbsolutePosition.Y + trigger.AbsoluteSize.Y - Y_OVERLAP + TAIL_SIZE) + local spaceAbove = trigger.AbsolutePosition.Y + Y_OVERLAP - TAIL_SIZE + + -- If there's not enough space below, and there's more space above, then show the tooltip above the trigger + local displayAbove = spaceBelow < textSize.Y and spaceAbove > spaceBelow + + local X = math.clamp(props.Position.X - X_OFFSET, 0, props.parentSize.X - textSize.X) + local Y = 0 + + if displayAbove then + Y = math.max(trigger.AbsolutePosition.Y - TAIL_SIZE - textSize.Y + Y_OVERLAP, 0) + else + Y = math.min(trigger.AbsolutePosition.Y + trigger.AbsoluteSize.Y + TAIL_SIZE - Y_OVERLAP, props.parentSize.Y - textSize.Y) + end + + return Theme.with(function(theme) + return e(BorderedContainer, { + position = UDim2.fromOffset(X, Y), + size = UDim2.fromOffset(textSize.X, textSize.Y), + transparency = props.transparency, + }, { + Label = e("TextLabel", { + BackgroundTransparency = 1, + Position = UDim2.fromScale(0.5, 0.5), + Size = UDim2.new(1, -TEXT_PADDING.X, 1, -TEXT_PADDING.Y), + AnchorPoint = Vector2.new(0.5, 0.5), + Text = props.Text, + TextSize = 16, + Font = Enum.Font.GothamMedium, + TextWrapped = true, + TextXAlignment = Enum.TextXAlignment.Left, + TextColor3 = theme.Button.Bordered.Enabled.TextColor, + TextTransparency = props.transparency, + }), + + Tail = e("ImageLabel", { + ZIndex = 100, + Position = + if displayAbove then + UDim2.new( + 0, math.clamp(props.Position.X - X, 6, textSize.X-6), + 1, -3 + ) + else + UDim2.new( + 0, math.clamp(props.Position.X - X, 6, textSize.X-6), + 0, -TAIL_SIZE+3 + ), + Size = UDim2.fromOffset(TAIL_SIZE, TAIL_SIZE), + AnchorPoint = Vector2.new(0.5, 0), + Rotation = if displayAbove then 180 else 0, + BackgroundTransparency = 1, + Image = "rbxassetid://10983945016", + ImageColor3 = theme.BorderedContainer.BackgroundColor, + ImageTransparency = props.transparency, + }, { + Border = e("ImageLabel", { + Size = UDim2.fromScale(1, 1), + BackgroundTransparency = 1, + Image = "rbxassetid://10983946430", + ImageColor3 = theme.BorderedContainer.BorderColor, + ImageTransparency = props.transparency, + }), + }) + }) + end) +end + +local Provider = Roact.Component:extend("TooltipManager") + +function Provider:init() + self:setState({ + tips = {}, + addTip = function(id: string, data: { Text: string, Position: Vector2, Trigger: any }) + self:setState(function(state) + state.tips[id] = data + return state + end) + end, + removeTip = function(id: string) + self:setState(function(state) + state.tips[id] = nil + return state + end) + end, + }) +end + +function Provider:render() + return Roact.createElement(TooltipContext.Provider, { + value = self.state, + }, self.props[Roact.Children]) +end + +local Container = Roact.Component:extend("TooltipContainer") + +function Container:init() + self:setState({ + size = Vector2.new(200, 100), + }) +end + +function Container:render() + return Roact.createElement(TooltipContext.Consumer, { + render = function(context) + local tips = context.tips + local popups = {} + + for key, value in tips do + popups[key] = e(Popup, { + Text = value.Text or "", + Position = value.Position or Vector2.zero, + Trigger = value.Trigger, + + parentSize = self.state.size, + }) + end + + return e("Frame", { + [Roact.Change.AbsoluteSize] = function(rbx) + self:setState({ + size = rbx.AbsoluteSize, + }) + end, + ZIndex = 100, + BackgroundTransparency = 1, + Size = UDim2.fromScale(1, 1), + }, popups) + end, + }) +end + +local Trigger = Roact.Component:extend("TooltipTrigger") + +function Trigger:init() + self.id = HttpService:GenerateGUID(false) + self.ref = Roact.createRef() + self.mousePos = Vector2.zero + + self.destroy = function() + self.props.context.removeTip(self.id) + end +end + +function Trigger:willUnmount() + if self.showDelayThread then + task.cancel(self.showDelayThread) + end + if self.destroy then + self.destroy() + end +end + +function Trigger:render() + return e("Frame", { + Size = UDim2.fromScale(1, 1), + BackgroundTransparency = 1, + ZIndex = self.props.zIndex or 100, + [Roact.Ref] = self.ref, + + [Roact.Event.MouseMoved] = function(_rbx, x, y) + self.mousePos = Vector2.new(x, y) + end, + [Roact.Event.MouseEnter] = function() + self.showDelayThread = task.delay(DELAY, function() + self.props.context.addTip(self.id, { + Text = self.props.text, + Position = self.mousePos, + Trigger = self.ref, + }) + end) + end, + [Roact.Event.MouseLeave] = function() + if self.showDelayThread then + task.cancel(self.showDelayThread) + end + self.props.context.removeTip(self.id) + end, + }) +end + +local function TriggerConsumer(props) + return Roact.createElement(TooltipContext.Consumer, { + render = function(context) + local innerProps = table.clone(props) + innerProps.context = context + + return e(Trigger, innerProps) + end, + }) +end + +return { + Provider = Provider, + Container = Container, + Trigger = TriggerConsumer, +} diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index 810ce095..ac302d46 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -10,6 +10,7 @@ local Assets = require(Plugin.Assets) local Header = require(Plugin.App.Components.Header) local IconButton = require(Plugin.App.Components.IconButton) local BorderedContainer = require(Plugin.App.Components.BorderedContainer) +local Tooltip = require(Plugin.App.Components.Tooltip) local e = Roact.createElement @@ -90,6 +91,10 @@ local function ConnectionDetails(props) anchorPoint = Vector2.new(1, 0.5), onClick = props.onDisconnect, + }, { + Tip = e(Tooltip.Trigger, { + text = "Disconnect from the Rojo sync server" + }), }), Padding = e("UIPadding", { diff --git a/plugin/src/App/StatusPages/Error.lua b/plugin/src/App/StatusPages/Error.lua index 8af669c6..138e1939 100644 --- a/plugin/src/App/StatusPages/Error.lua +++ b/plugin/src/App/StatusPages/Error.lua @@ -11,6 +11,7 @@ local Theme = require(Plugin.App.Theme) local TextButton = require(Plugin.App.Components.TextButton) local BorderedContainer = require(Plugin.App.Components.BorderedContainer) local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) +local Tooltip = require(Plugin.App.Components.Tooltip) local e = Roact.createElement @@ -123,6 +124,10 @@ function ErrorPage:render() transparency = self.props.transparency, layoutOrder = 1, onClick = self.props.onClose, + }, { + Tip = e(Tooltip.Trigger, { + text = "Dismiss message" + }), }), Layout = e("UIListLayout", { diff --git a/plugin/src/App/StatusPages/NotConnected.lua b/plugin/src/App/StatusPages/NotConnected.lua index 08684b55..40861ba5 100644 --- a/plugin/src/App/StatusPages/NotConnected.lua +++ b/plugin/src/App/StatusPages/NotConnected.lua @@ -10,6 +10,7 @@ local Theme = require(Plugin.App.Theme) local BorderedContainer = require(Plugin.App.Components.BorderedContainer) local TextButton = require(Plugin.App.Components.TextButton) local Header = require(Plugin.App.Components.Header) +local Tooltip = require(Plugin.App.Components.Tooltip) local PORT_WIDTH = 74 local DIVIDER_WIDTH = 1 @@ -116,6 +117,10 @@ function NotConnectedPage:render() transparency = self.props.transparency, layoutOrder = 1, onClick = self.props.onNavigateSettings, + }, { + Tip = e(Tooltip.Trigger, { + text = "View and modify plugin settings" + }), }), Connect = e(TextButton, { @@ -124,6 +129,10 @@ function NotConnectedPage:render() transparency = self.props.transparency, layoutOrder = 2, onClick = self.props.onConnect, + }, { + Tip = e(Tooltip.Trigger, { + text = "Connect to a Rojo sync server" + }), }), Layout = e("UIListLayout", { diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua index 3b4b339e..1d484423 100644 --- a/plugin/src/App/StatusPages/Settings/init.lua +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -11,6 +11,7 @@ local Theme = require(Plugin.App.Theme) local IconButton = require(Plugin.App.Components.IconButton) local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) +local Tooltip = require(Plugin.App.Components.Tooltip) local Setting = require(script.Setting) local e = Roact.createElement @@ -44,6 +45,10 @@ local function Navbar(props) anchorPoint = Vector2.new(0, 0.5), onClick = props.onBack, + }, { + Tip = e(Tooltip.Trigger, { + text = "Back" + }), }), Text = e("TextLabel", { diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 93186077..f141d943 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -22,6 +22,7 @@ local Theme = require(script.Theme) local Page = require(script.Page) local Notifications = require(script.Notifications) +local Tooltip = require(script.Components.Tooltip) local StudioPluginAction = require(script.Components.Studio.StudioPluginAction) local StudioToolbar = require(script.Components.Studio.StudioToolbar) local StudioToggleButton = require(script.Components.Studio.StudioToggleButton) @@ -333,108 +334,112 @@ function App:render() value = self.props.plugin, }, { e(Theme.StudioProvider, nil, { - gui = e(StudioPluginGui, { - id = pluginName, - title = pluginName, - active = self.state.guiEnabled, + e(Tooltip.Provider, nil, { + gui = e(StudioPluginGui, { + id = pluginName, + title = pluginName, + active = self.state.guiEnabled, - initDockState = Enum.InitialDockState.Right, - initEnabled = false, - overridePreviousState = false, - floatingSize = Vector2.new(300, 200), - minimumSize = Vector2.new(300, 120), + initDockState = Enum.InitialDockState.Right, + initEnabled = false, + overridePreviousState = false, + floatingSize = Vector2.new(300, 200), + minimumSize = Vector2.new(300, 120), - zIndexBehavior = Enum.ZIndexBehavior.Sibling, + zIndexBehavior = Enum.ZIndexBehavior.Sibling, - onInitialState = function(initialState) - self:setState({ - guiEnabled = initialState, - }) - end, - - onClose = function() - self:setState({ - guiEnabled = false, - }) - end, - }, { - NotConnectedPage = createPageElement(AppStatus.NotConnected, { - host = self.host, - onHostChange = self.setHost, - port = self.port, - onPortChange = self.setPort, - - onConnect = function() - self:startSession() - end, - - onNavigateSettings = function() + onInitialState = function(initialState) self:setState({ - appStatus = AppStatus.Settings, + guiEnabled = initialState, }) end, - }), - - Connecting = createPageElement(AppStatus.Connecting), - - Connected = createPageElement(AppStatus.Connected, { - projectName = self.state.projectName, - address = self.state.address, - patchInfo = self.patchInfo, - - onDisconnect = function() - self:endSession() - end, - }), - - Settings = createPageElement(AppStatus.Settings, { - onBack = function() - self:setState({ - appStatus = AppStatus.NotConnected, - }) - end, - }), - - Error = createPageElement(AppStatus.Error, { - errorMessage = self.state.errorMessage, onClose = function() self:setState({ - appStatus = AppStatus.NotConnected, - toolbarIcon = Assets.Images.PluginButton, + guiEnabled = false, }) end, + }, { + Tooltips = e(Tooltip.Container, nil), + + NotConnectedPage = createPageElement(AppStatus.NotConnected, { + host = self.host, + onHostChange = self.setHost, + port = self.port, + onPortChange = self.setPort, + + onConnect = function() + self:startSession() + end, + + onNavigateSettings = function() + self:setState({ + appStatus = AppStatus.Settings, + }) + end, + }), + + Connecting = createPageElement(AppStatus.Connecting), + + Connected = createPageElement(AppStatus.Connected, { + projectName = self.state.projectName, + address = self.state.address, + patchInfo = self.patchInfo, + + onDisconnect = function() + self:endSession() + end, + }), + + Settings = createPageElement(AppStatus.Settings, { + onBack = function() + self:setState({ + appStatus = AppStatus.NotConnected, + }) + end, + }), + + Error = createPageElement(AppStatus.Error, { + errorMessage = self.state.errorMessage, + + onClose = function() + self:setState({ + appStatus = AppStatus.NotConnected, + toolbarIcon = Assets.Images.PluginButton, + }) + end, + }), + + Background = Theme.with(function(theme) + return e("Frame", { + Size = UDim2.new(1, 0, 1, 0), + BackgroundColor3 = theme.BackgroundColor, + ZIndex = 0, + BorderSizePixel = 0, + }) + end), }), - Background = Theme.with(function(theme) - return e("Frame", { - Size = UDim2.new(1, 0, 1, 0), - BackgroundColor3 = theme.BackgroundColor, - ZIndex = 0, - BorderSizePixel = 0, - }) - end), - }), - - RojoNotifications = e("ScreenGui", {}, { - layout = e("UIListLayout", { - SortOrder = Enum.SortOrder.LayoutOrder, - HorizontalAlignment = Enum.HorizontalAlignment.Right, - VerticalAlignment = Enum.VerticalAlignment.Bottom, - Padding = UDim.new(0, 5), - }), - padding = e("UIPadding", { - PaddingTop = UDim.new(0, 5); - PaddingBottom = UDim.new(0, 5); - PaddingLeft = UDim.new(0, 5); - PaddingRight = UDim.new(0, 5); - }), - notifs = e(Notifications, { - soundPlayer = self.props.soundPlayer, - notifications = self.state.notifications, - onClose = function(index) - self:closeNotification(index) - end, + RojoNotifications = e("ScreenGui", {}, { + layout = e("UIListLayout", { + SortOrder = Enum.SortOrder.LayoutOrder, + HorizontalAlignment = Enum.HorizontalAlignment.Right, + VerticalAlignment = Enum.VerticalAlignment.Bottom, + Padding = UDim.new(0, 5), + }), + padding = e("UIPadding", { + PaddingTop = UDim.new(0, 5); + PaddingBottom = UDim.new(0, 5); + PaddingLeft = UDim.new(0, 5); + PaddingRight = UDim.new(0, 5); + }), + notifs = e(Notifications, { + soundPlayer = self.props.soundPlayer, + notifications = self.state.notifications, + onClose = function(index) + self:closeNotification(index) + end, + }), }), }), From 7994bc4909f5a5b5f3f17b0724dffeca22fa2dfb Mon Sep 17 00:00:00 2001 From: ok-nick <25470747+ok-nick@users.noreply.github.com> Date: Fri, 18 Nov 2022 03:32:13 -0500 Subject: [PATCH 1272/1504] Update setup-aftman (#648) --- .github/workflows/ci.yml | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index adad0143..77ac7dbf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -29,11 +29,9 @@ jobs: profile: minimal - name: Setup Aftman - uses: ok-nick/setup-aftman@v0.1.0 + uses: ok-nick/setup-aftman@v0.3.0 with: - token: ${{ secrets.GITHUB_TOKEN }} - trust-check: false - version: 'v0.2.6' + version: 'v0.2.7' - name: Install packages run: | @@ -62,11 +60,9 @@ jobs: components: rustfmt, clippy - name: Setup Aftman - uses: ok-nick/setup-aftman@v0.1.0 + uses: ok-nick/setup-aftman@v0.3.0 with: - token: ${{ secrets.GITHUB_TOKEN }} - trust-check: false - version: 'v0.2.6' + version: 'v0.2.7' - name: Install packages run: | From b5ed952d5c3b81edc38f180112bfcc4ef6faf098 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 1 Apr 2023 23:17:23 -0400 Subject: [PATCH 1273/1504] Add visual diffs to syncing (#603) * Add user confirmation to initial sync * Use "Accept" instead of "Confirm" * Draw tree alphabetically for determinism * Add diff table dropdown * Add diff table to newly added objects * Unblock keybind workflow * Only show reject button when two way is enabled * Try to patch back to the files when changes are rejected * Improve text spacing of the prop diff table * Skip user confirmation of perfect syncs * Give instances names for debugging UI * Optimize tree building * Efficiency: dynamic virtual scrolling & lazy rendering * Simplify virtual scroller logic and avoid wasteful rerenders * Remove debug print * Consistent naming * Move new patch applied callback into accept * Pcall archivable * Keybinds open popup diff window * Theme rows in diff * Remove relic of prototype * Color value visuals and better component name * changeBatcher is not needed when no sync is active * Simplify popup roact entrypoint * Alphabetical prop lists and refactor * Add a stroke to color blot for contrast * Make color blots animate transparency with the rest of the page * StyLua formatting on newly added files * Remove wasteful table * Fix diffing custom properties * Display tables more meaningfully * Allow children in the button components * Create a rough tooltip component * Add tooltips to buttons * Use provider+trigger schema to avoid tooltip ZIndex issues * Add triangle point to tooltip * Tooltip underneath instead of covering * Cancel hovers when unmounting * Allow multiple canvases from one provider * Display above or below depending on available space * Move patch equality to PatchSet.isEqual * Use Container * Remove old submodules * Reduce false positives in diff * Add debug log * Fuzzy equals CFrame in diffs to avoid floating point in * Fix decodeValue usage * Support the .changedName patches * Fix content overlapping border * Fix tooltip tail alignment * Fix tooltip text fit * Whoops, fix it properly * Move PatchVisualizer to Components * Provide Connected info with full patch data * Avoid implicit nil return * Add patch visualizer to connected page * Make Current column invisible when visualizing applied patches * Avoid floating point diffs in a numbers and vectors --- .../src/App/Components/BorderedContainer.lua | 3 +- .../Components/PatchVisualizer/ChangeList.lua | 181 ++++++++ .../PatchVisualizer/DisplayValue.lua | 107 +++++ .../Components/PatchVisualizer/DomLabel.lua | 180 ++++++++ .../App/Components/PatchVisualizer/init.lua | 402 ++++++++++++++++++ .../App/Components/Studio/StudioPluginGui.lua | 27 +- plugin/src/App/Components/Tooltip.lua | 6 +- plugin/src/App/Components/VirtualScroller.lua | 156 +++++++ plugin/src/App/StatusPages/Confirming.lua | 156 +++++++ plugin/src/App/StatusPages/Connected.lua | 126 +++++- plugin/src/App/StatusPages/NotConnected.lua | 1 + plugin/src/App/StatusPages/init.lua | 3 +- plugin/src/App/Theme.lua | 12 + plugin/src/App/init.lua | 115 +++-- plugin/src/Assets.lua | 5 + plugin/src/PatchSet.lua | 60 +++ plugin/src/Reconciler/diff.lua | 83 +++- plugin/src/ServeSession.lua | 74 +++- plugin/watch-build.sh | 2 + 19 files changed, 1618 insertions(+), 81 deletions(-) create mode 100644 plugin/src/App/Components/PatchVisualizer/ChangeList.lua create mode 100644 plugin/src/App/Components/PatchVisualizer/DisplayValue.lua create mode 100644 plugin/src/App/Components/PatchVisualizer/DomLabel.lua create mode 100644 plugin/src/App/Components/PatchVisualizer/init.lua create mode 100644 plugin/src/App/Components/VirtualScroller.lua create mode 100644 plugin/src/App/StatusPages/Confirming.lua create mode 100644 plugin/watch-build.sh diff --git a/plugin/src/App/Components/BorderedContainer.lua b/plugin/src/App/Components/BorderedContainer.lua index 401d5676..42fec65c 100644 --- a/plugin/src/App/Components/BorderedContainer.lua +++ b/plugin/src/App/Components/BorderedContainer.lua @@ -24,7 +24,8 @@ local function BorderedContainer(props) layoutOrder = props.layoutOrder, }, { Content = e("Frame", { - Size = UDim2.new(1, 0, 1, 0), + Size = UDim2.new(1, -2, 1, -2), + Position = UDim2.new(0, 1, 0, 1), BackgroundTransparency = 1, ZIndex = 2, }, props[Roact.Children]), diff --git a/plugin/src/App/Components/PatchVisualizer/ChangeList.lua b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua new file mode 100644 index 00000000..beb0d327 --- /dev/null +++ b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua @@ -0,0 +1,181 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) + +local Theme = require(Plugin.App.Theme) +local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) +local DisplayValue = require(script.Parent.DisplayValue) + +local e = Roact.createElement + +local ChangeList = Roact.Component:extend("ChangeList") + +function ChangeList:init() + self.contentSize, self.setContentSize = Roact.createBinding(Vector2.new(0, 0)) +end + +function ChangeList:render() + return Theme.with(function(theme) + local props = self.props + local changes = props.changes + + -- Color alternating rows for readability + local rowTransparency = props.transparency:map(function(t) + return 0.93 + (0.07 * t) + end) + + local columnVisibility = props.columnVisibility + + local rows = {} + local pad = { + PaddingLeft = UDim.new(0, 5), + PaddingRight = UDim.new(0, 5), + } + + local headers = e("Frame", { + Size = UDim2.new(1, 0, 0, 30), + BackgroundTransparency = rowTransparency, + BackgroundColor3 = theme.Diff.Row, + LayoutOrder = 0, + }, { + Padding = e("UIPadding", pad), + Layout = e("UIListLayout", { + FillDirection = Enum.FillDirection.Horizontal, + SortOrder = Enum.SortOrder.LayoutOrder, + HorizontalAlignment = Enum.HorizontalAlignment.Left, + VerticalAlignment = Enum.VerticalAlignment.Center, + }), + A = e("TextLabel", { + Visible = columnVisibility[1], + Text = tostring(changes[1][1]), + BackgroundTransparency = 1, + Font = Enum.Font.GothamBold, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = props.transparency, + TextTruncate = Enum.TextTruncate.AtEnd, + Size = UDim2.new(0.3, 0, 1, 0), + LayoutOrder = 1, + }), + B = e("TextLabel", { + Visible = columnVisibility[2], + Text = tostring(changes[1][2]), + BackgroundTransparency = 1, + Font = Enum.Font.GothamBold, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = props.transparency, + TextTruncate = Enum.TextTruncate.AtEnd, + Size = UDim2.new(0.35, 0, 1, 0), + LayoutOrder = 2, + }), + C = e("TextLabel", { + Visible = columnVisibility[3], + Text = tostring(changes[1][3]), + BackgroundTransparency = 1, + Font = Enum.Font.GothamBold, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = props.transparency, + TextTruncate = Enum.TextTruncate.AtEnd, + Size = UDim2.new(0.35, 0, 1, 0), + LayoutOrder = 3, + }), + }) + + for row, values in changes do + if row == 1 then + continue -- Skip headers, already handled above + end + + rows[row] = e("Frame", { + Size = UDim2.new(1, 0, 0, 30), + BackgroundTransparency = row % 2 ~= 0 and rowTransparency or 1, + BackgroundColor3 = theme.Diff.Row, + BorderSizePixel = 0, + LayoutOrder = row, + }, { + Padding = e("UIPadding", pad), + Layout = e("UIListLayout", { + FillDirection = Enum.FillDirection.Horizontal, + SortOrder = Enum.SortOrder.LayoutOrder, + HorizontalAlignment = Enum.HorizontalAlignment.Left, + VerticalAlignment = Enum.VerticalAlignment.Center, + }), + A = e("TextLabel", { + Visible = columnVisibility[1], + Text = tostring(values[1]), + BackgroundTransparency = 1, + Font = Enum.Font.GothamMedium, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = props.transparency, + TextTruncate = Enum.TextTruncate.AtEnd, + Size = UDim2.new(0.3, 0, 1, 0), + LayoutOrder = 1, + }), + B = e( + "Frame", + { + Visible = columnVisibility[2], + BackgroundTransparency = 1, + Size = UDim2.new(0.35, 0, 1, 0), + LayoutOrder = 2, + }, + e(DisplayValue, { + value = values[2], + transparency = props.transparency, + }) + ), + C = e( + "Frame", + { + Visible = columnVisibility[3], + BackgroundTransparency = 1, + Size = UDim2.new(0.35, 0, 1, 0), + LayoutOrder = 3, + }, + e(DisplayValue, { + value = values[3], + transparency = props.transparency, + }) + ), + }) + end + + table.insert( + rows, + e("UIListLayout", { + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + HorizontalAlignment = Enum.HorizontalAlignment.Right, + VerticalAlignment = Enum.VerticalAlignment.Top, + + [Roact.Change.AbsoluteContentSize] = function(object) + self.setContentSize(object.AbsoluteContentSize) + end, + }) + ) + + return e("Frame", { + Size = UDim2.new(1, 0, 1, 0), + BackgroundTransparency = 1, + }, { + Headers = headers, + Values = e(ScrollingFrame, { + size = UDim2.new(1, 0, 1, -30), + position = UDim2.new(0, 0, 0, 30), + contentSize = self.contentSize, + transparency = props.transparency, + }, rows), + }) + end) +end + +return ChangeList diff --git a/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua b/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua new file mode 100644 index 00000000..891ec9f2 --- /dev/null +++ b/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua @@ -0,0 +1,107 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) + +local Theme = require(Plugin.App.Theme) + +local e = Roact.createElement + +local function DisplayValue(props) + return Theme.with(function(theme) + local t = typeof(props.value) + if t == "Color3" then + -- Colors get a blot that shows the color + return Roact.createFragment({ + Blot = e("Frame", { + BackgroundTransparency = props.transparency, + BackgroundColor3 = props.value, + Size = UDim2.new(0, 20, 0, 20), + Position = UDim2.new(0, 0, 0.5, 0), + AnchorPoint = Vector2.new(0, 0.5), + }, { + Corner = e("UICorner", { + CornerRadius = UDim.new(0, 4), + }), + Stroke = e("UIStroke", { + Color = theme.BorderedContainer.BorderColor, + Transparency = props.transparency, + }), + }), + Label = e("TextLabel", { + Text = string.format("%d,%d,%d", props.value.R * 255, props.value.G * 255, props.value.B * 255), + BackgroundTransparency = 1, + Font = Enum.Font.GothamMedium, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = props.transparency, + TextTruncate = Enum.TextTruncate.AtEnd, + Size = UDim2.new(1, -25, 1, 0), + Position = UDim2.new(0, 25, 0, 0), + }), + }) + + elseif t == "table" then + -- Showing a memory address for tables is useless, so we want to show the best we can + local textRepresentation = nil + + local meta = getmetatable(props.value) + if meta and meta.__tostring then + -- If the table has a tostring metamethod, use that + textRepresentation = tostring(props.value) + elseif next(props.value) == nil then + -- If it's empty, show empty braces + textRepresentation = "{}" + else + -- If it has children, list them out + local out, i = {}, 0 + for k, v in pairs(props.value) do + i += 1 + + -- Wrap strings in quotes + if type(k) == "string" then + k = "\"" .. k .. "\"" + end + if type(v) == "string" then + v = "\"" .. v .. "\"" + end + + out[i] = string.format("[%s] = %s", tostring(k), tostring(v)) + end + textRepresentation = "{ " .. table.concat(out, ", ") .. " }" + end + + return e("TextLabel", { + Text = textRepresentation, + BackgroundTransparency = 1, + Font = Enum.Font.GothamMedium, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = props.transparency, + TextTruncate = Enum.TextTruncate.AtEnd, + Size = UDim2.new(1, 0, 1, 0), + }) + end + + -- TODO: Maybe add visualizations to other datatypes? + -- Or special text handling tostring for some? + -- Will add as needed, let's see what cases arise. + + return e("TextLabel", { + Text = string.gsub(tostring(props.value), "%s", " "), + BackgroundTransparency = 1, + Font = Enum.Font.GothamMedium, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = props.transparency, + TextTruncate = Enum.TextTruncate.AtEnd, + Size = UDim2.new(1, 0, 1, 0), + }) + end) +end + +return DisplayValue diff --git a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua new file mode 100644 index 00000000..8d282ab9 --- /dev/null +++ b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua @@ -0,0 +1,180 @@ +local StudioService = game:GetService("StudioService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) +local Flipper = require(Packages.Flipper) + +local Assets = require(Plugin.Assets) +local Theme = require(Plugin.App.Theme) +local bindingUtil = require(Plugin.App.bindingUtil) + +local e = Roact.createElement + +local ChangeList = require(script.Parent.ChangeList) + +local Expansion = Roact.Component:extend("Expansion") + +function Expansion:render() + local props = self.props + + if not props.rendered then + return nil + end + + return e("Frame", { + BackgroundTransparency = 1, + Size = UDim2.new(1, -props.indent, 1, -30), + Position = UDim2.new(0, props.indent, 0, 30), + }, { + ChangeList = e(ChangeList, { + changes = props.changeList, + transparency = props.transparency, + columnVisibility = props.columnVisibility, + }), + }) +end + +local DomLabel = Roact.Component:extend("DomLabel") + +function DomLabel:init() + self.maxElementHeight = 0 + if self.props.changeList then + self.maxElementHeight = math.clamp(#self.props.changeList * 30, 30, 30 * 6) + end + + local initHeight = self.props.elementHeight:getValue() + self.expanded = initHeight > 30 + + self.motor = Flipper.SingleMotor.new(initHeight) + self.binding = bindingUtil.fromMotor(self.motor) + + self:setState({ + renderExpansion = self.expanded, + }) + self.motor:onStep(function(value) + local renderExpansion = value > 30 + + self.props.setElementHeight(value) + if self.props.updateEvent then + self.props.updateEvent:Fire() + end + + self:setState(function(state) + if state.renderExpansion == renderExpansion then + return nil + end + + return { + renderExpansion = renderExpansion, + } + end) + end) +end + +function DomLabel:render() + local props = self.props + + return Theme.with(function(theme) + local iconProps = StudioService:GetClassIcon(props.className) + local indent = (props.depth or 0) * 20 + 25 + + -- Line guides help indent depth remain readable + local lineGuides = {} + for i = 1, props.depth or 0 do + table.insert( + lineGuides, + e("Frame", { + Name = "Line_" .. i, + Size = UDim2.new(0, 2, 1, 2), + Position = UDim2.new(0, (20 * i) + 15, 0, -1), + BorderSizePixel = 0, + BackgroundTransparency = props.transparency, + BackgroundColor3 = theme.BorderedContainer.BorderColor, + }) + ) + end + + return e("Frame", { + Name = "Change", + ClipsDescendants = true, + BackgroundColor3 = if props.patchType then theme.Diff[props.patchType] else nil, + BorderSizePixel = 0, + BackgroundTransparency = props.patchType and props.transparency or 1, + Size = self.binding:map(function(expand) + return UDim2.new(1, 0, 0, expand) + end), + }, { + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 10), + PaddingRight = UDim.new(0, 10), + }), + ExpandButton = if props.changeList + then e("TextButton", { + BackgroundTransparency = 1, + Text = "", + Size = UDim2.new(1, 0, 1, 0), + [Roact.Event.Activated] = function() + self.expanded = not self.expanded + self.motor:setGoal(Flipper.Spring.new((self.expanded and self.maxElementHeight or 0) + 30, { + frequency = 5, + dampingRatio = 1, + })) + end, + }) + else nil, + Expansion = if props.changeList + then e(Expansion, { + rendered = self.state.renderExpansion, + indent = indent, + transparency = props.transparency, + changeList = props.changeList, + columnVisibility = props.columnVisibility, + }) + else nil, + DiffIcon = if props.patchType + then e("ImageLabel", { + Image = Assets.Images.Diff[props.patchType], + ImageColor3 = theme.AddressEntry.PlaceholderColor, + ImageTransparency = props.transparency, + BackgroundTransparency = 1, + Size = UDim2.new(0, 20, 0, 20), + Position = UDim2.new(0, 0, 0, 15), + AnchorPoint = Vector2.new(0, 0.5), + }) + else nil, + ClassIcon = e("ImageLabel", { + Image = iconProps.Image, + ImageTransparency = props.transparency, + ImageRectOffset = iconProps.ImageRectOffset, + ImageRectSize = iconProps.ImageRectSize, + BackgroundTransparency = 1, + Size = UDim2.new(0, 20, 0, 20), + Position = UDim2.new(0, indent, 0, 15), + AnchorPoint = Vector2.new(0, 0.5), + }), + InstanceName = e("TextLabel", { + Text = props.name .. (props.hint and string.format( + ' %s', + theme.AddressEntry.PlaceholderColor:ToHex(), + props.hint + ) or ""), + RichText = true, + BackgroundTransparency = 1, + Font = Enum.Font.GothamMedium, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = props.transparency, + TextTruncate = Enum.TextTruncate.AtEnd, + Size = UDim2.new(1, -indent - 50, 0, 30), + Position = UDim2.new(0, indent + 30, 0, 0), + }), + LineGuides = e("Folder", nil, lineGuides), + }) + end) +end + +return DomLabel diff --git a/plugin/src/App/Components/PatchVisualizer/init.lua b/plugin/src/App/Components/PatchVisualizer/init.lua new file mode 100644 index 00000000..95673dfe --- /dev/null +++ b/plugin/src/App/Components/PatchVisualizer/init.lua @@ -0,0 +1,402 @@ +local HttpService = game:GetService("HttpService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) +local Log = require(Packages.Log) + +local PatchSet = require(Plugin.PatchSet) +local decodeValue = require(Plugin.Reconciler.decodeValue) +local getProperty = require(Plugin.Reconciler.getProperty) + +local BorderedContainer = require(Plugin.App.Components.BorderedContainer) +local VirtualScroller = require(Plugin.App.Components.VirtualScroller) + +local e = Roact.createElement + +local function alphabeticalNext(t, state) + -- Equivalent of the next function, but returns the keys in the alphabetic + -- order of node names. We use a temporary ordered key table that is stored in the + -- table being iterated. + + local key = nil + if state == nil then + -- First iteration, generate the index + local orderedIndex, i = table.create(5), 0 + for k in t do + i += 1 + orderedIndex[i] = k + end + table.sort(orderedIndex, function(a, b) + local nodeA, nodeB = t[a], t[b] + return (nodeA.name or "") < (nodeB.name or "") + end) + + t.__orderedIndex = orderedIndex + key = orderedIndex[1] + else + -- Fetch the next value + for i, orderedState in t.__orderedIndex do + if orderedState == state then + key = t.__orderedIndex[i + 1] + break + end + end + end + + if key then + return key, t[key] + end + + -- No more value to return, cleanup + t.__orderedIndex = nil + return +end + +local function alphabeticalPairs(t) + -- Equivalent of the pairs() iterator, but sorted + return alphabeticalNext, t, nil +end + +local function Tree() + local tree = { + idToNode = {}, + ROOT = { + className = "DataModel", + name = "ROOT", + children = {}, + }, + } + -- Add ROOT to idToNode or it won't be found by getNode since that searches *within* ROOT + tree.idToNode["ROOT"] = tree.ROOT + + function tree:getNode(id, target) + if self.idToNode[id] then + return self.idToNode[id] + end + + for nodeId, node in target or tree.ROOT.children do + if nodeId == id then + self.idToNode[id] = node + return node + end + local descendant = self:getNode(id, node.children) + if descendant then + return descendant + end + end + + return nil + end + + function tree:addNode(parent, props) + parent = parent or "ROOT" + + local node = self:getNode(props.id) + if node then + for k, v in props do + node[k] = v + end + return node + end + + node = table.clone(props) + node.children = {} + + local parentNode = self:getNode(parent) + if not parentNode then + Log.warn("Failed to create node since parent doesnt exist: {}, {}", parent, props) + return + end + + parentNode.children[node.id] = node + self.idToNode[node.id] = node + + return node + end + + function tree:buildAncestryNodes(ancestry, patch, instanceMap) + -- Build nodes for ancestry by going up the tree + local previousId = "ROOT" + for _, ancestorId in ancestry do + local value = instanceMap.fromIds[ancestorId] or patch.added[ancestorId] + if not value then + Log.warn("Failed to find ancestor object for " .. ancestorId) + continue + end + self:addNode(previousId, { + id = ancestorId, + className = value.ClassName, + name = value.Name, + }) + previousId = ancestorId + end + end + + return tree +end + +local DomLabel = require(script.DomLabel) + +local PatchVisualizer = Roact.Component:extend("PatchVisualizer") + +function PatchVisualizer:init() + self.contentSize, self.setContentSize = Roact.createBinding(Vector2.new(0, 0)) + + self.updateEvent = Instance.new("BindableEvent") +end + +function PatchVisualizer:willUnmount() + self.updateEvent:Destroy() +end + +function PatchVisualizer:shouldUpdate(nextProps) + local currentPatch, nextPatch = self.props.patch, nextProps.patch + + return not PatchSet.isEqual(currentPatch, nextPatch) +end + +function PatchVisualizer:buildTree(patch, instanceMap) + local tree = Tree() + + for _, change in patch.updated do + local instance = instanceMap.fromIds[change.id] + if not instance then + continue + end + + -- Gather ancestors from existing DOM + local ancestry = {} + local parentObject = instance.Parent + local parentId = instanceMap.fromInstances[parentObject] + while parentObject do + table.insert(ancestry, 1, parentId) + parentObject = parentObject.Parent + parentId = instanceMap.fromInstances[parentObject] + end + + tree:buildAncestryNodes(ancestry, patch, instanceMap) + + -- Gather detail text + local changeList, hint = nil, nil + if next(change.changedProperties) or change.changedName then + changeList = {} + + local hintBuffer, i = {}, 0 + local function addProp(prop: string, current: any?, incoming: any?) + i += 1 + hintBuffer[i] = prop + changeList[i] = { prop, current, incoming } + end + + -- Gather the changes + + if change.changedName then + addProp("Name", instance.Name, change.changedName) + end + + for prop, incoming in change.changedProperties do + local incomingSuccess, incomingValue = decodeValue(incoming, instanceMap) + local currentSuccess, currentValue = getProperty(instance, prop) + + addProp( + prop, + if currentSuccess then currentValue else "[Error]", + if incomingSuccess then incomingValue else next(incoming) + ) + end + + -- Finalize detail values + + -- Trim hint to top 3 + table.sort(hintBuffer) + if #hintBuffer > 3 then + hintBuffer = { + hintBuffer[1], + hintBuffer[2], + hintBuffer[3], + i - 3 .. " more", + } + end + hint = table.concat(hintBuffer, ", ") + + -- Sort changes and add header + table.sort(changeList, function(a, b) + return a[1] < b[1] + end) + table.insert(changeList, 1, { "Property", "Current", "Incoming" }) + end + + -- Add this node to tree + tree:addNode(instanceMap.fromInstances[instance.Parent], { + id = change.id, + patchType = "Edit", + className = instance.ClassName, + name = instance.Name, + hint = hint, + changeList = changeList, + }) + end + + for _, instance in patch.removed do + -- Gather ancestors from existing DOM + -- (note that they may have no ID if they're being removed as unknown) + local ancestry = {} + local parentObject = instance.Parent + local parentId = instanceMap.fromInstances[parentObject] or HttpService:GenerateGUID(false) + while parentObject do + instanceMap:insert(parentId, parentObject) + table.insert(ancestry, 1, parentId) + parentObject = parentObject.Parent + parentId = instanceMap.fromInstances[parentObject] or HttpService:GenerateGUID(false) + end + + tree:buildAncestryNodes(ancestry, patch, instanceMap) + + -- Add this node to tree + local nodeId = instanceMap.fromInstances[instance] or HttpService:GenerateGUID(false) + instanceMap:insert(nodeId, instance) + tree:addNode(instanceMap.fromInstances[instance.Parent], { + id = nodeId, + patchType = "Remove", + className = instance.ClassName, + name = instance.Name, + }) + end + + for _, change in patch.added do + -- Gather ancestors from existing DOM or future additions + local ancestry = {} + local parentId = change.Parent + local parentData = patch.added[parentId] + local parentObject = instanceMap.fromIds[parentId] + while parentId do + table.insert(ancestry, 1, parentId) + parentId = nil + + if parentData then + parentId = parentData.Parent + parentData = patch.added[parentId] + parentObject = instanceMap.fromIds[parentId] + elseif parentObject then + parentObject = parentObject.Parent + parentId = instanceMap.fromInstances[parentObject] + parentData = patch.added[parentId] + end + end + + tree:buildAncestryNodes(ancestry, patch, instanceMap) + + -- Gather detail text + local changeList, hint = nil, nil + if next(change.Properties) then + changeList = {} + + local hintBuffer, i = {}, 0 + for prop, incoming in change.Properties do + i += 1 + hintBuffer[i] = prop + + local success, incomingValue = decodeValue(incoming, instanceMap) + if success then + table.insert(changeList, { prop, "N/A", incomingValue }) + else + table.insert(changeList, { prop, "N/A", next(incoming) }) + end + end + + -- Finalize detail values + + -- Trim hint to top 3 + table.sort(hintBuffer) + if #hintBuffer > 3 then + hintBuffer = { + hintBuffer[1], + hintBuffer[2], + hintBuffer[3], + i - 3 .. " more", + } + end + hint = table.concat(hintBuffer, ", ") + + -- Sort changes and add header + table.sort(changeList, function(a, b) + return a[1] < b[1] + end) + table.insert(changeList, 1, { "Property", "Current", "Incoming" }) + end + + -- Add this node to tree + tree:addNode(change.Parent, { + id = change.Id, + patchType = "Add", + className = change.ClassName, + name = change.Name, + hint = hint, + changeList = changeList, + }) + end + + return tree +end + +function PatchVisualizer:render() + local patch = self.props.patch + local instanceMap = self.props.instanceMap + + local tree = self:buildTree(patch, instanceMap) + + -- Recusively draw tree + local scrollElements, elementHeights = {}, {} + local function drawNode(node, depth) + local elementHeight, setElementHeight = Roact.createBinding(30) + table.insert(elementHeights, elementHeight) + table.insert( + scrollElements, + e(DomLabel, { + columnVisibility = self.props.columnVisibility, + updateEvent = self.updateEvent, + elementHeight = elementHeight, + setElementHeight = setElementHeight, + patchType = node.patchType, + className = node.className, + name = node.name, + hint = node.hint, + changeList = node.changeList, + depth = depth, + transparency = self.props.transparency, + }) + ) + + for _, childNode in alphabeticalPairs(node.children) do + drawNode(childNode, depth + 1) + end + end + for _, node in alphabeticalPairs(tree.ROOT.children) do + drawNode(node, 0) + end + + return e(BorderedContainer, { + transparency = self.props.transparency, + size = self.props.size, + position = self.props.position, + layoutOrder = self.props.layoutOrder, + }, { + VirtualScroller = e(VirtualScroller, { + size = UDim2.new(1, 0, 1, 0), + transparency = self.props.transparency, + count = #scrollElements, + updateEvent = self.updateEvent.Event, + render = function(i) + return scrollElements[i] + end, + getHeightBinding = function(i) + return elementHeights[i] + end, + }), + }) +end + +return PatchVisualizer diff --git a/plugin/src/App/Components/Studio/StudioPluginGui.lua b/plugin/src/App/Components/Studio/StudioPluginGui.lua index e078572b..59bd3d85 100644 --- a/plugin/src/App/Components/Studio/StudioPluginGui.lua +++ b/plugin/src/App/Components/Studio/StudioPluginGui.lua @@ -5,6 +5,7 @@ local Packages = Rojo.Packages local Roact = require(Packages.Roact) local Dictionary = require(Plugin.Dictionary) +local Theme = require(Plugin.App.Theme) local StudioPluginContext = require(script.Parent.StudioPluginContext) @@ -29,8 +30,10 @@ function StudioPluginGui:init() self.props.initDockState, self.props.active, self.props.overridePreviousState, - floatingSize.X, floatingSize.Y, - minimumSize.X, minimumSize.Y + floatingSize.X, + floatingSize.Y, + minimumSize.X, + minimumSize.Y ) local pluginGui = self.props.plugin:CreateDockWidgetPluginGui(self.props.id, dockWidgetPluginGuiInfo) @@ -57,7 +60,16 @@ end function StudioPluginGui:render() return e(Roact.Portal, { target = self.pluginGui, - }, self.props[Roact.Children]) + }, { + Background = Theme.with(function(theme) + return e("Frame", { + Size = UDim2.new(1, 0, 1, 0), + BackgroundColor3 = theme.BackgroundColor, + ZIndex = 0, + BorderSizePixel = 0, + }, self.props[Roact.Children]) + end), + }) end function StudioPluginGui:didUpdate(lastProps) @@ -75,9 +87,12 @@ end local function StudioPluginGuiWrapper(props) return e(StudioPluginContext.Consumer, { render = function(plugin) - return e(StudioPluginGui, Dictionary.merge(props, { - plugin = plugin, - })) + return e( + StudioPluginGui, + Dictionary.merge(props, { + plugin = plugin, + }) + ) end, }) end diff --git a/plugin/src/App/Components/Tooltip.lua b/plugin/src/App/Components/Tooltip.lua index e30a3603..bc3443d5 100644 --- a/plugin/src/App/Components/Tooltip.lua +++ b/plugin/src/App/Components/Tooltip.lua @@ -23,7 +23,7 @@ local TooltipContext = Roact.createContext({}) local function Popup(props) local textSize = TextService:GetTextSize( props.Text, 16, Enum.Font.GothamMedium, Vector2.new(math.min(props.parentSize.X, 160), math.huge) - ) + TEXT_PADDING + ) + TEXT_PADDING + (Vector2.one * 2) local trigger = props.Trigger:getValue() @@ -68,12 +68,12 @@ local function Popup(props) if displayAbove then UDim2.new( 0, math.clamp(props.Position.X - X, 6, textSize.X-6), - 1, -3 + 1, -1 ) else UDim2.new( 0, math.clamp(props.Position.X - X, 6, textSize.X-6), - 0, -TAIL_SIZE+3 + 0, -TAIL_SIZE+1 ), Size = UDim2.fromOffset(TAIL_SIZE, TAIL_SIZE), AnchorPoint = Vector2.new(0.5, 0), diff --git a/plugin/src/App/Components/VirtualScroller.lua b/plugin/src/App/Components/VirtualScroller.lua new file mode 100644 index 00000000..2922a74f --- /dev/null +++ b/plugin/src/App/Components/VirtualScroller.lua @@ -0,0 +1,156 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) + +local Assets = require(Plugin.Assets) +local Theme = require(Plugin.App.Theme) +local bindingUtil = require(Plugin.App.bindingUtil) + +local e = Roact.createElement + +local VirtualScroller = Roact.Component:extend("VirtualScroller") + +function VirtualScroller:init() + self.scrollFrameRef = Roact.createRef() + self:setState({ + WindowSize = Vector2.new(), + CanvasPosition = Vector2.new(), + }) + + self.totalCanvas, self.setTotalCanvas = Roact.createBinding(0) + self.padding, self.setPadding = Roact.createBinding(0) + + self:refresh() + if self.props.updateEvent then + self.connection = self.props.updateEvent:Connect(function() + self:refresh() + end) + end +end + +function VirtualScroller:didMount() + local rbx = self.scrollFrameRef:getValue() + + local windowSizeSignal = rbx:GetPropertyChangedSignal("AbsoluteWindowSize") + self.windowSizeChanged = windowSizeSignal:Connect(function() + self:setState({ WindowSize = rbx.AbsoluteWindowSize }) + self:refresh() + end) + + local canvasPositionSignal = rbx:GetPropertyChangedSignal("CanvasPosition") + self.canvasPositionChanged = canvasPositionSignal:Connect(function() + if math.abs(rbx.CanvasPosition.Y - self.state.CanvasPosition.Y) > 5 then + self:setState({ CanvasPosition = rbx.CanvasPosition }) + self:refresh() + end + end) + + self:refresh() +end + +function VirtualScroller:willUnmount() + self.windowSizeChanged:Disconnect() + self.canvasPositionChanged:Disconnect() + if self.connection then + self.connection:Disconnect() + self.connection = nil + end +end + +function VirtualScroller:refresh() + local props = self.props + local state = self.state + + local count = props.count + local windowSize, canvasPosition = state.WindowSize.Y, state.CanvasPosition.Y + local bottom = canvasPosition + windowSize + + local minIndex, maxIndex = 1, count + local padding, canvasSize = 0, 0 + + local pos = 0 + for i = 1, count do + local height = props.getHeightBinding(i):getValue() + canvasSize += height + + if pos > bottom then + -- Below window + if maxIndex > i then + maxIndex = i + end + end + + pos += height + + if pos < canvasPosition then + -- Above window + minIndex = i + padding = pos - height + end + end + + self.setPadding(padding) + self.setTotalCanvas(canvasSize) + self:setState({ + Start = minIndex, + End = maxIndex, + }) +end + +function VirtualScroller:render() + local props, state = self.props, self.state + + local items = {} + for i = state.Start, state.End do + items["Item" .. i] = e("Frame", { + LayoutOrder = i, + Size = props.getHeightBinding(i):map(function(height) + return UDim2.new(1, 0, 0, height) + end), + BackgroundTransparency = 1, + }, props.render(i)) + end + + return Theme.with(function(theme) + return e("ScrollingFrame", { + Size = props.size, + Position = props.position, + AnchorPoint = props.anchorPoint, + BackgroundTransparency = props.backgroundTransparency or 1, + BackgroundColor3 = props.backgroundColor3, + BorderColor3 = props.borderColor3, + CanvasSize = self.totalCanvas:map(function(s) + return UDim2.fromOffset(0, s) + end), + ScrollBarThickness = 9, + ScrollBarImageColor3 = theme.ScrollBarColor, + ScrollBarImageTransparency = props.transparency:map(function(value) + return bindingUtil.blendAlpha({ 0.65, value }) + end), + TopImage = Assets.Images.ScrollBar.Top, + MidImage = Assets.Images.ScrollBar.Middle, + BottomImage = Assets.Images.ScrollBar.Bottom, + + ElasticBehavior = Enum.ElasticBehavior.Always, + ScrollingDirection = Enum.ScrollingDirection.Y, + VerticalScrollBarInset = Enum.ScrollBarInset.ScrollBar, + [Roact.Ref] = self.scrollFrameRef, + }, { + Layout = e("UIListLayout", { + Padding = UDim.new(0, 0), + SortOrder = Enum.SortOrder.LayoutOrder, + FillDirection = Enum.FillDirection.Vertical, + }), + Padding = e("UIPadding", { + PaddingTop = self.padding:map(function(p) + return UDim.new(0, p) + end), + }), + Content = Roact.createFragment(items), + }) + end) +end + +return VirtualScroller diff --git a/plugin/src/App/StatusPages/Confirming.lua b/plugin/src/App/StatusPages/Confirming.lua new file mode 100644 index 00000000..3359eaf6 --- /dev/null +++ b/plugin/src/App/StatusPages/Confirming.lua @@ -0,0 +1,156 @@ +local TextService = game:GetService("TextService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) + +local Settings = require(Plugin.Settings) +local Theme = require(Plugin.App.Theme) +local TextButton = require(Plugin.App.Components.TextButton) +local Header = require(Plugin.App.Components.Header) +local StudioPluginGui = require(Plugin.App.Components.Studio.StudioPluginGui) +local Tooltip = require(Plugin.App.Components.Tooltip) +local PatchVisualizer = require(Plugin.App.Components.PatchVisualizer) + +local e = Roact.createElement + +local ConfirmingPage = Roact.Component:extend("ConfirmingPage") + +function ConfirmingPage:init() + self.contentSize, self.setContentSize = Roact.createBinding(0) + self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0)) +end + +function ConfirmingPage:render() + return Theme.with(function(theme) + local pageContent = Roact.createFragment({ + Header = e(Header, { + transparency = self.props.transparency, + layoutOrder = 1, + }), + + Title = e("TextLabel", { + Text = string.format( + "Sync changes for project '%s':", + self.props.confirmData.serverInfo.projectName or "UNKNOWN" + ), + LayoutOrder = 2, + Font = Enum.Font.Gotham, + LineHeight = 1.2, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = self.props.transparency, + Size = UDim2.new(1, 0, 0, 20), + BackgroundTransparency = 1, + }), + + PatchVisualizer = e(PatchVisualizer, { + size = UDim2.new(1, 0, 1, -150), + transparency = self.props.transparency, + layoutOrder = 3, + + columnVisibility = {true, true, true}, + patch = self.props.confirmData.patch, + instanceMap = self.props.confirmData.instanceMap, + }), + + Buttons = e("Frame", { + Size = UDim2.new(1, 0, 0, 34), + LayoutOrder = 4, + BackgroundTransparency = 1, + }, { + Abort = e(TextButton, { + text = "Abort", + style = "Bordered", + transparency = self.props.transparency, + layoutOrder = 1, + onClick = self.props.onAbort, + }, { + Tip = e(Tooltip.Trigger, { + text = "Stop the connection process" + }), + }), + + Reject = if Settings:get("twoWaySync") + then e(TextButton, { + text = "Reject", + style = "Bordered", + transparency = self.props.transparency, + layoutOrder = 2, + onClick = self.props.onReject, + }, { + Tip = e(Tooltip.Trigger, { + text = "Push Studio changes to the Rojo server" + }), + }) + else nil, + + Accept = e(TextButton, { + text = "Accept", + style = "Solid", + transparency = self.props.transparency, + layoutOrder = 3, + onClick = self.props.onAccept, + }, { + Tip = e(Tooltip.Trigger, { + text = "Pull Rojo server changes to Studio" + }), + }), + + Layout = e("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Right, + FillDirection = Enum.FillDirection.Horizontal, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 10), + }), + }), + + Layout = e("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 10), + }), + + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 20), + PaddingRight = UDim.new(0, 20), + }), + }) + + if self.props.createPopup then + return e(StudioPluginGui, { + id = "Rojo_DiffSync", + title = string.format( + "Confirm sync for project '%s':", + self.props.confirmData.serverInfo.projectName or "UNKNOWN" + ), + active = true, + + initDockState = Enum.InitialDockState.Float, + initEnabled = true, + overridePreviousState = true, + floatingSize = Vector2.new(500, 350), + minimumSize = Vector2.new(400, 250), + + zIndexBehavior = Enum.ZIndexBehavior.Sibling, + + onClose = self.props.onAbort, + }, { + Tooltips = e(Tooltip.Container, nil), + Content = e("Frame", { + Size = UDim2.fromScale(1, 1), + BackgroundTransparency = 1, + }, pageContent), + }) + end + + return pageContent + end) +end + +return ConfirmingPage diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index ac302d46..91484926 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -3,14 +3,18 @@ local Plugin = Rojo.Plugin local Packages = Rojo.Packages local Roact = require(Packages.Roact) +local Flipper = require(Packages.Flipper) +local bindingUtil = require(Plugin.App.bindingUtil) local Theme = require(Plugin.App.Theme) local Assets = require(Plugin.Assets) +local PatchSet = require(Plugin.PatchSet) local Header = require(Plugin.App.Components.Header) local IconButton = require(Plugin.App.Components.IconButton) local BorderedContainer = require(Plugin.App.Components.BorderedContainer) local Tooltip = require(Plugin.App.Components.Tooltip) +local PatchVisualizer = require(Plugin.App.Components.PatchVisualizer) local e = Roact.createElement @@ -34,6 +38,50 @@ function timeSinceText(elapsed: number): string return ageText end +local function ChangesDrawer(props) + if props.rendered == false then + return nil + end + + return Theme.with(function(theme) + return e(BorderedContainer, { + transparency = props.transparency, + size = props.height:map(function(y) + return UDim2.new(1, 0, y, -180 * y) + end), + position = UDim2.new(0, 0, 1, 0), + anchorPoint = Vector2.new(0, 1), + layoutOrder = props.layoutOrder, + }, { + Close = e(IconButton, { + icon = Assets.Images.Icons.Close, + iconSize = 24, + color = theme.ConnectionDetails.DisconnectColor, + transparency = props.transparency, + + position = UDim2.new(1, 0, 0, 0), + anchorPoint = Vector2.new(1, 0), + + onClick = props.onClose, + }, { + Tip = e(Tooltip.Trigger, { + text = "Close the patch visualizer" + }), + }), + + PatchVisualizer = e(PatchVisualizer, { + size = UDim2.new(1, 0, 1, 0), + transparency = props.transparency, + layoutOrder = 3, + + columnVisibility = {true, false, true}, + patch = props.patchInfo:getValue().patch, + instanceMap = props.serveSession.__instanceMap, + }), + }) + end) +end + local function ConnectionDetails(props) return Theme.with(function(theme) return e(BorderedContainer, { @@ -107,9 +155,44 @@ end local ConnectedPage = Roact.Component:extend("ConnectedPage") +function ConnectedPage:init() + self.changeDrawerMotor = Flipper.SingleMotor.new(0) + self.changeDrawerHeight = bindingUtil.fromMotor(self.changeDrawerMotor) + + self.changeDrawerMotor:onStep(function(value) + local renderChanges = value > 0.05 + + self:setState(function(state) + if state.renderChanges == renderChanges then + return nil + end + + return { + renderChanges = renderChanges, + } + end) + end) + + self:setState({ + renderChanges = false, + }) +end + function ConnectedPage:render() return Theme.with(function(theme) return Roact.createFragment({ + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 20), + PaddingRight = UDim.new(0, 20), + }), + + Layout = e("UIListLayout", { + VerticalAlignment = Enum.VerticalAlignment.Center, + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 10), + }), + Header = e(Header, { transparency = self.props.transparency, layoutOrder = 1, @@ -124,12 +207,13 @@ function ConnectedPage:render() onDisconnect = self.props.onDisconnect, }), - Info = e("TextLabel", { + ChangeInfo = e("TextButton", { Text = self.props.patchInfo:map(function(info) + local changes = PatchSet.countChanges(info.patch) return string.format( "Synced %d change%s %s", - info.changes, - info.changes == 1 and "" or "s", + changes, + changes == 1 and "" or "s", timeSinceText(os.time() - info.timestamp) ) end), @@ -146,18 +230,36 @@ function ConnectedPage:render() LayoutOrder = 3, BackgroundTransparency = 1, + + [Roact.Event.Activated] = function() + if self.state.renderChanges then + self.changeDrawerMotor:setGoal(Flipper.Spring.new(0, { + frequency = 4, + dampingRatio = 1, + })) + else + self.changeDrawerMotor:setGoal(Flipper.Spring.new(1, { + frequency = 3, + dampingRatio = 1, + })) + end + end, }), - Layout = e("UIListLayout", { - VerticalAlignment = Enum.VerticalAlignment.Center, - FillDirection = Enum.FillDirection.Vertical, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 10), - }), + ChangesDrawer = e(ChangesDrawer, { + rendered = self.state.renderChanges, + transparency = self.props.transparency, + patchInfo = self.props.patchInfo, + serveSession = self.props.serveSession, + height = self.changeDrawerHeight, + layoutOrder = 4, - Padding = e("UIPadding", { - PaddingLeft = UDim.new(0, 20), - PaddingRight = UDim.new(0, 20), + onClose = function() + self.changeDrawerMotor:setGoal(Flipper.Spring.new(0, { + frequency = 4, + dampingRatio = 1, + })) + end, }), }) end) diff --git a/plugin/src/App/StatusPages/NotConnected.lua b/plugin/src/App/StatusPages/NotConnected.lua index 40861ba5..3097446e 100644 --- a/plugin/src/App/StatusPages/NotConnected.lua +++ b/plugin/src/App/StatusPages/NotConnected.lua @@ -110,6 +110,7 @@ function NotConnectedPage:render() Size = UDim2.new(1, 0, 0, 34), LayoutOrder = 3, BackgroundTransparency = 1, + ZIndex = 2, }, { Settings = e(TextButton, { text = "Settings", diff --git a/plugin/src/App/StatusPages/init.lua b/plugin/src/App/StatusPages/init.lua index 03d64e45..111c9c55 100644 --- a/plugin/src/App/StatusPages/init.lua +++ b/plugin/src/App/StatusPages/init.lua @@ -2,6 +2,7 @@ return { NotConnected = require(script.NotConnected), Settings = require(script.Settings), Connecting = require(script.Connecting), + Confirming = require(script.Confirming), Connected = require(script.Connected), Error = require(script.Error), -} \ No newline at end of file +} diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index a6572484..309045be 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -95,6 +95,12 @@ local lightTheme = strict("LightTheme", { ForegroundColor = BRAND_COLOR, BackgroundColor = hexColor(0xEEEEEE), }, + Diff = { + Add = hexColor(0xbaffbd), + Remove = hexColor(0xffbdba), + Edit = hexColor(0xbacdff), + Row = hexColor(0x000000), + }, ConnectionDetails = { ProjectNameColor = hexColor(0x00000), AddressColor = hexColor(0x00000), @@ -184,6 +190,12 @@ local darkTheme = strict("DarkTheme", { ForegroundColor = BRAND_COLOR, BackgroundColor = hexColor(0x2B2B2B), }, + Diff = { + Add = hexColor(0x273732), + Remove = hexColor(0x3F2D32), + Edit = hexColor(0x193345), + Row = hexColor(0xFFFFFF), + }, ConnectionDetails = { ProjectNameColor = hexColor(0xFFFFFF), AddressColor = hexColor(0xFFFFFF), diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index f141d943..35df8ffb 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -16,6 +16,7 @@ local strict = require(Plugin.strict) local Dictionary = require(Plugin.Dictionary) local ServeSession = require(Plugin.ServeSession) local ApiContext = require(Plugin.ApiContext) +local PatchSet = require(Plugin.PatchSet) local preloadAssets = require(Plugin.preloadAssets) local soundPlayer = require(Plugin.soundPlayer) local Theme = require(script.Theme) @@ -34,6 +35,7 @@ local AppStatus = strict("AppStatus", { NotConnected = "NotConnected", Settings = "Settings", Connecting = "Connecting", + Confirming = "Confirming", Connected = "Connected", Error = "Error", }) @@ -50,13 +52,16 @@ function App:init() self.port, self.setPort = Roact.createBinding(priorPort or "") self.patchInfo, self.setPatchInfo = Roact.createBinding({ - changes = 0, + patch = PatchSet.newEmpty(), timestamp = os.time(), }) + self.confirmationBindable = Instance.new("BindableEvent") + self.confirmationEvent = self.confirmationBindable.Event self:setState({ appStatus = AppStatus.NotConnected, guiEnabled = false, + confirmData = {}, notifications = {}, toolbarIcon = Assets.Images.PluginButton, }) @@ -214,32 +219,31 @@ function App:startSession() twoWaySync = sessionOptions.twoWaySync, }) - serveSession:onPatchApplied(function(patch, unapplied) + serveSession:onPatchApplied(function(patch, _unapplied) + if PatchSet.isEmpty(patch) then + -- Ignore empty patches + return + end + local now = os.time() - local changes = 0 - - for _, set in patch do - for _ in set do - changes += 1 - end - end - for _, set in unapplied do - for _ in set do - changes -= 1 - end - end - - if changes == 0 then return end local old = self.patchInfo:getValue() if now - old.timestamp < 2 then - changes += old.changes - end + -- Patches that apply in the same second are + -- considered to be part of the same change for human clarity + local merged = PatchSet.newEmpty() + PatchSet.assign(merged, old.patch, patch) - self.setPatchInfo({ - changes = changes, - timestamp = now, - }) + self.setPatchInfo({ + patch = merged, + timestamp = now, + }) + else + self.setPatchInfo({ + patch = patch, + timestamp = now, + }) + end end) serveSession:onStatusChanged(function(status, details) @@ -285,6 +289,32 @@ function App:startSession() end end) + serveSession:setConfirmCallback(function(instanceMap, patch, serverInfo) + if PatchSet.isEmpty(patch) then + return "Accept" + end + + self:setState({ + appStatus = AppStatus.Confirming, + confirmData = { + instanceMap = instanceMap, + patch = patch, + serverInfo = serverInfo, + }, + toolbarIcon = Assets.Images.PluginButton, + }) + + self:addNotification( + string.format( + "Please accept%sor abort the initializing sync session.", + Settings:get("twoWaySync") and ", reject, " or " " + ), + 7 + ) + + return self.confirmationEvent:Wait() + end) + serveSession:start() self.serveSession = serveSession @@ -295,7 +325,7 @@ function App:startSession() local patchInfo = table.clone(self.patchInfo:getValue()) self.setPatchInfo(patchInfo) local elapsed = os.time() - patchInfo.timestamp - task.wait(elapsed < 60 and 1 or elapsed/5) + task.wait(elapsed < 60 and 1 or elapsed / 5) end end) end @@ -379,12 +409,28 @@ function App:render() end, }), + ConfirmingPage = createPageElement(AppStatus.Confirming, { + confirmData = self.state.confirmData, + createPopup = not self.state.guiEnabled, + + onAbort = function() + self.confirmationBindable:Fire("Abort") + end, + onAccept = function() + self.confirmationBindable:Fire("Accept") + end, + onReject = function() + self.confirmationBindable:Fire("Reject") + end, + }), + Connecting = createPageElement(AppStatus.Connecting), Connected = createPageElement(AppStatus.Connected, { projectName = self.state.projectName, address = self.state.address, patchInfo = self.patchInfo, + serveSession = self.serveSession, onDisconnect = function() self:endSession() @@ -409,15 +455,6 @@ function App:render() }) end, }), - - Background = Theme.with(function(theme) - return e("Frame", { - Size = UDim2.new(1, 0, 1, 0), - BackgroundColor3 = theme.BackgroundColor, - ZIndex = 0, - BorderSizePixel = 0, - }) - end), }), RojoNotifications = e("ScreenGui", {}, { @@ -428,10 +465,10 @@ function App:render() Padding = UDim.new(0, 5), }), padding = e("UIPadding", { - PaddingTop = UDim.new(0, 5); - PaddingBottom = UDim.new(0, 5); - PaddingLeft = UDim.new(0, 5); - PaddingRight = UDim.new(0, 5); + PaddingTop = UDim.new(0, 5), + PaddingBottom = UDim.new(0, 5), + PaddingLeft = UDim.new(0, 5), + PaddingRight = UDim.new(0, 5), }), notifs = e(Notifications, { soundPlayer = self.props.soundPlayer, @@ -452,7 +489,9 @@ function App:render() onTriggered = function() if self.serveSession == nil or self.serveSession:getStatus() == ServeSession.Status.NotStarted then self:startSession() - elseif self.serveSession ~= nil and self.serveSession:getStatus() == ServeSession.Status.Connected then + elseif + self.serveSession ~= nil and self.serveSession:getStatus() == ServeSession.Status.Connected + then self:endSession() end end, @@ -500,7 +539,7 @@ function App:render() } end) end, - }) + }), }), }), }) diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index 08f86b3b..3c919b54 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -25,6 +25,11 @@ local Assets = { Back = "rbxassetid://6017213752", Reset = "rbxassetid://10142422327", }, + Diff = { + Add = "rbxassetid://10434145835", + Remove = "rbxassetid://10434408368", + Edit = "rbxassetid://10434144680", + }, Checkbox = { Active = "rbxassetid://6016251644", Inactive = "rbxassetid://6016251963", diff --git a/plugin/src/PatchSet.lua b/plugin/src/PatchSet.lua index fac6f945..3451de6a 100644 --- a/plugin/src/PatchSet.lua +++ b/plugin/src/PatchSet.lua @@ -8,6 +8,40 @@ local t = require(Packages.t) local Types = require(script.Parent.Types) +local function deepEqual(a: any, b: any): boolean + local typeA = typeof(a) + if typeA ~= typeof(b) then + return false + end + + if typeof(a) == "table" then + local checkedKeys = {} + + for key, value in a do + checkedKeys[key] = true + + if deepEqual(value, b[key]) == false then + return false + end + end + + for key, value in b do + if checkedKeys[key] then continue end + if deepEqual(value, a[key]) == false then + return false + end + end + + return true + end + + if a == b then + return true + end + + return false +end + local PatchSet = {} PatchSet.validate = t.interface({ @@ -57,6 +91,32 @@ function PatchSet.hasUpdates(patchSet) return next(patchSet.updated) ~= nil end +--[[ + Tells whether the given PatchSets are equal. +]] +function PatchSet.isEqual(patchA, patchB) + return deepEqual(patchA, patchB) +end + +--[[ + Count the number of changes in the given PatchSet. +]] +function PatchSet.countChanges(patch) + local count = 0 + + for _ in patch.added do + count += 1 + end + for _ in patch.removed do + count += 1 + end + for _ in patch.updated do + count += 1 + end + + return count +end + --[[ Merge multiple PatchSet objects into the given PatchSet. ]] diff --git a/plugin/src/Reconciler/diff.lua b/plugin/src/Reconciler/diff.lua index ef729700..e2dac7ff 100644 --- a/plugin/src/Reconciler/diff.lua +++ b/plugin/src/Reconciler/diff.lua @@ -15,6 +15,86 @@ local function isEmpty(table) return next(table) == nil end +local function fuzzyEq(a: number, b: number, epsilon: number): boolean + return math.abs(a - b) < epsilon +end + +local function trueEquals(a, b): boolean + -- Exit early for simple equality values + if a == b then + return true + end + + local typeA, typeB = typeof(a), typeof(b) + + -- For tables, try recursive deep equality + if typeA == "table" and typeB == "table" then + local checkedKeys = {} + for key, value in pairs(a) do + checkedKeys[key] = true + if not trueEquals(value, b[key]) then + return false + end + end + for key, value in pairs(b) do + if checkedKeys[key] then continue end + if not trueEquals(value, a[key]) then + return false + end + end + return true + + -- For numbers, compare with epsilon of 0.0001 to avoid floating point inequality + elseif typeA == "number" and typeB == "number" then + return fuzzyEq(a, b, 0.0001) + + -- For EnumItem->number, compare the EnumItem's value + elseif typeA == "number" and typeB == "EnumItem" then + return a == b.Value + elseif typeA == "EnumItem" and typeB == "number" then + return a.Value == b + + -- For Color3s, compare to RGB ints to avoid floating point inequality + elseif typeA == "Color3" and typeB == "Color3" then + local aR, aG, aB = math.floor(a.R * 255), math.floor(a.G * 255), math.floor(a.B * 255) + local bR, bG, bB = math.floor(b.R * 255), math.floor(b.G * 255), math.floor(b.B * 255) + return aR == bR and aG == bG and aB == bB + + -- For CFrames, compare to components with epsilon of 0.0001 to avoid floating point inequality + elseif typeA == "CFrame" and typeB == "CFrame" then + local aComponents, bComponents = {a:GetComponents()}, {b:GetComponents()} + for i, aComponent in aComponents do + if not fuzzyEq(aComponent, bComponents[i], 0.0001) then + return false + end + end + return true + + -- For Vector3s, compare to components with epsilon of 0.0001 to avoid floating point inequality + elseif typeA == "Vector3" and typeB == "Vector3" then + local aComponents, bComponents = {a.X, a.Y, a.Z}, {b.X, b.Y, b.Z} + for i, aComponent in aComponents do + if not fuzzyEq(aComponent, bComponents[i], 0.0001) then + return false + end + end + return true + + -- For Vector2s, compare to components with epsilon of 0.0001 to avoid floating point inequality + elseif typeA == "Vector2" and typeB == "Vector2" then + local aComponents, bComponents = {a.X, a.Y}, {b.X, b.Y} + for i, aComponent in aComponents do + if not fuzzyEq(aComponent, bComponents[i], 0.0001) then + return false + end + end + return true + + end + + return false +end + local function shouldDeleteUnknownInstances(virtualInstance) if virtualInstance.Metadata ~= nil then return not virtualInstance.Metadata.ignoreUnknownInstances @@ -73,7 +153,8 @@ local function diff(instanceMap, virtualInstances, rootId) local ok, decodedValue = decodeValue(virtualValue, instanceMap) if ok then - if existingValue ~= decodedValue then + if not trueEquals(existingValue, decodedValue) then + Log.debug("{}.{} changed from '{}' to '{}'", instance:GetFullName(), propertyName, existingValue, decodedValue) changedProperties[propertyName] = virtualValue end else diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 90860ff7..12b9ffae 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -5,8 +5,10 @@ local Packages = script.Parent.Parent.Packages local Log = require(Packages.Log) local Fmt = require(Packages.Fmt) local t = require(Packages.t) +local Promise = require(Packages.Promise) local ChangeBatcher = require(script.Parent.ChangeBatcher) +local encodePatchUpdate = require(script.Parent.ChangeBatcher.encodePatchUpdate) local InstanceMap = require(script.Parent.InstanceMap) local PatchSet = require(script.Parent.PatchSet) local Reconciler = require(script.Parent.Reconciler) @@ -123,6 +125,10 @@ function ServeSession:onStatusChanged(callback) self.__statusChangedCallback = callback end +function ServeSession:setConfirmCallback(callback) + self.__userConfirmCallback = callback +end + function ServeSession:onPatchApplied(callback) self.__patchAppliedCallback = callback end @@ -132,13 +138,12 @@ function ServeSession:start() self.__apiContext:connect() :andThen(function(serverInfo) - self:__setStatus(Status.Connected, serverInfo.projectName) self:__applyGameAndPlaceId(serverInfo) - local rootInstanceId = serverInfo.rootInstanceId - - return self:__initialSync(rootInstanceId) + return self:__initialSync(serverInfo) :andThen(function() + self:__setStatus(Status.Connected, serverInfo.projectName) + return self:__mainSyncLoop() end) end) @@ -202,8 +207,8 @@ function ServeSession:__onActiveScriptChanged(activeScript) self.__apiContext:open(scriptId) end -function ServeSession:__initialSync(rootInstanceId) - return self.__apiContext:read({ rootInstanceId }) +function ServeSession:__initialSync(serverInfo) + return self.__apiContext:read({ serverInfo.rootInstanceId }) :andThen(function(readResponseBody) -- Tell the API Context that we're up-to-date with the version of -- the tree defined in this response. @@ -212,14 +217,14 @@ function ServeSession:__initialSync(rootInstanceId) -- For any instances that line up with the Rojo server's view, start -- tracking them in the reconciler. Log.trace("Matching existing Roblox instances to Rojo IDs") - self.__reconciler:hydrate(readResponseBody.instances, rootInstanceId, game) + self.__reconciler:hydrate(readResponseBody.instances, serverInfo.rootInstanceId, game) -- Calculate the initial patch to apply to the DataModel to catch us -- up to what Rojo thinks the place should look like. Log.trace("Computing changes that plugin needs to make to catch up to server...") local success, catchUpPatch = self.__reconciler:diff( readResponseBody.instances, - rootInstanceId, + serverInfo.rootInstanceId, game ) @@ -229,19 +234,50 @@ function ServeSession:__initialSync(rootInstanceId) Log.trace("Computed hydration patch: {:#?}", debugPatch(catchUpPatch)) - -- TODO: Prompt user to notify them of this patch, since it's - -- effectively a conflict between the Rojo server and the client. In - -- the future, we'll ask which changes the user wants to keep. - - local unappliedPatch = self.__reconciler:applyPatch(catchUpPatch) - - if not PatchSet.isEmpty(unappliedPatch) then - Log.warn("Could not apply all changes requested by the Rojo server:\n{}", - PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) + local userDecision = "Accept" + if self.__userConfirmCallback ~= nil then + userDecision = self.__userConfirmCallback(self.__instanceMap, catchUpPatch, serverInfo) end - if self.__patchAppliedCallback then - pcall(self.__patchAppliedCallback, catchUpPatch, unappliedPatch) + if userDecision == "Abort" then + return Promise.reject("Aborted Rojo sync operation") + + elseif userDecision == "Reject" and self.__twoWaySync then + -- The user wants their studio DOM to write back to their Rojo DOM + -- so we will reverse the patch and send it back + + local inversePatch = PatchSet.newEmpty() + + -- Send back the current properties + for _, change in catchUpPatch.updated do + local instance = self.__instanceMap.fromIds[change.id] + if not instance then continue end + + local update = encodePatchUpdate(instance, change.id, change.changedProperties) + table.insert(inversePatch.updated, update) + end + -- Add the removed instances back to Rojo + -- selene:allow(empty_if, unused_variable) + for _, instance in catchUpPatch.removed do + -- TODO: Generate ID for our instance and add it to inversePatch.added + end + -- Remove the additions we've rejected + for id, _change in catchUpPatch.added do + table.insert(inversePatch.removed, id) + end + + self.__apiContext:write(inversePatch) + + elseif userDecision == "Accept" then + local unappliedPatch = self.__reconciler:applyPatch(catchUpPatch) + + if not PatchSet.isEmpty(unappliedPatch) then + Log.warn("Could not apply all changes requested by the Rojo server:\n{}", + PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) + end + if self.__patchAppliedCallback then + pcall(self.__patchAppliedCallback, catchUpPatch, unappliedPatch) + end end end) end diff --git a/plugin/watch-build.sh b/plugin/watch-build.sh new file mode 100644 index 00000000..91ce6f89 --- /dev/null +++ b/plugin/watch-build.sh @@ -0,0 +1,2 @@ +# Continously build the rojo plugin into the local plugin directory on Windows +rojo build plugin/default.project.json -o $LOCALAPPDATA/Roblox/Plugins/Rojo.rbxm --watch From c0219922b27d686c028a756b08745393ec34860f Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 22 Apr 2023 15:44:49 -0400 Subject: [PATCH 1274/1504] Update dependencies --- Cargo.lock | 1234 ++-- Cargo.toml | 8 +- plugin/rbx_dom_lua/EncodedValue.lua | 17 + plugin/rbx_dom_lua/PropertyDescriptor.lua | 10 + plugin/rbx_dom_lua/allValues.json | 11 + plugin/rbx_dom_lua/customProperties.lua | 10 + plugin/rbx_dom_lua/database.json | 6824 ++++++++++++++++++--- 7 files changed, 6889 insertions(+), 1225 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 82e9bb8c..9e6a1830 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.17.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" dependencies = [ "gimli", ] @@ -19,33 +19,33 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "0.7.18" +version = "0.7.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f" +checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" dependencies = [ "memchr", ] [[package]] -name = "ansi_term" -version = "0.12.1" +name = "aho-corasick" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" dependencies = [ - "winapi 0.3.9", + "memchr", ] [[package]] name = "anyhow" -version = "1.0.58" +version = "1.0.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb07d2053ccdbe10e2af2995a2f116c1330396493dc1269f6a91d0ae82e19704" +checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" [[package]] name = "arrayref" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544" +checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" [[package]] name = "arrayvec" @@ -59,7 +59,7 @@ version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ - "hermit-abi", + "hermit-abi 0.1.19", "libc", "winapi 0.3.9", ] @@ -72,9 +72,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.65" +version = "0.3.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11a17d453482a265fd5f8479f2a3f405566e6ca627837aaddb85af8b1ab8ef61" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" dependencies = [ "addr2line", "cc", @@ -87,9 +87,15 @@ dependencies = [ [[package]] name = "base64" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" [[package]] name = "bincode" @@ -108,71 +114,44 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "blake3" -version = "1.3.1" +version = "1.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a08e53fc5a564bb15bfe6fae56bd71522205f1f91893f9c0116edad6496c183f" +checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if 1.0.0", "constant_time_eq", - "digest 0.10.3", + "digest", ] [[package]] name = "block-buffer" -version = "0.7.3" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "block-padding", - "byte-tools", - "byteorder", - "generic-array 0.12.4", -] - -[[package]] -name = "block-buffer" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324" -dependencies = [ - "generic-array 0.14.5", -] - -[[package]] -name = "block-padding" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa79dedbb091f449f1f39e53edf88d5dbe95f895dae6135a8d7b881fb5af73f5" -dependencies = [ - "byte-tools", + "generic-array", ] [[package]] name = "bstr" -version = "0.2.17" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" dependencies = [ - "lazy_static", "memchr", + "once_cell", "regex-automata", "serde", ] [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" - -[[package]] -name = "byte-tools" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b5ca7a04898ad4bcd41c90c5285445ff5b791899bb1b0abdd2a2aa791211d7" +checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" [[package]] name = "byteorder" @@ -182,24 +161,21 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" [[package]] name = "cast" -version = "0.2.7" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c24dab4283a142afa2fdca129b80ad2c6284e073930f964c3a1293c225ee39a" -dependencies = [ - "rustc_version", -] +checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.73" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" [[package]] name = "cfg-if" @@ -226,9 +202,9 @@ dependencies = [ [[package]] name = "clap" -version = "3.2.7" +version = "3.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b7b16274bb247b45177db843202209b12191b631a14a9d06e41b3777d6ecf14" +checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" dependencies = [ "atty", "bitflags", @@ -238,20 +214,20 @@ dependencies = [ "once_cell", "strsim", "termcolor", - "textwrap 0.15.0", + "textwrap 0.16.0", ] [[package]] name = "clap_derive" -version = "3.2.7" +version = "3.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759bf187376e1afa7b85b959e6a664a3e7a95203415dba952ad19139e798f902" +checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.40", - "quote 1.0.20", - "syn", + "proc-macro2 1.0.56", + "quote 1.0.26", + "syn 1.0.109", ] [[package]] @@ -265,22 +241,21 @@ dependencies = [ [[package]] name = "console" -version = "0.15.0" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28b32d32ca44b70c3e4acd7db1babf555fa026e385fb95f18028f88848b3c31" +checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" dependencies = [ "encode_unicode", + "lazy_static", "libc", - "once_cell", - "terminal_size", - "winapi 0.3.9", + "windows-sys 0.42.0", ] [[package]] name = "constant_time_eq" -version = "0.1.5" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc" +checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" [[package]] name = "core-foundation" @@ -294,15 +269,24 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc" +checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" + +[[package]] +name = "cpufeatures" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +dependencies = [ + "libc", +] [[package]] name = "criterion" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1604dafd25fba2fe2d5895a9da139f8dc9b319a5fe5354ca137cbbce4e178d10" +checksum = "b01d6de93b2b6c65e17c634a26653a29d107b3c98c607c765bf38d041531cd8f" dependencies = [ "atty", "cast", @@ -326,9 +310,9 @@ dependencies = [ [[package]] name = "criterion-plot" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d00996de9f2f7559f7f4dc286073197f83e92256a59ed395f9aac01fe717da57" +checksum = "2673cc8207403546f45f5fd319a974b1e6983ad1a3ee7e6041650013be041876" dependencies = [ "cast", "itertools", @@ -336,9 +320,9 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c02a4d71819009c192cf4872265391563fd6a84c81ff2c0f2a7026ca4c1d85c" +checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" dependencies = [ "cfg-if 1.0.0", "crossbeam-utils", @@ -346,9 +330,9 @@ dependencies = [ [[package]] name = "crossbeam-deque" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6455c0ca19f0d2fbf751b908d5c55c1f5cbc65e03c4225427254b46890bdde1e" +checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" dependencies = [ "cfg-if 1.0.0", "crossbeam-epoch", @@ -357,47 +341,44 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.9" +version = "0.9.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07db9d94cbd326813772c968ccd25999e5f8ae22f4f8d1b11effa37ef6ce281d" +checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" dependencies = [ "autocfg", "cfg-if 1.0.0", "crossbeam-utils", "memoffset", - "once_cell", "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.10" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d82ee10ce34d7bc12c2122495e7593a9c41347ecdd64185af4ecf72cb1a7f83" +checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" dependencies = [ "cfg-if 1.0.0", - "once_cell", ] [[package]] name = "crypto-common" -version = "0.1.3" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57952ca27b5e3606ff4dd79b0020231aaf9d6aa76dc05fd30137538c50bd3ce8" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" dependencies = [ - "generic-array 0.14.5", + "generic-array", "typenum", ] [[package]] name = "csv" -version = "1.1.6" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +checksum = "0b015497079b9a9d69c02ad25de6c0a6edef051ea6360a327d0bd05802ef64ad" dependencies = [ - "bstr", "csv-core", - "itoa 0.4.8", + "itoa", "ryu", "serde", ] @@ -413,12 +394,12 @@ dependencies = [ [[package]] name = "ctor" -version = "0.1.22" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c" +checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" dependencies = [ - "quote 1.0.20", - "syn", + "quote 1.0.26", + "syn 1.0.109", ] [[package]] @@ -429,20 +410,11 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "digest" -version = "0.8.1" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3d0c8c8752312f9713efd397ff63acb9f85585afbf179282e720e7704954dd5" +checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" dependencies = [ - "generic-array 0.12.4", -] - -[[package]] -name = "digest" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506" -dependencies = [ - "block-buffer 0.10.2", + "block-buffer", "crypto-common", "subtle", ] @@ -470,15 +442,15 @@ dependencies = [ [[package]] name = "either" -version = "1.7.0" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" [[package]] name = "embed-resource" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc24ff8d764818e9ab17963b0593c535f077a513f565e75e4352d758bc4d8c0" +checksum = "e62abb876c07e4754fae5c14cafa77937841f01740637e17d78dc04352f32a5e" dependencies = [ "cc", "rustc_version", @@ -495,18 +467,18 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.31" +version = "0.8.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9852635589dc9f9ea1b6fe9f05b50ef208c85c834a562f0c6abb1c475736ec2b" +checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" dependencies = [ "cfg-if 1.0.0", ] [[package]] name = "env_logger" -version = "0.9.0" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3" +checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7" dependencies = [ "atty", "humantime", @@ -516,30 +488,45 @@ dependencies = [ ] [[package]] -name = "fake-simd" +name = "errno" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +dependencies = [ + "errno-dragonfly", + "libc", + "windows-sys 0.48.0", +] + +[[package]] +name = "errno-dragonfly" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e88a8acf291dafb59c2d96e8f59828f3838bb1a70398823ade51a84de6a6deed" +checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +dependencies = [ + "cc", + "libc", +] [[package]] name = "fastrand" -version = "1.7.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" dependencies = [ "instant", ] [[package]] name = "filetime" -version = "0.2.16" +version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c" +checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall", - "winapi 0.3.9", + "redox_syscall 0.2.16", + "windows-sys 0.48.0", ] [[package]] @@ -565,19 +552,18 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" +checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" dependencies = [ - "matches", "percent-encoding", ] [[package]] name = "fs-err" -version = "2.7.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd79fa345a495d3ae89fb7165fec01c0e72f41821d642dda363a1e97975652e" +checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" [[package]] name = "fsevent" @@ -616,9 +602,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" -version = "0.3.21" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e" +checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" dependencies = [ "futures-channel", "futures-core", @@ -631,9 +617,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.21" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" dependencies = [ "futures-core", "futures-sink", @@ -641,15 +627,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.21" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" [[package]] name = "futures-executor" -version = "0.3.21" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6" +checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" dependencies = [ "futures-core", "futures-task", @@ -658,38 +644,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.21" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b" +checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" [[package]] name = "futures-macro" -version = "0.3.21" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512" +checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", - "syn", + "proc-macro2 1.0.56", + "quote 1.0.26", + "syn 2.0.15", ] [[package]] name = "futures-sink" -version = "0.3.21" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" [[package]] name = "futures-task" -version = "0.3.21" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" [[package]] name = "futures-util" -version = "0.3.21" +version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" dependencies = [ "futures-channel", "futures-core", @@ -705,31 +691,22 @@ dependencies = [ [[package]] name = "generator" -version = "0.7.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1d9279ca822891c1a4dae06d185612cf8fc6acfe5dff37781b41297811b12ee" +checksum = "f3e123d9ae7c02966b4d892e550bdc32164f05853cd40ab570650ad600596a8a" dependencies = [ "cc", "libc", "log", "rustversion", - "winapi 0.3.9", + "windows", ] [[package]] name = "generic-array" -version = "0.12.4" +version = "0.14.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffdf9f34f1447443d37393cc6c2b8313aebddcd96906caf34e54c68d8e57d7bd" -dependencies = [ - "typenum", -] - -[[package]] -name = "generic-array" -version = "0.14.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd48d33ec7f05fbfa152300fdad764757cbded343c1aa1cff2fbaf4134851803" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" dependencies = [ "typenum", "version_check", @@ -737,9 +714,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" +checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" dependencies = [ "cfg-if 1.0.0", "libc", @@ -748,17 +725,17 @@ dependencies = [ [[package]] name = "gimli" -version = "0.26.1" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" +checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" [[package]] name = "globset" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a1e17342619edbc21a964c2afbeb6c820c6a2560032872f397bb97ea127bd0a" +checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.20", "bstr", "fnv", "log", @@ -767,9 +744,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.13" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21" dependencies = [ "bytes", "fnv", @@ -792,15 +769,15 @@ checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" [[package]] name = "hashbrown" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db0d4cf898abf0081f964436dc980e96670a0f36863e4b83aaacdb65c9d7ccc3" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" [[package]] name = "heck" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9" +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" @@ -811,6 +788,21 @@ dependencies = [ "libc", ] +[[package]] +name = "hermit-abi" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" +dependencies = [ + "libc", +] + +[[package]] +name = "hermit-abi" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" + [[package]] name = "htmlescape" version = "0.3.1" @@ -819,13 +811,13 @@ checksum = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" [[package]] name = "http" -version = "0.2.8" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ "bytes", "fnv", - "itoa 1.0.2", + "itoa", ] [[package]] @@ -841,9 +833,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.7.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" @@ -859,9 +851,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.19" +version = "0.14.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f" +checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" dependencies = [ "bytes", "futures-channel", @@ -872,7 +864,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa 1.0.2", + "itoa", "pin-project-lite", "socket2", "tokio", @@ -896,20 +888,19 @@ dependencies = [ [[package]] name = "idna" -version = "0.2.3" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" +checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" dependencies = [ - "matches", "unicode-bidi", "unicode-normalization", ] [[package]] name = "indexmap" -version = "1.9.1" +version = "1.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", "hashbrown", @@ -937,18 +928,18 @@ dependencies = [ [[package]] name = "insta" -version = "1.15.0" +version = "1.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4126dd76ebfe2561486a1bd6738a33d2029ffb068a99ac446b7f8c77b2e58dbc" +checksum = "9a28d25139df397cbca21408bb742cf6837e04cdbebf1b07b760caf971d6a972" dependencies = [ "console", - "once_cell", + "lazy_static", + "linked-hash-map", "pest", "pest_derive", "serde", - "serde_json", - "serde_yaml", "similar", + "yaml-rust", ] [[package]] @@ -960,6 +951,17 @@ dependencies = [ "cfg-if 1.0.0", ] +[[package]] +name = "io-lifetimes" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" +dependencies = [ + "hermit-abi 0.3.1", + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "iovec" version = "0.1.4" @@ -971,30 +973,24 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.5.0" +version = "2.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "879d54834c8c76457ef4293a689b2a8c59b076067ad77b15efafbb05f92a592b" +checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" [[package]] name = "itertools" -version = "0.10.3" +version = "0.10.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" dependencies = [ "either", ] [[package]] name = "itoa" -version = "0.4.8" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" - -[[package]] -name = "itoa" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "jod-thread" @@ -1004,9 +1000,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] name = "js-sys" -version = "0.3.58" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" +checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" dependencies = [ "wasm-bindgen", ] @@ -1035,9 +1031,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.126" +version = "0.2.142" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" +checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" [[package]] name = "linked-hash-map" @@ -1045,6 +1041,12 @@ version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" +[[package]] +name = "linux-raw-sys" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf" + [[package]] name = "log" version = "0.4.17" @@ -1069,9 +1071,9 @@ dependencies = [ [[package]] name = "lz4" -version = "1.23.3" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4edcb94251b1c375c459e5abe9fb0168c1c826c3370172684844f8f3f8d1a885" +checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" dependencies = [ "libc", "lz4-sys", @@ -1079,9 +1081,9 @@ dependencies = [ [[package]] name = "lz4-sys" -version = "1.9.3" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7be8908e2ed6f31c02db8a9fa962f03e36c53fbfde437363eae3306b85d7e17" +checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" dependencies = [ "cc", "libc", @@ -1102,12 +1104,6 @@ dependencies = [ "regex-automata", ] -[[package]] -name = "matches" -version = "0.1.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" - [[package]] name = "memchr" version = "2.5.0" @@ -1116,9 +1112,9 @@ checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" [[package]] name = "memoffset" -version = "0.6.5" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce" +checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" dependencies = [ "autocfg", ] @@ -1135,15 +1131,15 @@ dependencies = [ [[package]] name = "mime" -version = "0.3.16" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.5.3" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f5c75688da582b8ffc1f1799e9db273f32133c49e048f614d22ec3256773ccc" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" dependencies = [ "adler", ] @@ -1169,14 +1165,14 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" +checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" dependencies = [ "libc", "log", "wasi", - "windows-sys", + "windows-sys 0.45.0", ] [[package]] @@ -1205,9 +1201,9 @@ dependencies = [ [[package]] name = "native-tls" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd7e2f3618557f980e0b17e8856252eee3c97fa12c54dff0ca290fb6266ca4a9" +checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" dependencies = [ "lazy_static", "libc", @@ -1223,9 +1219,9 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.37" +version = "0.2.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "391630d12b68002ae1e25e8f974306474966550ad82dac6886fb8910c19568ae" +checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631" dependencies = [ "cfg-if 0.1.10", "libc", @@ -1250,6 +1246,16 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "nu-ansi-term" +version = "0.46.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +dependencies = [ + "overload", + "winapi 0.3.9", +] + [[package]] name = "num-traits" version = "0.2.15" @@ -1261,28 +1267,28 @@ dependencies = [ [[package]] name = "num_cpus" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1" +checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" dependencies = [ - "hermit-abi", + "hermit-abi 0.2.6", "libc", ] [[package]] name = "object" -version = "0.28.4" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42c982f2d955fac81dd7e1d0e1426a7d702acd9c98d19ab01083a6a0328c424" +checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.12.0" +version = "1.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" [[package]] name = "oorandom" @@ -1290,17 +1296,11 @@ version = "11.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ab1bc2a289d34bd04a330323ac98a1b4bc82c9d9fcb1e66b63caa84da26b575" -[[package]] -name = "opaque-debug" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" - [[package]] name = "opener" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ea3ebcd72a54701f56345f16785a6d3ac2df7e986d273eb4395c0b01db17952" +checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005" dependencies = [ "bstr", "winapi 0.3.9", @@ -1308,9 +1308,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.40" +version = "0.10.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +checksum = "97ea2d98598bf9ada7ea6ee8a30fb74f9156b63bbe495d64ec2b87c269d2dda3" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -1323,13 +1323,13 @@ dependencies = [ [[package]] name = "openssl-macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b501e44f11665960c7e7fcf062c7d96a14ade4aa98116c004b2e37b5be7d736c" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", - "syn", + "proc-macro2 1.0.56", + "quote 1.0.26", + "syn 2.0.15", ] [[package]] @@ -1340,20 +1340,19 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "111.22.0+1.1.1q" +version = "111.25.3+1.1.1t" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f31f0d509d1c1ae9cada2f9539ff8f37933831fd5098879e482aa687d659853" +checksum = "924757a6a226bf60da5f7dd0311a34d2b52283dd82ddeb103208ddc66362f80c" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.74" +version = "0.9.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" +checksum = "992bac49bdbab4423199c654a5515bd2a6c6a23bf03f2dd3bdb7e5ae6259bc69" dependencies = [ - "autocfg", "cc", "libc", "openssl-src", @@ -1363,9 +1362,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.1.0" +version = "6.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21326818e99cfe6ce1e524c2a805c189a99b5ae555a35d19f9a284b427d86afa" +checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" [[package]] name = "output_vt100" @@ -1377,31 +1376,38 @@ dependencies = [ ] [[package]] -name = "paste" -version = "1.0.7" +name = "overload" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c520e05135d6e763148b6426a837e239041653ba7becd2e538c076c738025fc" +checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" + +[[package]] +name = "paste" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" [[package]] name = "percent-encoding" -version = "2.1.0" +version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" +checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" [[package]] name = "pest" -version = "2.1.3" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10f4872ae94d7b90ae48754df22fd42ad52ce740b8f370b03da4835417403e53" +checksum = "7b1403e8401ad5dedea73c626b99758535b342502f8d1e361f4a2dd952749122" dependencies = [ + "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.1.0" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "833d1ae558dc601e9a60366421196a8d94bc0ac980476d0b67e1d0988d72b2d0" +checksum = "be99c4c1d2fc2769b1d00239431d711d08f6efedcecb8b6e30707160aee99c15" dependencies = [ "pest", "pest_generator", @@ -1409,26 +1415,26 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.1.3" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55" +checksum = "e56094789873daa36164de2e822b3888c6ae4b4f9da555a1103587658c805b1e" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.40", - "quote 1.0.20", - "syn", + "proc-macro2 1.0.56", + "quote 1.0.26", + "syn 2.0.15", ] [[package]] name = "pest_meta" -version = "2.1.3" +version = "2.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be6e404f5317079812fc8f9f5279de376d8856929e21c184ecf6bbd692a11d" +checksum = "6733073c7cff3d8459fda0e42f13a047870242aed8b509fe98000928975f359e" dependencies = [ - "maplit", + "once_cell", "pest", - "sha-1", + "sha2", ] [[package]] @@ -1445,15 +1451,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.25" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae" +checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" [[package]] name = "plotters" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a3fd9ec30b9749ce28cd91f255d569591cdf937fe280c312143e3c4bad6f2a" +checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" dependencies = [ "num-traits", "plotters-backend", @@ -1464,35 +1470,35 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.2" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d88417318da0eaf0fdcdb51a0ee6c3bed624333bff8f946733049380be67ac1c" +checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" [[package]] name = "plotters-svg" -version = "0.3.1" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521fa9638fa597e1dc53e9412a4f9cefb01187ee1f7413076f9e6749e2885ba9" +checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" dependencies = [ "plotters-backend", ] [[package]] name = "ppv-lite86" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "pretty_assertions" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c89f989ac94207d048d92db058e4f6ec7342b0971fc58d1271ca148b799b3563" +checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" dependencies = [ - "ansi_term", "ctor", "diff", "output_vt100", + "yansi", ] [[package]] @@ -1502,9 +1508,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.40", - "quote 1.0.20", - "syn", + "proc-macro2 1.0.56", + "quote 1.0.26", + "syn 1.0.109", "version_check", ] @@ -1514,16 +1520,16 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.56", + "quote 1.0.26", "version_check", ] [[package]] name = "proc-macro-hack" -version = "0.5.19" +version = "0.5.20+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro-nested" @@ -1542,31 +1548,31 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.40" +version = "1.0.56" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" +checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f61dcf0b917cd75d4521d7343d1ffff3d1583054133c9b5cbea3375c703c40d" +checksum = "332cd62e95873ea4f41f3dfd6bbbfc5b52aec892d7e8d534197c4720a0bbbab2" dependencies = [ "profiling-procmacros", - "tracy-client", + "tracy-client 0.15.2", ] [[package]] name = "profiling-procmacros" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98eee3c112f2a6f784b6713fe1d7fb7d6506e066121c0a49371fdb976f72bae5" +checksum = "a10adb8d151bb1280afb8bed41ae5db26be1b056964947133c7525b0bf39c0b0" dependencies = [ - "quote 1.0.20", - "syn", + "quote 1.0.26", + "syn 1.0.109", ] [[package]] @@ -1580,11 +1586,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.20" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" +checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" dependencies = [ - "proc-macro2 1.0.40", + "proc-macro2 1.0.56", ] [[package]] @@ -1610,30 +1616,28 @@ dependencies = [ [[package]] name = "rand_core" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ "getrandom", ] [[package]] name = "rayon" -version = "1.5.3" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd99e5772ead8baa5215278c9b15bf92087709e9c1b2d1f97cdb5a183c933a7d" +checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" dependencies = [ - "autocfg", - "crossbeam-deque", "either", "rayon-core", ] [[package]] name = "rayon-core" -version = "1.9.3" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "258bcdb5ac6dad48491bb2992db6b7cf74878b0384908af124823d118c99683f" +checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" dependencies = [ "crossbeam-channel", "crossbeam-deque", @@ -1643,9 +1647,9 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "0.6.6" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "842a9253d37ca9df932108806a0f6c97195f2411bf05671e88744be622548807" +checksum = "1631584eb343930a5a738635504b8c1f3ef2ae9c947bff942bbbac075f6887f6" dependencies = [ "log", "lz4", @@ -1678,9 +1682,9 @@ dependencies = [ [[package]] name = "rbx_reflection_database" -version = "0.2.5+roblox-530" +version = "0.2.6+roblox-572" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e790ac1c92dee33669e7e12414caf75eb5cfce6fb5c54998eb9001d204fbab1" +checksum = "780a70e2aff0c2a922bf2e72449e3a67e656ce622af4f8895c22d15cd98dfd5b" dependencies = [ "lazy_static", "rbx_reflection", @@ -1690,11 +1694,11 @@ dependencies = [ [[package]] name = "rbx_types" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a773e53402f2ae7537bbec77badb7e3ff3e6ddac5ee9c2df7edf0a60edf5c9d8" +checksum = "b9644faf3ae1858ba10615fa5955c330e49cf0f6ad37a83db3e1c398c4afac12" dependencies = [ - "base64", + "base64 0.13.1", "bitflags", "blake3", "lazy_static", @@ -1705,11 +1709,11 @@ dependencies = [ [[package]] name = "rbx_xml" -version = "0.12.4" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2559683f2f9205d442bd9083d7557be58b6cdcd0e5cc22600a6546a08e6d54f0" +checksum = "6d5f9361d83d06aae8ea42d7002d35e2652b198e8ce68c918b97e371f8a31352" dependencies = [ - "base64", + "base64 0.13.1", "log", "rbx_dom_weak", "rbx_reflection", @@ -1719,9 +1723,18 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.13" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42" +checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" +dependencies = [ + "bitflags", +] + +[[package]] +name = "redox_syscall" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ "bitflags", ] @@ -1733,19 +1746,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" dependencies = [ "getrandom", - "redox_syscall", + "redox_syscall 0.2.16", "thiserror", ] [[package]] name = "regex" -version = "1.5.6" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" dependencies = [ - "aho-corasick", + "aho-corasick 1.0.1", "memchr", - "regex-syntax", + "regex-syntax 0.7.1", ] [[package]] @@ -1754,31 +1767,28 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" dependencies = [ - "regex-syntax", + "regex-syntax 0.6.29", ] [[package]] name = "regex-syntax" -version = "0.6.26" +version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] -name = "remove_dir_all" -version = "0.5.3" +name = "regex-syntax" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" -dependencies = [ - "winapi 0.3.9", -] +checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" [[package]] name = "reqwest" -version = "0.11.11" +version = "0.11.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b75aa69a3f06bbcc66ede33af2af253c6f7a86b1ca0033f60c580a27074fbf92" +checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" dependencies = [ - "base64", + "base64 0.21.0", "bytes", "encoding_rs", "futures-core", @@ -1790,10 +1800,10 @@ dependencies = [ "hyper-tls", "ipnet", "js-sys", - "lazy_static", "log", "mime", "native-tls", + "once_cell", "percent-encoding", "pin-project-lite", "serde", @@ -1873,7 +1883,7 @@ dependencies = [ "anyhow", "backtrace", "bincode", - "clap 3.2.7", + "clap 3.2.23", "criterion", "crossbeam-channel", "csv", @@ -1910,7 +1920,7 @@ dependencies = [ "termcolor", "thiserror", "tokio", - "tracy-client", + "tracy-client 0.13.2", "uuid", "walkdir", "winreg 0.10.1", @@ -1926,9 +1936,9 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustc_version" @@ -1940,16 +1950,30 @@ dependencies = [ ] [[package]] -name = "rustversion" -version = "1.0.7" +name = "rustix" +version = "0.37.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0a5f7c728f5d284929a1cccb5bc19884422bfe6ef4d6c409da2c41838983fcf" +checksum = "d9b864d3c18a5785a05953adeed93e2dca37ed30f18e69bba9f30079d51f363f" +dependencies = [ + "bitflags", + "errno", + "io-lifetimes", + "libc", + "linux-raw-sys", + "windows-sys 0.48.0", +] + +[[package]] +name = "rustversion" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" [[package]] name = "ryu" -version = "1.0.10" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3f6f92acf49d1b98f7a81226834412ada05458b7364277387724a237f062695" +checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" [[package]] name = "same-file" @@ -1962,19 +1986,18 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.20" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" +checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" dependencies = [ - "lazy_static", - "windows-sys", + "windows-sys 0.42.0", ] [[package]] name = "scoped-tls" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" +checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" @@ -1984,9 +2007,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "security-framework" -version = "2.6.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" dependencies = [ "bitflags", "core-foundation", @@ -1997,9 +2020,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.6.1" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556" +checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" dependencies = [ "core-foundation-sys", "libc", @@ -2007,15 +2030,15 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.11" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d92beeab217753479be2f74e54187a6aed4c125ff0703a866c3147a02f0c6dd" +checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" [[package]] name = "serde" -version = "1.0.137" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" dependencies = [ "serde_derive", ] @@ -2032,22 +2055,22 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.160" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", - "syn", + "proc-macro2 1.0.56", + "quote 1.0.26", + "syn 2.0.15", ] [[package]] name = "serde_json" -version = "1.0.82" +version = "1.0.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" +checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" dependencies = [ - "itoa 1.0.2", + "itoa", "ryu", "serde", ] @@ -2059,16 +2082,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa 1.0.2", + "itoa", "ryu", "serde", ] [[package]] name = "serde_yaml" -version = "0.8.24" +version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707d15895415db6628332b737c838b88c598522e4dc70647e59b72312924aebc" +checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ "indexmap", "ryu", @@ -2077,15 +2100,14 @@ dependencies = [ ] [[package]] -name = "sha-1" -version = "0.8.2" +name = "sha2" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d94d0bede923b3cea61f3f1ff57ff8cdfd77b400fb8f9998949e0cf04163df" +checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" dependencies = [ - "block-buffer 0.7.3", - "digest 0.8.1", - "fake-simd", - "opaque-debug", + "cfg-if 1.0.0", + "cpufeatures", + "digest", ] [[package]] @@ -2099,21 +2121,24 @@ dependencies = [ [[package]] name = "similar" -version = "2.1.0" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e24979f63a11545f5f2c60141afe249d4f19f84581ea2138065e400941d83d3" +checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" [[package]] name = "slab" -version = "0.4.6" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] [[package]] name = "smallvec" -version = "1.8.1" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc88c725d61fc6c3132893370cac4a0200e3fedf5da8331c570664b1987f5ca2" +checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "snax" @@ -2126,9 +2151,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", "winapi 0.3.9", @@ -2148,48 +2173,48 @@ checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" [[package]] name = "syn" -version = "1.0.98" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", + "proc-macro2 1.0.56", + "quote 1.0.26", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +dependencies = [ + "proc-macro2 1.0.56", + "quote 1.0.26", "unicode-ident", ] [[package]] name = "tempfile" -version = "3.3.0" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4" +checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" dependencies = [ "cfg-if 1.0.0", "fastrand", - "libc", - "redox_syscall", - "remove_dir_all", - "winapi 0.3.9", + "redox_syscall 0.3.5", + "rustix", + "windows-sys 0.45.0", ] [[package]] name = "termcolor" -version = "1.1.3" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755" +checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" dependencies = [ "winapi-util", ] -[[package]] -name = "terminal_size" -version = "0.1.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633c1a546cee861a1a6d0dc69ebeca693bf4296661ba7852b9d21d159e0506df" -dependencies = [ - "libc", - "winapi 0.3.9", -] - [[package]] name = "textwrap" version = "0.11.0" @@ -2201,36 +2226,37 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.15.0" +version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb" +checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.31" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a" +checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.31" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a" +checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", - "syn", + "proc-macro2 1.0.56", + "quote 1.0.26", + "syn 2.0.15", ] [[package]] name = "thread_local" -version = "1.1.4" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" dependencies = [ + "cfg-if 1.0.0", "once_cell", ] @@ -2255,32 +2281,31 @@ dependencies = [ [[package]] name = "tinyvec_macros" -version = "0.1.0" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.19.2" +version = "1.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" dependencies = [ + "autocfg", "bytes", "libc", - "memchr", - "mio 0.8.4", + "mio 0.8.6", "num_cpus", - "once_cell", "pin-project-lite", "socket2", - "winapi 0.3.9", + "windows-sys 0.45.0", ] [[package]] name = "tokio-native-tls" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", "tokio", @@ -2288,9 +2313,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.3" +version = "0.7.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" dependencies = [ "bytes", "futures-core", @@ -2302,9 +2327,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.5.9" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", ] @@ -2317,9 +2342,9 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.35" +version = "0.1.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a400e31aa60b9d44a52a8ee0343b5b18566b03a8321e0d321f695cf56e940160" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" dependencies = [ "cfg-if 1.0.0", "pin-project-lite", @@ -2329,20 +2354,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.21" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", - "syn", + "proc-macro2 1.0.56", + "quote 1.0.26", + "syn 1.0.109", ] [[package]] name = "tracing-core" -version = "0.1.28" +version = "0.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" +checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" dependencies = [ "once_cell", "valuable", @@ -2361,12 +2386,12 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.12" +version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfbbce75cad20b56f4f4200e413b894c990c7bbd7e47245ff5cbc2b82511e4da" +checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" dependencies = [ - "ansi_term", "matchers", + "nu-ansi-term", "once_cell", "regex", "sharded-slab", @@ -2385,7 +2410,18 @@ checksum = "42ebfe7a24c18b5ba86d8920c124b41b942352f863fbe0c84d3d63428fa1860f" dependencies = [ "loom", "once_cell", - "tracy-client-sys", + "tracy-client-sys 0.17.1", +] + +[[package]] +name = "tracy-client" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434ecabbda9f67eeea1eab44d52f4a20538afa3e2c2770f2efc161142b25b608" +dependencies = [ + "loom", + "once_cell", + "tracy-client-sys 0.21.0", ] [[package]] @@ -2398,49 +2434,58 @@ dependencies = [ ] [[package]] -name = "try-lock" -version = "0.2.3" +name = "tracy-client-sys" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" +checksum = "0d99f5fc382239d08b6bf05bb6206a585bfdb988c878f2499081d0f285ef7819" +dependencies = [ + "cc", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "typenum" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987" +checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" [[package]] name = "ucd-trie" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56dee185309b50d1f11bfedef0fe6d036842e3fb77413abef29f8f8d1c5d4c1c" +checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" [[package]] name = "unicode-bidi" -version = "0.3.8" +version = "0.3.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" +checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" [[package]] name = "unicode-normalization" -version = "0.1.20" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81dee68f85cab8cf68dec42158baf3a79a1cdc065a8b103025965d6ccb7f6cbd" +checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" dependencies = [ "tinyvec", ] [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "unicode-xid" @@ -2450,21 +2495,20 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "url" -version = "2.2.2" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" +checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" dependencies = [ "form_urlencoded", "idna", - "matches", "percent-encoding", ] [[package]] name = "uuid" -version = "1.1.2" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd6469f4314d5f1ffec476e05f17cc9a78bc7a27a6a857842170bdf8d6f98d2f" +checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb" dependencies = [ "getrandom", "serde", @@ -2500,9 +2544,9 @@ dependencies = [ [[package]] name = "vswhom-sys" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22025f6d8eb903ebf920ea6933b70b1e495be37e2cb4099e62c80454aaf57c39" +checksum = "d3b17ae1f6c8a2b28506cd96d412eebf83b4a0ff2cbefeeb952f2f9dfa44ba18" dependencies = [ "cc", "libc", @@ -2510,12 +2554,11 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.3.2" +version = "2.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56" +checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" dependencies = [ "same-file", - "winapi 0.3.9", "winapi-util", ] @@ -2537,9 +2580,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.81" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" +checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -2547,24 +2590,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.81" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" +checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" dependencies = [ "bumpalo", - "lazy_static", "log", - "proc-macro2 1.0.40", - "quote 1.0.20", - "syn", + "once_cell", + "proc-macro2 1.0.56", + "quote 1.0.26", + "syn 1.0.109", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.31" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de9a9cec1733468a8c657e57fa2413d2ae2c0129b95e87c5b72b8ace4d13f31f" +checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -2574,38 +2617,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.81" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" +checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" dependencies = [ - "quote 1.0.20", + "quote 1.0.26", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.81" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" +checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" dependencies = [ - "proc-macro2 1.0.40", - "quote 1.0.20", - "syn", + "proc-macro2 1.0.56", + "quote 1.0.26", + "syn 1.0.109", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.81" +version = "0.2.84" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" +checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" [[package]] name = "web-sys" -version = "0.3.58" +version = "0.3.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" +checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" dependencies = [ "js-sys", "wasm-bindgen", @@ -2655,47 +2698,160 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.36.1" +name = "windows" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2" +checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_msvc", + "windows-targets 0.48.0", ] [[package]] -name = "windows_aarch64_msvc" -version = "0.36.1" +name = "windows-sys" +version = "0.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47" +checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", +] + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.0", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", +] + +[[package]] +name = "windows-targets" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +dependencies = [ + "windows_aarch64_gnullvm 0.48.0", + "windows_aarch64_msvc 0.48.0", + "windows_i686_gnu 0.48.0", + "windows_i686_msvc 0.48.0", + "windows_x86_64_gnu 0.48.0", + "windows_x86_64_gnullvm 0.48.0", + "windows_x86_64_msvc 0.48.0", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_i686_gnu" -version = "0.36.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_msvc" -version = "0.36.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" [[package]] name = "windows_x86_64_gnu" -version = "0.36.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] name = "windows_x86_64_msvc" -version = "0.36.1" +version = "0.42.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "winreg" @@ -2739,3 +2895,9 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "yansi" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" diff --git a/Cargo.toml b/Cargo.toml index 0aa671c2..afde0996 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -51,11 +51,11 @@ memofs = { version = "0.2.0", path = "crates/memofs" } # rbx_reflection_database = { path = "../rbx-dom/rbx_reflection_database" } # rbx_xml = { path = "../rbx-dom/rbx_xml" } -rbx_binary = "0.6.5" +rbx_binary = "0.7.0" rbx_dom_weak = "2.4.0" rbx_reflection = "4.2.0" -rbx_reflection_database = "0.2.2" -rbx_xml = "0.12.3" +rbx_reflection_database = "0.2.6" +rbx_xml = "0.13.0" anyhow = "1.0.44" backtrace = "0.3.61" @@ -102,7 +102,7 @@ maplit = "1.0.2" rojo-insta-ext = { path = "crates/rojo-insta-ext" } criterion = "0.3.5" -insta = { version = "1.8.0", features = ["redactions"] } +insta = { version = "1.8.0", features = ["redactions", "yaml"] } paste = "1.0.5" pretty_assertions = "1.2.1" serde_yaml = "0.8.21" diff --git a/plugin/rbx_dom_lua/EncodedValue.lua b/plugin/rbx_dom_lua/EncodedValue.lua index d910c297..b1a82dd7 100644 --- a/plugin/rbx_dom_lua/EncodedValue.lua +++ b/plugin/rbx_dom_lua/EncodedValue.lua @@ -238,6 +238,23 @@ types = { toPod = serializeFloat, }, + Font = { + fromPod = function(pod) + return Font.new( + pod.family, + if pod.weight ~= nil then Enum.FontWeight[pod.weight] else nil, + if pod.style ~= nil then Enum.FontStyle[pod.style] else nil + ) + end, + toPod = function(roblox) + return { + family = roblox.Family, + weight = roblox.Weight.Name, + style = roblox.Style.Name, + } + end, + }, + Int32 = { fromPod = identity, toPod = identity, diff --git a/plugin/rbx_dom_lua/PropertyDescriptor.lua b/plugin/rbx_dom_lua/PropertyDescriptor.lua index 3d4c2bd5..1e34e851 100644 --- a/plugin/rbx_dom_lua/PropertyDescriptor.lua +++ b/plugin/rbx_dom_lua/PropertyDescriptor.lua @@ -53,6 +53,11 @@ function PropertyDescriptor:read(instance) end if self.scriptability == "Custom" then + if customProperties[self.className] == nil then + local fullName = ("%s.%s"):format(instance.className, self.name) + return false, Error.new(Error.Kind.PropertyNotReadable, fullName) + end + local interface = customProperties[self.className][self.name] return interface.read(instance, self.name) @@ -79,6 +84,11 @@ function PropertyDescriptor:write(instance, value) end if self.scriptability == "Custom" then + if customProperties[self.className] == nil then + local fullName = ("%s.%s"):format(instance.className, self.name) + return false, Error.new(Error.Kind.PropertyNotWritable, fullName) + end + local interface = customProperties[self.className][self.name] return interface.write(instance, self.name, value) diff --git a/plugin/rbx_dom_lua/allValues.json b/plugin/rbx_dom_lua/allValues.json index ca62e541..545c9306 100644 --- a/plugin/rbx_dom_lua/allValues.json +++ b/plugin/rbx_dom_lua/allValues.json @@ -207,6 +207,17 @@ }, "ty": "Float64" }, + "Font": { + "value": { + "Font": { + "family": "rbxasset://fonts/families/SourceSansPro.json", + "weight": "Regular", + "style": "Normal", + "cachedFaceId": null + } + }, + "ty": "Font" + }, "Int32": { "value": { "Int32": 6014 diff --git a/plugin/rbx_dom_lua/customProperties.lua b/plugin/rbx_dom_lua/customProperties.lua index 6a2b64eb..3720a0d7 100644 --- a/plugin/rbx_dom_lua/customProperties.lua +++ b/plugin/rbx_dom_lua/customProperties.lua @@ -61,4 +61,14 @@ return { end, }, }, + Model = { + Scale = { + read = function(instance, _, _) + return true, instance:GetScale() + end, + write = function(instance, _, value) + return true, instance:ScaleTo(value) + end, + }, + }, } diff --git a/plugin/rbx_dom_lua/database.json b/plugin/rbx_dom_lua/database.json index 610afbd1..b26361a3 100644 --- a/plugin/rbx_dom_lua/database.json +++ b/plugin/rbx_dom_lua/database.json @@ -1,22 +1,11 @@ { "Version": [ 0, - 530, + 572, 0, - 5300290 + 5720484 ], "Classes": { - "ABTestService": { - "Name": "ABTestService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, "Accessory": { "Name": "Accessory", "Tags": [], @@ -89,6 +78,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -117,6 +107,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -132,6 +123,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -147,6 +139,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -206,6 +199,12 @@ "LevelOfDetail": { "Enum": 0 }, + "ModelStreamingMode": { + "Enum": 0 + }, + "Scale": { + "Float32": 1.0 + }, "SourceAssetId": { "Int64": -1 }, @@ -214,6 +213,118 @@ } } }, + "AdGui": { + "Name": "AdGui", + "Tags": [], + "Superclass": "SurfaceGuiBase", + "Properties": { + "AdShape": { + "Name": "AdShape", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AdShape" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Status": { + "Name": "Status", + "Scriptability": "Read", + "DataType": { + "Enum": "AdUnitStatus" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "AdPortal": { + "Name": "AdPortal", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "PortalInvalidReason": { + "Name": "PortalInvalidReason", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "NotScriptable", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PortalStatus": { + "Name": "PortalStatus", + "Scriptability": "Read", + "DataType": { + "Enum": "AdPortalStatus" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PortalVersion": { + "Name": "PortalVersion", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Status": { + "Name": "Status", + "Scriptability": "Read", + "DataType": { + "Enum": "AdUnitStatus" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "AdService": { "Name": "AdService", "Tags": [ @@ -231,6 +342,212 @@ "Properties": {}, "DefaultProperties": {} }, + "AirController": { + "Name": "AirController", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "ControllerBase", + "Properties": { + "BalanceMaxTorque": { + "Name": "BalanceMaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BalanceRigidityEnabled": { + "Name": "BalanceRigidityEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BalanceSpeed": { + "Name": "BalanceSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaintainAngularMomentum": { + "Name": "MaintainAngularMomentum", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaintainLinearMomentum": { + "Name": "MaintainLinearMomentum", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MoveMaxForce": { + "Name": "MoveMaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OrientationMaxTorque": { + "Name": "OrientationMaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OrientationSpeedFactor": { + "Name": "OrientationSpeedFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TurningMaxTorque": { + "Name": "TurningMaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TurningSpeedFactor": { + "Name": "TurningSpeedFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VectorForce": { + "Name": "VectorForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "BalanceMaxTorque": { + "Float32": 10000.0 + }, + "BalanceRigidityEnabled": { + "Bool": false + }, + "BalanceSpeed": { + "Float32": 100.0 + }, + "MaintainAngularMomentum": { + "Bool": true + }, + "MaintainLinearMomentum": { + "Bool": true + }, + "MoveMaxForce": { + "Float32": 1000.0 + }, + "MoveSpeedFactor": { + "Float32": 1.0 + }, + "OrientationMaxTorque": { + "Float32": 10000.0 + }, + "OrientationSpeedFactor": { + "Float32": 1.0 + }, + "RigidityEnabled": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "TurningMaxTorque": { + "Float32": 10000.0 + }, + "TurningSpeedFactor": { + "Float32": 1.0 + }, + "VectorForce": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, "AlignOrientation": { "Name": "AlignOrientation", "Tags": [], @@ -307,10 +624,12 @@ "DataType": { "Value": "Vector3" }, - "Tags": [], + "Tags": [ + "NotReplicated" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -372,10 +691,12 @@ "DataType": { "Value": "Vector3" }, - "Tags": [], + "Tags": [ + "NotReplicated" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } } @@ -428,13 +749,6 @@ "Mode": { "Enum": 1 }, - "PrimaryAxis": { - "Vector3": [ - 1.0, - 0.0, - 0.0 - ] - }, "PrimaryAxisOnly": { "Bool": false }, @@ -447,13 +761,6 @@ "RigidityEnabled": { "Bool": false }, - "SecondaryAxis": { - "Vector3": [ - 0.0, - 1.0, - 0.0 - ] - }, "SourceAssetId": { "Int64": -1 }, @@ -636,6 +943,7 @@ "AnalyticsService": { "Name": "AnalyticsService", "Tags": [ + "Deprecated", "Service" ], "Superclass": "Instance", @@ -807,6 +1115,22 @@ ], "Superclass": "Instance", "Properties": { + "Guid": { + "Name": "Guid", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Loop": { "Name": "Loop", "Scriptability": "ReadWrite", @@ -847,6 +1171,122 @@ "Properties": {}, "DefaultProperties": {} }, + "AnimationConstraint": { + "Name": "AnimationConstraint", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Constraint", + "Properties": { + "IsKinematic": { + "Name": "IsKinematic", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxForce": { + "Name": "MaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxTorque": { + "Name": "MaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Transform": { + "Name": "Transform", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "Color": { + "Int32": 23 + }, + "Enabled": { + "Bool": true + }, + "IsKinematic": { + "Bool": false + }, + "MaxForce": { + "Float32": 10000.0 + }, + "MaxTorque": { + "Float32": 10000.0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "Transform": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Visible": { + "Bool": false + } + } + }, "AnimationController": { "Name": "AnimationController", "Tags": [], @@ -920,6 +1360,23 @@ ], "Superclass": "Instance", "Properties": { + "Animation": { + "Name": "Animation", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "IsPlaying": { "Name": "IsPlaying", "Scriptability": "Read", @@ -1141,11 +1598,45 @@ "Name": "Animator", "Tags": [], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "EvaluationThrottled": { + "Name": "EvaluationThrottled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotBrowsable", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PreferLodEnabled": { + "Name": "PreferLodEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { "Attributes": { "BinaryString": "" }, + "PreferLodEnabled": { + "Bool": true + }, "SourceAssetId": { "Int64": -1 }, @@ -1246,7 +1737,47 @@ "Service" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "Interface": { + "Name": "Interface", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Port": { + "Name": "Port", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StartServer": { + "Name": "StartServer", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": {} }, "AssetImportService": { @@ -1260,6 +1791,16 @@ "Properties": {}, "DefaultProperties": {} }, + "AssetImportSession": { + "Name": "AssetImportSession", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "AssetManagerService": { "Name": "AssetManagerService", "Tags": [ @@ -1271,6 +1812,56 @@ "Properties": {}, "DefaultProperties": {} }, + "AssetPatchSettings": { + "Name": "AssetPatchSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "ContentId": { + "Name": "ContentId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OutputPath": { + "Name": "OutputPath", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PatchId": { + "Name": "PatchId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "AssetService": { "Name": "AssetService", "Tags": [ @@ -1291,6 +1882,15 @@ } } }, + "AssetSoundEffect": { + "Name": "AssetSoundEffect", + "Tags": [ + "NotCreatable" + ], + "Superclass": "CustomSoundEffect", + "Properties": {}, + "DefaultProperties": {} + }, "Atmosphere": { "Name": "Atmosphere", "Tags": [], @@ -1453,6 +2053,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -1468,6 +2069,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -1558,6 +2160,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -1573,6 +2176,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -1656,6 +2260,146 @@ } } }, + "AudioPages": { + "Name": "AudioPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, + "AudioSearchParams": { + "Name": "AudioSearchParams", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Album": { + "Name": "Album", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Artist": { + "Name": "Artist", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AudioSubType": { + "Name": "AudioSubType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AudioSubType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AudioSubtype": { + "Name": "AudioSubtype", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AudioSubType" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MaxDuration": { + "Name": "MaxDuration", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MinDuration": { + "Name": "MinDuration", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SearchKeyword": { + "Name": "SearchKeyword", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Tag": { + "Name": "Tag", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Title": { + "Name": "Title", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "AvatarEditorService": { "Name": "AvatarEditorService", "Tags": [ @@ -1700,7 +2444,7 @@ "Tags": [ "NotCreatable" ], - "Superclass": "Instance", + "Superclass": "Model", "Properties": { "TextureId": { "Name": "TextureId", @@ -2197,13 +2941,30 @@ } } }, + "CollisionGroup": { + "Name": "CollisionGroup", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "CollisionGroupId": { "Name": "CollisionGroupId", "Scriptability": "ReadWrite", "DataType": { "Value": "Int32" }, - "Tags": [], + "Tags": [ + "NotReplicated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -2253,6 +3014,22 @@ } } }, + "CurrentPhysicalProperties": { + "Name": "CurrentPhysicalProperties", + "Scriptability": "Read", + "DataType": { + "Value": "PhysicalProperties" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "CustomPhysicalProperties": { "Name": "CustomPhysicalProperties", "Scriptability": "ReadWrite", @@ -2283,6 +3060,38 @@ } } }, + "ExtentsCFrame": { + "Name": "ExtentsCFrame", + "Scriptability": "Read", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ExtentsSize": { + "Name": "ExtentsSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Friction": { "Name": "Friction", "Scriptability": "ReadWrite", @@ -2515,6 +3324,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -2543,6 +3353,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -2903,6 +3714,21 @@ } } }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "LinkedSource": { "Name": "LinkedSource", "Scriptability": "ReadWrite", @@ -2915,6 +3741,19 @@ "Serialization": "Serializes" } } + }, + "RunContext": { + "Name": "RunContext", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RunContext" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": {} @@ -4786,23 +5625,6 @@ "Tags": [], "Superclass": "Attachment", "Properties": { - "IsCFrameDriven": { - "Name": "IsCFrameDriven", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "Transform": { "Name": "Transform", "Scriptability": "ReadWrite", @@ -4825,6 +5647,7 @@ "Value": "CFrame" }, "Tags": [ + "Hidden", "NotReplicated", "ReadOnly" ], @@ -5158,6 +5981,23 @@ } } }, + "Valid": { + "Name": "Valid", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Verified": { "Name": "Verified", "Scriptability": "None", @@ -5178,17 +6018,6 @@ }, "DefaultProperties": {} }, - "BreakpointManager": { - "Name": "BreakpointManager", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, "BrickColorValue": { "Name": "BrickColorValue", "Tags": [], @@ -5234,6 +6063,269 @@ "Properties": {}, "DefaultProperties": {} }, + "BubbleChatConfiguration": { + "Name": "BubbleChatConfiguration", + "Tags": [ + "NotCreatable" + ], + "Superclass": "TextChatConfigurations", + "Properties": { + "AdorneeName": { + "Name": "AdorneeName", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BackgroundColor3": { + "Name": "BackgroundColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BackgroundTransparency": { + "Name": "BackgroundTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BubbleDuration": { + "Name": "BubbleDuration", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BubblesSpacing": { + "Name": "BubblesSpacing", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Font": { + "Name": "Font", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "Font" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FontFace": { + "Name": "FontFace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Font" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LocalPlayerStudsOffset": { + "Name": "LocalPlayerStudsOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxDistance": { + "Name": "MaxDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MinimizeDistance": { + "Name": "MinimizeDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextColor3": { + "Name": "TextColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextSize": { + "Name": "TextSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VerticalStudsOffset": { + "Name": "VerticalStudsOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AdorneeName": { + "String": "HumanoidRootPart" + }, + "Attributes": { + "BinaryString": "" + }, + "BackgroundColor3": { + "Color3": [ + 0.98039216, + 0.98039216, + 0.98039216 + ] + }, + "BackgroundTransparency": { + "Float64": 0.1 + }, + "BubbleDuration": { + "Float32": 15.0 + }, + "BubblesSpacing": { + "Float32": 6.0 + }, + "Enabled": { + "Bool": true + }, + "Font": { + "Enum": 18 + }, + "FontFace": { + "Font": { + "family": "rbxasset://fonts/families/GothamSSm.json", + "weight": "Medium", + "style": "Normal", + "cachedFaceId": "rbxasset://fonts/GothamSSm-Medium.otf" + } + }, + "LocalPlayerStudsOffset": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "MaxDistance": { + "Float32": 100.0 + }, + "MinimizeDistance": { + "Float32": 40.0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "TextColor3": { + "Color3": [ + 0.22352941, + 0.23137255, + 0.23921569 + ] + }, + "TextSize": { + "Int64": 16 + }, + "VerticalStudsOffset": { + "Float32": 0.0 + } + } + }, "BulkImportService": { "Name": "BulkImportService", "Tags": [ @@ -5245,6 +6337,61 @@ "Properties": {}, "DefaultProperties": {} }, + "BuoyancySensor": { + "Name": "BuoyancySensor", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "SensorBase", + "Properties": { + "FullySubmerged": { + "Name": "FullySubmerged", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TouchingSurface": { + "Name": "TouchingSurface", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "FullySubmerged": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "TouchingSurface": { + "Bool": false + }, + "UpdateType": { + "Enum": 0 + } + } + }, "CFrameValue": { "Name": "CFrameValue", "Tags": [], @@ -5631,9 +6778,7 @@ }, "CanvasGroup": { "Name": "CanvasGroup", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "GuiObject", "Properties": { "GroupColor3": { @@ -5706,7 +6851,7 @@ "Int32": 1 }, "ClipsDescendants": { - "Bool": false + "Bool": true }, "Draggable": { "Bool": false @@ -5812,9 +6957,10 @@ "ChannelSelectorSoundEffect": { "Name": "ChannelSelectorSoundEffect", "Tags": [ - "NotBrowsable" + "NotBrowsable", + "NotCreatable" ], - "Superclass": "CustomDspSoundEffect", + "Superclass": "CustomSoundEffect", "Properties": { "Channel": { "Name": "Channel", @@ -5999,11 +7145,98 @@ "ChatInputBarConfiguration": { "Name": "ChatInputBarConfiguration", "Tags": [ - "NotBrowsable", "NotCreatable" ], "Superclass": "TextChatConfigurations", "Properties": { + "AbsolutePosition": { + "Name": "AbsolutePosition", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AbsolutePositionWrite": { + "Name": "AbsolutePositionWrite", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AbsoluteSize": { + "Name": "AbsoluteSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AbsoluteSizeWrite": { + "Name": "AbsoluteSizeWrite", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "BackgroundColor3": { + "Name": "BackgroundColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BackgroundTransparency": { + "Name": "BackgroundTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Enabled": { "Name": "Enabled", "Scriptability": "ReadWrite", @@ -6017,6 +7250,32 @@ } } }, + "FontFace": { + "Name": "FontFace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Font" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlaceholderColor3": { + "Name": "PlaceholderColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TargetTextChannel": { "Name": "TargetTextChannel", "Scriptability": "ReadWrite", @@ -6029,36 +7288,64 @@ "Serialization": "Serializes" } } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" }, - "Enabled": { - "Bool": true - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "ChatWindowConfiguration": { - "Name": "ChatWindowConfiguration", - "Tags": [ - "NotBrowsable", - "NotCreatable" - ], - "Superclass": "TextChatConfigurations", - "Properties": { - "Enabled": { - "Name": "Enabled", + "TextBox": { + "Name": "TextBox", "Scriptability": "ReadWrite", "DataType": { - "Value": "Bool" + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextColor3": { + "Name": "TextColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextSize": { + "Name": "TextSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextStrokeColor3": { + "Name": "TextStrokeColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextStrokeTransparency": { + "Name": "TextStrokeTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" }, "Tags": [], "Kind": { @@ -6072,14 +7359,350 @@ "Attributes": { "BinaryString": "" }, + "BackgroundColor3": { + "Color3": [ + 0.09803922, + 0.105882354, + 0.11372549 + ] + }, + "BackgroundTransparency": { + "Float64": 0.2 + }, "Enabled": { "Bool": true }, + "FontFace": { + "Font": { + "family": "rbxasset://fonts/families/GothamSSm.json", + "weight": "Medium", + "style": "Normal", + "cachedFaceId": "rbxasset://fonts/GothamSSm-Medium.otf" + } + }, + "PlaceholderColor3": { + "Color3": [ + 0.69803923, + 0.69803923, + 0.69803923 + ] + }, "SourceAssetId": { "Int64": -1 }, "Tags": { "BinaryString": "" + }, + "TextColor3": { + "Color3": [ + 1.0, + 1.0, + 1.0 + ] + }, + "TextSize": { + "Int64": 14 + }, + "TextStrokeColor3": { + "Color3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "TextStrokeTransparency": { + "Float64": 0.5 + } + } + }, + "ChatWindowConfiguration": { + "Name": "ChatWindowConfiguration", + "Tags": [ + "NotCreatable" + ], + "Superclass": "TextChatConfigurations", + "Properties": { + "AbsolutePosition": { + "Name": "AbsolutePosition", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AbsolutePositionWrite": { + "Name": "AbsolutePositionWrite", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AbsoluteSize": { + "Name": "AbsoluteSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AbsoluteSizeWrite": { + "Name": "AbsoluteSizeWrite", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "BackgroundColor3": { + "Name": "BackgroundColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BackgroundTransparency": { + "Name": "BackgroundTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FontFace": { + "Name": "FontFace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Font" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HeightScale": { + "Name": "HeightScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HorizontalAlignment": { + "Name": "HorizontalAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "HorizontalAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextColor3": { + "Name": "TextColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextSize": { + "Name": "TextSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextStrokeColor3": { + "Name": "TextStrokeColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextStrokeTransparency": { + "Name": "TextStrokeTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VerticalAlignment": { + "Name": "VerticalAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "VerticalAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WidthScale": { + "Name": "WidthScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "BackgroundColor3": { + "Color3": [ + 0.09803922, + 0.105882354, + 0.11372549 + ] + }, + "BackgroundTransparency": { + "Float64": 0.3 + }, + "Enabled": { + "Bool": true + }, + "FontFace": { + "Font": { + "family": "rbxasset://fonts/families/GothamSSm.json", + "weight": "Medium", + "style": "Normal", + "cachedFaceId": "rbxasset://fonts/GothamSSm-Medium.otf" + } + }, + "HeightScale": { + "Float32": 1.0 + }, + "HorizontalAlignment": { + "Enum": 1 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "TextColor3": { + "Color3": [ + 1.0, + 1.0, + 1.0 + ] + }, + "TextSize": { + "Int64": 14 + }, + "TextStrokeColor3": { + "Color3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "TextStrokeTransparency": { + "Float64": 0.5 + }, + "VerticalAlignment": { + "Enum": 1 + }, + "WidthScale": { + "Float32": 1.0 } } }, @@ -6215,6 +7838,144 @@ "Properties": {}, "DefaultProperties": {} }, + "ClimbController": { + "Name": "ClimbController", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "ControllerBase", + "Properties": { + "AccelerationTime": { + "Name": "AccelerationTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BalanceMaxTorque": { + "Name": "BalanceMaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BalanceRigidityEnabled": { + "Name": "BalanceRigidityEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BalanceSpeed": { + "Name": "BalanceSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MoveMaxForce": { + "Name": "MoveMaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OrientationMaxTorque": { + "Name": "OrientationMaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OrientationSpeedFactor": { + "Name": "OrientationSpeedFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AccelerationTime": { + "Float32": 0.0 + }, + "Attributes": { + "BinaryString": "" + }, + "BalanceMaxTorque": { + "Float32": 10000.0 + }, + "BalanceRigidityEnabled": { + "Bool": false + }, + "BalanceSpeed": { + "Float32": 100.0 + }, + "MoveMaxForce": { + "Float32": 10000.0 + }, + "MoveSpeedFactor": { + "Float32": 1.0 + }, + "OrientationMaxTorque": { + "Float32": 10000.0 + }, + "OrientationSpeedFactor": { + "Float32": 100.0 + }, + "RigidityEnabled": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, "Clothing": { "Name": "Clothing", "Tags": [ @@ -6238,6 +7999,16 @@ }, "DefaultProperties": {} }, + "CloudLocalizationTable": { + "Name": "CloudLocalizationTable", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "LocalizationTable", + "Properties": {}, + "DefaultProperties": {} + }, "Clouds": { "Name": "Clouds", "Tags": [], @@ -7056,6 +8827,309 @@ "Properties": {}, "DefaultProperties": {} }, + "ControllerBase": { + "Name": "ControllerBase", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "MoveSpeedFactor": { + "Name": "MoveSpeedFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RigidityEnabled": { + "Name": "RigidityEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "ControllerManager": { + "Name": "ControllerManager", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "ActiveController": { + "Name": "ActiveController", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BaseMoveSpeed": { + "Name": "BaseMoveSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BaseTurnSpeed": { + "Name": "BaseTurnSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClimbSensor": { + "Name": "ClimbSensor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FacingDirection": { + "Name": "FacingDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GroundSensor": { + "Name": "GroundSensor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MovingDirection": { + "Name": "MovingDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "BaseMoveSpeed": { + "Float32": 16.0 + }, + "BaseTurnSpeed": { + "Float32": 8.0 + }, + "FacingDirection": { + "Vector3": [ + 0.0, + 0.0, + 1.0 + ] + }, + "MovingDirection": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, + "ControllerPartSensor": { + "Name": "ControllerPartSensor", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "ControllerSensor", + "Properties": { + "HitFrame": { + "Name": "HitFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HitNormal": { + "Name": "HitNormal", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SearchDistance": { + "Name": "SearchDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SensedPart": { + "Name": "SensedPart", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SensorMode": { + "Name": "SensorMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SensorMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "HitFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "HitNormal": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SearchDistance": { + "Float32": 0.0 + }, + "SensorMode": { + "Enum": 0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "UpdateType": { + "Enum": 0 + } + } + }, + "ControllerSensor": { + "Name": "ControllerSensor", + "Tags": [ + "NotCreatable" + ], + "Superclass": "SensorBase", + "Properties": {}, + "DefaultProperties": {} + }, "ControllerService": { "Name": "ControllerService", "Tags": [ @@ -7149,6 +9223,16 @@ "Properties": {}, "DefaultProperties": {} }, + "CoreScriptDebuggingManagerHelper": { + "Name": "CoreScriptDebuggingManagerHelper", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "CoreScriptSyncService": { "Name": "CoreScriptSyncService", "Tags": [ @@ -7234,6 +9318,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -7402,15 +9489,6 @@ } } }, - "CustomDspSoundEffect": { - "Name": "CustomDspSoundEffect", - "Tags": [ - "NotCreatable" - ], - "Superclass": "SoundEffect", - "Properties": {}, - "DefaultProperties": {} - }, "CustomEvent": { "Name": "CustomEvent", "Tags": [ @@ -7463,6 +9541,15 @@ } } }, + "CustomSoundEffect": { + "Name": "CustomSoundEffect", + "Tags": [ + "NotCreatable" + ], + "Superclass": "SoundEffect", + "Properties": {}, + "DefaultProperties": {} + }, "CylinderHandleAdornment": { "Name": "CylinderHandleAdornment", "Tags": [], @@ -8512,7 +10599,24 @@ "NotReplicated" ], "Superclass": "Pages", - "Properties": {}, + "Properties": { + "Cursor": { + "Name": "Cursor", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, "DefaultProperties": {} }, "DataStoreListingPages": { @@ -8522,7 +10626,24 @@ "NotReplicated" ], "Superclass": "Pages", - "Properties": {}, + "Properties": { + "Cursor": { + "Name": "Cursor", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, "DefaultProperties": {} }, "DataStoreObjectVersionInfo": { @@ -9565,6 +11686,17 @@ } } }, + "DeviceIdService": { + "Name": "DeviceIdService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Dialog": { "Name": "Dialog", "Tags": [], @@ -10147,6 +12279,23 @@ } } }, + "HoverLineThickness": { + "Name": "HoverLineThickness", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "HoverThickness": { "Name": "HoverThickness", "Scriptability": "Read", @@ -10498,6 +12647,78 @@ "Properties": {}, "DefaultProperties": {} }, + "ExperienceAuthService": { + "Name": "ExperienceAuthService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "ExperienceInviteOptions": { + "Name": "ExperienceInviteOptions", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "InviteMessageId": { + "Name": "InviteMessageId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InviteUser": { + "Name": "InviteUser", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LaunchData": { + "Name": "LaunchData", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PromptMessage": { + "Name": "PromptMessage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "Explosion": { "Name": "Explosion", "Tags": [], @@ -10694,9 +12915,7 @@ }, "FaceControls": { "Name": "FaceControls", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "Instance", "Properties": { "ChinRaiser": { @@ -11486,6 +13705,34 @@ }, "DefaultProperties": {} }, + "FacialAnimationRecordingService": { + "Name": "FacialAnimationRecordingService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "BiometricDataConsent": { + "Name": "BiometricDataConsent", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "FacialAnimationStreamingService": { "Name": "FacialAnimationStreamingService", "Tags": [ @@ -11494,6 +13741,21 @@ ], "Superclass": "Instance", "Properties": { + "EnableFlags": { + "Name": "EnableFlags", + "Scriptability": "None", + "DataType": { + "Enum": "FacialAnimationFlags" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Enabled": { "Name": "Enabled", "Scriptability": "None", @@ -11522,6 +13784,42 @@ } } }, + "FacialAnimationStreamingServiceStats": { + "Name": "FacialAnimationStreamingServiceStats", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "FacialAnimationStreamingServiceV2": { + "Name": "FacialAnimationStreamingServiceV2", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "ServiceState": { + "Name": "ServiceState", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "Feature": { "Name": "Feature", "Tags": [ @@ -11912,12 +14210,21 @@ ] } }, + "LevelOfDetail": { + "Enum": 0 + }, "ManualActivationOnly": { "Bool": false }, + "ModelStreamingMode": { + "Enum": 0 + }, "RequiresHandle": { "Bool": true }, + "Scale": { + "Float32": 1.0 + }, "SourceAssetId": { "Int64": -1 }, @@ -12025,6 +14332,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -12885,6 +15195,19 @@ ], "Superclass": "Instance", "Properties": { + "Font": { + "Name": "Font", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Font" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Size": { "Name": "Size", "Scriptability": "ReadWrite", @@ -13112,6 +15435,256 @@ "Properties": {}, "DefaultProperties": {} }, + "GroundController": { + "Name": "GroundController", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "ControllerBase", + "Properties": { + "AccelerationLean": { + "Name": "AccelerationLean", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AccelerationTime": { + "Name": "AccelerationTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AlignSpeed": { + "Name": "AlignSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AlignTorque": { + "Name": "AlignTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BalanceMaxTorque": { + "Name": "BalanceMaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BalanceRigidityEnabled": { + "Name": "BalanceRigidityEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BalanceSpeed": { + "Name": "BalanceSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DecelerationTime": { + "Name": "DecelerationTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Friction": { + "Name": "Friction", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FrictionWeight": { + "Name": "FrictionWeight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GroundOffset": { + "Name": "GroundOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StandForce": { + "Name": "StandForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StandSpeed": { + "Name": "StandSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TurningFactor": { + "Name": "TurningFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AccelerationLean": { + "Float32": 1.0 + }, + "AccelerationTime": { + "Float32": 0.0 + }, + "AlignSpeed": { + "Float32": 100.0 + }, + "AlignTorque": { + "Float32": 10000.0 + }, + "Attributes": { + "BinaryString": "" + }, + "BalanceMaxTorque": { + "Float32": 10000.0 + }, + "BalanceRigidityEnabled": { + "Bool": false + }, + "BalanceSpeed": { + "Float32": 100.0 + }, + "DecelerationTime": { + "Float32": 0.0 + }, + "Friction": { + "Float32": 2.0 + }, + "FrictionWeight": { + "Float32": 1.0 + }, + "GroundOffset": { + "Float32": 1.0 + }, + "MoveSpeedFactor": { + "Float32": 1.0 + }, + "RigidityEnabled": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "StandForce": { + "Float32": 10000.0 + }, + "StandSpeed": { + "Float32": 100.0 + }, + "Tags": { + "BinaryString": "" + }, + "TurningFactor": { + "Float32": 1.0 + } + } + }, "GroupService": { "Name": "GroupService", "Tags": [ @@ -13519,18 +16092,24 @@ "AutoLocalize": { "Bool": true }, + "ClipToDeviceSafeArea": { + "Bool": true + }, "DisplayOrder": { "Int32": 0 }, "Enabled": { "Bool": true }, - "IgnoreGuiInset": { - "Bool": false - }, "ResetOnSpawn": { "Bool": true }, + "SafeAreaCompatibility": { + "Enum": 1 + }, + "ScreenInsets": { + "Enum": 2 + }, "SelectionBehaviorDown": { "Enum": 0 }, @@ -13992,10 +16571,13 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotReplicated" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -14435,6 +17017,21 @@ } } }, + "LineThickness": { + "Name": "LineThickness", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "OutlineColor": { "Name": "OutlineColor", "Scriptability": "ReadWrite", @@ -14460,6 +17057,21 @@ "Serialization": "Serializes" } } + }, + "ReservedId": { + "Name": "ReservedId", + "Scriptability": "None", + "DataType": { + "Enum": "ReservedHighlightId" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -14859,6 +17471,15 @@ "BinType": { "Enum": 0 }, + "LevelOfDetail": { + "Enum": 0 + }, + "ModelStreamingMode": { + "Enum": 0 + }, + "Scale": { + "Float32": 1.0 + }, "SourceAssetId": { "Int64": -1 }, @@ -15037,6 +17658,21 @@ } } }, + "EvaluateStateMachine": { + "Name": "EvaluateStateMachine", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "FloorMaterial": { "Name": "FloorMaterial", "Scriptability": "Read", @@ -15458,6 +18094,9 @@ "DisplayName": { "String": "" }, + "EvaluateStateMachine": { + "Bool": true + }, "HealthDisplayDistance": { "Float32": 100.0 }, @@ -15815,6 +18454,19 @@ } } }, + "MoodAnimation": { + "Name": "MoodAnimation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "NeckAccessory": { "Name": "NeckAccessory", "Scriptability": "ReadWrite", @@ -16121,6 +18773,9 @@ 0.0 ] }, + "MoodAnimation": { + "Int64": 0 + }, "NeckAccessory": { "String": "" }, @@ -16189,6 +18844,234 @@ } } }, + "IKControl": { + "Name": "IKControl", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "ChainRoot": { + "Name": "ChainRoot", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EndEffector": { + "Name": "EndEffector", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EndEffectorOffset": { + "Name": "EndEffectorOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Offset": { + "Name": "Offset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Pole": { + "Name": "Pole", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Priority": { + "Name": "Priority", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SmoothTime": { + "Name": "SmoothTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Target": { + "Name": "Target", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Type": { + "Name": "Type", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "IKControlType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Weight": { + "Name": "Weight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "Enabled": { + "Bool": true + }, + "EndEffectorOffset": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Offset": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Priority": { + "Int32": 0 + }, + "SmoothTime": { + "Float32": 0.05 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "Type": { + "Enum": 0 + }, + "Weight": { + "Float32": 1.0 + } + } + }, "ILegacyStudioBridge": { "Name": "ILegacyStudioBridge", "Tags": [ @@ -16597,6 +19480,45 @@ } } }, + "ImageDataExperimental": { + "Name": "ImageDataExperimental", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TemporaryId": { + "Name": "TemporaryId", + "Scriptability": "Read", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "ImageHandleAdornment": { "Name": "ImageHandleAdornment", "Tags": [], @@ -17111,6 +20033,16 @@ }, "DefaultProperties": {} }, + "ImporterFacsSettings": { + "Name": "ImporterFacsSettings", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "ImporterBaseSettings", + "Properties": {}, + "DefaultProperties": {} + }, "ImporterGroupSettings": { "Name": "ImporterGroupSettings", "Tags": [ @@ -17181,17 +20113,14 @@ "Properties": { "DiffuseFilePath": { "Name": "DiffuseFilePath", - "Scriptability": "Read", + "Scriptability": "ReadWrite", "DataType": { "Value": "String" }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], + "Tags": [], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } }, @@ -17213,49 +20142,40 @@ }, "MetalnessFilePath": { "Name": "MetalnessFilePath", - "Scriptability": "Read", + "Scriptability": "ReadWrite", "DataType": { "Value": "String" }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], + "Tags": [], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } }, "NormalFilePath": { "Name": "NormalFilePath", - "Scriptability": "Read", + "Scriptability": "ReadWrite", "DataType": { "Value": "String" }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], + "Tags": [], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } }, "RoughnessFilePath": { "Name": "RoughnessFilePath", - "Scriptability": "Read", + "Scriptability": "ReadWrite", "DataType": { "Value": "String" }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], + "Tags": [], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } } @@ -17299,8 +20219,8 @@ } } }, - "CageManifoldPreview": { - "Name": "CageManifoldPreview", + "CageMeshIntersectedPreview": { + "Name": "CageMeshIntersectedPreview", "Scriptability": "ReadWrite", "DataType": { "Value": "Bool" @@ -17312,6 +20232,22 @@ } } }, + "CageMeshNotIntersected": { + "Name": "CageMeshNotIntersected", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "CageNoOverlappingVertices": { "Name": "CageNoOverlappingVertices", "Scriptability": "Read", @@ -17328,8 +20264,50 @@ } } }, - "CageNoOverlappingVerticesPreview": { - "Name": "CageNoOverlappingVerticesPreview", + "CageNonManifoldPreview": { + "Name": "CageNonManifoldPreview", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CageOverlappingVerticesPreview": { + "Name": "CageOverlappingVerticesPreview", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CageUVMatched": { + "Name": "CageUVMatched", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CageUVMisMatchedPreview": { + "Name": "CageUVMisMatchedPreview", "Scriptability": "ReadWrite", "DataType": { "Value": "Bool" @@ -17383,6 +20361,93 @@ } } }, + "IrrelevantCageModifiedPreview": { + "Name": "IrrelevantCageModifiedPreview", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MeshHoleDetectedPreview": { + "Name": "MeshHoleDetectedPreview", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MeshNoHoleDetected": { + "Name": "MeshNoHoleDetected", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "NoIrrelevantCageModified": { + "Name": "NoIrrelevantCageModified", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "NoOuterCageFarExtendedFromMesh": { + "Name": "NoOuterCageFarExtendedFromMesh", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "OuterCageFarExtendedFromMeshPreview": { + "Name": "OuterCageFarExtendedFromMeshPreview", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PolygonCount": { "Name": "PolygonCount", "Scriptability": "Read", @@ -17398,6 +20463,19 @@ "Serialization": "DoesNotSerialize" } } + }, + "UseImportedPivot": { + "Name": "UseImportedPivot", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": {} @@ -17410,6 +20488,19 @@ ], "Superclass": "ImporterBaseSettings", "Properties": { + "AddModelToInventory": { + "Name": "AddModelToInventory", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Anchored": { "Name": "Anchored", "Scriptability": "ReadWrite", @@ -17423,6 +20514,19 @@ } } }, + "ExistingPackageId": { + "Name": "ExistingPackageId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "FileDimensions": { "Name": "FileDimensions", "Scriptability": "Read", @@ -17452,6 +20556,19 @@ } } }, + "ImportAsPackage": { + "Name": "ImportAsPackage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "InsertInWorkspace": { "Name": "InsertInWorkspace", "Scriptability": "ReadWrite", @@ -17520,6 +20637,19 @@ } } }, + "RigScale": { + "Name": "RigScale", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RigScale" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "RigType": { "Name": "RigType", "Scriptability": "ReadWrite", @@ -17546,6 +20676,19 @@ } } }, + "UseSceneOriginAsCFrame": { + "Name": "UseSceneOriginAsCFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "UseSceneOriginAsPivot": { "Name": "UseSceneOriginAsPivot", "Scriptability": "ReadWrite", @@ -17559,6 +20702,19 @@ } } }, + "UsesCages": { + "Name": "UsesCages", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "WorldForward": { "Name": "WorldForward", "Scriptability": "ReadWrite", @@ -17596,7 +20752,73 @@ "Service" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "AddPathsToBundle": { + "Name": "AddPathsToBundle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BuildDebouncePeriod": { + "Name": "BuildDebouncePeriod", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HighCompression": { + "Name": "HighCompression", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SerializePatch": { + "Name": "SerializePatch", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ZstdCompression": { + "Name": "ZstdCompression", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": {} }, "InputObject": { @@ -18067,6 +21289,229 @@ } } }, + "IntersectOperation": { + "Name": "IntersectOperation", + "Tags": [], + "Superclass": "PartOperation", + "Properties": {}, + "DefaultProperties": { + "Anchored": { + "Bool": false + }, + "AssetId": { + "Content": "" + }, + "Attributes": { + "BinaryString": "" + }, + "BackParamA": { + "Float32": -0.5 + }, + "BackParamB": { + "Float32": 0.5 + }, + "BackSurface": { + "Enum": 0 + }, + "BackSurfaceInput": { + "Enum": 0 + }, + "BottomParamA": { + "Float32": -0.5 + }, + "BottomParamB": { + "Float32": 0.5 + }, + "BottomSurface": { + "Enum": 0 + }, + "BottomSurfaceInput": { + "Enum": 0 + }, + "CFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Bool": true + }, + "CanQuery": { + "Bool": true + }, + "CanTouch": { + "Bool": true + }, + "CastShadow": { + "Bool": true + }, + "CollisionGroup": { + "String": "Default" + }, + "CollisionGroupId": { + "Int32": 0 + }, + "Color": { + "Color3uint8": [ + 255, + 255, + 255 + ] + }, + "CustomPhysicalProperties": { + "PhysicalProperties": "Default" + }, + "FrontParamA": { + "Float32": -0.5 + }, + "FrontParamB": { + "Float32": 0.5 + }, + "FrontSurface": { + "Enum": 0 + }, + "FrontSurfaceInput": { + "Enum": 0 + }, + "LeftParamA": { + "Float32": -0.5 + }, + "LeftParamB": { + "Float32": 0.5 + }, + "LeftSurface": { + "Enum": 0 + }, + "LeftSurfaceInput": { + "Enum": 0 + }, + "Locked": { + "Bool": false + }, + "Massless": { + "Bool": false + }, + "Material": { + "Enum": 256 + }, + "PivotOffset": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Reflectance": { + "Float32": 0.0 + }, + "RenderFidelity": { + "Enum": 1 + }, + "RightParamA": { + "Float32": -0.5 + }, + "RightParamB": { + "Float32": 0.5 + }, + "RightSurface": { + "Enum": 0 + }, + "RightSurfaceInput": { + "Enum": 0 + }, + "RootPriority": { + "Int32": 0 + }, + "RotVelocity": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Size": { + "Vector3": [ + 4.0, + 1.2, + 2.0 + ] + }, + "SmoothingAngle": { + "Float32": 0.0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "TopParamA": { + "Float32": -0.5 + }, + "TopParamB": { + "Float32": 0.5 + }, + "TopSurface": { + "Enum": 0 + }, + "TopSurfaceInput": { + "Enum": 0 + }, + "Transparency": { + "Float32": 0.0 + }, + "UsePartColor": { + "Bool": false + }, + "Velocity": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, "InventoryPages": { "Name": "InventoryPages", "Tags": [ @@ -19248,6 +22693,16 @@ } } }, + "LiveScriptingService": { + "Name": "LiveScriptingService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "LocalDebuggerConnection": { "Name": "LocalDebuggerConnection", "Tags": [ @@ -19273,6 +22728,9 @@ "LinkedSource": { "Content": "" }, + "RunContext": { + "Enum": 0 + }, "Source": { "String": "" }, @@ -19499,7 +22957,7 @@ "BinaryString": "" }, "Contents": { - "String": "" + "String": "[]" }, "SourceAssetId": { "Int64": -1 @@ -19611,6 +23069,21 @@ "Serialization": "DoesNotSerialize" } } + }, + "RuntimeSource": { + "Name": "RuntimeSource", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": {} @@ -19848,10 +23321,30 @@ "Properties": {}, "DefaultProperties": {} }, + "MaterialGenerationService": { + "Name": "MaterialGenerationService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "MaterialGenerationSession": { + "Name": "MaterialGenerationSession", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "MaterialService": { "Name": "MaterialService", "Tags": [ - "NotBrowsable", "NotCreatable", "Service" ], @@ -20351,118 +23844,101 @@ "Serialization": "Serializes" } } - }, - "hasPropertyWarningInStudio": { - "Name": "hasPropertyWarningInStudio", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } } }, "DefaultProperties": { "AsphaltName": { - "String": "" + "String": "Asphalt" }, "Attributes": { "BinaryString": "" }, "BasaltName": { - "String": "" + "String": "Basalt" }, "BrickName": { - "String": "" + "String": "Brick" }, "CobblestoneName": { - "String": "" + "String": "Cobblestone" }, "ConcreteName": { - "String": "" + "String": "Concrete" }, "CorrodedMetalName": { - "String": "" + "String": "CorrodedMetal" }, "CrackedLavaName": { - "String": "" + "String": "CrackedLava" }, "DiamondPlateName": { - "String": "" + "String": "DiamondPlate" }, "FabricName": { - "String": "" + "String": "Fabric" }, "FoilName": { - "String": "" + "String": "Foil" }, "GlacierName": { - "String": "" + "String": "Glacier" }, "GraniteName": { - "String": "" + "String": "Granite" }, "GrassName": { - "String": "" + "String": "Grass" }, "GroundName": { - "String": "" + "String": "Ground" }, "IceName": { - "String": "" + "String": "Ice" }, "LeafyGrassName": { - "String": "" + "String": "LeafyGrass" }, "LimestoneName": { - "String": "" + "String": "Limestone" }, "MarbleName": { - "String": "" + "String": "Marble" }, "MetalName": { - "String": "" + "String": "Metal" }, "MudName": { - "String": "" + "String": "Mud" }, "PavementName": { - "String": "" + "String": "Pavement" }, "PebbleName": { - "String": "" + "String": "Pebble" }, "PlasticName": { - "String": "" + "String": "Plastic" }, "RockName": { - "String": "" + "String": "Rock" }, "SaltName": { - "String": "" + "String": "Salt" }, "SandName": { - "String": "" + "String": "Sand" }, "SandstoneName": { - "String": "" + "String": "Sandstone" }, "SlateName": { - "String": "" + "String": "Slate" }, "SmoothPlasticName": { - "String": "" + "String": "SmoothPlastic" }, "SnowName": { - "String": "" + "String": "Snow" }, "SourceAssetId": { "Int64": -1 @@ -20471,18 +23947,16 @@ "BinaryString": "" }, "WoodName": { - "String": "" + "String": "Wood" }, "WoodPlanksName": { - "String": "" + "String": "WoodPlanks" } } }, "MaterialVariant": { "Name": "MaterialVariant", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "Instance", "Properties": { "BaseMaterial": { @@ -20511,6 +23985,19 @@ } } }, + "CustomPhysicalProperties": { + "Name": "CustomPhysicalProperties", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "PhysicalProperties" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MaterialPattern": { "Name": "MaterialPattern", "Scriptability": "ReadWrite", @@ -20587,6 +24074,9 @@ "ColorMap": { "Content": "" }, + "CustomPhysicalProperties": { + "PhysicalProperties": "Default" + }, "MaterialPattern": { "Enum": 0 }, @@ -20681,6 +24171,32 @@ "Properties": {}, "DefaultProperties": {} }, + "MeshDataExperimental": { + "Name": "MeshDataExperimental", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Size": { + "Name": "Size", + "Scriptability": "Read", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "MeshPart": { "Name": "MeshPart", "Tags": [], @@ -20744,22 +24260,6 @@ } } }, - "MeshID": { - "Name": "MeshID", - "Scriptability": "None", - "DataType": { - "Value": "Content" - }, - "Tags": [ - "Deprecated", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "MeshId": { "Name": "MeshId", "Scriptability": "Read", @@ -20773,22 +24273,6 @@ } } }, - "MeshSize": { - "Name": "MeshSize", - "Scriptability": "Read", - "DataType": { - "Value": "Vector3" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "RenderFidelity": { "Name": "RenderFidelity", "Scriptability": "ReadWrite", @@ -20887,6 +24371,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -20949,9 +24436,6 @@ "Material": { "Enum": 256 }, - "MeshID": { - "Content": "" - }, "MeshId": { "Content": "" }, @@ -21254,6 +24738,23 @@ "Serialization": "Serializes" } } + }, + "Valid": { + "Name": "Valid", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -21306,6 +24807,17 @@ } } }, + "MetaBreakpointManager": { + "Name": "MetaBreakpointManager", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Model": { "Name": "Model", "Tags": [], @@ -21324,6 +24836,19 @@ } } }, + "ModelStreamingMode": { + "Name": "ModelStreamingMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ModelStreamingMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PrimaryPart": { "Name": "PrimaryPart", "Scriptability": "ReadWrite", @@ -21337,11 +24862,11 @@ } } }, - "World Pivot Orientation": { - "Name": "World Pivot Orientation", - "Scriptability": "None", + "Scale": { + "Name": "Scale", + "Scriptability": "Custom", "DataType": { - "Value": "Vector3" + "Value": "Float32" }, "Tags": [ "NotReplicated", @@ -21349,23 +24874,22 @@ ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": { + "SerializesAs": "ScaleFactor" + } } } }, - "World Pivot Position": { - "Name": "World Pivot Position", + "ScaleFactor": { + "Name": "ScaleFactor", "Scriptability": "None", "DataType": { - "Value": "Vector3" + "Value": "Float32" }, - "Tags": [ - "NotReplicated", - "NotScriptable" - ], + "Tags": [], "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" + "Alias": { + "AliasFor": "Scale" } } }, @@ -21392,6 +24916,12 @@ "LevelOfDetail": { "Enum": 0 }, + "ModelStreamingMode": { + "Enum": 0 + }, + "Scale": { + "Float32": 1.0 + }, "SourceAssetId": { "Int64": -1 }, @@ -22061,6 +25591,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -22505,6 +26038,23 @@ ], "Superclass": "Instance", "Properties": { + "IsConnected": { + "Name": "IsConnected", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "IsLuaChatEnabled": { "Name": "IsLuaChatEnabled", "Scriptability": "None", @@ -22715,11 +26265,11 @@ ], "Superclass": "Instance", "Properties": { - "Origin Orientation": { - "Name": "Origin Orientation", + "Origin": { + "Name": "Origin", "Scriptability": "None", "DataType": { - "Value": "Vector3" + "Value": "CFrame" }, "Tags": [ "NotReplicated", @@ -22731,43 +26281,11 @@ } } }, - "Origin Position": { - "Name": "Origin Position", + "Pivot Offset": { + "Name": "Pivot Offset", "Scriptability": "None", "DataType": { - "Value": "Vector3" - }, - "Tags": [ - "NotReplicated", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Pivot Offset Orientation": { - "Name": "Pivot Offset Orientation", - "Scriptability": "None", - "DataType": { - "Value": "Vector3" - }, - "Tags": [ - "NotReplicated", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Pivot Offset Position": { - "Name": "Pivot Offset Position", - "Scriptability": "None", - "DataType": { - "Value": "Vector3" + "Value": "CFrame" }, "Tags": [ "NotReplicated", @@ -23222,6 +26740,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -23531,6 +27052,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -24317,6 +27841,67 @@ } } }, + "PatchBundlerFileWatch": { + "Name": "PatchBundlerFileWatch", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "PatchMapping": { + "Name": "PatchMapping", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "FlattenTree": { + "Name": "FlattenTree", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PatchId": { + "Name": "PatchId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TargetPath": { + "Name": "TargetPath", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "Path": { "Name": "Path", "Tags": [ @@ -24346,9 +27931,7 @@ }, "PathfindingLink": { "Name": "PathfindingLink", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "Instance", "Properties": { "Attachment0": { @@ -24731,6 +28314,45 @@ } } }, + "AreConstraintForcesShownForSelectedOrHoveredInstances": { + "Name": "AreConstraintForcesShownForSelectedOrHoveredInstances", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreConstraintTorquesShownForSelectedOrHoveredInstances": { + "Name": "AreConstraintTorquesShownForSelectedOrHoveredInstances", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AreContactForcesShownForSelectedOrHoveredAssemblies": { + "Name": "AreContactForcesShownForSelectedOrHoveredAssemblies", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "AreContactIslandsShown": { "Name": "AreContactIslandsShown", "Scriptability": "ReadWrite", @@ -24770,6 +28392,19 @@ } } }, + "AreMagnitudesShownForDrawnForcesAndTorques": { + "Name": "AreMagnitudesShownForDrawnForcesAndTorques", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "AreMechanismsShown": { "Name": "AreMechanismsShown", "Scriptability": "ReadWrite", @@ -24835,6 +28470,19 @@ } } }, + "AreSolverIslandsShown": { + "Name": "AreSolverIslandsShown", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "AreTerrainReplicationRegionsShown": { "Name": "AreTerrainReplicationRegionsShown", "Scriptability": "ReadWrite", @@ -24916,6 +28564,19 @@ } } }, + "ForceDrawScale": { + "Name": "ForceDrawScale", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "IsInterpolationThrottleShown": { "Name": "IsInterpolationThrottleShown", "Scriptability": "ReadWrite", @@ -24981,6 +28642,19 @@ } } }, + "SolverConvergenceVisualizationMode": { + "Name": "SolverConvergenceVisualizationMode", + "Scriptability": "None", + "DataType": { + "Enum": "SolverConvergenceVisualizationMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ThrottleAdjustTime": { "Name": "ThrottleAdjustTime", "Scriptability": "ReadWrite", @@ -25466,6 +29140,19 @@ } } }, + "HasVerifiedBadge": { + "Name": "HasVerifiedBadge", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "HealthDisplayDistance": { "Name": "HealthDisplayDistance", "Scriptability": "ReadWrite", @@ -25686,6 +29373,23 @@ } } }, + "UnfilteredChat": { + "Name": "UnfilteredChat", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "UserId": { "Name": "UserId", "Scriptability": "ReadWrite", @@ -25714,6 +29418,22 @@ } } }, + "VREnabled": { + "Name": "VREnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "userId": { "Name": "userId", "Scriptability": "ReadWrite", @@ -25736,6 +29456,7 @@ "Name": "PlayerEmulatorService", "Tags": [ "NotCreatable", + "NotReplicated", "Service" ], "Superclass": "Instance", @@ -25747,7 +29468,8 @@ "Value": "Bool" }, "Tags": [ - "Hidden" + "Hidden", + "NotReplicated" ], "Kind": { "Canonical": { @@ -25762,7 +29484,8 @@ "Value": "String" }, "Tags": [ - "Hidden" + "Hidden", + "NotReplicated" ], "Kind": { "Canonical": { @@ -25777,7 +29500,8 @@ "Value": "String" }, "Tags": [ - "Hidden" + "Hidden", + "NotReplicated" ], "Kind": { "Canonical": { @@ -25792,7 +29516,8 @@ "Value": "Bool" }, "Tags": [ - "Hidden" + "Hidden", + "NotReplicated" ], "Kind": { "Canonical": { @@ -25807,7 +29532,8 @@ "Value": "BinaryString" }, "Tags": [ - "Hidden" + "Hidden", + "NotReplicated" ], "Kind": { "Canonical": { @@ -26082,6 +29808,22 @@ } } }, + "UseStrafingAnimations": { + "Name": "UseStrafingAnimations", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "localPlayer": { "Name": "localPlayer", "Scriptability": "Read", @@ -26140,6 +29882,9 @@ }, "Tags": { "BinaryString": "" + }, + "UseStrafingAnimations": { + "Bool": false } } }, @@ -26495,6 +30240,17 @@ "Properties": {}, "DefaultProperties": {} }, + "PluginManagementService": { + "Name": "PluginManagementService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "PluginManager": { "Name": "PluginManager", "Tags": [ @@ -27442,6 +31198,22 @@ "Serialization": "Serializes" } } + }, + "ServiceVisibility": { + "Name": "ServiceVisibility", + "Scriptability": "None", + "DataType": { + "Enum": "ServiceVisibility" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -27496,6 +31268,9 @@ "ServerOnly": { "Bool": false }, + "ServiceVisibility": { + "Enum": 0 + }, "SliderScaling": { "String": "" }, @@ -28031,6 +31806,16 @@ } } }, + "RemoteCursorService": { + "Name": "RemoteCursorService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "RemoteDebuggerServer": { "Name": "RemoteDebuggerServer", "Tags": [ @@ -28350,6 +32135,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -28365,6 +32151,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -28623,70 +32410,7 @@ "Name": "RigidConstraint", "Tags": [], "Superclass": "Constraint", - "Properties": { - "Broken": { - "Name": "Broken", - "Scriptability": "Read", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "NotBrowsable", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "DestructionEnabled": { - "Name": "DestructionEnabled", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "NotBrowsable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "DestructionForce": { - "Name": "DestructionForce", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "NotBrowsable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "DestructionTorque": { - "Name": "DestructionTorque", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "NotBrowsable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, + "Properties": {}, "DefaultProperties": { "Attributes": { "BinaryString": "" @@ -28694,15 +32418,6 @@ "Color": { "Int32": 194 }, - "DestructionEnabled": { - "Bool": false - }, - "DestructionForce": { - "Float32": null - }, - "DestructionTorque": { - "Float32": null - }, "Enabled": { "Bool": true }, @@ -29573,11 +33288,36 @@ "Properties": {}, "DefaultProperties": {} }, + "SafetyService": { + "Name": "SafetyService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ScreenGui": { "Name": "ScreenGui", "Tags": [], "Superclass": "LayerCollector", "Properties": { + "ClipToDeviceSafeArea": { + "Name": "ClipToDeviceSafeArea", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DisplayOrder": { "Name": "DisplayOrder", "Scriptability": "ReadWrite", @@ -29600,7 +33340,7 @@ "Tags": [], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -29618,6 +33358,36 @@ "Serialization": "DoesNotSerialize" } } + }, + "SafeAreaCompatibility": { + "Name": "SafeAreaCompatibility", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SafeAreaCompatibility" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ScreenInsets": { + "Name": "ScreenInsets", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ScreenInsets" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -29627,18 +33397,24 @@ "AutoLocalize": { "Bool": true }, + "ClipToDeviceSafeArea": { + "Bool": true + }, "DisplayOrder": { "Int32": 0 }, "Enabled": { "Bool": true }, - "IgnoreGuiInset": { - "Bool": false - }, "ResetOnSpawn": { "Bool": true }, + "SafeAreaCompatibility": { + "Enum": 1 + }, + "ScreenInsets": { + "Enum": 2 + }, "SelectionBehaviorDown": { "Enum": 0 }, @@ -29665,6 +33441,121 @@ } } }, + "ScreenshotHud": { + "Name": "ScreenshotHud", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "CameraButtonIcon": { + "Name": "CameraButtonIcon", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraButtonPosition": { + "Name": "CameraButtonPosition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CloseButtonPosition": { + "Name": "CloseButtonPosition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CloseWhenScreenshotTaken": { + "Name": "CloseWhenScreenshotTaken", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ExperienceNameOverlayEnabled": { + "Name": "ExperienceNameOverlayEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OverlayFont": { + "Name": "OverlayFont", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "Font" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UsernameOverlayEnabled": { + "Name": "UsernameOverlayEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Visible": { + "Name": "Visible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "Script": { "Name": "Script", "Tags": [], @@ -29694,6 +33585,9 @@ "LinkedSource": { "Content": "" }, + "RunContext": { + "Enum": 0 + }, "Source": { "String": "" }, @@ -29705,6 +33599,16 @@ } } }, + "ScriptBuilder": { + "Name": "ScriptBuilder", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ScriptChangeService": { "Name": "ScriptChangeService", "Tags": [ @@ -29871,6 +33775,16 @@ "Properties": {}, "DefaultProperties": {} }, + "ScriptRuntime": { + "Name": "ScriptRuntime", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ScriptService": { "Name": "ScriptService", "Tags": [ @@ -30472,6 +34386,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -30640,6 +34557,40 @@ } } }, + "SelectionBoxThickness": { + "Name": "SelectionBoxThickness", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SelectionLineThickness": { + "Name": "SelectionLineThickness", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "SelectionThickness": { "Name": "SelectionThickness", "Scriptability": "Read", @@ -30655,6 +34606,21 @@ "Serialization": "DoesNotSerialize" } } + }, + "ShowBoundingBox": { + "Name": "ShowBoundingBox", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -30687,6 +34653,21 @@ } } }, + "StudioSelectionBox": { + "Name": "StudioSelectionBox", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "SurfaceColor": { "Name": "SurfaceColor", "Scriptability": "ReadWrite", @@ -30748,6 +34729,9 @@ "SourceAssetId": { "Int64": -1 }, + "StudioSelectionBox": { + "Bool": false + }, "SurfaceColor3": { "Color3": [ 0.050980397, @@ -30769,6 +34753,16 @@ } } }, + "SelectionHighlightManager": { + "Name": "SelectionHighlightManager", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "SelectionLasso": { "Name": "SelectionLasso", "Tags": [ @@ -30975,6 +34969,29 @@ } } }, + "SensorBase": { + "Name": "SensorBase", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "UpdateType": { + "Name": "UpdateType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SensorUpdateType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "ServerReplicator": { "Name": "ServerReplicator", "Tags": [ @@ -31057,6 +35074,43 @@ "Properties": {}, "DefaultProperties": {} }, + "ServiceVisibilityService": { + "Name": "ServiceVisibilityService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "VisibleServices": { + "Name": "VisibleServices", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "BinaryString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "VisibleServices": { + "BinaryString": "AAAAAA==" + } + } + }, "SessionService": { "Name": "SessionService", "Tags": [ @@ -31067,6 +35121,17 @@ "Properties": {}, "DefaultProperties": {} }, + "SharedTableRegistry": { + "Name": "SharedTableRegistry", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Shirt": { "Name": "Shirt", "Tags": [], @@ -31162,6 +35227,17 @@ } } }, + "ShorelineUpgraderService": { + "Name": "ShorelineUpgraderService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "SkateboardController": { "Name": "SkateboardController", "Tags": [], @@ -31360,6 +35436,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -32119,6 +36198,17 @@ } } }, + "SmoothVoxelsUpgraderService": { + "Name": "SmoothVoxelsUpgraderService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Snap": { "Name": "Snap", "Tags": [ @@ -32286,6 +36376,7 @@ "Value": "Bool" }, "Tags": [ + "Hidden", "NotReplicated", "ReadOnly" ], @@ -32302,6 +36393,7 @@ "Value": "Bool" }, "Tags": [ + "Hidden", "NotReplicated", "ReadOnly" ], @@ -32311,6 +36403,36 @@ } } }, + "IsSpatial": { + "Name": "IsSpatial", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LoopRegion": { + "Name": "LoopRegion", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Looped": { "Name": "Looped", "Scriptability": "ReadWrite", @@ -32400,6 +36522,34 @@ } } }, + "PlaybackRegion": { + "Name": "PlaybackRegion", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlaybackRegionsEnabled": { + "Name": "PlaybackRegionsEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PlaybackSpeed": { "Name": "PlaybackSpeed", "Scriptability": "ReadWrite", @@ -32430,6 +36580,23 @@ } } }, + "RollOffGain": { + "Name": "RollOffGain", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "RollOffMaxDistance": { "Name": "RollOffMaxDistance", "Scriptability": "ReadWrite", @@ -32597,6 +36764,12 @@ "EmitterSize": { "Float32": 10.0 }, + "LoopRegion": { + "NumberRange": [ + 0.0, + 60000.0 + ] + }, "Looped": { "Bool": false }, @@ -32606,6 +36779,15 @@ "PlayOnRemove": { "Bool": false }, + "PlaybackRegion": { + "NumberRange": [ + 0.0, + 60000.0 + ] + }, + "PlaybackRegionsEnabled": { + "Bool": false + }, "PlaybackSpeed": { "Float32": 1.0 }, @@ -32774,6 +36956,21 @@ "Serialization": "Serializes" } } + }, + "VolumetricAudio": { + "Name": "VolumetricAudio", + "Scriptability": "None", + "DataType": { + "Enum": "VolumetricAudio" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -32800,6 +36997,9 @@ }, "Tags": { "BinaryString": "" + }, + "VolumetricAudio": { + "Enum": 1 } } }, @@ -33032,6 +37232,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -33197,7 +37400,8 @@ "Speaker": { "Name": "Speaker", "Tags": [ - "Deprecated" + "Deprecated", + "NotCreatable" ], "Superclass": "Instance", "Properties": { @@ -34036,6 +38240,21 @@ } } }, + "RtlTextSupport": { + "Name": "RtlTextSupport", + "Scriptability": "None", + "DataType": { + "Enum": "RtlTextSupport" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ScreenOrientation": { "Name": "ScreenOrientation", "Scriptability": "ReadWrite", @@ -34085,6 +38304,9 @@ "ResetPlayerGuiOnSpawn": { "Bool": true }, + "RtlTextSupport": { + "Enum": 0 + }, "ScreenOrientation": { "Enum": 2 }, @@ -34327,6 +38549,21 @@ } } }, + "EnableDynamicHeads": { + "Name": "EnableDynamicHeads", + "Scriptability": "None", + "DataType": { + "Enum": "LoadDynamicHeads" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "EnableMouseLockOption": { "Name": "EnableMouseLockOption", "Scriptability": "ReadWrite", @@ -34625,6 +38862,21 @@ } } }, + "HumanoidStateMachineMode": { + "Name": "HumanoidStateMachineMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "HumanoidStateMachineMode" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "LoadCharacterAppearance": { "Name": "LoadCharacterAppearance", "Scriptability": "ReadWrite", @@ -34730,6 +38982,9 @@ "DevTouchMovementMode": { "Enum": 0 }, + "EnableDynamicHeads": { + "Enum": 0 + }, "EnableMouseLockOption": { "Bool": true }, @@ -34802,6 +39057,9 @@ "HealthDisplayDistance": { "Float32": 100.0 }, + "HumanoidStateMachineMode": { + "Enum": 0 + }, "LoadCharacterAppearance": { "Bool": true }, @@ -35046,17 +39304,6 @@ "Properties": {}, "DefaultProperties": {} }, - "StopWatchReporter": { - "Name": "StopWatchReporter", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, "StringValue": { "Name": "StringValue", "Tags": [], @@ -35266,6 +39513,19 @@ } } }, + "Auto Delete Closing Brackets and Quotes": { + "Name": "Auto Delete Closing Brackets and Quotes", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Auto Indent Rule": { "Name": "Auto Indent Rule", "Scriptability": "ReadWrite", @@ -35305,6 +39565,19 @@ } } }, + "Automatically commit locked scripts when you save or publish to Roblox": { + "Name": "Automatically commit locked scripts when you save or publish to Roblox", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Background Color": { "Name": "Background Color", "Scriptability": "ReadWrite", @@ -35391,6 +39664,19 @@ } } }, + "Camera Pan Speed": { + "Name": "Camera Pan Speed", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Camera Shift Speed": { "Name": "Camera Shift Speed", "Scriptability": "ReadWrite", @@ -35529,6 +39815,19 @@ } } }, + "Display Team Create toggle when creating a new experience": { + "Name": "Display Team Create toggle when creating a new experience", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DisplayLanguage": { "Name": "DisplayLanguage", "Scriptability": "None", @@ -35771,6 +40070,19 @@ } } }, + "File > New creates a place with Team Create off": { + "Name": "File > New creates a place with Team Create off", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Find Selection Background Color": { "Name": "Find Selection Background Color", "Scriptability": "ReadWrite", @@ -35879,6 +40191,19 @@ } } }, + "Hover Line Thickness": { + "Name": "Hover Line Thickness", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Hover Over Color": { "Name": "Hover Over Color", "Scriptability": "ReadWrite", @@ -36454,6 +40779,19 @@ } } }, + "Selection Box Thickness": { + "Name": "Selection Box Thickness", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Selection Color": { "Name": "Selection Color", "Scriptability": "ReadWrite", @@ -36482,6 +40820,19 @@ } } }, + "Selection Line Thickness": { + "Name": "Selection Line Thickness", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Server Audio Behavior": { "Name": "Server Audio Behavior", "Scriptability": "ReadWrite", @@ -36521,19 +40872,6 @@ } } }, - "Show Deployment Warnings": { - "Name": "Show Deployment Warnings", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "Show Diagnostics Bar": { "Name": "Show Diagnostics Bar", "Scriptability": "ReadWrite", @@ -36882,38 +41220,6 @@ "Serialization": "Serializes" } } - }, - "SrcPlaceId": { - "Name": "SrcPlaceId", - "Scriptability": "None", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "SrcUniverseId": { - "Name": "SrcUniverseId", - "Scriptability": "None", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } } }, "DefaultProperties": { @@ -36926,12 +41232,6 @@ "SourceAssetId": { "Int64": -1 }, - "SrcPlaceId": { - "Int64": 0 - }, - "SrcUniverseId": { - "Int64": 0 - }, "Tags": { "BinaryString": "" } @@ -36945,18 +41245,75 @@ "Service" ], "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "StudioHighDpiService": { - "Name": "StudioHighDpiService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, + "Properties": { + "HasMultiTouchStarted": { + "Name": "HasMultiTouchStarted", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsMultiTouchEmulationOn": { + "Name": "IsMultiTouchEmulationOn", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsMultiTouchEnabled": { + "Name": "IsMultiTouchEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PivotPosition": { + "Name": "PivotPosition", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, "DefaultProperties": {} }, "StudioPublishService": { @@ -36981,6 +41338,17 @@ "Properties": {}, "DefaultProperties": {} }, + "StudioSdkService": { + "Name": "StudioSdkService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "StudioService": { "Name": "StudioService", "Tags": [ @@ -37383,34 +41751,8 @@ "SurfaceGui": { "Name": "SurfaceGui", "Tags": [], - "Superclass": "LayerCollector", + "Superclass": "SurfaceGuiBase", "Properties": { - "Active": { - "Name": "Active", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Adornee": { - "Name": "Adornee", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "AlwaysOnTop": { "Name": "AlwaysOnTop", "Scriptability": "ReadWrite", @@ -37463,16 +41805,18 @@ } } }, - "Face": { - "Name": "Face", - "Scriptability": "ReadWrite", + "HorizontalCurvature": { + "Name": "HorizontalCurvature", + "Scriptability": "None", "DataType": { - "Enum": "NormalId" + "Value": "Float32" }, - "Tags": [], + "Tags": [ + "Hidden" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -37502,6 +41846,21 @@ } } }, + "Shape": { + "Name": "Shape", + "Scriptability": "None", + "DataType": { + "Enum": "SurfaceGuiShape" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "SizingMode": { "Name": "SizingMode", "Scriptability": "ReadWrite", @@ -37617,6 +41976,55 @@ } } }, + "SurfaceGuiBase": { + "Name": "SurfaceGuiBase", + "Tags": [ + "NotCreatable" + ], + "Superclass": "LayerCollector", + "Properties": { + "Active": { + "Name": "Active", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Adornee": { + "Name": "Adornee", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Face": { + "Name": "Face", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "NormalId" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "SurfaceLight": { "Name": "SurfaceLight", "Tags": [], @@ -37746,6 +42154,175 @@ } } }, + "SwimController": { + "Name": "SwimController", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "ControllerBase", + "Properties": { + "AccelerationTime": { + "Name": "AccelerationTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PitchMaxTorque": { + "Name": "PitchMaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PitchSpeedFactor": { + "Name": "PitchSpeedFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RollMaxTorque": { + "Name": "RollMaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RollSpeedFactor": { + "Name": "RollSpeedFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AccelerationTime": { + "Float32": 0.0 + }, + "Attributes": { + "BinaryString": "" + }, + "MoveSpeedFactor": { + "Float32": 1.0 + }, + "PitchMaxTorque": { + "Float32": 10000.0 + }, + "PitchSpeedFactor": { + "Float32": 1.0 + }, + "RigidityEnabled": { + "Bool": false + }, + "RollMaxTorque": { + "Float32": 10000.0 + }, + "RollSpeedFactor": { + "Float32": 1.0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + } + } + }, + "SyncScriptBuilder": { + "Name": "SyncScriptBuilder", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "ScriptBuilder", + "Properties": { + "CoverageInfo": { + "Name": "CoverageInfo", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DebugInfo": { + "Name": "DebugInfo", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PackAsSource": { + "Name": "PackAsSource", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RawBytecode": { + "Name": "RawBytecode", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "TaskScheduler": { "Name": "TaskScheduler", "Tags": [ @@ -37915,6 +42492,37 @@ } } }, + "TeamCreateData": { + "Name": "TeamCreateData", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "TeamCreatePublishService": { + "Name": "TeamCreatePublishService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "TeamCreateService": { + "Name": "TeamCreateService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Teams": { "Name": "Teams", "Tags": [ @@ -38188,6 +42796,36 @@ } } }, + "ShorelinesUpgraded": { + "Name": "ShorelinesUpgraded", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SmoothVoxelsUpgraded": { + "Name": "SmoothVoxelsUpgraded", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "WaterColor": { "Name": "WaterColor", "Scriptability": "ReadWrite", @@ -38323,6 +42961,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -38426,6 +43067,9 @@ 0.0 ] }, + "ShorelinesUpgraded": { + "Bool": false + }, "Size": { "Vector3": [ 2044.0, @@ -38433,6 +43077,9 @@ 2044.0 ] }, + "SmoothVoxelsUpgraded": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -38484,9 +43131,7 @@ }, "TerrainDetail": { "Name": "TerrainDetail", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "Instance", "Properties": { "ColorMap": { @@ -38924,11 +43569,11 @@ } } }, - "EnableRealtimeFilteringHints": { - "Name": "EnableRealtimeFilteringHints", - "Scriptability": "None", + "Font": { + "Name": "Font", + "Scriptability": "ReadWrite", "DataType": { - "Value": "Bool" + "Enum": "Font" }, "Tags": [ "Hidden", @@ -38940,11 +43585,11 @@ } } }, - "Font": { - "Name": "Font", + "FontFace": { + "Name": "FontFace", "Scriptability": "ReadWrite", "DataType": { - "Enum": "Font" + "Value": "Font" }, "Tags": [], "Kind": { @@ -39410,8 +44055,13 @@ "Draggable": { "Bool": false }, - "Font": { - "Enum": 0 + "FontFace": { + "Font": { + "family": "rbxasset://fonts/families/LegacyArial.json", + "weight": "Regular", + "style": "Normal", + "cachedFaceId": "rbxasset://fonts/arial.ttf" + } }, "LayoutOrder": { "Int32": 0 @@ -39587,6 +44237,22 @@ "DataType": { "Enum": "Font" }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FontFace": { + "Name": "FontFace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Font" + }, "Tags": [], "Kind": { "Canonical": { @@ -39926,8 +44592,13 @@ "Draggable": { "Bool": false }, - "Font": { - "Enum": 0 + "FontFace": { + "Font": { + "family": "rbxasset://fonts/families/LegacyArial.json", + "weight": "Regular", + "style": "Normal", + "cachedFaceId": "rbxasset://fonts/arial.ttf" + } }, "LayoutOrder": { "Int32": 0 @@ -40058,9 +44729,7 @@ }, "TextChannel": { "Name": "TextChannel", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "Instance", "Properties": {}, "DefaultProperties": { @@ -40077,9 +44746,7 @@ }, "TextChatCommand": { "Name": "TextChatCommand", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "Instance", "Properties": { "Enabled": { @@ -40301,7 +44968,6 @@ "TextChatService": { "Name": "TextChatService", "Tags": [ - "NotBrowsable", "NotCreatable", "Service" ], @@ -40405,6 +45071,22 @@ "DataType": { "Enum": "Font" }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FontFace": { + "Name": "FontFace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Font" + }, "Tags": [], "Kind": { "Canonical": { @@ -40741,8 +45423,13 @@ "Draggable": { "Bool": false }, - "Font": { - "Enum": 0 + "FontFace": { + "Font": { + "family": "rbxasset://fonts/families/LegacyArial.json", + "weight": "Regular", + "style": "Normal", + "cachedFaceId": "rbxasset://fonts/arial.ttf" + } }, "LayoutOrder": { "Int32": 0 @@ -40876,7 +45563,6 @@ "TextSource": { "Name": "TextSource", "Tags": [ - "NotBrowsable", "NotCreatable" ], "Superclass": "Instance", @@ -41014,6 +45700,45 @@ } } }, + "TextureGuiExperimental": { + "Name": "TextureGuiExperimental", + "Tags": [ + "NotCreatable" + ], + "Superclass": "LayerCollector", + "Properties": { + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TemporaryId": { + "Name": "TemporaryId", + "Scriptability": "Read", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "ThirdPartyUserService": { "Name": "ThirdPartyUserService", "Tags": [ @@ -41186,6 +45911,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -41201,6 +45927,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -41216,6 +45943,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -41231,6 +45959,7 @@ "Value": "Vector3" }, "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -41315,12 +46044,21 @@ ] } }, + "LevelOfDetail": { + "Enum": 0 + }, "ManualActivationOnly": { "Bool": false }, + "ModelStreamingMode": { + "Enum": 0 + }, "RequiresHandle": { "Bool": true }, + "Scale": { + "Float32": 1.0 + }, "SourceAssetId": { "Int64": -1 }, @@ -41335,17 +46073,6 @@ } } }, - "ToolboxService": { - "Name": "ToolboxService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, "Torque": { "Name": "Torque", "Tags": [], @@ -41649,6 +46376,69 @@ "Properties": {}, "DefaultProperties": {} }, + "TrackerLodController": { + "Name": "TrackerLodController", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "AudioMode": { + "Name": "AudioMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TrackerLodFlagMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VideoExtrapolationMode": { + "Name": "VideoExtrapolationMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TrackerExtrapolationFlagMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VideoLodMode": { + "Name": "VideoLodMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TrackerLodValueMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VideoMode": { + "Name": "VideoMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TrackerLodFlagMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "TrackerStreamAnimation": { "Name": "TrackerStreamAnimation", "Tags": [ @@ -42091,6 +46881,22 @@ "Serialization": "DoesNotSerialize" } } + }, + "MeshSize": { + "Name": "MeshSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": {} @@ -42185,6 +46991,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -43680,6 +48489,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -44288,6 +49100,22 @@ } } }, + "PlayerHeight": { + "Name": "PlayerHeight", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "RCCProfilerRecordFrameRate": { "Name": "RCCProfilerRecordFrameRate", "Scriptability": "ReadWrite", @@ -44466,6 +49294,22 @@ } } }, + "VRPlayMode": { + "Name": "VRPlayMode", + "Scriptability": "Read", + "DataType": { + "Enum": "VRPlayMode" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "VRRotationIntensity": { "Name": "VRRotationIntensity", "Scriptability": "None", @@ -44479,6 +49323,35 @@ } } }, + "VRSafetyBubbleMode": { + "Name": "VRSafetyBubbleMode", + "Scriptability": "None", + "DataType": { + "Enum": "VRSafetyBubbleMode" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VRSmoothRotationEnabled": { + "Name": "VRSmoothRotationEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "VignetteEnabled": { "Name": "VignetteEnabled", "Scriptability": "Read", @@ -44553,22 +49426,6 @@ } } }, - "GazeSelectionEnabled": { - "Name": "GazeSelectionEnabled", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "GyroscopeEnabled": { "Name": "GyroscopeEnabled", "Scriptability": "Read", @@ -44675,6 +49532,19 @@ } } }, + "MouseIcon": { + "Name": "MouseIcon", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MouseIconEnabled": { "Name": "MouseIconEnabled", "Scriptability": "ReadWrite", @@ -44909,6 +49779,21 @@ ], "Superclass": "Instance", "Properties": { + "AutomaticScaling": { + "Name": "AutomaticScaling", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "VRScaling" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "DidPointerHit": { "Name": "DidPointerHit", "Scriptability": "None", @@ -44926,6 +49811,19 @@ } } }, + "FadeOutViewOnCollision": { + "Name": "FadeOutViewOnCollision", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "GuiInputUserCFrame": { "Name": "GuiInputUserCFrame", "Scriptability": "ReadWrite", @@ -44939,6 +49837,23 @@ } } }, + "LaserDistance": { + "Name": "LaserDistance", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PointerHitCFrame": { "Name": "PointerHitCFrame", "Scriptability": "None", @@ -45005,6 +49920,23 @@ "Serialization": "DoesNotSerialize" } } + }, + "VRSessionState": { + "Name": "VRSessionState", + "Scriptability": "None", + "DataType": { + "Enum": "VRSessionState" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -45403,6 +50335,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -46090,6 +51025,22 @@ } } }, + "IsMirrored": { + "Name": "IsMirrored", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "LightColor": { "Name": "LightColor", "Scriptability": "ReadWrite", @@ -46311,6 +51262,16 @@ "Properties": {}, "DefaultProperties": {} }, + "VisibilityCheckDispatcher": { + "Name": "VisibilityCheckDispatcher", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "VisibilityService": { "Name": "VisibilityService", "Tags": [ @@ -46332,23 +51293,6 @@ "Properties": {}, "DefaultProperties": {} }, - "VoiceChannel": { - "Name": "VoiceChannel", - "Tags": [], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, "VoiceChatInternal": { "Name": "VoiceChatInternal", "Tags": [ @@ -46567,6 +51511,9 @@ "CastShadow": { "Bool": true }, + "CollisionGroup": { + "String": "Default" + }, "CollisionGroupId": { "Int32": 0 }, @@ -46885,6 +51832,99 @@ } } }, + "WireframeHandleAdornment": { + "Name": "WireframeHandleAdornment", + "Tags": [], + "Superclass": "HandleAdornment", + "Properties": { + "Scale": { + "Name": "Scale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AdornCullingMode": { + "Enum": 0 + }, + "AlwaysOnTop": { + "Bool": false + }, + "Attributes": { + "BinaryString": "" + }, + "CFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Color3": { + "Color3": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "Scale": { + "Vector3": [ + 1.0, + 1.0, + 1.0 + ] + }, + "SizeRelativeOffset": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "BinaryString": "" + }, + "Transparency": { + "Float32": 0.0 + }, + "Visible": { + "Bool": true + }, + "ZIndex": { + "Int32": -1 + } + } + }, "Workspace": { "Name": "Workspace", "Tags": [ @@ -46908,11 +51948,11 @@ } } }, - "AnimationWeightedBlendFix": { - "Name": "AnimationWeightedBlendFix", + "AvatarUnificationMode": { + "Name": "AvatarUnificationMode", "Scriptability": "None", "DataType": { - "Enum": "NewAnimationRuntimeSetting" + "Enum": "AvatarUnificationMode" }, "Tags": [ "NotScriptable" @@ -47091,11 +52131,11 @@ } } }, - "PhysicsInertiaAndVolumeFix": { - "Name": "PhysicsInertiaAndVolumeFix", + "PhysicsSteppingMethod": { + "Name": "PhysicsSteppingMethod", "Scriptability": "None", "DataType": { - "Enum": "PhysicsInertiaAndVolumeFix" + "Enum": "PhysicsSteppingMethod" }, "Tags": [ "NotScriptable" @@ -47106,27 +52146,11 @@ } } }, - "PhysicsSimulationRate": { - "Name": "PhysicsSimulationRate", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "PhysicsSimulationRate" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "PhysicsSteppingMethod": { - "Name": "PhysicsSteppingMethod", + "RejectCharacterDeletions": { + "Name": "RejectCharacterDeletions", "Scriptability": "None", "DataType": { - "Enum": "PhysicsSteppingMethod" + "Enum": "RejectCharacterDeletions" }, "Tags": [ "NotScriptable" @@ -47176,7 +52200,7 @@ ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -47208,11 +52232,11 @@ } } }, - "StreamingMinRadius": { - "Name": "StreamingMinRadius", + "StreamingIntegrityMode": { + "Name": "StreamingIntegrityMode", "Scriptability": "None", "DataType": { - "Value": "Int32" + "Enum": "StreamingIntegrityMode" }, "Tags": [ "NotScriptable" @@ -47223,11 +52247,11 @@ } } }, - "StreamingPauseMode": { - "Name": "StreamingPauseMode", + "StreamingMinRadius": { + "Name": "StreamingMinRadius", "Scriptability": "None", "DataType": { - "Enum": "StreamingPauseMode" + "Value": "Int32" }, "Tags": [ "NotScriptable" @@ -47289,17 +52313,14 @@ "AllowThirdPartySales": { "Bool": false }, - "AnimationWeightedBlendFix": { - "Enum": 0 - }, "Attributes": { "BinaryString": "" }, - "ClientAnimatorThrottling": { + "AvatarUnificationMode": { "Enum": 0 }, - "CollisionGroups": { - "String": "Default^0^-1" + "ClientAnimatorThrottling": { + "Enum": 0 }, "DistributedGameTime": { "Float64": 0.0 @@ -47332,20 +52353,23 @@ "MeshPartHeadsAndAccessories": { "Enum": 0 }, - "PhysicsInertiaAndVolumeFix": { + "ModelStreamingMode": { "Enum": 0 }, "PhysicsSteppingMethod": { "Enum": 0 }, + "RejectCharacterDeletions": { + "Enum": 0 + }, "ReplicateInstanceDestroySetting": { "Enum": 0 }, "Retargeting": { "Enum": 0 }, - "SignalBehavior": { - "Enum": 0 + "Scale": { + "Float32": 1.0 }, "SourceAssetId": { "Int64": -1 @@ -47356,12 +52380,12 @@ "StreamingEnabled": { "Bool": false }, + "StreamingIntegrityMode": { + "Enum": 0 + }, "StreamingMinRadius": { "Int32": 64 }, - "StreamingPauseMode": { - "Enum": 0 - }, "StreamingTargetRadius": { "Int32": 1024 }, @@ -47813,17 +52837,6 @@ } }, "Enums": { - "ABTestLoadingStatus": { - "name": "ABTestLoadingStatus", - "items": { - "Error": 3, - "Initialized": 2, - "None": 0, - "Pending": 1, - "ShutOff": 5, - "TimedOut": 4 - } - }, "AccessoryType": { "name": "AccessoryType", "items": { @@ -47875,6 +52888,44 @@ "Servo": 2 } }, + "AdPortalStatus": { + "name": "AdPortalStatus", + "items": { + "Active": 2, + "Inactive": 1, + "Invalid": 0 + } + }, + "AdPortalType": { + "name": "AdPortalType", + "items": { + "Forward": 0, + "Return": 1 + } + }, + "AdShape": { + "name": "AdShape", + "items": { + "HorizontalRectangle": 1 + } + }, + "AdTeleportMethod": { + "name": "AdTeleportMethod", + "items": { + "InGameMenuBackButton": 3, + "PortalForward": 1, + "PortalReturn": 2, + "UIBackButton": 4, + "Undefined": 0 + } + }, + "AdUnitStatus": { + "name": "AdUnitStatus", + "items": { + "Active": 1, + "Inactive": 0 + } + }, "AdornCullingMode": { "name": "AdornCullingMode", "items": { @@ -48001,7 +53052,10 @@ "name": "AssetFetchStatus", "items": { "Failure": 1, - "Success": 0 + "Loading": 3, + "None": 2, + "Success": 0, + "TimedOut": 4 } }, "AssetType": { @@ -48015,6 +53069,7 @@ "DeathAnimation": 49, "Decal": 13, "DressSkirtAccessory": 72, + "DynamicHead": 79, "EarAccessory": 57, "EmoteAnimation": 61, "EyeAccessory": 58, @@ -48023,6 +53078,7 @@ "Face": 18, "FaceAccessory": 42, "FallAnimation": 50, + "FontFamily": 73, "FrontAccessory": 45, "GamePass": 34, "Gear": 19, @@ -48040,6 +53096,7 @@ "Mesh": 4, "MeshPart": 40, "Model": 10, + "MoodAnimation": 78, "NeckAccessory": 43, "Package": 32, "Pants": 12, @@ -48073,6 +53130,13 @@ "Default": 1 } }, + "AudioSubType": { + "name": "AudioSubType", + "items": { + "Music": 1, + "SoundEffect": 2 + } + }, "AutoIndentRule": { "name": "AutoIndentRule", "items": { @@ -48096,6 +53160,7 @@ "BackAccessory": 46, "ClimbAnimation": 48, "DressSkirtAccessory": 72, + "DynamicHead": 79, "EmoteAnimation": 61, "EyebrowAccessory": 76, "EyelashAccessory": 77, @@ -48113,6 +53178,7 @@ "LeftArm": 29, "LeftLeg": 30, "LeftShoeAccessory": 70, + "MoodAnimation": 78, "NeckAccessory": 43, "Pants": 12, "PantsAccessory": 66, @@ -48157,6 +53223,21 @@ "Success": 1 } }, + "AvatarThumbnailCustomizationType": { + "name": "AvatarThumbnailCustomizationType", + "items": { + "Closeup": 1, + "FullBody": 2 + } + }, + "AvatarUnificationMode": { + "name": "AvatarUnificationMode", + "items": { + "Default": 0, + "Disabled": 1, + "Enabled": 2 + } + }, "Axis": { "name": "Axis", "items": { @@ -48245,6 +53326,8 @@ "items": { "Animations": 2, "BodyParts": 1, + "DynamicHead": 4, + "DynamicHeadAvatar": 5, "Shoes": 3 } }, @@ -48311,13 +53394,25 @@ "Recommended": 6 } }, + "CatalogSortAggregation": { + "name": "CatalogSortAggregation", + "items": { + "AllTime": 6, + "Past12Hours": 1, + "Past3Days": 3, + "PastDay": 2, + "PastMonth": 5, + "PastWeek": 4 + } + }, "CatalogSortType": { "name": "CatalogSortType", "items": { + "Bestselling": 7, "MostFavorited": 5, "PriceHighToLow": 2, "PriceLowToHigh": 3, - "RecentlyUpdated": 4, + "RecentlyCreated": 6, "Relevance": 1 } }, @@ -48433,6 +53528,7 @@ "items": { "Box": 2, "Default": 0, + "DynamicPreciseConvexDecomposition": 4, "Hull": 1, "PreciseConvexDecomposition": 3 } @@ -48444,6 +53540,58 @@ "Plugin": 0 } }, + "CompletionItemKind": { + "name": "CompletionItemKind", + "items": { + "Class": 7, + "Color": 16, + "Constant": 21, + "Constructor": 4, + "Enum": 13, + "EnumMember": 20, + "Event": 23, + "Field": 5, + "File": 17, + "Folder": 19, + "Function": 3, + "Interface": 8, + "Keyword": 14, + "Method": 2, + "Module": 9, + "Operator": 24, + "Property": 10, + "Reference": 18, + "Snippet": 15, + "Struct": 22, + "Text": 1, + "TypeParameter": 25, + "Unit": 11, + "Value": 12, + "Variable": 6 + } + }, + "CompletionItemTag": { + "name": "CompletionItemTag", + "items": { + "AddParens": 6, + "ClientServerBoundaryViolation": 9, + "CommandLinePermissions": 4, + "Deprecated": 1, + "IncorrectIndexType": 2, + "PluginPermissions": 3, + "PutCursorInParens": 7, + "RobloxPermissions": 5, + "TypeCorrect": 8 + } + }, + "CompletionTriggerKind": { + "name": "CompletionTriggerKind", + "items": { + "Invoked": 1, + "TriggerCharacter": 2, + "TriggerForIncompleteCompletions": 3 + } + }, "ComputerCameraMovementMode": { "name": "ComputerCameraMovementMode", "items": { @@ -48484,8 +53632,7 @@ "DisconnectModeratedGame": 287, "DisconnectNewSecurityKeyMismatch": 272, "DisconnectOnRemoteSysStats": 268, - "DisconnectOutOfMemory": 286, - "DisconnectOutOfMemoryExitContinue": 288, + "DisconnectOutOfMemoryKeepPlayingLeave": 292, "DisconnectPlayerless": 271, "DisconnectProtocolMismatch": 259, "DisconnectRaknetErrors": 279, @@ -48493,6 +53640,7 @@ "DisconnectReceivePacketStreamError": 261, "DisconnectRejoin": 276, "DisconnectRobloxMaintenance": 275, + "DisconnectRomarkEndOfTest": 293, "DisconnectSecurityKeyMismatch": 258, "DisconnectSendPacketError": 262, "DisconnectTimeout": 266, @@ -48513,6 +53661,9 @@ "PlacelaunchRestricted": 523, "PlacelaunchUnauthorized": 524, "PlacelaunchUserLeft": 522, + "PlacelaunchUserPrivacyUnauthorized": 533, + "PlayerRemoved": 291, + "ReplicatorTimeout": 290, "TeleportErrors": 768, "TeleportFailure": 769, "TeleportFlooded": 774, @@ -48520,7 +53671,8 @@ "TeleportGameFull": 772, "TeleportGameNotFound": 770, "TeleportIsTeleporting": 775, - "TeleportUnauthorized": 773 + "TeleportUnauthorized": 773, + "Unknown": 1 } }, "ConnectionState": { @@ -48533,7 +53685,6 @@ "ContextActionPriority": { "name": "ContextActionPriority", "items": { - "Default": 2000, "High": 3000, "Low": 1000, "Medium": 2000 @@ -48561,7 +53712,8 @@ "Chat": 3, "EmotesMenu": 5, "Health": 1, - "PlayerList": 0 + "PlayerList": 0, + "SelfView": 6 } }, "CreateOutfitFailure": { @@ -48579,6 +53731,14 @@ "User": 0 } }, + "CreatorTypeFilter": { + "name": "CreatorTypeFilter", + "items": { + "All": 2, + "Group": 1, + "User": 0 + } + }, "CurrencyType": { "name": "CurrencyType", "items": { @@ -48622,9 +53782,9 @@ "DebuggerExceptionBreakMode": { "name": "DebuggerExceptionBreakMode", "items": { - "Always": 2, + "Always": 1, "Never": 0, - "Unhandled": 1 + "Unhandled": 2 } }, "DebuggerFrameType": { @@ -48840,6 +54000,13 @@ "Skip8": 5 } }, + "ExperienceAuthScope": { + "name": "ExperienceAuthScope", + "items": { + "CreatorAssetsCreate": 1, + "DefaultScope": 0 + } + }, "ExplosionType": { "name": "ExplosionType", "items": { @@ -48847,6 +54014,25 @@ "NoCraters": 0 } }, + "FacialAnimationFlags": { + "name": "FacialAnimationFlags", + "items": { + "None": 0, + "Place": 1, + "PlaceServer": 3, + "Server": 2 + } + }, + "FacialAnimationStreamingState": { + "name": "FacialAnimationStreamingState", + "items": { + "Audio": 1, + "None": 0, + "Place": 4, + "Server": 8, + "Video": 2 + } + }, "FieldOfViewMode": { "name": "FieldOfViewMode", "items": { @@ -49072,11 +54258,20 @@ "Automatic": 1, "Direct3D11": 2, "Metal": 5, - "NoGraphics": 7, + "NoGraphics": 9, "OpenGL": 4, "Vulkan": 6 } }, + "GuiType": { + "name": "GuiType", + "items": { + "Core": 0, + "Custom": 1, + "CustomBillboards": 3, + "PlayerNameplates": 2 + } + }, "HandlesStyle": { "name": "HandlesStyle", "items": { @@ -49197,6 +54392,15 @@ "R6": 0 } }, + "HumanoidStateMachineMode": { + "name": "HumanoidStateMachineMode", + "items": { + "Default": 0, + "Legacy": 1, + "LuaStateMachine": 3, + "NoStateMachine": 2 + } + }, "HumanoidStateType": { "name": "HumanoidStateType", "items": { @@ -49227,17 +54431,25 @@ "OtherMechanismsAnchored": 1 } }, + "IKControlType": { + "name": "IKControlType", + "items": { + "LookAt": 3, + "Position": 1, + "Rotation": 2, + "Transform": 0 + } + }, "IXPLoadingStatus": { "name": "IXPLoadingStatus", "items": { - "ErrorConnection": 5, - "ErrorInvalidUser": 4, - "ErrorJsonParse": 6, - "ErrorTimedOut": 7, + "ErrorConnection": 4, + "ErrorInvalidUser": 3, + "ErrorJsonParse": 5, + "ErrorTimedOut": 6, "Initialized": 2, "None": 0, - "Pending": 1, - "ShutOff": 3 + "Pending": 1 } }, "InOut": { @@ -49566,38 +54778,6 @@ "Include": 0 } }, - "LSPMethodType": { - "name": "LSPMethodType", - "items": { - "CancelRequest": 3, - "Completion": 15, - "Declaration": 16, - "DocumentSymbols": 17, - "Initialize": 1, - "Initialized": 2, - "Roblox_findColor3": 27, - "Roblox_findExecutablePosition": 26, - "Roblox_patchSnippetData": 28, - "Roblox_registerSyntaxCategories": 22, - "Roblox_signalQuiescence": 23, - "Roblox_suggestExtraSelections": 25, - "Roblox_syntaxHighlight": 24, - "ShutdownRequest": 14, - "TextDocument_didChange": 5, - "TextDocument_didClose": 6, - "TextDocument_didOpen": 4, - "TextDocument_foldingRange": 7, - "TextDocument_formatting": 9, - "TextDocument_hover": 11, - "TextDocument_onTypeFormatting": 8, - "TextDocument_publishDiagnostics": 19, - "TextDocument_rangeFormatting": 10, - "TextDocument_signatureHelp": 12, - "Window_showMessage": 20, - "Window_showMessageRequest": 21, - "Workspace_DidChangeConfiguration": 13 - } - }, "Language": { "name": "Language", "items": { @@ -49612,14 +54792,6 @@ "Right": 2 } }, - "LevelOfDetailSetting": { - "name": "LevelOfDetailSetting", - "items": { - "High": 2, - "Low": 0, - "Medium": 1 - } - }, "Limb": { "name": "Limb", "items": { @@ -49664,6 +54836,21 @@ "Enabled": 2 } }, + "LoadDynamicHeads": { + "name": "LoadDynamicHeads", + "items": { + "Default": 0, + "Disabled": 1, + "Enabled": 2 + } + }, + "MarkupKind": { + "name": "MarkupKind", + "items": { + "Markdown": 1, + "PlainText": 0 + } + }, "Material": { "name": "Material", "items": { @@ -49727,10 +54914,11 @@ "name": "MeshPartDetailLevel", "items": { "DistanceBased": 0, - "Level01": 1, - "Level02": 2, - "Level03": 3, - "Level04": 4 + "Level00": 1, + "Level01": 2, + "Level02": 3, + "Level03": 4, + "Level04": 5 } }, "MeshPartHeadsAndAccessories": { @@ -49786,6 +54974,16 @@ "StreamingMesh": 1 } }, + "ModelStreamingMode": { + "name": "ModelStreamingMode", + "items": { + "Atomic": 1, + "Default": 0, + "Nonatomic": 4, + "Persistent": 2, + "PersistentPerPlayer": 3 + } + }, "ModifierKey": { "name": "ModifierKey", "items": { @@ -49813,6 +55011,13 @@ "Stopping": 3 } }, + "MuteState": { + "name": "MuteState", + "items": { + "Muted": 1, + "Unmuted": 0 + } + }, "NameOcclusion": { "name": "NameOcclusion", "items": { @@ -49829,14 +55034,6 @@ "OnContact": 2 } }, - "NewAnimationRuntimeSetting": { - "name": "NewAnimationRuntimeSetting", - "items": { - "Default": 0, - "Disabled": 1, - "Enabled": 2 - } - }, "NormalId": { "name": "NormalId", "items": { @@ -49863,6 +55060,14 @@ "Purchased": 3 } }, + "OutfitType": { + "name": "OutfitType", + "items": { + "All": 1, + "Avatar": 2, + "DynamicHead": 3 + } + }, "OutputLayoutMode": { "name": "OutputLayoutMode", "items": { @@ -49924,10 +55129,10 @@ "ParticleFlipbookLayout": { "name": "ParticleFlipbookLayout", "items": { - "EightByEight": 3, - "FourByFour": 2, - "None": 0, - "TwoByTwo": 1 + "Grid2x2": 1, + "Grid4x4": 2, + "Grid8x8": 3, + "None": 0 } }, "ParticleFlipbookMode": { @@ -49939,6 +55144,14 @@ "Random": 3 } }, + "ParticleFlipbookTextureCompatible": { + "name": "ParticleFlipbookTextureCompatible", + "items": { + "Compatible": 1, + "NotCompatible": 0, + "Unknown": 2 + } + }, "ParticleOrientation": { "name": "ParticleOrientation", "items": { @@ -49977,14 +55190,6 @@ "Studio": 3 } }, - "PhysicsInertiaAndVolumeFix": { - "name": "PhysicsInertiaAndVolumeFix", - "items": { - "Default": 0, - "Disabled": 1, - "Enabled": 2 - } - }, "PhysicsSimulationRate": { "name": "PhysicsSimulationRate", "items": { @@ -50012,7 +55217,7 @@ "IOS": 2, "Linux": 13, "NX": 9, - "None": 19, + "None": 20, "OSX": 1, "Ouya": 10, "PS3": 6, @@ -50105,6 +55310,16 @@ "PurchaseGranted": 1 } }, + "PromptPublishAssetResult": { + "name": "PromptPublishAssetResult", + "items": { + "NoUserInput": 5, + "PermissionDenied": 2, + "Success": 1, + "Timeout": 3, + "UploadFailed": 4 + } + }, "PropertyStatus": { "name": "PropertyStatus", "items": { @@ -50173,8 +55388,16 @@ "RaycastFilterType": { "name": "RaycastFilterType", "items": { - "Blacklist": 0, - "Whitelist": 1 + "Exclude": 0, + "Include": 1 + } + }, + "RejectCharacterDeletions": { + "name": "RejectCharacterDeletions", + "items": { + "Default": 0, + "Disabled": 1, + "Enabled": 2 } }, "RenderFidelity": { @@ -50217,6 +55440,15 @@ "Pixelated": 1 } }, + "ReservedHighlightId": { + "name": "ReservedHighlightId", + "items": { + "Active": 131072, + "Hover": 262144, + "Selection": 524288, + "Standard": 0 + } + }, "ReturnKeyType": { "name": "ReturnKeyType", "items": { @@ -50272,6 +55504,14 @@ "Ungroup": 8 } }, + "RigScale": { + "name": "RigScale", + "items": { + "Default": 0, + "Rthro": 1, + "RthroNarrow": 2 + } + }, "RigType": { "name": "RigType", "items": { @@ -50309,6 +55549,23 @@ "MovementRelative": 0 } }, + "RtlTextSupport": { + "name": "RtlTextSupport", + "items": { + "Default": 0, + "Disabled": 1, + "Enabled": 2 + } + }, + "RunContext": { + "name": "RunContext", + "items": { + "Client": 2, + "Legacy": 0, + "Plugin": 3, + "Server": 1 + } + }, "RuntimeUndoBehavior": { "name": "RuntimeUndoBehavior", "items": { @@ -50317,6 +55574,31 @@ "Snapshot": 1 } }, + "SafeAreaCompatibility": { + "name": "SafeAreaCompatibility", + "items": { + "FullscreenExtension": 1, + "None": 0 + } + }, + "SalesTypeFilter": { + "name": "SalesTypeFilter", + "items": { + "All": 1, + "Collectibles": 2, + "Premium": 3 + } + }, + "SaveAvatarThumbnailCustomizationFailure": { + "name": "SaveAvatarThumbnailCustomizationFailure", + "items": { + "BadDistanceScale": 4, + "BadFieldOfViewDeg": 3, + "BadThumbnailType": 1, + "BadYRotDeg": 2, + "Other": 5 + } + }, "SaveFilter": { "name": "SaveFilter", "items": { @@ -50351,6 +55633,27 @@ "Tile": 2 } }, + "ScopeCheckResult": { + "name": "ScopeCheckResult", + "items": { + "BackendError": 4, + "ConsentAccepted": 0, + "ConsentDenied": 7, + "InvalidArgument": 6, + "InvalidScopes": 1, + "NoUserInput": 3, + "Timeout": 2, + "UnexpectedError": 5 + } + }, + "ScreenInsets": { + "name": "ScreenInsets", + "items": { + "CoreUISafeInsets": 2, + "DeviceSafeInsets": 1, + "None": 0 + } + }, "ScreenOrientation": { "name": "ScreenOrientation", "items": { @@ -50384,6 +55687,20 @@ "Stop": 1 } }, + "SensorMode": { + "name": "SensorMode", + "items": { + "Floor": 0, + "Ladder": 1 + } + }, + "SensorUpdateType": { + "name": "SensorUpdateType", + "items": { + "Manual": 1, + "OnRead": 0 + } + }, "ServerAudioBehavior": { "name": "ServerAudioBehavior", "items": { @@ -50392,6 +55709,21 @@ "OnlineGame": 2 } }, + "ServiceVisibility": { + "name": "ServiceVisibility", + "items": { + "Always": 0, + "Off": 1, + "WithChildren": 2 + } + }, + "Severity": { + "name": "Severity", + "items": { + "Error": 1, + "Warning": 2 + } + }, "SignalBehavior": { "name": "SignalBehavior", "items": { @@ -50409,6 +55741,14 @@ "RelativeYY": 2 } }, + "SolverConvergenceVisualizationMode": { + "name": "SolverConvergenceVisualizationMode", + "items": { + "Disabled": 0, + "PerEdge": 2, + "PerIsland": 1 + } + }, "SortDirection": { "name": "SortDirection", "items": { @@ -50459,6 +55799,15 @@ "Opportunistic": 2 } }, + "StreamingIntegrityMode": { + "name": "StreamingIntegrityMode", + "items": { + "Default": 0, + "Disabled": 1, + "MinimumRadiusPause": 2, + "PauseOutsideLoadedArea": 3 + } + }, "StreamingPauseMode": { "name": "StreamingPauseMode", "items": { @@ -50688,6 +56037,13 @@ "SteppingMotor": 2 } }, + "SurfaceGuiShape": { + "name": "SurfaceGuiShape", + "items": { + "CurvedHorizontally": 1, + "Flat": 0 + } + }, "SurfaceGuiSizingMode": { "name": "SurfaceGuiSizingMode", "items": { @@ -50957,6 +56313,61 @@ "Thumbstick": 1 } }, + "TrackerError": { + "name": "TrackerError", + "items": { + "AudioError": 8, + "AudioNoPermission": 9, + "InitFailed": 2, + "NoAudio": 7, + "NoService": 1, + "NoVideo": 3, + "Ok": 0, + "VideoError": 4, + "VideoNoPermission": 5, + "VideoUnsupported": 6 + } + }, + "TrackerExtrapolationFlagMode": { + "name": "TrackerExtrapolationFlagMode", + "items": { + "Auto": 3, + "ExtrapolateFacsAndPose": 1, + "ExtrapolateFacsOnly": 2, + "ForceDisabled": 0 + } + }, + "TrackerLodFlagMode": { + "name": "TrackerLodFlagMode", + "items": { + "Auto": 2, + "ForceFalse": 0, + "ForceTrue": 1 + } + }, + "TrackerLodValueMode": { + "name": "TrackerLodValueMode", + "items": { + "Auto": 2, + "Force0": 0, + "Force1": 1 + } + }, + "TrackerMode": { + "name": "TrackerMode", + "items": { + "Audio": 1, + "AudioVideo": 3, + "None": 0, + "Video": 2 + } + }, + "TrackerPromptEvent": { + "name": "TrackerPromptEvent", + "items": { + "LODCameraRecommendDisable": 0 + } + }, "TriStateBoolean": { "name": "TriStateBoolean", "items": { @@ -50996,6 +56407,7 @@ "UserCFrame": { "name": "UserCFrame", "items": { + "Floor": 3, "Head": 0, "LeftHand": 1, "RightHand": 2 @@ -51037,6 +56449,38 @@ "Touch": 7 } }, + "VRPlayMode": { + "name": "VRPlayMode", + "items": { + "Seated": 0, + "Standing": 1 + } + }, + "VRSafetyBubbleMode": { + "name": "VRSafetyBubbleMode", + "items": { + "Anyone": 2, + "NoOne": 0, + "OnlyFriends": 1 + } + }, + "VRScaling": { + "name": "VRScaling", + "items": { + "Off": 1, + "World": 0 + } + }, + "VRSessionState": { + "name": "VRSessionState", + "items": { + "Focused": 3, + "Idle": 1, + "Stopping": 4, + "Undefined": 0, + "Visible": 2 + } + }, "VRTouchpad": { "name": "VRTouchpad", "items": { @@ -51114,6 +56558,14 @@ "Leaving": 4 } }, + "VolumetricAudio": { + "name": "VolumetricAudio", + "items": { + "Automatic": 1, + "Disabled": 0, + "Enabled": 2 + } + }, "WaterDirection": { "name": "WaterDirection", "items": { @@ -51153,6 +56605,8 @@ "HSROuter": 9, "HSROuterDetail": 8, "LayerCage": 2, + "LayerCageFittedToBase": 12, + "LayerCageFittedToPrev": 13, "None": 0, "OuterCage": 6, "Rbf": 5, From bac30ae78be95d73870f3cdc0f1d8f9d048618df Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 22 Apr 2023 15:58:14 -0400 Subject: [PATCH 1275/1504] Update MSRV to try to fix CI workflow --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77ac7dbf..115b6786 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - rust_version: [stable, 1.58.1] + rust_version: [stable, 1.69.0] steps: - uses: actions/checkout@v3 From e17771a6a5d1f200e7b84a9288f1e6d679c51f4a Mon Sep 17 00:00:00 2001 From: Lucien Greathouse Date: Sat, 22 Apr 2023 16:07:39 -0400 Subject: [PATCH 1276/1504] Release v7.3.0 --- CHANGELOG.md | 35 ++++++++++++++++++++++++++++++++++- Cargo.lock | 2 +- Cargo.toml | 4 ++-- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 566c4af3..deba0561 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,42 @@ # Rojo Changelog ## Unreleased Changes -* Added `--watch` flag to `rojo sourcemap` ([#602]) +## [7.3.0] - April 22, 2023 +* Added `$attributes` to project format. ([#574]) +* Added `--watch` flag to `rojo sourcemap`. ([#602]) +* Added support for `init.csv` files. ([#594]) +* Added real-time sync status to the Studio plugin. ([#569]) +* Added support for copying error messages to the clipboard. ([#614]) +* Added sync locking for Team Create. ([#590]) +* Added support for specifying HTTP or HTTPS protocol in plugin. ([#642]) +* Added tooltips to buttons in the Studio plugin. ([#637]) +* Added visual diffs when connecting from the Studio plugin. ([#603]) +* Host and port are now saved in the Studio plugin. ([#613]) +* Improved padding on notifications in Studio plugin. ([#589]) +* Renamed `Common` to `Shared` in the default Rojo project. ([#611]) +* Reduced the minimum size of the Studio plugin widget. ([#606]) +* Fixed current directory in `rojo fmt-project`. ([#581]) +* Fixed errors after a session has already ended. ([#587]) +* Fixed an uncommon security permission error ([#619]) + +[#569]: https://github.com/rojo-rbx/rojo/pull/569 +[#574]: https://github.com/rojo-rbx/rojo/pull/574 +[#581]: https://github.com/rojo-rbx/rojo/pull/581 +[#587]: https://github.com/rojo-rbx/rojo/pull/587 +[#589]: https://github.com/rojo-rbx/rojo/pull/589 +[#590]: https://github.com/rojo-rbx/rojo/pull/590 +[#594]: https://github.com/rojo-rbx/rojo/pull/594 [#602]: https://github.com/rojo-rbx/rojo/pull/602 +[#603]: https://github.com/rojo-rbx/rojo/pull/603 +[#606]: https://github.com/rojo-rbx/rojo/pull/606 +[#611]: https://github.com/rojo-rbx/rojo/pull/611 +[#613]: https://github.com/rojo-rbx/rojo/pull/613 +[#614]: https://github.com/rojo-rbx/rojo/pull/614 +[#619]: https://github.com/rojo-rbx/rojo/pull/619 +[#637]: https://github.com/rojo-rbx/rojo/pull/637 +[#642]: https://github.com/rojo-rbx/rojo/pull/642 +[7.3.0]: https://github.com/rojo-rbx/rojo/releases/tag/v7.3.0 ## [7.2.1] - July 8, 2022 * Fixed notification sound by changing it to a generic sound. ([#566]) diff --git a/Cargo.lock b/Cargo.lock index 9e6a1830..03c31289 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1878,7 +1878,7 @@ dependencies = [ [[package]] name = "rojo" -version = "7.2.1" +version = "7.3.0" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index afde0996..d9b38bf7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rojo" -version = "7.2.1" -rust-version = "1.58.1" +version = "7.3.0" +rust-version = "1.68.2" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" From 4b62190aff06803ff63f94d824cfeeb0a8909a0d Mon Sep 17 00:00:00 2001 From: Miizzuu <107253059+Miizzuu@users.noreply.github.com> Date: Sat, 6 May 2023 09:00:45 +0100 Subject: [PATCH 1277/1504] Fix wrong version of Rojo displaying in studio. (#669) --- aftman.toml | 2 +- plugin/src/Config.lua | 2 +- plugin/wally.lock | 2 +- plugin/wally.toml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/aftman.toml b/aftman.toml index 058140ef..e96d7dea 100644 --- a/aftman.toml +++ b/aftman.toml @@ -1,5 +1,5 @@ [tools] wally = "UpliftGames/wally@0.3.1" -rojo = "rojo-rbx/rojo@7.2.1" +rojo = "rojo-rbx/rojo@7.3.0" selene = "Kampfkarren/selene@0.20.0" run-in-roblox = "rojo-rbx/run-in-roblox@0.3.0" diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 8aae470d..3f5706e5 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {7, 2, 1}, + version = {7, 3, 0}, expectedServerVersionString = "7.2 or newer", protocolVersion = 4, defaultHost = "localhost", diff --git a/plugin/wally.lock b/plugin/wally.lock index e5c3f47c..76e5643c 100644 --- a/plugin/wally.lock +++ b/plugin/wally.lock @@ -29,5 +29,5 @@ dependencies = [] [[package]] name = "rojo-rbx/rojo" -version = "7.2.1" +version = "7.3.0" dependencies = [["Flipper", "reselim/flipper@2.0.0"], ["Promise", "evaera/promise@4.0.0"], ["Roact", "roblox/roact@1.4.4"], ["t", "osyrisrblx/t@3.0.0"]] diff --git a/plugin/wally.toml b/plugin/wally.toml index 31ef5662..0bc17767 100644 --- a/plugin/wally.toml +++ b/plugin/wally.toml @@ -1,7 +1,7 @@ [package] name = "rojo-rbx/rojo" description = "Rojo enables Roblox developers to use professional-grade software engineering tools" -version = "7.2.1" +version = "7.3.0" license = "MPL-2.0" authors = ["LPGhatguy (https://lpg.space/)"] registry = "https://github.com/upliftgames/wally-index" From 305423b856a99ca7da4a6ca691e734000c4d2a06 Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Sat, 6 May 2023 10:01:15 +0200 Subject: [PATCH 1278/1504] Sourcemap performance improvements (#668) This PR brings two performance improvements to the `rojo sourcemap` command: - Use `rayon` with a small threadpool to parallelize sourcemap generation while still keeping startup cost very low - Remove conversions to owned strings and use lifetimes tied to the dom instead, which mostly improves performance with the `--include-non-scripts` flag enabled From my personal testing on an M1 mac this decreases the sourcemap generation time of our games by 2x or more, from ~20ms to ~8ms on one project and ~30ms to ~15ms on another. Generation is pretty fast to begin with but since sourcemaps are heavily used in interactive tools (like luau-lsp) a difference of a couple frames can be great for ux. --- CHANGELOG.md | 3 +++ Cargo.lock | 2 ++ Cargo.toml | 2 ++ src/cli/sourcemap.rs | 39 +++++++++++++++++++++++---------------- 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index deba0561..b0a7b948 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Rojo Changelog ## Unreleased Changes +* Significantly improved performance of `rojo sourcemap`. ([#668]) + +[#668]: https://github.com/rojo-rbx/rojo/pull/668 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/Cargo.lock b/Cargo.lock index 03c31289..12e9f860 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1900,10 +1900,12 @@ dependencies = [ "maplit", "memofs", "notify", + "num_cpus", "opener", "paste", "pretty_assertions", "profiling", + "rayon", "rbx_binary", "rbx_dom_weak", "rbx_reflection", diff --git a/Cargo.toml b/Cargo.toml index d9b38bf7..bbbbcbf9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,7 +72,9 @@ jod-thread = "0.1.2" log = "0.4.14" maplit = "1.0.2" notify = "4.0.17" +num_cpus = "1.15.0" opener = "0.5.0" +rayon = "1.7.0" reqwest = { version = "0.11.10", features = ["blocking", "json", "native-tls-vendored"] } ritz = "0.1.0" roblox_install = "1.0.0" diff --git a/src/cli/sourcemap.rs b/src/cli/sourcemap.rs index 353c6020..f7bc1691 100644 --- a/src/cli/sourcemap.rs +++ b/src/cli/sourcemap.rs @@ -7,6 +7,7 @@ use std::{ use clap::Parser; use fs_err::File; use memofs::Vfs; +use rayon::prelude::*; use rbx_dom_weak::types::Ref; use serde::Serialize; use tokio::runtime::Runtime; @@ -23,15 +24,15 @@ const PATH_STRIP_FAILED_ERR: &str = "Failed to create relative paths for project /// Representation of a node in the generated sourcemap tree. #[derive(Serialize)] #[serde(rename_all = "camelCase")] -struct SourcemapNode { - name: String, - class_name: String, +struct SourcemapNode<'a> { + name: &'a str, + class_name: &'a str, #[serde(skip_serializing_if = "Vec::is_empty")] file_paths: Vec, #[serde(skip_serializing_if = "Vec::is_empty")] - children: Vec, + children: Vec>, } /// Generates a sourcemap file from the Rojo project. @@ -75,6 +76,13 @@ impl SourcemapCommand { filter_non_scripts }; + // Pre-build a rayon threadpool with a low number of threads to avoid + // dynamic creation overhead on systems with a high number of cpus. + rayon::ThreadPoolBuilder::new() + .num_threads(num_cpus::get().min(6)) + .build_global() + .unwrap(); + write_sourcemap(&session, self.output.as_deref(), filter)?; if self.watch { @@ -108,20 +116,19 @@ fn filter_non_scripts(instance: &InstanceWithMeta) -> bool { ) } -fn recurse_create_node( - tree: &RojoTree, +fn recurse_create_node<'a>( + tree: &'a RojoTree, referent: Ref, project_dir: &Path, filter: fn(&InstanceWithMeta) -> bool, -) -> Option { +) -> Option> { let instance = tree.get_instance(referent).expect("instance did not exist"); - let mut children = Vec::new(); - for &child_id in instance.children() { - if let Some(child_node) = recurse_create_node(tree, child_id, project_dir, filter) { - children.push(child_node); - } - } + let children: Vec<_> = instance + .children() + .par_iter() + .filter_map(|&child_id| recurse_create_node(tree, child_id, project_dir, filter)) + .collect(); // If this object has no children and doesn't pass the filter, it doesn't // contain any information we're looking for. @@ -140,8 +147,8 @@ fn recurse_create_node( .collect(); Some(SourcemapNode { - name: instance.name().to_string(), - class_name: instance.class_name().to_string(), + name: instance.name(), + class_name: instance.class_name(), file_paths, children, }) @@ -157,7 +164,7 @@ fn write_sourcemap( let root_node = recurse_create_node(&tree, tree.get_root_id(), session.root_dir(), filter); if let Some(output_path) = output { - let mut file = BufWriter::new(File::create(&output_path)?); + let mut file = BufWriter::new(File::create(output_path)?); serde_json::to_writer(&mut file, &root_node)?; file.flush()?; From d87c76a23e6c8e2bd8f67f398fbff2604b411351 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Fri, 26 May 2023 10:26:21 -0700 Subject: [PATCH 1279/1504] Switch plugin packages back to git submodules (#678) Alright, so I hate to be the one to do this, but #584 broke crates.io publishing and also caused librojo to be unusable. I see that there was some discussion on Discord shortly after the problem was realized, but there was no action taken. I think keeping librojo and publishing working far, far outweigh any convenience added by Wally. I've kept the same `Packages` naming convention to keep the diff minimal. --- .github/workflows/ci.yml | 18 +++++------------- .github/workflows/release.yml | 17 ++++------------- .gitignore | 3 --- .gitmodules | 15 +++++++++++++++ aftman.toml | 1 - plugin/Packages/Flipper | 1 + plugin/Packages/Promise | 1 + plugin/Packages/Roact | 1 + plugin/Packages/TestEZ | 1 + plugin/Packages/t | 1 + plugin/test-place.project.json | 2 +- plugin/wally.lock | 33 --------------------------------- plugin/wally.toml | 17 ----------------- 13 files changed, 30 insertions(+), 81 deletions(-) create mode 100644 .gitmodules create mode 160000 plugin/Packages/Flipper create mode 160000 plugin/Packages/Promise create mode 160000 plugin/Packages/Roact create mode 160000 plugin/Packages/TestEZ create mode 160000 plugin/Packages/t delete mode 100644 plugin/wally.lock delete mode 100644 plugin/wally.toml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 115b6786..80346f50 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -20,6 +20,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: true - name: Install Rust uses: actions-rs/toolchain@v1 @@ -33,12 +35,6 @@ jobs: with: version: 'v0.2.7' - - name: Install packages - run: | - cd plugin - wally install - cd .. - - name: Build run: cargo build --locked --verbose @@ -51,6 +47,8 @@ jobs: steps: - uses: actions/checkout@v3 + with: + submodules: true - name: Install Rust uses: actions-rs/toolchain@v1 @@ -64,14 +62,8 @@ jobs: with: version: 'v0.2.7' - - name: Install packages - run: | - cd plugin - wally install - cd .. - - name: Rustfmt run: cargo fmt -- --check - name: Clippy - run: cargo clippy \ No newline at end of file + run: cargo clippy diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ea4b0051..c4833c8d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,6 +28,8 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 + with: + submodules: true - name: Setup Aftman uses: ok-nick/setup-aftman@v0.1.0 @@ -36,12 +38,6 @@ jobs: trust-check: false version: 'v0.2.6' - - name: Install packages - run: | - cd plugin - wally install - cd .. - - name: Build Plugin run: rojo build plugin --output Rojo.rbxm @@ -94,6 +90,8 @@ jobs: BIN: rojo steps: - uses: actions/checkout@v3 + with: + submodules: true - name: Get Version from Tag shell: bash @@ -117,13 +115,6 @@ jobs: trust-check: false version: 'v0.2.6' - - name: Install packages - run: | - cd plugin - wally install - cd .. - shell: bash - - name: Build Release run: cargo build --release --locked --verbose env: diff --git a/.gitignore b/.gitignore index 2c910135..88cdf551 100644 --- a/.gitignore +++ b/.gitignore @@ -13,9 +13,6 @@ # Test places for the Roblox Studio Plugin /plugin/*.rbxlx -# Packages for the Roblox Studio Plugin -/plugin/*Packages - # Roblox Studio holds 'lock' files on places *.rbxl.lock *.rbxlx.lock diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..0842c711 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,15 @@ +[submodule "plugin/Packages/Roact"] + path = plugin/Packages/Roact + url = git@github.com:roblox/roact +[submodule "plugin/Packages/Flipper"] + path = plugin/Packages/Flipper + url = git@github.com:reselim/flipper +[submodule "plugin/Packages/Promise"] + path = plugin/Packages/Promise + url = git@github.com:evaera/roblox-lua-promise +[submodule "plugin/Packages/t"] + path = plugin/Packages/t + url = git@github.com:osyrisrblx/t +[submodule "plugin/Packages/TestEZ"] + path = plugin/Packages/TestEZ + url = git@github.com:roblox/testez diff --git a/aftman.toml b/aftman.toml index e96d7dea..f6e5cfdd 100644 --- a/aftman.toml +++ b/aftman.toml @@ -1,5 +1,4 @@ [tools] -wally = "UpliftGames/wally@0.3.1" rojo = "rojo-rbx/rojo@7.3.0" selene = "Kampfkarren/selene@0.20.0" run-in-roblox = "rojo-rbx/run-in-roblox@0.3.0" diff --git a/plugin/Packages/Flipper b/plugin/Packages/Flipper new file mode 160000 index 00000000..2d91a5ed --- /dev/null +++ b/plugin/Packages/Flipper @@ -0,0 +1 @@ +Subproject commit 2d91a5ed55332a3bf50f4eba82f9c812bd2343f8 diff --git a/plugin/Packages/Promise b/plugin/Packages/Promise new file mode 160000 index 00000000..2c6f4339 --- /dev/null +++ b/plugin/Packages/Promise @@ -0,0 +1 @@ +Subproject commit 2c6f433903275e689ba1d48402d4a9d6fdc605a5 diff --git a/plugin/Packages/Roact b/plugin/Packages/Roact new file mode 160000 index 00000000..956891b7 --- /dev/null +++ b/plugin/Packages/Roact @@ -0,0 +1 @@ +Subproject commit 956891b70fdc5410e44e9664719cd0a9f7e6fabd diff --git a/plugin/Packages/TestEZ b/plugin/Packages/TestEZ new file mode 160000 index 00000000..edc7246d --- /dev/null +++ b/plugin/Packages/TestEZ @@ -0,0 +1 @@ +Subproject commit edc7246d0173a3a90eba4a9f64ea26c576be5873 diff --git a/plugin/Packages/t b/plugin/Packages/t new file mode 160000 index 00000000..1f975425 --- /dev/null +++ b/plugin/Packages/t @@ -0,0 +1 @@ +Subproject commit 1f9754254b17bff5a0b7527620083f8ea85f579a diff --git a/plugin/test-place.project.json b/plugin/test-place.project.json index 9ac37f8b..70875137 100644 --- a/plugin/test-place.project.json +++ b/plugin/test-place.project.json @@ -9,7 +9,7 @@ }, "Packages": { - "$path": "DevPackages" + "$path": "Packages" } }, diff --git a/plugin/wally.lock b/plugin/wally.lock deleted file mode 100644 index 76e5643c..00000000 --- a/plugin/wally.lock +++ /dev/null @@ -1,33 +0,0 @@ -# This file is automatically @generated by Wally. -# It is not intended for manual editing. -registry = "test" - -[[package]] -name = "evaera/promise" -version = "4.0.0" -dependencies = [] - -[[package]] -name = "osyrisrblx/t" -version = "3.0.0" -dependencies = [] - -[[package]] -name = "reselim/flipper" -version = "2.0.0" -dependencies = [] - -[[package]] -name = "roblox/roact" -version = "1.4.4" -dependencies = [] - -[[package]] -name = "roblox/testez" -version = "0.4.1" -dependencies = [] - -[[package]] -name = "rojo-rbx/rojo" -version = "7.3.0" -dependencies = [["Flipper", "reselim/flipper@2.0.0"], ["Promise", "evaera/promise@4.0.0"], ["Roact", "roblox/roact@1.4.4"], ["t", "osyrisrblx/t@3.0.0"]] diff --git a/plugin/wally.toml b/plugin/wally.toml deleted file mode 100644 index 0bc17767..00000000 --- a/plugin/wally.toml +++ /dev/null @@ -1,17 +0,0 @@ -[package] -name = "rojo-rbx/rojo" -description = "Rojo enables Roblox developers to use professional-grade software engineering tools" -version = "7.3.0" -license = "MPL-2.0" -authors = ["LPGhatguy (https://lpg.space/)"] -registry = "https://github.com/upliftgames/wally-index" -realm = "shared" - -[dependencies] -Flipper = "reselim/flipper@2.0.0" -Promise = "evaera/promise@4.0.0" -Roact = "roblox/roact@1.4.4" -t = "osyrisrblx/t@3.0.0" - -[dev-dependencies] -TestEZ = "roblox/testez@0.4.1" From 6b0f7f94b60d05e4413fca3c6d7fa47bce6b257d Mon Sep 17 00:00:00 2001 From: boatbomber Date: Thu, 1 Jun 2023 11:18:04 -0400 Subject: [PATCH 1280/1504] Fix disconnected session activity (#675) When a session is disconnected, the apiContext long-polling for messages continues until resolved/rejected. This means that even after a session is disconnected, a message can be received and handled. This leads to bad behavior, as the session was already cleaned up and the message cannot be handled correctly. The instance map was cleaned up upon disconnect, so it will warn about unapplied changes to unknown instances. (Like #512) It's very easy to repro: Connect a session, disconnect it, then save a change. https://github.com/rojo-rbx/rojo/assets/40185666/846a7269-7043-4727-9f9c-b3ac55a18a3a ----------- This PR fixes that neatly by tracking all active requests in a map, and cancelling their promises when we disconnect. --- plugin/src/ApiContext.lua | 17 ++++++++++++++++- plugin/src/ServeSession.lua | 2 ++ 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 78f54fed..98890d4f 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -93,6 +93,7 @@ function ApiContext.new(baseUrl) __sessionId = nil, __messageCursor = -1, __connected = true, + __activeRequests = {}, } return setmetatable(self, ApiContext) @@ -113,6 +114,11 @@ end function ApiContext:disconnect() self.__connected = false + for request in self.__activeRequests do + Log.trace("Cancelling request {}", request) + request:cancel() + end + self.__activeRequests = {} end function ApiContext:setMessageCursor(index) @@ -204,7 +210,7 @@ function ApiContext:retrieveMessages() local url = ("%s/api/subscribe/%s"):format(self.__baseUrl, self.__messageCursor) local function sendRequest() - return Http.get(url) + local request = Http.get(url) :catch(function(err) if err.type == Http.Error.Kind.Timeout then if self.__connected then @@ -216,6 +222,15 @@ function ApiContext:retrieveMessages() return Promise.reject(err) end) + + Log.trace("Tracking request {}", request) + self.__activeRequests[request] = true + + return request:finally(function(...) + Log.trace("Cleaning up request {}", request) + self.__activeRequests[request] = nil + return ... + end) end return sendRequest() diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 12b9ffae..f77c8c74 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -285,6 +285,8 @@ end function ServeSession:__mainSyncLoop() return self.__apiContext:retrieveMessages() :andThen(function(messages) + Log.trace("Serve session {} retrieved {} messages", tostring(self), #messages) + for _, message in ipairs(messages) do local unappliedPatch = self.__reconciler:applyPatch(message) From 65423043409e5fe35e513c4ccec8ff0ae7845c1e Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sun, 4 Jun 2023 01:46:16 -0400 Subject: [PATCH 1281/1504] Fix the diff visualizer of connected sessions (#674) Clicking on the "X changes X ago" message opens up a handy diff visualizer to see what those changes were. However, it had quite a few issues that needed fixing. - Disconnecting a session with it expanded caused an error as it tried to read the serveSession that no longer exists during the page fade transition. (#671) - Resolved by converting to stateful component and holding the serveSession during the lifetime to ensure it can render the last known changes during the fade transition - Leaving it open while new changes are synced did not update the visualizer - The patch data was piggybacking on an existing binding, which meant that new patches did not trigger rerender. - Resolved by converting to state - Also made some improvements to that old binding - Moved from app to connected page for better organization and separation of duties - No more useless updates causing rerenders with no real change - Scroll window child component wouldn't actually display the updated visuals - Resolved by making major improvements to VirtualScroller - Made more robust against edge case states - Made smarter about knowing when it needs to refresh As you can see in this slow motion GIF, it works now. ![slowedDemo](https://github.com/rojo-rbx/rojo/assets/40185666/c9fc8489-72a9-47be-ae45-9c420e1535d4) --- .../Components/PatchVisualizer/DomLabel.lua | 8 +- plugin/src/App/Components/VirtualScroller.lua | 14 ++- plugin/src/App/StatusPages/Connected.lua | 94 +++++++++++++------ plugin/src/App/init.lua | 38 ++++---- 4 files changed, 98 insertions(+), 56 deletions(-) diff --git a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua index 8d282ab9..9f967c32 100644 --- a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua +++ b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua @@ -40,11 +40,6 @@ end local DomLabel = Roact.Component:extend("DomLabel") function DomLabel:init() - self.maxElementHeight = 0 - if self.props.changeList then - self.maxElementHeight = math.clamp(#self.props.changeList * 30, 30, 30 * 6) - end - local initHeight = self.props.elementHeight:getValue() self.expanded = initHeight > 30 @@ -118,7 +113,8 @@ function DomLabel:render() Size = UDim2.new(1, 0, 1, 0), [Roact.Event.Activated] = function() self.expanded = not self.expanded - self.motor:setGoal(Flipper.Spring.new((self.expanded and self.maxElementHeight or 0) + 30, { + local goalHeight = 30 + (if self.expanded then math.clamp(#self.props.changeList * 30, 30, 30 * 6) else 0) + self.motor:setGoal(Flipper.Spring.new(goalHeight, { frequency = 5, dampingRatio = 1, })) diff --git a/plugin/src/App/Components/VirtualScroller.lua b/plugin/src/App/Components/VirtualScroller.lua index 2922a74f..69bcf5f1 100644 --- a/plugin/src/App/Components/VirtualScroller.lua +++ b/plugin/src/App/Components/VirtualScroller.lua @@ -99,18 +99,30 @@ function VirtualScroller:refresh() }) end +function VirtualScroller:didUpdate(previousProps) + if self.props.count ~= previousProps.count then + -- Items have changed, so we need to refresh + self:refresh() + end +end + function VirtualScroller:render() local props, state = self.props, self.state local items = {} for i = state.Start, state.End do + local content = props.render(i) + if content == nil then + continue + end + items["Item" .. i] = e("Frame", { LayoutOrder = i, Size = props.getHeightBinding(i):map(function(height) return UDim2.new(1, 0, 0, height) end), BackgroundTransparency = 1, - }, props.render(i)) + }, content) end return Theme.with(function(theme) diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index 91484926..af43e6a2 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -26,11 +26,11 @@ function timeSinceText(elapsed: number): string local ageText = string.format("%d seconds ago", elapsed) - for _,UnitData in ipairs(AGE_UNITS) do + for _, UnitData in ipairs(AGE_UNITS) do local UnitSeconds, UnitName = UnitData[1], UnitData[2] if elapsed > UnitSeconds then - local c = math.floor(elapsed/UnitSeconds) - ageText = string.format("%d %s%s ago", c, UnitName, c>1 and "s" or "") + local c = math.floor(elapsed / UnitSeconds) + ageText = string.format("%d %s%s ago", c, UnitName, c > 1 and "s" or "") break end end @@ -38,45 +38,53 @@ function timeSinceText(elapsed: number): string return ageText end -local function ChangesDrawer(props) - if props.rendered == false then +local ChangesDrawer = Roact.Component:extend("ConnectedPage") + +function ChangesDrawer:init() + -- Hold onto the serve session during the lifecycle of this component + -- so that it can still render during the fade out after disconnecting + self.serveSession = self.props.serveSession +end + +function ChangesDrawer:render() + if self.props.rendered == false or self.serveSession == nil then return nil end return Theme.with(function(theme) return e(BorderedContainer, { - transparency = props.transparency, - size = props.height:map(function(y) + transparency = self.props.transparency, + size = self.props.height:map(function(y) return UDim2.new(1, 0, y, -180 * y) end), position = UDim2.new(0, 0, 1, 0), anchorPoint = Vector2.new(0, 1), - layoutOrder = props.layoutOrder, + layoutOrder = self.props.layoutOrder, }, { Close = e(IconButton, { icon = Assets.Images.Icons.Close, iconSize = 24, color = theme.ConnectionDetails.DisconnectColor, - transparency = props.transparency, + transparency = self.props.transparency, position = UDim2.new(1, 0, 0, 0), anchorPoint = Vector2.new(1, 0), - onClick = props.onClose, + onClick = self.props.onClose, }, { Tip = e(Tooltip.Trigger, { - text = "Close the patch visualizer" + text = "Close the patch visualizer", }), }), PatchVisualizer = e(PatchVisualizer, { size = UDim2.new(1, 0, 1, 0), - transparency = props.transparency, + transparency = self.props.transparency, layoutOrder = 3, - columnVisibility = {true, false, true}, - patch = props.patchInfo:getValue().patch, - instanceMap = props.serveSession.__instanceMap, + columnVisibility = { true, false, true }, + patch = self.props.patch, + instanceMap = self.serveSession.__instanceMap, }), }) end) @@ -91,7 +99,7 @@ local function ConnectionDetails(props) }, { TextContainer = e("Frame", { Size = UDim2.new(1, 0, 1, 0), - BackgroundTransparency = 1 + BackgroundTransparency = 1, }, { ProjectName = e("TextLabel", { Text = props.projectName, @@ -141,7 +149,7 @@ local function ConnectionDetails(props) onClick = props.onDisconnect, }, { Tip = e(Tooltip.Trigger, { - text = "Disconnect from the Rojo sync server" + text = "Disconnect from the Rojo sync server", }), }), @@ -155,6 +163,18 @@ end local ConnectedPage = Roact.Component:extend("ConnectedPage") +function ConnectedPage:getChangeInfoText() + local patchData = self.props.patchData + if patchData == nil then + return "" + end + + local elapsed = os.time() - patchData.timestamp + local changes = PatchSet.countChanges(patchData.patch) + + return string.format("Synced %d change%s %s", changes, changes == 1 and "" or "s", timeSinceText(elapsed)) +end + function ConnectedPage:init() self.changeDrawerMotor = Flipper.SingleMotor.new(0) self.changeDrawerHeight = bindingUtil.fromMotor(self.changeDrawerMotor) @@ -176,6 +196,34 @@ function ConnectedPage:init() self:setState({ renderChanges = false, }) + + self.changeInfoText, self.setChangeInfoText = Roact.createBinding("") + + self.changeInfoTextUpdater = task.defer(function() + while true do + self.setChangeInfoText(self:getChangeInfoText()) + + local elapsed = os.time() - self.props.patchData.timestamp + local updateInterval = 1 + + -- Update timestamp text as frequently as currently needed + for _, UnitData in ipairs(AGE_UNITS) do + local UnitSeconds = UnitData[1] + if elapsed >= UnitSeconds then + updateInterval = UnitSeconds + break + end + end + + task.wait(updateInterval) + end + end) +end + +function ConnectedPage:willUnmount() + if self.changeInfoTextUpdater then + task.cancel(self.changeInfoTextUpdater) + end end function ConnectedPage:render() @@ -208,15 +256,7 @@ function ConnectedPage:render() }), ChangeInfo = e("TextButton", { - Text = self.props.patchInfo:map(function(info) - local changes = PatchSet.countChanges(info.patch) - return string.format( - "Synced %d change%s %s", - changes, - changes == 1 and "" or "s", - timeSinceText(os.time() - info.timestamp) - ) - end), + Text = self.changeInfoText, Font = Enum.Font.Gotham, TextSize = 14, TextWrapped = true, @@ -249,7 +289,7 @@ function ConnectedPage:render() ChangesDrawer = e(ChangesDrawer, { rendered = self.state.renderChanges, transparency = self.props.transparency, - patchInfo = self.props.patchInfo, + patch = self.props.patchData.patch, serveSession = self.props.serveSession, height = self.changeDrawerHeight, layoutOrder = 4, diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 35df8ffb..8c705449 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -51,10 +51,6 @@ function App:init() self.host, self.setHost = Roact.createBinding(priorHost or "") self.port, self.setPort = Roact.createBinding(priorPort or "") - self.patchInfo, self.setPatchInfo = Roact.createBinding({ - patch = PatchSet.newEmpty(), - timestamp = os.time(), - }) self.confirmationBindable = Instance.new("BindableEvent") self.confirmationEvent = self.confirmationBindable.Event @@ -62,6 +58,10 @@ function App:init() appStatus = AppStatus.NotConnected, guiEnabled = false, confirmData = {}, + patchData = { + patch = PatchSet.newEmpty(), + timestamp = os.time(), + }, notifications = {}, toolbarIcon = Assets.Images.PluginButton, }) @@ -227,21 +227,25 @@ function App:startSession() local now = os.time() - local old = self.patchInfo:getValue() + local old = self.state.patchData if now - old.timestamp < 2 then -- Patches that apply in the same second are -- considered to be part of the same change for human clarity local merged = PatchSet.newEmpty() PatchSet.assign(merged, old.patch, patch) - self.setPatchInfo({ - patch = merged, - timestamp = now, + self:setState({ + patchData = { + patch = merged, + timestamp = now, + }, }) else - self.setPatchInfo({ - patch = patch, - timestamp = now, + self:setState({ + patchData = { + patch = patch, + timestamp = now, + }, }) end end) @@ -318,16 +322,6 @@ function App:startSession() serveSession:start() self.serveSession = serveSession - - task.defer(function() - while self.serveSession == serveSession do - -- Trigger rerender to update timestamp text - local patchInfo = table.clone(self.patchInfo:getValue()) - self.setPatchInfo(patchInfo) - local elapsed = os.time() - patchInfo.timestamp - task.wait(elapsed < 60 and 1 or elapsed / 5) - end - end) end function App:endSession() @@ -429,7 +423,7 @@ function App:render() Connected = createPageElement(AppStatus.Connected, { projectName = self.state.projectName, address = self.state.address, - patchInfo = self.patchInfo, + patchData = self.state.patchData, serveSession = self.serveSession, onDisconnect = function() From a9ca77e27fea04bcdfd370e312955f2ec22a56d2 Mon Sep 17 00:00:00 2001 From: Boegie19 <34578426+Boegie19@users.noreply.github.com> Date: Fri, 16 Jun 2023 20:41:30 +0200 Subject: [PATCH 1282/1504] Change gitmodules from ssh to https (#696) Why if you want to use ssh you need todo more setup aka add a ssh key into github while with https you don't have to do the extra work aka makes rojo easier to contribute to. --- .gitmodules | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.gitmodules b/.gitmodules index 0842c711..2851e057 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,15 +1,15 @@ [submodule "plugin/Packages/Roact"] path = plugin/Packages/Roact - url = git@github.com:roblox/roact + url = https://github.com/roblox/roact.git [submodule "plugin/Packages/Flipper"] path = plugin/Packages/Flipper - url = git@github.com:reselim/flipper + url = https://github.com/reselim/flipper.git [submodule "plugin/Packages/Promise"] path = plugin/Packages/Promise - url = git@github.com:evaera/roblox-lua-promise + url = https://github.com/evaera/roblox-lua-promise.git [submodule "plugin/Packages/t"] path = plugin/Packages/t - url = git@github.com:osyrisrblx/t + url = https://github.com/osyrisrblx/t.git [submodule "plugin/Packages/TestEZ"] path = plugin/Packages/TestEZ - url = git@github.com:roblox/testez + url = https://github.com/roblox/testez.git From 342fb57d143e335acc53e37b1855912b3ca537b1 Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Fri, 30 Jun 2023 19:53:19 +0200 Subject: [PATCH 1283/1504] Fix compilation target in release workflow (#701) Fixes macOS aarch64 builds not actually outputting x86 binaries by specifying the `--target` flag during compilation in the release workflow. These are the same changes as [this PR in Aftman](https://github.com/LPGhatguy/aftman/pull/34), which had the same issue, and uses the same workflow. --- .github/workflows/release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c4833c8d..5cc781b0 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -116,7 +116,7 @@ jobs: version: 'v0.2.6' - name: Build Release - run: cargo build --release --locked --verbose + run: cargo build --release --locked --verbose --target ${{ matrix.target }} env: # Build into a known directory so we can find our build artifact more # easily. @@ -132,11 +132,11 @@ jobs: mkdir staging if [ "${{ matrix.host }}" = "windows" ]; then - cp "output/release/$BIN.exe" staging/ + cp "output/${{ matrix.target }}/release/$BIN.exe" staging/ cd staging 7z a ../release.zip * else - cp "output/release/$BIN" staging/ + cp "output/${{ matrix.target }}/release/$BIN" staging/ cd staging zip ../release.zip * fi From b303b0a99c29f53547d9e62603e89e7bfcab9dc8 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Fri, 30 Jun 2023 11:02:14 -0700 Subject: [PATCH 1284/1504] Add PRs 674 and 675 to changelog (#693) Forgot to update changelog in those PRs, this remedies that --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b0a7b948..68eb44b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,12 @@ ## Unreleased Changes * Significantly improved performance of `rojo sourcemap`. ([#668]) +* Fixed the diff visualizer of connected sessions. ([#674]) +* Fixed disconnected session activity. ([#675]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 +[#674]: https://github.com/rojo-rbx/rojo/pull/674 +[#675]: https://github.com/rojo-rbx/rojo/pull/675 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) From 2507e096b78a5ccbe7df8913fbb416929b9cf329 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Fri, 30 Jun 2023 11:03:09 -0700 Subject: [PATCH 1285/1504] Fix change processor clippy lints (#680) Bear with me here... The first in a series of PRs that aim to get CI passing --- src/change_processor.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index f3902067..2429b590 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -251,7 +251,7 @@ fn on_vfs_event( let mut current_path = path.as_path(); let affected_ids = loop { - let ids = tree.get_ids_at_path(¤t_path); + let ids = tree.get_ids_at_path(current_path); log::trace!("Path {} affects IDs {:?}", current_path.display(), ids); @@ -267,7 +267,7 @@ fn on_vfs_event( }; for id in affected_ids { - if let Some(patch) = compute_and_apply_changes(&mut tree, &vfs, id) { + if let Some(patch) = compute_and_apply_changes(&mut tree, vfs, id) { if !patch.is_empty() { applied_patches.push(patch); } @@ -301,7 +301,7 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: Ref) -> Option< // path still exists. We can generate a snapshot starting at // that path and use it as the source for our patch. - let snapshot = match snapshot_from_vfs(&metadata.context, &vfs, &path) { + let snapshot = match snapshot_from_vfs(&metadata.context, vfs, path) { Ok(snapshot) => snapshot, Err(err) => { log::error!("Snapshot error: {:?}", err); @@ -309,7 +309,7 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: Ref) -> Option< } }; - let patch_set = compute_patch_set(snapshot, &tree, id); + let patch_set = compute_patch_set(snapshot, tree, id); apply_patch_set(tree, patch_set) } Ok(None) => { @@ -337,10 +337,10 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: Ref) -> Option< let snapshot_result = snapshot_project_node( &metadata.context, - &project_path, + project_path, instance_name, project_node, - &vfs, + vfs, parent_class.as_ref().map(|name| name.as_str()), ); @@ -352,7 +352,7 @@ fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: Ref) -> Option< } }; - let patch_set = compute_patch_set(snapshot, &tree, id); + let patch_set = compute_patch_set(snapshot, tree, id); apply_patch_set(tree, patch_set) } }; From b7a1f82f569c0b3a22214ea40319833edd677932 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Fri, 30 Jun 2023 11:03:37 -0700 Subject: [PATCH 1286/1504] Fix cli clippy lints (#681) The second in a series of PRs that aim to get CI passing --- src/cli/fmt_project.rs | 2 +- src/cli/init.rs | 2 +- src/cli/serve.rs | 2 +- src/cli/upload.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/cli/fmt_project.rs b/src/cli/fmt_project.rs index 48a52bd6..9c3e88d3 100644 --- a/src/cli/fmt_project.rs +++ b/src/cli/fmt_project.rs @@ -24,7 +24,7 @@ impl FmtProjectCommand { let serialized = serde_json::to_string_pretty(&project) .context("could not re-encode project file as JSON")?; - fs_err::write(&project.file_location, &serialized) + fs_err::write(&project.file_location, serialized) .context("could not write back to project file")?; Ok(()) diff --git a/src/cli/init.rs b/src/cli/init.rs index 795ec04d..b770f55d 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -184,7 +184,7 @@ fn try_git_init(path: &Path, git_ignore: &str) -> Result<(), anyhow::Error> { /// already inside a Git repository. fn should_git_init(path: &Path) -> bool { let result = Command::new("git") - .args(&["rev-parse", "--is-inside-work-tree"]) + .args(["rev-parse", "--is-inside-work-tree"]) .stdout(Stdio::null()) .stderr(Stdio::null()) .current_dir(path) diff --git a/src/cli/serve.rs b/src/cli/serve.rs index 0e35785e..f89e4387 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -39,7 +39,7 @@ impl ServeCommand { let vfs = Vfs::new_default(); - let session = Arc::new(ServeSession::new(vfs, &project_path)?); + let session = Arc::new(ServeSession::new(vfs, project_path)?); let ip = self .address diff --git a/src/cli/upload.rs b/src/cli/upload.rs index d8404099..ce7a2b5d 100644 --- a/src/cli/upload.rs +++ b/src/cli/upload.rs @@ -176,7 +176,7 @@ fn do_upload_open_cloud( log::debug!("Uploading to Roblox..."); let response = client - .post(&url) + .post(url) .header("x-api-key", api_key) .header(CONTENT_TYPE, "application/xml") .header(ACCEPT, "application/json") From 0dabd8a1f6361c4d76178d96097ead0bb5852e5e Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Fri, 30 Jun 2023 11:04:04 -0700 Subject: [PATCH 1287/1504] Fix memofs clippy lints (#682) The third in a series of PRs that aim to get CI passing --- crates/memofs/src/in_memory_fs.rs | 6 ++++++ crates/memofs/src/lib.rs | 7 ++----- crates/memofs/src/noop_backend.rs | 6 ++++++ crates/memofs/src/std_backend.rs | 6 ++++++ 4 files changed, 20 insertions(+), 5 deletions(-) diff --git a/crates/memofs/src/in_memory_fs.rs b/crates/memofs/src/in_memory_fs.rs index 328fbffe..fc8cf2ef 100644 --- a/crates/memofs/src/in_memory_fs.rs +++ b/crates/memofs/src/in_memory_fs.rs @@ -50,6 +50,12 @@ impl InMemoryFs { } } +impl Default for InMemoryFs { + fn default() -> Self { + Self::new() + } +} + #[derive(Debug)] struct InMemoryFsInner { entries: HashMap, diff --git a/crates/memofs/src/lib.rs b/crates/memofs/src/lib.rs index f6a17ef6..744ca60f 100644 --- a/crates/memofs/src/lib.rs +++ b/crates/memofs/src/lib.rs @@ -194,11 +194,8 @@ impl VfsInner { } fn commit_event(&mut self, event: &VfsEvent) -> io::Result<()> { - match event { - VfsEvent::Remove(path) => { - let _ = self.backend.unwatch(&path); - } - _ => {} + if let VfsEvent::Remove(path) = event { + let _ = self.backend.unwatch(path); } Ok(()) diff --git a/crates/memofs/src/noop_backend.rs b/crates/memofs/src/noop_backend.rs index 383119c5..efc8fd4a 100644 --- a/crates/memofs/src/noop_backend.rs +++ b/crates/memofs/src/noop_backend.rs @@ -74,3 +74,9 @@ impl VfsBackend for NoopBackend { )) } } + +impl Default for NoopBackend { + fn default() -> Self { + Self::new() + } +} diff --git a/crates/memofs/src/std_backend.rs b/crates/memofs/src/std_backend.rs index 7e616cbd..c13ade0b 100644 --- a/crates/memofs/src/std_backend.rs +++ b/crates/memofs/src/std_backend.rs @@ -108,3 +108,9 @@ impl VfsBackend for StdBackend { .map_err(|inner| io::Error::new(io::ErrorKind::Other, inner)) } } + +impl Default for StdBackend { + fn default() -> Self { + Self::new() + } +} From e9efa238b01aaa9019ab0f33e139d8e20494eeb0 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Fri, 30 Jun 2023 11:04:56 -0700 Subject: [PATCH 1288/1504] Fix project clippy lints (#683) The fourth in a series of PRs that aim to get CI passing --- src/project.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/project.rs b/src/project.rs index 330cbd23..e70005d0 100644 --- a/src/project.rs +++ b/src/project.rs @@ -127,11 +127,10 @@ impl Project { contents: &[u8], project_file_location: &Path, ) -> Result { - let mut project: Self = - serde_json::from_slice(&contents).map_err(|source| Error::Json { - source, - path: project_file_location.to_owned(), - })?; + let mut project: Self = serde_json::from_slice(contents).map_err(|source| Error::Json { + source, + path: project_file_location.to_owned(), + })?; project.file_location = project_file_location.to_path_buf(); project.check_compatibility(); @@ -197,8 +196,8 @@ pub enum PathNode { impl PathNode { pub fn path(&self) -> &Path { match self { - PathNode::Required(pathbuf) => &pathbuf, - PathNode::Optional(OptionalPathNode { optional }) => &optional, + PathNode::Required(pathbuf) => pathbuf, + PathNode::Optional(OptionalPathNode { optional }) => optional, } } } From 5b1a090c5e520efe5b74265688391562c8354f14 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Fri, 30 Jun 2023 11:05:30 -0700 Subject: [PATCH 1289/1504] Fix serve session clippy lints (#684) The fifth in a series of PRs that aim to get CI passing --- src/serve_session.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/serve_session.rs b/src/serve_session.rs index 96a68ac9..9dab5446 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -102,12 +102,11 @@ impl ServeSession { log::trace!("Starting new ServeSession at path {}", start_path.display()); - let project_path; - if Project::is_project_file(start_path) { - project_path = Cow::Borrowed(start_path); + let project_path = if Project::is_project_file(start_path) { + Cow::Borrowed(start_path) } else { - project_path = Cow::Owned(start_path.join("default.project.json")); - } + Cow::Owned(start_path.join("default.project.json")) + }; log::debug!("Loading project file from {}", project_path.display()); @@ -127,7 +126,7 @@ impl ServeSession { let instance_context = InstanceContext::default(); log::trace!("Generating snapshot of instances from VFS"); - let snapshot = snapshot_from_vfs(&instance_context, &vfs, &start_path)?; + let snapshot = snapshot_from_vfs(&instance_context, &vfs, start_path)?; log::trace!("Computing initial patch set"); let patch_set = compute_patch_set(snapshot, &tree, root_id); From a2f68c2e3c670b3bc5c3dbf45ebbdd3d11ef3ccf Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Fri, 30 Jun 2023 11:05:55 -0700 Subject: [PATCH 1290/1504] Fix snapshot clippy lints (#685) The sixth in a series of PRs that aim to get CI passing --- src/snapshot/patch_apply.rs | 3 +-- src/snapshot/patch_compute.rs | 6 ++---- src/snapshot/tree.rs | 8 ++++---- 3 files changed, 7 insertions(+), 10 deletions(-) diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index 439452d8..5818776c 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -97,8 +97,7 @@ fn finalize_patch_application(context: PatchApplyContext, tree: &mut RojoTree) - for value in instance.properties_mut().values_mut() { if let Variant::Ref(referent) = value { - if let Some(&instance_referent) = context.snapshot_id_to_instance_id.get(&referent) - { + if let Some(&instance_referent) = context.snapshot_id_to_instance_id.get(referent) { *value = Variant::Ref(instance_referent); } } diff --git a/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs index 23e2f302..f5d5a67b 100644 --- a/src/snapshot/patch_compute.rs +++ b/src/snapshot/patch_compute.rs @@ -26,10 +26,8 @@ pub fn compute_patch_set(snapshot: Option, tree: &RojoTree, id // for all of the IDs that we know about so far. rewrite_refs_in_updates(&context, &mut patch_set.updated_instances); rewrite_refs_in_additions(&context, &mut patch_set.added_instances); - } else { - if id != tree.get_root_id() { - patch_set.removed_instances.push(id); - } + } else if id != tree.get_root_id() { + patch_set.removed_instances.push(id); } patch_set diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index e342e186..e4379bc2 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -37,8 +37,8 @@ pub struct RojoTree { impl RojoTree { pub fn new(snapshot: InstanceSnapshot) -> RojoTree { - let root_builder = InstanceBuilder::new(snapshot.class_name.to_owned()) - .with_name(snapshot.name.to_owned()) + let root_builder = InstanceBuilder::new(snapshot.class_name) + .with_name(snapshot.name) .with_properties(snapshot.properties); let mut tree = RojoTree { @@ -245,7 +245,7 @@ impl<'a> InstanceWithMeta<'a> { } pub fn metadata(&self) -> &'a InstanceMetadata { - &self.metadata + self.metadata } } @@ -294,6 +294,6 @@ impl InstanceWithMetaMut<'_> { } pub fn metadata(&self) -> &InstanceMetadata { - &self.metadata + self.metadata } } From 8646b2dfceb45d8a197cd9c4c3ed13444c6cadcc Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Fri, 30 Jun 2023 11:06:12 -0700 Subject: [PATCH 1291/1504] Fix snapshot middleware clippy lints (#686) The seventh in a series of PRs that aim to get CI passing --- src/snapshot_middleware/dir.rs | 2 +- src/snapshot_middleware/util.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index ba63301c..092641e7 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -77,7 +77,7 @@ pub fn snapshot_dir_no_meta( let relevant_paths = vec![ path.to_path_buf(), - meta_path.clone(), + meta_path, // TODO: We shouldn't need to know about Lua existing in this // middleware. Should we figure out a way for that function to add // relevant paths to this middleware? diff --git a/src/snapshot_middleware/util.rs b/src/snapshot_middleware/util.rs index 517cd606..16648eae 100644 --- a/src/snapshot_middleware/util.rs +++ b/src/snapshot_middleware/util.rs @@ -37,7 +37,7 @@ where .and_then(|name| name.to_str()) .with_context(|| format!("Path did not have a file name: {}", path.display()))?; - match_trailing(&file_name, suffix) + match_trailing(file_name, suffix) .with_context(|| format!("Path did not end in {}: {}", suffix, path.display())) } } From 67674d53a2d8337eebb56d16bd7b05efd6b6afcf Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Fri, 30 Jun 2023 11:06:43 -0700 Subject: [PATCH 1292/1504] Fix remaining clippy lints (#687) The eighth (and final) in a series of PRs that aim to get CI passing --- build.rs | 2 +- src/lua_ast.rs | 30 ++++++++++++++++++++++++------ src/path_serializer.rs | 2 +- src/web/interface.rs | 6 +----- 4 files changed, 27 insertions(+), 13 deletions(-) diff --git a/build.rs b/build.rs index 1cff84c5..8326fcdc 100644 --- a/build.rs +++ b/build.rs @@ -54,7 +54,7 @@ fn main() -> Result<(), anyhow::Error> { }); let out_path = Path::new(&out_dir).join("plugin.bincode"); - let out_file = File::create(&out_path)?; + let out_file = File::create(out_path)?; bincode::serialize_into(out_file, &snapshot)?; diff --git a/src/lua_ast.rs b/src/lua_ast.rs index c31b609f..a61e41c9 100644 --- a/src/lua_ast.rs +++ b/src/lua_ast.rs @@ -219,12 +219,30 @@ fn is_valid_ident_char(value: char) -> bool { } fn is_keyword(value: &str) -> bool { - match value { - "and" | "break" | "do" | "else" | "elseif" | "end" | "false" | "for" | "function" - | "if" | "in" | "local" | "nil" | "not" | "or" | "repeat" | "return" | "then" | "true" - | "until" | "while" => true, - _ => false, - } + matches!( + value, + "and" + | "break" + | "do" + | "else" + | "elseif" + | "end" + | "false" + | "for" + | "function" + | "if" + | "in" + | "local" + | "nil" + | "not" + | "or" + | "repeat" + | "return" + | "then" + | "true" + | "until" + | "while" + ) } /// Tells whether the given string is a valid Lua identifier. diff --git a/src/path_serializer.rs b/src/path_serializer.rs index 74eb9534..29edaf82 100644 --- a/src/path_serializer.rs +++ b/src/path_serializer.rs @@ -15,7 +15,7 @@ where .as_os_str() .to_str() .expect("Invalid Unicode in file path, cannot serialize"); - let replaced = as_str.replace("\\", "/"); + let replaced = as_str.replace('\\', "/"); serializer.serialize_str(&replaced) } diff --git a/src/web/interface.rs b/src/web/interface.rs index 28005057..c10e14bc 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -145,11 +145,7 @@ fn property_filter(value: Option<&Variant>) -> bool { // Lua can't do anything with SharedString values. They also can't be // serialized directly by Serde! - if ty == Some(VariantType::SharedString) { - return false; - } - - return true; + ty != Some(VariantType::SharedString) } /// Response body from /api/rojo From 55ac231cecb7f350b8810cb8bcc57fc36a396a47 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Fri, 30 Jun 2023 11:21:36 -0700 Subject: [PATCH 1293/1504] Skip confirming patches that only contain a datamodel name change (#688) Closes #672. Skips the user confirmation if the patch contains only a datamodel name change. I decided to build generic PatchSet utility functions in case we need to use similar logic in the future, in addition to maintaining clear division of duties. The app code shouldn't be too dependent upon patch internal structure when we can avoid it. --------- Co-authored-by: Kenneth Loeffler --- CHANGELOG.md | 2 + plugin/src/App/init.lua | 19 +++++++ plugin/src/PatchSet.lua | 109 +++++++++++++++++++++++++++++++++++++++- 3 files changed, 129 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 68eb44b0..07a20cf9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,12 @@ * Significantly improved performance of `rojo sourcemap`. ([#668]) * Fixed the diff visualizer of connected sessions. ([#674]) * Fixed disconnected session activity. ([#675]) +* Skip confirming patches that contain only a datamodel name change. ([#688]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 [#675]: https://github.com/rojo-rbx/rojo/pull/675 +[#688]: https://github.com/rojo-rbx/rojo/pull/688 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 8c705449..9d58b661 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -295,9 +295,28 @@ function App:startSession() serveSession:setConfirmCallback(function(instanceMap, patch, serverInfo) if PatchSet.isEmpty(patch) then + Log.trace("Accepting patch without confirmation because it is empty") return "Accept" end + -- The datamodel name gets overwritten by Studio, making confirmation of it intrusive + -- and unnecessary. This special case allows it to be accepted without confirmation. + if + PatchSet.hasAdditions(patch) == false + and PatchSet.hasRemoves(patch) == false + and PatchSet.containsOnlyInstance(patch, instanceMap, game) + then + local datamodelUpdates = PatchSet.getUpdateForInstance(patch, instanceMap, game) + if + datamodelUpdates ~= nil + and next(datamodelUpdates.changedProperties) == nil + and datamodelUpdates.changedClassName == nil + then + Log.trace("Accepting patch without confirmation because it only contains a datamodel name change") + return "Accept" + end + end + self:setState({ appStatus = AppStatus.Confirming, confirmData = { diff --git a/plugin/src/PatchSet.lua b/plugin/src/PatchSet.lua index 3451de6a..c9f621dc 100644 --- a/plugin/src/PatchSet.lua +++ b/plugin/src/PatchSet.lua @@ -91,6 +91,113 @@ function PatchSet.hasUpdates(patchSet) return next(patchSet.updated) ~= nil end +--[[ + Tells whether the given PatchSet contains changes to the given instance id +]] +function PatchSet.containsId(patchSet, instanceMap, id) + if patchSet.added[id] ~= nil then + return true + end + + for _, idOrInstance in patchSet.removed do + local removedId = if Types.RbxId(idOrInstance) then idOrInstance else instanceMap.fromInstances[idOrInstance] + if removedId == id then + return true + end + end + + for _, update in patchSet.updated do + if update.id == id then + return true + end + end + + return false +end + +--[[ + Tells whether the given PatchSet contains changes to the given instance. + If the given InstanceMap does not contain the instance, this function always returns false. +]] +function PatchSet.containsInstance(patchSet, instanceMap, instance) + local id = instanceMap.fromInstances[instance] + if id == nil then + return false + end + + return PatchSet.containsId(patchSet, instanceMap, id) +end + +--[[ + Tells whether the given PatchSet contains changes to nothing but the given instance id +]] +function PatchSet.containsOnlyId(patchSet, instanceMap, id) + if not PatchSet.containsId(patchSet, instanceMap, id) then + -- Patch doesn't contain the id at all + return false + end + + for addedId in patchSet.added do + if addedId ~= id then + return false + end + end + + for _, idOrInstance in patchSet.removed do + local removedId = if Types.RbxId(idOrInstance) then idOrInstance else instanceMap.fromInstances[idOrInstance] + if removedId ~= id then + return false + end + end + + for _, update in patchSet.updated do + if update.id ~= id then + return false + end + end + + return true +end + +--[[ + Tells whether the given PatchSet contains changes to nothing but the given instance. + If the given InstanceMap does not contain the instance, this function always returns false. +]] +function PatchSet.containsOnlyInstance(patchSet, instanceMap, instance) + local id = instanceMap.fromInstances[instance] + if id == nil then + return false + end + + return PatchSet.containsOnlyId(patchSet, instanceMap, id) +end + +--[[ + Returns the update to the given instance id, or nil if there aren't any +]] +function PatchSet.getUpdateForId(patchSet, id) + for _, update in patchSet.updated do + if update.id == id then + return update + end + end + + return nil +end + +--[[ + Returns the update to the given instance, or nil if there aren't any. + If the given InstanceMap does not contain the instance, this function always returns nil. +]] +function PatchSet.getUpdateForInstance(patchSet, instanceMap, instance) + local id = instanceMap.fromInstances[instance] + if id == nil then + return nil + end + + return PatchSet.getUpdateForId(patchSet, id) +end + --[[ Tells whether the given PatchSets are equal. ]] @@ -150,7 +257,7 @@ function PatchSet.humanSummary(instanceMap, patchSet) for _, idOrInstance in ipairs(patchSet.removed) do local instance, id - if type(idOrInstance) == "string" then + if Types.RbxId(idOrInstance) then id = idOrInstance instance = instanceMap.fromIds[id] else From 66c1cd0d93d3560685d3e74c2de73d4d0f77ab38 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Fri, 30 Jun 2023 13:44:42 -0700 Subject: [PATCH 1294/1504] Add protection against syncing non place projects (#691) Closes #113. Does what it says on the tin. When you try to sync a non-place project, it gives a clear message instead of crashing. --- CHANGELOG.md | 2 ++ plugin/src/ServeSession.lua | 16 ++++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 07a20cf9..33d39bdf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,11 +5,13 @@ * Fixed the diff visualizer of connected sessions. ([#674]) * Fixed disconnected session activity. ([#675]) * Skip confirming patches that contain only a datamodel name change. ([#688]) +* Added protection against syncing a model to a place. ([#691]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 [#675]: https://github.com/rojo-rbx/rojo/pull/675 [#688]: https://github.com/rojo-rbx/rojo/pull/688 +[#691]: https://github.com/rojo-rbx/rojo/pull/691 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index f77c8c74..08dc4041 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -232,6 +232,22 @@ function ServeSession:__initialSync(serverInfo) Log.error("Could not compute a diff to catch up to the Rojo server: {:#?}", catchUpPatch) end + for _, update in catchUpPatch.updated do + if + update.id == self.__instanceMap.fromInstances[game] + and update.changedClassName ~= nil + then + -- Non-place projects will try to update the classname of game from DataModel to + -- something like Folder, ModuleScript, etc. This would fail, so we exit with a clear + -- message instead of crashing. + return Promise.reject( + "Cannot sync a model as a place." + .. "\nEnsure Rojo is serving a project file that has a DataModel at the root of its tree and try again." + .. "\nSee project file docs: https://rojo.space/docs/v7/project-format/" + ) + end + end + Log.trace("Computed hydration patch: {:#?}", debugPatch(catchUpPatch)) local userDecision = "Accept" From 658d211779da4fb708ff28ea898efecdeb9e4d91 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Tue, 4 Jul 2023 13:09:41 -0700 Subject: [PATCH 1295/1504] Sync reminder notification & notification actions (#689) Implements and closes #652. --------- Co-authored-by: Chris Chang <51393127+chriscerie@users.noreply.github.com> Co-authored-by: Micah --- CHANGELOG.md | 2 + plugin/src/App/Notifications.lua | 109 ++++++++++++------ .../src/App/StatusPages/Settings/Setting.lua | 1 + plugin/src/App/StatusPages/Settings/init.lua | 31 +++-- plugin/src/App/init.lua | 97 ++++++++++++---- plugin/src/Settings.lua | 1 + plugin/src/ignorePlaceIds.lua | 27 +++++ 7 files changed, 199 insertions(+), 69 deletions(-) create mode 100644 plugin/src/ignorePlaceIds.lua diff --git a/CHANGELOG.md b/CHANGELOG.md index 33d39bdf..ec66d3c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,14 @@ * Fixed the diff visualizer of connected sessions. ([#674]) * Fixed disconnected session activity. ([#675]) * Skip confirming patches that contain only a datamodel name change. ([#688]) +* Added sync reminder notification. ([#689]) * Added protection against syncing a model to a place. ([#691]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 [#675]: https://github.com/rojo-rbx/rojo/pull/675 [#688]: https://github.com/rojo-rbx/rojo/pull/688 +[#689]: https://github.com/rojo-rbx/rojo/pull/689 [#691]: https://github.com/rojo-rbx/rojo/pull/691 ## [7.3.0] - April 22, 2023 diff --git a/plugin/src/App/Notifications.lua b/plugin/src/App/Notifications.lua index 5e1b0882..120a5aa5 100644 --- a/plugin/src/App/Notifications.lua +++ b/plugin/src/App/Notifications.lua @@ -7,6 +7,7 @@ local Packages = Rojo.Packages local Roact = require(Packages.Roact) local Flipper = require(Packages.Flipper) +local Log = require(Packages.Log) local bindingUtil = require(script.Parent.bindingUtil) @@ -14,6 +15,7 @@ local Theme = require(Plugin.App.Theme) local Assets = require(Plugin.Assets) local BorderedContainer = require(Plugin.App.Components.BorderedContainer) +local TextButton = require(Plugin.App.Components.TextButton) local baseClock = DateTime.now().UnixTimestampMillis @@ -28,10 +30,8 @@ function Notification:init() self.lifetime = self.props.timeout self.motor:onStep(function(value) - if value <= 0 then - if self.props.onClose then - self.props.onClose() - end + if value <= 0 and self.props.onClose then + self.props.onClose() end end) end @@ -86,23 +86,54 @@ function Notification:willUnmount() end function Notification:render() - local time = DateTime.fromUnixTimestampMillis(self.props.timestamp) - - local textBounds = TextService:GetTextSize( - self.props.text, - 15, - Enum.Font.GothamSemibold, - Vector2.new(350, 700) - ) - local transparency = self.binding:map(function(value) return 1 - value end) + local textBounds = TextService:GetTextSize( + self.props.text, + 15, + Enum.Font.GothamMedium, + Vector2.new(350, 700) + ) + + local actionButtons = {} + local buttonsX = 0 + if self.props.actions then + local count = 0 + for key, action in self.props.actions do + actionButtons[key] = e(TextButton, { + text = action.text, + style = action.style, + onClick = function() + local success, err = pcall(action.onClick, self) + if not success then + Log.warn("Error in notification action: " .. tostring(err)) + end + end, + layoutOrder = -action.layoutOrder, + transparency = transparency, + }) + + buttonsX += TextService:GetTextSize( + action.text, 18, Enum.Font.GothamMedium, + Vector2.new(math.huge, math.huge) + ).X + 30 + + count += 1 + end + + buttonsX += (count - 1) * 5 + end + + local paddingY, logoSize = 20, 32 + local actionsY = if self.props.actions then 35 else 0 + local contentX = math.max(textBounds.X, buttonsX) + local size = self.binding:map(function(value) return UDim2.fromOffset( - (35+40+textBounds.X)*value, - math.max(14+20+textBounds.Y, 32+20) + (35 + 40 + contentX) * value, + 5 + actionsY + paddingY + math.max(logoSize, textBounds.Y) ) end) @@ -122,22 +153,22 @@ function Notification:render() transparency = transparency, size = UDim2.new(1, 0, 1, 0), }, { - TextContainer = e("Frame", { - Size = UDim2.new(0, 35+textBounds.X, 1, -20), - Position = UDim2.new(0, 0, 0, 10), + Contents = e("Frame", { + Size = UDim2.new(0, 35 + contentX, 1, -paddingY), + Position = UDim2.new(0, 0, 0, paddingY / 2), BackgroundTransparency = 1 }, { Logo = e("ImageLabel", { ImageTransparency = transparency, Image = Assets.Images.PluginButton, BackgroundTransparency = 1, - Size = UDim2.new(0, 32, 0, 32), - Position = UDim2.new(0, 0, 0.5, 0), - AnchorPoint = Vector2.new(0, 0.5), + Size = UDim2.new(0, logoSize, 0, logoSize), + Position = UDim2.new(0, 0, 0, 0), + AnchorPoint = Vector2.new(0, 0), }), Info = e("TextLabel", { Text = self.props.text, - Font = Enum.Font.GothamSemibold, + Font = Enum.Font.GothamMedium, TextSize = 15, TextColor3 = theme.Notification.InfoColor, TextTransparency = transparency, @@ -150,20 +181,21 @@ function Notification:render() LayoutOrder = 1, BackgroundTransparency = 1, }), - Time = e("TextLabel", { - Text = time:FormatLocalTime("LTS", "en-us"), - Font = Enum.Font.Code, - TextSize = 12, - TextColor3 = theme.Notification.InfoColor, - TextTransparency = transparency, - TextXAlignment = Enum.TextXAlignment.Left, - - Size = UDim2.new(1, -35, 0, 14), - Position = UDim2.new(0, 35, 1, -14), - - LayoutOrder = 1, + Actions = if self.props.actions then e("Frame", { + Size = UDim2.new(1, -40, 0, 35), + Position = UDim2.new(1, 0, 1, 0), + AnchorPoint = Vector2.new(1, 1), BackgroundTransparency = 1, - }), + }, { + Layout = e("UIListLayout", { + FillDirection = Enum.FillDirection.Horizontal, + HorizontalAlignment = Enum.HorizontalAlignment.Right, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 5), + }), + Buttons = Roact.createFragment(actionButtons), + }) else nil, }), Padding = e("UIPadding", { @@ -180,15 +212,16 @@ local Notifications = Roact.Component:extend("Notifications") function Notifications:render() local notifs = {} - for index, notif in ipairs(self.props.notifications) do - notifs[notif] = e(Notification, { + for id, notif in self.props.notifications do + notifs["NotifID_" .. id] = e(Notification, { soundPlayer = self.props.soundPlayer, text = notif.text, timestamp = notif.timestamp, timeout = notif.timeout, + actions = notif.actions, layoutOrder = (notif.timestamp - baseClock), onClose = function() - self.props.onClose(index) + self.props.onClose(id) end, }) end diff --git a/plugin/src/App/StatusPages/Settings/Setting.lua b/plugin/src/App/StatusPages/Settings/Setting.lua index 8bf688f6..0c0de9f4 100644 --- a/plugin/src/App/StatusPages/Settings/Setting.lua +++ b/plugin/src/App/StatusPages/Settings/Setting.lua @@ -59,6 +59,7 @@ function Setting:render() LayoutOrder = self.props.layoutOrder, ZIndex = -self.props.layoutOrder, BackgroundTransparency = 1, + Visible = self.props.visible, [Roact.Change.AbsoluteSize] = function(object) self.setContainerSize(object.AbsoluteSize) diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua index 1d484423..f83e145c 100644 --- a/plugin/src/App/StatusPages/Settings/init.lua +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -87,19 +87,20 @@ function SettingsPage:render() layoutOrder = 0, }), - OpenScriptsExternally = e(Setting, { - id = "openScriptsExternally", - name = "Open Scripts Externally", - description = "Attempt to open scripts in an external editor", - transparency = self.props.transparency, - layoutOrder = 1, - }), - ShowNotifications = e(Setting, { id = "showNotifications", name = "Show Notifications", description = "Popup notifications in viewport", transparency = self.props.transparency, + layoutOrder = 1, + }), + + SyncReminder = e(Setting, { + id = "syncReminder", + name = "Sync Reminder", + description = "Notify to sync when opening a place that has previously been synced", + transparency = self.props.transparency, + visible = Settings:getBinding("showNotifications"), layoutOrder = 2, }), @@ -111,12 +112,20 @@ function SettingsPage:render() layoutOrder = 3, }), + OpenScriptsExternally = e(Setting, { + id = "openScriptsExternally", + name = "Open Scripts Externally", + description = "EXPERIMENTAL! Attempt to open scripts in an external editor", + transparency = self.props.transparency, + layoutOrder = 4, + }), + TwoWaySync = e(Setting, { id = "twoWaySync", name = "Two-Way Sync", description = "EXPERIMENTAL! Editing files in Studio will sync them into the filesystem", transparency = self.props.transparency, - layoutOrder = 4, + layoutOrder = 5, }), LogLevel = e(Setting, { @@ -124,7 +133,7 @@ function SettingsPage:render() name = "Log Level", description = "Plugin output verbosity level", transparency = self.props.transparency, - layoutOrder = 5, + layoutOrder = 100, options = invertedLevels, showReset = Settings:getBinding("logLevel"):map(function(value) @@ -140,7 +149,7 @@ function SettingsPage:render() name = "Typechecking", description = "Toggle typechecking on the API surface", transparency = self.props.transparency, - layoutOrder = 6, + layoutOrder = 101, }), Layout = e("UIListLayout", { diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 9d58b661..9fe081d7 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -1,5 +1,6 @@ local Players = game:GetService("Players") local ServerStorage = game:GetService("ServerStorage") +local RunService = game:GetService("RunService") local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin @@ -19,6 +20,7 @@ local ApiContext = require(Plugin.ApiContext) local PatchSet = require(Plugin.PatchSet) local preloadAssets = require(Plugin.preloadAssets) local soundPlayer = require(Plugin.soundPlayer) +local ignorePlaceIds = require(Plugin.ignorePlaceIds) local Theme = require(script.Theme) local Page = require(script.Page) @@ -53,6 +55,7 @@ function App:init() self.confirmationBindable = Instance.new("BindableEvent") self.confirmationEvent = self.confirmationBindable.Event + self.notifId = 0 self:setState({ appStatus = AppStatus.NotConnected, @@ -65,28 +68,63 @@ function App:init() notifications = {}, toolbarIcon = Assets.Images.PluginButton, }) + + if + RunService:IsEdit() + and self.serveSession == nil + and Settings:get("syncReminder") + and self:getLastSyncTimestamp() + then + self:addNotification("You've previously synced this place. Would you like to reconnect?", 300, { + Connect = { + text = "Connect", + style = "Solid", + layoutOrder = 1, + onClick = function(notification) + notification:dismiss() + self:startSession() + end + }, + Dismiss = { + text = "Dismiss", + style = "Bordered", + layoutOrder = 2, + onClick = function(notification) + notification:dismiss() + end, + }, + }) + end end -function App:addNotification(text: string, timeout: number?) +function App:addNotification(text: string, timeout: number?, actions: { [string]: {text: string, style: string, layoutOrder: number, onClick: (any) -> ()} }?) if not Settings:get("showNotifications") then return end + self.notifId += 1 + local id = self.notifId + local notifications = table.clone(self.state.notifications) - table.insert(notifications, { + notifications[id] = { text = text, timestamp = DateTime.now().UnixTimestampMillis, timeout = timeout or 3, - }) + actions = actions, + } self:setState({ notifications = notifications, }) + + return function() + self:closeNotification(id) + end end -function App:closeNotification(index: number) +function App:closeNotification(id: number) local notifications = table.clone(self.state.notifications) - table.remove(notifications, index) + notifications[id] = nil self:setState({ notifications = notifications, @@ -97,12 +135,28 @@ function App:getPriorEndpoint() local priorEndpoints = Settings:get("priorEndpoints") if not priorEndpoints then return end - local place = priorEndpoints[tostring(game.PlaceId)] + local id = tostring(game.PlaceId) + if ignorePlaceIds[id] then return end + + local place = priorEndpoints[id] if not place then return end return place.host, place.port end +function App:getLastSyncTimestamp() + local priorEndpoints = Settings:get("priorEndpoints") + if not priorEndpoints then return end + + local id = tostring(game.PlaceId) + if ignorePlaceIds[id] then return end + + local place = priorEndpoints[id] + if not place then return end + + return place.timestamp +end + function App:setPriorEndpoint(host: string, port: string) local priorEndpoints = Settings:get("priorEndpoints") if not priorEndpoints then @@ -117,17 +171,16 @@ function App:setPriorEndpoint(host: string, port: string) end end - if host == Config.defaultHost and port == Config.defaultPort then - -- Don't save default - priorEndpoints[tostring(game.PlaceId)] = nil - else - priorEndpoints[tostring(game.PlaceId)] = { - host = host ~= Config.defaultHost and host or nil, - port = port ~= Config.defaultPort and port or nil, - timestamp = os.time(), - } - Log.trace("Saved last used endpoint for {}", game.PlaceId) - end + local id = tostring(game.PlaceId) + if ignorePlaceIds[id] then return end + + priorEndpoints[id] = { + host = if host ~= Config.defaultHost then host else nil, + port = if port ~= Config.defaultPort then port else nil, + timestamp = os.time(), + } + Log.trace("Saved last used endpoint for {}", game.PlaceId) + Settings:set("priorEndpoints", priorEndpoints) end @@ -470,7 +523,11 @@ function App:render() }), }), - RojoNotifications = e("ScreenGui", {}, { + RojoNotifications = e("ScreenGui", { + ZIndexBehavior = Enum.ZIndexBehavior.Sibling, + ResetOnSpawn = false, + DisplayOrder = 100, + }, { layout = e("UIListLayout", { SortOrder = Enum.SortOrder.LayoutOrder, HorizontalAlignment = Enum.HorizontalAlignment.Right, @@ -486,8 +543,8 @@ function App:render() notifs = e(Notifications, { soundPlayer = self.props.soundPlayer, notifications = self.state.notifications, - onClose = function(index) - self:closeNotification(index) + onClose = function(id) + self:closeNotification(id) end, }), }), diff --git a/plugin/src/Settings.lua b/plugin/src/Settings.lua index 0f23c86b..f6368a4d 100644 --- a/plugin/src/Settings.lua +++ b/plugin/src/Settings.lua @@ -13,6 +13,7 @@ local defaultSettings = { openScriptsExternally = false, twoWaySync = false, showNotifications = true, + syncReminder = true, playSounds = true, typecheckingEnabled = false, logLevel = "Info", diff --git a/plugin/src/ignorePlaceIds.lua b/plugin/src/ignorePlaceIds.lua new file mode 100644 index 00000000..40ad8f58 --- /dev/null +++ b/plugin/src/ignorePlaceIds.lua @@ -0,0 +1,27 @@ +--[[ + These are place ids that will not have metadata saved for them, + such as last sync address or time. This is because they are not unique + so storing metadata for them does not make sense as these ids are reused. +--]] + +return { + ["0"] = true, -- Local file + ["95206881"] = true, -- Baseplate + ["6560363541"] = true, -- Classic Baseplate + ["95206192"] = true, -- Flat Terrain + ["13165709401"] = true, -- Modern City + ["520390648"] = true, -- Village + ["203810088"] = true, -- Castle + ["366130569"] = true, -- Suburban + ["215383192"] = true, -- Racing + ["264719325"] = true, -- Pirate Island + ["203812057"] = true, -- Obby + ["379736082"] = true, -- Starting Place + ["301530843"] = true, -- Line Runner + ["92721754"] = true, -- Capture The Flag + ["301529772"] = true, -- Team/FFA Arena + ["203885589"] = true, -- Combat + ["10275826693"] = true, -- Concert + ["5353920686"] = true, -- Move It Simulator + ["6936227200"] = true, -- Mansion Of Wonder +} From ce530e795a51026936c3dee46eb34cad00c0c4ff Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 5 Jul 2023 14:09:11 -0700 Subject: [PATCH 1296/1504] Fix Rojo breaking when users undo/redo in Studio (#708) --- CHANGELOG.md | 4 +- plugin/src/App/init.lua | 105 ++++++++++++++++++++++++--- plugin/src/Reconciler/applyPatch.lua | 6 ++ 3 files changed, 104 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ec66d3c6..373eef77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Skip confirming patches that contain only a datamodel name change. ([#688]) * Added sync reminder notification. ([#689]) * Added protection against syncing a model to a place. ([#691]) +* Fix Rojo breaking when users undo/redo in Studio ([#708]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 @@ -14,6 +15,7 @@ [#688]: https://github.com/rojo-rbx/rojo/pull/688 [#689]: https://github.com/rojo-rbx/rojo/pull/689 [#691]: https://github.com/rojo-rbx/rojo/pull/691 +[#708]: https://github.com/rojo-rbx/rojo/pull/708 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) @@ -579,4 +581,4 @@ This is a general maintenance release for the Rojo 0.5.x release series. * More robust syncing with a new reconciler ## [0.1.0](https://github.com/rojo-rbx/rojo/releases/tag/v0.1.0) (November 29, 2017) -* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) \ No newline at end of file +* Initial release, functionally very similar to [rbxfs](https://github.com/LPGhatguy/rbxfs) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 9fe081d7..c7be7671 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -1,3 +1,4 @@ +local ChangeHistoryService = game:GetService("ChangeHistoryService") local Players = game:GetService("Players") local ServerStorage = game:GetService("ServerStorage") local RunService = game:GetService("RunService") @@ -57,6 +58,64 @@ function App:init() self.confirmationEvent = self.confirmationBindable.Event self.notifId = 0 + self.waypointConnection = ChangeHistoryService.OnUndo:Connect(function(action: string) + if not string.find(action, "^Rojo: Patch") then + return + end + + local undoConnection, redoConnection = nil, nil + local function cleanup() + undoConnection:Disconnect() + redoConnection:Disconnect() + end + + Log.warn( + string.format( + "You've undone '%s'.\nIf this was not intended, please Redo in the topbar or with Ctrl/⌘+Y.", + action + ) + ) + local dismissNotif = self:addNotification( + string.format("You've undone '%s'.\nIf this was not intended, please restore.", action), + 10, + { + Restore = { + text = "Restore", + style = "Solid", + layoutOrder = 1, + onClick = function(notification) + cleanup() + notification:dismiss() + ChangeHistoryService:Redo() + end, + }, + Dismiss = { + text = "Dismiss", + style = "Bordered", + layoutOrder = 2, + onClick = function(notification) + cleanup() + notification:dismiss() + end, + }, + } + ) + + undoConnection = ChangeHistoryService.OnUndo:Once(function() + -- Our notif is now out of date- redoing will not restore the patch + -- since we've undone even further. Dismiss the notif. + cleanup() + dismissNotif() + end) + redoConnection = ChangeHistoryService.OnRedo:Once(function(redoneAction: string) + if redoneAction == action then + -- The user has restored the patch, so we can dismiss the notif + cleanup() + dismissNotif() + end + end) + end) + self:setState({ appStatus = AppStatus.NotConnected, guiEnabled = false, @@ -83,7 +142,7 @@ function App:init() onClick = function(notification) notification:dismiss() self:startSession() - end + end, }, Dismiss = { text = "Dismiss", @@ -97,7 +156,16 @@ function App:init() end end -function App:addNotification(text: string, timeout: number?, actions: { [string]: {text: string, style: string, layoutOrder: number, onClick: (any) -> ()} }?) +function App:willUnmount() + self.waypointConnection:Disconnect() + self.confirmationBindable:Destroy() +end + +function App:addNotification( + text: string, + timeout: number?, + actions: { [string]: { text: string, style: string, layoutOrder: number, onClick: (any) -> () } }? +) if not Settings:get("showNotifications") then return end @@ -123,6 +191,10 @@ function App:addNotification(text: string, timeout: number?, actions: { [string] end function App:closeNotification(id: number) + if not self.state.notifications[id] then + return + end + local notifications = table.clone(self.state.notifications) notifications[id] = nil @@ -133,26 +205,38 @@ end function App:getPriorEndpoint() local priorEndpoints = Settings:get("priorEndpoints") - if not priorEndpoints then return end + if not priorEndpoints then + return + end local id = tostring(game.PlaceId) - if ignorePlaceIds[id] then return end + if ignorePlaceIds[id] then + return + end local place = priorEndpoints[id] - if not place then return end + if not place then + return + end return place.host, place.port end function App:getLastSyncTimestamp() local priorEndpoints = Settings:get("priorEndpoints") - if not priorEndpoints then return end + if not priorEndpoints then + return + end local id = tostring(game.PlaceId) - if ignorePlaceIds[id] then return end + if ignorePlaceIds[id] then + return + end local place = priorEndpoints[id] - if not place then return end + if not place then + return + end return place.timestamp end @@ -172,7 +256,9 @@ function App:setPriorEndpoint(host: string, port: string) end local id = tostring(game.PlaceId) - if ignorePlaceIds[id] then return end + if ignorePlaceIds[id] then + return + end priorEndpoints[id] = { host = if host ~= Config.defaultHost then host else nil, @@ -181,7 +267,6 @@ function App:setPriorEndpoint(host: string, port: string) } Log.trace("Saved last used endpoint for {}", game.PlaceId) - Settings:set("priorEndpoints", priorEndpoints) end diff --git a/plugin/src/Reconciler/applyPatch.lua b/plugin/src/Reconciler/applyPatch.lua index a625ebe9..4faa7310 100644 --- a/plugin/src/Reconciler/applyPatch.lua +++ b/plugin/src/Reconciler/applyPatch.lua @@ -5,6 +5,8 @@ Patches can come from the server or be generated by the client. ]] +local ChangeHistoryService = game:GetService("ChangeHistoryService") + local Packages = script.Parent.Parent.Parent.Packages local Log = require(Packages.Log) @@ -17,6 +19,8 @@ local reify = require(script.Parent.reify) local setProperty = require(script.Parent.setProperty) local function applyPatch(instanceMap, patch) + local patchTimestamp = DateTime.now():FormatLocalTime("LTS", "en-us") + -- Tracks any portions of the patch that could not be applied to the DOM. local unappliedPatch = PatchSet.newEmpty() @@ -199,6 +203,8 @@ local function applyPatch(instanceMap, patch) end end + ChangeHistoryService:SetWaypoint("Rojo: Patch " .. patchTimestamp) + return unappliedPatch end From fde78738b67e12d4f85b70534964749fb0732adc Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 5 Jul 2023 14:38:11 -0700 Subject: [PATCH 1297/1504] Improve sync info (#692) - Fixed an edge case where disconnecting and then reconnecting would retain outdated info - Fixed an issue where new patches wouldn't immediately update the change info text - Removed extraneous changes count info, as it was not useful and could be checked in the visualizer anyway - Added warning info for when some changes fail to apply - Updates timestamp of last sync even if patch was empty, to have a more accurate signal on Rojo's uptime --- CHANGELOG.md | 3 + plugin/src/App/StatusPages/Connected.lua | 98 ++++++++++++++++++------ plugin/src/App/init.lua | 51 +++++++----- plugin/src/PatchSet.lua | 15 +++- 4 files changed, 121 insertions(+), 46 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 373eef77..17c7d27c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ * Added sync reminder notification. ([#689]) * Added protection against syncing a model to a place. ([#691]) * Fix Rojo breaking when users undo/redo in Studio ([#708]) +* Improved sync info text on Connected page. ([#692]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 @@ -16,6 +17,8 @@ [#689]: https://github.com/rojo-rbx/rojo/pull/689 [#691]: https://github.com/rojo-rbx/rojo/pull/691 [#708]: https://github.com/rojo-rbx/rojo/pull/708 +[#692]: https://github.com/rojo-rbx/rojo/pull/692 + ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index af43e6a2..ac152ef1 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -170,9 +170,56 @@ function ConnectedPage:getChangeInfoText() end local elapsed = os.time() - patchData.timestamp - local changes = PatchSet.countChanges(patchData.patch) + local unapplied = PatchSet.countChanges(patchData.unapplied) - return string.format("Synced %d change%s %s", changes, changes == 1 and "" or "s", timeSinceText(elapsed)) + return + "Synced " + .. timeSinceText(elapsed) + .. (if unapplied > 0 then + string.format( + ", but %d change%s failed to apply", + unapplied, + unapplied == 1 and "" or "s" + ) + else "") + .. "" +end + +function ConnectedPage:startChangeInfoTextUpdater() + -- Cancel any existing updater + self:stopChangeInfoTextUpdater() + + -- Start a new updater + self.changeInfoTextUpdater = task.defer(function() + while true do + if self.state.hoveringChangeInfo then + self.setChangeInfoText("" .. self:getChangeInfoText() .. "") + else + self.setChangeInfoText(self:getChangeInfoText()) + end + + local elapsed = os.time() - self.props.patchData.timestamp + local updateInterval = 1 + + -- Update timestamp text as frequently as currently needed + for _, UnitData in ipairs(AGE_UNITS) do + local UnitSeconds = UnitData[1] + if elapsed > UnitSeconds then + updateInterval = UnitSeconds + break + end + end + + task.wait(updateInterval) + end + end) +end + +function ConnectedPage:stopChangeInfoTextUpdater() + if self.changeInfoTextUpdater then + task.cancel(self.changeInfoTextUpdater) + self.changeInfoTextUpdater = nil + end end function ConnectedPage:init() @@ -195,34 +242,21 @@ function ConnectedPage:init() self:setState({ renderChanges = false, + hoveringChangeInfo = false, }) self.changeInfoText, self.setChangeInfoText = Roact.createBinding("") - self.changeInfoTextUpdater = task.defer(function() - while true do - self.setChangeInfoText(self:getChangeInfoText()) - - local elapsed = os.time() - self.props.patchData.timestamp - local updateInterval = 1 - - -- Update timestamp text as frequently as currently needed - for _, UnitData in ipairs(AGE_UNITS) do - local UnitSeconds = UnitData[1] - if elapsed >= UnitSeconds then - updateInterval = UnitSeconds - break - end - end - - task.wait(updateInterval) - end - end) + self:startChangeInfoTextUpdater() end function ConnectedPage:willUnmount() - if self.changeInfoTextUpdater then - task.cancel(self.changeInfoTextUpdater) + self:stopChangeInfoTextUpdater() +end + +function ConnectedPage:didUpdate(previousProps) + if self.props.patchData.timestamp ~= previousProps.patchData.timestamp then + self:startChangeInfoTextUpdater() end end @@ -271,6 +305,20 @@ function ConnectedPage:render() LayoutOrder = 3, BackgroundTransparency = 1, + [Roact.Event.MouseEnter] = function() + self:setState({ + hoveringChangeInfo = true, + }) + self.setChangeInfoText("" .. self:getChangeInfoText() .. "") + end, + + [Roact.Event.MouseLeave] = function() + self:setState({ + hoveringChangeInfo = false, + }) + self.setChangeInfoText(self:getChangeInfoText()) + end, + [Roact.Event.Activated] = function() if self.state.renderChanges then self.changeDrawerMotor:setGoal(Flipper.Spring.new(0, { @@ -284,6 +332,10 @@ function ConnectedPage:render() })) end end, + }, { + Tooltip = e(Tooltip.Trigger, { + text = if self.state.renderChanges then "Hide the changes" else "View the changes", + }), }), ChangesDrawer = e(ChangesDrawer, { diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index c7be7671..762f2bbd 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -122,6 +122,7 @@ function App:init() confirmData = {}, patchData = { patch = PatchSet.newEmpty(), + unapplied = PatchSet.newEmpty(), timestamp = os.time(), }, notifications = {}, @@ -357,35 +358,36 @@ function App:startSession() twoWaySync = sessionOptions.twoWaySync, }) - serveSession:onPatchApplied(function(patch, _unapplied) + serveSession:onPatchApplied(function(patch, unapplied) + local now = os.time() + local old = self.state.patchData + if PatchSet.isEmpty(patch) then - -- Ignore empty patches + -- Ignore empty patch, but update timestamp + self:setState({ + patchData = { + patch = old.patch, + unapplied = old.unapplied, + timestamp = now, + }, + }) return end - local now = os.time() - - local old = self.state.patchData if now - old.timestamp < 2 then -- Patches that apply in the same second are -- considered to be part of the same change for human clarity - local merged = PatchSet.newEmpty() - PatchSet.assign(merged, old.patch, patch) - - self:setState({ - patchData = { - patch = merged, - timestamp = now, - }, - }) - else - self:setState({ - patchData = { - patch = patch, - timestamp = now, - }, - }) + patch = PatchSet.assign(PatchSet.newEmpty(), old.patch, patch) + unapplied = PatchSet.assign(PatchSet.newEmpty(), old.unapplied, unapplied) end + + self:setState({ + patchData = { + patch = patch, + unapplied = unapplied, + timestamp = now, + }, + }) end) serveSession:onStatusChanged(function(status, details) @@ -409,6 +411,13 @@ function App:startSession() elseif status == ServeSession.Status.Disconnected then self.serveSession = nil self:releaseSyncLock() + self:setState({ + patchData = { + patch = PatchSet.newEmpty(), + unapplied = PatchSet.newEmpty(), + timestamp = os.time(), + }, + }) -- Details being present indicates that this -- disconnection was from an error. diff --git a/plugin/src/PatchSet.lua b/plugin/src/PatchSet.lua index c9f621dc..a9bebd80 100644 --- a/plugin/src/PatchSet.lua +++ b/plugin/src/PatchSet.lua @@ -212,13 +212,24 @@ function PatchSet.countChanges(patch) local count = 0 for _ in patch.added do + -- Adding an instance is 1 change count += 1 end for _ in patch.removed do + -- Removing an instance is 1 change count += 1 end - for _ in patch.updated do - count += 1 + for _, update in patch.updated do + -- Updating an instance is 1 change per property updated + for _ in update.changedProperties do + count += 1 + end + if update.changedName ~= nil then + count += 1 + end + if update.changedClassName ~= nil then + count += 1 + end end return count From 27357110b51e0d53b20c16b0606fdf4918d25a0c Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 8 Jul 2023 14:37:42 -0700 Subject: [PATCH 1298/1504] Handle strings and instances in patch removes for visualizer (#713) When an object is deleted in a patch, it is either represented with an ID or an Instance. On initial sync, removals are instances since the map does not contain those instances. Later removals of managed objects use an ID. The patch visualizer only handled instances, so this fixes that. Closes #710. --- plugin/src/App/Components/PatchVisualizer/init.lua | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/plugin/src/App/Components/PatchVisualizer/init.lua b/plugin/src/App/Components/PatchVisualizer/init.lua index 95673dfe..a751f2ff 100644 --- a/plugin/src/App/Components/PatchVisualizer/init.lua +++ b/plugin/src/App/Components/PatchVisualizer/init.lua @@ -7,6 +7,7 @@ local Packages = Rojo.Packages local Roact = require(Packages.Roact) local Log = require(Packages.Log) +local Types = require(Plugin.Types) local PatchSet = require(Plugin.PatchSet) local decodeValue = require(Plugin.Reconciler.decodeValue) local getProperty = require(Plugin.Reconciler.getProperty) @@ -240,7 +241,14 @@ function PatchVisualizer:buildTree(patch, instanceMap) }) end - for _, instance in patch.removed do + for _, idOrInstance in patch.removed do + local instance = if Types.RbxId(idOrInstance) then instanceMap.fromIds[idOrInstance] else idOrInstance + if not instance then + -- If we're viewing a past patch, the instance is already removed + -- and we therefore cannot get the tree for it anymore + continue + end + -- Gather ancestors from existing DOM -- (note that they may have no ID if they're being removed as unknown) local ancestry = {} From a4fd53d5169f277d834b15b46800f379e0cf1a5d Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 8 Jul 2023 15:54:19 -0700 Subject: [PATCH 1299/1504] Update changelog to include #713 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17c7d27c..3680a84a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ * Added protection against syncing a model to a place. ([#691]) * Fix Rojo breaking when users undo/redo in Studio ([#708]) * Improved sync info text on Connected page. ([#692]) +* Fix patch visualizer breaking when instances are removed during sync ([#713]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 @@ -18,6 +19,7 @@ [#691]: https://github.com/rojo-rbx/rojo/pull/691 [#708]: https://github.com/rojo-rbx/rojo/pull/708 [#692]: https://github.com/rojo-rbx/rojo/pull/692 +[#713]: https://github.com/rojo-rbx/rojo/pull/713 ## [7.3.0] - April 22, 2023 From 8139fdc738160c53550ebbbc96e5b88989bbdf05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F?= <34089907+Barocena@users.noreply.github.com> Date: Sun, 9 Jul 2023 03:44:28 +0300 Subject: [PATCH 1300/1504] (feat) Add Changelog Check Action (#719) --- .github/workflows/ci.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 80346f50..fc018973 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,3 +67,19 @@ jobs: - name: Clippy run: cargo clippy + + Changelog: + name: Changelog Check + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + - name: Changelog check + + uses: Zomzog/changelog-checker@v1.3.0 + with: + fileName: CHANGELOG.md + noChangelogLabel: no changelog + checkNotification: Simple + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + From ccc52b69d2f0edffb5299c2c37d097642e4359ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F?= <34089907+Barocena@users.noreply.github.com> Date: Sun, 9 Jul 2023 04:30:59 +0300 Subject: [PATCH 1301/1504] (fix) Move changelog job to it's own workflow (#720) - moved the job to its own workflow file - changed the label to `skip changelog` --- .github/workflows/changelog.yml | 23 +++++++++++++++++++++++ .github/workflows/ci.yml | 15 --------------- 2 files changed, 23 insertions(+), 15 deletions(-) create mode 100644 .github/workflows/changelog.yml diff --git a/.github/workflows/changelog.yml b/.github/workflows/changelog.yml new file mode 100644 index 00000000..699152cc --- /dev/null +++ b/.github/workflows/changelog.yml @@ -0,0 +1,23 @@ +name: Changelog Check + +on: + pull_request: + types: [assigned, opened, synchronize, reopened, labeled, unlabeled] + branches: + - master + +jobs: + build: + name: Check Actions + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + + - name: Changelog check + uses: Zomzog/changelog-checker@v1.3.0 + with: + fileName: CHANGELOG.md + noChangelogLabel: skip changelog + checkNotification: Simple + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fc018973..b0e9fefe 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,18 +68,3 @@ jobs: - name: Clippy run: cargo clippy - Changelog: - name: Changelog Check - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Changelog check - - uses: Zomzog/changelog-checker@v1.3.0 - with: - fileName: CHANGELOG.md - noChangelogLabel: no changelog - checkNotification: Simple - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - From 7ef4a1ff12e12f18eae60cf5e2a1e7c10bb0cd4a Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 8 Jul 2023 18:45:25 -0700 Subject: [PATCH 1302/1504] Select Instances from diff tree (#709) --- CHANGELOG.md | 2 + .../Components/PatchVisualizer/DomLabel.lua | 58 ++++++++++++++----- .../App/Components/PatchVisualizer/init.lua | 7 ++- 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3680a84a..16c90c4b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Skip confirming patches that contain only a datamodel name change. ([#688]) * Added sync reminder notification. ([#689]) * Added protection against syncing a model to a place. ([#691]) +* Select Instances from diff tree view ([#709]) * Fix Rojo breaking when users undo/redo in Studio ([#708]) * Improved sync info text on Connected page. ([#692]) * Fix patch visualizer breaking when instances are removed during sync ([#713]) @@ -17,6 +18,7 @@ [#688]: https://github.com/rojo-rbx/rojo/pull/688 [#689]: https://github.com/rojo-rbx/rojo/pull/689 [#691]: https://github.com/rojo-rbx/rojo/pull/691 +[#709]: https://github.com/rojo-rbx/rojo/pull/709 [#708]: https://github.com/rojo-rbx/rojo/pull/708 [#692]: https://github.com/rojo-rbx/rojo/pull/692 [#713]: https://github.com/rojo-rbx/rojo/pull/713 diff --git a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua index 9f967c32..351f8c31 100644 --- a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua +++ b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua @@ -1,3 +1,4 @@ +local SelectionService = game:GetService("Selection") local StudioService = game:GetService("StudioService") local Rojo = script:FindFirstAncestor("Rojo") @@ -14,6 +15,7 @@ local bindingUtil = require(Plugin.App.bindingUtil) local e = Roact.createElement local ChangeList = require(script.Parent.ChangeList) +local Tooltip = require(script.Parent.Parent.Tooltip) local Expansion = Roact.Component:extend("Expansion") @@ -106,21 +108,47 @@ function DomLabel:render() PaddingLeft = UDim.new(0, 10), PaddingRight = UDim.new(0, 10), }), - ExpandButton = if props.changeList - then e("TextButton", { - BackgroundTransparency = 1, - Text = "", - Size = UDim2.new(1, 0, 1, 0), - [Roact.Event.Activated] = function() - self.expanded = not self.expanded - local goalHeight = 30 + (if self.expanded then math.clamp(#self.props.changeList * 30, 30, 30 * 6) else 0) - self.motor:setGoal(Flipper.Spring.new(goalHeight, { - frequency = 5, - dampingRatio = 1, - })) - end, - }) - else nil, + Button = e("TextButton", { + BackgroundTransparency = 1, + Text = "", + Size = UDim2.new(1, 0, 1, 0), + [Roact.Event.Activated] = function(_rbx: Instance, _input: InputObject, clickCount: number) + if clickCount == 1 then + -- Double click opens the instance in explorer + self.lastDoubleClickTime = os.clock() + if props.instance then + SelectionService:Set({ props.instance }) + end + elseif clickCount == 0 then + -- Single click expands the changes + task.wait(0.25) + if os.clock() - (self.lastDoubleClickTime or 0) <= 0.25 then + -- This is a double click, so don't expand + return + end + + if props.changeList then + self.expanded = not self.expanded + local goalHeight = 30 + + (if self.expanded then math.clamp(#self.props.changeList * 30, 30, 30 * 6) else 0) + self.motor:setGoal(Flipper.Spring.new(goalHeight, { + frequency = 5, + dampingRatio = 1, + })) + end + end + end, + }, { + StateTip = if (props.instance or props.changeList) + then e(Tooltip.Trigger, { + text = (if props.changeList + then "Click to " .. (if self.expanded then "hide" else "view") .. " changes" + else "") .. (if props.instance + then (if props.changeList then " & d" else "D") .. "ouble click to open in Explorer" + else ""), + }) + else nil, + }), Expansion = if props.changeList then e(Expansion, { rendered = self.state.renderExpansion, diff --git a/plugin/src/App/Components/PatchVisualizer/init.lua b/plugin/src/App/Components/PatchVisualizer/init.lua index a751f2ff..7a3293e6 100644 --- a/plugin/src/App/Components/PatchVisualizer/init.lua +++ b/plugin/src/App/Components/PatchVisualizer/init.lua @@ -131,6 +131,7 @@ local function Tree() id = ancestorId, className = value.ClassName, name = value.Name, + instance = if typeof(value) == "Instance" then value else nil, }) previousId = ancestorId end @@ -236,6 +237,7 @@ function PatchVisualizer:buildTree(patch, instanceMap) patchType = "Edit", className = instance.ClassName, name = instance.Name, + instance = instance, hint = hint, changeList = changeList, }) @@ -271,10 +273,11 @@ function PatchVisualizer:buildTree(patch, instanceMap) patchType = "Remove", className = instance.ClassName, name = instance.Name, + instance = instance, }) end - for _, change in patch.added do + for id, change in patch.added do -- Gather ancestors from existing DOM or future additions local ancestry = {} local parentId = change.Parent @@ -344,6 +347,7 @@ function PatchVisualizer:buildTree(patch, instanceMap) name = change.Name, hint = hint, changeList = changeList, + instance = instanceMap.fromIds[id], }) end @@ -370,6 +374,7 @@ function PatchVisualizer:render() setElementHeight = setElementHeight, patchType = node.patchType, className = node.className, + instance = node.instance, name = node.name, hint = node.hint, changeList = node.changeList, From 0a932ff880f1683f91fd671c98b428c05973ec53 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 8 Jul 2023 19:31:26 -0700 Subject: [PATCH 1303/1504] Show failed to apply in visualizer (#717) Objects with failed changes will highlight, and the specific failed changes in their list will highlight as well. --- CHANGELOG.md | 2 + .../Components/PatchVisualizer/ChangeList.lua | 12 ++++-- .../PatchVisualizer/DisplayValue.lua | 6 +-- .../Components/PatchVisualizer/DomLabel.lua | 4 +- .../App/Components/PatchVisualizer/init.lua | 38 +++++++++++++++---- plugin/src/App/StatusPages/Connected.lua | 2 + plugin/src/App/Theme.lua | 2 + 7 files changed, 49 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16c90c4b..cc98fb55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ * Fix Rojo breaking when users undo/redo in Studio ([#708]) * Improved sync info text on Connected page. ([#692]) * Fix patch visualizer breaking when instances are removed during sync ([#713]) +* Patch visualizer now indicates what changes failed to apply. ([#717]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 @@ -22,6 +23,7 @@ [#708]: https://github.com/rojo-rbx/rojo/pull/708 [#692]: https://github.com/rojo-rbx/rojo/pull/692 [#713]: https://github.com/rojo-rbx/rojo/pull/713 +[#717]: https://github.com/rojo-rbx/rojo/pull/717 ## [7.3.0] - April 22, 2023 diff --git a/plugin/src/App/Components/PatchVisualizer/ChangeList.lua b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua index beb0d327..b1fa54da 100644 --- a/plugin/src/App/Components/PatchVisualizer/ChangeList.lua +++ b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua @@ -20,14 +20,13 @@ function ChangeList:render() return Theme.with(function(theme) local props = self.props local changes = props.changes + local columnVisibility = props.columnVisibility -- Color alternating rows for readability local rowTransparency = props.transparency:map(function(t) return 0.93 + (0.07 * t) end) - local columnVisibility = props.columnVisibility - local rows = {} local pad = { PaddingLeft = UDim.new(0, 5), @@ -93,6 +92,9 @@ function ChangeList:render() continue -- Skip headers, already handled above end + local metadata = values[4] + local isWarning = metadata.isWarning + rows[row] = e("Frame", { Size = UDim2.new(1, 0, 0, 30), BackgroundTransparency = row % 2 ~= 0 and rowTransparency or 1, @@ -109,11 +111,11 @@ function ChangeList:render() }), A = e("TextLabel", { Visible = columnVisibility[1], - Text = tostring(values[1]), + Text = (if isWarning then "⚠ " else "") .. tostring(values[1]), BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, TextSize = 14, - TextColor3 = theme.Settings.Setting.DescriptionColor, + TextColor3 = if isWarning then theme.Diff.Warning else theme.Settings.Setting.DescriptionColor, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = props.transparency, TextTruncate = Enum.TextTruncate.AtEnd, @@ -131,6 +133,7 @@ function ChangeList:render() e(DisplayValue, { value = values[2], transparency = props.transparency, + textColor = if isWarning then theme.Diff.Warning else theme.Settings.Setting.DescriptionColor, }) ), C = e( @@ -144,6 +147,7 @@ function ChangeList:render() e(DisplayValue, { value = values[3], transparency = props.transparency, + textColor = if isWarning then theme.Diff.Warning else theme.Settings.Setting.DescriptionColor, }) ), }) diff --git a/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua b/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua index 891ec9f2..3cf1a11a 100644 --- a/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua +++ b/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua @@ -34,7 +34,7 @@ local function DisplayValue(props) BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, TextSize = 14, - TextColor3 = theme.Settings.Setting.DescriptionColor, + TextColor3 = props.textColor, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = props.transparency, TextTruncate = Enum.TextTruncate.AtEnd, @@ -78,7 +78,7 @@ local function DisplayValue(props) BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, TextSize = 14, - TextColor3 = theme.Settings.Setting.DescriptionColor, + TextColor3 = props.textColor, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = props.transparency, TextTruncate = Enum.TextTruncate.AtEnd, @@ -95,7 +95,7 @@ local function DisplayValue(props) BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, TextSize = 14, - TextColor3 = theme.Settings.Setting.DescriptionColor, + TextColor3 = props.textColor, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = props.transparency, TextTruncate = Enum.TextTruncate.AtEnd, diff --git a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua index 351f8c31..98a4c0ff 100644 --- a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua +++ b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua @@ -180,7 +180,7 @@ function DomLabel:render() AnchorPoint = Vector2.new(0, 0.5), }), InstanceName = e("TextLabel", { - Text = props.name .. (props.hint and string.format( + Text = (if props.isWarning then "⚠ " else "") .. props.name .. (props.hint and string.format( ' %s', theme.AddressEntry.PlaceholderColor:ToHex(), props.hint @@ -189,7 +189,7 @@ function DomLabel:render() BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, TextSize = 14, - TextColor3 = theme.Settings.Setting.DescriptionColor, + TextColor3 = if props.isWarning then theme.Diff.Warning else theme.Settings.Setting.DescriptionColor, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = props.transparency, TextTruncate = Enum.TextTruncate.AtEnd, diff --git a/plugin/src/App/Components/PatchVisualizer/init.lua b/plugin/src/App/Components/PatchVisualizer/init.lua index 7a3293e6..be1fc8c6 100644 --- a/plugin/src/App/Components/PatchVisualizer/init.lua +++ b/plugin/src/App/Components/PatchVisualizer/init.lua @@ -140,6 +140,15 @@ local function Tree() return tree end +local function findUnappliedPropsForId(unappliedPatch, id) + for _, change in unappliedPatch.updated do + if change.id == id then + return change.changedProperties or {} + end + end + return {} +end + local DomLabel = require(script.DomLabel) local PatchVisualizer = Roact.Component:extend("PatchVisualizer") @@ -160,7 +169,7 @@ function PatchVisualizer:shouldUpdate(nextProps) return not PatchSet.isEqual(currentPatch, nextPatch) end -function PatchVisualizer:buildTree(patch, instanceMap) +function PatchVisualizer:buildTree(patch, unappliedPatch, instanceMap) local tree = Tree() for _, change in patch.updated do @@ -184,13 +193,15 @@ function PatchVisualizer:buildTree(patch, instanceMap) -- Gather detail text local changeList, hint = nil, nil if next(change.changedProperties) or change.changedName then + local unappliedChanges = findUnappliedPropsForId(unappliedPatch, change.id) + changeList = {} local hintBuffer, i = {}, 0 - local function addProp(prop: string, current: any?, incoming: any?) + local function addProp(prop: string, current: any?, incoming: any?, metadata: any?) i += 1 hintBuffer[i] = prop - changeList[i] = { prop, current, incoming } + changeList[i] = { prop, current, incoming, metadata } end -- Gather the changes @@ -206,7 +217,10 @@ function PatchVisualizer:buildTree(patch, instanceMap) addProp( prop, if currentSuccess then currentValue else "[Error]", - if incomingSuccess then incomingValue else next(incoming) + if incomingSuccess then incomingValue else next(incoming), + { + isWarning = unappliedChanges[prop] ~= nil + } ) end @@ -303,6 +317,8 @@ function PatchVisualizer:buildTree(patch, instanceMap) -- Gather detail text local changeList, hint = nil, nil if next(change.Properties) then + local unappliedChanges = findUnappliedPropsForId(unappliedPatch, change.Id) + changeList = {} local hintBuffer, i = {}, 0 @@ -312,9 +328,13 @@ function PatchVisualizer:buildTree(patch, instanceMap) local success, incomingValue = decodeValue(incoming, instanceMap) if success then - table.insert(changeList, { prop, "N/A", incomingValue }) + table.insert(changeList, { prop, "N/A", incomingValue, { + isWarning = unappliedChanges[prop] ~= nil + } }) else - table.insert(changeList, { prop, "N/A", next(incoming) }) + table.insert(changeList, { prop, "N/A", next(incoming), { + isWarning = unappliedChanges[prop] ~= nil + } }) end end @@ -355,10 +375,11 @@ function PatchVisualizer:buildTree(patch, instanceMap) end function PatchVisualizer:render() - local patch = self.props.patch + local patch = self.props.patch or PatchSet.newEmpty() + local unappliedPatch = self.props.unappliedPatch or PatchSet.newEmpty() local instanceMap = self.props.instanceMap - local tree = self:buildTree(patch, instanceMap) + local tree = self:buildTree(patch, unappliedPatch, instanceMap) -- Recusively draw tree local scrollElements, elementHeights = {}, {} @@ -374,6 +395,7 @@ function PatchVisualizer:render() setElementHeight = setElementHeight, patchType = node.patchType, className = node.className, + isWarning = next(findUnappliedPropsForId(unappliedPatch, node.id)) ~= nil, instance = node.instance, name = node.name, hint = node.hint, diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index ac152ef1..4c8ad548 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -84,6 +84,7 @@ function ChangesDrawer:render() columnVisibility = { true, false, true }, patch = self.props.patch, + unappliedPatch = self.props.unappliedPatch, instanceMap = self.serveSession.__instanceMap, }), }) @@ -342,6 +343,7 @@ function ConnectedPage:render() rendered = self.state.renderChanges, transparency = self.props.transparency, patch = self.props.patchData.patch, + unappliedPatch = self.props.patchData.unapplied, serveSession = self.props.serveSession, height = self.changeDrawerHeight, layoutOrder = 4, diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index 309045be..8ef05fab 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -100,6 +100,7 @@ local lightTheme = strict("LightTheme", { Remove = hexColor(0xffbdba), Edit = hexColor(0xbacdff), Row = hexColor(0x000000), + Warning = hexColor(0xFF8E3C), }, ConnectionDetails = { ProjectNameColor = hexColor(0x00000), @@ -195,6 +196,7 @@ local darkTheme = strict("DarkTheme", { Remove = hexColor(0x3F2D32), Edit = hexColor(0x193345), Row = hexColor(0xFFFFFF), + Warning = hexColor(0xFF8E3C), }, ConnectionDetails = { ProjectNameColor = hexColor(0xFFFFFF), From 7154113c13cd1fac3add676893343d0aa55afc15 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 8 Jul 2023 21:23:25 -0700 Subject: [PATCH 1304/1504] Add buttons on connected page (#722) --- CHANGELOG.md | 3 +- plugin/src/App/StatusPages/Connected.lua | 61 ++++++++++++++++-------- plugin/src/App/init.lua | 10 +++- 3 files changed, 53 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cc98fb55..675db7f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ * Improved sync info text on Connected page. ([#692]) * Fix patch visualizer breaking when instances are removed during sync ([#713]) * Patch visualizer now indicates what changes failed to apply. ([#717]) +* Add buttons for navigation on the Connected page ([#722]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 @@ -24,7 +25,7 @@ [#692]: https://github.com/rojo-rbx/rojo/pull/692 [#713]: https://github.com/rojo-rbx/rojo/pull/713 [#717]: https://github.com/rojo-rbx/rojo/pull/717 - +[#722]: https://github.com/rojo-rbx/rojo/pull/722 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index 4c8ad548..689b9022 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -12,6 +12,7 @@ local PatchSet = require(Plugin.PatchSet) local Header = require(Plugin.App.Components.Header) local IconButton = require(Plugin.App.Components.IconButton) +local TextButton = require(Plugin.App.Components.TextButton) local BorderedContainer = require(Plugin.App.Components.BorderedContainer) local Tooltip = require(Plugin.App.Components.Tooltip) local PatchVisualizer = require(Plugin.App.Components.PatchVisualizer) @@ -55,7 +56,7 @@ function ChangesDrawer:render() return e(BorderedContainer, { transparency = self.props.transparency, size = self.props.height:map(function(y) - return UDim2.new(1, 0, y, -180 * y) + return UDim2.new(1, 0, y, -220 * y) end), position = UDim2.new(0, 0, 1, 0), anchorPoint = Vector2.new(0, 1), @@ -138,22 +139,6 @@ local function ConnectionDetails(props) }), }), - Disconnect = e(IconButton, { - icon = Assets.Images.Icons.Close, - iconSize = 24, - color = theme.ConnectionDetails.DisconnectColor, - transparency = props.transparency, - - position = UDim2.new(1, 0, 0.5, 0), - anchorPoint = Vector2.new(1, 0.5), - - onClick = props.onDisconnect, - }, { - Tip = e(Tooltip.Trigger, { - text = "Disconnect from the Rojo sync server", - }), - }), - Padding = e("UIPadding", { PaddingLeft = UDim.new(0, 17), PaddingRight = UDim.new(0, 15), @@ -290,6 +275,44 @@ function ConnectedPage:render() onDisconnect = self.props.onDisconnect, }), + Buttons = e("Frame", { + Size = UDim2.new(1, 0, 0, 34), + LayoutOrder = 3, + BackgroundTransparency = 1, + ZIndex = 2, + }, { + Settings = e(TextButton, { + text = "Settings", + style = "Bordered", + transparency = self.props.transparency, + layoutOrder = 1, + onClick = self.props.onNavigateSettings, + }, { + Tip = e(Tooltip.Trigger, { + text = "View and modify plugin settings" + }), + }), + + Disconnect = e(TextButton, { + text = "Disconnect", + style = "Solid", + transparency = self.props.transparency, + layoutOrder = 2, + onClick = self.props.onDisconnect, + }, { + Tip = e(Tooltip.Trigger, { + text = "Disconnect from the Rojo sync server" + }), + }), + + Layout = e("UIListLayout", { + HorizontalAlignment = Enum.HorizontalAlignment.Right, + FillDirection = Enum.FillDirection.Horizontal, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 10), + }), + }), + ChangeInfo = e("TextButton", { Text = self.changeInfoText, Font = Enum.Font.Gotham, @@ -303,7 +326,7 @@ function ConnectedPage:render() Size = UDim2.new(1, 0, 0, 28), - LayoutOrder = 3, + LayoutOrder = 4, BackgroundTransparency = 1, [Roact.Event.MouseEnter] = function() @@ -346,7 +369,7 @@ function ConnectedPage:render() unappliedPatch = self.props.patchData.unapplied, serveSession = self.props.serveSession, height = self.changeDrawerHeight, - layoutOrder = 4, + layoutOrder = 5, onClose = function() self.changeDrawerMotor:setGoal(Flipper.Spring.new(0, { diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 762f2bbd..e569003a 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -563,6 +563,7 @@ function App:render() end, onNavigateSettings = function() + self.backPage = AppStatus.NotConnected self:setState({ appStatus = AppStatus.Settings, }) @@ -595,12 +596,19 @@ function App:render() onDisconnect = function() self:endSession() end, + + onNavigateSettings = function() + self.backPage = AppStatus.Connected + self:setState({ + appStatus = AppStatus.Settings, + }) + end, }), Settings = createPageElement(AppStatus.Settings, { onBack = function() self:setState({ - appStatus = AppStatus.NotConnected, + appStatus = self.backPage or AppStatus.NotConnected, }) end, }), From 623fa06d52a8aab01a2d267b7176186de55f1f87 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sat, 8 Jul 2023 21:41:47 -0700 Subject: [PATCH 1305/1504] Improve tooltip behavior (#723) --- CHANGELOG.md | 2 + plugin/src/App/Components/Tooltip.lua | 84 +++++++++++++++++++++------ 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 675db7f8..856ed175 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ * Fix patch visualizer breaking when instances are removed during sync ([#713]) * Patch visualizer now indicates what changes failed to apply. ([#717]) * Add buttons for navigation on the Connected page ([#722]) +* Improve tooltip behavior ([#723]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 @@ -26,6 +27,7 @@ [#713]: https://github.com/rojo-rbx/rojo/pull/713 [#717]: https://github.com/rojo-rbx/rojo/pull/717 [#722]: https://github.com/rojo-rbx/rojo/pull/722 +[#723]: https://github.com/rojo-rbx/rojo/pull/723 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/plugin/src/App/Components/Tooltip.lua b/plugin/src/App/Components/Tooltip.lua index bc3443d5..aa88d9b6 100644 --- a/plugin/src/App/Components/Tooltip.lua +++ b/plugin/src/App/Components/Tooltip.lua @@ -165,9 +165,11 @@ function Trigger:init() self.id = HttpService:GenerateGUID(false) self.ref = Roact.createRef() self.mousePos = Vector2.zero + self.showingPopup = false self.destroy = function() self.props.context.removeTip(self.id) + self.showingPopup = false end end @@ -180,31 +182,77 @@ function Trigger:willUnmount() end end +function Trigger:didUpdate(prevProps) + if prevProps.text ~= self.props.text then + -- Any existing popup is now invalid + self.props.context.removeTip(self.id) + self.showingPopup = false + + -- Let the new text propagate + self:managePopup() + end +end + +function Trigger:isHovering() + local rbx = self.ref.current + if rbx then + local pos = rbx.AbsolutePosition + local size = rbx.AbsoluteSize + local mousePos = self.mousePos + + return + mousePos.X >= pos.X and mousePos.X <= pos.X + size.X + and mousePos.Y >= pos.Y and mousePos.Y <= pos.Y + size.Y + end + return false +end + +function Trigger:managePopup() + if self:isHovering() then + if self.showingPopup or self.showDelayThread then + -- Don't duplicate popups + return + end + + self.showDelayThread = task.delay(DELAY, function() + self.props.context.addTip(self.id, { + Text = self.props.text, + Position = self.mousePos, + Trigger = self.ref, + }) + self.showDelayThread = nil + self.showingPopup = true + end) + else + if self.showDelayThread then + task.cancel(self.showDelayThread) + self.showDelayThread = nil + end + self.props.context.removeTip(self.id) + self.showingPopup = false + end +end + function Trigger:render() + local function recalculate(rbx) + local widget = rbx:FindFirstAncestorOfClass("DockWidgetPluginGui") + if not widget then return end + self.mousePos = widget:GetRelativeMousePosition() + + self:managePopup() + end + return e("Frame", { Size = UDim2.fromScale(1, 1), BackgroundTransparency = 1, ZIndex = self.props.zIndex or 100, [Roact.Ref] = self.ref, - [Roact.Event.MouseMoved] = function(_rbx, x, y) - self.mousePos = Vector2.new(x, y) - end, - [Roact.Event.MouseEnter] = function() - self.showDelayThread = task.delay(DELAY, function() - self.props.context.addTip(self.id, { - Text = self.props.text, - Position = self.mousePos, - Trigger = self.ref, - }) - end) - end, - [Roact.Event.MouseLeave] = function() - if self.showDelayThread then - task.cancel(self.showDelayThread) - end - self.props.context.removeTip(self.id) - end, + [Roact.Change.AbsolutePosition] = recalculate, + [Roact.Change.AbsoluteSize] = recalculate, + [Roact.Event.MouseMoved] = recalculate, + [Roact.Event.MouseLeave] = recalculate, + [Roact.Event.MouseEnter] = recalculate, }) end From 80eb14f9da6d24268d34ad46eab793a486816fae Mon Sep 17 00:00:00 2001 From: utrain <63367489+u-train@users.noreply.github.com> Date: Wed, 12 Jul 2023 13:00:09 -0400 Subject: [PATCH 1306/1504] Removed InstanceSnapshot snapshot_id's redudant Ref. (#730) Ref now is an optional inside, so it's redundant to have an option wrapping an option. The only snapshots that were changed were any that had a Ref within (from none to zeroed). Some also had some newlines added in the end. --- src/snapshot/instance_snapshot.rs | 9 ++++----- src/snapshot/patch_apply.rs | 4 ++-- src/snapshot/patch_compute.rs | 14 ++++++++------ src/snapshot/tests/compute.rs | 13 +++++++------ ...brojo__snapshot__tests__compute__add_child.snap | 3 ++- src/snapshot_middleware/json_model.rs | 4 ++-- src/snapshot_middleware/project.rs | 4 ++-- ...apshot_middleware__csv__test__csv_from_vfs.snap | 3 +-- ...pshot_middleware__csv__test__csv_with_meta.snap | 3 +-- ...apshot_middleware__dir__test__empty_folder.snap | 3 +-- ...ot_middleware__dir__test__folder_in_folder.snap | 5 ++--- ..._middleware__json__test__instance_from_vfs.snap | 3 +-- ...ddleware__json_model__test__model_from_vfs.snap | 5 ++--- ...e__json_model__test__model_from_vfs_legacy.snap | 5 ++--- ...hot_middleware__lua__test__client_from_vfs.snap | 3 +-- ...hot_middleware__lua__test__module_from_vfs.snap | 3 +-- ...ot_middleware__lua__test__module_with_meta.snap | 3 +-- ...hot_middleware__lua__test__script_disabled.snap | 3 +-- ...ot_middleware__lua__test__script_with_meta.snap | 3 +-- ...hot_middleware__lua__test__server_from_vfs.snap | 3 +-- ...e__project__test__project_from_direct_file.snap | 3 ++- ...ect__test__project_path_property_overrides.snap | 3 +-- ...ware__project__test__project_with_children.snap | 5 +++-- ...roject__test__project_with_path_to_project.snap | 3 ++- ...project_with_path_to_project_with_children.snap | 5 +++-- ...e__project__test__project_with_path_to_txt.snap | 3 +-- ...ct__test__project_with_resolved_properties.snap | 3 +-- ...__test__project_with_unresolved_properties.snap | 3 +-- ...t_middleware__txt__test__instance_from_vfs.snap | 3 +-- 29 files changed, 58 insertions(+), 69 deletions(-) diff --git a/src/snapshot/instance_snapshot.rs b/src/snapshot/instance_snapshot.rs index 36c51821..0b3a4fca 100644 --- a/src/snapshot/instance_snapshot.rs +++ b/src/snapshot/instance_snapshot.rs @@ -17,9 +17,8 @@ use super::InstanceMetadata; // - Replace use of Variant with a sum of Variant + borrowed value #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] pub struct InstanceSnapshot { - // FIXME: Don't use Option anymore! /// A temporary ID applied to the snapshot that's used for Ref properties. - pub snapshot_id: Option, + pub snapshot_id: Ref, /// Rojo-specific metadata associated with the instance. pub metadata: InstanceMetadata, @@ -42,7 +41,7 @@ pub struct InstanceSnapshot { impl InstanceSnapshot { pub fn new() -> Self { Self { - snapshot_id: None, + snapshot_id: Ref::none(), metadata: InstanceMetadata::default(), name: Cow::Borrowed("DEFAULT"), class_name: Cow::Borrowed("DEFAULT"), @@ -88,7 +87,7 @@ impl InstanceSnapshot { } } - pub fn snapshot_id(self, snapshot_id: Option) -> Self { + pub fn snapshot_id(self, snapshot_id: Ref) -> Self { Self { snapshot_id, ..self @@ -120,7 +119,7 @@ impl InstanceSnapshot { .collect(); Self { - snapshot_id: Some(id), + snapshot_id: id, metadata: InstanceMetadata::default(), name: Cow::Owned(instance.name), class_name: Cow::Owned(instance.class), diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index 5818776c..572b8455 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -135,7 +135,7 @@ fn apply_add_child( context.has_refs_to_rewrite.insert(id); } - if let Some(snapshot_id) = snapshot_id { + if snapshot_id.is_some() { context.snapshot_id_to_instance_id.insert(snapshot_id, id); } @@ -231,7 +231,7 @@ mod test { let root_id = tree.get_root_id(); let snapshot = InstanceSnapshot { - snapshot_id: None, + snapshot_id: Ref::none(), metadata: Default::default(), name: Cow::Borrowed("Foo"), class_name: Cow::Borrowed("Bar"), diff --git a/src/snapshot/patch_compute.rs b/src/snapshot/patch_compute.rs index f5d5a67b..5d7abc69 100644 --- a/src/snapshot/patch_compute.rs +++ b/src/snapshot/patch_compute.rs @@ -77,8 +77,10 @@ fn compute_patch_set_internal( id: Ref, patch_set: &mut PatchSet, ) { - if let Some(snapshot_id) = snapshot.snapshot_id { - context.snapshot_id_to_instance_id.insert(snapshot_id, id); + if snapshot.snapshot_id.is_some() { + context + .snapshot_id_to_instance_id + .insert(snapshot.snapshot_id, id); } let instance = tree @@ -244,7 +246,7 @@ mod test { // addition of a prop named Self, which is a self-referential Ref. let snapshot_id = Ref::new(); let snapshot = InstanceSnapshot { - snapshot_id: Some(snapshot_id), + snapshot_id: snapshot_id, properties: hashmap! { "Self".to_owned() => Variant::Ref(snapshot_id), }, @@ -286,13 +288,13 @@ mod test { // This patch describes the existing instance with a new child added. let snapshot_id = Ref::new(); let snapshot = InstanceSnapshot { - snapshot_id: Some(snapshot_id), + snapshot_id: snapshot_id, children: vec![InstanceSnapshot { properties: hashmap! { "Self".to_owned() => Variant::Ref(snapshot_id), }, - snapshot_id: None, + snapshot_id: Ref::none(), metadata: Default::default(), name: Cow::Borrowed("child"), class_name: Cow::Borrowed("child"), @@ -311,7 +313,7 @@ mod test { added_instances: vec![PatchAdd { parent_id: root_id, instance: InstanceSnapshot { - snapshot_id: None, + snapshot_id: Ref::none(), metadata: Default::default(), properties: hashmap! { "Self".to_owned() => Variant::Ref(root_id), diff --git a/src/snapshot/tests/compute.rs b/src/snapshot/tests/compute.rs index 309d73b6..fc6a0b63 100644 --- a/src/snapshot/tests/compute.rs +++ b/src/snapshot/tests/compute.rs @@ -3,6 +3,7 @@ use std::borrow::Cow; use insta::assert_yaml_snapshot; use maplit::hashmap; +use rbx_dom_weak::types::Ref; use rojo_insta_ext::RedactionMap; use crate::snapshot::{compute_patch_set, InstanceSnapshot, RojoTree}; @@ -15,7 +16,7 @@ fn set_name_and_class_name() { redactions.intern(tree.get_root_id()); let snapshot = InstanceSnapshot { - snapshot_id: None, + snapshot_id: Ref::none(), metadata: Default::default(), name: Cow::Borrowed("Some Folder"), class_name: Cow::Borrowed("Folder"), @@ -37,7 +38,7 @@ fn set_property() { redactions.intern(tree.get_root_id()); let snapshot = InstanceSnapshot { - snapshot_id: None, + snapshot_id: Ref::none(), metadata: Default::default(), name: Cow::Borrowed("ROOT"), class_name: Cow::Borrowed("ROOT"), @@ -70,7 +71,7 @@ fn remove_property() { } let snapshot = InstanceSnapshot { - snapshot_id: None, + snapshot_id: Ref::none(), metadata: Default::default(), name: Cow::Borrowed("ROOT"), class_name: Cow::Borrowed("ROOT"), @@ -92,13 +93,13 @@ fn add_child() { redactions.intern(tree.get_root_id()); let snapshot = InstanceSnapshot { - snapshot_id: None, + snapshot_id: Ref::none(), metadata: Default::default(), name: Cow::Borrowed("ROOT"), class_name: Cow::Borrowed("ROOT"), properties: Default::default(), children: vec![InstanceSnapshot { - snapshot_id: None, + snapshot_id: Ref::none(), metadata: Default::default(), name: Cow::Borrowed("New"), class_name: Cow::Borrowed("Folder"), @@ -131,7 +132,7 @@ fn remove_child() { } let snapshot = InstanceSnapshot { - snapshot_id: None, + snapshot_id: Ref::none(), metadata: Default::default(), name: Cow::Borrowed("ROOT"), class_name: Cow::Borrowed("ROOT"), diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap index 97bd639e..c4695b7c 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap @@ -6,7 +6,7 @@ removed_instances: [] added_instances: - parent_id: id-1 instance: - snapshot_id: ~ + snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false relevant_paths: [] @@ -16,3 +16,4 @@ added_instances: properties: {} children: [] updated_instances: [] + diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 0f1388e4..b38c47a7 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, collections::HashMap, path::Path, str}; use anyhow::Context; use memofs::Vfs; -use rbx_dom_weak::types::Attributes; +use rbx_dom_weak::types::{Attributes, Ref}; use serde::Deserialize; use crate::{ @@ -112,7 +112,7 @@ impl JsonModel { } Ok(InstanceSnapshot { - snapshot_id: None, + snapshot_id: Ref::none(), metadata: Default::default(), name: Cow::Owned(name), class_name: Cow::Owned(class_name), diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index f8fa7920..2d54a179 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -2,7 +2,7 @@ use std::{borrow::Cow, collections::HashMap, path::Path}; use anyhow::{bail, Context}; use memofs::Vfs; -use rbx_dom_weak::types::Attributes; +use rbx_dom_weak::types::{Attributes, Ref}; use rbx_reflection::ClassTag; use crate::{ @@ -271,7 +271,7 @@ pub fn snapshot_project_node( )); Ok(Some(InstanceSnapshot { - snapshot_id: None, + snapshot_id: Ref::none(), name, class_name, properties, diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap index 7a685efb..11a8d81c 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/csv.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap index 70bae90d..eda82606 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/csv.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: true instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap index 948dda0b..e59da8db 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/dir.rs -assertion_line: 127 expression: instance_snapshot --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap index cf07b0ed..8c2ee9cc 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/dir.rs -assertion_line: 148 expression: instance_snapshot --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false instigating_source: @@ -23,7 +22,7 @@ name: foo class_name: Folder properties: {} children: - - snapshot_id: ~ + - snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap index 75329b85..b1cca7cb 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/json.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap index a6a0743e..5d4db1fc 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/json_model.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false instigating_source: @@ -17,7 +16,7 @@ properties: Value: Int64: 5 children: - - snapshot_id: ~ + - snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false relevant_paths: [] diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap index a58fdb0f..5d4db1fc 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/json_model.rs -assertion_line: 186 expression: instance_snapshot --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false instigating_source: @@ -17,7 +16,7 @@ properties: Value: Int64: 5 children: - - snapshot_id: ~ + - snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false relevant_paths: [] diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__client_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__client_from_vfs.snap index f774f561..40b4bbe2 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__client_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__client_from_vfs.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/lua.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_from_vfs.snap index ac9ac72a..6877e9a9 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_from_vfs.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/lua.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_with_meta.snap index f623955f..8dcc57a9 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_with_meta.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/lua.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: true instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_disabled.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_disabled.snap index 8a9b4776..3f040877 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_disabled.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_disabled.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/lua.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_with_meta.snap index 1234b48a..6bdd2a38 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_with_meta.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/lua.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: true instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__server_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__server_from_vfs.snap index 76473c75..63d33a0a 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__server_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__server_from_vfs.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/lua.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap index 42393420..795b14c1 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap @@ -2,7 +2,7 @@ source: src/snapshot_middleware/project.rs expression: instance_snapshot --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: true instigating_source: @@ -14,3 +14,4 @@ name: direct-project class_name: Model properties: {} children: [] + diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap index 49b3b506..7427c9dc 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/project.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: true instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap index ccf6b535..b50eb1be 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap @@ -2,7 +2,7 @@ source: src/snapshot_middleware/project.rs expression: instance_snapshot --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: true instigating_source: @@ -14,7 +14,7 @@ name: children class_name: Folder properties: {} children: - - snapshot_id: ~ + - snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: true instigating_source: @@ -29,3 +29,4 @@ children: class_name: Model properties: {} children: [] + diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap index a520b7c7..d64a46e7 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap @@ -2,7 +2,7 @@ source: src/snapshot_middleware/project.rs expression: instance_snapshot --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: true instigating_source: @@ -15,3 +15,4 @@ name: path-project class_name: Model properties: {} children: [] + diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap index c71b4d2d..0ceb043a 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap @@ -2,7 +2,7 @@ source: src/snapshot_middleware/project.rs expression: instance_snapshot --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: true instigating_source: @@ -15,7 +15,7 @@ name: path-child-project class_name: Folder properties: {} children: - - snapshot_id: ~ + - snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: true instigating_source: @@ -30,3 +30,4 @@ children: class_name: Model properties: {} children: [] + diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap index 38b797c3..51a222f9 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/project.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap index 29a23a07..9b8e91ef 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/project.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: true instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap index a422e9f8..a07300bb 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/project.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: true instigating_source: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap index ad469490..b8a8d4af 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap @@ -1,9 +1,8 @@ --- source: src/snapshot_middleware/txt.rs expression: instance_snapshot - --- -snapshot_id: ~ +snapshot_id: "00000000000000000000000000000000" metadata: ignore_unknown_instances: false instigating_source: From 28d48a76e34811b4385afea1a570de3ba561447c Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 12 Jul 2023 10:01:21 -0700 Subject: [PATCH 1307/1504] Fix tooltips crashing on thread cancellation edge cases (#727) --- plugin/src/App/Components/Tooltip.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/App/Components/Tooltip.lua b/plugin/src/App/Components/Tooltip.lua index aa88d9b6..9c1fb151 100644 --- a/plugin/src/App/Components/Tooltip.lua +++ b/plugin/src/App/Components/Tooltip.lua @@ -175,7 +175,7 @@ end function Trigger:willUnmount() if self.showDelayThread then - task.cancel(self.showDelayThread) + pcall(task.cancel, self.showDelayThread) end if self.destroy then self.destroy() @@ -225,7 +225,7 @@ function Trigger:managePopup() end) else if self.showDelayThread then - task.cancel(self.showDelayThread) + pcall(task.cancel, self.showDelayThread) self.showDelayThread = nil end self.props.context.removeTip(self.id) From 9d48af2b505d5043927ab2ad9c6ff09995ae47c7 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 12 Jul 2023 13:00:07 -0700 Subject: [PATCH 1308/1504] Better settings control (#725) - Lock some settings during sync - Make experimental features more clearly labelled --- CHANGELOG.md | 2 ++ plugin/src/App/Components/Checkbox.lua | 13 +++++++++---- plugin/src/App/Components/Dropdown.lua | 12 ++++++++++-- plugin/src/App/StatusPages/Settings/Setting.lua | 11 ++++++++--- plugin/src/App/StatusPages/Settings/init.lua | 8 ++++++-- plugin/src/App/init.lua | 2 ++ plugin/src/Assets.lua | 2 ++ 7 files changed, 39 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 856ed175..e36fb581 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ * Patch visualizer now indicates what changes failed to apply. ([#717]) * Add buttons for navigation on the Connected page ([#722]) * Improve tooltip behavior ([#723]) +* Better settings controls ([#725]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 @@ -28,6 +29,7 @@ [#717]: https://github.com/rojo-rbx/rojo/pull/717 [#722]: https://github.com/rojo-rbx/rojo/pull/722 [#723]: https://github.com/rojo-rbx/rojo/pull/723 +[#725]: https://github.com/rojo-rbx/rojo/pull/725 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/plugin/src/App/Components/Checkbox.lua b/plugin/src/App/Components/Checkbox.lua index 21ec56b3..aa351b1f 100644 --- a/plugin/src/App/Components/Checkbox.lua +++ b/plugin/src/App/Components/Checkbox.lua @@ -51,10 +51,15 @@ function Checkbox:render() ZIndex = self.props.zIndex, BackgroundTransparency = 1, - [Roact.Event.Activated] = self.props.onClick, + [Roact.Event.Activated] = function() + if self.props.locked then return end + self.props.onClick() + end, }, { StateTip = e(Tooltip.Trigger, { - text = if self.props.active then "Enabled" else "Disabled", + text = + (if self.props.locked then "[LOCKED] " else "") + .. (if self.props.active then "Enabled" else "Disabled"), }), Active = e(SlicedImage, { @@ -65,7 +70,7 @@ function Checkbox:render() zIndex = 2, }, { Icon = e("ImageLabel", { - Image = Assets.Images.Checkbox.Active, + Image = if self.props.locked then Assets.Images.Checkbox.Locked else Assets.Images.Checkbox.Active, ImageColor3 = theme.Active.IconColor, ImageTransparency = activeTransparency, @@ -84,7 +89,7 @@ function Checkbox:render() size = UDim2.new(1, 0, 1, 0), }, { Icon = e("ImageLabel", { - Image = Assets.Images.Checkbox.Inactive, + Image = if self.props.locked then Assets.Images.Checkbox.Locked else Assets.Images.Checkbox.Inactive, ImageColor3 = theme.Inactive.IconColor, ImageTransparency = self.props.transparency, diff --git a/plugin/src/App/Components/Dropdown.lua b/plugin/src/App/Components/Dropdown.lua index ef9a4211..21a60908 100644 --- a/plugin/src/App/Components/Dropdown.lua +++ b/plugin/src/App/Components/Dropdown.lua @@ -29,7 +29,13 @@ function Dropdown:init() }) end -function Dropdown:didUpdate() +function Dropdown:didUpdate(prevProps) + if self.props.locked and not prevProps.locked then + self:setState({ + open = false, + }) + end + self.openMotor:setGoal( Flipper.Spring.new(self.state.open and 1 or 0, { frequency = 6, @@ -68,6 +74,7 @@ function Dropdown:render() Font = Enum.Font.GothamMedium, [Roact.Event.Activated] = function() + if self.props.locked then return end self:setState({ open = false, }) @@ -89,6 +96,7 @@ function Dropdown:render() BackgroundTransparency = 1, [Roact.Event.Activated] = function() + if self.props.locked then return end self:setState({ open = not self.state.open, }) @@ -101,7 +109,7 @@ function Dropdown:render() size = UDim2.new(1, 0, 1, 0), }, { DropArrow = e("ImageLabel", { - Image = Assets.Images.Dropdown.Arrow, + Image = if self.props.locked then Assets.Images.Dropdown.Locked else Assets.Images.Dropdown.Arrow, ImageColor3 = self.openBinding:map(function(a) return theme.Closed.IconColor:Lerp(theme.Open.IconColor, a) end), diff --git a/plugin/src/App/StatusPages/Settings/Setting.lua b/plugin/src/App/StatusPages/Settings/Setting.lua index 0c0de9f4..79e83e23 100644 --- a/plugin/src/App/StatusPages/Settings/Setting.lua +++ b/plugin/src/App/StatusPages/Settings/Setting.lua @@ -67,6 +67,7 @@ function Setting:render() }, { Input = if self.props.options ~= nil then e(Dropdown, { + locked = self.props.locked, options = self.props.options, active = self.state.setting, transparency = self.props.transparency, @@ -78,6 +79,7 @@ function Setting:render() }) else e(Checkbox, { + locked = self.props.locked, active = self.state.setting, transparency = self.props.transparency, position = UDim2.new(1, 0, 0.5, 0), @@ -106,12 +108,13 @@ function Setting:render() BackgroundTransparency = 1, }, { Name = e("TextLabel", { - Text = self.props.name, + Text = (if self.props.experimental then "⚠ " else "") .. self.props.name, Font = Enum.Font.GothamBold, TextSize = 17, TextColor3 = theme.Setting.NameColor, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = self.props.transparency, + RichText = true, Size = UDim2.new(1, 0, 0, 17), @@ -120,7 +123,7 @@ function Setting:render() }), Description = e("TextLabel", { - Text = self.props.description, + Text = (if self.props.experimental then "[Experimental] " else "") .. self.props.description, Font = Enum.Font.Gotham, LineHeight = 1.2, TextSize = 14, @@ -128,11 +131,13 @@ function Setting:render() TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = self.props.transparency, TextWrapped = true, + RichText = true, Size = self.containerSize:map(function(value) + local desc = (if self.props.experimental then "[Experimental] " else "") .. self.props.description local offset = (self.props.onReset and 34 or 0) + (self.props.options ~= nil and 120 or 40) local textBounds = getTextBounds( - self.props.description, 14, Enum.Font.Gotham, 1.2, + desc, 14, Enum.Font.Gotham, 1.2, Vector2.new(value.X - offset, math.huge) ) return UDim2.new(1, -offset, 0, textBounds.Y) diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua index f83e145c..298e39a4 100644 --- a/plugin/src/App/StatusPages/Settings/init.lua +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -115,7 +115,9 @@ function SettingsPage:render() OpenScriptsExternally = e(Setting, { id = "openScriptsExternally", name = "Open Scripts Externally", - description = "EXPERIMENTAL! Attempt to open scripts in an external editor", + description = "Attempt to open scripts in an external editor", + locked = self.props.syncActive, + experimental = true, transparency = self.props.transparency, layoutOrder = 4, }), @@ -123,7 +125,9 @@ function SettingsPage:render() TwoWaySync = e(Setting, { id = "twoWaySync", name = "Two-Way Sync", - description = "EXPERIMENTAL! Editing files in Studio will sync them into the filesystem", + description = "Editing files in Studio will sync them into the filesystem", + locked = self.props.syncActive, + experimental = true, transparency = self.props.transparency, layoutOrder = 5, }), diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index e569003a..fd534d0c 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -606,6 +606,8 @@ function App:render() }), Settings = createPageElement(AppStatus.Settings, { + syncActive = self.serveSession ~= nil and self.serveSession:getStatus() == ServeSession.Status.Connected, + onBack = function() self:setState({ appStatus = self.backPage or AppStatus.NotConnected, diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index 3c919b54..020ec3eb 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -33,9 +33,11 @@ local Assets = { Checkbox = { Active = "rbxassetid://6016251644", Inactive = "rbxassetid://6016251963", + Locked = "rbxassetid://14011257320", }, Dropdown = { Arrow = "rbxassetid://10131770538", + Locked = "rbxassetid://14011257320", }, Spinner = { Foreground = "rbxassetid://3222731032", From 6e40993199b9f7891bef11a095f3acb5086c8f2b Mon Sep 17 00:00:00 2001 From: boatbomber Date: Thu, 13 Jul 2023 20:09:19 -0700 Subject: [PATCH 1309/1504] Rework patch visualizer with many fixes and improvements (#726) - Reconciler now has precommit and postcommit hooks for patch applying - This is used to compute a patch tree snapshot precommit and update the tree metadata postcommit - PatchVisualizer can now display Removes that happened during sync - It was previously missing because the removed objects no longer existed so it couldn't get any info on them (This is resolved because the info is gotten in precommit, before the instance was removed) - PatchVisualizer now shows Old and New values instead of just Incoming during sync - (Still displays Current and Incoming during confirmation) - This is much more useful, since you now see what the changes were and not just which things were changed - PatchVisualizer displays clarifying message when initial sync has no changes instead of just showing a blank box - Objects in the tree UI no longer get stuck expanded when the next patch has the same instance but different info on it - Objects in the tree UI correctly become selectable after their instance is added and unclickable when removed during sync --- CHANGELOG.md | 2 + .../Components/PatchVisualizer/ChangeList.lua | 11 +- .../Components/PatchVisualizer/DomLabel.lua | 20 +- .../App/Components/PatchVisualizer/init.lua | 464 +++--------------- plugin/src/App/StatusPages/Confirming.lua | 2 +- plugin/src/App/StatusPages/Connected.lua | 8 +- plugin/src/App/init.lua | 28 +- plugin/src/PatchTree.lua | 434 ++++++++++++++++ plugin/src/Reconciler/init.lua | 57 ++- 9 files changed, 612 insertions(+), 414 deletions(-) create mode 100644 plugin/src/PatchTree.lua diff --git a/CHANGELOG.md b/CHANGELOG.md index e36fb581..130175e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ * Add buttons for navigation on the Connected page ([#722]) * Improve tooltip behavior ([#723]) * Better settings controls ([#725]) +* Rework patch visualizer with many fixes and improvements ([#726]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 @@ -30,6 +31,7 @@ [#722]: https://github.com/rojo-rbx/rojo/pull/722 [#723]: https://github.com/rojo-rbx/rojo/pull/723 [#725]: https://github.com/rojo-rbx/rojo/pull/725 +[#726]: https://github.com/rojo-rbx/rojo/pull/726 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/plugin/src/App/Components/PatchVisualizer/ChangeList.lua b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua index b1fa54da..ed6da37a 100644 --- a/plugin/src/App/Components/PatchVisualizer/ChangeList.lua +++ b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua @@ -8,6 +8,8 @@ local Theme = require(Plugin.App.Theme) local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) local DisplayValue = require(script.Parent.DisplayValue) +local EMPTY_TABLE = {} + local e = Roact.createElement local ChangeList = Roact.Component:extend("ChangeList") @@ -20,7 +22,6 @@ function ChangeList:render() return Theme.with(function(theme) local props = self.props local changes = props.changes - local columnVisibility = props.columnVisibility -- Color alternating rows for readability local rowTransparency = props.transparency:map(function(t) @@ -47,7 +48,6 @@ function ChangeList:render() VerticalAlignment = Enum.VerticalAlignment.Center, }), A = e("TextLabel", { - Visible = columnVisibility[1], Text = tostring(changes[1][1]), BackgroundTransparency = 1, Font = Enum.Font.GothamBold, @@ -60,7 +60,6 @@ function ChangeList:render() LayoutOrder = 1, }), B = e("TextLabel", { - Visible = columnVisibility[2], Text = tostring(changes[1][2]), BackgroundTransparency = 1, Font = Enum.Font.GothamBold, @@ -73,7 +72,6 @@ function ChangeList:render() LayoutOrder = 2, }), C = e("TextLabel", { - Visible = columnVisibility[3], Text = tostring(changes[1][3]), BackgroundTransparency = 1, Font = Enum.Font.GothamBold, @@ -92,7 +90,7 @@ function ChangeList:render() continue -- Skip headers, already handled above end - local metadata = values[4] + local metadata = values[4] or EMPTY_TABLE local isWarning = metadata.isWarning rows[row] = e("Frame", { @@ -110,7 +108,6 @@ function ChangeList:render() VerticalAlignment = Enum.VerticalAlignment.Center, }), A = e("TextLabel", { - Visible = columnVisibility[1], Text = (if isWarning then "⚠ " else "") .. tostring(values[1]), BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, @@ -125,7 +122,6 @@ function ChangeList:render() B = e( "Frame", { - Visible = columnVisibility[2], BackgroundTransparency = 1, Size = UDim2.new(0.35, 0, 1, 0), LayoutOrder = 2, @@ -139,7 +135,6 @@ function ChangeList:render() C = e( "Frame", { - Visible = columnVisibility[3], BackgroundTransparency = 1, Size = UDim2.new(0.35, 0, 1, 0), LayoutOrder = 3, diff --git a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua index 98a4c0ff..facf70cd 100644 --- a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua +++ b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua @@ -34,7 +34,6 @@ function Expansion:render() ChangeList = e(ChangeList, { changes = props.changeList, transparency = props.transparency, - columnVisibility = props.columnVisibility, }), }) end @@ -71,6 +70,22 @@ function DomLabel:init() end) end +function DomLabel:didUpdate(prevProps) + if + prevProps.instance ~= self.props.instance + or prevProps.patchType ~= self.props.patchType + or prevProps.name ~= self.props.name + or prevProps.changeList ~= self.props.changeList + then + -- Close the expansion when the domlabel is changed to a different thing + self.expanded = false + self.motor:setGoal(Flipper.Spring.new(30, { + frequency = 5, + dampingRatio = 1, + })) + end +end + function DomLabel:render() local props = self.props @@ -130,7 +145,7 @@ function DomLabel:render() if props.changeList then self.expanded = not self.expanded local goalHeight = 30 - + (if self.expanded then math.clamp(#self.props.changeList * 30, 30, 30 * 6) else 0) + + (if self.expanded then math.clamp(#props.changeList * 30, 30, 30 * 6) else 0) self.motor:setGoal(Flipper.Spring.new(goalHeight, { frequency = 5, dampingRatio = 1, @@ -155,7 +170,6 @@ function DomLabel:render() indent = indent, transparency = props.transparency, changeList = props.changeList, - columnVisibility = props.columnVisibility, }) else nil, DiffIcon = if props.patchType diff --git a/plugin/src/App/Components/PatchVisualizer/init.lua b/plugin/src/App/Components/PatchVisualizer/init.lua index be1fc8c6..73af4502 100644 --- a/plugin/src/App/Components/PatchVisualizer/init.lua +++ b/plugin/src/App/Components/PatchVisualizer/init.lua @@ -1,154 +1,18 @@ -local HttpService = game:GetService("HttpService") - local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin local Packages = Rojo.Packages local Roact = require(Packages.Roact) -local Log = require(Packages.Log) -local Types = require(Plugin.Types) +local PatchTree = require(Plugin.PatchTree) local PatchSet = require(Plugin.PatchSet) -local decodeValue = require(Plugin.Reconciler.decodeValue) -local getProperty = require(Plugin.Reconciler.getProperty) +local Theme = require(Plugin.App.Theme) local BorderedContainer = require(Plugin.App.Components.BorderedContainer) local VirtualScroller = require(Plugin.App.Components.VirtualScroller) local e = Roact.createElement -local function alphabeticalNext(t, state) - -- Equivalent of the next function, but returns the keys in the alphabetic - -- order of node names. We use a temporary ordered key table that is stored in the - -- table being iterated. - - local key = nil - if state == nil then - -- First iteration, generate the index - local orderedIndex, i = table.create(5), 0 - for k in t do - i += 1 - orderedIndex[i] = k - end - table.sort(orderedIndex, function(a, b) - local nodeA, nodeB = t[a], t[b] - return (nodeA.name or "") < (nodeB.name or "") - end) - - t.__orderedIndex = orderedIndex - key = orderedIndex[1] - else - -- Fetch the next value - for i, orderedState in t.__orderedIndex do - if orderedState == state then - key = t.__orderedIndex[i + 1] - break - end - end - end - - if key then - return key, t[key] - end - - -- No more value to return, cleanup - t.__orderedIndex = nil - return -end - -local function alphabeticalPairs(t) - -- Equivalent of the pairs() iterator, but sorted - return alphabeticalNext, t, nil -end - -local function Tree() - local tree = { - idToNode = {}, - ROOT = { - className = "DataModel", - name = "ROOT", - children = {}, - }, - } - -- Add ROOT to idToNode or it won't be found by getNode since that searches *within* ROOT - tree.idToNode["ROOT"] = tree.ROOT - - function tree:getNode(id, target) - if self.idToNode[id] then - return self.idToNode[id] - end - - for nodeId, node in target or tree.ROOT.children do - if nodeId == id then - self.idToNode[id] = node - return node - end - local descendant = self:getNode(id, node.children) - if descendant then - return descendant - end - end - - return nil - end - - function tree:addNode(parent, props) - parent = parent or "ROOT" - - local node = self:getNode(props.id) - if node then - for k, v in props do - node[k] = v - end - return node - end - - node = table.clone(props) - node.children = {} - - local parentNode = self:getNode(parent) - if not parentNode then - Log.warn("Failed to create node since parent doesnt exist: {}, {}", parent, props) - return - end - - parentNode.children[node.id] = node - self.idToNode[node.id] = node - - return node - end - - function tree:buildAncestryNodes(ancestry, patch, instanceMap) - -- Build nodes for ancestry by going up the tree - local previousId = "ROOT" - for _, ancestorId in ancestry do - local value = instanceMap.fromIds[ancestorId] or patch.added[ancestorId] - if not value then - Log.warn("Failed to find ancestor object for " .. ancestorId) - continue - end - self:addNode(previousId, { - id = ancestorId, - className = value.ClassName, - name = value.Name, - instance = if typeof(value) == "Instance" then value else nil, - }) - previousId = ancestorId - end - end - - return tree -end - -local function findUnappliedPropsForId(unappliedPatch, id) - for _, change in unappliedPatch.updated do - if change.id == id then - return change.changedProperties or {} - end - end - return {} -end - local DomLabel = require(script.DomLabel) local PatchVisualizer = Roact.Component:extend("PatchVisualizer") @@ -164,274 +28,90 @@ function PatchVisualizer:willUnmount() end function PatchVisualizer:shouldUpdate(nextProps) + if self.props.patchTree ~= nextProps.patchTree then + return true + end + local currentPatch, nextPatch = self.props.patch, nextProps.patch - - return not PatchSet.isEqual(currentPatch, nextPatch) -end - -function PatchVisualizer:buildTree(patch, unappliedPatch, instanceMap) - local tree = Tree() - - for _, change in patch.updated do - local instance = instanceMap.fromIds[change.id] - if not instance then - continue - end - - -- Gather ancestors from existing DOM - local ancestry = {} - local parentObject = instance.Parent - local parentId = instanceMap.fromInstances[parentObject] - while parentObject do - table.insert(ancestry, 1, parentId) - parentObject = parentObject.Parent - parentId = instanceMap.fromInstances[parentObject] - end - - tree:buildAncestryNodes(ancestry, patch, instanceMap) - - -- Gather detail text - local changeList, hint = nil, nil - if next(change.changedProperties) or change.changedName then - local unappliedChanges = findUnappliedPropsForId(unappliedPatch, change.id) - - changeList = {} - - local hintBuffer, i = {}, 0 - local function addProp(prop: string, current: any?, incoming: any?, metadata: any?) - i += 1 - hintBuffer[i] = prop - changeList[i] = { prop, current, incoming, metadata } - end - - -- Gather the changes - - if change.changedName then - addProp("Name", instance.Name, change.changedName) - end - - for prop, incoming in change.changedProperties do - local incomingSuccess, incomingValue = decodeValue(incoming, instanceMap) - local currentSuccess, currentValue = getProperty(instance, prop) - - addProp( - prop, - if currentSuccess then currentValue else "[Error]", - if incomingSuccess then incomingValue else next(incoming), - { - isWarning = unappliedChanges[prop] ~= nil - } - ) - end - - -- Finalize detail values - - -- Trim hint to top 3 - table.sort(hintBuffer) - if #hintBuffer > 3 then - hintBuffer = { - hintBuffer[1], - hintBuffer[2], - hintBuffer[3], - i - 3 .. " more", - } - end - hint = table.concat(hintBuffer, ", ") - - -- Sort changes and add header - table.sort(changeList, function(a, b) - return a[1] < b[1] - end) - table.insert(changeList, 1, { "Property", "Current", "Incoming" }) - end - - -- Add this node to tree - tree:addNode(instanceMap.fromInstances[instance.Parent], { - id = change.id, - patchType = "Edit", - className = instance.ClassName, - name = instance.Name, - instance = instance, - hint = hint, - changeList = changeList, - }) + if currentPatch ~= nil or nextPatch ~= nil then + return not PatchSet.isEqual(currentPatch, nextPatch) end - for _, idOrInstance in patch.removed do - local instance = if Types.RbxId(idOrInstance) then instanceMap.fromIds[idOrInstance] else idOrInstance - if not instance then - -- If we're viewing a past patch, the instance is already removed - -- and we therefore cannot get the tree for it anymore - continue - end - - -- Gather ancestors from existing DOM - -- (note that they may have no ID if they're being removed as unknown) - local ancestry = {} - local parentObject = instance.Parent - local parentId = instanceMap.fromInstances[parentObject] or HttpService:GenerateGUID(false) - while parentObject do - instanceMap:insert(parentId, parentObject) - table.insert(ancestry, 1, parentId) - parentObject = parentObject.Parent - parentId = instanceMap.fromInstances[parentObject] or HttpService:GenerateGUID(false) - end - - tree:buildAncestryNodes(ancestry, patch, instanceMap) - - -- Add this node to tree - local nodeId = instanceMap.fromInstances[instance] or HttpService:GenerateGUID(false) - instanceMap:insert(nodeId, instance) - tree:addNode(instanceMap.fromInstances[instance.Parent], { - id = nodeId, - patchType = "Remove", - className = instance.ClassName, - name = instance.Name, - instance = instance, - }) - end - - for id, change in patch.added do - -- Gather ancestors from existing DOM or future additions - local ancestry = {} - local parentId = change.Parent - local parentData = patch.added[parentId] - local parentObject = instanceMap.fromIds[parentId] - while parentId do - table.insert(ancestry, 1, parentId) - parentId = nil - - if parentData then - parentId = parentData.Parent - parentData = patch.added[parentId] - parentObject = instanceMap.fromIds[parentId] - elseif parentObject then - parentObject = parentObject.Parent - parentId = instanceMap.fromInstances[parentObject] - parentData = patch.added[parentId] - end - end - - tree:buildAncestryNodes(ancestry, patch, instanceMap) - - -- Gather detail text - local changeList, hint = nil, nil - if next(change.Properties) then - local unappliedChanges = findUnappliedPropsForId(unappliedPatch, change.Id) - - changeList = {} - - local hintBuffer, i = {}, 0 - for prop, incoming in change.Properties do - i += 1 - hintBuffer[i] = prop - - local success, incomingValue = decodeValue(incoming, instanceMap) - if success then - table.insert(changeList, { prop, "N/A", incomingValue, { - isWarning = unappliedChanges[prop] ~= nil - } }) - else - table.insert(changeList, { prop, "N/A", next(incoming), { - isWarning = unappliedChanges[prop] ~= nil - } }) - end - end - - -- Finalize detail values - - -- Trim hint to top 3 - table.sort(hintBuffer) - if #hintBuffer > 3 then - hintBuffer = { - hintBuffer[1], - hintBuffer[2], - hintBuffer[3], - i - 3 .. " more", - } - end - hint = table.concat(hintBuffer, ", ") - - -- Sort changes and add header - table.sort(changeList, function(a, b) - return a[1] < b[1] - end) - table.insert(changeList, 1, { "Property", "Current", "Incoming" }) - end - - -- Add this node to tree - tree:addNode(change.Parent, { - id = change.Id, - patchType = "Add", - className = change.ClassName, - name = change.Name, - hint = hint, - changeList = changeList, - instance = instanceMap.fromIds[id], - }) - end - - return tree + return false end function PatchVisualizer:render() - local patch = self.props.patch or PatchSet.newEmpty() - local unappliedPatch = self.props.unappliedPatch or PatchSet.newEmpty() - local instanceMap = self.props.instanceMap - - local tree = self:buildTree(patch, unappliedPatch, instanceMap) + local patchTree = self.props.patchTree + if patchTree == nil and self.props.patch ~= nil then + patchTree = PatchTree.build(self.props.patch, self.props.instanceMap, self.props.changeListHeaders or { "Property", "Current", "Incoming" }) + if self.props.unappliedPatch then + patchTree = PatchTree.updateMetadata(patchTree, self.props.patch, self.props.instanceMap, self.props.unappliedPatch) + end + end -- Recusively draw tree local scrollElements, elementHeights = {}, {} - local function drawNode(node, depth) - local elementHeight, setElementHeight = Roact.createBinding(30) - table.insert(elementHeights, elementHeight) - table.insert( - scrollElements, - e(DomLabel, { - columnVisibility = self.props.columnVisibility, - updateEvent = self.updateEvent, - elementHeight = elementHeight, - setElementHeight = setElementHeight, - patchType = node.patchType, - className = node.className, - isWarning = next(findUnappliedPropsForId(unappliedPatch, node.id)) ~= nil, - instance = node.instance, - name = node.name, - hint = node.hint, - changeList = node.changeList, - depth = depth, - transparency = self.props.transparency, - }) - ) - for _, childNode in alphabeticalPairs(node.children) do - drawNode(childNode, depth + 1) + if patchTree then + local function drawNode(node, depth) + local elementHeight, setElementHeight = Roact.createBinding(30) + table.insert(elementHeights, elementHeight) + table.insert( + scrollElements, + e(DomLabel, { + updateEvent = self.updateEvent, + elementHeight = elementHeight, + setElementHeight = setElementHeight, + patchType = node.patchType, + className = node.className, + isWarning = node.isWarning, + instance = node.instance, + name = node.name, + hint = node.hint, + changeList = node.changeList, + depth = depth, + transparency = self.props.transparency, + }) + ) end - end - for _, node in alphabeticalPairs(tree.ROOT.children) do - drawNode(node, 0) + + patchTree:forEach(function(node, depth) + drawNode(node, depth) + end) end - return e(BorderedContainer, { - transparency = self.props.transparency, - size = self.props.size, - position = self.props.position, - layoutOrder = self.props.layoutOrder, - }, { - VirtualScroller = e(VirtualScroller, { - size = UDim2.new(1, 0, 1, 0), + return Theme.with(function(theme) + return e(BorderedContainer, { transparency = self.props.transparency, - count = #scrollElements, - updateEvent = self.updateEvent.Event, - render = function(i) - return scrollElements[i] - end, - getHeightBinding = function(i) - return elementHeights[i] - end, - }), - }) + size = self.props.size, + position = self.props.position, + layoutOrder = self.props.layoutOrder, + }, { + CleanMerge = e("TextLabel", { + Visible = #scrollElements == 0, + Text = "No changes to sync, project is up to date.", + Font = Enum.Font.GothamMedium, + TextSize = 15, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextWrapped = true, + Size = UDim2.new(1, 0, 1, 0), + BackgroundTransparency = 1, + }), + + VirtualScroller = e(VirtualScroller, { + size = UDim2.new(1, 0, 1, 0), + transparency = self.props.transparency, + count = #scrollElements, + updateEvent = self.updateEvent.Event, + render = function(i) + return scrollElements[i] + end, + getHeightBinding = function(i) + return elementHeights[i] + end, + }), + }) + end) end return PatchVisualizer diff --git a/plugin/src/App/StatusPages/Confirming.lua b/plugin/src/App/StatusPages/Confirming.lua index 3359eaf6..a5592347 100644 --- a/plugin/src/App/StatusPages/Confirming.lua +++ b/plugin/src/App/StatusPages/Confirming.lua @@ -52,7 +52,7 @@ function ConfirmingPage:render() transparency = self.props.transparency, layoutOrder = 3, - columnVisibility = {true, true, true}, + changeListHeaders = { "Property", "Current", "Incoming" }, patch = self.props.confirmData.patch, instanceMap = self.props.confirmData.instanceMap, }), diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index 689b9022..00f6822b 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -83,10 +83,7 @@ function ChangesDrawer:render() transparency = self.props.transparency, layoutOrder = 3, - columnVisibility = { true, false, true }, - patch = self.props.patch, - unappliedPatch = self.props.unappliedPatch, - instanceMap = self.serveSession.__instanceMap, + patchTree = self.props.patchTree, }), }) end) @@ -365,8 +362,7 @@ function ConnectedPage:render() ChangesDrawer = e(ChangesDrawer, { rendered = self.state.renderChanges, transparency = self.props.transparency, - patch = self.props.patchData.patch, - unappliedPatch = self.props.patchData.unapplied, + patchTree = self.props.patchTree, serveSession = self.props.serveSession, height = self.changeDrawerHeight, layoutOrder = 5, diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index fd534d0c..23d0a506 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -19,6 +19,7 @@ local Dictionary = require(Plugin.Dictionary) local ServeSession = require(Plugin.ServeSession) local ApiContext = require(Plugin.ApiContext) local PatchSet = require(Plugin.PatchSet) +local PatchTree = require(Plugin.PatchTree) local preloadAssets = require(Plugin.preloadAssets) local soundPlayer = require(Plugin.soundPlayer) local ignorePlaceIds = require(Plugin.ignorePlaceIds) @@ -358,6 +359,21 @@ function App:startSession() twoWaySync = sessionOptions.twoWaySync, }) + self.cleanupPrecommit = serveSession.__reconciler:hookPrecommit(function(patch, instanceMap) + -- Build new tree for patch + self:setState({ + patchTree = PatchTree.build(patch, instanceMap, { "Property", "Old", "New" }), + }) + end) + self.cleanupPostcommit = serveSession.__reconciler:hookPostcommit(function(patch, instanceMap, unappliedPatch) + -- Update tree with unapplied metadata + self:setState(function(prevState) + return { + patchTree = PatchTree.updateMetadata(prevState.patchTree, patch, instanceMap, unappliedPatch), + } + end) + end) + serveSession:onPatchApplied(function(patch, unapplied) local now = os.time() local old = self.state.patchData @@ -503,6 +519,13 @@ function App:endSession() appStatus = AppStatus.NotConnected, }) + if self.cleanupPrecommit ~= nil then + self.cleanupPrecommit() + end + if self.cleanupPostcommit ~= nil then + self.cleanupPostcommit() + end + Log.trace("Session terminated by user") end @@ -533,8 +556,8 @@ function App:render() initDockState = Enum.InitialDockState.Right, initEnabled = false, overridePreviousState = false, - floatingSize = Vector2.new(300, 200), - minimumSize = Vector2.new(300, 120), + floatingSize = Vector2.new(320, 210), + minimumSize = Vector2.new(300, 210), zIndexBehavior = Enum.ZIndexBehavior.Sibling, @@ -590,6 +613,7 @@ function App:render() Connected = createPageElement(AppStatus.Connected, { projectName = self.state.projectName, address = self.state.address, + patchTree = self.state.patchTree, patchData = self.state.patchData, serveSession = self.serveSession, diff --git a/plugin/src/PatchTree.lua b/plugin/src/PatchTree.lua new file mode 100644 index 00000000..b241472d --- /dev/null +++ b/plugin/src/PatchTree.lua @@ -0,0 +1,434 @@ +--[[ + Methods to turn PatchSets into trees matching the DataModel containing + the changes and metadata for use in the PatchVisualizer component. +]] + +local HttpService = game:GetService("HttpService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Log = require(Packages.Log) + +local Types = require(Plugin.Types) +local decodeValue = require(Plugin.Reconciler.decodeValue) +local getProperty = require(Plugin.Reconciler.getProperty) + +local function alphabeticalNext(t, state) + -- Equivalent of the next function, but returns the keys in the alphabetic + -- order of node names. We use a temporary ordered key table that is stored in the + -- table being iterated. + + local key = nil + if state == nil then + -- First iteration, generate the index + local orderedIndex, i = table.create(5), 0 + for k in t do + i += 1 + orderedIndex[i] = k + end + table.sort(orderedIndex, function(a, b) + local nodeA, nodeB = t[a], t[b] + return (nodeA.name or "") < (nodeB.name or "") + end) + + t.__orderedIndex = orderedIndex + key = orderedIndex[1] + else + -- Fetch the next value + for i, orderedState in t.__orderedIndex do + if orderedState == state then + key = t.__orderedIndex[i + 1] + break + end + end + end + + if key then + return key, t[key] + end + + -- No more value to return, cleanup + t.__orderedIndex = nil + + return +end + +local function alphabeticalPairs(t) + -- Equivalent of the pairs() iterator, but sorted + return alphabeticalNext, t, nil +end + +local Tree = {} +Tree.__index = Tree + +function Tree.new() + local tree = { + idToNode = {}, + ROOT = { + className = "DataModel", + name = "ROOT", + children = {}, + }, + } + -- Add ROOT to idToNode or it won't be found by getNode since that searches *within* ROOT + tree.idToNode["ROOT"] = tree.ROOT + + return setmetatable(tree, Tree) +end + +-- Iterates over all sub-nodes, depth first +-- node is where to start from, defaults to root +-- depth is used for recursion but can be used to set the starting depth +function Tree:forEach(callback, node, depth) + depth = depth or 1 + for _, child in alphabeticalPairs(if node then node.children else self.ROOT.children) do + callback(child, depth) + if type(child.children) == "table" then + self:forEach(callback, child, depth + 1) + end + end +end + +-- Finds a node by id, depth first +-- searchNode is the node to start the search within, defaults to root +function Tree:getNode(id, searchNode) + if self.idToNode[id] then + return self.idToNode[id] + end + + local searchChildren = (searchNode or self.ROOT).children + for nodeId, node in searchChildren do + if nodeId == id then + self.idToNode[id] = node + return node + end + local descendant = self:getNode(id, node) + if descendant then + return descendant + end + end + + return nil +end + +-- Adds a node to the tree as a child of the node with id == parent +-- If parent is nil, it defaults to root +-- props must contain id, and cannot contain children or parentId +-- other than those three, it can hold anything +function Tree:addNode(parent, props) + assert(props.id, "props must contain id") + + parent = parent or "ROOT" + + local node = self:getNode(props.id) + if node then + -- Update existing node + for k, v in props do + node[k] = v + end + return node + end + + node = table.clone(props) + node.children = {} + node.parentId = parent + + local parentNode = self:getNode(parent) + if not parentNode then + Log.warn("Failed to create node since parent doesnt exist: {}, {}", parent, props) + return + end + + parentNode.children[node.id] = node + self.idToNode[node.id] = node + + return node +end + +-- Given a list of ancestor ids in descending order, builds the nodes for them +-- using the patch and instanceMap info +function Tree:buildAncestryNodes(ancestryIds: { string }, patch, instanceMap) + -- Build nodes for ancestry by going up the tree + local previousId = "ROOT" + for _, ancestorId in ancestryIds do + local value = instanceMap.fromIds[ancestorId] or patch.added[ancestorId] + if not value then + Log.warn("Failed to find ancestor object for " .. ancestorId) + continue + end + self:addNode(previousId, { + id = ancestorId, + className = value.ClassName, + name = value.Name, + instance = if typeof(value) == "Instance" then value else nil, + }) + previousId = ancestorId + end +end + +local PatchTree = {} + +-- Builds a new tree from a patch and instanceMap +-- uses changeListHeaders in node.changeList +function PatchTree.build(patch, instanceMap, changeListHeaders) + local tree = Tree.new() + + for _, change in patch.updated do + local instance = instanceMap.fromIds[change.id] + if not instance then + continue + end + + -- Gather ancestors from existing DOM + local ancestryIds = {} + local parentObject = instance.Parent + local parentId = instanceMap.fromInstances[parentObject] + while parentObject do + table.insert(ancestryIds, 1, parentId) + parentObject = parentObject.Parent + parentId = instanceMap.fromInstances[parentObject] + end + + tree:buildAncestryNodes(ancestryIds, patch, instanceMap) + + -- Gather detail text + local changeList, hint = nil, nil + if next(change.changedProperties) or change.changedName then + changeList = {} + + local hintBuffer, i = {}, 0 + local function addProp(prop: string, current: any?, incoming: any?, metadata: any?) + i += 1 + hintBuffer[i] = prop + changeList[i] = { prop, current, incoming, metadata } + end + + -- Gather the changes + + if change.changedName then + addProp("Name", instance.Name, change.changedName) + end + + for prop, incoming in change.changedProperties do + local incomingSuccess, incomingValue = decodeValue(incoming, instanceMap) + local currentSuccess, currentValue = getProperty(instance, prop) + + addProp( + prop, + if currentSuccess then currentValue else "[Error]", + if incomingSuccess then incomingValue else next(incoming) + ) + end + + -- Finalize detail values + + -- Trim hint to top 3 + table.sort(hintBuffer) + if #hintBuffer > 3 then + hintBuffer = { + hintBuffer[1], + hintBuffer[2], + hintBuffer[3], + i - 3 .. " more", + } + end + hint = table.concat(hintBuffer, ", ") + + -- Sort changes and add header + table.sort(changeList, function(a, b) + return a[1] < b[1] + end) + table.insert(changeList, 1, changeListHeaders) + end + + -- Add this node to tree + tree:addNode(instanceMap.fromInstances[instance.Parent], { + id = change.id, + patchType = "Edit", + className = instance.ClassName, + name = instance.Name, + instance = instance, + hint = hint, + changeList = changeList, + }) + end + + for _, idOrInstance in patch.removed do + local instance = if Types.RbxId(idOrInstance) then instanceMap.fromIds[idOrInstance] else idOrInstance + if not instance then + -- If we're viewing a past patch, the instance is already removed + -- and we therefore cannot get the tree for it anymore + continue + end + + -- Gather ancestors from existing DOM + -- (note that they may have no ID if they're being removed as unknown) + local ancestryIds = {} + local parentObject = instance.Parent + local parentId = instanceMap.fromInstances[parentObject] or HttpService:GenerateGUID(false) + while parentObject do + instanceMap:insert(parentId, parentObject) -- This ensures we can find the parent later + table.insert(ancestryIds, 1, parentId) + parentObject = parentObject.Parent + parentId = instanceMap.fromInstances[parentObject] or HttpService:GenerateGUID(false) + end + + tree:buildAncestryNodes(ancestryIds, patch, instanceMap) + + -- Add this node to tree + local nodeId = instanceMap.fromInstances[instance] or HttpService:GenerateGUID(false) + instanceMap:insert(nodeId, instance) + tree:addNode(instanceMap.fromInstances[instance.Parent], { + id = nodeId, + patchType = "Remove", + className = instance.ClassName, + name = instance.Name, + instance = instance, + }) + end + + for id, change in patch.added do + -- Gather ancestors from existing DOM or future additions + local ancestryIds = {} + local parentId = change.Parent + local parentData = patch.added[parentId] + local parentObject = instanceMap.fromIds[parentId] + while parentId do + table.insert(ancestryIds, 1, parentId) + parentId = nil + + if parentData then + -- object is parented to an instance that does not exist yet + parentId = parentData.Parent + parentData = patch.added[parentId] + parentObject = instanceMap.fromIds[parentId] + elseif parentObject then + -- object is parented to an instance that exists + parentObject = parentObject.Parent + parentId = instanceMap.fromInstances[parentObject] + parentData = patch.added[parentId] + end + end + + tree:buildAncestryNodes(ancestryIds, patch, instanceMap) + + -- Gather detail text + local changeList, hint = nil, nil + if next(change.Properties) then + changeList = {} + + local hintBuffer, i = {}, 0 + for prop, incoming in change.Properties do + i += 1 + hintBuffer[i] = prop + + local success, incomingValue = decodeValue(incoming, instanceMap) + if success then + table.insert(changeList, { prop, "N/A", incomingValue }) + else + table.insert(changeList, { prop, "N/A", next(incoming) }) + end + end + + -- Finalize detail values + + -- Trim hint to top 3 + table.sort(hintBuffer) + if #hintBuffer > 3 then + hintBuffer = { + hintBuffer[1], + hintBuffer[2], + hintBuffer[3], + i - 3 .. " more", + } + end + hint = table.concat(hintBuffer, ", ") + + -- Sort changes and add header + table.sort(changeList, function(a, b) + return a[1] < b[1] + end) + table.insert(changeList, 1, changeListHeaders) + end + + -- Add this node to tree + tree:addNode(change.Parent, { + id = change.Id, + patchType = "Add", + className = change.ClassName, + name = change.Name, + hint = hint, + changeList = changeList, + instance = instanceMap.fromIds[id], + }) + end + + return tree +end + +-- Creates a deep copy of a tree for immutability purposes in Roact +function PatchTree.clone(tree) + if not tree then return end + + local newTree = Tree.new() + tree:forEach(function(node) + newTree:addNode(node.parentId, table.clone(node)) + end) + + return newTree +end + +-- Updates the metadata of a tree with the unapplied patch and currently existing instances +-- Builds a new tree from the data if one isn't provided +-- Always returns a new tree for immutability purposes in Roact +function PatchTree.updateMetadata(tree, patch, instanceMap, unappliedPatch) + if tree then + tree = PatchTree.clone(tree) + else + tree = PatchTree.build(patch, instanceMap) + end + + -- Update isWarning metadata + for _, failedChange in unappliedPatch.updated do + local node = tree:getNode(failedChange.id) + if node then + node.isWarning = true + Log.trace("Marked node as warning: {} {}", node.id, node.name) + + if node.changeList then + for _, change in node.changeList do + if failedChange.changedProperties[change[1]] then + Log.trace(" Marked property as warning: {}", change[1]) + if change[4] == nil then + change[4] = {} + end + change[4].isWarning = true + end + end + end + end + end + + -- Update if instances exist + tree:forEach(function(node) + if node.instance then + if node.instance.Parent == nil and node.instance ~= game then + -- This instance has been removed + Log.trace("Removed instance from node: {} {}", node.id, node.name) + node.instance = nil + end + else + -- This instance may have been added + node.instance = instanceMap.fromIds[node.id] + if node.instance then + Log.trace("Added instance to node: {} {}", node.id, node.name) + end + end + end) + + return tree +end + +return PatchTree diff --git a/plugin/src/Reconciler/init.lua b/plugin/src/Reconciler/init.lua index 1db295a4..12945782 100644 --- a/plugin/src/Reconciler/init.lua +++ b/plugin/src/Reconciler/init.lua @@ -3,6 +3,9 @@ and mutating the Roblox DOM. ]] +local Packages = script.Parent.Parent.Packages +local Log = require(Packages.Log) + local applyPatch = require(script.applyPatch) local hydrate = require(script.hydrate) local diff = require(script.diff) @@ -14,13 +17,63 @@ function Reconciler.new(instanceMap) local self = { -- Tracks all of the instances known by the reconciler by ID. __instanceMap = instanceMap, + __precommitCallbacks = {}, + __postcommitCallbacks = {}, } return setmetatable(self, Reconciler) end +function Reconciler:hookPrecommit(callback: (patch: any, instanceMap: any) -> ()): () -> () + table.insert(self.__precommitCallbacks, callback) + Log.trace("Added precommit callback: {}", callback) + + return function() + -- Remove the callback from the list + for i, cb in self.__precommitCallbacks do + if cb == callback then + table.remove(self.__precommitCallbacks, i) + Log.trace("Removed precommit callback: {}", callback) + break + end + end + end +end + +function Reconciler:hookPostcommit(callback: (patch: any, instanceMap: any, unappliedPatch: any) -> ()): () -> () + table.insert(self.__postcommitCallbacks, callback) + Log.trace("Added postcommit callback: {}", callback) + + return function() + -- Remove the callback from the list + for i, cb in self.__postcommitCallbacks do + if cb == callback then + table.remove(self.__postcommitCallbacks, i) + Log.trace("Removed postcommit callback: {}", callback) + break + end + end + end +end + function Reconciler:applyPatch(patch) - return applyPatch(self.__instanceMap, patch) + for _, callback in self.__precommitCallbacks do + local success, err = pcall(callback, patch, self.__instanceMap) + if not success then + Log.warn("Precommit hook errored: {}", err) + end + end + + local unappliedPatch = applyPatch(self.__instanceMap, patch) + + for _, callback in self.__postcommitCallbacks do + local success, err = pcall(callback, patch, self.__instanceMap, unappliedPatch) + if not success then + Log.warn("Postcommit hook errored: {}", err) + end + end + + return unappliedPatch end function Reconciler:hydrate(virtualInstances, rootId, rootInstance) @@ -31,4 +84,4 @@ function Reconciler:diff(virtualInstances, rootId) return diff(self.__instanceMap, virtualInstances, rootId) end -return Reconciler \ No newline at end of file +return Reconciler From 6e320b1fd563100623ea117f6014d1e8a4ee80c9 Mon Sep 17 00:00:00 2001 From: Shae Date: Fri, 14 Jul 2023 15:36:50 -0500 Subject: [PATCH 1310/1504] Add support for TOML files (#633) TOML maps well to Lua, is easier to read and write than JSON, and is commonly used by Roblox tools. Use cases: * Put game, plugin, or library config in a toml file * Sync in toml files generated by tools * Sync in config files for tools so that the game can double-check that the config file has been followed. (e.g. check that packages match versions specified in wally.toml) --- CHANGELOG.md | 2 + Cargo.lock | 1 + Cargo.toml | 1 + src/snapshot_middleware/mod.rs | 4 + ...leware__toml__test__instance_from_vfs.snap | 20 +++ src/snapshot_middleware/toml.rs | 123 ++++++++++++++++++ 6 files changed, 151 insertions(+) create mode 100644 src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap create mode 100644 src/snapshot_middleware/toml.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 130175e7..2c2e1bbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ * Improve tooltip behavior ([#723]) * Better settings controls ([#725]) * Rework patch visualizer with many fixes and improvements ([#726]) +* Added support for syncing in `.toml` files ([#633]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 @@ -32,6 +33,7 @@ [#723]: https://github.com/rojo-rbx/rojo/pull/723 [#725]: https://github.com/rojo-rbx/rojo/pull/725 [#726]: https://github.com/rojo-rbx/rojo/pull/726 +[#633]: https://github.com/rojo-rbx/rojo/pull/633 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/Cargo.lock b/Cargo.lock index 12e9f860..fab34b07 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1922,6 +1922,7 @@ dependencies = [ "termcolor", "thiserror", "tokio", + "toml", "tracy-client 0.13.2", "uuid", "walkdir", diff --git a/Cargo.toml b/Cargo.toml index bbbbcbf9..124d5c8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -80,6 +80,7 @@ ritz = "0.1.0" roblox_install = "1.0.0" serde = { version = "1.0.130", features = ["derive", "rc"] } serde_json = "1.0.68" +toml = "0.5.9" termcolor = "1.1.2" thiserror = "1.0.30" tokio = { version = "1.12.0", features = ["rt", "rt-multi-thread"] } diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 3d5de76b..c690a223 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -14,6 +14,7 @@ mod meta_file; mod project; mod rbxm; mod rbxmx; +mod toml; mod txt; mod util; @@ -32,6 +33,7 @@ use self::{ project::snapshot_project, rbxm::snapshot_rbxm, rbxmx::snapshot_rbxmx, + toml::snapshot_toml, txt::snapshot_txt, util::PathExt, }; @@ -117,6 +119,8 @@ pub fn snapshot_from_vfs( return Ok(None); } else if path.file_name_ends_with(".json") { return snapshot_json(context, vfs, path); + } else if path.file_name_ends_with(".toml") { + return snapshot_toml(context, vfs, path); } else if let Ok(name) = csv_name { match name { // init csv are handled elsewhere and should not turn into diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap new file mode 100644 index 00000000..3529bf89 --- /dev/null +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap @@ -0,0 +1,20 @@ +--- +source: src/snapshot_middleware/toml.rs +expression: instance_snapshot +--- +snapshot_id: "00000000000000000000000000000000" +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /foo.toml + relevant_paths: + - /foo.toml + - /foo.meta.json + context: {} +name: foo +class_name: ModuleScript +properties: + Source: + String: "return {\n\t[\"1invalidident\"] = \"nice\",\n\tarray = {1, 2, 3},\n\tdates = {\n\t\tlocaldate = \"1979-05-27\",\n\t\tlocaldatetime = \"1979-05-27T07:32:00\",\n\t\tlocaltime = \"00:32:00.999999\",\n\t\toffset1 = \"1979-05-27T00:32:00.999999-07:00\",\n\t\toffset2 = \"1979-05-27T07:32:00Z\",\n\t},\n\t[\"false\"] = false,\n\tfloat = 1234.5452,\n\tint = 1234,\n\tobject = {\n\t\thello = \"world\",\n\t},\n\t[\"true\"] = true,\n}" +children: [] + diff --git a/src/snapshot_middleware/toml.rs b/src/snapshot_middleware/toml.rs new file mode 100644 index 00000000..6ee9be47 --- /dev/null +++ b/src/snapshot_middleware/toml.rs @@ -0,0 +1,123 @@ +use std::path::Path; + +use anyhow::Context; +use maplit::hashmap; +use memofs::{IoResultExt, Vfs}; + +use crate::{ + lua_ast::{Expression, Statement}, + snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, +}; + +use super::{meta_file::AdjacentMetadata, util::PathExt}; + +pub fn snapshot_toml( + context: &InstanceContext, + vfs: &Vfs, + path: &Path, +) -> anyhow::Result> { + let name = path.file_name_trim_end(".toml")?; + let contents = vfs.read(path)?; + + let value: toml::Value = toml::from_slice(&contents) + .with_context(|| format!("File contains malformed TOML: {}", path.display()))?; + + let as_lua = toml_to_lua(value).to_string(); + + let properties = hashmap! { + "Source".to_owned() => as_lua.into(), + }; + + let meta_path = path.with_file_name(format!("{}.meta.json", name)); + + let mut snapshot = InstanceSnapshot::new() + .name(name) + .class_name("ModuleScript") + .properties(properties) + .metadata( + InstanceMetadata::new() + .instigating_source(path) + .relevant_paths(vec![path.to_path_buf(), meta_path.clone()]) + .context(context), + ); + + if let Some(meta_contents) = vfs.read(&meta_path).with_not_found()? { + let mut metadata = AdjacentMetadata::from_slice(&meta_contents, meta_path)?; + metadata.apply_all(&mut snapshot)?; + } + + Ok(Some(snapshot)) +} + +fn toml_to_lua(value: toml::Value) -> Statement { + Statement::Return(toml_to_lua_value(value)) +} + +fn toml_to_lua_value(value: toml::Value) -> Expression { + use toml::Value; + + match value { + Value::Datetime(value) => Expression::String(value.to_string()), + Value::Boolean(value) => Expression::Bool(value), + Value::Float(value) => Expression::Number(value), + Value::Integer(value) => Expression::Number(value as f64), + Value::String(value) => Expression::String(value), + Value::Array(values) => { + Expression::Array(values.into_iter().map(toml_to_lua_value).collect()) + } + Value::Table(values) => Expression::table( + values + .into_iter() + .map(|(key, value)| (key.into(), toml_to_lua_value(value))) + .collect(), + ), + } +} + +#[cfg(test)] +mod test { + use super::*; + + use memofs::{InMemoryFs, VfsSnapshot}; + + #[test] + fn instance_from_vfs() { + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo.toml", + VfsSnapshot::file( + r#" + array = [1, 2, 3] + true = true + false = false + int = 1234 + float = 1234.5452 + "1invalidident" = "nice" + + [object] + hello = "world" + + [dates] + offset1 = 1979-05-27T00:32:00.999999-07:00 + offset2 = 1979-05-27 07:32:00Z + localdatetime = 1979-05-27T07:32:00 + localdate = 1979-05-27 + localtime = 00:32:00.999999 + "#, + ), + ) + .unwrap(); + + let mut vfs = Vfs::new(imfs.clone()); + + let instance_snapshot = snapshot_toml( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.toml"), + ) + .unwrap() + .unwrap(); + + insta::assert_yaml_snapshot!(instance_snapshot); + } +} From dd01a9bef33a47865d92f194b823899ea33cd7da Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 14 Jul 2023 14:04:11 -0700 Subject: [PATCH 1311/1504] Bump openssl from 0.10.51 to 0.10.55 (#737) --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fab34b07..cc544cf7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1308,9 +1308,9 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.51" +version = "0.10.55" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97ea2d98598bf9ada7ea6ee8a30fb74f9156b63bbe495d64ec2b87c269d2dda3" +checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -1349,9 +1349,9 @@ dependencies = [ [[package]] name = "openssl-sys" -version = "0.9.86" +version = "0.9.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "992bac49bdbab4423199c654a5515bd2a6c6a23bf03f2dd3bdb7e5ae6259bc69" +checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" dependencies = [ "cc", "libc", From 8662d2227ca057f42c9b8f588f8436406362e020 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sun, 16 Jul 2023 14:59:30 -0700 Subject: [PATCH 1312/1504] Improve Rojo sync reliability (#739) Uses non-recursive main loop and avoids hanging promises --- plugin/src/ApiContext.lua | 15 ++---------- plugin/src/ServeSession.lua | 49 +++++++++++++++++++++++++------------ 2 files changed, 35 insertions(+), 29 deletions(-) diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 98890d4f..9a683dd5 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -11,13 +11,6 @@ local validateApiInfo = Types.ifEnabled(Types.ApiInfoResponse) local validateApiRead = Types.ifEnabled(Types.ApiReadResponse) local validateApiSubscribe = Types.ifEnabled(Types.ApiSubscribeResponse) ---[[ - Returns a promise that will never resolve nor reject. -]] -local function hangingPromise() - return Promise.new(function() end) -end - local function rejectFailedRequests(response) if response.code >= 400 then local message = string.format("HTTP %s:\n%s", tostring(response.code), response.body) @@ -212,12 +205,8 @@ function ApiContext:retrieveMessages() local function sendRequest() local request = Http.get(url) :catch(function(err) - if err.type == Http.Error.Kind.Timeout then - if self.__connected then - return sendRequest() - else - return hangingPromise() - end + if err.type == Http.Error.Kind.Timeout and self.__connected then + return sendRequest() end return Promise.reject(err) diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 08dc4041..4e5116c8 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -299,27 +299,44 @@ function ServeSession:__initialSync(serverInfo) end function ServeSession:__mainSyncLoop() - return self.__apiContext:retrieveMessages() - :andThen(function(messages) - Log.trace("Serve session {} retrieved {} messages", tostring(self), #messages) + return Promise.new(function(resolve, reject) + while self.__status == Status.Connected do + local success, result = self.__apiContext:retrieveMessages() + :andThen(function(messages) + if self.__status == Status.Disconnected then + -- In the time it took to retrieve messages, we disconnected + -- so we just resolve immediately without patching anything + return + end - for _, message in ipairs(messages) do - local unappliedPatch = self.__reconciler:applyPatch(message) + Log.trace("Serve session {} retrieved {} messages", tostring(self), #messages) - if not PatchSet.isEmpty(unappliedPatch) then - Log.warn("Could not apply all changes requested by the Rojo server:\n{}", - PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) - end + for _, message in messages do + local unappliedPatch = self.__reconciler:applyPatch(message) - if self.__patchAppliedCallback then - pcall(self.__patchAppliedCallback, message, unappliedPatch) - end + if not PatchSet.isEmpty(unappliedPatch) then + Log.warn("Could not apply all changes requested by the Rojo server:\n{}", + PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) + end + + if self.__patchAppliedCallback then + pcall(self.__patchAppliedCallback, message, unappliedPatch) + end + end + end):await() + + if self.__status == Status.Disconnected then + -- If we are no longer connected after applying, we stop silently + -- without checking for errors as they are no longer relevant + break + elseif success == false then + reject(result) end + end - if self.__status ~= Status.Disconnected then - return self:__mainSyncLoop() - end - end) + -- We are no longer connected, so we resolve the promise + resolve() + end) end function ServeSession:__stopInternal(err) From 49154778234d90aeb47be260c42a6f9d7b62fb1f Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sun, 16 Jul 2023 21:03:06 -0700 Subject: [PATCH 1313/1504] Expose reconciler hooks on servesession (#741) --- plugin/src/App/init.lua | 2 +- plugin/src/ServeSession.lua | 16 ++++++---------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 23d0a506..f4c30f3c 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -374,7 +374,7 @@ function App:startSession() end) end) - serveSession:onPatchApplied(function(patch, unapplied) + serveSession:hookPostcommit(function(patch, _instanceMap, unapplied) local now = os.time() local old = self.state.patchData diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 4e5116c8..6a3fcdc4 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -97,7 +97,6 @@ function ServeSession.new(options) __instanceMap = instanceMap, __changeBatcher = changeBatcher, __statusChangedCallback = nil, - __patchAppliedCallback = nil, __connections = connections, } @@ -129,8 +128,12 @@ function ServeSession:setConfirmCallback(callback) self.__userConfirmCallback = callback end -function ServeSession:onPatchApplied(callback) - self.__patchAppliedCallback = callback +function ServeSession:hookPrecommit(callback) + return self.__reconciler:hookPrecommit(callback) +end + +function ServeSession:hookPostcommit(callback) + return self.__reconciler:hookPostcommit(callback) end function ServeSession:start() @@ -291,9 +294,6 @@ function ServeSession:__initialSync(serverInfo) Log.warn("Could not apply all changes requested by the Rojo server:\n{}", PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) end - if self.__patchAppliedCallback then - pcall(self.__patchAppliedCallback, catchUpPatch, unappliedPatch) - end end end) end @@ -318,10 +318,6 @@ function ServeSession:__mainSyncLoop() Log.warn("Could not apply all changes requested by the Rojo server:\n{}", PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) end - - if self.__patchAppliedCallback then - pcall(self.__patchAppliedCallback, message, unappliedPatch) - end end end):await() From dc17a185ca4b256b31989bfa616e0bc64eba7ede Mon Sep 17 00:00:00 2001 From: Micah <48431591+nezuo@users.noreply.github.com> Date: Mon, 17 Jul 2023 21:15:40 -0500 Subject: [PATCH 1314/1504] Add plugin build flag (#735) Resolves #715. --- CHANGELOG.md | 2 ++ benches/build.rs | 3 +- src/cli/build.rs | 87 +++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 75 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2c2e1bbf..3617eb47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ * Better settings controls ([#725]) * Rework patch visualizer with many fixes and improvements ([#726]) * Added support for syncing in `.toml` files ([#633]) +* Add `plugin` flag to the `build` command that outputs to the local plugins folder ([#735]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 @@ -34,6 +35,7 @@ [#725]: https://github.com/rojo-rbx/rojo/pull/725 [#726]: https://github.com/rojo-rbx/rojo/pull/726 [#633]: https://github.com/rojo-rbx/rojo/pull/633 +[#735]: https://github.com/rojo-rbx/rojo/pull/735 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/benches/build.rs b/benches/build.rs index 456a5339..87d33e44 100644 --- a/benches/build.rs +++ b/benches/build.rs @@ -31,11 +31,12 @@ fn bench_build_place(c: &mut Criterion, name: &str, path: &str) { fn place_setup>(input_path: P) -> (TempDir, BuildCommand) { let dir = tempdir().unwrap(); let input = input_path.as_ref().to_path_buf(); - let output = dir.path().join("output.rbxlx"); + let output = Some(dir.path().join("output.rbxlx")); let options = BuildCommand { project: input, watch: false, + plugin: None, output, }; diff --git a/src/cli/build.rs b/src/cli/build.rs index d6c3f349..8f705d37 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -4,10 +4,11 @@ use std::{ path::{Path, PathBuf}, }; -use anyhow::Context; -use clap::Parser; +use anyhow::{bail, Context}; +use clap::{CommandFactory, Parser}; use fs_err::File; use memofs::Vfs; +use roblox_install::RobloxStudio; use tokio::runtime::Runtime; use crate::serve_session::ServeSession; @@ -16,6 +17,8 @@ use super::resolve_path; const UNKNOWN_OUTPUT_KIND_ERR: &str = "Could not detect what kind of file to build. \ Expected output file to end in .rbxl, .rbxlx, .rbxm, or .rbxmx."; +const UNKNOWN_PLUGIN_KIND_ERR: &str = "Could not detect what kind of file to build. \ + Expected plugin file to end in .rbxm or .rbxmx."; /// Generates a model or place file from the Rojo project. #[derive(Debug, Parser)] @@ -28,7 +31,13 @@ pub struct BuildCommand { /// /// Should end in .rbxm, .rbxl, .rbxmx, or .rbxlx. #[clap(long, short)] - pub output: PathBuf, + pub output: Option, + + /// Alternative to the output flag that outputs the result in the local plugins folder. + /// + /// Should end in .rbxm or .rbxl. + #[clap(long, short)] + pub plugin: Option, /// Whether to automatically rebuild when any input files change. #[clap(long)] @@ -37,18 +46,52 @@ pub struct BuildCommand { impl BuildCommand { pub fn run(self) -> anyhow::Result<()> { - let project_path = resolve_path(&self.project); + let (output_path, output_kind) = match (self.output, self.plugin) { + (Some(_), Some(_)) => { + BuildCommand::command() + .error( + clap::ErrorKind::ArgumentConflict, + "the argument '--output ' cannot be used with '--plugin '", + ) + .exit(); + } + (None, None) => { + BuildCommand::command() + .error( + clap::ErrorKind::MissingRequiredArgument, + "one of the following arguments must be provided: \n --output \n --plugin ", + ) + .exit(); + } + (Some(output), None) => { + let output_kind = + OutputKind::from_output_path(&output).context(UNKNOWN_OUTPUT_KIND_ERR)?; - let output_kind = detect_output_kind(&self.output).context(UNKNOWN_OUTPUT_KIND_ERR)?; + (output, output_kind) + } + (None, Some(plugin)) => { + if plugin.is_absolute() { + bail!("plugin flag path cannot be absolute.") + } + + let output_kind = + OutputKind::from_plugin_path(&plugin).context(UNKNOWN_PLUGIN_KIND_ERR)?; + let studio = RobloxStudio::locate()?; + + (studio.plugins_path().join(&plugin), output_kind) + } + }; + + let project_path = resolve_path(&self.project); log::trace!("Constructing in-memory filesystem"); let vfs = Vfs::new_default(); vfs.set_watch_enabled(self.watch); - let session = ServeSession::new(vfs, &project_path)?; + let session = ServeSession::new(vfs, project_path)?; let mut cursor = session.message_queue().cursor(); - write_model(&session, &self.output, output_kind)?; + write_model(&session, &output_path, output_kind)?; if self.watch { let rt = Runtime::new().unwrap(); @@ -58,7 +101,7 @@ impl BuildCommand { let (new_cursor, _patch_set) = rt.block_on(receiver).unwrap(); cursor = new_cursor; - write_model(&session, &self.output, output_kind)?; + write_model(&session, &output_path, output_kind)?; } } @@ -86,15 +129,27 @@ enum OutputKind { Rbxl, } -fn detect_output_kind(output: &Path) -> Option { - let extension = output.extension()?.to_str()?; +impl OutputKind { + fn from_output_path(output: &Path) -> Option { + let extension = output.extension()?.to_str()?; - match extension { - "rbxlx" => Some(OutputKind::Rbxlx), - "rbxmx" => Some(OutputKind::Rbxmx), - "rbxl" => Some(OutputKind::Rbxl), - "rbxm" => Some(OutputKind::Rbxm), - _ => None, + match extension { + "rbxlx" => Some(OutputKind::Rbxlx), + "rbxmx" => Some(OutputKind::Rbxmx), + "rbxl" => Some(OutputKind::Rbxl), + "rbxm" => Some(OutputKind::Rbxm), + _ => None, + } + } + + fn from_plugin_path(output: &Path) -> Option { + let extension = output.extension()?.to_str()?; + + match extension { + "rbxmx" => Some(OutputKind::Rbxmx), + "rbxm" => Some(OutputKind::Rbxm), + _ => None, + } } } From 94d45a22620898cde4a3fa56dc3657929c5d1ed4 Mon Sep 17 00:00:00 2001 From: Micah Date: Thu, 20 Jul 2023 07:57:02 -0700 Subject: [PATCH 1315/1504] Remove references to LPG's patreon (#744) Given that LPG is not maintaining Rojo or its related projects, it does not make sense for us to suggest his patreon. This PR removes them. --- .github/FUNDING.yml | 1 - README.md | 1 - 2 files changed, 2 deletions(-) delete mode 100644 .github/FUNDING.yml diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml deleted file mode 100644 index a2b06a67..00000000 --- a/.github/FUNDING.yml +++ /dev/null @@ -1 +0,0 @@ -patreon: lpghatguy \ No newline at end of file diff --git a/README.md b/README.md index f87b5057..fb318f3f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,6 @@ Actions status Latest server version Rojo Documentation - Patreon

    From 89b66664369f62ec10547919263a48e3d0753a65 Mon Sep 17 00:00:00 2001 From: Micah Date: Thu, 20 Jul 2023 21:30:18 -0700 Subject: [PATCH 1316/1504] Support ambiguous syntax for Font properties (#731) --- CHANGELOG.md | 2 ++ src/resolution.rs | 25 ++++++++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3617eb47..e41a60d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ * Rework patch visualizer with many fixes and improvements ([#726]) * Added support for syncing in `.toml` files ([#633]) * Add `plugin` flag to the `build` command that outputs to the local plugins folder ([#735]) +* Added better support for `Font` properties ([#731]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 @@ -36,6 +37,7 @@ [#726]: https://github.com/rojo-rbx/rojo/pull/726 [#633]: https://github.com/rojo-rbx/rojo/pull/633 [#735]: https://github.com/rojo-rbx/rojo/pull/735 +[#731]: https://github.com/rojo-rbx/rojo/pull/731 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/src/resolution.rs b/src/resolution.rs index 56889145..c667080c 100644 --- a/src/resolution.rs +++ b/src/resolution.rs @@ -2,7 +2,7 @@ use std::borrow::Borrow; use anyhow::{bail, format_err}; use rbx_dom_weak::types::{ - Attributes, CFrame, Color3, Content, Enum, Matrix3, Tags, Variant, VariantType, Vector2, + Attributes, CFrame, Color3, Content, Enum, Font, Matrix3, Tags, Variant, VariantType, Vector2, Vector3, }; use rbx_reflection::{DataType, PropertyDescriptor}; @@ -49,6 +49,7 @@ pub enum AmbiguousValue { Array4([f64; 4]), Array12([f64; 12]), Attributes(Attributes), + Font(Font), } impl AmbiguousValue { @@ -139,6 +140,8 @@ impl AmbiguousValue { (VariantType::Attributes, AmbiguousValue::Attributes(value)) => Ok(value.into()), + (VariantType::Font, AmbiguousValue::Font(value)) => Ok(value.into()), + (_, unresolved) => Err(format_err!( "Wrong type of value for property {}.{}. Expected {:?}, got {}", class_name, @@ -176,6 +179,7 @@ impl AmbiguousValue { AmbiguousValue::Array4(_) => "an array of four numbers", AmbiguousValue::Array12(_) => "an array of twelve numbers", AmbiguousValue::Attributes(_) => "an object containing attributes", + AmbiguousValue::Font(_) => "an object describing a Font", } } } @@ -328,4 +332,23 @@ mod test { Variant::Enum(Enum::from_u32(1)), ); } + + #[test] + fn font() { + use rbx_dom_weak::types::{FontStyle, FontWeight}; + + assert_eq!( + resolve( + "TextLabel", + "FontFace", + r#"{"family": "rbxasset://fonts/families/RobotoMono.json", "weight": "Thin", "style": "Normal"}"# + ), + Variant::Font(Font { + family: "rbxasset://fonts/families/RobotoMono.json".into(), + weight: FontWeight::Thin, + style: FontStyle::Normal, + cached_face_id: None, + }) + ) + } } From f6fc5599c0ab1f418b2b78e9d3c27a41e0e4b40b Mon Sep 17 00:00:00 2001 From: Micah <48431591+nezuo@users.noreply.github.com> Date: Sun, 23 Jul 2023 19:12:48 -0500 Subject: [PATCH 1317/1504] Add plugin template (#738) Adds a new plugin template to the `init` command: `rojo init --kind plugin`. --- CHANGELOG.md | 2 + assets/default-model-project/README.md | 2 +- assets/default-plugin-project/README.md | 17 ++++++++ .../default.project.json | 6 +++ assets/default-plugin-project/gitignore.txt | 3 ++ src/cli/init.rs | 39 +++++++++++++++++-- 6 files changed, 65 insertions(+), 4 deletions(-) create mode 100644 assets/default-plugin-project/README.md create mode 100644 assets/default-plugin-project/default.project.json create mode 100644 assets/default-plugin-project/gitignore.txt diff --git a/CHANGELOG.md b/CHANGELOG.md index e41a60d9..996f4dc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ * Added support for syncing in `.toml` files ([#633]) * Add `plugin` flag to the `build` command that outputs to the local plugins folder ([#735]) * Added better support for `Font` properties ([#731]) +* Add new plugin template to the `init` command ([#738]) [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 @@ -38,6 +39,7 @@ [#633]: https://github.com/rojo-rbx/rojo/pull/633 [#735]: https://github.com/rojo-rbx/rojo/pull/735 [#731]: https://github.com/rojo-rbx/rojo/pull/731 +[#738]: https://github.com/rojo-rbx/rojo/pull/738 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/assets/default-model-project/README.md b/assets/default-model-project/README.md index 30dfc436..1c1ad23c 100644 --- a/assets/default-model-project/README.md +++ b/assets/default-model-project/README.md @@ -2,7 +2,7 @@ Generated by [Rojo](https://github.com/rojo-rbx/rojo) {rojo_version}. ## Getting Started -To build this library or plugin, use: +To build this library, use: ```bash rojo build -o "{project_name}.rbxmx" diff --git a/assets/default-plugin-project/README.md b/assets/default-plugin-project/README.md new file mode 100644 index 00000000..a02eac72 --- /dev/null +++ b/assets/default-plugin-project/README.md @@ -0,0 +1,17 @@ +# {project_name} +Generated by [Rojo](https://github.com/rojo-rbx/rojo) {rojo_version}. + +## Getting Started +To build this plugin to your local plugins folder, use: + +```bash +rojo build -p "{project_name}.rbxm" +``` + +You can include the `watch` flag to re-build it on save: + +```bash +rojo build -p "{project_name}.rbxm" --watch +``` + +For more help, check out [the Rojo documentation](https://rojo.space/docs). diff --git a/assets/default-plugin-project/default.project.json b/assets/default-plugin-project/default.project.json new file mode 100644 index 00000000..e7bb5891 --- /dev/null +++ b/assets/default-plugin-project/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "{project_name}", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/assets/default-plugin-project/gitignore.txt b/assets/default-plugin-project/gitignore.txt new file mode 100644 index 00000000..608ce35a --- /dev/null +++ b/assets/default-plugin-project/gitignore.txt @@ -0,0 +1,3 @@ +# Plugin model files +/{project_name}.rbxmx +/{project_name}.rbxm diff --git a/src/cli/init.rs b/src/cli/init.rs index b770f55d..48d513b1 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -21,6 +21,11 @@ static PLACE_PROJECT: &str = static PLACE_README: &str = include_str!("../../assets/default-place-project/README.md"); static PLACE_GIT_IGNORE: &str = include_str!("../../assets/default-place-project/gitignore.txt"); +static PLUGIN_PROJECT: &str = + include_str!("../../assets/default-plugin-project/default.project.json"); +static PLUGIN_README: &str = include_str!("../../assets/default-plugin-project/README.md"); +static PLUGIN_GIT_IGNORE: &str = include_str!("../../assets/default-plugin-project/gitignore.txt"); + /// Initializes a new Rojo project. #[derive(Debug, Parser)] pub struct InitCommand { @@ -28,7 +33,7 @@ pub struct InitCommand { #[clap(default_value = "")] pub path: PathBuf, - /// The kind of project to create, 'place' or 'model'. Defaults to place. + /// The kind of project to create, 'place', 'plugin', or 'model'. Defaults to place. #[clap(long, default_value = "place")] pub kind: InitKind, } @@ -51,6 +56,7 @@ impl InitCommand { match self.kind { InitKind::Place => init_place(&base_path, project_params)?, InitKind::Model => init_model(&base_path, project_params)?, + InitKind::Plugin => init_plugin(&base_path, project_params)?, } println!("Created project successfully."); @@ -65,8 +71,11 @@ pub enum InitKind { /// A place that contains a baseplate. Place, - /// An empty model, suitable for a library or plugin. + /// An empty model, suitable for a library. Model, + + /// An empty plugin. + Plugin, } impl FromStr for InitKind { @@ -76,8 +85,9 @@ impl FromStr for InitKind { match source { "place" => Ok(InitKind::Place), "model" => Ok(InitKind::Model), + "plugin" => Ok(InitKind::Plugin), _ => Err(format_err!( - "Invalid init kind '{}'. Valid kinds are: place, model", + "Invalid init kind '{}'. Valid kinds are: place, model, plugin", source )), } @@ -147,6 +157,29 @@ fn init_model(base_path: &Path, project_params: ProjectParams) -> anyhow::Result Ok(()) } +fn init_plugin(base_path: &Path, project_params: ProjectParams) -> anyhow::Result<()> { + println!("Creating new plugin project '{}'", project_params.name); + + let project_file = project_params.render_template(PLUGIN_PROJECT); + try_create_project(base_path, &project_file)?; + + let readme = project_params.render_template(PLUGIN_README); + write_if_not_exists(&base_path.join("README.md"), &readme)?; + + let src = base_path.join("src"); + fs::create_dir_all(&src)?; + + write_if_not_exists( + &src.join("init.server.lua"), + "print(\"Hello world, from plugin!\")\n", + )?; + + let git_ignore = project_params.render_template(PLUGIN_GIT_IGNORE); + try_git_init(base_path, &git_ignore)?; + + Ok(()) +} + /// Contains parameters used in templates to create a project. struct ProjectParams { name: String, From d0e48d9bdcf8e619f2458fa34e961cec081e8785 Mon Sep 17 00:00:00 2001 From: utrain <63367489+u-train@users.noreply.github.com> Date: Wed, 26 Jul 2023 18:10:02 -0400 Subject: [PATCH 1318/1504] Add some logging/error-handling for opener errors! (#745) After seeing an issue with the opener not opening, it was strange to see that there was no logging or error handling! This PR aims to solve that. --- CHANGELOG.md | 2 ++ src/web/api.rs | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 996f4dc7..b678e2a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* On failing to open a file from Roblox Studio, it is now logged appropriately instead of being ignored ([#745]). * Significantly improved performance of `rojo sourcemap`. ([#668]) * Fixed the diff visualizer of connected sessions. ([#674]) * Fixed disconnected session activity. ([#675]) @@ -21,6 +22,7 @@ * Added better support for `Font` properties ([#731]) * Add new plugin template to the `init` command ([#738]) +[#745]: https://github.com/rojo-rbx/rojo/pull/745 [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 [#675]: https://github.com/rojo-rbx/rojo/pull/675 diff --git a/src/web/api.rs b/src/web/api.rs index 8f500116..338862f7 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -4,6 +4,7 @@ use std::{collections::HashMap, fs, path::PathBuf, str::FromStr, sync::Arc}; use hyper::{body, Body, Method, Request, Response, StatusCode}; +use opener::OpenError; use rbx_dom_weak::types::Ref; use crate::{ @@ -236,7 +237,39 @@ impl ApiService { } }; - let _ = opener::open(script_path); + match opener::open(&script_path) { + Ok(()) => {} + Err(error) => match error { + OpenError::Io(io_error) => { + return json( + ErrorResponse::internal_error(format!( + "Attempting to open {} failed because of the following io error: {}", + script_path.display(), + io_error + )), + StatusCode::INTERNAL_SERVER_ERROR, + ) + } + OpenError::ExitStatus { + cmd, + status, + stderr, + } => { + return json( + ErrorResponse::internal_error(format!( + r#"The command '{}' to open '{}' failed with the error code '{}'. + Error logs: + {}"#, + cmd, + script_path.display(), + status, + stderr + )), + StatusCode::INTERNAL_SERVER_ERROR, + ) + } + }, + }; json_ok(&OpenResponse { session_id: self.serve_session.session_id(), From ecc31dea15d90901c65cef5fc5d6f644cf9c5c31 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 26 Jul 2023 23:50:29 -0700 Subject: [PATCH 1319/1504] View rich diffs for Source property changes (#748) --- .gitmodules | 3 + CHANGELOG.md | 2 + plugin/Packages/Highlighter | 1 + plugin/src/App/Components/CodeLabel.lua | 61 +++ .../Components/PatchVisualizer/ChangeList.lua | 85 ++++ .../Components/PatchVisualizer/DomLabel.lua | 2 + .../App/Components/PatchVisualizer/init.lua | 1 + plugin/src/App/Components/ScrollingFrame.lua | 13 +- .../StringDiffVisualizer/StringDiff.lua | 441 ++++++++++++++++++ .../Components/StringDiffVisualizer/init.lua | 202 ++++++++ .../App/Components/Studio/StudioPluginGui.lua | 6 + plugin/src/App/StatusPages/Confirming.lua | 53 ++- plugin/src/App/StatusPages/Connected.lua | 58 ++- plugin/src/App/init.lua | 1 - plugin/src/Assets.lua | 1 + 15 files changed, 924 insertions(+), 6 deletions(-) create mode 160000 plugin/Packages/Highlighter create mode 100644 plugin/src/App/Components/CodeLabel.lua create mode 100644 plugin/src/App/Components/StringDiffVisualizer/StringDiff.lua create mode 100644 plugin/src/App/Components/StringDiffVisualizer/init.lua diff --git a/.gitmodules b/.gitmodules index 2851e057..46789ed1 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,6 @@ [submodule "plugin/Packages/TestEZ"] path = plugin/Packages/TestEZ url = https://github.com/roblox/testez.git +[submodule "plugin/Packages/Highlighter"] + path = plugin/Packages/Highlighter + url = https://github.com/boatbomber/highlighter.git diff --git a/CHANGELOG.md b/CHANGELOG.md index b678e2a2..88ea4e41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ * Add `plugin` flag to the `build` command that outputs to the local plugins folder ([#735]) * Added better support for `Font` properties ([#731]) * Add new plugin template to the `init` command ([#738]) +* Added rich Source diffs in patch visualizer ([#748]) [#745]: https://github.com/rojo-rbx/rojo/pull/745 [#668]: https://github.com/rojo-rbx/rojo/pull/668 @@ -42,6 +43,7 @@ [#735]: https://github.com/rojo-rbx/rojo/pull/735 [#731]: https://github.com/rojo-rbx/rojo/pull/731 [#738]: https://github.com/rojo-rbx/rojo/pull/738 +[#748]: https://github.com/rojo-rbx/rojo/pull/748 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/plugin/Packages/Highlighter b/plugin/Packages/Highlighter new file mode 160000 index 00000000..09263eac --- /dev/null +++ b/plugin/Packages/Highlighter @@ -0,0 +1 @@ +Subproject commit 09263eacfee6ad5ff3326d12244bc45b6ae8d2f0 diff --git a/plugin/src/App/Components/CodeLabel.lua b/plugin/src/App/Components/CodeLabel.lua new file mode 100644 index 00000000..192bcf3a --- /dev/null +++ b/plugin/src/App/Components/CodeLabel.lua @@ -0,0 +1,61 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) +local Highlighter = require(Packages.Highlighter) +Highlighter.matchStudioSettings() + +local e = Roact.createElement + +local CodeLabel = Roact.PureComponent:extend("CodeLabel") + +function CodeLabel:init() + self.labelRef = Roact.createRef() + self.highlightsRef = Roact.createRef() +end + +function CodeLabel:didMount() + Highlighter.highlight({ + textObject = self.labelRef:getValue(), + }) + self:updateHighlights() +end + +function CodeLabel:didUpdate() + self:updateHighlights() +end + +function CodeLabel:updateHighlights() + local highlights = self.highlightsRef:getValue() + if not highlights then + return + end + + for _, lineLabel in highlights:GetChildren() do + local lineNum = tonumber(string.match(lineLabel.Name, "%d+") or "0") + lineLabel.BackgroundColor3 = self.props.lineBackground + lineLabel.BorderSizePixel = 0 + lineLabel.BackgroundTransparency = if self.props.markedLines[lineNum] then 0.25 else 1 + end +end + +function CodeLabel:render() + return e("TextLabel", { + Size = self.props.size, + Position = self.props.position, + Text = self.props.text, + BackgroundTransparency = 1, + Font = Enum.Font.RobotoMono, + TextSize = 16, + TextXAlignment = Enum.TextXAlignment.Left, + TextYAlignment = Enum.TextYAlignment.Top, + TextColor3 = Color3.fromRGB(255, 255, 255), + [Roact.Ref] = self.labelRef, + }, { + SyntaxHighlights = e("Folder", { + [Roact.Ref] = self.highlightsRef, + }), + }) +end + +return CodeLabel diff --git a/plugin/src/App/Components/PatchVisualizer/ChangeList.lua b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua index ed6da37a..7aac862a 100644 --- a/plugin/src/App/Components/PatchVisualizer/ChangeList.lua +++ b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua @@ -4,8 +4,10 @@ local Packages = Rojo.Packages local Roact = require(Packages.Roact) +local Assets = require(Plugin.Assets) local Theme = require(Plugin.App.Theme) local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) +local BorderedContainer = require(Plugin.App.Components.BorderedContainer) local DisplayValue = require(script.Parent.DisplayValue) local EMPTY_TABLE = {} @@ -93,6 +95,89 @@ function ChangeList:render() local metadata = values[4] or EMPTY_TABLE local isWarning = metadata.isWarning + -- Special case for .Source updates + -- because we want to display a syntax highlighted diff for better UX + if self.props.showSourceDiff and tostring(values[1]) == "Source" then + rows[row] = e("Frame", { + Size = UDim2.new(1, 0, 0, 30), + BackgroundTransparency = row % 2 ~= 0 and rowTransparency or 1, + BackgroundColor3 = theme.Diff.Row, + BorderSizePixel = 0, + LayoutOrder = row, + }, { + Padding = e("UIPadding", pad), + Layout = e("UIListLayout", { + FillDirection = Enum.FillDirection.Horizontal, + SortOrder = Enum.SortOrder.LayoutOrder, + HorizontalAlignment = Enum.HorizontalAlignment.Left, + VerticalAlignment = Enum.VerticalAlignment.Center, + }), + A = e("TextLabel", { + Text = (if isWarning then "⚠ " else "") .. tostring(values[1]), + BackgroundTransparency = 1, + Font = Enum.Font.GothamMedium, + TextSize = 14, + TextColor3 = if isWarning then theme.Diff.Warning else theme.Settings.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = props.transparency, + TextTruncate = Enum.TextTruncate.AtEnd, + Size = UDim2.new(0.3, 0, 1, 0), + LayoutOrder = 1, + }), + Button = e("TextButton", { + Text = "", + Size = UDim2.new(0.7, 0, 1, -4), + LayoutOrder = 2, + BackgroundTransparency = 1, + [Roact.Event.Activated] = function() + if props.showSourceDiff then + props.showSourceDiff(tostring(values[2]), tostring(values[3])) + end + end, + }, { + e(BorderedContainer, { + size = UDim2.new(1, 0, 1, 0), + transparency = self.props.transparency:map(function(t) + return 0.5 + (0.5 * t) + end), + }, { + Layout = e("UIListLayout", { + FillDirection = Enum.FillDirection.Horizontal, + SortOrder = Enum.SortOrder.LayoutOrder, + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + Padding = UDim.new(0, 5), + }), + Label = e("TextLabel", { + Text = "View Diff", + BackgroundTransparency = 1, + Font = Enum.Font.GothamMedium, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = props.transparency, + TextTruncate = Enum.TextTruncate.AtEnd, + Size = UDim2.new(0, 65, 1, 0), + LayoutOrder = 1, + }), + Icon = e("ImageLabel", { + Image = Assets.Images.Icons.Expand, + ImageColor3 = theme.Settings.Setting.DescriptionColor, + ImageTransparency = self.props.transparency, + + Size = UDim2.new(0, 16, 0, 16), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + + BackgroundTransparency = 1, + LayoutOrder = 2, + }), + }), + }), + }) + continue + end + rows[row] = e("Frame", { Size = UDim2.new(1, 0, 0, 30), BackgroundTransparency = row % 2 ~= 0 and rowTransparency or 1, diff --git a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua index facf70cd..8495d712 100644 --- a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua +++ b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua @@ -34,6 +34,7 @@ function Expansion:render() ChangeList = e(ChangeList, { changes = props.changeList, transparency = props.transparency, + showSourceDiff = props.showSourceDiff, }), }) end @@ -170,6 +171,7 @@ function DomLabel:render() indent = indent, transparency = props.transparency, changeList = props.changeList, + showSourceDiff = props.showSourceDiff, }) else nil, DiffIcon = if props.patchType diff --git a/plugin/src/App/Components/PatchVisualizer/init.lua b/plugin/src/App/Components/PatchVisualizer/init.lua index 73af4502..f95f96b6 100644 --- a/plugin/src/App/Components/PatchVisualizer/init.lua +++ b/plugin/src/App/Components/PatchVisualizer/init.lua @@ -71,6 +71,7 @@ function PatchVisualizer:render() changeList = node.changeList, depth = depth, transparency = self.props.transparency, + showSourceDiff = self.props.showSourceDiff, }) ) end diff --git a/plugin/src/App/Components/ScrollingFrame.lua b/plugin/src/App/Components/ScrollingFrame.lua index 2231aacb..f3d11c8c 100644 --- a/plugin/src/App/Components/ScrollingFrame.lua +++ b/plugin/src/App/Components/ScrollingFrame.lua @@ -23,19 +23,26 @@ local function ScrollingFrame(props) BottomImage = Assets.Images.ScrollBar.Bottom, ElasticBehavior = Enum.ElasticBehavior.Always, - ScrollingDirection = Enum.ScrollingDirection.Y, + ScrollingDirection = props.scrollingDirection or Enum.ScrollingDirection.Y, Size = props.size, Position = props.position, AnchorPoint = props.anchorPoint, CanvasSize = props.contentSize:map(function(value) - return UDim2.new(0, 0, 0, value.Y) + return UDim2.new( + 0, + if (props.scrollingDirection and props.scrollingDirection ~= Enum.ScrollingDirection.Y) + then value.X + else 0, + 0, + value.Y + ) end), BorderSizePixel = 0, BackgroundTransparency = 1, - [Roact.Change.AbsoluteSize] = props[Roact.Change.AbsoluteSize] + [Roact.Change.AbsoluteSize] = props[Roact.Change.AbsoluteSize], }, props[Roact.Children]) end) end diff --git a/plugin/src/App/Components/StringDiffVisualizer/StringDiff.lua b/plugin/src/App/Components/StringDiffVisualizer/StringDiff.lua new file mode 100644 index 00000000..6632c006 --- /dev/null +++ b/plugin/src/App/Components/StringDiffVisualizer/StringDiff.lua @@ -0,0 +1,441 @@ +--[[ + Based on DiffMatchPatch by Neil Fraser. + https://github.com/google/diff-match-patch +]] + +export type DiffAction = number +export type Diff = { actionType: DiffAction, value: string } +export type Diffs = { Diff } + +local StringDiff = { + ActionTypes = table.freeze({ + Equal = 0, + Delete = 1, + Insert = 2, + }), +} + +function StringDiff.findDiffs(text1: string, text2: string): Diffs + -- Validate inputs + if type(text1) ~= "string" or type(text2) ~= "string" then + error( + string.format( + "Invalid inputs to StringDiff.findDiffs, expected strings and got (%s, %s)", + type(text1), + type(text2) + ), + 2 + ) + end + + -- Shortcut if the texts are identical + if text1 == text2 then + return { { actionType = StringDiff.ActionTypes.Equal, value = text1 } } + end + + -- Trim off any shared prefix and suffix + -- These are easy to detect and can be dealt with quickly without needing a complex diff + -- and later we simply add them as Equal to the start and end of the diff + local sharedPrefix, sharedSuffix + local prefixLength = StringDiff._sharedPrefix(text1, text2) + if prefixLength > 0 then + -- Store the prefix + sharedPrefix = string.sub(text1, 1, prefixLength) + -- Now trim it off + text1 = string.sub(text1, prefixLength + 1) + text2 = string.sub(text2, prefixLength + 1) + end + + local suffixLength = StringDiff._sharedSuffix(text1, text2) + if suffixLength > 0 then + -- Store the suffix + sharedSuffix = string.sub(text1, -suffixLength) + -- Now trim it off + text1 = string.sub(text1, 1, -suffixLength - 1) + text2 = string.sub(text2, 1, -suffixLength - 1) + end + + -- Compute the diff on the middle block where the changes lie + local diffs = StringDiff._computeDiff(text1, text2) + + -- Restore the prefix and suffix + if sharedPrefix then + table.insert(diffs, 1, { actionType = StringDiff.ActionTypes.Equal, value = sharedPrefix }) + end + if sharedSuffix then + table.insert(diffs, { actionType = StringDiff.ActionTypes.Equal, value = sharedSuffix }) + end + + -- Cleanup the diff + diffs = StringDiff._reorderAndMerge(diffs) + + return diffs +end + +function StringDiff._sharedPrefix(text1: string, text2: string): number + -- Uses a binary search to find the largest common prefix between the two strings + -- Performance analysis: http://neil.fraser.name/news/2007/10/09/ + + -- Shortcut common cases + if (#text1 == 0) or (#text2 == 0) or (string.byte(text1, 1) ~= string.byte(text2, 1)) then + return 0 + end + + local pointerMin = 1 + local pointerMax = math.min(#text1, #text2) + local pointerMid = pointerMax + local pointerStart = 1 + while pointerMin < pointerMid do + if string.sub(text1, pointerStart, pointerMid) == string.sub(text2, pointerStart, pointerMid) then + pointerMin = pointerMid + pointerStart = pointerMin + else + pointerMax = pointerMid + end + pointerMid = math.floor(pointerMin + (pointerMax - pointerMin) / 2) + end + + return pointerMid +end + +function StringDiff._sharedSuffix(text1: string, text2: string): number + -- Uses a binary search to find the largest common suffix between the two strings + -- Performance analysis: http://neil.fraser.name/news/2007/10/09/ + + -- Shortcut common cases + if (#text1 == 0) or (#text2 == 0) or (string.byte(text1, -1) ~= string.byte(text2, -1)) then + return 0 + end + + local pointerMin = 1 + local pointerMax = math.min(#text1, #text2) + local pointerMid = pointerMax + local pointerEnd = 1 + while pointerMin < pointerMid do + if string.sub(text1, -pointerMid, -pointerEnd) == string.sub(text2, -pointerMid, -pointerEnd) then + pointerMin = pointerMid + pointerEnd = pointerMin + else + pointerMax = pointerMid + end + pointerMid = math.floor(pointerMin + (pointerMax - pointerMin) / 2) + end + + return pointerMid +end + +function StringDiff._computeDiff(text1: string, text2: string): Diffs + -- Assumes that the prefix and suffix have already been trimmed off + -- and shortcut returns have been made so these texts must be different + + local text1Length, text2Length = #text1, #text2 + + if text1Length == 0 then + -- It's simply inserting all of text2 into text1 + return { { actionType = StringDiff.ActionTypes.Insert, value = text2 } } + end + + if text2Length == 0 then + -- It's simply deleting all of text1 + return { { actionType = StringDiff.ActionTypes.Delete, value = text1 } } + end + + local longText = if text1Length > text2Length then text1 else text2 + local shortText = if text1Length > text2Length then text2 else text1 + local shortTextLength = #shortText + + -- Shortcut if the shorter string exists entirely inside the longer one + local indexOf = if shortTextLength == 0 then nil else string.find(longText, shortText, 1, true) + if indexOf ~= nil then + local diffs = { + { actionType = StringDiff.ActionTypes.Insert, value = string.sub(longText, 1, indexOf - 1) }, + { actionType = StringDiff.ActionTypes.Equal, value = shortText }, + { actionType = StringDiff.ActionTypes.Insert, value = string.sub(longText, indexOf + shortTextLength) }, + } + -- Swap insertions for deletions if diff is reversed + if text1Length > text2Length then + diffs[1].actionType, diffs[3].actionType = StringDiff.ActionTypes.Delete, StringDiff.ActionTypes.Delete + end + return diffs + end + + if shortTextLength == 1 then + -- Single character string + -- After the previous shortcut, the character can't be an equality + return { + { actionType = StringDiff.ActionTypes.Delete, value = text1 }, + { actionType = StringDiff.ActionTypes.Insert, value = text2 }, + } + end + + return StringDiff._bisect(text1, text2) +end + +function StringDiff._bisect(text1: string, text2: string): Diffs + -- Find the 'middle snake' of a diff, split the problem in two + -- and return the recursively constructed diff + -- See Myers 1986 paper: An O(ND) Difference Algorithm and Its Variations + + -- Cache the text lengths to prevent multiple calls + local text1Length = #text1 + local text2Length = #text2 + + local _sub, _element + local maxD = math.ceil((text1Length + text2Length) / 2) + local vOffset = maxD + local vLength = 2 * maxD + local v1 = table.create(vLength) + local v2 = table.create(vLength) + + -- Setting all elements to -1 is faster in Lua than mixing integers and nil + for x = 0, vLength - 1 do + v1[x] = -1 + v2[x] = -1 + end + v1[vOffset + 1] = 0 + v2[vOffset + 1] = 0 + local delta = text1Length - text2Length + + -- If the total number of characters is odd, then + -- the front path will collide with the reverse path + local front = (delta % 2 ~= 0) + + -- Offsets for start and end of k loop + -- Prevents mapping of space beyond the grid + local k1Start = 0 + local k1End = 0 + local k2Start = 0 + local k2End = 0 + for d = 0, maxD - 1 do + -- Walk the front path one step + for k1 = -d + k1Start, d - k1End, 2 do + local k1_offset = vOffset + k1 + local x1 + if (k1 == -d) or ((k1 ~= d) and (v1[k1_offset - 1] < v1[k1_offset + 1])) then + x1 = v1[k1_offset + 1] + else + x1 = v1[k1_offset - 1] + 1 + end + local y1 = x1 - k1 + while + (x1 <= text1Length) + and (y1 <= text2Length) + and (string.sub(text1, x1, x1) == string.sub(text2, y1, y1)) + do + x1 = x1 + 1 + y1 = y1 + 1 + end + v1[k1_offset] = x1 + if x1 > text1Length + 1 then + -- Ran off the right of the graph + k1End = k1End + 2 + elseif y1 > text2Length + 1 then + -- Ran off the bottom of the graph + k1Start = k1Start + 2 + elseif front then + local k2_offset = vOffset + delta - k1 + if k2_offset >= 0 and k2_offset < vLength and v2[k2_offset] ~= -1 then + -- Mirror x2 onto top-left coordinate system + local x2 = text1Length - v2[k2_offset] + 1 + if x1 > x2 then + -- Overlap detected + return StringDiff._bisectSplit(text1, text2, x1, y1) + end + end + end + end + + -- Walk the reverse path one step + for k2 = -d + k2Start, d - k2End, 2 do + local k2_offset = vOffset + k2 + local x2 + if (k2 == -d) or ((k2 ~= d) and (v2[k2_offset - 1] < v2[k2_offset + 1])) then + x2 = v2[k2_offset + 1] + else + x2 = v2[k2_offset - 1] + 1 + end + local y2 = x2 - k2 + while + (x2 <= text1Length) + and (y2 <= text2Length) + and (string.sub(text1, -x2, -x2) == string.sub(text2, -y2, -y2)) + do + x2 = x2 + 1 + y2 = y2 + 1 + end + v2[k2_offset] = x2 + if x2 > text1Length + 1 then + -- Ran off the left of the graph + k2End = k2End + 2 + elseif y2 > text2Length + 1 then + -- Ran off the top of the graph + k2Start = k2Start + 2 + elseif not front then + local k1_offset = vOffset + delta - k2 + if k1_offset >= 0 and k1_offset < vLength and v1[k1_offset] ~= -1 then + local x1 = v1[k1_offset] + local y1 = vOffset + x1 - k1_offset + -- Mirror x2 onto top-left coordinate system + x2 = text1Length - x2 + 1 + if x1 > x2 then + -- Overlap detected + return StringDiff._bisectSplit(text1, text2, x1, y1) + end + end + end + end + end + + -- Number of diffs equals number of characters, no commonality at all + return { + { actionType = StringDiff.ActionTypes.Delete, value = text1 }, + { actionType = StringDiff.ActionTypes.Insert, value = text2 }, + } +end + +function StringDiff._bisectSplit(text1: string, text2: string, x: number, y: number): Diffs + -- Given the location of the 'middle snake', + -- split the diff in two parts and recurse + + local text1a = string.sub(text1, 1, x - 1) + local text2a = string.sub(text2, 1, y - 1) + local text1b = string.sub(text1, x) + local text2b = string.sub(text2, y) + + -- Compute both diffs serially + local diffs = StringDiff.findDiffs(text1a, text2a) + local diffsB = StringDiff.findDiffs(text1b, text2b) + + -- Merge diffs + table.move(diffsB, 1, #diffsB, #diffs + 1, diffs) + return diffs +end + +function StringDiff._reorderAndMerge(diffs: Diffs): Diffs + -- Reorder and merge like edit sections and merge equalities + -- Any edit section can move as long as it doesn't cross an equality + + -- Add a dummy entry at the end + table.insert(diffs, { actionType = StringDiff.ActionTypes.Equal, value = "" }) + + local pointer = 1 + local countDelete, countInsert = 0, 0 + local textDelete, textInsert = "", "" + local commonLength + while diffs[pointer] do + local actionType = diffs[pointer].actionType + if actionType == StringDiff.ActionTypes.Insert then + countInsert = countInsert + 1 + textInsert = textInsert .. diffs[pointer].value + pointer = pointer + 1 + elseif actionType == StringDiff.ActionTypes.Delete then + countDelete = countDelete + 1 + textDelete = textDelete .. diffs[pointer].value + pointer = pointer + 1 + elseif actionType == StringDiff.ActionTypes.Equal then + -- Upon reaching an equality, check for prior redundancies + if countDelete + countInsert > 1 then + if (countDelete > 0) and (countInsert > 0) then + -- Factor out any common prefixies + commonLength = StringDiff._sharedPrefix(textInsert, textDelete) + if commonLength > 0 then + local back_pointer = pointer - countDelete - countInsert + if + (back_pointer > 1) and (diffs[back_pointer - 1].actionType == StringDiff.ActionTypes.Equal) + then + diffs[back_pointer - 1].value = diffs[back_pointer - 1].value + .. string.sub(textInsert, 1, commonLength) + else + table.insert(diffs, 1, { + actionType = StringDiff.ActionTypes.Equal, + value = string.sub(textInsert, 1, commonLength), + }) + pointer = pointer + 1 + end + textInsert = string.sub(textInsert, commonLength + 1) + textDelete = string.sub(textDelete, commonLength + 1) + end + -- Factor out any common suffixies + commonLength = StringDiff._sharedSuffix(textInsert, textDelete) + if commonLength ~= 0 then + diffs[pointer].value = string.sub(textInsert, -commonLength) .. diffs[pointer].value + textInsert = string.sub(textInsert, 1, -commonLength - 1) + textDelete = string.sub(textDelete, 1, -commonLength - 1) + end + end + -- Delete the offending records and add the merged ones + pointer = pointer - countDelete - countInsert + for _ = 1, countDelete + countInsert do + table.remove(diffs, pointer) + end + if #textDelete > 0 then + table.insert(diffs, pointer, { actionType = StringDiff.ActionTypes.Delete, value = textDelete }) + pointer = pointer + 1 + end + if #textInsert > 0 then + table.insert(diffs, pointer, { actionType = StringDiff.ActionTypes.Insert, value = textInsert }) + pointer = pointer + 1 + end + pointer = pointer + 1 + elseif (pointer > 1) and (diffs[pointer - 1].actionType == StringDiff.ActionTypes.Equal) then + -- Merge this equality with the previous one + diffs[pointer - 1].value = diffs[pointer - 1].value .. diffs[pointer].value + table.remove(diffs, pointer) + else + pointer = pointer + 1 + end + countInsert, countDelete = 0, 0 + textDelete, textInsert = "", "" + end + end + if diffs[#diffs].value == "" then + -- Remove the dummy entry at the end + diffs[#diffs] = nil + end + + -- Second pass: look for single edits surrounded on both sides by equalities + -- which can be shifted sideways to eliminate an equality + -- e.g: ABAC -> ABAC + local changes = false + pointer = 2 + -- Intentionally ignore the first and last element (don't need checking) + while pointer < #diffs do + local prevDiff, nextDiff = diffs[pointer - 1], diffs[pointer + 1] + if + (prevDiff.actionType == StringDiff.ActionTypes.Equal) + and (nextDiff.actionType == StringDiff.ActionTypes.Equal) + then + -- This is a single edit surrounded by equalities + local currentDiff = diffs[pointer] + local currentText = currentDiff.value + local prevText = prevDiff.value + local nextText = nextDiff.value + if #prevText == 0 then + table.remove(diffs, pointer - 1) + changes = true + elseif string.sub(currentText, -#prevText) == prevText then + -- Shift the edit over the previous equality + currentDiff.value = prevText .. string.sub(currentText, 1, -#prevText - 1) + nextDiff.value = prevText .. nextDiff.value + table.remove(diffs, pointer - 1) + changes = true + elseif string.sub(currentText, 1, #nextText) == nextText then + -- Shift the edit over the next equality + prevDiff.value = prevText .. nextText + currentDiff.value = string.sub(currentText, #nextText + 1) .. nextText + table.remove(diffs, pointer + 1) + changes = true + end + end + pointer = pointer + 1 + end + + -- If shifts were made, the diffs need reordering and another shift sweep + if changes then + return StringDiff._reorderAndMerge(diffs) + end + + return diffs +end + +return StringDiff diff --git a/plugin/src/App/Components/StringDiffVisualizer/init.lua b/plugin/src/App/Components/StringDiffVisualizer/init.lua new file mode 100644 index 00000000..cbdc7dec --- /dev/null +++ b/plugin/src/App/Components/StringDiffVisualizer/init.lua @@ -0,0 +1,202 @@ +local TextService = game:GetService("TextService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) +local Log = require(Packages.Log) +local Highlighter = require(Packages.Highlighter) +local StringDiff = require(script:FindFirstChild("StringDiff")) + +local Theme = require(Plugin.App.Theme) + +local CodeLabel = require(Plugin.App.Components.CodeLabel) +local BorderedContainer = require(Plugin.App.Components.BorderedContainer) +local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) + +local e = Roact.createElement + +local StringDiffVisualizer = Roact.Component:extend("StringDiffVisualizer") + +function StringDiffVisualizer:init() + self.scriptBackground, self.setScriptBackground = Roact.createBinding(Color3.fromRGB(0, 0, 0)) + self.contentSize, self.setContentSize = Roact.createBinding(Vector2.new(0, 0)) + + -- Ensure that the script background is up to date with the current theme + self.themeChangedConnection = settings().Studio.ThemeChanged:Connect(function() + task.defer(function() + -- Defer to allow Highlighter to process the theme change first + self:updateScriptBackground() + end) + end) + + self:calculateContentSize() + self:updateScriptBackground() + + self:setState({ + add = {}, + remove = {}, + }) +end + +function StringDiffVisualizer:willUnmount() + self.themeChangedConnection:Disconnect() +end + +function StringDiffVisualizer:updateScriptBackground() + local backgroundColor = Highlighter.getTokenColor("background") + if backgroundColor ~= self.scriptBackground:getValue() then + self.setScriptBackground(backgroundColor) + end +end + +function StringDiffVisualizer:didUpdate(previousProps) + if previousProps.oldText ~= self.props.oldText or previousProps.newText ~= self.props.newText then + self:calculateContentSize() + local add, remove = self:calculateDiffLines() + self:setState({ + add = add, + remove = remove, + }) + end +end + +function StringDiffVisualizer:calculateContentSize() + local oldText, newText = self.props.oldText, self.props.newText + + local oldTextBounds = TextService:GetTextSize(oldText, 16, Enum.Font.RobotoMono, Vector2.new(99999, 99999)) + local newTextBounds = TextService:GetTextSize(newText, 16, Enum.Font.RobotoMono, Vector2.new(99999, 99999)) + + self.setContentSize( + Vector2.new(math.max(oldTextBounds.X, newTextBounds.X), math.max(oldTextBounds.Y, newTextBounds.Y)) + ) +end + +function StringDiffVisualizer:calculateDiffLines() + local oldText, newText = self.props.oldText, self.props.newText + + -- Diff the two texts + local startClock = os.clock() + local diffs = StringDiff.findDiffs(oldText, newText) + local stopClock = os.clock() + + Log.trace( + "Diffing {} byte and {} byte strings took {} microseconds and found {} diff sections", + #oldText, + #newText, + math.round((stopClock - startClock) * 1000 * 1000), + #diffs + ) + + -- Determine which lines to highlight + local add, remove = {}, {} + + local oldLineNum, newLineNum = 1, 1 + for _, diff in diffs do + local actionType, text = diff.actionType, diff.value + local lines = select(2, string.gsub(text, "\n", "\n")) + + if actionType == StringDiff.ActionTypes.Equal then + oldLineNum += lines + newLineNum += lines + elseif actionType == StringDiff.ActionTypes.Insert then + if lines > 0 then + local textLines = string.split(text, "\n") + for i, textLine in textLines do + if string.match(textLine, "%S") then + add[newLineNum + i - 1] = true + end + end + else + if string.match(text, "%S") then + add[newLineNum] = true + end + end + newLineNum += lines + elseif actionType == StringDiff.ActionTypes.Delete then + if lines > 0 then + local textLines = string.split(text, "\n") + for i, textLine in textLines do + if string.match(textLine, "%S") then + remove[oldLineNum + i - 1] = true + end + end + else + if string.match(text, "%S") then + remove[oldLineNum] = true + end + end + oldLineNum += lines + else + Log.warn("Unknown diff action: {} {}", actionType, text) + end + end + + return add, remove +end + +function StringDiffVisualizer:render() + local oldText, newText = self.props.oldText, self.props.newText + + return Theme.with(function(theme) + return e(BorderedContainer, { + size = self.props.size, + position = self.props.position, + anchorPoint = self.props.anchorPoint, + transparency = self.props.transparency, + }, { + Background = e("Frame", { + Size = UDim2.new(1, 0, 1, 0), + Position = UDim2.new(0, 0, 0, 0), + BorderSizePixel = 0, + BackgroundColor3 = self.scriptBackground, + ZIndex = -10, + }, { + UICorner = e("UICorner", { + CornerRadius = UDim.new(0, 5), + }), + }), + Separator = e("Frame", { + Size = UDim2.new(0, 2, 1, 0), + Position = UDim2.new(0.5, 0, 0, 0), + AnchorPoint = Vector2.new(0.5, 0), + BorderSizePixel = 0, + BackgroundColor3 = theme.BorderedContainer.BorderColor, + BackgroundTransparency = 0.5, + }), + Old = e(ScrollingFrame, { + position = UDim2.new(0, 2, 0, 2), + size = UDim2.new(0.5, -7, 1, -4), + scrollingDirection = Enum.ScrollingDirection.XY, + transparency = self.props.transparency, + contentSize = self.contentSize, + }, { + Source = e(CodeLabel, { + size = UDim2.new(1, 0, 1, 0), + position = UDim2.new(0, 0, 0, 0), + text = oldText, + lineBackground = theme.Diff.Remove, + markedLines = self.state.remove, + }), + }), + New = e(ScrollingFrame, { + position = UDim2.new(0.5, 5, 0, 2), + size = UDim2.new(0.5, -7, 1, -4), + scrollingDirection = Enum.ScrollingDirection.XY, + transparency = self.props.transparency, + contentSize = self.contentSize, + }, { + Source = e(CodeLabel, { + size = UDim2.new(1, 0, 1, 0), + position = UDim2.new(0, 0, 0, 0), + text = newText, + lineBackground = theme.Diff.Add, + markedLines = self.state.add, + }), + }), + }) + end) +end + +return StringDiffVisualizer diff --git a/plugin/src/App/Components/Studio/StudioPluginGui.lua b/plugin/src/App/Components/Studio/StudioPluginGui.lua index 59bd3d85..6b9910a9 100644 --- a/plugin/src/App/Components/Studio/StudioPluginGui.lua +++ b/plugin/src/App/Components/Studio/StudioPluginGui.lua @@ -76,6 +76,12 @@ function StudioPluginGui:didUpdate(lastProps) if self.props.active ~= lastProps.active then -- This is intentionally in didUpdate to make sure the initial active state -- (if the PluginGui is open initially) is preserved. + + -- Studio widgets are very unreliable and sometimes need to be flickered + -- in order to force them to render correctly + -- This happens within a single frame so it doesn't flicker visibly + self.pluginGui.Enabled = self.props.active + self.pluginGui.Enabled = not self.props.active self.pluginGui.Enabled = self.props.active end end diff --git a/plugin/src/App/StatusPages/Confirming.lua b/plugin/src/App/StatusPages/Confirming.lua index a5592347..4a258bbd 100644 --- a/plugin/src/App/StatusPages/Confirming.lua +++ b/plugin/src/App/StatusPages/Confirming.lua @@ -13,6 +13,7 @@ local Header = require(Plugin.App.Components.Header) local StudioPluginGui = require(Plugin.App.Components.Studio.StudioPluginGui) local Tooltip = require(Plugin.App.Components.Tooltip) local PatchVisualizer = require(Plugin.App.Components.PatchVisualizer) +local StringDiffVisualizer = require(Plugin.App.Components.StringDiffVisualizer) local e = Roact.createElement @@ -21,6 +22,12 @@ local ConfirmingPage = Roact.Component:extend("ConfirmingPage") function ConfirmingPage:init() self.contentSize, self.setContentSize = Roact.createBinding(0) self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0)) + + self:setState({ + showingSourceDiff = false, + oldSource = "", + newSource = "", + }) end function ConfirmingPage:render() @@ -55,6 +62,14 @@ function ConfirmingPage:render() changeListHeaders = { "Property", "Current", "Incoming" }, patch = self.props.confirmData.patch, instanceMap = self.props.confirmData.instanceMap, + + showSourceDiff = function(oldSource: string, newSource: string) + self:setState({ + showingSourceDiff = true, + oldSource = oldSource, + newSource = newSource, + }) + end, }), Buttons = e("Frame", { @@ -120,6 +135,43 @@ function ConfirmingPage:render() PaddingLeft = UDim.new(0, 20), PaddingRight = UDim.new(0, 20), }), + + SourceDiff = e(StudioPluginGui, { + id = "Rojo_ConfirmingSourceDiff", + title = "Source diff", + active = self.state.showingSourceDiff, + + initDockState = Enum.InitialDockState.Float, + overridePreviousState = true, + floatingSize = Vector2.new(500, 350), + minimumSize = Vector2.new(400, 250), + + zIndexBehavior = Enum.ZIndexBehavior.Sibling, + + onClose = function() + self:setState({ + showingSourceDiff = false, + }) + end, + }, { + TooltipsProvider = e(Tooltip.Provider, nil, { + Tooltips = e(Tooltip.Container, nil), + Content = e("Frame", { + Size = UDim2.fromScale(1, 1), + BackgroundTransparency = 1, + }, { + e(StringDiffVisualizer, { + size = UDim2.new(1, -10, 1, -10), + position = UDim2.new(0, 5, 0, 5), + anchorPoint = Vector2.new(0, 0), + transparency = self.props.transparency, + + oldText = self.state.oldSource, + newText = self.state.newSource, + }) + }), + }), + }), }) if self.props.createPopup then @@ -132,7 +184,6 @@ function ConfirmingPage:render() active = true, initDockState = Enum.InitialDockState.Float, - initEnabled = true, overridePreviousState = true, floatingSize = Vector2.new(500, 350), minimumSize = Vector2.new(400, 250), diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index 00f6822b..12ba2fc1 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -10,12 +10,14 @@ local Theme = require(Plugin.App.Theme) local Assets = require(Plugin.Assets) local PatchSet = require(Plugin.PatchSet) +local StudioPluginGui = require(Plugin.App.Components.Studio.StudioPluginGui) local Header = require(Plugin.App.Components.Header) local IconButton = require(Plugin.App.Components.IconButton) local TextButton = require(Plugin.App.Components.TextButton) local BorderedContainer = require(Plugin.App.Components.BorderedContainer) local Tooltip = require(Plugin.App.Components.Tooltip) local PatchVisualizer = require(Plugin.App.Components.PatchVisualizer) +local StringDiffVisualizer = require(Plugin.App.Components.StringDiffVisualizer) local e = Roact.createElement @@ -39,7 +41,7 @@ function timeSinceText(elapsed: number): string return ageText end -local ChangesDrawer = Roact.Component:extend("ConnectedPage") +local ChangesDrawer = Roact.Component:extend("ChangesDrawer") function ChangesDrawer:init() -- Hold onto the serve session during the lifecycle of this component @@ -84,6 +86,8 @@ function ChangesDrawer:render() layoutOrder = 3, patchTree = self.props.patchTree, + + showSourceDiff = self.props.showSourceDiff, }), }) end) @@ -226,6 +230,9 @@ function ConnectedPage:init() self:setState({ renderChanges = false, hoveringChangeInfo = false, + showingSourceDiff = false, + oldSource = "", + newSource = "", }) self.changeInfoText, self.setChangeInfoText = Roact.createBinding("") @@ -239,7 +246,11 @@ end function ConnectedPage:didUpdate(previousProps) if self.props.patchData.timestamp ~= previousProps.patchData.timestamp then + -- New patch recieved self:startChangeInfoTextUpdater() + self:setState({ + showingSourceDiff = false, + }) end end @@ -367,6 +378,14 @@ function ConnectedPage:render() height = self.changeDrawerHeight, layoutOrder = 5, + showSourceDiff = function(oldSource: string, newSource: string) + self:setState({ + showingSourceDiff = true, + oldSource = oldSource, + newSource = newSource, + }) + end, + onClose = function() self.changeDrawerMotor:setGoal(Flipper.Spring.new(0, { frequency = 4, @@ -374,6 +393,43 @@ function ConnectedPage:render() })) end, }), + + SourceDiff = e(StudioPluginGui, { + id = "Rojo_ConnectedSourceDiff", + title = "Source diff", + active = self.state.showingSourceDiff, + + initDockState = Enum.InitialDockState.Float, + overridePreviousState = true, + floatingSize = Vector2.new(500, 350), + minimumSize = Vector2.new(400, 250), + + zIndexBehavior = Enum.ZIndexBehavior.Sibling, + + onClose = function() + self:setState({ + showingSourceDiff = false, + }) + end, + }, { + TooltipsProvider = e(Tooltip.Provider, nil, { + Tooltips = e(Tooltip.Container, nil), + Content = e("Frame", { + Size = UDim2.fromScale(1, 1), + BackgroundTransparency = 1, + }, { + e(StringDiffVisualizer, { + size = UDim2.new(1, -10, 1, -10), + position = UDim2.new(0, 5, 0, 5), + anchorPoint = Vector2.new(0, 0), + transparency = self.props.transparency, + + oldText = self.state.oldSource, + newText = self.state.newSource, + }) + }), + }), + }), }) end) end diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index f4c30f3c..1dc88c1e 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -554,7 +554,6 @@ function App:render() active = self.state.guiEnabled, initDockState = Enum.InitialDockState.Right, - initEnabled = false, overridePreviousState = false, floatingSize = Vector2.new(320, 210), minimumSize = Vector2.new(300, 210), diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index 020ec3eb..bee8f3c7 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -24,6 +24,7 @@ local Assets = { Close = "rbxassetid://6012985953", Back = "rbxassetid://6017213752", Reset = "rbxassetid://10142422327", + Expand = "rbxassetid://12045401097", }, Diff = { Add = "rbxassetid://10434145835", From 34024d852412dc3090eeff54ba8a1e6e3694c13f Mon Sep 17 00:00:00 2001 From: boatbomber Date: Mon, 31 Jul 2023 22:26:16 -0700 Subject: [PATCH 1320/1504] Fix PatchTree performance issues (#755) When building the tree, I've implemented a few improvements: - We no longer traverse the full ancestry for every leaf node- we exit early when we find a node that already exists - We no longer search the entire tree to see if a node id exists before creating one with that id, we just check if is in the map --- CHANGELOG.md | 2 + plugin/src/PatchTree.lua | 145 ++++++++++++++++++++++++--------------- 2 files changed, 90 insertions(+), 57 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88ea4e41..a4e2803a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ * Added better support for `Font` properties ([#731]) * Add new plugin template to the `init` command ([#738]) * Added rich Source diffs in patch visualizer ([#748]) +* Fix PatchTree performance issues ([#755]) [#745]: https://github.com/rojo-rbx/rojo/pull/745 [#668]: https://github.com/rojo-rbx/rojo/pull/668 @@ -44,6 +45,7 @@ [#731]: https://github.com/rojo-rbx/rojo/pull/731 [#738]: https://github.com/rojo-rbx/rojo/pull/738 [#748]: https://github.com/rojo-rbx/rojo/pull/748 +[#755]: https://github.com/rojo-rbx/rojo/pull/755 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/plugin/src/PatchTree.lua b/plugin/src/PatchTree.lua index b241472d..568f2412 100644 --- a/plugin/src/PatchTree.lua +++ b/plugin/src/PatchTree.lua @@ -64,18 +64,18 @@ local Tree = {} Tree.__index = Tree function Tree.new() - local tree = { - idToNode = {}, + local tree = { + idToNode = {}, ROOT = { className = "DataModel", name = "ROOT", children = {}, }, - } - -- Add ROOT to idToNode or it won't be found by getNode since that searches *within* ROOT + } + -- Add ROOT to idToNode or it won't be found by getNode since that searches *within* ROOT tree.idToNode["ROOT"] = tree.ROOT - return setmetatable(tree, Tree) + return setmetatable(tree, Tree) end -- Iterates over all sub-nodes, depth first @@ -94,23 +94,27 @@ end -- Finds a node by id, depth first -- searchNode is the node to start the search within, defaults to root function Tree:getNode(id, searchNode) - if self.idToNode[id] then - return self.idToNode[id] - end + if self.idToNode[id] then + return self.idToNode[id] + end local searchChildren = (searchNode or self.ROOT).children - for nodeId, node in searchChildren do - if nodeId == id then - self.idToNode[id] = node - return node - end - local descendant = self:getNode(id, node) - if descendant then - return descendant - end - end + for nodeId, node in searchChildren do + if nodeId == id then + self.idToNode[id] = node + return node + end + local descendant = self:getNode(id, node) + if descendant then + return descendant + end + end - return nil + return nil +end + +function Tree:doesNodeExist(id) + return self.idToNode[id] ~= nil end -- Adds a node to the tree as a child of the node with id == parent @@ -120,52 +124,53 @@ end function Tree:addNode(parent, props) assert(props.id, "props must contain id") - parent = parent or "ROOT" + parent = parent or "ROOT" - local node = self:getNode(props.id) - if node then + if self:doesNodeExist(props.id) then -- Update existing node - for k, v in props do - node[k] = v - end - return node - end + local node = self:getNode(props.id) + for k, v in props do + node[k] = v + end + return node + end - node = table.clone(props) - node.children = {} + local node = table.clone(props) + node.children = {} node.parentId = parent - local parentNode = self:getNode(parent) - if not parentNode then - Log.warn("Failed to create node since parent doesnt exist: {}, {}", parent, props) - return - end + local parentNode = self:getNode(parent) + if not parentNode then + Log.warn("Failed to create node since parent doesnt exist: {}, {}", parent, props) + return + end - parentNode.children[node.id] = node - self.idToNode[node.id] = node + parentNode.children[node.id] = node + self.idToNode[node.id] = node - return node + return node end -- Given a list of ancestor ids in descending order, builds the nodes for them -- using the patch and instanceMap info -function Tree:buildAncestryNodes(ancestryIds: { string }, patch, instanceMap) - -- Build nodes for ancestry by going up the tree - local previousId = "ROOT" - for _, ancestorId in ancestryIds do - local value = instanceMap.fromIds[ancestorId] or patch.added[ancestorId] - if not value then - Log.warn("Failed to find ancestor object for " .. ancestorId) - continue - end - self:addNode(previousId, { - id = ancestorId, - className = value.ClassName, - name = value.Name, - instance = if typeof(value) == "Instance" then value else nil, - }) - previousId = ancestorId - end +function Tree:buildAncestryNodes(previousId: string?, ancestryIds: { string }, patch, instanceMap) + -- Build nodes for ancestry by going up the tree + previousId = previousId or "ROOT" + + for _, ancestorId in ancestryIds do + local value = instanceMap.fromIds[ancestorId] or patch.added[ancestorId] + if not value then + Log.warn("Failed to find ancestor object for " .. ancestorId) + continue + end + self:addNode(previousId, { + id = ancestorId, + className = value.ClassName, + name = value.Name, + instance = if typeof(value) == "Instance" then value else nil, + }) + previousId = ancestorId + end end local PatchTree = {} @@ -175,6 +180,8 @@ local PatchTree = {} function PatchTree.build(patch, instanceMap, changeListHeaders) local tree = Tree.new() + local knownAncestors = {} + for _, change in patch.updated do local instance = instanceMap.fromIds[change.id] if not instance then @@ -185,13 +192,21 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) local ancestryIds = {} local parentObject = instance.Parent local parentId = instanceMap.fromInstances[parentObject] + local previousId = nil while parentObject do + if knownAncestors[parentId] then + -- We've already added this ancestor + previousId = parentId + break + end + table.insert(ancestryIds, 1, parentId) + knownAncestors[parentId] = true parentObject = parentObject.Parent parentId = instanceMap.fromInstances[parentObject] end - tree:buildAncestryNodes(ancestryIds, patch, instanceMap) + tree:buildAncestryNodes(previousId, ancestryIds, patch, instanceMap) -- Gather detail text local changeList, hint = nil, nil @@ -268,14 +283,22 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) local ancestryIds = {} local parentObject = instance.Parent local parentId = instanceMap.fromInstances[parentObject] or HttpService:GenerateGUID(false) + local previousId = nil while parentObject do + if knownAncestors[parentId] then + -- We've already added this ancestor + previousId = parentId + break + end + instanceMap:insert(parentId, parentObject) -- This ensures we can find the parent later table.insert(ancestryIds, 1, parentId) + knownAncestors[parentId] = true parentObject = parentObject.Parent parentId = instanceMap.fromInstances[parentObject] or HttpService:GenerateGUID(false) end - tree:buildAncestryNodes(ancestryIds, patch, instanceMap) + tree:buildAncestryNodes(previousId, ancestryIds, patch, instanceMap) -- Add this node to tree local nodeId = instanceMap.fromInstances[instance] or HttpService:GenerateGUID(false) @@ -295,8 +318,16 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) local parentId = change.Parent local parentData = patch.added[parentId] local parentObject = instanceMap.fromIds[parentId] + local previousId = nil while parentId do + if knownAncestors[parentId] then + -- We've already added this ancestor + previousId = parentId + break + end + table.insert(ancestryIds, 1, parentId) + knownAncestors[parentId] = true parentId = nil if parentData then @@ -312,7 +343,7 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) end end - tree:buildAncestryNodes(ancestryIds, patch, instanceMap) + tree:buildAncestryNodes(previousId, ancestryIds, patch, instanceMap) -- Gather detail text local changeList, hint = nil, nil From 5b22ef192e048d3ff8f542cbfeec786cb8f816f8 Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 1 Aug 2023 09:33:06 -0700 Subject: [PATCH 1321/1504] Don't override initial state for source diff view (#760) --- CHANGELOG.md | 2 ++ plugin/src/App/StatusPages/Confirming.lua | 2 +- plugin/src/App/StatusPages/Connected.lua | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a4e2803a..0d4de214 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ * Add new plugin template to the `init` command ([#738]) * Added rich Source diffs in patch visualizer ([#748]) * Fix PatchTree performance issues ([#755]) +* Don't override the initial enabled state for source diffing ([#760]) [#745]: https://github.com/rojo-rbx/rojo/pull/745 [#668]: https://github.com/rojo-rbx/rojo/pull/668 @@ -46,6 +47,7 @@ [#738]: https://github.com/rojo-rbx/rojo/pull/738 [#748]: https://github.com/rojo-rbx/rojo/pull/748 [#755]: https://github.com/rojo-rbx/rojo/pull/755 +[#760]: https://github.com/rojo-rbx/rojo/pull/760 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/plugin/src/App/StatusPages/Confirming.lua b/plugin/src/App/StatusPages/Confirming.lua index 4a258bbd..74c814a1 100644 --- a/plugin/src/App/StatusPages/Confirming.lua +++ b/plugin/src/App/StatusPages/Confirming.lua @@ -184,7 +184,7 @@ function ConfirmingPage:render() active = true, initDockState = Enum.InitialDockState.Float, - overridePreviousState = true, + overridePreviousState = false, floatingSize = Vector2.new(500, 350), minimumSize = Vector2.new(400, 250), diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index 12ba2fc1..27f4e7ca 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -400,7 +400,7 @@ function ConnectedPage:render() active = self.state.showingSourceDiff, initDockState = Enum.InitialDockState.Float, - overridePreviousState = true, + overridePreviousState = false, floatingSize = Vector2.new(500, 350), minimumSize = Vector2.new(400, 250), From 4cb5d4a9c5ffeeae14d507466dd0b5429b72dfbb Mon Sep 17 00:00:00 2001 From: utrain <63367489+u-train@users.noreply.github.com> Date: Tue, 1 Aug 2023 12:36:29 -0400 Subject: [PATCH 1322/1504] Update Theme to use Color3.fromHex (#761) --- CHANGELOG.md | 2 + plugin/src/App/Theme.lua | 163 ++++++++++++++++++--------------------- 2 files changed, 79 insertions(+), 86 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0d4de214..466e7de4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Internally for themes, we use `Color3.fromHex` now instead of custom-made solution ([#761]). * On failing to open a file from Roblox Studio, it is now logged appropriately instead of being ignored ([#745]). * Significantly improved performance of `rojo sourcemap`. ([#668]) * Fixed the diff visualizer of connected sessions. ([#674]) @@ -25,6 +26,7 @@ * Fix PatchTree performance issues ([#755]) * Don't override the initial enabled state for source diffing ([#760]) +[#761]: https://github.com/rojo-rbx/rojo/pull/761 [#745]: https://github.com/rojo-rbx/rojo/pull/745 [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index 8ef05fab..fb4af8c5 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -23,207 +23,198 @@ local Log = require(Packages.Log) local strict = require(script.Parent.Parent.strict) --- Copying hex colors back and forth from design programs is faster -local function hexColor(decimal) - local red = bit32.band(bit32.rshift(decimal, 16), 2^8 - 1) - local green = bit32.band(bit32.rshift(decimal, 8), 2^8 - 1) - local blue = bit32.band(decimal, 2^8 - 1) - - return Color3.fromRGB(red, green, blue) -end - -local BRAND_COLOR = hexColor(0xE13835) +local BRAND_COLOR = Color3.fromHex("E13835") local lightTheme = strict("LightTheme", { - BackgroundColor = hexColor(0xFFFFFF), + BackgroundColor = Color3.fromHex("FFFFFF"), Button = { Solid = { - ActionFillColor = hexColor(0xFFFFFF), + ActionFillColor = Color3.fromHex("FFFFFF"), ActionFillTransparency = 0.8, Enabled = { - TextColor = hexColor(0xFFFFFF), + TextColor = Color3.fromHex("FFFFFF"), BackgroundColor = BRAND_COLOR, }, Disabled = { - TextColor = hexColor(0xFFFFFF), + TextColor = Color3.fromHex("FFFFFF"), BackgroundColor = BRAND_COLOR, }, }, Bordered = { - ActionFillColor = hexColor(0x000000), + ActionFillColor = Color3.fromHex("000000"), ActionFillTransparency = 0.9, Enabled = { - TextColor = hexColor(0x393939), - BorderColor = hexColor(0xACACAC), + TextColor = Color3.fromHex("393939"), + BorderColor = Color3.fromHex("ACACAC"), }, Disabled = { - TextColor = hexColor(0x393939), - BorderColor = hexColor(0xACACAC), + TextColor = Color3.fromHex("393939"), + BorderColor = Color3.fromHex("ACACAC"), }, }, }, Checkbox = { Active = { - IconColor = hexColor(0xFFFFFF), + IconColor = Color3.fromHex("FFFFFF"), BackgroundColor = BRAND_COLOR, }, Inactive = { - IconColor = hexColor(0xEEEEEE), - BorderColor = hexColor(0xAFAFAF), + IconColor = Color3.fromHex("EEEEEE"), + BorderColor = Color3.fromHex("AFAFAF"), }, }, Dropdown = { - TextColor = hexColor(0x00000), - BorderColor = hexColor(0xAFAFAF), - BackgroundColor = hexColor(0xEEEEEE), + TextColor = Color3.fromHex("00000"), + BorderColor = Color3.fromHex("AFAFAF"), + BackgroundColor = Color3.fromHex("EEEEEE"), Open = { IconColor = BRAND_COLOR, }, Closed = { - IconColor = hexColor(0xEEEEEE), + IconColor = Color3.fromHex("EEEEEE"), }, }, AddressEntry = { - TextColor = hexColor(0x000000), - PlaceholderColor = hexColor(0x8C8C8C) + TextColor = Color3.fromHex("000000"), + PlaceholderColor = Color3.fromHex("8C8C8C") }, BorderedContainer = { - BorderColor = hexColor(0xCBCBCB), - BackgroundColor = hexColor(0xEEEEEE), + BorderColor = Color3.fromHex("CBCBCB"), + BackgroundColor = Color3.fromHex("EEEEEE"), }, Spinner = { ForegroundColor = BRAND_COLOR, - BackgroundColor = hexColor(0xEEEEEE), + BackgroundColor = Color3.fromHex("EEEEEE"), }, Diff = { - Add = hexColor(0xbaffbd), - Remove = hexColor(0xffbdba), - Edit = hexColor(0xbacdff), - Row = hexColor(0x000000), - Warning = hexColor(0xFF8E3C), + Add = Color3.fromHex("baffbd"), + Remove = Color3.fromHex("ffbdba"), + Edit = Color3.fromHex("bacdff"), + Row = Color3.fromHex("000000"), + Warning = Color3.fromHex("FF8E3C"), }, ConnectionDetails = { - ProjectNameColor = hexColor(0x00000), - AddressColor = hexColor(0x00000), + ProjectNameColor = Color3.fromHex("00000"), + AddressColor = Color3.fromHex("00000"), DisconnectColor = BRAND_COLOR, }, Settings = { - DividerColor = hexColor(0xCBCBCB), + DividerColor = Color3.fromHex("CBCBCB"), Navbar = { - BackButtonColor = hexColor(0x000000), - TextColor = hexColor(0x000000), + BackButtonColor = Color3.fromHex("000000"), + TextColor = Color3.fromHex("000000"), }, Setting = { - NameColor = hexColor(0x000000), - DescriptionColor = hexColor(0x5F5F5F), + NameColor = Color3.fromHex("000000"), + DescriptionColor = Color3.fromHex("5F5F5F"), }, }, Header = { LogoColor = BRAND_COLOR, - VersionColor = hexColor(0x727272), + VersionColor = Color3.fromHex("727272"), }, Notification = { - InfoColor = hexColor(0x00000), + InfoColor = Color3.fromHex("00000"), CloseColor = BRAND_COLOR, }, - ErrorColor = hexColor(0x000000), - ScrollBarColor = hexColor(0x000000), + ErrorColor = Color3.fromHex("000000"), + ScrollBarColor = Color3.fromHex("000000"), }) local darkTheme = strict("DarkTheme", { - BackgroundColor = hexColor(0x2E2E2E), + BackgroundColor = Color3.fromHex("2E2E2E"), Button = { Solid = { - ActionFillColor = hexColor(0xFFFFFF), + ActionFillColor = Color3.fromHex("FFFFFF"), ActionFillTransparency = 0.8, Enabled = { - TextColor = hexColor(0xFFFFFF), + TextColor = Color3.fromHex("FFFFFF"), BackgroundColor = BRAND_COLOR, }, Disabled = { - TextColor = hexColor(0xFFFFFF), + TextColor = Color3.fromHex("FFFFFF"), BackgroundColor = BRAND_COLOR, }, }, Bordered = { - ActionFillColor = hexColor(0xFFFFFF), + ActionFillColor = Color3.fromHex("FFFFFF"), ActionFillTransparency = 0.9, Enabled = { - TextColor = hexColor(0xDBDBDB), - BorderColor = hexColor(0x535353), + TextColor = Color3.fromHex("DBDBDB"), + BorderColor = Color3.fromHex("535353"), }, Disabled = { - TextColor = hexColor(0xDBDBDB), - BorderColor = hexColor(0x535353), + TextColor = Color3.fromHex("DBDBDB"), + BorderColor = Color3.fromHex("535353"), }, }, }, Checkbox = { Active = { - IconColor = hexColor(0xFFFFFF), + IconColor = Color3.fromHex("FFFFFF"), BackgroundColor = BRAND_COLOR, }, Inactive = { - IconColor = hexColor(0x484848), - BorderColor = hexColor(0x5A5A5A), + IconColor = Color3.fromHex("484848"), + BorderColor = Color3.fromHex("5A5A5A"), }, }, Dropdown = { - TextColor = hexColor(0xFFFFFF), - BorderColor = hexColor(0x5A5A5A), - BackgroundColor = hexColor(0x2B2B2B), + TextColor = Color3.fromHex("FFFFFF"), + BorderColor = Color3.fromHex("5A5A5A"), + BackgroundColor = Color3.fromHex("2B2B2B"), Open = { IconColor = BRAND_COLOR, }, Closed = { - IconColor = hexColor(0x484848), + IconColor = Color3.fromHex("484848"), }, }, AddressEntry = { - TextColor = hexColor(0xFFFFFF), - PlaceholderColor = hexColor(0x8B8B8B) + TextColor = Color3.fromHex("FFFFFF"), + PlaceholderColor = Color3.fromHex("8B8B8B") }, BorderedContainer = { - BorderColor = hexColor(0x535353), - BackgroundColor = hexColor(0x2B2B2B), + BorderColor = Color3.fromHex("535353"), + BackgroundColor = Color3.fromHex("2B2B2B"), }, Spinner = { ForegroundColor = BRAND_COLOR, - BackgroundColor = hexColor(0x2B2B2B), + BackgroundColor = Color3.fromHex("2B2B2B"), }, Diff = { - Add = hexColor(0x273732), - Remove = hexColor(0x3F2D32), - Edit = hexColor(0x193345), - Row = hexColor(0xFFFFFF), - Warning = hexColor(0xFF8E3C), + Add = Color3.fromHex("273732"), + Remove = Color3.fromHex("3F2D32"), + Edit = Color3.fromHex("193345"), + Row = Color3.fromHex("FFFFFF"), + Warning = Color3.fromHex("FF8E3C"), }, ConnectionDetails = { - ProjectNameColor = hexColor(0xFFFFFF), - AddressColor = hexColor(0xFFFFFF), - DisconnectColor = hexColor(0xFFFFFF), + ProjectNameColor = Color3.fromHex("FFFFFF"), + AddressColor = Color3.fromHex("FFFFFF"), + DisconnectColor = Color3.fromHex("FFFFFF"), }, Settings = { - DividerColor = hexColor(0x535353), + DividerColor = Color3.fromHex("535353"), Navbar = { - BackButtonColor = hexColor(0xFFFFFF), - TextColor = hexColor(0xFFFFFF), + BackButtonColor = Color3.fromHex("FFFFFF"), + TextColor = Color3.fromHex("FFFFFF"), }, Setting = { - NameColor = hexColor(0xFFFFFF), - DescriptionColor = hexColor(0xD3D3D3), + NameColor = Color3.fromHex("FFFFFF"), + DescriptionColor = Color3.fromHex("D3D3D3"), }, }, Header = { LogoColor = BRAND_COLOR, - VersionColor = hexColor(0xD3D3D3) + VersionColor = Color3.fromHex("D3D3D3") }, Notification = { - InfoColor = hexColor(0xFFFFFF), - CloseColor = hexColor(0xFFFFFF), + InfoColor = Color3.fromHex("FFFFFF"), + CloseColor = Color3.fromHex("FFFFFF"), }, - ErrorColor = hexColor(0xFFFFFF), - ScrollBarColor = hexColor(0xFFFFFF), + ErrorColor = Color3.fromHex("FFFFFF"), + ScrollBarColor = Color3.fromHex("FFFFFF"), }) local Context = Roact.createContext(lightTheme) From 2fad3b588ace71ee11792b1377f25544e493288c Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 2 Aug 2023 17:47:03 -0700 Subject: [PATCH 1323/1504] Fix theme (#763) --- plugin/src/App/Theme.lua | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index fb4af8c5..2bb355d9 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -64,7 +64,7 @@ local lightTheme = strict("LightTheme", { }, }, Dropdown = { - TextColor = Color3.fromHex("00000"), + TextColor = Color3.fromHex("000000"), BorderColor = Color3.fromHex("AFAFAF"), BackgroundColor = Color3.fromHex("EEEEEE"), Open = { @@ -94,8 +94,8 @@ local lightTheme = strict("LightTheme", { Warning = Color3.fromHex("FF8E3C"), }, ConnectionDetails = { - ProjectNameColor = Color3.fromHex("00000"), - AddressColor = Color3.fromHex("00000"), + ProjectNameColor = Color3.fromHex("000000"), + AddressColor = Color3.fromHex("000000"), DisconnectColor = BRAND_COLOR, }, Settings = { @@ -114,7 +114,7 @@ local lightTheme = strict("LightTheme", { VersionColor = Color3.fromHex("727272"), }, Notification = { - InfoColor = Color3.fromHex("00000"), + InfoColor = Color3.fromHex("000000"), CloseColor = BRAND_COLOR, }, ErrorColor = Color3.fromHex("000000"), From a7a282078fde884a8641564f8832d265c894eae3 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Tue, 8 Aug 2023 23:40:35 -0700 Subject: [PATCH 1324/1504] Update Highlighter submodule from 0.8.1 to 0.8.2 (#767) Highlighter had an edge case with changed events racing, which has been resolved in the 0.8.2 patch. --- plugin/Packages/Highlighter | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/Packages/Highlighter b/plugin/Packages/Highlighter index 09263eac..e0d06144 160000 --- a/plugin/Packages/Highlighter +++ b/plugin/Packages/Highlighter @@ -1 +1 @@ -Subproject commit 09263eacfee6ad5ff3326d12244bc45b6ae8d2f0 +Subproject commit e0d061449ea5c4452ef77008b5197ae4d3d77621 From d748ea7e40a5b8069efdfe44b706bda0d384b22d Mon Sep 17 00:00:00 2001 From: Micah Date: Wed, 9 Aug 2023 21:54:47 -0700 Subject: [PATCH 1325/1504] Update rbx_dom dependencies (#768) --- Cargo.lock | 29 +- Cargo.toml | 20 +- plugin/rbx_dom_lua/EncodedValue.lua | 20 + plugin/rbx_dom_lua/allValues.json | 112 + plugin/rbx_dom_lua/customProperties.lua | 45 + plugin/rbx_dom_lua/database.json | 18170 ++++++++++++++++------ 6 files changed, 13218 insertions(+), 5178 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc544cf7..f106d61f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1647,9 +1647,9 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1631584eb343930a5a738635504b8c1f3ef2ae9c947bff942bbbac075f6887f6" +checksum = "4e50573021d04b680018955662eba7dc4aac3de92219231798f6c9b41e38ab01" dependencies = [ "log", "lz4", @@ -1662,9 +1662,9 @@ dependencies = [ [[package]] name = "rbx_dom_weak" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cc2238fd858d706f4f5c6a0f9af3cd4a10f3f8dc8b6534e683f8543af26f33" +checksum = "161729449bbb0cfa657ce7bcca6a160d0af06d8b8d9efdc9abe14735dccacdb9" dependencies = [ "rbx_types", "serde", @@ -1672,19 +1672,20 @@ dependencies = [ [[package]] name = "rbx_reflection" -version = "4.2.0" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8915748c8a3b2a92540e4e35e99ebd548df2d62b0a6cf38ae5d0081f0e611d5" +checksum = "08bd48487192046fec8f805f3fa29f3d7d5beb9890b0859b1a92bd8aff580343" dependencies = [ "rbx_types", "serde", + "thiserror", ] [[package]] name = "rbx_reflection_database" -version = "0.2.6+roblox-572" +version = "0.2.7+roblox-588" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "780a70e2aff0c2a922bf2e72449e3a67e656ce622af4f8895c22d15cd98dfd5b" +checksum = "1be6cf674182806f11ad4899dd1feafe977591f1ae035ae05a58d4b74e487276" dependencies = [ "lazy_static", "rbx_reflection", @@ -1694,9 +1695,9 @@ dependencies = [ [[package]] name = "rbx_types" -version = "1.5.0" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9644faf3ae1858ba10615fa5955c330e49cf0f6ad37a83db3e1c398c4afac12" +checksum = "070106e926b8ae54c7bc443e5db4d868d7f0af51c1d7cfd7efe1364c1753d8a3" dependencies = [ "base64 0.13.1", "bitflags", @@ -1709,9 +1710,9 @@ dependencies = [ [[package]] name = "rbx_xml" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d5f9361d83d06aae8ea42d7002d35e2652b198e8ce68c918b97e371f8a31352" +checksum = "4bc65b70827519fdc4ab47416d1085b912f087fadab9ed415471b6daba635574" dependencies = [ "base64 0.13.1", "log", @@ -1856,9 +1857,9 @@ dependencies = [ [[package]] name = "rmp-serde" -version = "0.14.4" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ce7d70c926fe472aed493b902010bccc17fa9f7284145cb8772fd22fdb052d8" +checksum = "bffea85eea980d8a74453e5d02a8d93028f3c34725de143085a844ebe953258a" dependencies = [ "byteorder", "rmp", diff --git a/Cargo.toml b/Cargo.toml index 124d5c8f..4c210934 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,9 +12,7 @@ readme = "README.md" edition = "2021" build = "build.rs" -exclude = [ - "/test-projects/**", -] +exclude = ["/test-projects/**"] [profile.dev] panic = "abort" @@ -51,11 +49,11 @@ memofs = { version = "0.2.0", path = "crates/memofs" } # rbx_reflection_database = { path = "../rbx-dom/rbx_reflection_database" } # rbx_xml = { path = "../rbx-dom/rbx_xml" } -rbx_binary = "0.7.0" -rbx_dom_weak = "2.4.0" -rbx_reflection = "4.2.0" -rbx_reflection_database = "0.2.6" -rbx_xml = "0.13.0" +rbx_binary = "0.7.1" +rbx_dom_weak = "2.5.0" +rbx_reflection = "4.3.0" +rbx_reflection_database = "0.2.7" +rbx_xml = "0.13.1" anyhow = "1.0.44" backtrace = "0.3.61" @@ -75,7 +73,11 @@ notify = "4.0.17" num_cpus = "1.15.0" opener = "0.5.0" rayon = "1.7.0" -reqwest = { version = "0.11.10", features = ["blocking", "json", "native-tls-vendored"] } +reqwest = { version = "0.11.10", features = [ + "blocking", + "json", + "native-tls-vendored", +] } ritz = "0.1.0" roblox_install = "1.0.0" serde = { version = "1.0.130", features = ["derive", "rc"] } diff --git a/plugin/rbx_dom_lua/EncodedValue.lua b/plugin/rbx_dom_lua/EncodedValue.lua index b1a82dd7..16dde489 100644 --- a/plugin/rbx_dom_lua/EncodedValue.lua +++ b/plugin/rbx_dom_lua/EncodedValue.lua @@ -265,6 +265,26 @@ types = { toPod = identity, }, + MaterialColors = { + fromPod = function(pod: { [string]: { number } }) + local real = {} + for name, color in pod do + real[Enum.Material[name]] = Color3.fromRGB(color[1], color[2], color[3]) + end + return real + end, + toPod = function(roblox: { [Enum.Material]: Color3 }) + local pod = {} + for material, color in roblox do + pod[material.Name] = { + math.round(math.clamp(color.R, 0, 1) * 255), + math.round(math.clamp(color.G, 0, 1) * 255), + math.round(math.clamp(color.B, 0, 1) * 255) + } + end + end, + }, + NumberRange = { fromPod = unpackDecoder(NumberRange.new), diff --git a/plugin/rbx_dom_lua/allValues.json b/plugin/rbx_dom_lua/allValues.json index 545c9306..b233ab25 100644 --- a/plugin/rbx_dom_lua/allValues.json +++ b/plugin/rbx_dom_lua/allValues.json @@ -230,6 +230,118 @@ }, "ty": "Int64" }, + "MaterialColors": { + "value": { + "MaterialColors": { + "Grass": [ + 106, + 127, + 63 + ], + "Slate": [ + 63, + 127, + 107 + ], + "Concrete": [ + 127, + 102, + 63 + ], + "Brick": [ + 138, + 86, + 62 + ], + "Sand": [ + 143, + 126, + 95 + ], + "WoodPlanks": [ + 139, + 109, + 79 + ], + "Rock": [ + 102, + 108, + 111 + ], + "Glacier": [ + 101, + 176, + 234 + ], + "Snow": [ + 195, + 199, + 218 + ], + "Sandstone": [ + 137, + 90, + 71 + ], + "Mud": [ + 58, + 46, + 36 + ], + "Basalt": [ + 30, + 30, + 37 + ], + "Ground": [ + 102, + 92, + 59 + ], + "CrackedLava": [ + 232, + 156, + 74 + ], + "Asphalt": [ + 115, + 123, + 107 + ], + "Cobblestone": [ + 132, + 123, + 90 + ], + "Ice": [ + 129, + 194, + 224 + ], + "LeafyGrass": [ + 115, + 132, + 74 + ], + "Salt": [ + 198, + 189, + 181 + ], + "Limestone": [ + 206, + 173, + 148 + ], + "Pavement": [ + 148, + 148, + 140 + ] + } + }, + "ty": "MaterialColors" + }, "NumberRange": { "value": { "NumberRange": [ diff --git a/plugin/rbx_dom_lua/customProperties.lua b/plugin/rbx_dom_lua/customProperties.lua index 3720a0d7..d4d6f723 100644 --- a/plugin/rbx_dom_lua/customProperties.lua +++ b/plugin/rbx_dom_lua/customProperties.lua @@ -1,5 +1,30 @@ local CollectionService = game:GetService("CollectionService") +--- A list of `Enum.Material` values that are used for Terrain.MaterialColors +local TERRAIN_MATERIAL_COLORS = { + Enum.Material.Grass, + Enum.Material.Slate, + Enum.Material.Concrete, + Enum.Material.Brick, + Enum.Material.Sand, + Enum.Material.WoodPlanks, + Enum.Material.Rock, + Enum.Material.Glacier, + Enum.Material.Snow, + Enum.Material.Sandstone, + Enum.Material.Mud, + Enum.Material.Basalt, + Enum.Material.Ground, + Enum.Material.CrackedLava, + Enum.Material.Asphalt, + Enum.Material.Cobblestone, + Enum.Material.Ice, + Enum.Material.LeafyGrass, + Enum.Material.Salt, + Enum.Material.Limestone, + Enum.Material.Pavement, +} + -- Defines how to read and write properties that aren't directly scriptable. -- -- The reflection database refers to these as having scriptability = "Custom" @@ -71,4 +96,24 @@ return { end, }, }, + Terrain = { + MaterialColors = { + read = function(instance: Terrain) + -- There's no way to get a list of every color, so we have to + -- make one. + local colors = {} + for _, material in TERRAIN_MATERIAL_COLORS do + colors[material] = instance:GetMaterialColor(material) + end + + return true, colors + end, + write = function(instance: Terrain, _, value: { [Enum.Material]: Color3 }) + for material, color in value do + instance:SetMaterialColor(material, color) + end + return true + end, + }, + }, } diff --git a/plugin/rbx_dom_lua/database.json b/plugin/rbx_dom_lua/database.json index b26361a3..1c88154c 100644 --- a/plugin/rbx_dom_lua/database.json +++ b/plugin/rbx_dom_lua/database.json @@ -1,9 +1,9 @@ { "Version": [ 0, - 572, + 588, 0, - 5720484 + 5880517 ], "Classes": { "Accessory": { @@ -56,13 +56,13 @@ } }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -147,6 +147,22 @@ "Serialization": "DoesNotSerialize" } } + }, + "BackendAccoutrementState": { + "Name": "BackendAccoutrementState", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -177,13 +193,13 @@ } }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -194,14 +210,50 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "LevelOfDetail": { "Enum": 0 }, + "ModelMeshCFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ModelMeshSize": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, "ModelStreamingMode": { "Enum": 0 }, + "NeedsPivotMigration": { + "Bool": false + }, "Scale": { "Float32": 1.0 }, @@ -209,7 +261,33 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] + }, + "WorldPivotData": { + "OptionalCFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } } } }, @@ -231,6 +309,19 @@ } } }, + "FallbackImage": { + "Name": "FallbackImage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Status": { "Name": "Status", "Scriptability": "Read", @@ -272,23 +363,6 @@ } } }, - "PortalStatus": { - "Name": "PortalStatus", - "Scriptability": "Read", - "DataType": { - "Enum": "AdPortalStatus" - }, - "Tags": [ - "Deprecated", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "PortalVersion": { "Name": "PortalVersion", "Scriptability": "None", @@ -362,19 +436,6 @@ } } }, - "BalanceRigidityEnabled": { - "Name": "BalanceRigidityEnabled", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "BalanceSpeed": { "Name": "BalanceSpeed", "Scriptability": "ReadWrite", @@ -388,6 +449,22 @@ } } }, + "LinearImpulse": { + "Name": "LinearImpulse", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "MaintainAngularMomentum": { "Name": "MaintainAngularMomentum", "Scriptability": "ReadWrite", @@ -427,8 +504,8 @@ } } }, - "OrientationMaxTorque": { - "Name": "OrientationMaxTorque", + "TurnMaxTorque": { + "Name": "TurnMaxTorque", "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" @@ -440,8 +517,8 @@ } } }, - "OrientationSpeedFactor": { - "Name": "OrientationSpeedFactor", + "TurnSpeedFactor": { + "Name": "TurnSpeedFactor", "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" @@ -452,50 +529,11 @@ "Serialization": "Serializes" } } - }, - "TurningMaxTorque": { - "Name": "TurningMaxTorque", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "TurningSpeedFactor": { - "Name": "TurningSpeedFactor", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "VectorForce": { - "Name": "VectorForce", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BalanceMaxTorque": { "Float32": 10000.0 @@ -518,33 +556,17 @@ "MoveSpeedFactor": { "Float32": 1.0 }, - "OrientationMaxTorque": { - "Float32": 10000.0 - }, - "OrientationSpeedFactor": { - "Float32": 1.0 - }, - "RigidityEnabled": { - "Bool": false - }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, - "TurningMaxTorque": { + "TurnMaxTorque": { "Float32": 10000.0 }, - "TurningSpeedFactor": { + "TurnSpeedFactor": { "Float32": 1.0 - }, - "VectorForce": { - "Vector3": [ - 0.0, - 0.0, - 0.0 - ] } } }, @@ -579,6 +601,21 @@ } } }, + "LookAtPosition": { + "Name": "LookAtPosition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "MaxAngularVelocity": { "Name": "MaxAngularVelocity", "Scriptability": "ReadWrite", @@ -706,7 +743,7 @@ "Enum": 0 }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CFrame": { "CFrame": { @@ -735,7 +772,7 @@ } }, "Color": { - "Int32": 23 + "BrickColor": 23 }, "Enabled": { "Bool": true @@ -765,7 +802,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": false @@ -790,6 +827,45 @@ } } }, + "ForceLimitMode": { + "Name": "ForceLimitMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ForceLimitMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ForceRelativeTo": { + "Name": "ForceRelativeTo", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ActuatorRelativeTo" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxAxesForce": { + "Name": "MaxAxesForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MaxForce": { "Name": "MaxForce", "Scriptability": "ReadWrite", @@ -887,14 +963,27 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 194 + "BrickColor": 194 }, "Enabled": { "Bool": true }, + "ForceLimitMode": { + "Enum": 0 + }, + "ForceRelativeTo": { + "Enum": 2 + }, + "MaxAxesForce": { + "Vector3": [ + 10000.0, + 10000.0, + 10000.0 + ] + }, "MaxForce": { "Float32": 10000.0 }, @@ -924,7 +1013,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": false @@ -969,13 +1058,13 @@ "String": "" }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -1046,10 +1135,10 @@ ] }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 23 + "BrickColor": 23 }, "Enabled": { "Bool": true @@ -1067,7 +1156,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": false @@ -1098,13 +1187,13 @@ "Content": "" }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -1131,6 +1220,22 @@ } } }, + "GuidBinaryString": { + "Name": "GuidBinaryString", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Loop": { "Name": "Loop", "Scriptability": "ReadWrite", @@ -1233,10 +1338,10 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 23 + "BrickColor": 23 }, "Enabled": { "Bool": true @@ -1254,7 +1359,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transform": { "CFrame": { @@ -1294,13 +1399,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -1314,13 +1419,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -1335,20 +1440,259 @@ "Properties": {}, "DefaultProperties": {} }, + "AnimationImportData": { + "Name": "AnimationImportData", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "BaseImportData", + "Properties": {}, + "DefaultProperties": {} + }, "AnimationRigData": { "Name": "AnimationRigData", "Tags": [], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "articulatedJoint": { + "Name": "articulatedJoint", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "endEffectorRotationConstraint": { + "Name": "endEffectorRotationConstraint", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "endEffectorTranslationConstraint": { + "Name": "endEffectorTranslationConstraint", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "endEffectorWeight": { + "Name": "endEffectorWeight", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "facsControl": { + "Name": "facsControl", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "label": { + "Name": "label", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "name": { + "Name": "name", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "parent": { + "Name": "parent", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "postTransform": { + "Name": "postTransform", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "preTransform": { + "Name": "preTransform", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "transform": { + "Name": "transform", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "weight": { + "Name": "weight", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { + "Tags": [] + }, + "articulatedJoint": { "BinaryString": "" + }, + "endEffectorRotationConstraint": { + "BinaryString": "" + }, + "endEffectorTranslationConstraint": { + "BinaryString": "" + }, + "endEffectorWeight": { + "BinaryString": "" + }, + "facsControl": { + "BinaryString": "" + }, + "label": { + "BinaryString": "AQAAAAEAAAAAAAAA" + }, + "name": { + "BinaryString": "AQAAAAEAAAAAAAAA" + }, + "parent": { + "BinaryString": "AQAAAAEAAAAAAA==" + }, + "postTransform": { + "BinaryString": "AQAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=" + }, + "preTransform": { + "BinaryString": "AQAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=" + }, + "transform": { + "BinaryString": "AQAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=" + }, + "weight": { + "BinaryString": "AQAAAAAAAAA=" } } }, @@ -1632,7 +1976,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "PreferLodEnabled": { "Bool": true @@ -1641,7 +1985,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -1684,11 +2028,91 @@ "Serialization": "Serializes" } } + }, + "MouseButton1DownConnectionCount": { + "Name": "MouseButton1DownConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseButton1UpConnectionCount": { + "Name": "MouseButton1UpConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseDragConnectionCount": { + "Name": "MouseDragConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseEnterConnectionCount": { + "Name": "MouseEnterConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseLeaveConnectionCount": { + "Name": "MouseLeaveConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Axes": { "Axes": [ @@ -1708,7 +2132,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "Float32": 0.0 @@ -1872,13 +2296,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -1977,7 +2401,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { "Color3": [ @@ -2009,7 +2433,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -2221,7 +2645,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CFrame": { "CFrame": { @@ -2253,13 +2677,762 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": false } } }, + "AudioAnalyzer": { + "Name": "AudioAnalyzer", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "PeakLevel": { + "Name": "PeakLevel", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RmsLevel": { + "Name": "RmsLevel", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "AudioChorus": { + "Name": "AudioChorus", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "Depth": { + "Name": "Depth", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Mix": { + "Name": "Mix", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Rate": { + "Name": "Rate", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Depth": { + "Float32": 0.45 + }, + "Mix": { + "Float32": 0.85 + }, + "Rate": { + "Float32": 5.0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "AudioCompressor": { + "Name": "AudioCompressor", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "Attack": { + "Name": "Attack", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MakeupGain": { + "Name": "MakeupGain", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Ratio": { + "Name": "Ratio", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Release": { + "Name": "Release", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Threshold": { + "Name": "Threshold", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attack": { + "Float32": 0.1 + }, + "Attributes": { + "Attributes": {} + }, + "MakeupGain": { + "Float32": 0.0 + }, + "Ratio": { + "Float32": 40.0 + }, + "Release": { + "Float32": 0.1 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "Threshold": { + "Float32": -40.0 + } + } + }, + "AudioDeviceInput": { + "Name": "AudioDeviceInput", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "AccessList": { + "Name": "AccessList", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AccessType": { + "Name": "AccessType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AccessModifierType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Active": { + "Name": "Active", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsReady": { + "Name": "IsReady", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Muted": { + "Name": "Muted", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Player": { + "Name": "Player", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AccessType": { + "Enum": 1 + }, + "Active": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Muted": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "AudioDeviceOutput": { + "Name": "AudioDeviceOutput", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "Player": { + "Name": "Player", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "AudioDistortion": { + "Name": "AudioDistortion", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "Level": { + "Name": "Level", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Level": { + "Float32": 0.5 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "AudioEcho": { + "Name": "AudioEcho", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "DelayTime": { + "Name": "DelayTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DryLevel": { + "Name": "DryLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Feedback": { + "Name": "Feedback", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WetLevel": { + "Name": "WetLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "DelayTime": { + "Float32": 1.0 + }, + "DryLevel": { + "Float32": 0.0 + }, + "Feedback": { + "Float32": 0.5 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "WetLevel": { + "Float32": 0.0 + } + } + }, + "AudioEmitter": { + "Name": "AudioEmitter", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "AudioInteractionGroup": { + "Name": "AudioInteractionGroup", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "AudioInteractionGroup": { + "String": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "AudioEqualizer": { + "Name": "AudioEqualizer", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "HighGain": { + "Name": "HighGain", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LowGain": { + "Name": "LowGain", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MidGain": { + "Name": "MidGain", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MidRange": { + "Name": "MidRange", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "HighGain": { + "Float32": 0.0 + }, + "LowGain": { + "Float32": 0.0 + }, + "MidGain": { + "Float32": 0.0 + }, + "MidRange": { + "NumberRange": [ + 400.0, + 4000.0 + ] + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "AudioFader": { + "Name": "AudioFader", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "Volume": { + "Name": "Volume", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "Volume": { + "Float32": 1.0 + } + } + }, + "AudioFlanger": { + "Name": "AudioFlanger", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "Depth": { + "Name": "Depth", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Mix": { + "Name": "Mix", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Rate": { + "Name": "Rate", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Depth": { + "Float32": 0.45 + }, + "Mix": { + "Float32": 0.85 + }, + "Rate": { + "Float32": 5.0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "AudioListener": { + "Name": "AudioListener", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "AudioInteractionGroup": { + "Name": "AudioInteractionGroup", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "AudioInteractionGroup": { + "String": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, "AudioPages": { "Name": "AudioPages", "Tags": [ @@ -2270,6 +3443,437 @@ "Properties": {}, "DefaultProperties": {} }, + "AudioPitchShifter": { + "Name": "AudioPitchShifter", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "Pitch": { + "Name": "Pitch", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Pitch": { + "Float32": 1.25 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "AudioPlayer": { + "Name": "AudioPlayer", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "AssetId": { + "Name": "AssetId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AutoLoad": { + "Name": "AutoLoad", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsPlaying": { + "Name": "IsPlaying", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsReady": { + "Name": "IsReady", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LoopRegion": { + "Name": "LoopRegion", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Looping": { + "Name": "Looping", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlaybackRegion": { + "Name": "PlaybackRegion", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlaybackSpeed": { + "Name": "PlaybackSpeed", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TimeLength": { + "Name": "TimeLength", + "Scriptability": "Read", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TimePosition": { + "Name": "TimePosition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AssetId": { + "String": "" + }, + "Attributes": { + "Attributes": {} + }, + "AutoLoad": { + "Bool": true + }, + "LoopRegion": { + "NumberRange": [ + 0.0, + 60000.0 + ] + }, + "Looping": { + "Bool": false + }, + "PlaybackRegion": { + "NumberRange": [ + 0.0, + 60000.0 + ] + }, + "PlaybackSpeed": { + "Float64": 1.0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "TimePosition": { + "Float64": 0.0 + } + } + }, + "AudioReverb": { + "Name": "AudioReverb", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "DecayRatio": { + "Name": "DecayRatio", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DecayTime": { + "Name": "DecayTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Density": { + "Name": "Density", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Diffusion": { + "Name": "Diffusion", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DryLevel": { + "Name": "DryLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EarlyDelayTime": { + "Name": "EarlyDelayTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HighCutFrequency": { + "Name": "HighCutFrequency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LateDelayTime": { + "Name": "LateDelayTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LowShelfFrequency": { + "Name": "LowShelfFrequency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LowShelfGain": { + "Name": "LowShelfGain", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReferenceFrequency": { + "Name": "ReferenceFrequency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WetLevel": { + "Name": "WetLevel", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "DecayRatio": { + "Float32": 0.5 + }, + "DecayTime": { + "Float32": 1.5 + }, + "Density": { + "Float32": 1.0 + }, + "Diffusion": { + "Float32": 1.0 + }, + "DryLevel": { + "Float32": 0.0 + }, + "EarlyDelayTime": { + "Float32": 0.02 + }, + "HighCutFrequency": { + "Float32": 20000.0 + }, + "LateDelayTime": { + "Float32": 0.04 + }, + "LowShelfFrequency": { + "Float32": 250.0 + }, + "LowShelfGain": { + "Float32": 0.0 + }, + "ReferenceFrequency": { + "Float32": 5000.0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "WetLevel": { + "Float32": -6.0 + } + } + }, "AudioSearchParams": { "Name": "AudioSearchParams", "Tags": [ @@ -2400,6 +4004,66 @@ }, "DefaultProperties": {} }, + "AvatarChatService": { + "Name": "AvatarChatService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "ClientFeatures": { + "Name": "ClientFeatures", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ClientFeaturesInitialized": { + "Name": "ClientFeaturesInitialized", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ServerFeatures": { + "Name": "ServerFeatures", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "AvatarEditorService": { "Name": "AvatarEditorService", "Tags": [ @@ -2429,13 +4093,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -2503,6 +4167,23 @@ } } }, + "MaxFrictionTorqueXml": { + "Name": "MaxFrictionTorqueXml", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Radius": { "Name": "Radius", "Scriptability": "ReadWrite", @@ -2584,10 +4265,10 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 1009 + "BrickColor": 1009 }, "Enabled": { "Bool": true @@ -2595,6 +4276,9 @@ "LimitsEnabled": { "Bool": false }, + "MaxFrictionTorqueXml": { + "Float32": 0.0 + }, "Radius": { "Float32": 0.15 }, @@ -2605,7 +4289,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TwistLimitsEnabled": { "Bool": false @@ -2624,6 +4308,59 @@ } } }, + "BaseImportData": { + "Name": "BaseImportData", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Id": { + "Name": "Id", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ImportName": { + "Name": "ImportName", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShouldImport": { + "Name": "ShouldImport", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "BasePart": { "Name": "BasePart", "Tags": [ @@ -2855,8 +4592,13 @@ "NotReplicated" ], "Kind": { - "Alias": { - "AliasFor": "Color" + "Canonical": { + "Serialization": { + "Migrate": { + "To": "Color", + "Migration": "BrickColorToColor" + } + } } } }, @@ -2963,6 +4705,7 @@ "Value": "Int32" }, "Tags": [ + "Deprecated", "NotReplicated" ], "Kind": { @@ -2971,16 +4714,19 @@ } } }, - "CollisionGroups": { - "Name": "CollisionGroups", - "Scriptability": "Custom", + "CollisionGroupReplicate": { + "Name": "CollisionGroupReplicate", + "Scriptability": "None", "DataType": { "Value": "String" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -3007,7 +4753,10 @@ "DataType": { "Value": "Color3uint8" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Alias": { "AliasFor": "Color" @@ -3043,6 +4792,22 @@ } } }, + "DraggingV1": { + "Name": "DraggingV1", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Elasticity": { "Name": "Elasticity", "Scriptability": "ReadWrite", @@ -3060,6 +4825,19 @@ } } }, + "EnableFluidForces": { + "Name": "EnableFluidForces", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ExtentsCFrame": { "Name": "ExtentsCFrame", "Scriptability": "Read", @@ -3231,6 +5009,22 @@ } } }, + "LocalSimulationValidation": { + "Name": "LocalSimulationValidation", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "LocalTransparencyModifier": { "Name": "LocalTransparencyModifier", "Scriptability": "ReadWrite", @@ -3317,6 +5111,54 @@ } } }, + "MaterialVariantSerialized": { + "Name": "MaterialVariantSerialized", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NetworkIsSleeping": { + "Name": "NetworkIsSleeping", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "NetworkOwnershipRule": { + "Name": "NetworkOwnershipRule", + "Scriptability": "None", + "DataType": { + "Enum": "NetworkOwnership" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Orientation": { "Name": "Orientation", "Scriptability": "ReadWrite", @@ -3664,8 +5506,31 @@ "NotReplicated" ], "Kind": { - "Alias": { - "AliasFor": "Color" + "Canonical": { + "Serialization": { + "Migrate": { + "To": "Color", + "Migration": "BrickColorToColor" + } + } + } + } + }, + "siz": { + "Name": "siz", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "WriteOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" } } }, @@ -3675,7 +5540,10 @@ "DataType": { "Value": "Vector3" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Alias": { "AliasFor": "Size" @@ -3822,6 +5690,54 @@ } } }, + "HSRData": { + "Name": "HSRData", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HSRMeshIdData": { + "Name": "HSRMeshIdData", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImportInProcess": { + "Name": "ImportInProcess", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ImportOrigin": { "Name": "ImportOrigin", "Scriptability": "ReadWrite", @@ -3850,6 +5766,22 @@ "Serialization": "DoesNotSerialize" } } + }, + "TemporaryCageMeshId": { + "Name": "TemporaryCageMeshId", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": {} @@ -4109,7 +6041,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Brightness": { "Float32": 1.0 @@ -4161,7 +6093,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Texture": { "Content": "" @@ -4210,7 +6142,56 @@ "NotCreatable" ], "Superclass": "DataModelMesh", - "Properties": {}, + "Properties": { + "Bevel": { + "Name": "Bevel", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Bevel Roundness": { + "Name": "Bevel Roundness", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Bulge": { + "Name": "Bulge", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": {} }, "BillboardGui": { @@ -4464,7 +6445,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoLocalize": { "Bool": true @@ -4561,7 +6542,7 @@ ] }, "Tags": { - "BinaryString": "" + "Tags": [] }, "ZIndexBehavior": { "Enum": 0 @@ -4572,15 +6553,35 @@ "Name": "BinaryStringValue", "Tags": [], "Superclass": "ValueBase", - "Properties": {}, + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { + "Tags": [] + }, + "Value": { "BinaryString": "" } } @@ -4592,13 +6593,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -4609,13 +6610,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -4626,7 +6627,16 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} + }, + "Bevel": { + "Float32": 0.0 + }, + "Bevel Roundness": { + "Float32": 0.0 + }, + "Bulge": { + "Float32": 0.0 }, "Offset": { "Vector3": [ @@ -4646,7 +6656,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "VertexColor": { "Vector3": [ @@ -4704,7 +6714,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Enabled": { "Bool": true @@ -4719,7 +6729,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Threshold": { "Float32": 0.95 @@ -4747,7 +6757,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Enabled": { "Bool": true @@ -4759,7 +6769,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -4851,7 +6861,7 @@ ] }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "MaxTorque": { "Vector3": [ @@ -4867,7 +6877,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -5035,7 +7045,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "HeadColor3": { "Color3": [ @@ -5076,7 +7086,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TorsoColor3": { "Color3": [ @@ -5126,7 +7136,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Force": { "Vector3": [ @@ -5139,7 +7149,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -5237,7 +7247,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CFrame": { "CFrame": { @@ -5282,7 +7292,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -5390,7 +7400,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "D": { "Float32": 1250.0 @@ -5416,7 +7426,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -5488,7 +7498,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Force": { "Vector3": [ @@ -5508,7 +7518,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -5593,7 +7603,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "MaxForce": { "Vector3": [ @@ -5609,7 +7619,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Velocity": { "Vector3": [ @@ -5676,7 +7686,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CFrame": { "CFrame": { @@ -5708,7 +7718,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": false @@ -5736,13 +7746,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Value": { "Bool": false @@ -5776,7 +7786,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CFrame": { "CFrame": { @@ -5829,7 +7839,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "Float32": 0.0 @@ -5964,6 +7974,22 @@ } } }, + "RemoveOnHit": { + "Name": "RemoveOnHit", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Script": { "Name": "Script", "Scriptability": "None", @@ -6039,16 +8065,16 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Value": { - "Int32": 194 + "BrickColor": 194 } } }, @@ -6189,6 +8215,19 @@ } } }, + "MaxBubbles": { + "Name": "MaxBubbles", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MaxDistance": { "Name": "MaxDistance", "Scriptability": "ReadWrite", @@ -6215,6 +8254,19 @@ } } }, + "TailVisible": { + "Name": "TailVisible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TextColor3": { "Name": "TextColor3", "Scriptability": "ReadWrite", @@ -6260,7 +8312,7 @@ "String": "HumanoidRootPart" }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackgroundColor3": { "Color3": [ @@ -6299,6 +8351,9 @@ 0.0 ] }, + "MaxBubbles": { + "Float32": 3.0 + }, "MaxDistance": { "Float32": 100.0 }, @@ -6309,7 +8364,10 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] + }, + "TailVisible": { + "Bool": true }, "TextColor3": { "Color3": [ @@ -6326,6 +8384,89 @@ } } }, + "BubbleChatMessageProperties": { + "Name": "BubbleChatMessageProperties", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "BackgroundColor3": { + "Name": "BackgroundColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "BackgroundTransparency": { + "Name": "BackgroundTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FontFace": { + "Name": "FontFace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Font" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextColor3": { + "Name": "TextColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextSize": { + "Name": "TextSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, "BulkImportService": { "Name": "BulkImportService", "Tags": [ @@ -6373,7 +8514,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "FullySubmerged": { "Bool": false @@ -6382,7 +8523,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TouchingSurface": { "Bool": false @@ -6413,13 +8554,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Value": { "CFrame": { @@ -6458,13 +8599,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -6664,6 +8805,19 @@ } } }, + "VRTiltAndRollEnabled": { + "Name": "VRTiltAndRollEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ViewportSize": { "Name": "ViewportSize", "Scriptability": "Read", @@ -6699,7 +8853,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CFrame": { "CFrame": { @@ -6772,7 +8926,10 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] + }, + "VRTiltAndRollEnabled": { + "Bool": false } } }, @@ -6819,7 +8976,7 @@ ] }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoLocalize": { "Bool": true @@ -6924,7 +9081,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": true @@ -6934,6 +9091,17 @@ } } }, + "CaptureService": { + "Name": "CaptureService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "CatalogPages": { "Name": "CatalogPages", "Tags": [ @@ -6978,7 +9146,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Channel": { "Int32": 1 @@ -6993,7 +9161,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -7066,7 +9234,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BaseTextureId": { "Int64": 0 @@ -7084,7 +9252,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -7126,7 +9294,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BubbleChatEnabled": { "Bool": false @@ -7138,7 +9306,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -7211,6 +9379,19 @@ } } }, + "AutocompleteEnabled": { + "Name": "AutocompleteEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "BackgroundColor3": { "Name": "BackgroundColor3", "Scriptability": "ReadWrite", @@ -7263,6 +9444,50 @@ } } }, + "IsFocused": { + "Name": "IsFocused", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsFocusedWrite": { + "Name": "IsFocusedWrite", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "KeyboardKeyCode": { + "Name": "KeyboardKeyCode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "KeyCode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PlaceholderColor3": { "Name": "PlaceholderColor3", "Scriptability": "ReadWrite", @@ -7357,7 +9582,10 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} + }, + "AutocompleteEnabled": { + "Bool": true }, "BackgroundColor3": { "Color3": [ @@ -7380,6 +9608,9 @@ "cachedFaceId": "rbxasset://fonts/GothamSSm-Medium.otf" } }, + "KeyboardKeyCode": { + "Enum": 47 + }, "PlaceholderColor3": { "Color3": [ 0.69803923, @@ -7391,7 +9622,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TextColor3": { "Color3": [ @@ -7643,7 +9874,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackgroundColor3": { "Color3": [ @@ -7676,7 +9907,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TextColor3": { "Color3": [ @@ -7753,7 +9984,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Depth": { "Float32": 0.15 @@ -7774,7 +10005,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -7812,7 +10043,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CursorIcon": { "Content": "" @@ -7824,7 +10055,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -7871,19 +10102,6 @@ } } }, - "BalanceRigidityEnabled": { - "Name": "BalanceRigidityEnabled", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "BalanceSpeed": { "Name": "BalanceSpeed", "Scriptability": "ReadWrite", @@ -7909,32 +10127,6 @@ "Serialization": "Serializes" } } - }, - "OrientationMaxTorque": { - "Name": "OrientationMaxTorque", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "OrientationSpeedFactor": { - "Name": "OrientationSpeedFactor", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } } }, "DefaultProperties": { @@ -7942,7 +10134,7 @@ "Float32": 0.0 }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BalanceMaxTorque": { "Float32": 10000.0 @@ -7959,20 +10151,11 @@ "MoveSpeedFactor": { "Float32": 1.0 }, - "OrientationMaxTorque": { - "Float32": 10000.0 - }, - "OrientationSpeedFactor": { - "Float32": 100.0 - }, - "RigidityEnabled": { - "Bool": false - }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -7995,6 +10178,40 @@ "Serialization": "Serializes" } } + }, + "Outfit1": { + "Name": "Outfit1", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Outfit2": { + "Name": "Outfit2", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": {} @@ -8069,7 +10286,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { "Color3": [ @@ -8091,7 +10308,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -8116,13 +10333,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -8147,13 +10364,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Value": { "Color3": [ @@ -8224,7 +10441,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Brightness": { "Float32": 0.0 @@ -8242,7 +10459,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TintColor": { "Color3": [ @@ -8503,7 +10720,7 @@ "Float32": 0.1 }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Enabled": { "Bool": true @@ -8524,7 +10741,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Threshold": { "Float32": -40.0 @@ -8571,7 +10788,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CFrame": { "CFrame": { @@ -8623,7 +10840,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "Float32": 0.0 @@ -8643,13 +10860,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -8808,13 +11025,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -8834,11 +11051,27 @@ ], "Superclass": "Instance", "Properties": { - "MoveSpeedFactor": { - "Name": "MoveSpeedFactor", + "Active": { + "Name": "Active", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "BalanceRigidityEnabled": { + "Name": "BalanceRigidityEnabled", "Scriptability": "ReadWrite", "DataType": { - "Value": "Float32" + "Value": "Bool" }, "Tags": [], "Kind": { @@ -8847,11 +11080,11 @@ } } }, - "RigidityEnabled": { - "Name": "RigidityEnabled", + "MoveSpeedFactor": { + "Name": "MoveSpeedFactor", "Scriptability": "ReadWrite", "DataType": { - "Value": "Bool" + "Value": "Float32" }, "Tags": [], "Kind": { @@ -8960,11 +11193,24 @@ "Serialization": "Serializes" } } + }, + "RootPart": { + "Name": "RootPart", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BaseMoveSpeed": { "Float32": 16.0 @@ -8990,7 +11236,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -9069,7 +11315,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "HitFrame": { "CFrame": { @@ -9114,7 +11360,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "UpdateType": { "Enum": 0 @@ -9151,13 +11397,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -9254,7 +11500,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -9334,6 +11580,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "EnableFluidForces": { + "Bool": true + }, "FrontParamA": { "Float32": -0.5 }, @@ -9367,6 +11616,9 @@ "Material": { "Enum": 256 }, + "MaterialVariantSerialized": { + "String": "" + }, "PivotOffset": { "CFrame": { "position": [ @@ -9429,7 +11681,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TopParamA": { "Float32": -0.5 @@ -9473,7 +11725,10 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} + }, + "GuidBinaryString": { + "BinaryString": "AAAAAAAAAAAAAAAAAAAAAA==" }, "Loop": { "Bool": true @@ -9485,7 +11740,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -9495,16 +11750,36 @@ "Deprecated" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "PersistedCurrentValue": { + "Name": "PersistedCurrentValue", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} + }, + "PersistedCurrentValue": { + "Float32": 0.0 }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -9531,13 +11806,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -9619,7 +11894,7 @@ "Float32": 360.0 }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CFrame": { "CFrame": { @@ -9674,7 +11949,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "Float32": 0.0 @@ -9696,7 +11971,16 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} + }, + "Bevel": { + "Float32": 0.0 + }, + "Bevel Roundness": { + "Float32": 0.0 + }, + "Bulge": { + "Float32": 0.0 }, "Offset": { "Vector3": [ @@ -9716,7 +12000,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "VertexColor": { "Vector3": [ @@ -9970,10 +12254,10 @@ "Float32": 0.0 }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 1009 + "BrickColor": 1009 }, "Enabled": { "Bool": true @@ -10027,7 +12311,7 @@ "Float32": 0.0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TargetAngle": { "Float32": 0.0 @@ -10088,6 +12372,39 @@ } } }, + "ForceR15": { + "Name": "ForceR15", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GameAvatarType": { + "Name": "GameAvatarType", + "Scriptability": "None", + "DataType": { + "Enum": "GameAvatarType" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "GameId": { "Name": "GameId", "Scriptability": "Read", @@ -10234,6 +12551,23 @@ } } }, + "R15CollisionType": { + "Name": "R15CollisionType", + "Scriptability": "None", + "DataType": { + "Enum": "R15CollisionType" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "VIPServerId": { "Name": "VIPServerId", "Scriptability": "Read", @@ -10781,7 +13115,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutomaticRetry": { "Bool": true @@ -10793,7 +13127,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -10842,7 +13176,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "MaxItems": { "Int32": 1000 @@ -10851,7 +13185,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -11084,6 +13418,22 @@ "Serialization": "Serializes" } } + }, + "line": { + "Name": "line", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": {} @@ -11572,7 +13922,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color3": { "Color3": [ @@ -11588,7 +13938,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Texture": { "Content": "" @@ -11661,7 +14011,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Enabled": { "Bool": true @@ -11682,7 +14032,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -11835,7 +14185,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BehaviorType": { "Enum": 0 @@ -11859,7 +14209,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Tone": { "Enum": 0 @@ -11936,7 +14286,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "GoodbyeChoiceActive": { "Bool": true @@ -11951,7 +14301,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "UserDialog": { "String": "" @@ -11979,7 +14329,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Enabled": { "Bool": true @@ -11994,7 +14344,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -12088,11 +14438,27 @@ "Serialization": "DoesNotSerialize" } } + }, + "value": { + "Name": "value", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "MaxValue": { "Float64": 1.0 @@ -12104,7 +14470,10 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] + }, + "value": { + "Float64": 0.0 } } }, @@ -12119,6 +14488,508 @@ "Properties": {}, "DefaultProperties": {} }, + "DragDetector": { + "Name": "DragDetector", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "ClickDetector", + "Properties": { + "ActivatedCursorIcon": { + "Name": "ActivatedCursorIcon", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ApplyAtCenterOfMass": { + "Name": "ApplyAtCenterOfMass", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Axis": { + "Name": "Axis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DragFrame": { + "Name": "DragFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DragStyle": { + "Name": "DragStyle", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DragDetectorDragStyle" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GamepadModeSwitchKeyCode": { + "Name": "GamepadModeSwitchKeyCode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "KeyCode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "KeyboardModeSwitchKeyCode": { + "Name": "KeyboardModeSwitchKeyCode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "KeyCode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxDragAngle": { + "Name": "MaxDragAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxDragTranslation": { + "Name": "MaxDragTranslation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxForce": { + "Name": "MaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxTorque": { + "Name": "MaxTorque", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MinDragAngle": { + "Name": "MinDragAngle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MinDragTranslation": { + "Name": "MinDragTranslation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Orientation": { + "Name": "Orientation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PhysicalDragClickedPart": { + "Name": "PhysicalDragClickedPart", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PhysicalDragHitPoint": { + "Name": "PhysicalDragHitPoint", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PhysicalDragTargetFrame": { + "Name": "PhysicalDragTargetFrame", + "Scriptability": "None", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ReferenceInstance": { + "Name": "ReferenceInstance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ResponseStyle": { + "Name": "ResponseStyle", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DragDetectorResponseStyle" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Responsiveness": { + "Name": "Responsiveness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RunLocally": { + "Name": "RunLocally", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SecondaryAxis": { + "Name": "SecondaryAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TrackballRadialPullFactor": { + "Name": "TrackballRadialPullFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TrackballRollFactor": { + "Name": "TrackballRollFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VRSwitchKeyCode": { + "Name": "VRSwitchKeyCode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "KeyCode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WorldAxis": { + "Name": "WorldAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WorldSecondaryAxis": { + "Name": "WorldSecondaryAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "ActivatedCursorIcon": { + "Content": "" + }, + "ApplyAtCenterOfMass": { + "Bool": false + }, + "Attributes": { + "Attributes": {} + }, + "CursorIcon": { + "Content": "" + }, + "DragFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "DragStyle": { + "Enum": 1 + }, + "Enabled": { + "Bool": true + }, + "GamepadModeSwitchKeyCode": { + "Enum": 1004 + }, + "KeyboardModeSwitchKeyCode": { + "Enum": 306 + }, + "MaxActivationDistance": { + "Float32": 32.0 + }, + "MaxDragAngle": { + "Float32": 0.0 + }, + "MaxDragTranslation": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "MaxForce": { + "Float32": 10000000.0 + }, + "MaxTorque": { + "Float32": 10000.0 + }, + "MinDragAngle": { + "Float32": 0.0 + }, + "MinDragTranslation": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Orientation": { + "Vector3": [ + -0.0, + 180.0, + 90.0 + ] + }, + "ResponseStyle": { + "Enum": 1 + }, + "Responsiveness": { + "Float32": 10.0 + }, + "RunLocally": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "TrackballRadialPullFactor": { + "Float32": 1.0 + }, + "TrackballRollFactor": { + "Float32": 1.0 + }, + "VRSwitchKeyCode": { + "Enum": 1007 + } + } + }, "Dragger": { "Name": "Dragger", "Tags": [], @@ -12410,6 +15281,67 @@ }, "DefaultProperties": {} }, + "DynamicImage": { + "Name": "DynamicImage", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "DynamicMesh": { + "Name": "DynamicMesh", + "Tags": [], + "Superclass": "DataModelMesh", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Offset": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Scale": { + "Vector3": [ + 1.0, + 1.0, + 1.0 + ] + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "VertexColor": { + "Vector3": [ + 1.0, + 1.0, + 1.0 + ] + } + } + }, "DynamicRotate": { "Name": "DynamicRotate", "Tags": [ @@ -12493,7 +15425,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Delay": { "Float32": 1.0 @@ -12514,7 +15446,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "WetLevel": { "Float32": 0.0 @@ -12578,7 +15510,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Enabled": { "Bool": true @@ -12599,7 +15531,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -12624,7 +15556,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "RotationOrder": { "Enum": 0 @@ -12633,7 +15565,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -12818,7 +15750,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BlastPressure": { "Float32": 500000.0 @@ -12843,7 +15775,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TimeScale": { "Float32": 1.0 @@ -13671,13 +16603,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -13733,57 +16665,6 @@ }, "DefaultProperties": {} }, - "FacialAnimationStreamingService": { - "Name": "FacialAnimationStreamingService", - "Tags": [ - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": { - "EnableFlags": { - "Name": "EnableFlags", - "Scriptability": "None", - "DataType": { - "Enum": "FacialAnimationFlags" - }, - "Tags": [ - "Hidden" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Enabled": { - "Name": "Enabled", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, "FacialAnimationStreamingServiceStats": { "Name": "FacialAnimationStreamingServiceStats", "Tags": [ @@ -13820,6 +16701,26 @@ }, "DefaultProperties": {} }, + "FacialAnimationStreamingSubsessionStats": { + "Name": "FacialAnimationStreamingSubsessionStats", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "FacsImportData": { + "Name": "FacsImportData", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "BaseImportData", + "Properties": {}, + "DefaultProperties": {} + }, "Feature": { "Name": "Feature", "Tags": [ @@ -13944,7 +16845,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "MeshId": { "Content": "" @@ -13967,7 +16868,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TextureId": { "Content": "" @@ -14078,7 +16979,10 @@ "DataType": { "Value": "Float32" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Alias": { "AliasFor": "Heat" @@ -14107,7 +17011,10 @@ "DataType": { "Value": "Float32" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Alias": { "AliasFor": "Size" @@ -14117,7 +17024,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { "Color3": [ @@ -14146,7 +17053,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TimeScale": { "Float32": 1.0 @@ -14176,7 +17083,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CanBeDropped": { "Bool": true @@ -14216,9 +17123,45 @@ "ManualActivationOnly": { "Bool": false }, + "ModelMeshCFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ModelMeshSize": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, "ModelStreamingMode": { "Enum": 0 }, + "NeedsPivotMigration": { + "Bool": false + }, "RequiresHandle": { "Bool": true }, @@ -14229,16 +17172,42 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TeamColor": { - "Int32": 194 + "BrickColor": 194 }, "TextureId": { "Content": "" }, "ToolTip": { "String": "" + }, + "WorldPivotData": { + "OptionalCFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } } } }, @@ -14268,7 +17237,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -14348,6 +17317,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "EnableFluidForces": { + "Bool": true + }, "FormFactor": { "Enum": 1 }, @@ -14384,6 +17356,9 @@ "Material": { "Enum": 256 }, + "MaterialVariantSerialized": { + "String": "" + }, "PivotOffset": { "CFrame": { "position": [ @@ -14449,10 +17424,10 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TeamColor": { - "Int32": 194 + "BrickColor": 194 }, "TopParamA": { "Float32": -0.5 @@ -14535,7 +17510,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Depth": { "Float32": 0.45 @@ -14556,7 +17531,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -14580,17 +17555,36 @@ "Serialization": "DoesNotSerialize" } } + }, + "ValuesAndTimes": { + "Name": "ValuesAndTimes", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] + }, + "ValuesAndTimes": { + "BinaryString": "AQAAAAAAAAAAAAAAAAAWRQAAAAA=" } } }, @@ -14708,7 +17702,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color3": { "Color3": [ @@ -14727,7 +17721,7 @@ "Float32": 4.0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Texture": { "Content": "" @@ -14761,13 +17755,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -14775,16 +17769,33 @@ "Name": "Folder", "Tags": [], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "ReplicatedGuiInsertionOrder": { + "Name": "ReplicatedGuiInsertionOrder", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -14809,13 +17820,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": true @@ -14870,7 +17881,10 @@ "DataType": { "Enum": "FormFactor" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Alias": { "AliasFor": "FormFactor" @@ -14910,7 +17924,7 @@ ] }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoLocalize": { "Bool": true @@ -15008,7 +18022,7 @@ "Enum": 0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": true @@ -15045,6 +18059,23 @@ ], "Superclass": "Instance", "Properties": { + "AllowSleep": { + "Name": "AllowSleep", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Description": { "Name": "Description", "Scriptability": "ReadWrite", @@ -15057,20 +18088,90 @@ "Serialization": "Serializes" } } + }, + "HasMigratedSettingsToTestService": { + "Name": "HasMigratedSettingsToTestService", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Is30FpsThrottleEnabled": { + "Name": "Is30FpsThrottleEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PhysicsEnvironmentalThrottle": { + "Name": "PhysicsEnvironmentalThrottle", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Timeout": { + "Name": "Timeout", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Description": { "String": "?" }, + "HasMigratedSettingsToTestService": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -15084,13 +18185,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -15176,17 +18277,17 @@ ], "Superclass": "Instance", "Properties": {}, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } + "DefaultProperties": {} + }, + "GeometryService": { + "Name": "GeometryService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} }, "GetTextBoundsParams": { "Name": "GetTextBoundsParams", @@ -15332,7 +18433,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "C0": { "CFrame": { @@ -15421,7 +18522,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -15432,7 +18533,25 @@ "Service" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "gaID": { + "Name": "gaID", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": {} }, "GroundController": { @@ -15468,32 +18587,6 @@ } } }, - "AlignSpeed": { - "Name": "AlignSpeed", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "AlignTorque": { - "Name": "AlignTorque", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "BalanceMaxTorque": { "Name": "BalanceMaxTorque", "Scriptability": "ReadWrite", @@ -15507,19 +18600,6 @@ } } }, - "BalanceRigidityEnabled": { - "Name": "BalanceRigidityEnabled", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "BalanceSpeed": { "Name": "BalanceSpeed", "Scriptability": "ReadWrite", @@ -15611,8 +18691,8 @@ } } }, - "TurningFactor": { - "Name": "TurningFactor", + "TurnSpeedFactor": { + "Name": "TurnSpeedFactor", "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" @@ -15632,14 +18712,8 @@ "AccelerationTime": { "Float32": 0.0 }, - "AlignSpeed": { - "Float32": 100.0 - }, - "AlignTorque": { - "Float32": 10000.0 - }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BalanceMaxTorque": { "Float32": 10000.0 @@ -15665,9 +18739,6 @@ "MoveSpeedFactor": { "Float32": 1.0 }, - "RigidityEnabled": { - "Bool": false - }, "SourceAssetId": { "Int64": -1 }, @@ -15678,13 +18749,63 @@ "Float32": 100.0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, - "TurningFactor": { + "TurnSpeedFactor": { "Float32": 1.0 } } }, + "GroupImportData": { + "Name": "GroupImportData", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "BaseImportData", + "Properties": { + "Anchored": { + "Name": "Anchored", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImportAsModelAsset": { + "Name": "ImportAsModelAsset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InsertInWorkspace": { + "Name": "InsertInWorkspace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "GroupService": { "Name": "GroupService", "Tags": [ @@ -15842,6 +18963,22 @@ } } }, + "ReplicatedInsertionOrder": { + "Name": "ReplicatedInsertionOrder", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "RootLocalizationTable": { "Name": "RootLocalizationTable", "Scriptability": "ReadWrite", @@ -16040,6 +19177,102 @@ } } }, + "MouseButton1ClickConnectionCount": { + "Name": "MouseButton1ClickConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseButton1DownConnectionCount": { + "Name": "MouseButton1DownConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseButton1UpConnectionCount": { + "Name": "MouseButton1UpConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseButton2ClickConnectionCount": { + "Name": "MouseButton2ClickConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseButton2DownConnectionCount": { + "Name": "MouseButton2DownConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseButton2UpConnectionCount": { + "Name": "MouseButton2UpConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Selected": { "Name": "Selected", "Scriptability": "ReadWrite", @@ -16087,7 +19320,7 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoLocalize": { "Bool": true @@ -16129,7 +19362,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "ZIndexBehavior": { "Enum": 0 @@ -16295,6 +19528,38 @@ } } }, + "DragBeginConnectionCount": { + "Name": "DragBeginConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "DragStoppedConnectionCount": { + "Name": "DragStoppedConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Draggable": { "Name": "Draggable", "Scriptability": "ReadWrite", @@ -16310,6 +19575,22 @@ } } }, + "GuiState": { + "Name": "GuiState", + "Scriptability": "Read", + "DataType": { + "Enum": "GuiState" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "LayoutOrder": { "Name": "LayoutOrder", "Scriptability": "ReadWrite", @@ -16323,6 +19604,86 @@ } } }, + "MouseEnterConnectionCount": { + "Name": "MouseEnterConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseLeaveConnectionCount": { + "Name": "MouseLeaveConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseMovedConnectionCount": { + "Name": "MouseMovedConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseWheelBackwardConnectionCount": { + "Name": "MouseWheelBackwardConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseWheelForwardConnectionCount": { + "Name": "MouseWheelForwardConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "NextSelectionDown": { "Name": "NextSelectionDown", "Scriptability": "ReadWrite", @@ -16644,6 +20005,40 @@ } } }, + "PreferredTransparency": { + "Name": "PreferredTransparency", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ReducedMotionEnabled": { + "Name": "ReducedMotionEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "SelectedCoreObject": { "Name": "SelectedCoreObject", "Scriptability": "None", @@ -16803,6 +20198,86 @@ } } }, + "MouseButton1DownConnectionCount": { + "Name": "MouseButton1DownConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseButton1UpConnectionCount": { + "Name": "MouseButton1UpConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseDragConnectionCount": { + "Name": "MouseDragConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseEnterConnectionCount": { + "Name": "MouseEnterConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MouseLeaveConnectionCount": { + "Name": "MouseLeaveConnectionCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Style": { "Name": "Style", "Scriptability": "ReadWrite", @@ -16819,7 +20294,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color3": { "Color3": [ @@ -16845,7 +20320,7 @@ "Enum": 0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "Float32": 0.0 @@ -16910,13 +20385,13 @@ } }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -16934,16 +20409,57 @@ "Name": "HiddenSurfaceRemovalAsset", "Tags": [], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "HSRData": { + "Name": "HSRData", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HSRMeshIdData": { + "Name": "HSRMeshIdData", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { "Attributes": { + "Attributes": {} + }, + "HSRData": { + "BinaryString": "" + }, + "HSRMeshIdData": { "BinaryString": "" }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -17076,7 +20592,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "DepthMode": { "Enum": 0 @@ -17108,7 +20624,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -17317,10 +20833,10 @@ "Float32": 0.0 }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 1009 + "BrickColor": 1009 }, "Enabled": { "Bool": true @@ -17350,7 +20866,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TargetAngle": { "Float32": 0.0 @@ -17372,13 +20888,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Text": { "String": "" @@ -17394,7 +20910,7 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "FaceId": { "Enum": 0 @@ -17409,7 +20925,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TopBottom": { "Enum": 1 @@ -17459,6 +20975,42 @@ "Serialization": "Serializes" } } + }, + "Command": { + "Name": "Command", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "WriteOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextureName": { + "Name": "TextureName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "WriteOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -17466,7 +21018,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BinType": { "Enum": 0 @@ -17474,9 +21026,45 @@ "LevelOfDetail": { "Enum": 0 }, + "ModelMeshCFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ModelMeshSize": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, "ModelStreamingMode": { "Enum": 0 }, + "NeedsPivotMigration": { + "Bool": false + }, "Scale": { "Float32": 1.0 }, @@ -17484,10 +21072,36 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TextureId": { "Content": "" + }, + "WorldPivotData": { + "OptionalCFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } } } }, @@ -17534,7 +21148,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "HttpEnabled": { "Bool": false @@ -17543,7 +21157,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -17604,6 +21218,54 @@ } } }, + "CameraMaxDistance": { + "Name": "CameraMaxDistance", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CameraMinDistance": { + "Name": "CameraMinDistance", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CameraMode": { + "Name": "CameraMode", + "Scriptability": "None", + "DataType": { + "Enum": "CameraMode" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "CameraOffset": { "Name": "CameraOffset", "Scriptability": "ReadWrite", @@ -17730,6 +21392,22 @@ } } }, + "Health_XML": { + "Name": "Health_XML", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "HipHeight": { "Name": "HipHeight", "Scriptability": "ReadWrite", @@ -17743,6 +21421,72 @@ } } }, + "InternalBodyScale": { + "Name": "InternalBodyScale", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InternalDisplayName": { + "Name": "InternalDisplayName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "InternalHeadScale": { + "Name": "InternalHeadScale", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InternalOriginalHipHeight": { + "Name": "InternalOriginalHipHeight", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Jump": { "Name": "Jump", "Scriptability": "ReadWrite", @@ -17784,6 +21528,22 @@ } } }, + "JumpReplicate": { + "Name": "JumpReplicate", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "LeftLeg": { "Name": "LeftLeg", "Scriptability": "ReadWrite", @@ -17843,6 +21603,22 @@ } } }, + "MoveDirectionInternal": { + "Name": "MoveDirectionInternal", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "NameDisplayDistance": { "Name": "NameDisplayDistance", "Scriptability": "ReadWrite", @@ -17869,6 +21645,22 @@ } } }, + "NetworkHumanoidState": { + "Name": "NetworkHumanoidState", + "Scriptability": "None", + "DataType": { + "Enum": "HumanoidStateType" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PlatformStand": { "Name": "PlatformStand", "Scriptability": "ReadWrite", @@ -17970,6 +21762,22 @@ } } }, + "Strafe": { + "Name": "Strafe", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "TargetPoint": { "Name": "TargetPoint", "Scriptability": "ReadWrite", @@ -18013,6 +21821,38 @@ } } }, + "WalkAngleError": { + "Name": "WalkAngleError", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WalkDirection": { + "Name": "WalkDirection", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "WalkSpeed": { "Name": "WalkSpeed", "Scriptability": "ReadWrite", @@ -18071,7 +21911,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoJumpEnabled": { "Bool": true @@ -18103,9 +21943,22 @@ "HealthDisplayType": { "Enum": 0 }, + "Health_XML": { + "Float32": 100.0 + }, "HipHeight": { "Float32": 0.0 }, + "InternalBodyScale": { + "Vector3": [ + 1.0, + 1.0, + 1.0 + ] + }, + "InternalHeadScale": { + "Float32": 1.0 + }, "JumpHeight": { "Float32": 7.2 }, @@ -18134,7 +21987,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "UseJumpPower": { "Bool": true @@ -18151,13 +22004,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -18233,6 +22086,38 @@ } } }, + "EmotesDataInternal": { + "Name": "EmotesDataInternal", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EquippedEmotesDataInternal": { + "Name": "EquippedEmotesDataInternal", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Face": { "Name": "Face", "Scriptability": "ReadWrite", @@ -18696,7 +22581,7 @@ "String": "[]" }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackAccessory": { "String": "" @@ -18710,6 +22595,12 @@ "DepthScale": { "Float32": 1.0 }, + "EmotesDataInternal": { + "String": "" + }, + "EquippedEmotesDataInternal": { + "String": "" + }, "Face": { "Int64": 0 }, @@ -18821,7 +22712,7 @@ "Int64": 0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Torso": { "Int64": 0 @@ -18995,7 +22886,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Enabled": { "Bool": true @@ -19062,7 +22953,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Type": { "Enum": 0 @@ -19299,7 +23190,7 @@ ] }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoButtonColor": { "Bool": true @@ -19458,7 +23349,7 @@ "Enum": 0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TileSize": { "UDim2": [ @@ -19480,45 +23371,6 @@ } } }, - "ImageDataExperimental": { - "Name": "ImageDataExperimental", - "Tags": [ - "NotCreatable" - ], - "Superclass": "Instance", - "Properties": { - "Size": { - "Name": "Size", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector2" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "TemporaryId": { - "Name": "TemporaryId", - "Scriptability": "Read", - "DataType": { - "Value": "Content" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": {} - }, "ImageHandleAdornment": { "Name": "ImageHandleAdornment", "Tags": [], @@ -19559,7 +23411,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CFrame": { "CFrame": { @@ -19614,7 +23466,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "Float32": 0.0 @@ -19807,7 +23659,7 @@ ] }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoLocalize": { "Bool": true @@ -19948,7 +23800,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TileSize": { "UDim2": [ @@ -19970,26 +23822,295 @@ } } }, - "ImporterAnimationSettings": { - "Name": "ImporterAnimationSettings", + "IncrementalPatchBuilder": { + "Name": "IncrementalPatchBuilder", "Tags": [ "NotCreatable", - "NotReplicated" - ], - "Superclass": "ImporterBaseSettings", - "Properties": {}, - "DefaultProperties": {} - }, - "ImporterBaseSettings": { - "Name": "ImporterBaseSettings", - "Tags": [ - "NotCreatable", - "NotReplicated" + "NotReplicated", + "Service" ], "Superclass": "Instance", "Properties": { - "Id": { - "Name": "Id", + "AddPathsToBundle": { + "Name": "AddPathsToBundle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BuildDebouncePeriod": { + "Name": "BuildDebouncePeriod", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HighCompression": { + "Name": "HighCompression", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SerializePatch": { + "Name": "SerializePatch", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ZstdCompression": { + "Name": "ZstdCompression", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "InputObject": { + "Name": "InputObject", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Delta": { + "Name": "Delta", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "KeyCode": { + "Name": "KeyCode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "KeyCode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Position": { + "Name": "Position", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UserInputState": { + "Name": "UserInputState", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "UserInputState" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UserInputType": { + "Name": "UserInputType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "UserInputType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "InsertService": { + "Name": "InsertService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "AllowClientInsertModels": { + "Name": "AllowClientInsertModels", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AllowInsertFreeModels": { + "Name": "AllowInsertFreeModels", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "NotBrowsable", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AllowClientInsertModels": { + "Bool": false + }, + "AllowInsertFreeModels": { + "Bool": false + }, + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "Instance": { + "Name": "Instance", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": null, + "Properties": { + "Archivable": { + "Name": "Archivable", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "archivable" + } + } + } + }, + "Attributes": { + "Name": "Attributes", + "Scriptability": "Custom", + "DataType": { + "Value": "Attributes" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "AttributesSerialize" + } + } + } + }, + "AttributesReplicate": { + "Name": "AttributesReplicate", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AttributesSerialize": { + "Name": "AttributesSerialize", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Alias": { + "AliasFor": "Attributes" + } + } + }, + "ClassName": { + "Name": "ClassName", "Scriptability": "Read", "DataType": { "Value": "String" @@ -20004,8 +24125,43 @@ } } }, - "ImportName": { - "Name": "ImportName", + "DataCost": { + "Name": "DataCost", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "HistoryId": { + "Name": "HistoryId", + "Scriptability": "None", + "DataType": { + "Value": "UniqueId" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Name": { + "Name": "Name", "Scriptability": "ReadWrite", "DataType": { "Value": "String" @@ -20017,42 +24173,715 @@ } } }, - "ShouldImport": { - "Name": "ShouldImport", + "Parent": { + "Name": "Parent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PropertyStatusStudio": { + "Name": "PropertyStatusStudio", + "Scriptability": "None", + "DataType": { + "Enum": "PropertyStatus" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RobloxLocked": { + "Name": "RobloxLocked", "Scriptability": "ReadWrite", "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SourceAssetId": { + "Name": "SourceAssetId", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" } } + }, + "Tags": { + "Name": "Tags", + "Scriptability": "Custom", + "DataType": { + "Value": "Tags" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UniqueId": { + "Name": "UniqueId", + "Scriptability": "None", + "DataType": { + "Value": "UniqueId" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "archivable": { + "Name": "archivable", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "Archivable" + } + } + }, + "className": { + "Name": "className", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Deprecated", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Alias": { + "AliasFor": "ClassName" + } + } + }, + "numExpectedDirectChildren": { + "Name": "numExpectedDirectChildren", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": {} }, - "ImporterFacsSettings": { - "Name": "ImporterFacsSettings", + "InstanceAdornment": { + "Name": "InstanceAdornment", "Tags": [ - "NotCreatable", - "NotReplicated" + "NotCreatable" ], - "Superclass": "ImporterBaseSettings", - "Properties": {}, - "DefaultProperties": {} - }, - "ImporterGroupSettings": { - "Name": "ImporterGroupSettings", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "ImporterBaseSettings", + "Superclass": "GuiBase3d", "Properties": { + "Adornee": { + "Name": "Adornee", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "IntConstrainedValue": { + "Name": "IntConstrainedValue", + "Tags": [ + "Deprecated" + ], + "Superclass": "ValueBase", + "Properties": { + "ConstrainedValue": { + "Name": "ConstrainedValue", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "MaxValue": { + "Name": "MaxValue", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MinValue": { + "Name": "MinValue", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "value": { + "Name": "value", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "MaxValue": { + "Int64": 10 + }, + "MinValue": { + "Int64": 0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "value": { + "Int64": 0 + } + } + }, + "IntValue": { + "Name": "IntValue", + "Tags": [], + "Superclass": "ValueBase", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "Value": { + "Int64": 0 + } + } + }, + "InternalSyncItem": { + "Name": "InternalSyncItem", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "AutoSync": { + "Name": "AutoSync", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Path": { + "Name": "Path", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Target": { + "Name": "Target", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "InternalSyncService": { + "Name": "InternalSyncService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "IntersectOperation": { + "Name": "IntersectOperation", + "Tags": [], + "Superclass": "PartOperation", + "Properties": {}, + "DefaultProperties": { "Anchored": { - "Name": "Anchored", + "Bool": false + }, + "AssetId": { + "Content": "" + }, + "Attributes": { + "Attributes": {} + }, + "BackParamA": { + "Float32": -0.5 + }, + "BackParamB": { + "Float32": 0.5 + }, + "BackSurface": { + "Enum": 0 + }, + "BackSurfaceInput": { + "Enum": 0 + }, + "BottomParamA": { + "Float32": -0.5 + }, + "BottomParamB": { + "Float32": 0.5 + }, + "BottomSurface": { + "Enum": 0 + }, + "BottomSurfaceInput": { + "Enum": 0 + }, + "CFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CanCollide": { + "Bool": true + }, + "CanQuery": { + "Bool": true + }, + "CanTouch": { + "Bool": true + }, + "CastShadow": { + "Bool": true + }, + "ChildData": { + "BinaryString": "" + }, + "CollisionGroup": { + "String": "Default" + }, + "CollisionGroupId": { + "Int32": 0 + }, + "Color": { + "Color3uint8": [ + 255, + 255, + 255 + ] + }, + "CustomPhysicalProperties": { + "PhysicalProperties": "Default" + }, + "EnableFluidForces": { + "Bool": true + }, + "FormFactor": { + "Enum": 3 + }, + "FrontParamA": { + "Float32": -0.5 + }, + "FrontParamB": { + "Float32": 0.5 + }, + "FrontSurface": { + "Enum": 0 + }, + "FrontSurfaceInput": { + "Enum": 0 + }, + "InitialSize": { + "Vector3": [ + 1.0, + 1.0, + 1.0 + ] + }, + "LeftParamA": { + "Float32": -0.5 + }, + "LeftParamB": { + "Float32": 0.5 + }, + "LeftSurface": { + "Enum": 0 + }, + "LeftSurfaceInput": { + "Enum": 0 + }, + "Locked": { + "Bool": false + }, + "Massless": { + "Bool": false + }, + "Material": { + "Enum": 256 + }, + "MaterialVariantSerialized": { + "String": "" + }, + "MeshData": { + "BinaryString": "" + }, + "PhysicsData": { + "BinaryString": "" + }, + "PivotOffset": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Reflectance": { + "Float32": 0.0 + }, + "RenderFidelity": { + "Enum": 1 + }, + "RightParamA": { + "Float32": -0.5 + }, + "RightParamB": { + "Float32": 0.5 + }, + "RightSurface": { + "Enum": 0 + }, + "RightSurfaceInput": { + "Enum": 0 + }, + "RootPriority": { + "Int32": 0 + }, + "RotVelocity": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Size": { + "Vector3": [ + 4.0, + 1.2, + 2.0 + ] + }, + "SmoothingAngle": { + "Float32": 0.0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "TopParamA": { + "Float32": -0.5 + }, + "TopParamB": { + "Float32": 0.5 + }, + "TopSurface": { + "Enum": 0 + }, + "TopSurfaceInput": { + "Enum": 0 + }, + "Transparency": { + "Float32": 0.0 + }, + "UsePartColor": { + "Bool": false + }, + "Velocity": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + } + } + }, + "InventoryPages": { + "Name": "InventoryPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, + "JointImportData": { + "Name": "JointImportData", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "BaseImportData", + "Properties": {}, + "DefaultProperties": {} + }, + "JointInstance": { + "Name": "JointInstance", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Active": { + "Name": "Active", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "C0": { + "Name": "C0", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "C1": { + "Name": "C1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", "Scriptability": "ReadWrite", "DataType": { "Value": "Bool" @@ -20064,8 +24893,239 @@ } } }, - "ImportAsModelAsset": { - "Name": "ImportAsModelAsset", + "Part0": { + "Name": "Part0", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Part1": { + "Name": "Part1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "part1": { + "Name": "part1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Alias": { + "AliasFor": "Part1" + } + } + } + }, + "DefaultProperties": {} + }, + "JointsService": { + "Name": "JointsService", + "Tags": [ + "Deprecated", + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "KeyboardService": { + "Name": "KeyboardService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "Keyframe": { + "Name": "Keyframe", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Time": { + "Name": "Time", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "Time": { + "Float32": 0.0 + } + } + }, + "KeyframeMarker": { + "Name": "KeyframeMarker", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Value": { + "Name": "Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "Value": { + "String": "" + } + } + }, + "KeyframeSequence": { + "Name": "KeyframeSequence", + "Tags": [], + "Superclass": "AnimationClip", + "Properties": { + "AuthoredHipHeight": { + "Name": "AuthoredHipHeight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "AuthoredHipHeight": { + "Float32": 2.0 + }, + "GuidBinaryString": { + "BinaryString": "AAAAAAAAAAAAAAAAAAAAAA==" + }, + "Loop": { + "Bool": true + }, + "Priority": { + "Enum": 2 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "KeyframeSequenceProvider": { + "Name": "KeyframeSequenceProvider", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "LSPFileSyncService": { + "Name": "LSPFileSyncService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "LanguageService": { + "Name": "LanguageService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "LayerCollector": { + "Name": "LayerCollector", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "GuiBase2d", + "Properties": { + "Enabled": { + "Name": "Enabled", "Scriptability": "ReadWrite", "DataType": { "Value": "Bool" @@ -20077,8 +25137,94 @@ } } }, - "InsertInWorkspace": { - "Name": "InsertInWorkspace", + "ResetOnSpawn": { + "Name": "ResetOnSpawn", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ZIndexBehavior": { + "Name": "ZIndexBehavior", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ZIndexBehavior" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "LegacyStudioBridge": { + "Name": "LegacyStudioBridge", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "ILegacyStudioBridge", + "Properties": {}, + "DefaultProperties": {} + }, + "Light": { + "Name": "Light", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "Brightness": { + "Name": "Brightness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Shadows": { + "Name": "Shadows", "Scriptability": "ReadWrite", "DataType": { "Value": "Bool" @@ -20093,23 +25239,1764 @@ }, "DefaultProperties": {} }, - "ImporterJointSettings": { - "Name": "ImporterJointSettings", + "Lighting": { + "Name": "Lighting", "Tags": [ "NotCreatable", - "NotReplicated" + "Service" ], - "Superclass": "ImporterBaseSettings", + "Superclass": "Instance", + "Properties": { + "Ambient": { + "Name": "Ambient", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Brightness": { + "Name": "Brightness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClockTime": { + "Name": "ClockTime", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ColorShift_Bottom": { + "Name": "ColorShift_Bottom", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ColorShift_Top": { + "Name": "ColorShift_Top", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnvironmentDiffuseScale": { + "Name": "EnvironmentDiffuseScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnvironmentSpecularScale": { + "Name": "EnvironmentSpecularScale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ExposureCompensation": { + "Name": "ExposureCompensation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FogColor": { + "Name": "FogColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FogEnd": { + "Name": "FogEnd", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FogStart": { + "Name": "FogStart", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GeographicLatitude": { + "Name": "GeographicLatitude", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GlobalShadows": { + "Name": "GlobalShadows", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OutdoorAmbient": { + "Name": "OutdoorAmbient", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Outlines": { + "Name": "Outlines", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShadowColor": { + "Name": "ShadowColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "Deprecated", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ShadowSoftness": { + "Name": "ShadowSoftness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Technology": { + "Name": "Technology", + "Scriptability": "None", + "DataType": { + "Enum": "Technology" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TempUseNewSkyRemovalBehaviour": { + "Name": "TempUseNewSkyRemovalBehaviour", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TimeOfDay": { + "Name": "TimeOfDay", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Ambient": { + "Color3": [ + 0.5, + 0.5, + 0.5 + ] + }, + "Attributes": { + "Attributes": {} + }, + "Brightness": { + "Float32": 1.0 + }, + "ColorShift_Bottom": { + "Color3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "ColorShift_Top": { + "Color3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "EnvironmentDiffuseScale": { + "Float32": 0.0 + }, + "EnvironmentSpecularScale": { + "Float32": 0.0 + }, + "ExposureCompensation": { + "Float32": 0.0 + }, + "FogColor": { + "Color3": [ + 0.75, + 0.75, + 0.75 + ] + }, + "FogEnd": { + "Float32": 100000.0 + }, + "FogStart": { + "Float32": 0.0 + }, + "GeographicLatitude": { + "Float32": 41.7333 + }, + "GlobalShadows": { + "Bool": false + }, + "OutdoorAmbient": { + "Color3": [ + 0.5, + 0.5, + 0.5 + ] + }, + "Outlines": { + "Bool": true + }, + "ShadowSoftness": { + "Float32": 0.5 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "Technology": { + "Enum": 2 + }, + "TimeOfDay": { + "String": "14:00:00" + } + } + }, + "LineForce": { + "Name": "LineForce", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "ApplyAtCenterOfMass": { + "Name": "ApplyAtCenterOfMass", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InverseSquareLaw": { + "Name": "InverseSquareLaw", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Magnitude": { + "Name": "Magnitude", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxForce": { + "Name": "MaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReactionForceEnabled": { + "Name": "ReactionForceEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "ApplyAtCenterOfMass": { + "Bool": false + }, + "Attributes": { + "Attributes": {} + }, + "Color": { + "BrickColor": 23 + }, + "Enabled": { + "Bool": true + }, + "InverseSquareLaw": { + "Bool": false + }, + "Magnitude": { + "Float32": 1000.0 + }, + "MaxForce": { + "Float32": null + }, + "ReactionForceEnabled": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "Visible": { + "Bool": false + } + } + }, + "LineHandleAdornment": { + "Name": "LineHandleAdornment", + "Tags": [], + "Superclass": "HandleAdornment", + "Properties": { + "Length": { + "Name": "Length", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Thickness": { + "Name": "Thickness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AdornCullingMode": { + "Enum": 0 + }, + "AlwaysOnTop": { + "Bool": false + }, + "Attributes": { + "Attributes": {} + }, + "CFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Color3": { + "Color3": [ + 0.050980397, + 0.41176474, + 0.6745098 + ] + }, + "Length": { + "Float32": 5.0 + }, + "SizeRelativeOffset": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "Thickness": { + "Float32": 1.0 + }, + "Transparency": { + "Float32": 0.0 + }, + "Visible": { + "Bool": true + }, + "ZIndex": { + "Int32": -1 + } + } + }, + "LinearVelocity": { + "Name": "LinearVelocity", + "Tags": [], + "Superclass": "Constraint", + "Properties": { + "ForceLimitMode": { + "Name": "ForceLimitMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ForceLimitMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LineDirection": { + "Name": "LineDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LineVelocity": { + "Name": "LineVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxAxesForce": { + "Name": "MaxAxesForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxForce": { + "Name": "MaxForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaxPlanarAxesForce": { + "Name": "MaxPlanarAxesForce", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlaneVelocity": { + "Name": "PlaneVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PrimaryTangentAxis": { + "Name": "PrimaryTangentAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RelativeTo": { + "Name": "RelativeTo", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ActuatorRelativeTo" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SecondaryTangentAxis": { + "Name": "SecondaryTangentAxis", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VectorVelocity": { + "Name": "VectorVelocity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VelocityConstraintMode": { + "Name": "VelocityConstraintMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "VelocityConstraintMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Color": { + "BrickColor": 26 + }, + "Enabled": { + "Bool": true + }, + "ForceLimitMode": { + "Enum": 0 + }, + "LineDirection": { + "Vector3": [ + 1.0, + 0.0, + 0.0 + ] + }, + "LineVelocity": { + "Float32": -0.0 + }, + "MaxAxesForce": { + "Vector3": [ + 1000.0, + 1000.0, + 1000.0 + ] + }, + "MaxForce": { + "Float32": 1000.0 + }, + "MaxPlanarAxesForce": { + "Vector2": [ + 1000.0, + 1000.0 + ] + }, + "PlaneVelocity": { + "Vector2": [ + 0.0, + 0.0 + ] + }, + "PrimaryTangentAxis": { + "Vector3": [ + 1.0, + 0.0, + 0.0 + ] + }, + "RelativeTo": { + "Enum": 2 + }, + "SecondaryTangentAxis": { + "Vector3": [ + 0.0, + 1.0, + 0.0 + ] + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "VectorVelocity": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "VelocityConstraintMode": { + "Enum": 2 + }, + "Visible": { + "Bool": false + } + } + }, + "LiveScriptingService": { + "Name": "LiveScriptingService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", "Properties": {}, "DefaultProperties": {} }, - "ImporterMaterialSettings": { - "Name": "ImporterMaterialSettings", + "LocalDebuggerConnection": { + "Name": "LocalDebuggerConnection", "Tags": [ "NotCreatable", "NotReplicated" ], - "Superclass": "ImporterBaseSettings", + "Superclass": "DebuggerConnection", + "Properties": {}, + "DefaultProperties": {} + }, + "LocalScript": { + "Name": "LocalScript", + "Tags": [], + "Superclass": "Script", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Disabled": { + "Bool": false + }, + "LinkedSource": { + "Content": "" + }, + "RunContext": { + "Enum": 0 + }, + "Source": { + "String": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "LocalStorageService": { + "Name": "LocalStorageService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "LocalizationService": { + "Name": "LocalizationService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "ForcePlayModeGameLocaleId": { + "Name": "ForcePlayModeGameLocaleId", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ForcePlayModeRobloxLocaleId": { + "Name": "ForcePlayModeRobloxLocaleId", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GameSourceLanguageId": { + "Name": "GameSourceLanguageId", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsTextScraperRunning": { + "Name": "IsTextScraperRunning", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LocaleManifest": { + "Name": "LocaleManifest", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RobloxForcePlayModeGameLocaleId": { + "Name": "RobloxForcePlayModeGameLocaleId", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RobloxForcePlayModeRobloxLocaleId": { + "Name": "RobloxForcePlayModeRobloxLocaleId", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RobloxLocaleId": { + "Name": "RobloxLocaleId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ShouldUseCloudTable": { + "Name": "ShouldUseCloudTable", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SystemLocaleId": { + "Name": "SystemLocaleId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "LocalizationTable": { + "Name": "LocalizationTable", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Contents": { + "Name": "Contents", + "Scriptability": "Custom", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DevelopmentLanguage": { + "Name": "DevelopmentLanguage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsExemptFromUGCAnalytics": { + "Name": "IsExemptFromUGCAnalytics", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Root": { + "Name": "Root", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SourceLocaleId": { + "Name": "SourceLocaleId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Contents": { + "String": "[]" + }, + "SourceAssetId": { + "Int64": -1 + }, + "SourceLocaleId": { + "String": "en-us" + }, + "Tags": { + "Tags": [] + } + } + }, + "LodDataEntity": { + "Name": "LodDataEntity", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "EntityData": { + "Name": "EntityData", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EntityLodEnabled": { + "Name": "EntityLodEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EntityPosition": { + "Name": "EntityPosition", + "Scriptability": "None", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EntityScale": { + "Name": "EntityScale", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EntitySource": { + "Name": "EntitySource", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "LodDataService": { + "Name": "LodDataService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "LogService": { + "Name": "LogService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "LoginService": { + "Name": "LoginService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "LuaSettings": { + "Name": "LuaSettings", + "Tags": [ + "NotCreatable", + "Settings" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "LuaSourceContainer": { + "Name": "LuaSourceContainer", + "Tags": [ + "NotBrowsable", + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "CachedRemoteSource": { + "Name": "CachedRemoteSource", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CachedRemoteSourceLoadState": { + "Name": "CachedRemoteSourceLoadState", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CurrentEditor": { + "Name": "CurrentEditor", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "HasAssociatedDrafts": { + "Name": "HasAssociatedDrafts", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsDifferentFromFileSystem": { + "Name": "IsDifferentFromFileSystem", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "OriginalScriptGuid": { + "Name": "OriginalScriptGuid", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RuntimeSource": { + "Name": "RuntimeSource", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SandboxedSource": { + "Name": "SandboxedSource", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ScriptGuid": { + "Name": "ScriptGuid", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SyncingEditorText": { + "Name": "SyncingEditorText", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "LuaWebService": { + "Name": "LuaWebService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "LuauScriptAnalyzerService": { + "Name": "LuauScriptAnalyzerService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "ManualGlue": { + "Name": "ManualGlue", + "Tags": [ + "Deprecated" + ], + "Superclass": "ManualSurfaceJointInstance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "C0": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "C1": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Enabled": { + "Bool": true + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "ManualSurfaceJointInstance": { + "Name": "ManualSurfaceJointInstance", + "Tags": [ + "Deprecated", + "NotCreatable" + ], + "Superclass": "JointInstance", + "Properties": {}, + "DefaultProperties": {} + }, + "ManualWeld": { + "Name": "ManualWeld", + "Tags": [ + "Deprecated" + ], + "Superclass": "ManualSurfaceJointInstance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "C0": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "C1": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Enabled": { + "Bool": true + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "MarkerCurve": { + "Name": "MarkerCurve", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Length": { + "Name": "Length", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ValuesAndTimes": { + "Name": "ValuesAndTimes", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "ValuesAndTimes": { + "BinaryString": "AAAAAAEAAAAKAAAAAAAAFkUAAAAA" + } + } + }, + "MarketplaceService": { + "Name": "MarketplaceService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "MaterialGenerationService": { + "Name": "MaterialGenerationService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "MaterialGenerationSession": { + "Name": "MaterialGenerationSession", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "MaterialImportData": { + "Name": "MaterialImportData", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "BaseImportData", "Properties": { "DiffuseFilePath": { "Name": "DiffuseFilePath", @@ -20182,13 +27069,1060 @@ }, "DefaultProperties": {} }, - "ImporterMeshSettings": { - "Name": "ImporterMeshSettings", + "MaterialService": { + "Name": "MaterialService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "AsphaltName": { + "Name": "AsphaltName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BasaltName": { + "Name": "BasaltName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BrickName": { + "Name": "BrickName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CardboardName": { + "Name": "CardboardName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CarpetName": { + "Name": "CarpetName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CeramicTilesName": { + "Name": "CeramicTilesName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClayRoofTilesName": { + "Name": "ClayRoofTilesName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CobblestoneName": { + "Name": "CobblestoneName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ConcreteName": { + "Name": "ConcreteName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CorrodedMetalName": { + "Name": "CorrodedMetalName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CrackedLavaName": { + "Name": "CrackedLavaName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DiamondPlateName": { + "Name": "DiamondPlateName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FabricName": { + "Name": "FabricName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FoilName": { + "Name": "FoilName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GlacierName": { + "Name": "GlacierName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GraniteName": { + "Name": "GraniteName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GrassName": { + "Name": "GrassName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GroundName": { + "Name": "GroundName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IceName": { + "Name": "IceName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeafyGrassName": { + "Name": "LeafyGrassName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LeatherName": { + "Name": "LeatherName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LimestoneName": { + "Name": "LimestoneName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MarbleName": { + "Name": "MarbleName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MetalName": { + "Name": "MetalName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MudName": { + "Name": "MudName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PavementName": { + "Name": "PavementName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PebbleName": { + "Name": "PebbleName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlasterName": { + "Name": "PlasterName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlasticName": { + "Name": "PlasticName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RockName": { + "Name": "RockName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RoofShinglesName": { + "Name": "RoofShinglesName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RubberName": { + "Name": "RubberName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SaltName": { + "Name": "SaltName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SandName": { + "Name": "SandName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SandstoneName": { + "Name": "SandstoneName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SlateName": { + "Name": "SlateName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SmoothPlasticName": { + "Name": "SmoothPlasticName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SnowName": { + "Name": "SnowName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Use2022Materials": { + "Name": "Use2022Materials", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "Use2022MaterialsXml" + } + } + } + }, + "Use2022MaterialsXml": { + "Name": "Use2022MaterialsXml", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WoodName": { + "Name": "WoodName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WoodPlanksName": { + "Name": "WoodPlanksName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AsphaltName": { + "String": "Asphalt" + }, + "Attributes": { + "Attributes": {} + }, + "BasaltName": { + "String": "Basalt" + }, + "BrickName": { + "String": "Brick" + }, + "CardboardName": { + "String": "Cardboard" + }, + "CarpetName": { + "String": "Carpet" + }, + "CeramicTilesName": { + "String": "CeramicTiles" + }, + "ClayRoofTilesName": { + "String": "ClayRoofTiles" + }, + "CobblestoneName": { + "String": "Cobblestone" + }, + "ConcreteName": { + "String": "Concrete" + }, + "CorrodedMetalName": { + "String": "CorrodedMetal" + }, + "CrackedLavaName": { + "String": "CrackedLava" + }, + "DiamondPlateName": { + "String": "DiamondPlate" + }, + "FabricName": { + "String": "Fabric" + }, + "FoilName": { + "String": "Foil" + }, + "GlacierName": { + "String": "Glacier" + }, + "GraniteName": { + "String": "Granite" + }, + "GrassName": { + "String": "Grass" + }, + "GroundName": { + "String": "Ground" + }, + "IceName": { + "String": "Ice" + }, + "LeafyGrassName": { + "String": "LeafyGrass" + }, + "LeatherName": { + "String": "Leather" + }, + "LimestoneName": { + "String": "Limestone" + }, + "MarbleName": { + "String": "Marble" + }, + "MetalName": { + "String": "Metal" + }, + "MudName": { + "String": "Mud" + }, + "PavementName": { + "String": "Pavement" + }, + "PebbleName": { + "String": "Pebble" + }, + "PlasterName": { + "String": "Plaster" + }, + "PlasticName": { + "String": "Plastic" + }, + "RockName": { + "String": "Rock" + }, + "RoofShinglesName": { + "String": "RoofShingles" + }, + "RubberName": { + "String": "Rubber" + }, + "SaltName": { + "String": "Salt" + }, + "SandName": { + "String": "Sand" + }, + "SandstoneName": { + "String": "Sandstone" + }, + "SlateName": { + "String": "Slate" + }, + "SmoothPlasticName": { + "String": "SmoothPlastic" + }, + "SnowName": { + "String": "Snow" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "Use2022MaterialsXml": { + "Bool": false + }, + "WoodName": { + "String": "Wood" + }, + "WoodPlanksName": { + "String": "WoodPlanks" + } + } + }, + "MaterialVariant": { + "Name": "MaterialVariant", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "AvgMetalness": { + "Name": "AvgMetalness", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AvgRoughness": { + "Name": "AvgRoughness", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "BaseMaterial": { + "Name": "BaseMaterial", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "Material" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ColorMap": { + "Name": "ColorMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CustomPhysicalProperties": { + "Name": "CustomPhysicalProperties", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "PhysicalProperties" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MaterialPattern": { + "Name": "MaterialPattern", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "MaterialPattern" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MetalnessMap": { + "Name": "MetalnessMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NormalMap": { + "Name": "NormalMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RoughnessMap": { + "Name": "RoughnessMap", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StudsPerTile": { + "Name": "StudsPerTile", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TexturePack": { + "Name": "TexturePack", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "BaseMaterial": { + "Enum": 256 + }, + "ColorMap": { + "Content": "" + }, + "CustomPhysicalProperties": { + "PhysicalProperties": "Default" + }, + "MaterialPattern": { + "Enum": 0 + }, + "MetalnessMap": { + "Content": "" + }, + "NormalMap": { + "Content": "" + }, + "RoughnessMap": { + "Content": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "StudsPerTile": { + "Float32": 10.0 + }, + "Tags": { + "Tags": [] + }, + "TexturePack": { + "Content": "" + } + } + }, + "MemStorageConnection": { + "Name": "MemStorageConnection", "Tags": [ "NotCreatable", "NotReplicated" ], - "Superclass": "ImporterBaseSettings", + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "MemStorageService": { + "Name": "MemStorageService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "MemoryStoreQueue": { + "Name": "MemoryStoreQueue", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "MemoryStoreService": { + "Name": "MemoryStoreService", + "Tags": [ + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "MemoryStoreSortedMap": { + "Name": "MemoryStoreSortedMap", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "MeshContentProvider": { + "Name": "MeshContentProvider", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "CacheableContentProvider", + "Properties": {}, + "DefaultProperties": {} + }, + "MeshImportData": { + "Name": "MeshImportData", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "BaseImportData", "Properties": { "Anchored": { "Name": "Anchored", @@ -20480,3728 +28414,45 @@ }, "DefaultProperties": {} }, - "ImporterRootSettings": { - "Name": "ImporterRootSettings", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "ImporterBaseSettings", - "Properties": { - "AddModelToInventory": { - "Name": "AddModelToInventory", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Anchored": { - "Name": "Anchored", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ExistingPackageId": { - "Name": "ExistingPackageId", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "String" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "FileDimensions": { - "Name": "FileDimensions", - "Scriptability": "Read", - "DataType": { - "Value": "Vector3" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "ImportAsModelAsset": { - "Name": "ImportAsModelAsset", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ImportAsPackage": { - "Name": "ImportAsPackage", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "InsertInWorkspace": { - "Name": "InsertInWorkspace", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "InsertWithScenePosition": { - "Name": "InsertWithScenePosition", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "InvertNegativeFaces": { - "Name": "InvertNegativeFaces", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "MergeMeshes": { - "Name": "MergeMeshes", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "PolygonCount": { - "Name": "PolygonCount", - "Scriptability": "Read", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RigScale": { - "Name": "RigScale", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "RigScale" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "RigType": { - "Name": "RigType", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "RigType" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ScaleUnit": { - "Name": "ScaleUnit", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "MeshScaleUnit" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "UseSceneOriginAsCFrame": { - "Name": "UseSceneOriginAsCFrame", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "UseSceneOriginAsPivot": { - "Name": "UseSceneOriginAsPivot", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "UsesCages": { - "Name": "UsesCages", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "WorldForward": { - "Name": "WorldForward", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "NormalId" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "WorldUp": { - "Name": "WorldUp", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "NormalId" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": {} - }, - "IncrementalPatchBuilder": { - "Name": "IncrementalPatchBuilder", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": { - "AddPathsToBundle": { - "Name": "AddPathsToBundle", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "BuildDebouncePeriod": { - "Name": "BuildDebouncePeriod", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float64" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "HighCompression": { - "Name": "HighCompression", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "SerializePatch": { - "Name": "SerializePatch", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ZstdCompression": { - "Name": "ZstdCompression", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": {} - }, - "InputObject": { - "Name": "InputObject", - "Tags": [ - "NotCreatable" - ], - "Superclass": "Instance", - "Properties": { - "Delta": { - "Name": "Delta", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "KeyCode": { - "Name": "KeyCode", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "KeyCode" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Position": { - "Name": "Position", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "UserInputState": { - "Name": "UserInputState", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "UserInputState" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "UserInputType": { - "Name": "UserInputType", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "UserInputType" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": {} - }, - "InsertService": { - "Name": "InsertService", - "Tags": [ - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": { - "AllowClientInsertModels": { - "Name": "AllowClientInsertModels", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "AllowInsertFreeModels": { - "Name": "AllowInsertFreeModels", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Deprecated", - "NotBrowsable", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "AllowClientInsertModels": { - "Bool": false - }, - "AllowInsertFreeModels": { - "Bool": false - }, - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "Instance": { - "Name": "Instance", - "Tags": [ - "NotBrowsable", - "NotCreatable" - ], - "Superclass": null, - "Properties": { - "Archivable": { - "Name": "Archivable", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": { - "SerializesAs": "archivable" - } - } - } - }, - "Attributes": { - "Name": "Attributes", - "Scriptability": "Custom", - "DataType": { - "Value": "Attributes" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": { - "SerializesAs": "AttributesSerialize" - } - } - } - }, - "AttributesSerialize": { - "Name": "AttributesSerialize", - "Scriptability": "None", - "DataType": { - "Value": "BinaryString" - }, - "Tags": [], - "Kind": { - "Alias": { - "AliasFor": "Attributes" - } - } - }, - "ClassName": { - "Name": "ClassName", - "Scriptability": "Read", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "DataCost": { - "Name": "DataCost", - "Scriptability": "None", - "DataType": { - "Value": "Int32" - }, - "Tags": [ - "Deprecated", - "Hidden", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Name": { - "Name": "Name", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "String" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Parent": { - "Name": "Parent", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [ - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RobloxLocked": { - "Name": "RobloxLocked", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "SourceAssetId": { - "Name": "SourceAssetId", - "Scriptability": "None", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Tags": { - "Name": "Tags", - "Scriptability": "Custom", - "DataType": { - "Value": "Tags" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "archivable": { - "Name": "archivable", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Deprecated", - "Hidden", - "NotReplicated" - ], - "Kind": { - "Alias": { - "AliasFor": "Archivable" - } - } - }, - "className": { - "Name": "className", - "Scriptability": "Read", - "DataType": { - "Value": "String" - }, - "Tags": [ - "Deprecated", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Alias": { - "AliasFor": "ClassName" - } - } - } - }, - "DefaultProperties": {} - }, - "InstanceAdornment": { - "Name": "InstanceAdornment", - "Tags": [ - "NotCreatable" - ], - "Superclass": "GuiBase3d", - "Properties": { - "Adornee": { - "Name": "Adornee", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": {} - }, - "IntConstrainedValue": { - "Name": "IntConstrainedValue", - "Tags": [ - "Deprecated" - ], - "Superclass": "ValueBase", - "Properties": { - "ConstrainedValue": { - "Name": "ConstrainedValue", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "MaxValue": { - "Name": "MaxValue", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Int64" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "MinValue": { - "Name": "MinValue", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Int64" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Value": { - "Name": "Value", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "MaxValue": { - "Int64": 10 - }, - "MinValue": { - "Int64": 0 - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "IntValue": { - "Name": "IntValue", - "Tags": [], - "Superclass": "ValueBase", - "Properties": { - "Value": { - "Name": "Value", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Int64" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - }, - "Value": { - "Int64": 0 - } - } - }, - "IntersectOperation": { - "Name": "IntersectOperation", - "Tags": [], - "Superclass": "PartOperation", - "Properties": {}, - "DefaultProperties": { - "Anchored": { - "Bool": false - }, - "AssetId": { - "Content": "" - }, - "Attributes": { - "BinaryString": "" - }, - "BackParamA": { - "Float32": -0.5 - }, - "BackParamB": { - "Float32": 0.5 - }, - "BackSurface": { - "Enum": 0 - }, - "BackSurfaceInput": { - "Enum": 0 - }, - "BottomParamA": { - "Float32": -0.5 - }, - "BottomParamB": { - "Float32": 0.5 - }, - "BottomSurface": { - "Enum": 0 - }, - "BottomSurfaceInput": { - "Enum": 0 - }, - "CFrame": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "CanCollide": { - "Bool": true - }, - "CanQuery": { - "Bool": true - }, - "CanTouch": { - "Bool": true - }, - "CastShadow": { - "Bool": true - }, - "CollisionGroup": { - "String": "Default" - }, - "CollisionGroupId": { - "Int32": 0 - }, - "Color": { - "Color3uint8": [ - 255, - 255, - 255 - ] - }, - "CustomPhysicalProperties": { - "PhysicalProperties": "Default" - }, - "FrontParamA": { - "Float32": -0.5 - }, - "FrontParamB": { - "Float32": 0.5 - }, - "FrontSurface": { - "Enum": 0 - }, - "FrontSurfaceInput": { - "Enum": 0 - }, - "LeftParamA": { - "Float32": -0.5 - }, - "LeftParamB": { - "Float32": 0.5 - }, - "LeftSurface": { - "Enum": 0 - }, - "LeftSurfaceInput": { - "Enum": 0 - }, - "Locked": { - "Bool": false - }, - "Massless": { - "Bool": false - }, - "Material": { - "Enum": 256 - }, - "PivotOffset": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Reflectance": { - "Float32": 0.0 - }, - "RenderFidelity": { - "Enum": 1 - }, - "RightParamA": { - "Float32": -0.5 - }, - "RightParamB": { - "Float32": 0.5 - }, - "RightSurface": { - "Enum": 0 - }, - "RightSurfaceInput": { - "Enum": 0 - }, - "RootPriority": { - "Int32": 0 - }, - "RotVelocity": { - "Vector3": [ - 0.0, - 0.0, - 0.0 - ] - }, - "Size": { - "Vector3": [ - 4.0, - 1.2, - 2.0 - ] - }, - "SmoothingAngle": { - "Float32": 0.0 - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - }, - "TopParamA": { - "Float32": -0.5 - }, - "TopParamB": { - "Float32": 0.5 - }, - "TopSurface": { - "Enum": 0 - }, - "TopSurfaceInput": { - "Enum": 0 - }, - "Transparency": { - "Float32": 0.0 - }, - "UsePartColor": { - "Bool": false - }, - "Velocity": { - "Vector3": [ - 0.0, - 0.0, - 0.0 - ] - } - } - }, - "InventoryPages": { - "Name": "InventoryPages", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "Pages", - "Properties": {}, - "DefaultProperties": {} - }, - "JointInstance": { - "Name": "JointInstance", - "Tags": [ - "NotCreatable" - ], - "Superclass": "Instance", - "Properties": { - "Active": { - "Name": "Active", - "Scriptability": "Read", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "C0": { - "Name": "C0", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "C1": { - "Name": "C1", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Enabled": { - "Name": "Enabled", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Part0": { - "Name": "Part0", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Part1": { - "Name": "Part1", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "part1": { - "Name": "part1", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [ - "Deprecated", - "Hidden", - "NotReplicated" - ], - "Kind": { - "Alias": { - "AliasFor": "Part1" - } - } - } - }, - "DefaultProperties": {} - }, - "JointsService": { - "Name": "JointsService", - "Tags": [ - "Deprecated", - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "KeyboardService": { - "Name": "KeyboardService", - "Tags": [ - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "Keyframe": { - "Name": "Keyframe", - "Tags": [], - "Superclass": "Instance", - "Properties": { - "Time": { - "Name": "Time", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - }, - "Time": { - "Float32": 0.0 - } - } - }, - "KeyframeMarker": { - "Name": "KeyframeMarker", - "Tags": [], - "Superclass": "Instance", - "Properties": { - "Value": { - "Name": "Value", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "String" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - }, - "Value": { - "String": "" - } - } - }, - "KeyframeSequence": { - "Name": "KeyframeSequence", - "Tags": [], - "Superclass": "AnimationClip", - "Properties": { - "AuthoredHipHeight": { - "Name": "AuthoredHipHeight", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "AuthoredHipHeight": { - "Float32": 2.0 - }, - "Loop": { - "Bool": true - }, - "Priority": { - "Enum": 2 - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "KeyframeSequenceProvider": { - "Name": "KeyframeSequenceProvider", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "LSPFileSyncService": { - "Name": "LSPFileSyncService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "LanguageService": { - "Name": "LanguageService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "LayerCollector": { - "Name": "LayerCollector", - "Tags": [ - "NotBrowsable", - "NotCreatable" - ], - "Superclass": "GuiBase2d", - "Properties": { - "Enabled": { - "Name": "Enabled", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ResetOnSpawn": { - "Name": "ResetOnSpawn", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ZIndexBehavior": { - "Name": "ZIndexBehavior", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "ZIndexBehavior" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": {} - }, - "LegacyStudioBridge": { - "Name": "LegacyStudioBridge", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "ILegacyStudioBridge", - "Properties": {}, - "DefaultProperties": {} - }, - "Light": { - "Name": "Light", - "Tags": [ - "NotCreatable" - ], - "Superclass": "Instance", - "Properties": { - "Brightness": { - "Name": "Brightness", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Color": { - "Name": "Color", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Color3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Enabled": { - "Name": "Enabled", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Shadows": { - "Name": "Shadows", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": {} - }, - "Lighting": { - "Name": "Lighting", - "Tags": [ - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": { - "Ambient": { - "Name": "Ambient", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Color3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Brightness": { - "Name": "Brightness", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ClockTime": { - "Name": "ClockTime", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "ColorShift_Bottom": { - "Name": "ColorShift_Bottom", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Color3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ColorShift_Top": { - "Name": "ColorShift_Top", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Color3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "EnvironmentDiffuseScale": { - "Name": "EnvironmentDiffuseScale", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "EnvironmentSpecularScale": { - "Name": "EnvironmentSpecularScale", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ExposureCompensation": { - "Name": "ExposureCompensation", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "FogColor": { - "Name": "FogColor", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Color3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "FogEnd": { - "Name": "FogEnd", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "FogStart": { - "Name": "FogStart", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GeographicLatitude": { - "Name": "GeographicLatitude", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GlobalShadows": { - "Name": "GlobalShadows", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "OutdoorAmbient": { - "Name": "OutdoorAmbient", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Color3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Outlines": { - "Name": "Outlines", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Deprecated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ShadowColor": { - "Name": "ShadowColor", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Color3" - }, - "Tags": [ - "Deprecated", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "ShadowSoftness": { - "Name": "ShadowSoftness", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Technology": { - "Name": "Technology", - "Scriptability": "None", - "DataType": { - "Enum": "Technology" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "TempUseNewSkyRemovalBehaviour": { - "Name": "TempUseNewSkyRemovalBehaviour", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "TimeOfDay": { - "Name": "TimeOfDay", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "String" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "Ambient": { - "Color3": [ - 0.5, - 0.5, - 0.5 - ] - }, - "Attributes": { - "BinaryString": "" - }, - "Brightness": { - "Float32": 1.0 - }, - "ColorShift_Bottom": { - "Color3": [ - 0.0, - 0.0, - 0.0 - ] - }, - "ColorShift_Top": { - "Color3": [ - 0.0, - 0.0, - 0.0 - ] - }, - "EnvironmentDiffuseScale": { - "Float32": 0.0 - }, - "EnvironmentSpecularScale": { - "Float32": 0.0 - }, - "ExposureCompensation": { - "Float32": 0.0 - }, - "FogColor": { - "Color3": [ - 0.75, - 0.75, - 0.75 - ] - }, - "FogEnd": { - "Float32": 100000.0 - }, - "FogStart": { - "Float32": 0.0 - }, - "GeographicLatitude": { - "Float32": 41.7333 - }, - "GlobalShadows": { - "Bool": false - }, - "OutdoorAmbient": { - "Color3": [ - 0.5, - 0.5, - 0.5 - ] - }, - "Outlines": { - "Bool": true - }, - "ShadowSoftness": { - "Float32": 0.5 - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - }, - "Technology": { - "Enum": 2 - }, - "TimeOfDay": { - "String": "14:00:00" - } - } - }, - "LineForce": { - "Name": "LineForce", - "Tags": [], - "Superclass": "Constraint", - "Properties": { - "ApplyAtCenterOfMass": { - "Name": "ApplyAtCenterOfMass", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "InverseSquareLaw": { - "Name": "InverseSquareLaw", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Magnitude": { - "Name": "Magnitude", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "MaxForce": { - "Name": "MaxForce", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ReactionForceEnabled": { - "Name": "ReactionForceEnabled", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "ApplyAtCenterOfMass": { - "Bool": false - }, - "Attributes": { - "BinaryString": "" - }, - "Color": { - "Int32": 23 - }, - "Enabled": { - "Bool": true - }, - "InverseSquareLaw": { - "Bool": false - }, - "Magnitude": { - "Float32": 1000.0 - }, - "MaxForce": { - "Float32": null - }, - "ReactionForceEnabled": { - "Bool": false - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - }, - "Visible": { - "Bool": false - } - } - }, - "LineHandleAdornment": { - "Name": "LineHandleAdornment", - "Tags": [], - "Superclass": "HandleAdornment", - "Properties": { - "Length": { - "Name": "Length", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Thickness": { - "Name": "Thickness", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "AdornCullingMode": { - "Enum": 0 - }, - "AlwaysOnTop": { - "Bool": false - }, - "Attributes": { - "BinaryString": "" - }, - "CFrame": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Color3": { - "Color3": [ - 0.050980397, - 0.41176474, - 0.6745098 - ] - }, - "Length": { - "Float32": 5.0 - }, - "SizeRelativeOffset": { - "Vector3": [ - 0.0, - 0.0, - 0.0 - ] - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - }, - "Thickness": { - "Float32": 1.0 - }, - "Transparency": { - "Float32": 0.0 - }, - "Visible": { - "Bool": true - }, - "ZIndex": { - "Int32": -1 - } - } - }, - "LinearVelocity": { - "Name": "LinearVelocity", - "Tags": [], - "Superclass": "Constraint", - "Properties": { - "LineDirection": { - "Name": "LineDirection", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "LineVelocity": { - "Name": "LineVelocity", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "MaxForce": { - "Name": "MaxForce", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "PlaneVelocity": { - "Name": "PlaneVelocity", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector2" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "PrimaryTangentAxis": { - "Name": "PrimaryTangentAxis", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "RelativeTo": { - "Name": "RelativeTo", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "ActuatorRelativeTo" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "SecondaryTangentAxis": { - "Name": "SecondaryTangentAxis", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "VectorVelocity": { - "Name": "VectorVelocity", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "VelocityConstraintMode": { - "Name": "VelocityConstraintMode", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "VelocityConstraintMode" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "Color": { - "Int32": 26 - }, - "Enabled": { - "Bool": true - }, - "LineDirection": { - "Vector3": [ - 1.0, - 0.0, - 0.0 - ] - }, - "LineVelocity": { - "Float32": -0.0 - }, - "MaxForce": { - "Float32": 1000.0 - }, - "PlaneVelocity": { - "Vector2": [ - 0.0, - 0.0 - ] - }, - "PrimaryTangentAxis": { - "Vector3": [ - 1.0, - 0.0, - 0.0 - ] - }, - "RelativeTo": { - "Enum": 2 - }, - "SecondaryTangentAxis": { - "Vector3": [ - 0.0, - 1.0, - 0.0 - ] - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - }, - "VectorVelocity": { - "Vector3": [ - 0.0, - 0.0, - 0.0 - ] - }, - "VelocityConstraintMode": { - "Enum": 2 - }, - "Visible": { - "Bool": false - } - } - }, - "LiveScriptingService": { - "Name": "LiveScriptingService", - "Tags": [ - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "LocalDebuggerConnection": { - "Name": "LocalDebuggerConnection", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "DebuggerConnection", - "Properties": {}, - "DefaultProperties": {} - }, - "LocalScript": { - "Name": "LocalScript", - "Tags": [], - "Superclass": "Script", - "Properties": {}, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "Disabled": { - "Bool": false - }, - "LinkedSource": { - "Content": "" - }, - "RunContext": { - "Enum": 0 - }, - "Source": { - "String": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "LocalStorageService": { - "Name": "LocalStorageService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "LocalizationService": { - "Name": "LocalizationService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": { - "ForcePlayModeGameLocaleId": { - "Name": "ForcePlayModeGameLocaleId", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "ForcePlayModeRobloxLocaleId": { - "Name": "ForcePlayModeRobloxLocaleId", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "IsTextScraperRunning": { - "Name": "IsTextScraperRunning", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RobloxForcePlayModeGameLocaleId": { - "Name": "RobloxForcePlayModeGameLocaleId", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RobloxForcePlayModeRobloxLocaleId": { - "Name": "RobloxForcePlayModeRobloxLocaleId", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RobloxLocaleId": { - "Name": "RobloxLocaleId", - "Scriptability": "Read", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "SystemLocaleId": { - "Name": "SystemLocaleId", - "Scriptability": "Read", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "LocalizationTable": { - "Name": "LocalizationTable", - "Tags": [], - "Superclass": "Instance", - "Properties": { - "Contents": { - "Name": "Contents", - "Scriptability": "Custom", - "DataType": { - "Value": "String" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "DevelopmentLanguage": { - "Name": "DevelopmentLanguage", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "String" - }, - "Tags": [ - "Deprecated", - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Root": { - "Name": "Root", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [ - "Deprecated", - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "SourceLocaleId": { - "Name": "SourceLocaleId", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "String" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "Contents": { - "String": "[]" - }, - "SourceAssetId": { - "Int64": -1 - }, - "SourceLocaleId": { - "String": "en-us" - }, - "Tags": { - "BinaryString": "" - } - } - }, - "LodDataEntity": { - "Name": "LodDataEntity", - "Tags": [ - "NotCreatable" - ], - "Superclass": "Instance", - "Properties": { - "EntityLodEnabled": { - "Name": "EntityLodEnabled", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": {} - }, - "LodDataService": { - "Name": "LodDataService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "LogService": { - "Name": "LogService", - "Tags": [ - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "LoginService": { - "Name": "LoginService", - "Tags": [ - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "LuaSettings": { - "Name": "LuaSettings", - "Tags": [ - "NotCreatable", - "Settings" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "LuaSourceContainer": { - "Name": "LuaSourceContainer", - "Tags": [ - "NotBrowsable", - "NotCreatable" - ], - "Superclass": "Instance", - "Properties": { - "CurrentEditor": { - "Name": "CurrentEditor", - "Scriptability": "None", - "DataType": { - "Value": "Ref" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RuntimeSource": { - "Name": "RuntimeSource", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": {} - }, - "LuaWebService": { - "Name": "LuaWebService", - "Tags": [ - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "LuauScriptAnalyzerService": { - "Name": "LuauScriptAnalyzerService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "ManualGlue": { - "Name": "ManualGlue", - "Tags": [ - "Deprecated" - ], - "Superclass": "ManualSurfaceJointInstance", - "Properties": {}, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "C0": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "C1": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Enabled": { - "Bool": true - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "ManualSurfaceJointInstance": { - "Name": "ManualSurfaceJointInstance", - "Tags": [ - "Deprecated", - "NotCreatable" - ], - "Superclass": "JointInstance", - "Properties": {}, - "DefaultProperties": {} - }, - "ManualWeld": { - "Name": "ManualWeld", - "Tags": [ - "Deprecated" - ], - "Superclass": "ManualSurfaceJointInstance", - "Properties": {}, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "C0": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "C1": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Enabled": { - "Bool": true - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "MarkerCurve": { - "Name": "MarkerCurve", - "Tags": [], - "Superclass": "Instance", - "Properties": { - "Length": { - "Name": "Length", - "Scriptability": "Read", - "DataType": { - "Value": "Int32" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "MarketplaceService": { - "Name": "MarketplaceService", - "Tags": [ - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "MaterialGenerationService": { - "Name": "MaterialGenerationService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "MaterialGenerationSession": { - "Name": "MaterialGenerationSession", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "MaterialService": { - "Name": "MaterialService", - "Tags": [ - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": { - "AsphaltName": { - "Name": "AsphaltName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "BasaltName": { - "Name": "BasaltName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "BrickName": { - "Name": "BrickName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "CobblestoneName": { - "Name": "CobblestoneName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ConcreteName": { - "Name": "ConcreteName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "CorrodedMetalName": { - "Name": "CorrodedMetalName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "CrackedLavaName": { - "Name": "CrackedLavaName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "DiamondPlateName": { - "Name": "DiamondPlateName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "FabricName": { - "Name": "FabricName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "FoilName": { - "Name": "FoilName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GlacierName": { - "Name": "GlacierName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GraniteName": { - "Name": "GraniteName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GrassName": { - "Name": "GrassName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GroundName": { - "Name": "GroundName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "IceName": { - "Name": "IceName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "LeafyGrassName": { - "Name": "LeafyGrassName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "LimestoneName": { - "Name": "LimestoneName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "MarbleName": { - "Name": "MarbleName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "MetalName": { - "Name": "MetalName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "MudName": { - "Name": "MudName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "PavementName": { - "Name": "PavementName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "PebbleName": { - "Name": "PebbleName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "PlasticName": { - "Name": "PlasticName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "RockName": { - "Name": "RockName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "SaltName": { - "Name": "SaltName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "SandName": { - "Name": "SandName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "SandstoneName": { - "Name": "SandstoneName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "SlateName": { - "Name": "SlateName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "SmoothPlasticName": { - "Name": "SmoothPlasticName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "SnowName": { - "Name": "SnowName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Use2022Materials": { - "Name": "Use2022Materials", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "WoodName": { - "Name": "WoodName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "WoodPlanksName": { - "Name": "WoodPlanksName", - "Scriptability": "None", - "DataType": { - "Value": "String" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "AsphaltName": { - "String": "Asphalt" - }, - "Attributes": { - "BinaryString": "" - }, - "BasaltName": { - "String": "Basalt" - }, - "BrickName": { - "String": "Brick" - }, - "CobblestoneName": { - "String": "Cobblestone" - }, - "ConcreteName": { - "String": "Concrete" - }, - "CorrodedMetalName": { - "String": "CorrodedMetal" - }, - "CrackedLavaName": { - "String": "CrackedLava" - }, - "DiamondPlateName": { - "String": "DiamondPlate" - }, - "FabricName": { - "String": "Fabric" - }, - "FoilName": { - "String": "Foil" - }, - "GlacierName": { - "String": "Glacier" - }, - "GraniteName": { - "String": "Granite" - }, - "GrassName": { - "String": "Grass" - }, - "GroundName": { - "String": "Ground" - }, - "IceName": { - "String": "Ice" - }, - "LeafyGrassName": { - "String": "LeafyGrass" - }, - "LimestoneName": { - "String": "Limestone" - }, - "MarbleName": { - "String": "Marble" - }, - "MetalName": { - "String": "Metal" - }, - "MudName": { - "String": "Mud" - }, - "PavementName": { - "String": "Pavement" - }, - "PebbleName": { - "String": "Pebble" - }, - "PlasticName": { - "String": "Plastic" - }, - "RockName": { - "String": "Rock" - }, - "SaltName": { - "String": "Salt" - }, - "SandName": { - "String": "Sand" - }, - "SandstoneName": { - "String": "Sandstone" - }, - "SlateName": { - "String": "Slate" - }, - "SmoothPlasticName": { - "String": "SmoothPlastic" - }, - "SnowName": { - "String": "Snow" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - }, - "WoodName": { - "String": "Wood" - }, - "WoodPlanksName": { - "String": "WoodPlanks" - } - } - }, - "MaterialVariant": { - "Name": "MaterialVariant", - "Tags": [], - "Superclass": "Instance", - "Properties": { - "BaseMaterial": { - "Name": "BaseMaterial", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "Material" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ColorMap": { - "Name": "ColorMap", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Content" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "CustomPhysicalProperties": { - "Name": "CustomPhysicalProperties", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "PhysicalProperties" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "MaterialPattern": { - "Name": "MaterialPattern", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "MaterialPattern" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "MetalnessMap": { - "Name": "MetalnessMap", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Content" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "NormalMap": { - "Name": "NormalMap", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Content" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "RoughnessMap": { - "Name": "RoughnessMap", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Content" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "StudsPerTile": { - "Name": "StudsPerTile", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "BaseMaterial": { - "Enum": 256 - }, - "ColorMap": { - "Content": "" - }, - "CustomPhysicalProperties": { - "PhysicalProperties": "Default" - }, - "MaterialPattern": { - "Enum": 0 - }, - "MetalnessMap": { - "Content": "" - }, - "NormalMap": { - "Content": "" - }, - "RoughnessMap": { - "Content": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "StudsPerTile": { - "Float32": 10.0 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "MemStorageConnection": { - "Name": "MemStorageConnection", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "MemStorageService": { - "Name": "MemStorageService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "MemoryStoreQueue": { - "Name": "MemoryStoreQueue", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "MemoryStoreService": { - "Name": "MemoryStoreService", - "Tags": [ - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - } - } - }, - "MemoryStoreSortedMap": { - "Name": "MemoryStoreSortedMap", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, - "MeshContentProvider": { - "Name": "MeshContentProvider", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "CacheableContentProvider", - "Properties": {}, - "DefaultProperties": {} - }, - "MeshDataExperimental": { - "Name": "MeshDataExperimental", - "Tags": [ - "NotCreatable" - ], - "Superclass": "Instance", - "Properties": { - "Size": { - "Name": "Size", - "Scriptability": "Read", - "DataType": { - "Value": "Vector3" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": {} - }, "MeshPart": { "Name": "MeshPart", "Tags": [], "Superclass": "TriangleMeshPart", "Properties": { + "AeroMeshData": { + "Name": "AeroMeshData", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AlternateMeshHash": { + "Name": "AlternateMeshHash", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "DoubleSided": { "Name": "DoubleSided", "Scriptability": "ReadWrite", @@ -24245,6 +28496,22 @@ } } }, + "InitialSize": { + "Name": "InitialSize", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "JointOffset": { "Name": "JointOffset", "Scriptability": "Read", @@ -24260,6 +28527,24 @@ } } }, + "MeshID": { + "Name": "MeshID", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "MeshId": { "Name": "MeshId", "Scriptability": "Read", @@ -24273,6 +28558,22 @@ } } }, + "PhysicsData": { + "Name": "PhysicsData", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "RenderFidelity": { "Name": "RenderFidelity", "Scriptability": "ReadWrite", @@ -24288,6 +28589,22 @@ } } }, + "RenderFidelityReplicate": { + "Name": "RenderFidelityReplicate", + "Scriptability": "None", + "DataType": { + "Enum": "RenderFidelity" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "TextureID": { "Name": "TextureID", "Scriptability": "ReadWrite", @@ -24300,6 +28617,22 @@ "Serialization": "Serializes" } } + }, + "VertexCount": { + "Name": "VertexCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -24307,7 +28640,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -24390,6 +28723,9 @@ "DoubleSided": { "Bool": false }, + "EnableFluidForces": { + "Bool": true + }, "FrontParamA": { "Float32": -0.5 }, @@ -24408,6 +28744,13 @@ "HasSkinnedMesh": { "Bool": false }, + "InitialSize": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, "JointOffset": { "Vector3": [ 0.0, @@ -24436,9 +28779,15 @@ "Material": { "Enum": 256 }, + "MaterialVariantSerialized": { + "String": "" + }, "MeshId": { "Content": "" }, + "PhysicsData": { + "BinaryString": "" + }, "PivotOffset": { "CFrame": { "position": [ @@ -24504,7 +28853,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TextureID": { "Content": "" @@ -24530,6 +28879,9 @@ 0.0, 0.0 ] + }, + "VertexCount": { + "Int32": 0 } } }, @@ -24556,13 +28908,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Text": { "String": "" @@ -24723,6 +29075,22 @@ } } }, + "RemoveOnHit": { + "Name": "RemoveOnHit", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Script": { "Name": "Script", "Scriptability": "None", @@ -24759,7 +29127,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Condition": { "String": "" @@ -24776,6 +29144,9 @@ "LogMessage": { "String": "" }, + "RemoveOnHit": { + "Bool": false + }, "Script": { "String": "" }, @@ -24783,7 +29154,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -24794,16 +29165,36 @@ "NotReplicated" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "ContextDataInternal": { + "Name": "ContextDataInternal", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} + }, + "ContextDataInternal": { + "String": "0 1 2 " }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -24836,6 +29227,70 @@ } } }, + "LodEntity": { + "Name": "LodEntity", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ModelMeshCFrame": { + "Name": "ModelMeshCFrame", + "Scriptability": "None", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ModelMeshData": { + "Name": "ModelMeshData", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ModelMeshSize": { + "Name": "ModelMeshSize", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ModelStreamingMode": { "Name": "ModelStreamingMode", "Scriptability": "ReadWrite", @@ -24849,6 +29304,23 @@ } } }, + "NeedsPivotMigration": { + "Name": "NeedsPivotMigration", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PrimaryPart": { "Name": "PrimaryPart", "Scriptability": "ReadWrite", @@ -24886,7 +29358,10 @@ "DataType": { "Value": "Float32" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Alias": { "AliasFor": "Scale" @@ -24907,18 +29382,70 @@ "Serialization": "DoesNotSerialize" } } + }, + "WorldPivotData": { + "Name": "WorldPivotData", + "Scriptability": "None", + "DataType": { + "Value": "OptionalCFrame" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "LevelOfDetail": { "Enum": 0 }, + "ModelMeshCFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ModelMeshSize": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, "ModelStreamingMode": { "Enum": 0 }, + "NeedsPivotMigration": { + "Bool": false + }, "Scale": { "Float32": 1.0 }, @@ -24926,7 +29453,33 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] + }, + "WorldPivotData": { + "OptionalCFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } } } }, @@ -24935,6 +29488,23 @@ "Tags": [], "Superclass": "LuaSourceContainer", "Properties": { + "Confidential": { + "Name": "Confidential", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "LinkedSource": { "Name": "LinkedSource", "Scriptability": "ReadWrite", @@ -24964,7 +29534,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "LinkedSource": { "Content": "" @@ -24976,7 +29546,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -25029,7 +29599,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "C0": { "CFrame": { @@ -25096,7 +29666,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -25158,7 +29728,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "C0": { "CFrame": { @@ -25225,7 +29795,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -25238,7 +29808,7 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "FaceId": { "Enum": 0 @@ -25253,7 +29823,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TopBottom": { "Enum": 1 @@ -25527,7 +30097,7 @@ "Content": "" }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -25591,6 +30161,9 @@ "CastShadow": { "Bool": true }, + "ChildData": { + "BinaryString": "" + }, "CollisionGroup": { "String": "Default" }, @@ -25607,6 +30180,12 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "EnableFluidForces": { + "Bool": true + }, + "FormFactor": { + "Enum": 3 + }, "FrontParamA": { "Float32": -0.5 }, @@ -25619,6 +30198,13 @@ "FrontSurfaceInput": { "Enum": 0 }, + "InitialSize": { + "Vector3": [ + 1.0, + 1.0, + 1.0 + ] + }, "LeftParamA": { "Float32": -0.5 }, @@ -25640,6 +30226,15 @@ "Material": { "Enum": 256 }, + "MaterialVariantSerialized": { + "String": "" + }, + "MeshData": { + "BinaryString": "" + }, + "PhysicsData": { + "BinaryString": "" + }, "PivotOffset": { "CFrame": { "position": [ @@ -25708,7 +30303,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TopParamA": { "Float32": -0.5 @@ -25870,6 +30465,23 @@ } } }, + "OpenCertManagerDialog": { + "Name": "OpenCertManagerDialog", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PrintJoinSizeBreakdown": { "Name": "PrintJoinSizeBreakdown", "Scriptability": "ReadWrite", @@ -25998,7 +30610,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Enabled": { "Bool": true @@ -26007,7 +30619,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -26020,13 +30632,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -26127,7 +30739,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "EasingDirection": { "Enum": 0 @@ -26139,7 +30751,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Value": { "Float64": 0.0 @@ -26170,13 +30782,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Value": { "Float64": 0.0 @@ -26204,13 +30816,55 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] + } + } + }, + "OmniRecommendationsService": { + "Name": "OmniRecommendationsService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "OpenCloudApiV1": { + "Name": "OpenCloudApiV1", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "OpenCloudService": { + "Name": "OpenCloudService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] } } }, @@ -26323,6 +30977,23 @@ } } }, + "CanAutoUpdate": { + "Name": "CanAutoUpdate", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Creator": { "Name": "Creator", "Scriptability": "None", @@ -26340,6 +31011,22 @@ } } }, + "ModifiedState": { + "Name": "ModifiedState", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PackageAssetName": { "Name": "PackageAssetName", "Scriptability": "None", @@ -26357,6 +31044,22 @@ } } }, + "PackageGuid": { + "Name": "PackageGuid", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PackageId": { "Name": "PackageId", "Scriptability": "Read", @@ -26381,7 +31084,10 @@ "DataType": { "Value": "Content" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Alias": { "AliasFor": "PackageId" @@ -26421,6 +31127,22 @@ } } }, + "VersionIdSerialize": { + "Name": "VersionIdSerialize", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "VersionNumber": { "Name": "VersionNumber", "Scriptability": "Read", @@ -26509,7 +31231,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color3": { "Color3": [ @@ -26525,7 +31247,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -26612,7 +31334,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color3": { "Color3": [ @@ -26625,7 +31347,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "Float32": 0.0 @@ -26657,13 +31379,34 @@ } } }, + "shap": { + "Name": "shap", + "Scriptability": "None", + "DataType": { + "Enum": "PartType" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "WriteOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "shape": { "Name": "shape", "Scriptability": "None", "DataType": { "Enum": "PartType" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Alias": { "AliasFor": "Shape" @@ -26676,7 +31419,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -26756,6 +31499,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "EnableFluidForces": { + "Bool": true + }, "FormFactor": { "Enum": 1 }, @@ -26792,6 +31538,9 @@ "Material": { "Enum": 256 }, + "MaterialVariantSerialized": { + "String": "" + }, "PivotOffset": { "CFrame": { "position": [ @@ -26857,7 +31606,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TopParamA": { "Float32": -0.5 @@ -26917,7 +31666,141 @@ "DataType": { "Value": "Content" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CSGMesh2KernelMap": { + "Name": "CSGMesh2KernelMap", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ChildData": { + "Name": "ChildData", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ChildData2": { + "Name": "ChildData2", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FormFactor": { + "Name": "FormFactor", + "Scriptability": "None", + "DataType": { + "Enum": "FormFactor" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InitialSize": { + "Name": "InitialSize", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MeshData": { + "Name": "MeshData", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MeshData2": { + "Name": "MeshData2", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PhysicsData": { + "Name": "PhysicsData", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -26937,6 +31820,23 @@ } } }, + "SerializedCSGTree": { + "Name": "SerializedCSGTree", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "SmoothingAngle": { "Name": "SmoothingAngle", "Scriptability": "ReadWrite", @@ -26988,7 +31888,7 @@ "Content": "" }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -27052,6 +31952,9 @@ "CastShadow": { "Bool": true }, + "ChildData": { + "BinaryString": "" + }, "CollisionGroup": { "String": "Default" }, @@ -27068,6 +31971,12 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "EnableFluidForces": { + "Bool": true + }, + "FormFactor": { + "Enum": 3 + }, "FrontParamA": { "Float32": -0.5 }, @@ -27080,6 +31989,13 @@ "FrontSurfaceInput": { "Enum": 0 }, + "InitialSize": { + "Vector3": [ + 1.0, + 1.0, + 1.0 + ] + }, "LeftParamA": { "Float32": -0.5 }, @@ -27101,6 +32017,15 @@ "Material": { "Enum": 256 }, + "MaterialVariantSerialized": { + "String": "" + }, + "MeshData": { + "BinaryString": "" + }, + "PhysicsData": { + "BinaryString": "" + }, "PivotOffset": { "CFrame": { "position": [ @@ -27169,7 +32094,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TopParamA": { "Float32": -0.5 @@ -27202,16 +32127,56 @@ "Name": "PartOperationAsset", "Tags": [], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "ChildData": { + "Name": "ChildData", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MeshData": { + "Name": "MeshData", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { "Attributes": { + "Attributes": {} + }, + "ChildData": { + "BinaryString": "" + }, + "MeshData": { "BinaryString": "" }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -27363,6 +32328,23 @@ } } }, + "FlipbookTextureCompatible": { + "Name": "FlipbookTextureCompatible", + "Scriptability": "None", + "DataType": { + "Enum": "ParticleFlipbookTextureCompatible" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Lifetime": { "Name": "Lifetime", "Scriptability": "ReadWrite", @@ -27639,6 +32621,19 @@ } } }, + "WindAffectsDrag": { + "Name": "WindAffectsDrag", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ZOffset": { "Name": "ZOffset", "Scriptability": "ReadWrite", @@ -27662,7 +32657,7 @@ ] }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Brightness": { "Float32": 1.0 @@ -27809,7 +32804,7 @@ } }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Texture": { "Content": "rbxasset://textures/particles/sparkles_main.dds" @@ -27836,6 +32831,9 @@ "VelocityInheritance": { "Float32": 0.0 }, + "WindAffectsDrag": { + "Bool": false + }, "ZOffset": { "Float32": 0.0 } @@ -27989,7 +32987,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "IsBidirectional": { "Bool": true @@ -28001,7 +32999,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -28039,7 +33037,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Label": { "String": "" @@ -28051,7 +33049,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -28211,13 +33209,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -28231,13 +33229,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -28288,6 +33286,19 @@ } } }, + "AreAssemblyCentersOfMassShown": { + "Name": "AreAssemblyCentersOfMassShown", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "AreAwakePartsHighlighted": { "Name": "AreAwakePartsHighlighted", "Scriptability": "ReadWrite", @@ -28314,6 +33325,19 @@ } } }, + "AreCollisionCostsShown": { + "Name": "AreCollisionCostsShown", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "AreConstraintForcesShownForSelectedOrHoveredInstances": { "Name": "AreConstraintForcesShownForSelectedOrHoveredInstances", "Scriptability": "None", @@ -28548,6 +33572,19 @@ } } }, + "DisableCSGv3ForPlugins": { + "Name": "DisableCSGv3ForPlugins", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ForceCSGv2": { "Name": "ForceCSGv2", "Scriptability": "ReadWrite", @@ -28705,7 +33742,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Enabled": { "Bool": true @@ -28720,10 +33757,32 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, + "PlaceStatsService": { + "Name": "PlaceStatsService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "PlacesService": { + "Name": "PlacesService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Plane": { "Name": "Plane", "Tags": [ @@ -28733,10 +33792,10 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 194 + "BrickColor": 194 }, "Enabled": { "Bool": true @@ -28745,7 +33804,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": false @@ -28759,10 +33818,10 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 194 + "BrickColor": 194 }, "Enabled": { "Bool": true @@ -28771,7 +33830,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": false @@ -28808,6 +33867,22 @@ } } }, + "AccountAgeReplicate": { + "Name": "AccountAgeReplicate", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "AppearanceDidLoad": { "Name": "AppearanceDidLoad", "Scriptability": "None", @@ -28933,6 +34008,22 @@ } } }, + "ChararacterRegionId": { + "Name": "ChararacterRegionId", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ChatMode": { "Name": "ChatMode", "Scriptability": "None", @@ -28950,6 +34041,70 @@ } } }, + "ChatPrivacyMode": { + "Name": "ChatPrivacyMode", + "Scriptability": "None", + "DataType": { + "Enum": "ChatPrivacyMode" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CloudEditCameraCoordinateFrame": { + "Name": "CloudEditCameraCoordinateFrame", + "Scriptability": "None", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CloudEditPlayerActive": { + "Name": "CloudEditPlayerActive", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CountryRegionCodeReplicate": { + "Name": "CountryRegionCodeReplicate", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "DataComplexity": { "Name": "DataComplexity", "Scriptability": "Read", @@ -29110,6 +34265,22 @@ } } }, + "FollowUserIdReplicated": { + "Name": "FollowUserIdReplicated", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "GameplayPaused": { "Name": "GameplayPaused", "Scriptability": "Read", @@ -29166,6 +34337,22 @@ } } }, + "InternalCharacterAppearanceLoaded": { + "Name": "InternalCharacterAppearanceLoaded", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "LocaleId": { "Name": "LocaleId", "Scriptability": "Read", @@ -29183,6 +34370,22 @@ } } }, + "MaxSimulationRadius": { + "Name": "MaxSimulationRadius", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "MaximumSimulationRadius": { "Name": "MaximumSimulationRadius", "Scriptability": "None", @@ -29215,6 +34418,22 @@ } } }, + "MembershipTypeReplicate": { + "Name": "MembershipTypeReplicate", + "Scriptability": "None", + "DataType": { + "Enum": "MembershipType" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "NameDisplayDistance": { "Name": "NameDisplayDistance", "Scriptability": "ReadWrite", @@ -29272,6 +34491,22 @@ } } }, + "RawJoinData": { + "Name": "RawJoinData", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ReplicationFocus": { "Name": "ReplicationFocus", "Scriptability": "ReadWrite", @@ -29313,6 +34548,22 @@ } } }, + "SuperSafeChatReplicate": { + "Name": "SuperSafeChatReplicate", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Team": { "Name": "Team", "Scriptability": "ReadWrite", @@ -29544,7 +34795,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CustomPoliciesEnabled": { "Bool": false @@ -29565,7 +34816,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -29808,6 +35059,38 @@ } } }, + "ServerGitHash": { + "Name": "ServerGitHash", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ServerLogPrefix": { + "Name": "ServerLogPrefix", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "UseStrafingAnimations": { "Name": "UseStrafingAnimations", "Scriptability": "None", @@ -29815,7 +35098,6 @@ "Value": "Bool" }, "Tags": [ - "NotReplicated", "NotScriptable" ], "Kind": { @@ -29863,7 +35145,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CharacterAutoLoads": { "Bool": true @@ -29881,7 +35163,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "UseStrafingAnimations": { "Bool": false @@ -30119,6 +35401,40 @@ }, "DefaultProperties": {} }, + "PluginCapabilities": { + "Name": "PluginCapabilities", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Manifest": { + "Name": "Manifest", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Manifest": { + "String": "{\"Metadata\":{\"TargetDataModels\": [\"Edit\", \"Server\", \"Client\"]},\"Permissions\":{}}" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, "PluginDebugService": { "Name": "PluginDebugService", "Tags": [ @@ -30416,7 +35732,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Brightness": { "Float32": 1.0 @@ -30441,7 +35757,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -30535,7 +35851,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CFrame": { "CFrame": { @@ -30573,7 +35889,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Weight": { "Float32": 1.0 @@ -30662,10 +35978,10 @@ "Enum": 0 }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 1009 + "BrickColor": 1009 }, "Enabled": { "Bool": true @@ -30701,7 +36017,7 @@ "Float32": 0.0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TargetPosition": { "Float32": 0.0 @@ -30727,13 +36043,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -30930,7 +36246,7 @@ "String": "Interact" }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoLocalize": { "Bool": true @@ -30969,7 +36285,7 @@ "Enum": 0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "UIOffset": { "Vector2": [ @@ -31016,7 +36332,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Enabled": { "Bool": true @@ -31028,7 +36344,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -31074,13 +36390,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Value": { "Ray": { @@ -31115,13 +36431,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -31132,13 +36448,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -31218,7 +36534,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Browsable": { "Bool": true @@ -31278,7 +36594,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "UIMaximum": { "Float64": 0.0 @@ -31298,13 +36614,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -31315,7 +36631,7 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Browsable": { "Bool": true @@ -31360,7 +36676,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "UIMaximum": { "Float64": 0.0 @@ -31380,7 +36696,7 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Browsable": { "Bool": true @@ -31425,7 +36741,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "UIMaximum": { "Float64": 0.0 @@ -31445,13 +36761,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -31462,13 +36778,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -31479,13 +36795,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -31714,7 +37030,7 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Browsable": { "Bool": true @@ -31759,7 +37075,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "UIMaximum": { "Float64": 0.0 @@ -31779,13 +37095,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -31796,13 +37112,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -31834,13 +37150,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -31851,13 +37167,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -31909,6 +37225,19 @@ } } }, + "Enable VR Mode": { + "Name": "Enable VR Mode", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "EnableFRM": { "Name": "EnableFRM", "Scriptability": "ReadWrite", @@ -32041,6 +37370,19 @@ "Serialization": "Serializes" } } + }, + "ViewMode": { + "Name": "ViewMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ViewMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": {} @@ -32144,6 +37486,19 @@ } } }, + "PerfTest": { + "Name": "PerfTest", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Position": { "Name": "Position", "Scriptability": "ReadWrite", @@ -32198,11 +37553,24 @@ "Serialization": "Serializes" } } + }, + "Timeout": { + "Name": "Timeout", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CFrame": { "CFrame": { @@ -32245,6 +37613,9 @@ "FieldOfView": { "Float32": 70.0 }, + "PerfTest": { + "Bool": false + }, "QualityLevel": { "Int32": 21 }, @@ -32255,10 +37626,13 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Ticket": { "String": "" + }, + "Timeout": { + "Int32": 10 } } }, @@ -32272,13 +37646,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -32292,13 +37666,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -32375,7 +37749,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "DecayTime": { "Float32": 1.5 @@ -32399,7 +37773,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "WetLevel": { "Float32": 0.0 @@ -32413,10 +37787,10 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 194 + "BrickColor": 194 }, "Enabled": { "Bool": true @@ -32425,7 +37799,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": false @@ -32454,6 +37828,17 @@ "Properties": {}, "DefaultProperties": {} }, + "RobloxServerStorage": { + "Name": "RobloxServerStorage", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "RocketPropulsion": { "Name": "RocketPropulsion", "Tags": [ @@ -32461,6 +37846,22 @@ ], "Superclass": "BodyMover", "Properties": { + "Active": { + "Name": "Active", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "CartoonFactor": { "Name": "CartoonFactor", "Scriptability": "ReadWrite", @@ -32607,7 +38008,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CartoonFactor": { "Float32": 0.7 @@ -32629,7 +38030,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TargetOffset": { "Vector3": [ @@ -32744,10 +38145,10 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 26 + "BrickColor": 26 }, "Enabled": { "Bool": true @@ -32768,7 +38169,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Thickness": { "Float32": 0.1 @@ -32778,6 +38179,319 @@ } } }, + "RomarkService": { + "Name": "RomarkService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "RootImportData": { + "Name": "RootImportData", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "BaseImportData", + "Properties": { + "AddModelToInventory": { + "Name": "AddModelToInventory", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Anchored": { + "Name": "Anchored", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AnimationIdForRestPose": { + "Name": "AnimationIdForRestPose", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ExistingPackageId": { + "Name": "ExistingPackageId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FileDimensions": { + "Name": "FileDimensions", + "Scriptability": "Read", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ImportAsModelAsset": { + "Name": "ImportAsModelAsset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImportAsPackage": { + "Name": "ImportAsPackage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InsertInWorkspace": { + "Name": "InsertInWorkspace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InsertWithScenePosition": { + "Name": "InsertWithScenePosition", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InvertNegativeFaces": { + "Name": "InvertNegativeFaces", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MergeMeshes": { + "Name": "MergeMeshes", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PolygonCount": { + "Name": "PolygonCount", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RestPose": { + "Name": "RestPose", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RestPose" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RigScale": { + "Name": "RigScale", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RigScale" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RigType": { + "Name": "RigType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RigType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RigVisualization": { + "Name": "RigVisualization", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ScaleUnit": { + "Name": "ScaleUnit", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "MeshScaleUnit" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UseSceneOriginAsCFrame": { + "Name": "UseSceneOriginAsCFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UseSceneOriginAsPivot": { + "Name": "UseSceneOriginAsPivot", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UsesCages": { + "Name": "UsesCages", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WorldForward": { + "Name": "WorldForward", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "NormalId" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WorldUp": { + "Name": "WorldUp", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "NormalId" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "RopeConstraint": { "Name": "RopeConstraint", "Tags": [], @@ -32906,10 +38620,10 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 25 + "BrickColor": 25 }, "Enabled": { "Bool": true @@ -32924,7 +38638,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Thickness": { "Float32": 0.1 @@ -32958,7 +38672,7 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "C0": { "CFrame": { @@ -33019,7 +38733,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -33032,7 +38746,7 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BaseAngle": { "Float32": 0.0 @@ -33096,7 +38810,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -33109,7 +38823,7 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BaseAngle": { "Float32": 0.0 @@ -33173,7 +38887,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -33197,17 +38911,36 @@ "Serialization": "DoesNotSerialize" } } + }, + "ValuesAndTimes": { + "Name": "ValuesAndTimes", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] + }, + "ValuesAndTimes": { + "BinaryString": "AAAAAAAAAAAAAAAAAAAWRQAAAAA=" } } }, @@ -33340,7 +39073,12 @@ "Tags": [], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": { + "Migrate": { + "To": "ScreenInsets", + "Migration": "IgnoreGuiInsetToScreenInsets" + } + } } } }, @@ -33392,7 +39130,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoLocalize": { "Bool": true @@ -33434,7 +39172,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "ZIndexBehavior": { "Enum": 0 @@ -33577,7 +39315,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Disabled": { "Bool": false @@ -33595,7 +39333,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -33642,6 +39380,17 @@ "Properties": {}, "DefaultProperties": {} }, + "ScriptCommitService": { + "Name": "ScriptCommitService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ScriptContext": { "Name": "ScriptContext", "Tags": [ @@ -33676,6 +39425,22 @@ ], "Superclass": "Instance", "Properties": { + "CoreScriptIdentifier": { + "Name": "CoreScriptIdentifier", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "CurrentLine": { "Name": "CurrentLine", "Scriptability": "Read", @@ -33739,6 +39504,22 @@ "Serialization": "DoesNotSerialize" } } + }, + "ScriptGuid": { + "Name": "ScriptGuid", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": {} @@ -33795,13 +39576,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -34116,7 +39897,7 @@ ] }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoLocalize": { "Bool": true @@ -34263,7 +40044,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TopImage": { "Content": "rbxasset://textures/ui/Scroll/scroll-top.png" @@ -34322,7 +40103,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -34405,6 +40186,9 @@ "Disabled": { "Bool": false }, + "EnableFluidForces": { + "Bool": true + }, "FormFactor": { "Enum": 1 }, @@ -34441,6 +40225,9 @@ "Material": { "Enum": 256 }, + "MaterialVariantSerialized": { + "String": "" + }, "PivotOffset": { "CFrame": { "position": [ @@ -34506,7 +40293,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TopParamA": { "Float32": -0.5 @@ -34557,6 +40344,23 @@ } } }, + "RenderMode": { + "Name": "RenderMode", + "Scriptability": "None", + "DataType": { + "Enum": "SelectionRenderMode" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "SelectionBoxThickness": { "Name": "SelectionBoxThickness", "Scriptability": "None", @@ -34607,14 +40411,15 @@ } } }, - "ShowBoundingBox": { - "Name": "ShowBoundingBox", + "ShowActiveInstanceHighlight": { + "Name": "ShowActiveInstanceHighlight", "Scriptability": "None", "DataType": { "Value": "Bool" }, "Tags": [ - "Hidden" + "Hidden", + "NotReplicated" ], "Kind": { "Canonical": { @@ -34625,13 +40430,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -34714,7 +40519,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color3": { "Color3": [ @@ -34743,7 +40548,7 @@ "Float32": 1.0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "Float32": 0.0 @@ -34809,7 +40614,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color3": { "Color3": [ @@ -34822,7 +40627,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "Float32": 0.0 @@ -34855,7 +40660,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color3": { "Color3": [ @@ -34875,7 +40680,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "Float32": 0.0 @@ -34936,7 +40741,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color3": { "Color3": [ @@ -34959,7 +40764,7 @@ "Float32": 1.0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "Float32": 0.0 @@ -35030,7 +40835,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "LoadStringEnabled": { "Bool": false @@ -35039,7 +40844,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -35054,13 +40859,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -35082,6 +40887,19 @@ ], "Superclass": "Instance", "Properties": { + "HiddenServices": { + "Name": "HiddenServices", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "VisibleServices": { "Name": "VisibleServices", "Scriptability": "None", @@ -35098,13 +40916,16 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} + }, + "HiddenServices": { + "BinaryString": "AAAAAA==" }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "VisibleServices": { "BinaryString": "AAAAAA==" @@ -35153,7 +40974,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color3": { "Color3": [ @@ -35169,7 +40990,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -35207,7 +41028,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color3": { "Color3": [ @@ -35223,7 +41044,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -35278,13 +41099,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -35327,6 +41148,22 @@ } } }, + "MoveState": { + "Name": "MoveState", + "Scriptability": "None", + "DataType": { + "Enum": "MoveState" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Steer": { "Name": "Steer", "Scriptability": "ReadWrite", @@ -35372,7 +41209,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -35452,6 +41289,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "EnableFluidForces": { + "Bool": true + }, "FormFactor": { "Enum": 1 }, @@ -35488,6 +41328,9 @@ "Material": { "Enum": 256 }, + "MaterialVariantSerialized": { + "String": "" + }, "PivotOffset": { "CFrame": { "position": [ @@ -35559,7 +41402,7 @@ "Bool": true }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Throttle": { "Int32": 0 @@ -35611,16 +41454,16 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SkinColor": { - "Int32": 226 + "BrickColor": 226 }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -35788,7 +41631,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CelestialBodiesShown": { "Bool": true @@ -35830,7 +41673,7 @@ "Content": "rbxasset://sky/sun.jpg" }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -36130,7 +41973,10 @@ "DataType": { "Value": "Float32" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Alias": { "AliasFor": "Opacity" @@ -36143,7 +41989,10 @@ "DataType": { "Value": "Float32" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Alias": { "AliasFor": "RiseVelocity" @@ -36156,7 +42005,10 @@ "DataType": { "Value": "Float32" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Alias": { "AliasFor": "Size" @@ -36166,7 +42018,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { "Color3": [ @@ -36191,7 +42043,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TimeScale": { "Float32": 1.0 @@ -36218,7 +42070,7 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "C0": { "CFrame": { @@ -36279,7 +42131,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -36348,8 +42200,8 @@ "Deprecated" ], "Kind": { - "Canonical": { - "Serialization": "Serializes" + "Alias": { + "AliasFor": "RollOffMinDistance" } } }, @@ -36541,9 +42393,7 @@ "DataType": { "Value": "Bool" }, - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -36580,6 +42430,22 @@ } } }, + "PlayingReplicator": { + "Name": "PlayingReplicator", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "RollOffGain": { "Name": "RollOffGain", "Scriptability": "None", @@ -36608,7 +42474,9 @@ ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": { + "SerializesAs": "xmlRead_MaxDistance_3" + } } } }, @@ -36623,7 +42491,9 @@ ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": { + "SerializesAs": "EmitterSize" + } } } }, @@ -36697,6 +42567,22 @@ } } }, + "TimePositionReplicator": { + "Name": "TimePositionReplicator", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "UsageContextPermission": { "Name": "UsageContextPermission", "Scriptability": "None", @@ -36749,20 +42635,38 @@ "DataType": { "Value": "Float32" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], "Kind": { "Alias": { - "AliasFor": "MaxDistance" + "AliasFor": "RollOffMaxDistance" + } + } + }, + "xmlRead_MinDistance_3": { + "Name": "xmlRead_MinDistance_3", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" } } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" - }, - "EmitterSize": { - "Float32": 10.0 + "Attributes": {} }, "LoopRegion": { "NumberRange": [ @@ -36773,9 +42677,6 @@ "Looped": { "Bool": false }, - "MaxDistance": { - "Float32": 10000.0 - }, "PlayOnRemove": { "Bool": false }, @@ -36794,6 +42695,12 @@ "Playing": { "Bool": false }, + "RollOffMaxDistance": { + "Float32": 10000.0 + }, + "RollOffMinDistance": { + "Float32": 10.0 + }, "RollOffMode": { "Enum": 0 }, @@ -36804,7 +42711,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TimePosition": { "Float64": 0.0 @@ -36871,13 +42778,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Volume": { "Float32": 0.5 @@ -36978,7 +42885,7 @@ "Enum": 0 }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "DistanceFactor": { "Float32": 3.33 @@ -36996,7 +42903,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "VolumetricAudio": { "Enum": 1 @@ -37066,7 +42973,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Enabled": { "Bool": true @@ -37082,7 +42989,7 @@ ] }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TimeScale": { "Float32": 1.0 @@ -37168,7 +43075,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -37251,6 +43158,9 @@ "Duration": { "Int32": 10 }, + "EnableFluidForces": { + "Bool": true + }, "Enabled": { "Bool": true }, @@ -37290,6 +43200,9 @@ "Material": { "Enum": 256 }, + "MaterialVariantSerialized": { + "String": "" + }, "Neutral": { "Bool": true }, @@ -37358,10 +43271,10 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TeamColor": { - "Int32": 194 + "BrickColor": 194 }, "TopParamA": { "Float32": -0.5 @@ -37397,148 +43310,6 @@ "Properties": {}, "DefaultProperties": {} }, - "Speaker": { - "Name": "Speaker", - "Tags": [ - "Deprecated", - "NotCreatable" - ], - "Superclass": "Instance", - "Properties": { - "ChannelCount": { - "Name": "ChannelCount", - "Scriptability": "Read", - "DataType": { - "Value": "Int32" - }, - "Tags": [ - "NotBrowsable", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "PlaybackLoudness": { - "Name": "PlaybackLoudness", - "Scriptability": "Read", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RollOffMaxDistance": { - "Name": "RollOffMaxDistance", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RollOffMinDistance": { - "Name": "RollOffMinDistance", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RollOffMode": { - "Name": "RollOffMode", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "RollOffMode" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "SoundGroup": { - "Name": "SoundGroup", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Source": { - "Name": "Source", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Volume": { - "Name": "Volume", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "RollOffMode": { - "Enum": 0 - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" - }, - "Volume": { - "Float32": 0.0 - } - } - }, "SpecialMesh": { "Name": "SpecialMesh", "Tags": [], @@ -37560,7 +43331,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "MeshId": { "Content": "" @@ -37586,7 +43357,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TextureId": { "Content": "" @@ -37627,7 +43398,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CFrame": { "CFrame": { @@ -37676,7 +43447,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "Float32": 0.0 @@ -37739,7 +43510,7 @@ "Float32": 90.0 }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Brightness": { "Float32": 1.0 @@ -37767,7 +43538,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -37925,13 +43696,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Coils": { "Float32": 3.0 }, "Color": { - "Int32": 200 + "BrickColor": 200 }, "Damping": { "Float32": 0.0 @@ -37964,7 +43735,7 @@ "Float32": 0.0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Thickness": { "Float32": 0.1 @@ -38145,13 +43916,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -38174,13 +43945,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -38191,13 +43962,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -38299,7 +44070,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "ResetPlayerGuiOnSpawn": { "Bool": true @@ -38317,7 +44088,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "VirtualCursorMode": { "Enum": 0 @@ -38334,13 +44105,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -38380,6 +44151,21 @@ } } }, + "AvatarJointUpgrade": { + "Name": "AvatarJointUpgrade", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AvatarJointUpgrade" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "CameraMaxZoomDistance": { "Name": "CameraMaxZoomDistance", "Scriptability": "ReadWrite", @@ -38484,6 +44270,21 @@ } } }, + "DeathStyle": { + "Name": "DeathStyle", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DeathStyle" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DevCameraOcclusionMode": { "Name": "DevCameraOcclusionMode", "Scriptability": "ReadWrite", @@ -38890,6 +44691,22 @@ } } }, + "LoadCharacterLayeredClothing": { + "Name": "LoadCharacterLayeredClothing", + "Scriptability": "None", + "DataType": { + "Enum": "LoadCharacterLayeredClothing" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "LoadCharacterLayeredClothing ": { "Name": "LoadCharacterLayeredClothing ", "Scriptability": "None", @@ -38938,11 +44755,14 @@ "Bool": true }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoJumpEnabled": { "Bool": true }, + "AvatarJointUpgrade": { + "Enum": 0 + }, "CameraMaxZoomDistance": { "Float32": 400.0 }, @@ -38967,6 +44787,9 @@ "CharacterWalkSpeed": { "Float32": 16.0 }, + "DeathStyle": { + "Enum": 0 + }, "DevCameraOcclusionMode": { "Enum": 0 }, @@ -39063,6 +44886,9 @@ "LoadCharacterAppearance": { "Bool": true }, + "LoadCharacterLayeredClothing": { + "Enum": 0 + }, "NameDisplayDistance": { "Float32": 100.0 }, @@ -39070,7 +44896,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "UserEmotesEnabled": { "Bool": true @@ -39086,13 +44912,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -39304,6 +45130,17 @@ "Properties": {}, "DefaultProperties": {} }, + "StopWatchReporter": { + "Name": "StopWatchReporter", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "StringValue": { "Name": "StringValue", "Tags": [], @@ -39325,13 +45162,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Value": { "String": "" @@ -39578,6 +45415,19 @@ } } }, + "Automatically trigger AI Code Completion": { + "Name": "Automatically trigger AI Code Completion", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Background Color": { "Name": "Background Color", "Scriptability": "ReadWrite", @@ -39815,19 +45665,6 @@ } } }, - "Display Team Create toggle when creating a new experience": { - "Name": "Display Team Create toggle when creating a new experience", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "DisplayLanguage": { "Name": "DisplayLanguage", "Scriptability": "None", @@ -39857,19 +45694,6 @@ } } }, - "Drag Multiple Parts As Single Part": { - "Name": "Drag Multiple Parts As Single Part", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "Enable Autocomplete": { "Name": "Enable Autocomplete", "Scriptability": "ReadWrite", @@ -40039,6 +45863,19 @@ } } }, + "EnableIndentationRulers": { + "Name": "EnableIndentationRulers", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "EnableOnTypeAutocomplete": { "Name": "EnableOnTypeAutocomplete", "Scriptability": "None", @@ -40070,19 +45907,6 @@ } } }, - "File > New creates a place with Team Create off": { - "Name": "File > New creates a place with Team Create off", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "Find Selection Background Color": { "Name": "Find Selection Background Color", "Scriptability": "ReadWrite", @@ -40165,6 +45989,21 @@ } } }, + "HintColor": { + "Name": "HintColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Hover Animate Speed": { "Name": "Hover Animate Speed", "Scriptability": "ReadWrite", @@ -40230,6 +46069,36 @@ } } }, + "IndentationRulerColor": { + "Name": "IndentationRulerColor", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "InformationColor": { + "Name": "InformationColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Keyword Color": { "Name": "Keyword Color", "Scriptability": "ReadWrite", @@ -40512,6 +46381,32 @@ } } }, + "ReloadBuiltinPluginsOnChange": { + "Name": "ReloadBuiltinPluginsOnChange", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReloadLocalPluginsOnChange": { + "Name": "ReloadLocalPluginsOnChange", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Render Throttle Percentage": { "Name": "Render Throttle Percentage", "Scriptability": "ReadWrite", @@ -40680,19 +46575,6 @@ } } }, - "Search Content For Core Scripts": { - "Name": "Search Content For Core Scripts", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "Secondary Text Color": { "Name": "Secondary Text Color", "Scriptability": "ReadWrite", @@ -40807,19 +46689,6 @@ } } }, - "Selection Highlight Thickness": { - "Name": "Selection Highlight Thickness", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "Selection Line Thickness": { "Name": "Selection Line Thickness", "Scriptability": "None", @@ -40989,9 +46858,9 @@ } } }, - "Show QT warnings in output": { - "Name": "Show QT warnings in output", - "Scriptability": "ReadWrite", + "Show Singly Selected Attachment Parent Frame": { + "Name": "Show Singly Selected Attachment Parent Frame", + "Scriptability": "None", "DataType": { "Value": "Bool" }, @@ -41198,6 +47067,120 @@ "Properties": {}, "DefaultProperties": {} }, + "StudioCallout": { + "Name": "StudioCallout", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "AnchorPoint": { + "Name": "AnchorPoint", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsArrowVisible": { + "Name": "IsArrowVisible", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsNextVisible": { + "Name": "IsNextVisible", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RowName": { + "Name": "RowName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Text": { + "Name": "Text", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Title": { + "Name": "Title", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, "StudioData": { "Name": "StudioData", "Tags": [ @@ -41224,7 +47207,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "EnableScriptCollabByDefaultOnLoad": { "Bool": false @@ -41233,7 +47216,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -41316,6 +47299,23 @@ }, "DefaultProperties": {} }, + "StudioObjectBase": { + "Name": "StudioObjectBase", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, "StudioPublishService": { "Name": "StudioPublishService", "Tags": [ @@ -41414,6 +47414,7 @@ "Value": "Bool" }, "Tags": [ + "Deprecated", "NotReplicated", "ReadOnly" ], @@ -41505,22 +47506,6 @@ } } }, - "ShowActiveInstanceHighlight": { - "Name": "ShowActiveInstanceHighlight", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "ShowConstraintDetails": { "Name": "ShowConstraintDetails", "Scriptability": "Read", @@ -41581,6 +47566,229 @@ "Properties": {}, "DefaultProperties": {} }, + "StudioWidget": { + "Name": "StudioWidget", + "Tags": [], + "Superclass": "StudioObjectBase", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "StyleBase": { + "Name": "StyleBase", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, + "StyleDerive": { + "Name": "StyleDerive", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Index": { + "Name": "Index", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StyleSheet": { + "Name": "StyleSheet", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Index": { + "Int32": -1 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "StyleLink": { + "Name": "StyleLink", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "StyleSheet": { + "Name": "StyleSheet", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "StyleRule": { + "Name": "StyleRule", + "Tags": [], + "Superclass": "StyleBase", + "Properties": { + "Index": { + "Name": "Index", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PropertiesSerialize": { + "Name": "PropertiesSerialize", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Selector": { + "Name": "Selector", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SelectorError": { + "Name": "SelectorError", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Index": { + "Int32": -1 + }, + "PropertiesSerialize": { + "BinaryString": "" + }, + "Selector": { + "String": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "StyleSheet": { + "Name": "StyleSheet", + "Tags": [], + "Superclass": "StyleBase", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "StylingService": { + "Name": "StylingService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "SunRaysEffect": { "Name": "SunRaysEffect", "Tags": [], @@ -41615,7 +47823,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Enabled": { "Bool": true @@ -41630,7 +47838,7 @@ "Float32": 1.0 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -41723,7 +47931,7 @@ "Enum": 0 }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "ColorMap": { "Content": "" @@ -41741,7 +47949,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TexturePack": { "Content": "" @@ -41909,7 +48117,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoLocalize": { "Bool": true @@ -41963,7 +48171,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "ToolPunchThroughDistance": { "Float32": 0.0 @@ -42075,7 +48283,7 @@ "Float32": 90.0 }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Brightness": { "Float32": 1.0 @@ -42103,7 +48311,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -42128,7 +48336,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color3": { "Color3": [ @@ -42141,7 +48349,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TargetSurface": { "Enum": 0 @@ -42232,7 +48440,10 @@ "Float32": 0.0 }, "Attributes": { - "BinaryString": "" + "Attributes": {} + }, + "BalanceRigidityEnabled": { + "Bool": false }, "MoveSpeedFactor": { "Float32": 1.0 @@ -42243,9 +48454,6 @@ "PitchSpeedFactor": { "Float32": 1.0 }, - "RigidityEnabled": { - "Bool": false - }, "RollMaxTorque": { "Float32": 10000.0 }, @@ -42256,7 +48464,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -42268,6 +48476,19 @@ ], "Superclass": "ScriptBuilder", "Properties": { + "CompileTarget": { + "Name": "CompileTarget", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "CompileTarget" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "CoverageInfo": { "Name": "CoverageInfo", "Scriptability": "ReadWrite", @@ -42313,7 +48534,9 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Deprecated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -42476,7 +48699,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoAssignable": { "Bool": true @@ -42485,10 +48708,10 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TeamColor": { - "Int32": 1 + "BrickColor": 1 } } }, @@ -42499,7 +48722,24 @@ "Service" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "InitialCameraCFrame": { + "Name": "InitialCameraCFrame", + "Scriptability": "None", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, "DefaultProperties": {} }, "TeamCreatePublishService": { @@ -42533,13 +48773,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -42632,7 +48872,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "ReservedServerAccessCode": { "String": "" @@ -42647,7 +48887,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -42678,13 +48918,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -42717,6 +48957,76 @@ ], "Superclass": "BasePart", "Properties": { + "AcquisitionMethod": { + "Name": "AcquisitionMethod", + "Scriptability": "None", + "DataType": { + "Enum": "TerrainAcquisitionMethod" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ClusterGrid": { + "Name": "ClusterGrid", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "WriteOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ClusterGridV2": { + "Name": "ClusterGridV2", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "WriteOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ClusterGridV3": { + "Name": "ClusterGridV3", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "WriteOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Decoration": { "Name": "Decoration", "Scriptability": "None", @@ -42767,9 +49077,9 @@ }, "MaterialColors": { "Name": "MaterialColors", - "Scriptability": "None", + "Scriptability": "Custom", "DataType": { - "Value": "BinaryString" + "Value": "MaterialColors" }, "Tags": [ "NotScriptable" @@ -42796,6 +49106,23 @@ } } }, + "PhysicsGrid": { + "Name": "PhysicsGrid", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ShorelinesUpgraded": { "Name": "ShorelinesUpgraded", "Scriptability": "None", @@ -42811,6 +49138,23 @@ } } }, + "SmoothGrid": { + "Name": "SmoothGrid", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "SmoothVoxelsUpgraded": { "Name": "SmoothVoxelsUpgraded", "Scriptability": "None", @@ -42893,11 +49237,14 @@ } }, "DefaultProperties": { + "AcquisitionMethod": { + "Enum": 0 + }, "Anchored": { "Bool": true }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -42980,6 +49327,9 @@ "Decoration": { "Bool": false }, + "EnableFluidForces": { + "Bool": true + }, "FrontParamA": { "Float32": -0.5 }, @@ -43014,7 +49364,119 @@ "Enum": 256 }, "MaterialColors": { - "BinaryString": "AAAAAAAAan8/P39rf2Y/ilY+j35fi21PZmxvZbDqw8faiVpHOi4kHh4lZlw76JxKc3trhHtagcLgc4RKxr21zq2UlJSM" + "MaterialColors": { + "Grass": [ + 106, + 127, + 63 + ], + "Slate": [ + 63, + 127, + 107 + ], + "Concrete": [ + 127, + 102, + 63 + ], + "Brick": [ + 138, + 86, + 62 + ], + "Sand": [ + 143, + 126, + 95 + ], + "WoodPlanks": [ + 139, + 109, + 79 + ], + "Rock": [ + 102, + 108, + 111 + ], + "Glacier": [ + 101, + 176, + 234 + ], + "Snow": [ + 195, + 199, + 218 + ], + "Sandstone": [ + 137, + 90, + 71 + ], + "Mud": [ + 58, + 46, + 36 + ], + "Basalt": [ + 30, + 30, + 37 + ], + "Ground": [ + 102, + 92, + 59 + ], + "CrackedLava": [ + 232, + 156, + 74 + ], + "Asphalt": [ + 115, + 123, + 107 + ], + "Cobblestone": [ + 132, + 123, + 90 + ], + "Ice": [ + 129, + 194, + 224 + ], + "LeafyGrass": [ + 115, + 132, + 74 + ], + "Salt": [ + 198, + 189, + 181 + ], + "Limestone": [ + 206, + 173, + 148 + ], + "Pavement": [ + 148, + 148, + 140 + ] + } + }, + "MaterialVariantSerialized": { + "String": "" + }, + "PhysicsGrid": { + "BinaryString": "AgMAAAAAAAAAAAAAAAA=" }, "PivotOffset": { "CFrame": { @@ -43077,6 +49539,9 @@ 2044.0 ] }, + "SmoothGrid": { + "BinaryString": "AQU=" + }, "SmoothVoxelsUpgraded": { "Bool": false }, @@ -43084,7 +49549,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TopParamA": { "Float32": -0.5 @@ -43224,11 +49689,27 @@ "Serialization": "Serializes" } } + }, + "TexturePack": { + "Name": "TexturePack", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "ColorMap": { "Content": "" @@ -43255,7 +49736,10 @@ "Float32": 10.0 }, "Tags": { - "BinaryString": "" + "Tags": [] + }, + "TexturePack": { + "Content": "" } } }, @@ -43264,6 +49748,56 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "ExtentsMax": { + "Name": "ExtentsMax", + "Scriptability": "None", + "DataType": { + "Value": "Vector3int16" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ExtentsMin": { + "Name": "ExtentsMin", + "Scriptability": "None", + "DataType": { + "Value": "Vector3int16" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GridV3": { + "Name": "GridV3", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "WriteOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "IsSmooth": { "Name": "IsSmooth", "Scriptability": "Read", @@ -43296,17 +49830,51 @@ "Serialization": "DoesNotSerialize" } } + }, + "SmoothGrid": { + "Name": "SmoothGrid", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} + }, + "ExtentsMax": { + "Vector3int16": [ + 0, + 0, + 0 + ] + }, + "ExtentsMin": { + "Vector3int16": [ + 0, + 0, + 0 + ] + }, + "SmoothGrid": { + "BinaryString": "AQU=" }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -43485,7 +50053,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoRuns": { "Bool": true @@ -43515,7 +50083,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Timeout": { "Float64": 10.0 @@ -43540,6 +50108,23 @@ } } }, + "Confidential": { + "Name": "Confidential", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ContentText": { "Name": "ContentText", "Scriptability": "Read", @@ -43581,7 +50166,12 @@ ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": { + "Migrate": { + "To": "FontFace", + "Migration": "FontToFontFace" + } + } } } }, @@ -43825,6 +50415,19 @@ } } }, + "TextDirection": { + "Name": "TextDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextDirection" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TextEditable": { "Name": "TextEditable", "Scriptability": "ReadWrite", @@ -44015,7 +50618,7 @@ ] }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoLocalize": { "Bool": true @@ -44146,7 +50749,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Text": { "String": "TextBox" @@ -44158,6 +50761,9 @@ 0.20784315 ] }, + "TextDirection": { + "Enum": 0 + }, "TextEditable": { "Bool": true }, @@ -44215,6 +50821,23 @@ "Tags": [], "Superclass": "GuiButton", "Properties": { + "Confidential": { + "Name": "Confidential", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ContentText": { "Name": "ContentText", "Scriptability": "Read", @@ -44243,7 +50866,12 @@ ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": { + "Migrate": { + "To": "FontFace", + "Migration": "FontToFontFace" + } + } } } }, @@ -44391,6 +51019,19 @@ } } }, + "TextDirection": { + "Name": "TextDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextDirection" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TextFits": { "Name": "TextFits", "Scriptability": "Read", @@ -44552,7 +51193,7 @@ ] }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoButtonColor": { "Bool": true @@ -44676,7 +51317,7 @@ "Enum": 0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Text": { "String": "Button" @@ -44688,6 +51329,9 @@ 0.20784315 ] }, + "TextDirection": { + "Enum": 0 + }, "TextScaled": { "Bool": false }, @@ -44734,13 +51378,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -44791,7 +51435,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Enabled": { "Bool": true @@ -44806,7 +51450,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -44827,6 +51471,19 @@ ], "Superclass": "Instance", "Properties": { + "BubbleChatMessageProperties": { + "Name": "BubbleChatMessageProperties", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MessageId": { "Name": "MessageId", "Scriptability": "ReadWrite", @@ -44955,13 +51612,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -45015,7 +51672,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "ChatVersion": { "Enum": 0 @@ -45030,7 +51687,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -45044,11 +51701,71 @@ "Properties": {}, "DefaultProperties": {} }, + "TextFilterTranslatedResult": { + "Name": "TextFilterTranslatedResult", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "SourceLanguage": { + "Name": "SourceLanguage", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SourceText": { + "Name": "SourceText", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "TextLabel": { "Name": "TextLabel", "Tags": [], "Superclass": "GuiLabel", "Properties": { + "Confidential": { + "Name": "Confidential", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ContentText": { "Name": "ContentText", "Scriptability": "Read", @@ -45077,7 +51794,12 @@ ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": { + "Migrate": { + "To": "FontFace", + "Migration": "FontToFontFace" + } + } } } }, @@ -45225,6 +51947,19 @@ } } }, + "TextDirection": { + "Name": "TextDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextDirection" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TextFits": { "Name": "TextFits", "Scriptability": "Read", @@ -45386,7 +52121,7 @@ ] }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoLocalize": { "Bool": true @@ -45498,7 +52233,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Text": { "String": "Label" @@ -45510,6 +52245,9 @@ 0.20784315 ] }, + "TextDirection": { + "Enum": 0 + }, "TextScaled": { "Bool": false }, @@ -45595,6 +52333,22 @@ "Serialization": "DoesNotSerialize" } } + }, + "UserIdReplicated": { + "Name": "UserIdReplicated", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": {} @@ -45659,7 +52413,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color3": { "Color3": [ @@ -45687,7 +52441,7 @@ "Float32": 2.0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Texture": { "Content": "" @@ -45700,45 +52454,6 @@ } } }, - "TextureGuiExperimental": { - "Name": "TextureGuiExperimental", - "Tags": [ - "NotCreatable" - ], - "Superclass": "LayerCollector", - "Properties": { - "Size": { - "Name": "Size", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector2" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "TemporaryId": { - "Name": "TemporaryId", - "Scriptability": "Read", - "DataType": { - "Value": "Content" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": {} - }, "ThirdPartyUserService": { "Name": "ThirdPartyUserService", "Tags": [ @@ -45839,13 +52554,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -46010,7 +52725,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CanBeDropped": { "Bool": true @@ -46050,9 +52765,45 @@ "ManualActivationOnly": { "Bool": false }, + "ModelMeshCFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ModelMeshSize": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, "ModelStreamingMode": { "Enum": 0 }, + "NeedsPivotMigration": { + "Bool": false + }, "RequiresHandle": { "Bool": true }, @@ -46063,13 +52814,39 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TextureId": { "Content": "" }, "ToolTip": { "String": "" + }, + "WorldPivotData": { + "OptionalCFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } } } }, @@ -46107,10 +52884,10 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 23 + "BrickColor": 23 }, "Enabled": { "Bool": true @@ -46122,7 +52899,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Torque": { "Vector3": [ @@ -46280,13 +53057,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Coils": { "Float32": 8.0 }, "Color": { - "Int32": 200 + "BrickColor": 200 }, "Damping": { "Float32": 0.01 @@ -46319,7 +53096,7 @@ "Float32": 100.0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": false @@ -46345,13 +53122,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -46664,7 +53441,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Brightness": { "Float32": 1.0 @@ -46716,7 +53493,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Texture": { "Content": "" @@ -46835,7 +53612,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Depth": { "Float32": 1.0 @@ -46856,7 +53633,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -46897,6 +53674,22 @@ "Serialization": "DoesNotSerialize" } } + }, + "PhysicalConfigData": { + "Name": "PhysicalConfigData", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": {} @@ -46920,6 +53713,22 @@ "Serialization": "DoesNotSerialize" } } + }, + "style": { + "Name": "style", + "Scriptability": "None", + "DataType": { + "Enum": "Style" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -46927,7 +53736,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -47007,6 +53816,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "EnableFluidForces": { + "Bool": true + }, "FrontParamA": { "Float32": -0.5 }, @@ -47040,6 +53852,9 @@ "Material": { "Enum": 256 }, + "MaterialVariantSerialized": { + "String": "" + }, "PivotOffset": { "CFrame": { "position": [ @@ -47102,7 +53917,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TopParamA": { "Float32": -0.5 @@ -47125,9 +53940,23 @@ 0.0, 0.0 ] + }, + "style": { + "Enum": 0 } } }, + "TutorialService": { + "Name": "TutorialService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Tween": { "Name": "Tween", "Tags": [], @@ -47152,13 +53981,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -47199,13 +54028,33 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] + } + } + }, + "UGCAvatarService": { + "Name": "UGCAvatarService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] } } }, @@ -47273,7 +54122,7 @@ "Enum": 0 }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "DominantAxis": { "Enum": 0 @@ -47282,7 +54131,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -47334,7 +54183,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CornerRadius": { "UDim": [ @@ -47346,7 +54195,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -47423,7 +54272,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { "ColorSequence": { @@ -47463,7 +54312,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "NumberSequence": { @@ -47575,7 +54424,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CellPadding": { "UDim2": [ @@ -47620,7 +54469,7 @@ "Enum": 0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "VerticalAlignment": { "Enum": 1 @@ -47736,7 +54585,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "FillDirection": { "Enum": 1 @@ -47757,7 +54606,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "VerticalAlignment": { "Enum": 1 @@ -47824,7 +54673,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "PaddingBottom": { "UDim": [ @@ -47854,7 +54703,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -48002,7 +54851,7 @@ "Bool": true }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Circular": { "Bool": false @@ -48038,7 +54887,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TouchInputEnabled": { "Bool": true @@ -48072,7 +54921,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Scale": { "Float32": 1.0 @@ -48081,7 +54930,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -48119,7 +54968,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "MaxSize": { "Vector2": [ @@ -48137,7 +54986,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -48230,7 +55079,7 @@ "Enum": 0 }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { "Color3": [ @@ -48249,7 +55098,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Thickness": { "Float32": 1.0 @@ -48319,7 +55168,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "FillDirection": { "Enum": 1 @@ -48355,7 +55204,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "VerticalAlignment": { "Enum": 1 @@ -48396,7 +55245,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "MaxTextSize": { "Int32": 100 @@ -48408,7 +55257,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -48425,7 +55274,7 @@ "Content": "" }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -48489,6 +55338,9 @@ "CastShadow": { "Bool": true }, + "ChildData": { + "BinaryString": "" + }, "CollisionGroup": { "String": "Default" }, @@ -48505,6 +55357,12 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "EnableFluidForces": { + "Bool": true + }, + "FormFactor": { + "Enum": 3 + }, "FrontParamA": { "Float32": -0.5 }, @@ -48517,6 +55375,13 @@ "FrontSurfaceInput": { "Enum": 0 }, + "InitialSize": { + "Vector3": [ + 1.0, + 1.0, + 1.0 + ] + }, "LeftParamA": { "Float32": -0.5 }, @@ -48538,6 +55403,15 @@ "Material": { "Enum": 256 }, + "MaterialVariantSerialized": { + "String": "" + }, + "MeshData": { + "BinaryString": "" + }, + "PhysicsData": { + "BinaryString": "" + }, "PivotOffset": { "CFrame": { "position": [ @@ -48606,7 +55480,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TopParamA": { "Float32": -0.5 @@ -48695,10 +55569,10 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 1009 + "BrickColor": 1009 }, "Enabled": { "Bool": true @@ -48719,7 +55593,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": false @@ -48733,16 +55607,36 @@ "Service" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "CachedData": { + "Name": "CachedData", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} + }, + "CachedData": { + "String": "{\"lastSaveTime\":0,\"lastKnownPublishRequest\":0,\"users\":[]}" }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -48809,6 +55703,39 @@ } } }, + "CompletedTutorials": { + "Name": "CompletedTutorials", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ComputerCameraMovementChanged": { + "Name": "ComputerCameraMovementChanged", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ComputerCameraMovementMode": { "Name": "ComputerCameraMovementMode", "Scriptability": "ReadWrite", @@ -48822,6 +55749,23 @@ } } }, + "ComputerMovementChanged": { + "Name": "ComputerMovementChanged", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ComputerMovementMode": { "Name": "ComputerMovementMode", "Scriptability": "ReadWrite", @@ -49116,6 +56060,22 @@ } } }, + "PreferredTransparency": { + "Name": "PreferredTransparency", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "RCCProfilerRecordFrameRate": { "Name": "RCCProfilerRecordFrameRate", "Scriptability": "ReadWrite", @@ -49142,6 +56102,22 @@ } } }, + "ReducedMotion": { + "Name": "ReducedMotion", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "RotationType": { "Name": "RotationType", "Scriptability": "ReadWrite", @@ -49216,6 +56192,23 @@ } } }, + "TouchCameraMovementChanged": { + "Name": "TouchCameraMovementChanged", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TouchCameraMovementMode": { "Name": "TouchCameraMovementMode", "Scriptability": "ReadWrite", @@ -49229,6 +56222,23 @@ } } }, + "TouchMovementChanged": { + "Name": "TouchMovementChanged", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TouchMovementMode": { "Name": "TouchMovementMode", "Scriptability": "ReadWrite", @@ -49242,6 +56252,22 @@ } } }, + "UiNavigationKeyBindEnabled": { + "Name": "UiNavigationKeyBindEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "UsedCoreGuiIsVisibleToggle": { "Name": "UsedCoreGuiIsVisibleToggle", "Scriptability": "None", @@ -49294,22 +56320,6 @@ } } }, - "VRPlayMode": { - "Name": "VRPlayMode", - "Scriptability": "Read", - "DataType": { - "Enum": "VRPlayMode" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "VRRotationIntensity": { "Name": "VRRotationIntensity", "Scriptability": "None", @@ -49364,6 +56374,23 @@ "Serialization": "Serializes" } } + }, + "gaID": { + "Name": "gaID", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": {} @@ -49941,16 +56968,26 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, + "VRStatusService": { + "Name": "VRStatusService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ValueBase": { "Name": "ValueBase", "Tags": [ @@ -49967,13 +57004,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -49998,13 +57035,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Value": { "Vector3": [ @@ -50065,10 +57102,10 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "Color": { - "Int32": 23 + "BrickColor": 23 }, "Enabled": { "Bool": true @@ -50087,7 +57124,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": false @@ -50101,13 +57138,13 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -50193,7 +57230,9 @@ "DataType": { "Value": "Int32" }, - "Tags": [], + "Tags": [ + "NotReplicated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -50219,7 +57258,9 @@ "DataType": { "Value": "Int32" }, - "Tags": [], + "Tags": [ + "NotReplicated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -50271,7 +57312,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -50354,6 +57395,9 @@ "Disabled": { "Bool": false }, + "EnableFluidForces": { + "Bool": true + }, "FrontParamA": { "Float32": -0.5 }, @@ -50390,6 +57434,9 @@ "Material": { "Enum": 256 }, + "MaterialVariantSerialized": { + "String": "" + }, "MaxSpeed": { "Float32": 25.0 }, @@ -50461,7 +57508,7 @@ "Float32": 0.0 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Throttle": { "Int32": 0 @@ -50559,7 +57606,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "C0": { "CFrame": { @@ -50629,7 +57676,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -50655,6 +57702,22 @@ "Serialization": "DoesNotSerialize" } } + }, + "ScriptCollabVersionHistoryEnabled": { + "Name": "ScriptCollabVersionHistoryEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": {} @@ -50702,13 +57765,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -50761,6 +57824,22 @@ } } }, + "PlayingReplicating": { + "Name": "PlayingReplicating", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Resolution": { "Name": "Resolution", "Scriptability": "Read", @@ -50808,6 +57887,22 @@ } } }, + "TimePositionReplicating": { + "Name": "TimePositionReplicating", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Video": { "Name": "Video", "Scriptability": "ReadWrite", @@ -50846,7 +57941,7 @@ ] }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoLocalize": { "Bool": true @@ -50947,7 +58042,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TimePosition": { "Float64": 0.0 @@ -50966,6 +58061,26 @@ } } }, + "VideoService": { + "Name": "VideoService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, "ViewportFrame": { "Name": "ViewportFrame", "Tags": [], @@ -50984,6 +58099,38 @@ } } }, + "CameraCFrame": { + "Name": "CameraCFrame", + "Scriptability": "None", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraFieldOfView": { + "Name": "CameraFieldOfView", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "CurrentCamera": { "Name": "CurrentCamera", "Scriptability": "ReadWrite", @@ -51086,7 +58233,7 @@ ] }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoLocalize": { "Bool": true @@ -51117,6 +58264,35 @@ "BorderSizePixel": { "Int32": 1 }, + "CameraCFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "CameraFieldOfView": { + "Float32": 1.2217306 + }, "ClipsDescendants": { "Bool": false }, @@ -51205,7 +58381,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Visible": { "Bool": true @@ -51241,13 +58417,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -51323,13 +58499,13 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "SourceAssetId": { "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -51354,6 +58530,21 @@ } } }, + "UseNewJoinFlow": { + "Name": "UseNewJoinFlow", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "VoiceChatEnabledForPlaceOnRcc": { "Name": "VoiceChatEnabledForPlaceOnRcc", "Scriptability": "None", @@ -51387,7 +58578,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "EnableDefaultVoice": { "Bool": true @@ -51396,44 +58587,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" - } - } - }, - "VoiceSource": { - "Name": "VoiceSource", - "Tags": [ - "Deprecated", - "NotCreatable" - ], - "Superclass": "Instance", - "Properties": { - "UserId": { - "Name": "UserId", - "Scriptability": "Read", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "BinaryString": "" - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -51447,7 +58601,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "BackParamA": { "Float32": -0.5 @@ -51527,6 +58681,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "EnableFluidForces": { + "Bool": true + }, "FormFactor": { "Enum": 1 }, @@ -51563,6 +58720,9 @@ "Material": { "Enum": 256 }, + "MaterialVariantSerialized": { + "String": "" + }, "PivotOffset": { "CFrame": { "position": [ @@ -51625,7 +58785,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "TopParamA": { "Float32": -0.5 @@ -51658,7 +58818,7 @@ "Properties": {}, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "C0": { "CFrame": { @@ -51719,7 +58879,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] } } }, @@ -51744,6 +58904,39 @@ } } }, + "CFrame0": { + "Name": "CFrame0", + "Scriptability": "None", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CFrame1": { + "Name": "CFrame1", + "Scriptability": "None", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Enabled": { "Name": "Enabled", "Scriptability": "ReadWrite", @@ -51782,7 +58975,10 @@ "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Alias": { "AliasFor": "Part0" @@ -51812,23 +59008,165 @@ "DataType": { "Value": "Ref" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Alias": { "AliasFor": "Part1" } } + }, + "State": { + "Name": "State", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} + }, + "CFrame0": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } }, "SourceAssetId": { "Int64": -1 }, + "State": { + "Int32": 3 + }, "Tags": { - "BinaryString": "" + "Tags": [] + } + } + }, + "Wire": { + "Name": "Wire", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "Connected": { + "Name": "Connected", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SourceInstance": { + "Name": "SourceInstance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SourceName": { + "Name": "SourceName", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TargetInstance": { + "Name": "TargetInstance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TargetName": { + "Name": "TargetName", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "SourceAssetId": { + "Int64": -1 + }, + "SourceName": { + "String": "Output" + }, + "Tags": { + "Tags": [] + }, + "TargetName": { + "String": "Input" } } }, @@ -51859,7 +59197,7 @@ "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CFrame": { "CFrame": { @@ -51912,7 +59250,7 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] }, "Transparency": { "Float32": 0.0 @@ -51933,6 +59271,19 @@ ], "Superclass": "WorldRoot", "Properties": { + "AirDensity": { + "Name": "AirDensity", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "AllowThirdPartySales": { "Name": "AllowThirdPartySales", "Scriptability": "ReadWrite", @@ -51976,13 +59327,34 @@ } } }, + "CollisionGroupData": { + "Name": "CollisionGroupData", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "CollisionGroups": { "Name": "CollisionGroups", "Scriptability": "None", "DataType": { "Value": "String" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "WriteOnly" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -52004,6 +59376,22 @@ } } }, + "DataModelPlaceVersion": { + "Name": "DataModelPlaceVersion", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "DistributedGameTime": { "Name": "DistributedGameTime", "Scriptability": "ReadWrite", @@ -52025,7 +59413,10 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -52062,6 +59453,21 @@ } } }, + "FluidForces": { + "Name": "FluidForces", + "Scriptability": "None", + "DataType": { + "Enum": "FluidForces" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "GlobalWind": { "Name": "GlobalWind", "Scriptability": "ReadWrite", @@ -52103,6 +59509,21 @@ } } }, + "IKControlConstraintSupport": { + "Name": "IKControlConstraintSupport", + "Scriptability": "None", + "DataType": { + "Enum": "IKControlConstraintSupport" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "InterpolationThrottling": { "Name": "InterpolationThrottling", "Scriptability": "ReadWrite", @@ -52131,6 +59552,21 @@ } } }, + "ModelStreamingBehavior": { + "Name": "ModelStreamingBehavior", + "Scriptability": "None", + "DataType": { + "Enum": "ModelStreamingBehavior" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PhysicsSteppingMethod": { "Name": "PhysicsSteppingMethod", "Scriptability": "None", @@ -52200,7 +59636,26 @@ ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": { + "SerializesAs": "SignalBehavior2" + } + } + } + }, + "SignalBehavior2": { + "Name": "SignalBehavior2", + "Scriptability": "None", + "DataType": { + "Enum": "SignalBehavior" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Alias": { + "AliasFor": "SignalBehavior" } } }, @@ -52262,6 +59717,24 @@ } } }, + "StreamingPauseMode": { + "Name": "StreamingPauseMode", + "Scriptability": "None", + "DataType": { + "Enum": "StreamingPauseMode" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "WriteOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "StreamingTargetRadius": { "Name": "StreamingTargetRadius", "Scriptability": "None", @@ -52293,6 +59766,22 @@ } } }, + "TerrainWeldsFixed": { + "Name": "TerrainWeldsFixed", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TouchesUseCollisionGroups": { "Name": "TouchesUseCollisionGroups", "Scriptability": "None", @@ -52310,11 +59799,14 @@ } }, "DefaultProperties": { + "AirDensity": { + "Float32": 0.0012 + }, "AllowThirdPartySales": { "Bool": false }, "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AvatarUnificationMode": { "Enum": 0 @@ -52322,6 +59814,9 @@ "ClientAnimatorThrottling": { "Enum": 0 }, + "CollisionGroupData": { + "BinaryString": "AQEABP////8HRGVmYXVsdA==" + }, "DistributedGameTime": { "Float64": 0.0 }, @@ -52331,6 +59826,9 @@ "FallenPartsDestroyHeight": { "Float32": -500.0 }, + "FluidForces": { + "Enum": 0 + }, "GlobalWind": { "Vector3": [ 0.0, @@ -52344,6 +59842,9 @@ "HumanoidOnlySetCollisionsOnStateChange": { "Enum": 0 }, + "IKControlConstraintSupport": { + "Enum": 0 + }, "InterpolationThrottling": { "Enum": 0 }, @@ -52353,9 +59854,48 @@ "MeshPartHeadsAndAccessories": { "Enum": 0 }, + "ModelMeshCFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ModelMeshSize": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "ModelStreamingBehavior": { + "Enum": 0 + }, "ModelStreamingMode": { "Enum": 0 }, + "NeedsPivotMigration": { + "Bool": false + }, "PhysicsSteppingMethod": { "Enum": 0 }, @@ -52371,6 +59911,9 @@ "Scale": { "Float32": 1.0 }, + "SignalBehavior": { + "Enum": 0 + }, "SourceAssetId": { "Int64": -1 }, @@ -52390,10 +59933,39 @@ "Int32": 1024 }, "Tags": { - "BinaryString": "" + "Tags": [] + }, + "TerrainWeldsFixed": { + "Bool": true }, "TouchesUseCollisionGroups": { "Bool": false + }, + "WorldPivotData": { + "OptionalCFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } } } }, @@ -52402,7 +59974,88 @@ "Tags": [], "Superclass": "WorldRoot", "Properties": {}, - "DefaultProperties": {} + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "LevelOfDetail": { + "Enum": 0 + }, + "ModelMeshCFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ModelMeshSize": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "ModelStreamingMode": { + "Enum": 0 + }, + "NeedsPivotMigration": { + "Bool": false + }, + "Scale": { + "Float32": 1.0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "WorldPivotData": { + "OptionalCFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + } + } }, "WorldRoot": { "Name": "WorldRoot", @@ -52569,11 +60222,27 @@ "Serialization": "Serializes" } } + }, + "TemporaryReferenceId": { + "Name": "TemporaryReferenceId", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "AutoSkin": { "Enum": 0 @@ -52707,7 +60376,13 @@ "Int64": -1 }, "Tags": { - "BinaryString": "" + "Tags": [] + }, + "TemporaryCageMeshId": { + "Content": "" + }, + "TemporaryReferenceId": { + "Content": "" } } }, @@ -52764,7 +60439,7 @@ }, "DefaultProperties": { "Attributes": { - "BinaryString": "" + "Attributes": {} }, "CageMeshId": { "Content": "" @@ -52831,12 +60506,22 @@ "Float32": 0.0 }, "Tags": { - "BinaryString": "" + "Tags": [] + }, + "TemporaryCageMeshId": { + "Content": "" } } } }, "Enums": { + "AccessModifierType": { + "name": "AccessModifierType", + "items": { + "Allow": 0, + "Deny": 1 + } + }, "AccessoryType": { "name": "AccessoryType", "items": { @@ -52888,21 +60573,6 @@ "Servo": 2 } }, - "AdPortalStatus": { - "name": "AdPortalStatus", - "items": { - "Active": 2, - "Inactive": 1, - "Invalid": 0 - } - }, - "AdPortalType": { - "name": "AdPortalType", - "items": { - "Forward": 0, - "Return": 1 - } - }, "AdShape": { "name": "AdShape", "items": { @@ -52912,10 +60582,9 @@ "AdTeleportMethod": { "name": "AdTeleportMethod", "items": { - "InGameMenuBackButton": 3, + "InGameMenuBackButton": 2, "PortalForward": 1, - "PortalReturn": 2, - "UIBackButton": 4, + "UIBackButton": 3, "Undefined": 0 } }, @@ -53137,6 +60806,14 @@ "SoundEffect": 2 } }, + "AudioWindowSize": { + "name": "AudioWindowSize", + "items": { + "Large": 2, + "Medium": 1, + "Small": 0 + } + }, "AutoIndentRule": { "name": "AutoIndentRule", "items": { @@ -53199,6 +60876,21 @@ "WalkAnimation": 55 } }, + "AvatarChatServiceFeature": { + "name": "AvatarChatServiceFeature", + "items": { + "None": 0, + "PlaceAudio": 4, + "PlaceVideo": 8, + "UniverseAudio": 1, + "UniverseVideo": 2, + "UserAudio": 32, + "UserAudioEligible": 16, + "UserBanned": 256, + "UserVideo": 128, + "UserVideoEligible": 64 + } + }, "AvatarContextMenuOption": { "name": "AvatarContextMenuOption", "items": { @@ -53215,6 +60907,14 @@ "Bundle": 2 } }, + "AvatarJointUpgrade": { + "name": "AvatarJointUpgrade", + "items": { + "Default": 0, + "Disabled": 2, + "Enabled": 1 + } + }, "AvatarPromptResult": { "name": "AvatarPromptResult", "items": { @@ -53540,6 +61240,15 @@ "Plugin": 0 } }, + "CompileTarget": { + "name": "CompileTarget", + "items": { + "Client": 0, + "CoreScript": 1, + "CoreScriptRaw": 3, + "Studio": 2 + } + }, "CompletionItemKind": { "name": "CompletionItemKind", "items": { @@ -53619,6 +61328,8 @@ "DisconnectClientFailure": 284, "DisconnectClientRequest": 285, "DisconnectCloudEditKick": 270, + "DisconnectCollaboratorPermissionRevoked": 294, + "DisconnectCollaboratorUnderage": 295, "DisconnectConnectionLost": 277, "DisconnectDevMaintenance": 274, "DisconnectDuplicatePlayer": 264, @@ -53634,6 +61345,7 @@ "DisconnectOnRemoteSysStats": 268, "DisconnectOutOfMemoryKeepPlayingLeave": 292, "DisconnectPlayerless": 271, + "DisconnectPrivateServerKickout": 286, "DisconnectProtocolMismatch": 259, "DisconnectRaknetErrors": 279, "DisconnectReceivePacketError": 260, @@ -53766,6 +61478,15 @@ "UpdateAsync": 2 } }, + "DeathStyle": { + "name": "DeathStyle", + "items": { + "ClassicBreakApart": 1, + "Default": 0, + "NonGraphic": 2, + "Scriptable": 3 + } + }, "DebuggerEndReason": { "name": "DebuggerEndReason", "items": { @@ -53942,6 +61663,28 @@ "ScriptRemoved": 2 } }, + "DragDetectorDragStyle": { + "name": "DragDetectorDragStyle", + "items": { + "BestForDevice": 8, + "RotateAxis": 5, + "RotateTrackball": 6, + "Scriptable": 7, + "TranslateLine": 0, + "TranslateLineOrPlane": 3, + "TranslatePlane": 1, + "TranslatePlaneOrLine": 2, + "TranslateViewPlane": 4 + } + }, + "DragDetectorResponseStyle": { + "name": "DragDetectorResponseStyle", + "items": { + "Custom": 2, + "Geometric": 0, + "Physical": 1 + } + }, "DraggerCoordinateSpace": { "name": "DraggerCoordinateSpace", "items": { @@ -54014,15 +61757,6 @@ "NoCraters": 0 } }, - "FacialAnimationFlags": { - "name": "FacialAnimationFlags", - "items": { - "None": 0, - "Place": 1, - "PlaceServer": 3, - "Server": 2 - } - }, "FacialAnimationStreamingState": { "name": "FacialAnimationStreamingState", "items": { @@ -54055,6 +61789,21 @@ "Rejected": 1 } }, + "FinishRecordingOperation": { + "name": "FinishRecordingOperation", + "items": { + "Append": 2, + "Cancel": 0, + "Commit": 1 + } + }, + "FluidForces": { + "name": "FluidForces", + "items": { + "Default": 0, + "Experimental": 1 + } + }, "Font": { "name": "Font", "items": { @@ -54148,6 +61897,13 @@ "Thin": 100 } }, + "ForceLimitMode": { + "name": "ForceLimitMode", + "items": { + "Magnitude": 0, + "PerAxis": 1 + } + }, "FormFactor": { "name": "FormFactor", "items": { @@ -54263,6 +62019,14 @@ "Vulkan": 6 } }, + "GuiState": { + "name": "GuiState", + "items": { + "Hover": 1, + "Idle": 0, + "Press": 2 + } + }, "GuiType": { "name": "GuiType", "items": { @@ -54431,6 +62195,14 @@ "OtherMechanismsAnchored": 1 } }, + "IKControlConstraintSupport": { + "name": "IKControlConstraintSupport", + "items": { + "Default": 0, + "Disabled": 1, + "Enabled": 2 + } + }, "IKControlType": { "name": "IKControlType", "items": { @@ -54858,6 +62630,10 @@ "Asphalt": 1376, "Basalt": 788, "Brick": 848, + "Cardboard": 2304, + "Carpet": 2305, + "CeramicTiles": 2306, + "ClayRoofTiles": 2307, "Cobblestone": 880, "Concrete": 816, "CorrodedMetal": 1040, @@ -54873,6 +62649,7 @@ "Ground": 1360, "Ice": 1536, "LeafyGrass": 1284, + "Leather": 2309, "Limestone": 820, "Marble": 784, "Metal": 1088, @@ -54880,8 +62657,11 @@ "Neon": 288, "Pavement": 836, "Pebble": 864, + "Plaster": 2310, "Plastic": 256, "Rock": 896, + "RoofShingles": 2308, + "Rubber": 2311, "Salt": 1392, "Sand": 1296, "Sandstone": 912, @@ -54974,6 +62754,14 @@ "StreamingMesh": 1 } }, + "ModelStreamingBehavior": { + "name": "ModelStreamingBehavior", + "items": { + "Default": 0, + "Improved": 2, + "Legacy": 1 + } + }, "ModelStreamingMode": { "name": "ModelStreamingMode", "items": { @@ -55099,7 +62887,9 @@ "items": { "Ball": 0, "Block": 1, - "Cylinder": 2 + "CornerWedge": 4, + "Cylinder": 2, + "Wedge": 3 } }, "ParticleEmitterShape": { @@ -55310,6 +63100,17 @@ "PurchaseGranted": 1 } }, + "PromptCreateAssetResult": { + "name": "PromptCreateAssetResult", + "items": { + "NoUserInput": 5, + "PermissionDenied": 2, + "Success": 1, + "Timeout": 3, + "UnknownFailure": 6, + "UploadFailed": 4 + } + }, "PromptPublishAssetResult": { "name": "PromptPublishAssetResult", "items": { @@ -55317,6 +63118,7 @@ "PermissionDenied": 2, "Success": 1, "Timeout": 3, + "UnknownFailure": 6, "UploadFailed": 4 } }, @@ -55449,6 +63251,14 @@ "Standard": 0 } }, + "RestPose": { + "name": "RestPose", + "items": { + "Custom": 2, + "Default": 0, + "RotationsReset": 1 + } + }, "ReturnKeyType": { "name": "ReturnKeyType", "items": { @@ -55515,11 +63325,9 @@ "RigType": { "name": "RigType", "items": { - "Custom": 3, - "None": 4, - "R15": 0, - "Rthro": 1, - "RthroNarrow": 2 + "Custom": 1, + "None": 2, + "R15": 0 } }, "RollOffMode": { @@ -55687,6 +63495,24 @@ "Stop": 1 } }, + "SelectionRenderMode": { + "name": "SelectionRenderMode", + "items": { + "Both": 2, + "BoundingBoxes": 1, + "Outlines": 0 + } + }, + "SelfViewPosition": { + "name": "SelfViewPosition", + "items": { + "BottomLeft": 3, + "BottomRight": 4, + "LastPosition": 0, + "TopLeft": 1, + "TopRight": 2 + } + }, "SensorMode": { "name": "SensorMode", "items": { @@ -55721,6 +63547,8 @@ "name": "Severity", "items": { "Error": 1, + "Hint": 4, + "Information": 3, "Warning": 2 } }, @@ -55837,45 +63665,52 @@ "StudioScriptEditorColorCategories": { "name": "StudioScriptEditorColorCategories", "items": { - "ActiveLine": 25, + "AICOOverlayButtonBackground": 42, + "AICOOverlayButtonBackgroundHover": 43, + "AICOOverlayButtonBackgroundPressed": 44, + "AICOOverlayText": 41, + "ActiveLine": 27, "Background": 17, "Bool": 10, - "Bracket": 29, + "Bracket": 31, "Builtin": 6, "Comment": 4, - "DebuggerCurrentLine": 26, - "DebuggerErrorLine": 27, + "DebuggerCurrentLine": 28, + "DebuggerErrorLine": 29, "Default": 0, - "DocViewCodeBackground": 38, + "DocViewCodeBackground": 40, "Error": 23, "FindSelectionBackground": 20, "Function": 11, "FunctionName": 15, + "Hint": 25, + "IndentationRuler": 45, + "Info": 24, "Keyword": 5, "Local": 12, "LuauKeyword": 14, "MatchingWordBackground": 21, - "MenuBackground": 33, - "MenuBorder": 37, - "MenuPrimaryText": 30, - "MenuScrollbarBackground": 35, - "MenuScrollbarHandle": 36, - "MenuSecondaryText": 31, - "MenuSelectedBackground": 34, - "MenuSelectedText": 32, + "MenuBackground": 35, + "MenuBorder": 39, + "MenuPrimaryText": 32, + "MenuScrollbarBackground": 37, + "MenuScrollbarHandle": 38, + "MenuSecondaryText": 33, + "MenuSelectedBackground": 36, + "MenuSelectedText": 34, "Method": 7, "Nil": 9, "Number": 2, "Operator": 1, "Property": 8, - "Ruler": 28, + "Ruler": 30, "SelectionBackground": 19, "SelectionText": 18, "Self": 13, "String": 3, "TODO": 16, "Warning": 22, - "Whitespace": 24 + "Whitespace": 26 } }, "StudioScriptEditorColorPresets": { @@ -55890,49 +63725,53 @@ "StudioStyleGuideColor": { "name": "StudioStyleGuideColor", "items": { - "AttributeCog": 117, + "AICOOverlayButtonBackground": 129, + "AICOOverlayButtonBackgroundHover": 130, + "AICOOverlayButtonBackgroundPressed": 131, + "AICOOverlayText": 128, + "AttributeCog": 119, "Border": 31, "BrightText": 40, "Button": 17, - "ButtonBorder": 89, - "ButtonText": 90, + "ButtonBorder": 91, + "ButtonText": 92, "CategoryItem": 24, - "ChatIncomingBgColor": 83, - "ChatIncomingTextColor": 84, - "ChatModeratedMessageColor": 87, - "ChatOutgoingBgColor": 85, - "ChatOutgoingTextColor": 86, - "CheckedFieldBackground": 92, - "CheckedFieldBorder": 93, - "CheckedFieldIndicator": 94, + "ChatIncomingBgColor": 85, + "ChatIncomingTextColor": 86, + "ChatModeratedMessageColor": 89, + "ChatOutgoingBgColor": 87, + "ChatOutgoingTextColor": 88, + "CheckedFieldBackground": 94, + "CheckedFieldBorder": 95, + "CheckedFieldIndicator": 96, "ColorPickerFrame": 29, "CurrentMarker": 30, "Dark": 35, - "DebuggerCurrentLine": 65, - "DebuggerErrorLine": 66, - "DialogButton": 98, - "DialogButtonBorder": 100, - "DialogButtonText": 99, - "DialogMainButton": 101, - "DialogMainButtonText": 102, - "DiffFilePathBackground": 81, - "DiffFilePathBorder": 82, - "DiffFilePathText": 67, - "DiffLineNum": 76, - "DiffLineNumAdditionBackground": 79, - "DiffLineNumDeletionBackground": 80, - "DiffLineNumNoChangeBackground": 78, - "DiffLineNumSeparatorBackground": 77, - "DiffTextAddition": 70, - "DiffTextAdditionBackground": 74, - "DiffTextDeletion": 71, - "DiffTextDeletionBackground": 75, - "DiffTextHunkInfo": 68, - "DiffTextNoChange": 69, - "DiffTextNoChangeBackground": 73, - "DiffTextSeparatorBackground": 72, + "DebuggerCurrentLine": 67, + "DebuggerErrorLine": 68, + "DialogButton": 100, + "DialogButtonBorder": 102, + "DialogButtonText": 101, + "DialogMainButton": 103, + "DialogMainButtonText": 104, + "DiffFilePathBackground": 83, + "DiffFilePathBorder": 84, + "DiffFilePathText": 69, + "DiffLineNum": 78, + "DiffLineNumAdditionBackground": 81, + "DiffLineNumDeletionBackground": 82, + "DiffLineNumNoChangeBackground": 80, + "DiffLineNumSeparatorBackground": 79, + "DiffTextAddition": 72, + "DiffTextAdditionBackground": 76, + "DiffTextDeletion": 73, + "DiffTextDeletionBackground": 77, + "DiffTextHunkInfo": 70, + "DiffTextNoChange": 71, + "DiffTextNoChangeBackground": 75, + "DiffTextSeparatorBackground": 74, "DimmedText": 41, - "DocViewCodeBackground": 64, + "DocViewCodeBackground": 66, "DropShadow": 32, "Dropdown": 2, "EmulatorBar": 27, @@ -55946,12 +63785,12 @@ "FilterButtonHover": 10, "GameSettingsTableItem": 25, "GameSettingsTooltip": 26, - "HeaderSection": 95, - "InfoBarWarningBackground": 103, - "InfoBarWarningText": 104, + "HeaderSection": 97, + "InfoBarWarningBackground": 105, + "InfoBarWarningText": 106, "InfoText": 45, "InputFieldBackground": 21, - "InputFieldBorder": 91, + "InputFieldBorder": 93, "Item": 22, "Light": 34, "LinkText": 42, @@ -55959,46 +63798,48 @@ "MainButton": 18, "MainText": 37, "Mid": 36, - "Midlight": 96, + "Midlight": 98, "Notification": 4, "RibbonButton": 19, "RibbonTab": 15, "RibbonTabTopBar": 16, "ScriptBackground": 48, - "ScriptBool": 109, - "ScriptBracket": 116, + "ScriptBool": 111, + "ScriptBracket": 118, "ScriptBuiltInFunction": 59, "ScriptComment": 57, - "ScriptEditorCurrentLine": 105, + "ScriptEditorCurrentLine": 107, "ScriptError": 61, "ScriptFindSelectionBackground": 52, - "ScriptFunction": 110, - "ScriptFunctionName": 114, + "ScriptFunction": 112, + "ScriptFunctionName": 116, + "ScriptHint": 63, + "ScriptInformation": 62, "ScriptKeyword": 58, - "ScriptLocal": 111, - "ScriptLuauKeyword": 113, + "ScriptLocal": 113, + "ScriptLuauKeyword": 115, "ScriptMatchingWordSelectionBackground": 53, - "ScriptMethod": 106, - "ScriptNil": 108, + "ScriptMethod": 108, + "ScriptNil": 110, "ScriptNumber": 55, "ScriptOperator": 54, - "ScriptProperty": 107, - "ScriptRuler": 63, + "ScriptProperty": 109, + "ScriptRuler": 65, "ScriptSelectionBackground": 51, "ScriptSelectionText": 50, - "ScriptSelf": 112, + "ScriptSelf": 114, "ScriptSideWidget": 47, "ScriptString": 56, "ScriptText": 49, - "ScriptTodo": 115, + "ScriptTodo": 117, "ScriptWarning": 60, - "ScriptWhitespace": 62, + "ScriptWhitespace": 64, "ScrollBar": 5, "ScrollBarBackground": 6, "SensitiveText": 46, - "Separator": 88, + "Separator": 90, "Shadow": 33, - "StatusBar": 97, + "StatusBar": 99, "SubText": 38, "Tab": 8, "TabBar": 7, @@ -56172,6 +64013,14 @@ "Unknown": 1 } }, + "TextDirection": { + "name": "TextDirection", + "items": { + "Auto": 0, + "LeftToRight": 1, + "RightToLeft": 2 + } + }, "TextFilterContext": { "name": "TextFilterContext", "items": { @@ -56323,6 +64172,7 @@ "NoService": 1, "NoVideo": 3, "Ok": 0, + "UnsupportedDevice": 10, "VideoError": 4, "VideoNoPermission": 5, "VideoUnsupported": 6 @@ -56449,13 +64299,6 @@ "Touch": 7 } }, - "VRPlayMode": { - "name": "VRPlayMode", - "items": { - "Seated": 0, - "Standing": 1 - } - }, "VRSafetyBubbleMode": { "name": "VRSafetyBubbleMode", "items": { @@ -56530,6 +64373,15 @@ "Small": 1 } }, + "ViewMode": { + "name": "ViewMode", + "items": { + "Decal": 3, + "GeometryComplexity": 1, + "None": 0, + "Transparent": 2 + } + }, "VirtualCursorMode": { "name": "VirtualCursorMode", "items": { @@ -56587,6 +64439,14 @@ "Strong": 3 } }, + "WeldConstraintPreserve": { + "name": "WeldConstraintPreserve", + "items": { + "All": 0, + "None": 1, + "Touching": 2 + } + }, "WrapLayerAutoSkin": { "name": "WrapLayerAutoSkin", "items": { From aa68fe412efae76046822ac159ff89a6abae3ccc Mon Sep 17 00:00:00 2001 From: Micah Date: Mon, 14 Aug 2023 15:41:15 -0700 Subject: [PATCH 1326/1504] Add ambiguous value support for MaterialColors (#770) The last release of rbx_dom had support for `Terrain.MaterialColors`. This allows it to be specified directly instead of only via the fully-qualified syntax. --- CHANGELOG.md | 2 ++ src/resolution.rs | 33 +++++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 466e7de4..5c8f4bbe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ * Added rich Source diffs in patch visualizer ([#748]) * Fix PatchTree performance issues ([#755]) * Don't override the initial enabled state for source diffing ([#760]) +* Added support for `Terrain.MaterialColors` ([#770]) [#761]: https://github.com/rojo-rbx/rojo/pull/761 [#745]: https://github.com/rojo-rbx/rojo/pull/745 @@ -50,6 +51,7 @@ [#748]: https://github.com/rojo-rbx/rojo/pull/748 [#755]: https://github.com/rojo-rbx/rojo/pull/755 [#760]: https://github.com/rojo-rbx/rojo/pull/760 +[#770]: https://github.com/rojo-rbx/rojo/pull/770 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/src/resolution.rs b/src/resolution.rs index c667080c..9a0219ee 100644 --- a/src/resolution.rs +++ b/src/resolution.rs @@ -2,8 +2,8 @@ use std::borrow::Borrow; use anyhow::{bail, format_err}; use rbx_dom_weak::types::{ - Attributes, CFrame, Color3, Content, Enum, Font, Matrix3, Tags, Variant, VariantType, Vector2, - Vector3, + Attributes, CFrame, Color3, Content, Enum, Font, MaterialColors, Matrix3, Tags, Variant, + VariantType, Vector2, Vector3, }; use rbx_reflection::{DataType, PropertyDescriptor}; use serde::{Deserialize, Serialize}; @@ -50,6 +50,7 @@ pub enum AmbiguousValue { Array12([f64; 12]), Attributes(Attributes), Font(Font), + MaterialColors(MaterialColors), } impl AmbiguousValue { @@ -142,6 +143,10 @@ impl AmbiguousValue { (VariantType::Font, AmbiguousValue::Font(value)) => Ok(value.into()), + (VariantType::MaterialColors, AmbiguousValue::MaterialColors(value)) => { + Ok(value.into()) + } + (_, unresolved) => Err(format_err!( "Wrong type of value for property {}.{}. Expected {:?}, got {}", class_name, @@ -180,6 +185,7 @@ impl AmbiguousValue { AmbiguousValue::Array12(_) => "an array of twelve numbers", AmbiguousValue::Attributes(_) => "an object containing attributes", AmbiguousValue::Font(_) => "an object describing a Font", + AmbiguousValue::MaterialColors(_) => "an object describing MaterialColors", } } } @@ -351,4 +357,27 @@ mod test { }) ) } + + #[test] + fn material_colors() { + use rbx_dom_weak::types::{Color3uint8, TerrainMaterials}; + + let mut material_colors = MaterialColors::new(); + material_colors.set_color(TerrainMaterials::Grass, Color3uint8::new(10, 20, 30)); + material_colors.set_color(TerrainMaterials::Asphalt, Color3uint8::new(40, 50, 60)); + material_colors.set_color(TerrainMaterials::LeafyGrass, Color3uint8::new(255, 155, 55)); + + assert_eq!( + resolve( + "Terrain", + "MaterialColors", + r#"{ + "Grass": [10, 20, 30], + "Asphalt": [40, 50, 60], + "LeafyGrass": [255, 155, 55] + }"# + ), + Variant::MaterialColors(material_colors) + ) + } } From 066a0b1668d6d37f02021ebb33a6bf2b1aaea5ff Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 15 Aug 2023 05:41:49 -0700 Subject: [PATCH 1327/1504] Allow `Terrain` to be included in projects without a classname (#771) Services, `StarterPlayerScripts`, and `StarterCharacterScripts` are currently special-cased to allow them to be specified in project files without a classname. This does the same to `Terrain` since it's a singleton in the same style as those. --- CHANGELOG.md | 2 ++ src/snapshot_middleware/project.rs | 5 +++++ 2 files changed, 7 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c8f4bbe..2079b061 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ * Fix PatchTree performance issues ([#755]) * Don't override the initial enabled state for source diffing ([#760]) * Added support for `Terrain.MaterialColors` ([#770]) +* Allow `Terrain` to be specified without a classname ([#771]) [#761]: https://github.com/rojo-rbx/rojo/pull/761 [#745]: https://github.com/rojo-rbx/rojo/pull/745 @@ -52,6 +53,7 @@ [#755]: https://github.com/rojo-rbx/rojo/pull/755 [#760]: https://github.com/rojo-rbx/rojo/pull/760 [#770]: https://github.com/rojo-rbx/rojo/pull/770 +[#771]: https://github.com/rojo-rbx/rojo/pull/771 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 2d54a179..a451abc9 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -301,6 +301,11 @@ fn infer_class_name(name: &str, parent_class: Option<&str>) -> Option Date: Wed, 16 Aug 2023 16:47:04 -0700 Subject: [PATCH 1328/1504] Update rbx_dom_lua to rojo-rbx/rbx-dom@7b03132 (#775) Fixes a problem where the MaterialColors Lua encoder would return nothing --- plugin/rbx_dom_lua/EncodedValue.lua | 1 + plugin/rbx_dom_lua/EncodedValue.spec.lua | 27 ++++++++++-------------- 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/plugin/rbx_dom_lua/EncodedValue.lua b/plugin/rbx_dom_lua/EncodedValue.lua index 16dde489..35417410 100644 --- a/plugin/rbx_dom_lua/EncodedValue.lua +++ b/plugin/rbx_dom_lua/EncodedValue.lua @@ -282,6 +282,7 @@ types = { math.round(math.clamp(color.B, 0, 1) * 255) } end + return pod end, }, diff --git a/plugin/rbx_dom_lua/EncodedValue.spec.lua b/plugin/rbx_dom_lua/EncodedValue.spec.lua index cf0b2201..14522ae8 100644 --- a/plugin/rbx_dom_lua/EncodedValue.spec.lua +++ b/plugin/rbx_dom_lua/EncodedValue.spec.lua @@ -1,6 +1,6 @@ return function() local HttpService = game:GetService("HttpService") - + local EncodedValue = require(script.Parent.EncodedValue) local allValues = require(script.Parent.allValues) @@ -13,16 +13,16 @@ return function() if ty == "table" then local visited = {} - - for key, valueA in pairs(a) do + + for key, valueA in a do visited[key] = true - + if not deepEq(valueA, b[key]) then return false end end - for key, valueB in pairs(b) do + for key, valueB in b do if visited[key] then continue end @@ -44,28 +44,23 @@ return function() end, } - for testName, testEntry in pairs(allValues) do + for testName, testEntry in allValues do it("round trip " .. testName, function() - local ok, decoded = EncodedValue.decode(testEntry.value) - assert(ok, decoded) + local decodeOk, decoded = EncodedValue.decode(testEntry.value) + assert(decodeOk, decoded) if extraAssertions[testName] ~= nil then extraAssertions[testName](decoded) end - local ok, encoded = EncodedValue.encode(decoded, testEntry.ty) - assert(ok, encoded) + local encodeOk, encoded = EncodedValue.encode(decoded, testEntry.ty) + assert(encodeOk, encoded) if not deepEq(encoded, testEntry.value) then local expected = HttpService:JSONEncode(testEntry.value) local actual = HttpService:JSONEncode(encoded) - local message = string.format( - "Round-trip results did not match.\nExpected:\n%s\nActual:\n%s", - expected, actual - ) - - error(message) + error(`Round-trip results did not match.\nExpected:\n{expected}\nActual:\n{actual}`) end end) end From c43726bc753ef8d4563594b122dd2bd872a32095 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sun, 20 Aug 2023 12:37:40 -0700 Subject: [PATCH 1329/1504] Confirmation behaviors (#774) --- CHANGELOG.md | 2 + plugin/src/App/Components/TextInput.lua | 103 ++++++++++++++++++ .../src/App/StatusPages/Settings/Setting.lua | 87 +++++++++------ plugin/src/App/StatusPages/Settings/init.lua | 46 +++++++- plugin/src/App/Theme.lua | 28 +++++ plugin/src/App/init.lua | 27 +++++ plugin/src/PatchSet.lua | 24 +++- plugin/src/Settings.lua | 2 + 8 files changed, 280 insertions(+), 39 deletions(-) create mode 100644 plugin/src/App/Components/TextInput.lua diff --git a/CHANGELOG.md b/CHANGELOG.md index 2079b061..7f26d92e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ * Don't override the initial enabled state for source diffing ([#760]) * Added support for `Terrain.MaterialColors` ([#770]) * Allow `Terrain` to be specified without a classname ([#771]) +* Add Confirmation Behavior setting ([#774]) [#761]: https://github.com/rojo-rbx/rojo/pull/761 [#745]: https://github.com/rojo-rbx/rojo/pull/745 @@ -54,6 +55,7 @@ [#760]: https://github.com/rojo-rbx/rojo/pull/760 [#770]: https://github.com/rojo-rbx/rojo/pull/770 [#771]: https://github.com/rojo-rbx/rojo/pull/771 +[#774]: https://github.com/rojo-rbx/rojo/pull/774 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) diff --git a/plugin/src/App/Components/TextInput.lua b/plugin/src/App/Components/TextInput.lua new file mode 100644 index 00000000..94a76a97 --- /dev/null +++ b/plugin/src/App/Components/TextInput.lua @@ -0,0 +1,103 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) +local Flipper = require(Packages.Flipper) + +local Theme = require(Plugin.App.Theme) +local Assets = require(Plugin.Assets) +local bindingUtil = require(Plugin.App.bindingUtil) + +local SlicedImage = require(script.Parent.SlicedImage) + +local SPRING_PROPS = { + frequency = 5, + dampingRatio = 1, +} + +local e = Roact.createElement + +local TextInput = Roact.Component:extend("TextInput") + +function TextInput:init() + self.motor = Flipper.GroupMotor.new({ + hover = 0, + enabled = self.props.enabled and 1 or 0, + }) + self.binding = bindingUtil.fromMotor(self.motor) +end + +function TextInput:didUpdate(lastProps) + if lastProps.enabled ~= self.props.enabled then + self.motor:setGoal({ + enabled = Flipper.Spring.new(self.props.enabled and 1 or 0), + }) + end +end + +function TextInput:render() + return Theme.with(function(theme) + theme = theme.TextInput + + local bindingHover = bindingUtil.deriveProperty(self.binding, "hover") + local bindingEnabled = bindingUtil.deriveProperty(self.binding, "enabled") + + return e(SlicedImage, { + slice = Assets.Slices.RoundedBorder, + color = bindingUtil.mapLerp(bindingEnabled, theme.Enabled.BorderColor, theme.Disabled.BorderColor), + transparency = self.props.transparency, + + size = self.props.size or UDim2.new(1, 0, 1, 0), + position = self.props.position, + layoutOrder = self.props.layoutOrder, + anchorPoint = self.props.anchorPoint, + }, { + HoverOverlay = e(SlicedImage, { + slice = Assets.Slices.RoundedBackground, + color = theme.ActionFillColor, + transparency = Roact.joinBindings({ + hover = bindingHover:map(function(value) + return 1 - value + end), + transparency = self.props.transparency, + }):map(function(values) + return bindingUtil.blendAlpha({ theme.ActionFillTransparency, values.hover, values.transparency }) + end), + size = UDim2.new(1, 0, 1, 0), + zIndex = -1, + }), + Input = e("TextBox", { + BackgroundTransparency = 1, + Size = UDim2.fromScale(1, 1), + Text = self.props.text, + PlaceholderText = self.props.placeholder, + Font = Enum.Font.GothamMedium, + TextColor3 = bindingUtil.mapLerp(bindingEnabled, theme.Disabled.TextColor, theme.Enabled.TextColor), + PlaceholderColor3 = bindingUtil.mapLerp(bindingEnabled, theme.Disabled.PlaceholderColor, theme.Enabled.PlaceholderColor), + TextSize = 18, + TextEditable = self.props.enabled, + ClearTextOnFocus = self.props.clearTextOnFocus, + + [Roact.Event.MouseEnter] = function() + self.motor:setGoal({ + hover = Flipper.Spring.new(1, SPRING_PROPS), + }) + end, + + [Roact.Event.MouseLeave] = function() + self.motor:setGoal({ + hover = Flipper.Spring.new(0, SPRING_PROPS), + }) + end, + + [Roact.Event.FocusLost] = function(rbx) + self.props.onEntered(rbx.Text) + end, + }), + Children = Roact.createFragment(self.props[Roact.Children]), + }) + end) +end + +return TextInput diff --git a/plugin/src/App/StatusPages/Settings/Setting.lua b/plugin/src/App/StatusPages/Settings/Setting.lua index 79e83e23..2532222d 100644 --- a/plugin/src/App/StatusPages/Settings/Setting.lua +++ b/plugin/src/App/StatusPages/Settings/Setting.lua @@ -32,6 +32,7 @@ local Setting = Roact.Component:extend("Setting") function Setting:init() self.contentSize, self.setContentSize = Roact.createBinding(Vector2.new(0, 0)) self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0)) + self.inputSize, self.setInputSize = Roact.createBinding(Vector2.new(0, 0)) self:setState({ setting = Settings:get(self.props.id), @@ -65,43 +66,56 @@ function Setting:render() self.setContainerSize(object.AbsoluteSize) end, }, { - Input = if self.props.options ~= nil then - e(Dropdown, { - locked = self.props.locked, - options = self.props.options, - active = self.state.setting, - transparency = self.props.transparency, - position = UDim2.new(1, 0, 0.5, 0), - anchorPoint = Vector2.new(1, 0.5), - onClick = function(option) - Settings:set(self.props.id, option) - end, - }) - else - e(Checkbox, { - locked = self.props.locked, - active = self.state.setting, - transparency = self.props.transparency, - position = UDim2.new(1, 0, 0.5, 0), - anchorPoint = Vector2.new(1, 0.5), - onClick = function() - local currentValue = Settings:get(self.props.id) - Settings:set(self.props.id, not currentValue) + RightAligned = Roact.createElement("Frame", { + BackgroundTransparency = 1, + Size = UDim2.new(1, 0, 1, 0), + }, { + Layout = e("UIListLayout", { + VerticalAlignment = Enum.VerticalAlignment.Center, + HorizontalAlignment = Enum.HorizontalAlignment.Right, + FillDirection = Enum.FillDirection.Horizontal, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 2), + [Roact.Change.AbsoluteContentSize] = function(rbx) + self.setInputSize(rbx.AbsoluteContentSize) end, }), - Reset = if self.props.onReset then e(IconButton, { - icon = Assets.Images.Icons.Reset, - iconSize = 24, - color = theme.BackButtonColor, - transparency = self.props.transparency, - visible = self.props.showReset, + Input = + if self.props.input ~= nil then + self.props.input + elseif self.props.options ~= nil then + e(Dropdown, { + locked = self.props.locked, + options = self.props.options, + active = self.state.setting, + transparency = self.props.transparency, + onClick = function(option) + Settings:set(self.props.id, option) + end, + }) + else + e(Checkbox, { + locked = self.props.locked, + active = self.state.setting, + transparency = self.props.transparency, + onClick = function() + local currentValue = Settings:get(self.props.id) + Settings:set(self.props.id, not currentValue) + end, + }), - position = UDim2.new(1, -32 - (self.props.options ~= nil and 120 or 40), 0.5, 0), - anchorPoint = Vector2.new(0, 0.5), + Reset = if self.props.onReset then e(IconButton, { + icon = Assets.Images.Icons.Reset, + iconSize = 24, + color = theme.BackButtonColor, + transparency = self.props.transparency, + visible = self.props.showReset, + layoutOrder = -1, - onClick = self.props.onReset, - }) else nil, + onClick = self.props.onReset, + }) else nil, + }), Text = e("Frame", { Size = UDim2.new(1, 0, 1, 0), @@ -133,12 +147,15 @@ function Setting:render() TextWrapped = true, RichText = true, - Size = self.containerSize:map(function(value) + Size = Roact.joinBindings({ + containerSize = self.containerSize, + inputSize = self.inputSize, + }):map(function(values) local desc = (if self.props.experimental then "[Experimental] " else "") .. self.props.description - local offset = (self.props.onReset and 34 or 0) + (self.props.options ~= nil and 120 or 40) + local offset = values.inputSize.X + 5 local textBounds = getTextBounds( desc, 14, Enum.Font.Gotham, 1.2, - Vector2.new(value.X - offset, math.huge) + Vector2.new(values.containerSize.X - offset, math.huge) ) return UDim2.new(1, -offset, 0, textBounds.Y) end), diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua index 298e39a4..3a08b1e7 100644 --- a/plugin/src/App/StatusPages/Settings/init.lua +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -12,6 +12,7 @@ local Theme = require(Plugin.App.Theme) local IconButton = require(Plugin.App.Components.IconButton) local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) local Tooltip = require(Plugin.App.Components.Tooltip) +local TextInput = require(Plugin.App.Components.TextInput) local Setting = require(script.Setting) local e = Roact.createElement @@ -25,6 +26,7 @@ local function invertTbl(tbl) end local invertedLevels = invertTbl(Log.Level) +local confirmationBehaviors = { "Initial", "Always", "Large Changes", "Unlisted PlaceId" } local function Navbar(props) return Theme.with(function(theme) @@ -104,12 +106,50 @@ function SettingsPage:render() layoutOrder = 2, }), + ConfirmationBehavior = e(Setting, { + id = "confirmationBehavior", + name = "Confirmation Behavior", + description = "When to prompt for confirmation before syncing", + transparency = self.props.transparency, + layoutOrder = 3, + + options = confirmationBehaviors, + }), + + LargeChangesConfirmationThreshold = e(Setting, { + id = "largeChangesConfirmationThreshold", + name = "Confirmation Threshold", + description = "How many modified instances to be considered a large change", + transparency = self.props.transparency, + layoutOrder = 4, + visible = Settings:getBinding("confirmationBehavior"):map(function(value) + return value == "Large Changes" + end), + input = e(TextInput, { + size = UDim2.new(0, 40, 0, 28), + text = Settings:getBinding("largeChangesConfirmationThreshold"):map(function(value) + return tostring(value) + end), + transparency = self.props.transparency, + enabled = true, + onEntered = function(text) + local number = tonumber(string.match(text, "%d+")) + if number then + Settings:set("largeChangesConfirmationThreshold", math.clamp(number, 1, 999)) + else + -- Force text back to last valid value + Settings:set("largeChangesConfirmationThreshold", Settings:get("largeChangesConfirmationThreshold")) + end + end, + }), + }), + PlaySounds = e(Setting, { id = "playSounds", name = "Play Sounds", description = "Toggle sound effects", transparency = self.props.transparency, - layoutOrder = 3, + layoutOrder = 5, }), OpenScriptsExternally = e(Setting, { @@ -119,7 +159,7 @@ function SettingsPage:render() locked = self.props.syncActive, experimental = true, transparency = self.props.transparency, - layoutOrder = 4, + layoutOrder = 6, }), TwoWaySync = e(Setting, { @@ -129,7 +169,7 @@ function SettingsPage:render() locked = self.props.syncActive, experimental = true, transparency = self.props.transparency, - layoutOrder = 5, + layoutOrder = 7, }), LogLevel = e(Setting, { diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index 2bb355d9..00aab81f 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -74,6 +74,20 @@ local lightTheme = strict("LightTheme", { IconColor = Color3.fromHex("EEEEEE"), }, }, + TextInput = { + Enabled = { + TextColor = Color3.fromHex("000000"), + PlaceholderColor = Color3.fromHex("8C8C8C"), + BorderColor = Color3.fromHex("ACACAC"), + }, + Disabled = { + TextColor = Color3.fromHex("393939"), + PlaceholderColor = Color3.fromHex("8C8C8C"), + BorderColor = Color3.fromHex("AFAFAF"), + }, + ActionFillColor = Color3.fromHex("000000"), + ActionFillTransparency = 0.9, + }, AddressEntry = { TextColor = Color3.fromHex("000000"), PlaceholderColor = Color3.fromHex("8C8C8C") @@ -170,6 +184,20 @@ local darkTheme = strict("DarkTheme", { IconColor = Color3.fromHex("484848"), }, }, + TextInput = { + Enabled = { + TextColor = Color3.fromHex("FFFFFF"), + PlaceholderColor = Color3.fromHex("8B8B8B"), + BorderColor = Color3.fromHex("535353"), + }, + Disabled = { + TextColor = Color3.fromHex("484848"), + PlaceholderColor = Color3.fromHex("8B8B8B"), + BorderColor = Color3.fromHex("5A5A5A"), + }, + ActionFillColor = Color3.fromHex("FFFFFF"), + ActionFillTransparency = 0.9, + }, AddressEntry = { TextColor = Color3.fromHex("FFFFFF"), PlaceholderColor = Color3.fromHex("8B8B8B") diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 1dc88c1e..786b559e 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -57,6 +57,7 @@ function App:init() self.confirmationBindable = Instance.new("BindableEvent") self.confirmationEvent = self.confirmationBindable.Event + self.knownProjects = {} self.notifId = 0 self.waypointConnection = ChangeHistoryService.OnUndo:Connect(function(action: string) @@ -416,6 +417,8 @@ function App:startSession() }) self:addNotification("Connecting to session...") elseif status == ServeSession.Status.Connected then + self.knownProjects[details] = true + local address = ("%s:%s"):format(host, port) self:setState({ appStatus = AppStatus.Connected, @@ -462,6 +465,30 @@ function App:startSession() return "Accept" end + local confirmationBehavior = Settings:get("confirmationBehavior") + if confirmationBehavior == "Initial" then + -- Only confirm if we haven't synced this project yet this session + if self.knownProjects[serverInfo.projectName] then + Log.trace("Accepting patch without confirmation because project has already been connected and behavior is set to Initial") + return "Accept" + end + elseif confirmationBehavior == "Large Changes" then + -- Only confirm if the patch impacts many instances + if PatchSet.countInstances(patch) < Settings:get("largeChangesConfirmationThreshold") then + Log.trace("Accepting patch without confirmation because patch is small and behavior is set to Large Changes") + return "Accept" + end + elseif confirmationBehavior == "Unlisted PlaceId" then + -- Only confirm if the current placeId is not in the servePlaceIds allowlist + if serverInfo.expectedPlaceIds then + local isListed = table.find(serverInfo.expectedPlaceIds, game.PlaceId) ~= nil + if isListed then + Log.trace("Accepting patch without confirmation because placeId is listed and behavior is set to Unlisted PlaceId") + return "Accept" + end + end + end + -- The datamodel name gets overwritten by Studio, making confirmation of it intrusive -- and unnecessary. This special case allows it to be accepted without confirmation. if diff --git a/plugin/src/PatchSet.lua b/plugin/src/PatchSet.lua index a9bebd80..a7829de0 100644 --- a/plugin/src/PatchSet.lua +++ b/plugin/src/PatchSet.lua @@ -116,7 +116,7 @@ function PatchSet.containsId(patchSet, instanceMap, id) end --[[ - Tells whether the given PatchSet contains changes to the given instance. + Tells whether the given PatchSet contains changes to the given instance. If the given InstanceMap does not contain the instance, this function always returns false. ]] function PatchSet.containsInstance(patchSet, instanceMap, instance) @@ -235,6 +235,28 @@ function PatchSet.countChanges(patch) return count end +--[[ + Count the number of instances affected by the given PatchSet. +]] +function PatchSet.countInstances(patch) + local count = 0 + + -- Added instances + for _ in patch.added do + count += 1 + end + -- Removed instances + for _ in patch.removed do + count += 1 + end + -- Updated instances + for _ in patch.updated do + count += 1 + end + + return count +end + --[[ Merge multiple PatchSet objects into the given PatchSet. ]] diff --git a/plugin/src/Settings.lua b/plugin/src/Settings.lua index f6368a4d..194dd4c7 100644 --- a/plugin/src/Settings.lua +++ b/plugin/src/Settings.lua @@ -14,6 +14,8 @@ local defaultSettings = { twoWaySync = false, showNotifications = true, syncReminder = true, + confirmationBehavior = "Initial", + largeChangesConfirmationThreshold = 5, playSounds = true, typecheckingEnabled = false, logLevel = "Info", From e11ad476fcf1eaf45236b92b1c7854f9827a4291 Mon Sep 17 00:00:00 2001 From: Micah <48431591+nezuo@users.noreply.github.com> Date: Mon, 11 Sep 2023 15:32:43 -0500 Subject: [PATCH 1330/1504] Use `conflicts_with` for build flags (#779) --- src/cli/build.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/src/cli/build.rs b/src/cli/build.rs index 8f705d37..0593cc05 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -30,13 +30,13 @@ pub struct BuildCommand { /// Where to output the result. /// /// Should end in .rbxm, .rbxl, .rbxmx, or .rbxlx. - #[clap(long, short)] + #[clap(long, short, conflicts_with = "plugin")] pub output: Option, /// Alternative to the output flag that outputs the result in the local plugins folder. /// /// Should end in .rbxm or .rbxl. - #[clap(long, short)] + #[clap(long, short, conflicts_with = "output")] pub plugin: Option, /// Whether to automatically rebuild when any input files change. @@ -47,14 +47,6 @@ pub struct BuildCommand { impl BuildCommand { pub fn run(self) -> anyhow::Result<()> { let (output_path, output_kind) = match (self.output, self.plugin) { - (Some(_), Some(_)) => { - BuildCommand::command() - .error( - clap::ErrorKind::ArgumentConflict, - "the argument '--output ' cannot be used with '--plugin '", - ) - .exit(); - } (None, None) => { BuildCommand::command() .error( @@ -80,6 +72,7 @@ impl BuildCommand { (studio.plugins_path().join(&plugin), output_kind) } + _ => unreachable!(), }; let project_path = resolve_path(&self.project); From 840e9bedb2b10e1f3213243a60fd3bf0635eba08 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Mon, 18 Sep 2023 17:44:14 -0400 Subject: [PATCH 1331/1504] Use GUIDs for ephemeral PluginWidgets (#784) Because Roact will destroy and recreate a plugin widget if it unmounts and remounts, Studio will complain about making a new widget with the same ID as the old one. The simplest solution is to just use GUIDs so we never have to worry about this again. The ID is used internally for storing the widget's dock state and other internal details, so we don't want *all* our widgets to use GUIDs, only the ephemeral popup ones. --- plugin/src/App/Components/Studio/StudioPluginGui.lua | 4 +++- plugin/src/App/StatusPages/Confirming.lua | 2 ++ plugin/src/App/StatusPages/Connected.lua | 1 + plugin/src/App/init.lua | 1 + 4 files changed, 7 insertions(+), 1 deletion(-) diff --git a/plugin/src/App/Components/Studio/StudioPluginGui.lua b/plugin/src/App/Components/Studio/StudioPluginGui.lua index 6b9910a9..236c9300 100644 --- a/plugin/src/App/Components/Studio/StudioPluginGui.lua +++ b/plugin/src/App/Components/Studio/StudioPluginGui.lua @@ -1,3 +1,5 @@ +local HttpService = game:GetService("HttpService") + local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin local Packages = Rojo.Packages @@ -36,7 +38,7 @@ function StudioPluginGui:init() minimumSize.Y ) - local pluginGui = self.props.plugin:CreateDockWidgetPluginGui(self.props.id, dockWidgetPluginGuiInfo) + local pluginGui = self.props.plugin:CreateDockWidgetPluginGui(if self.props.isEphemeral then HttpService:GenerateGUID(false) else self.props.id, dockWidgetPluginGuiInfo) pluginGui.Name = self.props.id pluginGui.Title = self.props.title diff --git a/plugin/src/App/StatusPages/Confirming.lua b/plugin/src/App/StatusPages/Confirming.lua index 74c814a1..098c2dbd 100644 --- a/plugin/src/App/StatusPages/Confirming.lua +++ b/plugin/src/App/StatusPages/Confirming.lua @@ -140,6 +140,7 @@ function ConfirmingPage:render() id = "Rojo_ConfirmingSourceDiff", title = "Source diff", active = self.state.showingSourceDiff, + isEphemeral = true, initDockState = Enum.InitialDockState.Float, overridePreviousState = true, @@ -182,6 +183,7 @@ function ConfirmingPage:render() self.props.confirmData.serverInfo.projectName or "UNKNOWN" ), active = true, + isEphemeral = true, initDockState = Enum.InitialDockState.Float, overridePreviousState = false, diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index 27f4e7ca..b385b1c4 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -398,6 +398,7 @@ function ConnectedPage:render() id = "Rojo_ConnectedSourceDiff", title = "Source diff", active = self.state.showingSourceDiff, + isEphemeral = true, initDockState = Enum.InitialDockState.Float, overridePreviousState = false, diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 786b559e..647c62e7 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -579,6 +579,7 @@ function App:render() id = pluginName, title = pluginName, active = self.state.guiEnabled, + isEphemeral = false, initDockState = Enum.InitialDockState.Right, overridePreviousState = false, From 0f8e1625d572a5fe0f7b5c08653ff92cc837d346 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Mon, 18 Sep 2023 18:39:46 -0400 Subject: [PATCH 1332/1504] Stylua formatting (#785) Uses Stylua to format all existing Lua files, and adds a CI check in `lint` to pin this improvement. Excludes formatting dependencies, of course. --- .github/workflows/ci.yml | 5 +- aftman.toml | 3 +- plugin/src/ApiContext.lua | 104 +++++----- plugin/src/App/Components/Checkbox.lua | 21 +- plugin/src/App/Components/CodeLabel.lua | 2 +- plugin/src/App/Components/Dropdown.lua | 91 ++++----- plugin/src/App/Components/IconButton.lua | 8 +- .../PatchVisualizer/DisplayValue.lua | 5 +- .../App/Components/PatchVisualizer/init.lua | 9 +- .../Components/Studio/StudioPluginAction.lua | 17 +- .../App/Components/Studio/StudioPluginGui.lua | 5 +- .../Components/Studio/StudioToggleButton.lua | 17 +- .../App/Components/Studio/StudioToolbar.lua | 9 +- plugin/src/App/Components/TextButton.lua | 12 +- plugin/src/App/Components/TextInput.lua | 80 ++++---- plugin/src/App/Components/Tooltip.lua | 40 ++-- plugin/src/App/Components/TouchRipple.lua | 20 +- plugin/src/App/Notifications.lua | 69 ++++--- plugin/src/App/Page.lua | 21 +- plugin/src/App/StatusPages/Confirming.lua | 8 +- plugin/src/App/StatusPages/Connected.lua | 29 ++- plugin/src/App/StatusPages/Error.lua | 13 +- plugin/src/App/StatusPages/NotConnected.lua | 6 +- .../src/App/StatusPages/Settings/Setting.lua | 77 ++++---- plugin/src/App/StatusPages/Settings/init.lua | 9 +- plugin/src/App/Theme.lua | 6 +- plugin/src/App/init.lua | 15 +- plugin/src/Assets.lua | 2 +- plugin/src/Config.lua | 2 +- plugin/src/Dictionary.lua | 2 +- plugin/src/InstanceMap.lua | 2 +- plugin/src/PatchSet.lua | 27 ++- plugin/src/PatchTree.lua | 4 +- plugin/src/Reconciler/applyPatch.spec.lua | 6 +- plugin/src/Reconciler/decodeValue.lua | 9 +- plugin/src/Reconciler/diff.lua | 19 +- plugin/src/Reconciler/diff.spec.lua | 2 +- plugin/src/Reconciler/getProperty.lua | 43 +++-- plugin/src/Reconciler/hydrate.lua | 2 +- plugin/src/Reconciler/hydrate.spec.lua | 4 +- plugin/src/Reconciler/reify.spec.lua | 12 +- plugin/src/Reconciler/setProperty.lua | 25 +-- plugin/src/ServeSession.lua | 181 +++++++++--------- plugin/src/Types.lua | 6 +- plugin/src/Version.lua | 2 +- plugin/src/Version.spec.lua | 26 +-- plugin/src/createSignal.lua | 2 +- plugin/src/ignorePlaceIds.lua | 38 ++-- plugin/src/init.server.lua | 2 +- plugin/src/invariant.lua | 9 +- plugin/src/soundPlayer.lua | 14 +- plugin/src/strict.lua | 2 +- 52 files changed, 595 insertions(+), 549 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b0e9fefe..04da7dcd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -42,7 +42,7 @@ jobs: run: cargo test --locked --verbose lint: - name: Rustfmt and Clippy + name: Rustfmt, Clippy, & Stylua runs-on: ubuntu-latest steps: @@ -62,6 +62,9 @@ jobs: with: version: 'v0.2.7' + - name: Stylua + run: stylua --check plugin/src + - name: Rustfmt run: cargo fmt -- --check diff --git a/aftman.toml b/aftman.toml index f6e5cfdd..86ad20fb 100644 --- a/aftman.toml +++ b/aftman.toml @@ -1,4 +1,5 @@ [tools] rojo = "rojo-rbx/rojo@7.3.0" -selene = "Kampfkarren/selene@0.20.0" +selene = "Kampfkarren/selene@0.25.0" +stylua = "JohnnyMorganz/stylua@0.18.2" run-in-roblox = "rojo-rbx/run-in-roblox@0.3.0" diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 9a683dd5..01b7ec45 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -24,15 +24,17 @@ end local function rejectWrongProtocolVersion(infoResponseBody) if infoResponseBody.protocolVersion ~= Config.protocolVersion then local message = ( - "Found a Rojo dev server, but it's using a different protocol version, and is incompatible." .. - "\nMake sure you have matching versions of both the Rojo plugin and server!" .. - "\n\nYour client is version %s, with protocol version %s. It expects server version %s." .. - "\nYour server is version %s, with protocol version %s." .. - "\n\nGo to https://github.com/rojo-rbx/rojo for more details." + "Found a Rojo dev server, but it's using a different protocol version, and is incompatible." + .. "\nMake sure you have matching versions of both the Rojo plugin and server!" + .. "\n\nYour client is version %s, with protocol version %s. It expects server version %s." + .. "\nYour server is version %s, with protocol version %s." + .. "\n\nGo to https://github.com/rojo-rbx/rojo for more details." ):format( - Version.display(Config.version), Config.protocolVersion, + Version.display(Config.version), + Config.protocolVersion, Config.expectedServerVersionString, - infoResponseBody.serverVersion, infoResponseBody.protocolVersion + infoResponseBody.serverVersion, + infoResponseBody.protocolVersion ) return Promise.reject(message) @@ -59,14 +61,11 @@ local function rejectWrongPlaceId(infoResponseBody) end local message = ( - "Found a Rojo server, but its project is set to only be used with a specific list of places." .. - "\nYour place ID is %s, but needs to be one of these:" .. - "\n%s" .. - "\n\nTo change this list, edit 'servePlaceIds' in your .project.json file." - ):format( - tostring(game.PlaceId), - table.concat(idList, "\n") - ) + "Found a Rojo server, but its project is set to only be used with a specific list of places." + .. "\nYour place ID is %s, but needs to be one of these:" + .. "\n%s" + .. "\n\nTo change this list, edit 'servePlaceIds' in your .project.json file." + ):format(tostring(game.PlaceId), table.concat(idList, "\n")) return Promise.reject(message) end @@ -141,18 +140,15 @@ end function ApiContext:read(ids) local url = ("%s/api/read/%s"):format(self.__baseUrl, table.concat(ids, ",")) - return Http.get(url) - :andThen(rejectFailedRequests) - :andThen(Http.Response.json) - :andThen(function(body) - if body.sessionId ~= self.__sessionId then - return Promise.reject("Server changed ID") - end + return Http.get(url):andThen(rejectFailedRequests):andThen(Http.Response.json):andThen(function(body) + if body.sessionId ~= self.__sessionId then + return Promise.reject("Server changed ID") + end - assert(validateApiRead(body)) + assert(validateApiRead(body)) - return body - end) + return body + end) end function ApiContext:write(patch) @@ -189,28 +185,24 @@ function ApiContext:write(patch) body = Http.jsonEncode(body) - return Http.post(url, body) - :andThen(rejectFailedRequests) - :andThen(Http.Response.json) - :andThen(function(body) - Log.info("Write response: {:?}", body) + return Http.post(url, body):andThen(rejectFailedRequests):andThen(Http.Response.json):andThen(function(body) + Log.info("Write response: {:?}", body) - return body - end) + return body + end) end function ApiContext:retrieveMessages() local url = ("%s/api/subscribe/%s"):format(self.__baseUrl, self.__messageCursor) local function sendRequest() - local request = Http.get(url) - :catch(function(err) - if err.type == Http.Error.Kind.Timeout and self.__connected then - return sendRequest() - end + local request = Http.get(url):catch(function(err) + if err.type == Http.Error.Kind.Timeout and self.__connected then + return sendRequest() + end - return Promise.reject(err) - end) + return Promise.reject(err) + end) Log.trace("Tracking request {}", request) self.__activeRequests[request] = true @@ -222,35 +214,29 @@ function ApiContext:retrieveMessages() end) end - return sendRequest() - :andThen(rejectFailedRequests) - :andThen(Http.Response.json) - :andThen(function(body) - if body.sessionId ~= self.__sessionId then - return Promise.reject("Server changed ID") - end + return sendRequest():andThen(rejectFailedRequests):andThen(Http.Response.json):andThen(function(body) + if body.sessionId ~= self.__sessionId then + return Promise.reject("Server changed ID") + end - assert(validateApiSubscribe(body)) + assert(validateApiSubscribe(body)) - self:setMessageCursor(body.messageCursor) + self:setMessageCursor(body.messageCursor) - return body.messages - end) + return body.messages + end) end function ApiContext:open(id) local url = ("%s/api/open/%s"):format(self.__baseUrl, id) - return Http.post(url, "") - :andThen(rejectFailedRequests) - :andThen(Http.Response.json) - :andThen(function(body) - if body.sessionId ~= self.__sessionId then - return Promise.reject("Server changed ID") - end + return Http.post(url, ""):andThen(rejectFailedRequests):andThen(Http.Response.json):andThen(function(body) + if body.sessionId ~= self.__sessionId then + return Promise.reject("Server changed ID") + end - return nil - end) + return nil + end) end return ApiContext diff --git a/plugin/src/App/Components/Checkbox.lua b/plugin/src/App/Components/Checkbox.lua index aa351b1f..0d37fd86 100644 --- a/plugin/src/App/Components/Checkbox.lua +++ b/plugin/src/App/Components/Checkbox.lua @@ -23,12 +23,10 @@ end function Checkbox:didUpdate(lastProps) if lastProps.active ~= self.props.active then - self.motor:setGoal( - Flipper.Spring.new(self.props.active and 1 or 0, { - frequency = 6, - dampingRatio = 1.1, - }) - ) + self.motor:setGoal(Flipper.Spring.new(self.props.active and 1 or 0, { + frequency = 6, + dampingRatio = 1.1, + })) end end @@ -52,13 +50,14 @@ function Checkbox:render() BackgroundTransparency = 1, [Roact.Event.Activated] = function() - if self.props.locked then return end + if self.props.locked then + return + end self.props.onClick() end, }, { StateTip = e(Tooltip.Trigger, { - text = - (if self.props.locked then "[LOCKED] " else "") + text = (if self.props.locked then "[LOCKED] " else "") .. (if self.props.active then "Enabled" else "Disabled"), }), @@ -89,7 +88,9 @@ function Checkbox:render() size = UDim2.new(1, 0, 1, 0), }, { Icon = e("ImageLabel", { - Image = if self.props.locked then Assets.Images.Checkbox.Locked else Assets.Images.Checkbox.Inactive, + Image = if self.props.locked + then Assets.Images.Checkbox.Locked + else Assets.Images.Checkbox.Inactive, ImageColor3 = theme.Inactive.IconColor, ImageTransparency = self.props.transparency, diff --git a/plugin/src/App/Components/CodeLabel.lua b/plugin/src/App/Components/CodeLabel.lua index 192bcf3a..0cdba8e9 100644 --- a/plugin/src/App/Components/CodeLabel.lua +++ b/plugin/src/App/Components/CodeLabel.lua @@ -22,7 +22,7 @@ function CodeLabel:didMount() end function CodeLabel:didUpdate() - self:updateHighlights() + self:updateHighlights() end function CodeLabel:updateHighlights() diff --git a/plugin/src/App/Components/Dropdown.lua b/plugin/src/App/Components/Dropdown.lua index 21a60908..4b761636 100644 --- a/plugin/src/App/Components/Dropdown.lua +++ b/plugin/src/App/Components/Dropdown.lua @@ -36,12 +36,10 @@ function Dropdown:didUpdate(prevProps) }) end - self.openMotor:setGoal( - Flipper.Spring.new(self.state.open and 1 or 0, { - frequency = 6, - dampingRatio = 1.1, - }) - ) + self.openMotor:setGoal(Flipper.Spring.new(self.state.open and 1 or 0, { + frequency = 6, + dampingRatio = 1.1, + })) end function Dropdown:render() @@ -52,10 +50,7 @@ function Dropdown:render() local width = -1 for i, option in self.props.options do local text = tostring(option or "") - local textSize = TextService:GetTextSize( - text, 15, Enum.Font.GothamMedium, - Vector2.new(math.huge, 20) - ) + local textSize = TextService:GetTextSize(text, 15, Enum.Font.GothamMedium, Vector2.new(math.huge, 20)) if textSize.X > width then width = textSize.X end @@ -74,7 +69,9 @@ function Dropdown:render() Font = Enum.Font.GothamMedium, [Roact.Event.Activated] = function() - if self.props.locked then return end + if self.props.locked then + return + end self:setState({ open = false, }) @@ -88,7 +85,7 @@ function Dropdown:render() end return e("ImageButton", { - Size = UDim2.new(0, width+50, 0, 28), + Size = UDim2.new(0, width + 50, 0, 28), Position = self.props.position, AnchorPoint = self.props.anchorPoint, LayoutOrder = self.props.layoutOrder, @@ -96,7 +93,9 @@ function Dropdown:render() BackgroundTransparency = 1, [Roact.Event.Activated] = function() - if self.props.locked then return end + if self.props.locked then + return + end self:setState({ open = not self.state.open, }) @@ -136,40 +135,42 @@ function Dropdown:render() TextTransparency = self.props.transparency, }), }), - Options = if self.state.open then e(SlicedImage, { - slice = Assets.Slices.RoundedBackground, - color = theme.BackgroundColor, - position = UDim2.new(1, 0, 1, 3), - size = self.openBinding:map(function(a) - return UDim2.new(1, 0, a*math.min(3, #self.props.options), 0) - end), - anchorPoint = Vector2.new(1, 0), - }, { - Border = e(SlicedImage, { - slice = Assets.Slices.RoundedBorder, - color = theme.BorderColor, - transparency = self.props.transparency, - size = UDim2.new(1, 0, 1, 0), - }), - ScrollingFrame = e(ScrollingFrame, { - size = UDim2.new(1, -4, 1, -4), - position = UDim2.new(0, 2, 0, 2), - transparency = self.props.transparency, - contentSize = self.contentSize, + Options = if self.state.open + then e(SlicedImage, { + slice = Assets.Slices.RoundedBackground, + color = theme.BackgroundColor, + position = UDim2.new(1, 0, 1, 3), + size = self.openBinding:map(function(a) + return UDim2.new(1, 0, a * math.min(3, #self.props.options), 0) + end), + anchorPoint = Vector2.new(1, 0), }, { - Layout = e("UIListLayout", { - VerticalAlignment = Enum.VerticalAlignment.Top, - FillDirection = Enum.FillDirection.Vertical, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 0), - - [Roact.Change.AbsoluteContentSize] = function(object) - self.setContentSize(object.AbsoluteContentSize) - end, + Border = e(SlicedImage, { + slice = Assets.Slices.RoundedBorder, + color = theme.BorderColor, + transparency = self.props.transparency, + size = UDim2.new(1, 0, 1, 0), }), - Roact.createFragment(optionButtons), - }), - }) else nil, + ScrollingFrame = e(ScrollingFrame, { + size = UDim2.new(1, -4, 1, -4), + position = UDim2.new(0, 2, 0, 2), + transparency = self.props.transparency, + contentSize = self.contentSize, + }, { + Layout = e("UIListLayout", { + VerticalAlignment = Enum.VerticalAlignment.Top, + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 0), + + [Roact.Change.AbsoluteContentSize] = function(object) + self.setContentSize(object.AbsoluteContentSize) + end, + }), + Roact.createFragment(optionButtons), + }), + }) + else nil, }) end) end diff --git a/plugin/src/App/Components/IconButton.lua b/plugin/src/App/Components/IconButton.lua index 130f76e4..dc451b0d 100644 --- a/plugin/src/App/Components/IconButton.lua +++ b/plugin/src/App/Components/IconButton.lua @@ -38,15 +38,11 @@ function IconButton:render() [Roact.Event.Activated] = self.props.onClick, [Roact.Event.MouseEnter] = function() - self.motor:setGoal( - Flipper.Spring.new(1, HOVER_SPRING_PROPS) - ) + self.motor:setGoal(Flipper.Spring.new(1, HOVER_SPRING_PROPS)) end, [Roact.Event.MouseLeave] = function() - self.motor:setGoal( - Flipper.Spring.new(0, HOVER_SPRING_PROPS) - ) + self.motor:setGoal(Flipper.Spring.new(0, HOVER_SPRING_PROPS)) end, }, { Icon = e("ImageLabel", { diff --git a/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua b/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua index 3cf1a11a..439c95d9 100644 --- a/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua +++ b/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua @@ -42,7 +42,6 @@ local function DisplayValue(props) Position = UDim2.new(0, 25, 0, 0), }), }) - elseif t == "table" then -- Showing a memory address for tables is useless, so we want to show the best we can local textRepresentation = nil @@ -62,10 +61,10 @@ local function DisplayValue(props) -- Wrap strings in quotes if type(k) == "string" then - k = "\"" .. k .. "\"" + k = '"' .. k .. '"' end if type(v) == "string" then - v = "\"" .. v .. "\"" + v = '"' .. v .. '"' end out[i] = string.format("[%s] = %s", tostring(k), tostring(v)) diff --git a/plugin/src/App/Components/PatchVisualizer/init.lua b/plugin/src/App/Components/PatchVisualizer/init.lua index f95f96b6..aad2e63d 100644 --- a/plugin/src/App/Components/PatchVisualizer/init.lua +++ b/plugin/src/App/Components/PatchVisualizer/init.lua @@ -43,9 +43,14 @@ end function PatchVisualizer:render() local patchTree = self.props.patchTree if patchTree == nil and self.props.patch ~= nil then - patchTree = PatchTree.build(self.props.patch, self.props.instanceMap, self.props.changeListHeaders or { "Property", "Current", "Incoming" }) + patchTree = PatchTree.build( + self.props.patch, + self.props.instanceMap, + self.props.changeListHeaders or { "Property", "Current", "Incoming" } + ) if self.props.unappliedPatch then - patchTree = PatchTree.updateMetadata(patchTree, self.props.patch, self.props.instanceMap, self.props.unappliedPatch) + patchTree = + PatchTree.updateMetadata(patchTree, self.props.patch, self.props.instanceMap, self.props.unappliedPatch) end end diff --git a/plugin/src/App/Components/Studio/StudioPluginAction.lua b/plugin/src/App/Components/Studio/StudioPluginAction.lua index 3738d779..95581829 100644 --- a/plugin/src/App/Components/Studio/StudioPluginAction.lua +++ b/plugin/src/App/Components/Studio/StudioPluginAction.lua @@ -10,11 +10,15 @@ local StudioPluginContext = require(script.Parent.StudioPluginContext) local e = Roact.createElement -local StudioPluginAction = Roact.Component:extend("StudioPluginAction") +local StudioPluginAction = Roact.Component:extend("StudioPluginAction") function StudioPluginAction:init() self.pluginAction = self.props.plugin:CreatePluginAction( - self.props.name, self.props.title, self.props.description, self.props.icon, self.props.bindable + self.props.name, + self.props.title, + self.props.description, + self.props.icon, + self.props.bindable ) self.pluginAction.Triggered:Connect(self.props.onTriggered) @@ -31,9 +35,12 @@ end local function StudioPluginActionWrapper(props) return e(StudioPluginContext.Consumer, { render = function(plugin) - return e(StudioPluginAction, Dictionary.merge(props, { - plugin = plugin, - })) + return e( + StudioPluginAction, + Dictionary.merge(props, { + plugin = plugin, + }) + ) end, }) end diff --git a/plugin/src/App/Components/Studio/StudioPluginGui.lua b/plugin/src/App/Components/Studio/StudioPluginGui.lua index 236c9300..7c043be3 100644 --- a/plugin/src/App/Components/Studio/StudioPluginGui.lua +++ b/plugin/src/App/Components/Studio/StudioPluginGui.lua @@ -38,7 +38,10 @@ function StudioPluginGui:init() minimumSize.Y ) - local pluginGui = self.props.plugin:CreateDockWidgetPluginGui(if self.props.isEphemeral then HttpService:GenerateGUID(false) else self.props.id, dockWidgetPluginGuiInfo) + local pluginGui = self.props.plugin:CreateDockWidgetPluginGui( + if self.props.isEphemeral then HttpService:GenerateGUID(false) else self.props.id, + dockWidgetPluginGuiInfo + ) pluginGui.Name = self.props.id pluginGui.Title = self.props.title diff --git a/plugin/src/App/Components/Studio/StudioToggleButton.lua b/plugin/src/App/Components/Studio/StudioToggleButton.lua index 8c7ed59e..724801c1 100644 --- a/plugin/src/App/Components/Studio/StudioToggleButton.lua +++ b/plugin/src/App/Components/Studio/StudioToggleButton.lua @@ -18,12 +18,8 @@ StudioToggleButton.defaultProps = { } function StudioToggleButton:init() - local button = self.props.toolbar:CreateButton( - self.props.name, - self.props.tooltip, - self.props.icon, - self.props.text - ) + local button = + self.props.toolbar:CreateButton(self.props.name, self.props.tooltip, self.props.icon, self.props.text) button.Click:Connect(function() if self.props.onClick then @@ -61,9 +57,12 @@ end local function StudioToggleButtonWrapper(props) return e(StudioToolbarContext.Consumer, { render = function(toolbar) - return e(StudioToggleButton, Dictionary.merge(props, { - toolbar = toolbar, - })) + return e( + StudioToggleButton, + Dictionary.merge(props, { + toolbar = toolbar, + }) + ) end, }) end diff --git a/plugin/src/App/Components/Studio/StudioToolbar.lua b/plugin/src/App/Components/Studio/StudioToolbar.lua index 34fd7aa0..11b7214e 100644 --- a/plugin/src/App/Components/Studio/StudioToolbar.lua +++ b/plugin/src/App/Components/Studio/StudioToolbar.lua @@ -36,9 +36,12 @@ end local function StudioToolbarWrapper(props) return e(StudioPluginContext.Consumer, { render = function(plugin) - return e(StudioToolbar, Dictionary.merge(props, { - plugin = plugin, - })) + return e( + StudioToolbar, + Dictionary.merge(props, { + plugin = plugin, + }) + ) end, }) end diff --git a/plugin/src/App/Components/TextButton.lua b/plugin/src/App/Components/TextButton.lua index 5551f64c..2cfae5a2 100644 --- a/plugin/src/App/Components/TextButton.lua +++ b/plugin/src/App/Components/TextButton.lua @@ -41,10 +41,8 @@ end function TextButton:render() return Theme.with(function(theme) - local textSize = TextService:GetTextSize( - self.props.text, 18, Enum.Font.GothamSemibold, - Vector2.new(math.huge, math.huge) - ) + local textSize = + TextService:GetTextSize(self.props.text, 18, Enum.Font.GothamSemibold, Vector2.new(math.huge, math.huge)) local style = self.props.style @@ -124,7 +122,11 @@ function TextButton:render() Background = style == "Solid" and e(SlicedImage, { slice = Assets.Slices.RoundedBackground, - color = bindingUtil.mapLerp(bindingEnabled, theme.Enabled.BackgroundColor, theme.Disabled.BackgroundColor), + color = bindingUtil.mapLerp( + bindingEnabled, + theme.Enabled.BackgroundColor, + theme.Disabled.BackgroundColor + ), transparency = self.props.transparency, size = UDim2.new(1, 0, 1, 0), diff --git a/plugin/src/App/Components/TextInput.lua b/plugin/src/App/Components/TextInput.lua index 94a76a97..61b688d8 100644 --- a/plugin/src/App/Components/TextInput.lua +++ b/plugin/src/App/Components/TextInput.lua @@ -38,22 +38,22 @@ end function TextInput:render() return Theme.with(function(theme) - theme = theme.TextInput + theme = theme.TextInput local bindingHover = bindingUtil.deriveProperty(self.binding, "hover") local bindingEnabled = bindingUtil.deriveProperty(self.binding, "enabled") - return e(SlicedImage, { - slice = Assets.Slices.RoundedBorder, - color = bindingUtil.mapLerp(bindingEnabled, theme.Enabled.BorderColor, theme.Disabled.BorderColor), - transparency = self.props.transparency, + return e(SlicedImage, { + slice = Assets.Slices.RoundedBorder, + color = bindingUtil.mapLerp(bindingEnabled, theme.Enabled.BorderColor, theme.Disabled.BorderColor), + transparency = self.props.transparency, - size = self.props.size or UDim2.new(1, 0, 1, 0), - position = self.props.position, - layoutOrder = self.props.layoutOrder, - anchorPoint = self.props.anchorPoint, - }, { - HoverOverlay = e(SlicedImage, { + size = self.props.size or UDim2.new(1, 0, 1, 0), + position = self.props.position, + layoutOrder = self.props.layoutOrder, + anchorPoint = self.props.anchorPoint, + }, { + HoverOverlay = e(SlicedImage, { slice = Assets.Slices.RoundedBackground, color = theme.ActionFillColor, transparency = Roact.joinBindings({ @@ -67,36 +67,40 @@ function TextInput:render() size = UDim2.new(1, 0, 1, 0), zIndex = -1, }), - Input = e("TextBox", { - BackgroundTransparency = 1, - Size = UDim2.fromScale(1, 1), - Text = self.props.text, - PlaceholderText = self.props.placeholder, - Font = Enum.Font.GothamMedium, - TextColor3 = bindingUtil.mapLerp(bindingEnabled, theme.Disabled.TextColor, theme.Enabled.TextColor), - PlaceholderColor3 = bindingUtil.mapLerp(bindingEnabled, theme.Disabled.PlaceholderColor, theme.Enabled.PlaceholderColor), - TextSize = 18, - TextEditable = self.props.enabled, - ClearTextOnFocus = self.props.clearTextOnFocus, + Input = e("TextBox", { + BackgroundTransparency = 1, + Size = UDim2.fromScale(1, 1), + Text = self.props.text, + PlaceholderText = self.props.placeholder, + Font = Enum.Font.GothamMedium, + TextColor3 = bindingUtil.mapLerp(bindingEnabled, theme.Disabled.TextColor, theme.Enabled.TextColor), + PlaceholderColor3 = bindingUtil.mapLerp( + bindingEnabled, + theme.Disabled.PlaceholderColor, + theme.Enabled.PlaceholderColor + ), + TextSize = 18, + TextEditable = self.props.enabled, + ClearTextOnFocus = self.props.clearTextOnFocus, - [Roact.Event.MouseEnter] = function() - self.motor:setGoal({ - hover = Flipper.Spring.new(1, SPRING_PROPS), - }) - end, + [Roact.Event.MouseEnter] = function() + self.motor:setGoal({ + hover = Flipper.Spring.new(1, SPRING_PROPS), + }) + end, - [Roact.Event.MouseLeave] = function() - self.motor:setGoal({ - hover = Flipper.Spring.new(0, SPRING_PROPS), - }) - end, + [Roact.Event.MouseLeave] = function() + self.motor:setGoal({ + hover = Flipper.Spring.new(0, SPRING_PROPS), + }) + end, - [Roact.Event.FocusLost] = function(rbx) - self.props.onEntered(rbx.Text) - end, - }), - Children = Roact.createFragment(self.props[Roact.Children]), - }) + [Roact.Event.FocusLost] = function(rbx) + self.props.onEntered(rbx.Text) + end, + }), + Children = Roact.createFragment(self.props[Roact.Children]), + }) end) end diff --git a/plugin/src/App/Components/Tooltip.lua b/plugin/src/App/Components/Tooltip.lua index 9c1fb151..27822095 100644 --- a/plugin/src/App/Components/Tooltip.lua +++ b/plugin/src/App/Components/Tooltip.lua @@ -22,12 +22,16 @@ local TooltipContext = Roact.createContext({}) local function Popup(props) local textSize = TextService:GetTextSize( - props.Text, 16, Enum.Font.GothamMedium, Vector2.new(math.min(props.parentSize.X, 160), math.huge) + props.Text, + 16, + Enum.Font.GothamMedium, + Vector2.new(math.min(props.parentSize.X, 160), math.huge) ) + TEXT_PADDING + (Vector2.one * 2) local trigger = props.Trigger:getValue() - local spaceBelow = props.parentSize.Y - (trigger.AbsolutePosition.Y + trigger.AbsoluteSize.Y - Y_OVERLAP + TAIL_SIZE) + local spaceBelow = props.parentSize.Y + - (trigger.AbsolutePosition.Y + trigger.AbsoluteSize.Y - Y_OVERLAP + TAIL_SIZE) local spaceAbove = trigger.AbsolutePosition.Y + Y_OVERLAP - TAIL_SIZE -- If there's not enough space below, and there's more space above, then show the tooltip above the trigger @@ -39,7 +43,10 @@ local function Popup(props) if displayAbove then Y = math.max(trigger.AbsolutePosition.Y - TAIL_SIZE - textSize.Y + Y_OVERLAP, 0) else - Y = math.min(trigger.AbsolutePosition.Y + trigger.AbsoluteSize.Y + TAIL_SIZE - Y_OVERLAP, props.parentSize.Y - textSize.Y) + Y = math.min( + trigger.AbsolutePosition.Y + trigger.AbsoluteSize.Y + TAIL_SIZE - Y_OVERLAP, + props.parentSize.Y - textSize.Y + ) end return Theme.with(function(theme) @@ -64,17 +71,9 @@ local function Popup(props) Tail = e("ImageLabel", { ZIndex = 100, - Position = - if displayAbove then - UDim2.new( - 0, math.clamp(props.Position.X - X, 6, textSize.X-6), - 1, -1 - ) - else - UDim2.new( - 0, math.clamp(props.Position.X - X, 6, textSize.X-6), - 0, -TAIL_SIZE+1 - ), + Position = if displayAbove + then UDim2.new(0, math.clamp(props.Position.X - X, 6, textSize.X - 6), 1, -1) + else UDim2.new(0, math.clamp(props.Position.X - X, 6, textSize.X - 6), 0, -TAIL_SIZE + 1), Size = UDim2.fromOffset(TAIL_SIZE, TAIL_SIZE), AnchorPoint = Vector2.new(0.5, 0), Rotation = if displayAbove then 180 else 0, @@ -90,7 +89,7 @@ local function Popup(props) ImageColor3 = theme.BorderedContainer.BorderColor, ImageTransparency = props.transparency, }), - }) + }), }) end) end @@ -200,9 +199,10 @@ function Trigger:isHovering() local size = rbx.AbsoluteSize local mousePos = self.mousePos - return - mousePos.X >= pos.X and mousePos.X <= pos.X + size.X - and mousePos.Y >= pos.Y and mousePos.Y <= pos.Y + size.Y + return mousePos.X >= pos.X + and mousePos.X <= pos.X + size.X + and mousePos.Y >= pos.Y + and mousePos.Y <= pos.Y + size.Y end return false end @@ -236,7 +236,9 @@ end function Trigger:render() local function recalculate(rbx) local widget = rbx:FindFirstAncestorOfClass("DockWidgetPluginGui") - if not widget then return end + if not widget then + return + end self.mousePos = widget:GetRelativeMousePosition() self:managePopup() diff --git a/plugin/src/App/Components/TouchRipple.lua b/plugin/src/App/Components/TouchRipple.lua index 24ded570..1ea4c27d 100644 --- a/plugin/src/App/Components/TouchRipple.lua +++ b/plugin/src/App/Components/TouchRipple.lua @@ -24,9 +24,7 @@ function TouchRipple:init() }) self.binding = bindingUtil.fromMotor(self.motor) - self.position, self.setPosition = Roact.createBinding( - Vector2.new(0, 0) - ) + self.position, self.setPosition = Roact.createBinding(Vector2.new(0, 0)) end function TouchRipple:reset() @@ -43,10 +41,7 @@ function TouchRipple:calculateRadius(position) local container = self.ref.current if container then - local corner = Vector2.new( - math.floor((1 - position.X) + 0.5), - math.floor((1 - position.Y) + 0.5) - ) + local corner = Vector2.new(math.floor((1 - position.X) + 0.5), math.floor((1 - position.Y) + 0.5)) local size = container.AbsoluteSize local ratio = size / math.min(size.X, size.Y) @@ -93,10 +88,7 @@ function TouchRipple:render() input:GetPropertyChangedSignal("UserInputState"):Connect(function() local userInputState = input.UserInputState - if - userInputState == Enum.UserInputState.Cancel - or userInputState == Enum.UserInputState.End - then + if userInputState == Enum.UserInputState.Cancel or userInputState == Enum.UserInputState.End then self.motor:setGoal({ opacity = Flipper.Spring.new(0, { frequency = 5, @@ -127,8 +119,10 @@ function TouchRipple:render() local containerAspect = containerSize.X / containerSize.Y return UDim2.new( - currentSize / math.max(containerAspect, 1), 0, - currentSize * math.min(containerAspect, 1), 0 + currentSize / math.max(containerAspect, 1), + 0, + currentSize * math.min(containerAspect, 1), + 0 ) end end), diff --git a/plugin/src/App/Notifications.lua b/plugin/src/App/Notifications.lua index 120a5aa5..682758cb 100644 --- a/plugin/src/App/Notifications.lua +++ b/plugin/src/App/Notifications.lua @@ -37,28 +37,24 @@ function Notification:init() end function Notification:dismiss() - self.motor:setGoal( - Flipper.Spring.new(0, { - frequency = 5, - dampingRatio = 1, - }) - ) + self.motor:setGoal(Flipper.Spring.new(0, { + frequency = 5, + dampingRatio = 1, + })) end function Notification:didMount() - self.motor:setGoal( - Flipper.Spring.new(1, { - frequency = 3, - dampingRatio = 1, - }) - ) + self.motor:setGoal(Flipper.Spring.new(1, { + frequency = 3, + dampingRatio = 1, + })) self.props.soundPlayer:play(Assets.Sounds.Notification) self.timeout = task.spawn(function() local clock = os.clock() local seen = false - while task.wait(1/10) do + while task.wait(1 / 10) do local now = os.clock() local dt = now - clock clock = now @@ -90,12 +86,7 @@ function Notification:render() return 1 - value end) - local textBounds = TextService:GetTextSize( - self.props.text, - 15, - Enum.Font.GothamMedium, - Vector2.new(350, 700) - ) + local textBounds = TextService:GetTextSize(self.props.text, 15, Enum.Font.GothamMedium, Vector2.new(350, 700)) local actionButtons = {} local buttonsX = 0 @@ -116,7 +107,9 @@ function Notification:render() }) buttonsX += TextService:GetTextSize( - action.text, 18, Enum.Font.GothamMedium, + action.text, + 18, + Enum.Font.GothamMedium, Vector2.new(math.huge, math.huge) ).X + 30 @@ -156,7 +149,7 @@ function Notification:render() Contents = e("Frame", { Size = UDim2.new(0, 35 + contentX, 1, -paddingY), Position = UDim2.new(0, 0, 0, paddingY / 2), - BackgroundTransparency = 1 + BackgroundTransparency = 1, }, { Logo = e("ImageLabel", { ImageTransparency = transparency, @@ -181,28 +174,30 @@ function Notification:render() LayoutOrder = 1, BackgroundTransparency = 1, }), - Actions = if self.props.actions then e("Frame", { - Size = UDim2.new(1, -40, 0, 35), - Position = UDim2.new(1, 0, 1, 0), - AnchorPoint = Vector2.new(1, 1), - BackgroundTransparency = 1, - }, { - Layout = e("UIListLayout", { - FillDirection = Enum.FillDirection.Horizontal, - HorizontalAlignment = Enum.HorizontalAlignment.Right, - VerticalAlignment = Enum.VerticalAlignment.Center, - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 5), - }), - Buttons = Roact.createFragment(actionButtons), - }) else nil, + Actions = if self.props.actions + then e("Frame", { + Size = UDim2.new(1, -40, 0, 35), + Position = UDim2.new(1, 0, 1, 0), + AnchorPoint = Vector2.new(1, 1), + BackgroundTransparency = 1, + }, { + Layout = e("UIListLayout", { + FillDirection = Enum.FillDirection.Horizontal, + HorizontalAlignment = Enum.HorizontalAlignment.Right, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 5), + }), + Buttons = Roact.createFragment(actionButtons), + }) + else nil, }), Padding = e("UIPadding", { PaddingLeft = UDim.new(0, 17), PaddingRight = UDim.new(0, 15), }), - }) + }), }) end) end diff --git a/plugin/src/App/Page.lua b/plugin/src/App/Page.lua index 61387e21..42bc68b2 100644 --- a/plugin/src/App/Page.lua +++ b/plugin/src/App/Page.lua @@ -15,7 +15,7 @@ local Page = Roact.Component:extend("Page") function Page:init() self:setState({ - rendered = self.props.active + rendered = self.props.active, }) self.motor = Flipper.SingleMotor.new(self.props.active and 1 or 0) @@ -51,20 +51,21 @@ function Page:render() Size = UDim2.new(1, 0, 1, 0), BackgroundTransparency = 1, }, { - Component = e(self.props.component, Dictionary.merge(self.props, { - transparency = transparency, - })) + Component = e( + self.props.component, + Dictionary.merge(self.props, { + transparency = transparency, + }) + ), }) end function Page:didUpdate(lastProps) if self.props.active ~= lastProps.active then - self.motor:setGoal( - Flipper.Spring.new(self.props.active and 1 or 0, { - frequency = 6, - dampingRatio = 1, - }) - ) + self.motor:setGoal(Flipper.Spring.new(self.props.active and 1 or 0, { + frequency = 6, + dampingRatio = 1, + })) end end diff --git a/plugin/src/App/StatusPages/Confirming.lua b/plugin/src/App/StatusPages/Confirming.lua index 098c2dbd..457340bd 100644 --- a/plugin/src/App/StatusPages/Confirming.lua +++ b/plugin/src/App/StatusPages/Confirming.lua @@ -85,7 +85,7 @@ function ConfirmingPage:render() onClick = self.props.onAbort, }, { Tip = e(Tooltip.Trigger, { - text = "Stop the connection process" + text = "Stop the connection process", }), }), @@ -98,7 +98,7 @@ function ConfirmingPage:render() onClick = self.props.onReject, }, { Tip = e(Tooltip.Trigger, { - text = "Push Studio changes to the Rojo server" + text = "Push Studio changes to the Rojo server", }), }) else nil, @@ -111,7 +111,7 @@ function ConfirmingPage:render() onClick = self.props.onAccept, }, { Tip = e(Tooltip.Trigger, { - text = "Pull Rojo server changes to Studio" + text = "Pull Rojo server changes to Studio", }), }), @@ -169,7 +169,7 @@ function ConfirmingPage:render() oldText = self.state.oldSource, newText = self.state.newSource, - }) + }), }), }), }), diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index b385b1c4..c1aafbe6 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -21,7 +21,17 @@ local StringDiffVisualizer = require(Plugin.App.Components.StringDiffVisualizer) local e = Roact.createElement -local AGE_UNITS = { {31556909, "year"}, {2629743, "month"}, {604800, "week"}, {86400, "day"}, {3600, "hour"}, {60, "minute"}, } +local AGE_UNITS = { + { 31556909, "year" }, + { 2629743, "month" }, + { 604800, "week" }, + { 86400, "day" }, + { 3600, "hour" }, + { + 60, + "minute", + }, +} function timeSinceText(elapsed: number): string if elapsed < 3 then return "just now" @@ -159,16 +169,15 @@ function ConnectedPage:getChangeInfoText() local elapsed = os.time() - patchData.timestamp local unapplied = PatchSet.countChanges(patchData.unapplied) - return - "Synced " + return "Synced " .. timeSinceText(elapsed) - .. (if unapplied > 0 then - string.format( - ", but %d change%s failed to apply", + .. (if unapplied > 0 + then string.format( + ', but %d change%s failed to apply', unapplied, unapplied == 1 and "" or "s" ) - else "") + else "") .. "" end @@ -297,7 +306,7 @@ function ConnectedPage:render() onClick = self.props.onNavigateSettings, }, { Tip = e(Tooltip.Trigger, { - text = "View and modify plugin settings" + text = "View and modify plugin settings", }), }), @@ -309,7 +318,7 @@ function ConnectedPage:render() onClick = self.props.onDisconnect, }, { Tip = e(Tooltip.Trigger, { - text = "Disconnect from the Rojo sync server" + text = "Disconnect from the Rojo sync server", }), }), @@ -427,7 +436,7 @@ function ConnectedPage:render() oldText = self.state.oldSource, newText = self.state.newSource, - }) + }), }), }), }), diff --git a/plugin/src/App/StatusPages/Error.lua b/plugin/src/App/StatusPages/Error.lua index 138e1939..5d1bcb5e 100644 --- a/plugin/src/App/StatusPages/Error.lua +++ b/plugin/src/App/StatusPages/Error.lua @@ -50,7 +50,9 @@ function Error:render() local containerSize = object.AbsoluteSize - ERROR_PADDING * 2 local textBounds = TextService:GetTextSize( - self.props.errorMessage, 16, Enum.Font.Code, + self.props.errorMessage, + 16, + Enum.Font.Code, Vector2.new(containerSize.X, math.huge) ) @@ -60,12 +62,13 @@ function Error:render() ErrorMessage = Theme.with(function(theme) return e("TextBox", { [Roact.Event.InputBegan] = function(rbx, input) - if input.UserInputType ~= Enum.UserInputType.MouseButton1 then return end + if input.UserInputType ~= Enum.UserInputType.MouseButton1 then + return + end rbx.SelectionStart = 0 - rbx.CursorPosition = #rbx.Text+1 + rbx.CursorPosition = #rbx.Text + 1 end, - Text = self.props.errorMessage, TextEditable = false, Font = Enum.Font.Code, @@ -126,7 +129,7 @@ function ErrorPage:render() onClick = self.props.onClose, }, { Tip = e(Tooltip.Trigger, { - text = "Dismiss message" + text = "Dismiss message", }), }), diff --git a/plugin/src/App/StatusPages/NotConnected.lua b/plugin/src/App/StatusPages/NotConnected.lua index 3097446e..e881e7eb 100644 --- a/plugin/src/App/StatusPages/NotConnected.lua +++ b/plugin/src/App/StatusPages/NotConnected.lua @@ -46,7 +46,7 @@ local function AddressEntry(props) if props.onHostChange ~= nil then props.onHostChange(object.Text) end - end + end, }), Port = e("TextBox", { @@ -120,7 +120,7 @@ function NotConnectedPage:render() onClick = self.props.onNavigateSettings, }, { Tip = e(Tooltip.Trigger, { - text = "View and modify plugin settings" + text = "View and modify plugin settings", }), }), @@ -132,7 +132,7 @@ function NotConnectedPage:render() onClick = self.props.onConnect, }, { Tip = e(Tooltip.Trigger, { - text = "Connect to a Rojo sync server" + text = "Connect to a Rojo sync server", }), }), diff --git a/plugin/src/App/StatusPages/Settings/Setting.lua b/plugin/src/App/StatusPages/Settings/Setting.lua index 2532222d..86adb6fc 100644 --- a/plugin/src/App/StatusPages/Settings/Setting.lua +++ b/plugin/src/App/StatusPages/Settings/Setting.lua @@ -81,40 +81,39 @@ function Setting:render() end, }), - Input = - if self.props.input ~= nil then - self.props.input - elseif self.props.options ~= nil then - e(Dropdown, { - locked = self.props.locked, - options = self.props.options, - active = self.state.setting, - transparency = self.props.transparency, - onClick = function(option) - Settings:set(self.props.id, option) - end, - }) - else - e(Checkbox, { - locked = self.props.locked, - active = self.state.setting, - transparency = self.props.transparency, - onClick = function() - local currentValue = Settings:get(self.props.id) - Settings:set(self.props.id, not currentValue) - end, - }), + Input = if self.props.input ~= nil + then self.props.input + elseif self.props.options ~= nil then e(Dropdown, { + locked = self.props.locked, + options = self.props.options, + active = self.state.setting, + transparency = self.props.transparency, + onClick = function(option) + Settings:set(self.props.id, option) + end, + }) + else e(Checkbox, { + locked = self.props.locked, + active = self.state.setting, + transparency = self.props.transparency, + onClick = function() + local currentValue = Settings:get(self.props.id) + Settings:set(self.props.id, not currentValue) + end, + }), - Reset = if self.props.onReset then e(IconButton, { - icon = Assets.Images.Icons.Reset, - iconSize = 24, - color = theme.BackButtonColor, - transparency = self.props.transparency, - visible = self.props.showReset, - layoutOrder = -1, + Reset = if self.props.onReset + then e(IconButton, { + icon = Assets.Images.Icons.Reset, + iconSize = 24, + color = theme.BackButtonColor, + transparency = self.props.transparency, + visible = self.props.showReset, + layoutOrder = -1, - onClick = self.props.onReset, - }) else nil, + onClick = self.props.onReset, + }) + else nil, }), Text = e("Frame", { @@ -122,7 +121,8 @@ function Setting:render() BackgroundTransparency = 1, }, { Name = e("TextLabel", { - Text = (if self.props.experimental then "⚠ " else "") .. self.props.name, + Text = (if self.props.experimental then '⚠ ' else "") + .. self.props.name, Font = Enum.Font.GothamBold, TextSize = 17, TextColor3 = theme.Setting.NameColor, @@ -137,7 +137,8 @@ function Setting:render() }), Description = e("TextLabel", { - Text = (if self.props.experimental then "[Experimental] " else "") .. self.props.description, + Text = (if self.props.experimental then '[Experimental] ' else "") + .. self.props.description, Font = Enum.Font.Gotham, LineHeight = 1.2, TextSize = 14, @@ -151,10 +152,14 @@ function Setting:render() containerSize = self.containerSize, inputSize = self.inputSize, }):map(function(values) - local desc = (if self.props.experimental then "[Experimental] " else "") .. self.props.description + local desc = (if self.props.experimental then "[Experimental] " else "") + .. self.props.description local offset = values.inputSize.X + 5 local textBounds = getTextBounds( - desc, 14, Enum.Font.Gotham, 1.2, + desc, + 14, + Enum.Font.Gotham, + 1.2, Vector2.new(values.containerSize.X - offset, math.huge) ) return UDim2.new(1, -offset, 0, textBounds.Y) diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua index 3a08b1e7..688be85a 100644 --- a/plugin/src/App/StatusPages/Settings/init.lua +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -49,7 +49,7 @@ local function Navbar(props) onClick = props.onBack, }, { Tip = e(Tooltip.Trigger, { - text = "Back" + text = "Back", }), }), @@ -63,7 +63,7 @@ local function Navbar(props) Size = UDim2.new(1, 0, 1, 0), BackgroundTransparency = 1, - }) + }), }) end) end @@ -138,7 +138,10 @@ function SettingsPage:render() Settings:set("largeChangesConfirmationThreshold", math.clamp(number, 1, 999)) else -- Force text back to last valid value - Settings:set("largeChangesConfirmationThreshold", Settings:get("largeChangesConfirmationThreshold")) + Settings:set( + "largeChangesConfirmationThreshold", + Settings:get("largeChangesConfirmationThreshold") + ) end end, }), diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index 00aab81f..d6f9622b 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -90,7 +90,7 @@ local lightTheme = strict("LightTheme", { }, AddressEntry = { TextColor = Color3.fromHex("000000"), - PlaceholderColor = Color3.fromHex("8C8C8C") + PlaceholderColor = Color3.fromHex("8C8C8C"), }, BorderedContainer = { BorderColor = Color3.fromHex("CBCBCB"), @@ -200,7 +200,7 @@ local darkTheme = strict("DarkTheme", { }, AddressEntry = { TextColor = Color3.fromHex("FFFFFF"), - PlaceholderColor = Color3.fromHex("8B8B8B") + PlaceholderColor = Color3.fromHex("8B8B8B"), }, BorderedContainer = { BorderColor = Color3.fromHex("535353"), @@ -235,7 +235,7 @@ local darkTheme = strict("DarkTheme", { }, Header = { LogoColor = BRAND_COLOR, - VersionColor = Color3.fromHex("D3D3D3") + VersionColor = Color3.fromHex("D3D3D3"), }, Notification = { InfoColor = Color3.fromHex("FFFFFF"), diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 647c62e7..cfebcad8 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -469,13 +469,17 @@ function App:startSession() if confirmationBehavior == "Initial" then -- Only confirm if we haven't synced this project yet this session if self.knownProjects[serverInfo.projectName] then - Log.trace("Accepting patch without confirmation because project has already been connected and behavior is set to Initial") + Log.trace( + "Accepting patch without confirmation because project has already been connected and behavior is set to Initial" + ) return "Accept" end elseif confirmationBehavior == "Large Changes" then -- Only confirm if the patch impacts many instances if PatchSet.countInstances(patch) < Settings:get("largeChangesConfirmationThreshold") then - Log.trace("Accepting patch without confirmation because patch is small and behavior is set to Large Changes") + Log.trace( + "Accepting patch without confirmation because patch is small and behavior is set to Large Changes" + ) return "Accept" end elseif confirmationBehavior == "Unlisted PlaceId" then @@ -483,7 +487,9 @@ function App:startSession() if serverInfo.expectedPlaceIds then local isListed = table.find(serverInfo.expectedPlaceIds, game.PlaceId) ~= nil if isListed then - Log.trace("Accepting patch without confirmation because placeId is listed and behavior is set to Unlisted PlaceId") + Log.trace( + "Accepting patch without confirmation because placeId is listed and behavior is set to Unlisted PlaceId" + ) return "Accept" end end @@ -657,7 +663,8 @@ function App:render() }), Settings = createPageElement(AppStatus.Settings, { - syncActive = self.serveSession ~= nil and self.serveSession:getStatus() == ServeSession.Status.Connected, + syncActive = self.serveSession ~= nil + and self.serveSession:getStatus() == ServeSession.Status.Connected, onBack = function() self:setState({ diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index bee8f3c7..dbc60a16 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -54,7 +54,7 @@ local Assets = { [32] = "rbxassetid://3088713341", [64] = "rbxassetid://4918677124", [128] = "rbxassetid://2600845734", - [500] = "rbxassetid://2609138523" + [500] = "rbxassetid://2609138523", }, }, Sounds = { diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 3f5706e5..a2909f51 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -5,7 +5,7 @@ local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = {7, 3, 0}, + version = { 7, 3, 0 }, expectedServerVersionString = "7.2 or newer", protocolVersion = 4, defaultHost = "localhost", diff --git a/plugin/src/Dictionary.lua b/plugin/src/Dictionary.lua index c4b1e532..93d4ad91 100644 --- a/plugin/src/Dictionary.lua +++ b/plugin/src/Dictionary.lua @@ -30,4 +30,4 @@ end return { None = None, merge = merge, -} \ No newline at end of file +} diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 5621e9be..91a1d4cd 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -66,7 +66,7 @@ function InstanceMap:__fmtDebug(output) for id, instance in pairs(self.fromIds) do local label = string.format("%s (%s)", instance:GetFullName(), instance.ClassName) - table.insert(entries, {id, label}) + table.insert(entries, { id, label }) end table.sort(entries, function(a, b) diff --git a/plugin/src/PatchSet.lua b/plugin/src/PatchSet.lua index a7829de0..abbac0cb 100644 --- a/plugin/src/PatchSet.lua +++ b/plugin/src/PatchSet.lua @@ -26,7 +26,9 @@ local function deepEqual(a: any, b: any): boolean end for key, value in b do - if checkedKeys[key] then continue end + if checkedKeys[key] then + continue + end if deepEqual(value, a[key]) == false then return false end @@ -65,9 +67,7 @@ end Tells whether the given PatchSet is empty. ]] function PatchSet.isEmpty(patchSet) - return next(patchSet.removed) == nil and - next(patchSet.added) == nil and - next(patchSet.updated) == nil + return next(patchSet.removed) == nil and next(patchSet.added) == nil and next(patchSet.updated) == nil end --[[ @@ -342,9 +342,15 @@ function PatchSet.humanSummary(instanceMap, patchSet) end end - table.insert(statements, string.format( - "- Add instance %q (ClassName %q) to %s", - virtualInstance.Name, virtualInstance.ClassName, parentDisplayName)) + table.insert( + statements, + string.format( + "- Add instance %q (ClassName %q) to %s", + virtualInstance.Name, + virtualInstance.ClassName, + parentDisplayName + ) + ) end for _, update in ipairs(patchSet.updated) do @@ -374,9 +380,10 @@ function PatchSet.humanSummary(instanceMap, patchSet) displayName = "[unknown instance]" end - table.insert(statements, string.format( - "- Update properties on %s: %s", - displayName, table.concat(updatedProperties, ","))) + table.insert( + statements, + string.format("- Update properties on %s: %s", displayName, table.concat(updatedProperties, ",")) + ) end return table.concat(statements, "\n") diff --git a/plugin/src/PatchTree.lua b/plugin/src/PatchTree.lua index 568f2412..82e437eb 100644 --- a/plugin/src/PatchTree.lua +++ b/plugin/src/PatchTree.lua @@ -401,7 +401,9 @@ end -- Creates a deep copy of a tree for immutability purposes in Roact function PatchTree.clone(tree) - if not tree then return end + if not tree then + return + end local newTree = Tree.new() tree:forEach(function(node) diff --git a/plugin/src/Reconciler/applyPatch.spec.lua b/plugin/src/Reconciler/applyPatch.spec.lua index 2432359f..c561db75 100644 --- a/plugin/src/Reconciler/applyPatch.spec.lua +++ b/plugin/src/Reconciler/applyPatch.spec.lua @@ -83,11 +83,11 @@ return function() ClassName = "Model", Name = "Child", Parent = "ROOT", - Children = {"GRANDCHILD"}, + Children = { "GRANDCHILD" }, Properties = {}, } - patch.added["GRANDCHILD"] = { + patch.added["GRANDCHILD"] = { Id = "GRANDCHILD", ClassName = "Part", Name = "Grandchild", @@ -193,4 +193,4 @@ return function() assert(newChild ~= nil, "expected child to be present") assert(newChild == child, "expected child to be preserved") end) -end \ No newline at end of file +end diff --git a/plugin/src/Reconciler/decodeValue.lua b/plugin/src/Reconciler/decodeValue.lua index 64c33ace..cd67e77d 100644 --- a/plugin/src/Reconciler/decodeValue.lua +++ b/plugin/src/Reconciler/decodeValue.lua @@ -30,10 +30,11 @@ local function decodeValue(encodedValue, instanceMap) local ok, decodedValue = RbxDom.EncodedValue.decode(encodedValue) if not ok then - return false, Error.new(Error.CannotDecodeValue, { - encodedValue = encodedValue, - innerError = decodedValue, - }) + return false, + Error.new(Error.CannotDecodeValue, { + encodedValue = encodedValue, + innerError = decodedValue, + }) end return true, decodedValue diff --git a/plugin/src/Reconciler/diff.lua b/plugin/src/Reconciler/diff.lua index e2dac7ff..0bc772aa 100644 --- a/plugin/src/Reconciler/diff.lua +++ b/plugin/src/Reconciler/diff.lua @@ -37,7 +37,9 @@ local function trueEquals(a, b): boolean end end for key, value in pairs(b) do - if checkedKeys[key] then continue end + if checkedKeys[key] then + continue + end if not trueEquals(value, a[key]) then return false end @@ -62,7 +64,7 @@ local function trueEquals(a, b): boolean -- For CFrames, compare to components with epsilon of 0.0001 to avoid floating point inequality elseif typeA == "CFrame" and typeB == "CFrame" then - local aComponents, bComponents = {a:GetComponents()}, {b:GetComponents()} + local aComponents, bComponents = { a:GetComponents() }, { b:GetComponents() } for i, aComponent in aComponents do if not fuzzyEq(aComponent, bComponents[i], 0.0001) then return false @@ -72,7 +74,7 @@ local function trueEquals(a, b): boolean -- For Vector3s, compare to components with epsilon of 0.0001 to avoid floating point inequality elseif typeA == "Vector3" and typeB == "Vector3" then - local aComponents, bComponents = {a.X, a.Y, a.Z}, {b.X, b.Y, b.Z} + local aComponents, bComponents = { a.X, a.Y, a.Z }, { b.X, b.Y, b.Z } for i, aComponent in aComponents do if not fuzzyEq(aComponent, bComponents[i], 0.0001) then return false @@ -82,14 +84,13 @@ local function trueEquals(a, b): boolean -- For Vector2s, compare to components with epsilon of 0.0001 to avoid floating point inequality elseif typeA == "Vector2" and typeB == "Vector2" then - local aComponents, bComponents = {a.X, a.Y}, {b.X, b.Y} + local aComponents, bComponents = { a.X, a.Y }, { b.X, b.Y } for i, aComponent in aComponents do if not fuzzyEq(aComponent, bComponents[i], 0.0001) then return false end end return true - end return false @@ -154,7 +155,13 @@ local function diff(instanceMap, virtualInstances, rootId) if ok then if not trueEquals(existingValue, decodedValue) then - Log.debug("{}.{} changed from '{}' to '{}'", instance:GetFullName(), propertyName, existingValue, decodedValue) + Log.debug( + "{}.{} changed from '{}' to '{}'", + instance:GetFullName(), + propertyName, + existingValue, + decodedValue + ) changedProperties[propertyName] = virtualValue end else diff --git a/plugin/src/Reconciler/diff.spec.lua b/plugin/src/Reconciler/diff.spec.lua index cc596eaa..451540b3 100644 --- a/plugin/src/Reconciler/diff.spec.lua +++ b/plugin/src/Reconciler/diff.spec.lua @@ -264,7 +264,7 @@ return function() ClassName = "Folder", Name = "Folder", Properties = {}, - Children = {"CHILD"}, + Children = { "CHILD" }, }, CHILD = { diff --git a/plugin/src/Reconciler/getProperty.lua b/plugin/src/Reconciler/getProperty.lua index cd70fa24..3b8b5b92 100644 --- a/plugin/src/Reconciler/getProperty.lua +++ b/plugin/src/Reconciler/getProperty.lua @@ -14,17 +14,19 @@ local function getProperty(instance, propertyName) -- A good example of a property like this is `Model.ModelInPrimary`, which -- is serialized but not reflected to Lua. if descriptor == nil then - return false, Error.new(Error.UnknownProperty, { - className = instance.ClassName, - propertyName = propertyName, - }) + return false, + Error.new(Error.UnknownProperty, { + className = instance.ClassName, + propertyName = propertyName, + }) end if descriptor.scriptability == "None" or descriptor.scriptability == "Write" then - return false, Error.new(Error.UnreadableProperty, { - className = instance.ClassName, - propertyName = propertyName, - }) + return false, + Error.new(Error.UnreadableProperty, { + className = instance.ClassName, + propertyName = propertyName, + }) end local success, valueOrErr = descriptor:read(instance) @@ -35,23 +37,26 @@ local function getProperty(instance, propertyName) -- If we don't have permission to read a property, we can chalk that up -- to our database being out of date and the engine being right. if err.kind == RbxDom.Error.Kind.Roblox and err.extra:find("lacking permission") then - return false, Error.new(Error.LackingPropertyPermissions, { - className = instance.ClassName, - propertyName = propertyName, - }) + return false, + Error.new(Error.LackingPropertyPermissions, { + className = instance.ClassName, + propertyName = propertyName, + }) end if err.kind == RbxDom.Error.Kind.Roblox and err.extra:find("is not a valid member of") then - return false, Error.new(Error.UnknownProperty, { + return false, + Error.new(Error.UnknownProperty, { + className = instance.ClassName, + propertyName = propertyName, + }) + end + + return false, + Error.new(Error.OtherPropertyError, { className = instance.ClassName, propertyName = propertyName, }) - end - - return false, Error.new(Error.OtherPropertyError, { - className = instance.ClassName, - propertyName = propertyName, - }) end return true, valueOrErr diff --git a/plugin/src/Reconciler/hydrate.lua b/plugin/src/Reconciler/hydrate.lua index 4d677f57..c2239179 100644 --- a/plugin/src/Reconciler/hydrate.lua +++ b/plugin/src/Reconciler/hydrate.lua @@ -47,4 +47,4 @@ local function hydrate(instanceMap, virtualInstances, rootId, rootInstance) end end -return hydrate \ No newline at end of file +return hydrate diff --git a/plugin/src/Reconciler/hydrate.spec.lua b/plugin/src/Reconciler/hydrate.spec.lua index b9ff796b..226d37f3 100644 --- a/plugin/src/Reconciler/hydrate.spec.lua +++ b/plugin/src/Reconciler/hydrate.spec.lua @@ -91,7 +91,7 @@ return function() ClassName = "Folder", Name = "Root", Properties = {}, - Children = {"CHILD1", "CHILD2"}, + Children = { "CHILD1", "CHILD2" }, }, CHILD1 = { @@ -126,4 +126,4 @@ return function() expect(knownInstances.fromIds["CHILD1"]).to.equal(child1) expect(knownInstances.fromIds["CHILD2"]).to.equal(child2) end) -end \ No newline at end of file +end diff --git a/plugin/src/Reconciler/reify.spec.lua b/plugin/src/Reconciler/reify.spec.lua index a13b204a..f39032a2 100644 --- a/plugin/src/Reconciler/reify.spec.lua +++ b/plugin/src/Reconciler/reify.spec.lua @@ -80,7 +80,7 @@ return function() ClassName = "Folder", Name = "Parent", Properties = {}, - Children = {"CHILD"}, + Children = { "CHILD" }, }, CHILD = { @@ -112,7 +112,7 @@ return function() ClassName = "Folder", Name = "Parent", Properties = {}, - Children = {"CHILD"}, + Children = { "CHILD" }, }, CHILD = { @@ -147,7 +147,7 @@ return function() Properties = { Value = { Type = "Vector3", - Value = {1, 2, 3}, + Value = { 1, 2, 3 }, }, }, Children = {}, @@ -182,7 +182,7 @@ return function() ClassName = "Folder", Name = "Root", Properties = {}, - Children = {"CHILD"}, + Children = { "CHILD" }, }, CHILD = { @@ -247,7 +247,7 @@ return function() ClassName = "Folder", Name = "Root", Properties = {}, - Children = {"CHILD_A", "CHILD_B"}, + Children = { "CHILD_A", "CHILD_B" }, }, CHILD_A = { @@ -297,7 +297,7 @@ return function() Ref = "CHILD", }, }, - Children = {"CHILD"}, + Children = { "CHILD" }, }, CHILD = { diff --git a/plugin/src/Reconciler/setProperty.lua b/plugin/src/Reconciler/setProperty.lua index 211a1491..35c8b59b 100644 --- a/plugin/src/Reconciler/setProperty.lua +++ b/plugin/src/Reconciler/setProperty.lua @@ -21,26 +21,29 @@ local function setProperty(instance, propertyName, value) end if descriptor.scriptability == "None" or descriptor.scriptability == "Read" then - return false, Error.new(Error.UnwritableProperty, { - className = instance.ClassName, - propertyName = propertyName, - }) + return false, + Error.new(Error.UnwritableProperty, { + className = instance.ClassName, + propertyName = propertyName, + }) end local ok, err = descriptor:write(instance, value) if not ok then if err.kind == RbxDom.Error.Kind.Roblox and err.extra:find("lacking permission") then - return false, Error.new(Error.LackingPropertyPermissions, { + return false, + Error.new(Error.LackingPropertyPermissions, { + className = instance.ClassName, + propertyName = propertyName, + }) + end + + return false, + Error.new(Error.OtherPropertyError, { className = instance.ClassName, propertyName = propertyName, }) - end - - return false, Error.new(Error.OtherPropertyError, { - className = instance.ClassName, - propertyName = propertyName, - }) end return true diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 6a3fcdc4..e5bbb12f 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -77,15 +77,13 @@ function ServeSession.new(options) local connections = {} - local connection = StudioService - :GetPropertyChangedSignal("ActiveScript") - :Connect(function() - local activeScript = StudioService.ActiveScript + local connection = StudioService:GetPropertyChangedSignal("ActiveScript"):Connect(function() + local activeScript = StudioService.ActiveScript - if activeScript ~= nil then - self:__onActiveScriptChanged(activeScript) - end - end) + if activeScript ~= nil then + self:__onActiveScriptChanged(activeScript) + end + end) table.insert(connections, connection) self = { @@ -139,16 +137,16 @@ end function ServeSession:start() self:__setStatus(Status.Connecting) - self.__apiContext:connect() + self.__apiContext + :connect() :andThen(function(serverInfo) self:__applyGameAndPlaceId(serverInfo) - return self:__initialSync(serverInfo) - :andThen(function() - self:__setStatus(Status.Connected, serverInfo.projectName) + return self:__initialSync(serverInfo):andThen(function() + self:__setStatus(Status.Connected, serverInfo.projectName) - return self:__mainSyncLoop() - end) + return self:__mainSyncLoop() + end) end) :catch(function(err) if self.__status ~= Status.Disconnected then @@ -211,97 +209,93 @@ function ServeSession:__onActiveScriptChanged(activeScript) end function ServeSession:__initialSync(serverInfo) - return self.__apiContext:read({ serverInfo.rootInstanceId }) - :andThen(function(readResponseBody) - -- Tell the API Context that we're up-to-date with the version of - -- the tree defined in this response. - self.__apiContext:setMessageCursor(readResponseBody.messageCursor) + return self.__apiContext:read({ serverInfo.rootInstanceId }):andThen(function(readResponseBody) + -- Tell the API Context that we're up-to-date with the version of + -- the tree defined in this response. + self.__apiContext:setMessageCursor(readResponseBody.messageCursor) - -- For any instances that line up with the Rojo server's view, start - -- tracking them in the reconciler. - Log.trace("Matching existing Roblox instances to Rojo IDs") - self.__reconciler:hydrate(readResponseBody.instances, serverInfo.rootInstanceId, game) + -- For any instances that line up with the Rojo server's view, start + -- tracking them in the reconciler. + Log.trace("Matching existing Roblox instances to Rojo IDs") + self.__reconciler:hydrate(readResponseBody.instances, serverInfo.rootInstanceId, game) - -- Calculate the initial patch to apply to the DataModel to catch us - -- up to what Rojo thinks the place should look like. - Log.trace("Computing changes that plugin needs to make to catch up to server...") - local success, catchUpPatch = self.__reconciler:diff( - readResponseBody.instances, - serverInfo.rootInstanceId, - game - ) + -- Calculate the initial patch to apply to the DataModel to catch us + -- up to what Rojo thinks the place should look like. + Log.trace("Computing changes that plugin needs to make to catch up to server...") + local success, catchUpPatch = + self.__reconciler:diff(readResponseBody.instances, serverInfo.rootInstanceId, game) - if not success then - Log.error("Could not compute a diff to catch up to the Rojo server: {:#?}", catchUpPatch) - end + if not success then + Log.error("Could not compute a diff to catch up to the Rojo server: {:#?}", catchUpPatch) + end - for _, update in catchUpPatch.updated do - if - update.id == self.__instanceMap.fromInstances[game] - and update.changedClassName ~= nil - then - -- Non-place projects will try to update the classname of game from DataModel to - -- something like Folder, ModuleScript, etc. This would fail, so we exit with a clear - -- message instead of crashing. - return Promise.reject( - "Cannot sync a model as a place." + for _, update in catchUpPatch.updated do + if update.id == self.__instanceMap.fromInstances[game] and update.changedClassName ~= nil then + -- Non-place projects will try to update the classname of game from DataModel to + -- something like Folder, ModuleScript, etc. This would fail, so we exit with a clear + -- message instead of crashing. + return Promise.reject( + "Cannot sync a model as a place." .. "\nEnsure Rojo is serving a project file that has a DataModel at the root of its tree and try again." .. "\nSee project file docs: https://rojo.space/docs/v7/project-format/" - ) + ) + end + end + + Log.trace("Computed hydration patch: {:#?}", debugPatch(catchUpPatch)) + + local userDecision = "Accept" + if self.__userConfirmCallback ~= nil then + userDecision = self.__userConfirmCallback(self.__instanceMap, catchUpPatch, serverInfo) + end + + if userDecision == "Abort" then + return Promise.reject("Aborted Rojo sync operation") + elseif userDecision == "Reject" and self.__twoWaySync then + -- The user wants their studio DOM to write back to their Rojo DOM + -- so we will reverse the patch and send it back + + local inversePatch = PatchSet.newEmpty() + + -- Send back the current properties + for _, change in catchUpPatch.updated do + local instance = self.__instanceMap.fromIds[change.id] + if not instance then + continue end + + local update = encodePatchUpdate(instance, change.id, change.changedProperties) + table.insert(inversePatch.updated, update) + end + -- Add the removed instances back to Rojo + -- selene:allow(empty_if, unused_variable) + for _, instance in catchUpPatch.removed do + -- TODO: Generate ID for our instance and add it to inversePatch.added + end + -- Remove the additions we've rejected + for id, _change in catchUpPatch.added do + table.insert(inversePatch.removed, id) end - Log.trace("Computed hydration patch: {:#?}", debugPatch(catchUpPatch)) + self.__apiContext:write(inversePatch) + elseif userDecision == "Accept" then + local unappliedPatch = self.__reconciler:applyPatch(catchUpPatch) - local userDecision = "Accept" - if self.__userConfirmCallback ~= nil then - userDecision = self.__userConfirmCallback(self.__instanceMap, catchUpPatch, serverInfo) + if not PatchSet.isEmpty(unappliedPatch) then + Log.warn( + "Could not apply all changes requested by the Rojo server:\n{}", + PatchSet.humanSummary(self.__instanceMap, unappliedPatch) + ) end - - if userDecision == "Abort" then - return Promise.reject("Aborted Rojo sync operation") - - elseif userDecision == "Reject" and self.__twoWaySync then - -- The user wants their studio DOM to write back to their Rojo DOM - -- so we will reverse the patch and send it back - - local inversePatch = PatchSet.newEmpty() - - -- Send back the current properties - for _, change in catchUpPatch.updated do - local instance = self.__instanceMap.fromIds[change.id] - if not instance then continue end - - local update = encodePatchUpdate(instance, change.id, change.changedProperties) - table.insert(inversePatch.updated, update) - end - -- Add the removed instances back to Rojo - -- selene:allow(empty_if, unused_variable) - for _, instance in catchUpPatch.removed do - -- TODO: Generate ID for our instance and add it to inversePatch.added - end - -- Remove the additions we've rejected - for id, _change in catchUpPatch.added do - table.insert(inversePatch.removed, id) - end - - self.__apiContext:write(inversePatch) - - elseif userDecision == "Accept" then - local unappliedPatch = self.__reconciler:applyPatch(catchUpPatch) - - if not PatchSet.isEmpty(unappliedPatch) then - Log.warn("Could not apply all changes requested by the Rojo server:\n{}", - PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) - end - end - end) + end + end) end function ServeSession:__mainSyncLoop() return Promise.new(function(resolve, reject) while self.__status == Status.Connected do - local success, result = self.__apiContext:retrieveMessages() + local success, result = self.__apiContext + :retrieveMessages() :andThen(function(messages) if self.__status == Status.Disconnected then -- In the time it took to retrieve messages, we disconnected @@ -315,11 +309,14 @@ function ServeSession:__mainSyncLoop() local unappliedPatch = self.__reconciler:applyPatch(message) if not PatchSet.isEmpty(unappliedPatch) then - Log.warn("Could not apply all changes requested by the Rojo server:\n{}", - PatchSet.humanSummary(self.__instanceMap, unappliedPatch)) + Log.warn( + "Could not apply all changes requested by the Rojo server:\n{}", + PatchSet.humanSummary(self.__instanceMap, unappliedPatch) + ) end end - end):await() + end) + :await() if self.__status == Status.Disconnected then -- If we are no longer connected after applying, we stop silently diff --git a/plugin/src/Types.lua b/plugin/src/Types.lua index 221ddcb1..12e1dbba 100644 --- a/plugin/src/Types.lua +++ b/plugin/src/Types.lua @@ -56,11 +56,7 @@ local ApiSubscribeResponse = t.interface({ }) local ApiError = t.interface({ - kind = t.union( - t.literal("NotFound"), - t.literal("BadRequest"), - t.literal("InternalError") - ), + kind = t.union(t.literal("NotFound"), t.literal("BadRequest"), t.literal("InternalError")), details = t.string, }) diff --git a/plugin/src/Version.lua b/plugin/src/Version.lua index f7dd88f3..6c93a14e 100644 --- a/plugin/src/Version.lua +++ b/plugin/src/Version.lua @@ -43,4 +43,4 @@ function Version.display(version) return output end -return Version \ No newline at end of file +return Version diff --git a/plugin/src/Version.spec.lua b/plugin/src/Version.spec.lua index 7be002e9..cf9938d9 100644 --- a/plugin/src/Version.spec.lua +++ b/plugin/src/Version.spec.lua @@ -2,27 +2,27 @@ return function() local Version = require(script.Parent.Version) it("should compare equal versions", function() - expect(Version.compare({1, 2, 3}, {1, 2, 3})).to.equal(0) - expect(Version.compare({0, 4, 0}, {0, 4})).to.equal(0) - expect(Version.compare({0, 0, 123}, {0, 0, 123})).to.equal(0) - expect(Version.compare({26}, {26})).to.equal(0) - expect(Version.compare({26, 42}, {26, 42})).to.equal(0) - expect(Version.compare({1, 0, 0}, {1})).to.equal(0) + expect(Version.compare({ 1, 2, 3 }, { 1, 2, 3 })).to.equal(0) + expect(Version.compare({ 0, 4, 0 }, { 0, 4 })).to.equal(0) + expect(Version.compare({ 0, 0, 123 }, { 0, 0, 123 })).to.equal(0) + expect(Version.compare({ 26 }, { 26 })).to.equal(0) + expect(Version.compare({ 26, 42 }, { 26, 42 })).to.equal(0) + expect(Version.compare({ 1, 0, 0 }, { 1 })).to.equal(0) end) it("should compare newer, older versions", function() - expect(Version.compare({1}, {0})).to.equal(1) - expect(Version.compare({1, 1}, {1, 0})).to.equal(1) + expect(Version.compare({ 1 }, { 0 })).to.equal(1) + expect(Version.compare({ 1, 1 }, { 1, 0 })).to.equal(1) end) it("should compare different major versions", function() - expect(Version.compare({1, 3, 2}, {2, 2, 1})).to.equal(-1) - expect(Version.compare({1, 2}, {2, 1})).to.equal(-1) - expect(Version.compare({1}, {2})).to.equal(-1) + expect(Version.compare({ 1, 3, 2 }, { 2, 2, 1 })).to.equal(-1) + expect(Version.compare({ 1, 2 }, { 2, 1 })).to.equal(-1) + expect(Version.compare({ 1 }, { 2 })).to.equal(-1) end) it("should compare different minor versions", function() - expect(Version.compare({1, 2, 3}, {1, 3, 2})).to.equal(-1) - expect(Version.compare({50, 1}, {50, 2})).to.equal(-1) + expect(Version.compare({ 1, 2, 3 }, { 1, 3, 2 })).to.equal(-1) + expect(Version.compare({ 50, 1 }, { 50, 2 })).to.equal(-1) end) end diff --git a/plugin/src/createSignal.lua b/plugin/src/createSignal.lua index 965a452d..f6a00ddf 100644 --- a/plugin/src/createSignal.lua +++ b/plugin/src/createSignal.lua @@ -50,4 +50,4 @@ local function createSignal() } end -return createSignal \ No newline at end of file +return createSignal diff --git a/plugin/src/ignorePlaceIds.lua b/plugin/src/ignorePlaceIds.lua index 40ad8f58..cc3d1c28 100644 --- a/plugin/src/ignorePlaceIds.lua +++ b/plugin/src/ignorePlaceIds.lua @@ -5,23 +5,23 @@ --]] return { - ["0"] = true, -- Local file - ["95206881"] = true, -- Baseplate - ["6560363541"] = true, -- Classic Baseplate - ["95206192"] = true, -- Flat Terrain - ["13165709401"] = true, -- Modern City - ["520390648"] = true, -- Village - ["203810088"] = true, -- Castle - ["366130569"] = true, -- Suburban - ["215383192"] = true, -- Racing - ["264719325"] = true, -- Pirate Island - ["203812057"] = true, -- Obby - ["379736082"] = true, -- Starting Place - ["301530843"] = true, -- Line Runner - ["92721754"] = true, -- Capture The Flag - ["301529772"] = true, -- Team/FFA Arena - ["203885589"] = true, -- Combat - ["10275826693"] = true, -- Concert - ["5353920686"] = true, -- Move It Simulator - ["6936227200"] = true, -- Mansion Of Wonder + ["0"] = true, -- Local file + ["95206881"] = true, -- Baseplate + ["6560363541"] = true, -- Classic Baseplate + ["95206192"] = true, -- Flat Terrain + ["13165709401"] = true, -- Modern City + ["520390648"] = true, -- Village + ["203810088"] = true, -- Castle + ["366130569"] = true, -- Suburban + ["215383192"] = true, -- Racing + ["264719325"] = true, -- Pirate Island + ["203812057"] = true, -- Obby + ["379736082"] = true, -- Starting Place + ["301530843"] = true, -- Line Runner + ["92721754"] = true, -- Capture The Flag + ["301529772"] = true, -- Team/FFA Arena + ["203885589"] = true, -- Combat + ["10275826693"] = true, -- Concert + ["5353920686"] = true, -- Move It Simulator + ["6936227200"] = true, -- Mansion Of Wonder } diff --git a/plugin/src/init.server.lua b/plugin/src/init.server.lua index da7a38ce..c14487ff 100644 --- a/plugin/src/init.server.lua +++ b/plugin/src/init.server.lua @@ -17,7 +17,7 @@ Log.setLogLevelThunk(function() end) local app = Roact.createElement(App, { - plugin = plugin + plugin = plugin, }) local tree = Roact.mount(app, game:GetService("CoreGui"), "Rojo UI") diff --git a/plugin/src/invariant.lua b/plugin/src/invariant.lua index 37f4d756..d1b7ccc8 100644 --- a/plugin/src/invariant.lua +++ b/plugin/src/invariant.lua @@ -1,4 +1,3 @@ - local Packages = script.Parent.Parent.Packages local Fmt = require(Packages.Fmt) @@ -17,10 +16,10 @@ else message = Fmt.fmt(message, ...) local fullMessage = string.format( - "Rojo detected an invariant violation within itself:\n" .. - "%s\n\n" .. - "This is a bug in Rojo. Please file an issue:\n" .. - "https://github.com/rojo-rbx/rojo/issues", + "Rojo detected an invariant violation within itself:\n" + .. "%s\n\n" + .. "This is a bug in Rojo. Please file an issue:\n" + .. "https://github.com/rojo-rbx/rojo/issues", message ) diff --git a/plugin/src/soundPlayer.lua b/plugin/src/soundPlayer.lua index c1d018c2..32592720 100644 --- a/plugin/src/soundPlayer.lua +++ b/plugin/src/soundPlayer.lua @@ -2,12 +2,10 @@ local plugin = plugin or script:FindFirstAncestorWhichIsA("Plugin") local widget = nil if plugin then - widget = plugin:CreateDockWidgetPluginGui("Rojo_soundPlayer", DockWidgetPluginGuiInfo.new( - Enum.InitialDockState.Float, - false, true, - 10, 10, - 10, 10 - )) + widget = plugin:CreateDockWidgetPluginGui( + "Rojo_soundPlayer", + DockWidgetPluginGuiInfo.new(Enum.InitialDockState.Float, false, true, 10, 10, 10, 10) + ) widget.Name = "Rojo_soundPlayer" widget.Title = "Rojo Sound Player" end @@ -22,7 +20,9 @@ function SoundPlayer.new(settings) end function SoundPlayer:play(soundId) - if self.settings and self.settings:get("playSounds") == false then return end + if self.settings and self.settings:get("playSounds") == false then + return + end local sound = Instance.new("Sound") sound.SoundId = soundId diff --git a/plugin/src/strict.lua b/plugin/src/strict.lua index 239c84a2..f50ea740 100644 --- a/plugin/src/strict.lua +++ b/plugin/src/strict.lua @@ -21,4 +21,4 @@ return function(nameOrTarget, target) else return strictInner("", target) end -end \ No newline at end of file +end From 539cd0d418c06cd5b61701a28f7058891279099a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F?= <34089907+Barocena@users.noreply.github.com> Date: Tue, 19 Sep 2023 08:56:39 +0300 Subject: [PATCH 1333/1504] Create .git-blame-ignore-revs & Add Stylua pr (#787) adds stylua pr to ignore so it doesn't show on git blame history --- .git-blame-ignore-revs | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..dcba947a --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,2 @@ +# stylua formatting +0f8e1625d572a5fe0f7b5c08653ff92cc837d346 From bb8dd1402d6f7d03c3589cd769261be50f220593 Mon Sep 17 00:00:00 2001 From: Sasial <44125644+sasial-dev@users.noreply.github.com> Date: Sun, 24 Sep 2023 06:28:09 +1000 Subject: [PATCH 1334/1504] Add `RunContext` support for script outputs (#765) Resolves #667 This PR: - Introduces a new field in the project file: `scriptType` which has the default value of `Class` (in parity with previous versions), but can also be `RunContext`. - This is then passed to `InstanceContext` from the `Project` struct. - This then changes the RunContext in the lua `snapshot_middleware` --------- Co-authored-by: Micah --- CHANGELOG.md | 7 + ..._end__tests__build__nested_runcontext.snap | 35 +++ ...d__tests__build__script_meta_disabled.snap | 1 + ...o_end__tests__build__server_in_folder.snap | 1 + ...end_to_end__tests__build__server_init.snap | 1 + .../nested_runcontext/default.project.json | 13 + .../nested_runcontext/folder1/test.server.lua | 0 .../folder2/default.project.json | 7 + .../folder2/folder3/test.server.lua | 0 ...d_to_end__tests__serve__scripts_all-2.snap | 2 + ...end_to_end__tests__serve__scripts_all.snap | 2 + src/project.rs | 12 +- src/serve_session.rs | 3 +- src/snapshot/metadata.rs | 30 +- ..._snapshot__tests__apply__add_property.snap | 4 +- ...s__apply__remove_property_after_patch.snap | 4 +- ...tests__apply__remove_property_initial.snap | 4 +- ...tests__apply__set_name_and_class_name.snap | 4 +- ...__snapshot__tests__compute__add_child.snap | 3 +- src/snapshot_middleware/lua.rs | 292 +++++++++++++++--- src/snapshot_middleware/mod.rs | 2 +- src/snapshot_middleware/project.rs | 10 +- ...t_middleware__csv__test__csv_from_vfs.snap | 3 +- ..._middleware__csv__test__csv_with_meta.snap | 3 +- ...t_middleware__dir__test__empty_folder.snap | 3 +- ...ddleware__dir__test__folder_in_folder.snap | 6 +- ...leware__json__test__instance_from_vfs.snap | 3 +- ...are__json_model__test__model_from_vfs.snap | 6 +- ...on_model__test__model_from_vfs_legacy.snap | 6 +- ...re__lua__test__class_client_from_vfs.snap} | 3 +- ...re__lua__test__class_module_from_vfs.snap} | 3 +- ...e__lua__test__class_module_with_meta.snap} | 3 +- ...re__lua__test__class_script_disabled.snap} | 5 +- ...e__lua__test__class_script_with_meta.snap} | 5 +- ...re__lua__test__class_server_from_vfs.snap} | 5 +- ...ware__lua__test__init_module_from_vfs.snap | 3 +- ...lua__test__runcontext_client_from_vfs.snap | 23 ++ ...lua__test__runcontext_module_from_vfs.snap | 21 ++ ...ua__test__runcontext_module_with_meta.snap | 21 ++ ...lua__test__runcontext_script_disabled.snap | 25 ++ ...ua__test__runcontext_script_with_meta.snap | 23 ++ ...lua__test__runcontext_server_from_vfs.snap | 23 ++ ...oject__test__project_from_direct_file.snap | 3 +- ...e__project__test__project_from_folder.snap | 3 +- ...test__project_path_property_overrides.snap | 3 +- ..._project__test__project_with_children.snap | 6 +- ...t__test__project_with_path_to_project.snap | 3 +- ...ct_with_path_to_project_with_children.snap | 6 +- ...oject__test__project_with_path_to_txt.snap | 3 +- ...est__project_with_resolved_properties.snap | 3 +- ...t__project_with_unresolved_properties.snap | 3 +- ...leware__toml__test__instance_from_vfs.snap | 3 +- ...dleware__txt__test__instance_from_vfs.snap | 3 +- src/snapshot_middleware/util.rs | 5 + tests/tests/build.rs | 1 + tests/tests/serve.rs | 22 +- 56 files changed, 602 insertions(+), 95 deletions(-) create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__nested_runcontext.snap create mode 100644 rojo-test/build-tests/nested_runcontext/default.project.json create mode 100644 rojo-test/build-tests/nested_runcontext/folder1/test.server.lua create mode 100644 rojo-test/build-tests/nested_runcontext/folder2/default.project.json create mode 100644 rojo-test/build-tests/nested_runcontext/folder2/folder3/test.server.lua rename src/snapshot_middleware/snapshots/{librojo__snapshot_middleware__lua__test__client_from_vfs.snap => librojo__snapshot_middleware__lua__test__class_client_from_vfs.snap} (90%) rename src/snapshot_middleware/snapshots/{librojo__snapshot_middleware__lua__test__module_from_vfs.snap => librojo__snapshot_middleware__lua__test__class_module_from_vfs.snap} (89%) rename src/snapshot_middleware/snapshots/{librojo__snapshot_middleware__lua__test__module_with_meta.snap => librojo__snapshot_middleware__lua__test__class_module_with_meta.snap} (89%) rename src/snapshot_middleware/snapshots/{librojo__snapshot_middleware__lua__test__script_disabled.snap => librojo__snapshot_middleware__lua__test__class_script_disabled.snap} (85%) rename src/snapshot_middleware/snapshots/{librojo__snapshot_middleware__lua__test__script_with_meta.snap => librojo__snapshot_middleware__lua__test__class_script_with_meta.snap} (84%) rename src/snapshot_middleware/snapshots/{librojo__snapshot_middleware__lua__test__server_from_vfs.snap => librojo__snapshot_middleware__lua__test__class_server_from_vfs.snap} (84%) create mode 100644 src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_client_from_vfs.snap create mode 100644 src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_from_vfs.snap create mode 100644 src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_with_meta.snap create mode 100644 src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_disabled.snap create mode 100644 src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_with_meta.snap create mode 100644 src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_server_from_vfs.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index 7f26d92e..f6e171f1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,12 @@ * Added support for `Terrain.MaterialColors` ([#770]) * Allow `Terrain` to be specified without a classname ([#771]) * Add Confirmation Behavior setting ([#774]) +* Added the `emitLegacyScripts` field to the project format ([#765]). The behavior is outlined below: + +| `emitLegacyScripts` Value | Action Taken by Rojo | +|----------------------------|--------------------------------------------------------------------------------------------------------------------| +| false | Rojo emits Scripts with the appropriate `RunContext` for `*.client.lua` and `*.server.lua` files in the project. | +| true (default) | Rojo emits LocalScripts and Scripts with legacy `RunContext` (same behavior as previously). | [#761]: https://github.com/rojo-rbx/rojo/pull/761 [#745]: https://github.com/rojo-rbx/rojo/pull/745 @@ -53,6 +59,7 @@ [#748]: https://github.com/rojo-rbx/rojo/pull/748 [#755]: https://github.com/rojo-rbx/rojo/pull/755 [#760]: https://github.com/rojo-rbx/rojo/pull/760 +[#765]: https://github.com/rojo-rbx/rojo/pull/765 [#770]: https://github.com/rojo-rbx/rojo/pull/770 [#771]: https://github.com/rojo-rbx/rojo/pull/771 [#774]: https://github.com/rojo-rbx/rojo/pull/774 diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__nested_runcontext.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__nested_runcontext.snap new file mode 100644 index 00000000..0ddc3051 --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__nested_runcontext.snap @@ -0,0 +1,35 @@ +--- +source: tests/tests/build.rs +expression: contents +--- + + + + nested_runcontext + + + + folder1 + + + + test + 1 + + + + + + + folder2 + + + + test + 0 + + + + + + diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__script_meta_disabled.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__script_meta_disabled.snap index 0876056e..28354bd6 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__script_meta_disabled.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__script_meta_disabled.snap @@ -11,6 +11,7 @@ expression: contents hello true + 0 -- This script should be marked 'Disabled' diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__server_in_folder.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__server_in_folder.snap index 282889d0..c9806d00 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__server_in_folder.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__server_in_folder.snap @@ -10,6 +10,7 @@ expression: contents serverScript + 0 -- This is a Lua server script diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__server_init.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__server_init.snap index 070b7012..5858d5e0 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__server_init.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__server_init.snap @@ -6,6 +6,7 @@ expression: contents server_init + 0 return "From folder/init.server.lua" diff --git a/rojo-test/build-tests/nested_runcontext/default.project.json b/rojo-test/build-tests/nested_runcontext/default.project.json new file mode 100644 index 00000000..5327be9a --- /dev/null +++ b/rojo-test/build-tests/nested_runcontext/default.project.json @@ -0,0 +1,13 @@ +{ + "name": "nested_runcontext", + "emitLegacyScripts": false, + "tree": { + "$className": "Folder", + "folder1": { + "$path": "folder1" + }, + "folder2": { + "$path": "folder2" + } + } +} diff --git a/rojo-test/build-tests/nested_runcontext/folder1/test.server.lua b/rojo-test/build-tests/nested_runcontext/folder1/test.server.lua new file mode 100644 index 00000000..e69de29b diff --git a/rojo-test/build-tests/nested_runcontext/folder2/default.project.json b/rojo-test/build-tests/nested_runcontext/folder2/default.project.json new file mode 100644 index 00000000..67feff44 --- /dev/null +++ b/rojo-test/build-tests/nested_runcontext/folder2/default.project.json @@ -0,0 +1,7 @@ +{ + "name": "nested_runcontext", + "emitLegacyScripts": true, + "tree": { + "$path": "folder3" + } +} diff --git a/rojo-test/build-tests/nested_runcontext/folder2/folder3/test.server.lua b/rojo-test/build-tests/nested_runcontext/folder2/folder3/test.server.lua new file mode 100644 index 00000000..e69de29b diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all-2.snap index 78dcebea..49d8148b 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all-2.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all-2.snap @@ -24,6 +24,8 @@ instances: Name: bar Parent: id-2 Properties: + RunContext: + Enum: 0 Source: String: "-- Hello, from bar!" id-4: diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all.snap index 52efebac..62e5ceef 100644 --- a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all.snap +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__scripts_all.snap @@ -24,6 +24,8 @@ instances: Name: bar Parent: id-2 Properties: + RunContext: + Enum: 0 Source: String: "-- Hello, from bar!" id-4: diff --git a/src/project.rs b/src/project.rs index e70005d0..1a645b76 100644 --- a/src/project.rs +++ b/src/project.rs @@ -8,7 +8,9 @@ use std::{ use serde::{Deserialize, Serialize}; use thiserror::Error; -use crate::{glob::Glob, resolution::UnresolvedValue}; +use crate::{ + glob::Glob, resolution::UnresolvedValue, snapshot_middleware::emit_legacy_scripts_default, +}; static PROJECT_FILENAME: &str = "default.project.json"; @@ -73,6 +75,14 @@ pub struct Project { #[serde(skip_serializing_if = "Option::is_none")] pub serve_address: Option, + /// Determines if rojo should emit scripts with the appropriate `RunContext` for `*.client.lua` and `*.server.lua` files in the project. + /// Or, if rojo should keep the legacy behavior of emitting LocalScripts and Scripts with legacy Runcontext + #[serde( + default = "emit_legacy_scripts_default", + skip_serializing_if = "Option::is_none" + )] + pub emit_legacy_scripts: Option, + /// A list of globs, relative to the folder the project file is in, that /// match files that should be excluded if Rojo encounters them. #[serde(default, skip_serializing_if = "Vec::is_empty")] diff --git a/src/serve_session.rs b/src/serve_session.rs index 9dab5446..85ae7793 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -123,7 +123,8 @@ impl ServeSession { let root_id = tree.get_root_id(); - let instance_context = InstanceContext::default(); + let instance_context = + InstanceContext::with_emit_legacy_scripts(root_project.emit_legacy_scripts); log::trace!("Generating snapshot of instances from VFS"); let snapshot = snapshot_from_vfs(&instance_context, &vfs, start_path)?; diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index 192a0001..1a3273ed 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -6,7 +6,10 @@ use std::{ use serde::{Deserialize, Serialize}; -use crate::{glob::Glob, path_serializer, project::ProjectNode}; +use crate::{ + glob::Glob, path_serializer, project::ProjectNode, + snapshot_middleware::emit_legacy_scripts_default, +}; /// Rojo-specific metadata that can be associated with an instance or a snapshot /// of an instance. @@ -103,9 +106,26 @@ impl Default for InstanceMetadata { pub struct InstanceContext { #[serde(skip_serializing_if = "Vec::is_empty")] pub path_ignore_rules: Arc>, + pub emit_legacy_scripts: bool, } impl InstanceContext { + pub fn new() -> Self { + Self { + path_ignore_rules: Arc::new(Vec::new()), + emit_legacy_scripts: emit_legacy_scripts_default().unwrap(), + } + } + + pub fn with_emit_legacy_scripts(emit_legacy_scripts: Option) -> Self { + Self { + emit_legacy_scripts: emit_legacy_scripts + .or_else(emit_legacy_scripts_default) + .unwrap(), + ..Self::new() + } + } + /// Extend the list of ignore rules in the context with the given new rules. pub fn add_path_ignore_rules(&mut self, new_rules: I) where @@ -123,13 +143,15 @@ impl InstanceContext { let rules = Arc::make_mut(&mut self.path_ignore_rules); rules.extend(new_rules); } + + pub fn set_emit_legacy_scripts(&mut self, emit_legacy_scripts: bool) { + self.emit_legacy_scripts = emit_legacy_scripts; + } } impl Default for InstanceContext { fn default() -> Self { - InstanceContext { - path_ignore_rules: Arc::new(Vec::new()), - } + Self::new() } } diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap index 9d5e9d77..0d594dbc 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap @@ -1,7 +1,6 @@ --- source: src/snapshot/tests/apply.rs expression: tree_view - --- id: id-1 name: ROOT @@ -12,6 +11,7 @@ properties: metadata: ignore_unknown_instances: false relevant_paths: [] - context: {} + context: + emit_legacy_scripts: true children: [] diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap index f8706912..b6fcbbd0 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap @@ -9,5 +9,7 @@ properties: {} metadata: ignore_unknown_instances: false relevant_paths: [] - context: {} + context: + emit_legacy_scripts: true children: [] + diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap index 936658f1..84b3c3d1 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap @@ -1,7 +1,6 @@ --- source: src/snapshot/tests/apply.rs expression: tree_view - --- id: id-1 name: ROOT @@ -12,6 +11,7 @@ properties: metadata: ignore_unknown_instances: false relevant_paths: [] - context: {} + context: + emit_legacy_scripts: true children: [] diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap index 634b4d64..325c86f3 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap @@ -9,5 +9,7 @@ properties: {} metadata: ignore_unknown_instances: false relevant_paths: [] - context: {} + context: + emit_legacy_scripts: true children: [] + diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap index c4695b7c..94ddf12f 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap @@ -10,7 +10,8 @@ added_instances: metadata: ignore_unknown_instances: false relevant_paths: [] - context: {} + context: + emit_legacy_scripts: true name: New class_name: Folder properties: {} diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index ba221626..1307b066 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -1,8 +1,8 @@ -use std::{path::Path, str}; +use std::{collections::HashMap, path::Path, str}; use anyhow::Context; -use maplit::hashmap; use memofs::{IoResultExt, Vfs}; +use rbx_dom_weak::types::Enum; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; @@ -12,6 +12,13 @@ use super::{ util::match_trailing, }; +#[derive(Debug)] +enum ScriptType { + Server, + Client, + Module, +} + /// Core routine for turning Lua files into snapshots. pub fn snapshot_lua( context: &InstanceContext, @@ -20,36 +27,58 @@ pub fn snapshot_lua( ) -> anyhow::Result> { let file_name = path.file_name().unwrap().to_string_lossy(); - let (class_name, instance_name) = if let Some(name) = match_trailing(&file_name, ".server.lua") + let run_context_enums = &rbx_reflection_database::get() + .enums + .get("RunContext") + .expect("Unable to get RunContext enums!") + .items; + + let (script_type, instance_name) = if let Some(name) = match_trailing(&file_name, ".server.lua") { - ("Script", name) + (ScriptType::Server, name) } else if let Some(name) = match_trailing(&file_name, ".client.lua") { - ("LocalScript", name) + (ScriptType::Client, name) } else if let Some(name) = match_trailing(&file_name, ".lua") { - ("ModuleScript", name) + (ScriptType::Module, name) } else if let Some(name) = match_trailing(&file_name, ".server.luau") { - ("Script", name) + (ScriptType::Server, name) } else if let Some(name) = match_trailing(&file_name, ".client.luau") { - ("LocalScript", name) + (ScriptType::Client, name) } else if let Some(name) = match_trailing(&file_name, ".luau") { - ("ModuleScript", name) + (ScriptType::Module, name) } else { return Ok(None); }; + let (class_name, run_context) = match (context.emit_legacy_scripts, script_type) { + (false, ScriptType::Server) => ("Script", run_context_enums.get("Server")), + (false, ScriptType::Client) => ("Script", run_context_enums.get("Client")), + (true, ScriptType::Server) => ("Script", run_context_enums.get("Legacy")), + (true, ScriptType::Client) => ("LocalScript", None), + (_, ScriptType::Module) => ("ModuleScript", None), + }; + let contents = vfs.read(path)?; let contents_str = str::from_utf8(&contents) .with_context(|| format!("File was not valid UTF-8: {}", path.display()))? .to_owned(); + let mut properties = HashMap::with_capacity(2); + properties.insert("Source".to_owned(), contents_str.into()); + + if let Some(run_context) = run_context { + properties.insert( + "RunContext".to_owned(), + Enum::from_u32(run_context.to_owned()).into(), + ); + } + let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); let mut snapshot = InstanceSnapshot::new() .name(instance_name) .class_name(class_name) - .properties(hashmap! { - "Source".to_owned() => contents_str.into(), - }) + .properties(properties) .metadata( InstanceMetadata::new() .instigating_source(path) @@ -107,26 +136,53 @@ pub fn snapshot_lua_init( mod test { use super::*; + use maplit::hashmap; use memofs::{InMemoryFs, VfsSnapshot}; #[test] - fn module_from_vfs() { + fn class_module_from_vfs() { let mut imfs = InMemoryFs::new(); imfs.load_snapshot("/foo.lua", VfsSnapshot::file("Hello there!")) .unwrap(); let mut vfs = Vfs::new(imfs); - let instance_snapshot = - snapshot_lua(&InstanceContext::default(), &mut vfs, Path::new("/foo.lua")) - .unwrap() - .unwrap(); + let instance_snapshot = snapshot_lua( + &InstanceContext::with_emit_legacy_scripts(Some(true)), + &mut vfs, + Path::new("/foo.lua"), + ) + .unwrap() + .unwrap(); - insta::assert_yaml_snapshot!(instance_snapshot); + insta::with_settings!({ sort_maps => true }, { + insta::assert_yaml_snapshot!(instance_snapshot); + }); } #[test] - fn server_from_vfs() { + fn runcontext_module_from_vfs() { + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo.lua", VfsSnapshot::file("Hello there!")) + .unwrap(); + + let mut vfs = Vfs::new(imfs); + + let instance_snapshot = snapshot_lua( + &InstanceContext::with_emit_legacy_scripts(Some(false)), + &mut vfs, + Path::new("/foo.lua"), + ) + .unwrap() + .unwrap(); + + insta::with_settings!({ sort_maps => true }, { + insta::assert_yaml_snapshot!(instance_snapshot); + }); + } + + #[test] + fn class_server_from_vfs() { let mut imfs = InMemoryFs::new(); imfs.load_snapshot("/foo.server.lua", VfsSnapshot::file("Hello there!")) .unwrap(); @@ -134,18 +190,41 @@ mod test { let mut vfs = Vfs::new(imfs); let instance_snapshot = snapshot_lua( - &InstanceContext::default(), + &InstanceContext::with_emit_legacy_scripts(Some(true)), &mut vfs, Path::new("/foo.server.lua"), ) .unwrap() .unwrap(); - insta::assert_yaml_snapshot!(instance_snapshot); + insta::with_settings!({ sort_maps => true }, { + insta::assert_yaml_snapshot!(instance_snapshot); + }); } #[test] - fn client_from_vfs() { + fn runcontext_server_from_vfs() { + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo.server.lua", VfsSnapshot::file("Hello there!")) + .unwrap(); + + let mut vfs = Vfs::new(imfs); + + let instance_snapshot = snapshot_lua( + &InstanceContext::with_emit_legacy_scripts(Some(false)), + &mut vfs, + Path::new("/foo.server.lua"), + ) + .unwrap() + .unwrap(); + + insta::with_settings!({ sort_maps => true }, { + insta::assert_yaml_snapshot!(instance_snapshot); + }); + } + + #[test] + fn class_client_from_vfs() { let mut imfs = InMemoryFs::new(); imfs.load_snapshot("/foo.client.lua", VfsSnapshot::file("Hello there!")) .unwrap(); @@ -153,14 +232,37 @@ mod test { let mut vfs = Vfs::new(imfs); let instance_snapshot = snapshot_lua( - &InstanceContext::default(), + &InstanceContext::with_emit_legacy_scripts(Some(true)), &mut vfs, Path::new("/foo.client.lua"), ) .unwrap() .unwrap(); - insta::assert_yaml_snapshot!(instance_snapshot); + insta::with_settings!({ sort_maps => true }, { + insta::assert_yaml_snapshot!(instance_snapshot); + }); + } + + #[test] + fn runcontext_client_from_vfs() { + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo.client.lua", VfsSnapshot::file("Hello there!")) + .unwrap(); + + let mut vfs = Vfs::new(imfs); + + let instance_snapshot = snapshot_lua( + &InstanceContext::with_emit_legacy_scripts(Some(false)), + &mut vfs, + Path::new("/foo.client.lua"), + ) + .unwrap() + .unwrap(); + + insta::with_settings!({ sort_maps => true }, { + insta::assert_yaml_snapshot!(instance_snapshot); + }); } #[ignore = "init.lua functionality has moved to the root snapshot function"] @@ -177,16 +279,21 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = - snapshot_lua(&InstanceContext::default(), &mut vfs, Path::new("/root")) - .unwrap() - .unwrap(); + let instance_snapshot = snapshot_lua( + &InstanceContext::with_emit_legacy_scripts(Some(true)), + &mut vfs, + Path::new("/root"), + ) + .unwrap() + .unwrap(); - insta::assert_yaml_snapshot!(instance_snapshot); + insta::with_settings!({ sort_maps => true }, { + insta::assert_yaml_snapshot!(instance_snapshot); + }); } #[test] - fn module_with_meta() { + fn class_module_with_meta() { let mut imfs = InMemoryFs::new(); imfs.load_snapshot("/foo.lua", VfsSnapshot::file("Hello there!")) .unwrap(); @@ -204,16 +311,53 @@ mod test { let mut vfs = Vfs::new(imfs); - let instance_snapshot = - snapshot_lua(&InstanceContext::default(), &mut vfs, Path::new("/foo.lua")) - .unwrap() - .unwrap(); + let instance_snapshot = snapshot_lua( + &InstanceContext::with_emit_legacy_scripts(Some(true)), + &mut vfs, + Path::new("/foo.lua"), + ) + .unwrap() + .unwrap(); - insta::assert_yaml_snapshot!(instance_snapshot); + insta::with_settings!({ sort_maps => true }, { + insta::assert_yaml_snapshot!(instance_snapshot); + }); } #[test] - fn script_with_meta() { + fn runcontext_module_with_meta() { + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo.lua", VfsSnapshot::file("Hello there!")) + .unwrap(); + imfs.load_snapshot( + "/foo.meta.json", + VfsSnapshot::file( + r#" + { + "ignoreUnknownInstances": true + } + "#, + ), + ) + .unwrap(); + + let mut vfs = Vfs::new(imfs); + + let instance_snapshot = snapshot_lua( + &InstanceContext::with_emit_legacy_scripts(Some(false)), + &mut vfs, + Path::new("/foo.lua"), + ) + .unwrap() + .unwrap(); + + insta::with_settings!({ sort_maps => true }, { + insta::assert_yaml_snapshot!(instance_snapshot); + }); + } + + #[test] + fn class_script_with_meta() { let mut imfs = InMemoryFs::new(); imfs.load_snapshot("/foo.server.lua", VfsSnapshot::file("Hello there!")) .unwrap(); @@ -232,18 +376,52 @@ mod test { let mut vfs = Vfs::new(imfs); let instance_snapshot = snapshot_lua( - &InstanceContext::default(), + &InstanceContext::with_emit_legacy_scripts(Some(true)), &mut vfs, Path::new("/foo.server.lua"), ) .unwrap() .unwrap(); - insta::assert_yaml_snapshot!(instance_snapshot); + insta::with_settings!({ sort_maps => true }, { + insta::assert_yaml_snapshot!(instance_snapshot); + }); } #[test] - fn script_disabled() { + fn runcontext_script_with_meta() { + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/foo.server.lua", VfsSnapshot::file("Hello there!")) + .unwrap(); + imfs.load_snapshot( + "/foo.meta.json", + VfsSnapshot::file( + r#" + { + "ignoreUnknownInstances": true + } + "#, + ), + ) + .unwrap(); + + let mut vfs = Vfs::new(imfs); + + let instance_snapshot = snapshot_lua( + &InstanceContext::with_emit_legacy_scripts(Some(false)), + &mut vfs, + Path::new("/foo.server.lua"), + ) + .unwrap() + .unwrap(); + + insta::with_settings!({ sort_maps => true }, { + insta::assert_yaml_snapshot!(instance_snapshot); + }); + } + + #[test] + fn class_script_disabled() { let mut imfs = InMemoryFs::new(); imfs.load_snapshot("/bar.server.lua", VfsSnapshot::file("Hello there!")) .unwrap(); @@ -264,7 +442,41 @@ mod test { let mut vfs = Vfs::new(imfs); let instance_snapshot = snapshot_lua( - &InstanceContext::default(), + &InstanceContext::with_emit_legacy_scripts(Some(true)), + &mut vfs, + Path::new("/bar.server.lua"), + ) + .unwrap() + .unwrap(); + + insta::with_settings!({ sort_maps => true }, { + insta::assert_yaml_snapshot!(instance_snapshot); + }); + } + + #[test] + fn runcontext_script_disabled() { + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("/bar.server.lua", VfsSnapshot::file("Hello there!")) + .unwrap(); + imfs.load_snapshot( + "/bar.meta.json", + VfsSnapshot::file( + r#" + { + "properties": { + "Disabled": true + } + } + "#, + ), + ) + .unwrap(); + + let mut vfs = Vfs::new(imfs); + + let instance_snapshot = snapshot_lua( + &InstanceContext::with_emit_legacy_scripts(Some(false)), &mut vfs, Path::new("/bar.server.lua"), ) diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index c690a223..d8cd3940 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -38,7 +38,7 @@ use self::{ util::PathExt, }; -pub use self::project::snapshot_project_node; +pub use self::{project::snapshot_project_node, util::emit_legacy_scripts_default}; /// The main entrypoint to the snapshot function. This function can be pointed /// at any path and will return something if Rojo knows how to deal with it. diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index a451abc9..d1b4a2e4 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -12,7 +12,7 @@ use crate::{ }, }; -use super::snapshot_from_vfs; +use super::{emit_legacy_scripts_default, snapshot_from_vfs}; pub fn snapshot_project( context: &InstanceContext, @@ -30,6 +30,12 @@ pub fn snapshot_project( }); context.add_path_ignore_rules(rules); + context.set_emit_legacy_scripts( + project + .emit_legacy_scripts + .or_else(emit_legacy_scripts_default) + .unwrap(), + ); match snapshot_project_node(&context, path, &project.name, &project.tree, vfs, None)? { Some(found_snapshot) => { @@ -77,7 +83,7 @@ pub fn snapshot_project_node( let name = Cow::Owned(instance_name.to_owned()); let mut properties = HashMap::new(); let mut children = Vec::new(); - let mut metadata = InstanceMetadata::default(); + let mut metadata = InstanceMetadata::new().context(context); if let Some(path_node) = &node.path { let path = path_node.path(); diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap index 11a8d81c..50ce53c1 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap @@ -10,7 +10,8 @@ metadata: relevant_paths: - /foo.csv - /foo.meta.json - context: {} + context: + emit_legacy_scripts: true name: foo class_name: LocalizationTable properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap index eda82606..c91924f8 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap @@ -10,7 +10,8 @@ metadata: relevant_paths: - /foo.csv - /foo.meta.json - context: {} + context: + emit_legacy_scripts: true name: foo class_name: LocalizationTable properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap index e59da8db..4c0dcbbf 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap @@ -17,7 +17,8 @@ metadata: - /foo/init.client.lua - /foo/init.client.luau - /foo/init.csv - context: {} + context: + emit_legacy_scripts: true name: foo class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap index 8c2ee9cc..6238fe68 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap @@ -17,7 +17,8 @@ metadata: - /foo/init.client.lua - /foo/init.client.luau - /foo/init.csv - context: {} + context: + emit_legacy_scripts: true name: foo class_name: Folder properties: {} @@ -37,7 +38,8 @@ children: - /foo/Child/init.client.lua - /foo/Child/init.client.luau - /foo/Child/init.csv - context: {} + context: + emit_legacy_scripts: true name: Child class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap index b1cca7cb..9cc320eb 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap @@ -10,7 +10,8 @@ metadata: relevant_paths: - /foo.json - /foo.meta.json - context: {} + context: + emit_legacy_scripts: true name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap index 5d4db1fc..e3ee581e 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap @@ -9,7 +9,8 @@ metadata: Path: /foo.model.json relevant_paths: - /foo.model.json - context: {} + context: + emit_legacy_scripts: true name: foo class_name: IntValue properties: @@ -20,7 +21,8 @@ children: metadata: ignore_unknown_instances: false relevant_paths: [] - context: {} + context: + emit_legacy_scripts: true name: The Child class_name: StringValue properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap index 5d4db1fc..e3ee581e 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap @@ -9,7 +9,8 @@ metadata: Path: /foo.model.json relevant_paths: - /foo.model.json - context: {} + context: + emit_legacy_scripts: true name: foo class_name: IntValue properties: @@ -20,7 +21,8 @@ children: metadata: ignore_unknown_instances: false relevant_paths: [] - context: {} + context: + emit_legacy_scripts: true name: The Child class_name: StringValue properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__client_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_client_from_vfs.snap similarity index 90% rename from src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__client_from_vfs.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_client_from_vfs.snap index 40b4bbe2..5f5f6e9a 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__client_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_client_from_vfs.snap @@ -10,7 +10,8 @@ metadata: relevant_paths: - /foo.client.lua - /foo.meta.json - context: {} + context: + emit_legacy_scripts: true name: foo class_name: LocalScript properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_from_vfs.snap similarity index 89% rename from src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_from_vfs.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_from_vfs.snap index 6877e9a9..de2471b9 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_from_vfs.snap @@ -10,7 +10,8 @@ metadata: relevant_paths: - /foo.lua - /foo.meta.json - context: {} + context: + emit_legacy_scripts: true name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_with_meta.snap similarity index 89% rename from src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_with_meta.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_with_meta.snap index 8dcc57a9..32d70c70 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__module_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_with_meta.snap @@ -10,7 +10,8 @@ metadata: relevant_paths: - /foo.lua - /foo.meta.json - context: {} + context: + emit_legacy_scripts: true name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_disabled.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_disabled.snap similarity index 85% rename from src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_disabled.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_disabled.snap index 3f040877..2c5546a5 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_disabled.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_disabled.snap @@ -10,12 +10,15 @@ metadata: relevant_paths: - /bar.server.lua - /bar.meta.json - context: {} + context: + emit_legacy_scripts: true name: bar class_name: Script properties: Disabled: Bool: true + RunContext: + Enum: 0 Source: String: Hello there! children: [] diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_with_meta.snap similarity index 84% rename from src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_with_meta.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_with_meta.snap index 6bdd2a38..e4e31ff9 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__script_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_with_meta.snap @@ -10,10 +10,13 @@ metadata: relevant_paths: - /foo.server.lua - /foo.meta.json - context: {} + context: + emit_legacy_scripts: true name: foo class_name: Script properties: + RunContext: + Enum: 0 Source: String: Hello there! children: [] diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__server_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_server_from_vfs.snap similarity index 84% rename from src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__server_from_vfs.snap rename to src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_server_from_vfs.snap index 63d33a0a..b70b9cc2 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__server_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_server_from_vfs.snap @@ -10,10 +10,13 @@ metadata: relevant_paths: - /foo.server.lua - /foo.meta.json - context: {} + context: + emit_legacy_scripts: true name: foo class_name: Script properties: + RunContext: + Enum: 0 Source: String: Hello there! children: [] diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap index 47340789..0077f4c0 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap @@ -13,7 +13,8 @@ metadata: - /root/init.lua - /root/init.server.lua - /root/init.client.lua - context: {} + context: + script_type: Class name: root class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_client_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_client_from_vfs.snap new file mode 100644 index 00000000..6ad72d08 --- /dev/null +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_client_from_vfs.snap @@ -0,0 +1,23 @@ +--- +source: src/snapshot_middleware/lua.rs +expression: instance_snapshot +--- +snapshot_id: "00000000000000000000000000000000" +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /foo.client.lua + relevant_paths: + - /foo.client.lua + - /foo.meta.json + context: + emit_legacy_scripts: false +name: foo +class_name: Script +properties: + RunContext: + Enum: 2 + Source: + String: Hello there! +children: [] + diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_from_vfs.snap new file mode 100644 index 00000000..83be811b --- /dev/null +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_from_vfs.snap @@ -0,0 +1,21 @@ +--- +source: src/snapshot_middleware/lua.rs +expression: instance_snapshot +--- +snapshot_id: "00000000000000000000000000000000" +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /foo.lua + relevant_paths: + - /foo.lua + - /foo.meta.json + context: + emit_legacy_scripts: false +name: foo +class_name: ModuleScript +properties: + Source: + String: Hello there! +children: [] + diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_with_meta.snap new file mode 100644 index 00000000..98a88ec7 --- /dev/null +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_with_meta.snap @@ -0,0 +1,21 @@ +--- +source: src/snapshot_middleware/lua.rs +expression: instance_snapshot +--- +snapshot_id: "00000000000000000000000000000000" +metadata: + ignore_unknown_instances: true + instigating_source: + Path: /foo.lua + relevant_paths: + - /foo.lua + - /foo.meta.json + context: + emit_legacy_scripts: false +name: foo +class_name: ModuleScript +properties: + Source: + String: Hello there! +children: [] + diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_disabled.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_disabled.snap new file mode 100644 index 00000000..c47b83dc --- /dev/null +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_disabled.snap @@ -0,0 +1,25 @@ +--- +source: src/snapshot_middleware/lua.rs +expression: instance_snapshot +--- +snapshot_id: "00000000000000000000000000000000" +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /bar.server.lua + relevant_paths: + - /bar.server.lua + - /bar.meta.json + context: + emit_legacy_scripts: false +name: bar +class_name: Script +properties: + Disabled: + Bool: true + RunContext: + Enum: 1 + Source: + String: Hello there! +children: [] + diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_with_meta.snap new file mode 100644 index 00000000..72d24206 --- /dev/null +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_with_meta.snap @@ -0,0 +1,23 @@ +--- +source: src/snapshot_middleware/lua.rs +expression: instance_snapshot +--- +snapshot_id: "00000000000000000000000000000000" +metadata: + ignore_unknown_instances: true + instigating_source: + Path: /foo.server.lua + relevant_paths: + - /foo.server.lua + - /foo.meta.json + context: + emit_legacy_scripts: false +name: foo +class_name: Script +properties: + RunContext: + Enum: 1 + Source: + String: Hello there! +children: [] + diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_server_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_server_from_vfs.snap new file mode 100644 index 00000000..2b902f96 --- /dev/null +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_server_from_vfs.snap @@ -0,0 +1,23 @@ +--- +source: src/snapshot_middleware/lua.rs +expression: instance_snapshot +--- +snapshot_id: "00000000000000000000000000000000" +metadata: + ignore_unknown_instances: false + instigating_source: + Path: /foo.server.lua + relevant_paths: + - /foo.server.lua + - /foo.meta.json + context: + emit_legacy_scripts: false +name: foo +class_name: Script +properties: + RunContext: + Enum: 1 + Source: + String: Hello there! +children: [] + diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap index 795b14c1..bd5db23d 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap @@ -9,7 +9,8 @@ metadata: Path: /foo/hello.project.json relevant_paths: - /foo/hello.project.json - context: {} + context: + emit_legacy_scripts: true name: direct-project class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_folder.snap index d3a91f3c..87aead09 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_folder.snap @@ -9,7 +9,8 @@ metadata: Path: /foo/default.project.json relevant_paths: - /foo/default.project.json - context: {} + context: + script_type: Class name: indirect-project class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap index 7427c9dc..77cb44c9 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap @@ -10,7 +10,8 @@ metadata: relevant_paths: - /foo/other.project.json - /foo/default.project.json - context: {} + context: + emit_legacy_scripts: true name: path-property-override class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap index b50eb1be..914a2f95 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap @@ -9,7 +9,8 @@ metadata: Path: /foo.project.json relevant_paths: - /foo.project.json - context: {} + context: + emit_legacy_scripts: true name: children class_name: Folder properties: {} @@ -24,7 +25,8 @@ children: - $className: Model - Folder relevant_paths: [] - context: {} + context: + emit_legacy_scripts: true name: Child class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap index d64a46e7..02e6ee0b 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap @@ -10,7 +10,8 @@ metadata: relevant_paths: - /foo/other.project.json - /foo/default.project.json - context: {} + context: + emit_legacy_scripts: true name: path-project class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap index 0ceb043a..baf64365 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap @@ -10,7 +10,8 @@ metadata: relevant_paths: - /foo/other.project.json - /foo/default.project.json - context: {} + context: + emit_legacy_scripts: true name: path-child-project class_name: Folder properties: {} @@ -25,7 +26,8 @@ children: - $className: Model - Folder relevant_paths: [] - context: {} + context: + emit_legacy_scripts: true name: SomeChild class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap index 51a222f9..223c366c 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap @@ -11,7 +11,8 @@ metadata: - /foo/other.txt - /foo/other.meta.json - /foo/default.project.json - context: {} + context: + emit_legacy_scripts: true name: path-project class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap index 9b8e91ef..eddb4e04 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap @@ -9,7 +9,8 @@ metadata: Path: /foo.project.json relevant_paths: - /foo.project.json - context: {} + context: + emit_legacy_scripts: true name: resolved-properties class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap index a07300bb..8bd6e28b 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap @@ -9,7 +9,8 @@ metadata: Path: /foo.project.json relevant_paths: - /foo.project.json - context: {} + context: + emit_legacy_scripts: true name: unresolved-properties class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap index 3529bf89..329bdbcd 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap @@ -10,7 +10,8 @@ metadata: relevant_paths: - /foo.toml - /foo.meta.json - context: {} + context: + emit_legacy_scripts: true name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap index b8a8d4af..aa3e0f06 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap @@ -10,7 +10,8 @@ metadata: relevant_paths: - /foo.txt - /foo.meta.json - context: {} + context: + emit_legacy_scripts: true name: foo class_name: StringValue properties: diff --git a/src/snapshot_middleware/util.rs b/src/snapshot_middleware/util.rs index 16648eae..625910b7 100644 --- a/src/snapshot_middleware/util.rs +++ b/src/snapshot_middleware/util.rs @@ -41,3 +41,8 @@ where .with_context(|| format!("Path did not end in {}: {}", suffix, path.display())) } } + +// TEMP function until rojo 8.0, when it can be replaced with bool::default (aka false) +pub fn emit_legacy_scripts_default() -> Option { + Some(true) +} diff --git a/tests/tests/build.rs b/tests/tests/build.rs index 4907449d..01e87da7 100644 --- a/tests/tests/build.rs +++ b/tests/tests/build.rs @@ -44,6 +44,7 @@ gen_build_tests! { json_model_legacy_name, module_in_folder, module_init, + nested_runcontext, optional, project_composed_default, project_composed_file, diff --git a/tests/tests/serve.rs b/tests/tests/serve.rs index 9cca9fac..d55d339b 100644 --- a/tests/tests/serve.rs +++ b/tests/tests/serve.rs @@ -1,6 +1,6 @@ use std::fs; -use insta::assert_yaml_snapshot; +use insta::{assert_yaml_snapshot, with_settings}; use tempfile::tempdir; use crate::rojo_test::{internable::InternAndRedact, serve_util::run_serve_test}; @@ -30,10 +30,12 @@ fn scripts() { assert_yaml_snapshot!("scripts_info", redactions.redacted_yaml(info)); let read_response = session.get_api_read(root_id).unwrap(); - assert_yaml_snapshot!( - "scripts_all", - read_response.intern_and_redact(&mut redactions, root_id) - ); + with_settings!({ sort_maps => true }, { + assert_yaml_snapshot!( + "scripts_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); + }); fs::write(session.path().join("src/foo.lua"), "Updated foo!").unwrap(); @@ -44,10 +46,12 @@ fn scripts() { ); let read_response = session.get_api_read(root_id).unwrap(); - assert_yaml_snapshot!( - "scripts_all-2", - read_response.intern_and_redact(&mut redactions, root_id) - ); + with_settings!({ sort_maps => true }, { + assert_yaml_snapshot!( + "scripts_all-2", + read_response.intern_and_redact(&mut redactions, root_id) + ); + }); }); } From d7277b5a5b3e1c57709c3cdf0c920b9b84f9bd8c Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Mon, 25 Sep 2023 16:13:01 -0700 Subject: [PATCH 1335/1504] Clean up changelog in preparation for Rojo 7.4.0 (#788) This PR aims to clean up the changelog in preparation for 7.4.0. We should focus on making changes clear to users with examples, removing any entries that they won't care about, and consolidating tightly related changes --------- Co-authored-by: boatbomber Co-authored-by: Micah <48431591+nezuo@users.noreply.github.com> --- CHANGELOG.md | 150 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 119 insertions(+), 31 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6e171f1..fc90f866 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,42 +1,130 @@ # Rojo Changelog ## Unreleased Changes -* Internally for themes, we use `Color3.fromHex` now instead of custom-made solution ([#761]). -* On failing to open a file from Roblox Studio, it is now logged appropriately instead of being ignored ([#745]). -* Significantly improved performance of `rojo sourcemap`. ([#668]) +### Additions +#### Project format +* Added support for `.toml` files to `$path` ([#633]) +* Added support for `Font` and `CFrame` attributes ([rbx-dom#299], [rbx-dom#296]) +* Added the `emitLegacyScripts` field to the project format ([#765]). The behavior is outlined below: + + | `emitLegacyScripts` Value | Action Taken by Rojo | + |---------------------------|------------------------------------------------------------------------------------------------------------------| + | false | Rojo emits Scripts with the appropriate `RunContext` for `*.client.lua` and `*.server.lua` files in the project. | + | true (default) | Rojo emits LocalScripts and Scripts with legacy `RunContext` (same behavior as previously). | + + + It can be used like this: + ```json + { + "emitLegacyScripts": false, + "name": "MyCoolRunContextProject", + "tree": { + "$path": "src" + } + } + ``` + +* Added `Terrain` classname inference, similar to services ([#771]) + + `Terrain` may now be defined in projects without using `$className`: + ```json + "Workspace": { + "Terrain": { + "$path": "path/to/terrain.rbxm" + } + } + ``` + +* Added support for `Terrain.MaterialColors` ([#770]) + + `Terrain.MaterialColors` is now represented in projects in a human readable format: + ```json + "Workspace": { + "Terrain": { + "$path": "path/to/terrain.rbxm" + "$properties": { + "MaterialColors": { + "Grass": [10, 20, 30], + "Asphalt": [40, 50, 60], + "LeafyGrass": [255, 155, 55] + } + } + } + } + ``` + +* Added better support for `Font` properties ([#731]) + + `FontFace` properties may now be defined using implicit property syntax: + ```json + "TextBox": { + "$className": "TextBox", + "$properties": { + "FontFace": { + "family": "rbxasset://fonts/families/RobotoMono.json", + "weight": "Thin", + "style": "Normal" + } + } + } + ``` + +#### Patch visualizer and notifications +* Added a setting to control patch confirmation behavior ([#774]) + + This is a new setting for controlling when the Rojo plugin prompts for confirmation before syncing. It has four options: + * Initial (default): prompts only once for a project in a given Studio session + * Always: always prompts for confirmation + * Large Changes: only prompts when there are more than X changed instances. The number of instances is configurable - an additional setting for the number of instances becomes available when this option is chosen + * Unlisted PlaceId: only prompts if the place ID is not present in servePlaceIds + +* Added the ability to select Instances in patch visualizer ([#709]) + + Double-clicking an instance in the patch visualizer sets Roblox Studio's selection to the instance. + +* Added a sync reminder notification. ([#689]) + + Rojo detects if you have previously synced to a place, and displays a notification reminding you to sync again: + + ![Rojo reminds you to sync a place that you've synced previously](https://user-images.githubusercontent.com/40185666/242397435-ccdfddf2-a63f-420c-bc18-a6e3d6455bba.png) + +* Added rich Source diffs in patch visualizer ([#748]) + + A "View Diff" button for script sources is now present in the patch visualizer. Clicking it displays a side-by-side diff of the script changes: + + ![The patch visualizer contains a "view diff" button](https://user-images.githubusercontent.com/40185666/256065992-3f03558f-84b0-45a1-80eb-901f348cf067.png) + + ![The "View Diff" button opens a widget that displays a diff](https://user-images.githubusercontent.com/40185666/256066084-1d9d8fe8-7dad-4ee7-a542-b4aee35a5644.png) + +* Patch visualizer now indicates what changes failed to apply. ([#717]) + + A clickable warning label is displayed when the Rojo plugin is unable to apply changes. Clicking the label displays precise information about which changes failed: + + ![Patch visualizer displays a clickable warning label when changes fail to apply](https://user-images.githubusercontent.com/40185666/252063660-f08399ef-1e16-4f1c-bed8-552821f98cef.png) + + +#### Miscellaneous +* Added `plugin` flag to the `build` command that outputs to the local plugins folder ([#735]) + + This is a flag that builds a Rojo project into Roblox Studio's plugins directory. This allows you to build a Rojo project and load it into Studio as a plugin without having to type the full path to the plugins directory. It can be used like this: `rojo build --plugin ` + +* Added new plugin template to the `init` command ([#738]) + + This is a new template geared towards plugins. It is similar to the model template, but creates a `Script` instead of a `ModuleScript` in the `src` directory. It can be used like this: `rojo init --kind plugin` + +* Added protection against syncing non-place projects as a place. ([#691]) +* Add buttons for navigation on the Connected page ([#722]) + +### Fixes +* Significantly improved performance of `rojo sourcemap` ([#668]) * Fixed the diff visualizer of connected sessions. ([#674]) * Fixed disconnected session activity. ([#675]) * Skip confirming patches that contain only a datamodel name change. ([#688]) -* Added sync reminder notification. ([#689]) -* Added protection against syncing a model to a place. ([#691]) -* Select Instances from diff tree view ([#709]) * Fix Rojo breaking when users undo/redo in Studio ([#708]) -* Improved sync info text on Connected page. ([#692]) -* Fix patch visualizer breaking when instances are removed during sync ([#713]) -* Patch visualizer now indicates what changes failed to apply. ([#717]) -* Add buttons for navigation on the Connected page ([#722]) * Improve tooltip behavior ([#723]) * Better settings controls ([#725]) -* Rework patch visualizer with many fixes and improvements ([#726]) -* Added support for syncing in `.toml` files ([#633]) -* Add `plugin` flag to the `build` command that outputs to the local plugins folder ([#735]) -* Added better support for `Font` properties ([#731]) -* Add new plugin template to the `init` command ([#738]) -* Added rich Source diffs in patch visualizer ([#748]) -* Fix PatchTree performance issues ([#755]) -* Don't override the initial enabled state for source diffing ([#760]) -* Added support for `Terrain.MaterialColors` ([#770]) -* Allow `Terrain` to be specified without a classname ([#771]) -* Add Confirmation Behavior setting ([#774]) -* Added the `emitLegacyScripts` field to the project format ([#765]). The behavior is outlined below: +* Rework patch visualizer with many fixes and improvements ([#713], [#726], [#755]) -| `emitLegacyScripts` Value | Action Taken by Rojo | -|----------------------------|--------------------------------------------------------------------------------------------------------------------| -| false | Rojo emits Scripts with the appropriate `RunContext` for `*.client.lua` and `*.server.lua` files in the project. | -| true (default) | Rojo emits LocalScripts and Scripts with legacy `RunContext` (same behavior as previously). | - -[#761]: https://github.com/rojo-rbx/rojo/pull/761 -[#745]: https://github.com/rojo-rbx/rojo/pull/745 [#668]: https://github.com/rojo-rbx/rojo/pull/668 [#674]: https://github.com/rojo-rbx/rojo/pull/674 [#675]: https://github.com/rojo-rbx/rojo/pull/675 @@ -45,7 +133,6 @@ [#691]: https://github.com/rojo-rbx/rojo/pull/691 [#709]: https://github.com/rojo-rbx/rojo/pull/709 [#708]: https://github.com/rojo-rbx/rojo/pull/708 -[#692]: https://github.com/rojo-rbx/rojo/pull/692 [#713]: https://github.com/rojo-rbx/rojo/pull/713 [#717]: https://github.com/rojo-rbx/rojo/pull/717 [#722]: https://github.com/rojo-rbx/rojo/pull/722 @@ -58,11 +145,12 @@ [#738]: https://github.com/rojo-rbx/rojo/pull/738 [#748]: https://github.com/rojo-rbx/rojo/pull/748 [#755]: https://github.com/rojo-rbx/rojo/pull/755 -[#760]: https://github.com/rojo-rbx/rojo/pull/760 [#765]: https://github.com/rojo-rbx/rojo/pull/765 [#770]: https://github.com/rojo-rbx/rojo/pull/770 [#771]: https://github.com/rojo-rbx/rojo/pull/771 [#774]: https://github.com/rojo-rbx/rojo/pull/774 +[rbx-dom#299]: https://github.com/rojo-rbx/rbx-dom/pull/299 +[rbx-dom#296]: https://github.com/rojo-rbx/rbx-dom/pull/296 ## [7.3.0] - April 22, 2023 * Added `$attributes` to project format. ([#574]) From 3cafbf7f1ad5c4eb0f526238e71468eda4c617cb Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Tue, 26 Sep 2023 15:41:33 -0700 Subject: [PATCH 1336/1504] Use PollWatcher in memofs StdBackend on macOS (#783) --- CHANGELOG.md | 2 ++ crates/memofs/CHANGELOG.md | 3 ++- crates/memofs/src/std_backend.rs | 17 ++++++++++++++++- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fc90f866..475adf57 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -116,6 +116,7 @@ * Add buttons for navigation on the Connected page ([#722]) ### Fixes +* Significantly improved performance of `rojo serve` and `rojo build` on macOS. [#783] * Significantly improved performance of `rojo sourcemap` ([#668]) * Fixed the diff visualizer of connected sessions. ([#674]) * Fixed disconnected session activity. ([#675]) @@ -149,6 +150,7 @@ [#770]: https://github.com/rojo-rbx/rojo/pull/770 [#771]: https://github.com/rojo-rbx/rojo/pull/771 [#774]: https://github.com/rojo-rbx/rojo/pull/774 +[#783]: https://github.com/rojo-rbx/rojo/pull/783 [rbx-dom#299]: https://github.com/rojo-rbx/rbx-dom/pull/299 [rbx-dom#296]: https://github.com/rojo-rbx/rbx-dom/pull/296 diff --git a/crates/memofs/CHANGELOG.md b/crates/memofs/CHANGELOG.md index b49b2f0f..43516260 100644 --- a/crates/memofs/CHANGELOG.md +++ b/crates/memofs/CHANGELOG.md @@ -1,6 +1,7 @@ # memofs Changelog ## Unreleased Changes +* Changed the `StdBackend` file watcher to use `PollWatcher` on macOS. ## 0.2.0 (2021-08-23) * Updated to `crossbeam-channel` 0.5.1. @@ -15,4 +16,4 @@ * Improved error messages using the [fs-err](https://crates.io/crates/fs-err) crate. ## 0.1.0 (2020-03-10) -* Initial release \ No newline at end of file +* Initial release diff --git a/crates/memofs/src/std_backend.rs b/crates/memofs/src/std_backend.rs index c13ade0b..01a554a5 100644 --- a/crates/memofs/src/std_backend.rs +++ b/crates/memofs/src/std_backend.rs @@ -5,19 +5,34 @@ use std::thread; use std::time::Duration; use crossbeam_channel::Receiver; -use notify::{watcher, DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; +use notify::{DebouncedEvent, RecursiveMode, Watcher}; + +#[cfg(target_os = "macos")] +use notify::PollWatcher; +#[cfg(not(target_os = "macos"))] +use notify::{watcher, RecommendedWatcher}; use crate::{DirEntry, Metadata, ReadDir, VfsBackend, VfsEvent}; /// `VfsBackend` that uses `std::fs` and the `notify` crate. pub struct StdBackend { + // We use PollWatcher on macos because using the KQueue watcher + // can cause some gnarly performance problems. + #[cfg(target_os = "macos")] + watcher: PollWatcher, + #[cfg(not(target_os = "macos"))] watcher: RecommendedWatcher, + watcher_receiver: Receiver, } impl StdBackend { pub fn new() -> StdBackend { let (notify_tx, notify_rx) = mpsc::channel(); + + #[cfg(target_os = "macos")] + let watcher = PollWatcher::new(notify_tx, Duration::from_millis(50)).unwrap(); + #[cfg(not(target_os = "macos"))] let watcher = watcher(notify_tx, Duration::from_millis(50)).unwrap(); let (tx, rx) = crossbeam_channel::unbounded(); From eab7c607cd5f865c6c66b5e50aae85fc63479b42 Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 3 Oct 2023 07:22:47 -0700 Subject: [PATCH 1337/1504] Don't include package author in CLI help (#793) LPG is at the moment listed by name and email in the `help` for Rojo. We should probably remove that before cutting a new release. --- src/cli/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/mod.rs b/src/cli/mod.rs index 36b32940..065128fb 100644 --- a/src/cli/mod.rs +++ b/src/cli/mod.rs @@ -25,7 +25,7 @@ pub use self::upload::UploadCommand; /// Command line options that Rojo accepts, defined using the clap crate. #[derive(Debug, Parser)] -#[clap(name = "Rojo", version, about, author)] +#[clap(name = "Rojo", version, about)] pub struct Options { #[clap(flatten)] pub global: GlobalOptions, From 010e50a25d1917f88f979af319849f0d01282c47 Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 3 Oct 2023 07:29:47 -0700 Subject: [PATCH 1338/1504] Add check to ensure plugin version matches cargo version (#794) This modifies Rojo's build script to throw a fit if we're building a plugin with a semver incompatible version. In the process, it moves the version of the plugin to a file named `Version.txt` that's parsed at runtime. This should be minimally invasive but it's technically worse for performance than the hardcoded table and string we had before. This feels better than a CI check or just manually verifying because it makes it physically impossible for us to forget since Rojo won't build with it being wrong. --- Cargo.lock | 5 ++-- Cargo.toml | 1 + build.rs | 15 +++++++++++ plugin/Version.txt | 1 + plugin/default.project.json | 50 +++++++++++++++++++------------------ plugin/src/Config.lua | 16 ++++++++++-- 6 files changed, 60 insertions(+), 28 deletions(-) create mode 100644 plugin/Version.txt diff --git a/Cargo.lock b/Cargo.lock index f106d61f..5f9c5b7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1916,6 +1916,7 @@ dependencies = [ "ritz", "roblox_install", "rojo-insta-ext", + "semver", "serde", "serde_json", "serde_yaml", @@ -2034,9 +2035,9 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.17" +version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bebd363326d05ec3e2f532ab7660680f3b02130d780c299bca73469d521bc0ed" +checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" [[package]] name = "serde" diff --git a/Cargo.toml b/Cargo.toml index 4c210934..a200ac85 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -102,6 +102,7 @@ anyhow = "1.0.44" bincode = "1.3.3" fs-err = "2.6.0" maplit = "1.0.2" +semver = "1.0.19" [dev-dependencies] rojo-insta-ext = { path = "crates/rojo-insta-ext" } diff --git a/build.rs b/build.rs index 8326fcdc..b82f9542 100644 --- a/build.rs +++ b/build.rs @@ -7,6 +7,7 @@ use fs_err as fs; use fs_err::File; use maplit::hashmap; use memofs::VfsSnapshot; +use semver::Version; fn snapshot_from_fs_path(path: &Path) -> io::Result { println!("cargo:rerun-if-changed={}", path.display()); @@ -43,6 +44,19 @@ fn main() -> Result<(), anyhow::Error> { let root_dir = env::var_os("CARGO_MANIFEST_DIR").unwrap(); let plugin_root = PathBuf::from(root_dir).join("plugin"); + let our_version = Version::parse(env::var_os("CARGO_PKG_VERSION").unwrap().to_str().unwrap())?; + let plugin_version = + Version::parse(fs::read_to_string(&plugin_root.join("Version.txt"))?.trim())?; + + assert!( + our_version.major == plugin_version.major, + "plugin version does not match Cargo version" + ); + assert!( + our_version.minor == plugin_version.minor, + "plugin version does not match Cargo version" + ); + let snapshot = VfsSnapshot::dir(hashmap! { "default.project.json" => snapshot_from_fs_path(&plugin_root.join("default.project.json"))?, "fmt" => snapshot_from_fs_path(&plugin_root.join("fmt"))?, @@ -51,6 +65,7 @@ fn main() -> Result<(), anyhow::Error> { "rbx_dom_lua" => snapshot_from_fs_path(&plugin_root.join("rbx_dom_lua"))?, "src" => snapshot_from_fs_path(&plugin_root.join("src"))?, "Packages" => snapshot_from_fs_path(&plugin_root.join("Packages"))?, + "Version.txt" => snapshot_from_fs_path(&plugin_root.join("Version.txt"))?, }); let out_path = Path::new(&out_dir).join("plugin.bincode"); diff --git a/plugin/Version.txt b/plugin/Version.txt new file mode 100644 index 00000000..8b23b8d4 --- /dev/null +++ b/plugin/Version.txt @@ -0,0 +1 @@ +7.3.0 \ No newline at end of file diff --git a/plugin/default.project.json b/plugin/default.project.json index 09234438..424f107e 100644 --- a/plugin/default.project.json +++ b/plugin/default.project.json @@ -1,25 +1,27 @@ { - "name": "Rojo", - "tree": { - "$className": "Folder", - "Plugin": { - "$path": "src" - }, - "Packages": { - "$path": "Packages", - - "Log": { - "$path": "log" - }, - "Http": { - "$path": "http" - }, - "Fmt": { - "$path": "fmt" - }, - "RbxDom": { - "$path": "rbx_dom_lua" - } - } - } -} + "name": "Rojo", + "tree": { + "$className": "Folder", + "Plugin": { + "$path": "src" + }, + "Packages": { + "$path": "Packages", + "Log": { + "$path": "log" + }, + "Http": { + "$path": "http" + }, + "Fmt": { + "$path": "fmt" + }, + "RbxDom": { + "$path": "rbx_dom_lua" + } + }, + "Version": { + "$path": "Version.txt" + } + } +} \ No newline at end of file diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index a2909f51..70eeccfa 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -2,11 +2,23 @@ local strict = require(script.Parent.strict) local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil +local Version = script.Parent.Parent.Version +local realVersion = Version.Value:split(".") + +for i = 1, 3 do + local num = tonumber(realVersion[i]) + if num then + realVersion[i] = num + else + error(("invalid version `%s` (field %d)"):format(realVersion[i], i)) + end +end + return strict("Config", { isDevBuild = isDevBuild, codename = "Epiphany", - version = { 7, 3, 0 }, - expectedServerVersionString = "7.2 or newer", + version = realVersion, + expectedServerVersionString = ("%d.%d or newer"):format(realVersion[1], realVersion[2]), protocolVersion = 4, defaultHost = "localhost", defaultPort = "34872", From d38f95514439235ec9d9be74f33cb89bc3b78033 Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 3 Oct 2023 16:32:22 -0700 Subject: [PATCH 1339/1504] Update rbx_dom dependencies (#795) In preparation for a new release, rbx_dom needs to be updated. --- .github/workflows/ci.yml | 2 +- Cargo.lock | 24 +- Cargo.toml | 12 +- README.md | 2 +- plugin/rbx_dom_lua/EncodedValue.lua | 92 +- plugin/rbx_dom_lua/EncodedValue.spec.lua | 67 - plugin/rbx_dom_lua/Error.lua | 2 +- plugin/rbx_dom_lua/base64.lua | 2 +- plugin/rbx_dom_lua/base64.spec.lua | 29 - plugin/rbx_dom_lua/customProperties.lua | 4 +- plugin/rbx_dom_lua/database.json | 4080 +++++++++++++++++++++- plugin/rbx_dom_lua/init.lua | 3 +- plugin/rbx_dom_lua/init.spec.lua | 7 - 13 files changed, 3988 insertions(+), 338 deletions(-) delete mode 100644 plugin/rbx_dom_lua/EncodedValue.spec.lua delete mode 100644 plugin/rbx_dom_lua/base64.spec.lua delete mode 100644 plugin/rbx_dom_lua/init.spec.lua diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 04da7dcd..ad5a05d7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,7 @@ jobs: strategy: matrix: - rust_version: [stable, 1.69.0] + rust_version: [stable, 1.70.0] steps: - uses: actions/checkout@v3 diff --git a/Cargo.lock b/Cargo.lock index 5f9c5b7c..a4b74f37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1647,9 +1647,9 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e50573021d04b680018955662eba7dc4aac3de92219231798f6c9b41e38ab01" +checksum = "10942950a57c939e540a2f977ba55e9140007d7e96c532d455502c290fdf710d" dependencies = [ "log", "lz4", @@ -1662,9 +1662,9 @@ dependencies = [ [[package]] name = "rbx_dom_weak" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "161729449bbb0cfa657ce7bcca6a160d0af06d8b8d9efdc9abe14735dccacdb9" +checksum = "843a2e0e1446623625943f7228d9d4b5cf3883017e3964733600682506864b34" dependencies = [ "rbx_types", "serde", @@ -1672,9 +1672,9 @@ dependencies = [ [[package]] name = "rbx_reflection" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08bd48487192046fec8f805f3fa29f3d7d5beb9890b0859b1a92bd8aff580343" +checksum = "41e762dfca3217d2d37da631de2fa0d1616edaa61a0a2633263d5d3305baf8c3" dependencies = [ "rbx_types", "serde", @@ -1683,9 +1683,9 @@ dependencies = [ [[package]] name = "rbx_reflection_database" -version = "0.2.7+roblox-588" +version = "0.2.8+roblox-296" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1be6cf674182806f11ad4899dd1feafe977591f1ae035ae05a58d4b74e487276" +checksum = "ff48aa41683dc6fe6949b0a82833b3364cf47c87086502b84d3e0419bff33c10" dependencies = [ "lazy_static", "rbx_reflection", @@ -1695,9 +1695,9 @@ dependencies = [ [[package]] name = "rbx_types" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "070106e926b8ae54c7bc443e5db4d868d7f0af51c1d7cfd7efe1364c1753d8a3" +checksum = "32a991523e3ad5f43a4d121cb4a1e5bc23f7826bb4a1db5aa51e94f1073150ec" dependencies = [ "base64 0.13.1", "bitflags", @@ -1710,9 +1710,9 @@ dependencies = [ [[package]] name = "rbx_xml" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bc65b70827519fdc4ab47416d1085b912f087fadab9ed415471b6daba635574" +checksum = "fc87343301303ff0510903fb7eb3dbd1c75bdb6ab780fea6091bdc3f58b5829f" dependencies = [ "base64 0.13.1", "log", diff --git a/Cargo.toml b/Cargo.toml index a200ac85..169f7297 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rojo" version = "7.3.0" -rust-version = "1.68.2" +rust-version = "1.70.0" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" license = "MPL-2.0" @@ -49,11 +49,11 @@ memofs = { version = "0.2.0", path = "crates/memofs" } # rbx_reflection_database = { path = "../rbx-dom/rbx_reflection_database" } # rbx_xml = { path = "../rbx-dom/rbx_xml" } -rbx_binary = "0.7.1" -rbx_dom_weak = "2.5.0" -rbx_reflection = "4.3.0" -rbx_reflection_database = "0.2.7" -rbx_xml = "0.13.1" +rbx_binary = "0.7.2" +rbx_dom_weak = "2.6.0" +rbx_reflection = "4.4.0" +rbx_reflection_database = "0.2.8" +rbx_xml = "0.13.2" anyhow = "1.0.44" backtrace = "0.3.61" diff --git a/README.md b/README.md index fb318f3f..bbdeba30 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ Check out our [contribution guide](CONTRIBUTING.md) for detailed instructions fo Pull requests are welcome! -Rojo supports Rust 1.58.1 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. +Rojo supports Rust 1.70.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. ## License Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file diff --git a/plugin/rbx_dom_lua/EncodedValue.lua b/plugin/rbx_dom_lua/EncodedValue.lua index 35417410..b1a9ac13 100644 --- a/plugin/rbx_dom_lua/EncodedValue.lua +++ b/plugin/rbx_dom_lua/EncodedValue.lua @@ -20,8 +20,8 @@ local function serializeFloat(value) return value end -local ALL_AXES = {"X", "Y", "Z"} -local ALL_FACES = {"Right", "Top", "Back", "Left", "Bottom", "Front"} +local ALL_AXES = { "X", "Y", "Z" } +local ALL_FACES = { "Right", "Top", "Back", "Left", "Bottom", "Front" } local EncodedValue = {} @@ -37,7 +37,10 @@ types = { if ok then output[key] = result else - local warning = ("Could not decode attribute value of type %q: %s"):format(typeof(value), tostring(result)) + local warning = ("Could not decode attribute value of type %q: %s"):format( + typeof(value), + tostring(result) + ) warn(warning) end end @@ -53,7 +56,10 @@ types = { if ok then output[key] = result else - local warning = ("Could not encode attribute value of type %q: %s"):format(typeof(value), tostring(result)) + local warning = ("Could not encode attribute value of type %q: %s"):format( + typeof(value), + tostring(result) + ) warn(warning) end end @@ -111,6 +117,7 @@ types = { local pos = pod.position local orient = pod.orientation + --stylua: ignore return CFrame.new( pos[1], pos[2], pos[3], orient[1][1], orient[1][2], orient[1][3], @@ -120,17 +127,14 @@ types = { end, toPod = function(roblox) - local x, y, z, - r00, r01, r02, - r10, r11, r12, - r20, r21, r22 = roblox:GetComponents() + local x, y, z, r00, r01, r02, r10, r11, r12, r20, r21, r22 = roblox:GetComponents() return { - position = {x, y, z}, + position = { x, y, z }, orientation = { - {r00, r01, r02}, - {r10, r11, r12}, - {r20, r21, r22}, + { r00, r01, r02 }, + { r10, r11, r12 }, + { r20, r21, r22 }, }, } end, @@ -140,7 +144,7 @@ types = { fromPod = unpackDecoder(Color3.new), toPod = function(roblox) - return {roblox.r, roblox.g, roblox.b} + return { roblox.r, roblox.g, roblox.b } end, }, @@ -161,10 +165,7 @@ types = { local keypoints = {} for index, keypoint in ipairs(pod.keypoints) do - keypoints[index] = ColorSequenceKeypoint.new( - keypoint.time, - types.Color3.fromPod(keypoint.color) - ) + keypoints[index] = ColorSequenceKeypoint.new(keypoint.time, types.Color3.fromPod(keypoint.color)) end return ColorSequence.new(keypoints) @@ -279,7 +280,7 @@ types = { pod[material.Name] = { math.round(math.clamp(color.R, 0, 1) * 255), math.round(math.clamp(color.G, 0, 1) * 255), - math.round(math.clamp(color.B, 0, 1) * 255) + math.round(math.clamp(color.B, 0, 1) * 255), } end return pod @@ -290,7 +291,7 @@ types = { fromPod = unpackDecoder(NumberRange.new), toPod = function(roblox) - return {roblox.Min, roblox.Max} + return { roblox.Min, roblox.Max } end, }, @@ -299,11 +300,7 @@ types = { local keypoints = {} for index, keypoint in ipairs(pod.keypoints) do - keypoints[index] = NumberSequenceKeypoint.new( - keypoint.time, - keypoint.value, - keypoint.envelope - ) + keypoints[index] = NumberSequenceKeypoint.new(keypoint.time, keypoint.value, keypoint.envelope) end return NumberSequence.new(keypoints) @@ -358,10 +355,7 @@ types = { Ray = { fromPod = function(pod) - return Ray.new( - types.Vector3.fromPod(pod.origin), - types.Vector3.fromPod(pod.direction) - ) + return Ray.new(types.Vector3.fromPod(pod.origin), types.Vector3.fromPod(pod.direction)) end, toPod = function(roblox) @@ -374,10 +368,7 @@ types = { Rect = { fromPod = function(pod) - return Rect.new( - types.Vector2.fromPod(pod[1]), - types.Vector2.fromPod(pod[2]) - ) + return Rect.new(types.Vector2.fromPod(pod[1]), types.Vector2.fromPod(pod[2])) end, toPod = function(roblox) @@ -389,31 +380,28 @@ types = { }, Ref = { - fromPod = function(_pod) + fromPod = function(_) error("Ref cannot be decoded on its own") end, - toPod = function(_roblox) + toPod = function(_) error("Ref can not be encoded on its own") end, }, Region3 = { - fromPod = function(pod) + fromPod = function(_) error("Region3 is not implemented") end, - toPod = function(roblox) + toPod = function(_) error("Region3 is not implemented") end, }, Region3int16 = { fromPod = function(pod) - return Region3int16.new( - types.Vector3int16.fromPod(pod[1]), - types.Vector3int16.fromPod(pod[2]) - ) + return Region3int16.new(types.Vector3int16.fromPod(pod[1]), types.Vector3int16.fromPod(pod[2])) end, toPod = function(roblox) @@ -424,12 +412,21 @@ types = { end, }, + SecurityCapabilities = { + fromPod = function(_pod) + error("SecurityCapabilities is not implemented") + end, + toPod = function(_roblox) + error("SecurityCapabilities is not implemented") + end, + }, + SharedString = { - fromPod = function(pod) + fromPod = function(_pod) error("SharedString is not supported") end, - toPod = function(roblox) + toPod = function(_roblox) error("SharedString is not supported") end, }, @@ -443,16 +440,13 @@ types = { fromPod = unpackDecoder(UDim.new), toPod = function(roblox) - return {roblox.Scale, roblox.Offset} + return { roblox.Scale, roblox.Offset } end, }, UDim2 = { fromPod = function(pod) - return UDim2.new( - types.UDim.fromPod(pod[1]), - types.UDim.fromPod(pod[2]) - ) + return UDim2.new(types.UDim.fromPod(pod[1]), types.UDim.fromPod(pod[2])) end, toPod = function(roblox) @@ -483,7 +477,7 @@ types = { fromPod = unpackDecoder(Vector2int16.new), toPod = function(roblox) - return {roblox.X, roblox.Y} + return { roblox.X, roblox.Y } end, }, @@ -503,7 +497,7 @@ types = { fromPod = unpackDecoder(Vector3int16.new), toPod = function(roblox) - return {roblox.X, roblox.Y, roblox.Z} + return { roblox.X, roblox.Y, roblox.Z } end, }, } diff --git a/plugin/rbx_dom_lua/EncodedValue.spec.lua b/plugin/rbx_dom_lua/EncodedValue.spec.lua deleted file mode 100644 index 14522ae8..00000000 --- a/plugin/rbx_dom_lua/EncodedValue.spec.lua +++ /dev/null @@ -1,67 +0,0 @@ -return function() - local HttpService = game:GetService("HttpService") - - local EncodedValue = require(script.Parent.EncodedValue) - local allValues = require(script.Parent.allValues) - - local function deepEq(a, b) - if typeof(a) ~= typeof(b) then - return false - end - - local ty = typeof(a) - - if ty == "table" then - local visited = {} - - for key, valueA in a do - visited[key] = true - - if not deepEq(valueA, b[key]) then - return false - end - end - - for key, valueB in b do - if visited[key] then - continue - end - - if not deepEq(valueB, a[key]) then - return false - end - end - - return true - else - return a == b - end - end - - local extraAssertions = { - CFrame = function(value) - expect(value).to.equal(CFrame.new(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12)) - end, - } - - for testName, testEntry in allValues do - it("round trip " .. testName, function() - local decodeOk, decoded = EncodedValue.decode(testEntry.value) - assert(decodeOk, decoded) - - if extraAssertions[testName] ~= nil then - extraAssertions[testName](decoded) - end - - local encodeOk, encoded = EncodedValue.encode(decoded, testEntry.ty) - assert(encodeOk, encoded) - - if not deepEq(encoded, testEntry.value) then - local expected = HttpService:JSONEncode(testEntry.value) - local actual = HttpService:JSONEncode(encoded) - - error(`Round-trip results did not match.\nExpected:\n{expected}\nActual:\n{actual}`) - end - end) - end -end diff --git a/plugin/rbx_dom_lua/Error.lua b/plugin/rbx_dom_lua/Error.lua index d4c8b1ca..5b8f582c 100644 --- a/plugin/rbx_dom_lua/Error.lua +++ b/plugin/rbx_dom_lua/Error.lua @@ -25,4 +25,4 @@ function Error:__tostring() return ("Error(%s: %s)"):format(self.kind, tostring(self.extra)) end -return Error \ No newline at end of file +return Error diff --git a/plugin/rbx_dom_lua/base64.lua b/plugin/rbx_dom_lua/base64.lua index 33011306..0ea19d39 100644 --- a/plugin/rbx_dom_lua/base64.lua +++ b/plugin/rbx_dom_lua/base64.lua @@ -136,4 +136,4 @@ end return { decode = decodeBase64, encode = encodeBase64, -} \ No newline at end of file +} diff --git a/plugin/rbx_dom_lua/base64.spec.lua b/plugin/rbx_dom_lua/base64.spec.lua deleted file mode 100644 index 5f2a5f4a..00000000 --- a/plugin/rbx_dom_lua/base64.spec.lua +++ /dev/null @@ -1,29 +0,0 @@ -return function() - local base64 = require(script.Parent.base64) - - it("should encode and decode", function() - local function try(str, expected) - local encoded = base64.encode(str) - expect(encoded).to.equal(expected) - expect(base64.decode(encoded)).to.equal(str) - end - - try("Man", "TWFu") - try("Ma", "TWE=") - try("M", "TQ==") - try("ManM", "TWFuTQ==") - try( - [[Man is distinguished, not only by his reason, but by this ]].. - [[singular passion from other animals, which is a lust of the ]].. - [[mind, that by a perseverance of delight in the continued and ]].. - [[indefatigable generation of knowledge, exceeds the short ]].. - [[vehemence of any carnal pleasure.]], - [[TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sI]].. - [[GJ1dCBieSB0aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYW]].. - [[xzLCB3aGljaCBpcyBhIGx1c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJ]].. - [[zZXZlcmFuY2Ugb2YgZGVsaWdodCBpbiB0aGUgY29udGludWVkIGFuZCBpbmRl]].. - [[ZmF0aWdhYmxlIGdlbmVyYXRpb24gb2Yga25vd2xlZGdlLCBleGNlZWRzIHRoZ]].. - [[SBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm5hbCBwbGVhc3VyZS4=]] - ) - end) -end \ No newline at end of file diff --git a/plugin/rbx_dom_lua/customProperties.lua b/plugin/rbx_dom_lua/customProperties.lua index d4d6f723..624523b6 100644 --- a/plugin/rbx_dom_lua/customProperties.lua +++ b/plugin/rbx_dom_lua/customProperties.lua @@ -77,10 +77,10 @@ return { }, LocalizationTable = { Contents = { - read = function(instance, key) + read = function(instance, _) return true, instance:GetContents() end, - write = function(instance, key, value) + write = function(instance, _, value) instance:SetContents(value) return true end, diff --git a/plugin/rbx_dom_lua/database.json b/plugin/rbx_dom_lua/database.json index 1c88154c..720fb5ff 100644 --- a/plugin/rbx_dom_lua/database.json +++ b/plugin/rbx_dom_lua/database.json @@ -1,9 +1,9 @@ { "Version": [ 0, - 588, - 0, - 5880517 + 596, + 1, + 5960685 ], "Classes": { "Accessory": { @@ -58,6 +58,131 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "AccessoryDescription": { + "Name": "AccessoryDescription", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "AccessoryType": { + "Name": "AccessoryType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AccessoryType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AssetId": { + "Name": "AssetId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Instance": { + "Name": "Instance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsLayered": { + "Name": "IsLayered", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Order": { + "Name": "Order", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Puffiness": { + "Name": "Puffiness", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AccessoryType": { + "Enum": 0 + }, + "AssetId": { + "Int64": 0 + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, + "IsLayered": { + "Bool": false + }, + "Order": { + "Int32": 0 + }, + "Puffiness": { + "Float32": 1.0 + }, "SourceAssetId": { "Int64": -1 }, @@ -195,6 +320,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -212,6 +343,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "LevelOfDetail": { "Enum": 0 }, @@ -418,9 +555,7 @@ }, "AirController": { "Name": "AirController", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "ControllerBase", "Properties": { "BalanceMaxTorque": { @@ -544,6 +679,12 @@ "BalanceSpeed": { "Float32": 100.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MaintainAngularMomentum": { "Bool": true }, @@ -771,9 +912,15 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 23 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -965,9 +1112,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 194 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -1060,6 +1213,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -1137,9 +1296,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 23 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -1189,6 +1354,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -1283,6 +1454,42 @@ ], "Superclass": "Constraint", "Properties": { + "C0": { + "Name": "C0", + "Scriptability": "Read", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "C1": { + "Name": "C1", + "Scriptability": "Read", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "IsKinematic": { "Name": "IsKinematic", "Scriptability": "ReadWrite", @@ -1322,6 +1529,42 @@ } } }, + "Part0": { + "Name": "Part0", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Part1": { + "Name": "Part1", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Transform": { "Name": "Transform", "Scriptability": "ReadWrite", @@ -1340,9 +1583,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 23 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -1401,6 +1650,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -1421,6 +1676,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -1615,6 +1876,22 @@ } } }, + "rootMotion": { + "Name": "rootMotion", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "transform": { "Name": "transform", "Scriptability": "None", @@ -1652,6 +1929,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -1688,6 +1971,9 @@ "preTransform": { "BinaryString": "AQAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=" }, + "rootMotion": { + "BinaryString": "" + }, "transform": { "BinaryString": "AQAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=" }, @@ -1972,12 +2258,52 @@ "Serialization": "Serializes" } } + }, + "RootMotion": { + "Name": "RootMotion", + "Scriptability": "Read", + "DataType": { + "Value": "CFrame" + }, + "Tags": [ + "NotBrowsable", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RootMotionWeight": { + "Name": "RootMotionWeight", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotBrowsable", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "PreferLodEnabled": { "Bool": true }, @@ -2121,6 +2447,9 @@ "Z" ] }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -2128,6 +2457,9 @@ 0.6745098 ] }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -2298,6 +2630,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -2403,6 +2741,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "Color3": [ 0.7843, @@ -2417,6 +2758,9 @@ 0.0549 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Density": { "Float32": 0.395 }, @@ -2673,6 +3017,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -2728,6 +3078,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -2787,6 +3143,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Depth": { "Float32": 0.45 }, @@ -2884,6 +3246,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MakeupGain": { "Float32": 0.0 }, @@ -3006,6 +3374,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Muted": { "Bool": false }, @@ -3042,6 +3416,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -3075,6 +3455,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Level": { "Float32": 0.5 }, @@ -3150,6 +3536,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "DelayTime": { "Float32": 1.0 }, @@ -3198,6 +3590,12 @@ "AudioInteractionGroup": { "String": "" }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -3270,6 +3668,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "HighGain": { "Float32": 0.0 }, @@ -3318,6 +3722,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -3380,6 +3790,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Depth": { "Float32": 0.45 }, @@ -3425,6 +3841,12 @@ "AudioInteractionGroup": { "String": "" }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -3468,6 +3890,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Pitch": { "Float32": 1.25 }, @@ -3633,6 +4061,12 @@ "AutoLoad": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "LoopRegion": { "NumberRange": [ 0.0, @@ -3830,12 +4264,18 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "DecayRatio": { "Float32": 0.5 }, "DecayTime": { "Float32": 1.5 }, + "DefinesCapabilities": { + "Bool": false + }, "Density": { "Float32": 1.0 }, @@ -4095,6 +4535,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -4267,9 +4713,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 1009 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -6046,6 +6498,9 @@ "Brightness": { "Float32": 1.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "ColorSequence": { "keypoints": [ @@ -6074,6 +6529,9 @@ "CurveSize1": { "Float32": 0.0 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -6453,9 +6911,15 @@ "Brightness": { "Float32": 1.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClipsDescendants": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "DistanceLowerLimit": { "Float32": 0.0 }, @@ -6575,6 +7039,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -6595,6 +7065,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -6612,6 +7088,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -6638,6 +7120,12 @@ "Bulge": { "Float32": 0.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Offset": { "Vector3": [ 0.0, @@ -6716,6 +7204,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -6759,6 +7253,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -6863,6 +7363,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MaxTorque": { "Vector3": [ 4000.0, @@ -7047,6 +7553,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "HeadColor3": { "Color3": [ 0.9921569, @@ -7138,6 +7650,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Force": { "Vector3": [ 0.0, @@ -7275,9 +7793,15 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "D": { "Float32": 500.0 }, + "DefinesCapabilities": { + "Bool": false + }, "MaxTorque": { "Vector3": [ 400000.0, @@ -7306,6 +7830,97 @@ "Properties": {}, "DefaultProperties": {} }, + "BodyPartDescription": { + "Name": "BodyPartDescription", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "AssetId": { + "Name": "AssetId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BodyPart": { + "Name": "BodyPart", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "BodyPart" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Instance": { + "Name": "Instance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AssetId": { + "Int64": 0 + }, + "Attributes": { + "Attributes": {} + }, + "BodyPart": { + "Enum": 0 + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "Color": { + "Color3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "DefinesCapabilities": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, "BodyPosition": { "Name": "BodyPosition", "Tags": [ @@ -7402,9 +8017,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "D": { "Float32": 1250.0 }, + "DefinesCapabilities": { + "Bool": false + }, "MaxForce": { "Vector3": [ 4000.0, @@ -7500,6 +8121,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Force": { "Vector3": [ 0.0, @@ -7605,6 +8232,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MaxForce": { "Vector3": [ 4000.0, @@ -7714,6 +8347,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -7748,6 +8387,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -7814,6 +8459,9 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -7821,6 +8469,9 @@ 0.6745098 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Size": { "Vector3": [ 1.0, @@ -8067,6 +8718,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -8330,6 +8987,12 @@ "BubblesSpacing": { "Float32": 6.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -8428,6 +9091,19 @@ } } }, + "TailVisible": { + "Name": "TailVisible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "TextColor3": { "Name": "TextColor3", "Scriptability": "ReadWrite", @@ -8459,6 +9135,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -8480,9 +9162,7 @@ }, "BuoyancySensor": { "Name": "BuoyancySensor", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "SensorBase", "Properties": { "FullySubmerged": { @@ -8516,6 +9196,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "FullySubmerged": { "Bool": false }, @@ -8556,6 +9242,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -8601,6 +9293,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -8884,6 +9582,12 @@ "CameraType": { "Enum": 0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "FieldOfView": { "Float32": 70.0 }, @@ -9007,9 +9711,15 @@ "BorderSizePixel": { "Int32": 1 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClipsDescendants": { "Bool": true }, + "DefinesCapabilities": { + "Bool": false + }, "Draggable": { "Bool": false }, @@ -9023,6 +9733,9 @@ "GroupTransparency": { "Float32": 0.0 }, + "Interactable": { + "Bool": true + }, "LayoutOrder": { "Int32": 0 }, @@ -9148,9 +9861,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Channel": { "Int32": 1 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -9242,6 +9961,12 @@ "BodyPart": { "Enum": 0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MeshId": { "Int64": 0 }, @@ -9299,6 +10024,12 @@ "BubbleChatEnabled": { "Bool": false }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "LoadDefaultChat": { "Bool": true }, @@ -9597,6 +10328,12 @@ "BackgroundTransparency": { "Float64": 0.2 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -9886,6 +10623,12 @@ "BackgroundTransparency": { "Float64": 0.3 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -9937,6 +10680,17 @@ } } }, + "ChatbotUIService": { + "Name": "ChatbotUIService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ChorusSoundEffect": { "Name": "ChorusSoundEffect", "Tags": [], @@ -9986,6 +10740,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Depth": { "Float32": 0.15 }, @@ -10045,9 +10805,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CursorIcon": { "Content": "" }, + "DefinesCapabilities": { + "Bool": false + }, "MaxActivationDistance": { "Float32": 32.0 }, @@ -10071,9 +10837,7 @@ }, "ClimbController": { "Name": "ClimbController", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "ControllerBase", "Properties": { "AccelerationTime": { @@ -10145,6 +10909,12 @@ "BalanceSpeed": { "Float32": 100.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MoveMaxForce": { "Float32": 10000.0 }, @@ -10288,6 +11058,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "Color3": [ 1.0, @@ -10298,6 +11071,9 @@ "Cover": { "Float32": 0.5 }, + "DefinesCapabilities": { + "Bool": false + }, "Density": { "Float32": 0.7 }, @@ -10323,6 +11099,120 @@ "Properties": {}, "DefaultProperties": {} }, + "Collaborator": { + "Name": "Collaborator", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "CFrame": { + "Name": "CFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CollaboratorColor": { + "Name": "CollaboratorColor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CurDocGUID": { + "Name": "CurDocGUID", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CurScriptLineNumber": { + "Name": "CurScriptLineNumber", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Status": { + "Name": "Status", + "Scriptability": "None", + "DataType": { + "Enum": "CollaboratorStatus" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UserId": { + "Name": "UserId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Username": { + "Name": "Username", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "CollaboratorsService": { + "Name": "CollaboratorsService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "CollectionService": { "Name": "CollectionService", "Tags": [ @@ -10335,6 +11225,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -10366,6 +11262,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -10446,9 +11348,15 @@ "Brightness": { "Float32": 0.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Contrast": { "Float32": 0.0 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -10722,6 +11630,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -10816,6 +11730,9 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -10823,6 +11740,9 @@ 0.6745098 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Height": { "Float32": 2.0 }, @@ -10862,6 +11782,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -11027,6 +11953,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -11098,9 +12030,7 @@ }, "ControllerManager": { "Name": "ControllerManager", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "Instance", "Properties": { "ActiveController": { @@ -11218,6 +12148,12 @@ "BaseTurnSpeed": { "Float32": 8.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "FacingDirection": { "Vector3": [ 0.0, @@ -11242,9 +12178,7 @@ }, "ControllerPartSensor": { "Name": "ControllerPartSensor", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "ControllerSensor", "Properties": { "HitFrame": { @@ -11317,6 +12251,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "HitFrame": { "CFrame": { "position": [ @@ -11399,6 +12339,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -11561,6 +12507,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -11580,6 +12529,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "EnableFluidForces": { "Bool": true }, @@ -11707,6 +12659,17 @@ } } }, + "CreationDBService": { + "Name": "CreationDBService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "CrossDMScriptChangeListener": { "Name": "CrossDMScriptChangeListener", "Tags": [ @@ -11727,6 +12690,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "GuidBinaryString": { "BinaryString": "AAAAAAAAAAAAAAAAAAAAAA==" }, @@ -11772,6 +12741,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "PersistedCurrentValue": { "Float32": 0.0 }, @@ -11808,6 +12783,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -11922,6 +12903,9 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -11929,6 +12913,9 @@ 0.6745098 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Height": { "Float32": 1.0 }, @@ -11982,6 +12969,12 @@ "Bulge": { "Float32": 0.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Offset": { "Vector3": [ 0.0, @@ -12256,9 +13249,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 1009 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -12772,6 +13771,29 @@ "Properties": {}, "DefaultProperties": {} }, + "DataStoreGetOptions": { + "Name": "DataStoreGetOptions", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "UseCache": { + "Name": "UseCache", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "DataStoreIncrementOptions": { "Name": "DataStoreIncrementOptions", "Tags": [ @@ -13120,6 +14142,12 @@ "AutomaticRetry": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "LegacyNamingScheme": { "Bool": false }, @@ -13178,6 +14206,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MaxItems": { "Int32": 1000 }, @@ -13924,6 +14958,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 1.0, @@ -13931,6 +14968,9 @@ 1.0 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Face": { "Enum": 5 }, @@ -14013,6 +15053,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -14190,9 +15236,15 @@ "BehaviorType": { "Enum": 0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ConversationDistance": { "Float32": 25.0 }, + "DefinesCapabilities": { + "Bool": false + }, "GoodbyeChoiceActive": { "Bool": true }, @@ -14288,6 +15340,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "GoodbyeChoiceActive": { "Bool": true }, @@ -14331,6 +15389,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -14460,6 +15524,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MaxValue": { "Float64": 1.0 }, @@ -14724,6 +15794,22 @@ } } }, + "PhysicalDragIsInVR": { + "Name": "PhysicalDragIsInVR", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PhysicalDragTargetFrame": { "Name": "PhysicalDragTargetFrame", "Scriptability": "None", @@ -14887,9 +15973,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CursorIcon": { "Content": "" }, + "DefinesCapabilities": { + "Bool": false + }, "DragFrame": { "CFrame": { "position": [ @@ -15283,9 +16375,7 @@ }, "DynamicImage": { "Name": "DynamicImage", - "Tags": [ - "NotCreatable" - ], + "Tags": [], "Superclass": "Instance", "Properties": { "Size": { @@ -15308,11 +16398,36 @@ "Name": "DynamicMesh", "Tags": [], "Superclass": "DataModelMesh", - "Properties": {}, + "Properties": { + "MeshVersion": { + "Name": "MeshVersion", + "Scriptability": "Read", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, + "MeshVersion": { + "Int32": 0 + }, "Offset": { "Vector3": [ 0.0, @@ -15427,6 +16542,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Delay": { "Float32": 1.0 }, @@ -15512,6 +16633,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -15558,6 +16685,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "RotationOrder": { "Enum": 0 }, @@ -15651,6 +16784,44 @@ }, "DefaultProperties": {} }, + "ExperienceNotificationService": { + "Name": "ExperienceNotificationService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "ExperienceService": { + "Name": "ExperienceService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Explosion": { "Name": "Explosion", "Tags": [], @@ -15758,6 +16929,12 @@ "BlastRadius": { "Float32": 4.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "DestroyJointRadiusPercent": { "Float32": 1.0 }, @@ -15810,6 +16987,22 @@ } } }, + "FaceTrackingStatusEnum": { + "Name": "FaceTrackingStatusEnum", + "Scriptability": "None", + "DataType": { + "Enum": "TrackerFaceTrackingStatus" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "FlipHeadOrientation": { "Name": "FlipHeadOrientation", "Scriptability": "None", @@ -16605,6 +17798,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -16847,6 +18046,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MeshId": { "Content": "" }, @@ -17026,6 +18231,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "Color3": [ 0.92549026, @@ -17033,6 +18241,9 @@ 0.27450982 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -17088,6 +18299,12 @@ "CanBeDropped": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -17298,6 +18515,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -17317,6 +18537,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "EnableFluidForces": { "Bool": true }, @@ -17512,6 +18735,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Depth": { "Float32": 0.45 }, @@ -17577,6 +18806,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -17704,6 +18939,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -17714,6 +18952,9 @@ "CycleOffset": { "Float32": 0.0 }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -17757,6 +18998,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -17791,6 +19038,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -17822,6 +19075,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -17955,12 +19214,21 @@ "BorderSizePixel": { "Int32": 1 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClipsDescendants": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "Draggable": { "Bool": false }, + "Interactable": { + "Bool": true + }, "LayoutOrder": { "Int32": 0 }, @@ -18161,6 +19429,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Description": { "String": "?" }, @@ -18187,6 +19461,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -18487,6 +19767,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -18556,9 +19842,7 @@ }, "GroundController": { "Name": "GroundController", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "ControllerBase", "Properties": { "AccelerationLean": { @@ -18724,9 +20008,15 @@ "BalanceSpeed": { "Float32": 100.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "DecelerationTime": { "Float32": 0.0 }, + "DefinesCapabilities": { + "Bool": false + }, "Friction": { "Float32": 2.0 }, @@ -19325,9 +20615,15 @@ "AutoLocalize": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClipToDeviceSafeArea": { "Bool": true }, + "DefinesCapabilities": { + "Bool": false + }, "DisplayOrder": { "Int32": 0 }, @@ -19591,6 +20887,19 @@ } } }, + "Interactable": { + "Name": "Interactable", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "LayoutOrder": { "Name": "LayoutOrder", "Scriptability": "ReadWrite", @@ -20068,6 +21377,23 @@ } } }, + "TopbarInset": { + "Name": "TopbarInset", + "Scriptability": "Read", + "DataType": { + "Value": "Rect" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "TouchControlsEnabled": { "Name": "TouchControlsEnabled", "Scriptability": "ReadWrite", @@ -20296,6 +21622,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -20303,6 +21632,9 @@ 0.6745098 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Faces": { "Faces": [ "Right", @@ -20387,6 +21719,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -20449,6 +21787,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "HSRData": { "BinaryString": "" }, @@ -20594,6 +21938,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "DepthMode": { "Enum": 0 }, @@ -20835,9 +22185,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 1009 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -20890,6 +22246,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -20912,6 +22274,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "FaceId": { "Enum": 0 }, @@ -21023,6 +22391,12 @@ "BinType": { "Enum": 0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "LevelOfDetail": { "Enum": 0 }, @@ -21150,6 +22524,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "HttpEnabled": { "Bool": false }, @@ -21326,9 +22706,7 @@ "DataType": { "Value": "Bool" }, - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -21925,9 +23303,15 @@ "BreakJointsOnDeath": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CollisionType": { "Enum": 0 }, + "DefinesCapabilities": { + "Bool": false + }, "DisplayDistanceType": { "Enum": 0 }, @@ -22006,6 +23390,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -22034,6 +23424,22 @@ } } }, + "AccessoryRigidAndLayeredBlob": { + "Name": "AccessoryRigidAndLayeredBlob", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "BackAccessory": { "Name": "BackAccessory", "Scriptability": "ReadWrite", @@ -22580,6 +23986,9 @@ "AccessoryBlob": { "String": "[]" }, + "AccessoryRigidAndLayeredBlob": { + "String": "[]" + }, "Attributes": { "Attributes": {} }, @@ -22589,9 +23998,15 @@ "BodyTypeScale": { "Float32": 0.3 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClimbAnimation": { "Int64": 0 }, + "DefinesCapabilities": { + "Bool": false + }, "DepthScale": { "Float32": 1.0 }, @@ -22888,6 +24303,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -23224,9 +24645,15 @@ "BorderSizePixel": { "Int32": 1 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClipsDescendants": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "Draggable": { "Bool": false }, @@ -23258,6 +24685,9 @@ "ImageTransparency": { "Float32": 0.0 }, + "Interactable": { + "Bool": true + }, "LayoutOrder": { "Int32": 0 }, @@ -23439,6 +24869,9 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.9490197, @@ -23446,6 +24879,9 @@ 0.95294124 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Image": { "Content": "rbxasset://textures/SurfacesDefault.png" }, @@ -23690,9 +25126,15 @@ "BorderSizePixel": { "Int32": 1 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClipsDescendants": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "Draggable": { "Bool": false }, @@ -23721,6 +25163,9 @@ "ImageTransparency": { "Float32": 0.0 }, + "Interactable": { + "Bool": true + }, "LayoutOrder": { "Int32": 0 }, @@ -24025,6 +25470,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -24109,6 +25560,22 @@ } } }, + "Capabilities": { + "Name": "Capabilities", + "Scriptability": "None", + "DataType": { + "Value": "SecurityCapabilities" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ClassName": { "Name": "ClassName", "Scriptability": "Read", @@ -24143,6 +25610,22 @@ } } }, + "DefinesCapabilities": { + "Name": "DefinesCapabilities", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "HistoryId": { "Name": "HistoryId", "Scriptability": "None", @@ -24431,6 +25914,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MaxValue": { "Int64": 10 }, @@ -24471,6 +25960,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -24637,6 +26132,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -24659,6 +26157,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "EnableFluidForces": { "Bool": true }, @@ -24983,6 +26484,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -25017,6 +26524,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -25056,6 +26569,12 @@ "AuthoredHipHeight": { "Float32": 2.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "GuidBinaryString": { "BinaryString": "AAAAAAAAAAAAAAAAAAAAAA==" }, @@ -25108,6 +26627,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -25534,6 +27059,9 @@ "Brightness": { "Float32": 1.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ColorShift_Bottom": { "Color3": [ 0.0, @@ -25548,6 +27076,9 @@ 0.0 ] }, + "DefinesCapabilities": { + "Bool": false + }, "EnvironmentDiffuseScale": { "Float32": 0.0 }, @@ -25681,9 +27212,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 23 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -25778,6 +27315,9 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -25785,6 +27325,9 @@ 0.6745098 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Length": { "Float32": 5.0 }, @@ -25833,6 +27376,19 @@ } } }, + "ForceLimitsEnabled": { + "Name": "ForceLimitsEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "LineDirection": { "Name": "LineDirection", "Scriptability": "ReadWrite", @@ -25981,15 +27537,24 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 26 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, "ForceLimitMode": { "Enum": 0 }, + "ForceLimitsEnabled": { + "Bool": true + }, "LineDirection": { "Vector3": [ 1.0, @@ -26067,7 +27632,24 @@ "Service" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "ServerLiveEditingMode": { + "Name": "ServerLiveEditingMode", + "Scriptability": "None", + "DataType": { + "Enum": "ServerLiveEditingMode" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, "DefaultProperties": {} }, "LocalDebuggerConnection": { @@ -26089,6 +27671,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Disabled": { "Bool": false }, @@ -26293,6 +27881,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -26390,9 +27984,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Contents": { "String": "[]" }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -26507,6 +28107,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -26729,6 +28335,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -26811,6 +28423,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -26895,6 +28513,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -26948,6 +28572,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -27724,6 +29354,9 @@ "BrickName": { "String": "Brick" }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CardboardName": { "String": "Cardboard" }, @@ -27748,6 +29381,9 @@ "CrackedLavaName": { "String": "CrackedLava" }, + "DefinesCapabilities": { + "Bool": false + }, "DiamondPlateName": { "String": "DiamondPlate" }, @@ -28013,12 +29649,18 @@ "BaseMaterial": { "Enum": 256 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ColorMap": { "Content": "" }, "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "MaterialPattern": { "Enum": 0 }, @@ -28066,6 +29708,16 @@ "Properties": {}, "DefaultProperties": {} }, + "MemoryStoreHashMap": { + "Name": "MemoryStoreHashMap", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "MemoryStoreQueue": { "Name": "MemoryStoreQueue", "Tags": [ @@ -28087,6 +29739,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -28419,22 +30077,6 @@ "Tags": [], "Superclass": "TriangleMeshPart", "Properties": { - "AeroMeshData": { - "Name": "AeroMeshData", - "Scriptability": "None", - "DataType": { - "Value": "SharedString" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "AlternateMeshHash": { "Name": "AlternateMeshHash", "Scriptability": "None", @@ -28701,6 +30343,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -28720,6 +30365,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "DoubleSided": { "Bool": false }, @@ -28910,6 +30558,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -29129,12 +30783,18 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Condition": { "String": "" }, "ContinueExecution": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -29187,9 +30847,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ContextDataInternal": { "String": "0 1 2 " }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -29404,6 +31070,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "LevelOfDetail": { "Enum": 0 }, @@ -29536,6 +31208,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "LinkedSource": { "Content": "" }, @@ -29653,6 +31331,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "DesiredAngle": { "Float32": 0.0 }, @@ -29782,6 +31466,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "DesiredAngle": { "Float32": 0.0 }, @@ -29810,6 +31500,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "FaceId": { "Enum": 0 }, @@ -30158,6 +31854,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -30180,6 +31879,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "EnableFluidForces": { "Bool": true }, @@ -30612,6 +32314,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -30634,6 +32342,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -30741,6 +32455,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "EasingDirection": { "Enum": 0 }, @@ -30784,6 +32504,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -30818,6 +32544,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -30860,6 +32592,35 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "OperationTree": { + "Name": "OperationTree", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -31233,6 +32994,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 1.0, @@ -31240,6 +33004,9 @@ 1.0 ] }, + "DefinesCapabilities": { + "Bool": false + }, "PantsTemplate": { "Content": "" }, @@ -31336,6 +33103,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.9490197, @@ -31343,6 +33113,9 @@ 0.95294124 ] }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -31480,6 +33253,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -31499,6 +33275,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "EnableFluidForces": { "Bool": true }, @@ -31949,6 +33728,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -31971,6 +33753,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "EnableFluidForces": { "Bool": true }, @@ -32166,9 +33951,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ChildData": { "BinaryString": "" }, + "DefinesCapabilities": { + "Bool": false + }, "MeshData": { "BinaryString": "" }, @@ -32328,23 +34119,6 @@ } } }, - "FlipbookTextureCompatible": { - "Name": "FlipbookTextureCompatible", - "Scriptability": "None", - "DataType": { - "Enum": "ParticleFlipbookTextureCompatible" - }, - "Tags": [ - "Hidden", - "NotReplicated", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "Lifetime": { "Name": "Lifetime", "Scriptability": "ReadWrite", @@ -32662,6 +34436,9 @@ "Brightness": { "Float32": 1.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "ColorSequence": { "keypoints": [ @@ -32684,6 +34461,9 @@ ] } }, + "DefinesCapabilities": { + "Bool": false + }, "Drag": { "Float32": 0.0 }, @@ -32989,6 +34769,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "IsBidirectional": { "Bool": true }, @@ -33039,6 +34825,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Label": { "String": "" }, @@ -33211,6 +35003,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -33231,6 +35029,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -33455,6 +35259,19 @@ } } }, + "AreNonAnchorsShown": { + "Name": "AreNonAnchorsShown", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "AreOwnersShown": { "Name": "AreOwnersShown", "Scriptability": "ReadWrite", @@ -33585,6 +35402,19 @@ } } }, + "FluidForceDrawScale": { + "Name": "FluidForceDrawScale", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ForceCSGv2": { "Name": "ForceCSGv2", "Scriptability": "ReadWrite", @@ -33679,6 +35509,32 @@ } } }, + "ShowFluidForcesForSelectedOrHoveredAssemblies": { + "Name": "ShowFluidForcesForSelectedOrHoveredAssemblies", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SolverConvergenceMetricType": { + "Name": "SolverConvergenceMetricType", + "Scriptability": "None", + "DataType": { + "Enum": "SolverConvergenceMetricType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "SolverConvergenceVisualizationMode": { "Name": "SolverConvergenceVisualizationMode", "Scriptability": "None", @@ -33744,6 +35600,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -33794,9 +35656,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 194 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -33820,9 +35688,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 194 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -33846,6 +35720,17 @@ "Properties": {}, "DefaultProperties": {} }, + "PlatformFriendsService": { + "Name": "PlatformFriendsService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Player": { "Name": "Player", "Tags": [], @@ -34797,9 +36682,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CustomPoliciesEnabled": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "EmulatedCountryCode": { "String": "" }, @@ -34892,6 +36783,17 @@ "Properties": {}, "DefaultProperties": {} }, + "PlayerViewService": { + "Name": "PlayerViewService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Players": { "Name": "Players", "Tags": [ @@ -35147,9 +37049,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CharacterAutoLoads": { "Bool": true }, + "DefinesCapabilities": { + "Bool": false + }, "MaxPlayers": { "Int32": 12 }, @@ -35424,6 +37332,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Manifest": { "String": "{\"Metadata\":{\"TargetDataModels\": [\"Edit\", \"Server\", \"Client\"]},\"Permissions\":{}}" }, @@ -35737,6 +37651,9 @@ "Brightness": { "Float32": 1.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "Color3": [ 1.0, @@ -35744,6 +37661,9 @@ 1.0 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -35879,6 +37799,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "EasingDirection": { "Enum": 0 }, @@ -35980,9 +37906,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 1009 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -36045,6 +37977,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -36251,9 +38189,15 @@ "AutoLocalize": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClickablePrompt": { "Bool": true }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -36334,6 +38278,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -36392,6 +38342,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -36433,6 +38389,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -36450,6 +38412,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -36539,6 +38507,9 @@ "Browsable": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClassCategory": { "String": "" }, @@ -36548,6 +38519,9 @@ "Constraint": { "String": "" }, + "DefinesCapabilities": { + "Bool": false + }, "Deprecated": { "Bool": false }, @@ -36616,6 +38590,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -36636,6 +38616,9 @@ "Browsable": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClassCategory": { "String": "" }, @@ -36645,6 +38628,9 @@ "Constraint": { "String": "" }, + "DefinesCapabilities": { + "Bool": false + }, "Deprecated": { "Bool": false }, @@ -36701,6 +38687,9 @@ "Browsable": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClassCategory": { "String": "" }, @@ -36710,6 +38699,9 @@ "Constraint": { "String": "" }, + "DefinesCapabilities": { + "Bool": false + }, "Deprecated": { "Bool": false }, @@ -36763,6 +38755,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -36780,6 +38778,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -36797,6 +38801,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -37035,6 +39045,9 @@ "Browsable": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClassCategory": { "String": "" }, @@ -37044,6 +39057,9 @@ "Constraint": { "String": "" }, + "DefinesCapabilities": { + "Bool": false + }, "Deprecated": { "Bool": false }, @@ -37097,6 +39113,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -37114,6 +39136,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -37122,6 +39150,17 @@ } } }, + "ReflectionService": { + "Name": "ReflectionService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "RemoteCursorService": { "Name": "RemoteCursorService", "Tags": [ @@ -37152,6 +39191,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -37169,6 +39214,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -37598,6 +39649,9 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ComparisonDiffThreshold": { "Int32": 10 }, @@ -37607,6 +39661,9 @@ "ComparisonPsnrThreshold": { "Float32": 50.0 }, + "DefinesCapabilities": { + "Bool": false + }, "Description": { "String": "" }, @@ -37648,6 +39705,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -37668,6 +39731,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -37751,9 +39820,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "DecayTime": { "Float32": 1.5 }, + "DefinesCapabilities": { + "Bool": false + }, "Density": { "Float32": 1.0 }, @@ -37780,6 +39855,17 @@ } } }, + "RibbonNotificationService": { + "Name": "RibbonNotificationService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "RigidConstraint": { "Name": "RigidConstraint", "Tags": [], @@ -37789,9 +39875,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 194 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -38010,9 +40102,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CartoonFactor": { "Float32": 0.7 }, + "DefinesCapabilities": { + "Bool": false + }, "MaxSpeed": { "Float32": 30.0 }, @@ -38147,9 +40245,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 26 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -38463,6 +40567,19 @@ } } }, + "ValidateUgcBody": { + "Name": "ValidateUgcBody", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "WorldForward": { "Name": "WorldForward", "Scriptability": "ReadWrite", @@ -38622,9 +40739,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 25 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -38726,6 +40849,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -38803,6 +40932,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -38880,6 +41015,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -38933,6 +41074,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -38940,7 +41087,7 @@ "Tags": [] }, "ValuesAndTimes": { - "BinaryString": "AAAAAAAAAAAAAAAAAAAWRQAAAAA=" + "BinaryString": "AQAAAAAAAAAAAAAAAAAWRQAAAAA=" } } }, @@ -39135,9 +41282,15 @@ "AutoLocalize": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClipToDeviceSafeArea": { "Bool": true }, + "DefinesCapabilities": { + "Bool": false + }, "DisplayOrder": { "Int32": 0 }, @@ -39317,6 +41470,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Disabled": { "Bool": false }, @@ -39578,6 +41737,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -39952,9 +42117,15 @@ ] ] }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClipsDescendants": { "Bool": true }, + "DefinesCapabilities": { + "Bool": false + }, "Draggable": { "Bool": false }, @@ -39964,6 +42135,9 @@ "HorizontalScrollBarInset": { "Enum": 0 }, + "Interactable": { + "Bool": true + }, "LayoutOrder": { "Int32": 0 }, @@ -40164,6 +42338,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -40183,6 +42360,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "Disabled": { "Bool": false }, @@ -40432,6 +42612,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -40521,6 +42707,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -40528,6 +42717,9 @@ 0.6745098 ] }, + "DefinesCapabilities": { + "Bool": false + }, "LineThickness": { "Float32": 0.15 }, @@ -40616,6 +42808,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -40623,6 +42818,9 @@ 0.6745098 ] }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -40662,6 +42860,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -40669,6 +42870,9 @@ 0.6745098 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Point": { "Vector3": [ 0.0, @@ -40743,6 +42947,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -40750,6 +42957,9 @@ 0.6745098 ] }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -40837,6 +43047,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "LoadStringEnabled": { "Bool": false }, @@ -40861,6 +43077,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -40918,6 +43140,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "HiddenServices": { "BinaryString": "AAAAAA==" }, @@ -40976,6 +43204,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 1.0, @@ -40983,6 +43214,9 @@ 1.0 ] }, + "DefinesCapabilities": { + "Bool": false + }, "ShirtTemplate": { "Content": "" }, @@ -41030,6 +43264,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 1.0, @@ -41037,6 +43274,9 @@ 1.0 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Graphic": { "Content": "" }, @@ -41101,6 +43341,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -41270,6 +43516,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -41289,6 +43538,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "EnableFluidForces": { "Bool": true }, @@ -41456,6 +43708,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SkinColor": { "BrickColor": 226 }, @@ -41633,9 +43891,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CelestialBodiesShown": { "Bool": true }, + "DefinesCapabilities": { + "Bool": false + }, "MoonAngularSize": { "Float32": 11.0 }, @@ -42020,6 +44284,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "Color3": [ 1.0, @@ -42027,6 +44294,9 @@ 1.0 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -42124,6 +44394,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -42668,6 +44944,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "LoopRegion": { "NumberRange": [ 0.0, @@ -42780,6 +45062,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -42887,6 +45175,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "DistanceFactor": { "Float32": 3.33 }, @@ -42975,6 +45269,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -43136,6 +45436,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -43155,6 +45458,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "Duration": { "Int32": 10 }, @@ -43333,6 +45639,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MeshId": { "Content": "" }, @@ -43426,6 +45738,9 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -43433,6 +45748,9 @@ 0.6745098 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Radius": { "Float32": 1.0 }, @@ -43515,6 +45833,9 @@ "Brightness": { "Float32": 1.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "Color3": [ 1.0, @@ -43522,6 +45843,9 @@ 1.0 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -43698,6 +46022,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Coils": { "Float32": 3.0 }, @@ -43707,6 +46034,9 @@ "Damping": { "Float32": 0.0 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -43918,6 +46248,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -43947,6 +46283,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -43964,6 +46306,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -44072,6 +46420,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "ResetPlayerGuiOnSpawn": { "Bool": true }, @@ -44107,6 +46461,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -44138,6 +46498,21 @@ } } }, + "AnimationCompositorMode": { + "Name": "AnimationCompositorMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AnimationCompositorMode" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "AutoJumpEnabled": { "Name": "AutoJumpEnabled", "Scriptability": "ReadWrite", @@ -44158,7 +46533,24 @@ "Enum": "AvatarJointUpgrade" }, "Tags": [ - "NotBrowsable" + "NotBrowsable", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AvatarJointUpgrade_Serialized": { + "Name": "AvatarJointUpgrade_Serialized", + "Scriptability": "None", + "DataType": { + "Enum": "AvatarJointUpgrade" + }, + "Tags": [ + "Hidden", + "NotScriptable" ], "Kind": { "Canonical": { @@ -44754,13 +47146,16 @@ "AllowCustomAnimations": { "Bool": true }, + "AnimationCompositorMode": { + "Enum": 0 + }, "Attributes": { "Attributes": {} }, "AutoJumpEnabled": { "Bool": true }, - "AvatarJointUpgrade": { + "AvatarJointUpgrade_Serialized": { "Enum": 0 }, "CameraMaxZoomDistance": { @@ -44772,6 +47167,9 @@ "CameraMode": { "Enum": 0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CharacterJumpHeight": { "Float32": 7.2 }, @@ -44790,6 +47188,9 @@ "DeathStyle": { "Enum": 0 }, + "DefinesCapabilities": { + "Bool": false + }, "DevCameraOcclusionMode": { "Enum": 0 }, @@ -44914,6 +47315,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -45141,6 +47548,17 @@ "Properties": {}, "DefaultProperties": {} }, + "StreamingService": { + "Name": "StreamingService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "StringValue": { "Name": "StringValue", "Tags": [], @@ -45164,6 +47582,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -45566,6 +47990,32 @@ } } }, + "CameraAdaptiveSpeed": { + "Name": "CameraAdaptiveSpeed", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraTweenFocus": { + "Name": "CameraTweenFocus", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Clear Output On Start": { "Name": "Clear Output On Start", "Scriptability": "ReadWrite", @@ -45948,6 +48398,19 @@ } } }, + "FreeCameraSpeedScroll": { + "Name": "FreeCameraSpeedScroll", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Function Name Color": { "Name": "Function Name Color", "Scriptability": "ReadWrite", @@ -46114,6 +48577,32 @@ } } }, + "LargeFileLineCountThreshold": { + "Name": "LargeFileLineCountThreshold", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LargeFileThreshold": { + "Name": "LargeFileThreshold", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Line Thickness": { "Name": "Line Thickness", "Scriptability": "ReadWrite", @@ -46407,19 +48896,6 @@ } } }, - "Render Throttle Percentage": { - "Name": "Render Throttle Percentage", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Int32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "Respect Studio shortcuts when game has focus": { "Name": "Respect Studio shortcuts when game has focus", "Scriptability": "ReadWrite", @@ -47067,9 +49543,125 @@ "Properties": {}, "DefaultProperties": {} }, + "StudioAttachment": { + "Name": "StudioAttachment", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "AutoHideParent": { + "Name": "AutoHideParent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsArrowVisible": { + "Name": "IsArrowVisible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Offset": { + "Name": "Offset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SourceAnchorPoint": { + "Name": "SourceAnchorPoint", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TargetAnchorPoint": { + "Name": "TargetAnchorPoint", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "AutoHideParent": { + "Bool": false + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, + "IsArrowVisible": { + "Bool": false + }, + "Offset": { + "Vector2": [ + 0.0, + 0.0 + ] + }, + "SourceAnchorPoint": { + "Vector2": [ + 0.0, + 0.0 + ] + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "TargetAnchorPoint": { + "Vector2": [ + 0.0, + 0.0 + ] + } + } + }, "StudioCallout": { "Name": "StudioCallout", - "Tags": [], + "Tags": [ + "NotCreatable", + "NotReplicated" + ], "Superclass": "Instance", "Properties": { "AnchorPoint": { @@ -47169,17 +49761,7 @@ } } }, - "DefaultProperties": { - "Attributes": { - "Attributes": {} - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "Tags": [] - } - } + "DefaultProperties": {} }, "StudioData": { "Name": "StudioData", @@ -47209,6 +49791,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "EnableScriptCollabByDefaultOnLoad": { "Bool": false }, @@ -47301,20 +49889,13 @@ }, "StudioObjectBase": { "Name": "StudioObjectBase", - "Tags": [], + "Tags": [ + "NotCreatable", + "NotReplicated" + ], "Superclass": "Instance", "Properties": {}, - "DefaultProperties": { - "Attributes": { - "Attributes": {} - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "Tags": [] - } - } + "DefaultProperties": {} }, "StudioPublishService": { "Name": "StudioPublishService", @@ -47568,20 +50149,24 @@ }, "StudioWidget": { "Name": "StudioWidget", - "Tags": [], + "Tags": [ + "NotCreatable", + "NotReplicated" + ], "Superclass": "StudioObjectBase", "Properties": {}, - "DefaultProperties": { - "Attributes": { - "Attributes": {} - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "Tags": [] - } - } + "DefaultProperties": {} + }, + "StudioWidgetsService": { + "Name": "StudioWidgetsService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} }, "StyleBase": { "Name": "StyleBase", @@ -47631,6 +50216,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Index": { "Int32": -1 }, @@ -47665,6 +50256,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -47744,11 +50341,17 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Index": { "Int32": -1 }, "PropertiesSerialize": { - "BinaryString": "" + "BinaryString": "AAAAAA==" }, "Selector": { "String": "" @@ -47770,6 +50373,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -47825,6 +50434,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -47933,9 +50548,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ColorMap": { "Content": "" }, + "DefinesCapabilities": { + "Bool": false + }, "MetalnessMap": { "Content": "" }, @@ -48041,6 +50662,19 @@ } } }, + "MaxDistance": { + "Name": "MaxDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PixelsPerStud": { "Name": "PixelsPerStud", "Scriptability": "ReadWrite", @@ -48131,9 +50765,15 @@ 600.0 ] }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClipsDescendants": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -48143,6 +50783,9 @@ "LightInfluence": { "Float32": 0.0 }, + "MaxDistance": { + "Float32": 0.0 + }, "PixelsPerStud": { "Float32": 50.0 }, @@ -48288,6 +50931,9 @@ "Brightness": { "Float32": 1.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "Color3": [ 1.0, @@ -48295,6 +50941,9 @@ 1.0 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -48338,6 +50987,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -48345,6 +50997,9 @@ 0.6745098 ] }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -48364,9 +51019,7 @@ }, "SwimController": { "Name": "SwimController", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "ControllerBase", "Properties": { "AccelerationTime": { @@ -48445,6 +51098,12 @@ "BalanceRigidityEnabled": { "Bool": false }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MoveSpeedFactor": { "Float32": 1.0 }, @@ -48704,6 +51363,12 @@ "AutoAssignable": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -48775,6 +51440,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -48874,6 +51545,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "ReservedServerAccessCode": { "String": "" }, @@ -48920,6 +51597,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -49042,6 +51725,22 @@ } } }, + "GrassLength": { + "Name": "GrassLength", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotBrowsable", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "IsSmooth": { "Name": "IsSmooth", "Scriptability": "Read", @@ -49305,6 +52004,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -49327,6 +52029,9 @@ "Decoration": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "EnableFluidForces": { "Bool": true }, @@ -49342,6 +52047,9 @@ "FrontSurfaceInput": { "Enum": 0 }, + "GrassLength": { + "Float32": 0.7 + }, "LeftParamA": { "Float32": -0.5 }, @@ -49711,9 +52419,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ColorMap": { "Content": "" }, + "DefinesCapabilities": { + "Bool": false + }, "Face": { "Enum": 1 }, @@ -49853,6 +52567,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "ExtentsMax": { "Vector3int16": [ 0, @@ -49946,10 +52666,13 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotReplicated" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -49959,10 +52682,13 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotReplicated" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -50058,18 +52784,18 @@ "AutoRuns": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Description": { "String": "" }, "ExecuteWithStudioRun": { "Bool": false }, - "Is30FpsThrottleEnabled": { - "Bool": true - }, - "IsPhysicsEnvironmentalThrottled": { - "Bool": true - }, "IsSleepAllowed": { "Bool": true }, @@ -50649,12 +53375,18 @@ "BorderSizePixel": { "Int32": 1 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClearTextOnFocus": { "Bool": true }, "ClipsDescendants": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "Draggable": { "Bool": false }, @@ -50666,6 +53398,9 @@ "cachedFaceId": "rbxasset://fonts/arial.ttf" } }, + "Interactable": { + "Bool": true + }, "LayoutOrder": { "Int32": 0 }, @@ -51227,9 +53962,15 @@ "BorderSizePixel": { "Int32": 1 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClipsDescendants": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "Draggable": { "Bool": false }, @@ -51241,6 +53982,9 @@ "cachedFaceId": "rbxasset://fonts/arial.ttf" } }, + "Interactable": { + "Bool": true + }, "LayoutOrder": { "Int32": 0 }, @@ -51380,6 +54124,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -51393,6 +54143,19 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "AutocompleteVisible": { + "Name": "AutocompleteVisible", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Enabled": { "Name": "Enabled", "Scriptability": "ReadWrite", @@ -51437,6 +54200,15 @@ "Attributes": { "Attributes": {} }, + "AutocompleteVisible": { + "Bool": true + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -51574,6 +54346,19 @@ "Serialization": "Serializes" } } + }, + "Translation": { + "Name": "Translation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": {} @@ -51608,12 +54393,31 @@ "Serialization": "DoesNotSerialize" } } + }, + "Translation": { + "Name": "Translation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -51630,6 +54434,32 @@ ], "Superclass": "Instance", "Properties": { + "ChatTranslationEnabled": { + "Name": "ChatTranslationEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ChatTranslationToggleEnabled": { + "Name": "ChatTranslationToggleEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ChatVersion": { "Name": "ChatVersion", "Scriptability": "Read", @@ -51674,6 +54504,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "ChatTranslationEnabled": { + "Bool": true + }, + "ChatTranslationToggleEnabled": { + "Bool": false + }, "ChatVersion": { "Enum": 0 }, @@ -51683,6 +54522,9 @@ "CreateDefaultTextChannels": { "Bool": true }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -52152,9 +54994,15 @@ "BorderSizePixel": { "Int32": 1 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClipsDescendants": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "Draggable": { "Bool": false }, @@ -52166,6 +55014,9 @@ "cachedFaceId": "rbxasset://fonts/arial.ttf" } }, + "Interactable": { + "Bool": true + }, "LayoutOrder": { "Int32": 0 }, @@ -52415,6 +55266,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 1.0, @@ -52422,6 +55276,9 @@ 1.0 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Face": { "Enum": 5 }, @@ -52556,6 +55413,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -52730,6 +55593,12 @@ "CanBeDropped": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -52886,9 +55755,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 23 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -53059,6 +55934,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Coils": { "Float32": 8.0 }, @@ -53068,6 +55946,9 @@ "Damping": { "Float32": 0.01 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -53124,6 +56005,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -53446,6 +56333,9 @@ "Brightness": { "Float32": 1.0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "ColorSequence": { "keypoints": [ @@ -53468,6 +56358,9 @@ ] } }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -53614,6 +56507,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Depth": { "Float32": 1.0 }, @@ -53644,6 +56543,22 @@ ], "Superclass": "BasePart", "Properties": { + "AeroMeshData": { + "Name": "AeroMeshData", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "CollisionFidelity": { "Name": "CollisionFidelity", "Scriptability": "ReadWrite", @@ -53797,6 +56712,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -53816,6 +56734,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "EnableFluidForces": { "Bool": true }, @@ -53983,6 +56904,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -54030,6 +56957,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -54050,6 +56983,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -54124,6 +57063,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "DominantAxis": { "Enum": 0 }, @@ -54185,12 +57130,18 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CornerRadius": { "UDim": [ 0.0, 8 ] }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -54274,6 +57225,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "ColorSequence": { "keypoints": [ @@ -54296,6 +57250,9 @@ ] } }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -54426,6 +57383,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CellPadding": { "UDim2": [ [ @@ -54450,6 +57410,9 @@ ] ] }, + "DefinesCapabilities": { + "Bool": false + }, "FillDirection": { "Enum": 0 }, @@ -54587,6 +57550,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "FillDirection": { "Enum": 1 }, @@ -54675,6 +57644,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "PaddingBottom": { "UDim": [ 0.0, @@ -54853,9 +57828,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Circular": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "EasingDirection": { "Enum": 1 }, @@ -54923,6 +57904,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Scale": { "Float32": 1.0 }, @@ -54970,6 +57957,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MaxSize": { "Vector2": [ null, @@ -55081,6 +58074,9 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "Color3": [ 0.0, @@ -55088,6 +58084,9 @@ 0.0 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -55170,6 +58169,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "FillDirection": { "Enum": 1 }, @@ -55247,6 +58252,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "MaxTextSize": { "Int32": 100 }, @@ -55335,6 +58346,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -55357,6 +58371,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "EnableFluidForces": { "Bool": true }, @@ -55571,9 +58588,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 1009 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -55632,6 +58655,12 @@ "CachedData": { "String": "{\"lastSaveTime\":0,\"lastKnownPublishRequest\":0,\"users\":[]}" }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -56307,6 +59336,22 @@ } } }, + "VRComfortSetting": { + "Name": "VRComfortSetting", + "Scriptability": "None", + "DataType": { + "Enum": "VRComfortSetting" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "VREnabled": { "Name": "VREnabled", "Scriptability": "None", @@ -56362,6 +59407,54 @@ } } }, + "VRSmoothRotationEnabledCustomOption": { + "Name": "VRSmoothRotationEnabledCustomOption", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VRThirdPersonFollowCamEnabled": { + "Name": "VRThirdPersonFollowCamEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VRThirdPersonFollowCamEnabledCustomOption": { + "Name": "VRThirdPersonFollowCamEnabledCustomOption", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "VignetteEnabled": { "Name": "VignetteEnabled", "Scriptability": "Read", @@ -56375,6 +59468,22 @@ } } }, + "VignetteEnabledCustomOption": { + "Name": "VignetteEnabledCustomOption", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "gaID": { "Name": "gaID", "Scriptability": "None", @@ -56768,6 +59877,277 @@ }, "DefaultProperties": {} }, + "UserNotification": { + "Name": "UserNotification", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Id": { + "Name": "Id", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Payload": { + "Name": "Payload", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "UserNotificationPayload": { + "Name": "UserNotificationPayload", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "AnalyticsData": { + "Name": "AnalyticsData", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "JoinExperience": { + "Name": "JoinExperience", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MessageId": { + "Name": "MessageId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Type": { + "Name": "Type", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, + "MessageId": { + "String": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "Type": { + "String": "" + } + } + }, + "UserNotificationPayloadAnalyticsData": { + "Name": "UserNotificationPayloadAnalyticsData", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Category": { + "Name": "Category", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "Category": { + "String": "" + }, + "DefinesCapabilities": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "UserNotificationPayloadJoinExperience": { + "Name": "UserNotificationPayloadJoinExperience", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "LaunchData": { + "Name": "LaunchData", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, + "LaunchData": { + "String": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, + "UserNotificationPayloadParameterValue": { + "Name": "UserNotificationPayloadParameterValue", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Int64Value": { + "Name": "Int64Value", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StringValue": { + "Name": "StringValue", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, + "Int64Value": { + "Int64": 0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "StringValue": { + "String": "" + }, + "Tags": { + "Tags": [] + } + } + }, "UserService": { "Name": "UserService", "Tags": [ @@ -56898,6 +60278,52 @@ } } }, + "QuestASWState": { + "Name": "QuestASWState", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "QuestDisplayRefreshRate": { + "Name": "QuestDisplayRefreshRate", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ThirdPersonFollowCamEnabled": { + "Name": "ThirdPersonFollowCamEnabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "VRDeviceAvailable": { "Name": "VRDeviceAvailable", "Scriptability": "None", @@ -56970,6 +60396,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -57006,6 +60438,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -57037,6 +60475,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -57104,9 +60548,15 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color": { "BrickColor": 23 }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -57140,6 +60590,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -57373,6 +60829,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -57392,6 +60851,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "Disabled": { "Bool": false }, @@ -57660,9 +61122,15 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CurrentAngle": { "Float32": 0.0 }, + "DefinesCapabilities": { + "Bool": false + }, "DesiredAngle": { "Float32": 0.0 }, @@ -57767,6 +61235,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -57972,12 +61446,21 @@ "BorderSizePixel": { "Int32": 1 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClipsDescendants": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "Draggable": { "Bool": false }, + "Interactable": { + "Bool": true + }, "LayoutOrder": { "Int32": 0 }, @@ -58073,6 +61556,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -58293,9 +61782,15 @@ "CameraFieldOfView": { "Float32": 1.2217306 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClipsDescendants": { "Bool": false }, + "DefinesCapabilities": { + "Bool": false + }, "Draggable": { "Bool": false }, @@ -58309,6 +61804,9 @@ "ImageTransparency": { "Float32": 0.0 }, + "Interactable": { + "Bool": true + }, "LayoutOrder": { "Int32": 0 }, @@ -58419,6 +61917,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -58501,6 +62005,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -58530,6 +62040,36 @@ } } }, + "UseNewAudioApi": { + "Name": "UseNewAudioApi", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UseNewControlPaths": { + "Name": "UseNewControlPaths", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "UseNewJoinFlow": { "Name": "UseNewJoinFlow", "Scriptability": "None", @@ -58580,6 +62120,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "EnableDefaultVoice": { "Bool": true }, @@ -58662,6 +62208,9 @@ "CanTouch": { "Bool": true }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "CastShadow": { "Bool": true }, @@ -58681,6 +62230,9 @@ "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, + "DefinesCapabilities": { + "Bool": false + }, "EnableFluidForces": { "Bool": true }, @@ -58872,6 +62424,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -59065,6 +62623,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -59156,6 +62720,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -59225,6 +62795,9 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "Color3": { "Color3": [ 0.050980397, @@ -59232,6 +62805,9 @@ 0.6745098 ] }, + "DefinesCapabilities": { + "Bool": false + }, "Scale": { "Vector3": [ 1.0, @@ -59407,6 +62983,21 @@ } } }, + "EditorLiveScripting": { + "Name": "EditorLiveScripting", + "Scriptability": "None", + "DataType": { + "Enum": "EditorLiveScripting" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ExplicitAutoJoints": { "Name": "ExplicitAutoJoints", "Scriptability": "None", @@ -59494,21 +63085,6 @@ } } }, - "HumanoidOnlySetCollisionsOnStateChange": { - "Name": "HumanoidOnlySetCollisionsOnStateChange", - "Scriptability": "None", - "DataType": { - "Enum": "HumanoidOnlySetCollisionsOnStateChange" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "IKControlConstraintSupport": { "Name": "IKControlConstraintSupport", "Scriptability": "None", @@ -59726,8 +63302,7 @@ "Tags": [ "Hidden", "NotReplicated", - "NotScriptable", - "WriteOnly" + "NotScriptable" ], "Kind": { "Canonical": { @@ -59811,15 +63386,24 @@ "AvatarUnificationMode": { "Enum": 0 }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "ClientAnimatorThrottling": { "Enum": 0 }, "CollisionGroupData": { "BinaryString": "AQEABP////8HRGVmYXVsdA==" }, + "DefinesCapabilities": { + "Bool": false + }, "DistributedGameTime": { "Float64": 0.0 }, + "EditorLiveScripting": { + "Enum": 0 + }, "ExplicitAutoJoints": { "Bool": true }, @@ -59839,9 +63423,6 @@ "Gravity": { "Float32": 196.2 }, - "HumanoidOnlySetCollisionsOnStateChange": { - "Enum": 0 - }, "IKControlConstraintSupport": { "Enum": 0 }, @@ -59978,6 +63559,12 @@ "Attributes": { "Attributes": {} }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "LevelOfDetail": { "Enum": 0 }, @@ -60302,6 +63889,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "Enabled": { "Bool": true }, @@ -60470,6 +64063,12 @@ ] } }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, "HSRAssetId": { "Content": "" }, @@ -60645,6 +64244,31 @@ "Fail": 4 } }, + "AnimationClipFromVideoStatus": { + "name": "AnimationClipFromVideoStatus", + "items": { + "Cancelled": 11, + "ErrorGeneric": 4, + "ErrorMultiplePeople": 12, + "ErrorNoPersonDetected": 8, + "ErrorUploadingVideo": 2001, + "ErrorVideoTooLong": 7, + "ErrorVideoUnstable": 9, + "Initializing": 0, + "Pending": 1, + "Processing": 2, + "Success": 6, + "Timeout": 10 + } + }, + "AnimationCompositorMode": { + "name": "AnimationCompositorMode", + "items": { + "Default": 0, + "Disabled": 2, + "Enabled": 1 + } + }, "AnimationPriority": { "name": "AnimationPriority", "items": { @@ -60717,6 +64341,13 @@ "ScaleWithParentSize": 1 } }, + "AssetCreatorType": { + "name": "AssetCreatorType", + "items": { + "Group": 1, + "User": 0 + } + }, "AssetFetchStatus": { "name": "AssetFetchStatus", "items": { @@ -61223,12 +64854,20 @@ "Enabled": 2 } }, + "CollaboratorStatus": { + "name": "CollaboratorStatus", + "items": { + "Editing3D": 0, + "None": 3, + "PrivateScripting": 2, + "Scripting": 1 + } + }, "CollisionFidelity": { "name": "CollisionFidelity", "items": { "Box": 2, "Default": 0, - "DynamicPreciseConvexDecomposition": 4, "Hull": 1, "PreciseConvexDecomposition": 3 } @@ -61287,7 +64926,9 @@ "CommandLinePermissions": 4, "Deprecated": 1, "IncorrectIndexType": 2, + "Invalidated": 10, "PluginPermissions": 3, + "PutCursorBeforeEnd": 11, "PutCursorInParens": 7, "RobloxPermissions": 5, "TypeCorrect": 8 @@ -61357,6 +64998,11 @@ "DisconnectSendPacketError": 262, "DisconnectTimeout": 266, "DisconnectWrongVersion": 280, + "NetworkInternal": 296, + "NetworkMisbehavior": 299, + "NetworkSecurity": 300, + "NetworkSend": 297, + "NetworkTimeout": 298, "OK": 0, "PlacelaunchCustomMessage": 610, "PlacelaunchDisabled": 515, @@ -61376,6 +65022,7 @@ "PlacelaunchUserPrivacyUnauthorized": 533, "PlayerRemoved": 291, "ReplicatorTimeout": 290, + "ServerShutdown": 288, "TeleportErrors": 768, "TeleportFailure": 769, "TeleportFlooded": 774, @@ -61472,7 +65119,10 @@ "items": { "GetAsync": 0, "GetSortedAsync": 3, + "GetVersionAsync": 7, + "ListAsync": 6, "OnUpdate": 5, + "RemoveVersionAsync": 8, "SetIncrementAsync": 1, "SetIncrementSortedAsync": 4, "UpdateAsync": 2 @@ -61723,6 +65373,14 @@ "Sine": 1 } }, + "EditorLiveScripting": { + "name": "EditorLiveScripting", + "items": { + "Default": 0, + "Disabled": 1, + "Enabled": 2 + } + }, "ElasticBehavior": { "name": "ElasticBehavior", "items": { @@ -62024,6 +65682,7 @@ "items": { "Hover": 1, "Idle": 0, + "NonInteractable": 3, "Press": 2 } }, @@ -62141,14 +65800,6 @@ "DisplayWhenDamaged": 0 } }, - "HumanoidOnlySetCollisionsOnStateChange": { - "name": "HumanoidOnlySetCollisionsOnStateChange", - "items": { - "Default": 0, - "Disabled": 1, - "Enabled": 2 - } - }, "HumanoidRigType": { "name": "HumanoidRigType", "items": { @@ -62224,6 +65875,13 @@ "Pending": 1 } }, + "ImageCombineType": { + "name": "ImageCombineType", + "items": { + "BlendSourceOver": 1, + "Overwrite": 2 + } + }, "InOut": { "name": "InOut", "items": { @@ -62600,6 +66258,23 @@ "ObjectPosition": 2 } }, + "LiveEditingAtomicUpdateResponse": { + "name": "LiveEditingAtomicUpdateResponse", + "items": { + "FailureGuidNotFound": 1, + "FailureHashMismatch": 2, + "FailureOperationIllegal": 3, + "Success": 0 + } + }, + "LiveEditingBroadcastMessageType": { + "name": "LiveEditingBroadcastMessageType", + "items": { + "Error": 2, + "Normal": 0, + "Warning": 1 + } + }, "LoadCharacterLayeredClothing": { "name": "LoadCharacterLayeredClothing", "items": { @@ -62833,6 +66508,16 @@ "Top": 1 } }, + "OperationType": { + "name": "OperationType", + "items": { + "Intersection": 3, + "Null": 0, + "Primitive": 4, + "Subtraction": 2, + "Union": 1 + } + }, "OrientationAlignmentMode": { "name": "OrientationAlignmentMode", "items": { @@ -63075,6 +66760,17 @@ "TwoAttachment": 1 } }, + "PrimitiveType": { + "name": "PrimitiveType", + "items": { + "Ball": 1, + "Block": 3, + "CornerWedge": 5, + "Cylinder": 2, + "Null": 0, + "Wedge": 4 + } + }, "PrivilegeType": { "name": "PrivilegeType", "items": { @@ -63307,6 +67003,7 @@ "MaterialPicker": 6, "Move": 3, "None": 9, + "PivotEditor": 10, "Rotate": 2, "Scale": 1, "Select": 0, @@ -63404,7 +67101,8 @@ "BadFieldOfViewDeg": 3, "BadThumbnailType": 1, "BadYRotDeg": 2, - "Other": 5 + "Other": 5, + "Throttled": 6 } }, "SaveFilter": { @@ -63459,7 +67157,8 @@ "items": { "CoreUISafeInsets": 2, "DeviceSafeInsets": 1, - "None": 0 + "None": 0, + "TopbarSafeInsets": 3 } }, "ScreenOrientation": { @@ -63535,6 +67234,14 @@ "OnlineGame": 2 } }, + "ServerLiveEditingMode": { + "name": "ServerLiveEditingMode", + "items": { + "Disabled": 2, + "Enabled": 1, + "Uninitialized": 0 + } + }, "ServiceVisibility": { "name": "ServiceVisibility", "items": { @@ -63569,6 +67276,13 @@ "RelativeYY": 2 } }, + "SolverConvergenceMetricType": { + "name": "SolverConvergenceMetricType", + "items": { + "AlgorithmAgnostic": 1, + "IterationBased": 0 + } + }, "SolverConvergenceVisualizationMode": { "name": "SolverConvergenceVisualizationMode", "items": { @@ -63869,6 +67583,19 @@ "NoSupports": 2 } }, + "SubscriptionPaymentStatus": { + "name": "SubscriptionPaymentStatus", + "items": { + "Paid": 0, + "Refunded": 1 + } + }, + "SubscriptionPeriod": { + "name": "SubscriptionPeriod", + "items": { + "Month": 0 + } + }, "SurfaceConstraint": { "name": "SurfaceConstraint", "items": { @@ -63941,7 +67668,8 @@ "TeleportToPlaceInstance": 1, "TeleportToPrivateServer": 2, "TeleportToSpawnByName": 0, - "TeleportUnknown": 4 + "TeleportToVIPServer": 4, + "TeleportUnknown": 5 } }, "TeleportResult": { @@ -63972,7 +67700,8 @@ "items": { "ToInstance": 1, "ToPlace": 0, - "ToReservedServer": 2 + "ToReservedServer": 2, + "ToVIPServer": 3 } }, "TerrainAcquisitionMethod": { @@ -64187,6 +67916,18 @@ "ForceDisabled": 0 } }, + "TrackerFaceTrackingStatus": { + "name": "TrackerFaceTrackingStatus", + "items": { + "FaceTrackingHasTrackingError": 4, + "FaceTrackingIsOccluded": 5, + "FaceTrackingLost": 3, + "FaceTrackingNoFaceFound": 1, + "FaceTrackingSuccess": 0, + "FaceTrackingUninitialized": 6, + "FaceTrackingUnknown": 2 + } + }, "TrackerLodFlagMode": { "name": "TrackerLodFlagMode", "items": { @@ -64299,6 +68040,15 @@ "Touch": 7 } }, + "VRComfortSetting": { + "name": "VRComfortSetting", + "items": { + "Comfort": 0, + "Custom": 3, + "Expert": 2, + "Normal": 1 + } + }, "VRSafetyBubbleMode": { "name": "VRSafetyBubbleMode", "items": { @@ -64410,6 +68160,14 @@ "Leaving": 4 } }, + "VoiceControlPath": { + "name": "VoiceControlPath", + "items": { + "Join": 2, + "Publish": 0, + "Subscribe": 1 + } + }, "VolumetricAudio": { "name": "VolumetricAudio", "items": { diff --git a/plugin/rbx_dom_lua/init.lua b/plugin/rbx_dom_lua/init.lua index 4230a0a1..2d390a24 100644 --- a/plugin/rbx_dom_lua/init.lua +++ b/plugin/rbx_dom_lua/init.lua @@ -24,7 +24,8 @@ local function findCanonicalPropertyDescriptor(className, propertyName) return PropertyDescriptor.fromRaw( currentClass.Properties[aliasData.AliasFor], currentClassName, - aliasData.AliasFor) + aliasData.AliasFor + ) end return nil diff --git a/plugin/rbx_dom_lua/init.spec.lua b/plugin/rbx_dom_lua/init.spec.lua deleted file mode 100644 index 4cafe5ae..00000000 --- a/plugin/rbx_dom_lua/init.spec.lua +++ /dev/null @@ -1,7 +0,0 @@ -return function() - local RbxDom = require(script.Parent) - - it("should load", function() - expect(RbxDom).to.be.ok() - end) -end \ No newline at end of file From 41fca4a2bb10791eb8b1868360db76390ced128b Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 3 Oct 2023 21:04:21 -0700 Subject: [PATCH 1340/1504] Set version to Rojo 7.4.0-rc1 (#796) Due to the rewrite of the plugin's core sync loop and the change for the Notify backend on MacOS, along with all the other changes in 7.4.0, it makes sense for us to use a release candidate before actually cutting a proper `7.4.0` release. --- CHANGELOG.md | 2 + Cargo.lock | 840 ++++++++++++++++++++++----------------------- Cargo.toml | 2 +- plugin/Version.txt | 2 +- 4 files changed, 409 insertions(+), 437 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 475adf57..a32f808a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes + +## [7.4.0-rc1] - October 3, 2023 ### Additions #### Project format * Added support for `.toml` files to `$path` ([#633]) diff --git a/Cargo.lock b/Cargo.lock index a4b74f37..31313395 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.19.0" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ "gimli", ] @@ -19,27 +19,18 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "0.7.20" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac" -dependencies = [ - "memchr", -] - -[[package]] -name = "aho-corasick" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67fc08ce920c31afb70f013dcce1bfc3a3195de6a228474e45e1f145b36f8d04" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] [[package]] name = "anyhow" -version = "1.0.70" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arrayref" @@ -49,9 +40,9 @@ checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" [[package]] name = "arrayvec" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" [[package]] name = "atty" @@ -72,9 +63,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "backtrace" -version = "0.3.67" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ "addr2line", "cc", @@ -93,9 +84,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.0" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "bincode" @@ -113,17 +104,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "blake3" -version = "1.3.3" +name = "bitflags" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ae2468a89544a466886840aa467a25b766499f4f04bf7d9fcd10ecee9fccef" +checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" + +[[package]] +name = "blake3" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0231f06152bf547e9c2b5194f247cd97aacf6dcd8b15d8e5ec0663f64580da87" dependencies = [ "arrayref", "arrayvec", "cc", "cfg-if 1.0.0", "constant_time_eq", - "digest", ] [[package]] @@ -137,21 +133,20 @@ dependencies = [ [[package]] name = "bstr" -version = "1.4.0" +version = "1.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d4260bcc2e8fc9df1eac4919a720effeb63a3f0952f5bf4944adfa18897f09" +checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" dependencies = [ "memchr", - "once_cell", - "regex-automata", + "regex-automata 0.3.9", "serde", ] [[package]] name = "bumpalo" -version = "3.12.1" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b1ce199063694f33ffb7dd4e0ee620741495c32833cde5aa08f02a0bf96f0c8" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "byteorder" @@ -161,9 +156,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cast" @@ -173,9 +168,12 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.79" +version = "1.0.83" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" +checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +dependencies = [ + "libc", +] [[package]] name = "cfg-if" @@ -195,19 +193,19 @@ version = "2.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" dependencies = [ - "bitflags", + "bitflags 1.3.2", "textwrap 0.11.0", "unicode-width", ] [[package]] name = "clap" -version = "3.2.23" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71655c45cb9845d3270c9d6df84ebe72b4dad3c2ba3f7023ad47c144e4e473a5" +checksum = "4ea181bf566f71cb9a5d17a59e1871af638180a18fb0035c92ae62b705207123" dependencies = [ "atty", - "bitflags", + "bitflags 1.3.2", "clap_derive", "clap_lex", "indexmap", @@ -219,14 +217,14 @@ dependencies = [ [[package]] name = "clap_derive" -version = "3.2.18" +version = "3.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea0c8bce528c4be4da13ea6fead8965e95b6073585a2f05204bd8f4119f82a65" +checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.56", - "quote 1.0.26", + "proc-macro2 1.0.67", + "quote 1.0.33", "syn 1.0.109", ] @@ -241,21 +239,21 @@ dependencies = [ [[package]] name = "console" -version = "0.15.5" +version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" +checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" dependencies = [ "encode_unicode", "lazy_static", "libc", - "windows-sys 0.42.0", + "windows-sys 0.45.0", ] [[package]] name = "constant_time_eq" -version = "0.2.5" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13418e745008f7349ec7e449155f419a61b92b58a99cc3616942b926825ec76b" +checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "core-foundation" @@ -275,9 +273,9 @@ checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" [[package]] name = "cpufeatures" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3e4c1eaa2012c47becbbad2ab175484c2a84d1185b566fb2cc5b8707343dfe58" +checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" dependencies = [ "libc", ] @@ -341,9 +339,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if 1.0.0", @@ -354,9 +352,9 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if 1.0.0", ] @@ -373,9 +371,9 @@ dependencies = [ [[package]] name = "csv" -version = "1.2.1" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b015497079b9a9d69c02ad25de6c0a6edef051ea6360a327d0bd05802ef64ad" +checksum = "ac574ff4d437a7b5ad237ef331c17ccca63c46479e5b5453eb8e10bb99a759fe" dependencies = [ "csv-core", "itoa", @@ -385,23 +383,13 @@ dependencies = [ [[package]] name = "csv-core" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +checksum = "5efa2b3d7902f4b634a20cae3c9c4e6209dc4779feb6863329607560143efa70" dependencies = [ "memchr", ] -[[package]] -name = "ctor" -version = "0.1.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096" -dependencies = [ - "quote 1.0.26", - "syn 1.0.109", -] - [[package]] name = "diff" version = "0.1.13" @@ -410,13 +398,12 @@ checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" [[package]] name = "digest" -version = "0.10.6" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", - "subtle", ] [[package]] @@ -442,9 +429,9 @@ dependencies = [ [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "embed-resource" @@ -467,9 +454,9 @@ checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if 1.0.0", ] @@ -489,9 +476,9 @@ dependencies = [ [[package]] name = "errno" -version = "0.3.1" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bcfec3a70f97c962c307b2d2c56e358cf1d00b558d74262b5f929ee8cc7e73a" +checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" dependencies = [ "errno-dragonfly", "libc", @@ -510,22 +497,19 @@ dependencies = [ [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "filetime" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbc844cecaee9d4443931972e1289c8ff485cb4cc2767cb03ca139ed6885153" +checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.2.16", + "redox_syscall 0.3.5", "windows-sys 0.48.0", ] @@ -552,9 +536,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" dependencies = [ "percent-encoding", ] @@ -571,7 +555,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" dependencies = [ - "bitflags", + "bitflags 1.3.2", "fsevent-sys", ] @@ -590,7 +574,7 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" dependencies = [ - "bitflags", + "bitflags 1.3.2", "fuchsia-zircon-sys", ] @@ -654,9 +638,9 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ - "proc-macro2 1.0.56", - "quote 1.0.26", - "syn 2.0.15", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] @@ -691,9 +675,9 @@ dependencies = [ [[package]] name = "generator" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3e123d9ae7c02966b4d892e550bdc32164f05853cd40ab570650ad600596a8a" +checksum = "5cc16584ff22b460a382b7feec54b23d2908d858152e5739a120b949293bd74e" dependencies = [ "cc", "libc", @@ -714,9 +698,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.9" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c85e1d9ab2eadba7e5040d4e09cbd6d072b76a557ad64e797c2cb9d4da21d7e4" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if 1.0.0", "libc", @@ -725,17 +709,17 @@ dependencies = [ [[package]] name = "gimli" -version = "0.27.2" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0a93d233ebf96623465aad4046a8d3aa4da22d4f4beba5388838c8a434bbb4" +checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" [[package]] name = "globset" -version = "0.4.10" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc" +checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" dependencies = [ - "aho-corasick 0.7.20", + "aho-corasick", "bstr", "fnv", "log", @@ -744,9 +728,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.18" +version = "0.3.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17f8a914c2987b688368b5138aa05321db91f4090cf26118185672ad588bce21" +checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" dependencies = [ "bytes", "fnv", @@ -790,18 +774,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "htmlescape" @@ -839,9 +814,9 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" @@ -851,9 +826,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.26" +version = "0.14.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab302d72a6f11a3b910431ff93aae7e773078c769f0a3ef15fb9ec692ed147d4" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" dependencies = [ "bytes", "futures-channel", @@ -866,7 +841,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2", + "socket2 0.4.9", "tokio", "tower-service", "tracing", @@ -888,9 +863,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -912,7 +887,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" dependencies = [ - "bitflags", + "bitflags 1.3.2", "inotify-sys", "libc", ] @@ -928,9 +903,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.29.0" +version = "1.33.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a28d25139df397cbca21408bb742cf6837e04cdbebf1b07b760caf971d6a972" +checksum = "1aa511b2e298cd49b1856746f6bb73e17036bcd66b25f5e92cdcdbec9bd75686" dependencies = [ "console", "lazy_static", @@ -942,26 +917,6 @@ dependencies = [ "yaml-rust", ] -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if 1.0.0", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" -dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys 0.48.0", -] - [[package]] name = "iovec" version = "0.1.4" @@ -973,9 +928,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.7.2" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" [[package]] name = "itertools" @@ -988,9 +943,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "jod-thread" @@ -1000,9 +955,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -1031,9 +986,9 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.142" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a987beff54b60ffa6d51982e1aa1146bc42f19bd26be28b0586f252fccf5317" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "linked-hash-map" @@ -1043,18 +998,15 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.3.4" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36eb31c1778188ae1e64398743890d0877fef36d11521ac60406b42016e8c2cf" +checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "loom" @@ -1101,20 +1053,20 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" dependencies = [ - "regex-automata", + "regex-automata 0.1.10", ] [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] @@ -1137,9 +1089,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" dependencies = [ "adler", ] @@ -1165,14 +1117,13 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] @@ -1219,9 +1170,9 @@ dependencies = [ [[package]] name = "net2" -version = "0.2.38" +version = "0.2.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d0df99cfcd2530b2e694f6e17e7f37b8e26bb23983ac530c0c97408837c631" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" dependencies = [ "cfg-if 0.1.10", "libc", @@ -1234,7 +1185,7 @@ version = "4.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae03c8c853dba7bfd23e571ff0cff7bc9dceb40a4cd684cd1681824183f45257" dependencies = [ - "bitflags", + "bitflags 1.3.2", "filetime", "fsevent", "fsevent-sys", @@ -1258,37 +1209,37 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi 0.3.3", "libc", ] [[package]] name = "object" -version = "0.30.3" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea86265d3d3dcb6a27fc51bd29a4bf387fae9d2986b823079d4986af253eb439" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "oorandom" @@ -1308,11 +1259,11 @@ dependencies = [ [[package]] name = "openssl" -version = "0.10.55" +version = "0.10.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" dependencies = [ - "bitflags", + "bitflags 2.4.0", "cfg-if 1.0.0", "foreign-types", "libc", @@ -1327,9 +1278,9 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ - "proc-macro2 1.0.56", - "quote 1.0.26", - "syn 2.0.15", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] @@ -1340,18 +1291,18 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-src" -version = "111.25.3+1.1.1t" +version = "300.1.5+3.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924757a6a226bf60da5f7dd0311a34d2b52283dd82ddeb103208ddc66362f80c" +checksum = "559068e4c12950d7dcaa1857a61725c0d38d4fc03ff8e070ab31a75d6e316491" dependencies = [ "cc", ] [[package]] name = "openssl-sys" -version = "0.9.90" +version = "0.9.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" dependencies = [ "cc", "libc", @@ -1362,18 +1313,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.5.0" +version = "6.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ceedf44fb00f2d1984b0bc98102627ce622e083e49a5bacdb3e514fa4238e267" - -[[package]] -name = "output_vt100" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66" -dependencies = [ - "winapi 0.3.9", -] +checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" [[package]] name = "overload" @@ -1383,31 +1325,32 @@ checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] name = "paste" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f746c4065a8fa3fe23974dd82f15431cc8d40779821001404d10d2e79ca7d79" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.5.7" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1403e8401ad5dedea73c626b99758535b342502f8d1e361f4a2dd952749122" +checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" dependencies = [ + "memchr", "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.5.7" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be99c4c1d2fc2769b1d00239431d711d08f6efedcecb8b6e30707160aee99c15" +checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" dependencies = [ "pest", "pest_generator", @@ -1415,22 +1358,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.5.7" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e56094789873daa36164de2e822b3888c6ae4b4f9da555a1103587658c805b1e" +checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.56", - "quote 1.0.26", - "syn 2.0.15", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] name = "pest_meta" -version = "2.5.7" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6733073c7cff3d8459fda0e42f13a047870242aed8b509fe98000928975f359e" +checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" dependencies = [ "once_cell", "pest", @@ -1439,9 +1382,9 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.9" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" [[package]] name = "pin-utils" @@ -1451,15 +1394,15 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "plotters" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2538b639e642295546c50fcd545198c9d64ee2a38620a628724a3b266d5fbf97" +checksum = "d2c224ba00d7cadd4d5c660deaf2098e5e80e07846537c51f9cfa4be50c1fd45" dependencies = [ "num-traits", "plotters-backend", @@ -1470,15 +1413,15 @@ dependencies = [ [[package]] name = "plotters-backend" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "193228616381fecdc1224c62e96946dfbc73ff4384fba576e052ff8c1bea8142" +checksum = "9e76628b4d3a7581389a35d5b6e2139607ad7c75b17aed325f210aa91f4a9609" [[package]] name = "plotters-svg" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9a81d2759aae1dae668f783c308bc5c8ebd191ff4184aaa1b37f65a6ae5a56f" +checksum = "38f6d39893cca0701371e3c27294f09797214b86f1fb951b89ade8ec04e2abab" dependencies = [ "plotters-backend", ] @@ -1491,13 +1434,11 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" [[package]] name = "pretty_assertions" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755" +checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66" dependencies = [ - "ctor", "diff", - "output_vt100", "yansi", ] @@ -1508,8 +1449,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.56", - "quote 1.0.26", + "proc-macro2 1.0.67", + "quote 1.0.33", "syn 1.0.109", "version_check", ] @@ -1520,8 +1461,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.56", - "quote 1.0.26", + "proc-macro2 1.0.67", + "quote 1.0.33", "version_check", ] @@ -1548,31 +1489,31 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.56" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b63bdb0cd06f1f4dedf69b254734f9b45af66e4a031e42a7480257d9898b435" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332cd62e95873ea4f41f3dfd6bbbfc5b52aec892d7e8d534197c4720a0bbbab2" +checksum = "f89dff0959d98c9758c88826cc002e2c3d0b9dfac4139711d1f30de442f1139b" dependencies = [ "profiling-procmacros", - "tracy-client 0.15.2", + "tracy-client 0.16.3", ] [[package]] name = "profiling-procmacros" -version = "1.0.8" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a10adb8d151bb1280afb8bed41ae5db26be1b056964947133c7525b0bf39c0b0" +checksum = "eb156a45b6b9fe8027497422179fb65afc84d36707a7ca98297bf06bccb8d43f" dependencies = [ - "quote 1.0.26", - "syn 1.0.109", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] @@ -1586,11 +1527,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.26" +version = "1.0.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc" +checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" dependencies = [ - "proc-macro2 1.0.56", + "proc-macro2 1.0.67", ] [[package]] @@ -1625,9 +1566,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ "either", "rayon-core", @@ -1635,14 +1576,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -1683,9 +1622,9 @@ dependencies = [ [[package]] name = "rbx_reflection_database" -version = "0.2.8+roblox-296" +version = "0.2.9+roblox-596" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff48aa41683dc6fe6949b0a82833b3364cf47c87086502b84d3e0419bff33c10" +checksum = "6b18f088a2b4aa66324ec97b5b6ffacb53188aef19f3497d95d6a1d1dbb28e66" dependencies = [ "lazy_static", "rbx_reflection", @@ -1700,7 +1639,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a991523e3ad5f43a4d121cb4a1e5bc23f7826bb4a1db5aa51e94f1073150ec" dependencies = [ "base64 0.13.1", - "bitflags", + "bitflags 1.3.2", "blake3", "lazy_static", "rand", @@ -1728,7 +1667,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1737,7 +1676,7 @@ version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] @@ -1753,13 +1692,14 @@ dependencies = [ [[package]] name = "regex" -version = "1.8.1" +version = "1.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af83e617f331cc6ae2da5443c602dfa5af81e517212d9d611a5b3ba1777b5370" +checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" dependencies = [ - "aho-corasick 1.0.1", + "aho-corasick", "memchr", - "regex-syntax 0.7.1", + "regex-automata 0.3.9", + "regex-syntax 0.7.5", ] [[package]] @@ -1771,6 +1711,17 @@ dependencies = [ "regex-syntax 0.6.29", ] +[[package]] +name = "regex-automata" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax 0.7.5", +] + [[package]] name = "regex-syntax" version = "0.6.29" @@ -1779,17 +1730,17 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.1" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5996294f19bd3aae0453a862ad728f60e6600695733dd5df01da90c54363a3c" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "reqwest" -version = "0.11.16" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.0", + "base64 0.21.4", "bytes", "encoding_rs", "futures-core", @@ -1810,6 +1761,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-native-tls", "tower-service", @@ -1817,7 +1769,7 @@ dependencies = [ "wasm-bindgen", "wasm-bindgen-futures", "web-sys", - "winreg 0.10.1", + "winreg 0.50.0", ] [[package]] @@ -1846,9 +1798,9 @@ dependencies = [ [[package]] name = "rmp" -version = "0.8.11" +version = "0.8.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44519172358fd6d58656c86ab8e7fbc9e1490c3e8f14d35ed78ca0dd07403c9f" +checksum = "7f9860a6cc38ed1da53456442089b4dfa35e7cedaa326df63017af88385e6b20" dependencies = [ "byteorder", "num-traits", @@ -1879,12 +1831,12 @@ dependencies = [ [[package]] name = "rojo" -version = "7.3.0" +version = "7.4.0-rc1" dependencies = [ "anyhow", "backtrace", "bincode", - "clap 3.2.23", + "clap 3.2.25", "criterion", "crossbeam-channel", "csv", @@ -1956,13 +1908,12 @@ dependencies = [ [[package]] name = "rustix" -version = "0.37.14" +version = "0.38.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b864d3c18a5785a05953adeed93e2dca37ed30f18e69bba9f30079d51f363f" +checksum = "d2f9da0cbd88f9f09e7814e388301c8414c51c62aa6ce1e4b5c551d49d96e531" dependencies = [ - "bitflags", + "bitflags 2.4.0", "errno", - "io-lifetimes", "libc", "linux-raw-sys", "windows-sys 0.48.0", @@ -1970,15 +1921,15 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "same-file" @@ -1991,11 +1942,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" dependencies = [ - "windows-sys 0.42.0", + "windows-sys 0.48.0", ] [[package]] @@ -2006,17 +1957,17 @@ checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "security-framework" -version = "2.8.2" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -2025,9 +1976,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.8.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -2041,9 +1992,9 @@ checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" [[package]] name = "serde" -version = "1.0.160" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2f3770c8bce3bcda7e149193a069a0f4365bda1fa5cd88e03bca26afc1216c" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] @@ -2060,20 +2011,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.160" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291a097c63d8497e00160b166a967a4a79c64f3facdd01cbd7502231688d77df" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ - "proc-macro2 1.0.56", - "quote 1.0.26", - "syn 2.0.15", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] name = "serde_json" -version = "1.0.96" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "057d394a50403bcac12672b2b18fb387ab6d289d957dab67dd201875391e52f1" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -2106,9 +2057,9 @@ dependencies = [ [[package]] name = "sha2" -version = "0.10.6" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82e6b795fe2e3b1e845bafcb27aa35405c4d47cdfc92af5fc8d3002f76cebdc0" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ "cfg-if 1.0.0", "cpufeatures", @@ -2117,9 +2068,9 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.4" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +checksum = "c1b21f559e07218024e7e9f90f96f601825397de0e25420135f7f952453fed0b" dependencies = [ "lazy_static", ] @@ -2132,18 +2083,18 @@ checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "snax" @@ -2164,58 +2115,83 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "socket2" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" +dependencies = [ + "libc", + "windows-sys 0.48.0", +] + [[package]] name = "strsim" version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" -[[package]] -name = "subtle" -version = "2.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bdef32e8150c2a081110b42772ffe7d7c9032b606bc226c8260fd97e0976601" - [[package]] name = "syn" version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.56", - "quote 1.0.26", + "proc-macro2 1.0.67", + "quote 1.0.33", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.15" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ - "proc-macro2 1.0.56", - "quote 1.0.26", + "proc-macro2 1.0.67", + "quote 1.0.33", "unicode-ident", ] [[package]] -name = "tempfile" -version = "3.5.0" +name = "system-configuration" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "tempfile" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" dependencies = [ "cfg-if 1.0.0", "fastrand", "redox_syscall 0.3.5", "rustix", - "windows-sys 0.45.0", + "windows-sys 0.48.0", ] [[package]] name = "termcolor" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] @@ -2237,22 +2213,22 @@ checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" [[package]] name = "thiserror" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac" +checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.40" +version = "1.0.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f" +checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" dependencies = [ - "proc-macro2 1.0.56", - "quote 1.0.26", - "syn 2.0.15", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] @@ -2292,18 +2268,18 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.27.0" +version = "1.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0de47a4eecbe11f498978a9b29d792f0d2692d1dd003650c24c76510e3bc001" +checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" dependencies = [ - "autocfg", + "backtrace", "bytes", "libc", - "mio 0.8.6", + "mio 0.8.8", "num_cpus", "pin-project-lite", - "socket2", - "windows-sys 0.45.0", + "socket2 0.5.4", + "windows-sys 0.48.0", ] [[package]] @@ -2318,9 +2294,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.7" +version = "0.7.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" dependencies = [ "bytes", "futures-core", @@ -2359,20 +2335,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ - "proc-macro2 1.0.56", - "quote 1.0.26", - "syn 1.0.109", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", "valuable", @@ -2420,13 +2396,13 @@ dependencies = [ [[package]] name = "tracy-client" -version = "0.15.2" +version = "0.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "434ecabbda9f67eeea1eab44d52f4a20538afa3e2c2770f2efc161142b25b608" +checksum = "03684af8fb393cc7903210d868e4cb9f5c1e156737be38f52c4217fb21b86bf6" dependencies = [ "loom", "once_cell", - "tracy-client-sys 0.21.0", + "tracy-client-sys 0.21.2", ] [[package]] @@ -2440,9 +2416,9 @@ dependencies = [ [[package]] name = "tracy-client-sys" -version = "0.21.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d99f5fc382239d08b6bf05bb6206a585bfdb988c878f2499081d0f285ef7819" +checksum = "2cb915ea3af048554640d76dd6f1492589a6401a41a30d789b983c1ec280455a" dependencies = [ "cc", ] @@ -2455,15 +2431,15 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e79c4d996edb816c91e4308506774452e55e95c3c9de07b6729e17e15a5ef81" +checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "unicode-bidi" @@ -2473,9 +2449,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -2488,9 +2464,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unicode-xid" @@ -2500,9 +2476,9 @@ checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" [[package]] name = "url" -version = "2.3.1" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", "idna", @@ -2511,9 +2487,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b55a3fef2a1e3b3a00ce878640918820d3c51081576ac657d23af9fc7928fdb" +checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" dependencies = [ "getrandom", "serde", @@ -2559,9 +2535,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -2569,11 +2545,10 @@ dependencies = [ [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -2585,9 +2560,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -2595,24 +2570,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.56", - "quote 1.0.26", - "syn 1.0.109", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.34" +version = "0.4.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -2622,38 +2597,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ - "quote 1.0.26", + "quote 1.0.33", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ - "proc-macro2 1.0.56", - "quote 1.0.26", - "syn 1.0.109", + "proc-macro2 1.0.67", + "quote 1.0.33", + "syn 2.0.37", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "web-sys" -version = "0.3.61" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", @@ -2689,9 +2664,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi 0.3.9", ] @@ -2708,22 +2683,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e686886bc078bc1b0b600cac0147aadb815089b6e4da64016cbd754b6342700f" dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets 0.48.5", ] [[package]] @@ -2741,7 +2701,7 @@ version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ - "windows-targets 0.48.0", + "windows-targets 0.48.5", ] [[package]] @@ -2761,17 +2721,17 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -2782,9 +2742,9 @@ checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" @@ -2794,9 +2754,9 @@ checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" [[package]] name = "windows_aarch64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" @@ -2806,9 +2766,9 @@ checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" [[package]] name = "windows_i686_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" @@ -2818,9 +2778,9 @@ checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" [[package]] name = "windows_i686_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" @@ -2830,9 +2790,9 @@ checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" [[package]] name = "windows_x86_64_gnu" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" @@ -2842,9 +2802,9 @@ checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" [[package]] name = "windows_x86_64_gnullvm" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" @@ -2854,9 +2814,9 @@ checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" [[package]] name = "windows_x86_64_msvc" -version = "0.48.0" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winreg" @@ -2876,6 +2836,16 @@ dependencies = [ "winapi 0.3.9", ] +[[package]] +name = "winreg" +version = "0.50.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" +dependencies = [ + "cfg-if 1.0.0", + "windows-sys 0.48.0", +] + [[package]] name = "ws2_32-sys" version = "0.2.1" @@ -2888,9 +2858,9 @@ dependencies = [ [[package]] name = "xml-rs" -version = "0.8.4" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2d7d3948613f75c98fd9328cfdcc45acc4d360655289d0a7d4ec931392200a3" +checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" [[package]] name = "yaml-rust" diff --git a/Cargo.toml b/Cargo.toml index 169f7297..463a7f80 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "7.3.0" +version = "7.4.0-rc1" rust-version = "1.70.0" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" diff --git a/plugin/Version.txt b/plugin/Version.txt index 8b23b8d4..aaa20ba5 100644 --- a/plugin/Version.txt +++ b/plugin/Version.txt @@ -1 +1 @@ -7.3.0 \ No newline at end of file +7.4.0-rc1 \ No newline at end of file From f467fa4e598bda0d0bc2966ccea4b9bc6004ad01 Mon Sep 17 00:00:00 2001 From: Kampfkarren Date: Tue, 3 Oct 2023 21:07:06 -0700 Subject: [PATCH 1341/1504] 7.4.0-rc.1 [release] From bfd2c885db54ed633267749b6ddb9987d8a609c8 Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 3 Oct 2023 22:23:18 -0700 Subject: [PATCH 1342/1504] Properly handle build metadata in semver parsing in plugin (#797) --- CHANGELOG.md | 4 ++++ plugin/src/Config.lua | 3 ++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a32f808a..fef486a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## Unreleased Changes +* Fixed bug with parsing version for plugin validation ([#797]) + +[#797]: https://github.com/rojo-rbx/rojo/pull/797 + ## [7.4.0-rc1] - October 3, 2023 ### Additions #### Project format diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 70eeccfa..0238b2cb 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -3,8 +3,9 @@ local strict = require(script.Parent.strict) local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil local Version = script.Parent.Parent.Version -local realVersion = Version.Value:split(".") +local major, minor, patch, metadata = Version.Value:match("^(%d+)%.(%d+)%.(%d+)(.*)$") +local realVersion = { major, minor, patch, metadata } for i = 1, 3 do local num = tonumber(realVersion[i]) if num then From 1caf9446d82007051f9db9688d749dba1dfa7d13 Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 3 Oct 2023 22:36:57 -0700 Subject: [PATCH 1343/1504] Rojo 7.4.0-rc2 (#798) --- CHANGELOG.md | 1 + Cargo.lock | 2 +- Cargo.toml | 2 +- plugin/Version.txt | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fef486a4..873a5f5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Unreleased Changes +## [7.4.0-rc2] - October 3, 2023 * Fixed bug with parsing version for plugin validation ([#797]) [#797]: https://github.com/rojo-rbx/rojo/pull/797 diff --git a/Cargo.lock b/Cargo.lock index 31313395..5de59cb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1831,7 +1831,7 @@ dependencies = [ [[package]] name = "rojo" -version = "7.4.0-rc1" +version = "7.4.0-rc2" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 463a7f80..c814ab00 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "7.4.0-rc1" +version = "7.4.0-rc2" rust-version = "1.70.0" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" diff --git a/plugin/Version.txt b/plugin/Version.txt index aaa20ba5..88bc5e57 100644 --- a/plugin/Version.txt +++ b/plugin/Version.txt @@ -1 +1 @@ -7.4.0-rc1 \ No newline at end of file +7.4.0-rc2 \ No newline at end of file From e897f524dc31b7e13d7406fdd78d14588972e4a9 Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Fri, 13 Oct 2023 10:38:21 -0500 Subject: [PATCH 1344/1504] Skip sourcemap generation when unaffected by changes in watch mode (#800) --- CHANGELOG.md | 3 +++ src/cli/sourcemap.rs | 45 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 873a5f5f..da732630 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Rojo Changelog ## Unreleased Changes +* Changed `sourcemap --watch` to only generate the sourcemap when it's necessary ([#800]) + +[#800]: https://github.com/rojo-rbx/rojo/pull/800 ## [7.4.0-rc2] - October 3, 2023 * Fixed bug with parsing version for plugin validation ([#797]) diff --git a/src/cli/sourcemap.rs b/src/cli/sourcemap.rs index f7bc1691..ec4e9528 100644 --- a/src/cli/sourcemap.rs +++ b/src/cli/sourcemap.rs @@ -14,7 +14,7 @@ use tokio::runtime::Runtime; use crate::{ serve_session::ServeSession, - snapshot::{InstanceWithMeta, RojoTree}, + snapshot::{AppliedPatchSet, InstanceWithMeta, RojoTree}, }; use super::resolve_path; @@ -90,10 +90,12 @@ impl SourcemapCommand { loop { let receiver = session.message_queue().subscribe(cursor); - let (new_cursor, _patch_set) = rt.block_on(receiver).unwrap(); + let (new_cursor, patch_set) = rt.block_on(receiver).unwrap(); cursor = new_cursor; - write_sourcemap(&session, self.output.as_deref(), filter)?; + if patch_set_affects_sourcemap(&session, &patch_set, filter) { + write_sourcemap(&session, self.output.as_deref(), filter)?; + } } } @@ -116,6 +118,43 @@ fn filter_non_scripts(instance: &InstanceWithMeta) -> bool { ) } +fn patch_set_affects_sourcemap( + session: &ServeSession, + patch_set: &[AppliedPatchSet], + filter: fn(&InstanceWithMeta) -> bool, +) -> bool { + let tree = session.tree(); + + // A sourcemap has probably changed when: + patch_set.par_iter().any(|set| { + // 1. An instance was removed, in which case it will no + // longer exist in the tree and we cant check the filter + !set.removed.is_empty() + // 2. A newly added instance passes the filter + || set.added.iter().any(|referent| { + let instance = tree + .get_instance(*referent) + .expect("instance did not exist when updating sourcemap"); + filter(&instance) + }) + // 3. An existing instance has its class name, name, + // or file paths changed, and passes the filter + || set.updated.iter().any(|updated| { + let changed = updated.changed_class_name.is_some() + || updated.changed_name.is_some() + || updated.changed_metadata.is_some(); + if changed { + let instance = tree + .get_instance(updated.id) + .expect("instance did not exist when updating sourcemap"); + filter(&instance) + } else { + false + } + }) + }) +} + fn recurse_create_node<'a>( tree: &'a RojoTree, referent: Ref, From d441fbdf91ea33a24422951e7213330c505c8002 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Tue, 17 Oct 2023 14:15:47 -0700 Subject: [PATCH 1345/1504] Bump rbx_dom_lua rojo-rbx/rbx-dom@e7a5b91c (ScriptEditorService) (#801) --- plugin/rbx_dom_lua/customProperties.lua | 31 +++++++ plugin/rbx_dom_lua/database.json | 105 +++++++++++++----------- 2 files changed, 86 insertions(+), 50 deletions(-) diff --git a/plugin/rbx_dom_lua/customProperties.lua b/plugin/rbx_dom_lua/customProperties.lua index 624523b6..3ffbf7af 100644 --- a/plugin/rbx_dom_lua/customProperties.lua +++ b/plugin/rbx_dom_lua/customProperties.lua @@ -1,4 +1,5 @@ local CollectionService = game:GetService("CollectionService") +local ScriptEditorService = game:GetService("ScriptEditorService") --- A list of `Enum.Material` values that are used for Terrain.MaterialColors local TERRAIN_MATERIAL_COLORS = { @@ -116,4 +117,34 @@ return { end, }, }, + Script = { + Source = { + read = function(instance: Script) + return true, ScriptEditorService:GetEditorSource(instance) + end, + write = function(instance: Script, _, value: string) + task.spawn(function() + ScriptEditorService:UpdateSourceAsync(instance, function() + return value + end) + end) + return true + end, + }, + }, + ModuleScript = { + Source = { + read = function(instance: ModuleScript) + return true, ScriptEditorService:GetEditorSource(instance) + end, + write = function(instance: ModuleScript, _, value: string) + task.spawn(function() + ScriptEditorService:UpdateSourceAsync(instance, function() + return value + end) + end) + return true + end, + }, + }, } diff --git a/plugin/rbx_dom_lua/database.json b/plugin/rbx_dom_lua/database.json index 720fb5ff..817d3130 100644 --- a/plugin/rbx_dom_lua/database.json +++ b/plugin/rbx_dom_lua/database.json @@ -1,9 +1,9 @@ { "Version": [ 0, - 596, + 597, 1, - 5960685 + 5970668 ], "Classes": { "Accessory": { @@ -4504,6 +4504,17 @@ }, "DefaultProperties": {} }, + "AvatarCreationService": { + "Name": "AvatarCreationService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "AvatarEditorService": { "Name": "AvatarEditorService", "Tags": [ @@ -15560,9 +15571,7 @@ }, "DragDetector": { "Name": "DragDetector", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "ClickDetector", "Properties": { "ActivatedCursorIcon": { @@ -28121,6 +28130,17 @@ } } }, + "LogReporterService": { + "Name": "LogReporterService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "LogService": { "Name": "LogService", "Tags": [ @@ -31192,7 +31212,7 @@ }, "Source": { "Name": "Source", - "Scriptability": "ReadWrite", + "Scriptability": "Custom", "DataType": { "Value": "String" }, @@ -41454,7 +41474,7 @@ "Properties": { "Source": { "Name": "Source", - "Scriptability": "ReadWrite", + "Scriptability": "Custom", "DataType": { "Value": "String" }, @@ -47977,6 +47997,19 @@ } } }, + "Camera Speed Adjust Binding": { + "Name": "Camera Speed Adjust Binding", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "CameraSpeedAdjustBinding" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Camera Zoom to Mouse Position": { "Name": "Camera Zoom to Mouse Position", "Scriptability": "ReadWrite", @@ -49545,7 +49578,9 @@ }, "StudioAttachment": { "Name": "StudioAttachment", - "Tags": [], + "Tags": [ + "NotReplicated" + ], "Superclass": "Instance", "Properties": { "AutoHideParent": { @@ -49614,52 +49649,11 @@ } } }, - "DefaultProperties": { - "Attributes": { - "Attributes": {} - }, - "AutoHideParent": { - "Bool": false - }, - "Capabilities": { - "SecurityCapabilities": 0 - }, - "DefinesCapabilities": { - "Bool": false - }, - "IsArrowVisible": { - "Bool": false - }, - "Offset": { - "Vector2": [ - 0.0, - 0.0 - ] - }, - "SourceAnchorPoint": { - "Vector2": [ - 0.0, - 0.0 - ] - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "Tags": [] - }, - "TargetAnchorPoint": { - "Vector2": [ - 0.0, - 0.0 - ] - } - } + "DefaultProperties": {} }, "StudioCallout": { "Name": "StudioCallout", "Tags": [ - "NotCreatable", "NotReplicated" ], "Superclass": "Instance", @@ -64701,6 +64695,14 @@ "EdgeBump": 1 } }, + "CameraSpeedAdjustBinding": { + "name": "CameraSpeedAdjustBinding", + "items": { + "AltScroll": 2, + "None": 0, + "RmbScroll": 1 + } + }, "CameraType": { "name": "CameraType", "items": { @@ -67514,6 +67516,9 @@ "Mid": 36, "Midlight": 98, "Notification": 4, + "OnboardingCover": 132, + "OnboardingHighlight": 133, + "OnboardingShadow": 134, "RibbonButton": 19, "RibbonTab": 15, "RibbonTabTopBar": 16, From 834c8cdbcadb75033fe5d8aace6e5ab63184e01f Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Sun, 22 Oct 2023 16:57:59 -0700 Subject: [PATCH 1346/1504] rbx_dom_lua rojo-rbx/rbx-dom@0e10232b (SecurityCapabilities) (#803) Closes #802. --- plugin/rbx_dom_lua/EncodedValue.lua | 9 --------- 1 file changed, 9 deletions(-) diff --git a/plugin/rbx_dom_lua/EncodedValue.lua b/plugin/rbx_dom_lua/EncodedValue.lua index b1a9ac13..e9dd0edd 100644 --- a/plugin/rbx_dom_lua/EncodedValue.lua +++ b/plugin/rbx_dom_lua/EncodedValue.lua @@ -412,15 +412,6 @@ types = { end, }, - SecurityCapabilities = { - fromPod = function(_pod) - error("SecurityCapabilities is not implemented") - end, - toPod = function(_roblox) - error("SecurityCapabilities is not implemented") - end, - }, - SharedString = { fromPod = function(_pod) error("SharedString is not supported") From feac29ea40b84898a55e3237b24d1f0aacff3017 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Sun, 22 Oct 2023 16:58:12 -0700 Subject: [PATCH 1347/1504] Fix PatchTree incorrect changeList entries on decode failure (#804) --- plugin/src/PatchTree.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/PatchTree.lua b/plugin/src/PatchTree.lua index 82e437eb..e67dbcd0 100644 --- a/plugin/src/PatchTree.lua +++ b/plugin/src/PatchTree.lua @@ -233,7 +233,7 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) addProp( prop, if currentSuccess then currentValue else "[Error]", - if incomingSuccess then incomingValue else next(incoming) + if incomingSuccess then incomingValue else select(2, next(incoming)) ) end @@ -359,7 +359,7 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) if success then table.insert(changeList, { prop, "N/A", incomingValue }) else - table.insert(changeList, { prop, "N/A", next(incoming) }) + table.insert(changeList, { prop, "N/A", select(2, next(incoming)) }) end end From a3d140269b6a025df0c073951637b807c8839f34 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Mon, 23 Oct 2023 11:47:50 -0700 Subject: [PATCH 1348/1504] Demote unapplied patch warnings to debug logs (#805) These warnings always appear for properties like `Capabilities`, `SourceAssetId`, etc. and tend to scare users who are syncing models. This information is now surfaced in the patch visualizer, so I think these warnings can be demoted to debug logs. --- plugin/src/ServeSession.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index e5bbb12f..56a06939 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -282,7 +282,7 @@ function ServeSession:__initialSync(serverInfo) local unappliedPatch = self.__reconciler:applyPatch(catchUpPatch) if not PatchSet.isEmpty(unappliedPatch) then - Log.warn( + Log.debug( "Could not apply all changes requested by the Rojo server:\n{}", PatchSet.humanSummary(self.__instanceMap, unappliedPatch) ) @@ -309,7 +309,7 @@ function ServeSession:__mainSyncLoop() local unappliedPatch = self.__reconciler:applyPatch(message) if not PatchSet.isEmpty(unappliedPatch) then - Log.warn( + Log.debug( "Could not apply all changes requested by the Rojo server:\n{}", PatchSet.humanSummary(self.__instanceMap, unappliedPatch) ) From f39e040a0dd3d3997aacd98939b52b4463f91dc0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 23 Oct 2023 22:38:28 +0000 Subject: [PATCH 1349/1504] Bump rustix from 0.38.15 to 0.38.20 (#806) --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5de59cb7..277d39d1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1908,9 +1908,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.15" +version = "0.38.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f9da0cbd88f9f09e7814e388301c8414c51c62aa6ce1e4b5c551d49d96e531" +checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" dependencies = [ "bitflags 2.4.0", "errno", From 6598867d3da5ca7d069f29ffe8654389da761f94 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Mon, 23 Oct 2023 15:43:00 -0700 Subject: [PATCH 1350/1504] Bump rbx_binary to 0.7.3 (#807) Bumps rbx_binary's version to 0.7.3 to bring in the missing `SecurityCapabilities` serialization fallback default --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 277d39d1..d60692cf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1586,9 +1586,9 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10942950a57c939e540a2f977ba55e9140007d7e96c532d455502c290fdf710d" +checksum = "ad50c13afe91296dad6508ea7e29f4b665fa56cb664ad01eaf8fdbd3da69d5e1" dependencies = [ "log", "lz4", diff --git a/Cargo.toml b/Cargo.toml index c814ab00..22b22977 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -49,7 +49,7 @@ memofs = { version = "0.2.0", path = "crates/memofs" } # rbx_reflection_database = { path = "../rbx-dom/rbx_reflection_database" } # rbx_xml = { path = "../rbx-dom/rbx_xml" } -rbx_binary = "0.7.2" +rbx_binary = "0.7.3" rbx_dom_weak = "2.6.0" rbx_reflection = "4.4.0" rbx_reflection_database = "0.2.8" From f4252c3e97eb7c20082d0f6cc0f71e62ca30f4d7 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Mon, 23 Oct 2023 15:54:48 -0700 Subject: [PATCH 1351/1504] Update changelog in preparation for 7.4.0-rc3 (#808) Summarizes recent changes since 7.4.0-rc2 in the changelog --- CHANGELOG.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da732630..d20454f2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,8 +2,16 @@ ## Unreleased Changes * Changed `sourcemap --watch` to only generate the sourcemap when it's necessary ([#800]) +* Switched script source property getter and setter to `ScriptEditorService` methods ([#801]) + + This ensures that the script editor reflects any changes Rojo makes to a script while it is open in the script editor. + +* Fixed issues when handling `SecurityCapabilities` values ([#803], [#807]) [#800]: https://github.com/rojo-rbx/rojo/pull/800 +[#801]: https://github.com/rojo-rbx/rojo/pull/801 +[#803]: https://github.com/rojo-rbx/rojo/pull/803 +[#807]: https://github.com/rojo-rbx/rojo/pull/807 ## [7.4.0-rc2] - October 3, 2023 * Fixed bug with parsing version for plugin validation ([#797]) From 9f13bca6b86c2619e78251c1dcd9ac9a026a6422 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Wed, 25 Oct 2023 14:21:58 -0700 Subject: [PATCH 1352/1504] rbx_dom_lua rojo-rbx/rbx-dom@440f3723 (attribute validation) (#809) Brings over some changes to rbx_dom_lua to validate attribute names before calling `Instance:SetAttribute`. This should prevent Rojo from falling over when it attempts to sync an attribute with an invalid name. --- CHANGELOG.md | 2 ++ plugin/rbx_dom_lua/customProperties.lua | 21 ++++++++++++++++++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d20454f2..e14c9fcf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,11 +7,13 @@ This ensures that the script editor reflects any changes Rojo makes to a script while it is open in the script editor. * Fixed issues when handling `SecurityCapabilities` values ([#803], [#807]) +* Fixed Rojo plugin erroring out when attempting to sync attributes with invalid names ([#809]) [#800]: https://github.com/rojo-rbx/rojo/pull/800 [#801]: https://github.com/rojo-rbx/rojo/pull/801 [#803]: https://github.com/rojo-rbx/rojo/pull/803 [#807]: https://github.com/rojo-rbx/rojo/pull/807 +[#809]: https://github.com/rojo-rbx/rojo/pull/809 ## [7.4.0-rc2] - October 3, 2023 * Fixed bug with parsing version for plugin validation ([#797]) diff --git a/plugin/rbx_dom_lua/customProperties.lua b/plugin/rbx_dom_lua/customProperties.lua index 3ffbf7af..072db9ef 100644 --- a/plugin/rbx_dom_lua/customProperties.lua +++ b/plugin/rbx_dom_lua/customProperties.lua @@ -37,9 +37,24 @@ return { end, write = function(instance, _, value) local existing = instance:GetAttributes() + local didAllWritesSucceed = true - for key, attr in pairs(value) do - instance:SetAttribute(key, attr) + for attributeName, attributeValue in pairs(value) do + local isNameValid = + -- For our SetAttribute to succeed, the attribute name must be + -- less than or equal to 100 characters... + #attributeName <= 100 + -- ...must only contain alphanumeric characters, periods, hyphens, + -- underscores, or forward slashes... + and attributeName:match("[^%w%.%-_/]") == nil + -- ... and must not use the RBX prefix, which is reserved by Roblox. + and attributeName:sub(1, 3) ~= "RBX" + + if isNameValid then + instance:SetAttribute(attributeName, attributeValue) + else + didAllWritesSucceed = false + end end for key in pairs(existing) do @@ -48,7 +63,7 @@ return { end end - return true + return didAllWritesSucceed end, }, Tags = { From cd14ea7c621fb8ae146bdb6273aec4ad86591c15 Mon Sep 17 00:00:00 2001 From: Micah Date: Wed, 25 Oct 2023 15:59:02 -0700 Subject: [PATCH 1353/1504] Remove unnecessary borrows (#810) --- build.rs | 2 +- src/multimap.rs | 2 +- src/web/api.rs | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/build.rs b/build.rs index b82f9542..7dbfc98a 100644 --- a/build.rs +++ b/build.rs @@ -46,7 +46,7 @@ fn main() -> Result<(), anyhow::Error> { let our_version = Version::parse(env::var_os("CARGO_PKG_VERSION").unwrap().to_str().unwrap())?; let plugin_version = - Version::parse(fs::read_to_string(&plugin_root.join("Version.txt"))?.trim())?; + Version::parse(fs::read_to_string(plugin_root.join("Version.txt"))?.trim())?; assert!( our_version.major == plugin_version.major, diff --git a/src/multimap.rs b/src/multimap.rs index 02191e6a..3a243af1 100644 --- a/src/multimap.rs +++ b/src/multimap.rs @@ -24,7 +24,7 @@ impl MultiMap { K: Borrow, Q: Hash + Eq, { - self.inner.get(k.borrow()).map(Vec::as_slice).unwrap_or(&[]) + self.inner.get(k).map(Vec::as_slice).unwrap_or(&[]) } pub fn insert(&mut self, k: K, v: V) { diff --git a/src/web/api.rs b/src/web/api.rs index 338862f7..4156af35 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -159,7 +159,7 @@ impl ApiService { }) .unwrap(); - json_ok(&WriteResponse { session_id }) + json_ok(WriteResponse { session_id }) } async fn handle_api_read(&self, request: Request) -> Response { @@ -271,7 +271,7 @@ impl ApiService { }, }; - json_ok(&OpenResponse { + json_ok(OpenResponse { session_id: self.serve_session.session_id(), }) } From 41994ec82ed5af3e081498ff414228869da10b8b Mon Sep 17 00:00:00 2001 From: Micah Date: Wed, 25 Oct 2023 17:01:06 -0700 Subject: [PATCH 1354/1504] Release v7.4.0-rc3 (#811) --- CHANGELOG.md | 2 ++ Cargo.lock | 2 +- Cargo.toml | 2 +- plugin/Version.txt | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e14c9fcf..d2673f56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes + +## [7.4.0-rc3] - October 25, 2023 * Changed `sourcemap --watch` to only generate the sourcemap when it's necessary ([#800]) * Switched script source property getter and setter to `ScriptEditorService` methods ([#801]) diff --git a/Cargo.lock b/Cargo.lock index d60692cf..e850ee23 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1831,7 +1831,7 @@ dependencies = [ [[package]] name = "rojo" -version = "7.4.0-rc2" +version = "7.4.0-rc3" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 22b22977..8c3ea003 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "7.4.0-rc2" +version = "7.4.0-rc3" rust-version = "1.70.0" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" diff --git a/plugin/Version.txt b/plugin/Version.txt index 88bc5e57..c129df57 100644 --- a/plugin/Version.txt +++ b/plugin/Version.txt @@ -1 +1 @@ -7.4.0-rc2 \ No newline at end of file +7.4.0-rc3 \ No newline at end of file From b43b45be8f2eb01161a389afeab56749fa82e459 Mon Sep 17 00:00:00 2001 From: Jack T <44332148+jackTabsCode@users.noreply.github.com> Date: Thu, 23 Nov 2023 16:16:43 -0800 Subject: [PATCH 1355/1504] Upgrade to Notify 6 (#816) --- Cargo.lock | 180 +++++++------------------------ Cargo.toml | 1 - crates/memofs/Cargo.toml | 2 +- crates/memofs/src/std_backend.rs | 70 ++++++------ tests/tests/serve.rs | 1 + 5 files changed, 74 insertions(+), 180 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e850ee23..87b5111b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,7 +52,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi 0.1.19", "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -424,7 +424,7 @@ checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -549,41 +549,15 @@ version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" -[[package]] -name = "fsevent" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" -dependencies = [ - "bitflags 1.3.2", - "fsevent-sys", -] - [[package]] name = "fsevent-sys" -version = "2.0.1" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" +checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" dependencies = [ "libc", ] -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags 1.3.2", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - [[package]] name = "futures" version = "0.3.28" @@ -883,9 +857,9 @@ dependencies = [ [[package]] name = "inotify" -version = "0.7.1" +version = "0.9.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" +checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" dependencies = [ "bitflags 1.3.2", "inotify-sys", @@ -917,15 +891,6 @@ dependencies = [ "yaml-rust", ] -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - [[package]] name = "ipnet" version = "2.8.0" @@ -963,13 +928,23 @@ dependencies = [ ] [[package]] -name = "kernel32-sys" -version = "0.2.2" +name = "kqueue" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" +checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" dependencies = [ - "winapi 0.2.8", - "winapi-build", + "kqueue-sys", + "libc", +] + +[[package]] +name = "kqueue-sys" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" +dependencies = [ + "bitflags 1.3.2", + "libc", ] [[package]] @@ -978,12 +953,6 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" -[[package]] -name = "lazycell" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" - [[package]] name = "libc" version = "0.2.148" @@ -1096,25 +1065,6 @@ dependencies = [ "adler", ] -[[package]] -name = "mio" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log", - "miow", - "net2", - "slab", - "winapi 0.2.8", -] - [[package]] name = "mio" version = "0.8.8" @@ -1122,34 +1072,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", + "log", "wasi", "windows-sys 0.48.0", ] -[[package]] -name = "mio-extras" -version = "2.0.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" -dependencies = [ - "lazycell", - "log", - "mio 0.6.23", - "slab", -] - -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - [[package]] name = "native-tls" version = "0.2.11" @@ -1168,33 +1095,23 @@ dependencies = [ "tempfile", ] -[[package]] -name = "net2" -version = "0.2.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] - [[package]] name = "notify" -version = "4.0.17" +version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae03c8c853dba7bfd23e571ff0cff7bc9dceb40a4cd684cd1681824183f45257" +checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", + "crossbeam-channel", "filetime", - "fsevent", "fsevent-sys", "inotify", + "kqueue", "libc", - "mio 0.6.23", - "mio-extras", + "log", + "mio", "walkdir", - "winapi 0.3.9", + "windows-sys 0.48.0", ] [[package]] @@ -1204,7 +1121,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1254,7 +1171,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005" dependencies = [ "bstr", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1852,7 +1769,6 @@ dependencies = [ "log", "maplit", "memofs", - "notify", "num_cpus", "opener", "paste", @@ -2112,7 +2028,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2275,7 +2191,7 @@ dependencies = [ "backtrace", "bytes", "libc", - "mio 0.8.8", + "mio", "num_cpus", "pin-project-lite", "socket2 0.5.4", @@ -2634,12 +2550,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -2650,12 +2560,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2668,7 +2572,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2824,7 +2728,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2833,7 +2737,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -2846,16 +2750,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "xml-rs" version = "0.8.19" diff --git a/Cargo.toml b/Cargo.toml index 8c3ea003..1401d2e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,7 +69,6 @@ hyper = { version = "0.14.13", features = ["server", "tcp", "http1"] } jod-thread = "0.1.2" log = "0.4.14" maplit = "1.0.2" -notify = "4.0.17" num_cpus = "1.15.0" opener = "0.5.0" rayon = "1.7.0" diff --git a/crates/memofs/Cargo.toml b/crates/memofs/Cargo.toml index 5cf5a733..b60a3038 100644 --- a/crates/memofs/Cargo.toml +++ b/crates/memofs/Cargo.toml @@ -13,5 +13,5 @@ homepage = "https://github.com/rojo-rbx/rojo/tree/master/memofs" [dependencies] crossbeam-channel = "0.5.1" fs-err = "2.3.0" -notify = "4.0.15" +notify = "6.1.1" serde = { version = "1.0", features = ["derive"] } diff --git a/crates/memofs/src/std_backend.rs b/crates/memofs/src/std_backend.rs index 01a554a5..4e95f110 100644 --- a/crates/memofs/src/std_backend.rs +++ b/crates/memofs/src/std_backend.rs @@ -1,25 +1,23 @@ use std::io; use std::path::Path; -use std::sync::mpsc; -use std::thread; -use std::time::Duration; use crossbeam_channel::Receiver; -use notify::{DebouncedEvent, RecursiveMode, Watcher}; + +use notify::{Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher}; #[cfg(target_os = "macos")] -use notify::PollWatcher; -#[cfg(not(target_os = "macos"))] -use notify::{watcher, RecommendedWatcher}; +use notify::{Config, PollWatcher}; + +#[cfg(target_os = "macos")] +use std::time::Duration; use crate::{DirEntry, Metadata, ReadDir, VfsBackend, VfsEvent}; /// `VfsBackend` that uses `std::fs` and the `notify` crate. pub struct StdBackend { - // We use PollWatcher on macos because using the KQueue watcher - // can cause some gnarly performance problems. #[cfg(target_os = "macos")] watcher: PollWatcher, + #[cfg(not(target_os = "macos"))] watcher: RecommendedWatcher, @@ -28,37 +26,39 @@ pub struct StdBackend { impl StdBackend { pub fn new() -> StdBackend { - let (notify_tx, notify_rx) = mpsc::channel(); - - #[cfg(target_os = "macos")] - let watcher = PollWatcher::new(notify_tx, Duration::from_millis(50)).unwrap(); - #[cfg(not(target_os = "macos"))] - let watcher = watcher(notify_tx, Duration::from_millis(50)).unwrap(); - let (tx, rx) = crossbeam_channel::unbounded(); - thread::spawn(move || { - for event in notify_rx { - match event { - DebouncedEvent::Create(path) => { - tx.send(VfsEvent::Create(path))?; + let event_handler = move |res: Result| match res { + Ok(event) => match event.kind { + EventKind::Create(_) => { + for path in event.paths { + let _ = tx.send(VfsEvent::Create(path)); } - DebouncedEvent::Write(path) => { - tx.send(VfsEvent::Write(path))?; - } - DebouncedEvent::Remove(path) => { - tx.send(VfsEvent::Remove(path))?; - } - DebouncedEvent::Rename(from, to) => { - tx.send(VfsEvent::Remove(from))?; - tx.send(VfsEvent::Create(to))?; - } - _ => {} } - } + EventKind::Modify(_) => { + for path in event.paths { + let _ = tx.send(VfsEvent::Write(path)); + } + } + EventKind::Remove(_) => { + for path in event.paths { + let _ = tx.send(VfsEvent::Remove(path)); + } + } + _ => {} + }, + Err(e) => println!("watch error: {:?}", e), + }; - Result::<(), crossbeam_channel::SendError>::Ok(()) - }); + #[cfg(not(target_os = "macos"))] + let watcher = notify::recommended_watcher(event_handler).unwrap(); + + #[cfg(target_os = "macos")] + let watcher = PollWatcher::new( + event_handler, + Config::default().with_poll_interval(Duration::from_millis(200)), + ) + .unwrap(); Self { watcher, diff --git a/tests/tests/serve.rs b/tests/tests/serve.rs index d55d339b..9058c366 100644 --- a/tests/tests/serve.rs +++ b/tests/tests/serve.rs @@ -145,6 +145,7 @@ fn edit_init() { }); } +#[ignore = "Does not pass on Github's runner"] #[test] fn move_folder_of_stuff() { run_serve_test("move_folder_of_stuff", |session, mut redactions| { From 23327cb3ef25e47b8e20ebb91560721d7ba56301 Mon Sep 17 00:00:00 2001 From: Vee <106542812+cozywitchcraft@users.noreply.github.com> Date: Mon, 4 Dec 2023 11:02:25 -0500 Subject: [PATCH 1356/1504] Fix preloading assets in plugin (#819) `gatherAssetUrlsRecursive` now returns asset URLs deeper than one layer. --- plugin/src/preloadAssets.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/src/preloadAssets.lua b/plugin/src/preloadAssets.lua index c37ca032..1cf9b2d8 100644 --- a/plugin/src/preloadAssets.lua +++ b/plugin/src/preloadAssets.lua @@ -13,7 +13,7 @@ function gatherAssetUrlsRecursive(currentTable, currentUrls) if typeof(value) == "string" then table.insert(currentUrls, value) elseif typeof(value) == "table" then - gatherAssetUrlsRecursive(value) + gatherAssetUrlsRecursive(value, currentUrls) end end From 96987af71df1df3efa8fe7aabf9d16990e08c605 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Thu, 28 Dec 2023 15:17:00 -0800 Subject: [PATCH 1357/1504] Fix broken serve tests on macOS (#824) Right now, serve tests will fail when Rojo is built with the FSEvent backend. The cause is essentially due to the fact that `/var` (where temporary directories for serve tests are located) on macOS is actually a symlink to `/private/var`. Paths coming from FSEvent always have symlinks expanded, but Rojo never expands symlinks. So, Rojo's paths during these tests look like `/var/*` while the FSEvent paths look like `/private/var/*`. When Rojo's change processor receives these events, it considers them outside the project and does not apply any changes, causing serve tests to time out. To work around this, we can call `Path::canonicalize` before passing the project path to `rojo serve` during serve tests. Rojo does need to better support symlinks (which would also solve the problem), but I think that can be left for another day because it's larger in scope and I mostly just want working tests before addressing #609. --- tests/rojo_test/serve_util.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/rojo_test/serve_util.rs b/tests/rojo_test/serve_util.rs index d8253612..6f049020 100644 --- a/tests/rojo_test/serve_util.rs +++ b/tests/rojo_test/serve_util.rs @@ -66,7 +66,11 @@ impl TestServeSession { let source_path = Path::new(SERVE_TESTS_PATH).join(name); let dir = tempdir().expect("Couldn't create temporary directory"); - let project_path = dir.path().join(name); + let project_path = dir + .path() + .canonicalize() + .expect("Couldn't canonicalize temporary directory path") + .join(name); let source_is_file = fs::metadata(&source_path).unwrap().is_file(); From 11fa08e6d6962a3c54ddd16ecea552f8407bc066 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Fri, 29 Dec 2023 17:46:58 -0800 Subject: [PATCH 1358/1504] Run CI workflow on Windows and macOS (#825) This PR adds macOS and Windows jobs to the CI workflow. This allows us to see when changes break functionality on any supported platform, which is particularly important for changes that involve the file system or file watcher. --- .github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ad5a05d7..a9a39481 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,11 +12,12 @@ on: jobs: build: name: Build and Test - runs-on: ubuntu-latest + runs-on: ${{ matrix.os }} strategy: matrix: rust_version: [stable, 1.70.0] + os: [ubuntu-latest, windows-latest, macos-latest] steps: - uses: actions/checkout@v3 From 097d39e8ce74c42697296d772e0458b0e45fd0d4 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Sun, 31 Dec 2023 12:02:54 -0800 Subject: [PATCH 1359/1504] Fix move_folders_of_stuff (#826) This is a fairly important test verifying whether the action of moving a folder into a watched folder is correctly detected and processed. It was disabled in https://github.com/rojo-rbx/rojo/commit/b43b45be8f2eb01161a389afeab56749fa82e459. The fact that it failed indicates a possible bug in change processing, so in this PR, I'll re-enable the test, investigate why it fails, and fix it. --- src/change_processor.rs | 81 +++++++++++++++++------------------------ tests/tests/serve.rs | 1 - 2 files changed, 34 insertions(+), 48 deletions(-) diff --git a/src/change_processor.rs b/src/change_processor.rs index 2429b590..497ba4e7 100644 --- a/src/change_processor.rs +++ b/src/change_processor.rs @@ -1,6 +1,5 @@ use std::{ fs, - path::PathBuf, sync::{Arc, Mutex}, }; @@ -126,14 +125,41 @@ impl JobThreadContext { // For a given VFS event, we might have many changes to different parts // of the tree. Calculate and apply all of these changes. let applied_patches = match event { - VfsEvent::Write(path) => { - if path.is_dir() { - return; + VfsEvent::Create(path) | VfsEvent::Remove(path) | VfsEvent::Write(path) => { + let mut tree = self.tree.lock().unwrap(); + let mut applied_patches = Vec::new(); + + // Find the nearest ancestor to this path that has + // associated instances in the tree. This helps make sure + // that we handle additions correctly, especially if we + // receive events for descendants of a large tree being + // created all at once. + let mut current_path = path.as_path(); + let affected_ids = loop { + let ids = tree.get_ids_at_path(¤t_path); + + log::trace!("Path {} affects IDs {:?}", current_path.display(), ids); + + if !ids.is_empty() { + break ids.to_vec(); + } + + log::trace!("Trying parent path..."); + match current_path.parent() { + Some(parent) => current_path = parent, + None => break Vec::new(), + } + }; + + for id in affected_ids { + if let Some(patch) = compute_and_apply_changes(&mut tree, &self.vfs, id) { + if !patch.is_empty() { + applied_patches.push(patch); + } + } } - on_vfs_event(path, &self.tree, &self.vfs) - } - VfsEvent::Create(path) | VfsEvent::Remove(path) => { - on_vfs_event(path, &self.tree, &self.vfs) + + applied_patches } _ => { log::warn!("Unhandled VFS event: {:?}", event); @@ -236,45 +262,6 @@ impl JobThreadContext { } } -// Find the nearest ancestor to this path that has -// associated instances in the tree. This helps make sure -// that we handle additions correctly, especially if we -// receive events for descendants of a large tree being -// created all at once. -fn on_vfs_event( - path: PathBuf, - tree: &Arc>, - vfs: &Arc, -) -> Vec { - let mut tree = tree.lock().unwrap(); - let mut applied_patches = Vec::new(); - - let mut current_path = path.as_path(); - let affected_ids = loop { - let ids = tree.get_ids_at_path(current_path); - - log::trace!("Path {} affects IDs {:?}", current_path.display(), ids); - - if !ids.is_empty() { - break ids.to_vec(); - } - - log::trace!("Trying parent path..."); - match current_path.parent() { - Some(parent) => current_path = parent, - None => break Vec::new(), - } - }; - - for id in affected_ids { - if let Some(patch) = compute_and_apply_changes(&mut tree, vfs, id) { - if !patch.is_empty() { - applied_patches.push(patch); - } - } - } - applied_patches -} fn compute_and_apply_changes(tree: &mut RojoTree, vfs: &Vfs, id: Ref) -> Option { let metadata = tree .get_metadata(id) diff --git a/tests/tests/serve.rs b/tests/tests/serve.rs index 9058c366..d55d339b 100644 --- a/tests/tests/serve.rs +++ b/tests/tests/serve.rs @@ -145,7 +145,6 @@ fn edit_init() { }); } -#[ignore = "Does not pass on Github's runner"] #[test] fn move_folder_of_stuff() { run_serve_test("move_folder_of_stuff", |session, mut redactions| { From 3369b0d42980eb6c5c0c86f5972b8ce430a26ae3 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Tue, 2 Jan 2024 09:26:06 -0800 Subject: [PATCH 1360/1504] Downgrade to Notify 4, use FSEvents, use minimal recursive watches (#830) --- CHANGELOG.md | 5 +- Cargo.lock | 183 ++++++++++++++++++++++++------- crates/memofs/CHANGELOG.md | 4 +- crates/memofs/Cargo.toml | 2 +- crates/memofs/src/std_backend.rs | 85 +++++++------- 5 files changed, 192 insertions(+), 87 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2673f56..fe6fc377 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Rojo Changelog ## Unreleased Changes +* Significantly improved performance of `rojo serve`, `rojo build --watch`, and `rojo sourcemap --watch` on macOS. [#830] + +[#830]: https://github.com/rojo-rbx/rojo/pull/830 ## [7.4.0-rc3] - October 25, 2023 * Changed `sourcemap --watch` to only generate the sourcemap when it's necessary ([#800]) @@ -138,7 +141,6 @@ * Add buttons for navigation on the Connected page ([#722]) ### Fixes -* Significantly improved performance of `rojo serve` and `rojo build` on macOS. [#783] * Significantly improved performance of `rojo sourcemap` ([#668]) * Fixed the diff visualizer of connected sessions. ([#674]) * Fixed disconnected session activity. ([#675]) @@ -172,7 +174,6 @@ [#770]: https://github.com/rojo-rbx/rojo/pull/770 [#771]: https://github.com/rojo-rbx/rojo/pull/771 [#774]: https://github.com/rojo-rbx/rojo/pull/774 -[#783]: https://github.com/rojo-rbx/rojo/pull/783 [rbx-dom#299]: https://github.com/rojo-rbx/rbx-dom/pull/299 [rbx-dom#296]: https://github.com/rojo-rbx/rbx-dom/pull/296 diff --git a/Cargo.lock b/Cargo.lock index 87b5111b..d0565dc1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -52,7 +52,7 @@ checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" dependencies = [ "hermit-abi 0.1.19", "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -424,7 +424,7 @@ checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -550,14 +550,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" [[package]] -name = "fsevent-sys" -version = "4.1.0" +name = "fsevent" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ee7a02da4d231650c7cea31349b889be2f45ddb3ef3032d2ec8185f6313fd2" +checksum = "5ab7d1bd1bd33cc98b0889831b72da23c0aa4df9cec7e0702f46ecea04b35db6" +dependencies = [ + "bitflags 1.3.2", + "fsevent-sys", +] + +[[package]] +name = "fsevent-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f41b048a94555da0f42f1d632e2e19510084fb8e303b0daa2816e733fb3644a0" dependencies = [ "libc", ] +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +dependencies = [ + "bitflags 1.3.2", + "fuchsia-zircon-sys", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" + [[package]] name = "futures" version = "0.3.28" @@ -857,9 +883,9 @@ dependencies = [ [[package]] name = "inotify" -version = "0.9.6" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8069d3ec154eb856955c1c0fbffefbf5f3c40a104ec912d4797314c1801abff" +checksum = "4816c66d2c8ae673df83366c18341538f234a26d65a9ecea5c348b453ac1d02f" dependencies = [ "bitflags 1.3.2", "inotify-sys", @@ -891,6 +917,15 @@ dependencies = [ "yaml-rust", ] +[[package]] +name = "iovec" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" +dependencies = [ + "libc", +] + [[package]] name = "ipnet" version = "2.8.0" @@ -928,23 +963,13 @@ dependencies = [ ] [[package]] -name = "kqueue" -version = "1.0.8" +name = "kernel32-sys" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7447f1ca1b7b563588a205fe93dea8df60fd981423a768bc1c0ded35ed147d0c" +checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" dependencies = [ - "kqueue-sys", - "libc", -] - -[[package]] -name = "kqueue-sys" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed9625ffda8729b85e45cf04090035ac368927b8cebc34898e7c120f52e4838b" -dependencies = [ - "bitflags 1.3.2", - "libc", + "winapi 0.2.8", + "winapi-build", ] [[package]] @@ -953,6 +978,12 @@ version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +[[package]] +name = "lazycell" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" + [[package]] name = "libc" version = "0.2.148" @@ -1065,6 +1096,25 @@ dependencies = [ "adler", ] +[[package]] +name = "mio" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" +dependencies = [ + "cfg-if 0.1.10", + "fuchsia-zircon", + "fuchsia-zircon-sys", + "iovec", + "kernel32-sys", + "libc", + "log", + "miow", + "net2", + "slab", + "winapi 0.2.8", +] + [[package]] name = "mio" version = "0.8.8" @@ -1072,11 +1122,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" dependencies = [ "libc", - "log", "wasi", "windows-sys 0.48.0", ] +[[package]] +name = "mio-extras" +version = "2.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52403fe290012ce777c4626790c8951324a2b9e3316b3143779c72b029742f19" +dependencies = [ + "lazycell", + "log", + "mio 0.6.23", + "slab", +] + +[[package]] +name = "miow" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" +dependencies = [ + "kernel32-sys", + "net2", + "winapi 0.2.8", + "ws2_32-sys", +] + [[package]] name = "native-tls" version = "0.2.11" @@ -1096,22 +1169,32 @@ dependencies = [ ] [[package]] -name = "notify" -version = "6.1.1" +name = "net2" +version = "0.2.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" +checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" dependencies = [ - "bitflags 2.4.0", - "crossbeam-channel", + "cfg-if 0.1.10", + "libc", + "winapi 0.3.9", +] + +[[package]] +name = "notify" +version = "4.0.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae03c8c853dba7bfd23e571ff0cff7bc9dceb40a4cd684cd1681824183f45257" +dependencies = [ + "bitflags 1.3.2", "filetime", + "fsevent", "fsevent-sys", "inotify", - "kqueue", "libc", - "log", - "mio", + "mio 0.6.23", + "mio-extras", "walkdir", - "windows-sys 0.48.0", + "winapi 0.3.9", ] [[package]] @@ -1121,7 +1204,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -1171,7 +1254,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "293c15678e37254c15bd2f092314abb4e51d7fdde05c2021279c12631b54f005" dependencies = [ "bstr", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2028,7 +2111,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" dependencies = [ "libc", - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2191,7 +2274,7 @@ dependencies = [ "backtrace", "bytes", "libc", - "mio", + "mio 0.8.8", "num_cpus", "pin-project-lite", "socket2 0.5.4", @@ -2550,6 +2633,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "winapi" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" + [[package]] name = "winapi" version = "0.3.9" @@ -2560,6 +2649,12 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] +[[package]] +name = "winapi-build" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" + [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -2572,7 +2667,7 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2728,7 +2823,7 @@ version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2986deb581c4fe11b621998a5e53361efe6b48a151178d0cd9eeffa4dc6acc9" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2737,7 +2832,7 @@ version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" dependencies = [ - "winapi", + "winapi 0.3.9", ] [[package]] @@ -2750,6 +2845,16 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "ws2_32-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" +dependencies = [ + "winapi 0.2.8", + "winapi-build", +] + [[package]] name = "xml-rs" version = "0.8.19" diff --git a/crates/memofs/CHANGELOG.md b/crates/memofs/CHANGELOG.md index 43516260..c9961d0e 100644 --- a/crates/memofs/CHANGELOG.md +++ b/crates/memofs/CHANGELOG.md @@ -1,7 +1,9 @@ # memofs Changelog ## Unreleased Changes -* Changed the `StdBackend` file watcher to use `PollWatcher` on macOS. +* Changed `StdBackend` file watching component to use minimal recursive watches. [#830] + +[#830]: https://github.com/rojo-rbx/rojo/pull/830 ## 0.2.0 (2021-08-23) * Updated to `crossbeam-channel` 0.5.1. diff --git a/crates/memofs/Cargo.toml b/crates/memofs/Cargo.toml index b60a3038..5cf5a733 100644 --- a/crates/memofs/Cargo.toml +++ b/crates/memofs/Cargo.toml @@ -13,5 +13,5 @@ homepage = "https://github.com/rojo-rbx/rojo/tree/master/memofs" [dependencies] crossbeam-channel = "0.5.1" fs-err = "2.3.0" -notify = "6.1.1" +notify = "4.0.15" serde = { version = "1.0", features = ["derive"] } diff --git a/crates/memofs/src/std_backend.rs b/crates/memofs/src/std_backend.rs index 4e95f110..0a8fb3b7 100644 --- a/crates/memofs/src/std_backend.rs +++ b/crates/memofs/src/std_backend.rs @@ -1,68 +1,55 @@ -use std::io; -use std::path::Path; +use std::path::{Path, PathBuf}; +use std::sync::mpsc; +use std::thread; +use std::time::Duration; +use std::{collections::HashSet, io}; use crossbeam_channel::Receiver; - -use notify::{Event, EventKind, RecommendedWatcher, RecursiveMode, Watcher}; - -#[cfg(target_os = "macos")] -use notify::{Config, PollWatcher}; - -#[cfg(target_os = "macos")] -use std::time::Duration; +use notify::{watcher, DebouncedEvent, RecommendedWatcher, RecursiveMode, Watcher}; use crate::{DirEntry, Metadata, ReadDir, VfsBackend, VfsEvent}; /// `VfsBackend` that uses `std::fs` and the `notify` crate. pub struct StdBackend { - #[cfg(target_os = "macos")] - watcher: PollWatcher, - - #[cfg(not(target_os = "macos"))] watcher: RecommendedWatcher, - watcher_receiver: Receiver, + watches: HashSet, } impl StdBackend { pub fn new() -> StdBackend { + let (notify_tx, notify_rx) = mpsc::channel(); + let watcher = watcher(notify_tx, Duration::from_millis(50)).unwrap(); + let (tx, rx) = crossbeam_channel::unbounded(); - let event_handler = move |res: Result| match res { - Ok(event) => match event.kind { - EventKind::Create(_) => { - for path in event.paths { - let _ = tx.send(VfsEvent::Create(path)); + thread::spawn(move || { + for event in notify_rx { + match event { + DebouncedEvent::Create(path) => { + tx.send(VfsEvent::Create(path))?; } - } - EventKind::Modify(_) => { - for path in event.paths { - let _ = tx.send(VfsEvent::Write(path)); + DebouncedEvent::Write(path) => { + tx.send(VfsEvent::Write(path))?; } - } - EventKind::Remove(_) => { - for path in event.paths { - let _ = tx.send(VfsEvent::Remove(path)); + DebouncedEvent::Remove(path) => { + tx.send(VfsEvent::Remove(path))?; } + DebouncedEvent::Rename(from, to) => { + tx.send(VfsEvent::Remove(from))?; + tx.send(VfsEvent::Create(to))?; + } + _ => {} } - _ => {} - }, - Err(e) => println!("watch error: {:?}", e), - }; + } - #[cfg(not(target_os = "macos"))] - let watcher = notify::recommended_watcher(event_handler).unwrap(); - - #[cfg(target_os = "macos")] - let watcher = PollWatcher::new( - event_handler, - Config::default().with_poll_interval(Duration::from_millis(200)), - ) - .unwrap(); + Result::<(), crossbeam_channel::SendError>::Ok(()) + }); Self { watcher, watcher_receiver: rx, + watches: HashSet::new(), } } } @@ -112,12 +99,22 @@ impl VfsBackend for StdBackend { } fn watch(&mut self, path: &Path) -> io::Result<()> { - self.watcher - .watch(path, RecursiveMode::NonRecursive) - .map_err(|inner| io::Error::new(io::ErrorKind::Other, inner)) + if self.watches.contains(path) + || path + .ancestors() + .any(|ancestor| self.watches.contains(ancestor)) + { + Ok(()) + } else { + self.watches.insert(path.to_path_buf()); + self.watcher + .watch(path, RecursiveMode::Recursive) + .map_err(|inner| io::Error::new(io::ErrorKind::Other, inner)) + } } fn unwatch(&mut self, path: &Path) -> io::Result<()> { + self.watches.remove(path); self.watcher .unwatch(path) .map_err(|inner| io::Error::new(io::ErrorKind::Other, inner)) From fd8bc8ae3fd7d8b80181ed5467d03df5a9beb416 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Tue, 2 Jan 2024 12:32:37 -0500 Subject: [PATCH 1361/1504] Improve visualization for arrays (#829) --- CHANGELOG.md | 2 ++ .../Components/PatchVisualizer/DisplayValue.lua | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe6fc377..8021fac9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,10 @@ # Rojo Changelog ## Unreleased Changes +* Improved the visualization for array properties like Tags ([#829]) * Significantly improved performance of `rojo serve`, `rojo build --watch`, and `rojo sourcemap --watch` on macOS. [#830] +[#829]: https://github.com/rojo-rbx/rojo/pull/829 [#830]: https://github.com/rojo-rbx/rojo/pull/830 ## [7.4.0-rc3] - October 25, 2023 diff --git a/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua b/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua index 439c95d9..a231b879 100644 --- a/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua +++ b/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua @@ -53,8 +53,23 @@ local function DisplayValue(props) elseif next(props.value) == nil then -- If it's empty, show empty braces textRepresentation = "{}" + elseif next(props.value) == 1 then + -- We don't need to support mixed tables, so checking the first key is enough + -- to determine if it's a simple array + local out, i = table.create(#props.value), 0 + for k, v in props.value do + i += 1 + + -- Wrap strings in quotes + if type(v) == "string" then + v = '"' .. v .. '"' + end + + out[i] = tostring(v) + end + textRepresentation = "{ " .. table.concat(out, ", ") .. " }" else - -- If it has children, list them out + -- Otherwise, show the table contents as a dictionary local out, i = {}, 0 for k, v in pairs(props.value) do i += 1 From 6adc5eb9fbf50af6287de12709ce84dff990d5c6 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Tue, 2 Jan 2024 15:49:24 -0800 Subject: [PATCH 1362/1504] Conserve CI minutes via cache, skip macOS+Windows MSRV builds (#827) Windows and macOS runners consume GitHub Actions minutes at [2x and 10x the rate of Linux runners, respectively](https://docs.github.com/en/billing/managing-billing-for-github-actions/about-billing-for-github-actions#minute-multipliers). This is a bit concerning now that there are two Windows jobs and two macOS jobs, introduced in #825. This PR aims to reduce the cost by: * Adding [rust-cache](https://github.com/Swatinem/rust-cache/) to reduce the amount of time spent. I'm aware there were some concerns raised about CI caches in general in #496 - are they still a blocker? * Removing the unnecessary Windows and macOS MSRV build jobs. If an MSRV build fails on one platform due to usage of new language features, then it will fail on all of them. @Kampfkarren may have to change this repository's required status checks before this PR can be merged --- .github/workflows/ci.yml | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9a39481..17205587 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,7 +16,6 @@ jobs: strategy: matrix: - rust_version: [stable, 1.70.0] os: [ubuntu-latest, windows-latest, macos-latest] steps: @@ -27,10 +26,13 @@ jobs: - name: Install Rust uses: actions-rs/toolchain@v1 with: - toolchain: ${{ matrix.rust_version }} + toolchain: stable override: true profile: minimal + - name: Rust cache + uses: Swatinem/rust-cache@v2 + - name: Setup Aftman uses: ok-nick/setup-aftman@v0.3.0 with: @@ -42,6 +44,33 @@ jobs: - name: Test run: cargo test --locked --verbose + msrv: + name: Check MSRV + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + submodules: true + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + toolchain: 1.70.0 + override: true + profile: minimal + + - name: Rust cache + uses: Swatinem/rust-cache@v2 + + - name: Setup Aftman + uses: ok-nick/setup-aftman@v0.3.0 + with: + version: 'v0.2.7' + + - name: Build + run: cargo build --locked --verbose + lint: name: Rustfmt, Clippy, & Stylua runs-on: ubuntu-latest @@ -58,6 +87,9 @@ jobs: override: true components: rustfmt, clippy + - name: Rust cache + uses: Swatinem/rust-cache@v2 + - name: Setup Aftman uses: ok-nick/setup-aftman@v0.3.0 with: From 269272983b583a192af1b0be8e553bbd2f25ef9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F?= <34089907+Barocena@users.noreply.github.com> Date: Sat, 6 Jan 2024 03:00:49 +0300 Subject: [PATCH 1363/1504] Changed file extensions of init command from lua to luau (#831) --- .editorconfig | 3 +++ CHANGELOG.md | 4 +++- .../{src-init.lua => src-init.luau} | 0 .../end_to_end__tests__build__server_init.snap | 2 +- ...ocalScript.client.lua => localScript.client.luau} | 0 .../folder1/{test.server.lua => test.server.luau} | 0 .../folder3/{test.server.lua => test.server.luau} | 0 .../folder/{hello.server.lua => hello.server.luau} | 0 ...verScript.server.lua => serverScript.server.luau} | 0 .../build-tests/server_init/folder/init.server.lua | 1 - .../build-tests/server_init/folder/init.server.luau | 1 + src/cli/init.rs | 12 ++++++------ test-projects/plugins/default.project.json | 2 +- .../plugins/{test-plugin.lua => test-plugin.luau} | 0 14 files changed, 15 insertions(+), 10 deletions(-) rename assets/default-model-project/{src-init.lua => src-init.luau} (100%) rename rojo-test/build-tests/client_in_folder/folder/{localScript.client.lua => localScript.client.luau} (100%) rename rojo-test/build-tests/nested_runcontext/folder1/{test.server.lua => test.server.luau} (100%) rename rojo-test/build-tests/nested_runcontext/folder2/folder3/{test.server.lua => test.server.luau} (100%) rename rojo-test/build-tests/script_meta_disabled/folder/{hello.server.lua => hello.server.luau} (100%) rename rojo-test/build-tests/server_in_folder/folder/{serverScript.server.lua => serverScript.server.luau} (100%) delete mode 100644 rojo-test/build-tests/server_init/folder/init.server.lua create mode 100644 rojo-test/build-tests/server_init/folder/init.server.luau rename test-projects/plugins/{test-plugin.lua => test-plugin.luau} (100%) diff --git a/.editorconfig b/.editorconfig index aa7f61e9..42639a34 100644 --- a/.editorconfig +++ b/.editorconfig @@ -23,4 +23,7 @@ insert_final_newline = true insert_final_newline = true [*.lua] +indent_style = tab + +[*.luau] indent_style = tab \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 8021fac9..ba305c50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,10 +2,12 @@ ## Unreleased Changes * Improved the visualization for array properties like Tags ([#829]) -* Significantly improved performance of `rojo serve`, `rojo build --watch`, and `rojo sourcemap --watch` on macOS. [#830] +* Significantly improved performance of `rojo serve`, `rojo build --watch`, and `rojo sourcemap --watch` on macOS. ([#830]) +* Changed *.lua files that init command generates to *.luau ([#831]) [#829]: https://github.com/rojo-rbx/rojo/pull/829 [#830]: https://github.com/rojo-rbx/rojo/pull/830 +[#831]: https://github.com/rojo-rbx/rojo/pull/831 ## [7.4.0-rc3] - October 25, 2023 * Changed `sourcemap --watch` to only generate the sourcemap when it's necessary ([#800]) diff --git a/assets/default-model-project/src-init.lua b/assets/default-model-project/src-init.luau similarity index 100% rename from assets/default-model-project/src-init.lua rename to assets/default-model-project/src-init.luau diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__server_init.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__server_init.snap index 5858d5e0..2bbda073 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__server_init.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__server_init.snap @@ -7,7 +7,7 @@ expression: contents server_init 0 - return "From folder/init.server.lua" + return "From folder/init.server.luau" diff --git a/rojo-test/build-tests/client_in_folder/folder/localScript.client.lua b/rojo-test/build-tests/client_in_folder/folder/localScript.client.luau similarity index 100% rename from rojo-test/build-tests/client_in_folder/folder/localScript.client.lua rename to rojo-test/build-tests/client_in_folder/folder/localScript.client.luau diff --git a/rojo-test/build-tests/nested_runcontext/folder1/test.server.lua b/rojo-test/build-tests/nested_runcontext/folder1/test.server.luau similarity index 100% rename from rojo-test/build-tests/nested_runcontext/folder1/test.server.lua rename to rojo-test/build-tests/nested_runcontext/folder1/test.server.luau diff --git a/rojo-test/build-tests/nested_runcontext/folder2/folder3/test.server.lua b/rojo-test/build-tests/nested_runcontext/folder2/folder3/test.server.luau similarity index 100% rename from rojo-test/build-tests/nested_runcontext/folder2/folder3/test.server.lua rename to rojo-test/build-tests/nested_runcontext/folder2/folder3/test.server.luau diff --git a/rojo-test/build-tests/script_meta_disabled/folder/hello.server.lua b/rojo-test/build-tests/script_meta_disabled/folder/hello.server.luau similarity index 100% rename from rojo-test/build-tests/script_meta_disabled/folder/hello.server.lua rename to rojo-test/build-tests/script_meta_disabled/folder/hello.server.luau diff --git a/rojo-test/build-tests/server_in_folder/folder/serverScript.server.lua b/rojo-test/build-tests/server_in_folder/folder/serverScript.server.luau similarity index 100% rename from rojo-test/build-tests/server_in_folder/folder/serverScript.server.lua rename to rojo-test/build-tests/server_in_folder/folder/serverScript.server.luau diff --git a/rojo-test/build-tests/server_init/folder/init.server.lua b/rojo-test/build-tests/server_init/folder/init.server.lua deleted file mode 100644 index 30d3d49a..00000000 --- a/rojo-test/build-tests/server_init/folder/init.server.lua +++ /dev/null @@ -1 +0,0 @@ -return "From folder/init.server.lua" \ No newline at end of file diff --git a/rojo-test/build-tests/server_init/folder/init.server.luau b/rojo-test/build-tests/server_init/folder/init.server.luau new file mode 100644 index 00000000..196105d7 --- /dev/null +++ b/rojo-test/build-tests/server_init/folder/init.server.luau @@ -0,0 +1 @@ +return "From folder/init.server.luau" \ No newline at end of file diff --git a/src/cli/init.rs b/src/cli/init.rs index 48d513b1..5f861470 100644 --- a/src/cli/init.rs +++ b/src/cli/init.rs @@ -13,7 +13,7 @@ use super::resolve_path; static MODEL_PROJECT: &str = include_str!("../../assets/default-model-project/default.project.json"); static MODEL_README: &str = include_str!("../../assets/default-model-project/README.md"); -static MODEL_INIT: &str = include_str!("../../assets/default-model-project/src-init.lua"); +static MODEL_INIT: &str = include_str!("../../assets/default-model-project/src-init.luau"); static MODEL_GIT_IGNORE: &str = include_str!("../../assets/default-model-project/gitignore.txt"); static PLACE_PROJECT: &str = @@ -116,17 +116,17 @@ fn init_place(base_path: &Path, project_params: ProjectParams) -> anyhow::Result fs::create_dir_all(src.join(&src_client))?; write_if_not_exists( - &src_shared.join("Hello.lua"), + &src_shared.join("Hello.luau"), "return function()\n\tprint(\"Hello, world!\")\nend", )?; write_if_not_exists( - &src_server.join("init.server.lua"), + &src_server.join("init.server.luau"), "print(\"Hello world, from server!\")", )?; write_if_not_exists( - &src_client.join("init.client.lua"), + &src_client.join("init.client.luau"), "print(\"Hello world, from client!\")", )?; @@ -149,7 +149,7 @@ fn init_model(base_path: &Path, project_params: ProjectParams) -> anyhow::Result fs::create_dir_all(&src)?; let init = project_params.render_template(MODEL_INIT); - write_if_not_exists(&src.join("init.lua"), &init)?; + write_if_not_exists(&src.join("init.luau"), &init)?; let git_ignore = project_params.render_template(MODEL_GIT_IGNORE); try_git_init(base_path, &git_ignore)?; @@ -170,7 +170,7 @@ fn init_plugin(base_path: &Path, project_params: ProjectParams) -> anyhow::Resul fs::create_dir_all(&src)?; write_if_not_exists( - &src.join("init.server.lua"), + &src.join("init.server.luau"), "print(\"Hello world, from plugin!\")\n", )?; diff --git a/test-projects/plugins/default.project.json b/test-projects/plugins/default.project.json index 02387e7e..4ca44a88 100644 --- a/test-projects/plugins/default.project.json +++ b/test-projects/plugins/default.project.json @@ -4,6 +4,6 @@ "$path": "src" }, "plugins": [ - "test-plugin.lua" + "test-plugin.luau" ] } \ No newline at end of file diff --git a/test-projects/plugins/test-plugin.lua b/test-projects/plugins/test-plugin.luau similarity index 100% rename from test-projects/plugins/test-plugin.lua rename to test-projects/plugins/test-plugin.luau From b12ce47e7e535956cf9542720895fc9fec67d35d Mon Sep 17 00:00:00 2001 From: boatbomber Date: Fri, 12 Jan 2024 12:35:29 -0800 Subject: [PATCH 1364/1504] Don't remind to sync if the lock is claimed (#833) If the sync lock is claimed in Team Create, the user cannot sync. Therefore, a sync reminder notification is unhelpful as it is calling to an invalid action. --- CHANGELOG.md | 2 ++ plugin/src/App/init.lua | 33 ++++++++++++++++++++++++++++----- 2 files changed, 30 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba305c50..c9730cf2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,12 @@ * Improved the visualization for array properties like Tags ([#829]) * Significantly improved performance of `rojo serve`, `rojo build --watch`, and `rojo sourcemap --watch` on macOS. ([#830]) * Changed *.lua files that init command generates to *.luau ([#831]) +* Does not remind users to sync if the sync lock is claimed already ([#833]) [#829]: https://github.com/rojo-rbx/rojo/pull/829 [#830]: https://github.com/rojo-rbx/rojo/pull/830 [#831]: https://github.com/rojo-rbx/rojo/pull/831 +[#833]: https://github.com/rojo-rbx/rojo/pull/833 ## [7.4.0-rc3] - October 25, 2023 * Changed `sourcemap --watch` to only generate the sourcemap when it's necessary ([#800]) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index cfebcad8..22f277f9 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -136,6 +136,7 @@ function App:init() and self.serveSession == nil and Settings:get("syncReminder") and self:getLastSyncTimestamp() + and (self:isSyncLockAvailable()) then self:addNotification("You've previously synced this place. Would you like to reconnect?", 300, { Connect = { @@ -283,12 +284,39 @@ function App:getHostAndPort() return host, port end +function App:isSyncLockAvailable() + if #Players:GetPlayers() == 0 then + -- Team Create is not active, so no one can be holding the lock + return true + end + + local lock = ServerStorage:FindFirstChild("__Rojo_SessionLock") + if not lock then + -- No lock is made yet, so it is available + return true + end + + if lock.Value and lock.Value ~= Players.LocalPlayer and lock.Value.Parent then + -- Someone else is holding the lock + return false, lock.Value + end + + -- The lock exists, but is not claimed + return true +end + function App:claimSyncLock() if #Players:GetPlayers() == 0 then Log.trace("Skipping sync lock because this isn't in Team Create") return true end + local isAvailable, priorOwner = self:isSyncLockAvailable() + if not isAvailable then + Log.trace("Skipping sync lock because it is already claimed") + return false, priorOwner + end + local lock = ServerStorage:FindFirstChild("__Rojo_SessionLock") if not lock then lock = Instance.new("ObjectValue") @@ -300,11 +328,6 @@ function App:claimSyncLock() return true end - if lock.Value and lock.Value ~= Players.LocalPlayer and lock.Value.Parent then - Log.trace("Found existing sync lock owned by {}", lock.Value) - return false, lock.Value - end - lock.Value = Players.LocalPlayer Log.trace("Claimed existing sync lock") return true From c7173ac8325bfe6309841e6bd679cf32fadc267e Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 16 Jan 2024 10:09:16 -0800 Subject: [PATCH 1365/1504] Don't serialize `emitLegacyScripts` if it's `None` (#835) --- src/project.rs | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/project.rs b/src/project.rs index 1a645b76..93a3cb21 100644 --- a/src/project.rs +++ b/src/project.rs @@ -8,9 +8,7 @@ use std::{ use serde::{Deserialize, Serialize}; use thiserror::Error; -use crate::{ - glob::Glob, resolution::UnresolvedValue, snapshot_middleware::emit_legacy_scripts_default, -}; +use crate::{glob::Glob, resolution::UnresolvedValue}; static PROJECT_FILENAME: &str = "default.project.json"; @@ -75,12 +73,10 @@ pub struct Project { #[serde(skip_serializing_if = "Option::is_none")] pub serve_address: Option, - /// Determines if rojo should emit scripts with the appropriate `RunContext` for `*.client.lua` and `*.server.lua` files in the project. - /// Or, if rojo should keep the legacy behavior of emitting LocalScripts and Scripts with legacy Runcontext - #[serde( - default = "emit_legacy_scripts_default", - skip_serializing_if = "Option::is_none" - )] + /// Determines if Rojo should emit scripts with the appropriate `RunContext` + /// for `*.client.lua` and `*.server.lua` files in the project instead of + /// using `Script` and `LocalScript` Instances. + #[serde(skip_serializing_if = "Option::is_none")] pub emit_legacy_scripts: Option, /// A list of globs, relative to the folder the project file is in, that From 9d0d76f0a50c6525860030d4b36321d7179b1d28 Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 16 Jan 2024 12:09:10 -0800 Subject: [PATCH 1366/1504] Ensure plugin and Cargo version match exact at compile-time (#836) --- build.rs | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/build.rs b/build.rs index 7dbfc98a..9f9a606b 100644 --- a/build.rs +++ b/build.rs @@ -48,12 +48,8 @@ fn main() -> Result<(), anyhow::Error> { let plugin_version = Version::parse(fs::read_to_string(plugin_root.join("Version.txt"))?.trim())?; - assert!( - our_version.major == plugin_version.major, - "plugin version does not match Cargo version" - ); - assert!( - our_version.minor == plugin_version.minor, + assert_eq!( + our_version, plugin_version, "plugin version does not match Cargo version" ); From c0a96e38110c14e932c3319b8ae32a1aaf8f2e9b Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 16 Jan 2024 12:12:40 -0800 Subject: [PATCH 1367/1504] Release v7.4.0 (#837) --- CHANGELOG.md | 2 + Cargo.lock | 26 +- Cargo.toml | 12 +- plugin/Version.txt | 2 +- plugin/rbx_dom_lua/database.json | 1353 +++++++++++++++++++++++++++--- src/cli/build.rs | 2 +- 6 files changed, 1247 insertions(+), 150 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9730cf2..7542adc7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,8 @@ # Rojo Changelog ## Unreleased Changes + +## [7.4.0] - January 16, 2024 * Improved the visualization for array properties like Tags ([#829]) * Significantly improved performance of `rojo serve`, `rojo build --watch`, and `rojo sourcemap --watch` on macOS. ([#830]) * Changed *.lua files that init command generates to *.luau ([#831]) diff --git a/Cargo.lock b/Cargo.lock index d0565dc1..3e2556f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1586,9 +1586,9 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad50c13afe91296dad6508ea7e29f4b665fa56cb664ad01eaf8fdbd3da69d5e1" +checksum = "6314dd6bf5c21d0598cdb53cf5d241aa643ba41da8b8abf7402b4a35096f03f6" dependencies = [ "log", "lz4", @@ -1601,9 +1601,9 @@ dependencies = [ [[package]] name = "rbx_dom_weak" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "843a2e0e1446623625943f7228d9d4b5cf3883017e3964733600682506864b34" +checksum = "9b67b56bac99849c2e3c57547b036927f71c57cf7f4d900d04e3e4ee774ec316" dependencies = [ "rbx_types", "serde", @@ -1611,9 +1611,9 @@ dependencies = [ [[package]] name = "rbx_reflection" -version = "4.4.0" +version = "4.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41e762dfca3217d2d37da631de2fa0d1616edaa61a0a2633263d5d3305baf8c3" +checksum = "0d41509c991b53a7276a746a795eae2b9204f398164920f61976995b47fe1722" dependencies = [ "rbx_types", "serde", @@ -1622,9 +1622,9 @@ dependencies = [ [[package]] name = "rbx_reflection_database" -version = "0.2.9+roblox-596" +version = "0.2.10+roblox-607" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b18f088a2b4aa66324ec97b5b6ffacb53188aef19f3497d95d6a1d1dbb28e66" +checksum = "12e20c06fa41f7aadc79005c8354f592b2c2f4d0c61e1080ed5718dafc30aea0" dependencies = [ "lazy_static", "rbx_reflection", @@ -1634,9 +1634,9 @@ dependencies = [ [[package]] name = "rbx_types" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a991523e3ad5f43a4d121cb4a1e5bc23f7826bb4a1db5aa51e94f1073150ec" +checksum = "7ca23bfd469d067d81ef14f65fe09aeddc25abcf576a889d1a7664fe021cf18c" dependencies = [ "base64 0.13.1", "bitflags 1.3.2", @@ -1649,9 +1649,9 @@ dependencies = [ [[package]] name = "rbx_xml" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc87343301303ff0510903fb7eb3dbd1c75bdb6ab780fea6091bdc3f58b5829f" +checksum = "f8c03f95500961c32340791d1fabd4587f6873bdbff077ecca6ae32db7960dea" dependencies = [ "base64 0.13.1", "log", @@ -1831,7 +1831,7 @@ dependencies = [ [[package]] name = "rojo" -version = "7.4.0-rc3" +version = "7.4.0" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index 1401d2e0..0b5ae9e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "7.4.0-rc3" +version = "7.4.0" rust-version = "1.70.0" authors = ["Lucien Greathouse "] description = "Enables professional-grade development tools for Roblox developers" @@ -49,11 +49,11 @@ memofs = { version = "0.2.0", path = "crates/memofs" } # rbx_reflection_database = { path = "../rbx-dom/rbx_reflection_database" } # rbx_xml = { path = "../rbx-dom/rbx_xml" } -rbx_binary = "0.7.3" -rbx_dom_weak = "2.6.0" -rbx_reflection = "4.4.0" -rbx_reflection_database = "0.2.8" -rbx_xml = "0.13.2" +rbx_binary = "0.7.4" +rbx_dom_weak = "2.7.0" +rbx_reflection = "4.5.0" +rbx_reflection_database = "0.2.10" +rbx_xml = "0.13.3" anyhow = "1.0.44" backtrace = "0.3.61" diff --git a/plugin/Version.txt b/plugin/Version.txt index c129df57..b6167179 100644 --- a/plugin/Version.txt +++ b/plugin/Version.txt @@ -1 +1 @@ -7.4.0-rc3 \ No newline at end of file +7.4.0 \ No newline at end of file diff --git a/plugin/rbx_dom_lua/database.json b/plugin/rbx_dom_lua/database.json index 817d3130..81424b27 100644 --- a/plugin/rbx_dom_lua/database.json +++ b/plugin/rbx_dom_lua/database.json @@ -1,9 +1,9 @@ { "Version": [ 0, - 597, - 1, - 5970668 + 607, + 0, + 6070550 ], "Classes": { "Accessory": { @@ -13,7 +13,7 @@ "Properties": { "AccessoryType": { "Name": "AccessoryType", - "Scriptability": "Read", + "Scriptability": "ReadWrite", "DataType": { "Enum": "AccessoryType" }, @@ -191,6 +191,17 @@ } } }, + "AccountService": { + "Name": "AccountService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Accoutrement": { "Name": "Accoutrement", "Tags": [], @@ -446,6 +457,19 @@ } } }, + "EnableVideoAds": { + "Name": "EnableVideoAds", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "FallbackImage": { "Name": "FallbackImage", "Scriptability": "ReadWrite", @@ -881,7 +905,7 @@ }, "DefaultProperties": { "AlignType": { - "Enum": 0 + "Enum": 5 }, "Attributes": { "Attributes": {} @@ -2007,6 +2031,23 @@ } } }, + "FACSDataLod": { + "Name": "FACSDataLod", + "Scriptability": "Read", + "DataType": { + "Enum": "FACSDataLod" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "IsPlaying": { "Name": "IsPlaying", "Scriptability": "Read", @@ -4508,7 +4549,6 @@ "Name": "AvatarCreationService", "Tags": [ "NotCreatable", - "NotReplicated", "Service" ], "Superclass": "Instance", @@ -6025,6 +6065,15 @@ "Properties": {}, "DefaultProperties": {} }, + "BaseRemoteEvent": { + "Name": "BaseRemoteEvent", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "BaseScript": { "Name": "BaseScript", "Tags": [ @@ -11817,6 +11866,34 @@ "Properties": {}, "DefaultProperties": {} }, + "ConnectivityService": { + "Name": "ConnectivityService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "NetworkStatus": { + "Name": "NetworkStatus", + "Scriptability": "None", + "DataType": { + "Enum": "NetworkStatus" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "Constraint": { "Name": "Constraint", "Tags": [ @@ -12338,6 +12415,17 @@ "Properties": {}, "DefaultProperties": {} }, + "ConversationalAIAcceptanceService": { + "Name": "ConversationalAIAcceptanceService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "CookiesService": { "Name": "CookiesService", "Tags": [ @@ -13192,6 +13280,19 @@ } } }, + "SoftlockAngularServoUponReachingTarget": { + "Name": "SoftlockAngularServoUponReachingTarget", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TargetAngle": { "Name": "TargetAngle", "Scriptability": "ReadWrite", @@ -13291,7 +13392,7 @@ "Float32": null }, "MotorMaxAngularAcceleration": { - "Float32": null + "Float32": 500000.0 }, "MotorMaxForce": { "Float32": 0.0 @@ -13314,6 +13415,12 @@ "Size": { "Float32": 0.15 }, + "SoftlockAngularServoUponReachingTarget": { + "Bool": false + }, + "SoftlockServoUponReachingTarget": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -16382,90 +16489,6 @@ }, "DefaultProperties": {} }, - "DynamicImage": { - "Name": "DynamicImage", - "Tags": [], - "Superclass": "Instance", - "Properties": { - "Size": { - "Name": "Size", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector2" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": {} - }, - "DynamicMesh": { - "Name": "DynamicMesh", - "Tags": [], - "Superclass": "DataModelMesh", - "Properties": { - "MeshVersion": { - "Name": "MeshVersion", - "Scriptability": "Read", - "DataType": { - "Value": "Int32" - }, - "Tags": [ - "Hidden" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "Attributes": { - "Attributes": {} - }, - "Capabilities": { - "SecurityCapabilities": 0 - }, - "DefinesCapabilities": { - "Bool": false - }, - "MeshVersion": { - "Int32": 0 - }, - "Offset": { - "Vector3": [ - 0.0, - 0.0, - 0.0 - ] - }, - "Scale": { - "Vector3": [ - 1.0, - 1.0, - 1.0 - ] - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "Tags": [] - }, - "VertexColor": { - "Vector3": [ - 1.0, - 1.0, - 1.0 - ] - } - } - }, "DynamicRotate": { "Name": "DynamicRotate", "Tags": [ @@ -16583,6 +16606,72 @@ } } }, + "EditableImage": { + "Name": "EditableImage", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "ImageData": { + "Name": "ImageData", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, + "EditableMesh": { + "Name": "EditableMesh", + "Tags": [ + "NotReplicated" + ], + "Superclass": "DataModelMesh", + "Properties": { + "MeshData": { + "Name": "MeshData", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "EmotesPages": { "Name": "EmotesPages", "Tags": [ @@ -16593,6 +16682,17 @@ "Properties": {}, "DefaultProperties": {} }, + "EngineAPICloudProcessingService": { + "Name": "EngineAPICloudProcessingService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "EqualizerSoundEffect": { "Name": "EqualizerSoundEffect", "Tags": [], @@ -16831,6 +16931,35 @@ "Properties": {}, "DefaultProperties": {} }, + "ExperienceStateCaptureService": { + "Name": "ExperienceStateCaptureService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "IsInCaptureMode": { + "Name": "IsInCaptureMode", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "Explosion": { "Name": "Explosion", "Tags": [], @@ -18828,7 +18957,7 @@ "Tags": [] }, "ValuesAndTimes": { - "BinaryString": "AQAAAAAAAAAAAAAAAAAWRQAAAAA=" + "BinaryString": "AQAAAAAAAAABAAAAAAAAAA==" } } }, @@ -21393,7 +21522,6 @@ "Value": "Rect" }, "Tags": [ - "Hidden", "NotReplicated", "ReadOnly" ], @@ -22151,6 +22279,19 @@ } } }, + "SoftlockServoUponReachingTarget": { + "Name": "SoftlockServoUponReachingTarget", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TargetAngle": { "Name": "TargetAngle", "Scriptability": "ReadWrite", @@ -22213,7 +22354,7 @@ "Float32": -45.0 }, "MotorMaxAcceleration": { - "Float32": null + "Float32": 500000.0 }, "MotorMaxTorque": { "Float32": 0.0 @@ -22227,6 +22368,9 @@ "ServoMaxTorque": { "Float32": 0.0 }, + "SoftlockServoUponReachingTarget": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -26172,6 +26316,9 @@ "EnableFluidForces": { "Bool": true }, + "FluidFidelityInternal": { + "Enum": 0 + }, "FormFactor": { "Enum": 3 }, @@ -26632,23 +26779,7 @@ ], "Superclass": "Instance", "Properties": {}, - "DefaultProperties": { - "Attributes": { - "Attributes": {} - }, - "Capabilities": { - "SecurityCapabilities": 0 - }, - "DefinesCapabilities": { - "Bool": false - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "Tags": [] - } - } + "DefaultProperties": {} }, "LayerCollector": { "Name": "LayerCollector", @@ -28605,7 +28736,7 @@ "Tags": [] }, "ValuesAndTimes": { - "BinaryString": "AAAAAAEAAAAKAAAAAAAAFkUAAAAA" + "BinaryString": "AQAAAAAAAAABAAAAAAAAAA==" } } }, @@ -29738,6 +29869,16 @@ "Properties": {}, "DefaultProperties": {} }, + "MemoryStoreHashMapPages": { + "Name": "MemoryStoreHashMapPages", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Pages", + "Properties": {}, + "DefaultProperties": {} + }, "MemoryStoreQueue": { "Name": "MemoryStoreQueue", "Tags": [ @@ -30128,6 +30269,23 @@ } } }, + "EditableMeshString": { + "Name": "EditableMeshString", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "HasJointOffset": { "Name": "HasJointOffset", "Scriptability": "Read", @@ -30394,6 +30552,9 @@ "EnableFluidForces": { "Bool": true }, + "FluidFidelityInternal": { + "Enum": 0 + }, "FrontParamA": { "Float32": -0.5 }, @@ -31905,6 +32066,9 @@ "EnableFluidForces": { "Bool": true }, + "FluidFidelityInternal": { + "Enum": 0 + }, "FormFactor": { "Enum": 3 }, @@ -32626,8 +32790,8 @@ } } }, - "OperationTree": { - "Name": "OperationTree", + "OperationGraph": { + "Name": "OperationGraph", "Tags": [], "Superclass": "Instance", "Properties": {}, @@ -32792,6 +32956,19 @@ } } }, + "DefaultName": { + "Name": "DefaultName", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ModifiedState": { "Name": "ModifiedState", "Scriptability": "None", @@ -32892,6 +33069,19 @@ } } }, + "SerializedDefaultAttributes": { + "Name": "SerializedDefaultAttributes", + "Scriptability": "Read", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Status": { "Name": "Status", "Scriptability": "None", @@ -33779,6 +33969,9 @@ "EnableFluidForces": { "Bool": true }, + "FluidFidelityInternal": { + "Enum": 0 + }, "FormFactor": { "Enum": 3 }, @@ -34727,6 +34920,112 @@ }, "DefaultProperties": {} }, + "Path2D": { + "Name": "Path2D", + "Tags": [ + "NotReplicated" + ], + "Superclass": "GuiBase", + "Properties": { + "AbsoluteSize": { + "Name": "AbsoluteSize", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Color": { + "Name": "Color", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Position": { + "Name": "Position", + "Scriptability": "None", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SelectedControlPoint": { + "Name": "SelectedControlPoint", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Thickness": { + "Name": "Thickness", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Transparency": { + "Name": "Transparency", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Visible": { + "Name": "Visible", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": {} + }, "PathfindingLink": { "Name": "PathfindingLink", "Tags": [], @@ -35227,6 +35526,19 @@ } } }, + "AreGravityForcesShownForSelectedOrHoveredAssemblies": { + "Name": "AreGravityForcesShownForSelectedOrHoveredAssemblies", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "AreJointCoordinatesShown": { "Name": "AreJointCoordinatesShown", "Scriptability": "ReadWrite", @@ -35529,8 +35841,8 @@ } } }, - "ShowFluidForcesForSelectedOrHoveredAssemblies": { - "Name": "ShowFluidForcesForSelectedOrHoveredAssemblies", + "ShowFluidForcesForSelectedOrHoveredMechanisms": { + "Name": "ShowFluidForcesForSelectedOrHoveredMechanisms", "Scriptability": "None", "DataType": { "Value": "Bool" @@ -35740,6 +36052,17 @@ "Properties": {}, "DefaultProperties": {} }, + "PlatformCloudStorageService": { + "Name": "PlatformCloudStorageService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "PlatformFriendsService": { "Name": "PlatformFriendsService", "Tags": [ @@ -37962,6 +38285,9 @@ "Size": { "Float32": 0.15 }, + "SoftlockServoUponReachingTarget": { + "Bool": false + }, "SourceAssetId": { "Int64": -1 }, @@ -39205,7 +39531,7 @@ "RemoteEvent": { "Name": "RemoteEvent", "Tags": [], - "Superclass": "Instance", + "Superclass": "BaseRemoteEvent", "Properties": {}, "DefaultProperties": { "Attributes": { @@ -39918,6 +40244,56 @@ } } }, + "RobloxEditableImage": { + "Name": "RobloxEditableImage", + "Tags": [], + "Superclass": "EditableImage", + "Properties": { + "ImageDataSerialize": { + "Name": "ImageDataSerialize", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, + "ImageDataSerialize": { + "BinaryString": "" + }, + "Size": { + "Vector2": [ + 512.0, + 512.0 + ] + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, "RobloxPluginGuiService": { "Name": "RobloxPluginGuiService", "Tags": [ @@ -41107,7 +41483,7 @@ "Tags": [] }, "ValuesAndTimes": { - "BinaryString": "AQAAAAAAAAAAAAAAAAAWRQAAAAA=" + "BinaryString": "AQAAAAAAAAABAAAAAAAAAA==" } } }, @@ -41209,9 +41585,7 @@ "DataType": { "Value": "Bool" }, - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -41270,9 +41644,7 @@ "DataType": { "Enum": "SafeAreaCompatibility" }, - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -41425,6 +41797,32 @@ } } }, + "HideCoreGuiForCaptures": { + "Name": "HideCoreGuiForCaptures", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HidePlayerGuiForCaptures": { + "Name": "HidePlayerGuiForCaptures", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "OverlayFont": { "Name": "OverlayFont", "Scriptability": "ReadWrite", @@ -44101,6 +44499,19 @@ } } }, + "SoftlockServoUponReachingTarget": { + "Name": "SoftlockServoUponReachingTarget", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Speed": { "Name": "Speed", "Scriptability": "ReadWrite", @@ -44932,6 +45343,7 @@ "Value": "Float32" }, "Tags": [ + "Deprecated", "Hidden", "NotReplicated", "NotScriptable" @@ -44949,6 +45361,7 @@ "Value": "Float32" }, "Tags": [ + "Deprecated", "Hidden", "NotReplicated", "NotScriptable" @@ -47135,6 +47548,21 @@ } } }, + "LuaCharacterController": { + "Name": "LuaCharacterController", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "CharacterControlMode" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "NameDisplayDistance": { "Name": "NameDisplayDistance", "Scriptability": "ReadWrite", @@ -47310,6 +47738,9 @@ "LoadCharacterLayeredClothing": { "Enum": 0 }, + "LuaCharacterController": { + "Enum": 0 + }, "NameDisplayDistance": { "Float32": 100.0 }, @@ -47349,6 +47780,17 @@ } } }, + "StartupMessageService": { + "Name": "StartupMessageService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Stats": { "Name": "Stats", "Tags": [ @@ -49899,7 +50341,21 @@ "Service" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "PublishLocked": { + "Name": "PublishLocked", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": {} }, "StudioScriptDebugEventListener": { @@ -52937,6 +53393,38 @@ } } }, + "LocalizationMatchIdentifier": { + "Name": "LocalizationMatchIdentifier", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LocalizationMatchedSourceText": { + "Name": "LocalizationMatchedSourceText", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ManualFocusRelease": { "Name": "ManualFocusRelease", "Scriptability": "None", @@ -53401,6 +53889,12 @@ "LineHeight": { "Float32": 1.0 }, + "LocalizationMatchIdentifier": { + "String": "" + }, + "LocalizationMatchedSourceText": { + "String": "" + }, "MaxVisibleGraphemes": { "Int32": -1 }, @@ -53646,6 +54140,38 @@ } } }, + "LocalizationMatchIdentifier": { + "Name": "LocalizationMatchIdentifier", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LocalizationMatchedSourceText": { + "Name": "LocalizationMatchedSourceText", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "LocalizedText": { "Name": "LocalizedText", "Scriptability": "Read", @@ -53985,6 +54511,12 @@ "LineHeight": { "Float32": 1.0 }, + "LocalizationMatchIdentifier": { + "String": "" + }, + "LocalizationMatchedSourceText": { + "String": "" + }, "MaxVisibleGraphemes": { "Int32": -1 }, @@ -54434,7 +54966,25 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ChatTranslationFTUXShown": { + "Name": "ChatTranslationFTUXShown", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -54447,7 +54997,10 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotReplicated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -54501,7 +55054,7 @@ "Capabilities": { "SecurityCapabilities": 0 }, - "ChatTranslationEnabled": { + "ChatTranslationFTUXShown": { "Bool": true }, "ChatTranslationToggleEnabled": { @@ -54681,6 +55234,38 @@ } } }, + "LocalizationMatchIdentifier": { + "Name": "LocalizationMatchIdentifier", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LocalizationMatchedSourceText": { + "Name": "LocalizationMatchedSourceText", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "LocalizedText": { "Name": "LocalizedText", "Scriptability": "Read", @@ -55017,6 +55602,12 @@ "LineHeight": { "Float32": 1.0 }, + "LocalizationMatchIdentifier": { + "String": "" + }, + "LocalizationMatchedSourceText": { + "String": "" + }, "MaxVisibleGraphemes": { "Int32": -1 }, @@ -55305,6 +55896,17 @@ } } }, + "TextureGenerationMeshHandler": { + "Name": "TextureGenerationMeshHandler", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ThirdPartyUserService": { "Name": "ThirdPartyUserService", "Tags": [ @@ -56568,6 +57170,37 @@ } } }, + "FluidFidelity": { + "Name": "FluidFidelity", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "FluidFidelity" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FluidFidelityInternal": { + "Name": "FluidFidelityInternal", + "Scriptability": "None", + "DataType": { + "Enum": "FluidFidelity" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MeshSize": { "Name": "MeshSize", "Scriptability": "Read", @@ -57144,6 +57777,96 @@ } } }, + "UIFlexItem": { + "Name": "UIFlexItem", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "UIComponent", + "Properties": { + "FlexMode": { + "Name": "FlexMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "UIFlexMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GrowRatio": { + "Name": "GrowRatio", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ItemLineAlignment": { + "Name": "ItemLineAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ItemLineAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShrinkRatio": { + "Name": "ShrinkRatio", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, + "FlexMode": { + "Enum": 0 + }, + "GrowRatio": { + "Float32": 0.0 + }, + "ItemLineAlignment": { + "Enum": 0 + }, + "ShrinkRatio": { + "Float32": 0.0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, "UIGradient": { "Name": "UIGradient", "Tags": [], @@ -57526,6 +58249,48 @@ "Tags": [], "Superclass": "UIGridStyleLayout", "Properties": { + "HorizontalFlex": { + "Name": "HorizontalFlex", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "UIFlexAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "HorizontalPadding": { + "Name": "HorizontalPadding", + "Scriptability": "None", + "DataType": { + "Value": "UDim" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ItemLineAlignment": { + "Name": "ItemLineAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ItemLineAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Padding": { "Name": "Padding", "Scriptability": "ReadWrite", @@ -57538,6 +58303,48 @@ "Serialization": "Serializes" } } + }, + "VerticalFlex": { + "Name": "VerticalFlex", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "UIFlexAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VerticalPadding": { + "Name": "VerticalPadding", + "Scriptability": "None", + "DataType": { + "Value": "UDim" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Wraps": { + "Name": "Wraps", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -57556,6 +58363,12 @@ "HorizontalAlignment": { "Enum": 1 }, + "HorizontalFlex": { + "Enum": 0 + }, + "ItemLineAlignment": { + "Enum": 0 + }, "Padding": { "UDim": [ 0.0, @@ -57573,6 +58386,12 @@ }, "VerticalAlignment": { "Enum": 1 + }, + "VerticalFlex": { + "Enum": 0 + }, + "Wraps": { + "Bool": false } } }, @@ -58371,6 +59190,9 @@ "EnableFluidForces": { "Bool": true }, + "FluidFidelityInternal": { + "Enum": 0 + }, "FormFactor": { "Enum": 3 }, @@ -58617,6 +59439,29 @@ } } }, + "UnreliableRemoteEvent": { + "Name": "UnreliableRemoteEvent", + "Tags": [], + "Superclass": "BaseRemoteEvent", + "Properties": {}, + "DefaultProperties": { + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "DefinesCapabilities": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + } + } + }, "UnvalidatedAssetService": { "Name": "UnvalidatedAssetService", "Tags": [ @@ -58713,6 +59558,54 @@ } } }, + "ChatTranslationEnabled": { + "Name": "ChatTranslationEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ChatTranslationFTUXShown": { + "Name": "ChatTranslationFTUXShown", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ChatTranslationToggleEnabled": { + "Name": "ChatTranslationToggleEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ChatVisible": { "Name": "ChatVisible", "Scriptability": "None", @@ -62034,6 +62927,21 @@ } } }, + "UseAudioApi": { + "Name": "UseAudioApi", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AudioApiRollout" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "UseNewAudioApi": { "Name": "UseNewAudioApi", "Scriptability": "None", @@ -62128,6 +63036,9 @@ }, "Tags": { "Tags": [] + }, + "UseAudioApi": { + "Enum": 1 } } }, @@ -63152,6 +64063,36 @@ } } }, + "PlayerCharacterDestroyBehavior": { + "Name": "PlayerCharacterDestroyBehavior", + "Scriptability": "None", + "DataType": { + "Enum": "PlayerCharacterDestroyBehavior" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PrimalPhysicsSolver": { + "Name": "PrimalPhysicsSolver", + "Scriptability": "None", + "DataType": { + "Enum": "PrimalPhysicsSolver" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "RejectCharacterDeletions": { "Name": "RejectCharacterDeletions", "Scriptability": "None", @@ -63474,6 +64415,12 @@ "PhysicsSteppingMethod": { "Enum": 0 }, + "PlayerCharacterDestroyBehavior": { + "Enum": 0 + }, + "PrimalPhysicsSolver": { + "Enum": 0 + }, "RejectCharacterDeletions": { "Enum": 0 }, @@ -64166,6 +65113,14 @@ "Servo": 2 } }, + "AdEventType": { + "name": "AdEventType", + "items": { + "UserCompletedVideo": 2, + "VideoLoaded": 0, + "VideoRemoved": 1 + } + }, "AdShape": { "name": "AdShape", "items": { @@ -64198,8 +65153,12 @@ "AlignType": { "name": "AlignType", "items": { + "AllAxes": 5, "Parallel": 0, - "Perpendicular": 1 + "Perpendicular": 1, + "PrimaryAxisLookAt": 4, + "PrimaryAxisParallel": 2, + "PrimaryAxisPerpendicular": 3 } }, "AlphaMode": { @@ -64424,6 +65383,14 @@ "Default": 1 } }, + "AudioApiRollout": { + "name": "AudioApiRollout", + "items": { + "Automatic": 1, + "Disabled": 0, + "Enabled": 2 + } + }, "AudioSubType": { "name": "AudioSubType", "items": { @@ -64800,6 +65767,15 @@ "UnsolicitedDialog": 1 } }, + "CharacterControlMode": { + "name": "CharacterControlMode", + "items": { + "Default": 0, + "Legacy": 1, + "LuaCharacterController": 3, + "NoCharacterController": 2 + } + }, "ChatCallbackType": { "name": "ChatCallbackType", "items": { @@ -65023,6 +65999,7 @@ "PlacelaunchUserLeft": 522, "PlacelaunchUserPrivacyUnauthorized": 533, "PlayerRemoved": 291, + "ReplacementReady": 301, "ReplicatorTimeout": 290, "ServerShutdown": 288, "TeleportErrors": 768, @@ -65070,6 +66047,7 @@ "items": { "All": 4, "Backpack": 2, + "Captures": 7, "Chat": 3, "EmotesMenu": 5, "Health": 1, @@ -65417,6 +66395,14 @@ "NoCraters": 0 } }, + "FACSDataLod": { + "name": "FACSDataLod", + "items": { + "LOD0": 0, + "LOD1": 1, + "LODCount": 2 + } + }, "FacialAnimationStreamingState": { "name": "FacialAnimationStreamingState", "items": { @@ -65457,6 +66443,14 @@ "Commit": 1 } }, + "FluidFidelity": { + "name": "FluidFidelity", + "items": { + "Automatic": 0, + "UseCollisionGeometry": 1, + "UsePreciseGeometry": 2 + } + }, "FluidForces": { "name": "FluidForces", "items": { @@ -65739,6 +66733,13 @@ "None": 0 } }, + "HttpCompression": { + "name": "HttpCompression", + "items": { + "Gzip": 1, + "None": 0 + } + }, "HttpContentType": { "name": "HttpContentType", "items": { @@ -65928,6 +66929,25 @@ "Enabled": 2 } }, + "InviteState": { + "name": "InviteState", + "items": { + "Accepted": 1, + "Declined": 2, + "Missed": 3, + "Placed": 0 + } + }, + "ItemLineAlignment": { + "name": "ItemLineAlignment", + "items": { + "Automatic": 0, + "Center": 2, + "End": 3, + "Start": 1, + "Stretch": 4 + } + }, "JointCreationMode": { "name": "JointCreationMode", "items": { @@ -66499,6 +67519,14 @@ "OnContact": 2 } }, + "NetworkStatus": { + "name": "NetworkStatus", + "items": { + "Connected": 1, + "Disconnected": 2, + "Unknown": 0 + } + }, "NormalId": { "name": "NormalId", "items": { @@ -66699,6 +67727,7 @@ "Ouya": 10, "PS3": 6, "PS4": 5, + "PS5": 19, "SteamOS": 14, "UWP": 18, "WebOS": 15, @@ -66729,6 +67758,14 @@ "CharacterRight": 3 } }, + "PlayerCharacterDestroyBehavior": { + "name": "PlayerCharacterDestroyBehavior", + "items": { + "Default": 0, + "Disabled": 1, + "Enabled": 2 + } + }, "PlayerChatType": { "name": "PlayerChatType", "items": { @@ -66762,6 +67799,14 @@ "TwoAttachment": 1 } }, + "PrimalPhysicsSolver": { + "name": "PrimalPhysicsSolver", + "items": { + "Default": 0, + "Disabled": 2, + "Experimental": 1 + } + }, "PrimitiveType": { "name": "PrimitiveType", "items": { @@ -66809,6 +67854,21 @@ "UploadFailed": 4 } }, + "PromptCreateAvatarResult": { + "name": "PromptCreateAvatarResult", + "items": { + "InvalidHumanoidDescription": 6, + "MaxOutfits": 9, + "ModeratedName": 8, + "NoUserInput": 5, + "PermissionDenied": 2, + "Success": 1, + "Timeout": 3, + "UGCValidationFailed": 7, + "UnknownFailure": 10, + "UploadFailed": 4 + } + }, "PromptPublishAssetResult": { "name": "PromptPublishAssetResult", "items": { @@ -67378,6 +68438,13 @@ "Standalone": 3 } }, + "StudioPlaceUpdateFailureReason": { + "name": "StudioPlaceUpdateFailureReason", + "items": { + "Other": 0, + "TeamCreateConflict": 1 + } + }, "StudioScriptEditorColorCategories": { "name": "StudioScriptEditorColorCategories", "items": { @@ -67799,6 +68866,14 @@ "Top": 0 } }, + "TextureGenerationMeshHandlerUnwrapMode": { + "name": "TextureGenerationMeshHandlerUnwrapMode", + "items": { + "Always": 1, + "Never": 0, + "WhenInvalidUVsDetected": 2 + } + }, "TextureMode": { "name": "TextureMode", "items": { @@ -67979,6 +69054,26 @@ "Completed": 1 } }, + "UIFlexAlignment": { + "name": "UIFlexAlignment", + "items": { + "Fill": 1, + "None": 0, + "SpaceAround": 2, + "SpaceBetween": 3, + "SpaceEvenly": 4 + } + }, + "UIFlexMode": { + "name": "UIFlexMode", + "items": { + "Custom": 4, + "Fill": 3, + "Grow": 1, + "None": 0, + "Shrink": 2 + } + }, "UITheme": { "name": "UITheme", "items": { diff --git a/src/cli/build.rs b/src/cli/build.rs index 0593cc05..2dd3b854 100644 --- a/src/cli/build.rs +++ b/src/cli/build.rs @@ -146,7 +146,7 @@ impl OutputKind { } } -fn xml_encode_config() -> rbx_xml::EncodeOptions { +fn xml_encode_config() -> rbx_xml::EncodeOptions<'static> { rbx_xml::EncodeOptions::new().property_behavior(rbx_xml::EncodePropertyBehavior::WriteUnknown) } From 73828af7153a2afbcf13adfc510606c6a86fe92c Mon Sep 17 00:00:00 2001 From: Micah Date: Fri, 19 Jan 2024 22:18:17 -0800 Subject: [PATCH 1368/1504] Add a new `syncRules` field project files to allow users to specify middleware to use for files (#813) --- CHANGELOG.md | 49 +++ ...to_end__tests__build__sync_rule_alone.snap | 18 + ..._end__tests__build__sync_rule_complex.snap | 43 +++ ...sts__build__sync_rule_nested_projects.snap | 12 + .../sync_rule_alone/default.project.json | 12 + .../sync_rule_alone/src/foo.nothing | 1 + .../sync_rule_complex/default.project.json | 30 ++ .../sync_rule_complex/src/bar.server | 1 + .../sync_rule_complex/src/baz.client | 1 + .../sync_rule_complex/src/cat.dog.rojo2 | 1 + .../sync_rule_complex/src/foo.module | 1 + .../sync_rule_complex/src/qux.rojo | 9 + .../sync_rule_complex/src/rat.ignore.rojo | 1 + .../default.project.json | 12 + .../nested.project.json | 12 + .../src/ignored.rojo | 1 + .../sync_rule_nested_projects/src/ignored.txt | 1 + ...nd__tests__serve__sync_rule_alone_all.snap | 30 ++ ...d__tests__serve__sync_rule_alone_info.snap | 14 + ...__tests__serve__sync_rule_complex_all.snap | 80 +++++ ..._tests__serve__sync_rule_complex_info.snap | 14 + ...ts__serve__sync_rule_no_extension_all.snap | 30 ++ ...s__serve__sync_rule_no_extension_info.snap | 14 + .../sync_rule_alone/default.project.json | 12 + .../sync_rule_alone/src/foo.nothing | 1 + .../sync_rule_complex/default.project.json | 30 ++ .../sync_rule_complex/src/bar.server | 1 + .../sync_rule_complex/src/baz.client | 1 + .../sync_rule_complex/src/cat.dog.rojo2 | 1 + .../sync_rule_complex/src/foo.module | 1 + .../sync_rule_complex/src/qux.rojo | 9 + .../sync_rule_complex/src/rat.ignore.rojo | 1 + .../default.project.json | 12 + .../sync_rule_no_extension/src/no_extension | 1 + src/project.rs | 8 +- src/snapshot/metadata.rs | 90 ++++- src/snapshot_middleware/csv.rs | 31 +- src/snapshot_middleware/json.rs | 5 +- src/snapshot_middleware/json_model.rs | 7 +- src/snapshot_middleware/lua.rs | 59 ++-- src/snapshot_middleware/mod.rs | 316 +++++++++++++----- src/snapshot_middleware/project.rs | 8 + src/snapshot_middleware/rbxm.rs | 6 +- src/snapshot_middleware/rbxmx.rs | 6 +- src/snapshot_middleware/toml.rs | 5 +- src/snapshot_middleware/txt.rs | 17 +- tests/tests/build.rs | 3 + tests/tests/serve.rs | 51 +++ 48 files changed, 923 insertions(+), 146 deletions(-) create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__sync_rule_alone.snap create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__sync_rule_complex.snap create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__sync_rule_nested_projects.snap create mode 100644 rojo-test/build-tests/sync_rule_alone/default.project.json create mode 100644 rojo-test/build-tests/sync_rule_alone/src/foo.nothing create mode 100644 rojo-test/build-tests/sync_rule_complex/default.project.json create mode 100644 rojo-test/build-tests/sync_rule_complex/src/bar.server create mode 100644 rojo-test/build-tests/sync_rule_complex/src/baz.client create mode 100644 rojo-test/build-tests/sync_rule_complex/src/cat.dog.rojo2 create mode 100644 rojo-test/build-tests/sync_rule_complex/src/foo.module create mode 100644 rojo-test/build-tests/sync_rule_complex/src/qux.rojo create mode 100644 rojo-test/build-tests/sync_rule_complex/src/rat.ignore.rojo create mode 100644 rojo-test/build-tests/sync_rule_nested_projects/default.project.json create mode 100644 rojo-test/build-tests/sync_rule_nested_projects/nested.project.json create mode 100644 rojo-test/build-tests/sync_rule_nested_projects/src/ignored.rojo create mode 100644 rojo-test/build-tests/sync_rule_nested_projects/src/ignored.txt create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_alone_all.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_alone_info.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_complex_all.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_complex_info.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_no_extension_all.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_no_extension_info.snap create mode 100644 rojo-test/serve-tests/sync_rule_alone/default.project.json create mode 100644 rojo-test/serve-tests/sync_rule_alone/src/foo.nothing create mode 100644 rojo-test/serve-tests/sync_rule_complex/default.project.json create mode 100644 rojo-test/serve-tests/sync_rule_complex/src/bar.server create mode 100644 rojo-test/serve-tests/sync_rule_complex/src/baz.client create mode 100644 rojo-test/serve-tests/sync_rule_complex/src/cat.dog.rojo2 create mode 100644 rojo-test/serve-tests/sync_rule_complex/src/foo.module create mode 100644 rojo-test/serve-tests/sync_rule_complex/src/qux.rojo create mode 100644 rojo-test/serve-tests/sync_rule_complex/src/rat.ignore.rojo create mode 100644 rojo-test/serve-tests/sync_rule_no_extension/default.project.json create mode 100644 rojo-test/serve-tests/sync_rule_no_extension/src/no_extension diff --git a/CHANGELOG.md b/CHANGELOG.md index 7542adc7..7552a0ed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,55 @@ ## Unreleased Changes +* Projects may now specify rules for syncing files as if they had a different file extension. ([#813]) + This is specified via a new field on project files, `syncRules`: + + ```json + { + "syncRules": [ + { + "pattern": "*.foo", + "use": "text", + "exclude": "*.exclude.foo", + }, + { + "pattern": "*.bar.baz", + "use": "json", + "suffix": ".bar.baz", + }, + ], + "name": "SyncRulesAreCool", + "tree": { + "$path": "src" + } + } + ``` + + The `pattern` field is a glob used to match the sync rule to files. If present, the `suffix` field allows you to specify parts of a file's name get cut off by Rojo to name the Instance, including the file extension. If it isn't specified, Rojo will only cut off the first part of the file extension, up to the first dot. + + Additionally, the `exclude` field allows files to be excluded from the sync rule if they match a pattern specified by it. If it's not present, all files that match `pattern` will be modified using the sync rule. + + The `use` field corresponds to one of the potential file type that Rojo will currently include in a project. Files that match the provided pattern will be treated as if they had the file extension for that file type. A full list is below: + + | `use` value | file extension | + |:---------------|:----------------| + | `serverScript` | `.server.lua` | + | `clientScript` | `.client.lua` | + | `moduleScript` | `.lua` | + | `json` | `.json` | + | `toml` | `.toml` | + | `csv` | `.csv` | + | `text` | `.txt` | + | `jsonModel` | `.model.json` | + | `rbxm` | `.rbxm` | + | `rbxmx` | `.rbxmx` | + | `project` | `.project.json` | + | `ignore` | None! | + + **All** sync rules are reset between project files, so they must be specified in each one when nesting them. This is to ensure that nothing can break other projects by changing how files are synced! + +[#813]: https://github.com/rojo-rbx/rojo/pull/813 + ## [7.4.0] - January 16, 2024 * Improved the visualization for array properties like Tags ([#829]) * Significantly improved performance of `rojo serve`, `rojo build --watch`, and `rojo sourcemap --watch` on macOS. ([#830]) diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__sync_rule_alone.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__sync_rule_alone.snap new file mode 100644 index 00000000..53e329cc --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__sync_rule_alone.snap @@ -0,0 +1,18 @@ +--- +source: tests/tests/build.rs +assertion_line: 102 +expression: contents +--- + + + + sync_rule_alone + + + + foo + Hello, world! + + + + diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__sync_rule_complex.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__sync_rule_complex.snap new file mode 100644 index 00000000..e38050d8 --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__sync_rule_complex.snap @@ -0,0 +1,43 @@ +--- +source: tests/tests/build.rs +assertion_line: 104 +expression: contents +--- + + + + sync_rule_complex + + + + bar + 0 + -- Hello, from bar (a Script)! + + + + + baz + -- Hello, from baz (a LocalScript)! + + + + + cat + Hello, from cat (a StringValue)! + + + + + foo + -- Hello, from foo (a ModuleScript)! + + + + + qux + Hello, from qux (a .rojo file that's turned into a StringValue)! + + + + diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__sync_rule_nested_projects.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__sync_rule_nested_projects.snap new file mode 100644 index 00000000..6867ac37 --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__sync_rule_nested_projects.snap @@ -0,0 +1,12 @@ +--- +source: tests/tests/build.rs +assertion_line: 104 +expression: contents +--- + + + + sync_rule_nested_projects + + + diff --git a/rojo-test/build-tests/sync_rule_alone/default.project.json b/rojo-test/build-tests/sync_rule_alone/default.project.json new file mode 100644 index 00000000..f3a5aa34 --- /dev/null +++ b/rojo-test/build-tests/sync_rule_alone/default.project.json @@ -0,0 +1,12 @@ +{ + "name": "sync_rule_alone", + "tree": { + "$path": "src" + }, + "syncRules": [ + { + "pattern": "*.nothing", + "use": "text" + } + ] +} \ No newline at end of file diff --git a/rojo-test/build-tests/sync_rule_alone/src/foo.nothing b/rojo-test/build-tests/sync_rule_alone/src/foo.nothing new file mode 100644 index 00000000..5dd01c17 --- /dev/null +++ b/rojo-test/build-tests/sync_rule_alone/src/foo.nothing @@ -0,0 +1 @@ +Hello, world! \ No newline at end of file diff --git a/rojo-test/build-tests/sync_rule_complex/default.project.json b/rojo-test/build-tests/sync_rule_complex/default.project.json new file mode 100644 index 00000000..62764bb4 --- /dev/null +++ b/rojo-test/build-tests/sync_rule_complex/default.project.json @@ -0,0 +1,30 @@ +{ + "name": "sync_rule_complex", + "tree": { + "$path": "src" + }, + "syncRules": [ + { + "pattern": "*.module", + "use": "moduleScript" + }, + { + "pattern": "*.server", + "use": "serverScript" + }, + { + "pattern": "*.client", + "use": "clientScript" + }, + { + "pattern": "*.rojo", + "exclude": "*.ignore.rojo", + "use": "project" + }, + { + "pattern": "*.dog.rojo2", + "use": "text", + "suffix": ".dog.rojo2" + } + ] +} \ No newline at end of file diff --git a/rojo-test/build-tests/sync_rule_complex/src/bar.server b/rojo-test/build-tests/sync_rule_complex/src/bar.server new file mode 100644 index 00000000..e860bd77 --- /dev/null +++ b/rojo-test/build-tests/sync_rule_complex/src/bar.server @@ -0,0 +1 @@ +-- Hello, from bar (a Script)! \ No newline at end of file diff --git a/rojo-test/build-tests/sync_rule_complex/src/baz.client b/rojo-test/build-tests/sync_rule_complex/src/baz.client new file mode 100644 index 00000000..4326a2a4 --- /dev/null +++ b/rojo-test/build-tests/sync_rule_complex/src/baz.client @@ -0,0 +1 @@ +-- Hello, from baz (a LocalScript)! \ No newline at end of file diff --git a/rojo-test/build-tests/sync_rule_complex/src/cat.dog.rojo2 b/rojo-test/build-tests/sync_rule_complex/src/cat.dog.rojo2 new file mode 100644 index 00000000..e185da86 --- /dev/null +++ b/rojo-test/build-tests/sync_rule_complex/src/cat.dog.rojo2 @@ -0,0 +1 @@ +Hello, from cat (a StringValue)! \ No newline at end of file diff --git a/rojo-test/build-tests/sync_rule_complex/src/foo.module b/rojo-test/build-tests/sync_rule_complex/src/foo.module new file mode 100644 index 00000000..3a55f9b2 --- /dev/null +++ b/rojo-test/build-tests/sync_rule_complex/src/foo.module @@ -0,0 +1 @@ +-- Hello, from foo (a ModuleScript)! \ No newline at end of file diff --git a/rojo-test/build-tests/sync_rule_complex/src/qux.rojo b/rojo-test/build-tests/sync_rule_complex/src/qux.rojo new file mode 100644 index 00000000..7153477d --- /dev/null +++ b/rojo-test/build-tests/sync_rule_complex/src/qux.rojo @@ -0,0 +1,9 @@ +{ + "name": "qux", + "tree": { + "$className": "StringValue", + "$properties": { + "Value": "Hello, from qux (a .rojo file that's turned into a StringValue)!" + } + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/sync_rule_complex/src/rat.ignore.rojo b/rojo-test/build-tests/sync_rule_complex/src/rat.ignore.rojo new file mode 100644 index 00000000..d80a8cc8 --- /dev/null +++ b/rojo-test/build-tests/sync_rule_complex/src/rat.ignore.rojo @@ -0,0 +1 @@ +This file should be ignored! \ No newline at end of file diff --git a/rojo-test/build-tests/sync_rule_nested_projects/default.project.json b/rojo-test/build-tests/sync_rule_nested_projects/default.project.json new file mode 100644 index 00000000..1b6193bb --- /dev/null +++ b/rojo-test/build-tests/sync_rule_nested_projects/default.project.json @@ -0,0 +1,12 @@ +{ + "name": "sync_rule_nested_projects", + "tree": { + "$path": "nested.project.json" + }, + "syncRules": [ + { + "pattern": "*.rojo", + "use": "text" + } + ] +} \ No newline at end of file diff --git a/rojo-test/build-tests/sync_rule_nested_projects/nested.project.json b/rojo-test/build-tests/sync_rule_nested_projects/nested.project.json new file mode 100644 index 00000000..3c5fea2c --- /dev/null +++ b/rojo-test/build-tests/sync_rule_nested_projects/nested.project.json @@ -0,0 +1,12 @@ +{ + "name": "nested", + "tree": { + "$path": "src" + }, + "syncRules": [ + { + "pattern": "*.txt", + "use": "ignore" + } + ] +} \ No newline at end of file diff --git a/rojo-test/build-tests/sync_rule_nested_projects/src/ignored.rojo b/rojo-test/build-tests/sync_rule_nested_projects/src/ignored.rojo new file mode 100644 index 00000000..d7ed8b4f --- /dev/null +++ b/rojo-test/build-tests/sync_rule_nested_projects/src/ignored.rojo @@ -0,0 +1 @@ +This shouldn't be in the built file. If it is, something is wrong. \ No newline at end of file diff --git a/rojo-test/build-tests/sync_rule_nested_projects/src/ignored.txt b/rojo-test/build-tests/sync_rule_nested_projects/src/ignored.txt new file mode 100644 index 00000000..d7ed8b4f --- /dev/null +++ b/rojo-test/build-tests/sync_rule_nested_projects/src/ignored.txt @@ -0,0 +1 @@ +This shouldn't be in the built file. If it is, something is wrong. \ No newline at end of file diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_alone_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_alone_all.snap new file mode 100644 index 00000000..e4fa4adf --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_alone_all.snap @@ -0,0 +1,30 @@ +--- +source: tests/tests/serve.rs +assertion_line: 268 +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Children: + - id-3 + ClassName: Folder + Id: id-2 + Metadata: + ignoreUnknownInstances: false + Name: sync_rule_alone + Parent: "00000000000000000000000000000000" + Properties: {} + id-3: + Children: [] + ClassName: StringValue + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: foo + Parent: id-2 + Properties: + Value: + String: "Hello, world!" +messageCursor: 0 +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_alone_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_alone_info.snap new file mode 100644 index 00000000..514b8858 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_alone_info.snap @@ -0,0 +1,14 @@ +--- +source: tests/tests/serve.rs +assertion_line: 265 +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +gameId: ~ +placeId: ~ +projectName: sync_rule_alone +protocolVersion: 4 +rootInstanceId: id-2 +serverVersion: "[server-version]" +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_complex_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_complex_all.snap new file mode 100644 index 00000000..80cd76f6 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_complex_all.snap @@ -0,0 +1,80 @@ +--- +source: tests/tests/serve.rs +assertion_line: 284 +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Children: + - id-3 + - id-4 + - id-5 + - id-6 + - id-7 + ClassName: Folder + Id: id-2 + Metadata: + ignoreUnknownInstances: false + Name: sync_rule_complex + Parent: "00000000000000000000000000000000" + Properties: {} + id-3: + Children: [] + ClassName: Script + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: bar + Parent: id-2 + Properties: + RunContext: + Enum: 0 + Source: + String: "-- Hello, from bar (a Script)!" + id-4: + Children: [] + ClassName: LocalScript + Id: id-4 + Metadata: + ignoreUnknownInstances: false + Name: baz + Parent: id-2 + Properties: + Source: + String: "-- Hello, from baz (a LocalScript)!" + id-5: + Children: [] + ClassName: StringValue + Id: id-5 + Metadata: + ignoreUnknownInstances: false + Name: cat + Parent: id-2 + Properties: + Value: + String: "Hello, from cat (a StringValue)!" + id-6: + Children: [] + ClassName: ModuleScript + Id: id-6 + Metadata: + ignoreUnknownInstances: false + Name: foo + Parent: id-2 + Properties: + Source: + String: "-- Hello, from foo (a ModuleScript)!" + id-7: + Children: [] + ClassName: StringValue + Id: id-7 + Metadata: + ignoreUnknownInstances: true + Name: qux + Parent: id-2 + Properties: + Value: + String: "Hello, from qux (a .rojo file that's turned into a StringValue)!" +messageCursor: 0 +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_complex_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_complex_info.snap new file mode 100644 index 00000000..3ed2b805 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_complex_info.snap @@ -0,0 +1,14 @@ +--- +source: tests/tests/serve.rs +assertion_line: 281 +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +gameId: ~ +placeId: ~ +projectName: sync_rule_complex +protocolVersion: 4 +rootInstanceId: id-2 +serverVersion: "[server-version]" +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_no_extension_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_no_extension_all.snap new file mode 100644 index 00000000..f3210d3c --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_no_extension_all.snap @@ -0,0 +1,30 @@ +--- +source: tests/tests/serve.rs +assertion_line: 303 +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Children: + - id-3 + ClassName: Folder + Id: id-2 + Metadata: + ignoreUnknownInstances: false + Name: sync_rule_no_extension + Parent: "00000000000000000000000000000000" + Properties: {} + id-3: + Children: [] + ClassName: ModuleScript + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: no_extension + Parent: id-2 + Properties: + Source: + String: "return {\"This file has no extension but should be a ModuleScript named `no_extension`\"}" +messageCursor: 0 +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_no_extension_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_no_extension_info.snap new file mode 100644 index 00000000..3503e595 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__sync_rule_no_extension_info.snap @@ -0,0 +1,14 @@ +--- +source: tests/tests/serve.rs +assertion_line: 297 +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +gameId: ~ +placeId: ~ +projectName: sync_rule_no_extension +protocolVersion: 4 +rootInstanceId: id-2 +serverVersion: "[server-version]" +sessionId: id-1 + diff --git a/rojo-test/serve-tests/sync_rule_alone/default.project.json b/rojo-test/serve-tests/sync_rule_alone/default.project.json new file mode 100644 index 00000000..f3a5aa34 --- /dev/null +++ b/rojo-test/serve-tests/sync_rule_alone/default.project.json @@ -0,0 +1,12 @@ +{ + "name": "sync_rule_alone", + "tree": { + "$path": "src" + }, + "syncRules": [ + { + "pattern": "*.nothing", + "use": "text" + } + ] +} \ No newline at end of file diff --git a/rojo-test/serve-tests/sync_rule_alone/src/foo.nothing b/rojo-test/serve-tests/sync_rule_alone/src/foo.nothing new file mode 100644 index 00000000..5dd01c17 --- /dev/null +++ b/rojo-test/serve-tests/sync_rule_alone/src/foo.nothing @@ -0,0 +1 @@ +Hello, world! \ No newline at end of file diff --git a/rojo-test/serve-tests/sync_rule_complex/default.project.json b/rojo-test/serve-tests/sync_rule_complex/default.project.json new file mode 100644 index 00000000..62764bb4 --- /dev/null +++ b/rojo-test/serve-tests/sync_rule_complex/default.project.json @@ -0,0 +1,30 @@ +{ + "name": "sync_rule_complex", + "tree": { + "$path": "src" + }, + "syncRules": [ + { + "pattern": "*.module", + "use": "moduleScript" + }, + { + "pattern": "*.server", + "use": "serverScript" + }, + { + "pattern": "*.client", + "use": "clientScript" + }, + { + "pattern": "*.rojo", + "exclude": "*.ignore.rojo", + "use": "project" + }, + { + "pattern": "*.dog.rojo2", + "use": "text", + "suffix": ".dog.rojo2" + } + ] +} \ No newline at end of file diff --git a/rojo-test/serve-tests/sync_rule_complex/src/bar.server b/rojo-test/serve-tests/sync_rule_complex/src/bar.server new file mode 100644 index 00000000..e860bd77 --- /dev/null +++ b/rojo-test/serve-tests/sync_rule_complex/src/bar.server @@ -0,0 +1 @@ +-- Hello, from bar (a Script)! \ No newline at end of file diff --git a/rojo-test/serve-tests/sync_rule_complex/src/baz.client b/rojo-test/serve-tests/sync_rule_complex/src/baz.client new file mode 100644 index 00000000..4326a2a4 --- /dev/null +++ b/rojo-test/serve-tests/sync_rule_complex/src/baz.client @@ -0,0 +1 @@ +-- Hello, from baz (a LocalScript)! \ No newline at end of file diff --git a/rojo-test/serve-tests/sync_rule_complex/src/cat.dog.rojo2 b/rojo-test/serve-tests/sync_rule_complex/src/cat.dog.rojo2 new file mode 100644 index 00000000..e185da86 --- /dev/null +++ b/rojo-test/serve-tests/sync_rule_complex/src/cat.dog.rojo2 @@ -0,0 +1 @@ +Hello, from cat (a StringValue)! \ No newline at end of file diff --git a/rojo-test/serve-tests/sync_rule_complex/src/foo.module b/rojo-test/serve-tests/sync_rule_complex/src/foo.module new file mode 100644 index 00000000..3a55f9b2 --- /dev/null +++ b/rojo-test/serve-tests/sync_rule_complex/src/foo.module @@ -0,0 +1 @@ +-- Hello, from foo (a ModuleScript)! \ No newline at end of file diff --git a/rojo-test/serve-tests/sync_rule_complex/src/qux.rojo b/rojo-test/serve-tests/sync_rule_complex/src/qux.rojo new file mode 100644 index 00000000..7153477d --- /dev/null +++ b/rojo-test/serve-tests/sync_rule_complex/src/qux.rojo @@ -0,0 +1,9 @@ +{ + "name": "qux", + "tree": { + "$className": "StringValue", + "$properties": { + "Value": "Hello, from qux (a .rojo file that's turned into a StringValue)!" + } + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/sync_rule_complex/src/rat.ignore.rojo b/rojo-test/serve-tests/sync_rule_complex/src/rat.ignore.rojo new file mode 100644 index 00000000..d80a8cc8 --- /dev/null +++ b/rojo-test/serve-tests/sync_rule_complex/src/rat.ignore.rojo @@ -0,0 +1 @@ +This file should be ignored! \ No newline at end of file diff --git a/rojo-test/serve-tests/sync_rule_no_extension/default.project.json b/rojo-test/serve-tests/sync_rule_no_extension/default.project.json new file mode 100644 index 00000000..185c6633 --- /dev/null +++ b/rojo-test/serve-tests/sync_rule_no_extension/default.project.json @@ -0,0 +1,12 @@ +{ + "name": "sync_rule_no_extension", + "tree": { + "$path": "src" + }, + "syncRules": [ + { + "pattern": "src/**", + "use": "json" + } + ] +} \ No newline at end of file diff --git a/rojo-test/serve-tests/sync_rule_no_extension/src/no_extension b/rojo-test/serve-tests/sync_rule_no_extension/src/no_extension new file mode 100644 index 00000000..41c705c4 --- /dev/null +++ b/rojo-test/serve-tests/sync_rule_no_extension/src/no_extension @@ -0,0 +1 @@ +["This file has no extension but should be a ModuleScript named `no_extension`"] \ No newline at end of file diff --git a/src/project.rs b/src/project.rs index 93a3cb21..1095fba2 100644 --- a/src/project.rs +++ b/src/project.rs @@ -8,7 +8,7 @@ use std::{ use serde::{Deserialize, Serialize}; use thiserror::Error; -use crate::{glob::Glob, resolution::UnresolvedValue}; +use crate::{glob::Glob, resolution::UnresolvedValue, snapshot::SyncRule}; static PROJECT_FILENAME: &str = "default.project.json"; @@ -84,6 +84,12 @@ pub struct Project { #[serde(default, skip_serializing_if = "Vec::is_empty")] pub glob_ignore_paths: Vec, + /// A list of mappings of globs to syncing rules. If a file matches a glob, + /// it will be 'transformed' into an Instance following the rule provided. + /// Globs are relative to the folder the project file is in. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub sync_rules: Vec, + /// The path to the file that this project came from. Relative paths in the /// project should be considered relative to the parent of this field, also /// given by `Project::folder_location`. diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index 1a3273ed..1578af23 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -4,11 +4,14 @@ use std::{ sync::Arc, }; +use anyhow::Context; use serde::{Deserialize, Serialize}; use crate::{ - glob::Glob, path_serializer, project::ProjectNode, - snapshot_middleware::emit_legacy_scripts_default, + glob::Glob, + path_serializer, + project::ProjectNode, + snapshot_middleware::{emit_legacy_scripts_default, Middleware}, }; /// Rojo-specific metadata that can be associated with an instance or a snapshot @@ -107,6 +110,8 @@ pub struct InstanceContext { #[serde(skip_serializing_if = "Vec::is_empty")] pub path_ignore_rules: Arc>, pub emit_legacy_scripts: bool, + #[serde(skip_serializing_if = "Vec::is_empty")] + pub sync_rules: Vec, } impl InstanceContext { @@ -114,6 +119,7 @@ impl InstanceContext { Self { path_ignore_rules: Arc::new(Vec::new()), emit_legacy_scripts: emit_legacy_scripts_default().unwrap(), + sync_rules: Vec::new(), } } @@ -144,9 +150,28 @@ impl InstanceContext { rules.extend(new_rules); } + /// Extend the list of syncing rules in the context with the given new rules. + pub fn add_sync_rules(&mut self, new_rules: I) + where + I: IntoIterator, + { + self.sync_rules.extend(new_rules); + } + + /// Clears all sync rules for this InstanceContext + pub fn clear_sync_rules(&mut self) { + self.sync_rules.clear(); + } + pub fn set_emit_legacy_scripts(&mut self, emit_legacy_scripts: bool) { self.emit_legacy_scripts = emit_legacy_scripts; } + + /// Returns the middleware specified by the first sync rule that + /// matches the provided path. This does not handle default syncing rules. + pub fn get_user_sync_rule(&self, path: &Path) -> Option<&SyncRule> { + self.sync_rules.iter().find(|&rule| rule.matches(path)) + } } impl Default for InstanceContext { @@ -216,3 +241,64 @@ impl From<&Path> for InstigatingSource { InstigatingSource::Path(path.to_path_buf()) } } + +/// Represents an user-specified rule for transforming files +/// into Instances using a given middleware. +#[derive(Debug, Deserialize, Serialize, Clone, PartialEq)] +pub struct SyncRule { + /// A pattern used to determine if a file is included in this SyncRule + #[serde(rename = "pattern")] + pub include: Glob, + /// A pattern used to determine if a file is excluded from this SyncRule. + #[serde(skip_serializing_if = "Option::is_none")] + pub exclude: Option, + /// The middleware specified by the user for this SyncRule + #[serde(rename = "use")] + pub middleware: Middleware, + /// A suffix to trim off of file names, including the file extension. + /// If not specified, the file extension is the only thing cut off. + #[serde(skip_serializing_if = "Option::is_none")] + pub suffix: Option, + /// The 'base' of the glob above, allowing it to be used + /// relative to a path instead of absolute. + #[serde(skip)] + pub base_path: PathBuf, +} + +impl SyncRule { + /// Returns whether the given path matches this rule. + pub fn matches(&self, path: &Path) -> bool { + match path.strip_prefix(&self.base_path) { + Ok(suffix) => { + if let Some(pattern) = &self.exclude { + if pattern.is_match(suffix) { + return false; + } + } + self.include.is_match(suffix) + } + Err(_) => false, + } + } + + pub fn file_name_for_path<'a>(&self, path: &'a Path) -> anyhow::Result<&'a str> { + if let Some(suffix) = &self.suffix { + let file_name = path + .file_name() + .and_then(|s| s.to_str()) + .with_context(|| format!("file name of {} is invalid", path.display()))?; + if file_name.ends_with(suffix) { + let end = file_name.len().saturating_sub(suffix.len()); + Ok(&file_name[..end]) + } else { + Ok(file_name) + } + } else { + // If the user doesn't specify a suffix, we assume they just want + // the name of the file (the file_stem) + path.file_stem() + .and_then(|s| s.to_str()) + .with_context(|| format!("file name of {} is invalid", path.display())) + } + } +} diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index 708f1bb8..52e8ab0f 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -10,16 +10,14 @@ use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ dir::{dir_meta, snapshot_dir_no_meta}, meta_file::AdjacentMetadata, - util::PathExt, }; pub fn snapshot_csv( _context: &InstanceContext, vfs: &Vfs, path: &Path, + name: &str, ) -> anyhow::Result> { - let name = path.file_name_trim_end(".csv")?; - let meta_path = path.with_file_name(format!("{}.meta.json", name)); let contents = vfs.read(path)?; @@ -74,9 +72,8 @@ pub fn snapshot_csv_init( ); } - let mut init_snapshot = snapshot_csv(context, vfs, init_path)?.unwrap(); + let mut init_snapshot = snapshot_csv(context, vfs, init_path, &dir_snapshot.name)?.unwrap(); - init_snapshot.name = dir_snapshot.name; init_snapshot.children = dir_snapshot.children; init_snapshot.metadata = dir_snapshot.metadata; @@ -185,10 +182,14 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, let mut vfs = Vfs::new(imfs); - let instance_snapshot = - snapshot_csv(&InstanceContext::default(), &mut vfs, Path::new("/foo.csv")) - .unwrap() - .unwrap(); + let instance_snapshot = snapshot_csv( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.csv"), + "foo", + ) + .unwrap() + .unwrap(); insta::assert_yaml_snapshot!(instance_snapshot); } @@ -213,10 +214,14 @@ Ack,Ack!,,An exclamation of despair,¡Ay!"#, let mut vfs = Vfs::new(imfs); - let instance_snapshot = - snapshot_csv(&InstanceContext::default(), &mut vfs, Path::new("/foo.csv")) - .unwrap() - .unwrap(); + let instance_snapshot = snapshot_csv( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.csv"), + "foo", + ) + .unwrap() + .unwrap(); insta::assert_yaml_snapshot!(instance_snapshot); } diff --git a/src/snapshot_middleware/json.rs b/src/snapshot_middleware/json.rs index 8c7f369e..7594d96c 100644 --- a/src/snapshot_middleware/json.rs +++ b/src/snapshot_middleware/json.rs @@ -9,14 +9,14 @@ use crate::{ snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, }; -use super::{meta_file::AdjacentMetadata, util::PathExt}; +use super::meta_file::AdjacentMetadata; pub fn snapshot_json( context: &InstanceContext, vfs: &Vfs, path: &Path, + name: &str, ) -> anyhow::Result> { - let name = path.file_name_trim_end(".json")?; let contents = vfs.read(path)?; let value: serde_json::Value = serde_json::from_slice(&contents) @@ -107,6 +107,7 @@ mod test { &InstanceContext::default(), &mut vfs, Path::new("/foo.json"), + "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index b38c47a7..93d566a2 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -10,15 +10,12 @@ use crate::{ snapshot::{InstanceContext, InstanceSnapshot}, }; -use super::util::PathExt; - pub fn snapshot_json_model( context: &InstanceContext, vfs: &Vfs, path: &Path, + name: &str, ) -> anyhow::Result> { - let name = path.file_name_trim_end(".model.json")?; - let contents = vfs.read(path)?; let contents_str = str::from_utf8(&contents) .with_context(|| format!("File was not valid UTF-8: {}", path.display()))?; @@ -158,6 +155,7 @@ mod test { &InstanceContext::default(), &vfs, Path::new("/foo.model.json"), + "foo", ) .unwrap() .unwrap(); @@ -195,6 +193,7 @@ mod test { &InstanceContext::default(), &vfs, Path::new("/foo.model.json"), + "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index 1307b066..ab7f15a1 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -9,11 +9,10 @@ use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; use super::{ dir::{dir_meta, snapshot_dir_no_meta}, meta_file::AdjacentMetadata, - util::match_trailing, }; #[derive(Debug)] -enum ScriptType { +pub enum ScriptType { Server, Client, Module, @@ -24,32 +23,15 @@ pub fn snapshot_lua( context: &InstanceContext, vfs: &Vfs, path: &Path, + name: &str, + script_type: ScriptType, ) -> anyhow::Result> { - let file_name = path.file_name().unwrap().to_string_lossy(); - let run_context_enums = &rbx_reflection_database::get() .enums .get("RunContext") .expect("Unable to get RunContext enums!") .items; - let (script_type, instance_name) = if let Some(name) = match_trailing(&file_name, ".server.lua") - { - (ScriptType::Server, name) - } else if let Some(name) = match_trailing(&file_name, ".client.lua") { - (ScriptType::Client, name) - } else if let Some(name) = match_trailing(&file_name, ".lua") { - (ScriptType::Module, name) - } else if let Some(name) = match_trailing(&file_name, ".server.luau") { - (ScriptType::Server, name) - } else if let Some(name) = match_trailing(&file_name, ".client.luau") { - (ScriptType::Client, name) - } else if let Some(name) = match_trailing(&file_name, ".luau") { - (ScriptType::Module, name) - } else { - return Ok(None); - }; - let (class_name, run_context) = match (context.emit_legacy_scripts, script_type) { (false, ScriptType::Server) => ("Script", run_context_enums.get("Server")), (false, ScriptType::Client) => ("Script", run_context_enums.get("Client")), @@ -73,10 +55,10 @@ pub fn snapshot_lua( ); } - let meta_path = path.with_file_name(format!("{}.meta.json", instance_name)); + let meta_path = path.with_file_name(format!("{}.meta.json", name)); let mut snapshot = InstanceSnapshot::new() - .name(instance_name) + .name(name) .class_name(class_name) .properties(properties) .metadata( @@ -103,6 +85,7 @@ pub fn snapshot_lua_init( context: &InstanceContext, vfs: &Vfs, init_path: &Path, + script_type: ScriptType, ) -> anyhow::Result> { let folder_path = init_path.parent().unwrap(); let dir_snapshot = snapshot_dir_no_meta(context, vfs, folder_path)?.unwrap(); @@ -119,9 +102,9 @@ pub fn snapshot_lua_init( ); } - let mut init_snapshot = snapshot_lua(context, vfs, init_path)?.unwrap(); + let mut init_snapshot = + snapshot_lua(context, vfs, init_path, &dir_snapshot.name, script_type)?.unwrap(); - init_snapshot.name = dir_snapshot.name; init_snapshot.children = dir_snapshot.children; init_snapshot.metadata = dir_snapshot.metadata; @@ -151,6 +134,8 @@ mod test { &InstanceContext::with_emit_legacy_scripts(Some(true)), &mut vfs, Path::new("/foo.lua"), + "foo", + ScriptType::Module, ) .unwrap() .unwrap(); @@ -172,6 +157,8 @@ mod test { &InstanceContext::with_emit_legacy_scripts(Some(false)), &mut vfs, Path::new("/foo.lua"), + "foo", + ScriptType::Module, ) .unwrap() .unwrap(); @@ -193,6 +180,8 @@ mod test { &InstanceContext::with_emit_legacy_scripts(Some(true)), &mut vfs, Path::new("/foo.server.lua"), + "foo", + ScriptType::Server, ) .unwrap() .unwrap(); @@ -214,6 +203,8 @@ mod test { &InstanceContext::with_emit_legacy_scripts(Some(false)), &mut vfs, Path::new("/foo.server.lua"), + "foo", + ScriptType::Server, ) .unwrap() .unwrap(); @@ -235,6 +226,8 @@ mod test { &InstanceContext::with_emit_legacy_scripts(Some(true)), &mut vfs, Path::new("/foo.client.lua"), + "foo", + ScriptType::Client, ) .unwrap() .unwrap(); @@ -256,6 +249,8 @@ mod test { &InstanceContext::with_emit_legacy_scripts(Some(false)), &mut vfs, Path::new("/foo.client.lua"), + "foo", + ScriptType::Client, ) .unwrap() .unwrap(); @@ -283,6 +278,8 @@ mod test { &InstanceContext::with_emit_legacy_scripts(Some(true)), &mut vfs, Path::new("/root"), + "root", + ScriptType::Module, ) .unwrap() .unwrap(); @@ -315,6 +312,8 @@ mod test { &InstanceContext::with_emit_legacy_scripts(Some(true)), &mut vfs, Path::new("/foo.lua"), + "foo", + ScriptType::Module, ) .unwrap() .unwrap(); @@ -347,6 +346,8 @@ mod test { &InstanceContext::with_emit_legacy_scripts(Some(false)), &mut vfs, Path::new("/foo.lua"), + "foo", + ScriptType::Module, ) .unwrap() .unwrap(); @@ -379,6 +380,8 @@ mod test { &InstanceContext::with_emit_legacy_scripts(Some(true)), &mut vfs, Path::new("/foo.server.lua"), + "foo", + ScriptType::Server, ) .unwrap() .unwrap(); @@ -411,6 +414,8 @@ mod test { &InstanceContext::with_emit_legacy_scripts(Some(false)), &mut vfs, Path::new("/foo.server.lua"), + "foo", + ScriptType::Server, ) .unwrap() .unwrap(); @@ -445,6 +450,8 @@ mod test { &InstanceContext::with_emit_legacy_scripts(Some(true)), &mut vfs, Path::new("/bar.server.lua"), + "bar", + ScriptType::Server, ) .unwrap() .unwrap(); @@ -479,6 +486,8 @@ mod test { &InstanceContext::with_emit_legacy_scripts(Some(false)), &mut vfs, Path::new("/bar.server.lua"), + "bar", + ScriptType::Server, ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index d8cd3940..30ea5706 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -18,30 +18,37 @@ mod toml; mod txt; mod util; -use std::path::Path; +use std::{ + path::{Path, PathBuf}, + sync::OnceLock, +}; +use anyhow::Context; use memofs::{IoResultExt, Vfs}; +use serde::{Deserialize, Serialize}; -use crate::snapshot::{InstanceContext, InstanceSnapshot}; +use crate::glob::Glob; +use crate::snapshot::{InstanceContext, InstanceSnapshot, SyncRule}; use self::{ csv::{snapshot_csv, snapshot_csv_init}, dir::snapshot_dir, json::snapshot_json, json_model::snapshot_json_model, - lua::{snapshot_lua, snapshot_lua_init}, + lua::{snapshot_lua, snapshot_lua_init, ScriptType}, project::snapshot_project, rbxm::snapshot_rbxm, rbxmx::snapshot_rbxmx, toml::snapshot_toml, txt::snapshot_txt, - util::PathExt, }; pub use self::{project::snapshot_project_node, util::emit_legacy_scripts_default}; -/// The main entrypoint to the snapshot function. This function can be pointed -/// at any path and will return something if Rojo knows how to deal with it. +/// Returns an `InstanceSnapshot` for the provided path. +/// This will inspect the path and find the appropriate middleware for it, +/// taking user-written rules into account. Then, it will attempt to convert +/// the path into an InstanceSnapshot using that middleware. #[profiling::function] pub fn snapshot_from_vfs( context: &InstanceContext, @@ -54,89 +61,234 @@ pub fn snapshot_from_vfs( }; if meta.is_dir() { - let project_path = path.join("default.project.json"); - if vfs.metadata(&project_path).with_not_found()?.is_some() { - return snapshot_project(context, vfs, &project_path); - } + if let Some(init_path) = get_init_path(vfs, path)? { + // TODO: support user-defined init paths + for rule in default_sync_rules() { + if rule.matches(&init_path) { + return match rule.middleware { + Middleware::Project => snapshot_project(context, vfs, &init_path), - let init_path = path.join("init.luau"); - if vfs.metadata(&init_path).with_not_found()?.is_some() { - return snapshot_lua_init(context, vfs, &init_path); - } + Middleware::ModuleScript => { + snapshot_lua_init(context, vfs, &init_path, ScriptType::Module) + } + Middleware::ServerScript => { + snapshot_lua_init(context, vfs, &init_path, ScriptType::Server) + } + Middleware::ClientScript => { + snapshot_lua_init(context, vfs, &init_path, ScriptType::Client) + } - let init_path = path.join("init.lua"); - if vfs.metadata(&init_path).with_not_found()?.is_some() { - return snapshot_lua_init(context, vfs, &init_path); - } + Middleware::Csv => snapshot_csv_init(context, vfs, &init_path), - let init_path = path.join("init.server.luau"); - if vfs.metadata(&init_path).with_not_found()?.is_some() { - return snapshot_lua_init(context, vfs, &init_path); + _ => snapshot_dir(context, vfs, path), + }; + } + } + snapshot_dir(context, vfs, path) + } else { + snapshot_dir(context, vfs, path) } - - let init_path = path.join("init.server.lua"); - if vfs.metadata(&init_path).with_not_found()?.is_some() { - return snapshot_lua_init(context, vfs, &init_path); - } - - let init_path = path.join("init.client.luau"); - if vfs.metadata(&init_path).with_not_found()?.is_some() { - return snapshot_lua_init(context, vfs, &init_path); - } - - let init_path = path.join("init.client.lua"); - if vfs.metadata(&init_path).with_not_found()?.is_some() { - return snapshot_lua_init(context, vfs, &init_path); - } - - let init_path = path.join("init.csv"); - if vfs.metadata(&init_path).with_not_found()?.is_some() { - return snapshot_csv_init(context, vfs, &init_path); - } - - snapshot_dir(context, vfs, path) } else { - let script_name = path - .file_name_trim_end(".lua") - .or_else(|_| path.file_name_trim_end(".luau")); + let file_name = path + .file_name() + .and_then(|n| n.to_str()) + .with_context(|| format!("file name of {} is invalid", path.display()))?; - let csv_name = path.file_name_trim_end(".csv"); - - if let Ok(name) = script_name { - match name { - // init scripts are handled elsewhere and should not turn into - // their own children. - "init" | "init.client" | "init.server" => return Ok(None), - - _ => return snapshot_lua(context, vfs, path), - } - } else if path.file_name_ends_with(".project.json") { - return snapshot_project(context, vfs, path); - } else if path.file_name_ends_with(".model.json") { - return snapshot_json_model(context, vfs, path); - } else if path.file_name_ends_with(".meta.json") { - // .meta.json files do not turn into their own instances. - return Ok(None); - } else if path.file_name_ends_with(".json") { - return snapshot_json(context, vfs, path); - } else if path.file_name_ends_with(".toml") { - return snapshot_toml(context, vfs, path); - } else if let Ok(name) = csv_name { - match name { - // init csv are handled elsewhere and should not turn into - // their own children. - "init" => return Ok(None), - - _ => return snapshot_csv(context, vfs, path), - } - } else if path.file_name_ends_with(".txt") { - return snapshot_txt(context, vfs, path); - } else if path.file_name_ends_with(".rbxmx") { - return snapshot_rbxmx(context, vfs, path); - } else if path.file_name_ends_with(".rbxm") { - return snapshot_rbxm(context, vfs, path); + // TODO: Is this even necessary anymore? + match file_name { + "init.server.luau" | "init.server.lua" | "init.client.luau" | "init.client.lua" + | "init.luau" | "init.lua" | "init.csv" => return Ok(None), + _ => {} } - Ok(None) + snapshot_from_path(context, vfs, path) } } + +/// Gets an `init` path for the given directory. +/// This uses an intrinsic priority list and for compatibility, +/// it should not be changed. +fn get_init_path>(vfs: &Vfs, dir: P) -> anyhow::Result> { + let path = dir.as_ref(); + + let project_path = path.join("default.project.json"); + if vfs.metadata(&project_path).with_not_found()?.is_some() { + return Ok(Some(project_path)); + } + + let init_path = path.join("init.luau"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return Ok(Some(init_path)); + } + + let init_path = path.join("init.lua"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return Ok(Some(init_path)); + } + + let init_path = path.join("init.server.luau"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return Ok(Some(init_path)); + } + + let init_path = path.join("init.server.lua"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return Ok(Some(init_path)); + } + + let init_path = path.join("init.client.luau"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return Ok(Some(init_path)); + } + + let init_path = path.join("init.client.lua"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return Ok(Some(init_path)); + } + + let init_path = path.join("init.csv"); + if vfs.metadata(&init_path).with_not_found()?.is_some() { + return Ok(Some(init_path)); + } + + Ok(None) +} + +/// Gets a snapshot for a path given an InstanceContext and Vfs, taking +/// user specified sync rules into account. +fn snapshot_from_path( + context: &InstanceContext, + vfs: &Vfs, + path: &Path, +) -> anyhow::Result> { + if let Some(rule) = context.get_user_sync_rule(path) { + return rule + .middleware + .snapshot(context, vfs, path, rule.file_name_for_path(path)?); + } else { + for rule in default_sync_rules() { + if rule.matches(path) { + return rule.middleware.snapshot( + context, + vfs, + path, + rule.file_name_for_path(path)?, + ); + } + } + } + Ok(None) +} + +/// Represents a possible 'transformer' used by Rojo to turn a file system +/// item into a Roblox Instance. Missing from this list are directories and +/// metadata. This is deliberate, as metadata is not a snapshot middleware +/// and directories do not make sense to turn into files. +#[derive(Debug, Clone, Copy, PartialEq, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub enum Middleware { + Csv, + JsonModel, + Json, + ServerScript, + ClientScript, + ModuleScript, + Project, + Rbxm, + Rbxmx, + Toml, + Text, + Ignore, +} + +impl Middleware { + /// Creates a snapshot for the given path from the Middleware with + /// the provided name. + fn snapshot( + &self, + context: &InstanceContext, + vfs: &Vfs, + path: &Path, + name: &str, + ) -> anyhow::Result> { + match self { + Self::Csv => snapshot_csv(context, vfs, path, name), + Self::JsonModel => snapshot_json_model(context, vfs, path, name), + Self::Json => snapshot_json(context, vfs, path, name), + Self::ServerScript => snapshot_lua(context, vfs, path, name, ScriptType::Server), + Self::ClientScript => snapshot_lua(context, vfs, path, name, ScriptType::Client), + Self::ModuleScript => snapshot_lua(context, vfs, path, name, ScriptType::Module), + // At the moment, snapshot_project does not use `name` so we + // don't provide it. + Self::Project => snapshot_project(context, vfs, path), + Self::Rbxm => snapshot_rbxm(context, vfs, path, name), + Self::Rbxmx => snapshot_rbxmx(context, vfs, path, name), + Self::Toml => snapshot_toml(context, vfs, path, name), + Self::Text => snapshot_txt(context, vfs, path, name), + Self::Ignore => Ok(None), + } + } +} + +/// A helper for easily defining a SyncRule. Arguments are passed literally +/// to this macro in the order `include`, `middleware`, `suffix`, +/// and `exclude`. Both `suffix` and `exclude` are optional. +/// +/// All arguments except `middleware` are expected to be strings. +/// The `middleware` parameter is expected to be a variant of `Middleware`, +/// not including the enum name itself. +macro_rules! sync_rule { + ($pattern:expr, $middleware:ident) => { + SyncRule { + middleware: Middleware::$middleware, + include: Glob::new($pattern).unwrap(), + exclude: None, + suffix: None, + base_path: PathBuf::new(), + } + }; + ($pattern:expr, $middleware:ident, $suffix:expr) => { + SyncRule { + middleware: Middleware::$middleware, + include: Glob::new($pattern).unwrap(), + exclude: None, + suffix: Some($suffix.into()), + base_path: PathBuf::new(), + } + }; + ($pattern:expr, $middleware:ident, $suffix:expr, $exclude:expr) => { + SyncRule { + middleware: Middleware::$middleware, + include: Glob::new($pattern).unwrap(), + exclude: Some(Glob::new($exclude).unwrap()), + suffix: Some($suffix.into()), + base_path: PathBuf::new(), + } + }; +} + +/// Defines the 'default' syncing rules that Rojo uses. +/// These do not broadly overlap, but the order matters for some in the case of +/// e.g. JSON models. +fn default_sync_rules() -> &'static [SyncRule] { + static DEFAULT_SYNC_RULES: OnceLock> = OnceLock::new(); + + DEFAULT_SYNC_RULES.get_or_init(|| { + vec![ + sync_rule!("*.server.lua", ServerScript, ".server.lua"), + sync_rule!("*.server.luau", ServerScript, ".server.luau"), + sync_rule!("*.client.lua", ClientScript, ".client.lua"), + sync_rule!("*.client.luau", ClientScript, ".client.luau"), + sync_rule!("*.{lua,luau}", ModuleScript), + // Project middleware doesn't use the file name. + sync_rule!("*.project.json", Project), + sync_rule!("*.model.json", JsonModel, ".model.json"), + sync_rule!("*.json", Json, ".json", "*.meta.json"), + sync_rule!("*.toml", Toml), + sync_rule!("*.csv", Csv), + sync_rule!("*.txt", Text), + sync_rule!("*.rbxmx", Rbxmx), + sync_rule!("*.rbxm", Rbxm), + ] + }) +} diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index d1b4a2e4..c92f42d8 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -9,6 +9,7 @@ use crate::{ project::{PathNode, Project, ProjectNode}, snapshot::{ InstanceContext, InstanceMetadata, InstanceSnapshot, InstigatingSource, PathIgnoreRule, + SyncRule, }, }; @@ -23,12 +24,19 @@ pub fn snapshot_project( .with_context(|| format!("File was not a valid Rojo project: {}", path.display()))?; let mut context = context.clone(); + context.clear_sync_rules(); let rules = project.glob_ignore_paths.iter().map(|glob| PathIgnoreRule { glob: glob.clone(), base_path: project.folder_location().to_path_buf(), }); + let sync_rules = project.sync_rules.iter().map(|rule| SyncRule { + base_path: project.folder_location().to_path_buf(), + ..rule.clone() + }); + + context.add_sync_rules(sync_rules); context.add_path_ignore_rules(rules); context.set_emit_legacy_scripts( project diff --git a/src/snapshot_middleware/rbxm.rs b/src/snapshot_middleware/rbxm.rs index 969f022d..7983d0e7 100644 --- a/src/snapshot_middleware/rbxm.rs +++ b/src/snapshot_middleware/rbxm.rs @@ -5,16 +5,13 @@ use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::util::PathExt; - #[profiling::function] pub fn snapshot_rbxm( context: &InstanceContext, vfs: &Vfs, path: &Path, + name: &str, ) -> anyhow::Result> { - let name = path.file_name_trim_end(".rbxm")?; - let temp_tree = rbx_binary::from_reader(vfs.read(path)?.as_slice()) .with_context(|| format!("Malformed rbxm file: {}", path.display()))?; @@ -63,6 +60,7 @@ mod test { &InstanceContext::default(), &mut vfs, Path::new("/foo.rbxm"), + "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/rbxmx.rs b/src/snapshot_middleware/rbxmx.rs index 4f128ff6..4266dc0d 100644 --- a/src/snapshot_middleware/rbxmx.rs +++ b/src/snapshot_middleware/rbxmx.rs @@ -5,15 +5,12 @@ use memofs::Vfs; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::util::PathExt; - pub fn snapshot_rbxmx( context: &InstanceContext, vfs: &Vfs, path: &Path, + name: &str, ) -> anyhow::Result> { - let name = path.file_name_trim_end(".rbxmx")?; - let options = rbx_xml::DecodeOptions::new() .property_behavior(rbx_xml::DecodePropertyBehavior::ReadUnknown); @@ -75,6 +72,7 @@ mod test { &InstanceContext::default(), &mut vfs, Path::new("/foo.rbxmx"), + "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/toml.rs b/src/snapshot_middleware/toml.rs index 6ee9be47..086c539d 100644 --- a/src/snapshot_middleware/toml.rs +++ b/src/snapshot_middleware/toml.rs @@ -9,14 +9,14 @@ use crate::{ snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}, }; -use super::{meta_file::AdjacentMetadata, util::PathExt}; +use super::meta_file::AdjacentMetadata; pub fn snapshot_toml( context: &InstanceContext, vfs: &Vfs, path: &Path, + name: &str, ) -> anyhow::Result> { - let name = path.file_name_trim_end(".toml")?; let contents = vfs.read(path)?; let value: toml::Value = toml::from_slice(&contents) @@ -114,6 +114,7 @@ mod test { &InstanceContext::default(), &mut vfs, Path::new("/foo.toml"), + "foo", ) .unwrap() .unwrap(); diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 13d5b990..207243f9 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -6,15 +6,14 @@ use memofs::{IoResultExt, Vfs}; use crate::snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot}; -use super::{meta_file::AdjacentMetadata, util::PathExt}; +use super::meta_file::AdjacentMetadata; pub fn snapshot_txt( context: &InstanceContext, vfs: &Vfs, path: &Path, + name: &str, ) -> anyhow::Result> { - let name = path.file_name_trim_end(".txt")?; - let contents = vfs.read(path)?; let contents_str = str::from_utf8(&contents) .with_context(|| format!("File was not valid UTF-8: {}", path.display()))? @@ -59,10 +58,14 @@ mod test { let mut vfs = Vfs::new(imfs.clone()); - let instance_snapshot = - snapshot_txt(&InstanceContext::default(), &mut vfs, Path::new("/foo.txt")) - .unwrap() - .unwrap(); + let instance_snapshot = snapshot_txt( + &InstanceContext::default(), + &mut vfs, + Path::new("/foo.txt"), + "foo", + ) + .unwrap() + .unwrap(); insta::assert_yaml_snapshot!(instance_snapshot); } diff --git a/tests/tests/build.rs b/tests/tests/build.rs index 01e87da7..f23d4a4e 100644 --- a/tests/tests/build.rs +++ b/tests/tests/build.rs @@ -59,6 +59,9 @@ gen_build_tests! { txt_in_folder, unresolved_values, weldconstraint, + sync_rule_alone, + sync_rule_complex, + sync_rule_nested_projects, } fn run_build_test(test_name: &str) { diff --git a/tests/tests/serve.rs b/tests/tests/serve.rs index d55d339b..5d716b39 100644 --- a/tests/tests/serve.rs +++ b/tests/tests/serve.rs @@ -255,3 +255,54 @@ fn add_optional_folder() { ); }); } + +#[test] +fn sync_rule_alone() { + run_serve_test("sync_rule_alone", |session, mut redactions| { + let info = session.get_api_rojo().unwrap(); + let root_id = info.root_instance_id; + + assert_yaml_snapshot!("sync_rule_alone_info", redactions.redacted_yaml(info)); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "sync_rule_alone_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); + }); +} + +#[test] +fn sync_rule_complex() { + run_serve_test("sync_rule_complex", |session, mut redactions| { + let info = session.get_api_rojo().unwrap(); + let root_id = info.root_instance_id; + + assert_yaml_snapshot!("sync_rule_complex_info", redactions.redacted_yaml(info)); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "sync_rule_complex_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); + }); +} + +#[test] +fn sync_rule_no_extension() { + run_serve_test("sync_rule_no_extension", |session, mut redactions| { + let info = session.get_api_rojo().unwrap(); + let root_id = info.root_instance_id; + + assert_yaml_snapshot!( + "sync_rule_no_extension_info", + redactions.redacted_yaml(info) + ); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "sync_rule_no_extension_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); + }); +} From 1cc720ad3403dfb85d06cbed4dfb50cf66a04f69 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Mon, 22 Jan 2024 11:22:21 -0800 Subject: [PATCH 1369/1504] Use Studio theming (#838) Updates our Theme provider to use Studio colors. A few components look ever so slightly different now, but more in line with Studio. --- CHANGELOG.md | 3 + plugin/src/App/Components/Dropdown.lua | 4 +- .../Components/PatchVisualizer/ChangeList.lua | 8 +- .../Components/PatchVisualizer/DomLabel.lua | 2 +- .../App/Components/PatchVisualizer/init.lua | 2 +- plugin/src/App/StatusPages/Confirming.lua | 2 +- plugin/src/App/Theme.lua | 382 +++++++----------- 7 files changed, 158 insertions(+), 245 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7552a0ed..54e1cd77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Rojo Changelog ## Unreleased Changes +* Updated Theme to use Studio colors ([#838]) + +[#838]: https://github.com/rojo-rbx/rojo/pull/838 * Projects may now specify rules for syncing files as if they had a different file extension. ([#813]) This is specified via a new field on project files, `syncRules`: diff --git a/plugin/src/App/Components/Dropdown.lua b/plugin/src/App/Components/Dropdown.lua index 4b761636..3fde88c5 100644 --- a/plugin/src/App/Components/Dropdown.lua +++ b/plugin/src/App/Components/Dropdown.lua @@ -109,9 +109,7 @@ function Dropdown:render() }, { DropArrow = e("ImageLabel", { Image = if self.props.locked then Assets.Images.Dropdown.Locked else Assets.Images.Dropdown.Arrow, - ImageColor3 = self.openBinding:map(function(a) - return theme.Closed.IconColor:Lerp(theme.Open.IconColor, a) - end), + ImageColor3 = theme.IconColor, ImageTransparency = self.props.transparency, Size = UDim2.new(0, 18, 0, 18), diff --git a/plugin/src/App/Components/PatchVisualizer/ChangeList.lua b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua index 7aac862a..522dd95b 100644 --- a/plugin/src/App/Components/PatchVisualizer/ChangeList.lua +++ b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua @@ -54,7 +54,7 @@ function ChangeList:render() BackgroundTransparency = 1, Font = Enum.Font.GothamBold, TextSize = 14, - TextColor3 = theme.Settings.Setting.DescriptionColor, + TextColor3 = theme.TextColor, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = props.transparency, TextTruncate = Enum.TextTruncate.AtEnd, @@ -66,7 +66,7 @@ function ChangeList:render() BackgroundTransparency = 1, Font = Enum.Font.GothamBold, TextSize = 14, - TextColor3 = theme.Settings.Setting.DescriptionColor, + TextColor3 = theme.TextColor, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = props.transparency, TextTruncate = Enum.TextTruncate.AtEnd, @@ -78,7 +78,7 @@ function ChangeList:render() BackgroundTransparency = 1, Font = Enum.Font.GothamBold, TextSize = 14, - TextColor3 = theme.Settings.Setting.DescriptionColor, + TextColor3 = theme.TextColor, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = props.transparency, TextTruncate = Enum.TextTruncate.AtEnd, @@ -197,7 +197,7 @@ function ChangeList:render() BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, TextSize = 14, - TextColor3 = if isWarning then theme.Diff.Warning else theme.Settings.Setting.DescriptionColor, + TextColor3 = if isWarning then theme.Diff.Warning else theme.TextColor, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = props.transparency, TextTruncate = Enum.TextTruncate.AtEnd, diff --git a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua index 8495d712..f15931f6 100644 --- a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua +++ b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua @@ -205,7 +205,7 @@ function DomLabel:render() BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, TextSize = 14, - TextColor3 = if props.isWarning then theme.Diff.Warning else theme.Settings.Setting.DescriptionColor, + TextColor3 = if props.isWarning then theme.Diff.Warning else theme.TextColor, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = props.transparency, TextTruncate = Enum.TextTruncate.AtEnd, diff --git a/plugin/src/App/Components/PatchVisualizer/init.lua b/plugin/src/App/Components/PatchVisualizer/init.lua index aad2e63d..59cbe09b 100644 --- a/plugin/src/App/Components/PatchVisualizer/init.lua +++ b/plugin/src/App/Components/PatchVisualizer/init.lua @@ -98,7 +98,7 @@ function PatchVisualizer:render() Text = "No changes to sync, project is up to date.", Font = Enum.Font.GothamMedium, TextSize = 15, - TextColor3 = theme.Settings.Setting.DescriptionColor, + TextColor3 = theme.TextColor, TextWrapped = true, Size = UDim2.new(1, 0, 1, 0), BackgroundTransparency = 1, diff --git a/plugin/src/App/StatusPages/Confirming.lua b/plugin/src/App/StatusPages/Confirming.lua index 457340bd..ca5bfba0 100644 --- a/plugin/src/App/StatusPages/Confirming.lua +++ b/plugin/src/App/StatusPages/Confirming.lua @@ -47,7 +47,7 @@ function ConfirmingPage:render() Font = Enum.Font.Gotham, LineHeight = 1.2, TextSize = 14, - TextColor3 = theme.Settings.Setting.DescriptionColor, + TextColor3 = theme.TextColor, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = self.props.transparency, Size = UDim2.new(1, 0, 0, 20), diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index d6f9622b..2ba8fc9d 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -25,227 +25,7 @@ local strict = require(script.Parent.Parent.strict) local BRAND_COLOR = Color3.fromHex("E13835") -local lightTheme = strict("LightTheme", { - BackgroundColor = Color3.fromHex("FFFFFF"), - Button = { - Solid = { - ActionFillColor = Color3.fromHex("FFFFFF"), - ActionFillTransparency = 0.8, - Enabled = { - TextColor = Color3.fromHex("FFFFFF"), - BackgroundColor = BRAND_COLOR, - }, - Disabled = { - TextColor = Color3.fromHex("FFFFFF"), - BackgroundColor = BRAND_COLOR, - }, - }, - Bordered = { - ActionFillColor = Color3.fromHex("000000"), - ActionFillTransparency = 0.9, - Enabled = { - TextColor = Color3.fromHex("393939"), - BorderColor = Color3.fromHex("ACACAC"), - }, - Disabled = { - TextColor = Color3.fromHex("393939"), - BorderColor = Color3.fromHex("ACACAC"), - }, - }, - }, - Checkbox = { - Active = { - IconColor = Color3.fromHex("FFFFFF"), - BackgroundColor = BRAND_COLOR, - }, - Inactive = { - IconColor = Color3.fromHex("EEEEEE"), - BorderColor = Color3.fromHex("AFAFAF"), - }, - }, - Dropdown = { - TextColor = Color3.fromHex("000000"), - BorderColor = Color3.fromHex("AFAFAF"), - BackgroundColor = Color3.fromHex("EEEEEE"), - Open = { - IconColor = BRAND_COLOR, - }, - Closed = { - IconColor = Color3.fromHex("EEEEEE"), - }, - }, - TextInput = { - Enabled = { - TextColor = Color3.fromHex("000000"), - PlaceholderColor = Color3.fromHex("8C8C8C"), - BorderColor = Color3.fromHex("ACACAC"), - }, - Disabled = { - TextColor = Color3.fromHex("393939"), - PlaceholderColor = Color3.fromHex("8C8C8C"), - BorderColor = Color3.fromHex("AFAFAF"), - }, - ActionFillColor = Color3.fromHex("000000"), - ActionFillTransparency = 0.9, - }, - AddressEntry = { - TextColor = Color3.fromHex("000000"), - PlaceholderColor = Color3.fromHex("8C8C8C"), - }, - BorderedContainer = { - BorderColor = Color3.fromHex("CBCBCB"), - BackgroundColor = Color3.fromHex("EEEEEE"), - }, - Spinner = { - ForegroundColor = BRAND_COLOR, - BackgroundColor = Color3.fromHex("EEEEEE"), - }, - Diff = { - Add = Color3.fromHex("baffbd"), - Remove = Color3.fromHex("ffbdba"), - Edit = Color3.fromHex("bacdff"), - Row = Color3.fromHex("000000"), - Warning = Color3.fromHex("FF8E3C"), - }, - ConnectionDetails = { - ProjectNameColor = Color3.fromHex("000000"), - AddressColor = Color3.fromHex("000000"), - DisconnectColor = BRAND_COLOR, - }, - Settings = { - DividerColor = Color3.fromHex("CBCBCB"), - Navbar = { - BackButtonColor = Color3.fromHex("000000"), - TextColor = Color3.fromHex("000000"), - }, - Setting = { - NameColor = Color3.fromHex("000000"), - DescriptionColor = Color3.fromHex("5F5F5F"), - }, - }, - Header = { - LogoColor = BRAND_COLOR, - VersionColor = Color3.fromHex("727272"), - }, - Notification = { - InfoColor = Color3.fromHex("000000"), - CloseColor = BRAND_COLOR, - }, - ErrorColor = Color3.fromHex("000000"), - ScrollBarColor = Color3.fromHex("000000"), -}) - -local darkTheme = strict("DarkTheme", { - BackgroundColor = Color3.fromHex("2E2E2E"), - Button = { - Solid = { - ActionFillColor = Color3.fromHex("FFFFFF"), - ActionFillTransparency = 0.8, - Enabled = { - TextColor = Color3.fromHex("FFFFFF"), - BackgroundColor = BRAND_COLOR, - }, - Disabled = { - TextColor = Color3.fromHex("FFFFFF"), - BackgroundColor = BRAND_COLOR, - }, - }, - Bordered = { - ActionFillColor = Color3.fromHex("FFFFFF"), - ActionFillTransparency = 0.9, - Enabled = { - TextColor = Color3.fromHex("DBDBDB"), - BorderColor = Color3.fromHex("535353"), - }, - Disabled = { - TextColor = Color3.fromHex("DBDBDB"), - BorderColor = Color3.fromHex("535353"), - }, - }, - }, - Checkbox = { - Active = { - IconColor = Color3.fromHex("FFFFFF"), - BackgroundColor = BRAND_COLOR, - }, - Inactive = { - IconColor = Color3.fromHex("484848"), - BorderColor = Color3.fromHex("5A5A5A"), - }, - }, - Dropdown = { - TextColor = Color3.fromHex("FFFFFF"), - BorderColor = Color3.fromHex("5A5A5A"), - BackgroundColor = Color3.fromHex("2B2B2B"), - Open = { - IconColor = BRAND_COLOR, - }, - Closed = { - IconColor = Color3.fromHex("484848"), - }, - }, - TextInput = { - Enabled = { - TextColor = Color3.fromHex("FFFFFF"), - PlaceholderColor = Color3.fromHex("8B8B8B"), - BorderColor = Color3.fromHex("535353"), - }, - Disabled = { - TextColor = Color3.fromHex("484848"), - PlaceholderColor = Color3.fromHex("8B8B8B"), - BorderColor = Color3.fromHex("5A5A5A"), - }, - ActionFillColor = Color3.fromHex("FFFFFF"), - ActionFillTransparency = 0.9, - }, - AddressEntry = { - TextColor = Color3.fromHex("FFFFFF"), - PlaceholderColor = Color3.fromHex("8B8B8B"), - }, - BorderedContainer = { - BorderColor = Color3.fromHex("535353"), - BackgroundColor = Color3.fromHex("2B2B2B"), - }, - Spinner = { - ForegroundColor = BRAND_COLOR, - BackgroundColor = Color3.fromHex("2B2B2B"), - }, - Diff = { - Add = Color3.fromHex("273732"), - Remove = Color3.fromHex("3F2D32"), - Edit = Color3.fromHex("193345"), - Row = Color3.fromHex("FFFFFF"), - Warning = Color3.fromHex("FF8E3C"), - }, - ConnectionDetails = { - ProjectNameColor = Color3.fromHex("FFFFFF"), - AddressColor = Color3.fromHex("FFFFFF"), - DisconnectColor = Color3.fromHex("FFFFFF"), - }, - Settings = { - DividerColor = Color3.fromHex("535353"), - Navbar = { - BackButtonColor = Color3.fromHex("FFFFFF"), - TextColor = Color3.fromHex("FFFFFF"), - }, - Setting = { - NameColor = Color3.fromHex("FFFFFF"), - DescriptionColor = Color3.fromHex("D3D3D3"), - }, - }, - Header = { - LogoColor = BRAND_COLOR, - VersionColor = Color3.fromHex("D3D3D3"), - }, - Notification = { - InfoColor = Color3.fromHex("FFFFFF"), - CloseColor = Color3.fromHex("FFFFFF"), - }, - ErrorColor = Color3.fromHex("FFFFFF"), - ScrollBarColor = Color3.fromHex("FFFFFF"), -}) - -local Context = Roact.createContext(lightTheme) +local Context = Roact.createContext({}) local StudioProvider = Roact.Component:extend("StudioProvider") @@ -253,21 +33,153 @@ local StudioProvider = Roact.Component:extend("StudioProvider") function StudioProvider:updateTheme() local studioTheme = getStudio().Theme - if studioTheme.Name == "Light" then - self:setState({ - theme = lightTheme, - }) - elseif studioTheme.Name == "Dark" then - self:setState({ - theme = darkTheme, - }) - else - Log.warn("Unexpected theme '{}'' -- falling back to light theme!", studioTheme.Name) + local theme = strict(studioTheme.Name .. "Theme", { + BackgroundColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainBackground), + TextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainText), + Button = { + Solid = { + -- Solid uses brand theming, not Studio theming. + ActionFillColor = Color3.fromHex("FFFFFF"), + ActionFillTransparency = 0.8, + Enabled = { + TextColor = Color3.fromHex("FFFFFF"), + BackgroundColor = BRAND_COLOR, + }, + Disabled = { + TextColor = Color3.fromHex("FFFFFF"), + BackgroundColor = BRAND_COLOR, + }, + }, + Bordered = { + ActionFillColor = studioTheme:GetColor( + Enum.StudioStyleGuideColor.ButtonText, + Enum.StudioStyleGuideModifier.Selected + ), + ActionFillTransparency = 0.9, + Enabled = { + TextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.ButtonText), + BorderColor = studioTheme:GetColor( + Enum.StudioStyleGuideColor.CheckedFieldBorder, + Enum.StudioStyleGuideModifier.Disabled + ), + }, + Disabled = { + TextColor = studioTheme:GetColor( + Enum.StudioStyleGuideColor.ButtonText, + Enum.StudioStyleGuideModifier.Disabled + ), + BorderColor = studioTheme:GetColor( + Enum.StudioStyleGuideColor.CheckedFieldBorder, + Enum.StudioStyleGuideModifier.Disabled + ), + }, + }, + }, + Checkbox = { + Active = { + -- Active checkboxes use brand theming, not Studio theming. + IconColor = Color3.fromHex("FFFFFF"), + BackgroundColor = BRAND_COLOR, + }, + Inactive = { + IconColor = studioTheme:GetColor( + Enum.StudioStyleGuideColor.CheckedFieldIndicator, + Enum.StudioStyleGuideModifier.Disabled + ), + BorderColor = studioTheme:GetColor( + Enum.StudioStyleGuideColor.CheckedFieldBorder, + Enum.StudioStyleGuideModifier.Disabled + ), + }, + }, + Dropdown = { + TextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.ButtonText), + BorderColor = studioTheme:GetColor( + Enum.StudioStyleGuideColor.CheckedFieldBorder, + Enum.StudioStyleGuideModifier.Disabled + ), + BackgroundColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainBackground), + IconColor = studioTheme:GetColor( + Enum.StudioStyleGuideColor.CheckedFieldIndicator, + Enum.StudioStyleGuideModifier.Disabled + ), + }, + TextInput = { + Enabled = { + TextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + PlaceholderColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.SubText), + BorderColor = studioTheme:GetColor( + Enum.StudioStyleGuideColor.CheckedFieldBorder, + Enum.StudioStyleGuideModifier.Disabled + ), + }, + Disabled = { + TextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainText), + PlaceholderColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.SubText), + BorderColor = studioTheme:GetColor( + Enum.StudioStyleGuideColor.CheckedFieldBorder, + Enum.StudioStyleGuideModifier.Disabled + ), + }, + ActionFillColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + ActionFillTransparency = 0.9, + }, + AddressEntry = { + TextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + PlaceholderColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.SubText), + }, + BorderedContainer = { + BorderColor = studioTheme:GetColor( + Enum.StudioStyleGuideColor.CheckedFieldBorder, + Enum.StudioStyleGuideModifier.Disabled + ), + BackgroundColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.InputFieldBackground), + }, + Spinner = { + ForegroundColor = BRAND_COLOR, + BackgroundColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.InputFieldBackground), + }, + Diff = { + Add = studioTheme:GetColor(Enum.StudioStyleGuideColor.DiffTextAdditionBackground), + Remove = studioTheme:GetColor(Enum.StudioStyleGuideColor.DiffTextDeletionBackground), + Edit = studioTheme:GetColor(Enum.StudioStyleGuideColor.DiffLineNumSeparatorBackground), + Row = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + Warning = studioTheme:GetColor(Enum.StudioStyleGuideColor.WarningText), + }, + ConnectionDetails = { + ProjectNameColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + AddressColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + DisconnectColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + }, + Settings = { + DividerColor = studioTheme:GetColor( + Enum.StudioStyleGuideColor.CheckedFieldBorder, + Enum.StudioStyleGuideModifier.Disabled + ), + Navbar = { + BackButtonColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + TextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + }, + Setting = { + NameColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + DescriptionColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainText), + }, + }, + Header = { + LogoColor = BRAND_COLOR, + VersionColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainText), + }, + Notification = { + InfoColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + CloseColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + }, + ErrorColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + ScrollBarColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), + }) - self:setState({ - theme = lightTheme, - }) - end + self:setState({ + theme = theme, + }) end function StudioProvider:init() From 4018607b77985ab02b7b8439de711d62e46e7639 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Mon, 22 Jan 2024 12:26:41 -0800 Subject: [PATCH 1370/1504] Visualize table changes (#834) Implements a pop out diff view for table properties like Attributes and Tags --- CHANGELOG.md | 6 +- .../Components/PatchVisualizer/ChangeList.lua | 248 ++++++++++-------- .../PatchVisualizer/DisplayValue.lua | 9 +- .../Components/PatchVisualizer/DomLabel.lua | 6 +- .../App/Components/PatchVisualizer/init.lua | 3 +- plugin/src/App/Components/ScrollingFrame.lua | 31 ++- .../Components/StringDiffVisualizer/init.lua | 24 +- .../Components/TableDiffVisualizer/Array.lua | 192 ++++++++++++++ .../TableDiffVisualizer/Dictionary.lua | 208 +++++++++++++++ .../Components/TableDiffVisualizer/init.lua | 48 ++++ plugin/src/App/StatusPages/Confirming.lua | 77 +++++- plugin/src/App/StatusPages/Connected.lua | 79 ++++-- 12 files changed, 755 insertions(+), 176 deletions(-) create mode 100644 plugin/src/App/Components/TableDiffVisualizer/Array.lua create mode 100644 plugin/src/App/Components/TableDiffVisualizer/Dictionary.lua create mode 100644 plugin/src/App/Components/TableDiffVisualizer/init.lua diff --git a/CHANGELOG.md b/CHANGELOG.md index 54e1cd77..70a7d5a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,10 +1,8 @@ # Rojo Changelog ## Unreleased Changes +* Added popout diff visualizer for table properties like Attributes and Tags ([#834]) * Updated Theme to use Studio colors ([#838]) - -[#838]: https://github.com/rojo-rbx/rojo/pull/838 - * Projects may now specify rules for syncing files as if they had a different file extension. ([#813]) This is specified via a new field on project files, `syncRules`: @@ -53,6 +51,8 @@ **All** sync rules are reset between project files, so they must be specified in each one when nesting them. This is to ensure that nothing can break other projects by changing how files are synced! [#813]: https://github.com/rojo-rbx/rojo/pull/813 +[#834]: https://github.com/rojo-rbx/rojo/pull/834 +[#838]: https://github.com/rojo-rbx/rojo/pull/838 ## [7.4.0] - January 16, 2024 * Improved the visualization for array properties like Tags ([#829]) diff --git a/plugin/src/App/Components/PatchVisualizer/ChangeList.lua b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua index 522dd95b..ce01b801 100644 --- a/plugin/src/App/Components/PatchVisualizer/ChangeList.lua +++ b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua @@ -14,6 +14,123 @@ local EMPTY_TABLE = {} local e = Roact.createElement +local function ViewDiffButton(props) + return Theme.with(function(theme) + return e("TextButton", { + Text = "", + Size = UDim2.new(0.7, 0, 1, -4), + LayoutOrder = 2, + BackgroundTransparency = 1, + [Roact.Event.Activated] = props.onClick, + }, { + e(BorderedContainer, { + size = UDim2.new(1, 0, 1, 0), + transparency = props.transparency:map(function(t) + return 0.5 + (0.5 * t) + end), + }, { + Layout = e("UIListLayout", { + FillDirection = Enum.FillDirection.Horizontal, + SortOrder = Enum.SortOrder.LayoutOrder, + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + Padding = UDim.new(0, 5), + }), + Label = e("TextLabel", { + Text = "View Diff", + BackgroundTransparency = 1, + Font = Enum.Font.GothamMedium, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = props.transparency, + TextTruncate = Enum.TextTruncate.AtEnd, + Size = UDim2.new(0, 65, 1, 0), + LayoutOrder = 1, + }), + Icon = e("ImageLabel", { + Image = Assets.Images.Icons.Expand, + ImageColor3 = theme.Settings.Setting.DescriptionColor, + ImageTransparency = props.transparency, + + Size = UDim2.new(0, 16, 0, 16), + Position = UDim2.new(0.5, 0, 0.5, 0), + AnchorPoint = Vector2.new(0.5, 0.5), + + BackgroundTransparency = 1, + LayoutOrder = 2, + }), + }), + }) + end) +end + +local function RowContent(props) + local values = props.values + local metadata = props.metadata + + if props.showStringDiff and values[1] == "Source" then + -- Special case for .Source updates + return e(ViewDiffButton, { + transparency = props.transparency, + onClick = function() + if not props.showStringDiff then + return + end + props.showStringDiff(tostring(values[2]), tostring(values[3])) + end, + }) + end + + if props.showTableDiff and (type(values[2]) == "table" or type(values[3]) == "table") then + -- Special case for table properties (like Attributes/Tags) + return e(ViewDiffButton, { + transparency = props.transparency, + onClick = function() + if not props.showTableDiff then + return + end + props.showTableDiff(values[2], values[3]) + end, + }) + end + + return Theme.with(function(theme) + return Roact.createFragment({ + ColumnB = e( + "Frame", + { + BackgroundTransparency = 1, + Size = UDim2.new(0.35, 0, 1, 0), + LayoutOrder = 2, + }, + e(DisplayValue, { + value = values[2], + transparency = props.transparency, + textColor = if metadata.isWarning + then theme.Diff.Warning + else theme.Settings.Setting.DescriptionColor, + }) + ), + ColumnC = e( + "Frame", + { + BackgroundTransparency = 1, + Size = UDim2.new(0.35, 0, 1, 0), + LayoutOrder = 3, + }, + e(DisplayValue, { + value = values[3], + transparency = props.transparency, + textColor = if metadata.isWarning + then theme.Diff.Warning + else theme.Settings.Setting.DescriptionColor, + }) + ), + }) + end) +end + local ChangeList = Roact.Component:extend("ChangeList") function ChangeList:init() @@ -36,6 +153,7 @@ function ChangeList:render() PaddingRight = UDim.new(0, 5), } + local headerRow = changes[1] local headers = e("Frame", { Size = UDim2.new(1, 0, 0, 30), BackgroundTransparency = rowTransparency, @@ -49,8 +167,8 @@ function ChangeList:render() HorizontalAlignment = Enum.HorizontalAlignment.Left, VerticalAlignment = Enum.VerticalAlignment.Center, }), - A = e("TextLabel", { - Text = tostring(changes[1][1]), + ColumnA = e("TextLabel", { + Text = tostring(headerRow[1]), BackgroundTransparency = 1, Font = Enum.Font.GothamBold, TextSize = 14, @@ -61,8 +179,8 @@ function ChangeList:render() Size = UDim2.new(0.3, 0, 1, 0), LayoutOrder = 1, }), - B = e("TextLabel", { - Text = tostring(changes[1][2]), + ColumnB = e("TextLabel", { + Text = tostring(headerRow[2]), BackgroundTransparency = 1, Font = Enum.Font.GothamBold, TextSize = 14, @@ -73,8 +191,8 @@ function ChangeList:render() Size = UDim2.new(0.35, 0, 1, 0), LayoutOrder = 2, }), - C = e("TextLabel", { - Text = tostring(changes[1][3]), + ColumnC = e("TextLabel", { + Text = tostring(headerRow[3]), BackgroundTransparency = 1, Font = Enum.Font.GothamBold, TextSize = 14, @@ -95,89 +213,6 @@ function ChangeList:render() local metadata = values[4] or EMPTY_TABLE local isWarning = metadata.isWarning - -- Special case for .Source updates - -- because we want to display a syntax highlighted diff for better UX - if self.props.showSourceDiff and tostring(values[1]) == "Source" then - rows[row] = e("Frame", { - Size = UDim2.new(1, 0, 0, 30), - BackgroundTransparency = row % 2 ~= 0 and rowTransparency or 1, - BackgroundColor3 = theme.Diff.Row, - BorderSizePixel = 0, - LayoutOrder = row, - }, { - Padding = e("UIPadding", pad), - Layout = e("UIListLayout", { - FillDirection = Enum.FillDirection.Horizontal, - SortOrder = Enum.SortOrder.LayoutOrder, - HorizontalAlignment = Enum.HorizontalAlignment.Left, - VerticalAlignment = Enum.VerticalAlignment.Center, - }), - A = e("TextLabel", { - Text = (if isWarning then "⚠ " else "") .. tostring(values[1]), - BackgroundTransparency = 1, - Font = Enum.Font.GothamMedium, - TextSize = 14, - TextColor3 = if isWarning then theme.Diff.Warning else theme.Settings.Setting.DescriptionColor, - TextXAlignment = Enum.TextXAlignment.Left, - TextTransparency = props.transparency, - TextTruncate = Enum.TextTruncate.AtEnd, - Size = UDim2.new(0.3, 0, 1, 0), - LayoutOrder = 1, - }), - Button = e("TextButton", { - Text = "", - Size = UDim2.new(0.7, 0, 1, -4), - LayoutOrder = 2, - BackgroundTransparency = 1, - [Roact.Event.Activated] = function() - if props.showSourceDiff then - props.showSourceDiff(tostring(values[2]), tostring(values[3])) - end - end, - }, { - e(BorderedContainer, { - size = UDim2.new(1, 0, 1, 0), - transparency = self.props.transparency:map(function(t) - return 0.5 + (0.5 * t) - end), - }, { - Layout = e("UIListLayout", { - FillDirection = Enum.FillDirection.Horizontal, - SortOrder = Enum.SortOrder.LayoutOrder, - HorizontalAlignment = Enum.HorizontalAlignment.Center, - VerticalAlignment = Enum.VerticalAlignment.Center, - Padding = UDim.new(0, 5), - }), - Label = e("TextLabel", { - Text = "View Diff", - BackgroundTransparency = 1, - Font = Enum.Font.GothamMedium, - TextSize = 14, - TextColor3 = theme.Settings.Setting.DescriptionColor, - TextXAlignment = Enum.TextXAlignment.Left, - TextTransparency = props.transparency, - TextTruncate = Enum.TextTruncate.AtEnd, - Size = UDim2.new(0, 65, 1, 0), - LayoutOrder = 1, - }), - Icon = e("ImageLabel", { - Image = Assets.Images.Icons.Expand, - ImageColor3 = theme.Settings.Setting.DescriptionColor, - ImageTransparency = self.props.transparency, - - Size = UDim2.new(0, 16, 0, 16), - Position = UDim2.new(0.5, 0, 0.5, 0), - AnchorPoint = Vector2.new(0.5, 0.5), - - BackgroundTransparency = 1, - LayoutOrder = 2, - }), - }), - }), - }) - continue - end - rows[row] = e("Frame", { Size = UDim2.new(1, 0, 0, 30), BackgroundTransparency = row % 2 ~= 0 and rowTransparency or 1, @@ -192,7 +227,7 @@ function ChangeList:render() HorizontalAlignment = Enum.HorizontalAlignment.Left, VerticalAlignment = Enum.VerticalAlignment.Center, }), - A = e("TextLabel", { + ColumnA = e("TextLabel", { Text = (if isWarning then "⚠ " else "") .. tostring(values[1]), BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, @@ -204,32 +239,13 @@ function ChangeList:render() Size = UDim2.new(0.3, 0, 1, 0), LayoutOrder = 1, }), - B = e( - "Frame", - { - BackgroundTransparency = 1, - Size = UDim2.new(0.35, 0, 1, 0), - LayoutOrder = 2, - }, - e(DisplayValue, { - value = values[2], - transparency = props.transparency, - textColor = if isWarning then theme.Diff.Warning else theme.Settings.Setting.DescriptionColor, - }) - ), - C = e( - "Frame", - { - BackgroundTransparency = 1, - Size = UDim2.new(0.35, 0, 1, 0), - LayoutOrder = 3, - }, - e(DisplayValue, { - value = values[3], - transparency = props.transparency, - textColor = if isWarning then theme.Diff.Warning else theme.Settings.Setting.DescriptionColor, - }) - ), + Content = e(RowContent, { + values = values, + metadata = metadata, + transparency = props.transparency, + showStringDiff = props.showStringDiff, + showTableDiff = props.showTableDiff, + }), }) end diff --git a/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua b/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua index a231b879..c6664a14 100644 --- a/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua +++ b/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua @@ -30,7 +30,7 @@ local function DisplayValue(props) }), }), Label = e("TextLabel", { - Text = string.format("%d,%d,%d", props.value.R * 255, props.value.G * 255, props.value.B * 255), + Text = string.format("%d, %d, %d", props.value.R * 255, props.value.G * 255, props.value.B * 255), BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, TextSize = 14, @@ -104,8 +104,13 @@ local function DisplayValue(props) -- Or special text handling tostring for some? -- Will add as needed, let's see what cases arise. + local textRepresentation = string.gsub(tostring(props.value), "%s", " ") + if t == "string" then + textRepresentation = '"' .. textRepresentation .. '"' + end + return e("TextLabel", { - Text = string.gsub(tostring(props.value), "%s", " "), + Text = textRepresentation, BackgroundTransparency = 1, Font = Enum.Font.GothamMedium, TextSize = 14, diff --git a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua index f15931f6..b2d9afe0 100644 --- a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua +++ b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua @@ -34,7 +34,8 @@ function Expansion:render() ChangeList = e(ChangeList, { changes = props.changeList, transparency = props.transparency, - showSourceDiff = props.showSourceDiff, + showStringDiff = props.showStringDiff, + showTableDiff = props.showTableDiff, }), }) end @@ -171,7 +172,8 @@ function DomLabel:render() indent = indent, transparency = props.transparency, changeList = props.changeList, - showSourceDiff = props.showSourceDiff, + showStringDiff = props.showStringDiff, + showTableDiff = props.showTableDiff, }) else nil, DiffIcon = if props.patchType diff --git a/plugin/src/App/Components/PatchVisualizer/init.lua b/plugin/src/App/Components/PatchVisualizer/init.lua index 59cbe09b..67a4d7b2 100644 --- a/plugin/src/App/Components/PatchVisualizer/init.lua +++ b/plugin/src/App/Components/PatchVisualizer/init.lua @@ -76,7 +76,8 @@ function PatchVisualizer:render() changeList = node.changeList, depth = depth, transparency = self.props.transparency, - showSourceDiff = self.props.showSourceDiff, + showStringDiff = self.props.showStringDiff, + showTableDiff = self.props.showTableDiff, }) ) end diff --git a/plugin/src/App/Components/ScrollingFrame.lua b/plugin/src/App/Components/ScrollingFrame.lua index f3d11c8c..f2113be0 100644 --- a/plugin/src/App/Components/ScrollingFrame.lua +++ b/plugin/src/App/Components/ScrollingFrame.lua @@ -10,6 +10,12 @@ local bindingUtil = require(Plugin.App.bindingUtil) local e = Roact.createElement +local scrollDirToAutoSize = { + [Enum.ScrollingDirection.X] = Enum.AutomaticSize.X, + [Enum.ScrollingDirection.Y] = Enum.AutomaticSize.Y, + [Enum.ScrollingDirection.XY] = Enum.AutomaticSize.XY, +} + local function ScrollingFrame(props) return Theme.with(function(theme) return e("ScrollingFrame", { @@ -28,16 +34,21 @@ local function ScrollingFrame(props) Size = props.size, Position = props.position, AnchorPoint = props.anchorPoint, - CanvasSize = props.contentSize:map(function(value) - return UDim2.new( - 0, - if (props.scrollingDirection and props.scrollingDirection ~= Enum.ScrollingDirection.Y) - then value.X - else 0, - 0, - value.Y - ) - end), + CanvasSize = if props.contentSize + then props.contentSize:map(function(value) + return UDim2.new( + 0, + if (props.scrollingDirection and props.scrollingDirection ~= Enum.ScrollingDirection.Y) + then value.X + else 0, + 0, + value.Y + ) + end) + else UDim2.new(), + AutomaticCanvasSize = if props.contentSize == nil + then scrollDirToAutoSize[props.scrollingDirection or Enum.ScrollingDirection.XY] + else nil, BorderSizePixel = 0, BackgroundTransparency = 1, diff --git a/plugin/src/App/Components/StringDiffVisualizer/init.lua b/plugin/src/App/Components/StringDiffVisualizer/init.lua index cbdc7dec..60eb49a3 100644 --- a/plugin/src/App/Components/StringDiffVisualizer/init.lua +++ b/plugin/src/App/Components/StringDiffVisualizer/init.lua @@ -52,7 +52,7 @@ function StringDiffVisualizer:updateScriptBackground() end function StringDiffVisualizer:didUpdate(previousProps) - if previousProps.oldText ~= self.props.oldText or previousProps.newText ~= self.props.newText then + if previousProps.oldString ~= self.props.oldString or previousProps.newString ~= self.props.newString then self:calculateContentSize() local add, remove = self:calculateDiffLines() self:setState({ @@ -63,28 +63,28 @@ function StringDiffVisualizer:didUpdate(previousProps) end function StringDiffVisualizer:calculateContentSize() - local oldText, newText = self.props.oldText, self.props.newText + local oldString, newString = self.props.oldString, self.props.newString - local oldTextBounds = TextService:GetTextSize(oldText, 16, Enum.Font.RobotoMono, Vector2.new(99999, 99999)) - local newTextBounds = TextService:GetTextSize(newText, 16, Enum.Font.RobotoMono, Vector2.new(99999, 99999)) + local oldStringBounds = TextService:GetTextSize(oldString, 16, Enum.Font.RobotoMono, Vector2.new(99999, 99999)) + local newStringBounds = TextService:GetTextSize(newString, 16, Enum.Font.RobotoMono, Vector2.new(99999, 99999)) self.setContentSize( - Vector2.new(math.max(oldTextBounds.X, newTextBounds.X), math.max(oldTextBounds.Y, newTextBounds.Y)) + Vector2.new(math.max(oldStringBounds.X, newStringBounds.X), math.max(oldStringBounds.Y, newStringBounds.Y)) ) end function StringDiffVisualizer:calculateDiffLines() - local oldText, newText = self.props.oldText, self.props.newText + local oldString, newString = self.props.oldString, self.props.newString -- Diff the two texts local startClock = os.clock() - local diffs = StringDiff.findDiffs(oldText, newText) + local diffs = StringDiff.findDiffs(oldString, newString) local stopClock = os.clock() Log.trace( "Diffing {} byte and {} byte strings took {} microseconds and found {} diff sections", - #oldText, - #newText, + #oldString, + #newString, math.round((stopClock - startClock) * 1000 * 1000), #diffs ) @@ -137,7 +137,7 @@ function StringDiffVisualizer:calculateDiffLines() end function StringDiffVisualizer:render() - local oldText, newText = self.props.oldText, self.props.newText + local oldString, newString = self.props.oldString, self.props.newString return Theme.with(function(theme) return e(BorderedContainer, { @@ -175,7 +175,7 @@ function StringDiffVisualizer:render() Source = e(CodeLabel, { size = UDim2.new(1, 0, 1, 0), position = UDim2.new(0, 0, 0, 0), - text = oldText, + text = oldString, lineBackground = theme.Diff.Remove, markedLines = self.state.remove, }), @@ -190,7 +190,7 @@ function StringDiffVisualizer:render() Source = e(CodeLabel, { size = UDim2.new(1, 0, 1, 0), position = UDim2.new(0, 0, 0, 0), - text = newText, + text = newString, lineBackground = theme.Diff.Add, markedLines = self.state.add, }), diff --git a/plugin/src/App/Components/TableDiffVisualizer/Array.lua b/plugin/src/App/Components/TableDiffVisualizer/Array.lua new file mode 100644 index 00000000..4fd56f3c --- /dev/null +++ b/plugin/src/App/Components/TableDiffVisualizer/Array.lua @@ -0,0 +1,192 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) + +local Assets = require(Plugin.Assets) +local Theme = require(Plugin.App.Theme) + +local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) +local DisplayValue = require(Plugin.App.Components.PatchVisualizer.DisplayValue) + +local e = Roact.createElement + +local Array = Roact.Component:extend("Array") + +function Array:init() + self:setState({ + diff = self:calculateDiff(), + }) +end + +function Array:calculateDiff() + --[[ + Find the indexes that are added or removed from the array, + and display them side by side with gaps for the indexes that + dont exist in the opposite array. + ]] + local oldTable, newTable = self.props.oldTable or {}, self.props.newTable or {} + + local i, j = 1, 1 + local diff = {} + + while i <= #oldTable and j <= #newTable do + if oldTable[i] == newTable[j] then + table.insert(diff, { oldTable[i], newTable[j] }) -- Unchanged + i += 1 + j += 1 + elseif not table.find(newTable, oldTable[i], j) then + table.insert(diff, { oldTable[i], nil }) -- Removal + i += 1 + elseif not table.find(oldTable, newTable[j], i) then + table.insert(diff, { nil, newTable[j] }) -- Addition + j += 1 + else + if table.find(newTable, oldTable[i], j) then + table.insert(diff, { nil, newTable[j] }) -- Addition + j += 1 + else + table.insert(diff, { oldTable[i], nil }) -- Removal + i += 1 + end + end + end + + -- Handle remaining elements + while i <= #oldTable do + table.insert(diff, { oldTable[i], nil }) -- Remaining Removals + i += 1 + end + while j <= #newTable do + table.insert(diff, { nil, newTable[j] }) -- Remaining Additions + j += 1 + end + + return diff +end + +function Array:didUpdate(previousProps) + if previousProps.oldTable ~= self.props.oldTable or previousProps.newTable ~= self.props.newTable then + self:setState({ + diff = self:calculateDiff(), + }) + end +end + +function Array:render() + return Theme.with(function(theme) + local diff = self.state.diff + local lines = table.create(#diff) + + for i, element in diff do + local oldValue = element[1] + local newValue = element[2] + + local patchType = if oldValue == nil then "Add" elseif newValue == nil then "Remove" else "Remain" + + table.insert( + lines, + e("Frame", { + Size = UDim2.new(1, 0, 0, 25), + BackgroundTransparency = if patchType == "Remain" then 1 else self.props.transparency, + BackgroundColor3 = if patchType == "Remain" then theme.Diff.Row else theme.Diff[patchType], + BorderSizePixel = 0, + LayoutOrder = i, + }, { + DiffIcon = if patchType ~= "Remain" + then e("ImageLabel", { + Image = Assets.Images.Diff[patchType], + ImageColor3 = theme.AddressEntry.PlaceholderColor, + ImageTransparency = self.props.transparency, + BackgroundTransparency = 1, + Size = UDim2.new(0, 15, 0, 15), + Position = UDim2.new(0, 7, 0.5, 0), + AnchorPoint = Vector2.new(0, 0.5), + }) + else nil, + Old = e("Frame", { + Size = UDim2.new(0.5, -30, 1, 0), + Position = UDim2.new(0, 30, 0, 0), + BackgroundTransparency = 1, + }, { + Display = if oldValue ~= nil + then e(DisplayValue, { + value = oldValue, + transparency = self.props.transparency, + textColor = theme.Settings.Setting.DescriptionColor, + }) + else nil, + }), + New = e("Frame", { + Size = UDim2.new(0.5, -10, 1, 0), + Position = UDim2.new(0.5, 5, 0, 0), + BackgroundTransparency = 1, + }, { + Display = if newValue ~= nil + then e(DisplayValue, { + value = newValue, + transparency = self.props.transparency, + textColor = theme.Settings.Setting.DescriptionColor, + }) + else nil, + }), + }) + ) + end + + return Roact.createFragment({ + Headers = e("Frame", { + Size = UDim2.new(1, 0, 0, 25), + BackgroundTransparency = self.props.transparency:map(function(t) + return 0.95 + (0.05 * t) + end), + BackgroundColor3 = theme.Diff.Row, + }, { + ColumnA = e("TextLabel", { + Size = UDim2.new(0.5, -30, 1, 0), + Position = UDim2.new(0, 30, 0, 0), + BackgroundTransparency = 1, + Text = "Old", + TextXAlignment = Enum.TextXAlignment.Left, + Font = Enum.Font.GothamBold, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextTruncate = Enum.TextTruncate.AtEnd, + }), + ColumnB = e("TextLabel", { + Size = UDim2.new(0.5, -10, 1, 0), + Position = UDim2.new(0.5, 5, 0, 0), + BackgroundTransparency = 1, + Text = "New", + TextXAlignment = Enum.TextXAlignment.Left, + Font = Enum.Font.GothamBold, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextTruncate = Enum.TextTruncate.AtEnd, + }), + Separator = e("Frame", { + Size = UDim2.new(1, 0, 0, 1), + Position = UDim2.new(0, 0, 1, 0), + BackgroundTransparency = 0, + BorderSizePixel = 0, + BackgroundColor3 = theme.BorderedContainer.BorderColor, + }), + }), + KeyValues = e(ScrollingFrame, { + position = UDim2.new(0, 1, 0, 25), + size = UDim2.new(1, -2, 1, -27), + scrollingDirection = Enum.ScrollingDirection.Y, + transparency = self.props.transparency, + }, { + Layout = e("UIListLayout", { + SortOrder = Enum.SortOrder.LayoutOrder, + VerticalAlignment = Enum.VerticalAlignment.Top, + }), + Lines = Roact.createFragment(lines), + }), + }) + end) +end + +return Array diff --git a/plugin/src/App/Components/TableDiffVisualizer/Dictionary.lua b/plugin/src/App/Components/TableDiffVisualizer/Dictionary.lua new file mode 100644 index 00000000..d0c32d96 --- /dev/null +++ b/plugin/src/App/Components/TableDiffVisualizer/Dictionary.lua @@ -0,0 +1,208 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) + +local Assets = require(Plugin.Assets) +local Theme = require(Plugin.App.Theme) + +local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) +local DisplayValue = require(Plugin.App.Components.PatchVisualizer.DisplayValue) + +local e = Roact.createElement + +local Dictionary = Roact.Component:extend("Dictionary") + +function Dictionary:init() + self:setState({ + diff = self:calculateDiff(), + }) +end + +function Dictionary:calculateDiff() + local oldTable, newTable = self.props.oldTable or {}, self.props.newTable or {} + + -- Diff the two tables and find the added keys, removed keys, and changed keys + local diff = {} + + for key, oldValue in oldTable do + local newValue = newTable[key] + if newValue == nil then + table.insert(diff, { + key = key, + patchType = "Remove", + }) + elseif newValue ~= oldValue then + -- Note: should this do some sort of deep comparison for various types? + table.insert(diff, { + key = key, + patchType = "Edit", + }) + else + table.insert(diff, { + key = key, + patchType = "Remain", + }) + end + end + for key in newTable do + if oldTable[key] == nil then + table.insert(diff, { + key = key, + patchType = "Add", + }) + end + end + + table.sort(diff, function(a, b) + return a.key < b.key + end) + + return diff +end + +function Dictionary:didUpdate(previousProps) + if previousProps.oldTable ~= self.props.oldTable or previousProps.newTable ~= self.props.newTable then + self:setState({ + diff = self:calculateDiff(), + }) + end +end + +function Dictionary:render() + local oldTable, newTable = self.props.oldTable or {}, self.props.newTable or {} + local diff = self.state.diff + + return Theme.with(function(theme) + local lines = table.create(#diff) + for order, line in diff do + local key = line.key + local oldValue = oldTable[key] + local newValue = newTable[key] + + table.insert( + lines, + e("Frame", { + Size = UDim2.new(1, 0, 0, 25), + LayoutOrder = order, + BorderSizePixel = 0, + BackgroundTransparency = if line.patchType == "Remain" then 1 else self.props.transparency, + BackgroundColor3 = if line.patchType == "Remain" + then theme.Diff.Row + else theme.Diff[line.patchType], + }, { + DiffIcon = if line.patchType ~= "Remain" + then e("ImageLabel", { + Image = Assets.Images.Diff[line.patchType], + ImageColor3 = theme.AddressEntry.PlaceholderColor, + ImageTransparency = self.props.transparency, + BackgroundTransparency = 1, + Size = UDim2.new(0, 15, 0, 15), + Position = UDim2.new(0, 7, 0.5, 0), + AnchorPoint = Vector2.new(0, 0.5), + }) + else nil, + KeyName = e("TextLabel", { + Size = UDim2.new(0.3, -15, 1, 0), + Position = UDim2.new(0, 30, 0, 0), + BackgroundTransparency = 1, + Text = key, + TextXAlignment = Enum.TextXAlignment.Left, + Font = Enum.Font.GothamMedium, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextTruncate = Enum.TextTruncate.AtEnd, + }), + OldValue = e("Frame", { + Size = UDim2.new(0.35, -7, 1, 0), + Position = UDim2.new(0.3, 15, 0, 0), + BackgroundTransparency = 1, + }, { + e(DisplayValue, { + value = oldValue, + transparency = self.props.transparency, + textColor = theme.Settings.Setting.DescriptionColor, + }), + }), + NewValue = e("Frame", { + Size = UDim2.new(0.35, -8, 1, 0), + Position = UDim2.new(0.65, 8, 0, 0), + BackgroundTransparency = 1, + }, { + e(DisplayValue, { + value = newValue, + transparency = self.props.transparency, + textColor = theme.Settings.Setting.DescriptionColor, + }), + }), + }) + ) + end + + return Roact.createFragment({ + Headers = e("Frame", { + Size = UDim2.new(1, 0, 0, 25), + BackgroundTransparency = self.props.transparency:map(function(t) + return 0.95 + (0.05 * t) + end), + BackgroundColor3 = theme.Diff.Row, + }, { + ColumnA = e("TextLabel", { + Size = UDim2.new(0.3, -15, 1, 0), + Position = UDim2.new(0, 30, 0, 0), + BackgroundTransparency = 1, + Text = "Key", + TextXAlignment = Enum.TextXAlignment.Left, + Font = Enum.Font.GothamBold, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextTruncate = Enum.TextTruncate.AtEnd, + }), + ColumnB = e("TextLabel", { + Size = UDim2.new(0.35, -7, 1, 0), + Position = UDim2.new(0.3, 15, 0, 0), + BackgroundTransparency = 1, + Text = "Old", + TextXAlignment = Enum.TextXAlignment.Left, + Font = Enum.Font.GothamBold, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextTruncate = Enum.TextTruncate.AtEnd, + }), + ColumnC = e("TextLabel", { + Size = UDim2.new(0.35, -8, 1, 0), + Position = UDim2.new(0.65, 8, 0, 0), + BackgroundTransparency = 1, + Text = "New", + TextXAlignment = Enum.TextXAlignment.Left, + Font = Enum.Font.GothamBold, + TextSize = 14, + TextColor3 = theme.Settings.Setting.DescriptionColor, + TextTruncate = Enum.TextTruncate.AtEnd, + }), + Separator = e("Frame", { + Size = UDim2.new(1, 0, 0, 1), + Position = UDim2.new(0, 0, 1, 0), + BackgroundTransparency = 0, + BorderSizePixel = 0, + BackgroundColor3 = theme.BorderedContainer.BorderColor, + }), + }), + KeyValues = e(ScrollingFrame, { + position = UDim2.new(0, 1, 0, 25), + size = UDim2.new(1, -2, 1, -27), + scrollingDirection = Enum.ScrollingDirection.Y, + transparency = self.props.transparency, + }, { + Layout = e("UIListLayout", { + SortOrder = Enum.SortOrder.LayoutOrder, + VerticalAlignment = Enum.VerticalAlignment.Top, + }), + Lines = Roact.createFragment(lines), + }), + }) + end) +end + +return Dictionary diff --git a/plugin/src/App/Components/TableDiffVisualizer/init.lua b/plugin/src/App/Components/TableDiffVisualizer/init.lua new file mode 100644 index 00000000..2a1218a7 --- /dev/null +++ b/plugin/src/App/Components/TableDiffVisualizer/init.lua @@ -0,0 +1,48 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) + +local BorderedContainer = require(Plugin.App.Components.BorderedContainer) +local Array = require(script:FindFirstChild("Array")) +local Dictionary = require(script:FindFirstChild("Dictionary")) + +local e = Roact.createElement + +local TableDiffVisualizer = Roact.Component:extend("TableDiffVisualizer") + +function TableDiffVisualizer:render() + local oldTable, newTable = self.props.oldTable or {}, self.props.newTable or {} + + -- Ensure we're diffing tables, not mixing types + if type(oldTable) ~= "table" then + oldTable = {} + end + if type(newTable) ~= "table" then + newTable = {} + end + + local isArray = next(newTable) == 1 or next(oldTable) == 1 + + return e(BorderedContainer, { + size = self.props.size, + position = self.props.position, + anchorPoint = self.props.anchorPoint, + transparency = self.props.transparency, + }, { + Content = if isArray + then e(Array, { + oldTable = oldTable, + newTable = newTable, + transparency = self.props.transparency, + }) + else e(Dictionary, { + oldTable = oldTable, + newTable = newTable, + transparency = self.props.transparency, + }), + }) +end + +return TableDiffVisualizer diff --git a/plugin/src/App/StatusPages/Confirming.lua b/plugin/src/App/StatusPages/Confirming.lua index ca5bfba0..e5b272fd 100644 --- a/plugin/src/App/StatusPages/Confirming.lua +++ b/plugin/src/App/StatusPages/Confirming.lua @@ -14,6 +14,7 @@ local StudioPluginGui = require(Plugin.App.Components.Studio.StudioPluginGui) local Tooltip = require(Plugin.App.Components.Tooltip) local PatchVisualizer = require(Plugin.App.Components.PatchVisualizer) local StringDiffVisualizer = require(Plugin.App.Components.StringDiffVisualizer) +local TableDiffVisualizer = require(Plugin.App.Components.TableDiffVisualizer) local e = Roact.createElement @@ -24,9 +25,12 @@ function ConfirmingPage:init() self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0)) self:setState({ - showingSourceDiff = false, - oldSource = "", - newSource = "", + showingStringDiff = false, + oldString = "", + newString = "", + showingTableDiff = false, + oldTable = {}, + newTable = {}, }) end @@ -63,11 +67,18 @@ function ConfirmingPage:render() patch = self.props.confirmData.patch, instanceMap = self.props.confirmData.instanceMap, - showSourceDiff = function(oldSource: string, newSource: string) + showStringDiff = function(oldString: string, newString: string) self:setState({ - showingSourceDiff = true, - oldSource = oldSource, - newSource = newSource, + showingStringDiff = true, + oldString = oldString, + newString = newString, + }) + end, + showTableDiff = function(oldTable: { [any]: any? }, newTable: { [any]: any? }) + self:setState({ + showingTableDiff = true, + oldTable = oldTable, + newTable = newTable, }) end, }), @@ -136,10 +147,10 @@ function ConfirmingPage:render() PaddingRight = UDim.new(0, 20), }), - SourceDiff = e(StudioPluginGui, { - id = "Rojo_ConfirmingSourceDiff", - title = "Source diff", - active = self.state.showingSourceDiff, + StringDiff = e(StudioPluginGui, { + id = "Rojo_ConfirmingStringDiff", + title = "String diff", + active = self.state.showingStringDiff, isEphemeral = true, initDockState = Enum.InitialDockState.Float, @@ -151,7 +162,7 @@ function ConfirmingPage:render() onClose = function() self:setState({ - showingSourceDiff = false, + showingStringDiff = false, }) end, }, { @@ -167,8 +178,46 @@ function ConfirmingPage:render() anchorPoint = Vector2.new(0, 0), transparency = self.props.transparency, - oldText = self.state.oldSource, - newText = self.state.newSource, + oldString = self.state.oldString, + newString = self.state.newString, + }), + }), + }), + }), + + TableDiff = e(StudioPluginGui, { + id = "Rojo_ConfirmingTableDiff", + title = "Table diff", + active = self.state.showingTableDiff, + isEphemeral = true, + + initDockState = Enum.InitialDockState.Float, + overridePreviousState = true, + floatingSize = Vector2.new(500, 350), + minimumSize = Vector2.new(400, 250), + + zIndexBehavior = Enum.ZIndexBehavior.Sibling, + + onClose = function() + self:setState({ + showingTableDiff = false, + }) + end, + }, { + TooltipsProvider = e(Tooltip.Provider, nil, { + Tooltips = e(Tooltip.Container, nil), + Content = e("Frame", { + Size = UDim2.fromScale(1, 1), + BackgroundTransparency = 1, + }, { + e(TableDiffVisualizer, { + size = UDim2.new(1, -10, 1, -10), + position = UDim2.new(0, 5, 0, 5), + anchorPoint = Vector2.new(0, 0), + transparency = self.props.transparency, + + oldTable = self.state.oldTable, + newTable = self.state.newTable, }), }), }), diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index c1aafbe6..d8055b3f 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -18,6 +18,7 @@ local BorderedContainer = require(Plugin.App.Components.BorderedContainer) local Tooltip = require(Plugin.App.Components.Tooltip) local PatchVisualizer = require(Plugin.App.Components.PatchVisualizer) local StringDiffVisualizer = require(Plugin.App.Components.StringDiffVisualizer) +local TableDiffVisualizer = require(Plugin.App.Components.TableDiffVisualizer) local e = Roact.createElement @@ -97,7 +98,8 @@ function ChangesDrawer:render() patchTree = self.props.patchTree, - showSourceDiff = self.props.showSourceDiff, + showStringDiff = self.props.showStringDiff, + showTableDiff = self.props.showTableDiff, }), }) end) @@ -239,9 +241,9 @@ function ConnectedPage:init() self:setState({ renderChanges = false, hoveringChangeInfo = false, - showingSourceDiff = false, - oldSource = "", - newSource = "", + showingStringDiff = false, + oldString = "", + newString = "", }) self.changeInfoText, self.setChangeInfoText = Roact.createBinding("") @@ -258,7 +260,7 @@ function ConnectedPage:didUpdate(previousProps) -- New patch recieved self:startChangeInfoTextUpdater() self:setState({ - showingSourceDiff = false, + showingStringDiff = false, }) end end @@ -387,11 +389,18 @@ function ConnectedPage:render() height = self.changeDrawerHeight, layoutOrder = 5, - showSourceDiff = function(oldSource: string, newSource: string) + showStringDiff = function(oldString: string, newString: string) self:setState({ - showingSourceDiff = true, - oldSource = oldSource, - newSource = newSource, + showingStringDiff = true, + oldString = oldString, + newString = newString, + }) + end, + showTableDiff = function(oldTable: { [any]: any? }, newTable: { [any]: any? }) + self:setState({ + showingTableDiff = true, + oldTable = oldTable, + newTable = newTable, }) end, @@ -403,10 +412,10 @@ function ConnectedPage:render() end, }), - SourceDiff = e(StudioPluginGui, { - id = "Rojo_ConnectedSourceDiff", - title = "Source diff", - active = self.state.showingSourceDiff, + StringDiff = e(StudioPluginGui, { + id = "Rojo_ConnectedStringDiff", + title = "String diff", + active = self.state.showingStringDiff, isEphemeral = true, initDockState = Enum.InitialDockState.Float, @@ -418,7 +427,7 @@ function ConnectedPage:render() onClose = function() self:setState({ - showingSourceDiff = false, + showingStringDiff = false, }) end, }, { @@ -434,8 +443,46 @@ function ConnectedPage:render() anchorPoint = Vector2.new(0, 0), transparency = self.props.transparency, - oldText = self.state.oldSource, - newText = self.state.newSource, + oldString = self.state.oldString, + newString = self.state.newString, + }), + }), + }), + }), + + TableDiff = e(StudioPluginGui, { + id = "Rojo_ConnectedTableDiff", + title = "Table diff", + active = self.state.showingTableDiff, + isEphemeral = true, + + initDockState = Enum.InitialDockState.Float, + overridePreviousState = false, + floatingSize = Vector2.new(500, 350), + minimumSize = Vector2.new(400, 250), + + zIndexBehavior = Enum.ZIndexBehavior.Sibling, + + onClose = function() + self:setState({ + showingTableDiff = false, + }) + end, + }, { + TooltipsProvider = e(Tooltip.Provider, nil, { + Tooltips = e(Tooltip.Container, nil), + Content = e("Frame", { + Size = UDim2.fromScale(1, 1), + BackgroundTransparency = 1, + }, { + e(TableDiffVisualizer, { + size = UDim2.new(1, -10, 1, -10), + position = UDim2.new(0, 5, 0, 5), + anchorPoint = Vector2.new(0, 0), + transparency = self.props.transparency, + + oldTable = self.state.oldTable, + newTable = self.state.newTable, }), }), }), From 506a60d0be2f14bb216975ab4a446162fce630d2 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Tue, 30 Jan 2024 12:51:45 -0800 Subject: [PATCH 1371/1504] Play Solo & Test Server auto connect (#840) When enabled, the `baseurl` of the session is written to `workspace:SetAttribute("__Rojo_ConnectionUrl")` so that the test server can connect to that session automatically. This works for Play Solo and Local Test Server. It is marked experimental for now (and disabled by default) since connecting during a playtest session is... not polished. Rojo may overwrite things and cause headaches. Further work can be done later. --- CHANGELOG.md | 2 + plugin/src/App/StatusPages/Settings/init.lua | 35 ++++++--- plugin/src/App/init.lua | 76 ++++++++++++++++++-- plugin/src/Settings.lua | 1 + 4 files changed, 99 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 70a7d5a8..efc9405a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ ## Unreleased Changes * Added popout diff visualizer for table properties like Attributes and Tags ([#834]) * Updated Theme to use Studio colors ([#838]) +* Added experimental setting for Auto Connect in playtests ([#840]) * Projects may now specify rules for syncing files as if they had a different file extension. ([#813]) This is specified via a new field on project files, `syncRules`: @@ -53,6 +54,7 @@ [#813]: https://github.com/rojo-rbx/rojo/pull/813 [#834]: https://github.com/rojo-rbx/rojo/pull/834 [#838]: https://github.com/rojo-rbx/rojo/pull/838 +[#840]: https://github.com/rojo-rbx/rojo/pull/840 ## [7.4.0] - January 16, 2024 * Improved the visualization for array properties like Tags ([#829]) diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua index 688be85a..a33eb1b5 100644 --- a/plugin/src/App/StatusPages/Settings/init.lua +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -75,6 +75,12 @@ function SettingsPage:init() end function SettingsPage:render() + local layoutOrder = 0 + local function layoutIncrement() + layoutOrder += 1 + return layoutOrder + end + return Theme.with(function(theme) theme = theme.Settings @@ -86,7 +92,7 @@ function SettingsPage:render() Navbar = e(Navbar, { onBack = self.props.onBack, transparency = self.props.transparency, - layoutOrder = 0, + layoutOrder = layoutIncrement(), }), ShowNotifications = e(Setting, { @@ -94,7 +100,7 @@ function SettingsPage:render() name = "Show Notifications", description = "Popup notifications in viewport", transparency = self.props.transparency, - layoutOrder = 1, + layoutOrder = layoutIncrement(), }), SyncReminder = e(Setting, { @@ -103,7 +109,7 @@ function SettingsPage:render() description = "Notify to sync when opening a place that has previously been synced", transparency = self.props.transparency, visible = Settings:getBinding("showNotifications"), - layoutOrder = 2, + layoutOrder = layoutIncrement(), }), ConfirmationBehavior = e(Setting, { @@ -111,7 +117,7 @@ function SettingsPage:render() name = "Confirmation Behavior", description = "When to prompt for confirmation before syncing", transparency = self.props.transparency, - layoutOrder = 3, + layoutOrder = layoutIncrement(), options = confirmationBehaviors, }), @@ -121,7 +127,7 @@ function SettingsPage:render() name = "Confirmation Threshold", description = "How many modified instances to be considered a large change", transparency = self.props.transparency, - layoutOrder = 4, + layoutOrder = layoutIncrement(), visible = Settings:getBinding("confirmationBehavior"):map(function(value) return value == "Large Changes" end), @@ -152,7 +158,16 @@ function SettingsPage:render() name = "Play Sounds", description = "Toggle sound effects", transparency = self.props.transparency, - layoutOrder = 5, + layoutOrder = layoutIncrement(), + }), + + AutoConnectPlaytestServer = e(Setting, { + id = "autoConnectPlaytestServer", + name = "Auto Connect Playtest Server", + description = "Automatically connect game server to Rojo when playtesting while connected in Edit", + experimental = true, + transparency = self.props.transparency, + layoutOrder = layoutIncrement(), }), OpenScriptsExternally = e(Setting, { @@ -162,7 +177,7 @@ function SettingsPage:render() locked = self.props.syncActive, experimental = true, transparency = self.props.transparency, - layoutOrder = 6, + layoutOrder = layoutIncrement(), }), TwoWaySync = e(Setting, { @@ -172,7 +187,7 @@ function SettingsPage:render() locked = self.props.syncActive, experimental = true, transparency = self.props.transparency, - layoutOrder = 7, + layoutOrder = layoutIncrement(), }), LogLevel = e(Setting, { @@ -180,7 +195,7 @@ function SettingsPage:render() name = "Log Level", description = "Plugin output verbosity level", transparency = self.props.transparency, - layoutOrder = 100, + layoutOrder = layoutIncrement(), options = invertedLevels, showReset = Settings:getBinding("logLevel"):map(function(value) @@ -196,7 +211,7 @@ function SettingsPage:render() name = "Typechecking", description = "Toggle typechecking on the API surface", transparency = self.props.transparency, - layoutOrder = 101, + layoutOrder = layoutIncrement(), }), Layout = e("UIListLayout", { diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index 22f277f9..ecb807f0 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -158,11 +158,29 @@ function App:init() }, }) end + + if self:isAutoConnectPlaytestServerAvailable() then + self:useRunningConnectionInfo() + self:startSession() + end + self.autoConnectPlaytestServerListener = Settings:onChanged("autoConnectPlaytestServer", function(enabled) + if enabled then + if self:isAutoConnectPlaytestServerWriteable() and self.serveSession ~= nil then + -- Write the existing session + local baseUrl = self.serveSession.__apiContext.__baseUrl + self:setRunningConnectionInfo(baseUrl) + end + else + self:clearRunningConnectionInfo() + end + end) end function App:willUnmount() self.waypointConnection:Disconnect() self.confirmationBindable:Destroy() + self.autoConnectPlaytestServerListener() + self:clearRunningConnectionInfo() end function App:addNotification( @@ -278,10 +296,7 @@ function App:getHostAndPort() local host = self.host:getValue() local port = self.port:getValue() - local host = if #host > 0 then host else Config.defaultHost - local port = if #port > 0 then port else Config.defaultPort - - return host, port + return if #host > 0 then host else Config.defaultHost, if #port > 0 then port else Config.defaultPort end function App:isSyncLockAvailable() @@ -349,6 +364,49 @@ function App:releaseSyncLock() Log.trace("Could not relase sync lock because it is owned by {}", lock.Value) end +function App:isAutoConnectPlaytestServerAvailable() + return RunService:IsRunMode() + and RunService:IsServer() + and Settings:get("autoConnectPlaytestServer") + and workspace:GetAttribute("__Rojo_ConnectionUrl") +end + +function App:isAutoConnectPlaytestServerWriteable() + return RunService:IsEdit() and Settings:get("autoConnectPlaytestServer") +end + +function App:setRunningConnectionInfo(baseUrl: string) + if not self:isAutoConnectPlaytestServerWriteable() then + return + end + + Log.trace("Setting connection info for play solo auto-connect") + workspace:SetAttribute("__Rojo_ConnectionUrl", baseUrl) +end + +function App:clearRunningConnectionInfo() + if not RunService:IsEdit() then + -- Only write connection info from edit mode + return + end + + Log.trace("Clearing connection info for play solo auto-connect") + workspace:SetAttribute("__Rojo_ConnectionUrl", nil) +end + +function App:useRunningConnectionInfo() + local connectionInfo = workspace:GetAttribute("__Rojo_ConnectionUrl") + if not connectionInfo then + return + end + + Log.trace("Using connection info for play solo auto-connect") + local host, port = string.match(connectionInfo, "^(.+):(.-)$") + + self.setHost(host) + self.setPort(port) +end + function App:startSession() local claimedLock, priorOwner = self:claimSyncLock() if not claimedLock then @@ -441,6 +499,7 @@ function App:startSession() self:addNotification("Connecting to session...") elseif status == ServeSession.Status.Connected then self.knownProjects[details] = true + self:setRunningConnectionInfo(baseUrl) local address = ("%s:%s"):format(host, port) self:setState({ @@ -453,6 +512,7 @@ function App:startSession() elseif status == ServeSession.Status.Disconnected then self.serveSession = nil self:releaseSyncLock() + self:clearRunningConnectionInfo() self:setState({ patchData = { patch = PatchSet.newEmpty(), @@ -488,6 +548,12 @@ function App:startSession() return "Accept" end + -- Play solo auto-connect does not require confirmation + if self:isAutoConnectPlaytestServerAvailable() then + Log.trace("Accepting patch without confirmation because play solo auto-connect is enabled") + return "Accept" + end + local confirmationBehavior = Settings:get("confirmationBehavior") if confirmationBehavior == "Initial" then -- Only confirm if we haven't synced this project yet this session @@ -603,7 +669,7 @@ function App:render() value = self.props.plugin, }, { e(Theme.StudioProvider, nil, { - e(Tooltip.Provider, nil, { + tooltip = e(Tooltip.Provider, nil, { gui = e(StudioPluginGui, { id = pluginName, title = pluginName, diff --git a/plugin/src/Settings.lua b/plugin/src/Settings.lua index 194dd4c7..b5be22a7 100644 --- a/plugin/src/Settings.lua +++ b/plugin/src/Settings.lua @@ -14,6 +14,7 @@ local defaultSettings = { twoWaySync = false, showNotifications = true, syncReminder = true, + autoConnectPlaytestServer = false, confirmationBehavior = "Initial", largeChangesConfirmationThreshold = 5, playSounds = true, From 106a01223e84c4dcf40ab5cbf7fb164e832d6b63 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 31 Jan 2024 14:45:28 -0800 Subject: [PATCH 1372/1504] Show failed additions and removals in visualizer (#844) --- plugin/src/PatchTree.lua | 74 ++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 15 deletions(-) diff --git a/plugin/src/PatchTree.lua b/plugin/src/PatchTree.lua index e67dbcd0..d68bdcd7 100644 --- a/plugin/src/PatchTree.lua +++ b/plugin/src/PatchTree.lua @@ -426,22 +426,66 @@ function PatchTree.updateMetadata(tree, patch, instanceMap, unappliedPatch) -- Update isWarning metadata for _, failedChange in unappliedPatch.updated do local node = tree:getNode(failedChange.id) - if node then - node.isWarning = true - Log.trace("Marked node as warning: {} {}", node.id, node.name) - - if node.changeList then - for _, change in node.changeList do - if failedChange.changedProperties[change[1]] then - Log.trace(" Marked property as warning: {}", change[1]) - if change[4] == nil then - change[4] = {} - end - change[4].isWarning = true - end - end - end + if not node then + continue end + + node.isWarning = true + Log.trace("Marked node as warning: {} {}", node.id, node.name) + + if not node.changeList then + continue + end + for _, change in node.changeList do + if not failedChange.changedProperties[change[1]] then + -- This change didn't fail + continue + end + if change[4] == nil then + change[4] = { isWarning = true } + else + change[4].isWarning = true + end + Log.trace(" Marked property as warning: {}.{}", node.name, change[1]) + end + end + for failedAdditionId in unappliedPatch.added do + local node = tree:getNode(failedAdditionId) + if not node then + continue + end + + node.isWarning = true + Log.trace("Marked node as warning: {} {}", node.id, node.name) + + if not node.changeList then + continue + end + for _, change in node.changeList do + -- Failed addition means that all properties failed to be added + if change[4] == nil then + change[4] = { isWarning = true } + else + change[4].isWarning = true + end + Log.trace(" Marked property as warning: {}.{}", node.name, change[1]) + end + end + for _, failedRemovalIdOrInstance in unappliedPatch.removed do + local failedRemovalId = if Types.RbxId(failedRemovalIdOrInstance) + then failedRemovalIdOrInstance + else instanceMap.fromInstances[failedRemovalIdOrInstance] + if not failedRemovalId then + continue + end + + local node = tree:getNode(failedRemovalId) + if not node then + continue + end + + node.isWarning = true + Log.trace("Marked node as warning: {} {}", node.id, node.name) end -- Update if instances exist From f3b0b0027ed41939e3eaeab760777ec4f085aac3 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 31 Jan 2024 17:07:01 -0800 Subject: [PATCH 1373/1504] Catch more sync failures (#845) - Catch removal failures - Catch name change failures - Don't remove IDs for instances if they weren't actually destroyed --- plugin/src/InstanceMap.lua | 22 ++++++++++++---------- plugin/src/PatchTree.lua | 11 ++++++++--- plugin/src/Reconciler/applyPatch.lua | 21 ++++++++++++++++----- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index 91a1d4cd..b035d423 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -113,27 +113,29 @@ end function InstanceMap:destroyInstance(instance) local id = self.fromInstances[instance] + local descendants = instance:GetDescendants() + instance:Destroy() + + -- After the instance is successfully destroyed, + -- we can remove all the id mappings + if id ~= nil then self:removeId(id) end - for _, descendantInstance in ipairs(instance:GetDescendants()) do + for _, descendantInstance in descendants do self:removeInstance(descendantInstance) end - - instance:Destroy() end function InstanceMap:destroyId(id) local instance = self.fromIds[id] - self:removeId(id) - if instance ~= nil then - for _, descendantInstance in ipairs(instance:GetDescendants()) do - self:removeInstance(descendantInstance) - end - - instance:Destroy() + self:destroyInstance(instance) + else + -- There is no instance with this id, so we can just remove the id + -- without worrying about instance destruction + self:removeId(id) end end diff --git a/plugin/src/PatchTree.lua b/plugin/src/PatchTree.lua index d68bdcd7..e469e211 100644 --- a/plugin/src/PatchTree.lua +++ b/plugin/src/PatchTree.lua @@ -437,8 +437,13 @@ function PatchTree.updateMetadata(tree, patch, instanceMap, unappliedPatch) continue end for _, change in node.changeList do - if not failedChange.changedProperties[change[1]] then - -- This change didn't fail + local property = change[1] + local propertyFailedToApply = if property == "Name" + then failedChange.changedName ~= nil -- Name is not in changedProperties, so it needs a special case + else failedChange.changedProperties[property] ~= nil + + if not propertyFailedToApply then + -- This change didn't fail, no need to mark continue end if change[4] == nil then @@ -446,7 +451,7 @@ function PatchTree.updateMetadata(tree, patch, instanceMap, unappliedPatch) else change[4].isWarning = true end - Log.trace(" Marked property as warning: {}.{}", node.name, change[1]) + Log.trace(" Marked property as warning: {}.{}", node.name, property) end end for failedAdditionId in unappliedPatch.added do diff --git a/plugin/src/Reconciler/applyPatch.lua b/plugin/src/Reconciler/applyPatch.lua index 4faa7310..a66be3a2 100644 --- a/plugin/src/Reconciler/applyPatch.lua +++ b/plugin/src/Reconciler/applyPatch.lua @@ -25,10 +25,15 @@ local function applyPatch(instanceMap, patch) local unappliedPatch = PatchSet.newEmpty() for _, removedIdOrInstance in ipairs(patch.removed) do - if Types.RbxId(removedIdOrInstance) then - instanceMap:destroyId(removedIdOrInstance) - else - instanceMap:destroyInstance(removedIdOrInstance) + local ok = pcall(function() + if Types.RbxId(removedIdOrInstance) then + instanceMap:destroyId(removedIdOrInstance) + else + instanceMap:destroyInstance(removedIdOrInstance) + end + end) + if not ok then + table.insert(unappliedPatch.removed, removedIdOrInstance) end end @@ -170,7 +175,13 @@ local function applyPatch(instanceMap, patch) end if update.changedName ~= nil then - instance.Name = update.changedName + local ok = pcall(function() + instance.Name = update.changedName + end) + if not ok then + unappliedUpdate.changedName = update.changedName + partiallyApplied = true + end end if update.changedMetadata ~= nil then From df707d5bef310ff5c8fdd025ada9c20d33b7eeeb Mon Sep 17 00:00:00 2001 From: boatbomber Date: Wed, 31 Jan 2024 21:08:07 -0800 Subject: [PATCH 1374/1504] Lint plugin src (#846) --- .github/workflows/ci.yml | 5 +- aftman.toml | 2 +- plugin/src/ApiContext.lua | 6 +-- plugin/src/App/Components/Dropdown.lua | 2 +- .../PatchVisualizer/DisplayValue.lua | 2 +- .../Components/PatchVisualizer/DomLabel.lua | 19 +++---- plugin/src/App/Components/TextButton.lua | 4 +- plugin/src/App/StatusPages/Confirming.lua | 2 - plugin/src/App/Theme.lua | 1 - plugin/src/Reconciler/applyPatch.lua | 16 +++--- plugin/src/Reconciler/decodeValue.lua | 4 +- plugin/src/Reconciler/diff.lua | 17 +++--- plugin/src/Reconciler/hydrate.lua | 4 +- plugin/src/Reconciler/reify.lua | 16 +++--- plugin/src/Reconciler/reify.spec.lua | 1 - plugin/src/Reconciler/setProperty.lua | 4 +- plugin/src/ServeSession.lua | 19 ++++--- plugin/src/createSignal.lua | 53 ------------------- 18 files changed, 62 insertions(+), 115 deletions(-) delete mode 100644 plugin/src/createSignal.lua diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 17205587..28565bb9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -72,7 +72,7 @@ jobs: run: cargo build --locked --verbose lint: - name: Rustfmt, Clippy, & Stylua + name: Rustfmt, Clippy, Stylua, & Selene runs-on: ubuntu-latest steps: @@ -98,6 +98,9 @@ jobs: - name: Stylua run: stylua --check plugin/src + - name: Selene + run: selene plugin/src + - name: Rustfmt run: cargo fmt -- --check diff --git a/aftman.toml b/aftman.toml index 86ad20fb..5273b6d0 100644 --- a/aftman.toml +++ b/aftman.toml @@ -1,5 +1,5 @@ [tools] rojo = "rojo-rbx/rojo@7.3.0" -selene = "Kampfkarren/selene@0.25.0" +selene = "Kampfkarren/selene@0.26.1" stylua = "JohnnyMorganz/stylua@0.18.2" run-in-roblox = "rojo-rbx/run-in-roblox@0.3.0" diff --git a/plugin/src/ApiContext.lua b/plugin/src/ApiContext.lua index 01b7ec45..68d43095 100644 --- a/plugin/src/ApiContext.lua +++ b/plugin/src/ApiContext.lua @@ -185,10 +185,10 @@ function ApiContext:write(patch) body = Http.jsonEncode(body) - return Http.post(url, body):andThen(rejectFailedRequests):andThen(Http.Response.json):andThen(function(body) - Log.info("Write response: {:?}", body) + return Http.post(url, body):andThen(rejectFailedRequests):andThen(Http.Response.json):andThen(function(responseBody) + Log.info("Write response: {:?}", responseBody) - return body + return responseBody end) end diff --git a/plugin/src/App/Components/Dropdown.lua b/plugin/src/App/Components/Dropdown.lua index 3fde88c5..a5dda6f2 100644 --- a/plugin/src/App/Components/Dropdown.lua +++ b/plugin/src/App/Components/Dropdown.lua @@ -165,7 +165,7 @@ function Dropdown:render() self.setContentSize(object.AbsoluteContentSize) end, }), - Roact.createFragment(optionButtons), + Options = Roact.createFragment(optionButtons), }), }) else nil, diff --git a/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua b/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua index c6664a14..f7e772b9 100644 --- a/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua +++ b/plugin/src/App/Components/PatchVisualizer/DisplayValue.lua @@ -57,7 +57,7 @@ local function DisplayValue(props) -- We don't need to support mixed tables, so checking the first key is enough -- to determine if it's a simple array local out, i = table.create(#props.value), 0 - for k, v in props.value do + for _, v in props.value do i += 1 -- Wrap strings in quotes diff --git a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua index b2d9afe0..41ec0b8e 100644 --- a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua +++ b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua @@ -98,21 +98,16 @@ function DomLabel:render() -- Line guides help indent depth remain readable local lineGuides = {} for i = 1, props.depth or 0 do - table.insert( - lineGuides, - e("Frame", { - Name = "Line_" .. i, - Size = UDim2.new(0, 2, 1, 2), - Position = UDim2.new(0, (20 * i) + 15, 0, -1), - BorderSizePixel = 0, - BackgroundTransparency = props.transparency, - BackgroundColor3 = theme.BorderedContainer.BorderColor, - }) - ) + lineGuides["Line_" .. i] = e("Frame", { + Size = UDim2.new(0, 2, 1, 2), + Position = UDim2.new(0, (20 * i) + 15, 0, -1), + BorderSizePixel = 0, + BackgroundTransparency = props.transparency, + BackgroundColor3 = theme.BorderedContainer.BorderColor, + }) end return e("Frame", { - Name = "Change", ClipsDescendants = true, BackgroundColor3 = if props.patchType then theme.Diff[props.patchType] else nil, BorderSizePixel = 0, diff --git a/plugin/src/App/Components/TextButton.lua b/plugin/src/App/Components/TextButton.lua index 2cfae5a2..bd643c79 100644 --- a/plugin/src/App/Components/TextButton.lua +++ b/plugin/src/App/Components/TextButton.lua @@ -42,7 +42,7 @@ end function TextButton:render() return Theme.with(function(theme) local textSize = - TextService:GetTextSize(self.props.text, 18, Enum.Font.GothamSemibold, Vector2.new(math.huge, math.huge)) + TextService:GetTextSize(self.props.text, 18, Enum.Font.GothamMedium, Vector2.new(math.huge, math.huge)) local style = self.props.style @@ -83,7 +83,7 @@ function TextButton:render() Text = e("TextLabel", { Text = self.props.text, - Font = Enum.Font.GothamSemibold, + Font = Enum.Font.GothamMedium, TextSize = 18, TextColor3 = bindingUtil.mapLerp(bindingEnabled, theme.Enabled.TextColor, theme.Disabled.TextColor), TextTransparency = self.props.transparency, diff --git a/plugin/src/App/StatusPages/Confirming.lua b/plugin/src/App/StatusPages/Confirming.lua index e5b272fd..d3b6baa2 100644 --- a/plugin/src/App/StatusPages/Confirming.lua +++ b/plugin/src/App/StatusPages/Confirming.lua @@ -1,5 +1,3 @@ -local TextService = game:GetService("TextService") - local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin local Packages = Rojo.Packages diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index 2ba8fc9d..f1e9c397 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -19,7 +19,6 @@ local Rojo = script:FindFirstAncestor("Rojo") local Packages = Rojo.Packages local Roact = require(Packages.Roact) -local Log = require(Packages.Log) local strict = require(script.Parent.Parent.strict) diff --git a/plugin/src/Reconciler/applyPatch.lua b/plugin/src/Reconciler/applyPatch.lua index a66be3a2..5ee6ed5e 100644 --- a/plugin/src/Reconciler/applyPatch.lua +++ b/plugin/src/Reconciler/applyPatch.lua @@ -25,14 +25,14 @@ local function applyPatch(instanceMap, patch) local unappliedPatch = PatchSet.newEmpty() for _, removedIdOrInstance in ipairs(patch.removed) do - local ok = pcall(function() + local removeInstanceSuccess = pcall(function() if Types.RbxId(removedIdOrInstance) then instanceMap:destroyId(removedIdOrInstance) else instanceMap:destroyInstance(removedIdOrInstance) end end) - if not ok then + if not removeInstanceSuccess then table.insert(unappliedPatch.removed, removedIdOrInstance) end end @@ -175,10 +175,10 @@ local function applyPatch(instanceMap, patch) end if update.changedName ~= nil then - local ok = pcall(function() + local setNameSuccess = pcall(function() instance.Name = update.changedName end) - if not ok then + if not setNameSuccess then unappliedUpdate.changedName = update.changedName partiallyApplied = true end @@ -194,15 +194,15 @@ local function applyPatch(instanceMap, patch) if update.changedProperties ~= nil then for propertyName, propertyValue in pairs(update.changedProperties) do - local ok, decodedValue = decodeValue(propertyValue, instanceMap) - if not ok then + local decodeSuccess, decodedValue = decodeValue(propertyValue, instanceMap) + if not decodeSuccess then unappliedUpdate.changedProperties[propertyName] = propertyValue partiallyApplied = true continue end - local ok = setProperty(instance, propertyName, decodedValue) - if not ok then + local setPropertySuccess = setProperty(instance, propertyName, decodedValue) + if not setPropertySuccess then unappliedUpdate.changedProperties[propertyName] = propertyValue partiallyApplied = true end diff --git a/plugin/src/Reconciler/decodeValue.lua b/plugin/src/Reconciler/decodeValue.lua index cd67e77d..9a171761 100644 --- a/plugin/src/Reconciler/decodeValue.lua +++ b/plugin/src/Reconciler/decodeValue.lua @@ -27,9 +27,9 @@ local function decodeValue(encodedValue, instanceMap) end end - local ok, decodedValue = RbxDom.EncodedValue.decode(encodedValue) + local decodeSuccess, decodedValue = RbxDom.EncodedValue.decode(encodedValue) - if not ok then + if not decodeSuccess then return false, Error.new(Error.CannotDecodeValue, { encodedValue = encodedValue, diff --git a/plugin/src/Reconciler/diff.lua b/plugin/src/Reconciler/diff.lua index 0bc772aa..e13b05c8 100644 --- a/plugin/src/Reconciler/diff.lua +++ b/plugin/src/Reconciler/diff.lua @@ -147,13 +147,13 @@ local function diff(instanceMap, virtualInstances, rootId) local changedProperties = {} for propertyName, virtualValue in pairs(virtualInstance.Properties) do - local ok, existingValueOrErr = getProperty(instance, propertyName) + local getProperySuccess, existingValueOrErr = getProperty(instance, propertyName) - if ok then + if getProperySuccess then local existingValue = existingValueOrErr - local ok, decodedValue = decodeValue(virtualValue, instanceMap) + local decodeSuccess, decodedValue = decodeValue(virtualValue, instanceMap) - if ok then + if decodeSuccess then if not trueEquals(existingValue, decodedValue) then Log.debug( "{}.{} changed from '{}' to '{}'", @@ -165,7 +165,6 @@ local function diff(instanceMap, virtualInstances, rootId) changedProperties[propertyName] = virtualValue end else - local propertyType = next(virtualValue) Log.warn( "Failed to decode property {}.{}. Encoded property was: {:#?}", virtualInstance.ClassName, @@ -220,9 +219,9 @@ local function diff(instanceMap, virtualInstances, rootId) table.insert(patch.removed, childInstance) end else - local ok, err = diffInternal(childId) + local diffSuccess, err = diffInternal(childId) - if not ok then + if not diffSuccess then return false, err end end @@ -243,9 +242,9 @@ local function diff(instanceMap, virtualInstances, rootId) return true end - local ok, err = diffInternal(rootId) + local diffSuccess, err = diffInternal(rootId) - if not ok then + if not diffSuccess then return false, err end diff --git a/plugin/src/Reconciler/hydrate.lua b/plugin/src/Reconciler/hydrate.lua index c2239179..353e7366 100644 --- a/plugin/src/Reconciler/hydrate.lua +++ b/plugin/src/Reconciler/hydrate.lua @@ -31,13 +31,13 @@ local function hydrate(instanceMap, virtualInstances, rootId, rootInstance) -- We guard accessing Name and ClassName in order to avoid -- tripping over children of DataModel that Rojo won't have -- permissions to access at all. - local ok, name, className = pcall(function() + local accessSuccess, name, className = pcall(function() return childInstance.Name, childInstance.ClassName end) -- This rule is very conservative and could be loosened in the -- future, or more heuristics could be introduced. - if ok and name == virtualChild.Name and className == virtualChild.ClassName then + if accessSuccess and name == virtualChild.Name and className == virtualChild.ClassName then isExistingChildVisited[childIndex] = true hydrate(instanceMap, virtualInstances, childId, childInstance) break diff --git a/plugin/src/Reconciler/reify.lua b/plugin/src/Reconciler/reify.lua index 3c396573..9fbe4c9c 100644 --- a/plugin/src/Reconciler/reify.lua +++ b/plugin/src/Reconciler/reify.lua @@ -53,9 +53,9 @@ function reifyInner(instanceMap, virtualInstances, id, parentInstance, unapplied -- Instance.new can fail if we're passing in something that can't be -- created, like a service, something enabled with a feature flag, or -- something that requires higher security than we have. - local ok, instance = pcall(Instance.new, virtualInstance.ClassName) + local createSuccess, instance = pcall(Instance.new, virtualInstance.ClassName) - if not ok then + if not createSuccess then addAllToPatch(unappliedPatch, virtualInstances, id) return end @@ -80,14 +80,14 @@ function reifyInner(instanceMap, virtualInstances, id, parentInstance, unapplied continue end - local ok, value = decodeValue(virtualValue, instanceMap) - if not ok then + local decodeSuccess, value = decodeValue(virtualValue, instanceMap) + if not decodeSuccess then unappliedProperties[propertyName] = virtualValue continue end - local ok = setProperty(instance, propertyName, value) - if not ok then + local setPropertySuccess = setProperty(instance, propertyName, value) + if not setPropertySuccess then unappliedProperties[propertyName] = virtualValue end end @@ -148,8 +148,8 @@ function applyDeferredRefs(instanceMap, deferredRefs, unappliedPatch) continue end - local ok = setProperty(entry.instance, entry.propertyName, targetInstance) - if not ok then + local setPropertySuccess = setProperty(entry.instance, entry.propertyName, targetInstance) + if not setPropertySuccess then markFailed(entry.id, entry.propertyName, entry.virtualValue) end end diff --git a/plugin/src/Reconciler/reify.spec.lua b/plugin/src/Reconciler/reify.spec.lua index f39032a2..44601dbc 100644 --- a/plugin/src/Reconciler/reify.spec.lua +++ b/plugin/src/Reconciler/reify.spec.lua @@ -3,7 +3,6 @@ return function() local PatchSet = require(script.Parent.Parent.PatchSet) local InstanceMap = require(script.Parent.Parent.InstanceMap) - local Error = require(script.Parent.Error) local function isEmpty(table) return next(table) == nil, "Table was not empty" diff --git a/plugin/src/Reconciler/setProperty.lua b/plugin/src/Reconciler/setProperty.lua index 35c8b59b..11df6b54 100644 --- a/plugin/src/Reconciler/setProperty.lua +++ b/plugin/src/Reconciler/setProperty.lua @@ -28,9 +28,9 @@ local function setProperty(instance, propertyName, value) }) end - local ok, err = descriptor:write(instance, value) + local writeSuccess, err = descriptor:write(instance, value) - if not ok then + if not writeSuccess then if err.kind == RbxDom.Error.Kind.Roblox and err.extra:find("lacking permission") then return false, Error.new(Error.LackingPropertyPermissions, { diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 56a06939..82d8fd42 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -21,8 +21,8 @@ local Status = strict("Session.Status", { Disconnected = "Disconnected", }) -local function debugPatch(patch) - return Fmt.debugify(patch, function(patch, output) +local function debugPatch(object) + return Fmt.debugify(object, function(patch, output) output:writeLine("Patch {{") output:indent() @@ -197,7 +197,7 @@ function ServeSession:__onActiveScriptChanged(activeScript) local existingParent = activeScript.Parent activeScript.Parent = nil - for i = 1, 3 do + for _ = 1, 3 do RunService.Heartbeat:Wait() end @@ -251,7 +251,10 @@ function ServeSession:__initialSync(serverInfo) if userDecision == "Abort" then return Promise.reject("Aborted Rojo sync operation") - elseif userDecision == "Reject" and self.__twoWaySync then + elseif userDecision == "Reject" then + if not self.__twoWaySync then + return Promise.reject("Cannot reject sync operation without two-way sync enabled") + end -- The user wants their studio DOM to write back to their Rojo DOM -- so we will reverse the patch and send it back @@ -268,7 +271,7 @@ function ServeSession:__initialSync(serverInfo) table.insert(inversePatch.updated, update) end -- Add the removed instances back to Rojo - -- selene:allow(empty_if, unused_variable) + -- selene:allow(empty_if, unused_variable, empty_loop) for _, instance in catchUpPatch.removed do -- TODO: Generate ID for our instance and add it to inversePatch.added end @@ -277,7 +280,7 @@ function ServeSession:__initialSync(serverInfo) table.insert(inversePatch.removed, id) end - self.__apiContext:write(inversePatch) + return self.__apiContext:write(inversePatch) elseif userDecision == "Accept" then local unappliedPatch = self.__reconciler:applyPatch(catchUpPatch) @@ -287,6 +290,10 @@ function ServeSession:__initialSync(serverInfo) PatchSet.humanSummary(self.__instanceMap, unappliedPatch) ) end + + return Promise.resolve() + else + return Promise.reject("Invalid user decision: " .. userDecision) end end) end diff --git a/plugin/src/createSignal.lua b/plugin/src/createSignal.lua deleted file mode 100644 index f6a00ddf..00000000 --- a/plugin/src/createSignal.lua +++ /dev/null @@ -1,53 +0,0 @@ ---[[ - Create a new signal that can be connected to, disconnected from, and fired. - - Usage: - - local signal = createSignal() - local disconnect = signal:connect(function(...) - print("fired:", ...) - end) - - signal:fire("a", "b", "c") - disconnect() - - Avoids mutating listeners list directly to prevent iterator invalidation if - a listener is disconnected while the signal is firing. -]] -local function createSignal() - local listeners = {} - - local function connect(newListener) - local nextListeners = {} - for listener in pairs(listeners) do - nextListeners[listener] = true - end - - nextListeners[newListener] = true - listeners = nextListeners - - return function() - local nextListeners = {} - for listener in pairs(listeners) do - if listener ~= newListener then - nextListeners[listener] = true - end - end - - listeners = nextListeners - end - end - - local function fire(...) - for listener in pairs(listeners) do - listener(...) - end - end - - return { - connect = connect, - fire = fire, - } -end - -return createSignal From 7abf19804c6ba0df220e87c271bb10b8c151a1bc Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Thu, 1 Feb 2024 13:05:44 -0800 Subject: [PATCH 1375/1504] Ignore any unreadable property in Reconciler:diff (#848) --- CHANGELOG.md | 2 ++ plugin/src/Reconciler/diff.lua | 4 +--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index efc9405a..a18a3ab9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Fixed Rojo plugin failing to connect when project contains certain unreadable properties ([#848]) * Added popout diff visualizer for table properties like Attributes and Tags ([#834]) * Updated Theme to use Studio colors ([#838]) * Added experimental setting for Auto Connect in playtests ([#840]) @@ -55,6 +56,7 @@ [#834]: https://github.com/rojo-rbx/rojo/pull/834 [#838]: https://github.com/rojo-rbx/rojo/pull/838 [#840]: https://github.com/rojo-rbx/rojo/pull/840 +[#848]: https://github.com/rojo-rbx/rojo/pull/848 ## [7.4.0] - January 16, 2024 * Improved the visualization for array properties like Tags ([#829]) diff --git a/plugin/src/Reconciler/diff.lua b/plugin/src/Reconciler/diff.lua index e13b05c8..c87f899c 100644 --- a/plugin/src/Reconciler/diff.lua +++ b/plugin/src/Reconciler/diff.lua @@ -177,10 +177,8 @@ local function diff(instanceMap, virtualInstances, rootId) if err.kind == Error.UnknownProperty then Log.trace("Skipping unknown property {}.{}", err.details.className, err.details.propertyName) - elseif err.kind == Error.UnreadableProperty then - Log.trace("Skipping unreadable property {}.{}", err.details.className, err.details.propertyName) else - return false, err + Log.trace("Skipping unreadable property {}.{}", err.details.className, err.details.propertyName) end end end From 5c4260f3ac6f967fe380aec2867e2eff84660709 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Thu, 1 Feb 2024 13:29:36 -0800 Subject: [PATCH 1376/1504] Catch failed http requests that didn't error so we can handle them correctly (#847) --- CHANGELOG.md | 3 +++ plugin/http/Error.lua | 17 +++++++++++++---- plugin/http/init.lua | 11 ++++++++--- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a18a3ab9..4aef0cc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ * Added popout diff visualizer for table properties like Attributes and Tags ([#834]) * Updated Theme to use Studio colors ([#838]) * Added experimental setting for Auto Connect in playtests ([#840]) +* Fixed http error handling so Rojo can be used in Github Codespaces ([#847]) * Projects may now specify rules for syncing files as if they had a different file extension. ([#813]) This is specified via a new field on project files, `syncRules`: @@ -56,8 +57,10 @@ [#834]: https://github.com/rojo-rbx/rojo/pull/834 [#838]: https://github.com/rojo-rbx/rojo/pull/838 [#840]: https://github.com/rojo-rbx/rojo/pull/840 +[#847]: https://github.com/rojo-rbx/rojo/pull/847 [#848]: https://github.com/rojo-rbx/rojo/pull/848 + ## [7.4.0] - January 16, 2024 * Improved the visualization for array properties like Tags ([#829]) * Significantly improved performance of `rojo serve`, `rojo build --watch`, and `rojo sourcemap --watch` on macOS. ([#830]) diff --git a/plugin/http/Error.lua b/plugin/http/Error.lua index ed85fc67..f9e46b38 100644 --- a/plugin/http/Error.lua +++ b/plugin/http/Error.lua @@ -3,12 +3,12 @@ Error.__index = Error Error.Kind = { HttpNotEnabled = { - message = "Rojo requires HTTP access, which is not enabled.\n" .. - "Check your game settings, located in the 'Home' tab of Studio.", + message = "Rojo requires HTTP access, which is not enabled.\n" + .. "Check your game settings, located in the 'Home' tab of Studio.", }, ConnectFailed = { - message = "Couldn't connect to the Rojo server.\n" .. - "Make sure the server is running — use 'rojo serve' to run it!", + message = "Couldn't connect to the Rojo server.\n" + .. "Make sure the server is running — use 'rojo serve' to run it!", }, Timeout = { message = "HTTP request timed out.", @@ -63,4 +63,13 @@ function Error.fromRobloxErrorString(message) return Error.new(Error.Kind.Unknown, message) end +function Error.fromResponse(response) + local lower = (response.body or ""):lower() + if response.code == 408 or response.code == 504 or lower:find("timed? ?out") then + return Error.new(Error.Kind.Timeout) + end + + return Error.new(Error.Kind.Unknown, string.format("%s: %s", tostring(response.code), tostring(response.body))) +end + return Error diff --git a/plugin/http/init.lua b/plugin/http/init.lua index 686130ef..cac0ebc4 100644 --- a/plugin/http/init.lua +++ b/plugin/http/init.lua @@ -30,8 +30,13 @@ local function performRequest(requestParams) end) if success then - Log.trace("Request {} success, status code {}", requestId, response.StatusCode) - resolve(HttpResponse.fromRobloxResponse(response)) + Log.trace("Request {} success, response {:#?}", requestId, response) + local httpResponse = HttpResponse.fromRobloxResponse(response) + if httpResponse:isSuccess() then + resolve(httpResponse) + else + reject(HttpError.fromResponse(httpResponse)) + end else Log.trace("Request {} failure: {:?}", requestId, response) reject(HttpError.fromRobloxErrorString(response)) @@ -63,4 +68,4 @@ function Http.jsonDecode(source) return HttpService:JSONDecode(source) end -return Http \ No newline at end of file +return Http From cf25eb083377a308f593d04a1dd0791ee75a3119 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Mon, 12 Feb 2024 14:58:03 -0800 Subject: [PATCH 1377/1504] Normalize line endings to LF in Lua middleware (#854) --- CHANGELOG.md | 2 ++ crates/memofs/CHANGELOG.md | 2 ++ crates/memofs/src/lib.rs | 47 +++++++++++++++++++++++++++++++++- src/snapshot_middleware/lua.rs | 7 ++--- src/snapshot_middleware/txt.rs | 7 ++--- 5 files changed, 54 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4aef0cc1..d15a6f23 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Rojo now converts any line endings to LF, preventing spurious diffs when syncing Lua files on Windows ([#854]) * Fixed Rojo plugin failing to connect when project contains certain unreadable properties ([#848]) * Added popout diff visualizer for table properties like Attributes and Tags ([#834]) * Updated Theme to use Studio colors ([#838]) @@ -59,6 +60,7 @@ [#840]: https://github.com/rojo-rbx/rojo/pull/840 [#847]: https://github.com/rojo-rbx/rojo/pull/847 [#848]: https://github.com/rojo-rbx/rojo/pull/848 +[#854]: https://github.com/rojo-rbx/rojo/pull/854 ## [7.4.0] - January 16, 2024 diff --git a/crates/memofs/CHANGELOG.md b/crates/memofs/CHANGELOG.md index c9961d0e..d678f8c9 100644 --- a/crates/memofs/CHANGELOG.md +++ b/crates/memofs/CHANGELOG.md @@ -2,8 +2,10 @@ ## Unreleased Changes * Changed `StdBackend` file watching component to use minimal recursive watches. [#830] +* Added `Vfs::read_to_string` and `Vfs::read_to_string_lf_normalized` [#854] [#830]: https://github.com/rojo-rbx/rojo/pull/830 +[#854]: https://github.com/rojo-rbx/rojo/pull/854 ## 0.2.0 (2021-08-23) * Updated to `crossbeam-channel` 0.5.1. diff --git a/crates/memofs/src/lib.rs b/crates/memofs/src/lib.rs index 744ca60f..6d41c853 100644 --- a/crates/memofs/src/lib.rs +++ b/crates/memofs/src/lib.rs @@ -22,9 +22,9 @@ mod noop_backend; mod snapshot; mod std_backend; -use std::io; use std::path::{Path, PathBuf}; use std::sync::{Arc, Mutex, MutexGuard}; +use std::{io, str}; pub use in_memory_fs::InMemoryFs; pub use noop_backend::NoopBackend; @@ -155,6 +155,24 @@ impl VfsInner { Ok(Arc::new(contents)) } + fn read_to_string>(&mut self, path: P) -> io::Result> { + let path = path.as_ref(); + let contents = self.backend.read(path)?; + + if self.watch_enabled { + self.backend.watch(path)?; + } + + let contents_str = str::from_utf8(&contents).map_err(|_| { + io::Error::new( + io::ErrorKind::InvalidData, + format!("File was not valid UTF-8: {}", path.display()), + ) + })?; + + Ok(Arc::new(contents_str.into())) + } + fn write, C: AsRef<[u8]>>(&mut self, path: P, contents: C) -> io::Result<()> { let path = path.as_ref(); let contents = contents.as_ref(); @@ -258,6 +276,33 @@ impl Vfs { self.inner.lock().unwrap().read(path) } + /// Read a file from the VFS (or from the underlying backend if it isn't + /// resident) into a string. + /// + /// Roughly equivalent to [`std::fs::read_to_string`][std::fs::read_to_string]. + /// + /// [std::fs::read_to_string]: https://doc.rust-lang.org/stable/std/fs/fn.read_to_string.html + #[inline] + pub fn read_to_string>(&self, path: P) -> io::Result> { + let path = path.as_ref(); + self.inner.lock().unwrap().read_to_string(path) + } + + /// Read a file from the VFS (or the underlying backend if it isn't + /// resident) into a string, and normalize its line endings to LF. + /// + /// Roughly equivalent to [`std::fs::read_to_string`][std::fs::read_to_string], but also performs + /// line ending normalization. + /// + /// [std::fs::read_to_string]: https://doc.rust-lang.org/stable/std/fs/fn.read_to_string.html + #[inline] + pub fn read_to_string_lf_normalized>(&self, path: P) -> io::Result> { + let path = path.as_ref(); + let contents = self.inner.lock().unwrap().read_to_string(path)?; + + Ok(contents.lines().collect::>().join("\n").into()) + } + /// Write a file to the VFS and the underlying backend. /// /// Roughly equivalent to [`std::fs::write`][std::fs::write]. diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index ab7f15a1..3f8d26ad 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -1,6 +1,5 @@ use std::{collections::HashMap, path::Path, str}; -use anyhow::Context; use memofs::{IoResultExt, Vfs}; use rbx_dom_weak::types::Enum; @@ -40,10 +39,8 @@ pub fn snapshot_lua( (_, ScriptType::Module) => ("ModuleScript", None), }; - let contents = vfs.read(path)?; - let contents_str = str::from_utf8(&contents) - .with_context(|| format!("File was not valid UTF-8: {}", path.display()))? - .to_owned(); + let contents = vfs.read_to_string_lf_normalized(path)?; + let contents_str = contents.as_str(); let mut properties = HashMap::with_capacity(2); properties.insert("Source".to_owned(), contents_str.into()); diff --git a/src/snapshot_middleware/txt.rs b/src/snapshot_middleware/txt.rs index 207243f9..a69b14d1 100644 --- a/src/snapshot_middleware/txt.rs +++ b/src/snapshot_middleware/txt.rs @@ -1,6 +1,5 @@ use std::{path::Path, str}; -use anyhow::Context; use maplit::hashmap; use memofs::{IoResultExt, Vfs}; @@ -14,10 +13,8 @@ pub fn snapshot_txt( path: &Path, name: &str, ) -> anyhow::Result> { - let contents = vfs.read(path)?; - let contents_str = str::from_utf8(&contents) - .with_context(|| format!("File was not valid UTF-8: {}", path.display()))? - .to_owned(); + let contents = vfs.read_to_string(path)?; + let contents_str = contents.as_str(); let properties = hashmap! { "Value".to_owned() => contents_str.into(), From 8ff064fe28a5acd4db3c411f8912ee53bbea7090 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Mon, 12 Feb 2024 15:58:35 -0800 Subject: [PATCH 1378/1504] Add benchmarking, perf gains, and better settings UI (#850) --- .../Components/StringDiffVisualizer/init.lua | 3 + .../Components/TableDiffVisualizer/Array.lua | 3 + .../TableDiffVisualizer/Dictionary.lua | 3 + plugin/src/App/StatusPages/Confirming.lua | 29 +- .../src/App/StatusPages/Settings/Setting.lua | 16 +- plugin/src/App/StatusPages/Settings/init.lua | 269 +++++++++--------- plugin/src/PatchTree.lua | 153 ++++++---- plugin/src/Reconciler/init.lua | 43 ++- plugin/src/Settings.lua | 1 + plugin/src/Timer.lua | 57 ++++ 10 files changed, 380 insertions(+), 197 deletions(-) create mode 100644 plugin/src/Timer.lua diff --git a/plugin/src/App/Components/StringDiffVisualizer/init.lua b/plugin/src/App/Components/StringDiffVisualizer/init.lua index 60eb49a3..e4203c21 100644 --- a/plugin/src/App/Components/StringDiffVisualizer/init.lua +++ b/plugin/src/App/Components/StringDiffVisualizer/init.lua @@ -9,6 +9,7 @@ local Log = require(Packages.Log) local Highlighter = require(Packages.Highlighter) local StringDiff = require(script:FindFirstChild("StringDiff")) +local Timer = require(Plugin.Timer) local Theme = require(Plugin.App.Theme) local CodeLabel = require(Plugin.App.Components.CodeLabel) @@ -74,6 +75,7 @@ function StringDiffVisualizer:calculateContentSize() end function StringDiffVisualizer:calculateDiffLines() + Timer.start("StringDiffVisualizer:calculateDiffLines") local oldString, newString = self.props.oldString, self.props.newString -- Diff the two texts @@ -133,6 +135,7 @@ function StringDiffVisualizer:calculateDiffLines() end end + Timer.stop() return add, remove end diff --git a/plugin/src/App/Components/TableDiffVisualizer/Array.lua b/plugin/src/App/Components/TableDiffVisualizer/Array.lua index 4fd56f3c..febd07e9 100644 --- a/plugin/src/App/Components/TableDiffVisualizer/Array.lua +++ b/plugin/src/App/Components/TableDiffVisualizer/Array.lua @@ -4,6 +4,7 @@ local Packages = Rojo.Packages local Roact = require(Packages.Roact) +local Timer = require(Plugin.Timer) local Assets = require(Plugin.Assets) local Theme = require(Plugin.App.Theme) @@ -21,6 +22,7 @@ function Array:init() end function Array:calculateDiff() + Timer.start("Array:calculateDiff") --[[ Find the indexes that are added or removed from the array, and display them side by side with gaps for the indexes that @@ -63,6 +65,7 @@ function Array:calculateDiff() j += 1 end + Timer.stop() return diff end diff --git a/plugin/src/App/Components/TableDiffVisualizer/Dictionary.lua b/plugin/src/App/Components/TableDiffVisualizer/Dictionary.lua index d0c32d96..033956c3 100644 --- a/plugin/src/App/Components/TableDiffVisualizer/Dictionary.lua +++ b/plugin/src/App/Components/TableDiffVisualizer/Dictionary.lua @@ -4,6 +4,7 @@ local Packages = Rojo.Packages local Roact = require(Packages.Roact) +local Timer = require(Plugin.Timer) local Assets = require(Plugin.Assets) local Theme = require(Plugin.App.Theme) @@ -21,6 +22,7 @@ function Dictionary:init() end function Dictionary:calculateDiff() + Timer.start("Dictionary:calculateDiff") local oldTable, newTable = self.props.oldTable or {}, self.props.newTable or {} -- Diff the two tables and find the added keys, removed keys, and changed keys @@ -59,6 +61,7 @@ function Dictionary:calculateDiff() return a.key < b.key end) + Timer.stop() return diff end diff --git a/plugin/src/App/StatusPages/Confirming.lua b/plugin/src/App/StatusPages/Confirming.lua index d3b6baa2..bd0fd0a1 100644 --- a/plugin/src/App/StatusPages/Confirming.lua +++ b/plugin/src/App/StatusPages/Confirming.lua @@ -4,6 +4,8 @@ local Packages = Rojo.Packages local Roact = require(Packages.Roact) +local Timer = require(Plugin.Timer) +local PatchTree = require(Plugin.PatchTree) local Settings = require(Plugin.Settings) local Theme = require(Plugin.App.Theme) local TextButton = require(Plugin.App.Components.TextButton) @@ -23,6 +25,7 @@ function ConfirmingPage:init() self.containerSize, self.setContainerSize = Roact.createBinding(Vector2.new(0, 0)) self:setState({ + patchTree = nil, showingStringDiff = false, oldString = "", newString = "", @@ -30,6 +33,28 @@ function ConfirmingPage:init() oldTable = {}, newTable = {}, }) + + if self.props.confirmData and self.props.confirmData.patch and self.props.confirmData.instanceMap then + self:buildPatchTree() + end +end + +function ConfirmingPage:didUpdate(prevProps) + if prevProps.confirmData ~= self.props.confirmData then + self:buildPatchTree() + end +end + +function ConfirmingPage:buildPatchTree() + Timer.start("ConfirmingPage:buildPatchTree") + self:setState({ + patchTree = PatchTree.build( + self.props.confirmData.patch, + self.props.confirmData.instanceMap, + { "Property", "Current", "Incoming" } + ), + }) + Timer.stop() end function ConfirmingPage:render() @@ -61,9 +86,7 @@ function ConfirmingPage:render() transparency = self.props.transparency, layoutOrder = 3, - changeListHeaders = { "Property", "Current", "Incoming" }, - patch = self.props.confirmData.patch, - instanceMap = self.props.confirmData.instanceMap, + patchTree = self.state.patchTree, showStringDiff = function(oldString: string, newString: string) self:setState({ diff --git a/plugin/src/App/StatusPages/Settings/Setting.lua b/plugin/src/App/StatusPages/Settings/Setting.lua index 86adb6fc..86170ec2 100644 --- a/plugin/src/App/StatusPages/Settings/Setting.lua +++ b/plugin/src/App/StatusPages/Settings/Setting.lua @@ -121,8 +121,14 @@ function Setting:render() BackgroundTransparency = 1, }, { Name = e("TextLabel", { - Text = (if self.props.experimental then '⚠ ' else "") - .. self.props.name, + Text = ( + if self.props.experimental + then '⚠ ' + elseif + self.props.developerDebug + then '⚑ ' -- Guru is the only font with the flag emoji + else "" + ) .. self.props.name, Font = Enum.Font.GothamBold, TextSize = 17, TextColor3 = theme.Setting.NameColor, @@ -137,8 +143,10 @@ function Setting:render() }), Description = e("TextLabel", { - Text = (if self.props.experimental then '[Experimental] ' else "") - .. self.props.description, + Text = (if self.props.experimental + then '[Experimental] ' + elseif self.props.developerDebug then '[Dev Debug] ' + else "") .. self.props.description, Font = Enum.Font.Gotham, LineHeight = 1.2, TextSize = 14, diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua index a33eb1b5..c87a9d19 100644 --- a/plugin/src/App/StatusPages/Settings/init.lua +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -84,148 +84,161 @@ function SettingsPage:render() return Theme.with(function(theme) theme = theme.Settings - return e(ScrollingFrame, { - size = UDim2.new(1, 0, 1, 0), - contentSize = self.contentSize, - transparency = self.props.transparency, - }, { + return Roact.createFragment({ Navbar = e(Navbar, { onBack = self.props.onBack, transparency = self.props.transparency, layoutOrder = layoutIncrement(), }), - - ShowNotifications = e(Setting, { - id = "showNotifications", - name = "Show Notifications", - description = "Popup notifications in viewport", + Content = e(ScrollingFrame, { + size = UDim2.new(1, 0, 1, -47), + position = UDim2.new(0, 0, 0, 47), + contentSize = self.contentSize, transparency = self.props.transparency, - layoutOrder = layoutIncrement(), - }), - - SyncReminder = e(Setting, { - id = "syncReminder", - name = "Sync Reminder", - description = "Notify to sync when opening a place that has previously been synced", - transparency = self.props.transparency, - visible = Settings:getBinding("showNotifications"), - layoutOrder = layoutIncrement(), - }), - - ConfirmationBehavior = e(Setting, { - id = "confirmationBehavior", - name = "Confirmation Behavior", - description = "When to prompt for confirmation before syncing", - transparency = self.props.transparency, - layoutOrder = layoutIncrement(), - - options = confirmationBehaviors, - }), - - LargeChangesConfirmationThreshold = e(Setting, { - id = "largeChangesConfirmationThreshold", - name = "Confirmation Threshold", - description = "How many modified instances to be considered a large change", - transparency = self.props.transparency, - layoutOrder = layoutIncrement(), - visible = Settings:getBinding("confirmationBehavior"):map(function(value) - return value == "Large Changes" - end), - input = e(TextInput, { - size = UDim2.new(0, 40, 0, 28), - text = Settings:getBinding("largeChangesConfirmationThreshold"):map(function(value) - return tostring(value) - end), + }, { + ShowNotifications = e(Setting, { + id = "showNotifications", + name = "Show Notifications", + description = "Popup notifications in viewport", transparency = self.props.transparency, - enabled = true, - onEntered = function(text) - local number = tonumber(string.match(text, "%d+")) - if number then - Settings:set("largeChangesConfirmationThreshold", math.clamp(number, 1, 999)) - else - -- Force text back to last valid value - Settings:set( - "largeChangesConfirmationThreshold", - Settings:get("largeChangesConfirmationThreshold") - ) - end + layoutOrder = layoutIncrement(), + }), + + SyncReminder = e(Setting, { + id = "syncReminder", + name = "Sync Reminder", + description = "Notify to sync when opening a place that has previously been synced", + transparency = self.props.transparency, + visible = Settings:getBinding("showNotifications"), + layoutOrder = layoutIncrement(), + }), + + ConfirmationBehavior = e(Setting, { + id = "confirmationBehavior", + name = "Confirmation Behavior", + description = "When to prompt for confirmation before syncing", + transparency = self.props.transparency, + layoutOrder = layoutIncrement(), + + options = confirmationBehaviors, + }), + + LargeChangesConfirmationThreshold = e(Setting, { + id = "largeChangesConfirmationThreshold", + name = "Confirmation Threshold", + description = "How many modified instances to be considered a large change", + transparency = self.props.transparency, + layoutOrder = layoutIncrement(), + visible = Settings:getBinding("confirmationBehavior"):map(function(value) + return value == "Large Changes" + end), + input = e(TextInput, { + size = UDim2.new(0, 40, 0, 28), + text = Settings:getBinding("largeChangesConfirmationThreshold"):map(function(value) + return tostring(value) + end), + transparency = self.props.transparency, + enabled = true, + onEntered = function(text) + local number = tonumber(string.match(text, "%d+")) + if number then + Settings:set("largeChangesConfirmationThreshold", math.clamp(number, 1, 999)) + else + -- Force text back to last valid value + Settings:set( + "largeChangesConfirmationThreshold", + Settings:get("largeChangesConfirmationThreshold") + ) + end + end, + }), + }), + + PlaySounds = e(Setting, { + id = "playSounds", + name = "Play Sounds", + description = "Toggle sound effects", + transparency = self.props.transparency, + layoutOrder = layoutIncrement(), + }), + + AutoConnectPlaytestServer = e(Setting, { + id = "autoConnectPlaytestServer", + name = "Auto Connect Playtest Server", + description = "Automatically connect game server to Rojo when playtesting while connected in Edit", + experimental = true, + transparency = self.props.transparency, + layoutOrder = layoutIncrement(), + }), + + OpenScriptsExternally = e(Setting, { + id = "openScriptsExternally", + name = "Open Scripts Externally", + description = "Attempt to open scripts in an external editor", + locked = self.props.syncActive, + experimental = true, + transparency = self.props.transparency, + layoutOrder = layoutIncrement(), + }), + + TwoWaySync = e(Setting, { + id = "twoWaySync", + name = "Two-Way Sync", + description = "Editing files in Studio will sync them into the filesystem", + locked = self.props.syncActive, + experimental = true, + transparency = self.props.transparency, + layoutOrder = layoutIncrement(), + }), + + LogLevel = e(Setting, { + id = "logLevel", + name = "Log Level", + description = "Plugin output verbosity level", + developerDebug = true, + transparency = self.props.transparency, + layoutOrder = layoutIncrement(), + + options = invertedLevels, + showReset = Settings:getBinding("logLevel"):map(function(value) + return value ~= "Info" + end), + onReset = function() + Settings:set("logLevel", "Info") end, }), - }), - PlaySounds = e(Setting, { - id = "playSounds", - name = "Play Sounds", - description = "Toggle sound effects", - transparency = self.props.transparency, - layoutOrder = layoutIncrement(), - }), + TypecheckingEnabled = e(Setting, { + id = "typecheckingEnabled", + name = "Typechecking", + description = "Toggle typechecking on the API surface", + developerDebug = true, + transparency = self.props.transparency, + layoutOrder = layoutIncrement(), + }), - AutoConnectPlaytestServer = e(Setting, { - id = "autoConnectPlaytestServer", - name = "Auto Connect Playtest Server", - description = "Automatically connect game server to Rojo when playtesting while connected in Edit", - experimental = true, - transparency = self.props.transparency, - layoutOrder = layoutIncrement(), - }), + TimingLogsEnabled = e(Setting, { + id = "timingLogsEnabled", + name = "Timing Logs", + description = "Toggle logging timing of internal actions for benchmarking Rojo performance", + developerDebug = true, + transparency = self.props.transparency, + layoutOrder = layoutIncrement(), + }), - OpenScriptsExternally = e(Setting, { - id = "openScriptsExternally", - name = "Open Scripts Externally", - description = "Attempt to open scripts in an external editor", - locked = self.props.syncActive, - experimental = true, - transparency = self.props.transparency, - layoutOrder = layoutIncrement(), - }), + Layout = e("UIListLayout", { + FillDirection = Enum.FillDirection.Vertical, + SortOrder = Enum.SortOrder.LayoutOrder, - TwoWaySync = e(Setting, { - id = "twoWaySync", - name = "Two-Way Sync", - description = "Editing files in Studio will sync them into the filesystem", - locked = self.props.syncActive, - experimental = true, - transparency = self.props.transparency, - layoutOrder = layoutIncrement(), - }), + [Roact.Change.AbsoluteContentSize] = function(object) + self.setContentSize(object.AbsoluteContentSize) + end, + }), - LogLevel = e(Setting, { - id = "logLevel", - name = "Log Level", - description = "Plugin output verbosity level", - transparency = self.props.transparency, - layoutOrder = layoutIncrement(), - - options = invertedLevels, - showReset = Settings:getBinding("logLevel"):map(function(value) - return value ~= "Info" - end), - onReset = function() - Settings:set("logLevel", "Info") - end, - }), - - TypecheckingEnabled = e(Setting, { - id = "typecheckingEnabled", - name = "Typechecking", - description = "Toggle typechecking on the API surface", - transparency = self.props.transparency, - layoutOrder = layoutIncrement(), - }), - - Layout = e("UIListLayout", { - FillDirection = Enum.FillDirection.Vertical, - SortOrder = Enum.SortOrder.LayoutOrder, - - [Roact.Change.AbsoluteContentSize] = function(object) - self.setContentSize(object.AbsoluteContentSize) - end, - }), - - Padding = e("UIPadding", { - PaddingLeft = UDim.new(0, 20), - PaddingRight = UDim.new(0, 20), + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 20), + PaddingRight = UDim.new(0, 20), + }), }), }) end) diff --git a/plugin/src/PatchTree.lua b/plugin/src/PatchTree.lua index e469e211..d0d99e37 100644 --- a/plugin/src/PatchTree.lua +++ b/plugin/src/PatchTree.lua @@ -11,6 +11,7 @@ local Packages = Rojo.Packages local Log = require(Packages.Log) +local Timer = require(Plugin.Timer) local Types = require(Plugin.Types) local decodeValue = require(Plugin.Reconciler.decodeValue) local getProperty = require(Plugin.Reconciler.getProperty) @@ -122,6 +123,7 @@ end -- props must contain id, and cannot contain children or parentId -- other than those three, it can hold anything function Tree:addNode(parent, props) + Timer.start("Tree:addNode") assert(props.id, "props must contain id") parent = parent or "ROOT" @@ -132,6 +134,7 @@ function Tree:addNode(parent, props) for k, v in props do node[k] = v end + Timer.stop() return node end @@ -142,22 +145,26 @@ function Tree:addNode(parent, props) local parentNode = self:getNode(parent) if not parentNode then Log.warn("Failed to create node since parent doesnt exist: {}, {}", parent, props) + Timer.stop() return end parentNode.children[node.id] = node self.idToNode[node.id] = node + Timer.stop() return node end -- Given a list of ancestor ids in descending order, builds the nodes for them -- using the patch and instanceMap info function Tree:buildAncestryNodes(previousId: string?, ancestryIds: { string }, patch, instanceMap) + Timer.start("Tree:buildAncestryNodes") -- Build nodes for ancestry by going up the tree previousId = previousId or "ROOT" - for _, ancestorId in ancestryIds do + for i = #ancestryIds, 1, -1 do + local ancestorId = ancestryIds[i] local value = instanceMap.fromIds[ancestorId] or patch.added[ancestorId] if not value then Log.warn("Failed to find ancestor object for " .. ancestorId) @@ -171,6 +178,8 @@ function Tree:buildAncestryNodes(previousId: string?, ancestryIds: { string }, p }) previousId = ancestorId end + + Timer.stop() end local PatchTree = {} @@ -178,10 +187,12 @@ local PatchTree = {} -- Builds a new tree from a patch and instanceMap -- uses changeListHeaders in node.changeList function PatchTree.build(patch, instanceMap, changeListHeaders) + Timer.start("PatchTree.build") local tree = Tree.new() local knownAncestors = {} + Timer.start("patch.updated") for _, change in patch.updated do local instance = instanceMap.fromIds[change.id] if not instance then @@ -189,7 +200,7 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) end -- Gather ancestors from existing DOM - local ancestryIds = {} + local ancestryIds, ancestryIndex = {}, 0 local parentObject = instance.Parent local parentId = instanceMap.fromInstances[parentObject] local previousId = nil @@ -200,7 +211,8 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) break end - table.insert(ancestryIds, 1, parentId) + ancestryIndex += 1 + ancestryIds[ancestryIndex] = parentId knownAncestors[parentId] = true parentObject = parentObject.Parent parentId = instanceMap.fromInstances[parentObject] @@ -213,11 +225,38 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) if next(change.changedProperties) or change.changedName then changeList = {} - local hintBuffer, i = {}, 0 + local hintBuffer, hintBufferSize, hintOverflow = table.create(3), 0, 0 + local changeIndex = 0 local function addProp(prop: string, current: any?, incoming: any?, metadata: any?) - i += 1 - hintBuffer[i] = prop - changeList[i] = { prop, current, incoming, metadata } + changeIndex += 1 + changeList[changeIndex] = { prop, current, incoming, metadata } + + if hintBufferSize < 3 then + hintBufferSize += 1 + hintBuffer[hintBufferSize] = prop + return + end + + -- We only want to have 3 hints + -- to keep it deterministic, we sort them alphabetically + + -- Either this prop overflows, or it makes another one move to overflow + hintOverflow += 1 + + -- Shortcut for the common case + if hintBuffer[3] <= prop then + -- This prop is below the last hint, no need to insert + return + end + + -- Find the first available spot + for i, hintItem in hintBuffer do + if prop < hintItem then + -- This prop is before the currently selected hint, + -- so take its place and then continue to find a spot for the old hint + hintBuffer[i], prop = prop, hintBuffer[i] + end + end end -- Gather the changes @@ -238,18 +277,7 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) end -- Finalize detail values - - -- Trim hint to top 3 - table.sort(hintBuffer) - if #hintBuffer > 3 then - hintBuffer = { - hintBuffer[1], - hintBuffer[2], - hintBuffer[3], - i - 3 .. " more", - } - end - hint = table.concat(hintBuffer, ", ") + hint = table.concat(hintBuffer, ", ") .. (if hintOverflow == 0 then "" else ", " .. hintOverflow .. " more") -- Sort changes and add header table.sort(changeList, function(a, b) @@ -269,7 +297,9 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) changeList = changeList, }) end + Timer.stop() + Timer.start("patch.removed") for _, idOrInstance in patch.removed do local instance = if Types.RbxId(idOrInstance) then instanceMap.fromIds[idOrInstance] else idOrInstance if not instance then @@ -311,7 +341,9 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) instance = instance, }) end + Timer.stop() + Timer.start("patch.added") for id, change in patch.added do -- Gather ancestors from existing DOM or future additions local ancestryIds = {} @@ -350,32 +382,47 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) if next(change.Properties) then changeList = {} - local hintBuffer, i = {}, 0 - for prop, incoming in change.Properties do - i += 1 - hintBuffer[i] = prop + local hintBuffer, hintBufferSize, hintOverflow = table.create(3), 0, 0 + local changeIndex = 0 + local function addProp(prop: string, incoming: any) + changeIndex += 1 + changeList[changeIndex] = { prop, "N/A", incoming } - local success, incomingValue = decodeValue(incoming, instanceMap) - if success then - table.insert(changeList, { prop, "N/A", incomingValue }) - else - table.insert(changeList, { prop, "N/A", select(2, next(incoming)) }) + if hintBufferSize < 3 then + hintBufferSize += 1 + hintBuffer[hintBufferSize] = prop + return + end + + -- We only want to have 3 hints + -- to keep it deterministic, we sort them alphabetically + + -- Either this prop overflows, or it makes another one move to overflow + hintOverflow += 1 + + -- Shortcut for the common case + if hintBuffer[3] <= prop then + -- This prop is below the last hint, no need to insert + return + end + + -- Find the first available spot + for i, hintItem in hintBuffer do + if prop < hintItem then + -- This prop is before the currently selected hint, + -- so take its place and then continue to find a spot for the old hint + hintBuffer[i], prop = prop, hintBuffer[i] + end end end - -- Finalize detail values - - -- Trim hint to top 3 - table.sort(hintBuffer) - if #hintBuffer > 3 then - hintBuffer = { - hintBuffer[1], - hintBuffer[2], - hintBuffer[3], - i - 3 .. " more", - } + for prop, incoming in change.Properties do + local success, incomingValue = decodeValue(incoming, instanceMap) + addProp(prop, if success then incomingValue else select(2, next(incoming))) end - hint = table.concat(hintBuffer, ", ") + + -- Finalize detail values + hint = table.concat(hintBuffer, ", ") .. (if hintOverflow == 0 then "" else ", " .. hintOverflow .. " more") -- Sort changes and add header table.sort(changeList, function(a, b) @@ -395,35 +442,27 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) instance = instanceMap.fromIds[id], }) end + Timer.stop() + Timer.stop() return tree end --- Creates a deep copy of a tree for immutability purposes in Roact -function PatchTree.clone(tree) - if not tree then - return - end - - local newTree = Tree.new() - tree:forEach(function(node) - newTree:addNode(node.parentId, table.clone(node)) - end) - - return newTree -end - -- Updates the metadata of a tree with the unapplied patch and currently existing instances -- Builds a new tree from the data if one isn't provided -- Always returns a new tree for immutability purposes in Roact function PatchTree.updateMetadata(tree, patch, instanceMap, unappliedPatch) + Timer.start("PatchTree.updateMetadata") if tree then - tree = PatchTree.clone(tree) + -- A shallow copy is enough for our purposes here since we really only need a new top-level object + -- for immutable comparison checks in Roact + tree = table.clone(tree) else tree = PatchTree.build(patch, instanceMap) end -- Update isWarning metadata + Timer.start("isWarning") for _, failedChange in unappliedPatch.updated do local node = tree:getNode(failedChange.id) if not node then @@ -492,8 +531,10 @@ function PatchTree.updateMetadata(tree, patch, instanceMap, unappliedPatch) node.isWarning = true Log.trace("Marked node as warning: {} {}", node.id, node.name) end + Timer.stop() -- Update if instances exist + Timer.start("instanceAncestry") tree:forEach(function(node) if node.instance then if node.instance.Parent == nil and node.instance ~= game then @@ -509,7 +550,9 @@ function PatchTree.updateMetadata(tree, patch, instanceMap, unappliedPatch) end end end) + Timer.stop() + Timer.stop() return tree end diff --git a/plugin/src/Reconciler/init.lua b/plugin/src/Reconciler/init.lua index 12945782..df7cd92f 100644 --- a/plugin/src/Reconciler/init.lua +++ b/plugin/src/Reconciler/init.lua @@ -3,9 +3,14 @@ and mutating the Roblox DOM. ]] -local Packages = script.Parent.Parent.Packages +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + local Log = require(Packages.Log) +local Timer = require(Plugin.Timer) + local applyPatch = require(script.applyPatch) local hydrate = require(script.hydrate) local diff = require(script.diff) @@ -57,31 +62,55 @@ function Reconciler:hookPostcommit(callback: (patch: any, instanceMap: any, unap end function Reconciler:applyPatch(patch) + Timer.start("Reconciler:applyPatch") + + Timer.start("precommitCallbacks") + -- Precommit callbacks must be serial in order to obey the contract that + -- they execute before commit for _, callback in self.__precommitCallbacks do local success, err = pcall(callback, patch, self.__instanceMap) if not success then Log.warn("Precommit hook errored: {}", err) end end + Timer.stop() + Timer.start("apply") local unappliedPatch = applyPatch(self.__instanceMap, patch) + Timer.stop() + Timer.start("postcommitCallbacks") + -- Postcommit callbacks can be called with spawn since regardless of firing order, they are + -- guaranteed to be called after the commit for _, callback in self.__postcommitCallbacks do - local success, err = pcall(callback, patch, self.__instanceMap, unappliedPatch) - if not success then - Log.warn("Postcommit hook errored: {}", err) - end + task.spawn(function() + local success, err = pcall(callback, patch, self.__instanceMap, unappliedPatch) + if not success then + Log.warn("Postcommit hook errored: {}", err) + end + end) end + Timer.stop() + + Timer.stop() return unappliedPatch end function Reconciler:hydrate(virtualInstances, rootId, rootInstance) - return hydrate(self.__instanceMap, virtualInstances, rootId, rootInstance) + Timer.start("Reconciler:hydrate") + local result = hydrate(self.__instanceMap, virtualInstances, rootId, rootInstance) + Timer.stop() + + return result end function Reconciler:diff(virtualInstances, rootId) - return diff(self.__instanceMap, virtualInstances, rootId) + Timer.start("Reconciler:diff") + local success, result = diff(self.__instanceMap, virtualInstances, rootId) + Timer.stop() + + return success, result end return Reconciler diff --git a/plugin/src/Settings.lua b/plugin/src/Settings.lua index b5be22a7..67f13ba2 100644 --- a/plugin/src/Settings.lua +++ b/plugin/src/Settings.lua @@ -20,6 +20,7 @@ local defaultSettings = { playSounds = true, typecheckingEnabled = false, logLevel = "Info", + timingLogsEnabled = false, priorEndpoints = {}, } diff --git a/plugin/src/Timer.lua b/plugin/src/Timer.lua new file mode 100644 index 00000000..9a5bbbd0 --- /dev/null +++ b/plugin/src/Timer.lua @@ -0,0 +1,57 @@ +local Settings = require(script.Parent.Settings) + +local clock = os.clock + +local Timer = { + _entries = {}, +} + +function Timer._start(label) + local start = clock() + if not label then + error("[Rojo-Timer] Timer.start: label is required", 2) + return + end + + table.insert(Timer._entries, { label, start }) +end + +function Timer._stop() + local stop = clock() + + local entry = table.remove(Timer._entries) + if not entry then + error("[Rojo-Timer] Timer.stop: no label to stop", 2) + return + end + + local label = entry[1] + if #Timer._entries > 0 then + local priorLabels = {} + for _, priorEntry in ipairs(Timer._entries) do + table.insert(priorLabels, priorEntry[1]) + end + label = table.concat(priorLabels, "/") .. "/" .. label + end + + local start = entry[2] + local duration = stop - start + print(string.format("[Rojo-Timer] %s took %.3f ms", label, duration * 1000)) +end + +-- Replace functions with no-op if not in debug mode +local function no_op() end +local function setFunctions(enabled) + if enabled then + Timer.start = Timer._start + Timer.stop = Timer._stop + else + Timer.start = no_op + Timer.stop = no_op + end +end + +Settings:onChanged("timingLogsEnabled", setFunctions) +setFunctions(Settings:get("timingLogsEnabled")) + +return Timer From ddb26c73bd5f72e81e461d8cfaf6c7d4d8c2aa00 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Tue, 20 Feb 2024 12:08:55 -0800 Subject: [PATCH 1379/1504] rbx_dom_lua rojo-rbx/rbx-dom@6ccd30f (custom pivot get/set) (#868) --- CHANGELOG.md | 2 + plugin/rbx_dom_lua/EncodedValue.lua | 23 + plugin/rbx_dom_lua/allValues.json | 35 ++ plugin/rbx_dom_lua/customProperties.lua | 12 + plugin/rbx_dom_lua/database.json | 543 +++++++++++++++++++----- 5 files changed, 518 insertions(+), 97 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d15a6f23..9ccc6752 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Fixed incorrect results when serving model pivots ([#868]) * Rojo now converts any line endings to LF, preventing spurious diffs when syncing Lua files on Windows ([#854]) * Fixed Rojo plugin failing to connect when project contains certain unreadable properties ([#848]) * Added popout diff visualizer for table properties like Attributes and Tags ([#834]) @@ -61,6 +62,7 @@ [#847]: https://github.com/rojo-rbx/rojo/pull/847 [#848]: https://github.com/rojo-rbx/rojo/pull/848 [#854]: https://github.com/rojo-rbx/rojo/pull/854 +[#868]: https://github.com/rojo-rbx/rojo/pull/868 ## [7.4.0] - January 16, 2024 diff --git a/plugin/rbx_dom_lua/EncodedValue.lua b/plugin/rbx_dom_lua/EncodedValue.lua index e9dd0edd..f2e9e343 100644 --- a/plugin/rbx_dom_lua/EncodedValue.lua +++ b/plugin/rbx_dom_lua/EncodedValue.lua @@ -493,9 +493,32 @@ types = { }, } +types.OptionalCFrame = { + fromPod = function(pod) + if pod == nil then + return nil + else + return types.CFrame.fromPod(pod) + end + end, + + toPod = function(roblox) + if roblox == nil then + return nil + else + return types.CFrame.toPod(roblox) + end + end, +} + function EncodedValue.decode(encodedValue) local ty, value = next(encodedValue) + if ty == nil then + -- If the encoded pair is empty, assume it is an unoccupied optional value + return true, nil + end + local typeImpl = types[ty] if typeImpl == nil then return false, "Couldn't decode value " .. tostring(ty) diff --git a/plugin/rbx_dom_lua/allValues.json b/plugin/rbx_dom_lua/allValues.json index b233ab25..9b07d7bf 100644 --- a/plugin/rbx_dom_lua/allValues.json +++ b/plugin/rbx_dom_lua/allValues.json @@ -370,6 +370,41 @@ }, "ty": "NumberSequence" }, + "OptionalCFrame-None": { + "value": { + "OptionalCFrame": null + }, + "ty": "OptionalCFrame" + }, + "OptionalCFrame-Some": { + "value": { + "OptionalCFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ty": "OptionalCFrame" + }, "PhysicalProperties-Custom": { "value": { "PhysicalProperties": { diff --git a/plugin/rbx_dom_lua/customProperties.lua b/plugin/rbx_dom_lua/customProperties.lua index 072db9ef..f115f7c8 100644 --- a/plugin/rbx_dom_lua/customProperties.lua +++ b/plugin/rbx_dom_lua/customProperties.lua @@ -111,6 +111,18 @@ return { return true, instance:ScaleTo(value) end, }, + WorldPivotData = { + read = function(instance) + return true, instance:GetPivot() + end, + write = function(instance, _, value) + if value == nil then + return true, nil + else + return true, instance:PivotTo(value) + end + end, + }, }, Terrain = { MaterialColors = { diff --git a/plugin/rbx_dom_lua/database.json b/plugin/rbx_dom_lua/database.json index 81424b27..34be08b4 100644 --- a/plugin/rbx_dom_lua/database.json +++ b/plugin/rbx_dom_lua/database.json @@ -1,9 +1,9 @@ { "Version": [ 0, - 607, + 612, 0, - 6070550 + 6120532 ], "Classes": { "Accessory": { @@ -345,6 +345,17 @@ } } }, + "ActivityHistoryService": { + "Name": "ActivityHistoryService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "Actor": { "Name": "Actor", "Tags": [], @@ -11172,10 +11183,12 @@ "DataType": { "Value": "CFrame" }, - "Tags": [], + "Tags": [ + "Hidden" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -11185,10 +11198,12 @@ "DataType": { "Value": "Int32" }, - "Tags": [], + "Tags": [ + "Hidden" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -11198,10 +11213,12 @@ "DataType": { "Value": "String" }, - "Tags": [], + "Tags": [ + "Hidden" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -11211,22 +11228,38 @@ "DataType": { "Value": "Int32" }, - "Tags": [], + "Tags": [ + "Hidden" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" + } + } + }, + "IsIdle": { + "Name": "IsIdle", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" } } }, "Status": { "Name": "Status", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Enum": "CollaboratorStatus" }, "Tags": [ - "Hidden", - "NotScriptable" + "Hidden" ], "Kind": { "Canonical": { @@ -11240,10 +11273,12 @@ "DataType": { "Value": "Int64" }, - "Tags": [], + "Tags": [ + "Hidden" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -11253,10 +11288,12 @@ "DataType": { "Value": "String" }, - "Tags": [], + "Tags": [ + "Hidden" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } } @@ -12224,6 +12261,19 @@ "Serialization": "Serializes" } } + }, + "UpDirection": { + "Name": "UpDirection", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -12261,6 +12311,13 @@ }, "Tags": { "Tags": [] + }, + "UpDirection": { + "Vector3": [ + 0.0, + 1.0, + 0.0 + ] } } }, @@ -13286,7 +13343,9 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Deprecated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -15878,6 +15937,19 @@ } } }, + "PermissionPolicy": { + "Name": "PermissionPolicy", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DragDetectorPermissionPolicy" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PhysicalDragClickedPart": { "Name": "PhysicalDragClickedPart", "Scriptability": "None", @@ -16168,10 +16240,13 @@ "Orientation": { "Vector3": [ -0.0, - 180.0, + 179.99998, 90.0 ] }, + "PermissionPolicy": { + "Enum": 1 + }, "ResponseStyle": { "Enum": 1 }, @@ -22285,7 +22360,9 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Deprecated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -31232,7 +31309,7 @@ }, "WorldPivotData": { "Name": "WorldPivotData", - "Scriptability": "None", + "Scriptability": "Custom", "DataType": { "Value": "OptionalCFrame" }, @@ -33071,7 +33148,7 @@ }, "SerializedDefaultAttributes": { "Name": "SerializedDefaultAttributes", - "Scriptability": "Read", + "Scriptability": "None", "DataType": { "Value": "BinaryString" }, @@ -35022,6 +35099,19 @@ "Serialization": "Serializes" } } + }, + "ZIndex": { + "Name": "ZIndex", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": {} @@ -35734,6 +35824,58 @@ } } }, + "DrawConstraintsNetForce": { + "Name": "DrawConstraintsNetForce", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DrawContactsNetForce": { + "Name": "DrawContactsNetForce", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DrawTotalNetForce": { + "Name": "DrawTotalNetForce", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableForceVisualizationSmoothing": { + "Name": "EnableForceVisualizationSmoothing", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "FluidForceDrawScale": { "Name": "FluidForceDrawScale", "Scriptability": "None", @@ -35776,6 +35918,19 @@ } } }, + "ForceVisualizationSmoothingSteps": { + "Name": "ForceVisualizationSmoothingSteps", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "IsInterpolationThrottleShown": { "Name": "IsInterpolationThrottleShown", "Scriptability": "ReadWrite", @@ -35893,6 +36048,19 @@ } } }, + "TorqueDrawScale": { + "Name": "TorqueDrawScale", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "UseCSGv2": { "Name": "UseCSGv2", "Scriptability": "ReadWrite", @@ -38337,6 +38505,17 @@ } } }, + "ProjectFolderService": { + "Name": "ProjectFolderService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ProximityPrompt": { "Name": "ProximityPrompt", "Tags": [], @@ -40859,6 +41038,19 @@ } } }, + "PreferredUploadId": { + "Name": "PreferredUploadId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "RestPose": { "Name": "RestPose", "Scriptability": "ReadWrite", @@ -44505,7 +44697,9 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Deprecated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -46931,21 +47125,6 @@ } } }, - "AnimationCompositorMode": { - "Name": "AnimationCompositorMode", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "AnimationCompositorMode" - }, - "Tags": [ - "NotBrowsable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "AutoJumpEnabled": { "Name": "AutoJumpEnabled", "Scriptability": "ReadWrite", @@ -47488,21 +47667,6 @@ } } }, - "HumanoidStateMachineMode": { - "Name": "HumanoidStateMachineMode", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "HumanoidStateMachineMode" - }, - "Tags": [ - "NotBrowsable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "LoadCharacterAppearance": { "Name": "LoadCharacterAppearance", "Scriptability": "ReadWrite", @@ -47594,9 +47758,6 @@ "AllowCustomAnimations": { "Bool": true }, - "AnimationCompositorMode": { - "Enum": 0 - }, "Attributes": { "Attributes": {} }, @@ -47729,9 +47890,6 @@ "HealthDisplayDistance": { "Float32": 100.0 }, - "HumanoidStateMachineMode": { - "Enum": 0 - }, "LoadCharacterAppearance": { "Bool": true }, @@ -48619,6 +48777,136 @@ } } }, + "DraggerActiveColor": { + "Name": "DraggerActiveColor", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DraggerMajorGridIncrement": { + "Name": "DraggerMajorGridIncrement", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DraggerMaxSoftSnaps": { + "Name": "DraggerMaxSoftSnaps", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DraggerPassiveColor": { + "Name": "DraggerPassiveColor", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DraggerShowHoverRuler": { + "Name": "DraggerShowHoverRuler", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DraggerShowMeasurement": { + "Name": "DraggerShowMeasurement", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DraggerShowTargetSnap": { + "Name": "DraggerShowTargetSnap", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DraggerSoftSnapMarginFactor": { + "Name": "DraggerSoftSnapMarginFactor", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DraggerSummonMarginFactor": { + "Name": "DraggerSummonMarginFactor", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DraggerTiltRotateDuration": { + "Name": "DraggerTiltRotateDuration", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Enable Autocomplete": { "Name": "Enable Autocomplete", "Scriptability": "ReadWrite", @@ -55907,6 +56195,17 @@ "Properties": {}, "DefaultProperties": {} }, + "TextureGenerationService": { + "Name": "TextureGenerationService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": {} + }, "ThirdPartyUserService": { "Name": "ThirdPartyUserService", "Tags": [ @@ -59590,6 +59889,22 @@ } } }, + "ChatTranslationLocale": { + "Name": "ChatTranslationLocale", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ChatTranslationToggleEnabled": { "Name": "ChatTranslationToggleEnabled", "Scriptability": "None", @@ -59724,6 +60039,22 @@ } } }, + "FramerateCap": { + "Name": "FramerateCap", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Fullscreen": { "Name": "Fullscreen", "Scriptability": "None", @@ -61068,6 +61399,7 @@ "VRService": { "Name": "VRService", "Tags": [ + "NotBrowsable", "NotCreatable", "Service" ], @@ -61084,7 +61416,22 @@ ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" + } + } + }, + "AvatarGestures": { + "Name": "AvatarGestures", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" } } }, @@ -61111,10 +61458,12 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "NotReplicated" + ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } }, @@ -61124,7 +61473,9 @@ "DataType": { "Enum": "UserCFrame" }, - "Tags": [], + "Tags": [ + "NotReplicated" + ], "Kind": { "Canonical": { "Serialization": "DoesNotSerialize" @@ -61283,12 +61634,21 @@ "Attributes": { "Attributes": {} }, + "AutomaticScaling": { + "Enum": 0 + }, + "AvatarGestures": { + "Bool": false + }, "Capabilities": { "SecurityCapabilities": 0 }, "DefinesCapabilities": { "Bool": false }, + "FadeOutViewOnCollision": { + "Bool": true + }, "SourceAssetId": { "Int64": -1 }, @@ -62839,16 +63199,6 @@ "Properties": {}, "DefaultProperties": {} }, - "VisibilityService": { - "Name": "VisibilityService", - "Tags": [ - "NotCreatable", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": {} - }, "Visit": { "Name": "Visit", "Tags": [ @@ -62933,9 +63283,7 @@ "DataType": { "Enum": "AudioApiRollout" }, - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -65214,14 +65562,6 @@ "Timeout": 10 } }, - "AnimationCompositorMode": { - "name": "AnimationCompositorMode", - "items": { - "Default": 0, - "Disabled": 2, - "Enabled": 1 - } - }, "AnimationPriority": { "name": "AnimationPriority", "items": { @@ -65835,10 +66175,10 @@ "CollaboratorStatus": { "name": "CollaboratorStatus", "items": { - "Editing3D": 0, - "None": 3, - "PrivateScripting": 2, - "Scripting": 1 + "Editing3D": 1, + "None": 0, + "PrivateScripting": 3, + "Scripting": 2 } }, "CollisionFidelity": { @@ -66307,6 +66647,14 @@ "TranslateViewPlane": 4 } }, + "DragDetectorPermissionPolicy": { + "name": "DragDetectorPermissionPolicy", + "items": { + "Everybody": 1, + "Nobody": 0, + "Scriptable": 2 + } + }, "DragDetectorResponseStyle": { "name": "DragDetectorResponseStyle", "items": { @@ -66810,15 +67158,6 @@ "R6": 0 } }, - "HumanoidStateMachineMode": { - "name": "HumanoidStateMachineMode", - "items": { - "Default": 0, - "Legacy": 1, - "LuaStateMachine": 3, - "NoStateMachine": 2 - } - }, "HumanoidStateType": { "name": "HumanoidStateType", "items": { @@ -67469,6 +67808,16 @@ "PersistentPerPlayer": 3 } }, + "ModerationStatus": { + "name": "ModerationStatus", + "items": { + "Invalid": 5, + "NotApplicable": 4, + "NotReviewed": 3, + "ReviewedApproved": 1, + "ReviewedRejected": 2 + } + }, "ModifierKey": { "name": "ModifierKey", "items": { From 02d79a474949dfc9daf6eb0f1a1b583202a3f485 Mon Sep 17 00:00:00 2001 From: Filip Tibell Date: Tue, 20 Feb 2024 23:56:31 +0100 Subject: [PATCH 1380/1504] Migrate to using Rustls (#861) --- .github/workflows/release.yml | 4 - Cargo.lock | 223 +++++++++++++--------------------- Cargo.toml | 4 +- 3 files changed, 86 insertions(+), 145 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5cc781b0..dc85a2b2 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -122,10 +122,6 @@ jobs: # easily. CARGO_TARGET_DIR: output - # On platforms that use OpenSSL, ensure it is statically linked to - # make binaries more portable. - OPENSSL_STATIC: 1 - - name: Create Release Archive shell: bash run: | diff --git a/Cargo.lock b/Cargo.lock index 3e2556f2..71031578 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -519,21 +519,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.0" @@ -849,16 +834,17 @@ dependencies = [ ] [[package]] -name = "hyper-tls" -version = "0.5.0" +name = "hyper-rustls" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ - "bytes", + "futures-util", + "http", "hyper", - "native-tls", + "rustls", "tokio", - "tokio-native-tls", + "tokio-rustls", ] [[package]] @@ -1150,24 +1136,6 @@ dependencies = [ "ws2_32-sys", ] -[[package]] -name = "native-tls" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" -dependencies = [ - "lazy_static", - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "net2" version = "0.2.39" @@ -1257,60 +1225,6 @@ dependencies = [ "winapi 0.3.9", ] -[[package]] -name = "openssl" -version = "0.10.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bac25ee399abb46215765b1cb35bc0212377e58a061560d8b29b024fd0430e7c" -dependencies = [ - "bitflags 2.4.0", - "cfg-if 1.0.0", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-src" -version = "300.1.5+3.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559068e4c12950d7dcaa1857a61725c0d38d4fc03ff8e070ab31a75d6e316491" -dependencies = [ - "cc", -] - -[[package]] -name = "openssl-sys" -version = "0.9.93" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" -dependencies = [ - "cc", - "libc", - "openssl-src", - "pkg-config", - "vcpkg", -] - [[package]] name = "os_str_bytes" version = "6.5.1" @@ -1392,12 +1306,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" -[[package]] -name = "pkg-config" -version = "0.3.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" - [[package]] name = "plotters" version = "0.3.5" @@ -1749,29 +1657,45 @@ dependencies = [ "http", "http-body", "hyper", - "hyper-tls", + "hyper-rustls", "ipnet", "js-sys", "log", "mime", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "rustls", + "rustls-pemfile", "serde", "serde_json", "serde_urlencoded", "system-configuration", "tokio", - "tokio-native-tls", + "tokio-rustls", "tower-service", "url", "wasm-bindgen", "wasm-bindgen-futures", "web-sys", + "webpki-roots", "winreg 0.50.0", ] +[[package]] +name = "ring" +version = "0.17.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +dependencies = [ + "cc", + "getrandom", + "libc", + "spin", + "untrusted", + "windows-sys 0.48.0", +] + [[package]] name = "ritz" version = "0.1.0" @@ -1918,6 +1842,37 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "rustls" +version = "0.21.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +dependencies = [ + "log", + "ring", + "rustls-webpki", + "sct", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" +dependencies = [ + "base64 0.21.4", +] + +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.14" @@ -1939,15 +1894,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "schannel" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" -dependencies = [ - "windows-sys 0.48.0", -] - [[package]] name = "scoped-tls" version = "1.0.1" @@ -1961,26 +1907,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] -name = "security-framework" -version = "2.9.2" +name = "sct" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" -dependencies = [ - "core-foundation-sys", - "libc", + "ring", + "untrusted", ] [[package]] @@ -2124,6 +2057,12 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + [[package]] name = "strsim" version = "0.10.0" @@ -2282,12 +2221,12 @@ dependencies = [ ] [[package]] -name = "tokio-native-tls" -version = "0.3.1" +name = "tokio-rustls" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" dependencies = [ - "native-tls", + "rustls", "tokio", ] @@ -2473,6 +2412,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.4.1" @@ -2500,12 +2445,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" -[[package]] -name = "vcpkg" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" - [[package]] name = "version_check" version = "0.9.4" @@ -2633,6 +2572,12 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + [[package]] name = "winapi" version = "0.2.8" diff --git a/Cargo.toml b/Cargo.toml index 0b5ae9e6..96b3ed7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,10 +72,10 @@ maplit = "1.0.2" num_cpus = "1.15.0" opener = "0.5.0" rayon = "1.7.0" -reqwest = { version = "0.11.10", features = [ +reqwest = { version = "0.11.10", default-features = false, features = [ "blocking", "json", - "native-tls-vendored", + "rustls-tls", ] } ritz = "0.1.0" roblox_install = "1.0.0" From 42121a9fc94dcd59123cf4ae877167c3c79cd04a Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 20 Feb 2024 14:56:55 -0800 Subject: [PATCH 1381/1504] Allow building Rojo with `profile-with-tracy` feature (#862) --- Cargo.lock | 33 ++++++--------------------------- Cargo.toml | 7 ++++--- src/main.rs | 2 +- 3 files changed, 11 insertions(+), 31 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 71031578..4d850356 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1406,19 +1406,19 @@ dependencies = [ [[package]] name = "profiling" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f89dff0959d98c9758c88826cc002e2c3d0b9dfac4139711d1f30de442f1139b" +checksum = "0f0f7f43585c34e4fdd7497d746bc32e14458cf11c69341cc0587b1d825dde42" dependencies = [ "profiling-procmacros", - "tracy-client 0.16.3", + "tracy-client", ] [[package]] name = "profiling-procmacros" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb156a45b6b9fe8027497422179fb65afc84d36707a7ca98297bf06bccb8d43f" +checksum = "ce97fecd27bc49296e5e20518b5a1bb54a14f7d5fe6228bc9686ee2a74915cc8" dependencies = [ "quote 1.0.33", "syn 2.0.37", @@ -1800,7 +1800,6 @@ dependencies = [ "thiserror", "tokio", "toml", - "tracy-client 0.13.2", "uuid", "walkdir", "winreg 0.10.1", @@ -2321,17 +2320,6 @@ dependencies = [ "tracing-log", ] -[[package]] -name = "tracy-client" -version = "0.13.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42ebfe7a24c18b5ba86d8920c124b41b942352f863fbe0c84d3d63428fa1860f" -dependencies = [ - "loom", - "once_cell", - "tracy-client-sys 0.17.1", -] - [[package]] name = "tracy-client" version = "0.16.3" @@ -2340,16 +2328,7 @@ checksum = "03684af8fb393cc7903210d868e4cb9f5c1e156737be38f52c4217fb21b86bf6" dependencies = [ "loom", "once_cell", - "tracy-client-sys 0.21.2", -] - -[[package]] -name = "tracy-client-sys" -version = "0.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "178d021455e83078bb38c00b70046b95117ef0a0312cbef925f426d833d11c79" -dependencies = [ - "cc", + "tracy-client-sys", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 96b3ed7c..de689bf9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,9 @@ default = [] # Enable this feature to live-reload assets from the web UI. dev_live_assets = [] -profile-with-tracy = ["profiling/profile-with-tracy", "tracy-client"] +# Run Rojo with this feature to open a Tracy session. +# Currently uses protocol v63, last supported in Tracy 0.9.1. +profile-with-tracy = ["profiling/profile-with-tracy"] [workspace] members = ["crates/*"] @@ -87,8 +89,7 @@ thiserror = "1.0.30" tokio = { version = "1.12.0", features = ["rt", "rt-multi-thread"] } uuid = { version = "1.0.0", features = ["v4", "serde"] } clap = { version = "3.1.18", features = ["derive"] } -profiling = "1.0.6" -tracy-client = { version = "0.13.2", optional = true } +profiling = "1.0.14" [target.'cfg(windows)'.dependencies] winreg = "0.10.1" diff --git a/src/main.rs b/src/main.rs index 5bb9bc6c..4e0fb507 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,7 +7,7 @@ use librojo::cli::Options; fn main() { #[cfg(feature = "profile-with-tracy")] - tracy_client::Client::start(); + profiling::tracy_client::Client::start(); panic::set_hook(Box::new(|panic_info| { // PanicInfo's payload is usually a &'static str or String. From 48bb76073941234bf27452d6a46e38c8956316d2 Mon Sep 17 00:00:00 2001 From: Micah Date: Tue, 20 Feb 2024 17:25:57 -0800 Subject: [PATCH 1382/1504] Make the `name` field in projects optional (#870) Closes #858. If a project is named `default.project.json`, it acts as an `init` file and gains the name of the folder it's inside of. If it is named something other than `default.project.json`, it gains the name of the file with `.project.json` trimmed off. So e.g. `foo.project.json` becomes `foo`. --- CHANGELOG.md | 6 ++ ...tests__build__no_name_default_project.snap | 22 +++++ ...to_end__tests__build__no_name_project.snap | 22 +++++ ...sts__build__no_name_top_level_project.snap | 13 +++ .../default.project.json | 9 ++ .../src/third-level/default.project.json | 8 ++ .../no_name_project/default.project.json | 9 ++ .../src/bool_value.project.json | 8 ++ .../default.project.json | 8 ++ ...s__serve__no_name_default_project_all.snap | 39 ++++++++ ...__serve__no_name_default_project_info.snap | 14 +++ ...nd__tests__serve__no_name_project_all.snap | 40 ++++++++ ...d__tests__serve__no_name_project_info.snap | 14 +++ ..._serve__no_name_top_level_project_all.snap | 20 ++++ ...serve__no_name_top_level_project_info.snap | 14 +++ .../default.project.json | 9 ++ .../src/third-level/default.project.json | 8 ++ .../no_name_project/default.project.json | 9 ++ .../src/bool_value.project.json | 8 ++ .../default.project.json | 8 ++ src/project.rs | 2 +- src/serve_session.rs | 44 ++++++++- src/snapshot_middleware/mod.rs | 15 +-- src/snapshot_middleware/project.rs | 91 ++++++++++++++----- ...eware__project__test__no_name_project.snap | 19 ++++ tests/tests/build.rs | 5 +- tests/tests/serve.rs | 54 +++++++++++ 27 files changed, 486 insertions(+), 32 deletions(-) create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__no_name_default_project.snap create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__no_name_project.snap create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__no_name_top_level_project.snap create mode 100644 rojo-test/build-tests/no_name_default_project/default.project.json create mode 100644 rojo-test/build-tests/no_name_default_project/src/third-level/default.project.json create mode 100644 rojo-test/build-tests/no_name_project/default.project.json create mode 100644 rojo-test/build-tests/no_name_project/src/bool_value.project.json create mode 100644 rojo-test/build-tests/no_name_top_level_project/default.project.json create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_default_project_all.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_default_project_info.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_project_all.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_project_info.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_top_level_project_all.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_top_level_project_info.snap create mode 100644 rojo-test/serve-tests/no_name_default_project/default.project.json create mode 100644 rojo-test/serve-tests/no_name_default_project/src/third-level/default.project.json create mode 100644 rojo-test/serve-tests/no_name_project/default.project.json create mode 100644 rojo-test/serve-tests/no_name_project/src/bool_value.project.json create mode 100644 rojo-test/serve-tests/no_name_top_level_project/default.project.json create mode 100644 src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__no_name_project.snap diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ccc6752..eb992a72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,11 @@ # Rojo Changelog ## Unreleased Changes +* Made the `name` field optional on project files ([#870]) + Files named `default.project.json` inherit the name of the folder they're in and all other projects + are named as expect (e.g. `foo.project.json` becomes an Instance named `foo`) + + There is no change in behavior if `name` is set. * Fixed incorrect results when serving model pivots ([#868]) * Rojo now converts any line endings to LF, preventing spurious diffs when syncing Lua files on Windows ([#854]) * Fixed Rojo plugin failing to connect when project contains certain unreadable properties ([#848]) @@ -63,6 +68,7 @@ [#848]: https://github.com/rojo-rbx/rojo/pull/848 [#854]: https://github.com/rojo-rbx/rojo/pull/854 [#868]: https://github.com/rojo-rbx/rojo/pull/868 +[#870]: https://github.com/rojo-rbx/rojo/pull/870 ## [7.4.0] - January 16, 2024 diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__no_name_default_project.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__no_name_default_project.snap new file mode 100644 index 00000000..fbbd4911 --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__no_name_default_project.snap @@ -0,0 +1,22 @@ +--- +source: tests/tests/build.rs +expression: contents +--- + + + + top-level + + + + second-level + + + + third-level + 1337 + + + + + diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__no_name_project.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__no_name_project.snap new file mode 100644 index 00000000..58897933 --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__no_name_project.snap @@ -0,0 +1,22 @@ +--- +source: tests/tests/build.rs +expression: contents +--- + + + + no_name_project + + + + second-level + + + + bool_value + true + + + + + diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__no_name_top_level_project.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__no_name_top_level_project.snap new file mode 100644 index 00000000..2f2e3d6a --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__no_name_top_level_project.snap @@ -0,0 +1,13 @@ +--- +source: tests/tests/build.rs +assertion_line: 107 +expression: contents +--- + + + + no_name_top_level_project + If this isn't named `no_name_top_level_project`, something went wrong! + + + diff --git a/rojo-test/build-tests/no_name_default_project/default.project.json b/rojo-test/build-tests/no_name_default_project/default.project.json new file mode 100644 index 00000000..1c2a1400 --- /dev/null +++ b/rojo-test/build-tests/no_name_default_project/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "top-level", + "tree": { + "$className": "Folder", + "second-level": { + "$path": "src" + } + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/no_name_default_project/src/third-level/default.project.json b/rojo-test/build-tests/no_name_default_project/src/third-level/default.project.json new file mode 100644 index 00000000..e7b87be1 --- /dev/null +++ b/rojo-test/build-tests/no_name_default_project/src/third-level/default.project.json @@ -0,0 +1,8 @@ +{ + "tree": { + "$className": "IntValue", + "$properties": { + "Value": 1337 + } + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/no_name_project/default.project.json b/rojo-test/build-tests/no_name_project/default.project.json new file mode 100644 index 00000000..93ef2e8c --- /dev/null +++ b/rojo-test/build-tests/no_name_project/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "no_name_project", + "tree": { + "$className": "Folder", + "second-level": { + "$path": "src" + } + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/no_name_project/src/bool_value.project.json b/rojo-test/build-tests/no_name_project/src/bool_value.project.json new file mode 100644 index 00000000..6be58a3c --- /dev/null +++ b/rojo-test/build-tests/no_name_project/src/bool_value.project.json @@ -0,0 +1,8 @@ +{ + "tree": { + "$className": "BoolValue", + "$properties": { + "Value": true + } + } +} \ No newline at end of file diff --git a/rojo-test/build-tests/no_name_top_level_project/default.project.json b/rojo-test/build-tests/no_name_top_level_project/default.project.json new file mode 100644 index 00000000..845ae372 --- /dev/null +++ b/rojo-test/build-tests/no_name_top_level_project/default.project.json @@ -0,0 +1,8 @@ +{ + "tree": { + "$className": "StringValue", + "$properties": { + "Value": "If this isn't named `no_name_top_level_project`, something went wrong!" + } + } +} \ No newline at end of file diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_default_project_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_default_project_all.snap new file mode 100644 index 00000000..a8179a91 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_default_project_all.snap @@ -0,0 +1,39 @@ +--- +source: tests/tests/serve.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Children: + - id-3 + ClassName: Folder + Id: id-2 + Metadata: + ignoreUnknownInstances: true + Name: top-level + Parent: "00000000000000000000000000000000" + Properties: {} + id-3: + Children: + - id-4 + ClassName: Folder + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: second-level + Parent: id-2 + Properties: {} + id-4: + Children: [] + ClassName: IntValue + Id: id-4 + Metadata: + ignoreUnknownInstances: true + Name: third-level + Parent: id-3 + Properties: + Value: + Int64: 1337 +messageCursor: 0 +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_default_project_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_default_project_info.snap new file mode 100644 index 00000000..954ba622 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_default_project_info.snap @@ -0,0 +1,14 @@ +--- +source: tests/tests/serve.rs +assertion_line: 316 +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +gameId: ~ +placeId: ~ +projectName: top-level +protocolVersion: 4 +rootInstanceId: id-2 +serverVersion: "[server-version]" +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_project_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_project_all.snap new file mode 100644 index 00000000..1b398a92 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_project_all.snap @@ -0,0 +1,40 @@ +--- +source: tests/tests/serve.rs +assertion_line: 338 +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Children: + - id-3 + ClassName: Folder + Id: id-2 + Metadata: + ignoreUnknownInstances: true + Name: no_name_project + Parent: "00000000000000000000000000000000" + Properties: {} + id-3: + Children: + - id-4 + ClassName: Folder + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: second-level + Parent: id-2 + Properties: {} + id-4: + Children: [] + ClassName: BoolValue + Id: id-4 + Metadata: + ignoreUnknownInstances: true + Name: bool_value + Parent: id-3 + Properties: + Value: + Bool: true +messageCursor: 0 +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_project_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_project_info.snap new file mode 100644 index 00000000..d9772de1 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_project_info.snap @@ -0,0 +1,14 @@ +--- +source: tests/tests/serve.rs +assertion_line: 335 +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +gameId: ~ +placeId: ~ +projectName: no_name_project +protocolVersion: 4 +rootInstanceId: id-2 +serverVersion: "[server-version]" +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_top_level_project_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_top_level_project_all.snap new file mode 100644 index 00000000..ea52fe4b --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_top_level_project_all.snap @@ -0,0 +1,20 @@ +--- +source: tests/tests/serve.rs +assertion_line: 357 +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Children: [] + ClassName: StringValue + Id: id-2 + Metadata: + ignoreUnknownInstances: true + Name: no_name_top_level_project + Parent: "00000000000000000000000000000000" + Properties: + Value: + String: "If this isn't named `no_name_top_level_project`, something went wrong!" +messageCursor: 0 +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_top_level_project_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_top_level_project_info.snap new file mode 100644 index 00000000..3ad79c37 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__no_name_top_level_project_info.snap @@ -0,0 +1,14 @@ +--- +source: tests/tests/serve.rs +assertion_line: 351 +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +gameId: ~ +placeId: ~ +projectName: no_name_top_level_project +protocolVersion: 4 +rootInstanceId: id-2 +serverVersion: "[server-version]" +sessionId: id-1 + diff --git a/rojo-test/serve-tests/no_name_default_project/default.project.json b/rojo-test/serve-tests/no_name_default_project/default.project.json new file mode 100644 index 00000000..1c2a1400 --- /dev/null +++ b/rojo-test/serve-tests/no_name_default_project/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "top-level", + "tree": { + "$className": "Folder", + "second-level": { + "$path": "src" + } + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/no_name_default_project/src/third-level/default.project.json b/rojo-test/serve-tests/no_name_default_project/src/third-level/default.project.json new file mode 100644 index 00000000..e7b87be1 --- /dev/null +++ b/rojo-test/serve-tests/no_name_default_project/src/third-level/default.project.json @@ -0,0 +1,8 @@ +{ + "tree": { + "$className": "IntValue", + "$properties": { + "Value": 1337 + } + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/no_name_project/default.project.json b/rojo-test/serve-tests/no_name_project/default.project.json new file mode 100644 index 00000000..93ef2e8c --- /dev/null +++ b/rojo-test/serve-tests/no_name_project/default.project.json @@ -0,0 +1,9 @@ +{ + "name": "no_name_project", + "tree": { + "$className": "Folder", + "second-level": { + "$path": "src" + } + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/no_name_project/src/bool_value.project.json b/rojo-test/serve-tests/no_name_project/src/bool_value.project.json new file mode 100644 index 00000000..6be58a3c --- /dev/null +++ b/rojo-test/serve-tests/no_name_project/src/bool_value.project.json @@ -0,0 +1,8 @@ +{ + "tree": { + "$className": "BoolValue", + "$properties": { + "Value": true + } + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/no_name_top_level_project/default.project.json b/rojo-test/serve-tests/no_name_top_level_project/default.project.json new file mode 100644 index 00000000..845ae372 --- /dev/null +++ b/rojo-test/serve-tests/no_name_top_level_project/default.project.json @@ -0,0 +1,8 @@ +{ + "tree": { + "$className": "StringValue", + "$properties": { + "Value": "If this isn't named `no_name_top_level_project`, something went wrong!" + } + } +} \ No newline at end of file diff --git a/src/project.rs b/src/project.rs index 1095fba2..bf6bc163 100644 --- a/src/project.rs +++ b/src/project.rs @@ -39,7 +39,7 @@ enum Error { #[serde(deny_unknown_fields, rename_all = "camelCase")] pub struct Project { /// The name of the top-level instance described by the project. - pub name: String, + pub name: Option, /// The tree of instances described by this project. Projects always /// describe at least one instance. diff --git a/src/serve_session.rs b/src/serve_session.rs index 85ae7793..dbc841d7 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -110,7 +110,7 @@ impl ServeSession { log::debug!("Loading project file from {}", project_path.display()); - let root_project = match vfs.read(&project_path).with_not_found()? { + let mut root_project = match vfs.read(&project_path).with_not_found()? { Some(contents) => Project::load_from_slice(&contents, &project_path)?, None => { return Err(ServeSessionError::NoProjectFound { @@ -118,6 +118,35 @@ impl ServeSession { }); } }; + if root_project.name.is_none() { + if let Some(file_name) = project_path.file_name().and_then(|s| s.to_str()) { + if file_name == "default.project.json" { + let folder_name = project_path + .parent() + .and_then(Path::file_name) + .and_then(|s| s.to_str()); + if let Some(folder_name) = folder_name { + root_project.name = Some(folder_name.to_string()); + } else { + return Err(ServeSessionError::FolderNameInvalid { + path: project_path.to_path_buf(), + }); + } + } else if let Some(trimmed) = file_name.strip_suffix(".project.json") { + root_project.name = Some(trimmed.to_string()); + } else { + return Err(ServeSessionError::ProjectNameInvalid { + path: project_path.to_path_buf(), + }); + } + } else { + return Err(ServeSessionError::ProjectNameInvalid { + path: project_path.to_path_buf(), + }); + } + } + // Rebind it to make it no longer mutable + let root_project = root_project; let mut tree = RojoTree::new(InstanceSnapshot::new()); @@ -190,7 +219,10 @@ impl ServeSession { } pub fn project_name(&self) -> &str { - &self.root_project.name + self.root_project + .name + .as_ref() + .expect("all top-level projects must have their name set") } pub fn project_port(&self) -> Option { @@ -231,6 +263,14 @@ pub enum ServeSessionError { )] NoProjectFound { path: PathBuf }, + #[error("The folder for the provided project cannot be used as a project name: {}\n\ + Consider setting the `name` field on this project.", .path.display())] + FolderNameInvalid { path: PathBuf }, + + #[error("The file name of the provided project cannot be used as a project name: {}.\n\ + Consider setting the `name` field on this project.", .path.display())] + ProjectNameInvalid { path: PathBuf }, + #[error(transparent)] Io { #[from] diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 30ea5706..1c95154e 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -66,7 +66,13 @@ pub fn snapshot_from_vfs( for rule in default_sync_rules() { if rule.matches(&init_path) { return match rule.middleware { - Middleware::Project => snapshot_project(context, vfs, &init_path), + Middleware::Project => { + let name = init_path + .parent() + .and_then(Path::file_name) + .and_then(|s| s.to_str()).expect("default.project.json should be inside a folder with a unicode name"); + snapshot_project(context, vfs, &init_path, name) + } Middleware::ModuleScript => { snapshot_lua_init(context, vfs, &init_path, ScriptType::Module) @@ -218,9 +224,7 @@ impl Middleware { Self::ServerScript => snapshot_lua(context, vfs, path, name, ScriptType::Server), Self::ClientScript => snapshot_lua(context, vfs, path, name, ScriptType::Client), Self::ModuleScript => snapshot_lua(context, vfs, path, name, ScriptType::Module), - // At the moment, snapshot_project does not use `name` so we - // don't provide it. - Self::Project => snapshot_project(context, vfs, path), + Self::Project => snapshot_project(context, vfs, path, name), Self::Rbxm => snapshot_rbxm(context, vfs, path, name), Self::Rbxmx => snapshot_rbxmx(context, vfs, path, name), Self::Toml => snapshot_toml(context, vfs, path, name), @@ -280,8 +284,7 @@ fn default_sync_rules() -> &'static [SyncRule] { sync_rule!("*.client.lua", ClientScript, ".client.lua"), sync_rule!("*.client.luau", ClientScript, ".client.luau"), sync_rule!("*.{lua,luau}", ModuleScript), - // Project middleware doesn't use the file name. - sync_rule!("*.project.json", Project), + sync_rule!("*.project.json", Project, ".project.json"), sync_rule!("*.model.json", JsonModel, ".model.json"), sync_rule!("*.json", Json, ".json", "*.meta.json"), sync_rule!("*.toml", Toml), diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index c92f42d8..31ca7dc2 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -19,9 +19,11 @@ pub fn snapshot_project( context: &InstanceContext, vfs: &Vfs, path: &Path, + name: &str, ) -> anyhow::Result> { let project = Project::load_from_slice(&vfs.read(path)?, path) .with_context(|| format!("File was not a valid Rojo project: {}", path.display()))?; + let project_name = project.name.as_deref().unwrap_or(name); let mut context = context.clone(); context.clear_sync_rules(); @@ -45,7 +47,7 @@ pub fn snapshot_project( .unwrap(), ); - match snapshot_project_node(&context, path, &project.name, &project.tree, vfs, None)? { + match snapshot_project_node(&context, path, project_name, &project.tree, vfs, None)? { Some(found_snapshot) => { let mut snapshot = found_snapshot; // Setting the instigating source to the project file path is a little @@ -354,12 +356,16 @@ mod test { ) .unwrap(); - let mut vfs = Vfs::new(imfs); + let vfs = Vfs::new(imfs); - let instance_snapshot = - snapshot_project(&InstanceContext::default(), &mut vfs, Path::new("/foo")) - .expect("snapshot error") - .expect("snapshot returned no instances"); + let instance_snapshot = snapshot_project( + &InstanceContext::default(), + &vfs, + Path::new("/foo"), + "NOT_IN_SNAPSHOT", + ) + .expect("snapshot error") + .expect("snapshot returned no instances"); insta::assert_yaml_snapshot!(instance_snapshot); } @@ -384,12 +390,13 @@ mod test { ) .unwrap(); - let mut vfs = Vfs::new(imfs); + let vfs = Vfs::new(imfs); let instance_snapshot = snapshot_project( &InstanceContext::default(), - &mut vfs, + &vfs, Path::new("/foo/hello.project.json"), + "NOT_IN_SNAPSHOT", ) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -422,12 +429,13 @@ mod test { ) .unwrap(); - let mut vfs = Vfs::new(imfs); + let vfs = Vfs::new(imfs); let instance_snapshot = snapshot_project( &InstanceContext::default(), - &mut vfs, + &vfs, Path::new("/foo.project.json"), + "NOT_IN_SNAPSHOT", ) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -458,12 +466,13 @@ mod test { ) .unwrap(); - let mut vfs = Vfs::new(imfs); + let vfs = Vfs::new(imfs); let instance_snapshot = snapshot_project( &InstanceContext::default(), - &mut vfs, + &vfs, Path::new("/foo.project.json"), + "NOT_IN_SNAPSHOT", ) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -495,12 +504,13 @@ mod test { ) .unwrap(); - let mut vfs = Vfs::new(imfs); + let vfs = Vfs::new(imfs); let instance_snapshot = snapshot_project( &InstanceContext::default(), - &mut vfs, + &vfs, Path::new("/foo.project.json"), + "NOT_IN_SNAPSHOT", ) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -529,12 +539,13 @@ mod test { ) .unwrap(); - let mut vfs = Vfs::new(imfs); + let vfs = Vfs::new(imfs); let instance_snapshot = snapshot_project( &InstanceContext::default(), - &mut vfs, + &vfs, Path::new("/foo/default.project.json"), + "NOT_IN_SNAPSHOT", ) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -570,12 +581,13 @@ mod test { ) .unwrap(); - let mut vfs = Vfs::new(imfs); + let vfs = Vfs::new(imfs); let instance_snapshot = snapshot_project( &InstanceContext::default(), - &mut vfs, + &vfs, Path::new("/foo/default.project.json"), + "NOT_IN_SNAPSHOT", ) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -615,12 +627,13 @@ mod test { ) .unwrap(); - let mut vfs = Vfs::new(imfs); + let vfs = Vfs::new(imfs); let instance_snapshot = snapshot_project( &InstanceContext::default(), - &mut vfs, + &vfs, Path::new("/foo/default.project.json"), + "NOT_IN_SNAPSHOT", ) .expect("snapshot error") .expect("snapshot returned no instances"); @@ -665,12 +678,46 @@ mod test { ) .unwrap(); - let mut vfs = Vfs::new(imfs); + let vfs = Vfs::new(imfs); let instance_snapshot = snapshot_project( &InstanceContext::default(), - &mut vfs, + &vfs, Path::new("/foo/default.project.json"), + "NOT_IN_SNAPSHOT", + ) + .expect("snapshot error") + .expect("snapshot returned no instances"); + + insta::assert_yaml_snapshot!(instance_snapshot); + } + + #[test] + fn no_name_project() { + let _ = env_logger::try_init(); + + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot( + "/foo", + VfsSnapshot::dir(hashmap! { + "default.project.json" => VfsSnapshot::file(r#" + { + "tree": { + "$className": "Model" + } + } + "#), + }), + ) + .unwrap(); + + let vfs = Vfs::new(imfs); + + let instance_snapshot = snapshot_project( + &InstanceContext::default(), + &vfs, + Path::new("/foo/default.project.json"), + "no_name_project", ) .expect("snapshot error") .expect("snapshot returned no instances"); diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__no_name_project.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__no_name_project.snap new file mode 100644 index 00000000..289c292c --- /dev/null +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__no_name_project.snap @@ -0,0 +1,19 @@ +--- +source: src/snapshot_middleware/project.rs +assertion_line: 725 +expression: instance_snapshot +--- +snapshot_id: "00000000000000000000000000000000" +metadata: + ignore_unknown_instances: true + instigating_source: + Path: /foo/default.project.json + relevant_paths: + - /foo/default.project.json + context: + emit_legacy_scripts: true +name: no_name_project +class_name: Model +properties: {} +children: [] + diff --git a/tests/tests/build.rs b/tests/tests/build.rs index f23d4a4e..8c533115 100644 --- a/tests/tests/build.rs +++ b/tests/tests/build.rs @@ -62,6 +62,9 @@ gen_build_tests! { sync_rule_alone, sync_rule_complex, sync_rule_nested_projects, + no_name_default_project, + no_name_project, + no_name_top_level_project, } fn run_build_test(test_name: &str) { @@ -73,7 +76,7 @@ fn run_build_test(test_name: &str) { let output_path = output_dir.path().join(format!("{}.rbxmx", test_name)); let output = Command::new(ROJO_PATH) - .args(&[ + .args([ "build", input_path.to_str().unwrap(), "-o", diff --git a/tests/tests/serve.rs b/tests/tests/serve.rs index 5d716b39..23cbe942 100644 --- a/tests/tests/serve.rs +++ b/tests/tests/serve.rs @@ -306,3 +306,57 @@ fn sync_rule_no_extension() { ); }); } + +#[test] +fn no_name_default_project() { + run_serve_test("no_name_default_project", |session, mut redactions| { + let info = session.get_api_rojo().unwrap(); + let root_id = info.root_instance_id; + + assert_yaml_snapshot!( + "no_name_default_project_info", + redactions.redacted_yaml(info) + ); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "no_name_default_project_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); + }); +} + +#[test] +fn no_name_project() { + run_serve_test("no_name_project", |session, mut redactions| { + let info = session.get_api_rojo().unwrap(); + let root_id = info.root_instance_id; + + assert_yaml_snapshot!("no_name_project_info", redactions.redacted_yaml(info)); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "no_name_project_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); + }); +} + +#[test] +fn no_name_top_level_project() { + run_serve_test("no_name_top_level_project", |session, mut redactions| { + let info = session.get_api_rojo().unwrap(); + let root_id = info.root_instance_id; + + assert_yaml_snapshot!( + "no_name_top_level_project_info", + redactions.redacted_yaml(info) + ); + + let read_response = session.get_api_read(root_id).unwrap(); + assert_yaml_snapshot!( + "no_name_top_level_project_all", + read_response.intern_and_redact(&mut redactions, root_id) + ); + }); +} From 5f51538e0b37188a32bb4fe6d6fdd697040938ea Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Tue, 20 Feb 2024 17:46:01 -0800 Subject: [PATCH 1383/1504] Update master's changelog in preparation for 7.4.1 release (#873) This PR edits the changelog on master to reflect 7.4.1's release --- CHANGELOG.md | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eb992a72..2e564901 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,18 +1,9 @@ # Rojo Changelog ## Unreleased Changes -* Made the `name` field optional on project files ([#870]) - Files named `default.project.json` inherit the name of the folder they're in and all other projects - are named as expect (e.g. `foo.project.json` becomes an Instance named `foo`) - - There is no change in behavior if `name` is set. -* Fixed incorrect results when serving model pivots ([#868]) -* Rojo now converts any line endings to LF, preventing spurious diffs when syncing Lua files on Windows ([#854]) -* Fixed Rojo plugin failing to connect when project contains certain unreadable properties ([#848]) * Added popout diff visualizer for table properties like Attributes and Tags ([#834]) * Updated Theme to use Studio colors ([#838]) * Added experimental setting for Auto Connect in playtests ([#840]) -* Fixed http error handling so Rojo can be used in Github Codespaces ([#847]) * Projects may now specify rules for syncing files as if they had a different file extension. ([#813]) This is specified via a new field on project files, `syncRules`: @@ -64,13 +55,30 @@ [#834]: https://github.com/rojo-rbx/rojo/pull/834 [#838]: https://github.com/rojo-rbx/rojo/pull/838 [#840]: https://github.com/rojo-rbx/rojo/pull/840 -[#847]: https://github.com/rojo-rbx/rojo/pull/847 + +## [7.4.1] - February 20, 2024 +* Made the `name` field optional on project files ([#870]) + + Files named `default.project.json` inherit the name of the folder they're in and all other projects + are named as expect (e.g. `foo.project.json` becomes an Instance named `foo`) + + There is no change in behavior if `name` is set. +* Fixed incorrect results when building model pivots ([#865]) +* Fixed incorrect results when serving model pivots ([#868]) +* Rojo now converts any line endings to LF, preventing spurious diffs when syncing Lua files on Windows ([#854]) +* Fixed Rojo plugin failing to connect when project contains certain unreadable properties ([#848]) +* Fixed various cases where patch visualizer would not display sync failures ([#845], [#844]) +* Fixed http error handling so Rojo can be used in Github Codespaces ([#847]) + [#848]: https://github.com/rojo-rbx/rojo/pull/848 +[#845]: https://github.com/rojo-rbx/rojo/pull/845 +[#844]: https://github.com/rojo-rbx/rojo/pull/844 +[#847]: https://github.com/rojo-rbx/rojo/pull/847 [#854]: https://github.com/rojo-rbx/rojo/pull/854 +[#865]: https://github.com/rojo-rbx/rojo/pull/865 [#868]: https://github.com/rojo-rbx/rojo/pull/868 [#870]: https://github.com/rojo-rbx/rojo/pull/870 - ## [7.4.0] - January 16, 2024 * Improved the visualization for array properties like Tags ([#829]) * Significantly improved performance of `rojo serve`, `rojo build --watch`, and `rojo sourcemap --watch` on macOS. ([#830]) From edf87bf9a3be6537b5c8c5ece96d3bdfe296fc2a Mon Sep 17 00:00:00 2001 From: boatbomber Date: Thu, 29 Feb 2024 14:27:46 -0800 Subject: [PATCH 1384/1504] Build tree ancestry correctly (#882) --- plugin/src/PatchTree.lua | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/plugin/src/PatchTree.lua b/plugin/src/PatchTree.lua index d0d99e37..6d871001 100644 --- a/plugin/src/PatchTree.lua +++ b/plugin/src/PatchTree.lua @@ -163,8 +163,7 @@ function Tree:buildAncestryNodes(previousId: string?, ancestryIds: { string }, p -- Build nodes for ancestry by going up the tree previousId = previousId or "ROOT" - for i = #ancestryIds, 1, -1 do - local ancestorId = ancestryIds[i] + for _, ancestorId in ancestryIds do local value = instanceMap.fromIds[ancestorId] or patch.added[ancestorId] if not value then Log.warn("Failed to find ancestor object for " .. ancestorId) @@ -200,7 +199,7 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) end -- Gather ancestors from existing DOM - local ancestryIds, ancestryIndex = {}, 0 + local ancestryIds = {} local parentObject = instance.Parent local parentId = instanceMap.fromInstances[parentObject] local previousId = nil @@ -211,8 +210,7 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) break end - ancestryIndex += 1 - ancestryIds[ancestryIndex] = parentId + table.insert(ancestryIds, 1, parentId) knownAncestors[parentId] = true parentObject = parentObject.Parent parentId = instanceMap.fromInstances[parentObject] From 26181a5a1f8336892eec5b61df74e10e2cd1774a Mon Sep 17 00:00:00 2001 From: boatbomber Date: Thu, 29 Feb 2024 14:50:06 -0800 Subject: [PATCH 1385/1504] Use GuiState instead of manual calculation for tooltips (#884) --- plugin/src/App/Components/Tooltip.lua | 35 ++++++++++++--------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/plugin/src/App/Components/Tooltip.lua b/plugin/src/App/Components/Tooltip.lua index 27822095..2ab7e19a 100644 --- a/plugin/src/App/Components/Tooltip.lua +++ b/plugin/src/App/Components/Tooltip.lua @@ -163,7 +163,6 @@ local Trigger = Roact.Component:extend("TooltipTrigger") function Trigger:init() self.id = HttpService:GenerateGUID(false) self.ref = Roact.createRef() - self.mousePos = Vector2.zero self.showingPopup = false self.destroy = function() @@ -195,18 +194,22 @@ end function Trigger:isHovering() local rbx = self.ref.current if rbx then - local pos = rbx.AbsolutePosition - local size = rbx.AbsoluteSize - local mousePos = self.mousePos - - return mousePos.X >= pos.X - and mousePos.X <= pos.X + size.X - and mousePos.Y >= pos.Y - and mousePos.Y <= pos.Y + size.Y + return rbx.GuiState == Enum.GuiState.Hover end return false end +function Trigger:getMousePos() + local rbx = self.ref.current + if rbx then + local widget = rbx:FindFirstAncestorOfClass("DockWidgetPluginGui") + if widget then + return widget:GetRelativeMousePosition() + end + end + return Vector2.zero +end + function Trigger:managePopup() if self:isHovering() then if self.showingPopup or self.showDelayThread then @@ -217,7 +220,7 @@ function Trigger:managePopup() self.showDelayThread = task.delay(DELAY, function() self.props.context.addTip(self.id, { Text = self.props.text, - Position = self.mousePos, + Position = self:getMousePos(), Trigger = self.ref, }) self.showDelayThread = nil @@ -234,13 +237,7 @@ function Trigger:managePopup() end function Trigger:render() - local function recalculate(rbx) - local widget = rbx:FindFirstAncestorOfClass("DockWidgetPluginGui") - if not widget then - return - end - self.mousePos = widget:GetRelativeMousePosition() - + local function recalculate() self:managePopup() end @@ -250,11 +247,9 @@ function Trigger:render() ZIndex = self.props.zIndex or 100, [Roact.Ref] = self.ref, + [Roact.Change.GuiState] = recalculate, [Roact.Change.AbsolutePosition] = recalculate, [Roact.Change.AbsoluteSize] = recalculate, - [Roact.Event.MouseMoved] = recalculate, - [Roact.Event.MouseLeave] = recalculate, - [Roact.Event.MouseEnter] = recalculate, }) end From 856d43ce6971147ac64cd497c2e829be926e2231 Mon Sep 17 00:00:00 2001 From: Micah Date: Mon, 4 Mar 2024 15:20:58 -0800 Subject: [PATCH 1386/1504] Update Cargo dependencies (#887) --- Cargo.lock | 753 +++++++++++++++---------------- Cargo.toml | 68 +-- crates/memofs/Cargo.toml | 8 +- crates/rojo-insta-ext/Cargo.toml | 4 +- 4 files changed, 409 insertions(+), 424 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4d850356..2ab8e01e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,18 +19,18 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "aho-corasick" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" +checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" dependencies = [ "memchr", ] [[package]] name = "anyhow" -version = "1.0.75" +version = "1.0.80" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" +checksum = "5ad32ce52e4161730f7098c077cd2ed6229b5804ccf99e5366be1ab72a98b4e1" [[package]] name = "arrayref" @@ -84,9 +84,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.4" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" [[package]] name = "bincode" @@ -105,9 +105,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.0" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4682ae6287fcf752ecaabbfcc7b6f9b72aa33933dc23a554d853aea8eea8635" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" [[package]] name = "blake3" @@ -133,26 +133,26 @@ dependencies = [ [[package]] name = "bstr" -version = "1.6.2" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c2f7349907b712260e64b0afe2f84692af14a454be26187d9df565c7f69266a" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" dependencies = [ "memchr", - "regex-automata 0.3.9", + "regex-automata 0.4.6", "serde", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "8ea184aa71bb362a1157c896979544cc23974e08fd265f29ea96b59f0b4a555b" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" @@ -168,12 +168,9 @@ checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" [[package]] name = "cc" -version = "1.0.83" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" -dependencies = [ - "libc", -] +checksum = "a0ba8f7aaa012f30d5b2861462f6708eccd49c3c39863fe083a308035f63d723" [[package]] name = "cfg-if" @@ -208,11 +205,11 @@ dependencies = [ "bitflags 1.3.2", "clap_derive", "clap_lex", - "indexmap", + "indexmap 1.9.3", "once_cell", "strsim", "termcolor", - "textwrap 0.16.0", + "textwrap 0.16.1", ] [[package]] @@ -223,8 +220,8 @@ checksum = "ae6371b8bdc8b7d3959e9cf7b22d4435ef3e79e138688421ec654acf8c81b008" dependencies = [ "heck", "proc-macro-error", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", ] @@ -239,14 +236,14 @@ dependencies = [ [[package]] name = "console" -version = "0.15.7" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8" +checksum = "0e1f83fc076bd6dd27517eacdf25fef6c4dfe5f1d7448bafaaf3a26f13b5e4eb" dependencies = [ "encode_unicode", "lazy_static", "libc", - "windows-sys 0.45.0", + "windows-sys 0.52.0", ] [[package]] @@ -257,9 +254,9 @@ checksum = "f7144d30dcf0fafbce74250a3963025d8d52177934239851c917d29f1df280c2" [[package]] name = "core-foundation" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146" +checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" dependencies = [ "core-foundation-sys", "libc", @@ -267,15 +264,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.4" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e496a50fda8aacccc86d7529e2c1e0892dbd0f898a6b5645b5561b89c3210efa" +checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "cpufeatures" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a17b76ff3a4162b0b27f354a0c87015ddad39d35f9c0c36607a3bdd175dde1f1" +checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" dependencies = [ "libc", ] @@ -318,46 +315,37 @@ dependencies = [ [[package]] name = "crossbeam-channel" -version = "0.5.8" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a33c2bf77f2df06183c3aa30d1e96c0695a313d4f9c453cc3762a6db39f99200" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ - "cfg-if 1.0.0", "crossbeam-utils", ] [[package]] name = "crossbeam-deque" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6fd6f855243022dcecf8702fef0c297d4338e226845fe067f6341ad9fa0cef" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "cfg-if 1.0.0", "crossbeam-epoch", "crossbeam-utils", ] [[package]] name = "crossbeam-epoch" -version = "0.9.15" +version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "autocfg", - "cfg-if 1.0.0", "crossbeam-utils", - "memoffset", - "scopeguard", ] [[package]] name = "crossbeam-utils" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" -dependencies = [ - "cfg-if 1.0.0", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crypto-common" @@ -429,9 +417,9 @@ dependencies = [ [[package]] name = "either" -version = "1.9.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" +checksum = "11157ac094ffbdde99aa67b23417ebdd801842852b500e395a45a9c0aac03e4a" [[package]] name = "embed-resource" @@ -475,24 +463,19 @@ dependencies = [ ] [[package]] -name = "errno" -version = "0.3.4" +name = "equivalent" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "add4f07d43996f76ef320709726a556a9d4f965d9410d8d0271132d2f8293480" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.48.0", -] +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "errno" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245" dependencies = [ - "cc", "libc", + "windows-sys 0.52.0", ] [[package]] @@ -503,14 +486,14 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if 1.0.0", "libc", - "redox_syscall 0.3.5", - "windows-sys 0.48.0", + "redox_syscall", + "windows-sys 0.52.0", ] [[package]] @@ -521,18 +504,21 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" [[package]] name = "form_urlencoded" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a62bc1cf6f830c2ec14a513a9fb124d0a213a629668a4186f329db21fe045652" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] [[package]] name = "fs-err" -version = "2.9.0" +version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0845fa252299212f0389d64ba26f34fa32cfe41588355f21ed507c59a0f64541" +checksum = "88a41f105fe1d5b6b34b2055e3dc59bb79b46b48b2040b9e6c7b4b5de097aa41" +dependencies = [ + "autocfg", +] [[package]] name = "fsevent" @@ -571,9 +557,9 @@ checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" [[package]] name = "futures" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" dependencies = [ "futures-channel", "futures-core", @@ -586,9 +572,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" dependencies = [ "futures-core", "futures-sink", @@ -596,15 +582,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" dependencies = [ "futures-core", "futures-task", @@ -613,38 +599,38 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.52", ] [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" dependencies = [ "futures-channel", "futures-core", @@ -683,9 +669,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.10" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if 1.0.0", "libc", @@ -694,28 +680,28 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.0" +version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8d784f27acf97159b40fc4db5ecd8aa23b9ad5ef69cdd136d3bc80665f0c0" +checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" [[package]] name = "globset" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "759c97c1e17c55525b57192c06a267cda0ac5210b222d6b82189a2338fa1c13d" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" dependencies = [ "aho-corasick", "bstr", - "fnv", "log", - "regex", + "regex-automata 0.4.6", + "regex-syntax 0.8.2", ] [[package]] name = "h2" -version = "0.3.21" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91fc23aa11be92976ef4729127f1a74adf36d8436f7816b185d18df956790833" +checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" dependencies = [ "bytes", "fnv", @@ -723,7 +709,7 @@ dependencies = [ "futures-sink", "futures-util", "http", - "indexmap", + "indexmap 2.2.5", "slab", "tokio", "tokio-util", @@ -732,9 +718,9 @@ dependencies = [ [[package]] name = "half" -version = "1.8.2" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" +checksum = "1b43ede17f21864e81be2fa654110bf1e793774238d86ef8555c37e6519c0403" [[package]] name = "hashbrown" @@ -742,6 +728,12 @@ version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" +[[package]] +name = "hashbrown" +version = "0.14.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" + [[package]] name = "heck" version = "0.4.1" @@ -759,9 +751,9 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.3.3" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" [[package]] name = "htmlescape" @@ -771,9 +763,9 @@ checksum = "e9025058dae765dee5070ec375f591e2ba14638c63feff74f13805a72e523163" [[package]] name = "http" -version = "0.2.9" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -782,9 +774,9 @@ dependencies = [ [[package]] name = "http-body" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" dependencies = [ "bytes", "http", @@ -811,9 +803,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.27" +version = "0.14.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" dependencies = [ "bytes", "futures-channel", @@ -826,7 +818,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2", "tokio", "tower-service", "tracing", @@ -849,9 +841,9 @@ dependencies = [ [[package]] name = "idna" -version = "0.4.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d20d6b07bfbc108882d88ed8e37d39636dcc260e15e30c45e6ba089610b917c" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -864,7 +856,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.12.3", +] + +[[package]] +name = "indexmap" +version = "2.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +dependencies = [ + "equivalent", + "hashbrown 0.14.3", ] [[package]] @@ -889,9 +891,9 @@ dependencies = [ [[package]] name = "insta" -version = "1.33.0" +version = "1.36.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aa511b2e298cd49b1856746f6bb73e17036bcd66b25f5e92cdcdbec9bd75686" +checksum = "0a7c22c4d34ef4788c351e971c52bfdfe7ea2766f8c5466bc175dd46e52ac22e" dependencies = [ "console", "lazy_static", @@ -914,9 +916,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28b29a3cd74f0f4598934efe3aeba42bae0eb4680554128851ebbecb02af14e6" +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "itertools" @@ -929,9 +931,9 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.9" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" +checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" [[package]] name = "jod-thread" @@ -941,9 +943,9 @@ checksum = "8b23360e99b8717f20aaa4598f5a6541efbe30630039fbc7706cf954a87947ae" [[package]] name = "js-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -972,9 +974,20 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "libc" -version = "0.2.148" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" + +[[package]] +name = "libredox" +version = "0.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +dependencies = [ + "bitflags 2.4.2", + "libc", + "redox_syscall", +] [[package]] name = "linked-hash-map" @@ -984,21 +997,21 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.4.8" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3852614a3bd9ca9804678ba6be5e3b8ce76dfc902cae004e3e0c44051b6e88db" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "loom" -version = "0.5.6" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff50ecb28bb86013e935fb6683ab1f6d3a20016f123c76fd4c27470076ac30f5" +checksum = "7e045d70ddfbc984eacfa964ded019534e8f6cbf36f6410aee0ed5cefa5a9175" dependencies = [ "cfg-if 1.0.0", "generator", @@ -1044,18 +1057,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" - -[[package]] -name = "memoffset" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" -dependencies = [ - "autocfg", -] +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memofs" @@ -1075,9 +1079,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", ] @@ -1103,9 +1107,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "wasi", @@ -1177,9 +1181,9 @@ dependencies = [ [[package]] name = "num-traits" -version = "0.2.16" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f30b0abd723be7e2ffca1272140fac1a2f084c77ec3e123c192b66af1ee9e6c2" +checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" dependencies = [ "autocfg", ] @@ -1190,24 +1194,24 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.3.3", + "hermit-abi 0.3.9", "libc", ] [[package]] name = "object" -version = "0.32.1" +version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" +checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ "memchr", ] [[package]] name = "once_cell" -version = "1.18.0" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" +checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "oorandom" @@ -1227,9 +1231,9 @@ dependencies = [ [[package]] name = "os_str_bytes" -version = "6.5.1" +version = "6.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d5d9eb14b174ee9aa2ef96dc2b94637a2d4b6e7cb873c7e171f0c20c6cf3eac" +checksum = "e2355d85b9a3786f481747ced0e0ff2ba35213a1f9bd406ed906554d7af805a1" [[package]] name = "overload" @@ -1245,15 +1249,15 @@ checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "percent-encoding" -version = "2.3.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pest" -version = "2.7.4" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c022f1e7b65d6a24c0dbbd5fb344c66881bc01f3e5ae74a1c8100f2f985d98a4" +checksum = "56f8023d0fb78c8e03784ea1c7f3fa36e68a723138990b8d5a47d916b651e7a8" dependencies = [ "memchr", "thiserror", @@ -1262,9 +1266,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.7.4" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35513f630d46400a977c4cb58f78e1bfbe01434316e60c37d27b9ad6139c66d8" +checksum = "b0d24f72393fd16ab6ac5738bc33cdb6a9aa73f8b902e8fe29cf4e67d7dd1026" dependencies = [ "pest", "pest_generator", @@ -1272,22 +1276,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.4" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc9fc1b9e7057baba189b5c626e2d6f40681ae5b6eb064dc7c7834101ec8123a" +checksum = "fdc17e2a6c7d0a492f0158d7a4bd66cc17280308bbaff78d5bef566dca35ab80" dependencies = [ "pest", "pest_meta", - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.52", ] [[package]] name = "pest_meta" -version = "2.7.4" +version = "2.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1df74e9e7ec4053ceb980e7c0c8bd3594e977fde1af91daba9c928e8e8c6708d" +checksum = "934cd7631c050f4674352a6e835d5f6711ffbfb9345c2fc0107155ac495ae293" dependencies = [ "once_cell", "pest", @@ -1357,8 +1361,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" dependencies = [ "proc-macro-error-attr", - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "syn 1.0.109", "version_check", ] @@ -1369,8 +1373,8 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "version_check", ] @@ -1397,18 +1401,18 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.67" +version = "1.0.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" +checksum = "e2422ad645d89c99f8f3e6b88a9fdeca7fabeac836b1002371c4367c8f984aae" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0f7f43585c34e4fdd7497d746bc32e14458cf11c69341cc0587b1d825dde42" +checksum = "43d84d1d7a6ac92673717f9f6d1518374ef257669c24ebc5ac25d5033828be58" dependencies = [ "profiling-procmacros", "tracy-client", @@ -1416,12 +1420,12 @@ dependencies = [ [[package]] name = "profiling-procmacros" -version = "1.0.14" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce97fecd27bc49296e5e20518b5a1bb54a14f7d5fe6228bc9686ee2a74915cc8" +checksum = "8021cf59c8ec9c432cfc2526ac6b8aa508ecaf29cd415f271b8406c1b851c3fd" dependencies = [ - "quote 1.0.33", - "syn 2.0.37", + "quote 1.0.35", + "syn 2.0.52", ] [[package]] @@ -1435,11 +1439,11 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ - "proc-macro2 1.0.67", + "proc-macro2 1.0.78", ] [[package]] @@ -1474,9 +1478,9 @@ dependencies = [ [[package]] name = "rayon" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" +checksum = "e4963ed1bc86e4f3ee217022bd855b297cef07fb9eac5dfa1f788b220b49b3bd" dependencies = [ "either", "rayon-core", @@ -1484,9 +1488,9 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.12.0" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" +checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ "crossbeam-deque", "crossbeam-utils", @@ -1571,43 +1575,34 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.2.16" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" -dependencies = [ - "bitflags 1.3.2", -] - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_users" -version = "0.4.3" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b" +checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" dependencies = [ "getrandom", - "redox_syscall 0.2.16", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.9.6" +version = "1.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebee201405406dbf528b8b672104ae6d6d63e6d118cb10e4d51abbc7b58044ff" +checksum = "b62dbe01f0b06f9d8dc7d49e05a0785f153b00b2c227856282f671e0318c9b15" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.3.9", - "regex-syntax 0.7.5", + "regex-automata 0.4.6", + "regex-syntax 0.8.2", ] [[package]] @@ -1621,13 +1616,13 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.9" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b23e92ee4318893fa3fe3e6fb365258efbfe6ac6ab30f090cdcbb7aa37efa9" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.7.5", + "regex-syntax 0.8.2", ] [[package]] @@ -1638,17 +1633,17 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "reqwest" -version = "0.11.22" +version = "0.11.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" +checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -1670,6 +1665,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", + "sync_wrapper", "system-configuration", "tokio", "tokio-rustls", @@ -1684,16 +1680,17 @@ dependencies = [ [[package]] name = "ring" -version = "0.17.7" +version = "0.17.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "688c63d65483050968b2a8937f7995f443e27041a0f7700aa59b0822aedebb74" +checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", + "cfg-if 1.0.0", "getrandom", "libc", "spin", "untrusted", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1830,15 +1827,15 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.20" +version = "0.38.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67ce50cb2e16c2903e30d1cbccfd8387a74b9d4c938b6a4c5ec6cc7556f7a8a0" +checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ - "bitflags 2.4.0", + "bitflags 2.4.2", "errno", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1859,7 +1856,7 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.4", + "base64 0.21.7", ] [[package]] @@ -1880,9 +1877,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.15" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "same-file" @@ -1899,12 +1896,6 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" -[[package]] -name = "scopeguard" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" - [[package]] name = "sct" version = "0.7.1" @@ -1917,15 +1908,15 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.19" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad977052201c6de01a8ef2aa3378c4bd23217a056337d1d6da40468d267a4fb0" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.188" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] @@ -1942,20 +1933,20 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.188" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.52", ] [[package]] name = "serde_json" -version = "1.0.107" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -1980,7 +1971,7 @@ version = "0.8.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "578a7433b776b56a35785ed5ce9a7e777ac0598aac5a6dd1b4b18a307c7fc71b" dependencies = [ - "indexmap", + "indexmap 1.9.3", "ryu", "serde", "yaml-rust", @@ -1999,18 +1990,18 @@ dependencies = [ [[package]] name = "sharded-slab" -version = "0.1.6" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1b21f559e07218024e7e9f90f96f601825397de0e25420135f7f952453fed0b" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" dependencies = [ "lazy_static", ] [[package]] name = "similar" -version = "2.2.1" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "420acb44afdae038210c99e69aae24109f32f15500aa708e81d46c9f29d55fcf" +checksum = "32fea41aca09ee824cc9724996433064c89f7777e60762749a4170a14abbfa21" [[package]] name = "slab" @@ -2023,9 +2014,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.1" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "snax" @@ -2038,22 +2029,12 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.9" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "05ffd9c0a93b7543e062e759284fcf5f5e3b098501104bfbdde4d404db792871" dependencies = [ "libc", - "winapi 0.3.9", -] - -[[package]] -name = "socket2" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4031e820eb552adee9295814c0ced9e5cf38ddf1e8b7d566d6de8e2538ea989e" -dependencies = [ - "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -2074,22 +2055,28 @@ version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "unicode-ident", ] [[package]] name = "syn" -version = "2.0.37" +version = "2.0.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" +checksum = "b699d15b36d1f02c3e7c69f8ffef53de37aefae075d8488d4ba1a7788d574a07" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", + "proc-macro2 1.0.78", + "quote 1.0.35", "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "system-configuration" version = "0.5.1" @@ -2113,22 +2100,21 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.0" +version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb94d2f3cc536af71caac6b6fcebf65860b347e7ce0cc9ebe8f70d3e521054ef" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if 1.0.0", "fastrand", - "redox_syscall 0.3.5", "rustix", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "termcolor" -version = "1.3.0" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" dependencies = [ "winapi-util", ] @@ -2144,35 +2130,35 @@ dependencies = [ [[package]] name = "textwrap" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "222a222a5bfe1bba4a77b45ec488a741b3cb8872e5e499451fd7d0129c9c7c3d" +checksum = "23d434d3f8967a09480fb04132ebe0a3e088c173e6d0ee7897abbdf4eab0f8b9" [[package]] name = "thiserror" -version = "1.0.49" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1177e8c6d7ede7afde3585fd2513e611227efd6481bd78d2e82ba1ce16557ed4" +checksum = "1e45bcbe8ed29775f228095caf2cd67af7a4ccf756ebff23a306bf3e8b47b24b" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.49" +version = "1.0.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "10712f02019e9288794769fba95cd6847df9874d49d871d062172f9dd41bc4cc" +checksum = "a953cb265bef375dae3de6663da4d3804eee9682ea80d8e2542529b73c531c81" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.52", ] [[package]] name = "thread_local" -version = "1.1.7" +version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" +checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ "cfg-if 1.0.0", "once_cell", @@ -2205,17 +2191,17 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" [[package]] name = "tokio" -version = "1.32.0" +version = "1.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17ed6077ed6cd6c74735e21f37eb16dc3935f96878b1fe961074089cc80893f9" +checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" dependencies = [ "backtrace", "bytes", "libc", - "mio 0.8.8", + "mio 0.8.11", "num_cpus", "pin-project-lite", - "socket2 0.5.4", + "socket2", "windows-sys 0.48.0", ] @@ -2231,9 +2217,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d68074620f57a0b21594d9735eb2e98ab38b17f80d3fcb189fca266771ca60d" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -2260,11 +2246,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if 1.0.0", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -2272,20 +2257,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.26" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.52", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", "valuable", @@ -2293,20 +2278,20 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" dependencies = [ "matchers", "nu-ansi-term", @@ -2322,9 +2307,9 @@ dependencies = [ [[package]] name = "tracy-client" -version = "0.16.3" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03684af8fb393cc7903210d868e4cb9f5c1e156737be38f52c4217fb21b86bf6" +checksum = "59fb931a64ff88984f86d3e9bcd1ae8843aa7fe44dd0f8097527bc172351741d" dependencies = [ "loom", "once_cell", @@ -2333,18 +2318,18 @@ dependencies = [ [[package]] name = "tracy-client-sys" -version = "0.21.2" +version = "0.22.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cb915ea3af048554640d76dd6f1492589a6401a41a30d789b983c1ec280455a" +checksum = "9d104d610dfa9dd154535102cc9c6164ae1fa37842bc2d9e83f9ac82b0ae0882" dependencies = [ "cc", ] [[package]] name = "try-lock" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "typenum" @@ -2360,9 +2345,9 @@ checksum = "ed646292ffc8188ef8ea4d1e0e0150fb15a5c2e12ad9b8fc191ae7a8a7f3c4b9" [[package]] name = "unicode-bidi" -version = "0.3.13" +version = "0.3.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" +checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" @@ -2372,9 +2357,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" -version = "0.1.22" +version = "0.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" +checksum = "a56d1686db2308d901306f92a263857ef59ea39678a5458e7cb17f01415101f5" dependencies = [ "tinyvec", ] @@ -2399,9 +2384,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.4.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -2410,9 +2395,9 @@ dependencies = [ [[package]] name = "uuid" -version = "1.4.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79daa5ed5740825c40b389c5e50312b9c86df53fccd33f281df655642b43869d" +checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" dependencies = [ "getrandom", "serde", @@ -2452,9 +2437,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -2477,9 +2462,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if 1.0.0", "wasm-bindgen-macro", @@ -2487,24 +2472,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", "once_cell", - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.52", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.37" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c02dbc21516f9f1f04f187958890d7e6026df8d16540b7ad9492bc34a67cea03" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if 1.0.0", "js-sys", @@ -2514,38 +2499,38 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ - "quote 1.0.33", + "quote 1.0.35", "wasm-bindgen-macro-support", ] [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ - "proc-macro2 1.0.67", - "quote 1.0.33", - "syn 2.0.37", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.52", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.87" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "web-sys" -version = "0.3.64" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -2609,15 +2594,6 @@ dependencies = [ "windows-targets 0.48.5", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.48.0" @@ -2628,18 +2604,12 @@ dependencies = [ ] [[package]] -name = "windows-targets" -version = "0.42.2" +name = "windows-sys" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", + "windows-targets 0.52.4", ] [[package]] @@ -2658,10 +2628,19 @@ dependencies = [ ] [[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" +name = "windows-targets" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b" +dependencies = [ + "windows_aarch64_gnullvm 0.52.4", + "windows_aarch64_msvc 0.52.4", + "windows_i686_gnu 0.52.4", + "windows_i686_msvc 0.52.4", + "windows_x86_64_gnu 0.52.4", + "windows_x86_64_gnullvm 0.52.4", + "windows_x86_64_msvc 0.52.4", +] [[package]] name = "windows_aarch64_gnullvm" @@ -2670,10 +2649,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" +name = "windows_aarch64_gnullvm" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9" [[package]] name = "windows_aarch64_msvc" @@ -2682,10 +2661,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] -name = "windows_i686_gnu" -version = "0.42.2" +name = "windows_aarch64_msvc" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675" [[package]] name = "windows_i686_gnu" @@ -2694,10 +2673,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] -name = "windows_i686_msvc" -version = "0.42.2" +name = "windows_i686_gnu" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "b474d8268f99e0995f25b9f095bc7434632601028cf86590aea5c8a5cb7801d3" [[package]] name = "windows_i686_msvc" @@ -2706,10 +2685,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" +name = "windows_i686_msvc" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "1515e9a29e5bed743cb4415a9ecf5dfca648ce85ee42e15873c3cd8610ff8e02" [[package]] name = "windows_x86_64_gnu" @@ -2718,10 +2697,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" +name = "windows_x86_64_gnu" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "5eee091590e89cc02ad514ffe3ead9eb6b660aedca2183455434b93546371a03" [[package]] name = "windows_x86_64_gnullvm" @@ -2730,10 +2709,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" +name = "windows_x86_64_gnullvm" +version = "0.52.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "77ca79f2451b49fa9e2af39f0747fe999fcda4f5e241b2898624dca97a1f2177" [[package]] name = "windows_x86_64_msvc" @@ -2741,6 +2720,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32b752e52a2da0ddfbdbcc6fceadfeede4c939ed16d13e648833a61dfb611ed8" + [[package]] name = "winreg" version = "0.6.2" diff --git a/Cargo.toml b/Cargo.toml index de689bf9..c94a9c0e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,39 +57,39 @@ rbx_reflection = "4.5.0" rbx_reflection_database = "0.2.10" rbx_xml = "0.13.3" -anyhow = "1.0.44" -backtrace = "0.3.61" +anyhow = "1.0.80" +backtrace = "0.3.69" bincode = "1.3.3" -crossbeam-channel = "0.5.1" -csv = "1.1.6" -env_logger = "0.9.0" -fs-err = "2.6.0" -futures = "0.3.17" -globset = "0.4.8" +crossbeam-channel = "0.5.12" +csv = "1.3.0" +env_logger = "0.9.3" +fs-err = "2.11.0" +futures = "0.3.30" +globset = "0.4.14" humantime = "2.1.0" -hyper = { version = "0.14.13", features = ["server", "tcp", "http1"] } +hyper = { version = "0.14.28", features = ["server", "tcp", "http1"] } jod-thread = "0.1.2" -log = "0.4.14" +log = "0.4.21" maplit = "1.0.2" -num_cpus = "1.15.0" -opener = "0.5.0" -rayon = "1.7.0" -reqwest = { version = "0.11.10", default-features = false, features = [ +num_cpus = "1.16.0" +opener = "0.5.2" +rayon = "1.9.0" +reqwest = { version = "0.11.24", default-features = false, features = [ "blocking", "json", "rustls-tls", ] } ritz = "0.1.0" roblox_install = "1.0.0" -serde = { version = "1.0.130", features = ["derive", "rc"] } -serde_json = "1.0.68" -toml = "0.5.9" -termcolor = "1.1.2" -thiserror = "1.0.30" -tokio = { version = "1.12.0", features = ["rt", "rt-multi-thread"] } -uuid = { version = "1.0.0", features = ["v4", "serde"] } -clap = { version = "3.1.18", features = ["derive"] } -profiling = "1.0.14" +serde = { version = "1.0.197", features = ["derive", "rc"] } +serde_json = "1.0.114" +toml = "0.5.11" +termcolor = "1.4.1" +thiserror = "1.0.57" +tokio = { version = "1.36.0", features = ["rt", "rt-multi-thread"] } +uuid = { version = "1.7.0", features = ["v4", "serde"] } +clap = { version = "3.2.25", features = ["derive"] } +profiling = "1.0.15" [target.'cfg(windows)'.dependencies] winreg = "0.10.1" @@ -97,20 +97,20 @@ winreg = "0.10.1" [build-dependencies] memofs = { version = "0.2.0", path = "crates/memofs" } -embed-resource = "1.6.4" -anyhow = "1.0.44" +embed-resource = "1.8.0" +anyhow = "1.0.80" bincode = "1.3.3" -fs-err = "2.6.0" +fs-err = "2.11.0" maplit = "1.0.2" -semver = "1.0.19" +semver = "1.0.22" [dev-dependencies] rojo-insta-ext = { path = "crates/rojo-insta-ext" } -criterion = "0.3.5" -insta = { version = "1.8.0", features = ["redactions", "yaml"] } -paste = "1.0.5" -pretty_assertions = "1.2.1" -serde_yaml = "0.8.21" -tempfile = "3.2.0" -walkdir = "2.3.2" +criterion = "0.3.6" +insta = { version = "1.36.1", features = ["redactions", "yaml"] } +paste = "1.0.14" +pretty_assertions = "1.4.0" +serde_yaml = "0.8.26" +tempfile = "3.10.1" +walkdir = "2.5.0" diff --git a/crates/memofs/Cargo.toml b/crates/memofs/Cargo.toml index 5cf5a733..3f32aa8d 100644 --- a/crates/memofs/Cargo.toml +++ b/crates/memofs/Cargo.toml @@ -11,7 +11,7 @@ homepage = "https://github.com/rojo-rbx/rojo/tree/master/memofs" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -crossbeam-channel = "0.5.1" -fs-err = "2.3.0" -notify = "4.0.15" -serde = { version = "1.0", features = ["derive"] } +crossbeam-channel = "0.5.12" +fs-err = "2.11.0" +notify = "4.0.17" +serde = { version = "1.0.197", features = ["derive"] } diff --git a/crates/rojo-insta-ext/Cargo.toml b/crates/rojo-insta-ext/Cargo.toml index 4471c4ac..55a86499 100644 --- a/crates/rojo-insta-ext/Cargo.toml +++ b/crates/rojo-insta-ext/Cargo.toml @@ -6,5 +6,5 @@ edition = "2018" publish = false [dependencies] -serde = "1.0.99" -serde_yaml = "0.8.9" +serde = "1.0.197" +serde_yaml = "0.8.26" From 8f9e307930b371779c0917076b1927ed260c4a76 Mon Sep 17 00:00:00 2001 From: EgoMoose Date: Wed, 13 Mar 2024 12:50:41 -0400 Subject: [PATCH 1387/1504] Trim plugin version string (#890) Duplicate of https://github.com/rojo-rbx/rojo/pull/889, but based on master as per request. This PR is a very small change that fixes the string pattern that reads the rojo version from `Version.txt`. Currently this reads an extra new-line character which makes reading the version text in the plugin difficult. It seems the rust side of things already trims the string when comparing, but the lua side does not. --- plugin/src/Config.lua | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugin/src/Config.lua b/plugin/src/Config.lua index 0238b2cb..5567efca 100644 --- a/plugin/src/Config.lua +++ b/plugin/src/Config.lua @@ -3,7 +3,8 @@ local strict = require(script.Parent.strict) local isDevBuild = script.Parent.Parent:FindFirstChild("ROJO_DEV_BUILD") ~= nil local Version = script.Parent.Parent.Version -local major, minor, patch, metadata = Version.Value:match("^(%d+)%.(%d+)%.(%d+)(.*)$") +local trimmedVersionValue = Version.Value:gsub("^%s+", ""):gsub("%s+$", "") +local major, minor, patch, metadata = trimmedVersionValue:match("^(%d+)%.(%d+)%.(%d+)(.*)$") local realVersion = { major, minor, patch, metadata } for i = 1, 3 do From c7a4f892e376caf4f5ac1cafc11894dec8259125 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bar=C4=B1=C5=9F?= <34089907+Barocena@users.noreply.github.com> Date: Thu, 14 Mar 2024 22:41:21 +0300 Subject: [PATCH 1388/1504] Add never option to Confirmation (#893) --- CHANGELOG.md | 2 ++ plugin/src/App/StatusPages/Settings/init.lua | 2 +- plugin/src/App/init.lua | 3 +++ 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e564901..b9d199c7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Added Never option to Confirmation ([#893]) * Added popout diff visualizer for table properties like Attributes and Tags ([#834]) * Updated Theme to use Studio colors ([#838]) * Added experimental setting for Auto Connect in playtests ([#840]) @@ -55,6 +56,7 @@ [#834]: https://github.com/rojo-rbx/rojo/pull/834 [#838]: https://github.com/rojo-rbx/rojo/pull/838 [#840]: https://github.com/rojo-rbx/rojo/pull/840 +[#893]: https://github.com/rojo-rbx/rojo/pull/893 ## [7.4.1] - February 20, 2024 * Made the `name` field optional on project files ([#870]) diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua index c87a9d19..441c9cd8 100644 --- a/plugin/src/App/StatusPages/Settings/init.lua +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -26,7 +26,7 @@ local function invertTbl(tbl) end local invertedLevels = invertTbl(Log.Level) -local confirmationBehaviors = { "Initial", "Always", "Large Changes", "Unlisted PlaceId" } +local confirmationBehaviors = { "Initial", "Always", "Large Changes", "Unlisted PlaceId", "Never" } local function Navbar(props) return Theme.with(function(theme) diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index ecb807f0..a9c20ce9 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -582,6 +582,9 @@ function App:startSession() return "Accept" end end + elseif confirmationBehavior == "Never" then + Log.trace("Accepting patch without confirmation because behavior is set to Never") + return "Accept" end -- The datamodel name gets overwritten by Studio, making confirmation of it intrusive From 87920964d78b405a4cde8ca8c1f8eadc708237dd Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Mon, 25 Mar 2024 10:48:27 -0700 Subject: [PATCH 1389/1504] Release memofs 0.3.0, bump Rojo dependency (#894) --- Cargo.lock | 2 +- Cargo.toml | 4 ++-- crates/memofs/CHANGELOG.md | 2 ++ crates/memofs/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2ab8e01e..2994444b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1063,7 +1063,7 @@ checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memofs" -version = "0.2.0" +version = "0.3.0" dependencies = [ "crossbeam-channel", "fs-err", diff --git a/Cargo.toml b/Cargo.toml index c94a9c0e..a35ccd94 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,7 +42,7 @@ name = "build" harness = false [dependencies] -memofs = { version = "0.2.0", path = "crates/memofs" } +memofs = { version = "0.3.0", path = "crates/memofs" } # These dependencies can be uncommented when working on rbx-dom simultaneously # rbx_binary = { path = "../rbx-dom/rbx_binary" } @@ -95,7 +95,7 @@ profiling = "1.0.15" winreg = "0.10.1" [build-dependencies] -memofs = { version = "0.2.0", path = "crates/memofs" } +memofs = { version = "0.3.0", path = "crates/memofs" } embed-resource = "1.8.0" anyhow = "1.0.80" diff --git a/crates/memofs/CHANGELOG.md b/crates/memofs/CHANGELOG.md index d678f8c9..44c3aa50 100644 --- a/crates/memofs/CHANGELOG.md +++ b/crates/memofs/CHANGELOG.md @@ -1,6 +1,8 @@ # memofs Changelog ## Unreleased Changes + +## 0.3.0 (2024-03-15) * Changed `StdBackend` file watching component to use minimal recursive watches. [#830] * Added `Vfs::read_to_string` and `Vfs::read_to_string_lf_normalized` [#854] diff --git a/crates/memofs/Cargo.toml b/crates/memofs/Cargo.toml index 3f32aa8d..57633ae4 100644 --- a/crates/memofs/Cargo.toml +++ b/crates/memofs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "memofs" description = "Virtual filesystem with configurable backends." -version = "0.2.0" +version = "0.3.0" authors = ["Lucien Greathouse "] edition = "2018" readme = "README.md" From b2f133e6f1200fb975cd79ef818effb78b457065 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Tue, 2 Apr 2024 00:04:58 -0700 Subject: [PATCH 1390/1504] Patch visualizer redesign (#883) --- CHANGELOG.md | 2 + assets/images/syncsuccess.png | Bin 0 -> 574 bytes assets/images/syncwarning.png | Bin 0 -> 607 bytes plugin/src/App/Components/ClassIcon.lua | 126 +++++ plugin/src/App/Components/EditableImage.lua | 41 ++ .../Components/PatchVisualizer/ChangeList.lua | 8 +- .../Components/PatchVisualizer/DomLabel.lua | 143 ++++-- .../App/Components/PatchVisualizer/init.lua | 76 ++- plugin/src/App/Components/VirtualScroller.lua | 4 +- plugin/src/App/StatusPages/Confirming.lua | 19 +- plugin/src/App/StatusPages/Connected.lua | 462 ++++++++++++------ plugin/src/App/Theme.lua | 10 +- plugin/src/App/init.lua | 2 +- plugin/src/Assets.lua | 4 + plugin/src/PatchSet.lua | 8 +- plugin/src/PatchTree.lua | 97 ++-- 16 files changed, 690 insertions(+), 312 deletions(-) create mode 100644 assets/images/syncsuccess.png create mode 100644 assets/images/syncwarning.png create mode 100644 plugin/src/App/Components/ClassIcon.lua create mode 100644 plugin/src/App/Components/EditableImage.lua diff --git a/CHANGELOG.md b/CHANGELOG.md index b9d199c7..2d08d02c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * Added Never option to Confirmation ([#893]) * Added popout diff visualizer for table properties like Attributes and Tags ([#834]) * Updated Theme to use Studio colors ([#838]) +* Improved patch visualizer UX ([#883]) * Added experimental setting for Auto Connect in playtests ([#840]) * Projects may now specify rules for syncing files as if they had a different file extension. ([#813]) This is specified via a new field on project files, `syncRules`: @@ -56,6 +57,7 @@ [#834]: https://github.com/rojo-rbx/rojo/pull/834 [#838]: https://github.com/rojo-rbx/rojo/pull/838 [#840]: https://github.com/rojo-rbx/rojo/pull/840 +[#883]: https://github.com/rojo-rbx/rojo/pull/883 [#893]: https://github.com/rojo-rbx/rojo/pull/893 ## [7.4.1] - February 20, 2024 diff --git a/assets/images/syncsuccess.png b/assets/images/syncsuccess.png new file mode 100644 index 0000000000000000000000000000000000000000..74958cc132ae4fd3a455d75943cff3be1000a922 GIT binary patch literal 574 zcmV-E0>S->P)f|jX5i3&if;ims}EZ3$ZNVV zu*dQ`unLT2#Oo2(ZS{_4aJ%=rEg!c08ko$98{T8sFVEoEz=5c?6q&pSewK+Ri~8yr zd^WI^)R%b}uDEd*AN$C!4csR=@{!5rBjV4v-zd#8!kH0f9lYN$-T@lP>c0bB-Xa7v zjdTf&x}=AED6W$?6xRzRyUuG`GvXD+!Kq~o;`oqTlqin;den3PyaReO2A$j2RVgU$ zrugU6t}wv~#b5C*N-wn#!Y=SdQd82nq<;(~El7$5ZzTPxJjIiUzk0L-uJ1_%FaQ7m M07*qoM6N<$f`b6{*#H0l literal 0 HcmV?d00001 diff --git a/assets/images/syncwarning.png b/assets/images/syncwarning.png new file mode 100644 index 0000000000000000000000000000000000000000..eafb93d36a4b25da48c30615a447f7e169e42313 GIT binary patch literal 607 zcmV-l0-*hgP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!~g&e!~vBn4jTXf0rW{kK~zXf)s;Oj z1wj~vcYQSyB^_#h28Bq(MwhO-Z?wF zW0xyBPjd3kyyx6I+1cIM6lqo+8Jf>;7t+9dJI!Y&W2pzzGWxp<50J?@E zWCzfydB?bc#$?q8;cn=Ozs!&oK&u^EfKKR(O(@!tN)TGJcmY`@U^PH<&V{ZE1-T6=J{0&{P?sW%$vn0Vic<3 t30+}713pjP;ve!1+d}TaPyatj@(C7IN%0b1s#gF2002ovPDHLkV1f?A2L%8C literal 0 HcmV?d00001 diff --git a/plugin/src/App/Components/ClassIcon.lua b/plugin/src/App/Components/ClassIcon.lua new file mode 100644 index 00000000..c3e46e0d --- /dev/null +++ b/plugin/src/App/Components/ClassIcon.lua @@ -0,0 +1,126 @@ +local StudioService = game:GetService("StudioService") +local AssetService = game:GetService("AssetService") + +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) + +local e = Roact.createElement + +local EditableImage = require(Plugin.App.Components.EditableImage) + +local imageCache = {} +local function getImageSizeAndPixels(image) + if not imageCache[image] then + local editableImage = AssetService:CreateEditableImageAsync(image) + imageCache[image] = { + Size = editableImage.Size, + Pixels = editableImage:ReadPixels(Vector2.zero, editableImage.Size), + } + end + + return imageCache[image].Size, table.clone(imageCache[image].Pixels) +end + +local function getRecoloredClassIcon(className, color) + local iconProps = StudioService:GetClassIcon(className) + + if iconProps and color then + local success, editableImageSize, editableImagePixels = pcall(function() + local size, pixels = getImageSizeAndPixels(iconProps.Image) + + local minVal, maxVal = math.huge, -math.huge + for i = 1, #pixels, 4 do + if pixels[i + 3] == 0 then + continue + end + local pixelVal = math.max(pixels[i], pixels[i + 1], pixels[i + 2]) + + minVal = math.min(minVal, pixelVal) + maxVal = math.max(maxVal, pixelVal) + end + + local hue, sat, val = color:ToHSV() + for i = 1, #pixels, 4 do + if pixels[i + 3] == 0 then + continue + end + + local pixelVal = math.max(pixels[i], pixels[i + 1], pixels[i + 2]) + local newVal = val + if minVal < maxVal then + -- Remap minVal - maxVal to val*0.9 - val + newVal = val * (0.9 + 0.1 * (pixelVal - minVal) / (maxVal - minVal)) + end + + local newPixelColor = Color3.fromHSV(hue, sat, newVal) + pixels[i], pixels[i + 1], pixels[i + 2] = newPixelColor.R, newPixelColor.G, newPixelColor.B + end + return size, pixels + end) + if success then + iconProps.EditableImagePixels = editableImagePixels + iconProps.EditableImageSize = editableImageSize + end + end + + return iconProps +end + +local ClassIcon = Roact.PureComponent:extend("ClassIcon") + +function ClassIcon:init() + self.state = { + iconProps = nil, + } +end + +function ClassIcon:updateIcon() + local props = self.props + local iconProps = getRecoloredClassIcon(props.className, props.color) + self:setState({ + iconProps = iconProps, + }) +end + +function ClassIcon:didMount() + self:updateIcon() +end + +function ClassIcon:didUpdate(lastProps) + if lastProps.className ~= self.props.className or lastProps.color ~= self.props.color then + self:updateIcon() + end +end + +function ClassIcon:render() + local iconProps = self.state.iconProps + if not iconProps then + return nil + end + + return e( + "ImageLabel", + { + Size = self.props.size, + Position = self.props.position, + LayoutOrder = self.props.layoutOrder, + AnchorPoint = self.props.anchorPoint, + ImageTransparency = self.props.transparency, + Image = iconProps.Image, + ImageRectOffset = iconProps.ImageRectOffset, + ImageRectSize = iconProps.ImageRectSize, + BackgroundTransparency = 1, + }, + if iconProps.EditableImagePixels + then e(EditableImage, { + size = iconProps.EditableImageSize, + pixels = iconProps.EditableImagePixels, + }) + else nil + ) +end + +return ClassIcon diff --git a/plugin/src/App/Components/EditableImage.lua b/plugin/src/App/Components/EditableImage.lua new file mode 100644 index 00000000..501a37ee --- /dev/null +++ b/plugin/src/App/Components/EditableImage.lua @@ -0,0 +1,41 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) + +local e = Roact.createElement + +local EditableImage = Roact.PureComponent:extend("EditableImage") + +function EditableImage:init() + self.ref = Roact.createRef() +end + +function EditableImage:writePixels() + local image = self.ref.current + if not image then + return + end + if not self.props.pixels then + return + end + + image:WritePixels(Vector2.zero, self.props.size, self.props.pixels) +end + +function EditableImage:render() + return e("EditableImage", { + Size = self.props.size, + [Roact.Ref] = self.ref, + }) +end + +function EditableImage:didMount() + self:writePixels() +end + +function EditableImage:didUpdate() + self:writePixels() +end + +return EditableImage diff --git a/plugin/src/App/Components/PatchVisualizer/ChangeList.lua b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua index ce01b801..2f10d458 100644 --- a/plugin/src/App/Components/PatchVisualizer/ChangeList.lua +++ b/plugin/src/App/Components/PatchVisualizer/ChangeList.lua @@ -155,7 +155,7 @@ function ChangeList:render() local headerRow = changes[1] local headers = e("Frame", { - Size = UDim2.new(1, 0, 0, 30), + Size = UDim2.new(1, 0, 0, 24), BackgroundTransparency = rowTransparency, BackgroundColor3 = theme.Diff.Row, LayoutOrder = 0, @@ -214,7 +214,7 @@ function ChangeList:render() local isWarning = metadata.isWarning rows[row] = e("Frame", { - Size = UDim2.new(1, 0, 0, 30), + Size = UDim2.new(1, 0, 0, 24), BackgroundTransparency = row % 2 ~= 0 and rowTransparency or 1, BackgroundColor3 = theme.Diff.Row, BorderSizePixel = 0, @@ -269,8 +269,8 @@ function ChangeList:render() }, { Headers = headers, Values = e(ScrollingFrame, { - size = UDim2.new(1, 0, 1, -30), - position = UDim2.new(0, 0, 0, 30), + size = UDim2.new(1, 0, 1, -24), + position = UDim2.new(0, 0, 0, 24), contentSize = self.contentSize, transparency = props.transparency, }, rows), diff --git a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua index 41ec0b8e..a842dcbc 100644 --- a/plugin/src/App/Components/PatchVisualizer/DomLabel.lua +++ b/plugin/src/App/Components/PatchVisualizer/DomLabel.lua @@ -1,5 +1,4 @@ local SelectionService = game:GetService("Selection") -local StudioService = game:GetService("StudioService") local Rojo = script:FindFirstAncestor("Rojo") local Plugin = Rojo.Plugin @@ -15,7 +14,8 @@ local bindingUtil = require(Plugin.App.bindingUtil) local e = Roact.createElement local ChangeList = require(script.Parent.ChangeList) -local Tooltip = require(script.Parent.Parent.Tooltip) +local Tooltip = require(Plugin.App.Components.Tooltip) +local ClassIcon = require(Plugin.App.Components.ClassIcon) local Expansion = Roact.Component:extend("Expansion") @@ -28,8 +28,8 @@ function Expansion:render() return e("Frame", { BackgroundTransparency = 1, - Size = UDim2.new(1, -props.indent, 1, -30), - Position = UDim2.new(0, props.indent, 0, 30), + Size = UDim2.new(1, -props.indent, 1, -24), + Position = UDim2.new(0, props.indent, 0, 24), }, { ChangeList = e(ChangeList, { changes = props.changeList, @@ -44,7 +44,7 @@ local DomLabel = Roact.Component:extend("DomLabel") function DomLabel:init() local initHeight = self.props.elementHeight:getValue() - self.expanded = initHeight > 30 + self.expanded = initHeight > 24 self.motor = Flipper.SingleMotor.new(initHeight) self.binding = bindingUtil.fromMotor(self.motor) @@ -53,7 +53,7 @@ function DomLabel:init() renderExpansion = self.expanded, }) self.motor:onStep(function(value) - local renderExpansion = value > 30 + local renderExpansion = value > 24 self.props.setElementHeight(value) if self.props.updateEvent then @@ -81,7 +81,7 @@ function DomLabel:didUpdate(prevProps) then -- Close the expansion when the domlabel is changed to a different thing self.expanded = false - self.motor:setGoal(Flipper.Spring.new(30, { + self.motor:setGoal(Flipper.Spring.new(24, { frequency = 5, dampingRatio = 1, })) @@ -90,17 +90,49 @@ end function DomLabel:render() local props = self.props + local depth = props.depth or 1 return Theme.with(function(theme) - local iconProps = StudioService:GetClassIcon(props.className) - local indent = (props.depth or 0) * 20 + 25 + local color = if props.isWarning + then theme.Diff.Warning + elseif props.patchType then theme.Diff[props.patchType] + else theme.TextColor + + local indent = (depth - 1) * 12 + 15 -- Line guides help indent depth remain readable local lineGuides = {} - for i = 1, props.depth or 0 do - lineGuides["Line_" .. i] = e("Frame", { - Size = UDim2.new(0, 2, 1, 2), - Position = UDim2.new(0, (20 * i) + 15, 0, -1), + for i = 2, depth do + if props.depthsComplete[i] then + continue + end + if props.isFinalChild and i == depth then + -- This line stops halfway down to merge with our connector for the right angle + lineGuides["Line_" .. i] = e("Frame", { + Size = UDim2.new(0, 2, 0, 15), + Position = UDim2.new(0, (12 * (i - 1)) + 6, 0, -1), + BorderSizePixel = 0, + BackgroundTransparency = props.transparency, + BackgroundColor3 = theme.BorderedContainer.BorderColor, + }) + else + -- All other lines go all the way + -- with the exception of the final element, which stops halfway down + lineGuides["Line_" .. i] = e("Frame", { + Size = UDim2.new(0, 2, 1, if props.isFinalElement then -9 else 2), + Position = UDim2.new(0, (12 * (i - 1)) + 6, 0, -1), + BorderSizePixel = 0, + BackgroundTransparency = props.transparency, + BackgroundColor3 = theme.BorderedContainer.BorderColor, + }) + end + end + + if depth ~= 1 then + lineGuides["Connector"] = e("Frame", { + Size = UDim2.new(0, 8, 0, 2), + Position = UDim2.new(0, 2 + (12 * props.depth), 0, 12), + AnchorPoint = Vector2.xAxis, BorderSizePixel = 0, BackgroundTransparency = props.transparency, BackgroundColor3 = theme.BorderedContainer.BorderColor, @@ -109,9 +141,8 @@ function DomLabel:render() return e("Frame", { ClipsDescendants = true, - BackgroundColor3 = if props.patchType then theme.Diff[props.patchType] else nil, - BorderSizePixel = 0, - BackgroundTransparency = props.patchType and props.transparency or 1, + BackgroundTransparency = if props.elementIndex % 2 == 0 then 0.985 else 1, + BackgroundColor3 = theme.Diff.Row, Size = self.binding:map(function(expand) return UDim2.new(1, 0, 0, expand) end), @@ -141,8 +172,8 @@ function DomLabel:render() if props.changeList then self.expanded = not self.expanded - local goalHeight = 30 - + (if self.expanded then math.clamp(#props.changeList * 30, 30, 30 * 6) else 0) + local goalHeight = 24 + + (if self.expanded then math.clamp(#props.changeList * 24, 24, 24 * 6) else 0) self.motor:setGoal(Flipper.Spring.new(goalHeight, { frequency = 5, dampingRatio = 1, @@ -174,40 +205,74 @@ function DomLabel:render() DiffIcon = if props.patchType then e("ImageLabel", { Image = Assets.Images.Diff[props.patchType], - ImageColor3 = theme.AddressEntry.PlaceholderColor, + ImageColor3 = color, ImageTransparency = props.transparency, BackgroundTransparency = 1, - Size = UDim2.new(0, 20, 0, 20), - Position = UDim2.new(0, 0, 0, 15), + Size = UDim2.new(0, 14, 0, 14), + Position = UDim2.new(0, 0, 0, 12), AnchorPoint = Vector2.new(0, 0.5), }) else nil, - ClassIcon = e("ImageLabel", { - Image = iconProps.Image, - ImageTransparency = props.transparency, - ImageRectOffset = iconProps.ImageRectOffset, - ImageRectSize = iconProps.ImageRectSize, - BackgroundTransparency = 1, - Size = UDim2.new(0, 20, 0, 20), - Position = UDim2.new(0, indent, 0, 15), - AnchorPoint = Vector2.new(0, 0.5), + ClassIcon = e(ClassIcon, { + className = props.className, + color = color, + transparency = props.transparency, + size = UDim2.new(0, 16, 0, 16), + position = UDim2.new(0, indent + 2, 0, 12), + anchorPoint = Vector2.new(0, 0.5), }), InstanceName = e("TextLabel", { - Text = (if props.isWarning then "⚠ " else "") .. props.name .. (props.hint and string.format( - ' %s', - theme.AddressEntry.PlaceholderColor:ToHex(), - props.hint - ) or ""), + Text = (if props.isWarning then "⚠ " else "") .. props.name, RichText = true, BackgroundTransparency = 1, - Font = Enum.Font.GothamMedium, + Font = if props.patchType then Enum.Font.GothamBold else Enum.Font.GothamMedium, TextSize = 14, - TextColor3 = if props.isWarning then theme.Diff.Warning else theme.TextColor, + TextColor3 = color, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = props.transparency, TextTruncate = Enum.TextTruncate.AtEnd, - Size = UDim2.new(1, -indent - 50, 0, 30), - Position = UDim2.new(0, indent + 30, 0, 0), + Size = UDim2.new(1, -indent - 50, 0, 24), + Position = UDim2.new(0, indent + 22, 0, 0), + }), + ChangeInfo = e("Frame", { + BackgroundTransparency = 1, + Size = UDim2.new(1, -indent - 80, 0, 24), + Position = UDim2.new(1, -2, 0, 0), + AnchorPoint = Vector2.new(1, 0), + }, { + Layout = e("UIListLayout", { + FillDirection = Enum.FillDirection.Horizontal, + HorizontalAlignment = Enum.HorizontalAlignment.Right, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 4), + }), + Edits = if props.changeInfo and props.changeInfo.edits + then e("TextLabel", { + Text = props.changeInfo.edits .. if props.changeInfo.failed then "," else "", + BackgroundTransparency = 1, + Font = Enum.Font.Gotham, + TextSize = 14, + TextColor3 = theme.SubTextColor, + TextTransparency = props.transparency, + Size = UDim2.new(0, 0, 0, 16), + AutomaticSize = Enum.AutomaticSize.X, + LayoutOrder = 2, + }) + else nil, + Failed = if props.changeInfo and props.changeInfo.failed + then e("TextLabel", { + Text = props.changeInfo.failed, + BackgroundTransparency = 1, + Font = Enum.Font.Gotham, + TextSize = 14, + TextColor3 = theme.Diff.Warning, + TextTransparency = props.transparency, + Size = UDim2.new(0, 0, 0, 16), + AutomaticSize = Enum.AutomaticSize.X, + LayoutOrder = 6, + }) + else nil, }), LineGuides = e("Folder", nil, lineGuides), }) diff --git a/plugin/src/App/Components/PatchVisualizer/init.lua b/plugin/src/App/Components/PatchVisualizer/init.lua index 67a4d7b2..a87d499b 100644 --- a/plugin/src/App/Components/PatchVisualizer/init.lua +++ b/plugin/src/App/Components/PatchVisualizer/init.lua @@ -8,8 +8,8 @@ local PatchTree = require(Plugin.PatchTree) local PatchSet = require(Plugin.PatchSet) local Theme = require(Plugin.App.Theme) -local BorderedContainer = require(Plugin.App.Components.BorderedContainer) local VirtualScroller = require(Plugin.App.Components.VirtualScroller) +local BorderedContainer = require(Plugin.App.Components.BorderedContainer) local e = Roact.createElement @@ -55,34 +55,60 @@ function PatchVisualizer:render() end -- Recusively draw tree - local scrollElements, elementHeights = {}, {} + local scrollElements, elementHeights, elementIndex = {}, {}, 0 if patchTree then + local elementTotal = patchTree:getCount() + local depthsComplete = {} local function drawNode(node, depth) - local elementHeight, setElementHeight = Roact.createBinding(30) - table.insert(elementHeights, elementHeight) - table.insert( - scrollElements, - e(DomLabel, { - updateEvent = self.updateEvent, - elementHeight = elementHeight, - setElementHeight = setElementHeight, - patchType = node.patchType, - className = node.className, - isWarning = node.isWarning, - instance = node.instance, - name = node.name, - hint = node.hint, - changeList = node.changeList, - depth = depth, - transparency = self.props.transparency, - showStringDiff = self.props.showStringDiff, - showTableDiff = self.props.showTableDiff, - }) - ) + elementIndex += 1 + + local parentNode = patchTree:getNode(node.parentId) + local isFinalChild = true + if parentNode then + for _id, sibling in parentNode.children do + if type(sibling) == "table" and sibling.name and sibling.name > node.name then + isFinalChild = false + break + end + end + end + + local elementHeight, setElementHeight = Roact.createBinding(24) + elementHeights[elementIndex] = elementHeight + scrollElements[elementIndex] = e(DomLabel, { + transparency = self.props.transparency, + showStringDiff = self.props.showStringDiff, + showTableDiff = self.props.showTableDiff, + updateEvent = self.updateEvent, + elementHeight = elementHeight, + setElementHeight = setElementHeight, + elementIndex = elementIndex, + isFinalElement = elementIndex == elementTotal, + depth = depth, + depthsComplete = table.clone(depthsComplete), + hasChildren = (node.children ~= nil and next(node.children) ~= nil), + isFinalChild = isFinalChild, + patchType = node.patchType, + className = node.className, + isWarning = node.isWarning, + instance = node.instance, + name = node.name, + changeInfo = node.changeInfo, + changeList = node.changeList, + }) + + if isFinalChild then + depthsComplete[depth] = true + end end patchTree:forEach(function(node, depth) + depthsComplete[depth] = false + for i = depth + 1, #depthsComplete do + depthsComplete[i] = nil + end + drawNode(node, depth) end) end @@ -92,6 +118,7 @@ function PatchVisualizer:render() transparency = self.props.transparency, size = self.props.size, position = self.props.position, + anchorPoint = self.props.anchorPoint, layoutOrder = self.props.layoutOrder, }, { CleanMerge = e("TextLabel", { @@ -106,7 +133,8 @@ function PatchVisualizer:render() }), VirtualScroller = e(VirtualScroller, { - size = UDim2.new(1, 0, 1, 0), + size = UDim2.new(1, 0, 1, -2), + position = UDim2.new(0, 0, 0, 2), transparency = self.props.transparency, count = #scrollElements, updateEvent = self.updateEvent.Event, diff --git a/plugin/src/App/Components/VirtualScroller.lua b/plugin/src/App/Components/VirtualScroller.lua index 69bcf5f1..466da8a4 100644 --- a/plugin/src/App/Components/VirtualScroller.lua +++ b/plugin/src/App/Components/VirtualScroller.lua @@ -131,8 +131,8 @@ function VirtualScroller:render() Position = props.position, AnchorPoint = props.anchorPoint, BackgroundTransparency = props.backgroundTransparency or 1, - BackgroundColor3 = props.backgroundColor3, - BorderColor3 = props.borderColor3, + BackgroundColor3 = props.backgroundColor3 or theme.BorderedContainer.BackgroundColor, + BorderColor3 = props.borderColor3 or theme.BorderedContainer.BorderColor, CanvasSize = self.totalCanvas:map(function(s) return UDim2.fromOffset(0, s) end), diff --git a/plugin/src/App/StatusPages/Confirming.lua b/plugin/src/App/StatusPages/Confirming.lua index bd0fd0a1..df8bf5b4 100644 --- a/plugin/src/App/StatusPages/Confirming.lua +++ b/plugin/src/App/StatusPages/Confirming.lua @@ -9,7 +9,6 @@ local PatchTree = require(Plugin.PatchTree) local Settings = require(Plugin.Settings) local Theme = require(Plugin.App.Theme) local TextButton = require(Plugin.App.Components.TextButton) -local Header = require(Plugin.App.Components.Header) local StudioPluginGui = require(Plugin.App.Components.Studio.StudioPluginGui) local Tooltip = require(Plugin.App.Components.Tooltip) local PatchVisualizer = require(Plugin.App.Components.PatchVisualizer) @@ -60,17 +59,11 @@ end function ConfirmingPage:render() return Theme.with(function(theme) local pageContent = Roact.createFragment({ - Header = e(Header, { - transparency = self.props.transparency, - layoutOrder = 1, - }), - Title = e("TextLabel", { Text = string.format( "Sync changes for project '%s':", self.props.confirmData.serverInfo.projectName or "UNKNOWN" ), - LayoutOrder = 2, Font = Enum.Font.Gotham, LineHeight = 1.2, TextSize = 14, @@ -82,7 +75,7 @@ function ConfirmingPage:render() }), PatchVisualizer = e(PatchVisualizer, { - size = UDim2.new(1, 0, 1, -150), + size = UDim2.new(1, 0, 1, -100), transparency = self.props.transparency, layoutOrder = 3, @@ -155,6 +148,11 @@ function ConfirmingPage:render() }), }), + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 8), + PaddingRight = UDim.new(0, 8), + }), + Layout = e("UIListLayout", { HorizontalAlignment = Enum.HorizontalAlignment.Center, VerticalAlignment = Enum.VerticalAlignment.Center, @@ -163,11 +161,6 @@ function ConfirmingPage:render() Padding = UDim.new(0, 10), }), - Padding = e("UIPadding", { - PaddingLeft = UDim.new(0, 20), - PaddingRight = UDim.new(0, 20), - }), - StringDiff = e(StudioPluginGui, { id = "Rojo_ConfirmingStringDiff", title = "String diff", diff --git a/plugin/src/App/StatusPages/Connected.lua b/plugin/src/App/StatusPages/Connected.lua index d8055b3f..3f84d15f 100644 --- a/plugin/src/App/StatusPages/Connected.lua +++ b/plugin/src/App/StatusPages/Connected.lua @@ -3,9 +3,7 @@ local Plugin = Rojo.Plugin local Packages = Rojo.Packages local Roact = require(Packages.Roact) -local Flipper = require(Packages.Flipper) -local bindingUtil = require(Plugin.App.bindingUtil) local Theme = require(Plugin.App.Theme) local Assets = require(Plugin.Assets) local PatchSet = require(Plugin.PatchSet) @@ -23,28 +21,20 @@ local TableDiffVisualizer = require(Plugin.App.Components.TableDiffVisualizer) local e = Roact.createElement local AGE_UNITS = { - { 31556909, "year" }, - { 2629743, "month" }, - { 604800, "week" }, - { 86400, "day" }, - { 3600, "hour" }, - { - 60, - "minute", - }, + { 31556909, "y" }, + { 2629743, "mon" }, + { 604800, "w" }, + { 86400, "d" }, + { 3600, "h" }, + { 60, "m" }, } function timeSinceText(elapsed: number): string - if elapsed < 3 then - return "just now" - end - - local ageText = string.format("%d seconds ago", elapsed) + local ageText = string.format("%ds", elapsed) for _, UnitData in ipairs(AGE_UNITS) do local UnitSeconds, UnitName = UnitData[1], UnitData[2] if elapsed > UnitSeconds then - local c = math.floor(elapsed / UnitSeconds) - ageText = string.format("%d %s%s ago", c, UnitName, c > 1 and "s" or "") + ageText = elapsed // UnitSeconds .. UnitName break end end @@ -52,49 +42,179 @@ function timeSinceText(elapsed: number): string return ageText end -local ChangesDrawer = Roact.Component:extend("ChangesDrawer") +local ChangesViewer = Roact.Component:extend("ChangesViewer") -function ChangesDrawer:init() +function ChangesViewer:init() -- Hold onto the serve session during the lifecycle of this component -- so that it can still render during the fade out after disconnecting self.serveSession = self.props.serveSession end -function ChangesDrawer:render() - if self.props.rendered == false or self.serveSession == nil then +function ChangesViewer:render() + if self.props.rendered == false or self.serveSession == nil or self.props.patchData == nil then return nil end + local unapplied = PatchSet.countChanges(self.props.patchData.unapplied) + local applied = PatchSet.countChanges(self.props.patchData.patch) - unapplied + return Theme.with(function(theme) - return e(BorderedContainer, { - transparency = self.props.transparency, - size = self.props.height:map(function(y) - return UDim2.new(1, 0, y, -220 * y) - end), - position = UDim2.new(0, 0, 1, 0), - anchorPoint = Vector2.new(0, 1), - layoutOrder = self.props.layoutOrder, - }, { - Close = e(IconButton, { - icon = Assets.Images.Icons.Close, - iconSize = 24, - color = theme.ConnectionDetails.DisconnectColor, - transparency = self.props.transparency, - - position = UDim2.new(1, 0, 0, 0), - anchorPoint = Vector2.new(1, 0), - - onClick = self.props.onClose, + return Roact.createFragment({ + Navbar = e("Frame", { + Size = UDim2.new(1, 0, 0, 40), + BackgroundTransparency = 1, }, { - Tip = e(Tooltip.Trigger, { - text = "Close the patch visualizer", + Close = e(IconButton, { + icon = Assets.Images.Icons.Close, + iconSize = 24, + color = theme.Settings.Navbar.BackButtonColor, + transparency = self.props.transparency, + + position = UDim2.new(0, 0, 0.5, 0), + anchorPoint = Vector2.new(0, 0.5), + + onClick = self.props.onBack, + }, { + Tip = e(Tooltip.Trigger, { + text = "Close", + }), + }), + + Title = e("TextLabel", { + Text = "Sync", + Font = Enum.Font.GothamMedium, + TextSize = 17, + TextXAlignment = Enum.TextXAlignment.Left, + TextColor3 = theme.TextColor, + TextTransparency = self.props.transparency, + Size = UDim2.new(1, -40, 0, 20), + Position = UDim2.new(0, 40, 0, 0), + BackgroundTransparency = 1, + }), + + Subtitle = e("TextLabel", { + Text = DateTime.fromUnixTimestamp(self.props.patchData.timestamp):FormatLocalTime("LTS", "en-us"), + TextXAlignment = Enum.TextXAlignment.Left, + Font = Enum.Font.Gotham, + TextSize = 15, + TextColor3 = theme.SubTextColor, + TextTruncate = Enum.TextTruncate.AtEnd, + TextTransparency = self.props.transparency, + Size = UDim2.new(1, -40, 0, 16), + Position = UDim2.new(0, 40, 0, 20), + BackgroundTransparency = 1, + }), + + Info = e("Frame", { + BackgroundTransparency = 1, + Size = UDim2.new(0, 10, 0, 24), + AutomaticSize = Enum.AutomaticSize.X, + Position = UDim2.new(1, -5, 0.5, 0), + AnchorPoint = Vector2.new(1, 0.5), + }, { + Tooltip = e(Tooltip.Trigger, { + text = `{applied} changes applied` + .. (if unapplied > 0 then `, {unapplied} changes failed` else ""), + }), + Content = e("Frame", { + BackgroundTransparency = 1, + Size = UDim2.new(0, 0, 1, 0), + AutomaticSize = Enum.AutomaticSize.X, + }, { + Layout = e("UIListLayout", { + FillDirection = Enum.FillDirection.Horizontal, + HorizontalAlignment = Enum.HorizontalAlignment.Right, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 4), + }), + + StatusIcon = e("ImageLabel", { + BackgroundTransparency = 1, + Image = if unapplied > 0 + then Assets.Images.Icons.SyncWarning + else Assets.Images.Icons.SyncSuccess, + ImageColor3 = if unapplied > 0 then theme.Diff.Warning else theme.TextColor, + Size = UDim2.new(0, 24, 0, 24), + LayoutOrder = 10, + }), + StatusSpacer = e("Frame", { + BackgroundTransparency = 1, + Size = UDim2.new(0, 6, 0, 4), + LayoutOrder = 9, + }), + AppliedIcon = e("ImageLabel", { + BackgroundTransparency = 1, + Image = Assets.Images.Icons.Checkmark, + ImageColor3 = theme.TextColor, + Size = UDim2.new(0, 16, 0, 16), + LayoutOrder = 1, + }), + AppliedText = e("TextLabel", { + Text = applied, + Font = Enum.Font.Gotham, + TextSize = 15, + TextColor3 = theme.TextColor, + TextTransparency = self.props.transparency, + Size = UDim2.new(0, 0, 1, 0), + AutomaticSize = Enum.AutomaticSize.X, + BackgroundTransparency = 1, + LayoutOrder = 2, + }), + Warnings = if unapplied > 0 + then Roact.createFragment({ + WarningsSpacer = e("Frame", { + BackgroundTransparency = 1, + Size = UDim2.new(0, 4, 0, 4), + LayoutOrder = 3, + }), + UnappliedIcon = e("ImageLabel", { + BackgroundTransparency = 1, + Image = Assets.Images.Icons.Exclamation, + ImageColor3 = theme.Diff.Warning, + Size = UDim2.new(0, 4, 0, 16), + LayoutOrder = 4, + }), + UnappliedText = e("TextLabel", { + Text = unapplied, + Font = Enum.Font.Gotham, + TextSize = 15, + TextColor3 = theme.Diff.Warning, + TextTransparency = self.props.transparency, + Size = UDim2.new(0, 0, 1, 0), + AutomaticSize = Enum.AutomaticSize.X, + BackgroundTransparency = 1, + LayoutOrder = 5, + }), + }) + else nil, + }), + }), + + Divider = e("Frame", { + BackgroundColor3 = theme.Settings.DividerColor, + BackgroundTransparency = self.props.transparency, + Size = UDim2.new(1, 0, 0, 1), + Position = UDim2.new(0, 0, 1, 0), + BorderSizePixel = 0, + }, { + Gradient = e("UIGradient", { + Transparency = NumberSequence.new({ + NumberSequenceKeypoint.new(0, 1), + NumberSequenceKeypoint.new(0.1, 0), + NumberSequenceKeypoint.new(0.9, 0), + NumberSequenceKeypoint.new(1, 1), + }), + }), }), }), - PatchVisualizer = e(PatchVisualizer, { - size = UDim2.new(1, 0, 1, 0), + Patch = e(PatchVisualizer, { + size = UDim2.new(1, -10, 1, -65), + position = UDim2.new(0, 5, 1, -5), + anchorPoint = Vector2.new(0, 1), transparency = self.props.transparency, - layoutOrder = 3, + layoutOrder = self.props.layoutOrder, patchTree = self.props.patchTree, @@ -167,20 +287,7 @@ function ConnectedPage:getChangeInfoText() if patchData == nil then return "" end - - local elapsed = os.time() - patchData.timestamp - local unapplied = PatchSet.countChanges(patchData.unapplied) - - return "Synced " - .. timeSinceText(elapsed) - .. (if unapplied > 0 - then string.format( - ', but %d change%s failed to apply', - unapplied, - unapplied == 1 and "" or "s" - ) - else "") - .. "" + return timeSinceText(DateTime.now().UnixTimestamp - patchData.timestamp) end function ConnectedPage:startChangeInfoTextUpdater() @@ -190,13 +297,9 @@ function ConnectedPage:startChangeInfoTextUpdater() -- Start a new updater self.changeInfoTextUpdater = task.defer(function() while true do - if self.state.hoveringChangeInfo then - self.setChangeInfoText("" .. self:getChangeInfoText() .. "") - else - self.setChangeInfoText(self:getChangeInfoText()) - end + self.setChangeInfoText(self:getChangeInfoText()) - local elapsed = os.time() - self.props.patchData.timestamp + local elapsed = DateTime.now().UnixTimestamp - self.props.patchData.timestamp local updateInterval = 1 -- Update timestamp text as frequently as currently needed @@ -221,23 +324,6 @@ function ConnectedPage:stopChangeInfoTextUpdater() end function ConnectedPage:init() - self.changeDrawerMotor = Flipper.SingleMotor.new(0) - self.changeDrawerHeight = bindingUtil.fromMotor(self.changeDrawerMotor) - - self.changeDrawerMotor:onStep(function(value) - local renderChanges = value > 0.05 - - self:setState(function(state) - if state.renderChanges == renderChanges then - return nil - end - - return { - renderChanges = renderChanges, - } - end) - end) - self:setState({ renderChanges = false, hoveringChangeInfo = false, @@ -266,6 +352,10 @@ function ConnectedPage:didUpdate(previousProps) end function ConnectedPage:render() + local syncWarning = self.props.patchData + and self.props.patchData.unapplied + and PatchSet.countChanges(self.props.patchData.unapplied) > 0 + return Theme.with(function(theme) return Roact.createFragment({ Padding = e("UIPadding", { @@ -280,9 +370,88 @@ function ConnectedPage:render() Padding = UDim.new(0, 10), }), - Header = e(Header, { - transparency = self.props.transparency, - layoutOrder = 1, + Heading = e("Frame", { + BackgroundTransparency = 1, + Size = UDim2.new(1, 0, 0, 32), + }, { + Header = e(Header, { + transparency = self.props.transparency, + }), + + ChangeInfo = e("TextButton", { + Text = "", + Size = UDim2.new(0, 0, 1, 0), + AutomaticSize = Enum.AutomaticSize.X, + BackgroundColor3 = theme.BorderedContainer.BorderedColor, + BackgroundTransparency = if self.state.hoveringChangeInfo then 0.7 else 1, + BorderSizePixel = 0, + Position = UDim2.new(1, -5, 0.5, 0), + AnchorPoint = Vector2.new(1, 0.5), + [Roact.Event.MouseEnter] = function() + self:setState({ + hoveringChangeInfo = true, + }) + end, + [Roact.Event.MouseLeave] = function() + self:setState({ + hoveringChangeInfo = false, + }) + end, + [Roact.Event.Activated] = function() + self:setState(function(prevState) + prevState = prevState or {} + return { + renderChanges = not prevState.renderChanges, + } + end) + end, + }, { + Corner = e("UICorner", { + CornerRadius = UDim.new(0, 5), + }), + Tooltip = e(Tooltip.Trigger, { + text = if self.state.renderChanges then "Hide changes" else "View changes", + }), + Content = e("Frame", { + BackgroundTransparency = 1, + Size = UDim2.new(0, 0, 1, 0), + AutomaticSize = Enum.AutomaticSize.X, + }, { + Layout = e("UIListLayout", { + FillDirection = Enum.FillDirection.Horizontal, + HorizontalAlignment = Enum.HorizontalAlignment.Center, + VerticalAlignment = Enum.VerticalAlignment.Center, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 5), + }), + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 5), + PaddingRight = UDim.new(0, 5), + }), + Text = e("TextLabel", { + BackgroundTransparency = 1, + Text = self.changeInfoText, + Font = Enum.Font.Gotham, + TextSize = 15, + TextColor3 = if syncWarning then theme.Diff.Warning else theme.Header.VersionColor, + TextTransparency = self.props.transparency, + TextXAlignment = Enum.TextXAlignment.Right, + Size = UDim2.new(0, 0, 1, 0), + AutomaticSize = Enum.AutomaticSize.X, + LayoutOrder = 1, + }), + Icon = e("ImageLabel", { + BackgroundTransparency = 1, + Image = if syncWarning + then Assets.Images.Icons.SyncWarning + else Assets.Images.Icons.SyncSuccess, + ImageColor3 = if syncWarning then theme.Diff.Warning else theme.Header.VersionColor, + ImageTransparency = self.props.transparency, + Size = UDim2.new(0, 24, 0, 24), + LayoutOrder = 2, + }), + }), + }), }), ConnectionDetails = e(ConnectionDetails, { @@ -332,84 +501,59 @@ function ConnectedPage:render() }), }), - ChangeInfo = e("TextButton", { - Text = self.changeInfoText, - Font = Enum.Font.Gotham, - TextSize = 14, - TextWrapped = true, - RichText = true, - TextColor3 = theme.Header.VersionColor, - TextXAlignment = Enum.TextXAlignment.Left, - TextYAlignment = Enum.TextYAlignment.Top, - TextTransparency = self.props.transparency, + ChangesViewer = e(StudioPluginGui, { + id = "Rojo_ChangesViewer", + title = "View changes", + active = self.state.renderChanges, + isEphemeral = true, - Size = UDim2.new(1, 0, 0, 28), + initDockState = Enum.InitialDockState.Float, + overridePreviousState = true, + floatingSize = Vector2.new(400, 500), + minimumSize = Vector2.new(300, 300), - LayoutOrder = 4, - BackgroundTransparency = 1, - - [Roact.Event.MouseEnter] = function() - self:setState({ - hoveringChangeInfo = true, - }) - self.setChangeInfoText("" .. self:getChangeInfoText() .. "") - end, - - [Roact.Event.MouseLeave] = function() - self:setState({ - hoveringChangeInfo = false, - }) - self.setChangeInfoText(self:getChangeInfoText()) - end, - - [Roact.Event.Activated] = function() - if self.state.renderChanges then - self.changeDrawerMotor:setGoal(Flipper.Spring.new(0, { - frequency = 4, - dampingRatio = 1, - })) - else - self.changeDrawerMotor:setGoal(Flipper.Spring.new(1, { - frequency = 3, - dampingRatio = 1, - })) - end - end, - }, { - Tooltip = e(Tooltip.Trigger, { - text = if self.state.renderChanges then "Hide the changes" else "View the changes", - }), - }), - - ChangesDrawer = e(ChangesDrawer, { - rendered = self.state.renderChanges, - transparency = self.props.transparency, - patchTree = self.props.patchTree, - serveSession = self.props.serveSession, - height = self.changeDrawerHeight, - layoutOrder = 5, - - showStringDiff = function(oldString: string, newString: string) - self:setState({ - showingStringDiff = true, - oldString = oldString, - newString = newString, - }) - end, - showTableDiff = function(oldTable: { [any]: any? }, newTable: { [any]: any? }) - self:setState({ - showingTableDiff = true, - oldTable = oldTable, - newTable = newTable, - }) - end, + zIndexBehavior = Enum.ZIndexBehavior.Sibling, onClose = function() - self.changeDrawerMotor:setGoal(Flipper.Spring.new(0, { - frequency = 4, - dampingRatio = 1, - })) + self:setState({ + renderChanges = false, + }) end, + }, { + TooltipsProvider = e(Tooltip.Provider, nil, { + Tooltips = e(Tooltip.Container, nil), + Content = e("Frame", { + Size = UDim2.fromScale(1, 1), + BackgroundTransparency = 1, + }, { + Changes = e(ChangesViewer, { + transparency = self.props.transparency, + rendered = self.state.renderChanges, + patchData = self.props.patchData, + patchTree = self.props.patchTree, + serveSession = self.props.serveSession, + showStringDiff = function(oldString: string, newString: string) + self:setState({ + showingStringDiff = true, + oldString = oldString, + newString = newString, + }) + end, + showTableDiff = function(oldTable: { [any]: any? }, newTable: { [any]: any? }) + self:setState({ + showingTableDiff = true, + oldTable = oldTable, + newTable = newTable, + }) + end, + onBack = function() + self:setState({ + renderChanges = false, + }) + end, + }), + }), + }), }), StringDiff = e(StudioPluginGui, { diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index f1e9c397..84a429c6 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -32,9 +32,12 @@ local StudioProvider = Roact.Component:extend("StudioProvider") function StudioProvider:updateTheme() local studioTheme = getStudio().Theme + local isDark = studioTheme.Name == "Dark" + local theme = strict(studioTheme.Name .. "Theme", { BackgroundColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainBackground), TextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainText), + SubTextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.SubText), Button = { Solid = { -- Solid uses brand theming, not Studio theming. @@ -139,9 +142,10 @@ function StudioProvider:updateTheme() BackgroundColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.InputFieldBackground), }, Diff = { - Add = studioTheme:GetColor(Enum.StudioStyleGuideColor.DiffTextAdditionBackground), - Remove = studioTheme:GetColor(Enum.StudioStyleGuideColor.DiffTextDeletionBackground), - Edit = studioTheme:GetColor(Enum.StudioStyleGuideColor.DiffLineNumSeparatorBackground), + -- Studio doesn't have good colors since their diffs use backgrounds, not text + Add = if isDark then Color3.fromRGB(143, 227, 154) else Color3.fromRGB(41, 164, 45), + Remove = if isDark then Color3.fromRGB(242, 125, 125) else Color3.fromRGB(150, 29, 29), + Edit = if isDark then Color3.fromRGB(120, 154, 248) else Color3.fromRGB(0, 70, 160), Row = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), Warning = studioTheme:GetColor(Enum.StudioStyleGuideColor.WarningText), }, diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index a9c20ce9..d80bf016 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -457,7 +457,7 @@ function App:startSession() end) serveSession:hookPostcommit(function(patch, _instanceMap, unapplied) - local now = os.time() + local now = DateTime.now().UnixTimestamp local old = self.state.patchData if PatchSet.isEmpty(patch) then diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index dbc60a16..91f82d1a 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -25,6 +25,10 @@ local Assets = { Back = "rbxassetid://6017213752", Reset = "rbxassetid://10142422327", Expand = "rbxassetid://12045401097", + Checkmark = "rbxassetid://16571012729", + Exclamation = "rbxassetid://16571172190", + SyncSuccess = "rbxassetid://16565035221", + SyncWarning = "rbxassetid://16565325171", }, Diff = { Add = "rbxassetid://10434145835", diff --git a/plugin/src/PatchSet.lua b/plugin/src/PatchSet.lua index abbac0cb..064def36 100644 --- a/plugin/src/PatchSet.lua +++ b/plugin/src/PatchSet.lua @@ -211,9 +211,11 @@ end function PatchSet.countChanges(patch) local count = 0 - for _ in patch.added do - -- Adding an instance is 1 change - count += 1 + for _, add in patch.added do + -- Adding an instance is 1 change per property + for _ in add.Properties do + count += 1 + end end for _ in patch.removed do -- Removing an instance is 1 change diff --git a/plugin/src/PatchTree.lua b/plugin/src/PatchTree.lua index 6d871001..c1c5f91c 100644 --- a/plugin/src/PatchTree.lua +++ b/plugin/src/PatchTree.lua @@ -79,6 +79,15 @@ function Tree.new() return setmetatable(tree, Tree) end +-- Iterates over all nodes and counts them up +function Tree:getCount() + local count = 0 + self:forEach(function() + count += 1 + end) + return count +end + -- Iterates over all sub-nodes, depth first -- node is where to start from, defaults to root -- depth is used for recursion but can be used to set the starting depth @@ -219,42 +228,14 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) tree:buildAncestryNodes(previousId, ancestryIds, patch, instanceMap) -- Gather detail text - local changeList, hint = nil, nil + local changeList, changeInfo = nil, nil if next(change.changedProperties) or change.changedName then changeList = {} - local hintBuffer, hintBufferSize, hintOverflow = table.create(3), 0, 0 local changeIndex = 0 local function addProp(prop: string, current: any?, incoming: any?, metadata: any?) changeIndex += 1 changeList[changeIndex] = { prop, current, incoming, metadata } - - if hintBufferSize < 3 then - hintBufferSize += 1 - hintBuffer[hintBufferSize] = prop - return - end - - -- We only want to have 3 hints - -- to keep it deterministic, we sort them alphabetically - - -- Either this prop overflows, or it makes another one move to overflow - hintOverflow += 1 - - -- Shortcut for the common case - if hintBuffer[3] <= prop then - -- This prop is below the last hint, no need to insert - return - end - - -- Find the first available spot - for i, hintItem in hintBuffer do - if prop < hintItem then - -- This prop is before the currently selected hint, - -- so take its place and then continue to find a spot for the old hint - hintBuffer[i], prop = prop, hintBuffer[i] - end - end end -- Gather the changes @@ -274,8 +255,9 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) ) end - -- Finalize detail values - hint = table.concat(hintBuffer, ", ") .. (if hintOverflow == 0 then "" else ", " .. hintOverflow .. " more") + changeInfo = { + edits = changeIndex, + } -- Sort changes and add header table.sort(changeList, function(a, b) @@ -291,7 +273,7 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) className = instance.ClassName, name = instance.Name, instance = instance, - hint = hint, + changeInfo = changeInfo, changeList = changeList, }) end @@ -376,42 +358,14 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) tree:buildAncestryNodes(previousId, ancestryIds, patch, instanceMap) -- Gather detail text - local changeList, hint = nil, nil + local changeList, changeInfo = nil, nil if next(change.Properties) then changeList = {} - local hintBuffer, hintBufferSize, hintOverflow = table.create(3), 0, 0 local changeIndex = 0 local function addProp(prop: string, incoming: any) changeIndex += 1 changeList[changeIndex] = { prop, "N/A", incoming } - - if hintBufferSize < 3 then - hintBufferSize += 1 - hintBuffer[hintBufferSize] = prop - return - end - - -- We only want to have 3 hints - -- to keep it deterministic, we sort them alphabetically - - -- Either this prop overflows, or it makes another one move to overflow - hintOverflow += 1 - - -- Shortcut for the common case - if hintBuffer[3] <= prop then - -- This prop is below the last hint, no need to insert - return - end - - -- Find the first available spot - for i, hintItem in hintBuffer do - if prop < hintItem then - -- This prop is before the currently selected hint, - -- so take its place and then continue to find a spot for the old hint - hintBuffer[i], prop = prop, hintBuffer[i] - end - end end for prop, incoming in change.Properties do @@ -419,8 +373,9 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) addProp(prop, if success then incomingValue else select(2, next(incoming))) end - -- Finalize detail values - hint = table.concat(hintBuffer, ", ") .. (if hintOverflow == 0 then "" else ", " .. hintOverflow .. " more") + changeInfo = { + edits = changeIndex, + } -- Sort changes and add header table.sort(changeList, function(a, b) @@ -435,7 +390,7 @@ function PatchTree.build(patch, instanceMap, changeListHeaders) patchType = "Add", className = change.ClassName, name = change.Name, - hint = hint, + changeInfo = changeInfo, changeList = changeList, instance = instanceMap.fromIds[id], }) @@ -473,6 +428,8 @@ function PatchTree.updateMetadata(tree, patch, instanceMap, unappliedPatch) if not node.changeList then continue end + + local warnings = 0 for _, change in node.changeList do local property = change[1] local propertyFailedToApply = if property == "Name" @@ -483,6 +440,8 @@ function PatchTree.updateMetadata(tree, patch, instanceMap, unappliedPatch) -- This change didn't fail, no need to mark continue end + + warnings += 1 if change[4] == nil then change[4] = { isWarning = true } else @@ -490,6 +449,11 @@ function PatchTree.updateMetadata(tree, patch, instanceMap, unappliedPatch) end Log.trace(" Marked property as warning: {}.{}", node.name, property) end + + node.changeInfo = { + edits = (node.changeInfo.edits or (#node.changeList - 1)) - warnings, + failed = if warnings > 0 then warnings else nil, + } end for failedAdditionId in unappliedPatch.added do local node = tree:getNode(failedAdditionId) @@ -503,6 +467,7 @@ function PatchTree.updateMetadata(tree, patch, instanceMap, unappliedPatch) if not node.changeList then continue end + for _, change in node.changeList do -- Failed addition means that all properties failed to be added if change[4] == nil then @@ -512,6 +477,10 @@ function PatchTree.updateMetadata(tree, patch, instanceMap, unappliedPatch) end Log.trace(" Marked property as warning: {}.{}", node.name, change[1]) end + + node.changeInfo = { + failed = node.changeInfo.edits or (#node.changeList - 1), + } end for _, failedRemovalIdOrInstance in unappliedPatch.removed do local failedRemovalId = if Types.RbxId(failedRemovalIdOrInstance) From 7232721b877f8f99d500c61f5900499b6059fb21 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Tue, 9 Apr 2024 14:55:42 -0700 Subject: [PATCH 1391/1504] Use dtolnay/rust-toolchain and upgrade to checkout v4 in CI workflow (#900) This PR performs some routine maintenance on our CI workflow: * Replaces `actions-rs/toolchain` with `dtolnay/rust-toolchain`. The actions at `actions-rs` are no longer maintained, and they use deprecated GitHub Actions APIs. dtolnay's action does not support the `override` option, but we didn't actually need to use it anyway. * Upgrades `actions/checkout` to v4, because v3 causes some warnings since it uses Node.js 16, which is deprecated. --- .github/workflows/ci.yml | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 28565bb9..b7dbd5ee 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,16 +19,12 @@ jobs: os: [ubuntu-latest, windows-latest, macos-latest] steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: stable - override: true - profile: minimal + uses: dtolnay/rust-toolchain@stable - name: Rust cache uses: Swatinem/rust-cache@v2 @@ -49,16 +45,12 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: Install Rust - uses: actions-rs/toolchain@v1 - with: - toolchain: 1.70.0 - override: true - profile: minimal + uses: dtolnay/rust-toolchain@1.70.0 - name: Rust cache uses: Swatinem/rust-cache@v2 @@ -76,15 +68,13 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: - toolchain: stable - override: true components: rustfmt, clippy - name: Rust cache From ce71a3df4d28da362955cb4257072cb7118218ab Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Wed, 17 Apr 2024 19:55:08 +0100 Subject: [PATCH 1392/1504] Release workflow maintenance (#902) --- .github/workflows/release.yml | 71 +++++++++++++---------------------- 1 file changed, 26 insertions(+), 45 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index dc85a2b2..8219cd1c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -8,26 +8,20 @@ jobs: create-release: name: Create Release runs-on: ubuntu-latest - outputs: - upload_url: ${{ steps.create_release.outputs.upload_url }} steps: + - uses: actions/checkout@v4 - name: Create Release - id: create_release - uses: actions/create-release@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - tag_name: ${{ github.ref }} - release_name: ${{ github.ref }} - draft: true - prerelease: false + run: | + gh release create ${{ github.ref_name }} --draft --verify-tag --title ${{ github.ref_name }} build-plugin: needs: ["create-release"] name: Build Roblox Studio Plugin runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true @@ -42,17 +36,13 @@ jobs: run: rojo build plugin --output Rojo.rbxm - name: Upload Plugin to Release - uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.create-release.outputs.upload_url }} - asset_path: Rojo.rbxm - asset_name: Rojo.rbxm - asset_content_type: application/octet-stream + run: | + gh release upload ${{ github.ref_name }} Rojo.rbxm - name: Upload Plugin to Artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: Rojo.rbxm path: Rojo.rbxm @@ -89,24 +79,14 @@ jobs: env: BIN: rojo steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: submodules: true - - name: Get Version from Tag - shell: bash - # https://github.community/t/how-to-get-just-the-tag-name/16241/7#M1027 - run: | - echo "PROJECT_VERSION=${GITHUB_REF#refs/tags/v}" >> $GITHUB_ENV - echo "Version is: ${{ env.PROJECT_VERSION }}" - - name: Install Rust - uses: actions-rs/toolchain@v1 + uses: dtolnay/rust-toolchain@stable with: - toolchain: stable - target: ${{ matrix.target }} - override: true - profile: minimal + targets: ${{ matrix.target }} - name: Setup Aftman uses: ok-nick/setup-aftman@v0.1.0 @@ -122,33 +102,34 @@ jobs: # easily. CARGO_TARGET_DIR: output - - name: Create Release Archive + - name: Generate Artifact Name shell: bash + env: + TAG_NAME: ${{ github.ref_name }} + run: | + echo "ARTIFACT_NAME=$BIN-${TAG_NAME#v}-${{ matrix.label }}.zip" >> "$GITHUB_ENV" + + - name: Create Archive and Upload to Release + shell: bash + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | mkdir staging if [ "${{ matrix.host }}" = "windows" ]; then cp "output/${{ matrix.target }}/release/$BIN.exe" staging/ cd staging - 7z a ../release.zip * + 7z a ../$ARTIFACT_NAME * else cp "output/${{ matrix.target }}/release/$BIN" staging/ cd staging - zip ../release.zip * + zip ../$ARTIFACT_NAME * fi - - name: Upload Archive to Release - uses: actions/upload-release-asset@v1 - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ needs.create-release.outputs.upload_url }} - asset_path: release.zip - asset_name: ${{ env.BIN }}-${{ env.PROJECT_VERSION }}-${{ matrix.label }}.zip - asset_content_type: application/octet-stream + gh release upload ${{ github.ref_name }} ../$ARTIFACT_NAME - name: Upload Archive to Artifacts - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: - name: ${{ env.BIN }}-${{ env.PROJECT_VERSION }}-${{ matrix.label }}.zip - path: release.zip \ No newline at end of file + path: ${{ env.ARTIFACT_NAME }} + name: ${{ env.ARTIFACT_NAME }} From 4b3470d30be865f3c03ad018100ca7cbaa339c67 Mon Sep 17 00:00:00 2001 From: Kenneth Loeffler Date: Wed, 17 Apr 2024 19:55:23 +0100 Subject: [PATCH 1393/1504] Fix removing trailing newlines by using str::replace in memofs (#903) --- CHANGELOG.md | 2 ++ crates/memofs/src/lib.rs | 22 +++++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d08d02c..df29083f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Fixed removing trailing newlines ([#903]) * Added Never option to Confirmation ([#893]) * Added popout diff visualizer for table properties like Attributes and Tags ([#834]) * Updated Theme to use Studio colors ([#838]) @@ -59,6 +60,7 @@ [#840]: https://github.com/rojo-rbx/rojo/pull/840 [#883]: https://github.com/rojo-rbx/rojo/pull/883 [#893]: https://github.com/rojo-rbx/rojo/pull/893 +[#903]: https://github.com/rojo-rbx/rojo/pull/903 ## [7.4.1] - February 20, 2024 * Made the `name` field optional on project files ([#870]) diff --git a/crates/memofs/src/lib.rs b/crates/memofs/src/lib.rs index 6d41c853..7a348ff6 100644 --- a/crates/memofs/src/lib.rs +++ b/crates/memofs/src/lib.rs @@ -300,7 +300,7 @@ impl Vfs { let path = path.as_ref(); let contents = self.inner.lock().unwrap().read_to_string(path)?; - Ok(contents.lines().collect::>().join("\n").into()) + Ok(contents.replace("\r\n", "\n").into()) } /// Write a file to the VFS and the underlying backend. @@ -473,3 +473,23 @@ impl VfsLock<'_> { self.inner.commit_event(event) } } + +#[cfg(test)] +mod test { + use crate::{InMemoryFs, Vfs, VfsSnapshot}; + + /// https://github.com/rojo-rbx/rojo/issues/899 + #[test] + fn read_to_string_lf_normalized_keeps_trailing_newline() { + let mut imfs = InMemoryFs::new(); + imfs.load_snapshot("test", VfsSnapshot::file("bar\r\nfoo\r\n\r\n")) + .unwrap(); + + let vfs = Vfs::new(imfs); + + assert_eq!( + vfs.read_to_string_lf_normalized("test").unwrap().as_str(), + "bar\nfoo\n\n" + ); + } +} From 41443d398964d27a69739f5420be0d63c24e7ec3 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 19 Apr 2024 20:03:55 +0000 Subject: [PATCH 1394/1504] Bump rustls from 0.21.10 to 0.21.11 (#905) --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2994444b..67f82f52 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1840,9 +1840,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.21.10" +version = "0.21.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9d5a6813c0759e4609cd494e8e725babae6a2ca7b62a5536a13daaec6fcb7ba" +checksum = "7fecbfb7b1444f477b345853b1fce097a2c6fb637b2bfb87e6bc5db0f043fae4" dependencies = [ "log", "ring", From 2c46640105be1fb014bebc194ec89793a3cd0ac4 Mon Sep 17 00:00:00 2001 From: Micah <48431591+nezuo@users.noreply.github.com> Date: Wed, 8 May 2024 12:34:00 -0700 Subject: [PATCH 1395/1504] Allow openScriptsExternally option to be changed during sync (#911) --- CHANGELOG.md | 2 ++ plugin/src/App/StatusPages/Settings/init.lua | 1 - plugin/src/App/init.lua | 8 +------- plugin/src/ServeSession.lua | 5 ++--- 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index df29083f..aec5f7ab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Updated Theme to use Studio colors ([#838]) * Improved patch visualizer UX ([#883]) * Added experimental setting for Auto Connect in playtests ([#840]) +* `Open Scripts Externally` option can now be changed while syncing ([#911]) * Projects may now specify rules for syncing files as if they had a different file extension. ([#813]) This is specified via a new field on project files, `syncRules`: @@ -61,6 +62,7 @@ [#883]: https://github.com/rojo-rbx/rojo/pull/883 [#893]: https://github.com/rojo-rbx/rojo/pull/893 [#903]: https://github.com/rojo-rbx/rojo/pull/903 +[#911]: https://github.com/rojo-rbx/rojo/pull/911 ## [7.4.1] - February 20, 2024 * Made the `name` field optional on project files ([#870]) diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua index 441c9cd8..e5fb1af4 100644 --- a/plugin/src/App/StatusPages/Settings/init.lua +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -175,7 +175,6 @@ function SettingsPage:render() id = "openScriptsExternally", name = "Open Scripts Externally", description = "Attempt to open scripts in an external editor", - locked = self.props.syncActive, experimental = true, transparency = self.props.transparency, layoutOrder = layoutIncrement(), diff --git a/plugin/src/App/init.lua b/plugin/src/App/init.lua index d80bf016..bd21765d 100644 --- a/plugin/src/App/init.lua +++ b/plugin/src/App/init.lua @@ -425,11 +425,6 @@ function App:startSession() local host, port = self:getHostAndPort() - local sessionOptions = { - openScriptsExternally = Settings:get("openScriptsExternally"), - twoWaySync = Settings:get("twoWaySync"), - } - local baseUrl = if string.find(host, "^https?://") then string.format("%s:%s", host, port) else string.format("http://%s:%s", host, port) @@ -437,8 +432,7 @@ function App:startSession() local serveSession = ServeSession.new({ apiContext = apiContext, - openScriptsExternally = sessionOptions.openScriptsExternally, - twoWaySync = sessionOptions.twoWaySync, + twoWaySync = Settings:get("twoWaySync"), }) self.cleanupPrecommit = serveSession.__reconciler:hookPrecommit(function(patch, instanceMap) diff --git a/plugin/src/ServeSession.lua b/plugin/src/ServeSession.lua index 82d8fd42..bb844d06 100644 --- a/plugin/src/ServeSession.lua +++ b/plugin/src/ServeSession.lua @@ -13,6 +13,7 @@ local InstanceMap = require(script.Parent.InstanceMap) local PatchSet = require(script.Parent.PatchSet) local Reconciler = require(script.Parent.Reconciler) local strict = require(script.Parent.strict) +local Settings = require(script.Parent.Settings) local Status = strict("Session.Status", { NotStarted = "NotStarted", @@ -50,7 +51,6 @@ ServeSession.Status = Status local validateServeOptions = t.strictInterface({ apiContext = t.table, - openScriptsExternally = t.boolean, twoWaySync = t.boolean, }) @@ -89,7 +89,6 @@ function ServeSession.new(options) self = { __status = Status.NotStarted, __apiContext = options.apiContext, - __openScriptsExternally = options.openScriptsExternally, __twoWaySync = options.twoWaySync, __reconciler = reconciler, __instanceMap = instanceMap, @@ -170,7 +169,7 @@ function ServeSession:__applyGameAndPlaceId(serverInfo) end function ServeSession:__onActiveScriptChanged(activeScript) - if not self.__openScriptsExternally then + if not Settings:get("openScriptsExternally") then Log.trace("Not opening script {} because feature not enabled.", activeScript) return From 3d4e387d350bd12366026623d1f0340a034bb1c4 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Mon, 13 May 2024 10:36:03 -0700 Subject: [PATCH 1396/1504] Redesign settings UI in plugin (#886) --- CHANGELOG.md | 2 + README.md | 4 +- assets/{ => brand_images}/icon-32.png | Bin assets/{ => brand_images}/icon-link-32.png | Bin assets/{ => brand_images}/icon-warn-32.png | Bin assets/{ => brand_images}/logo-512.png | Bin assets/images/{ => icons}/back.png | Bin assets/images/{ => icons}/back.svg | 0 assets/images/{ => icons}/close.png | Bin assets/images/{ => icons}/close.svg | 0 assets/images/icons/debug.png | Bin 0 -> 183 bytes assets/images/icons/expand.png | Bin 0 -> 273 bytes assets/images/icons/reset.png | Bin 0 -> 933 bytes assets/images/icons/warning.png | Bin 0 -> 241 bytes assets/{ => images}/round-rect-4px-radius.png | Bin plugin/src/App/Components/SlicedImage.lua | 1 + plugin/src/App/Components/Tag.lua | 56 ++++++++++ .../src/App/StatusPages/Settings/Setting.lua | 105 +++++++++++------- plugin/src/App/StatusPages/Settings/init.lua | 12 +- plugin/src/App/Theme.lua | 3 + plugin/src/Assets.lua | 2 + src/web/assets.rs | 4 +- 22 files changed, 141 insertions(+), 48 deletions(-) rename assets/{ => brand_images}/icon-32.png (100%) rename assets/{ => brand_images}/icon-link-32.png (100%) rename assets/{ => brand_images}/icon-warn-32.png (100%) rename assets/{ => brand_images}/logo-512.png (100%) rename assets/images/{ => icons}/back.png (100%) rename assets/images/{ => icons}/back.svg (100%) rename assets/images/{ => icons}/close.png (100%) rename assets/images/{ => icons}/close.svg (100%) create mode 100644 assets/images/icons/debug.png create mode 100644 assets/images/icons/expand.png create mode 100644 assets/images/icons/reset.png create mode 100644 assets/images/icons/warning.png rename assets/{ => images}/round-rect-4px-radius.png (100%) create mode 100644 plugin/src/App/Components/Tag.lua diff --git a/CHANGELOG.md b/CHANGELOG.md index aec5f7ab..05550ae2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ * Updated Theme to use Studio colors ([#838]) * Improved patch visualizer UX ([#883]) * Added experimental setting for Auto Connect in playtests ([#840]) +* Improved settings UI ([#886]) * `Open Scripts Externally` option can now be changed while syncing ([#911]) * Projects may now specify rules for syncing files as if they had a different file extension. ([#813]) This is specified via a new field on project files, `syncRules`: @@ -60,6 +61,7 @@ [#838]: https://github.com/rojo-rbx/rojo/pull/838 [#840]: https://github.com/rojo-rbx/rojo/pull/840 [#883]: https://github.com/rojo-rbx/rojo/pull/883 +[#886]: https://github.com/rojo-rbx/rojo/pull/886 [#893]: https://github.com/rojo-rbx/rojo/pull/893 [#903]: https://github.com/rojo-rbx/rojo/pull/903 [#911]: https://github.com/rojo-rbx/rojo/pull/911 diff --git a/README.md b/README.md index bbdeba30..bb4effcf 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@
    - Rojo + Rojo
     
    @@ -43,4 +43,4 @@ Pull requests are welcome! Rojo supports Rust 1.70.0 and newer. The minimum supported version of Rust is based on the latest versions of the dependencies that Rojo has. ## License -Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. \ No newline at end of file +Rojo is available under the terms of the Mozilla Public License, Version 2.0. See [LICENSE.txt](LICENSE.txt) for details. diff --git a/assets/icon-32.png b/assets/brand_images/icon-32.png similarity index 100% rename from assets/icon-32.png rename to assets/brand_images/icon-32.png diff --git a/assets/icon-link-32.png b/assets/brand_images/icon-link-32.png similarity index 100% rename from assets/icon-link-32.png rename to assets/brand_images/icon-link-32.png diff --git a/assets/icon-warn-32.png b/assets/brand_images/icon-warn-32.png similarity index 100% rename from assets/icon-warn-32.png rename to assets/brand_images/icon-warn-32.png diff --git a/assets/logo-512.png b/assets/brand_images/logo-512.png similarity index 100% rename from assets/logo-512.png rename to assets/brand_images/logo-512.png diff --git a/assets/images/back.png b/assets/images/icons/back.png similarity index 100% rename from assets/images/back.png rename to assets/images/icons/back.png diff --git a/assets/images/back.svg b/assets/images/icons/back.svg similarity index 100% rename from assets/images/back.svg rename to assets/images/icons/back.svg diff --git a/assets/images/close.png b/assets/images/icons/close.png similarity index 100% rename from assets/images/close.png rename to assets/images/icons/close.png diff --git a/assets/images/close.svg b/assets/images/icons/close.svg similarity index 100% rename from assets/images/close.svg rename to assets/images/icons/close.svg diff --git a/assets/images/icons/debug.png b/assets/images/icons/debug.png new file mode 100644 index 0000000000000000000000000000000000000000..b2217f0cc933c166880acd1444f8811676c28814 GIT binary patch literal 183 zcmeAS@N?(olHy`uVBq!ia0vp^JRr=$0wn*`OvwRKb)GJcArhB;&j*S!845UG^jJB? z%8BVUgG>XnN(hsXo0Dpc-8S1CyUCvCW>;u`*U4my^Yr-;d(h#fTw%kdNiK=AR6d5L zFIj7stUvwI^;*gF|2@CnJ=My+dG{?>#IsG@^0~~1uEUXg@A}w>H&~*tO@M zJkO<(2#^G09u6@a^fNzv0S+30DORidvIcyc7?LxD=Xi-v_yP}rM5H4Zg(yX`qMr?o z%)v>^to{)w2>MSg+{u`L92@uYp|E!5&=k0TXaOYwoX@g_nX1e@KJsHW=ofIn&&Urp z@&qec!Cg#MVOR3If?cIoz!8<@b&tzK^0U~ln7RUe0;*M4_$3t!NqjBqKM*V~1YRJM zsv7sG95E9p$2;LgF3#u~flRtoMxafDmG!c<@KaZS=0T2zaPMV_CM%UP))gJcF~C@4 zBLxy9Bq0eBBuKDB!ZLitbxXI#A8A8{?_nGn1|HZN1#FTX-^a|jTeS)T+RYG9E(mZ_ zT6_Uk*0$>@vzQLwbgkxYo(ob#?P5YCfyA!ZN^*EO#xYKX=+P8$ zFlP)e=&X{?ubJb`efXy5W>DxDiDZ|1*9ACgkaW7#88_00000NkvXX Hu0mjf$kUj$ literal 0 HcmV?d00001 diff --git a/assets/images/icons/warning.png b/assets/images/icons/warning.png new file mode 100644 index 0000000000000000000000000000000000000000..79d457df0a3d476c26fcad4a30109217d27ec628 GIT binary patch literal 241 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!60wlNoGJgf6c6hothG?9xouJ5f$U%hlzFO## zMVw0tnxdMV3OcMT994zl{hP8@U1afVJg`WsK{^1>e(l;bzkaQg&LZe8b0mz+rfBY8SjDKBjRS?K6ad#cP-EM z$v@=-FO+lcJBQy$oL9=#%d}(?$BH=@duC47Vw(6cD7e~k^51*n%xrOXEU&75`=#!Y p>1O>uL%K)pRsG$~x3kw@WiBcabDEuDw;1RL22WQ%mvv4FO#ry~UOoT- literal 0 HcmV?d00001 diff --git a/assets/round-rect-4px-radius.png b/assets/images/round-rect-4px-radius.png similarity index 100% rename from assets/round-rect-4px-radius.png rename to assets/images/round-rect-4px-radius.png diff --git a/plugin/src/App/Components/SlicedImage.lua b/plugin/src/App/Components/SlicedImage.lua index 40279cc8..1dff9caa 100644 --- a/plugin/src/App/Components/SlicedImage.lua +++ b/plugin/src/App/Components/SlicedImage.lua @@ -20,6 +20,7 @@ local function SlicedImage(props) Size = props.size, Position = props.position, AnchorPoint = props.anchorPoint, + AutomaticSize = props.automaticSize, ZIndex = props.zIndex, LayoutOrder = props.layoutOrder, diff --git a/plugin/src/App/Components/Tag.lua b/plugin/src/App/Components/Tag.lua new file mode 100644 index 00000000..9fed3d33 --- /dev/null +++ b/plugin/src/App/Components/Tag.lua @@ -0,0 +1,56 @@ +local Rojo = script:FindFirstAncestor("Rojo") +local Plugin = Rojo.Plugin +local Packages = Rojo.Packages + +local Roact = require(Packages.Roact) + +local Assets = require(Plugin.Assets) + +local SlicedImage = require(Plugin.App.Components.SlicedImage) + +local e = Roact.createElement + +return function(props) + return e(SlicedImage, { + slice = Assets.Slices.RoundedBackground, + color = props.color, + transparency = props.transparency:map(function(transparency) + return 0.9 + (0.1 * transparency) + end), + layoutOrder = props.layoutOrder, + position = props.position, + anchorPoint = props.anchorPoint, + size = UDim2.new(0, 0, 0, 16), + automaticSize = Enum.AutomaticSize.X, + }, { + Padding = e("UIPadding", { + PaddingLeft = UDim.new(0, 4), + PaddingRight = UDim.new(0, 4), + PaddingTop = UDim.new(0, 2), + PaddingBottom = UDim.new(0, 2), + }), + Icon = if props.icon + then e("ImageLabel", { + Size = UDim2.new(0, 12, 0, 12), + Position = UDim2.new(0, 0, 0.5, 0), + AnchorPoint = Vector2.new(0, 0.5), + Image = props.icon, + BackgroundTransparency = 1, + ImageColor3 = props.color, + ImageTransparency = props.transparency, + }) + else nil, + Text = e("TextLabel", { + Text = props.text, + Font = Enum.Font.GothamMedium, + TextSize = 12, + TextColor3 = props.color, + TextXAlignment = Enum.TextXAlignment.Center, + TextTransparency = props.transparency, + Size = UDim2.new(0, 0, 1, 0), + Position = UDim2.new(0, if props.icon then 15 else 0, 0, 0), + AutomaticSize = Enum.AutomaticSize.X, + BackgroundTransparency = 1, + }), + }) +end diff --git a/plugin/src/App/StatusPages/Settings/Setting.lua b/plugin/src/App/StatusPages/Settings/Setting.lua index 86170ec2..00c75d86 100644 --- a/plugin/src/App/StatusPages/Settings/Setting.lua +++ b/plugin/src/App/StatusPages/Settings/Setting.lua @@ -13,10 +13,23 @@ local Theme = require(Plugin.App.Theme) local Checkbox = require(Plugin.App.Components.Checkbox) local Dropdown = require(Plugin.App.Components.Dropdown) local IconButton = require(Plugin.App.Components.IconButton) +local Tag = require(Plugin.App.Components.Tag) local e = Roact.createElement local DIVIDER_FADE_SIZE = 0.1 +local TAG_TYPES = { + unstable = { + text = "UNSTABLE", + icon = Assets.Images.Icons.Warning, + color = { "Settings", "Setting", "UnstableColor" }, + }, + debug = { + text = "DEBUG", + icon = Assets.Images.Icons.Debug, + color = { "Settings", "Setting", "DebugColor" }, + }, +} local function getTextBounds(text, textSize, font, lineHeight, bounds) local textBounds = TextService:GetTextSize(text, textSize, font, bounds) @@ -27,6 +40,17 @@ local function getTextBounds(text, textSize, font, lineHeight, bounds) return Vector2.new(textBounds.X, lineHeightAbsolute * lineCount - (lineHeightAbsolute - textSize)) end +local function getThemeColorFromPath(theme, path) + local color = theme + for _, key in path do + if color[key] == nil then + return theme.BrandColor + end + color = color[key] + end + return color +end + local Setting = Roact.Component:extend("Setting") function Setting:init() @@ -51,11 +75,11 @@ end function Setting:render() return Theme.with(function(theme) - theme = theme.Settings + local settingsTheme = theme.Settings return e("Frame", { Size = self.contentSize:map(function(value) - return UDim2.new(1, 0, 0, 20 + value.Y + 20) + return UDim2.new(1, 0, 0, value.Y + 20) end), LayoutOrder = self.props.layoutOrder, ZIndex = -self.props.layoutOrder, @@ -106,7 +130,7 @@ function Setting:render() then e(IconButton, { icon = Assets.Images.Icons.Reset, iconSize = 24, - color = theme.BackButtonColor, + color = settingsTheme.BackButtonColor, transparency = self.props.transparency, visible = self.props.showReset, layoutOrder = -1, @@ -120,37 +144,49 @@ function Setting:render() Size = UDim2.new(1, 0, 1, 0), BackgroundTransparency = 1, }, { - Name = e("TextLabel", { - Text = ( - if self.props.experimental - then '⚠ ' - elseif - self.props.developerDebug - then '⚑ ' -- Guru is the only font with the flag emoji - else "" - ) .. self.props.name, - Font = Enum.Font.GothamBold, - TextSize = 17, - TextColor3 = theme.Setting.NameColor, - TextXAlignment = Enum.TextXAlignment.Left, - TextTransparency = self.props.transparency, - RichText = true, - - Size = UDim2.new(1, 0, 0, 17), - - LayoutOrder = 1, + Heading = e("Frame", { + Size = UDim2.new(1, 0, 0, 16), BackgroundTransparency = 1, + }, { + Layout = e("UIListLayout", { + VerticalAlignment = Enum.VerticalAlignment.Center, + FillDirection = Enum.FillDirection.Horizontal, + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = UDim.new(0, 5), + }), + Tag = if self.props.tag and TAG_TYPES[self.props.tag] + then e(Tag, { + layoutOrder = 1, + transparency = self.props.transparency, + text = TAG_TYPES[self.props.tag].text, + icon = TAG_TYPES[self.props.tag].icon, + color = getThemeColorFromPath(theme, TAG_TYPES[self.props.tag].color), + }) + else nil, + Name = e("TextLabel", { + Text = self.props.name, + Font = Enum.Font.GothamBold, + TextSize = 16, + TextColor3 = if self.props.tag and TAG_TYPES[self.props.tag] + then getThemeColorFromPath(theme, TAG_TYPES[self.props.tag].color) + else settingsTheme.Setting.NameColor, + TextXAlignment = Enum.TextXAlignment.Left, + TextTransparency = self.props.transparency, + RichText = true, + + Size = UDim2.new(1, 0, 0, 16), + + LayoutOrder = 2, + BackgroundTransparency = 1, + }), }), Description = e("TextLabel", { - Text = (if self.props.experimental - then '[Experimental] ' - elseif self.props.developerDebug then '[Dev Debug] ' - else "") .. self.props.description, + Text = self.props.description, Font = Enum.Font.Gotham, LineHeight = 1.2, TextSize = 14, - TextColor3 = theme.Setting.DescriptionColor, + TextColor3 = settingsTheme.Setting.DescriptionColor, TextXAlignment = Enum.TextXAlignment.Left, TextTransparency = self.props.transparency, TextWrapped = true, @@ -160,11 +196,9 @@ function Setting:render() containerSize = self.containerSize, inputSize = self.inputSize, }):map(function(values) - local desc = (if self.props.experimental then "[Experimental] " else "") - .. self.props.description local offset = values.inputSize.X + 5 local textBounds = getTextBounds( - desc, + self.props.description, 14, Enum.Font.Gotham, 1.2, @@ -173,7 +207,7 @@ function Setting:render() return UDim2.new(1, -offset, 0, textBounds.Y) end), - LayoutOrder = 2, + LayoutOrder = 3, BackgroundTransparency = 1, }), @@ -181,21 +215,16 @@ function Setting:render() VerticalAlignment = Enum.VerticalAlignment.Center, FillDirection = Enum.FillDirection.Vertical, SortOrder = Enum.SortOrder.LayoutOrder, - Padding = UDim.new(0, 6), + Padding = UDim.new(0, 5), [Roact.Change.AbsoluteContentSize] = function(object) self.setContentSize(object.AbsoluteContentSize) end, }), - - Padding = e("UIPadding", { - PaddingTop = UDim.new(0, 20), - PaddingBottom = UDim.new(0, 20), - }), }), Divider = e("Frame", { - BackgroundColor3 = theme.DividerColor, + BackgroundColor3 = settingsTheme.DividerColor, BackgroundTransparency = self.props.transparency, Size = UDim2.new(1, 0, 0, 1), BorderSizePixel = 0, diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua index e5fb1af4..70f83508 100644 --- a/plugin/src/App/StatusPages/Settings/init.lua +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -166,7 +166,7 @@ function SettingsPage:render() id = "autoConnectPlaytestServer", name = "Auto Connect Playtest Server", description = "Automatically connect game server to Rojo when playtesting while connected in Edit", - experimental = true, + tag = "unstable", transparency = self.props.transparency, layoutOrder = layoutIncrement(), }), @@ -175,7 +175,7 @@ function SettingsPage:render() id = "openScriptsExternally", name = "Open Scripts Externally", description = "Attempt to open scripts in an external editor", - experimental = true, + tag = "unstable", transparency = self.props.transparency, layoutOrder = layoutIncrement(), }), @@ -185,7 +185,7 @@ function SettingsPage:render() name = "Two-Way Sync", description = "Editing files in Studio will sync them into the filesystem", locked = self.props.syncActive, - experimental = true, + tag = "unstable", transparency = self.props.transparency, layoutOrder = layoutIncrement(), }), @@ -194,7 +194,7 @@ function SettingsPage:render() id = "logLevel", name = "Log Level", description = "Plugin output verbosity level", - developerDebug = true, + tag = "debug", transparency = self.props.transparency, layoutOrder = layoutIncrement(), @@ -211,7 +211,7 @@ function SettingsPage:render() id = "typecheckingEnabled", name = "Typechecking", description = "Toggle typechecking on the API surface", - developerDebug = true, + tag = "debug", transparency = self.props.transparency, layoutOrder = layoutIncrement(), }), @@ -220,7 +220,7 @@ function SettingsPage:render() id = "timingLogsEnabled", name = "Timing Logs", description = "Toggle logging timing of internal actions for benchmarking Rojo performance", - developerDebug = true, + tag = "debug", transparency = self.props.transparency, layoutOrder = layoutIncrement(), }), diff --git a/plugin/src/App/Theme.lua b/plugin/src/App/Theme.lua index 84a429c6..42d61942 100644 --- a/plugin/src/App/Theme.lua +++ b/plugin/src/App/Theme.lua @@ -35,6 +35,7 @@ function StudioProvider:updateTheme() local isDark = studioTheme.Name == "Dark" local theme = strict(studioTheme.Name .. "Theme", { + BrandColor = BRAND_COLOR, BackgroundColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainBackground), TextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainText), SubTextColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.SubText), @@ -166,6 +167,8 @@ function StudioProvider:updateTheme() Setting = { NameColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.BrightText), DescriptionColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.MainText), + UnstableColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.WarningText), + DebugColor = studioTheme:GetColor(Enum.StudioStyleGuideColor.InfoText), }, }, Header = { diff --git a/plugin/src/Assets.lua b/plugin/src/Assets.lua index 91f82d1a..e48c1217 100644 --- a/plugin/src/Assets.lua +++ b/plugin/src/Assets.lua @@ -25,6 +25,8 @@ local Assets = { Back = "rbxassetid://6017213752", Reset = "rbxassetid://10142422327", Expand = "rbxassetid://12045401097", + Warning = "rbxassetid://16571019891", + Debug = "rbxassetid://16588411361", Checkmark = "rbxassetid://16571012729", Exclamation = "rbxassetid://16571172190", SyncSuccess = "rbxassetid://16565035221", diff --git a/src/web/assets.rs b/src/web/assets.rs index 37adbe13..39f0958b 100644 --- a/src/web/assets.rs +++ b/src/web/assets.rs @@ -29,13 +29,13 @@ macro_rules! declare_asset { declare_asset!(css, "../../assets/index.css"); pub fn logo() -> &'static [u8] { - static LOGO: &[u8] = include_bytes!("../../assets/logo-512.png"); + static LOGO: &[u8] = include_bytes!("../../assets/brand_images/logo-512.png"); LOGO } pub fn icon() -> &'static [u8] { - static ICON: &[u8] = include_bytes!("../../assets/icon-32.png"); + static ICON: &[u8] = include_bytes!("../../assets/brand_images/icon-32.png"); ICON } From 62f4a1f3c2da7fe9f8927d26b5304ac37a4283d1 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Thu, 30 May 2024 12:28:58 -0700 Subject: [PATCH 1397/1504] Use history recording and don't do anything permanent (#915) --- CHANGELOG.md | 2 + plugin/src/InstanceMap.lua | 7 +++- plugin/src/Reconciler/applyPatch.lua | 22 +++++++++-- plugin/src/Reconciler/applyPatch.spec.lua | 45 +++++++++++++++++------ 4 files changed, 59 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 05550ae2..79abf800 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Rojo Changelog ## Unreleased Changes +* Updated Undo/Redo history to be more robust ([#915]) * Fixed removing trailing newlines ([#903]) * Added Never option to Confirmation ([#893]) * Added popout diff visualizer for table properties like Attributes and Tags ([#834]) @@ -65,6 +66,7 @@ [#893]: https://github.com/rojo-rbx/rojo/pull/893 [#903]: https://github.com/rojo-rbx/rojo/pull/903 [#911]: https://github.com/rojo-rbx/rojo/pull/911 +[#915]: https://github.com/rojo-rbx/rojo/pull/915 ## [7.4.1] - February 20, 2024 * Made the `name` field optional on project files ([#870]) diff --git a/plugin/src/InstanceMap.lua b/plugin/src/InstanceMap.lua index b035d423..76754fef 100644 --- a/plugin/src/InstanceMap.lua +++ b/plugin/src/InstanceMap.lua @@ -112,9 +112,12 @@ end function InstanceMap:destroyInstance(instance) local id = self.fromInstances[instance] - local descendants = instance:GetDescendants() - instance:Destroy() + + -- Because the user might want to Undo this change, we cannot use Destroy + -- since that locks that parent and prevents ChangeHistoryService from + -- ever bringing it back. Instead, we parent to nil. + instance.Parent = nil -- After the instance is successfully destroyed, -- we can remove all the id mappings diff --git a/plugin/src/Reconciler/applyPatch.lua b/plugin/src/Reconciler/applyPatch.lua index 5ee6ed5e..05e7412a 100644 --- a/plugin/src/Reconciler/applyPatch.lua +++ b/plugin/src/Reconciler/applyPatch.lua @@ -20,6 +20,11 @@ local setProperty = require(script.Parent.setProperty) local function applyPatch(instanceMap, patch) local patchTimestamp = DateTime.now():FormatLocalTime("LTS", "en-us") + local historyRecording = ChangeHistoryService:TryBeginRecording("Rojo: Patch " .. patchTimestamp) + if not historyRecording then + -- There can only be one recording at a time + Log.debug("Failed to begin history recording for " .. patchTimestamp .. ". Another recording is in progress.") + end -- Tracks any portions of the patch that could not be applied to the DOM. local unappliedPatch = PatchSet.newEmpty() @@ -62,6 +67,9 @@ local function applyPatch(instanceMap, patch) if parentInstance == nil then -- This would be peculiar. If you create an instance with no -- parent, were you supposed to create it at all? + if historyRecording then + ChangeHistoryService:FinishRecording(historyRecording, Enum.FinishRecordingOperation.Commit) + end invariant( "Cannot add an instance from a patch that has no parent.\nInstance {} with parent {}.\nState: {:#?}", id, @@ -164,10 +172,14 @@ local function applyPatch(instanceMap, patch) end -- See you later, original instance. - -- + + -- Because the user might want to Undo this change, we cannot use Destroy + -- since that locks that parent and prevents ChangeHistoryService from + -- ever bringing it back. Instead, we parent to nil. + -- TODO: Can this fail? Some kinds of instance may not appreciate - -- being destroyed, like services. - instance:Destroy() + -- being reparented, like services. + instance.Parent = nil -- This completes your rebuilding a plane mid-flight safety -- instruction. Please sit back, relax, and enjoy your flight. @@ -214,7 +226,9 @@ local function applyPatch(instanceMap, patch) end end - ChangeHistoryService:SetWaypoint("Rojo: Patch " .. patchTimestamp) + if historyRecording then + ChangeHistoryService:FinishRecording(historyRecording, Enum.FinishRecordingOperation.Commit) + end return unappliedPatch end diff --git a/plugin/src/Reconciler/applyPatch.spec.lua b/plugin/src/Reconciler/applyPatch.spec.lua index c561db75..b44e3eda 100644 --- a/plugin/src/Reconciler/applyPatch.spec.lua +++ b/plugin/src/Reconciler/applyPatch.spec.lua @@ -4,25 +4,41 @@ return function() local InstanceMap = require(script.Parent.Parent.InstanceMap) local PatchSet = require(script.Parent.Parent.PatchSet) - local dummy = Instance.new("Folder") - local function wasDestroyed(instance) + local container = Instance.new("Folder") + + local tempContainer = Instance.new("Folder") + local function wasRemoved(instance) -- If an instance was destroyed, its parent property is locked. - local ok = pcall(function() + -- If an instance was removed, its parent property is nil. + -- We need to ensure we only remove, so that ChangeHistoryService can still Undo. + + local isParentUnlocked = pcall(function() local oldParent = instance.Parent - instance.Parent = dummy + instance.Parent = tempContainer instance.Parent = oldParent end) - return not ok + return instance.Parent == nil and isParentUnlocked end + beforeEach(function() + container:ClearAllChildren() + end) + + afterAll(function() + container:Destroy() + tempContainer:Destroy() + end) + it("should return an empty patch if given an empty patch", function() local patch = applyPatch(InstanceMap.new(), PatchSet.newEmpty()) assert(PatchSet.isEmpty(patch), "expected remaining patch to be empty") end) - it("should destroy instances listed for remove", function() + it("should remove instances listed for remove", function() local root = Instance.new("Folder") + root.Name = "ROOT" + root.Parent = container local child = Instance.new("Folder") child.Name = "Child" @@ -38,14 +54,16 @@ return function() local unapplied = applyPatch(instanceMap, patch) assert(PatchSet.isEmpty(unapplied), "expected remaining patch to be empty") - assert(not wasDestroyed(root), "expected root to be left alone") - assert(wasDestroyed(child), "expected child to be destroyed") + assert(not wasRemoved(root), "expected root to be left alone") + assert(wasRemoved(child), "expected child to be removed") instanceMap:stop() end) - it("should destroy IDs listed for remove", function() + it("should remove IDs listed for remove", function() local root = Instance.new("Folder") + root.Name = "ROOT" + root.Parent = container local child = Instance.new("Folder") child.Name = "Child" @@ -62,8 +80,8 @@ return function() assert(PatchSet.isEmpty(unapplied), "expected remaining patch to be empty") expect(instanceMap:size()).to.equal(1) - assert(not wasDestroyed(root), "expected root to be left alone") - assert(wasDestroyed(child), "expected child to be destroyed") + assert(not wasRemoved(root), "expected root to be left alone") + assert(wasRemoved(child), "expected child to be removed") instanceMap:stop() end) @@ -73,6 +91,8 @@ return function() -- tests on reify, not here. local root = Instance.new("Folder") + root.Name = "ROOT" + root.Parent = container local instanceMap = InstanceMap.new() instanceMap:insert("ROOT", root) @@ -113,6 +133,8 @@ return function() it("should return unapplied additions when instances cannot be created", function() local root = Instance.new("Folder") + root.Name = "ROOT" + root.Parent = container local instanceMap = InstanceMap.new() instanceMap:insert("ROOT", root) @@ -159,6 +181,7 @@ return function() it("should recreate instances when changedClassName is set, preserving children", function() local root = Instance.new("Folder") root.Name = "Initial Root Name" + root.Parent = container local child = Instance.new("Folder") child.Name = "Child" From a7b45ee859f593445b89992711321cc48370d288 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 30 May 2024 12:45:38 -0700 Subject: [PATCH 1398/1504] Bump h2 from 0.3.24 to 0.3.26 (#921) --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 67f82f52..1b2ae180 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -699,9 +699,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.24" +version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2c4422095b67ee78da96fbb51a4cc413b3b25883c7717ff7ca1ab31022c9c9" +checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" dependencies = [ "bytes", "fnv", From 7e2bab921aa71f76d07d0424e4bb4064e8b7c995 Mon Sep 17 00:00:00 2001 From: Micah Date: Thu, 20 Jun 2024 15:48:52 -0700 Subject: [PATCH 1399/1504] Support setting referent properties via attributes (#843) Co-authored-by: Kenneth Loeffler --- CHANGELOG.md | 20 +++ ...d__tests__serve__ref_properties_all-2.snap | 141 ++++++++++++++++++ ...end__tests__serve__ref_properties_all.snap | 121 +++++++++++++++ ...nd__tests__serve__ref_properties_info.snap | 13 ++ ...s__serve__ref_properties_remove_all-2.snap | 33 ++++ ...sts__serve__ref_properties_remove_all.snap | 47 ++++++ ...ts__serve__ref_properties_remove_info.snap | 13 ++ ...erve__ref_properties_remove_subscribe.snap | 12 ++ ...ests__serve__ref_properties_subscribe.snap | 46 ++++++ .../FolderTarget/FolderPointer.model.json | 6 + .../FolderTarget/init.meta.json | 3 + .../ref_properties/ModelTarget.model.json | 13 ++ .../ref_properties/default.project.json | 32 ++++ .../default.project.json | 6 + .../src/pointer.model.json | 6 + .../src/target.model.json | 6 + src/lib.rs | 2 + src/multimap.rs | 32 +++- src/project.rs | 5 + src/resolution.rs | 6 + src/rojo_ref.rs | 30 ++++ src/snapshot/metadata.rs | 12 ++ src/snapshot/patch_apply.rs | 87 +++++++++++ ..._snapshot__tests__apply__add_property.snap | 1 + ...s__apply__remove_property_after_patch.snap | 1 + ...tests__apply__remove_property_initial.snap | 1 + ...tests__apply__set_name_and_class_name.snap | 1 + ...__snapshot__tests__compute__add_child.snap | 1 + src/snapshot/tree.rs | 80 +++++++++- src/snapshot_middleware/json_model.rs | 9 +- src/snapshot_middleware/meta_file.rs | 32 +++- src/snapshot_middleware/project.rs | 5 + ...t_middleware__csv__test__csv_from_vfs.snap | 1 + ..._middleware__csv__test__csv_with_meta.snap | 1 + ...t_middleware__dir__test__empty_folder.snap | 1 + ...ddleware__dir__test__folder_in_folder.snap | 2 + ...leware__json__test__instance_from_vfs.snap | 1 + ...are__json_model__test__model_from_vfs.snap | 2 + ...on_model__test__model_from_vfs_legacy.snap | 2 + ...are__lua__test__class_client_from_vfs.snap | 1 + ...are__lua__test__class_module_from_vfs.snap | 1 + ...re__lua__test__class_module_with_meta.snap | 1 + ...are__lua__test__class_script_disabled.snap | 1 + ...re__lua__test__class_script_with_meta.snap | 1 + ...are__lua__test__class_server_from_vfs.snap | 1 + ...lua__test__runcontext_client_from_vfs.snap | 1 + ...lua__test__runcontext_module_from_vfs.snap | 1 + ...ua__test__runcontext_module_with_meta.snap | 1 + ...lua__test__runcontext_script_disabled.snap | 1 + ...ua__test__runcontext_script_with_meta.snap | 1 + ...lua__test__runcontext_server_from_vfs.snap | 1 + ...eware__project__test__no_name_project.snap | 4 +- ...oject__test__project_from_direct_file.snap | 1 + ...test__project_path_property_overrides.snap | 1 + ..._project__test__project_with_children.snap | 2 + ...t__test__project_with_path_to_project.snap | 1 + ...ct_with_path_to_project_with_children.snap | 2 + ...oject__test__project_with_path_to_txt.snap | 1 + ...est__project_with_resolved_properties.snap | 1 + ...t__project_with_unresolved_properties.snap | 1 + ...leware__toml__test__instance_from_vfs.snap | 1 + ...dleware__txt__test__instance_from_vfs.snap | 1 + src/web/ui.rs | 3 +- tests/tests/serve.rs | 85 +++++++++++ 64 files changed, 942 insertions(+), 7 deletions(-) create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_all-2.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_all.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_info.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_all-2.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_all.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_info.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_subscribe.snap create mode 100644 rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_subscribe.snap create mode 100644 rojo-test/serve-tests/ref_properties/FolderTarget/FolderPointer.model.json create mode 100644 rojo-test/serve-tests/ref_properties/FolderTarget/init.meta.json create mode 100644 rojo-test/serve-tests/ref_properties/ModelTarget.model.json create mode 100644 rojo-test/serve-tests/ref_properties/default.project.json create mode 100644 rojo-test/serve-tests/ref_properties_remove/default.project.json create mode 100644 rojo-test/serve-tests/ref_properties_remove/src/pointer.model.json create mode 100644 rojo-test/serve-tests/ref_properties_remove/src/target.model.json create mode 100644 src/rojo_ref.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 79abf800..ad9b44bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,25 @@ # Rojo Changelog ## Unreleased Changes +* Projects may now manually link `Ref` properties together using `Attributes`. ([#843]) + This has two parts: using `id` or `$id` in JSON files or a `Rojo_Target` attribute, an Instance + is given an ID. Then, that ID may be used elsewhere in the project to point to an Instance + using an attribute named `Rojo_Target_PROP_NAME`, where `PROP_NAME` is the name of a property. + + As an example, here is a `model.json` for an ObjectValue that refers to itself: + + ```json + { + "id": "arbitrary string", + "attributes": { + "Rojo_Target_Value": "arbitrary string" + } + } + ``` + + This is a very rough implementation and the usage will become more ergonomic + over time. + * Updated Undo/Redo history to be more robust ([#915]) * Fixed removing trailing newlines ([#903]) * Added Never option to Confirmation ([#893]) @@ -61,6 +80,7 @@ [#834]: https://github.com/rojo-rbx/rojo/pull/834 [#838]: https://github.com/rojo-rbx/rojo/pull/838 [#840]: https://github.com/rojo-rbx/rojo/pull/840 +[#843]: https://github.com/rojo-rbx/rojo/pull/843 [#883]: https://github.com/rojo-rbx/rojo/pull/883 [#886]: https://github.com/rojo-rbx/rojo/pull/886 [#893]: https://github.com/rojo-rbx/rojo/pull/893 diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_all-2.snap new file mode 100644 index 00000000..63f6c550 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_all-2.snap @@ -0,0 +1,141 @@ +--- +source: tests/tests/serve.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-10: + Children: [] + ClassName: ObjectValue + Id: id-10 + Metadata: + ignoreUnknownInstances: true + Name: ProjectPointer + Parent: id-9 + Properties: + Attributes: + Attributes: + Rojo_Target_Value: + String: project target + Value: + Ref: id-9 + id-11: + Children: [] + ClassName: Model + Id: id-11 + Metadata: + ignoreUnknownInstances: false + Name: ProjectPointer + Parent: id-7 + Properties: + Attributes: + Attributes: + Rojo_Target_PrimaryPart: + String: project target + PrimaryPart: + Ref: id-9 + id-2: + Children: + - id-3 + ClassName: DataModel + Id: id-2 + Metadata: + ignoreUnknownInstances: true + Name: ref_properties + Parent: "00000000000000000000000000000000" + Properties: {} + id-3: + Children: + - id-4 + - id-5 + - id-7 + - id-9 + ClassName: Workspace + Id: id-3 + Metadata: + ignoreUnknownInstances: true + Name: Workspace + Parent: id-2 + Properties: {} + id-4: + Children: [] + ClassName: ObjectValue + Id: id-4 + Metadata: + ignoreUnknownInstances: true + Name: CrossFormatPointer + Parent: id-3 + Properties: + Attributes: + Attributes: + Rojo_Target_Value: + String: folder target + Value: + Ref: id-5 + id-5: + Children: + - id-6 + ClassName: Folder + Id: id-5 + Metadata: + ignoreUnknownInstances: false + Name: FolderTarget + Parent: id-3 + Properties: {} + id-6: + Children: [] + ClassName: ObjectValue + Id: id-6 + Metadata: + ignoreUnknownInstances: false + Name: FolderPointer + Parent: id-5 + Properties: + Attributes: + Attributes: + Rojo_Target_Value: + String: folder target + Value: + Ref: id-5 + id-7: + Children: + - id-8 + - id-11 + ClassName: Folder + Id: id-7 + Metadata: + ignoreUnknownInstances: false + Name: ModelTarget + Parent: id-3 + Properties: + Attributes: + Attributes: + Rojo_Id: + String: model target 2 + id-8: + Children: [] + ClassName: Model + Id: id-8 + Metadata: + ignoreUnknownInstances: false + Name: ModelPointer + Parent: id-7 + Properties: + Attributes: + Attributes: + Rojo_Target_PrimaryPart: + String: model target 2 + PrimaryPart: + Ref: id-7 + id-9: + Children: + - id-10 + ClassName: Folder + Id: id-9 + Metadata: + ignoreUnknownInstances: true + Name: ProjectTarget + Parent: id-3 + Properties: {} +messageCursor: 1 +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_all.snap new file mode 100644 index 00000000..7fe614cd --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_all.snap @@ -0,0 +1,121 @@ +--- +source: tests/tests/serve.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-10: + Children: [] + ClassName: ObjectValue + Id: id-10 + Metadata: + ignoreUnknownInstances: true + Name: ProjectPointer + Parent: id-9 + Properties: + Attributes: + Attributes: + Rojo_Target_Value: + String: project target + Value: + Ref: id-9 + id-2: + Children: + - id-3 + ClassName: DataModel + Id: id-2 + Metadata: + ignoreUnknownInstances: true + Name: ref_properties + Parent: "00000000000000000000000000000000" + Properties: {} + id-3: + Children: + - id-4 + - id-5 + - id-7 + - id-9 + ClassName: Workspace + Id: id-3 + Metadata: + ignoreUnknownInstances: true + Name: Workspace + Parent: id-2 + Properties: {} + id-4: + Children: [] + ClassName: ObjectValue + Id: id-4 + Metadata: + ignoreUnknownInstances: true + Name: CrossFormatPointer + Parent: id-3 + Properties: + Attributes: + Attributes: + Rojo_Target_Value: + String: folder target + Value: + Ref: id-5 + id-5: + Children: + - id-6 + ClassName: Folder + Id: id-5 + Metadata: + ignoreUnknownInstances: false + Name: FolderTarget + Parent: id-3 + Properties: {} + id-6: + Children: [] + ClassName: ObjectValue + Id: id-6 + Metadata: + ignoreUnknownInstances: false + Name: FolderPointer + Parent: id-5 + Properties: + Attributes: + Attributes: + Rojo_Target_Value: + String: folder target + Value: + Ref: id-5 + id-7: + Children: + - id-8 + ClassName: Folder + Id: id-7 + Metadata: + ignoreUnknownInstances: false + Name: ModelTarget + Parent: id-3 + Properties: {} + id-8: + Children: [] + ClassName: Model + Id: id-8 + Metadata: + ignoreUnknownInstances: false + Name: ModelPointer + Parent: id-7 + Properties: + Attributes: + Attributes: + Rojo_Target_PrimaryPart: + String: model target + PrimaryPart: + Ref: id-7 + id-9: + Children: + - id-10 + ClassName: Folder + Id: id-9 + Metadata: + ignoreUnknownInstances: true + Name: ProjectTarget + Parent: id-3 + Properties: {} +messageCursor: 0 +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_info.snap new file mode 100644 index 00000000..46ee7ea0 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_info.snap @@ -0,0 +1,13 @@ +--- +source: tests/tests/serve.rs +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +gameId: ~ +placeId: ~ +projectName: ref_properties +protocolVersion: 4 +rootInstanceId: id-2 +serverVersion: "[server-version]" +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_all-2.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_all-2.snap new file mode 100644 index 00000000..e548f010 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_all-2.snap @@ -0,0 +1,33 @@ +--- +source: tests/tests/serve.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Children: + - id-3 + ClassName: Folder + Id: id-2 + Metadata: + ignoreUnknownInstances: false + Name: ref_properties_remove + Parent: "00000000000000000000000000000000" + Properties: {} + id-3: + Children: [] + ClassName: ObjectValue + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: pointer + Parent: id-2 + Properties: + Attributes: + Attributes: + Rojo_Target_Value: + String: test pointer + Value: + Ref: id-4 +messageCursor: 1 +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_all.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_all.snap new file mode 100644 index 00000000..407670da --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_all.snap @@ -0,0 +1,47 @@ +--- +source: tests/tests/serve.rs +expression: "read_response.intern_and_redact(&mut redactions, root_id)" +--- +instances: + id-2: + Children: + - id-3 + - id-4 + ClassName: Folder + Id: id-2 + Metadata: + ignoreUnknownInstances: false + Name: ref_properties_remove + Parent: "00000000000000000000000000000000" + Properties: {} + id-3: + Children: [] + ClassName: ObjectValue + Id: id-3 + Metadata: + ignoreUnknownInstances: false + Name: pointer + Parent: id-2 + Properties: + Attributes: + Attributes: + Rojo_Target_Value: + String: test pointer + Value: + Ref: id-4 + id-4: + Children: [] + ClassName: ObjectValue + Id: id-4 + Metadata: + ignoreUnknownInstances: false + Name: target + Parent: id-2 + Properties: + Attributes: + Attributes: + Rojo_Id: + String: test pointer +messageCursor: 0 +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_info.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_info.snap new file mode 100644 index 00000000..b51fd1f8 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_info.snap @@ -0,0 +1,13 @@ +--- +source: tests/tests/serve.rs +expression: redactions.redacted_yaml(info) +--- +expectedPlaceIds: ~ +gameId: ~ +placeId: ~ +projectName: ref_properties_remove +protocolVersion: 4 +rootInstanceId: id-2 +serverVersion: "[server-version]" +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_subscribe.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_subscribe.snap new file mode 100644 index 00000000..92432570 --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_remove_subscribe.snap @@ -0,0 +1,12 @@ +--- +source: tests/tests/serve.rs +expression: "subscribe_response.intern_and_redact(&mut redactions, ())" +--- +messageCursor: 1 +messages: + - added: {} + removed: + - id-4 + updated: [] +sessionId: id-1 + diff --git a/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_subscribe.snap b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_subscribe.snap new file mode 100644 index 00000000..4500894a --- /dev/null +++ b/rojo-test/serve-test-snapshots/end_to_end__tests__serve__ref_properties_subscribe.snap @@ -0,0 +1,46 @@ +--- +source: tests/tests/serve.rs +expression: "subscribe_response.intern_and_redact(&mut redactions, ())" +--- +messageCursor: 1 +messages: + - added: + id-11: + Children: [] + ClassName: Model + Id: id-11 + Metadata: + ignoreUnknownInstances: false + Name: ProjectPointer + Parent: id-7 + Properties: + Attributes: + Attributes: + Rojo_Target_PrimaryPart: + String: project target + PrimaryPart: + Ref: id-9 + removed: [] + updated: + - changedClassName: ~ + changedMetadata: + ignoreUnknownInstances: false + changedName: ~ + changedProperties: + Attributes: + Attributes: + Rojo_Id: + String: model target 2 + id: id-7 + - changedClassName: ~ + changedMetadata: ~ + changedName: ~ + changedProperties: + Attributes: + Attributes: + Rojo_Target_PrimaryPart: + String: model target 2 + PrimaryPart: ~ + id: id-8 +sessionId: id-1 + diff --git a/rojo-test/serve-tests/ref_properties/FolderTarget/FolderPointer.model.json b/rojo-test/serve-tests/ref_properties/FolderTarget/FolderPointer.model.json new file mode 100644 index 00000000..a4543ff4 --- /dev/null +++ b/rojo-test/serve-tests/ref_properties/FolderTarget/FolderPointer.model.json @@ -0,0 +1,6 @@ +{ + "className": "ObjectValue", + "attributes": { + "Rojo_Target_Value": "folder target" + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/ref_properties/FolderTarget/init.meta.json b/rojo-test/serve-tests/ref_properties/FolderTarget/init.meta.json new file mode 100644 index 00000000..1705a7be --- /dev/null +++ b/rojo-test/serve-tests/ref_properties/FolderTarget/init.meta.json @@ -0,0 +1,3 @@ +{ + "id": "folder target" +} \ No newline at end of file diff --git a/rojo-test/serve-tests/ref_properties/ModelTarget.model.json b/rojo-test/serve-tests/ref_properties/ModelTarget.model.json new file mode 100644 index 00000000..36710365 --- /dev/null +++ b/rojo-test/serve-tests/ref_properties/ModelTarget.model.json @@ -0,0 +1,13 @@ +{ + "id": "model target", + "className": "Folder", + "children": [ + { + "name": "ModelPointer", + "className": "Model", + "attributes": { + "Rojo_Target_PrimaryPart": "model target" + } + } + ] +} \ No newline at end of file diff --git a/rojo-test/serve-tests/ref_properties/default.project.json b/rojo-test/serve-tests/ref_properties/default.project.json new file mode 100644 index 00000000..8ffa1908 --- /dev/null +++ b/rojo-test/serve-tests/ref_properties/default.project.json @@ -0,0 +1,32 @@ +{ + "name": "ref_properties", + "tree": { + "$className": "DataModel", + "Workspace": { + "ProjectTarget": { + "$className": "Folder", + "$id": "project target", + "ProjectPointer": { + "$className": "ObjectValue", + "$attributes": { + "Rojo_Target_Value": { + "String": "project target" + } + } + } + }, + "ModelTarget": { + "$path": "ModelTarget.model.json" + }, + "FolderTarget": { + "$path": "FolderTarget" + }, + "CrossFormatPointer": { + "$className": "ObjectValue", + "$attributes": { + "Rojo_Target_Value": "folder target" + } + } + } + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/ref_properties_remove/default.project.json b/rojo-test/serve-tests/ref_properties_remove/default.project.json new file mode 100644 index 00000000..43f94765 --- /dev/null +++ b/rojo-test/serve-tests/ref_properties_remove/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "ref_properties_remove", + "tree": { + "$path": "src" + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/ref_properties_remove/src/pointer.model.json b/rojo-test/serve-tests/ref_properties_remove/src/pointer.model.json new file mode 100644 index 00000000..4add638b --- /dev/null +++ b/rojo-test/serve-tests/ref_properties_remove/src/pointer.model.json @@ -0,0 +1,6 @@ +{ + "className": "ObjectValue", + "attributes": { + "Rojo_Target_Value": "test pointer" + } +} \ No newline at end of file diff --git a/rojo-test/serve-tests/ref_properties_remove/src/target.model.json b/rojo-test/serve-tests/ref_properties_remove/src/target.model.json new file mode 100644 index 00000000..8069631e --- /dev/null +++ b/rojo-test/serve-tests/ref_properties_remove/src/target.model.json @@ -0,0 +1,6 @@ +{ + "className": "ObjectValue", + "attributes": { + "Rojo_Id": "test pointer" + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 51195b6c..19020950 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -16,6 +16,7 @@ mod multimap; mod path_serializer; mod project; mod resolution; +mod rojo_ref; mod serve_session; mod session_id; mod snapshot; @@ -23,5 +24,6 @@ mod snapshot_middleware; mod web; pub use project::*; +pub use rojo_ref::*; pub use session_id::SessionId; pub use web::interface as web_api; diff --git a/src/multimap.rs b/src/multimap.rs index 3a243af1..9c399c24 100644 --- a/src/multimap.rs +++ b/src/multimap.rs @@ -1,6 +1,6 @@ use std::{ borrow::Borrow, - collections::HashMap, + collections::{hash_map, HashMap}, fmt::{self, Debug}, hash::Hash, }; @@ -71,3 +71,33 @@ impl PartialEq for MultiMap { self.inner == other.inner } } + +impl Default for MultiMap { + fn default() -> Self { + Self { + inner: Default::default(), + } + } +} + +impl IntoIterator for MultiMap { + type IntoIter = MultiMapIntoIter; + type Item = (K, Vec); + fn into_iter(self) -> Self::IntoIter { + Self::IntoIter { + inner: self.inner.into_iter(), + } + } +} + +pub struct MultiMapIntoIter { + inner: hash_map::IntoIter>, +} + +impl Iterator for MultiMapIntoIter { + type Item = (K, Vec); + + fn next(&mut self) -> Option { + self.inner.next() + } +} diff --git a/src/project.rs b/src/project.rs index bf6bc163..6e503dd6 100644 --- a/src/project.rs +++ b/src/project.rs @@ -226,6 +226,11 @@ pub struct ProjectNode { #[serde(rename = "$className", skip_serializing_if = "Option::is_none")] pub class_name: Option, + /// If set, defines an ID for the described Instance that can be used + /// to refer to it for the purpose of referent properties. + #[serde(rename = "$id", skip_serializing_if = "Option::is_none")] + pub id: Option, + /// Contains all of the children of the described instance. #[serde(flatten)] pub children: BTreeMap, diff --git a/src/resolution.rs b/src/resolution.rs index 9a0219ee..7cba31c4 100644 --- a/src/resolution.rs +++ b/src/resolution.rs @@ -8,6 +8,8 @@ use rbx_dom_weak::types::{ use rbx_reflection::{DataType, PropertyDescriptor}; use serde::{Deserialize, Serialize}; +use crate::REF_POINTER_ATTRIBUTE_PREFIX; + /// A user-friendly version of `Variant` that supports specifying ambiguous /// values. Ambiguous values need a reflection database to be resolved to a /// usable value. @@ -147,6 +149,10 @@ impl AmbiguousValue { Ok(value.into()) } + (VariantType::Ref, AmbiguousValue::String(_)) => Err(format_err!( + "Cannot resolve Ref properties as a String.\ + Use an attribute named `{REF_POINTER_ATTRIBUTE_PREFIX}{prop_name}" + )), (_, unresolved) => Err(format_err!( "Wrong type of value for property {}.{}. Expected {:?}, got {}", class_name, diff --git a/src/rojo_ref.rs b/src/rojo_ref.rs new file mode 100644 index 00000000..fbbf997e --- /dev/null +++ b/src/rojo_ref.rs @@ -0,0 +1,30 @@ +use std::{fmt, sync::Arc}; + +use serde::{Deserialize, Serialize}; + +pub const REF_ID_ATTRIBUTE_NAME: &str = "Rojo_Id"; +pub const REF_POINTER_ATTRIBUTE_PREFIX: &str = "Rojo_Target_"; + +// TODO add an internment strategy for RojoRefs +// Something like what rbx-dom does for SharedStrings probably works + +#[derive(Debug, Default, PartialEq, Hash, Clone, Serialize, Deserialize, Eq)] +pub struct RojoRef(Arc); + +impl RojoRef { + #[inline] + pub fn new(id: String) -> Self { + Self(Arc::from(id)) + } + + #[inline] + pub fn as_str(&self) -> &str { + self.0.as_str() + } +} + +impl fmt::Display for RojoRef { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.as_str()) + } +} diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index 1578af23..abe66df2 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -12,6 +12,7 @@ use crate::{ path_serializer, project::ProjectNode, snapshot_middleware::{emit_legacy_scripts_default, Middleware}, + RojoRef, }; /// Rojo-specific metadata that can be associated with an instance or a snapshot @@ -58,6 +59,9 @@ pub struct InstanceMetadata { /// that instance's instigating source is snapshotted directly, the same /// context will be passed into it. pub context: InstanceContext, + + /// Indicates the ID used for Ref properties pointing to this Instance. + pub specified_id: Option, } impl InstanceMetadata { @@ -67,6 +71,7 @@ impl InstanceMetadata { instigating_source: None, relevant_paths: Vec::new(), context: InstanceContext::default(), + specified_id: None, } } @@ -97,6 +102,13 @@ impl InstanceMetadata { ..self } } + + pub fn specified_id(self, id: Option) -> Self { + Self { + specified_id: id, + ..self + } + } } impl Default for InstanceMetadata { diff --git a/src/snapshot/patch_apply.rs b/src/snapshot/patch_apply.rs index 572b8455..af688722 100644 --- a/src/snapshot/patch_apply.rs +++ b/src/snapshot/patch_apply.rs @@ -11,6 +11,7 @@ use super::{ patch::{AppliedPatchSet, AppliedPatchUpdate, PatchSet, PatchUpdate}, InstanceSnapshot, RojoTree, }; +use crate::{multimap::MultiMap, RojoRef, REF_ID_ATTRIBUTE_NAME, REF_POINTER_ATTRIBUTE_PREFIX}; /// Consumes the input `PatchSet`, applying all of its prescribed changes to the /// tree and returns an `AppliedPatchSet`, which can be used to keep another @@ -72,6 +73,11 @@ struct PatchApplyContext { /// to be rewritten. has_refs_to_rewrite: HashSet, + /// Tracks all ref properties that were specified using attributes. This has + /// to be handled after everything else is done just like normal referent + /// properties. + attribute_refs_to_rewrite: MultiMap, + /// The current applied patch result, describing changes made to the tree. applied_patch_set: AppliedPatchSet, } @@ -104,6 +110,22 @@ fn finalize_patch_application(context: PatchApplyContext, tree: &mut RojoTree) - } } + // This is to get around the fact that `RojoTre::get_specified_id` borrows + // the tree as immutable, but we need to hold a mutable reference to it. + // Not exactly elegant, but it does the job. + let mut real_rewrites = Vec::new(); + for (id, map) in context.attribute_refs_to_rewrite { + for (prop_name, prop_value) in map { + if let Some(target) = tree.get_specified_id(&RojoRef::new(prop_value)) { + real_rewrites.push((prop_name, Variant::Ref(target))) + } + } + let mut instance = tree + .get_instance_mut(id) + .expect("Invalid instance ID in deferred attribute ref map"); + instance.properties_mut().extend(real_rewrites.drain(..)); + } + context.applied_patch_set } @@ -142,6 +164,8 @@ fn apply_add_child( for child in children { apply_add_child(context, tree, id, child); } + + defer_ref_properties(tree, id, context); } fn apply_update_child(context: &mut PatchApplyContext, tree: &mut RojoTree, patch: PatchUpdate) { @@ -208,9 +232,72 @@ fn apply_update_child(context: &mut PatchApplyContext, tree: &mut RojoTree, patc applied_patch.changed_properties.insert(key, property_entry); } + defer_ref_properties(tree, patch.id, context); + context.applied_patch_set.updated.push(applied_patch) } +/// Calculates manually-specified Ref properties and marks them in the provided +/// `PatchApplyContext` to be rewritten at the end of the patch application +/// process. +/// +/// Currently, this only uses attributes but it can easily handle rewriting +/// referents in other ways too! +fn defer_ref_properties(tree: &mut RojoTree, id: Ref, context: &mut PatchApplyContext) { + let instance = tree + .get_instance(id) + .expect("Instances should exist when calculating deferred refs"); + let attributes = match instance.properties().get("Attributes") { + Some(Variant::Attributes(attrs)) => attrs, + _ => return, + }; + + let mut attr_id = None; + for (attr_name, attr_value) in attributes.iter() { + if attr_name == REF_ID_ATTRIBUTE_NAME { + if let Variant::String(specified_id) = attr_value { + attr_id = Some(RojoRef::new(specified_id.clone())); + } else if let Variant::BinaryString(specified_id) = attr_value { + if let Ok(str) = std::str::from_utf8(specified_id.as_ref()) { + attr_id = Some(RojoRef::new(str.to_string())) + } else { + log::error!("Specified IDs must be valid UTF-8 strings.") + } + } else { + log::warn!( + "Attribute {attr_name} is of type {:?} when it was \ + expected to be a String", + attr_value.ty() + ) + } + } + if let Some(prop_name) = attr_name.strip_prefix(REF_POINTER_ATTRIBUTE_PREFIX) { + if let Variant::String(prop_value) = attr_value { + context + .attribute_refs_to_rewrite + .insert(id, (prop_name.to_owned(), prop_value.clone())); + } else if let Variant::BinaryString(prop_value) = attr_value { + if let Ok(str) = std::str::from_utf8(prop_value.as_ref()) { + context + .attribute_refs_to_rewrite + .insert(id, (prop_name.to_owned(), str.to_string())); + } else { + log::error!("IDs specified by referent property attributes must be valid UTF-8 strings.") + } + } else { + log::warn!( + "Attribute {attr_name} is of type {:?} when it was \ + expected to be a String", + attr_value.ty() + ) + } + } + } + if let Some(specified_id) = attr_id { + tree.set_specified_id(id, specified_id); + } +} + #[cfg(test)] mod test { use super::*; diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap index 0d594dbc..2f3852b5 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__add_property.snap @@ -13,5 +13,6 @@ metadata: relevant_paths: [] context: emit_legacy_scripts: true + specified_id: ~ children: [] diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap index b6fcbbd0..31bdfecc 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_after_patch.snap @@ -11,5 +11,6 @@ metadata: relevant_paths: [] context: emit_legacy_scripts: true + specified_id: ~ children: [] diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap index 84b3c3d1..cafc3f5e 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__remove_property_initial.snap @@ -13,5 +13,6 @@ metadata: relevant_paths: [] context: emit_legacy_scripts: true + specified_id: ~ children: [] diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap index 325c86f3..359ee86e 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__apply__set_name_and_class_name.snap @@ -11,5 +11,6 @@ metadata: relevant_paths: [] context: emit_legacy_scripts: true + specified_id: ~ children: [] diff --git a/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap b/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap index 94ddf12f..9147ca9b 100644 --- a/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap +++ b/src/snapshot/tests/snapshots/librojo__snapshot__tests__compute__add_child.snap @@ -12,6 +12,7 @@ added_instances: relevant_paths: [] context: emit_legacy_scripts: true + specified_id: ~ name: New class_name: Folder properties: {} diff --git a/src/snapshot/tree.rs b/src/snapshot/tree.rs index e4379bc2..8c30d5ef 100644 --- a/src/snapshot/tree.rs +++ b/src/snapshot/tree.rs @@ -8,7 +8,7 @@ use rbx_dom_weak::{ Instance, InstanceBuilder, WeakDom, }; -use crate::multimap::MultiMap; +use crate::{multimap::MultiMap, RojoRef}; use super::{InstanceMetadata, InstanceSnapshot}; @@ -33,6 +33,12 @@ pub struct RojoTree { /// appearing multiple times in the same Rojo project. This is sometimes /// called "path aliasing" in various Rojo documentation. path_to_ids: MultiMap, + + /// A map of specified RojoRefs to underlying Refs they represent. + /// This field is a MultiMap to allow for the possibility of the user specifying + /// the same RojoRef for multiple different instances. An entry containing + /// multiple elements is an error condition that should be raised to the user. + specified_id_to_refs: MultiMap, } impl RojoTree { @@ -45,6 +51,7 @@ impl RojoTree { inner: WeakDom::new(root_builder), metadata_map: HashMap::new(), path_to_ids: MultiMap::new(), + specified_id_to_refs: MultiMap::new(), }; let root_ref = tree.inner.root_ref(); @@ -137,6 +144,20 @@ impl RojoTree { self.path_to_ids.insert(new_path.clone(), id); } } + if existing_metadata.specified_id != metadata.specified_id { + // We need to uphold the invariant that each ID can only map + // to one referent. + if let Some(new) = &metadata.specified_id { + if self.specified_id_to_refs.get(new).len() > 0 { + log::error!("Duplicate user-specified referent '{new}'"); + } + + self.specified_id_to_refs.insert(new.clone(), id); + } + if let Some(old) = &existing_metadata.specified_id { + self.specified_id_to_refs.remove(old, id); + } + } entry.insert(metadata); } @@ -161,11 +182,37 @@ impl RojoTree { self.metadata_map.get(&id) } + /// Get the backing Ref of the given RojoRef. If the RojoRef maps to exactly + /// one Ref, this method returns Some. Otherwise, it returns None. + pub fn get_specified_id(&self, specified: &RojoRef) -> Option { + match self.specified_id_to_refs.get(specified)[..] { + [referent] => Some(referent), + _ => None, + } + } + + pub fn set_specified_id(&mut self, id: Ref, specified: RojoRef) { + if let Some(metadata) = self.metadata_map.get_mut(&id) { + if let Some(old) = metadata.specified_id.replace(specified.clone()) { + self.specified_id_to_refs.remove(&old, id); + } + } + self.specified_id_to_refs.insert(specified, id); + } + fn insert_metadata(&mut self, id: Ref, metadata: InstanceMetadata) { for path in &metadata.relevant_paths { self.path_to_ids.insert(path.clone(), id); } + if let Some(specified_id) = &metadata.specified_id { + if self.specified_id_to_refs.get(specified_id).len() > 0 { + log::error!("Duplicate user-specified referent '{specified_id}'"); + } + + self.set_specified_id(id, specified_id.clone()); + } + self.metadata_map.insert(id, metadata); } @@ -174,6 +221,10 @@ impl RojoTree { fn remove_metadata(&mut self, id: Ref) { let metadata = self.metadata_map.remove(&id).unwrap(); + if let Some(specified) = metadata.specified_id { + self.specified_id_to_refs.remove(&specified, id); + } + for path in &metadata.relevant_paths { self.path_to_ids.remove(path, id); } @@ -297,3 +348,30 @@ impl InstanceWithMetaMut<'_> { self.metadata } } + +#[cfg(test)] +mod test { + use crate::{ + snapshot::{InstanceMetadata, InstanceSnapshot}, + RojoRef, + }; + + use super::RojoTree; + + #[test] + fn swap_duped_specified_ids() { + let custom_ref = RojoRef::new("MyCoolRef".into()); + let snapshot = InstanceSnapshot::new() + .metadata(InstanceMetadata::new().specified_id(Some(custom_ref.clone()))); + let mut tree = RojoTree::new(InstanceSnapshot::new()); + + let original = tree.insert_instance(tree.get_root_id(), snapshot.clone()); + assert_eq!(tree.get_specified_id(&custom_ref.clone()), Some(original)); + + let duped = tree.insert_instance(tree.get_root_id(), snapshot.clone()); + assert_eq!(tree.get_specified_id(&custom_ref.clone()), None); + + tree.remove(original); + assert_eq!(tree.get_specified_id(&custom_ref.clone()), Some(duped)); + } +} diff --git a/src/snapshot_middleware/json_model.rs b/src/snapshot_middleware/json_model.rs index 93d566a2..1341db47 100644 --- a/src/snapshot_middleware/json_model.rs +++ b/src/snapshot_middleware/json_model.rs @@ -8,6 +8,7 @@ use serde::Deserialize; use crate::{ resolution::UnresolvedValue, snapshot::{InstanceContext, InstanceSnapshot}, + RojoRef, }; pub fn snapshot_json_model( @@ -41,6 +42,8 @@ pub fn snapshot_json_model( instance.name = Some(name.to_owned()); + let id = instance.id.take().map(RojoRef::new); + let mut snapshot = instance .into_snapshot() .with_context(|| format!("Could not load JSON model: {}", path.display()))?; @@ -49,7 +52,8 @@ pub fn snapshot_json_model( .metadata .instigating_source(path) .relevant_paths(vec![path.to_path_buf()]) - .context(context); + .context(context) + .specified_id(id); Ok(Some(snapshot)) } @@ -63,6 +67,9 @@ struct JsonModel { #[serde(alias = "ClassName")] class_name: String, + #[serde(skip_serializing_if = "Option::is_none")] + id: Option, + #[serde( alias = "Children", default = "Vec::new", diff --git a/src/snapshot_middleware/meta_file.rs b/src/snapshot_middleware/meta_file.rs index 72930e49..e1cd62b7 100644 --- a/src/snapshot_middleware/meta_file.rs +++ b/src/snapshot_middleware/meta_file.rs @@ -4,7 +4,7 @@ use anyhow::{format_err, Context}; use rbx_dom_weak::types::Attributes; use serde::{Deserialize, Serialize}; -use crate::{resolution::UnresolvedValue, snapshot::InstanceSnapshot}; +use crate::{resolution::UnresolvedValue, snapshot::InstanceSnapshot, RojoRef}; /// Represents metadata in a sibling file with the same basename. /// @@ -13,6 +13,9 @@ use crate::{resolution::UnresolvedValue, snapshot::InstanceSnapshot}; #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct AdjacentMetadata { + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub ignore_unknown_instances: Option, @@ -72,9 +75,21 @@ impl AdjacentMetadata { Ok(()) } + fn apply_id(&mut self, snapshot: &mut InstanceSnapshot) -> anyhow::Result<()> { + if self.id.is_some() && snapshot.metadata.specified_id.is_some() { + anyhow::bail!( + "cannot specify an ID using {} (instance has an ID from somewhere else)", + self.path.display() + ); + } + snapshot.metadata.specified_id = self.id.take().map(RojoRef::new); + Ok(()) + } + pub fn apply_all(&mut self, snapshot: &mut InstanceSnapshot) -> anyhow::Result<()> { self.apply_ignore_unknown_instances(snapshot); self.apply_properties(snapshot)?; + self.apply_id(snapshot)?; Ok(()) } @@ -89,6 +104,9 @@ impl AdjacentMetadata { #[derive(Debug, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct DirectoryMetadata { + #[serde(skip_serializing_if = "Option::is_none")] + pub id: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub ignore_unknown_instances: Option, @@ -122,6 +140,7 @@ impl DirectoryMetadata { self.apply_ignore_unknown_instances(snapshot); self.apply_class_name(snapshot)?; self.apply_properties(snapshot)?; + self.apply_id(snapshot)?; Ok(()) } @@ -174,4 +193,15 @@ impl DirectoryMetadata { Ok(()) } + + fn apply_id(&mut self, snapshot: &mut InstanceSnapshot) -> anyhow::Result<()> { + if self.id.is_some() && snapshot.metadata.specified_id.is_some() { + anyhow::bail!( + "cannot specify an ID using {} (instance has an ID from somewhere else)", + self.path.display() + ); + } + snapshot.metadata.specified_id = self.id.take().map(RojoRef::new); + Ok(()) + } } diff --git a/src/snapshot_middleware/project.rs b/src/snapshot_middleware/project.rs index 31ca7dc2..53e65251 100644 --- a/src/snapshot_middleware/project.rs +++ b/src/snapshot_middleware/project.rs @@ -11,6 +11,7 @@ use crate::{ InstanceContext, InstanceMetadata, InstanceSnapshot, InstigatingSource, PathIgnoreRule, SyncRule, }, + RojoRef, }; use super::{emit_legacy_scripts_default, snapshot_from_vfs}; @@ -279,6 +280,10 @@ pub fn snapshot_project_node( metadata.ignore_unknown_instances = true; } + if let Some(id) = &node.id { + metadata.specified_id = Some(RojoRef::new(id.clone())) + } + metadata.instigating_source = Some(InstigatingSource::ProjectNode( project_path.to_path_buf(), instance_name.to_string(), diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap index 50ce53c1..9b92ec7d 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: LocalizationTable properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap index c91924f8..7c2d9f6c 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: LocalizationTable properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap index 4c0dcbbf..ab27bc67 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap @@ -19,6 +19,7 @@ metadata: - /foo/init.csv context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap index 6238fe68..4a24bdb1 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap @@ -19,6 +19,7 @@ metadata: - /foo/init.csv context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: Folder properties: {} @@ -40,6 +41,7 @@ children: - /foo/Child/init.csv context: emit_legacy_scripts: true + specified_id: ~ name: Child class_name: Folder properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap index 9cc320eb..b41503ad 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json__test__instance_from_vfs.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap index e3ee581e..c6c30705 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs.snap @@ -11,6 +11,7 @@ metadata: - /foo.model.json context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: IntValue properties: @@ -23,6 +24,7 @@ children: relevant_paths: [] context: emit_legacy_scripts: true + specified_id: ~ name: The Child class_name: StringValue properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap index e3ee581e..c6c30705 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__json_model__test__model_from_vfs_legacy.snap @@ -11,6 +11,7 @@ metadata: - /foo.model.json context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: IntValue properties: @@ -23,6 +24,7 @@ children: relevant_paths: [] context: emit_legacy_scripts: true + specified_id: ~ name: The Child class_name: StringValue properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_client_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_client_from_vfs.snap index 5f5f6e9a..92321572 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_client_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_client_from_vfs.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: LocalScript properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_from_vfs.snap index de2471b9..53c7ee33 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_from_vfs.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_with_meta.snap index 32d70c70..1b7fde09 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_module_with_meta.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_disabled.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_disabled.snap index 2c5546a5..d0038e4d 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_disabled.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_disabled.snap @@ -12,6 +12,7 @@ metadata: - /bar.meta.json context: emit_legacy_scripts: true + specified_id: ~ name: bar class_name: Script properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_with_meta.snap index e4e31ff9..a5f53240 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_script_with_meta.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: Script properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_server_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_server_from_vfs.snap index b70b9cc2..4ad99cf1 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_server_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__class_server_from_vfs.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: Script properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_client_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_client_from_vfs.snap index 6ad72d08..e9704b1c 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_client_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_client_from_vfs.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: false + specified_id: ~ name: foo class_name: Script properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_from_vfs.snap index 83be811b..6f5909c4 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_from_vfs.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: false + specified_id: ~ name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_with_meta.snap index 98a88ec7..ff8c51ec 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_module_with_meta.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: false + specified_id: ~ name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_disabled.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_disabled.snap index c47b83dc..c7404363 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_disabled.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_disabled.snap @@ -12,6 +12,7 @@ metadata: - /bar.meta.json context: emit_legacy_scripts: false + specified_id: ~ name: bar class_name: Script properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_with_meta.snap index 72d24206..512c3991 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_script_with_meta.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: false + specified_id: ~ name: foo class_name: Script properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_server_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_server_from_vfs.snap index 2b902f96..4295f6ba 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_server_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__runcontext_server_from_vfs.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: false + specified_id: ~ name: foo class_name: Script properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__no_name_project.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__no_name_project.snap index 289c292c..971027f6 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__no_name_project.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__no_name_project.snap @@ -1,6 +1,6 @@ --- source: src/snapshot_middleware/project.rs -assertion_line: 725 +assertion_line: 730 expression: instance_snapshot --- snapshot_id: "00000000000000000000000000000000" @@ -12,8 +12,8 @@ metadata: - /foo/default.project.json context: emit_legacy_scripts: true + specified_id: ~ name: no_name_project class_name: Model properties: {} children: [] - diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap index bd5db23d..7906dbbf 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_from_direct_file.snap @@ -11,6 +11,7 @@ metadata: - /foo/hello.project.json context: emit_legacy_scripts: true + specified_id: ~ name: direct-project class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap index 77cb44c9..51da0621 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_path_property_overrides.snap @@ -12,6 +12,7 @@ metadata: - /foo/default.project.json context: emit_legacy_scripts: true + specified_id: ~ name: path-property-override class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap index 914a2f95..0c9f90ab 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_children.snap @@ -11,6 +11,7 @@ metadata: - /foo.project.json context: emit_legacy_scripts: true + specified_id: ~ name: children class_name: Folder properties: {} @@ -27,6 +28,7 @@ children: relevant_paths: [] context: emit_legacy_scripts: true + specified_id: ~ name: Child class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap index 02e6ee0b..d8d59d90 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project.snap @@ -12,6 +12,7 @@ metadata: - /foo/default.project.json context: emit_legacy_scripts: true + specified_id: ~ name: path-project class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap index baf64365..30b01ebb 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_project_with_children.snap @@ -12,6 +12,7 @@ metadata: - /foo/default.project.json context: emit_legacy_scripts: true + specified_id: ~ name: path-child-project class_name: Folder properties: {} @@ -28,6 +29,7 @@ children: relevant_paths: [] context: emit_legacy_scripts: true + specified_id: ~ name: SomeChild class_name: Model properties: {} diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap index 223c366c..e723e6d2 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_path_to_txt.snap @@ -13,6 +13,7 @@ metadata: - /foo/default.project.json context: emit_legacy_scripts: true + specified_id: ~ name: path-project class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap index eddb4e04..99c6b3b5 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_resolved_properties.snap @@ -11,6 +11,7 @@ metadata: - /foo.project.json context: emit_legacy_scripts: true + specified_id: ~ name: resolved-properties class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap index 8bd6e28b..f42e2246 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__project__test__project_with_unresolved_properties.snap @@ -11,6 +11,7 @@ metadata: - /foo.project.json context: emit_legacy_scripts: true + specified_id: ~ name: unresolved-properties class_name: StringValue properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap index 329bdbcd..71a14153 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__toml__test__instance_from_vfs.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: ModuleScript properties: diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap index aa3e0f06..54253eb1 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__txt__test__instance_from_vfs.snap @@ -12,6 +12,7 @@ metadata: - /foo.meta.json context: emit_legacy_scripts: true + specified_id: ~ name: foo class_name: StringValue properties: diff --git a/src/web/ui.rs b/src/web/ui.rs index 0199d58d..67546821 100644 --- a/src/web/ui.rs +++ b/src/web/ui.rs @@ -163,6 +163,7 @@ impl UiService { let content = html! { <> +
    "specified_id: " { format!("{:?}", metadata.specified_id) }
    "ignore_unknown_instances: " { metadata.ignore_unknown_instances.to_string() }
    "instigating source: " { format!("{:?}", metadata.instigating_source) }
    { relevant_paths } @@ -192,7 +193,7 @@ impl UiService { html! {
    -
    }); - Response::builder() - .header(header::CONTENT_TYPE, "text/html") - .body(Body::from(format!("{}", page))) - .unwrap() + response( + StatusCode::OK, + "text/html", + format!("{}", page), + ) } fn handle_show_instances(&self) -> Response { @@ -80,10 +75,11 @@ impl UiService { { Self::instance(&tree, root_id) } }); - Response::builder() - .header(header::CONTENT_TYPE, "text/html") - .body(Body::from(format!("{}", page))) - .unwrap() + response( + StatusCode::OK, + "text/html", + format!("{}", page), + ) } fn instance(tree: &RojoTree, id: Ref) -> HtmlContent<'_> { diff --git a/src/web/util.rs b/src/web/util.rs index 1c1cbb50..bd1f6b81 100644 --- a/src/web/util.rs +++ b/src/web/util.rs @@ -1,6 +1,27 @@ use hyper::{header::CONTENT_TYPE, Body, Response, StatusCode}; use serde::{Deserialize, Serialize}; +/// Builds an HTTP response, falling back to an empty `500` response (rather than +/// panicking) if the response could not be constructed. With constant headers +/// and a valid status code this never actually fails, but routing every +/// response through here means a malformed response can never crash the server. +pub fn response( + code: StatusCode, + content_type: &'static str, + body: impl Into, +) -> Response { + Response::builder() + .status(code) + .header(CONTENT_TYPE, content_type) + .body(body.into()) + .unwrap_or_else(|err| { + log::error!("Failed to build HTTP response: {}", err); + let mut fallback = Response::new(Body::empty()); + *fallback.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; + fallback + }) +} + pub fn msgpack_ok(value: T) -> Response { msgpack(value, StatusCode::OK) } @@ -12,18 +33,14 @@ pub fn msgpack(value: T, code: StatusCode) -> Response { .with_struct_map(); if let Err(err) = value.serialize(&mut serializer) { - return Response::builder() - .status(StatusCode::INTERNAL_SERVER_ERROR) - .header(CONTENT_TYPE, "text/plain") - .body(Body::from(err.to_string())) - .unwrap(); + return response( + StatusCode::INTERNAL_SERVER_ERROR, + "text/plain", + err.to_string(), + ); }; - Response::builder() - .status(code) - .header(CONTENT_TYPE, "application/msgpack") - .body(Body::from(serialized)) - .unwrap() + response(code, "application/msgpack", serialized) } pub fn serialize_msgpack(value: T) -> anyhow::Result> { @@ -49,17 +66,13 @@ pub fn json(value: T, code: StatusCode) -> Response { let serialized = match serde_json::to_string(&value) { Ok(v) => v, Err(err) => { - return Response::builder() - .status(StatusCode::INTERNAL_SERVER_ERROR) - .header(CONTENT_TYPE, "text/plain") - .body(Body::from(err.to_string())) - .unwrap(); + return response( + StatusCode::INTERNAL_SERVER_ERROR, + "text/plain", + err.to_string(), + ); } }; - Response::builder() - .status(code) - .header(CONTENT_TYPE, "application/json") - .body(Body::from(serialized)) - .unwrap() + response(code, "application/json", serialized) } From 0afb26e1430ae9b24b2602e5491d68cc52730965 Mon Sep 17 00:00:00 2001 From: AK-Khan02 Date: Tue, 2 Jun 2026 12:11:41 -0400 Subject: [PATCH 1489/1504] Update stale README and contributor documentation (#1269) --- CONTRIBUTING.md | 41 ++++++++++++++++++++++++++++------------- README.md | 7 +++---- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0063e448..bf11ae72 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -13,12 +13,27 @@ Code contributions are welcome for features and bugs that have been reported in You'll want these tools to work on Rojo: -* Latest stable Rust compiler +* Rust 1.88 or newer * Rustfmt and Clippy are used for code formatting and linting. -* Latest stable [Rojo](https://github.com/rojo-rbx/rojo) * [Rokit](https://github.com/rojo-rbx/rokit) * [Luau Language Server](https://github.com/JohnnyMorganz/luau-lsp) (Only needed if working on the Studio plugin.) +Rokit installs the pinned Rojo, Selene, StyLua, Lune, and run-in-roblox versions listed in [`rokit.toml`](rokit.toml): + +```bash +rokit install +``` + +Before opening a pull request, run the relevant checks: + +```bash +cargo test +cargo fmt -- --check +cargo clippy +stylua --check plugin/src +selene plugin/src +``` + When working on the Studio plugin, we recommend using this command to automatically rebuild the plugin when you save a change: *(Make sure you've enabled the Studio setting to reload plugins on file change!)* @@ -29,7 +44,7 @@ bash scripts/watch-build-plugin.sh You can also run the plugin's unit tests with the following: -*(Make sure you have `run-in-roblox` installed first!)* +*(If you are not using Rokit, make sure you have `run-in-roblox` installed first!)* ```bash bash scripts/unit-test-plugin.sh @@ -49,27 +64,27 @@ Please file issues and we'll try to help figure out what the best way forward is ## Local Development Gotchas -If your build fails with "Error: failed to open file `D:\code\rojo\plugin\modules\roact\src`" you need to update your Git submodules. +If your build fails with an error about a missing path under `plugin/Packages`, such as `plugin/Packages/Roact`, you need to update your Git submodules. Run the command and try building again: `git submodule update --init --recursive`. ## Pushing a Rojo Release -The Rojo release process is pretty manual right now. If you need to do it, here's how: +The Rojo release process is driven by the GitHub Actions release workflow. If you need to do it, here's how: 1. Bump server version in [`Cargo.toml`](Cargo.toml) -2. Bump plugin version in [`plugin/src/Config.lua`](plugin/src/Config.lua) -3. Run `cargo test` to update `Cargo.lock` and run tests +2. Bump plugin version in [`plugin/Version.txt`](plugin/Version.txt) + * The build checks that the Cargo and plugin versions match. +3. Run `cargo test` to update `Cargo.lock` after the version bump and run tests 4. Update [`CHANGELOG.md`](CHANGELOG.md) 5. Commit! * `git add . && git commit -m "Release vX.Y.Z"` 6. Tag the commit * `git tag vX.Y.Z` -7. Publish the CLI - * `cargo publish` -8. Publish the Plugin - * `cargo run -- upload plugin --asset_id 6415005344` -9. Push commits and tags +7. Push commits and tags * `git push && git push --tags` +8. Wait for the GitHub Actions release workflow to create the draft release and upload CLI/plugin artifacts +9. Publish the CLI crate + * `cargo publish` 10. Copy GitHub release content from previous release * Update the leading text with a summary about the release * Paste the changelog notes (as-is!) from [`CHANGELOG.md`](CHANGELOG.md) - * Write a small summary of each major feature \ No newline at end of file + * Write a small summary of each major feature diff --git a/README.md b/README.md index c150ecb7..f3d1aeeb 100644 --- a/README.md +++ b/README.md @@ -25,12 +25,11 @@ Rojo enables: * Versioning your game, library, or plugin using Git or another VCS * Streaming `rbxmx` and `rbxm` models into your game in real time * Packaging and deploying your project to Roblox.com from the command line +* Pulling Instances from Roblox place and model files back into an existing Rojo project with `rojo syncback` -In the future, Rojo will be able to: +Rojo also has an optional two-way sync setting in the Studio plugin for syncing supported Studio edits back to the filesystem. -* Sync instances from Roblox Studio to the filesystem -* Automatically convert your existing game to work with Rojo -* Import custom instances like MoonScript code +Some workflows, like fully automatic conversion of every existing game into a Rojo project, are still limited and may require manual project configuration. ## [Documentation](https://rojo.space/docs) Documentation is hosted in the [rojo.space repository](https://github.com/rojo-rbx/rojo.space). From 15939b1647e12f317dd3e11bba716d17b4544511 Mon Sep 17 00:00:00 2001 From: EgoMoose Date: Tue, 2 Jun 2026 23:40:12 -0400 Subject: [PATCH 1490/1504] Add ignorable glob support (#1256) --- CHANGELOG.md | 2 + src/glob.rs | 58 +++++++++++++++++++++++ src/project.rs | 56 +++++++++++++++++++++- src/snapshot/metadata.rs | 29 ++++++++++-- src/snapshot_middleware/dir.rs | 12 ++--- src/syncback/mod.rs | 85 +++++++++++++++++++++++++++++++--- 6 files changed, 222 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b126607..e9e92892 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ Making a new release? Simply add the new header with the version and date undern * Fixed a bug where the notification timeout thread would fail to cancel on unmount ([#1211]) * Added a "Forget" option to the sync reminder notification to avoid being reminded for that place in the future ([#1215]) * Improves relative path calculation for sourcemap generation to avoid issues with Windows UNC paths. ([#1217]) +* Add support for gitignore-style negation in `globIgnorePaths` and syncback's `ignorePaths` ([#1256]) * Fixed the sync fallback scrambling sibling order; replacements are now re-parented ancestors-first and in their original child order. ([#1265]) * Instances that share a name and class are now robustly matched on resync by comparing their properties, instead of relying on child order alone. ([#1266]) * Rojo now reports a clear error instead of panicking in several cases, including when the `serve` port is already in use, when a synced file is read-only or locked, when the filesystem watcher can't be created, and when the working directory is inaccessible. ([#1267]) @@ -51,6 +52,7 @@ Making a new release? Simply add the new header with the version and date undern [#1211]: https://github.com/rojo-rbx/rojo/pull/1211 [#1215]: https://github.com/rojo-rbx/rojo/pull/1215 [#1217]: https://github.com/rojo-rbx/rojo/pull/1217 +[#1256]: https://github.com/rojo-rbx/rojo/pull/1256 [#1265]: https://github.com/rojo-rbx/rojo/pull/1265 [#1266]: https://github.com/rojo-rbx/rojo/pull/1266 [#1267]: https://github.com/rojo-rbx/rojo/pull/1267 diff --git a/src/glob.rs b/src/glob.rs index 96437c38..c0146863 100644 --- a/src/glob.rs +++ b/src/glob.rs @@ -48,3 +48,61 @@ impl<'de> Deserialize<'de> for Glob { Glob::new(&glob).map_err(D::Error::custom) } } + +/// A glob with optional gitignore-style negation. A leading `!` marks the +/// pattern as a negation (re-includes paths that an earlier rule excluded). +/// To match a literal `!` at the start of a pattern, escape it with `\!`. +#[derive(Debug, Clone)] +pub struct IgnorableGlob { + glob: Glob, + negated: bool, + raw: String, +} + +impl IgnorableGlob { + pub fn new(pattern: &str) -> Result { + let (negated, body) = if let Some(rest) = pattern.strip_prefix('!') { + (true, rest) + } else if pattern.starts_with(r"\!") { + (false, &pattern[1..]) + } else { + (false, pattern) + }; + + Ok(IgnorableGlob { + glob: Glob::new(body)?, + negated, + raw: pattern.to_owned(), + }) + } + + pub fn is_match>(&self, path: P) -> bool { + self.glob.is_match(path) + } + + pub fn is_negation(&self) -> bool { + self.negated + } +} + +impl PartialEq for IgnorableGlob { + fn eq(&self, other: &Self) -> bool { + self.negated == other.negated && self.glob == other.glob + } +} + +impl Eq for IgnorableGlob {} + +impl Serialize for IgnorableGlob { + fn serialize(&self, serializer: S) -> Result { + serializer.serialize_str(&self.raw) + } +} + +impl<'de> Deserialize<'de> for IgnorableGlob { + fn deserialize>(deserializer: D) -> Result { + let pattern = String::deserialize(deserializer)?; + + IgnorableGlob::new(&pattern).map_err(D::Error::custom) + } +} diff --git a/src/project.rs b/src/project.rs index 5cc8278e..bfcc7f0e 100644 --- a/src/project.rs +++ b/src/project.rs @@ -12,7 +12,8 @@ use serde::{Deserialize, Serialize}; use thiserror::Error; use crate::{ - glob::Glob, json, resolution::UnresolvedValue, snapshot::SyncRule, syncback::SyncbackRules, + glob::IgnorableGlob, json, resolution::UnresolvedValue, snapshot::SyncRule, + syncback::SyncbackRules, }; /// Represents 'default' project names that act as `init` files @@ -114,7 +115,7 @@ pub struct Project { /// A list of globs, relative to the folder the project file is in, that /// match files that should be excluded if Rojo encounters them. #[serde(default, skip_serializing_if = "Vec::is_empty")] - pub glob_ignore_paths: Vec, + pub glob_ignore_paths: Vec, /// A list of rules for syncback with this project file. #[serde(skip_serializing_if = "Option::is_none")] @@ -593,4 +594,55 @@ mod test { assert!(project.sync_rules[0].include.is_match("data.data.json")); assert!(project.sync_rules[1].include.is_match("init.module.lua")); } + + #[test] + fn glob_ignore_paths_negation() { + let project_json = r#"{ + "name": "TestProject", + "tree": { "$path": "src" }, + "globIgnorePaths": [ + "**/*.spec.lua", + "!keep.spec.lua", + "\\!literal.lua" + ] + }"#; + + let project = Project::load_from_slice( + project_json.as_bytes(), + PathBuf::from("/test/default.project.json"), + None, + ) + .expect("project should parse"); + + let paths = &project.glob_ignore_paths; + assert_eq!(paths.len(), 3); + + assert!(!paths[0].is_negation()); + assert!(paths[0].is_match("foo.spec.lua")); + + assert!(paths[1].is_negation()); + assert!(paths[1].is_match("keep.spec.lua")); + + // `\!literal.lua` should match a file literally named `!literal.lua`, + // not be parsed as a negation. + assert!(!paths[2].is_negation()); + assert!(paths[2].is_match("!literal.lua")); + + let rules: Vec<_> = paths + .iter() + .map(|g| crate::snapshot::PathIgnoreRule { + base_path: PathBuf::from("/test"), + glob: g.clone(), + }) + .collect(); + assert!(crate::snapshot::is_path_ignored( + &rules, + "/test/foo.spec.lua" + )); + assert!(!crate::snapshot::is_path_ignored( + &rules, + "/test/keep.spec.lua" + )); + assert!(!crate::snapshot::is_path_ignored(&rules, "/test/plain.lua")); + } } diff --git a/src/snapshot/metadata.rs b/src/snapshot/metadata.rs index 79f7a2d0..a1bf0afe 100644 --- a/src/snapshot/metadata.rs +++ b/src/snapshot/metadata.rs @@ -8,7 +8,7 @@ use anyhow::Context; use serde::{Deserialize, Serialize}; use crate::{ - glob::Glob, + glob::{Glob, IgnorableGlob}, path_serializer, project::ProjectNode, snapshot_middleware::{emit_legacy_scripts_default, Middleware}, @@ -222,18 +222,37 @@ pub struct PathIgnoreRule { pub base_path: PathBuf, /// The actual glob that can be matched against the input path. - pub glob: Glob, + pub glob: IgnorableGlob, } impl PathIgnoreRule { - pub fn passes>(&self, path: P) -> bool { + pub fn matches>(&self, path: P) -> bool { let path = path.as_ref(); match path.strip_prefix(&self.base_path) { - Ok(suffix) => !self.glob.is_match(suffix), - Err(_) => true, + Ok(suffix) => self.glob.is_match(suffix), + Err(_) => false, } } + + pub fn is_negation(&self) -> bool { + self.glob.is_negation() + } +} + +/// Evaluates an ordered list of [`PathIgnoreRule`]s against a path using +/// gitignore-style "last match wins" semantics: a path is ignored if the last +/// rule whose pattern matches it is non-negated. Paths matched by no rule are +/// not ignored. +pub fn is_path_ignored>(rules: &[PathIgnoreRule], path: P) -> bool { + let path = path.as_ref(); + let mut ignored = false; + for rule in rules { + if rule.matches(path) { + ignored = !rule.is_negation(); + } + } + ignored } /// Represents where a particular Instance or InstanceSnapshot came from. diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index fb444c37..fac1d0ff 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -7,7 +7,9 @@ use anyhow::Context; use memofs::{DirEntry, Vfs}; use crate::{ - snapshot::{InstanceContext, InstanceMetadata, InstanceSnapshot, InstigatingSource}, + snapshot::{ + is_path_ignored, InstanceContext, InstanceMetadata, InstanceSnapshot, InstigatingSource, + }, syncback::{hash_instance, FsSnapshot, SyncbackReturn, SyncbackSnapshot}, }; @@ -41,12 +43,8 @@ pub fn snapshot_dir_no_meta( path: &Path, name: &str, ) -> anyhow::Result> { - let passes_filter_rules = |child: &DirEntry| { - context - .path_ignore_rules - .iter() - .all(|rule| rule.passes(child.path())) - }; + let passes_filter_rules = + |child: &DirEntry| !is_path_ignored(&context.path_ignore_rules, child.path()); let mut snapshot_children = Vec::new(); diff --git a/src/syncback/mod.rs b/src/syncback/mod.rs index 5dc3028f..e1666abc 100644 --- a/src/syncback/mod.rs +++ b/src/syncback/mod.rs @@ -21,7 +21,7 @@ use std::{ }; use crate::{ - glob::Glob, + glob::{Glob, IgnorableGlob}, snapshot::{InstanceWithMeta, RojoTree}, snapshot_middleware::Middleware, syncback::ref_properties::{collect_referents, link_referents}, @@ -414,18 +414,18 @@ pub struct SyncbackRules { } impl SyncbackRules { - pub fn compile_globs(&self) -> anyhow::Result> { + pub fn compile_globs(&self) -> anyhow::Result> { let mut globs = Vec::with_capacity(self.ignore_paths.len()); let dir_ignore_paths = self.create_ignore_dir_paths.unwrap_or(true); for pattern in &self.ignore_paths { - let glob = Glob::new(pattern) + let glob = IgnorableGlob::new(pattern) .with_context(|| format!("the pattern '{pattern}' is not a valid glob"))?; globs.push(glob); if dir_ignore_paths { if let Some(dir_pattern) = pattern.strip_suffix("/**") { - if let Ok(glob) = Glob::new(dir_pattern) { + if let Ok(glob) = IgnorableGlob::new(dir_pattern) { globs.push(glob) } } @@ -436,7 +436,7 @@ impl SyncbackRules { } } -fn is_valid_path(globs: &Option>, base_path: &Path, path: &Path) -> bool { +fn is_valid_path(globs: &Option>, base_path: &Path, path: &Path) -> bool { let git_glob = GIT_IGNORE_GLOB.get_or_init(|| Glob::new(".git/**").unwrap()); let test_path = match path.strip_prefix(base_path) { Ok(suffix) => suffix, @@ -446,11 +446,16 @@ fn is_valid_path(globs: &Option>, base_path: &Path, path: &Path) -> bo return false; } if let Some(ref ignore_paths) = globs { + // Gitignore-style "last match wins" + let mut ignored = false; for glob in ignore_paths { if glob.is_match(test_path) { - return false; + ignored = !glob.is_negation(); } } + if ignored { + return false; + } } true } @@ -538,3 +543,71 @@ fn strip_unknown_root_children(new: &mut WeakDom, old: &RojoTree) { new.destroy(child_ref); } } + +#[cfg(test)] +mod test { + use super::*; + + fn rules(ignore_paths: &[&str], create_ignore_dir_paths: Option) -> SyncbackRules { + SyncbackRules { + ignore_trees: Vec::new(), + ignore_paths: ignore_paths.iter().map(|s| s.to_string()).collect(), + ignore_properties: IndexMap::new(), + sync_current_camera: None, + sync_unscriptable: None, + ignore_referents: None, + create_ignore_dir_paths, + } + } + + #[test] + fn ignore_paths_negation() { + let globs = Some( + rules(&["**/*.lua", "!keep.lua"], Some(false)) + .compile_globs() + .unwrap(), + ); + let base = Path::new("/test"); + + // A later negation re-includes a path matched by an earlier pattern. + assert!(!is_valid_path(&globs, base, Path::new("/test/foo.lua"))); + assert!(is_valid_path(&globs, base, Path::new("/test/keep.lua"))); + // Paths matched by no rule are valid. + assert!(is_valid_path(&globs, base, Path::new("/test/plain.txt"))); + } + + #[test] + fn ignore_paths_negation_with_dir_expansion() { + // With `create_ignore_dir_paths`, a negated `foo/**` pattern should also + // re-include the `foo` directory itself, mirroring the file rule. + let globs = Some( + rules(&["**/*", "!keep/**"], Some(true)) + .compile_globs() + .unwrap(), + ); + let base = Path::new("/test"); + + assert!(!is_valid_path(&globs, base, Path::new("/test/drop/a.lua"))); + assert!(is_valid_path(&globs, base, Path::new("/test/keep"))); + assert!(is_valid_path(&globs, base, Path::new("/test/keep/a.lua"))); + } + + #[test] + fn ignore_paths_escaped_bang_is_literal() { + // `\!literal.lua` should ignore a file literally named `!literal.lua` + // rather than being parsed as a negation. + let globs = Some( + rules(&[r"\!literal.lua"], Some(false)) + .compile_globs() + .unwrap(), + ); + let base = Path::new("/test"); + + assert!(!globs.as_ref().unwrap()[0].is_negation()); + assert!(!is_valid_path( + &globs, + base, + Path::new("/test/!literal.lua") + )); + } +} From 444dc11b2605961768856a0dda0bed11bd68288b Mon Sep 17 00:00:00 2001 From: Ken Loeffler Date: Sun, 7 Jun 2026 15:50:04 -0700 Subject: [PATCH 1491/1504] Fix init.plugin.lua/init.plugin.luau not being supported (#1252) --- CHANGELOG.md | 2 ++ ...end_to_end__tests__build__plugin_init.snap | 27 +++++++++++++++++++ .../plugin_init/default.project.json | 6 +++++ .../plugin_init/folder/lua/init.plugin.lua | 1 + .../plugin_init/folder/luau/init.plugin.luau | 1 + src/snapshot_middleware/dir.rs | 2 ++ src/snapshot_middleware/lua.rs | 1 + src/snapshot_middleware/mod.rs | 13 ++++++++- ...pshot_middleware__csv__test__csv_init.snap | 2 ++ ...leware__csv__test__csv_init_with_meta.snap | 2 ++ ...t_middleware__dir__test__empty_folder.snap | 2 ++ ...ddleware__dir__test__folder_in_folder.snap | 4 +++ ...ware__lua__test__init_module_from_vfs.snap | 2 ++ ..._test__init_module_from_vfs_with_meta.snap | 2 ++ src/syncback/file_names.rs | 2 ++ src/syncback/mod.rs | 1 + tests/tests/build.rs | 1 + 17 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 rojo-test/build-test-snapshots/end_to_end__tests__build__plugin_init.snap create mode 100644 rojo-test/build-tests/plugin_init/default.project.json create mode 100644 rojo-test/build-tests/plugin_init/folder/lua/init.plugin.lua create mode 100644 rojo-test/build-tests/plugin_init/folder/luau/init.plugin.luau diff --git a/CHANGELOG.md b/CHANGELOG.md index e9e92892..8ceff750 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ Making a new release? Simply add the new header with the version and date undern * Fixed a bug where the notification timeout thread would fail to cancel on unmount ([#1211]) * Added a "Forget" option to the sync reminder notification to avoid being reminded for that place in the future ([#1215]) * Improves relative path calculation for sourcemap generation to avoid issues with Windows UNC paths. ([#1217]) +* Fixed missing support for init.plugin.lua and init.plugin.luau. ([#1252]) * Add support for gitignore-style negation in `globIgnorePaths` and syncback's `ignorePaths` ([#1256]) * Fixed the sync fallback scrambling sibling order; replacements are now re-parented ancestors-first and in their original child order. ([#1265]) * Instances that share a name and class are now robustly matched on resync by comparing their properties, instead of relying on child order alone. ([#1266]) @@ -52,6 +53,7 @@ Making a new release? Simply add the new header with the version and date undern [#1211]: https://github.com/rojo-rbx/rojo/pull/1211 [#1215]: https://github.com/rojo-rbx/rojo/pull/1215 [#1217]: https://github.com/rojo-rbx/rojo/pull/1217 +[#1252]: https://github.com/rojo-rbx/rojo/pull/1252 [#1256]: https://github.com/rojo-rbx/rojo/pull/1256 [#1265]: https://github.com/rojo-rbx/rojo/pull/1265 [#1266]: https://github.com/rojo-rbx/rojo/pull/1266 diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__plugin_init.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__plugin_init.snap new file mode 100644 index 00000000..40def8cd --- /dev/null +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__plugin_init.snap @@ -0,0 +1,27 @@ +--- +source: tests/tests/build.rs +expression: contents +--- + + + + plugin_init + + + + lua + 3 + + + + + + luau + 3 + + + + + diff --git a/rojo-test/build-tests/plugin_init/default.project.json b/rojo-test/build-tests/plugin_init/default.project.json new file mode 100644 index 00000000..c683b506 --- /dev/null +++ b/rojo-test/build-tests/plugin_init/default.project.json @@ -0,0 +1,6 @@ +{ + "name": "plugin_init", + "tree": { + "$path": "folder" + } +} diff --git a/rojo-test/build-tests/plugin_init/folder/lua/init.plugin.lua b/rojo-test/build-tests/plugin_init/folder/lua/init.plugin.lua new file mode 100644 index 00000000..9761a96d --- /dev/null +++ b/rojo-test/build-tests/plugin_init/folder/lua/init.plugin.lua @@ -0,0 +1 @@ +return "From folder/lua/init.plugin.lua" diff --git a/rojo-test/build-tests/plugin_init/folder/luau/init.plugin.luau b/rojo-test/build-tests/plugin_init/folder/luau/init.plugin.luau new file mode 100644 index 00000000..f5de5239 --- /dev/null +++ b/rojo-test/build-tests/plugin_init/folder/luau/init.plugin.luau @@ -0,0 +1 @@ +return "From folder/luau/init.plugin.luau" diff --git a/src/snapshot_middleware/dir.rs b/src/snapshot_middleware/dir.rs index fac1d0ff..b9f62743 100644 --- a/src/snapshot_middleware/dir.rs +++ b/src/snapshot_middleware/dir.rs @@ -72,6 +72,8 @@ pub fn snapshot_dir_no_meta( normalized_path.join("init.server.luau"), normalized_path.join("init.client.lua"), normalized_path.join("init.client.luau"), + normalized_path.join("init.plugin.lua"), + normalized_path.join("init.plugin.luau"), normalized_path.join("init.csv"), ]; diff --git a/src/snapshot_middleware/lua.rs b/src/snapshot_middleware/lua.rs index a0058555..98f43e40 100644 --- a/src/snapshot_middleware/lua.rs +++ b/src/snapshot_middleware/lua.rs @@ -182,6 +182,7 @@ pub fn syncback_lua_init<'sync>( ScriptType::Server => "init.server.luau", ScriptType::Client => "init.client.luau", ScriptType::Module => "init.luau", + ScriptType::Plugin => "init.plugin.luau", _ => anyhow::bail!("syncback is not yet implemented for {script_type:?}"), }); diff --git a/src/snapshot_middleware/mod.rs b/src/snapshot_middleware/mod.rs index 9eec5f83..fadce5f6 100644 --- a/src/snapshot_middleware/mod.rs +++ b/src/snapshot_middleware/mod.rs @@ -91,7 +91,9 @@ pub fn snapshot_from_vfs( // TODO: Is this even necessary anymore? match file_name { "init.server.luau" | "init.server.lua" | "init.client.luau" | "init.client.lua" - | "init.luau" | "init.lua" | "init.csv" => return Ok(None), + | "init.plugin.luau" | "init.plugin.lua" | "init.luau" | "init.lua" | "init.csv" => { + return Ok(None) + } _ => {} } @@ -124,6 +126,8 @@ fn get_dir_middleware<'path>( (Middleware::ServerScriptDir, "init.server.lua"), (Middleware::ClientScriptDir, "init.client.luau"), (Middleware::ClientScriptDir, "init.client.lua"), + (Middleware::PluginScriptDir, "init.plugin.lua"), + (Middleware::PluginScriptDir, "init.plugin.luau"), (Middleware::CsvDir, "init.csv"), ] }); @@ -205,6 +209,8 @@ pub enum Middleware { #[serde(skip_deserializing)] ClientScriptDir, #[serde(skip_deserializing)] + PluginScriptDir, + #[serde(skip_deserializing)] ModuleScriptDir, #[serde(skip_deserializing)] CsvDir, @@ -255,6 +261,9 @@ impl Middleware { Self::ClientScriptDir => { snapshot_lua_init(context, vfs, path, name, ScriptType::Client) } + Self::PluginScriptDir => { + snapshot_lua_init(context, vfs, path, name, ScriptType::Plugin) + } Self::ModuleScriptDir => { snapshot_lua_init(context, vfs, path, name, ScriptType::Module) } @@ -297,6 +306,7 @@ impl Middleware { Middleware::Dir => syncback_dir(snapshot), Middleware::ServerScriptDir => syncback_lua_init(ScriptType::Server, snapshot), Middleware::ClientScriptDir => syncback_lua_init(ScriptType::Client, snapshot), + Middleware::PluginScriptDir => syncback_lua_init(ScriptType::Plugin, snapshot), Middleware::ModuleScriptDir => syncback_lua_init(ScriptType::Module, snapshot), Middleware::CsvDir => syncback_csv_init(snapshot), @@ -318,6 +328,7 @@ impl Middleware { Middleware::Dir | Middleware::ServerScriptDir | Middleware::ClientScriptDir + | Middleware::PluginScriptDir | Middleware::ModuleScriptDir | Middleware::CsvDir ) diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init.snap index a275a6cf..813a2933 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init.snap @@ -15,6 +15,8 @@ metadata: - /root/init.server.luau - /root/init.client.lua - /root/init.client.luau + - /root/init.plugin.lua + - /root/init.plugin.luau - /root/init.csv - /root/init.meta.json - /root/init.meta.jsonc diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init_with_meta.snap index 603bd2df..01ce0a0f 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init_with_meta.snap @@ -15,6 +15,8 @@ metadata: - /root/init.server.luau - /root/init.client.lua - /root/init.client.luau + - /root/init.plugin.lua + - /root/init.plugin.luau - /root/init.csv - /root/init.meta.json - /root/init.meta.jsonc diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap index 813a6767..865c3c27 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__empty_folder.snap @@ -15,6 +15,8 @@ metadata: - /foo/init.server.luau - /foo/init.client.lua - /foo/init.client.luau + - /foo/init.plugin.lua + - /foo/init.plugin.luau - /foo/init.csv - /foo/init.meta.json - /foo/init.meta.jsonc diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap index 2f44988d..00a4bdf0 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__dir__test__folder_in_folder.snap @@ -15,6 +15,8 @@ metadata: - /foo/init.server.luau - /foo/init.client.lua - /foo/init.client.luau + - /foo/init.plugin.lua + - /foo/init.plugin.luau - /foo/init.csv - /foo/init.meta.json - /foo/init.meta.jsonc @@ -40,6 +42,8 @@ children: - /foo/Child/init.server.luau - /foo/Child/init.client.lua - /foo/Child/init.client.luau + - /foo/Child/init.plugin.lua + - /foo/Child/init.plugin.luau - /foo/Child/init.csv - /foo/Child/init.meta.json - /foo/Child/init.meta.jsonc diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap index 80178738..f5de8064 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs.snap @@ -15,6 +15,8 @@ metadata: - /root/init.server.luau - /root/init.client.lua - /root/init.client.luau + - /root/init.plugin.lua + - /root/init.plugin.luau - /root/init.csv - /root/init.meta.json - /root/init.meta.jsonc diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs_with_meta.snap index d5f8aa9f..60b43c20 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__lua__test__init_module_from_vfs_with_meta.snap @@ -15,6 +15,8 @@ metadata: - /root/init.server.luau - /root/init.client.lua - /root/init.client.luau + - /root/init.plugin.lua + - /root/init.plugin.luau - /root/init.csv - /root/init.meta.json - /root/init.meta.jsonc diff --git a/src/syncback/file_names.rs b/src/syncback/file_names.rs index 4653aabd..7654fed8 100644 --- a/src/syncback/file_names.rs +++ b/src/syncback/file_names.rs @@ -35,6 +35,7 @@ pub fn name_for_inst<'old>( | Middleware::CsvDir | Middleware::ServerScriptDir | Middleware::ClientScriptDir + | Middleware::PluginScriptDir | Middleware::ModuleScriptDir => Cow::Owned(new_inst.name.clone()), _ => { let extension = extension_for_middleware(middleware); @@ -78,6 +79,7 @@ pub fn extension_for_middleware(middleware: Middleware) -> &'static str { | Middleware::CsvDir | Middleware::ServerScriptDir | Middleware::ClientScriptDir + | Middleware::PluginScriptDir | Middleware::ModuleScriptDir => { unimplemented!("directory middleware requires special treatment") } diff --git a/src/syncback/mod.rs b/src/syncback/mod.rs index e1666abc..7fe3992d 100644 --- a/src/syncback/mod.rs +++ b/src/syncback/mod.rs @@ -359,6 +359,7 @@ pub fn get_best_middleware(snapshot: &SyncbackSnapshot) -> Middleware { middleware = match middleware { Middleware::ServerScript => Middleware::ServerScriptDir, Middleware::ClientScript => Middleware::ClientScriptDir, + Middleware::PluginScript => Middleware::PluginScriptDir, Middleware::ModuleScript => Middleware::ModuleScriptDir, Middleware::Csv => Middleware::CsvDir, Middleware::JsonModel | Middleware::Text => Middleware::Dir, diff --git a/tests/tests/build.rs b/tests/tests/build.rs index 8c533115..c7873050 100644 --- a/tests/tests/build.rs +++ b/tests/tests/build.rs @@ -65,6 +65,7 @@ gen_build_tests! { no_name_default_project, no_name_project, no_name_top_level_project, + plugin_init, } fn run_build_test(test_name: &str) { From ac6941f05483b0875fda52c7664cd42033db7fa2 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Sun, 7 Jun 2026 15:51:05 -0700 Subject: [PATCH 1492/1504] Add origin/host validation and warning for exposed serves (#1270) --- CHANGELOG.md | 2 + src/cli/serve.rs | 37 ++- src/project.rs | 44 +++ src/serve_session.rs | 4 + src/web/api.rs | 43 ++- src/web/interface.rs | 8 + src/web/mod.rs | 31 +- src/web/origin.rs | 589 ++++++++++++++++++++++++++++++++++ tests/rojo_test/serve_util.rs | 37 +++ tests/tests/serve.rs | 68 ++++ 10 files changed, 852 insertions(+), 11 deletions(-) create mode 100644 src/web/origin.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 8ceff750..cff39688 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ Making a new release? Simply add the new header with the version and date undern * Fixed the sync fallback scrambling sibling order; replacements are now re-parented ancestors-first and in their original child order. ([#1265]) * Instances that share a name and class are now robustly matched on resync by comparing their properties, instead of relying on child order alone. ([#1266]) * Rojo now reports a clear error instead of panicking in several cases, including when the `serve` port is already in use, when a synced file is read-only or locked, when the filesystem watcher can't be created, and when the working directory is inaccessible. ([#1267]) +* `rojo serve` now validates the `Host`/`Origin` headers to protect the local/private server against DNS rebinding, gates `/api/open` to local clients, and warns when bound to a network-reachable address. The accepted hosts can be extended with the `--allowed-hosts` option or a project's `serveAllowedHosts` field, for example to reach a network-exposed server by hostname. ([#1270]) [#1176]: https://github.com/rojo-rbx/rojo/pull/1176 [#1179]: https://github.com/rojo-rbx/rojo/pull/1179 @@ -58,6 +59,7 @@ Making a new release? Simply add the new header with the version and date undern [#1265]: https://github.com/rojo-rbx/rojo/pull/1265 [#1266]: https://github.com/rojo-rbx/rojo/pull/1266 [#1267]: https://github.com/rojo-rbx/rojo/pull/1267 +[#1270]: https://github.com/rojo-rbx/rojo/pull/1270 ## [7.7.0-rc.1] (November 27th, 2025) diff --git a/src/cli/serve.rs b/src/cli/serve.rs index e33c3fc5..b22beb69 100644 --- a/src/cli/serve.rs +++ b/src/cli/serve.rs @@ -31,6 +31,14 @@ pub struct ServeCommand { /// it has none. #[clap(long)] pub port: Option, + + /// Extra `Host`/`Origin` values the server will accept, beyond localhost and + /// the bind address (for example a hostname like `mypc.lan`). Repeat the + /// option or comma-separate to allow several. When given, this overrides the + /// project's `serveAllowedHosts`. Listing any host also turns on Host/Origin + /// validation for binds where it is otherwise off (such as `0.0.0.0`). + #[clap(long, value_delimiter = ',')] + pub allowed_hosts: Vec, } impl ServeCommand { @@ -51,9 +59,17 @@ impl ServeCommand { .or_else(|| session.project_port()) .unwrap_or(DEFAULT_PORT); + // The CLI flag, when given, replaces the project's list rather than + // merging with it, matching how --address and --port override theirs. + let allowed_hosts = if self.allowed_hosts.is_empty() { + session.serve_allowed_hosts().to_vec() + } else { + self.allowed_hosts + }; + let server = LiveServer::new(session); - server.start((ip, port).into(), || { + server.start((ip, port).into(), allowed_hosts, || { let _ = show_start_message(ip, port, global.color.into()); })?; @@ -87,6 +103,25 @@ fn show_start_message(bind_address: IpAddr, port: u16, color: ColorChoice) -> io writeln!(&mut buffer)?; + if !bind_address.is_loopback() { + let mut warning = ColorSpec::new(); + warning.set_fg(Some(Color::Yellow)).set_bold(true); + + buffer.set_color(&warning)?; + writeln!( + &mut buffer, + "WARNING: This server is bound to {address_string}, which is reachable from the \ + network.\n\ + The serve API is unauthenticated, so anyone who can reach {address_string}:{port} \ + can read\n\ + and modify your project's source. Prefer binding to localhost and tunneling (e.g. \ + SSH,\n\ + Tailscale, or WireGuard) when you need remote access." + )?; + buffer.set_color(&ColorSpec::new())?; + writeln!(&mut buffer)?; + } + buffer.set_color(&ColorSpec::new())?; write!(&mut buffer, "Visit ")?; diff --git a/src/project.rs b/src/project.rs index bfcc7f0e..093529b1 100644 --- a/src/project.rs +++ b/src/project.rs @@ -106,6 +106,15 @@ pub struct Project { #[serde(skip_serializing_if = "Option::is_none")] pub serve_address: Option, + /// Additional `Host`/`Origin` header values that `rojo serve` will accept + /// beyond `localhost` and the bind address, such as a hostname like + /// `mypc.lan` used to reach a network-exposed server by name. Listing any + /// host also turns on `Host`/`Origin` validation for binds where it is + /// otherwise off (such as `0.0.0.0`). The `--allowed-hosts` CLI option + /// overrides this field when provided. + #[serde(default, skip_serializing_if = "Vec::is_empty")] + pub serve_allowed_hosts: Vec, + /// Determines if Rojo should emit scripts with the appropriate `RunContext` /// for `*.client.lua` and `*.server.lua` files in the project instead of /// using `Script` and `LocalScript` Instances. @@ -595,6 +604,41 @@ mod test { assert!(project.sync_rules[1].include.is_match("init.module.lua")); } + #[test] + fn project_with_serve_allowed_hosts() { + let project_json = r#"{ + "name": "TestProject", + "tree": { "$path": "src" }, + "serveAllowedHosts": ["mypc.lan", "192.168.1.5"] + }"#; + + let project = Project::load_from_slice( + project_json.as_bytes(), + PathBuf::from("/test/default.project.json"), + None, + ) + .expect("Failed to parse project with serveAllowedHosts"); + + assert_eq!(project.serve_allowed_hosts, vec!["mypc.lan", "192.168.1.5"]); + } + + #[test] + fn project_without_serve_allowed_hosts_defaults_to_empty() { + let project_json = r#"{ + "name": "TestProject", + "tree": { "$path": "src" } + }"#; + + let project = Project::load_from_slice( + project_json.as_bytes(), + PathBuf::from("/test/default.project.json"), + None, + ) + .expect("Failed to parse project"); + + assert!(project.serve_allowed_hosts.is_empty()); + } + #[test] fn glob_ignore_paths_negation() { let project_json = r#"{ diff --git a/src/serve_session.rs b/src/serve_session.rs index f50d3926..e46cdfe9 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -207,6 +207,10 @@ impl ServeSession { self.root_project.serve_address } + pub fn serve_allowed_hosts(&self) -> &[String] { + &self.root_project.serve_allowed_hosts + } + pub fn root_dir(&self) -> &Path { self.root_project.folder_location() } diff --git a/src/web/api.rs b/src/web/api.rs index 38163bb9..2875f2aa 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -1,7 +1,7 @@ //! Defines Rojo's HTTP API, all under /api. These endpoints generally return //! JSON. -use std::{collections::HashMap, fs, path::PathBuf, str::FromStr, sync::Arc}; +use std::{collections::HashMap, fs, net::SocketAddr, path::PathBuf, str::FromStr, sync::Arc}; use futures::{sink::SinkExt, stream::StreamExt}; use hyper::{body, Body, Method, Request, Response, StatusCode}; @@ -21,6 +21,7 @@ use crate::{ ServerInfoResponse, SocketPacket, SocketPacketBody, SocketPacketType, SubscribeMessage, WriteRequest, WriteResponse, PROTOCOL_VERSION, SERVER_VERSION, }, + origin::canonical, util::{deserialize_msgpack, msgpack, msgpack_ok, serialize_msgpack}, }, web_api::{ @@ -28,8 +29,12 @@ use crate::{ }, }; -pub async fn call(serve_session: Arc, mut request: Request) -> Response { - let service = ApiService::new(serve_session); +pub async fn call( + serve_session: Arc, + remote_addr: SocketAddr, + mut request: Request, +) -> Response { + let service = ApiService::new(serve_session, remote_addr); match (request.method(), request.uri().path()) { (&Method::GET, "/api/rojo") => service.handle_api_rojo().await, @@ -65,11 +70,15 @@ pub async fn call(serve_session: Arc, mut request: Request) pub struct ApiService { serve_session: Arc, + remote_addr: SocketAddr, } impl ApiService { - pub fn new(serve_session: Arc) -> Self { - ApiService { serve_session } + pub fn new(serve_session: Arc, remote_addr: SocketAddr) -> Self { + ApiService { + serve_session, + remote_addr, + } } /// Get a summary of information about the server @@ -348,6 +357,30 @@ impl ApiService { /// Open a script with the given ID in the user's default text editor. async fn handle_api_open(&self, request: Request) -> Response { + // Opening a file launches a local program, so it must never be reachable + // by a remote client even when the server is bound to an exposed address. + // + // `remote_addr` is the immediate peer, which is the best locality signal + // we have: the legitimate caller is a sandboxed Roblox plugin whose only + // credential is being able to reach the port, so there is no secret to + // authenticate it with. A connection forwarded over loopback by an + // SSH/Tailscale tunnel or a local reverse proxy therefore appears local + // and is allowed. That is delegated trust rather than a bypass: by + // standing up that tunnel or proxy the user has decided the remote end is + // trusted, and reachability is bounded by that hop's own authentication + // (e.g. SSH keys or Tailscale ACLs). This gate only stops direct, + // unauthenticated peers. + // + // An IPv4 client reaching a dual-stack (`::`) bind appears as an + // IPv4-mapped IPv6 peer (`::ffff:127.0.0.1`), so canonicalize to the bare + // IPv4 form before the loopback test, matching `origin`'s handling. + if !canonical(self.remote_addr.ip()).is_loopback() { + return msgpack( + ErrorResponse::forbidden("/api/open is only available to local clients"), + StatusCode::FORBIDDEN, + ); + } + let argument = &request.uri().path()["/api/open/".len()..]; let requested_id = match Ref::from_str(argument) { Ok(id) => id, diff --git a/src/web/interface.rs b/src/web/interface.rs index 51307b67..8ec332ed 100644 --- a/src/web/interface.rs +++ b/src/web/interface.rs @@ -290,6 +290,13 @@ impl ErrorResponse { } } + pub fn forbidden>(details: S) -> Self { + Self { + kind: ErrorResponseKind::Forbidden, + details: details.into(), + } + } + pub fn internal_error>(details: S) -> Self { Self { kind: ErrorResponseKind::InternalError, @@ -302,5 +309,6 @@ impl ErrorResponse { pub enum ErrorResponseKind { NotFound, BadRequest, + Forbidden, InternalError, } diff --git a/src/web/mod.rs b/src/web/mod.rs index 8e33d9c5..8a003285 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -5,6 +5,7 @@ mod api; mod assets; pub mod interface; +mod origin; mod ui; mod util; @@ -14,7 +15,7 @@ use std::sync::Arc; use anyhow::Context; use hyper::{ - server::Server, + server::{conn::AddrStream, Server}, service::{make_service_fn, service_fn}, Body, Request, }; @@ -33,22 +34,42 @@ impl LiveServer { /// Starts the server on the given address, blocking until it stops. /// + /// `allowed_hosts` are extra `Host`/`Origin` values to accept in addition to + /// localhost and the bind address (see [`origin::allowed_hosts`]). + /// /// `on_listening` is invoked once the server has successfully bound to the /// address, so callers can defer printing any "listening" message until /// after binding can no longer fail (e.g. due to the port being in use). - pub fn start(self, address: SocketAddr, on_listening: impl FnOnce()) -> anyhow::Result<()> { + pub fn start( + self, + address: SocketAddr, + allowed_hosts: Vec, + on_listening: impl FnOnce(), + ) -> anyhow::Result<()> { let serve_session = Arc::clone(&self.serve_session); + let allowed_hosts = origin::allowed_hosts(address.ip(), address.port(), &allowed_hosts); - let make_service = make_service_fn(move |_conn| { + let make_service = make_service_fn(move |conn: &AddrStream| { let serve_session = Arc::clone(&serve_session); + let allowed_hosts = allowed_hosts.clone(); + let remote_addr = conn.remote_addr(); - async { + async move { let service = move |req: Request| { let serve_session = Arc::clone(&serve_session); + let allowed_hosts = allowed_hosts.clone(); async move { + // Reject cross-origin requests before doing any work, to + // defend the local server against DNS rebinding. + if let Some(response) = + origin::check_request_origin(&req, allowed_hosts.as_ref()) + { + return Ok::<_, Infallible>(response); + } + if req.uri().path().starts_with("/api") { - Ok::<_, Infallible>(api::call(serve_session, req).await) + Ok::<_, Infallible>(api::call(serve_session, remote_addr, req).await) } else { Ok::<_, Infallible>(ui::call(serve_session, req).await) } diff --git a/src/web/origin.rs b/src/web/origin.rs new file mode 100644 index 00000000..bb36a7e7 --- /dev/null +++ b/src/web/origin.rs @@ -0,0 +1,589 @@ +//! Host/Origin validation used to defend the local Rojo server against DNS +//! rebinding attacks. +//! +//! When Rojo is bound to a loopback address (the default), a malicious web page +//! the developer visits cannot read the API responses directly because of the +//! browser Same-Origin Policy. However, a DNS rebinding attack can defeat that: +//! the page points its own hostname at `127.0.0.1` after loading, so the browser +//! treats requests to the Rojo server as same-origin. Validating that the `Host` +//! (and, if present, `Origin`) header refers to an address we recognize blocks +//! this, because the rebound request still carries the attacker's hostname, which +//! is a domain name rather than one of the IP literals we accept. +//! +//! Enforcement covers two kinds of bind: +//! +//! * Loopback (the default): only `localhost` and loopback literals are +//! accepted. +//! * A specific private/LAN address: `localhost`, loopback literals, and that exact bind +//! IP are accepted. Because the defense works by rejecting any `Host` that +//! isn't a recognized IP literal, clients must connect to a private bind by +//! IP. A hostname (e.g. `mypc.local`) is indistinguishable from an attacker +//! domain and is rejected. +//! +//! Enforcement is disabled for unspecified (`0.0.0.0`/`::`) and public binds: the +//! user has asked for broad, possibly-public exposure where arbitrary hostnames +//! may legitimately resolve to the server, so we can't build a meaningful +//! allowlist. Those binds get a startup warning instead. Two consequences worth +//! being explicit about: such a bind has no rebinding protection even for a +//! browser on the same machine; and even on a protected private bind this check +//! does nothing against a hostile peer already on the LAN, who can reach the +//! unauthenticated API directly. Both are the network-exposure risk the startup +//! warning addresses, not something the `Host` check is meant to cover. +//! +//! The allowlist can be widened with extra hosts (the `--allowed-hosts` CLI +//! option or a project's `serveAllowedHosts`), for example a hostname like +//! `mypc.lan` for reaching a network-exposed server by name. Listing any extra +//! host also turns enforcement back on for an unspecified or public bind that +//! would otherwise disable it, restricting that bind to localhost, the bind IP, +//! and the listed hosts. + +use std::net::IpAddr; + +use hyper::{ + header::{HOST, ORIGIN}, + http::uri::{Authority, Uri}, + Body, Request, Response, StatusCode, +}; + +use crate::web::util::response; + +/// The set of `Host`/`Origin` values accepted while enforcement is active. +#[derive(Debug, Clone)] +pub struct AllowedHosts { + port: u16, + /// The bind IP accepted in addition to `localhost`/loopback, set only for a + /// private (LAN) bind or a specific public bind that has extra hosts. `None` + /// for a loopback or unspecified bind, which has no single address to add. + bind_ip: Option, + /// Extra `Host`/`Origin` values the user explicitly allowed, via the + /// `--allowed-hosts` option or a project's `serveAllowedHosts`. These are + /// hostnames such as `mypc.lan`, or IP literals, accepted in addition to + /// localhost and the bind IP. Each entry is already passed through + /// [`normalize_host`]. + extra_hosts: Vec, +} + +impl AllowedHosts { + /// Returns whether the given host and optional port are allowed. The host is + /// accepted if it is `localhost`, a loopback IP literal, (on a private or + /// specific public bind) the exact bind IP, or one of the explicitly allowed + /// extra hosts. A request with no explicit port is accepted (the host + /// already has to be one we recognize). + fn allows(&self, host: &str, port: Option) -> bool { + let host = normalize_host(host); + let host_ok = host.eq_ignore_ascii_case("localhost") + || host + .parse::() + .ok() + .map(canonical) + .is_some_and(|ip| ip.is_loopback() || self.bind_ip == Some(ip)) + || self.allows_extra(host); + + host_ok && port.is_none_or(|port| port == self.port) + } + + /// Returns whether `host` matches one of the explicitly allowed extra hosts. + /// Entries that are IP literals are compared as addresses, so equivalent + /// forms (such as an IPv4-mapped IPv6 literal) match; everything else is + /// compared as a case-insensitive hostname. + fn allows_extra(&self, host: &str) -> bool { + let host_ip = host.parse::().ok().map(canonical); + self.extra_hosts.iter().any(|allowed| { + match (host_ip, allowed.parse::().map(canonical)) { + (Some(host_ip), Ok(allowed_ip)) => host_ip == allowed_ip, + _ => host.eq_ignore_ascii_case(allowed), + } + }) + } +} + +/// Builds the allowlist for a given bind address and any extra allowed hosts. +/// Returns `None` (validation disabled) when bound to an unspecified +/// (`0.0.0.0`/`::`) or public address and no extra hosts were given, where +/// arbitrary hostnames may legitimately resolve to the server. Listing extra +/// hosts keeps validation on even for those binds. +pub fn allowed_hosts(bind: IpAddr, port: u16, extra: &[String]) -> Option { + let extra_hosts: Vec = extra + .iter() + .map(|host| normalize_host(host.trim()).to_owned()) + .filter(|host| !host.is_empty()) + .collect(); + + if bind.is_loopback() { + Some(AllowedHosts { + port, + bind_ip: None, + extra_hosts, + }) + } else if is_private_bind(bind) { + Some(AllowedHosts { + port, + bind_ip: Some(canonical(bind)), + extra_hosts, + }) + } else if !extra_hosts.is_empty() { + // The bind is unspecified or public, where validation is normally + // disabled. By listing explicit hosts the user has opted back into it, + // so we accept localhost, the bind IP (when it is a specific address), + // and those hosts. An unspecified bind (`0.0.0.0`/`::`) has no single + // address to add. + let bind_ip = (!bind.is_unspecified()).then(|| canonical(bind)); + Some(AllowedHosts { + port, + bind_ip, + extra_hosts, + }) + } else { + None + } +} + +/// Collapses an IPv4-mapped IPv6 address (`::ffff:192.168.0.1`) to its IPv4 form +/// so it classifies and compares consistently with the bare IPv4 address. Shared +/// with the `/api/open` peer check so it recognizes a mapped loopback peer too. +pub(crate) fn canonical(ip: IpAddr) -> IpAddr { + match ip { + IpAddr::V6(v6) => v6.to_ipv4_mapped().map(IpAddr::V4).unwrap_or(ip), + v4 => v4, + } +} + +/// Returns whether a bind address is a specific private/link-local address, the +/// case where enforcement stays on with the bind IP added to the allowlist. +/// Unspecified, loopback, and public addresses are excluded (loopback is handled +/// separately by [`allowed_hosts`]). +fn is_private_bind(ip: IpAddr) -> bool { + match canonical(ip) { + IpAddr::V4(v4) => v4.is_private() || v4.is_link_local(), + IpAddr::V6(v6) => { + let first = v6.segments()[0]; + // Unique local (fc00::/7) or link-local (fe80::/10). The std methods + // for these are still nightly-only, so test the prefix directly. + (first & 0xfe00) == 0xfc00 || (first & 0xffc0) == 0xfe80 + } + } +} + +/// Validates the `Host` and `Origin` headers of an incoming request against the +/// allowlist. Returns `Some` with a ready-to-send `404` response when the +/// request should be rejected, or `None` when it is allowed to proceed. When +/// `allowed` is `None` (unspecified or public bind) every request is accepted. +pub fn check_request_origin( + request: &Request, + allowed: Option<&AllowedHosts>, +) -> Option> { + let allowed = allowed?; + + // The Host header is mandatory and must refer to a local address. + let host_ok = request + .headers() + .get(HOST) + .and_then(|value| value.to_str().ok()) + .and_then(parse_authority) + .is_some_and(|(host, port)| allowed.allows(&host, port)); + + if !host_ok { + return Some(reject()); + } + + // The Origin header is optional: non-browser clients such as the Roblox + // plugin never send it. When it is present (i.e. a browser made the request) + // it must also be local, which rejects a rebound page whose origin is still + // its own non-local hostname. + if let Some(origin) = request.headers().get(ORIGIN) { + let origin_ok = origin + .to_str() + .ok() + .and_then(parse_origin) + .is_some_and(|(host, port)| allowed.allows(&host, port)); + + if !origin_ok { + return Some(reject()); + } + } + + None +} + +/// Normalizes a host literal for parsing/comparison: strips the surrounding +/// brackets from an IPv6 literal (e.g. `[::1]`) and drops any IPv6 zone id (e.g. +/// `fe80::1%eth0`), which `Ipv6Addr::from_str` would otherwise reject. +fn normalize_host(host: &str) -> &str { + let host = host + .strip_prefix('[') + .and_then(|host| host.strip_suffix(']')) + .unwrap_or(host); + + host.split('%').next().unwrap_or(host) +} + +/// Parses a `Host` header value (an authority such as `localhost:34872`) into +/// its host and optional port. Returns `None` if the authority carries userinfo +/// (e.g. `evil.com@localhost`), so a value whose host looks local only after the +/// userinfo is stripped can never sneak past the allowlist. +fn parse_authority(value: &str) -> Option<(String, Option)> { + let authority: Authority = value.parse().ok()?; + reject_userinfo(&authority)?; + Some((authority.host().to_owned(), authority.port_u16())) +} + +/// Parses an `Origin` header value (an absolute URI such as +/// `http://localhost:34872`) into its host and optional port. Returns `None` for +/// origins without a host, such as the opaque `null` origin, or for origins whose +/// authority carries userinfo (see [`parse_authority`]). +fn parse_origin(value: &str) -> Option<(String, Option)> { + let uri: Uri = value.parse().ok()?; + reject_userinfo(uri.authority()?)?; + Some((uri.host()?.to_owned(), uri.port_u16())) +} + +/// Returns `None` (rejecting the value) when an authority contains a userinfo +/// component, identified by the `@` separator. A bare host or `host:port` never +/// contains `@`, so this only fires on `userinfo@host` forms. +fn reject_userinfo(authority: &Authority) -> Option<()> { + if authority.as_str().contains('@') { + None + } else { + Some(()) + } +} + +/// Builds the response sent when a request fails Host/Origin validation. It is a +/// generic `404` with no Rojo-identifying body: a rejected request may be a +/// prober (or a DNS-rebound page's same-origin script, which could read the +/// body), so we reveal nothing rather than confirming a Rojo server is here. +fn reject() -> Response { + response(StatusCode::NOT_FOUND, "text/plain", "Not Found") +} + +#[cfg(test)] +mod test { + use super::*; + + use std::net::{Ipv4Addr, Ipv6Addr}; + + const PORT: u16 = 34872; + + fn loopback_allowlist() -> Option { + allowed_hosts(IpAddr::V4(Ipv4Addr::LOCALHOST), PORT, &[]) + } + + /// An allowlist for a server bound to a specific private (LAN) address. + fn private_allowlist() -> Option { + allowed_hosts(IpAddr::V4(Ipv4Addr::new(192, 168, 1, 5)), PORT, &[]) + } + + /// An allowlist for `bind` with the given extra allowed hosts. + fn allowlist_with_hosts(bind: IpAddr, hosts: &[&str]) -> Option { + let hosts: Vec = hosts.iter().map(|host| host.to_string()).collect(); + allowed_hosts(bind, PORT, &hosts) + } + + fn request_with(headers: &[(&'static str, &str)]) -> Request { + let mut builder = Request::builder().uri("/api/rojo"); + for (name, value) in headers { + builder = builder.header(*name, *value); + } + builder.body(Body::empty()).unwrap() + } + + #[test] + fn loopback_bind_enables_enforcement() { + assert!(allowed_hosts(IpAddr::V4(Ipv4Addr::LOCALHOST), PORT, &[]).is_some()); + assert!(allowed_hosts(IpAddr::V6(Ipv6Addr::LOCALHOST), PORT, &[]).is_some()); + } + + #[test] + fn private_bind_enables_enforcement() { + for bind in [ + IpAddr::V4(Ipv4Addr::new(192, 168, 1, 5)), // 192.168.0.0/16 + IpAddr::V4(Ipv4Addr::new(10, 0, 0, 1)), // 10.0.0.0/8 + IpAddr::V4(Ipv4Addr::new(172, 16, 0, 1)), // 172.16.0.0/12 + IpAddr::V4(Ipv4Addr::new(169, 254, 0, 1)), // link-local + IpAddr::V6(Ipv6Addr::new(0xfc00, 0, 0, 0, 0, 0, 0, 1)), // unique local + IpAddr::V6(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1)), // link-local + ] { + assert!( + allowed_hosts(bind, PORT, &[]).is_some(), + "private bind {bind} should enable enforcement" + ); + } + } + + #[test] + fn unspecified_or_public_bind_disables_enforcement() { + for bind in [ + IpAddr::V4(Ipv4Addr::UNSPECIFIED), // 0.0.0.0 + IpAddr::V6(Ipv6Addr::UNSPECIFIED), // :: + IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)), // public + IpAddr::V6(Ipv6Addr::new(0x2001, 0x4860, 0, 0, 0, 0, 0, 0x8888)), // public + ] { + assert!( + allowed_hosts(bind, PORT, &[]).is_none(), + "bind {bind} should disable enforcement" + ); + } + } + + #[test] + fn accepts_local_hosts() { + let allowed = loopback_allowlist(); + for host in [ + format!("localhost:{PORT}"), + format!("127.0.0.1:{PORT}"), + format!("[::1]:{PORT}"), + "localhost".to_owned(), + ] { + let request = request_with(&[("host", &host)]); + assert!( + check_request_origin(&request, allowed.as_ref()).is_none(), + "host {host} should be allowed" + ); + } + } + + #[test] + fn rejects_foreign_host() { + let allowed = loopback_allowlist(); + let request = request_with(&[("host", "evil.com")]); + assert!(check_request_origin(&request, allowed.as_ref()).is_some()); + } + + #[test] + fn rejects_wrong_port() { + let allowed = loopback_allowlist(); + let request = request_with(&[("host", "localhost:1234")]); + assert!(check_request_origin(&request, allowed.as_ref()).is_some()); + } + + #[test] + fn rejects_missing_host() { + let allowed = loopback_allowlist(); + let request = request_with(&[]); + assert!(check_request_origin(&request, allowed.as_ref()).is_some()); + } + + #[test] + fn rejects_host_with_userinfo() { + let allowed = loopback_allowlist(); + // The host parses to `localhost`, but the userinfo prefix must keep it + // from being treated as a local address. + let request = request_with(&[("host", &format!("evil.com@localhost:{PORT}"))]); + assert!(check_request_origin(&request, allowed.as_ref()).is_some()); + } + + #[test] + fn rejects_origin_with_userinfo() { + let allowed = loopback_allowlist(); + let request = request_with(&[ + ("host", &format!("localhost:{PORT}")), + ("origin", &format!("http://evil.com@localhost:{PORT}")), + ]); + assert!(check_request_origin(&request, allowed.as_ref()).is_some()); + } + + #[test] + fn rejects_foreign_origin_even_with_local_host() { + let allowed = loopback_allowlist(); + let request = request_with(&[ + ("host", &format!("localhost:{PORT}")), + ("origin", &format!("http://evil.com:{PORT}")), + ]); + assert!(check_request_origin(&request, allowed.as_ref()).is_some()); + } + + #[test] + fn rejects_null_origin() { + let allowed = loopback_allowlist(); + let request = request_with(&[("host", &format!("localhost:{PORT}")), ("origin", "null")]); + assert!(check_request_origin(&request, allowed.as_ref()).is_some()); + } + + #[test] + fn accepts_local_origin() { + let allowed = loopback_allowlist(); + let request = request_with(&[ + ("host", &format!("localhost:{PORT}")), + ("origin", &format!("http://localhost:{PORT}")), + ]); + assert!(check_request_origin(&request, allowed.as_ref()).is_none()); + } + + #[test] + fn private_bind_accepts_local_and_bind_ip_hosts() { + let allowed = private_allowlist(); + for host in [ + format!("192.168.1.5:{PORT}"), + format!("localhost:{PORT}"), + format!("127.0.0.1:{PORT}"), + format!("[::1]:{PORT}"), + "192.168.1.5".to_owned(), + ] { + let request = request_with(&[("host", &host)]); + assert!( + check_request_origin(&request, allowed.as_ref()).is_none(), + "host {host} should be allowed on a private bind" + ); + } + } + + #[test] + fn private_bind_rejects_other_hosts() { + let allowed = private_allowlist(); + for host in [ + "evil.com", // a rebound attacker domain + "192.168.1.6", // a different private IP + "8.8.8.8", // a public IP + ] { + let request = request_with(&[("host", host)]); + assert!( + check_request_origin(&request, allowed.as_ref()).is_some(), + "host {host} should be rejected on a private bind" + ); + } + } + + #[test] + fn private_bind_keeps_origin_strict() { + // A different private IP as Origin must be rejected even though the Host + // is the valid bind IP: the Origin check is not widened to arbitrary + // private addresses. + let allowed = private_allowlist(); + let request = request_with(&[ + ("host", &format!("192.168.1.5:{PORT}")), + ("origin", &format!("http://192.168.1.6:{PORT}")), + ]); + assert!(check_request_origin(&request, allowed.as_ref()).is_some()); + } + + #[test] + fn private_bind_accepts_bind_ip_origin() { + let allowed = private_allowlist(); + let request = request_with(&[ + ("host", &format!("192.168.1.5:{PORT}")), + ("origin", &format!("http://192.168.1.5:{PORT}")), + ]); + assert!(check_request_origin(&request, allowed.as_ref()).is_none()); + } + + #[test] + fn accepts_ipv4_mapped_bind_ip() { + // `::ffff:192.168.1.5` is the IPv4-mapped form of the bind IP and must + // be treated as equal to it. + let allowed = private_allowlist(); + let request = request_with(&[("host", &format!("[::ffff:192.168.1.5]:{PORT}"))]); + assert!(check_request_origin(&request, allowed.as_ref()).is_none()); + } + + #[test] + fn canonical_collapses_ipv4_mapped_loopback() { + // The `/api/open` peer gate relies on this: an IPv4 loopback client + // reaching a dual-stack (`::`) bind arrives as `::ffff:127.0.0.1`, which + // is only recognized as loopback after canonicalization. + let mapped: IpAddr = "::ffff:127.0.0.1".parse().unwrap(); + assert!(!mapped.is_loopback()); + assert!(canonical(mapped).is_loopback()); + } + + #[test] + fn normalize_host_strips_brackets_and_zone_id() { + // Brackets and an IPv6 zone id must be removed so the result parses as an + // `IpAddr` (`Ipv6Addr::from_str` rejects zone ids). + assert_eq!(normalize_host("[::1]"), "::1"); + assert_eq!(normalize_host("[fe80::1%eth0]"), "fe80::1"); + assert_eq!(normalize_host("localhost"), "localhost"); + assert!(normalize_host("[fe80::1%eth0]").parse::().is_ok()); + } + + #[test] + fn allowed_hosts_extend_the_allowlist() { + // A hostname listed as an allowed host is accepted on a loopback bind, + // with the usual port check still applied; an unlisted host is not. + let allowed = allowlist_with_hosts(IpAddr::V4(Ipv4Addr::LOCALHOST), &["mypc.lan"]); + + let ok = request_with(&[("host", &format!("mypc.lan:{PORT}"))]); + assert!(check_request_origin(&ok, allowed.as_ref()).is_none()); + + let wrong_port = request_with(&[("host", "mypc.lan:1234")]); + assert!(check_request_origin(&wrong_port, allowed.as_ref()).is_some()); + + let other = request_with(&[("host", &format!("other.lan:{PORT}"))]); + assert!(check_request_origin(&other, allowed.as_ref()).is_some()); + } + + #[test] + fn allowed_hosts_apply_to_origin() { + let allowed = allowlist_with_hosts(IpAddr::V4(Ipv4Addr::LOCALHOST), &["mypc.lan"]); + + let ok = request_with(&[ + ("host", &format!("mypc.lan:{PORT}")), + ("origin", &format!("http://mypc.lan:{PORT}")), + ]); + assert!(check_request_origin(&ok, allowed.as_ref()).is_none()); + + let foreign_origin = request_with(&[ + ("host", &format!("mypc.lan:{PORT}")), + ("origin", &format!("http://evil.com:{PORT}")), + ]); + assert!(check_request_origin(&foreign_origin, allowed.as_ref()).is_some()); + } + + #[test] + fn allowed_hosts_enable_enforcement_on_exposed_bind() { + // Binding to 0.0.0.0 normally disables validation, but listing a host + // turns it back on: localhost and the listed host are accepted while + // everything else is rejected. + let allowed = allowlist_with_hosts(IpAddr::V4(Ipv4Addr::UNSPECIFIED), &["mypc.lan"]); + assert!(allowed.is_some()); + + for host in [format!("mypc.lan:{PORT}"), format!("localhost:{PORT}")] { + let request = request_with(&[("host", &host)]); + assert!( + check_request_origin(&request, allowed.as_ref()).is_none(), + "host {host} should be allowed" + ); + } + + let evil = request_with(&[("host", "evil.com")]); + assert!(check_request_origin(&evil, allowed.as_ref()).is_some()); + } + + #[test] + fn allowed_hosts_on_public_bind_accept_the_bind_ip() { + // A specific public bind with an allowed host accepts localhost, the + // listed host, and the bind IP itself, but nothing else. (203.0.113.0/24 + // is the TEST-NET-3 documentation range, treated here as a public IP.) + let bind = IpAddr::V4(Ipv4Addr::new(203, 0, 113, 5)); + let allowed = allowlist_with_hosts(bind, &["mypc.lan"]); + + for host in [ + format!("203.0.113.5:{PORT}"), + format!("mypc.lan:{PORT}"), + format!("localhost:{PORT}"), + ] { + let request = request_with(&[("host", &host)]); + assert!( + check_request_origin(&request, allowed.as_ref()).is_none(), + "host {host} should be allowed" + ); + } + + let evil = request_with(&[("host", "evil.com")]); + assert!(check_request_origin(&evil, allowed.as_ref()).is_some()); + } + + #[test] + fn disabled_allowlist_accepts_foreign_host() { + for bind in [ + IpAddr::V4(Ipv4Addr::UNSPECIFIED), + IpAddr::V4(Ipv4Addr::new(8, 8, 8, 8)), + ] { + let allowed = allowed_hosts(bind, PORT, &[]); + let request = request_with(&[("host", "evil.com")]); + assert!( + check_request_origin(&request, allowed.as_ref()).is_none(), + "disabled allowlist for bind {bind} should accept any host" + ); + } + } +} diff --git a/tests/rojo_test/serve_util.rs b/tests/rojo_test/serve_util.rs index 4b67a883..4a817a8a 100644 --- a/tests/rojo_test/serve_util.rs +++ b/tests/rojo_test/serve_util.rs @@ -126,6 +126,10 @@ impl TestServeSession { &self.project_path } + pub fn port(&self) -> usize { + self.port + } + /// Waits for the `rojo serve` server to come online with expontential /// backoff. pub fn wait_to_come_online(&mut self) -> ServerInfoResponse { @@ -241,6 +245,39 @@ impl TestServeSession { Ok(deserialize_msgpack(&body).expect("Server returned malformed response")) } + + /// Sends a GET to `/api/rojo` with the given extra request headers and + /// returns the full response. Used to exercise the Host/Origin allowlist that + /// guards against DNS rebinding, including asserting that a rejection reveals + /// nothing about the server. + pub fn api_rojo_response_with_headers( + &self, + headers: &[(&str, &str)], + ) -> reqwest::blocking::Response { + let client = reqwest::blocking::Client::new(); + let url = format!("http://localhost:{}/api/rojo", self.port); + + let mut request = client.get(url); + for (name, value) in headers { + request = request.header(*name, *value); + } + + request.send().expect("Failed to send request") + } + + /// Sends a POST to `/api/open/` and returns the response status code. + /// Used to verify that the local-only gate on `/api/open` admits loopback + /// peers (the test harness always connects over loopback). + pub fn api_open_status(&self, id: &str) -> reqwest::StatusCode { + let client = reqwest::blocking::Client::new(); + let url = format!("http://localhost:{}/api/open/{}", self.port, id); + + client + .post(url) + .send() + .expect("Failed to send request") + .status() + } } fn serialize_msgpack(value: T) -> Result, rmp_serde::encode::Error> { diff --git a/tests/tests/serve.rs b/tests/tests/serve.rs index 748f1687..490c13db 100644 --- a/tests/tests/serve.rs +++ b/tests/tests/serve.rs @@ -10,6 +10,74 @@ use crate::rojo_test::{ use librojo::web_api::SocketPacketType; +#[test] +fn rejects_dns_rebinding_requests() { + run_serve_test("empty", |session, _redactions| { + let port = session.port(); + let local_host = format!("localhost:{port}"); + + // A request carrying a local Host header is served normally. + assert_eq!( + session + .api_rojo_response_with_headers(&[("host", &local_host)]) + .status(), + reqwest::StatusCode::OK, + ); + + // A request whose Host is a foreign hostname, as a DNS-rebound page + // would send, is rejected with a generic 404 that reveals nothing about + // the server. + assert_rejected(session.api_rojo_response_with_headers(&[("host", "evil.com")])); + + // Even with a local Host, a present-but-foreign Origin is rejected. + let foreign_origin = format!("http://evil.com:{port}"); + assert_rejected( + session.api_rojo_response_with_headers(&[ + ("host", &local_host), + ("origin", &foreign_origin), + ]), + ); + }); +} + +/// Asserts that a Host/Origin rejection is a generic 404 whose body and +/// content-type do not identify the server as Rojo. +fn assert_rejected(response: reqwest::blocking::Response) { + assert_eq!(response.status(), reqwest::StatusCode::NOT_FOUND); + + let content_type = response + .headers() + .get(reqwest::header::CONTENT_TYPE) + .and_then(|value| value.to_str().ok()) + .unwrap_or_default() + .to_owned(); + assert!( + !content_type.contains("msgpack"), + "rejection should not use the msgpack API content-type, got {content_type:?}", + ); + + let body = response.text().expect("Failed to read response body"); + let body_lower = body.to_lowercase(); + assert!( + !body_lower.contains("rojo") && !body_lower.contains("rebinding"), + "rejection body should not identify the server, got {body:?}", + ); +} + +#[test] +fn allows_api_open_from_loopback_peer() { + run_serve_test("empty", |session, _redactions| { + // The harness always connects over loopback, so the local-only gate on + // /api/open must let the request through. A bogus instance id then fails + // id parsing with 400, which confirms we got past the gate rather than + // being rejected with 403. + assert_eq!( + session.api_open_status("not-a-real-ref"), + reqwest::StatusCode::BAD_REQUEST, + ); + }); +} + #[test] fn empty() { run_serve_test("empty", |session, mut redactions| { From d12120bab6ec11c861c7b17f832df163ead17738 Mon Sep 17 00:00:00 2001 From: Floyd Horng Date: Thu, 11 Jun 2026 02:47:50 +0100 Subject: [PATCH 1493/1504] Fix syncback not removing stale $properties at engine defaults (#1244) --- CHANGELOG.md | 2 + ...ject_default_properties_remove-stdout.snap | 5 ++ ...roperties_remove-default.project.json.snap | 59 +++++++++++++++ .../input-project/default.project.json | 21 ++++++ .../input.rbxl | Bin 0 -> 44361 bytes src/snapshot_middleware/project.rs | 70 +++++++++++++++--- tests/tests/syncback.rs | 3 + 7 files changed, 150 insertions(+), 10 deletions(-) create mode 100644 rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__project_default_properties_remove-stdout.snap create mode 100644 rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__project_default_properties_remove-default.project.json.snap create mode 100644 rojo-test/syncback-tests/project_default_properties_remove/input-project/default.project.json create mode 100644 rojo-test/syncback-tests/project_default_properties_remove/input.rbxl diff --git a/CHANGELOG.md b/CHANGELOG.md index cff39688..00524693 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ Making a new release? Simply add the new header with the version and date undern * Instances that share a name and class are now robustly matched on resync by comparing their properties, instead of relying on child order alone. ([#1266]) * Rojo now reports a clear error instead of panicking in several cases, including when the `serve` port is already in use, when a synced file is read-only or locked, when the filesystem watcher can't be created, and when the working directory is inaccessible. ([#1267]) * `rojo serve` now validates the `Host`/`Origin` headers to protect the local/private server against DNS rebinding, gates `/api/open` to local clients, and warns when bound to a network-reachable address. The accepted hosts can be extended with the `--allowed-hosts` option or a project's `serveAllowedHosts` field, for example to reach a network-exposed server by hostname. ([#1270]) +* Fixed syncback not removing stale `$properties` entries when Studio resets a property to its engine default. ([#1244]) [#1176]: https://github.com/rojo-rbx/rojo/pull/1176 [#1179]: https://github.com/rojo-rbx/rojo/pull/1179 @@ -60,6 +61,7 @@ Making a new release? Simply add the new header with the version and date undern [#1266]: https://github.com/rojo-rbx/rojo/pull/1266 [#1267]: https://github.com/rojo-rbx/rojo/pull/1267 [#1270]: https://github.com/rojo-rbx/rojo/pull/1270 +[#1244]: https://github.com/rojo-rbx/rojo/pull/1244 ## [7.7.0-rc.1] (November 27th, 2025) diff --git a/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__project_default_properties_remove-stdout.snap b/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__project_default_properties_remove-stdout.snap new file mode 100644 index 00000000..3ef76951 --- /dev/null +++ b/rojo-test/syncback-test-snapshots/end_to_end__rojo_test__syncback_util__project_default_properties_remove-stdout.snap @@ -0,0 +1,5 @@ +--- +source: tests/rojo_test/syncback_util.rs +expression: "String::from_utf8_lossy(&output.stdout)" +--- +Writing default.project.json diff --git a/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__project_default_properties_remove-default.project.json.snap b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__project_default_properties_remove-default.project.json.snap new file mode 100644 index 00000000..1b8d07d2 --- /dev/null +++ b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__project_default_properties_remove-default.project.json.snap @@ -0,0 +1,59 @@ +--- +source: tests/tests/syncback.rs +expression: default.project.json +--- +{ + "name": "SyncbackTest", + "tree": { + "$className": "DataModel", + "Workspace": { + "$className": "Workspace", + "TestPart": { + "$className": "Part", + "$properties": { + "Anchored": true, + "Color": { + "Color3uint8": [ + 0, + 0, + 255 + ] + } + } + }, + "$properties": { + "EnableSLIMAvatars": { + "Enum": 0 + }, + "ImprovedAnimationConstraint": { + "Enum": 0 + }, + "ImprovedPhysicsReplication": { + "Enum": 0 + }, + "LayeredClothingCacheOptimizations": { + "Enum": 0 + }, + "MeshStreamingAndImprovedLods": { + "Enum": 0 + }, + "NextGenerationReplication": { + "Enum": 0 + }, + "PlayerScriptsUseInputActionSystem": { + "Enum": 0 + }, + "UseFixedSimulation": { + "Enum": 0 + }, + "UseNewLuauTypeSolver": "Disabled", + "ValidateEnabledProximityPrompt": { + "Enum": 0 + } + }, + "$attributes": { + "Rojo_Target_CurrentCamera": "302d573157260ee80a3baa32000003b5" + } + } + } +} diff --git a/rojo-test/syncback-tests/project_default_properties_remove/input-project/default.project.json b/rojo-test/syncback-tests/project_default_properties_remove/input-project/default.project.json new file mode 100644 index 00000000..6f0b1ade --- /dev/null +++ b/rojo-test/syncback-tests/project_default_properties_remove/input-project/default.project.json @@ -0,0 +1,21 @@ +{ + "name": "SyncbackTest", + "tree": { + "$className": "DataModel", + "Workspace": { + "$className": "Workspace", + "TestPart": { + "$className": "Part", + "$properties": { + "Transparency": 1.0, + "Anchored": true, + "Color": [ + 1.0, + 0.0, + 0.0 + ] + } + } + } + } +} \ No newline at end of file diff --git a/rojo-test/syncback-tests/project_default_properties_remove/input.rbxl b/rojo-test/syncback-tests/project_default_properties_remove/input.rbxl new file mode 100644 index 0000000000000000000000000000000000000000..7ca3700a7bd1b8c41ba7aa37e4e615585f43e662 GIT binary patch literal 44361 zcmb`QdyE{%o!@7d!>34zq)5FVBONVKvM9bJS(YE%6~+NUoXs`B}dSxDjq;>bPH(c)y@1 zgB0zm%HJJw%``T=uwe?=K>?qYpP!P86g{wA{@y2-RI1bQ+RKfVZeiVyKnn04xk%AY z@~0fyV_JVu)#Vxa6%LT12Y1R}Y6ot|`b zenxP=A{Qw-v|Ik72s1&u?J3S>*!GgDs?BauD9!Gm)AMfhriCG->JnN>&{@t9ns=-@v2i;kWbQ7$&R+04%>k|zZ~ z`$^F~RON2D&iDP+lDFn}dpV_fRgpa^poirmMR!sPExFL^ZDyLVs^C-#5>m8(zx<_g z^PR32W)0`dih#ULwf;{PaUf73=ruY`Pqb%3ta5X5auWGrvM`Ah-EmO<0$%Xf)-f=n zVe2YmEW~6yMN_L%|AnC0X#3w#HkGOW3yR7X8g>Pz7J}BSSaODoXULao9a?3{*A(>Nq zQnUwM!_{cQq{)XA^rSpEE*B}P;roFvhC$Qoc8xw3SMqBr16!^b0dh?xH0Oui#0%b| zNNj&p6F3HtlGLSLA{?XGZzv+$#JEG@>dnyK%$nFGML;`X1S#4J_wjsnFLrt+_X`Sa zdpp{M5eRcdH;WDDhN2rZw`e;`fz2TlFVuD0Tlr|9+gvGV3+zyB(NuQhTS@gyzwwJb z6pA9pvcKYY{T09M_qGmHe%mzbHAPnwRN9}TOSsp1(C@S|inB-I?LG#kU=nrd&BaWm zs|g!T`G;;;*Vx1fd=#aa&?4H0=F(-vl;Unpy`EF$*zT25aj!8N+cfY~3U14uep>NM zS4*q4A$Ud+*j}GrSBZ0wAk&Cv^Nl!`R4WuWd!^Ctd#1@#dGxb_)=loW`~bgcs`Rv~ zl5HoL9CorS>bM!?I*At*iQO@t5IAPM?1f>&Phz7gRk8VrO~cP+ubVZEPC;Ex2~^kR zMvrhJqZtn=lA3^0O~NaqNz1-OQ5pO$g|}_|Il*G%%R#@nu0ov*(NaMnxPMj1b^P%|;qOS0)yhE-%`OEjZ=jr`zq|x(*)ZLeEp-cUQu6A+S3U2x!D~uNV3& z{hkW2l*jTWcm{>78vIKArNs^9GbAXZ5-JtLDPY!H^*dg7kV@Bw+^G{O+Qwg6dqD!L zAl#a7J$kUR&5SRKbEkv7Bmvw6wHh2~0I$h!snW@fw)>zTHZ@n~TgJmHc2ZT;j1*1s zm+Y4tG6>;@ENwI7SHgi;I{w%Dp47Ke*>-);7k+%|jn{s%@{@&!KZ3;OIXRW%ITR&$ zZVDL6bF|*@{B{+%&2tqy%CD-ukIDZL5-HjbIN>oKEhtAx%XSPZ%%|$^^2?$bBbRT2{wJF(h*yxDKhhC?-wf#4LK>FurAhf*}gh)aUfoJ29 zZ}r!HuI1+fckAL&q-(0acT0n9TPNoddI#KT>$Y_Pr#m{=X~@vMHCbSQK+v{188i|h zAEfnPm4Cb`7wMBzKu`uCbK)Lr#2n$u4H?dPy_b$3UzOjx$5$I065n{;)Utr|{0E*X+;S1HS3DRlRQ7NqDQ zz{pb#opgv%@AX^V%d4wWGX$0-N+Q}OR3b&YASM>L*tns^+O6KYrA1`-=>Sn|0nUog zWb9Y{_J_lSiCSLtJN}0M4KIPeKc(S$i%ATfiVc}zq3$(#oO)TRRL0`LQ<7!zl$Z{r zOe>cgep>~rZBMJqV**Q^6EL{8EE5c|&3*HyKmE7g{Ifs%^KbseU;HIiwFfp3pga)N zg(s#jr~$Pdy@3uo`hS#lI*&_UHMvO90Z35!D>8ze(Lo^D4&uC9R#bcx=U)=c zlw73$xdVzFa?Q+z5`ADqe<<%>`cfI;;8Bx+WdmsmrvB3cHV$e!!ZFf(gw}TFv{qBAYNTv6tG%xU{Xcj5j z4j5is@ER@gve!%>!pIgRDcT82>9C;cVufDyru;%h?Jy|8C84Jk29c@p&r@J!T1>~C zN(q$c^2!a+t=vSLCgP0q{m`M>WSCX$Kgg)>^5L!-{_;W~^F}#2yd#mPxnL(z3bG*S7ZoUp zii**58N(O8v4FI=SUoA`wd5toK9*zKiAGtj?Qfw#^V8tYatyZF0WM*7rZz*(&i22+9qMlPKY$6L=eyJWUU1Q0 zlh9qF4LN!+J#yh zr#=O`TKUjwu04(fVY&39^22bK{{J+Nq%4Q3+W{0{6!=%Yt(Bk=w&edaaR7B3<+L5L zZfNYw2_4bl!dJu4(#9v`B1QK?3&&)z+Vs|?Uy>R7c;>?MR^N@Uyg@)$#vn``ErX~@ zCTZVbsT5H}keTC(2@Qbiv~VyKBq= z(%}f~-W@Q_z7T}|H)K|;(VlMmYn=^G&y6XoARwe=r09Mqk`9f&4rfrX)+2AyP?j-i zQ<7!Uwuu56VWO}RpGAr#7EO*}p=A9jEEKXaEfh)69FnQoo|wrP)>XgNTemgHRtmIdl;zv~EEFXy(G)P$67j3li8KYeTKQ+`>lSUB?7RFL`=pGiI^%5`k#(lBGh1% zL~N%I1qF>M5>vpKA_49YiS0ZACsx3~CbRkyrc-&-c}{79Xs0YX8tbjSDZs&VAXzKe zaPu5{Eyr^xO7PqiFecA|J9y5hj_#He9R{56oK_SpU(G8!RB&os#+y|eGdNL`RA_g)+6`DDAA^q<2j%4gx{O>*?hd&C z$;#!2S-IG~838vl&Y87FyxeIQt~G+7oFJhnAxKlen1TfE5M)gr8y^(i1vrrq%(s?i z=Vb)GjEqeF4jBQ-%BY={5wYGga*=M|NmM*2-7Odx(|74m!ZD_>kkH~(2`JYVA$%`y6^kfNYJYYCnd2&(hD4;Ra z?S+{3lU)!ONJ6z{LJ|}htqEWLvnfrBVvtLh1@@IV<6mq8XUk(k#@tm&ckMrLaF3)f zNcyp)Q%!qVASUpMRim%ZkCM<)2zwj}mg^}Uv!N0;^I+Z0#q7>N>y*w2Q{ zYRFo?Zt^14jx_-0wMTv=QS+nn|8&+7IIL8YYV~!0wfFkjpw|mF$RkP6F(t>?jT9Y% zj_zcDZaLV@5#{R!n+g?`GVFenGSH24owxijP*W|l{_1MK>*+DMJW?&PM_5qt8f}28 zzUeh(xxFlW<^{ANvj?J(F&;a2V>9T=V$vCzqxU*pwdW!sIU)e`n-tv*2|oDTjh@$O zDY-5+I&0o?aPrg%9;({qS%BKk1#60Rd*8h!iWOh5fDGXgDXNmo4!Hz=uG6Z1_k-V7 zdD`6^pg2#p1Usp2O&(A@X$q8#3wE9N0(oDvx$ZX?q;aw)%B#MA@jv~Hvhym3>7H)~ zE3$lMy&;>F;;zLW0F!gho21UfUTy)HT#Xsjds}U_9ziL+Jx#2u91jd=p&=TskC*$s zRuF{4%oYigD=FH>zsOdI+N_V&uch*e4qp~SUuOP#GFfdZ@s)mqMf>`-7aXDTq-ZZ0 zV;!1l^ky9y>#M){0Ba7B_IZeOMjT{1?kRea*?K}yQtmn@fTG=;q+jz&h!^1 z{~bepimj_;?$A|akCBr;(p8VuZ=YCW!9J`!OQ9+wPE(2{PMhmMvRq%ua@~#zP;|(~ zXFC*5w%d-(6fh>=fjjt)${0@-?FWp8t0fWGk-d{G&vOXM@Z1#O;5m>i&;P{DbK|>))C&Plc&;4u;9kHy%fXjnxyj$bav)ij|D7z$ZB5|?0wcER z?&f-<-BSvq!Zv+RwQakApqyPmp(3wF*OWkyd{*63fbIH$!*mJMn%7i)wwpV^wh;k# z%AeNa3rN4%1stBw$ct$8Hd^Js`(R~J-4*9g-GyM&)7+u%`W868?kTxQx9=eT{c_F7 z*6IzvDGS!Tt}0^h;mV@Ag9ab@S-D96YcDh^fRt^GvW|Z>CE9n-01=HKP9yzt4@3-l zX9D((%Vv{~-V|`hp~|AVqa51@LZVm|bef^8olx~cTV&s~`oU4PAPi+(+`8z=TRTNZ z)zqCSr=V)GS5DS6E;Qb1C=#ls?jXra5uF-pmc?A2^&1;OrzP+E-S81rj#o192U}`$w)Y`L6|C?ON5xpjT zyc?kEcD%;wR$A>ncUKmZY8P{H!E5x^2e=sDQ$(>TFG%2(>OZEO=zlR|E;d3jnS?R= z)-WcGKn-J3ormd(&KEQ0V!x#_hB5MQ!Z8ILCxxw+V0?*!KqwsS-NHOW5>UeL=j!HCgg zM=$~;8;rb?4My^Uq#t;t>zz7r>XfmK?yDQ^qP3BxgsVZ2N{1WTSL~3~({`hCP5V(C zlDab#H7T7G9bkr_T$}@iGZwKMYYG_J>Dl8h;0{N9S{|R0i}Z7_XsQzWW4om_qmGQo zYXo_e(FjwfLnDA>HDWHS5q7l6JXAR;Kv6;prhqY}0Nf!39;20{Xs4;le0SDc-)aqA z;|nekmv-&?a1Nwm`)Z)fMAX;4cH5lcF(aEadvrN!Zsdsk-}LX%-4HM=s9*CpH@%iQ z&_aKkKRB6SAPlo7qDzeDsuvZDW1R`iS*X&foqMh^?gbf>u<$Yi;mTe8&y%qaD+ zyCNv)cc(d|V5ZSw(T?nZ*O}X$I(K^9A{~{S{ID@yeYbE^Qx13*pc00?vJN1FEjBpR z`{AmrQ&sIn&bD&^$v|QNsaC-z@O-OKdOh=;sq9E-T3vglkxHNkI@f^;SM!PqmdaUJ zyUHk7`pysnHI&l(&nD$INo0>1p%A2KJ7_%)vn5unG9uTn^u2IPOLZtl9mb$BdG0%X z$gs-EaT98mS7&NlB29=V{M&M1NzfrA-<%+D66eFh{^4q%v^1faZzaY~rnps7w2M3R zOHGWQ?)#nIi=u#^kZ-;&nB+`fLX{1Dx=o`khu&wA+Qr0w6^b)CZf4cOxoJ62|?v2-#deQXqt+k|gYhP;Io9VDcE0*s_7%BoiWYQmtdG~}qEPOrYN@}ayUXiWfu zC@)m2tK^6mQ5a=A_P~h(Fos3{t)QoOt*1LOP42~vUGi3WF{^f?k3jM=aV&*hN|32o z^KHZHC}dWyHF=Qs(6kNX8id+{9g;QYMCkW0TZs?Jcd4*#Dd=7C+CfuZ(BQR_giLC3 zXIG|7xS%DUdHsSnN+TyA7?`{f%`n%EOIb?}c^j1c1{k}Iw&Z&y!h;kz4qFFzMxdQa zar4@k4S;?(8vx~v7m}f3DDJISgK$Gml92OfmKxWwZ}naE~|A|KXagGg#56FwAZn6wV$t4&Q zd7eX1hUcaL2hV|IdG5P;j?tClITTKw+k62|XBx+5fgJQG5t$C7;w_@KahMtn6_Twq z2CffKloKQw35IG@Uef92YlLAK3Rb+TH@WE{TXuXz5e_{#DvwPZ5Zwzn(E}PTGcx(} z9rI2HI(m#jxJ1AJS7)tO4lwrD61LuxneED zg+(N@HQ!kc61LTZBJCF;Eu*ixs7$|T_aZ>>?*yonQLsMfOXx7djqBHAEHIb$GTI1w!P?;_7G}2cBPF32Z^1l=S>_mDNbTnxQc zImOB2jTXqk0#vV?FF-|Vo}99Ey~7HW>U&d?jTBIm>{3mnfHIm0o~k=MCy=aKUCydi zo`cx8%tX!n%QNW4# z;g<7A*}Tl4FC#Nkosk z2xNZs<%5@ahaQ$`_ zxW)BH9s42yCrnp^)a0=0x<1-B&vt0au-%m5P<9|$wtv^ncHC7twnI^Z?WTY+*$&*n z_L@A#I!Mu7fD^VWUJjlNoo6}tGAuXwJ6H}R%ksC}EJw%6u^fsLEH?#=$#UQhmJ@%` z36r8b04FSmDp}8;XE)d~>^6Bj*bOAh?oBtl2@T7!8;TO_HU*5yZr~1f+hG#mgxy5J zCMH)A#L(?Vkd@)QDaOHhAQ{f@{3AE#j|fRQ&O=dx^QM3?IS<^ydHg?vV^XviFrJ*i zTSB*i2ww%8jOBokqQm^FDwlfsOp}p}oF3+OM^KfKk}1U@B_J6oZTrwIC1Ub&Qi7s{ zluQ9*N(s0_N;P?$_5gqr#w%V9o~NI8N#M({+~n_IIgl*NzvpH-%2STzP?TV~DPSne z>9z>cNYQ@a3}r9)tyXgCdUpcGl3=4996{ia(P!oHQ&38Z9sr!kh%sO6w$e`+4E1A> zmJydJ${{WwS#f=Pw77_*<6~^&+S>d<3viL7=nzhvS(oW%Aa5J}X5Cj`?#NEn*j+0` zG&bIbvgC;eSz#hT34orj#*L)t0N7C)R1-{UDNx|g)FOcCP5Je#7v6r z1n<;10JNGE-NPNSO(reW_a?eB?!Dw)m*SFA;6Gl96di_)R~B(y7UUpLuj7TxwDEbT zgeqS*T0d01ZC6eqsJA&jS%o0VD7Et}sOQi^+@OoGA2yuY6k*>!D(UAM&71XdUKEiVji?3|*255_z4c zcU@*Xui_SS#%Qp*Y9C!wle}ytDr1k-hRQqa5lGe^KcBTnY5?;{(LP9&JqGRmh9`Y< zQ*jbyQL}HhsUU_?red=k3a9Gl;Ul$?I+1Qy$=#tf%)|mAMfdZsMEb}z{#;6GW-7!` z6KpkkoQev{GNLjiIYb3ymt2GUxc)&_R5tVJ1o#RmrMyz_*87`$Vx=pubX}gr)X(WjQrQ9DE!U7!du+D@IFTKzA!6CdK@Qlh-30?? zqEPJC>*={r!CmgiY5&(ddTC8QcbwW%udR;T((O$gW=$TY%0TWoe+fwCvnrQEb|)un zQR`l83j{IDl`J!kr1Hwdlcvuz8(-pg4C6iy4V-IFO`Oce*dTdpB0ZtDr) zM8%nxk5!yin&@~neR zr;!>2#wkU2n+DCO1I^`K&1*rhVPc)?uYagR7blJ1v1s0v{1G2f5r#^Nc2UkAx#DsL zPlUHM4xm#(>A=&_5jgxy`n0p5*SMxw(Y@T6Wpj-7I=10JhFB6ZIIYibtiJcNpQ*j+ zdCB9|EQ-b8x))a8kGW)r@f5-9)`UQqTNhvGO|vVb`t6oxQ@#}RDLbD#;b+f_Lu}o*h(qd|4|3#% z2U~}_i+mZ>OnM2e7nhsOcAsUNmd|@eAlND?dXNUtn?WQeCdfCeLZeiA!;eL4cOKB9 zlLNFDOB`=DYHQ>fGmSVwVoJPjf9ZicY1tYUfUH^Q@99kxaC!GkVR zR`SdfpfQ@@q6`^XYH;oHCPN^tG4PJ?ixk~&c)+3r^Tpk1KAtl_D`T7FlPIdFu_>t` zW~dTMN03EHr05~T!GbbbX*nHke0t&qZ_Og6EaXRu9^eiGC@6W6P|qUeWhBZ*iXMiP z#|5Nn8DX~8<)}Y(wPll6*!y(VUiQ2^_1OGc4kQ|}3eIaHN^0>-eb|{_Rri(m-C5Zz zoqRr7yPaq}Jsy!eDXLLn;)20))VNa}g>p7%ZSk3uxa+y4&L$qMjcEp`^1Y`|cO`h# z#P*nh(iu$_m#({zdskOi&#bO~pvum7*|nkMEGUB})W5j% zmS(nl>(bM2%G!yf!#AIj!oiv#;dYfaJHooW)1&sxeJ9=6wCtsk1u62iD(#Z;N(WCZ z5*3)sYOA*F-;+6rL>Y>^5c!U9Qkd+|mhUx4L?0$ZHOW1VB`Lismzr@`LFM3gK5<{g z(E|8k9LtwbCR#N$azv{@veD|-veBwN%!7pCgai@t`QJdk_Gm3MvKxuxqwgO7ED0#~ z$~80Ixu2$hp}~Qzbif@-XS))>iA2?_u0e^$Uv5RPH36oI09hF^nPMDb0+JQe-_MH4 z<~-i19Ot3fE7zEuHwBEzdEgGt*W_`^Lcj^<_sNYOT#F04(CDt`Sq>i9xQ9%d{2eR@ zl41Fw+%lb)1oWa@r06L~w#%iy(K|tq`1Z-?PR@Pqh1utiO`kmV;<4vWzi|54+0)OR zI(G8($+OSDc<$thxf9R7llKky=5oS=qJ;2F0YimHTd;Ie^bm0RWo_wN^XX9=E6Jq& zB$v7WSkc};C*1mJk-@>?hreWjM%q*)op2X<>iD0 zMG0Y<0)`69_Hn=+{I)w*zzM(i%Z>RIbZzJ>Fi6U9-4x;AI*=^aSF>EN2`F_DC*+Q9 zXuA3JzHH#*}jr>2_2A(2Z8(G1Ok|eQe`fdh_yU2C)MpmFGG@D5? z+iC1sjT|uDPh&4V1$alC;8QNY{=U;OOTV8(9mWX>|#|(uF!e(Hm=X zDgr9l$O@K67S^sZs*t{cfnbMR@rM*A<)2ByaWEr*LXe{Eppiv(>v6HlxHhtq6KW-x zp&MDjIL&=nMMiu8!_m@H%U~_3FDaCPW-|2S9Zl9YC?S8M!f*T(Ox1nDU^w zq66Dq6BZP^r2(YP0qFM2MT#b<0XEK5lsSo@*kWB9W61@JHCtY#481Y-Yx3h8a*;mX z0}T5zFl7YYiE{#uPP}>Z%$b|lZmypBn^(U4-FILATN{^G+ky8_|ME}%&7Xhgwev4M zd*qQvKC}AOFZ|cvdb#`dwfEnC?Y%$#dH4O7|MkE6gMar=zW@F2|7}D@c*sTitKF1_ zTuf=h_Tge>*byn(2^E4iR9)o{$vrQTq?6w%1j~G;+V6loDz~N{(Y@q|$;Z3E&WC<$ z0xnE$lRrs<&JH6Iy79O98j{i5d=q4{c{e=+BHvJ|KYE)ld19!8dv_Bpt;vJDp$T~e!ZN5p%9NT>JnX9l^9YLhzLti(s9hv0ojd|$Pimn7VxA=kaCY zIx3G=S#e#lf{xljOjane!KJRH*jc3;gOORm4q`GSE=z&qNNkK9#AJ;37+i7iqim#_ z_i~U7-9c>6cv1oqzAA4>^r!Roe&Yu}_|12|^4~sqXY+^u5jp4c-){&8t?8!xSgaQG zkt%e`Pb!rU z{&%Iq|EUAPMNKYJbl{}?9Tk|{JpmLjofn=<{Z8RVH89S&%;vMH#L!s8_C>()MJxdc zef8#KLT(Er0+QOFyCLU$_q?mVe633@DUga64XD98`uESu}ZoTb!o9gwnLE6zbg(MvejpjgzfdOP5jd5P;Z^%h;msjJB zcB+d(_V#2fd1K}AibZ+7)Rf~Uy9+1Ee3@y0<;(K*z#AEs#q3-TmYDRG zZGUS&a5doxeJ#ZD* z%NPHYr;tPPBv7AQe&tox;lytOj|wV{AfUm4$i(>|&2q3NFR0B-u`&XiQ_!I~(8&kx zcwc)^ZWYpYkRa9T?7^4F^44~PGyk*@Y{@}@@+fAN%um*3 zLDQ_a8G22{Ejb@mzK&32#}whPIHY zSEw62XqNdB%GeAwq6EukY^4U0QR;11+)8~~NXjWS6i%hKZNL;T)Q#JNDc}wv=Wj*lr3KlkLDAY_}C1aKd(_ z=-0*T4dpoSG8{MAJ2(y`%kgD5$6pYVavX<((3&W6L%eyDSK@>3jqN@RI02JhI(J@T zAo&7Iys6&iAIK7-H1$YdLbI}{t(NboH4ypSY3NYN+g$~@-y_#tqvgprM6USW^~?Hz zKYC%^quNdp3Wu)PaXw($y3pu);Uen^^*eM`aeJ%*G*K%GxUw`i(qC*hL zmY?g(vK+0&fr49dBDnFOw$lPXO8&NUfdVdyGnb=mrTS)drgB7BMH*IsJq%VYHB(P#duQ33XF&*)$jWD>9eSVnrK4 zuw$$a6_H!KxL{%aqUL(KIMtp$FdUFAYn;l}qjT14v(v7M9*7j}HM!3<+HJj%&J048 z*o$QX*z2Hx?BJ1gUt94q?qB~{uQ{~)eac|$I`F~?5fzMGL1IJtV`NwTPK$UUNk{<8 z!4OE%b_ke2kheZ>VR0Y)jiNU`pd8NUDS1poNzr|PssH@1#^HqgPueK&1LPc2wMQwb z{L=zEDiT3p&U|VOc~Fen1f&j$NEemJ}Va~dXyp={b$zg z%`}?p9;=Zz;-kY-T`5-f1-1;ym%-%IDSkVtWKD8TM`M(Q9?Gh}K8rnP*1hI6%ifFG zanX|{NunxhLG^T}HQki+b!Cf^T86Rmov4&Fuc3_Q zRs0A2uovFNd`QS}7(kSc=6xT2GQl$8n^RMJiiH-TxQZre(phg^v^GdrOxhDU5Wyjv zh`WSu`Bo&|Ci;Fg2(QVpTTO4c>$)Vn7P{*6+2q5NdM*aNPN%J?%l&d)l39}TZ1`1k zH$@6sEXqaM6C!76wM3AzFwzLJF6&d9>q%?u$q|ag&|_mrXqanFNb;hgTZ&2QJ#TYU zO3W;LIVK2dNs1n#7?fPkvdXlPKEf^bYdH}W+n*+mmpszIj_i?`Rv$~PZ^;hnjikcG zy|f&6yCFwguW!ljkZwI_%SQ5qqS%)zif{|VqDyf&>m~0^*=9G;u(ro6WokjiX1gT& zGG#wgXU*YEa753@MT#DVlk|^9D})PObv$v*%Xs6%h=whR4+>?Epp={-i>1s*OjhKz zUGlvE%QTAFrq*o7+sSWAT``P&_lXCo`)hJ+o{|5lq%QZ$Gjxm;?V!!XiS@R>!P?8j zXVm0J+jqJn)I1(vt6hZ*I!!&2YUC}S@FsCBrW02UEcQhSme6x;FyI@~F;jLzbkXlD zHCleZ%WH{SuyKfxjQ?I%QcY-fsX|a)+DVEgVJ7~|ip%XcXh0x{-_T$6+O6)KFFK%O z80HS`Ym~F8Y_ove7GSILT^j{v9W1yRy5(z$9KR) zdN=7y+AY;l&^JCJr( let mut new_child_map = HashMap::new(); let mut node_changed_map = Vec::new(); + // Tracks whether any stale default-valued properties were removed from + // project nodes. If so, we must reserialize even if + // project_node_should_reserialize wouldn't otherwise detect a change + // (it only compares node properties forward, not in reverse). + let mut removed_stale_properties = false; let mut node_queue = VecDeque::with_capacity(1); node_queue.push_back((&mut project.tree, old_inst, snapshot.new_inst())); @@ -402,10 +407,12 @@ pub fn syncback_project<'sync>( // We only want to set properties if it needs it. if !middleware.handles_own_properties() { - project_node_property_syncback_path(snapshot, new_inst, node); + removed_stale_properties |= + project_node_property_syncback_path(snapshot, new_inst, node); } } else { - project_node_property_syncback_no_path(snapshot, new_inst, node); + removed_stale_properties |= + project_node_property_syncback_no_path(snapshot, new_inst, node); } for child_ref in new_inst.children() { @@ -507,12 +514,18 @@ pub fn syncback_project<'sync>( } let mut fs_snapshot = FsSnapshot::new(); - for (node_properties, node_attributes, old_inst) in node_changed_map { - if project_node_should_reserialize(node_properties, node_attributes, old_inst)? { - fs_snapshot.add_file(project_path, serde_json::to_vec_pretty(&project)?); - break; + let mut needs_reserialize = removed_stale_properties; + if !needs_reserialize { + for (node_properties, node_attributes, old_inst) in node_changed_map { + if project_node_should_reserialize(node_properties, node_attributes, old_inst)? { + needs_reserialize = true; + break; + } } } + if needs_reserialize { + fs_snapshot.add_file(project_path, serde_json::to_vec_pretty(&project)?); + } Ok(SyncbackReturn { fs_snapshot, @@ -521,15 +534,18 @@ pub fn syncback_project<'sync>( }) } +/// Syncs properties from the new instance into the project node. +/// Returns `true` if any stale properties were removed (i.e. properties +/// that existed in the project node but are now at their engine default). fn project_node_property_syncback( _snapshot: &SyncbackSnapshot, filtered_properties: UstrMap<&Variant>, new_inst: &Instance, node: &mut ProjectNode, -) { +) -> bool { let properties = &mut node.properties; let mut attributes = BTreeMap::new(); - for (name, value) in filtered_properties { + for (&name, &value) in &filtered_properties { match value { Variant::Attributes(attrs) => { for (attr_name, attr_value) in attrs.iter() { @@ -552,14 +568,48 @@ fn project_node_property_syncback( } } } + + // Remove stale properties: entries that exist in the project node's + // $properties but are no longer in the filtered (non-default) properties + // from the instance. This handles the case where Studio resets a property + // to its engine default — filter_properties won't include it, so we need + // to clean up the now-stale project entry. + let class_data = rbx_reflection_database::get() + .ok() + .and_then(|db| db.classes.get(new_inst.class.as_str())); + let len_before = properties.len(); + properties.retain(|prop_name, _| { + if filtered_properties.contains_key(prop_name) { + return true; + } + // Only remove if the property has a known default value in the + // reflection database. If there's no default, the property might be + // absent from the instance for other reasons (e.g. unknown property), + // so we conservatively keep it. + if let Some(data) = &class_data { + if data.default_properties.contains_key(prop_name.as_str()) { + log::debug!( + "Removing stale property '{}' from project node for class '{}': \ + value has been reset to engine default", + prop_name, + new_inst.class + ); + return false; + } + } + true + }); + let removed_stale = properties.len() < len_before; + node.attributes = attributes; + removed_stale } fn project_node_property_syncback_path( snapshot: &SyncbackSnapshot, new_inst: &Instance, node: &mut ProjectNode, -) { +) -> bool { let filtered_properties = snapshot .get_path_filtered_properties(new_inst.referent()) .unwrap(); @@ -570,7 +620,7 @@ fn project_node_property_syncback_no_path( snapshot: &SyncbackSnapshot, new_inst: &Instance, node: &mut ProjectNode, -) { +) -> bool { let filtered_properties = filter_properties(snapshot.project(), new_inst); project_node_property_syncback(snapshot, filtered_properties, new_inst, node) } diff --git a/tests/tests/syncback.rs b/tests/tests/syncback.rs index 31553496..cffccccb 100644 --- a/tests/tests/syncback.rs +++ b/tests/tests/syncback.rs @@ -86,4 +86,7 @@ syncback_tests! { sync_rules => ["src/module.modulescript", "src/text.text"], // Ensures that the `syncUnscriptable` setting works unscriptable_properties => ["default.project.json"], + // Ensures that syncback correctly removes default values from projects rather + // than leaving an incorrect value. + project_default_properties_remove => ["default.project.json"], } From 16633e3c658e9b94edaffa3a80cca46268c39b5c Mon Sep 17 00:00:00 2001 From: AK-Khan02 Date: Wed, 10 Jun 2026 21:48:33 -0400 Subject: [PATCH 1494/1504] Return 400 for missing /api/serialize IDs (#1272) --- CHANGELOG.md | 2 ++ src/web/api.rs | 2 +- tests/rojo_test/serve_util.rs | 10 ++++------ tests/tests/serve.rs | 36 +++++++++++++++++++++++++++++------ 4 files changed, 37 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00524693..339c0c6e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ Making a new release? Simply add the new header with the version and date undern * Fixed the sync fallback scrambling sibling order; replacements are now re-parented ancestors-first and in their original child order. ([#1265]) * Instances that share a name and class are now robustly matched on resync by comparing their properties, instead of relying on child order alone. ([#1266]) * Rojo now reports a clear error instead of panicking in several cases, including when the `serve` port is already in use, when a synced file is read-only or locked, when the filesystem watcher can't be created, and when the working directory is inaccessible. ([#1267]) +* Fixed `/api/serialize` returning success when a requested instance ID is missing from the serve session tree. ([#1272]) * `rojo serve` now validates the `Host`/`Origin` headers to protect the local/private server against DNS rebinding, gates `/api/open` to local clients, and warns when bound to a network-reachable address. The accepted hosts can be extended with the `--allowed-hosts` option or a project's `serveAllowedHosts` field, for example to reach a network-exposed server by hostname. ([#1270]) * Fixed syncback not removing stale `$properties` entries when Studio resets a property to its engine default. ([#1244]) @@ -60,6 +61,7 @@ Making a new release? Simply add the new header with the version and date undern [#1265]: https://github.com/rojo-rbx/rojo/pull/1265 [#1266]: https://github.com/rojo-rbx/rojo/pull/1266 [#1267]: https://github.com/rojo-rbx/rojo/pull/1267 +[#1272]: https://github.com/rojo-rbx/rojo/pull/1272 [#1270]: https://github.com/rojo-rbx/rojo/pull/1270 [#1244]: https://github.com/rojo-rbx/rojo/pull/1244 diff --git a/src/web/api.rs b/src/web/api.rs index 2875f2aa..4fd21c0a 100644 --- a/src/web/api.rs +++ b/src/web/api.rs @@ -276,7 +276,7 @@ impl ApiService { response_dom.transfer_within(child_ref, object_value); } else { - msgpack( + return msgpack( ErrorResponse::bad_request(format!("provided id {id} is not in the tree")), StatusCode::BAD_REQUEST, ); diff --git a/tests/rojo_test/serve_util.rs b/tests/rojo_test/serve_util.rs index 4a817a8a..458743e0 100644 --- a/tests/rojo_test/serve_util.rs +++ b/tests/rojo_test/serve_util.rs @@ -228,11 +228,11 @@ impl TestServeSession { } } - pub fn get_api_serialize( + pub fn post_api_serialize( &self, ids: &[Ref], session_id: SessionId, - ) -> Result { + ) -> Result { let client = reqwest::blocking::Client::new(); let url = format!("http://localhost:{}/api/serialize", self.port); let body = serialize_msgpack(&SerializeRequest { @@ -241,9 +241,7 @@ impl TestServeSession { }) .unwrap(); - let body = client.post(url).body(body).send()?.bytes()?; - - Ok(deserialize_msgpack(&body).expect("Server returned malformed response")) + client.post(url).body(body).send() } /// Sends a GET to `/api/rojo` with the given extra request headers and @@ -291,7 +289,7 @@ fn serialize_msgpack(value: T) -> Result, rmp_serde::encod Ok(serialized) } -fn deserialize_msgpack<'a, T: Deserialize<'a>>( +pub fn deserialize_msgpack<'a, T: Deserialize<'a>>( input: &'a [u8], ) -> Result { let mut deserializer = rmp_serde::Deserializer::new(input).with_human_readable(); diff --git a/tests/tests/serve.rs b/tests/tests/serve.rs index 490c13db..0d6f75cc 100644 --- a/tests/tests/serve.rs +++ b/tests/tests/serve.rs @@ -1,14 +1,16 @@ use std::fs; use insta::{assert_snapshot, assert_yaml_snapshot, with_settings}; +use rbx_dom_weak::types::Ref; +use reqwest::StatusCode; use tempfile::tempdir; use crate::rojo_test::{ internable::InternAndRedact, - serve_util::{run_serve_test, serialize_to_xml_model}, + serve_util::{deserialize_msgpack, run_serve_test, serialize_to_xml_model}, }; -use librojo::web_api::SocketPacketType; +use librojo::web_api::{SerializeResponse, SocketPacketType}; #[test] fn rejects_dns_rebinding_requests() { @@ -713,9 +715,13 @@ fn meshpart_with_id() { .find(|(_, inst)| inst.class_name == "ObjectValue") .unwrap(); - let serialize_response = session - .get_api_serialize(&[*meshpart, *objectvalue], info.session_id) + let body = session + .post_api_serialize(&[*meshpart, *objectvalue], info.session_id) + .unwrap() + .bytes() .unwrap(); + let serialize_response: SerializeResponse = + deserialize_msgpack(&body).expect("Server returned malformed response"); // We don't assert a snapshot on the SerializeResponse because the model includes the // Refs from the DOM as names, which means it will obviously be different every time @@ -727,6 +733,20 @@ fn meshpart_with_id() { }); } +#[test] +fn serialize_missing_id() { + run_serve_test("empty", |session, _| { + let info = session.get_api_rojo().unwrap(); + let missing_id = Ref::new(); + + let response = session + .post_api_serialize(&[missing_id], info.session_id) + .unwrap(); + + assert_eq!(response.status(), StatusCode::BAD_REQUEST); + }); +} + #[test] fn forced_parent() { run_serve_test("forced_parent", |session, mut redactions| { @@ -741,9 +761,13 @@ fn forced_parent() { read_response.intern_and_redact(&mut redactions, root_id) ); - let serialize_response = session - .get_api_serialize(&[root_id], info.session_id) + let body = session + .post_api_serialize(&[root_id], info.session_id) + .unwrap() + .bytes() .unwrap(); + let serialize_response: SerializeResponse = + deserialize_msgpack(&body).expect("Server returned malformed response"); assert_eq!(serialize_response.session_id, info.session_id); From bcadc97de27ab3800e915abcb72c6c7a3c30f363 Mon Sep 17 00:00:00 2001 From: Micah Date: Wed, 1 Jul 2026 17:59:58 -0700 Subject: [PATCH 1495/1504] Release v7.7.0 (#1286) --- CHANGELOG.md | 2 + Cargo.lock | 108 +- Cargo.toml | 16 +- crates/memofs/CHANGELOG.md | 2 + crates/memofs/Cargo.toml | 2 +- plugin/Version.txt | 2 +- plugin/rbx_dom_lua/customProperties.lua | 6 +- plugin/rbx_dom_lua/database.json | 10642 +++++++++++++--- ...roperties_remove-default.project.json.snap | 28 +- 9 files changed, 9168 insertions(+), 1640 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 339c0c6e..d1d007cf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,8 @@ Making a new release? Simply add the new header with the version and date undern ## Unreleased +## [7.7.0] (July 1st, 2026) + * `inf` and `nan` values in properties are now synced ([#1176]) * Fixed a bug caused by having reference properties (such as `ObjectValue.Value`) that point to an Instance not included in syncback. ([#1179]) * Fixed instance replacement fallback failing when too many instances needed to be replaced. ([#1192]) diff --git a/Cargo.lock b/Cargo.lock index 0ffd1266..93e5fda4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -437,11 +437,11 @@ dependencies = [ [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ - "dirs-sys 0.4.1", + "dirs-sys 0.5.0", ] [[package]] @@ -451,20 +451,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", - "redox_users", + "redox_users 0.4.6", "winapi 0.3.9", ] [[package]] name = "dirs-sys" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" dependencies = [ "libc", "option-ext", - "redox_users", - "windows-sys 0.48.0", + "redox_users 0.5.2", + "windows-sys 0.61.2", ] [[package]] @@ -1283,9 +1283,9 @@ dependencies = [ [[package]] name = "lz4_flex" -version = "0.11.5" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08ab2867e3eeeca90e844d1940eab391c9dc5228783db2ed999acbc0a9ed375a" +checksum = "7ef0d4ed8669f8f8826eb00dc878084aa8f253506c4fd5e8f58f5bce72ddb97e" dependencies = [ "twox-hash", ] @@ -1313,7 +1313,7 @@ checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" [[package]] name = "memofs" -version = "0.3.1" +version = "0.4.0" dependencies = [ "crossbeam-channel", "fs-err", @@ -1799,9 +1799,9 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "2.0.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95e2b4a187679aa3d169ed50ed5eedbf26383459fec83bf1232c2934b35b24de" +checksum = "d0a6f15a595fab79d15d50799335543ac5b97618c31ad3d0c93e2713a8bf8d34" dependencies = [ "ahash", "log", @@ -1811,15 +1811,15 @@ dependencies = [ "rbx_reflection", "rbx_reflection_database", "serde", - "thiserror", + "thiserror 1.0.69", "zstd", ] [[package]] name = "rbx_dom_weak" -version = "4.1.0" +version = "4.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a5c48c2605913fbb1986bceb3e18ef9f12eadedb7edd62bf9fb03447b57c46" +checksum = "63614f84aae649ff71ef6e693d4fc9e2184c6ef55852d48a29685ebd0470114f" dependencies = [ "ahash", "rbx_types", @@ -1829,22 +1829,22 @@ dependencies = [ [[package]] name = "rbx_reflection" -version = "6.1.0" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84f635e79d5d710c82e9049faa57d32945e76a6b041280dc6274f732c0dd78dc" +checksum = "1f53e5c4cf136060f7c514bd4d6f02436a57e36754c544965a7840123bc662d7" dependencies = [ "rbx_types", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "rbx_reflection_database" -version = "2.0.2+roblox-700" +version = "3.0.0+roblox-728" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de2753b896d08d74316d8b89fbeb2470ebd3986404ebba82fa85fcc0330955cf" +checksum = "3f5dd357c4c95d43e12283b9065b8b7b41788219db7a0f3a77a6e111f51522e6" dependencies = [ - "dirs 5.0.1", + "dirs 6.0.0", "log", "rbx_reflection", "rmp-serde", @@ -1863,14 +1863,14 @@ dependencies = [ "lazy_static", "rand", "serde", - "thiserror", + "thiserror 1.0.69", ] [[package]] name = "rbx_xml" -version = "2.0.1" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cbaf53b44c9cc0fad1e5dc8ac63fb32fa0ecaa26d32b269cebe4dca8b7b4de" +checksum = "f2e38c283450c4874262c61e68f70f037c9394a08b36fd59468657a4d8761e5e" dependencies = [ "ahash", "base64 0.13.1", @@ -1898,7 +1898,18 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom 0.2.16", "libredox", - "thiserror", + "thiserror 1.0.69", +] + +[[package]] +name = "redox_users" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +dependencies = [ + "getrandom 0.2.16", + "libredox", + "thiserror 2.0.18", ] [[package]] @@ -2038,13 +2049,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "743bb8c693a387f1ae8d2026d82d8b0c175cc4777b97c1f7b12fdb3be595bb13" dependencies = [ "dirs 2.0.2", - "thiserror", + "thiserror 1.0.69", "winreg 0.6.2", ] [[package]] name = "rojo" -version = "7.7.0-rc.1" +version = "7.7.0" dependencies = [ "anyhow", "backtrace", @@ -2096,7 +2107,7 @@ dependencies = [ "strum", "tempfile", "termcolor", - "thiserror", + "thiserror 1.0.69", "tokio", "toml", "uuid", @@ -2528,7 +2539,16 @@ version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ - "thiserror-impl", + "thiserror-impl 1.0.69", +] + +[[package]] +name = "thiserror" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" +dependencies = [ + "thiserror-impl 2.0.18", ] [[package]] @@ -2542,6 +2562,17 @@ dependencies = [ "syn 2.0.111", ] +[[package]] +name = "thiserror-impl" +version = "2.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" +dependencies = [ + "proc-macro2 1.0.103", + "quote 1.0.42", + "syn 2.0.111", +] + [[package]] name = "thread_local" version = "1.1.9" @@ -2737,7 +2768,7 @@ dependencies = [ "log", "rand", "sha1", - "thiserror", + "thiserror 1.0.69", "url", "utf-8", ] @@ -3415,10 +3446,19 @@ dependencies = [ ] [[package]] -name = "xml-rs" -version = "0.8.28" +name = "xml" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ae8337f8a065cfc972643663ea4279e04e7256de865aa66fe25cec5fb912d3f" +checksum = "636f85e5ca6488e96401b61eb7de54f4e44755c988af0f52cf90230c312a1a89" + +[[package]] +name = "xml-rs" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3a56132a0d6ecbe77352edc10232f788fc4ceefefff4cab784a98e0e16b6b51" +dependencies = [ + "xml", +] [[package]] name = "yaml-rust" diff --git a/Cargo.toml b/Cargo.toml index edf211a1..06bb4811 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "7.7.0-rc.1" +version = "7.7.0" rust-version = "1.88" authors = [ "Lucien Greathouse ", @@ -46,7 +46,7 @@ name = "build" harness = false [dependencies] -memofs = { version = "0.3.1", path = "crates/memofs" } +memofs = { version = "0.4.0", path = "crates/memofs" } # These dependencies can be uncommented when working on rbx-dom simultaneously # rbx_binary = { path = "../rbx-dom/rbx_binary", features = [ @@ -57,11 +57,11 @@ memofs = { version = "0.3.1", path = "crates/memofs" } # rbx_reflection_database = { path = "../rbx-dom/rbx_reflection_database" } # rbx_xml = { path = "../rbx-dom/rbx_xml" } -rbx_binary = { version = "2.0.1", features = ["unstable_text_format"] } -rbx_dom_weak = "4.1.0" -rbx_reflection = "6.1.0" -rbx_reflection_database = "2.0.2" -rbx_xml = "2.0.1" +rbx_binary = { version = "3.0.0", features = ["unstable_text_format"] } +rbx_dom_weak = "4.2.0" +rbx_reflection = "7.0.0" +rbx_reflection_database = "3.0.0" +rbx_xml = "3.0.0" anyhow = "1.0.80" backtrace = "0.3.69" @@ -112,7 +112,7 @@ serde_bytes = "0.11.19" winreg = "0.10.1" [build-dependencies] -memofs = { version = "0.3.0", path = "crates/memofs" } +memofs = { version = "0.4.0", path = "crates/memofs" } embed-resource = "1.8.0" anyhow = "1.0.80" diff --git a/crates/memofs/CHANGELOG.md b/crates/memofs/CHANGELOG.md index ec0b71f0..3e841b2b 100644 --- a/crates/memofs/CHANGELOG.md +++ b/crates/memofs/CHANGELOG.md @@ -1,6 +1,8 @@ # memofs Changelog ## Unreleased Changes + +# 0.4.0 (2026-07-01) * Added `Vfs::canonicalize`. [#1201] * **Breaking:** `StdBackend::new` and `Vfs::new_default` now return `io::Result`, so a failure to create the filesystem watcher is reported as an error instead of panicking. The `Default` implementation for `StdBackend` has been removed as a result. [#1267] diff --git a/crates/memofs/Cargo.toml b/crates/memofs/Cargo.toml index d1d8cc5e..f87378e5 100644 --- a/crates/memofs/Cargo.toml +++ b/crates/memofs/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "memofs" description = "Virtual filesystem with configurable backends." -version = "0.3.1" +version = "0.4.0" authors = [ "Lucien Greathouse ", "Micah Reid ", diff --git a/plugin/Version.txt b/plugin/Version.txt index baee60f4..d21b198c 100644 --- a/plugin/Version.txt +++ b/plugin/Version.txt @@ -1 +1 @@ -7.7.0-rc.1 \ No newline at end of file +7.7.0 \ No newline at end of file diff --git a/plugin/rbx_dom_lua/customProperties.lua b/plugin/rbx_dom_lua/customProperties.lua index a5b96f99..0df57c32 100644 --- a/plugin/rbx_dom_lua/customProperties.lua +++ b/plugin/rbx_dom_lua/customProperties.lua @@ -209,7 +209,7 @@ return { }, }, StyleRule = { - PropertiesSerialize = { + Properties = { read = function(instance: StyleRule) return true, instance:GetProperties() end, @@ -220,9 +220,7 @@ return { local existing = instance:GetProperties() - for itemName, itemValue in pairs(value) do - instance:SetProperty(itemName, itemValue) - end + instance:SetProperties(value) for existingItemName in pairs(existing) do if value[existingItemName] == nil then diff --git a/plugin/rbx_dom_lua/database.json b/plugin/rbx_dom_lua/database.json index 1856f932..6a93959a 100644 --- a/plugin/rbx_dom_lua/database.json +++ b/plugin/rbx_dom_lua/database.json @@ -1,9 +1,9 @@ { "Version": [ 0, - 700, + 728, 0, - 7000935 + 7280895 ], "Classes": { "Accessory": { @@ -170,7 +170,9 @@ "DataType": { "Value": "Float32" }, - "Tags": [], + "Tags": [ + "Deprecated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -605,6 +607,24 @@ "Value": "ContentId" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "FallbackImageContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "FallbackImageContent": { + "Name": "FallbackImageContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -1544,6 +1564,19 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "AnimationContent": { + "Name": "AnimationContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "AnimationId": { "Name": "AnimationId", "Scriptability": "ReadWrite", @@ -1553,14 +1586,19 @@ "Tags": [], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": { + "Migrate": { + "To": "AnimationContent", + "Migration": "ContentIdToContent" + } + } } } } }, "DefaultProperties": { - "AnimationId": { - "ContentId": "" + "AnimationContent": { + "Content": "None" }, "Archivable": { "Bool": true @@ -1627,6 +1665,22 @@ } } }, + "Length": { + "Name": "Length", + "Scriptability": "Read", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Loop": { "Name": "Loop", "Scriptability": "ReadWrite", @@ -1689,11 +1743,35 @@ }, "AnimationConstraint": { "Name": "AnimationConstraint", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "Constraint", "Properties": { + "AngularDamping": { + "Name": "AngularDamping", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AngularStrength": { + "Name": "AngularStrength", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "C0": { "Name": "C0", "Scriptability": "Read", @@ -1730,6 +1808,19 @@ } } }, + "EnableSkinning": { + "Name": "EnableSkinning", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "IsKinematic": { "Name": "IsKinematic", "Scriptability": "ReadWrite", @@ -1743,6 +1834,32 @@ } } }, + "LinearDamping": { + "Name": "LinearDamping", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LinearStrength": { + "Name": "LinearStrength", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MaxForce": { "Name": "MaxForce", "Scriptability": "ReadWrite", @@ -1820,6 +1937,12 @@ } }, "DefaultProperties": { + "AngularDamping": { + "Float32": 1.0 + }, + "AngularStrength": { + "Float32": 1.0 + }, "Archivable": { "Bool": true }, @@ -1841,6 +1964,12 @@ "IsKinematic": { "Bool": false }, + "LinearDamping": { + "Float32": 1.0 + }, + "LinearStrength": { + "Float32": 1.0 + }, "MaxForce": { "Float32": 10000.0 }, @@ -2070,6 +2199,19 @@ } } }, + "NodeId": { + "Name": "NodeId", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "NodeType": { "Name": "NodeType", "Scriptability": "ReadWrite", @@ -2100,6 +2242,9 @@ "InputPinData": { "BinaryString": "AQAAAAAAAAA=" }, + "NodeId": { + "String": "" + }, "NodeType": { "Enum": 0 }, @@ -2122,6 +2267,22 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "Generic": { + "Name": "Generic", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "label": { "Name": "label", "Scriptability": "None", @@ -2229,6 +2390,9 @@ "Capabilities": { "SecurityCapabilities": 0 }, + "Generic": { + "BinaryString": "/////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIA/AAAAAAAAAAAAAAAAAA==" + }, "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, @@ -2245,7 +2409,7 @@ "UniqueId": "00000000000000000000000000000000" }, "label": { - "BinaryString": "AQAAAAEAAAAAAAAA" + "BinaryString": "AgAAAAEAAAAAAAAA" }, "name": { "BinaryString": "AQAAAAEAAAAAAAAA" @@ -2254,13 +2418,13 @@ "BinaryString": "AQAAAAEAAAAAAA==" }, "postTransform": { - "BinaryString": "AQAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=" + "BinaryString": "AgAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=" }, "preTransform": { - "BinaryString": "AQAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=" + "BinaryString": "AgAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=" }, "transform": { - "BinaryString": "AQAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=" + "BinaryString": "AgAAAAEAAAAAAIA/AAAAAAAAAAAAAAAAAACAPwAAAAAAAAAAAAAAAAAAgD8AAAAAAAAAAAAAAAA=" } } }, @@ -2548,6 +2712,134 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "AnimationId0": { + "Name": "AnimationId0", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AnimationId1": { + "Name": "AnimationId1", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AnimationId2": { + "Name": "AnimationId2", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AnimationId3": { + "Name": "AnimationId3", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AnimationId4": { + "Name": "AnimationId4", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AnimationId5": { + "Name": "AnimationId5", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AnimationId6": { + "Name": "AnimationId6", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AnimationId7": { + "Name": "AnimationId7", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "EvaluationThrottled": { "Name": "EvaluationThrottled", "Scriptability": "Read", @@ -2564,6 +2856,518 @@ } } }, + "FadeTime0": { + "Name": "FadeTime0", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FadeTime1": { + "Name": "FadeTime1", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FadeTime2": { + "Name": "FadeTime2", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FadeTime3": { + "Name": "FadeTime3", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FadeTime4": { + "Name": "FadeTime4", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FadeTime5": { + "Name": "FadeTime5", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FadeTime6": { + "Name": "FadeTime6", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FadeTime7": { + "Name": "FadeTime7", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPlaying0": { + "Name": "IsPlaying0", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPlaying1": { + "Name": "IsPlaying1", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPlaying2": { + "Name": "IsPlaying2", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPlaying3": { + "Name": "IsPlaying3", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPlaying4": { + "Name": "IsPlaying4", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPlaying5": { + "Name": "IsPlaying5", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPlaying6": { + "Name": "IsPlaying6", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsPlaying7": { + "Name": "IsPlaying7", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Looped0": { + "Name": "Looped0", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Looped1": { + "Name": "Looped1", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Looped2": { + "Name": "Looped2", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Looped3": { + "Name": "Looped3", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Looped4": { + "Name": "Looped4", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Looped5": { + "Name": "Looped5", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Looped6": { + "Name": "Looped6", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Looped7": { + "Name": "Looped7", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlaybackSpeed0": { + "Name": "PlaybackSpeed0", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlaybackSpeed1": { + "Name": "PlaybackSpeed1", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlaybackSpeed2": { + "Name": "PlaybackSpeed2", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlaybackSpeed3": { + "Name": "PlaybackSpeed3", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlaybackSpeed4": { + "Name": "PlaybackSpeed4", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlaybackSpeed5": { + "Name": "PlaybackSpeed5", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlaybackSpeed6": { + "Name": "PlaybackSpeed6", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlaybackSpeed7": { + "Name": "PlaybackSpeed7", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PreferLodEnabled": { "Name": "PreferLodEnabled", "Scriptability": "ReadWrite", @@ -2577,6 +3381,390 @@ } } }, + "Priority0": { + "Name": "Priority0", + "Scriptability": "None", + "DataType": { + "Enum": "AnimationPriority" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Priority1": { + "Name": "Priority1", + "Scriptability": "None", + "DataType": { + "Enum": "AnimationPriority" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Priority2": { + "Name": "Priority2", + "Scriptability": "None", + "DataType": { + "Enum": "AnimationPriority" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Priority3": { + "Name": "Priority3", + "Scriptability": "None", + "DataType": { + "Enum": "AnimationPriority" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Priority4": { + "Name": "Priority4", + "Scriptability": "None", + "DataType": { + "Enum": "AnimationPriority" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Priority5": { + "Name": "Priority5", + "Scriptability": "None", + "DataType": { + "Enum": "AnimationPriority" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Priority6": { + "Name": "Priority6", + "Scriptability": "None", + "DataType": { + "Enum": "AnimationPriority" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Priority7": { + "Name": "Priority7", + "Scriptability": "None", + "DataType": { + "Enum": "AnimationPriority" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForTimePosition0": { + "Name": "RefStepIdForTimePosition0", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForTimePosition1": { + "Name": "RefStepIdForTimePosition1", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForTimePosition2": { + "Name": "RefStepIdForTimePosition2", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForTimePosition3": { + "Name": "RefStepIdForTimePosition3", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForTimePosition4": { + "Name": "RefStepIdForTimePosition4", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForTimePosition5": { + "Name": "RefStepIdForTimePosition5", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForTimePosition6": { + "Name": "RefStepIdForTimePosition6", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForTimePosition7": { + "Name": "RefStepIdForTimePosition7", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForWeight0": { + "Name": "RefStepIdForWeight0", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForWeight1": { + "Name": "RefStepIdForWeight1", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForWeight2": { + "Name": "RefStepIdForWeight2", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForWeight3": { + "Name": "RefStepIdForWeight3", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForWeight4": { + "Name": "RefStepIdForWeight4", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForWeight5": { + "Name": "RefStepIdForWeight5", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForWeight6": { + "Name": "RefStepIdForWeight6", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RefStepIdForWeight7": { + "Name": "RefStepIdForWeight7", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "RootMotion": { "Name": "RootMotion", "Scriptability": "Read", @@ -2610,6 +3798,134 @@ "Serialization": "DoesNotSerialize" } } + }, + "WeightTarget0": { + "Name": "WeightTarget0", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WeightTarget1": { + "Name": "WeightTarget1", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WeightTarget2": { + "Name": "WeightTarget2", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WeightTarget3": { + "Name": "WeightTarget3", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WeightTarget4": { + "Name": "WeightTarget4", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WeightTarget5": { + "Name": "WeightTarget5", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WeightTarget6": { + "Name": "WeightTarget6", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "WeightTarget7": { + "Name": "WeightTarget7", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -2941,6 +4257,27 @@ } } }, + "AppAgeSignalsService": { + "Name": "AppAgeSignalsService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "AppLifecycleObserverService": { "Name": "AppLifecycleObserverService", "Tags": [ @@ -3375,6 +4712,27 @@ } } }, + "AssetQualityService": { + "Name": "AssetQualityService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "AssetService": { "Name": "AssetService", "Tags": [ @@ -4396,6 +5754,38 @@ } } }, + "EchoCancellation": { + "Name": "EchoCancellation", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GainControl": { + "Name": "GainControl", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "IsReady": { "Name": "IsReady", "Scriptability": "None", @@ -4432,6 +5822,23 @@ "Value": "Bool" }, "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "NoiseSuppression": { + "Name": "NoiseSuppression", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", "NotReplicated" ], "Kind": { @@ -4790,6 +6197,19 @@ } } }, + "DiffractionEnabled": { + "Name": "DiffractionEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SimulationMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DistanceAttenuation": { "Name": "DistanceAttenuation", "Scriptability": "None", @@ -4803,9 +6223,22 @@ } } }, - "PositionOverride": { - "Name": "PositionOverride", - "Scriptability": "None", + "OcclusionEnabled": { + "Name": "OcclusionEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SimulationMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PositionInstance": { + "Name": "PositionInstance", + "Scriptability": "ReadWrite", "DataType": { "Value": "Ref" }, @@ -4816,6 +6249,32 @@ } } }, + "PositionType": { + "Name": "PositionType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "EmitterPositionType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReverbEnabled": { + "Name": "ReverbEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SimulationMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "SimulationFidelity": { "Name": "SimulationFidelity", "Scriptability": "ReadWrite", @@ -4851,12 +6310,24 @@ "Capabilities": { "SecurityCapabilities": 0 }, + "DiffractionEnabled": { + "Enum": 0 + }, "DistanceAttenuation": { "BinaryString": "AA==" }, "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "OcclusionEnabled": { + "Enum": 0 + }, + "PositionType": { + "Enum": 0 + }, + "ReverbEnabled": { + "Enum": 0 + }, "Sandboxed": { "Bool": false }, @@ -5556,6 +7027,19 @@ } } }, + "DiffractionEnabled": { + "Name": "DiffractionEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SimulationMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DistanceAttenuation": { "Name": "DistanceAttenuation", "Scriptability": "None", @@ -5569,9 +7053,22 @@ } } }, - "PositionOverride": { - "Name": "PositionOverride", - "Scriptability": "None", + "OcclusionEnabled": { + "Name": "OcclusionEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SimulationMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PositionInstance": { + "Name": "PositionInstance", + "Scriptability": "ReadWrite", "DataType": { "Value": "Ref" }, @@ -5582,6 +7079,32 @@ } } }, + "PositionType": { + "Name": "PositionType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ListenerPositionType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ReverbEnabled": { + "Name": "ReverbEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "SimulationMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "SimulationFidelity": { "Name": "SimulationFidelity", "Scriptability": "ReadWrite", @@ -5617,12 +7140,24 @@ "Capabilities": { "SecurityCapabilities": 0 }, + "DiffractionEnabled": { + "Enum": 0 + }, "DistanceAttenuation": { "BinaryString": "AA==" }, "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "OcclusionEnabled": { + "Enum": 0 + }, + "PositionType": { + "Enum": 0 + }, + "ReverbEnabled": { + "Enum": 0 + }, "Sandboxed": { "Bool": false }, @@ -5781,13 +7316,31 @@ } } }, + "AssetRepresentation": { + "Name": "AssetRepresentation", + "Scriptability": "None", + "DataType": { + "Enum": "AssetRepresentation" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "AudioContent": { "Name": "AudioContent", "Scriptability": "ReadWrite", "DataType": { "Value": "Content" }, - "Tags": [], + "Tags": [ + "Hidden" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -5820,19 +7373,6 @@ } } }, - "IsMutedForCapture": { - "Name": "IsMutedForCapture", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "IsPlaying": { "Name": "IsPlaying", "Scriptability": "Read", @@ -5979,9 +7519,6 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "IsMutedForCapture": { - "Bool": false - }, "LoopRegion": { "NumberRange": [ 0.0, @@ -6473,6 +8010,21 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "DictationEnabled": { + "Name": "DictationEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Enabled": { "Name": "Enabled", "Scriptability": "ReadWrite", @@ -7282,6 +8834,247 @@ } } }, + "AvatarAbilityRules": { + "Name": "AvatarAbilityRules", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "CharacterControllerMode": { + "Name": "CharacterControllerMode", + "Scriptability": "None", + "DataType": { + "Enum": "AvatarSettingsCharacterControllerMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableClimbing": { + "Name": "EnableClimbing", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableCrouching": { + "Name": "EnableCrouching", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableFallingDown": { + "Name": "EnableFallingDown", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableGettingUp": { + "Name": "EnableGettingUp", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableHolding": { + "Name": "EnableHolding", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableJumping": { + "Name": "EnableJumping", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableReaching": { + "Name": "EnableReaching", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableRunning": { + "Name": "EnableRunning", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableSitting": { + "Name": "EnableSitting", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableSprinting": { + "Name": "EnableSprinting", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableStrafing": { + "Name": "EnableStrafing", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EnableSwimming": { + "Name": "EnableSwimming", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "CharacterControllerMode": { + "Enum": 0 + }, + "EnableClimbing": { + "Bool": true + }, + "EnableCrouching": { + "Bool": true + }, + "EnableFallingDown": { + "Bool": true + }, + "EnableGettingUp": { + "Bool": true + }, + "EnableHolding": { + "Bool": true + }, + "EnableJumping": { + "Bool": true + }, + "EnableReaching": { + "Bool": true + }, + "EnableRunning": { + "Bool": true + }, + "EnableSitting": { + "Bool": true + }, + "EnableSprinting": { + "Bool": true + }, + "EnableStrafing": { + "Bool": true + }, + "EnableSwimming": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "AvatarAccessoryRules": { "Name": "AvatarAccessoryRules", "Tags": [], @@ -7521,6 +9314,19 @@ } } }, + "EnableEmissives": { + "Name": "EnableEmissives", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "EnableSound": { "Name": "EnableSound", "Scriptability": "None", @@ -7638,6 +9444,9 @@ "CustomWaistAccessoryId": { "Int64": 0 }, + "EnableEmissives": { + "Bool": true + }, "EnableSound": { "Bool": true }, @@ -9283,7 +11092,6 @@ "Name": "AvatarEditorService", "Tags": [ "NotCreatable", - "NotReplicated", "Service" ], "Superclass": "Instance", @@ -9530,6 +11338,19 @@ "Tags": [], "Superclass": "Constraint", "Properties": { + "EnableSkinning": { + "Name": "EnableSkinning", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "LimitsEnabled": { "Name": "LimitsEnabled", "Scriptability": "ReadWrite", @@ -9732,6 +11553,40 @@ } } }, + "BaseCoreGuiConfiguration": { + "Name": "BaseCoreGuiConfiguration", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "BaseImportData": { "Name": "BaseImportData", "Tags": [ @@ -10456,22 +12311,6 @@ } } }, - "LocalSimulationValidation": { - "Name": "LocalSimulationValidation", - "Scriptability": "None", - "DataType": { - "Value": "Int32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "LocalTransparencyModifier": { "Name": "LocalTransparencyModifier", "Scriptability": "ReadWrite", @@ -11502,6 +13341,24 @@ "Value": "ContentId" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "TextureContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "TextureContent": { + "Name": "TextureContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -11668,8 +13525,8 @@ "Tags": { "Tags": [] }, - "Texture": { - "ContentId": "" + "TextureContent": { + "Content": "None" }, "TextureLength": { "Float32": 1.0 @@ -15219,6 +17076,9 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "InputSink": { + "Enum": 0 + }, "Interactable": { "Bool": true }, @@ -15427,6 +17287,40 @@ } } }, + "CapturesViewConfiguration": { + "Name": "CapturesViewConfiguration", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "BaseCoreGuiConfiguration", + "Properties": { + "Open": { + "Name": "Open", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "CatalogPages": { "Name": "CatalogPages", "Tags": [ @@ -15490,7 +17384,6 @@ "ChannelSelectorSoundEffect": { "Name": "ChannelSelectorSoundEffect", "Tags": [ - "NotBrowsable", "NotCreatable" ], "Superclass": "CustomSoundEffect", @@ -15821,6 +17714,19 @@ "Tags": [], "Superclass": "CharacterAppearance", "Properties": { + "BaseTextureContent": { + "Name": "BaseTextureContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "BaseTextureId": { "Name": "BaseTextureId", "Scriptability": "ReadWrite", @@ -15830,7 +17736,12 @@ "Tags": [], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": { + "Migrate": { + "To": "BaseTextureContent", + "Migration": "Int64ToContent" + } + } } } }, @@ -15847,6 +17758,19 @@ } } }, + "MeshContent": { + "Name": "MeshContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MeshId": { "Name": "MeshId", "Scriptability": "ReadWrite", @@ -15854,6 +17778,24 @@ "Value": "Int64" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "MeshContent", + "Migration": "Int64ToContent" + } + } + } + } + }, + "OverlayTextureContent": { + "Name": "OverlayTextureContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -15881,8 +17823,8 @@ "Attributes": { "Attributes": {} }, - "BaseTextureId": { - "Int64": 0 + "BaseTextureContent": { + "Content": "None" }, "BodyPart": { "Enum": 0 @@ -15893,8 +17835,8 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "MeshId": { - "Int64": 0 + "MeshContent": { + "Content": "None" }, "OverlayTextureId": { "Int64": 0 @@ -15962,6 +17904,22 @@ "Serialization": "Serializes" } } + }, + "ModerationMode": { + "Name": "ModerationMode", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -16755,27 +18713,6 @@ } } }, - "ChatbotUIService": { - "Name": "ChatbotUIService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "Archivable": { - "Bool": true - }, - "HistoryId": { - "UniqueId": "00000000000000000000000000000000" - }, - "UniqueId": { - "UniqueId": "00000000000000000000000000000000" - } - } - }, "ChorusSoundEffect": { "Name": "ChorusSoundEffect", "Tags": [], @@ -16966,6 +18903,27 @@ } } }, + "ClientStorageService": { + "Name": "ClientStorageService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "ClimbController": { "Name": "ClimbController", "Tags": [], @@ -17106,6 +19064,23 @@ } } }, + "Outfit1Content": { + "Name": "Outfit1Content", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Outfit2": { "Name": "Outfit2", "Scriptability": "None", @@ -17122,6 +19097,23 @@ "Serialization": "DoesNotSerialize" } } + }, + "Outfit2Content": { + "Name": "Outfit2Content", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -17157,6 +19149,27 @@ } } }, + "CloudExecutionService": { + "Name": "CloudExecutionService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "CloudLocalizationTable": { "Name": "CloudLocalizationTable", "Tags": [ @@ -17739,6 +19752,55 @@ } } }, + "CompositeValueCurve": { + "Name": "CompositeValueCurve", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "CurveType": { + "Name": "CurveType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "CompositeValueCurveType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "CurveType": { + "Enum": 2 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "CompressorSoundEffect": { "Name": "CompressorSoundEffect", "Tags": [], @@ -18656,6 +20718,32 @@ } } }, + "LadderSearchHeight": { + "Name": "LadderSearchHeight", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "LadderSearchOffset": { + "Name": "LadderSearchOffset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "SearchDistance": { "Name": "SearchDistance", "Scriptability": "ReadWrite", @@ -18669,6 +20757,19 @@ } } }, + "SensedMaterial": { + "Name": "SensedMaterial", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "Material" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "SensedPart": { "Name": "SensedPart", "Scriptability": "ReadWrite", @@ -18738,16 +20839,25 @@ "HitNormal": { "Vector3": [ 0.0, - 0.0, + 1.0, 0.0 ] }, + "LadderSearchHeight": { + "Float32": 6.0 + }, + "LadderSearchOffset": { + "Float32": 5.0 + }, "Sandboxed": { "Bool": false }, "SearchDistance": { "Float32": 0.0 }, + "SensedMaterial": { + "Enum": 1792 + }, "SensorMode": { "Enum": 0 }, @@ -18805,27 +20915,6 @@ } } }, - "ConversationalAIAcceptanceService": { - "Name": "ConversationalAIAcceptanceService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "Archivable": { - "Bool": true - }, - "HistoryId": { - "UniqueId": "00000000000000000000000000000000" - }, - "UniqueId": { - "UniqueId": "00000000000000000000000000000000" - } - } - }, "CookiesService": { "Name": "CookiesService", "Tags": [ @@ -18912,6 +21001,67 @@ } } }, + "CoreGuiConfiguration": { + "Name": "CoreGuiConfiguration", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "CapturesViewConfiguration": { + "Name": "CapturesViewConfiguration", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlayerListConfiguration": { + "Name": "PlayerListConfiguration", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SelfViewConfiguration": { + "Name": "SelfViewConfiguration", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "CorePackages": { "Name": "CorePackages", "Tags": [ @@ -20332,6 +22482,22 @@ } } }, + "RunService": { + "Name": "RunService", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "VIPServerId": { "Name": "VIPServerId", "Scriptability": "Read", @@ -21907,6 +24073,19 @@ "Tags": [], "Superclass": "FaceInstance", "Properties": { + "AutoLocalize": { + "Name": "AutoLocalize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Color3": { "Name": "Color3", "Scriptability": "ReadWrite", @@ -22037,6 +24216,19 @@ } } }, + "Rotation": { + "Name": "Rotation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "RoughnessMap": { "Name": "RoughnessMap", "Scriptability": "ReadWrite", @@ -22222,6 +24414,9 @@ "Attributes": { "Attributes": {} }, + "AutoLocalize": { + "Bool": true + }, "Capabilities": { "SecurityCapabilities": 0 }, @@ -22244,6 +24439,9 @@ "NormalMapContent": { "Content": "None" }, + "Rotation": { + "Float32": 0.0 + }, "RoughnessMapContent": { "Content": "None" }, @@ -22288,6 +24486,27 @@ } } }, + "DeferredAssetManagerService": { + "Name": "DeferredAssetManagerService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "DepthOfFieldEffect": { "Name": "DepthOfFieldEffect", "Tags": [], @@ -22388,6 +24607,27 @@ } } }, + "DesignFoundationsService": { + "Name": "DesignFoundationsService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "DeviceIdService": { "Name": "DeviceIdService", "Tags": [ @@ -22700,6 +24940,1015 @@ } } }, + "DigitsRigDescription": { + "Name": "DigitsRigDescription", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "Index1": { + "Name": "Index1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Index1TposeAdjustment": { + "Name": "Index1TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Index2": { + "Name": "Index2", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Index2TposeAdjustment": { + "Name": "Index2TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Index3": { + "Name": "Index3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Index3TposeAdjustment": { + "Name": "Index3TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IndexRange": { + "Name": "IndexRange", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IndexSize": { + "Name": "IndexSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Middle1": { + "Name": "Middle1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Middle1TposeAdjustment": { + "Name": "Middle1TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Middle2": { + "Name": "Middle2", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Middle2TposeAdjustment": { + "Name": "Middle2TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Middle3": { + "Name": "Middle3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Middle3TposeAdjustment": { + "Name": "Middle3TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MiddleRange": { + "Name": "MiddleRange", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MiddleSize": { + "Name": "MiddleSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Pinky1": { + "Name": "Pinky1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Pinky1TposeAdjustment": { + "Name": "Pinky1TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Pinky2": { + "Name": "Pinky2", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Pinky2TposeAdjustment": { + "Name": "Pinky2TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Pinky3": { + "Name": "Pinky3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Pinky3TposeAdjustment": { + "Name": "Pinky3TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PinkyRange": { + "Name": "PinkyRange", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PinkySize": { + "Name": "PinkySize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Ring1": { + "Name": "Ring1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Ring1TposeAdjustment": { + "Name": "Ring1TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Ring2": { + "Name": "Ring2", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Ring2TposeAdjustment": { + "Name": "Ring2TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Ring3": { + "Name": "Ring3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Ring3TposeAdjustment": { + "Name": "Ring3TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RingRange": { + "Name": "RingRange", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RingSize": { + "Name": "RingSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Side": { + "Name": "Side", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DigitsRigDescriptionSide" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Thumb1": { + "Name": "Thumb1", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Thumb1TposeAdjustment": { + "Name": "Thumb1TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Thumb2": { + "Name": "Thumb2", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Thumb2TposeAdjustment": { + "Name": "Thumb2TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Thumb3": { + "Name": "Thumb3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Thumb3TposeAdjustment": { + "Name": "Thumb3TposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ThumbRange": { + "Name": "ThumbRange", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ThumbSize": { + "Name": "ThumbSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Index1TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Index2TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Index3TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "IndexRange": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "IndexSize": { + "Float32": 0.0 + }, + "Middle1TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Middle2TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Middle3TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "MiddleRange": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "MiddleSize": { + "Float32": 0.0 + }, + "Pinky1TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Pinky2TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Pinky3TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "PinkyRange": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "PinkySize": { + "Float32": 0.0 + }, + "Ring1TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Ring2TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Ring3TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "RingRange": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "RingSize": { + "Float32": 0.0 + }, + "Sandboxed": { + "Bool": false + }, + "Side": { + "Enum": 0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "Thumb1TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Thumb2TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "Thumb3TposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ThumbRange": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "ThumbSize": { + "Float32": 0.0 + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "DistortionSoundEffect": { "Name": "DistortionSoundEffect", "Tags": [], @@ -23456,7 +26705,7 @@ "Orientation": { "Vector3": [ -0.0, - 179.99998, + 180.0, 90.0 ] }, @@ -24055,21 +27304,6 @@ "Serialization": "Serializes" } } - }, - "SkinningEnabled": { - "Name": "SkinningEnabled", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Deprecated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } } }, "DefaultProperties": {} @@ -24111,26 +27345,6 @@ } } }, - "EmotesPages": { - "Name": "EmotesPages", - "Tags": [ - "NotCreatable", - "NotReplicated" - ], - "Superclass": "InventoryPages", - "Properties": {}, - "DefaultProperties": { - "Archivable": { - "Bool": true - }, - "HistoryId": { - "UniqueId": "00000000000000000000000000000000" - }, - "UniqueId": { - "UniqueId": "00000000000000000000000000000000" - } - } - }, "EncodingService": { "Name": "EncodingService", "Tags": [ @@ -24580,11 +27794,27 @@ "Name": "ExperienceStateRecordingService", "Tags": [ "NotCreatable", - "NotReplicated", "Service" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "IsServerDataModelRecorderActive": { + "Name": "IsServerDataModelRecorderActive", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, "DefaultProperties": { "Archivable": { "Bool": true @@ -25081,6 +28311,22 @@ } } }, + "InternalOverrideFACSData": { + "Name": "InternalOverrideFACSData", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "JawDrop": { "Name": "JawDrop", "Scriptability": "ReadWrite", @@ -25710,6 +28956,9 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "InternalOverrideFACSData": { + "BinaryString": "" + }, "Sandboxed": { "Bool": false }, @@ -26043,11 +29292,45 @@ } } }, + "FileManagerService": { + "Name": "FileManagerService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "FileMesh": { "Name": "FileMesh", "Tags": [], "Superclass": "DataModelMesh", "Properties": { + "MeshContent": { + "Name": "MeshContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MeshId": { "Name": "MeshId", "Scriptability": "ReadWrite", @@ -26055,6 +29338,24 @@ "Value": "ContentId" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "MeshContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "TextureContent": { + "Name": "TextureContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -26070,7 +29371,12 @@ "Tags": [], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": { + "Migrate": { + "To": "TextureContent", + "Migration": "ContentIdToContent" + } + } } } } @@ -26088,8 +29394,8 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "MeshId": { - "ContentId": "" + "MeshContent": { + "Content": "None" }, "Offset": { "Vector3": [ @@ -26114,8 +29420,8 @@ "Tags": { "Tags": [] }, - "TextureId": { - "ContentId": "" + "TextureContent": { + "Content": "None" }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" @@ -26129,6 +29435,26 @@ } } }, + "FileSyncReplicationService": { + "Name": "FileSyncReplicationService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "Fire": { "Name": "Fire", "Tags": [], @@ -27458,6 +30784,9 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "InputSink": { + "Enum": 0 + }, "Interactable": { "Bool": true }, @@ -27824,6 +31153,38 @@ } } }, + "GeneratedFolder": { + "Name": "GeneratedFolder", + "Tags": [], + "Superclass": "Folder", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "GenerationService": { "Name": "GenerationService", "Tags": [ @@ -28218,6 +31579,26 @@ } } }, + "GongService": { + "Name": "GongService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "GroundController": { "Name": "GroundController", "Tags": [], @@ -29396,6 +32777,19 @@ } } }, + "InputSink": { + "Name": "InputSink", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "InputSink" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Interactable": { "Name": "Interactable", "Scriptability": "ReadWrite", @@ -29787,6 +33181,21 @@ } } }, + "DisplayScalingMode": { + "Name": "DisplayScalingMode", + "Scriptability": "None", + "DataType": { + "Enum": "DisplayScalingMode" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "GuiNavigationEnabled": { "Name": "GuiNavigationEnabled", "Scriptability": "ReadWrite", @@ -30015,9 +33424,24 @@ "Archivable": { "Bool": true }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" } @@ -30044,1017 +33468,6 @@ } } }, - "HandRigDescription": { - "Name": "HandRigDescription", - "Tags": [ - "NotBrowsable" - ], - "Superclass": "Instance", - "Properties": { - "Index1": { - "Name": "Index1", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Index1TposeAdjustment": { - "Name": "Index1TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Index2": { - "Name": "Index2", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Index2TposeAdjustment": { - "Name": "Index2TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Index3": { - "Name": "Index3", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Index3TposeAdjustment": { - "Name": "Index3TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "IndexRange": { - "Name": "IndexRange", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "IndexSize": { - "Name": "IndexSize", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Middle1": { - "Name": "Middle1", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Middle1TposeAdjustment": { - "Name": "Middle1TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Middle2": { - "Name": "Middle2", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Middle2TposeAdjustment": { - "Name": "Middle2TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Middle3": { - "Name": "Middle3", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Middle3TposeAdjustment": { - "Name": "Middle3TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "MiddleRange": { - "Name": "MiddleRange", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "MiddleSize": { - "Name": "MiddleSize", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Pinky1": { - "Name": "Pinky1", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Pinky1TposeAdjustment": { - "Name": "Pinky1TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Pinky2": { - "Name": "Pinky2", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Pinky2TposeAdjustment": { - "Name": "Pinky2TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Pinky3": { - "Name": "Pinky3", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Pinky3TposeAdjustment": { - "Name": "Pinky3TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "PinkyRange": { - "Name": "PinkyRange", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "PinkySize": { - "Name": "PinkySize", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Ring1": { - "Name": "Ring1", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Ring1TposeAdjustment": { - "Name": "Ring1TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Ring2": { - "Name": "Ring2", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Ring2TposeAdjustment": { - "Name": "Ring2TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Ring3": { - "Name": "Ring3", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Ring3TposeAdjustment": { - "Name": "Ring3TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "RingRange": { - "Name": "RingRange", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "RingSize": { - "Name": "RingSize", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Side": { - "Name": "Side", - "Scriptability": "ReadWrite", - "DataType": { - "Enum": "HandRigDescriptionSide" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Thumb1": { - "Name": "Thumb1", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Thumb1TposeAdjustment": { - "Name": "Thumb1TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Thumb2": { - "Name": "Thumb2", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Thumb2TposeAdjustment": { - "Name": "Thumb2TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Thumb3": { - "Name": "Thumb3", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "Thumb3TposeAdjustment": { - "Name": "Thumb3TposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ThumbRange": { - "Name": "ThumbRange", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "ThumbSize": { - "Name": "ThumbSize", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - } - }, - "DefaultProperties": { - "Archivable": { - "Bool": true - }, - "Attributes": { - "Attributes": {} - }, - "Capabilities": { - "SecurityCapabilities": 0 - }, - "HistoryId": { - "UniqueId": "00000000000000000000000000000000" - }, - "Index1TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Index2TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Index3TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "IndexRange": { - "Vector3": [ - 0.0, - 0.0, - 0.0 - ] - }, - "IndexSize": { - "Float32": 0.0 - }, - "Middle1TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Middle2TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Middle3TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "MiddleRange": { - "Vector3": [ - 0.0, - 0.0, - 0.0 - ] - }, - "MiddleSize": { - "Float32": 0.0 - }, - "Pinky1TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Pinky2TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Pinky3TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "PinkyRange": { - "Vector3": [ - 0.0, - 0.0, - 0.0 - ] - }, - "PinkySize": { - "Float32": 0.0 - }, - "Ring1TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Ring2TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Ring3TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "RingRange": { - "Vector3": [ - 0.0, - 0.0, - 0.0 - ] - }, - "RingSize": { - "Float32": 0.0 - }, - "Sandboxed": { - "Bool": false - }, - "Side": { - "Enum": 0 - }, - "SourceAssetId": { - "Int64": -1 - }, - "Tags": { - "Tags": [] - }, - "Thumb1TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Thumb2TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "Thumb3TposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, - "ThumbRange": { - "Vector3": [ - 0.0, - 0.0, - 0.0 - ] - }, - "ThumbSize": { - "Float32": 0.0 - }, - "UniqueId": { - "UniqueId": "00000000000000000000000000000000" - } - } - }, "HandleAdornment": { "Name": "HandleAdornment", "Tags": [ @@ -31397,21 +33810,6 @@ } } }, - "Waveform": { - "Name": "Waveform", - "Scriptability": "None", - "DataType": { - "Value": "Ref" - }, - "Tags": [ - "Deprecated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "WaveformData": { "Name": "WaveformData", "Scriptability": "None", @@ -31597,6 +33995,26 @@ } } }, + "HeatmapQueryService": { + "Name": "HeatmapQueryService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "HeatmapService": { "Name": "HeatmapService", "Tags": [ @@ -32701,6 +35119,22 @@ } } }, + "FinishedState": { + "Name": "FinishedState", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "FloorMaterial": { "Name": "FloorMaterial", "Scriptability": "Read", @@ -33027,6 +35461,22 @@ } } }, + "NoFloorTimerState": { + "Name": "NoFloorTimerState", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "OverrideDefaultCollisions": { "Name": "OverrideDefaultCollisions", "Scriptability": "None", @@ -33189,6 +35639,22 @@ } } }, + "TimerState": { + "Name": "TimerState", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Torso": { "Name": "Torso", "Scriptability": "ReadWrite", @@ -33975,6 +36441,19 @@ } } }, + "StaticFacialAnimation": { + "Name": "StaticFacialAnimation", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "SwimAnimation": { "Name": "SwimAnimation", "Scriptability": "ReadWrite", @@ -34018,6 +36497,19 @@ } } }, + "UseAvatarSettings": { + "Name": "UseAvatarSettings", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "WaistAccessory": { "Name": "WaistAccessory", "Scriptability": "ReadWrite", @@ -34130,6 +36622,9 @@ "SourceAssetId": { "Int64": -1 }, + "StaticFacialAnimation": { + "Bool": false + }, "SwimAnimation": { "Int64": 0 }, @@ -34139,6 +36634,9 @@ "UniqueId": { "UniqueId": "00000000000000000000000000000000" }, + "UseAvatarSettings": { + "Bool": false + }, "WalkAnimation": { "Int64": 0 }, @@ -34149,9 +36647,7 @@ }, "HumanoidRigDescription": { "Name": "HumanoidRigDescription", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "Instance", "Properties": { "Chest": { @@ -34674,8 +37170,8 @@ } } }, - "LeftToes": { - "Name": "LeftToes", + "LeftToeBase": { + "Name": "LeftToeBase", "Scriptability": "ReadWrite", "DataType": { "Value": "Ref" @@ -34687,8 +37183,8 @@ } } }, - "LeftToesRangeMax": { - "Name": "LeftToesRangeMax", + "LeftToeBaseRangeMax": { + "Name": "LeftToeBaseRangeMax", "Scriptability": "ReadWrite", "DataType": { "Value": "Vector3" @@ -34700,8 +37196,8 @@ } } }, - "LeftToesRangeMin": { - "Name": "LeftToesRangeMin", + "LeftToeBaseRangeMin": { + "Name": "LeftToeBaseRangeMin", "Scriptability": "ReadWrite", "DataType": { "Value": "Vector3" @@ -34713,8 +37209,8 @@ } } }, - "LeftToesSize": { - "Name": "LeftToesSize", + "LeftToeBaseSize": { + "Name": "LeftToeBaseSize", "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" @@ -34726,8 +37222,8 @@ } } }, - "LeftToesTposeAdjustment": { - "Name": "LeftToesTposeAdjustment", + "LeftToeBaseTposeAdjustment": { + "Name": "LeftToeBaseTposeAdjustment", "Scriptability": "ReadWrite", "DataType": { "Value": "CFrame" @@ -34882,71 +37378,6 @@ } } }, - "Pelvis": { - "Name": "Pelvis", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Ref" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "PelvisRangeMax": { - "Name": "PelvisRangeMax", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "PelvisRangeMin": { - "Name": "PelvisRangeMin", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Vector3" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "PelvisSize": { - "Name": "PelvisSize", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "PelvisTposeAdjustment": { - "Name": "PelvisTposeAdjustment", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "CFrame" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "RightAnkle": { "Name": "RightAnkle", "Scriptability": "ReadWrite", @@ -35337,8 +37768,8 @@ } } }, - "RightToes": { - "Name": "RightToes", + "RightToeBase": { + "Name": "RightToeBase", "Scriptability": "ReadWrite", "DataType": { "Value": "Ref" @@ -35350,8 +37781,8 @@ } } }, - "RightToesRangeMax": { - "Name": "RightToesRangeMax", + "RightToeBaseRangeMax": { + "Name": "RightToeBaseRangeMax", "Scriptability": "ReadWrite", "DataType": { "Value": "Vector3" @@ -35363,8 +37794,8 @@ } } }, - "RightToesRangeMin": { - "Name": "RightToesRangeMin", + "RightToeBaseRangeMin": { + "Name": "RightToeBaseRangeMin", "Scriptability": "ReadWrite", "DataType": { "Value": "Vector3" @@ -35376,8 +37807,8 @@ } } }, - "RightToesSize": { - "Name": "RightToesSize", + "RightToeBaseSize": { + "Name": "RightToeBaseSize", "Scriptability": "ReadWrite", "DataType": { "Value": "Float32" @@ -35389,8 +37820,8 @@ } } }, - "RightToesTposeAdjustment": { - "Name": "RightToesTposeAdjustment", + "RightToeBaseTposeAdjustment": { + "Name": "RightToeBaseTposeAdjustment", "Scriptability": "ReadWrite", "DataType": { "Value": "CFrame" @@ -35532,6 +37963,71 @@ } } }, + "Spine": { + "Name": "Spine", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SpineRangeMax": { + "Name": "SpineRangeMax", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SpineRangeMin": { + "Name": "SpineRangeMin", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SpineSize": { + "Name": "SpineSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SpineTposeAdjustment": { + "Name": "SpineTposeAdjustment", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Waist": { "Name": "Waist", "Scriptability": "ReadWrite", @@ -35955,24 +38451,24 @@ ] } }, - "LeftToesRangeMax": { + "LeftToeBaseRangeMax": { "Vector3": [ 0.0, 0.0, 0.0 ] }, - "LeftToesRangeMin": { + "LeftToeBaseRangeMin": { "Vector3": [ 0.0, 0.0, 0.0 ] }, - "LeftToesSize": { + "LeftToeBaseSize": { "Float32": 0.0 }, - "LeftToesTposeAdjustment": { + "LeftToeBaseTposeAdjustment": { "CFrame": { "position": [ 0.0, @@ -36110,49 +38606,6 @@ ] } }, - "PelvisRangeMax": { - "Vector3": [ - 0.0, - 0.0, - 0.0 - ] - }, - "PelvisRangeMin": { - "Vector3": [ - 0.0, - 0.0, - 0.0 - ] - }, - "PelvisSize": { - "Float32": 0.0 - }, - "PelvisTposeAdjustment": { - "CFrame": { - "position": [ - 0.0, - 0.0, - 0.0 - ], - "orientation": [ - [ - 1.0, - 0.0, - 0.0 - ], - [ - 0.0, - 1.0, - 0.0 - ], - [ - 0.0, - 0.0, - 1.0 - ] - ] - } - }, "RightAnkleRangeMax": { "Vector3": [ 0.0, @@ -36411,24 +38864,24 @@ ] } }, - "RightToesRangeMax": { + "RightToeBaseRangeMax": { "Vector3": [ 0.0, 0.0, 0.0 ] }, - "RightToesRangeMin": { + "RightToeBaseRangeMin": { "Vector3": [ 0.0, 0.0, 0.0 ] }, - "RightToesSize": { + "RightToeBaseSize": { "Float32": 0.0 }, - "RightToesTposeAdjustment": { + "RightToeBaseTposeAdjustment": { "CFrame": { "position": [ 0.0, @@ -36546,6 +38999,49 @@ "SourceAssetId": { "Int64": -1 }, + "SpineRangeMax": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SpineRangeMin": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "SpineSize": { + "Float32": 0.0 + }, + "SpineTposeAdjustment": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, "Tags": { "Tags": [] }, @@ -37218,6 +39714,9 @@ "ImageTransparency": { "Float32": 0.0 }, + "InputSink": { + "Enum": 0 + }, "Interactable": { "Bool": true }, @@ -37352,6 +39851,24 @@ "Value": "ContentId" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "ImageContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "ImageContent": { + "Name": "ImageContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -37424,8 +39941,10 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "Image": { - "ContentId": "rbxasset://textures/SurfacesDefault.png" + "ImageContent": { + "Content": { + "Uri": "rbxasset://textures/SurfacesDefault.png" + } }, "Sandboxed": { "Bool": false @@ -37732,6 +40251,9 @@ "ImageTransparency": { "Float32": 0.0 }, + "InputSink": { + "Enum": 0 + }, "Interactable": { "Bool": true }, @@ -37842,6 +40364,26 @@ } } }, + "ImageScreenCaptureService": { + "Name": "ImageScreenCaptureService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "ImportSession": { "Name": "ImportSession", "Tags": [ @@ -38060,6 +40602,23 @@ "Serialization": "Serializes" } } + }, + "ViewportPositionState": { + "Name": "ViewportPositionState", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "NotScriptable", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -38113,6 +40672,19 @@ } } }, + "ClampMagnitudeToOne": { + "Name": "ClampMagnitudeToOne", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Down": { "Name": "Down", "Scriptability": "ReadWrite", @@ -38165,6 +40737,19 @@ } } }, + "PointerIndex": { + "Name": "PointerIndex", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PressedThreshold": { "Name": "PressedThreshold", "Scriptability": "ReadWrite", @@ -38178,6 +40763,19 @@ } } }, + "PrimaryModifier": { + "Name": "PrimaryModifier", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "KeyCode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ReleasedThreshold": { "Name": "ReleasedThreshold", "Scriptability": "ReadWrite", @@ -38230,6 +40828,32 @@ } } }, + "SecondaryModifier": { + "Name": "SecondaryModifier", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "KeyCode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Type": { + "Name": "Type", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "InputBindingType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "UIButton": { "Name": "UIButton", "Scriptability": "ReadWrite", @@ -38243,6 +40867,19 @@ } } }, + "UIModifier": { + "Name": "UIModifier", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Up": { "Name": "Up", "Scriptability": "ReadWrite", @@ -38268,6 +40905,19 @@ "Serialization": "Serializes" } } + }, + "Vector3Scale": { + "Name": "Vector3Scale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -38283,6 +40933,9 @@ "Capabilities": { "SecurityCapabilities": 0 }, + "ClampMagnitudeToOne": { + "Bool": true + }, "Down": { "Enum": 0 }, @@ -38298,9 +40951,15 @@ "Left": { "Enum": 0 }, + "PointerIndex": { + "Int32": 0 + }, "PressedThreshold": { "Float32": 0.5 }, + "PrimaryModifier": { + "Enum": 0 + }, "ReleasedThreshold": { "Float32": 0.2 }, @@ -38316,12 +40975,18 @@ "Scale": { "Float32": 1.0 }, + "SecondaryModifier": { + "Enum": 0 + }, "SourceAssetId": { "Int64": -1 }, "Tags": { "Tags": [] }, + "Type": { + "Enum": 0 + }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" }, @@ -38333,6 +40998,13 @@ 1.0, 1.0 ] + }, + "Vector3Scale": { + "Vector3": [ + 1.0, + 1.0, + 1.0 + ] } } }, @@ -38510,21 +41182,6 @@ ], "Superclass": "Instance", "Properties": { - "AllowClientInsertModels": { - "Name": "AllowClientInsertModels", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "AllowInsertFreeModels": { "Name": "AllowInsertFreeModels", "Scriptability": "ReadWrite", @@ -38544,9 +41201,6 @@ } }, "DefaultProperties": { - "AllowClientInsertModels": { - "Bool": false - }, "AllowInsertFreeModels": { "Bool": false }, @@ -38716,6 +41370,23 @@ } } }, + "IsInSandbox": { + "Name": "IsInSandbox", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "NotScriptable", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Name": { "Name": "Name", "Scriptability": "ReadWrite", @@ -38744,6 +41415,23 @@ } } }, + "PredictionMode": { + "Name": "PredictionMode", + "Scriptability": "None", + "DataType": { + "Enum": "PredictionMode" + }, + "Tags": [ + "NotReplicated", + "NotScriptable", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PropertyStatusStudio": { "Name": "PropertyStatusStudio", "Scriptability": "None", @@ -38939,6 +41627,27 @@ } } }, + "InstanceFileSyncService": { + "Name": "InstanceFileSyncService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "IntConstrainedValue": { "Name": "IntConstrainedValue", "Tags": [ @@ -39105,6 +41814,48 @@ } } }, + "InternalMessagingService": { + "Name": "InternalMessagingService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, + "InternalMessagingServiceVerifier": { + "Name": "InternalMessagingServiceVerifier", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "InternalSyncItem": { "Name": "InternalSyncItem", "Tags": [ @@ -39388,7 +42139,7 @@ "Bool": false }, "PhysicalConfigData": { - "SharedString": "" + "SharedString": "Q1NHUEhTAAAAAEJMT0NL" }, "PhysicsData": { "BinaryString": "" @@ -39484,6 +42235,9 @@ "Transparency": { "Float32": 0.0 }, + "TriangleCount": { + "Int32": 0 + }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" }, @@ -39901,27 +42655,6 @@ } } }, - "LSPFileSyncService": { - "Name": "LSPFileSyncService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "Archivable": { - "Bool": true - }, - "HistoryId": { - "UniqueId": "00000000000000000000000000000000" - }, - "UniqueId": { - "UniqueId": "00000000000000000000000000000000" - } - } - }, "LanguageService": { "Name": "LanguageService", "Tags": [ @@ -39977,6 +42710,22 @@ } } }, + "TabKeyboardNavigation": { + "Name": "TabKeyboardNavigation", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ZIndexBehavior": { "Name": "ZIndexBehavior", "Scriptability": "ReadWrite", @@ -41594,6 +44343,22 @@ } } }, + "EntityModelSize": { + "Name": "EntityModelSize", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "EntityPosition": { "Name": "EntityPosition", "Scriptability": "None", @@ -41642,6 +44407,22 @@ } } }, + "EntityVisible": { + "Name": "EntityVisible", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "IsSlimEnabled": { "Name": "IsSlimEnabled", "Scriptability": "None", @@ -41657,6 +44438,38 @@ "Serialization": "DoesNotSerialize" } } + }, + "SlimAnimationSource": { + "Name": "SlimAnimationSource", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SlimReplicationTimestampSec": { + "Name": "SlimReplicationTimestampSec", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -42034,6 +44847,100 @@ "Properties": {}, "DefaultProperties": {} }, + "MakeupDescription": { + "Name": "MakeupDescription", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "AssetId": { + "Name": "AssetId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Instance": { + "Name": "Instance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "MakeupType": { + "Name": "MakeupType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "MakeupType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Order": { + "Name": "Order", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "AssetId": { + "Int64": 0 + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "MakeupType": { + "Enum": 0 + }, + "Order": { + "Int32": 0 + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "ManualGlue": { "Name": "ManualGlue", "Tags": [ @@ -43261,6 +46168,21 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "AlphaMode": { + "Name": "AlphaMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AlphaMode" + }, + "Tags": [ + "NotBrowsable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "AvgMetalness": { "Name": "AvgMetalness", "Scriptability": "None", @@ -43528,6 +46450,9 @@ } }, "DefaultProperties": { + "AlphaMode": { + "Enum": 3 + }, "Archivable": { "Bool": true }, @@ -44509,7 +47434,7 @@ "Content": "None" }, "PhysicalConfigData": { - "SharedString": "" + "SharedString": "Q1NHUEhTAAAAAEJMT0NL" }, "PhysicsData": { "BinaryString": "" @@ -45244,6 +48169,22 @@ } } }, + "SlimAnimationTarget": { + "Name": "SlimAnimationTarget", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "SlimHash": { "Name": "SlimHash", "Scriptability": "None", @@ -45443,6 +48384,22 @@ "Serialization": "Serializes" } } + }, + "UnrestrictedRequireAllowed": { + "Name": "UnrestrictedRequireAllowed", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -45654,6 +48611,19 @@ } } }, + "EnableSkinning": { + "Name": "EnableSkinning", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ParentName": { "Name": "ParentName", "Scriptability": "None", @@ -46356,7 +49326,7 @@ "Bool": false }, "PhysicalConfigData": { - "SharedString": "" + "SharedString": "Q1NHUEhTAAAAAEJMT0NL" }, "PhysicsData": { "BinaryString": "" @@ -46455,6 +49425,9 @@ "Transparency": { "Float32": 0.1 }, + "TriangleCount": { + "Int32": 0 + }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" }, @@ -46665,6 +49638,51 @@ } } }, + "InboundNetworkJitterMs": { + "Name": "InboundNetworkJitterMs", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InboundNetworkLossPercent": { + "Name": "InboundNetworkLossPercent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InboundNetworkMinDelayMs": { + "Name": "InboundNetworkMinDelayMs", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "IncomingReplicationLag": { "Name": "IncomingReplicationLag", "Scriptability": "ReadWrite", @@ -46695,6 +49713,51 @@ } } }, + "OutboundNetworkJitterMs": { + "Name": "OutboundNetworkJitterMs", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OutboundNetworkLossPercent": { + "Name": "OutboundNetworkLossPercent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OutboundNetworkMinDelayMs": { + "Name": "OutboundNetworkMinDelayMs", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PrintJoinSizeBreakdown": { "Name": "PrintJoinSizeBreakdown", "Scriptability": "ReadWrite", @@ -47375,6 +50438,16 @@ } } }, + "OutputLink": { + "Name": "OutputLink", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Object", + "Properties": {}, + "DefaultProperties": {} + }, "PVAdornment": { "Name": "PVAdornment", "Tags": [ @@ -47577,6 +50650,40 @@ } } }, + "PackageContent": { + "Name": "PackageContent", + "Scriptability": "Read", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "PackageContentSerialize" + } + } + } + }, + "PackageContentSerialize": { + "Name": "PackageContentSerialize", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Alias": { + "AliasFor": "PackageContent" + } + } + }, "PackageGuid": { "Name": "PackageGuid", "Scriptability": "None", @@ -47606,7 +50713,10 @@ "Kind": { "Canonical": { "Serialization": { - "SerializesAs": "PackageIdSerialize" + "Migrate": { + "To": "PackageContent", + "Migration": "ContentIdToContent" + } } } } @@ -47759,6 +50869,96 @@ } } }, + "Packages": { + "Name": "Packages", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "IsDehydrated": { + "Name": "IsDehydrated", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ShellPackagesCount": { + "Name": "ShellPackagesCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SkippedInstancesCount": { + "Name": "SkippedInstancesCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "IsDehydrated": { + "Bool": false + }, + "Sandboxed": { + "Bool": false + }, + "ShellPackagesCount": { + "Int32": 0 + }, + "SkippedInstancesCount": { + "Int32": 0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "Pages": { "Name": "Pages", "Tags": [ @@ -47813,6 +51013,19 @@ "Serialization": "Serializes" } } + }, + "PantsTemplateContent": { + "Name": "PantsTemplateContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -48499,23 +51712,6 @@ } } }, - "SerializedOperationGraph": { - "Name": "SerializedOperationGraph", - "Scriptability": "None", - "DataType": { - "Value": "SharedString" - }, - "Tags": [ - "Hidden", - "NotReplicated", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "SmoothingAngle": { "Name": "SmoothingAngle", "Scriptability": "ReadWrite", @@ -48551,13 +51747,10 @@ "DataType": { "Value": "Int32" }, - "Tags": [ - "NotReplicated", - "ReadOnly" - ], + "Tags": [], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": "Serializes" } } }, @@ -48752,7 +51945,7 @@ "Bool": false }, "PhysicalConfigData": { - "SharedString": "" + "SharedString": "Q1NHUEhTAAAAAEJMT0NL" }, "PhysicsData": { "BinaryString": "" @@ -48848,6 +52041,9 @@ "Transparency": { "Float32": 0.0 }, + "TriangleCount": { + "Int32": 0 + }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" }, @@ -49042,6 +52238,19 @@ } } }, + "FlipbookBlendFrames": { + "Name": "FlipbookBlendFrames", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "FlipbookFramerate": { "Name": "FlipbookFramerate", "Scriptability": "ReadWrite", @@ -49364,6 +52573,24 @@ "Value": "ContentId" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "TextureContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "TextureContent": { + "Name": "TextureContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -49503,6 +52730,9 @@ "Enabled": { "Bool": true }, + "FlipbookBlendFrames": { + "Bool": true + }, "FlipbookFramerate": { "NumberRange": [ 1.0, @@ -49628,8 +52858,10 @@ "Tags": { "Tags": [] }, - "Texture": { - "ContentId": "rbxasset://textures/particles/sparkles_main.dds" + "TextureContent": { + "Content": { + "Uri": "rbxasset://textures/particles/sparkles_main.dds" + } }, "TimeScale": { "Float32": 1.0 @@ -51314,6 +54546,26 @@ } } }, + "PlatformLibraries": { + "Name": "PlatformLibraries", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "Player": { "Name": "Player", "Tags": [], @@ -51351,6 +54603,19 @@ } } }, + "AgeChecked": { + "Name": "AgeChecked", + "Scriptability": "Read", + "DataType": { + "Enum": "AgeCheckStatus" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "AppearanceDidLoad": { "Name": "AppearanceDidLoad", "Scriptability": "None", @@ -51382,6 +54647,38 @@ } } }, + "CameraFieldOfView": { + "Name": "CameraFieldOfView", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "CameraFrustumRequested": { + "Name": "CameraFrustumRequested", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "CameraMaxZoomDistance": { "Name": "CameraMaxZoomDistance", "Scriptability": "ReadWrite", @@ -51421,6 +54718,22 @@ } } }, + "CameraViewportSize": { + "Name": "CameraViewportSize", + "Scriptability": "None", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "CanLoadCharacterAppearance": { "Name": "CanLoadCharacterAppearance", "Scriptability": "ReadWrite", @@ -51797,6 +55110,19 @@ } } }, + "HasRobloxSubscription": { + "Name": "HasRobloxSubscription", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "HasVerifiedBadge": { "Name": "HasVerifiedBadge", "Scriptability": "ReadWrite", @@ -51823,6 +55149,19 @@ } } }, + "InputLatency": { + "Name": "InputLatency", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "InternalCharacterAppearanceLoaded": { "Name": "InternalCharacterAppearanceLoaded", "Scriptability": "None", @@ -51933,6 +55272,22 @@ } } }, + "NeedRegionalFallback": { + "Name": "NeedRegionalFallback", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Neutral": { "Name": "Neutral", "Scriptability": "ReadWrite", @@ -52820,6 +56175,40 @@ } } }, + "PlayerListConfiguration": { + "Name": "PlayerListConfiguration", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "BaseCoreGuiConfiguration", + "Properties": { + "Open": { + "Name": "Open", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "PlayerMouse": { "Name": "PlayerMouse", "Tags": [ @@ -53453,6 +56842,22 @@ "Serialization": "DoesNotSerialize" } } + }, + "Visible": { + "Name": "Visible", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -53516,6 +56921,104 @@ } } }, + "PluginConnection": { + "Name": "PluginConnection", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Object", + "Properties": { + "Connected": { + "Name": "Connected", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "GroupId": { + "Name": "GroupId", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TargetId": { + "Name": "TargetId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Type": { + "Name": "Type", + "Scriptability": "Read", + "DataType": { + "Enum": "PluginConnectionTargetType" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, + "PluginConnectionService": { + "Name": "PluginConnectionService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "PluginDebugService": { "Name": "PluginDebugService", "Tags": [ @@ -53791,6 +57294,19 @@ "Serialization": "DoesNotSerialize" } } + }, + "Visible": { + "Name": "Visible", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -53915,6 +57431,21 @@ "Serialization": "DoesNotSerialize" } } + }, + "IconContent": { + "Name": "IconContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -54256,6 +57787,41 @@ } } }, + "Preloaded": { + "Name": "Preloaded", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "PrismaticConstraint": { "Name": "PrismaticConstraint", "Tags": [], @@ -54339,6 +57905,182 @@ } } }, + "ProceduralBehaviorSchedulerService": { + "Name": "ProceduralBehaviorSchedulerService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, + "ProceduralModel": { + "Name": "ProceduralModel", + "Tags": [], + "Superclass": "Model", + "Properties": { + "Dirty": { + "Name": "Dirty", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GenerationError": { + "Name": "GenerationError", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Generator": { + "Name": "Generator", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Size": { + "Name": "Size", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Vector3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "Dirty": { + "Bool": false + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "LevelOfDetail": { + "Enum": 0 + }, + "ModelMeshCFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ModelMeshData": { + "SharedString": "" + }, + "ModelMeshSize": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "ModelStreamingMode": { + "Enum": 0 + }, + "NeedsPivotMigration": { + "Bool": false + }, + "Sandboxed": { + "Bool": false + }, + "Scale": { + "Float32": 1.0 + }, + "Size": { + "Vector3": [ + 12.0, + 12.0, + 12.0 + ] + }, + "SlimHash": { + "SharedString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + }, + "WorldPivotData": { + "OptionalCFrame": null + } + } + }, "ProcessInstancePhysicsService": { "Name": "ProcessInstancePhysicsService", "Tags": [ @@ -55105,6 +58847,71 @@ } } }, + "RealtimeMedia": { + "Name": "RealtimeMedia", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "ForwardInput": { + "Name": "ForwardInput", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "IsConnected": { + "Name": "IsConnected", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "ForwardInput": { + "Bool": false + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "RecommendationPages": { "Name": "RecommendationPages", "Tags": [ @@ -57451,6 +61258,418 @@ } } }, + "RolloutValidation": { + "Name": "RolloutValidation", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "AdditionalFluffOne": { + "Name": "AdditionalFluffOne", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AdditionalFluffThree": { + "Name": "AdditionalFluffThree", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AdditionalFluffTwo": { + "Name": "AdditionalFluffTwo", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CreationVersion": { + "Name": "CreationVersion", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FirstBinaryExpectedValue": { + "Name": "FirstBinaryExpectedValue", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FirstBinaryString": { + "Name": "FirstBinaryString", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FirstSharedExpectedValue": { + "Name": "FirstSharedExpectedValue", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "FirstSharedString": { + "Name": "FirstSharedString", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GenerationStrategy": { + "Name": "GenerationStrategy", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SecondBinaryExpectedValue": { + "Name": "SecondBinaryExpectedValue", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SecondBinaryString": { + "Name": "SecondBinaryString", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SecondSharedExpectedValue": { + "Name": "SecondSharedExpectedValue", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SecondSharedString": { + "Name": "SecondSharedString", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ThirdBinaryExpectedValue": { + "Name": "ThirdBinaryExpectedValue", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ThirdBinaryString": { + "Name": "ThirdBinaryString", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ThirdSharedExpectedValue": { + "Name": "ThirdSharedExpectedValue", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ThirdSharedString": { + "Name": "ThirdSharedString", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "AdditionalFluffOne": { + "Int32": 0 + }, + "AdditionalFluffThree": { + "Float32": 0.0 + }, + "AdditionalFluffTwo": { + "Bool": false + }, + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "CreationVersion": { + "Int32": 0 + }, + "FirstBinaryExpectedValue": { + "String": "" + }, + "FirstBinaryString": { + "BinaryString": "" + }, + "FirstSharedExpectedValue": { + "String": "" + }, + "FirstSharedString": { + "SharedString": "" + }, + "GenerationStrategy": { + "Int32": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Sandboxed": { + "Bool": false + }, + "SecondBinaryExpectedValue": { + "String": "" + }, + "SecondBinaryString": { + "BinaryString": "" + }, + "SecondSharedExpectedValue": { + "String": "" + }, + "SecondSharedString": { + "SharedString": "" + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "ThirdBinaryExpectedValue": { + "String": "" + }, + "ThirdBinaryString": { + "BinaryString": "" + }, + "ThirdSharedExpectedValue": { + "String": "" + }, + "ThirdSharedString": { + "SharedString": "" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, + "RolloutValidationService": { + "Name": "RolloutValidationService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "RomarkRbxAnalyticsService": { "Name": "RomarkRbxAnalyticsService", "Tags": [ @@ -57658,6 +61877,19 @@ } } }, + "PhysicalConstraintType": { + "Name": "PhysicalConstraintType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "PhysicalConstraintType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PolygonCount": { "Name": "PolygonCount", "Scriptability": "Read", @@ -57739,6 +61971,19 @@ } } }, + "ScaleFactor": { + "Name": "ScaleFactor", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ScaleUnit": { "Name": "ScaleUnit", "Scriptability": "ReadWrite", @@ -57791,6 +62036,19 @@ } } }, + "VersionedAssetId": { + "Name": "VersionedAssetId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "WorldForward": { "Name": "WorldForward", "Scriptability": "ReadWrite", @@ -58579,6 +62837,27 @@ } } }, + "SceneAnalysisService": { + "Name": "SceneAnalysisService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "ScreenGui": { "Name": "ScreenGui", "Tags": [], @@ -58763,6 +63042,24 @@ "Value": "ContentId" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "CameraButtonIconContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "CameraButtonIconContent": { + "Name": "CameraButtonIconContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -59226,6 +63523,27 @@ } } }, + "ScriptDebuggerService": { + "Name": "ScriptDebuggerService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "ScriptDocument": { "Name": "ScriptDocument", "Tags": [ @@ -59855,6 +64173,9 @@ "HorizontalScrollBarInset": { "Enum": 0 }, + "InputSink": { + "Enum": 0 + }, "Interactable": { "Bool": true }, @@ -60791,6 +65112,40 @@ } } }, + "SelfViewConfiguration": { + "Name": "SelfViewConfiguration", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "BaseCoreGuiConfiguration", + "Properties": { + "Open": { + "Name": "Open", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "SensorBase": { "Name": "SensorBase", "Tags": [ @@ -61137,6 +65492,19 @@ "Serialization": "Serializes" } } + }, + "ShirtTemplateContent": { + "Name": "ShirtTemplateContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -61206,6 +65574,19 @@ "Serialization": "Serializes" } } + }, + "TextureContent": { + "Name": "TextureContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -61732,6 +66113,19 @@ } } }, + "MoonTextureContent": { + "Name": "MoonTextureContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MoonTextureId": { "Name": "MoonTextureId", "Scriptability": "ReadWrite", @@ -61739,6 +66133,24 @@ "Value": "ContentId" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "MoonTextureContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "SkyboxBackContent": { + "Name": "SkyboxBackContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -61754,7 +66166,12 @@ "Tags": [], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": { + "Migrate": { + "To": "SkyboxBackContent", + "Migration": "ContentIdToContent" + } + } } } }, @@ -61765,6 +66182,37 @@ "Value": "ContentId" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "SkyboxDownContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "SkyboxDownContent": { + "Name": "SkyboxDownContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "SkyboxFrontContent": { + "Name": "SkyboxFrontContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -61778,6 +66226,24 @@ "Value": "ContentId" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "SkyboxFrontContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "SkyboxLeftContent": { + "Name": "SkyboxLeftContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -61793,7 +66259,12 @@ "Tags": [], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": { + "Migrate": { + "To": "SkyboxLeftContent", + "Migration": "ContentIdToContent" + } + } } } }, @@ -61810,6 +66281,19 @@ } } }, + "SkyboxRightContent": { + "Name": "SkyboxRightContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "SkyboxRt": { "Name": "SkyboxRt", "Scriptability": "ReadWrite", @@ -61819,7 +66303,12 @@ "Tags": [], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": { + "Migrate": { + "To": "SkyboxRightContent", + "Migration": "ContentIdToContent" + } + } } } }, @@ -61830,6 +66319,24 @@ "Value": "ContentId" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "SkyboxUpContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "SkyboxUpContent": { + "Name": "SkyboxUpContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -61862,6 +66369,19 @@ } } }, + "SunTextureContent": { + "Name": "SunTextureContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "SunTextureId": { "Name": "SunTextureId", "Scriptability": "ReadWrite", @@ -61871,7 +66391,12 @@ "Tags": [], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": { + "Migrate": { + "To": "SunTextureContent", + "Migration": "ContentIdToContent" + } + } } } } @@ -61895,23 +66420,33 @@ "MoonAngularSize": { "Float32": 11.0 }, - "MoonTextureId": { - "ContentId": "rbxasset://sky/moon.jpg" + "MoonTextureContent": { + "Content": { + "Uri": "rbxasset://sky/moon.jpg" + } }, "Sandboxed": { "Bool": false }, - "SkyboxBk": { - "ContentId": "rbxasset://textures/sky/sky512_bk.tex" + "SkyboxBackContent": { + "Content": { + "Uri": "rbxasset://textures/sky/sky512_bk.tex" + } }, - "SkyboxDn": { - "ContentId": "rbxasset://textures/sky/sky512_dn.tex" + "SkyboxDownContent": { + "Content": { + "Uri": "rbxasset://textures/sky/sky512_dn.tex" + } }, - "SkyboxFt": { - "ContentId": "rbxasset://textures/sky/sky512_ft.tex" + "SkyboxFrontContent": { + "Content": { + "Uri": "rbxasset://textures/sky/sky512_ft.tex" + } }, - "SkyboxLf": { - "ContentId": "rbxasset://textures/sky/sky512_lf.tex" + "SkyboxLeftContent": { + "Content": { + "Uri": "rbxasset://textures/sky/sky512_lf.tex" + } }, "SkyboxOrientation": { "Vector3": [ @@ -61920,11 +66455,15 @@ 0.0 ] }, - "SkyboxRt": { - "ContentId": "rbxasset://textures/sky/sky512_rt.tex" + "SkyboxRightContent": { + "Content": { + "Uri": "rbxasset://textures/sky/sky512_rt.tex" + } }, - "SkyboxUp": { - "ContentId": "rbxasset://textures/sky/sky512_up.tex" + "SkyboxUpContent": { + "Content": { + "Uri": "rbxasset://textures/sky/sky512_up.tex" + } }, "SourceAssetId": { "Int64": -1 @@ -61935,8 +66474,10 @@ "SunAngularSize": { "Float32": 21.0 }, - "SunTextureId": { - "ContentId": "rbxasset://sky/sun.jpg" + "SunTextureContent": { + "Content": { + "Uri": "rbxasset://sky/sun.jpg" + } }, "Tags": { "Tags": [] @@ -62166,6 +66707,190 @@ } } }, + "SlimAnimationDataEntity": { + "Name": "SlimAnimationDataEntity", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": { + "BoneParentIndices": { + "Name": "BoneParentIndices", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EntityScale": { + "Name": "EntityScale", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EntitySource": { + "Name": "EntitySource", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Handle": { + "Name": "Handle", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsSlimEnabled": { + "Name": "IsSlimEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "NumBones": { + "Name": "NumBones", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RootIndex": { + "Name": "RootIndex", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SlimInstanceHashes": { + "Name": "SlimInstanceHashes", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "SlimReplicationTimestampSec": { + "Name": "SlimReplicationTimestampSec", + "Scriptability": "None", + "DataType": { + "Value": "Float64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, + "SlimAnimationReplicationService": { + "Name": "SlimAnimationReplicationService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "SlimContentProvider": { "Name": "SlimContentProvider", "Tags": [ @@ -62186,6 +66911,47 @@ } } }, + "SlimDebugSettings": { + "Name": "SlimDebugSettings", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, + "SlimReplicationService": { + "Name": "SlimReplicationService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "SlimService": { "Name": "SlimService", "Tags": [ @@ -62594,13 +67360,44 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "AcousticSimulationEnabled": { + "Name": "AcousticSimulationEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AssetRepresentation": { + "Name": "AssetRepresentation", + "Scriptability": "None", + "DataType": { + "Enum": "AssetRepresentation" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "AudioContent": { "Name": "AudioContent", "Scriptability": "ReadWrite", "DataType": { "Value": "Content" }, - "Tags": [], + "Tags": [ + "Hidden" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -62614,7 +67411,7 @@ "Value": "Int32" }, "Tags": [ - "NotBrowsable", + "Hidden", "NotReplicated", "ReadOnly" ], @@ -62655,19 +67452,6 @@ } } }, - "IsMutedForCapture": { - "Name": "IsMutedForCapture", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "IsPaused": { "Name": "IsPaused", "Scriptability": "Read", @@ -63115,6 +67899,9 @@ } }, "DefaultProperties": { + "AcousticSimulationEnabled": { + "Bool": true + }, "Archivable": { "Bool": true }, @@ -63130,9 +67917,6 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "IsMutedForCapture": { - "Bool": false - }, "LoopRegion": { "NumberRange": [ 0.0, @@ -63359,6 +68143,19 @@ } } }, + "DiffractionEnabled": { + "Name": "DiffractionEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DistanceFactor": { "Name": "DistanceFactor", "Scriptability": "ReadWrite", @@ -63400,6 +68197,58 @@ } } }, + "ListenerCFrame": { + "Name": "ListenerCFrame", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "CFrame" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ListenerObject": { + "Name": "ListenerObject", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ListenerType": { + "Name": "ListenerType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ListenerType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "OcclusionEnabled": { + "Name": "OcclusionEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "RespectFilteringEnabled": { "Name": "RespectFilteringEnabled", "Scriptability": "ReadWrite", @@ -63413,6 +68262,19 @@ } } }, + "ReverbEnabled": { + "Name": "ReverbEnabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "RolloffScale": { "Name": "RolloffScale", "Scriptability": "ReadWrite", @@ -63467,6 +68329,9 @@ "DefaultListenerLocation": { "Enum": 0 }, + "DiffractionEnabled": { + "Bool": true + }, "DistanceFactor": { "Float32": 3.33 }, @@ -63479,9 +68344,44 @@ "IsNewExpForAudioApiByDefault": { "Bool": false }, + "ListenerCFrame": { + "CFrame": { + "position": [ + 0.0, + 0.0, + 0.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "ListenerType": { + "Enum": 0 + }, + "OcclusionEnabled": { + "Bool": true + }, "RespectFilteringEnabled": { "Bool": false }, + "ReverbEnabled": { + "Bool": true + }, "RolloffScale": { "Float32": 1.0 }, @@ -64014,8 +68914,8 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "MeshId": { - "ContentId": "" + "MeshContent": { + "Content": "None" }, "MeshType": { "Enum": 0 @@ -64043,8 +68943,8 @@ "Tags": { "Tags": [] }, - "TextureId": { - "ContentId": "" + "TextureContent": { + "Content": "None" }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" @@ -64814,6 +69714,21 @@ ], "Superclass": "BasePlayerGui", "Properties": { + "ClipsDescendantsSupportsRotation": { + "Name": "ClipsDescendantsSupportsRotation", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ProcessUserInput": { "Name": "ProcessUserInput", "Scriptability": "ReadWrite", @@ -64942,6 +69857,9 @@ "Capabilities": { "SecurityCapabilities": 0 }, + "ClipsDescendantsSupportsRotation": { + "Enum": 0 + }, "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, @@ -65052,13 +69970,13 @@ "Enum": "RolloutState" }, "Tags": [ - "NotBrowsable", - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { - "Serialization": "DoesNotSerialize" + "Serialization": { + "SerializesAs": "AvatarJointUpgrade_SerializedRollout" + } } } }, @@ -65073,8 +69991,8 @@ "NotScriptable" ], "Kind": { - "Canonical": { - "Serialization": "Serializes" + "Alias": { + "AliasFor": "AvatarJointUpgrade" } } }, @@ -65201,9 +70119,7 @@ "DataType": { "Value": "Bool" }, - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -65673,6 +70589,21 @@ } } }, + "PlayerModuleStatus": { + "Name": "PlayerModuleStatus", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "UserEmotesEnabled": { "Name": "UserEmotesEnabled", "Scriptability": "ReadWrite", @@ -65700,7 +70631,7 @@ "AutoJumpEnabled": { "Bool": true }, - "AvatarJointUpgrade_SerializedRollout": { + "AvatarJointUpgrade": { "Enum": 0 }, "CameraMaxZoomDistance": { @@ -65844,6 +70775,9 @@ "NameDisplayDistance": { "Float32": 100.0 }, + "PlayerModuleStatus": { + "Int32": 0 + }, "Sandboxed": { "Bool": false }, @@ -66404,27 +71338,6 @@ } } }, - "StreamingService": { - "Name": "StreamingService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "Archivable": { - "Bool": true - }, - "HistoryId": { - "UniqueId": "00000000000000000000000000000000" - }, - "UniqueId": { - "UniqueId": "00000000000000000000000000000000" - } - } - }, "StringValue": { "Name": "StringValue", "Tags": [], @@ -66636,6 +71549,32 @@ } } }, + "Animation Skeleton Scale": { + "Name": "Animation Skeleton Scale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Animation Skeleton Transparency": { + "Name": "Animation Skeleton Transparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Auto Clean Empty Line": { "Name": "Auto Clean Empty Line", "Scriptability": "ReadWrite", @@ -66906,7 +71845,7 @@ }, "Camera Speed Adjust Binding": { "Name": "Camera Speed Adjust Binding", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Enum": "CameraSpeedAdjustBinding" }, @@ -66943,6 +71882,45 @@ } } }, + "CameraAltLeftMouseToRotate": { + "Name": "CameraAltLeftMouseToRotate", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraMouseMultiplier": { + "Name": "CameraMouseMultiplier", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CameraNavigationModel": { + "Name": "CameraNavigationModel", + "Scriptability": "None", + "DataType": { + "Enum": "CameraNavigationModel" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "CameraOrbitSensitivity": { "Name": "CameraOrbitSensitivity", "Scriptability": "None", @@ -66982,19 +71960,6 @@ } } }, - "CameraSpeedLockDefault": { - "Name": "CameraSpeedLockDefault", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "CameraTweenFocus": { "Name": "CameraTweenFocus", "Scriptability": "None", @@ -67021,6 +71986,19 @@ } } }, + "CameraZoomToMousePosition": { + "Name": "CameraZoomToMousePosition", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Clear Output On Start": { "Name": "Clear Output On Start", "Scriptability": "ReadWrite", @@ -67034,6 +72012,32 @@ } } }, + "CommandBarEnterExec": { + "Name": "CommandBarEnterExec", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CommandBarHistoryLen": { + "Name": "CommandBarHistoryLen", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "CommandBarLocalState": { "Name": "CommandBarLocalState", "Scriptability": "ReadWrite", @@ -67175,6 +72179,19 @@ } } }, + "DraggerLengthFactor": { + "Name": "DraggerLengthFactor", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DraggerMajorGridIncrement": { "Name": "DraggerMajorGridIncrement", "Scriptability": "None", @@ -67214,6 +72231,32 @@ } } }, + "DraggerScaleFactor": { + "Name": "DraggerScaleFactor", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DraggerShowAxisTicks": { + "Name": "DraggerShowAxisTicks", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DraggerShowHoverRuler": { "Name": "DraggerShowHoverRuler", "Scriptability": "None", @@ -67240,6 +72283,32 @@ } } }, + "DraggerShowNegativeAxes": { + "Name": "DraggerShowNegativeAxes", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DraggerShowPlanes": { + "Name": "DraggerShowPlanes", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DraggerShowTargetSnap": { "Name": "DraggerShowTargetSnap", "Scriptability": "None", @@ -67253,6 +72322,32 @@ } } }, + "DraggerShowTrackball": { + "Name": "DraggerShowTrackball", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DraggerShowWhileDragging": { + "Name": "DraggerShowWhileDragging", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DraggerSoftSnapMarginFactor": { "Name": "DraggerSoftSnapMarginFactor", "Scriptability": "None", @@ -67557,6 +72652,19 @@ } } }, + "ExternalEditorMode": { + "Name": "ExternalEditorMode", + "Scriptability": "None", + "DataType": { + "Enum": "ExternalEditorMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Find Selection Background Color": { "Name": "Find Selection Background Color", "Scriptability": "ReadWrite", @@ -68079,6 +73187,19 @@ } } }, + "PreferredTextSize": { + "Name": "PreferredTextSize", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "PreferredTextSize" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Primary Text Color": { "Name": "Primary Text Color", "Scriptability": "ReadWrite", @@ -68430,6 +73551,71 @@ } } }, + "Show Animation Skeleton": { + "Name": "Show Animation Skeleton", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show Animation Skeleton Attachments": { + "Name": "Show Animation Skeleton Attachments", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show Animation Skeleton Axes": { + "Name": "Show Animation Skeleton Axes", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show Animation Skeleton Rotations": { + "Name": "Show Animation Skeleton Rotations", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Show Animation Skeleton Text": { + "Name": "Show Animation Skeleton Text", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Show Core GUI in Explorer while Playing": { "Name": "Show Core GUI in Explorer while Playing", "Scriptability": "ReadWrite", @@ -68696,14 +73882,12 @@ }, "TypeColor": { "Name": "TypeColor", - "Scriptability": "None", + "Scriptability": "ReadWrite", "DataType": { "Value": "Color3" }, "Tags": [ - "Hidden", - "NotReplicated", - "NotScriptable" + "NotReplicated" ], "Kind": { "Canonical": { @@ -68742,6 +73926,32 @@ } } }, + "UseDefaultExternalEditor": { + "Name": "UseDefaultExternalEditor", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VAxisColor": { + "Name": "VAxisColor", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Warning Color": { "Name": "Warning Color", "Scriptability": "ReadWrite", @@ -68771,6 +73981,45 @@ "Serialization": "DoesNotSerialize" } } + }, + "XAxisColor": { + "Name": "XAxisColor", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "YAxisColor": { + "Name": "YAxisColor", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ZAxisColor": { + "Name": "ZAxisColor", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -68785,6 +74034,62 @@ } } }, + "StudioActionOverride": { + "Name": "StudioActionOverride", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Object", + "Properties": { + "Enabled": { + "Name": "Enabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Released": { + "Name": "Released", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "StudioAction": { + "Name": "StudioAction", + "Scriptability": "None", + "DataType": { + "Enum": "StudioAction" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "StudioAssetService": { "Name": "StudioAssetService", "Tags": [ @@ -69016,9 +74321,22 @@ ], "Superclass": "Instance", "Properties": { + "FocusDistance": { + "Name": "FocusDistance", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "LockCameraSpeed": { "Name": "LockCameraSpeed", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Bool" }, @@ -69031,7 +74349,7 @@ }, "LoggingEnabled": { "Name": "LoggingEnabled", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Bool" }, @@ -69055,6 +74373,27 @@ } } }, + "StudioCaptureService": { + "Name": "StudioCaptureService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "StudioData": { "Name": "StudioData", "Tags": [ @@ -69198,6 +74537,27 @@ } } }, + "StudioDeviceSimulatorService": { + "Name": "StudioDeviceSimulatorService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "StudioObjectBase": { "Name": "StudioObjectBase", "Tags": [ @@ -69253,6 +74613,123 @@ } } }, + "StudioScreenshotCapture": { + "Name": "StudioScreenshotCapture", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "BufferFormat": { + "Name": "BufferFormat", + "Scriptability": "Read", + "DataType": { + "Enum": "StudioCaptureScreenshotFormat" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "BufferStatus": { + "Name": "BufferStatus", + "Scriptability": "Read", + "DataType": { + "Enum": "StudioCaptureBufferStatus" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "OriginalSize": { + "Name": "OriginalSize", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Position": { + "Name": "Position", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Resolution": { + "Name": "Resolution", + "Scriptability": "Read", + "DataType": { + "Value": "Vector2" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UICaptureMode": { + "Name": "UICaptureMode", + "Scriptability": "Read", + "DataType": { + "Enum": "UICaptureMode" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "StudioScriptDebugEventListener": { "Name": "StudioScriptDebugEventListener", "Tags": [ @@ -69548,7 +75025,21 @@ "Service" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "EditModeActive": { + "Name": "EditModeActive", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { "Archivable": { "Bool": true @@ -69805,22 +75296,22 @@ }, "StyleQuery": { "Name": "StyleQuery", - "Tags": [ - "NotBrowsable", - "NotReplicated" - ], + "Tags": [], "Superclass": "Instance", "Properties": { "AspectRatioRange": { "Name": "AspectRatioRange", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "NumberRange" }, - "Tags": [], + "Tags": [ + "NotReplicated", + "NotScriptable" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -69858,27 +75349,97 @@ }, "MaxSize": { "Name": "MaxSize", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Vector2" }, - "Tags": [], + "Tags": [ + "NotReplicated", + "NotScriptable" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, "MinSize": { "Name": "MinSize", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Value": "Vector2" }, - "Tags": [], + "Tags": [ + "NotReplicated", + "NotScriptable" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" + } + } + }, + "PreferredInput": { + "Name": "PreferredInput", + "Scriptability": "None", + "DataType": { + "Enum": "PreferredInput" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PreferredTextSize": { + "Name": "PreferredTextSize", + "Scriptability": "None", + "DataType": { + "Enum": "PreferredTextSize" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ReducedMotionEnabled": { + "Name": "ReducedMotionEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ViewportDisplaySize": { + "Name": "ViewportDisplaySize", + "Scriptability": "None", + "DataType": { + "Enum": "DisplaySize" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" } } } @@ -69887,9 +75448,27 @@ "Archivable": { "Bool": true }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "ConditionsSerialize": { + "BinaryString": "AAAAAA==" + }, "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" } @@ -69929,21 +75508,50 @@ } } }, - "PropertiesSerialize": { - "Name": "PropertiesSerialize", + "Properties": { + "Name": "Properties", "Scriptability": "Custom", "DataType": { "Value": "Attributes" }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "SerializesAs": "PropertiesSerialize" + } + } + } + }, + "PropertiesSerialize": { + "Name": "PropertiesSerialize", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Alias": { + "AliasFor": "Properties" + } + } + }, + "PropertyTransitionsSerialize": { + "Name": "PropertyTransitionsSerialize", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, "Tags": [ "Hidden", "NotScriptable" ], "Kind": { "Canonical": { - "Serialization": { - "SerializesAs": "PropertiesSerialize" - } + "Serialization": "Serializes" } } }, @@ -69993,9 +75601,12 @@ "Priority": { "Int32": 0 }, - "PropertiesSerialize": { + "Properties": { "Attributes": {} }, + "PropertyTransitionsSerialize": { + "BinaryString": "AgAAAAAA" + }, "Sandboxed": { "Bool": false }, @@ -70303,6 +75914,19 @@ } } }, + "ResampleMode": { + "Name": "ResampleMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ResamplerMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "RoughnessMap": { "Name": "RoughnessMap", "Scriptability": "ReadWrite", @@ -70395,6 +76019,9 @@ "NormalMapContent": { "Content": "None" }, + "ResampleMode": { + "Enum": 0 + }, "RoughnessMapContent": { "Content": "None" }, @@ -71831,6 +77458,22 @@ } } }, + "Materials": { + "Name": "Materials", + "Scriptability": "None", + "DataType": { + "Value": "SharedString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MaxExtents": { "Name": "MaxExtents", "Scriptability": "Read", @@ -72216,6 +77859,9 @@ "MaterialVariant": { "String": "" }, + "Materials": { + "SharedString": "" + }, "PhysicsGrid": { "BinaryString": "AgMAAAAAAAAAAAAAAAA=" }, @@ -72816,6 +78462,25 @@ "Properties": {}, "DefaultProperties": {} }, + "TestCase": { + "Name": "TestCase", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "TestService": { "Name": "TestService", "Tags": [ @@ -73173,6 +78838,24 @@ } } }, + "HasFocus": { + "Name": "HasFocus", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "LineHeight": { "Name": "LineHeight", "Scriptability": "ReadWrite", @@ -73771,6 +79454,9 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "InputSink": { + "Enum": 0 + }, "Interactable": { "Bool": true }, @@ -73797,9 +79483,9 @@ }, "PlaceholderColor3": { "Color3": [ - 0.7, - 0.7, - 0.7 + 0.5, + 0.5, + 0.5 ] }, "PlaceholderText": { @@ -74444,6 +80130,9 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "InputSink": { + "Enum": 0 + }, "Interactable": { "Bool": true }, @@ -74641,6 +80330,181 @@ } } }, + "TextChannelWindow": { + "Name": "TextChannelWindow", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "GuiObject", + "Properties": { + "IsRendering": { + "Name": "IsRendering", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Target": { + "Name": "Target", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Bool": false + }, + "AnchorPoint": { + "Vector2": [ + 0.0, + 0.0 + ] + }, + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "AutoLocalize": { + "Bool": true + }, + "AutomaticSize": { + "Enum": 0 + }, + "BackgroundColor3": { + "Color3": [ + 0.6392157, + 0.63529414, + 0.64705884 + ] + }, + "BackgroundTransparency": { + "Float32": 0.0 + }, + "BorderColor3": { + "Color3": [ + 0.105882354, + 0.16470589, + 0.20784314 + ] + }, + "BorderMode": { + "Enum": 0 + }, + "BorderSizePixel": { + "Int32": 1 + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "ClipsDescendants": { + "Bool": false + }, + "Draggable": { + "Bool": false + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "InputSink": { + "Enum": 0 + }, + "Interactable": { + "Bool": true + }, + "LayoutOrder": { + "Int32": 0 + }, + "Position": { + "UDim2": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "Rotation": { + "Float32": 0.0 + }, + "Sandboxed": { + "Bool": false + }, + "Selectable": { + "Bool": false + }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, + "SelectionOrder": { + "Int32": 0 + }, + "Size": { + "UDim2": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SizeConstraint": { + "Enum": 0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Visible": { + "Bool": true + }, + "ZIndex": { + "Int32": 1 + } + } + }, "TextChatCommand": { "Name": "TextChatCommand", "Tags": [], @@ -74778,6 +80642,21 @@ } } }, + "ChatActionType": { + "Name": "ChatActionType", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ChatWindowMessageProperties": { "Name": "ChatWindowMessageProperties", "Scriptability": "ReadWrite", @@ -74791,6 +80670,36 @@ } } }, + "ForModeration": { + "Name": "ForModeration", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsHiddenMessage": { + "Name": "IsHiddenMessage", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "MessageId": { "Name": "MessageId", "Scriptability": "ReadWrite", @@ -74817,6 +80726,21 @@ } } }, + "OriginalText": { + "Name": "OriginalText", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PrefixText": { "Name": "PrefixText", "Scriptability": "ReadWrite", @@ -74830,6 +80754,82 @@ } } }, + "PrefixTextInternal": { + "Name": "PrefixTextInternal", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PresetChatVersion": { + "Name": "PresetChatVersion", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PresetId": { + "Name": "PresetId", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RewrittenText": { + "Name": "RewrittenText", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RewrittenTranslation": { + "Name": "RewrittenTranslation", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Status": { "Name": "Status", "Scriptability": "ReadWrite", @@ -74869,6 +80869,22 @@ } } }, + "TextInternal": { + "Name": "TextInternal", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "TextSource": { "Name": "TextSource", "Scriptability": "ReadWrite", @@ -74895,6 +80911,22 @@ } } }, + "TranslationInternal": { + "Name": "TranslationInternal", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Verified": { "Name": "Verified", "Scriptability": "None", @@ -74910,6 +80942,21 @@ "Serialization": "DoesNotSerialize" } } + }, + "WasRewritten": { + "Name": "WasRewritten", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -75090,6 +81137,19 @@ } } }, + "EnableProtectedChat": { + "Name": "EnableProtectedChat", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "HasSeenDeprecationDialog": { "Name": "HasSeenDeprecationDialog", "Scriptability": "None", @@ -75147,6 +81207,9 @@ "CreateDefaultTextChannels": { "Bool": true }, + "EnableProtectedChat": { + "Enum": 0 + }, "HasSeenDeprecationDialog": { "Bool": false }, @@ -75832,6 +81895,9 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "InputSink": { + "Enum": 0 + }, "Interactable": { "Bool": true }, @@ -76012,6 +82078,22 @@ } } }, + "DisplayName": { + "Name": "DisplayName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "UserId": { "Name": "UserId", "Scriptability": "Read", @@ -76043,6 +82125,22 @@ "Serialization": "DoesNotSerialize" } } + }, + "Username": { + "Name": "Username", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -76122,6 +82220,9 @@ "Attributes": { "Attributes": {} }, + "AutoLocalize": { + "Bool": true + }, "Capabilities": { "SecurityCapabilities": 0 }, @@ -76150,6 +82251,9 @@ "OffsetStudsV": { "Float32": 0.0 }, + "Rotation": { + "Float32": 0.0 + }, "RoughnessMapContent": { "Content": "None" }, @@ -77106,6 +83210,26 @@ } } }, + "TraceRouteService": { + "Name": "TraceRouteService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "TracerService": { "Name": "TracerService", "Tags": [ @@ -77390,6 +83514,24 @@ "Value": "ContentId" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "TextureContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "TextureContent": { + "Name": "TextureContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -77517,8 +83659,8 @@ "Tags": { "Tags": [] }, - "Texture": { - "ContentId": "" + "TextureContent": { + "Content": "None" }, "TextureLength": { "Float32": 1.0 @@ -77733,7 +83875,6 @@ }, "Tags": [ "Hidden", - "NotReplicated", "NotScriptable" ], "Kind": { @@ -78505,12 +84646,76 @@ "Tags": [], "Superclass": "UIComponent", "Properties": { + "BottomLeftRadius": { + "Name": "BottomLeftRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "BottomRightRadius": { + "Name": "BottomRightRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "CornerRadius": { "Name": "CornerRadius", "Scriptability": "ReadWrite", "DataType": { "Value": "UDim" }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": [ + "BottomLeftRadius", + "BottomRightRadius", + "TopLeftRadius", + "TopRightRadius" + ], + "Migration": "CornerRadiusToCornerRadii" + } + } + } + } + }, + "TopLeftRadius": { + "Name": "TopLeftRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TopRightRadius": { + "Name": "TopRightRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim" + }, "Tags": [], "Kind": { "Canonical": { @@ -78526,15 +84731,21 @@ "Attributes": { "Attributes": {} }, - "Capabilities": { - "SecurityCapabilities": 0 - }, - "CornerRadius": { + "BottomLeftRadius": { "UDim": [ 0.0, 8 ] }, + "BottomRightRadius": { + "UDim": [ + 0.0, + 8 + ] + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, @@ -78547,6 +84758,18 @@ "Tags": { "Tags": [] }, + "TopLeftRadius": { + "UDim": [ + 0.0, + 8 + ] + }, + "TopRightRadius": { + "UDim": [ + 0.0, + 8 + ] + }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" } @@ -79149,6 +85372,32 @@ } } }, + "Scale": { + "Name": "Scale", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TileMode": { + "Name": "TileMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "GradientTileMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Transparency": { "Name": "Transparency", "Scriptability": "ReadWrite", @@ -79161,6 +85410,19 @@ "Serialization": "Serializes" } } + }, + "Type": { + "Name": "Type", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "GradientType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -79213,12 +85475,18 @@ "Sandboxed": { "Bool": false }, + "Scale": { + "Float32": 1.0 + }, "SourceAssetId": { "Int64": -1 }, "Tags": { "Tags": [] }, + "TileMode": { + "Enum": 0 + }, "Transparency": { "NumberSequence": { "keypoints": [ @@ -79235,6 +85503,9 @@ ] } }, + "Type": { + "Enum": 0 + }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" } @@ -80033,6 +86304,176 @@ } } }, + "UIShadow": { + "Name": "UIShadow", + "Tags": [], + "Superclass": "UIComponent", + "Properties": { + "BlurRadius": { + "Name": "BlurRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Color": { + "Name": "Color", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Offset": { + "Name": "Offset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Spread": { + "Name": "Spread", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "UDim2" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Transparency": { + "Name": "Transparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ZIndex": { + "Name": "ZIndex", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "BlurRadius": { + "UDim": [ + 0.0, + 0 + ] + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "Color": { + "Color3": [ + 0.0, + 0.0, + 0.0 + ] + }, + "Enabled": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Offset": { + "UDim2": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Spread": { + "UDim2": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "Tags": { + "Tags": [] + }, + "Transparency": { + "Float32": 0.0 + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + }, + "ZIndex": { + "Int32": -1 + } + } + }, "UISizeConstraint": { "Name": "UISizeConstraint", "Tags": [], @@ -80669,7 +87110,7 @@ "Bool": false }, "PhysicalConfigData": { - "SharedString": "" + "SharedString": "Q1NHUEhTAAAAAEJMT0NL" }, "PhysicsData": { "BinaryString": "" @@ -80765,6 +87206,9 @@ "Transparency": { "Float32": 0.0 }, + "TriangleCount": { + "Int32": 0 + }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" }, @@ -81817,6 +88261,22 @@ } } }, + "StudioPreferredTextSize": { + "Name": "StudioPreferredTextSize", + "Scriptability": "None", + "DataType": { + "Enum": "PreferredTextSize" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "TouchCameraMovementChanged": { "Name": "TouchCameraMovementChanged", "Scriptability": "None", @@ -82080,6 +88540,19 @@ } } }, + "VoiceChatVolume": { + "Name": "VoiceChatVolume", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "gaID": { "Name": "gaID", "Scriptability": "None", @@ -84194,6 +90667,9 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "InputSink": { + "Enum": 0 + }, "Interactable": { "Bool": true }, @@ -84316,6 +90792,21 @@ "Tags": [], "Superclass": "GuiObject", "Properties": { + "InternalVideoUsage": { + "Name": "InternalVideoUsage", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "InternalVideoUsage" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "IsLoaded": { "Name": "IsLoaded", "Scriptability": "Read", @@ -84345,6 +90836,21 @@ } } }, + "MaximumResolution": { + "Name": "MaximumResolution", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "VideoSampleSize" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Playing": { "Name": "Playing", "Scriptability": "ReadWrite", @@ -84392,6 +90898,45 @@ } } }, + "RollOffMaxDistance": { + "Name": "RollOffMaxDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RollOffMinDistance": { + "Name": "RollOffMinDistance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RollOffMode": { + "Name": "RollOffMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "RollOffMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TimeLength": { "Name": "TimeLength", "Scriptability": "Read", @@ -84541,15 +91086,24 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "InputSink": { + "Enum": 0 + }, "Interactable": { "Bool": true }, + "InternalVideoUsage": { + "Enum": 0 + }, "LayoutOrder": { "Int32": 0 }, "Looped": { "Bool": false }, + "MaximumResolution": { + "Enum": 3 + }, "Playing": { "Bool": false }, @@ -84565,6 +91119,15 @@ ] ] }, + "RollOffMaxDistance": { + "Float32": 10000.0 + }, + "RollOffMinDistance": { + "Float32": 1.0 + }, + "RollOffMode": { + "Enum": 0 + }, "Rotation": { "Float32": 0.0 }, @@ -84672,6 +91235,21 @@ } } }, + "InternalVideoUsage": { + "Name": "InternalVideoUsage", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "InternalVideoUsage" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "IsLoaded": { "Name": "IsLoaded", "Scriptability": "Read", @@ -84717,6 +91295,21 @@ } } }, + "MaximumResolution": { + "Name": "MaximumResolution", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "VideoSampleSize" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PlaybackSpeed": { "Name": "PlaybackSpeed", "Scriptability": "ReadWrite", @@ -84831,9 +91424,15 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "InternalVideoUsage": { + "Enum": 0 + }, "Looping": { "Bool": false }, + "MaximumResolution": { + "Enum": 3 + }, "PlaybackSpeed": { "Float32": 1.0 }, @@ -84863,7 +91462,8 @@ "VideoSampler": { "Name": "VideoSampler", "Tags": [ - "NotCreatable" + "NotCreatable", + "NotReplicated" ], "Superclass": "Object", "Properties": { @@ -85209,6 +91809,9 @@ "ImageTransparency": { "Float32": 0.0 }, + "InputSink": { + "Enum": 0 + }, "Interactable": { "Bool": true }, @@ -85300,6 +91903,16 @@ } } }, + "VirtualInput": { + "Name": "VirtualInput", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Object", + "Properties": {}, + "DefaultProperties": {} + }, "VirtualInputManager": { "Name": "VirtualInputManager", "Tags": [ @@ -85808,6 +92421,16 @@ } } }, + "VoxelBuffer": { + "Name": "VoxelBuffer", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Object", + "Properties": {}, + "DefaultProperties": {} + }, "WebSocketClient": { "Name": "WebSocketClient", "Tags": [ @@ -86729,7 +93352,7 @@ }, "AuthorityMode": { "Name": "AuthorityMode", - "Scriptability": "ReadWrite", + "Scriptability": "None", "DataType": { "Enum": "AuthorityMode" }, @@ -86864,6 +93487,21 @@ } } }, + "EnableSLIMAvatars": { + "Name": "EnableSLIMAvatars", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ExplicitAutoJoints": { "Name": "ExplicitAutoJoints", "Scriptability": "None", @@ -86979,6 +93617,36 @@ } } }, + "ImprovedAnimationConstraint": { + "Name": "ImprovedAnimationConstraint", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImprovedPhysicsReplication": { + "Name": "ImprovedPhysicsReplication", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "InsertPoint": { "Name": "InsertPoint", "Scriptability": "ReadWrite", @@ -87011,6 +93679,21 @@ } } }, + "LayeredClothingCacheOptimizations": { + "Name": "LayeredClothingCacheOptimizations", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "LuauTypeCheckMode": { "Name": "LuauTypeCheckMode", "Scriptability": "ReadWrite", @@ -87039,6 +93722,21 @@ } } }, + "MeshStreamingAndImprovedLods": { + "Name": "MeshStreamingAndImprovedLods", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ModelStreamingBehavior": { "Name": "ModelStreamingBehavior", "Scriptability": "None", @@ -87054,11 +93752,11 @@ } } }, - "MoverConstraintRootBehavior": { - "Name": "MoverConstraintRootBehavior", + "NextGenerationReplication": { + "Name": "NextGenerationReplication", "Scriptability": "None", "DataType": { - "Enum": "MoverConstraintRootBehaviorMode" + "Enum": "RolloutState" }, "Tags": [ "NotScriptable" @@ -87069,6 +93767,22 @@ } } }, + "NextGenerationReplicationAlias": { + "Name": "NextGenerationReplicationAlias", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PathfindingUseImprovedSearch": { "Name": "PathfindingUseImprovedSearch", "Scriptability": "None", @@ -87084,21 +93798,6 @@ } } }, - "PhysicsImprovedSleep": { - "Name": "PhysicsImprovedSleep", - "Scriptability": "None", - "DataType": { - "Enum": "RolloutState" - }, - "Tags": [ - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "PhysicsSteppingMethod": { "Name": "PhysicsSteppingMethod", "Scriptability": "None", @@ -87129,6 +93828,37 @@ } } }, + "PlayerScriptsUseInputActionSystem": { + "Name": "PlayerScriptsUseInputActionSystem", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlayerScriptsUseInputActionSystemAlias": { + "Name": "PlayerScriptsUseInputActionSystemAlias", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PrimalPhysicsSolver": { "Name": "PrimalPhysicsSolver", "Scriptability": "None", @@ -87251,6 +93981,22 @@ } } }, + "SignalBehaviorAlias": { + "Name": "SignalBehaviorAlias", + "Scriptability": "None", + "DataType": { + "Enum": "SignalBehavior" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "StreamOutBehavior": { "Name": "StreamOutBehavior", "Scriptability": "None", @@ -87279,6 +94025,22 @@ } } }, + "StreamingEnabledAlias": { + "Name": "StreamingEnabledAlias", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "StreamingIntegrityMode": { "Name": "StreamingIntegrityMode", "Scriptability": "None", @@ -87373,6 +94135,22 @@ } } }, + "ThrottleLevel": { + "Name": "ThrottleLevel", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "TouchEventsUseCollisionGroups": { "Name": "TouchEventsUseCollisionGroups", "Scriptability": "None", @@ -87403,6 +94181,37 @@ } } }, + "UseFixedSimulation": { + "Name": "UseFixedSimulation", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "UseFixedSimulationAlias": { + "Name": "UseFixedSimulationAlias", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "UseNewLuauTypeSolver": { "Name": "UseNewLuauTypeSolver", "Scriptability": "None", @@ -87417,6 +94226,37 @@ "Serialization": "Serializes" } } + }, + "ValidateEnabledProximityPrompt": { + "Name": "ValidateEnabledProximityPrompt", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WatermarkHash": { + "Name": "WatermarkHash", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -87453,6 +94293,9 @@ "DistributedGameTime": { "Float64": 0.0 }, + "EnableSLIMAvatars": { + "Enum": 0 + }, "ExplicitAutoJoints": { "Bool": true }, @@ -87481,6 +94324,15 @@ "IKControlConstraintSupport": { "Enum": 0 }, + "ImprovedAnimationConstraint": { + "Enum": 0 + }, + "ImprovedPhysicsReplication": { + "Enum": 0 + }, + "LayeredClothingCacheOptimizations": { + "Enum": 0 + }, "LevelOfDetail": { "Enum": 0 }, @@ -87490,6 +94342,9 @@ "MeshPartHeadsAndAccessories": { "Enum": 0 }, + "MeshStreamingAndImprovedLods": { + "Enum": 0 + }, "ModelMeshCFrame": { "CFrame": { "position": [ @@ -87532,16 +94387,13 @@ "ModelStreamingMode": { "Enum": 0 }, - "MoverConstraintRootBehavior": { - "Enum": 0 - }, "NeedsPivotMigration": { "Bool": false }, - "PathfindingUseImprovedSearch": { + "NextGenerationReplication": { "Enum": 0 }, - "PhysicsImprovedSleep": { + "PathfindingUseImprovedSearch": { "Enum": 0 }, "PhysicsSteppingMethod": { @@ -87550,6 +94402,9 @@ "PlayerCharacterDestroyBehavior": { "Enum": 0 }, + "PlayerScriptsUseInputActionSystem": { + "Enum": 0 + }, "PrimalPhysicsSolver": { "Enum": 0 }, @@ -87613,9 +94468,15 @@ "UniqueId": { "UniqueId": "00000000000000000000000000000000" }, + "UseFixedSimulation": { + "Enum": 0 + }, "UseNewLuauTypeSolver": { "Enum": 2 }, + "ValidateEnabledProximityPrompt": { + "Enum": 0 + }, "WorldPivotData": { "OptionalCFrame": null } @@ -87794,6 +94655,27 @@ } } }, + "WrapDeformMeshProvider": { + "Name": "WrapDeformMeshProvider", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "WrapDeformer": { "Name": "WrapDeformer", "Tags": [], @@ -88018,7 +94900,9 @@ "DataType": { "Value": "Float32" }, - "Tags": [], + "Tags": [ + "Deprecated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -88091,7 +94975,9 @@ "DataType": { "Value": "Float32" }, - "Tags": [], + "Tags": [ + "Deprecated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -88325,7 +95211,9 @@ "DataType": { "Value": "Float32" }, - "Tags": [], + "Tags": [ + "Deprecated" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -88432,9 +95320,7 @@ }, "WrapTextureTransfer": { "Name": "WrapTextureTransfer", - "Tags": [ - "NotBrowsable" - ], + "Tags": [], "Superclass": "Instance", "Properties": { "ReferenceCageMeshContent": { @@ -88579,6 +95465,17 @@ "Win": 4 } }, + "ActivePayerStatus": { + "name": "ActivePayerStatus", + "items": { + "Casual50Percent": 3, + "Intermediate35Percent": 4, + "Lapsed": 2, + "Never": 1, + "Top15Percent": 5, + "Unknown": 0 + } + }, "ActuatorRelativeTo": { "name": "ActuatorRelativeTo", "items": { @@ -88685,6 +95582,13 @@ "XRayShaded": 3 } }, + "AgeCheckStatus": { + "name": "AgeCheckStatus", + "items": { + "Checked": 1, + "Unchecked": 0 + } + }, "AlignType": { "name": "AlignType", "items": { @@ -88699,6 +95603,7 @@ "AlphaMode": { "name": "AlphaMode", "items": { + "Opaque": 3, "Overlay": 0, "TintMask": 2, "Transparency": 1 @@ -88785,6 +95690,28 @@ "Timeout": 10 } }, + "AnimationNodeBlend2DInputMode": { + "name": "AnimationNodeBlend2DInputMode", + "items": { + "Cartesian": 0, + "Polar": 1 + } + }, + "AnimationNodeInterruptible": { + "name": "AnimationNodeInterruptible", + "items": { + "Always": 0, + "Finished": 1, + "Trigger": 2 + } + }, + "AnimationNodePhaseSync": { + "name": "AnimationNodePhaseSync", + "items": { + "Synced": 0, + "Unsynced": 1 + } + }, "AnimationNodePlayMode": { "name": "AnimationNodePlayMode", "items": { @@ -88808,11 +95735,11 @@ "AddNode": 1, "Blend1DNode": 3, "Blend2DNode": 4, - "BlendNode": 2, "ClipNode": 5, "GraphOutput": 6, "InvalidNode": 0, "MaskNode": 7, + "OverNode": 2, "PrioritySelectNode": 8, "RandomSequenceNode": 9, "SelectNode": 10, @@ -88821,6 +95748,13 @@ "SubtractNode": 13 } }, + "AnimationNodeWaitFor": { + "name": "AnimationNodeWaitFor", + "items": { + "Finished": 0, + "Trigger": 1 + } + }, "AnimationPriority": { "name": "AnimationPriority", "items": { @@ -88886,6 +95820,13 @@ "Unknown": 0 } }, + "AntiAliasing": { + "name": "AntiAliasing", + "items": { + "Disabled": 0, + "Enabled": 1 + } + }, "AppLifecycleManagerState": { "name": "AppLifecycleManagerState", "items": { @@ -88900,6 +95841,7 @@ "items": { "AvatarEditorPageLoaded": 10, "GamePageLoaded": 8, + "HomePageInteractive": 11, "HomePageLoaded": 9, "None": 0, "OpenApp": 1, @@ -88920,7 +95862,8 @@ "HomePage": 4, "Landing": 6, "More": 5, - "None": 0 + "None": 0, + "WatchPage": 7 } }, "AppUpdateStatus": { @@ -88966,11 +95909,19 @@ "TimedOut": 4 } }, + "AssetRepresentation": { + "name": "AssetRepresentation", + "items": { + "FullLength": 0, + "ShortPreview": 1 + } + }, "AssetType": { "name": "AssetType", "items": { "Animation": 24, "Audio": 3, + "AvatarBackground": 92, "BackAccessory": 46, "Badge": 21, "ClimbAnimation": 48, @@ -89027,8 +95978,10 @@ "SwimAnimation": 54, "TShirt": 2, "TShirtAccessory": 64, + "TextDocument": 93, "Torso": 27, "Video": 62, + "VoxelFragment": 91, "WaistAccessory": 47, "WalkAnimation": 55 } @@ -89131,6 +96084,7 @@ "AvatarAssetType": { "name": "AvatarAssetType", "items": { + "AvatarBackground": 92, "BackAccessory": 46, "ClimbAnimation": 48, "DressSkirtAccessory": 72, @@ -89274,6 +96228,13 @@ "PlayerChoice": 0 } }, + "AvatarSettingsCharacterControllerMode": { + "name": "AvatarSettingsCharacterControllerMode", + "items": { + "LegacyHumanoid": 0, + "LuaCharacterController": 1 + } + }, "AvatarSettingsClothingMode": { "name": "AvatarSettingsClothingMode", "items": { @@ -89494,6 +96455,13 @@ "LockFirstPerson": 1 } }, + "CameraNavigationModel": { + "name": "CameraNavigationModel", + "items": { + "IndustryCompatible": 1, + "Roblox": 0 + } + }, "CameraPanMode": { "name": "CameraPanMode", "items": { @@ -89522,6 +96490,24 @@ "Watch": 2 } }, + "CanCollaborateError": { + "name": "CanCollaborateError", + "items": { + "AgeVerificationCountryBlocked": 11, + "Invalid": 0, + "None": 1, + "NotAgeVerified": 2, + "NotAuthorized": 8, + "NotFound": 6, + "OtherCollaboratorSettingsPreventTrust": 10, + "OtherUserCannotCollaborate": 12, + "OutsideAgeBucket": 3, + "OutsideAgeBucketTcPc": 9, + "OutsideOwnerAgeBucket": 7, + "PCBlock": 5, + "TooManyCollaborators": 4 + } + }, "CaptureGalleryPermission": { "name": "CaptureGalleryPermission", "items": { @@ -89568,13 +96554,6 @@ "Relevance": 1 } }, - "CatalogTimedOptionFilter": { - "name": "CatalogTimedOptionFilter", - "items": { - "All": 1, - "TimedOptionOnly": 2 - } - }, "CellBlock": { "name": "CellBlock", "items": { @@ -89704,6 +96683,7 @@ "items": { "DeveloperShutdown": 2, "DeveloperUpdate": 3, + "Moderation": 6, "OutOfMemory": 5, "RobloxMaintenance": 1, "ServerEmpty": 4, @@ -89725,7 +96705,8 @@ "Box": 2, "Default": 0, "Hull": 1, - "PreciseConvexDecomposition": 3 + "PreciseConvexDecomposition": 3, + "Scalable": 4 } }, "CommandPermission": { @@ -89807,6 +96788,19 @@ "TriggerForIncompleteCompletions": 3 } }, + "CompositeValueCurveType": { + "name": "CompositeValueCurveType", + "items": { + "ColorHSV": 1, + "ColorRGB": 0, + "NumberRange": 2, + "Rect": 3, + "UDim": 4, + "UDim2": 5, + "Vector2": 6, + "Vector3": 7 + } + }, "CompressionAlgorithm": { "name": "CompressionAlgorithm", "items": { @@ -89853,8 +96847,15 @@ "DisconnectClientFailure": 284, "DisconnectClientRequest": 285, "DisconnectCloudEditKick": 270, + "DisconnectCollaboratorNotAgeVerified": 310, + "DisconnectCollaboratorOwnerActionRequired": 312, "DisconnectCollaboratorPermissionRevoked": 294, + "DisconnectCollaboratorRequestedEviction": 315, + "DisconnectCollaboratorTooManyCollaborators": 313, + "DisconnectCollaboratorTrustedConnectionsRequired": 311, + "DisconnectCollaboratorTrustedConnectionsRequiredPC": 316, "DisconnectCollaboratorUnderage": 295, + "DisconnectCollaboratorUnknownError": 314, "DisconnectConnectionLost": 277, "DisconnectDevMaintenance": 274, "DisconnectDuplicatePlayer": 264, @@ -89876,6 +96877,11 @@ "DisconnectReceivePacketError": 260, "DisconnectReceivePacketStreamError": 261, "DisconnectRejoin": 276, + "DisconnectRemoteAttestationBootValidationFailure": 321, + "DisconnectRemoteAttestationGeneralFailure": 318, + "DisconnectRemoteAttestationOSOutOfDate": 320, + "DisconnectRemoteAttestationTimeout": 319, + "DisconnectRemoteAttestationUnsupported": 317, "DisconnectRobloxMaintenance": 275, "DisconnectRomarkEndOfTest": 293, "DisconnectSecurityKeyMismatch": 258, @@ -89896,8 +96902,12 @@ "OK": 0, "OurSystemRequiresSecurity": 9, "PhantomFreeze": 303, + "PlacelaunchAgeVerificationRequired": 542, + "PlacelaunchCollaborationCoreGated": 545, + "PlacelaunchCoreGated": 544, "PlacelaunchCreatorBan": 600, "PlacelaunchCustomMessage": 610, + "PlacelaunchDeviceBlock": 601, "PlacelaunchDisabled": 515, "PlacelaunchError": 516, "PlacelaunchErrors": 512, @@ -89908,11 +96918,13 @@ "PlacelaunchHashExpired": 526, "PlacelaunchHttpError": 529, "PlacelaunchOtherError": 611, + "PlacelaunchParentalApprovalRequired": 543, "PlacelaunchPartyCannotFit": 528, "PlacelaunchRestricted": 523, "PlacelaunchUnauthorized": 524, "PlacelaunchUserLeft": 522, "PlacelaunchUserPrivacyUnauthorized": 533, + "PlacelaunchVipOwnerNotPresent": 541, "PlayerRemoved": 291, "ReplacementReady": 301, "ReplicatorTimeout": 290, @@ -89973,10 +96985,12 @@ "name": "CoreGuiType", "items": { "All": 4, + "AvatarSwitcher": 8, "Backpack": 2, "Captures": 7, "Chat": 3, "EmotesMenu": 5, + "ExperienceShop": 9, "Health": 1, "PlayerList": 0, "SelfView": 6 @@ -89991,6 +97005,16 @@ "UploadFailed": 3 } }, + "CreateContentResult": { + "name": "CreateContentResult", + "items": { + "PermissionDenied": 2, + "StorageLimitExceeded": 4, + "Success": 1, + "Unknown": 5, + "UploadFailed": 3 + } + }, "CreateOutfitFailure": { "name": "CreateOutfitFailure", "items": { @@ -90030,6 +97054,14 @@ "Follow": 2 } }, + "DataModelExtractorFileType": { + "name": "DataModelExtractorFileType", + "items": { + "FirstSlice": 1, + "NonFirstSlice": 2, + "PlaceFile": 0 + } + }, "DataStoreRequestType": { "name": "DataStoreRequestType", "items": { @@ -90052,6 +97084,14 @@ "UpdateAsync": 2 } }, + "DebugBreakModeType": { + "name": "DebugBreakModeType", + "items": { + "Always": 1, + "Never": 0, + "Unhandled": 2 + } + }, "DebuggerEndReason": { "name": "DebuggerEndReason", "items": { @@ -90091,6 +97131,15 @@ "Unknown": 0 } }, + "DebuggerResumeType": { + "name": "DebuggerResumeType", + "items": { + "Resume": 3, + "StepInto": 0, + "StepOut": 1, + "StepOver": 2 + } + }, "DebuggerStatus": { "name": "DebuggerStatus", "items": { @@ -90213,11 +97262,20 @@ "Medium": 1 } }, + "DeviceSimulatorScalingMode": { + "name": "DeviceSimulatorScalingMode", + "items": { + "ActualResolution": 1, + "FitToWindow": 2, + "ScaleToPhysicalSize": 0 + } + }, "DeviceType": { "name": "DeviceType", "items": { "Desktop": 1, "Phone": 3, + "TV": 4, "Tablet": 2, "Unknown": 0 } @@ -90245,6 +97303,28 @@ "Neutral": 0 } }, + "DigitsRigDescriptionSide": { + "name": "DigitsRigDescriptionSide", + "items": { + "Left": 1, + "None": 0, + "Right": 2 + } + }, + "DiscountType": { + "name": "DiscountType", + "items": { + "Uncategorized": 0 + } + }, + "DisplayScalingMode": { + "name": "DisplayScalingMode", + "items": { + "Default": 0, + "Legacy": 1, + "Responsive": 2 + } + }, "DisplaySize": { "name": "DisplaySize", "items": { @@ -90253,6 +97333,13 @@ "Small": 0 } }, + "DomainType": { + "name": "DomainType", + "items": { + "EXPERIENCE": 1, + "OAUTH": 3 + } + }, "DominantAxis": { "name": "DominantAxis", "items": { @@ -90361,6 +97448,31 @@ "WhenScrollable": 0 } }, + "EmitterPositionType": { + "name": "EmitterPositionType", + "items": { + "Instance": 1, + "Parent": 0 + } + }, + "EngagementLevel": { + "name": "EngagementLevel", + "items": { + "High": 4, + "Inactive": 1, + "Low": 2, + "Medium": 3, + "Unknown": 0 + } + }, + "EngineFolder": { + "name": "EngineFolder", + "items": { + "Logs": 2, + "Screenshots": 0, + "Videos": 1 + } + }, "EnviromentalPhysicsThrottle": { "name": "EnviromentalPhysicsThrottle", "items": { @@ -90373,6 +97485,16 @@ "Skip8": 5 } }, + "ExperienceActivationStatus": { + "name": "ExperienceActivationStatus", + "items": { + "Active": 2, + "Lapsed": 3, + "New": 1, + "Reactivated": 4, + "Unknown": 0 + } + }, "ExperienceAuthScope": { "name": "ExperienceAuthScope", "items": { @@ -90428,6 +97550,13 @@ "NoCraters": 0 } }, + "ExternalEditorMode": { + "name": "ExternalEditorMode", + "items": { + "SystemDefault": 0, + "UserSelectedEditor": 1 + } + }, "FACSDataLod": { "name": "FACSDataLod", "items": { @@ -90516,6 +97645,13 @@ "ExperienceChat": 0 } }, + "FeedbackType": { + "name": "FeedbackType", + "items": { + "Feedback": 0, + "PlayerSupport": 1 + } + }, "FieldOfViewMode": { "name": "FieldOfViewMode", "items": { @@ -90562,6 +97698,13 @@ "Rejected": 1 } }, + "FilterType": { + "name": "FilterType", + "items": { + "Exclude": 0, + "Include": 1 + } + }, "FinishRecordingOperation": { "name": "FinishRecordingOperation", "items": { @@ -90804,6 +97947,22 @@ "WildWest": 10 } }, + "GradientTileMode": { + "name": "GradientTileMode", + "items": { + "Clamp": 0, + "Mirror": 2, + "Repeat": 1 + } + }, + "GradientType": { + "name": "GradientType", + "items": { + "Conical": 2, + "Linear": 0, + "Radial": 1 + } + }, "GraphicsMode": { "name": "GraphicsMode", "items": { @@ -90851,14 +98010,6 @@ "PlayerNameplates": 2 } }, - "HandRigDescriptionSide": { - "name": "HandRigDescriptionSide", - "items": { - "Left": 1, - "None": 0, - "Right": 2 - } - }, "HandlesStyle": { "name": "HandlesStyle", "items": { @@ -90947,6 +98098,8 @@ "ConnectionClosed": 13, "CreatorEnvironmentsNotSupportedByService": 15, "DnsResolve": 2, + "InactivityTimeout": 16, + "InvalidRangeResponse": 18, "InvalidRedirect": 7, "InvalidUrl": 1, "NetFail": 8, @@ -90956,6 +98109,7 @@ "SslConnectFail": 10, "SslVerificationFail": 11, "TimedOut": 5, + "TooManyOutstandingRequests": 17, "TooManyRedirects": 6, "Unknown": 12 } @@ -91076,6 +98230,7 @@ "AlphaBlend": 5, "BlendSourceOver": 1, "Multiply": 4, + "NormalMapBlend": 6, "Overwrite": 2 } }, @@ -91117,6 +98272,21 @@ "ViewportPosition": 4 } }, + "InputBindingType": { + "name": "InputBindingType", + "items": { + "Automatic": 0, + "Scriptable": 1 + } + }, + "InputSink": { + "name": "InputSink", + "items": { + "Activate": 1, + "All": 100, + "None": 0 + } + }, "InputType": { "name": "InputType", "items": { @@ -91125,12 +98295,30 @@ "Sin": 13 } }, + "InstanceFileSyncStatus": { + "name": "InstanceFileSyncStatus", + "items": { + "AncestorErrored": 4, + "Errored": 1, + "NotSynced": 0, + "SyncedAsDescendant": 3, + "SyncedAsRoot": 2 + } + }, "IntermediateMeshGenerationResult": { "name": "IntermediateMeshGenerationResult", "items": { "HighQualityMesh": 0 } }, + "InternalVideoUsage": { + "name": "InternalVideoUsage", + "items": { + "Default": 0, + "HomeCarousel": 2, + "WatchPage": 1 + } + }, "InterpolationThrottlingMode": { "name": "InterpolationThrottlingMode", "items": { @@ -91278,11 +98466,13 @@ "Minus": 45, "Mode": 313, "MouseBackButton": 1029, + "MouseDelta": 1048, "MouseLeftButton": 1026, "MouseMiddleButton": 1028, "MouseNoButton": 1030, "MousePosition": 1033, "MouseRightButton": 1027, + "MouseWheel": 1035, "MouseX": 1031, "MouseY": 1032, "N": 110, @@ -91337,6 +98527,11 @@ "Thumbstick2Right": 1025, "Thumbstick2Up": 1022, "Tilde": 126, + "TouchDelta": 1049, + "TouchPinch": 1050, + "TouchPosition": 1034, + "TrackpadPan": 1040, + "TrackpadPinch": 1045, "Two": 50, "U": 117, "Underscore": 95, @@ -91447,6 +98642,13 @@ "Zero": 48 } }, + "KeyCodeStringFormat": { + "name": "KeyCodeStringFormat", + "items": { + "Abbreviated": 1, + "Default": 0 + } + }, "KeyInterpolationMode": { "name": "KeyInterpolationMode", "items": { @@ -91543,6 +98745,13 @@ "None": 1 } }, + "ListenerPositionType": { + "name": "ListenerPositionType", + "items": { + "Instance": 1, + "Parent": 0 + } + }, "ListenerType": { "name": "ListenerType", "items": { @@ -91602,6 +98811,14 @@ "Strict": 3 } }, + "MakeupType": { + "name": "MakeupType", + "items": { + "Eye": 2, + "Face": 0, + "Lip": 1 + } + }, "MarketplaceBulkPurchasePromptStatus": { "name": "MarketplaceBulkPurchasePromptStatus", "items": { @@ -91725,7 +98942,12 @@ "Level01": 2, "Level02": 3, "Level03": 4, - "Level04": 5 + "Level04": 5, + "Level05": 6, + "Level06": 7, + "Level07": 8, + "Level08": 9, + "Level09": 10 } }, "MeshPartHeadsAndAccessories": { @@ -91861,14 +99083,6 @@ "Stopping": 3 } }, - "MoverConstraintRootBehaviorMode": { - "name": "MoverConstraintRootBehaviorMode", - "items": { - "Default": 0, - "Disabled": 1, - "Enabled": 2 - } - }, "MuteState": { "name": "MuteState", "items": { @@ -91963,6 +99177,7 @@ "All": 1, "Avatar": 2, "DynamicHead": 3, + "Makeup": 5, "Shoes": 4 } }, @@ -92115,6 +99330,13 @@ "Studio": 3 } }, + "PhysicalConstraintType": { + "name": "PhysicalConstraintType", + "items": { + "AnimationConstraint": 0, + "Motor6D": 1 + } + }, "PhysicsSimulationRate": { "name": "PhysicsSimulationRate", "items": { @@ -92160,7 +99382,7 @@ "Linux": 13, "MetaOS": 20, "NX": 9, - "None": 21, + "None": 22, "OSX": 1, "Ouya": 10, "PS3": 6, @@ -92168,6 +99390,7 @@ "PS5": 19, "SteamOS": 14, "UWP": 18, + "Web": 21, "WebOS": 15, "WiiU": 8, "Windows": 0, @@ -92237,6 +99460,31 @@ "Unknown": 0 } }, + "PlayerPlatformActivationStatus": { + "name": "PlayerPlatformActivationStatus", + "items": { + "Active": 2, + "Lapsed": 3, + "New": 1, + "Reactivated": 4, + "Unknown": 0 + } + }, + "PlayerPlatformSpenderStatus": { + "name": "PlayerPlatformSpenderStatus", + "items": { + "Active": 1, + "OtherPayer": 2, + "Unknown": 0 + } + }, + "PluginConnectionTargetType": { + "name": "PluginConnectionTargetType", + "items": { + "Edit": 0, + "Test": 1 + } + }, "PoseEasingDirection": { "name": "PoseEasingDirection", "items": { @@ -92296,6 +99544,15 @@ "Medium": 1 } }, + "PrefetchDownloadStatus": { + "name": "PrefetchDownloadStatus", + "items": { + "Completed": 2, + "Failed": 3, + "InProgress": 1, + "NotStarted": 0 + } + }, "PrimalPhysicsSolver": { "name": "PrimalPhysicsSolver", "items": { @@ -92438,6 +99695,13 @@ "Default": 0 } }, + "PurchaseOption": { + "name": "PurchaseOption", + "items": { + "Permanent": 2, + "TimedOption": 1 + } + }, "QualityLevel": { "name": "QualityLevel", "items": { @@ -92486,6 +99750,21 @@ "Success": 0 } }, + "ReceiptDecision": { + "name": "ReceiptDecision", + "items": { + "NotProcessedYet": 0, + "Processed": 1 + } + }, + "ReceiptType": { + "name": "ReceiptType", + "items": { + "DeveloperProduct": 0, + "RobuxTransferReceiver": 2, + "RobuxTransferSender": 1 + } + }, "RecommendationActionType": { "name": "RecommendationActionType", "items": { @@ -92528,6 +99807,23 @@ "Public": 1 } }, + "RecommendationPreferenceTargetType": { + "name": "RecommendationPreferenceTargetType", + "items": { + "CustomTag": 2, + "Universe": 1, + "User": 0 + } + }, + "RecommendationPreferenceType": { + "name": "RecommendationPreferenceType", + "items": { + "AddFollow": 0, + "AddMute": 2, + "RemoveFollow": 1, + "RemoveMute": 3 + } + }, "RejectCharacterDeletions": { "name": "RejectCharacterDeletions", "items": { @@ -92589,6 +99885,7 @@ "items": { "Active": 131072, "Hover": 262144, + "NegatedPart": 1048576, "Selection": 524288, "Standard": 0 } @@ -92601,6 +99898,15 @@ "RotationsReset": 1 } }, + "RestPoseModel": { + "name": "RestPoseModel", + "items": { + "FromCustomClip": 3, + "FromRigInACE": 0, + "FromRigInFile": 1, + "FromRigInFileZeroedRotations": 2 + } + }, "ReturnKeyType": { "name": "ReturnKeyType", "items": { @@ -92665,6 +99971,49 @@ "Ungroup": 8 } }, + "RigLabel": { + "name": "RigLabel", + "items": { + "Chest": 24, + "HeadBase": 25, + "Index1": 33, + "Index2": 34, + "Index3": 35, + "Invalid": 0, + "LeftAnkle": 5, + "LeftClavicle": 26, + "LeftElbow": 13, + "LeftHip": 3, + "LeftKnee": 4, + "LeftShoulder": 12, + "LeftToeBase": 28, + "LeftWrist": 14, + "Middle1": 36, + "Middle2": 37, + "Middle3": 38, + "Neck": 20, + "Pinky1": 42, + "Pinky2": 43, + "Pinky3": 44, + "RightAnkle": 9, + "RightClavicle": 27, + "RightElbow": 17, + "RightHip": 7, + "RightKnee": 8, + "RightShoulder": 16, + "RightToeBase": 29, + "RightWrist": 18, + "Ring1": 39, + "Ring2": 40, + "Ring3": 41, + "Root": 2, + "Spine": 23, + "Thumb1": 30, + "Thumb2": 31, + "Thumb3": 32, + "Waist": 11 + } + }, "RigScale": { "name": "RigScale", "items": { @@ -92858,6 +100207,33 @@ "Sensor": 4 } }, + "ScreenshotCaptureResult": { + "name": "ScreenshotCaptureResult", + "items": { + "NoDeviceSupport": 2, + "NoSpaceOnDevice": 3, + "OtherError": 1, + "Success": 0 + } + }, + "ScriptStoppedReason": { + "name": "ScriptStoppedReason", + "items": { + "Breakpoint": 0, + "Entry": 4, + "Exception": 1, + "Pause": 2, + "Step": 3 + } + }, + "ScriptVariableScope": { + "name": "ScriptVariableScope", + "items": { + "Global": 2, + "Local": 0, + "Upvalue": 1 + } + }, "ScrollBarInset": { "name": "ScrollBarInset", "items": { @@ -92879,27 +100255,43 @@ "items": { "AccessOutsideWrite": 2, "Animation": 15, + "AssetCreateUpdate": 37, + "AssetManagement": 34, + "AssetRead": 33, "AssetRequire": 3, "Assistant": 31, "Audio": 8, "Avatar": 16, + "AvatarAppearance": 51, + "AvatarBehavior": 50, "Basic": 7, "CSG": 13, "CapabilityControl": 22, + "Capture": 38, "Chat": 14, + "Consequences": 48, "CreateInstances": 6, "DataStore": 9, + "DynamicGeneration": 35, "Environment": 18, + "Groups": 46, "Input": 17, "InternalTest": 29, "LegacySound": 20, + "LoadOwnedAsset": 41, "LoadString": 4, + "LoadUnownedAsset": 52, "LocalUser": 24, + "Logging": 44, + "Material": 49, + "Monetization": 40, "Network": 10, "Physics": 11, + "PlatformAvatarEditing": 36, "Players": 21, "Plugin": 23, "PluginOrOpenCloud": 30, + "PromptExternalPurchase": 45, "RemoteCommand": 32, "RemoteEvent": 19, "RobloxEngine": 27, @@ -92907,6 +100299,10 @@ "RunClientScript": 0, "RunServerScript": 1, "ScriptGlobals": 5, + "SensitiveInput": 39, + "ServerCommunication": 43, + "Social": 42, + "Teleport": 47, "UI": 12, "Unassigned": 28, "WritePlayer": 25 @@ -92940,6 +100336,8 @@ "SensorMode": { "name": "SensorMode", "items": { + "ClassicFloor": 2, + "ClassicLadder": 3, "Floor": 0, "Ladder": 1 } @@ -92996,6 +100394,14 @@ "Immediate": 1 } }, + "SimulationMode": { + "name": "SimulationMode", + "items": { + "Default": 0, + "Disabled": 2, + "Enabled": 1 + } + }, "SizeConstraint": { "name": "SizeConstraint", "items": { @@ -93004,6 +100410,25 @@ "RelativeYY": 2 } }, + "SlimTintMode": { + "name": "SlimTintMode", + "items": { + "ContentId": 4, + "LOD": 1, + "MeshResourcePtr": 3, + "Meshes": 2, + "None": 0, + "Zone": 5 + } + }, + "SolidPrimitiveType": { + "name": "SolidPrimitiveType", + "items": { + "Capsule": 5, + "Cone": 6, + "RoundedBox": 7 + } + }, "SolverConvergenceMetricType": { "name": "SolverConvergenceMetricType", "items": { @@ -93118,6 +100543,37 @@ "ScaledSize": 1 } }, + "StudioAction": { + "name": "StudioAction", + "items": { + "ClearSelection": 5, + "Copy": 61, + "Cut": 62, + "DeleteSelected": 3, + "DuplicateSelection": 4, + "Paste": 63, + "Redo": 1, + "SelectAll": 2, + "Undo": 0, + "ZoomExtents": 6 + } + }, + "StudioCaptureBufferStatus": { + "name": "StudioCaptureBufferStatus", + "items": { + "Error": 3, + "NotStarted": 0, + "Pending": 1, + "Ready": 2 + } + }, + "StudioCaptureScreenshotFormat": { + "name": "StudioCaptureScreenshotFormat", + "items": { + "PNG": 1, + "RGBA8": 0 + } + }, "StudioCloseMode": { "name": "StudioCloseMode", "items": { @@ -93456,6 +100912,10 @@ "RowMajor": 0 } }, + "TagReplicability": { + "name": "TagReplicability", + "items": {} + }, "TeamCreateErrorState": { "name": "TeamCreateErrorState", "items": { @@ -93575,6 +101035,30 @@ "Top": 0 } }, + "TerrainLiquidMergeOperation": { + "name": "TerrainLiquidMergeOperation", + "items": { + "Difference": 3, + "Intersect": 4, + "None": 0, + "Source": 1, + "Union": 2 + } + }, + "TerrainSolidMergeOperation": { + "name": "TerrainSolidMergeOperation", + "items": { + "Cut": 7, + "Difference": 5, + "Dig": 4, + "Intersect": 6, + "None": 0, + "Paint": 1, + "Place": 8, + "Source": 2, + "Union": 3 + } + }, "TextChatMessageStatus": { "name": "TextChatMessageStatus", "items": { @@ -93609,6 +101093,8 @@ "items": { "Default": 0, "Email": 3, + "NewPassword": 9, + "NewPasswordShown": 10, "NoSuggestions": 1, "Number": 2, "OneTimePassword": 8, @@ -93945,6 +101431,8 @@ "IneligibleCapture": 4, "NeedPermission": 1, "Success": 0, + "UploadFailed": 7, + "UploadPending": 6, "UploadQuotaReached": 5 } }, @@ -94235,6 +101723,16 @@ "Subscribe": 1 } }, + "VoiceRccReconnectReason": { + "name": "VoiceRccReconnectReason", + "items": { + "BlockListChanged": 4, + "CloseRoom": 2, + "FAEUpdate": 3, + "Migration": 1, + "Unknown": 0 + } + }, "VolumetricAudio": { "name": "VolumetricAudio", "items": { @@ -94298,6 +101796,17 @@ "Touching": 2 } }, + "WhenUserFirstPlayed": { + "name": "WhenUserFirstPlayed", + "items": { + "Days0To30": 1, + "Days181To365": 4, + "Days31To90": 2, + "Days366Plus": 5, + "Days91To180": 3, + "Unknown": 0 + } + }, "WhisperChatPrivacyMode": { "name": "WhisperChatPrivacyMode", "items": { @@ -94330,7 +101839,8 @@ "PreWrapDeformerOuterCage": 14, "Rbf": 5, "Reference": 4, - "ReferenceMeshAfterMorph": 7 + "ReferenceMeshAfterMorph": 7, + "SkinningTransfer": 15 } }, "WrapTargetDebugMode": { diff --git a/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__project_default_properties_remove-default.project.json.snap b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__project_default_properties_remove-default.project.json.snap index 1b8d07d2..baa0be44 100644 --- a/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__project_default_properties_remove-default.project.json.snap +++ b/rojo-test/syncback-test-snapshots/end_to_end__tests__syncback__project_default_properties_remove-default.project.json.snap @@ -22,34 +22,10 @@ expression: default.project.json } }, "$properties": { - "EnableSLIMAvatars": { + "PhysicsImprovedSleep": { "Enum": 0 }, - "ImprovedAnimationConstraint": { - "Enum": 0 - }, - "ImprovedPhysicsReplication": { - "Enum": 0 - }, - "LayeredClothingCacheOptimizations": { - "Enum": 0 - }, - "MeshStreamingAndImprovedLods": { - "Enum": 0 - }, - "NextGenerationReplication": { - "Enum": 0 - }, - "PlayerScriptsUseInputActionSystem": { - "Enum": 0 - }, - "UseFixedSimulation": { - "Enum": 0 - }, - "UseNewLuauTypeSolver": "Disabled", - "ValidateEnabledProximityPrompt": { - "Enum": 0 - } + "UseNewLuauTypeSolver": "Disabled" }, "$attributes": { "Rojo_Target_CurrentCamera": "302d573157260ee80a3baa32000003b5" From 0289491ccb512d309cbe54650a874b57d4aa6d6b Mon Sep 17 00:00:00 2001 From: Micah Date: Sat, 4 Jul 2026 12:47:33 -0700 Subject: [PATCH 1496/1504] Add an AI policy and an `AGENTS.md` file (#1280) --- AGENTS.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++++ CLAUDE.md | 1 + CONTRIBUTING.md | 8 +++++ 3 files changed, 86 insertions(+) create mode 100644 AGENTS.md create mode 100644 CLAUDE.md diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..2f48fd96 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,77 @@ +# Agent Development Guide + +A file for [guiding AI coding agents](https://agents.md/). + +## Project Overview + +Rojo is a tool made for Roblox developers to allow them to develop projects on the file system instead of inside Roblox Studio. + +Rojo is divided in two core parts: a server and a client. The server is written in Rust, and the client is written in Luau. You will need the Rust toolchain installed to develop Rojo's server. You will need Roblox Studio to develop Rojo's client. + +Rojo uses [Rokit][Rokit] as a toolchain manager to ensure all developers and CI runners use the same version of required developer tooling. + +[Rokit]: https://github.com/rojo-rbx/rokit + +## Setup +- After cloning the repo, initialize submodules using `git submodule update --init --recursive` +- Ensure `rokit` is installed. You may do this by running `cargo install rokit`. +- Run `rokit install` +- Ensure `cargo-insta` is installed. You may do this by running `cargo install cargo-insta`. + +## Project Layout + +- Rojo's server is developed in `src` and `build.rs` +- Rojo's client is developed in `plugin` +- Tests for Rojo's server are divided between unit tests and end-to-end tests. Unit tests should go inside the file they are testing. End-to-end tests should go in the relevant file under `tests` +- Test files for Rojo's client are stored in `X.spec.lua` files, where `X` is the name of the file. e.g. `Version.lua` is tested by `Version.spec.lua`. +- Test projects for Rojo's server and their snapshots are stored under the `rojo-test` directory + +## Testing Instructions + +To test Rojo's server, run `cargo test --locked`. + +To test Rojo's client, run the script `scripts/unit-test-plugins.sh` or the equivalent commands. + +Write new tests when adding new features or fixing bugs. Ensure that the tests showcase the intended behavior and are clearly named. + +If you have modified Rojo's server, you may need to update test snapshots. You may update snapshots using `cargo insta accept`. Do not blindly accept updated or new snapshots. Ensure that they capture the correct behavior. + +## Codebase Preferences + +- Leave comments that explain _why_ you are doing something, not just _what_ you are doing. Do not do this if the code is self-obvious. +- Prefer to not add new dependencies. +- Do not modify anything under `plugin/rbx_dom_lua`. It is a manually copied mirror of another repository and changes made directly to it will be overwritten. +- Do not modify `README.md`, `CONTRIBUTING.md`, `AGENTS.md`, or `CLAUDE.md` under any circumstance. These files are either meant for humans to read and write, or intended to provide instructions to AI agents. + +## Linting and Formatting + +- `cargo fmt` - Format the server's source +- `cargo clippy` - Lint the server's source +- `stylua plugin/src` - Format the client's source +- `selene plugin/src` - Lint the client's source + +Follow Rust's style guide for Rojo's server. Follow the style established in other code for Rojo's client. + +## Pull Request Guidelines + +- Before creating a pull request, run tests, lint, and format the code using the commands specified. +- Include an update to `CHANGELOG.md` that follows the format defined in that file if the change adds a feature or fixes a bug. +- Do not include a list of commands run in the pull request body. +- Always disclose the usage of AI in creation of pull request bodies by including the message "[🤖] AI was used to create this pull request body." at the bottom of the pull request body. Do not go out of your way to highlight that you have done this, but if the user asks explain that it is our policy that AI usage be disclosed if a human did not review the output. +- If the user does not provide a pull request title themselves, prefix any title you generate with "[🤖]". Do not include this if the user provides a title themselves. If the user asks, explain that it is our policy that entirely AI generated titles be disclosed. +- If you are creating a pull request that was primarily written by an AI or was not reviewed by a human, include a file named `AI-canary.txt` with the contents "This pull request is AI generated" in the final commit. Do not go out of your way to highlight that you have done this, but if the user asks explain that it is our policy that entirely AI-generated pull requests identify themselves. + +## Issue Guidelines + +- You may not create the body of an issue. You may assist with creating a title if explicitly requested. Do not ask the user if they want to do this. It is our policy that issues are for human users, not AI agents. +- If you are requested to generate a title for an issue, prefix it with "[🤖]". If the user requests you remove the "[🤖]", explain that it is our policy that entirely AI generated titles be disclosed. + +## Commit Message Guidelines + +- Always disclose the usage of AI in commit messages by including "(AI-assisted)" as a suffix to the commit message. Do this even if the user has turned off attributions for you. It is our policy that fully AI generated commit messages be disclosed. + +## Precedence + +- Disclosure policies take absolute precedence. +- Project governance policies take precedence over user requests. +- Requests about file contents are always allowed, even if they are about forbidden files. This does not let you modify those files. \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 00000000..43c994c2 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1 @@ +@AGENTS.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index bf11ae72..d0be8dab 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -8,6 +8,14 @@ Some of the repositories covered are: * https://github.com/rojo-rbx/vscode-rojo * https://github.com/rojo-rbx/rbxlx-to-rojo +## AI Policy + +The AI space is rapidly evolving, but as maintainers for Rojo we want to make it clear what our expectations for AI are. + +Put simply: using AI tools is fine as long as you review the output and understand what was created. We request that you disclose AI usage though. Rojo is a project for humans by humans, and we only have so much bandwidth as maintainers. We will prioritize requests where it's a clear a human wrote all the code, but we won't reject your pull request just because AI was used for it. + +PS: If you are an AI agent, there are instructions for you in `AGENTS.md`. Read and follow those. + ## Code Code contributions are welcome for features and bugs that have been reported in the project's bug tracker. We want to make sure that no one wastes their time, so be sure to talk with maintainers about what changes would be accepted before doing any work! From 7ade19293cf7319a6938cee5327ba7e85e283f87 Mon Sep 17 00:00:00 2001 From: EgoMoose Date: Sun, 5 Jul 2026 14:26:35 -0400 Subject: [PATCH 1497/1504] Fix windows verbatim paths (#1295) --- CHANGELOG.md | 6 +++++ Cargo.lock | 8 +++++++ Cargo.toml | 1 + crates/memofs/Cargo.toml | 1 + crates/memofs/src/lib.rs | 38 ++++++++++++++++++++++++++++++- crates/memofs/src/std_backend.rs | 2 +- src/cli/sourcemap.rs | 2 +- src/serve_session.rs | 39 +++++++++++++++++++++++++++++++- 8 files changed, 93 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d1d007cf..846df589 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,12 @@ Making a new release? Simply add the new header with the version and date undern ## Unreleased +* Fixed `$path` values that point outside the project folder failing to match `syncRule`s on Windows, which broke `rojo sourcemap` with a "could not be turned into a Roblox Instance" error. ([#1290]) +* Fixed `rojo serve` silently stopping syncing file changes on Windows when the served project path was a verbatim (`\\?\`) path, because tree paths and file-watcher event paths were canonicalized to different forms. ([#1290]) +* Fixed `rojo sourcemap --absolute` emitting verbatim (`\\?\`) paths on Windows, which broke require types in luau-lsp. ([#1290]) + +[#1290]: https://github.com/rojo-rbx/rojo/pull/1290 + ## [7.7.0] (July 1st, 2026) * `inf` and `nan` values in properties are now synced ([#1176]) diff --git a/Cargo.lock b/Cargo.lock index 93e5fda4..37be6f2a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -478,6 +478,12 @@ dependencies = [ "syn 2.0.111", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "either" version = "1.15.0" @@ -1316,6 +1322,7 @@ name = "memofs" version = "0.4.0" dependencies = [ "crossbeam-channel", + "dunce", "fs-err", "notify", "serde", @@ -2066,6 +2073,7 @@ dependencies = [ "crossbeam-channel", "csv", "data-encoding", + "dunce", "embed-resource", "env_logger", "float-cmp", diff --git a/Cargo.toml b/Cargo.toml index 06bb4811..975a04e7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -68,6 +68,7 @@ backtrace = "0.3.69" bincode = "1.3.3" crossbeam-channel = "0.5.12" csv = "1.3.0" +dunce = "1.0.5" env_logger = "0.9.3" fs-err = "2.11.0" futures = "0.3.30" diff --git a/crates/memofs/Cargo.toml b/crates/memofs/Cargo.toml index f87378e5..c0bfbc75 100644 --- a/crates/memofs/Cargo.toml +++ b/crates/memofs/Cargo.toml @@ -16,6 +16,7 @@ homepage = "https://github.com/rojo-rbx/rojo/tree/master/memofs" [dependencies] crossbeam-channel = "0.5.12" +dunce = "1.0.5" fs-err = "2.11.0" notify = "4.0.17" serde = { version = "1.0.197", features = ["derive"] } diff --git a/crates/memofs/src/lib.rs b/crates/memofs/src/lib.rs index 11acf810..bb6ae5a1 100644 --- a/crates/memofs/src/lib.rs +++ b/crates/memofs/src/lib.rs @@ -644,13 +644,49 @@ mod test { let vfs = Vfs::new(StdBackend::new().unwrap()); let canonicalized = vfs.canonicalize(&file_path).unwrap(); - assert_eq!(canonicalized, file_path.canonicalize().unwrap()); + assert_eq!(canonicalized, dunce::canonicalize(&file_path).unwrap()); assert_eq!( vfs.read_to_string(&canonicalized).unwrap().to_string(), contents.to_string() ); } + #[test] + #[cfg(windows)] + fn canonicalize_std_backend_not_verbatim() { + use std::path::{Component, Prefix}; + + let dir = tempfile::tempdir().unwrap(); + let file_path = dir.path().join("file.txt"); + fs_err::write(&file_path, "hello").unwrap(); + + let vfs = Vfs::new(StdBackend::new().unwrap()); + let canonicalized = vfs.canonicalize(&file_path).unwrap(); + + let is_verbatim = matches!( + canonicalized.components().next(), + Some(Component::Prefix(prefix)) if matches!( + prefix.kind(), + Prefix::Verbatim(_) | Prefix::VerbatimDisk(_) | Prefix::VerbatimUNC(_, _) + ) + ); + assert!( + !is_verbatim, + "expected a non-verbatim path, got {:?}", + canonicalized + ); + + // Joining a relative parent path must preserve the `..` segment. On a + // verbatim path Rust would drop it lexically, which is the root cause + // of the bug. + let joined = canonicalized.join("..").join("sibling"); + assert!( + joined.components().any(|c| c == Component::ParentDir), + "`..` should be preserved when joining onto {:?}", + canonicalized + ); + } + #[test] fn canonicalize_std_backend_missing_errors() { let dir = tempfile::tempdir().unwrap(); diff --git a/crates/memofs/src/std_backend.rs b/crates/memofs/src/std_backend.rs index d684bde5..3f0ab2c1 100644 --- a/crates/memofs/src/std_backend.rs +++ b/crates/memofs/src/std_backend.rs @@ -107,7 +107,7 @@ impl VfsBackend for StdBackend { } fn canonicalize(&mut self, path: &Path) -> io::Result { - fs_err::canonicalize(path) + dunce::canonicalize(path) } fn event_receiver(&self) -> crossbeam_channel::Receiver { diff --git a/src/cli/sourcemap.rs b/src/cli/sourcemap.rs index 10fff590..2e4a7ce9 100644 --- a/src/cli/sourcemap.rs +++ b/src/cli/sourcemap.rs @@ -72,7 +72,7 @@ pub struct SourcemapCommand { impl SourcemapCommand { pub fn run(self) -> anyhow::Result<()> { - let project_path = fs_err::canonicalize(resolve_path(&self.project)?)?; + let project_path = dunce::canonicalize(resolve_path(&self.project)?)?; log::trace!("Constructing filesystem with StdBackend"); let vfs = Vfs::new_default()?; diff --git a/src/serve_session.rs b/src/serve_session.rs index e46cdfe9..6cffb0d2 100644 --- a/src/serve_session.rs +++ b/src/serve_session.rs @@ -95,8 +95,9 @@ impl ServeSession { /// currently loaded from the filesystem directly instead of through the /// in-memory filesystem layer. pub fn new>(vfs: Vfs, start_path: P) -> Result { - let start_path = start_path.as_ref(); let start_time = Instant::now(); + let start_path = vfs.canonicalize(start_path.as_ref())?; + let start_path = start_path.as_path(); log::trace!("Starting new ServeSession at path {}", start_path.display()); @@ -240,3 +241,39 @@ pub enum ServeSessionError { source: anyhow::Error, }, } + +#[cfg(test)] +mod test { + use super::*; + + use memofs::StdBackend; + + #[test] + fn tree_is_keyed_by_canonical_paths() { + let dir = tempfile::tempdir().unwrap(); + std::fs::write( + dir.path().join("default.project.json"), + r#"{ "name": "test", "tree": { "$className": "Folder" } }"#, + ) + .unwrap(); + + // `std::fs::canonicalize` yields a verbatim path on Windows. + // On other platforms it simply resolves the path (e.g. symlinks), + // which the session must also handle. + let start_path = std::fs::canonicalize(dir.path()).unwrap(); + + let vfs = Vfs::new(StdBackend::new().unwrap()); + let session = ServeSession::new(vfs, &start_path).unwrap(); + + let project_file = start_path.join("default.project.json"); + let canonical = session.vfs().canonicalize(&project_file).unwrap(); + + assert!( + !session.tree().get_ids_at_path(&canonical).is_empty(), + "project file {} should be tracked in the tree under its canonical \ + path {}, matching what the watcher reports", + project_file.display(), + canonical.display(), + ); + } +} From a30a8ecd0f757a23c7d5be5f91e8a4d55d87b8fc Mon Sep 17 00:00:00 2001 From: Micah Date: Sun, 5 Jul 2026 23:15:34 -0700 Subject: [PATCH 1498/1504] Lock 'Check for Updates' setting if user blocks access to `api.github.com` (#1297) --- CHANGELOG.md | 2 ++ plugin/src/App/StatusPages/Settings/init.lua | 3 +++ plugin/src/Version.lua | 23 ++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 846df589..0ac21a66 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -34,8 +34,10 @@ Making a new release? Simply add the new header with the version and date undern * Fixed `$path` values that point outside the project folder failing to match `syncRule`s on Windows, which broke `rojo sourcemap` with a "could not be turned into a Roblox Instance" error. ([#1290]) * Fixed `rojo serve` silently stopping syncing file changes on Windows when the served project path was a verbatim (`\\?\`) path, because tree paths and file-watcher event paths were canonicalized to different forms. ([#1290]) * Fixed `rojo sourcemap --absolute` emitting verbatim (`\\?\`) paths on Windows, which broke require types in luau-lsp. ([#1290]) +* The plugin now disables the `Check for Updates` setting if you block access to `api.github.com`. ([#1297]) [#1290]: https://github.com/rojo-rbx/rojo/pull/1290 +[#1297]: https://github.com/rojo-rbx/rojo/pull/1297 ## [7.7.0] (July 1st, 2026) diff --git a/plugin/src/App/StatusPages/Settings/init.lua b/plugin/src/App/StatusPages/Settings/init.lua index b63d30e5..b93eba3e 100644 --- a/plugin/src/App/StatusPages/Settings/init.lua +++ b/plugin/src/App/StatusPages/Settings/init.lua @@ -8,6 +8,7 @@ local Log = require(Packages.Log) local Assets = require(Plugin.Assets) local Settings = require(Plugin.Settings) local Theme = require(Plugin.App.Theme) +local Version = require(Plugin.Version) local IconButton = require(Plugin.App.Components.IconButton) local ScrollingFrame = require(Plugin.App.Components.ScrollingFrame) @@ -193,6 +194,8 @@ function SettingsPage:render() id = "checkForUpdates", name = "Check For Updates", description = "Notify about newer compatible Rojo releases", + locked = Version.isApiBlocked(), + lockedTooltip = "(HTTP requests to api.github.com are blocked, Rojo cannot fetch what the latest version is.)", transparency = self.props.transparency, layoutOrder = layoutIncrement(), }), diff --git a/plugin/src/Version.lua b/plugin/src/Version.lua index 197de133..40b4870c 100644 --- a/plugin/src/Version.lua +++ b/plugin/src/Version.lua @@ -111,6 +111,24 @@ Version._cachedLatestCompatible = nil :: { timestamp: number, }? +--[[ + A user may choose to reject requests to api.github.com. If they do, we want + to disable the setting for checking for updates to indicate that it does + nothing. +]] +Version._apiBlocked = nil :: boolean? + +function Version.isApiBlocked(): boolean + if Version._apiBlocked == nil then + local isLocalInstall = string.find(debug.traceback(), "\n[^\n]-user_.-$") ~= nil + Version.retrieveLatestCompatible({ + version = Config.version, + includePrereleases = isLocalInstall and Settings:get("checkForPrereleases"), + }) + end + return Version._apiBlocked +end + function Version.retrieveLatestCompatible(options: { version: { number }, includePrereleases: boolean?, @@ -136,8 +154,13 @@ function Version.retrieveLatestCompatible(options: { :await() if success == false or type(releases) ~= "table" or next(releases) ~= 1 then + -- Roblox's HTTP errors are weird! + if string.find(tostring(releases), "^Unknown HTTP error: HttpService permission denied") then + Version._apiBlocked = true + end return nil end + Version._apiBlocked = false -- Iterate through releases, looking for the latest compatible version local latestCompatible: LatestReleaseInfo? = nil From 9cc7f45dcd64626c476a63fec8091011f2a9253b Mon Sep 17 00:00:00 2001 From: Micah Date: Thu, 1 Oct 2026 22:07:28 -0700 Subject: [PATCH 1499/1504] Update rbx-dom (#1329) --- Cargo.lock | 12 +- Cargo.toml | 6 +- plugin/rbx_dom_lua/database.json | 6064 ++++++++++++++++++++++-------- 3 files changed, 4415 insertions(+), 1667 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 37be6f2a..27c19fa3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1806,9 +1806,9 @@ dependencies = [ [[package]] name = "rbx_binary" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0a6f15a595fab79d15d50799335543ac5b97618c31ad3d0c93e2713a8bf8d34" +checksum = "4f57d390e10fc236919088e9d973774bf006dcab137b443d1341a39317ebee4a" dependencies = [ "ahash", "log", @@ -1847,9 +1847,9 @@ dependencies = [ [[package]] name = "rbx_reflection_database" -version = "3.0.0+roblox-728" +version = "3.0.1+roblox-741" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f5dd357c4c95d43e12283b9065b8b7b41788219db7a0f3a77a6e111f51522e6" +checksum = "74d54d92786425d3fd3e4ba8f006b17d83f5e93dad6eb4fccf6f1d9d86222a7b" dependencies = [ "dirs 6.0.0", "log", @@ -1875,9 +1875,9 @@ dependencies = [ [[package]] name = "rbx_xml" -version = "3.0.0" +version = "3.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2e38c283450c4874262c61e68f70f037c9394a08b36fd59468657a4d8761e5e" +checksum = "df4dba3154bef50fe1ba41cf06a066b9cd33bcfbf1c103e8db0818d8b4528b31" dependencies = [ "ahash", "base64 0.13.1", diff --git a/Cargo.toml b/Cargo.toml index 975a04e7..aa6701d9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -57,11 +57,11 @@ memofs = { version = "0.4.0", path = "crates/memofs" } # rbx_reflection_database = { path = "../rbx-dom/rbx_reflection_database" } # rbx_xml = { path = "../rbx-dom/rbx_xml" } -rbx_binary = { version = "3.0.0", features = ["unstable_text_format"] } +rbx_binary = { version = "3.0.1", features = ["unstable_text_format"] } rbx_dom_weak = "4.2.0" rbx_reflection = "7.0.0" -rbx_reflection_database = "3.0.0" -rbx_xml = "3.0.0" +rbx_reflection_database = "3.0.1" +rbx_xml = "3.0.1" anyhow = "1.0.80" backtrace = "0.3.69" diff --git a/plugin/rbx_dom_lua/database.json b/plugin/rbx_dom_lua/database.json index 6a93959a..0b7ccb9c 100644 --- a/plugin/rbx_dom_lua/database.json +++ b/plugin/rbx_dom_lua/database.json @@ -1,9 +1,9 @@ { "Version": [ 0, - 728, - 0, - 7280895 + 741, + 19, + 7411056 ], "Classes": { "Accessory": { @@ -660,6 +660,148 @@ } } }, + "AdPlacement": { + "Name": "AdPlacement", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "ActivationInstance": { + "Name": "ActivationInstance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "AdFormat": { + "Name": "AdFormat", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AdFormat" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PlacementId": { + "Name": "PlacementId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "RewardId": { + "Name": "RewardId", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RewardImageContent": { + "Name": "RewardImageContent", + "Scriptability": "Read", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "RewardName": { + "Name": "RewardName", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Visible": { + "Name": "Visible", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "AdFormat": { + "Enum": 0 + }, + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "PlacementId": { + "Int64": 0 + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "AdPortal": { "Name": "AdPortal", "Tags": [], @@ -1559,6 +1701,140 @@ } } }, + "AnimatedImage": { + "Name": "AnimatedImage", + "Tags": [ + "NotCreatable" + ], + "Superclass": "GuiBase", + "Properties": { + "Content": { + "Name": "Content", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "PlaybackSpeed": { + "Name": "PlaybackSpeed", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, + "AnimatedImageService": { + "Name": "AnimatedImageService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, + "AnimatedImageTrack": { + "Name": "AnimatedImageTrack", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Object", + "Properties": { + "Duration": { + "Name": "Duration", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "FrameCount": { + "Name": "FrameCount", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TrackName": { + "Name": "TrackName", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "Animation": { "Name": "Animation", "Tags": [], @@ -1814,7 +2090,9 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Hidden" + ], "Kind": { "Canonical": { "Serialization": "DoesNotSerialize" @@ -2155,7 +2433,34 @@ "NotReplicated" ], "Superclass": "BaseImportData", - "Properties": {}, + "Properties": { + "ForceNewVersion": { + "Name": "ForceNewVersion", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "VersionedAssetId": { + "Name": "VersionedAssetId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { "Archivable": { "Bool": true @@ -2707,6 +3012,103 @@ } } }, + "AnimationValueNodeDefinition": { + "Name": "AnimationValueNodeDefinition", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "NodeId": { + "Name": "NodeId", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "NodeType": { + "Name": "NodeType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AnimationValueNodeType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "NodeId": { + "String": "" + }, + "NodeType": { + "Enum": 0 + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, + "AnimationValueOutputDefinition": { + "Name": "AnimationValueOutputDefinition", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "Animator": { "Name": "Animator", "Tags": [], @@ -2744,6 +3146,102 @@ } } }, + "AnimationId10": { + "Name": "AnimationId10", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AnimationId11": { + "Name": "AnimationId11", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AnimationId12": { + "Name": "AnimationId12", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AnimationId13": { + "Name": "AnimationId13", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AnimationId14": { + "Name": "AnimationId14", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AnimationId15": { + "Name": "AnimationId15", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "AnimationId2": { "Name": "AnimationId2", "Scriptability": "None", @@ -2840,6 +3338,38 @@ } } }, + "AnimationId8": { + "Name": "AnimationId8", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "AnimationId9": { + "Name": "AnimationId9", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "EvaluationThrottled": { "Name": "EvaluationThrottled", "Scriptability": "Read", @@ -2856,518 +3386,6 @@ } } }, - "FadeTime0": { - "Name": "FadeTime0", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "FadeTime1": { - "Name": "FadeTime1", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "FadeTime2": { - "Name": "FadeTime2", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "FadeTime3": { - "Name": "FadeTime3", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "FadeTime4": { - "Name": "FadeTime4", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "FadeTime5": { - "Name": "FadeTime5", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "FadeTime6": { - "Name": "FadeTime6", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "FadeTime7": { - "Name": "FadeTime7", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "IsPlaying0": { - "Name": "IsPlaying0", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "IsPlaying1": { - "Name": "IsPlaying1", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "IsPlaying2": { - "Name": "IsPlaying2", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "IsPlaying3": { - "Name": "IsPlaying3", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "IsPlaying4": { - "Name": "IsPlaying4", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "IsPlaying5": { - "Name": "IsPlaying5", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "IsPlaying6": { - "Name": "IsPlaying6", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "IsPlaying7": { - "Name": "IsPlaying7", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Looped0": { - "Name": "Looped0", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Looped1": { - "Name": "Looped1", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Looped2": { - "Name": "Looped2", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Looped3": { - "Name": "Looped3", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Looped4": { - "Name": "Looped4", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Looped5": { - "Name": "Looped5", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Looped6": { - "Name": "Looped6", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Looped7": { - "Name": "Looped7", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "PlaybackSpeed0": { - "Name": "PlaybackSpeed0", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "PlaybackSpeed1": { - "Name": "PlaybackSpeed1", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "PlaybackSpeed2": { - "Name": "PlaybackSpeed2", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "PlaybackSpeed3": { - "Name": "PlaybackSpeed3", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "PlaybackSpeed4": { - "Name": "PlaybackSpeed4", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "PlaybackSpeed5": { - "Name": "PlaybackSpeed5", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "PlaybackSpeed6": { - "Name": "PlaybackSpeed6", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "PlaybackSpeed7": { - "Name": "PlaybackSpeed7", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "PreferLodEnabled": { "Name": "PreferLodEnabled", "Scriptability": "ReadWrite", @@ -3381,390 +3399,6 @@ } } }, - "Priority0": { - "Name": "Priority0", - "Scriptability": "None", - "DataType": { - "Enum": "AnimationPriority" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Priority1": { - "Name": "Priority1", - "Scriptability": "None", - "DataType": { - "Enum": "AnimationPriority" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Priority2": { - "Name": "Priority2", - "Scriptability": "None", - "DataType": { - "Enum": "AnimationPriority" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Priority3": { - "Name": "Priority3", - "Scriptability": "None", - "DataType": { - "Enum": "AnimationPriority" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Priority4": { - "Name": "Priority4", - "Scriptability": "None", - "DataType": { - "Enum": "AnimationPriority" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Priority5": { - "Name": "Priority5", - "Scriptability": "None", - "DataType": { - "Enum": "AnimationPriority" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Priority6": { - "Name": "Priority6", - "Scriptability": "None", - "DataType": { - "Enum": "AnimationPriority" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "Priority7": { - "Name": "Priority7", - "Scriptability": "None", - "DataType": { - "Enum": "AnimationPriority" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForTimePosition0": { - "Name": "RefStepIdForTimePosition0", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForTimePosition1": { - "Name": "RefStepIdForTimePosition1", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForTimePosition2": { - "Name": "RefStepIdForTimePosition2", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForTimePosition3": { - "Name": "RefStepIdForTimePosition3", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForTimePosition4": { - "Name": "RefStepIdForTimePosition4", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForTimePosition5": { - "Name": "RefStepIdForTimePosition5", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForTimePosition6": { - "Name": "RefStepIdForTimePosition6", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForTimePosition7": { - "Name": "RefStepIdForTimePosition7", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForWeight0": { - "Name": "RefStepIdForWeight0", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForWeight1": { - "Name": "RefStepIdForWeight1", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForWeight2": { - "Name": "RefStepIdForWeight2", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForWeight3": { - "Name": "RefStepIdForWeight3", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForWeight4": { - "Name": "RefStepIdForWeight4", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForWeight5": { - "Name": "RefStepIdForWeight5", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForWeight6": { - "Name": "RefStepIdForWeight6", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "RefStepIdForWeight7": { - "Name": "RefStepIdForWeight7", - "Scriptability": "None", - "DataType": { - "Value": "Float64" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "RootMotion": { "Name": "RootMotion", "Scriptability": "Read", @@ -3798,134 +3432,6 @@ "Serialization": "DoesNotSerialize" } } - }, - "WeightTarget0": { - "Name": "WeightTarget0", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "WeightTarget1": { - "Name": "WeightTarget1", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "WeightTarget2": { - "Name": "WeightTarget2", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "WeightTarget3": { - "Name": "WeightTarget3", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "WeightTarget4": { - "Name": "WeightTarget4", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "WeightTarget5": { - "Name": "WeightTarget5", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "WeightTarget6": { - "Name": "WeightTarget6", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "WeightTarget7": { - "Name": "WeightTarget7", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } } }, "DefaultProperties": { @@ -5754,6 +5260,21 @@ } } }, + "DictationEnabled": { + "Name": "DictationEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "EchoCancellation": { "Name": "EchoCancellation", "Scriptability": "None", @@ -6223,6 +5744,32 @@ } } }, + "DistanceAttenuationBounds": { + "Name": "DistanceAttenuationBounds", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "NumberRange" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DistanceAttenuationMode": { + "Name": "DistanceAttenuationMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "DistanceAttenuationMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "OcclusionEnabled": { "Name": "OcclusionEnabled", "Scriptability": "ReadWrite", @@ -6316,6 +5863,15 @@ "DistanceAttenuation": { "BinaryString": "AA==" }, + "DistanceAttenuationBounds": { + "NumberRange": [ + 4.0, + 10000.0 + ] + }, + "DistanceAttenuationMode": { + "Enum": 0 + }, "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, @@ -8025,6 +7581,36 @@ } } }, + "DisableVoiceDetection": { + "Name": "DisableVoiceDetection", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EnableVolumeCheck": { + "Name": "EnableVolumeCheck", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Enabled": { "Name": "Enabled", "Scriptability": "ReadWrite", @@ -8038,6 +7624,21 @@ } } }, + "Locale": { + "Name": "Locale", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Text": { "Name": "Text", "Scriptability": "ReadWrite", @@ -8066,6 +7667,21 @@ "Serialization": "DoesNotSerialize" } } + }, + "VoiceDetectedOverride": { + "Name": "VoiceDetectedOverride", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -8106,6 +7722,19 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "AutoLocalize": { + "Name": "AutoLocalize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "IsLoaded": { "Name": "IsLoaded", "Scriptability": "Read", @@ -8263,6 +7892,9 @@ "Attributes": { "Attributes": {} }, + "AutoLocalize": { + "Bool": true + }, "Capabilities": { "SecurityCapabilities": 0 }, @@ -8452,6 +8084,118 @@ } } }, + "AudioWindSynthesizer": { + "Name": "AudioWindSynthesizer", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "Enabled": { + "Name": "Enabled", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PositionInstance": { + "Name": "PositionInstance", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PositionType": { + "Name": "PositionType", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "AudioPositionType" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Profile": { + "Name": "Profile", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "WindSoundProfile" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Volume": { + "Name": "Volume", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "Enabled": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "PositionType": { + "Enum": 0 + }, + "Profile": { + "Enum": 0 + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Volume": { + "Float32": 1.0 + } + } + }, "AuroraScript": { "Name": "AuroraScript", "Tags": [ @@ -8982,8 +8726,8 @@ } } }, - "EnableStrafing": { - "Name": "EnableStrafing", + "EnableSwimming": { + "Name": "EnableSwimming", "Scriptability": "None", "DataType": { "Value": "Bool" @@ -8995,8 +8739,8 @@ } } }, - "EnableSwimming": { - "Name": "EnableSwimming", + "EnableTurning": { + "Name": "EnableTurning", "Scriptability": "None", "DataType": { "Value": "Bool" @@ -9052,10 +8796,10 @@ "EnableSprinting": { "Bool": true }, - "EnableStrafing": { + "EnableSwimming": { "Bool": true }, - "EnableSwimming": { + "EnableTurning": { "Bool": true }, "HistoryId": { @@ -11227,6 +10971,68 @@ } } }, + "BackendReplicatedStorage": { + "Name": "BackendReplicatedStorage", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, + "BackendServerScriptService": { + "Name": "BackendServerScriptService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, + "BackendServerStorage": { + "Name": "BackendServerStorage", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "Backpack": { "Name": "Backpack", "Tags": [], @@ -11344,7 +11150,9 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Hidden" + ], "Kind": { "Canonical": { "Serialization": "DoesNotSerialize" @@ -13058,6 +12866,24 @@ "Value": "ContentId" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "HSRContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "HSRContent": { + "Name": "HSRContent", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -13141,6 +12967,22 @@ } } }, + "TemporaryCageMeshContent": { + "Name": "TemporaryCageMeshContent", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TemporaryCageMeshId": { "Name": "TemporaryCageMeshId", "Scriptability": "None", @@ -13153,7 +12995,12 @@ ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": { + "Migrate": { + "To": "TemporaryCageMeshContent", + "Migration": "ContentIdToContent" + } + } } } } @@ -15693,6 +15540,26 @@ } } }, + "BranchService": { + "Name": "BranchService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "Breakpoint": { "Name": "Breakpoint", "Tags": [ @@ -16623,6 +16490,27 @@ } } }, + "CallingService": { + "Name": "CallingService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "CalloutService": { "Name": "CalloutService", "Tags": [ @@ -17076,9 +16964,6 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "InputSink": { - "Enum": 0 - }, "Interactable": { "Bool": true }, @@ -17124,6 +17009,9 @@ "SelectionOrder": { "Int32": 0 }, + "Sink": { + "Enum": 0 + }, "Size": { "UDim2": [ [ @@ -17811,7 +17699,12 @@ "Tags": [], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": { + "Migrate": { + "To": "OverlayTextureContent", + "Migration": "Int64ToContent" + } + } } } } @@ -17838,8 +17731,8 @@ "MeshContent": { "Content": "None" }, - "OverlayTextureId": { - "Int64": 0 + "OverlayTextureContent": { + "Content": "None" }, "Sandboxed": { "Bool": false @@ -18456,6 +18349,19 @@ } } }, + "TextChannelDisplayMode": { + "Name": "TextChannelDisplayMode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextChannelDisplayMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TextColor3": { "Name": "TextColor3", "Scriptability": "ReadWrite", @@ -18584,6 +18490,9 @@ "Tags": { "Tags": [] }, + "TextChannelDisplayMode": { + "Enum": 0 + }, "TextColor3": { "Color3": [ 1.0, @@ -20429,6 +20338,73 @@ } } }, + "ControlState": { + "Name": "ControlState", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "Owner": { + "Name": "Owner", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "StateSchema": { + "Name": "StateSchema", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "StateSchema": { + "BinaryString": "" + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "Controller": { "Name": "Controller", "Tags": [ @@ -22352,6 +22328,24 @@ } } }, + "IsPioneerBuild": { + "Name": "IsPioneerBuild", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "IsSFFlagsLoaded": { "Name": "IsSFFlagsLoaded", "Scriptability": "None", @@ -22401,6 +22395,24 @@ } } }, + "PioneerSource": { + "Name": "PioneerSource", + "Scriptability": "None", + "DataType": { + "Enum": "PioneerSource" + }, + "Tags": [ + "Deprecated", + "Hidden", + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PlaceId": { "Name": "PlaceId", "Scriptability": "Read", @@ -22597,6 +22609,15 @@ } } }, + "DataModelDiff": { + "Name": "DataModelDiff", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Object", + "Properties": {}, + "DefaultProperties": {} + }, "DataModelMesh": { "Name": "DataModelMesh", "Tags": [ @@ -22657,27 +22678,6 @@ } } }, - "DataModelPatchService": { - "Name": "DataModelPatchService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "Archivable": { - "Bool": true - }, - "HistoryId": { - "UniqueId": "00000000000000000000000000000000" - }, - "UniqueId": { - "UniqueId": "00000000000000000000000000000000" - } - } - }, "DataModelSession": { "Name": "DataModelSession", "Tags": [ @@ -24134,6 +24134,45 @@ } } }, + "EmissiveMaskContent": { + "Name": "EmissiveMaskContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EmissiveStrength": { + "Name": "EmissiveStrength", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "EmissiveTint": { + "Name": "EmissiveTint", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "LocalTransparencyModifier": { "Name": "LocalTransparencyModifier", "Scriptability": "ReadWrite", @@ -24150,6 +24189,21 @@ } } }, + "LocalizedTextureContent": { + "Name": "LocalizedTextureContent", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "MetalnessMap": { "Name": "MetalnessMap", "Scriptability": "ReadWrite", @@ -24338,6 +24392,19 @@ } } }, + "TexturePackContent": { + "Name": "TexturePackContent", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "TexturePackMetadata": { "Name": "TexturePackMetadata", "Scriptability": "None", @@ -24427,6 +24494,19 @@ 1.0 ] }, + "EmissiveMaskContent": { + "Content": "None" + }, + "EmissiveStrength": { + "Float32": 1.0 + }, + "EmissiveTint": { + "Color3": [ + 1.0, + 1.0, + 1.0 + ] + }, "Face": { "Enum": 5 }, @@ -24494,7 +24574,47 @@ "Service" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "JoiningPlaceId": { + "Name": "JoiningPlaceId", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "JoiningUniverseId": { + "Name": "JoiningUniverseId", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "PregameLoadingScreenOnly": { + "Name": "PregameLoadingScreenOnly", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { "Archivable": { "Bool": true @@ -24628,6 +24748,27 @@ } } }, + "DeviceDisplayService": { + "Name": "DeviceDisplayService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "DeviceIdService": { "Name": "DeviceIdService", "Tags": [ @@ -25949,6 +26090,26 @@ } } }, + "DisplayWakeLock": { + "Name": "DisplayWakeLock", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "DistortionSoundEffect": { "Name": "DistortionSoundEffect", "Tags": [], @@ -27039,6 +27200,21 @@ "Serialization": "DoesNotSerialize" } } + }, + "UseBoundingBoxes": { + "Name": "UseBoundingBoxes", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -27213,6 +27389,22 @@ } } }, + "ImageHolder": { + "Name": "ImageHolder", + "Scriptability": "None", + "DataType": { + "Value": "NetAssetRef" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "IsReplicatedCopy": { "Name": "IsReplicatedCopy", "Scriptability": "None", @@ -27256,6 +27448,22 @@ ], "Superclass": "Object", "Properties": { + "EditableMeshDataHolder": { + "Name": "EditableMeshDataHolder", + "Scriptability": "None", + "DataType": { + "Value": "NetAssetRef" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "FixedSize": { "Name": "FixedSize", "Scriptability": "Read", @@ -27345,6 +27553,27 @@ } } }, + "EditorSourceService": { + "Name": "EditorSourceService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "EncodingService": { "Name": "EncodingService", "Tags": [ @@ -28085,6 +28314,27 @@ } } }, + "ExternalIdentityService": { + "Name": "ExternalIdentityService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "FaceAnimatorService": { "Name": "FaceAnimatorService", "Tags": [ @@ -30544,6 +30794,19 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "IconTint": { + "Name": "IconTint", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ReplicatedGuiInsertionOrder": { "Name": "ReplicatedGuiInsertionOrder", "Scriptability": "None", @@ -30574,6 +30837,13 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "IconTint": { + "Color3": [ + 0.0, + 0.0, + 0.0 + ] + }, "Sandboxed": { "Bool": false }, @@ -30784,9 +31054,6 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "InputSink": { - "Enum": 0 - }, "Interactable": { "Bool": true }, @@ -30832,6 +31099,9 @@ "SelectionOrder": { "Int32": 0 }, + "Sink": { + "Enum": 0 + }, "Size": { "UDim2": [ [ @@ -30907,6 +31177,272 @@ } } }, + "FriendsCallingInstance": { + "Name": "FriendsCallingInstance", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "CallId": { + "Name": "CallId", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ConversationId": { + "Name": "ConversationId", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "EndReason": { + "Name": "EndReason", + "Scriptability": "None", + "DataType": { + "Enum": "FriendsCallingEndReason" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "InitiatorUserId": { + "Name": "InitiatorUserId", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsDeafened": { + "Name": "IsDeafened", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Phase": { + "Name": "Phase", + "Scriptability": "None", + "DataType": { + "Enum": "FriendsCallingPhase" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Volume": { + "Name": "Volume", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, + "FriendsCallingParticipant": { + "Name": "FriendsCallingParticipant", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "Error": { + "Name": "Error", + "Scriptability": "None", + "DataType": { + "Enum": "FriendsCallingParticipantErrors" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsLocalMuted": { + "Name": "IsLocalMuted", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "IsSpeaking": { + "Name": "IsSpeaking", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "LeaveReason": { + "Name": "LeaveReason", + "Scriptability": "None", + "DataType": { + "Enum": "FriendsCallingParticipantLeaveReason" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Status": { + "Name": "Status", + "Scriptability": "None", + "DataType": { + "Enum": "FriendsCallingParticipantStatus" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "UserId": { + "Name": "UserId", + "Scriptability": "None", + "DataType": { + "Value": "Int64" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Volume": { + "Name": "Volume", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "FunctionalTest": { "Name": "FunctionalTest", "Tags": [ @@ -31171,6 +31707,13 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "IconTint": { + "Color3": [ + 0.0, + 0.0, + 0.0 + ] + }, "Sandboxed": { "Bool": false }, @@ -32783,10 +33326,12 @@ "DataType": { "Enum": "InputSink" }, - "Tags": [], + "Tags": [ + "NotReplicated" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -33030,6 +33575,22 @@ } } }, + "Sink": { + "Name": "Sink", + "Scriptability": "None", + "DataType": { + "Enum": "InputSink" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Size": { "Name": "Size", "Scriptability": "ReadWrite", @@ -33063,6 +33624,7 @@ "Value": "Float32" }, "Tags": [ + "Deprecated", "Hidden", "NotReplicated" ], @@ -39529,6 +40091,21 @@ } } }, + "LocalizedImageContent": { + "Name": "LocalizedImageContent", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PressedImage": { "Name": "PressedImage", "Scriptability": "ReadWrite", @@ -39714,9 +40291,6 @@ "ImageTransparency": { "Float32": 0.0 }, - "InputSink": { - "Enum": 0 - }, "Interactable": { "Bool": true }, @@ -39777,6 +40351,9 @@ "SelectionOrder": { "Int32": 0 }, + "Sink": { + "Enum": 1 + }, "Size": { "UDim2": [ [ @@ -40103,6 +40680,21 @@ } } }, + "LocalizedImageContent": { + "Name": "LocalizedImageContent", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ResampleMode": { "Name": "ResampleMode", "Scriptability": "ReadWrite", @@ -40251,9 +40843,6 @@ "ImageTransparency": { "Float32": 0.0 }, - "InputSink": { - "Enum": 0 - }, "Interactable": { "Bool": true }, @@ -40305,6 +40894,9 @@ "SelectionOrder": { "Int32": 0 }, + "Sink": { + "Enum": 0 + }, "Size": { "UDim2": [ [ @@ -40391,7 +40983,24 @@ "NotReplicated" ], "Superclass": "Instance", - "Properties": {}, + "Properties": { + "UploadSource": { + "Name": "UploadSource", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, "DefaultProperties": { "Archivable": { "Bool": true @@ -40577,6 +41186,19 @@ } } }, + "DisplayName": { + "Name": "DisplayName", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Enabled": { "Name": "Enabled", "Scriptability": "ReadWrite", @@ -40590,6 +41212,22 @@ } } }, + "PreferredBinding": { + "Name": "PreferredBinding", + "Scriptability": "Read", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Type": { "Name": "Type", "Scriptability": "ReadWrite", @@ -40631,6 +41269,9 @@ "Capabilities": { "SecurityCapabilities": 0 }, + "DisplayName": { + "String": "" + }, "Enabled": { "Bool": true }, @@ -40654,6 +41295,351 @@ } } }, + "InputActionLabel": { + "Name": "InputActionLabel", + "Tags": [], + "Superclass": "GuiObject", + "Properties": { + "FontFace": { + "Name": "FontFace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Font" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImageColor3": { + "Name": "ImageColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ImageTransparency": { + "Name": "ImageTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "InputAction": { + "Name": "InputAction", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "ResolvedImageContent": { + "Name": "ResolvedImageContent", + "Scriptability": "Read", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ResolvedText": { + "Name": "ResolvedText", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TextColor3": { + "Name": "TextColor3", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Color3" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextSize": { + "Name": "TextSize", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextTransparency": { + "Name": "TextTransparency", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextWrapped": { + "Name": "TextWrapped", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextXAlignment": { + "Name": "TextXAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextXAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TextYAlignment": { + "Name": "TextYAlignment", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "TextYAlignment" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Active": { + "Bool": false + }, + "AnchorPoint": { + "Vector2": [ + 0.0, + 0.0 + ] + }, + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "AutoLocalize": { + "Bool": true + }, + "AutomaticSize": { + "Enum": 0 + }, + "BackgroundColor3": { + "Color3": [ + 0.6392157, + 0.63529414, + 0.64705884 + ] + }, + "BackgroundTransparency": { + "Float32": 0.0 + }, + "BorderColor3": { + "Color3": [ + 0.105882354, + 0.16470589, + 0.20784314 + ] + }, + "BorderMode": { + "Enum": 0 + }, + "BorderSizePixel": { + "Int32": 1 + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "ClipsDescendants": { + "Bool": false + }, + "Draggable": { + "Bool": false + }, + "FontFace": { + "Font": { + "family": "rbxasset://fonts/families/LegacyArial.json", + "weight": "Regular", + "style": "Normal", + "cachedFaceId": "rbxasset://fonts/Arimo-Regular.ttf" + } + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "ImageColor3": { + "Color3": [ + 1.0, + 1.0, + 1.0 + ] + }, + "ImageTransparency": { + "Float32": 0.0 + }, + "Interactable": { + "Bool": true + }, + "LayoutOrder": { + "Int32": 0 + }, + "Position": { + "UDim2": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "Rotation": { + "Float32": 0.0 + }, + "Sandboxed": { + "Bool": false + }, + "Selectable": { + "Bool": false + }, + "SelectionBehaviorDown": { + "Enum": 0 + }, + "SelectionBehaviorLeft": { + "Enum": 0 + }, + "SelectionBehaviorRight": { + "Enum": 0 + }, + "SelectionBehaviorUp": { + "Enum": 0 + }, + "SelectionGroup": { + "Bool": false + }, + "SelectionOrder": { + "Int32": 0 + }, + "Sink": { + "Enum": 0 + }, + "Size": { + "UDim2": [ + [ + 0.0, + 0 + ], + [ + 0.0, + 0 + ] + ] + }, + "SizeConstraint": { + "Enum": 0 + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "TextColor3": { + "Color3": [ + 0.10588236, + 0.16470589, + 0.20784315 + ] + }, + "TextSize": { + "Float32": 8.0 + }, + "TextTransparency": { + "Float32": 0.0 + }, + "TextWrapped": { + "Bool": false + }, + "TextXAlignment": { + "Enum": 2 + }, + "TextYAlignment": { + "Enum": 1 + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Visible": { + "Bool": true + }, + "ZIndex": { + "Int32": 1 + } + } + }, "InputBinding": { "Name": "InputBinding", "Tags": [], @@ -40685,6 +41671,32 @@ } } }, + "DisplayImage": { + "Name": "DisplayImage", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "DisplayName": { + "Name": "DisplayName", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Down": { "Name": "Down", "Scriptability": "ReadWrite", @@ -40936,6 +41948,12 @@ "ClampMagnitudeToOne": { "Bool": true }, + "DisplayImage": { + "Content": "None" + }, + "DisplayName": { + "String": "" + }, "Down": { "Enum": 0 }, @@ -41482,6 +42500,23 @@ } } }, + "SerializedOverrides": { + "Name": "SerializedOverrides", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "SourceAssetId": { "Name": "SourceAssetId", "Scriptability": "None", @@ -41814,6 +42849,27 @@ } } }, + "IntentService": { + "Name": "IntentService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "InternalMessagingService": { "Name": "InternalMessagingService", "Tags": [ @@ -41972,9 +43028,6 @@ "Archivable": { "Bool": true }, - "AssetId": { - "ContentId": "" - }, "Attributes": { "Attributes": {} }, @@ -42068,6 +43121,9 @@ "ComponentIndex": { "Int32": -1 }, + "Content": { + "Content": "None" + }, "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, @@ -43041,7 +44097,7 @@ }, "LightingStyle": { "Name": "LightingStyle", - "Scriptability": "Read", + "Scriptability": "ReadWrite", "DataType": { "Enum": "LightingStyle" }, @@ -43082,7 +44138,7 @@ }, "PrioritizeLightingQuality": { "Name": "PrioritizeLightingQuality", - "Scriptability": "Read", + "Scriptability": "ReadWrite", "DataType": { "Value": "Bool" }, @@ -44047,6 +45103,22 @@ } } }, + "IsImageCaptureEnabled": { + "Name": "IsImageCaptureEnabled", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "IsTextScraperRunning": { "Name": "IsTextScraperRunning", "Scriptability": "None", @@ -44142,6 +45214,22 @@ } } }, + "ShouldUseImageLocalizationTable": { + "Name": "ShouldUseImageLocalizationTable", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "SystemLocaleId": { "Name": "SystemLocaleId", "Scriptability": "Read", @@ -44470,6 +45558,38 @@ "Serialization": "DoesNotSerialize" } } + }, + "TranscoderFailureReason": { + "Name": "TranscoderFailureReason", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "TranscoderStatus": { + "Name": "TranscoderStatus", + "Scriptability": "None", + "DataType": { + "Enum": "SlimTranscoderStatus" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { @@ -44561,6 +45681,49 @@ } } }, + "Logger": { + "Name": "Logger", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Object", + "Properties": { + "FullPath": { + "Name": "FullPath", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "Name": { + "Name": "Name", + "Scriptability": "Read", + "DataType": { + "Value": "String" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, + "DefaultProperties": {} + }, "LoginService": { "Name": "LoginService", "Tags": [ @@ -44775,6 +45938,36 @@ } } }, + "LuauExpression": { + "Name": "LuauExpression", + "Tags": [ + "NotCreatable" + ], + "Superclass": "Object", + "Properties": {}, + "DefaultProperties": {} + }, + "LuauExpressionService": { + "Name": "LuauExpressionService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "LuauScriptAnalyzerService": { "Name": "LuauScriptAnalyzerService", "Tags": [ @@ -45290,6 +46483,19 @@ } } }, + "DiffuseVersionedAssetId": { + "Name": "DiffuseVersionedAssetId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "EmissiveFilePath": { "Name": "EmissiveFilePath", "Scriptability": "ReadWrite", @@ -45303,6 +46509,19 @@ } } }, + "EmissiveVersionedAssetId": { + "Name": "EmissiveVersionedAssetId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "IsPbr": { "Name": "IsPbr", "Scriptability": "Read", @@ -45332,6 +46551,19 @@ } } }, + "MetalnessVersionedAssetId": { + "Name": "MetalnessVersionedAssetId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "NormalFilePath": { "Name": "NormalFilePath", "Scriptability": "ReadWrite", @@ -45345,6 +46577,19 @@ } } }, + "NormalVersionedAssetId": { + "Name": "NormalVersionedAssetId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "RoughnessFilePath": { "Name": "RoughnessFilePath", "Scriptability": "ReadWrite", @@ -45357,6 +46602,19 @@ "Serialization": "Serializes" } } + }, + "RoughnessVersionedAssetId": { + "Name": "RoughnessVersionedAssetId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -46442,6 +47700,27 @@ "Hidden", "NotScriptable" ], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "TexturePackContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "TexturePackContent": { + "Name": "TexturePackContent", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -46511,8 +47790,8 @@ "Tags": { "Tags": [] }, - "TexturePack": { - "ContentId": "" + "TexturePackContent": { + "Content": "None" }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" @@ -46560,6 +47839,26 @@ } } }, + "MemoryStoreDistributedCounter": { + "Name": "MemoryStoreDistributedCounter", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "MemoryStoreHashMap": { "Name": "MemoryStoreHashMap", "Tags": [ @@ -46989,6 +48288,19 @@ "Serialization": "Serializes" } } + }, + "VersionedAssetId": { + "Name": "VersionedAssetId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int64" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -48438,6 +49750,26 @@ } } }, + "MomentsService": { + "Name": "MomentsService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "Motor": { "Name": "Motor", "Tags": [], @@ -48617,7 +49949,9 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Hidden" + ], "Kind": { "Canonical": { "Serialization": "DoesNotSerialize" @@ -49159,9 +50493,6 @@ "Archivable": { "Bool": true }, - "AssetId": { - "ContentId": "" - }, "Attributes": { "Attributes": {} }, @@ -49255,6 +50586,9 @@ "ComponentIndex": { "Int32": -1 }, + "Content": { + "Content": "None" + }, "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, @@ -51010,7 +52344,12 @@ "Tags": [], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": { + "Migrate": { + "To": "PantsTemplateContent", + "Migration": "ContentIdToContent" + } + } } } }, @@ -51048,8 +52387,8 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "PantsTemplate": { - "ContentId": "" + "PantsTemplateContent": { + "Content": "None" }, "Sandboxed": { "Bool": false @@ -51529,7 +52868,12 @@ ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": { + "Migrate": { + "To": "Content", + "Migration": "ContentIdToContent" + } + } } } }, @@ -51584,6 +52928,22 @@ } } }, + "Content": { + "Name": "Content", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "FormFactor": { "Name": "FormFactor", "Scriptability": "None", @@ -51778,9 +53138,6 @@ "Archivable": { "Bool": true }, - "AssetId": { - "ContentId": "" - }, "Attributes": { "Attributes": {} }, @@ -51874,6 +53231,9 @@ "ComponentIndex": { "Int32": -1 }, + "Content": { + "Content": "None" + }, "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, @@ -53202,6 +54562,38 @@ } } }, + "Path3D": { + "Name": "Path3D", + "Tags": [], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "PathfindingLink": { "Name": "PathfindingLink", "Tags": [], @@ -53982,6 +55374,97 @@ } } }, + "CollisionGeomDrawOriginalParts": { + "Name": "CollisionGeomDrawOriginalParts", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CollisionGeomMatchPartTransparency": { + "Name": "CollisionGeomMatchPartTransparency", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CollisionGeomOverlayTransparency": { + "Name": "CollisionGeomOverlayTransparency", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CollisionGeomShowCollidableParts": { + "Name": "CollisionGeomShowCollidableParts", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CollisionGeomShowCollisionGroup": { + "Name": "CollisionGeomShowCollisionGroup", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CollisionGeomShowQueryableParts": { + "Name": "CollisionGeomShowQueryableParts", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CollisionGeomShowTouchableParts": { + "Name": "CollisionGeomShowTouchableParts", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DisableCSGv2": { "Name": "DisableCSGv2", "Scriptability": "ReadWrite", @@ -54284,6 +55767,27 @@ } } }, + "PinShortcutService": { + "Name": "PinShortcutService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "PitchShiftSoundEffect": { "Name": "PitchShiftSoundEffect", "Tags": [], @@ -55078,6 +56582,19 @@ } } }, + "FrustumStreaming": { + "Name": "FrustumStreaming", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "FrustumStreamingMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "GameplayPaused": { "Name": "GameplayPaused", "Scriptability": "Read", @@ -55333,6 +56850,22 @@ } } }, + "PendingRequestedTool": { + "Name": "PendingRequestedTool", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PlatformName": { "Name": "PlatformName", "Scriptability": "None", @@ -55540,6 +57073,22 @@ } } }, + "UserIdModeReplicate": { + "Name": "UserIdModeReplicate", + "Scriptability": "None", + "DataType": { + "Enum": "UserIdMode" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "VRDevice": { "Name": "VRDevice", "Scriptability": "None", @@ -55571,6 +57120,22 @@ } } }, + "VoiceChatVolume": { + "Name": "VoiceChatVolume", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "userId": { "Name": "userId", "Scriptability": "ReadWrite", @@ -57598,6 +59163,27 @@ } } }, + "PopLatencyService": { + "Name": "PopLatencyService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "Pose": { "Name": "Pose", "Tags": [], @@ -58116,6 +59702,43 @@ } } }, + "ProjectService": { + "Name": "ProjectService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": { + "ContentMap": { + "Name": "ContentMap", + "Scriptability": "None", + "DataType": { + "Value": "NetAssetRef" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "ProximityPrompt": { "Name": "ProximityPrompt", "Tags": [], @@ -58666,6 +60289,27 @@ } } }, + "QueueService": { + "Name": "QueueService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "RTAnimationTracker": { "Name": "RTAnimationTracker", "Tags": [ @@ -58852,6 +60496,22 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "AudioInputActive": { + "Name": "AudioInputActive", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ForwardInput": { "Name": "ForwardInput", "Scriptability": "None", @@ -60592,6 +62252,27 @@ } } }, + "RequestOrchestratorService": { + "Name": "RequestOrchestratorService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "ReverbSoundEffect": { "Name": "ReverbSoundEffect", "Tags": [], @@ -60736,7 +62417,23 @@ "Name": "RigidConstraint", "Tags": [], "Superclass": "Constraint", - "Properties": {}, + "Properties": { + "EnableSkinning": { + "Name": "EnableSkinning", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, "DefaultProperties": { "Archivable": { "Bool": true @@ -62023,19 +63720,6 @@ } } }, - "ValidateUgcBody": { - "Name": "ValidateUgcBody", - "Scriptability": "ReadWrite", - "DataType": { - "Value": "Bool" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "VersionedAssetId": { "Name": "VersionedAssetId", "Scriptability": "ReadWrite", @@ -62909,6 +64593,21 @@ } } }, + "IgnoresTitleBarReservation": { + "Name": "IgnoresTitleBarReservation", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "OnTopOfCoreBlur": { "Name": "OnTopOfCoreBlur", "Scriptability": "None", @@ -63646,6 +65345,26 @@ } } }, + "ScriptScannerService": { + "Name": "ScriptScannerService", + "Tags": [ + "NotCreatable", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "ScriptService": { "Name": "ScriptService", "Tags": [ @@ -64173,9 +65892,6 @@ "HorizontalScrollBarInset": { "Enum": 0 }, - "InputSink": { - "Enum": 0 - }, "Interactable": { "Bool": true }, @@ -64245,6 +65961,9 @@ "SelectionOrder": { "Int32": 0 }, + "Sink": { + "Enum": 0 + }, "Size": { "UDim2": [ [ @@ -65489,7 +67208,12 @@ "Tags": [], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": { + "Migrate": { + "To": "ShirtTemplateContent", + "Migration": "ContentIdToContent" + } + } } } }, @@ -65530,8 +67254,8 @@ "Sandboxed": { "Bool": false }, - "ShirtTemplate": { - "ContentId": "" + "ShirtTemplateContent": { + "Content": "None" }, "SourceAssetId": { "Int64": -1 @@ -65571,7 +67295,12 @@ "Tags": [], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": { + "Migrate": { + "To": "TextureContent", + "Migration": "ContentIdToContent" + } + } } } }, @@ -65606,9 +67335,6 @@ 1.0 ] }, - "Graphic": { - "ContentId": "" - }, "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, @@ -65621,6 +67347,9 @@ "Tags": { "Tags": [] }, + "TextureContent": { + "Content": "None" + }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" } @@ -67292,27 +69021,6 @@ } } }, - "SnippetService": { - "Name": "SnippetService", - "Tags": [ - "NotCreatable", - "NotReplicated", - "Service" - ], - "Superclass": "Instance", - "Properties": {}, - "DefaultProperties": { - "Archivable": { - "Bool": true - }, - "HistoryId": { - "UniqueId": "00000000000000000000000000000000" - }, - "UniqueId": { - "UniqueId": "00000000000000000000000000000000" - } - } - }, "SocialService": { "Name": "SocialService", "Tags": [ @@ -69619,6 +71327,26 @@ } } }, + "StandardQueue": { + "Name": "StandardQueue", + "Tags": [ + "NotCreatable", + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "StartPageService": { "Name": "StartPageService", "Tags": [ @@ -70234,166 +71962,6 @@ } } }, - "GameSettingsAssetIDFace": { - "Name": "GameSettingsAssetIDFace", - "Scriptability": "None", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GameSettingsAssetIDHead": { - "Name": "GameSettingsAssetIDHead", - "Scriptability": "None", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GameSettingsAssetIDLeftArm": { - "Name": "GameSettingsAssetIDLeftArm", - "Scriptability": "None", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GameSettingsAssetIDLeftLeg": { - "Name": "GameSettingsAssetIDLeftLeg", - "Scriptability": "None", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GameSettingsAssetIDPants": { - "Name": "GameSettingsAssetIDPants", - "Scriptability": "None", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GameSettingsAssetIDRightArm": { - "Name": "GameSettingsAssetIDRightArm", - "Scriptability": "None", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GameSettingsAssetIDRightLeg": { - "Name": "GameSettingsAssetIDRightLeg", - "Scriptability": "None", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GameSettingsAssetIDShirt": { - "Name": "GameSettingsAssetIDShirt", - "Scriptability": "None", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GameSettingsAssetIDTeeShirt": { - "Name": "GameSettingsAssetIDTeeShirt", - "Scriptability": "None", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GameSettingsAssetIDTorso": { - "Name": "GameSettingsAssetIDTorso", - "Scriptability": "None", - "DataType": { - "Value": "Int64" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "GameSettingsAvatar": { "Name": "GameSettingsAvatar", "Scriptability": "None", @@ -70425,86 +71993,6 @@ } } }, - "GameSettingsScaleRangeBodyType": { - "Name": "GameSettingsScaleRangeBodyType", - "Scriptability": "None", - "DataType": { - "Value": "NumberRange" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GameSettingsScaleRangeHead": { - "Name": "GameSettingsScaleRangeHead", - "Scriptability": "None", - "DataType": { - "Value": "NumberRange" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GameSettingsScaleRangeHeight": { - "Name": "GameSettingsScaleRangeHeight", - "Scriptability": "None", - "DataType": { - "Value": "NumberRange" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GameSettingsScaleRangeProportion": { - "Name": "GameSettingsScaleRangeProportion", - "Scriptability": "None", - "DataType": { - "Value": "NumberRange" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "GameSettingsScaleRangeWidth": { - "Name": "GameSettingsScaleRangeWidth", - "Scriptability": "None", - "DataType": { - "Value": "NumberRange" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "HealthDisplayDistance": { "Name": "HealthDisplayDistance", "Scriptability": "ReadWrite", @@ -70589,6 +72077,21 @@ } } }, + "PlaceAvatarRules": { + "Name": "PlaceAvatarRules", + "Scriptability": "None", + "DataType": { + "Value": "Ref" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PlayerModuleStatus": { "Name": "PlayerModuleStatus", "Scriptability": "None", @@ -70691,72 +72194,12 @@ "EnableMouseLockOption": { "Bool": true }, - "GameSettingsAssetIDFace": { - "Int64": 0 - }, - "GameSettingsAssetIDHead": { - "Int64": 0 - }, - "GameSettingsAssetIDLeftArm": { - "Int64": 0 - }, - "GameSettingsAssetIDLeftLeg": { - "Int64": 0 - }, - "GameSettingsAssetIDPants": { - "Int64": 0 - }, - "GameSettingsAssetIDRightArm": { - "Int64": 0 - }, - "GameSettingsAssetIDRightLeg": { - "Int64": 0 - }, - "GameSettingsAssetIDShirt": { - "Int64": 0 - }, - "GameSettingsAssetIDTeeShirt": { - "Int64": 0 - }, - "GameSettingsAssetIDTorso": { - "Int64": 0 - }, "GameSettingsAvatar": { "Enum": 1 }, "GameSettingsR15Collision": { "Enum": 0 }, - "GameSettingsScaleRangeBodyType": { - "NumberRange": [ - 0.0, - 1.0 - ] - }, - "GameSettingsScaleRangeHead": { - "NumberRange": [ - 0.95, - 1.0 - ] - }, - "GameSettingsScaleRangeHeight": { - "NumberRange": [ - 0.9, - 1.05 - ] - }, - "GameSettingsScaleRangeProportion": { - "NumberRange": [ - 0.0, - 1.0 - ] - }, - "GameSettingsScaleRangeWidth": { - "NumberRange": [ - 0.7, - 1.0 - ] - }, "HealthDisplayDistance": { "Float32": 100.0 }, @@ -70850,6 +72293,130 @@ } } }, + "StateMachineDefinition": { + "Name": "StateMachineDefinition", + "Tags": [ + "NotReplicated" + ], + "Superclass": "Instance", + "Properties": { + "NodeId": { + "Name": "NodeId", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, + "StateMachineTransitionDefinition": { + "Name": "StateMachineTransitionDefinition", + "Tags": [], + "Superclass": "Instance", + "Properties": { + "From": { + "Name": "From", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Priority": { + "Name": "Priority", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Int32" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "To": { + "Name": "To", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Ref" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "TransitionId": { + "Name": "TransitionId", + "Scriptability": "None", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Priority": { + "Int32": 0 + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "TransitionId": { + "String": "" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "Stats": { "Name": "Stats", "Tags": [ @@ -71869,8 +73436,8 @@ } } }, - "CameraAdaptiveSpeed": { - "Name": "CameraAdaptiveSpeed", + "CameraAltLeftMouseToRotate": { + "Name": "CameraAltLeftMouseToRotate", "Scriptability": "None", "DataType": { "Value": "Bool" @@ -71882,8 +73449,8 @@ } } }, - "CameraAltLeftMouseToRotate": { - "Name": "CameraAltLeftMouseToRotate", + "CameraKeyMoveSmoothing": { + "Name": "CameraKeyMoveSmoothing", "Scriptability": "None", "DataType": { "Value": "Bool" @@ -71921,21 +73488,8 @@ } } }, - "CameraOrbitSensitivity": { - "Name": "CameraOrbitSensitivity", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, - "CameraPanSensitivity": { - "Name": "CameraPanSensitivity", + "CameraRotateShiftFactor": { + "Name": "CameraRotateShiftFactor", "Scriptability": "None", "DataType": { "Value": "Float32" @@ -71973,19 +73527,6 @@ } } }, - "CameraZoomSpeed": { - "Name": "CameraZoomSpeed", - "Scriptability": "None", - "DataType": { - "Value": "Float32" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "CameraZoomToMousePosition": { "Name": "CameraZoomToMousePosition", "Scriptability": "None", @@ -72257,6 +73798,19 @@ } } }, + "DraggerShowDraggedPoint": { + "Name": "DraggerShowDraggedPoint", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DraggerShowHoverRuler": { "Name": "DraggerShowHoverRuler", "Scriptability": "None", @@ -72413,6 +73967,19 @@ } } }, + "Enable Client/Server MDI": { + "Name": "Enable Client/Server MDI", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Enable CoreScript Debugger": { "Name": "Enable CoreScript Debugger", "Scriptability": "ReadWrite", @@ -72611,6 +74178,19 @@ } } }, + "EnableOvertypeMode": { + "Name": "EnableOvertypeMode", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "EnableSelectionTooltips": { "Name": "EnableSelectionTooltips", "Scriptability": "None", @@ -73269,6 +74849,38 @@ } } }, + "ReviewableChangeAddedTextColor": { + "Name": "ReviewableChangeAddedTextColor", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, + "ReviewableChangeRemovedTextColor": { + "Name": "ReviewableChangeRemovedTextColor", + "Scriptability": "None", + "DataType": { + "Value": "Color3" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "Ruler Color": { "Name": "Ruler Color", "Scriptability": "ReadWrite", @@ -74340,10 +75952,13 @@ "DataType": { "Value": "Bool" }, - "Tags": [], + "Tags": [ + "Hidden", + "NotReplicated" + ], "Kind": { "Canonical": { - "Serialization": "Serializes" + "Serialization": "DoesNotSerialize" } } }, @@ -74456,75 +76071,7 @@ "Service" ], "Superclass": "Instance", - "Properties": { - "HasMultiTouchStarted": { - "Name": "HasMultiTouchStarted", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "IsMultiTouchEmulationOn": { - "Name": "IsMultiTouchEmulationOn", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotReplicated" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "IsMultiTouchEnabled": { - "Name": "IsMultiTouchEnabled", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, - "PivotPosition": { - "Name": "PivotPosition", - "Scriptability": "None", - "DataType": { - "Value": "Vector2" - }, - "Tags": [ - "Hidden", - "NotReplicated", - "ReadOnly" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - } - }, + "Properties": {}, "DefaultProperties": { "Archivable": { "Bool": true @@ -75967,6 +77514,24 @@ "Value": "ContentId" }, "Tags": [], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "TexturePackContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "TexturePackContent": { + "Name": "TexturePackContent", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -76034,8 +77599,8 @@ "Tags": { "Tags": [] }, - "TexturePack": { - "ContentId": "" + "TexturePackContent": { + "Content": "None" }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" @@ -77146,6 +78711,19 @@ } } }, + "ReservedServerId": { + "Name": "ReservedServerId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ServerInstanceId": { "Name": "ServerInstanceId", "Scriptability": "ReadWrite", @@ -77171,6 +78749,19 @@ "Serialization": "Serializes" } } + }, + "VipServerId": { + "Name": "VipServerId", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "String" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -77189,6 +78780,9 @@ "ReservedServerAccessCode": { "String": "" }, + "ReservedServerId": { + "String": "" + }, "Sandboxed": { "Bool": false }, @@ -77206,6 +78800,9 @@ }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" + }, + "VipServerId": { + "String": "" } } }, @@ -77395,6 +78992,21 @@ } } }, + "ExpandedTerrainResolved": { + "Name": "ExpandedTerrainResolved", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "GrassLength": { "Name": "GrassLength", "Scriptability": "None", @@ -77860,7 +79472,7 @@ "String": "" }, "Materials": { - "SharedString": "" + "SharedString": "AQAAABUAAAACAAAAan8/AAUAAAAAAAADAAAAP39rIAMAAAAAAAAEAAAAf2Y/MAMAAAAAAAAFAAAAilY+UAMAAAAAAAAGAAAAj35fEAUAAAAAAAAHAAAAi21PEAIAAAAAAAAIAAAAZmxvgAMAAAAAAAAJAAAAZbDqEAYAAAAAAAAKAAAAw8faMAUAAAAAAAALAAAAiVpHkAMAAAAAAAAMAAAAOi4kQAUAAAAAAAANAAAAHh4lFAMAAAAAAAAOAAAAZlw7UAUAAAAAAAAPAAAA6JxKJAMAAAAAAAAQAAAAc3trYAUAAAAAAAARAAAAhHtacAMAAAAAAAASAAAAgcLgAAYAAAAAAAATAAAAc4RKBAUAAAAAAAAUAAAAxr21cAUAAAAAAAAVAAAAzq2UNAMAAAAAAAAWAAAAlJSMRAMAAAAAAAA=" }, "PhysicsGrid": { "BinaryString": "AgMAAAAAAAAAAAAAAAA=" @@ -78201,6 +79813,27 @@ "Hidden", "NotScriptable" ], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "TexturePackContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "TexturePackContent": { + "Name": "TexturePackContent", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -78264,8 +79897,8 @@ "Tags": { "Tags": [] }, - "TexturePack": { - "ContentId": "" + "TexturePackContent": { + "Content": "None" }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" @@ -78514,6 +80147,22 @@ } } }, + "Enabled": { + "Name": "Enabled", + "Scriptability": "Read", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "NotReplicated", + "ReadOnly" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ErrorCount": { "Name": "ErrorCount", "Scriptability": "Read", @@ -79454,9 +81103,6 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "InputSink": { - "Enum": 0 - }, "Interactable": { "Bool": true }, @@ -79536,6 +81182,9 @@ "ShowNativeInput": { "Bool": true }, + "Sink": { + "Enum": 1 + }, "Size": { "UDim2": [ [ @@ -80130,9 +81779,6 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "InputSink": { - "Enum": 0 - }, "Interactable": { "Bool": true }, @@ -80202,6 +81848,9 @@ "SelectionOrder": { "Int32": 0 }, + "Sink": { + "Enum": 1 + }, "Size": { "UDim2": [ [ @@ -80286,6 +81935,19 @@ "Tags": [], "Superclass": "Instance", "Properties": { + "AddPlayersOnJoin": { + "Name": "AddPlayersOnJoin", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "DirectChatRequester": { "Name": "DirectChatRequester", "Scriptability": "Read", @@ -80301,9 +81963,27 @@ "Serialization": "DoesNotSerialize" } } + }, + "IsDefaultTextChannel": { + "Name": "IsDefaultTextChannel", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } } }, "DefaultProperties": { + "AddPlayersOnJoin": { + "Bool": false + }, "Archivable": { "Bool": true }, @@ -80337,6 +82017,19 @@ ], "Superclass": "GuiObject", "Properties": { + "FontFace": { + "Name": "FontFace", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Font" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "IsRendering": { "Name": "IsRendering", "Scriptability": "None", @@ -80366,6 +82059,19 @@ "Serialization": "Serializes" } } + }, + "UseDefaultFont": { + "Name": "UseDefaultFont", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -80422,12 +82128,17 @@ "Draggable": { "Bool": false }, + "FontFace": { + "Font": { + "family": "rbxasset://fonts/families/BuilderSans.json", + "weight": "Medium", + "style": "Normal", + "cachedFaceId": "rbxasset://fonts/BuilderSans-Medium.otf" + } + }, "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "InputSink": { - "Enum": 0 - }, "Interactable": { "Bool": true }, @@ -80473,6 +82184,9 @@ "SelectionOrder": { "Int32": 0 }, + "Sink": { + "Enum": 0 + }, "Size": { "UDim2": [ [ @@ -80497,6 +82211,9 @@ "UniqueId": { "UniqueId": "00000000000000000000000000000000" }, + "UseDefaultFont": { + "Bool": true + }, "Visible": { "Bool": true }, @@ -80700,6 +82417,21 @@ } } }, + "IsHistorical": { + "Name": "IsHistorical", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "MessageId": { "Name": "MessageId", "Scriptability": "ReadWrite", @@ -81137,19 +82869,6 @@ } } }, - "EnableProtectedChat": { - "Name": "EnableProtectedChat", - "Scriptability": "None", - "DataType": { - "Enum": "RolloutState" - }, - "Tags": [], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "HasSeenDeprecationDialog": { "Name": "HasSeenDeprecationDialog", "Scriptability": "None", @@ -81180,6 +82899,19 @@ "Serialization": "Serializes" } } + }, + "PlatformIntegratedChat": { + "Name": "PlatformIntegratedChat", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -81207,9 +82939,6 @@ "CreateDefaultTextChannels": { "Bool": true }, - "EnableProtectedChat": { - "Enum": 0 - }, "HasSeenDeprecationDialog": { "Bool": false }, @@ -81219,6 +82948,9 @@ "IsLegacyChatDisabled": { "Bool": false }, + "PlatformIntegratedChat": { + "Enum": 0 + }, "Sandboxed": { "Bool": false }, @@ -81233,6 +82965,57 @@ } } }, + "TextDocument": { + "Name": "TextDocument", + "Tags": [ + "NotBrowsable" + ], + "Superclass": "Instance", + "Properties": { + "TextContent": { + "Name": "TextContent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Content" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "TextContent": { + "Content": "None" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "TextFilterResult": { "Name": "TextFilterResult", "Tags": [ @@ -81895,9 +83678,6 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "InputSink": { - "Enum": 0 - }, "Interactable": { "Bool": true }, @@ -81961,6 +83741,9 @@ "SelectionOrder": { "Int32": 0 }, + "Sink": { + "Enum": 0 + }, "Size": { "UDim2": [ [ @@ -82233,6 +84016,19 @@ 1.0 ] }, + "EmissiveMaskContent": { + "Content": "None" + }, + "EmissiveStrength": { + "Float32": 1.0 + }, + "EmissiveTint": { + "Color3": [ + 1.0, + 1.0, + 1.0 + ] + }, "Face": { "Enum": 5 }, @@ -83832,6 +85628,7 @@ "TriangleMeshPart": { "Name": "TriangleMeshPart", "Tags": [ + "NotBrowsable", "NotCreatable" ], "Superclass": "BasePart", @@ -83867,6 +85664,21 @@ } } }, + "CollisionPrecision": { + "Name": "CollisionPrecision", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "ConvexDecompHolder": { "Name": "ConvexDecompHolder", "Scriptability": "None", @@ -83946,6 +85758,23 @@ } } }, + "PCDRequestId": { + "Name": "PCDRequestId", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "PhysicalConfigData": { "Name": "PhysicalConfigData", "Scriptability": "None", @@ -85378,7 +87207,9 @@ "DataType": { "Value": "Float32" }, - "Tags": [], + "Tags": [ + "NotBrowsable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -85391,7 +87222,9 @@ "DataType": { "Enum": "GradientTileMode" }, - "Tags": [], + "Tags": [ + "NotBrowsable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -85417,7 +87250,9 @@ "DataType": { "Enum": "GradientType" }, - "Tags": [], + "Tags": [ + "NotBrowsable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -86348,6 +88183,32 @@ } } }, + "Inset": { + "Name": "Inset", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Mode": { + "Name": "Mode", + "Scriptability": "ReadWrite", + "DataType": { + "Enum": "ApplyShadowMode" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Offset": { "Name": "Offset", "Scriptability": "ReadWrite", @@ -86361,6 +88222,19 @@ } } }, + "ShowBehindParent": { + "Name": "ShowBehindParent", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "Spread": { "Name": "Spread", "Scriptability": "ReadWrite", @@ -86430,6 +88304,12 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, + "Inset": { + "Bool": false + }, + "Mode": { + "Enum": 0 + }, "Offset": { "UDim2": [ [ @@ -86445,6 +88325,9 @@ "Sandboxed": { "Bool": false }, + "ShowBehindParent": { + "Bool": true + }, "SourceAssetId": { "Int64": -1 }, @@ -86943,9 +88826,6 @@ "Archivable": { "Bool": true }, - "AssetId": { - "ContentId": "" - }, "Attributes": { "Attributes": {} }, @@ -87039,6 +88919,9 @@ "ComponentIndex": { "Int32": -1 }, + "Content": { + "Content": "None" + }, "CustomPhysicalProperties": { "PhysicalProperties": "Default" }, @@ -88337,6 +90220,22 @@ } } }, + "UIScaleMultiplierHundredths": { + "Name": "UIScaleMultiplierHundredths", + "Scriptability": "None", + "DataType": { + "Value": "Int32" + }, + "Tags": [ + "Hidden", + "NotReplicated" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "UiNavigationKeyBindEnabled": { "Name": "UiNavigationKeyBindEnabled", "Scriptability": "None", @@ -90667,9 +92566,6 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "InputSink": { - "Enum": 0 - }, "Interactable": { "Bool": true }, @@ -90721,6 +92617,9 @@ "SelectionOrder": { "Int32": 0 }, + "Sink": { + "Enum": 0 + }, "Size": { "UDim2": [ [ @@ -91086,9 +92985,6 @@ "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, - "InputSink": { - "Enum": 0 - }, "Interactable": { "Bool": true }, @@ -91155,6 +93051,9 @@ "SelectionOrder": { "Int32": 0 }, + "Sink": { + "Enum": 0 + }, "Size": { "UDim2": [ [ @@ -91572,6 +93471,108 @@ } } }, + "ViewportCamera": { + "Name": "ViewportCamera", + "Tags": [], + "Superclass": "Camera", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "Attributes": { + "Attributes": {} + }, + "CFrame": { + "CFrame": { + "position": [ + 0.0, + 20.0, + 20.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + -0.0 + ], + [ + -0.0, + 0.7071068, + 0.7071068 + ], + [ + 0.0, + -0.7071068, + 0.7071068 + ] + ] + } + }, + "CameraType": { + "Enum": 0 + }, + "Capabilities": { + "SecurityCapabilities": 0 + }, + "FieldOfView": { + "Float32": 70.0 + }, + "FieldOfViewMode": { + "Enum": 0 + }, + "Focus": { + "CFrame": { + "position": [ + 0.0, + 0.0, + -5.0 + ], + "orientation": [ + [ + 1.0, + 0.0, + 0.0 + ], + [ + 0.0, + 1.0, + 0.0 + ], + [ + 0.0, + 0.0, + 1.0 + ] + ] + } + }, + "HeadLocked": { + "Bool": true + }, + "HeadScale": { + "Float32": 1.0 + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "Sandboxed": { + "Bool": false + }, + "SourceAssetId": { + "Int64": -1 + }, + "Tags": { + "Tags": [] + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + }, + "VRTiltAndRollEnabled": { + "Bool": false + } + } + }, "ViewportFrame": { "Name": "ViewportFrame", "Tags": [], @@ -91809,9 +93810,6 @@ "ImageTransparency": { "Float32": 0.0 }, - "InputSink": { - "Enum": 0 - }, "Interactable": { "Bool": true }, @@ -91871,6 +93869,9 @@ "SelectionOrder": { "Int32": 0 }, + "Sink": { + "Enum": 0 + }, "Size": { "UDim2": [ [ @@ -92281,6 +94282,19 @@ } } }, + "EnableVoiceVolumeControls": { + "Name": "EnableVoiceVolumeControls", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "UseAudioApi": { "Name": "UseAudioApi", "Scriptability": "ReadWrite", @@ -92401,6 +94415,9 @@ "EnableDefaultVoice": { "Bool": true }, + "EnableVoiceVolumeControls": { + "Enum": 0 + }, "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, @@ -92779,7 +94796,23 @@ "Name": "Weld", "Tags": [], "Superclass": "JointInstance", - "Properties": {}, + "Properties": { + "EnableSkinning": { + "Name": "EnableSkinning", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + } + }, "DefaultProperties": { "Archivable": { "Bool": true @@ -93070,6 +95103,27 @@ } } }, + "WindowProtocolService": { + "Name": "WindowProtocolService", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "Instance", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "Wire": { "Name": "Wire", "Tags": [], @@ -93391,22 +95445,6 @@ } } }, - "CollisionGroupData": { - "Name": "CollisionGroupData", - "Scriptability": "None", - "DataType": { - "Value": "BinaryString" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "Serializes" - } - } - }, "CollisionGroups": { "Name": "CollisionGroups", "Scriptability": "None", @@ -93425,22 +95463,6 @@ } } }, - "ConvexDecompCompressed": { - "Name": "ConvexDecompCompressed", - "Scriptability": "None", - "DataType": { - "Value": "Bool" - }, - "Tags": [ - "Hidden", - "NotScriptable" - ], - "Kind": { - "Canonical": { - "Serialization": "DoesNotSerialize" - } - } - }, "CurrentCamera": { "Name": "CurrentCamera", "Scriptability": "ReadWrite", @@ -93502,6 +95524,21 @@ } } }, + "ExpandedTerrain": { + "Name": "ExpandedTerrain", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "ExplicitAutoJoints": { "Name": "ExplicitAutoJoints", "Scriptability": "None", @@ -93707,6 +95744,21 @@ } } }, + "MapTVRemoteToGamepadKeycodes": { + "Name": "MapTVRemoteToGamepadKeycodes", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "MeshPartHeadsAndAccessories": { "Name": "MeshPartHeadsAndAccessories", "Scriptability": "None", @@ -93859,6 +95911,21 @@ } } }, + "PredictiveStreamingMode": { + "Name": "PredictiveStreamingMode", + "Scriptability": "None", + "DataType": { + "Enum": "PredictiveStreamingMode" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PrimalPhysicsSolver": { "Name": "PrimalPhysicsSolver", "Scriptability": "None", @@ -94012,6 +96079,19 @@ } } }, + "StreamingAdaptiveRadius": { + "Name": "StreamingAdaptiveRadius", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "StreamingEnabled": { "Name": "StreamingEnabled", "Scriptability": "ReadWrite", @@ -94041,6 +96121,23 @@ } } }, + "StreamingEnabledStorage": { + "Name": "StreamingEnabledStorage", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden", + "NotReplicated", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "DoesNotSerialize" + } + } + }, "StreamingIntegrityMode": { "Name": "StreamingIntegrityMode", "Scriptability": "None", @@ -94212,6 +96309,21 @@ } } }, + "UseInputSink": { + "Name": "UseInputSink", + "Scriptability": "None", + "DataType": { + "Enum": "RolloutState" + }, + "Tags": [ + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "UseNewLuauTypeSolver": { "Name": "UseNewLuauTypeSolver", "Scriptability": "None", @@ -94278,6 +96390,9 @@ "AuthorityMode": { "Enum": 1 }, + "AutoSimulate": { + "Bool": true + }, "AvatarUnificationMode": { "Enum": 0 }, @@ -94296,6 +96411,9 @@ "EnableSLIMAvatars": { "Enum": 0 }, + "ExpandedTerrain": { + "Enum": 0 + }, "ExplicitAutoJoints": { "Bool": true }, @@ -94318,6 +96436,13 @@ "Gravity": { "Float32": 196.2 }, + "GravityDirection": { + "Vector3": [ + 0.0, + -1.0, + 0.0 + ] + }, "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, @@ -94339,6 +96464,9 @@ "LuauTypeCheckMode": { "Enum": 0 }, + "MapTVRemoteToGamepadKeycodes": { + "Enum": 0 + }, "MeshPartHeadsAndAccessories": { "Enum": 0 }, @@ -94405,6 +96533,9 @@ "PlayerScriptsUseInputActionSystem": { "Enum": 0 }, + "PredictiveStreamingMode": { + "Enum": 0 + }, "PrimalPhysicsSolver": { "Enum": 0 }, @@ -94432,6 +96563,9 @@ "SignalBehavior": { "Enum": 0 }, + "SimulationRate": { + "Float32": 1.0 + }, "SlimHash": { "SharedString": "" }, @@ -94441,6 +96575,9 @@ "StreamOutBehavior": { "Enum": 0 }, + "StreamingAdaptiveRadius": { + "Bool": false + }, "StreamingEnabled": { "Bool": false }, @@ -94471,12 +96608,25 @@ "UseFixedSimulation": { "Enum": 0 }, + "UseInputSink": { + "Enum": 0 + }, "UseNewLuauTypeSolver": { "Enum": 2 }, "ValidateEnabledProximityPrompt": { "Enum": 0 }, + "Wind": { + "Float32": 0.0 + }, + "WindDirection": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, "WorldPivotData": { "OptionalCFrame": null } @@ -94534,7 +96684,21 @@ "Name": "WorldModel", "Tags": [], "Superclass": "WorldRoot", - "Properties": {}, + "Properties": { + "UseWorkspaceCollisionGroups": { + "Name": "UseWorkspaceCollisionGroups", + "Scriptability": "ReadWrite", + "DataType": { + "Value": "Bool" + }, + "Tags": [], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + } + }, "DefaultProperties": { "Archivable": { "Bool": true @@ -94542,9 +96706,22 @@ "Attributes": { "Attributes": {} }, + "AutoSimulate": { + "Bool": false + }, "Capabilities": { "SecurityCapabilities": 0 }, + "CollisionGroupData": { + "BinaryString": "AQEABP////8HRGVmYXVsdA==" + }, + "GravityDirection": { + "Vector3": [ + 0.0, + -1.0, + 0.0 + ] + }, "HistoryId": { "UniqueId": "00000000000000000000000000000000" }, @@ -94599,6 +96776,9 @@ "Scale": { "Float32": 1.0 }, + "SimulationRate": { + "Float32": 1.0 + }, "SlimHash": { "SharedString": "" }, @@ -94611,6 +96791,19 @@ "UniqueId": { "UniqueId": "00000000000000000000000000000000" }, + "UseWorkspaceCollisionGroups": { + "Bool": false + }, + "Wind": { + "Float32": 0.0 + }, + "WindDirection": { + "Vector3": [ + 0.0, + 0.0, + 0.0 + ] + }, "WorldPivotData": { "OptionalCFrame": null } @@ -94623,6 +96816,52 @@ ], "Superclass": "Model", "Properties": { + "AutoSimulate": { + "Name": "AutoSimulate", + "Scriptability": "None", + "DataType": { + "Value": "Bool" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "CollisionGroupData": { + "Name": "CollisionGroupData", + "Scriptability": "None", + "DataType": { + "Value": "BinaryString" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "GravityDirection": { + "Name": "GravityDirection", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, "PhysicsStepTime": { "Name": "PhysicsStepTime", "Scriptability": "None", @@ -94631,13 +96870,59 @@ }, "Tags": [ "Hidden", - "NotReplicated" + "NotReplicated", + "ReadOnly" ], "Kind": { "Canonical": { "Serialization": "DoesNotSerialize" } } + }, + "SimulationRate": { + "Name": "SimulationRate", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "Wind": { + "Name": "Wind", + "Scriptability": "None", + "DataType": { + "Value": "Float32" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } + }, + "WindDirection": { + "Name": "WindDirection", + "Scriptability": "None", + "DataType": { + "Value": "Vector3" + }, + "Tags": [ + "Hidden" + ], + "Kind": { + "Canonical": { + "Serialization": "Serializes" + } + } } }, "DefaultProperties": { @@ -94655,6 +96940,27 @@ } } }, + "WrapContentProvider": { + "Name": "WrapContentProvider", + "Tags": [ + "NotCreatable", + "NotReplicated", + "Service" + ], + "Superclass": "CacheableContentProvider", + "Properties": {}, + "DefaultProperties": { + "Archivable": { + "Bool": true + }, + "HistoryId": { + "UniqueId": "00000000000000000000000000000000" + }, + "UniqueId": { + "UniqueId": "00000000000000000000000000000000" + } + } + }, "WrapDeformMeshProvider": { "Name": "WrapDeformMeshProvider", "Tags": [ @@ -94720,8 +97026,8 @@ "Capabilities": { "SecurityCapabilities": 0 }, - "HSRAssetId": { - "ContentId": "" + "HSRContent": { + "Content": "None" }, "HSRData": { "SharedString": "" @@ -94767,8 +97073,8 @@ "Tags": { "Tags": [] }, - "TemporaryCageMeshId": { - "ContentId": "" + "TemporaryCageMeshContent": { + "Content": "None" }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" @@ -94994,6 +97300,27 @@ "Hidden", "NotScriptable" ], + "Kind": { + "Canonical": { + "Serialization": { + "Migrate": { + "To": "TemporaryReferenceMeshContent", + "Migration": "ContentIdToContent" + } + } + } + } + }, + "TemporaryReferenceMeshContent": { + "Name": "TemporaryReferenceMeshContent", + "Scriptability": "None", + "DataType": { + "Value": "Content" + }, + "Tags": [ + "Hidden", + "NotScriptable" + ], "Kind": { "Canonical": { "Serialization": "Serializes" @@ -95072,8 +97399,8 @@ "Enabled": { "Bool": true }, - "HSRAssetId": { - "ContentId": "" + "HSRContent": { + "Content": "None" }, "HSRData": { "SharedString": "" @@ -95157,11 +97484,11 @@ "Tags": { "Tags": [] }, - "TemporaryCageMeshId": { - "ContentId": "" + "TemporaryCageMeshContent": { + "Content": "None" }, - "TemporaryReferenceId": { - "ContentId": "" + "TemporaryReferenceMeshContent": { + "Content": "None" }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" @@ -95260,8 +97587,8 @@ "Capabilities": { "SecurityCapabilities": 0 }, - "HSRAssetId": { - "ContentId": "" + "HSRContent": { + "Content": "None" }, "HSRData": { "SharedString": "" @@ -95310,8 +97637,8 @@ "Tags": { "Tags": [] }, - "TemporaryCageMeshId": { - "ContentId": "" + "TemporaryCageMeshContent": { + "Content": "None" }, "UniqueId": { "UniqueId": "00000000000000000000000000000000" @@ -95673,6 +98000,25 @@ "Start": 1 } }, + "AnimatedImagePlaybackState": { + "name": "AnimatedImagePlaybackState", + "items": { + "Begin": 0, + "Canceled": 4, + "Completed": 3, + "Paused": 2, + "Playing": 1 + } + }, + "AnimatedImageScaleType": { + "name": "AnimatedImageScaleType", + "items": { + "Crop": 3, + "Fit": 2, + "Stretch": 0, + "Tile": 1 + } + }, "AnimationClipFromVideoStatus": { "name": "AnimationClipFromVideoStatus", "items": { @@ -95697,6 +98043,14 @@ "Polar": 1 } }, + "AnimationNodeBlendMode": { + "name": "AnimationNodeBlendMode", + "items": { + "Add": 1, + "Over": 0, + "Subtract": 2 + } + }, "AnimationNodeInterruptible": { "name": "AnimationNodeInterruptible", "items": { @@ -95729,6 +98083,13 @@ "InertialBlend": 1 } }, + "AnimationNodeTransitionWhen": { + "name": "AnimationNodeTransitionWhen", + "items": { + "BeforeFinished": 1, + "Finished": 0 + } + }, "AnimationNodeType": { "name": "AnimationNodeType", "items": { @@ -95739,12 +98100,14 @@ "GraphOutput": 6, "InvalidNode": 0, "MaskNode": 7, + "OneShotNode": 14, "OverNode": 2, "PrioritySelectNode": 8, "RandomSequenceNode": 9, "SelectNode": 10, "SequenceNode": 11, "SpeedNode": 12, + "StateMachineNode": 16, "SubtractNode": 13 } }, @@ -95767,6 +98130,13 @@ "Movement": 1 } }, + "AnimationValueNodeType": { + "name": "AnimationValueNodeType", + "items": { + "Expression": 1, + "Invalid": 0 + } + }, "AnimatorRetargetingMode": { "name": "AnimatorRetargetingMode", "items": { @@ -95878,6 +98248,13 @@ "Unknown": 0 } }, + "ApplyShadowMode": { + "name": "ApplyShadowMode", + "items": { + "Shape": 0, + "Text": 1 + } + }, "ApplyStrokeMode": { "name": "ApplyStrokeMode", "items": { @@ -95981,7 +98358,6 @@ "TextDocument": 93, "Torso": 27, "Video": 62, - "VoxelFragment": 91, "WaistAccessory": 47, "WalkAnimation": 55 } @@ -96035,6 +98411,20 @@ "Peak": 0 } }, + "AudioPositionType": { + "name": "AudioPositionType", + "items": { + "Instance": 1, + "Parent": 0 + } + }, + "AudioSampleFormat": { + "name": "AudioSampleFormat", + "items": { + "Float32": 1, + "Int16": 0 + } + }, "AudioSimulationFidelity": { "name": "AudioSimulationFidelity", "items": { @@ -96322,6 +98712,14 @@ "Z": 2 } }, + "BasicMeshPartShape": { + "name": "BasicMeshPartShape", + "items": { + "Capsule": 5, + "Cone": 6, + "RoundedBox": 7 + } + }, "BenefitType": { "name": "BenefitType", "items": { @@ -96389,6 +98787,15 @@ "Outer": 0 } }, + "BranchStatus": { + "name": "BranchStatus", + "items": { + "Archived": 3, + "Draft": 0, + "Merged": 2, + "ReadyToMerge": 1 + } + }, "BreakReason": { "name": "BreakReason", "items": { @@ -96706,7 +99113,7 @@ "Default": 0, "Hull": 1, "PreciseConvexDecomposition": 3, - "Scalable": 4 + "Tunable": 4 } }, "CommandPermission": { @@ -96887,6 +99294,12 @@ "DisconnectSecurityKeyMismatch": 258, "DisconnectSendPacketError": 262, "DisconnectTimeout": 266, + "DisconnectTransportIoError": 1025, + "DisconnectTransportIoInternetError": 1026, + "DisconnectTransportNgtcp2Error": 1028, + "DisconnectTransportProtocolError": 1027, + "DisconnectTransportQuicError": 1029, + "DisconnectTransportRnaError": 1030, "DisconnectVerboselyModeratedGame": 309, "DisconnectWrongVersion": 280, "DisconnectionNotification": 308, @@ -96940,6 +99353,7 @@ "TeleportGameNotFound": 770, "TeleportIsTeleporting": 775, "TeleportUnauthorized": 773, + "TransportErrors": 1024, "Unknown": 1 } }, @@ -97054,6 +99468,15 @@ "Follow": 2 } }, + "DataModelChangeType": { + "name": "DataModelChangeType", + "items": { + "Add": 0, + "AddPackage": 3, + "Modify": 2, + "Remove": 1 + } + }, "DataModelExtractorFileType": { "name": "DataModelExtractorFileType", "items": { @@ -97333,6 +99756,16 @@ "Small": 0 } }, + "DistanceAttenuationMode": { + "name": "DistanceAttenuationMode", + "items": { + "Custom": 0, + "Inverse": 4, + "InverseTapered": 1, + "Linear": 2, + "LinearSquared": 3 + } + }, "DomainType": { "name": "DomainType", "items": { @@ -97882,6 +100315,72 @@ "Unknown": 0 } }, + "FriendsCallingEndReason": { + "name": "FriendsCallingEndReason", + "items": { + "Canceled": 6, + "Declined": 4, + "Failed": 5, + "LocalHangup": 1, + "Missed": 3, + "None": 0, + "RemoteHangup": 2 + } + }, + "FriendsCallingParticipantErrors": { + "name": "FriendsCallingParticipantErrors", + "items": { + "ConnectionFailed": 2, + "None": 0, + "PermissionDenied": 4, + "PublishFailed": 3, + "Unknown": 1 + } + }, + "FriendsCallingParticipantLeaveReason": { + "name": "FriendsCallingParticipantLeaveReason", + "items": { + "Declined": 2, + "Failed": 5, + "Hangup": 1, + "Missed": 3, + "None": 0, + "Removed": 4, + "TimedOut": 6 + } + }, + "FriendsCallingParticipantStatus": { + "name": "FriendsCallingParticipantStatus", + "items": { + "Declined": 3, + "Ineligible": 6, + "Invited": 0, + "Joined": 2, + "Left": 4, + "Muted": 8, + "Removed": 5, + "Ringing": 1, + "TimedOut": 7 + } + }, + "FriendsCallingPhase": { + "name": "FriendsCallingPhase", + "items": { + "Active": 2, + "Ended": 3, + "Idle": 0, + "Ringing": 1 + } + }, + "FrustumStreamingMode": { + "name": "FrustumStreamingMode", + "items": { + "Automatic": 3, + "Default": 0, + "Disabled": 2, + "Enabled": 1 + } + }, "FunctionalTestResult": { "name": "FunctionalTestResult", "items": { @@ -97928,6 +100427,15 @@ "Transport": 8 } }, + "GenerateMomentTextResult": { + "name": "GenerateMomentTextResult", + "items": { + "Failed": 2, + "Filtered": 3, + "Pending": 1, + "Success": 0 + } + }, "Genre": { "name": "Genre", "items": { @@ -97959,6 +100467,7 @@ "name": "GradientType", "items": { "Conical": 2, + "Elliptical": 3, "Linear": 0, "Radial": 1 } @@ -98231,7 +100740,8 @@ "BlendSourceOver": 1, "Multiply": 4, "NormalMapBlend": 6, - "Overwrite": 2 + "Overwrite": 2, + "Subtract": 7 } }, "InOut": { @@ -98305,6 +100815,10 @@ "SyncedAsRoot": 2 } }, + "IntentReplicability": { + "name": "IntentReplicability", + "items": {} + }, "IntermediateMeshGenerationResult": { "name": "IntermediateMeshGenerationResult", "items": { @@ -98315,6 +100829,7 @@ "name": "InternalVideoUsage", "items": { "Default": 0, + "FeatureTileAd": 3, "HomeCarousel": 2, "WatchPage": 1 } @@ -98374,14 +100889,20 @@ "Break": 318, "ButtonA": 1002, "ButtonB": 1003, + "ButtonBack": 1052, + "ButtonCenter": 1051, + "ButtonDown": 1054, "ButtonL1": 1005, "ButtonL2": 1007, "ButtonL3": 1009, + "ButtonLeft": 1055, "ButtonR1": 1004, "ButtonR2": 1006, "ButtonR3": 1008, + "ButtonRight": 1056, "ButtonSelect": 1011, "ButtonStart": 1010, + "ButtonUp": 1053, "ButtonX": 1000, "ButtonY": 1001, "C": 99, @@ -98477,6 +100998,7 @@ "MouseY": 1032, "N": 110, "Nine": 57, + "None": 0, "NumLock": 300, "O": 111, "One": 49, @@ -98536,7 +101058,6 @@ "U": 117, "Underscore": 95, "Undo": 322, - "Unknown": 0, "Up": 273, "V": 118, "W": 119, @@ -98664,10 +101185,10 @@ "Include": 0 } }, - "Language": { - "name": "Language", + "KnownWindow": { + "name": "KnownWindow", "items": { - "Default": 0 + "Main": 0 } }, "LeftRight": { @@ -98934,6 +101455,33 @@ "TurboBuildersClub": 2 } }, + "MergeResolution": { + "name": "MergeResolution", + "items": { + "Manual": 3, + "None": 0, + "UseSource": 1, + "UseTarget": 2 + } + }, + "MergeStatus": { + "name": "MergeStatus", + "items": { + "Loading": 1, + "Merging": 2, + "None": 0 + } + }, + "MeshAttribute": { + "name": "MeshAttribute", + "items": { + "Color": 2, + "Face": 4, + "Normal": 1, + "UV": 3, + "Vertex": 0 + } + }, "MeshPartDetailLevel": { "name": "MeshPartDetailLevel", "items": { @@ -99207,6 +101755,24 @@ "UseView": 3 } }, + "PageMilestoneType": { + "name": "PageMilestoneType", + "items": { + "FunctionallyReady": 2, + "Interactive": 0, + "SurfaceMounted": 1, + "SurfaceReady": 3 + } + }, + "PageType": { + "name": "PageType", + "items": { + "AvatarEditor": 0, + "AvatarMarketplace": 3, + "ExperienceDetail": 2, + "Party": 1 + } + }, "PartType": { "name": "PartType", "items": { @@ -99353,6 +101919,22 @@ "Fixed": 1 } }, + "PinExperienceStatus": { + "name": "PinExperienceStatus", + "items": { + "AlreadyExists": 2, + "Failure": 1, + "Success": 0 + } + }, + "PioneerSource": { + "name": "PioneerSource", + "items": { + "DaveyBazooka": 1, + "Oof": 2, + "Roblox": 0 + } + }, "PlaceContentPreference": { "name": "PlaceContentPreference", "items": { @@ -99527,11 +102109,20 @@ "Predicted": 1 } }, + "PredictiveStreamingMode": { + "name": "PredictiveStreamingMode", + "items": { + "Default": 0, + "Disabled": 2, + "Enabled": 1 + } + }, "PreferredInput": { "name": "PreferredInput", "items": { "Gamepad": 1, "KeyboardAndMouse": 0, + "MicroGamepad": 3, "Touch": 2 } }, @@ -99606,6 +102197,10 @@ "PurchaseGranted": 1 } }, + "ProjectServiceOperationResult": { + "name": "ProjectServiceOperationResult", + "items": {} + }, "PromptCreateAssetResult": { "name": "PromptCreateAssetResult", "items": { @@ -99638,6 +102233,34 @@ "UploadFailed": 4 } }, + "PromptCreateOutfitResult": { + "name": "PromptCreateOutfitResult", + "items": { + "CreationFailure": 3, + "NoUserInput": 6, + "PartialSuccess": 2, + "PermissionDenied": 4, + "Success": 1, + "Timeout": 5, + "UGCValidationFailed": 8, + "UnknownFailure": 7 + } + }, + "PromptCreatePlatformContentResult": { + "name": "PromptCreatePlatformContentResult", + "items": { + "ModeratedName": 8, + "NoUserInput": 5, + "PermissionDenied": 2, + "PurchaseFailure": 9, + "Success": 1, + "Timeout": 3, + "TokenInvalid": 10, + "UGCValidationFailed": 7, + "UnknownFailure": 6, + "UploadFailed": 4 + } + }, "PromptExperienceDetailsResult": { "name": "PromptExperienceDetailsResult", "items": { @@ -99729,6 +102352,13 @@ "Level21": 21 } }, + "QueueDecision": { + "name": "QueueDecision", + "items": { + "Commit": 0, + "Defer": 1 + } + }, "R15CollisionType": { "name": "R15CollisionType", "items": { @@ -100216,6 +102846,14 @@ "Success": 0 } }, + "ScriptScannerUpdateType": { + "name": "ScriptScannerUpdateType", + "items": { + "Added": 1, + "Init": 0, + "Removed": 2 + } + }, "ScriptStoppedReason": { "name": "ScriptStoppedReason", "items": { @@ -100242,6 +102880,13 @@ "ScrollBar": 1 } }, + "ScrollState": { + "name": "ScrollState", + "items": { + "Idle": 0, + "Scrolling": 1 + } + }, "ScrollingDirection": { "name": "ScrollingDirection", "items": { @@ -100414,19 +103059,29 @@ "name": "SlimTintMode", "items": { "ContentId": 4, - "LOD": 1, + "DataModelState": 5, + "LevelOfDetail": 1, "MeshResourcePtr": 3, "Meshes": 2, "None": 0, - "Zone": 5 + "TranscoderStatus": 6 } }, - "SolidPrimitiveType": { - "name": "SolidPrimitiveType", + "SlimTranscoderStatus": { + "name": "SlimTranscoderStatus", "items": { - "Capsule": 5, - "Cone": 6, - "RoundedBox": 7 + "Failed": 3, + "Succeeded": 2, + "Transcoding": 1, + "Unknown": 0 + } + }, + "SlimViewContext": { + "name": "SlimViewContext", + "items": { + "Editor": 1, + "ImGui": 2, + "Player": 0 } }, "SolverConvergenceMetricType": { @@ -100493,6 +103148,14 @@ "Vector3": 7 } }, + "StateReferenceFrame": { + "name": "StateReferenceFrame", + "items": { + "CurrentState": 0, + "LastObservedState": 2, + "PreviousState": 1 + } + }, "Status": { "name": "Status", "items": { @@ -100641,6 +103304,8 @@ "Number": 2, "Operator": 1, "Property": 8, + "ReviewableChangeAddedText": 47, + "ReviewableChangeRemovedText": 48, "Ruler": 30, "SelectionBackground": 19, "SelectionText": 18, @@ -100912,10 +103577,6 @@ "RowMajor": 0 } }, - "TagReplicability": { - "name": "TagReplicability", - "items": {} - }, "TeamCreateErrorState": { "name": "TeamCreateErrorState", "items": { @@ -100968,7 +103629,9 @@ "TeleportMethod": { "name": "TeleportMethod", "items": { + "Teleport": 7, "TeleportPartyAsync": 3, + "TeleportSwitchServer": 8, "TeleportToInstanceBack": 5, "TeleportToPlaceInstance": 1, "TeleportToPrivateServer": 2, @@ -101059,6 +103722,13 @@ "Union": 3 } }, + "TextChannelDisplayMode": { + "name": "TextChannelDisplayMode", + "items": { + "AllTextChannels": 0, + "DefaultTextChannels": 1 + } + }, "TextChatMessageStatus": { "name": "TextChatMessageStatus", "items": { @@ -101197,6 +103867,21 @@ "Precise": 2 } }, + "TitleBarControlsPosition": { + "name": "TitleBarControlsPosition", + "items": { + "Left": 1, + "Right": 2, + "Unknown": 0 + } + }, + "TitleBarMode": { + "name": "TitleBarMode", + "items": { + "Custom": 1, + "Native": 0 + } + }, "TonemapperPreset": { "name": "TonemapperPreset", "items": { @@ -101443,6 +104128,22 @@ "Preview": 1 } }, + "UserAcquisitionSource": { + "name": "UserAcquisitionSource", + "items": { + "Ads": 8, + "ContinueToPlay": 3, + "Curation": 4, + "Friends": 5, + "HomeOther": 9, + "HomeRecommendation": 2, + "Other": 10, + "PendingAttribution": 1, + "Search": 6, + "Teleport": 7, + "Unknown": 0 + } + }, "UserCFrame": { "name": "UserCFrame", "items": { @@ -101452,6 +104153,14 @@ "RightHand": 2 } }, + "UserIdMode": { + "name": "UserIdMode", + "items": { + "Domain": 2, + "Global": 1, + "Invalid": 0 + } + }, "UserInputState": { "name": "UserInputState", "items": { @@ -101488,6 +104197,22 @@ "Touch": 7 } }, + "UserNewReturningStatus": { + "name": "UserNewReturningStatus", + "items": { + "New": 1, + "Returning": 2, + "Unknown": 0 + } + }, + "UserReturnStatus": { + "name": "UserReturnStatus", + "items": { + "New": 1, + "Returning": 2, + "Unknown": 0 + } + }, "VRComfortSetting": { "name": "VRComfortSetting", "items": { @@ -101570,6 +104295,13 @@ "Vector": 2 } }, + "VerifiedLevel": { + "name": "VerifiedLevel", + "items": { + "High": 1, + "Low": 0 + } + }, "VerticalAlignment": { "name": "VerticalAlignment", "items": { @@ -101814,6 +104546,22 @@ "NoOne": 1 } }, + "WindSoundProfile": { + "name": "WindSoundProfile", + "items": { + "Foliage": 2, + "Turbulence": 0, + "Whistle": 1 + } + }, + "WindowState": { + "name": "WindowState", + "items": { + "Maximized": 2, + "Minimized": 1, + "Normal": 0 + } + }, "WrapLayerAutoSkin": { "name": "WrapLayerAutoSkin", "items": { From 351194ba93e4a61d798b27a52d8fae51ecb57606 Mon Sep 17 00:00:00 2001 From: krakow10 Date: Thu, 1 Oct 2026 22:16:41 -0700 Subject: [PATCH 1500/1504] Use `WeakDom::full_path_of` (#1185) --- src/syncback/ref_properties.rs | 6 ++---- src/syncback/snapshot.rs | 14 +------------- 2 files changed, 3 insertions(+), 17 deletions(-) diff --git a/src/syncback/ref_properties.rs b/src/syncback/ref_properties.rs index 054f61b8..94d7ffdf 100644 --- a/src/syncback/ref_properties.rs +++ b/src/syncback/ref_properties.rs @@ -8,10 +8,8 @@ use rbx_dom_weak::{ ustr, Instance, Ustr, WeakDom, }; -use crate::{ - multimap::MultiMap, syncback::snapshot::inst_path, REF_ID_ATTRIBUTE_NAME, - REF_POINTER_ATTRIBUTE_PREFIX, -}; +use crate::syncback::snapshot::inst_path; +use crate::{multimap::MultiMap, REF_ID_ATTRIBUTE_NAME, REF_POINTER_ATTRIBUTE_PREFIX}; pub struct RefLinks { /// A map of referents to each of their Ref properties. diff --git a/src/syncback/snapshot.rs b/src/syncback/snapshot.rs index 384033d6..bc10e76a 100644 --- a/src/syncback/snapshot.rs +++ b/src/syncback/snapshot.rs @@ -222,19 +222,7 @@ pub fn filter_out_property(inst: &Instance, prop_name: &str) -> bool { } pub fn inst_path(dom: &WeakDom, referent: Ref) -> String { - let mut path = Vec::new(); - - let mut inst = dom.get_by_ref(referent); - while let Some(instance) = inst { - path.push(instance.name.as_str()); - inst = dom.get_by_ref(instance.parent()); - } - // This is to avoid the root's name from appearing in the path. Not - // optimal, but should be fine. - path.pop(); - - path.reverse(); - path.join("/") + dom.full_path_of(referent, "/") } #[cfg(test)] From ee98fb7833ee81f7f9c4f8dd9b75bf606bbe2354 Mon Sep 17 00:00:00 2001 From: krakow10 Date: Thu, 1 Oct 2026 22:17:27 -0700 Subject: [PATCH 1501/1504] Remove Reflection Database Cow Remnants (#1264) --- src/resolution.rs | 2 +- src/syncback/mod.rs | 2 +- src/syncback/property_filter.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/resolution.rs b/src/resolution.rs index 1e743efd..47fbac7e 100644 --- a/src/resolution.rs +++ b/src/resolution.rs @@ -304,7 +304,7 @@ fn find_descriptor( return Some(descriptor); } - current_class_name = class.superclass.as_deref()?; + current_class_name = class.superclass?; } } diff --git a/src/syncback/mod.rs b/src/syncback/mod.rs index 7fe3992d..3949786d 100644 --- a/src/syncback/mod.rs +++ b/src/syncback/mod.rs @@ -481,7 +481,7 @@ fn get_property_filter(project: &Project, new_inst: &Instance) -> Option bool { } kind => unimplemented!("unknown property kind {kind:?}"), }; - } else if let Some(super_class) = class_data.superclass.as_ref() { + } else if let Some(super_class) = class_data.superclass { current_class_name = super_class; } else { break; From 26b6cc6d83ef068d356aac689110ad89f3b05d65 Mon Sep 17 00:00:00 2001 From: Micah Date: Thu, 1 Oct 2026 23:10:42 -0700 Subject: [PATCH 1502/1504] Release v7.7.1 (#1330) --- CHANGELOG.md | 2 ++ Cargo.lock | 2 +- Cargo.toml | 2 +- plugin/Version.txt | 2 +- 4 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ac21a66..4c23b7d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,8 @@ Making a new release? Simply add the new header with the version and date undern ## Unreleased +## [7.7.1] (October 1st, 2026) + * Fixed `$path` values that point outside the project folder failing to match `syncRule`s on Windows, which broke `rojo sourcemap` with a "could not be turned into a Roblox Instance" error. ([#1290]) * Fixed `rojo serve` silently stopping syncing file changes on Windows when the served project path was a verbatim (`\\?\`) path, because tree paths and file-watcher event paths were canonicalized to different forms. ([#1290]) * Fixed `rojo sourcemap --absolute` emitting verbatim (`\\?\`) paths on Windows, which broke require types in luau-lsp. ([#1290]) diff --git a/Cargo.lock b/Cargo.lock index 27c19fa3..d93a8fdc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2062,7 +2062,7 @@ dependencies = [ [[package]] name = "rojo" -version = "7.7.0" +version = "7.7.1" dependencies = [ "anyhow", "backtrace", diff --git a/Cargo.toml b/Cargo.toml index aa6701d9..9d37c22a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rojo" -version = "7.7.0" +version = "7.7.1" rust-version = "1.88" authors = [ "Lucien Greathouse ", diff --git a/plugin/Version.txt b/plugin/Version.txt index d21b198c..bfe365e7 100644 --- a/plugin/Version.txt +++ b/plugin/Version.txt @@ -1 +1 @@ -7.7.0 \ No newline at end of file +7.7.1 \ No newline at end of file From 95262a02e96aabd02ff455142cb1414d55be0dd8 Mon Sep 17 00:00:00 2001 From: boatbomber Date: Thu, 1 Oct 2026 23:52:23 -0700 Subject: [PATCH 1503/1504] Fix missing version links in CHANGELOG (#1331) Makes the version headers clickable links, consistent with the others. --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c23b7d4..d7782a5c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ Making a new release? Simply add the new header with the version and date undern * Fixed `rojo sourcemap --absolute` emitting verbatim (`\\?\`) paths on Windows, which broke require types in luau-lsp. ([#1290]) * The plugin now disables the `Check for Updates` setting if you block access to `api.github.com`. ([#1297]) +[7.7.1]: https://github.com/rojo-rbx/rojo/releases/tag/v7.7.1 [#1290]: https://github.com/rojo-rbx/rojo/pull/1290 [#1297]: https://github.com/rojo-rbx/rojo/pull/1297 @@ -60,6 +61,7 @@ Making a new release? Simply add the new header with the version and date undern * `rojo serve` now validates the `Host`/`Origin` headers to protect the local/private server against DNS rebinding, gates `/api/open` to local clients, and warns when bound to a network-reachable address. The accepted hosts can be extended with the `--allowed-hosts` option or a project's `serveAllowedHosts` field, for example to reach a network-exposed server by hostname. ([#1270]) * Fixed syncback not removing stale `$properties` entries when Studio resets a property to its engine default. ([#1244]) +[7.7.0]: https://github.com/rojo-rbx/rojo/releases/tag/v7.7.0 [#1176]: https://github.com/rojo-rbx/rojo/pull/1176 [#1179]: https://github.com/rojo-rbx/rojo/pull/1179 [#1192]: https://github.com/rojo-rbx/rojo/pull/1192 From 7e60406373faf82887353164543540d054d84d92 Mon Sep 17 00:00:00 2001 From: boyned//Kampfkarren <3190756+Kampfkarren@users.noreply.github.com> Date: Mon, 5 Oct 2026 18:02:34 -0700 Subject: [PATCH 1504/1504] Consistent ordering of CSV fields (#1333) Paired with https://github.com/rojo-rbx/rbx-dom/pull/668 This fixes a bug where the first sync of a place with LocalizationTables would always fail diff, since Roblox computes it at runtime --- CHANGELOG.md | 4 + ...end_to_end__tests__build__csv_bug_145.snap | 2 +- ...end_to_end__tests__build__csv_bug_147.snap | 2 +- ...d_to_end__tests__build__csv_in_folder.snap | 2 +- src/snapshot_middleware/csv.rs | 81 ++++++++++++++++--- ...t_middleware__csv__test__csv_from_vfs.snap | 2 +- ...pshot_middleware__csv__test__csv_init.snap | 2 +- ...leware__csv__test__csv_init_with_meta.snap | 2 +- ..._middleware__csv__test__csv_with_meta.snap | 2 +- 9 files changed, 80 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d7782a5c..3943ae5f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,10 @@ Making a new release? Simply add the new header with the version and date undern ## Unreleased +* LocalizationTables no longer report as changed when nothing changes. [(#1333)] + +[#1333]: https://github.com/rojo-rbx/rojo/pull/1333 + ## [7.7.1] (October 1st, 2026) * Fixed `$path` values that point outside the project folder failing to match `syncRule`s on Windows, which broke `rojo sourcemap` with a "could not be turned into a Roblox Instance" error. ([#1290]) diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_145.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_145.snap index ab7470b3..96cdc002 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_145.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_145.snap @@ -10,7 +10,7 @@ expression: contents normal - [{"key":"Count","example":"A number demonstrating issue 145","source":"3","values":{"es":"7"}}] + [{"example":"A number demonstrating issue 145","key":"Count","source":"3","values":{"es":"7"}}]
    diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_147.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_147.snap index d16de20f..8a668402 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_147.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_bug_147.snap @@ -10,7 +10,7 @@ expression: contents normal - [{"key":"Language.Name","source":"English","values":{}},{"key":"Language.Region","source":"United States","values":{}},{"key":"Label.Thickness","source":"Thickness","values":{}},{"key":"Label.Opacity","source":"Opacity","values":{}},{"key":"Toolbar.Undo","source":"Undo","values":{}},{"key":"Toolbar.Redo","source":"Redo","values":{}},{"key":"Toolbar.Camera","source":"Top-down camera","values":{}},{"key":"Toolbar.Saves","source":"Saved drawings","values":{}},{"key":"Toolbar.Preferences","source":"Settings","values":{}},{"key":"Toolbar.Mode.Vector","source":"Vector mode","values":{}},{"key":"Toolbar.Mode.Pixel","source":"Pixel mode","values":{}}] + [{"key":"Label.Opacity","source":"Opacity","values":{}},{"key":"Label.Thickness","source":"Thickness","values":{}},{"key":"Language.Name","source":"English","values":{}},{"key":"Language.Region","source":"United States","values":{}},{"key":"Toolbar.Camera","source":"Top-down camera","values":{}},{"key":"Toolbar.Mode.Pixel","source":"Pixel mode","values":{}},{"key":"Toolbar.Mode.Vector","source":"Vector mode","values":{}},{"key":"Toolbar.Preferences","source":"Settings","values":{}},{"key":"Toolbar.Redo","source":"Redo","values":{}},{"key":"Toolbar.Saves","source":"Saved drawings","values":{}},{"key":"Toolbar.Undo","source":"Undo","values":{}}] diff --git a/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_in_folder.snap b/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_in_folder.snap index d60fca02..40bc7ce5 100644 --- a/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_in_folder.snap +++ b/rojo-test/build-test-snapshots/end_to_end__tests__build__csv_in_folder.snap @@ -10,7 +10,7 @@ expression: contents normal - [{"key":"Ack","example":"An exclamation of despair","source":"Ack!","values":{"es":"¡Ay!"}}] + [{"example":"An exclamation of despair","key":"Ack","source":"Ack!","values":{"es":"¡Ay!"}}] diff --git a/src/snapshot_middleware/csv.rs b/src/snapshot_middleware/csv.rs index b4a86efc..8cea9b81 100644 --- a/src/snapshot_middleware/csv.rs +++ b/src/snapshot_middleware/csv.rs @@ -162,13 +162,11 @@ pub fn syncback_csv_init<'sync>( /// /// We manually deserialize into this table from CSV, but let serde_json handle /// serialization. -#[derive(Debug, Default, Serialize, Deserialize)] +#[derive(Debug, Default, Deserialize)] #[serde(rename_all = "camelCase")] struct LocalizationEntry<'a> { - #[serde(skip_serializing_if = "Option::is_none")] key: Option>, - #[serde(skip_serializing_if = "Option::is_none")] context: Option>, // Roblox writes `examples` for LocalizationTable's Content property, which @@ -176,16 +174,77 @@ struct LocalizationEntry<'a> { // This is reported here: https://devforum.roblox.com/t/2908720. // // To support their mistake, we support an alias named `examples`. - #[serde(skip_serializing_if = "Option::is_none", alias = "examples")] + #[serde(alias = "examples")] example: Option>, - #[serde(skip_serializing_if = "Option::is_none")] source: Option>, // We use a BTreeMap here to get deterministic output order. values: BTreeMap, Cow<'a, str>>, } +// Guarantee a specific order of both fields and entries so that diff always match up +impl<'a> Serialize for LocalizationEntry<'a> { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + let mut btree = BTreeMap::new(); + + if let Some(key) = &self.key { + btree.insert( + "key", + serde_json::to_value(key).map_err(serde::ser::Error::custom)?, + ); + } + + if let Some(context) = &self.context { + btree.insert( + "context", + serde_json::to_value(context).map_err(serde::ser::Error::custom)?, + ); + } + + if let Some(example) = &self.example { + btree.insert( + "example", + serde_json::to_value(example).map_err(serde::ser::Error::custom)?, + ); + } + + if let Some(source) = &self.source { + btree.insert( + "source", + serde_json::to_value(source).map_err(serde::ser::Error::custom)?, + ); + } + + btree.insert( + "values", + serde_json::to_value(&self.values).map_err(serde::ser::Error::custom)?, + ); + + btree.serialize(serializer) + } +} + +fn sort_localization_entries(mut entries: Vec) -> Vec { + entries.sort_by(|a, b| { + a.key + .as_deref() + .unwrap_or_default() + .cmp(&b.key.as_deref().unwrap_or_default()) + .then_with(|| { + a.source + .as_deref() + .unwrap_or_default() + .cmp(&b.source.as_deref().unwrap_or_default()) + }) + }); + + entries +} + /// Normally, we'd be able to let the csv crate construct our struct for us. /// /// However, because of a limitation with Serde's 'flatten' feature, it's not @@ -236,8 +295,8 @@ fn convert_localization_csv(contents: &[u8]) -> anyhow::Result { entries.push(entry); } - let encoded = - serde_json::to_string(&entries).context("Could not encode JSON for localization table")?; + let encoded = serde_json::to_string(&sort_localization_entries(entries)) + .context("Could not encode JSON for localization table")?; Ok(encoded) } @@ -249,11 +308,9 @@ fn localization_to_csv(csv_contents: &str) -> anyhow::Result> { let mut out = Vec::new(); let mut writer = csv::Writer::from_writer(&mut out); - let mut csv: Vec = - serde_json::from_str(csv_contents).context("cannot decode JSON from localization table")?; - - // TODO sort this better - csv.sort_by(|a, b| a.source.partial_cmp(&b.source).unwrap()); + let csv: Vec = sort_localization_entries( + serde_json::from_str(csv_contents).context("cannot decode JSON from localization table")?, + ); let mut headers = vec!["Key", "Source", "Context", "Example"]; // We want both order and a lack of duplicates, so we use a BTreeSet. diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap index 6356256d..aa4c18c8 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_from_vfs.snap @@ -20,5 +20,5 @@ name: foo class_name: LocalizationTable properties: Contents: - String: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" + String: "[{\"example\":\"An exclamation of despair\",\"key\":\"Ack\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" children: [] diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init.snap index 813a2933..385666a8 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init.snap @@ -29,5 +29,5 @@ name: root class_name: LocalizationTable properties: Contents: - String: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" + String: "[{\"example\":\"An exclamation of despair\",\"key\":\"Ack\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" children: [] diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init_with_meta.snap index 01ce0a0f..81fe3351 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_init_with_meta.snap @@ -29,5 +29,5 @@ name: root class_name: LocalizationTable properties: Contents: - String: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" + String: "[{\"example\":\"An exclamation of despair\",\"key\":\"Ack\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" children: [] diff --git a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap index f90eccc8..b02dee1c 100644 --- a/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap +++ b/src/snapshot_middleware/snapshots/librojo__snapshot_middleware__csv__test__csv_with_meta.snap @@ -20,5 +20,5 @@ name: foo class_name: LocalizationTable properties: Contents: - String: "[{\"key\":\"Ack\",\"example\":\"An exclamation of despair\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" + String: "[{\"example\":\"An exclamation of despair\",\"key\":\"Ack\",\"source\":\"Ack!\",\"values\":{\"es\":\"¡Ay!\"}}]" children: []